Compare commits

..

1918 Commits

Author SHA1 Message Date
Peter Steinberger
e4cf6682f0 feat(slack): expand message action parity 2026-05-09 14:30:41 +01:00
Peter Steinberger
e06988196b test: tighten runtime context queue assertion 2026-05-09 14:25:24 +01:00
Peter Steinberger
45e9d33732 test: tighten prompt image loader assertion 2026-05-09 14:24:02 +01:00
Shakker
cb368c4a5a test: isolate health snapshot account inspection 2026-05-09 14:23:52 +01:00
Peter Steinberger
d6480c9cec test: tighten attempt resource loader assertion 2026-05-09 14:22:24 +01:00
Peter Steinberger
9e82306e4d chore: update canvas a2ui bundle hash 2026-05-09 14:21:51 +01:00
Peter Steinberger
6a2260eac0 fix: stabilize Discord realtime voice proxy 2026-05-09 14:21:51 +01:00
Peter Steinberger
b766b8e846 test: tighten attempt cache ttl assertion 2026-05-09 14:18:51 +01:00
Peter Steinberger
fa87c91531 test: tighten incomplete turn meta assertion 2026-05-09 14:16:55 +01:00
Peter Steinberger
cb5fdcf52c test: tighten fallback error context assertion 2026-05-09 14:15:00 +01:00
Shakker
4473a588ef test: stub trajectory metadata in attempt harness 2026-05-09 14:13:45 +01:00
Peter Steinberger
c0132e9aa3 test: tighten static catalog model assertion 2026-05-09 14:12:00 +01:00
Peter Steinberger
2b27dc77b9 test: tighten startup retry model assertion 2026-05-09 14:09:54 +01:00
Peter Steinberger
8f023f3678 test: tighten codex forward compat assertion 2026-05-09 14:08:30 +01:00
Peter Steinberger
5aab2d69fe test: tighten embedded extension runtime assertion 2026-05-09 14:07:09 +01:00
Peter Steinberger
56e4beff9b test: tighten image dimension parser assertion 2026-05-09 14:05:45 +01:00
Peter Steinberger
2066e8b271 test: tighten bundle lsp spawn assertion 2026-05-09 14:03:54 +01:00
Peter Steinberger
c7de8f6a56 test: tighten subagent thinking assertion 2026-05-09 14:02:29 +01:00
Peter Steinberger
32df92056d test: tighten provider policy normalization assertion 2026-05-09 14:01:04 +01:00
Peter Steinberger
9f4be5e9ad test: tighten model catalog visibility assertion 2026-05-09 13:59:47 +01:00
Ayaan Zaidi
7d00183d44 fix(telegram): clean chat window prompt context 2026-05-09 18:28:50 +05:30
Ayaan Zaidi
b3afcc6eec fix(telegram): prioritize live chat context 2026-05-09 18:28:50 +05:30
Ayaan Zaidi
4cdf19eabe fix(telegram): add local chat context windows 2026-05-09 18:28:50 +05:30
Ayaan Zaidi
40fd42206f perf(reply): compact chat window context 2026-05-09 18:28:50 +05:30
Ayaan Zaidi
176d0126cd fix(reply): unify current turn context 2026-05-09 18:28:50 +05:30
Peter Steinberger
e47784364f test: tighten workspace plugin auth assertion 2026-05-09 13:57:45 +01:00
Peter Steinberger
17bbd1829d test: tighten model auth marker assertion 2026-05-09 13:56:11 +01:00
Peter Steinberger
0c49f5dcfe test: tighten harness registry assertion 2026-05-09 13:53:23 +01:00
Peter Steinberger
9ac8909b15 test: tighten codex native search assertion 2026-05-09 13:51:59 +01:00
Peter Steinberger
937c474f14 test: tighten supervisor capture assertion 2026-05-09 13:50:23 +01:00
Peter Steinberger
dd99e8c6a8 test: tighten cli runner cron hook assertion 2026-05-09 13:49:04 +01:00
Peter Steinberger
dfc175c4a0 test: tighten cli output assertion 2026-05-09 13:47:30 +01:00
Peter Steinberger
4920878c19 test: tighten cache trace assertion 2026-05-09 13:46:09 +01:00
Peter Steinberger
38472ca6b1 test: tighten bootstrap context assertion 2026-05-09 13:44:22 +01:00
Shakker
50c955394e perf: defer whatsapp setup finalize import 2026-05-09 13:43:23 +01:00
Peter Steinberger
511290bc34 test: tighten exec path assertion 2026-05-09 13:42:52 +01:00
Peter Steinberger
b0991fa364 test: tighten background exec assertion 2026-05-09 13:41:19 +01:00
Peter Steinberger
98078eaa8c test: tighten auth session override assertion 2026-05-09 13:40:05 +01:00
Peter Steinberger
7699ea3e1c test: tighten concurrent oauth assertion 2026-05-09 13:38:35 +01:00
Peter Steinberger
e7d5e7eb2b test: tighten oauth lock timeout assertion 2026-05-09 13:36:05 +01:00
Peter Steinberger
1e894199db test: tighten external cli auth scope assertion 2026-05-09 13:34:50 +01:00
Peter Steinberger
854fd2a9eb test: tighten auth health assertion 2026-05-09 13:33:03 +01:00
Peter Steinberger
0cd121ff06 test: tighten agent scope assertion 2026-05-09 13:31:47 +01:00
Peter Steinberger
9de1ccf5a4 test: tighten acp session assertion 2026-05-09 13:30:20 +01:00
Peter Steinberger
22ead00102 test: tighten acp session meta assertion 2026-05-09 13:29:17 +01:00
Peter Steinberger
2856f8ccce test: tighten acp permission relay assertion 2026-05-09 13:28:07 +01:00
Ayaan Zaidi
39dcff3d5b docs(changelog): note telegram cache persistence fix 2026-05-09 17:57:16 +05:30
Ayaan Zaidi
aec262034b perf(telegram): append reply-chain cache records 2026-05-09 17:57:16 +05:30
Peter Steinberger
b39daef3da test: tighten acp event ledger assertion 2026-05-09 13:26:57 +01:00
Shakker
9d37d06233 test: isolate model selection normalization 2026-05-09 13:26:45 +01:00
Peter Steinberger
06eed5a454 test: tighten oauth lock path assertion 2026-05-09 13:25:39 +01:00
Peter Steinberger
2a00bd6209 test: tighten install package dir assertions 2026-05-09 13:23:30 +01:00
Peter Steinberger
20837afb21 test: tighten docker setup missing path assertions 2026-05-09 13:20:59 +01:00
Peter Steinberger
e216fed88f test: tighten deprecated auth repair assertions 2026-05-09 13:19:28 +01:00
Peter Steinberger
a7727b1fcd test: tighten secrets runtime assertions 2026-05-09 13:18:06 +01:00
Peter Steinberger
7e7d72f781 test: tighten secrets warning assertions 2026-05-09 13:16:49 +01:00
Peter Steinberger
a62889f6c2 test: tighten commitment chain assertions 2026-05-09 13:14:50 +01:00
Peter Steinberger
a957ba6c2d test: tighten tui launch assertions 2026-05-09 13:13:18 +01:00
Peter Steinberger
13f498f382 docs: prepare 2026.5.9 changelog 2026-05-09 13:12:40 +01:00
Peter Steinberger
e5a102249f test: tighten provider usage plugin assertions 2026-05-09 13:11:48 +01:00
Peter Steinberger
cc37c5d6b5 docs: cite backup temp manifest issue 2026-05-09 08:10:18 -04:00
Soham Patankar
3f5dce29e9 fix(backup): keep temp manifest outside source paths
The backup temp manifest is created via os.tmpdir() and passed to tar.c
alongside the included asset paths. When TMPDIR resolves inside a backed-up
asset (for example a sandboxed cron run with TMPDIR=~/.openclaw/tmp), the
recursive walk of that asset visits the same manifest a second time and both
copies are remapped to <archiveRoot>/manifest.json. backup-verify then fails
with 'Expected exactly one backup manifest entry, found 2'.

Add chooseBackupTempRoot() that prefers os.tmpdir() and falls back to the
output directory (already validated as outside every asset and writable by
the caller) when the system tempdir overlaps a source path. A defensive
guard re-checks the fallback. A tar filter alone cannot fix this because
the filter fires for both the explicit-arg and the traversed entry, so
excluding by path drops the manifest entirely.

Add regression tests for tmpdir nested in the state dir and tmpdir equal
to the state dir.

(cherry picked from commit 00ec151f68)
2026-05-09 08:10:18 -04:00
Peter Steinberger
098ed624f6 fix: normalize google catalog model ids 2026-05-09 13:10:06 +01:00
samzong
ee6b29b715 fix(agents): handle resumed cli jsonl output
Signed-off-by: samzong <samzong.lu@gmail.com>
2026-05-09 08:08:52 -04:00
samzong
02ca572a26 fix(agents): bound cli runner supervisor output
Signed-off-by: samzong <samzong.lu@gmail.com>
2026-05-09 08:08:52 -04:00
Peter Steinberger
1ab7c7e248 test: tighten heartbeat typing assertions 2026-05-09 13:06:19 +01:00
Peter Steinberger
7f9aefe43b test: tighten proxy capture headers 2026-05-09 13:02:49 +01:00
Liu Wenyu
c91fffdd67 feat(config): support Qwen thinkingFormat values (#79777)
## Summary
- allow configured OpenAI-compatible Qwen models to opt into `qwen` and `qwen-chat-template` thinking payloads
- preserve those compat values through schema validation and catalog normalization
- map OpenClaw `/think` levels to `enable_thinking` or `chat_template_kwargs.enable_thinking` without also sending `reasoning_effort`
- clarify docs that request-level chat-template kwargs require compatible backends such as vLLM

## Verification
- git diff --check
- pnpm exec oxfmt --check --threads=1 CHANGELOG.md docs/gateway/config-agents.md docs/gateway/config-tools.md src/config/zod-schema.core.ts src/config/types.models.ts src/model-catalog/normalize.ts src/agents/openai-transport-stream.ts src/config/config-misc.test.ts src/model-catalog/normalize.test.ts src/agents/openai-transport-stream.test.ts
- pnpm config:schema:check
- pnpm test src/config/config-misc.test.ts src/model-catalog/normalize.test.ts src/agents/openai-transport-stream.test.ts
- GitHub CI on 2404edca39

Thanks @indulgeback.
2026-05-09 08:02:39 -04:00
Peter Steinberger
cb46ace2e8 test: tighten model catalog authority assertions 2026-05-09 13:00:47 +01:00
Peter Steinberger
0a09a8f02f fix: propagate image generation SSRF policy (#79765) (thanks @hclsys) 2026-05-09 07:59:31 -04:00
Peter Steinberger
b4d37feec6 test: tighten wizard plugin config assertions 2026-05-09 12:58:47 +01:00
Peter Steinberger
ae14f3a459 test: tighten nodes camera assertion 2026-05-09 12:57:03 +01:00
Peter Steinberger
bfee4c17f7 test: tighten fetch timeout assertions 2026-05-09 12:55:40 +01:00
Peter Steinberger
974fdc6bc0 test: tighten directive tag assertions 2026-05-09 12:53:44 +01:00
Peter Steinberger
91adcc68fe test: tighten boot hook assertions 2026-05-09 12:50:53 +01:00
Peter Steinberger
019f1bde01 test: tighten tts config assertion 2026-05-09 12:48:28 +01:00
Peter Steinberger
b8a6a9a10a fix: preserve Gemini flash image capability (#79759) (thanks @hclsys) 2026-05-09 07:47:06 -04:00
Peter Steinberger
9907f38c83 test: tighten wizard session assertion 2026-05-09 12:46:33 +01:00
Shakker
efa8c83200 fix: keep auth profile rotation nonblocking 2026-05-09 12:45:03 +01:00
Peter Steinberger
2ad0282556 test: tighten test state assertions 2026-05-09 12:44:28 +01:00
Peter Steinberger
3cb2651295 test: tighten memory dreaming assertions 2026-05-09 12:42:26 +01:00
Peter Steinberger
a4e3b4b6e3 test: tighten logging assertions 2026-05-09 12:40:54 +01:00
Peter Steinberger
4cbf13e600 test: tighten speech provider assertions 2026-05-09 12:39:16 +01:00
Peter Steinberger
46738f1677 fix(agents): add sandbox container path hint (#79766) (thanks @hclsys) 2026-05-09 07:38:51 -04:00
Peter Steinberger
00faea921f test: tighten slug generator assertions 2026-05-09 12:37:16 +01:00
Ayaan Zaidi
f9feb9cf17 docs(changelog): fix PR 79741 attribution 2026-05-09 17:07:03 +05:30
Peter Steinberger
eb200e369c feat: default discord voice to agent proxy 2026-05-09 12:36:37 +01:00
Peter Steinberger
9859c23bad test: tighten commitment heartbeat assertion 2026-05-09 12:35:34 +01:00
Peter Steinberger
55b4fc880c test: tighten cron event assertions 2026-05-09 12:34:05 +01:00
Peter Steinberger
c9293b4738 test: tighten video capability assertions 2026-05-09 12:32:23 +01:00
Peter Steinberger
f4addf8713 test: tighten context engine assertions 2026-05-09 12:30:55 +01:00
stain lu
2fb05bc402 fix: harden agent recovery failures (#79729)
Fixes #79688. Fixes #79712.
2026-05-09 07:29:08 -04:00
Peter Steinberger
b447d30349 test: tighten process assertions 2026-05-09 12:28:59 +01:00
Shakker
153813ac52 test: align openai runtime dependency assertion 2026-05-09 12:27:06 +01:00
Peter Steinberger
9ba545a916 test: tighten plugin state e2e assertions 2026-05-09 12:25:50 +01:00
Peter Steinberger
d1c7b57e45 test: tighten plugin state store assertions 2026-05-09 12:24:33 +01:00
Peter Steinberger
0a505563d6 test: tighten durable json error assertion 2026-05-09 12:22:36 +01:00
Peter Steinberger
0a8beba3c8 test: tighten supervisor marker assertions 2026-05-09 12:21:18 +01:00
Peter Steinberger
5b4bee9f1b test: tighten video capability overlay assertions 2026-05-09 12:20:25 +01:00
Peter Steinberger
7183aeb4c4 test: tighten video provider registry assertions 2026-05-09 12:19:33 +01:00
Peter Steinberger
516f624ad9 docs: link telegram DM guard changelog (#79700) 2026-05-09 07:18:42 -04:00
TSHOGX
1355701d73 fix(telegram): guard DM bindings from being parsed as topics 2026-05-09 07:18:42 -04:00
Peter Steinberger
f90b94d231 test: tighten hook retry-after assertions 2026-05-09 12:18:32 +01:00
Peter Steinberger
355ea947f5 fix: allow explicit local infer static catalog models 2026-05-09 12:16:58 +01:00
Peter Steinberger
02708a6225 test: tighten node invoke policy assertions 2026-05-09 12:16:43 +01:00
Peter Steinberger
0f00244f10 test: tighten heartbeat wake assertions 2026-05-09 12:15:18 +01:00
Peter Steinberger
d7b73d8d94 test: tighten live media plan assertion 2026-05-09 12:14:18 +01:00
Peter Steinberger
8aec682993 test: tighten channel catalog id assertions 2026-05-09 12:13:21 +01:00
Peter Steinberger
dd59bbf992 test: tighten pairing store approval assertion 2026-05-09 12:12:24 +01:00
Peter Steinberger
840ee27669 test: tighten crestodian rescue policy assertions 2026-05-09 12:11:27 +01:00
Peter Steinberger
79abc3fe83 test: tighten node-host runner assertion 2026-05-09 12:09:56 +01:00
Bryan Pearson
a2b8f2aef0 fix(launchd): set ProcessType=Interactive to prevent macOS App Nap
The gateway launchd plist does not set ProcessType, so macOS treats it as a background process eligible for App Nap. When the system is idle, App Nap can suspend the process and freeze setTimeout-based heartbeat timers.

Setting ProcessType to Interactive tells launchd the process needs timely execution.

Fixes #58061; refs #62294 and #66992.
2026-05-09 16:39:27 +05:30
Peter Steinberger
dce5f809a1 test: tighten proxy capture store assertions 2026-05-09 12:08:46 +01:00
Peter Steinberger
3ede7540d4 test: tighten workspace hook exclusion assertion 2026-05-09 12:07:39 +01:00
Peter Steinberger
620698abdb test: tighten proxy coverage assertions 2026-05-09 12:06:24 +01:00
Shakker
234ea60c9d test: align telegram fast command callbacks 2026-05-09 12:05:59 +01:00
Peter Steinberger
8bb9331855 test: tighten talk schema success assertion 2026-05-09 12:05:17 +01:00
Peter Steinberger
ccaf4a03fc test: tighten trajectory cleanup path assertions 2026-05-09 12:04:22 +01:00
Peter Steinberger
d9b950d148 test: tighten sandbox media path assertion 2026-05-09 12:03:17 +01:00
Peter Steinberger
c43f00c267 fix: mark auth failure promise as fire-and-forget 2026-05-09 12:03:14 +01:00
Peter Steinberger
6eb633b29e test: tighten backup json assertion 2026-05-09 11:56:36 +01:00
Shakker
cedf30e3d6 fix: keep profile rotation nonblocking 2026-05-09 11:56:09 +01:00
Shakker
2ff63570d8 test: align opencode go catalog assertions 2026-05-09 11:56:09 +01:00
Peter Steinberger
a550149129 test: tighten music generation assertions 2026-05-09 11:55:18 +01:00
Ayaan Zaidi
7872909709 fix(status): restore codex status usage 2026-05-09 16:23:09 +05:30
Kelaw - Keshav's Agent
f27a263f29 test(status): restore codex usage fetch spy 2026-05-09 16:23:09 +05:30
Kelaw - Keshav's Agent
757324e40f fix(status): show codex usage for codex harness 2026-05-09 16:23:09 +05:30
Peter Steinberger
4f437f0040 test: tighten provider index catalog assertions 2026-05-09 11:52:42 +01:00
Peter Steinberger
7909d84a81 test: tighten commitment store assertions 2026-05-09 11:51:28 +01:00
Peter Steinberger
242a71663a test: refresh lint suppression allowlist 2026-05-09 06:51:20 -04:00
Peter Steinberger
8f56484b12 chore: remove stale unused imports 2026-05-09 06:51:20 -04:00
Peter Steinberger
815621c0d4 fix: finish run control defaults (#79385) (thanks @VACInc) 2026-05-09 06:51:20 -04:00
VACInc
b8e2f648a7 chat: clear thinking and fast defaults 2026-05-09 06:51:20 -04:00
VACInc
5ac1fee4de fix(cli): route infer thinking through simple completions 2026-05-09 06:51:20 -04:00
VACInc
223c4cf46c feat(cli): add thinking override to infer model run 2026-05-09 06:51:20 -04:00
VACInc
cfb0c34ff6 feat: add realtime consult overrides 2026-05-09 06:51:20 -04:00
Peter Steinberger
4235f6b192 test: tighten commitment extraction assertions 2026-05-09 11:50:15 +01:00
Peter Steinberger
bc27557301 test: tighten image provider registry assertions 2026-05-09 11:48:55 +01:00
hcl
398dd6e0b0 fix(failover): stop retrying assistant-prefill format failures
Summary:
- classify assistant-prefill provider rejections as format errors
- surface terminal format failover reasons instead of rotating profiles or falling back
- refresh shared Swift protocol output from current main

Verification:
- pnpm test src/agents/pi-embedded-runner/run/failover-policy.test.ts src/agents/pi-embedded-helpers.isbillingerrormessage.test.ts
- pnpm exec oxfmt --check --threads=1 CHANGELOG.md src/agents/pi-embedded-runner/run.ts src/agents/pi-embedded-runner/run/assistant-failover.ts src/agents/pi-embedded-runner/run/failover-policy.ts src/agents/pi-embedded-runner/run/failover-policy.test.ts src/agents/pi-embedded-helpers/failover-matches.ts src/agents/pi-embedded-helpers.isbillingerrormessage.test.ts
- fnm exec --using=24.13.0 pnpm lint --threads=8
- pnpm protocol:check
- GitHub CI on 678e92bcb2
2026-05-09 06:48:29 -04:00
Peter Steinberger
01cf27bc2e test: tighten image asset assertions 2026-05-09 11:47:37 +01:00
Peter Steinberger
bf185f9817 test: tighten config preset schema assertion 2026-05-09 11:45:58 +01:00
Peter Steinberger
b27a251ce5 docs: document mistral medium 3.5 usage 2026-05-09 11:45:43 +01:00
Peter Steinberger
8dc1080db7 test: tighten tool stream fallback assertions 2026-05-09 11:44:48 +01:00
Peter Steinberger
656fb80f4a test: tighten commitment runtime assertions 2026-05-09 11:43:13 +01:00
Peter Steinberger
c9f2d6f446 test: tighten planner error assertions 2026-05-09 11:41:57 +01:00
Peter Steinberger
85a28d02ca test: tighten websocket session error assertions 2026-05-09 11:40:55 +01:00
Peter Steinberger
f21b93e896 test: tighten google meet pull failure assertions 2026-05-09 11:39:36 +01:00
Peter Steinberger
fb238e06fb test: tighten google meet node realtime assertions 2026-05-09 11:38:20 +01:00
Steven Liekens
8d70f7e90f feat(mistral): add mistral-medium-3-5 model with reasoning support
- Add mistral-medium-3-5 to model catalog with reasoning: true
- Add compat support for reasoning in api.ts
- Update docs/providers/mistral.md

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-05-09 06:37:45 -04:00
Steven Liekens
25f7eae2ad feat(mistral): add mistral-medium-3-5 model
Add mistral-medium-3-5 to model catalog with input cost 1.5 and output cost 7.5.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-05-09 06:37:45 -04:00
Peter Steinberger
257383139f ci: stabilize oxlint unused import policy (#72101) 2026-05-09 06:36:20 -04:00
Peter Steinberger
5996d7b2c5 fix: remove stale imports after lint upgrade (#72101) 2026-05-09 06:36:20 -04:00
Peter Steinberger
f0adff9f60 docs: add changelog for sessions spawn fix (#72101) 2026-05-09 06:36:20 -04:00
xialonglee
f305499da3 fix(agents): ignore ACP-only streamTo and treat default model as unset 2026-05-09 06:36:20 -04:00
Peter Steinberger
30ce4751e3 test: tighten google meet talkback assertions 2026-05-09 11:35:57 +01:00
Peter Steinberger
b93fb8925e test: tighten google meet realtime callbacks 2026-05-09 11:34:38 +01:00
Peter Steinberger
d80f20057e fix: align realtime voice consult tool flow 2026-05-09 11:33:56 +01:00
Peter Steinberger
6810298cb3 test: tighten google meet audio bridge assertions 2026-05-09 11:32:19 +01:00
Peter Steinberger
ca31a705d0 test: tighten google meet manual action assertions 2026-05-09 11:30:24 +01:00
Peter Steinberger
288638dd1b test: tighten google meet listen assertions 2026-05-09 11:27:23 +01:00
Shakker
01741f81f8 test: remove stale unused imports 2026-05-09 11:26:43 +01:00
Peter Steinberger
8952d74b9a test: tighten google meet tab recovery assertions 2026-05-09 11:25:59 +01:00
Peter Lee
f039a9c32c fix(qqbot): route gateway websocket through ambient proxy agent (#72961)
Summary:
- Route QQBot gateway WebSocket creation through the ambient proxy agent.
- Preserve direct WebSocket behavior when no proxy environment is configured.
- Add proxy/no-proxy unit coverage and changelog credit.

Verification:
- pnpm test extensions/qqbot/src/engine/gateway/ws-client.test.ts
- git diff --check origin/main...HEAD
- Testbox: current main a83a8cfa fails pnpm lint:core with unrelated unused-import errors outside this PR diff.

Thanks @xialonglee.
2026-05-09 06:25:16 -04:00
Peter Steinberger
a83a8cfa18 test: tighten google meet node assertions 2026-05-09 11:23:27 +01:00
Val Alexander
fa79e9754e fix(gateway): harden macOS update restart lifecycle
Summary:
- Clear stale SIGUSR1 restart state before rejected or externally allowed restart handling can leave an in-flight token stuck.
- Verify the live gateway version after macOS package-update service refreshes and skip redundant restarts when the refreshed LaunchAgent already serves the expected version.
- Set generated LaunchAgents to a 10s throttle plus 20s shutdown window and widen gateway bind retries around supervisor-owned restarts.

Fixes #79577. Refs #78699 and #60885.

Verification:
- pnpm test src/cli/gateway-cli/run-loop.test.ts src/infra/infra-runtime.test.ts
- pnpm test src/cli/update-cli.test.ts src/daemon/launchd.test.ts src/gateway/server/http-listen.test.ts
- pnpm exec oxfmt --check --threads=1 src/cli/gateway-cli/run-loop.ts src/cli/gateway-cli/run-loop.test.ts
- pnpm check:changed
- Crabbox/Blacksmith wrapper smoke passed focused tests plus pnpm check:changed: https://github.com/openclaw/openclaw/actions/runs/25595985603
- PR CI was green before upstream main advanced; the latest rebased heads hit unrelated broad lint failures also reproduced on current main CI (for example https://github.com/openclaw/openclaw/actions/runs/25598671666). No failing lint diagnostics referenced this gateway/update diff.
2026-05-09 05:21:17 -05:00
Peter Steinberger
4e8914861f test: tighten google meet status assertions 2026-05-09 11:20:03 +01:00
Peter Steinberger
1bf26cd11f test: tighten google meet browser assertions 2026-05-09 11:18:15 +01:00
hekunwang
7236d6487e fix(agents): classify stream_read_error as transient (#79692)
* fix(agents): classify stream_read_error as transient

* fix: classify stream read errors as transient (#79692)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-09 06:18:04 -04:00
Shakker
a855414bc6 test: fix bundled lint and override guard 2026-05-09 11:16:27 +01:00
Peter Steinberger
4cc786930e test: tighten google meet setup diagnostics 2026-05-09 11:16:05 +01:00
Peter Steinberger
d2c4b944ba test: tighten google meet export assertions 2026-05-09 11:13:27 +01:00
Peter Steinberger
cc4a596be2 fix(discord): make realtime barge-in guard tunable 2026-05-09 11:11:54 +01:00
Peter Steinberger
2a89e03bf4 test: tighten google meet session assertions 2026-05-09 11:11:19 +01:00
Peter Steinberger
8921848436 test: tighten google meet artifact assertions 2026-05-09 11:08:29 +01:00
Peter Steinberger
2cc9efd231 test: tighten google meet api assertions 2026-05-09 11:06:42 +01:00
Peter Steinberger
4312ca0464 ci: cover plugin lanes in legacy release chunks 2026-05-09 06:06:08 -04:00
Peter Steinberger
b59d46b699 ci: include plugin docker lanes in full release 2026-05-09 06:06:08 -04:00
Peter Steinberger
c443469452 test: add plugin install docker e2e lanes 2026-05-09 06:06:08 -04:00
Peter Steinberger
1f4f51e8e2 feat: add plugin install overrides 2026-05-09 06:06:08 -04:00
Peter Steinberger
5cfcb70962 docs: tighten PR review skill guidance 2026-05-09 11:04:58 +01:00
Peter Steinberger
be875240b7 test: tighten google meet config assertions 2026-05-09 11:04:02 +01:00
Ayaan Zaidi
dc64b99c41 docs(qa): list Telegram auth E2E scenario 2026-05-09 15:28:54 +05:30
Ayaan Zaidi
fa6c3442d3 test(qa): add Telegram auth transition E2E 2026-05-09 15:28:54 +05:30
Peter Steinberger
4883a0e6c4 chore: update workspace dependencies 2026-05-09 10:58:36 +01:00
Peter Steinberger
e7fb5418b8 test: tighten memory host http assertions 2026-05-09 10:58:00 +01:00
Peter Steinberger
a6b01a6d71 test: tighten memory host sdk assertions 2026-05-09 10:55:28 +01:00
Peter Steinberger
63abd1fad5 test: tighten plugin npm package assertions 2026-05-09 10:52:37 +01:00
Peter Steinberger
eb9c227a09 test: tighten plugin clawhub release assertions 2026-05-09 10:50:14 +01:00
Peter Steinberger
ec25f282cb test: tighten plugin npm release assertions 2026-05-09 10:48:48 +01:00
Peter Steinberger
bd44369a26 test: tighten release check assertions 2026-05-09 10:47:08 +01:00
Peter Steinberger
446f4b2e2e docs: tighten PR review skill guidance 2026-05-09 10:47:02 +01:00
Peter Steinberger
ff3cb2930f test: tighten unit vitest config assertions 2026-05-09 10:45:10 +01:00
Peter Steinberger
d479216d92 fix: honor effective model auth health 2026-05-09 05:44:02 -04:00
nimbleenigma
aab7756859 fix(models): use effective auth health for status 2026-05-09 05:44:02 -04:00
Peter Steinberger
78a8ecad17 test: tighten scoped vitest config assertions 2026-05-09 10:43:34 +01:00
Peter Steinberger
76dd3b2518 test: tighten official channel catalog assertions 2026-05-09 10:40:45 +01:00
Peter Steinberger
beaecbcad4 refactor: use PI Codex Responses transport (#79726)
Routes explicit OpenAI Codex Responses runs through PI's native WebSocket-capable transport and removes the custom OpenClaw WebSocket implementation.
2026-05-09 05:40:30 -04:00
Peter Steinberger
f62cca91e6 test: tighten barnacle action assertions 2026-05-09 10:38:11 +01:00
Peter Steinberger
6cd63353ab docs: note qmd conflict warning (#72297) 2026-05-09 05:36:40 -04:00
Ted Li
c39f85822a fix(memory): warn on unverified qmd conflict 2026-05-09 05:36:40 -04:00
Ted Li
49db1908f3 fix(memory): verify qmd conflict before rebind 2026-05-09 05:36:40 -04:00
Ted Li
e422bcfc2a fix(memory): rebind qmd path conflicts from add errors 2026-05-09 05:36:40 -04:00
Peter Steinberger
b6136e38a9 test: tighten barnacle classifier assertions 2026-05-09 10:35:30 +01:00
Peter Steinberger
560c7440fb fix: serialize CLI preview bridge (#76914) (thanks @jack-stormentswe) 2026-05-09 05:34:47 -04:00
jack-stormentswe
2afffccee3 fix(agents/cli): bridge CLI assistant deltas into channel preview (#76869) 2026-05-09 05:34:47 -04:00
Peter Steinberger
b1bcfa6573 test: tighten changed lanes package assertions 2026-05-09 10:33:58 +01:00
Peter Steinberger
c38234b738 test: tighten changed lanes routing assertions 2026-05-09 10:31:55 +01:00
Peter Steinberger
cf0f1a171a test: tighten changed lanes baseline assertions 2026-05-09 10:30:27 +01:00
Peter Steinberger
f93caa5cd0 test: tighten docker e2e selected lane assertions 2026-05-09 10:28:24 +01:00
Peter Steinberger
c1a0d9db18 test: tighten docker e2e survivor assertions 2026-05-09 10:25:55 +01:00
Peter Steinberger
553c5dd1a8 test: tighten docker e2e chunk alias assertions 2026-05-09 10:24:20 +01:00
Peter Steinberger
edde12a43e test: tighten docker e2e release chunk assertions 2026-05-09 10:22:23 +01:00
Peter Steinberger
95cc6f4745 test: tighten docker e2e plan needs assertions 2026-05-09 10:20:24 +01:00
Peter Steinberger
e8483ea610 test: tighten plugin prerelease workflow assertions 2026-05-09 10:17:57 +01:00
Ted Li
43ea5c3e6f fix(feishu): stop automatic mention cascades (#71396)
Fix Feishu inbound mention targets being carried into outbound replies, with regression coverage for text, card, and streaming-card paths.\n\nThanks @MonkeyLeeT and @AxelHu.
2026-05-09 05:16:14 -04:00
Peter Steinberger
4672c3eed3 test: tighten postinstall migration assertions 2026-05-09 10:14:49 +01:00
Peter Steinberger
93cfa46454 test: dedupe postinstall missing path assertions 2026-05-09 10:13:33 +01:00
Peter Steinberger
0071f67fe6 feat(plugin-sdk): share presentation control helpers 2026-05-09 10:11:56 +01:00
Peter Steinberger
f46fda18d1 test: tighten plugin prerelease lane assertions 2026-05-09 10:11:49 +01:00
Abner Shang
9eaca28ef7 fix(backup): retry tar EOF races and skip live volatile files
Fixes #72249.\n\nSummary:\n- retry live backup tar EOF races\n- skip current live session, cron, log, and delivery-queue state files\n- preserve workspace lock/temp files and keep backup --json parseable\n\nVerification:\n- Crabbox pre-fix repro: tbx_01kr5xt9vf5pas5ee4aefrp3am\n- Crabbox post-fix proof: tbx_01kr5y3e1kbtt6chbypfdydbgs\n- pnpm check:test-types\n- pnpm lint:core\n- pnpm test src/commands/backup.test.ts src/infra/backup-volatile-filter.test.ts src/infra/backup-create.test.ts\n- CI on 37664570c7: green\n\nThanks @abnershang.
2026-05-09 05:11:43 -04:00
Peter Steinberger
7d91fcbe21 test: tighten package acceptance workflow assertions 2026-05-09 10:10:05 +01:00
Peter Steinberger
00adfdb9db test: tighten cross os release assertions 2026-05-09 10:08:57 +01:00
Peter Steinberger
e53ec522c2 test: tighten extension batch runner assertion 2026-05-09 10:07:21 +01:00
Peter Steinberger
fa73ef5711 test: tighten extension boundary error assertions 2026-05-09 10:06:23 +01:00
Peter Steinberger
0d7fbfeee1 build(canvas): refresh A2UI bundle hash 2026-05-09 10:05:07 +01:00
Dmitry Golubev
f13fb2e940 docs: update stale sub-agent context injection details (#79470)
Summary:
- Correct stale sub-agent docs to list the current minimal bootstrap context files.
- Add changelog credit for @lastguru-net.

Verification:
- pnpm docs:list
- pnpm exec oxfmt --check --threads=1 docs/tools/subagents.md CHANGELOG.md
- git diff --check
- GitHub CI: check-docs, Real behavior proof
2026-05-09 05:04:56 -04:00
Peter Steinberger
75a509aa52 test: tighten live shard assertions 2026-05-09 10:04:42 +01:00
Peter Steinberger
2807981669 fix: suppress DeepSeek DSML stream artifacts (#78331) 2026-05-09 05:03:10 -04:00
samzong
145cb6d35a fix(agents): suppress DeepSeek DSML stream artifacts 2026-05-09 05:03:10 -04:00
Peter Steinberger
7bf2d9ca87 test: tighten root dependency audit assertions 2026-05-09 10:02:55 +01:00
Peter Steinberger
62bdf5d5eb test: tighten build all cache assertions 2026-05-09 10:01:38 +01:00
Peter Steinberger
83caeb8396 test: tighten parallels smoke model assertions 2026-05-09 09:58:43 +01:00
Peter Steinberger
2def317185 test: tighten ci node test plan assertions 2026-05-09 09:57:11 +01:00
Peter Steinberger
53efd6350f test: tighten test report utils invocation assertions 2026-05-09 09:55:23 +01:00
Shakker
8c3a0c1296 test: align plain tool block parser spacing 2026-05-09 09:54:43 +01:00
Peter Steinberger
6c882f0470 test: tighten deadcode unused file assertions 2026-05-09 09:54:06 +01:00
Peter Steinberger
61bee804de test: tighten rtt harness assertions 2026-05-09 09:52:37 +01:00
Peter Steinberger
2abb0271a4 test: tighten real behavior proof assertions 2026-05-09 09:51:04 +01:00
Peter Steinberger
cb472abaf3 test: tighten vitest shard timing assertions 2026-05-09 09:49:55 +01:00
Peter Steinberger
daf0d8f9a0 test: tighten duplicate PR close plan assertions 2026-05-09 09:48:52 +01:00
Peter Steinberger
482cffb21d test: tighten test group report assertions 2026-05-09 09:47:28 +01:00
Peter Steinberger
31b73556d1 test: tighten codex protocol source assertions 2026-05-09 09:46:23 +01:00
Peter Steinberger
73437fdb65 test: tighten openclaw test state assertions 2026-05-09 09:45:28 +01:00
Peter Steinberger
b2d0e3ec40 test: tighten bundled plugin build entry assertions 2026-05-09 09:44:24 +01:00
Peter Steinberger
805b959c6f test: tighten prompt snapshot catalog assertions 2026-05-09 09:42:03 +01:00
Peter Steinberger
7822c35339 test: align plain tool block stripping expectations 2026-05-09 04:41:45 -04:00
Peter Steinberger
0a960da506 fix(matrix): preserve presentation fallback body 2026-05-09 04:41:45 -04:00
Peter Steinberger
e582cebf2d fix(matrix): wire presentation metadata delivery 2026-05-09 04:41:45 -04:00
kakahu
ad39262604 fix(matrix): avoid explicit undefined reply fanout options 2026-05-09 04:41:45 -04:00
kakahu
4a3abb78eb fix(matrix): consume implicit reply once in payload media fanout 2026-05-09 04:41:45 -04:00
kakahu
31a9eda81f Document Matrix presentation metadata 2026-05-09 04:41:45 -04:00
kakahu
4f2c7c7eec Test Matrix presentation metadata schema marker 2026-05-09 04:41:45 -04:00
kakahu
9b912ec70a Harden Matrix presentation metadata schema 2026-05-09 04:41:45 -04:00
OpenClaw Agent
90908cdf71 fix(matrix): preserve payload audioAsVoice in presentation sends 2026-05-09 04:41:45 -04:00
OpenClaw Agent
13cfb846ae test: regression guard — mediaUrls must never be dropped by sendPayload 2026-05-09 04:41:45 -04:00
OpenClaw Agent
d1645c04fd fix: version last in buildMatrixPresentationContent so it always wins 2026-05-09 04:41:45 -04:00
OpenClaw Agent
c5ff4d40ae fix: sendPayload now handles payload.mediaUrls (iterate all items, extraContent only on first) 2026-05-09 04:41:45 -04:00
OpenClaw Agent
ada2ff35c0 fix: test type error (await renderPresentation) and lint (remove ?? {} in spread) 2026-05-09 04:41:45 -04:00
OpenClaw Agent
2f826ce188 feat(matrix): expose MessagePresentation metadata in Matrix events 2026-05-09 04:41:45 -04:00
Peter Steinberger
493724ef2c test: tighten ci run timing selection assertions 2026-05-09 09:40:27 +01:00
Peter Steinberger
9fa8429c26 test: tighten ts topology record assertions 2026-05-09 09:39:22 +01:00
Shakker
76df5aaac0 test: preserve bracketed tool block spacing 2026-05-09 09:38:25 +01:00
Peter Steinberger
ad1c360322 test: tighten plugin gauntlet matrix assertions 2026-05-09 09:37:05 +01:00
Peter Steinberger
21970c9ac9 fix(openai): log realtime voice interruptions 2026-05-09 09:36:09 +01:00
Peter Steinberger
07fd11e175 test: tighten package candidate resolver assertions 2026-05-09 09:35:26 +01:00
Peter Steinberger
4b37b6de0d test: tighten ios version resolution assertions 2026-05-09 09:34:22 +01:00
Peter Steinberger
bb75d408b9 test: tighten bundled plugin asset assertions 2026-05-09 09:33:20 +01:00
Peter Steinberger
ef90023d14 test: tighten extension source classifier assertions 2026-05-09 09:31:47 +01:00
Peter Steinberger
e57441dfff test: tighten plugin boundary report assertions 2026-05-09 09:30:40 +01:00
Peter Steinberger
660a8a47db test: tighten run-oxlint sparse assertions 2026-05-09 09:29:34 +01:00
Peter Steinberger
d9a209161e docs(skills): clarify issue triage ship flow 2026-05-09 09:28:57 +01:00
Peter Steinberger
6697c6179c test: tighten sbom risk report assertions 2026-05-09 09:28:27 +01:00
Peter Steinberger
06ba26707d test: tighten run-vitest env assertions 2026-05-09 09:26:02 +01:00
Peter Steinberger
65fab4eb68 fix(agents): reuse context engine checkpoint 2026-05-09 09:25:19 +01:00
Peter Steinberger
5550d0ecf5 fix(ui): refresh model cache from session status 2026-05-09 09:25:19 +01:00
Peter Steinberger
ba2b033774 fix(plugin-sdk): parse harmony text tool calls 2026-05-09 09:25:19 +01:00
Peter Steinberger
089d777413 fix(markdown): trim blockquote separator spans 2026-05-09 09:25:19 +01:00
Peter Steinberger
a436547642 test: tighten discord proxy abort assertions 2026-05-09 09:24:45 +01:00
Peter Steinberger
b62166301e fix: annotate message-tool-only replies in Codex tool spec
Thread sourceReplyDeliveryMode into Codex/OpenClaw tool construction and annotate the message tool description for message-tool-only turns so visible replies use message(action=send).\n\nAlso adds focused regression coverage and a changelog entry.
2026-05-09 04:24:40 -04:00
Peter Steinberger
657d2331b3 test: tighten custom theme fetch assertions 2026-05-09 09:22:35 +01:00
Peter Steinberger
308006ad5e test: tighten voice-call config assertions 2026-05-09 09:20:41 +01:00
NVIDIAN
2db6bde617 fix(plugins): fail unresolved openclaw peer installs (#79494) 2026-05-09 17:19:54 +09:00
Peter Steinberger
14ce958eaf test: tighten deepinfra onboard assertions 2026-05-09 09:18:58 +01:00
Peter Steinberger
7541b8f4b6 fix: harden openai realtime response create 2026-05-09 09:18:04 +01:00
Peter Steinberger
3b0dafae1e test: tighten deepinfra model discovery assertions 2026-05-09 09:17:27 +01:00
Peter Steinberger
2c4ec93245 test: tighten deepinfra image assertions 2026-05-09 09:15:52 +01:00
Peter Steinberger
918ba58fe9 test: tighten deepinfra video assertions 2026-05-09 09:14:08 +01:00
Peter Steinberger
d3ac73c55a test: tighten deepinfra speech request assertions 2026-05-09 09:12:30 +01:00
Peter Steinberger
03b067ed8b test: tighten deepinfra embedding adapter assertions 2026-05-09 09:11:00 +01:00
Peter Steinberger
67b844860f test: tighten deepinfra media assertions 2026-05-09 09:08:56 +01:00
Peter Steinberger
4a9d3a5551 test: tighten runtime postbuild assertions 2026-05-09 09:07:05 +01:00
Peter Steinberger
e697ee354f test: tighten tsdown cleanup assertions 2026-05-09 09:05:54 +01:00
Peter Steinberger
1ab814e66f test: tighten web media rejection assertions 2026-05-09 09:04:50 +01:00
Peter Steinberger
1997ac449d test: tighten local media roots assertions 2026-05-09 09:00:48 +01:00
Peter Steinberger
b2bc45424d test: tighten media fetch assertions 2026-05-09 08:58:44 +01:00
Peter Steinberger
5849c32402 fix: install Codex for OpenAI onboarding (#79709)
* fix: install codex for openai onboarding

* docs: require crabbox e2e bug proof
2026-05-09 16:57:40 +09:00
Peter Steinberger
8ff6707e85 test: tighten media store error assertions 2026-05-09 08:55:57 +01:00
Peter Steinberger
f11ac1a734 test: tighten audio transcode ffmpeg assertion 2026-05-09 08:52:50 +01:00
Peter Steinberger
7cfa12fd2b feat: inject runtime model identity into prompts 2026-05-09 08:51:41 +01:00
Peter Steinberger
fe9a89a2d2 fix: interrupt active discord realtime voice 2026-05-09 08:51:41 +01:00
Peter Steinberger
d52ecd353d test: tighten document extractor runtime assertions 2026-05-09 08:51:15 +01:00
Peter Steinberger
602c59a092 test: tighten media read capability assertions 2026-05-09 08:49:54 +01:00
Peter Steinberger
a2e719bcee test: tighten media reference assertions 2026-05-09 08:48:01 +01:00
Peter Steinberger
854159fe1c test: tighten local media access error assertion 2026-05-09 08:46:00 +01:00
Peter Steinberger
74e930870e test: tighten media outside-workspace error assertion 2026-05-09 08:44:56 +01:00
Peter Steinberger
3cf5b8f7f5 test: tighten image tempdir cleanup assertion 2026-05-09 08:43:12 +01:00
Peter Steinberger
c605a0e6e8 test: tighten telephony tts override assertion 2026-05-09 08:41:53 +01:00
Peter Steinberger
4862dee679 test: tighten run-tsgo sparse guard assertion 2026-05-09 08:40:15 +01:00
Peter Steinberger
ad75cb661c test: tighten openclaw test instance assertions 2026-05-09 08:37:07 +01:00
Peter Steinberger
d2ac6c3dd5 test: tighten npm release parser assertions 2026-05-09 08:34:58 +01:00
Peter Steinberger
17f03566d8 test: tighten irc setup config assertions 2026-05-09 08:33:03 +01:00
Peter Steinberger
e4bae42d63 feat(plugin-sdk): derive tool target paths for hooks
Summary:
- derive apply_patch target paths for before_tool_call and trusted policy events
- route native Codex PreToolUse cwd/sandbox path facts through the host parser
- document the additive derivedPaths hook field and refresh the SDK API baseline

Verification:
- pnpm test src/agents/apply-patch-paths.test.ts src/plugins/host-tool-param-parsers.test.ts src/agents/pi-tools.before-tool-call.e2e.test.ts src/agents/harness/native-hook-relay.test.ts src/plugins/contracts/host-hooks.contract.test.ts
- pnpm check:test-types
- pnpm lint:core
- pnpm plugin-sdk:api:gen
- pnpm plugin-sdk:api:check
- pnpm run check:no-conflict-markers
- pnpm exec oxfmt --check --threads=1 CHANGELOG.md docs/plugins/hooks.md docs/.generated/plugin-sdk-api-baseline.sha256 src/agents/apply-patch-paths.test.ts src/agents/apply-patch-paths.ts src/agents/harness/native-hook-relay.test.ts src/agents/harness/native-hook-relay.ts src/agents/pi-tools.before-tool-call.e2e.test.ts src/agents/pi-tools.before-tool-call.ts src/agents/pi-tools.ts src/auto-reply/reply/dispatch-from-config.test.ts src/plugins/contracts/host-hooks.contract.test.ts src/plugins/hook-types.ts src/plugins/host-tool-param-parsers.test.ts src/plugins/host-tool-param-parsers.ts src/plugins/trusted-tool-policy.ts
- git diff --check origin/main...HEAD && git diff --check
- pnpm build

Co-authored-by: Eva <eva@100yen.org>
Co-authored-by: Josh Lehman <josh@martian.engineering>
2026-05-09 03:31:42 -04:00
Peter Steinberger
f8e15d52d8 test: tighten realtime voice consult runtime assertions 2026-05-09 08:30:55 +01:00
Peter Steinberger
86cc247d4d test: tighten realtime voice consult tool assertions 2026-05-09 08:27:46 +01:00
Peter Steinberger
d410289e7a test: tighten talk logging assertions 2026-05-09 08:25:35 +01:00
Peter Steinberger
44d7d6fd52 fix(qa-lab): refresh parity models and approval timeout
Summary:
- refresh QA parity workflow model refs to Opus 4.7 / GPT-5.5-alt
- raise approval-turn-tool-followthrough mock fallback timeouts to 60s
- credit the original contributor in the changelog

Verification:
- OPENCLAW_BUILD_PRIVATE_QA=1 OPENCLAW_ENABLE_PRIVATE_QA_CLI=1 pnpm build
- mock-openai approval-turn scenario passed 1/1 for openai/gpt-5.5 + openai/gpt-5.5-alt
- mock-openai approval-turn scenario passed 1/1 for anthropic/claude-opus-4-7 + anthropic/claude-sonnet-4-7
- pnpm test extensions/qa-lab/src/providers/mock-openai/server.test.ts extensions/qa-lab/src/qa-gateway-config.test.ts extensions/qa-lab/src/suite-planning.test.ts extensions/qa-lab/src/cli.runtime.test.ts
- pnpm check:workflows
- pnpm check:test-types
- pnpm exec oxfmt --check --threads=1 .github/workflows/openclaw-release-checks.yml .github/workflows/qa-live-transports-convex.yml CHANGELOG.md qa/scenarios/runtime/approval-turn-tool-followthrough.md
- git diff --check origin/main...HEAD
2026-05-09 03:22:55 -04:00
Peter Steinberger
63b8013b44 test: tighten realtime voice talkback assertions 2026-05-09 08:22:04 +01:00
Peter Steinberger
d00d4e5517 test: tighten realtime voice provider resolver assertions 2026-05-09 08:20:31 +01:00
Peter Steinberger
4f58bb38ec test: tighten talk session controller assertions 2026-05-09 08:19:12 +01:00
Peter Steinberger
54f32451f5 test: tighten talk event envelope assertion 2026-05-09 08:16:39 +01:00
Peter Steinberger
87665a435c test: tighten talk session log assertions 2026-05-09 08:15:05 +01:00
Peter Steinberger
d5f8860306 test: tighten talk diagnostics assertion 2026-05-09 08:13:58 +01:00
Peter Steinberger
47bf21a798 test: tighten qianfan provider assertions 2026-05-09 08:12:28 +01:00
Peter Steinberger
0c50957dbb fix(cli): clarify plugin tool command mistakes
Summary:
- clarify CLI diagnostics when an unknown subcommand is actually a plugin agent tool
- route early proxy-preflight misses through the same policy helper
- refresh bundled sidecar update fixtures for current package ownership

Verification:
- pnpm test src/cli/run-main.test.ts src/cli/run-main.exit.test.ts src/plugins/manifest-command-aliases.test.ts
- pnpm test src/infra/update-global.test.ts src/infra/update-runner.test.ts
- pnpm exec oxfmt --check --threads=1 CHANGELOG.md src/cli/run-main-policy.ts src/cli/run-main.ts src/cli/run-main.test.ts src/cli/run-main.exit.test.ts src/plugins/manifest-command-aliases.ts src/plugins/manifest-command-aliases.runtime.ts src/plugins/manifest-command-aliases.test.ts
- pnpm build
- live temp lossless-claw manifest: pnpm openclaw lcm_recent emits the agent-tool diagnostic and no plugins.allow suggestion

Co-authored-by: 100yenadmin <100yenadmin+agent-77214@100yen.org>
2026-05-09 03:11:44 -04:00
Peter Steinberger
678c41a222 test: tighten media image runtime assertions 2026-05-09 08:08:02 +01:00
Peter Steinberger
9385eaaf88 chore(release): prepare 2026.5.8 2026-05-09 08:05:17 +01:00
Peter Steinberger
588606c83f test: tighten media apply cli assertions 2026-05-09 08:05:03 +01:00
Peter Steinberger
2a5172665b test: tighten media apply skip assertions 2026-05-09 08:03:38 +01:00
Shakker
2e29090c37 test: wire qa channel turn fixture 2026-05-09 08:01:50 +01:00
Peter Steinberger
fd3aa10202 test: tighten media shared guard assertions 2026-05-09 08:01:15 +01:00
Peter Steinberger
b865bddd96 test: tighten media vision skip output assertion 2026-05-09 07:59:47 +01:00
Peter Steinberger
59e2165796 test: tighten media auto audio output assertion 2026-05-09 07:58:43 +01:00
Peter Steinberger
b4376a8bcd test: tighten media video header assertion 2026-05-09 07:57:27 +01:00
Peter Steinberger
cb61d357d9 test: tighten media cli audio assertions 2026-05-09 07:56:29 +01:00
Shakker
dbb62f21f4 test: isolate ollama discovery catalog cache 2026-05-09 07:55:00 +01:00
Peter Steinberger
39a6f3fa47 test: tighten media echo transcript assertions 2026-05-09 07:53:46 +01:00
Peter Steinberger
5c57e55f2f test: tighten media runtime override assertion 2026-05-09 07:52:19 +01:00
Shakker
1d36ab8cb0 test: fix nvidia plugin registration stub 2026-05-09 07:51:46 +01:00
Peter Steinberger
fccb04a311 fix: normalize google configured catalog model ids 2026-05-09 07:49:54 +01:00
Shakker
cb0f6e6466 test: fix matrix package scan baselines 2026-05-09 07:48:58 +01:00
Peter Steinberger
3a8cfdf652 test: mock durable channel send seam 2026-05-09 02:47:26 -04:00
Peter Steinberger
281f04e866 test: mock durable transcript echo sends 2026-05-09 02:47:26 -04:00
Peter Steinberger
1b7e150a2d docs: add changelog for codex hook relay fix (#77533) 2026-05-09 02:47:26 -04:00
Ruben Cuevas
86c28c84c9 fix(codex): keep native hook relay alive for long turns 2026-05-09 02:47:26 -04:00
Peter Steinberger
082c683d30 test: tighten deepgram runner assertions 2026-05-09 07:43:15 +01:00
Peter Steinberger
db2cc57cf1 test: tighten media ssrf result assertion 2026-05-09 07:41:38 +01:00
Peter Steinberger
95b936fd46 test: tighten backup asset kind assertion 2026-05-09 07:40:02 +01:00
Val Alexander
49cb2b97ae docs: update Val maintainer areas (#79680) 2026-05-09 01:39:31 -05:00
Peter Steinberger
f1fc182430 fix: avoid false event-loop degradation (#77028) (thanks @rubencu) 2026-05-09 02:39:03 -04:00
Ruben Cuevas
105c1ec8c8 fix(gateway): avoid false event-loop health degradation 2026-05-09 02:39:03 -04:00
Peter Steinberger
383f9d096a test: tighten media url fallback assertions 2026-05-09 07:38:19 +01:00
Peter Steinberger
38ab7f8427 test: tighten fast json status assertions 2026-05-09 07:35:45 +01:00
Peter Steinberger
74ab0fdd7a docs: refresh plugin sdk api baseline 2026-05-09 02:34:56 -04:00
Peter Steinberger
477f1f2917 test: update echo transcript send mock 2026-05-09 02:34:56 -04:00
Peter Steinberger
311e4608d1 feat: unify model catalog registration 2026-05-09 02:34:56 -04:00
Peter Steinberger
d9261a292a test: tighten status scan assertions 2026-05-09 07:33:53 +01:00
Peter Steinberger
1671e7532a test: tighten channel status fallback assertions 2026-05-09 07:30:27 +01:00
Peter Steinberger
f35993b426 test: tighten embedded tui event assertions 2026-05-09 07:29:06 +01:00
Peter Steinberger
70ac5f5421 test: tighten backup verify wrapper assertions 2026-05-09 07:27:28 +01:00
TheArchitectit
80a3d48b99 feat(acpx): support structured agent args
Summary:
- Add optional ACPX agent args config support while preserving command-only configs.
- Quote flattened args before passing the command string to the ACP client so spaces and single quotes preserve argv boundaries.
- Document the config shape and add changelog attribution.

Verification:
- pnpm test extensions/acpx/src/config.test.ts
- pnpm exec oxfmt --check --threads=1 extensions/acpx/src/config.ts extensions/acpx/src/config.test.ts docs/tools/acp-agents-setup.md CHANGELOG.md
- git diff --check
- pnpm check:changed
- isolated openclaw config patch/validate/get real behavior proof for ACPX args.
2026-05-09 01:26:17 -05:00
Peter Steinberger
a6bead8e04 test: tighten status json audit assertions 2026-05-09 07:25:37 +01:00
Shakker
730b0bea71 test: fix discord voice route mock type 2026-05-09 07:24:17 +01:00
Peter Steinberger
f5e19470ce docs: update maintainer review policy 2026-05-09 07:23:07 +01:00
Peter Steinberger
edbb8f738f test: tighten status runtime plugin assertions 2026-05-09 07:22:34 +01:00
Peter Steinberger
36aa7b6a3c test: tighten status json version assertion 2026-05-09 07:21:11 +01:00
Peter Steinberger
95b6b18310 test: tighten status overview version assertion 2026-05-09 07:19:39 +01:00
Peter Steinberger
decc8e8e5a test: tighten gateway proxy repair assertions 2026-05-09 07:18:05 +01:00
Peter Steinberger
17427557b7 test: tighten gateway install token persistence assertions 2026-05-09 07:16:12 +01:00
Peter Steinberger
2e5ab0ae91 feat: improve discord realtime voice routing 2026-05-09 07:15:40 +01:00
Peter Steinberger
bf35236419 test: tighten agents list provider assertions 2026-05-09 07:13:48 +01:00
Peter Steinberger
7013112f8d test: tighten agent runtime secret target assertions 2026-05-09 07:12:15 +01:00
Shakker
56ab8d56ee test: fix message delivery contract assertions 2026-05-09 07:11:22 +01:00
Peter Steinberger
abfa355884 test: tighten channel setup status formatter assertion 2026-05-09 07:10:46 +01:00
Peter Steinberger
86c0e3d3eb test: tighten doctor startup maintenance assertions 2026-05-09 07:08:23 +01:00
Peter Steinberger
5977eb825b test: tighten channel list config assertions 2026-05-09 07:07:07 +01:00
Peter Steinberger
1b23bf16c0 test: tighten backup manifest assertions 2026-05-09 07:05:39 +01:00
Peter Steinberger
a4b17d65a8 refactor: consolidate message delivery API 2026-05-09 07:04:04 +01:00
Peter Steinberger
195db88d71 test: tighten cli route runtime assertions 2026-05-09 07:03:42 +01:00
Josh Avant
6b090b8cc8 fix: preserve Cloudflare gateway auth transport (#79673)
* fix: preserve Cloudflare gateway auth transport

* docs: add Cloudflare gateway changelog
2026-05-09 01:02:34 -05:00
Peter Steinberger
38a53aa5e3 test: tighten system run sha assertions 2026-05-09 07:01:59 +01:00
Peter Steinberger
19a5a80286 test: tighten cli exit callback assertions 2026-05-09 07:00:33 +01:00
Peter Steinberger
e3f336c22d test: tighten private qa cli module assertions 2026-05-09 06:58:22 +01:00
Peter Steinberger
47a755969d test: tighten plugin service logger assertions 2026-05-09 06:56:14 +01:00
tmimmanuel
2945948a5e feat(gateway): add SDK task ledger RPCs (#74847)
Adds Gateway task ledger RPCs and SDK methods for listing, fetching, and cancelling durable background tasks. Includes protocol schemas/scopes, generated Swift models, docs, and tests. Public task summary text is sanitized before SDK exposure.
2026-05-09 00:55:06 -05:00
Peter Steinberger
fa637c1744 test: tighten ui responsive geometry assertions 2026-05-09 06:54:30 +01:00
Peter Steinberger
39dfe4d1f8 test: tighten ui chat idempotency keys 2026-05-09 06:53:16 +01:00
Josh Avant
3af81481b4 fix(google): retry stalled Gemini first response (#79668)
* fix(google): retry stalled gemini first response

* docs(changelog): note gemini first-response retry

* fix(google): clear gemini first-response deadline
2026-05-09 00:52:44 -05:00
Peter Steinberger
b972e207cf test: tighten voice continue operation id 2026-05-09 06:51:43 +01:00
Peter Steinberger
9162d547a5 test: tighten voice tailscale spawn assertions 2026-05-09 06:50:17 +01:00
Peter Steinberger
58a80d3d93 docs(oc-path): expand usage examples 2026-05-09 01:48:35 -04:00
Peter Steinberger
696540f63a docs(oc-path): explain why path addressing helps 2026-05-09 01:48:35 -04:00
Peter Steinberger
52a319047e docs(oc-path): add bundled plugin overview and per-kind CLI recipes 2026-05-09 01:48:35 -04:00
Gio Della-Libera
4656848900 docs(path): format oc-path CLI table 2026-05-09 01:48:35 -04:00
Gio Della-Libera
8f26422840 fix(oc-path): tighten path contracts 2026-05-09 01:48:35 -04:00
Peter Steinberger
295c30fd61 test: avoid hoisted cron mock import 2026-05-09 01:48:35 -04:00
Peter Steinberger
a22c5822c3 docs: finish oc-path plugin docs 2026-05-09 01:48:35 -04:00
Gio Della-Libera
457c29b36a docs(path): scrub references to dropped grammar features 2026-05-09 01:48:35 -04:00
Gio Della-Libera
7ad33c05b1 lint(oc-path): satisfy CI's stricter consistent-return + type-param rules 2026-05-09 01:48:35 -04:00
Gio Della-Libera
080e34a2c2 lint(oc-path): satisfy curly + unused-import rules 2026-05-09 01:48:35 -04:00
Gio Della-Libera
ac9418d206 refactor(oc-path): drop YAGNI grammar features
Removes four path-syntax features that added complexity without
enough real-world use:

- **Quoted-segment escape sequences**: kept quoted segments themselves
  (still needed for keys with `/` or `.`) but dropped `\"` and `\`
  escapes. Quoted content is now byte-literal, refused if it contains
  `"` or `\`. Simplifies scanBracketAware (drops the `escaped` state),
  unquoteSeg (no decode loop), quoteSeg (no escape encoding).

- **CSS-style predicate operators**: removed `*=` (substring), `^=`
  (prefix), `$=` (suffix). Predicate set is now `=`, `!=`, and the
  numeric `<` / `<=` / `>` / `>=`. Lint rules needing substring
  matching can use `findOcPaths(*)` + JS filter.

- **`$first` positional**: alias for index 0 (or first-declared key).
  Use the literal `0` instead.

- **`-N` negative index**: rarely useful beyond `-1`, which is already
  covered by `$last`. The "negative numeric key on object" case
  (Telegram supergroup IDs) still works — non-indexable containers
  fall through to literal-key lookup.

Behavior loss: zero in observed real workspace files. Tests for the
dropped features removed (15 tests).

Net: -22 LoC src + 15 fewer tests. Total package: 10,570 → 10,275 LoC.
2026-05-09 01:48:35 -04:00
Gio Della-Libera
71c855f244 refactor(oc-path): consolidate dispatch and trim comment surface
Substrate simplifications and broad comment cleanup:

**Walker collapse (find.ts)**: three near-parallel walkers
(walkJsonc, walkJsonl + walkJsonlInsideLine, walkMd + walkMdInsideBlock
+ walkMdInsideItem) shared the same segment-shape dispatch — union /
predicate / `*` / `**` / positional / literal — with different child
types. Extracted as a single `dispatchSeg<T>(ops, ...)` that takes a
per-kind `WalkOps<T>` table; each walker is a thin wrapper. The three
md walkers fold into one `walkMd(level, ...)` polymorphic on a
`MdLevel` discriminated union. JSONL routes the post-line-slot
descent through walkJsonc via a WeakMap-tagged ast holder.

**CLI (cli.ts)**: each command duplicated four times the same
try/catch/emit/exit dance — missing-arg check, parseOcPath try/catch,
OcEmitSentinelError catch. Extracted as `requireArg`, `tryParse`,
`catchSentinel`. Folded `RawPathOptions` into `PathCommandOptions`
(identical shape) and collapsed `.option(...)` chains via
`withCommonOpts`.

**universal.ts**: setJsoncLeaf and setJsonlLeaf were near-identical
(resolve, refuse root, coerce, set, wrap). Extracted as
`setStructuredLeaf<A, M>` with optional `onLine` for jsonl's
whole-line replacement. Inlined setMdLeaf (7-line passthrough) into
setOcPath. Dropped four `throw new Error("unreachable")` statements
TS exhaustive checking already covers.

**oc-path.ts**: 35 `throw new OcPathError(...)` sites compress through
a `fail()` helper. File-slot containment check (absolute, parent-dir,
control chars) extracted as `validateFileSlot` so parse + format share
the same defense. Three structural-nesting throws in formatOcPath
collapse into two. Three near-parallel string scanners
(`indexOfTopLevel`, `splitRespectingBrackets`, `validateBrackets`) fold
through one `scanBracketAware(s, onChar, onUnbalanced)` helper.

**jsonl/edit.ts**: pickLineIndex compressed; line-address dispatch
shares the value-line filter as a small helper.

**Internal review codes stripped**: P-NNN, F-NN, I-NN, H2-NN, OP-NN,
R-NN, T-NN, S-NN, BFJ-NN, RJC-NN, RJL-NN, FM-NN, A-NN, B-NN, CC-NN,
wave-NN — these were review-process artifacts (sprint identifiers,
finding IDs, pitfall taxonomy IDs) that mean nothing to a reader who
didn't participate in the originating review. Test names rewritten
human-readable; comments lose their P-NNN bookmarks; describe blocks
drop the wave-NN prefix.

**Pitfalls test consolidated**: `tests/scenarios/pitfalls.test.ts`
(637 LoC, organized by P-NNN) replaced by `security-and-limits.test.ts`
(288 LoC) — unique coverage migrates over with descriptive names;
duplicates of OP-/R-/etc. tests are dropped.

**Comment cleanup**: per CLAUDE.md "default to writing no comments;
add one only when the WHY is non-obvious", trimmed multi-paragraph
WHY-prose on every public export, running prose inside function
bodies that restated what the next line of code said, section-divider
comments in test files, and module-level doc-comments that paraphrased
the file name. Kept load-bearing context: NFC re-check after grow,
quote-aware split symmetry, multi-char operator precedence, sentinel
guard catch routes, WeakMap holder rationale.

**MdAst slimmed**: `tables` and `codeBlocks` fields removed — substrate
addressing doesn't go inside them, and markdown-it's tokenizer
already excludes them from heading/item misparse without
first-class AST modeling.

Net reduction across the 10 consolidation/cleanup commits: ~3,800 LoC.
2026-05-09 01:48:35 -04:00
Gio Della-Libera
7b7e65105b refactor(oc-path): markdown-it tokenizer + grammar relaxation
The hand-rolled MD parser is replaced with a markdown-it token-stream
walker. AstTable and AstCodeBlock are dropped from the AST — the
substrate doesn't address into table rows or fence content, and
markdown-it's tokenizer already handles "##/- inside fenced code
should not be a heading/item" correctly without first-class AST
modeling.

Grammar opinions move from parser to lint:
  - Indented `## foo` (1-3 spaces) is now a heading
  - Empty `## ` is a heading with empty slug
  - Ordered lists (`1. step`) become items
  - Nested sub-bullets become items at flat level

Each was previously a silent parser refusal — now they are recognized
shapes. Lint rules can flag them (`OC_HEADING_INDENTED`,
`OC_HEADING_EMPTY`, etc.) where authoring conventions require the
narrower shape.

Net: parse.ts drops 301 → 207 LoC; tables/code-blocks scenario tests
removed wholesale (-251 LoC of test surface that pinned dead AST
fields).
2026-05-09 01:48:35 -04:00
Gio Della-Libera
6283c8247c refactor(oc-path): drop YAML kind from substrate
The YAML AST/parser/emitter/edit-resolve module is removed. The
substrate now supports md / jsonc / jsonl. Walker, universal verbs,
CLI, and tests are stripped of yaml-kind branches; the `yaml` package
dependency is dropped.

Why: YAML editing was the most complex per-kind module (~750 LoC of
parse/emit/resolve plus walker scaffold) for the smallest surface area
in real-world usage — substrate consumers (lkg, gateway config, agent
metadata) all pivoted to jsonc / md / jsonl. Carrying yaml support
indefinitely was net cost.

Walker depth-cap test that previously relied on YAML's lack of a
parser-level depth cap is rewritten to construct a synthetic JSONC AST
chain by hand, exercising the walker's MAX_TRAVERSAL_DEPTH defense in
isolation from the parser's MAX_PARSE_DEPTH.

Net: -1467 LoC across substrate + tests.
2026-05-09 01:48:35 -04:00
Gio Della-Libera
30e69142f0 fix(oc-path): three followup fixes (sentinel guard, byte cap, walker parity)
Closes three load-bearing gaps in the substrate's defenses:

- **md sentinel defense-in-depth (I2)**: `setJsoncOcPath` and the jsonl
  finalize-via-render path both refuse sentinel-bearing values before
  they reach the AST. The md path was deferring entirely to round-trip
  echo through `emitMd`, which `acceptPreExistingSentinel` skips by
  default. Closes the cross-kind asymmetry.

- **jsonc byte-length cap (N3)**: pre-parse cap on input length, symmetric
  with the existing post-parse depth cap at `nodeToJsoncValue`. Without
  this, `parseTree` allocates the full tree before our walker notices.

- **md walker union + predicate parity (I3)**: jsonc walkers dispatched
  union and predicate at every slot; md dispatched only on
  wildcard/ordinal/positional/literal, so `oc://X.md/{Boundaries,Limits}/...`
  matched zero items where the same shape on jsonc would match both.
  Pins the parity.
2026-05-09 01:48:35 -04:00
Peter Steinberger
e3b33a26cd refactor: move oc-path into plugin 2026-05-09 01:48:35 -04:00
Peter Steinberger
9a151b248e test: tighten msteams continue callbacks 2026-05-09 06:48:16 +01:00
Peter Steinberger
094d0b88a5 test: tighten discord dispatch cfg assertions 2026-05-09 06:46:51 +01:00
Peter Steinberger
eb9f803ff1 test: tighten codex trajectory recorder assertion 2026-05-09 06:44:19 +01:00
Peter Steinberger
c85aaa6e47 test: tighten googlechat auth runtime callbacks 2026-05-09 06:42:46 +01:00
Peter Steinberger
3e1dc0f284 test: tighten googlechat auth transport assertions 2026-05-09 06:41:05 +01:00
Peter Steinberger
be1a1c4a6e test: tighten googlechat pairing text 2026-05-09 06:39:20 +01:00
Peter Steinberger
b34cf2f1a2 fix: externalize matrix plugin 2026-05-09 06:38:29 +01:00
Josh Avant
5fdef4c39e fix(codex): ignore account updates for turn liveness (#79667)
* fix codex app-server completion liveness

* docs changelog codex liveness fix
2026-05-09 00:38:22 -05:00
Peter Steinberger
bb95031ea5 test: tighten googlechat webhook body assertion 2026-05-09 06:38:00 +01:00
Peter Steinberger
ce843fe53d test: tighten googlechat pairing timestamp 2026-05-09 06:36:58 +01:00
Peter Steinberger
73cd9f4eb8 test: tighten qa runtime tool assertions 2026-05-09 06:35:35 +01:00
Peter Steinberger
c1ac243d0f test: tighten codex registration callbacks 2026-05-09 06:34:27 +01:00
Peter Steinberger
ba07111800 test: tighten slack dispatch cfg assertions 2026-05-09 06:33:07 +01:00
Peter Steinberger
0257a88df8 test: tighten slack action cfg assertions 2026-05-09 06:30:20 +01:00
Peter Steinberger
0d277e9533 test: tighten slack thread cfg assertions 2026-05-09 06:29:07 +01:00
Peter Steinberger
255f9648c0 test: tighten slack reaction cfg assertions 2026-05-09 06:27:15 +01:00
Peter Steinberger
f1c189cd19 test: tighten slack socket logger assertions 2026-05-09 06:24:17 +01:00
Peter Steinberger
9635d26c52 test: tighten slack reconnect timestamps 2026-05-09 06:23:07 +01:00
Peter Steinberger
d3a29110a0 test: tighten slack thread cache timestamp 2026-05-09 06:21:33 +01:00
Peter Steinberger
0e1ea080b8 test: tighten msteams conversation timestamps 2026-05-09 06:20:14 +01:00
Peter Steinberger
4b2e231bf4 test: tighten memory probe cache assertions 2026-05-09 06:18:10 +01:00
Peter Steinberger
0889223a07 fix: validate inline images against session agent model (#79416) 2026-05-09 01:18:04 -04:00
Peter Steinberger
3938328aa4 test: tighten voice outbound lifecycle assertions 2026-05-09 06:16:55 +01:00
Shakker
0d93faac54 test: fix telegram proxy send mock 2026-05-09 06:16:25 +01:00
Peter Steinberger
1a08e77ded test: tighten bonjour callback assertions 2026-05-09 06:15:09 +01:00
Peter Steinberger
63926e749d test: tighten mattermost dm retry assertion 2026-05-09 06:13:57 +01:00
Peter Steinberger
285283ce04 test: tighten app settings timing assertions 2026-05-09 06:12:29 +01:00
Peter Steinberger
951025ca9d test: tighten gateway client timing assertions 2026-05-09 06:10:43 +01:00
Peter Steinberger
0ed57bf337 test: tighten discord action option assertions 2026-05-09 06:08:42 +01:00
Peter Steinberger
6af6d166cd test: tighten voice response session assertions 2026-05-09 06:07:30 +01:00
Shakker
f8355a82f3 test: tighten live array assertions 2026-05-09 06:07:01 +01:00
Josh Avant
024528c937 fix(nextcloud-talk): detect missing bot response feature (#79657)
* fix(nextcloud-talk): detect missing bot response feature

* docs(changelog): note nextcloud talk response fix
2026-05-09 00:06:44 -05:00
Peter Steinberger
9202e74b11 test: tighten memory watcher error assertion 2026-05-09 06:06:05 +01:00
Peter Steinberger
12ebb97168 test: tighten voice runtime consult assertions 2026-05-09 06:05:09 +01:00
Peter Steinberger
b5def5dbdf test: tighten voice webhook handler assertion 2026-05-09 06:03:55 +01:00
Shakker
5c9755d347 test: tighten e2e array assertions 2026-05-09 06:03:18 +01:00
Peter Steinberger
98cc3d8839 test: tighten voice call tunnel spawn options 2026-05-09 06:01:49 +01:00
Shakker
d8537bffac test: tighten agent runtime array assertions 2026-05-09 06:00:40 +01:00
Peter Steinberger
e8c76de8e0 test: tighten qa web runtime options 2026-05-09 06:00:09 +01:00
Peter Steinberger
84273aebdb test: tighten approval handler runtime assertion 2026-05-09 05:58:40 +01:00
Shakker
0fef42ddcc test: tighten plugin extension array assertions 2026-05-09 05:58:17 +01:00
Peter Steinberger
dedbd8d6fd fix(google): canonicalize gemini pro dynamic ids 2026-05-09 05:57:18 +01:00
Shakker
e2d8b78b69 test: tighten daemon infra array assertions 2026-05-09 05:56:26 +01:00
Shakker
0924eb0731 test: tighten gateway array assertions 2026-05-09 05:54:12 +01:00
Peter Steinberger
4962620a4b test: tighten node builtin mock defaults 2026-05-09 05:52:27 +01:00
Shakker
90ab12c6dc test: tighten agent helper array assertions 2026-05-09 05:52:12 +01:00
Peter Steinberger
e22730e1c5 test: tighten provider auth runtime export assertion 2026-05-09 05:50:47 +01:00
Shakker
2d72566fa1 test: tighten command array assertions 2026-05-09 05:50:35 +01:00
Peter Steinberger
fdc8726e46 test: tighten status json runtime result assertion 2026-05-09 05:49:09 +01:00
Shakker
8f786b25a2 test: tighten infra array assertions 2026-05-09 05:48:53 +01:00
Peter Steinberger
748fe6b212 test: tighten gateway live helper client assertion 2026-05-09 05:47:36 +01:00
Peter Steinberger
b61ec71103 test: tighten agents delete workspace assertion 2026-05-09 05:46:35 +01:00
Shakker
0517b54942 test: tighten agents array assertions 2026-05-09 05:46:22 +01:00
Peter Steinberger
9dc8131466 test: tighten models auth context assertion 2026-05-09 05:45:35 +01:00
Shakker
00a96acb21 test: tighten plugin provider array assertions 2026-05-09 05:44:40 +01:00
Peter Steinberger
b928bc619f test: tighten doctor version note assertion 2026-05-09 05:44:23 +01:00
Peter Steinberger
e0225380a7 test: tighten status table renderer assertion 2026-05-09 05:43:08 +01:00
Shakker
114aad8281 test: tighten auto reply array assertions 2026-05-09 05:42:39 +01:00
Peter Steinberger
9795b5c7ee test: tighten line webhook event assertions 2026-05-09 05:42:00 +01:00
Shakker
3ee3fd72bb test: tighten registry empty array assertions 2026-05-09 05:40:02 +01:00
Peter Steinberger
e7f3644207 test: tighten vllm discovery assertion 2026-05-09 05:39:52 +01:00
Peter Steinberger
297665197b test: tighten browser request timeout assertion 2026-05-09 05:38:42 +01:00
Shakker
d19735cbb3 test: tighten shared empty array assertions 2026-05-09 05:37:51 +01:00
Peter Steinberger
170c1cd1f8 test: tighten qa runtime export assertions 2026-05-09 05:37:40 +01:00
Peter Steinberger
e7e8b81662 test: tighten lazy service handle assertion 2026-05-09 05:36:20 +01:00
Shakker
7d5cfd157a test: tighten infra sdk empty array assertions 2026-05-09 05:36:12 +01:00
Peter Steinberger
d4b20e8904 test: tighten npm pack temp dir assertion 2026-05-09 05:34:39 +01:00
Peter Steinberger
da6abf1b09 test: tighten approval gateway resolver assertion 2026-05-09 05:33:42 +01:00
Shakker
1f63003b93 test: tighten command empty array assertions 2026-05-09 05:32:52 +01:00
Peter Steinberger
fc11a54598 test: tighten approval route timer assertion 2026-05-09 05:32:36 +01:00
Shakker
9e4fb927bc test: tighten cli empty array assertions 2026-05-09 05:31:22 +01:00
Peter Steinberger
2fd29af86c test: tighten wait forever interval assertion 2026-05-09 05:30:04 +01:00
Shakker
e771e251eb test: tighten core io empty array assertions 2026-05-09 05:29:45 +01:00
Peter Steinberger
ef214587fd test: tighten line reply fallback assertion 2026-05-09 05:29:01 +01:00
Shakker
a88ab55389 test: tighten optional plugin tool assertions 2026-05-09 05:28:15 +01:00
Peter Steinberger
27ac19836c test: tighten gateway stage error assertions 2026-05-09 05:28:02 +01:00
Shakker
a805abc878 test: tighten channel plugin id assertions 2026-05-09 05:27:08 +01:00
Peter Steinberger
8a710a6b66 test: tighten websocket session error assertions 2026-05-09 05:26:40 +01:00
Shakker
e6755fdef9 test: tighten qa and memory array assertions 2026-05-09 05:26:01 +01:00
Peter Steinberger
87ebc05948 test: tighten channel queue error assertions 2026-05-09 05:25:42 +01:00
Peter Steinberger
1a7b358f00 test: tighten temp dir creation assertion 2026-05-09 05:24:10 +01:00
Shakker
70a0da9ad0 test: tighten bundled channel empty array assertions 2026-05-09 05:23:46 +01:00
Peter Steinberger
a35a1f8315 test: tighten concurrency error callback assertion 2026-05-09 05:23:05 +01:00
Shakker
647a5e0de6 test: tighten plugin contract empty array assertions 2026-05-09 05:22:30 +01:00
Peter Steinberger
6710763e5c test: tighten discord webhook activity assertion 2026-05-09 05:21:42 +01:00
Shakker
d8a83510ce test: tighten plugin registry empty array assertions 2026-05-09 05:21:01 +01:00
Peter Steinberger
11a9d94c07 test: tighten discord component edit assertion 2026-05-09 05:20:41 +01:00
Peter Steinberger
2ee51f4826 test: tighten discord startup delay assertion 2026-05-09 05:19:22 +01:00
Shakker
df4aaaecfa test: tighten plugin loader empty array assertions 2026-05-09 05:19:02 +01:00
Shakker
5496100a51 test: tighten browser empty array assertions 2026-05-09 05:17:37 +01:00
Peter Steinberger
b1cb77bc84 test: tighten msteams sent cache timestamp 2026-05-09 05:17:22 +01:00
Shakker
2ddd8dddba test: tighten messaging empty array assertions 2026-05-09 05:16:20 +01:00
Peter Steinberger
a370f18bba test: tighten sdk live shape assertions 2026-05-09 05:15:54 +01:00
Josh Avant
3391c5b050 fix(gateway): preserve trusted-proxy Control UI scopes (#79643)
* fix(gateway): preserve trusted proxy control ui scopes

* docs: add trusted proxy control ui changelog
2026-05-08 23:15:19 -05:00
Peter Steinberger
fa126d43fb test: tighten media image provider assertions 2026-05-09 05:14:42 +01:00
Shakker
7b73faaa7e test: tighten task empty array assertions 2026-05-09 05:13:55 +01:00
Shakker
8cd978c02a test: tighten core empty array assertions 2026-05-09 05:12:12 +01:00
Peter Steinberger
7e6ce0d8f3 test: tighten cli audio runner exec assertion 2026-05-09 05:12:02 +01:00
Shakker
21317a69df test: tighten config empty array assertions 2026-05-09 05:10:54 +01:00
Peter Steinberger
89653ff1fd fix: canonicalize nested gemini catalog ids 2026-05-09 05:10:50 +01:00
Shakker
f35dbcc328 test: tighten security empty array assertions 2026-05-09 05:09:12 +01:00
Shakker
1663b75862 test: tighten acp empty array assertions 2026-05-09 05:07:44 +01:00
Shakker
919e87784c test: tighten ui session array assertions 2026-05-09 05:05:25 +01:00
Peter Steinberger
c04df3adfb test: tighten whatsapp connection close assertion 2026-05-09 05:05:04 +01:00
Shakker
b33fe72fc3 test: tighten script empty array assertions 2026-05-09 05:03:42 +01:00
Peter Steinberger
e68206deed test: tighten stale call reaper error assertion 2026-05-09 05:03:18 +01:00
Shakker
3ce49c0acb test: tighten memory empty array assertions 2026-05-09 05:02:14 +01:00
Peter Steinberger
bef9f75f05 test: tighten app tool stream compaction assertions 2026-05-09 05:01:16 +01:00
Shakker
c4d05b0dfc test: tighten messaging plugin array assertions 2026-05-09 05:00:33 +01:00
Peter Steinberger
c83a40e474 test: tighten mock voice provider timestamps 2026-05-09 04:58:41 +01:00
Shakker
92d7ab6845 test: tighten channel empty array assertions 2026-05-09 04:58:00 +01:00
Peter Steinberger
9d94e6f847 test: tighten lifecycle nack assertion 2026-05-09 04:57:02 +01:00
Peter Steinberger
0056f84e8b test: tighten native bridge cleanup assertion 2026-05-09 04:55:29 +01:00
Shakker
84c4a4fc5b test: tighten provider empty array assertions 2026-05-09 04:55:18 +01:00
Andi Liao
21d758c644 fix(logging): redact http client secrets (#75033)
Summary:
- The branch expands shared logging redaction for quoted HTTP client secret and auth-header fields, adds redaction/error-chain regression tests, and adds an Unreleased changelog entry.
- Reproducibility: yes. at source level. Current main routes formatted Error.cause text through shared redaction, and the current default patterns do not match the quoted HTTP client secret/auth fields covered by this PR.

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

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

Prepared head SHA: fcd308be71
Review: https://github.com/openclaw/openclaw/pull/75033#issuecomment-4351803001

Co-authored-by: Andi Liao <liaoandi95@gmail.com>
2026-05-09 03:53:59 +00:00
Peter Steinberger
08a38dca08 test: tighten config custom theme assertion 2026-05-09 04:53:39 +01:00
Shakker
2ec43dce47 test: tighten plugin empty array assertions 2026-05-09 04:53:25 +01:00
Peter Steinberger
8d563f40ea test: tighten quick settings theme assertion 2026-05-09 04:52:22 +01:00
Peter Steinberger
1ddab3067c test: tighten grouped render listener assertion 2026-05-09 04:50:39 +01:00
Shakker
5206f40104 test: tighten release empty array assertions 2026-05-09 04:50:34 +01:00
Peter Steinberger
877b860093 test: tighten custom theme fetch assertion 2026-05-09 04:48:56 +01:00
Shakker
ef2be8a982 test: tighten script empty array assertions 2026-05-09 04:48:47 +01:00
Peter Steinberger
497ec02242 test: tighten config form element helper 2026-05-09 04:47:30 +01:00
loongfay
c9f451996a feat(yuanbao) update yuanbao channel plugin npm version (#79620)
* feat(yuanbao) update yuanbao channel plugin npm version

* feat: update yuanbao channel plugin npm version to 2.13.0 (#79620) (thanks @loongfay)

---------

Co-authored-by: loongzhao <loongzhao@tencent.com>
Co-authored-by: sliverp <870080352@qq.com>
2026-05-09 11:47:06 +08:00
Shakker
80a2b4471e test: tighten media empty array assertions 2026-05-09 04:46:49 +01:00
Peter Steinberger
29560c49e0 test: tighten memory remote http mode assertion 2026-05-09 04:46:20 +01:00
Shakker
86a54caee2 test: tighten codex app empty array assertions 2026-05-09 04:45:12 +01:00
Peter Steinberger
696eb6cf35 test: tighten qmd embed lock assertion 2026-05-09 04:44:37 +01:00
Shakker
11f9383f8a test: tighten teams empty array assertions 2026-05-09 04:43:24 +01:00
Peter Steinberger
55b8451ea0 test: tighten dreaming content hash assertions 2026-05-09 04:42:37 +01:00
Shakker
714f3647e5 test: tighten discord empty array assertions 2026-05-09 04:41:43 +01:00
Peter Steinberger
07234384fc test: tighten slack qa artifact assertion 2026-05-09 04:40:45 +01:00
Shakker
c2f6bb0e71 test: tighten voice call empty array assertions 2026-05-09 04:40:00 +01:00
Peter Steinberger
9dbbd9b5d4 test: tighten feishu client http assertion 2026-05-09 04:39:10 +01:00
Shakker
3d1e349e7f test: tighten channel empty array assertions 2026-05-09 04:38:48 +01:00
Peter Steinberger
1d7fbc94c6 test: tighten feishu setup entry assertion 2026-05-09 04:37:59 +01:00
Ayaan Zaidi
7a2cc4b8d6 fix(telegram): stop DM topic threadless fallback (#78575) (thanks @tmimmanuel) 2026-05-09 09:07:42 +05:30
Shakker
3c3e0e7f9b test: tighten ui chat empty array assertions 2026-05-09 04:37:23 +01:00
Peter Steinberger
dc73d1baa1 test: tighten discord voice command assertion 2026-05-09 04:36:54 +01:00
Peter Steinberger
d9c6f7efec test: tighten discord presence helper assertion 2026-05-09 04:35:57 +01:00
Shakker
c36c7e9b80 test: tighten ui empty array assertions 2026-05-09 04:35:45 +01:00
Peter Steinberger
9db7a62c70 test: tighten memory cli sync assertion 2026-05-09 04:34:54 +01:00
Shakker
81758c497c test: tighten boundary empty array assertions 2026-05-09 04:34:10 +01:00
Peter Steinberger
50ba48c1fd test: tighten memory search timing assertion 2026-05-09 04:32:39 +01:00
Shakker
3cc2c28f0e test: tighten app session empty assertions 2026-05-09 04:32:14 +01:00
Peter Steinberger
97b32e8271 test: tighten google meet cli gateway assertion 2026-05-09 04:31:15 +01:00
Shakker
67e1f1a6b2 test: tighten plugin config empty assertions 2026-05-09 04:30:16 +01:00
Peter Steinberger
535d70c202 test: tighten twitch setup validation assertions 2026-05-09 04:29:14 +01:00
Shakker
c6faba0713 test: tighten browser empty payload assertions 2026-05-09 04:28:18 +01:00
Peter Steinberger
d8daa71666 test: tighten brave response duration assertion 2026-05-09 04:28:07 +01:00
Peter Steinberger
9ae2abf100 test: tighten google meet oauth expiry assertion 2026-05-09 04:27:06 +01:00
Peter Steinberger
d0a41b1041 test: tighten tlon upload body assertions 2026-05-09 04:25:54 +01:00
Shakker
7d4f76fa5e test: tighten matrix empty state assertions 2026-05-09 04:25:34 +01:00
Peter Steinberger
7b6307ef7f test: tighten xai transcription error assertion 2026-05-09 04:24:51 +01:00
Shakker
880a542944 test: tighten channel plugin empty assertions 2026-05-09 04:24:16 +01:00
Peter Steinberger
1dd05923d6 test: tighten nextcloud talk status timestamp assertion 2026-05-09 04:23:54 +01:00
Peter Steinberger
2bdb774726 test: tighten tokenjuice middleware assertion 2026-05-09 04:22:45 +01:00
Shakker
9757a62397 test: tighten provider empty payload assertions 2026-05-09 04:22:31 +01:00
Peter Steinberger
2d10afa6d7 test: tighten talkback consult signal assertions 2026-05-09 04:21:30 +01:00
Peter Steinberger
31e1d2e701 test: tighten audio pin dns request assertion 2026-05-09 04:20:03 +01:00
Shakker
3a654fd5eb test: tighten ui empty form assertions 2026-05-09 04:19:22 +01:00
Peter Steinberger
068bbf0a17 test: tighten ssrf dispatcher lookup assertion 2026-05-09 04:19:01 +01:00
Shakker
bcec18d38b test: tighten helper empty object assertions 2026-05-09 04:18:03 +01:00
Peter Steinberger
6dea4f5421 test: tighten provider validation assertion 2026-05-09 04:17:22 +01:00
Shakker
be3fd09ae0 test: tighten cron empty state assertions 2026-05-09 04:16:38 +01:00
Peter Steinberger
2a70264b83 test: tighten plugin lookup metrics assertions 2026-05-09 04:16:23 +01:00
Peter Steinberger
b2507b9a79 test: tighten plugin cli node runtime assertion 2026-05-09 04:15:28 +01:00
Josh Avant
b30ead9ca8 fix: hide subagent announce handoff prompts (#79618)
* fix: hide subagent announce handoff prompts

* chore: update subagent announce changelog entry
2026-05-08 22:15:01 -05:00
Peter Steinberger
1c2a0b4b89 test: tighten plugin cleanup timeout assertion 2026-05-09 04:14:35 +01:00
Shakker
2a272aa4a8 test: tighten shared empty object assertions 2026-05-09 04:13:56 +01:00
Peter Steinberger
d9f0ffc424 test: tighten proxy lifecycle assertions 2026-05-09 04:13:42 +01:00
Peter Steinberger
067dda2f26 test: tighten web push subscription assertion 2026-05-09 04:12:46 +01:00
Shakker
dcf3c851f0 test: tighten config snapshot empty assertions 2026-05-09 04:11:57 +01:00
Peter Steinberger
c5a3ed698d test: tighten global hook runner assertion 2026-05-09 04:11:54 +01:00
Shakker
fa83925fab test: tighten plugin empty state assertions 2026-05-09 04:10:32 +01:00
Peter Steinberger
5720aa08d2 test: tighten minimax image endpoint assertion 2026-05-09 04:10:28 +01:00
Peter Steinberger
441e1b2930 test: tighten minimax music header assertion 2026-05-09 04:09:30 +01:00
Shakker
3076da5e31 test: tighten plugin empty result assertions 2026-05-09 04:09:00 +01:00
Peter Steinberger
dc36430df3 test: tighten mattermost retry delay assertion 2026-05-09 04:08:32 +01:00
Peter Steinberger
594abbd44b test: tighten plugin loader transform assertions 2026-05-09 04:07:17 +01:00
Shakker
73f6344906 test: tighten gateway empty result assertions 2026-05-09 04:07:06 +01:00
Peter Steinberger
71a4c29d51 test: tighten sdk alias runtime assertion 2026-05-09 04:06:16 +01:00
Peter Steinberger
5bec7022c7 test: tighten plugin loader hook assertion 2026-05-09 04:05:24 +01:00
Peter Steinberger
1c19ce4e1b test: tighten trajectory recorder assertion 2026-05-09 04:04:38 +01:00
Peter Steinberger
e110b09b9f test: tighten temp home directory assertion 2026-05-09 04:03:50 +01:00
Shakker
7442355088 test: tighten config empty map assertions 2026-05-09 04:03:34 +01:00
Peter Steinberger
97757dd324 test: tighten fs-safe directory assertion 2026-05-09 04:03:07 +01:00
Peter Steinberger
8562aa8ab2 test: tighten cron task cleanup assertion 2026-05-09 04:02:22 +01:00
Peter Steinberger
83c238d6da test: tighten gateway lock helper assertion 2026-05-09 04:01:33 +01:00
Shakker
cf71412a35 test: tighten config empty object assertions 2026-05-09 04:01:03 +01:00
Peter Steinberger
3ba8c2cd52 test: tighten install target directory assertion 2026-05-09 04:00:42 +01:00
Peter Steinberger
08076208cd test: tighten timer delay callback assertion 2026-05-09 03:59:47 +01:00
Shakker
1b60d4f761 test: tighten command config cleanup assertions 2026-05-09 03:59:05 +01:00
Peter Steinberger
fa04bb9175 test: tighten cli respawn bridge assertion 2026-05-09 03:57:45 +01:00
Ayaan Zaidi
b66cc66440 fix(telegram): share bot api throttler 2026-05-09 08:27:39 +05:30
Shakker
a9d168ca23 test: tighten command empty result assertions 2026-05-09 03:57:18 +01:00
Peter Steinberger
45d67b98d1 test: tighten compile cache bridge assertion 2026-05-09 03:56:07 +01:00
Omar Shahine
81e0a1a99b feat(imessage): inbound catchup (cursor + replay loop + monitor wiring) (#79387)
Closes #78649. Adds opt-in inbound iMessage catchup that recovers messages landing in chat.db while the gateway is offline (crash, restart, mac sleep). Mirrors the design of the retired BlueBubbles catchup, adapted for the imsg JSON-RPC chats.list + messages.history fetch path.

- Schema: new channels.imessage.catchup block with enabled / maxAgeMinutes (1..720) / perRunLimit (1..500) / firstRunLookbackMinutes (1..720) / maxFailureRetries (1..1000). Disabled by default — opt-in.
- Cursor + replay loop (extensions/imessage/src/monitor/catchup.ts): per-account state under <openclawStateDir>/imessage/catchup/. Walks rows oldest-first, advances on success/give-up, holds at failed.rowid - 1 when a failure is below maxFailureRetries (cannot leapfrog held failures even when later rows in the same batch succeed). Watermark floor for parse-rejected rows.
- Bridge (extensions/imessage/src/monitor/catchup-bridge.ts): live chats.list + per-chat messages.history fetch adapter; dispatch adapter routes through the live handleMessageNow path so allowlists / group policy / dedupe / echo cache behave identically on replayed and live messages. Watermark clamped to last dispatched rowid when the cap truncates.
- Monitor wiring (extensions/imessage/src/monitor/monitor-provider.ts): catchup runs once between watch.subscribe and the live dispatch loop when enabled. Bypasses the inbound debouncer for serial per-row dispatch.
- Echo-cache TTL bumped 2 min → 12 h so own outbound rows from before a gap are not re-fed as inbound on replay.
- Generated bundled-channel-config-metadata.generated.ts so the runtime AJV schema accepts the new catchup block.
- Docs: new "Catching up after gateway downtime" section + BlueBubbles migration parity update.

Tests: 322/322 in extensions/imessage/, including 5 regression tests covering the cursor-leapfrog, parse-rejected stall, watermark vs held failure, and cap-truncation-cursor-floor edge cases that codex (gpt-5.4) and clawsweeper (gpt-5.5) found during review. Live-tested end-to-end against the running gateway: replayed=1 fetchedCount=1, agent reply observed, cursor persisted at the test row's exact rowid.

Co-authored-by: Omar Shahine <10343873+omarshahine@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 22:55:59 -04:00
Shakker
8989d0a777 test: tighten doctor empty config assertions 2026-05-09 03:55:42 +01:00
Peter Steinberger
c9f3b099b2 test: tighten task maintenance recovery timestamp assertion 2026-05-09 03:54:24 +01:00
Shakker
561df3fe03 test: tighten model picker empty assertions 2026-05-09 03:54:12 +01:00
Peter Steinberger
21af67f9a9 test: tighten detached task warning timing assertion 2026-05-09 03:52:23 +01:00
Peter Steinberger
00a44b08ed fix(gateway): preserve active agent dedupe retries 2026-05-08 22:52:17 -04:00
Gabriel Piss
972f9db1d2 test(gateway): strengthen dedupe eviction regression tests and add changelog 2026-05-08 22:52:17 -04:00
Gabriel Piss
da03269f6d fix(gateway): align dedupe eviction with entry timestamp 2026-05-08 22:52:17 -04:00
Shakker
11e6c66004 test: tighten hook empty result assertions 2026-05-09 03:52:06 +01:00
Shakker
48bba2df3b test: tighten acp empty response assertions 2026-05-09 03:50:30 +01:00
Peter Steinberger
03c8eb730b test: tighten task cancellation timestamp assertions 2026-05-09 03:50:01 +01:00
Shakker
3bbee2255b test: tighten agent overlay empty assertions 2026-05-09 03:48:28 +01:00
Peter Steinberger
0048f95667 test: tighten skill workshop hook assertions 2026-05-09 03:48:08 +01:00
Peter Steinberger
f94dc2cbb0 test: tighten media provider registry assertions 2026-05-09 03:46:43 +01:00
Shakker
8b20bc2f95 test: tighten agent empty config assertions 2026-05-09 03:46:35 +01:00
Peter Steinberger
ddde7900d8 test: tighten opencode media assertions 2026-05-09 03:45:24 +01:00
Shakker
cca2686f45 test: tighten auth identity empty assertions 2026-05-09 03:44:29 +01:00
Peter Steinberger
35fc60e097 test: tighten opencode go media assertions 2026-05-09 03:44:09 +01:00
Shakker
46ab4f139b test: tighten runner tool argument assertions 2026-05-09 03:42:56 +01:00
Peter Steinberger
2cd25ea27e test: tighten media load callback assertions 2026-05-09 03:42:46 +01:00
Peter Steinberger
f824271e77 test: tighten minimax video fetch assertions 2026-05-09 03:41:21 +01:00
Shakker
9534575134 test: tighten gemini schema cleanup assertions 2026-05-09 03:39:58 +01:00
Peter Steinberger
f8e2a2ff63 test: tighten boundary failure timing assertion 2026-05-09 03:39:47 +01:00
Peter Steinberger
4cdb9dfe8b test: tighten openrouter video fetch assertions 2026-05-09 03:38:14 +01:00
Shakker
eafc4230d6 test: tighten agent empty result assertions 2026-05-09 03:38:10 +01:00
Peter Steinberger
ffe72ffbb9 test: tighten test state payload assertions 2026-05-09 03:36:42 +01:00
Shakker
c414863505 test: tighten tool argument fallback assertions 2026-05-09 03:36:22 +01:00
Peter Steinberger
4f43026db6 test: tighten extension batch metric assertions 2026-05-09 03:35:35 +01:00
Shakker
02635d9e3e test: tighten agent tool schema assertions 2026-05-09 03:34:32 +01:00
Peter Steinberger
0a173bb362 test: tighten android live string assertion 2026-05-09 03:33:02 +01:00
Shakker
ba30f7c0ed test: tighten plugin runtime lookup assertions 2026-05-09 03:32:25 +01:00
Peter Steinberger
ac18768c19 test: tighten browser download path assertion 2026-05-09 03:31:54 +01:00
Peter Steinberger
2083d25e31 test: tighten core primitive assertions 2026-05-09 03:30:40 +01:00
Shakker
3d52a2962e test: tighten channel plugin discovery assertion 2026-05-09 03:29:49 +01:00
Peter Steinberger
d2c1f94234 test: tighten remaining object assertions 2026-05-09 03:28:29 +01:00
Shakker
c547427ca7 test: tighten release metadata guard assertion 2026-05-09 03:26:23 +01:00
Shakker
2f6047a16f test: tighten config schema rejection assertions 2026-05-09 03:26:23 +01:00
Peter Steinberger
e855091a58 test: tighten discord monitor object assertions 2026-05-09 03:23:12 +01:00
Shakker
7b660730e6 test: tighten sdk reconnect assertion 2026-05-09 03:20:35 +01:00
Peter Steinberger
ff2dc79fe7 fix: canonicalize gemini onboarding model keys 2026-05-09 03:19:57 +01:00
Peter Steinberger
2f9a9c6b91 test: tighten config helper object assertions 2026-05-09 03:11:58 +01:00
Peter Steinberger
06625e87df test: tighten doctor storage assertion 2026-05-09 03:10:46 +01:00
Peter Steinberger
c131865944 test: tighten bundled plugin schema assertion 2026-05-09 03:09:33 +01:00
Peter Steinberger
bfe9d5d224 test: tighten clawhub docs schema assertion 2026-05-09 03:07:57 +01:00
Peter Steinberger
b3c06e8d79 revert: remove oc-path implementation 2026-05-09 03:07:12 +01:00
Peter Steinberger
9c8bd022aa revert: remove oc-path workspace substrate 2026-05-09 03:07:12 +01:00
Peter Steinberger
a6dee24c3f test: tighten qa channel context assertion 2026-05-09 03:06:42 +01:00
Peter Steinberger
31ffaf0544 test: tighten respawn plan assertion 2026-05-09 03:05:30 +01:00
Peter Steinberger
25bfe29024 test: tighten core helper object assertions 2026-05-09 03:04:29 +01:00
Peter Steinberger
af5eca9371 test: tighten memory wiki schema assertion 2026-05-09 03:02:03 +01:00
Peter Steinberger
6f575481e7 test: tighten qmd models absence assertion 2026-05-09 02:59:24 +01:00
Shakker
02e60e293f test: tighten memory cleanup assertions 2026-05-09 02:58:05 +01:00
Peter Steinberger
4fe43b9eaf test: tighten memory wiki absence assertion 2026-05-09 02:57:13 +01:00
Shakker
20a2ac3e5d test: tighten extension cleanup assertions 2026-05-09 02:56:17 +01:00
Peter Steinberger
b9bd578d7c test: tighten msteams feedback absence assertion 2026-05-09 02:56:04 +01:00
Peter Steinberger
880c094407 fix: preserve copilot gpt-5.5 fallback metadata 2026-05-08 21:55:18 -04:00
Eduardo Piva
0a911524f2 chore(changelog): collapse github-copilot dynamic-discovery entries
Galin asked for shorter changelog entries — collapse the 2 long
github-copilot bullets (one per code change) into a single one-line
entry that points at the runtime behavior. The PR body retains the
full mapping/fallback/header detail.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 21:55:18 -04:00
Eduardo Piva
ed2a179d3e docs(github-copilot): note live catalog refresh + discovery opt-out
Add an accordion under the Built-in provider tab describing the runtime
catalog refresh from the Copilot `/models` endpoint and the
`plugins.entries.github-copilot.config.discovery.enabled = false` opt-out
for offline / air-gapped scenarios. Pairs with the
`fetchCopilotModelCatalog` change so users know what the new behavior
is and how to disable it if needed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 21:55:18 -04:00
Eduardo Piva
75405f64d0 github-copilot: live catalog discovery via /models + add gpt-5.5
The plugin's `catalog.run` hook already exchanged a GitHub OAuth token
for a short-lived Copilot API token and resolved the per-account baseUrl,
but it returned `models: []` and the bundled openclaw runtime relied
entirely on the static manifest catalog. That meant:

- Static `contextWindow` values were a conservative 128k for every
  model, far below reality (gpt-5.4/5.5 are 400k, claude-opus-4.6/4.7
  internal variants are 1M, claude-sonnet-4 is 200k, etc.).
- Newly published Copilot models (gpt-5.5, gpt-5.1*, gemini-3-pro-preview,
  the claude-opus-*-1m internal variants, etc.) didn't appear at all
  until the manifest was patched.
- Per-account entitlement was invisible — every user saw the same
  hardcoded 22-model list regardless of plan.

Wire it up:

- Add `fetchCopilotModelCatalog` in `extensions/github-copilot/models.ts`.
  Calls `${baseUrl}/models` with the resolved Copilot API token and the
  same Editor-Version / Copilot-Integration-Id headers used elsewhere in
  the plugin. Maps each entry to a `ModelDefinitionConfig`:
  - `contextWindow` ← `capabilities.limits.max_context_window_tokens`
  - `maxTokens`     ← `capabilities.limits.max_output_tokens`
  - `input`         ← `["text", "image"]` if `supports.vision`, else `["text"]`
  - `reasoning`     ← `Array.isArray(supports.reasoning_effort) && supports.reasoning_effort.length > 0`
  - `api`           ← `anthropic-messages` for Anthropic vendor or claude*
                      ids; otherwise `openai-responses`
  Filters out non-chat objects (embeddings) and internal routers
  (`accounts/...` ids). Dedupes by id. 10s default timeout.

- Update the `catalog.run` hook in `extensions/github-copilot/index.ts`
  to call the new function after token-exchange and return the live
  results. On any HTTP/parse failure it falls back to `models: []`,
  which preserves the static manifest catalog as the visible fallback —
  no behavior regression for users with `discovery.enabled: false` or
  in offline scenarios.

- Bump `modelCatalog.discovery."github-copilot"` from `"static"` to
  `"refreshable"` in `openclaw.plugin.json` so the catalog hook is
  actually invoked at runtime. Without this the discovery infrastructure
  treats the provider as static-only and never calls `catalog.run`.

- Add `gpt-5.5` to the static manifest catalog and `DEFAULT_MODEL_IDS`
  with the correct values from the API (`contextWindow: 400000`,
  `maxTokens: 128000`, `reasoning: true`, multimodal). This means users
  on `discovery.enabled: false` still get gpt-5.5 visible without
  needing to override `models.providers.github-copilot.models` in their
  config.

Tests added (5, all passing alongside the existing 24):

- `fetchCopilotModelCatalog` maps a representative `/models` response
  (chat models incl. an internal 1M-context Anthropic variant, a router,
  an embedding) to the right `ModelDefinitionConfig` shape with real
  context windows.
- baseUrl trailing slash is normalized.
- Duplicate ids in the API response are deduped (first wins).
- Non-2xx HTTP raises so the caller can fall back to the static catalog.
- Empty token / baseUrl reject synchronously without calling fetch.

Targeted run: `pnpm test extensions/github-copilot/models.test.ts` →
29/29 pass. `pnpm exec oxfmt --check extensions/github-copilot/` clean.
`pnpm tsgo:core` clean.

Real-world proof:

Built locally and dropped the resulting tarball into a downstream
container with `gh auth login --hostname github.com` (Copilot
subscription on the linked account). Before this change,
`openclaw models list --provider github-copilot` returned the 22-entry
static catalog with every entry showing 128k context. After this change,
the same command (with `--refresh`) returns 30 entries with API-accurate
context windows including the new gpt-5.1 family, the claude-opus-*-1m
variants, and the corrected `gemini-3*-preview` ids.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 21:55:18 -04:00
Peter Steinberger
8111ae40c0 test: tighten qqbot symlink assertion 2026-05-09 02:55:01 +01:00
Peter Steinberger
6eddcb8c22 test: tighten cli runner absence assertion 2026-05-09 02:53:53 +01:00
Shakker
b5a66a04aa test: tighten cli runner cleanup assertion 2026-05-09 02:53:43 +01:00
Shakker
50898c4a72 test: tighten backup camera cleanup assertions 2026-05-09 02:51:16 +01:00
Peter Steinberger
e8049fec1c test: tighten backup archive absence assertion 2026-05-09 02:50:35 +01:00
Shakker
ecc7e3c7b5 test: tighten auto reply cleanup assertions 2026-05-09 02:49:41 +01:00
Peter Steinberger
4d8e0bcecc test: tighten session lock cleanup assertion 2026-05-09 02:49:38 +01:00
Peter Steinberger
da0e949d78 test: tighten archive json error assertion 2026-05-09 02:48:38 +01:00
Shakker
59f75e793c test: update cli guidance assertions 2026-05-09 02:47:46 +01:00
Peter Steinberger
05168dd00d test: tighten install source cleanup assertion 2026-05-09 02:47:30 +01:00
Peter Steinberger
55439d81a1 test: tighten update startup absence assertion 2026-05-09 02:46:28 +01:00
Peter Steinberger
0aa7633f5c test: tighten state dir cleanup assertions 2026-05-09 02:45:30 +01:00
Shakker
2f50bb71ef test: tighten session lock absence assertion 2026-05-09 02:44:56 +01:00
Peter Steinberger
65e1cfb773 test: tighten temp home cleanup assertion 2026-05-09 02:44:36 +01:00
Peter Steinberger
065ca2fe25 test: tighten test instance cleanup assertion 2026-05-09 02:43:43 +01:00
Peter Steinberger
c958716d10 test: dedupe browser download absence assertions 2026-05-09 02:42:52 +01:00
Peter Steinberger
68d222456f test: dedupe memory reindex absence assertions 2026-05-09 02:41:51 +01:00
Peter Steinberger
37ffc96b60 test: dedupe qa lab file absence assertions 2026-05-09 02:40:49 +01:00
Peter Steinberger
72d811f39f test: dedupe mantis video absence assertions 2026-05-09 02:39:47 +01:00
Peter Steinberger
5e055e8887 test: dedupe signal download absence assertions 2026-05-09 02:38:50 +01:00
Peter Steinberger
88aeca5e62 test: dedupe oauth lock absence assertions 2026-05-09 02:37:47 +01:00
Peter Steinberger
c23ada75ce test: dedupe sandbox scp absence assertions 2026-05-09 02:36:55 +01:00
Peter Steinberger
08f760ea27 test: dedupe config recovery absence assertions 2026-05-09 02:35:57 +01:00
Peter Steinberger
aa6602a8fc test: dedupe cron store absence assertions 2026-05-09 02:34:48 +01:00
Peter Steinberger
ed3ce0032c test: dedupe managed image absence assertions 2026-05-09 02:32:42 +01:00
Peter Steinberger
8859b2b2ed test: dedupe restart sentinel absence assertions 2026-05-09 02:30:37 +01:00
Peter Steinberger
f662eda57d test: dedupe run-node absence assertions 2026-05-09 02:28:59 +01:00
Peter Steinberger
50ec12ff5c test: dedupe test state absence assertions 2026-05-09 02:26:56 +01:00
Shakker
6369349484 test: update gateway auth assertions 2026-05-09 02:26:32 +01:00
Peter Steinberger
4c06dee4cd test: dedupe runtime postbuild absence assertions 2026-05-09 02:25:26 +01:00
Vincent Koc
e45b9d7a74 fix(cli): clarify remaining required options 2026-05-09 09:24:59 +08:00
Peter Steinberger
737d5253e5 test: dedupe qa matrix absence assertions 2026-05-09 02:24:01 +01:00
Peter Steinberger
e8f798e506 test: dedupe clawhub cleanup absence assertions 2026-05-09 02:22:24 +01:00
Peter Steinberger
0a52fd17a3 test: dedupe session disk budget absence assertions 2026-05-09 02:21:03 +01:00
Vincent Koc
ad943ec30c fix(cli): guide auth and gateway setup errors 2026-05-09 09:20:16 +08:00
Peter Steinberger
4775b01031 test: dedupe gateway media absence assertions 2026-05-09 02:19:29 +01:00
Peter Steinberger
d134e0669a test: dedupe session memory absence assertions 2026-05-09 02:18:03 +01:00
Kevin Lin
d922edd861 Fix Codex plugin migration selection UX (#79160)
* fix: prompt for codex plugin migration selection

* test: use shared ANSI stripping in migrate output test

* fix(codex): guard migrated plugins with guardian mode

* fix(codex): keep plugin migration interactive after skill skip

* fix(codex): keep migration plugins on default app server

* fix(codex): exit cleanly when migration selection is empty

* fix(codex): remove migration test non-null assertions

* test(codex): drop auth profile migration fixture
2026-05-08 18:17:41 -07:00
Peter Steinberger
2efc8e2ab0 test: dedupe trajectory cleanup absence assertions 2026-05-09 02:16:42 +01:00
Shakker
bf47202182 test: relax channels resolve command hint assertion 2026-05-09 02:15:42 +01:00
Peter Steinberger
e8e4648bbf test: dedupe backup rotation absence assertions 2026-05-09 02:14:46 +01:00
Peter Steinberger
ed1be9553a test: dedupe media store absence assertions 2026-05-09 02:13:16 +01:00
Peter Steinberger
74a644b340 test: dedupe sandbox mutation absence assertions 2026-05-09 02:11:54 +01:00
Vincent Koc
56916bc8bf fix(cli): guide migration and setup errors 2026-05-09 09:11:19 +08:00
Peter Steinberger
24662e9f67 test: dedupe sandbox registry absence assertions 2026-05-09 02:10:21 +01:00
Kevin Lin
a7bfa44c35 docs: document codex harness model availability (#79582) 2026-05-08 18:10:15 -07:00
Peter Steinberger
3435e18896 test: dedupe plugin dependency cleanup absence assertions 2026-05-09 02:08:49 +01:00
Peter Steinberger
146ca9519e test: dedupe openshell mirror absence assertions 2026-05-09 02:07:21 +01:00
Peter Steinberger
995d2af036 test: dedupe session lock absence assertions 2026-05-09 02:05:49 +01:00
Peter Steinberger
ec49e28c04 test: dedupe session pruning absence assertions 2026-05-09 02:03:58 +01:00
Omar Shahine
85ebb4c471 feat(imessage): per-group systemPrompt (parity with other channels) (#79383)
Merged via squash.

Prepared head SHA: 2eecd01ed8
Co-authored-by: omarshahine <10343873+omarshahine@users.noreply.github.com>
Co-authored-by: omarshahine <10343873+omarshahine@users.noreply.github.com>
Reviewed-by: @omarshahine
2026-05-08 21:02:39 -04:00
Peter Steinberger
30e870e424 test: tighten e2e absence assertions 2026-05-09 02:02:28 +01:00
Peter Steinberger
89a435b1e8 test: tighten sandbox media absence assertions 2026-05-09 02:00:34 +01:00
Peter Steinberger
a0dfd83878 test: tighten onboard auth absence assertions 2026-05-09 01:59:19 +01:00
Peter Steinberger
9d4c4a7f15 test: tighten plugin absence assertions 2026-05-09 01:57:58 +01:00
Peter Steinberger
18b3581ac9 test: tighten session store queued error assertions 2026-05-09 01:55:03 +01:00
Peter Steinberger
a0b970f849 test: tighten trajectory export existing dir assertion 2026-05-09 01:53:45 +01:00
Peter Steinberger
7fa75bd6ce test: tighten npm managed root malformed manifest assertion 2026-05-09 01:52:11 +01:00
Peter Steinberger
0abb3c17fb test: tighten model config default write assertion 2026-05-09 01:50:42 +01:00
Peter Steinberger
b28e29c4f3 test: tighten browser cdp transport failure assertions 2026-05-09 01:49:26 +01:00
Peter Steinberger
c0e6475a25 test: tighten tsdown cleanup absence assertions 2026-05-09 01:47:19 +01:00
Peter Steinberger
f5e053e485 test: tighten openshell boundary assertions 2026-05-09 01:46:12 +01:00
Peter Steinberger
387846f1c7 test: tighten browser proxy file absence assertion 2026-05-09 01:44:15 +01:00
Peter Steinberger
bf273c451a test: tighten inworld tts failure assertion 2026-05-09 01:42:51 +01:00
Solomon Neas
b81414be45 fix: expose safe restart deferral bypass (#78658)
Expose the existing safe-restart skipDeferral escape hatch through gateway RPC and the daemon CLI, document the flag, and add restart/CLI regression coverage.

Also keep CLI failure output off the cold bootstrap graph and align CLI guidance expectations needed by current CI.

Co-authored-by: Solomon Neas <solomonneas@users.noreply.github.com>
2026-05-08 20:42:36 -04:00
Peter Steinberger
612e72ebbd test: tighten mattermost retry failure assertions 2026-05-09 01:41:35 +01:00
Peter Steinberger
15d33cba9c test: tighten discord proxy abort assertions 2026-05-09 01:40:15 +01:00
Peter Steinberger
9cb204bdc2 test: tighten googlechat auth redaction assertion 2026-05-09 01:38:46 +01:00
Peter Steinberger
f0b0988b04 test: assert stale cron render output 2026-05-09 01:37:33 +01:00
Peter Steinberger
b584cadd9d test: tighten imessage coalesce guard assertion 2026-05-09 01:36:18 +01:00
Peter Steinberger
c940c69edf test: tighten malformed include path assertion 2026-05-09 01:35:04 +01:00
Peter Steinberger
0ffd38564f test: tighten cli runner process cleanup assertion 2026-05-09 01:33:47 +01:00
Peter Steinberger
7674df0eb8 test: tighten nostr negative key assertions 2026-05-09 01:31:40 +01:00
Shakker
1751694b0e test: align command guidance assertions 2026-05-09 01:30:27 +01:00
Peter Steinberger
7e503bdbbb test: tighten ci changed scope injection assertion 2026-05-09 01:29:03 +01:00
Peter Steinberger
f9814cc7de test: tighten sdk alias missing-subpath assertion 2026-05-09 01:27:24 +01:00
Peter Steinberger
65b490c7cd test: tighten whatsapp channel guard assertion 2026-05-09 01:26:06 +01:00
Peter Steinberger
9883c31029 test: tighten agent defaults schema rejections 2026-05-09 01:24:43 +01:00
Peter Steinberger
4e3de3574f test: tighten proxy schema rejection 2026-05-09 01:22:45 +01:00
Peter Steinberger
f1c2baf5f7 test: tighten markdown table schema rejection 2026-05-09 01:21:24 +01:00
Peter Steinberger
92ffb4a86c test: tighten typing mode schema rejection 2026-05-09 01:20:18 +01:00
Shakker
ed11b64cbf test: remove active memory hard deadline timer 2026-05-09 01:19:29 +01:00
Peter Steinberger
fad580ff18 test: tighten cli parser error assertions 2026-05-09 01:18:56 +01:00
Shakker
41cf024776 test: clear acp abort timeout guard 2026-05-09 01:18:16 +01:00
Peter Steinberger
e3cc2c41ec test: replace native bridge throw-only assertions 2026-05-09 01:17:29 +01:00
Shakker
f5200eb466 test: clear acp delivery timeout guard 2026-05-09 01:17:15 +01:00
Shakker
2f415618b3 test: clear openai ws fallback timeout 2026-05-09 01:16:12 +01:00
Peter Steinberger
553d17618a test: tighten cli transcript session file assertion 2026-05-09 01:15:59 +01:00
Shakker
e2b2ebd86a test: clear fetch guard timeout sentinel 2026-05-09 01:14:34 +01:00
Peter Steinberger
917684dee8 test: simplify gateway live profile parsing 2026-05-09 01:14:13 +01:00
Shakker
b945680f7e test: clear feishu drive cleanup timers 2026-05-09 01:12:43 +01:00
Shakker
d857b83d5a test: clear feishu outbound cleanup timer 2026-05-09 01:11:48 +01:00
Vincent Koc
858a4471bd fix(cli): clarify operator command errors 2026-05-09 08:11:34 +08:00
Shakker
b2645c7354 test: clear feishu comment handler timer 2026-05-09 01:11:00 +01:00
Peter Steinberger
91eecba6e5 test: simplify openai live model parsing 2026-05-09 01:10:38 +01:00
Shakker
7e6771a6b0 test: clear feishu comment dispatcher timer 2026-05-09 01:09:54 +01:00
Peter Steinberger
7e733bedab test: simplify copilot live text extraction 2026-05-09 01:09:27 +01:00
Vincent Koc
05414e2ac3 fix(cli): explain plugin and secrets failures 2026-05-09 08:08:26 +08:00
Peter Steinberger
d47b64609c test: simplify xai live error messages 2026-05-09 01:08:12 +01:00
Shakker
c008c54f9e test: clear chat refresh macrotask timers 2026-05-09 01:07:27 +01:00
Shakker
cc027d49c3 test: clear refresh tab macrotask timers 2026-05-09 01:06:04 +01:00
Vincent Koc
d326694069 docs(changelog): note cli recovery copy 2026-05-09 08:05:06 +08:00
Vincent Koc
bb0332bfbf fix(cli): guide lookup misses 2026-05-09 08:05:06 +08:00
Vincent Koc
f09bb6d75c fix(cli): improve config recovery copy 2026-05-09 08:05:06 +08:00
Vincent Koc
938cc3628c fix(cli): guide common command errors 2026-05-09 08:05:06 +08:00
Vincent Koc
23d5e630cd fix(cli): add parser value examples 2026-05-09 08:05:05 +08:00
Vincent Koc
66113d6c15 docs(cli): sharpen root help copy 2026-05-09 08:05:05 +08:00
Vincent Koc
3500a0bffa fix(cli): improve guardrail messages 2026-05-09 08:05:05 +08:00
Vincent Koc
ebd59f1e01 fix(cli): clarify startup failures 2026-05-09 08:05:05 +08:00
Vincent Koc
f06b77c0d4 fix(cli): explain parser errors 2026-05-09 08:05:04 +08:00
Shakker
c0bad2eda5 test: clear node invoke connect timeout 2026-05-09 01:04:49 +01:00
Peter Steinberger
37611ef89a test: simplify openai ws summary extraction 2026-05-09 01:03:54 +01:00
Shakker
a24e76e9c7 test: clear gateway node hello timeout 2026-05-09 01:03:13 +01:00
Vincent Koc
a834175e01 chore(imessage): remove bluebubbles code comments 2026-05-09 08:03:02 +08:00
Peter Steinberger
6dfbee78e4 test: simplify launchd event parsing 2026-05-09 01:02:42 +01:00
Shakker
2157c2537f test: clear qa bus abort timeout guard 2026-05-09 01:02:10 +01:00
Shakker
c9e85fdbd6 test: clear ollama stream timeout guard 2026-05-09 01:01:04 +01:00
Shakker
105cc8d18a test: clear browser open tab timeout guard 2026-05-09 00:59:36 +01:00
Vincent Koc
fad6066926 changelog: split c6d4f1fab8 Discord/Gateway entry by area 2026-05-09 07:59:19 +08:00
Peter Steinberger
06f8093e68 test: simplify openshell failure message assembly 2026-05-09 00:58:46 +01:00
Shakker
4cbc723f3a test: clear sdk e2e timeout guards 2026-05-09 00:58:17 +01:00
Peter Steinberger
e3a3093fdb test: simplify cache live trace parsing 2026-05-09 00:57:28 +01:00
Shakker
5fe5c6484a test: clear plugin cleanup guard timer 2026-05-09 00:56:27 +01:00
Peter Steinberger
fc74dc5dec test: simplify pi runner session jsonl parsing 2026-05-09 00:56:03 +01:00
Shakker
8f856c1489 test: tighten session cost polling 2026-05-09 00:54:14 +01:00
Shakker
34649d3257 test: use vitest polling for session memory 2026-05-09 00:53:00 +01:00
Vincent Koc
6aa7e371e4 test(memory): avoid control-regex lint 2026-05-09 07:52:36 +08:00
Peter Steinberger
5377e952ca test: simplify nodes media path collection 2026-05-09 00:52:06 +01:00
Vincent Koc
3ba2ce6694 fix(plugins): avoid managed npm prefix on Windows
Fixes #78514.
2026-05-09 07:51:49 +08:00
Shakker
becfeb48b4 test: isolate launcher compile cache temp 2026-05-09 00:50:44 +01:00
Peter Steinberger
47099da937 test: simplify manual compaction text extraction 2026-05-09 00:49:06 +01:00
Peter Steinberger
93ba934620 test: simplify dispatch block text collection 2026-05-09 00:47:22 +01:00
Peter Steinberger
265a47d21e test: dedupe codex transcript mirror parsing 2026-05-09 00:45:27 +01:00
Nandana Dileep
5adbbaa3cb fix(scripts): avoid DEP0190 when spawning .cmd files on Windows
Use the shared Windows cmd.exe command-line builder for `.cmd` and `.bat` UI runner launches so Node.js v24 no longer sees `spawn(file, args, { shell: true })` and emits DEP0190.

The launcher keeps ordinary `.exe`/`.com` and non-Windows paths on direct argv spawning, while Windows command scripts now run through `cmd.exe /d /s /c` with `shell: false` and `windowsVerbatimArguments: true`.

Local and CI verification passed, including focused UI runner tests, build, check, Real behavior proof, and ClawSweeper gates.

Co-authored-by: Nandana Dileep <nandanadileep@users.noreply.github.com>
Co-authored-by: Brad Groux <3053586+BradGroux@users.noreply.github.com>
2026-05-08 18:45:20 -05:00
Vincent Koc
ccfbd96082 test(memory): normalize styled CLI status assertions 2026-05-09 07:44:13 +08:00
Peter Steinberger
f55fdc6ae5 test: simplify host hook context joining 2026-05-09 00:43:30 +01:00
Shakker
ffb83a57e5 test: gate run-node postbuild lock 2026-05-09 00:42:43 +01:00
Shakker
92884d0498 test: avoid json lock sleep 2026-05-09 00:41:20 +01:00
Vincent Koc
c6d4f1fab8 fix(runtime): preserve reviewed routing and transcript behavior (#79076)
* fix(runtime): preserve reviewed routing and transcript behavior

* docs(changelog): note runtime review fixes
2026-05-09 07:40:43 +08:00
Peter Steinberger
791e83419b test: simplify extension dependency import parsing 2026-05-09 00:38:53 +01:00
Shakker
b5eb9ea552 test: tighten qa lab server polling 2026-05-09 00:38:40 +01:00
Shakker
b96f936a76 test: tighten memory recall polling 2026-05-09 00:37:12 +01:00
Shakker
b1d584709f test: advance memory lock repair retry 2026-05-09 00:35:52 +01:00
Peter Steinberger
79d85bf514 test: simplify chat model provider lookup 2026-05-09 00:34:44 +01:00
Shakker
e5975ef859 test: advance session cost retry timers 2026-05-09 00:34:25 +01:00
Peter Steinberger
a1d288cbb7 test: simplify quick settings card collection 2026-05-09 00:33:23 +01:00
Shakker
57301d7624 test: set zalouser credential mtime explicitly 2026-05-09 00:31:52 +01:00
Peter Steinberger
2848f63e5a test: simplify followup prompt sections 2026-05-09 00:31:15 +01:00
Val Alexander
32bbd8e423 docs: consolidate Homebrew LaunchAgent changelog (#79554) 2026-05-08 18:31:09 -05:00
Peter Steinberger
7356517fbf test: dedupe directive tag transcript reads 2026-05-09 00:29:41 +01:00
Peter Steinberger
bb6c9d210d test: simplify session status text formatting 2026-05-09 00:27:55 +01:00
Peter Steinberger
b6423fbd32 test: dedupe chat inject transcript reads 2026-05-09 00:26:16 +01:00
Peter Steinberger
5d87f7b62d test: dedupe cli attempt transcript parsing 2026-05-09 00:24:54 +01:00
Peter Steinberger
71816a3fb2 test: simplify bash exec path normalization 2026-05-09 00:22:33 +01:00
Peter Steinberger
08ecf78412 test: simplify subagent reply text collection 2026-05-09 00:20:50 +01:00
Peter Steinberger
2cb18cbf53 test: simplify raw body prompt prefixing 2026-05-09 00:19:31 +01:00
Peter Steinberger
17c1ee1400 test: simplify plugin sdk export parsing 2026-05-09 00:18:09 +01:00
Peter Steinberger
de651aaadd test: simplify plugin tool argument parsing 2026-05-09 00:16:14 +01:00
Peter Steinberger
ac5acaeb8f test: simplify agent command path joining 2026-05-09 00:11:14 +01:00
Peter Steinberger
ff4d5541a2 test: simplify bash tools command splitting 2026-05-09 00:09:25 +01:00
Peter Steinberger
3dc4029189 test: clean up core test helpers 2026-05-09 00:08:07 +01:00
Peter Steinberger
f65418c57c test: simplify whatsapp setup entry splitting 2026-05-09 00:05:34 +01:00
Peter Steinberger
91c93156af test: simplify telegram callback data collection 2026-05-09 00:04:25 +01:00
Shakker
0617da1daa test: set dreaming mtime explicitly 2026-05-09 00:03:30 +01:00
Peter Steinberger
63b29b9ebf test: simplify twitch outbound chunk mock 2026-05-09 00:02:49 +01:00
Shakker
8e3848d215 test: wait for node pairing command visibility 2026-05-09 00:02:11 +01:00
Peter Steinberger
f7e9c315e4 test: simplify diffs viewer id extraction 2026-05-09 00:01:30 +01:00
Shakker
6e2b1d6366 test: use openresponses command wait 2026-05-09 00:00:51 +01:00
Shakker
6414405839 test: release models config write gate 2026-05-08 23:59:54 +01:00
Andy Ye
368c21e211 fix(daemon): include Homebrew in macOS service PATH
Summary:
- Document the canonical macOS LaunchAgent PATH including Apple Silicon Homebrew bin directories.
- Add service-audit regression coverage that flags stale macOS service PATHs missing Homebrew directories.
- Record the user-facing Gateway/macOS fix in the changelog.

Verification:
- Exact PR head 8aa19dde07 was approved, CLEAN, and MERGEABLE before merge.
- GitHub exact-head CI/check-docs/proof lanes were green with no failing or pending check runs.
- pnpm exec oxfmt --check --threads=1 CHANGELOG.md docs/gateway/doctor.md src/daemon/service-audit.test.ts src/daemon/service-env.ts src/daemon/service-env.test.ts src/commands/daemon-install-helpers.test.ts
- pnpm check:changelog-attributions
2026-05-08 17:59:46 -05:00
Shakker
83de0b689a test: release codex app extension init 2026-05-08 23:58:32 +01:00
Peter Steinberger
d415737bd7 test: simplify session thinking label collection 2026-05-08 23:57:51 +01:00
Shakker
07c9ad9dd9 test: rely on subagent resume signal 2026-05-08 23:56:44 +01:00
Peter Steinberger
42ae0fd99f test: simplify external plugin catalog id collection 2026-05-08 23:55:42 +01:00
Shakker
f1b42d542b test: release matrix sync poll deterministically 2026-05-08 23:54:33 +01:00
Peter Steinberger
9557fd1e23 test: simplify googlechat chunk word scan 2026-05-08 23:54:11 +01:00
Shakker
49e2f91335 test: gate qa character concurrency 2026-05-08 23:53:25 +01:00
Peter Steinberger
56fa80d334 test: simplify secret coverage path parsing 2026-05-08 23:52:54 +01:00
Shakker
0859e4aa52 test: advance msteams pending upload ttl 2026-05-08 23:51:38 +01:00
Peter Steinberger
6e9ed3efca test: simplify cron run log line collection 2026-05-08 23:51:11 +01:00
Shakker
3391dfecda test: drop acp relay rejection sleeps 2026-05-08 23:50:31 +01:00
Peter Steinberger
a33d994e3a test: simplify ci changed scope output parsing 2026-05-08 23:49:56 +01:00
Shakker
74868c808d test: release qa suite concurrency workers 2026-05-08 23:49:14 +01:00
Peter Steinberger
4be8fd5055 test: simplify health account id collection 2026-05-08 23:48:37 +01:00
AlexAlves87
41130a83d1 feat(ui): add SPA-side support for WebView2 native bridge (#69633)
Summary:
- Add the Control UI SPA-side WebView2 bridge for native Windows hosts.
- Route native `draft-text` messages through the existing chat draft path and send the `ready` handshake on bridge setup.
- Cover listener ordering, cleanup, malformed message handling, browser no-op behavior, and input-history reset.

Verification:
- Exact-head CI passed on c59bb4f5c8.
- Real behavior proof passed with Windows/WebView2 screen recording evidence.
- Maintainer review approved.
2026-05-08 17:48:00 -05:00
Peter Steinberger
e305c7a9b0 test: simplify ios team candidate parsing 2026-05-08 23:47:17 +01:00
Shakker
ee09a484ac test: await xai realtime events directly 2026-05-08 23:46:39 +01:00
Peter Steinberger
d510401bdc test: simplify channel setup account collectors 2026-05-08 23:45:45 +01:00
Shakker
1d835ad6ec test: advance feishu queue timers 2026-05-08 23:45:15 +01:00
Shakker
194753bc74 test: wait on block reply abort signal 2026-05-08 23:43:53 +01:00
Peter Steinberger
13910f9284 test: simplify channel registry helper projections 2026-05-08 23:43:39 +01:00
Peter Steinberger
359115f0d9 test: simplify docker setup log collectors 2026-05-08 23:42:28 +01:00
Shakker
3256316122 test: avoid media stream pending sleep 2026-05-08 23:42:22 +01:00
Peter Steinberger
617f2554d2 test: simplify config recovery collectors 2026-05-08 23:40:51 +01:00
Shakker
459e77e25a test: speed voice realtime consult timers 2026-05-08 23:40:38 +01:00
Peter Steinberger
40ac54adbb test: simplify committer path collection 2026-05-08 23:39:30 +01:00
Peter Steinberger
8b79b4b3de test: reuse precommit staged line parsing 2026-05-08 23:38:04 +01:00
Peter Steinberger
aff1f57a64 test: simplify embedding chunk diagnostics 2026-05-08 23:37:03 +01:00
Peter Steinberger
b4b4c7aab1 test: simplify live replay text collectors 2026-05-08 23:35:15 +01:00
Shakker
4726755f6a test: avoid live text helper temp arrays 2026-05-08 23:30:20 +01:00
Peter Steinberger
23341e5432 test: simplify oc path matched item collection 2026-05-08 23:29:41 +01:00
Peter Steinberger
5aa9095454 test: guard fallback disabled cooldown expiry 2026-05-08 23:26:04 +01:00
Shakker
f83037800d test: reuse sessions call counters 2026-05-08 23:24:02 +01:00
Shakker
4415c4e21e test: count qa lab events without filters 2026-05-08 23:22:38 +01:00
Peter Steinberger
d88f154045 test: simplify websocket manager close count 2026-05-08 23:22:04 +01:00
Shakker
64e731b5e8 test: avoid cooldown expiry sort allocation 2026-05-08 23:20:57 +01:00
Peter Steinberger
00d64a7148 test: simplify session compact line count 2026-05-08 23:20:25 +01:00
Shakker
5d335dd603 fix: pin fast-uri audit dependency 2026-05-08 23:19:34 +01:00
Peter Steinberger
1c8e58b4ff test: simplify slack final dispatch count 2026-05-08 23:17:36 +01:00
Peter Steinberger
3c131c8474 test: simplify loader duplicate counts 2026-05-08 23:15:30 +01:00
Peter Steinberger
4aac25a588 test: simplify memory wiki path collection 2026-05-08 23:13:32 +01:00
Peter Steinberger
019d7247cd test: simplify setup allowlist normalization 2026-05-08 23:11:09 +01:00
Peter Steinberger
f4d5f9985b test: simplify provider thinking level scans 2026-05-08 23:09:23 +01:00
Peter Steinberger
5104fd02c9 test: simplify matrix room state count 2026-05-08 23:06:56 +01:00
Peter Steinberger
05fb889efa test: simplify ollama warning count 2026-05-08 23:05:08 +01:00
Shakker
8cc9618bfa test: isolate session reset cleanup queues 2026-05-08 23:04:01 +01:00
Peter Steinberger
35363a279b test: simplify browser doctor warning ids 2026-05-08 23:03:18 +01:00
Peter Steinberger
4fb3bd845f test: simplify bootstrap cache hit count 2026-05-08 23:01:35 +01:00
Peter Steinberger
df1851b27d test: simplify export html specificity count 2026-05-08 22:59:57 +01:00
Peter Steinberger
91a6372897 test: simplify openresponses event type collection 2026-05-08 22:58:30 +01:00
Peter Steinberger
946419d105 test: simplify auto reply allowlist normalization 2026-05-08 22:56:59 +01:00
Peter Steinberger
0c0e2e6c8b test: simplify acp env key normalization 2026-05-08 22:54:57 +01:00
Peter Steinberger
3e56f86237 test: simplify doctor warning collection 2026-05-08 22:53:40 +01:00
Peter Steinberger
1968db9ddd test: simplify pi package missing scan 2026-05-08 22:52:04 +01:00
Peter Steinberger
3d5002f2db test: simplify role allowlist node counts 2026-05-08 22:50:37 +01:00
Peter Steinberger
672426eb50 test: simplify connected node collection 2026-05-08 22:49:12 +01:00
Peter Steinberger
5cb295926c test: simplify pairing read call counts 2026-05-08 22:47:51 +01:00
Peter Steinberger
dc062ee9b1 test: dedupe command builtin name checks 2026-05-08 22:46:44 +01:00
Peter Steinberger
10e425debe test: simplify cron event call counts 2026-05-08 22:45:16 +01:00
Peter Steinberger
cac418d0dd test: simplify query expansion duplicate count 2026-05-08 22:44:01 +01:00
Peter Steinberger
b07b21df66 test: simplify install package dir scans 2026-05-08 22:42:41 +01:00
Peter Steinberger
a232ac3783 test: simplify status reaction call scans 2026-05-08 22:40:30 +01:00
Peter Steinberger
d82cc7f702 test: simplify migration status counts 2026-05-08 22:38:24 +01:00
Peter Steinberger
07f6167cce test: simplify unit-fast forced diagnostics 2026-05-08 22:37:19 +01:00
Peter Steinberger
247fed1ca9 test: dedupe import boundary file checks 2026-05-08 22:35:47 +01:00
Peter Steinberger
3dfc4d85bf test: simplify safe-bin doc normalization 2026-05-08 22:34:43 +01:00
Peter Steinberger
b3b9d4a858 test: simplify abort transcript lookups 2026-05-08 22:32:45 +01:00
Peter Steinberger
1b9cfc86cd test: dedupe replay JSONL parsing 2026-05-08 22:30:52 +01:00
Peter Steinberger
db35bc7693 fix: normalize retired Gemini config keys 2026-05-08 22:29:02 +01:00
Peter Steinberger
17b1562c1e test: avoid filtered map assertion allocations 2026-05-08 22:23:52 +01:00
Peter Steinberger
aa34ce41a1 test: avoid single result filter assertions 2026-05-08 22:19:50 +01:00
Peter Steinberger
aa78d9eab9 test: avoid extension filter count helpers 2026-05-08 22:15:56 +01:00
Peter Steinberger
edfc5294cb test: avoid line count filter allocations 2026-05-08 22:13:46 +01:00
Tak Hoffman
2f26025085 fix(active-memory): allow active-memory to support custom recall tools (#77906)
* fix(active-memory): allow custom recall tools

* docs(active-memory): document custom recall tools

* docs(active-memory): note tools allowlist change

* fix(active-memory): constrain recall tool allowlist

* fix(active-memory): preserve lancedb recall defaults

* fix(active-memory): block non-memory recall tools

* fix(active-memory): satisfy bundled lint

* fix(active-memory): satisfy type-aware lint

* fix(tests): satisfy type-aware lint

* fix(tests): clear next type-aware lint batch

* fix(tests): clear lint and test type annotations

* docs(changelog): consolidate active memory entry

* docs(changelog): reclassify active memory tools entry
2026-05-08 16:12:48 -05:00
Peter Steinberger
2c7f2d3ac2 test: avoid extension count filter predicates 2026-05-08 22:11:01 +01:00
Peter Steinberger
27ddb6bea2 test: avoid core count filter predicates 2026-05-08 22:08:55 +01:00
Peter Steinberger
7188ab7f6b test: clear exact count filter assertions 2026-05-08 22:07:09 +01:00
Peter Steinberger
ce515dbf4d test: avoid misc count filter allocations 2026-05-08 22:05:41 +01:00
Peter Steinberger
cd7f733a99 test: avoid agent count filter allocations 2026-05-08 22:02:06 +01:00
Peter Steinberger
66232280b7 test: avoid loader count filter allocations 2026-05-08 22:00:29 +01:00
Peter Steinberger
7645824c9c test: avoid extension count filter allocations 2026-05-08 21:58:28 +01:00
Peter Steinberger
8543b38698 test: avoid infra count filter allocations 2026-05-08 21:56:52 +01:00
Peter Steinberger
9803a96adc test: avoid cli count filter allocations 2026-05-08 21:54:43 +01:00
Peter Steinberger
016c8c9968 test: avoid subagent count filter allocations 2026-05-08 21:53:22 +01:00
Peter Steinberger
25985ebb8e test: avoid sessions count filter allocations 2026-05-08 21:52:15 +01:00
Peter Steinberger
6d785f01e8 test: avoid diagnostic count filter allocations 2026-05-08 21:50:46 +01:00
Peter Steinberger
84c4e66288 test: avoid zero length filter assertions 2026-05-08 21:49:20 +01:00
Peter Steinberger
ed4d7bb94e test: clear remaining empty filter assertions 2026-05-08 21:47:38 +01:00
Peter Steinberger
66d2825841 test: avoid agent filter allocation assertions 2026-05-08 21:44:50 +01:00
Peter Steinberger
3653127e05 test: avoid core utility filter allocation assertions 2026-05-08 21:43:27 +01:00
Peter Steinberger
849f499e38 test: avoid telegram filter allocation assertions 2026-05-08 21:41:59 +01:00
Peter Steinberger
a0dd3ac65c test: avoid messaging filter allocation assertions 2026-05-08 21:40:05 +01:00
Peter Steinberger
aa8b233942 test: avoid command filter allocation assertions 2026-05-08 21:38:37 +01:00
Peter Steinberger
b2808ac712 test: avoid core filter allocation assertions 2026-05-08 21:37:19 +01:00
Peter Steinberger
c33d71c6b8 test: avoid extension filter allocation assertions 2026-05-08 21:35:49 +01:00
Peter Steinberger
a899f81921 test: avoid more filter allocation assertions 2026-05-08 21:33:48 +01:00
Peter Steinberger
70723b306d fix: canonicalize nested gemini catalog ids 2026-05-08 21:32:07 +01:00
Peter Steinberger
9bc8237f7b test: avoid filter allocation assertions 2026-05-08 21:26:50 +01:00
Peter Steinberger
c7a0a7af7b test: tighten compaction hook helper 2026-05-08 21:24:32 +01:00
Peter Steinberger
02ea672dd6 test: tighten sdk transport helper 2026-05-08 21:23:24 +01:00
Shakker
f49beec09a test: tighten compaction hook assertion 2026-05-08 21:22:34 +01:00
Peter Steinberger
32ec6c2ba7 test: tighten release tooling helpers 2026-05-08 21:22:04 +01:00
Shakker
34f515429a test: tighten plugin hook assertions 2026-05-08 21:21:54 +01:00
Shakker
dca7b18155 test: tighten sdk transport assertions 2026-05-08 21:21:01 +01:00
Peter Steinberger
7a39b855d3 test: tighten topology helper 2026-05-08 21:20:22 +01:00
Shakker
b415efa2e9 test: tighten root override assertion 2026-05-08 21:20:15 +01:00
Shakker
431d478e5c test: tighten release check assertions 2026-05-08 21:19:51 +01:00
Shakker
4f02ef9cc2 test: tighten plugin boundary assertions 2026-05-08 21:19:21 +01:00
Peter Steinberger
03d6a5a6dc test: tighten docker e2e helper 2026-05-08 21:19:19 +01:00
Shakker
2ccc08851d test: tighten cross os release assertion 2026-05-08 21:18:44 +01:00
Shakker
e54f392b84 test: tighten topology record assertions 2026-05-08 21:18:09 +01:00
Peter Steinberger
daa48e8681 test: tighten acp security helpers 2026-05-08 21:18:04 +01:00
Shakker
d7f4c8b437 test: tighten docker e2e lane assertion 2026-05-08 21:17:37 +01:00
Shakker
6bafd975e2 test: tighten unit coverage assertions 2026-05-08 21:16:59 +01:00
Peter Steinberger
e7b429436b test: tighten security plugin helpers 2026-05-08 21:16:33 +01:00
Alex Knight
68f9710f47 Relay ACP exec approval permissions
* Relay ACP exec approval permissions

* fix: relay ACP exec approvals before tool completion

* fix: guard ACP approval relay retries

* test: fix ACP permission relay mock typing

* test: satisfy ACP permission relay lint

---------

Co-authored-by: Alex Knight <15041791+amknight@users.noreply.github.com>
2026-05-09 06:16:17 +10:00
Shakker
78bbbdec4c test: tighten security fix account assertion 2026-05-08 21:16:07 +01:00
Shakker
61afdefe0c test: tighten windows acl assertions 2026-05-08 21:15:31 +01:00
Shakker
8d9d0038a9 test: tighten node command assertions 2026-05-08 21:14:56 +01:00
Peter Steinberger
ea65056e21 test: tighten security trust helpers 2026-05-08 21:14:43 +01:00
Shakker
2ad93720a9 test: tighten plugin trust assertions 2026-05-08 21:14:20 +01:00
Shakker
86f393062d test: tighten async audit assertion 2026-05-08 21:13:43 +01:00
Shakker
3a66f982f5 test: tighten sandbox browser assertion 2026-05-08 21:13:04 +01:00
Peter Steinberger
f2c21e4278 test: tighten security audit helpers 2026-05-08 21:12:58 +01:00
Shakker
dd85761638 test: tighten gateway http auth assertions 2026-05-08 21:12:35 +01:00
Shakker
ea1220016b test: tighten trust model assertion 2026-05-08 21:11:57 +01:00
Shakker
ab16feb5bf test: tighten gateway exposure assertions 2026-05-08 21:11:32 +01:00
Peter Steinberger
a0ef60eb4c test: clear weak assertion scan 2026-05-08 21:11:12 +01:00
Shakker
4a3b516557 test: tighten account metadata assertion 2026-05-08 21:10:55 +01:00
Shakker
0cb6382da1 test: tighten probe failure assertion 2026-05-08 21:10:22 +01:00
Shakker
39405ebe14 test: tighten small model risk assertions 2026-05-08 21:09:59 +01:00
Shakker
bb8a16f37c test: tighten workspace skill assertion 2026-05-08 21:09:13 +01:00
Peter Steinberger
f5c7465dac test: tighten telegram media assertions 2026-05-08 21:09:04 +01:00
Shakker
69cecf4030 test: tighten exec safe bin assertion 2026-05-08 21:08:39 +01:00
Shakker
558cc44e74 test: tighten channel readonly assertion 2026-05-08 21:07:53 +01:00
Shakker
94314ef8cf test: tighten gateway auth warning assertion 2026-05-08 21:07:31 +01:00
Peter Steinberger
1e9d8b4d92 test: tighten telegram context assertions 2026-05-08 21:07:06 +01:00
Shakker
bffa43df09 test: tighten exec surface assertion 2026-05-08 21:06:54 +01:00
Shakker
3cdb73c423 test: tighten audit extra assertions 2026-05-08 21:06:13 +01:00
Shakker
2e28459a0e test: tighten audit summary assertion 2026-05-08 21:05:49 +01:00
Peter Steinberger
e63ca03bc9 test: tighten pairing provider assertions 2026-05-08 21:05:31 +01:00
Shakker
986efee29c test: tighten safe regex assertions 2026-05-08 21:05:09 +01:00
Peter Steinberger
c895afe872 test: tighten live media chunk helpers 2026-05-08 21:04:00 +01:00
Shakker
8465629fb8 test: tighten pairing request assertions 2026-05-08 21:03:09 +01:00
Peter Steinberger
b570511e23 test: tighten auto reply nullable assertions 2026-05-08 21:02:37 +01:00
Shakker
f10e5c80f1 test: tighten live media plan assertions 2026-05-08 21:02:06 +01:00
Shakker
517c7660dd test: tighten chunk length assertions 2026-05-08 21:01:15 +01:00
Peter Steinberger
c9716d934a test: tighten discord msteams assertions 2026-05-08 21:00:47 +01:00
Shakker
42141d24aa test: tighten command menu assertions 2026-05-08 21:00:18 +01:00
Shakker
c3cab25ff4 test: tighten command arg assertions 2026-05-08 20:59:22 +01:00
Peter Steinberger
127d698b68 test: tighten slack prepared message assertions 2026-05-08 20:58:58 +01:00
Shakker
8fe1379426 test: tighten native command lookup assertions 2026-05-08 20:58:06 +01:00
Peter Steinberger
0c2f604051 test: tighten extension helper assertions 2026-05-08 20:57:42 +01:00
Shakker
1d1883ad88 test: tighten docker digest update assertions 2026-05-08 20:57:01 +01:00
Peter Steinberger
9235dcc7b7 test: tighten video helper assertions 2026-05-08 20:56:19 +01:00
Shakker
4b913dc347 test: tighten docs audit invocation assertions 2026-05-08 20:56:08 +01:00
Shakker
76b5ea5775 test: tighten media fetch guard assertion 2026-05-08 20:55:23 +01:00
Peter Steinberger
45ef4815df test: tighten messaging helper assertions 2026-05-08 20:55:20 +01:00
Shakker
b758abd3ad test: tighten video fallback attempt assertions 2026-05-08 20:54:38 +01:00
Shakker
789fd014cf test: tighten video provider lookup assertions 2026-05-08 20:53:51 +01:00
Peter Steinberger
3a09899e2a test: tighten command capture helper assertions 2026-05-08 20:53:28 +01:00
Shakker
7d2dd28443 test: tighten vitest process listener assertions 2026-05-08 20:52:50 +01:00
Peter Steinberger
92c702b97a test: tighten provider config helper assertions 2026-05-08 20:52:17 +01:00
Shakker
4783dc1e05 test: tighten gateway auth prompt assertions 2026-05-08 20:51:59 +01:00
Shakker
9f5400c108 test: tighten health json log assertion 2026-05-08 20:51:07 +01:00
Shakker
c5cc6d6ae4 test: tighten config validation log assertion 2026-05-08 20:50:34 +01:00
Peter Steinberger
d456dd1bd3 test: tighten command extension helper assertions 2026-05-08 20:50:06 +01:00
Shakker
5ee3a505e6 test: tighten image provider lookup assertions 2026-05-08 20:49:50 +01:00
Shakker
1a8c643734 test: tighten auth repair assertions 2026-05-08 20:49:11 +01:00
Shakker
93af8cffcb test: tighten cron repair assertions 2026-05-08 20:48:00 +01:00
Peter Steinberger
3a2cd7ded5 test: tighten cli status helper assertions 2026-05-08 20:47:39 +01:00
Shakker
189a074573 test: tighten channel config write assertion 2026-05-08 20:46:52 +01:00
Shakker
35adf7cbd3 test: tighten agent identity write assertion 2026-05-08 20:46:23 +01:00
Shakker
2cd44d864a test: tighten backup asset assertions 2026-05-08 20:45:46 +01:00
Shakker
f0dfabfc38 test: tighten browser doctor warning assertion 2026-05-08 20:45:05 +01:00
Peter Steinberger
150ded8f27 test: tighten core capture assertions 2026-05-08 20:44:46 +01:00
Shakker
cbe805e49d test: tighten status json log assertions 2026-05-08 20:44:24 +01:00
Shakker
7645da2643 test: tighten fallback json assertion 2026-05-08 20:43:23 +01:00
Shakker
91d8e55679 test: tighten embedded cleanup assertions 2026-05-08 20:42:54 +01:00
Shakker
004ba1012f test: tighten embedded fallback assertions 2026-05-08 20:42:24 +01:00
Peter Steinberger
a632a68c55 test: tighten core helper assertions 2026-05-08 20:41:57 +01:00
Shakker
6a76976f73 test: tighten gateway request assertions 2026-05-08 20:41:46 +01:00
Shakker
700230c07c test: tighten extension script mock assertion 2026-05-08 20:41:06 +01:00
Shakker
bab07e994f test: tighten preinstall warning assertion 2026-05-08 20:40:33 +01:00
Shakker
1dfe696b71 test: tighten image request header assertion 2026-05-08 20:40:01 +01:00
Peter Steinberger
13dacceed4 test: tighten extension helper assertions 2026-05-08 20:39:25 +01:00
Shakker
a79b88280d test: tighten unit include assertions 2026-05-08 20:39:08 +01:00
Shakker
b893e543b6 test: tighten unit config coverage assertions 2026-05-08 20:38:39 +01:00
Shakker
23c2b8e62d test: tighten unit config defaults 2026-05-08 20:38:12 +01:00
Peter Steinberger
15217b2857 test: tighten provider media helper assertions 2026-05-08 20:37:31 +01:00
Shakker
0122b3bd5f test: tighten config controller request assertions 2026-05-08 20:37:23 +01:00
Shakker
1e90eb8936 test: tighten heartbeat wake assertions 2026-05-08 20:36:40 +01:00
Shakker
469be1b591 test: tighten plugin policy entry assertions 2026-05-08 20:36:04 +01:00
Peter Steinberger
40bf847394 test: tighten ui media helper assertions 2026-05-08 20:35:41 +01:00
Shakker
635863ab38 test: tighten plugin policy write assertions 2026-05-08 20:35:24 +01:00
Shakker
66112e6669 test: tighten telegram lane assertions 2026-05-08 20:34:47 +01:00
Shakker
bff408e332 test: tighten remaining lane assertions 2026-05-08 20:34:17 +01:00
Peter Steinberger
9f2fda6079 test: tighten core ui helper assertions 2026-05-08 20:33:50 +01:00
Shakker
8bd1febba1 test: tighten tooling lane assertions 2026-05-08 20:33:43 +01:00
Shakker
56c82c8024 test: tighten shared lane assertions 2026-05-08 20:33:14 +01:00
Shakker
aa276e0902 test: tighten core lane assertions 2026-05-08 20:32:43 +01:00
Shakker
d692f89f0b test: tighten extension group assertions 2026-05-08 20:32:09 +01:00
Peter Steinberger
88d32bca40 test: tighten tooling helper assertions 2026-05-08 20:31:49 +01:00
Shakker
54f952e984 test: tighten hooks config assertions 2026-05-08 20:31:39 +01:00
Shakker
0d3ca24934 test: tighten extension lane assertions 2026-05-08 20:31:05 +01:00
Peter Steinberger
f7189a4139 test: tighten memory host package assertions 2026-05-08 20:30:09 +01:00
Shakker
2187f98434 test: tighten qa credential fetch assertion 2026-05-08 20:29:23 +01:00
Peter Steinberger
f8187cadc8 fix: canonicalize gemini configured catalog ids 2026-05-08 20:28:04 +01:00
Shakker
0b8a2204a3 test: tighten mobile controls dropdown assertions 2026-05-08 20:27:53 +01:00
Shakker
79d5f49735 test: tighten scoped messaging config assertions 2026-05-08 20:26:11 +01:00
Shakker
cea589a826 test: tighten task registry upsert assertion 2026-05-08 20:24:36 +01:00
Shakker
0c4ccdc3c7 test: tighten system run command assertions 2026-05-08 20:23:41 +01:00
Shakker
f9692d6d28 test: tighten scoped provider config assertions 2026-05-08 20:22:37 +01:00
Shakker
5b478a8fdf test: tighten ssh config spawn assertions 2026-05-08 20:21:41 +01:00
Shakker
57f6521e31 test: tighten fallback status assertions 2026-05-08 20:20:50 +01:00
Peter Steinberger
4016a4f96d test: remove final async placeholders 2026-05-08 20:20:13 +01:00
Shakker
579f091cc4 test: tighten archived session entry assertions 2026-05-08 20:19:42 +01:00
Shakker
baa0face5c test: tighten session entry line assertions 2026-05-08 20:18:54 +01:00
Shakker
45e8f97886 test: tighten scoped extension include assertions 2026-05-08 20:17:44 +01:00
Shakker
32ffbd03f2 test: tighten scoped channel config assertions 2026-05-08 20:16:55 +01:00
Omar Shahine
ad0abdb3d0 docs(imessage): call out includeAttachments off-by-default (#79486)
Merged via squash.

Prepared head SHA: e2e507b6b0
Co-authored-by: omarshahine <10343873+omarshahine@users.noreply.github.com>
Co-authored-by: omarshahine <10343873+omarshahine@users.noreply.github.com>
Reviewed-by: @omarshahine
2026-05-08 12:16:35 -07:00
Peter Steinberger
834b9950fe test: require codex harness reference 2026-05-08 20:15:57 +01:00
Shakker
371563f0a2 test: tighten runtime fetch init assertions 2026-05-08 20:15:13 +01:00
Shakker
0ff793b996 test: tighten slug generator runner assertions 2026-05-08 20:14:06 +01:00
Peter Steinberger
03e7fcfcc8 test: simplify supervisor adapter fixture 2026-05-08 20:13:35 +01:00
Shakker
5e80c6abed test: tighten channel config snapshot assertion 2026-05-08 20:13:16 +01:00
Shakker
a51a9fcd06 test: tighten usage helper tool assertions 2026-05-08 20:12:07 +01:00
Peter Steinberger
368fd23af6 test: require before tool call callback 2026-05-08 20:11:43 +01:00
Shakker
b1cca76b45 test: tighten memory backend override assertions 2026-05-08 20:11:17 +01:00
Shakker
1c588ad452 test: tighten memory backend defaults assertions 2026-05-08 20:10:20 +01:00
Peter Steinberger
630cf8e079 test: require context engine maintenance callbacks 2026-05-08 20:09:30 +01:00
Shakker
62bafd4e6e test: tighten systemd status assertions 2026-05-08 20:09:21 +01:00
Shakker
98ef659a42 test: tighten fire and forget log assertion 2026-05-08 20:08:22 +01:00
Shakker
a80b774b32 test: tighten extension batch assertion 2026-05-08 20:07:44 +01:00
Shakker
4ae1780805 test: tighten image provider header assertions 2026-05-08 20:06:18 +01:00
Peter Steinberger
57c82f4ca5 test: require cli runner async callbacks 2026-05-08 20:06:05 +01:00
Shakker
c747b46c79 test: tighten package manager warning assertion 2026-05-08 20:05:15 +01:00
Shakker
ea20c03988 test: tighten media fetch guard assertion 2026-05-08 20:04:34 +01:00
Shakker
c51b5b52ca test: tighten channel catalog install assertions 2026-05-08 20:03:58 +01:00
Peter Steinberger
848ffe90e6 test: tighten plugin contract async callbacks 2026-05-08 20:03:03 +01:00
Shakker
2322c47901 test: tighten plugin runtime build assertions 2026-05-08 20:02:50 +01:00
Shakker
17c57b7ba3 test: tighten memory multimodal assertions 2026-05-08 20:02:00 +01:00
Shakker
99af8ec2e1 test: tighten memory batch retry assertions 2026-05-08 20:01:06 +01:00
Shakker
49878da759 test: tighten copied env config assertions 2026-05-08 20:00:28 +01:00
Peter Steinberger
11d7f54555 test: require agent async callbacks 2026-05-08 19:59:59 +01:00
Shakker
174d331455 test: tighten unit fast config assertions 2026-05-08 19:59:34 +01:00
Shakker
f4489aec96 test: tighten scoped lane assertions 2026-05-08 19:58:03 +01:00
Peter Steinberger
7460954c53 test: require embedded runner deferred callbacks 2026-05-08 19:57:38 +01:00
Shakker
438802d1bc test: tighten scoped config setup assertions 2026-05-08 19:56:55 +01:00
Shakker
b1f4788e15 test: tighten vitest project config assertions 2026-05-08 19:55:56 +01:00
Peter Steinberger
f956c21c1e test: require gateway startup callbacks 2026-05-08 19:55:29 +01:00
Shakker
ff053eda41 test: tighten ui package config assertions 2026-05-08 19:55:07 +01:00
Shakker
0895cf6989 test: tighten boundary config assertions 2026-05-08 19:54:39 +01:00
Shakker
16a2773d4e test: tighten microsoft foundry auth assertions 2026-05-08 19:53:49 +01:00
Peter Steinberger
0a4b6695c7 test: require inbound debounce callbacks 2026-05-08 19:53:21 +01:00
Peter Steinberger
ae2ae469c2 test: require auto reply prep callbacks 2026-05-08 19:50:54 +01:00
Shakker
b3aea2eab8 test: tighten provider env metadata assertion 2026-05-08 19:50:41 +01:00
Shakker
83fa0cda3b test: tighten external channel runtime assertion 2026-05-08 19:49:22 +01:00
Peter Steinberger
8f52e77ca1 test: require gateway async callbacks 2026-05-08 19:48:29 +01:00
Shakker
e8023c85a7 test: tighten secrets fast path assertion 2026-05-08 19:48:02 +01:00
Shakker
1359d09e05 test: tighten matrix shadowing assertion 2026-05-08 19:46:03 +01:00
Shakker
b7359a74a7 test: tighten telegram inactive runtime assertion 2026-05-08 19:44:52 +01:00
Peter Steinberger
7011bbb953 test: require logging async callbacks 2026-05-08 19:44:10 +01:00
Shakker
1eb876ff8f test: tighten zalo token runtime assertions 2026-05-08 19:43:41 +01:00
Shakker
7a877750b4 test: tighten plugin config collector assertions 2026-05-08 19:42:13 +01:00
Peter Steinberger
ae2338b744 test: require core ui async callbacks 2026-05-08 19:41:54 +01:00
Shakker
950cdfdaf4 test: tighten runtime web tools assertions 2026-05-08 19:40:30 +01:00
Shakker
a9e322c4c1 test: tighten secret target registry assertion 2026-05-08 19:39:29 +01:00
Peter Steinberger
7e8ac5e6fb test: require discord async callbacks 2026-05-08 19:39:02 +01:00
Shakker
d213397b1d test: tighten channel secret contract assertions 2026-05-08 19:38:11 +01:00
Peter Steinberger
beff4dfb58 test: require qqbot queue callbacks 2026-05-08 19:37:28 +01:00
Shakker
4239c15085 test: tighten secrets plan assertions 2026-05-08 19:37:00 +01:00
Shakker
7765b1f91f test: tighten web fetch resolution assertions 2026-05-08 19:35:58 +01:00
Peter Steinberger
1b15116aa8 test: require telegram async callbacks 2026-05-08 19:35:31 +01:00
Shakker
64862c7ff5 test: tighten media provider registry assertions 2026-05-08 19:34:11 +01:00
Peter Steinberger
ffb1cc97cb test: require messaging async callbacks 2026-05-08 19:33:17 +01:00
Shakker
41c3a541c2 test: tighten vision skip assertions 2026-05-08 19:32:55 +01:00
Shakker
ddccd22b1e test: tighten tiny audio failure assertions 2026-05-08 19:31:19 +01:00
Peter Steinberger
4e0f193e2e test: require slack async callbacks 2026-05-08 19:31:01 +01:00
Shakker
3a0b81af9d test: tighten auto audio output assertions 2026-05-08 19:30:23 +01:00
Peter Steinberger
d5ccdab3d8 test: require matrix async callbacks 2026-05-08 19:29:35 +01:00
Shakker
7a6b98c3df test: tighten video runner output assertions 2026-05-08 19:28:42 +01:00
Shakker
0043560cca test: tighten qwen video request assertions 2026-05-08 19:27:09 +01:00
Peter Steinberger
0c34f7ac1c test: reuse command queue deferred helper 2026-05-08 19:26:34 +01:00
Shakker
29ac446afe test: tighten qwen catalog assertions 2026-05-08 19:25:50 +01:00
Shakker
9acf08a38a test: tighten mattermost model picker assertion 2026-05-08 19:24:09 +01:00
Peter Steinberger
73faa75be1 test: require browser async callbacks 2026-05-08 19:23:45 +01:00
Shakker
17127ef022 test: tighten usage aggregate assertion 2026-05-08 19:23:12 +01:00
Shakker
a1ea0b65de test: tighten firecrawl fetch config assertion 2026-05-08 19:22:12 +01:00
Shakker
67e40485cd test: tighten debug view command assertion 2026-05-08 19:21:20 +01:00
Peter Steinberger
16c54655d3 test: require common deferred callbacks 2026-05-08 19:20:42 +01:00
Shakker
2f247cf20c test: tighten readability extractor assertions 2026-05-08 19:20:28 +01:00
Shakker
e733351413 test: tighten runway video assertion 2026-05-08 19:19:40 +01:00
Peter Steinberger
8db4b3af6f test: require core deferred callbacks 2026-05-08 19:18:54 +01:00
Shakker
d39f4dcce6 test: tighten byteplus video assertions 2026-05-08 19:18:44 +01:00
Shakker
2844eb0f7b test: tighten openrouter video assertions 2026-05-08 19:17:48 +01:00
Shakker
358c182a7f test: tighten openrouter image assertions 2026-05-08 19:16:25 +01:00
Peter Steinberger
d642cce5ae test: require ui deferred callbacks 2026-05-08 19:15:40 +01:00
Shakker
076526b5c0 test: tighten zalouser setup assertions 2026-05-08 19:15:27 +01:00
Shakker
71a20422a0 test: tighten zalo setup assertions 2026-05-08 19:14:39 +01:00
Shakker
b332b7dff7 test: tighten zalo api request assertions 2026-05-08 19:13:40 +01:00
Peter Steinberger
c8d7db55ad test: require voice-call async gates 2026-05-08 19:12:11 +01:00
Shakker
a91267c1d9 test: tighten mattermost client request assertion 2026-05-08 19:11:50 +01:00
Shakker
873e26adbb test: tighten synology chat tls assertions 2026-05-08 19:10:29 +01:00
Shakker
25cac63563 test: tighten moonshot catalog assertions 2026-05-08 19:09:30 +01:00
Peter Steinberger
ab6e496317 test: require memory deferred callbacks 2026-05-08 19:09:14 +01:00
Shakker
d65098e89f test: tighten inworld tts request assertion 2026-05-08 19:08:13 +01:00
Peter Steinberger
8100984e0e test: require extension async gates 2026-05-08 19:07:38 +01:00
Shakker
b5c8f6dd01 test: tighten inworld directive assertions 2026-05-08 19:07:26 +01:00
Shakker
d0c1850152 test: tighten qqbot queue assertions 2026-05-08 19:06:37 +01:00
Shakker
bdec274079 test: tighten mattermost slash command assertion 2026-05-08 19:05:45 +01:00
Shakker
f2c917d104 test: tighten firecrawl config assertion 2026-05-08 19:05:05 +01:00
Peter Steinberger
b71312d7d5 test: require signal deferred callbacks 2026-05-08 19:04:48 +01:00
Shakker
8da80d57da test: tighten cloudflare gateway assertions 2026-05-08 19:04:19 +01:00
Shakker
228c60064f test: tighten moonshot video request assertions 2026-05-08 19:03:25 +01:00
Peter Steinberger
9c496467cd test: require gateway deferred callbacks 2026-05-08 19:02:55 +01:00
Shakker
97fdba0614 test: tighten image prompt assertions 2026-05-08 19:02:19 +01:00
Peter Steinberger
0df60360e7 test: require queue deferred callbacks 2026-05-08 19:01:37 +01:00
Shakker
520fe726af test: tighten canvas migration assertions 2026-05-08 19:01:28 +01:00
Shakker
cf8be4adda test: tighten chutes model assertions 2026-05-08 19:00:34 +01:00
Shakker
429d7238d4 test: tighten discord guild lookup assertion 2026-05-08 18:59:39 +01:00
Peter Steinberger
9c91e17483 test: require plugin async gates 2026-05-08 18:59:24 +01:00
Shakker
6451000229 test: tighten discord api request assertion 2026-05-08 18:58:56 +01:00
Shakker
b7bdcaeb88 test: tighten web search provider assertions 2026-05-08 18:58:20 +01:00
Peter Steinberger
45f3ec2ead test: require deferred callbacks 2026-05-08 18:57:36 +01:00
Shakker
db883ec26a test: tighten fireworks provider assertions 2026-05-08 18:57:27 +01:00
Shakker
7f5df0b97d test: tighten mattermost config assertions 2026-05-08 18:56:26 +01:00
Peter Steinberger
f29327b65d test: require channels controller fixtures 2026-05-08 18:55:56 +01:00
Shakker
d98752155d test: tighten kilocode provider assertions 2026-05-08 18:55:07 +01:00
Shakker
a4c95bbb80 test: tighten locale version assertion 2026-05-08 18:54:12 +01:00
Shakker
8543ba40de test: tighten huggingface provider assertion 2026-05-08 18:53:29 +01:00
Shakker
7c86f7434d test: tighten qianfan provider assertions 2026-05-08 18:52:40 +01:00
Peter Steinberger
7d3cb57f92 test: require node host path token 2026-05-08 18:51:12 +01:00
Peter Steinberger
fb689b9b97 test: require imessage adapter fixtures 2026-05-08 18:49:32 +01:00
Shakker
6d1c5c9df3 test: tighten custom theme parse assertion 2026-05-08 18:48:59 +01:00
Shakker
af4213c5a3 test: tighten echo transcript delivery assertion 2026-05-08 18:47:42 +01:00
Peter Steinberger
f972d9e7d1 test: require provider rollback fixtures 2026-05-08 18:47:01 +01:00
Shakker
e3d23114b8 test: tighten deepinfra image result assertions 2026-05-08 18:45:40 +01:00
Peter Steinberger
2956013a23 test: require outbound contract hooks 2026-05-08 18:45:16 +01:00
Shakker
d3e3c96a80 test: tighten task flow snapshot assertions 2026-05-08 18:43:47 +01:00
Peter Steinberger
edb3e6732c test: require dreaming markdown paths 2026-05-08 18:42:37 +01:00
Shakker
84094573fb test: tighten deepgram audio request assertion 2026-05-08 18:42:19 +01:00
Peter Steinberger
80cc3e66fd test: require msteams config fixture 2026-05-08 18:41:04 +01:00
Shakker
38e9d93da7 test: tighten tool planner hidden assertions 2026-05-08 18:40:14 +01:00
Peter Steinberger
5cd175bde9 test: require provider optional hooks 2026-05-08 18:38:52 +01:00
Peter Steinberger
a7b359d319 test: require channel lifecycle starters 2026-05-08 18:36:59 +01:00
Shakker
9a83706da4 test: tighten groq media provider assertion 2026-05-08 18:36:32 +01:00
Peter Steinberger
d7ce507d6f test: require feishu outbound fixtures 2026-05-08 18:35:24 +01:00
Shakker
a130dd080b test: tighten image completion call assertions 2026-05-08 18:34:24 +01:00
Peter Steinberger
8f30e37da8 test: require slack message adapter 2026-05-08 18:33:13 +01:00
Peter Steinberger
86a9b3fcb1 test: require msteams message senders 2026-05-08 18:31:40 +01:00
Shakker
02f762117d test: tighten media proxy output assertions 2026-05-08 18:30:44 +01:00
Peter Steinberger
326f637c48 test: require mattermost setup validator 2026-05-08 18:30:04 +01:00
Peter Steinberger
bbead1bb1e test: require mattermost message adapter 2026-05-08 18:28:46 +01:00
Shakker
47119a5527 test: tighten cli respawn plan assertions 2026-05-08 18:28:10 +01:00
Peter Steinberger
6cb3effd9c test: require outbound payload senders 2026-05-08 18:26:44 +01:00
Shakker
0b6f56fae0 test: tighten discord proxy abort assertion 2026-05-08 18:25:54 +01:00
Peter Steinberger
46d56725c9 test: require zalouser outbound fixtures 2026-05-08 18:25:13 +01:00
Shakker
e11a2dcf07 test: tighten voice consult session assertion 2026-05-08 18:24:09 +01:00
Peter Steinberger
e328bbc5ad test: require setup validators 2026-05-08 18:23:37 +01:00
Shakker
f9c56bbce0 test: tighten byteplus video result assertion 2026-05-08 18:22:31 +01:00
Peter Steinberger
7ce0532fa5 test: reuse tlon text sender 2026-05-08 18:22:01 +01:00
Shakker
1849e0c34b test: tighten deepinfra video result assertion 2026-05-08 18:21:05 +01:00
Peter Steinberger
5e34a350de test: require discord message adapter 2026-05-08 18:20:29 +01:00
Shakker
f9c8542dae test: tighten vydra video result assertions 2026-05-08 18:19:06 +01:00
Peter Steinberger
c201c8dcf6 test: require mattermost actions 2026-05-08 18:18:43 +01:00
Shakker
30049c6d56 test: tighten together video result assertion 2026-05-08 18:17:40 +01:00
Shakker
df22284f85 test: tighten control ui buffer assertions 2026-05-08 18:16:04 +01:00
Peter Steinberger
9fcb583faf test: require plugin update fixtures 2026-05-08 18:15:45 +01:00
Shakker
dc5ebc24fc test: tighten talkback abort assertion 2026-05-08 18:14:35 +01:00
Peter Steinberger
e875ba97ab test: require media config fixture 2026-05-08 18:14:07 +01:00
Shakker
582895939f test: tighten deepgram media output assertion 2026-05-08 18:13:07 +01:00
Peter Steinberger
90f821efb4 test: require compaction provider lookup 2026-05-08 18:12:13 +01:00
Shakker
75e13da8fd test: tighten memory citation result assertions 2026-05-08 18:11:49 +01:00
Peter Steinberger
ba2c4e075a test: require taskflow child task 2026-05-08 18:10:55 +01:00
Shakker
eb71492d0d test: tighten canvas snapshot file assertion 2026-05-08 18:10:13 +01:00
Shakker
2faf2303a1 test: tighten pdf extraction image assertion 2026-05-08 18:09:09 +01:00
Peter Steinberger
b7bf529441 test: require extension scenario schemas 2026-05-08 18:08:25 +01:00
Shakker
1eb81f65ca test: tighten commitment full chain assertions 2026-05-08 18:07:51 +01:00
Shakker
9df3f3be1a test: tighten commitment due window assertions 2026-05-08 18:06:39 +01:00
Peter Steinberger
668f7417e2 test: require dreaming repair archive dir 2026-05-08 18:06:05 +01:00
Shakker
7f0cde8d16 test: tighten commitment batch privacy assertions 2026-05-08 18:05:23 +01:00
Peter Steinberger
2fc4b4c38f test: require provider optional hooks 2026-05-08 18:04:38 +01:00
Shakker
32fb032ba0 test: tighten talk diagnostic event assertion 2026-05-08 18:03:42 +01:00
Shakker
809abda82b test: tighten realtime voice bridge assertions 2026-05-08 18:01:58 +01:00
Peter Steinberger
b42bce0c8c test: require device pair media url 2026-05-08 18:01:30 +01:00
Peter Steinberger
de82701603 test: require powershell command runner 2026-05-08 17:59:15 +01:00
Shakker
79dd22bfb2 test: tighten heartbeat session store assertions 2026-05-08 17:58:01 +01:00
Peter Steinberger
396179883c test: require compact ui controls 2026-05-08 17:57:22 +01:00
Peter Steinberger
ceb0385d29 test: require media process handles 2026-05-08 17:55:10 +01:00
Shakker
b13e8b2ed7 test: tighten memory fallback provider assertions 2026-05-08 17:54:23 +01:00
Peter Steinberger
6f26a477be test: require core weak guard lookups 2026-05-08 17:53:05 +01:00
Shakker
9b3c3686bc test: tighten block reply enqueue assertion 2026-05-08 17:52:20 +01:00
Peter Steinberger
827354b7b2 test: require active video task status 2026-05-08 17:51:25 +01:00
Shakker
07a577630a test: tighten subagent target assertions 2026-05-08 17:50:30 +01:00
Shakker
6e6c0cfbbe test: tighten discord queue timeout assertions 2026-05-08 17:48:42 +01:00
Peter Steinberger
ce6fca41d8 test: require codex block reply text 2026-05-08 17:48:12 +01:00
Shakker
6f2ada1723 test: tighten tts command result assertions 2026-05-08 17:44:40 +01:00
Peter Steinberger
127fdb6120 test: require status gateway warning 2026-05-08 17:43:52 +01:00
Peter Steinberger
1ecc1e899e test: require active secrets snapshot 2026-05-08 17:42:21 +01:00
Peter Steinberger
28893ce89c test: require cron cadence timestamps 2026-05-08 17:40:50 +01:00
Shakker
de21569e05 test: tighten discord audio preflight assertions 2026-05-08 17:39:54 +01:00
Peter Steinberger
bbfd6a2e59 test: require frontmatter install base 2026-05-08 17:39:36 +01:00
Shakker
dfcafcaf41 test: tighten discord mention preflight assertions 2026-05-08 17:38:59 +01:00
Peter Steinberger
2ccc85e986 test: require task parent flow ids 2026-05-08 17:38:03 +01:00
Shakker
e09ff2bc15 test: tighten discord bot preflight assertions 2026-05-08 17:37:57 +01:00
Shakker
b927d50cc7 test: tighten discord bound preflight assertions 2026-05-08 17:37:08 +01:00
Peter Steinberger
ebe6ef321c test: require modal shadow labels 2026-05-08 17:36:12 +01:00
Shakker
6c015e83a1 test: tighten discord preflight result assertions 2026-05-08 17:36:05 +01:00
Shakker
b542daab1f test: tighten discord thread lifecycle assertions 2026-05-08 17:35:02 +01:00
Peter Steinberger
f42f6dde9a test: require generation tool handles 2026-05-08 17:34:42 +01:00
Shakker
db21504632 test: tighten doctor auth migration assertion 2026-05-08 17:31:51 +01:00
Shakker
ca4d6da0aa test: tighten reply normalization assertions 2026-05-08 17:30:42 +01:00
Peter Steinberger
c109e29c15 test: require infra helper results 2026-05-08 17:29:29 +01:00
Shakker
e0e8354536 test: tighten memory index manager assertion 2026-05-08 17:29:19 +01:00
Shakker
631c655db7 test: tighten memory watcher manager assertions 2026-05-08 17:28:27 +01:00
Shakker
4cfe562fa4 test: tighten google oauth cache assertion 2026-05-08 17:27:37 +01:00
Peter Steinberger
3da1c71273 test: require core catalog results 2026-05-08 17:27:19 +01:00
Peter Steinberger
596cbd2da8 test: require qa lab rpc callbacks 2026-05-08 17:25:33 +01:00
Shakker
b204b5dd25 test: tighten qmd update callback assertion 2026-05-08 17:25:22 +01:00
Shakker
0c6200cd14 test: tighten plugin status inspect assertions 2026-05-08 17:24:23 +01:00
Shakker
a68f58a436 test: tighten voice media upgrade callback assertion 2026-05-08 17:23:15 +01:00
Shakker
f785d96b0f test: tighten qa gateway rpc callback assertions 2026-05-08 17:22:18 +01:00
Peter Steinberger
26644d3e9d test: require plugin inspect reports 2026-05-08 17:21:54 +01:00
Shakker
7e0f2301c9 test: tighten discord thread binding shared state assertion 2026-05-08 17:20:51 +01:00
Peter Steinberger
f4c51937e8 test: require oc-path resolver matches 2026-05-08 17:20:02 +01:00
Shakker
1b91cdf459 test: tighten discord acp preflight assertions 2026-05-08 17:19:54 +01:00
Shakker
f38e65fb89 test: tighten discord acp bind route assertion 2026-05-08 17:19:10 +01:00
Shakker
b0f481bdf1 test: tighten web provider fast path assertions 2026-05-08 17:17:55 +01:00
Shakker
686f595c47 test: tighten external content marker assertion 2026-05-08 17:16:31 +01:00
Peter Steinberger
c223fa61cd test: fix backup callback narrowing 2026-05-08 17:15:54 +01:00
Peter Steinberger
de850f44f5 test: require command helper results 2026-05-08 17:15:54 +01:00
Shakker
2d5a5ee666 test: tighten windows acl command assertions 2026-05-08 17:15:31 +01:00
Shakker
d470d89327 test: tighten config footprint record assertion 2026-05-08 17:14:12 +01:00
Shakker
069aa10c18 test: tighten service audit drift assertion 2026-05-08 17:13:12 +01:00
Shakker
cb2f2e013a test: tighten clawhub docs schema assertion 2026-05-08 17:12:25 +01:00
Shakker
1b16944eb4 test: tighten gateway auth snapshot assertion 2026-05-08 17:11:33 +01:00
Shakker
07b972ca07 test: tighten backup manifest callback assertions 2026-05-08 17:11:00 +01:00
Shakker
a09e68e249 test: tighten matrix logger assertion 2026-05-08 17:10:01 +01:00
Peter Steinberger
6575788231 test: require CLI routes 2026-05-08 17:09:33 +01:00
Shakker
de9e5b44de test: tighten bundled plugin schema assertion 2026-05-08 17:09:08 +01:00
Shakker
7c4c4762eb test: tighten session fork assertions 2026-05-08 17:08:00 +01:00
Shakker
0bd7995ddb test: tighten post compaction context assertions 2026-05-08 17:07:16 +01:00
Peter Steinberger
172158bfcb test: require plugin test handles 2026-05-08 17:06:54 +01:00
Shakker
4d448e4cce test: tighten missing plugin command assertion 2026-05-08 17:05:55 +01:00
Shakker
534fef2836 test: tighten slack command payload assertion 2026-05-08 17:05:05 +01:00
Shakker
111863a7b1 test: tighten slack media result assertions 2026-05-08 17:04:27 +01:00
Peter Steinberger
ad818ed99d test: require matrix test targets 2026-05-08 17:03:43 +01:00
Shakker
f193efbcd3 test: tighten discord owner allowlist assertion 2026-05-08 17:02:36 +01:00
Shakker
415958ec08 test: tighten discord permission bitfield assertion 2026-05-08 17:01:19 +01:00
Peter Steinberger
e4622823e4 test: require approval handler runtime 2026-05-08 17:00:43 +01:00
Shakker
0d5ddc719a test: tighten discord threading utility assertions 2026-05-08 17:00:22 +01:00
Shakker
504000ff61 test: tighten mantle provider assertions 2026-05-08 16:59:30 +01:00
Peter Steinberger
99df40b49e test: require core helper results 2026-05-08 16:59:17 +01:00
Shakker
a8bbfdc7e6 test: tighten whatsapp transport activity assertion 2026-05-08 16:58:32 +01:00
Shakker
40998a8152 test: tighten command queue wait assertion 2026-05-08 16:57:46 +01:00
Peter Steinberger
2cf0c07f7c test: require proxy lifecycle handles 2026-05-08 16:57:21 +01:00
Shakker
a07802e7f0 test: tighten browser profile assertion 2026-05-08 16:56:54 +01:00
Shakker
d040d6d639 test: tighten memory flush defaults assertion 2026-05-08 16:55:55 +01:00
Peter Steinberger
5a91c7c2a7 test: require gateway lock acquisitions 2026-05-08 16:54:36 +01:00
Shakker
17444268a9 test: tighten memory wiki schema assertion 2026-05-08 16:53:30 +01:00
Peter Steinberger
bcf094f443 test: tighten cron timer assertions 2026-05-08 16:52:48 +01:00
Peter Steinberger
bbd6d9e254 test: stabilize node 26 full-suite edge cases 2026-05-08 16:52:23 +01:00
Peter Steinberger
7cc0b21e4d test: restore node 26 test compatibility 2026-05-08 16:52:23 +01:00
Peter Steinberger
ddaf9178c5 test: tighten extension helper assertions 2026-05-08 16:51:15 +01:00
Shakker
15ad70356c test: tighten telegram media retry assertions 2026-05-08 16:51:01 +01:00
Shakker
e554bf7376 test: tighten telegram mention assertions 2026-05-08 16:49:17 +01:00
Peter Steinberger
03ac05a3cd test: tighten core helper assertions 2026-05-08 16:48:41 +01:00
Shakker
fbf71abcfd test: tighten telegram thread binding assertion 2026-05-08 16:48:32 +01:00
Shakker
faceeb8cd6 test: tighten telegram acp binding assertions 2026-05-08 16:47:22 +01:00
Peter Steinberger
8bf721f307 test: tighten extension media assertions 2026-05-08 16:46:56 +01:00
Shakker
9c584567b3 test: tighten telegram reaction assertions 2026-05-08 16:46:37 +01:00
Shakker
46214d973f test: tighten telegram route thread assertions 2026-05-08 16:45:24 +01:00
Shakker
2866eeb1a6 test: tighten telegram topic name assertions 2026-05-08 16:44:12 +01:00
Shakker
69b43a71b8 test: tighten telegram dm thread assertions 2026-05-08 16:43:09 +01:00
Peter Steinberger
e6fa674b75 test: tighten parser null assertions 2026-05-08 16:42:26 +01:00
Shakker
f1ba8da395 test: tighten telegram reply target assertions 2026-05-08 16:42:00 +01:00
Shakker
8c8dc84aad test: tighten telegram forward context assertions 2026-05-08 16:41:14 +01:00
Peter Steinberger
9ce5a6db5b test: require grouped render elements 2026-05-08 16:40:34 +01:00
Shakker
18b6015d71 test: tighten telegram topic agent assertions 2026-05-08 16:40:13 +01:00
Shakker
62c2835767 test: tighten line routing assertions 2026-05-08 16:38:49 +01:00
Shakker
b1bfb86520 test: tighten qqbot audio assertions 2026-05-08 16:38:01 +01:00
Peter Steinberger
a54ec4572e test: require config browser elements 2026-05-08 16:37:35 +01:00
Shakker
af9ae6b244 test: tighten twitch client message assertion 2026-05-08 16:37:02 +01:00
Shakker
82ebd54afe test: tighten feishu comment turn assertion 2026-05-08 16:36:18 +01:00
Shakker
39f33ed7bc test: tighten twitch account assertions 2026-05-08 16:35:32 +01:00
Peter Steinberger
64eff58248 test: require navigation browser elements 2026-05-08 16:35:20 +01:00
Shakker
14a9164e39 test: tighten secret fast path assertion 2026-05-08 16:34:23 +01:00
Shakker
590363cb93 test: tighten secret target assertions 2026-05-08 16:33:39 +01:00
Shakker
14b480defc test: require tool card controls 2026-05-08 16:32:35 +01:00
Peter Steinberger
1b9431f0c4 test: require chat responsive geometry 2026-05-08 16:31:55 +01:00
Shakker
5ad0b7f920 test: require grouped render action targets 2026-05-08 16:31:46 +01:00
Shakker
a7ecc7bcd9 test: require dreaming diary buttons 2026-05-08 16:30:53 +01:00
Shakker
7b377d23dc test: require agents preview controls 2026-05-08 16:29:40 +01:00
Peter Steinberger
43d9b44c7a test: tighten talk and session controls 2026-05-08 16:29:27 +01:00
Shakker
fce7b95d19 test: require skills view buttons 2026-05-08 16:28:52 +01:00
Shakker
e101ca9ed1 test: require command palette controls 2026-05-08 16:27:39 +01:00
Peter Steinberger
a13ffb9d9f test: require cron view dom elements 2026-05-08 16:27:21 +01:00
Shakker
d4278fcaf7 test: require channel action buttons 2026-05-08 16:26:51 +01:00
Shakker
19ac69bba3 test: require session view controls 2026-05-08 16:26:00 +01:00
Peter Steinberger
4a2081c675 test: require chat view model picker 2026-05-08 16:25:37 +01:00
Shakker
fd443f8bec test: require chat action buttons 2026-05-08 16:24:26 +01:00
Shakker
2e50223efa test: require quick settings buttons 2026-05-08 16:23:45 +01:00
Peter Steinberger
007b366fb6 test: require dreaming view elements 2026-05-08 16:23:36 +01:00
Shakker
41514e8393 test: simplify discord allowlist helper 2026-05-08 16:22:47 +01:00
Peter Steinberger
7a39059dc0 test: tighten app stream lifecycle assertions 2026-05-08 16:22:18 +01:00
Shakker
d82500bd7b test: simplify plugin inspect guard 2026-05-08 16:22:04 +01:00
Shakker
f56f1dd161 test: tighten qa lab staged root assertion 2026-05-08 16:20:22 +01:00
Peter Steinberger
838b546778 test: require chat control buttons 2026-05-08 16:20:10 +01:00
Shakker
c6aad445e4 test: require navigation chat containers 2026-05-08 16:19:41 +01:00
Peter Steinberger
ffcb7bf7a0 test: require modal dialog helpers 2026-05-08 16:18:18 +01:00
Shakker
1c4a20d581 test: tighten memory cli json payload assertions 2026-05-08 16:18:04 +01:00
Shakker
434a682677 test: tighten node pairing token assertion 2026-05-08 16:16:52 +01:00
Peter Steinberger
2f17faf4c7 test: tighten extension context assertions 2026-05-08 16:16:47 +01:00
Shakker
ca34143a9d test: require cron filter controls 2026-05-08 16:15:52 +01:00
Peter Steinberger
7bad53eca0 test: require cron view action elements 2026-05-08 16:14:04 +01:00
Shakker
57d987a55f test: require config raw controls 2026-05-08 16:13:59 +01:00
Shakker
5534233b08 test: tighten qa channel media context assertion 2026-05-08 16:12:59 +01:00
Shakker
9ecb7fd5e9 test: tighten line group context assertions 2026-05-08 16:11:48 +01:00
Peter Steinberger
a9ea60db5d test: require config view action buttons 2026-05-08 16:11:14 +01:00
Shakker
cfdcd730bf test: dedupe discord allowlist guards 2026-05-08 16:11:00 +01:00
Shakker
65f72255fd test: tighten allowed values assertions 2026-05-08 16:09:59 +01:00
Shakker
a1f80a4c82 test: tighten chat control assertions 2026-05-08 16:09:08 +01:00
Peter Steinberger
4d385e7065 test: require ui navigation controls 2026-05-08 16:09:00 +01:00
Shakker
c8af77a280 test: tighten config browser assertions 2026-05-08 16:08:04 +01:00
Shakker
54b625e761 test: tighten run controls dom counts 2026-05-08 16:07:13 +01:00
Shakker
c0f8eda4ab test: fail hard on missing avatar input 2026-05-08 16:06:20 +01:00
Peter Steinberger
c011300dd4 test: tighten config form control assertions 2026-05-08 16:06:04 +01:00
Shakker
dbda4782fb test: tighten grouped metadata assertions 2026-05-08 16:05:21 +01:00
Shakker
f8e1bafca7 test: tighten grouped delete assertions 2026-05-08 16:04:42 +01:00
Shakker
01c057cc40 test: dedupe exec approval modal assertions 2026-05-08 16:03:52 +01:00
Shakker
8f44dc7da8 test: tighten chat view assertions 2026-05-08 16:02:57 +01:00
Peter Steinberger
add9b8920e test: clear nullable matcher scan 2026-05-08 16:02:28 +01:00
Shakker
2b6704dedc test: tighten agents panel assertions 2026-05-08 16:00:54 +01:00
Peter Steinberger
ca2c00bd7b test: tighten gateway helper assertions 2026-05-08 16:00:11 +01:00
Shakker
bbf536c0c6 test: tighten agents preview assertion 2026-05-08 16:00:01 +01:00
the sun gif man
954d20ece2 fix: allow Nix store plugin hardlinks (#79344)
Merged via squash.

Prepared head SHA: bf533f8654

Co-authored-by: Codex <noreply@openai.com>
Reviewed-by: @joshp123
2026-05-08 16:59:53 +02:00
Shakker
b856b3f51c test: tighten dreaming empty state assertion 2026-05-08 15:59:02 +01:00
Peter Steinberger
a571fcf041 test: tighten auth profile assertions 2026-05-08 15:58:11 +01:00
Shakker
b46c26b4b0 test: tighten tool card button assertions 2026-05-08 15:57:58 +01:00
Shakker
d9175464d7 test: tighten chat mobile helper assertions 2026-05-08 15:56:30 +01:00
Peter Steinberger
e5dd03fb3d test: tighten runner image helper assertions 2026-05-08 15:56:02 +01:00
Shakker
fc327378a0 test: tighten root output assertions 2026-05-08 15:55:39 +01:00
Shakker
58e9468f4f test: tighten exec approval assertions 2026-05-08 15:54:43 +01:00
Peter Steinberger
7c401f24e4 test: dedupe history image prune assertions 2026-05-08 15:54:03 +01:00
Shakker
8940d34682 test: tighten settings poller assertions 2026-05-08 15:53:52 +01:00
Shakker
0aa2bcd8d3 test: tighten quick settings assertions 2026-05-08 15:52:28 +01:00
Peter Steinberger
a6313f64f9 test: tighten nullable agent helper assertions 2026-05-08 15:51:12 +01:00
Peter Steinberger
28fad6a6c3 test: dedupe image generation tool assertions 2026-05-08 15:49:38 +01:00
Shakker
b98d860d4d test: tighten oc path assertions 2026-05-08 15:49:22 +01:00
Shakker
2cbc67dbc6 test: tighten run controls stop assertion 2026-05-08 15:48:30 +01:00
Shakker
5871350356 test: tighten provider choice assertions 2026-05-08 15:48:30 +01:00
Peter Steinberger
a0459cde8a test: use gemini 3.1 in live switch 2026-05-08 15:47:36 +01:00
Shakker
8161dafacf test: tighten command palette assertions 2026-05-08 15:47:27 +01:00
Shakker
10d445c911 test: tighten cron view assertions 2026-05-08 15:46:22 +01:00
Shakker
4763c07be6 test: tighten run controls assertions 2026-05-08 15:45:10 +01:00
Shakker
72209f7758 test: tighten component fixture assertions 2026-05-08 15:44:08 +01:00
Shakker
29e27d2d9c test: tighten ui element assertions 2026-05-08 15:43:01 +01:00
Peter Steinberger
0cf28560fa test: tighten compaction checkpoint assertions 2026-05-08 15:42:50 +01:00
Shakker
bb9beba7cf test: tighten storage session map assertions 2026-05-08 15:42:18 +01:00
Shakker
df913465f8 test: tighten provider env assertions 2026-05-08 15:41:38 +01:00
Peter Steinberger
3e7f2da32d test: tighten gateway lifecycle assertions 2026-05-08 15:40:54 +01:00
Shakker
8a0a56556d test: tighten memory session file assertions 2026-05-08 15:40:09 +01:00
Peter Steinberger
bf0cbfead7 test: dedupe gateway hooks assertions 2026-05-08 15:38:31 +01:00
Peter Steinberger
d7d83eb867 test: dedupe cli backend resolution assertions 2026-05-08 15:36:43 +01:00
Peter Steinberger
23a9bf8333 test: tighten image tool factory assertions 2026-05-08 15:33:36 +01:00
Peter Steinberger
e402efe818 test: tighten media tool factory assertions 2026-05-08 15:31:27 +01:00
Peter Steinberger
b4a717829d test: tighten gateway nullable assertions 2026-05-08 15:29:10 +01:00
Peter Steinberger
7ff5e09289 test: tighten nullable status assertions 2026-05-08 15:27:28 +01:00
Peter Steinberger
f309a4020d test: clear defined matcher scan 2026-05-08 15:25:24 +01:00
Peter Steinberger
7c31a9aafc test: clear object shape matcher scan 2026-05-08 15:23:09 +01:00
Peter Steinberger
b7033369a6 test: tighten non-live object guards 2026-05-08 15:21:00 +01:00
Peter Steinberger
d0ea405662 test: tighten object shape assertions 2026-05-08 15:17:56 +01:00
Shakker
60068c52b0 test: run json stdout e2e from source 2026-05-08 15:17:52 +01:00
Peter Steinberger
f6476140d2 test: tighten live provider assertions 2026-05-08 15:11:21 +01:00
Statxc
9da2f7cf81 fix(gateway): reset webchat /new in place when dmScope is main (#77434) (#71170)
Merged via squash.

Prepared head SHA: 96a9a83eac
Co-authored-by: statxc <181730535+statxc@users.noreply.github.com>
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Reviewed-by: @velvet-shark
2026-05-08 16:11:17 +02:00
Peter Steinberger
dce9261415 test: tighten e2e helper assertions 2026-05-08 15:08:47 +01:00
Peter Steinberger
ff860dcf6e test: tighten slack slash session key 2026-05-08 15:06:59 +01:00
Peter Steinberger
eecef7e10c test: tighten storage doctor assertions 2026-05-08 15:05:29 +01:00
Peter Steinberger
9491176811 test: tighten provider rewrite assertions 2026-05-08 15:03:49 +01:00
Peter Steinberger
7d20be5fb5 test: tighten gateway health auth assertions 2026-05-08 15:02:25 +01:00
Shakker
5c39e2da3a test: accept utc timestamp label 2026-05-08 15:01:42 +01:00
Peter Steinberger
dd1b276a9c test: tighten provider stream assertions 2026-05-08 15:00:10 +01:00
Peter Steinberger
cd89496d08 test: tighten timeout signature assertions 2026-05-08 14:57:41 +01:00
Peter Steinberger
048a50cfe1 test: tighten auto reply timestamps 2026-05-08 14:56:01 +01:00
Peter Steinberger
2008873be6 test: tighten agent timestamp assertions 2026-05-08 14:54:31 +01:00
Peter Steinberger
f9a29a06ef test: tighten agent string assertions 2026-05-08 14:53:25 +01:00
Peter Steinberger
a16f0dd73c test: tighten session status ids 2026-05-08 14:52:15 +01:00
Peter Steinberger
0248305ab2 test: tighten gateway compaction ids 2026-05-08 14:51:08 +01:00
Peter Steinberger
0fe6a3c938 test: tighten subagent registry timestamps 2026-05-08 14:49:49 +01:00
Jeremy Knows
b32312efa5 fix(failover): defer profile cooldown marking to unblock rate-limit rotation (#57283)
Merged via squash.

Prepared head SHA: 498c31d6dc
Co-authored-by: jeremyknows <237305675+jeremyknows@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-05-08 16:49:47 +03:00
Peter Steinberger
1b9986952c test: tighten auth profile assertions 2026-05-08 14:47:55 +01:00
Peter Steinberger
164714d36a test: tighten acp lifecycle assertions 2026-05-08 14:46:19 +01:00
Peter Steinberger
c238a51f59 fix(config): keep Gemini 3.1 model writes canonical 2026-05-08 14:44:58 +01:00
Peter Steinberger
d056715007 test: tighten gateway session id assertions 2026-05-08 14:41:41 +01:00
Peter Steinberger
1a34ef4516 test: tighten gateway id assertions 2026-05-08 14:39:02 +01:00
Peter Steinberger
ad52612008 test: tighten docs config task assertions 2026-05-08 14:37:25 +01:00
Peter Steinberger
2806e22caa test: tighten gateway logging string assertions 2026-05-08 14:35:32 +01:00
Peter Steinberger
a44021ce17 test: tighten plugin contract assertions 2026-05-08 14:33:24 +01:00
RenzoMXD
60f1b1f8d9 fix(gateway): preserve external Tailscale Funnel routes in serve mode
Adds opt-in `gateway.tailscale.preserveFunnel`. When `tailscale.mode = "serve"`
and an externally configured Tailscale Funnel route already covers the gateway
port, OpenClaw checks `tailscale funnel status --json` before re-applying
`tailscale serve` and skips both Serve and the `resetOnExit` teardown for that
run, preserving operator-managed Funnel exposure across gateway restarts.

The Funnel-status parser handles every documented Tailscale target scheme
(http, https, https+insecure) via an RFC 3986 scheme strip, plus loopback
hostnames (127.0.0.1, localhost, ::1) and bare-port forms. AllowFunnel-disabled
hosts and other-port routes are ignored.

Closes #57241.
2026-05-08 09:28:51 -04:00
Peter Steinberger
067ceb38b7 test: tighten session proxy assertions 2026-05-08 14:25:43 +01:00
Peter Steinberger
fa15090ead test: tighten core flow config assertions 2026-05-08 14:23:34 +01:00
Peter Steinberger
aefba95dba test: tighten extension shape assertions 2026-05-08 14:21:44 +01:00
Peter Steinberger
49f1f712d6 test: tighten telegram string assertions 2026-05-08 14:19:48 +01:00
Peter Steinberger
6da9e7e158 test: tighten mixed matcher helpers 2026-05-08 14:17:55 +01:00
Peter Steinberger
5457462e62 feat(discord): add realtime voice modes
Add Discord realtime voice modes with OpenAI realtime support, talk-buffer/bidi routing, per-turn speaker context enforcement, and lifecycle cleanup.
2026-05-08 09:16:04 -04:00
Peter Steinberger
a027444529 test: tighten irc discord string assertions 2026-05-08 14:15:38 +01:00
Peter Steinberger
0fad0a43ca test: tighten core timestamp assertions 2026-05-08 14:14:21 +01:00
Peter Steinberger
596aa452bf test: tighten ui controller assertions 2026-05-08 14:13:01 +01:00
Ayaan Zaidi
10bbed8a6d fix(telegram): chain over-limit stream previews 2026-05-08 18:41:49 +05:30
Peter Steinberger
c7cf34a955 test: tighten diffs artifact assertions 2026-05-08 14:11:26 +01:00
Peter Steinberger
190c07afe9 test: tighten generic matcher assertions 2026-05-08 14:09:53 +01:00
Super Zheng
e7277b4e3a refactor(agents): preserve raw reasoning stream and push formatting to edge (#78397)
Merged via squash.

Prepared head SHA: bb56f7ee00
Co-authored-by: medns <1575008+medns@users.noreply.github.com>
Co-authored-by: odysseus0 <8635094+odysseus0@users.noreply.github.com>
Reviewed-by: @odysseus0
2026-05-08 06:08:21 -07:00
Peter Steinberger
be28fdcb60 test: clarify live loose boolean assertions 2026-05-08 14:06:02 +01:00
Ayaan Zaidi
f2c813cb31 refactor(memory): simplify memory flush counter 2026-05-08 18:35:59 +05:30
Vincent Koc
731814ca7e fix(memory): preserve memory flush compaction count 2026-05-08 18:35:59 +05:30
Shakker
2340e2a581 test: stabilize interactive respawn assertion 2026-05-08 14:05:21 +01:00
Peter Steinberger
12aa508f98 test: clarify qa host env assertions 2026-05-08 14:03:01 +01:00
Ayaan Zaidi
30e079dd89 fix(channels): honor reasoning defaults in previews (#71817) (thanks @anagnorisis2peripeteia) 2026-05-08 18:32:04 +05:30
Peter Steinberger
5c589673ec test: clarify loose boolean assertions 2026-05-08 14:00:34 +01:00
Ayaan Zaidi
12e885da5f refactor(telegram): simplify inbound watch log formatting 2026-05-08 18:30:26 +05:30
Ruben Cuevas
227e252a58 docs: add Telegram changelog entry 2026-05-08 18:30:26 +05:30
Ruben Cuevas
4935ab1ff0 fix(telegram): log inbound gateway watch messages 2026-05-08 18:30:26 +05:30
Peter Steinberger
270421f3da test: clarify secrets audit findings 2026-05-08 13:57:08 +01:00
Peter Steinberger
bc720dedaf test: clarify boolean membership assertions 2026-05-08 13:54:10 +01:00
Peter Steinberger
81a34a260d test: remove oc-path no-op pitfall smoke 2026-05-08 13:51:21 +01:00
Ayaan Zaidi
67fa43d054 test(auto-reply): reuse duplicate dispatch helper 2026-05-08 18:21:17 +05:30
Ayaan Zaidi
21c33bed3b fix(telegram): preserve tool-only duplicate suppression 2026-05-08 18:21:17 +05:30
Peter Steinberger
a973e3199d test: clarify telegram qa assertions 2026-05-08 13:49:41 +01:00
Peter Steinberger
d3b47526bc test: clarify discord matrix assertions 2026-05-08 13:48:05 +01:00
Peter Steinberger
7e26b59f13 test: clarify nostr metrics assertions 2026-05-08 13:45:29 +01:00
Peter Steinberger
4708909dc2 test: clarify resilience test wording 2026-05-08 13:43:26 +01:00
Peter Steinberger
8ec92f544c test: clarify extension resilience test names 2026-05-08 13:41:40 +01:00
Peter Steinberger
7c8857be99 test: clarify core resilience test names 2026-05-08 13:39:18 +01:00
Ayaan Zaidi
013e1ac72f test(reply): cover native slash fast path 2026-05-08 18:08:40 +05:30
Ayaan Zaidi
ba91d477a2 fix(reply): fast-path native slash commands 2026-05-08 18:08:40 +05:30
Peter Steinberger
8221f0914a test: clarify small core accepted assertions 2026-05-08 13:37:09 +01:00
Peter Steinberger
961f99091d test: clarify stale pid cleanup assertions 2026-05-08 13:35:51 +01:00
Peter Steinberger
3708aad903 test: clarify infra accepted assertions 2026-05-08 13:34:40 +01:00
Peter Steinberger
20037285fb test: clarify oc-path resolver assertions 2026-05-08 13:33:19 +01:00
Peter Steinberger
4baf472285 test: clarify oc-path pitfalls assertions 2026-05-08 13:31:31 +01:00
Peter Steinberger
0905389ccf test: clarify oc-path malformed assertions 2026-05-08 13:30:20 +01:00
Peter Steinberger
aaca2342f8 test: clarify oc-path sentinel assertions 2026-05-08 13:28:51 +01:00
Peter Steinberger
472a7a6abd test: clarify gateway hook resilience assertions 2026-05-08 13:25:52 +01:00
Peter Steinberger
249e58b939 test: clarify tooling accepted assertions 2026-05-08 13:23:23 +01:00
Peter Steinberger
f40e3fe67e test: clarify extension resilience assertions 2026-05-08 13:20:40 +01:00
Peter Steinberger
f5e6108133 test: clarify browser cdp fuzz assertions 2026-05-08 13:17:30 +01:00
Peter Steinberger
2f001fc144 test: clarify memory fallback assertions 2026-05-08 13:14:50 +01:00
Peter Steinberger
59d86d65db test: clarify context pruning malformed assertions 2026-05-08 13:11:55 +01:00
Peter Steinberger
52b0d14825 test: clarify sandbox auth assertions 2026-05-08 13:10:00 +01:00
Panda Dev
d1bf0eb770 fix(fetch-timeout): pass operation and url context at omitting call sites (#79195) (#79253) 2026-05-08 22:09:45 +10:00
Peter Steinberger
210df889f0 test: clarify cron config task assertions 2026-05-08 13:08:22 +01:00
Peter Steinberger
d0f484d024 test: clarify runtime event assertions 2026-05-08 13:06:18 +01:00
Peter Steinberger
e6031fd03a test: clarify gateway auth probe assertions 2026-05-08 13:04:33 +01:00
Peter Steinberger
450b541d77 test: clarify extension auth assertions 2026-05-08 13:02:44 +01:00
Peter Steinberger
d16fff10c0 test: clarify ui gateway no throw assertions 2026-05-08 12:58:57 +01:00
Peter Steinberger
a4764091ce test: clarify infra cleanup assertions 2026-05-08 12:56:00 +01:00
Peter Steinberger
42c9bd59e7 test: clarify guard fallback assertions 2026-05-08 12:54:21 +01:00
Peter Steinberger
cd7f008688 test: clarify config schema accepted assertions 2026-05-08 12:52:36 +01:00
Peter Steinberger
d04002c7d9 test: clarify config preset schema assertions 2026-05-08 12:50:39 +01:00
Peter Steinberger
ea2799389a test: clarify proxy tui cli accepted paths 2026-05-08 12:47:48 +01:00
Peter Steinberger
390664c5bb test: clarify transcript event listener assertions 2026-05-08 12:45:58 +01:00
Peter Steinberger
b67bc04c43 test: clarify command queue reset assertions 2026-05-08 12:44:20 +01:00
Peter Steinberger
250eff0e4d test: clarify gateway http helper assertions 2026-05-08 12:42:19 +01:00
Peter Steinberger
79b88224e1 test: clarify plugin registry cleanup 2026-05-08 12:41:07 +01:00
Peter Steinberger
6dec8ee440 test: clarify archive path accepted paths 2026-05-08 12:39:42 +01:00
Peter Steinberger
933f092c98 test: clarify runtime guard accepted path 2026-05-08 12:38:05 +01:00
Peter Steinberger
bc0abcee74 test: clarify config env var assertions 2026-05-08 12:36:47 +01:00
Peter Steinberger
1d8659fdcb test: clarify cron store validator assertions 2026-05-08 12:35:30 +01:00
Peter Steinberger
604c73a489 test: clarify cron cli list output 2026-05-08 12:34:05 +01:00
Peter Steinberger
5517b82f78 test: clarify config infra accepted paths 2026-05-08 12:32:36 +01:00
Peter Steinberger
f0af64958c test: strengthen plugin registration assertions 2026-05-08 12:31:03 +01:00
Peter Steinberger
828de037ff test: clarify acpx runtime guard assertions 2026-05-08 12:28:52 +01:00
Peter Steinberger
8caef5d0ea test: clarify cron job accepted paths 2026-05-08 12:27:33 +01:00
Peter Steinberger
6abfb66aa5 test: clarify package spec validator assertions 2026-05-08 12:26:08 +01:00
Peter Steinberger
bfa0ee3b33 test: strengthen no-throw assertions 2026-05-08 12:24:43 +01:00
Peter Steinberger
79c1f1be48 test: remove weak no-throw wrappers 2026-05-08 12:22:55 +01:00
Peter Steinberger
ac3b3a04b8 test: replace truthy test assertions 2026-05-08 12:20:17 +01:00
Chencheng Li
15b39313cc fix: separate Current time from Reference UTC (#42654)
Merged via squash.

Prepared head SHA: 0829399ebd
Co-authored-by: chencheng-li <49442600+chencheng-li@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-05-08 14:19:28 +03:00
Peter Steinberger
52474c2d30 test: clarify live assertion lists 2026-05-08 12:18:13 +01:00
Peter Steinberger
fd3678a489 test: clarify plugin registry assertions 2026-05-08 12:16:27 +01:00
Peter Steinberger
fd2914f534 test: clarify plugin discovery assertions 2026-05-08 12:14:38 +01:00
Peter Steinberger
487c615c65 test: clarify ollama setup assertions 2026-05-08 12:13:24 +01:00
Peter Steinberger
ee935bb13b test: clarify telegram sticker cache assertions 2026-05-08 12:12:12 +01:00
Peter Steinberger
c54a70355f test: clarify oc-path scenario assertions 2026-05-08 12:10:54 +01:00
Peter Steinberger
82ef158403 test: clarify openresponses stream assertions 2026-05-08 12:07:16 +01:00
Peter Steinberger
9bd8ee054f test: clarify gateway session assertions 2026-05-08 12:05:50 +01:00
Peter Steinberger
feccd70b9d test: clarify memory wiki assertions 2026-05-08 12:03:52 +01:00
Peter Steinberger
d7853ed5b3 test: clarify signal and matrix assertions 2026-05-08 12:00:52 +01:00
Shakker
ae8b3de2d9 test: sync telegram release scenario assertion 2026-05-08 12:00:07 +01:00
RenzoMXD
8fb22fdfe2 fix(agents): compare file-target structurally not via fingerprint split
Address clawsweeper P2 on PR #79067: the prior cross-tool recovery
extracted the path target by splitting the joined fingerprint string
on `|`, which is also a legal character in file paths. A failed edit on
`/tmp/a|left` and a successful write to `/tmp/a|right` would both
extract as `path=/tmp/a` and incorrectly clear the prior failure.

Carry a structured `fileTarget: { path?, oldpath? }` alongside the
existing `actionFingerprint` string and compare it directly.
`extractFileTarget` reads args once at fingerprint-build time, with
the same alias support as `buildToolActionFingerprint`. The
fingerprint string is unchanged for diagnostics and the exact-equality
match path; only the cross-tool fallback now compares structurally.

Threaded through `ToolMutationState`, `ToolActionRef`, `ToolCallSummary`,
and `ToolErrorSummary` so the existing handler code at
`pi-embedded-subscribe.handlers.tools.ts:910-928` can populate and
consume it without re-parsing.

Adds delimiter-bearing-path regression test asserting that
`/tmp/a|left` vs `/tmp/a|right` returns false, and that an identical
delimiter-bearing path on both sides still matches.
2026-05-08 07:00:00 -04:00
RenzoMXD
3f4c64163d fix(agents): narrow self-heal recovery to edit↔write pair
Drop apply_patch from the file-mutating recovery set after clawsweeper
P2 review on PR #79067 noted production apply_patch calls only carry
opaque `input` patch text, so buildToolActionFingerprint never extracts
a `path=` segment from real call args. Including apply_patch only
matched handcrafted fingerprints in tests, not real recoveries, and
the public CHANGELOG claim was unimplemented.

Also drops the now-orphaned `oldpath` segment from
FILE_TARGET_FINGERPRINT_KEYS since edit and write do not produce it,
and replaces the apply_patch test expectation with an explicit
negative assertion that proves the narrowing.

Re-files apply_patch ↔ write recovery as a future enhancement; it
needs single-file patch-target extraction in
buildToolActionFingerprint to be honestly supportable.
2026-05-08 07:00:00 -04:00
RenzoMXD
0a7d9d7abe docs(changelog): credit @RenzoMXD on #79024 fix
Adds the Thanks attribution called out by clawsweeper P3 review on
PR #79067, keeping the bullet on a single line per repo policy.
2026-05-08 07:00:00 -04:00
RenzoMXD
79b292c2be fix(agents): self-heal cross-tool file-mutation in cron classifier
Recognize a successful file-mutation on the same path/oldpath target as
recovery for an earlier failed file-mutation, even when the tool name
differs (edit -> write, apply_patch -> write, etc). Previously
isSameToolMutationAction required exact fingerprint equality, which
includes tool=<name>, so an edit failure followed by a successful
write to the same path was never recognized as recovery. The unresolved
lastToolError then drove the cron classifier to flag a healthy
self-healed run as fatal with the user-visible warning prefix from
issue #79024. Limited to file-mutating tools (edit, write, apply_patch)
and the stable path/oldpath segments of the action fingerprint;
non-file-mutating tools and different paths still fail closed.

Fixes #79024.
2026-05-08 07:00:00 -04:00
Peter Steinberger
6389059632 test: clarify telegram send assertions 2026-05-08 11:59:17 +01:00
Peter Steinberger
7dc6a79905 test: clarify telegram command assertions 2026-05-08 11:57:22 +01:00
Shakker
2a8565ea67 test: restore matrix progress draft expectation 2026-05-08 11:56:52 +01:00
Peter Steinberger
054d0163dd test: clarify codex app-server assertions 2026-05-08 11:55:45 +01:00
Peter Steinberger
9905f2d13a test: clarify memory and slack assertions 2026-05-08 11:53:22 +01:00
Peter Steinberger
05fd67f822 test: clarify nvidia provider assertions 2026-05-08 11:51:58 +01:00
Peter Steinberger
7ebcce6a3d test: clarify qmd manager assertions 2026-05-08 11:50:46 +01:00
Peter Steinberger
774e8a7054 test: clarify memory core assertions 2026-05-08 11:49:00 +01:00
Peter Steinberger
b332f06e30 test: clarify google meet setup assertions 2026-05-08 11:47:49 +01:00
Peter Steinberger
607f0b4a9d test: clear remaining agent assertion scans 2026-05-08 11:46:22 +01:00
Peter Steinberger
07a850a5fb test: clarify websocket error assertions 2026-05-08 11:44:56 +01:00
Ayaan Zaidi
5e27993cbe docs(qa): document telegram e2e defaults 2026-05-08 16:14:42 +05:30
Ayaan Zaidi
5cd4996205 feat(qa-lab): list telegram live scenarios 2026-05-08 16:14:42 +05:30
Ayaan Zaidi
ec54642581 test(qa-lab): expand telegram e2e defaults 2026-05-08 16:14:42 +05:30
Ayaan Zaidi
0ff4ff4667 fix(qa-lab): harden mock telegram prompt routing 2026-05-08 16:14:42 +05:30
Shakker
d0402671c6 fix: make orphan attachment pruning deterministic 2026-05-08 11:43:17 +01:00
Peter Steinberger
90ba0f9690 test: clarify maintenance task assertions 2026-05-08 11:42:57 +01:00
Peter Steinberger
5760d7f38f test: clarify sandbox browser env assertion 2026-05-08 11:41:55 +01:00
Peter Steinberger
60b6b492e4 test: clarify openai transport assertions 2026-05-08 11:40:49 +01:00
Peter Steinberger
44268a134c test: clarify harness diagnostic assertions 2026-05-08 11:39:18 +01:00
Peter Steinberger
4624a1642f test: clarify bootstrap warning assertions 2026-05-08 11:38:16 +01:00
Peter Steinberger
4aa2fe45de test: clarify native hook relay retention assertion 2026-05-08 11:37:23 +01:00
Peter Steinberger
fddec6d8cd test: clarify abort listener cleanup assertion 2026-05-08 11:36:13 +01:00
Peter Steinberger
0c5f604fd6 test: clarify websocket stream assertions 2026-05-08 11:35:10 +01:00
Peter Steinberger
85587e17d7 test: clarify coding tool content assertions 2026-05-08 11:33:54 +01:00
Shakker
baffa57c00 revert: restore progress draft behavior 2026-05-08 11:33:08 +01:00
Peter Steinberger
ee495603d1 test: clarify coding tool name assertions 2026-05-08 11:31:46 +01:00
clawsweeper
48c24c86c9 test: cover download parent symlink race 2026-05-08 20:31:43 +10:00
jesse-merhi
c71dfb6f52 test: cover download parent symlink race 2026-05-08 20:31:43 +10:00
Peter Steinberger
c2927e6d87 test: clarify script preflight flag assertion 2026-05-08 11:30:00 +01:00
Peter Steinberger
fecddcabd7 test: clarify sessions send gateway assertion 2026-05-08 11:28:29 +01:00
Peter Steinberger
97d7dd9add test: clarify sessions tool call assertions 2026-05-08 11:27:09 +01:00
Peter Steinberger
c2b2a4cdf4 test: clarify read only channel plugin assertions 2026-05-08 11:26:06 +01:00
Shakker
2aa6d6ba14 test: assert discord voice staging output 2026-05-08 11:25:16 +01:00
Peter Steinberger
3c6dd9fcb2 test: clarify final tag payload assertion 2026-05-08 11:24:02 +01:00
Shakker
acb3b09e2a fix: keep progress draft labels visible 2026-05-08 11:23:59 +01:00
Peter Steinberger
036c432101 test: clarify transcript repair assertion 2026-05-08 11:22:57 +01:00
Peter Steinberger
8b57d0fe9e test: clarify update cli exit assertions 2026-05-08 11:21:56 +01:00
Peter Steinberger
767dbe469e test: clarify subscribe media assertions 2026-05-08 11:20:24 +01:00
Peter Steinberger
b38c78fe63 test: clarify plugin loader channel assertions 2026-05-08 11:19:17 +01:00
Peter Steinberger
a31f4c57e5 fix: normalize Gemini auth config patches 2026-05-08 11:17:54 +01:00
Peter Steinberger
e8d63b8bd0 test: clarify update plan tool assertions 2026-05-08 11:13:36 +01:00
Shakker
150b869cf8 fix: set tts conversion output formats 2026-05-08 11:12:25 +01:00
Shakker
e1e9cd82c1 test: add codex media session id 2026-05-08 11:11:31 +01:00
Peter Steinberger
3a5d39688c test: clarify bootstrap file assertions 2026-05-08 11:10:54 +01:00
Shakker
665d823237 fix: restore rolling progress labels 2026-05-08 11:10:16 +01:00
Peter Steinberger
378cfe2da2 test: clarify cli media error assertion 2026-05-08 11:08:58 +01:00
Peter Steinberger
5099e4712e test: clarify daemon launchd signal assertion 2026-05-08 11:07:39 +01:00
Peter Steinberger
12487509c8 test: clarify config cli error assertions 2026-05-08 11:05:56 +01:00
Peter Steinberger
eaaef2dbf8 test: clarify plugin sdk assertions 2026-05-08 11:04:19 +01:00
Shakker
039269c738 test: align startup runtime policy assertions 2026-05-08 11:02:51 +01:00
Peter Steinberger
751d47188c test: clarify bundled command assertion 2026-05-08 11:01:43 +01:00
Peter Steinberger
d11fb85152 test: clarify auto reply chunk assertion 2026-05-08 11:00:23 +01:00
Shakker
c55fa0ace7 test: assert fallback cooldown suspension 2026-05-08 10:59:28 +01:00
Peter Steinberger
dd271968df test: clarify docker setup line assertions 2026-05-08 10:58:51 +01:00
Shakker
0dc6d3de9f test: assert cron protocol fixtures 2026-05-08 10:58:24 +01:00
Peter Steinberger
e132e3a539 test: clarify daemon path assertion 2026-05-08 10:57:27 +01:00
Peter Steinberger
cf30d620f4 test: clarify acp runtime mode assertion 2026-05-08 10:56:15 +01:00
Shakker
09e471f32e test: assert bundled sdk import guards 2026-05-08 10:55:24 +01:00
Peter Steinberger
0faa729eec test: clarify wizard note assertions 2026-05-08 10:55:00 +01:00
Shakker
1e6a674cfa test: assert teams bot framework audience 2026-05-08 10:54:16 +01:00
Shakker
8159efadf7 test: assert memory watcher concrete paths 2026-05-08 10:53:14 +01:00
Peter Steinberger
0ae3c84790 test: clarify command e2e assertions 2026-05-08 10:52:57 +01:00
Peter Steinberger
0da9f7e88d test: clarify delivery recovery retry assertion 2026-05-08 10:50:30 +01:00
Shakker
2175a0fa66 test: assert crestodian rescue audit entry 2026-05-08 10:49:18 +01:00
Peter Steinberger
0ddfaff5a4 test: clarify plugin state probe assertions 2026-05-08 10:49:01 +01:00
Peter Steinberger
d21a9cf4f0 test: clarify table wrapping assertion 2026-05-08 10:47:56 +01:00
Shakker
06d34c5e5f test: assert sandbox mutation helper script 2026-05-08 10:47:31 +01:00
Shakker
52b7e8598b test: assert active memory debug logs 2026-05-08 10:46:49 +01:00
Peter Steinberger
66ffac40e7 test: clarify backup archive assertions 2026-05-08 10:46:32 +01:00
Peter Steinberger
3de1de8bb8 test: clarify doctor state archive assertions 2026-05-08 10:45:25 +01:00
Shakker
82aef467b3 test: assert matrix sas notice messages 2026-05-08 10:45:10 +01:00
Shakker
9c471637d1 test: assert matrix group history messages 2026-05-08 10:44:26 +01:00
Peter Steinberger
d929aa6cf1 test: clarify session pruning archive assertions 2026-05-08 10:43:55 +01:00
Shakker
427542532c test: assert pi error payload suppression 2026-05-08 10:43:33 +01:00
NVIDIAN
263469f696 fix(cli): canonicalize infer model refs safely (#78940)
* fix(cli): canonicalize infer model refs safely

* docs: add changelog entry for infer model ref canonicalization

---------

Co-authored-by: Mason Huang <masonxhuang@tencent.com>
2026-05-08 17:43:22 +08:00
Shakker
f94ca14364 test: assert pi tool policy warnings 2026-05-08 10:42:58 +01:00
Peter Steinberger
4213d8f4d9 test: clarify cron session reaper assertion 2026-05-08 10:42:46 +01:00
Shakker
3dfe70b8f8 test: assert npm spec warning suppression 2026-05-08 10:42:22 +01:00
Shakker
a40ef6691e test: assert plugin install scanner warnings 2026-05-08 10:41:53 +01:00
Peter Steinberger
3cf101ff8b test: clarify cron regression job assertion 2026-05-08 10:41:28 +01:00
Shakker
3299e10ee9 test: assert plugin path scan warnings 2026-05-08 10:40:57 +01:00
Shakker
d2d4728340 test: assert plugin discovery safety diagnostics 2026-05-08 10:40:27 +01:00
Shakker
bc5a4bdb47 test: assert plugin manifest diagnostics 2026-05-08 10:39:58 +01:00
Peter Steinberger
da770059ae test: clarify gateway status target assertion 2026-05-08 10:39:35 +01:00
Shakker
e978ec6ff7 test: assert plugin loader diagnostics 2026-05-08 10:39:20 +01:00
Shakker
318058a24b test: assert acp parent stream relay messages 2026-05-08 10:38:51 +01:00
Shakker
2ef84a9fc4 test: assert acp stream logging contracts 2026-05-08 10:38:14 +01:00
Peter Steinberger
c4413e30f9 test: clarify heartbeat scheduler assertions 2026-05-08 10:37:54 +01:00
Shakker
d760bf87f0 test: assert config secret resolvability errors 2026-05-08 10:37:43 +01:00
Shakker
5b9f94baae test: assert update restart message suppression 2026-05-08 10:37:15 +01:00
Shakker
2d84fd749e test: clarify gateway cron event assertion 2026-05-08 10:36:40 +01:00
Shakker
d52aad4cf2 test: clarify gateway hook event assertions 2026-05-08 10:36:13 +01:00
Peter Steinberger
2790549fc6 test: clarify update runner command assertions 2026-05-08 10:35:51 +01:00
Shakker
8441c64434 test: clarify gateway reload event assertions 2026-05-08 10:35:39 +01:00
Shakker
1e5d0a205a test: clarify session transcript candidate assertion 2026-05-08 10:35:07 +01:00
Shakker
7875c1a6c1 test: clarify memory wiki session filters 2026-05-08 10:34:40 +01:00
Shakker
efd795e98a test: clarify telegram status issue assertions 2026-05-08 10:34:12 +01:00
Shakker
45d0efad23 test: clarify ollama setup fetch assertions 2026-05-08 10:33:39 +01:00
Shakker
a2ef6ff8b8 test: clarify doctor config warning assertions 2026-05-08 10:33:12 +01:00
Peter Steinberger
419b6e8993 test: clarify legacy migration change assertions 2026-05-08 10:32:10 +01:00
Shakker
3f1e422859 test: clarify status output assertions 2026-05-08 10:32:02 +01:00
Val Alexander
84fe3c5409 fix(daemon): include homebrew paths in launchagent env (#79331) 2026-05-08 04:31:30 -05:00
Shakker
9ca5e4aaa9 test: clarify doctor default account assertions 2026-05-08 10:31:25 +01:00
Shakker
d32ff05090 test: clarify health snapshot probe assertions 2026-05-08 10:30:59 +01:00
Peter Steinberger
d150d8c053 test: clarify port diagnostics assertions 2026-05-08 10:30:44 +01:00
Shakker
5fbbfa97aa test: clarify doctor state integrity assertions 2026-05-08 10:30:29 +01:00
Shakker
838565fe59 test: clarify update runner command assertions 2026-05-08 10:29:55 +01:00
Shakker
b6a6580db3 test: clarify nostr profile http assertion 2026-05-08 10:29:25 +01:00
Shakker
c0921c2f24 test: clarify nostr profile validation assertions 2026-05-08 10:29:01 +01:00
Shakker
4fd9d0e44d test: clarify google oauth fallback assertion 2026-05-08 10:28:36 +01:00
Shakker
281318e3da test: clarify slack external menu assertion 2026-05-08 10:28:10 +01:00
Peter Steinberger
8282d21d35 test: dedupe sessions cleanup log assertions 2026-05-08 10:27:49 +01:00
Shakker
da6231a84e test: clarify discord model picker nav assertions 2026-05-08 10:27:35 +01:00
Peter Steinberger
6a9f10eb88 test: clarify channel streaming labels 2026-05-08 10:25:51 +01:00
Shakker
7bb89f915b test: clarify discord startup log assertions 2026-05-08 10:25:28 +01:00
Shakker
663c9700e4 test: clarify config cli dry run assertion 2026-05-08 10:24:16 +01:00
Shakker
2bf3c1d387 test: clarify logs cli reconnect assertions 2026-05-08 10:23:44 +01:00
Shakker
f46fec4f4c test: clarify skills cli log assertions 2026-05-08 10:23:23 +01:00
Peter Steinberger
b5453bb1b7 test: clarify cron scheduler delay assertions 2026-05-08 10:23:08 +01:00
Shakker
3d70ffa596 test: clarify update cli completion warning assertions 2026-05-08 10:23:01 +01:00
Shakker
856a0b135e test: clarify plugin update restart assertions 2026-05-08 10:22:15 +01:00
Shakker
779122d761 test: clarify plugin install persist cache assertion 2026-05-08 10:21:55 +01:00
Peter Steinberger
2c0dac5851 test: dedupe trajectory export event assertions 2026-05-08 10:21:49 +01:00
Shakker
16cdf85a05 test: clarify plugin install persist warning assertion 2026-05-08 10:21:16 +01:00
Shakker
b0966f5356 test: clarify plugin uninstall log assertions 2026-05-08 10:20:50 +01:00
Shakker
f82d842335 test: clarify plugin install log assertions 2026-05-08 10:20:22 +01:00
Peter Steinberger
bd72cc4aa5 test: clarify gateway stability event assertions 2026-05-08 10:19:58 +01:00
Peter Steinberger
3b626e4e36 test: clarify exec approval broadcast assertion 2026-05-08 10:18:16 +01:00
Peter Steinberger
b16bcda63a test: clarify gateway command list assertions 2026-05-08 10:17:12 +01:00
Peter Steinberger
d7f2c3d344 test: clarify daemon install warning assertion 2026-05-08 10:16:05 +01:00
Peter Steinberger
8df998e55e test: dedupe cron cli log assertions 2026-05-08 10:15:07 +01:00
Peter Steinberger
aa6160c1db test: clarify secrets cli skipped notes 2026-05-08 10:14:08 +01:00
Peter Steinberger
5b002b0428 test: clarify agent skill assertions 2026-05-08 10:12:45 +01:00
Peter Steinberger
f91da88ed7 test: clarify gateway pricing timer assertion 2026-05-08 10:11:53 +01:00
Shakker
49e307a64d test: clarify mantis staged video assertion 2026-05-08 10:11:49 +01:00
Val Alexander
f6a5405658 fix(macos): guard config writer fallback
Guard macOS config writes so stale or destructive fallback payloads cannot silently remove gateway.mode, metadata, or auth and trigger gateway restore churn.

Verification:
- swift test --package-path apps/macos --filter OpenClawConfigFileTests
- swift test --package-path apps/macos --filter AppStateRemoteConfigTests
- swift test --package-path apps/macos --filter ConfigStoreTests
- pnpm lint:swift
- git diff --check origin/main..HEAD
- Blacksmith Testbox pnpm check:changed: blocked by missing swiftlint in the Linux Testbox image after reaching apps lane
2026-05-08 04:11:28 -05:00
Peter Steinberger
2d1f4f909e fix: normalize retired gemini preview ids 2026-05-08 10:10:41 +01:00
tmimmanuel
b78295b4dd fix(ui): hide sender metadata in control chat (#78790)
Summary:
- Strip untrusted sender metadata from Control UI live stream and transcript rendering.
- Preserve canvas preview anchors while suppressing metadata-only render items.
- Stop operator UI clients from injecting internal client IDs as sender identity while preserving external channel attribution.

Verification:
- pnpm exec oxfmt --check --threads=1 CHANGELOG.md ui/src/ui/chat/build-chat-items.ts ui/src/ui/chat/build-chat-items.test.ts ui/src/ui/chat/message-normalizer.ts ui/src/ui/chat/message-normalizer.test.ts src/gateway/server-methods/chat.ts src/gateway/server-methods/chat.directive-tags.test.ts
- pnpm check:changelog-attributions
- git diff --check
- pnpm test ui/src/ui/chat/build-chat-items.test.ts ui/src/ui/chat/message-normalizer.test.ts -- --reporter=verbose
- pnpm test src/gateway/server-methods/chat.directive-tags.test.ts -- --reporter=verbose -t 'operator UI client sender context'
- GitHub PR checks green on a67ab34fbe

Fixes #78739.
Thanks @tmimmanuel, @guguangxin-eng, @hclsys, and @BunsDev.
2026-05-08 04:10:21 -05:00
Shakker
d1a482ba0b test: clarify qqbot stt guarded fetch 2026-05-08 10:09:18 +01:00
Peter Steinberger
695d4ccd1b test: clarify gateway tools catalog server assertions 2026-05-08 10:07:11 +01:00
Peter Steinberger
b417a100f9 test: clarify daemon cli json actions 2026-05-08 10:05:25 +01:00
Peter Steinberger
20316cc079 test: clarify capability cli list assertion 2026-05-08 10:03:28 +01:00
Peter Steinberger
033c02bbf6 test: clarify context pruning image assertion 2026-05-08 10:02:01 +01:00
Peter Steinberger
3bae07cb75 test: clarify bootstrap diagnostic assertion 2026-05-08 10:00:53 +01:00
Shakker
2c498e66fe test: clarify telegram reply chain assertions 2026-05-08 10:00:45 +01:00
Peter Steinberger
d42ae2536e test: clarify channels status error assertion 2026-05-08 09:59:22 +01:00
Peter Steinberger
8fa6f9a28b test: clarify message target scope assertion 2026-05-08 09:57:35 +01:00
Peter Steinberger
8a17aeb7cc test: clarify model status provider assertions 2026-05-08 09:56:24 +01:00
Peter Steinberger
47caafc464 test: clarify migration selection statuses 2026-05-08 09:55:19 +01:00
Shakker
43d095b6ff test: restore request animation frame cleanup 2026-05-08 09:55:05 +01:00
Peter Steinberger
7adadbdda6 test: clarify onboard search notes 2026-05-08 09:54:18 +01:00
Peter Steinberger
29a393d540 test: clarify doctor workspace note assertion 2026-05-08 09:53:04 +01:00
Peter Steinberger
88166ad840 test: clarify gateway install token warnings 2026-05-08 09:52:05 +01:00
Shakker
9dde80eae2 test: clarify node exec fallback plan assertions 2026-05-08 09:51:22 +01:00
Peter Steinberger
9e8a6355bf test: clarify agents prune assertions 2026-05-08 09:50:14 +01:00
Peter Steinberger
aca43b29e1 test: clarify command diagnostic assertions 2026-05-08 09:48:47 +01:00
Peter Steinberger
0baa9a93e7 test: clarify auth choice option assertions 2026-05-08 09:47:24 +01:00
Shakker
9ae982f486 test: clarify browser download output assertions 2026-05-08 09:45:28 +01:00
Peter Steinberger
53824a0cbf test: clarify gateway tools catalog assertions 2026-05-08 09:45:10 +01:00
Shakker
08337a1177 test: clarify staged media output assertions 2026-05-08 09:44:00 +01:00
Peter Steinberger
4be63a9e8f test: clarify tool image log assertions 2026-05-08 09:43:36 +01:00
Peter Steinberger
76b09fbc68 test: clarify cli secret target scope assertions 2026-05-08 09:42:07 +01:00
Shakker
951897c45c test: clarify harness runtime policy assertions 2026-05-08 09:40:54 +01:00
Peter Steinberger
b06f0abe57 test: clarify gateway session thinking assertions 2026-05-08 09:40:29 +01:00
Peter Steinberger
9094c801ce test: clarify backup workspace asset assertion 2026-05-08 09:38:37 +01:00
Peter Steinberger
f00e09c34b test: clarify model picker router assertions 2026-05-08 09:36:48 +01:00
Peter Steinberger
404353ad4f test: clarify opencode thinking level assertions 2026-05-08 09:35:45 +01:00
Shakker
ea5116089c test: clarify acp live streaming assertions 2026-05-08 09:35:03 +01:00
Peter Steinberger
0242d3e50d test: clarify tsdown graph assertions 2026-05-08 09:34:24 +01:00
Peter Steinberger
911d4555cb test: clarify update package manager path assertion 2026-05-08 09:33:17 +01:00
Peter Steinberger
4fd85c5ee5 test: clarify command analysis warning assertion 2026-05-08 09:32:01 +01:00
Peter Steinberger
5fccaa1e32 test: clarify gateway exposure audit assertions 2026-05-08 09:30:48 +01:00
Peter Steinberger
4b8717f14e test: clarify sandbox browser audit assertion 2026-05-08 09:29:28 +01:00
Peter Steinberger
d84239c0fc test: clarify bonjour discovery command assertions 2026-05-08 09:28:20 +01:00
Peter Steinberger
a5e9b205ac test: clarify system presence pruning assertions 2026-05-08 09:27:13 +01:00
Peter Steinberger
eff631e269 test: clarify plugin snapshot stale index assertions 2026-05-08 09:26:03 +01:00
Peter Steinberger
973adb0fe1 test: clarify infra offender assertions 2026-05-08 09:24:10 +01:00
Peter Steinberger
d1630ced14 test: clarify markdown assertion lists 2026-05-08 09:22:56 +01:00
Peter Steinberger
ba675d8964 test: clarify secrets warning assertion 2026-05-08 09:21:23 +01:00
Peter Steinberger
84212d58b8 test: clarify skill scanner assertions 2026-05-08 09:19:53 +01:00
Peter Steinberger
af8cf11e19 test: clarify security scanner assertions 2026-05-08 09:18:33 +01:00
Peter Steinberger
a8dcbb26f8 test: clarify security audit assertions 2026-05-08 09:17:15 +01:00
Peter Steinberger
f9812e6cba test: clarify tui list assertions 2026-05-08 09:16:07 +01:00
Peter Steinberger
1aa9f6d3e1 test: clarify qa lab server assertions 2026-05-08 09:14:38 +01:00
Peter Steinberger
a1244d6108 test: clarify qa browser runtime env assertion 2026-05-08 09:12:46 +01:00
Peter Steinberger
3e49a00555 test: clarify config legacy issue assertions 2026-05-08 09:11:03 +01:00
Peter Steinberger
c94641c08b test: clarify launchd command assertions 2026-05-08 09:09:16 +01:00
Peter Steinberger
a6bbcd0a01 test: clarify config pdf limit assertion 2026-05-08 09:07:27 +01:00
Peter Steinberger
5989a9ad60 test: clarify config io assertions 2026-05-08 09:06:21 +01:00
Peter Steinberger
5bb23c2f95 test: clarify qa parity failure assertion 2026-05-08 09:05:03 +01:00
Peter Steinberger
f992dd61f1 test: clarify qa whatsapp boundary assertion 2026-05-08 09:03:59 +01:00
Peter Steinberger
544c0468c1 test: clarify qa bus search assertions 2026-05-08 09:02:30 +01:00
Peter Steinberger
69c1487e0b test: clarify feishu streaming status assertions 2026-05-08 09:01:08 +01:00
scoootscooob
09f83bfec0 fix(compaction): preserve tail for empty manual compact
Manual /compact now preserves Pi's recent tail when the compaction input has no summarizable messages or yields an empty summary, avoiding an empty checkpoint that drops live context.

Verification:
- pnpm test src/agents/pi-embedded-runner/manual-compaction-boundary.test.ts -- --reporter=verbose
- pnpm exec oxfmt --check --threads=1 src/agents/pi-embedded-runner/manual-compaction-boundary.ts src/agents/pi-embedded-runner/manual-compaction-boundary.test.ts
- git diff --check -- src/agents/pi-embedded-runner/manual-compaction-boundary.ts src/agents/pi-embedded-runner/manual-compaction-boundary.test.ts CHANGELOG.md
- Local gateway proof in PR body: real sessions.compact preserved the recent tail while the provider saw an empty conversation.

Note: checks-node-auto-reply-reply-dispatch is already failing on upstream/main with the same four dispatch-from-config.test.ts assertions; this PR only touches compaction boundary files.
2026-05-08 01:00:20 -07:00
Peter Steinberger
94ceddc481 test: clarify config schema child assertion 2026-05-08 08:59:42 +01:00
Peter Steinberger
2c7c57d519 test: clarify feishu validation assertions 2026-05-08 08:58:25 +01:00
Peter Steinberger
29689c62d0 test: clarify bootstrap extra path assertion 2026-05-08 08:56:51 +01:00
Peter Steinberger
9730be1bba test: reuse daemon service audit helper 2026-05-08 08:55:31 +01:00
Peter Steinberger
9bcfc93ada test: clarify qa scenario catalog assertions 2026-05-08 08:53:40 +01:00
Peter Steinberger
c2ffe1fd04 test: remove redundant service path assertions 2026-05-08 08:51:51 +01:00
Peter Steinberger
1ae3e5b527 test: clarify hook workspace assertions 2026-05-08 08:50:33 +01:00
Ayu
e63e4f9551 fix(docker): run runtime image under tini (#78777)
Run the Docker runtime image under tini so long-lived containers reap orphaned child processes and forward signals correctly.

Thanks @VintageAyu!
2026-05-08 13:19:55 +05:30
Peter Steinberger
fb66a101e2 test: clarify config validation path assertions 2026-05-08 08:49:19 +01:00
Peter Steinberger
6a2c67d314 test: clarify proxy capture assertions 2026-05-08 08:47:30 +01:00
Peter Steinberger
f64915c564 test: clarify feishu mention merge assertions 2026-05-08 08:46:22 +01:00
Peter Steinberger
279aa7f7b8 test: remove redundant web boundary assertion 2026-05-08 08:44:42 +01:00
Peter Steinberger
2e816710ed fix: remove telegram cache redundant spread 2026-05-08 08:43:51 +01:00
Peter Steinberger
b55dfd53b4 test: clarify browser doctor warning assertions 2026-05-08 08:43:51 +01:00
Rob Riggs
0ef1f36286 feat(bedrock): add service_tier parameter support
- Add resolveBedrockServiceTier() and createBedrockServiceTierWrapper()
  to bedrock-stream-wrappers.ts
- Export service tier functions from provider-stream-shared.ts SDK barrel
- Wire service tier into Bedrock provider wrapStreamFn
- Accepts serviceTier or service_tier via agents.defaults.params

Valid values: default, flex, priority, reserved

Authored by Deepseek-v4-Pro, reviewed by rob@mobilinkd.com.
2026-05-08 13:10:43 +05:30
Peter Steinberger
a3e48fd259 test: clarify qa coverage inventory assertions 2026-05-08 08:39:52 +01:00
Ayaan Zaidi
8e94689add refactor(telegram): distill reply chain hydration 2026-05-08 13:08:46 +05:30
Ayaan Zaidi
a7cd93ec4d fix(telegram): share persisted reply cache buckets 2026-05-08 13:08:46 +05:30
Ayaan Zaidi
ac75d6f76e fix(reply): render hydrated reply chain in inbound prompt 2026-05-08 13:08:46 +05:30
Ayaan Zaidi
99850d17ad docs(telegram): document reply-chain cache 2026-05-08 13:08:46 +05:30
Ayaan Zaidi
45928ef298 fix(telegram): hydrate inbound reply chains 2026-05-08 13:08:46 +05:30
Ayaan Zaidi
3c4b482fc5 feat(telegram): persist observed message cache 2026-05-08 13:08:46 +05:30
Ayaan Zaidi
c307a61264 feat(reply): add reply-chain prompt context 2026-05-08 13:08:46 +05:30
Peter Steinberger
1a99690e99 test: clarify telegram chunk assertions 2026-05-08 08:38:19 +01:00
Peter Steinberger
f4f0d8569c fix: normalize legacy gemini cli model refs 2026-05-08 08:36:21 +01:00
Peter Steinberger
d8d441cd49 test: clarify synology security warning assertions 2026-05-08 08:28:04 +01:00
Peter Steinberger
f45b65c9c3 test: clarify matrix idb database assertion 2026-05-08 08:26:21 +01:00
Peter Steinberger
7468e071dd test: clarify dreaming diary label assertion 2026-05-08 08:24:17 +01:00
Peter Steinberger
d22dccdf93 test: clarify channel config schema issue assertions 2026-05-08 08:23:02 +01:00
Peter Steinberger
6a20bbd166 test: clarify provider thinking level assertions 2026-05-08 08:21:47 +01:00
Peter Steinberger
8ced077f62 test: clarify slack chunk length assertions 2026-05-08 08:20:26 +01:00
Peter Steinberger
c1c3e79a9d test: clarify control ui performance event assertion 2026-05-08 08:18:18 +01:00
Peter Steinberger
3e53b19284 test: clarify browser client endpoint assertions 2026-05-08 08:17:08 +01:00
Peter Steinberger
5bdec9112b test: clarify telegram reserved command assertion 2026-05-08 08:15:47 +01:00
Shakker
074dbc3bee docs: note durable acp telegram replies 2026-05-08 08:14:29 +01:00
Shakker
511f42d8a3 fix: keep acp telegram replies durable 2026-05-08 08:14:29 +01:00
Shakker
d2cd9badd9 perf: avoid sorting session lookup paths 2026-05-08 08:14:29 +01:00
Shakker
7d4011862a perf: bound compaction contributor selection 2026-05-08 08:14:29 +01:00
Shakker
75fca35d38 perf: bound plugin and doctor selections 2026-05-08 08:14:29 +01:00
Shakker
b9791e347c perf: avoid sorting runtime selections 2026-05-08 08:14:29 +01:00
Peter Steinberger
43345b43b7 test: clarify discord async status assertion 2026-05-08 08:14:07 +01:00
zucchini
3adbbe7c34 fix(plugins): dispatch cached tools by runtime name (#78716)
Fix cached descriptor-backed plugin tool dispatch for unnamed factories sharing manifest contracts.

Thanks @zanni098!
2026-05-08 12:44:01 +05:30
scotthuang
37af50f3db fix(browser): keep user tabs open on SSRF-denied reads (#78874)
Summary:
- Split browser SSRF quarantine from tab closure so read-only browser operations do not close user-owned tabs on policy denial.
- Keep OpenClaw-initiated navigation/create paths closing blocked tabs, and add regression coverage for both contracts.
- Update changelog with contributor credit.

Verification:
- pnpm test extensions/browser/src/browser/pw-session.assert-navigation-safety.test.ts extensions/browser/src/browser/pw-tools-core.snapshot.navigate-guard.test.ts
- pnpm test extensions/browser/src/browser/pw-tools-core.browser-ssrf-guard.test.ts extensions/browser/src/browser/pw-tools-core.snapshot.test.ts
- Exact-head CI success: 25535578610
- Exact-head Real behavior proof success: 25536652326

Thanks @scotthuang.
2026-05-08 08:13:04 +01:00
Peter Steinberger
d2cb0b0528 test: remove redundant lmstudio stream assertion 2026-05-08 08:12:46 +01:00
Super Zheng
b96ac7105d perf(agents): skip idle wait on abort to release session lock synchronously (#74919)
Merged via squash.

Prepared head SHA: 0af4c4685f
Co-authored-by: medns <1575008+medns@users.noreply.github.com>
Co-authored-by: odysseus0 <8635094+odysseus0@users.noreply.github.com>
Reviewed-by: @odysseus0
2026-05-08 00:12:42 -07:00
Peter Steinberger
a92a349925 test: clarify chat canvas block assertions 2026-05-08 08:10:39 +01:00
Peter Steinberger
10eb02fc8e test: clarify sessions option assertions 2026-05-08 08:08:26 +01:00
Peter Steinberger
d16657e921 test: clarify slash command browser import assertion 2026-05-08 08:06:57 +01:00
pashpashpash
02fe0d8978 Keep OpenAI Codex migrations on automatic runtime routing (#79238)
* fix: keep migrated openai codex routes automatic

* scope runtime policy to providers and models

* fix runtime policy surfaces

* fix ci runtime policy checks

* fix doctor stale session runtime pins
2026-05-08 16:05:35 +09:00
Peter Steinberger
b7aca7dc6e test: clarify usage helper warning assertions 2026-05-08 08:05:01 +01:00
Peter Steinberger
2d1ef7b6b4 test: clarify channel config save request assertion 2026-05-08 08:03:31 +01:00
Peter Steinberger
7b5d6cfb92 test: clarify msteams attachment url assertions 2026-05-08 08:02:20 +01:00
Peter Steinberger
27fc627f6e test: clarify zalouser chunk length assertion 2026-05-08 08:00:18 +01:00
Peter Steinberger
1eb60b8894 test: clarify mattermost websocket patch assertion 2026-05-08 07:58:56 +01:00
Peter Steinberger
e35d4a9e41 test: clarify mattermost model picker ids 2026-05-08 07:57:48 +01:00
Peter Steinberger
b01889c00d test: clarify google meet export mime assertions 2026-05-08 07:55:39 +01:00
Peter Steinberger
fc31e86e54 test: clarify irc chunk length assertion 2026-05-08 07:54:36 +01:00
Peter Steinberger
af49c09d13 test: clarify kilocode model catalog assertions 2026-05-08 07:53:39 +01:00
Brandon
2d65908f7f fix(update): pipe post-core child stdio on Windows (#78483)
Fixes #78445.

- Use piped stdio for the post-core update child on Windows so the child and descendants do not inherit the parent console handles.
- Relay child stdout/stderr back to the parent when piped so update output remains visible.
- Keep non-Windows behavior on inherited stdio.
- Add focused coverage for the stdio resolver.

Verification:
- `pnpm vitest run src/cli/update-cli/update-command.test.ts`
- `pnpm build`
- `pnpm exec oxlint src/cli/update-cli/update-command.ts src/cli/update-cli/update-command.test.ts`
- Full GitHub CI green at `321608e00ba118421ea65124f494458ed229defd`.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 01:52:28 -05:00
Peter Steinberger
5604cbd3ef test: clarify voice call webhook concurrency assertions 2026-05-08 07:52:16 +01:00
Brad Groux
2bd4529dfd fix(shell-env): hide Windows login shell probe (#78266)
Fixes #78159.

- Add `windowsHide: true` to the login-shell env probe used by shell-env fallback on Windows.
- Cover the fallback and trusted-shell paths with focused tests.
- Add the changelog attribution for #78266.

Verification:
- `pnpm vitest run src/infra/shell-env.test.ts`
- `pnpm build`
- `pnpm check`
- Full GitHub CI green at `deb6ffbd3c203fc52f5b320fe5ca5aafa11ade57`.
2026-05-08 01:51:40 -05:00
Peter Steinberger
30817c09e9 test: clarify voice call talk event waits 2026-05-08 07:51:07 +01:00
Peter Steinberger
1ae4db279c test: clarify foundry refresh rejection assertion 2026-05-08 07:49:58 +01:00
Peter Steinberger
b91277381f test: clarify scoped vitest exclude assertions 2026-05-08 07:47:20 +01:00
Peter Steinberger
3b254b4d36 test: clarify channel registry id assertion 2026-05-08 07:45:51 +01:00
Peter Steinberger
b5533734ba test: clarify deepinfra model catalog assertions 2026-05-08 07:42:50 +01:00
Peter Steinberger
05f117aae2 test: clarify unit fast forced routing assertion 2026-05-08 07:41:09 +01:00
Peter Steinberger
6bb3678fd9 test: clarify plugin extension boundary assertions 2026-05-08 07:39:54 +01:00
Jesse Merhi
297a164536 Highlight exec command risks in Web approvals (#77153)
Summary:
- Adds parser-derived exec approval command-span metadata through host registration, gateway validation, generated Swift models, Control UI parsing/rendering, tests, and changelog.
- Reproducibility: not applicable. this is a feature PR rather than a bug report. The before/after behavior is ... rom current main’s plain command rendering to PR-head span generation, validation, and Web rendering tests.

Automerge notes:
- PR branch already contained follow-up commit before automerge: refactor: use neutral exec command spans
- PR branch already contained follow-up commit before automerge: refactor: simplify exec command span extraction
- PR branch already contained follow-up commit before automerge: refactor: inline approval command span params
- PR branch already contained follow-up commit before automerge: fix: keep exec approval spans lazy
- PR branch already contained follow-up commit before automerge: build: refresh exec approval protocol models
- PR branch already contained follow-up commit before automerge: Highlight exec command risks in Web approvals

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

Prepared head SHA: 8d9977eb53
Review: https://github.com/openclaw/openclaw/pull/77153#issuecomment-4368769228

Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
2026-05-08 06:38:41 +00:00
Peter Steinberger
132bcebe41 fix: keep gemini config normalization acyclic 2026-05-08 07:33:51 +01:00
Peter Steinberger
b81033d7d8 fix: normalize gemini 3.1 config writes 2026-05-08 07:26:42 +01:00
Peter Steinberger
4fe12fc099 test: clarify block chunker length assertion 2026-05-08 07:16:07 +01:00
Peter Steinberger
f8e34422ea test: clarify cross-os suite filter assertion 2026-05-08 07:14:45 +01:00
Peter Steinberger
fb38bcb356 test: clarify bundled plugin prefix assertions 2026-05-08 07:12:48 +01:00
Peter Steinberger
5cf4969911 test: clarify plugin prerelease lane assertion 2026-05-08 07:11:25 +01:00
Peter Steinberger
d7f566b267 test: clarify sandbox fs bridge shell assertions 2026-05-08 07:10:03 +01:00
Peter Steinberger
151e61cadf test: clarify discord unresolved allowlist assertion 2026-05-08 07:08:03 +01:00
Peter Steinberger
eaad397981 test: clarify discord wildcard id assertion 2026-05-08 07:06:46 +01:00
Peter Steinberger
350889dd75 test: clarify ci shard plan assertions 2026-05-08 07:05:05 +01:00
Peter Steinberger
a4796c47e4 test: clarify plugin runtime path assertions 2026-05-08 07:03:27 +01:00
Peter Steinberger
d85942284c test: clarify embedding chunk limit failures 2026-05-08 07:02:27 +01:00
Peter Steinberger
c6b07d2f32 test: tighten acp session cwd assertions 2026-05-08 07:00:54 +01:00
Peter Steinberger
6e67a6374b test: dedupe model resolution assertions 2026-05-08 06:59:08 +01:00
Jesse Merhi
a9377fe667 Harden browser download output writes (#78780)
Summary:
- The PR exports `ensureAbsoluteDirectory` through the fs-safe/SDK runtime facades and routes browser download ... through safe output directory/file helpers with focused tests, a changelog entry, and SDK API hash updates.
- Reproducibility: yes. at source level: current main creates browser download/output roots with raw recursive ... jection coverage for that path. I did not run a live browser runtime reproduction in this read-only review.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(browser): use fs-safe output directory helper
- PR branch already contained follow-up commit before automerge: docs(changelog): mention browser fs-safe hardening
- PR branch already contained follow-up commit before automerge: fix(browser): harden download output writes

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

Prepared head SHA: a9c9570f66
Review: https://github.com/openclaw/openclaw/pull/78780#issuecomment-4394146682

Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
2026-05-08 05:57:23 +00:00
Peter Steinberger
ab192eb3f0 test: tighten helper assertion guards 2026-05-08 06:56:38 +01:00
Peter Steinberger
c9053ff208 fix(pairing): preserve narrowed token scopes on upgrade (#79206)
* fix(pairing): preserve narrowed token scopes on upgrade

* fix(pairing): require pending scopes for approval

* fix(pairing): type approval scope merge
2026-05-08 06:54:07 +01:00
sallyom
07e8aecb39 fix: speed up status json channel detection
Signed-off-by: sallyom <somalley@redhat.com>
2026-05-08 01:51:01 -04:00
Peter Steinberger
d29201fe4f docs: clarify BlueBubbles to imsg migration 2026-05-08 06:49:37 +01:00
Peter Steinberger
fc1d238909 fix: normalize gemini 3.1 config refs 2026-05-08 06:48:36 +01:00
Peter Steinberger
e7391fc2b6 fix(gateway): ignore malformed node catalog capabilities (#79205) 2026-05-08 06:47:36 +01:00
sallyom
eebbe41da2 fix(gateway): allow no-auth backend self-pairing
Signed-off-by: sallyom <somalley@redhat.com>
2026-05-08 01:42:46 -04:00
Ava Daigo
f29efde73a fix(gateway): scoped no-auth local backend bypass (#75781)
When gateway.auth.mode is 'none', the local backend self-pairing skip was
gated on sharedAuthOk, which stays false for no-auth mode. The missing-device
handler still rejected with 1008: device identity required.

Fix: shouldSkipLocalBackendSelfPairing now bypasses sharedAuthOk entirely
when authMethod is 'none' and the connection is local (direct_local or
shared_secret_loopback_local) without browser origin. Remote and
browser-originated connections still require proper device auth.

ClawSweeper P1: Make the none-auth backend bypass reachable
ClawSweeper P2: Test the reachable none-auth connect state

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-08 01:42:46 -04:00
Peter Steinberger
fd08fd0b1f fix(ui): read exec security from tools config (#79207) 2026-05-08 06:41:02 +01:00
Peter Steinberger
089dd91d69 test: tighten remaining defined assertions 2026-05-08 06:40:27 +01:00
Peter Steinberger
bd3f09e969 fix(doctor): avoid duplicate gateway runtime warnings (#79203) 2026-05-08 06:39:44 +01:00
Peter Steinberger
0a6818bbb5 test: finish exact function assertion cleanup 2026-05-08 06:38:25 +01:00
Peter Steinberger
948ba9e7cb test: guard extension callback captures 2026-05-08 06:34:45 +01:00
Peter Steinberger
a360aa3c8c fix(gateway): require owner auth for managed image media (#79204) 2026-05-08 06:34:11 +01:00
Peter Steinberger
24f9f4455b test: invoke matrix entry hooks 2026-05-08 06:32:40 +01:00
Peter Steinberger
765ca52915 test: invoke whatsapp setup validators 2026-05-08 06:31:10 +01:00
Peter Steinberger
0f31b6424e test: tighten proxy fetch assertions 2026-05-08 06:28:56 +01:00
Peter Steinberger
6eae017dd6 fix(agents): route pi default streams through transport (#79201) 2026-05-08 06:27:46 +01:00
Peter Steinberger
03c41eac2d test: invoke auth and reply callbacks 2026-05-08 06:26:42 +01:00
Gio Della-Libera
bc735f4fde feat(workspace): oc-path addressing substrate + openclaw path CLI (md/jsonc/jsonl/yaml) (#78678)
Implements #78051 — oc:// addressing substrate for workspace files.

New src/oc-path/ substrate (parser/formatter, per-kind parse+emit for
md/jsonc/jsonl/yaml, universal resolveOcPath/setOcPath/findOcPaths verbs,
sentinel emit guard) + openclaw path resolve|find|set|validate|emit CLI +
docs/cli/path.md reference page + CHANGELOG entry.

Co-authored-by: giodl73-repo <235387111+giodl73-repo@users.noreply.github.com>
Co-authored-by: galiniliev <5711535+galiniliev@users.noreply.github.com>
2026-05-07 22:26:28 -07:00
Peter Steinberger
11d0c5e42a test: invoke captured test callbacks 2026-05-08 06:23:20 +01:00
Peter Steinberger
41c5990d13 fix(auto-reply): resolve scp from path for media staging (#79202) 2026-05-08 06:20:37 +01:00
Peter Steinberger
8af475d9be test: tighten function-shape assertions 2026-05-08 06:19:37 +01:00
Peter Steinberger
6a07855d5a test: type msteams monitor mocks 2026-05-08 06:18:36 +01:00
Peter Steinberger
48ff229a82 test(msteams): type lifecycle mocks 2026-05-08 06:14:53 +01:00
Peter Steinberger
87f9d5dbae test: align media temp path assertions 2026-05-08 06:10:06 +01:00
Peter Steinberger
d4eb40248a fix: normalize gemini 3 pro preview config 2026-05-08 06:08:58 +01:00
Pavan Kumar Gondhi
ff80167e5a fix(discord): gate user allowlist name resolution [AI] (#79002)
* fix: gate discord user allowlist name resolution

* docs: add changelog entry for PR merge
2026-05-08 10:38:39 +05:30
Pavan Kumar Gondhi
c1edfafa3e fix(msteams): gate startup user allowlist resolution [AI] (#79003)
* fix: gate msteams user allowlist name resolution

* addressing codex review

* docs: add changelog entry for PR merge
2026-05-08 10:38:05 +05:30
Peter Steinberger
8fc53e7937 fix: satisfy shell inline lint 2026-05-08 06:03:24 +01:00
Peter Steinberger
5ed1cfc15c docs: keep qa broker notes internal 2026-05-08 06:01:23 +01:00
Peter Steinberger
c659590d22 fix: restore external file write helper 2026-05-08 06:01:23 +01:00
sallyom
397cf2b9ff fix: clarify gateway version mismatch warnings 2026-05-08 00:59:42 -04:00
Peter Steinberger
9e58cc82c8 test: fix strict CI gates 2026-05-08 05:56:38 +01:00
Val Alexander
79e3142122 fix(control-ui): clarify login failure guidance
Summary:
- Replace raw Control UI login failures with structured remediation guidance.
- Classify auth, pairing, insecure HTTP, origin, protocol mismatch, and transport failures without changing Gateway protocol/auth contracts.
- Localize the new login failure copy across shipped Control UI locale bundles and add regression coverage.

Verification:
- pnpm ui:i18n:sync
- pnpm ui:i18n:check
- pnpm exec vitest run --config test/vitest/vitest.ui.config.ts ui/src/i18n/test/translate.test.ts
- pnpm test ui/src/ui/views/login-gate.test.ts ui/src/ui/views/overview.node.test.ts ui/src/ui/app-gateway.node.test.ts
- pnpm tsgo:test:ui
- pnpm exec oxfmt --check --threads=1 CHANGELOG.md ui/src/i18n/locales/*.ts ui/src/i18n/test/translate.test.ts ui/src/styles/components.css ui/src/ui/views/login-gate.ts ui/src/ui/views/login-gate.test.ts
- git diff --check origin/main..HEAD
- Testbox: pnpm check:changed, https://github.com/openclaw/openclaw/actions/runs/25536382431

Notes:
- Current broad CI has unrelated failures in files outside this PR diff; the PR-specific changed gate and touched UI/i18n checks passed.
- Closes none.
2026-05-07 23:52:48 -05:00
Pavan Kumar Gondhi
fc065b2693 Harden macOS shell wrapper allowlist parsing [AI] (#78518)
* fix: harden shell wrapper allowlist parsing

* fix: harden shell wrapper approval binding

* docs: add changelog entry for PR merge

---------

Co-authored-by: Ishaan <ishaan@Ishaans-Mac-mini.local>
2026-05-08 10:18:41 +05:30
Peter Steinberger
eabae023eb perf: lazy load memory embedding runtime 2026-05-08 05:39:13 +01:00
Peter Steinberger
8dcc2ff1d2 fix(discord): prefer latest voice auto-join channel 2026-05-08 05:35:51 +01:00
Peter Steinberger
1f88cb2ce5 fix(gateway): persist macOS stop disable after bootout
Summary:
- carry forward #78412's macOS LaunchAgent bootout-by-default stop behavior and repair guard
- fix the remaining `gateway stop --disable` tail when the service is already not loaded after bootout
- add lifecycle regressions, docs, and changelog

Verification:
- pnpm install
- pnpm test src/cli/daemon-cli/lifecycle-core.test.ts src/cli/daemon-cli/lifecycle.test.ts src/daemon/launchd.test.ts
- pnpm exec oxfmt --check --threads=1 CHANGELOG.md src/cli/daemon-cli/lifecycle-core.ts src/cli/daemon-cli/lifecycle.ts src/cli/daemon-cli/lifecycle-core.test.ts src/cli/daemon-cli/lifecycle.test.ts docs/cli/gateway.md docs/gateway/index.md src/daemon/launchd.ts src/daemon/launchd.test.ts src/cli/daemon-cli/register-service-commands.ts src/cli/daemon-cli/types.ts src/daemon/service-types.ts
- git diff --check origin/main...HEAD
- pnpm build
- Parallels macOS Tahoe VM reproduce/fix proof in PR body
- PR checks green: Real behavior proof, auto-response, dispatch, label, label-issues

Co-authored-by: wdeveloper16 <25180374+wdeveloper16@users.noreply.github.com>
2026-05-08 05:35:21 +01:00
Peter Steinberger
fe79d85ae0 feat(imessage): add native imsg message actions
Adds native iMessage private-API message actions, lightweight message-tool discovery, bridge capability cache sharing, execution-time action gates, target alias coverage, and regression tests.
2026-05-08 05:34:22 +01:00
samzong
1819e41d26 fix(gateway): preserve node reconnect state (#78351)
Preserve node registry ownership across same-node WebSocket reconnect races so stale old-socket closes cannot clear the replacement session or complete the wrong pending invoke.

Thanks @samzong.
2026-05-08 12:32:18 +08:00
Peter Steinberger
9ef37d1907 test: tighten assertions and harness coverage 2026-05-08 05:28:12 +01:00
Kevin Lin
f62618f805 fix: respect Codex requirements for app-server defaults (#79151)
* fix(codex): honor requirements for app-server defaults

* test(codex): harden requirements policy coverage

* fix(codex): match requirements sandbox constraints

* fix(codex): honor approval requirements in defaults

* fix(codex): honor reviewer requirements in defaults

* fix(codex): honor remote sandbox requirements
2026-05-07 21:16:08 -07:00
NVIDIAN
36f847a60e fix(whatsapp): ignore outbound echoes for inbound activity (#79057)
Merged via squash.

Prepared head SHA: 3b1f38a2bd
Co-authored-by: ai-hpc <183861985+ai-hpc@users.noreply.github.com>
Co-authored-by: mcaxtr <7562095+mcaxtr@users.noreply.github.com>
Reviewed-by: @mcaxtr
2026-05-08 01:02:19 -03:00
Val Alexander
30214a40cb fix(ui): read exec policy from tools config (#79119) thanks @BunsDev
Co-authored-by: Nova <nova@openclaw.local>
2026-05-07 22:58:47 -05:00
Alex Knight
b1eedb2fc8 Add ACP session load event ledger (#79093)
* Add ACP session load event ledger

* Record ACP prompts after send acceptance

* Support ACP ledger replay by session key

* Harden ACP ledger replay completeness

* Harden ACP ledger review gaps

* Fix ACP canonical session key handling

---------

Co-authored-by: Alex Knight <15041791+amknight@users.noreply.github.com>
2026-05-08 13:54:08 +10:00
Ayaan Zaidi
252456e2f6 fix(telegram): recover sticky fallback transport 2026-05-08 09:15:31 +05:30
github-actions[bot]
4aaf934c88 chore(ui): refresh fa control ui locale 2026-05-08 03:44:43 +00:00
github-actions[bot]
114d109df2 chore(ui): refresh nl control ui locale 2026-05-08 03:44:23 +00:00
github-actions[bot]
3b6886bdd5 chore(ui): refresh vi control ui locale 2026-05-08 03:44:20 +00:00
github-actions[bot]
034122bdc6 chore(ui): refresh th control ui locale 2026-05-08 03:43:44 +00:00
github-actions[bot]
071c1c0bfe chore(ui): refresh pl control ui locale 2026-05-08 03:43:23 +00:00
github-actions[bot]
0af2441c31 chore(ui): refresh id control ui locale 2026-05-08 03:43:15 +00:00
github-actions[bot]
881e8cfff3 chore(ui): refresh uk control ui locale 2026-05-08 03:43:10 +00:00
github-actions[bot]
d8a5ef1702 chore(ui): refresh it control ui locale 2026-05-08 03:42:33 +00:00
github-actions[bot]
4e848ada7d chore(ui): refresh ar control ui locale 2026-05-08 03:42:21 +00:00
github-actions[bot]
6ce9680932 chore(ui): refresh tr control ui locale 2026-05-08 03:42:17 +00:00
github-actions[bot]
64cc58c8c8 chore(ui): refresh fr control ui locale 2026-05-08 03:41:55 +00:00
github-actions[bot]
89a0e75772 chore(ui): refresh ko control ui locale 2026-05-08 03:41:22 +00:00
github-actions[bot]
1b3bbed785 chore(ui): refresh ja-JP control ui locale 2026-05-08 03:41:20 +00:00
github-actions[bot]
7b2255ecb7 chore(ui): refresh es control ui locale 2026-05-08 03:41:10 +00:00
github-actions[bot]
abf6b6619d chore(ui): refresh pt-BR control ui locale 2026-05-08 03:40:48 +00:00
github-actions[bot]
448f62f53a chore(ui): refresh de control ui locale 2026-05-08 03:40:16 +00:00
github-actions[bot]
858b6bf3ae chore(ui): refresh zh-CN control ui locale 2026-05-08 03:40:14 +00:00
github-actions[bot]
9fc08fbf42 chore(ui): refresh zh-TW control ui locale 2026-05-08 03:40:07 +00:00
Val Alexander
d12c92c216 fix(usage): roll up session lineage history
Summary:
- Roll up transcript-backed session usage across logical session lineage.
- Preserve lineage through /new and /reset rotations.
- Add Control UI usage scope controls with legacy gateway fallback.
- Refresh generated protocol and Control UI locale fallback surfaces.

Verification:
- pnpm test src/auto-reply/reply/session.test.ts ui/src/ui/controllers/usage.node.test.ts src/gateway/server-methods/usage.sessions-usage.test.ts
- pnpm protocol:check
- pnpm ui:i18n:check
- pnpm ui:build
- git diff --check
- PR CI green on 10f10850ee

Closes #50701.
2026-05-07 22:38:11 -05:00
Bek
737e5707f1 docs: clarify Slack thread sessions (#79221) 2026-05-07 23:36:37 -04:00
Momo
681042a897 Add Maurice Niu as maintainer (#79219) 2026-05-08 11:33:58 +08:00
sallyom
79853b2fe8 docs: align digitalocean root setup 2026-05-07 23:31:03 -04:00
Jerry-Xin
6ec4e5cf4a fix: check effective UID (geteuid) in root guard
assertNotRoot only checked process.getuid(), so the guard was bypassed
when the CLI was launched with a non-root real UID but an effective UID
of 0 (e.g. via a setuid-root wrapper). In that context the process still
has root write privileges and can cause the same state/config corruption
the guard was added to prevent.

Now checks both getuid() and geteuid() — either being 0 triggers the
guard. Added three tests covering setuid-root scenarios.
2026-05-07 23:31:03 -04:00
Jerry-Xin
ad461c74cc fix: narrow container bypass to require container hint
OPENCLAW_CLI_CONTAINER_BYPASS alone is an internal recursion sentinel,
not a user-facing opt-in. Require OPENCLAW_CONTAINER_HINT to also be
present — this combination only occurs in the container-forwarding flow
(container-target.ts), so inherited or accidental env vars can no
longer silently skip the root guard.
2026-05-07 23:31:03 -04:00
Jerry-Xin
5986c2d013 fix: enforce root guard unconditionally on legacy entrypoint
Remove the --help/--version exemption from the legacy entrypoint
(src/index.ts). Unlike src/entry.ts which has fast-path exits before
startup work, the legacy path always calls runCli() which runs dotenv
loading and debug capture initialization before rendering output. The
assertNotRoot() error message already shows the OPENCLAW_ALLOW_ROOT=1
escape hatch, so users can still discover the override.
2026-05-07 23:31:03 -04:00
Jerry-Xin
690c7aa263 fix: apply root guard to legacy CLI entrypoint in src/index.ts
runLegacyCliEntry now calls assertNotRoot() before runCli, matching
the protection already present in src/entry.ts. Help and version
invocations are exempted so users can still discover OPENCLAW_ALLOW_ROOT.
2026-05-07 23:31:03 -04:00
Jerry-Xin
a5f6668a5c fix: skip root guard for container-forwarded CLI
The container forwarder sets OPENCLAW_CLI_CONTAINER_BYPASS=1 but not
OPENCLAW_ALLOW_ROOT. When the child CLI inside a root-based container
hits assertNotRoot(), it would exit before command handling. Exempt
container-forwarded invocations from the root guard.
2026-05-07 23:31:03 -04:00
Jerry-Xin
225339abc8 test: use static import in root-guard tests
Replace dynamic import helper with a static import since root-guard.ts
has no module-level mutable state and vi.resetModules() is not used,
making the dynamic import unnecessary.
2026-05-07 23:31:03 -04:00
忻役
ca8121d22b fix: add root guard to prevent CLI execution as root (#67478)
Block openclaw CLI from running as root (uid 0) to prevent:
- Separate state directory at /root/.openclaw/
- Conflicting systemd user services racing on port 18789
- Root-owned files in the service user state dir (EACCES)

The guard runs early in src/entry.ts before any state/config operations.
Root-level --help and --version bypass the guard so users can discover
the OPENCLAW_ALLOW_ROOT=1 override. Subcommand help paths still enforce
the guard since they enter runCli() and resolve state directories.

Closes #67478
2026-05-07 23:31:03 -04:00
Zeroth
741315e657 fix(slack): seed thread routing for implicit-conversation channels (#78522)
When a Slack channel has `requireMention: false` and a non-`off` reply mode, every top-level bot reply creates a Slack thread (because `replyToMode` does). Without seeding the inbound root, the root turn landed on the channel session while later thread replies landed on a fresh `🧵<root_ts>` session, breaking conversational continuity.

Extend `seedTopLevelRoomThreadBySource` to also fire for those channels, mirroring how `app_mention` / `explicitlyMentioned` roots already get seeded. The thread session key is now consistent on both sides of the turn, so follow-up thread messages route back to the originating session.

Fixes #78505
2026-05-07 23:30:10 -04:00
Val Alexander
4e983aa57b fix: hide retired google gemini chat models
Summary:
- Hide retired and non-public Google Gemini model IDs from Control UI/chat model catalogs.
- Route the bare gemini-3-pro alias to gemini-3.1-pro-preview.
- Keep models.list fallback rows filtered by manifest suppressions and update stale pricing-cache expectations.

Verification:
- pnpm test src/commands/models/list.list-command.forward-compat.test.ts src/commands/models/list.rows.test.ts extensions/google/manifest.test.ts extensions/google/model-id.test.ts extensions/google/provider-models.test.ts extensions/google/provider-policy-api.test.ts extensions/google/media-understanding-provider.video.test.ts src/plugin-sdk/provider-model-id-normalize.test.ts src/plugins/manifest-model-suppression.test.ts src/gateway/server-methods/models.test.ts ui/src/ui/chat-model-select-state.test.ts ui/src/ui/chat-model-ref.test.ts
- pnpm test src/gateway/model-pricing-cache.test.ts
- pnpm --silent openclaw models list --all --json --provider google / google-vertex hidden-row probe
- Testbox pnpm check:changed: https://github.com/openclaw/openclaw/actions/runs/25534551033
2026-05-07 22:20:07 -05:00
pashpashpash
fb106fb9ae fix codex harness service tiers (#79152) 2026-05-08 12:10:41 +09:00
Omar Shahine
df069f7b02 fix(imessage): surface silent group-allowlist drops at default log level (#79190)
Merged via squash.

Prepared head SHA: 6454366a62
Co-authored-by: omarshahine <10343873+omarshahine@users.noreply.github.com>
Co-authored-by: omarshahine <10343873+omarshahine@users.noreply.github.com>
Reviewed-by: @omarshahine
2026-05-07 20:09:05 -07:00
Val Alexander
5ae385b2f0 fix(ui): keep control ui refresh responsive
Summary:
- Keep Control UI chat refresh usable while history and secondary metadata refreshes are slow, with an explicit history-await path for manual refresh.
- Let config and channel tabs render cheap/stale snapshots before slow schema or probe work finishes, then request updates when background refreshes settle.
- Bound large chat render pressure to the last 100 history messages and preserve slow-render/long-frame instrumentation for follow-up tuning.
- Add regression coverage for non-blocking refreshes, manual refresh completion, background update callbacks, and the 100-message render cap.

Verification:
- pnpm test ui/src/ui/app-chat.test.ts ui/src/ui/app-render.helpers.node.test.ts ui/src/ui/app-settings.refresh-active-tab.node.test.ts ui/src/ui/control-ui-performance.test.ts ui/src/ui/controllers/chat.test.ts ui/src/ui/chat/build-chat-items.test.ts
- pnpm exec oxfmt --check --threads=1 CHANGELOG.md ui/src/ui/app-chat.ts ui/src/ui/app-chat.test.ts ui/src/ui/app-render.helpers.ts ui/src/ui/app-render.helpers.node.test.ts ui/src/ui/app-render.ts ui/src/ui/app-settings.ts ui/src/ui/app-settings.refresh-active-tab.node.test.ts ui/src/ui/chat/build-chat-items.ts ui/src/ui/chat/build-chat-items.test.ts ui/src/ui/chat/history-limits.ts
- git diff --check origin/main..HEAD && git diff --check
- GitHub CI on exact head 53295aeb4f: all required checks passed
2026-05-07 22:02:35 -05:00
sallyom
cbc69d9a96 fix: surface gateway version skew
Signed-off-by: sallyom <somalley@redhat.com>
2026-05-07 22:58:14 -04:00
Patrick Erichsen
cde99c3349 docs: add ClawHub publishing page 2026-05-07 19:43:06 -07:00
Daev Mithran
9e1e59717f feat(plugin-sdk): add LLM completion API to plugin (#64294) 2026-05-07 19:27:48 -07:00
Omar Shahine
e259751ec9 feat(imessage): private-API support via imsg JSON-RPC [AI-assisted] (#78317)
Merged via squash.

Prepared head SHA: b7d336b296
Co-authored-by: omarshahine <10343873+omarshahine@users.noreply.github.com>
Co-authored-by: omarshahine <10343873+omarshahine@users.noreply.github.com>
Reviewed-by: @omarshahine
2026-05-07 19:20:18 -07:00
Peter Steinberger
6cfb08680e fix(codex): close app-server stdio gracefully 2026-05-08 02:58:27 +01:00
Peter Steinberger
bee3a7372e fix(cli): dispose agent harnesses on exit 2026-05-08 02:58:12 +01:00
Peter Steinberger
22657861c8 fix(agents): enable codex for openai overrides 2026-05-08 02:57:55 +01:00
Peter Steinberger
f463d471d3 fix(gateway): scope explicit live model registry 2026-05-08 02:57:30 +01:00
Patrick Erichsen
10f9a758b6 docs: add dedicated ClawHub docs tab (#79159)
* docs: add clawhub docs tab

* fix: satisfy docs sync lint

* docs: prune internal clawhub nav pages

* docs: include ClawHub publishing page in nav

* docs: use clawhub how-it-works route
2026-05-07 18:55:08 -07:00
Peter Steinberger
478996231a test: stabilize Codex searchable dynamic tools test 2026-05-08 02:42:38 +01:00
Val Alexander
af0c273d28 ui: gate WhatsApp QR actions by link state
Summary:
- Gate WhatsApp Control UI QR actions by link state so unlinked accounts show Show QR, linked accounts show Relink, and Wait for scan appears only while a QR is active.
- Preserve the existing web.login.start/web.login.wait controller flow while removing misleading simultaneous actions.
- Add focused Lit render tests and a user-facing changelog entry.

Verification:
- pnpm docs:list
- pnpm exec oxfmt --check --threads=1 CHANGELOG.md ui/src/ui/views/channels.whatsapp.ts ui/src/ui/views/channels.test.ts
- pnpm test ui/src/ui/views/channels.test.ts ui/src/ui/controllers/channels.test.ts
- git diff --check
- pnpm changed:lanes --json
- pnpm check:changed
- GitHub CI passed on b5f4433f89
2026-05-07 20:21:47 -05:00
Josh Avant
83aad863fd Clarify exec filesystem policy drift (#79153)
* docs: clarify exec filesystem policy

* fix: warn on exec filesystem policy drift

* docs: clarify exec filesystem mutation surface
2026-05-07 20:05:19 -05:00
Peter Steinberger
e0cc5c0eee fix: preserve progress draft tool titles 2026-05-08 02:03:12 +01:00
Peter Steinberger
164ecfd7c8 fix: show web search queries in progress drafts 2026-05-08 02:03:12 +01:00
Peter Steinberger
accf774591 fix: make channel progress labels rolling 2026-05-08 02:03:12 +01:00
Peter Steinberger
ef29c85a48 fix: improve Discord progress draft rendering 2026-05-08 02:03:12 +01:00
Patrick Erichsen
31a710c5a6 Fix Telegram model status Codex auth label (#79135) 2026-05-07 20:43:31 -04:00
Kevin Lin
a1ac559ed7 feat(codex): enable native plugin app support (#78733)
* feat(codex): add native plugin config schema

* feat(codex): add native plugin inventory activation

* feat(codex): configure native plugin apps for threads

* feat(codex): enforce plugin elicitation policy

* feat(codex): migrate native plugins

* docs(codex): document native plugin support

* fix(codex): harden plugin migration refresh

* fix(codex): satisfy plugin activation lint

* fix: stabilize codex plugin app config

* fix: address codex plugin review feedback

* fix: key codex plugin app cache by websocket credentials

* fix: keep codex plugin app fingerprints stable

* fix: refresh codex plugin cache test fixtures

* fix: refresh plugin app readiness after activation

* fix: support remote codex plugin activation

* fix: recover plugin app bindings after cache refresh

* fix: force codex app refresh after plugin activation

* fix: recover partial codex plugin app bindings

* fix: sync codex plugin selection config

* fix: keep codex plugin activation fail closed

* fix: align codex plugin protocol types with main

* fix: refresh partial codex plugin app bindings

* fix: key codex app cache by env api key

* fix: skip failed codex plugin migration config

* test: update codex prompt snapshots

* fix: fail closed on missing codex app inventory entries

* fix(codex): enforce native plugin policy gates

* fix(codex): normalize native plugin policy types

* fix(codex): fail closed on plugin refresh errors

* fix(codex): use native plugin destructive policy

* fix(codex): key plugin cache by api-key profiles

* fix(codex): drop unshipped plugin fingerprint compat

* fix(codex): let native app policy gate plugin tools

* fix(codex): allow open-world plugin app tools

* fix(codex): revalidate native plugin app bindings

* fix(codex): preserve plugin binding on recheck failure

* docs(codex): clarify plugin harness scope

* fix(codex): return activation report state exhaustively

* test(codex): refresh prompt snapshots after rebase

* fix(codex): match namespaced plugin ids
2026-05-07 17:20:28 -07:00
Peter Steinberger
b75e5c50bf docs: document OpenAI realtime voices 2026-05-08 01:07:46 +01:00
Peter Steinberger
63ec912786 fix(openai): use GA realtime bridge for gpt-realtime-2
Summary:
- switch OpenAI realtime voice default to gpt-realtime-2
- migrate backend OpenAI WebSocket bridge to the GA session shape and drop the beta header
- keep Azure deployment realtime bridges on the deployment-compatible shape
- extend live Talk smoke coverage and align npm Telegram package-runtime assertions

Verification:
- pnpm test extensions/openai/realtime-voice-provider.test.ts src/gateway/protocol/index.test.ts src/gateway/talk-handoff.test.ts extensions/google-meet/index.test.ts -- --reporter=dot
- pnpm test test/scripts/npm-telegram-live.test.ts -- --reporter=dot
- pnpm check:docs
- env OPENCLAW_TESTBOX=0 pnpm check:changed
- OPENCLAW_REALTIME_OPENAI_MODEL=gpt-realtime-2 node --import tsx scripts/dev/realtime-talk-live-smoke.ts
2026-05-08 00:47:25 +01:00
pashpashpash
3f217964d1 Defer Codex dynamic tools behind search
Defer OpenClaw Codex dynamic tools behind Codex tool_search, keep required turn-control tools direct, pin the managed Codex harness to 0.129.0-alpha.15, and document the real behavior/token impact from the live dev-agent watch.
2026-05-07 16:40:37 -07:00
Kevin Lin
e984a99c7e fix: keep gateway watch sync tracing opt-in (#79110) 2026-05-07 16:40:35 -07:00
Mert Başar
029ca8c268 feat(agents): implement state-aware failover and lane suspension
Summary:
- Persist quota-suspension state transitions and reload fresh suspension state before failover handoff injection.
- Restore suspended lanes to configured concurrency and share failover-to-suspension reason mapping across fallback and embedded runner paths.
- Export model.failover diagnostics via OTLP and cover queueing/resume behavior with regressions.

Verification:
- pnpm test src/config/sessions/store.pruning.integration.test.ts src/process/command-queue.test.ts src/agents/session-suspension.test.ts src/agents/model-fallback.test.ts extensions/diagnostics-otel/src/service.test.ts
- git diff --check
- pnpm exec oxfmt --check --threads=1 on changed TypeScript files
- GitHub checks: 92 successful, 0 pending, 0 failed on head 962146be88
- Review threads: none unresolved
2026-05-07 18:34:05 -05:00
Peter Steinberger
e29f4ff6b8 fix: keep npm telegram e2e on package runtime 2026-05-08 00:29:20 +01:00
Peter Steinberger
6a4069dead fix: share plugin runtime helpers
Consolidate shared plugin runtime MIME/schema helpers, preserve canonical runtime behavior, and guard QQBot STT fetches.
2026-05-08 00:28:43 +01:00
Peter Steinberger
f3c9203631 fix(mistral): normalize structured completion content 2026-05-08 00:21:55 +01:00
Peter Steinberger
9e4da8c7b3 fix(active-memory): honor agent allowlist in status 2026-05-08 00:21:44 +01:00
Peter Steinberger
b00c9943bd fix(active-memory): avoid google chat space ids as channels 2026-05-08 00:21:26 +01:00
Peter Steinberger
84dd9c7395 fix(gateway): fail closed for trusted-proxy auth 2026-05-08 00:21:08 +01:00
Peter Steinberger
97d2d40fb7 fix: allow safe exec secret passEnv inheritance 2026-05-08 00:00:40 +01:00
Peter Steinberger
3adce8fac1 fix: show active model in session status 2026-05-08 00:00:40 +01:00
Peter Steinberger
3a452a029c ci(release): automate stable appcast handoff 2026-05-07 23:46:33 +01:00
sallyom
244c2b5b23 fix: bound skills watcher traversal
Signed-off-by: sallyom <somalley@redhat.com>
2026-05-07 18:12:08 -04:00
3571 changed files with 113625 additions and 37956 deletions

View File

@@ -7,7 +7,7 @@ description: "Use for all ClawSweeper work: OpenClaw issue/PR sweep reports, com
ClawSweeper lives at `~/Projects/clawsweeper`. It is the one OpenClaw
maintenance bot for sweeping, commit review, repair jobs, and guarded fix PRs.
Use this skill whenever Peter asks about reports, findings, dispatch health,
Use this skill whenever asked about reports, findings, dispatch health,
repair/cloud PR creation, comment commands, automerge, permissions, or gates.
## Start
@@ -20,7 +20,7 @@ pnpm run build:all
```
Do not overwrite unrelated edits. If the tree is dirty, inspect first and keep
read-only report work read-only unless Peter asked to commit.
read-only report work read-only unless the requester asked to commit.
## One Bot, One App
@@ -79,7 +79,7 @@ gh workflow run commit-review.yml --repo openclaw/clawsweeper \
-f enabled=true
```
Use `create_checks=true` only when Peter explicitly wants target commit Check
Use `create_checks=true` only when the requester explicitly wants target commit Check
Runs. Add `-f additional_prompt="..."` for focused one-off review instructions.
## Sweep Reports
@@ -175,7 +175,7 @@ gh variable set CLAWSWEEPER_ALLOW_MERGE --repo openclaw/clawsweeper --body 1
gh variable set CLAWSWEEPER_ALLOW_AUTOMERGE --repo openclaw/clawsweeper --body 1
```
Reset gates only when Peter asks; the active maintainer window may intentionally
Reset gates only when explicitly requested; the active maintainer window may intentionally
leave them at `1`.
Important gates:
@@ -255,15 +255,16 @@ loop. The router:
- never merges autofix PRs or draft PRs;
- merges automerge PRs only when ClawSweeper passed the exact current head,
checks are green, GitHub says mergeable, no human-review label is present,
the PR is not draft, required user-facing OpenClaw changelog entries are
present, and both merge gates are open.
the PR is not draft, and both merge gates are open.
Missing changelog is not a review finding or merge blocker. If repairing a user-facing change, add/update changelog automatically when practical; never ask or block solely on it.
If ClawSweeper passes while merge gates are closed, it labels
`clawsweeper:merge-ready` and comments instead of merging. `@clawsweeper stop`
adds `clawsweeper:human-review`.
When Peter asks Codex to create a PR and enable ClawSweeper automerge, do not
leave his local OpenClaw checkout on the PR branch. After the PR is created,
When asked to create a PR and enable ClawSweeper automerge, do not
leave the local OpenClaw checkout on the PR branch. After the PR is created,
pushed, and the `@clawsweeper automerge` request is posted or otherwise
confirmed, return the local checkout to `main` and fast-forward it when the
working tree is clean:

View File

@@ -31,6 +31,13 @@ pnpm crabbox:run -- --help | sed -n '1,120p'
- Check `.crabbox.yaml` for repo defaults, but override provider explicitly.
Even if config still says AWS, maintainer validation should normally pass
`--provider blacksmith-testbox`.
- For live/provider bugs, check keys on the local Mac before downgrading to
mocks: source local `~/.profile` and test only presence/length. If Crabbox
does not already have the key, copy only the exact needed key into the remote
process environment for that one command. Do not print it, do not sync it as a
repo file, and do not leave it in remote shell history or logs. If no
secret-safe injection path is available, say true live provider auth is
blocked instead of silently using a fake key.
- Prefer local targeted tests for tight edit loops. Broad gates belong remote.
- Do not treat inherited shell env as operator intent. In particular,
`OPENCLAW_LOCAL_CHECK_MODE=throttled` from the local shell is not permission
@@ -131,6 +138,81 @@ unclear:
blacksmith testbox list
```
## Efficient Bug E2E Verification
Use the smallest Crabbox lane that proves the reported user path, not just the
touched code. Aim for one after-fix E2E proof before commenting, closing, or
opening a PR for a user-visible bug.
Pick the lane by symptom:
- Docker/setup/install bug: build a package tarball and run the matching
`scripts/e2e/*-docker.sh` or package script. This proves npm packaging,
install paths, runtime deps, config writes, and container behavior.
- Provider/model/auth bug: prefer true live E2E. First source local Mac
`~/.profile`, then inject the single needed key into Crabbox if needed. Scrub
unrelated provider env vars in the child command so interactive defaults do
not drift to another provider. If only a dummy key is used, label the proof
narrowly, e.g. "UI/install path only; live provider auth not exercised."
- Channel delivery bug: use the channel Docker/live lane when available; include
setup, config, gateway start, send/receive or agent-turn proof, and redacted
logs.
- Gateway/session/tool bug: prefer an end-to-end CLI or Gateway RPC command that
creates real state and inspects the resulting files/API output.
- Pure parser/config bug: targeted tests may be enough, but still run a
Crabbox command when OS, package, Docker, secrets, or service lifecycle could
change behavior.
Efficient flow:
1. Reproduce or prove the pre-fix symptom when feasible. If the issue cannot be
reproduced, capture the exact command and observed behavior instead.
2. Patch locally and run narrow local tests for edit speed.
3. Run one Crabbox E2E command that starts from the user-facing entrypoint:
package install, Docker setup, onboarding, channel add, gateway start, or
agent turn as appropriate.
4. Record proof as: Testbox id, command, environment shape, redacted secret
source, and copied success/failure output.
5. If the issue says "cannot reproduce", ask for the missing config/log fields
that would distinguish the tested path from the reporter's path.
Keep it efficient:
- Reuse existing E2E scripts and helper assertions before writing ad hoc shell.
- Use one-shot Crabbox for a single proof; use a reusable Testbox only when
several commands must share built images, installed packages, or live state.
- Prefer `OPENCLAW_CURRENT_PACKAGE_TGZ` with Docker/package lanes when testing a
candidate tarball; prefer the repo's package helper instead of direct source
execution when the bug might be packaging/install related.
- Keep secrets redacted. It is fine to report key presence, source, and length;
never print secret values.
- Include `--timing-json` on broad or flaky runs when command duration or sync
behavior matters.
Interactive CLI/onboarding:
- For full-screen or prompt-heavy CLI flows, run the target command inside tmux
on the Crabbox and drive it with `tmux send-keys`; capture proof with
`tmux capture-pane`, redacted through `sed`.
- Prefer deterministic arrow navigation over search typing for Clack-style
searchable selects. Raw `send-keys -l openai` may not trigger filtering in a
tmux pane; inspect option order locally or on-box and send exact Down/Enter
sequences.
- Isolate mutable state with `OPENCLAW_STATE_DIR=$(mktemp -d)`. Plugin npm
installs live under that state dir (`npm/node_modules/...`), not under
`OPENCLAW_CONFIG_DIR`. Verify downloads by checking the state dir, package
lock, and installed package metadata.
- To test automatic setup installs against local package artifacts, use
`OPENCLAW_ALLOW_PLUGIN_INSTALL_OVERRIDES=1` plus
`OPENCLAW_PLUGIN_INSTALL_OVERRIDES='{"plugin-id":"npm-pack:/tmp/plugin.tgz"}'`.
Pack with `npm pack`, set an isolated `OPENCLAW_STATE_DIR`, and verify the
package under `npm/node_modules`. Overrides are test-only and must not be
treated as official/trusted-source installs.
- For OpenAI/Codex onboarding proof, the useful markers are the UI line
`Installed Codex plugin`, `npm/node_modules/@openclaw/codex`, and the
package-lock entry showing the bundled `@openai/codex` dependency. A dummy
OpenAI-shaped key can prove only UI/install behavior; it is not live auth.
## Reuse And Keepalive
For most Blacksmith-backed Crabbox calls, one-shot is enough. Use reuse only

View File

@@ -48,7 +48,7 @@ gitcrawl cluster-detail openclaw/openclaw --id <cluster-id> --member-limit 20 --
## Suppress top-maintainer items in issue triage
When Peter asks for issue triage, hot issues, pressing bugs, Discord-correlated issues, or "what is still open", do not surface issues or PRs authored by top maintainers by default. He wants external/user-reported hot issues and external PRs, not maintainer-owned work queues.
When asked for issue triage, hot issues, pressing bugs, Discord-correlated issues, or "what is still open", do not surface issues or PRs authored by top maintainers by default. Prefer external/user-reported hot issues and external PRs, not maintainer-owned work queues.
Suppress by default when the opener/author is one of:
@@ -77,7 +77,7 @@ Also suppress lower-priority maintainer-owned noise from the broader keep/top-ma
Exceptions:
- Show maintainer-authored items when Peter explicitly asks for maintainer PRs/issues, PR landing candidates, release-blocking maintainer work, or a specific PR/issue number.
- Show maintainer-authored items when the requester explicitly asks for maintainer PRs/issues, PR landing candidates, release-blocking maintainer work, or a specific PR/issue number.
- Show a maintainer-authored item when it is the canonical fix for an external hot issue, but frame it as the fix path rather than as a user-facing issue candidate.
- Do not close, label, or deprioritize solely because an item is maintainer-authored; this section only controls what appears in triage shortlists.
@@ -103,11 +103,18 @@ Exceptions:
When asked for `X` issues or PRs to triage, `X` means qualified candidates, not sampled threads.
Triage is read/prove/patch-local by default. Do not commit unless Peter writes
`commit` in the current instruction for the exact diff being handled. Do not
treat earlier messages, inferred intent, "next", sweep momentum, or bundled
publish language as commit permission. If Peter asks for follow-up work without
saying `commit`, keep the files dirty after local fixes and proof.
Issue triage is review/prove/patch-local by default:
1. Review the issue body, comments, related threads, current code, and adjacent tests.
2. Fix only issues that are easy, high-confidence, and narrowly owned by the implicated path.
3. Add focused regression proof when practical.
4. Stop with the dirty diff, touched files, and test/gate output for maintainer review.
5. After maintainer approval to ship, make one commit per accepted fix, with its own changelog entry when user-facing.
6. Pull/rebase, push, then comment and close only the issues that were fixed or explicitly triaged closed.
Do not batch unrelated issue fixes into one commit. Do not publish, comment, close, or label during the review/prove phase.
Missing changelog is not a PR review finding or merge blocker. If landing/fixing a user-visible change, add/update changelog automatically when practical; never ask or block solely on it.
Only list candidates that pass all gates:
@@ -127,9 +134,29 @@ Loop:
Output only qualifying candidates, with: ref, surface, proof, cause, fix sketch, why small, expected test/gate. If none qualify, say so; do not pad.
## Structure PR review output
- Start every PR review with 1-3 plain sentences explaining what the change does and why it matters. Put this before `Findings`.
- Then list findings first. If none, say `No blocking findings` or `No findings`.
- Always answer: bug/behavior being fixed, PR/issue URL and affected surface, and best-fix verdict.
- Keep summaries compact, but include enough proof that the verdict is auditable without rereading the PR.
## Read beyond the diff
- Review the surrounding code path, not just changed lines. Open the caller, callee, data contracts, adjacent tests, and owner module.
- For large-codebase PRs, sample enough related files to understand the runtime boundary before deciding. Default to more code reading when the change touches agents, gateway, plugins, auth, sessions, process, config, or provider/runtime seams.
- Compare the PR against current `origin/main` behavior. Check whether recent main already changed the same surface.
- Dependency-backed behavior: MUST read upstream docs/source/types before judging API use, defaults, output shapes, errors, timeouts, memory behavior, or compatibility. Do not assume dependency contracts from memory or PR text.
- Judge solution quality, not only correctness. Ask whether the PR is the clean owner-boundary fix or a wart/workaround that should be replaced by a small refactor, moved seam, contract change, or deletion of duplicate logic.
- Mention the main files read when the verdict depends on code-path evidence.
## Enforce the bug-fix evidence bar
- Never merge a bug-fix PR based only on issue text, PR text, or AI rationale.
- Whenever feasible, use Crabbox (`$crabbox`) for end-to-end verification before
commenting that a bug is unreproducible, closing an issue, or opening/landing
a fix PR. Prefer a real packaged/Docker/live lane that exercises the reported
user flow over unit-only proof.
- Before landing, require:
1. symptom evidence such as a repro, logs, or a failing test
2. a verified root cause in code with file/line
@@ -137,6 +164,9 @@ Output only qualifying candidates, with: ref, surface, proof, cause, fix sketch,
4. a regression test when feasible, or explicit manual verification plus a reason no test was added
- If the claim is unsubstantiated or likely wrong, request evidence or changes instead of merging.
- If the linked issue appears outdated or incorrect, correct triage first. Do not merge a speculative fix.
- If Crabbox/E2E proof is blocked, say exactly why and use the closest available
local, Docker, mocked, or targeted proof. Do not present unit tests as real
behavior proof.
## Close low-signal manual PRs carefully
@@ -179,6 +209,9 @@ gh search issues --repo openclaw/openclaw --match title,body --limit 50 \
## Follow PR review and landing hygiene
- Never mention merge conflicts that are relatively easy to resolve, such as
`CHANGELOG.md` entries, in review-only output. These are landing mechanics,
not correctness findings.
- If bot review conversations exist on your PR, address them and resolve them yourself once fixed.
- Leave a review conversation unresolved only when reviewer or maintainer judgment is still needed.
- When landing or merging any PR, follow the global `/landpr` process.

View File

@@ -7,17 +7,19 @@ description: Fix only small, high-certainty OpenClaw bugs from a pasted issue/PR
Batch workflow for pasted OpenClaw issue/PR refs.
Execute, do not summarize.
Triage does not commit, push, create PRs, comment, close, label, land, or merge.
Triage reviews, proves, and patches local fixes first; publishing waits for Peter's manual review.
## Peter Review Gate
Peter always wants to review code before commits.
After local fixes and proof, stop with the diff summary, touched files, and test/gate output.
Do not commit unless Peter writes `commit` in the current instruction for the exact diff being handled.
Do not treat earlier messages, inferred intent, "next", sweep momentum, or bundled publish language as commit permission.
If Peter asks for follow-up work without saying `commit`, keep the files dirty after local fixes and proof.
Do not push, comment, close, label, land, merge, or otherwise publish until Peter explicitly asks for that exact action after the code has been reviewed.
If Peter asks for a bundled action like `commit push close`, first confirm the code has already been reviewed in chat; if not, stop with the dirty diff and ask for review/approval.
Default flow:
1. Review each issue deeply enough to prove current behavior and root cause.
2. Fix only easy, high-confidence bugs with narrow ownership and focused proof.
3. Stop with the dirty diff summary, touched files, and test/gate output for Peter's manual review.
4. After Peter approves shipping, make one commit per accepted fix, with a changelog entry for each user-facing fix.
5. Pull/rebase, push, then comment and close only the fixed or explicitly triaged-closed issues.
Do not batch unrelated issue fixes into one commit. Do not push, create PRs, comment, close, label, land, merge, or otherwise publish during the review/prove phase.
## Companion Skills
@@ -58,8 +60,9 @@ Skip with terse reason. Do not pad with low-confidence fixes.
- no drive-by refactors
- tests near failing surface
- docs only for changed public behavior
- no commit unless Peter writes `commit` in the current instruction
- no push/create PR/comment/close/label/land/merge unless explicitly asked for that exact action after review
- no commit during the review/prove phase
- after Peter approves shipping, one commit plus changelog per accepted user-facing fix
- no push/create PR/comment/close/label/land/merge until Peter approves shipping after review
## PR Rules

4
.github/labeler.yml vendored
View File

@@ -276,6 +276,10 @@
- changed-files:
- any-glob-to-any-file:
- "extensions/memory-wiki/**"
"extensions: oc-path":
- changed-files:
- any-glob-to-any-file:
- "extensions/oc-path/**"
"extensions: open-prose":
- changed-files:
- any-glob-to-any-file:

View File

@@ -1742,7 +1742,17 @@ jobs:
with:
install-bun: "false"
- name: Checkout ClawHub docs source
uses: actions/checkout@v6
with:
repository: openclaw/clawhub
path: clawhub-source
fetch-depth: 1
persist-credentials: false
- name: Check docs
env:
OPENCLAW_DOCS_SYNC_CLAWHUB_REPO: ${{ github.workspace }}/clawhub-source
run: pnpm check:docs
skills-python:

View File

@@ -22,6 +22,15 @@ jobs:
with:
fetch-depth: 0
- name: Checkout ClawHub docs source
uses: actions/checkout@v6
with:
repository: openclaw/clawhub
path: clawhub-source
fetch-depth: 1
persist-credentials: false
token: ${{ secrets.OPENCLAW_DOCS_SYNC_TOKEN || github.token }}
- name: Setup Node
uses: actions/setup-node@v6
with:
@@ -48,12 +57,17 @@ jobs:
- name: Sync docs into publish repo
run: |
clawhub_sha="$(git -C "$GITHUB_WORKSPACE/clawhub-source" rev-parse HEAD)"
node scripts/docs-sync-publish.mjs \
--target "$GITHUB_WORKSPACE/publish" \
--source-repo "$GITHUB_REPOSITORY" \
--source-sha "$GITHUB_SHA"
--source-sha "$GITHUB_SHA" \
--clawhub-repo "$GITHUB_WORKSPACE/clawhub-source" \
--clawhub-source-repo "openclaw/clawhub" \
--clawhub-source-sha "$clawhub_sha"
- name: Install docs MDX checker dependency
working-directory: publish
run: npm install --no-save --package-lock=false @mdx-js/mdx@3.1.1
- name: Check publish docs MDX

View File

@@ -98,5 +98,5 @@ jobs:
echo "- Run \`openclaw/releases-private/.github/workflows/openclaw-macos-validate.yml\` with tag \`${RELEASE_TAG}\` and wait for the private mac validation lane to pass."
echo "- Run \`openclaw/releases-private/.github/workflows/openclaw-macos-publish.yml\` with tag \`${RELEASE_TAG}\` and \`preflight_only=true\` for the full private mac preflight."
echo "- For the real publish path, run the same private mac publish workflow from \`main\` with the successful private preflight \`preflight_run_id\` so it promotes the prepared artifacts instead of rebuilding them."
echo "- For stable releases, also download \`macos-appcast-${RELEASE_TAG}\` from the successful private run and commit \`appcast.xml\` back to \`main\` in \`openclaw/openclaw\`."
echo "- For stable releases, the private publish workflow also publishes the signed \`appcast.xml\` to public \`main\`, or opens an appcast PR if direct push is blocked."
} >> "$GITHUB_STEP_SUMMARY"

View File

@@ -2135,8 +2135,8 @@ jobs:
# inside the already-isolated container to keep MCP cron/tool
# execution representative instead of failing on nested sandbox
# setup.
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"
echo 'OPENCLAW_LIVE_CLI_BACKEND_ARGS=["exec","--json","--color","never","--sandbox","danger-full-access","-c","service_tier=\"priority\"","--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=\"priority\"","--skip-git-repo-check"]' >> "$GITHUB_ENV"
echo "OPENCLAW_LIVE_CLI_BACKEND_DEBUG=1" >> "$GITHUB_ENV"
echo "OPENCLAW_CLI_BACKEND_LOG_OUTPUT=1" >> "$GITHUB_ENV"
echo "OPENCLAW_TEST_CONSOLE=1" >> "$GITHUB_ENV"
@@ -2354,8 +2354,8 @@ jobs:
live-cli-backend-docker)
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"
echo 'OPENCLAW_LIVE_CLI_BACKEND_ARGS=["exec","--json","--color","never","--sandbox","danger-full-access","-c","service_tier=\"priority\"","--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=\"priority\"","--skip-git-repo-check"]' >> "$GITHUB_ENV"
echo "OPENCLAW_LIVE_CLI_BACKEND_DEBUG=1" >> "$GITHUB_ENV"
echo "OPENCLAW_CLI_BACKEND_LOG_OUTPUT=1" >> "$GITHUB_ENV"
echo "OPENCLAW_TEST_CONSOLE=1" >> "$GITHUB_ENV"

View File

@@ -599,7 +599,7 @@ jobs:
published_upgrade_survivor_baselines: ${{ needs.resolve_target.outputs.run_release_soak == 'true' && 'last-stable-4 2026.4.23 2026.5.2 2026.4.15' || '' }}
published_upgrade_survivor_scenarios: ${{ needs.resolve_target.outputs.run_release_soak == 'true' && '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-current-session-status-tool,telegram-mention-gating
telegram_scenarios: telegram-help-command,telegram-commands-command,telegram-tools-compact-command,telegram-whoami-command,telegram-status-command,telegram-other-bot-command-gating,telegram-context-command,telegram-mentioned-message-reply,telegram-reply-chain-exact-marker,telegram-stream-final-single-message,telegram-long-final-reuses-preview,telegram-mention-gating
secrets:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL }}
@@ -705,11 +705,11 @@ jobs:
case "${QA_PARITY_LANE}" in
candidate)
model="${OPENCLAW_CI_OPENAI_MODEL}"
alt_model="openai/gpt-5.4-alt"
alt_model="openai/gpt-5.5-alt"
;;
baseline)
model="anthropic/claude-opus-4-6"
alt_model="anthropic/claude-sonnet-4-6"
model="anthropic/claude-opus-4-7"
alt_model="anthropic/claude-sonnet-4-7"
;;
*)
echo "Unknown QA parity lane: ${QA_PARITY_LANE}" >&2
@@ -779,7 +779,7 @@ jobs:
--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 \
--baseline-label anthropic/claude-opus-4-7 \
--output-dir .artifacts/qa-e2e/parity
- name: Upload parity artifacts

View File

@@ -187,17 +187,17 @@ jobs:
--parity-pack agentic \
--concurrency "${QA_PARITY_CONCURRENCY}" \
--model "${OPENCLAW_CI_OPENAI_MODEL}" \
--alt-model openai/gpt-5.4-alt \
--alt-model openai/gpt-5.5-alt \
--output-dir .artifacts/qa-e2e/gpt54
- name: Run Opus 4.6 lane
- name: Run Opus 4.7 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 \
--model anthropic/claude-opus-4-7 \
--alt-model anthropic/claude-sonnet-4-7 \
--output-dir .artifacts/qa-e2e/opus46
- name: Generate parity report
@@ -207,7 +207,7 @@ jobs:
--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 \
--baseline-label anthropic/claude-opus-4-7 \
--output-dir .artifacts/qa-e2e/parity
- name: Upload parity artifacts

4
.gitignore vendored
View File

@@ -95,6 +95,10 @@ docs/internal/
tmp/
IDENTITY.md
USER.md
# Exception: oc-path real-world test fixtures need to be tracked even
# though the bare names match the local-untracked rule above.
!extensions/oc-path/src/oc-path/tests/fixtures/real/IDENTITY.md
!extensions/oc-path/src/oc-path/tests/fixtures/real/USER.md
*.tgz
*.tar.gz
*.zip

View File

@@ -30,6 +30,7 @@
"eslint/no-useless-computed-key": "error",
"eslint/no-useless-concat": "error",
"eslint/no-useless-constructor": "error",
"eslint/no-unused-vars": "off",
"eslint/no-warning-comments": "error",
"eslint/no-unmodified-loop-condition": "error",
"eslint/no-new-wrappers": "error",

View File

@@ -71,7 +71,7 @@ Telegraph style. Root rules only. Read scoped `AGENTS.md` before subtree work.
## GitHub / CI
- Triage: list first, hydrate few. Use bounded `gh --json --jq`; avoid repeated full comment scans.
- Automatic PR/issue discovery: skip maintainer-owned items unless directly relevant. Do not comment, close, label, retitle, rebase, fix up, or land them without Peter asking.
- Automatic PR/issue discovery: skip maintainer-owned items unless directly relevant. Do not comment, close, label, retitle, rebase, fix up, or land them without explicit maintainer request.
- PR scan/triage: no unsolicited PR comments/reviews. Report in chat only unless explicitly asked, or a close/duplicate action needs a reason comment.
- Search/dedupe: prefer `gh search issues 'repo:openclaw/openclaw is:open <terms>' --json number,title,state,updatedAt --limit 20`.
- GitHub search boolean text is fussy. If `OR` queries return empty, split exact terms and search title/body/comments separately before concluding no hits.
@@ -157,8 +157,10 @@ Telegraph style. Root rules only. Read scoped `AGENTS.md` before subtree work.
## Docs / Changelog
- Docs change with behavior/API. Use docs list/read_when hints; docs links per `docs/AGENTS.md`.
- When upgrading the bundled Codex harness (`@openai/codex` in `extensions/codex/package.json`), refresh the model availability snapshot in `docs/plugins/codex-harness.md` from the new harness's `model/list` result.
- 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.
- Missing changelog is not a PR review finding or merge blocker. If landing/fixing a user-visible change, add/update changelog automatically when practical; never ask or block solely on it.
- 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.

File diff suppressed because it is too large Load Diff

View File

@@ -41,7 +41,7 @@ Welcome to the lobster tank! 🦞
- **Vincent Koc** - Agents, Telemetry, Hooks, Security
- GitHub: [@vincentkoc](https://github.com/vincentkoc) · X: [@vincent_koc](https://x.com/vincent_koc)
- **Val Alexander** - UI/UX, Docs, and Agent DevX
- **Val Alexander** - UI/UX, Docs, SDK, and Agent DevX
- GitHub: [@BunsDev](https://github.com/BunsDev) · X: [@BunsDev](https://x.com/BunsDev)
- **Seb Slight** - Docs, Agent Reliability, Runtime Hardening
@@ -86,6 +86,9 @@ Welcome to the lobster tank! 🦞
- **Mason Huang** - Stability, Security, Speed
- GitHub: [@hxy91819](https://github.com/hxy91819) · X: [@chenjingtalk](https://x.com/chenjingtalk)
- **Maurice Niu** - ClawHub, Security, Stability, Data integrity
- GitHub: [@momothemage](https://github.com/momothemage) · X: [@MomoPsicasso](https://x.com/MomoPsicasso)
## How to Contribute
1. **Bugs & small fixes** → Open a PR!

View File

@@ -160,7 +160,7 @@ RUN --mount=type=cache,id=openclaw-bookworm-apt-cache,target=/var/cache/apt,shar
--mount=type=cache,id=openclaw-bookworm-apt-lists,target=/var/lib/apt,sharing=locked \
apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
ca-certificates procps hostname curl git lsof openssl python3 && \
ca-certificates procps hostname curl git lsof openssl python3 tini && \
update-ca-certificates
RUN chown node:node /app
@@ -287,4 +287,5 @@ USER node
# For external access from host/ingress, override bind to "lan" and set auth.
HEALTHCHECK --interval=3m --timeout=10s --start-period=15s --retries=3 \
CMD node -e "fetch('http://127.0.0.1:18789/healthz').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
ENTRYPOINT ["tini", "-s", "--"]
CMD ["node", "openclaw.mjs", "gateway", "--allow-unconfigured"]

View File

@@ -2,6 +2,53 @@
<rss xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" version="2.0">
<channel>
<title>OpenClaw</title>
<item>
<title>2026.5.7</title>
<pubDate>Thu, 07 May 2026 22:36:27 +0000</pubDate>
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
<sparkle:version>2026050790</sparkle:version>
<sparkle:shortVersionString>2026.5.7</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[<h2>OpenClaw 2026.5.7</h2>
<h3>Fixes</h3>
<ul>
<li>Release/plugin publishing: retry transient ClawHub CLI dependency install failures, keep preview-passing plugins publishable when one preview cell flakes, and verify every expected ClawHub package version after publish so maintenance releases are faster to recover and less likely to hide partial plugin publishes.</li>
<li>OpenAI: support <code>openai/chat-latest</code> as an explicit direct API-key model override for trying the moving ChatGPT Instant API alias without changing the stable default model.</li>
<li>Cron CLI: include computed <code>status</code> in <code>cron list --json</code> and <code>cron show --json</code> output so external tooling can read disabled/running/ok/error/skipped/idle state without reimplementing cron status derivation. (#78701) Thanks @aweiker.</li>
<li>Channels CLI: make <code>openclaw channels list</code> channel-only, add <code>--all</code> for bundled and catalog channels, render installed/configured/enabled state, and move model auth/usage details to <code>openclaw models auth list</code>, <code>openclaw status</code>, and <code>openclaw models list</code>. (#78456) Thanks @sliverp.</li>
<li>Native commands: honor owner enforcement for native command handlers. (#78864) Thanks @pgondhi987.</li>
<li>Active Memory: require admin scope for global memory toggles. (#78863) Thanks @pgondhi987.</li>
<li>Gateway/sessions: clear cached skills snapshots during <code>/new</code> and <code>sessions.reset</code> so long-lived channel sessions rebuild the visible skill list after skills change. (#78873) Thanks @Evizero.</li>
<li>Auto-reply: gate inline skill tool dispatch through before-tool-call authorization hooks. (#78517) Thanks @pgondhi987.</li>
<li>Tavily: resolve dedicated <code>tavily_search</code> and <code>tavily_extract</code> tool credentials from the active runtime config snapshot, so <code>exec</code> SecretRef-backed API keys do not reach the tools unresolved. (#78610) Thanks @VACInc.</li>
<li>Plugins/install: use the same absolute POSIX npm lifecycle shell for managed plugin install, rollback, repair, and uninstall npm operations as staged package updates, preventing restricted PATH shells from breaking cleanup. Thanks @vincentkoc.</li>
<li>Agents/context engine: invalidate cached assembled context views when source history shrinks or assembly fails, preventing stale pre-reset history from being reused. Fixes #77968. (#78163) Thanks @brokemac79 and @ChrisBot2026.</li>
<li>Discord/message: parse provider-prefixed targets like <code>discord:channel:<id></code> as channel sends instead of legacy Discord DM targets, so cross-channel agent <code>message(action="send")</code> calls no longer misroute channel IDs into misleading <code>Unknown Channel</code> failures. Fixes #78572.</li>
<li>Agents/compaction: clamp compaction summary reserve tokens to each model's output limit so high-context compaction no longer requests invalid <code>max_tokens</code> values. (#54392) Thanks @adzendo.</li>
<li>Commands/BTW: show the <code>/btw</code> missing-question usage placeholder with brackets so outbound channel sanitization keeps it visible. Fixes #62877. Thanks @RajvardhanPatil07.</li>
<li>Cron/doctor: repair persisted cron jobs whose <code>payload.model</code> was stored as <code>"default"</code>, <code>"null"</code>, blank, or JSON <code>null</code> by removing the bad override during <code>openclaw doctor --fix</code> while keeping cron runtime model validation strict. Fixes #78549. Thanks @bizzle12368239.</li>
<li>Telegram: honor <code>accessGroup:*</code> sender allowlists for DMs, groups, native commands, and callback authorization before applying Telegram's numeric sender-ID checks. Fixes #78660. Thanks @manugc.</li>
<li>Agent delivery: report <code>deliverySucceeded=false</code> when outbound delivery returns no adapter result, so claimed/empty delivery paths no longer masquerade as successful sends. Fixes #78532. Thanks @joeyfrasier.</li>
<li>Cron/isolated runs: fail implicit announce delivery before model execution when <code>delivery.channel=last</code> has no previous route, so recurring jobs do not spend tokens before hitting a permanent delivery-target error. Fixes #78608. Thanks @sallyom.</li>
<li>Gateway/sessions: persist a new generated transcript file when daily gateway-agent session rollover changes the session id, while preserving custom transcript paths. Fixes #78607. Thanks @nailujac, @zerone0x, and @sallyom.</li>
<li>Doctor/Codex OAuth: preserve working <code>openai-codex/*</code> PI routes during <code>doctor --fix</code> and recover 2026.5.5-rewritten <code>openai/*</code> GPT-5 routes when only Codex OAuth auth is available, so update repair does not break subscription-auth setups. Fixes #78407. Thanks @shakkernerd.</li>
<li>Telegram: keep the polling watchdog tied to <code>getUpdates</code> liveness so unrelated outbound Bot API calls cannot mask a wedged inbound poller. Fixes #78422. Thanks @ai-hpc.</li>
<li>Agents/subagents: have completed session-mode subagent registry rows honor <code>agents.defaults.subagents.archiveAfterMinutes</code> instead of a hardcoded 5-minute TTL, so registry-backed surfaces keep one retention knob across spawn modes. (#78263) Thanks @arniesaha.</li>
<li>Plugins/channel setup: forward <code>setChannelRuntime</code> from non-bundled external plugin setup entries so deferred external channel runtime initializers are installed before startup polling. Fixes #77779. (#77799) Thanks @openperf.</li>
<li>Telegram: treat successful same-chat <code>message</code> tool outbound sends during an inbound Telegram turn as delivered when deciding whether to emit the rewritten silent reply fallback. (#78685) Thanks @neeravmakwana.</li>
<li>Gateway/tasks: reconcile stale CLI run-context tasks whose live run context disappeared and bound channel hot-reload deferrals so stale task records cannot block Discord/Slack/Telegram reloads forever.</li>
<li>Discord/voice: audit Discord voice-channel permissions in <code>channels capabilities</code> and <code>channels status --probe</code>, including auto-join targets, so missing Connect/Speak/Read Message History permissions show up before <code>/vc join</code>.</li>
<li>Discord/voice: make voice capture less choppy by extending the default post-speech silence grace to 2.5s, add <code>voice.captureSilenceGraceMs</code> for noisy Discord sessions, and tighten the spoken-output prompt around live STT fragments. Thanks @vincentkoc.</li>
<li>WhatsApp: route proactive phone-number sends through Baileys LID forward mappings when available, so LID-addressed contacts receive agent messages instead of creating sender-only ghost chats. Fixes #67378. (#74925) Thanks @edenfunf.</li>
<li>WhatsApp: send captioned <code>MEDIA:</code> directive auto-replies once instead of emitting an empty media message before the captioned media reply. (#78770) Thanks @ai-hpc.</li>
<li>Codex/approvals: in Codex approval modes, stop installing the pre-guardian native <code>PermissionRequest</code> hook by default so Codex's reviewer can approve safe commands before OpenClaw surfaces an approval, remember <code>allow-always</code> decisions for identical Codex native <code>PermissionRequest</code> payloads within the active session window, and make plugin approval requests validate/render their actual allowed decisions so Telegram and other native approval UIs cannot offer stale actions. Thanks @shakkernerd.</li>
<li>Model providers: normalize APNG sniffed PNG uploads, preserve Gemini 3 tool-call thought-signature replay with fallback signatures, accept legacy <code>__env__:VAR</code> custom-provider keys, and repair snake_case tool-call transcript sanitization. Fixes #51881, #48915, #77566, and #42858.</li>
<li>Telegram/models: parse provider ids containing dots in <code>/models</code> callback buttons so <code>hf.co</code> model lists render as inline keyboard buttons. Fixes #38745.</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.7/OpenClaw-2026.5.7.zip" length="51130645" type="application/octet-stream" sparkle:edSignature="Zu+EzBGMRE1k7N4//L8HUxtUCPdO0ImrfDbgr2GrPMBrj7VGI1tOOl74gxNJoi/wfWvXz3fYVcBz2W/84ojuCw=="/>
</item>
<item>
<title>2026.5.2</title>
<pubDate>Sun, 03 May 2026 01:11:51 +0000</pubDate>
@@ -765,297 +812,5 @@
]]></description>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.4.29/OpenClaw-2026.4.29.zip" length="50896802" type="application/octet-stream" sparkle:edSignature="YfQ25zMGgDv8XvHbdlL/s0SMJXyu763l5ppnfjiKOjSyxZY9sfoLaoXthcctFQDXA8isR1EEb/EEausu+XkFCA=="/>
</item>
<item>
<title>2026.4.27</title>
<pubDate>Wed, 29 Apr 2026 23:53:26 +0000</pubDate>
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
<sparkle:version>2026042790</sparkle:version>
<sparkle:shortVersionString>2026.4.27</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[<h2>OpenClaw 2026.4.27</h2>
<h3>Changes</h3>
<ul>
<li>Sandbox/Docker: add opt-in <code>sandbox.docker.gpus</code> passthrough for Docker sandbox containers so local GPU workloads can run inside sandboxed agents when the host Docker runtime supports <code>--gpus</code>. Fixes #57976; carries forward #58124. Thanks @cyan-ember.</li>
<li>iOS/Gateway: add an authenticated <code>node.presence.alive</code> protocol event and <code>node.list</code> last-seen fields so background iOS wakes can mark paired nodes recently alive without treating them as connected. Carries forward #63123. Thanks @ngutman.</li>
<li>Android: publish authenticated <code>node.presence.alive</code> events after node connect and background transitions so paired Android nodes retain durable last-seen metadata after disconnects. Carries forward #63123. Thanks @ngutman.</li>
<li>Gateway/chat: accept non-image attachments through <code>chat.send</code> by staging them as agent-readable media paths, while keeping unsupported RPC attachment paths explicit instead of silently dropping files. Fixes #48123. (#67572) Thanks @samzong.</li>
<li>Security/networking: add opt-in operator-managed outbound proxy routing (proxy.enabled + proxy.proxyUrl/OPENCLAW_PROXY_URL) with strict http:// forward-proxy validation, loopback-only Gateway bypass, and cleanup of proxy env/dispatcher state on exit. (#70044) Thanks @jesse-merhi and @joshavant.</li>
<li>Dependencies: refresh provider and tooling dependencies, including AWS SDK, PI runtime packages, AJV, Feishu SDK, Anthropic SDK, tokenjuice, and native TypeScript/oxlint tooling. Thanks @dependabot.</li>
<li>Matrix/QA: add live Matrix approval scenarios for exec metadata, chunked fallback, plugin approvals, deny reactions, thread targeting, and <code>target: "both"</code> delivery, with redacted artifacts preserving safe approval summaries. Thanks @gumadeiras.</li>
<li>Codex: add Computer Use setup for Codex-mode agents, including <code>/codex computer-use status/install</code>, marketplace discovery, optional auto-install, and fail-closed MCP server checks before Codex-mode turns start. Fixes #72094. (#71842) Thanks @pash-openai.</li>
<li>Apps: consume Peekaboo 3.0.0-beta4 and ElevenLabsKit 0.1.1, align Swabble on Commander 0.2.2, and refresh macOS/iOS SwiftPM resolutions against the released dependency graph. Thanks @Blaizzy.</li>
<li>Plugin SDK: expose shared channel route normalization, parser-driven target resolution, raw-target compact keys, parsed-target types, and route comparison helpers through <code>openclaw/plugin-sdk/channel-route</code>, switch native approval origin matching onto that route contract with optional delivery and match-only target normalization, and retire the internal channel-route shim behind dated compatibility aliases for legacy key/comparable-target helpers. Thanks @vincentkoc.</li>
<li>Docs/Codex: document how Codex Computer Use, direct <code>cua-driver mcp</code>, and OpenClaw.app's PeekabooBridge fit together so desktop-control setup choices are clearer. Thanks @pash-openai and @trycua.</li>
<li>Matrix/streaming: stream tool-progress updates into live Matrix preview edits by default when preview streaming is active, with <code>streaming.preview.toolProgress: false</code> to keep answer previews while hiding interim tool lines. Thanks @gumadeiras.</li>
<li>Plugins/models: wire manifest <code>modelCatalog.aliases</code> and <code>modelCatalog.suppressions</code> into model-catalog planning and built-in model suppression, with stale Spark and Qwen Coding Plan suppressions now declared in plugin manifests instead of runtime fallback hooks. Thanks @shakkernerd.</li>
<li>Plugin SDK/models: add a shared manifest-backed provider catalog builder and move Qianfan, Xiaomi, NVIDIA, Cerebras, Mistral, Moonshot, DeepSeek, Tencent TokenHub, and StepFun provider catalogs onto their plugin manifest <code>modelCatalog</code> rows. Thanks @shakkernerd.</li>
<li>Plugin SDK/models: move BytePlus and Volcano Engine standard and plan-provider catalogs into plugin manifest <code>modelCatalog</code> rows and remove the now-unused Volcengine-family shared catalog SDK subpath. Thanks @shakkernerd.</li>
<li>CLI/models: move Fireworks and Together AI fixed provider catalogs into plugin manifest <code>modelCatalog</code> rows so provider-filtered listing can use manifest-backed static rows. Thanks @shakkernerd.</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>Channels/Yuanbao: add a channel docs entrance so the Tencent Yuanbao bot appears in the channel listing and sidebar navigation. (#73443) Thanks @loongfay.</li>
<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>Plugins/startup: migrate bundled plugin manifests to explicit <code>activation.onStartup</code> declarations so Gateway startup imports only the bundled plugins that intentionally register startup-time runtime surfaces. Thanks @shakkernerd.</li>
<li>Plugins/startup: add an opt-in future-mode gate for disabling deprecated implicit startup sidecar loading while preserving explicit startup and narrower activation triggers. Thanks @shakkernerd.</li>
<li>Plugins/startup: add plugin compatibility warnings for deprecated implicit startup loading so authors can migrate to explicit <code>activation.onStartup</code> metadata. Thanks @shakkernerd.</li>
<li>Plugins/runtime: load bundled agent tool-result middleware from manifest contracts on demand so tokenjuice stays startup-lazy without losing Pi/Codex tool-output compaction. Thanks @shakkernerd.</li>
<li>Plugins/startup: add explicit <code>activation.onStartup</code> metadata so plugins can declare Gateway startup import behavior while the deprecated implicit sidecar fallback remains for legacy plugins. Thanks @shakkernerd.</li>
<li>Gateway/startup: reuse lookup-table plugin manifests when loading startup plugins so Gateway boot avoids rebuilding plugin discovery and manifest metadata. Thanks @shakkernerd.</li>
<li>CLI/models: declare fixed Qianfan, Xiaomi, NVIDIA, Cerebras, Mistral, Chutes, Kilo, OpenAI, and OpenCode Go model catalogs in refreshable plugin manifests, keep broad <code>models list --all</code> on raw registry and supplement rows without runtime normalization, and avoid duplicate supplement resolution. Thanks @shakkernerd.</li>
<li>Gateway/runtime: reuse the current plugin metadata snapshot for provider discovery so repeated model-provider discovery avoids rebuilding plugin manifest metadata. Thanks @shakkernerd.</li>
<li>Gateway/startup: pass the plugin metadata snapshot from config validation into plugin bootstrap so startup reuses one manifest product instead of rebuilding plugin metadata. Thanks @shakkernerd.</li>
<li>Plugin SDK/testing: move core-only channel contract fixtures under the channel contract test tree and retire the old <code>test/helpers/channels</code> bridge directory so plugin tests stay on focused SDK surfaces. Thanks @vincentkoc.</li>
<li>Plugin SDK/testing: expose native agent-runtime contract fixtures through <code>plugin-sdk/agent-runtime-test-contracts</code>, move sandbox config fixtures into the focused generic fixture subpath, and block extension tests from importing repo-only <code>test/helpers</code> bridges. Thanks @vincentkoc.</li>
<li>Plugin SDK/testing: expose generic module reload, bundled-path, Node builtin mock, channel pairing/envelope, HTTP server, temp-home, replay-policy, and live STT helpers through focused SDK test subpaths so extension tests no longer depend on repo-only helper bridges. Thanks @vincentkoc.</li>
<li>Plugin SDK: move maintained bundled channels off the deprecated <code>channel-config-schema-legacy</code> subpath, add an explicit bundled-channel schema SDK surface, and track both remaining legacy test/config compatibility barrels with dated removal windows. Thanks @vincentkoc.</li>
<li>Plugin SDK/testing: expose media provider capability assertions and provider HTTP mocks through focused SDK test subpaths, and retire the repo-only media-generation test helper bridge. Thanks @vincentkoc.</li>
<li>Plugin SDK/testing: promote bundled plugin/provider/channel contract helpers to focused SDK test subpaths and retire the repo-only <code>test/helpers/plugins</code> TypeScript bridge. Thanks @vincentkoc.</li>
<li>Plugin SDK/testing: expose generic channel action, setup, status, and directory contract helpers through <code>plugin-sdk/channel-test-helpers</code> so bundled extension tests no longer import repo-only channel helper bridges. Thanks @vincentkoc.</li>
<li>Plugin SDK/testing: add <code>plugin-sdk/channel-target-testing</code> for shared channel target-resolution cases, document channel reaction helpers on <code>plugin-sdk/channel-feedback</code>, and keep the old <code>plugin-sdk/test-utils</code> alias as compatibility-only. Thanks @vincentkoc.</li>
<li>Plugin SDK/testing: add a focused generic fixture subpath for CLI capture, sandbox, skill, agent-message, system-event, terminal, chunking, auth-token, and typed-case helpers. Thanks @vincentkoc.</li>
<li>Plugin SDK/testing: add focused plugin runtime and environment fixture subpaths so plugin tests can avoid the broad <code>plugin-sdk/testing</code> barrel for common setup helpers. Thanks @vincentkoc.</li>
<li>Plugin SDK/testing: add a focused <code>plugin-sdk/plugin-test-api</code> helper subpath and move bundled plugin registration tests off the repo-only plugin API bridge. Thanks @vincentkoc.</li>
<li>Plugin SDK: add generic host hooks for session state, next-turn context, trusted tool policy, UI descriptors, events, scheduler cleanup, and run-scoped plugin context. (#72287) Thanks @100yenadmin.</li>
<li>Plugin SDK/testing: expose provider catalog, wizard, registry, manifest, public-artifact, outbound, and TTS contract helpers through documented SDK testing seams so bundled plugin tests no longer import repo <code>src/**</code> internals. Thanks @vincentkoc.</li>
<li>Providers/DeepInfra: add a bundled DeepInfra provider with <code>DEEPINFRA_API_KEY</code> onboarding, dynamic OpenAI-compatible model discovery, image generation/editing, image/audio media understanding, TTS, text-to-video, memory embeddings, static catalog metadata, and provider-owned base URL policy. Carries forward #53805, #48088, #37576, #43896, #11533, and #2554. Thanks @ats3v.</li>
<li>Matrix: attach versioned structured approval metadata to pending approval messages so capable Matrix clients can render richer approval UI while body text and reaction fallback keep working. (#72432) Thanks @kakahu2015.</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Gateway/sessions: align <code>chat.history</code> and <code>sessions.list</code> thinking defaults with owning-agent and catalog-aware resolution so Control UI session defaults match backend runtime state. (#63418) Thanks @jpreagan.</li>
<li>Devices/pairing: recover array-shaped device and node pairing state files before persisting approvals, so UUID-keyed pending and paired entries no longer disappear after a malformed JSON store write. Fixes #63035. Thanks @sar618.</li>
<li>Gateway/auth: clear reused stale device tokens and stop reconnecting on device-token mismatch in the Control UI and Node gateway clients, avoiding rate-limit loops after scope-upgrade or token-rotation handoffs. Fixes #71609. Thanks @ricksayhi.</li>
<li>Gateway/approvals: treat duplicate same-decision approval resolves as idempotent during the resolved-entry grace window, including consumed <code>allow-once</code> approvals, while returning an explicit already-resolved error for conflicting repeats. Fixes #59162; refs #58479 and #65486. Thanks @wikithoughts, @sajazuniga7-coder, and @mjmai20682068-create.</li>
<li>Channels/Telegram: honor <code>approvals.exec/plugin.targets[].accountId</code> when routing native approvals across multi-bot Telegram accounts while preserving unscoped Telegram targets for any account. Fixes #69916. Thanks @joerod26.</li>
<li>Telegram/gateway: bound outbound Bot API calls and cache bundled plugin alias lookup so slow Telegram sends or WSL2 filesystem scans no longer wedge gateway replies. (#74210) Thanks @obviyus.</li>
<li>Agents/exec: omit the internal session-resume fallback preface from successful async exec completion messages sent directly back to chat. Fixes #67181. Thanks @raistlin88.</li>
<li>Agents/media: register detached <code>video_generate</code> and <code>music_generate</code> tool run contexts until terminal status, so Discord-backed provider jobs stay live in <code>/tasks</code> instead of becoming <code>lost</code> when the parent chat run context disappears. Thanks @vincentkoc.</li>
<li>Agents/media: prefer OpenAI image and video providers when the default model uses the OpenAI Codex auth alias, so auto media generation no longer falls through to Fal before GPT Image or Sora. Thanks @vincentkoc.</li>
<li>Tasks/media: infer agent ownership for session-scoped task records so <code>/tasks</code> agent-local fallback includes session-backed <code>video_generate</code> and other async media jobs even when the current chat session has no linked rows. Thanks @vincentkoc.</li>
<li>Agents/media: keep long-running <code>video_generate</code> and <code>music_generate</code> tasks fresh while provider jobs are still pending, so task maintenance does not mark active Discord media renders lost before completion. Thanks @vincentkoc.</li>
<li>CLI/status: treat scope-limited gateway probes as reachable-but-degraded in shared status scans, so <code>openclaw status --all</code> no longer reports a live gateway as unreachable after <code>missing scope: operator.read</code>. Fixes #49180; supersedes #47981. Thanks @openjay.</li>
<li>CLI/update: skip tracked plugins disabled in config during post-update plugin sync before npm, ClawHub, or marketplace update checks, preserving their install records without failing the update. Fixes #73880. Thanks @islandpreneur007.</li>
<li>Slack/Socket Mode: use a 15s Slack SDK pong timeout by default and add <code>channels.slack.socketMode.clientPingTimeout</code>, <code>serverPingTimeout</code>, and <code>pingPongLoggingEnabled</code> overrides so stale-websocket handling no longer depends on app-event health heuristics. Fixes #14248; refs #58519, #64009, and #63488. Thanks @shivasymbl and @freerk.</li>
<li>Slack/media: bound private file and forwarded attachment downloads with idle and total timeouts while preserving placeholder fallback, so stalled Slack <code>file_share</code> media no longer wedges inbound message handling. Fixes #61850. Thanks @bassboy2k.</li>
<li>Plugins/inspector: keep bundled plugin runtime capture quiet and config-tolerant for Codex, memory-lancedb, Feishu, Mattermost, QQBot, and Tlon so plugin-inspector JSON checks can validate the full bundled set. Thanks @vincentkoc.</li>
<li>Slack/auto-reply: keep fully consumed text reset triggers such as <code>new session</code> out of <code>BodyForAgent</code> after directive cleanup, so configured Slack reset phrases do not leak into the fresh model turn. Fixes #73137. Thanks @neeravmakwana.</li>
<li>Plugins/runtime deps: prune stale retained bundled runtime deps and keep doctor/secret channel contract scans on lightweight artifacts, so disabled bundled channels stop preserving old dependency trees or importing heavy plugin surfaces. Thanks @SymbolStar and @vincentkoc.</li>
<li>Plugins/runtime deps: cache unchanged bundled runtime mirror dist-file materialization decisions and close file-lock handles on owner-write failures, reducing repeated startup chunk scans and avoiding FileHandle-GC recovery stalls. Refs #73532. Thanks @oadiazp and @bstanbury.</li>
<li>Auto-reply: bound the post-run pending tool-result delivery drain with a progress-aware idle timeout, so a never-settling tool-result task no longer leaves the session active forever while slow healthy deliveries can keep draining. Fixes #53889; supersedes #64733 and #73434. Thanks @zijunl and @wujiaming88.</li>
<li>Gateway/startup: start chat channels without waiting for primary model prewarm, keeping model warmup bounded in the background so Slack and other channels come online promptly when provider discovery is slow. Supersedes #73420. Thanks @dorukardahan.</li>
<li>Gateway/install: carry env-backed config SecretRefs such as <code>channels.discord.token</code> into generated service environments when they are present only in the installing shell, while keeping gateway auth SecretRefs non-persisted. Fixes #67817; supersedes #73426. Thanks @wdimaculangan and @ztexydt-cqh.</li>
<li>Auto-reply/commands: stop bare <code>/reset</code> and <code>/new</code> after reset hooks acknowledge the command, so non-ACP channels no longer fall through into empty provider calls while <code>/reset <message></code> and <code>/new <message></code> still seed the next model turn. Fixes #73367 and #73412. Thanks @hoyanhan, @wenxu007, and @amdhelper.</li>
<li>Providers/DeepSeek: backfill DeepSeek V4 <code>reasoning_content</code> on plain assistant replay messages as well as tool-call turns, so thinking sessions with prior tool use no longer fail follow-up requests with missing reasoning content. Fixes #73417; refs #71372. Thanks @34262315716 and @Bartok9.</li>
<li>Agents/gateway tool: strip full config payloads from <code>config.patch</code> and <code>config.apply</code> tool responses while preserving direct RPC responses, so config-heavy sessions no longer replay large redacted configs into transcript history. Fixes #47610; supersedes #73439. Thanks @HanenVit and @juan-flores077.</li>
<li>Auto-reply: preserve voice-note media from silent turns while continuing to suppress text and non-voice media, so <code>NO_REPLY</code> TTS replies still deliver the requested audio bubble. (#73406) Thanks @zqchris.</li>
<li>Channels/Mattermost: stop enqueueing regular inbound posts as system events, so Mattermost user messages reach the model only as user-role inbound-envelope content instead of also appearing as <code>System: Mattermost message...</code> directives. Fixes #71795. Thanks @juan-flores077.</li>
<li>Agents/media: qualify bare <code>agents.defaults.imageModel</code> and <code>pdfModel</code> refs from unique configured image-capable providers, so Ollama vision models such as <code>moondream</code> and <code>qwen2.5vl:7b</code> do not fall through to the default provider. Fixes #38816; supersedes #73396. Thanks @alainasclaw and @vincentkoc.</li>
<li>Agents/Anthropic: send implicit Anthropic beta headers only to direct public Anthropic endpoints, including OAuth, so custom Anthropic-compatible providers no longer mis-handle unsupported beta flags unless explicitly configured. Refs #73346. Thanks @byBrodowski.</li>
<li>Skills: require explicit <code>skills.entries.coding-agent.enabled</code> before exposing the bundled coding-agent skill, so installs with Codex on PATH but no OpenAI auth do not silently offer Codex delegation. Fixes #73358. Thanks @LaFleurAdvertising and @Sanjays2402.</li>
<li>Plugins/startup: treat manifestless Claude bundles as valid installed-plugin registry entries instead of stale missing manifests, so workspace bundles no longer force repeated derived registry rebuilds or noisy <code>plugins.entries.workspace</code> warnings during Gateway startup. Fixes #73433. Thanks @AnneVoss.</li>
<li>Agents/subagents: preserve <code>sessions_yield</code> as a paused subagent state and ignore its wait text while freezing completion output, so parent sessions wait for the final post-compaction answer instead of receiving intermediate progress or <code>(no output)</code>. Fixes #73413. Thanks @Ask-sola.</li>
<li>Plugins/startup: precompute bundled runtime mirror fingerprints before taking the mirror lock and keep Docker bundled plugin runtime deps/mirrors in a Docker-managed volume instead of the Windows/WSL config bind mount, so cold starts avoid slow host-volume mirror writes. Fixes #73339. Thanks @1yihui.</li>
<li>Plugins/runtime deps: refresh bundled runtime mirrors without deleting active import trees, so config-triggered restarts do not see transient missing plugin files during registration. Thanks @shakkernerd.</li>
<li>Channels/LINE: persist inbound image, video, audio, and file downloads in <code>~/.openclaw/media/inbound/</code> instead of temporary files so agents can still read LINE media after <code>/tmp</code> cleanup. Fixes #73370. Thanks @hijirii and @wenxu007.</li>
<li>CLI/plugins: keep bundled plugin installs out of <code>plugins.load.paths</code> while preserving install records, so install/inspect/doctor loops no longer warn about the current bundled plugin directory. Thanks @vincentkoc.</li>
<li>CLI/plugins: scope <code>plugins inspect <id></code> runtime loading to the matched plugin so single-plugin inspection does not load every plugin before checking the target. Thanks @shakkernerd.</li>
<li>CLI/plugins: remove managed copied-path plugin directories during uninstall and plan uninstall from metadata instead of runtime-loading plugins, so plugin lifecycle commands avoid unnecessary bundled runtime-deps work. Thanks @shakkernerd.</li>
<li>Cron tool: infer the creating session's agentId for <code>cron.add</code> jobs when <code>agentId</code> is omitted or passed as undefined, keeping scheduled agentTurn jobs routed to the session agent; #40571 identified the guard bug and supplied the focused regression coverage. Thanks @ChanningYul.</li>
<li>Cron/Telegram: add <code>--thread-id</code> to <code>openclaw cron add</code> and <code>openclaw cron edit</code>, preserving Telegram forum topic delivery targets across scheduled announcements. Carries forward #51581, #60373, and #60890. Thanks @ChunHao-dev.</li>
<li>Cron/Telegram: preserve session-derived Telegram topic thread IDs when isolated cron delivery explicitly targets the parent chat, keeping bare chat targets in the active forum topic without leaking stale topics to other chats. Carries forward #64708. Thanks @addelh.</li>
<li>Memory/compaction: keep pre-compaction memory-flush prompts runtime-only so session transcripts and <code>chat.history</code> no longer expose them as normal user turns. Fixes #54408 and #58956; refs #43567. Thanks @markgong and @guoyuhang9.</li>
<li>Control UI/WebChat: keep large attachment payloads out of Lit state and optimistic chat messages, using object URL previews plus send-time payload serialization so PDF/image uploads no longer trigger <code>RangeError: Maximum call stack size exceeded</code>. Fixes #73360; refs #54378 and #63432. Thanks @hejunhui-73, @Ansub, and @christianhernandez3-afk.</li>
<li>Agents/Anthropic: cancel stalled Anthropic Messages SSE body reads when abort signals fire, so active-memory timeouts release transport resources instead of leaving hidden recall runs parked on <code>reader.read()</code>. Refs #72965 and #73120. Thanks @wdeveloper16.</li>
<li>Control UI/WebChat: keep pending run and typing state attached to the active client run, so unowned inject/announce/side-result finals no longer unlock unrelated active runs while completed owned runs still clear promptly. Fixes #57795; carries forward the narrow diagnosis from #57887. Thanks @haoyu-haoyu.</li>
<li>Sandbox/Docker: stop satisfying a missing default sandbox image by tagging plain Debian as <code>openclaw-sandbox:bookworm-slim</code>, preserving the Python tooling required by sandbox write/edit helpers and directing users to build the default image. Fixes #51185; refs #45108, #51099, #51609, and #57713. Thanks @dpalis, @Tin55FoilDev, @jbcohen2-coder, @macminihal-cyber, and @PraxoOnline.</li>
<li>Control UI/WebChat: confirm toolbar New Session button resets before dispatching <code>/new</code> while leaving typed <code>/new</code> and <code>/reset</code> commands immediate. Fixes #45800; refs #27065, #56611, #54499, and #27110. Thanks @aethnova, @kosta228-huli, @adambezemek, and @xss925175263 (xianshishan).</li>
<li>Agents/models: keep per-agent primary models strict when <code>fallbacks</code> is omitted, so probe-only custom providers are not tried as hidden fallback candidates unless the agent explicitly opts in. Fixes #73332. Thanks @haumanto.</li>
<li>Gateway/models: add <code>models.pricing.enabled</code> so offline or restricted-network installs can skip startup OpenRouter and LiteLLM pricing-catalog fetches while keeping explicit model costs working. Fixes #53639. Thanks @callebtc, @palewire, and @rjdjohnston.</li>
<li>Gateway/startup: warn when legacy <code>CLAWDBOT_*</code> or <code>MOLTBOT_*</code> environment variables are still present, pointing users to <code>OPENCLAW_*</code> names instead of failing silently. Fixes #53482; carries forward #53667. Thanks @lndyzwdxhs.</li>
<li>Onboarding: pin interactive and non-interactive health checks to the just-configured setup token/password so stale <code>OPENCLAW_GATEWAY_TOKEN</code> or <code>OPENCLAW_GATEWAY_PASSWORD</code> values do not produce false gateway-token-mismatch failures after setup. Fixes #72203. Thanks @galiniliev.</li>
<li>Doctor/state: require an interactive confirmation before archiving orphan transcript files, so <code>openclaw doctor --fix</code> no longer silently renames recoverable session history after upgrades regenerate <code>sessions.json</code>. Fixes #73106. Thanks @scottgl9.</li>
<li>Cron/Telegram: preserve explicit <code>:topic:</code> delivery targets over stale session-derived thread IDs when isolated cron announces to Telegram forum topics. Carries forward #59069; refs #49704 and #43808. Thanks @roytong9.</li>
<li>Build/runtime: write the runtime-postbuild stamp after <code>pnpm build</code> writes the build stamp, so the next CLI invocation does not re-sync runtime artifacts after a successful build. Fixes #73151. Thanks @bittoby.</li>
<li>Build/runtime: preserve staged bundled-plugin runtime dependency caches across source-checkout tsdown rebuilds, so local CLI and gateway-watch rebuilds no longer recreate large plugin dependency trees before starting. Refs #73205. Thanks @SymbolStar.</li>
<li>CLI/channels: list configured chat channel accounts from read-only setup metadata even when the standalone CLI has not loaded the runtime channel registry, so <code>openclaw channels list</code> shows Telegram accounts before auth providers. Fixes #73319 and #73322. Thanks @mlaihk.</li>
<li>CLI/model probes: keep <code>infer model run --gateway</code> raw by skipping prior session transcript, bootstrap context, context-engine assembly, tools, and bundled MCP servers, so local backends can be tested without full agent-context overhead. Fixes #73308. Thanks @ScientificProgrammer.</li>
<li>CLI/image describe: pass <code>--prompt</code> and <code>--timeout-ms</code> through <code>infer image describe</code> and <code>describe-many</code>, so custom vision instructions and slow local model budgets reach media-understanding providers such as Ollama, OpenAI, Google, and OpenRouter. Addresses #63700. Thanks @cedricjanssens.</li>
<li>Providers/Ollama: reject long non-linguistic Kimi/GLM symbol runs as provider failures instead of storing them as successful visible assistant replies, so fallback or error handling can recover from garbled cloud output. Fixes #64262; refs #67019. Thanks @Kloz813 and @xiaomenger123.</li>
<li>CLI/model probes: reject empty or whitespace-only <code>infer model run --prompt</code> values before calling local providers or the Gateway, so smoke checks do not spend provider calls on invalid turns. Fixes #73185. Thanks @iot2edge.</li>
<li>Gateway/media: route text-only <code>chat.send</code> image offloads through media-understanding fields so <code>agents.defaults.imageModel</code> can describe WebChat attachments instead of leaving only an opaque <code>media://inbound</code> marker. Fixes #72968. Thanks @vorajeeah.</li>
<li>Gateway/Windows: route no-listener restart handoffs through the Windows supervisor without leaving restart tokens in flight, so failed task scheduling can be retried and successful handoffs do not coalesce later restart requests. (#69056) Thanks @Thatgfsj.</li>
<li>Gateway/model pricing: skip plugin manifest discovery during background pricing refreshes when <code>plugins.enabled: false</code>, so disabled-plugin setups do not keep rebuilding plugin metadata from the Gateway hot path. Fixes #73291. Thanks @slideshow-dingo and @fishgills.</li>
<li>Ollama/thinking: validate <code>/think</code> commands against live Ollama catalog reasoning metadata and preserve explicit native <code>params.think</code>/<code>params.thinking</code>, so models whose <code>/api/show</code> capabilities include <code>thinking</code> expose <code>low</code>, <code>medium</code>, <code>high</code>, and <code>max</code> instead of being stuck on <code>off</code>. Fixes #73366. Thanks @cymise.</li>
<li>Gateway/sessions: remove automatic oversized <code>sessions.json</code> rotation backups, deprecate <code>session.maintenance.rotateBytes</code>, and teach <code>openclaw doctor --fix</code> to remove the ignored key so hot session writes no longer copy multi-MB stores. Refs #72338. Thanks @midhunmonachan and @DougButdorf.</li>
<li>Channels/Telegram: fail fast when Telegram rejects the startup <code>getMe</code> token probe with 401, so invalid or stale BotFather tokens are reported as token auth failures instead of misleading <code>deleteWebhook</code> cleanup failures. Fixes #47674. Thanks @samaedan-arch.</li>
<li>ACPX: keep generated Codex and Claude ACP wrapper startup paths working when remote or special state filesystems reject chmod, since OpenClaw invokes the wrappers through Node instead of executing them directly. Fixes #73333. Thanks @david-garcia-garcia.</li>
<li>CLI/onboarding: infer image input for common custom-provider vision model IDs, ask only for unknown models, and keep <code>--custom-image-input</code>/<code>--custom-text-input</code> overrides so vision-capable proxies do not get saved as text-only configs. Fixes #51869. Thanks @Antsoldier1974.</li>
<li>Models/OpenAI Codex: stop listing or resolving unsupported <code>openai-codex/gpt-5.4-mini</code> rows through Codex OAuth, keep stale discovery rows suppressed with a clear API-key-route hint, and leave direct <code>openai/gpt-5.4-mini</code> available. Fixes #73242. Thanks @0xCyda.</li>
<li>Plugin SDK: restore the root <code>stringEnum</code> and <code>optionalStringEnum</code> exports on both the published SDK entry and runtime root-alias bridge, so older external plugins can keep building and loading while migrating to focused SDK subpaths. Fixes #68279. Thanks @marzliak.</li>
<li>Plugin SDK: restore the root-alias bridge for <code>registerContextEngine</code> and expose missing legacy compat helpers <code>normalizeAccountId</code> and <code>resolvePreferredOpenClawTmpDir</code> so older external plugins such as <code>openclaw-weixin</code> can keep loading while migrating to focused SDK subpaths. Fixes #53497. Thanks @alanxchen85.</li>
<li>Auth profiles: make <code>openclaw doctor --fix</code> migrate legacy flat <code>auth-profiles.json</code> files such as <code>{ "ollama-windows": { "apiKey": "ollama-local" } }</code> to canonical provider default API-key profiles with a backup, so custom Ollama/OpenAI-compatible providers recover cleanly after upgrading. Fixes #59629; supersedes #59642. Thanks @Xsanders555 and @Linux2010.</li>
<li>Memory/Dreaming: retry Dream Diary once with the session default when a configured dreaming model is unavailable, while leaving subagent trust and allowlist errors visible instead of silently masking configuration problems. Refs #67409 and #69209. Thanks @Ghiggins18 and @everySympathy.</li>
<li>Feishu/inbound files: recover CJK filenames from plain <code>Content-Disposition: filename=</code> download headers when Feishu exposes UTF-8 bytes through Latin-1 header decoding, while leaving valid Latin-1 and JSON-derived names unchanged. (#48578, #50435, #59431) Thanks @alex-xuweilong, @lishuaigit, and @DoChaoing.</li>
<li>Channels/Telegram: normalize accidental full <code>/bot<TOKEN></code> Telegram <code>apiRoot</code> values at runtime and teach <code>openclaw doctor --fix</code> to remove the suffix, so startup control calls no longer 404 when direct Bot API curl commands work. Fixes #55387. Thanks @brendanmatthewjones-cmyk, @techfindubai-ux, and @Sivlerback-Chris.</li>
<li>Zalo Personal: persist refreshed <code>zca-js</code> session cookies after QR login, session restore, and successful API calls so gateway restarts restore the freshest local session. (#73277) Thanks @darkamenosa.</li>
<li>Logging/security: redact sensitive tokens (sk-\* keys, Bearer/Authorization values, etc.) at the subsystem console sink so <code>createSubsystemLogger().info/warn/error</code> output that bypasses the patched console-capture handler still applies the same redaction the file transport already does. Fixes #73284; refs #67953 and #64046. Thanks @edwin-rivera-dev.</li>
<li>Plugins/runtime deps: reuse enclosing versioned cache roots when bundled plugins resolve from nested staged paths, so plugin-runtime-deps no longer mints <code>openclaw-unknown-*</code> directories or loops on <code>ENOTEMPTY</code>. Fixes #72956. (#73205) Thanks @SymbolStar.</li>
<li>Agents/failover: classify CJK provider transport, quota, billing, auth, and overload error text so Chinese-language provider failures trigger fallback and user-facing transport copy instead of surfacing as unclassified raw errors. (#56242) Thanks @tomcatzh.</li>
<li>Agents/failover: seed non-claude-cli fallback prompts with Claude Code session context when a claude-cli attempt fails, so fallback models do not restart cold after billing or quota failover. (#72069) Thanks @stainlu.</li>
<li>Agents/CLI runner: transfer bundle-MCP tempDir cleanup from the per-turn runner finally to the Claude live-session lifecycle, so persistent Claude CLI sessions keep their <code>--mcp-config</code> directory until the live subprocess closes. Fixes #73244. Thanks @edwin-rivera-dev.</li>
<li>Gateway/nodes: allow Windows companion nodes to use safe declared commands such as canvas, camera list, location, device info, and screen snapshot by default while keeping dangerous media commands opt-in. (#71884) Thanks @shanselman.</li>
<li>Agents/cron: clarify agent-tool and CLI cron timezone guidance so supplied <code>tz</code> values use local wall-clock cron fields and omitted cron <code>tz</code> falls back to the Gateway host local timezone. Fixes #53669; carries forward #46177. (#73372) Thanks @chen-zhang-cs-code and @maranello-o.</li>
<li>Providers/Qwen: allow explicitly configured <code>qwen/qwen3.6-plus</code> to resolve on Qwen Coding Plan endpoints while keeping the built-in catalog from advertising it there. Fixes #63654; carries forward #63987. Thanks @jepson-liu.</li>
<li>Channels/Telegram: keep Bot API network fallbacks sticky after failed attempts and retry timed-out startup control calls once on the fallback route, so <code>deleteWebhook</code> IPv6 stalls no longer trigger slow multi-account retry storms. Fixes #73255. Thanks @ttomiczek and @sktbrd.</li>
<li>Gateway/agents: accept heartbeat, cron, and webhook as internal channel hints for agent runs so <code>sessions_spawn</code> works from non-delivery parent sessions while unknown channel hints still fail closed. Fixes #73237. Thanks @KeWang0622.</li>
<li>Gateway/models: merge explicit <code>models.providers.*.models</code> rows into the Gateway model catalog with normalized provider/model dedupe, and use normalized image-capability lookup so custom vision models keep native image attachments even when Pi discovery omits them or model ID casing differs. Fixes #64213 and #65165. Thanks @billonese and @202233a.</li>
<li>Gateway/reload: publish canonical post-write source config to in-process reloaders so simple config saves no longer create phantom plugin diffs or trigger unnecessary Gateway restarts. (#73267) Thanks @szsip239.</li>
<li>Gateway/Docker: keep config-triggered restarts in-process inside containers instead of spawning a detached child and exiting PID 1 cleanly, so Docker Swarm and other on-failure supervisors do not leave the service stuck at 0/1 replicas. Fixes #73178. Thanks @du-nguyen-IT007.</li>
<li>CLI/tasks: ship the task-registry control runtime in npm packages so <code>openclaw tasks cancel</code> can load ACP/subagent cancellation helpers from published builds. Fixes #68997. Thanks @1OAKDesign.</li>
<li>Channels/Telegram: preserve unsent generated media after partial reply streaming has already delivered the text, so <code>image_generate</code> outputs still reach Telegram as photos instead of being dropped from the final payload. Fixes #73253. Thanks @mlaihk.</li>
<li>Memory-core/dreaming: cap detached Dream Diary narrative subagents across cron sweeps so multi-workspace dreaming no longer fans out unbounded subagent sessions, lock contention, and cascading narrative timeouts. Fixes #73198. (#73287) Thanks @KeWang0622.</li>
<li>CLI/agents: close local one-shot Claude live stdio sessions and bundled MCP loopback resources after embedded <code>openclaw agent --local</code> runs, while keeping gateway-owned MCP loopback cleanup internal to the Gateway. Thanks @frankekn.</li>
<li>Export/session: keep inline export HTML scripts and vendor libraries injected after template formatting so generated session exports open with the app code, markdown renderer, and syntax highlighter present. Fixes #41862 and #49957; carries forward #41861 and #68947. Thanks @briannewman, @martenzi, and @armanddp.</li>
<li>Agents/ACPX: stage the patched Claude ACP adapter as an ACPX runtime dependency and route known Codex/Claude ACP commands through local wrappers, so Gateway runtime no longer depends on live <code>npx</code> adapter resolution. Fixes #73202. Thanks @joerod26.</li>
<li>Memory/compaction: let pre-compaction memory flush use an exact <code>agents.defaults.compaction.memoryFlush.model</code> override such as <code>ollama/qwen3:8b</code> without inheriting the active session fallback chain, so local housekeeping can avoid paid conversation models. Fixes #53772. Thanks @limen96.</li>
<li>macOS/update: stop managed Gateway services before package replacement and keep LaunchAgent service secrets out of world-readable plist metadata by loading them from owner-only env files. Fixes #72996. Thanks @Mathewb7.</li>
<li>Google Meet: keep observe-only Chrome joins and setup checks from requiring BlackHole or audio bridge commands, avoid granting or selecting the microphone in observe-only mode, and make <code>test_speech</code> report fresh realtime output-byte verification instead of only confirming a queued utterance. Refs #72478. Thanks @DougButdorf.</li>
<li>Gateway/hooks: route non-delivered hook completion and error summaries to the target agent's main session instead of the default agent session, preserving multi-agent hook isolation. Fixes #24693; carries forward #68667. Thanks @abersonFAC and @bluesky6868.</li>
<li>Control UI/models: request the configured Gateway model-list view so dashboards with only <code>models.providers.*.models</code> show those configured models first instead of flooding the picker with the full built-in catalog. Fixes #65405. Thanks @wbyanclaw.</li>
<li>CLI/models: keep default-model and allowlist pickers on explicit <code>models.providers.*.models</code> entries when <code>models.mode</code> is <code>replace</code> instead of loading the full built-in catalog. Fixes #64950. Thanks @mrozentsvayg.</li>
<li>Media/security: tighten media-understanding MIME sanitization so parameterized MIME values stay end-anchored and malformed whitespace or suffix payloads are rejected before file-context handling. Fixes #9795; carries forward #68225 with related review/test context from #61016/#68456. Thanks @ymaxgit, @bluesky6868, and @shamsulalam1114.</li>
<li>Discord: own the Carbon interaction listener and hand off Discord slash/component handling asynchronously, so compaction or long session locks no longer trip <code>InteractionEventListener</code> listener timeouts. Fixes #73204. Thanks @slideshow-dingo.</li>
<li>Compaction/diagnostics: keep unknown compaction failure classifications stable while logging sanitized detail for unclassified provider errors such as missing Ollama provider adapters. Thanks @gzsiang.</li>
<li>Models/fallbacks: record first-class <code>model.fallback_step</code> trajectory events with from/to models, failure detail, chain position, and final outcome so support exports preserve the primary model failure even when a later fallback also fails. Fixes #71744. Thanks @nikolaykazakovvs-ux.</li>
<li>Gateway/agents: block agent <code>exec</code> from launching interactive <code>openclaw channels login</code> flows and abort active agent runs after invalid-config recovery restores last-known-good config, preventing known channel-login and reload paths from wedging replies. Refs #72338. Thanks @midhunmonachan.</li>
<li>Gateway/diagnostics: emit payload-free liveness warnings with event-loop delay, event-loop utilization, CPU-core ratio, active-session counts, and OTEL warning metrics/spans so live-but-stalled Gateways capture CPU-spin context in stability bundles and telemetry. Refs #72338. Thanks @midhunmonachan and @DougButdorf.</li>
<li>Gateway/startup: keep value-option foreground starts on the gateway fast path and skip proxy bootstrap unless proxy env is configured, reducing normal gateway startup RSS and avoiding full CLI graph loading. Thanks @vincentkoc.</li>
<li>Heartbeat/models: show heartbeat model bleed guidance on context-overflow resets when the last runtime model matches configured <code>heartbeat.model</code>, so smaller local heartbeat models point users to <code>isolatedSession</code> or <code>lightContext</code> instead of only compaction-buffer tuning. Fixes #67314. Thanks @Knightmare6890.</li>
<li>Subagents/models: persist <code>sessions_spawn.model</code> and configured subagent models as child-session model overrides before the first turn, so spawned subagents actually run on the requested provider/model instead of reverting to the target agent default. Fixes #73180. Thanks @danielzinhu99.</li>
<li>Channels/Telegram: keep webhook-mode local listeners alive and retry Telegram <code>setWebhook</code> registration after recoverable startup network failures, so transient Bot API timeouts no longer leave reverse proxies pointing at a closed listener. Fixes #71834. Thanks @jinon86.</li>
<li>Agents/ACPX: bundle the Codex ACP adapter and launch it from the isolated <code>CODEX_HOME</code> wrapper before falling back to npm, so Codex ACP startup no longer depends on live <code>npx</code> resolution or the stale <code>@zed-industries/codex-acp@^0.11.1</code> range. Fixes #72037; refs #73202. Thanks @jasonftl, @sazora, and @joerod26.</li>
<li>Agents/ACPX: register the embedded ACP backend at Gateway startup through a lightweight ACP backend SDK path and without importing the heavy ACPX runtime until an ACP session or explicit startup probe needs it, reducing baseline Gateway RSS. Thanks @vincentkoc.</li>
<li>CLI/update: keep restart health polling when the restarted Gateway is reachable but has not reported its version yet, so macOS service restarts do not fail early with <code>actual unavailable</code>. Thanks @ProspectOre.</li>
<li>Backup: skip installed plugin <code>extensions/*/node_modules</code> dependency trees while keeping plugin manifests and source files in archives, so local backups avoid rebuildable npm payload bloat. Fixes #64144. Thanks @BrilliantWang.</li>
<li>Cron/models: fail isolated cron runs closed when an explicit <code>payload.model</code> is not allowed or cannot be resolved, so scheduled jobs do not silently fall back to an unrelated agent default or paid route before configured provider proxies such as LiteLLM can run. Fixes #73146. Thanks @oneandrewwang.</li>
<li>Memory/QMD: back off repeated chat-turn QMD open failures while still letting memory status and CLI probes recheck immediately, so a broken sidecar dependency cannot trigger active-memory or cron retry storms. Fixes #73188 and #73176. Thanks @leonlushgit and @w3i-William.</li>
<li>Talk Mode: resolve <code>messages.tts.providers.<id>.apiKey</code> through the active runtime snapshot for <code>talk.config</code>, so Talk overlays can discover SecretRef-backed speech providers without falling back to local speech. Fixes #73109. (#73111) Thanks @omarshahine.</li>
<li>Memory/Ollama: resolve <code>memorySearch.provider</code> custom provider ids through their configured <code>models.providers.<id>.api</code> owner, so multi-GPU Ollama setups can dedicate embeddings to providers such as <code>ollama-5080</code> without losing the Ollama adapter or local auth semantics. Fixes #73150. Thanks @oneandrewwang.</li>
<li>CLI/memory: skip eager context-window warmup for <code>openclaw memory</code> commands so memory search does not race unrelated model metadata discovery. Fixes #73123. Thanks @oalansilva and @neeravmakwana.</li>
<li>CLI/Telegram: route Telegram <code>message send</code> and poll actions through the running Gateway when available, so packaged installs use the staged <code>grammy</code> runtime deps and CLI sends return instead of hanging after the Telegram channel is active. Fixes #73140. Thanks @oalansilva.</li>
<li>Plugins/runtime deps: prepare staged bundled plugin dependencies before loading packaged public surfaces, so OpenClaw's Telegram runtime/test facade loads resolve <code>grammy</code> from the managed runtime-deps stage without copying dependencies into the global package root. Refs #73140. Thanks @oalansilva.</li>
<li>Agents/exec: emit <code>(no output)</code> for silent exec update and node-host result blocks so Anthropic-compatible providers no longer reject empty tool-result text after quiet commands. Fixes #73117. Thanks @pfrederiksen and @Sanjays2402.</li>
<li>Cron/providers: preflight local Ollama and OpenAI-compatible provider endpoints before isolated cron agent turns, record unreachable local providers as skipped runs, and cache dead-endpoint probes so many jobs do not hammer the same stopped local server. Fixes #58584. Thanks @jpeghead.</li>
<li>Gateway/config: let config reload continue in degraded mode when invalidity is scoped to plugin entries, so incompatible plugin configs can be skipped and the Gateway restart can still pick up the rest of the config after rollbacks. Fixes #73131. Thanks @Adam-Researchh.</li>
<li>Doctor/channels: suppress disabled bundled-plugin blocker warnings when a trusted external plugin owns the configured channel, so Lark/Feishu installs no longer get Feishu repair noise after switching to <code>openclaw-lark</code>. Fixes #56794. Thanks @wuji-tech-dev.</li>
<li>CLI/status: show skipped fast-path memory checks as <code>not checked</code> and report active custom memory plugin runtime status from <code>status --json --all</code> without requiring built-in <code>agents.defaults.memorySearch</code>, so plugins such as memory-lancedb-pro and memory-cms no longer look unavailable when their own runtime is healthy. Fixes #56968. Thanks @Tony-ooo and @aderius.</li>
<li>Gateway/channels: record and log unexpected clean channel monitor exits so channels that return without throwing no longer appear stopped with no error. Fixes #73099. Thanks @balaji1968-kingler.</li>
<li>Discord/group chats: keep group/channel replies private by default unless the agent explicitly uses the message tool, so always-on rooms can lurk without leaking automatic final, block, preview, or status-reaction output; <code>messages.groupChat.visibleReplies: "automatic"</code> restores legacy auto-posting. (#73046) Thanks @scoootscooob.</li>
<li>Plugins/package: force nested bundled-plugin runtime dependency installs out of inherited npm dry-run mode during prepack and package smoke checks, so packed installs materialize required plugin modules instead of reporting missing bundled files. Refs #73128. Thanks @Adam-Researchh.</li>
<li>Discord: skip reaction events before REST channel fetch when notifications are off, guild reactions are disabled, or allowlist mode cannot match without channel overrides, reducing reconnect bursts that caused slow listener warnings. Fixes #73133. Thanks @isaacsummers.</li>
<li>Channels/Telegram: centralize polling update tracking so accepted offsets remain durable across restarts, same-process handler failures can still retry, and slow offset writes cannot overwrite newer accepted watermarks. Refs #73115. Thanks @vdruts.</li>
<li>Agents/models: classify empty, reasoning-only, and planning-only terminal agent runs before accepting a model fallback candidate, so invalid or incompatible models can advance to the next configured fallback instead of returning a 30-second terminal failure. Fixes #73115. Thanks @vdruts.</li>
<li>Memory/LanceDB: let embedding config use provider-backed auth profiles, environment credentials, or provider config without a separate plugin <code>embedding.apiKey</code>, so OAuth-capable embedding providers can power auto-recall/capture. Fixes #68950. Thanks @malshaalan-ai.</li>
<li>CLI/parents: invoking <code>openclaw <parent></code> (memory, channels, plugins, approvals, devices, cron, mcp) without a subcommand now prints the parent's help and exits <code>0</code>, matching <code><parent> --help</code> and the existing <code>agents</code> / <code>sessions</code> defaults so shell <code>&&</code> chains and pnpm wrappers no longer surface a misleading <code>ELIFECYCLE Command failed with exit code 1.</code> line. Fixes #73077. Thanks @hclsys.</li>
<li>Plugins/hooks: time out never-settling <code>agent_end</code> observation hooks after 30 seconds and log the plugin failure, so hung embedding endpoints no longer leave memory capture silently pending forever. Fixes #65544. Thanks @ghoc0099.</li>
<li>Gateway/config: serve runtime config schemas from the current plugin metadata snapshot and generated bundled channel schema metadata instead of rebuilding plugin channel config modules on every <code>config.get</code>/<code>config.schema</code>, preventing idle plugin-discovery CPU churn after upgrades. Fixes #73088. Thanks @sleitor and @geovansb.</li>
<li>Memory/LanceDB: call OpenAI-compatible embedding endpoints through the raw SDK transport without sending <code>encoding_format</code>, then normalize float-array or base64 responses so providers such as ZhiPu and DashScope no longer fail recall with wrong vector dimensions or rejected parameters. Fixes #63655. Thanks @kinthaiofficial.</li>
<li>Plugins/install: run dependency installs with npm error-level logging instead of silent mode so failed plugin or hook installs surface actionable npm errors such as EUNSUPPORTEDPROTOCOL instead of <code>npm install failed:</code> with no detail. (#73093) Thanks @sanctrl.</li>
<li>Memory/LanceDB: bound memory recall embedding queries with a new <code>recallMaxChars</code> setting, prefer the latest user message over channel prompt metadata during auto-recall, and document the knob so small Ollama embedding models avoid context-length failures. Fixes #56780. Thanks @rungmc357 and @zak-collaborator.</li>
<li>CLI/skills: resolve workspace-backed skills commands from <code>--agent</code>, then the current agent workspace, before falling back to the default agent, so multi-agent ClawHub installs, updates, and status checks stay scoped to the active workspace. Fixes #56161; carries forward #72726. Thanks @langbowang and @luyao618.</li>
<li>Plugin SDK: fall back from partial bundled plugin directory overrides to package source public surfaces while preserving <code>OPENCLAW_DISABLE_BUNDLED_PLUGINS</code> as a hard disable. (#72817) Thanks @serkonyc.</li>
<li>Agents/ACPX: stop forwarding Codex ACP timeout config controls that Codex rejects while preserving OpenClaw's run-timeout watchdog for ACP subagents. Fixes #73052. Thanks @pfrederiksen and @richa65.</li>
<li>Memory Core: stream fallback vector search scoring with a bounded top-K result set so large indexes do not materialize every chunk embedding when sqlite-vec is unavailable. (#73069) Thanks @parkertoddbrooks.</li>
<li>Memory Core: stream embedding-cache seeding during safe reindex so large local caches do not materialize every row into the V8 heap before the atomic rebuild. (#73067) Thanks @parkertoddbrooks.</li>
<li>Memory/Ollama: add <code>memorySearch.remote.nonBatchConcurrency</code> for inline embedding indexing, default Ollama non-batch indexing to one request at a time, and keep batch concurrency separate from non-batch concurrency so local embedding backfills avoid timeout storms on smaller hosts. Carries forward #57733. Thanks @itilys.</li>
<li>macOS app: update Peekaboo, ElevenLabsKit, and MLX TTS helper dependencies, make canvas file watching and config/exec-approval state writes reliable under concurrent app/test activity, and keep the app plus helper builds warning-free. Thanks @Blaizzy.</li>
<li>iOS app: refresh SwiftPM/XcodeGen source hygiene, make app, extension, watch, and curated shared Swift files pass the prebuild SwiftFormat and SwiftLint checks, move relay registration off deprecated StoreKit receipt APIs, and keep simulator builds and logic tests warning-free. Thanks @ngutman.</li>
<li>Agents/models: keep <code>models.json</code> readiness and provider-hook caches warm across repeated agent and subagent model resolution while preserving external <code>models.json</code> invalidation, reducing repeated provider-plugin loads on slower ARM64 hosts. Fixes #73075. Thanks @jochen.</li>
<li>Docs/tools: clarify that <code>tools.profile: "messaging"</code> is intentionally narrow and that <code>tools.profile: "full"</code> is the unrestricted baseline for broader command/control access. Carries forward #39954. Thanks @posigit.</li>
<li>Control UI/Agents: redact tool-call args, partial/final results, derived exec output, and configured custom secret patterns before streaming tool events to the Control UI, so tool output cannot expose provider or channel credentials. Fixes #72283. (#72319) Thanks @volcano303 and @BunsDev.</li>
<li>Agents/sessions: keep <code>sessions_history</code> recall redaction enabled even when general log redaction is disabled, and clarify that safety-boundary UI/tool/diagnostic payloads still redact independently of <code>logging.redactSensitive</code>. Carries forward #72319. Thanks @volcano303 and @BunsDev.</li>
<li>Providers/Codex: pass agent and workspace directories into provider stream wrappers so Codex native <code>web_search</code> activation can evaluate the correct auth context, and smoke-test the built status-message runtime by resolving the emitted bundle name. Carries forward #67843; refs #65909. Thanks @neilofneils404.</li>
<li>Cron/models: keep <code>payload.model</code> as a per-job primary that can use configured fallbacks, while still letting <code>payload.fallbacks: []</code> make cron runs strict and avoid hidden agent-primary retries. Refs #73023. Thanks @pavelyortho-cyber.</li>
<li>Models/fallbacks: treat user-selected session models as exact choices, so <code>/model ollama/...</code> and model-picker switches fail visibly when the selected provider is unreachable instead of answering from an unrelated configured fallback. Fixes #73023. Thanks @pavelyortho-cyber.</li>
<li>Codex harness: keep ChatGPT subscription app-server runs from inheriting <code>CODEX_API_KEY</code> or <code>OPENAI_API_KEY</code>, and fall back to <code>CODEX_API_KEY</code> / <code>OPENAI_API_KEY</code> app-server login only when no Codex account is available. Fixes #73057. Thanks @holgergruenhagen and @pashpashpash.</li>
<li>CLI/model probes: fail local <code>infer model run</code> probes when the provider returns no text output, so unreachable local providers and empty completions no longer look like successful smoke tests. Refs #73023. Thanks @pavelyortho-cyber.</li>
<li>CLI/Ollama: run local <code>infer model run</code> through the lean provider completion path and skip global model discovery for one-shot local probes, so Ollama smoke tests no longer pay full chat-agent/tool startup cost or hang before the native <code>/api/chat</code> request. Fixes #72851. Thanks @TotalRes2020.</li>
<li>Doctor/gateway services: ignore launchd/systemd companion services that only reference the gateway as a dependency, suppress inactive Linux extra-service warnings, and avoid rewriting a running systemd gateway command/entrypoint during doctor repair. Carries forward #39118. Thanks @therk.</li>
<li>Daemon/service: only emit hard-coded version-manager paths such as <code>~/.volta/bin</code>, <code>~/.asdf/shims</code>, <code>~/.bun/bin</code>, and fnm/pnpm fallbacks into gateway and node service PATHs when the directories exist, so <code>openclaw doctor</code> no longer flags <code>gateway.path.non-minimal</code> against a PATH the daemon just wrote. Env-driven roots and stable user-bin dirs remain unconditional. Fixes #71944; carries forward #71964. Thanks @Sanjays2402.</li>
<li>CLI/startup: disable Node's module compile cache automatically for live source-checkout launchers so in-place <code>pnpm build</code> updates are visible to the next <code>openclaw</code> CLI invocation. Fixes #73037. Thanks @LouisGameDev.</li>
<li>Agents/group chat: keep silent-allowed empty and reasoning-only turns on the <code>NO_REPLY</code> path without injecting visible-answer retry prompts, and clarify the group prompt so agents use the exact silent token instead of prose. Thanks @vincentkoc.</li>
<li>Agents/group chat: move <code>NO_REPLY</code> mechanics into channel-aware direct/group prompts and suppress the duplicate generic silent-reply section for auto-reply runs, so always-on group agents get one consistent stay-silent instruction. Thanks @vincentkoc.</li>
<li>Providers/OpenAI: preserve encrypted empty-summary Responses reasoning items in WebSocket replay and request <code>reasoning.encrypted_content</code> on reasoning turns so GPT-5.4/GPT-5.5 sessions do not lose required <code>rs_*</code> state beside <code>msg_*</code> items. Fixes #73053. Thanks @odb36777.</li>
<li>Gateway/startup: treat <code>plugins.enabled=false</code> as an early plugin fast path, skipping plugin auto-enable discovery, gateway plugin lookup/runtime-dependency staging, and stale-plugin cleanup warnings while preserving channel blocker warnings. (#73041) Thanks @WuKongAI-CMU.</li>
<li>Channels/commands: make generated <code>/dock-*</code> commands switch the active session reply route through <code>session.identityLinks</code> instead of falling through to normal chat. Fixes #69206; carries forward #73033. Thanks @clawbones and @michaelatamuk.</li>
<li>Providers/Cloudflare AI Gateway: strip assistant prefill turns from Anthropic Messages payloads when thinking is enabled, so Claude requests through Cloudflare AI Gateway no longer fail Anthropic conversation-ending validation. Fixes #72905; carries forward #73005. Thanks @AaronFaby and @sahilsatralkar.</li>
<li>Gateway/startup: keep primary-model startup prewarm on scoped metadata preparation, let native approval bootstraps retry outside channel startup, and skip the global hook runner when no <code>gateway_start</code> hook is registered, so clean post-ready sidecar work stays off the critical path. Refs #72846. Thanks @RayWoo, @livekm0309, and @mrz1836.</li>
<li>Gateway/channels: start bundled channel accounts with a lightweight <code>runtimeContexts</code> surface instead of importing the full reply/routing/session channel runtime before <code>startAccount</code>, so Discord, Telegram, Slack, Matrix, and QQBot startup no longer block on unrelated channel helper graphs. Refs #72846 and #72960. Thanks @mrz1836, @RayWoo, and @rollingshmily.</li>
<li>Gateway/supervisor: exit cleanly when a supervised restart finds an existing healthy gateway and bound retries when the existing gateway stays unhealthy, so stale lock contention cannot loop indefinitely. Refs #72846. Thanks @azgardtek.</li>
<li>Gateway/startup: scope primary-model provider discovery during channel prewarm to the configured provider owner and add split startup trace timings, so boot avoids staging unrelated bundled provider dependencies while setup discovery remains broad. Fixes #73002. Thanks @Schnup03.</li>
<li>Plugins/runtime deps: declare retained staged bundled plugin dependencies in the npm staging manifest while installing only newly missing packages, so Gateway restarts avoid reinstalling the full retained dependency set when one runtime dependency is absent. Fixes #73055. Thanks @GCorp2026.</li>
<li>CLI/status: keep default <code>openclaw status</code> off the heavyweight security audit, plugin compatibility, and memory-vector probes while still showing configured Telegram channels through setup metadata, so routine health checks stay fast and no longer render an empty Channels table. Fixes #72993. Thanks @comick1.</li>
<li>Channels/Telegram: send a best-effort native typing cue immediately after an inbound message is accepted, so slow pre-dispatch turns show Telegram liveness before queueing, compaction, model, or tool work starts. Fixes #63759. Thanks @alessandropcostabr.</li>
<li>Channels/Telegram: stop native approval startup auth failures from retrying every second, while still waiting through retryable Gateway auth handoffs, so Telegram approval setup problems no longer create a reconnect/log loop during channel startup. Refs #72846 and #72867. Thanks @kiranvk-2011 and @porly1985.</li>
<li>Channels/Microsoft Teams: unwrap staged CommonJS JWT runtime dependencies before Bot Connector token validation so inbound Teams messages no longer 401 after the bundled runtime-deps move. Fixes #73026. Thanks @kbrown10000.</li>
<li>Gateway/auth: allow local direct callers in trusted-proxy mode to use the configured gateway password as an internal fallback while keeping token fallback rejected. Fixes #17761. Thanks @dashed, @vincentkoc, and @jetd1.</li>
<li>Gateway/auth: add explicit <code>trustedProxy.allowLoopback</code> support for same-host loopback reverse proxies while keeping loopback trusted-proxy auth fail-closed by default and preserving required-header and allowlist checks. Fixes #59167; carries forward #63379. Thanks @Matir, @jeremyakers, and @mrosmarin.</li>
<li>Channels/sessions: prevent guarded inbound session recording from creating route-only phantom sessions while still allowing last-route updates for sessions that already exist. Carries forward #73009. Thanks @jzakirov.</li>
<li>Cron: accept <code>delivery.threadId</code> in Gateway cron add/update schemas so scheduled announce delivery can target Telegram forum topics and other threaded channel destinations through the documented delivery path. Fixes #73017. Thanks @coachsootz.</li>
<li>Plugins/runtime deps: stage bundled plugin dependencies imported by mirrored root dist chunks, so packaged memory and status commands do not miss <code>chokidar</code> or similar root-chunk dependencies after update. Fixes #72882 and #72970; carries forward #72992. Thanks @shrimpy8, @colin-chang, and @Schnup03.</li>
<li>Plugins/runtime deps: reuse unchanged bundled plugin runtime mirrors instead of rebuilding plugin trees on every load, cutting avoidable writes and restart/reconnect I/O on slow storage. Fixes #72933. Thanks @jasonftl.</li>
<li>Agents/runtime context: deliver hidden runtime context through prompt-local system context while keeping the transcript-only custom entry out of provider user turns, and strip stale copied runtime-context prefaces from user-facing replies. Fixes #72386; carries forward #72969. Thanks @jhsmith409.</li>
<li>Channels/Telegram: skip the optional webhook-info API call during polling-mode status checks and startup bot-label probes so long-polling setups avoid an unnecessary Telegram round trip. Carries forward #72990. Thanks @danielgruneberg.</li>
<li>CLI/message: resolve targeted <code>openclaw message</code> channels to their owning plugin before loading the registry, and fall back to configured channel plugins when the channel must be inferred, so scripted sends avoid full bundled plugin registry scans without assuming channel ids match plugin ids. Fixes #73006. Thanks @jasonftl.</li>
<li>Plugins/startup: parse strict JSON plugin manifests with native JSON first and keep JSON5 as the compatibility fallback, reducing manifest registry CPU during Gateway boot and CLI startup. Fixes #73011. Thanks @jasonftl.</li>
<li>CLI/models: keep route-first <code>models status --json</code> stdout reserved for the JSON payload by routing auth-profile and startup diagnostics to stderr. Fixes #72962. Thanks @vishutdhar.</li>
<li>Gateway/runtime: keep dirty-tree status calls from rebuilding live <code>dist</code>, clear stale task and restart state across in-process restarts, retry transient Discord lazy imports, and let channel startup continue after slow model warmup so browser, Discord, and voice-call sidecars come online. Thanks @vincentkoc.</li>
<li>Security/CodeQL: replace file SecretRef id gateway schema regex validation with segment-aligned predicates and set empty permissions on release summary/backfill jobs so the narrowed CodeQL profile stays clean. Thanks @vincentkoc.</li>
<li>Sessions: ignore future-dated session activity timestamps during reset freshness checks and cap future <code>updatedAt</code> values at the merge boundary so clock-skewed messages cannot keep stale sessions alive forever. Fixes #72989. Thanks @martingarramon.</li>
<li>Sessions: apply search, activity filters, and limits before gateway row enrichment so bounded session lists avoid scanning discarded transcripts. Carries forward #72978. Thanks @yeager.</li>
<li>Sessions: remove trajectory runtime and pointer sidecars when session maintenance prunes, caps, or disk-evicts their owning session, while preserving sidecars still referenced by live rows. Fixes #73000. Thanks @jared-rebel.</li>
<li>Plugins/CLI: allow managed plugin installs when the active extensions root is a symlink to a real state directory, while keeping nested target symlinks blocked and suppressing misleading hook-pack fallback errors for install-boundary failures. Fixes #72946. Thanks @mayank6136.</li>
<li>Providers/Ollama: mark discovered Ollama catalog models as supporting streaming usage metadata so token accounting stays enabled for local models. (#72976) Thanks @sdeyang.</li>
<li>Media understanding: reject malformed MIME values with trailing junk while preserving standard parameter tails before enrichment uses them. (#72914) Thanks @volcano303.</li>
<li>WebChat: keep bare <code>/new</code> and <code>/reset</code> prompts from producing empty transcript text by inserting the hidden session marker when the visible tail is blank. (#72863) Thanks @mahopan.</li>
<li>CLI/update: explain completion-cache refresh timeouts with manual refresh guidance instead of surfacing a raw low-level timeout. Fixes #72842. (#72850) Thanks @iot2edge.</li>
<li>Memory-core/dreaming: give narrative generation a 60-second timeout so slower local or remote models can finish instead of timing out at 15 seconds. Fixes #72837. (#72852) Thanks @RayWoo.</li>
<li>Plugins/hooks: inject each plugin's resolved config into internal hook event context without mutating the shared event object. (#72888) Thanks @jalapeno777.</li>
<li>Agents/ACP: pass the resolved ACP agent directory into media understanding so per-agent media caches and config are used for ACP-dispatched image turns. (#72832) Thanks @luyao618.</li>
<li>Gateway/Bonjour: truncate mDNS service names and host labels to the 63-byte DNS label limit at valid UTF-8 boundaries. (#72809) Thanks @luyao618.</li>
<li>Feishu: treat groups explicitly configured under channels.feishu.groups as admitted even when groupAllowFrom is empty, while preserving groupPolicy: "disabled" as a hard group block and keeping groups.\* wildcard defaults non-admitting. Fixes #67687. (#72789) Thanks @MoerAI.</li>
<li>Gateway/startup: keep hot Gateway boot paths on leaf config imports and add max-RSS reporting to the gateway startup bench so low-memory startup regressions are visible before release. Thanks @vincentkoc.</li>
<li>WebChat: read <code>chat.history</code> from active transcript branches, drop stale streamed assistant tails once final history catches up, and coalesce duplicate in-flight Control UI submits, so rewritten prompts, completed replies, and rapid send events no longer render or process twice. Fixes #72975, #72963, and #72974. Thanks @dmagdici, @lhtpluto, and @Benjamin5281999.</li>
<li>WebChat/TTS: persist automatic final-mode TTS audio as a supplemental audio-only transcript update instead of adding a second assistant message with the same visible text. Fixes #72830. Thanks @lhtpluto.</li>
<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>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>Providers/Ollama: honor <code>/api/show</code> capabilities when registering local models so non-tool Ollama models no longer receive the agent tool surface, and keep native Ollama thinking opt-in instead of enabling it by default. Fixes #64710 and duplicate #65343. Thanks @yuan-b, @netherby, @xilopaint, and @Diyforfun2026.</li>
<li>Control UI/Agents: remount the Overview model controls when switching agents so the primary-model picker cannot retain stale per-agent selection. Fixes #39392; carries forward #39401, notes the duplicate #39495 approach, and keeps #46275/#54724 broader stabilization out of scope. Thanks @daijunyi002, @SergioChan, @aworki, and @wsyjh8.</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: 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. Thanks @vincentkoc.</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>. Thanks @vincentkoc.</li>
<li>Gateway/plugins: resolve <code>gateway_start</code> cron hooks from live Gateway runtime state before the legacy deps fallback, so memory-core dreaming cron reconciliation keeps working on installs where <code>deps.cron</code> is not populated during service startup. Fixes #72835. Thanks @RayWoo.</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: inventory doctor-side deprecation migrations separately from runtime plugin compatibility so release sweeps preserve needed repairs while enforcing dated removal windows. Thanks @vincentkoc.</li>
<li>Plugins/compat: add missing dated compatibility records for legacy extension-api, memory registration, provider hook/type aliases, runtime aliases, channel SDK helpers, and approval/test utility shims. Thanks @vincentkoc.</li>
<li>Plugins/CLI: refresh the persisted registry after managed plugin files are removed so ClawHub uninstall cannot leave stale <code>plugins list</code> entries. Thanks @vincentkoc.</li>
<li>Plugins/CLI: make plugin install and uninstall config writes conflict-aware, clear stale denylist entries on explicit reinstall/removal, and delete managed plugin files only after config/index commit succeeds. Thanks @vincentkoc.</li>
<li>Plugins: fail <code>plugins update</code> when tracked plugin or hook updates error, keep bundled runtime-dependency repair behind restrictive allowlists, and reject package installs with unloadable extension entries. 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/chat: preserve repeated boundary characters while merging assistant chat stream deltas, including repeated digits, CJK characters, and markdown/table tokens. Fixes #63769; carries forward #63994 and #65457. Thanks @yon950905 and @mohuaxiao.</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. Thanks @vincentkoc.</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>TTS/BlueBubbles: pre-transcode synthesized MP3 audio to opus-in-CAF (mono, 24 kHz — validated against macOS 15.x Messages.app's native voice-memo CAF descriptor) on macOS hosts before handing the file to BlueBubbles, so iMessage renders the result as a native voice-memo bubble with proper duration and waveform UI instead of a plain file attachment. Adds an opt-in <code>tts.voice.preferAudioFileFormat</code> channel capability and a magic-byte sniff for the CAF container so the host-local-media validator (which uses <code>file-type</code> and didn't recognize CAF natively) can verify the pre-transcoded buffer. Channels that don't opt in are unaffected. (#72586) Fixes #72506. Thanks @omarshahine.</li>
<li>Feishu: retry WebSocket startup failures with monitor-owned backoff while preserving SDK-local heartbeat defaults, so persistent-connection startup failures no longer leave the monitor hung. Fixes #68766; related #42354 and #55532. Thanks @alex-xuweilong, @120106835, @sirfengyu, and @tianhaocui.</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.27/OpenClaw-2026.4.27.zip" length="50595360" type="application/octet-stream" sparkle:edSignature="X8DQNQNWVcvtpYLkhZcsKNpnA78ycyzgGlZaG0XBY1GIph3oZNUIpAszGGocJVqTK7+F89Au5ZPb60mOqJQ6DQ=="/>
</item>
</channel>
</rss>

View File

@@ -65,8 +65,8 @@ android {
applicationId = "ai.openclaw.app"
minSdk = 31
targetSdk = 36
versionCode = 2026050600
versionName = "2026.5.6"
versionCode = 2026050800
versionName = "2026.5.8"
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,9 @@
# OpenClaw iOS Changelog
## 2026.5.8 - 2026-05-08
Maintenance update for the current OpenClaw development release.
## 2026.5.6 - 2026-05-06
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.5.6
OPENCLAW_MARKETING_VERSION = 2026.5.6
OPENCLAW_IOS_VERSION = 2026.5.8
OPENCLAW_MARKETING_VERSION = 2026.5.8
OPENCLAW_BUILD_VERSION = 1
#include? "../build/Version.xcconfig"

View File

@@ -1,3 +1,3 @@
{
"version": "2026.5.6"
"version": "2026.5.8"
}

View File

@@ -8,6 +8,8 @@ import SwiftUI
@MainActor
@Observable
final class AppState {
private static let logger = Logger(subsystem: "ai.openclaw", category: "app-state")
private let isPreview: Bool
private var isInitializing = true
private var isApplyingRemoteTokenConfig = false
@@ -696,7 +698,10 @@ final class AppState {
remoteToken: self.remoteToken,
remoteTokenDirty: self.remoteTokenDirty))
guard synced.changed else { return }
OpenClawConfigFile.saveDict(synced.root)
guard OpenClawConfigFile.saveDict(synced.root) else {
Self.logger.warning("gateway config sync rejected to protect persisted gateway auth/mode")
return
}
}
func triggerVoiceEars(ttl: TimeInterval? = 5) {

View File

@@ -8,6 +8,7 @@ enum ConfigStore {
var saveLocal: (@MainActor @Sendable ([String: Any]) -> Void)?
var loadRemote: (@MainActor @Sendable () async -> [String: Any])?
var saveRemote: (@MainActor @Sendable ([String: Any]) async throws -> Void)?
var saveGateway: (@MainActor @Sendable ([String: Any]) async throws -> Void)?
}
private actor OverrideStore {
@@ -66,10 +67,19 @@ enum ConfigStore {
do {
try await self.saveToGateway(root)
} catch {
OpenClawConfigFile.saveDict(
guard self.shouldFallbackToLocalWrite(afterGatewaySaveError: error) else {
self.lastHash = nil
throw error
}
guard OpenClawConfigFile.saveDict(
root,
preserveExistingKeys: true,
allowGatewayAuthMutation: allowGatewayAuthMutation)
else {
throw NSError(domain: "ConfigStore", code: 2, userInfo: [
NSLocalizedDescriptionKey: "Local config write rejected to protect gateway auth/mode.",
])
}
}
}
}
@@ -89,8 +99,30 @@ enum ConfigStore {
}
}
private static func shouldFallbackToLocalWrite(afterGatewaySaveError error: Error) -> Bool {
let nsError = error as NSError
let message = "\(nsError.domain) \(nsError.localizedDescription)".lowercased()
let blockedFragments = [
"invalid_request",
"invalid request",
"invalid config",
"config changed since last load",
"base hash",
"basehash",
"unauthorized",
"token mismatch",
"auth",
]
return !blockedFragments.contains { message.contains($0) }
}
@MainActor
private static func saveToGateway(_ root: [String: Any]) async throws {
let overrides = await self.overrideStore.overrides
if let saveGateway = overrides.saveGateway {
try await saveGateway(root)
return
}
if self.lastHash == nil {
_ = await self.loadFromGateway()
}

View File

@@ -779,7 +779,10 @@ struct DebugSettings: View {
session["store"] = trimmed.isEmpty ? SessionLoader.defaultStorePath : trimmed
root["session"] = session
OpenClawConfigFile.saveDict(root)
guard OpenClawConfigFile.saveDict(root) else {
self.sessionStoreSaveError = "Config write rejected to protect gateway auth/mode."
return
}
self.sessionStoreSaveError = nil
}

View File

@@ -43,7 +43,8 @@ enum ExecApprovalEvaluator {
let allowAlwaysPatterns = ExecCommandResolution.resolveAllowAlwaysPatterns(
command: command,
cwd: cwd,
env: env)
env: env,
rawCommand: allowlistRawCommand)
let allowlistMatches = security == .allowlist
? ExecAllowlistMatcher.matchAll(entries: approvals.allowlist, resolutions: allowlistResolutions)
: []

View File

@@ -27,7 +27,7 @@ struct ExecCommandResolution {
{
// Allowlist resolution must follow actual argv execution for wrappers.
// `rawCommand` is caller-supplied display text and may be canonicalized.
let shell = ExecShellWrapperParser.extract(command: command, rawCommand: nil)
let shell = ExecShellWrapperParser.extractForAllowlist(command: command, rawCommand: rawCommand)
if shell.isWrapper {
// Fail closed when env modifiers precede a shell wrapper. This mirrors
// system-run binding behavior where such invocations must stay bound to
@@ -68,7 +68,8 @@ struct ExecCommandResolution {
static func resolveAllowAlwaysPatterns(
command: [String],
cwd: String?,
env: [String: String]?) -> [String]
env: [String: String]?,
rawCommand: String? = nil) -> [String]
{
var patterns: [String] = []
var seen = Set<String>()
@@ -76,6 +77,7 @@ struct ExecCommandResolution {
command: command,
cwd: cwd,
env: env,
rawCommand: rawCommand,
depth: 0,
patterns: &patterns,
seen: &seen)
@@ -152,6 +154,7 @@ struct ExecCommandResolution {
command: [String],
cwd: String?,
env: [String: String]?,
rawCommand: String?,
depth: Int,
patterns: inout [String],
seen: inout Set<String>)
@@ -162,13 +165,19 @@ struct ExecCommandResolution {
if let token0 = command.first?.trimmingCharacters(in: .whitespacesAndNewlines),
ExecCommandToken.basenameLower(token0) == "env",
let envUnwrapped = ExecEnvInvocationUnwrapper.unwrap(command),
!envUnwrapped.isEmpty
let envUnwrapped = ExecEnvInvocationUnwrapper.unwrapWithMetadata(command),
!envUnwrapped.command.isEmpty
{
if envUnwrapped.usesModifiers,
self.isAllowlistShellWrapper(command: envUnwrapped.command, rawCommand: rawCommand)
{
return
}
self.collectAllowAlwaysPatterns(
command: envUnwrapped,
command: envUnwrapped.command,
cwd: cwd,
env: env,
rawCommand: rawCommand,
depth: depth + 1,
patterns: &patterns,
seen: &seen)
@@ -180,13 +189,14 @@ struct ExecCommandResolution {
command: shellMultiplexer,
cwd: cwd,
env: env,
rawCommand: rawCommand,
depth: depth + 1,
patterns: &patterns,
seen: &seen)
return
}
let shell = ExecShellWrapperParser.extract(command: command, rawCommand: nil)
let shell = ExecShellWrapperParser.extractForAllowlist(command: command, rawCommand: rawCommand)
if shell.isWrapper {
guard let shellCommand = shell.command,
let segments = self.splitShellCommandChain(shellCommand)
@@ -202,6 +212,7 @@ struct ExecCommandResolution {
command: tokens,
cwd: cwd,
env: env,
rawCommand: nil,
depth: depth + 1,
patterns: &patterns,
seen: &seen)
@@ -218,6 +229,10 @@ struct ExecCommandResolution {
patterns.append(pattern)
}
private static func isAllowlistShellWrapper(command: [String], rawCommand: String?) -> Bool {
ExecShellWrapperParser.extractForAllowlist(command: command, rawCommand: rawCommand).isWrapper
}
private static func unwrapShellMultiplexerInvocation(_ argv: [String]) -> [String]? {
guard let token0 = argv.first?.trimmingCharacters(in: .whitespacesAndNewlines), !token0.isEmpty else {
return nil

View File

@@ -0,0 +1,278 @@
import Foundation
enum ExecInlineCommandParser {
struct Match {
let tokenIndex: Int
let inlineCommand: String?
let valueTokenOffset: Int
init(tokenIndex: Int, inlineCommand: String?, valueTokenOffset: Int = 1) {
self.tokenIndex = tokenIndex
self.inlineCommand = inlineCommand
self.valueTokenOffset = valueTokenOffset
}
}
private struct CombinedCommandFlag {
let attachedCommand: String?
let separateValueCount: Int
}
private static let posixShellOptionsWithSeparateValues = Set([
"--init-file",
"--rcfile",
"-O",
"-o",
"+O",
"+o",
])
static func hasPosixInteractiveStartupBeforeInlineCommand(
_ argv: [String],
flags: Set<String>) -> Bool
{
var idx = 1
var sawInteractiveMode = false
while idx < argv.count {
let token = argv[idx].trimmingCharacters(in: .whitespacesAndNewlines)
if token.isEmpty {
idx += 1
continue
}
if token == "--" {
return false
}
if self.isPosixInteractiveModeOption(token) {
sawInteractiveMode = true
}
if flags.contains(token) || self.isCombinedCommandFlag(token) {
return sawInteractiveMode
}
if !token.hasPrefix("-"), !token.hasPrefix("+") {
return false
}
let combinedValueCount = self.combinedSeparateValueOptionCount(token)
if combinedValueCount > 0 {
idx += 1 + combinedValueCount
continue
}
if self.consumesSeparateValue(token) {
idx += 2
continue
}
idx += 1
}
return false
}
static func hasPosixLoginStartupBeforeInlineCommand(
_ argv: [String],
flags: Set<String>) -> Bool
{
var idx = 1
var sawLoginMode = false
while idx < argv.count {
let token = argv[idx].trimmingCharacters(in: .whitespacesAndNewlines)
if token.isEmpty {
idx += 1
continue
}
if token == "--" {
return false
}
if token == "--login" || self.isPosixShortOption(token, containing: "l") {
sawLoginMode = true
}
if flags.contains(token) || self.isCombinedCommandFlag(token) {
return sawLoginMode
}
if !token.hasPrefix("-"), !token.hasPrefix("+") {
return false
}
let combinedValueCount = self.combinedSeparateValueOptionCount(token)
if combinedValueCount > 0 {
idx += 1 + combinedValueCount
continue
}
if self.consumesSeparateValue(token) {
idx += 2
continue
}
idx += 1
}
return false
}
static func hasFishInitCommandOption(_ argv: [String]) -> Bool {
var idx = 1
while idx < argv.count {
let token = argv[idx].trimmingCharacters(in: .whitespacesAndNewlines)
if token.isEmpty {
idx += 1
continue
}
if token == "--" {
return false
}
if token == "-C" || token == "--init-command" {
return true
}
if token.hasPrefix("-C"), token != "-C" {
return true
}
if token.hasPrefix("--init-command=") {
return true
}
if !token.hasPrefix("-"), !token.hasPrefix("+") {
return false
}
idx += 1
}
return false
}
static func hasFishAttachedCommandOption(_ argv: [String]) -> Bool {
var idx = 1
while idx < argv.count {
let token = argv[idx].trimmingCharacters(in: .whitespacesAndNewlines)
if token.isEmpty {
idx += 1
continue
}
if token == "--" {
return false
}
if token.hasPrefix("-c"), token != "-c" {
return true
}
if !token.hasPrefix("-"), !token.hasPrefix("+") {
return false
}
idx += 1
}
return false
}
static func findMatch(
_ argv: [String],
flags: Set<String>,
allowCombinedC: Bool) -> Match?
{
var idx = 1
while idx < argv.count {
let token = argv[idx].trimmingCharacters(in: .whitespacesAndNewlines)
if token.isEmpty {
idx += 1
continue
}
if token == "--" {
break
}
let comparableToken = allowCombinedC ? token : token.lowercased()
if flags.contains(comparableToken) {
return Match(tokenIndex: idx, inlineCommand: nil)
}
if allowCombinedC, let combined = self.parseCombinedCommandFlag(token) {
if let attachedCommand = combined.attachedCommand {
return Match(tokenIndex: idx, inlineCommand: attachedCommand, valueTokenOffset: 0)
}
return Match(
tokenIndex: idx,
inlineCommand: nil,
valueTokenOffset: 1 + combined.separateValueCount)
}
if allowCombinedC, !token.hasPrefix("-"), !token.hasPrefix("+") {
break
}
let combinedValueCount = allowCombinedC ? self.combinedSeparateValueOptionCount(token) : 0
if combinedValueCount > 0 {
idx += 1 + combinedValueCount
continue
}
if allowCombinedC, self.consumesSeparateValue(token) {
idx += 2
continue
}
idx += 1
}
return nil
}
static func extractInlineCommand(
_ argv: [String],
flags: Set<String>,
allowCombinedC: Bool) -> String?
{
guard let match = self.findMatch(argv, flags: flags, allowCombinedC: allowCombinedC) else {
return nil
}
if let inlineCommand = match.inlineCommand {
return inlineCommand
}
let nextIndex = match.tokenIndex + match.valueTokenOffset
let payload = nextIndex < argv.count
? argv[nextIndex].trimmingCharacters(in: .whitespacesAndNewlines)
: ""
return payload.isEmpty ? nil : payload
}
private static func isCombinedCommandFlag(_ token: String) -> Bool {
self.parseCombinedCommandFlag(token) != nil
}
private static func parseCombinedCommandFlag(_ token: String) -> CombinedCommandFlag? {
let chars = Array(token)
guard chars.count >= 2, chars[0] == "-", chars[1] != "-" else {
return nil
}
let optionChars = Array(chars.dropFirst())
guard let commandFlagIndex = optionChars.firstIndex(of: "c") else {
return nil
}
if optionChars.contains("-") {
return nil
}
let suffix = String(optionChars.dropFirst(commandFlagIndex + 1))
if !suffix.isEmpty,
suffix.range(of: #"[^A-Za-z]"#, options: .regularExpression) != nil
{
return CombinedCommandFlag(attachedCommand: suffix, separateValueCount: 0)
}
let separateValueCount = optionChars.reduce(0) { count, char in
count + ((char == "o" || char == "O") ? 1 : 0)
}
return CombinedCommandFlag(attachedCommand: nil, separateValueCount: separateValueCount)
}
private static func combinedSeparateValueOptionCount(_ token: String) -> Int {
let chars = Array(token)
guard chars.count >= 2, chars[0] == "-" || chars[0] == "+", chars[1] != "-" else {
return 0
}
if chars.dropFirst().contains("-") {
return 0
}
return chars.dropFirst().reduce(0) { count, char in
count + ((char == "o" || char == "O") ? 1 : 0)
}
}
private static func consumesSeparateValue(_ token: String) -> Bool {
self.posixShellOptionsWithSeparateValues.contains(token)
}
private static func isPosixInteractiveModeOption(_ token: String) -> Bool {
token == "--interactive" || self.isPosixShortOption(token, containing: "i")
}
private static func isPosixShortOption(_ token: String, containing option: Character) -> Bool {
let chars = Array(token)
guard chars.count >= 2, chars[0] == "-", chars[1] != "-" else {
return false
}
if chars.dropFirst().contains("-") {
return false
}
return chars.dropFirst().contains(option)
}
}

View File

@@ -6,9 +6,10 @@ enum ExecShellWrapperParser {
let command: String?
static let notWrapper = ParsedShellWrapper(isWrapper: false, command: nil)
static let blockedWrapper = ParsedShellWrapper(isWrapper: true, command: nil)
}
private enum Kind {
private enum Kind: Equatable {
case posix
case cmd
case powershell
@@ -27,14 +28,34 @@ enum ExecShellWrapperParser {
WrapperSpec(kind: .cmd, names: ["cmd.exe", "cmd"]),
WrapperSpec(kind: .powershell, names: ["powershell", "powershell.exe", "pwsh", "pwsh.exe"]),
]
private static let loginStartupShellNames = Set(["ash", "bash", "dash", "fish", "ksh", "sh", "zsh"])
static func extract(command: [String], rawCommand: String?) -> ParsedShellWrapper {
let trimmedRaw = rawCommand?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
let preferredRaw = trimmedRaw.isEmpty ? nil : trimmedRaw
return self.extract(command: command, preferredRaw: preferredRaw, depth: 0)
return self.extract(
command: command,
preferredRaw: preferredRaw,
failClosedOnStartupWrappers: false,
depth: 0)
}
private static func extract(command: [String], preferredRaw: String?, depth: Int) -> ParsedShellWrapper {
static func extractForAllowlist(command: [String], rawCommand: String?) -> ParsedShellWrapper {
let trimmedRaw = rawCommand?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
let preferredRaw = trimmedRaw.isEmpty ? nil : trimmedRaw
return self.extract(
command: command,
preferredRaw: preferredRaw,
failClosedOnStartupWrappers: true,
depth: 0)
}
private static func extract(
command: [String],
preferredRaw: String?,
failClosedOnStartupWrappers: Bool,
depth: Int) -> ParsedShellWrapper
{
guard depth < ExecEnvInvocationUnwrapper.maxWrapperDepth else {
return .notWrapper
}
@@ -47,19 +68,96 @@ enum ExecShellWrapperParser {
guard let unwrapped = ExecEnvInvocationUnwrapper.unwrap(command) else {
return .notWrapper
}
return self.extract(command: unwrapped, preferredRaw: preferredRaw, depth: depth + 1)
return self.extract(
command: unwrapped,
preferredRaw: preferredRaw,
failClosedOnStartupWrappers: failClosedOnStartupWrappers,
depth: depth + 1)
}
guard let spec = self.wrapperSpecs.first(where: { $0.names.contains(base0) }) else {
return .notWrapper
}
if spec.kind == .posix,
base0 == "fish",
ExecInlineCommandParser.hasFishAttachedCommandOption(command)
{
return .blockedWrapper
}
let includeLegacyLoginInlineForm = failClosedOnStartupWrappers &&
!self.legacyLoginInlinePayloadMatchesRaw(
command: command,
spec: spec,
base0: base0,
preferredRaw: preferredRaw)
if self.startupWrapperRequiresFullArgv(
command: command,
spec: spec,
base0: base0,
includeLegacyLoginInlineForm: includeLegacyLoginInlineForm)
{
return .blockedWrapper
}
guard let payload = self.extractPayload(command: command, spec: spec) else {
return .notWrapper
}
let normalized = preferredRaw ?? payload
let normalized = failClosedOnStartupWrappers ? payload : preferredRaw ?? payload
return ParsedShellWrapper(isWrapper: true, command: normalized)
}
private static func startupWrapperRequiresFullArgv(
command: [String],
spec: WrapperSpec,
base0: String,
includeLegacyLoginInlineForm: Bool) -> Bool
{
guard spec.kind == .posix else {
return false
}
if base0 == "fish",
ExecInlineCommandParser.hasFishInitCommandOption(command)
{
return true
}
if self.loginStartupShellNames.contains(base0),
ExecInlineCommandParser.hasPosixLoginStartupBeforeInlineCommand(
command,
flags: self.posixInlineFlags)
{
return includeLegacyLoginInlineForm || !self.isLegacyShLoginInlineForm(command, base0: base0)
}
return ExecInlineCommandParser.hasPosixInteractiveStartupBeforeInlineCommand(
command,
flags: self.posixInlineFlags)
}
private static func isLegacyLoginInlineForm(_ command: [String]) -> Bool {
guard command.count > 1 else {
return false
}
return command[1].trimmingCharacters(in: .whitespacesAndNewlines) == "-lc"
}
private static func isLegacyShLoginInlineForm(_ command: [String], base0: String) -> Bool {
base0 == "sh" && self.isLegacyLoginInlineForm(command)
}
private static func legacyLoginInlinePayloadMatchesRaw(
command: [String],
spec: WrapperSpec,
base0: String,
preferredRaw: String?) -> Bool
{
guard let preferredRaw,
base0 == "sh",
self.isLegacyLoginInlineForm(command),
let payload = self.extractPayload(command: command, spec: spec)
else {
return false
}
return payload == preferredRaw.trimmingCharacters(in: .whitespacesAndNewlines)
}
private static func extractPayload(command: [String], spec: WrapperSpec) -> String? {
switch spec.kind {
case .posix:
@@ -72,12 +170,10 @@ enum ExecShellWrapperParser {
}
private static func extractPosixInlineCommand(_ command: [String]) -> String? {
let flag = command.count > 1 ? command[1].trimmingCharacters(in: .whitespacesAndNewlines) : ""
guard self.posixInlineFlags.contains(flag.lowercased()) else {
return nil
}
let payload = command.count > 2 ? command[2].trimmingCharacters(in: .whitespacesAndNewlines) : ""
return payload.isEmpty ? nil : payload
ExecInlineCommandParser.extractInlineCommand(
command,
flags: self.posixInlineFlags,
allowCombinedC: true)
}
private static func extractCmdInlineCommand(_ command: [String]) -> String? {
@@ -97,10 +193,10 @@ enum ExecShellWrapperParser {
if token.isEmpty { continue }
if token == "--" { break }
if self.powershellInlineFlags.contains(token) {
let payload = idx + 1 < command.count
? command[idx + 1].trimmingCharacters(in: .whitespacesAndNewlines)
: ""
return payload.isEmpty ? nil : payload
return ExecInlineCommandParser.extractInlineCommand(
command,
flags: self.powershellInlineFlags,
allowCombinedC: false)
}
}
return nil

View File

@@ -326,40 +326,12 @@ enum ExecSystemRunCommandValidator {
return current
}
private struct InlineCommandTokenMatch {
var tokenIndex: Int
var inlineCommand: String?
}
private static func findInlineCommandTokenMatch(
_ argv: [String],
flags: Set<String>,
allowCombinedC: Bool) -> InlineCommandTokenMatch?
allowCombinedC: Bool) -> ExecInlineCommandParser.Match?
{
var idx = 1
while idx < argv.count {
let token = argv[idx].trimmingCharacters(in: .whitespacesAndNewlines)
if token.isEmpty {
idx += 1
continue
}
let lower = token.lowercased()
if lower == "--" {
break
}
if flags.contains(lower) {
return InlineCommandTokenMatch(tokenIndex: idx, inlineCommand: nil)
}
if allowCombinedC, let inlineOffset = self.combinedCommandInlineOffset(token) {
let inline = String(token.dropFirst(inlineOffset))
.trimmingCharacters(in: .whitespacesAndNewlines)
return InlineCommandTokenMatch(
tokenIndex: idx,
inlineCommand: inline.isEmpty ? nil : inline)
}
idx += 1
}
return nil
ExecInlineCommandParser.findMatch(argv, flags: flags, allowCombinedC: allowCombinedC)
}
private static func resolveInlineCommandTokenIndex(
@@ -373,24 +345,10 @@ enum ExecSystemRunCommandValidator {
if match.inlineCommand != nil {
return match.tokenIndex
}
let nextIndex = match.tokenIndex + 1
let nextIndex = match.tokenIndex + match.valueTokenOffset
return nextIndex < argv.count ? nextIndex : nil
}
private static func combinedCommandInlineOffset(_ token: String) -> Int? {
let chars = Array(token.lowercased())
guard chars.count >= 2, chars[0] == "-", chars[1] != "-" else {
return nil
}
if chars.dropFirst().contains("-") {
return nil
}
guard let commandIndex = chars.firstIndex(of: "c"), commandIndex > 0 else {
return nil
}
return commandIndex + 1
}
private static func extractShellInlinePayload(
_ argv: [String],
normalizedWrapper: String) -> String?
@@ -421,7 +379,7 @@ enum ExecSystemRunCommandValidator {
if let inlineCommand = match.inlineCommand {
return inlineCommand
}
let nextIndex = match.tokenIndex + 1
let nextIndex = match.tokenIndex + match.valueTokenOffset
return self.trimmedNonEmpty(nextIndex < argv.count ? argv[nextIndex] : nil)
}

View File

@@ -52,14 +52,16 @@ enum OpenClawConfigFile {
}
}
@discardableResult
static func saveDict(
_ dict: [String: Any],
preserveExistingKeys: Bool = false,
allowGatewayAuthMutation: Bool = false)
-> Bool
{
self.withFileLock {
// Nix mode disables config writes in production, but tests rely on saving temp configs.
if ProcessInfo.processInfo.isNixMode, !ProcessInfo.processInfo.isRunningTests { return }
if ProcessInfo.processInfo.isNixMode, !ProcessInfo.processInfo.isRunningTests { return false }
let url = self.url()
let previousData = try? Data(contentsOf: url)
let previousRoot = previousData.flatMap { self.parseConfigData($0) }
@@ -81,12 +83,7 @@ enum OpenClawConfigFile {
do {
let data = try JSONSerialization.data(withJSONObject: output, options: [.prettyPrinted, .sortedKeys])
try FileManager().createDirectory(
at: url.deletingLastPathComponent(),
withIntermediateDirectories: true)
try data.write(to: url, options: [.atomic])
let nextBytes = data.count
let nextAttributes = try? FileManager().attributesOfItem(atPath: url.path)
let gatewayModeAfter = self.gatewayMode(output)
var suspicious = self.configWriteSuspiciousReasons(
existsBefore: previousData != nil,
@@ -98,6 +95,44 @@ enum OpenClawConfigFile {
if preservedGatewayAuth {
suspicious.append("gateway-auth-preserved")
}
let blocking = self.configWriteBlockingReasons(suspicious)
if !blocking.isEmpty {
let rejectedPath = self.persistRejectedConfigWrite(data: data, configURL: url)
self.logger.warning("config write rejected (\(blocking.joined(separator: ", "))) at \(url.path)")
self.appendConfigWriteAudit([
"result": "rejected",
"configPath": url.path,
"existsBefore": previousData != nil,
"previousBytes": previousBytes ?? NSNull(),
"nextBytes": nextBytes,
"previousDev": self.fileSystemNumber(previousAttributes?[.systemNumber]) ?? NSNull(),
"nextDev": NSNull(),
"previousIno": self.fileSystemNumber(previousAttributes?[.systemFileNumber]) ?? NSNull(),
"nextIno": NSNull(),
"previousMode": self.posixMode(previousAttributes?[.posixPermissions]) ?? NSNull(),
"nextMode": NSNull(),
"previousNlink": self.fileAttributeInt(previousAttributes?[.referenceCount]) ?? NSNull(),
"nextNlink": NSNull(),
"previousUid": self.fileAttributeInt(previousAttributes?[.ownerAccountID]) ?? NSNull(),
"nextUid": NSNull(),
"previousGid": self.fileAttributeInt(previousAttributes?[.groupOwnerAccountID]) ?? NSNull(),
"nextGid": NSNull(),
"hasMetaBefore": hadMetaBefore,
"hasMetaAfter": self.hasMeta(output),
"gatewayModeBefore": gatewayModeBefore ?? NSNull(),
"gatewayModeAfter": gatewayModeAfter ?? NSNull(),
"preservedGatewayAuth": preservedGatewayAuth,
"suspicious": suspicious,
"blocking": blocking,
"rejectedPath": rejectedPath ?? NSNull(),
])
return false
}
try FileManager().createDirectory(
at: url.deletingLastPathComponent(),
withIntermediateDirectories: true)
try data.write(to: url, options: [.atomic])
let nextAttributes = try? FileManager().attributesOfItem(atPath: url.path)
if !suspicious.isEmpty {
self.logger.warning("config write anomaly (\(suspicious.joined(separator: ", "))) at \(url.path)")
}
@@ -123,9 +158,11 @@ enum OpenClawConfigFile {
"hasMetaAfter": self.hasMeta(output),
"gatewayModeBefore": gatewayModeBefore ?? NSNull(),
"gatewayModeAfter": gatewayModeAfter ?? NSNull(),
"preservedGatewayAuth": preservedGatewayAuth,
"suspicious": suspicious,
])
self.observeConfigRead(data: data, root: output, configURL: url, valid: true)
return true
} catch {
self.logger.error("config save failed: \(error.localizedDescription)")
self.appendConfigWriteAudit([
@@ -138,9 +175,11 @@ enum OpenClawConfigFile {
"hasMetaAfter": self.hasMeta(output),
"gatewayModeBefore": gatewayModeBefore ?? NSNull(),
"gatewayModeAfter": self.gatewayMode(output) ?? NSNull(),
"preservedGatewayAuth": preservedGatewayAuth,
"suspicious": preservedGatewayAuth ? ["gateway-auth-preserved"] : [],
"error": error.localizedDescription,
])
return false
}
}
}
@@ -416,6 +455,12 @@ enum OpenClawConfigFile {
return reasons
}
private static func configWriteBlockingReasons(_ suspicious: [String]) -> [String] {
suspicious.filter { reason in
reason.hasPrefix("size-drop:") || reason == "gateway-mode-removed"
}
}
private static func configAuditLogURL() -> URL {
self.stateDirURL()
.appendingPathComponent("logs", isDirectory: true)
@@ -594,6 +639,26 @@ enum OpenClawConfigFile {
}
}
private static func persistRejectedConfigWrite(data: Data, configURL: URL) -> String? {
let timestamp = ISO8601DateFormatter().string(from: Date())
let url = configURL.deletingLastPathComponent()
.appendingPathComponent("\(configURL.lastPathComponent).rejected.\(self.configTimestampToken(timestamp))")
let fileManager = FileManager()
let privatePermissions: NSNumber = 0o600
if fileManager.fileExists(atPath: url.path) {
try? fileManager.setAttributes([.posixPermissions: privatePermissions], ofItemAtPath: url.path)
return url.path
}
guard fileManager.createFile(
atPath: url.path,
contents: data,
attributes: [.posixPermissions: privatePermissions])
else {
return nil
}
return url.path
}
private static func observeConfigRead(data: Data, root: [String: Any]?, configURL: URL, valid: Bool) {
let observedAt = ISO8601DateFormatter().string(from: Date())
let current = self.configFingerprint(data: data, root: root, configURL: configURL, observedAt: observedAt)

View File

@@ -15,9 +15,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>2026.5.6</string>
<string>2026.5.8</string>
<key>CFBundleVersion</key>
<string>2026050600</string>
<string>2026050800</string>
<key>CFBundleIconFile</key>
<string>OpenClaw</string>
<key>CFBundleURLTypes</key>

View File

@@ -259,4 +259,37 @@ struct AppStateRemoteConfigTests {
remoteTokenDirty: true))
#expect((cleared["token"] as? String) == nil)
}
@Test
func `synced gateway root preserves gateway auth across mode changes`() {
let initialRoot: [String: Any] = [
"gateway": [
"mode": "remote",
"auth": [
"mode": "token",
"token": "test-token", // pragma: allowlist secret
],
"remote": [
"transport": "direct",
"url": "wss://old-gateway.example",
],
],
]
let localRoot = AppState._testSyncedGatewayRoot(
currentRoot: initialRoot,
draft: .init(
connectionMode: .local,
remoteTransport: .ssh,
remoteTarget: "",
remoteIdentity: "",
remoteUrl: "",
remoteToken: "",
remoteTokenDirty: false))
let localGateway = localRoot["gateway"] as? [String: Any]
let auth = localGateway?["auth"] as? [String: Any]
#expect(localGateway?["mode"] as? String == "local")
#expect(auth?["mode"] as? String == "token")
#expect(auth?["token"] as? String == "test-token") // pragma: allowlist secret
}
}

View File

@@ -1,3 +1,4 @@
import Foundation
import Testing
@testable import OpenClaw
@@ -65,4 +66,76 @@ struct ConfigStoreTests {
#expect(localHit)
#expect(!remoteHit)
}
@Test func `local save does not fall back to direct write after stale gateway rejection`() async throws {
let stateDir = FileManager().temporaryDirectory
.appendingPathComponent("openclaw-state-\(UUID().uuidString)", isDirectory: true)
let configPath = stateDir.appendingPathComponent("openclaw.json")
defer { try? FileManager().removeItem(at: stateDir) }
try await TestIsolation.withEnvValues([
"OPENCLAW_STATE_DIR": stateDir.path,
"OPENCLAW_CONFIG_PATH": configPath.path,
]) {
OpenClawConfigFile.saveDict([
"gateway": [
"mode": "local",
"auth": [
"mode": "token",
"token": "test-token", // pragma: allowlist secret
],
],
])
let before = try String(contentsOf: configPath, encoding: .utf8)
await ConfigStore._testSetOverrides(.init(
isRemoteMode: { false },
saveGateway: { _ in
throw NSError(domain: "Gateway", code: 0, userInfo: [
NSLocalizedDescriptionKey: "config changed since last load; re-run config.get and retry",
])
}))
var didThrow = false
do {
try await ConfigStore.save(["browser": ["enabled": false]])
} catch {
didThrow = true
}
await ConfigStore._testClearOverrides()
#expect(didThrow)
let after = try String(contentsOf: configPath, encoding: .utf8)
#expect(after == before)
}
}
@Test func `local save can fall back to protected direct write when gateway is unavailable`() async throws {
let stateDir = FileManager().temporaryDirectory
.appendingPathComponent("openclaw-state-\(UUID().uuidString)", isDirectory: true)
let configPath = stateDir.appendingPathComponent("openclaw.json")
defer { try? FileManager().removeItem(at: stateDir) }
try await TestIsolation.withEnvValues([
"OPENCLAW_STATE_DIR": stateDir.path,
"OPENCLAW_CONFIG_PATH": configPath.path,
]) {
await ConfigStore._testSetOverrides(.init(
isRemoteMode: { false },
saveGateway: { _ in
throw NSError(domain: "Gateway", code: 0, userInfo: [
NSLocalizedDescriptionKey: "gateway not configured",
])
}))
try await ConfigStore.save([
"gateway": ["mode": "local"],
"browser": ["enabled": false],
])
await ConfigStore._testClearOverrides()
let data = try Data(contentsOf: configPath)
let root = try JSONSerialization.jsonObject(with: data) as? [String: Any]
#expect(((root?["browser"] as? [String: Any])?["enabled"] as? Bool) == false)
#expect((root?["meta"] as? [String: Any]) != nil)
}
}
}

View File

@@ -111,7 +111,7 @@ struct ExecAllowlistTests {
}
@Test func `resolve for allowlist splits shell chains`() {
let command = ["/bin/sh", "-lc", "echo allowlisted && /usr/bin/touch /tmp/openclaw-allowlist-test"]
let command = ["/bin/sh", "-c", "echo allowlisted && /usr/bin/touch /tmp/openclaw-allowlist-test"]
let resolutions = ExecCommandResolution.resolveForAllowlist(
command: command,
rawCommand: "echo allowlisted && /usr/bin/touch /tmp/openclaw-allowlist-test",
@@ -122,9 +122,109 @@ struct ExecAllowlistTests {
#expect(resolutions[1].executableName == "touch")
}
@Test func `resolve for allowlist splits posix combined c flag payloads`() {
for command in [
["/bin/bash", "-xc", "/usr/bin/printf safe_marker"],
["/bin/bash", "-ec", "/usr/bin/printf safe_marker"],
["/bin/bash", "-euxc", "/usr/bin/printf safe_marker"],
["/bin/bash", "-cx", "/usr/bin/printf safe_marker"],
["/bin/bash", "-O", "extglob", "-xc", "/usr/bin/printf safe_marker"],
["/bin/bash", "-co", "vi", "/usr/bin/printf safe_marker"],
["/bin/bash", "-oc", "vi", "/usr/bin/printf safe_marker"],
["/bin/bash", "-cO", "extglob", "/usr/bin/printf safe_marker"],
["/bin/bash", "-xo", "vi", "-c", "/usr/bin/printf safe_marker"],
["/bin/bash", "-xO", "extglob", "-c", "/usr/bin/printf safe_marker"],
["/bin/bash", "+xo", "vi", "-c", "/usr/bin/printf safe_marker"],
["/bin/bash", "--rcfile", "/tmp/rc", "-c", "/usr/bin/printf safe_marker"],
["/bin/bash", "--init-file=/tmp/rc", "-c", "/usr/bin/printf safe_marker"],
] {
let resolutions = ExecCommandResolution.resolveForAllowlist(
command: command,
rawCommand: nil,
cwd: nil,
env: ["PATH": "/usr/bin:/bin"])
#expect(resolutions.count == 1)
#expect(resolutions[0].resolvedPath == "/usr/bin/printf")
#expect(resolutions[0].executableName == "printf")
}
}
@Test func `resolve for allowlist treats c after posix shell operand as direct exec`() {
for command in [
["/bin/bash", "./script.sh", "-c", "/usr/bin/printf safe_marker"],
["/bin/bash", "-x", "-C", "echo ok", "-c", "/usr/bin/printf safe_marker"],
] {
let resolutions = ExecCommandResolution.resolveForAllowlist(
command: command,
rawCommand: nil,
cwd: "/tmp",
env: ["PATH": "/usr/bin:/bin"])
#expect(resolutions.count == 1)
#expect(resolutions[0].resolvedPath == "/bin/bash")
#expect(resolutions[0].executableName == "bash")
}
}
@Test func `resolve for allowlist fails closed for interactive posix shell wrappers`() {
for command in [
["/bin/bash", "-i", "-c", "/usr/bin/printf safe_marker"],
["/bin/bash", "-ic", "/usr/bin/printf safe_marker"],
["/bin/bash", "--rcfile", "/tmp/payload.sh", "-i", "-c", "/usr/bin/printf safe_marker"],
["/usr/bin/fish", "--interactive", "-c", "/usr/bin/printf safe_marker"],
] {
let resolutions = ExecCommandResolution.resolveForAllowlist(
command: command,
rawCommand: nil,
cwd: nil,
env: ["PATH": "/usr/bin:/bin"])
#expect(resolutions.isEmpty)
}
}
@Test func `resolve for allowlist fails closed for login shell wrappers`() {
for command in [
["/bin/bash", "-l", "-c", "/usr/bin/printf safe_marker"],
["/bin/bash", "--login", "-c", "/usr/bin/printf safe_marker"],
["/bin/bash", "-xlc", "/usr/bin/printf safe_marker"],
["/bin/dash", "-lc", "/usr/bin/printf safe_marker"],
["ash", "-lc", "/usr/bin/printf safe_marker"],
["/usr/bin/fish", "-l", "-c", "/usr/bin/printf safe_marker"],
["/usr/bin/fish", "--login", "-c", "/usr/bin/printf safe_marker"],
["/bin/sh", "-lc", "/usr/bin/printf safe_marker"],
["/bin/sh", "-x", "-lc", "/usr/bin/printf safe_marker"],
["/usr/bin/env", "/bin/sh", "-lc", "/usr/bin/printf safe_marker"],
] {
let resolutions = ExecCommandResolution.resolveForAllowlist(
command: command,
rawCommand: nil,
cwd: nil,
env: ["PATH": "/usr/bin:/bin"])
#expect(resolutions.isEmpty)
}
}
@Test func `resolve for allowlist fails closed for fish init command wrappers`() {
for command in [
["/usr/bin/fish", "--init-command=/tmp/payload.fish", "-c", "/usr/bin/printf safe_marker"],
["/usr/bin/fish", "--init-command", "/tmp/payload.fish", "-c", "/usr/bin/printf safe_marker"],
["/usr/bin/fish", "-C", "/tmp/payload.fish", "-c", "/usr/bin/printf safe_marker"],
["/usr/bin/fish", "-C/tmp/payload.fish", "-c", "/usr/bin/printf safe_marker"],
["/usr/bin/fish", "--init-command", "-c; /tmp/payload.fish", "/usr/bin/printf safe_marker"],
["/usr/bin/fish", "-C", "-c", "/usr/bin/printf safe_marker"],
["/usr/bin/fish", "-c/tmp/payload.fish", "/usr/bin/printf safe_marker"],
] {
let resolutions = ExecCommandResolution.resolveForAllowlist(
command: command,
rawCommand: nil,
cwd: nil,
env: ["PATH": "/usr/bin:/bin"])
#expect(resolutions.isEmpty)
}
}
@Test func `resolve for allowlist uses wrapper argv payload even with canonical raw command`() {
let command = ["/bin/sh", "-lc", "echo allowlisted && /usr/bin/touch /tmp/openclaw-allowlist-test"]
let canonicalRaw = "/bin/sh -lc \"echo allowlisted && /usr/bin/touch /tmp/openclaw-allowlist-test\""
let command = ["/bin/sh", "-c", "echo allowlisted && /usr/bin/touch /tmp/openclaw-allowlist-test"]
let canonicalRaw = "/bin/sh -c \"echo allowlisted && /usr/bin/touch /tmp/openclaw-allowlist-test\""
let resolutions = ExecCommandResolution.resolveForAllowlist(
command: command,
rawCommand: canonicalRaw,
@@ -135,6 +235,25 @@ struct ExecAllowlistTests {
#expect(resolutions[1].executableName == "touch")
}
@Test func `resolve for allowlist preserves generated sh lc raw payload binding`() {
let command = ["/bin/sh", "-lc", "/usr/bin/printf safe_marker"]
let resolutions = ExecCommandResolution.resolveForAllowlist(
command: command,
rawCommand: "/usr/bin/printf safe_marker",
cwd: nil,
env: ["PATH": "/usr/bin:/bin"])
#expect(resolutions.count == 1)
#expect(resolutions[0].resolvedPath == "/usr/bin/printf")
#expect(resolutions[0].executableName == "printf")
let rawlessResolutions = ExecCommandResolution.resolveForAllowlist(
command: command,
rawCommand: nil,
cwd: nil,
env: ["PATH": "/usr/bin:/bin"])
#expect(rawlessResolutions.isEmpty)
}
@Test func `resolve for allowlist fails closed for env modified shell wrappers`() {
let command = ["/usr/bin/env", "BASH_ENV=/tmp/payload.sh", "bash", "-lc", "echo allowlisted"]
let canonicalRaw = "/usr/bin/env BASH_ENV=/tmp/payload.sh bash -lc \"echo allowlisted\""
@@ -158,7 +277,7 @@ struct ExecAllowlistTests {
}
@Test func `resolve for allowlist keeps quoted operators in single segment`() {
let command = ["/bin/sh", "-lc", "echo \"a && b\""]
let command = ["/bin/sh", "-c", "echo \"a && b\""]
let resolutions = ExecCommandResolution.resolveForAllowlist(
command: command,
rawCommand: "echo \"a && b\"",
@@ -169,7 +288,7 @@ struct ExecAllowlistTests {
}
@Test func `resolve for allowlist fails closed on command substitution`() {
let command = ["/bin/sh", "-lc", "echo $(/usr/bin/touch /tmp/openclaw-allowlist-test-subst)"]
let command = ["/bin/sh", "-c", "echo $(/usr/bin/touch /tmp/openclaw-allowlist-test-subst)"]
let resolutions = ExecCommandResolution.resolveForAllowlist(
command: command,
rawCommand: "echo $(/usr/bin/touch /tmp/openclaw-allowlist-test-subst)",
@@ -179,7 +298,7 @@ struct ExecAllowlistTests {
}
@Test func `resolve for allowlist fails closed on quoted command substitution`() {
let command = ["/bin/sh", "-lc", "echo \"ok $(/usr/bin/touch /tmp/openclaw-allowlist-test-quoted-subst)\""]
let command = ["/bin/sh", "-c", "echo \"ok $(/usr/bin/touch /tmp/openclaw-allowlist-test-quoted-subst)\""]
let resolutions = ExecCommandResolution.resolveForAllowlist(
command: command,
rawCommand: "echo \"ok $(/usr/bin/touch /tmp/openclaw-allowlist-test-quoted-subst)\"",
@@ -189,7 +308,7 @@ struct ExecAllowlistTests {
}
@Test func `resolve for allowlist fails closed on line-continued command substitution`() {
let command = ["/bin/sh", "-lc", "echo $\\\n(/usr/bin/touch /tmp/openclaw-allowlist-test-line-cont-subst)"]
let command = ["/bin/sh", "-c", "echo $\\\n(/usr/bin/touch /tmp/openclaw-allowlist-test-line-cont-subst)"]
let resolutions = ExecCommandResolution.resolveForAllowlist(
command: command,
rawCommand: "echo $\\\n(/usr/bin/touch /tmp/openclaw-allowlist-test-line-cont-subst)",
@@ -201,7 +320,7 @@ struct ExecAllowlistTests {
@Test func `resolve for allowlist fails closed on chained line-continued command substitution`() {
let command = [
"/bin/sh",
"-lc",
"-c",
"echo ok && $\\\n(/usr/bin/touch /tmp/openclaw-allowlist-test-chained-line-cont-subst)",
]
let resolutions = ExecCommandResolution.resolveForAllowlist(
@@ -213,7 +332,7 @@ struct ExecAllowlistTests {
}
@Test func `resolve for allowlist fails closed on quoted backticks`() {
let command = ["/bin/sh", "-lc", "echo \"ok `/usr/bin/id`\""]
let command = ["/bin/sh", "-c", "echo \"ok `/usr/bin/id`\""]
let resolutions = ExecCommandResolution.resolveForAllowlist(
command: command,
rawCommand: "echo \"ok `/usr/bin/id`\"",
@@ -226,7 +345,7 @@ struct ExecAllowlistTests {
let fixtures = try Self.loadShellParserParityCases()
for fixture in fixtures {
let resolutions = ExecCommandResolution.resolveForAllowlist(
command: ["/bin/sh", "-lc", fixture.command],
command: ["/bin/sh", "-c", fixture.command],
rawCommand: fixture.command,
cwd: nil,
env: ["PATH": "/usr/bin:/bin"])
@@ -276,7 +395,7 @@ struct ExecAllowlistTests {
let command = [
"/usr/bin/env",
"/bin/sh",
"-lc",
"-c",
"echo allowlisted && /usr/bin/touch /tmp/openclaw-allowlist-test",
]
let resolutions = ExecCommandResolution.resolveForAllowlist(
@@ -290,7 +409,7 @@ struct ExecAllowlistTests {
}
@Test func `resolve for allowlist unwraps env dispatch wrappers inside shell segments`() {
let command = ["/bin/sh", "-lc", "env /usr/bin/touch /tmp/openclaw-allowlist-test"]
let command = ["/bin/sh", "-c", "env /usr/bin/touch /tmp/openclaw-allowlist-test"]
let resolutions = ExecCommandResolution.resolveForAllowlist(
command: command,
rawCommand: "env /usr/bin/touch /tmp/openclaw-allowlist-test",
@@ -302,7 +421,7 @@ struct ExecAllowlistTests {
}
@Test func `resolve for allowlist preserves env assignments inside shell segments`() {
let command = ["/bin/sh", "-lc", "env FOO=bar /usr/bin/touch /tmp/openclaw-allowlist-test"]
let command = ["/bin/sh", "-c", "env FOO=bar /usr/bin/touch /tmp/openclaw-allowlist-test"]
let resolutions = ExecCommandResolution.resolveForAllowlist(
command: command,
rawCommand: "env FOO=bar /usr/bin/touch /tmp/openclaw-allowlist-test",
@@ -326,8 +445,8 @@ struct ExecAllowlistTests {
}
@Test func `approval evaluator resolves shell payload from canonical wrapper text`() async {
let command = ["/bin/sh", "-lc", "/usr/bin/printf ok"]
let rawCommand = "/bin/sh -lc \"/usr/bin/printf ok\""
let command = ["/bin/sh", "-c", "/usr/bin/printf ok"]
let rawCommand = "/bin/sh -c \"/usr/bin/printf ok\""
let evaluation = await ExecApprovalEvaluator.evaluate(
command: command,
rawCommand: rawCommand,
@@ -350,6 +469,32 @@ struct ExecAllowlistTests {
#expect(patterns == ["/usr/bin/printf"])
}
@Test func `allow always patterns fail closed for env modified shell wrappers`() {
let patterns = ExecCommandResolution.resolveAllowAlwaysPatterns(
command: [
"/usr/bin/env",
"BASH_ENV=/tmp/payload.sh",
"/bin/sh",
"-lc",
"/usr/bin/printf ok",
],
cwd: nil,
env: ["PATH": "/usr/bin:/bin"],
rawCommand: "/usr/bin/printf ok")
#expect(patterns.isEmpty)
}
@Test func `allow always patterns preserve generated sh lc raw payload binding`() {
let patterns = ExecCommandResolution.resolveAllowAlwaysPatterns(
command: ["/bin/sh", "-lc", "/usr/bin/printf safe_marker"],
cwd: nil,
env: ["PATH": "/usr/bin:/bin"],
rawCommand: "/usr/bin/printf safe_marker")
#expect(patterns == ["/usr/bin/printf"])
}
@Test func `match all requires every segment to match`() {
let first = ExecCommandResolution(
rawExecutable: "echo",

View File

@@ -85,6 +85,48 @@ struct ExecSystemRunCommandValidatorTests {
}
}
@Test func `fish attached c command requires canonical raw command binding`() {
let command = ["/usr/bin/fish", "-c/tmp/payload.fish", "/usr/bin/printf safe_marker"]
let result = ExecSystemRunCommandValidator.resolve(
command: command,
rawCommand: "/usr/bin/printf safe_marker")
switch result {
case .ok:
Issue.record("expected rawCommand mismatch for attached fish command payload")
case let .invalid(message):
#expect(message.contains("rawCommand does not match command"))
}
}
@Test func `startup shell wrappers require canonical raw command binding`() {
for command in [
["/bin/bash", "-lc", "/usr/bin/printf safe_marker"],
["/bin/bash", "--rcfile", "/tmp/payload.sh", "-i", "-c", "/usr/bin/printf safe_marker"],
["/bin/bash", "--login", "-c", "/usr/bin/printf safe_marker"],
["/usr/bin/fish", "--init-command=/tmp/payload.fish", "-c", "/usr/bin/printf safe_marker"],
] {
let legacy = ExecSystemRunCommandValidator.resolve(
command: command,
rawCommand: "/usr/bin/printf safe_marker")
switch legacy {
case .ok:
Issue.record("expected rawCommand mismatch for startup shell wrapper")
case let .invalid(message):
#expect(message.contains("rawCommand does not match command"))
}
let canonicalRaw = ExecCommandFormatter.displayString(for: command)
let canonical = ExecSystemRunCommandValidator.resolve(command: command, rawCommand: canonicalRaw)
switch canonical {
case let .ok(resolved):
#expect(resolved.displayCommand == canonicalRaw)
case let .invalid(message):
Issue.record("unexpected invalid result for canonical raw command: \(message)")
}
}
}
private static func loadContractCases() throws -> [SystemRunCommandContractCase] {
let fixtureURL = try self.findContractFixtureURL()
let data = try Data(contentsOf: fixtureURL)

View File

@@ -336,4 +336,118 @@ struct OpenClawConfigFileTests {
}
}
}
@MainActor
@Test
func `save dict records preserved gateway auth in audit`() async throws {
let stateDir = FileManager().temporaryDirectory
.appendingPathComponent("openclaw-state-\(UUID().uuidString)", isDirectory: true)
let configPath = stateDir.appendingPathComponent("openclaw.json")
let auditPath = stateDir.appendingPathComponent("logs/config-audit.jsonl")
defer { try? FileManager().removeItem(at: stateDir) }
try await TestIsolation.withEnvValues([
"OPENCLAW_STATE_DIR": stateDir.path,
"OPENCLAW_CONFIG_PATH": configPath.path,
]) {
OpenClawConfigFile.saveDict([
"gateway": [
"mode": "local",
"auth": [
"mode": "token",
"token": "test-token", // pragma: allowlist secret
],
],
])
let saved = OpenClawConfigFile.saveDict([
"gateway": [
"mode": "local",
],
"browser": [
"enabled": false,
],
])
#expect(saved)
let data = try Data(contentsOf: configPath)
let root = try JSONSerialization.jsonObject(with: data) as? [String: Any]
let gateway = root?["gateway"] as? [String: Any]
let auth = gateway?["auth"] as? [String: Any]
#expect(gateway?["mode"] as? String == "local")
#expect(auth?["mode"] as? String == "token")
#expect(auth?["token"] as? String == "test-token") // pragma: allowlist secret
#expect((root?["meta"] as? [String: Any]) != nil)
let rawAudit = try String(contentsOf: auditPath, encoding: .utf8)
let last = rawAudit.split(whereSeparator: \.isNewline).map(String.init).last
let auditRoot = try JSONSerialization.jsonObject(with: Data((last ?? "{}").utf8)) as? [String: Any]
#expect(auditRoot?["result"] as? String == "success")
#expect(auditRoot?["preservedGatewayAuth"] as? Bool == true)
let suspicious = auditRoot?["suspicious"] as? [String] ?? []
#expect(suspicious.contains("gateway-auth-preserved"))
}
}
@MainActor
@Test
func `save dict rejects gateway mode removal and keeps previous config`() async throws {
let stateDir = FileManager().temporaryDirectory
.appendingPathComponent("openclaw-state-\(UUID().uuidString)", isDirectory: true)
let configPath = stateDir.appendingPathComponent("openclaw.json")
let auditPath = stateDir.appendingPathComponent("logs/config-audit.jsonl")
defer { try? FileManager().removeItem(at: stateDir) }
try await TestIsolation.withEnvValues([
"OPENCLAW_STATE_DIR": stateDir.path,
"OPENCLAW_CONFIG_PATH": configPath.path,
]) {
OpenClawConfigFile.saveDict([
"gateway": [
"mode": "local",
"auth": [
"mode": "token",
"token": "test-token", // pragma: allowlist secret
],
],
"browser": [
"enabled": true,
],
])
let before = try String(contentsOf: configPath, encoding: .utf8)
let saved = OpenClawConfigFile.saveDict([
"browser": [
"enabled": false,
],
])
#expect(!saved)
let after = try String(contentsOf: configPath, encoding: .utf8)
#expect(after == before)
let rawAudit = try String(contentsOf: auditPath, encoding: .utf8)
let lines = rawAudit.split(whereSeparator: \.isNewline).map(String.init)
guard let last = lines.last else {
Issue.record("Missing rejected config audit line")
return
}
let auditRoot = try JSONSerialization.jsonObject(with: Data(last.utf8)) as? [String: Any]
#expect(auditRoot?["result"] as? String == "rejected")
let suspicious = auditRoot?["suspicious"] as? [String] ?? []
let blocking = auditRoot?["blocking"] as? [String] ?? []
#expect(suspicious.contains("gateway-mode-removed"))
#expect(blocking.contains("gateway-mode-removed"))
if let rejectedPath = auditRoot?["rejectedPath"] as? String {
#expect(FileManager().fileExists(atPath: rejectedPath))
let attributes = try FileManager().attributesOfItem(atPath: rejectedPath)
let mode = attributes[.posixPermissions] as? NSNumber
#expect(mode?.intValue == 0o600)
} else {
Issue.record("Missing rejected payload path")
}
}
}
}

View File

@@ -165,14 +165,14 @@ public struct ResponseFrame: Codable, Sendable {
public let id: String
public let ok: Bool
public let payload: AnyCodable?
public let error: [String: AnyCodable]?
public let error: ErrorShape?
public init(
type: String,
id: String,
ok: Bool,
payload: AnyCodable?,
error: [String: AnyCodable]?)
error: ErrorShape?)
{
self.type = type
self.id = id
@@ -195,14 +195,14 @@ public struct EventFrame: Codable, Sendable {
public let event: String
public let payload: AnyCodable?
public let seq: Int?
public let stateversion: [String: AnyCodable]?
public let stateversion: StateVersion?
public init(
type: String,
event: String,
payload: AnyCodable?,
seq: Int?,
stateversion: [String: AnyCodable]?)
stateversion: StateVersion?)
{
self.type = type
self.event = event
@@ -2243,6 +2243,9 @@ public struct SessionsUsageParams: Codable, Sendable {
public let startdate: String?
public let enddate: String?
public let mode: AnyCodable?
public let range: AnyCodable?
public let groupby: AnyCodable?
public let includehistorical: Bool?
public let utcoffset: String?
public let limit: Int?
public let includecontextweight: Bool?
@@ -2252,6 +2255,9 @@ public struct SessionsUsageParams: Codable, Sendable {
startdate: String?,
enddate: String?,
mode: AnyCodable?,
range: AnyCodable?,
groupby: AnyCodable?,
includehistorical: Bool?,
utcoffset: String?,
limit: Int?,
includecontextweight: Bool?)
@@ -2260,6 +2266,9 @@ public struct SessionsUsageParams: Codable, Sendable {
self.startdate = startdate
self.enddate = enddate
self.mode = mode
self.range = range
self.groupby = groupby
self.includehistorical = includehistorical
self.utcoffset = utcoffset
self.limit = limit
self.includecontextweight = includecontextweight
@@ -2270,12 +2279,229 @@ public struct SessionsUsageParams: Codable, Sendable {
case startdate = "startDate"
case enddate = "endDate"
case mode
case range
case groupby = "groupBy"
case includehistorical = "includeHistorical"
case utcoffset = "utcOffset"
case limit
case includecontextweight = "includeContextWeight"
}
}
public struct TaskSummary: Codable, Sendable {
public let id: String
public let kind: String?
public let runtime: String?
public let status: AnyCodable
public let title: String?
public let agentid: String?
public let sessionkey: String?
public let childsessionkey: String?
public let ownerkey: String?
public let runid: String?
public let taskid: String?
public let flowid: String?
public let parenttaskid: String?
public let sourceid: String?
public let createdat: AnyCodable?
public let updatedat: AnyCodable?
public let startedat: AnyCodable?
public let endedat: AnyCodable?
public let progresssummary: String?
public let terminalsummary: String?
public let error: String?
public init(
id: String,
kind: String?,
runtime: String?,
status: AnyCodable,
title: String?,
agentid: String?,
sessionkey: String?,
childsessionkey: String?,
ownerkey: String?,
runid: String?,
taskid: String?,
flowid: String?,
parenttaskid: String?,
sourceid: String?,
createdat: AnyCodable?,
updatedat: AnyCodable?,
startedat: AnyCodable?,
endedat: AnyCodable?,
progresssummary: String?,
terminalsummary: String?,
error: String?)
{
self.id = id
self.kind = kind
self.runtime = runtime
self.status = status
self.title = title
self.agentid = agentid
self.sessionkey = sessionkey
self.childsessionkey = childsessionkey
self.ownerkey = ownerkey
self.runid = runid
self.taskid = taskid
self.flowid = flowid
self.parenttaskid = parenttaskid
self.sourceid = sourceid
self.createdat = createdat
self.updatedat = updatedat
self.startedat = startedat
self.endedat = endedat
self.progresssummary = progresssummary
self.terminalsummary = terminalsummary
self.error = error
}
private enum CodingKeys: String, CodingKey {
case id
case kind
case runtime
case status
case title
case agentid = "agentId"
case sessionkey = "sessionKey"
case childsessionkey = "childSessionKey"
case ownerkey = "ownerKey"
case runid = "runId"
case taskid = "taskId"
case flowid = "flowId"
case parenttaskid = "parentTaskId"
case sourceid = "sourceId"
case createdat = "createdAt"
case updatedat = "updatedAt"
case startedat = "startedAt"
case endedat = "endedAt"
case progresssummary = "progressSummary"
case terminalsummary = "terminalSummary"
case error
}
}
public struct TasksListParams: Codable, Sendable {
public let status: AnyCodable?
public let agentid: String?
public let sessionkey: String?
public let limit: Int?
public let cursor: String?
public init(
status: AnyCodable?,
agentid: String?,
sessionkey: String?,
limit: Int?,
cursor: String?)
{
self.status = status
self.agentid = agentid
self.sessionkey = sessionkey
self.limit = limit
self.cursor = cursor
}
private enum CodingKeys: String, CodingKey {
case status
case agentid = "agentId"
case sessionkey = "sessionKey"
case limit
case cursor
}
}
public struct TasksListResult: Codable, Sendable {
public let tasks: [TaskSummary]
public let nextcursor: String?
public init(
tasks: [TaskSummary],
nextcursor: String?)
{
self.tasks = tasks
self.nextcursor = nextcursor
}
private enum CodingKeys: String, CodingKey {
case tasks
case nextcursor = "nextCursor"
}
}
public struct TasksGetParams: Codable, Sendable {
public let taskid: String
public init(
taskid: String)
{
self.taskid = taskid
}
private enum CodingKeys: String, CodingKey {
case taskid = "taskId"
}
}
public struct TasksGetResult: Codable, Sendable {
public let task: TaskSummary
public init(
task: TaskSummary)
{
self.task = task
}
private enum CodingKeys: String, CodingKey {
case task
}
}
public struct TasksCancelParams: Codable, Sendable {
public let taskid: String
public let reason: String?
public init(
taskid: String,
reason: String?)
{
self.taskid = taskid
self.reason = reason
}
private enum CodingKeys: String, CodingKey {
case taskid = "taskId"
case reason
}
}
public struct TasksCancelResult: Codable, Sendable {
public let found: Bool
public let cancelled: Bool
public let reason: String?
public let task: TaskSummary?
public init(
found: Bool,
cancelled: Bool,
reason: String?,
task: TaskSummary?)
{
self.found = found
self.cancelled = cancelled
self.reason = reason
self.task = task
}
private enum CodingKeys: String, CodingKey {
case found
case cancelled
case reason
case task
}
}
public struct ConfigGetParams: Codable, Sendable {}
public struct ConfigSetParams: Codable, Sendable {
@@ -2552,13 +2778,13 @@ public struct WizardStep: Codable, Sendable {
public struct WizardNextResult: Codable, Sendable {
public let done: Bool
public let step: [String: AnyCodable]?
public let step: WizardStep?
public let status: AnyCodable?
public let error: String?
public init(
done: Bool,
step: [String: AnyCodable]?,
step: WizardStep?,
status: AnyCodable?,
error: String?)
{
@@ -2579,14 +2805,14 @@ public struct WizardNextResult: Codable, Sendable {
public struct WizardStartResult: Codable, Sendable {
public let sessionid: String
public let done: Bool
public let step: [String: AnyCodable]?
public let step: WizardStep?
public let status: AnyCodable?
public let error: String?
public init(
sessionid: String,
done: Bool,
step: [String: AnyCodable]?,
step: WizardStep?,
status: AnyCodable?,
error: String?)
{
@@ -3180,21 +3406,25 @@ public struct TalkSessionSubmitToolResultParams: Codable, Sendable {
public let sessionid: String
public let callid: String
public let result: AnyCodable
public let options: [String: AnyCodable]?
public init(
sessionid: String,
callid: String,
result: AnyCodable)
result: AnyCodable,
options: [String: AnyCodable]?)
{
self.sessionid = sessionid
self.callid = callid
self.result = result
self.options = options
}
private enum CodingKeys: String, CodingKey {
case sessionid = "sessionId"
case callid = "callId"
case result
case options
}
}
@@ -4529,7 +4759,7 @@ public struct ToolsInvokeResult: Codable, Sendable {
public let requiresapproval: Bool?
public let approvalid: String?
public let source: AnyCodable?
public let error: [String: AnyCodable]?
public let error: ToolsInvokeError?
public init(
ok: Bool,
@@ -4538,7 +4768,7 @@ public struct ToolsInvokeResult: Codable, Sendable {
requiresapproval: Bool?,
approvalid: String?,
source: AnyCodable?,
error: [String: AnyCodable]?)
error: ToolsInvokeError?)
{
self.ok = ok
self.toolname = toolname
@@ -5132,6 +5362,7 @@ public struct ExecApprovalRequestParams: Codable, Sendable {
public let security: AnyCodable?
public let ask: AnyCodable?
public let warningtext: AnyCodable?
public let commandspans: [[String: AnyCodable]]?
public let agentid: AnyCodable?
public let resolvedpath: AnyCodable?
public let sessionkey: AnyCodable?
@@ -5154,6 +5385,7 @@ public struct ExecApprovalRequestParams: Codable, Sendable {
security: AnyCodable?,
ask: AnyCodable?,
warningtext: AnyCodable?,
commandspans: [[String: AnyCodable]]?,
agentid: AnyCodable?,
resolvedpath: AnyCodable?,
sessionkey: AnyCodable?,
@@ -5175,6 +5407,7 @@ public struct ExecApprovalRequestParams: Codable, Sendable {
self.security = security
self.ask = ask
self.warningtext = warningtext
self.commandspans = commandspans
self.agentid = agentid
self.resolvedpath = resolvedpath
self.sessionkey = sessionkey
@@ -5198,6 +5431,7 @@ public struct ExecApprovalRequestParams: Codable, Sendable {
case security
case ask
case warningtext = "warningText"
case commandspans = "commandSpans"
case agentid = "agentId"
case resolvedpath = "resolvedPath"
case sessionkey = "sessionKey"
@@ -5589,6 +5823,7 @@ public struct ChatSendParams: Codable, Sendable {
public let sessionid: String?
public let message: String
public let thinking: String?
public let fastmode: Bool?
public let deliver: Bool?
public let originatingchannel: String?
public let originatingto: String?
@@ -5605,6 +5840,7 @@ public struct ChatSendParams: Codable, Sendable {
sessionid: String?,
message: String,
thinking: String?,
fastmode: Bool?,
deliver: Bool?,
originatingchannel: String?,
originatingto: String?,
@@ -5620,6 +5856,7 @@ public struct ChatSendParams: Codable, Sendable {
self.sessionid = sessionid
self.message = message
self.thinking = thinking
self.fastmode = fastmode
self.deliver = deliver
self.originatingchannel = originatingchannel
self.originatingto = originatingto
@@ -5637,6 +5874,7 @@ public struct ChatSendParams: Codable, Sendable {
case sessionid = "sessionId"
case message
case thinking
case fastmode = "fastMode"
case deliver
case originatingchannel = "originatingChannel"
case originatingto = "originatingTo"

View File

@@ -1,4 +1,4 @@
7238265b921affbb481198f603293c9b1c988025713c55ee19fdbf132a8339ab config-baseline.json
97579293de31bc607194bce3e22c16d140c08ab9e6f1e38298f3ce47fbc9d68b config-baseline.core.json
463c45a79d02598184caccbc6f316692df962fe6b0e84d1a3e3cc1809f862b15 config-baseline.channel.json
b6d36d17e554a2ec5a1a6c6d32107a9a1113c274a700100962d97b6afbdafb25 config-baseline.plugin.json
a1523d01a78c449ee064761ccc065088584237879925d61a670d246aeb078b3f config-baseline.json
0f1af8c72fe0c0ba9219e35b4547b8884d0556fc6e72b24ab9dd8fbcc2ff76a8 config-baseline.core.json
60040c66e8cc488b85a10250936354ea1411015dab17af1b52b533c54a83a722 config-baseline.channel.json
1da42cb10427fb08510f29732493d24851ab915a424f91556569febdd450d9c3 config-baseline.plugin.json

View File

@@ -1,2 +1,2 @@
28e280d21693216c99cfa8da553589b41741d37c0ada956e316ee01d3d6c202c plugin-sdk-api-baseline.json
633dae33da97f6a073c5561709c57d5c0b7ff67af0512d0261f05455c24b38de plugin-sdk-api-baseline.jsonl
1aa92e012261d21474fde2aea8b1724bea369b5bc730e9fb943ff82de73f38de plugin-sdk-api-baseline.json
f076fb0cc1d09b5d50502741428e88a52725d73db950745801ae4fe782d709e2 plugin-sdk-api-baseline.jsonl

View File

@@ -3,6 +3,26 @@
"source": "OpenClaw",
"target": "OpenClaw"
},
{
"source": "iMessage",
"target": "iMessage"
},
{
"source": "Coming from BlueBubbles",
"target": "Coming from BlueBubbles"
},
{
"source": "BlueBubbles",
"target": "BlueBubbles"
},
{
"source": "Pairing",
"target": "配对"
},
{
"source": "Channel Routing",
"target": "频道路由"
},
{
"source": "ClawHub",
"target": "ClawHub"
@@ -591,6 +611,18 @@
"source": "Plugin path ownership",
"target": "插件路径所有权"
},
{
"source": "Path",
"target": "路径"
},
{
"source": "OC Path plugin",
"target": "OC Path 插件"
},
{
"source": "CLI reference",
"target": "CLI 参考"
},
{
"source": "Docker permissions",
"target": "Docker 权限"
@@ -735,6 +767,10 @@
"source": "Matrix QA",
"target": "Matrix QA"
},
{
"source": "Matrix presentation metadata",
"target": "Matrix 呈现元数据"
},
{
"source": "QA overview",
"target": "QA overview"

View File

@@ -203,7 +203,6 @@
"zh-CN/tools/slash-commands",
"zh-CN/tools/skills",
"zh-CN/tools/skills-config",
"zh-CN/tools/clawhub",
"zh-CN/tools/plugin"
]
},

View File

@@ -16,6 +16,14 @@ This directory owns docs authoring, Mintlify link rules, and docs i18n policy.
- For docs, UI copy, and picker lists, order services/providers alphabetically unless the section is explicitly describing runtime order or auto-detection order.
- Keep bundled plugin naming consistent with the repo-wide plugin terminology rules in the root `AGENTS.md`.
## Internal Docs
- Long-lived private operator docs belong in `~/Projects/manager/docs/`.
- Repo-local internal scratch/mirror docs may live under ignored `docs/internal/`.
- Never add `docs/internal/**` pages to `docs/docs.json` navigation or link them from public docs.
- `scripts/docs-sync-publish.mjs` excludes and prunes `docs/internal/**` from the public `openclaw/docs` publish repo if a page is force-added later.
- Internal docs may mention repo paths, private app names, 1Password item names, and runbooks, but never include secret values.
## Docs i18n
- Foreign-language docs are not maintained in this repo. The generated publish output lives in the separate `openclaw/docs` repo (often cloned locally as `../openclaw-docs`).

View File

@@ -90,7 +90,7 @@ Recommended data provenance fields for every collected item:
Have the workflow reject or mark stale items before summarization. The LLM step should receive only structured JSON and should be asked to preserve `sourceUrl`, `retrievedAt`, and `asOf` in its output. Use [LLM Task](/tools/llm-task) when you need a schema-validated model step inside the workflow.
For reusable team or community workflows, package the CLI, `.lobster` files, and any setup notes as a skill or plugin and publish it through [ClawHub](/tools/clawhub). Keep workflow-specific guardrails in that package unless the plugin API is missing a needed generic capability.
For reusable team or community workflows, package the CLI, `.lobster` files, and any setup notes as a skill or plugin and publish it through [ClawHub](/clawhub). Keep workflow-specific guardrails in that package unless the plugin API is missing a needed generic capability.
## Sync modes

View File

@@ -662,7 +662,7 @@ Default slash command settings:
</Accordion>
<Accordion title="Live stream preview">
OpenClaw can stream draft replies by sending a temporary message and editing it as text arrives. `channels.discord.streaming` takes `off` | `partial` | `block` | `progress` (default). `progress` keeps one editable status draft and updates it with tool progress until final delivery; `streamMode` is a legacy runtime alias. Run `openclaw doctor --fix` to rewrite persisted config to the canonical key.
OpenClaw can stream draft replies by sending a temporary message and editing it as text arrives. `channels.discord.streaming` takes `off` | `partial` | `block` | `progress` (default). `progress` keeps one editable status draft and updates it with tool progress until final delivery; the shared starter label is a rolling line, so it scrolls away like the rest once enough work appears. `streamMode` is a legacy runtime alias. Run `openclaw doctor --fix` to rewrite persisted config to the canonical key.
Set `channels.discord.streaming.mode` to `off` to disable Discord preview edits. If Discord block streaming is explicitly enabled, OpenClaw skips the preview stream to avoid double-streaming.
@@ -687,6 +687,7 @@ Default slash command settings:
- `block` emits draft-sized chunks (use `draftChunk` to tune size and breakpoints, clamped to `textChunkLimit`).
- Media, error, and explicit-reply finals cancel pending preview edits.
- `streaming.preview.toolProgress` (default `true`) controls whether tool/progress updates reuse the preview message.
- Tool/progress rows render as compact emoji + title + detail when available, for example `🛠️ Bash: run tests` or `🔎 Web Search: for "query"`.
- `streaming.preview.commandText` / `streaming.progress.commandText` controls command/exec detail in compact progress lines: `raw` (default) or `status` (tool label only).
Hide raw command/exec text while keeping compact progress lines:
@@ -1171,7 +1172,7 @@ Auto-join example:
discord: {
voice: {
enabled: true,
model: "openai/gpt-5.4-mini",
model: "openai-codex/gpt-5.5",
autoJoin: [
{
guildId: "123456789012345678",
@@ -1182,9 +1183,10 @@ Auto-join example:
decryptionFailureTolerance: 24,
connectTimeoutMs: 30000,
reconnectGraceMs: 15000,
tts: {
realtime: {
provider: "openai",
openai: { voice: "onyx" },
model: "gpt-realtime-2",
voice: "cedar",
},
},
},
@@ -1194,18 +1196,27 @@ Auto-join example:
Notes:
- `voice.tts` overrides `messages.tts` for voice playback only.
- `voice.model` overrides the LLM used for Discord voice channel responses only. Leave it unset to inherit the routed agent model.
- STT uses `tools.media.audio`; `voice.model` does not affect transcription.
- `voice.tts` overrides `messages.tts` for `stt-tts` voice playback only. Realtime modes use `voice.realtime.voice`.
- `voice.mode` controls the conversation path. The default is `agent-proxy`: a realtime voice front end handles turn timing, interruption, and playback, delegates substantive work to the routed OpenClaw agent through `openclaw_agent_consult`, and treats the result like a typed Discord prompt from that speaker. `stt-tts` keeps the older batch STT plus TTS flow. `bidi` lets the realtime model converse directly while exposing `openclaw_agent_consult` for the OpenClaw brain.
- `voice.agentSession` controls which OpenClaw conversation receives voice turns. Leave it unset for the voice channel's own session, or set `{ mode: "target", target: "channel:<text-channel-id>" }` to make the voice channel act as the microphone/speaker extension of an existing Discord text channel session such as `#maintainers`.
- `voice.model` overrides the OpenClaw agent brain for Discord voice responses and realtime consults. Leave it unset to inherit the routed agent model. It is separate from `voice.realtime.model`.
- `agent-proxy` routes speech through `discord-voice`, which preserves normal owner/tool authorization for the speaker and target session but hides the agent `tts` tool because Discord voice owns playback. By default, `agent-proxy` gives the consult full owner-equivalent tool access for owner speakers (`voice.realtime.toolPolicy: "owner"`) and strongly prefers consulting the OpenClaw agent before substantive answers (`voice.realtime.consultPolicy: "always"`).
- In `stt-tts` mode, STT uses `tools.media.audio`; `voice.model` does not affect transcription.
- In realtime modes, `voice.realtime.provider`, `voice.realtime.model`, and `voice.realtime.voice` configure the realtime audio session. For OpenAI Realtime 2 plus the Codex brain, use `voice.realtime.model: "gpt-realtime-2"` and `voice.model: "openai-codex/gpt-5.5"`.
- `voice.realtime.bargeIn` controls whether Discord speaker-start events interrupt active realtime playback. If unset, it follows the realtime provider's input-audio interruption setting.
- `voice.realtime.minBargeInAudioEndMs` controls the minimum assistant playback duration before an OpenAI realtime barge-in truncates audio. Default: `250`. Set `0` for immediate interruption in low-echo rooms, or raise it for echo-heavy speaker setups.
- For an OpenAI voice on Discord playback, set `voice.tts.provider: "openai"` and choose a Text-to-speech voice under `voice.tts.openai.voice` or `voice.tts.providers.openai.voice`. `cedar` is a good masculine-sounding choice on the current OpenAI TTS model.
- Per-channel Discord `systemPrompt` overrides apply to voice transcript turns for that voice channel.
- Voice transcript turns derive owner status from Discord `allowFrom` (or `dm.allowFrom`); non-owner speakers cannot access owner-only tools (for example `gateway` and `cron`).
- Discord voice is opt-in for text-only configs; set `channels.discord.voice.enabled=true` (or keep an existing `channels.discord.voice` block) to enable `/vc` commands, the voice runtime, and the `GuildVoiceStates` gateway intent.
- `channels.discord.intents.voiceStates` can explicitly override voice-state intent subscription. Leave it unset for the intent to follow effective voice enablement.
- If `voice.autoJoin` has multiple entries for the same guild, OpenClaw joins the last configured channel for that guild.
- `voice.daveEncryption` and `voice.decryptionFailureTolerance` pass through to `@discordjs/voice` join options.
- `@discordjs/voice` defaults are `daveEncryption=true` and `decryptionFailureTolerance=24` if unset.
- `voice.connectTimeoutMs` controls the initial `@discordjs/voice` Ready wait for `/vc join` and auto-join attempts. Default: `30000`.
- `voice.reconnectGraceMs` controls how long OpenClaw waits for a disconnected voice session to begin reconnecting before destroying it. Default: `15000`.
- Voice playback does not stop just because another user starts speaking. To avoid feedback loops, OpenClaw ignores new voice capture while TTS is playing; speak after playback finishes for the next turn.
- In `stt-tts` mode, voice playback does not stop just because another user starts speaking. To avoid feedback loops, OpenClaw ignores new voice capture while TTS is playing; speak after playback finishes for the next turn. Realtime modes forward speaker starts as barge-in signals to the realtime provider.
- In realtime modes, echo from speakers into an open mic can look like barge-in and interrupt playback. For echo-heavy Discord rooms, set `voice.realtime.providers.openai.interruptResponseOnInputAudio: false` to keep OpenAI from auto-interrupting on input audio. Add `voice.realtime.bargeIn: true` if you still want Discord speaker-start events to interrupt active playback. The OpenAI realtime bridge ignores playback truncations shorter than `voice.realtime.minBargeInAudioEndMs` as likely echo/noise and logs them as skipped instead of clearing Discord playback.
- `voice.captureSilenceGraceMs` controls how long OpenClaw waits after Discord reports a speaker has stopped before finalizing that audio segment for STT. Default: `2500`; raise this if Discord splits normal pauses into choppy partial transcripts.
- When ElevenLabs is the selected TTS provider, Discord voice playback uses streaming TTS and starts from the provider response stream. Providers without streaming support fall back to the synthesized temp-file path.
- OpenClaw also watches receive decrypt failures and auto-recovers by leaving/rejoining the voice channel after repeated failures in a short window.
@@ -1213,7 +1224,7 @@ Notes:
- `The operation was aborted` receive events are expected when OpenClaw finalizes a captured speaker segment; they are verbose diagnostics, not warnings.
- Verbose Discord voice logs include a bounded one-line STT transcript preview for each accepted speaker segment, so debugging shows both the user side and the agent reply side without dumping unbounded transcript text.
Voice channel pipeline:
STT plus TTS pipeline:
- Discord PCM capture is converted to a WAV temp file.
- `tools.media.audio` handles STT, for example `openai/gpt-4o-mini-transcribe`.
@@ -1221,7 +1232,150 @@ Voice channel pipeline:
- `voice.model`, when set, overrides only the response LLM for this voice-channel turn.
- `voice.tts` is merged over `messages.tts`; streaming-capable providers feed the player directly, otherwise the resulting audio file is played in the joined channel.
Credentials are resolved per component: LLM route auth for `voice.model`, STT auth for `tools.media.audio`, and TTS auth for `messages.tts`/`voice.tts`.
Default agent-proxy voice-channel session example:
```json5
{
channels: {
discord: {
voice: {
enabled: true,
model: "openai-codex/gpt-5.5",
realtime: {
provider: "openai",
model: "gpt-realtime-2",
voice: "cedar",
},
},
},
},
}
```
With no `voice.agentSession` block, each voice channel gets its own routed OpenClaw session. For example, `/vc join channel:234567890123456789` talks to the session for that Discord voice channel. The realtime model is only the voice front end; substantive requests are handed to the configured OpenClaw agent. If the realtime model produces a final transcript without calling the consult tool, OpenClaw forces the consult as a fallback so the default still behaves like talking to the agent.
Legacy STT plus TTS example:
```json5
{
channels: {
discord: {
voice: {
enabled: true,
mode: "stt-tts",
model: "openai/gpt-5.4-mini",
tts: {
provider: "openai",
openai: {
model: "gpt-4o-mini-tts",
voice: "cedar",
},
},
},
},
},
}
```
Realtime bidi example:
```json5
{
channels: {
discord: {
voice: {
enabled: true,
mode: "bidi",
model: "openai-codex/gpt-5.5",
realtime: {
provider: "openai",
model: "gpt-realtime-2",
voice: "cedar",
toolPolicy: "safe-read-only",
consultPolicy: "always",
},
},
},
},
}
```
Voice as an extension of an existing Discord channel session:
```json5
{
channels: {
discord: {
voice: {
enabled: true,
mode: "agent-proxy",
model: "openai-codex/gpt-5.5",
agentSession: {
mode: "target",
target: "channel:123456789012345678",
},
realtime: {
provider: "openai",
model: "gpt-realtime-2",
voice: "cedar",
},
},
},
},
}
```
In `agent-proxy` mode the bot joins the configured voice channel, but OpenClaw agent turns use the target channel's normal routed session and agent. The realtime voice session speaks the returned result back into the voice channel. The supervisor agent can still use normal message tools according to its tool policy, including sending a separate Discord message if that is the right action.
Useful target forms:
- `target: "channel:123456789012345678"` routes through a Discord text channel session.
- `target: "123456789012345678"` is treated as a channel target.
- `target: "dm:123456789012345678"` or `target: "user:123456789012345678"` routes through that direct-message session.
Echo-heavy OpenAI Realtime example:
```json5
{
channels: {
discord: {
voice: {
enabled: true,
mode: "bidi",
model: "openai-codex/gpt-5.5",
realtime: {
provider: "openai",
model: "gpt-realtime-2",
voice: "cedar",
bargeIn: true,
minBargeInAudioEndMs: 500,
consultPolicy: "always",
providers: {
openai: {
interruptResponseOnInputAudio: false,
},
},
},
},
},
},
}
```
Use this when the model hears its own Discord playback through an open mic, but you still want to interrupt it by speaking. OpenClaw keeps OpenAI from auto-interrupting on raw input audio, while `bargeIn: true` lets Discord speaker-start events and already-active speaker audio cancel active realtime responses before the next captured turn reaches OpenAI. Very early barge-in signals with `audioEndMs` below `minBargeInAudioEndMs` are treated as likely echo/noise and ignored so the model does not cut off at the first playback frame.
Expected voice logs:
- On join: `discord voice: joining ... voiceSession=... supervisorSession=... agentSessionMode=... voiceModel=... realtimeModel=...`
- On realtime start: `discord voice: realtime bridge starting ... interruptResponse=false bargeIn=true minBargeInAudioEndMs=...`
- On realtime consult: `discord voice: realtime consult requested ... voiceSession=... supervisorSession=... question=...`
- On agent answer: `discord voice: agent turn answer ...`
- On same-speaker interruption: `discord voice: realtime barge-in from active speaker audio ...`
- On realtime interruption: `discord voice: realtime model interrupt requested client:response.cancel reason=barge-in`, followed by either `discord voice: realtime model audio truncated client:conversation.item.truncate reason=barge-in audioEndMs=...` or `discord voice: realtime model interrupt confirmed server:response.done status=cancelled ...`
- On ignored echo/noise: `discord voice: realtime model interrupt ignored client:conversation.item.truncate.skipped reason=barge-in audioEndMs=0 minAudioEndMs=250`
- On disabled barge-in: `discord voice: realtime capture ignored during playback (barge-in disabled) ...`
Credentials are resolved per component: LLM route auth for `voice.model`, STT auth for `tools.media.audio`, TTS auth for `messages.tts`/`voice.tts`, and realtime provider auth for `voice.realtime.providers` or the provider's normal auth config.
### Voice messages

View File

@@ -0,0 +1,242 @@
---
summary: "Migrate old BlueBubbles configs to the bundled iMessage plugin without losing pairing, allowlists, or group bindings."
read_when:
- Planning a move from BlueBubbles to the bundled iMessage plugin
- Translating BlueBubbles config keys to iMessage equivalents
- Verifying imsg before enabling the iMessage plugin
title: "Coming from BlueBubbles"
---
The bundled `imessage` plugin now reaches the same private API surface as BlueBubbles (`react`, `edit`, `unsend`, `reply`, `sendWithEffect`, group management, attachments) by driving [`steipete/imsg`](https://github.com/steipete/imsg) over JSON-RPC. If you already run a Mac with `imsg` installed, you can drop the BlueBubbles server and let the plugin talk to Messages.app directly.
BlueBubbles support was removed. OpenClaw supports iMessage through `imsg` only. This guide is for migrating old `channels.bluebubbles` configs to `channels.imessage`; there is no other supported migration path.
## When this migration makes sense
- You already run `imsg` on the same Mac (or one reachable over SSH) where Messages.app is signed in.
- You want one fewer moving part — no separate BlueBubbles server, no REST endpoint to authenticate, no webhook plumbing. Single CLI binary instead of a server + client app + helper.
- You are on a [supported macOS / `imsg` build](/channels/imessage#requirements-and-permissions-macos) where the private API probe reports `available: true`.
## What imsg does
`imsg` is a local macOS CLI for Messages. OpenClaw starts `imsg rpc` as a child process and talks JSON-RPC over stdin/stdout. There is no HTTP server, webhook URL, background daemon, launch agent, or port to expose.
- Reads come from `~/Library/Messages/chat.db` using a read-only SQLite handle.
- Live inbound messages come from `imsg watch` / `watch.subscribe`, which follows `chat.db` filesystem events with a polling fallback.
- Sends use Messages.app automation for normal text and file sends.
- Advanced actions use `imsg launch` to inject the `imsg` helper into Messages.app. That is what unlocks read receipts, typing indicators, rich sends, edit, unsend, threaded reply, tapbacks, and group management.
- Linux builds can inspect a copied `chat.db`, but cannot send, watch the live Mac database, or drive Messages.app. For OpenClaw iMessage, run `imsg` on the signed-in Mac or through an SSH wrapper to that Mac.
## Before you start
1. Install `imsg` on the Mac that runs Messages.app:
```bash
brew install steipete/tap/imsg
imsg --version
imsg chats --limit 3
```
If `imsg chats` fails with `unable to open database file`, empty output, or `authorization denied`, grant Full Disk Access to the terminal, editor, Node process, Gateway service, or SSH parent process that launches `imsg`, then reopen that parent process.
2. Verify the read, watch, send, and RPC surfaces before changing OpenClaw config:
```bash
imsg chats --limit 10 --json | jq -s
imsg history --chat-id 42 --limit 10 --attachments --json | jq -s
imsg watch --chat-id 42 --reactions --json
imsg send --chat-id 42 --text "OpenClaw imsg test"
imsg rpc --help
```
Replace `42` with a real chat id from `imsg chats`. Sending requires Automation permission for Messages.app. If OpenClaw will run through SSH, run these commands through the same SSH wrapper or user context that OpenClaw will use.
3. Enable the private API bridge when you need advanced actions:
```bash
imsg launch
imsg status --json
```
`imsg launch` requires SIP to be disabled. Basic send, history, and watch work without `imsg launch`; advanced actions do not.
4. Verify the bridge through OpenClaw:
```bash
openclaw channels status --probe
```
You want `imessage.privateApi.available: true`. If it reports `false`, fix that first — see [Capability detection](/channels/imessage#private-api-actions).
5. Snapshot your config:
```bash
cp ~/.openclaw/openclaw.json5 ~/.openclaw/openclaw.json5.bak
```
## Config translation
iMessage and BlueBubbles share a lot of channel-level config. The keys that change are mostly transport (REST server vs local CLI). Behavior keys (`dmPolicy`, `groupPolicy`, `allowFrom`, etc.) keep the same meaning.
| BlueBubbles | bundled iMessage | Notes |
| ---------------------------------------------------------- | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `channels.bluebubbles.enabled` | `channels.imessage.enabled` | Same semantics. |
| `channels.bluebubbles.serverUrl` | _(removed)_ | No REST server — the plugin spawns `imsg rpc` over stdio. |
| `channels.bluebubbles.password` | _(removed)_ | No webhook authentication needed. |
| _(implicit)_ | `channels.imessage.cliPath` | Path to `imsg` (default `imsg`); use a wrapper script for SSH. |
| _(implicit)_ | `channels.imessage.dbPath` | Optional Messages.app `chat.db` override; auto-detected when omitted. |
| _(implicit)_ | `channels.imessage.remoteHost` | `host` or `user@host` — only needed when `cliPath` is an SSH wrapper and you want SCP attachment fetches. |
| `channels.bluebubbles.dmPolicy` | `channels.imessage.dmPolicy` | Same values (`pairing` / `allowlist` / `open` / `disabled`). |
| `channels.bluebubbles.allowFrom` | `channels.imessage.allowFrom` | Pairing approvals carry over by handle, not by token. |
| `channels.bluebubbles.groupPolicy` | `channels.imessage.groupPolicy` | Same values (`allowlist` / `open` / `disabled`). |
| `channels.bluebubbles.groupAllowFrom` | `channels.imessage.groupAllowFrom` | Same. |
| `channels.bluebubbles.groups` | `channels.imessage.groups` | **Copy this verbatim, including any `groups: { "*": { ... } }` wildcard entry.** Per-group `requireMention`, `tools`, `toolsBySender` carry over. With `groupPolicy: "allowlist"`, an empty or missing `groups` block silently drops every group message — see "Group registry footgun" below. |
| `channels.bluebubbles.sendReadReceipts` | `channels.imessage.sendReadReceipts` | Default `true`. With the bundled plugin this only fires when the private API probe is up. |
| `channels.bluebubbles.includeAttachments` | `channels.imessage.includeAttachments` | Same shape, **same off-by-default**. If you had attachments flowing on BlueBubbles you must re-set this explicitly on the iMessage block — it does not carry over implicitly, and inbound photos/media will be silently dropped with no `Inbound message` log line until you do. |
| `channels.bluebubbles.attachmentRoots` | `channels.imessage.attachmentRoots` | Local roots; same wildcard rules. |
| _(N/A)_ | `channels.imessage.remoteAttachmentRoots` | Only used when `remoteHost` is set for SCP fetches. |
| `channels.bluebubbles.mediaMaxMb` | `channels.imessage.mediaMaxMb` | Default 16 MB on iMessage (BlueBubbles default was 8 MB). Set explicitly if you want to keep the lower cap. |
| `channels.bluebubbles.textChunkLimit` | `channels.imessage.textChunkLimit` | Default 4000 on both. |
| `channels.bluebubbles.coalesceSameSenderDms` | `channels.imessage.coalesceSameSenderDms` | Same opt-in. DM-only — group chats keep instant per-message dispatch on both channels. Widens the default inbound debounce to 2500 ms when enabled without an explicit `messages.inbound.byChannel.imessage`. See [iMessage docs § Coalescing split-send DMs](/channels/imessage#coalescing-split-send-dms-command--url-in-one-composition). |
| `channels.bluebubbles.enrichGroupParticipantsFromContacts` | _(N/A)_ | iMessage already reads sender display names from `chat.db`. |
| `channels.bluebubbles.actions.*` | `channels.imessage.actions.*` | Per-action toggles: `reactions`, `edit`, `unsend`, `reply`, `sendWithEffect`, `renameGroup`, `setGroupIcon`, `addParticipant`, `removeParticipant`, `leaveGroup`, `sendAttachment`. |
Multi-account configs (`channels.bluebubbles.accounts.*`) translate one-to-one to `channels.imessage.accounts.*`.
## Group registry footgun
The bundled iMessage plugin runs **two** separate group allowlist gates back-to-back. Both must pass for a group message to reach the agent:
1. **Sender / chat-target allowlist** (`channels.imessage.groupAllowFrom`) — checked by `isAllowedIMessageSender`. Matches inbound messages by sender handle, `chat_guid`, `chat_identifier`, or `chat_id`. Same shape as BlueBubbles.
2. **Group registry** (`channels.imessage.groups`) — checked by `resolveChannelGroupPolicy` from `inbound-processing.ts:199`. With `groupPolicy: "allowlist"`, this gate requires either:
- a `groups: { "*": { ... } }` wildcard entry (sets `allowAll = true`), or
- an explicit per-`chat_id` entry under `groups`.
If gate 1 passes but gate 2 fails, the message is dropped. The plugin emits two `warn`-level signals so this is no longer silent at default log level:
- A one-time startup `warn` per account when `groupPolicy: "allowlist"` is set but `channels.imessage.groups` is empty (no `"*"` wildcard, no per-`chat_id` entries) — fired before any messages land.
- A one-time per-`chat_id` `warn` the first time a specific group is dropped at runtime, naming the chat_id and the exact key to add to `groups` to allow it.
DMs continue to work because they take a different code path.
This is the most common BlueBubbles → bundled-iMessage migration failure mode: operators copy `groupAllowFrom` and `groupPolicy` but skip the `groups` block, because BlueBubbles' `groups: { "*": { "requireMention": true } }` looks like an unrelated mention setting. It's actually load-bearing for the registry gate.
The minimum config to keep group messages flowing after `groupPolicy: "allowlist"`:
```json5
{
channels: {
imessage: {
groupPolicy: "allowlist",
groupAllowFrom: ["+15555550123", "chat_guid:any;-;..."],
groups: {
"*": { requireMention: true },
},
},
},
}
```
`requireMention: true` under `*` is harmless when no mention patterns are configured: the runtime sets `canDetectMention = false` and short-circuits the mention drop at `inbound-processing.ts:512`. With mention patterns configured (`agents.list[].groupChat.mentionPatterns`), it works as expected.
If the gateway logs `imessage: dropping group message from chat_id=<id>` or the startup line `imessage: groupPolicy="allowlist" but channels.imessage.groups is empty`, gate 2 is dropping — add the `groups` block.
## Step-by-step
1. Add an iMessage block alongside the existing BlueBubbles block. Keep the old block only as a copy source until the new path is verified:
```json5
{
channels: {
bluebubbles: {
enabled: true,
// ... existing config ...
},
imessage: {
enabled: false, // turn on after the dry run below
cliPath: "/opt/homebrew/bin/imsg",
dmPolicy: "pairing",
allowFrom: ["+15555550123"], // copy from bluebubbles.allowFrom
groupPolicy: "allowlist",
groupAllowFrom: [], // copy from bluebubbles.groupAllowFrom
groups: { "*": { requireMention: true } }, // copy from bluebubbles.groups — silently drops groups if missing, see "Group registry footgun" above
actions: {
reactions: true,
edit: true,
unsend: true,
reply: true,
sendWithEffect: true,
sendAttachment: true,
},
},
},
}
```
2. **Dry-run probe** — start the gateway and confirm iMessage reports healthy:
```bash
openclaw gateway
openclaw channels status
openclaw channels status --probe # expect imessage.privateApi.available: true
```
Because `imessage.enabled` is still `false`, no inbound iMessage traffic is routed yet — but `--probe` exercises the bridge so you catch permission/install issues before the cutover.
3. **Cut over.** Remove the BlueBubbles config and enable iMessage in one config edit:
```json5
{
channels: {
imessage: { enabled: true /* ... */ },
},
}
```
Restart the gateway. Inbound iMessage traffic now flows through the bundled plugin.
4. **Verify DMs.** Send the agent a direct message; confirm the reply lands.
5. **Verify groups separately.** DMs and groups take different code paths — DM success does not prove groups are routing. Send the agent a message in a paired group chat and confirm the reply lands. If the group goes silent (no agent reply, no error), check the gateway log for `imessage: dropping group message from chat_id=<id>` or the startup `imessage: groupPolicy="allowlist" but channels.imessage.groups is empty` line — both fire at the default log level. If either appears, your `groups` block is missing or empty — see "Group registry footgun" above.
6. **Verify the action surface** — from a paired DM, ask the agent to react, edit, unsend, reply, send a photo, and (in a group) rename the group / add or remove a participant. Each action should land natively in Messages.app. If any throws "iMessage `<action>` requires the imsg private API bridge", run `imsg launch` again and refresh `channels status --probe`.
7. **Remove the BlueBubbles server and config** once iMessage DMs, groups, and actions are verified. OpenClaw will not use `channels.bluebubbles`.
## Action parity at a glance
| Action | legacy BlueBubbles | bundled iMessage |
| ---------------------------------------------------------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| Send text / SMS fallback | ✅ | ✅ |
| Send media (photo, video, file, voice) | ✅ | ✅ |
| Threaded reply (`reply_to_guid`) | ✅ | ✅ (closes [#51892](https://github.com/openclaw/openclaw/issues/51892)) |
| Tapback (`react`) | ✅ | ✅ |
| Edit / unsend (macOS 13+ recipients) | ✅ | ✅ |
| Send with screen effect | ✅ | ✅ (closes part of [#9394](https://github.com/openclaw/openclaw/issues/9394)) |
| Rich text bold / italic / underline / strikethrough | ✅ | ✅ (typed-run formatting via attributedBody) |
| Rename group / set group icon | ✅ | ✅ |
| Add / remove participant, leave group | ✅ | ✅ |
| Read receipts and typing indicator | ✅ | ✅ (gated on private API probe) |
| Same-sender DM coalescing | ✅ | ✅ (DM-only; opt-in via `channels.imessage.coalesceSameSenderDms`) |
| Catchup of inbound messages received while gateway is down | ✅ (webhook replay + history fetch) | ✅ (opt-in via `channels.imessage.catchup.enabled`; closes [#78649](https://github.com/openclaw/openclaw/issues/78649)) |
iMessage catchup is now available as an opt-in feature on the bundled plugin. On gateway startup, if `channels.imessage.catchup.enabled` is `true`, the gateway runs one `chats.list` + per-chat `messages.history` pass against the same JSON-RPC client used by `imsg watch`, replays each missed inbound row through the live dispatch path (allowlists, group policy, debouncer, echo cache), and persists a per-account cursor so subsequent startups pick up where they left off. See [Catching up after gateway downtime](/channels/imessage#catching-up-after-gateway-downtime) for tuning.
## Pairing, sessions, and ACP bindings
- **Pairing approvals** carry over by handle. You do not need to re-approve known senders — `channels.imessage.allowFrom` recognizes the same `+15555550123` / `user@example.com` strings BlueBubbles used.
- **Sessions** stay scoped per agent + chat. DMs collapse into the agent main session under default `session.dmScope=main`; group sessions stay isolated per `chat_id`. The session keys differ (`agent:<id>:imessage:group:<chat_id>` vs the BlueBubbles equivalent) — old conversation history under BlueBubbles session keys does not carry into iMessage sessions.
- **ACP bindings** referencing `match.channel: "bluebubbles"` need to be updated to `"imessage"`. The `match.peer.id` shapes (`chat_id:`, `chat_guid:`, `chat_identifier:`, bare handle) are identical.
## No rollback channel
There is no supported BlueBubbles runtime to switch back to. If iMessage verification fails, set `channels.imessage.enabled: false`, restart the Gateway, fix the `imsg` blocker, and retry the cutover.
The reply cache lives at `~/.openclaw/state/imessage/reply-cache.jsonl` (mode `0600`, parent dir `0700`). It is safe to delete if you want a clean slate.
## Related
- [iMessage](/channels/imessage) — full iMessage channel reference, including `imsg launch` setup and capability detection.
- `/channels/bluebubbles` — legacy URL that redirects to this migration guide.
- [Pairing](/channels/pairing) — DM authentication and pairing flow.
- [Channel Routing](/channels/channel-routing) — how the gateway picks a channel for outbound replies.

View File

@@ -1,5 +1,5 @@
---
summary: "Native iMessage support via imsg (JSON-RPC over stdio). Preferred for new OpenClaw iMessage setups when host requirements fit."
summary: "Native iMessage support via imsg (JSON-RPC over stdio), with private API actions for replies, tapbacks, effects, attachments, and group management. Preferred for new OpenClaw iMessage setups when host requirements fit."
read_when:
- Setting up iMessage support
- Debugging iMessage send/receive
@@ -8,15 +8,20 @@ title: "iMessage"
<Note>
For OpenClaw iMessage deployments, use `imsg` on a signed-in macOS Messages host. If your Gateway runs on Linux or Windows, point `channels.imessage.cliPath` at an SSH wrapper that runs `imsg` on the Mac.
**Gateway-downtime catchup is opt-in.** When enabled (`channels.imessage.catchup.enabled: true`), the gateway replays inbound messages that landed in `chat.db` while it was offline (crash, restart, Mac sleep) on next startup. Disabled by default — see [Catching up after gateway downtime](#catching-up-after-gateway-downtime). Closes [openclaw#78649](https://github.com/openclaw/openclaw/issues/78649).
</Note>
<Warning>
BlueBubbles is deprecated and no longer ships as a bundled OpenClaw channel. Migrate `channels.bluebubbles` configs to `channels.imessage`; OpenClaw now supports iMessage through `imsg` only. If you still need a BlueBubbles-backed bridge, publish or install it as a third-party plugin outside core.
BlueBubbles support was removed. Migrate `channels.bluebubbles` configs to `channels.imessage`; OpenClaw supports iMessage through `imsg` only.
</Warning>
Status: native external CLI integration. Gateway spawns `imsg rpc` and communicates over JSON-RPC on stdio (no separate daemon/port).
Status: native external CLI integration. Gateway spawns `imsg rpc` and communicates over JSON-RPC on stdio (no separate daemon/port). Advanced actions require `imsg launch` and a successful private API probe.
<CardGroup cols={3}>
<Card title="Private API actions" icon="wand-sparkles" href="#private-api-actions">
Replies, tapbacks, effects, attachments, and group management.
</Card>
<Card title="Pairing" icon="link" href="/channels/pairing">
iMessage DMs default to pairing mode.
</Card>
@@ -38,6 +43,8 @@ Status: native external CLI integration. Gateway spawns `imsg rpc` and communica
```bash
brew install steipete/tap/imsg
imsg rpc --help
imsg launch
openclaw channels status --probe
```
</Step>
@@ -119,6 +126,7 @@ exec ssh -T gateway-host imsg "$@"
- Messages must be signed in on the Mac running `imsg`.
- Full Disk Access is required for the process context running OpenClaw/`imsg` (Messages DB access).
- Automation permission is required to send messages through Messages.app.
- For advanced actions (react / edit / unsend / threaded reply / effects / group ops), System Integrity Protection must be disabled — see [Enabling the imsg private API](#enabling-the-imsg-private-api) below. Basic text and media send/receive work without it.
<Tip>
Permissions are granted per process context. If gateway runs headless (LaunchAgent/SSH), run a one-time interactive command in that same context to trigger prompts:
@@ -131,6 +139,71 @@ imsg send <handle> "test"
</Tip>
## Enabling the imsg private API
`imsg` ships in two operational modes:
- **Basic mode** (default, no SIP changes needed): outbound text and media via `send`, inbound watch/history, chat list. This is what you get out of the box from a fresh `brew install steipete/tap/imsg` plus the standard macOS permissions above.
- **Private API mode**: `imsg` injects a helper dylib into `Messages.app` to call internal `IMCore` functions. This is what unlocks `react`, `edit`, `unsend`, `reply` (threaded), `sendWithEffect`, `renameGroup`, `setGroupIcon`, `addParticipant`, `removeParticipant`, `leaveGroup`, plus typing indicators and read receipts.
To reach the advanced action surface that this channel page documents, you need Private API mode. The `imsg` README is explicit about the requirement:
> Advanced features such as `read`, `typing`, `launch`, bridge-backed rich send, message mutation, and chat management are opt-in. They require SIP to be disabled and a helper dylib to be injected into `Messages.app`. `imsg launch` refuses to inject when SIP is enabled.
The helper-injection technique uses `imsg`'s own dylib to reach Messages private APIs. There is no third-party server or BlueBubbles runtime in the OpenClaw iMessage path.
<Warning>
**Disabling SIP is a real security tradeoff.** SIP is one of macOS's core protections against running modified system code; turning it off system-wide opens up additional attack surface and side effects. Notably, **disabling SIP on Apple Silicon Macs also disables the ability to install and run iOS apps on your Mac**.
Treat this as a deliberate operational choice, not a default. If your threat model can't tolerate SIP being off, bundled iMessage is limited to basic mode — text and media send/receive only, no reactions / edit / unsend / effects / group ops.
</Warning>
### Setup
1. **Install (or upgrade) `imsg`** on the Mac that runs Messages.app:
```bash
brew install steipete/tap/imsg
imsg --version
imsg status --json
```
The `imsg status --json` output reports `bridge_version`, `rpc_methods`, and per-method `selectors` so you can see what the current build supports before you start.
2. **Disable System Integrity Protection.** This is macOS-version-specific because the underlying Apple requirement depends on the OS and hardware:
- **macOS 10.1310.15 (SierraCatalina):** disable Library Validation via Terminal, reboot to Recovery Mode, run `csrutil disable`, restart.
- **macOS 11+ (Big Sur and later), Intel:** Recovery Mode (or Internet Recovery), `csrutil disable`, restart.
- **macOS 11+, Apple Silicon:** power-button startup sequence to enter Recovery; on recent macOS versions hold the **Left Shift** key when you click Continue, then `csrutil disable`. Virtual-machine setups follow a separate flow — take a VM snapshot first.
- **macOS 26 / Tahoe:** library-validation policies and `imagent` private-entitlement checks have tightened further; `imsg` may need an updated build to keep up. If `imsg launch` injection or specific `selectors` start returning false after a macOS major upgrade, check `imsg`'s release notes before assuming the SIP step succeeded.
Follow Apple's Recovery-mode flow for your Mac to disable SIP before running `imsg launch`.
3. **Inject the helper.** With SIP disabled and Messages.app signed in:
```bash
imsg launch
```
`imsg launch` refuses to inject when SIP is still enabled, so this also doubles as a confirmation that step 2 took.
4. **Verify the bridge from OpenClaw:**
```bash
openclaw channels status --probe
```
The iMessage entry should report `works`, and `imsg status --json | jq '.selectors'` should show `retractMessagePart: true` plus whichever edit / typing / read selectors your macOS build exposes. The OpenClaw plugin per-method gating in `actions.ts` only advertises actions whose underlying selector is `true`, so the action surface you see in the agent's tool list reflects what the bridge can actually do on this host.
If `openclaw channels status --probe` reports the channel as `works` but specific actions throw "iMessage `<action>` requires the imsg private API bridge" at dispatch time, run `imsg launch` again — the helper can fall out (Messages.app restart, OS update, etc.) and the cached `available: true` status will keep advertising actions until the next probe refreshes.
### When you can't disable SIP
If SIP-disabled isn't acceptable for your threat model:
- `imsg` falls back to basic mode — text + media + receive only.
- The OpenClaw plugin still advertises text/media send and inbound monitoring; it just hides `react`, `edit`, `unsend`, `reply`, `sendWithEffect`, and group ops from the action surface (per the per-method capability gate).
- You can run a separate non-Apple-Silicon Mac (or a dedicated bot Mac) with SIP off for the iMessage workload, while keeping SIP enabled on your primary devices. See [Dedicated bot macOS user (separate iMessage identity)](#deployment-patterns) below.
## Access control and routing
<Tabs>
@@ -160,6 +233,36 @@ imsg send <handle> "test"
Runtime fallback: if `groupAllowFrom` is unset, iMessage group sender checks fall back to `allowFrom` when available.
Runtime note: if `channels.imessage` is completely missing, runtime falls back to `groupPolicy="allowlist"` and logs a warning (even if `channels.defaults.groupPolicy` is set).
<Warning>
Group routing has **two** allowlist gates running back-to-back, and both must pass:
1. **Sender / chat-target allowlist** (`channels.imessage.groupAllowFrom`) — handle, `chat_guid`, `chat_identifier`, or `chat_id`.
2. **Group registry** (`channels.imessage.groups`) — with `groupPolicy: "allowlist"`, this gate requires either a `groups: { "*": { ... } }` wildcard entry (sets `allowAll = true`), or an explicit per-`chat_id` entry under `groups`.
If gate 2 has nothing in it, every group message is dropped. The plugin emits two `warn`-level signals at the default log level:
- one-time per account at startup: `imessage: groupPolicy="allowlist" but channels.imessage.groups is empty for account "<id>"`
- one-time per `chat_id` at runtime: `imessage: dropping group message from chat_id=<id> ...`
DMs continue to work because they take a different code path.
Minimum config to keep groups flowing under `groupPolicy: "allowlist"`:
```json5
{
channels: {
imessage: {
groupPolicy: "allowlist",
groupAllowFrom: ["+15555550123"],
groups: { "*": { "requireMention": true } },
},
},
}
```
If those `warn` lines appear in the gateway log, gate 2 is dropping — add the `groups` block.
</Warning>
Mention gating for groups:
- iMessage has no native mention metadata
@@ -168,6 +271,37 @@ imsg send <handle> "test"
Control commands from authorized senders can bypass mention gating in groups.
Per-group `systemPrompt`:
Each entry under `channels.imessage.groups.*` accepts an optional `systemPrompt` string. The value is injected into the agent's system prompt on every turn that handles a message in that group. Resolution mirrors the per-group prompt resolution used by `channels.whatsapp.groups`:
1. **Group-specific system prompt** (`groups["<chat_id>"].systemPrompt`): used when the specific group entry exists in the map **and** its `systemPrompt` key is defined. If `systemPrompt` is an empty string (`""`) the wildcard is suppressed and no system prompt is applied to that group.
2. **Group wildcard system prompt** (`groups["*"].systemPrompt`): used when the specific group entry is absent from the map entirely, or when it exists but defines no `systemPrompt` key.
```json5
{
channels: {
imessage: {
groupPolicy: "allowlist",
groupAllowFrom: ["+15555550123"],
groups: {
"*": { systemPrompt: "Use British spelling." },
"8421": {
requireMention: true,
systemPrompt: "This is the on-call rotation chat. Keep replies under 3 sentences.",
},
"9907": {
// explicit suppression: the wildcard "Use British spelling." does not apply here
systemPrompt: "",
},
},
},
},
}
```
Per-group prompts only apply to group messages — direct messages in this channel are unaffected.
</Tab>
<Tab title="Sessions and deterministic replies">
@@ -264,24 +398,24 @@ See [ACP Agents](/tools/acp-agents) for shared ACP binding behavior.
Example:
```json5
{
channels: {
imessage: {
enabled: true,
cliPath: "~/.openclaw/scripts/imsg-ssh",
remoteHost: "bot@mac-mini.tailnet-1234.ts.net",
includeAttachments: true,
dbPath: "/Users/bot/Library/Messages/chat.db",
},
},
}
```
```json5
{
channels: {
imessage: {
enabled: true,
cliPath: "~/.openclaw/scripts/imsg-ssh",
remoteHost: "bot@mac-mini.tailnet-1234.ts.net",
includeAttachments: true,
dbPath: "/Users/bot/Library/Messages/chat.db",
},
},
}
```
```bash
#!/usr/bin/env bash
exec ssh -T bot@mac-mini.tailnet-1234.ts.net imsg "$@"
```
```bash
#!/usr/bin/env bash
exec ssh -T bot@mac-mini.tailnet-1234.ts.net imsg "$@"
```
Use SSH keys so both SSH and SCP are non-interactive.
Ensure the host key is trusted first (for example `ssh bot@mac-mini.tailnet-1234.ts.net`) so `known_hosts` is populated.
@@ -300,7 +434,7 @@ exec ssh -T bot@mac-mini.tailnet-1234.ts.net imsg "$@"
<AccordionGroup>
<Accordion title="Attachments and media">
- inbound attachment ingestion is optional: `channels.imessage.includeAttachments`
- inbound attachment ingestion is **off by default** — set `channels.imessage.includeAttachments: true` to forward photos, voice memos, video, and other attachments to the agent. With it disabled, attachment-only iMessages are dropped before reaching the agent and may produce no `Inbound message` log line at all.
- remote attachment paths can be fetched via SCP when `remoteHost` is set
- attachment paths must match allowed roots:
- `channels.imessage.attachmentRoots` (local)
@@ -332,10 +466,76 @@ exec ssh -T bot@mac-mini.tailnet-1234.ts.net imsg "$@"
- `sms:+1555...`
- `user@example.com`
```bash
imsg chats --limit 20
```bash
imsg chats --limit 20
```
</Accordion>
</AccordionGroup>
## Private API actions
When `imsg launch` is running and `openclaw channels status --probe` reports `privateApi.available: true`, the message tool can use iMessage-native actions in addition to normal text sends.
```json5
{
channels: {
imessage: {
actions: {
reactions: true,
edit: true,
unsend: true,
reply: true,
sendWithEffect: true,
sendAttachment: true,
renameGroup: true,
setGroupIcon: true,
addParticipant: true,
removeParticipant: true,
leaveGroup: true,
},
},
},
}
```
<AccordionGroup>
<Accordion title="Available actions">
- **react**: Add/remove iMessage tapbacks (`messageId`, `emoji`, `remove`). Supported tapbacks map to love, like, dislike, laugh, emphasize, and question.
- **reply**: Send a threaded reply to an existing message (`messageId`, `text` or `message`, plus `chatGuid`, `chatId`, `chatIdentifier`, or `to`).
- **sendWithEffect**: Send text with an iMessage effect (`text` or `message`, `effect` or `effectId`).
- **edit**: Edit a sent message on supported macOS/private API versions (`messageId`, `text` or `newText`).
- **unsend**: Retract a sent message on supported macOS/private API versions (`messageId`).
- **upload-file**: Send media/files (`buffer` as base64 or a hydrated `media`/`path`/`filePath`, `filename`, optional `asVoice`). Legacy alias: `sendAttachment`.
- **renameGroup**, **setGroupIcon**, **addParticipant**, **removeParticipant**, **leaveGroup**: Manage group chats when the current target is a group conversation.
</Accordion>
<Accordion title="Message IDs">
Inbound iMessage context includes both short `MessageSid` values and full message GUIDs when available. Short IDs are scoped to the recent in-memory reply cache and are checked against the current chat before use. If a short ID has expired or belongs to another chat, retry with the full `MessageSidFull`.
</Accordion>
<Accordion title="Capability detection">
OpenClaw hides private API actions only when the cached probe status says the bridge is unavailable. If the status is unknown, actions remain visible and dispatch probes lazily so the first action can succeed after `imsg launch` without a separate manual status refresh.
</Accordion>
<Accordion title="Read receipts and typing">
When the private API bridge is up, accepted inbound chats are marked read before dispatch and a typing bubble is shown to the sender while the agent generates. Disable read-marking with:
```json5
{
channels: {
imessage: {
sendReadReceipts: false,
},
},
}
```
Older `imsg` builds that pre-date the per-method capability list will gate off typing/read silently; OpenClaw logs a one-time warning per restart so the missing receipt is attributable.
</Accordion>
</AccordionGroup>
@@ -355,18 +555,158 @@ Disable:
}
```
<a id="coalescing-split-send-dms-command--url-in-one-composition"></a>
## Coalescing split-send DMs (command + URL in one composition)
When a user types a command and a URL together — e.g. `Dump https://example.com/article` — Apple's Messages app splits the send into **two separate `chat.db` rows**:
1. A text message (`"Dump"`).
2. A URL-preview balloon (`"https://..."`) with OG-preview images as attachments.
The two rows arrive at OpenClaw ~0.8-2.0 s apart on most setups. Without coalescing, the agent receives the command alone on turn 1, replies (often "send me the URL"), and only sees the URL on turn 2 — at which point the command context is already lost. This is Apple's send pipeline, not anything OpenClaw or `imsg` introduces.
`channels.imessage.coalesceSameSenderDms` opts a DM into merging consecutive same-sender rows into a single agent turn. Group chats continue to dispatch per-message so multi-user turn structure is preserved.
<Tabs>
<Tab title="When to enable">
Enable when:
- You ship skills that expect `command + payload` in one message (dump, paste, save, queue, etc.).
- Your users paste URLs, images, or long content alongside commands.
- You can accept the added DM turn latency (see below).
Leave disabled when:
- You need minimum command latency for single-word DM triggers.
- All your flows are one-shot commands without payload follow-ups.
</Tab>
<Tab title="Enabling">
```json5
{
channels: {
imessage: {
coalesceSameSenderDms: true, // opt in (default: false)
},
},
}
```
With the flag on and no explicit `messages.inbound.byChannel.imessage`, the debounce window widens to **2500 ms** (the legacy default is 0 ms — no debouncing). The wider window is required because Apple's split-send cadence of 0.8-2.0 s does not fit in a tighter default.
To tune the window yourself:
```json5
{
messages: {
inbound: {
byChannel: {
// 2500 ms works for most setups; raise to 4000 ms if your Mac is
// slow or under memory pressure (observed gap can stretch past 2 s
// then).
imessage: 2500,
},
},
},
}
```
</Tab>
<Tab title="Trade-offs">
- **Added latency for DM messages.** With the flag on, every DM (including standalone control commands and single-text follow-ups) waits up to the debounce window before dispatching, in case a payload row is coming. Group-chat messages keep instant dispatch.
- **Merged output is bounded.** Merged text caps at 4000 chars with an explicit `…[truncated]` marker; attachments cap at 20; source entries cap at 10 (first-plus-latest retained beyond that). Every source GUID is tracked in `coalescedMessageGuids` for downstream telemetry.
- **DM-only.** Group chats fall through to per-message dispatch so the bot stays responsive when multiple people are typing.
- **Opt-in, per-channel.** Other channels (Telegram, WhatsApp, Slack, …) are unaffected. Legacy BlueBubbles configs that set `channels.bluebubbles.coalesceSameSenderDms` should migrate that value to `channels.imessage.coalesceSameSenderDms`.
</Tab>
</Tabs>
### Scenarios and what the agent sees
| User composes | `chat.db` produces | Flag off (default) | Flag on + 2500 ms window |
| ------------------------------------------------------------------ | --------------------- | --------------------------------------- | ----------------------------------------------------------------------- |
| `Dump https://example.com` (one send) | 2 rows ~1 s apart | Two agent turns: "Dump" alone, then URL | One turn: merged text `Dump https://example.com` |
| `Save this 📎image.jpg caption` (attachment + text) | 2 rows | Two turns (attachment dropped on merge) | One turn: text + image preserved |
| `/status` (standalone command) | 1 row | Instant dispatch | **Wait up to window, then dispatch** |
| URL pasted alone | 1 row | Instant dispatch | Instant dispatch (only one entry in bucket) |
| Text + URL sent as two deliberate separate messages, minutes apart | 2 rows outside window | Two turns | Two turns (window expires between them) |
| Rapid flood (>10 small DMs inside window) | N rows | N turns | One turn, bounded output (first + latest, text/attachment caps applied) |
| Two people typing in a group chat | N rows from M senders | M+ turns (one per sender bucket) | M+ turns — group chats are not coalesced |
## Catching up after gateway downtime
When the gateway is offline (crash, restart, Mac sleep, machine off), `imsg watch` resumes from the current `chat.db` state once the gateway comes back up — anything that arrived during the gap is, by default, never seen. Catchup replays those messages on the next startup so the agent does not silently miss inbound traffic.
Catchup is **disabled by default**. Enable it per channel:
```ts
channels: {
imessage: {
catchup: {
enabled: true, // master switch (default: false)
maxAgeMinutes: 120, // skip rows older than now - 2h (default: 120, clamp 1..720)
perRunLimit: 50, // max rows replayed per startup (default: 50, clamp 1..500)
firstRunLookbackMinutes: 30, // first run with no cursor: look back 30 min (default: 30)
maxFailureRetries: 10, // give up on a wedged guid after 10 dispatch failures (default: 10)
},
},
}
```
### How it runs
One pass per `monitorIMessageProvider` startup, sequenced as `imsg launch` ready → `watch.subscribe` → `performIMessageCatchup` → live dispatch loop. Catchup itself uses `chats.list` + per-chat `messages.history` against the same JSON-RPC client used by `imsg watch`. Anything that arrives during the catchup pass flows through live dispatch normally; the existing inbound-dedupe cache absorbs any overlap with replayed rows.
Each replayed row is fed through the live dispatch path (`evaluateIMessageInbound` + `dispatchInboundMessage`), so allowlists, group policy, debouncer, echo cache, and read receipts behave identically on replayed and live messages.
### Cursor and retry semantics
Catchup keeps a per-account cursor at `<openclawStateDir>/imessage/catchup/<account>__<hash>.json` (the OpenClaw state dir defaults to `~/.openclaw`, overridable with `OPENCLAW_STATE_DIR`):
```json
{
"lastSeenMs": 1717900800000,
"lastSeenRowid": 482910,
"updatedAt": 1717900801234,
"failureRetries": { "<guid>": 1 }
}
```
- The cursor advances on each successful dispatch and is held when a row's dispatch throws — the next startup retries the same row from the held cursor.
- After `maxFailureRetries` consecutive throws against the same `guid`, catchup logs a `warn` and force-advances the cursor past the wedged message so subsequent startups can make progress.
- Already-given-up guids are skipped on sight (no dispatch attempt) on later runs and counted under `skippedGivenUp` in the run summary.
### Operator-visible signals
```
imessage catchup: replayed=N skippedFromMe=… skippedGivenUp=… failed=… givenUp=… fetchedCount=…
imessage catchup: giving up on guid=<guid> after <N> failures; advancing cursor past it
imessage catchup: fetched <X> rows across chats, capped to perRunLimit=<Y>
```
A `WARN ... capped to perRunLimit` line means a single startup did not drain the full backlog. Raise `perRunLimit` (max 500) if your gaps regularly exceed the default 50-row pass.
### When to leave it off
- Gateway runs continuously with watchdog auto-restart and gaps are always < a few seconds — the default of off is fine.
- DM volume is low and missed messages would not change agent behavior — the `firstRunLookbackMinutes` initial window can dispatch surprising old context on first enable.
When you turn catchup on, the first startup with no cursor only looks back `firstRunLookbackMinutes` (30 min default), not the full `maxAgeMinutes` window — this avoids replaying a long history of pre-enable messages.
## Troubleshooting
<AccordionGroup>
<Accordion title="imsg not found or RPC unsupported">
Validate the binary and RPC support:
```bash
imsg rpc --help
openclaw channels status --probe
```
```bash
imsg rpc --help
imsg status --json
openclaw channels status --probe
```
If probe reports RPC unsupported, update `imsg`. If the Gateway is not running on macOS, use the Remote Mac over SSH setup above instead of the default local `imsg` path.
If probe reports RPC unsupported, update `imsg`. If private API actions are unavailable, run `imsg launch` in the logged-in macOS user session and probe again. If the Gateway is not running on macOS, use the Remote Mac over SSH setup above instead of the default local `imsg` path.
</Accordion>
@@ -419,10 +759,10 @@ openclaw channels status --probe --channel imessage
<Accordion title="macOS permission prompts were missed">
Re-run in an interactive GUI terminal in the same user/session context and approve prompts:
```bash
imsg chats --limit 1
imsg send <handle> "test"
```
```bash
imsg chats --limit 1
imsg send <handle> "test"
```
Confirm Full Disk Access + Automation are granted for the process context that runs OpenClaw/`imsg`.
@@ -438,6 +778,7 @@ imsg send <handle> "test"
## Related
- [Channels Overview](/channels) — all supported channels
- [Coming from BlueBubbles](/channels/imessage-from-bluebubbles) — config translation table and step-by-step cutover
- [Pairing](/channels/pairing) — DM authentication and pairing flow
- [Groups](/channels/groups) — group chat behavior and mention gating
- [Channel Routing](/channels/channel-routing) — session routing for messages

View File

@@ -24,7 +24,7 @@ Text is supported everywhere; media and reactions vary by channel.
- [Discord](/channels/discord) - Discord Bot API + Gateway; supports servers, channels, and DMs.
- [Feishu](/channels/feishu) - Feishu/Lark bot via WebSocket (bundled plugin).
- [Google Chat](/channels/googlechat) - Google Chat API app via HTTP webhook (downloadable plugin).
- [iMessage](/channels/imessage) - Native macOS integration via the `imsg` CLI on a signed-in Mac; use an SSH wrapper when the Gateway runs elsewhere.
- [iMessage](/channels/imessage) - Native macOS integration via the `imsg` bridge on a signed-in Mac (or SSH wrapper when the Gateway runs elsewhere), including private API actions for replies, tapbacks, effects, attachments, and group management. Preferred for new OpenClaw iMessage setups when host permissions and Messages access fit.
- [IRC](/channels/irc) - Classic IRC servers; channels + DMs with pairing/allowlist controls.
- [LINE](/channels/line) - LINE Messaging API bot (downloadable plugin).
- [Matrix](/channels/matrix) - Matrix protocol (downloadable plugin).

View File

@@ -0,0 +1,77 @@
---
summary: "Matrix MessagePresentation metadata for OpenClaw-aware clients"
read_when:
- Building Matrix clients that render OpenClaw rich responses
- Debugging com.openclaw.presentation event content
title: "Matrix presentation metadata"
---
OpenClaw can attach normalized `MessagePresentation` metadata to outbound Matrix `m.room.message` events under `com.openclaw.presentation`.
Stock Matrix clients continue to render the plain text `body`. OpenClaw-aware clients can read the structured metadata and render native UI such as buttons, selects, context rows, and dividers.
## Event content
The metadata is stored in Matrix event content:
```json
{
"msgtype": "m.text",
"body": "Select model\n\n- DeepSeek: /model deepseek/deepseek-chat",
"com.openclaw.presentation": {
"version": 1,
"type": "message.presentation",
"title": "Select model",
"tone": "info",
"blocks": [
{
"type": "select",
"placeholder": "Choose model",
"options": [
{
"label": "DeepSeek",
"value": "/model deepseek/deepseek-chat"
}
]
}
]
}
}
```
`version` is the Matrix presentation metadata schema version. `type` is a stable discriminator for OpenClaw-aware clients. Clients should ignore unknown `type` values, unknown versions they cannot safely interpret, and unknown block types.
## Fallback behavior
OpenClaw always renders a readable plain text fallback into `body`. The structured metadata is additive and must not be required for basic Matrix interoperability.
Unsupported clients should continue to show the fallback text. OpenClaw-aware clients may prefer the structured metadata for display while preserving the fallback text for copy, search, notifications, and accessibility.
## Supported blocks
The Matrix outbound adapter advertises support for:
- `buttons`
- `select`
- `context`
- `divider`
Clients should treat these blocks as best-effort presentation hints. Unknown fields and unknown block types should be ignored rather than causing the full message to fail rendering.
## Interactions
This metadata does not add Matrix callback semantics. Button and select option values are fallback interaction payloads, usually slash commands or text commands. A Matrix client that wants to support interaction can send the selected value back to the room as a normal message.
For example, a button with value `/model deepseek/deepseek-chat` can be handled by sending that value as an encrypted Matrix text message in the same room.
## Relationship to approval metadata
`com.openclaw.presentation` is for general rich message presentation.
Approval prompts use the dedicated `com.openclaw.approval` metadata because approvals carry safety-sensitive state, decisions, and exec/plugin details. If both metadata keys are present on the same event, clients should prefer the dedicated approval renderer.
## Media messages
When a reply contains multiple media URLs, OpenClaw sends one Matrix event per media URL. Presentation metadata is attached only to the first media event so clients have one stable structured payload and duplicate renderers are avoided.
Keep presentation metadata compact. Large user-visible text should stay in `body` and use the normal Matrix text chunking path.

View File

@@ -11,12 +11,14 @@ It uses the official `matrix-js-sdk` and supports DMs, rooms, threads, media, re
## Install
Install Matrix before configuring the channel:
Install Matrix from ClawHub before configuring the channel:
```bash
openclaw plugins install @openclaw/matrix
```
Bare plugin specs try ClawHub first, then npm fallback. To force the registry source, use `openclaw plugins install clawhub:@openclaw/matrix` or `openclaw plugins install npm:@openclaw/matrix`.
From a local checkout:
```bash

View File

@@ -40,7 +40,7 @@ Details: [Plugins](/tools/plugin)
2. On your Nextcloud server, create a bot:
```bash
./occ talk:bot:install "OpenClaw" "<shared-secret>" "<webhook-url>" --feature reaction
./occ talk:bot:install "OpenClaw" "<shared-secret>" "<webhook-url>" --feature webhook --feature response --feature reaction
```
3. Enable the bot in the target room settings.

View File

@@ -77,6 +77,10 @@ Both transports are production-ready and reach feature parity for messaging, sla
"bot": [
"app_mentions:read",
"assistant:write",
"bookmarks:read",
"bookmarks:write",
"canvases:read",
"canvases:write",
"channels:history",
"channels:read",
"chat:write",
@@ -96,6 +100,8 @@ Both transports are production-ready and reach feature parity for messaging, sla
"pins:write",
"reactions:read",
"reactions:write",
"reminders:read",
"reminders:write",
"usergroups:read",
"users:read"
]
@@ -268,6 +274,10 @@ openclaw gateway
"bot": [
"app_mentions:read",
"assistant:write",
"bookmarks:read",
"bookmarks:write",
"canvases:read",
"canvases:write",
"channels:history",
"channels:read",
"chat:write",
@@ -287,6 +297,8 @@ openclaw gateway
"pins:write",
"reactions:read",
"reactions:write",
"reminders:read",
"reminders:write",
"usergroups:read",
"users:read"
]
@@ -494,6 +506,10 @@ Base manifest (Socket Mode default):
"bot": [
"app_mentions:read",
"assistant:write",
"bookmarks:read",
"bookmarks:write",
"canvases:read",
"canvases:write",
"channels:history",
"channels:read",
"chat:write",
@@ -513,6 +529,8 @@ Base manifest (Socket Mode default):
"pins:write",
"reactions:read",
"reactions:write",
"reminders:read",
"reminders:write",
"usergroups:read",
"users:read"
]
@@ -801,15 +819,17 @@ Slack actions are controlled by `channels.slack.actions.*`.
Available action groups in current Slack tooling:
| Group | Default |
| ---------- | ------- |
| messages | enabled |
| reactions | enabled |
| pins | enabled |
| memberInfo | enabled |
| emojiList | enabled |
- Default-enabled groups: `messages`, `reactions`, `pins`, `memberInfo`, `emojiList`.
- Opt-in advanced groups: `search`, `channelInfo`, `channels`, `files`, `scheduledMessages`, `ephemeralMessages`, `bookmarks`, `reminders`, `canvases`.
Current Slack message actions include `send`, `upload-file`, `download-file`, `read`, `edit`, `delete`, `pin`, `unpin`, `list-pins`, `member-info`, and `emoji-list`. `download-file` accepts Slack file IDs shown in inbound file placeholders and returns image previews for images or local file metadata for other file types.
Current Slack message actions include `send`, `upload-file`, `download-file`, `read`, `edit`, `delete`, `get-permalink`, `pin`, `unpin`, `list-pins`, `member-info`, and `emoji-list`. `download-file` accepts Slack file IDs shown in inbound file placeholders and returns image previews for images or local file metadata for other file types.
Advanced opt-in actions:
- Search and discovery: `search`, `channel-info`, `channel-list`. `search` uses Slack `search.messages` and requires `channels.slack.userToken` with the user-token `search:read` scope.
- Files: `file-list`, `file-delete`.
- Delivery controls: `post-ephemeral`, `schedule-message`, `scheduled-list`, `delete-scheduled`; `send` and scheduled sends also accept Slack `replyBroadcast`, `unfurlLinks`, and `unfurlMedia`.
- Workspace objects: `bookmark-add`, `bookmark-edit`, `bookmark-list`, `bookmark-remove`, `reminder-add`, `reminder-list`, `reminder-info`, `reminder-complete`, `reminder-delete`, `canvas-create`, `canvas-edit`, `canvas-delete`, `canvas-section-lookup`, `channel-canvas-create`.
## Access control and routing
@@ -930,6 +950,7 @@ Current Slack message actions include `send`, `upload-file`, `download-file`, `r
- With default `session.dmScope=main`, Slack DMs collapse to agent main session.
- Channel sessions: `agent:<agentId>:slack:channel:<channelId>`.
- Thread replies can create thread session suffixes (`:thread:<threadTs>`) when applicable.
- In channels where OpenClaw handles top-level messages without requiring an explicit mention, non-`off` `replyToMode` routes each handled root into `agent:<agentId>:slack:channel:<channelId>:thread:<rootTs>` so the visible Slack thread maps to one OpenClaw session from the first turn.
- `channels.slack.thread.historyScope` default is `thread`; `thread.inheritParent` default is `false`.
- `channels.slack.thread.initialHistoryLimit` controls how many existing thread messages are fetched when a new thread session starts (default `20`; set `0` to disable).
- `channels.slack.thread.requireExplicitMention` (default `false`): when `true`, suppress implicit thread mentions so the bot only responds to explicit `@bot` mentions inside threads, even when the bot already participated in the thread. Without this, replies in a bot-participated thread bypass `requireMention` gating.

View File

@@ -258,7 +258,7 @@ curl "https://api.telegram.org/bot<bot_token>/getUpdates"
- Telegram is owned by the gateway process.
- Routing is deterministic: Telegram inbound replies back to Telegram (the model does not pick channels).
- Inbound messages normalize into the shared channel envelope with reply metadata and media placeholders.
- Inbound messages normalize into the shared channel envelope with reply metadata, media placeholders, and persisted reply-chain context for Telegram replies the gateway has observed.
- Group sessions are isolated by group ID. Forum topics append `:topic:<threadId>` to keep topics isolated.
- DM messages can carry `message_thread_id`; OpenClaw preserves the thread ID for replies but keeps DMs on the flat session by default. Configure `channels.telegram.dm.threadReplies: "inbound"`, `channels.telegram.direct.<chatId>.threadReplies: "inbound"`, `requireTopic: true`, or a matching topic config when you intentionally want DM topic session isolation.
- Long polling uses grammY runner with per-chat/per-thread sequencing. Overall runner sink concurrency uses `agents.defaults.maxConcurrent`.
@@ -773,7 +773,7 @@ curl "https://api.telegram.org/bot<bot_token>/getUpdates"
- `channels.telegram.timeoutSeconds` overrides Telegram API client timeout (if unset, grammY default applies). Bot clients clamp configured values below the 60-second outbound text/typing request guard so grammY does not abort visible reply delivery before OpenClaw's transport guard and fallback can run. Long polling still uses a 45-second `getUpdates` request guard so idle polls are not abandoned indefinitely.
- `channels.telegram.pollingStallThresholdMs` defaults to `120000`; tune between `30000` and `600000` only for false-positive polling-stall restarts.
- group context history uses `channels.telegram.historyLimit` or `messages.groupChat.historyLimit` (default 50); `0` disables.
- reply/quote/forward supplemental context is currently passed as received.
- reply/quote/forward supplemental context is normalized into a nearest-first reply chain when the gateway has observed the parent messages; the observed-message cache is persisted beside the session store. Telegram only includes one shallow `reply_to_message` in updates, so chains older than the cache are limited to Telegram's current update payload.
- Telegram allowlists primarily gate who can trigger the agent, not a full supplemental-context redaction boundary.
- DM history controls:
- `channels.telegram.dmHistoryLimit`

View File

@@ -0,0 +1,96 @@
---
summary: "How ClawHub publishing works for skills, plugins, owners, scopes, releases, and review."
read_when:
- Publishing a skill or plugin
- Debugging owner or package scope errors
- Adding publish UI, CLI, or backend behavior
---
# Publishing on ClawHub
ClawHub publishing is owner-scoped: every publish targets a publisher, and the
server decides whether the signed-in user is allowed to publish there.
## Owners
An owner is a ClawHub publisher handle, such as `@alice` or `@openclaw`.
Personal owners are created for users. Org owners can have multiple members.
When you publish, you either use your personal owner or choose an org owner
where you have publisher access.
## Skills
Skills are published from a skill folder. The public page is:
```text
https://clawhub.ai/<owner>/<slug>
```
Example:
```text
https://clawhub.ai/alice/review-helper
```
The publish request includes the selected owner, slug, version, changelog, and
files. The server verifies that the actor can publish as that owner before it
creates the release.
## Plugins
Plugins use npm-style package names. Scoped package names include the owner in
the first part of the name:
```text
@owner/package-name
```
The scope must match the selected publish owner. If your package is named
`@openclaw/dronzer`, it can only be published as `@openclaw`. If you publish as
`@vintageayu`, rename the package to `@vintageayu/dronzer`.
This prevents a package from claiming an org namespace that the publisher does
not control.
## Release Flow
1. The UI, CLI, or GitHub workflow gathers package metadata and files.
2. The publish request is sent to ClawHub with the selected owner.
3. The server validates owner permissions, package scope, package name, version,
file limits, and source metadata.
4. ClawHub stores the release and starts automated security checks.
5. New releases are hidden from normal install/download surfaces until review
and verification finish.
If validation fails, the release is not created.
## FAQ
### Package scope must match selected owner
If the package scope and selected owner do not match, ClawHub rejects the
publish:
```text
Package scope "@openclaw" must match selected owner "@vintageayu".
Publish as "@openclaw" or rename this package to "@vintageayu/dronzer".
```
To fix it, either choose the owner named by the package scope, or rename the
package so the scope matches the owner you can publish as.
If the package name already has the right scope but the package is owned by the
wrong publisher, transfer ownership instead:
```sh
clawhub package transfer @opik/opik-openclaw --to opik
```
Use package transfer only when you have admin access to both the current package
owner and the destination publisher. It does not let you publish into a scope you
cannot manage.
This protects org namespaces. A package named `@openclaw/dronzer` claims the
`@openclaw` namespace, so only publishers with access to the `@openclaw` owner
can publish it.

View File

@@ -44,11 +44,12 @@ Quick rule:
| `initialize`, `newSession`, `prompt`, `cancel` | Implemented | Core bridge flow over stdio to Gateway chat/send + abort. |
| `listSessions`, slash commands | Implemented | Session list works against Gateway session state with bounded cursor pagination and `cwd` filtering where Gateway session rows carry workspace metadata; commands are advertised via `available_commands_update`. |
| `resumeSession`, `closeSession` | Implemented | Resume rebinds an ACP session to an existing Gateway session without replaying history. Close cancels active bridge work, resolves pending prompts as cancelled, and releases bridge session state. |
| `loadSession` | Partial | Rebinds the ACP session to a Gateway session key and replays stored user/assistant text history. Tool/system history is not reconstructed yet. |
| `loadSession` | Partial | Rebinds the ACP session to a Gateway session key and replays ACP event-ledger history for bridge-created sessions. Older/no-ledger sessions fall back to stored user/assistant text. |
| Prompt content (`text`, embedded `resource`, images) | Partial | Text/resources are flattened into chat input; images become Gateway attachments. |
| Session modes | Partial | `session/set_mode` is supported and the bridge exposes initial Gateway-backed session controls for thought level, tool verbosity, reasoning, usage detail, and elevated actions. Broader ACP-native mode/config surfaces are still out of scope. |
| Session info and usage updates | Partial | The bridge emits `session_info_update` and best-effort `usage_update` notifications from cached Gateway session snapshots. Usage is approximate and only sent when Gateway token totals are marked fresh. |
| Tool streaming | Partial | `tool_call` / `tool_call_update` events include raw I/O, text content, and best-effort file locations when Gateway tool args/results expose them. Embedded terminals and richer diff-native output are still not exposed. |
| Exec approvals | Partial | Gateway exec approval prompts during active ACP prompt turns are relayed to the ACP client with `session/request_permission`. |
| Per-session MCP servers (`mcpServers`) | Unsupported | Bridge mode rejects per-session MCP server requests. Configure MCP on the OpenClaw gateway or agent instead. |
| Client filesystem methods (`fs/read_text_file`, `fs/write_text_file`) | Unsupported | The bridge does not call ACP client filesystem methods. |
| Client terminal methods (`terminal/*`) | Unsupported | The bridge does not create ACP client terminals or stream terminal ids through tool calls. |
@@ -56,9 +57,9 @@ Quick rule:
## Known Limitations
- `loadSession` replays stored user and assistant text history, but it does not
reconstruct historic tool calls, system notices, or richer ACP-native event
types.
- `loadSession` can replay complete ACP event-ledger history only for
bridge-created sessions. Older/no-ledger sessions still use transcript
fallback and do not reconstruct historic tool calls or system notices.
- If multiple ACP clients share the same Gateway session key, event and cancel
routing are best-effort rather than strictly isolated per client. Prefer the
default isolated `acp:<uuid>` sessions when you need clean editor-local
@@ -76,6 +77,8 @@ Quick rule:
- Tool follow-along data is best-effort. The bridge can surface file paths that
appear in known tool args/results, but it does not yet emit ACP terminals or
structured file diffs.
- Exec approval relay is scoped to the active ACP prompt turn; approvals from
other Gateway sessions are ignored.
## Usage

View File

@@ -53,6 +53,8 @@ skipped.
The archive payload stores file contents from those source trees, and the embedded `manifest.json` records the resolved absolute source paths plus the archive layout used for each asset.
During archive creation, OpenClaw skips known live-mutation files that do not have restoration value, including active agent session transcripts, cron run logs, rolling logs, delivery queues, socket/pid/temp files under the state directory, and related durable-queue temp files. The JSON result includes `skippedVolatileCount` so automation can see how many files were intentionally omitted.
Installed plugin source and manifest files under the state directory's
`extensions/` tree are included, but their nested `node_modules/` dependency
trees are skipped. Those dependencies are rebuildable install artifacts; after

View File

@@ -170,7 +170,7 @@ configured OpenClaw model. If no configured model is usable yet, it can fall
back to local runtimes already present on the machine:
- Claude Code CLI: `claude-cli/claude-opus-4-7`
- Codex app-server harness: `openai/gpt-5.5` with `agentRuntime.id: "codex"`
- Codex app-server harness: `openai/gpt-5.5`
- Codex CLI: `codex-cli/gpt-5.5`
The model-assisted planner cannot mutate config directly. It must translate the

View File

@@ -36,7 +36,7 @@ openclaw daemon uninstall
- `status`: `--url`, `--token`, `--password`, `--timeout`, `--no-probe`, `--require-rpc`, `--deep`, `--json`
- `install`: `--port`, `--runtime <node|bun>`, `--token`, `--force`, `--json`
- `restart`: `--safe`, `--force`, `--wait <duration>`, `--json`
- `restart`: `--safe`, `--skip-deferral`, `--force`, `--wait <duration>`, `--json`
- lifecycle (`uninstall|start|stop`): `--json`
Notes:
@@ -54,6 +54,7 @@ Notes:
- On macOS, `install` keeps LaunchAgent plists owner-only and loads managed service environment values through an owner-only file and wrapper instead of serializing API keys or auth-profile env refs into `EnvironmentVariables`.
- If you intentionally run multiple gateways on one host, isolate ports, config/state, and workspaces; see [/gateway#multiple-gateways-same-host](/gateway#multiple-gateways-same-host).
- `restart --safe` asks the running Gateway to preflight active work and schedule one coalesced restart after active work drains. Plain `restart` keeps the existing service-manager behavior; `--force` remains the immediate override path.
- `restart --safe --skip-deferral` runs the OpenClaw-aware safe restart but bypasses the active-work deferral gate so the Gateway emits the restart immediately even when blockers are reported. Operator escape hatch when a stuck task run pins the safe restart; requires `--safe`.
## Prefer

View File

@@ -56,7 +56,7 @@ Notes:
- Doctor also scans `~/.openclaw/cron/jobs.json` (or `cron.store`) for legacy cron job shapes and can rewrite them in place before the scheduler has to auto-normalize them at runtime.
- On Linux, doctor warns when the user's crontab still runs legacy `~/.openclaw/bin/ensure-whatsapp.sh`; that script is no longer maintained and can log false WhatsApp gateway outages when cron lacks the systemd user-bus environment.
- When WhatsApp is enabled, doctor checks for a degraded Gateway event loop with local `openclaw-tui` clients still running. `doctor --fix` stops only verified local TUI clients so WhatsApp replies are not queued behind stale TUI refresh loops.
- Doctor rewrites legacy `openai-codex/*` model refs to canonical `openai/*` refs across primary models, fallbacks, heartbeat/subagent/compaction overrides, hooks, channel model overrides, and stale session route pins. `--fix` selects `agentRuntime.id: "codex"` only when the Codex plugin is installed, enabled, contributes the `codex` harness, and has usable OAuth; otherwise it selects `agentRuntime.id: "pi"` so the route stays on the default OpenClaw runner.
- Doctor rewrites legacy `openai-codex/*` model refs to canonical `openai/*` refs across primary models, fallbacks, heartbeat/subagent/compaction overrides, hooks, channel model overrides, and stale session route pins. `--fix` preserves explicit provider/model `agentRuntime` policy, removes stale whole-agent/session runtime pins, and leaves canonical OpenAI agent refs on the default Codex harness when the official OpenAI provider is in use.
- Doctor cleans legacy plugin dependency staging state created by older OpenClaw versions. It also repairs missing downloadable plugins that are referenced by config, such as `plugins.entries`, configured channels, configured provider/search settings, or configured agent runtimes. During package updates, doctor skips package-manager plugin repair until the package swap is complete; rerun `openclaw doctor --fix` afterward if a configured plugin still needs recovery. If the download fails, doctor reports the install error and preserves the configured plugin entry for the next repair attempt.
- Doctor repairs stale plugin config by removing missing plugin ids from `plugins.allow`/`plugins.entries`, plus matching dangling channel config, heartbeat targets, and channel model overrides when plugin discovery is healthy.
- Doctor quarantines invalid plugin config by disabling the affected `plugins.entries.<id>` entry and removing its invalid `config` payload. Gateway startup already skips only that bad plugin so other plugins and channels can keep running.

View File

@@ -110,11 +110,14 @@ openclaw gateway run
```bash
openclaw gateway restart
openclaw gateway restart --safe
openclaw gateway restart --safe --skip-deferral
openclaw gateway restart --force
```
`openclaw gateway restart --safe` asks the running Gateway to preflight active OpenClaw work before restarting. If queued operations, reply delivery, embedded runs, or task runs are active, the Gateway reports the blockers, coalesces duplicate safe restart requests, and restarts once the active work drains. Plain `restart` keeps the existing service-manager behavior for compatibility. Use `--force` only when you explicitly want the immediate override path.
`openclaw gateway restart --safe --skip-deferral` runs the same OpenClaw-aware coordinated restart as `--safe`, but bypasses the active-work deferral gate so the Gateway emits the restart immediately even when blockers are reported. Use it as the operator escape hatch when a deferral has been pinned by a stuck task run and `--safe` alone would wait indefinitely. `--skip-deferral` requires `--safe`.
<Warning>
Inline `--password` can be exposed in local process listings. Prefer `--password-file`, env, or a SecretRef-backed `gateway.auth.password`.
</Warning>
@@ -482,14 +485,17 @@ openclaw gateway restart
<Accordion title="Command options">
- `gateway status`: `--url`, `--token`, `--password`, `--timeout`, `--no-probe`, `--require-rpc`, `--deep`, `--json`
- `gateway install`: `--port`, `--runtime <node|bun>`, `--token`, `--wrapper <path>`, `--force`, `--json`
- `gateway restart`: `--safe`, `--force`, `--wait <duration>`, `--json`
- `gateway uninstall|start|stop`: `--json`
- `gateway restart`: `--safe`, `--skip-deferral`, `--force`, `--wait <duration>`, `--json`
- `gateway uninstall|start`: `--json`
- `gateway stop`: `--disable`, `--json`
</Accordion>
<Accordion title="Lifecycle behavior">
- Use `gateway restart` to restart a managed service. Do not chain `gateway stop` and `gateway start` as a restart substitute; on macOS, `gateway stop` intentionally disables the LaunchAgent before stopping it.
- Use `gateway restart` to restart a managed service. Do not chain `gateway stop` and `gateway start` as a restart substitute.
- On macOS, `gateway stop` uses `launchctl bootout` by default, which removes the LaunchAgent from the current boot session without persisting a disable — KeepAlive auto-recovery remains active for future crashes and `gateway start` re-enables cleanly without a manual `launchctl enable`. Pass `--disable` to persistently suppress KeepAlive and RunAtLoad so the gateway does not respawn until the next explicit `gateway start`; use this when a manual stop should survive reboots or system restarts.
- `gateway restart --safe` asks the running Gateway to preflight active OpenClaw work and defer the restart until reply delivery, embedded runs, and task runs drain. `--safe` cannot be combined with `--force` or `--wait`.
- `gateway restart --wait 30s` overrides the configured restart drain budget for that restart. Bare numbers are milliseconds; units such as `s`, `m`, and `h` are accepted. `--wait 0` waits indefinitely.
- `gateway restart --safe --skip-deferral` runs the OpenClaw-aware safe restart but bypasses the deferral gate so the Gateway emits the restart immediately even when blockers are reported. Operator escape hatch for stuck-task-run deferrals; requires `--safe`.
- `gateway restart --force` skips the active-work drain and restarts immediately. Use it when an operator has already inspected the listed task blockers and wants the gateway back now.
- Lifecycle commands accept `--json` for scripting.

View File

@@ -28,7 +28,7 @@ apply across the CLI.
| Pairing and channels | [`pairing`](/cli/pairing) · [`qr`](/cli/qr) · [`channels`](/cli/channels) |
| Security and plugins | [`security`](/cli/security) · [`secrets`](/cli/secrets) · [`skills`](/cli/skills) · [`plugins`](/cli/plugins) · [`proxy`](/cli/proxy) |
| Legacy aliases | [`daemon`](/cli/daemon) (gateway service) · [`clawbot`](/cli/clawbot) (namespace) |
| Plugins (optional) | [`voicecall`](/cli/voicecall) (if installed) |
| Plugins (optional) | [`path`](/cli/path) · [`voicecall`](/cli/voicecall) (if installed) |
## Global flags
@@ -121,6 +121,12 @@ openclaw [--dev] [--profile <name>] <command>
status
index
search
path
resolve
find
set
validate
emit
commitments
list
dismiss

View File

@@ -126,6 +126,7 @@ This table maps common inference tasks to the corresponding infer command.
- `openclaw infer ...` is the primary CLI surface for these workflows.
- Use `--json` when the output will be consumed by another command or script.
- Use `--provider` or `--model provider/model` when a specific backend is required.
- Use `model run --thinking <level>` to pass a one-shot thinking/reasoning level (`off`, `minimal`, `low`, `medium`, `high`, `adaptive`, `xhigh`, or `max`) while keeping the run raw.
- For `image describe`, `audio transcribe`, and `video describe`, `--model` must use the form `<provider/model>`.
- For `image describe`, an explicit `--model` runs that provider/model directly. The model must be image-capable in the model catalog or provider config. `codex/<model>` runs a bounded Codex app-server image-understanding turn; `openai-codex/<model>` uses the OpenAI Codex OAuth provider path.
- Stateless execution commands default to local.
@@ -136,6 +137,7 @@ This table maps common inference tasks to the corresponding infer command.
- `model run --file` rejects non-image inputs. Use `infer audio transcribe` for audio files and `infer video describe` for video files.
- `model run --gateway` exercises Gateway routing, saved auth, provider selection, and the embedded runtime, but still runs as a raw model probe: it sends the supplied prompt and any image attachments without prior session transcript, bootstrap/AGENTS context, context-engine assembly, tools, or bundled MCP servers.
- `model run --gateway --model <provider/model>` requires a trusted operator gateway credential because the request asks the Gateway to run a one-off provider/model override.
- Local `model run --thinking` uses the lean provider-completion path; provider-specific levels such as `adaptive` and `max` are mapped to the closest portable simple-completion level.
## Model
@@ -145,6 +147,7 @@ Use `model` for provider-backed text inference and model/provider inspection.
openclaw infer model run --prompt "Reply with exactly: smoke-ok" --json
openclaw infer model run --prompt "Summarize this changelog entry" --model openai/gpt-5.4 --json
openclaw infer model run --prompt "Describe this image in one sentence" --file ./photo.jpg --model google/gemini-2.5-flash --json
openclaw infer model run --prompt "Use more reasoning here" --thinking high --json
openclaw infer model providers --json
openclaw infer model inspect --name gpt-5.5 --json
```
@@ -157,6 +160,7 @@ openclaw infer model run --local --model anthropic/claude-sonnet-4-6 --prompt "R
openclaw infer model run --local --model cerebras/zai-glm-4.7 --prompt "Reply with exactly: pong" --json
openclaw infer model run --local --model google/gemini-2.5-flash --prompt "Reply with exactly: pong" --json
openclaw infer model run --local --model groq/llama-3.1-8b-instant --prompt "Reply with exactly: pong" --json
openclaw infer model run --local --model mistral/mistral-medium-3-5 --prompt "Reply with exactly: pong" --json
openclaw infer model run --local --model mistral/mistral-small-latest --prompt "Reply with exactly: pong" --json
openclaw infer model run --local --model openai/gpt-4.1 --prompt "Reply with exactly: pong" --json
openclaw infer model run --local --model ollama/qwen2.5vl:7b --prompt "Describe this image." --file ./photo.jpg --json
@@ -165,6 +169,8 @@ openclaw infer model run --local --model ollama/qwen2.5vl:7b --prompt "Describe
Notes:
- Local `model run` is the narrowest CLI smoke for provider/model/auth health because, for non-Codex providers, it sends only the supplied prompt to the selected model.
- Local `model run --model <provider/model>` can use exact bundled static catalog rows from `models list --all` before that provider is written to config. Provider auth is still required; missing credentials fail as auth errors, not `Unknown model`.
- For Mistral Medium 3.5 reasoning probes, leave temperature unset/default. Mistral rejects `reasoning_effort="high"` plus `temperature: 0`; use `mistral/mistral-medium-3-5` with default temperature or a non-zero reasoning-mode value such as `0.7`.
- `openai-codex/*` local probes are the narrow exception: OpenClaw adds a minimal system instruction so the Codex Responses transport can populate its required `instructions` field, without adding full agent context, tools, memory, or session transcript.
- Local `model run --file` keeps that lean path and attaches image content directly to the single user message. Common image files such as PNG, JPEG, and WebP work when their MIME type is detected as `image/*`; unsupported or unrecognized files fail before the provider is called.
- `model run --file` is best when you want to test the selected multimodal text model directly. Use `infer image describe` when you want OpenClaw's image-understanding provider selection and default image-model routing.

View File

@@ -21,9 +21,11 @@ openclaw migrate list
openclaw migrate claude --dry-run
openclaw migrate codex --dry-run
openclaw migrate codex --skill gog-vault77-google-workspace
openclaw migrate codex --plugin google-calendar --dry-run
openclaw migrate hermes --dry-run
openclaw migrate hermes
openclaw migrate apply codex --yes --skill gog-vault77-google-workspace
openclaw migrate apply codex --yes --plugin google-calendar
openclaw migrate apply codex --yes
openclaw migrate apply claude --yes
openclaw migrate apply hermes --yes
@@ -54,6 +56,9 @@ openclaw onboard --import-from hermes --import-source ~/.hermes
<ParamField path="--skill <name>" type="string">
Select one skill copy item by skill name or item id. Repeat the flag to migrate multiple skills. When omitted, interactive Codex migrations show a checkbox selector and non-interactive migrations keep all planned skills.
</ParamField>
<ParamField path="--plugin <name>" type="string">
Select one Codex plugin install item by plugin name or item id. Repeat the flag to migrate multiple Codex plugins. When omitted, interactive Codex migrations show a native Codex plugin checkbox selector and non-interactive migrations keep all planned plugins. This only applies to source-installed `openai-curated` Codex plugins discovered by the Codex app-server inventory.
</ParamField>
<ParamField path="--no-backup" type="boolean">
Skip the pre-apply backup. Requires `--force` when local OpenClaw state exists.
</ParamField>
@@ -118,31 +123,69 @@ launches use per-agent `CODEX_HOME` and `HOME` directories, so they do not read
your personal Codex CLI state by default.
Running `openclaw migrate codex` in an interactive terminal previews the full
plan, then opens a checkbox selector for skill copy items before the final
apply confirmation. Use `Toggle all on` or `Toggle all off` for bulk selection;
planned skills start checked, conflict skills start unchecked, and `Skip for now`
leaves skills unchanged without applying. For scripted or exact runs, pass
`--skill <name>` once per skill, for example:
plan, then opens checkbox selectors before the final apply confirmation. Skill
copy items are prompted first. Use `Toggle all on` or `Toggle all off` for bulk
selection; planned skills start checked, conflict skills start unchecked, and
`Skip for now` skips skill copies for this run while still continuing to plugin
selection. When source-installed curated Codex plugins are migratable and
`--plugin` was not supplied, migration then prompts for native Codex plugin
activation by plugin name. Plugin items
start checked unless the target OpenClaw Codex plugin config already has that
plugin. Existing target plugins start unchecked and show a conflict hint such as
`conflict: plugin exists`; choose `Toggle all off` to migrate no native Codex
plugins in that run, or `Skip for now` to stop before applying. For scripted or
exact runs, pass `--skill <name>` once per skill, for example:
```bash
openclaw migrate codex --dry-run --skill gog-vault77-google-workspace
openclaw migrate apply codex --yes --skill gog-vault77-google-workspace
```
Use `--plugin <name>` to limit native Codex plugin migration non-interactively
to one or more source-installed curated plugins:
```bash
openclaw migrate codex --dry-run --plugin google-calendar
openclaw migrate apply codex --yes --plugin google-calendar
```
### What Codex imports
- Codex CLI skill directories under `$CODEX_HOME/skills`, excluding Codex's
`.system` cache.
- Personal AgentSkills under `$HOME/.agents/skills`, copied into the current
OpenClaw agent workspace when you want per-agent ownership.
- Source-installed `openai-curated` Codex plugins discovered through Codex
app-server `plugin/list`. Apply calls app-server `plugin/install` for each
selected plugin, even if the target app-server already reports that plugin as
installed and enabled. Migrated Codex plugins are usable only in sessions that
select the native Codex harness; they are not exposed to Pi, normal OpenAI
provider runs, ACP conversation bindings, or other harnesses.
### Manual-review Codex state
Codex native plugins, `config.toml`, and native `hooks/hooks.json` are not
activated automatically. Plugins may expose MCP servers, apps, hooks, or other
executable behavior, so the provider reports them for review instead of loading
them into OpenClaw. Config and hook files are copied into the migration report
for manual review.
Codex `config.toml`, native `hooks/hooks.json`, non-curated marketplaces, and
cached plugin bundles that are not source-installed curated plugins are not
activated automatically. They are copied or reported in the migration report for
manual review.
For migrated source-installed curated plugins, apply writes:
- `plugins.entries.codex.enabled: true`
- `plugins.entries.codex.config.codexPlugins.enabled: true`
- `plugins.entries.codex.config.codexPlugins.allow_destructive_actions: false`
- one explicit plugin entry with `marketplaceName: "openai-curated"` and
`pluginName` for each selected plugin
Migration never writes `plugins["*"]` and never stores local marketplace cache
paths. Auth-required installs are reported on the affected plugin item with
`status: "skipped"`, `reason: "auth_required"`, and sanitized app identifiers.
Their explicit config entries are written disabled until you reauthorize and
enable them. Other install failures are item-scoped `error` results.
If Codex app-server plugin inventory is unavailable during planning, migration
falls back to cached bundle advisory items instead of failing the whole
migration.
## Hermes provider

450
docs/cli/path.md Normal file
View File

@@ -0,0 +1,450 @@
---
summary: "CLI reference for `openclaw path` (inspect and edit workspace files via the `oc://` addressing scheme)"
read_when:
- You want to read or write a leaf inside a workspace file from the terminal
- You're scripting against workspace state and want a stable, kind-agnostic addressing scheme
- You're debugging a `oc://` path (validate the syntax, see what it resolves to)
title: "Path"
---
# `openclaw path`
Plugin-provided shell access to the `oc://` addressing substrate: one
kind-dispatched path scheme for inspecting and editing addressable workspace
files (markdown, jsonc, jsonl). Self-hosters, plugin authors, and editor
extensions use it to read, find, or update a narrow location without
hand-rolling per-file parsers.
The CLI mirrors the substrate's public verbs:
- `resolve` is concrete and single-match.
- `find` is the multi-match verb for wildcards, unions, predicates, and
positional expansion.
- `set` only accepts concrete paths or insertion markers; wildcard patterns are
rejected before writing.
`path` is provided by the bundled optional `oc-path` plugin. Enable it before
first use:
```bash
openclaw plugins enable oc-path
```
## Why use it
OpenClaw state is spread across human-edited markdown, commented JSONC config,
and append-only JSONL logs. Shell scripts, hooks, and agents often need one
small value from those files: a frontmatter key, a plugin setting, a log record
field, or a bullet item under a named section.
`openclaw path` gives those callers a stable address instead of a one-off grep,
regex, or parser for each file kind. The same `oc://` path can be validated,
resolved, searched, dry-run, and written from the terminal, which makes narrow
automation easier to review and safer to replay. It is especially useful when
you want to update one leaf while preserving the rest of the file's comments,
line endings, and surrounding formatting.
Use it when the thing you want has a logical address, but the physical file
shape varies:
- A hook wants to read one setting from commented JSONC without losing comments
when it writes the value back.
- A maintenance script wants to find every matching event field in a JSONL log
without loading the whole log into a custom parser.
- An editor extension wants to jump to a markdown section or bullet item by
slug, then render the exact line it resolved to.
- An agent wants to dry-run a tiny workspace edit before applying it, with the
changed bytes visible in review.
You probably do not need `openclaw path` for ordinary whole-file edits, rich
config migrations, or memory-specific writes. Those should use the owner
command or plugin. `path` is for small, addressable file operations where a
repeatable terminal command is clearer than another bespoke parser.
## How it is used
Read one value from a human-edited config file:
```bash
openclaw path resolve 'oc://config.jsonc/plugins/github/enabled'
```
Preview a write without touching disk:
```bash
openclaw path set 'oc://config.jsonc/plugins/github/enabled' 'true' --dry-run
```
Find matching records in an append-only JSONL log:
```bash
openclaw path find 'oc://session.jsonl/[event=tool_call]/name'
```
Address an instruction in markdown by section and item instead of by line
number:
```bash
openclaw path resolve 'oc://AGENTS.md/runtime-safety/openclaw-gateway'
```
Validate a path in CI or a preflight script before the script reads or writes:
```bash
openclaw path validate 'oc://AGENTS.md/tools/$last/risk'
```
Those commands are meant to be copyable into shell scripts. Use `--json` when a
caller needs structured output and `--human` when a person is inspecting the
result.
## How it works
`openclaw path` does four things:
1. Parses the `oc://` address into slots: file, section, item, field, and
optional session.
2. Chooses the file-kind adapter from the target extension (`.md`, `.jsonc`,
`.jsonl`, and related aliases).
3. Resolves the slots against that file kind's AST: markdown headings/items,
JSONC object keys/array indexes, or JSONL line records.
4. For `set`, emits edited bytes through the same adapter so the untouched
parts of the file keep their comments, line endings, and nearby formatting
where the kind supports it.
`resolve` and `set` require one concrete target. `find` is the exploratory
verb: it expands wildcards, unions, predicates, and ordinals into the concrete
matches you can inspect before choosing one to write.
## Subcommands
| Subcommand | Purpose |
| ----------------------- | ---------------------------------------------------------------------------- |
| `resolve <oc-path>` | Print the concrete match at the path (or "not found"). |
| `find <pattern>` | Enumerate matches for a wildcard / union / predicate path. |
| `set <oc-path> <value>` | Write a leaf or insertion target at a concrete path. Supports `--dry-run`. |
| `validate <oc-path>` | Parse-only; print structural breakdown (file / section / item / field). |
| `emit <file>` | Round-trip a file through `parseXxx` + `emitXxx` (byte-fidelity diagnostic). |
## Global flags
| Flag | Purpose |
| --------------- | ------------------------------------------------------------------------ |
| `--cwd <dir>` | Resolve the file slot against this directory (default: `process.cwd()`). |
| `--file <path>` | Override the file slot's resolved path (absolute access). |
| `--json` | Force JSON output (default when stdout is not a TTY). |
| `--human` | Force human output (default when stdout is a TTY). |
| `--dry-run` | (only on `set`) print the bytes that would be written without writing. |
## `oc://` syntax
```
oc://FILE/SECTION/ITEM/FIELD?session=SCOPE
```
Slot rules: `field` requires `item`, and `item` requires `section`. Across all
four slots:
- **Quoted segments** — `"a/b.c"` survives `/` and `.` separators.
Content is byte-literal; `"` and `\` are not allowed inside quotes.
The file slot is also quote-aware: `oc://"skills/email-drafter"/Tools/$last`
treats `skills/email-drafter` as a single file path.
- **Predicates** — `[k=v]`, `[k!=v]`, `[k<v]`, `[k<=v]`, `[k>v]`,
`[k>=v]`. Numeric ops require both sides to coerce to finite numbers.
- **Unions** — `{a,b,c}` matches any of the alternatives.
- **Wildcards** — `*` (single sub-segment) and `**` (zero-or-more,
recursive). `find` accepts these; `resolve` and `set` reject them as
ambiguous.
- **Positional** — `$last` resolves to the last index / last-declared key.
- **Ordinal** — `#N` for Nth match by document order.
- **Insertion markers** — `+`, `+key`, `+nnn` for keyed / indexed
insertion (use with `set`).
- **Session scope** — `?session=cron-daily` etc. Orthogonal to slot
nesting. Session values are raw, not percent-decoded; they may not contain
control characters or reserved query delimiters (`?`, `&`, `%`).
Reserved characters (`?`, `&`, `%`) outside quoted, predicate, or union
segments are rejected. Control characters (U+0000-U+001F, U+007F) are rejected
anywhere, including the `session` query value.
`formatOcPath(parseOcPath(path)) === path` is guaranteed for canonical paths.
Non-canonical query parameters are ignored except for the first non-empty
`session=` value.
## Addressing by file kind
| Kind | Addressing model |
| ---------- | ----------------------------------------------------------------------------------------- |
| Markdown | H2 sections by slug, bullet items by slug or `#N`, frontmatter via `[frontmatter]`. |
| JSONC/JSON | Object keys and array indexes; dots split nested sub-segments unless quoted. |
| JSONL | Top-level line addresses (`L1`, `L2`, `$last`), then JSONC-style descent inside the line. |
`resolve` returns a structured match: `root`, `node`, `leaf`, or
`insertion-point`, with a 1-based line number. Leaf values are surfaced as text
plus a `leafType` so plugin authors can render previews without depending on
the per-kind AST shape.
## Mutation contract
`set` writes one concrete target:
- Markdown frontmatter values and `- key: value` item fields are string leaves.
Markdown insertions append sections, frontmatter keys, or section items and
render a canonical markdown shape for the changed file.
- JSONC leaf writes coerce the string value to the existing leaf type
(`string`, finite `number`, `true`/`false`, or `null`). JSONC object and array
insertions parse `<value>` as JSON and use the `jsonc-parser` edit path for
ordinary leaf writes, preserving comments and nearby formatting.
- JSONL leaf writes coerce like JSONC inside a line. Whole-line replacement and
append parse `<value>` as JSON. Rendered JSONL preserves the file's dominant
LF/CRLF line-ending convention.
Use `--dry-run` before user-visible writes when the exact bytes matter. The
substrate preserves byte-identical output for parse/emit round-trips, but a
mutation can canonicalize the edited region or file depending on kind.
## Examples
```bash
# Validate a path (no filesystem access)
openclaw path validate 'oc://AGENTS.md/Tools/$last/risk'
# Read a leaf
openclaw path resolve 'oc://gateway.jsonc/version'
# Wildcard search
openclaw path find 'oc://session.jsonl/*/event' --file ./logs/session.jsonl
# Dry-run a write
openclaw path set 'oc://gateway.jsonc/version' '2.0' --dry-run
# Apply the write
openclaw path set 'oc://gateway.jsonc/version' '2.0'
# Byte-fidelity round-trip (diagnostic)
openclaw path emit ./AGENTS.md
```
More grammar examples:
```bash
# Quote keys containing / or .
openclaw path resolve 'oc://config.jsonc/agents.defaults.models/"anthropic/claude-opus-4-7"/alias'
# Predicate search over JSONC children
openclaw path find 'oc://config.jsonc/plugins/[enabled=true]/id'
# Insert into a JSONC array
openclaw path set 'oc://config.jsonc/items/+1' '{"id":"new","enabled":true}' --dry-run
# Insert a JSONC object key
openclaw path set 'oc://config.jsonc/plugins/+github' '{"enabled":true}' --dry-run
# Append a JSONL event
openclaw path set 'oc://session.jsonl/+' '{"event":"checkpoint","ok":true}' --file ./logs/session.jsonl
# Resolve the last JSONL value line
openclaw path resolve 'oc://session.jsonl/$last/event' --file ./logs/session.jsonl
# Address markdown frontmatter
openclaw path resolve 'oc://AGENTS.md/[frontmatter]/name'
# Insert markdown frontmatter
openclaw path set 'oc://AGENTS.md/[frontmatter]/+description' 'Agent instructions' --dry-run
# Find markdown item fields
openclaw path find 'oc://SKILL.md/Tools/*/send_email'
# Validate a session-scoped path
openclaw path validate 'oc://AGENTS.md/Tools/$last/risk?session=cron-daily'
```
## Recipes by file kind
The same five verbs work across kinds; the addressing scheme dispatches on the
file extension. The examples below use the fixtures from the PR description.
### Markdown
```text
<!-- frontmatter.md -->
---
name: drafter
description: email drafting agent
tier: core
---
## Tools
- gh: GitHub CLI
- curl: HTTP client
- send_email: enabled
```
```bash
$ openclaw path resolve 'oc://x.md/[frontmatter]/tier' --file frontmatter.md --human
leaf @ L4: "core" (string)
$ openclaw path resolve 'oc://x.md/tools/gh/gh' --file frontmatter.md --human
leaf @ L9: "GitHub CLI" (string)
$ openclaw path find 'oc://x.md/tools/*' --file frontmatter.md --human
3 matches for oc://x.md/tools/*:
oc://x.md/tools/gh → node @ L9 [md-item]
oc://x.md/tools/curl → node @ L10 [md-item]
oc://x.md/tools/send-email → node @ L11 [md-item]
```
The `[frontmatter]` predicate addresses the YAML frontmatter block; `tools`
matches the `## Tools` heading via slug, and item leaves keep their slug form
even when the source uses underscores (`send_email``send-email`).
### JSONC
```text
// config.jsonc
{
"plugins": {
"github": {"enabled": true, "role": "vcs"},
"slack": {"enabled": false, "role": "chat"}
}
}
```
```bash
$ openclaw path resolve 'oc://config.jsonc/plugins/github/enabled' --file config.jsonc --human
leaf @ L4: "true" (boolean)
$ openclaw path set 'oc://config.jsonc/plugins/slack/enabled' 'true' --file config.jsonc --dry-run
--dry-run: would write 142 bytes to /…/config.jsonc
{
"plugins": {
"github": {"enabled": true, "role": "vcs"},
"slack": {"enabled": true, "role": "chat"}
}
}
```
JSONC edits go through `jsonc-parser`, so comments and whitespace survive a
`set`. Run with `--dry-run` first to inspect the bytes before committing.
### JSONL
```text
{"event":"start","userId":"u1","ts":1}
{"event":"action","userId":"u1","ts":2}
{"event":"end","userId":"u1","ts":3}
```
```bash
$ openclaw path find 'oc://session.jsonl/[event=action]/userId' --file session.jsonl --human
1 match for oc://session.jsonl/[event=action]/userId:
oc://session.jsonl/L2/userId → leaf @ L2: "u1" (string)
$ openclaw path resolve 'oc://session.jsonl/L2/ts' --file session.jsonl --human
leaf @ L2: "2" (number)
```
Each line is a record. Address by predicate (`[event=action]`) when you do not
know the line number, or by the canonical `LN` segment when you do.
## Subcommand reference
### `resolve <oc-path>`
Read a single leaf or node. Wildcards are rejected — use `find` for those.
Exits `0` on a match, `1` on a clean miss, `2` on a parse error or refused
pattern.
```bash
openclaw path resolve 'oc://AGENTS.md/tools/gh/risk' --human
openclaw path resolve 'oc://gateway.jsonc/server/port' --json
```
### `find <pattern>`
Enumerate every match for a wildcard / predicate / union pattern. Exits `0`
on at least one match, `1` on zero. File-slot wildcards are rejected with
`OC_PATH_FILE_WILDCARD_UNSUPPORTED` — pass a concrete file (multi-file
globbing is a follow-up feature).
```bash
openclaw path find 'oc://AGENTS.md/tools/**/risk'
openclaw path find 'oc://session.jsonl/[event=action]/userId'
openclaw path find 'oc://config.jsonc/plugins/{github,slack}/enabled'
```
### `set <oc-path> <value>`
Write a leaf. Pair with `--dry-run` to preview the bytes that would be
written without touching the file. Exits `0` on a successful write, `1` if
the substrate refuses (for example, a sentinel guard hit), `2` on parse
errors.
```bash
openclaw path set 'oc://gateway.jsonc/version' '2.0' --dry-run
openclaw path set 'oc://gateway.jsonc/version' '2.0'
openclaw path set 'oc://AGENTS.md/Tools/+gh/risk' 'low'
```
The `+key` insertion marker creates the named child if it does not already
exist; `+nnn` and bare `+` work for indexed and append insertion respectively.
### `validate <oc-path>`
Parse-only check. No filesystem access. Useful when you want to confirm a
template path is well-formed before substituting variables, or when you want
the structural breakdown for debugging:
```bash
$ openclaw path validate 'oc://AGENTS.md/tools/gh' --human
valid: oc://AGENTS.md/tools/gh
file: AGENTS.md
section: tools
item: gh
```
Exits `0` when valid, `1` when invalid (with a structured `code` and
`message`), `2` on argument errors.
### `emit <file>`
Round-trip a file through the per-kind parser and emitter. The output should
be byte-identical to the input on a sound file — divergence indicates a
parser bug or a sentinel hit. Useful for debugging substrate behavior on
real-world inputs.
```bash
openclaw path emit ./AGENTS.md
openclaw path emit ./gateway.jsonc --json
```
## Exit codes
| Code | Meaning |
| ---- | -------------------------------------------------------------------------- |
| `0` | Success. (`resolve` / `find`: at least one match. `set`: write succeeded.) |
| `1` | No match, or `set` rejected by the substrate (no system-level error). |
| `2` | Argument or parse error. |
## Output mode
`openclaw path` is TTY-aware: human-readable output on a terminal, JSON when
stdout is piped or redirected. `--json` and `--human` override the
auto-detection.
## Notes
- `set` writes bytes through the substrate's emit path, which applies the
redaction-sentinel guard automatically. A leaf carrying
`__OPENCLAW_REDACTED__` (verbatim or as a substring) is refused at write
time.
- JSONC parsing and leaf edits use the plugin-local `jsonc-parser`
dependency, so comments and formatting are preserved on ordinary leaf
writes instead of going through a hand-rolled parser/re-render path.
- `path` does not know about LKG. If the file is LKG-tracked, the next
observe call decides whether to promote / recover. `set --batch` for
atomic multi-set through the LKG promote/recover lifecycle is planned
alongside the LKG-recovery substrate.
## Related
- [CLI reference](/cli)

View File

@@ -90,6 +90,10 @@ openclaw plugins install <plugin> --marketplace <name> # marketplace (explicit)
openclaw plugins install <plugin> --marketplace https://github.com/<owner>/<repo>
```
Maintainers testing setup-time installs can override automatic plugin install
sources with guarded environment variables. See
[Plugin install overrides](/plugins/install-overrides).
<Warning>
Bare package names install from npm by default during the launch cutover. Use `clawhub:<package>` for ClawHub. Treat plugin installs like running code. Prefer pinned versions.
</Warning>
@@ -129,7 +133,7 @@ is available, then fall back to `latest`.
This CLI flag applies to plugin install/update flows. Gateway-backed skill dependency installs use the matching `dangerouslyForceUnsafeInstall` request override, while `openclaw skills install` remains a separate ClawHub skill download/install flow.
If a plugin you published on ClawHub is blocked by a registry scan, use the publisher steps in [ClawHub](/tools/clawhub).
If a plugin you published on ClawHub is blocked by a registry scan, use the publisher steps in [ClawHub](/clawhub/security).
</Accordion>
<Accordion title="Hook packs and npm specs">
@@ -417,4 +421,4 @@ Marketplace list accepts a local marketplace path, a `marketplace.json` path, a
- [Building plugins](/plugins/building-plugins)
- [CLI reference](/cli)
- [Community plugins](/plugins/community)
- [ClawHub](/clawhub)

View File

@@ -33,7 +33,7 @@ It also emits `security.trust_model.multi_user_heuristic` when config suggests l
For intentional shared-user setups, the audit guidance is to sandbox all sessions, keep filesystem access workspace-scoped, and keep personal/private identities or credentials off that runtime.
It also warns when small models (`<=300B`) are used without sandboxing and with web/browser tools enabled.
For webhook ingress, it warns when `hooks.token` reuses the Gateway token, when `hooks.token` is short, when `hooks.path="/"`, when `hooks.defaultSessionKey` is unset, when `hooks.allowedAgentIds` is unrestricted, when request `sessionKey` overrides are enabled, and when overrides are enabled without `hooks.allowedSessionKeyPrefixes`.
It also warns when sandbox Docker settings are configured while sandbox mode is off, when `gateway.nodes.denyCommands` uses ineffective pattern-like/unknown entries (exact node command-name matching only, not shell-text filtering), when `gateway.nodes.allowCommands` explicitly enables dangerous node commands, when global `tools.profile="minimal"` is overridden by agent tool profiles, when open groups expose runtime/filesystem tools without sandbox/workspace guards, and when installed plugin tools may be reachable under permissive tool policy.
It also warns when sandbox Docker settings are configured while sandbox mode is off, when `gateway.nodes.denyCommands` uses ineffective pattern-like/unknown entries (exact node command-name matching only, not shell-text filtering), when `gateway.nodes.allowCommands` explicitly enables dangerous node commands, when global `tools.profile="minimal"` is overridden by agent tool profiles, when write/edit tools are disabled but `exec` is still available without a constraining sandbox filesystem boundary, when open groups expose runtime/filesystem tools without sandbox/workspace guards, and when installed plugin tools may be reachable under permissive tool policy.
It also flags `gateway.allowRealIpFallback=true` (header-spoofing risk if proxies are misconfigured) and `discovery.mdns.mode="full"` (metadata leakage via mDNS TXT records).
It also warns when sandbox browser uses Docker `bridge` network without `sandbox.browser.cdpSourceRange`.
It also flags dangerous sandbox Docker network modes (including `host` and `container:*` namespace joins).

View File

@@ -15,7 +15,7 @@ Related:
- Skills system: [Skills](/tools/skills)
- Skills config: [Skills config](/tools/skills-config)
- ClawHub installs: [ClawHub](/tools/clawhub)
- ClawHub installs: [ClawHub](/clawhub/cli)
## Commands

View File

@@ -332,12 +332,16 @@ flowchart LR
I --> M["Main Reply"]
```
The blocking memory sub-agent can use only the available memory recall tools:
The blocking memory sub-agent can use only the configured memory recall tools.
By default that is:
- `memory_recall`
- `memory_search`
- `memory_get`
When `plugins.slots.memory` is `memory-lancedb`, the default is `memory_recall`
instead. Set `config.toolsAllow` when another memory provider exposes a
different recall tool contract.
If the connection is weak, it should return `NONE`.
## Query modes
@@ -462,6 +466,110 @@ skips recall for that turn.
`config.modelFallbackPolicy` is retained only as a deprecated compatibility
field for older configs. It no longer changes runtime behavior.
## Memory tools
By default Active Memory lets the blocking recall sub-agent call
`memory_search` and `memory_get`. That matches the built-in `memory-core`
contract. When `plugins.slots.memory` selects `memory-lancedb` and
`config.toolsAllow` is unset, Active Memory keeps the existing LanceDB behavior
and uses `memory_recall` instead.
If you use another memory plugin, set `config.toolsAllow` to the exact tool
names that plugin registers. Active Memory lists those tools in the recall
prompt and passes the same list to the embedded sub-agent. If none of the
configured tools are available, or the memory sub-agent fails, Active Memory
skips recall for that turn and the main reply continues without memory context.
`toolsAllow` only accepts concrete memory tool names. Wildcards, `group:*`
entries, and core agent tools such as `read`, `exec`, `message`, and
`web_search` are ignored before the hidden memory sub-agent starts.
Default-behavior note: Active Memory no longer includes `memory_recall` in the
memory-core default allowlist. Existing `memory-lancedb` setups keep working
when `plugins.slots.memory` is set to `memory-lancedb`. Explicit `toolsAllow`
always overrides the automatic default.
### Built-in memory-core
The default setup does not need an explicit `toolsAllow`:
```json5
{
plugins: {
entries: {
"active-memory": {
enabled: true,
config: {
agents: ["main"],
// Default: ["memory_search", "memory_get"]
},
},
},
},
}
```
### LanceDB memory
The bundled `memory-lancedb` plugin exposes `memory_recall`. Selecting the
memory slot is enough for Active Memory to use that recall tool:
```json5
{
plugins: {
slots: {
memory: "memory-lancedb",
},
entries: {
"memory-lancedb": {
enabled: true,
config: {
embedding: {
provider: "openai",
model: "text-embedding-3-small",
},
},
},
"active-memory": {
enabled: true,
config: {
agents: ["main"],
promptAppend: "Use memory_recall for long-term user preferences, past decisions, and previously discussed topics. If recall finds nothing useful, return NONE.",
},
},
},
},
}
```
### Lossless Claw
Lossless Claw is a context-engine plugin with its own recall tools. Install and
configure it as a context engine first; see [Context engine](/concepts/context-engine).
Then let Active Memory use the Lossless Claw recall tools:
```json5
{
plugins: {
entries: {
"lossless-claw": {
enabled: true,
},
"active-memory": {
enabled: true,
config: {
agents: ["main"],
toolsAllow: ["lcm_grep", "lcm_describe", "lcm_expand_query"],
promptAppend: "Use lcm_grep first for compacted conversation recall. Use lcm_describe to inspect a specific summary. Use lcm_expand_query only when the latest user message needs exact details that may have been compacted away. Return NONE if the retrieved context is not clearly useful.",
},
},
},
},
}
```
Do not include `lcm_expand` in `toolsAllow` for the main Active Memory sub-agent.
Lossless Claw uses that as a lower-level delegated expansion tool.
## Advanced escape hatches
These options are intentionally not part of the recommended setup.
@@ -488,6 +596,9 @@ Memory prompt and before the conversation context:
promptAppend: "Prefer stable long-term preferences over one-off events."
```
Use `promptAppend` with custom `toolsAllow` when a non-core memory plugin needs
provider-specific tool order or query-shaping instructions.
`config.promptOverride` replaces the default Active Memory prompt. OpenClaw
still appends the conversation context afterward:
@@ -558,25 +669,26 @@ plugins.entries.active-memory
The most important fields are:
| Key | Type | Meaning |
| ---------------------------- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enabled` | `boolean` | Enables the plugin itself |
| `config.agents` | `string[]` | Agent ids that may use active memory |
| `config.model` | `string` | Optional blocking memory sub-agent model ref; when unset, active memory uses the current session model |
| `config.allowedChatTypes` | `("direct" \| "group" \| "channel")[]` | Session types that may run Active Memory; defaults to direct-message style sessions |
| `config.allowedChatIds` | `string[]` | Optional per-conversation allowlist applied after `allowedChatTypes`; non-empty lists fail closed |
| `config.deniedChatIds` | `string[]` | Optional per-conversation denylist that overrides allowed session types and allowed ids |
| `config.queryMode` | `"message" \| "recent" \| "full"` | Controls how much conversation the blocking memory sub-agent sees |
| `config.promptStyle` | `"balanced" \| "strict" \| "contextual" \| "recall-heavy" \| "precision-heavy" \| "preference-only"` | Controls how eager or strict the blocking memory sub-agent is when deciding whether to return memory |
| `config.thinking` | `"off" \| "minimal" \| "low" \| "medium" \| "high" \| "xhigh" \| "adaptive" \| "max"` | Advanced thinking override for the blocking memory sub-agent; default `off` for speed |
| `config.promptOverride` | `string` | Advanced full prompt replacement; not recommended for normal use |
| `config.promptAppend` | `string` | Advanced extra instructions appended to the default or overridden prompt |
| `config.timeoutMs` | `number` | Hard timeout for the blocking memory sub-agent, capped at 120000 ms |
| `config.setupGraceTimeoutMs` | `number` | Advanced extra setup budget before the recall timeout expires; defaults to 0 and is capped at 30000 ms. See [Cold-start grace](#cold-start-grace) for v2026.4.x upgrade guidance |
| `config.maxSummaryChars` | `number` | Maximum total characters allowed in the active-memory summary |
| `config.logging` | `boolean` | Emits active memory logs while tuning |
| `config.persistTranscripts` | `boolean` | Keeps blocking memory sub-agent transcripts on disk instead of deleting temp files |
| `config.transcriptDir` | `string` | Relative blocking memory sub-agent transcript directory under the agent sessions folder |
| Key | Type | Meaning |
| ---------------------------- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enabled` | `boolean` | Enables the plugin itself |
| `config.agents` | `string[]` | Agent ids that may use active memory |
| `config.model` | `string` | Optional blocking memory sub-agent model ref; when unset, active memory uses the current session model |
| `config.allowedChatTypes` | `("direct" \| "group" \| "channel")[]` | Session types that may run Active Memory; defaults to direct-message style sessions |
| `config.allowedChatIds` | `string[]` | Optional per-conversation allowlist applied after `allowedChatTypes`; non-empty lists fail closed |
| `config.deniedChatIds` | `string[]` | Optional per-conversation denylist that overrides allowed session types and allowed ids |
| `config.queryMode` | `"message" \| "recent" \| "full"` | Controls how much conversation the blocking memory sub-agent sees |
| `config.promptStyle` | `"balanced" \| "strict" \| "contextual" \| "recall-heavy" \| "precision-heavy" \| "preference-only"` | Controls how eager or strict the blocking memory sub-agent is when deciding whether to return memory |
| `config.toolsAllow` | `string[]` | Concrete memory tool names the blocking memory sub-agent may call; defaults to `["memory_search", "memory_get"]`, or `["memory_recall"]` when `plugins.slots.memory` is `memory-lancedb`; wildcards, `group:*` entries, and core agent tools are ignored |
| `config.thinking` | `"off" \| "minimal" \| "low" \| "medium" \| "high" \| "xhigh" \| "adaptive" \| "max"` | Advanced thinking override for the blocking memory sub-agent; default `off` for speed |
| `config.promptOverride` | `string` | Advanced full prompt replacement; not recommended for normal use |
| `config.promptAppend` | `string` | Advanced extra instructions appended to the default or overridden prompt |
| `config.timeoutMs` | `number` | Hard timeout for the blocking memory sub-agent, capped at 120000 ms |
| `config.setupGraceTimeoutMs` | `number` | Advanced extra setup budget before the recall timeout expires; defaults to 0 and is capped at 30000 ms. See [Cold-start grace](#cold-start-grace) for v2026.4.x upgrade guidance |
| `config.maxSummaryChars` | `number` | Maximum total characters allowed in the active-memory summary |
| `config.logging` | `boolean` | Emits active memory logs while tuning |
| `config.persistTranscripts` | `boolean` | Keeps blocking memory sub-agent transcripts on disk instead of deleting temp files |
| `config.transcriptDir` | `string` | Relative blocking memory sub-agent transcript directory under the agent sessions folder |
Useful tuning fields:
@@ -692,8 +804,9 @@ If active memory is too slow:
Active Memory rides on the configured memory plugin's recall pipeline, so most
recall surprises are embedding-provider problems, not Active Memory bugs. The
default `memory-core` path uses `memory_search`; `memory-lancedb` uses
`memory_recall`.
default `memory-core` path uses `memory_search` and `memory_get`; the
`memory-lancedb` slot uses `memory_recall`. If you use another memory plugin,
confirm `config.toolsAllow` names the tools that plugin actually registers.
<AccordionGroup>
<Accordion title="Embedding provider switched or stopped working">

View File

@@ -23,8 +23,11 @@ configuration. They are different layers:
You will also see the word **harness** in code. A harness is the implementation
that provides an agent runtime. For example, the bundled Codex harness
implements the `codex` runtime. Public config uses `agentRuntime.id`; `openclaw
doctor --fix` rewrites older runtime-policy keys to that shape.
implements the `codex` runtime. Public config uses `agentRuntime.id` on
provider or model entries; whole-agent runtime keys are legacy and ignored.
`openclaw doctor --fix` removes old whole-agent runtime pins and rewrites
legacy runtime model refs to canonical provider/model refs plus model-scoped
runtime policy where needed.
There are two runtime families:
@@ -33,9 +36,9 @@ There are two runtime families:
`codex`.
- **CLI backends** run a local CLI process while keeping the model ref
canonical. For example, `anthropic/claude-opus-4-7` with
`agentRuntime.id: "claude-cli"` means "select the Anthropic model, execute
through Claude CLI." `claude-cli` is not an embedded harness id and must not
be passed to AgentHarness selection.
a model-scoped `agentRuntime.id: "claude-cli"` means "select the Anthropic
model, execute through Claude CLI." `claude-cli` is not an embedded harness id
and must not be passed to AgentHarness selection.
## Codex surfaces
@@ -87,9 +90,9 @@ This is the agent-facing decision tree:
2. If the user asks for **Codex as the embedded runtime** or wants the normal
subscription-backed Codex agent experience, use `openai/<model>`.
3. If the user explicitly chooses **PI for an OpenAI model**, keep the model ref
as `openai/<model>` and set `agentRuntime.id: "pi"`. A selected
`openai-codex` auth profile is routed internally through PI's legacy
Codex-auth transport.
as `openai/<model>` and set provider/model runtime policy to
`agentRuntime.id: "pi"`. A selected `openai-codex` auth profile is routed
internally through PI's legacy Codex-auth transport.
4. If legacy config still contains **`openai-codex/*` model refs**, repair it to
`openai/<model>` with `openclaw doctor --fix`.
5. If the user explicitly says **ACP**, **acpx**, or **Codex ACP adapter**, use
@@ -132,21 +135,26 @@ This ownership split is the main design rule:
OpenClaw chooses an embedded runtime after provider and model resolution:
1. A session's recorded runtime wins. Config changes do not hot-switch an
existing transcript to a different native thread system.
2. `OPENCLAW_AGENT_RUNTIME=<id>` forces that runtime for new or reset sessions.
3. `agents.defaults.agentRuntime.id` or `agents.list[].agentRuntime.id` can set
`auto`, `pi`, a registered embedded harness id such as `codex`, or a
supported CLI backend alias such as `claude-cli`.
4. In `auto` mode, registered plugin runtimes can claim supported provider/model
1. Model-scoped runtime policy wins. This can live in a configured provider
model entry or in `agents.defaults.models["provider/model"].agentRuntime` /
`agents.list[].models["provider/model"].agentRuntime`.
2. Provider-scoped runtime policy comes next at
`models.providers.<provider>.agentRuntime`.
3. In `auto` mode, registered plugin runtimes can claim supported provider/model
pairs.
5. If no runtime claims a turn in `auto` mode, OpenClaw uses PI as the
4. If no runtime claims a turn in `auto` mode, OpenClaw uses PI as the
compatibility runtime. Use an explicit runtime id when the run must be
strict.
Explicit plugin runtimes fail closed. For example, `agentRuntime.id: "codex"`
means Codex or a clear selection/runtime error; it is never silently routed back
to PI.
Whole-session and whole-agent runtime pins are ignored. That includes
`OPENCLAW_AGENT_RUNTIME`, session `agentHarnessId`/`agentRuntimeOverride` state,
`agents.defaults.agentRuntime`, and `agents.list[].agentRuntime`. Run
`openclaw doctor --fix` to remove stale whole-agent runtime config and convert
legacy runtime model refs where OpenClaw can preserve the intent.
Explicit provider/model plugin runtimes fail closed. For example,
`agentRuntime.id: "codex"` on a provider or model means Codex or a clear
selection/runtime error; it is never silently routed back to PI.
CLI backend aliases are different from embedded harness ids. The preferred
Claude CLI form is:
@@ -156,7 +164,11 @@ Claude CLI form is:
agents: {
defaults: {
model: "anthropic/claude-opus-4-7",
agentRuntime: { id: "claude-cli" },
models: {
"anthropic/claude-opus-4-7": {
agentRuntime: { id: "claude-cli" },
},
},
},
},
}
@@ -164,15 +176,15 @@ Claude CLI form is:
Legacy refs such as `claude-cli/claude-opus-4-7` remain supported for
compatibility, but new config should keep the provider/model canonical and put
the execution backend in `agentRuntime.id`.
the execution backend in provider/model runtime policy.
`auto` mode is intentionally conservative for most providers. OpenAI agent
models are the exception: unset runtime and `auto` both resolve to the Codex
harness. Explicit PI runtime config remains an opt-in compatibility route for
`openai/*` agent turns; when paired with a selected `openai-codex` auth profile,
OpenClaw routes PI internally through the legacy Codex-auth transport while
keeping the public model ref as `openai/*`. Stale OpenAI PI session pins without
explicit config are repaired back to Codex.
keeping the public model ref as `openai/*`. Stale OpenAI PI session pins are
ignored by runtime selection and can be cleaned with `openclaw doctor --fix`.
If `openclaw doctor` warns that the `codex` plugin is enabled while
`openai-codex/*` remains in config, treat that as legacy route state. Run
@@ -206,10 +218,8 @@ diagnostics, not as provider names.
- A runtime id such as `codex` tells you which loop is executing the turn.
- A channel label such as Telegram or Discord tells you where the conversation is happening.
If a session still shows PI after changing runtime config, start a new session
with `/new` or clear the current one with `/reset`. Existing sessions keep their
recorded runtime so a transcript is not replayed through two incompatible native
session systems.
If a run still shows an unexpected runtime, inspect the selected provider/model
runtime policy first. Legacy session runtime pins no longer decide routing.
## Related

View File

@@ -29,19 +29,19 @@ Reference for **LLM/model providers** (not chat channels like WhatsApp/Telegram)
<Accordion title="OpenAI provider/runtime split">
OpenAI-family routes are prefix-specific:
- `openai/<model>` plus `agents.defaults.agentRuntime.id: "codex"` uses the native Codex app-server harness. This is the usual ChatGPT/Codex subscription setup.
- `openai-codex/<model>` uses Codex OAuth in PI.
- `openai/<model>` without a Codex runtime override uses the direct OpenAI API-key provider in PI.
- `openai/<model>` uses the native Codex app-server harness for agent turns by default. This is the usual ChatGPT/Codex subscription setup.
- `openai-codex/<model>` is legacy config that doctor rewrites to `openai/<model>`.
- `openai/<model>` plus provider/model `agentRuntime.id: "pi"` uses PI for explicit API-key or compatibility routes.
See [OpenAI](/providers/openai) and [Codex harness](/plugins/codex-harness). If the provider/runtime split is confusing, read [Agent runtimes](/concepts/agent-runtimes) first.
Plugin auto-enable follows the same boundary: `openai-codex/<model>` belongs to the OpenAI plugin, while the Codex plugin is enabled by `agentRuntime.id: "codex"` or legacy `codex/<model>` refs.
Plugin auto-enable follows the same boundary: `openai/*` agent refs enable the Codex plugin for the default route, and explicit provider/model `agentRuntime.id: "codex"` or legacy `codex/<model>` refs also require it.
GPT-5.5 is available through the native Codex app-server harness when `agentRuntime.id: "codex"` is set, through `openai-codex/gpt-5.5` in PI for Codex OAuth, and through `openai/gpt-5.5` in PI for direct API-key traffic when your account exposes it.
GPT-5.5 is available through the native Codex app-server harness by default on `openai/gpt-5.5`, and through PI only when provider/model runtime policy explicitly selects `pi`.
</Accordion>
<Accordion title="CLI runtimes">
CLI runtimes use the same split: choose canonical model refs such as `anthropic/claude-*`, `google/gemini-*`, or `openai/gpt-*`, then set `agents.defaults.agentRuntime.id` to `claude-cli`, `google-gemini-cli`, or `codex-cli` when you want a local CLI backend.
CLI runtimes use the same split: choose canonical model refs such as `anthropic/claude-*`, `google/gemini-*`, or `openai/gpt-*`, then set provider/model runtime policy to `claude-cli`, `google-gemini-cli`, or `codex-cli` when you want a local CLI backend.
Legacy `claude-cli/*`, `google-gemini-cli/*`, and `codex-cli/*` refs migrate back to canonical provider refs with the runtime recorded separately.
@@ -92,9 +92,8 @@ OpenClaw ships with the pi-ai catalog. These providers require **no** `models.pr
- Example models: `openai/gpt-5.5`, `openai/gpt-5.4-mini`
- Verify account/model availability with `openclaw models list --provider openai` if a specific install or API key behaves differently.
- CLI: `openclaw onboard --auth-choice openai-api-key`
- Default transport is `auto` (WebSocket-first, SSE fallback)
- Default transport is `auto`; OpenClaw passes the transport choice to pi-ai.
- Override per model via `agents.defaults.models["openai/<model>"].params.transport` (`"sse"`, `"websocket"`, or `"auto"`)
- OpenAI Responses WebSocket warm-up defaults to enabled via `params.openaiWsWarmup` (`true`/`false`)
- OpenAI priority processing can be enabled via `agents.defaults.models["openai/<model>"].params.serviceTier`
- `/fast` and `params.fastMode` map direct `openai/*` Responses requests to `service_tier=priority` on `api.openai.com`
- Use `params.serviceTier` when you want an explicit tier instead of the shared `/fast` toggle
@@ -118,7 +117,7 @@ OpenClaw ships with the pi-ai catalog. These providers require **no** `models.pr
- Direct public Anthropic requests support the shared `/fast` toggle and `params.fastMode`, including API-key and OAuth-authenticated traffic sent to `api.anthropic.com`; OpenClaw maps that to Anthropic `service_tier` (`auto` vs `standard_only`)
- Preferred Claude CLI config keeps the model ref canonical and selects the CLI
backend separately: `anthropic/claude-opus-4-7` with
`agents.defaults.agentRuntime.id: "claude-cli"`. Legacy
model-scoped `agentRuntime.id: "claude-cli"`. Legacy
`claude-cli/claude-opus-4-7` refs still work for compatibility.
<Note>
@@ -135,8 +134,8 @@ Anthropic staff told us OpenClaw-style Claude CLI usage is allowed again, so Ope
- Provider: `openai-codex`
- Auth: OAuth (ChatGPT)
- PI model ref: `openai-codex/gpt-5.5`
- Native Codex app-server harness ref: `openai/gpt-5.5` with `agents.defaults.agentRuntime.id: "codex"`
- Legacy PI model ref: `openai-codex/gpt-5.5`
- Native Codex app-server harness ref: `openai/gpt-5.5`
- Native Codex app-server harness docs: [Codex harness](/plugins/codex-harness)
- Legacy model refs: `codex/gpt-*`
- Plugin boundary: `openai-codex/*` loads the OpenAI plugin; the native Codex app-server plugin is selected only by the Codex harness runtime or legacy `codex/*` refs.
@@ -148,8 +147,8 @@ Anthropic staff told us OpenClaw-style Claude CLI usage is allowed again, so Ope
- Shares the same `/fast` toggle and `params.fastMode` config as direct `openai/*`; OpenClaw maps that to `service_tier=priority`
- `openai-codex/gpt-5.5` uses the Codex catalog native `contextWindow = 400000` and default runtime `contextTokens = 272000`; override the runtime cap with `models.providers.openai-codex.models[].contextTokens`
- Policy note: OpenAI Codex OAuth is explicitly supported for external tools/workflows like OpenClaw.
- For the common subscription plus native Codex runtime route, sign in with `openai-codex` auth but configure `openai/gpt-5.5` plus `agents.defaults.agentRuntime.id: "codex"`.
- Use `openai-codex/gpt-5.5` only when you want the Codex OAuth/subscription route through PI; use `openai/gpt-5.5` without the Codex runtime override when your API-key setup and local catalog expose the public API route.
- For the common subscription plus native Codex runtime route, sign in with `openai-codex` auth but configure `openai/gpt-5.5`; OpenAI agent turns select Codex by default.
- Use provider/model `agentRuntime.id: "pi"` only when you want a compatibility route through PI; otherwise keep `openai/gpt-5.5` on the default Codex harness.
- Older `openai-codex/gpt-5.1*`, `openai-codex/gpt-5.2*`, and `openai-codex/gpt-5.3*` refs are suppressed because ChatGPT/Codex OAuth accounts reject them; use `openai-codex/gpt-5.5` or the native Codex runtime route instead.
```json5
@@ -158,7 +157,6 @@ Anthropic staff told us OpenClaw-style Claude CLI usage is allowed again, so Ope
agents: {
defaults: {
model: { primary: "openai/gpt-5.5" },
agentRuntime: { id: "codex" },
},
},
}

View File

@@ -23,7 +23,7 @@ sidebarTitle: "Models CLI"
</Card>
</CardGroup>
Model refs choose a provider and model. They do not usually choose the low-level agent runtime. For example, `openai/gpt-5.5` can run through the normal OpenAI provider path or through the Codex app-server runtime, depending on `agents.defaults.agentRuntime.id`. In Codex runtime mode, the `openai/gpt-*` ref does not imply API-key billing; auth can come from a Codex account or `openai-codex` auth profile. See [Agent runtimes](/concepts/agent-runtimes).
Model refs choose a provider and model. They do not usually choose the low-level agent runtime. OpenAI agent refs are the main exception: `openai/gpt-5.5` runs through the Codex app-server runtime by default on the official OpenAI provider. Explicit runtime overrides belong on provider/model policy, not on the whole agent or session. In Codex runtime mode, the `openai/gpt-*` ref does not imply API-key billing; auth can come from a Codex account or `openai-codex` auth profile. See [Agent runtimes](/concepts/agent-runtimes).
## How model selection works

View File

@@ -37,6 +37,7 @@ resources.
| `Run.cancel()` | Ready | Calls `sessions.abort` by run id, with session key when available. |
| `oc.sessions` | Ready | Creates, resolves, sends to, patches, compacts, and gets session handles. |
| `Session.send()` | Ready | Calls `sessions.send` and returns a `Run`. |
| `oc.tasks` | Ready | Lists, reads, and cancels Gateway task ledger entries. |
| `oc.models` | Ready | Calls `models.list` and the current `models.authStatus` status RPC. |
| `oc.tools` | Ready | Lists, scopes, and invokes Gateway tools through the policy pipeline. |
| `oc.artifacts` | Ready | Lists, gets, and downloads Gateway transcript artifacts. |
@@ -50,7 +51,9 @@ The SDK also exports the core types used by those surfaces:
`OpenClawEventType`, `GatewayEvent`, `OpenClawTransport`,
`GatewayRequestOptions`, `SessionCreateParams`, `SessionSendParams`,
`ArtifactSummary`, `ArtifactQuery`, `ArtifactsListResult`,
`ArtifactsGetResult`, `ArtifactsDownloadResult`, `RuntimeSelection`,
`ArtifactsGetResult`, `ArtifactsDownloadResult`,
`TaskSummary`, `TaskStatus`, `TasksListParams`, `TasksListResult`,
`TasksGetResult`, `TasksCancelResult`, `RuntimeSelection`,
`EnvironmentSelection`, `WorkspaceSelection`, `ApprovalMode`, and related
result types.
@@ -254,6 +257,14 @@ const approvals = await oc.approvals.list();
await oc.approvals.respond("approval-id", { decision: "approve" });
```
Task helpers use the durable task ledger that also backs `openclaw tasks`:
```typescript
const tasks = await oc.tasks.list({ status: "running", sessionKey: "agent:main:main" });
const task = await oc.tasks.get(tasks.tasks[0].id);
await oc.tasks.cancel(task.task.id, { reason: "user stopped task" });
```
Environment helpers expose read-only Gateway-local and node discovery:
```typescript
@@ -268,10 +279,6 @@ pretend Gateway RPCs exist. These calls currently throw explicit unsupported
errors:
```typescript
await oc.tasks.list();
await oc.tasks.get("task-id");
await oc.tasks.cancel("task-id");
await oc.environments.create({});
await oc.environments.delete("environment-id");
```

View File

@@ -18,9 +18,9 @@ into the final answer when the channel can do that safely.
```text
Shelling...
📖 Read: from docs/concepts/progress-drafts.md
📖 from docs/concepts/progress-drafts.md
🔎 Web Search: for "discord edit message"
🛠️ Exec: run tests
🛠️ Bash: run tests
```
Use progress drafts when you want one tidy status message during tool-heavy work
@@ -51,15 +51,17 @@ progress chatter for that turn.
A progress draft has two parts:
| Part | Purpose |
| -------------- | --------------------------------------------------------------------------- |
| Label | A short title such as `Thinking...` or `Shelling...`. |
| Progress lines | Compact run updates using the same tool labels and icons as verbose output. |
| Part | Purpose |
| -------------- | ------------------------------------------------------------------------------------- |
| Label | A short starter/status line such as `Thinking...` or `Shelling...`. |
| Progress lines | Compact run updates using the same tool icons and detail formatter as verbose output. |
The label appears after the agent starts meaningful work and either remains busy
for five seconds or emits a second work event. Plain text-only replies do not
show a progress draft. Progress lines are added only when the agent emits useful
work updates, for example `🛠️ Exec`, `🔎 Web Search`, or `✍️ Write: to /tmp/file`.
for five seconds or emits a second work event. It is part of the rolling progress
line list, so the starter status scrolls away once enough concrete work appears.
Plain text-only replies do not show a progress draft. Progress lines are added
only when the agent emits useful work updates, for example `🛠️ Bash: run tests`,
`🔎 Web Search: for "discord edit message"`, or `✍️ Write: to /tmp/file`.
By default they use the same compact explain mode as `/verbose`; set
`agents.defaults.toolProgressDetail: "raw"` when debugging and you also want raw
commands/details appended.
@@ -189,16 +191,16 @@ OpenClaw uses the same formatter for progress drafts and `/verbose`:
```
`"explain"` is the default and keeps drafts stable with concise labels like
`🛠️ Exec: check JS syntax for /tmp/app.js`. `"raw"` appends the underlying
`🛠️ check JS syntax for /tmp/app.js`. `"raw"` appends the underlying
command/detail when available, which is useful while debugging but noisier in
chat.
For example, the same command appears differently depending on the detail mode:
| Mode | Progress line |
| --------- | -------------------------------------------------------------------- |
| `explain` | `🛠️ Exec: check JS syntax for /tmp/app.js` |
| `raw` | `🛠️ Exec: check JS syntax for /tmp/app.js, node --check /tmp/app.js` |
| Mode | Progress line |
| --------- | -------------------------------------------------------------- |
| `explain` | `🛠️ check JS syntax for /tmp/app.js` |
| `raw` | `🛠️ check JS syntax for /tmp/app.js, node --check /tmp/app.js` |
Limit how many lines stay visible:

View File

@@ -278,7 +278,7 @@ Optional:
- `OPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT=1` keeps message bodies in observed-message artifacts (default redacts).
Scenarios (`extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.ts:44`):
Scenarios (`extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.ts`):
- `telegram-canary`
- `telegram-mention-gating`
@@ -287,10 +287,18 @@ Scenarios (`extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime
- `telegram-commands-command`
- `telegram-tools-compact-command`
- `telegram-whoami-command`
- `telegram-status-command`
- `telegram-repeated-command-authorization`
- `telegram-other-bot-command-gating`
- `telegram-context-command`
- `telegram-current-session-status-tool`
- `telegram-reply-chain-exact-marker`
- `telegram-stream-final-single-message`
- `telegram-long-final-reuses-preview`
- `telegram-long-final-three-chunks`
The implicit default set always covers canary, mention gating, native command replies, command addressing, and bot-to-bot group replies. `mock-openai` defaults also include deterministic reply-chain and final-message streaming checks. `telegram-current-session-status-tool` remains opt-in because it is only stable when threaded directly after canary, not after arbitrary native command replies. Use `pnpm openclaw qa telegram --list-scenarios --provider-mode mock-openai` to print the current default/optional split with regression refs.
Output artifacts:
- `telegram-qa-report.md`
@@ -559,15 +567,17 @@ A green run completes in well under 30 seconds and `slack-qa-report.md` shows bo
### Convex credential pool
Telegram, Discord, and Slack lanes can lease credentials from a shared Convex pool instead of reading the env vars above. Pass `--credential-source convex` (or set `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`); QA Lab acquires an exclusive lease, heartbeats it for the duration of the run, and releases it on shutdown. Pool kinds are `"telegram"`, `"discord"`, and `"slack"`.
Telegram, Discord, Slack, and WhatsApp lanes can lease credentials from a shared Convex pool instead of reading the env vars above. Pass `--credential-source convex` (or set `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`); QA Lab acquires an exclusive lease, heartbeats it for the duration of the run, and releases it on shutdown. Pool kinds are `"telegram"`, `"discord"`, `"slack"`, and `"whatsapp"`.
Payload shapes the broker validates on `admin/add`:
- Telegram (`kind: "telegram"`): `{ groupId: string, driverToken: string, sutToken: string }` - `groupId` must be a numeric chat-id string.
- Discord (`kind: "discord"`): `{ guildId: string, channelId: string, driverBotToken: string, sutBotToken: string, sutApplicationId: string }`.
- Slack (`kind: "slack"`): `{ channelId: string, driverBotToken: string, sutBotToken: string, sutAppToken: string }` - `channelId` must match `^[A-Z][A-Z0-9]+$` (a Slack id like `Cxxxxxxxxxx`). See [Setting up the Slack workspace](#setting-up-the-slack-workspace) for app and scope provisioning.
- WhatsApp (`kind: "whatsapp"`): `{ driverPhoneE164: string, sutPhoneE164: string, driverAuthArchiveBase64: string, sutAuthArchiveBase64: string, groupJid?: string }` - phone numbers must be distinct E.164 strings.
Operational env vars and the Convex broker endpoint contract live in [Testing → Shared Telegram credentials via Convex](/help/testing#shared-telegram-credentials-via-convex-v1) (the section name predates Discord support; the broker semantics are identical for both kinds).
Slack lanes can also use the pool. Slack payload shape checks currently live in the Slack QA runner rather than the broker; use `{ channelId: string, driverBotToken: string, sutBotToken: string, sutAppToken: string }`, with a Slack channel id like `Cxxxxxxxxxx`. See [Setting up the Slack workspace](#setting-up-the-slack-workspace) for app and scope provisioning.
Operational env vars and the Convex broker endpoint contract live in [Testing → Shared Telegram credentials via Convex](/help/testing#shared-telegram-credentials-via-convex-v1) (the section name predates the multi-channel pool; the lease semantics are shared across kinds).
## Repo-backed seeds

View File

@@ -54,7 +54,7 @@
"redirects": [
{
"source": "/channels/bluebubbles",
"destination": "/channels/imessage"
"destination": "/channels/imessage-from-bluebubbles"
},
{
"source": "/install/migrating-matrix",
@@ -393,16 +393,16 @@
"destination": "/channels/pairing"
},
{
"source": "/clawhub",
"destination": "/tools/clawhub"
"source": "/clawdhub",
"destination": "/clawhub"
},
{
"source": "/clawdhub",
"destination": "/tools/clawhub"
"source": "/tools/clawhub",
"destination": "/clawhub"
},
{
"source": "/tools/clawdhub",
"destination": "/tools/clawhub"
"destination": "/clawhub"
},
{
"source": "/configuration",
@@ -1063,8 +1063,10 @@
"channels/msteams",
"channels/googlechat",
"channels/imessage",
"channels/imessage-from-bluebubbles",
"channels/matrix",
"channels/matrix-migration",
"channels/matrix-presentation",
"channels/matrix-push-rules"
]
},
@@ -1193,6 +1195,7 @@
"plugins/reference",
"plugins/bundles",
"plugins/dependency-resolution",
"plugins/install-overrides",
"plugins/codex-harness",
"plugins/codex-computer-use",
"plugins/google-meet",
@@ -1201,6 +1204,7 @@
"plugins/memory-wiki",
"plugins/memory-lancedb",
"plugins/message-presentation",
"plugins/oc-path",
"plugins/skill-workshop",
"plugins/zalouser",
{
@@ -1242,7 +1246,6 @@
"tools/creating-skills",
"tools/skills-config",
"tools/slash-commands",
"tools/clawhub",
"prose"
]
},
@@ -1325,6 +1328,36 @@
}
]
},
{
"tab": "ClawHub",
"groups": [
{
"group": "Overview",
"pages": ["clawhub/index", "clawhub/quickstart", "clawhub/how-it-works"]
},
{
"group": "Using ClawHub",
"pages": [
"clawhub/cli",
"clawhub/publishing",
"clawhub/skill-format",
"clawhub/soul-format",
"clawhub/auth",
"clawhub/telemetry",
"clawhub/troubleshooting"
]
},
{
"group": "API and trust",
"pages": [
"clawhub/api",
"clawhub/http-api",
"clawhub/security",
"clawhub/acceptable-usage"
]
}
]
},
{
"tab": "Models",
"groups": [
@@ -1644,7 +1677,7 @@
},
{
"group": "Plugins and skills",
"pages": ["cli/plugins", "cli/skills"]
"pages": ["cli/plugins", "cli/path", "cli/skills"]
},
{
"group": "Interfaces",

View File

@@ -336,9 +336,6 @@ Time format in system prompt. Default: `auto` (OS preference).
fallbacks: ["openai/gpt-5.4-mini"],
},
params: { cacheRetention: "long" }, // global default provider params
agentRuntime: {
id: "pi", // pi | auto | registered harness id, e.g. codex
},
pdfMaxBytesMb: 10,
pdfMaxPages: 20,
thinkingDefault: "low",
@@ -396,27 +393,31 @@ Time format in system prompt. Default: `auto` (OS preference).
- `params` merge precedence (config): `agents.defaults.params` (global base) is overridden by `agents.defaults.models["provider/model"].params` (per-model), then `agents.list[].params` (matching agent id) overrides by key. See [Prompt Caching](/reference/prompt-caching) for details.
- `params.extra_body`/`params.extraBody`: advanced pass-through JSON merged into `api: "openai-completions"` request bodies for OpenAI-compatible proxies. If it collides with generated request keys, the extra body wins; non-native completions routes still strip OpenAI-only `store` afterward.
- `params.chat_template_kwargs`: vLLM/OpenAI-compatible chat-template arguments merged into top-level `api: "openai-completions"` request bodies. For `vllm/nemotron-3-*` with thinking off, the bundled vLLM plugin automatically sends `enable_thinking: false` and `force_nonempty_content: true`; explicit `chat_template_kwargs` override generated defaults, and `extra_body.chat_template_kwargs` still has final precedence. For vLLM Qwen thinking controls, set `params.qwenThinkingFormat` to `"chat-template"` or `"top-level"` on that model entry.
- `compat.thinkingFormat`: OpenAI-compatible thinking payload style. Use `"qwen"` for Qwen-style top-level `enable_thinking`, or `"qwen-chat-template"` for `chat_template_kwargs.enable_thinking` on Qwen-family backends that support request-level chat-template kwargs, such as vLLM. OpenClaw maps disabled thinking to `false` and enabled thinking to `true`.
- `compat.supportedReasoningEfforts`: per-model OpenAI-compatible reasoning effort list. Include `"xhigh"` for custom endpoints that truly accept it; OpenClaw then exposes `/think xhigh` in command menus, Gateway session rows, session patch validation, agent CLI validation, and `llm-task` validation for that configured provider/model. Use `compat.reasoningEffortMap` when the backend wants a provider-specific value for a canonical level.
- `params.preserveThinking`: Z.AI-only opt-in for preserved thinking. When enabled and thinking is on, OpenClaw sends `thinking.clear_thinking: false` and replays prior `reasoning_content`; see [Z.AI thinking and preserved thinking](/providers/zai#thinking-and-preserved-thinking).
- `agentRuntime`: default low-level agent runtime policy. Omitted id defaults to OpenClaw Pi. Use `id: "pi"` to force the built-in PI harness, `id: "auto"` to let registered plugin harnesses claim supported models and use PI when none match, a registered harness id such as `id: "codex"` to require that harness, or a supported CLI backend alias such as `id: "claude-cli"`. Explicit plugin runtimes fail closed when the harness is unavailable or fails. Keep model refs canonical as `provider/model`; select Codex, Claude CLI, Gemini CLI, and other execution backends through runtime config instead of legacy runtime provider prefixes. See [Agent runtimes](/concepts/agent-runtimes) for how this differs from provider/model selection.
- Runtime policy belongs on providers or models, not on `agents.defaults`. Use `models.providers.<provider>.agentRuntime` for provider-wide rules or `agents.defaults.models["provider/model"].agentRuntime` / `agents.list[].models["provider/model"].agentRuntime` for model-specific rules. OpenAI agent models on the official OpenAI provider select Codex by default.
- Config writers that mutate these fields (for example `/models set`, `/models set-image`, and fallback add/remove commands) save canonical object form and preserve existing fallback lists when possible.
- `maxConcurrent`: max parallel agent runs across sessions (each session still serialized). Default: 4.
### `agents.defaults.agentRuntime`
`agentRuntime` controls which low-level executor runs agent turns. Most
deployments should keep the default OpenClaw Pi runtime. Use it when a trusted
plugin provides a native harness, such as the bundled Codex app-server harness,
or when you want a supported CLI backend such as Claude CLI. For the mental
model, see [Agent runtimes](/concepts/agent-runtimes).
### Runtime policy
```json5
{
models: {
providers: {
openai: {
agentRuntime: { id: "codex" },
},
},
},
agents: {
defaults: {
model: "openai/gpt-5.5",
agentRuntime: {
id: "codex",
models: {
"anthropic/claude-opus-4-7": {
agentRuntime: { id: "claude-cli" },
},
},
},
},
@@ -425,11 +426,9 @@ model, see [Agent runtimes](/concepts/agent-runtimes).
- `id`: `"auto"`, `"pi"`, a registered plugin harness id, or a supported CLI backend alias. The bundled Codex plugin registers `codex`; the bundled Anthropic plugin provides the `claude-cli` CLI backend.
- `id: "auto"` lets registered plugin harnesses claim supported turns and uses PI when no harness matches. An explicit plugin runtime such as `id: "codex"` requires that harness and fails closed if it is unavailable or fails.
- Environment override: `OPENCLAW_AGENT_RUNTIME=<id|auto|pi>` overrides `id` for that process.
- OpenAI agent models use the Codex harness by default; `agentRuntime.id: "codex"` remains valid when you want to make that explicit.
- For Claude CLI deployments, prefer `model: "anthropic/claude-opus-4-7"` plus `agentRuntime.id: "claude-cli"`. Legacy `claude-cli/claude-opus-4-7` model refs still work for compatibility, but new config should keep provider/model selection canonical and put the execution backend in `agentRuntime.id`.
- Older runtime-policy keys are rewritten to `agentRuntime` by `openclaw doctor --fix`.
- Harness choice is pinned per session id after the first embedded run. Config/env changes affect new or reset sessions, not an existing transcript. Legacy OpenAI sessions with transcript history but no recorded pin use Codex; stale OpenAI PI pins can be repaired with `openclaw doctor --fix`. `/status` reports the effective runtime, for example `Runtime: OpenClaw Pi Default` or `Runtime: OpenAI Codex`.
- Whole-agent runtime keys are legacy. `agents.defaults.agentRuntime`, `agents.list[].agentRuntime`, session runtime pins, and `OPENCLAW_AGENT_RUNTIME` are ignored by runtime selection. Run `openclaw doctor --fix` to remove stale values.
- OpenAI agent models use the Codex harness by default; provider/model `agentRuntime.id: "codex"` remains valid when you want to make that explicit.
- For Claude CLI deployments, prefer `model: "anthropic/claude-opus-4-7"` plus model-scoped `agentRuntime.id: "claude-cli"`. Legacy `claude-cli/claude-opus-4-7` model refs still work for compatibility, but new config should keep provider/model selection canonical and put the execution backend in provider/model runtime policy.
- This only controls text agent-turn execution. Media generation, vision, PDF, music, video, and TTS still use their provider/model settings.
**Built-in alias shorthands** (only apply when the model is in `agents.defaults.models`):
@@ -959,7 +958,6 @@ for provider examples and precedence.
thinkingDefault: "high", // per-agent thinking level override
reasoningDefault: "on", // per-agent reasoning visibility override
fastModeDefault: false, // per-agent fast mode override
agentRuntime: { id: "auto" },
params: { cacheRetention: "none" }, // overrides matching defaults.models params by key
tts: {
providers: {
@@ -1006,7 +1004,7 @@ for provider examples and precedence.
- `thinkingDefault`: optional per-agent default thinking level (`off | minimal | low | medium | high | xhigh | adaptive | max`). Overrides `agents.defaults.thinkingDefault` for this agent when no per-message or session override is set. The selected provider/model profile controls which values are valid; for Google Gemini, `adaptive` keeps provider-owned dynamic thinking (`thinkingLevel` omitted on Gemini 3/3.1, `thinkingBudget: -1` on Gemini 2.5).
- `reasoningDefault`: optional per-agent default reasoning visibility (`on | off | stream`). Overrides `agents.defaults.reasoningDefault` for this agent when no per-message or session reasoning override is set.
- `fastModeDefault`: optional per-agent default for fast mode (`true | false`). Applies when no per-message or session fast-mode override is set.
- `agentRuntime`: optional per-agent low-level runtime policy override. Use `{ id: "codex" }` to make one agent Codex-only while other agents keep the default PI fallback in `auto` mode.
- `models`: optional per-agent model catalog/runtime overrides keyed by full `provider/model` ids. Use `models["provider/model"].agentRuntime` for per-agent runtime exceptions.
- `runtime`: optional per-agent runtime descriptor. Use `type: "acp"` with `runtime.acp` defaults (`agent`, `backend`, `mode`, `cwd`) when the agent should default to ACP harness sessions.
- `identity.avatar`: workspace-relative path, `http(s)` URL, or `data:` URI.
- `identity` derives defaults: `ackReaction` from `emoji`, `mentionPatterns` from `name`/`emoji`.
@@ -1381,6 +1379,8 @@ Defaults for Talk mode (macOS/iOS/Android).
},
system: {},
},
consultThinkingLevel: "low",
consultFastMode: true,
speechLocale: "ru-RU",
silenceTimeoutMs: 1500,
interruptOnSpeech: true,
@@ -1388,8 +1388,8 @@ Defaults for Talk mode (macOS/iOS/Android).
provider: "openai",
providers: {
openai: {
model: "gpt-realtime",
voice: "alloy",
model: "gpt-realtime-2",
voice: "cedar",
},
},
mode: "realtime",
@@ -1408,6 +1408,8 @@ Defaults for Talk mode (macOS/iOS/Android).
- `providers.*.voiceAliases` lets Talk directives use friendly names.
- `providers.mlx.modelId` selects the Hugging Face repo used by the macOS local MLX helper. If omitted, macOS uses `mlx-community/Soprano-80M-bf16`.
- macOS MLX playback runs through the bundled `openclaw-mlx-tts` helper when present, or an executable on `PATH`; `OPENCLAW_MLX_TTS_BIN` overrides the helper path for development.
- `consultThinkingLevel` controls the thinking level for the full OpenClaw agent run behind Control UI Talk realtime `openclaw_agent_consult` calls. Leave unset to preserve normal session/model behavior.
- `consultFastMode` sets a one-shot fast-mode override for Control UI Talk realtime consults without changing the session's normal fast-mode setting.
- `speechLocale` sets the BCP 47 locale id used by iOS/macOS Talk speech recognition. Leave unset to use the device default.
- `silenceTimeoutMs` controls how long Talk mode waits after user silence before it sends the transcript. Unset keeps the platform default pause window (`700 ms on macOS and Android, 900 ms on iOS`).

View File

@@ -585,7 +585,7 @@ When Mattermost native commands are enabled:
OpenClaw spawns `imsg rpc` (JSON-RPC over stdio). No daemon or port required. This is the preferred path for new OpenClaw iMessage setups when the host can grant Messages database and Automation permissions.
BlueBubbles is deprecated and no longer ships as a bundled OpenClaw channel. Migrate `channels.bluebubbles` configs to `channels.imessage`; third-party BlueBubbles bridges belong outside core.
BlueBubbles support was removed. Migrate `channels.bluebubbles` configs to `channels.imessage`; OpenClaw supports iMessage through `imsg` only.
If the Gateway is not running on the signed-in Messages Mac, keep `channels.imessage.enabled=true` and set `channels.imessage.cliPath` to an SSH wrapper that runs `imsg "$@"` on that Mac. The default local `imsg` path is macOS-only.

View File

@@ -474,6 +474,7 @@ OpenClaw uses the built-in model catalog. Add custom providers via `models.provi
- `models.providers.*.models.*.contextTokens`: optional runtime context cap. This overrides provider-level `contextTokens`; use it when you want a smaller effective context budget than the model's native `contextWindow`; `openclaw models list` shows both values when they differ.
- `models.providers.*.models.*.compat.supportsDeveloperRole`: optional compatibility hint. For `api: "openai-completions"` with a non-empty non-native `baseUrl` (host not `api.openai.com`), OpenClaw forces this to `false` at runtime. Empty/omitted `baseUrl` keeps default OpenAI behavior.
- `models.providers.*.models.*.compat.requiresStringContent`: optional compatibility hint for string-only OpenAI-compatible chat endpoints. When `true`, OpenClaw flattens pure text `messages[].content` arrays into plain strings before sending the request.
- `models.providers.*.models.*.compat.thinkingFormat`: optional thinking payload hint. Use `"qwen"` for top-level `enable_thinking`, or `"qwen-chat-template"` for `chat_template_kwargs.enable_thinking` on Qwen-family OpenAI-compatible servers that support request-level chat-template kwargs, such as vLLM.
</Accordion>
<Accordion title="Amazon Bedrock discovery">

View File

@@ -48,6 +48,8 @@ Moved to a dedicated page - see
- `session.*` (session lifecycle, compaction, pruning)
- `messages.*` (message delivery, TTS, markdown rendering)
- `talk.*` (Talk mode)
- `talk.consultThinkingLevel`: thinking level override for the full OpenClaw agent run behind Control UI Talk realtime consults
- `talk.consultFastMode`: one-shot fast-mode override for Control UI Talk realtime consults
- `talk.speechLocale`: optional BCP 47 locale id for Talk speech recognition on iOS/macOS
- `talk.silenceTimeoutMs`: when unset, Talk keeps the platform default pause window before sending the transcript (`700 ms on macOS and Android, 900 ms on iOS`)
@@ -198,8 +200,75 @@ See [MCP](/cli/mcp#openclaw-as-an-mcp-client-registry) and
- `plugins.entries.<id>.hooks.allowConversationAccess`: when `true`, trusted non-bundled plugins may read raw conversation content from typed hooks such as `llm_input`, `llm_output`, `before_model_resolve`, `before_agent_reply`, `before_agent_run`, `before_agent_finalize`, and `agent_end`.
- `plugins.entries.<id>.subagent.allowModelOverride`: explicitly trust this plugin to request per-run `provider` and `model` overrides for background subagent runs.
- `plugins.entries.<id>.subagent.allowedModels`: optional allowlist of canonical `provider/model` targets for trusted subagent overrides. Use `"*"` only when you intentionally want to allow any model.
- `plugins.entries.<id>.llm.allowModelOverride`: explicitly trust this plugin to request model overrides for `api.runtime.llm.complete`.
- `plugins.entries.<id>.llm.allowedModels`: optional allowlist of canonical `provider/model` targets for trusted plugin LLM completion overrides. Use `"*"` only when you intentionally want to allow any model.
- `plugins.entries.<id>.llm.allowAgentIdOverride`: explicitly trust this plugin to run `api.runtime.llm.complete` against a non-default agent id.
- `plugins.entries.<id>.config`: plugin-defined config object (validated by native OpenClaw plugin schema when available).
- Channel plugin account/runtime settings live under `channels.<id>` and should be described by the owning plugin's manifest `channelConfigs` metadata, not by a central OpenClaw option registry.
### Codex harness plugin config
The bundled `codex` plugin owns native Codex app-server harness settings under
`plugins.entries.codex.config`. See [Codex harness](/plugins/codex-harness) for
the full runtime model.
`codexPlugins` applies only to sessions that select the native Codex harness.
It does not enable Codex plugins for Pi, normal OpenAI provider runs, ACP
conversation bindings, or any non-Codex harness.
```json5
{
plugins: {
entries: {
codex: {
enabled: true,
config: {
codexPlugins: {
enabled: true,
allow_destructive_actions: false,
plugins: {
"google-calendar": {
enabled: true,
marketplaceName: "openai-curated",
pluginName: "google-calendar",
allow_destructive_actions: false,
},
},
},
},
},
},
},
}
```
- `plugins.entries.codex.config.codexPlugins.enabled`: enables native Codex
plugin/app support for the Codex harness. Default: `false`.
- `plugins.entries.codex.config.codexPlugins.allow_destructive_actions`:
default destructive-action policy for migrated plugin app elicitations.
Default: `false`.
- `plugins.entries.codex.config.codexPlugins.plugins.<key>.enabled`: enables a
migrated plugin entry when global `codexPlugins.enabled` is also true.
Default: `true` for explicit entries.
- `plugins.entries.codex.config.codexPlugins.plugins.<key>.marketplaceName`:
stable marketplace identity. V1 only supports `"openai-curated"`.
- `plugins.entries.codex.config.codexPlugins.plugins.<key>.pluginName`: stable
Codex plugin identity from migration, for example `"google-calendar"`.
- `plugins.entries.codex.config.codexPlugins.plugins.<key>.allow_destructive_actions`:
per-plugin destructive-action override. When omitted, the global
`allow_destructive_actions` value is used.
`codexPlugins.enabled` is the global enablement directive. Explicit plugin
entries written by migration are the durable install and repair eligibility set.
`plugins["*"]` is not supported, there is no `install` switch, and local
`marketplacePath` values are intentionally not config fields because they are
host-specific.
`app/list` readiness checks are cached for one hour and refreshed
asynchronously when stale. Codex thread app config is computed at Codex harness
session establishment, not on every turn; use `/new`, `/reset`, or a gateway
restart after changing native plugin config.
- `plugins.entries.firecrawl.config.webFetch`: Firecrawl web-fetch provider settings.
- `apiKey`: Firecrawl API key (accepts SecretRef). Falls back to `plugins.entries.firecrawl.config.webSearch.apiKey`, legacy `tools.web.fetch.firecrawl.apiKey`, or `FIRECRAWL_API_KEY` env var.
- `baseUrl`: Firecrawl API base URL (default: `https://api.firecrawl.dev`; self-hosted overrides must target private/internal endpoints).
@@ -443,6 +512,10 @@ See [Inferred commitments](/concepts/commitments).
value, so repeated failures from one localhost origin do not automatically
lock out a different origin.
- `tailscale.mode`: `serve` (tailnet only, loopback bind) or `funnel` (public, requires auth).
- `tailscale.preserveFunnel`: when `true` and `tailscale.mode = "serve"`, OpenClaw
checks `tailscale funnel status` before re-applying Serve at startup and skips
it if an externally configured Funnel route already covers the gateway port.
Default `false`.
- `controlUi.allowedOrigins`: explicit browser-origin allowlist for Gateway WebSocket connects. Required when browser clients are expected from non-loopback origins.
- `controlUi.chatMessageMaxWidth`: optional max-width for grouped Control UI chat messages. Accepts constrained CSS width values such as `960px`, `82%`, `min(1280px, 82%)`, and `calc(100% - 2rem)`.
- `controlUi.dangerouslyAllowHostHeaderOriginFallback`: dangerous mode that enables Host-header origin fallback for deployments that intentionally rely on Host-header origin policy.

View File

@@ -87,7 +87,7 @@ cat ~/.openclaw/openclaw.json
- Legacy on-disk state migration (sessions/agent dir/WhatsApp auth).
- Legacy plugin manifest contract key migration (`speechProviders`, `realtimeTranscriptionProviders`, `realtimeVoiceProviders`, `mediaUnderstandingProviders`, `imageGenerationProviders`, `videoGenerationProviders`, `webFetchProviders`, `webSearchProviders` → `contracts`).
- Legacy cron store migration (`jobId`, `schedule.cron`, top-level delivery/payload fields, payload `provider`, simple `notify: true` webhook fallback jobs).
- Legacy agent runtime-policy migration to `agents.defaults.agentRuntime` and `agents.list[].agentRuntime`.
- Legacy whole-agent runtime-policy cleanup; provider/model runtime policy is the active route selector.
- Stale plugin config cleanup when plugins are enabled; when `plugins.enabled=false`, stale plugin references are treated as inert containment config and are preserved.
</Accordion>
@@ -109,7 +109,7 @@ cat ~/.openclaw/openclaw.json
- Channel status warnings (probed from the running gateway).
- Channel-specific permission checks live under `openclaw channels capabilities`; for example, Discord voice channel permissions are audited with `openclaw channels capabilities --channel discord --target channel:<channel-id>`.
- WhatsApp responsiveness checks for degraded Gateway event-loop health with local TUI clients still running; `--fix` stops only verified local TUI clients.
- Codex route repair for legacy `openai-codex/*` model refs in primary models, fallbacks, heartbeat/subagent/compaction overrides, hooks, channel model overrides, and session route pins; `--fix` rewrites them to `openai/*` and selects `agentRuntime.id: "codex"` only when the Codex plugin is installed, enabled, contributes the `codex` harness, and has usable OAuth. Otherwise it selects `agentRuntime.id: "pi"`.
- Codex route repair for legacy `openai-codex/*` model refs in primary models, fallbacks, heartbeat/subagent/compaction overrides, hooks, channel model overrides, and session route pins; `--fix` rewrites them to `openai/*`, removes stale session/whole-agent runtime pins, and leaves canonical OpenAI agent refs on the default Codex harness.
- Supervisor config audit (launchd/systemd/schtasks) with optional repair.
- Embedded proxy environment cleanup for gateway services that captured shell `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` values during install or update.
- Gateway runtime best-practice checks (Node vs Bun, version-manager paths).
@@ -269,8 +269,8 @@ That stages grounded durable candidates into the short-term dreaming store while
In `--fix` / `--repair` mode, doctor rewrites affected default-agent and per-agent refs, including primary models, fallbacks, heartbeat/subagent/compaction overrides, hooks, channel model overrides, and stale persisted session route state:
- `openai-codex/gpt-*` becomes `openai/gpt-*`.
- The matching agent runtime becomes `agentRuntime.id: "codex"` only when Codex is installed, enabled, contributes the `codex` harness, and has usable OAuth.
- Otherwise the matching agent runtime becomes `agentRuntime.id: "pi"`.
- Stale whole-agent runtime config and persisted session runtime pins are removed because runtime selection is provider/model-scoped.
- Explicit provider/model runtime policy is preserved.
- Existing model fallback lists are preserved with their legacy entries rewritten; copied per-model settings move from the legacy key to the canonical `openai/*` key.
- Persisted session `modelProvider`/`providerOverride`, `model`/`modelOverride`, fallback notices, auth-profile pins, and Codex harness pins are repaired across all discovered agent session stores.
- `/codex ...` means "control or bind a native Codex conversation from chat."
@@ -489,7 +489,7 @@ That stages grounded durable candidates into the short-term dreaming store while
<Accordion title="17. Gateway runtime best practices">
Doctor warns when the gateway service runs on Bun or a version-managed Node path (`nvm`, `fnm`, `volta`, `asdf`, etc.). WhatsApp + Telegram channels require Node, and version-manager paths can break after upgrades because the service does not load your shell init. Doctor offers to migrate to a system Node install when available (Homebrew/apt/choco).
Newly installed or repaired macOS LaunchAgents use a canonical system PATH (`/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin`) instead of copying the interactive shell PATH, so Volta, asdf, fnm, pnpm, and other version-manager directories do not change which Node child processes resolve. Linux services still keep explicit environment roots (`NVM_DIR`, `FNM_DIR`, `VOLTA_HOME`, `ASDF_DATA_DIR`, `BUN_INSTALL`, `PNPM_HOME`) and stable user-bin directories, but guessed version-manager fallback directories are only written to the service PATH when those directories exist on disk.
Newly installed or repaired macOS LaunchAgents use a canonical system PATH (`/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin`) instead of copying the interactive shell PATH, so Homebrew-managed system binaries remain available while Volta, asdf, fnm, pnpm, and other version-manager directories do not change which Node child processes resolve. Linux services still keep explicit environment roots (`NVM_DIR`, `FNM_DIR`, `VOLTA_HOME`, `ASDF_DATA_DIR`, `BUN_INSTALL`, `PNPM_HOME`) and stable user-bin directories, but guessed version-manager fallback directories are only written to the service PATH when those directories exist on disk.
</Accordion>
<Accordion title="18. Config write + wizard metadata">

View File

@@ -217,7 +217,9 @@ openclaw gateway restart
openclaw gateway stop
```
Use `openclaw gateway restart` for restarts. Do not chain `openclaw gateway stop` and `openclaw gateway start`; on macOS, `gateway stop` intentionally disables the LaunchAgent before stopping it.
Use `openclaw gateway restart` for restarts. Do not chain `openclaw gateway stop` and `openclaw gateway start` as a restart substitute.
On macOS, `gateway stop` uses `launchctl bootout` by default — this removes the LaunchAgent from the current boot session without persisting a disable, so KeepAlive auto-recovery still works after unexpected crashes and `gateway start` re-enables cleanly. To persistently suppress auto-respawn across reboots, pass `--disable`: `openclaw gateway stop --disable`.
LaunchAgent labels are `ai.openclaw.gateway` (default) or `ai.openclaw.<profile>` (named profile). `openclaw doctor` audits and repairs service config drift.

View File

@@ -377,7 +377,7 @@ enumeration of `src/gateway/server-methods/*.ts`.
- `talk.session.appendAudio` appends base64 PCM input audio to Gateway-owned realtime relay and transcription sessions.
- `talk.session.startTurn`, `talk.session.endTurn`, and `talk.session.cancelTurn` drive managed-room turn lifecycle with stale-turn rejection before state is cleared.
- `talk.session.cancelOutput` stops assistant audio output, primarily for VAD-gated barge-in in Gateway relay sessions.
- `talk.session.submitToolResult` completes a provider tool call emitted by a Gateway-owned realtime relay session.
- `talk.session.submitToolResult` completes a provider tool call emitted by a Gateway-owned realtime relay session. Pass `options: { willContinue: true }` for interim tool output when a final result will follow.
- `talk.session.close` closes a Gateway-owned relay, transcription, or managed-room session and emits terminal Talk events.
- `talk.mode` sets/broadcasts the current Talk mode state for WebChat/Control UI clients.
- `talk.client.create` creates a client-owned realtime provider session using `webrtc` or `provider-websocket` while the Gateway owns config, credentials, instructions, and tool policy.
@@ -411,6 +411,7 @@ enumeration of `src/gateway/server-methods/*.ts`.
- `agents.list` returns configured agent entries, including effective model and runtime metadata.
- `agents.create`, `agents.update`, and `agents.delete` manage agent records and workspace wiring.
- `agents.files.list`, `agents.files.get`, and `agents.files.set` manage the bootstrap workspace files exposed for an agent.
- `tasks.list`, `tasks.get`, and `tasks.cancel` expose the Gateway task ledger to SDK and operator clients.
- `artifacts.list`, `artifacts.get`, and `artifacts.download` expose transcript-derived artifact summaries and downloads for an explicit `sessionKey`, `runId`, or `taskId` scope. Run and task queries resolve the owning session server-side and only return transcript media with matching provenance; unsafe or local URL sources return unsupported downloads instead of fetching server-side.
- `environments.list` and `environments.status` expose read-only Gateway-local and node environment discovery for SDK clients.
- `agent.identity.get` returns the effective assistant identity for an agent or session.
@@ -499,6 +500,34 @@ enumeration of `src/gateway/server-methods/*.ts`.
- Nodes may call `skills.bins` to fetch the current list of skill executables
for auto-allow checks.
### Task ledger RPCs
Operator clients may inspect and cancel Gateway background task records through
the task ledger RPCs. These methods return sanitized task summaries, not raw
runtime state.
- `tasks.list` requires `operator.read`.
- Params: optional `status` (`"queued"`, `"running"`, `"completed"`,
`"failed"`, `"cancelled"`, or `"timed_out"`) or an array of those statuses,
optional `agentId`, optional `sessionKey`, optional `limit` from `1` to
`500`, and optional string `cursor`.
- Result: `{ "tasks": TaskSummary[], "nextCursor"?: string }`.
- `tasks.get` requires `operator.read`.
- Params: `{ "taskId": string }`.
- Result: `{ "task": TaskSummary }`.
- Missing task ids return the Gateway not-found error shape.
- `tasks.cancel` requires `operator.write`.
- Params: `{ "taskId": string, "reason"?: string }`.
- Result:
`{ "found": boolean, "cancelled": boolean, "reason"?: string, "task"?: TaskSummary }`.
- `found` reports whether the ledger had a matching task. `cancelled`
reports whether the runtime accepted or recorded cancellation.
`TaskSummary` includes `id`, `status`, and optional metadata such as `kind`,
`runtime`, `title`, `agentId`, `sessionKey`, `childSessionKey`, `ownerKey`,
`runId`, `taskId`, `flowId`, `parentTaskId`, `sourceId`, timestamps, progress,
terminal summary, and sanitized error text.
### Operator helper methods
- Operators may call `commands.list` (`operator.read`) to fetch the runtime

View File

@@ -64,6 +64,7 @@ Rules of thumb:
- `deny` always wins.
- If `allow` is non-empty, everything else is treated as blocked.
- Tool policy is the hard stop: `/exec` cannot override a denied `exec` tool.
- Tool policy filters tool availability by name; it does not inspect side effects inside `exec`. If `exec` is allowed, denying `write`, `edit`, or `apply_patch` does not make shell commands read-only.
- `/exec` only changes session defaults for authorized senders; it does not grant tool access.
Provider tool keys accept either `provider` (e.g. `google-antigravity`) or `provider/model` (e.g. `openai/gpt-5.4`).
@@ -88,6 +89,7 @@ Available groups:
- `group:runtime`: `exec`, `process`, `code_execution` (`bash` is accepted as
an alias for `exec`)
- `group:fs`: `read`, `write`, `edit`, `apply_patch`
For read-only agents, deny `group:runtime` as well as mutating filesystem tools unless sandbox filesystem policy or a separate host boundary enforces the read-only constraint.
- `group:sessions`: `sessions_list`, `sessions_history`, `sessions_send`, `sessions_spawn`, `sessions_yield`, `subagents`, `session_status`
- `group:memory`: `memory_search`, `memory_get`
- `group:web`: `web_search`, `x_search`, `web_fetch`

View File

@@ -91,6 +91,7 @@ exhaustive):
| `tools.exec.host_sandbox_no_sandbox_defaults` | warn | `exec host=sandbox` fails closed when sandbox is off | `tools.exec.host`, `agents.defaults.sandbox.mode` | no |
| `tools.exec.host_sandbox_no_sandbox_agents` | warn | Per-agent `exec host=sandbox` fails closed when sandbox is off | `agents.list[].tools.exec.host`, `agents.list[].sandbox.mode` | no |
| `tools.exec.security_full_configured` | warn/critical | Host exec is running with `security="full"` | `tools.exec.security`, `agents.list[].tools.exec.security` | no |
| `tools.exec.fs_tools_disabled_but_exec_enabled` | warn | Filesystem tool policy does not make shell execution read-only | `tools.deny`, `agents.list[].tools.deny`, `agents.*.sandbox.workspaceAccess` | no |
| `tools.exec.auto_allow_skills_enabled` | warn | Exec approvals trust skill bins implicitly | `~/.openclaw/exec-approvals.json` | no |
| `tools.exec.allowlist_interpreter_without_strict_inline_eval` | warn | Interpreter allowlists permit inline eval without forced reapproval | `tools.exec.strictInlineEval`, `agents.list[].tools.exec.strictInlineEval`, exec approvals allowlist | no |
| `tools.exec.safe_bins_interpreter_unprofiled` | warn | Interpreter/runtime bins in `safeBins` without explicit profiles broaden exec risk | `tools.exec.safeBins`, `tools.exec.safeBinProfiles`, `agents.list[].tools.exec.*` | no |

View File

@@ -220,6 +220,7 @@ Advisory triage guidance:
- **Inbound access** (DM policies, group policies, allowlists): can strangers trigger the bot?
- **Tool blast radius** (elevated tools + open rooms): could prompt injection turn into shell/file/network actions?
- **Exec filesystem drift**: are mutating filesystem tools denied while `exec`/`process` remain available without sandbox filesystem constraints?
- **Exec approval drift** (`security=full`, `autoAllowSkills`, interpreter allowlists without `strictInlineEval`): are host-exec guardrails still doing what you think they are?
- `security="full"` is a broad posture warning, not proof of a bug. It is the chosen default for trusted personal-assistant setups; tighten it only when your threat model needs approval or allowlist guardrails.
- **Network exposure** (Gateway bind/auth, Tailscale Serve/Funnel, weak/short auth tokens).

View File

@@ -116,6 +116,11 @@ openclaw gateway --tailscale funnel --auth password
- `tailscale.mode: "funnel"` refuses to start unless auth mode is `password` to avoid public exposure.
- Set `gateway.tailscale.resetOnExit` if you want OpenClaw to undo `tailscale serve`
or `tailscale funnel` configuration on shutdown.
- Set `gateway.tailscale.preserveFunnel: true` to keep an externally configured
`tailscale funnel` route alive across gateway restarts. When enabled and the
gateway runs in `mode: "serve"`, OpenClaw checks `tailscale funnel status`
before re-applying Serve and skips it when a Funnel route already covers the
gateway port. The OpenClaw-managed Funnel password-only policy is unchanged.
- `gateway.bind: "tailnet"` is a direct Tailnet bind (no HTTPS, no Serve/Funnel).
- `gateway.bind: "auto"` prefers loopback; use `tailnet` if you want Tailnet-only.
- Serve/Funnel only expose the **Gateway control UI + WS**. Nodes connect over

View File

@@ -97,6 +97,7 @@ If a tool is not allowed by policy, the endpoint returns **404**.
Important boundary notes:
- Exec approvals are operator guardrails, not a separate authorization boundary for this HTTP endpoint. If a tool is reachable here via Gateway auth + tool policy, `/tools/invoke` does not add an extra per-call approval prompt.
- If `exec` is reachable here, treat it as a mutating shell surface. Denying `write`, `edit`, `apply_patch`, or HTTP filesystem-write tools does not make shell execution read-only.
- Do not share Gateway bearer credentials with untrusted callers. If you need separation across trust boundaries, run separate gateways (and ideally separate OS users/hosts).
Gateway HTTP also applies a hard deny list by default (even if session policy allows the tool):

View File

@@ -96,9 +96,9 @@ add Node's sync I/O trace flag through the source runner:
OPENCLAW_TRACE_SYNC_IO=1 pnpm openclaw gateway --force
```
`pnpm gateway:watch` enables this flag by default for the watched Gateway child.
Set `OPENCLAW_TRACE_SYNC_IO=0` to suppress Node sync I/O trace output in watch
mode.
`pnpm gateway:watch` leaves this flag disabled by default for the watched
Gateway child. Set `OPENCLAW_TRACE_SYNC_IO=1` when you explicitly want Node
sync I/O trace output in watch mode.
## Gateway watch mode

View File

@@ -594,12 +594,11 @@ and troubleshooting see the main [FAQ](/help/faq).
<Accordion title="How does Codex auth work?">
OpenClaw supports **OpenAI Code (Codex)** via OAuth (ChatGPT sign-in). Use
`openai/gpt-5.5` with `agentRuntime.id: "codex"` for the common setup:
ChatGPT/Codex subscription auth plus native Codex app-server execution. Use
`openai-codex/gpt-5.5` only when you want Codex OAuth through the default
Codex runtime. Direct OpenAI API-key access remains available for non-agent
OpenAI API surfaces and for agent models through an ordered
`openai-codex` API-key profile.
`openai/gpt-5.5` for the common setup: ChatGPT/Codex subscription auth plus
native Codex app-server execution. `openai-codex/gpt-*` model refs are
legacy config repaired by `openclaw doctor --fix`. Direct OpenAI API-key
access remains available for non-agent OpenAI API surfaces and for agent
models through an ordered `openai-codex` API-key profile.
See [Model providers](/concepts/model-providers) and [Onboarding (CLI)](/start/wizard).
</Accordion>

View File

@@ -150,7 +150,7 @@ troubleshooting, see the main [FAQ](/help/faq).
- **Native Codex coding agent:** set `agents.defaults.model.primary` to `openai/gpt-5.5`. Sign in with `openclaw models auth login --provider openai-codex` when you want ChatGPT/Codex subscription auth.
- **Direct OpenAI API tasks outside the agent loop:** configure `OPENAI_API_KEY` for images, embeddings, speech, realtime, and other non-agent OpenAI API surfaces.
- **OpenAI agent API-key auth:** use `/model openai/gpt-5.5` with an ordered `openai-codex` API-key profile.
- **Sub-agents:** route coding tasks to a Codex-only agent with its own model and `agentRuntime` default.
- **Sub-agents:** route coding tasks to a Codex-focused agent with its own `openai/gpt-5.5` model.
See [Models](/concepts/models) and [Slash commands](/tools/slash-commands).

View File

@@ -409,7 +409,7 @@ lives on the [First-run FAQ](/help/faq-first-run).
openclaw skills update --all
```
Native installs land in the active workspace `skills/` directory. For shared skills across agents, place them in `~/.openclaw/skills/<name>/SKILL.md`. If only some agents should see a shared install, configure `agents.defaults.skills` or `agents.list[].skills`. Some skills expect binaries installed via Homebrew; on Linux that means Linuxbrew (see the Homebrew Linux FAQ entry above). See [Skills](/tools/skills), [Skills config](/tools/skills-config), and [ClawHub](/tools/clawhub).
Native installs land in the active workspace `skills/` directory. For shared skills across agents, place them in `~/.openclaw/skills/<name>/SKILL.md`. If only some agents should see a shared install, configure `agents.defaults.skills` or `agents.list[].skills`. Some skills expect binaries installed via Homebrew; on Linux that means Linuxbrew (see the Homebrew Linux FAQ entry above). See [Skills](/tools/skills), [Skills config](/tools/skills-config), and [ClawHub](/clawhub).
</Accordion>

View File

@@ -285,8 +285,8 @@ Docker notes:
- Goal: validate the plugin-owned Codex harness through the normal gateway
`agent` method:
- load the bundled `codex` plugin
- select `OPENCLAW_AGENT_RUNTIME=codex`
- send a first gateway agent turn to `openai/gpt-5.5` with the Codex harness forced
- select `openai/gpt-5.5`, which routes OpenAI agent turns through Codex by default
- send a first gateway agent turn to `openai/gpt-5.5` with the Codex harness selected
- send a second turn to the same OpenClaw session and verify the app-server
thread can resume
- run `/codex status` and `/codex models` through the same gateway command
@@ -300,8 +300,8 @@ Docker notes:
- Optional image probe: `OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=1`
- Optional MCP/tool probe: `OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=1`
- Optional Guardian probe: `OPENCLAW_LIVE_CODEX_HARNESS_GUARDIAN_PROBE=1`
- The smoke uses `agentRuntime.id: "codex"` so a broken Codex harness cannot
pass by silently falling back to PI.
- The smoke forces provider/model `agentRuntime.id: "codex"` so a broken Codex
harness cannot pass by silently falling back to PI.
- Auth: Codex app-server auth from the local Codex subscription login. Docker
smokes can also provide `OPENAI_API_KEY` for non-Codex probes when applicable,
plus optional copied `~/.codex/auth.json` and `~/.codex/config.toml`.

View File

@@ -81,6 +81,14 @@ When debugging real providers/models (requires real creds):
`OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_GUARDIAN_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=1 pnpm test:docker:live-codex-harness`.
This exits after the sub-agent probe unless
`OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_ONLY=0` is set.
- Codex on-demand install smoke: `pnpm test:docker:codex-on-demand`
- Installs the packaged OpenClaw tarball in Docker, runs OpenAI API-key
onboarding, and verifies the Codex plugin plus `@openai/codex` dependency
were downloaded into the managed npm root on demand.
- Live plugin tool dependency smoke: `pnpm test:docker:live-plugin-tool`
- Packs a fixture plugin with a real `slugify` dependency, installs it through
`npm-pack:`, verifies the dependency under the managed npm root, then asks a
live OpenAI model to call the plugin tool and return the hidden slug.
- Crestodian rescue command smoke: `pnpm test:live:crestodian-rescue-channel`
- Opt-in belt-and-suspenders check for the message-channel rescue command
surface. It exercises `/crestodian status`, queues a persistent model
@@ -195,6 +203,10 @@ inside every shard.
- Installs an OpenClaw package candidate in Docker, runs installed-package
onboarding, configures Telegram through the installed CLI, then reuses the
live Telegram QA lane with that installed package as the SUT Gateway.
- The wrapper mounts only the `qa-lab` harness source from the checkout; the
installed package owns `dist`, `openclaw/plugin-sdk`, and bundled plugin
runtime so the lane does not mix current checkout plugins into the package
under test.
- Defaults to `OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@beta`; set
`OPENCLAW_NPM_TELEGRAM_PACKAGE_TGZ=/path/to/openclaw-current.tgz` or
`OPENCLAW_CURRENT_PACKAGE_TGZ` to test a resolved local tarball instead of
@@ -307,6 +319,7 @@ gh workflow run package-acceptance.yml --ref main \
- Runs the Telegram live QA lane against a real private group using the driver and SUT bot tokens from env.
- Requires `OPENCLAW_QA_TELEGRAM_GROUP_ID`, `OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN`, and `OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`. The group id must be the numeric Telegram chat id.
- Supports `--credential-source convex` for shared pooled credentials. Use env mode by default, or set `OPENCLAW_QA_CREDENTIAL_SOURCE=convex` to opt into pooled leases.
- Defaults cover canary, mention gating, command addressing, `/status`, bot-to-bot mentioned replies, and core native command replies. `mock-openai` defaults also cover deterministic reply-chain and Telegram final-message streaming regressions. Use `--list-scenarios` for optional probes such as `session_status`.
- Exits non-zero when any scenario fails. Use `--allow-failures` when you
want artifacts without a failing exit code.
- Requires two distinct bots in the same private group, with the SUT bot exposing a Telegram username.
@@ -318,8 +331,9 @@ Live transport lanes share one standard contract so new transports do not drift;
### Shared Telegram credentials via Convex (v1)
When `--credential-source convex` (or `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`) is enabled for
`openclaw qa telegram`, QA lab acquires an exclusive lease from a Convex-backed pool, heartbeats
that lease while the lane is running, and releases the lease on shutdown.
live transport QA, QA lab acquires an exclusive lease from a Convex-backed pool, heartbeats that
lease while the lane is running, and releases the lease on shutdown. The section name predates
Discord, Slack, and WhatsApp support; the lease contract is shared across kinds.
Reference Convex project scaffold:
@@ -393,6 +407,16 @@ Payload shape for Telegram kind:
- `groupId` must be a numeric Telegram chat id string.
- `admin/add` validates this shape for `kind: "telegram"` and rejects malformed payloads.
Broker-validated multi-channel payloads:
- Discord: `{ guildId: string, channelId: string, driverBotToken: string, sutBotToken: string, sutApplicationId: string, voiceChannelId?: string }`
- WhatsApp: `{ driverPhoneE164: string, sutPhoneE164: string, driverAuthArchiveBase64: string, sutAuthArchiveBase64: string, groupJid?: string }`
Slack lanes can also lease from the pool, but Slack payload validation currently
lives in the Slack QA runner rather than the broker. Use
`{ channelId: string, driverBotToken: string, sutBotToken: string, sutAppToken: string }`
for Slack rows.
### Adding a channel to QA
The architecture and scenario-helper names for new channel adapters live in [QA overview → Adding a channel](/concepts/qa-e2e-automation#adding-a-channel). The minimum bar: implement the transport runner on the shared `qa-lab` host seam, declare `qaRunners` in the plugin manifest, mount as `openclaw qa <runner>`, and author scenarios under `qa/scenarios/`.

View File

@@ -50,9 +50,18 @@ DigitalOcean is the simplest paid VPS path. If you prefer cheaper or free option
# Install OpenClaw
curl -fsSL https://openclaw.ai/install.sh | bash
# Create the non-root user that will own OpenClaw state and services.
adduser openclaw
usermod -aG sudo openclaw
loginctl enable-linger openclaw
su - openclaw
openclaw --version
```
Use the root shell only for system bootstrap. Run OpenClaw commands as the non-root `openclaw` user so state lives under `/home/openclaw/.openclaw/` and the Gateway installs as that user's systemd service.
</Step>
<Step title="Run onboarding">
@@ -97,8 +106,8 @@ DigitalOcean is the simplest paid VPS path. If you prefer cheaper or free option
**Option B: Tailscale Serve**
```bash
curl -fsSL https://tailscale.com/install.sh | sh
tailscale up
curl -fsSL https://tailscale.com/install.sh | sudo sh
sudo tailscale up
openclaw config set gateway.tailscale.mode serve
openclaw gateway restart
```

View File

@@ -427,8 +427,7 @@ See [ClawDock](/install/clawdock) for the full helper guide.
</Accordion>
<Accordion title="Base image metadata">
The main Docker runtime image uses `node:24-bookworm-slim` and publishes OCI
base-image annotations including `org.opencontainers.image.base.name`,
The main Docker runtime image uses `node:24-bookworm-slim` and includes `tini` as the entrypoint init process (PID 1) to ensure zombie processes are reaped and signals are handled correctly in long-running containers. It publishes OCI base-image annotations including `org.opencontainers.image.base.name`,
`org.opencontainers.image.source`, and others. The Node base digest is
refreshed through Dependabot Docker base-image PRs; release builds do not run
a distro upgrade layer. See

View File

@@ -78,6 +78,8 @@ read_when:
destination = "/data"
```
The OpenClaw Docker image uses `tini` as its entrypoint. Fly process commands replace Docker `CMD` without replacing `ENTRYPOINT`, so the process still runs under `tini`.
**Key settings:**
| Setting | Why |

View File

@@ -81,8 +81,8 @@ Supported keys:
providers: {
openai: {
apiKey: "openai_api_key",
model: "gpt-realtime",
voice: "alloy",
model: "gpt-realtime-2",
voice: "cedar",
},
},
mode: "realtime",
@@ -102,8 +102,11 @@ Defaults:
- `providers.elevenlabs.modelId`: defaults to `eleven_v3` when unset.
- `providers.mlx.modelId`: defaults to `mlx-community/Soprano-80M-bf16` when unset.
- `providers.elevenlabs.apiKey`: falls back to `ELEVENLABS_API_KEY` (or gateway shell profile if available).
- `consultThinkingLevel`: optional thinking level override for the full OpenClaw agent run behind realtime `openclaw_agent_consult` calls.
- `consultFastMode`: optional fast-mode override for realtime `openclaw_agent_consult` calls.
- `realtime.provider`: selects the active browser/server realtime voice provider. Use `openai` for WebRTC, `google` for provider WebSocket, or a bridge-only provider through Gateway relay.
- `realtime.providers.<provider>` stores provider-owned realtime config. The browser receives only ephemeral or constrained session credentials, never a standard API key.
- `realtime.providers.openai.voice`: built-in OpenAI Realtime voice id. Current `gpt-realtime-2` voices are `alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, `verse`, `marin`, and `cedar`; `marin` and `cedar` are recommended for best quality.
- `realtime.brain`: `agent-consult` routes realtime tool calls through Gateway policy; `direct-tools` is owner-only compatibility behavior; `none` is for transcription or external orchestration.
- `talk.catalog` exposes each provider's valid modes, transports, brain strategies, realtime audio formats, and capability flags so first-party Talk clients can avoid unsupported combinations.
- Streaming transcription providers are discovered through `talk.catalog.transcription`. The current Gateway relay uses the Voice Call streaming provider config until the dedicated Talk transcription config surface is added.

View File

@@ -764,10 +764,21 @@ built-in implicit providers:
Later providers win on key collision, so plugins can intentionally override a
built-in provider entry with the same provider id.
Plugins can also publish read-only model rows through
`api.registerModelCatalogProvider({ provider, kinds, staticCatalog, liveCatalog
})`. This is the forward path for list/help/picker surfaces and supports
`text`, `image_generation`, `video_generation`, and `music_generation` rows.
Provider plugins still own live endpoint calls, token exchange, and vendor
response mapping; core owns the common row shape, source labels, and media tool
help formatting. Media-generation provider registrations synthesize static
catalog rows automatically from `defaultModel`, `models`, and `capabilities`.
Compatibility:
- `discovery` still works as a legacy alias
- `discovery` still works as a legacy alias, but emits a deprecation warning
- if both `catalog` and `discovery` are registered, OpenClaw uses `catalog`
- `augmentModelCatalog` is deprecated; bundled providers should publish
supplemental rows through `registerModelCatalogProvider`
## Read-only channel inspection

View File

@@ -14,7 +14,7 @@ generation, video generation, web fetch, web search, agent tools, or any
combination.
You do not need to add your plugin to the OpenClaw repository. Publish to
[ClawHub](/tools/clawhub) and users install with
[ClawHub](/clawhub) and users install with
`openclaw plugins install clawhub:<package-name>`. Bare package specs still
install from npm during the launch cutover.

View File

@@ -96,9 +96,6 @@ Computer Use available before a thread starts:
agents: {
defaults: {
model: "openai/gpt-5.5",
agentRuntime: {
id: "codex",
},
},
},
}
@@ -114,9 +111,8 @@ register the bundled Codex marketplace from
fails. If setup still cannot make the MCP server available, the turn fails
before the thread starts.
Existing sessions keep their runtime and Codex thread binding. After changing
`agentRuntime` or Computer Use config, use `/new` or `/reset` in the affected
chat before testing.
After changing Computer Use config, use `/new` or `/reset` in the affected chat
before testing if an existing Codex thread has already started.
## Commands

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