Compare commits

...

2796 Commits

Author SHA1 Message Date
Peter Steinberger
8287402da7 ci: preserve release preflight artifact across checkout 2026-05-10 18:36:56 +01:00
Peter Steinberger
2dee06f7af build: refresh canvas bundle hash 2026-05-10 18:05:28 +01:00
Peter Steinberger
d094fc79f3 chore: bump version to 2026.5.10-beta.2 2026-05-10 18:00:40 +01:00
Peter Steinberger
2a609f8a7b test: refresh generated release backport hashes 2026-05-10 17:53:45 +01:00
Frank Yang
df99775c5d fix: pass media roots to gateway message actions 2026-05-10 17:48:59 +01:00
Kagura
b99398e807 fix(codex): normalize thread id/sessionId cross-fill before schema validation (#80137)
Merged via squash.

Prepared head SHA: b2c20dd5d6
Co-authored-by: kagura-agent <268167063+kagura-agent@users.noreply.github.com>
Co-authored-by: omarshahine <10343873+omarshahine@users.noreply.github.com>
Reviewed-by: @omarshahine
2026-05-10 17:48:59 +01:00
Peter Steinberger
0e6e63b20b fix: keep provider auth login sdk compat 2026-05-10 17:48:16 +01:00
Peter Steinberger
1b204f2504 fix(acpx): await startup probe before gateway ready 2026-05-10 17:46:40 +01:00
Peter Steinberger
f66b1d1738 fix: strip OpenAI-compatible replay reasoning 2026-05-10 17:46:18 +01:00
Andy Ye
1205a9a58a fix(agents): initialize context engines before CLI compaction 2026-05-10 17:45:57 +01:00
Peter Steinberger
a5b2efa336 fix: add strict OpenAI-compatible message key mode 2026-05-10 17:45:56 +01:00
Peter Steinberger
587bb5d34b fix: preserve custom provider context limits (#79911) 2026-05-10 17:45:09 +01:00
Jefsky
01af462223 fix(onboard): avoid custom-provider compaction deadlock (#79428)
Raise default/effective Custom Provider contextWindow above the compaction
reserveTokensFloor default so new onboard flows do not infinite-compact.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-10 17:44:41 +01:00
Peter Steinberger
d39cec9510 fix: honor voice agent tool allowlist 2026-05-10 17:44:41 +01:00
scoootscooob
720e51202c fix: reread config on in-process gateway restart (#80161)
* fix: reread config on in-process gateway restart

* fix: refresh swift protocol model
2026-05-10 17:44:22 +01:00
Peter Steinberger
6edf77c65f fix: normalize merged gemini model config 2026-05-10 17:43:52 +01:00
Peter Steinberger
964e944de5 fix(discord): make native opus opt-in 2026-05-10 17:43:52 +01:00
Peter Steinberger
ed40ef0a68 fix: show deep status config warnings 2026-05-10 16:12:07 +01:00
Peter Steinberger
e5296a2401 docs: note gateway status warning visibility 2026-05-10 16:00:53 +01:00
Peter Steinberger
aa9af608a1 ci: speed up release validation profiles 2026-05-10 15:50:47 +01:00
Peter Steinberger
410efd9850 ci: tighten release publish timeouts 2026-05-10 15:19:39 +01:00
Peter Steinberger
9c7e67b0f8 ci: skip OpenAI install tool smoke 2026-05-10 13:59:23 +01:00
Peter Steinberger
fcdbaaff2b ci: trim OpenAI install package smoke 2026-05-10 13:42:56 +01:00
Peter Steinberger
638dea598c ci: use faster OpenAI model for installer proof 2026-05-10 13:16:12 +01:00
Peter Steinberger
56d192be06 ci: parallelize OpenAI installer proof turns 2026-05-10 12:44:24 +01:00
Peter Steinberger
31d78ca77c ci: give OpenAI package lane cleanup margin 2026-05-10 11:55:40 +01:00
Peter Steinberger
9877a614f8 test: refresh canvas bundle hash 2026-05-10 11:18:13 +01:00
Peter Steinberger
e8920158f0 fix(agents): preserve OpenAI event streams 2026-05-10 11:07:40 +01:00
Peter Steinberger
85a0f1c018 test(agents): type stream setup timeout mock 2026-05-10 10:15:50 +01:00
Peter Steinberger
8541f69f89 fix(agents): cap provider setup timeout 2026-05-10 10:03:06 +01:00
Peter Steinberger
a14e0aefe7 fix(agents): abort timed out stream setup 2026-05-10 09:54:20 +01:00
Peter Steinberger
3f04632448 fix(agents): enforce idle timeout during stream setup 2026-05-10 09:39:23 +01:00
Peter Steinberger
e0d48a8913 ci: use current OpenAI model for release smokes 2026-05-10 09:01:29 +01:00
Peter Steinberger
8841d9270f test(browser): relax chromium xdg env assertion 2026-05-10 07:45:44 +01:00
Peter Steinberger
d5c094f169 fix(models): include auth catalog rows in configured list 2026-05-10 07:45:39 +01:00
Peter Steinberger
d8640a847b test: clear agents mutate broad matchers 2026-05-10 07:44:44 +01:00
Peter Steinberger
9a1f6ab7f8 test: clear plugin provider broad matchers 2026-05-10 07:41:31 +01:00
Peter Steinberger
f9a106fb28 ci: cap OpenAI package update lane timeout 2026-05-10 07:41:07 +01:00
Peter Steinberger
482af6de69 fix(memory): yield while parsing session transcripts 2026-05-10 02:40:56 -04:00
bitloi
f10faa8f04 Add changelog credit for memory sync fix 2026-05-10 02:40:56 -04:00
bitloi
82bc6025bc fix(memory): yield during session indexing 2026-05-10 02:40:56 -04:00
Peter Steinberger
10db5a67aa fix(discord): defer model picker interactions 2026-05-10 07:40:30 +01:00
Peter Steinberger
59fd3e6481 test: clear subagent announce broad matchers 2026-05-10 07:38:16 +01:00
Peter Steinberger
314ab1e936 fix(models): keep keyref auth visible to discovery 2026-05-10 07:37:12 +01:00
Peter Steinberger
47326513d2 test: clear agent server method broad matchers 2026-05-10 07:35:43 +01:00
Peter Steinberger
b2bc1e9a56 test: clear talk server method broad matchers 2026-05-10 07:27:47 +01:00
Vincent Koc
5c844bea88 Merge branch 'main' of https://github.com/openclaw/openclaw
* 'main' of https://github.com/openclaw/openclaw:
  fix(config): persist explicit default values
  fix(google): default gemini onboarding to 3.1 pro
2026-05-10 14:26:55 +08:00
Peter Steinberger
2e400c5b76 fix(config): persist explicit default values
Fixes #79856.

Preserves explicitly set config values that equal runtime defaults across CLI set/patch, exported config writes, object paths, array-index paths, and normalized model paths. Rejects default-equal explicit writes under include-owned config instead of reporting a no-op success.

Co-authored-by: hclsys <hclsys@users.noreply.github.com>
2026-05-10 02:24:39 -04:00
Peter Steinberger
b27bae3a73 fix(google): default gemini onboarding to 3.1 pro 2026-05-10 07:24:03 +01:00
Vincent Koc
0eb6848c7c fix(plugins): explain disabled CLI command roots 2026-05-10 14:23:15 +08:00
Vincent Koc
89960cfcc9 fix(channels): keep guided add quiet before selection 2026-05-10 14:23:15 +08:00
Vincent Koc
be2f333e6f fix(cli): clarify terminal recovery errors 2026-05-10 14:23:15 +08:00
Peter Steinberger
acd882bde0 test: clear compact hooks broad matchers 2026-05-10 07:21:33 +01:00
Peter Steinberger
de186a8b66 fix(security): honor model tool denies in audit 2026-05-10 07:21:23 +01:00
Peter Steinberger
6d7fb9e15e fix(openrouter): add kimi k2.5 catalog fallback 2026-05-10 07:17:45 +01:00
Peter Steinberger
1d65f965e8 test: clear codex migration broad matchers 2026-05-10 07:14:08 +01:00
MkDev11
e37a3050d9 fix(agents): clean false-live session locks (#76854)
Summary:
- Clean false-live session locks whose live PID resolves to a non-OpenClaw owner.
- Tighten owner argv detection so generic JS entrypoints require an OpenClaw command token.
- Add regression coverage for generic non-OpenClaw entrypoints and preserve real gateway argv.

Verification:
- pnpm test src/agents/session-write-lock.test.ts src/commands/doctor-session-locks.test.ts
- pnpm test src/infra/gateway-process-argv.test.ts
- pnpm exec oxfmt --check --threads=1 src/agents/session-write-lock.ts src/agents/session-write-lock.test.ts src/commands/doctor-session-locks.ts src/commands/doctor-session-locks.test.ts docs/gateway/doctor.md CHANGELOG.md
- node scripts/run-oxlint.mjs src/agents/session-write-lock.ts src/agents/session-write-lock.test.ts src/commands/doctor-session-locks.ts src/commands/doctor-session-locks.test.ts
- CI workflow success on d42f9c46ef

Co-authored-by: mkdev11 <MkDev11@users.noreply.github.com>
2026-05-10 02:13:55 -04:00
Jeff
c919702b8f fix(moonshot): resolve moonshotai direct model refs
Summary:
- accept `moonshotai` and `moonshot-ai` as direct Moonshot provider aliases at runtime
- expose both aliases in the Moonshot manifest catalog
- add resolver/catalog regression coverage for #73876

Verification:
- `pnpm test src/agents/model-selection.test.ts src/agents/pi-embedded-runner/model.test.ts src/model-catalog/manifest-planner.test.ts`
- `pnpm test src/plugins/contracts/plugin-registration.moonshot.contract.test.ts`
- `git diff --check`
- `OPENCLAW_TESTBOX=0 pnpm check:changed`
2026-05-10 02:12:13 -04:00
Peter Steinberger
9dc5738bb5 test: clear host hook contract broad matchers 2026-05-10 07:10:06 +01:00
Ayaan Zaidi
a13d569f07 fix(browser): use OpenClaw temp dir for Chromium state 2026-05-10 11:37:37 +05:30
Ayaan Zaidi
082c932e94 fix(docker): export Playwright browser runtime path 2026-05-10 11:37:37 +05:30
Ayaan Zaidi
3050b1568d fix(browser): detect Playwright chrome-linux64 cache 2026-05-10 11:37:37 +05:30
Ayaan Zaidi
d40e062800 docs(browser): note Docker Chromium autodetect 2026-05-10 11:37:37 +05:30
Ayaan Zaidi
baa08dd5d1 fix(browser): detect Playwright Chromium cache 2026-05-10 11:37:37 +05:30
Peter Steinberger
8329958439 test: clear matrix cli broad matchers 2026-05-10 07:05:51 +01:00
Peter Steinberger
a9a70b6e60 fix(cron): allow self-scoped runs inspection
Co-authored-by: hclsys <hclsys@openclaw.ai>
2026-05-10 02:05:31 -04:00
bitking
be22a541ce fix(agents): reject blank model tool names before dispatch
Summary:
- Preserve id-based tool-name recovery for blank streamed calls.
- Reject final unrecoverable blank tool names before dispatch instead of inventing a callable `_blank` tool.
- Keep unrecoverable blank replay calls pruned.

Verification:
- pnpm test src/agents/pi-embedded-runner/run/attempt.test.ts src/agents/openai-transport-stream.test.ts
- git diff --check
- OPENCLAW_TESTBOX=0 pnpm check:changed

Fixes #34129.
Thanks @smartchainark.
2026-05-10 02:05:23 -04:00
Peter Steinberger
328952c6f5 fix(release): drop missing bundled runtime deps pack entry
Remove the nonexistent bundled runtime deps installer path from release packaging requirements and package files.\n\nThe original #74430 change was wrong because it required scripts/lib/bundled-runtime-deps-install.mjs without adding or generating that file, making npm pack validation impossible to satisfy.\n\nVerification:\n- pnpm test test/release-check.test.ts\n- package-files existence guard\n- Testbox tbx_01kr87j7wet04hw8v90htssege: pnpm build && pnpm ui:build && pnpm release:check
2026-05-10 02:04:52 -04:00
Vincent Koc
8055e1735f docs(matrix): remove bluebubbles changelog mention 2026-05-10 14:02:47 +08:00
Peter Steinberger
3d802cfa82 test: clear gateway server method broad matchers 2026-05-10 07:01:47 +01:00
Peter Steinberger
863fe90249 chore(installer): remove legacy cmd installer 2026-05-10 06:59:33 +01:00
Peter Steinberger
1cc354483c test: clear session status broad matchers 2026-05-10 06:58:32 +01:00
Peter Steinberger
555cfed534 test: clear openai transport stream broad matchers 2026-05-10 06:55:36 +01:00
Peter Steinberger
07df423557 fix(openrouter): honor model tool support metadata 2026-05-10 06:54:57 +01:00
Vincent Koc
a31b75f543 chore(channels): remove bluebubbles hangover 2026-05-10 13:53:58 +08:00
Peter Steinberger
681b56fc0a fix(openai): update realtime transcription session shape 2026-05-10 06:52:49 +01:00
Peter Steinberger
d4ba3615da test: clear configured plugin install broad matchers 2026-05-10 06:51:17 +01:00
TinyClaw
d580ec474c fix(telegram): show full OpenRouter model labels
Summary:\n- show provider-prefixed fallback labels for nested OpenRouter model ids in Telegram model picker\n- add regression coverage and changelog credit\n\nVerification:\n- pnpm test extensions/telegram/src/model-buttons.test.ts\n- OPENCLAW_TESTBOX=0 pnpm check:changed
2026-05-10 01:49:16 -04:00
Peter Steinberger
2c873af29c test: clear telegram delivery broad matchers 2026-05-10 06:45:40 +01:00
Peter Steinberger
eced12d091 test: reduce telegram delivery broad matchers 2026-05-10 06:43:31 +01:00
Peter Steinberger
dc3c5b048e test(release): isolate live thinking clamp fixture 2026-05-10 06:43:02 +01:00
Peter Steinberger
2f8cb86381 ci: skip symlinks in opengrep changed scan (#79930) 2026-05-10 01:40:56 -04:00
Gabriel Piss
5e874ed138 docs(outbound): add CLAUDE.md sibling symlink for AGENTS.md
Root AGENTS.md states: 'New AGENTS.md: add sibling CLAUDE.md symlink.'
src/infra/outbound/ had the guide but not the sibling symlink. Every
other scoped AGENTS.md in the repo already has one; this closes the
only real gap (the one remaining hit is an intentional test fixture in
extensions/oc-path/src/oc-path/tests/fixtures/real/).

Also adds CLAUDE.md to .semgrepignore so opengrep's PR-diff scan stops
trying to open the symlink as a regular file. Scanning the symlink is
redundant with scanning the underlying AGENTS.md.
2026-05-10 01:40:56 -04:00
Peter Steinberger
2eb07e68a1 fix(models): canonicalize auth default models 2026-05-10 06:40:42 +01:00
Peter Steinberger
2796eebb03 fix(installer): avoid literal path shellcheck suppression 2026-05-10 06:40:26 +01:00
Peter Steinberger
378da8b9d3 feat: add telegram mantis evidence builder 2026-05-10 06:39:54 +01:00
Peter Steinberger
572dd675d8 fix(models): repair provider-wrapped session overrides 2026-05-10 06:39:38 +01:00
Peter Steinberger
fe23f8803d test: clear pi model broad matchers 2026-05-10 06:36:37 +01:00
Peter Steinberger
936c02e22c fix(models): fail over OpenRouter budget-limit 403s 2026-05-10 06:34:39 +01:00
Peter Steinberger
1f74185364 test: refresh release validation expectations 2026-05-10 06:32:16 +01:00
Peter Steinberger
029f6b42e7 test: clear provider attribution broad matchers 2026-05-10 06:31:06 +01:00
Peter Steinberger
f43dc9aa61 fix(mcp): keep numeric bundle tool names provider-safe 2026-05-10 06:29:08 +01:00
Peter Steinberger
66a8ff178c ci(installer): add macOS install proof 2026-05-10 01:28:24 -04:00
Peter Steinberger
ccbf2dae17 test: clear gateway doctor broad matchers 2026-05-10 06:27:17 +01:00
Peter Steinberger
bf7cc278d2 fix(models): explain missing provider model registration 2026-05-10 06:25:32 +01:00
Peter Steinberger
74dc2a6830 test: clear acp manager broad matchers 2026-05-10 06:23:05 +01:00
Peter Steinberger
f1ced1961a fix(control-ui): serve namespaced public assets 2026-05-10 06:19:57 +01:00
Peter Steinberger
2a4d859ad0 test: clear task registry broad matchers 2026-05-10 06:19:10 +01:00
Peter Steinberger
53cd3daed3 fix(kimi): use stable coding model id 2026-05-10 06:17:58 +01:00
Peter Steinberger
e65017b0f9 docs(plugins): add clickclack reference 2026-05-10 06:13:38 +01:00
Peter Steinberger
9243b575ed chore(release): prepare 2026.5.10-beta.1 2026-05-10 06:13:38 +01:00
Ayaan Zaidi
a6eb95dc3a docs(telegram): add maintainer review notes 2026-05-10 10:43:16 +05:30
Peter Steinberger
8c49121ec8 fix(models): preserve explicit provider fallback selection 2026-05-10 06:12:41 +01:00
Peter Steinberger
844762e8f2 test: clear plugin install cli broad matchers 2026-05-10 06:12:15 +01:00
Peter Steinberger
7394792546 fix(models): hide openrouter nested provider duplicates 2026-05-10 06:08:39 +01:00
Peter Steinberger
0a387bfa69 test: clear clawhub broad matchers 2026-05-10 06:07:02 +01:00
Peter Steinberger
d83877ae2b docs: credit copilot token fix (#80074) 2026-05-10 01:05:59 -04:00
Andy Ye
c20450a82b fix(github-copilot): mint tokens with vscode chat identity 2026-05-10 01:05:59 -04:00
Peter Steinberger
6d89bf65e0 test: clear openai image broad matchers 2026-05-10 06:03:15 +01:00
Peter Steinberger
5d12774613 fix(agents): report anthropic 1m context 2026-05-10 06:02:49 +01:00
Peter Steinberger
f24814e32d test: clear feishu drive broad matchers 2026-05-10 05:56:39 +01:00
Peter Steinberger
7983fb0319 fix: type volcengine compat test 2026-05-10 05:56:31 +01:00
Peter Steinberger
743413aa6f fix: preserve auth profiles for one-off model overrides 2026-05-10 00:50:10 -04:00
Peter Steinberger
3678169952 fix: preserve exact wildcard provider models 2026-05-10 00:50:10 -04:00
Peter Steinberger
f7a14e678b fix: keep model visibility policy internal 2026-05-10 00:50:10 -04:00
Peter Steinberger
2d78c72e5e refactor: centralize model visibility policy 2026-05-10 00:50:10 -04:00
Peter Steinberger
743e543639 docs: mention provider wildcard model allowlists 2026-05-10 00:50:10 -04:00
Peter Steinberger
a6b833b8a6 fix: defer wildcard default rejection 2026-05-10 00:50:10 -04:00
Peter Steinberger
7f5728b4b2 fix: align wildcard model allowlist selection 2026-05-10 00:50:10 -04:00
80mills
f80a1c374f Fix agent command model-selection mock 2026-05-10 00:50:10 -04:00
80mills
2e495b07f3 Preserve provider wildcard allowlist intent 2026-05-10 00:50:10 -04:00
80mills
f0ed2b5229 Fix wildcard allowed catalog visibility 2026-05-10 00:50:10 -04:00
80mills
ebd776298f Add provider wildcard model visibility 2026-05-10 00:50:10 -04:00
Peter Steinberger
9189f8ea85 test: tighten feishu drive comment assertions 2026-05-10 05:49:57 +01:00
Peter Steinberger
b97cb15b07 fix(deepseek): backfill v4 reasoning for proxy models 2026-05-10 05:48:02 +01:00
Peter Steinberger
8faf133620 fix(volcengine): strip unsupported tool schema keywords 2026-05-10 05:48:01 +01:00
Peter Steinberger
acd8d38c1f test: clear feishu media broad matchers 2026-05-10 05:47:20 +01:00
Ayaan Zaidi
1b38f80088 fix(telegram): cool down unhealthy transports 2026-05-10 10:16:59 +05:30
Peter Steinberger
60967c3a47 fix(docker): raise build heap limit 2026-05-10 05:45:53 +01:00
Peter Steinberger
9c20f43520 test: clear feishu bot broad matchers 2026-05-10 05:43:03 +01:00
Peter Steinberger
549693ffcb fix(installer): promote persisted PATH entries 2026-05-10 05:40:38 +01:00
Peter Steinberger
91522b5534 test: tighten feishu bot media assertions 2026-05-10 05:37:42 +01:00
Kevin Lin
b79de62b3c fix(codex): remove dynamic tools profile option 2026-05-09 21:34:33 -07:00
Peter Steinberger
9f028e9942 test: tighten feishu bot assertions 2026-05-10 05:34:07 +01:00
Peter Steinberger
78e4330fb2 fix: type xai runtime thinking levels 2026-05-10 05:34:07 +01:00
Val Alexander
dafbdb6f20 fix: preserve shared macOS and CLI device identities
Fixes #76815.

- Teach the Swift macOS identity store to load TypeScript PEM identity files without regenerating device IDs.
- Teach the TypeScript identity store to migrate legacy Swift raw-key identities to PEM after validating key material.
- Preserve recognized invalid identity files instead of clobbering them, preventing repeated pairing churn while retaining diagnostic evidence.
- Align the macOS wizard CLI with the generated protocol model.

Reported by @aboundTechOlogy.
Thanks @BunsDev.
2026-05-09 23:32:33 -05:00
Peter Steinberger
4c1e6ba2f0 test: clear browser tool broad matchers 2026-05-10 05:28:31 +01:00
Peter Steinberger
7504fc3a47 fix(xai): pass grok reasoning controls
Co-authored-by: Colin McIntosh <4840146+colinmcintosh@users.noreply.github.com>
2026-05-10 05:28:00 +01:00
Peter Steinberger
cb207f97c9 test(installer): avoid login shell PATH noise 2026-05-10 05:26:53 +01:00
Brandon Zarnitz
86b53aa2ca fix(telegram): suppress silent-reply rewrite in DM no-response turns (#78188)
When a Telegram turn ends with no visible final response, the dispatcher synthesized a NO_REPLY payload that silent-reply rewrite could turn into visible DM chatter such as "All quiet on my side."

Gate that synthesized fallback on group chats. DMs with no queued final response now stay quiet, while group/forum fallback behavior remains available when policy asks for a visible rewrite.

Tests:
- pnpm test extensions/telegram/src/bot-message-dispatch.test.ts
- pnpm check:changed
2026-05-10 09:56:00 +05:30
Peter Steinberger
932e436250 test: tighten browser tool assertions 2026-05-10 05:24:11 +01:00
Peter Steinberger
2fb99143a4 fix(openai): use chat completion choice delta type 2026-05-10 05:23:55 +01:00
Peter Steinberger
808d268634 test(installer): source guarded shell rc in wrapper 2026-05-10 05:21:32 +01:00
Peter Steinberger
40aa57ba8f fix(openai): accept realtime event aliases 2026-05-10 05:20:52 +01:00
Peter Steinberger
ff045ea9ca fix(installer): silence node activation wrapper shellcheck (#80094) 2026-05-10 00:19:00 -04:00
Peter Steinberger
a0fb7fb045 refactor: centralize channel ingress access 2026-05-10 00:18:36 -04:00
Peter Steinberger
1725eebe62 fix(openai): handle json streaming fallbacks 2026-05-10 05:16:12 +01:00
Peter Steinberger
2a257f5228 fix: type reasoning compat transcript policy 2026-05-10 05:15:57 +01:00
Peter Steinberger
8e5c79ab55 fix: normalize nested google model config ids 2026-05-10 05:15:57 +01:00
Colin
6481021763 fix: pass config to google meet realtime bridge 2026-05-10 00:13:23 -04:00
Colin
ed4012642a docs: credit realtime voice contributor 2026-05-10 00:13:23 -04:00
Colin
d5893d99d0 fix: keep realtime OAuth off custom endpoints 2026-05-10 00:13:23 -04:00
Colin
a77d2c142c fix: address realtime voice review feedback 2026-05-10 00:13:23 -04:00
Colin
7a2a31dede feat: add realtime voice OAuth controls 2026-05-10 00:13:23 -04:00
Peter Steinberger
cd58e46223 test: tighten command explainer assertions 2026-05-10 05:12:47 +01:00
Peter Steinberger
e1ced53ac3 fix(installer): satisfy shellcheck promotion wrapper 2026-05-10 05:12:44 +01:00
Peter Steinberger
2fcfc647b3 ci: rebase website installer sync before push (#80092) 2026-05-10 00:11:12 -04:00
Peter Steinberger
207bcd6b20 fix(installer): persist Linux supported PATH 2026-05-10 05:10:17 +01:00
Peter Steinberger
aac9ebd4f3 fix: prune stale generated declarations before tsdown build 2026-05-10 05:09:26 +01:00
Peter Steinberger
428cc54164 fix(anthropic): backfill haiku api key allowlist 2026-05-10 05:09:12 +01:00
Peter Steinberger
57020daeb4 fix(agents): drop unsupported anthropic thinking replay 2026-05-10 05:09:12 +01:00
Peter Steinberger
1b3809430c test: clear chat directive broad matchers 2026-05-10 05:08:40 +01:00
Peter Steinberger
05d5a940ec docs: add session kill changelog (#72439) 2026-05-10 00:05:40 -04:00
Ruben Cuevas
83abb72aac fix(gateway): reject malformed session kill paths 2026-05-10 00:05:40 -04:00
Peter Steinberger
7036e8f681 test: tighten chat directive route assertions 2026-05-10 05:04:59 +01:00
Peter Steinberger
5f0ec8053a test: clear feishu outbound broad matchers 2026-05-10 05:01:35 +01:00
Peter Steinberger
f83dbbc926 fix(discord): prevent realtime answer replacement 2026-05-10 05:01:19 +01:00
Peter Steinberger
83a108080d fix: canonicalize embedded reply payloads
Fixes #79621. Fixes #79986.
2026-05-10 00:00:07 -04:00
Peter Steinberger
7b3805fff2 test: tighten feishu outbound comment assertions 2026-05-10 04:59:47 +01:00
Peter Steinberger
d6a5690ea5 ci: use Node 24 for website installer sync (#80090) 2026-05-09 23:59:15 -04:00
Peter Steinberger
76b64d76b5 test: tighten feishu outbound card assertions 2026-05-10 04:56:33 +01:00
Peter Steinberger
4f053b8704 docs: add changelog for gateway log redaction (#76306) (thanks @rubencu) 2026-05-09 23:55:37 -04:00
Ruben Cuevas
d0bba218e4 fix(gateway): redact fast-path console logs 2026-05-09 23:55:37 -04:00
Ruben Cuevas
c61abfab30 docs(memory): clarify memory maintenance expectations 2026-05-09 23:53:37 -04:00
Peter Steinberger
d30011062f test: clear gateway send broad matchers 2026-05-10 04:53:07 +01:00
Peter Steinberger
3daf4cbd55 test: clear update cli broad matchers 2026-05-10 04:51:03 +01:00
Peter Steinberger
997edf66a1 fix(openai): respect disabled realtime input interruption 2026-05-10 04:50:29 +01:00
Peter Steinberger
e60928d13c ci: verify and sync website installers (#80067)
* ci: verify and sync website installers

* test: fix pi runner boundary test type cast

* fix(installer): scope Windows legacy cleanup to git checkout

* ci: install curl for minimal install-cli smoke

* fix(installer): promote supported Linux node after install

* test(cli): align command hint expectations

* fix(installer): avoid shellcheck warning in node promotion

* fix(installer): sync Linux path hardening

* ci: raise build artifact testbox heap

* test(installer): align PowerShell installer tests
2026-05-09 23:48:49 -04:00
Peter Steinberger
71ebedee95 test: tighten update cli post core assertions 2026-05-10 04:45:50 +01:00
Peter Steinberger
1f99cddb61 test: tighten update cli spawn assertions 2026-05-10 04:44:14 +01:00
Peter Steinberger
e07febd075 fix: repair model media probes 2026-05-10 04:42:01 +01:00
Peter Steinberger
f81cfc0501 test: tighten gateway send scope assertions 2026-05-10 04:41:18 +01:00
Peter Steinberger
7458f41e70 test: tighten gateway send media assertions 2026-05-10 04:40:05 +01:00
Peter Steinberger
829fae4ef0 test: clear plugin update broad matchers 2026-05-10 04:38:23 +01:00
Peter Steinberger
183615145e test: tighten plugin update installer assertions 2026-05-10 04:36:20 +01:00
Peter Steinberger
5e332e1d58 test: tighten plugin update fallback assertions 2026-05-10 04:34:44 +01:00
Peter Steinberger
4a6bf45422 fix(discord): log realtime voice barge-in diagnostics 2026-05-10 04:33:32 +01:00
Peter Steinberger
d428822d01 test: tighten plugin update outcome assertions 2026-05-10 04:33:23 +01:00
Peter Steinberger
e0142c6cd7 test: tighten plugin update npm assertions 2026-05-10 04:31:46 +01:00
Peter Steinberger
069ac6ca82 test: clear capability broad matchers 2026-05-10 04:29:54 +01:00
Ayaan Zaidi
32f5e01a30 docs(changelog): note Telegram select callback fix (#79816) (thanks @moeedahmed) 2026-05-10 08:59:39 +05:30
Ayaan Zaidi
175c42eacd fix(telegram): tighten select callback handling 2026-05-10 08:59:39 +05:30
Moeed Ahmed
3c5e68e80f fix: bound subagent completion context 2026-05-10 08:59:39 +05:30
Moeed Ahmed
243618e804 fix: handle telegram select callbacks safely 2026-05-10 08:59:39 +05:30
Peter Steinberger
f1d935d39f test: tighten capability generation assertions 2026-05-10 04:27:26 +01:00
Peter Steinberger
85c023bce3 test: tighten capability gateway assertions 2026-05-10 04:25:31 +01:00
Peter Steinberger
dec13eb5d8 test: tighten capability model assertions 2026-05-10 04:23:33 +01:00
Peter Steinberger
1bb583c41e test: clear dispatch broad matchers 2026-05-10 04:21:01 +01:00
Peter Steinberger
fc5fe8dd51 test: tighten dispatch plugin binding assertions 2026-05-10 04:18:54 +01:00
Ayaan Zaidi
6bf9185d27 fix(telegram): gate media dedup on visible delivery 2026-05-10 08:47:04 +05:30
Roger Deng
22e564da4b fix(telegram): track block media only after successful delivery
Move sentBlockMediaUrls recording from before sends to after successful
delivery completion. If a block send throws, the URL is not recorded,
so final fallback delivery retains the media attachment instead of
incorrectly deduplicating it.

Add regression tests for both success-path dedup and failure-path
media preservation.

Addresses ClawSweeper P2: block-failure → final-media-loss.
2026-05-10 08:47:04 +05:30
Roger Deng
bc3fd5bf0f fix(telegram): clear legacy mediaUrl when all mediaUrls deduped 2026-05-10 08:47:04 +05:30
Roger Deng
b5af229172 fix(telegram): use generic type in deduplicateBlockSentMedia
Preserve the full ReplyPayload type through deduplication so that
channelData and other properties are not lost.
2026-05-10 08:47:04 +05:30
Roger Deng
8ff38c0988 fix(telegram): deduplicate MEDIA attachments in non-streaming mode
Non-streaming Telegram delivers each MEDIA: attachment twice — once
from the media-only block reply and once from the final reply. Track
media URLs sent via block replies and filter duplicates from final
replies.

Closes #78372
2026-05-10 08:47:04 +05:30
Peter Steinberger
4e09538f44 test: tighten dispatch hook metadata assertions 2026-05-10 04:16:04 +01:00
Hua Yang
dff4a04c1f feat(signal): support container REST API
Adds container REST/WebSocket support for bbernhard/signal-cli-rest-api Signal deployments.

Closes #10240.

Thanks @Hua688.

Verification:
- pnpm exec oxfmt --check --threads=1 docs/channels/signal.md
- pnpm lint:extensions
- pnpm test extensions/signal
- pnpm tsgo:extensions && pnpm tsgo:test:extensions
- pnpm config:docs:check
- git diff --check
- CI checks on PR head 1d0a536ecd
- Crabbox/Testbox live Docker smoke tbx_01kr7h07shhcafxjc0ezfh946w / run 25614453516
2026-05-09 23:13:55 -04:00
Peter Steinberger
7af50ce47b test: tighten dispatch acp binding assertions 2026-05-10 04:13:30 +01:00
Peter Steinberger
fe645767d7 test: tighten dispatch acp lifecycle assertions 2026-05-10 04:12:09 +01:00
Peter Steinberger
b395285afb test: tighten dispatch tool progress assertions 2026-05-10 04:10:43 +01:00
Val Alexander
8ead938c7c Fix chat-channel node exec approval replays
Fixes #77656.

Summary:
- Carry chat turn-source metadata through approved async host=node replays.
- Bind trusted backend replay to node, command, session, agent, and chat target metadata instead of transient WebSocket connection ids.
- Cover Telegram and WeCom-style reconnect replay plus denial cases with gateway, websocket, and agent tests.
- Carry the current-main CLI help assertion fix needed to clear exact-head CI after the rebase.

Verification:
- pnpm test src/gateway/node-invoke-system-run-approval.test.ts src/gateway/server.node-invoke-approval-bypass.test.ts src/agents/bash-tools.exec-host-node.test.ts -- --reporter=verbose
- pnpm test src/cli/channel-auth.test.ts src/cli/plugins-cli.policy.test.ts src/cli/command-registration-policy.test.ts -- --reporter=verbose
- pnpm check:changed
- GitHub CI passed on d1392a873c
- ClawSweeper re-review completed on the approval replay head
2026-05-09 22:10:21 -05:00
Peter Steinberger
392ce6d8d8 test: tighten dispatch cross channel assertions 2026-05-10 04:09:08 +01:00
Jordan Baker
86c1622a3a fix(acp): propagate AcpRuntimeError detail through lifecycle boundary
Summary:
- Preserve AcpRuntimeError detail across the ACP lifecycle boundary.
- Redact non-Error lifecycle failure strings and add gateway/agent propagation coverage.
- Align rebased CLI command-hint formatting with current main.

Verification:
- pnpm check:test-types
- pnpm test src/acp/runtime/errors.test.ts src/agents/command/attempt-execution.error-propagation.test.ts src/gateway/server.agent.gateway-server-agent-b.test.ts
- CI exact head c96d63298b green

Co-authored-by: Jordan Baker <23538+hexsprite@users.noreply.github.com>
2026-05-09 23:08:30 -04:00
Peter Steinberger
f9f9633bc5 test: tighten dispatch route assertions 2026-05-10 04:07:43 +01:00
Peter Steinberger
d88f7ab637 test: tighten migrate json apply assertions 2026-05-10 04:05:30 +01:00
Peter Steinberger
4b6cb9e9bc fix(cli): keep plugin help registration reachable 2026-05-10 04:03:45 +01:00
Peter Steinberger
aafadd45a5 test: tighten migrate skip selection assertions 2026-05-10 04:03:32 +01:00
Peter Steinberger
67634a1e5a test: tighten migrate conflict selection assertions 2026-05-10 04:02:06 +01:00
Peter Steinberger
bbddd801c4 test: tighten migrate plugin selection assertions 2026-05-10 04:00:56 +01:00
Peter Steinberger
e2bbbf8879 test: tighten migrate skill selection assertions 2026-05-10 03:59:29 +01:00
Ayaan Zaidi
5eaed7d8dd docs(changelog): mention telegram partial previews (#80045) (thanks @TurboTheTurtle) 2026-05-10 08:29:19 +05:30
Ayaan Zaidi
1367ec7461 fix(telegram): use partial stream deltas 2026-05-10 08:29:19 +05:30
Andy Ye
512a26c29b fix telegram partial progress coalescing 2026-05-10 08:29:19 +05:30
Andy Ye
0a4ef37f65 fix telegram partial draft fragments 2026-05-10 08:29:19 +05:30
Peter Steinberger
487687a6f0 build(discord): skip native opus builds by default (#80071) 2026-05-09 22:59:09 -04:00
Andrew Cunliffe
048ca8c765 fix(telegram): suppress 'no extra answer' placeholder when reply is in flight (#78929) 2026-05-10 08:28:31 +05:30
Peter Steinberger
fa2ffa6fbe test: tighten outbound hook error assertions 2026-05-10 03:57:19 +01:00
Peter Steinberger
9cf0651e46 test: tighten outbound queue persistence assertions 2026-05-10 03:54:12 +01:00
Peter Steinberger
c0b94fd075 ci(release): pass OpenAI install e2e env 2026-05-10 03:53:04 +01:00
Peter Steinberger
b3f4fb8f8f test: tighten outbound chunk config assertions 2026-05-10 03:52:24 +01:00
Peter Steinberger
e8b3ff7891 test: tighten outbound media delivery assertions 2026-05-10 03:51:10 +01:00
Peter Steinberger
d644798d67 test: tighten outbound runtime payload assertions 2026-05-10 03:48:46 +01:00
Peter Steinberger
467b0f87ff test: tighten outbound media policy assertions 2026-05-10 03:47:09 +01:00
Peter Steinberger
972b3c673a test: tighten outbound diagnostic assertions 2026-05-10 03:45:05 +01:00
Peter Steinberger
7d38acbbbf test: tighten outbound adapter assertions 2026-05-10 03:43:25 +01:00
Peter Steinberger
c7c7e2b94e fix(cli): restore terminal guidance typecheck 2026-05-09 22:41:25 -04:00
Linux2010
d6881962a3 fix(media): allow buffer-verified ZIP archives in host-read validator
Host-local media sends were rejecting ZIP attachments with the error
'Host-local media sends only allow buffer-verified images, audio, video,
PDF, and Office documents (got application/zip)'.

This adds application/zip to the HOST_READ_ALLOWED_DOCUMENT_MIMES set,
enabling agents to send ZIP files via the message tool. ZIP files are
validated by file-type magic bytes detection, ensuring they are genuine
archives rather than disguised executables.

Fixes #78057 (regression from v2026.4.23 to v2026.5.2).
2026-05-09 22:41:25 -04:00
Peter Steinberger
72e17c17ae test: tighten qa matrix gateway cli assertions 2026-05-10 03:40:42 +01:00
Peter Steinberger
337148a821 test: tighten qa matrix recovery cli assertions 2026-05-10 03:37:55 +01:00
Peter Steinberger
cb60a06c9e test: tighten qa matrix encryption cli assertions 2026-05-10 03:36:11 +01:00
Peter Steinberger
9b8a6040a5 test: tighten qa matrix account add assertions 2026-05-10 03:34:14 +01:00
Peter Steinberger
968732019a test: tighten qa matrix cli assertions 2026-05-10 03:33:02 +01:00
Peter Steinberger
526da2d919 test: tighten qa matrix e2ee trust assertions 2026-05-10 03:31:01 +01:00
Peter Steinberger
d9cb393f4e test: tighten qa matrix e2ee assertions 2026-05-10 03:29:29 +01:00
Vincent Koc
0c8bca4500 fix(cli): keep root help pluginless by default 2026-05-10 10:28:48 +08:00
Vincent Koc
e855b9c8d9 fix(cli): skip proxy config for help 2026-05-10 10:28:48 +08:00
Vincent Koc
074161415b fix(cli): keep help banner configless 2026-05-10 10:28:48 +08:00
Vincent Koc
f13dfd6004 docs(cli): align setup command hierarchy 2026-05-10 10:28:48 +08:00
Vincent Koc
be1c38e692 fix(cli): improve terminal error guidance 2026-05-10 10:28:47 +08:00
Vincent Koc
6811ef058b fix(cli): keep help paths configless 2026-05-10 10:28:47 +08:00
Peter Steinberger
7d481b1fe9 test: tighten qa matrix room assertions 2026-05-10 03:27:59 +01:00
Peter Steinberger
8e8f7915b2 test: tighten qa matrix dm notice assertions 2026-05-10 03:26:33 +01:00
Peter Steinberger
57bc5f14d6 docs: update changelog for browser status probe (#77473) (thanks @rubencu) 2026-05-09 22:26:16 -04:00
Ruben Cuevas
f654f2f353 fix(browser): extend existing-session status probe 2026-05-09 22:26:16 -04:00
Peter Steinberger
a05f185366 test: tighten qa matrix media assertions 2026-05-10 03:24:35 +01:00
Peter Steinberger
79d281358e test: tighten qa matrix tool progress assertions 2026-05-10 03:22:59 +01:00
Peter Steinberger
2e23be7f18 test: tighten qa matrix preview assertions 2026-05-10 03:21:45 +01:00
Peter Steinberger
ba24dd9184 test: tighten qa matrix subagent assertions 2026-05-10 03:20:12 +01:00
Peter Steinberger
9ff66b0942 test: tighten qa matrix dm assertions 2026-05-10 03:19:05 +01:00
Peter Steinberger
a04ab3e27b test: tighten qa matrix restart resume assertions 2026-05-10 03:17:53 +01:00
Peter Steinberger
05f82f619f test: tighten qa matrix sync loss assertions 2026-05-10 03:15:48 +01:00
Peter Steinberger
cf679e5dec test: tighten qa matrix stale sync assertions 2026-05-10 03:14:15 +01:00
Ayaan Zaidi
760160c641 refactor(telegram): simplify chat action coalescing 2026-05-10 07:43:35 +05:30
VACInc
f5ad8e5b53 fix telegram topic bottleneck 2026-05-10 07:43:35 +05:30
Peter Steinberger
e349a237d5 docs: add fallback delivery changelog (#80009) 2026-05-09 22:12:33 -04:00
Andy Ye
2e38e92229 fix fallback timeout response delivery 2026-05-09 22:12:33 -04:00
Peter Steinberger
93e8389148 test: tighten qa matrix restart assertions 2026-05-10 03:11:21 +01:00
Peter Steinberger
49883acb12 fix(slack): suppress socket mode ping timeout noise 2026-05-10 03:10:34 +01:00
Peter Steinberger
206bad2227 test: tighten qa matrix hot reload assertions 2026-05-10 03:09:40 +01:00
Peter Steinberger
50cc8488e8 test: tighten qa matrix allowbot assertions 2026-05-10 03:08:20 +01:00
Peter Steinberger
cd08b88c8b test: tighten qa matrix observer assertions 2026-05-10 03:07:12 +01:00
Peter Steinberger
cf41bb9bc1 test: tighten qa matrix artifact assertions 2026-05-10 03:05:38 +01:00
Peter Steinberger
62070fd717 docs: update changelog for exec approvals (#76943) 2026-05-09 22:05:09 -04:00
Ruben Cuevas
fd5c5467e0 fix(exec-approvals): lazy-load command explainer 2026-05-09 22:05:09 -04:00
Peter Steinberger
c8d82e4535 ci(release): raise build heap for validation gates 2026-05-10 03:03:55 +01:00
Peter Steinberger
e3e60ad7c2 test: tighten diagnostics content assertions 2026-05-10 03:03:38 +01:00
Kevin Lin
ce0584af89 docs: reorganize Codex harness docs (#80029)
* docs: reorganize codex harness docs

* docs: address codex harness review findings

* docs: move codex references to reference nav

* docs: add codex topic configuration section
2026-05-09 19:02:50 -07:00
Peter Steinberger
28cc60f13c test: tighten diagnostics delivery assertions 2026-05-10 03:02:19 +01:00
Peter Steinberger
a08f765fc7 test: tighten diagnostics unparented lifecycle assertions 2026-05-10 03:00:46 +01:00
Peter Steinberger
5051b10f44 test: tighten diagnostics lifecycle parent assertions 2026-05-10 02:59:44 +01:00
Peter Steinberger
5f0eb12442 test: tighten diagnostics memory assertions 2026-05-10 02:58:40 +01:00
Peter Steinberger
265167daa5 test: tighten diagnostics context assembly assertions 2026-05-10 02:57:31 +01:00
Peter Steinberger
b1f3a717c9 docs: update changelog for exec failure warning (#80003) 2026-05-09 21:57:11 -04:00
Jayesh Betala
658a30b42f fix(agents): surface exec failures after claimed success 2026-05-09 21:57:11 -04:00
Peter Steinberger
06f15b6f9a test: tighten diagnostics genai assertions 2026-05-10 02:55:54 +01:00
Peter Steinberger
f8fee34aef ci(release): stabilize full validation gates 2026-05-10 02:54:37 +01:00
Peter Steinberger
7bb2712dc6 test: tighten diagnostics failover assertions 2026-05-10 02:54:27 +01:00
Peter Steinberger
49b9b021ea test: tighten diagnostics context metric assertions 2026-05-10 02:53:10 +01:00
Peter Steinberger
86c9ea8347 test: tighten diagnostics context span assertions 2026-05-10 02:51:44 +01:00
Peter Steinberger
87d90505a1 test: tighten diagnostics model usage assertions 2026-05-10 02:50:05 +01:00
Peter Steinberger
026d9e9aa7 test: tighten diagnostics histogram assertions 2026-05-10 02:48:33 +01:00
Peter Steinberger
eda0316af3 fix: classify active memory no-relevant status (#80015)
Recreated locally from PR #80015 because the contributor branch could not be updated by maintainers (maintainerCanModify=false).

Fixes #79812.

Co-authored-by: Andy Ye <andy@Andys-MacBook-Pro-2.local>
2026-05-10 02:47:41 +01:00
Peter Steinberger
64b5b9796d test: update codex prompt snapshots 2026-05-09 21:47:14 -04:00
Peter Steinberger
f7a6b9b5a1 fix: preserve subagent target precedence 2026-05-09 21:47:14 -04:00
Peter Steinberger
c09f790732 fix: guard subagent yield guidance 2026-05-09 21:47:14 -04:00
Peter Steinberger
eacdfbc84b feat: improve subagent orchestration 2026-05-09 21:47:14 -04:00
Peter Steinberger
5b16c47828 test: tighten diagnostics log context assertions 2026-05-10 02:46:38 +01:00
Peter Steinberger
0e4a2c8c7f test: tighten diagnostics liveness assertions 2026-05-10 02:45:25 +01:00
Peter Steinberger
fb2f5526a4 ci: raise build artifact heap 2026-05-10 02:44:44 +01:00
Peter Steinberger
dabebdb160 test: tighten diagnostics exporter assertions 2026-05-10 02:43:10 +01:00
Peter Steinberger
f59cb4d6d7 test: tighten diagnostics span option assertions 2026-05-10 02:41:24 +01:00
Vincent Koc
69c29a8c45 fix(cli): restore hatch agent wording 2026-05-10 09:40:24 +08:00
Peter Steinberger
eae1ffdf4a test: tighten codex app-server policy assertions 2026-05-10 02:39:54 +01:00
Peter Steinberger
7eac2f8c77 test: tighten codex plugin recovery assertions 2026-05-10 02:38:07 +01:00
Peter Steinberger
359fc173e7 ci(release): honor Open WebUI smoke mode 2026-05-10 02:36:55 +01:00
Peter Steinberger
21debd2347 test: tighten codex plugin config assertions 2026-05-10 02:36:41 +01:00
Peter Steinberger
3c9173259a test: tighten codex binding restart assertions 2026-05-10 02:35:20 +01:00
Peter Steinberger
78384fc260 test: tighten codex app enable assertions 2026-05-10 02:33:13 +01:00
Peter Steinberger
f2d9e23c70 test: tighten codex app policy assertions 2026-05-10 02:31:40 +01:00
Peter Steinberger
e9ee7b6aa3 test: tighten codex completion assertions 2026-05-10 02:30:07 +01:00
Peter Steinberger
61a5fc9a9a test: tighten codex queued input assertions 2026-05-10 02:28:47 +01:00
Peter Steinberger
c6183abb33 test: tighten codex hook failure assertions 2026-05-10 02:26:29 +01:00
Peter Steinberger
11ea53eb28 test: tighten codex failed turn assertions 2026-05-10 02:24:40 +01:00
Peter Steinberger
38fe4d36c6 fix(discord): suppress stale realtime consults 2026-05-10 02:23:25 +01:00
Peter Steinberger
2d0dca7882 test: tighten codex relay resume assertions 2026-05-10 02:23:07 +01:00
Peter Steinberger
3d2155da1d test: tighten codex native hook relay assertions 2026-05-10 02:21:17 +01:00
Peter Steinberger
b5ca9e85bf docs: update changelog for Talk realtime instructions (#79081) 2026-05-09 21:20:06 -04:00
VACInc
c5cc1bb184 Enable realtime Talk instructions config 2026-05-09 21:20:06 -04:00
Peter Steinberger
1463974c46 test: tighten codex prompt hook assertions 2026-05-10 02:19:05 +01:00
Peter Steinberger
26e117cef1 fix: preserve requested gateway scopes (#78837) (thanks @VACInc) 2026-05-09 21:18:05 -04:00
VACInc
1d910cc4fb fix agent model override gateway scope 2026-05-09 21:18:05 -04:00
Peter Steinberger
26753f1431 test: tighten codex terminal watchdog assertions 2026-05-10 02:15:43 +01:00
Peter Steinberger
0255323621 docs: credit diffs ttl fix (#77456) (thanks @VACInc) 2026-05-09 21:15:22 -04:00
VACInc
852757ad2f fix(diffs): restore viewer ttl config 2026-05-09 21:15:22 -04:00
Peter Steinberger
c2af1ea10c build: refresh canvas asset hash 2026-05-10 02:14:41 +01:00
Peter Steinberger
5131c3d677 build: clean tsdown declaration warnings 2026-05-10 02:14:40 +01:00
Peter Steinberger
6d1a7169da fix(whatsapp): support Baileys rc10 postinstall patch 2026-05-10 02:14:40 +01:00
Peter Steinberger
0496063264 build(deps): refresh workspace dependency pins 2026-05-10 02:14:40 +01:00
Peter Steinberger
f6e2ad07ec ci(release): normalize Windows loader npm paths 2026-05-10 02:14:00 +01:00
Peter Steinberger
063ada7809 test(release): pin Codex live harness runtime 2026-05-10 02:14:00 +01:00
Peter Steinberger
8065f36bee test: tighten codex run attempt watchdog assertions 2026-05-10 02:13:39 +01:00
Peter Steinberger
3bd64d60df test: tighten codex run attempt tool events 2026-05-10 02:11:50 +01:00
Peter Steinberger
b426422332 test: tighten codex run attempt dynamic assertions 2026-05-10 02:10:12 +01:00
Peter Steinberger
c16fabab5d test: tighten onboarding plugin install assertions 2026-05-10 02:07:41 +01:00
Peter Steinberger
6a6e922033 test: tighten gateway onboarding assertions 2026-05-10 02:04:48 +01:00
brokemac79
48f51c1a51 fix: align xai tool auth profiles 2026-05-09 21:02:40 -04:00
Peter Steinberger
7376b27746 test(release): configure Codex live dev agent 2026-05-10 02:02:35 +01:00
Peter Steinberger
4eecdd8b47 test: tighten gateway status assertions 2026-05-10 02:01:20 +01:00
Peter Steinberger
4aa2f91a78 test: tighten doctor config flow assertions 2026-05-10 02:00:01 +01:00
Peter Steinberger
8f27421922 test: tighten shared status scan assertions 2026-05-10 01:58:37 +01:00
pashpashpash
e391f66801 Keep migrated OpenAI Codex OAuth runs on native Codex auth (#80017)
* fix: bind codex oauth metadata to plugin harness runs

* fix: scope codex harness auth metadata
2026-05-10 09:56:10 +09:00
Peter Steinberger
f3f644a6b9 test: tighten agent delivery assertions 2026-05-10 01:54:51 +01:00
Peter Steinberger
9b2f947b4c test: tighten cron migration assertions 2026-05-10 01:52:49 +01:00
Peter Steinberger
2097447426 test: tighten model auth assertions 2026-05-10 01:50:51 +01:00
brokemac79
864cd1444b fix(feishu): keep group context on chat target 2026-05-09 20:50:12 -04:00
Peter Steinberger
a1b89317a8 fix(ollama): keep DeepSeek cloud thinking enabled 2026-05-10 01:49:43 +01:00
brokemac79
877eae9b58 fix(qqbot): preserve framework command source 2026-05-09 20:49:23 -04:00
Peter Steinberger
2a6239084f test(release): route Codex live slash checks through chat 2026-05-10 01:48:07 +01:00
Peter Steinberger
c9eeb2d48c test: tighten doctor state integrity assertions 2026-05-10 01:46:37 +01:00
samzong
d832ad214c [Feat] Add upload archive install RPC (#74430)
* feat(skills): add upload archive install RPC

- src/agents/skills-archive-install.ts:83 [BOT-SCOPE]: `withExtractedArchiveRoot()` still returns unstructured extract failures, so exact transient-vs-terminal classification should be moved into the shared install-flow layer in a follow-up rather than expanding this PR.

Signed-off-by: samzong <samzong.lu@gmail.com>

* fix(skills): address archive upload review findings

Signed-off-by: samzong <samzong.lu@gmail.com>

* fix(skills): regen protocol bindings and classify transient archive errors

* feat: gate uploaded skill installs by config

* test: add docker skill install proof

* docs: clarify uploaded skill archive gate

* chore: refresh config docs baseline

* style: format docker e2e plan test

* fix: use fs-safe path checks for skill archives

* fix: classify skill publish failures as unavailable

* test: update skill clawhub path mock

* fix: pass mutable archive root markers

* fix: use current json dir mode option

* test: satisfy skill upload lint

* test: refresh core support expectations

---------

Signed-off-by: samzong <samzong.lu@gmail.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-09 20:44:18 -04:00
Peter Steinberger
8073c95a5a test: tighten message command assertions 2026-05-10 01:42:58 +01:00
Peter Steinberger
342076b4c0 test: tighten release plugin install assertions 2026-05-10 01:40:52 +01:00
brokemac79
af69e78901 fix image generation provider discovery 2026-05-09 20:40:31 -04:00
Peter Steinberger
099d773f23 test: tighten sessions cleanup assertions 2026-05-10 01:39:05 +01:00
Peter Steinberger
19bc6ae3be test: tighten agent command assertions 2026-05-10 01:37:21 +01:00
Peter Steinberger
aaeb64bec4 test(release): update Docker smoke command assertion 2026-05-10 01:36:16 +01:00
Peter Steinberger
5d0045786b test: tighten doctor repair sequencing assertions 2026-05-10 01:35:32 +01:00
Peter Steinberger
77d608d02a test: tighten agents delete assertions 2026-05-10 01:34:27 +01:00
Peter Steinberger
0e66d6ae11 test: tighten legacy config migration assertions 2026-05-10 01:32:24 +01:00
Peter Steinberger
b10c98854d test: tighten gateway daemon flow assertions 2026-05-10 01:31:02 +01:00
Peter Steinberger
5832839353 ci(release): make Open WebUI release smoke deterministic 2026-05-10 01:30:07 +01:00
Peter Steinberger
10caa76473 fix: drop stale managed plugin install records 2026-05-10 01:29:56 +01:00
Peter Steinberger
0f66f21e62 test: tighten status json runtime assertions 2026-05-10 01:26:23 +01:00
Peter Steinberger
b288b81fef docs: credit status diagnostics contributor (#78128) 2026-05-09 20:24:41 -04:00
brokemac79
89c0ccce28 docs(changelog): drop duplicate gateway shutdown entry 2026-05-09 20:24:41 -04:00
brokemac79
e71589a14b test(ports): accept expected gateway bind 2026-05-09 20:24:41 -04:00
brokemac79
3dec1b3267 fix(status): accept expected gateway bind listeners 2026-05-09 20:24:41 -04:00
Peter Steinberger
4fcc502d25 test: tighten model source plan assertions 2026-05-10 01:24:18 +01:00
Peter Steinberger
8d9f531a49 test: tighten daemon install assertions 2026-05-10 01:22:38 +01:00
Peter Steinberger
8ecd29067c test: tighten health snapshot assertions 2026-05-10 01:20:44 +01:00
Peter Steinberger
c43599a23e test: tighten auth configure prompt assertions 2026-05-10 01:19:19 +01:00
brokemac79
2bdbec8246 fix(status): treat CLI runtime aliases as selected route 2026-05-09 20:18:41 -04:00
Peter Steinberger
fa0506bd31 test: tighten channel status command assertions 2026-05-10 01:17:13 +01:00
Peter Steinberger
01bfa76791 test: tighten gateway status output assertions 2026-05-10 01:15:44 +01:00
Peter Steinberger
eb18005c9e test: tighten status scan assertions 2026-05-10 01:13:57 +01:00
Peter Steinberger
44eecbb7ae test: tighten doctor route assertions 2026-05-10 01:12:29 +01:00
Peter Steinberger
dd53545ffc test: tighten model catalog assertions 2026-05-10 01:10:47 +01:00
Peter Steinberger
d5fe89abb5 test: tighten status and onboarding assertions 2026-05-10 01:08:57 +01:00
Peter Steinberger
0aa0083fc8 test(release): stabilize plugin prerelease shards 2026-05-10 01:06:09 +01:00
brokemac79
907ac7e311 fix(qqbot): translate skill descriptions (#78153)
Summary:
- Translate the UI-facing QQBot skill description frontmatter to English.
- Add the changelog entry for #77810.

Validation:
- PR CI status rollup succeeded on 4789487630.
- Reviewed source path: manifest publishes QQBot skills, loader reads frontmatter description, skills.status passes it through, Skills UI renders it.

Thanks @brokemac79 and @eabase.
2026-05-09 20:05:45 -04:00
Peter Steinberger
5f83f4644e test: tighten model and migration assertions 2026-05-10 01:05:34 +01:00
brokemac79
2e3fa8c086 docs(changelog): mention tasks maintenance session pruning 2026-05-09 20:05:07 -04:00
brokemac79
4ab6878473 fix(tasks): report cron session preserves from locked store 2026-05-09 20:05:07 -04:00
brokemac79
021f753f72 fix(tasks): prune stale cron session registry entries 2026-05-09 20:05:07 -04:00
Peter Steinberger
e68eb601fa test: tighten command resolver assertions 2026-05-10 01:03:21 +01:00
Peter Steinberger
6f3f13782f test(release): harden Codex harness status matching 2026-05-10 00:59:52 +01:00
Peter Steinberger
f78308147a test: tighten remaining small command matchers 2026-05-10 00:59:13 +01:00
Peter Steinberger
ccd697fb10 test: tighten channel setup assertions 2026-05-10 00:55:38 +01:00
Shakker
933306475c perf: keep channel SDK runtime imports lazy 2026-05-10 00:54:15 +01:00
Shakker
be916995da test: isolate subagent archive registry deps 2026-05-10 00:54:15 +01:00
Peter Steinberger
0311fe9d8a test: tighten small command assertions 2026-05-10 00:53:49 +01:00
Peter Steinberger
4c72240a56 fix: normalize emitted google gemini model ids 2026-05-10 00:51:26 +01:00
Peter Steinberger
d5a1792a66 test(release): harden live release validation 2026-05-10 00:50:19 +01:00
Peter Steinberger
6f9f3bc1ec test: tighten remaining one-hit assertions 2026-05-10 00:45:21 +01:00
Peter Steinberger
c6f7e63cb7 test: tighten doctor helper assertions 2026-05-10 00:41:48 +01:00
Peter Steinberger
fd52454746 test: tighten small onboarding model assertions 2026-05-10 00:39:27 +01:00
Peter Steinberger
cbbbdb37eb test: tighten onboarding doctor assertions 2026-05-10 00:36:18 +01:00
Peter Steinberger
e9373925bb test: tighten channel status task assertions 2026-05-10 00:34:42 +01:00
Peter Steinberger
c522acc08d test: tighten small command matcher assertions 2026-05-10 00:32:13 +01:00
Peter Steinberger
8705055175 docs: add changelog for runtime watch fix (#70805) 2026-05-09 19:31:51 -04:00
Ruben Cuevas
e40ddf9b02 fix(gateway): cover restored watch artifacts 2026-05-09 19:31:51 -04:00
Ruben Cuevas
6b5296d4d4 chore(gateway): remove contributor changelog entry 2026-05-09 19:31:51 -04:00
Ruben Cuevas
9ce359b370 fix(gateway): check restored runtime overlays 2026-05-09 19:31:51 -04:00
Ruben Cuevas
23eec7b0fa test(gateway): cover runtime static asset edge cases 2026-05-09 19:31:51 -04:00
Ruben Cuevas
1ff83a6c66 fix(gateway): preserve static runtime assets 2026-05-09 19:31:51 -04:00
Ruben Cuevas
12933a2bcb fix(gateway): stage static runtime assets 2026-05-09 19:31:51 -04:00
Ruben Cuevas
d605efc17f fix(gateway): include legacy runtime output checks 2026-05-09 19:31:51 -04:00
Ruben Cuevas
31f74259cb fix(gateway): respect missing runtime outputs in watch 2026-05-09 19:31:51 -04:00
Ruben Cuevas
8a9f142942 fix(gateway): verify all runtime postbuild outputs 2026-05-09 19:31:51 -04:00
Ruben Cuevas
795dd2d02e fix(gateway): share runtime asset list 2026-05-09 19:31:51 -04:00
Ruben Cuevas
28de7cc2e3 fix(gateway): require static runtime assets 2026-05-09 19:31:51 -04:00
Ruben Cuevas
ee7f2da0b7 fix(gateway): check runtime SDK alias outputs 2026-05-09 19:31:51 -04:00
Ruben Cuevas
17643e549f fix(gateway): restore runtime postbuild freshness 2026-05-09 19:31:51 -04:00
Peter Steinberger
0a13bd5841 test: tighten small status model assertions 2026-05-10 00:29:50 +01:00
Peter Steinberger
dd27ad41a9 test: tighten small command assertions 2026-05-10 00:28:15 +01:00
Peter Steinberger
fc2834c217 test: tighten onboard search assertions 2026-05-10 00:26:53 +01:00
Peter Steinberger
3241f64594 test: tighten gateway agent assertions 2026-05-10 00:25:20 +01:00
Peter Steinberger
58692b9b55 test: tighten secrets snapshot assertions 2026-05-10 00:23:29 +01:00
Peter Steinberger
e3b684d61e test: tighten plugin provider auth assertions 2026-05-10 00:21:57 +01:00
Peter Steinberger
9d91b6ec41 test(release): allow beta install specs in command tests 2026-05-10 00:21:11 +01:00
Peter Steinberger
388af50ba1 fix: smooth beta update health checks 2026-05-10 00:20:38 +01:00
Peter Steinberger
e3b2ddb757 test: tighten auth choice model assertions 2026-05-10 00:19:28 +01:00
Peter Steinberger
1720eb4688 test: tighten auth choice option assertions 2026-05-10 00:16:21 +01:00
Peter Steinberger
5c7630e4bd test: tighten config schema assertions 2026-05-10 00:14:58 +01:00
Peter Steinberger
390762962f test: tighten status runtime assertions 2026-05-10 00:12:39 +01:00
Peter Steinberger
c2f4f251c9 fix: canonicalize ACP permission mode aliases (#79926) (thanks @InTheCloudDan) 2026-05-09 19:12:06 -04:00
Dan O'Brien
ce7053005b Map ACP thinking to advertised effort key 2026-05-09 19:12:06 -04:00
Peter Steinberger
ac482047f5 test: tighten dreaming cron migration assertions 2026-05-10 00:10:47 +01:00
Peter Steinberger
b6d63c0acd test(release): use public plugin test env 2026-05-10 00:10:07 +01:00
Peter Steinberger
ba6dbffca8 test: tighten agents list assertions 2026-05-10 00:08:58 +01:00
Peter Steinberger
05dac1e127 test: tighten status summary assertions 2026-05-10 00:07:43 +01:00
Peter Steinberger
44ae23ad9f test: tighten openai runtime helper assertions 2026-05-10 00:06:32 +01:00
Peter Steinberger
db81936f0e test: tighten sandbox docker audit assertions 2026-05-10 00:04:53 +01:00
Shakker
c27171a848 test: align thinking default policy assertions 2026-05-10 00:03:57 +01:00
Peter Steinberger
16008d7ad1 test: tighten readonly channel audit assertions 2026-05-10 00:03:32 +01:00
Peter Steinberger
7272c4790f test: tighten runtime plugin origin assertions 2026-05-10 00:02:18 +01:00
Peter Steinberger
18125b0daf test: tighten gateway exposure assertions 2026-05-10 00:00:43 +01:00
Peter Steinberger
6ea3908867 test: tighten secrets configure assertions 2026-05-09 23:59:29 +01:00
Shakker
00e160f395 test: align command expectations with stable plugin specs 2026-05-09 23:58:56 +01:00
Peter Steinberger
dd60c6bc4d fix(release): stabilize threaded Telegram stream QA 2026-05-09 23:57:21 +01:00
Peter Steinberger
4efc25fe49 test: tighten channel config loader assertions 2026-05-09 23:57:05 +01:00
Peter Steinberger
fe49112ebf test: tighten channel capabilities assertions 2026-05-09 23:55:46 +01:00
Peter Steinberger
90a9975adf docs: clarify model failover format errors 2026-05-09 23:55:31 +01:00
Peter Steinberger
434b3d3876 fix: clarify Codex OAuth recovery hints 2026-05-09 23:53:57 +01:00
Peter Steinberger
c58e01569b test: tighten config validation assertions 2026-05-09 23:53:49 +01:00
Peter Steinberger
eef5e2a55f test: tighten security audit assertions 2026-05-09 23:52:39 +01:00
Peter Steinberger
4cd0207519 fix: stabilize Gemini default and Bedrock thinking policy 2026-05-09 23:51:55 +01:00
Peter Steinberger
be9d839830 test: tighten command json assertions 2026-05-09 23:51:03 +01:00
Peter Steinberger
ea2ed3b9f5 test: tighten doctor cron assertions 2026-05-09 23:48:31 +01:00
Peter Steinberger
765549966f test: tighten config audit assertions 2026-05-09 23:46:35 +01:00
Peter Steinberger
449b61e232 test: tighten config schema assertions 2026-05-09 23:44:37 +01:00
Peter Steinberger
3681ff6874 test: tighten runtime schema loader assertions 2026-05-09 23:43:21 +01:00
Peter Steinberger
5aa9377feb fix(release): stabilize full validation gates 2026-05-09 23:42:27 +01:00
Peter Steinberger
37bf0a9a92 test: tighten detached task runtime assertions 2026-05-09 23:41:24 +01:00
Shakker
72c789a8e5 test: speed up commitment runtime imports 2026-05-09 23:41:03 +01:00
Shakker
4de6296a04 test: speed up mcp channel server imports 2026-05-09 23:38:38 +01:00
Peter Steinberger
f82deaff04 fix: normalize retired gemini config writes 2026-05-09 23:38:25 +01:00
Vincent Koc
554acb85a4 fix(cli): explain port and gateway prompts 2026-05-10 06:36:16 +08:00
Vincent Koc
e1a7ee6b2b fix(cli): clarify channel setup paths 2026-05-10 06:36:15 +08:00
Vincent Koc
174bcc27c4 fix(cli): make onboarding prompts clearer 2026-05-10 06:36:15 +08:00
Vincent Koc
4c7cc57a46 docs(cli): clarify setup wayfinding 2026-05-10 06:36:15 +08:00
Shakker
63ded1ca21 test: speed up plugin state seed helper 2026-05-09 23:34:03 +01:00
Peter Steinberger
999bd8bf6c test: tighten task registry media recovery assertions 2026-05-09 23:32:31 +01:00
Shakker
20d891af58 test: speed up sqlite vec loader test 2026-05-09 23:31:50 +01:00
Peter Steinberger
e491a2e7e8 test(agents): cover minimax music availability 2026-05-09 23:31:06 +01:00
Peter Steinberger
b0c7f75a6d test: tighten task registry recovery assertions 2026-05-09 23:30:44 +01:00
Shakker
752e76b705 test: speed up acp translator imports 2026-05-09 23:29:23 +01:00
Peter Steinberger
19cb8c1ae6 test: tighten task registry maintenance cache assertions 2026-05-09 23:28:55 +01:00
Peter Steinberger
0e19167a6b test: tighten secrets audit assertions 2026-05-09 23:27:05 +01:00
Peter Steinberger
0107a78e59 test(release): align async cooldown assertion 2026-05-09 23:25:28 +01:00
Peter Steinberger
0735c329fb test(release): accept codex idle-ready variants 2026-05-09 23:25:28 +01:00
Peter Steinberger
c8a02962da test(release): accept codex idle-ready status 2026-05-09 23:25:28 +01:00
Peter Steinberger
7674a897cc test(release): harden OpenWebUI release lane 2026-05-09 23:25:28 +01:00
Peter Steinberger
7bc2deb0d6 test(release): accept codex normal status prose 2026-05-09 23:25:27 +01:00
Peter Steinberger
b1f333d2bf fix(release): harden OpenAI installer proof lane 2026-05-09 23:25:27 +01:00
Peter Steinberger
b4fec8ded1 test(release): isolate deferred channel fixture 2026-05-09 23:25:27 +01:00
Peter Steinberger
86ad1749b3 fix(release): extend OpenAI installer e2e timeout 2026-05-09 23:25:27 +01:00
Peter Steinberger
c53b8196c8 ci(release): disable corepack download prompts 2026-05-09 23:25:27 +01:00
Peter Steinberger
5cf8919028 fix(release): accept codex idle status wording 2026-05-09 23:25:27 +01:00
Peter Steinberger
1d772f3b1a fix(release): extend Open WebUI docker command timeout 2026-05-09 23:25:27 +01:00
Peter Steinberger
a672bef837 fix(release): serialize live OpenAI Docker lanes 2026-05-09 23:25:27 +01:00
Peter Steinberger
354e49ac7d fix(release): serialize OpenAI installer e2e turns 2026-05-09 23:25:27 +01:00
Peter Steinberger
279ae6f5f3 fix(release): classify unavailable read tool probe refusals 2026-05-09 23:25:27 +01:00
Peter Steinberger
6443b5c37d fix(release): relax OpenAI live e2e timeouts 2026-05-09 23:25:27 +01:00
Peter Steinberger
dee0aa4344 fix(release): accept config-only survivor plugin rows 2026-05-09 23:25:27 +01:00
Peter Steinberger
a902b00231 fix(release): tolerate matrix-free survivor index 2026-05-09 23:25:27 +01:00
Peter Steinberger
971738bbfa fix(release): stabilize beta release harness 2026-05-09 23:25:27 +01:00
Peter Steinberger
ae66f70209 fix(release): keep package validation within live contracts 2026-05-09 23:25:27 +01:00
Peter Steinberger
19f66b4a90 test(plugins): isolate startup planner fixture coverage 2026-05-09 23:25:27 +01:00
Peter Steinberger
5c464aa9a1 fix(qa): accept Telegram long final chunk variants 2026-05-09 23:25:27 +01:00
Peter Steinberger
5b560b9d45 test(release): cover root gateway stop guard 2026-05-09 23:25:27 +01:00
Peter Steinberger
0d1c4393b9 fix(release): pin direct OpenAI smoke runtime 2026-05-09 23:25:27 +01:00
Peter Steinberger
6a20083098 fix(release): cover live validation edge cases 2026-05-09 23:25:27 +01:00
Peter Steinberger
978334a83a test(telegram): satisfy transport stub contract 2026-05-09 23:25:27 +01:00
Peter Steinberger
195e721211 fix(release): stabilize full validation gates 2026-05-09 23:25:27 +01:00
Peter Steinberger
bcb4c8d597 fix(release): stabilize Codex live validation 2026-05-09 23:25:26 +01:00
Peter Steinberger
16f3350b84 fix(release): repair full validation gates 2026-05-09 23:25:26 +01:00
Peter Steinberger
877e257269 test(gateway): relax session rotation close wait 2026-05-09 23:25:26 +01:00
Peter Steinberger
be793e2d85 ci(release): skip npm acceptance hash pin 2026-05-09 23:25:26 +01:00
Peter Steinberger
35f63f2473 fix(macos): read typed gateway error frames 2026-05-09 23:25:26 +01:00
Peter Steinberger
af9baddac0 fix(release): align beta plugin install expectations 2026-05-09 23:25:26 +01:00
Peter Steinberger
d28124a14b fix(release): classify externalized root package imports 2026-05-09 23:25:26 +01:00
Peter Steinberger
221f876c3f fix(plugin-sdk): stabilize API baseline generation 2026-05-09 23:25:26 +01:00
Peter Steinberger
c441d51c32 test: tighten secrets apply assertions 2026-05-09 23:24:46 +01:00
Shakker
022556869b test: narrow channel audit fallback test 2026-05-09 23:24:05 +01:00
Peter Steinberger
b8afa2cb10 test: tighten auth runtime integration assertions 2026-05-09 23:23:25 +01:00
Peter Steinberger
2a31dae5e8 fix(discord): sync realtime voice playback timestamps 2026-05-09 23:22:18 +01:00
Peter Steinberger
00c00fb2c4 test: tighten discord surface warning assertions 2026-05-09 23:22:03 +01:00
Shakker
9ec2831c20 test: avoid channel catalog import in logger setup 2026-05-09 23:21:44 +01:00
Peter Steinberger
0fb84a9bcd test: tighten channel contract api assertions 2026-05-09 23:20:40 +01:00
Peter Steinberger
e0454ea9d2 test: tighten matrix shadowing assertions 2026-05-09 23:19:20 +01:00
Peter Steinberger
5f3703d757 test: tighten channel origin discovery assertions 2026-05-09 23:17:36 +01:00
Peter Steinberger
27ae291682 docs: clarify bare GitHub review routing 2026-05-09 23:16:51 +01:00
Shakker
7768d1374a test: speed up plugin state runtime test 2026-05-09 23:16:30 +01:00
Peter Steinberger
d9d8439dfd test: tighten inactive channel warning assertions 2026-05-09 23:16:21 +01:00
Peter Steinberger
e8d01a3eba test: tighten channel config collector assertions 2026-05-09 23:15:24 +01:00
Peter Steinberger
9a180ca24b test: tighten windows acl command assertions 2026-05-09 23:13:57 +01:00
Peter Steinberger
1fbd8e9dfb test: tighten acp command assertions 2026-05-09 23:12:18 +01:00
Peter Steinberger
29fe823fed test: tighten channel account diagnostics 2026-05-09 23:10:13 +01:00
Peter Steinberger
9b6b418902 test: tighten task flow maintenance assertions 2026-05-09 23:09:21 +01:00
Peter Steinberger
e5c5be7cc5 test: tighten secret audit status assertions 2026-05-09 23:08:01 +01:00
Shakker
9a454509f5 test: speed up memory host remote client tests 2026-05-09 23:06:47 +01:00
Peter Steinberger
5a16ec4f08 test: tighten security audit source assertions 2026-05-09 23:06:28 +01:00
Peter Steinberger
a92f7085d6 test: tighten security config audit assertions 2026-05-09 23:05:04 +01:00
Peter Steinberger
a059f0571b test: tighten secret registry assertions 2026-05-09 23:02:14 +01:00
pashpashpash
52771b65e2 Stop preserving stale whole-agent Codex runtime pins
This removes stale whole-agent Codex runtime pins from the remaining doctor/Crestodian paths and teaches doctor cron repair to normalize old openai-codex payload model refs to canonical openai refs. Runtime policy stays provider/model-scoped and cron execution stays strict.
2026-05-09 15:01:18 -07:00
Peter Steinberger
34d275cf87 test: tighten security audit finding assertions 2026-05-09 23:00:07 +01:00
Shakker
8334e755a1 test: speed up plugin state store tests 2026-05-09 22:59:30 +01:00
Peter Steinberger
0e53a2b49b test: tighten gateway auth surface assertions 2026-05-09 22:58:55 +01:00
Peter Steinberger
8e47cd5344 test: tighten provider env var dynamic assertion 2026-05-09 22:57:31 +01:00
Peter Steinberger
c0f4db339d test: tighten secret env var assertions 2026-05-09 22:56:14 +01:00
Peter Steinberger
624af621e6 test: tighten cron failure notification assertions 2026-05-09 22:55:00 +01:00
Peter Steinberger
4ec277ca00 test: tighten cron isolated agent assertions 2026-05-09 22:53:45 +01:00
Peter Steinberger
ad4ec8049d test: tighten channel setup status assertions 2026-05-09 22:52:27 +01:00
Peter Steinberger
0873242dd0 test: tighten provider flow assertions 2026-05-09 22:51:28 +01:00
Peter Steinberger
c47797a549 test: tighten search setup assertions 2026-05-09 22:50:15 +01:00
Peter Steinberger
98190f7a7b test: tighten channel turn kernel assertions 2026-05-09 22:48:10 +01:00
Peter Steinberger
aa720a6bb7 test: tighten durable message send assertions 2026-05-09 22:45:47 +01:00
Peter Steinberger
4e56fb82b6 test: tighten durable delivery assertions 2026-05-09 22:43:00 +01:00
Peter Steinberger
102a670cf3 test: tighten channel message lifecycle assertions 2026-05-09 22:41:46 +01:00
Vincent Koc
346e327586 fix(cli): guide onboarding option errors 2026-05-10 05:41:28 +08:00
Peter Steinberger
021565bd71 test: tighten channel outbound bridge assertions 2026-05-09 22:39:54 +01:00
Peter Steinberger
90f2a0b23c test: tighten channel message receipt assertions 2026-05-09 22:37:48 +01:00
Shakker
64f4c7b07d test: speed up managed proxy tests 2026-05-09 22:37:16 +01:00
Peter Steinberger
666ed4d889 test: tighten channel message contract assertions 2026-05-09 22:36:42 +01:00
Peter Steinberger
2575c6aea6 test: tighten channel turn context assertions 2026-05-09 22:35:09 +01:00
Shakker
56d58f21e0 test: speed up channel audit setup fallback test 2026-05-09 22:34:21 +01:00
Peter Steinberger
51ba22f49e test: tighten xai live voice assertion 2026-05-09 22:33:53 +01:00
Peter Steinberger
b54bf9adb4 test: tighten xai web search assertions 2026-05-09 22:31:20 +01:00
Peter Steinberger
d99c3f7432 test: tighten xai realtime transcription assertion 2026-05-09 22:28:16 +01:00
Peter Steinberger
8558af7e1a test: tighten xai plugin assertions 2026-05-09 22:26:33 +01:00
Vincent Koc
749dc78b8d changelog: add Codex transcript tool-call mirroring entry for #79952 2026-05-10 05:24:44 +08:00
Peter Steinberger
11bb77ae3c test: tighten xai video assertions 2026-05-09 22:24:03 +01:00
Peter Steinberger
ff34245d4b test: tighten xai image assertions 2026-05-09 22:22:17 +01:00
Peter Steinberger
dd224c8560 test: tighten xai onboard assertions 2026-05-09 22:20:47 +01:00
Peter Steinberger
c3d9815320 test: tighten xai stt assertions 2026-05-09 22:19:39 +01:00
Peter Steinberger
0b7d796bb0 test: tighten xai speech assertions 2026-05-09 22:18:11 +01:00
Peter Steinberger
dcc0c90ba4 test: tighten manifest planner assertions 2026-05-09 22:16:27 +01:00
Peter Steinberger
40e8779677 test: tighten channel session assertions 2026-05-09 22:14:48 +01:00
Peter Steinberger
3c97092135 test: tighten thread binding policy assertion 2026-05-09 22:13:14 +01:00
Shakker
b4541fe8c7 test: speed up voice realtime tests 2026-05-09 22:12:29 +01:00
Peter Steinberger
96d68c4877 test: tighten state dir env assertion 2026-05-09 22:11:54 +01:00
Peter Steinberger
21dd96cdff test: tighten image generation assertions 2026-05-09 22:10:33 +01:00
Peter Steinberger
8140465765 test: tighten task executor assertions 2026-05-09 22:07:54 +01:00
Peter Steinberger
81a02f08ef test: tighten task flow audit assertions 2026-05-09 22:05:30 +01:00
Peter Steinberger
f183b16289 test: tighten task registry store assertions 2026-05-09 22:04:12 +01:00
Peter Steinberger
eda94a434d test: tighten task flow assertions 2026-05-09 22:02:32 +01:00
Shakker
408efe489a test: speed up task registry tests 2026-05-09 22:00:51 +01:00
scoootscooob
480af03009 fix(codex): mirror tool calls in transcripts (#79952) 2026-05-09 17:00:47 -04:00
Peter Steinberger
e83e59e19b test: tighten trajectory assertions 2026-05-09 22:00:03 +01:00
Peter Steinberger
0dffb94644 test: tighten tui array assertions 2026-05-09 21:57:27 +01:00
Peter Steinberger
4c6f3bc07e test: tighten video runtime assertions 2026-05-09 21:56:07 +01:00
Shakker
f715a84771 test: speed up canvas setup migration test 2026-05-09 21:55:07 +01:00
Peter Steinberger
26c8410282 test: tighten usage render assertions 2026-05-09 21:54:09 +01:00
Peter Steinberger
9f986882fc test: tighten google meet voice assertions 2026-05-09 21:52:21 +01:00
Peter Steinberger
97a5277021 test: tighten usage metrics assertion 2026-05-09 21:51:03 +01:00
Shakker
f0bc3e27ae test: speed up update cli tests 2026-05-09 21:50:18 +01:00
Peter Steinberger
d791eba206 test: tighten ui log parser assertion 2026-05-09 21:49:57 +01:00
Peter Steinberger
62939f0593 test: tighten vydra image assertions 2026-05-09 21:48:53 +01:00
Peter Steinberger
0456672aaf test: tighten vydra video assertions 2026-05-09 21:47:38 +01:00
Peter Steinberger
0bc1e5e1cd test: tighten byteplus catalog assertions 2026-05-09 21:46:18 +01:00
Peter Steinberger
02ac487738 test: tighten byteplus video assertions 2026-05-09 21:45:04 +01:00
Peter Steinberger
86b6091f8e test: tighten tlon upload assertions 2026-05-09 21:43:22 +01:00
Peter Steinberger
48f192de3d test: tighten runway video assertions 2026-05-09 21:41:55 +01:00
Shakker
b56e4f457c test: speed up agent command tests 2026-05-09 21:41:24 +01:00
Peter Steinberger
eefb0ee6f8 test: tighten firecrawl tool assertions 2026-05-09 21:39:34 +01:00
Shakker
c7ab83e8ab test: speed up cron model override tests 2026-05-09 21:38:24 +01:00
Peter Steinberger
50a64283d5 test: tighten sdk e2e assertions 2026-05-09 21:37:34 +01:00
Peter Steinberger
3c12501b54 test: tighten sdk unit assertions 2026-05-09 21:35:21 +01:00
Peter Steinberger
91fac5d441 test: tighten realtime voice call assertions 2026-05-09 21:32:39 +01:00
Peter Steinberger
9356797bcd test: tighten voice call webhook assertions 2026-05-09 21:29:44 +01:00
Peter Steinberger
438f647f7a test: tighten telnyx provider assertions 2026-05-09 21:28:20 +01:00
Peter Steinberger
46aa7e130f test: tighten twilio api assertions 2026-05-09 21:24:57 +01:00
Peter Steinberger
eabbf06d47 test: tighten twilio provider call assertions 2026-05-09 21:23:40 +01:00
Peter Steinberger
1b24dacff2 test: tighten voice call config assertions 2026-05-09 21:22:09 +01:00
Peter Steinberger
39fe6977a3 test: tighten voice call inbound allowlist assertions 2026-05-09 21:20:13 +01:00
Peter Steinberger
8a8076d65e test: tighten voice call response assertions 2026-05-09 21:18:44 +01:00
Shakker
2acd6aef92 test: speed up subagent registry persistence tests 2026-05-09 21:17:10 +01:00
Peter Steinberger
7c1ab59ee2 test: tighten voice call event assertions 2026-05-09 21:15:21 +01:00
Peter Steinberger
bd43b38096 test: tighten voice call outbound assertions 2026-05-09 21:13:56 +01:00
Peter Steinberger
18aeac86a1 fix: normalize gemini config mutations 2026-05-09 21:12:23 +01:00
Peter Steinberger
fb0ea0fc73 test: tighten voice call timer timeout assertion 2026-05-09 21:02:38 +01:00
Peter Steinberger
a90f5597bd test: tighten voice call tunnel assertions 2026-05-09 21:01:18 +01:00
Peter Steinberger
9353febc9a test: tighten voice call webhook security assertion 2026-05-09 20:59:24 +01:00
Peter Steinberger
ae81d2aa09 test: tighten qa matrix cli options 2026-05-09 20:57:49 +01:00
Andy Ye
e7c784f7a8 fix(agents): preserve active exec references across compaction (#79307)
Merged via squash.

Prepared head SHA: b8da3158f9
Co-authored-by: TurboTheTurtle <35905412+TurboTheTurtle@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-05-09 12:57:20 -07:00
Peter Steinberger
54d0baa6e6 test: tighten moonshot video content assertion 2026-05-09 20:56:01 +01:00
Peter Steinberger
80f3c0a036 test: tighten voice call hangup assertion 2026-05-09 20:54:29 +01:00
Peter Steinberger
42babf5486 test: tighten test projects cache assertion 2026-05-09 20:52:57 +01:00
Peter Steinberger
9bf5f52a19 test: tighten docs link audit invocations 2026-05-09 20:51:53 +01:00
Peter Steinberger
3dfbf5af43 test: tighten codex ci auth payload assertions 2026-05-09 20:50:37 +01:00
Peter Steinberger
efee3f9793 test: tighten temp home cleanup assertion 2026-05-09 20:49:34 +01:00
Peter Steinberger
79b1c6a626 test: tighten zalouser doctor assertions 2026-05-09 20:48:06 +01:00
Peter Steinberger
0c465156de test: tighten zalouser outbound assertions 2026-05-09 20:46:16 +01:00
Peter Steinberger
5cc6a1397e test: tighten together video request assertions 2026-05-09 20:44:28 +01:00
Peter Steinberger
43cf6c4387 test: tighten nvidia onboard assertions 2026-05-09 20:39:47 +01:00
Peter Steinberger
9e2a30c353 test: tighten lobster tool assertions 2026-05-09 20:37:57 +01:00
Peter Steinberger
425c4ff9ea test: tighten lobster runner assertions 2026-05-09 20:36:07 +01:00
Peter Steinberger
f89baa047d test: tighten kilocode model discovery assertions 2026-05-09 20:34:07 +01:00
Peter Steinberger
38442a9342 test: tighten speech core tts assertions 2026-05-09 20:32:21 +01:00
Shakker
024d6e9f22 test: align opencode go catalog assertion 2026-05-09 20:31:09 +01:00
Peter Steinberger
a1fe4ae646 test: tighten synology chat context assertions 2026-05-09 20:28:25 +01:00
Peter Steinberger
a2aab81e05 test: tighten zalouser account scope assertions 2026-05-09 20:26:51 +01:00
Peter Steinberger
6a2db8d9ca test: tighten opencode go catalog assertions 2026-05-09 20:24:44 +01:00
Peter Steinberger
4769d40e2b test: tighten auth profile rotation assertions 2026-05-09 20:21:32 +01:00
Peter Steinberger
9a6f02590b test: tighten alibaba video request assertions 2026-05-09 20:16:14 +01:00
Peter Steinberger
1ca4f15149 test: tighten voice call notify assertions 2026-05-09 20:14:19 +01:00
Peter Steinberger
df1267216f test: tighten voice call runtime assertions 2026-05-09 20:12:12 +01:00
Shakker
cb8091453b test: avoid provider hooks in context engine harness 2026-05-09 20:10:32 +01:00
Peter Steinberger
aa97e92b41 test: tighten voice call restore assertions 2026-05-09 20:10:00 +01:00
Peter Steinberger
51d84bcc2e test: tighten voice call media stream assertions 2026-05-09 20:08:35 +01:00
Peter Steinberger
88a6dceecd test: tighten subagent orphan recovery assertions 2026-05-09 20:06:13 +01:00
Peter Steinberger
3f3e94a604 test: tighten history image prune assertions 2026-05-09 20:03:37 +01:00
Peter Steinberger
79e7a6c082 test: tighten context engine maintenance assertions 2026-05-09 20:01:46 +01:00
Peter Steinberger
51dc4a20be test: tighten exec approval id assertions 2026-05-09 19:59:35 +01:00
Omar Shahine
200eb62ef4 fix(imessage): wire reply attachments through send-rich --file (with feature gate) (#79864)
Merged via squash.

Prepared head SHA: 5e5cdfed79
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-09 14:59:04 -04:00
Peter Steinberger
bbabd9bec4 test: tighten exec approval followup assertions 2026-05-09 19:57:08 +01:00
Peter Steinberger
d416adb424 test: tighten docker e2e plan assertions 2026-05-09 19:55:41 +01:00
Peter Steinberger
05a200f848 test: tighten media background assertions 2026-05-09 19:54:32 +01:00
Peter Steinberger
fb890e7069 test: tighten live matcher assertions 2026-05-09 19:52:49 +01:00
Peter Steinberger
b7ca251a56 test: tighten sessions tool assertions 2026-05-09 19:51:23 +01:00
Peter Steinberger
b76df1fa8d test: tighten model catalog assertions 2026-05-09 19:49:50 +01:00
Shakker
04a9a61e18 test: avoid proxy-wide root alias matcher 2026-05-09 19:46:49 +01:00
Peter Steinberger
9e3303d959 test: tighten model fallback assertions 2026-05-09 19:46:40 +01:00
Peter Steinberger
1e6fb45bcf test: tighten edit recovery assertions 2026-05-09 19:43:30 +01:00
Peter Steinberger
7db96894c2 test: tighten camera tool assertions 2026-05-09 19:41:33 +01:00
Omar Shahine
fec1c3f696 test: sandbox audit-exec-surface under HOME tempdir (#79885)
Merged via squash.

Prepared head SHA: de039cde81
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-09 14:39:30 -04:00
Peter Steinberger
9a2eba684e test: tighten subagent restart assertions 2026-05-09 19:38:46 +01:00
Peter Steinberger
7b8a995a07 test: tighten sandbox registry assertions 2026-05-09 19:37:09 +01:00
Peter Steinberger
4264ba6446 test: tighten before tool approval assertions 2026-05-09 19:35:23 +01:00
brokemac79
f6c499708a [AI-assisted] fix(whatsapp): delta repeated tool preambles (#79120)
Merged via squash.

Prepared head SHA: 53da6d0f63
Co-authored-by: brokemac79 <255583030+brokemac79@users.noreply.github.com>
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Reviewed-by: @velvet-shark
2026-05-09 20:34:09 +02:00
Peter Steinberger
4fee645d74 test: tighten compaction transcript assertions 2026-05-09 19:32:37 +01:00
Radek Sienkiewicz
59326c8e3b fix(slack): wake interactive reply sessions (#79836)
Merged via squash.

Prepared head SHA: 2bc9182d0f
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Reviewed-by: @velvet-shark
2026-05-09 20:31:40 +02:00
Peter Steinberger
95a87f2f21 test: tighten skills status assertions 2026-05-09 19:29:28 +01:00
Peter Steinberger
5d43e8336a test: tighten runtime plan assertions 2026-05-09 19:27:07 +01:00
Peter Steinberger
e2aac4fbc1 test: tighten pi auth json assertions 2026-05-09 19:24:58 +01:00
Peter Steinberger
df8ccb0001 test: tighten command delivery assertions 2026-05-09 19:23:23 +01:00
Peter Steinberger
0f8b52f99c test: tighten codex oauth fallback assertions 2026-05-09 19:20:58 +01:00
Shakker
f1406b1b56 fix: load linked plugin facades when bundled fallback is off 2026-05-09 19:19:14 +01:00
Peter Steinberger
9b17c98429 test: tighten subagent context assertions 2026-05-09 19:18:55 +01:00
Peter Steinberger
f3e752ccf8 test: tighten run wait assertions 2026-05-09 19:16:13 +01:00
Peter Steinberger
2f0b0befba test: tighten coding tools assertions 2026-05-09 19:14:10 +01:00
Peter Steinberger
60cb2325a1 test: tighten tool result context guard assertions 2026-05-09 19:10:56 +01:00
Peter Steinberger
34d040644d test: tighten sandbox create arg assertions 2026-05-09 19:09:23 +01:00
Peter Steinberger
5d8ce65a8e test: tighten embedded subscribe assertions 2026-05-09 19:07:34 +01:00
Peter Steinberger
5d451a5f3c test: canonicalize gemini live probe model 2026-05-09 19:04:55 +01:00
Peter Steinberger
cb86388cec test: tighten plugin context assertions 2026-05-09 18:58:07 +01:00
Peter Steinberger
59b88e4f01 test: tighten model auth assertions 2026-05-09 18:56:34 +01:00
Peter Steinberger
9931cafe70 test: tighten external cli auth assertions 2026-05-09 18:53:54 +01:00
Peter Steinberger
75d44714dc test: tighten music background assertions 2026-05-09 18:50:55 +01:00
Peter Steinberger
bafe49f062 test: tighten message tool assertions 2026-05-09 18:48:57 +01:00
Peter Steinberger
7f59a5e128 test: tighten subagent announce assertions 2026-05-09 18:47:11 +01:00
Shakker
29661a3179 test: avoid duplicate session event wait 2026-05-09 18:46:54 +01:00
Shakker
7e3a25f5dc test: narrow session search registry helpers 2026-05-09 18:44:57 +01:00
Peter Steinberger
8f8426342e test: tighten subagent depth assertions 2026-05-09 18:44:37 +01:00
Peter Steinberger
4cfcc32ee3 test: tighten skip pi discovery hook assertions 2026-05-09 18:42:30 +01:00
Peter Steinberger
c0aa046dd6 test: tighten subagent model plan assertions 2026-05-09 18:41:11 +01:00
Peter Steinberger
c198d4f23b test: tighten provider auth alias assertions 2026-05-09 18:38:33 +01:00
Peter Steinberger
c8f738786f test: tighten model fallback probe assertions 2026-05-09 18:37:11 +01:00
Peter Steinberger
a9a5106fa9 test: tighten cli session history assertions 2026-05-09 18:35:26 +01:00
Shakker
d1e40ca3e8 test: skip disabled bundled facade resolution 2026-05-09 18:35:20 +01:00
Peter Steinberger
ca8bcea186 test: tighten process supervisor assertions 2026-05-09 18:33:53 +01:00
Peter Steinberger
8be0c72e97 test: tighten external oauth assertions 2026-05-09 18:32:35 +01:00
Shakker
a0262c33d0 test: narrow web search provider contract imports 2026-05-09 18:31:20 +01:00
Peter Steinberger
d00c9e06e2 test: tighten web runtime context assertions 2026-05-09 18:31:04 +01:00
Peter Steinberger
23344cfb1d test: tighten tts tool assertions 2026-05-09 18:29:31 +01:00
Peter Steinberger
4b534df4f2 test: tighten gateway restart assertions 2026-05-09 18:28:11 +01:00
Peter Steinberger
5d10e54aae test: tighten subagent workspace assertions 2026-05-09 18:26:23 +01:00
Peter Steinberger
f2257b4544 test: tighten simple completion selection assertions 2026-05-09 18:25:04 +01:00
Peter Steinberger
a8634e6e5b test: tighten ssh sandbox assertions 2026-05-09 18:23:18 +01:00
Peter Steinberger
29a5d85e5d test: tighten sandbox browser assertions 2026-05-09 18:21:29 +01:00
Peter Steinberger
cc6f6bfb02 test: tighten provider transport fetch assertions 2026-05-09 18:20:10 +01:00
Peter Steinberger
8fe0956f8e test: tighten embedded lifecycle assertions 2026-05-09 18:17:21 +01:00
Peter Steinberger
c7c21b86eb test: tighten tool call normalization assertions 2026-05-09 18:15:13 +01:00
Shakker
c896ddbb20 test: isolate compact hook runtime plan 2026-05-09 18:13:58 +01:00
Peter Steinberger
3117b6630d test: tighten embedded extra params assertions 2026-05-09 18:11:51 +01:00
奥森木
1f75d3c187 Cron: honor server_error retries (#45594)
Merged via squash.

Prepared head SHA: d2b1d73d32
Co-authored-by: clovericbot <258443621+clovericbot@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-05-09 20:10:29 +03:00
Peter Steinberger
627917dc1a test: tighten media factory plan assertions 2026-05-09 18:10:17 +01:00
Peter Steinberger
901b0652bf test: tighten embedded fallback assertions 2026-05-09 18:08:07 +01:00
Peter Steinberger
d91dc63b00 test: tighten oauth mirror refresh assertions 2026-05-09 18:05:08 +01:00
Peter Steinberger
5ffb936873 test: tighten auth profile runtime assertions 2026-05-09 18:03:11 +01:00
Peter Steinberger
5d452e8179 test: tighten transport transform assertions 2026-05-09 18:00:46 +01:00
Peter Steinberger
de9549f678 test: tighten gateway tool assertions 2026-05-09 17:57:44 +01:00
Shakker
94e2928e6c test: isolate status usage summary 2026-05-09 17:57:07 +01:00
Peter Steinberger
ac51c1c1b7 test: tighten subagent thread binding assertions 2026-05-09 17:55:07 +01:00
Peter Steinberger
2cdd545bcf test: tighten subagent control assertions 2026-05-09 17:53:43 +01:00
Shakker
610febeaf1 test: avoid slow missing extension base lookup 2026-05-09 17:53:14 +01:00
Peter Steinberger
36132759d5 test: tighten requester origin assertions 2026-05-09 17:51:49 +01:00
Peter Steinberger
5967218cdf test: tighten sandbox security assertions 2026-05-09 17:49:15 +01:00
Shakker
85ef6d248d test: mock tts in system prompt wrappers 2026-05-09 17:48:34 +01:00
Peter Steinberger
7a14ae8c6f test: tighten sandbox manage assertions 2026-05-09 17:47:18 +01:00
hcl
55e7f5f27c fix(whatsapp): pass routing ctx to transcribeFirstAudio so echoTranscript can deliver (#79778) (#79788)
Merged via squash.

Prepared head SHA: b5d2936d52
Co-authored-by: hclsys <7755017+hclsys@users.noreply.github.com>
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Reviewed-by: @velvet-shark
2026-05-09 18:46:54 +02:00
Peter Steinberger
8542a7d6c1 test: tighten plugin text transform assertions 2026-05-09 17:45:56 +01:00
Peter Steinberger
a3d378012c test: tighten tool schema assertions 2026-05-09 17:44:22 +01:00
Peter Steinberger
2127b9f2a9 test: tighten tool adapter assertions 2026-05-09 17:42:59 +01:00
Shakker
0d4b69389d test: isolate harness registry state 2026-05-09 17:42:45 +01:00
Peter Steinberger
aa41e23519 test: tighten tool adapter logging assertions 2026-05-09 17:41:12 +01:00
Peter Steinberger
a7d37dc4bb test: tighten compaction safeguard assertions 2026-05-09 17:39:50 +01:00
Peter Steinberger
9fbba8175b test: tighten embedded observation assertions 2026-05-09 17:37:31 +01:00
Peter Steinberger
77a46bca1e test: tighten sessions spawn lifecycle assertions 2026-05-09 17:35:57 +01:00
Peter Steinberger
6cb4a8b2db test: tighten harness selection assertions 2026-05-09 17:33:47 +01:00
Peter Steinberger
72f304234f test: tighten codex extension diagnostics 2026-05-09 17:31:53 +01:00
Shakker
89a8aa8dfd test: reuse video dimensions imports 2026-05-09 17:31:44 +01:00
Shakker
336aa81556 test: reuse remote embeddings import 2026-05-09 17:30:41 +01:00
Peter Steinberger
d1ff0b0fc2 test: tighten exec host gateway assertions 2026-05-09 17:30:23 +01:00
Shakker
7c27a51788 test: reuse memory post json imports 2026-05-09 17:29:46 +01:00
Shakker
76c117a441 test: reuse exec host shared imports 2026-05-09 17:28:25 +01:00
Peter Steinberger
b6512fe706 test: tighten exec approval request assertions 2026-05-09 17:27:23 +01:00
Shakker
1a39d519f1 test: reuse skills runtime import 2026-05-09 17:26:53 +01:00
Peter Steinberger
b67a2ff579 test: tighten auth profile cache assertions 2026-05-09 17:26:04 +01:00
Shakker
31d63d7c0b test: reuse host edit tool import 2026-05-09 17:25:48 +01:00
Peter Steinberger
baeb1de015 test: tighten transport params assertions 2026-05-09 17:24:38 +01:00
Shakker
8fd9c8edc6 test: reuse minimax vlm import 2026-05-09 17:24:21 +01:00
Shakker
d65fbdf37f test: reuse model auth label import 2026-05-09 17:23:41 +01:00
Peter Steinberger
523ddb64cf test: tighten web tools defaults assertions 2026-05-09 17:23:05 +01:00
Shakker
b655234ce5 test: reuse compaction fallback import 2026-05-09 17:22:38 +01:00
Peter Steinberger
70d3c53ecb test: tighten web guarded fetch assertions 2026-05-09 17:21:47 +01:00
Shakker
30e6bd11b3 test: reuse transcript policy import 2026-05-09 17:21:37 +01:00
Shakker
9929fd0989 test: reuse session slug import 2026-05-09 17:20:43 +01:00
Peter Steinberger
bc729494e4 test: tighten web fetch provider fallback assertions 2026-05-09 17:20:21 +01:00
Shakker
a7e2dd0538 test: hoist gateway helper imports 2026-05-09 17:19:51 +01:00
Peter Steinberger
b66e20d684 test: tighten sessions send a2a assertions 2026-05-09 17:19:16 +01:00
Shakker
89c09b030a test: reuse web search signal import 2026-05-09 17:18:42 +01:00
Shakker
4cf31767b9 test: reuse nodes utils import 2026-05-09 17:17:56 +01:00
Peter Steinberger
ce1a52a5f2 test: tighten skills install assertions 2026-05-09 17:17:46 +01:00
Shakker
8ce831e55b test: reuse sessions list import 2026-05-09 17:16:47 +01:00
Peter Steinberger
732664688c test: tighten skills install fallback assertions 2026-05-09 17:16:01 +01:00
Shakker
ca39429a28 test: reuse openclaw tools import 2026-05-09 17:14:34 +01:00
Peter Steinberger
4a9f28f5cf test: tighten provider request config assertions 2026-05-09 17:14:08 +01:00
Shakker
46a1d2eaa9 test: reuse lsp spawn runtime import 2026-05-09 17:13:06 +01:00
Peter Steinberger
84ccff34ad test: tighten host tilde expansion assertions 2026-05-09 17:12:56 +01:00
Shakker
4b1cecdc47 test: hoist gateway tool mocks 2026-05-09 17:12:05 +01:00
Peter Steinberger
478cc1c323 test: tighten messaging extract assertions 2026-05-09 17:10:57 +01:00
Shakker
1277bf338d test: reuse web runtime context imports 2026-05-09 17:10:01 +01:00
Peter Steinberger
e77dbe875f test: tighten usage reporting assertions 2026-05-09 17:09:47 +01:00
Shakker
fa04cc3526 test: reuse web search tool import 2026-05-09 17:08:53 +01:00
Peter Steinberger
375f5ac58c test: tighten payload error assertions 2026-05-09 17:08:42 +01:00
Shakker
b9d6bb91ec test: reuse stdio transport import 2026-05-09 17:07:37 +01:00
Peter Steinberger
55b5333e99 test: tighten embedded auth controller assertions 2026-05-09 17:07:29 +01:00
Shakker
a5d2e43fea test: reuse agents list tool import 2026-05-09 17:06:42 +01:00
Peter Steinberger
d721ed09e5 test: tighten context injection assertions 2026-05-09 17:06:13 +01:00
Shakker
4a87bc980b test: reuse provider transport fetch import 2026-05-09 17:05:42 +01:00
Peter Steinberger
65173324ce test: tighten sessions visibility assertions 2026-05-09 17:04:50 +01:00
Shakker
73d97a420f test: dedupe bundle settings mocks 2026-05-09 17:04:10 +01:00
Peter Steinberger
5664978a18 test: tighten models config serialization assertions 2026-05-09 17:03:50 +01:00
Peter Steinberger
13bc743a87 test: tighten models config merge assertions 2026-05-09 17:02:46 +01:00
Shakker
3657e60d48 test: reuse trajectory export module import 2026-05-09 17:01:54 +01:00
Peter Steinberger
e7d320eb2b test: tighten model auth profile assertions 2026-05-09 17:01:41 +01:00
Shakker
4cec3ca2ba test: reuse export session module import 2026-05-09 17:00:37 +01:00
Peter Steinberger
01b1a56025 test: tighten mcp transport config assertions 2026-05-09 17:00:28 +01:00
Shakker
faea23cffa test: avoid provider policy module resets 2026-05-09 16:59:43 +01:00
Peter Steinberger
87f01a408d test: tighten pty fallback assertions 2026-05-09 16:59:20 +01:00
Shakker
9f6722ac85 test: isolate group runtime reloads 2026-05-09 16:58:17 +01:00
Peter Steinberger
8a8c3d7fa3 test: tighten apply patch assertions 2026-05-09 16:57:52 +01:00
Peter Steinberger
b6067fd7cd test: tighten pi tools fs helper assertions 2026-05-09 16:56:45 +01:00
Shakker
991e618e8e test: load bootstrap cache test modules once 2026-05-09 16:56:18 +01:00
Peter Steinberger
4089c557c0 test: tighten embedded runner e2e assertions 2026-05-09 16:53:44 +01:00
Shakker
8437ccf5a2 test: avoid status module reload 2026-05-09 16:53:32 +01:00
Shakker
3307478282 test: stop reloading thinking module 2026-05-09 16:51:29 +01:00
Peter Steinberger
879bddd08f test: tighten embedded message assertions 2026-05-09 16:51:17 +01:00
Shakker
59f31e0484 test: tighten web search late bind assertions 2026-05-09 16:50:17 +01:00
Peter Steinberger
2dff50f947 test: tighten subagent announce assertions 2026-05-09 16:49:58 +01:00
Peter Steinberger
ea11d465e1 test: tighten pi auth discovery assertions 2026-05-09 16:48:44 +01:00
Peter Steinberger
2b2ad43a09 test: tighten context engine lifecycle assertions 2026-05-09 16:46:10 +01:00
Peter Steinberger
e51c007418 test: tighten tts config assertions 2026-05-09 16:43:23 +01:00
Peter Steinberger
a5d33b1c27 test: tighten workspace skill assertions 2026-05-09 16:41:26 +01:00
Peter Steinberger
984c9ac16a test: tighten subagent scope assertions 2026-05-09 16:40:12 +01:00
Peter Steinberger
216f25977d test: tighten subagent query assertions 2026-05-09 16:38:54 +01:00
Peter Steinberger
06be0cf2d5 test: tighten model discovery compat assertions 2026-05-09 16:37:35 +01:00
Peter Steinberger
8d9a108e1a test: tighten lsp spawn assertions 2026-05-09 16:36:33 +01:00
Peter Steinberger
78099d2820 test: tighten process send-key assertions 2026-05-09 16:35:10 +01:00
Peter Steinberger
988a8f009d test: tighten exec approval assertions 2026-05-09 16:33:44 +01:00
Peter Steinberger
864899d1b0 test: tighten exec notify assertions 2026-05-09 16:32:11 +01:00
Peter Steinberger
9cdbc7de43 test: tighten materialization helper assertions 2026-05-09 16:30:54 +01:00
Ayaan Zaidi
0b8857d653 fix(gateway): honor restart continuation retry budget 2026-05-09 20:58:12 +05:30
VACInc
2efb36c623 fix: keep restart continuations from heartbeat racing 2026-05-09 20:58:12 +05:30
VACInc
0c8c620d6f fix: retry restart continuations during shutdown 2026-05-09 20:58:12 +05:30
VACInc
09be7de2b2 fix: preserve restart continuation authority 2026-05-09 20:58:12 +05:30
Peter Steinberger
cc04874b09 test: tighten runtime payload assertions 2026-05-09 16:27:39 +01:00
Peter Steinberger
0ffcba5dd1 test: tighten scope option assertions 2026-05-09 16:25:59 +01:00
Peter Steinberger
34053c8d3a test: tighten forward compat helper assertions 2026-05-09 16:23:29 +01:00
Peter Steinberger
7ad5a2d612 test: tighten agent helper assertions 2026-05-09 16:21:59 +01:00
Peter Steinberger
741bba4999 test: tighten web fetch ssrf assertions 2026-05-09 16:19:22 +01:00
Peter Steinberger
5903c10629 test: tighten session resolution assertions 2026-05-09 16:18:04 +01:00
Peter Steinberger
466dba3df2 test: tighten small tool assertions 2026-05-09 16:16:43 +01:00
Peter Steinberger
3f0c0ce4f4 test: tighten model runtime assertions 2026-05-09 16:14:15 +01:00
Peter Steinberger
02dfdb40da test: tighten provider config assertions 2026-05-09 16:12:37 +01:00
Peter Steinberger
29ca557698 test: tighten auth profile snapshot assertions 2026-05-09 16:11:02 +01:00
Peter Steinberger
63eb82b456 test: tighten oauth manager assertions 2026-05-09 16:09:10 +01:00
Peter Steinberger
4df5543525 test: tighten bootstrap budget assertions 2026-05-09 16:05:42 +01:00
Shakker
6f7862bc71 test: reuse prompt snapshot generation 2026-05-09 16:04:16 +01:00
Peter Steinberger
87dc900e13 test: tighten custom api registry assertions 2026-05-09 16:03:53 +01:00
Peter Steinberger
f7719ae975 test: tighten web tool assertions 2026-05-09 16:02:31 +01:00
Peter Steinberger
0ca5e45aff test: tighten video web tool assertions 2026-05-09 16:01:05 +01:00
Peter Steinberger
7db99b13e9 test: tighten acp parent stream assertions 2026-05-09 15:59:02 +01:00
Peter Steinberger
6c7d46f37b test: tighten sandbox agent config assertions 2026-05-09 15:56:57 +01:00
Shakker
7aa6b47d31 test: isolate system prompt config assertions 2026-05-09 15:55:47 +01:00
Peter Steinberger
0e1e4854b7 test: tighten nodes video assertions 2026-05-09 15:55:09 +01:00
Peter Steinberger
3adb3dc6c2 test: tighten media status assertions 2026-05-09 15:53:38 +01:00
hcl
aeb7d07364 fix(cli-runner): gate raw transcript reseed
Summary:
- Gate raw transcript reseeding behind an explicit CLI backend opt-in.
- Keep auth-profile and auth-epoch invalidations from replaying raw transcript history.
- Add regression coverage, docs, config schema/baseline, and changelog entry for #79713.

Verification:
- pnpm exec oxfmt --check --threads=1 CHANGELOG.md docs/gateway/cli-backends.md docs/gateway/config-agents.md src/agents/cli-runner.reliability.test.ts src/agents/cli-runner/prepare.test.ts src/agents/cli-runner/prepare.ts src/agents/cli-runner/session-history.test.ts src/agents/cli-runner/session-history.ts src/config/types.agent-defaults.ts src/config/zod-schema.core.ts
- pnpm run lint:extensions:bundled
- pnpm deadcode:dependencies
- pnpm test src/agents/cli-runner/session-history.test.ts src/agents/cli-runner/prepare.test.ts src/agents/cli-runner.reliability.test.ts src/config/schema.test.ts src/config/zod-schema.agent-defaults.test.ts
- GitHub CI on b63f3afdc4: lint, prod/test types, docs, dependencies, fast contracts, core/agentic shards, and real behavior proof passed.

Co-authored-by: hclsys <hclsys@openclaw.ai>
2026-05-09 10:52:30 -04:00
Peter Steinberger
565e71da98 test: tighten agent tool log assertions 2026-05-09 15:52:03 +01:00
NVIDIAN
aecd4fba7e fix(feishu): keep group_topic message-tool replies inside the topic (#77151)
Merged via squash.

Prepared head SHA: 3a47a09da1
Co-authored-by: ai-hpc <183861985+ai-hpc@users.noreply.github.com>
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
Reviewed-by: @hxy91819
2026-05-09 22:51:36 +08:00
Alexis Dagues
d44aeb6901 fix(telegram): mirror outbound replies to session transcript
Telegram's deliverReplies dispatches via Grammy SDK directly, bypassing
deliverOutboundPayloads where the channel-mirror writer runs. Outbound
assistant replies were never appended to the session transcript, leaving
Telegram .jsonl files empty (the sessions.json sessionFile path was
populated but the file was never created on disk).

Add an optional transcriptMirror callback param to deliverReplies and
populate it from bot-message-dispatch's deliveryBaseOptions. Reuses the
existing appendAssistantMessageToSessionTranscript helper that
deliverOutboundPayloads already calls. Also mirrors preview-finalized
replies so the transcript captures all final assistant output.

Plugin SDK boundary expansion: re-export
appendAssistantMessageToSessionTranscript from
plugin-sdk/agent-harness-runtime so extension code can call it without
reaching into core src/. API baseline regenerated.

Addresses openclaw#75991 for telegram + CLI runtime combinations.
Supersedes openclaw#77484 (incorporates reviewer feedback: preview-
finalized mirror + changelog entry).
2026-05-09 20:20:25 +05:30
Peter Steinberger
5dfb052f9f test: tighten subagent policy assertions 2026-05-09 15:49:17 +01:00
Peter Steinberger
8c4c1288b9 test: tighten skills assertions 2026-05-09 15:46:34 +01:00
Peter Steinberger
907578a2c5 test: tighten simple completion transport assertions 2026-05-09 15:45:05 +01:00
Peter Steinberger
1582bdd344 test: tighten transcript repair assertions 2026-05-09 15:43:59 +01:00
Shakker
14e9c064ee test: fix clickclack lint failures 2026-05-09 15:43:31 +01:00
Peter Steinberger
5ab7a458ba test: tighten session write lock assertions 2026-05-09 15:42:37 +01:00
Peter Steinberger
c6f2fa5c6f test: tighten sandbox policy assertions 2026-05-09 15:41:18 +01:00
Shakker
9b629758fe test: align clickclack package contracts 2026-05-09 15:38:50 +01:00
Peter Steinberger
4015402534 test: tighten sandbox mounted path assertions 2026-05-09 15:38:27 +01:00
Peter Steinberger
64c5d52ca2 test: tighten bundle settings assertions 2026-05-09 15:36:57 +01:00
Peter Steinberger
e204d1b755 test: tighten compaction wait assertions 2026-05-09 15:35:07 +01:00
Ayaan Zaidi
b6265c1504 fix(telegram): harden command menu cache keys 2026-05-09 20:03:47 +05:30
heejae chang
564ab9b89b Reduce Telegram command menu CPU work 2026-05-09 20:03:47 +05:30
Peter Steinberger
603929909a test: tighten subscribe media assertions 2026-05-09 15:32:15 +01:00
Peter Steinberger
71bef8c7b9 test: tighten transcript rewrite assertions 2026-05-09 15:30:27 +01:00
Peter Steinberger
caf14ceb33 fix: repair clickclack channel metadata 2026-05-09 15:29:27 +01:00
Peter Steinberger
e5e1b7b834 feat: add clickclack channel extension 2026-05-09 15:29:27 +01:00
Peter Steinberger
c62168af8d test: tighten thinking recovery assertions 2026-05-09 15:28:46 +01:00
Peter Steinberger
bb241b22e0 test: tighten sanitize history assertions 2026-05-09 15:27:23 +01:00
Peter Steinberger
3e444875e4 test: tighten transcript policy assertions 2026-05-09 15:25:41 +01:00
Shakker
731b1ed27c test: stabilize gateway websocket startup assertion 2026-05-09 15:25:18 +01:00
Peter Steinberger
884b6af77c test: tighten cron reply seam assertions 2026-05-09 15:23:46 +01:00
Peter Steinberger
4d6091c919 test: tighten openrouter capability assertions 2026-05-09 15:21:44 +01:00
Peter Steinberger
d1a51a6a24 test: tighten openai stream wrapper assertions 2026-05-09 15:20:23 +01:00
Peter Steinberger
a99729fd21 test: tighten effective tool policy assertions 2026-05-09 15:18:49 +01:00
Peter Steinberger
98e93ce7ec test: tighten compaction context assertions 2026-05-09 15:17:40 +01:00
Peter Steinberger
10a6751c87 test: tighten openrouter extra params assertions 2026-05-09 15:16:22 +01:00
Peter Steinberger
1c951e0996 test: tighten bundle mcp assertions 2026-05-09 15:15:07 +01:00
Peter Steinberger
766b4f0668 test: tighten fallback contract assertions 2026-05-09 15:13:48 +01:00
Peter Steinberger
83dd905736 test: tighten mcp stdio assertions 2026-05-09 15:12:10 +01:00
Peter Steinberger
f18e0722cd test: tighten openclaw tools assertions 2026-05-09 15:09:04 +01:00
Peter Steinberger
24d9e16662 test: tighten models config assertions 2026-05-09 15:06:53 +01:00
Peter Steinberger
0a8c98e7cb test: tighten failover recovery assertions 2026-05-09 15:05:16 +01:00
Peter Steinberger
2f73f423c7 test: tighten command session assertions 2026-05-09 15:03:14 +01:00
Peter Steinberger
24e1bbc014 feat: add subagent delegation preference mode 2026-05-09 15:02:44 +01:00
Peter Steinberger
42033929d4 test: tighten cli runner assertions 2026-05-09 15:00:50 +01:00
Peter Steinberger
50cb027a88 docs: document trusted skill symlink targets 2026-05-09 14:59:34 +01:00
Peter Steinberger
b21414e49e test: tighten bash tool assertions 2026-05-09 14:58:21 +01:00
Peter Steinberger
8eaca55cbb test: tighten auth profile assertions 2026-05-09 14:55:56 +01:00
Peter Steinberger
483075ddd4 fix(memory): preserve atomic reindex cleanup cause 2026-05-09 14:53:33 +01:00
Peter Steinberger
d7d53004a9 test: tighten agent tool assertions 2026-05-09 14:53:03 +01:00
Peter Steinberger
8afbe42258 test: tighten subagent assertions 2026-05-09 14:50:26 +01:00
Peter Steinberger
a168fa9ae6 test: tighten session and skills assertions 2026-05-09 14:48:32 +01:00
Peter Steinberger
ce09e594cd test: tighten sandbox assertions 2026-05-09 14:46:06 +01:00
Peter Steinberger
8e0486c6b7 fix: honor Codex dynamic tool timeouts 2026-05-09 14:45:38 +01:00
Peter Steinberger
41714c38a9 test: tighten runtime plan tool assertions 2026-05-09 14:44:14 +01:00
Peter Steinberger
5618a8f8f6 feat: allow trusted skill symlink targets 2026-05-09 14:43:54 +01:00
Peter Steinberger
53a97fe0a7 fix(memory): harden atomic reindex cleanup 2026-05-09 14:43:32 +01:00
Peter Steinberger
8d42854c79 test: tighten provider transport assertion 2026-05-09 14:42:36 +01:00
Shakker
930cedeb7a perf: slim qa channel setup imports 2026-05-09 14:40:14 +01:00
Peter Steinberger
9e5c263db7 test: tighten owner only gating assertion 2026-05-09 14:39:37 +01:00
Peter Steinberger
d466911ea4 test: tighten read truncation assertion 2026-05-09 14:37:26 +01:00
Peter Steinberger
004d1935c8 test: tighten before tool call extension assertion 2026-05-09 14:35:32 +01:00
Peter Steinberger
26816bf852 test: tighten apply patch traversal assertion 2026-05-09 14:33:14 +01:00
Peter Steinberger
e84eb59ea2 test: tighten context pruning placeholder assertion 2026-05-09 14:30:42 +01:00
Peter Steinberger
3925370e70 test: tighten lifecycle billing assertion 2026-05-09 14:28:57 +01:00
Peter Steinberger
36da8c1b9e test: tighten tool schema diagnostic assertion 2026-05-09 14:27:02 +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
4458 changed files with 182427 additions and 72763 deletions

View File

@@ -0,0 +1,37 @@
# Telegram Maintainer Decisions
Use this page during Telegram PR review. These are intentional maintainer decisions, not incidental implementation details.
Verified against Telegram Bot API 10.0, May 8 2026.
## Streaming
- Do not reintroduce `sendMessageDraft` for answer streaming. Telegram drafts are ephemeral 30-second previews in private chats; final delivery still requires a separate `sendMessage`. OpenClaw uses `sendMessage` plus `editMessageText`, then finalizes in place so the user sees one persistent answer.
- Streaming owns one visible preview message. Edit it forward. Do not send an extra final bubble unless the final edit genuinely failed.
- Keep the first-preview debounce. If a provider sends token-sized deltas, coalesce them into cumulative preview text instead of removing the debounce.
- Respect Telegram limits in the Telegram layer. Text over 4096 chars chains into continuation messages. Polls keep the current Bot API 12-option cap.
## Telegram API Ownership
- Prefer grammY primitives and Telegram-native helpers when they model the behavior directly. Avoid custom Bot API wrappers for behavior grammY already owns.
- Throttling is bot-token scoped. All Telegram API clients for the same token share one grammY `apiThrottler()` instance.
- Do not silently retry failed topic sends without topic metadata. A wrong-surface success is worse than a loud Telegram error.
- DM topics and forum topics are distinct. `direct_messages_topic_id` and `message_thread_id` are not interchangeable.
## Context And Authorization
- Reply context comes from OpenClaw-observed messages. Bot API updates expose `reply_to_message`, but there is no arbitrary `getMessage(chat, id)` hydration path later.
- Current local chat context must outrank stale reply ancestry in the prompt. Old replied-to messages should not look like the active conversation.
- Pairing is DM-only. Group and topic authorization need explicit config allowlists.
- Telegram allowlists use numeric sender IDs. Usernames are optional, mutable, and not a reliable arbitrary-user lookup key in the Bot API.
- Group and channel visible replies are policy-controlled. Normal room replies stay private unless `messages.groupChat.visibleReplies: "automatic"` is set or the agent explicitly calls `message.send`.
## Interactive Surfaces
- Native callbacks stay structured. Approval, native command, plugin, select, and multiselect callbacks must not fall through as raw callback text.
- Preserve callback values exactly, including delimiters such as `env|prod`.
- Native slash commands should remain fast-pathable before full workspace and agent-turn setup.
## Review Standard
Telegram behavior PRs need real Telegram proof when they touch transport, streaming, topics, callbacks, authorization, or reply context. Prefer the bot-to-bot QA lane or an equivalent live Telegram probe over synthetic-only validation.

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

@@ -0,0 +1,234 @@
---
name: openclaw-docs
description: Write or review high-quality OpenClaw developer documentation.
dependencies: []
---
# OpenClaw Docs
## Overview
Use this skill when writing, editing, or reviewing OpenClaw developer documentation for APIs, SDKs, CLI tools, integrations, quickstarts, platform guides, or technical product docs.
Write documentation that is concise, helpful, and comprehensive: fast for first success, precise for production, and easy to scan when debugging.
## Core Model
Use an OpenClaw documentation model, strengthened by Write the Docs principles:
- Lead with what the developer is trying to do.
- Give one recommended path before alternatives.
- Make examples runnable and realistic.
- Keep guides task-oriented and references exhaustive.
- Explain production risks exactly where developers can make mistakes.
- Link concepts, guides, API references, SDKs, testing, and troubleshooting so readers can move between them without rereading.
- Treat docs as part of the product lifecycle: draft them before or alongside implementation, review them with code, and keep them current.
- Make each page discoverable, addressable, cumulative, complete within its stated scope, and easy to skim.
## Structure
Choose the page type before writing:
- Overview: route readers to the right product, integration path, or guide.
- Quickstart: get a new user to a working result with the fewest safe steps.
- Topic page: give an end-to-end overview of a major domain entity, with setup,
key subtopics, troubleshooting, and links to deeper references.
- Guide: explain one workflow from prerequisites to production readiness.
- API reference: define every object, endpoint, parameter, enum, response, error, and version rule.
- SDK or CLI reference: document install, auth, commands or methods, options, examples, and failure modes.
- Testing guide: show sandbox setup, fixtures, test data, simulated failures, and live-mode differences.
- Troubleshooting guide: map symptoms to checks, causes, and fixes.
Use this default topic page structure:
1. Title: name the major entity or surface.
2. Overview: explain what it is, what it owns, and what it does not own.
3. Requirements: include only when setup needs specific accounts, versions,
permissions, plugins, operating systems, or credentials.
4. Quickstart: show the recommended setup path and smallest reliable verification.
5. Configuration: show the minimum configuration needed to use the surface,
common variants users must choose between, and where each option is set:
CLI, config file, environment variable, plugin manifest, dashboard, or API.
6. Subtopics: organize the entity's major concepts, workflows, and decisions by
reader intent.
7. Troubleshooting: diagnose common observable failures.
8. Related: link to guides, references, commands, concepts, and adjacent topics.
Topic pages may be longer than quickstarts, but they should not become exhaustive
references. Move field tables, API contracts, narrow internals, legacy details,
and rare debugging workflows to linked reference or troubleshooting pages when
they interrupt the end-to-end overview.
For configuration, keep task-critical options inline. Link to reference docs for
full option lists, defaults, enums, generated schemas, and advanced settings. Do
not duplicate exhaustive config reference tables in topic pages unless the topic
page is itself the reference.
Use this default guide structure:
1. Title: name the outcome, not the implementation detail.
2. Opening: state what the reader can accomplish in one or two sentences.
3. Before you begin: list accounts, keys, permissions, versions, tools, and assumptions.
4. Choose a path: compare options only when the reader must decide.
5. Steps: use verb-led headings with code, expected output, and checks.
6. Test: show the smallest reliable proof that the integration works.
7. Production readiness: cover security, idempotency, retries, limits, observability, migrations, and cleanup.
8. Troubleshooting: include common errors near the workflow that causes them.
9. See also: link to concepts, API references, SDK docs, and adjacent guides.
Keep navigation user-intent based. Do not force readers to understand internal product taxonomy before they can pick a task.
## Documentation Lifecycle
Write and maintain docs with the same discipline as code:
- Draft docs early enough to expose unclear product, API, CLI, or config design.
- Keep docs source near the code, config, command, plugin, or protocol it describes when the repo layout allows it.
- Avoid duplicate truth. If the same contract appears in multiple places, pick the canonical page and link to it.
- Update docs in the same change as behavior, config, API, CLI, plugin, or troubleshooting changes.
- Remove, redirect, or clearly mark stale docs. Incorrect docs are worse than missing docs.
- Involve the right reviewers: code owners for behavior, support or QA for user failure modes, and docs maintainers for structure and style.
- Preserve older-version guidance only when users need it; otherwise document the current supported behavior.
Do not use FAQs as a dumping ground for unrelated material. Promote recurring questions into task, concept, troubleshooting, or reference pages.
## Writing Style
Write in a direct, practical voice:
- Use present tense and active voice.
- Address the reader as "you" when giving instructions.
- Prefer short paragraphs and scannable lists.
- Use concrete nouns: "agent profile", "Gateway webhook", "plugin manifest", "session state".
- Put caveats exactly where they affect the step.
- Avoid marketing language, hype, generic benefits, and vague claims.
- Avoid long conceptual lead-ins before the first actionable step.
- Do not over-explain common developer concepts unless the product has a nonstandard contract.
- Define OpenClaw-specific jargon and abbreviations before first use.
- Use sentence case for headings unless an OpenClaw product name, command, or identifier requires capitalization.
- Use descriptive link text that names the destination or action; avoid vague links such as "this page" or "click here".
- Avoid culturally specific idioms, violent idioms, and jokes that make docs harder to translate or scan.
- Write accessible prose: do not rely on color, screenshots, or visual position as the only way to understand an instruction.
Use headings that describe actions or reference surfaces:
- Good: "Create an agent", "Configure a Slack channel", "Repair plugin installation"
- Avoid: "How it works", "Under the hood", "Important notes" unless the section truly needs that shape
Use precise modal language:
- Use "must" for required behavior.
- Use "can" for optional capability.
- Use "recommended" for the default path.
- Use "avoid" for known footguns.
- Explain "why" only when it changes a developer decision.
## Detail Level
Vary detail by page type:
- Overview pages: be brief; help readers choose.
- Quickstarts: be procedural; include only what is needed for first success.
- Guides: be complete for one workflow; include decisions, side effects, and failure handling.
- References: be exhaustive; document every field, default, enum, nullable value, constraint, response, and error.
- Troubleshooting: be explicit; assume the reader is blocked and needs observable checks.
Go deep where mistakes are expensive:
- Authentication and secret handling
- Money movement, billing, permissions, and irreversible actions
- Webhooks, retries, duplicate events, and ordering
- Idempotency and concurrency
- Sandbox versus production differences
- Versioning, migrations, and backwards compatibility
- Limits, rate limits, quotas, and timeouts
- Error codes and recovery paths
- Data retention, privacy, and compliance-sensitive behavior
Do not bury this detail in a distant reference if developers need it to complete the task safely.
## Examples
Make examples production-shaped, even when using test data:
- Prefer complete copy-pasteable commands or snippets.
- Use realistic variable names and values.
- Mark placeholders clearly with angle-bracket names such as `<API_KEY>` or `<CUSTOMER_ID>`.
- Show expected success output after commands.
- Show full request and response examples for API references when response shape matters.
- Keep one conceptual unit per code block.
- Use language-specific code fences.
- Avoid toy examples that hide required setup, auth, error handling, or cleanup.
When multiple languages are useful, keep the same scenario across languages so readers can compare equivalents.
## Discoverability and Navigation
Design every page so readers can find it, link to it, and decide quickly whether it answers their question:
- Use goal-oriented titles and headings that match likely search terms.
- Start each page with a concise answer to "what can I do here?"
- Include metadata or frontmatter required by the OpenClaw docs index.
- Add "Read when" hints for docs-list routing when creating or changing OpenClaw docs pages that participate in the docs index.
- Link from likely entry points, not only from nearby internal taxonomy pages.
- Keep section headings stable enough for links from issues, PRs, support replies, and chat answers.
- Order tutorials and examples from prerequisites to advanced tasks; order reference pages alphabetically or topically when that helps lookup.
- State scope up front when a page is intentionally partial.
## API Reference Pattern
For endpoints, methods, objects, or commands, include:
1. Short purpose statement.
2. Auth or permission requirements.
3. Request shape, including path, query, headers, and body fields.
4. Parameter table with type, requiredness, default, constraints, enum values, and side effects.
5. Return shape with object lifecycle states.
6. Error cases with codes, causes, and recovery guidance.
7. Runnable example request.
8. Representative successful response.
9. Related guides and adjacent reference pages.
For nested objects, document child fields near their parent. Do not make readers jump across pages to understand the shape of a single request.
## Verification
Verify docs changes like product changes:
- Run the relevant docs build, docs index, formatter, link checker, or generated-doc check when available.
- Run commands, snippets, and examples that the page tells users to run whenever feasible.
- Confirm screenshots, UI labels, CLI output, config keys, flags, defaults, errors, and file paths match current behavior.
- Prefer executable checks over prose-only review for API, CLI, config, generated reference, and troubleshooting docs.
- If a verification step is not feasible, say what was not verified and why.
## Completeness Checks
Before finalizing a page, verify:
- The first screen tells readers what they can accomplish.
- The recommended path is obvious.
- Prerequisites are explicit and testable.
- Examples can run with documented inputs.
- The page has a clear audience: user, operator, plugin author, contributor, or maintainer.
- Test-mode and production-mode behavior are separated.
- Security-sensitive values are never exposed in examples.
- Every warning is attached to the step where it matters.
- Edge cases are documented where they affect implementation.
- API fields include types, defaults, constraints, and errors.
- Troubleshooting starts from observable symptoms.
- Related links help the reader continue without duplicating the page.
- The page says where to get support, file issues, or contribute when that is relevant to the reader's next step.
- The page is complete for the scope it claims, or the limitation is stated up front.
## Review Pass
Edit in this order:
1. Remove repetition and generic explanation.
2. Move conceptual background below the first useful action unless it is required to choose correctly.
3. Replace passive or abstract wording with concrete instructions.
4. Tighten headings until the outline reads like a task map.
5. Add missing operational details for production safety.
6. Check examples for copy-paste accuracy.
7. Add links between guide, reference, SDK, testing, and troubleshooting surfaces.
8. Check discoverability, addressability, accessibility, and docs-as-code verification.

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

View File

@@ -555,6 +555,13 @@ top-level phase timings for preflight, image build, package prep, lane pools,
and cleanup. Use `pnpm test:docker:timings <summary.json>` to rank slow lanes
and phases before deciding whether a broader rerun is justified.
Skill install proof: use `pnpm test:docker:skill-install` or targeted
`docker_lanes=skill-install` for live ClawHub skill-install validation. The
lane installs the package tarball in a bare runner, keeps
`skills.install.allowUploadedArchives=false`, resolves the current live slug
from `openclaw skills search`, installs it, and verifies `.clawhub` origin/lock
metadata. Prefer this checked-in script over inline heredoc Testbox recipes.
## Cheap Docker Reruns
First derive the smallest rerun command from artifacts:

View File

@@ -39,6 +39,7 @@ runs:
- name: Setup pnpm (corepack retry)
shell: bash
env:
COREPACK_ENABLE_DOWNLOAD_PROMPT: "0"
PNPM_VERSION: ${{ inputs.pnpm-version }}
run: |
set -euo pipefail

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

@@ -147,6 +147,8 @@ jobs:
- name: Build dist on cache miss
if: steps.dist-cache.outputs.cache-hit != 'true'
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build:ci-artifacts
- name: Build Control UI on cache miss

View File

@@ -520,6 +520,8 @@ jobs:
install-bun: "false"
- name: Build dist
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build:ci-artifacts
- name: Build Control UI
@@ -602,14 +604,14 @@ jobs:
if [ "$RUN_CHANNELS" = "true" ]; then
start_check "channels" env \
NODE_OPTIONS=--max-old-space-size=6144 \
NODE_OPTIONS=--max-old-space-size=8192 \
OPENCLAW_VITEST_MAX_WORKERS=1 \
pnpm test:channels
fi
if [ "$RUN_CORE_SUPPORT_BOUNDARY" = "true" ]; then
start_check "core-support-boundary" env \
NODE_OPTIONS=--max-old-space-size=6144 \
NODE_OPTIONS=--max-old-space-size=8192 \
OPENCLAW_VITEST_MAX_WORKERS=2 \
node scripts/run-vitest.mjs run --config test/vitest/vitest.full-core-support-boundary.config.ts
fi
@@ -1120,7 +1122,7 @@ jobs:
- name: Run Node 22 compatibility
env:
NODE_OPTIONS: --max-old-space-size=6144
NODE_OPTIONS: --max-old-space-size=8192
run: |
pnpm build
pnpm ui:build
@@ -1200,7 +1202,7 @@ jobs:
- name: Run Node test shard
env:
NODE_OPTIONS: --max-old-space-size=6144
NODE_OPTIONS: --max-old-space-size=8192
OPENCLAW_NODE_TEST_CONFIGS_JSON: ${{ toJson(matrix.configs) }}
OPENCLAW_NODE_TEST_INCLUDE_PATTERNS_JSON: ${{ toJson(matrix.includePatterns) }}
OPENCLAW_VITEST_SHARD_NAME: ${{ matrix.shard_name }}
@@ -1742,7 +1744,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:
@@ -1785,7 +1797,7 @@ jobs:
runs-on: ${{ github.repository == 'openclaw/openclaw' && 'blacksmith-16vcpu-windows-2025' || 'windows-2025' }}
timeout-minutes: 60
env:
NODE_OPTIONS: --max-old-space-size=6144
NODE_OPTIONS: --max-old-space-size=8192
# Keep total concurrency predictable on the smaller Windows runner.
OPENCLAW_VITEST_MAX_WORKERS: 1
OPENCLAW_TEST_SKIP_FULL_EXTENSIONS_SHARD: 1

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

@@ -32,7 +32,7 @@ on:
default: stable
type: choice
options:
- minimum
- beta
- stable
- full
run_release_soak:
@@ -202,7 +202,7 @@ jobs:
needs: [resolve_target]
if: contains(fromJSON('["all","ci"]'), inputs.rerun_group)
runs-on: ubuntu-24.04
timeout-minutes: 240
timeout-minutes: ${{ inputs.release_profile == 'full' && 240 || 60 }}
outputs:
run_id: ${{ steps.dispatch.outputs.run_id }}
url: ${{ steps.dispatch.outputs.url }}
@@ -301,7 +301,7 @@ jobs:
needs: [resolve_target]
if: contains(fromJSON('["all","plugin-prerelease"]'), inputs.rerun_group)
runs-on: ubuntu-24.04
timeout-minutes: 300
timeout-minutes: ${{ inputs.release_profile == 'full' && 300 || 60 }}
outputs:
run_id: ${{ steps.dispatch.outputs.run_id }}
url: ${{ steps.dispatch.outputs.url }}
@@ -400,7 +400,7 @@ jobs:
needs: [resolve_target]
if: contains(fromJSON('["all","release-checks","install-smoke","cross-os","live-e2e","package","qa","qa-parity","qa-live"]'), inputs.rerun_group)
runs-on: ubuntu-24.04
timeout-minutes: 720
timeout-minutes: ${{ inputs.release_profile == 'full' && 720 || 60 }}
outputs:
run_id: ${{ steps.dispatch.outputs.run_id }}
url: ${{ steps.dispatch.outputs.url }}
@@ -616,7 +616,7 @@ jobs:
needs: [resolve_target, prepare_release_package]
if: ${{ always() && contains(fromJSON('["all","npm-telegram"]'), inputs.rerun_group) && (inputs.npm_telegram_package_spec != '' || (inputs.rerun_group == 'all' && inputs.release_profile == 'full')) }}
runs-on: ubuntu-24.04
timeout-minutes: 120
timeout-minutes: ${{ inputs.release_profile == 'full' && 120 || 60 }}
outputs:
run_id: ${{ steps.dispatch.outputs.run_id }}
url: ${{ steps.dispatch.outputs.url }}

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

@@ -12,6 +12,7 @@ on:
- discord-status-reactions-tool-only
- discord-thread-reply-filepath-attachment
- slack-desktop-smoke
- telegram-live
baseline_ref:
description: Optional baseline ref for before/after scenarios
required: false
@@ -90,6 +91,18 @@ jobs:
fi
gh "${args[@]}"
;;
telegram-live)
args=(
workflow run mantis-telegram-live.yml
--repo "$GITHUB_REPOSITORY"
--ref main
-f "candidate_ref=${CANDIDATE_REF}"
)
if [[ -n "${PR_NUMBER:-}" ]]; then
args+=(-f "pr_number=${PR_NUMBER}")
fi
gh "${args[@]}"
;;
*)
echo "Unsupported Mantis scenario: ${SCENARIO_ID}" >&2
exit 1

View File

@@ -0,0 +1,500 @@
name: Mantis Telegram Live
on:
issue_comment:
types: [created]
workflow_dispatch:
inputs:
candidate_ref:
description: Ref, tag, or SHA to verify with Telegram live QA
required: true
default: main
type: string
pr_number:
description: Optional PR number to receive the QA evidence comment
required: false
type: string
scenario:
description: Optional comma-separated Telegram scenario ids
required: false
default: telegram-status-command
type: string
crabbox_provider:
description: Crabbox provider for the desktop transcript capture
required: false
default: aws
type: choice
options:
- aws
- hetzner
crabbox_lease_id:
description: Optional existing Crabbox desktop/browser lease id or slug to reuse
required: false
type: string
permissions:
contents: write
issues: write
pull-requests: write
concurrency:
group: mantis-telegram-live-${{ github.event.issue.number || inputs.pr_number || inputs.candidate_ref || github.run_id }}-${{ github.run_attempt }}
cancel-in-progress: false
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
NODE_VERSION: "24.x"
PNPM_VERSION: "10.33.0"
OPENCLAW_BUILD_PRIVATE_QA: "1"
OPENCLAW_ENABLE_PRIVATE_QA_CLI: "1"
CRABBOX_REF: main
jobs:
authorize_actor:
name: Authorize workflow actor
if: >-
${{
github.event_name == 'workflow_dispatch' ||
(
github.event_name == 'issue_comment' &&
github.event.issue.pull_request &&
(
contains(github.event.comment.body, '@Mantis') ||
contains(github.event.comment.body, '@mantis') ||
contains(github.event.comment.body, '/mantis')
)
)
}}
runs-on: ubuntu-24.04
steps:
- name: Require maintainer-level repository access
uses: actions/github-script@v8
with:
script: |
const allowed = new Set(["admin", "maintain", "write"]);
const { owner, repo } = context.repo;
const { data } = await github.rest.repos.getCollaboratorPermissionLevel({
owner,
repo,
username: context.actor,
});
const permission = data.permission;
core.info(`Actor ${context.actor} permission: ${permission}`);
if (!allowed.has(permission)) {
core.setFailed(
`Workflow requires write/maintain/admin access. Actor "${context.actor}" has "${permission}".`,
);
}
resolve_request:
name: Resolve Mantis request
needs: authorize_actor
runs-on: ubuntu-24.04
outputs:
candidate_ref: ${{ steps.resolve.outputs.candidate_ref }}
crabbox_provider: ${{ steps.resolve.outputs.crabbox_provider }}
lease_id: ${{ steps.resolve.outputs.lease_id }}
pr_number: ${{ steps.resolve.outputs.pr_number }}
request_source: ${{ steps.resolve.outputs.request_source }}
scenario: ${{ steps.resolve.outputs.scenario }}
should_run: ${{ steps.resolve.outputs.should_run }}
steps:
- name: Resolve refs and target PR
id: resolve
uses: actions/github-script@v8
with:
script: |
const eventName = context.eventName;
function setOutput(name, value) {
core.setOutput(name, value ?? "");
core.info(`${name}=${value ?? ""}`);
}
if (eventName === "workflow_dispatch") {
const inputs = context.payload.inputs ?? {};
setOutput("should_run", "true");
setOutput("candidate_ref", inputs.candidate_ref || "main");
setOutput("pr_number", inputs.pr_number || "");
setOutput("scenario", inputs.scenario || "telegram-status-command");
setOutput("crabbox_provider", inputs.crabbox_provider || "aws");
setOutput("lease_id", inputs.crabbox_lease_id || "");
setOutput("request_source", "workflow_dispatch");
return;
}
if (eventName !== "issue_comment") {
core.setFailed(`Unsupported event: ${eventName}`);
return;
}
const issue = context.payload.issue;
const body = context.payload.comment?.body ?? "";
if (!issue?.pull_request) {
core.setFailed("Mantis issue_comment trigger requires a pull request comment.");
return;
}
const normalized = body.toLowerCase();
const requested =
(normalized.includes("@mantis") || normalized.includes("/mantis")) &&
normalized.includes("telegram");
if (!requested) {
core.notice("Comment mentioned Mantis but did not request Telegram live QA.");
setOutput("should_run", "false");
setOutput("candidate_ref", "");
setOutput("pr_number", "");
setOutput("scenario", "");
setOutput("crabbox_provider", "");
setOutput("lease_id", "");
setOutput("request_source", "unsupported_issue_comment");
return;
}
const { owner, repo } = context.repo;
const { data: pr } = await github.rest.pulls.get({
owner,
repo,
pull_number: issue.number,
});
const candidateMatch = body.match(/(?:candidate|head)[\s:=]+([^\s`]+)/i);
const scenarioMatch = body.match(/(?:scenario|scenarios)[\s:=]+([^\s`]+)/i);
const providerMatch = body.match(/(?:provider|crabbox_provider)[\s:=]+([^\s`]+)/i);
const leaseMatch = body.match(/(?:lease|lease_id|crabbox_lease_id)[\s:=]+([^\s`]+)/i);
const rawCandidate = candidateMatch?.[1];
const candidate =
rawCandidate && !["head", "pr", "pr-head"].includes(rawCandidate.toLowerCase())
? rawCandidate
: pr.head.sha;
const provider = providerMatch?.[1] || "aws";
if (!["aws", "hetzner"].includes(provider)) {
core.setFailed(`Unsupported Crabbox provider for Mantis Telegram: ${provider}`);
return;
}
setOutput("should_run", "true");
setOutput("candidate_ref", candidate);
setOutput("pr_number", String(issue.number));
setOutput("scenario", scenarioMatch?.[1] || "telegram-status-command");
setOutput("crabbox_provider", provider);
setOutput("lease_id", leaseMatch?.[1] || "");
setOutput("request_source", "issue_comment");
await github.rest.reactions.createForIssueComment({
owner,
repo,
comment_id: context.payload.comment.id,
content: "eyes",
}).catch((error) => core.warning(`Could not add eyes reaction: ${error.message}`));
validate_ref:
name: Validate candidate ref
needs: resolve_request
if: ${{ needs.resolve_request.outputs.should_run == 'true' }}
runs-on: ubuntu-24.04
outputs:
candidate_revision: ${{ steps.validate.outputs.candidate_revision }}
steps:
- name: Checkout harness ref
uses: actions/checkout@v6
with:
persist-credentials: false
fetch-depth: 0
- name: Validate ref is trusted
id: validate
env:
GH_TOKEN: ${{ github.token }}
CANDIDATE_REF: ${{ needs.resolve_request.outputs.candidate_ref }}
shell: bash
run: |
set -euo pipefail
git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main
revision="$(git rev-parse "${CANDIDATE_REF}^{commit}")"
reason=""
if git merge-base --is-ancestor "$revision" refs/remotes/origin/main; then
reason="main-ancestor"
elif git tag --points-at "$revision" | grep -Eq '^v'; then
reason="release-tag"
else
pr_head_count="$(
gh api \
-H "Accept: application/vnd.github+json" \
"repos/${GITHUB_REPOSITORY}/commits/${revision}/pulls" \
--jq '[.[] | select(.state == "open" and .head.repo.full_name == "'"${GITHUB_REPOSITORY}"'" and .head.sha == "'"${revision}"'")] | length'
)"
if [[ "$pr_head_count" != "0" ]]; then
reason="open-pr-head"
fi
fi
if [[ -z "$reason" ]]; then
echo "Candidate ref '${CANDIDATE_REF}' resolved to ${revision}, which is not trusted for this secret-bearing Mantis run." >&2
exit 1
fi
echo "candidate_revision=${revision}" >> "$GITHUB_OUTPUT"
{
echo "candidate: \`${CANDIDATE_REF}\`"
echo "candidate SHA: \`${revision}\`"
echo "candidate trust reason: \`${reason}\`"
} >> "$GITHUB_STEP_SUMMARY"
run_telegram_live:
name: Run Telegram live QA with Crabbox evidence
needs: [resolve_request, validate_ref]
if: ${{ needs.resolve_request.outputs.should_run == 'true' }}
runs-on: ubuntu-24.04
timeout-minutes: 180
environment: qa-live-shared
outputs:
comparison_status: ${{ steps.run_mantis.outputs.comparison_status }}
output_dir: ${{ steps.run_mantis.outputs.output_dir }}
steps:
- name: Checkout harness ref
uses: actions/checkout@v6
with:
persist-credentials: false
fetch-depth: 0
- name: Setup Node environment
uses: ./.github/actions/setup-node-env
with:
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
install-bun: "true"
- name: Build Mantis harness
run: pnpm build
- name: Cache Mantis candidate pnpm store
uses: actions/cache@v4
with:
path: |
~/.local/share/pnpm/store
~/.cache/pnpm
key: mantis-telegram-pnpm-${{ runner.os }}-${{ env.NODE_VERSION }}-${{ hashFiles('pnpm-lock.yaml') }}
restore-keys: |
mantis-telegram-pnpm-${{ runner.os }}-${{ env.NODE_VERSION }}-
- name: Setup Go for Crabbox CLI
uses: actions/setup-go@v6
with:
go-version: "1.26.x"
cache: false
- name: Install Crabbox CLI
shell: bash
run: |
set -euo pipefail
install_dir="${RUNNER_TEMP}/crabbox"
mkdir -p "$install_dir/src" "$HOME/.local/bin"
git init "$install_dir/src"
git -C "$install_dir/src" remote add origin https://github.com/openclaw/crabbox.git
git -C "$install_dir/src" fetch --depth 1 origin "$CRABBOX_REF"
git -C "$install_dir/src" checkout --detach FETCH_HEAD
go build -C "$install_dir/src" -o "$HOME/.local/bin/crabbox" ./cmd/crabbox
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
"$HOME/.local/bin/crabbox" --version
"$HOME/.local/bin/crabbox" warmup --help > "$install_dir/warmup-help.txt" 2>&1
grep -q -- "-desktop" "$install_dir/warmup-help.txt"
"$HOME/.local/bin/crabbox" media preview --help >/dev/null
- name: Prepare candidate worktree
env:
CANDIDATE_SHA: ${{ needs.validate_ref.outputs.candidate_revision }}
shell: bash
run: |
set -euo pipefail
worktree_root=".artifacts/qa-e2e/mantis/telegram-live-worktrees"
mkdir -p "$worktree_root"
git worktree add --detach "$worktree_root/candidate" "$CANDIDATE_SHA"
pnpm --dir "$worktree_root/candidate" install --frozen-lockfile --prefer-offline
pnpm --dir "$worktree_root/candidate" build
- name: Run Telegram live scenario and capture desktop evidence
id: run_mantis
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENCLAW_QA_CONVEX_SITE_URL: ${{ secrets.OPENCLAW_QA_CONVEX_SITE_URL }}
OPENCLAW_QA_CONVEX_SECRET_CI: ${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }}
OPENCLAW_QA_REDACT_PUBLIC_METADATA: "1"
OPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT: "1"
CRABBOX_COORDINATOR: ${{ secrets.CRABBOX_COORDINATOR }}
CRABBOX_COORDINATOR_TOKEN: ${{ secrets.CRABBOX_COORDINATOR_TOKEN }}
OPENCLAW_QA_MANTIS_CRABBOX_COORDINATOR: ${{ secrets.OPENCLAW_QA_MANTIS_CRABBOX_COORDINATOR }}
OPENCLAW_QA_MANTIS_CRABBOX_COORDINATOR_TOKEN: ${{ secrets.OPENCLAW_QA_MANTIS_CRABBOX_COORDINATOR_TOKEN }}
CRABBOX_ACCESS_CLIENT_ID: ${{ secrets.CRABBOX_ACCESS_CLIENT_ID }}
CRABBOX_ACCESS_CLIENT_SECRET: ${{ secrets.CRABBOX_ACCESS_CLIENT_SECRET }}
CRABBOX_LEASE_ID: ${{ needs.resolve_request.outputs.lease_id }}
CRABBOX_PROVIDER: ${{ needs.resolve_request.outputs.crabbox_provider }}
SCENARIO_INPUT: ${{ needs.resolve_request.outputs.scenario }}
CANDIDATE_SHA: ${{ needs.validate_ref.outputs.candidate_revision }}
shell: bash
run: |
set -euo pipefail
require_var() {
local key="$1"
if [[ -z "${!key:-}" ]]; then
echo "Missing required ${key}." >&2
exit 1
fi
}
CRABBOX_COORDINATOR="${CRABBOX_COORDINATOR:-${OPENCLAW_QA_MANTIS_CRABBOX_COORDINATOR:-}}"
CRABBOX_COORDINATOR_TOKEN="${CRABBOX_COORDINATOR_TOKEN:-${OPENCLAW_QA_MANTIS_CRABBOX_COORDINATOR_TOKEN:-}}"
export CRABBOX_COORDINATOR CRABBOX_COORDINATOR_TOKEN
require_var OPENAI_API_KEY
require_var OPENCLAW_QA_CONVEX_SITE_URL
require_var OPENCLAW_QA_CONVEX_SECRET_CI
require_var CRABBOX_COORDINATOR_TOKEN
candidate_repo="$(pwd)/.artifacts/qa-e2e/mantis/telegram-live-worktrees/candidate"
output_rel=".artifacts/qa-e2e/mantis/telegram-live"
root="$candidate_repo/$output_rel"
echo "output_dir=${root}" >> "$GITHUB_OUTPUT"
model="${OPENCLAW_CI_OPENAI_MODEL:-openai/gpt-5.4}"
scenario_args=()
if [[ -n "${SCENARIO_INPUT// }" ]]; then
IFS=',' read -r -a raw_scenarios <<<"${SCENARIO_INPUT}"
for raw in "${raw_scenarios[@]}"; do
scenario="$(printf '%s' "${raw}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
if [[ -n "${scenario}" ]]; then
scenario_args+=(--scenario "${scenario}")
fi
done
fi
set +e
pnpm --dir "$candidate_repo" openclaw qa telegram \
--repo-root "$candidate_repo" \
--output-dir "$output_rel" \
--provider-mode live-frontier \
--model "$model" \
--alt-model "$model" \
--fast \
--credential-source convex \
--credential-role ci \
--allow-failures \
"${scenario_args[@]}"
telegram_exit=$?
set -e
if [[ ! -f "$root/telegram-qa-summary.json" ]]; then
echo "Telegram live QA did not produce a summary." >&2
exit "$telegram_exit"
fi
echo "telegram_exit=${telegram_exit}" >> "$GITHUB_OUTPUT"
node "${GITHUB_WORKSPACE}/scripts/mantis/build-telegram-evidence.mjs" \
--output-dir "$root" \
--candidate-ref "$CANDIDATE_SHA" \
--candidate-sha "$CANDIDATE_SHA" \
--scenario-label "${SCENARIO_INPUT:-telegram-live}"
comparison_status="$(jq -r 'if .comparison.pass then "pass" else "fail" end' "$root/mantis-evidence.json")"
echo "comparison_status=${comparison_status}" >> "$GITHUB_OUTPUT"
desktop_args=()
if [[ -n "${CRABBOX_LEASE_ID:-}" ]]; then
desktop_args+=(--lease-id "$CRABBOX_LEASE_ID")
fi
pnpm --dir "$candidate_repo" openclaw qa mantis desktop-browser-smoke \
--repo-root "$candidate_repo" \
--html-file "$output_rel/telegram-live-transcript.html" \
--output-dir "$output_rel/desktop-browser" \
--provider "$CRABBOX_PROVIDER" \
--class standard \
--idle-timeout 45m \
--ttl 120m \
--video-duration 18 \
"${desktop_args[@]}"
cp "$root/desktop-browser/desktop-browser-smoke.png" "$root/telegram-live-desktop.png"
if [[ -f "$root/desktop-browser/desktop-browser-smoke.mp4" ]]; then
cp "$root/desktop-browser/desktop-browser-smoke.mp4" "$root/telegram-live.mp4"
fi
if [[ -f "$root/telegram-live.mp4" ]]; then
if ! command -v ffmpeg >/dev/null 2>&1 || ! command -v ffprobe >/dev/null 2>&1; then
sudo apt-get update -y >/tmp/mantis-telegram-ffmpeg-apt.log 2>&1 || true
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y ffmpeg >>/tmp/mantis-telegram-ffmpeg-apt.log 2>&1 || true
fi
if ! crabbox media preview \
--input "$root/telegram-live.mp4" \
--output "$root/telegram-live-preview.gif" \
--trimmed-video-output "$root/telegram-live-change.mp4" \
--json > "$root/telegram-live-preview.json"; then
rm -f "$root/telegram-live-preview.gif"
rm -f "$root/telegram-live-change.mp4"
rm -f "$root/telegram-live-preview.json"
echo "::warning::Could not generate Telegram motion-trimmed desktop preview."
fi
fi
cat "$root/telegram-qa-report.md" >> "$GITHUB_STEP_SUMMARY"
- name: Upload Mantis Telegram artifacts
id: upload_artifact
if: ${{ always() && steps.run_mantis.outputs.output_dir != '' }}
uses: actions/upload-artifact@v4
with:
name: mantis-telegram-live-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ steps.run_mantis.outputs.output_dir }}
retention-days: 14
if-no-files-found: warn
- name: Create Mantis GitHub App token
id: mantis_app_token
if: ${{ always() && needs.resolve_request.outputs.pr_number != '' }}
uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.MANTIS_GITHUB_APP_ID }}
private-key: ${{ secrets.MANTIS_GITHUB_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: ${{ github.event.repository.name }}
permission-contents: write
permission-issues: write
permission-pull-requests: write
- name: Comment PR with inline QA evidence
if: ${{ always() && needs.resolve_request.outputs.pr_number != '' && steps.run_mantis.outputs.output_dir != '' }}
env:
GH_TOKEN: ${{ steps.mantis_app_token.outputs.token }}
TARGET_PR: ${{ needs.resolve_request.outputs.pr_number }}
ARTIFACT_URL: ${{ steps.upload_artifact.outputs.artifact-url }}
REQUEST_SOURCE: ${{ needs.resolve_request.outputs.request_source }}
shell: bash
run: |
set -euo pipefail
root="${{ steps.run_mantis.outputs.output_dir }}"
if [[ ! -f "$root/mantis-evidence.json" ]]; then
echo "No Mantis evidence manifest found; skipping PR evidence comment."
exit 0
fi
artifact_url_args=()
if [[ -n "${ARTIFACT_URL:-}" ]]; then
artifact_url_args=(--artifact-url "$ARTIFACT_URL")
fi
node scripts/mantis/publish-pr-evidence.mjs \
--manifest "$root/mantis-evidence.json" \
--target-pr "$TARGET_PR" \
--artifact-root "mantis/telegram-live/pr-${TARGET_PR}/run-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" \
--marker "<!-- mantis-telegram-live -->" \
"${artifact_url_args[@]}" \
--run-url "https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" \
--request-source "$REQUEST_SOURCE"
- name: Fail when Mantis Telegram failed
if: ${{ always() && steps.run_mantis.outputs.output_dir != '' && (steps.run_mantis.outputs.comparison_status != 'pass' || steps.run_mantis.outputs.telegram_exit != '0') }}
env:
COMPARISON_STATUS: ${{ steps.run_mantis.outputs.comparison_status }}
TELEGRAM_EXIT: ${{ steps.run_mantis.outputs.telegram_exit }}
run: |
echo "Mantis Telegram live failed: comparison=${COMPARISON_STATUS:-unset} telegram_exit=${TELEGRAM_EXIT:-unset}." >&2
exit 1

View File

@@ -94,7 +94,7 @@ on:
default: stable
type: choice
options:
- minimum
- beta
- stable
- full
workflow_call:
@@ -385,22 +385,21 @@ jobs:
if [[ -n "$live_model_providers" ]]; then
add_suite docker-live-models
else
add_profile_suite docker-live-models "minimum stable full"
add_profile_suite docker-live-models "beta minimum stable full"
fi
if [[ "$LIVE_MODELS_ONLY" != "true" ]]; then
add_suite live-cache
add_suite openai-ws-stream-live-e2e
add_profile_suite native-live-src-agents "stable full"
add_profile_suite native-live-src-gateway-core "minimum stable full"
add_profile_suite native-live-src-gateway-core "beta minimum stable full"
add_profile_suite native-live-src-gateway-profiles-anthropic "stable full"
add_profile_suite native-live-src-gateway-profiles-anthropic-smoke "stable"
add_profile_suite native-live-src-gateway-profiles-anthropic-opus "full"
add_profile_suite native-live-src-gateway-profiles-anthropic-sonnet-haiku "full"
add_profile_suite native-live-src-gateway-profiles-google "stable full"
add_profile_suite native-live-src-gateway-profiles-minimax "stable full"
add_profile_suite native-live-src-gateway-profiles-openai "minimum stable full"
add_profile_suite native-live-src-gateway-profiles-openai "beta minimum stable full"
add_profile_suite native-live-src-gateway-profiles-fireworks "full"
add_profile_suite native-live-src-gateway-profiles-deepseek "full"
add_profile_suite native-live-src-gateway-profiles-opencode-go "full"
@@ -413,11 +412,11 @@ jobs:
add_profile_suite native-live-test "stable full"
add_profile_suite native-live-extensions-l-n "full"
add_profile_suite native-live-extensions-moonshot "full"
add_profile_suite native-live-extensions-openai "minimum stable full"
add_profile_suite native-live-extensions-openai "beta minimum stable full"
add_profile_suite native-live-extensions-o-z-other "full"
add_profile_suite native-live-extensions-xai "full"
add_profile_suite live-gateway-docker "minimum stable full"
add_profile_suite live-gateway-docker "beta minimum stable full"
add_profile_suite live-gateway-anthropic-docker "stable full"
add_profile_suite live-gateway-google-docker "stable full"
add_profile_suite live-gateway-minimax-docker "stable full"
@@ -506,7 +505,7 @@ jobs:
needs: validate_selected_ref
if: inputs.include_repo_e2e && inputs.live_suite_filter == ''
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 90
timeout-minutes: ${{ inputs.release_test_profile == 'full' && 90 || 60 }}
env:
OPENCLAW_VITEST_MAX_WORKERS: "2"
steps:
@@ -524,6 +523,8 @@ jobs:
install-bun: "true"
- name: Build dist for repo E2E
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build
- name: Run repo E2E suite
@@ -531,7 +532,7 @@ jobs:
validate_special_e2e:
needs: validate_selected_ref
if: (inputs.include_repo_e2e || (inputs.include_live_suites && !inputs.live_models_only)) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == 'openshell-e2e' || inputs.live_suite_filter == 'openai-ws-stream-live-e2e')
if: inputs.include_repo_e2e && (inputs.live_suite_filter == '' || inputs.live_suite_filter == 'openshell-e2e')
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: ${{ matrix.timeout_minutes }}
strategy:
@@ -541,15 +542,9 @@ jobs:
- suite_id: openshell-e2e
label: OpenShell repo E2E
command: pnpm test:e2e:openshell
timeout_minutes: 120
timeout_minutes: 60
requires_repo_e2e: true
requires_live_suites: false
- suite_id: openai-ws-stream-live-e2e
label: OpenAI WebSocket live E2E
command: pnpm test:e2e src/agents/openai-ws-stream.e2e.test.ts
timeout_minutes: 90
requires_repo_e2e: false
requires_live_suites: true
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENCLAW_E2E_WORKERS: "1"
@@ -575,6 +570,8 @@ jobs:
(inputs.include_live_suites && matrix.requires_live_suites)
) &&
(inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id)
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build
- name: Configure suite-specific env
@@ -583,9 +580,7 @@ jobs:
run: |
set -euo pipefail
case "${{ matrix.suite_id }}" in
openai-ws-stream-live-e2e)
echo "OPENAI_LIVE_TEST=1" >> "$GITHUB_ENV"
echo "OPENCLAW_LIVE_TEST=1" >> "$GITHUB_ENV"
openshell-e2e)
;;
esac
@@ -595,11 +590,7 @@ jobs:
run: |
set -euo pipefail
case "${{ matrix.suite_id }}" in
openai-ws-stream-live-e2e)
[[ -n "${OPENAI_API_KEY:-}" ]] || {
echo "OPENAI_API_KEY is required for the OpenAI WebSocket live E2E suite." >&2
exit 1
}
openshell-e2e)
;;
esac
@@ -624,46 +615,60 @@ jobs:
include:
- chunk_id: core
label: core
timeout_minutes: 120
timeout_minutes: 60
profiles: stable full
- chunk_id: package-update-openai
label: package/update OpenAI install
timeout_minutes: 180
timeout_minutes: 20
profiles: beta minimum stable full
- chunk_id: package-update-anthropic
label: package/update Anthropic install
timeout_minutes: 180
timeout_minutes: 60
profiles: beta minimum stable full
- chunk_id: package-update-core
label: package/update core
timeout_minutes: 120
timeout_minutes: 60
profiles: beta minimum stable full
- chunk_id: plugins-runtime-plugins
label: plugins/runtime plugins
timeout_minutes: 120
timeout_minutes: 60
profiles: stable full
- chunk_id: plugins-runtime-services
label: plugins/runtime services
timeout_minutes: 120
timeout_minutes: 60
profiles: stable full
- chunk_id: plugins-runtime-install-a
label: plugins/runtime install A
timeout_minutes: 120
timeout_minutes: 60
profiles: stable full
- chunk_id: plugins-runtime-install-b
label: plugins/runtime install B
timeout_minutes: 120
timeout_minutes: 60
profiles: stable full
- chunk_id: plugins-runtime-install-c
label: plugins/runtime install C
timeout_minutes: 120
timeout_minutes: 60
profiles: stable full
- chunk_id: plugins-runtime-install-d
label: plugins/runtime install D
timeout_minutes: 120
timeout_minutes: 60
profiles: stable full
- chunk_id: plugins-runtime-install-e
label: plugins/runtime install E
timeout_minutes: 120
timeout_minutes: 60
profiles: stable full
- chunk_id: plugins-runtime-install-f
label: plugins/runtime install F
timeout_minutes: 120
timeout_minutes: 60
profiles: stable full
- chunk_id: plugins-runtime-install-g
label: plugins/runtime install G
timeout_minutes: 120
timeout_minutes: 60
profiles: stable full
- chunk_id: plugins-runtime-install-h
label: plugins/runtime install H
timeout_minutes: 120
timeout_minutes: 60
profiles: stable full
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL }}
@@ -716,6 +721,7 @@ jobs:
OPENCLAW_DOCKER_E2E_PACKAGE_ARTIFACT_NAME: ${{ inputs.package_artifact_name || 'docker-e2e-package' }}
OPENCLAW_DOCKER_E2E_REPO_ROOT: ${{ github.workspace }}
OPENCLAW_DOCKER_E2E_SELECTED_SHA: ${{ needs.validate_selected_ref.outputs.selected_sha }}
OPENCLAW_DOCKER_ALL_RELEASE_PROFILE: ${{ inputs.release_test_profile }}
OPENCLAW_CURRENT_PACKAGE_TGZ: .artifacts/docker-e2e-package/openclaw-current.tgz
OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPEC: ${{ inputs.published_upgrade_survivor_baseline }}
OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPECS: ${{ inputs.published_upgrade_survivor_baselines }}
@@ -725,12 +731,14 @@ jobs:
DOCKER_E2E_CHUNK: ${{ matrix.chunk_id }}
steps:
- name: Checkout selected ref
if: contains(matrix.profiles, inputs.release_test_profile)
uses: actions/checkout@v6
with:
ref: ${{ needs.validate_selected_ref.outputs.selected_sha }}
fetch-depth: 1
- name: Checkout trusted release harness
if: contains(matrix.profiles, inputs.release_test_profile)
uses: actions/checkout@v6
with:
ref: ${{ github.sha }}
@@ -738,6 +746,7 @@ jobs:
path: .release-harness
- name: Log in to GHCR for shared Docker E2E image
if: contains(matrix.profiles, inputs.release_test_profile)
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
with:
registry: ghcr.io
@@ -745,6 +754,7 @@ jobs:
password: ${{ github.token }}
- name: Setup Node environment
if: contains(matrix.profiles, inputs.release_test_profile)
uses: ./.github/actions/setup-node-env
with:
node-version: ${{ env.NODE_VERSION }}
@@ -752,14 +762,17 @@ jobs:
install-bun: "true"
- name: Hydrate live auth/profile inputs
if: contains(matrix.profiles, inputs.release_test_profile)
run: bash scripts/ci-hydrate-live-auth.sh
- name: Plan Docker E2E chunk
if: contains(matrix.profiles, inputs.release_test_profile)
id: plan
shell: bash
env:
CHUNK: ${{ matrix.chunk_id }}
INCLUDE_OPENWEBUI: ${{ inputs.include_openwebui }}
RELEASE_TEST_PROFILE: ${{ inputs.release_test_profile }}
run: |
set -euo pipefail
if [[ -z "$CHUNK" ]]; then
@@ -771,6 +784,7 @@ jobs:
export OPENCLAW_DOCKER_ALL_PROFILE=release-path
export OPENCLAW_DOCKER_ALL_CHUNK="$CHUNK"
export OPENCLAW_DOCKER_ALL_INCLUDE_OPENWEBUI="$INCLUDE_OPENWEBUI"
export OPENCLAW_DOCKER_ALL_RELEASE_PROFILE="$RELEASE_TEST_PROFILE"
plan_path=".artifacts/docker-tests/release-${CHUNK}-plan.json"
node .release-harness/scripts/test-docker-all.mjs --plan-json > "$plan_path"
@@ -778,27 +792,28 @@ jobs:
echo "plan_json=$plan_path" >> "$GITHUB_OUTPUT"
- name: Download OpenClaw Docker E2E package
if: steps.plan.outputs.needs_package == '1'
if: contains(matrix.profiles, inputs.release_test_profile) && steps.plan.outputs.needs_package == '1'
uses: actions/download-artifact@v8
with:
name: ${{ inputs.package_artifact_name || 'docker-e2e-package' }}
path: .artifacts/docker-e2e-package
- name: Pull shared bare Docker E2E image
if: steps.plan.outputs.needs_bare_image == '1'
if: contains(matrix.profiles, inputs.release_test_profile) && steps.plan.outputs.needs_bare_image == '1'
shell: bash
run: |
set -euo pipefail
bash .release-harness/scripts/ci-docker-pull-retry.sh "${OPENCLAW_DOCKER_E2E_BARE_IMAGE}"
- name: Pull shared functional Docker E2E image
if: steps.plan.outputs.needs_functional_image == '1'
if: contains(matrix.profiles, inputs.release_test_profile) && steps.plan.outputs.needs_functional_image == '1'
shell: bash
run: |
set -euo pipefail
bash .release-harness/scripts/ci-docker-pull-retry.sh "${OPENCLAW_DOCKER_E2E_FUNCTIONAL_IMAGE}"
- name: Validate Docker E2E credentials
if: contains(matrix.profiles, inputs.release_test_profile)
shell: bash
env:
CREDENTIALS: ${{ steps.plan.outputs.credentials }}
@@ -817,11 +832,13 @@ jobs:
fi
- name: Run Docker E2E chunk
if: contains(matrix.profiles, inputs.release_test_profile)
shell: bash
run: |
set -euo pipefail
export OPENCLAW_DOCKER_ALL_PROFILE=release-path
export OPENCLAW_DOCKER_ALL_CHUNK="${DOCKER_E2E_CHUNK}"
export OPENCLAW_DOCKER_ALL_RELEASE_PROFILE="${OPENCLAW_DOCKER_ALL_RELEASE_PROFILE}"
export OPENCLAW_DOCKER_ALL_BUILD=0
export OPENCLAW_DOCKER_ALL_PREFLIGHT=0
export OPENCLAW_DOCKER_ALL_FAIL_FAST=0
@@ -886,7 +903,7 @@ jobs:
if: inputs.docker_lanes != ''
name: Docker E2E targeted lanes (${{ matrix.group.label }})
runs-on: blacksmith-32vcpu-ubuntu-2404
timeout-minutes: 90
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
@@ -1095,7 +1112,7 @@ jobs:
if: inputs.include_openwebui && !inputs.include_release_path_suites && inputs.docker_lanes == ''
name: Docker E2E (openwebui)
runs-on: blacksmith-32vcpu-ubuntu-2404
timeout-minutes: 75
timeout-minutes: 60
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL }}
@@ -1222,7 +1239,7 @@ jobs:
needs: validate_selected_ref
if: inputs.include_release_path_suites || inputs.include_openwebui || inputs.docker_lanes != ''
runs-on: blacksmith-32vcpu-ubuntu-2404
timeout-minutes: 90
timeout-minutes: ${{ inputs.release_test_profile == 'full' && 90 || 60 }}
permissions:
actions: read
contents: read
@@ -1261,6 +1278,7 @@ jobs:
LANES: ${{ inputs.docker_lanes }}
INCLUDE_RELEASE_PATH_SUITES: ${{ inputs.include_release_path_suites }}
INCLUDE_OPENWEBUI: ${{ inputs.include_openwebui }}
RELEASE_TEST_PROFILE: ${{ inputs.release_test_profile }}
OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPEC: ${{ inputs.published_upgrade_survivor_baseline }}
OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPECS: ${{ inputs.published_upgrade_survivor_baselines }}
OPENCLAW_UPGRADE_SURVIVOR_SCENARIOS: ${{ inputs.published_upgrade_survivor_scenarios }}
@@ -1277,6 +1295,7 @@ jobs:
export OPENCLAW_DOCKER_ALL_LANES=openwebui
fi
export OPENCLAW_DOCKER_ALL_INCLUDE_OPENWEBUI="$INCLUDE_OPENWEBUI"
export OPENCLAW_DOCKER_ALL_RELEASE_PROFILE="$RELEASE_TEST_PROFILE"
plan_path=".artifacts/docker-tests/plan.json"
node .release-harness/scripts/test-docker-all.mjs --plan-json > "$plan_path"
@@ -1553,7 +1572,7 @@ jobs:
profiles: stable full
- provider_label: OpenAI
providers: openai
profiles: minimum stable full
profiles: beta minimum stable full
- provider_label: OpenCode
providers: opencode-go
profiles: full
@@ -1872,15 +1891,15 @@ jobs:
- suite_id: native-live-src-agents
label: Native live agents
command: node .release-harness/scripts/test-live-shard.mjs native-live-src-agents
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: stable full
- suite_id: native-live-src-gateway-core
label: Native live gateway core
command: node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-core
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: minimum stable full
profiles: beta minimum stable full
- suite_id: native-live-src-gateway-profiles-anthropic-smoke
suite_group: native-live-src-gateway-profiles-anthropic
label: Native live gateway profiles Anthropic smoke
@@ -1892,72 +1911,72 @@ jobs:
suite_group: native-live-src-gateway-profiles-anthropic
label: Native live gateway profiles Anthropic Opus
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=anthropic OPENCLAW_LIVE_GATEWAY_MODELS=anthropic/claude-opus-4-7,anthropic/claude-opus-4-6 node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: full
- suite_id: native-live-src-gateway-profiles-anthropic-sonnet-haiku
suite_group: native-live-src-gateway-profiles-anthropic
label: Native live gateway profiles Anthropic Sonnet/Haiku
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=anthropic OPENCLAW_LIVE_GATEWAY_MODELS=anthropic/claude-sonnet-4-6,anthropic/claude-haiku-4-5 node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: full
- suite_id: native-live-src-gateway-profiles-google
label: Native live gateway profiles Google
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=google OPENCLAW_LIVE_GATEWAY_MODELS=google/gemini-3.1-pro-preview,google/gemini-3-flash-preview node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: stable full
- suite_id: native-live-src-gateway-profiles-minimax
label: Native live gateway profiles MiniMax
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=minimax,minimax-portal OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2 node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: stable full
- suite_id: native-live-src-gateway-profiles-openai
label: Native live gateway profiles OpenAI
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=openai OPENCLAW_LIVE_GATEWAY_MODELS=openai/gpt-5.5 node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: minimum stable full
profiles: beta minimum stable full
- suite_id: native-live-src-gateway-profiles-fireworks
label: Native live gateway profiles Fireworks
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=fireworks node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: full
- suite_id: native-live-src-gateway-profiles-deepseek
label: Native live gateway profiles DeepSeek
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=deepseek node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: full
- suite_id: native-live-src-gateway-profiles-opencode-go-deepseek-glm
suite_group: native-live-src-gateway-profiles-opencode-go
label: Native live gateway profiles OpenCode Go DeepSeek/GLM
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=opencode-go OPENCLAW_LIVE_GATEWAY_MODELS=opencode-go/deepseek-v4-flash,opencode-go/deepseek-v4-pro,opencode-go/glm-5,opencode-go/glm-5.1 node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: full
- suite_id: native-live-src-gateway-profiles-opencode-go-kimi
suite_group: native-live-src-gateway-profiles-opencode-go
label: Native live gateway profiles OpenCode Go Kimi
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=opencode-go OPENCLAW_LIVE_GATEWAY_MODELS=opencode-go/kimi-k2.5,opencode-go/kimi-k2.6 node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: full
- suite_id: native-live-src-gateway-profiles-opencode-go-mimo
suite_group: native-live-src-gateway-profiles-opencode-go
label: Native live gateway profiles OpenCode Go MiMo
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=opencode-go OPENCLAW_LIVE_GATEWAY_MODELS=opencode-go/mimo-v2-omni,opencode-go/mimo-v2-pro,opencode-go/mimo-v2.5,opencode-go/mimo-v2.5-pro node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: full
- suite_id: native-live-src-gateway-profiles-opencode-go-minimax-qwen
suite_group: native-live-src-gateway-profiles-opencode-go
label: Native live gateway profiles OpenCode Go MiniMax/Qwen
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=opencode-go OPENCLAW_LIVE_GATEWAY_MODELS=opencode-go/minimax-m2.5,opencode-go/minimax-m2.7,opencode-go/qwen3.5-plus,opencode-go/qwen3.6-plus node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: full
- suite_id: native-live-src-gateway-profiles-opencode-go-smoke
@@ -1969,25 +1988,25 @@ jobs:
- suite_id: native-live-src-gateway-profiles-openrouter
label: Native live gateway profiles OpenRouter
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=openrouter node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: full
- suite_id: native-live-src-gateway-profiles-xai
label: Native live gateway profiles xAI
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=xai node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: full
- suite_id: native-live-src-gateway-profiles-zai
label: Native live gateway profiles Z.ai
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=zai node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: full
- suite_id: native-live-src-gateway-backends
label: Native live gateway backends
command: node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-backends
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: stable full
- suite_id: native-live-src-infra
@@ -1999,13 +2018,13 @@ jobs:
- suite_id: native-live-test
label: Native live test harnesses
command: node .release-harness/scripts/test-live-shard.mjs native-live-test
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: stable full
- suite_id: native-live-extensions-l-n
label: Native live plugins L-N
command: node .release-harness/scripts/test-live-shard.mjs native-live-extensions-l-n
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: full
- suite_id: native-live-extensions-moonshot
@@ -2018,19 +2037,19 @@ jobs:
- suite_id: native-live-extensions-openai
label: Native live OpenAI plugin
command: node .release-harness/scripts/test-live-shard.mjs native-live-extensions-openai
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: minimum stable full
profiles: beta minimum stable full
- suite_id: native-live-extensions-o-z-other
label: Native live plugins O-Z other
command: node .release-harness/scripts/test-live-shard.mjs native-live-extensions-o-z-other
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: full
- suite_id: native-live-extensions-xai
label: Native live xAI plugin
command: node .release-harness/scripts/test-live-shard.mjs native-live-extensions-xai
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: full
env:
@@ -2197,7 +2216,7 @@ jobs:
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=openai OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=30000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=60000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 25m bash .release-harness/scripts/test-live-gateway-models-docker.sh
timeout_minutes: 30
profile_env_only: false
profiles: minimum stable full
profiles: beta minimum stable full
- suite_id: live-gateway-anthropic-docker
label: Docker live gateway Anthropic
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=anthropic OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=30000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=60000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 25m bash .release-harness/scripts/test-live-gateway-models-docker.sh
@@ -2400,53 +2419,53 @@ jobs:
- suite_id: native-live-extensions-a-k
label: Native live plugins A-K
command: node .release-harness/scripts/test-live-shard.mjs native-live-extensions-a-k
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: full
- suite_id: native-live-extensions-media-audio
label: Native live media audio plugins
command: node .release-harness/scripts/test-live-shard.mjs native-live-extensions-media-audio
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: full
- suite_id: native-live-extensions-media-music-google
label: Native live media music Google
command: OPENCLAW_LIVE_MUSIC_GENERATION_PROVIDERS=google node .release-harness/scripts/test-live-shard.mjs native-live-extensions-media-music-google
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: full
- suite_id: native-live-extensions-media-music-minimax
label: Native live media music MiniMax
command: OPENCLAW_LIVE_MUSIC_GENERATION_PROVIDERS=minimax node .release-harness/scripts/test-live-shard.mjs native-live-extensions-media-music-minimax
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: full
- suite_id: native-live-extensions-media-video-a
suite_group: native-live-extensions-media-video
label: Native live media video plugins A
command: OPENCLAW_LIVE_VIDEO_GENERATION_PROVIDERS=alibaba,byteplus,deepinfra,fal node .release-harness/scripts/test-live-shard.mjs native-live-extensions-media-video
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: full
- suite_id: native-live-extensions-media-video-b
suite_group: native-live-extensions-media-video
label: Native live media video plugins B
command: OPENCLAW_LIVE_VIDEO_GENERATION_PROVIDERS=google,minimax node .release-harness/scripts/test-live-shard.mjs native-live-extensions-media-video
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: full
- suite_id: native-live-extensions-media-video-c
suite_group: native-live-extensions-media-video
label: Native live media video plugins C
command: OPENCLAW_LIVE_VIDEO_GENERATION_PROVIDERS=openai,openrouter,xai node .release-harness/scripts/test-live-shard.mjs native-live-extensions-media-video
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: full
- suite_id: native-live-extensions-media-video-d
suite_group: native-live-extensions-media-video
label: Native live media video plugins D
command: OPENCLAW_LIVE_VIDEO_GENERATION_PROVIDERS=qwen,runway,together,vydra node .release-harness/scripts/test-live-shard.mjs native-live-extensions-media-video
timeout_minutes: 90
timeout_minutes: 60
profile_env_only: false
profiles: full
env:

View File

@@ -239,6 +239,9 @@ jobs:
exit 1
fi
RELEASE_SHA="$(git rev-parse HEAD)"
PACKAGE_VERSION="$(node -p "require('./package.json').version")"
TARBALL_NAME="$(basename "$PACK_PATH")"
TARBALL_SHA256="$(sha256sum "$PACK_PATH" | awk '{print $1}')"
ARTIFACT_DIR="$RUNNER_TEMP/openclaw-npm-preflight"
rm -rf "$ARTIFACT_DIR"
mkdir -p "$ARTIFACT_DIR"
@@ -246,6 +249,24 @@ jobs:
printf '%s\n' "$RELEASE_TAG" > "$ARTIFACT_DIR/release-tag.txt"
printf '%s\n' "$RELEASE_SHA" > "$ARTIFACT_DIR/release-sha.txt"
printf '%s\n' "$RELEASE_NPM_DIST_TAG" > "$ARTIFACT_DIR/release-npm-dist-tag.txt"
ARTIFACT_DIR="$ARTIFACT_DIR" RELEASE_TAG="$RELEASE_TAG" RELEASE_SHA="$RELEASE_SHA" RELEASE_NPM_DIST_TAG="$RELEASE_NPM_DIST_TAG" PACKAGE_VERSION="$PACKAGE_VERSION" TARBALL_NAME="$TARBALL_NAME" TARBALL_SHA256="$TARBALL_SHA256" node <<'NODE'
const fs = require("node:fs");
const path = require("node:path");
const manifest = {
version: 1,
releaseTag: process.env.RELEASE_TAG,
releaseSha: process.env.RELEASE_SHA,
npmDistTag: process.env.RELEASE_NPM_DIST_TAG,
packageName: "openclaw",
packageVersion: process.env.PACKAGE_VERSION,
tarballName: process.env.TARBALL_NAME,
tarballSha256: process.env.TARBALL_SHA256,
};
fs.writeFileSync(
path.join(process.env.ARTIFACT_DIR, "preflight-manifest.json"),
`${JSON.stringify(manifest, null, 2)}\n`,
);
NODE
echo "dir=$ARTIFACT_DIR" >> "$GITHUB_OUTPUT"
- name: Upload prepared npm publish bundle
@@ -379,17 +400,17 @@ jobs:
run: |
set -euo pipefail
EXPECTED_RELEASE_SHA="$(git rev-parse HEAD)"
TAG_FILE="preflight-tarball/release-tag.txt"
SHA_FILE="preflight-tarball/release-sha.txt"
NPM_DIST_TAG_FILE="preflight-tarball/release-npm-dist-tag.txt"
if [[ ! -f "$TAG_FILE" || ! -f "$SHA_FILE" || ! -f "$NPM_DIST_TAG_FILE" ]]; then
MANIFEST_FILE="preflight-tarball/preflight-manifest.json"
if [[ ! -f "$MANIFEST_FILE" ]]; then
echo "Prepared preflight metadata is missing." >&2
ls -la preflight-tarball >&2 || true
exit 1
fi
ARTIFACT_RELEASE_TAG="$(tr -d '\r\n' < "$TAG_FILE")"
ARTIFACT_RELEASE_SHA="$(tr -d '\r\n' < "$SHA_FILE")"
ARTIFACT_RELEASE_NPM_DIST_TAG="$(tr -d '\r\n' < "$NPM_DIST_TAG_FILE")"
ARTIFACT_RELEASE_TAG="$(jq -r '.releaseTag // ""' "$MANIFEST_FILE")"
ARTIFACT_RELEASE_SHA="$(jq -r '.releaseSha // ""' "$MANIFEST_FILE")"
ARTIFACT_RELEASE_NPM_DIST_TAG="$(jq -r '.npmDistTag // ""' "$MANIFEST_FILE")"
ARTIFACT_TARBALL_NAME="$(jq -r '.tarballName // ""' "$MANIFEST_FILE")"
ARTIFACT_TARBALL_SHA256="$(jq -r '.tarballSha256 // ""' "$MANIFEST_FILE")"
if [[ "$ARTIFACT_RELEASE_TAG" != "$RELEASE_TAG" ]]; then
echo "Prepared preflight tag mismatch: expected $RELEASE_TAG, got $ARTIFACT_RELEASE_TAG" >&2
exit 1
@@ -402,6 +423,15 @@ jobs:
echo "Prepared preflight npm dist-tag mismatch: expected $RELEASE_NPM_DIST_TAG, got $ARTIFACT_RELEASE_NPM_DIST_TAG" >&2
exit 1
fi
if [[ -z "$ARTIFACT_TARBALL_NAME" || ! -f "preflight-tarball/$ARTIFACT_TARBALL_NAME" ]]; then
echo "Prepared preflight tarball named in manifest is missing: $ARTIFACT_TARBALL_NAME" >&2
exit 1
fi
actual_tarball_sha256="$(sha256sum "preflight-tarball/$ARTIFACT_TARBALL_NAME" | awk '{print $1}')"
if [[ "$actual_tarball_sha256" != "$ARTIFACT_TARBALL_SHA256" ]]; then
echo "Prepared preflight tarball digest mismatch." >&2
exit 1
fi
- name: Resolve publish tarball
id: publish_tarball

View File

@@ -36,7 +36,7 @@ on:
default: stable
type: choice
options:
- minimum
- beta
- stable
- full
run_release_soak:
@@ -259,7 +259,18 @@ jobs:
else
run_release_soak=true
fi
if [[ "$RELEASE_PROFILE_INPUT" == "full" ]]; then
release_profile="$RELEASE_PROFILE_INPUT"
if [[ "$release_profile" == "minimum" ]]; then
release_profile=beta
fi
case "$release_profile" in
beta|stable|full) ;;
*)
echo "release_profile must be one of: beta, stable, full" >&2
exit 1
;;
esac
if [[ "$release_profile" == "full" ]]; then
run_release_soak=true
fi
@@ -330,7 +341,7 @@ jobs:
printf 'ref=%s\n' "$RELEASE_REF_INPUT"
printf 'provider=%s\n' "$RELEASE_PROVIDER_INPUT"
printf 'mode=%s\n' "$RELEASE_MODE_INPUT"
printf 'release_profile=%s\n' "$RELEASE_PROFILE_INPUT"
printf 'release_profile=%s\n' "$release_profile"
printf 'run_release_soak=%s\n' "$run_release_soak"
printf 'rerun_group=%s\n' "$RELEASE_RERUN_GROUP_INPUT"
printf 'live_suite_filter=%s\n' "$RELEASE_LIVE_SUITE_FILTER_INPUT"
@@ -350,7 +361,7 @@ jobs:
RELEASE_REF_FAST_PATH: ${{ steps.fast_ref.outputs.fast }}
RELEASE_PROVIDER: ${{ inputs.provider }}
RELEASE_MODE: ${{ inputs.mode }}
RELEASE_PROFILE: ${{ inputs.release_profile }}
RELEASE_PROFILE: ${{ steps.inputs.outputs.release_profile }}
RUN_RELEASE_SOAK: ${{ steps.inputs.outputs.run_release_soak }}
RELEASE_RERUN_GROUP: ${{ inputs.rerun_group }}
RELEASE_LIVE_SUITE_FILTER: ${{ inputs.live_suite_filter }}
@@ -572,7 +583,7 @@ jobs:
ref: ${{ needs.resolve_target.outputs.revision }}
include_repo_e2e: false
include_release_path_suites: true
include_openwebui: ${{ needs.resolve_target.outputs.release_profile != 'minimum' }}
include_openwebui: ${{ needs.resolve_target.outputs.release_profile != 'beta' }}
include_live_suites: false
release_test_profile: ${{ needs.resolve_target.outputs.release_profile }}
package_artifact_name: ${{ needs.prepare_release_package.outputs.artifact_name }}
@@ -593,13 +604,13 @@ jobs:
source: ${{ needs.resolve_target.outputs.package_acceptance_package_spec != '' && 'npm' || 'artifact' }}
package_spec: ${{ needs.resolve_target.outputs.package_acceptance_package_spec || 'openclaw@beta' }}
artifact_name: ${{ needs.prepare_release_package.outputs.artifact_name }}
package_sha256: ${{ needs.prepare_release_package.outputs.package_sha256 }}
package_sha256: ${{ needs.resolve_target.outputs.package_acceptance_package_spec == '' && needs.prepare_release_package.outputs.package_sha256 || '' }}
suite_profile: custom
docker_lanes: doctor-switch update-channel-switch update-corrupt-plugin upgrade-survivor published-upgrade-survivor update-restart-auth plugins-offline plugin-update
docker_lanes: doctor-switch update-channel-switch skill-install update-corrupt-plugin upgrade-survivor published-upgrade-survivor update-restart-auth plugins-offline plugin-update
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 }}
@@ -693,6 +704,8 @@ jobs:
install-bun: "true"
- name: Build private QA runtime
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build
- name: Run parity lane
@@ -705,11 +718,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
@@ -770,6 +783,8 @@ jobs:
merge-multiple: true
- name: Build private QA runtime
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build
- name: Generate parity report
@@ -779,7 +794,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
@@ -821,6 +836,8 @@ jobs:
install-bun: "true"
- name: Build private QA runtime
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build
- name: Run Matrix live lane
@@ -918,6 +935,8 @@ jobs:
require_var OPENCLAW_QA_CONVEX_SECRET_CI
- name: Build private QA runtime
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build
- name: Run Telegram live lane
@@ -1012,6 +1031,8 @@ jobs:
require_var OPENCLAW_QA_CONVEX_SECRET_CI
- name: Build private QA runtime
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build
- name: Run Discord live lane
@@ -1106,6 +1127,8 @@ jobs:
require_var OPENCLAW_QA_CONVEX_SECRET_CI
- name: Build private QA runtime
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build
- name: Run WhatsApp live lane
@@ -1200,6 +1223,8 @@ jobs:
require_var OPENCLAW_QA_CONVEX_SECRET_CI
- name: Build private QA runtime
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build
- name: Run Slack live lane

View File

@@ -37,6 +37,15 @@ on:
required: true
default: true
type: boolean
release_profile:
description: Release coverage profile used for release evidence summaries
required: false
default: beta
type: choice
options:
- beta
- stable
- full
wait_for_clawhub:
description: Wait for ClawHub plugin publish before marking this workflow complete
required: true
@@ -62,7 +71,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 20
outputs:
sha: ${{ steps.ref.outputs.sha }}
sha: ${{ steps.manifest.outputs.sha || steps.ref.outputs.sha }}
steps:
- name: Validate inputs
env:
@@ -72,6 +81,7 @@ jobs:
PLUGIN_PUBLISH_SCOPE: ${{ inputs.plugin_publish_scope }}
PLUGINS: ${{ inputs.plugins }}
RELEASE_NPM_DIST_TAG: ${{ inputs.npm_dist_tag }}
RELEASE_PROFILE: ${{ inputs.release_profile }}
WORKFLOW_REF: ${{ github.ref }}
run: |
set -euo pipefail
@@ -103,6 +113,23 @@ jobs:
echo "plugin_publish_scope=all-publishable must not include plugins." >&2
exit 1
fi
case "$RELEASE_PROFILE" in
beta|stable|full) ;;
*)
echo "release_profile must be one of: beta, stable, full" >&2
exit 1
;;
esac
- name: Download OpenClaw npm preflight manifest
if: ${{ inputs.publish_openclaw_npm }}
uses: actions/download-artifact@v8
with:
name: openclaw-npm-preflight-${{ inputs.tag }}
path: ${{ runner.temp }}/openclaw-npm-preflight-manifest
repository: ${{ github.repository }}
run-id: ${{ inputs.preflight_run_id }}
github-token: ${{ github.token }}
- name: Checkout release tag
uses: actions/checkout@v6
@@ -111,17 +138,54 @@ jobs:
fetch-depth: 0
persist-credentials: false
- name: Setup Node environment
uses: ./.github/actions/setup-node-env
with:
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
install-bun: "false"
- name: Resolve checked-out release ref
id: ref
run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
- name: Validate OpenClaw npm preflight manifest
id: manifest
if: ${{ inputs.publish_openclaw_npm }}
env:
RELEASE_TAG: ${{ inputs.tag }}
RELEASE_NPM_DIST_TAG: ${{ inputs.npm_dist_tag }}
EXPECTED_SHA: ${{ steps.ref.outputs.sha }}
run: |
set -euo pipefail
preflight_dir="${RUNNER_TEMP}/openclaw-npm-preflight-manifest"
manifest="${preflight_dir}/preflight-manifest.json"
if [[ ! -f "$manifest" ]]; then
echo "OpenClaw npm preflight manifest is missing." >&2
ls -la "$preflight_dir" >&2 || true
exit 1
fi
release_tag="$(jq -r '.releaseTag // ""' "$manifest")"
release_sha="$(jq -r '.releaseSha // ""' "$manifest")"
npm_dist_tag="$(jq -r '.npmDistTag // ""' "$manifest")"
tarball_name="$(jq -r '.tarballName // ""' "$manifest")"
tarball_sha256="$(jq -r '.tarballSha256 // ""' "$manifest")"
if [[ "$release_tag" != "$RELEASE_TAG" ]]; then
echo "Preflight manifest tag mismatch: expected $RELEASE_TAG, got $release_tag" >&2
exit 1
fi
if [[ "$release_sha" != "$EXPECTED_SHA" ]]; then
echo "Preflight manifest SHA mismatch: expected $EXPECTED_SHA, got $release_sha" >&2
exit 1
fi
if [[ "$npm_dist_tag" != "$RELEASE_NPM_DIST_TAG" ]]; then
echo "Preflight manifest npm dist-tag mismatch: expected $RELEASE_NPM_DIST_TAG, got $npm_dist_tag" >&2
exit 1
fi
if [[ -z "$tarball_name" || ! -f "${preflight_dir}/${tarball_name}" ]]; then
echo "Preflight manifest tarball is missing: $tarball_name" >&2
exit 1
fi
actual_tarball_sha256="$(sha256sum "${preflight_dir}/${tarball_name}" | awk '{print $1}')"
if [[ "$actual_tarball_sha256" != "$tarball_sha256" ]]; then
echo "Preflight manifest tarball digest mismatch." >&2
exit 1
fi
echo "sha=$release_sha" >> "$GITHUB_OUTPUT"
- name: Validate release tag is reachable from main or release branch
run: |
set -euo pipefail
@@ -139,26 +203,25 @@ jobs:
echo "Release tag must point to a commit reachable from main or release/*." >&2
exit 1
- name: Verify plugin versions were synced for this release
run: pnpm plugins:sync:check
- name: Summarize release target
env:
RELEASE_TAG: ${{ inputs.tag }}
TARGET_SHA: ${{ steps.ref.outputs.sha }}
TARGET_SHA: ${{ steps.manifest.outputs.sha || steps.ref.outputs.sha }}
RELEASE_PROFILE: ${{ inputs.release_profile }}
run: |
{
echo "### Release target"
echo
echo "- Tag: \`${RELEASE_TAG}\`"
echo "- SHA: \`${TARGET_SHA}\`"
echo "- Release profile: \`${RELEASE_PROFILE}\`"
} >> "$GITHUB_STEP_SUMMARY"
publish:
name: Publish plugins, then OpenClaw
needs: [resolve_release_target]
runs-on: ubuntu-latest
timeout-minutes: 360
timeout-minutes: 60
steps:
- name: Dispatch publish workflows
env:
@@ -274,15 +337,22 @@ jobs:
changelog_file="${RUNNER_TEMP}/CHANGELOG.md"
notes_file="${RUNNER_TEMP}/release-notes.md"
gh api --repo "$GITHUB_REPOSITORY" "repos/${GITHUB_REPOSITORY}/contents/CHANGELOG.md?ref=${TARGET_SHA}" \
gh api "repos/${GITHUB_REPOSITORY}/contents/CHANGELOG.md?ref=${TARGET_SHA}" \
--jq '.content' | base64 --decode > "${changelog_file}"
awk -v version="${notes_version}" '
$0 == "## " version { in_section = 1; next }
/^## / && in_section { exit }
in_section { print }
' "${changelog_file}" > "${notes_file}"
if [[ ! -s "${notes_file}" ]] && [[ "${RELEASE_TAG}" == *"-alpha."* || "${RELEASE_TAG}" == *"-beta."* ]]; then
awk '
$0 == "## Unreleased" { in_section = 1; next }
/^## / && in_section { exit }
in_section { print }
' "${changelog_file}" > "${notes_file}"
fi
if [[ ! -s "${notes_file}" ]]; then
echo "CHANGELOG.md does not contain release notes for ${notes_version}." >&2
echo "CHANGELOG.md does not contain release notes for ${notes_version} or an Unreleased prerelease fallback." >&2
exit 1
fi

View File

@@ -386,10 +386,10 @@ jobs:
docker_lanes="npm-onboard-channel-agent gateway-network config-reload"
;;
package)
docker_lanes="npm-onboard-channel-agent doctor-switch update-channel-switch update-corrupt-plugin upgrade-survivor published-upgrade-survivor update-restart-auth plugins-offline plugin-update"
docker_lanes="npm-onboard-channel-agent doctor-switch update-channel-switch skill-install update-corrupt-plugin upgrade-survivor published-upgrade-survivor update-restart-auth plugins-offline plugin-update"
;;
product)
docker_lanes="npm-onboard-channel-agent doctor-switch update-channel-switch update-corrupt-plugin upgrade-survivor published-upgrade-survivor update-restart-auth plugins plugin-update mcp-channels cron-mcp-cleanup openai-web-search-minimal openwebui"
docker_lanes="npm-onboard-channel-agent doctor-switch update-channel-switch skill-install update-corrupt-plugin upgrade-survivor published-upgrade-survivor update-restart-auth plugins plugin-update mcp-channels cron-mcp-cleanup openai-web-search-minimal openwebui"
include_openwebui=true
;;
full)

View File

@@ -270,7 +270,7 @@ jobs:
- name: Run release-only plugin Node shard
env:
NODE_OPTIONS: --max-old-space-size=6144
NODE_OPTIONS: --max-old-space-size=8192
OPENCLAW_NODE_TEST_CONFIGS_JSON: ${{ toJson(matrix.configs) }}
OPENCLAW_NODE_TEST_INCLUDE_PATTERNS_JSON: ${{ toJson(matrix.includePatterns) }}
OPENCLAW_VITEST_SHARD_NAME: ${{ matrix.shard_name }}
@@ -340,7 +340,7 @@ jobs:
- name: Run extension shard
env:
NODE_OPTIONS: --max-old-space-size=6144
NODE_OPTIONS: --max-old-space-size=8192
OPENCLAW_EXTENSION_BATCH_PARALLEL: 2
OPENCLAW_VITEST_MAX_WORKERS: 1
OPENCLAW_EXTENSION_BATCH: ${{ matrix.extensions_csv }}

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

View File

@@ -0,0 +1,202 @@
name: Website Installer Sync
on:
pull_request:
paths:
- scripts/install.sh
- scripts/install-cli.sh
- scripts/install.ps1
- .github/workflows/website-installer-sync.yml
push:
branches: [main]
paths:
- scripts/install.sh
- scripts/install-cli.sh
- scripts/install.ps1
- .github/workflows/website-installer-sync.yml
workflow_dispatch:
inputs:
sync_website:
description: Sync openclaw.ai after verification
required: false
default: false
type: boolean
permissions:
contents: read
concurrency:
group: website-installer-sync-${{ github.event_name == 'workflow_dispatch' && github.run_id || github.ref }}
cancel-in-progress: ${{ github.event_name != 'workflow_dispatch' }}
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
jobs:
static:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Install ShellCheck
run: sudo apt-get update -y && sudo apt-get install -y shellcheck
- name: Shell syntax
run: bash -n scripts/install.sh scripts/install-cli.sh
- name: ShellCheck
run: shellcheck -e SC1091 scripts/install.sh scripts/install-cli.sh
- name: Installer help and dry-runs
run: |
bash scripts/install.sh --help >/tmp/install-help.txt
bash scripts/install.sh --dry-run --no-onboard --no-prompt
bash scripts/install-cli.sh --help >/tmp/install-cli-help.txt
- name: PowerShell syntax
shell: pwsh
run: |
$errors = $null
$null = [System.Management.Automation.PSParser]::Tokenize(
(Get-Content -Raw scripts/install.ps1),
[ref]$errors
)
if ($errors -and $errors.Count -gt 0) {
$errors | Format-List | Out-String | Write-Error
exit 1
}
linux-docker:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: install.sh in Docker
run: |
docker run --rm \
-e OPENCLAW_NO_ONBOARD=1 \
-e OPENCLAW_NO_PROMPT=1 \
-v "$PWD/scripts/install.sh:/tmp/install.sh:ro" \
node:24-bookworm-slim \
bash -lc 'bash /tmp/install.sh --no-prompt --no-onboard --version latest && openclaw --version'
- name: install-cli.sh in Docker
run: |
docker run --rm \
-e OPENCLAW_NO_ONBOARD=1 \
-e OPENCLAW_NO_PROMPT=1 \
-v "$PWD/scripts/install-cli.sh:/tmp/install-cli.sh:ro" \
node:24-bookworm-slim \
bash -lc 'apt-get update -y && apt-get install -y curl && bash /tmp/install-cli.sh --prefix /tmp/openclaw --no-onboard --version latest && /tmp/openclaw/bin/openclaw --version'
macos-installer:
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 24
- name: install.sh dry run
run: bash scripts/install.sh --dry-run --no-onboard --no-prompt
- name: install.sh on macOS
env:
OPENCLAW_NO_ONBOARD: "1"
OPENCLAW_NO_PROMPT: "1"
run: |
bash scripts/install.sh --no-onboard --no-prompt --version latest
openclaw --version
windows-installer:
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 24
- name: install.ps1 dry run
shell: pwsh
run: .\scripts\install.ps1 -DryRun -NoOnboard -InstallMethod npm
sync-website:
needs: [static, linux-docker, macos-installer, windows-installer]
if: >
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
(github.event_name == 'workflow_dispatch' && inputs.sync_website)
runs-on: ubuntu-24.04
steps:
- name: Checkout OpenClaw
uses: actions/checkout@v6
with:
path: openclaw
- name: Checkout openclaw.ai
uses: actions/checkout@v6
with:
repository: openclaw/openclaw.ai
token: ${{ secrets.OPENCLAW_GH_TOKEN }}
path: openclaw.ai
- name: Sync installer scripts
run: |
cp openclaw/scripts/install.sh openclaw.ai/public/install.sh
cp openclaw/scripts/install-cli.sh openclaw.ai/public/install-cli.sh
cp openclaw/scripts/install.ps1 openclaw.ai/public/install.ps1
rm -f openclaw.ai/public/install.cmd
chmod +x openclaw.ai/public/install.sh openclaw.ai/public/install-cli.sh
- name: Check for changes
id: changes
working-directory: openclaw.ai
run: |
if git diff --quiet -- public/install.sh public/install-cli.sh public/install.ps1 public/install.cmd; then
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
- name: Setup Bun
if: steps.changes.outputs.changed == 'true'
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Setup Node.js
if: steps.changes.outputs.changed == 'true'
uses: actions/setup-node@v6
with:
node-version: "24"
- name: Install ShellCheck
if: steps.changes.outputs.changed == 'true'
run: sudo apt-get update -y && sudo apt-get install -y shellcheck
- name: Verify website with synced installers
if: steps.changes.outputs.changed == 'true'
working-directory: openclaw.ai
run: |
bash -n public/install.sh public/install-cli.sh
shellcheck -e SC1091 public/install.sh public/install-cli.sh
bun install --frozen-lockfile
bun run build
- name: Commit and push website sync
if: steps.changes.outputs.changed == 'true'
working-directory: openclaw.ai
run: |
git config user.name "openclaw-installer-sync[bot]"
git config user.email "openclaw-installer-sync[bot]@users.noreply.github.com"
git add public/install.sh public/install-cli.sh public/install.ps1 public/install.cmd
git commit -m "chore: sync installers from openclaw ${GITHUB_SHA::12}"
git pull --rebase origin main
git push origin HEAD:main

5
.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
@@ -113,6 +117,7 @@ USER.md
!.agents/skills/crabbox/**
!.agents/skills/gitcrawl/
!.agents/skills/gitcrawl/**
!.agents/skills/openclaw-docs/**
!.agents/skills/openclaw-ghsa-maintainer/
!.agents/skills/openclaw-ghsa-maintainer/**
!.agents/skills/openclaw-parallels-smoke/

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

@@ -93,3 +93,12 @@ scripts/run-tests*
scripts/lib/test-*
scripts/lib/extension-test-*
scripts/lib/vitest-*
# ----------------------------------------------------------------------------
# Sibling symlinks for scoped guides
# ----------------------------------------------------------------------------
# Every `AGENTS.md` has a sibling `CLAUDE.md` symlink pointing at it (see
# root AGENTS.md: "New AGENTS.md: add sibling CLAUDE.md symlink"). Scanning
# the symlinks is redundant with scanning the underlying AGENTS.md and
# breaks opengrep's PR-diff scan when a new CLAUDE.md symlink is added.
CLAUDE.md

View File

@@ -71,7 +71,8 @@ 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.
- Bare GitHub issue/PR URL or number => `review <ref>`: load repo maintainer skill if available, inspect live with `gh`, report findings in chat. No comments/close/merge/fix unless explicitly asked.
- 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 +158,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

@@ -101,7 +101,7 @@ RUN pnpm canvas:a2ui:bundle || \
echo "/* A2UI bundle unavailable in this build */" > extensions/canvas/src/host/a2ui/a2ui.bundle.js && \
echo "stub" > extensions/canvas/src/host/a2ui/.bundle.hash && \
rm -rf vendor/a2ui apps/shared/OpenClawKit/Tools/CanvasA2UI)
RUN pnpm build:docker
RUN NODE_OPTIONS=--max-old-space-size=8192 pnpm build:docker
# Force pnpm for UI build (Bun may fail on ARM/Synology architectures)
ENV OPENCLAW_PREFER_PNPM=1
RUN pnpm ui:build
@@ -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
@@ -207,15 +207,15 @@ RUN --mount=type=cache,id=openclaw-bookworm-apt-cache,target=/var/cache/apt,shar
# Adds ~300MB but eliminates the 60-90s Playwright install on every container start.
# Must run after node_modules COPY so playwright-core is available.
ARG OPENCLAW_INSTALL_BROWSER=""
ENV PLAYWRIGHT_BROWSERS_PATH=/home/node/.cache/ms-playwright
RUN --mount=type=cache,id=openclaw-bookworm-apt-cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,id=openclaw-bookworm-apt-lists,target=/var/lib/apt,sharing=locked \
if [ -n "$OPENCLAW_INSTALL_BROWSER" ]; then \
apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends xvfb && \
mkdir -p /home/node/.cache/ms-playwright && \
PLAYWRIGHT_BROWSERS_PATH=/home/node/.cache/ms-playwright \
mkdir -p "$PLAYWRIGHT_BROWSERS_PATH" && \
node /app/node_modules/playwright-core/cli.js install --with-deps chromium && \
chown -R node:node /home/node/.cache/ms-playwright; \
chown -R node:node "$PLAYWRIGHT_BROWSERS_PATH"; \
fi
# Optionally install Docker CLI for sandbox container management.
@@ -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 = 2026051000
versionName = "2026.5.10"
ndk {
// Support all major ABIs — native libs are tiny (~47 KB per ABI)
abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")

View File

@@ -1,5 +1,13 @@
# OpenClaw iOS Changelog
## 2026.5.10 - 2026-05-10
Maintenance update for the current OpenClaw beta release.
## 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.10
OPENCLAW_MARKETING_VERSION = 2026.5.10
OPENCLAW_BUILD_VERSION = 1
#include? "../build/Version.xcconfig"

View File

@@ -1 +1 @@
Maintenance update for the current OpenClaw development release.
Maintenance update for the current OpenClaw beta release.

View File

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

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

@@ -16,7 +16,6 @@ enum GatewayAgentChannel: String, Codable, CaseIterable {
case signal
case imessage
case msteams
case bluebubbles
case webchat
init(raw: String?) {

View File

@@ -471,7 +471,8 @@ actor MacNodeRuntime {
}
private func resolveA2UIHostUrl() async -> String? {
Self.resolveA2UIHostUrl(from: await self.canvasSurfaceUrl())
let canvasSurfaceUrl = await self.canvasSurfaceUrl()
return Self.resolveA2UIHostUrl(from: canvasSurfaceUrl)
}
private static func resolveA2UIHostUrl(from raw: String?) -> String? {
@@ -485,7 +486,8 @@ actor MacNodeRuntime {
if !forceRefresh, let current = await self.resolveA2UIHostUrl() {
return current
}
return Self.resolveA2UIHostUrl(from: await self.refreshCanvasSurfaceUrl())
let refreshedCanvasSurfaceUrl = await self.refreshCanvasSurfaceUrl()
return Self.resolveA2UIHostUrl(from: refreshedCanvasSurfaceUrl)
}
private func isA2UIReady(poll: Bool = false) async -> Bool {

View File

@@ -145,10 +145,7 @@ final class OnboardingWizardModel {
self.sessionId = res.sessionid
self.status = wizardStatusString(res.status) ?? (res.done ? "done" : "running")
self.errorMessage = res.error
self.currentStep = decodeWizardStep(res.step)
if self.currentStep == nil, res.step != nil {
onboardingWizardLogger.error("wizard step decode failed")
}
self.currentStep = res.step
if res.done { self.currentStep = nil }
self.restartAttempts = 0
}
@@ -157,10 +154,7 @@ final class OnboardingWizardModel {
let status = wizardStatusString(res.status)
self.status = status ?? self.status
self.errorMessage = res.error
self.currentStep = decodeWizardStep(res.step)
if self.currentStep == nil, res.step != nil {
onboardingWizardLogger.error("wizard step decode failed")
}
self.currentStep = res.step
if res.done { self.currentStep = nil }
if res.done || status == "done" || status == "cancelled" || status == "error" {
self.sessionId = 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.10</string>
<key>CFBundleVersion</key>
<string>2026050600</string>
<string>2026051000</string>
<key>CFBundleIconFile</key>
<string>OpenClaw</string>
<key>CFBundleURLTypes</key>

View File

@@ -207,7 +207,7 @@ actor GatewayWizardClient {
let frame = try decodeFrame(message)
if case let .res(res) = frame, res.id == id {
if res.ok == false {
let msg = (res.error?["message"]?.value as? String) ?? "gateway error"
let msg = res.error?.message ?? "gateway error"
throw WizardCliError.gatewayError(msg)
}
return res
@@ -308,7 +308,7 @@ actor GatewayWizardClient {
let frameResponse = try decodeFrame(message)
if case let .res(res) = frameResponse, res.id == reqId {
if res.ok == false {
let msg = (res.error?["message"]?.value as? String) ?? "gateway connect failed"
let msg = res.error?.message ?? "gateway connect failed"
throw WizardCliError.gatewayError(msg)
}
_ = try self.decodePayload(res, as: HelloOk.self)
@@ -375,7 +375,7 @@ private func runWizard(client: GatewayWizardClient, opts: WizardCliOptions) asyn
return
}
if let step = decodeWizardStep(nextResult.step) {
if let step = nextResult.step {
let answer = try promptAnswer(for: step)
var answerPayload: [String: ProtoAnyCodable] = [
"stepId": ProtoAnyCodable(step.id),

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

@@ -12,7 +12,7 @@ struct GatewayAgentChannelTests {
#expect(GatewayAgentChannel.whatsapp.shouldDeliver(true) == true)
#expect(GatewayAgentChannel.telegram.shouldDeliver(true) == true)
#expect(GatewayAgentChannel.googlechat.shouldDeliver(true) == true)
#expect(GatewayAgentChannel.bluebubbles.shouldDeliver(true) == true)
#expect(GatewayAgentChannel.imessage.shouldDeliver(true) == true)
#expect(GatewayAgentChannel.last.shouldDeliver(false) == false)
}
@@ -21,7 +21,7 @@ struct GatewayAgentChannelTests {
#expect(GatewayAgentChannel(raw: " ") == .last)
#expect(GatewayAgentChannel(raw: "WEBCHAT") == .webchat)
#expect(GatewayAgentChannel(raw: "googlechat") == .googlechat)
#expect(GatewayAgentChannel(raw: "BLUEBUBBLES") == .bluebubbles)
#expect(GatewayAgentChannel(raw: "IMESSAGE") == .imessage)
#expect(GatewayAgentChannel(raw: "unknown") == .last)
}
}

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

@@ -27,7 +27,6 @@ enum ChatMarkdownPreprocessor {
"Matrix",
"Zalo",
"Zalo Personal",
"BlueBubbles",
]
private static let markdownImagePattern = #"!\[([^\]]*)\]\(([^)]+)\)"#

View File

@@ -38,22 +38,68 @@ enum DeviceIdentityPaths {
public enum DeviceIdentityStore {
private static let fileName = "device.json"
private static let ed25519SPKIPrefix = Data([
0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
0x70, 0x03, 0x21, 0x00,
])
private static let ed25519PKCS8PrivatePrefix = Data([
0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06,
0x03, 0x2b, 0x65, 0x70, 0x04, 0x22, 0x04, 0x20,
])
public static func loadOrCreate() -> DeviceIdentity {
let url = self.fileURL()
if let data = try? Data(contentsOf: url),
let decoded = try? JSONDecoder().decode(DeviceIdentity.self, from: data),
!decoded.deviceId.isEmpty,
!decoded.publicKey.isEmpty,
!decoded.privateKey.isEmpty
{
return decoded
self.loadOrCreate(fileURL: self.fileURL())
}
static func loadOrCreate(fileURL url: URL) -> DeviceIdentity {
if let data = try? Data(contentsOf: url) {
switch self.decodeStoredIdentity(data) {
case .identity(let decoded):
return decoded
case .recognizedInvalid:
return self.generate()
case .unknown:
break
}
}
let identity = self.generate()
self.save(identity)
self.save(identity, to: url)
return identity
}
private enum DecodeResult {
case identity(DeviceIdentity)
case recognizedInvalid
case unknown
}
private static func decodeStoredIdentity(_ data: Data) -> DecodeResult {
let decoder = JSONDecoder()
if let decoded = try? decoder.decode(DeviceIdentity.self, from: data) {
guard let identity = self.normalizedRawIdentity(decoded) else {
return .recognizedInvalid
}
return .identity(identity)
}
if let decoded = try? decoder.decode(PemDeviceIdentity.self, from: data) {
guard decoded.version == 1,
let publicKeyData = self.rawPublicKey(fromPEM: decoded.publicKeyPem),
let privateKeyData = self.rawPrivateKey(fromPEM: decoded.privateKeyPem),
self.keyPairMatches(publicKeyData: publicKeyData, privateKeyData: privateKeyData)
else {
return .recognizedInvalid
}
return .identity(DeviceIdentity(
deviceId: self.deviceId(publicKeyData: publicKeyData),
publicKey: publicKeyData.base64EncodedString(),
privateKey: privateKeyData.base64EncodedString(),
createdAtMs: decoded.createdAtMs))
}
return self.hasRecognizedIdentityShape(data) ? .recognizedInvalid : .unknown
}
public static func signPayload(_ payload: String, identity: DeviceIdentity) -> String? {
guard let privateKeyData = Data(base64Encoded: identity.privateKey) else { return nil }
do {
@@ -70,7 +116,7 @@ public enum DeviceIdentityStore {
let publicKey = privateKey.publicKey
let publicKeyData = publicKey.rawRepresentation
let privateKeyData = privateKey.rawRepresentation
let deviceId = SHA256.hash(data: publicKeyData).compactMap { String(format: "%02x", $0) }.joined()
let deviceId = self.deviceId(publicKeyData: publicKeyData)
return DeviceIdentity(
deviceId: deviceId,
publicKey: publicKeyData.base64EncodedString(),
@@ -91,8 +137,69 @@ public enum DeviceIdentityStore {
return self.base64UrlEncode(data)
}
private static func save(_ identity: DeviceIdentity) {
let url = self.fileURL()
private static func normalizedRawIdentity(_ identity: DeviceIdentity) -> DeviceIdentity? {
guard !identity.deviceId.isEmpty,
let publicKeyData = Data(base64Encoded: identity.publicKey),
let privateKeyData = Data(base64Encoded: identity.privateKey)
else { return nil }
guard publicKeyData.count == 32 && privateKeyData.count == 32,
self.keyPairMatches(publicKeyData: publicKeyData, privateKeyData: privateKeyData)
else { return nil }
return DeviceIdentity(
deviceId: self.deviceId(publicKeyData: publicKeyData),
publicKey: identity.publicKey,
privateKey: identity.privateKey,
createdAtMs: identity.createdAtMs)
}
private static func rawPublicKey(fromPEM pem: String) -> Data? {
guard let der = self.derData(fromPEM: pem),
der.count == self.ed25519SPKIPrefix.count + 32,
der.prefix(self.ed25519SPKIPrefix.count) == self.ed25519SPKIPrefix
else { return nil }
return der.suffix(32)
}
private static func rawPrivateKey(fromPEM pem: String) -> Data? {
guard let der = self.derData(fromPEM: pem),
der.count == self.ed25519PKCS8PrivatePrefix.count + 32,
der.prefix(self.ed25519PKCS8PrivatePrefix.count) == self.ed25519PKCS8PrivatePrefix
else { return nil }
return der.suffix(32)
}
private static func keyPairMatches(publicKeyData: Data, privateKeyData: Data) -> Bool {
guard let privateKey = try? Curve25519.Signing.PrivateKey(rawRepresentation: privateKeyData)
else {
return false
}
return privateKey.publicKey.rawRepresentation == publicKeyData
}
private static func derData(fromPEM pem: String) -> Data? {
let body = pem
.split(whereSeparator: \.isNewline)
.filter { !$0.hasPrefix("-----") }
.joined()
return Data(base64Encoded: body)
}
private static func hasRecognizedIdentityShape(_ data: Data) -> Bool {
guard let object = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
return false
}
return object.keys.contains("publicKeyPem")
|| object.keys.contains("privateKeyPem")
|| object.keys.contains("publicKey")
|| object.keys.contains("privateKey")
}
private static func deviceId(publicKeyData: Data) -> String {
SHA256.hash(data: publicKeyData).compactMap { String(format: "%02x", $0) }.joined()
}
private static func save(_ identity: DeviceIdentity, to url: URL) {
do {
try FileManager.default.createDirectory(
at: url.deletingLastPathComponent(),
@@ -111,3 +218,11 @@ public enum DeviceIdentityStore {
.appendingPathComponent(self.fileName, isDirectory: false)
}
}
private struct PemDeviceIdentity: Codable {
var version: Int
var deviceId: String
var publicKeyPem: String
var privateKeyPem: String
var createdAtMs: Int
}

View File

@@ -124,6 +124,24 @@ public enum GatewayAuthSource: String, Sendable {
/// Avoid ambiguity with the app's own AnyCodable type.
private typealias ProtoAnyCodable = OpenClawProtocol.AnyCodable
private func gatewayErrorDetails(_ error: ErrorShape?) -> [String: ProtoAnyCodable] {
var details: [String: ProtoAnyCodable] = [:]
if let nested = error?.details?.value as? [String: ProtoAnyCodable] {
details.merge(nested) { _, nestedValue in nestedValue }
}
if let error {
details["code"] = ProtoAnyCodable(error.code)
details["message"] = ProtoAnyCodable(error.message)
if let retryable = error.retryable {
details["retryable"] = ProtoAnyCodable(retryable)
}
if let retryAfterMs = error.retryafterms {
details["retryAfterMs"] = ProtoAnyCodable(retryAfterMs)
}
}
return details
}
private enum ConnectChallengeError: Error {
case timeout
}
@@ -623,21 +641,22 @@ public actor GatewayChannelActor {
role: String) async throws
{
if res.ok == false {
let msg = (res.error?["message"]?.value as? String) ?? "gateway connect failed"
let details = res.error?["details"]?.value as? [String: ProtoAnyCodable]
let detailCode = details?["code"]?.value as? String
let canRetryWithDeviceToken = details?["canRetryWithDeviceToken"]?.value as? Bool ?? false
let recommendedNextStep = details?["recommendedNextStep"]?.value as? String
let requestId = details?["requestId"]?.value as? String
let reason = details?["reason"]?.value as? String
let owner = details?["owner"]?.value as? String
let title = details?["title"]?.value as? String
let userMessage = details?["userMessage"]?.value as? String
let actionLabel = details?["actionLabel"]?.value as? String
let actionCommand = details?["actionCommand"]?.value as? String
let docsURLString = details?["docsUrl"]?.value as? String
let retryableOverride = details?["retryable"]?.value as? Bool
let pauseReconnectOverride = details?["pauseReconnect"]?.value as? Bool
let error = res.error
let msg = error?.message ?? "gateway connect failed"
let details = gatewayErrorDetails(error)
let detailCode = details["code"]?.value as? String
let canRetryWithDeviceToken = details["canRetryWithDeviceToken"]?.value as? Bool ?? false
let recommendedNextStep = details["recommendedNextStep"]?.value as? String
let requestId = details["requestId"]?.value as? String
let reason = details["reason"]?.value as? String
let owner = details["owner"]?.value as? String
let title = details["title"]?.value as? String
let userMessage = details["userMessage"]?.value as? String
let actionLabel = details["actionLabel"]?.value as? String
let actionCommand = details["actionCommand"]?.value as? String
let docsURLString = details["docsUrl"]?.value as? String
let retryableOverride = details["retryable"]?.value as? Bool
let pauseReconnectOverride = details["pauseReconnect"]?.value as? Bool
throw GatewayConnectAuthError(
message: msg,
detailCodeRaw: detailCode,
@@ -974,11 +993,9 @@ public actor GatewayChannelActor {
throw NSError(domain: "Gateway", code: 2, userInfo: [NSLocalizedDescriptionKey: "unexpected frame"])
}
if res.ok == false {
let code = res.error?["code"]?.value as? String
let msg = res.error?["message"]?.value as? String
let details: [String: AnyCodable] = (res.error ?? [:]).reduce(into: [:]) { acc, pair in
acc[pair.key] = AnyCodable(pair.value.value)
}
let code = res.error?.code
let msg = res.error?.message
let details = gatewayErrorDetails(res.error)
throw GatewayResponseError(method: method, code: code, message: msg, details: details)
}
if let payload = res.payload {
@@ -1013,7 +1030,11 @@ public actor GatewayChannelActor {
/// Wrap low-level URLSession/WebSocket errors with context so UI can surface them.
private func wrap(_ error: Error, context: String) -> Error {
if error is GatewayConnectAuthError || error is GatewayResponseError || error is GatewayDecodingError || error is GatewayTLSValidationError {
if error is GatewayConnectAuthError ||
error is GatewayResponseError ||
error is GatewayDecodingError ||
error is GatewayTLSValidationError
{
return error
}
if let urlError = error as? URLError {

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
@@ -716,6 +716,7 @@ public struct AgentParams: Codable, Sendable {
public let bootstrapcontextmode: AnyCodable?
public let bootstrapcontextrunkind: AnyCodable?
public let acpturnsource: String?
public let internalruntimehandoffid: String?
public let internalevents: [[String: AnyCodable]]?
public let inputprovenance: [String: AnyCodable]?
public let voicewaketrigger: String?
@@ -752,6 +753,7 @@ public struct AgentParams: Codable, Sendable {
bootstrapcontextmode: AnyCodable?,
bootstrapcontextrunkind: AnyCodable?,
acpturnsource: String?,
internalruntimehandoffid: String?,
internalevents: [[String: AnyCodable]]?,
inputprovenance: [String: AnyCodable]?,
voicewaketrigger: String?,
@@ -787,6 +789,7 @@ public struct AgentParams: Codable, Sendable {
self.bootstrapcontextmode = bootstrapcontextmode
self.bootstrapcontextrunkind = bootstrapcontextrunkind
self.acpturnsource = acpturnsource
self.internalruntimehandoffid = internalruntimehandoffid
self.internalevents = internalevents
self.inputprovenance = inputprovenance
self.voicewaketrigger = voicewaketrigger
@@ -824,6 +827,7 @@ public struct AgentParams: Codable, Sendable {
case bootstrapcontextmode = "bootstrapContextMode"
case bootstrapcontextrunkind = "bootstrapContextRunKind"
case acpturnsource = "acpTurnSource"
case internalruntimehandoffid = "internalRuntimeHandoffId"
case internalevents = "internalEvents"
case inputprovenance = "inputProvenance"
case voicewaketrigger = "voiceWakeTrigger"
@@ -2243,6 +2247,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 +2259,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 +2270,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 +2283,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 +2782,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 +2809,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?)
{
@@ -2757,6 +2987,10 @@ public struct TalkClientCreateParams: Codable, Sendable {
public let provider: String?
public let model: String?
public let voice: String?
public let vadthreshold: Double?
public let silencedurationms: Int?
public let prefixpaddingms: Int?
public let reasoningeffort: String?
public let mode: AnyCodable?
public let transport: AnyCodable?
public let brain: AnyCodable?
@@ -2766,6 +3000,10 @@ public struct TalkClientCreateParams: Codable, Sendable {
provider: String?,
model: String?,
voice: String?,
vadthreshold: Double?,
silencedurationms: Int?,
prefixpaddingms: Int?,
reasoningeffort: String?,
mode: AnyCodable?,
transport: AnyCodable?,
brain: AnyCodable?)
@@ -2774,6 +3012,10 @@ public struct TalkClientCreateParams: Codable, Sendable {
self.provider = provider
self.model = model
self.voice = voice
self.vadthreshold = vadthreshold
self.silencedurationms = silencedurationms
self.prefixpaddingms = prefixpaddingms
self.reasoningeffort = reasoningeffort
self.mode = mode
self.transport = transport
self.brain = brain
@@ -2784,6 +3026,10 @@ public struct TalkClientCreateParams: Codable, Sendable {
case provider
case model
case voice
case vadthreshold = "vadThreshold"
case silencedurationms = "silenceDurationMs"
case prefixpaddingms = "prefixPaddingMs"
case reasoningeffort = "reasoningEffort"
case mode
case transport
case brain
@@ -2937,6 +3183,10 @@ public struct TalkSessionCreateParams: Codable, Sendable {
public let provider: String?
public let model: String?
public let voice: String?
public let vadthreshold: Double?
public let silencedurationms: Int?
public let prefixpaddingms: Int?
public let reasoningeffort: String?
public let mode: AnyCodable?
public let transport: AnyCodable?
public let brain: AnyCodable?
@@ -2947,6 +3197,10 @@ public struct TalkSessionCreateParams: Codable, Sendable {
provider: String?,
model: String?,
voice: String?,
vadthreshold: Double?,
silencedurationms: Int?,
prefixpaddingms: Int?,
reasoningeffort: String?,
mode: AnyCodable?,
transport: AnyCodable?,
brain: AnyCodable?,
@@ -2956,6 +3210,10 @@ public struct TalkSessionCreateParams: Codable, Sendable {
self.provider = provider
self.model = model
self.voice = voice
self.vadthreshold = vadthreshold
self.silencedurationms = silencedurationms
self.prefixpaddingms = prefixpaddingms
self.reasoningeffort = reasoningeffort
self.mode = mode
self.transport = transport
self.brain = brain
@@ -2967,6 +3225,10 @@ public struct TalkSessionCreateParams: Codable, Sendable {
case provider
case model
case voice
case vadthreshold = "vadThreshold"
case silencedurationms = "silenceDurationMs"
case prefixpaddingms = "prefixPaddingMs"
case reasoningeffort = "reasoningEffort"
case mode
case transport
case brain
@@ -3180,21 +3442,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 +4795,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 +4804,7 @@ public struct ToolsInvokeResult: Codable, Sendable {
requiresapproval: Bool?,
approvalid: String?,
source: AnyCodable?,
error: [String: AnyCodable]?)
error: ToolsInvokeError?)
{
self.ok = ok
self.toolname = toolname
@@ -4648,6 +4914,80 @@ public struct SkillsDetailResult: Codable, Sendable {
}
}
public struct SkillsUploadBeginParams: Codable, Sendable {
public let kind: String
public let slug: String
public let sizebytes: Int
public let sha256: String?
public let force: Bool?
public let idempotencykey: String?
public init(
kind: String,
slug: String,
sizebytes: Int,
sha256: String?,
force: Bool?,
idempotencykey: String?)
{
self.kind = kind
self.slug = slug
self.sizebytes = sizebytes
self.sha256 = sha256
self.force = force
self.idempotencykey = idempotencykey
}
private enum CodingKeys: String, CodingKey {
case kind
case slug
case sizebytes = "sizeBytes"
case sha256
case force
case idempotencykey = "idempotencyKey"
}
}
public struct SkillsUploadChunkParams: Codable, Sendable {
public let uploadid: String
public let offset: Int
public let database64: String
public init(
uploadid: String,
offset: Int,
database64: String)
{
self.uploadid = uploadid
self.offset = offset
self.database64 = database64
}
private enum CodingKeys: String, CodingKey {
case uploadid = "uploadId"
case offset
case database64 = "dataBase64"
}
}
public struct SkillsUploadCommitParams: Codable, Sendable {
public let uploadid: String
public let sha256: String?
public init(
uploadid: String,
sha256: String?)
{
self.uploadid = uploadid
self.sha256 = sha256
}
private enum CodingKeys: String, CodingKey {
case uploadid = "uploadId"
case sha256
}
}
public struct CronJob: Codable, Sendable {
public let id: String
public let agentid: String?
@@ -5132,6 +5472,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 +5495,7 @@ public struct ExecApprovalRequestParams: Codable, Sendable {
security: AnyCodable?,
ask: AnyCodable?,
warningtext: AnyCodable?,
commandspans: [[String: AnyCodable]]?,
agentid: AnyCodable?,
resolvedpath: AnyCodable?,
sessionkey: AnyCodable?,
@@ -5175,6 +5517,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 +5541,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 +5933,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 +5950,7 @@ public struct ChatSendParams: Codable, Sendable {
sessionid: String?,
message: String,
thinking: String?,
fastmode: Bool?,
deliver: Bool?,
originatingchannel: String?,
originatingto: String?,
@@ -5620,6 +5966,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 +5984,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

@@ -0,0 +1,95 @@
import CryptoKit
import Foundation
import Testing
@testable import OpenClawKit
@Suite(.serialized)
struct DeviceIdentityStoreTests {
@Test("loads TypeScript PEM identity schema without rewriting or regenerating")
func loadsTypeScriptPEMIdentitySchema() throws {
let tempDir = FileManager.default.temporaryDirectory
.appendingPathComponent(UUID().uuidString, isDirectory: true)
let identityURL = tempDir
.appendingPathComponent("identity", isDirectory: true)
.appendingPathComponent("device.json", isDirectory: false)
defer { try? FileManager.default.removeItem(at: tempDir) }
try FileManager.default.createDirectory(
at: identityURL.deletingLastPathComponent(),
withIntermediateDirectories: true)
let stored = try Self.identityJSON(
publicKeyPem: Self.pem(
label: "PUBLIC KEY",
body: "MCowBQYDK2VwAyEAA6EHv/POEL4dcN0Y50vAmWfk1jCbpQ1fHdyGZBJVMbg="),
privateKeyPem: Self.pem(
label: "PRIVATE KEY",
body: "MC4CAQAwBQYDK2VwBCIEIAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4f"))
try stored.write(to: identityURL, atomically: true, encoding: .utf8)
let before = try String(contentsOf: identityURL, encoding: .utf8)
let identity = DeviceIdentityStore.loadOrCreate(fileURL: identityURL)
#expect(identity.deviceId == "56475aa75463474c0285df5dbf2bcab73da651358839e9b77481b2eab107708c")
#expect(identity.publicKey == "A6EHv/POEL4dcN0Y50vAmWfk1jCbpQ1fHdyGZBJVMbg=")
#expect(identity.privateKey == "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=")
#expect(DeviceIdentityStore.publicKeyBase64Url(identity) == "A6EHv_POEL4dcN0Y50vAmWfk1jCbpQ1fHdyGZBJVMbg")
let signature = try #require(DeviceIdentityStore.signPayload("hello", identity: identity))
let publicKeyData = try #require(Data(base64Encoded: identity.publicKey))
let signatureData = try #require(Self.base64UrlDecode(signature))
let publicKey = try Curve25519.Signing.PublicKey(rawRepresentation: publicKeyData)
#expect(publicKey.isValidSignature(signatureData, for: Data("hello".utf8)))
#expect(try String(contentsOf: identityURL, encoding: .utf8) == before)
}
@Test("does not overwrite a recognized invalid TypeScript identity schema")
func preservesInvalidTypeScriptPEMIdentitySchema() throws {
let tempDir = FileManager.default.temporaryDirectory
.appendingPathComponent(UUID().uuidString, isDirectory: true)
let identityURL = tempDir
.appendingPathComponent("identity", isDirectory: true)
.appendingPathComponent("device.json", isDirectory: false)
defer { try? FileManager.default.removeItem(at: tempDir) }
try FileManager.default.createDirectory(
at: identityURL.deletingLastPathComponent(),
withIntermediateDirectories: true)
let stored = """
{
"version": 1,
"deviceId": "stale-device-id",
"publicKeyPem": "not-a-valid-public-key",
"privateKeyPem": "not-a-valid-private-key",
"createdAtMs": 1700000000000
}
"""
try stored.write(to: identityURL, atomically: true, encoding: .utf8)
let before = try String(contentsOf: identityURL, encoding: .utf8)
let identity = DeviceIdentityStore.loadOrCreate(fileURL: identityURL)
#expect(identity.deviceId != "stale-device-id")
#expect(try String(contentsOf: identityURL, encoding: .utf8) == before)
}
private static func base64UrlDecode(_ value: String) -> Data? {
let normalized = value
.replacingOccurrences(of: "-", with: "+")
.replacingOccurrences(of: "_", with: "/")
let padded = normalized + String(repeating: "=", count: (4 - normalized.count % 4) % 4)
return Data(base64Encoded: padded)
}
private static func identityJSON(publicKeyPem: String, privateKeyPem: String) throws -> String {
let object: [String: Any] = [
"version": 1,
"deviceId": "stale-device-id",
"publicKeyPem": publicKeyPem,
"privateKeyPem": privateKeyPem,
"createdAtMs": 1_700_000_000_000,
]
let data = try JSONSerialization.data(withJSONObject: object, options: [.prettyPrinted, .sortedKeys])
return String(decoding: data, as: UTF8.self) + "\n"
}
private static func pem(label: String, body: String) -> String {
"-----BEGIN \(label)-----\n\(body)\n-----END \(label)-----\n"
}
}

View File

@@ -0,0 +1 @@
- Signal/container mode: add REST API support for bbernhard/signal-cli-rest-api containerized deployments via a unified adapter layer, with automatic mode detection and `channels.signal.apiMode` config. (#10240) Thanks @Hua688.

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
422a42f7dbd40e3cb6f6661a1a89019adc854712ede8b79c46078128110c1592 config-baseline.json
8d9b6bedecec620af4a135e8d86c22e8afda43fbc2fce81e4e13cc013122ab4a config-baseline.core.json
80f0f51caedf14dc2138d975b62852ff7c5cf085df1c734c9de279f5859a7eeb config-baseline.channel.json
dba159f639977bb96d79f0b78de2c6de48d25ed6ba1590f55812affb7ca6e4b0 config-baseline.plugin.json

View File

@@ -1,2 +1,2 @@
28e280d21693216c99cfa8da553589b41741d37c0ada956e316ee01d3d6c202c plugin-sdk-api-baseline.json
633dae33da97f6a073c5561709c57d5c0b7ff67af0512d0261f05455c24b38de plugin-sdk-api-baseline.jsonl
76508e5ff2d153b67d1766179e52734119a5a82b4c00216a270f51ce73fec710 plugin-sdk-api-baseline.json
7e57007f2086074a3a22b9cd970964c1565058a412c7b141e468bc908cbf9eb8 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"
@@ -39,6 +59,22 @@
"source": "Channel message API",
"target": "频道消息 API"
},
{
"source": "Channel ingress API",
"target": "频道入口 API"
},
{
"source": "Channel access cleanup",
"target": "频道访问清理"
},
{
"source": "Ingress core shrink plan",
"target": "入口核心精简计划"
},
{
"source": "Ingress core shrink",
"target": "入口核心精简"
},
{
"source": "Talk mode",
"target": "Talk 模式"
@@ -91,6 +127,26 @@
"source": "Codex harness",
"target": "Codex harness"
},
{
"source": "Codex harness reference",
"target": "Codex harness reference"
},
{
"source": "Codex harness runtime",
"target": "Codex harness runtime"
},
{
"source": "Native Codex plugins",
"target": "Native Codex plugins"
},
{
"source": "Codex Computer Use",
"target": "Codex Computer Use"
},
{
"source": "Diagnostics export",
"target": "诊断导出"
},
{
"source": "Agent harness plugins",
"target": "Agent harness plugins"
@@ -591,6 +647,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 权限"
@@ -659,6 +727,10 @@
"source": "Migrate",
"target": "迁移"
},
{
"source": "Migrate CLI",
"target": "迁移 CLI"
},
{
"source": "Migrating",
"target": "迁移"
@@ -735,6 +807,10 @@
"source": "Matrix QA",
"target": "Matrix QA"
},
{
"source": "Matrix presentation metadata",
"target": "Matrix 呈现元数据"
},
{
"source": "QA overview",
"target": "QA overview"
@@ -747,6 +823,10 @@
"source": "Rich Output Protocol",
"target": "富输出协议"
},
{
"source": "Trajectory export",
"target": "轨迹导出"
},
{
"source": "Tencent Cloud (TokenHub)",
"target": "腾讯云TokenHub"

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

@@ -48,7 +48,7 @@ Cron is the Gateway's built-in scheduler. It persists jobs, wakes the agent at t
- On Gateway startup, overdue isolated agent-turn jobs are rescheduled out of the channel-connect window instead of replaying immediately, so Discord/Telegram startup and native-command setup stay responsive after restarts.
- One-shot jobs (`--at`) auto-delete after success by default.
- Isolated cron runs best-effort close tracked browser tabs/processes for their `cron:<jobId>` session when the run completes, so detached browser automation does not leave orphaned processes behind.
- Isolated cron runs that receive the narrow cron self-cleanup grant can still read scheduler status and a self-filtered list of their current job, so status/heartbeat checks can inspect their own schedule without gaining broader cron mutation access.
- Isolated cron runs that receive the narrow cron self-cleanup grant can still read scheduler status, a self-filtered list of their current job, and that job's run history, so status/heartbeat checks can inspect their own schedule without gaining broader cron mutation access.
- Isolated cron runs also guard against stale acknowledgement replies. If the first result is just an interim status update (`on it`, `pulling everything together`, and similar hints) and no descendant subagent run is still responsible for the final answer, OpenClaw re-prompts once for the actual result before delivery.
- Isolated cron runs prefer structured execution-denial metadata from the embedded run, then fall back to known final summary/output markers such as `SYSTEM_RUN_DENIED` and `INVALID_REQUEST`, so a blocked command is not reported as a green run.
- Isolated cron runs also treat run-level agent failures as job errors even when no reply payload is produced, so model/provider failures increment error counters and trigger failure notifications instead of clearing the job as successful.

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

@@ -243,7 +243,7 @@ openclaw tasks notify <lookup> state_changes
openclaw tasks maintenance --apply [--json]
```
Use this to preview or apply reconciliation, cleanup stamping, and pruning for tasks and Task Flow state.
Use this to preview or apply reconciliation, cleanup stamping, and pruning for tasks, Task Flow state, and stale cron run session registry rows.
Reconciliation is runtime-aware:
@@ -260,6 +260,8 @@ openclaw tasks notify <lookup> state_changes
- Subagent completion delivery prefers the latest visible assistant text; if that is empty it falls back to sanitized latest tool/toolResult text, and timeout-only tool-call runs can collapse to a short partial-progress summary. Terminal failed runs announce failure status without replaying captured reply text.
- Cleanup failures do not mask the real task outcome.
When applying maintenance, OpenClaw also removes stale `cron:<jobId>:run:<uuid>` session registry rows older than 7 days, while preserving rows for currently running cron jobs and leaving non-cron session rows untouched.
</Accordion>
<Accordion title="tasks flow list | show | cancel">
```bash

View File

@@ -125,7 +125,26 @@ Access groups are available in shared message-channel authorization paths, inclu
- channel-specific per-room sender allowlists that use the same sender matching rules
- command authorization paths that reuse message-channel sender allowlists
Channel support depends on whether that channel is wired through the shared OpenClaw sender-authorization helpers. Current bundled support includes Discord, Google Chat, Nostr, WhatsApp, Zalo, and Zalo Personal. Static `message.senders` groups are designed to be channel-agnostic, so new message channels should support them by using the shared plugin SDK helpers instead of custom allowlist expansion.
Channel support depends on whether that channel is wired through the shared OpenClaw sender-authorization helpers. Current bundled support includes Discord, Feishu, Google Chat, iMessage, LINE, Mattermost, Microsoft Teams, Nextcloud Talk, Nostr, QQBot, Signal, WhatsApp, Zalo, and Zalo Personal. Static `message.senders` groups are designed to be channel-agnostic, so new message channels should support them by using the shared plugin SDK helpers instead of custom allowlist expansion.
## Plugin diagnostics
Plugin authors can inspect structured access-group state without expanding it back into a flat allowlist:
```typescript
import { resolveAccessGroupAllowFromState } from "openclaw/plugin-sdk/security-runtime";
const state = await resolveAccessGroupAllowFromState({
accessGroups: cfg.accessGroups,
allowFrom: channelConfig.allowFrom,
channel: "my-channel",
accountId: "default",
senderId,
isSenderAllowed,
});
```
The result reports referenced, matched, missing, unsupported, and failed groups. Use this when you need diagnostics or conformance tests. Use `expandAllowFromWithAccessGroups(...)` only for compatibility paths that still expect a flat `allowFrom` array.
## Discord channel audiences

138
docs/channels/clickclack.md Normal file
View File

@@ -0,0 +1,138 @@
---
summary: "ClickClack bot-token channel setup and target syntax"
read_when:
- Connecting OpenClaw to a ClickClack workspace
- Testing ClickClack bot identities
title: "ClickClack"
---
ClickClack connects OpenClaw to a self-hosted ClickClack workspace through first-class ClickClack bot tokens.
Use this when you want an OpenClaw agent to appear as a ClickClack bot user. ClickClack supports independent service bots and user-owned bots; user-owned bots keep an `owner_user_id` and receive only the token scopes you grant.
## Quick setup
Create a bot token in ClickClack:
```bash
clickclack admin bot create \
--workspace <workspace_id_or_slug> \
--name "OpenClaw" \
--handle openclaw \
--scopes bot:write \
--plain
```
For a user-owned bot, add `--owner <user_id>`.
Configure OpenClaw:
```json5
{
plugins: {
entries: {
clickclack: {
llm: {
allowAgentIdOverride: true,
},
},
},
},
channels: {
clickclack: {
enabled: true,
baseUrl: "https://app.clickclack.chat",
token: { source: "env", provider: "default", id: "CLICKCLACK_BOT_TOKEN" },
workspace: "default",
defaultTo: "channel:general",
agentId: "clickclack-bot",
replyMode: "model",
},
},
}
```
Then run:
```bash
export CLICKCLACK_BOT_TOKEN="ccb_..."
openclaw gateway
```
## Multiple bots
Each account opens its own ClickClack realtime connection and uses its own bot token.
```json5
{
plugins: {
entries: {
clickclack: {
llm: {
allowAgentIdOverride: true,
},
},
},
},
channels: {
clickclack: {
enabled: true,
baseUrl: "https://app.clickclack.chat",
defaultAccount: "service",
accounts: {
service: {
token: { source: "env", provider: "default", id: "CLICKCLACK_SERVICE_BOT_TOKEN" },
workspace: "default",
defaultTo: "channel:general",
agentId: "service-bot",
replyMode: "model",
},
peter: {
token: { source: "env", provider: "default", id: "CLICKCLACK_PETER_BOT_TOKEN" },
workspace: "default",
defaultTo: "dm:usr_...",
agentId: "peter-bot",
replyMode: "model",
},
},
},
},
}
```
`replyMode: "model"` uses `api.runtime.llm.complete` directly for short bot replies.
When an account sets `agentId`, OpenClaw requires the explicit
`plugins.entries.clickclack.llm.allowAgentIdOverride` trust bit so the plugin
can run completions for that bot agent. Keep it off if you only use the default
agent route.
## Targets
- `channel:<name-or-id>` sends to a workspace channel. Bare targets default to `channel:`.
- `dm:<user_id>` creates or reuses a direct conversation with that user.
- `thread:<message_id>` replies in an existing thread.
Examples:
```bash
openclaw message send --channel clickclack --target channel:general --message "hello"
openclaw message send --channel clickclack --target dm:usr_123 --message "hello"
openclaw message send --channel clickclack --target thread:msg_123 --message "following up"
```
## Permissions
ClickClack token scopes are enforced by the ClickClack API.
- `bot:read`: read workspace/channel/message/thread/DM/realtime/profile data.
- `bot:write`: `bot:read` plus channel messages, thread replies, DMs, and uploads.
- `bot:admin`: `bot:write` plus channel creation.
OpenClaw only needs `bot:write` for normal agent chat.
## Troubleshooting
- `ClickClack is not configured`: set `channels.clickclack.token` or `CLICKCLACK_BOT_TOKEN`.
- `workspace not found`: set `workspace` to the workspace id or slug returned by ClickClack.
- No inbound replies: confirm the token has realtime read access and the bot is not replying to its own messages.
- Channel sends fail: verify the bot is a member of the workspace and has `bot:write`.

View File

@@ -352,7 +352,7 @@ By default, components are single use. Set `components.reusable=true` to allow b
To restrict who can click a button, set `allowedUsers` on that button (Discord user IDs, tags, or `*`). When configured, unmatched users receive an ephemeral denial.
The `/model` and `/models` slash commands open an interactive model picker with provider, model, and compatible runtime dropdowns plus a Submit step. `/models add` is deprecated and now returns a deprecation message instead of registering models from chat. The picker reply is ephemeral and only the invoking user can use it.
The `/model` and `/models` slash commands open an interactive model picker with provider, model, and compatible runtime dropdowns plus a Submit step. `/models add` is deprecated and now returns a deprecation message instead of registering models from chat. The picker reply is ephemeral and only the invoking user can use it. Discord select menus are limited to 25 options, so add `provider/*` entries to `agents.defaults.models` when you want the picker to show dynamically discovered models only for selected providers such as `openai-codex` or `vllm`.
File attachments:
@@ -451,8 +451,8 @@ Example:
</Tab>
<Tab title="DM access groups">
Discord DMs can use dynamic `accessGroup:<name>` entries in `channels.discord.allowFrom`.
<Tab title="Access groups">
Discord DMs and text command authorization can use dynamic `accessGroup:<name>` entries in `channels.discord.allowFrom`.
Access group names are shared across message channels. Use `type: "message.senders"` for a static group whose members are expressed in each channel's normal `allowFrom` syntax, or `type: "discord.channelAudience"` when a Discord channel's current `ViewChannel` audience should define membership dynamically. Shared access-group behavior is documented here: [Access groups](/channels/access-groups).
@@ -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,26 +1196,55 @@ 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 that default `always` mode, the realtime layer does not auto-speak filler before the consult answer; it captures and transcribes speech, then speaks the routed OpenClaw answer. If multiple forced consult answers finish while Discord is still playing the first answer, later exact-speech answers are queued until playback idles instead of replacing speech mid-sentence.
- 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"`.
- The OpenAI realtime provider accepts current Realtime 2 event names and legacy Codex-compatible aliases for output audio and transcript events, so compatible provider snapshots can drift without dropping assistant audio.
- `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.
- OpenClaw defaults to the pure-JS `opusscript` decoder for Discord voice receive. The optional native `@discordjs/opus` package is ignored by the repo pnpm install policy so normal installs, Docker lanes, and unrelated tests do not compile a native addon. Dedicated voice-performance hosts can opt in with `OPENCLAW_DISCORD_OPUS_DECODER=native` after installing the native addon.
- `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.
- If receive logs repeatedly show `DecryptionFailed(UnencryptedWhenPassthroughDisabled)` after updating, collect a dependency report and logs. The bundled `@discordjs/voice` line includes the upstream padding fix from discord.js PR #11449, which closed discord.js issue #11419.
- `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.
- In `agent-proxy` mode, forced consult fallback skips likely incomplete transcript fragments such as text ending in `...` or a trailing connector like `and`, plus obvious non-actionable closings like “be right back” or “bye”. Logs show `forced agent consult skipped reason=...` when this prevents a stale queued answer.
Voice channel pipeline:
Native opus setup for source checkouts:
```bash
pnpm install
mise exec node@22 -- pnpm discord:opus:install
```
Use Node 22 for the gateway when you want the upstream macOS arm64 prebuilt native addon. If you use another Node runtime, the opt-in installer may need a local `node-gyp` source-build toolchain.
After installing the native addon, start the Gateway with:
```bash
OPENCLAW_DISCORD_OPUS_DECODER=native pnpm gateway:watch
```
Verbose voice logs should show `discord voice: opus decoder: @discordjs/opus`. Without the env opt-in, or if the native addon is missing or cannot load on the host, OpenClaw logs `discord voice: opus decoder: opusscript` and keeps receiving voice through the pure-JS fallback.
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 +1252,184 @@ 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 ... autoRespond=false interruptResponse=false bargeIn=false minBargeInAudioEndMs=...`
- On speaker audio: `discord voice: realtime speaker turn opened ...`, `discord voice: realtime input audio started ... outputAudioMs=... outputActive=...`, and `discord voice: realtime speaker turn closed ... chunks=... discordBytes=... realtimeBytes=... interruptedPlayback=...`
- On skipped stale speech: `discord voice: realtime forced agent consult skipped reason=incomplete-transcript ...` or `reason=non-actionable-closing ...`
- On realtime response completion: `discord voice: realtime audio playback finishing reason=response.done ... audioMs=... chunks=...`
- On playback stop/reset: `discord voice: realtime audio playback stopped reason=... audioMs=... elapsedMs=... chunks=...`
- On realtime consult: `discord voice: realtime consult requested ... voiceSession=... supervisorSession=... question=...`
- On agent answer: `discord voice: agent turn answer ...`
- On queued exact speech: `discord voice: realtime exact speech queued ... queued=... outputAudioMs=... outputActive=...`, followed by `discord voice: realtime exact speech dequeued reason=player-idle ...`
- On barge-in detection: `discord voice: realtime barge-in detected source=speaker-start ...` or `discord voice: realtime barge-in detected source=active-speaker-audio ...`, followed by `discord voice: realtime barge-in requested reason=... outputAudioMs=... outputActive=...`
- 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) ...`
- On idle playback: `discord voice: realtime barge-in ignored reason=... outputActive=false ... playbackChunks=0`
To debug cut-off audio, read the realtime voice logs as a timeline:
1. `realtime audio playback started` means Discord has begun playing assistant audio. The bridge starts counting assistant output chunks, Discord PCM bytes, provider realtime bytes, and synthesized audio duration from this point.
2. `realtime speaker turn opened` marks a Discord speaker becoming active. If playback is already active and `bargeIn` is enabled, this can be followed by `barge-in detected source=speaker-start`.
3. `realtime input audio started` marks the first actual audio frame received for that speaker turn. `outputActive=true` or a nonzero `outputAudioMs` here means the mic is sending input while assistant playback is still active.
4. `barge-in detected source=active-speaker-audio` means OpenClaw saw live speaker audio while assistant playback was active. This is useful for distinguishing a real interruption from a Discord speaker-start event with no useful audio.
5. `barge-in requested reason=...` means OpenClaw asked the realtime provider to cancel or truncate the active response. It includes `outputAudioMs`, `outputActive`, and `playbackChunks` so you can see how much assistant audio had actually played before the interruption.
6. `realtime audio playback stopped reason=...` is the local Discord playback reset point. The reason says who stopped playback: `barge-in`, `player-idle`, `provider-clear-audio`, `forced-agent-consult`, `stream-close`, or `session-close`.
7. `realtime speaker turn closed` summarizes the captured input turn. `chunks=0` or `hasAudio=false` means the speaker turn opened but no usable audio reached the realtime bridge. `interruptedPlayback=true` means that input turn overlapped assistant output and triggered barge-in logic.
Useful fields:
- `outputAudioMs`: assistant audio duration generated by the realtime provider before the log line.
- `audioMs`: assistant audio duration that OpenClaw counted before playback stopped.
- `elapsedMs`: wall-clock time between opening and closing the playback stream or speaker turn.
- `discordBytes`: 48 kHz stereo PCM bytes sent to or received from Discord voice.
- `realtimeBytes`: provider-format PCM bytes sent to or received from the realtime provider.
- `playbackChunks`: assistant audio chunks forwarded to Discord for the active response.
- `sinceLastAudioMs`: gap between the last captured speaker audio frame and the speaker turn closing.
Common patterns:
- Immediate cut-off with `source=active-speaker-audio`, small `outputAudioMs`, and the same user nearby usually points to speaker echo entering the mic. Raise `voice.realtime.minBargeInAudioEndMs`, lower speaker volume, use headphones, or set `voice.realtime.providers.openai.interruptResponseOnInputAudio: false`.
- `source=speaker-start` followed by `speaker turn closed ... hasAudio=false` means Discord reported a speaker start but no audio reached OpenClaw. That can be a transient Discord voice event, noise gate behavior, or a client briefly keying the mic.
- `audio playback stopped reason=stream-close` without a nearby barge-in or `provider-clear-audio` means the local Discord playback stream ended unexpectedly. Check the preceding provider and Discord player logs.
- `capture ignored during playback (barge-in disabled)` means OpenClaw intentionally dropped input while assistant audio was active. Enable `voice.realtime.bargeIn` if you want speech to interrupt playback.
- `barge-in ignored ... outputActive=false` means Discord or provider VAD reported speech, but OpenClaw had no active playback to interrupt. This should not cut off audio.
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>
@@ -144,7 +217,7 @@ imsg send <handle> "test"
Allowlist field: `channels.imessage.allowFrom`.
Allowlist entries can be handles or chat targets (`chat_id:*`, `chat_guid:*`, `chat_identifier:*`).
Allowlist entries can be handles, static sender access groups (`accessGroup:<name>`), or chat targets (`chat_id:*`, `chat_guid:*`, `chat_identifier:*`).
</Tab>
@@ -157,9 +230,41 @@ imsg send <handle> "test"
Group sender allowlist: `channels.imessage.groupAllowFrom`.
`groupAllowFrom` entries can also reference static sender access groups (`accessGroup:<name>`).
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 +273,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 +400,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 +436,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 +468,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 +557,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 +761,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 +780,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

@@ -139,6 +139,7 @@ Allowlists and policies:
- `channels.line.groupPolicy`: `allowlist | open | disabled`
- `channels.line.groupAllowFrom`: allowlisted LINE user IDs for groups
- Per-group overrides: `channels.line.groups.<groupId>.allowFrom`
- Static sender access groups can be referenced from `allowFrom`, `groupAllowFrom`, and per-group `allowFrom` with `accessGroup:<name>`.
- Runtime note: if `channels.line` is completely missing, runtime falls back to `groupPolicy="allowlist"` for group checks (even if `channels.defaults.groupPolicy` is set).
LINE IDs are case-sensitive. Valid IDs look like:

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

@@ -189,11 +189,13 @@ Notes:
- `openclaw pairing list mattermost`
- `openclaw pairing approve mattermost <CODE>`
- Public DMs: `channels.mattermost.dmPolicy="open"` plus `channels.mattermost.allowFrom=["*"]`.
- `channels.mattermost.allowFrom` accepts `accessGroup:<name>` entries. See [Access groups](/channels/access-groups).
## Channels (groups)
- Default: `channels.mattermost.groupPolicy = "allowlist"` (mention-gated).
- Allowlist senders with `channels.mattermost.groupAllowFrom` (user IDs recommended).
- `channels.mattermost.groupAllowFrom` accepts `accessGroup:<name>` entries. See [Access groups](/channels/access-groups).
- Per-channel mention overrides live under `channels.mattermost.groups.<channelId>.requireMention` or `channels.mattermost.groups["*"].requireMention` for a default.
- `@username` matching is mutable and only enabled when `channels.mattermost.dangerouslyAllowNameMatching: true`.
- Open channels: `channels.mattermost.groupPolicy="open"` (mention-gated).

View File

@@ -146,14 +146,14 @@ Disable with:
**DM access**
- Default: `channels.msteams.dmPolicy = "pairing"`. Unknown senders are ignored until approved.
- `channels.msteams.allowFrom` should use stable AAD object IDs.
- `channels.msteams.allowFrom` should use stable AAD object IDs or static sender access groups such as `accessGroup:core-team`.
- Do not rely on UPN/display-name matching for allowlists - they can change. OpenClaw disables direct name matching by default; opt in explicitly with `channels.msteams.dangerouslyAllowNameMatching: true`.
- The wizard can resolve names to IDs via Microsoft Graph when credentials allow.
**Group access**
- Default: `channels.msteams.groupPolicy = "allowlist"` (blocked unless you add `groupAllowFrom`). Use `channels.defaults.groupPolicy` to override the default when unset.
- `channels.msteams.groupAllowFrom` controls which senders can trigger in group chats/channels (falls back to `channels.msteams.allowFrom`).
- `channels.msteams.groupAllowFrom` controls which senders or static sender access groups can trigger in group chats/channels (falls back to `channels.msteams.allowFrom`).
- Set `groupPolicy: "open"` to allow any member (still mention-gated by default).
- To allow **no channels**, set `channels.msteams.groupPolicy: "disabled"`.
@@ -164,7 +164,7 @@ Example:
channels: {
msteams: {
groupPolicy: "allowlist",
groupAllowFrom: ["user@org.com"],
groupAllowFrom: ["00000000-0000-0000-0000-000000000000", "accessGroup:core-team"],
},
},
}

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.
@@ -157,6 +157,7 @@ Provider options:
- `channels.nextcloud-talk.groupPolicy`: `allowlist | open | disabled`.
- `channels.nextcloud-talk.groupAllowFrom`: group allowlist (user IDs).
- `channels.nextcloud-talk.rooms`: per-room settings and allowlist.
- Static sender access groups can be referenced from `allowFrom` and `groupAllowFrom` with `accessGroup:<name>`.
- `channels.nextcloud-talk.historyLimit`: group history limit (0 disables).
- `channels.nextcloud-talk.dmHistoryLimit`: DM history limit (0 disables).
- `channels.nextcloud-talk.dms`: per-DM overrides (historyLimit).

View File

@@ -44,7 +44,14 @@ Account keys:
- `botUserId` - Matrix-style bot user id used in target grammar.
- `botDisplayName` - display name for outbound messages.
- `pollTimeoutMs` - long-poll wait window. Integer between 100 and 30000.
- `allowFrom` - sender allowlist (user ids or `"*"`).
- `allowFrom` - sender allowlist (user ids or `"*"`). Direct messages and
allowlisted group policy both use these synthetic sender ids.
- `groupPolicy` - shared-room policy: `"open"` (default), `"allowlist"`, or
`"disabled"`.
- `groupAllowFrom` - optional shared-room sender allowlist. When omitted under
`"allowlist"`, QA Channel falls back to `allowFrom`.
- `groups.<room>.requireMention` - require a bot mention before replying in a
specific group/channel room. `groups."*"` sets the default.
- `defaultTo` - fallback target when none is supplied.
- `actions.messages` / `actions.reactions` / `actions.search` / `actions.threads` - per-action tool gating.

View File

@@ -1,17 +1,19 @@
---
summary: "Signal support via signal-cli (JSON-RPC + SSE), setup paths, and number model"
summary: "Signal support via signal-cli (native daemon or bbernhard container), setup paths, and number model"
read_when:
- Setting up Signal support
- Debugging Signal send/receive
title: "Signal"
---
Status: external CLI integration. Gateway talks to `signal-cli` over HTTP JSON-RPC + SSE.
Status: external CLI integration. Gateway talks to `signal-cli` over HTTP — either native daemon (JSON-RPC + SSE) or bbernhard/signal-cli-rest-api container (REST + WebSocket).
## Prerequisites
- OpenClaw installed on your server (Linux flow below tested on Ubuntu 24).
- `signal-cli` available on the host where the gateway runs.
- One of:
- `signal-cli` available on the host (native mode), **or**
- `bbernhard/signal-cli-rest-api` Docker container (container mode).
- A phone number that can receive one verification SMS (for SMS registration path).
- Browser access for Signal captcha (`signalcaptchas.org`) during registration.
@@ -179,6 +181,63 @@ If you want to manage `signal-cli` yourself (slow JVM cold starts, container ini
This skips auto-spawn and the startup wait inside OpenClaw. For slow starts when auto-spawning, set `channels.signal.startupTimeoutMs`.
## Container mode (bbernhard/signal-cli-rest-api)
Instead of running `signal-cli` natively, you can use the [bbernhard/signal-cli-rest-api](https://github.com/bbernhard/signal-cli-rest-api) Docker container. This wraps `signal-cli` behind a REST API and WebSocket interface.
Requirements:
- The container **must** run with `MODE=json-rpc` for real-time message receiving.
- Register or link your Signal account inside the container before connecting OpenClaw.
Example `docker-compose.yml` service:
```yaml
signal-cli:
image: bbernhard/signal-cli-rest-api:latest
environment:
MODE: json-rpc
ports:
- "8080:8080"
volumes:
- signal-cli-data:/home/.local/share/signal-cli
```
OpenClaw config:
```json5
{
channels: {
signal: {
enabled: true,
account: "+15551234567",
httpUrl: "http://signal-cli:8080",
autoStart: false,
apiMode: "container", // or "auto" to detect automatically
},
},
}
```
The `apiMode` field controls which protocol OpenClaw uses:
| Value | Behavior |
| ------------- | ------------------------------------------------------------------------------------ |
| `"auto"` | (Default) Probes both transports; streaming validates container WebSocket receive |
| `"native"` | Force native signal-cli (JSON-RPC at `/api/v1/rpc`, SSE at `/api/v1/events`) |
| `"container"` | Force bbernhard container (REST at `/v2/send`, WebSocket at `/v1/receive/{account}`) |
When `apiMode` is `"auto"`, OpenClaw caches the detected mode for 30 seconds to avoid repeated probes. Container receive is only selected for streaming after `/v1/receive/{account}` upgrades to WebSocket, which requires `MODE=json-rpc`.
Container mode supports the same Signal channel operations as native mode where the container exposes matching APIs: sends, receives, attachments, typing indicators, read/viewed receipts, reactions, groups, and styled text. OpenClaw translates its native Signal RPC calls into the container's REST payloads, including `group.{base64(internal_id)}` group IDs and `text_mode: "styled"` for formatted text.
Operational notes:
- Use `autoStart: false` with container mode. OpenClaw should not spawn a native daemon when `apiMode: "container"` is selected.
- Use `MODE=json-rpc` for receiving. `MODE=normal` can make `/v1/about` look healthy, but `/v1/receive/{account}` does not WebSocket-upgrade, so OpenClaw will not select container receive streaming in `auto` mode.
- Set `apiMode: "container"` when you know the `httpUrl` points at bbernhard's REST API. Set `apiMode: "native"` when you know it points at native `signal-cli` JSON-RPC/SSE. Use `"auto"` when the deployment may vary.
- Container attachment downloads honor the same media byte limits as native mode. Oversized responses are rejected before being fully buffered when the server sends `Content-Length`, and while streaming otherwise.
## Access control (DMs + groups)
DMs:
@@ -202,7 +261,8 @@ Groups:
## How it works (behavior)
- `signal-cli` runs as a daemon; the gateway reads events via SSE.
- Native mode: `signal-cli` runs as a daemon; the gateway reads events via SSE.
- Container mode: the gateway sends via REST API and receives via WebSocket.
- Inbound messages are normalized into the shared channel envelope.
- Replies always route back to the same number or group.
@@ -302,6 +362,7 @@ Full configuration: [Configuration](/gateway/configuration)
Provider options:
- `channels.signal.enabled`: enable/disable channel startup.
- `channels.signal.apiMode`: `auto | native | container` (default: auto). See [Container mode](#container-mode-bbernhardsignal-cli-rest-api).
- `channels.signal.account`: E.164 for the bot account.
- `channels.signal.cliPath`: path to `signal-cli`.
- `channels.signal.httpUrl`: full daemon URL (overrides host/port).

View File

@@ -930,6 +930,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

@@ -81,7 +81,7 @@ openclaw directory groups list --channel zalouser --query "work"
`channels.zalouser.dmPolicy` supports: `pairing | allowlist | open | disabled` (default: `pairing`).
`channels.zalouser.allowFrom` should use stable Zalo user IDs. During interactive setup, entered names can be resolved to IDs using the plugin's in-process contact lookup.
`channels.zalouser.allowFrom` should use stable Zalo user IDs. It can also reference static sender access groups (`accessGroup:<name>`). During interactive setup, entered names can be resolved to IDs using the plugin's in-process contact lookup.
If a raw name remains in config, startup resolves it only when `channels.zalouser.dangerouslyAllowNameMatching: true` is enabled. Without that opt-in, runtime sender checks are ID-only and raw names are ignored for authorization.
@@ -96,7 +96,7 @@ Approve via:
- Restrict to an allowlist with:
- `channels.zalouser.groupPolicy = "allowlist"`
- `channels.zalouser.groups` (keys should be stable group IDs; names are resolved to IDs on startup only when `channels.zalouser.dangerouslyAllowNameMatching: true` is enabled)
- `channels.zalouser.groupAllowFrom` (controls which senders in allowed groups can trigger the bot)
- `channels.zalouser.groupAllowFrom` (controls which senders in allowed groups can trigger the bot; static sender access groups can be referenced with `accessGroup:<name>`)
- Block all groups: `channels.zalouser.groupPolicy = "disabled"`.
- The configure wizard can prompt for group allowlists.
- On startup, OpenClaw resolves group/user names in allowlists to IDs and logs the mapping only when `channels.zalouser.dangerouslyAllowNameMatching: true` is enabled.

View File

@@ -258,7 +258,7 @@ Keep `workflow_ref` and `package_ref` separate. `workflow_ref` is the trusted wo
### Suite profiles
- `smoke``npm-onboard-channel-agent`, `gateway-network`, `config-reload`
- `package``npm-onboard-channel-agent`, `doctor-switch`, `update-channel-switch`, `upgrade-survivor`, `published-upgrade-survivor`, `plugins-offline`, `plugin-update`
- `package``npm-onboard-channel-agent`, `doctor-switch`, `update-channel-switch`, `skill-install`, `update-corrupt-plugin`, `upgrade-survivor`, `published-upgrade-survivor`, `update-restart-auth`, `plugins-offline`, `plugin-update`
- `product``package` plus `mcp-channels`, `cron-mcp-cleanup`, `openai-web-search-minimal`, `openwebui`
- `full` — full Docker release-path chunks with OpenWebUI
- `custom` — exact `docker_lanes`; required when `suite_profile=custom`
@@ -269,7 +269,7 @@ For the dedicated update and plugin testing policy, including local commands,
Docker lanes, Package Acceptance inputs, release defaults, and failure triage,
see [Testing updates and plugins](/help/testing-updates-plugins).
Release checks call Package Acceptance with `source=artifact`, the prepared release package artifact, `suite_profile=custom`, `docker_lanes='doctor-switch update-channel-switch upgrade-survivor published-upgrade-survivor plugins-offline plugin-update'`, and `telegram_mode=mock-openai`. This keeps package migration, update, stale-plugin-dependency cleanup, configured-plugin install repair, offline plugin, plugin-update, and Telegram proof on the same resolved package tarball. Set `package_acceptance_package_spec` on Full Release Validation or OpenClaw Release Checks to run that same matrix against a shipped npm package instead of the SHA-built artifact. Cross-OS release checks still cover OS-specific onboarding, installer, and platform behavior; package/update product validation should start with Package Acceptance. The `published-upgrade-survivor` Docker lane validates one published package baseline per run in the blocking release path. In Package Acceptance, the resolved `package-under-test` tarball is always the candidate and `published_upgrade_survivor_baseline` selects the fallback published baseline, defaulting to `openclaw@latest`; failed-lane rerun commands preserve that baseline. Full Release Validation with `run_release_soak=true` or `release_profile=full` sets `published_upgrade_survivor_baselines='last-stable-4 2026.4.23 2026.5.2 2026.4.15'` and `published_upgrade_survivor_scenarios=reported-issues` to expand across the four latest stable npm releases plus pinned plugin-compatibility boundary releases and issue-shaped fixtures for Feishu config, preserved bootstrap/persona files, configured OpenClaw plugin installs, tilde log paths, and stale legacy plugin dependency roots. Multi-baseline published-upgrade survivor selections are sharded by baseline into separate targeted Docker runner jobs. The separate `Update Migration` workflow uses the `update-migration` Docker lane with `all-since-2026.4.23` and `plugin-deps-cleanup` when the question is exhaustive published update cleanup, not normal Full Release CI breadth. Local aggregate runs can pass exact package specs with `OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPECS`, keep a single lane with `OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPEC` such as `openclaw@2026.4.15`, or set `OPENCLAW_UPGRADE_SURVIVOR_SCENARIOS` for the scenario matrix. The published lane configures the baseline with a baked `openclaw config set` command recipe, records recipe steps in `summary.json`, and probes `/healthz`, `/readyz`, plus RPC status after Gateway start. The Windows packaged and installer fresh lanes also verify that an installed package can import a browser-control override from a raw absolute Windows path. The OpenAI cross-OS agent-turn smoke defaults to `OPENCLAW_CROSS_OS_OPENAI_MODEL` when set, otherwise `openai/gpt-5.4`, so the install and gateway proof stays on a GPT-5 test model while avoiding GPT-4.x defaults.
Release checks call Package Acceptance with `source=artifact`, the prepared release package artifact, `suite_profile=custom`, `docker_lanes='doctor-switch update-channel-switch skill-install update-corrupt-plugin upgrade-survivor published-upgrade-survivor update-restart-auth plugins-offline plugin-update'`, and `telegram_mode=mock-openai`. This keeps package migration, update, live ClawHub skill install, stale-plugin-dependency cleanup, configured-plugin install repair, offline plugin, plugin-update, and Telegram proof on the same resolved package tarball. Set `package_acceptance_package_spec` on Full Release Validation or OpenClaw Release Checks to run that same matrix against a shipped npm package instead of the SHA-built artifact. Cross-OS release checks still cover OS-specific onboarding, installer, and platform behavior; package/update product validation should start with Package Acceptance. The `published-upgrade-survivor` Docker lane validates one published package baseline per run in the blocking release path. In Package Acceptance, the resolved `package-under-test` tarball is always the candidate and `published_upgrade_survivor_baseline` selects the fallback published baseline, defaulting to `openclaw@latest`; failed-lane rerun commands preserve that baseline. Full Release Validation with `run_release_soak=true` or `release_profile=full` sets `published_upgrade_survivor_baselines='last-stable-4 2026.4.23 2026.5.2 2026.4.15'` and `published_upgrade_survivor_scenarios=reported-issues` to expand across the four latest stable npm releases plus pinned plugin-compatibility boundary releases and issue-shaped fixtures for Feishu config, preserved bootstrap/persona files, configured OpenClaw plugin installs, tilde log paths, and stale legacy plugin dependency roots. Multi-baseline published-upgrade survivor selections are sharded by baseline into separate targeted Docker runner jobs. The separate `Update Migration` workflow uses the `update-migration` Docker lane with `all-since-2026.4.23` and `plugin-deps-cleanup` when the question is exhaustive published update cleanup, not normal Full Release CI breadth. Local aggregate runs can pass exact package specs with `OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPECS`, keep a single lane with `OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPEC` such as `openclaw@2026.4.15`, or set `OPENCLAW_UPGRADE_SURVIVOR_SCENARIOS` for the scenario matrix. The published lane configures the baseline with a baked `openclaw config set` command recipe, records recipe steps in `summary.json`, and probes `/healthz`, `/readyz`, plus RPC status after Gateway start. The Windows packaged and installer fresh lanes also verify that an installed package can import a browser-control override from a raw absolute Windows path. The OpenAI cross-OS agent-turn smoke defaults to `OPENCLAW_CROSS_OS_OPENAI_MODEL` when set, otherwise `openai/gpt-5.4`, so the install and gateway proof stays on a GPT-5 test model while avoiding GPT-4.x defaults.
### Legacy compatibility windows

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

@@ -80,7 +80,7 @@ When you run `openclaw channels add` without flags, the interactive wizard can p
- account ids per selected channel
- optional display names for those accounts
- `Bind configured channel accounts to agents now?`
- `Route these channel accounts to agents now?`
If you confirm bind now, the wizard asks which agent should own each configured channel account and writes account-scoped routing bindings.

View File

@@ -7,7 +7,9 @@ title: "Configure"
# `openclaw configure`
Interactive prompt to set up credentials, devices, and agent defaults.
Interactive prompt for targeted changes to an existing setup: credentials, devices, agent defaults, gateway, channels, plugins, skills, and health checks.
Use `openclaw onboard` for the full guided first-run journey, `openclaw setup` for the baseline config/workspace only, and `openclaw channels add` when you only need channel account setup.
<Note>
The **Model** section includes a multi-select for the `agents.defaults.models` allowlist (what shows up in `/model` and the model picker). Provider-scoped setup choices merge their selected models into the existing allowlist instead of replacing unrelated providers already in the config.

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.
@@ -67,6 +67,7 @@ Notes:
- Doctor includes a memory-search readiness check and can recommend `openclaw configure --section model` when embedding credentials are missing.
- Doctor warns when no command owner is configured. The command owner is the human operator account allowed to run owner-only commands and approve dangerous actions. DM pairing only lets someone talk to the bot; if you approved a sender before first-owner bootstrap existed, set `commands.ownerAllowFrom` explicitly.
- Doctor warns when Codex-mode agents are configured and personal Codex CLI assets exist in the operator's Codex home. Local Codex app-server launches use isolated per-agent homes, so use `openclaw migrate codex --dry-run` to inventory assets that should be promoted deliberately.
- Doctor removes retired `plugins.entries.codex.config.codexDynamicToolsProfile`; Codex app-server always keeps Codex-native workspace tools native.
- Doctor warns when skills allowed for the default agent are unavailable in the current runtime environment because bins, env vars, config, or OS requirements are missing. `doctor --fix` can disable those unavailable skills with `skills.entries.<skill>.enabled=false`; install/configure the missing requirement instead when you want to keep the skill active.
- If sandbox mode is enabled but Docker is unavailable, doctor reports a high-signal warning with remediation (`install Docker` or `openclaw config set agents.defaults.sandbox.mode off`).
- If legacy sandbox registry files (`~/.openclaw/sandbox/containers.json` or `~/.openclaw/sandbox/browsers.json`) are present, doctor reports them; `openclaw doctor --fix` migrates valid entries into sharded registry directories and quarantines invalid legacy files.

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

@@ -11,6 +11,13 @@ dedicated reference page or is documented with the command it aliases; this
index lists the commands, the global flags, and the output styling rules that
apply across the CLI.
Use the setup commands by intent:
- `openclaw setup` creates the baseline config and workspace without walking the full guided onboarding flow.
- `openclaw onboard` is the full guided first-run path for gateway, model auth, workspace, channels, skills, and health.
- `openclaw configure` changes targeted parts of an existing setup, such as model auth, gateway, channels, plugins, or skills.
- `openclaw channels add` configures channel accounts after the baseline exists; run it without flags for guided channel setup or with channel-specific flags for scripts.
## Command pages
| Area | Commands |
@@ -28,7 +35,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 +128,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.

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