Compare commits

...

1384 Commits

Author SHA1 Message Date
Vincent Koc
54429aa15d chore(plugin-sdk): refresh API baseline 2026-05-14 09:15:44 +08:00
Vincent Koc
b4bdd50c64 test(agents): fix live profile lint 2026-05-14 08:44:01 +08:00
Vincent Koc
690c521704 fix(plugin-sdk): export codex runtime helpers 2026-05-14 08:43:35 +08:00
Peter Steinberger
f3361dc928 test(agents): surface live OpenAI replay auth failures 2026-05-14 01:36:56 +01:00
Val Alexander
52370c5998 feat(ui): add browser-local Control UI text size setting
Adds a bounded browser-local Control UI text size setting in Appearance and Quick Settings, persists it in UiSettings, and applies CSS text-scale variables across chat text, composer input, sidebars, and tool cards while preserving mobile Safari input zoom safety.

Fixes #8547.
Thanks @BunsDev.
2026-05-13 19:18:05 -05:00
Peter Steinberger
0b55317494 test(plugins): isolate capability provider runtime mocks 2026-05-14 01:07:57 +01:00
Peter Steinberger
3225ec43c8 test(plugin-install): align npm peer scan expectations 2026-05-14 00:51:09 +01:00
Peter Steinberger
23446a248b ci(release): fail full validation on child failure 2026-05-14 00:46:22 +01:00
Eduardo Piva
9431d18aaf fix(sessions): classify spawn-child sessions correctly
Classify ACP spawn-child sessions via persisted spawnedBy metadata and share the session kind classifier across sessions/status output.

Verified with Azure Crabbox seeded ACP session-store proof, targeted session/status tests, touched-file lint, build, and green PR CI.
2026-05-13 16:39:04 -07:00
pashpashpash
74860e93fd fix(codex): preserve user home for app-server launches 2026-05-13 16:37:03 -07:00
Peter Steinberger
8046b5e462 docs: add plugin update changelog (#81512) (thanks @JARVIS-Glasses) 2026-05-14 00:25:52 +01:00
JARVIS-Glasses
5214f16e29 fix(update): clear stale plugin refs after failed updates 2026-05-14 00:25:52 +01:00
Vincent Koc
b5c3379097 fix(telegram): clear progress draft before answer 2026-05-14 07:19:00 +08:00
Peter Steinberger
dc7fab4dc5 perf: cache pi model discovery 2026-05-14 00:13:29 +01:00
Peter Steinberger
b10b946b12 docs(clawhub): remove missing security route 2026-05-13 23:57:05 +01:00
이민재
72f50dd127 fix(slack): normalize read timestamp bounds (#81338)
* fix(slack): normalize read timestamp bounds

* fix(slack): document read timestamp bounds fix

* fix(slack): simplify timestamp bounds validation

---------

Co-authored-by: honor2030 <19909783+honor2030@users.noreply.github.com>
Co-authored-by: Altay <altay@hey.com>
2026-05-14 01:52:55 +03:00
Vincent Koc
d08f68dee7 test(e2e): cover root-managed VPS upgrades 2026-05-14 06:50:58 +08:00
Peter Steinberger
25dd30d656 build(whatsapp): keep audio decoder dependency 2026-05-13 23:48:05 +01:00
Peter Steinberger
c654f1f811 test(whatsapp): allow audio runtime dependency 2026-05-13 23:47:03 +01:00
Josh Lehman
6395117142 fix: restore Codex cron automation compatibility (#81510)
* fix: restore Codex cron automation compatibility

* fix: document Codex cron automation restore
2026-05-13 15:34:31 -07:00
Shakker
26da4edbe1 docs: add acp request error changelog 2026-05-13 22:39:24 +01:00
vyctorbrzezowski
c5071a8061 fix(acp): preserve RequestError details 2026-05-13 22:39:24 +01:00
Eduardo Piva
207fb9951d fix(sessions): display ACP runtime sentinel for ACP sessions (#79543)
Display the ACP runtime sentinel for ACP control-plane session rows in openclaw sessions output, while preserving configured model/provider display for direct sessions.

Verified with focused sessions tests, touched-file oxlint, check:test-types, Crabbox after-fix proof, and exact-head GitHub CI.
2026-05-13 14:26:51 -07:00
B.K.
b8ea6097d9 fix(cli): report stale plugin doctor config (#81515)
Merged via squash.

Prepared head SHA: 23bc849abd
Co-authored-by: BKF-Gitty <263413630+BKF-Gitty@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-05-14 00:03:54 +03:00
vyctorbrzezowski
4d2e708726 fix(memory-lancedb): support cjk auto-capture triggers 2026-05-13 21:49:22 +01:00
Sarah Fortune
6602884b06 test(codex-migrate): stub clack log in migrate mock 2026-05-13 13:29:23 -07:00
Sarah Fortune
b85259c443 test(codex-migrate): cover new preview/result format 2026-05-13 13:29:23 -07:00
Sarah Fortune
49adf206e8 fix(codex-migrate): use String#replace in display name 2026-05-13 13:29:23 -07:00
Sarah Fortune
d7d1fba74b ux(codex-migrate): polish preview/result output
Restructure the migrate codex CLI output:

- Split into separate Before (preview) and After (result) messages
  so each can be tuned independently. Both render through clack's
  log.message so they pick up the standard '|' gutter.
- Group items by kind (Skills, Plugins, Memory, Secrets, Archive,
  Manual review, Other) instead of one flat list. Hide config items
  from display and exclude them from the summary count.
- Drop the internal kind/action tag (e.g. 'manual/manual'), strip
  '<kind>:' id prefixes and trailing ':N' disambiguators, and use
  '•' for bullets.
- Mute parenthetical action text.
- In result mode: replace status text with emoji ( migrated,
   error, ⏭️ skipped, ⚠️ conflict), show '(Migrated)' on success,
  show humanized failure reasons for known codes (plugin_missing,
  marketplace_missing, etc.), say '(Skipped)' for user-deselected
  skill/plugin items but keep the real message on manual-review
  skips. Drop warnings from the result message.
- In preview mode: omit the 'Next' section and move warnings to
  the bottom. Use generic action descriptions ('Copy Codex skill
  into OpenClaw', 'Install Codex plugin into OpenClaw').
- Drop the redundant 'Codex cached plugin bundles remain
  manual-review only.' warning — covered by the source-installed
  warning above it.
2026-05-13 13:29:23 -07:00
Peter Steinberger
cf571c1b58 fix(plugins): scope install scanner to runtime graph 2026-05-13 21:22:37 +01:00
dwc1997
cffae53b43 fix(security): classify broad Windows SIDs as world principals
Carry Windows ACL world-principal classification through @openclaw/fs-safe@0.2.2 so Anonymous Logon, Guests, Interactive, Network, and Local SID/principal variants are treated as world-equivalent in filesystem audit findings.

Also add regression coverage, changelog coverage, a narrow lint cleanup, and a UI test isolation fix needed by the current CI shard.

Co-authored-by: dwc <118101032587@njust.edu.cn>
2026-05-13 15:19:02 -05:00
Kevin Lin
6a23e26a27 docs: consolidate plugin install docs (#81167)
* docs: consolidate plugin install docs

* docs: align plugin getting started page

* snap

* docs: add reusable audit viewer tooling

* docs: add audit viewer doc mode

* docs: add audit viewer diff mode

* docs: strengthen plugin docs audit coverage

* docs: preserve plugin scan order reference

* docs: resolve plugin audit coverage gaps

* docs: strengthen audit line mappings

* docs: narrow plugin docs refactor scope

* docs: preserve plugin audit facts

* docs: keep audit skill local

* docs: remove audit skill from pr

* fix: satisfy plugin scan lint

* docs: address plugin docs review
2026-05-13 13:17:39 -07:00
Peter Steinberger
308b39efd5 docs: document real behavior proof fields 2026-05-13 21:08:17 +01:00
Peter Steinberger
f30c9eff76 docs: refresh clawdtributor update guidance 2026-05-13 21:07:49 +01:00
Peter Steinberger
7c4f607572 docs: refresh config baseline hash 2026-05-13 20:59:11 +01:00
Peter Steinberger
ebd829cffd test: add release qa docker lanes 2026-05-13 20:57:44 +01:00
edge_kase
8237d165e2 feat(acp): add backend provider failover for UNAVAILABLE errors (#69542)
Merged via squash.

Prepared head SHA: 1d4c929ad7
Co-authored-by: kaseonedge <15183881+kaseonedge@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-05-13 22:52:14 +03:00
狼哥
609187f5f6 fix(security): classify dangerous Windows sandbox binds first (#63074)
Adds Windows USERPROFILE to the sandbox blocked home roots so credential binds are denied even when HOME points at a different shell home.

Verified:
- node scripts/test-projects.mjs src/agents/sandbox/validate-sandbox-security.test.ts
- node scripts/test-projects.mjs src/agents/sandbox/bind-spec.test.ts src/agents/sandbox/host-paths.test.ts src/agents/sandbox/validate-sandbox-security.test.ts
- git diff --check HEAD^ HEAD

Co-authored-by: luoyanglang <hanwanlonga@gmail.com>
2026-05-13 14:42:45 -05:00
AI-HUB
b7d3b74f1c fix(ui): order live chat items by timestamp (#81016)
* fix(ui): order live chat items by timestamp

* fix(ui): stabilize chat timestamp sorting

* test: refresh core lint fixtures

* test: refresh current main guard fixtures

* test: refresh codex prompt snapshots

* test(matrix): keep runtime helper local

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-13 20:30:44 +01:00
Peter Steinberger
439e396262 fix(plugins): allow benign LanceDB runtime shims 2026-05-13 20:24:46 +01:00
Peter Steinberger
1f59031373 test(matrix): keep runtime media mock local 2026-05-13 20:07:10 +01:00
Peter Steinberger
8a406528b4 fix(codex): project user MCP servers into app-server threads
Fixes #80814.

Co-authored-by: kinjitakabe <273844887+kinjitakabe@users.noreply.github.com>
2026-05-13 20:07:10 +01:00
sallyom
d4484158d9 fix: avoid broad provider env marker inference 2026-05-13 15:02:56 -04:00
Josh Lehman
b55d9fa466 fix(codex): rotate incompatible context-engine threads (#81223)
* fix(codex): rotate incompatible context-engine threads

* fix(codex): tighten context-engine sidecar policy

* fix: type context-engine binding policy config

---------

Co-authored-by: Josh Lehman <phaedrus@Mac.hsd1.ca.comcast.net>
2026-05-13 11:50:03 -07:00
Shakker
433bafa55b fix: avoid bodyless media response buffering 2026-05-13 19:38:26 +01:00
Shakker
af6f75f78c docs: credit media fetch retry author 2026-05-13 19:38:26 +01:00
vyctorbrzezowski
e9a9434842 fix(media): retry transient remote media fetches 2026-05-13 19:38:26 +01:00
Peter Steinberger
58bfefbad3 test: add release user journey docker lane 2026-05-13 19:17:57 +01:00
homer-byte
c3e5d85ce1 fix(imessage): avoid visible media placeholder text (#81209)
Keep media-only iMessage sends from delivering visible <media:image> text while preserving a non-visible echo key for self-echo dedupe. Thanks @homer-byte.
2026-05-13 09:03:05 -07:00
Ayaan Zaidi
ddd79e51ba docs(changelog): note agent session bootstrap 2026-05-13 21:29:21 +05:30
Ayaan Zaidi
652af36d17 test(gateway): prove agent session bootstrap 2026-05-13 21:29:21 +05:30
Ayaan Zaidi
2d3f3de235 fix(gateway): bootstrap agent sessions before send 2026-05-13 21:29:21 +05:30
homer-byte
1d6e5f7a3e fix(imessage): make inbound image attachments readable by agents (#78580)
Stage native iMessage inbound attachments into managed media and convert HEIC/HEIF images to JPEG before dispatch. Thanks @homer-byte.
2026-05-13 08:35:52 -07:00
Peter Steinberger
58591c37a4 fix(tui): emit v4 embedded chat deltas
(cherry picked from commit a6d878376b)
2026-05-13 16:28:12 +01:00
Peter Steinberger
64ba5e2ae3 docs: add inline comment guidance 2026-05-13 16:13:49 +01:00
Peter Steinberger
f441a569ea docs: update changelog for OpenAI OAuth prompt (#81301) (thanks @rubencu) 2026-05-13 16:13:35 +01:00
Rubén Cuevas
83549774cd fix(openai): clarify remote Codex OAuth prompt 2026-05-13 16:13:35 +01:00
Peter Steinberger
48fb4bade8 docs: credit Telegram group fix contributor (#81030) 2026-05-13 16:09:13 +01:00
kinjitakabe
ab719c2f82 fix(telegram/groups): treat empty accounts.<id>.groups: {} as unspecified in single-account setups
`mergeTelegramAccountConfig` and the generic `resolveChannelGroups` both used
`accountGroups ?? channelConfig.groups` to fall back to root group allowlists,
which only catches the `undefined` case. An explicit empty `{}` survives
nullish coalescing and overrides the root allowlist with an empty allowlist,
which then pairs with the default `groupPolicy: "allowlist"` to silently
deny every group update — the symptom reported in #79427.

Treat an explicit empty `{}` the same as undefined for fallback purposes in
single-account setups (one or zero configured accounts). Multi-account setups
keep current semantics so per-account explicit-empty groups still scope
disable a single account without affecting its siblings. The explicit way to
block all groups for any account remains `groupPolicy: "disabled"`, which
this PR does not touch.

Fixes #79427.
2026-05-13 16:09:13 +01:00
Peter Steinberger
d540512d00 fix(gateway): satisfy node registry lint 2026-05-13 16:06:37 +01:00
Peter Steinberger
babd48b6cd docs(changelog): note v4 chat delta protocol 2026-05-13 16:06:37 +01:00
Peter Steinberger
a6497b1759 fix(gateway): avoid duplicate v4 deltas 2026-05-13 16:06:37 +01:00
Peter Steinberger
150bebcd0c fix(gateway): require v4 chat deltas 2026-05-13 16:06:37 +01:00
samzong
63724ddcfd fix(sdk): preserve replayed chat snapshots 2026-05-13 16:06:37 +01:00
samzong
10315ce215 fix(gateway): add incremental chat delta payloads 2026-05-13 16:06:37 +01:00
Vincent Koc
2a67a7f65e fix(plugins): prune managed peers on uninstall 2026-05-13 22:53:58 +08:00
Peter Steinberger
0513b285ef docs: update crabbox skill guidance 2026-05-13 15:46:50 +01:00
Pavan Kumar Gondhi
418d7afb33 gateway: pass Talk session scope to resolver [AI] (#81379)
* fix: pass talk session visibility scope

* addressing review-skill

* addressing review-skill

* addressing codex review

* addressing codex review

* addressing codex review

* addressing codex review

* addressing codex review

* addressing codex review

* addressing claude review

* addressing ci

* docs: add changelog entry for PR merge
2026-05-13 20:09:03 +05:30
Peter Steinberger
4d8aec8210 fix(plugins): attribute runtime config deprecations (#81425) (thanks @BKF-Gitty)
Co-authored-by: BKF-Gitty <bandark@mac.com>
2026-05-13 15:37:43 +01:00
Altay
a40499b21a fix(test): isolate auth profile secrets in test state (#81393)
Merged via squash.

Prepared head SHA: fde8787cb7
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-05-13 17:34:45 +03:00
Peter Steinberger
210c7c1b85 fix: preserve SGLang reasoning replay (#81091) 2026-05-13 15:28:07 +01:00
AI-HUB
51cd3cddeb fix(sglang): preserve reasoning replay history 2026-05-13 15:28:07 +01:00
Shakker
402b0df3b6 fix: preserve owned plugin dependencies during peer repair 2026-05-13 15:26:40 +01:00
Shakker
f4cb20300f fix: harden managed plugin peer recovery 2026-05-13 15:26:40 +01:00
Shakker
6e5042cd62 fix: avoid rescanning repaired plugin peers 2026-05-13 15:26:40 +01:00
Shakker
18ca285ed6 fix: preserve managed plugin peer dependencies 2026-05-13 15:26:40 +01:00
Peter Steinberger
1c28e4a0bb test: add docker live subagent announce proof 2026-05-13 15:21:37 +01:00
Peter Steinberger
0b8ee4616d fix(github-copilot): support Gemini image understanding
Fixes Copilot image understanding by exchanging OAuth tokens for Copilot API tokens, routing Copilot Gemini image requests through Chat Completions, and sending the prompt in user content with Copilot vision headers.

Real behavior proof:
- Old Responses route with real Copilot key reproduced `400 model gemini-3.1-pro-preview does not support Responses API`.
- Fixed route with the same real Copilot key returned `Cat`.
- Final CLI live smoke returned `ok: true` and `text: Cat` for `github-copilot/gemini-3.1-pro-preview`.

Verification:
- pnpm test src/media-understanding/image.test.ts extensions/github-copilot/models.test.ts extensions/github-copilot/stream.test.ts src/agents/pi-hooks/compaction-safeguard.test.ts -- --reporter=verbose
- pnpm check:changed via Blacksmith Testbox tbx_01krgt56pqmft8txekt017wke6, Actions run https://github.com/openclaw/openclaw/actions/runs/25803926150, exit 0.

Refs #80393, #80442.

Co-authored-by: Yang Haoyu <150496764+afunnyhy@users.noreply.github.com>
2026-05-13 15:20:27 +01:00
Peter Steinberger
6160e7a411 fix(gateway): hide unapproved node surfaces
Co-authored-by: samzong <samzong.lu@gmail.com>
2026-05-13 15:13:44 +01:00
Peter Steinberger
53d007bc87 refactor(media): centralize bounded remote downloads
Co-authored-by: samzong <samzong.lu@gmail.com>
2026-05-13 15:04:49 +01:00
Peter Steinberger
218156447c docs: add config mutation changelog 2026-05-13 15:00:07 +01:00
Peter Steinberger
ab3d61813a fix: rebase synthetic browser profiles 2026-05-13 15:00:07 +01:00
Peter Steinberger
23344fdb61 fix: avoid stale config mutation rebases 2026-05-13 15:00:07 +01:00
Peter Steinberger
756379b11d refactor: centralize config mutations 2026-05-13 15:00:07 +01:00
Peter Steinberger
c4c0b65b80 fix: rebase browser profile mutations 2026-05-13 15:00:07 +01:00
Peter Steinberger
ec998d1e95 fix: clean current dependency checks 2026-05-13 15:00:07 +01:00
Peter Steinberger
07c5e2465b fix: handle rebased config mutation races 2026-05-13 15:00:07 +01:00
Peter Steinberger
743cbc2f13 fix: mark slack channel system events untrusted 2026-05-13 15:00:07 +01:00
Peter Steinberger
66cce180c3 test: align config mutation mocks 2026-05-13 15:00:07 +01:00
Peter Steinberger
f3327ac30b fix: clean production config mutation checks 2026-05-13 15:00:07 +01:00
Peter Steinberger
2fe39ce949 refactor: rebase runtime config writes 2026-05-13 15:00:07 +01:00
Peter Steinberger
fb3aa155be fix: remove redundant config clone casts 2026-05-13 15:00:07 +01:00
Peter Steinberger
2e983e47df fix: serialize config mutation writes 2026-05-13 15:00:07 +01:00
Peter Steinberger
488a3d8e52 fix(ci): refresh stale metadata ownership 2026-05-13 14:59:47 +01:00
Peter Steinberger
5ac6b600de docs(channels): document bot loop protection 2026-05-13 14:59:47 +01:00
Peter Steinberger
4785a073d6 feat(channels): add generic bot loop protection 2026-05-13 14:59:47 +01:00
Peter Steinberger
d00e9eba65 docs: add ds4 provider guide 2026-05-13 14:45:34 +01:00
Peter Steinberger
96c0309db9 test: fix queue settings session fixtures 2026-05-13 14:24:45 +01:00
Peter Steinberger
714f62f976 test: add live subagent steering proof 2026-05-13 14:24:45 +01:00
Peter Steinberger
3cef9a65d3 fix: use in-process subagent announce handoff 2026-05-13 14:24:45 +01:00
stain lu
f1381b5312 fix(telegram): limit startup probes (#80986)
## Summary

- Limit Telegram startup `getMe` probes to two concurrent accounts.
- Add regression coverage for queued startup and queued abort behavior.
- Document the multi-account startup bound and add changelog credit.

## Verification

- `pnpm exec oxfmt --check --threads=1 CHANGELOG.md docs/channels/telegram.md extensions/telegram/src/channel.ts extensions/telegram/src/channel.gateway.test.ts extensions/telegram/src/startup-probe-limiter.ts`
- `node scripts/format-docs.mjs --check docs/channels/telegram.md`
- `git diff --check HEAD~1..HEAD`
- `env OPENCLAW_TEST_HEAVY_CHECK_LOCK_HELD=1 OPENCLAW_VITEST_MAX_WORKERS=1 pnpm --config.manage-package-manager-versions=false test extensions/telegram/src/channel.gateway.test.ts src/gateway/server-channels.test.ts`
- `env OPENCLAW_TSGO_HEAVY_CHECK_LOCK_HELD=1 pnpm --config.manage-package-manager-versions=false run tsgo:extensions`
- `env OPENCLAW_TSGO_HEAVY_CHECK_LOCK_HELD=1 pnpm --config.manage-package-manager-versions=false run tsgo:extensions:test`
- GitHub CI mostly green on `2d389e1010742efa884eacea520afd588d0b898f`; `check-test-types` red in unrelated `src/auto-reply/reply/queue/settings.test.ts` outside this PR's diff.

Co-authored-by: stainlu <stainlu@newtype-ai.org>
2026-05-13 14:23:32 +01:00
Pavan Kumar Gondhi
b17e77a22b Require approval for setup-code device pairing [AI] (#81292)
* fix: require approval for setup-code bootstrap pairing

* addressing review-skill

* addressing codex review

* addressing codex review

* addressing codex review

* addressing codex review

* addressing codex review

* addressing ci

* addressing ci

* docs: add changelog entry for PR merge
2026-05-13 18:48:44 +05:30
Peter Steinberger
05bef5db20 docs: update changelog for docker setup path fix (#81105) 2026-05-13 14:13:57 +01:00
brokemac79
3cf296185f fix(docker): pin setup cli container paths 2026-05-13 14:13:57 +01:00
Jason
70df2b8fe2 feat: steer mid-turn prompts by default (#77023)
Summary:
- Default active-run queueing to steer while preserving explicit followup/collect modes.
- Keep `/steer` fallback behavior and migrate retired queue steering config.
- Await Codex app-server steering acceptance so rejected/aborted steering can fall back safely.
- Route active subagent announcements through intentional acceptance-aware steering, with legacy queue helpers deprecated for delivery decisions.

Verification:
- git diff --check
- rg -n "^(<<<<<<<|=======|>>>>>>>|\|\|\|\|\|\|\|)" CHANGELOG.md docs src extensions || true
- pnpm test src/agents/subagent-announce-dispatch.test.ts src/agents/subagent-announce-delivery.test.ts src/agents/pi-embedded-runner/runs.test.ts src/agents/subagent-announce.format.e2e.test.ts src/agents/subagent-announce.test.ts
- pnpm test src/auto-reply/reply/commands-steer.test.ts src/auto-reply/reply/queue/settings.test.ts src/auto-reply/reply/queue-policy.test.ts src/auto-reply/reply/agent-runner.runreplyagent.e2e.test.ts src/auto-reply/reply/get-reply-run.media-only.test.ts extensions/codex/src/app-server/run-attempt.test.ts -- -t "queued steering|explicit all-mode steering|flushes pending default queued steering|rejects queued steering|resolveActiveRunQueueAction|resolveQueueSettings|handleSteerCommand"

Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
2026-05-13 14:00:11 +01:00
Peter Steinberger
1c5c72ea24 docs: update changelog for chat action overlap (#81244) 2026-05-13 13:54:30 +01:00
JARVIS-Glasses
3b7181a38b fix(ui): prevent chat actions overlapping replies 2026-05-13 13:54:06 +01:00
Peter Steinberger
4e34c1aa47 fix(channel): refresh wecom onboarding install (#80390) (thanks @brokemac79) 2026-05-13 13:52:05 +01:00
brokemac79
f2cbe9ecc5 fix(channel): refresh wecom onboarding install 2026-05-13 13:52:05 +01:00
Peter Steinberger
dfead3198d ci: make testbox session shutdown non-blocking 2026-05-13 13:50:44 +01:00
Peter Steinberger
852f88f1e7 ci: guard optional website installer file 2026-05-13 13:35:54 +01:00
Peter Steinberger
694ca50e97 Revert "refactor: move runtime state to SQLite"
This reverts commit f91de52f0d.
2026-05-13 13:33:38 +01:00
Peter Steinberger
3de5979bdc ci: fix website installer sync git add 2026-05-13 13:31:39 +01:00
Peter Steinberger
d1fdd6e186 fix(installer): honor git install versions 2026-05-13 13:17:29 +01:00
Peter Steinberger
f91de52f0d refactor: move runtime state to SQLite
* refactor: remove stale file-backed shims

* fix: harden sqlite state ci boundaries

* refactor: store matrix idb snapshots in sqlite

* fix: satisfy rebased CI guardrails

* refactor: store current conversation bindings in sqlite table

* refactor: store tui last sessions in sqlite table

* refactor: reset sqlite schema history

* refactor: drop unshipped sqlite table migration

* refactor: remove plugin index file rollback

* refactor: drop unshipped sqlite sidecar migrations

* refactor: remove runtime commitments kv migration

* refactor: preserve kysely sync result types

* refactor: drop unshipped sqlite schema migration table

* test: keep session usage coverage sqlite-backed

* refactor: keep sqlite migration doctor-only

* refactor: isolate device legacy imports

* refactor: isolate push voicewake legacy imports

* refactor: isolate remaining runtime legacy imports

* refactor: tighten sqlite migration guardrails

* test: cover sqlite persisted enum parsing

* refactor: isolate legacy update and tui imports

* refactor: tighten sqlite state ownership

* refactor: move legacy imports behind doctor

* refactor: remove legacy session row lookup

* refactor: canonicalize memory transcript locators

* refactor: drop transcript path scope fallbacks

* refactor: drop runtime legacy session delivery pruning

* refactor: store tts prefs only in sqlite

* refactor: remove cron store path runtime

* refactor: use cron sqlite store keys

* refactor: rename telegram message cache scope

* refactor: read memory dreaming status from sqlite

* refactor: rename cron status store key

* refactor: stop remembering transcript file paths

* test: use sqlite locators in agent fixtures

* refactor: remove file-shaped commitments and cron store surfaces

* refactor: keep compaction transcript handles out of session rows

* refactor: derive transcript handles from session identity

* refactor: derive runtime transcript handles

* refactor: remove gateway session locator reads

* refactor: remove transcript locator from session rows

* refactor: store raw stream diagnostics in sqlite

* refactor: remove file-shaped transcript rotation

* refactor: hide legacy trajectory paths from runtime

* refactor: remove runtime transcript file bridges

* refactor: repair database-first rebase fallout

* refactor: align tests with database-first state

* refactor: remove transcript file handoffs

* refactor: sync post-compaction memory by transcript scope

* refactor: run codex app-server sessions by id

* refactor: bind codex runtime state by session id

* refactor: pass memory transcripts by sqlite scope

* refactor: remove transcript locator cleanup leftovers

* test: remove stale transcript file fixtures

* refactor: remove transcript locator test helper

* test: make cron sqlite keys explicit

* test: remove cron runtime store paths

* test: remove stale session file fixtures

* test: use sqlite cron keys in diagnostics

* refactor: remove runtime delivery queue backfill

* test: drop fake export session file mocks

* refactor: rename acp session read failure flag

* refactor: rename acp row session key

* refactor: remove session store test seams

* refactor: move legacy session parser tests to doctor

* refactor: reindex managed memory in place

* refactor: drop stale session store wording

* refactor: rename session row helpers

* refactor: rename sqlite session entry modules

* refactor: remove transcript locator leftovers

* refactor: trim file-era audit wording

* refactor: clean managed media through sqlite

* fix: prefer explicit agent for exports

* fix: use prepared agent for session resets

* fix: canonicalize legacy codex binding import

* test: rename state cleanup helper

* docs: align backup docs with sqlite state

* refactor: drop legacy Pi usage auth fallback

* refactor: move legacy auth profile imports to doctor

* refactor: keep Pi model discovery auth in memory

* refactor: remove MSTeams legacy learning key fallback

* refactor: store model catalog config in sqlite

* refactor: use sqlite model catalog at runtime

* refactor: remove model json compatibility aliases

* refactor: store auth profiles in sqlite

* refactor: seed copied auth profiles in sqlite

* refactor: make auth profile runtime sqlite-addressed

* refactor: migrate hermes secrets into sqlite auth store

* refactor: move plugin install config migration to doctor

* refactor: rename plugin index audit checks

* test: drop auth file assumptions

* test: remove legacy transcript file assertions

* refactor: drop legacy cli session aliases

* refactor: store skill uploads in sqlite

* refactor: keep subagent attachments in sqlite vfs

* refactor: drop subagent attachment cleanup state

* refactor: move legacy session aliases to doctor

* refactor: require node 24 for sqlite state runtime

* refactor: move provider caches into sqlite state

* fix: harden virtual agent filesystem

* refactor: enforce database-first runtime state

* refactor: rename compaction transcript rotation setting

* test: clean sqlite refactor test types

* refactor: consolidate sqlite runtime state

* refactor: model session conversations in sqlite

* refactor: stop deriving cron delivery from session keys

* refactor: stop classifying sessions from key shape

* refactor: hydrate announce targets from typed delivery

* refactor: route heartbeat delivery from typed sqlite context

* refactor: tighten typed sqlite session routing

* refactor: remove session origin routing shadow

* refactor: drop session origin shadow fixtures

* perf: query sqlite vfs paths by prefix

* refactor: use typed conversation metadata for sessions

* refactor: prefer typed session routing metadata

* refactor: require typed session routing metadata

* refactor: resolve group tool policy from typed sessions

* refactor: delete dead session thread info bridge

* Show Codex subscription reset times in channel errors (#80456)

* feat(plugin-sdk): consolidate session workflow APIs

* fix(agents): allow read-only agent mount reads

* [codex] refresh plugin regression fixtures

* fix(agents): restore compaction gateway logs

* test: tighten gateway startup assertions

* Redact persisted secret-shaped payloads [AI] (#79006)

* test: tighten device pair notify assertions

* test: tighten hermes secret assertions

* test: assert matrix client error shapes

* test: assert config compat warnings

* fix(heartbeat): remap cron-run exec events to session keys (#80214)

* fix(codex): route btw through native side threads

* fix(auth): accept friendly OpenAI order for Codex profiles

* fix(codex): rotate auth profiles inside harness

* fix: keep browser status page probe within timeout

* test: assert agents add outputs

* test: pin cron read status

* fix(agents): avoid Pi resource discovery stalls

Co-authored-by: dataCenter430 <titan032000@gmail.com>

* fix: retire timed-out codex app-server clients

* test: tighten qa lab runtime assertions

* test: check security fix outputs

* test: verify extension runtime messages

* feat(wake): expose typed sessionKey on wake protocol + system event CLI

* fix(gateway): await session_end during shutdown drain and track channel + compaction lifecycle paths (#57790)

* test: guard talk consult call helper

* fix(codex): scale context engine projection (#80761)

* fix(codex): scale context engine projection

* fix: document Codex context projection scaling

* fix: document Codex context projection scaling

* fix: document Codex context projection scaling

* fix: document Codex context projection scaling

* chore: align Codex projection changelog

* chore: realign Codex projection changelog

* fix: isolate Codex projection patch

---------

Co-authored-by: Eva (agent) <eva+agent-78055@100yen.org>
Co-authored-by: Josh Lehman <josh@martian.engineering>

* refactor: move agent runtime state toward piless

* refactor: remove cron session reaper

* refactor: move session management to sqlite

* refactor: finish database-first state migration

* chore: refresh generated sqlite db types

* refactor: remove stale file-backed shims

* test: harden kysely type coverage

# Conflicts:
#	.agents/skills/kysely-database-access/SKILL.md
#	src/infra/kysely-sync.types.test.ts
#	src/proxy-capture/store.sqlite.test.ts
#	src/state/openclaw-agent-db.test.ts
#	src/state/openclaw-state-db.test.ts

* refactor: remove cron store path runtime

* refactor: keep compaction transcript handles out of session rows

* refactor: derive embedded transcripts from sqlite identity

* refactor: remove embedded transcript locator handoff

* refactor: remove runtime transcript file bridges

* refactor: remove transcript file handoffs

* refactor: remove MSTeams legacy learning key fallback

* refactor: store model catalog config in sqlite

* refactor: use sqlite model catalog at runtime

# Conflicts:
#	docs/cli/secrets.md
#	docs/gateway/authentication.md
#	docs/gateway/secrets.md

* fix: keep oauth sibling sync sqlite-local

# Conflicts:
#	src/commands/onboard-auth.test.ts

* refactor: remove task session store maintenance

# Conflicts:
#	src/commands/tasks.ts

* refactor: keep diagnostics in state sqlite

* refactor: enforce database-first runtime state

* refactor: consolidate sqlite runtime state

* Show Codex subscription reset times in channel errors (#80456)

* fix(codex): refresh subscription limit resets

* fix(codex): format reset times for channels

* Update CHANGELOG with latest changes and fixes

Updated CHANGELOG with recent fixes and improvements.

* fix(codex): keep command load failures on codex surface

* fix(codex): format account rate limits as rows

* fix(codex): summarize account limits as usage status

* fix(codex): simplify account limit status

* test: tighten subagent announce queue assertion

* test: tighten session delete lifecycle assertions

* test: tighten cron ops assertions

* fix: track cron execution milestones

* test: tighten hermes secret assertions

* test: assert matrix sync store payloads

* test: assert config compat warnings

* fix(codex): align btw side thread semantics

* fix(codex): honor codex fallback blocking

* fix(agents): avoid Pi resource discovery stalls

* test: tighten codex event assertions

* test: tighten cron assertions

* Fix Codex app-server OAuth harness auth

* refactor: move agent runtime state toward piless

* refactor: move device and push state to sqlite

* refactor: move runtime json state imports to doctor

* refactor: finish database-first state migration

* chore: refresh generated sqlite db types

* refactor: clarify cron sqlite store keys

* refactor: remove stale file-backed shims

* refactor: bind codex runtime state by session id

* test: expect sqlite trajectory branch export

* refactor: rename session row helpers

* fix: keep legacy device identity import in doctor

* refactor: enforce database-first runtime state

* refactor: consolidate sqlite runtime state

* build: align pi contract wrappers

* chore: repair database-first rebase

* refactor: remove session file test contracts

* test: update gateway session expectations

* refactor: stop routing from session compatibility shadows

* refactor: stop persisting session route shadows

* refactor: use typed delivery context in clients

* refactor: stop echoing session route shadows

* refactor: repair embedded runner rebase imports

# Conflicts:
#	src/agents/pi-embedded-runner/run/attempt.tool-call-argument-repair.ts

* refactor: align pi contract imports

* refactor: satisfy kysely sync helper guard

* refactor: remove file transcript bridge remnants

* refactor: remove session locator compatibility

* refactor: remove session file test contracts

* refactor: keep rebase database-first clean

* refactor: remove session file assumptions from e2e

* docs: clarify database-first goal state

* test: remove legacy store markers from sqlite runtime tests

* refactor: remove legacy store assumptions from runtime seams

* refactor: align sqlite runtime helper seams

* test: update memory recall sqlite audit mock

* refactor: align database-first runtime type seams

* test: clarify doctor cron legacy store names

* fix: preserve sqlite session route projections

* test: fix copilot token cache test syntax

* docs: update database-first proof status

* test: align database-first test fixtures

* docs: update database-first proof status

* refactor: clean extension database-first drift

* test: align agent session route proof

* test: clarify doctor legacy path fixtures

* chore: clean database-first changed checks

* chore: repair database-first rebase markers

* build: allow baileys git subdependency

* chore: repair exp-vfs rebase drift

* chore: finish exp-vfs rebase cleanup

* chore: satisfy rebase lint drift

* chore: fix qqbot rebase type seam

* chore: fix rebase drift leftovers

* fix: keep auth profile oauth secrets out of sqlite

* fix: repair rebase drift tests

* test: stabilize pairing request ordering

* test: use source manifests in plugin contract checks

* fix: restore gateway session metadata after rebase

* fix: repair database-first rebase drift

* fix: clean up database-first rebase fallout

* test: stabilize line quick reply receipt time

* fix: repair extension rebase drift

* test: keep transcript redaction tests sqlite-backed

* fix: carry injected transcript redaction through sqlite

* chore: clean database branch rebase residue

* fix: repair database branch CI drift

* fix: repair database branch CI guard drift

* fix: stabilize oauth tls preflight test

* test: align database branch fast guards

* test: repair build artifact boundary guards

* chore: clean changelog rebase markers

---------

Co-authored-by: pashpashpash <nik@vault77.ai>
Co-authored-by: Eva <eva@100yen.org>
Co-authored-by: stainlu <stainlu@newtype-ai.org>
Co-authored-by: Jason Zhou <jason.zhou.design@gmail.com>
Co-authored-by: Ruben Cuevas <hi@rubencu.com>
Co-authored-by: Pavan Kumar Gondhi <pavangondhi@gmail.com>
Co-authored-by: Shakker <shakkerdroid@gmail.com>
Co-authored-by: Kaspre <36520309+Kaspre@users.noreply.github.com>
Co-authored-by: dataCenter430 <titan032000@gmail.com>
Co-authored-by: Kaspre <kaspre@gmail.com>
Co-authored-by: pandadev66 <nova.full.stack@outlook.com>
Co-authored-by: Eva <admin@100yen.org>
Co-authored-by: Eva (agent) <eva+agent-78055@100yen.org>
Co-authored-by: Josh Lehman <josh@martian.engineering>
Co-authored-by: jeffjhunter <support@aipersonamethod.com>
2026-05-13 13:15:12 +01:00
Peter Steinberger
0a9f7afb66 fix(agents): surface memory-flush errors safely
Refs #80755.
Replaces #80884.

Verification:
- pnpm test src/plugins/contracts/extension-runtime-dependencies.contract.test.ts src/auto-reply/reply/agent-runner-memory.test.ts
- pnpm changed:lanes --json
- git diff --check
- node scripts/run-oxlint.mjs --tsconfig config/tsconfig/oxlint.scripts.json scripts/generate-plugin-inventory-doc.mjs scripts/deadcode-unused-files.allowlist.mjs
- pnpm deadcode:unused-files
- pnpm check:changed via Blacksmith Testbox tbx_01krgjhyx965k8ew4qg9nxq8yn
- GitHub CI on PR #81387 head 695f694b70

Co-authored-by: kinjitakabe <273844887+kinjitakabe@users.noreply.github.com>
2026-05-13 12:56:09 +01:00
Peter Steinberger
c796b96d34 docs: add changelog for Claude CLI reseed (#80934) (thanks @bitloi) 2026-05-13 12:54:40 +01:00
bitloi
dd8aa1dcce fix: reseed Claude CLI session context on rotation closes #80905 2026-05-13 12:54:40 +01:00
Jason
ce31fc91e1 Allow pnpm source updates to build OpenClaw (#81294)
Merged via squash.

Prepared head SHA: 4815d5a8c9
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-05-13 14:30:08 +03:00
Pavan Kumar Gondhi
af42260440 Require explicit browser device pairing [AI] (#81289)
* fix: require explicit pairing for browser-origin device sessions

* addressing ci

* addressing ci

* docs: add changelog entry for PR merge
2026-05-13 16:49:24 +05:30
Pavan Kumar Gondhi
96fba91b3a Require Control UI pairing before proxy-scoped access [AI] (#81288)
* fix: require control ui device pairing for proxy auth

* addressing review-skill

* fix: cover proxy control ui unbound scopes

* docs: add changelog entry for PR merge
2026-05-13 16:48:39 +05:30
Peter Steinberger
5f8e1dd399 feat(telegram): support web app presentation buttons
Refs #81356
Co-authored-by: Jamil Zakirov <jamil@zakirov.com>
2026-05-13 12:08:29 +01:00
Peter Steinberger
b4d148e21a fix: harden telegram localized command menus (#81351) (thanks @jzakirov) 2026-05-13 11:59:21 +01:00
Jamil Zakirov
97df0bc55a feat(telegram): localized command menu descriptions
Consume `descriptionLocalizations` from plugin command specs and
register per-locale command menus via Telegram `setMyCommands`
`language_code` parameter. Follows the same pattern already used
by the Discord extension.
2026-05-13 11:59:21 +01:00
Peter Steinberger
ca4672458c docs: stop referencing shell profile secrets 2026-05-13 11:55:14 +01:00
Peter Steinberger
0832343197 fix(discord): quiet fatal realtime voice startup failures 2026-05-13 11:51:43 +01:00
Peter Steinberger
74a809a1cd ci: grant dependency awareness pull request writes 2026-05-13 11:45:33 +01:00
Peter Steinberger
1bc45af1db ci: tolerate dependency awareness read-only tokens 2026-05-13 11:45:33 +01:00
Peter Steinberger
46f7750c63 fix: narrow plugin SDK hook type exports 2026-05-13 11:40:37 +01:00
Jamil Zakirov
68c77bb55d feat(plugin-sdk): export plugin hook types
Add `openclaw/plugin-sdk/types` entrypoint that re-exports plugin hook
types, so external plugins can import typed hook interfaces without
reaching into internal paths.

Also export `resolveActiveEmbeddedRunSessionId` from
`agent-harness-runtime` for session resolution in embedded runs.
2026-05-13 11:40:25 +01:00
Pavan Kumar Gondhi
26c7da2d02 Harden trusted-proxy source validation [AI] (#81290)
* fix: reject local-interface trusted-proxy peers

* addressing claude review

* docs: add changelog entry for PR merge
2026-05-13 16:10:11 +05:30
Jamil Zakirov
b7572cc384 feat(plugins): expose tools in LLM input hook event
Add optional `tools` array to `PluginHookLlmInputEvent` so plugin
hooks receive the full LLM call context, not just prompt and history.
2026-05-13 11:38:32 +01:00
Vincent Koc
65e37017b6 revert(cli): remove global root refusal (#81370) 2026-05-13 18:34:46 +08:00
Peter Steinberger
9f46e9cb85 refactor(provider): share operation timeout resolvers 2026-05-13 11:26:30 +01:00
Peter Steinberger
bd326cdd5e fix(provider): retry post status and download deadlines 2026-05-13 11:26:30 +01:00
Peter Steinberger
8b0b4ea82f fix(provider): retry google rest status failures 2026-05-13 11:26:30 +01:00
Peter Steinberger
af021aac8d fix(provider): preserve retry deadlines 2026-05-13 11:26:30 +01:00
Peter Steinberger
47ba73de27 fix(provider): type minimax retry helper 2026-05-13 11:26:30 +01:00
Peter Steinberger
86ee352138 fix(provider): avoid nested transcription retries 2026-05-13 11:26:30 +01:00
Peter Steinberger
ecdad948b5 refactor(provider): centralize transient retry stages 2026-05-13 11:26:30 +01:00
Peter Steinberger
9741bbe2c1 fix(provider): retry top-level network codes 2026-05-13 11:26:29 +01:00
Peter Steinberger
635f6e0d0e fix(provider): tag timeout aborts for retry 2026-05-13 11:26:29 +01:00
Peter Steinberger
b150e23a60 fix(provider): keep abort retries timeout-scoped 2026-05-13 11:26:29 +01:00
Peter Steinberger
2e3c49b161 fix(provider): dedupe transient retry policy 2026-05-13 11:26:29 +01:00
sqsge
f20054ba79 fix(provider): add opt-in transient retries for provider execution 2026-05-13 11:26:29 +01:00
Peter Steinberger
27e5d49fe5 build(whatsapp): keep audio deps external 2026-05-13 11:21:17 +01:00
Peter Steinberger
1e8e004361 build(pnpm): restore exotic subdependency blocking 2026-05-13 11:21:17 +01:00
Peter Steinberger
85f9276624 build(whatsapp): externalize whatsapp plugin 2026-05-13 11:21:17 +01:00
Peter Steinberger
49ccd4e080 docs: quote clawdtributor skill description 2026-05-13 11:20:33 +01:00
Peter Steinberger
7c89fb455b docs: tighten clawdtributor skill trigger 2026-05-13 11:18:31 +01:00
Peter Steinberger
09a490de17 docs: add clawdtributor triage skill 2026-05-13 11:16:34 +01:00
Peter Steinberger
a15559b8d0 fix: normalize array tool schemas (#81217) (thanks @JARVIS-Glasses) 2026-05-13 11:04:13 +01:00
JARVIS-Glasses
392b23c01e fix(agents): normalize array tool schemas 2026-05-13 11:04:13 +01:00
Peter Steinberger
2cae5e92a6 test: dedupe codex user input mock read 2026-05-13 10:58:25 +01:00
Peter Steinberger
16c5d5b87b test: dedupe codex subagent mirror mock reads 2026-05-13 10:57:08 +01:00
Peter Steinberger
453019a2c7 test: dedupe codex compact mock reads 2026-05-13 10:55:45 +01:00
Peter Steinberger
fe19d9fea8 test: dedupe codex schema mock read 2026-05-13 10:54:10 +01:00
Peter Steinberger
a661b7b04c test: dedupe feishu cleanup mock reads 2026-05-13 10:52:29 +01:00
Peter Steinberger
db6bb6d329 test: dedupe zalo pairing mock read 2026-05-13 10:51:10 +01:00
Peter Steinberger
c115b126d2 test: dedupe codex client mock reads 2026-05-13 10:49:47 +01:00
Peter Steinberger
48c8aa11f8 test: dedupe codex context engine mock read 2026-05-13 10:48:18 +01:00
Sarah Fortune
aae173a1c9 fix(plugins): raise default install scan file limit to 25k (#81361) 2026-05-13 02:47:13 -07:00
Peter Steinberger
62adbe0b80 test: dedupe codex binding mock helper 2026-05-13 10:45:51 +01:00
Peter Steinberger
80190249ec test: dedupe nostr mock call helper 2026-05-13 10:44:22 +01:00
Peter Steinberger
95901042d4 fix(config): normalize gemini subagent model writes 2026-05-13 10:42:08 +01:00
Jesse Merhi
6c92324c5f Revert "Check ClawHub trust before plugin installs (#81307)" (#81363)
This reverts commit 87eb450047.
2026-05-13 19:34:18 +10:00
Peter Steinberger
060768ef75 test: dedupe gateway run loop mock read 2026-05-13 10:33:35 +01:00
Peter Steinberger
a9215ef2d4 test: dedupe command secret target mock read 2026-05-13 10:28:56 +01:00
Peter Steinberger
578d723b48 test: dedupe daemon cli mock read 2026-05-13 10:25:54 +01:00
Peter Steinberger
b1db684aca test: dedupe command secret gateway mock read 2026-05-13 10:23:44 +01:00
Peter Steinberger
5904e2027f test: dedupe node cli mock read 2026-05-13 10:20:51 +01:00
Peter Steinberger
06b8cd4565 test: tighten core test mock fixtures 2026-05-13 10:18:35 +01:00
Peter Steinberger
2e6d34d2c9 test: dedupe matrix devices mock read 2026-05-13 10:13:47 +01:00
Peter Steinberger
321c996af8 test: dedupe matrix logger mock read 2026-05-13 10:12:05 +01:00
Peter Steinberger
0fa30e790c docs: clarify cluster close policy 2026-05-13 10:08:17 +01:00
Mason Huang
0eeafbdce2 docs(changelog): credit Ziy1-Tan for transcript redaction (#81343)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-13 17:06:17 +08:00
Peter Steinberger
7c3e4dbf94 test: dedupe whatsapp audio mock read 2026-05-13 10:02:45 +01:00
Peter Steinberger
3a44d88d09 test: dedupe litellm image mock read 2026-05-13 10:00:10 +01:00
Peter Steinberger
383ebe723b test: dedupe canvas tool mock read 2026-05-13 09:56:50 +01:00
Peter Steinberger
5bb2c5e454 test: dedupe canvas cli mock read 2026-05-13 09:54:55 +01:00
Peter Steinberger
f02b715f2b test: dedupe qqbot image mock reads 2026-05-13 09:51:51 +01:00
Peter Steinberger
898a5aae21 test: dedupe line signature mock read 2026-05-13 09:48:41 +01:00
Peter Steinberger
c1700a5c9f test: dedupe imessage action mock read 2026-05-13 09:45:26 +01:00
Peter Steinberger
ffb2dcc2e6 test: dedupe imessage retry mock reads 2026-05-13 09:43:20 +01:00
Peter Steinberger
1d331bcfc5 test: fix telegram transcript mock type 2026-05-13 09:39:19 +01:00
Peter Steinberger
6cd2059749 test: dedupe line rich menu mock reads 2026-05-13 09:35:04 +01:00
Peter Steinberger
33655ee290 test: dedupe line lifecycle mock read 2026-05-13 09:32:43 +01:00
clawsweeper[bot]
faaa7efef0 fix(security): inline redact into appendSessionTranscriptMessage (#79645)
Merged via squash.

Prepared head SHA: da91ab6cf1
Co-authored-by: app/clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
Reviewed-by: @hxy91819
2026-05-13 16:31:04 +08:00
Peter Steinberger
5ef9207813 test: dedupe mattermost retry mock read 2026-05-13 09:30:56 +01:00
Peter Steinberger
c8ddf71989 test: dedupe qa runtime mock read 2026-05-13 09:28:16 +01:00
Peter Steinberger
6c2e0bdc0c test: dedupe matrix action mock read 2026-05-13 09:25:59 +01:00
Peter Steinberger
06e04291e0 test: dedupe signal reply mock reads 2026-05-13 09:24:08 +01:00
Peter Steinberger
b693173e0d test: dedupe synology webhook mock read 2026-05-13 09:22:14 +01:00
Ayaan Zaidi
f7e9d80536 docs(changelog): credit idle timeout fallback fix (#80449) (thanks @jimdawdy-hub) 2026-05-13 13:51:51 +05:30
Ayaan Zaidi
a7ae889ae5 test(agents): cover idle timeout fallback during tools 2026-05-13 13:51:51 +05:30
Jim Dawdy
a6e4132a8c fix: preserve timeout reason after idle-only profile rotations
Addresses Codex P3 review finding: when shouldRotateAssistant fires on
idleTimedOut alone (timedOut=false), mergeRetryFailoverReason was passed
timedOut: params.timedOut (false), so the accumulated retry reason did
not record 'timeout'. Pass timedOut || idleTimedOut so the timeout reason
survives idle-only rotations and downstream fallback_model receives the
correct reason.
2026-05-13 13:51:51 +05:30
Jim Dawdy
b3ef14dbfc fix: address code review findings
- failover-policy.test.ts: move 4 new it() blocks inside describe()
  (they were orphaned outside the block and would not execute)
- run.ts: add idleTimedOut to the assistantFailoverDecision call site
  (missing required field caused TypeScript error and reproduced the freeze
  for the initial-decision code path in the outer loop)
- assistant-failover.ts: treat idleTimedOut same as timedOut in
  markFailedProfile to avoid incorrect profile failure recording
- assistant-failover.ts: add warn log when idle timeout rotates a profile
- assistant-failover.ts: extend resolveAssistantFailoverErrorMessage to
  accept idleTimedOut so surface_error emits "LLM request timed out."
  instead of the generic "LLM request failed."
2026-05-13 13:51:51 +05:30
Jim Dawdy
5ca95b2012 fix(agents): escalate LLM idle timeout to model fallback after profile rotation
When the LLM idle watchdog fires (model produced no tokens for N seconds),
idleTimedOut is set in handleAssistantFailover but was never passed into
resolveRunFailoverDecision. As a result, shouldRotateAssistant saw neither
failoverReason nor timedOut (the run-budget timeout) set, returned false,
and the decision fell through to continue_normal -- the agent silently froze
without surfacing an error or advancing the fallback chain.

Fixes #76877 (regression since 2026.4.24).

Changes:
- failover-policy.ts: add idleTimedOut to AssistantDecisionParams; include it
  in shouldRotateAssistant and reason selection in resolveRunFailoverDecision
- assistant-failover.ts: pass idleTimedOut into resolveRunFailoverDecision
- failover-policy.test.ts: 4 new cases for idle timeout path; update existing
  assistant stage cases with the new required field (idleTimedOut: false)
2026-05-13 13:51:51 +05:30
Peter Steinberger
ba17ddaef3 test: dedupe mattermost route mock read 2026-05-13 09:19:41 +01:00
Peter Steinberger
99f81f10e3 test: dedupe qqbot websocket mock read 2026-05-13 09:17:48 +01:00
Peter Steinberger
9ac275a8bf test: dedupe line download mock read 2026-05-13 09:16:20 +01:00
Peter Steinberger
1dc678393f test: dedupe huggingface provider mock read 2026-05-13 09:15:12 +01:00
Peter Steinberger
4e1f92641c test: dedupe tavily client mock reads 2026-05-13 09:13:34 +01:00
Peter Steinberger
9d13203d15 test: dedupe ollama setup mock reads 2026-05-13 09:12:26 +01:00
Peter Steinberger
6648950862 test: dedupe irc inbound mock read 2026-05-13 09:11:22 +01:00
Peter Steinberger
0f7b1c5414 test: dedupe clickclack inbound mock reads 2026-05-13 09:10:17 +01:00
Peter Steinberger
6ad1c7f3b7 test: dedupe discord listener mock read 2026-05-13 09:08:57 +01:00
Ayaan Zaidi
95a105334b docs(changelog): note worktree heavy-check locks (#80734) (thanks @samzong) 2026-05-13 13:38:52 +05:30
Ayaan Zaidi
25cda2b24c test(scripts): simplify worktree lock setup 2026-05-13 13:38:52 +05:30
samzong
94aae40c28 feat(scripts): allow worktree heavy-check locks
Signed-off-by: samzong <samzong.lu@gmail.com>
2026-05-13 13:38:52 +05:30
Peter Steinberger
64ff396593 test: dedupe discord webhook mock read 2026-05-13 09:06:09 +01:00
Josh Avant
bd4db5ee62 Add dependency release safety evidence and PR awareness (#81325)
* test: cover dependency pin guard

* build: add dependency vulnerability gate

* build: add dependency risk report

* build: add dependency drift reports

* build: include dependency ownership surface evidence

* build: rename dependency report commands

* build: respect release age exclusions in risk report

* build: clarify transitive risk accounting

* build: remove transitive risk exception registry

* build: clarify transitive risk signal wording

* ci: attach dependency evidence to release preflight

* ci: extract dependency release evidence generator

* build: rename ownership surface dependency report

* ci: clarify release evidence naming

* build: clarify recently published risk report

* build: reorder transitive risk report sections

* build: fix ownership surface pluralization

* ci: surface dependency changes on PRs

* ci: harden dependency change awareness

* ci: use dependency changed PR label

* build: fix dependency report lint

* docs: add dependency safety changelog
2026-05-13 03:05:09 -05:00
Peter Steinberger
b9b7ffc8cd test: dedupe memory search mock read 2026-05-13 09:04:40 +01:00
Peter Steinberger
f2bd20351f test: dedupe llm task mock read 2026-05-13 09:03:18 +01:00
Peter Steinberger
abd45b1763 test: dedupe zalo reply mock read 2026-05-13 08:59:31 +01:00
Peter Steinberger
96752f9804 test: dedupe tlon guarded fetch mock read 2026-05-13 08:57:52 +01:00
Peter Steinberger
22411e17cb fix(cli): normalize Gemini config mutation refs 2026-05-13 08:56:02 +01:00
Peter Steinberger
954407ab74 test: dedupe outbound matrix mock read 2026-05-13 08:43:35 +01:00
Peter Steinberger
edce338e32 test: dedupe cron model override last mock read 2026-05-13 08:41:20 +01:00
Peter Steinberger
cf11d16b43 fix(agents): make subagent task delivery visible
Co-authored-by: stainlu <stainlu@newtype-ai.org>
2026-05-13 08:40:27 +01:00
Peter Steinberger
17fe41a4b9 test: dedupe heartbeat stability mock read 2026-05-13 08:38:57 +01:00
Peter Steinberger
e2ced4cb53 test: dedupe command status mock read 2026-05-13 08:36:19 +01:00
Lellansin Huang
78e03e3004 fix(gateway): forward OpenAI sampling params
- Forward temperature and top_p through OpenAI-compatible chat and responses gateway paths.
- Return OpenAI-compatible 400 errors for invalid sampling params and provider validation failures instead of collapsing them to 500s.
- Add regression coverage and changelog credit.

Co-authored-by: lellansin <lellansin@gmail.com>
2026-05-13 08:35:48 +01:00
Peter Steinberger
b0c817ee9d test: dedupe discord sdk mock read 2026-05-13 08:32:31 +01:00
Peter Steinberger
27af4f618e test: dedupe inbound reply mock read 2026-05-13 08:30:05 +01:00
Peter Steinberger
52a02ab310 test: dedupe acp runtime mock read 2026-05-13 08:27:26 +01:00
Peter Steinberger
34ce85a83d test: dedupe heartbeat commitment mock read 2026-05-13 08:24:24 +01:00
Peter Steinberger
a95a317425 test: dedupe cron tts mock read 2026-05-13 08:22:07 +01:00
Peter Steinberger
40e8782400 test: dedupe cron skills snapshot mock read 2026-05-13 08:20:12 +01:00
Peter Steinberger
d97f72633c test: dedupe plugin approval mock read 2026-05-13 08:18:31 +01:00
Peter Steinberger
49e34f2b7b docs: update crabbox cross-platform skill 2026-05-13 08:16:47 +01:00
Peter Steinberger
f5be0d1406 fix: make codex harness live test portable 2026-05-13 08:16:47 +01:00
Peter Steinberger
984981832e test: dedupe cron model preflight mock read 2026-05-13 08:16:07 +01:00
Peter Steinberger
718476ccc5 test: dedupe cron model override mock read 2026-05-13 08:13:55 +01:00
Peter Steinberger
9ade25d985 test: dedupe isolated cron fallback mock read 2026-05-13 08:11:55 +01:00
Peter Steinberger
62f9024361 test: dedupe isolated cron session mock read 2026-05-13 08:09:59 +01:00
Peter Steinberger
1ae9d8227a test: dedupe cron enqueue mock read 2026-05-13 08:07:09 +01:00
Peter Steinberger
f706d3c322 test: dedupe approval route mock read 2026-05-13 08:05:28 +01:00
Peter Steinberger
4a97da8b47 test: dedupe scheduled turn mock read 2026-05-13 08:03:52 +01:00
Peter Steinberger
b6fcb63d75 test: dedupe session attachment mock read 2026-05-13 08:01:55 +01:00
Peter Steinberger
4c7ce0ad91 test: dedupe web search provider mock read 2026-05-13 07:59:34 +01:00
Peter Steinberger
81811e55a7 test: dedupe provider runtime mock read 2026-05-13 07:58:05 +01:00
Peter Steinberger
0bd3d7c2ed test: dedupe plugin runtime mock read 2026-05-13 07:56:44 +01:00
Peter Steinberger
d29225fde4 test: dedupe plugin install path mock read 2026-05-13 07:54:50 +01:00
Peter Steinberger
57027e35db test: dedupe metadata registry mock read 2026-05-13 07:53:22 +01:00
Peter Steinberger
15481dab26 test: dedupe plugin uninstall mock read 2026-05-13 07:51:59 +01:00
Sarah Fortune
a197e31abb feat(migrate): suppress plan log on embedding + add "Accept recommended" affordance (#81219)
Two related improvements to the interactive `openclaw migrate <provider>`
flow, both surfaced by the onboarding post-install migration prompt that
landed in #81192.

1. `suppressPlanLog?: boolean` on `MigrateCommonOptions`
   (`src/commands/migrate/types.ts`). When set, `migratePlanCommand`
   skips the up-front `runtime.log(formatMigrationPlan(plan))` dump.
   The interactive Codex selection picker and the "Apply this migration
   now?" confirm still run. Wired from the wizard helper at
   `src/wizard/setup.post-install-migration.ts` so that path no longer
   shows the plan dump after the user has already confirmed at the
   wizard prompt.

2. New "Accept recommended" sentinel row at the top of both Codex
   selection pickers, with "Toggle all on" and "Toggle all off" moved
   to the bottom. The cursor starts on "Accept recommended" so pressing
   Enter at the default position submits the picker's `initialValues`
   (the recommended set) — matching the visual state of the checkboxes.

   Implemented in `skill-selection-prompt.ts`:
   - Enter on the Accept sentinel sets `prompt.value` to
     `opts.initialValues` and lets clack submit.
   - Space on the Accept sentinel snaps `prompt.value` to
     `opts.initialValues` so the visible checkboxes flip to the
     recommended state. The user can then Enter to commit or continue
     toggling individual rows. The Accept row itself is never persisted
     in the submitted value list.

   The existing Enter handler for "Toggle all on" / "Toggle all off"
   stays unchanged.

3. Removed the "Skip for now" sentinel entirely. It was a single-
   keystroke trap: with the picker cursor wrapping from Accept to Skip
   via up-arrow (or via accidental down-arrows), Enter on Skip wiped
   `prompt.value` to `[MIGRATION_SELECTION_SKIP]` and abandoned the
   whole migration — including any items the user had already
   confirmed in the previous picker. To exit without migrating, users
   now navigate to "Toggle all off" (or use the `a` / `i` keyboard
   shortcuts) to clear the selection; the apply phase then sees no
   planned work and skips itself via the existing
   `shouldSkipCodexApplyAfterInteractiveSelection` path.

   Cleanup spans `migrate/selection.ts` (constants, `{ action: "skip" }`
   variant, and the reconcile/resolve SKIP branches),
   `migrate.ts` (the picker option rows and the
   `if (selection.action === "skip")` handler blocks in both pickers),
   and the corresponding tests.

4. Plugin selection hint relabelled from "Activate every recommended
   plugin" to "Migrate every recommended plugin" so it matches the
   skill hint and the prompt's own verb ("Migrate ... into this agent
   now?").

Tests:

- `src/commands/migrate/skill-selection-prompt.test.ts` — Accept
  sentinel cases (Enter and Space + Enter both submit initialValues);
  Skip-related test removed; Skip row dropped from the picker fixture.
- `src/commands/migrate/selection.test.ts` — Skip-related sub-
  assertions trimmed from the resolve/reconcile tests; the
  "skip + toggle-off precedence" test renamed to "toggle-off precedence
  over toggle-on" and Skip cases removed.
- `src/commands/migrate.test.ts` — four Skip-driven scenarios removed
  (plugin-only skip, both-pickers skip, skip-skills-continue-to-plugins,
  Codex subscription warning + skip).
- `src/wizard/setup.post-install-migration.test.ts` — call-args
  assertion expects the new `suppressPlanLog` option.

Verification:

- `pnpm lint` clean
- `pnpm tsgo:core` + `pnpm tsgo:core:test` clean
- Touched test suites green (migrate 32/32, selection 17/17,
  skill-selection-prompt 6/6, setup.post-install-migration 10/10).
2026-05-12 23:51:19 -07:00
Peter Steinberger
96b49f0b93 test: dedupe plugin service mock read 2026-05-13 07:50:21 +01:00
Peter Steinberger
10663e4ba2 test: dedupe plugin lifecycle mock read 2026-05-13 07:48:52 +01:00
Peter Steinberger
86dfc78d97 test: dedupe npm pack temp dir mock read 2026-05-13 07:46:07 +01:00
Peter Steinberger
8ebb18416a test: dedupe shell env exec mock read 2026-05-13 07:44:38 +01:00
Peter Steinberger
e898ea67b4 test: dedupe marketplace command mock read 2026-05-13 07:42:52 +01:00
Peter Steinberger
23856156e2 test: dedupe inbound claim log mock read 2026-05-13 07:41:24 +01:00
Peter Steinberger
21aaa9ed81 test: dedupe google video download mock read 2026-05-13 07:39:14 +01:00
Peter Steinberger
6b4333ae6b test: dedupe xiaomi speech fetch mock read 2026-05-13 07:37:35 +01:00
Peter Steinberger
3bc433c179 fix(config): normalize per-agent Gemini preview refs 2026-05-13 07:35:56 +01:00
Jesse Merhi
87eb450047 Check ClawHub trust before plugin installs (#81307)
Merged via squash.

Prepared head SHA: 273fd7c20e
Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com>
Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com>
Reviewed-by: @jesse-merhi
2026-05-13 16:31:52 +10:00
Peter Steinberger
cf68115e6e test: dedupe synology client mock reads 2026-05-13 07:25:03 +01:00
Peter Steinberger
ef78fc9534 test: dedupe synology route mock read 2026-05-13 07:23:36 +01:00
Ayaan Zaidi
8879c671e3 docs(changelog): note Telegram polling stall fix 2026-05-13 11:53:00 +05:30
Ayaan Zaidi
56873b6065 fix(telegram): detect polling stalls from getUpdates 2026-05-13 11:53:00 +05:30
Peter Steinberger
7899b70c18 test: dedupe whatsapp close mock read 2026-05-13 07:21:41 +01:00
Peter Steinberger
0b4f0129df test: dedupe qwen video request mock reads 2026-05-13 07:19:44 +01:00
Peter Steinberger
63ee74109e test: dedupe ollama embedding fetch mock read 2026-05-13 07:18:13 +01:00
Peter Steinberger
4cf6971130 test: dedupe gradium tts fetch mock read 2026-05-13 07:15:45 +01:00
Peter Steinberger
dd127ba0ba test: dedupe google image fetch mock read 2026-05-13 07:14:29 +01:00
Peter Steinberger
6932c66ffe test: dedupe minimax speech fetch mock reads 2026-05-13 07:12:39 +01:00
Peter Steinberger
7e1e4c5f78 test: dedupe memory wiki cli mock read 2026-05-13 07:11:04 +01:00
Peter Steinberger
6ced971cf1 test: dedupe minimax image fetch mock reads 2026-05-13 07:09:24 +01:00
Peter Steinberger
b430270429 test: dedupe copilot model fetch mock reads 2026-05-13 07:07:56 +01:00
Peter Steinberger
29ac94b0e4 test: dedupe device pair qr mock read 2026-05-13 07:06:34 +01:00
Ayaan Zaidi
bfbb9c6f9f docs(changelog): note ACP Claude timeout fix (#80812) (thanks @sxxtony) 2026-05-13 11:35:36 +05:30
Ayaan Zaidi
a146bf03db refactor(acpx): distill ACP command detection 2026-05-13 11:35:36 +05:30
sxxtony
bf8f5d991c fix(acp): drop unsupported timeout config option for claude-agent-acp
`runtime-options.buildRuntimeConfigOptionPairs` translated
`AcpSessionRuntimeOptions.timeoutSeconds` into a
`session/set_config_option(configId: "timeout")` pair on every turn. Both the
control plane (`AcpSessionManager.applyManagerRuntimeControls`) and the ACPX
wrapper (`AcpxRuntime.setConfigOption`) sit between that pair and the backend:

- The control plane validates pairs against the backend's advertised
  config-option keys and throws `ACP_BACKEND_UNSUPPORTED_CONTROL` for any
  pair the backend did not advertise. claude-agent-acp does not advertise a
  `timeout` alias.
- The wrapper then forwards remaining pairs to the delegate. The Codex ACP
  command was already short-circuited there; every other command, including
  claude-agent-acp, fell through.

Net effect on the reporter's scenario:
`sessions_spawn({ runtime:"acp", agentId:"claude", timeoutSeconds: 60 })`
failed at the control-plane validation with `ACP_BACKEND_UNSUPPORTED_CONTROL`
(and, had it reached the wire, claude-agent-acp would have answered
`-32603 Internal error / Unknown config option: timeout`, surfacing as
`ACP_TURN_FAILED: Internal error`).

Fix two layers:

1. Control plane (`src/acp/control-plane/runtime-options.ts`): add
   `isTimeoutConfigOptionAdvertised(advertisedConfigOptionKeys)` and gate the
   timeout pair on it. When advertised keys are unknown (`undefined` or
   empty), keep emitting the pair — this preserves current behavior for
   backends that have not produced a capability list yet. When advertised
   keys are present but exclude every alias in
   `RUNTIME_CONFIG_OPTION_ALIASES.timeoutSeconds`, skip the pair. The
   per-turn timeout is still enforced in-process via
   `AcpSessionManager.resolveTurnTimeoutMs` in `manager.core.ts`.

2. ACPX wrapper (`extensions/acpx/src/runtime.ts`): hoist the Codex
   `timeout` / `timeout_seconds` suppression so it also applies to
   claude-agent-acp commands. Add `isClaudeAcpCommand` mirroring
   `isCodexAcpCommand` (package spec, binary, generated wrapper script).
   This layer is defense in depth — relevant when callers reach the wrapper
   without going through `applyManagerRuntimeControls`, or when advertised
   keys are not yet known.

Coverage:

- `src/acp/control-plane/runtime-options.test.ts` (new) asserts:
  - the timeout pair is omitted when advertised keys exclude every alias,
  - the pair is kept when `timeout` or `timeout_seconds` is advertised,
  - the pair is kept when advertised keys are unknown,
  - model/thinking emission is unaffected.
- `extensions/acpx/src/runtime.test.ts` flips the previous
  `forwards timeout config controls for non-Codex ACP agents` test, which
  codified the buggy behavior, into a suppression assertion. Adds a
  positive `still forwards non-timeout config controls for claude-agent-acp`
  test and an `isClaudeAcpCommand` detector test.

Closes #81127
2026-05-13 11:35:36 +05:30
Peter Steinberger
50cb5ae089 test: dedupe openrouter stream mock read 2026-05-13 07:05:03 +01:00
Peter Steinberger
6a589017ca test: dedupe memory wiki gateway mock reads 2026-05-13 07:03:45 +01:00
Peter Steinberger
3945fd5812 test: dedupe tokenjuice mock read 2026-05-13 07:02:06 +01:00
Peter Steinberger
53032505bd test: dedupe memory lancedb provider assertion 2026-05-13 07:00:59 +01:00
Peter Steinberger
b8727202a5 test: dedupe inworld tts mock read 2026-05-13 06:59:47 +01:00
Peter Steinberger
7de4c47da2 test: dedupe qa credential lease mock read 2026-05-13 06:57:56 +01:00
Peter Steinberger
2a931b5906 test: dedupe google meet oauth mock read 2026-05-13 06:56:44 +01:00
Peter Steinberger
be343e3134 test: dedupe zalouser pairing mock reads 2026-05-13 06:55:30 +01:00
Peter Steinberger
0e3347cba6 test: dedupe reply flow mock read 2026-05-13 06:54:15 +01:00
Peter Steinberger
dccb382283 test: dedupe hook security mock read 2026-05-13 06:51:28 +01:00
Peter Steinberger
134461723e test: dedupe session hook mock read 2026-05-13 06:49:45 +01:00
Peter Steinberger
4a6e46152a test: dedupe sandbox media mock read 2026-05-13 06:48:05 +01:00
Peter Steinberger
6de17fcb75 test: dedupe exec host mock read 2026-05-13 06:46:29 +01:00
Peter Steinberger
560679a2ad test: dedupe outbound channel mock read 2026-05-13 06:45:08 +01:00
Peter Steinberger
af21973ea2 test: dedupe outbound send mock read 2026-05-13 06:43:10 +01:00
Peter Steinberger
07ffc2b955 test: dedupe outbound media mock read 2026-05-13 06:41:47 +01:00
Peter Steinberger
2b5d9bb47c test: dedupe cron owner auth mock read 2026-05-13 06:39:53 +01:00
Peter Steinberger
cd993f4584 test: dedupe cron fast mode mock read 2026-05-13 06:38:15 +01:00
Peter Steinberger
210f606be8 test: dedupe lmstudio stream mock read 2026-05-13 06:36:48 +01:00
Peter Steinberger
93233b2c6b test: dedupe azure speech mock reads 2026-05-13 06:35:12 +01:00
Peter Steinberger
f513c3f0dd test: dedupe qa manual lane mock reads 2026-05-13 06:32:35 +01:00
Peter Steinberger
b21630d6d1 test: dedupe memory watcher mock reads 2026-05-13 06:30:58 +01:00
Peter Steinberger
61268e8117 test: dedupe memory search mock read 2026-05-13 06:29:31 +01:00
Peter Steinberger
df9c9adeff test: dedupe mantle anthropic mock read 2026-05-13 06:27:58 +01:00
Peter Steinberger
87109e5fb5 test: dedupe anthropic vertex mock reads 2026-05-13 06:26:33 +01:00
Peter Steinberger
a282bdc601 test: dedupe openai image mock reads 2026-05-13 06:25:08 +01:00
Peter Steinberger
7bb2153fb2 test: dedupe openai tts mock reads 2026-05-13 06:23:44 +01:00
Peter Steinberger
30af076000 test: dedupe doctor registry mock read 2026-05-13 06:21:35 +01:00
homer-byte
ba1f4271e8 fix(imessage): keep pasted links without preview media (#79374)
Thanks @homer-byte.
2026-05-12 22:20:44 -07:00
Peter Steinberger
a123cddb4b test: dedupe channel module mock read 2026-05-13 06:19:57 +01:00
Ayaan Zaidi
8fe196e28b docs(changelog): add diagnostic lane PR reference 2026-05-13 10:48:46 +05:30
Ayaan Zaidi
d571f21c66 docs(changelog): note diagnostic lane fix 2026-05-13 10:48:46 +05:30
Ayaan Zaidi
3d3a2399b5 fix(logging): track reply runs in diagnostics 2026-05-13 10:48:46 +05:30
Peter Steinberger
5a10326612 test: dedupe node media log mock read 2026-05-13 06:17:56 +01:00
Peter Steinberger
934198b9a5 test: dedupe mcp channel mock read 2026-05-13 06:16:31 +01:00
Peter Steinberger
b25f657394 test: dedupe fetch timeout mock read 2026-05-13 06:15:29 +01:00
Peter Steinberger
6715ac526e test: dedupe plugin cli mock reads 2026-05-13 06:13:46 +01:00
Peter Steinberger
0b0539af17 test: dedupe outbound send mock read 2026-05-13 06:12:32 +01:00
Peter Steinberger
5a2dfac674 test: dedupe cli utility mock read 2026-05-13 06:11:23 +01:00
Peter Steinberger
6af82efcad test: dedupe feishu chat mock reads 2026-05-13 06:10:09 +01:00
Peter Steinberger
54c633db36 test: dedupe feishu docx mock reads 2026-05-13 06:09:06 +01:00
Peter Steinberger
73e0c51a5a test: dedupe vydra fetch mock reads 2026-05-13 06:07:49 +01:00
Peter Steinberger
832f91adbc test: dedupe gateway devices mock read 2026-05-13 06:06:21 +01:00
Peter Steinberger
8d50c3bc05 test: dedupe gateway tools mock reads 2026-05-13 06:05:23 +01:00
Peter Steinberger
2e7036e85c test: dedupe gateway sessions mock read 2026-05-13 06:04:18 +01:00
Peter Steinberger
f9157fcf82 test: dedupe gateway drain mock read 2026-05-13 06:03:11 +01:00
Peter Steinberger
5c67c93ac9 test: dedupe brave fetch mock read 2026-05-13 06:01:48 +01:00
Gio Della-Libera
f141a086fc fix(update): suppress handoff newer-config warning (#81235)
Merged via squash.

Prepared head SHA: 61a5c975bf
Co-authored-by: giodl73-repo <giodl@microsoft.com>
Co-authored-by: galiniliev <5711535+galiniliev@users.noreply.github.com>
Reviewed-by: @galiniliev
2026-05-12 22:01:21 -07:00
Peter Steinberger
94fdc56b64 test: dedupe cron ops mock read 2026-05-13 06:00:25 +01:00
Peter Steinberger
2c3582ad0b test: dedupe cron service mock reads 2026-05-13 05:58:16 +01:00
Peter Steinberger
8fd0f9965e test: dedupe google chat mock reads 2026-05-13 05:56:42 +01:00
Pavan Kumar Gondhi
39bcd1e088 fix(plugins): scan installed dependency runtime code [AI] (#81066)
* fix: scan installed plugin dependency code

* addressing review-skill

* addressing review-skill

* addressing codex review

* addressing codex review

* addressing codex review

* addressing codex review

* addressing codex review

* addressing codex review

* addressing codex review

* addressing codex review

* addressing ci

* addressing ci

* docs: add changelog entry for PR merge
2026-05-13 10:26:24 +05:30
Peter Steinberger
06c3318bba test: dedupe cli plugin registry mock read 2026-05-13 05:55:05 +01:00
Peter Steinberger
77f08d095d test: dedupe models cli mock read 2026-05-13 05:54:01 +01:00
Peter Steinberger
c27eca08e3 test: dedupe plugin timeout mock read 2026-05-13 05:52:55 +01:00
Peter Steinberger
2597d6d6d4 test: dedupe runtime web tools mock read 2026-05-13 05:51:45 +01:00
Pavan Kumar Gondhi
6c918ca85f Inherit tool restrictions for delegated sessions [AI] (#80979)
* fix: inherit tool restrictions for delegated sessions

* addressing review-skill

* addressing review-skill

* addressing review-skill

* addressing review-skill

* addressing codex review

* addressing codex review

* addressing codex review

* addressing codex review

* addressing codex review

* addressing review-skill

* addressing codex review

* addressing claude review

* addressing ci

* docs: add changelog entry for PR merge
2026-05-13 10:21:36 +05:30
Peter Steinberger
aba7652b76 test: dedupe echo transcript mock read 2026-05-13 05:50:33 +01:00
Peter Steinberger
5ce26962c5 test: dedupe daemon restart mock read 2026-05-13 05:49:16 +01:00
Peter Steinberger
30f09cc54c test: dedupe daemon lifecycle mock read 2026-05-13 05:48:12 +01:00
Peter Steinberger
277ad4a71b fix: guard link understanding fetches 2026-05-13 05:47:36 +01:00
Peter Steinberger
d3b16ddec8 docs: note baileys install policy 2026-05-13 05:47:36 +01:00
Peter Steinberger
266e72149b test: dedupe daemon config guard mock read 2026-05-13 05:47:11 +01:00
Peter Steinberger
27e47ae8e6 test: dedupe daemon install mock read 2026-05-13 05:46:18 +01:00
Peter Steinberger
7f8ce2dfd6 test: dedupe daemon service mock read 2026-05-13 05:44:49 +01:00
Peter Steinberger
1eeec9e183 test: dedupe exec approval mock read 2026-05-13 05:43:52 +01:00
Peter Steinberger
54dd6e6da2 test: dedupe cli help mock read 2026-05-13 05:42:52 +01:00
Ayaan Zaidi
a820bda89d docs(changelog): credit telegram offset fix (#80671) (thanks @sxxtony) 2026-05-13 10:12:31 +05:30
Ayaan Zaidi
306b51011f fix(telegram): handle legacy rotated offsets 2026-05-13 10:12:31 +05:30
sxxtony
cb93c0f8f5 fix(telegram): factor offset rotation handling into typed surfaces
Builds on the prior commit by introducing the typed surfaces the rest of
the plugin (and `openclaw doctor`-style consumers) can reuse:

- `inspectTelegramUpdateOffset` returns a discriminated union
  (`absent | valid | rotated`) so callers can act on the rotation event
  without re-implementing the bot-id / fingerprint comparison.
  `readTelegramUpdateOffset` is now a thin adapter over it.
- `TelegramOffsetRotationReason` is exported as a named type alias so
  downstream code can switch over it exhaustively.
- New `TelegramOffsetRotationHandler` class encapsulates the
  "log warning + delete stale file" side effect that the monitor needs at
  startup, plus a `createTelegramOffsetRotationHandler` factory and a
  pure `formatTelegramOffsetRotationMessage` helper used to keep the
  wording consistent.
- `monitor.ts` now constructs the handler once per polling startup
  instead of inlining the closure, and the new surfaces are re-exported
  through `monitor-polling.runtime.ts`.

Unit coverage:
  pnpm test extensions/telegram/src/update-offset-store.test.ts \
            extensions/telegram/src/offset-rotation-handler.test.ts \
            extensions/telegram/src/monitor.test.ts
2026-05-13 10:12:31 +05:30
sxxtony
290d3879eb fix(telegram): detect same-bot token rotation via fingerprinted offset state
Closes #80653.

Persist a non-reversible SHA-256 fingerprint of the bot token alongside the
bot id in the long-poll update offset store (version 3). On read, treat the
persisted offset as stale when the fingerprint diverges from the current
token, even when the bot id still matches. This covers the BotFather
`/revoke` case where the bot id is unchanged but the secret rotates -- the
in-process update tracker would otherwise silently skip any new updates
whose `update_id` is `<=` the restored watermark.

The legacy v2 (bot-id-only) layout still parses, and offsets are preserved
when the bot id matches so existing installs don't lose a watermark on
upgrade; the next persistence upgrades the file to v3 and enables rotation
detection going forward.

`readTelegramUpdateOffset` now reports each rotation through a new
`onRotationDetected` callback. `monitor.ts` uses it to log a clear warning
naming the previous/new bot id and the discarded offset, and to delete the
stale file rather than waiting for the first update to overwrite it.

Acceptance suites pass:
  pnpm test extensions/telegram/src/update-offset-store.test.ts \
            extensions/telegram/src/bot-update-tracker.test.ts \
            extensions/telegram/src/monitor.test.ts \
            extensions/telegram/src/bot.create-telegram-bot.test.ts \
            extensions/telegram/src/token.test.ts \
            extensions/telegram/src/polling-lease.test.ts
2026-05-13 10:12:31 +05:30
Peter Steinberger
9850cb5057 test: dedupe media understanding mock read 2026-05-13 05:41:53 +01:00
Peter Steinberger
11919c8a97 test: dedupe launchd handoff mock read 2026-05-13 05:40:55 +01:00
Peter Steinberger
4e8d9d26a9 test: dedupe wizard install plan mock read 2026-05-13 05:39:57 +01:00
Gio Della-Libera
14170f1be8 fix(commitments): write json output to stdout (#81215)
Merged via squash.

Prepared head SHA: 4a8d3bb51b
Co-authored-by: giodl73-repo <235387111+giodl73-repo@users.noreply.github.com>
Co-authored-by: galiniliev <5711535+galiniliev@users.noreply.github.com>
Reviewed-by: @galiniliev
2026-05-12 21:38:43 -07:00
Peter Steinberger
84f4bc6ca4 test: dedupe plugin uninstall mock read 2026-05-13 05:35:45 +01:00
Peter Steinberger
2ffad5c18a test: dedupe commitments mock read 2026-05-13 05:33:37 +01:00
Peter Steinberger
5592132f56 test: dedupe foundry provider mock read 2026-05-13 05:31:55 +01:00
Peter Steinberger
e643890176 test: dedupe task store mock reads 2026-05-13 05:30:29 +01:00
Pavan Kumar Gondhi
3d93174c43 browser: enforce navigation checks for act interactions [AI] (#81070)
* fix: apply browser navigation policy to act interactions

* addressing ci

* docs: add changelog entry for PR merge
2026-05-13 09:59:36 +05:30
Peter Steinberger
0d3b6d8ff6 test: dedupe cli registration mock reads 2026-05-13 05:29:02 +01:00
rendrag-git
8831754f5c fix: resolve custom provider env markers 2026-05-13 00:27:39 -04:00
rendrag-git
2269ec727f fix: list self-hosted runtime wildcard models 2026-05-13 00:27:39 -04:00
rendrag-git
3b361cf51c fix: discover self-hosted provider wildcards 2026-05-13 00:27:39 -04:00
Peter Steinberger
0c5bbdaad0 test: dedupe plugin install mock read 2026-05-13 05:27:34 +01:00
Peter Steinberger
e68dfa511e test: dedupe gateway hook mock read 2026-05-13 05:26:13 +01:00
Pavan Kumar Gondhi
17fa101c16 Validate node exec event provenance [AI] (#81071)
* fix: validate node exec event provenance

* addressing codex review

* addressing codex review

* addressing codex review

* addressing codex review

* addressing codex review

* addressing claude review

* addressing ci

* addressing ci

* addressing ci

* docs: add changelog entry for PR merge
2026-05-13 09:56:09 +05:30
Peter Steinberger
d643d64194 test: dedupe memory dreaming mock read 2026-05-13 05:25:01 +01:00
Peter Steinberger
8560bd845c test: dedupe realtime talk mock read 2026-05-13 05:23:45 +01:00
Peter Steinberger
98e6519878 test: dedupe acp permission mock read 2026-05-13 05:22:13 +01:00
Peter Steinberger
a840f3e775 test: dedupe message hooks mock read 2026-05-13 05:21:06 +01:00
Peter Steinberger
ac7b406d9d test: dedupe acp startup mock reads 2026-05-13 05:19:52 +01:00
Peter Steinberger
bc6fd1fe79 test: dedupe acp stop reason mock reads 2026-05-13 05:18:48 +01:00
Peter Steinberger
39f6dc7108 test: dedupe realtime websocket mock read 2026-05-13 05:17:42 +01:00
Peter Steinberger
33152f4162 test: dedupe provider env mock read 2026-05-13 05:16:18 +01:00
Peter Steinberger
3f590b4828 test: dedupe chat controller mock read 2026-05-13 05:15:18 +01:00
Peter Steinberger
8748ce9f57 test: dedupe system run mock read 2026-05-13 05:14:13 +01:00
Peter Steinberger
7b86539be2 test: dedupe auto reply helper mock read 2026-05-13 05:13:15 +01:00
Peter Steinberger
89a8047e18 test: dedupe heartbeat ack mock read 2026-05-13 05:11:46 +01:00
Peter Steinberger
d377c78aa3 test: dedupe heartbeat subagent mock read 2026-05-13 05:10:39 +01:00
Peter Steinberger
875dffca9e test: dedupe heartbeat tool mock reads 2026-05-13 05:09:36 +01:00
NVIDIAN
ecc48c6d86 fix(config): reject auto-managed meta.lastTouched* paths in config set/unset (#80856)
Merged via squash.

Prepared head SHA: a574312f5c
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-13 12:09:25 +08:00
Peter Steinberger
6a9e1a7aad test: dedupe tui shell mock read 2026-05-13 05:08:31 +01:00
Peter Steinberger
6912af6d83 test: dedupe proxy validation mock read 2026-05-13 05:07:36 +01:00
Peter Steinberger
4f7a6cebbc test: dedupe windows restart mock read 2026-05-13 05:06:40 +01:00
Peter Steinberger
401d2c6acc test: dedupe ssh config mock read 2026-05-13 05:05:47 +01:00
Peter Steinberger
ef44aa71d3 test: dedupe ssrf dispatcher mock read 2026-05-13 05:04:50 +01:00
Peter Steinberger
a6160b99d9 test: dedupe tui launch mock read 2026-05-13 05:03:53 +01:00
Peter Steinberger
b26db874a3 test: dedupe heartbeat reply mock read 2026-05-13 05:02:58 +01:00
Peter Steinberger
bc92f73ffb test: dedupe heartbeat prefix mock read 2026-05-13 05:02:01 +01:00
Peter Steinberger
02d2c1fee2 test: dedupe heartbeat typing mock read 2026-05-13 05:01:00 +01:00
Peter Steinberger
d7a6656913 test: dedupe transcript mock read 2026-05-13 04:58:43 +01:00
Peter Steinberger
ce712f503f test: dedupe run main mock read 2026-05-13 04:57:39 +01:00
Peter Steinberger
09116464b6 test: dedupe message lifecycle mock read 2026-05-13 04:56:24 +01:00
Peter Steinberger
69f7269e7d test: dedupe message send mock read 2026-05-13 04:55:34 +01:00
Peter Steinberger
abc2f57768 test: dedupe approval gateway mock read 2026-05-13 04:54:36 +01:00
Peter Steinberger
0cd0e57e9c test: dedupe npm root mock read 2026-05-13 04:53:42 +01:00
Peter Steinberger
e202231d56 test: dedupe security audit mock read 2026-05-13 04:52:25 +01:00
Peter Steinberger
65c056d7e2 test: dedupe sessions mock read 2026-05-13 04:51:24 +01:00
Peter Steinberger
45b0c92b3a test: dedupe plugin policy mock read 2026-05-13 04:50:28 +01:00
Peter Steinberger
5ca5c59de2 test: dedupe container target mock read 2026-05-13 04:49:36 +01:00
Peter Steinberger
20ec18807c test: dedupe batch http mock read 2026-05-13 04:48:40 +01:00
Peter Steinberger
06045b578a test: dedupe crestodian mock read 2026-05-13 04:47:44 +01:00
Peter Steinberger
23edebbaed test: dedupe audio transcode mock read 2026-05-13 04:46:31 +01:00
Peter Steinberger
f57c500034 test: dedupe custom theme mock reads 2026-05-13 04:45:33 +01:00
Peter Steinberger
b52a36d6e0 test: dedupe memory cli mock reads 2026-05-13 04:44:08 +01:00
Peter Steinberger
58cebd63c1 test: dedupe acp spawn mock reads 2026-05-13 04:43:00 +01:00
Peter Steinberger
53342ee5f3 test: dedupe live model switch mock reads 2026-05-13 04:42:04 +01:00
Peter Steinberger
6afe7f12b1 test: dedupe cli runner mock reads 2026-05-13 04:40:54 +01:00
Peter Steinberger
596f7a5cda test: dedupe pty fallback mock reads 2026-05-13 04:39:58 +01:00
Peter Steinberger
2cd936366b test: dedupe compaction summary mock reads 2026-05-13 04:39:08 +01:00
Peter Steinberger
36088884ac test: dedupe mcp transport mock reads 2026-05-13 04:38:19 +01:00
Peter Steinberger
3cfbc9e234 test: dedupe restart recovery mock reads 2026-05-13 04:36:36 +01:00
Peter Steinberger
c31874fe87 test: dedupe extra params mock reads 2026-05-13 04:35:34 +01:00
Peter Steinberger
6405977c03 test: dedupe context maintenance mock reads 2026-05-13 04:33:51 +01:00
Peter Steinberger
48e4a38655 test: dedupe prompt cache mock reads 2026-05-13 04:32:52 +01:00
Peter Steinberger
06d15572d3 test: dedupe runner cron mock reads 2026-05-13 04:31:58 +01:00
Peter Steinberger
6a14c838ca test: dedupe media handler mock reads 2026-05-13 04:30:55 +01:00
Peter Steinberger
92c84bbee4 test: dedupe acp lifecycle mock reads 2026-05-13 04:29:54 +01:00
Peter Steinberger
280d7931c1 test: dedupe memory dreaming mock reads 2026-05-13 04:28:50 +01:00
Peter Steinberger
5db2bf75c4 test: dedupe memory qmd mock reads 2026-05-13 04:27:38 +01:00
Peter Steinberger
f6d093e75e test: dedupe embedded subscribe flush mock reads 2026-05-13 04:25:31 +01:00
Peter Steinberger
9831b28dd7 test: dedupe before-tool-call e2e mock reads 2026-05-13 04:23:34 +01:00
Peter Steinberger
9eed27a9b8 test: dedupe before-tool-call mock reads 2026-05-13 04:21:55 +01:00
Peter Steinberger
47f31dd15d test: dedupe ui bootstrap mock reads 2026-05-13 04:20:35 +01:00
Peter Steinberger
d534c15b0a test: dedupe ui gateway mock reads 2026-05-13 04:19:08 +01:00
Peter Steinberger
936989a88b test: dedupe codex projector mock reads 2026-05-13 04:17:31 +01:00
Peter Steinberger
01fc684502 test: dedupe discord component mock reads 2026-05-13 04:16:05 +01:00
Peter Steinberger
32103aa3fd test: dedupe feishu doc mock reads 2026-05-13 04:14:38 +01:00
Peter Steinberger
da23f4572d test: dedupe matrix handler mock reads 2026-05-13 04:13:25 +01:00
Peter Steinberger
a08a38d4d9 test: dedupe mattermost monitor mock reads 2026-05-13 04:11:41 +01:00
Peter Steinberger
e566e817fb test: dedupe openai codex mock reads 2026-05-13 04:10:17 +01:00
Peter Steinberger
efc3e072a4 test: dedupe qqbot adapter mock reads 2026-05-13 04:09:05 +01:00
Peter Steinberger
a4514860e5 test: dedupe telegram command mock reads 2026-05-13 04:06:53 +01:00
Peter Steinberger
a5f5504b0d test: dedupe telegram monitor mock reads 2026-05-13 04:05:30 +01:00
pashpashpash
3688c47f1f Trust installed Codex for its private task runtime (#81206)
* fix(codex): trust installed codex task runtime

* fix(codex): keep private runtime alias packaged
2026-05-12 20:04:45 -07:00
Peter Steinberger
85eb8d47d4 test: dedupe vydra provider mock reads 2026-05-13 04:04:12 +01:00
Peter Steinberger
e1f24786f4 test: dedupe whatsapp login mock reads 2026-05-13 04:02:31 +01:00
Peter Steinberger
12f36b9a5a test: dedupe whatsapp allowlist mock reads 2026-05-13 04:01:19 +01:00
Peter Steinberger
a37c201776 test: dedupe whatsapp monitor mock reads 2026-05-13 03:59:43 +01:00
Rubén Cuevas
d4998d7b88 fix(plugins): retry npm alias override installs (#80539)
* fix(plugins): retry npm alias override installs

* fix(onboarding): space install retry warning

* fix(onboarding): shorten retry progress label

* docs(changelog): note npm alias install retry

---------

Co-authored-by: pashpashpash <nik@vault77.ai>
2026-05-12 19:58:21 -07:00
Peter Steinberger
38e1d68d7a test: dedupe discord process mock reads 2026-05-13 03:58:10 +01:00
Peter Steinberger
3375473e2b test: dedupe matrix cli mock reads 2026-05-13 03:56:49 +01:00
Peter Steinberger
b3260b1d15 test: dedupe telegram media mock reads 2026-05-13 03:55:27 +01:00
Peter Steinberger
889c1d7c15 test: dedupe whatsapp media mock reads 2026-05-13 03:54:10 +01:00
Peter Steinberger
eeecb48775 test: dedupe browser tool mock reads 2026-05-13 03:52:46 +01:00
Peter Steinberger
7159dab78d test: dedupe codex approval mock reads 2026-05-13 03:50:11 +01:00
Peter Steinberger
2edb8dede8 test: dedupe matrix send mock reads 2026-05-13 03:48:40 +01:00
Peter Steinberger
b8a27720f2 test: dedupe telegram gateway mock reads 2026-05-13 03:47:20 +01:00
Peter Steinberger
1f02abe381 fix(update): make pnpm preflight resolution deterministic 2026-05-13 03:46:33 +01:00
Peter Steinberger
f1ddaf46c7 ci: avoid pnpm prompts in live docker tests 2026-05-13 03:46:33 +01:00
Peter Steinberger
130b9bb2c1 test: dedupe browser cli mock reads 2026-05-13 03:45:26 +01:00
Peter Steinberger
ff7beea3da test: dedupe feishu routing mock reads 2026-05-13 03:43:41 +01:00
Peter Steinberger
cb613022ff test: dedupe telegram send mock reads 2026-05-13 03:42:22 +01:00
Peter Steinberger
4c663056d9 test: dedupe qa matrix mock reads 2026-05-13 03:40:17 +01:00
Peter Steinberger
6b77b8d978 test: dedupe discord voice mock reads 2026-05-13 03:37:28 +01:00
Peter Steinberger
a20d253819 test: dedupe active memory mock reads 2026-05-13 03:35:41 +01:00
Peter Steinberger
a06b735f32 test: dedupe provider fetch mock reads 2026-05-13 03:32:22 +01:00
Peter Steinberger
52ce64302f test: dedupe ssh spawn mock reads 2026-05-13 03:31:20 +01:00
Peter Steinberger
1296211c2e test: dedupe auto reply dispatch mock reads 2026-05-13 03:30:15 +01:00
Peter Steinberger
6b0b29fd04 test: dedupe reply media mock reads 2026-05-13 03:29:15 +01:00
Peter Steinberger
a6886d3fc4 test: dedupe durable delivery mock reads 2026-05-13 03:28:07 +01:00
Peter Steinberger
4ce9ff7845 test: dedupe exec policy mock reads 2026-05-13 03:26:58 +01:00
Peter Steinberger
d1ddb68d37 test: dedupe mcp cli mock reads 2026-05-13 03:25:53 +01:00
Peter Steinberger
91bae4baa5 test: dedupe nodes cli mock reads 2026-05-13 03:23:24 +01:00
Peter Steinberger
d8111ea65b test: dedupe setup cli mock reads 2026-05-13 03:21:50 +01:00
Peter Steinberger
48013bb259 test: dedupe qr cli mock reads 2026-05-13 03:20:26 +01:00
Peter Steinberger
00a01d1a39 test: dedupe security cli mock reads 2026-05-13 03:19:01 +01:00
Peter Steinberger
597c69036d test: dedupe cron retry mock reads 2026-05-13 03:17:40 +01:00
Peter Steinberger
9287aa5ef7 test: dedupe channel setup mock reads 2026-05-13 03:16:21 +01:00
Peter Steinberger
b2da3e0a02 test: dedupe embeddings http mock reads 2026-05-13 03:15:02 +01:00
Peter Steinberger
950831d6d1 test: dedupe gateway discovery mock reads 2026-05-13 03:13:55 +01:00
Marcus Castro
81a3de1d9d fix(whatsapp): drain debounced inbound before close (#81246)
* fix(whatsapp): drain debounced inbound before close

* docs(changelog): note WhatsApp debounce close drain
2026-05-12 23:13:38 -03:00
Peter Steinberger
ccf58b069d test: dedupe restart sentinel mock reads 2026-05-13 03:12:38 +01:00
Peter Steinberger
4f1549a6ae test: dedupe gateway reload mock reads 2026-05-13 03:11:19 +01:00
Peter Steinberger
cbf6d5cfe2 test: dedupe fetch guard mock reads 2026-05-13 03:08:34 +01:00
Peter Steinberger
4fdd71d186 test: dedupe transport ready mock reads 2026-05-13 03:07:27 +01:00
Peter Steinberger
74bbac994d test: dedupe git install mock reads 2026-05-13 03:06:23 +01:00
Peter Steinberger
661aa45eeb test: dedupe optional plugin tool mock reads 2026-05-13 03:05:15 +01:00
Peter Steinberger
fc09643aa2 test: dedupe tui command mock reads 2026-05-13 03:04:11 +01:00
Peter Steinberger
784b6cf2da test: dedupe dispatch config mock reads 2026-05-13 03:02:58 +01:00
WhatsSkiLL
e0f6f78b02 fix(gateway): clarify invalid config recovery hints
Closes #40652.

Thanks @JARVIS-Glasses.
2026-05-12 19:01:59 -07:00
Peter Steinberger
7cb596c807 test: dedupe model fallback mock reads 2026-05-13 03:01:37 +01:00
Peter Steinberger
b8bbe0e1e4 test: dedupe embedded reasoning mock reads 2026-05-13 02:59:52 +01:00
Peter Steinberger
46aa0ff9d0 test: dedupe embedded subscribe mock reads 2026-05-13 02:58:29 +01:00
Peter Steinberger
8f37126df7 test: dedupe session status mock reads 2026-05-13 02:57:13 +01:00
Peter Steinberger
919c8f1da5 test: dedupe models config mock reads 2026-05-13 02:56:04 +01:00
Peter Steinberger
191e9b68d7 test: dedupe compaction safeguard mock reads 2026-05-13 02:54:59 +01:00
Pavan Kumar Gondhi
a3fda2ada9 Limit hook CLI tool authority [AI] (#81065)
* fix: limit hook cli tool authority

* docs: add changelog entry for PR merge
2026-05-13 07:24:41 +05:30
Peter Steinberger
ac3aaad70c test: dedupe message tool mock reads 2026-05-13 02:53:44 +01:00
Peter Steinberger
6ace272a4b test: dedupe tts command mock reads 2026-05-13 02:52:35 +01:00
Peter Steinberger
9b4568c78f test: dedupe channel kernel mock reads 2026-05-13 02:51:21 +01:00
Pavan Kumar Gondhi
1c85eff9b1 Require admin scope for node device token management [AI] (#81067)
* fix: require admin for node device token management

* addressing review-skill

* addressing review-skill

* addressing review-skill

* addressing review-skill

* addressing claude review

* addressing ci

* docs: add changelog entry for PR merge
2026-05-13 07:20:35 +05:30
Peter Steinberger
e2965b5f96 test: dedupe openresponses mock reads 2026-05-13 02:50:18 +01:00
Peter Steinberger
0e9ebe0a92 test: dedupe gateway agent mock reads 2026-05-13 02:49:13 +01:00
Peter Steinberger
dfd63a2145 test: dedupe gateway watch tmux mock reads 2026-05-13 02:48:11 +01:00
Peter Steinberger
cc6da043bd test: dedupe apns http2 mock reads 2026-05-13 02:47:01 +01:00
Pavan Kumar Gondhi
b7e0decf0c Restrict chat sender allowlist matching [AI] (#80898)
* fix: restrict chat sender allowlist matching

* fix: restrict chat sender allowlist matching

* addressing codex review

* fix: complete sender allowlist root cause

* addressing codex review

* addressing codex review

* fix: complete root-cause handling

* addressing review-skill

* addressing codex review

* addressing review-skill

* addressing codex review

* addressing codex review

* fix: complete chat sender allowlist handling

* addressing codex review

* fix: complete root-cause handling

* addressing codex review

* fix: complete root-cause handling

* addressing codex review

* fix: cover sender matcher conversation target opt-in

* addressing review-skill

* addressing codex review

* fix: require explicit chat target sender matching

* addressing review-skill

* addressing codex review

* addressing codex review

* fix: require explicit chat target sender matching

* addressing codex review

* fix: require explicit chat target sender matching

* addressing codex review

* addressing codex review

* fix: require explicit chat target sender matching

* docs: add changelog entry for PR merge
2026-05-13 07:16:27 +05:30
Peter Steinberger
e3a4280788 test: dedupe fetch auth mock reads 2026-05-13 02:44:01 +01:00
Peter Steinberger
73ae1decdf test: dedupe tts contract mock reads 2026-05-13 02:42:04 +01:00
Peter Steinberger
0adc4ed0e7 test: dedupe agent command delivery mock reads 2026-05-13 02:39:43 +01:00
Peter Steinberger
90ea70b63b test: dedupe reply tag mock reads 2026-05-13 02:38:21 +01:00
Peter Steinberger
50f38cc0de test: dedupe subagent announce mock reads 2026-05-13 02:36:59 +01:00
Peter Steinberger
f507f52e19 test: dedupe cron hook prompt reads 2026-05-13 02:35:37 +01:00
Peter Steinberger
a5668efb7a test: dedupe cron session identity mock reads 2026-05-13 02:34:11 +01:00
Peter Steinberger
f9b3733f77 test: dedupe chat abort authorization mock reads 2026-05-13 02:31:53 +01:00
Peter Steinberger
c456e6fa97 test: dedupe chat abort persistence mock reads 2026-05-13 02:30:26 +01:00
Peter Steinberger
e3916e2606 test: dedupe plugin provider mock reads 2026-05-13 02:28:33 +01:00
Peter Steinberger
d0b3b1e1a4 test: dedupe soft chunk reply reads 2026-05-13 02:26:28 +01:00
Peter Steinberger
b7741b6f8c test: dedupe model fallback mock reads 2026-05-13 02:25:06 +01:00
Peter Steinberger
f537b06e8d test: dedupe gateway tool mock reads 2026-05-13 02:23:20 +01:00
Peter Steinberger
4aedf91028 test: dedupe followup runner mock reads 2026-05-13 02:22:08 +01:00
Peter Steinberger
9307df225d test: dedupe chat directive mock reads 2026-05-13 02:20:46 +01:00
Peter Steinberger
e7f6dfa925 test: dedupe incomplete turn attempt reads 2026-05-13 02:18:43 +01:00
Peter Steinberger
e17e881653 test: dedupe gateway plugin mock reads 2026-05-13 02:17:03 +01:00
Peter Steinberger
a9f34bf1f5 test: dedupe config cli log payload reads 2026-05-13 02:15:39 +01:00
Peter Steinberger
5e44f53c5b test: dedupe gateway cron mock reads 2026-05-13 02:13:28 +01:00
Peter Steinberger
e64a9a0507 test: dedupe update cli mock reads 2026-05-13 02:11:06 +01:00
Peter Steinberger
caa7b8a81d test: dedupe media reply mock reads 2026-05-13 02:09:23 +01:00
Peter Steinberger
dd923d9752 test: clear command mock call at usage 2026-05-13 02:07:53 +01:00
Peter Steinberger
5ad3f7adaa test: dedupe command helper mock reads 2026-05-13 02:05:55 +01:00
Peter Steinberger
28b19f4c66 test: dedupe command mock call reads 2026-05-13 02:04:09 +01:00
Peter Steinberger
38bab38ce7 fix: normalize per-agent gemini config refs 2026-05-13 02:02:54 +01:00
Peter Steinberger
bd8e986bb2 test: dedupe doctor security mock read 2026-05-13 01:57:55 +01:00
Peter Steinberger
6014aa5688 test: dedupe channels config write mock read 2026-05-13 01:56:32 +01:00
Peter Steinberger
019dd6282e test: dedupe status json mock read 2026-05-13 01:55:06 +01:00
Peter Steinberger
b5290d0692 test: dedupe agents delete mock read 2026-05-13 01:53:17 +01:00
Peter Steinberger
45f0f4a5ea test: dedupe channel doctor mock read 2026-05-13 01:52:05 +01:00
Peter Steinberger
c36089c417 test: dedupe launchctl note mock read 2026-05-13 01:50:52 +01:00
Peter Steinberger
05ea6054e3 test: dedupe channels status mock read 2026-05-13 01:49:06 +01:00
Peter Steinberger
bf16038b5c test: dedupe models forward mock read 2026-05-13 01:47:52 +01:00
Peter Steinberger
367c600849 test: dedupe doctor memory mock reads 2026-05-13 01:46:13 +01:00
Peter Steinberger
068e6e0291 test: dedupe auth choice install mock read 2026-05-13 01:44:36 +01:00
Peter Steinberger
832ab4787c test: dedupe models status mock read 2026-05-13 01:43:24 +01:00
Peter Steinberger
60f53f5d58 test: dedupe models list mock read 2026-05-13 01:41:59 +01:00
Peter Steinberger
a32c2e6cf5 test: dedupe status report mock read 2026-05-13 01:40:19 +01:00
Peter Steinberger
856b3efeba test: dedupe empty allowlist mock read 2026-05-13 01:39:02 +01:00
Peter Steinberger
c2b46b1331 test: dedupe channels config mock read 2026-05-13 01:37:53 +01:00
Peter Steinberger
0904357eb9 test: dedupe auth choice provider mock read 2026-05-13 01:36:27 +01:00
Peter Steinberger
97c8944eeb test: dedupe dashboard links mock read 2026-05-13 01:35:25 +01:00
Peter Steinberger
02ddaafd99 test: dedupe local daemon mock read 2026-05-13 01:34:22 +01:00
Peter Steinberger
00c99972df test: dedupe channels logs mock read 2026-05-13 01:32:59 +01:00
Peter Steinberger
ccd51b40dd test: dedupe oauth tls mock read 2026-05-13 01:31:59 +01:00
Peter Steinberger
963207d265 test: dedupe bootstrap size mock read 2026-05-13 01:30:54 +01:00
Peter Steinberger
8504029d73 test: dedupe configure daemon mock read 2026-05-13 01:29:36 +01:00
Peter Steinberger
e92806278d test: dedupe local auth choice mock read 2026-05-13 01:28:37 +01:00
Peter Steinberger
74171908cb test: dedupe configure gateway mock read 2026-05-13 01:27:35 +01:00
Sarah Fortune
d06f0a0ee7 fix(install): don't abort install.ps1 when git writes to stderr (#80834)
PowerShell 7+ honors $ErrorActionPreference=Stop for native commands,
so git's normal progress line ("From https://...") on stderr during
`git pull --rebase` would turn into a terminating error and abort the
installer immediately after a fresh clone — before pnpm install/build
ever runs. The existing `2>$null` redirects the display but the error
record is still generated.

Wrap the git status / pull calls in try/catch so the pull stays
best-effort and the rest of the installer can proceed. Reproduced on
Windows 11 ARM under PowerShell 7.x with -InstallMethod git.
2026-05-12 17:26:30 -07:00
Peter Steinberger
31ea86bf7d test: dedupe agents identity mock read 2026-05-13 01:25:54 +01:00
Peter Steinberger
003782a521 test: dedupe channels list mock read 2026-05-13 01:24:51 +01:00
Peter Steinberger
3356aafe3a test: dedupe status json mock read 2026-05-13 01:23:49 +01:00
Peter Steinberger
532fea836b test: dedupe flows mock read 2026-05-13 01:22:28 +01:00
Peter Steinberger
ccb9c68487 test: dedupe sandbox mock read 2026-05-13 01:21:33 +01:00
Peter Steinberger
48eb4e39b2 test: dedupe api key mock read 2026-05-13 01:20:16 +01:00
Peter Steinberger
5f5a0cf916 test: dedupe models shared mock read 2026-05-13 01:19:16 +01:00
Peter Steinberger
945d46c2b7 test: dedupe daemon install mock read 2026-05-13 01:18:11 +01:00
Sarah Fortune
e7c9e84a42 feat(onboard): add --skip-hooks flag (#81220) 2026-05-12 17:17:26 -07:00
Peter Steinberger
373fb93693 test: dedupe status runtime mock read 2026-05-13 01:16:00 +01:00
Peter Steinberger
57863c6009 test: dedupe doctor claude mock read 2026-05-13 01:14:18 +01:00
sallyom
f65251d0ec docs: note tool result detail redaction 2026-05-12 20:13:26 -04:00
nimbleenigma
277eb16652 fix: redact persisted tool result details
Refresh PR #80444 on current upstream main.
2026-05-12 20:13:26 -04:00
Peter Steinberger
250c26d02c test: dedupe backup verify mock read 2026-05-13 01:12:49 +01:00
Peter Steinberger
bf92aa7bc0 test: dedupe doctor browser mock read 2026-05-13 01:11:45 +01:00
Peter Steinberger
c6249e4809 test: dedupe doctor transcript mock read 2026-05-13 01:10:22 +01:00
Peter Steinberger
fccee9485c test: dedupe status service mock read 2026-05-13 01:09:16 +01:00
Peter Steinberger
4b33ade05e test: dedupe doctor auth mock read 2026-05-13 01:08:06 +01:00
Peter Steinberger
cf77ad5025 test: dedupe backup mock read 2026-05-13 01:06:38 +01:00
Peter Steinberger
9147a53274 fix: normalize nested gemini preview config ids 2026-05-13 01:05:25 +01:00
Peter Steinberger
f8953d94bd test: dedupe nodes tool mock read 2026-05-13 01:01:32 +01:00
Peter Steinberger
b8c0edf91c test: dedupe gateway tool mock read 2026-05-13 00:59:30 +01:00
Peter Steinberger
6d631d3adf test: dedupe cron tool mock read 2026-05-13 00:58:26 +01:00
Peter Steinberger
93a81865f0 test: dedupe embedded subscribe warning read 2026-05-13 00:56:52 +01:00
Peter Steinberger
5147d2849f test: dedupe coding tools mock read 2026-05-13 00:55:45 +01:00
Peter Steinberger
8830527536 test: dedupe model catalog mock read 2026-05-13 00:54:38 +01:00
Peter Steinberger
30442d9e4e test: dedupe pi project settings mock read 2026-05-13 00:53:31 +01:00
sallyom
14a9bb98b7 fix(config-audit): guard scrub rename after temp write
Signed-off-by: sallyom <somalley@redhat.com>
2026-05-12 19:52:52 -04:00
YB0y
432b94989b fix(config-audit): scrub pre-redactor argv values from historical config-audit.jsonl entries (#80777)
PR #75095 added `redactConfigAuditArgv` so newly-written entries in
`~/.openclaw/logs/config-audit.jsonl` mask token-shaped values, but the
audit log has no rotation, retention, or one-shot scrub. Users who ran
`openclaw config set <path> <secret-value>` between commit `748d6821d2`
(audit added 2026-02-14) and `a853c5e8c2` (redactor merged 2026-05-01)
still have plaintext Slack, Telegram, gateway, etc. tokens sitting in
`config-audit.jsonl` at rest after upgrading.

Add `scrubConfigAuditLog` in `src/config/io.audit.ts` that reads the
audit log, rewrites every record's `argv` / `execArgv` fields through
the existing forward redactor, and writes the file back atomically
(`*.scrub.tmp` + rename, mode 0o600). Idempotent — already-masked
entries pass through unchanged. Malformed lines are preserved verbatim
and counted as `skipped` so the scrub never destroys forensic content
it cannot understand. Concurrent-append guard: re-stat the audit log
immediately before rename and abort (no on-disk change) if the file
grew during the scrub, so a parallel appendConfigAuditRecord call is
never overwritten by the rename swap. Wire into the doctor health flow
as `runConfigAuditScrubHealth`: scan-only on a normal `openclaw doctor`
(prints the count and suggests `--fix`); rewrite atomically on
`openclaw doctor --fix` with a "rotate any credentials" note; print a
"stop the gateway and rerun" hint on the abort path. No plaintext
backup file is produced; file mode and parent dir mode are preserved.

Per repo CLAUDE.md ("Legacy config repair: doctor/fix paths, not
startup/load-time core migrations") the scrub is gated to `--fix`
and runs only when the user opts in.

Verified:
- pnpm install --frozen-lockfile
- pnpm test src/config/io.audit.test.ts
- pnpm test src/commands/doctor-config-flow.test.ts
- pnpm tsgo:core:test
- pnpm exec oxfmt --check --threads=1 src/config/io.audit.ts src/config/io.audit.test.ts src/commands/doctor-config-audit-scrub.ts src/flows/doctor-health-contributions.ts

Closes #80777
2026-05-12 19:52:52 -04:00
Peter Steinberger
9ae29c8bb1 test: dedupe pi tools schema mock read 2026-05-13 00:52:27 +01:00
Sarah Fortune
48529f1a96 feat(onboard): offer codex migration after harness install (#81192)
Add a post-install seam so the wizard can prompt the user to import their
existing Codex CLI state (skills, archived config/hooks, advisory cached
plugins) through the existing `openclaw migrate codex` flow once the
harness plugin is in place. Fires on both fresh installs and repair runs;
the user can decline at any time.

Trigger sites, both routing through one helper:

- src/plugins/provider-auth-choice.ts: after
  `ensureCodexRuntimePluginForModelSelection` reports `installed: true`,
  dynamically import `offerPostInstallMigrations` and call it before the
  wizard moves on.
- src/commands/onboard-non-interactive/local/auth-choice.plugin-providers.ts:
  same call shape with `nonInteractive: true`, so the helper emits a hint
  line only and never mutates state.

Helper (src/wizard/setup.post-install-migration.ts) is generic, not
Codex-hardcoded — it resolves migration providers via the manifest
`migrationProviders` contract, filters to providers owned by plugins the
caller flags as installed in this onboarding step, runs `provider.detect`,
and on TTY hands accepted runs to `migrateDefaultCommand`. All detect,
prompt, and migrate failures are swallowed so onboarding never aborts on
this optional offer.

Also harden the Codex app-server subprocess lifecycle now that `detect()`
runs from a hotter onboarding path: isolate the plugin-install
`plugin/read` call (extensions/codex/src/migration/apply.ts) and have the
isolated request wait for child exit with a SIGKILL fallback
(extensions/codex/src/app-server/request.ts) so parents are not held open
by an orphaned codex binary.

Tests:

- src/wizard/setup.post-install-migration.test.ts (new, 10 cases)
- src/commands/onboard-non-interactive/local/auth-choice.plugin-providers.test.ts
  extended with hint-call assertions and a not-required-no-offer case.
2026-05-12 16:51:27 -07:00
Peter Steinberger
37237a5129 test: dedupe auth profile mock read 2026-05-13 00:50:55 +01:00
Peter Steinberger
ce21937c97 test: dedupe cli helper mock read 2026-05-13 00:49:56 +01:00
Peter Steinberger
20e2206eac test: dedupe exec followup mock reads 2026-05-13 00:48:42 +01:00
Peter Steinberger
21a46f48d2 test: dedupe pi tool adapter log reads 2026-05-13 00:47:32 +01:00
Peter Steinberger
1ade7a53af test: dedupe cron scope mock reads 2026-05-13 00:43:49 +01:00
Peter Steinberger
f2935ca3ec test: dedupe sandbox manage mock reads 2026-05-13 00:41:53 +01:00
Peter Steinberger
a0833ed20b test: dedupe skills install mock reads 2026-05-13 00:40:42 +01:00
Peter Steinberger
9c3e08b346 test: dedupe subagent announce mock reads 2026-05-13 00:39:10 +01:00
Peter Steinberger
7964a49378 test: dedupe subagent spawn mock reads 2026-05-13 00:37:52 +01:00
Peter Steinberger
5051024366 test: dedupe subagent thread mock reads 2026-05-13 00:36:47 +01:00
Peter Steinberger
b540882703 test: dedupe music generate mock reads 2026-05-13 00:35:16 +01:00
Peter Steinberger
3c27f7428b test: dedupe cf markdown mock reads 2026-05-13 00:33:58 +01:00
Peter Steinberger
3436fc2f72 test: dedupe web search mock reads 2026-05-13 00:32:48 +01:00
Peter Steinberger
caa4cf7f0f test: dedupe web fetch mock reads 2026-05-13 00:31:44 +01:00
Peter Steinberger
0e4f2c53c7 test: dedupe command control mock reads 2026-05-13 00:30:24 +01:00
Peter Steinberger
df7a71afc6 test: dedupe agent runner execution mock reads 2026-05-13 00:29:14 +01:00
Peter Steinberger
b3cc2c17fc test: dedupe secret resolution mock reads 2026-05-13 00:27:20 +01:00
Peter Steinberger
a7b9bce139 test: dedupe acp command mock reads 2026-05-13 00:25:54 +01:00
Peter Steinberger
33419d7d1b test: dedupe commands core mock reads 2026-05-13 00:21:44 +01:00
Peter Steinberger
ba625e2cff test: dedupe models command mock reads 2026-05-13 00:18:15 +01:00
Peter Steinberger
f2b560ff5d test: dedupe session restart mock reads 2026-05-13 00:16:04 +01:00
Peter Steinberger
b46e5ae60c test: dedupe session usage mock reads 2026-05-13 00:13:54 +01:00
Peter Steinberger
0b165f708f test: dedupe subagents focus mock reads 2026-05-13 00:11:14 +01:00
Peter Steinberger
65d801cf8a test: dedupe reply dispatch mock reads 2026-05-13 00:09:13 +01:00
Peter Steinberger
e15cce76c7 test: dedupe get reply mock reads 2026-05-13 00:06:48 +01:00
Peter Steinberger
73e47fc6a9 test: dedupe session lifecycle mock reads 2026-05-13 00:04:44 +01:00
Peter Steinberger
f96cfeeb73 test: dedupe gateway cli mock reads 2026-05-13 00:02:45 +01:00
Peter Steinberger
86c4482c58 test: dedupe message thread mock reads 2026-05-13 00:01:15 +01:00
Peter Steinberger
8998e536fa test: dedupe cli route mock reads 2026-05-12 23:59:23 +01:00
Peter Steinberger
1cd736afd2 test: dedupe update cli mock reads 2026-05-12 23:57:58 +01:00
Peter Steinberger
d3099ff0de test: dedupe agent acp mock reads 2026-05-12 23:55:54 +01:00
Peter Steinberger
73907fdf5c test: dedupe channel setup mock reads 2026-05-12 23:54:01 +01:00
Peter Steinberger
4cd356fa2a test: dedupe channels remove mock reads 2026-05-12 23:52:31 +01:00
Peter Steinberger
87f5fb3ab2 test: dedupe doctor startup note mock reads 2026-05-12 23:51:02 +01:00
Peter Steinberger
6676be413e test: dedupe doctor sandbox mock reads 2026-05-12 23:49:46 +01:00
Peter Steinberger
6769b37c36 test: dedupe doctor workspace mock reads 2026-05-12 23:48:32 +01:00
Peter Steinberger
19599c268c test: dedupe doctor repair mock reads 2026-05-12 23:47:20 +01:00
Peter Steinberger
870e6f0ace test: dedupe doctor migration mock reads 2026-05-12 23:45:42 +01:00
Peter Steinberger
c4d4e5d315 test: dedupe message command mock reads 2026-05-12 23:44:26 +01:00
Peter Steinberger
51886077bd test: dedupe sessions cleanup mock reads 2026-05-12 23:43:09 +01:00
Peter Steinberger
2f21db25b0 test: dedupe status fast json mock reads 2026-05-12 23:41:39 +01:00
Peter Steinberger
afe2e07181 test: dedupe status scan mock reads 2026-05-12 23:40:29 +01:00
Peter Steinberger
b3c74c10c9 test: dedupe cron delivery mock reads 2026-05-12 23:39:09 +01:00
Peter Steinberger
1974e6f7b5 test: dedupe cron heartbeat mock reads 2026-05-12 23:37:55 +01:00
Peter Steinberger
b9d3843aff test: dedupe chat attachment mock reads 2026-05-12 23:36:35 +01:00
Peter Steinberger
73abe9e98a test: dedupe control ui auto root mock reads 2026-05-12 23:35:23 +01:00
Peter Steinberger
8a6c18a08a test: dedupe control ui http mock reads 2026-05-12 23:32:42 +01:00
Peter Steinberger
3779c10f27 test: dedupe managed image mock reads 2026-05-12 23:30:44 +01:00
Peter Steinberger
37d01fdd4a test: dedupe server channels mock reads 2026-05-12 23:29:04 +01:00
Peter Steinberger
55aadd2d48 test: dedupe server close mock reads 2026-05-12 23:27:26 +01:00
Peter Steinberger
85f89442c5 test: dedupe agent create event mock reads 2026-05-12 23:25:35 +01:00
Peter Steinberger
c34559d91d test: dedupe channels status mock reads 2026-05-12 23:24:01 +01:00
Kevin Lin
bc44f3824f fix: improve Codex migration selector enter 2026-05-12 15:23:28 -07:00
Peter Steinberger
ec7962fdc3 test: dedupe diagnostics mock reads 2026-05-12 23:21:48 +01:00
Peter Steinberger
096a331ab2 test: dedupe doctor response mock reads 2026-05-12 23:20:16 +01:00
Peter Steinberger
29ba6f8312 test: dedupe nodes pending mock reads 2026-05-12 23:18:10 +01:00
Peter Steinberger
fd79013b8f test: dedupe plugin approval mock reads 2026-05-12 23:15:29 +01:00
Peter Steinberger
ed3df9cbb8 test: dedupe tools catalog mock reads 2026-05-12 23:13:32 +01:00
Peter Steinberger
5ab28bf164 test: dedupe restart sentinel mock reads 2026-05-12 23:11:46 +01:00
Peter Steinberger
d79d6b2e5c test: dedupe startup log mock reads 2026-05-12 23:10:01 +01:00
Peter Steinberger
2c69c41643 test: dedupe sessions list mock reads 2026-05-12 23:08:25 +01:00
Peter Steinberger
b3ee777664 test: dedupe ws connection mock reads 2026-05-12 23:06:37 +01:00
Peter Steinberger
0768b4f2ad test: dedupe tools invoke mock reads 2026-05-12 23:05:20 +01:00
Peter Steinberger
e8a8675128 test: dedupe install flow mock reads 2026-05-12 23:03:59 +01:00
Peter Steinberger
fc94d7541c test: dedupe fetch guard mock reads 2026-05-12 23:02:32 +01:00
Peter Steinberger
c6ebc1d7e8 test: dedupe apns relay mock reads 2026-05-12 23:00:48 +01:00
Peter Steinberger
a3ff7aa02c test: dedupe run node mock reads 2026-05-12 22:59:34 +01:00
Peter Steinberger
3eaefda824 test: dedupe runtime llm mock reads 2026-05-12 22:57:53 +01:00
Peter Steinberger
d42b3c2b4a test: dedupe web fetch provider mock reads 2026-05-12 22:56:41 +01:00
Peter Steinberger
c9d7ba8690 test: dedupe wired hook error mock reads 2026-05-12 22:55:08 +01:00
Peter Steinberger
413580bef2 test: dedupe qa lab live gateway mock reads 2026-05-12 22:53:58 +01:00
Peter Steinberger
ec2944dc82 test: dedupe qa lab agent process mock reads 2026-05-12 22:52:33 +01:00
Peter Steinberger
65c5c3faf8 test: dedupe git install mock reads 2026-05-12 22:50:20 +01:00
Peter Steinberger
cf1987bbe9 test: dedupe plugin install mock reads 2026-05-12 22:48:58 +01:00
Peter Steinberger
6bd565d9f2 test: dedupe provider runtime mock reads 2026-05-12 22:46:49 +01:00
Peter Steinberger
96b2ef812d test: dedupe qa runner mock reads 2026-05-12 22:44:33 +01:00
Peter Steinberger
af8f3552e4 test: dedupe session maintenance mock reads 2026-05-12 22:42:15 +01:00
Peter Steinberger
9531befca5 test: dedupe heartbeat override mock reads 2026-05-12 22:40:54 +01:00
Peter Steinberger
f469cc69d3 test: dedupe approval handler mock reads 2026-05-12 22:39:17 +01:00
Solomon Neas
48af99ed30 fix(agents/harness): pass tool results through tool-result middleware safely (#78743)
Skip tool-result middleware validation when no handler is registered, and
sanitize incoming tool result `details` (functions, symbols, bigints,
cycles, oversized payloads) before middleware sees them. Tool emitters
legitimately produce raw dependency payloads on `details`, and the
harness owes any registered middleware a JSON-safe view of that payload;
otherwise a no-op middleware (e.g. bundled tokenjuice on the pi runtime)
causes the validator to reject every tool result and silently substitute
a failure sentinel, dropping outbound Discord messages, exec output,
cron results, and any other tool whose payload carries non-serializable
values.
2026-05-12 14:37:06 -07:00
Peter Steinberger
75a2e959b2 test: dedupe sessions thinking mock reads 2026-05-12 22:36:44 +01:00
Edward Abrams
b247b1432f fix(heartbeat): multi-agent cadence — parallel broadcast, per-agent busy check, prompt assembly, connect-timeout, doctor warning (#80470)
* fix(heartbeat): unblock beads cadence — parallel broadcast, agent-scoped busy check, full HEARTBEAT.md prompt, connect-timeout, doctor warning

* docs(changelog): note heartbeat cadence fixes

* fix(heartbeat): address review feedback

* fix(heartbeat): append HEARTBEAT.md directives to commitment-only task dispatch (review feedback)

* docs(changelog): extend heartbeat fix entry — commitment-only task dispatch path (review feedback)

* fix(heartbeat): clear connect timer on synchronous baseFn throw (review feedback)

When the provider stream function passed to streamWithIdleTimeout throws

synchronously during setup, the connect watchdog timer was left armed

and could fire onIdleTimeout later with a stale error, keeping the

process open past the real failure. Wrap the synchronous baseFn(...)

invocation in a try/catch that clears the connect timer before

rethrowing, and add a regression test that asserts onIdleTimeout is

not invoked after the synchronous throw.

* docs(changelog): note round-4 heartbeat fix (review feedback)

Bump the heartbeat fixes list from six to seven and document the

synchronous-baseFn-throw connect-timer cleanup added in the prior

commit.

* fix(heartbeat): honor omitted doctor target (review feedback)

* fix(heartbeat): merge doctor heartbeat defaults (review feedback)

Teach the heartbeat session-target doctor warning to enumerate the same agents as the runtime heartbeat runner and merge agents.defaults.heartbeat with per-agent overrides before checking pinned sessions.

Add regression coverage for default-only heartbeat.session pins and explicit agent heartbeat entries that inherit the default session.

Validation:
- pnpm test src/commands/doctor-heartbeat-session-target.test.ts
- pnpm tsgo:core
- pnpm tsgo:core:test
- pnpm config:schema:check
- pnpm exec oxlint src/commands/doctor-heartbeat-session-target.ts src/commands/doctor-heartbeat-session-target.test.ts
- pnpm exec oxfmt --check src/commands/doctor-heartbeat-session-target.ts src/commands/doctor-heartbeat-session-target.test.ts
- git diff --check

Beads: openclaw-8zp

* test(heartbeat): avoid redundant doctor assertion (review feedback)

The CI lint shard flags the non-null assertion in the heartbeat doctor regression test. Keep the same test setup while using an explicit guard so the test still narrows the fixture before mutating the heartbeat entry.

Validation:
- pnpm exec oxlint src/commands/doctor-heartbeat-session-target.test.ts
- pnpm test src/commands/doctor-heartbeat-session-target.test.ts
- pnpm tsgo:core:test
- git diff --check

Beads: openclaw-8zp

* docs(config): refresh baseline after heartbeat branch update

* fix(heartbeat): narrow doctor session warnings (review feedback)
2026-05-12 14:36:25 -07:00
Peter Steinberger
aef80a2940 test: dedupe gateway startup mock reads 2026-05-12 22:35:08 +01:00
Peter Steinberger
ae9b7041ef test: dedupe gateway push mock reads 2026-05-12 22:33:51 +01:00
Peter Steinberger
041906e2d5 test: dedupe models auth-status mock reads 2026-05-12 22:29:35 +01:00
Peter Steinberger
efb404b14f test: dedupe agents mutate mock reads 2026-05-12 22:27:00 +01:00
Peter Steinberger
2d4ac9a7f5 test: dedupe gateway aux mock reads 2026-05-12 22:24:34 +01:00
Peter Steinberger
de8022ba0e test: dedupe chat abort mock reads 2026-05-12 22:21:48 +01:00
Peter Steinberger
0428a6dd6f test: dedupe status scan mock reads 2026-05-12 22:20:02 +01:00
Shakker
67ead6ec0e test: payload error text output 2026-05-12 22:19:49 +01:00
Shakker
73723368b8 test: loop compaction log output 2026-05-12 22:19:14 +01:00
Shakker
d1c2ea0cba test: alert incomplete turn warnings 2026-05-12 22:18:39 +01:00
Shakker
369d252317 test: maintain context event output 2026-05-12 22:17:51 +01:00
Shakker
ed1d2db3da test: emit fs bridge script output 2026-05-12 22:17:25 +01:00
Peter Steinberger
46bd83498e test: dedupe models scan mock reads 2026-05-12 22:17:00 +01:00
Shakker
482a05a542 test: hide gh config home hint 2026-05-12 22:16:46 +01:00
Shakker
a5912b92f7 test: quarantine dangerous skill warnings 2026-05-12 22:16:02 +01:00
Shakker
4754b585f4 test: deliver command error output 2026-05-12 22:15:27 +01:00
Shakker
342d697276 test: single default account warning output 2026-05-12 22:14:59 +01:00
Peter Steinberger
8b6328d791 test: dedupe provider catalog mock reads 2026-05-12 22:14:50 +01:00
Shakker
6630766e7e test: disambiguate acp log output 2026-05-12 22:14:11 +01:00
Shakker
71d2e41bb0 test: bundle daemon secret warnings 2026-05-12 22:13:20 +01:00
Peter Steinberger
daffccddb6 test: dedupe doctor locks mock reads 2026-05-12 22:13:00 +01:00
Shakker
bb10e2b22d test: stringify daemon install warnings 2026-05-12 22:12:33 +01:00
Shakker
3653a231cc test: fuse auth choice error output 2026-05-12 22:12:04 +01:00
Shakker
a0f5cac723 test: dedicate gh config hint output 2026-05-12 22:11:35 +01:00
Peter Steinberger
77fb105aad test: dedupe configure wizard mock reads 2026-05-12 22:11:16 +01:00
Shakker
f9c87de73f test: condense gateway mismatch notes 2026-05-12 22:10:56 +01:00
Shakker
736b8c676b test: coalesce capability cli errors 2026-05-12 22:10:25 +01:00
Shakker
c4d26b9e0c test: compress plugin uninstall logs 2026-05-12 22:10:00 +01:00
Shakker
3cfcaf80d0 test: unify daemon status log assertions 2026-05-12 22:09:35 +01:00
Shakker
6e8d0605c3 test: concatenate cron list logs 2026-05-12 22:08:58 +01:00
Peter Steinberger
b51a7cb35e test: dedupe channel setup mock reads 2026-05-12 22:08:43 +01:00
Shakker
171d3e4fa2 test: assemble sandbox command output 2026-05-12 22:08:23 +01:00
Shakker
102cdd8d32 test: aggregate completion timeout logs 2026-05-12 22:07:47 +01:00
Solomon Neas
314903417f fix(memory-core): prevent staged dream candidates from leaking into MEMORY.md (#68774)
* fix(memory-core): prevent staged dream candidates from leaking into MEMORY.md

* fix(memory-core): correct PromotionComponents shape in dream-fence test fixture
2026-05-12 14:07:43 -07:00
Peter Steinberger
706699bd24 test: dedupe agents bind mock reads 2026-05-12 22:06:56 +01:00
Shakker
e156b4299c test: token gateway install warnings 2026-05-12 22:05:36 +01:00
Peter Steinberger
fd3f654f20 test: dedupe cli program mock reads 2026-05-12 22:05:30 +01:00
Shakker
6d91d60615 test: onboard search provider notes 2026-05-12 22:04:49 +01:00
Shakker
881878da39 test: spare state integrity files 2026-05-12 22:03:54 +01:00
Peter Steinberger
4472066237 test: dedupe gateway cli mock reads 2026-05-12 22:03:46 +01:00
Shakker
726ecc4987 test: prompt auth choice messages 2026-05-12 22:02:49 +01:00
Shakker
e6c09b90cb test: fetch claude usage urls 2026-05-12 22:02:20 +01:00
Peter Steinberger
a8dd5653ee test: dedupe exec approvals cli mock reads 2026-05-12 22:02:03 +01:00
Shakker
5959a99646 test: queue outbound log text 2026-05-12 22:01:40 +01:00
Shakker
201dd735a0 test: log diagnostic messages 2026-05-12 22:00:59 +01:00
Peter Steinberger
0d4f4bab94 test: dedupe config cli mock reads 2026-05-12 22:00:36 +01:00
Shakker
d4c9aaf53a test: image agent log filenames 2026-05-12 22:00:18 +01:00
Shakker
c0f2e20660 test: hook gateway event text 2026-05-12 21:59:43 +01:00
Shakker
ac3f06fd4f test: rebase update runner commands 2026-05-12 21:59:11 +01:00
Peter Steinberger
d1e53c9488 test: dedupe acp cli mock reads 2026-05-12 21:58:47 +01:00
Shakker
4fd15fcce2 test: ping health snapshot urls 2026-05-12 21:58:35 +01:00
y471823206
3b9796ce9b Handle generic provider internal errors (#49401)
Merged via squash.

Prepared head SHA: 492caa49a9
Co-authored-by: y471823206 <2311651347@qq.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-05-12 23:58:27 +03:00
Shakker
2ed2fbb55d test: service gateway doctor notes 2026-05-12 21:57:56 +01:00
Peter Steinberger
87d8545c97 test: dedupe media get-reply mock reads 2026-05-12 21:57:18 +01:00
Shakker
ed20e5e10c test: present command output text 2026-05-12 21:57:00 +01:00
Shakker
bf9fd2cfcd test: secret gateway warning text 2026-05-12 21:55:55 +01:00
Peter Steinberger
f3b5dc80f9 test: dedupe agent runner misc mock reads 2026-05-12 21:55:29 +01:00
Shakker
168bb4fac8 test: note wizard finalize calls 2026-05-12 21:55:01 +01:00
Shakker
71cdb6ab9a test: display cli output text 2026-05-12 21:54:12 +01:00
Shakker
016852186d test: observe config warning text 2026-05-12 21:53:17 +01:00
Shakker
9ff2627b7d test: squelch signal client logs 2026-05-12 21:52:38 +01:00
Shakker
c80152eadd test: canonicalise plugin discovery paths 2026-05-12 21:52:03 +01:00
Peter Steinberger
712ceabb40 test: dedupe agent runner memory mock reads 2026-05-12 21:51:44 +01:00
Shakker
559a744594 test: offer slack monitor text 2026-05-12 21:50:13 +01:00
Shakker
cee32280c6 test: weave matrix message assertions 2026-05-12 21:49:38 +01:00
Peter Steinberger
8792341cf6 test: dedupe trigger handling mock reads 2026-05-12 21:49:26 +01:00
Shakker
9456cc850a test: signal plugin warning text 2026-05-12 21:48:49 +01:00
Shakker
8d5623acc8 test: search tui no matches output 2026-05-12 21:48:07 +01:00
Shakker
f7646f9fde test: shutter browser tab cleanup urls 2026-05-12 21:47:37 +01:00
Peter Steinberger
98ca0858f4 test: dedupe web guarded fetch mock reads 2026-05-12 21:47:12 +01:00
Shakker
f8ceffde7c test: watch memory path assertions 2026-05-12 21:46:57 +01:00
Shakker
9656cd365b test: erase discord progress labels 2026-05-12 21:46:17 +01:00
Shakker
c716a30a58 test: block discord picker nav ids 2026-05-12 21:45:49 +01:00
Peter Steinberger
1fe4e9a8f0 test: dedupe video tool mock reads 2026-05-12 21:45:39 +01:00
Shakker
ad882f681d test: hush discord provider logs 2026-05-12 21:45:04 +01:00
Shakker
5396510370 test: point media wav argument 2026-05-12 21:43:55 +01:00
Peter Steinberger
9be1be8f1e test: dedupe sessions send a2a mock reads 2026-05-12 21:43:49 +01:00
Shakker
693c775a7f test: tag provider unit assertions 2026-05-12 21:42:48 +01:00
Peter Steinberger
1725b4ae49 test: dedupe workspace skills warning mock reads 2026-05-12 21:42:02 +01:00
Shakker
40b3236415 test: probe qa lab message snapshots 2026-05-12 21:41:42 +01:00
Shakker
8930897220 test: fasten active memory log lines 2026-05-12 21:40:48 +01:00
Kevin Lin
233d65f09d docs: split plugin docs navigation
Split plugin docs navigation into reader-intent groups.
2026-05-12 13:40:12 -07:00
Peter Steinberger
d71a2427c0 test: dedupe skills install command mock reads 2026-05-12 21:40:00 +01:00
Shakker
05c83c7bd4 test: steady whatsapp status assertions 2026-05-12 21:38:32 +01:00
Peter Steinberger
22f6be52ee test: dedupe provider transport policy mock reads 2026-05-12 21:38:21 +01:00
Shakker
6890ef4952 test: reserve telegram fallback assertions 2026-05-12 21:37:25 +01:00
Peter Steinberger
4ef0d45a91 test: dedupe pi subscribe tool result mock reads 2026-05-12 21:36:45 +01:00
Shakker
2f306546ab test: cradle memory dreaming assertions 2026-05-12 21:36:21 +01:00
Shakker
22235e85de test: caption feishu streaming updates 2026-05-12 21:35:36 +01:00
Peter Steinberger
9cdb59ec4f test: dedupe pi message handler mock reads 2026-05-12 21:35:10 +01:00
Shakker
97a991d037 test: screen ollama setup request probes 2026-05-12 21:34:42 +01:00
Peter Steinberger
a330cba9f8 test: dedupe pi compaction log mock reads 2026-05-12 21:33:42 +01:00
Shakker
f0c016c212 test: dodge msteams graph shares 2026-05-12 21:32:50 +01:00
Shakker
b97d07683a test: heal matrix doctor changes 2026-05-12 21:32:17 +01:00
Peter Steinberger
05a2fed3b7 test: dedupe pi usage reporting mock reads 2026-05-12 21:32:14 +01:00
Shakker
c90635d023 test: vault dreaming repair archives 2026-05-12 21:31:40 +01:00
Shakker
2eba3dabb7 test: reject slack download image content 2026-05-12 21:31:03 +01:00
Peter Steinberger
188bbe92e5 test: dedupe pi failover warning mock reads 2026-05-12 21:30:50 +01:00
Shakker
178a50e017 test: triage telegram status issues 2026-05-12 21:30:11 +01:00
Shakker
70817ed5fa test: locate signal config issues 2026-05-12 21:29:39 +01:00
Peter Steinberger
5dd5dc3bcc test: dedupe embedded pi runner mock reads 2026-05-12 21:29:25 +01:00
Shakker
b5cb5fa711 test: score memory wiki lint codes 2026-05-12 21:28:56 +01:00
Shakker
c1bfc7b3de test: deny googlechat body reads 2026-05-12 21:28:20 +01:00
Shakker
a76bebd2e6 test: etch discord status patches 2026-05-12 21:27:50 +01:00
Peter Steinberger
95e9b87d69 test: dedupe pi lsp windows spawn mock reads 2026-05-12 21:27:30 +01:00
Shakker
5c56ac7efd test: advertise bonjour warning checks 2026-05-12 21:26:42 +01:00
Peter Steinberger
d286e16a37 test: dedupe browser plugin tools mock reads 2026-05-12 21:26:05 +01:00
Shakker
4cfbfc73e0 test: splice matrix notice bodies 2026-05-12 21:25:33 +01:00
Shakker
1b645b21fc test: joiner synology warning checks 2026-05-12 21:25:03 +01:00
Shakker
dbf5b213af test: mute telegram account warning scan 2026-05-12 21:24:26 +01:00
Peter Steinberger
4091be857d test: dedupe implicit provider discovery mock reads 2026-05-12 21:24:07 +01:00
Shakker
d20ba302f8 test: partition bundled entry prefixes 2026-05-12 21:23:47 +01:00
Kevin Lin
eba73e593a build(canvas): stop tracking a2ui bundle hash (#81141) 2026-05-12 13:23:12 -07:00
Shakker
fd8ba6ae63 test: survey slack message schema props 2026-05-12 21:22:27 +01:00
Peter Steinberger
8f4941fd12 test: dedupe model catalog visibility mock reads 2026-05-12 21:22:09 +01:00
Shakker
2b2d696f89 test: vet telegram markdown chunks 2026-05-12 21:21:46 +01:00
Shakker
7fa771b665 test: ground memory lancedb hook checks 2026-05-12 21:21:01 +01:00
Peter Steinberger
db529f7517 test: dedupe cli runner supervisor capture mock reads 2026-05-12 21:20:54 +01:00
Shakker
0659780b21 test: sift openai catalog ids 2026-05-12 21:19:44 +01:00
Peter Steinberger
b36b0de04e test: dedupe bash exec runtime mock reads 2026-05-12 21:19:36 +01:00
Shakker
b7afe26a54 test: surface plugin registry diagnostics 2026-05-12 21:18:39 +01:00
Peter Steinberger
f3a03e1870 test: dedupe acp spawn mock reads 2026-05-12 21:18:20 +01:00
Shakker
33e5f29d0a test: bar codex computer use setup calls 2026-05-12 21:17:56 +01:00
Shakker
97e44aca75 test: recount codex plugin refresh calls 2026-05-12 21:17:19 +01:00
Peter Steinberger
346cc29fc2 test: dedupe acp spawn parent stream mock reads 2026-05-12 21:16:41 +01:00
Shakker
650b145686 test: delineate acp spawn relay calls 2026-05-12 21:16:10 +01:00
Shakker
fed2b9f132 test: stipulate hermes migration warnings 2026-05-12 21:15:01 +01:00
Shakker
bebb36caa5 test: affirm codex native auth calls 2026-05-12 21:13:33 +01:00
Peter Steinberger
ad1947732d test: dedupe signal container fetch reads 2026-05-12 21:13:22 +01:00
Shakker
8cc5870b49 test: sharpen codex migration warnings 2026-05-12 21:12:27 +01:00
Peter Steinberger
4b81881700 test: dedupe qa channel inbound mock reads 2026-05-12 21:11:05 +01:00
Peter Steinberger
86bcd179a7 test: dedupe openai realtime keychain reads 2026-05-12 21:09:35 +01:00
Shakker
6c44a6b21f test: elide run main null guard 2026-05-12 21:07:14 +01:00
Peter Steinberger
2f33554ed4 test: dedupe mattermost slash log reads 2026-05-12 21:07:04 +01:00
Shakker
116282a2c0 test: summon sandbox docker create 2026-05-12 21:05:44 +01:00
Peter Steinberger
c299249b4f test: dedupe matrix media failure mock reads 2026-05-12 21:05:11 +01:00
Shakker
75001adc7e test: carry matrix chunk config 2026-05-12 21:04:17 +01:00
Peter Steinberger
fd75588190 test: dedupe matrix profile mock reads 2026-05-12 21:03:11 +01:00
Shakker
cd98df601c test: compel uninstall plan params 2026-05-12 21:02:16 +01:00
Kevin Lin
9ff5250792 fix(codex): gate migration on app readiness (#80815)
* fix(codex): gate migration on app readiness

* fix(codex): preserve source auth during migration

* fix(codex): isolate migration source app probes

* docs(codex): align migration readiness reasons

* docs(codex): remove stale auth-required source reason

* fix(codex): narrow native auth profile resolver input

* fix: clarify codex migration subscription gating

* refactor: simplify codex migration subscription gate

* fix: make codex app verification optional

* docs: clarify codex app inventory cache

* test: avoid map spread in migration test
2026-05-12 13:01:22 -07:00
Shakker
5c4a723f7c test: demand gateway agent payloads 2026-05-12 21:01:00 +01:00
Peter Steinberger
a1d7fb1273 test: dedupe lmstudio setup mock reads 2026-05-12 21:00:54 +01:00
Shakker
044b4175b3 test: winnow config validation issues 2026-05-12 20:59:14 +01:00
Peter Steinberger
2e45a8ff44 test: dedupe line webhook payload reads 2026-05-12 20:59:10 +01:00
Peter Steinberger
b499d8f60c test: dedupe gradium speech fetch reads 2026-05-12 20:57:38 +01:00
Shakker
a814173e74 test: lone plugin allow warning 2026-05-12 20:56:24 +01:00
Peter Steinberger
de235b96f0 test: dedupe feishu reaction mock reads 2026-05-12 20:55:42 +01:00
Shakker
9b9e73ad59 test: stack missing plugin warnings 2026-05-12 20:54:57 +01:00
Shakker
af20c89e83 test: weigh codex turn results 2026-05-12 20:53:50 +01:00
Peter Steinberger
bc26023b7e test: dedupe feishu comment mock reads 2026-05-12 20:53:45 +01:00
Shakker
3e425dde0d test: mine compaction branch messages 2026-05-12 20:52:19 +01:00
Peter Steinberger
eb46fa15ae test: dedupe feishu bot menu mock reads 2026-05-12 20:51:45 +01:00
Shakker
b428427108 test: carve overflow timeout payloads 2026-05-12 20:51:05 +01:00
Shakker
7c5b3283d6 test: supply codex auth profile store 2026-05-12 20:49:47 +01:00
Peter Steinberger
6a012282a4 test: dedupe discord monitor mock reads 2026-05-12 20:49:44 +01:00
Shakker
046d6fc0ae test: seek cron list log text 2026-05-12 20:48:33 +01:00
Shakker
8f55f0d38c test: collect status reaction emojis 2026-05-12 20:47:45 +01:00
Peter Steinberger
9b52daf595 test: dedupe diffs browser mock reads 2026-05-12 20:47:25 +01:00
Shakker
3a37bb717c test: account plugin repair outcomes 2026-05-12 20:46:39 +01:00
Shakker
c5a227163e test: report plugin repair records 2026-05-12 20:44:51 +01:00
Peter Steinberger
c3399806b3 test: dedupe heartbeat ghost reminder mock reads 2026-05-12 20:44:43 +01:00
Shakker
8423884a51 test: negate realtime response events 2026-05-12 20:43:33 +01:00
Shakker
ee40ce6d4b test: ledger session runtime options 2026-05-12 20:42:28 +01:00
Peter Steinberger
906dd432cf test: dedupe exec approval mock reads 2026-05-12 20:41:37 +01:00
Shakker
a455edc2b1 test: stamp task registry exact records 2026-05-12 20:40:52 +01:00
Peter Steinberger
652a56fc74 test: dedupe startup migration log reads 2026-05-12 20:39:27 +01:00
Shakker
ed4c287bf3 test: clinch forced realtime barge-in 2026-05-12 20:38:21 +01:00
Shakker
5768d55db8 test: trail realtime barge-in events 2026-05-12 20:37:25 +01:00
Peter Steinberger
3f26f3ddfd test: dedupe gateway update mock reads 2026-05-12 20:36:55 +01:00
Shakker
0452ad6d1a test: plumb doctor peer link repair call 2026-05-12 20:36:26 +01:00
Shakker
9623bb0af7 test: peg idle timeout stream args 2026-05-12 20:35:17 +01:00
Shakker
b60ae89aa4 test: settle plugin repair noops 2026-05-12 20:33:52 +01:00
Peter Steinberger
d18bbfe7ae test: dedupe gateway config reload mock reads 2026-05-12 20:33:34 +01:00
Shakker
ea7f74ffc9 test: idle disabled plugin repair results 2026-05-12 20:31:00 +01:00
Peter Steinberger
1b9603e7c1 test: dedupe whatsapp session mock reads 2026-05-12 20:30:06 +01:00
Shakker
ba54c0e060 test: unlock synology schema passthrough 2026-05-12 20:29:12 +01:00
Shakker
81fe17c4a6 test: regularize codex collab statuses 2026-05-12 20:27:32 +01:00
Shakker
a5aadea756 test: persist codex collab terminal message 2026-05-12 20:26:56 +01:00
Peter Steinberger
1993b2a40c test: dedupe openrouter media mock reads 2026-05-12 20:26:40 +01:00
Shakker
354bb11702 test: originate codex collab task payloads 2026-05-12 20:26:01 +01:00
Shakker
108507f6a2 test: terminate codex subagent statuses 2026-05-12 20:24:55 +01:00
Shakker
5f68002509 test: shadow codex subagent task payloads 2026-05-12 20:24:10 +01:00
Shakker
f0e381d6e9 test: transmit context ingest identity 2026-05-12 20:22:57 +01:00
Shakker
886e9223c9 test: rotate compaction context rows 2026-05-12 20:21:53 +01:00
Shakker
dacb8cf08a test: profile openrouter media descriptor 2026-05-12 20:20:09 +01:00
Shakker
f58515431e test: draft browser think command 2026-05-12 20:19:18 +01:00
Shakker
58bb7a50ef test: declare openrouter stt request 2026-05-12 20:18:19 +01:00
Peter Steinberger
ce085e5fa8 test: dedupe gateway client mock reads 2026-05-12 20:17:49 +01:00
Shakker
d8a2d1aaa9 test: relay gateway bridge payloads 2026-05-12 20:17:17 +01:00
Shakker
0ad0ff32fe test: pipe googlechat webhook limits 2026-05-12 20:16:11 +01:00
Shakker
0d9c38ffdf test: measure msteams upload options 2026-05-12 20:15:09 +01:00
Shakker
f6ee35fc86 test: decode tool card raw payload 2026-05-12 20:13:51 +01:00
Shakker
2eb302db1f test: imprint openrouter stt payloads 2026-05-12 20:13:10 +01:00
Peter Steinberger
82882ddf1a test: dedupe gateway boot mock reads 2026-05-12 20:12:52 +01:00
Shakker
b3ea131d51 test: box codex activation diagnostics 2026-05-12 20:11:54 +01:00
Shakker
975fd2a038 test: collate feishu doc descendants 2026-05-12 20:11:13 +01:00
Shakker
288eee88b1 test: sieve usage cache card 2026-05-12 20:10:20 +01:00
Peter Steinberger
acef9920df test: dedupe tasks command log reads 2026-05-12 20:09:55 +01:00
Shakker
5782d3441e test: clamp googlemeet cli registrations 2026-05-12 20:09:38 +01:00
Shakker
d14fa499a6 test: marshal gateway chat responses 2026-05-12 20:08:19 +01:00
Peter Steinberger
d356f84801 test: dedupe models list registry reads 2026-05-12 20:05:56 +01:00
Shakker
2ff3514037 test: portray channel status rows 2026-05-12 20:04:47 +01:00
Shakker
17dd725150 test: broadcast node pairing payloads 2026-05-12 20:03:29 +01:00
Peter Steinberger
513c717cd3 test: dedupe gateway status mock reads 2026-05-12 20:02:55 +01:00
Shakker
d05624aa3c test: assay exec command analysis fields 2026-05-12 20:02:02 +01:00
Shakker
d3f959a83a test: verbalize partial reply chunks 2026-05-12 20:01:19 +01:00
Peter Steinberger
91ae344c19 test: dedupe channels add mock reads 2026-05-12 20:00:04 +01:00
Shakker
383485e785 test: articulate node pairing requests 2026-05-12 19:59:47 +01:00
Shakker
b60f785777 test: certify bootstrap approval status 2026-05-12 19:58:41 +01:00
Shakker
4071fc6288 test: excise tool result details exactly 2026-05-12 19:57:57 +01:00
Peter Steinberger
0dbe2e9e12 test: dedupe nodes approval timeout mock reads 2026-05-12 19:57:38 +01:00
Shakker
c9d28775ec test: reprise optional install retry 2026-05-12 19:56:38 +01:00
Shakker
a0a91f8028 test: unwrap cmd transport argv 2026-05-12 19:55:54 +01:00
Shakker
d7f7a71981 test: purify health probe snapshots 2026-05-12 19:55:08 +01:00
Peter Steinberger
c964da8d58 test: dedupe daemon install mock reads 2026-05-12 19:54:55 +01:00
Shakker
129b147871 test: qualify model auth checker options 2026-05-12 19:54:32 +01:00
Shakker
b304155f66 test: confine respawn bridge options 2026-05-12 19:53:38 +01:00
Shakker
94c46c606a test: reflect side alias events 2026-05-12 19:52:59 +01:00
Peter Steinberger
a3534aedae test: dedupe channel auth mock reads 2026-05-12 19:52:39 +01:00
Shakker
69ea7b115d test: encase discovery log calls 2026-05-12 19:52:08 +01:00
Shakker
bb692899ab test: linearize launchd command calls 2026-05-12 19:51:23 +01:00
Shakker
f634799b45 test: capsize tool location traversal 2026-05-12 19:50:35 +01:00
Shakker
a263c4c58f test: ordinalize ledger replay chunks 2026-05-12 19:49:42 +01:00
Peter Steinberger
57db08504d test: dedupe sessions spawn hook reads 2026-05-12 19:49:17 +01:00
Shakker
e523183e46 test: schematize session mode requests 2026-05-12 19:49:00 +01:00
Shakker
492336414d test: thread media-only inbound context 2026-05-12 19:47:45 +01:00
Shakker
fdcd83da08 test: inscribe command config writes 2026-05-12 19:46:59 +01:00
Peter Steinberger
44f2cc71d5 test: dedupe subagent steer restart mock reads 2026-05-12 19:46:05 +01:00
Shakker
24e8a28057 test: forward daemon probe timeouts exactly 2026-05-12 19:45:50 +01:00
Shakker
b7cd7cb914 test: pinpoint session target discovery 2026-05-12 19:45:11 +01:00
Shakker
1e4155eb2e test: truncate acp deliveries exactly 2026-05-12 19:44:32 +01:00
Peter Steinberger
1f8c0dfc64 test: dedupe subagent orphan recovery mock reads 2026-05-12 19:44:14 +01:00
Shakker
061ef36397 test: disallow elevated allowlist failures 2026-05-12 19:43:58 +01:00
Shakker
008a837e5e test: retrieve cron jobs exactly 2026-05-12 19:42:39 +01:00
Peter Steinberger
85dbd478a6 test: dedupe subagent announce mock reads 2026-05-12 19:42:18 +01:00
Shakker
8e5e326de2 test: flag suppressed model refs 2026-05-12 19:41:50 +01:00
Peter Steinberger
71aec03dd9 test: dedupe ssh sandbox mock reads 2026-05-12 19:39:52 +01:00
Shakker
fa8965a4de test: singularize union validation issues 2026-05-12 19:39:00 +01:00
Peter Steinberger
ff64d8dde7 test: dedupe capability cli mock reads 2026-05-12 19:37:37 +01:00
Shakker
7901e7a454 test: enact launchd stop calls 2026-05-12 19:37:01 +01:00
Shakker
c5dd54431d test: script scheduled restart calls 2026-05-12 19:35:25 +01:00
Peter Steinberger
48e7f24565 test: dedupe cron gateway mock reads 2026-05-12 19:35:01 +01:00
Shakker
ebaa674bdc test: purge stale proof labels 2026-05-12 19:33:02 +01:00
Peter Steinberger
973e978aee test: dedupe session repair log reads 2026-05-12 19:32:49 +01:00
Shakker
b32e870e38 test: revisit active reaction calls 2026-05-12 19:31:49 +01:00
Peter Steinberger
2416fdece9 test: dedupe model diagnostic hook reads 2026-05-12 19:30:55 +01:00
Shakker
97207192b5 test: timeline status reaction cleanup 2026-05-12 19:30:32 +01:00
Shakker
50dd00ade6 test: chronicle turn record failure 2026-05-12 19:29:14 +01:00
Peter Steinberger
6398836079 test: dedupe embedded subscribe final filter reads 2026-05-12 19:29:04 +01:00
Shakker
d6bde4994c test: wrap blockquote style ir 2026-05-12 19:27:59 +01:00
Shakker
8483659477 test: slot ci dependency shard 2026-05-12 19:27:03 +01:00
Shakker
c54a3e6f78 test: rank boundary check guards 2026-05-12 19:26:26 +01:00
Peter Steinberger
8cd6e8ee42 test: dedupe embedded subscribe block reply reads 2026-05-12 19:26:17 +01:00
Shakker
14cd8193db test: position prerelease liveish check 2026-05-12 19:24:55 +01:00
Peter Steinberger
b5dc9a578b test: dedupe exec host followup mock reads 2026-05-12 19:24:11 +01:00
Shakker
e75c63fb08 test: furnish status json payload 2026-05-12 19:23:49 +01:00
Shakker
8a8cb1b8d5 test: concretize video override normalization 2026-05-12 19:22:39 +01:00
Shakker
f2ce07cd67 test: serialize config tuple baseline 2026-05-12 19:21:58 +01:00
Peter Steinberger
0ab328c915 test: dedupe exec approval mock reads 2026-05-12 19:21:15 +01:00
Shakker
ceaa5c08d6 test: crystallize blockquote spacing 2026-05-12 19:20:37 +01:00
Shakker
6dbe3b187c test: delimit command span formatting 2026-05-12 19:19:30 +01:00
Shakker
6e79a06d50 test: encompass beta verifier args 2026-05-12 19:18:40 +01:00
Peter Steinberger
ef8e6650ae test: dedupe anthropic transport mock reads 2026-05-12 19:17:27 +01:00
Shakker
7fd1f5c73c test: omit opus build allowlist 2026-05-12 19:17:08 +01:00
Shakker
52cbb7de33 test: literalize media fetch redaction 2026-05-12 19:16:12 +01:00
Shakker
ff580f2fb6 test: bracket file context output 2026-05-12 19:14:57 +01:00
Peter Steinberger
fc28f9376e test: dedupe compaction safeguard mock reads 2026-05-12 19:14:36 +01:00
Shakker
364212c6c0 test: summarize skill frontmatter exactly 2026-05-12 19:13:58 +01:00
Shakker
0d0832c24d test: compare provider index previews 2026-05-12 19:11:32 +01:00
Shakker
5ce8410041 test: disclose custom acp backend hint 2026-05-12 19:11:32 +01:00
Shakker
1f4cf100e8 test: compose waiting status message 2026-05-12 19:11:32 +01:00
Peter Steinberger
66421d413f test: dedupe maintenance cli mock reads 2026-05-12 19:10:46 +01:00
Shakker
b5706597c1 test: reproduce memory ingest page 2026-05-12 19:09:31 +01:00
Shakker
23725bf11f test: sequence zai model ids 2026-05-12 19:09:31 +01:00
Peter Steinberger
d548adb610 test: tighten channel catalog mock assertions 2026-05-12 19:08:47 +01:00
Shakker
ce6ba9a263 test: warn on shared agent dirs 2026-05-12 19:06:20 +01:00
Shakker
c22ea053d1 test: merge tuple doc metadata 2026-05-12 19:05:55 +01:00
Shakker
99a976e527 test: demonstrate raw redaction output 2026-05-12 19:05:16 +01:00
Shakker
796126912d test: scrub auth state warning 2026-05-12 19:04:30 +01:00
Shakker
50420d9e8f test: map runtime channel capabilities 2026-05-12 19:04:30 +01:00
Peter Steinberger
63a44ed310 test: dedupe system cli mock reads 2026-05-12 19:04:19 +01:00
Shakker
1bd0455072 test: index shell env expected keys 2026-05-12 19:02:27 +01:00
Shakker
ea4c365a4c test: phrase deferred followup tools 2026-05-12 19:02:27 +01:00
Shakker
493b2c918c test: catalog core tool profiles 2026-05-12 19:02:27 +01:00
Peter Steinberger
06938c9117 test: dedupe tool context guard mock reads 2026-05-12 19:01:54 +01:00
Shakker
e0841015e3 test: constrain typing mode issue paths 2026-05-12 19:00:01 +01:00
Shakker
9d9816b307 test: read qa workspace marker 2026-05-12 19:00:01 +01:00
Shakker
8ba6d3e207 test: show openai default allowlist 2026-05-12 19:00:01 +01:00
Shakker
8d71a42294 test: echo optional channel setup hint 2026-05-12 19:00:01 +01:00
Peter Steinberger
ad3ce47224 test: dedupe live model switch mock reads 2026-05-12 18:58:04 +01:00
Shakker
806d1f3cca test: identify logging size issue 2026-05-12 18:57:20 +01:00
Shakker
5497371ff0 test: pin e2e vitest setup 2026-05-12 18:57:04 +01:00
Shakker
ae571575f8 test: pin live vitest setup 2026-05-12 18:56:52 +01:00
Shakker
6abe2526d0 test: preserve discord gateway fallback log 2026-05-12 18:56:09 +01:00
Shakker
174e7ddffd test: name google setup entries 2026-05-12 18:56:08 +01:00
Shakker
6e562f5163 test: order telegram updates 2026-05-12 18:56:08 +01:00
Shakker
eecbc596b3 test: detail audit surface summary 2026-05-12 18:56:08 +01:00
Peter Steinberger
3d70d037aa test: dedupe embedded subscribe lifecycle mock reads 2026-05-12 18:55:45 +01:00
Shakker
ac9cddf353 test: print cli parse errors 2026-05-12 18:54:06 +01:00
Shakker
133fe11618 test: arrange cli failure lines 2026-05-12 18:54:06 +01:00
Shakker
c34a982f87 test: resolve docs links exactly 2026-05-12 18:54:06 +01:00
Peter Steinberger
c2bbb73e18 test: dedupe setup registry mock reads 2026-05-12 18:53:38 +01:00
Shakker
29a087be5a test: transcribe sherpa usage output 2026-05-12 18:52:29 +01:00
Shakker
a231036436 test: mark table block ir text 2026-05-12 18:52:14 +01:00
Shakker
7194be8fb8 test: capture docker enoent guidance 2026-05-12 18:51:58 +01:00
Shakker
3a2220f0a5 test: enumerate persisted auth channels 2026-05-12 18:51:23 +01:00
Shakker
8554e851af test: list pdf tool registration 2026-05-12 18:51:23 +01:00
Shakker
068bbb474b test: spell qwen doctor hint 2026-05-12 18:51:23 +01:00
Peter Steinberger
5d68e645ce test: dedupe overflow compaction mock reads 2026-05-12 18:51:19 +01:00
Shakker
3eeab53b80 test: state discord voice contract 2026-05-12 18:50:02 +01:00
Shakker
61903a2f08 test: outline qa markdown report 2026-05-12 18:49:48 +01:00
Shakker
e7c1d10f1d test: seal matrix logger redaction 2026-05-12 18:49:37 +01:00
Shakker
2bd58b5cfa test: distinguish allowed value summaries 2026-05-12 18:48:37 +01:00
Shakker
2e7cf45ed2 test: mirror btw inline rows 2026-05-12 18:48:37 +01:00
Shakker
83bf5ce4f3 test: require subagent wait guidance 2026-05-12 18:48:37 +01:00
Peter Steinberger
6861d8a6d7 test: dedupe subagent lifecycle mock reads 2026-05-12 18:48:06 +01:00
Shakker
542ee2f77b test: fix browser tab error guidance 2026-05-12 18:47:21 +01:00
Shakker
4b4adc767a test: specify markdown table fallback 2026-05-12 18:47:21 +01:00
Shakker
cc9197e51e test: nail daemon runtime status text 2026-05-12 18:47:20 +01:00
Peter Steinberger
4b41e591fe test: dedupe directory cli mock reads 2026-05-12 18:46:03 +01:00
Shakker
f054295e48 test: bind matrix mention html output 2026-05-12 18:45:40 +01:00
brokemac79
58700db5ff fix(gateway): suppress heartbeat tool events in webchat (#80378) 2026-05-12 10:45:16 -07:00
Shakker
45cf560f4e test: tighten matrix markdown html basics 2026-05-12 18:44:47 +01:00
Shakker
b2f6e06e13 test: verify sidebar status label 2026-05-12 18:43:42 +01:00
Peter Steinberger
4d74353064 test: dedupe auth profile runtime mock reads 2026-05-12 18:43:28 +01:00
Shakker
2a95f2cd48 test: assert markdown fallback structure 2026-05-12 18:42:48 +01:00
Peter Steinberger
052724416b test: dedupe btw mock reads 2026-05-12 18:40:39 +01:00
Shakker
864eb07d44 test: lock browser slash imports 2026-05-12 18:39:39 +01:00
Shakker
e2f512ce49 test: localize copy code markup 2026-05-12 18:38:01 +01:00
Shakker
dd75205d9f test: encode remaining www autolinks 2026-05-12 18:37:02 +01:00
Shakker
1611539b03 test: freeze unsafe markdown links 2026-05-12 18:36:03 +01:00
Peter Steinberger
4339a18657 test: dedupe attempt execution mock reads 2026-05-12 18:35:56 +01:00
Shakker
bd3d1fbb58 test: define markdown structural blocks 2026-05-12 18:34:21 +01:00
Shakker
62fff1f738 test: specify basic markdown rendering 2026-05-12 18:33:32 +01:00
Peter Steinberger
3c8bf48bb5 test: dedupe gateway usage mock reads 2026-05-12 18:33:17 +01:00
Shakker
ffc7d88473 test: codify markdown code blocks 2026-05-12 18:32:23 +01:00
Shakker
ad4bc5f80d test: capture unsafe markdown sanitizing 2026-05-12 18:31:00 +01:00
Peter Steinberger
7d9232a9a9 test: dedupe codex command mock reads 2026-05-12 18:30:47 +01:00
Shakker
77233877ac test: describe markdown image output 2026-05-12 18:29:43 +01:00
Shakker
fafe11bc67 test: escape task details exactly 2026-05-12 18:29:01 +01:00
Shakker
c60308239f test: detail task list markdown 2026-05-12 18:28:02 +01:00
Peter Steinberger
b5f2e4b5bb test: complete auto reply mock call helpers 2026-05-12 18:27:15 +01:00
Shakker
a043e7b7b3 test: spell escaped html output 2026-05-12 18:26:45 +01:00
Shakker
119dd0ee57 test: pin protocol CJK link rendering 2026-05-12 18:25:26 +01:00
Shakker
7d7d5809ab test: leave plain domains unlinked 2026-05-12 18:24:01 +01:00
clawsweeper[bot]
81cd5028a5 ci: add missing extension and channel labels to labeler.yml (#81095)
Summary:
- This PR adds `.github/labeler.yml` changed-file rules for 22 bundled plugin directories that currently have no dedicated labeler entry.
- Reproducibility: not applicable. as a CI metadata PR rather than a product bug. The gap is source-verifiable ...  with current-main `.github/labeler.yml`, which shows the added plugin paths exist and are unlabeled today.

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

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

Prepared head SHA: eef42948d3
Review: https://github.com/openclaw/openclaw/pull/81095#issuecomment-4432997258

Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: bing <33149547+bing0901@users.noreply.github.com>
2026-05-12 17:23:35 +00:00
Peter Steinberger
cab7c4536e test: avoid mutating grouped render params 2026-05-12 18:23:28 +01:00
Peter Steinberger
bce0e9e0be test: dedupe cli runner spawn mock reads 2026-05-12 18:23:28 +01:00
Shakker
8536340e89 test: fence www autolink boundaries 2026-05-12 18:23:09 +01:00
Shakker
1a6b1aeb9d test: preserve quoted www autolinks 2026-05-12 18:22:06 +01:00
Shakker
6ddc2b5f49 test: fix www autolink suffix output 2026-05-12 18:21:14 +01:00
Shakker
8f10a86842 test: render basic www autolinks exactly 2026-05-12 18:20:02 +01:00
Shakker
d267880017 test: anchor slash command refreshes 2026-05-12 18:18:56 +01:00
Peter Steinberger
cae1263198 test: dedupe feishu reply dispatcher mock reads 2026-05-12 18:18:26 +01:00
Shakker
9fa1d9bf36 test: parse assistant media metadata urls 2026-05-12 18:17:38 +01:00
Shakker
5cefebd352 test: trace stored attachment previews 2026-05-12 18:16:54 +01:00
Shakker
038a968e36 test: color context notice exactly 2026-05-12 18:15:57 +01:00
Shakker
df6bc365bf test: quote websocket constructor errors 2026-05-12 18:15:06 +01:00
Shakker
94dc1e32c2 test: name update mismatch banner 2026-05-12 18:14:08 +01:00
Peter Steinberger
797ce4c05c test: dedupe slack slash mock reads 2026-05-12 18:13:53 +01:00
Shakker
d161053caa test: define dreaming error states 2026-05-12 18:13:24 +01:00
Shakker
d08a407610 test: state agent tool errors 2026-05-12 18:12:47 +01:00
Shakker
b881243dc6 test: spell out chat controller errors 2026-05-12 18:12:06 +01:00
Shakker
1d31583e0d test: pin gateway close messages 2026-05-12 18:11:12 +01:00
Shakker
49029cbdcc test: specify chat attachment transcript 2026-05-12 18:10:38 +01:00
Peter Steinberger
1e3a7548d9 test: dedupe update cli mock reads 2026-05-12 18:10:15 +01:00
Shakker
46ca9cf9c4 test: trim mismatched thinking defaults 2026-05-12 18:08:31 +01:00
Shakker
7b4fd3d67a test: alias slash commands exactly 2026-05-12 18:07:06 +01:00
Peter Steinberger
0f390fc820 test: dedupe telegram bot mock reads 2026-05-12 18:06:03 +01:00
Shakker
362ebc9c4f test: export chat markdown exactly 2026-05-12 18:04:50 +01:00
Shakker
5d9f16a093 test: tally performance event buffer 2026-05-12 18:03:41 +01:00
Shakker
378fff4330 test: nest session option labels 2026-05-12 18:02:52 +01:00
Peter Steinberger
78e9717d9b test: dedupe whatsapp send mock reads 2026-05-12 18:02:40 +01:00
Shakker
a390424442 test: sign gateway auth payloads 2026-05-12 18:01:27 +01:00
Peter Steinberger
c3c4510942 test: dedupe agent event mock reads 2026-05-12 18:00:04 +01:00
Shakker
cb0de89ef4 test: prune stored gateway scopes 2026-05-12 17:59:05 +01:00
Shakker
63c0f2894e test: chain channel save recovery 2026-05-12 17:58:08 +01:00
Shakker
cd34b0ce54 test: line model picker options 2026-05-12 17:57:23 +01:00
Peter Steinberger
df89ad90d8 test: dedupe voice call mock reads 2026-05-12 17:57:15 +01:00
Shakker
e5e1e7b489 test: derive custom theme colors 2026-05-12 17:56:03 +01:00
Shakker
35af092508 test: total usage helper tools 2026-05-12 17:55:18 +01:00
Shakker
a407eba98c test: engrave tool card payloads 2026-05-12 17:54:20 +01:00
Peter Steinberger
c4b106bcfe test: dedupe node wake mock calls 2026-05-12 17:53:56 +01:00
Shakker
fe46705640 test: zero config form unsupported paths 2026-05-12 17:53:04 +01:00
Shakker
8829fcaaf0 test: print tool helper previews 2026-05-12 17:52:07 +01:00
Shakker
44b7f5bceb test: table navigation metadata 2026-05-12 17:51:08 +01:00
Shakker
10f166a0fd test: sketch dreaming scene rows 2026-05-12 17:50:07 +01:00
Galin Iliev
4b28312bd8 fix(azure):Drain split provider stream frames (#80927)
Merged via squash.

Prepared head SHA: 03a7e1fec3
Co-authored-by: galiniliev <5711535+galiniliev@users.noreply.github.com>
Co-authored-by: galiniliev <5711535+galiniliev@users.noreply.github.com>
Reviewed-by: @galiniliev
2026-05-12 09:49:51 -07:00
Shakker
8d823a98c0 test: summarize peak error rows 2026-05-12 17:48:32 +01:00
Peter Steinberger
103664dd23 test: dedupe control ui response reads 2026-05-12 17:48:27 +01:00
pashpashpash
36b9da5c91 Keep Codex media tools backed by auth profiles (#81059)
* fix(codex): pass auth profiles to dynamic tools

* fix: bump protobufjs past advisory range
2026-05-13 01:46:21 +09:00
Shakker
6053532bd2 test: checkpoint sessions compaction text 2026-05-12 17:45:50 +01:00
Peter Steinberger
43316c2909 test: dedupe qa matrix mock calls 2026-05-12 17:44:26 +01:00
Peter Steinberger
6a5290e49e test: dedupe migrate mock calls 2026-05-12 17:38:47 +01:00
Shakker
65b608388a test: pare voice option exclusions 2026-05-12 17:37:42 +01:00
Shakker
687f4be9ec test: stage dreaming scene buttons 2026-05-12 17:36:55 +01:00
Shakker
9cbfc843a1 test: recite dream diary prose 2026-05-12 17:36:14 +01:00
Shakker
230be4e91c test: cleanse login raw errors 2026-05-12 17:35:05 +01:00
Peter Steinberger
6a099e5971 test: dedupe model picker mock calls 2026-05-12 17:34:46 +01:00
Shakker
07f68b1b4d test: diagnose login connection guidance 2026-05-12 17:33:57 +01:00
Shakker
63563713c6 test: pair login context guidance 2026-05-12 17:33:21 +01:00
Shakker
505aa38079 test: prescribe login auth guidance 2026-05-12 17:32:33 +01:00
Shakker
fe04523211 test: option session override selects 2026-05-12 17:31:32 +01:00
Shakker
5f081c8cd5 test: column sessions table 2026-05-12 17:30:39 +01:00
Peter Steinberger
05fabfbc9c test: dedupe google meet mock calls 2026-05-12 17:29:52 +01:00
Shakker
b98e97210b test: unhide raw config body 2026-05-12 17:29:15 +01:00
Shakker
bfc5d99828 test: flatten malformed config values 2026-05-12 17:28:45 +01:00
Shakker
ddfa97eba2 test: arrange config tabs 2026-05-12 17:27:32 +01:00
Shakker
2cb8a0c4fb test: retain cron advanced labels 2026-05-12 17:26:49 +01:00
Shakker
d7dfd4a8b2 test: navigate cron run links 2026-05-12 17:26:02 +01:00
Peter Steinberger
a8bc83edf4 test: dedupe diagnostics otel mock calls 2026-05-12 17:25:57 +01:00
Shakker
3aeec2e4a4 test: wire cron suggestion lists 2026-05-12 17:25:00 +01:00
Shakker
5681cfd839 test: distinguish cron delivery options 2026-05-12 17:24:14 +01:00
Shakker
641eaeecf3 test: gather localized selectors 2026-05-12 17:23:27 +01:00
Shakker
706b9a2ef7 test: announce slash option exactly 2026-05-12 17:22:34 +01:00
Shakker
637afd6a11 test: sequence thinking option labels 2026-05-12 17:21:06 +01:00
Shakker
a728e6aaf6 test: expect config section titles 2026-05-12 17:19:26 +01:00
Peter Steinberger
6cfb532afd test: dedupe feishu drive mock calls 2026-05-12 17:19:17 +01:00
Shakker
0c5e33480e test: honor wildcard raw redaction 2026-05-12 17:18:20 +01:00
Shakker
3589827635 test: disclose raw redaction state 2026-05-12 17:17:48 +01:00
Shakker
c630aa3488 test: prove config reveal reset 2026-05-12 17:17:08 +01:00
Shakker
16f2b22b33 test: mask config raw secrets 2026-05-12 17:14:49 +01:00
Shakker
b5f8e4c18a test: notice raw mode lockout 2026-05-12 17:13:34 +01:00
Peter Steinberger
72d9ea3b76 test: dedupe matrix send mock calls 2026-05-12 17:13:20 +01:00
Shakker
628eeda84a test: limit scoped config labels 2026-05-12 17:12:41 +01:00
Shakker
ae773272ac test: clear config diff panel 2026-05-12 17:12:00 +01:00
Shakker
0918f3823b test: open config diff rows 2026-05-12 17:11:07 +01:00
Shakker
1f1a5c205c test: quote theme importer hints 2026-05-12 17:09:59 +01:00
Shakker
adb8d553e4 test: mark imported theme metadata 2026-05-12 17:09:19 +01:00
Peter Steinberger
3598938458 test: dedupe openresponses mock calls 2026-05-12 17:09:07 +01:00
Shakker
c5574eb796 test: redact secret ref input 2026-05-12 17:08:23 +01:00
Shakker
c967410bed test: unpack device pairing rows 2026-05-12 17:07:34 +01:00
Shakker
87a4da89e3 test: badge agent tool provenance 2026-05-12 17:05:43 +01:00
Shakker
9be8d38f95 test: freeze exec approval expiry 2026-05-12 17:04:46 +01:00
Peter Steinberger
c0e287f3c1 test: dedupe embedded attempt mock calls 2026-05-12 17:04:11 +01:00
Shakker
e15bb302e0 test: translate exec approval chrome 2026-05-12 17:03:22 +01:00
Shakker
4fe36dc608 test: inventory cron filter options 2026-05-12 17:02:20 +01:00
Shakker
9808fd6802 test: localize talk button title 2026-05-12 17:01:21 +01:00
Shakker
a230aefb40 test: itemize login failure panel 2026-05-12 17:00:24 +01:00
Peter Steinberger
8c6dd5bddc test: dedupe outbound delivery mock calls 2026-05-12 16:59:51 +01:00
Shakker
9076ce0a7d test: outline cron advanced controls 2026-05-12 16:56:32 +01:00
Shakker
24fa9ba6a4 test: expose cron edit controls 2026-05-12 16:55:20 +01:00
Shakker
a5557d1fb5 test: index cron validation status 2026-05-12 16:54:47 +01:00
Peter Steinberger
4f1bee9f8b test: dedupe telegram send mock calls 2026-05-12 16:54:31 +01:00
Ayaan Zaidi
4272ce1597 chore(voice-call): note Telnyx realtime PR (#81024) (thanks @dynamite-bud) 2026-05-12 21:23:50 +05:30
Ayaan Zaidi
665c29d4dc fix(voice-call): bind Telnyx realtime streams to issued calls 2026-05-12 21:23:50 +05:30
Rudra
148e5467b5 fix: align Telnyx stream lifecycle parsing with carrier docs
Two parsing bugs caught by Codex review on the Telnyx Media Streaming
PR:

Lifecycle webhook event names had a stray `call.` prefix that never
matched Telnyx's documented event types. Telnyx surfaces stream
lifecycle as `streaming.started` and `streaming.stopped` (no prefix);
stream errors arrive as `{event:"error"}` JSON frames over the
WebSocket, not as carrier webhooks. Drop the bogus
`call.streaming.failed` case from the webhook parser and add a new
`error` frame kind to the StreamFrameAdapter union so the realtime
handler can log failures instead of silently dropping them.

Telnyx WebSocket frames carry `stream_id` at the top level of the
envelope and `call_control_id` inside the `start` object; the
Telnyx adapter was reading `start.stream_id` (always undefined) and
defaulting `providerCallId` to the constructor-supplied value
regardless of what the carrier sent. Read both fields from the
documented locations and fall back to the constructor providerCallId
only when the carrier frame omits them.

Tests updated to reflect the carrier-documented frame shapes; new
fixture covers `{event:"error"}` round-trip through the adapter.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 21:23:50 +05:30
Rudra
b28e3b378e test: cover Telnyx Media Streaming for voice-call realtime
Adds tests across the touched surface: StreamFrameAdapter for both
Twilio (with streamSid) and Telnyx (without), the generalized
RealtimeAudioPacer carrying both envelopes, Telnyx provider
dial-time and answer-action streaming params with the
call.streaming.failed -> call.error mapping, manager
streamSessionIssuer wiring for Telnyx outbound, and the widened
realtime + telnyx config gate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 21:23:50 +05:30
Rudra
bb1b075118 feat: add Telnyx Media Streaming for voice-call realtime
Wires bidirectional PCMU WebSocket audio for Telnyx so realtime
providers (OpenAI Realtime, etc.) can drive Telnyx calls the same
way they drive Twilio. Telnyx attaches Media Streaming at dial
time and answer-action time per the documented canonical patterns
(no actions/streaming_start call needed).

New StreamFrameAdapter abstraction owns provider-shaped frame
parsing and outbound serialization, so realtime-handler.ts stays
carrier-agnostic. RealtimeAudioPacer is generalized to accept any
serializer. The provider-twilio realtime gate widens to accept
telnyx.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 21:23:50 +05:30
Shakker
a517434261 test: read cron error bodies 2026-05-12 16:52:13 +01:00
Shakker
a665c004c1 test: scope cron history subtitle 2026-05-12 16:51:12 +01:00
Shakker
f1569b4afd test: read cron due metadata 2026-05-12 16:50:21 +01:00
Shakker
d0c2cce07e test: name stale cron job 2026-05-12 16:49:13 +01:00
Shakker
d6a65e928b test: tabulate cron delivery fields 2026-05-12 16:48:10 +01:00
Shakker
0aed7c5090 test: select localized welcome copy 2026-05-12 16:47:04 +01:00
Shakker
80c615daee test: bind pairing hint commands 2026-05-12 16:45:47 +01:00
Peter Steinberger
cb957fe0d2 test: dedupe telegram delivery mock calls 2026-05-12 16:44:58 +01:00
Shakker
4b4b8d9305 test: rely on context detail text 2026-05-12 16:43:54 +01:00
Shakker
23a4d5298d test: target chat detail labels 2026-05-12 16:42:57 +01:00
Shakker
ec082a7790 test: route chat loading assertions 2026-05-12 16:41:42 +01:00
Peter Steinberger
fcd1073b72 test: dedupe auto-reply dispatch mock calls 2026-05-12 16:41:33 +01:00
Shakker
7d208f3a5d test: scope localized agent refresh 2026-05-12 16:39:47 +01:00
Shakker
678cd504e8 test: order advanced review controls 2026-05-12 16:38:36 +01:00
Shakker
aef22e659b test: pin wiki preview truncation 2026-05-12 16:37:09 +01:00
Shakker
34e69362d9 test: read parsed dream entry 2026-05-12 16:36:21 +01:00
Shakker
aac9c9bc96 test: specify diary empty states 2026-05-12 16:35:32 +01:00
Shakker
4941c919d9 test: detail wiki enablement cta 2026-05-12 16:34:42 +01:00
Shakker
44001b7d25 test: extract diary insight fields 2026-05-12 16:33:56 +01:00
Peter Steinberger
e215dfcadf test: dedupe outbound matrix mock calls 2026-05-12 16:33:49 +01:00
Shakker
b0cdb5b3ce test: normalize dreaming status detail 2026-05-12 16:32:57 +01:00
Shakker
2174cabcbe test: anchor live canvas preview 2026-05-12 16:31:39 +01:00
Shakker
19a70d98b1 test: separate visible canvas rows 2026-05-12 16:30:52 +01:00
Shakker
4289e4c834 test: locate hidden canvas details 2026-05-12 16:30:07 +01:00
Peter Steinberger
5e009ed142 test: dedupe subagent announce mock calls 2026-05-12 16:29:54 +01:00
Shakker
a46fa1d952 test: describe canvas embed frame 2026-05-12 16:29:23 +01:00
Shakker
ba23d9ac71 test: resolve document media link 2026-05-12 16:28:19 +01:00
Peter Steinberger
2379da6cf1 test: dedupe qa matrix cli mock calls 2026-05-12 16:27:30 +01:00
Shakker
263d7cbf27 test: recheck media retry state 2026-05-12 16:22:45 +01:00
Shakker
52a958727b test: verify platform media checks 2026-05-12 16:22:12 +01:00
Peter Steinberger
c5135c1efd test: dedupe qa matrix message body mock calls 2026-05-12 16:22:00 +01:00
Shakker
f56a091607 test: identify blocked media fields 2026-05-12 16:21:09 +01:00
Gavin Zeng
a7f1c7b672 fix(exec): skip heartbeat wake for subagent sessions (#66749)
Merged via squash.

Prepared head SHA: 86bf841519
Co-authored-by: ggzeng <20488795+ggzeng@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-05-12 18:21:03 +03:00
Shakker
3c8ff0af26 test: separate same-origin media state 2026-05-12 16:20:24 +01:00
Shakker
372ed1e5e4 test: differentiate media auth refresh 2026-05-12 16:19:54 +01:00
Shakker
ca87dabac0 test: trace local media ticket cards 2026-05-12 16:19:17 +01:00
Shakker
565e612a5b test: confirm assistant media surfaces 2026-05-12 16:18:35 +01:00
Peter Steinberger
d24254ef5f test: dedupe telegram bot mock call 2026-05-12 16:17:54 +01:00
Shakker
4a5009f8d1 test: bind tool catalog warning 2026-05-12 16:15:17 +01:00
Peter Steinberger
730cbb356f test: dedupe bonjour advertiser mock calls 2026-05-12 16:15:03 +01:00
Peter Steinberger
7b52b60051 test: dedupe codex side question mock calls 2026-05-12 16:13:08 +01:00
Shakker
7058b5a859 test: structure sessions empty states 2026-05-12 16:12:56 +01:00
Shakker
81ba006442 test: narrow runtime filter result 2026-05-12 16:12:24 +01:00
Shakker
e1ebe46d12 test: scope identity filter rows 2026-05-12 16:11:35 +01:00
Peter Steinberger
250e16d3c9 test: dedupe codex conversation mock calls 2026-05-12 16:11:24 +01:00
Shakker
8a2dae7050 test: select compaction disclosure 2026-05-12 16:10:52 +01:00
Shakker
e40fa869da test: inspect session details fields 2026-05-12 16:10:12 +01:00
Peter Steinberger
b2d8a92f48 test: dedupe feishu docx mock calls 2026-05-12 16:09:16 +01:00
Shakker
4dd0231ecc test: parse grouped tool outputs 2026-05-12 16:08:11 +01:00
Pavan Kumar Gondhi
9ac4272b35 fix: harden safe-bin argument validation [AI] (#80999)
* fix: reject shell expansion in safe-bin tokens

* fix: complete safe-bin shell payload handling

* addressing codex review

* addressing ci

* addressing ci

* addressing codex review

* docs: add changelog entry for PR merge
2026-05-12 20:37:58 +05:30
Peter Steinberger
186de9daa0 test: dedupe feishu outbound mock calls 2026-05-12 16:06:08 +01:00
Shakker
cbb73134ef test: expand grouped tool blocks 2026-05-12 16:05:05 +01:00
Peter Steinberger
fdb2d3a083 test: dedupe googlechat auth mock calls 2026-05-12 16:04:22 +01:00
Shakker
78c0ba016c test: query run control buttons 2026-05-12 16:04:04 +01:00
Shakker
45b68a2c20 test: label session filter field 2026-05-12 16:03:06 +01:00
Peter Steinberger
fa0c23c8ba test: dedupe googlechat target mock calls 2026-05-12 16:02:29 +01:00
Shakker
6390733519 test: read grouped meta spans 2026-05-12 16:02:14 +01:00
Shakker
af5f6a3276 test: place delete confirms exactly 2026-05-12 16:01:26 +01:00
Shakker
2030a6390c test: catalogue agent tool details 2026-05-12 16:00:29 +01:00
Peter Steinberger
7121791735 test: dedupe matrix client mock calls 2026-05-12 15:59:47 +01:00
Shakker
188fa93862 test: address agent tabs directly 2026-05-12 15:59:31 +01:00
Shakker
a20a213daa test: find quick settings rows 2026-05-12 15:58:50 +01:00
Pavan Kumar Gondhi
a5dce367ce fix: scan plugin runtime entries during install [AI] (#80998)
* fix: scan plugin runtime entries during install

* addressing review-skill

* addressing claude review

* docs: add changelog entry for PR merge
2026-05-12 20:28:40 +05:30
Peter Steinberger
b076215e82 test: dedupe memory search mock calls 2026-05-12 15:57:57 +01:00
Shakker
33ca27f4f6 test: parse tool card raw details 2026-05-12 15:57:32 +01:00
Shakker
c423ef2e34 test: split tool card block checks 2026-05-12 15:56:38 +01:00
Shakker
44de39a1df test: filter config form tag labels 2026-05-12 15:56:01 +01:00
Peter Steinberger
b28714307d test: dedupe minimax speech mock calls 2026-05-12 15:55:38 +01:00
Shakker
166361c5eb test: frame markdown sidebar slots 2026-05-12 15:55:13 +01:00
Shakker
c77f199fd6 test: resolve lazy view text 2026-05-12 15:53:58 +01:00
Peter Steinberger
f3d5a9926f test: dedupe nostr inbound mock calls 2026-05-12 15:53:31 +01:00
Shakker
151de16001 test: render side result slots 2026-05-12 15:52:50 +01:00
Shakker
4a83448662 test: shape context notice controls 2026-05-12 15:52:05 +01:00
Peter Steinberger
cb8b7ff891 test: dedupe ollama embedding mock calls 2026-05-12 15:51:45 +01:00
Shakker
449da806bd test: name session source toggles 2026-05-12 15:51:16 +01:00
Peter Steinberger
7a9613e66b test: dedupe openai tts mock calls 2026-05-12 15:49:59 +01:00
Peter Steinberger
49d42bea6e test: dedupe openrouter video mock calls 2026-05-12 15:48:23 +01:00
Shakker
b0cd70f021 test: grade session status badges 2026-05-12 15:47:13 +01:00
Peter Steinberger
360b0769db test: dedupe qqbot websocket mock calls 2026-05-12 15:46:33 +01:00
Peter Steinberger
67ac7ee200 test: dedupe signal client mock calls 2026-05-12 15:45:01 +01:00
Shakker
94e7678be4 test: expand preview class checks 2026-05-12 15:44:49 +01:00
Shakker
8c134178d6 test: isolate mount fallback elements 2026-05-12 15:44:14 +01:00
Shakker
b8db4fc859 test: preserve focus shell classes 2026-05-12 15:43:31 +01:00
Peter Steinberger
cc736fdf1c test: dedupe signal monitor mock calls 2026-05-12 15:43:14 +01:00
Shakker
b80f5c2ea5 test: lock mobile controls classes 2026-05-12 15:42:56 +01:00
Shakker
3e1360cfea test: map navigation shell classes 2026-05-12 15:42:20 +01:00
Shakker
b14f91bd86 test: require config action buttons 2026-05-12 15:41:03 +01:00
Peter Steinberger
7c8d32211d test: dedupe speech tts mock calls 2026-05-12 15:40:41 +01:00
Peter Steinberger
094f6d83c7 test: dedupe telegram dispatch mock calls 2026-05-12 15:38:59 +01:00
Shakker
859977e5d8 test: define custom theme style sync 2026-05-12 15:38:07 +01:00
Shakker
14a95bffb5 test: capture tool card action class 2026-05-12 15:37:28 +01:00
Peter Steinberger
26afc763b3 test: dedupe telegram command menu mock calls 2026-05-12 15:37:11 +01:00
Shakker
7c2c91a0fa test: track divider dragging class 2026-05-12 15:35:39 +01:00
Shakker
b9e0babe04 test: match chat avatar initials 2026-05-12 15:34:59 +01:00
Shakker
10e6d7eb3e test: spell out agent tool classes 2026-05-12 15:34:04 +01:00
Shakker
24f0ae7937 test: list active quick profile classes 2026-05-12 15:33:16 +01:00
Peter Steinberger
f4ae21cb0a test: dedupe telegram channel post mock calls 2026-05-12 15:33:06 +01:00
Shakker
3fdb2b78c5 test: pin chat status indicators 2026-05-12 15:32:41 +01:00
Shakker
1dbf788619 test: enumerate chat control classes 2026-05-12 15:31:29 +01:00
Peter Steinberger
2bfbe25239 test: dedupe telegram fetch mock calls 2026-05-12 15:30:17 +01:00
Shakker
13111d8e27 test: verify mount fallback copy 2026-05-12 15:29:21 +01:00
Shakker
ffbeb53838 test: target lazy view states 2026-05-12 15:28:31 +01:00
Shakker
98f72eda21 test: tighten context notice text 2026-05-12 15:27:50 +01:00
Shakker
8e068bc72c test: locate config tag result 2026-05-12 15:27:06 +01:00
Peter Steinberger
684e13c7fd test: dedupe vydra fetch mock calls 2026-05-12 15:26:51 +01:00
Shakker
646ef0c78f test: anchor config hint label 2026-05-12 15:26:06 +01:00
Peter Steinberger
f6418812ef test: dedupe whatsapp media cap mock calls 2026-05-12 15:24:54 +01:00
Peter Steinberger
99f9b78bcd test: dedupe whatsapp process mock calls 2026-05-12 15:22:22 +01:00
Shakker
26df0e4782 test: pin cron run filters 2026-05-12 15:22:06 +01:00
Shakker
ac3bf79d9d test: assert debug callout class 2026-05-12 15:21:16 +01:00
Shakker
3b2735f3ee test: check dreaming tab labels 2026-05-12 15:20:41 +01:00
Peter Steinberger
4e3b952b70 test: dedupe feishu comment mock calls 2026-05-12 15:19:46 +01:00
Peter Steinberger
a34d45e2a1 test: dedupe feishu media mock calls 2026-05-12 15:17:31 +01:00
Peter Steinberger
ca2523f9d5 test: dedupe line download mock calls 2026-05-12 15:14:46 +01:00
Peter Steinberger
185ace0155 test: dedupe synology chat http mock calls 2026-05-12 15:12:36 +01:00
Peter Steinberger
2298889cb9 test: dedupe telegram session metadata mock calls 2026-05-12 15:09:56 +01:00
Pavan Kumar Gondhi
b6a94d4ef9 Require auth for sandbox browser CDP relay [AI] (#81002)
* fix: require auth for sandbox browser cdp relay

* addressing review-skill

* addressing review-skill

* addressing review-skill

* addressing codex review

* addressing claude review

* docs: add changelog entry for PR merge
2026-05-12 19:37:32 +05:30
Peter Steinberger
ed2a451363 test: dedupe whatsapp audio mock calls 2026-05-12 15:06:58 +01:00
Pavan Kumar Gondhi
65d7232218 fix: detect carried exec command forms [AI] (#81000)
* fix: detect carried inline exec forms

* addressing review-skill

* addressing codex review

* addressing ci

* docs: add changelog entry for PR merge
2026-05-12 19:36:04 +05:30
Peter Steinberger
64b7be436c test: dedupe export session write mock calls 2026-05-12 15:04:54 +01:00
Pavan Kumar Gondhi
731af9c96b Reject truncated exec approval commands [AI] (#81001)
* fix: reject truncated exec approval commands

* docs: add changelog entry for PR merge
2026-05-12 19:33:42 +05:30
Peter Steinberger
8d41e4d53f test: dedupe daemon install mock calls 2026-05-12 15:02:28 +01:00
Pavan Kumar Gondhi
50f4440c96 Enforce inline shell wrapper payload matching [AI] (#80978)
* fix: enforce inline shell wrapper payload matching

* addressing review-skill

* addressing codex review

* addressing codex review

* addressing claude review

* addressing claude review

* fix: complete shell wrapper allowlist handling

* addressing codex review

* addressing codex review

* addressing codex review

* addressing codex review

* addressing codex review

* addressing ci

* docs: add changelog entry for PR merge
2026-05-12 19:30:18 +05:30
Peter Steinberger
b1131cddbd test: dedupe claude doctor note mock calls 2026-05-12 14:59:03 +01:00
Peter Steinberger
bf4ab7ecf0 test: dedupe models list runtime mock calls 2026-05-12 14:57:30 +01:00
Peter Steinberger
07748507cc test: dedupe chat directive mock calls 2026-05-12 14:55:53 +01:00
Shakker
086aec8d85 test: compare inherited session keys 2026-05-12 14:55:13 +01:00
Shakker
5f83ddba9f test: match session identity cells 2026-05-12 14:54:26 +01:00
Shakker
313df5814d test: locate markdown preview label 2026-05-12 14:53:38 +01:00
Peter Steinberger
3b7fdb3033 test: dedupe heartbeat tool response mock calls 2026-05-12 14:52:21 +01:00
Shakker
e101ee184b test: preserve localized agent tabs 2026-05-12 14:51:51 +01:00
Shakker
e21efc6ccc test: check active tool profile state 2026-05-12 14:50:37 +01:00
Peter Steinberger
e2c32806c1 test: dedupe anthropic vertex stream mock calls 2026-05-12 14:50:30 +01:00
Shakker
806a3bce68 test: list whatsapp action buttons 2026-05-12 14:49:27 +01:00
Shakker
9bfa2d031f test: order quick identity titles 2026-05-12 14:48:56 +01:00
Peter Steinberger
3b45ad6960 test: dedupe matrix device mock calls 2026-05-12 14:48:14 +01:00
Peter Steinberger
a45b96fd88 test: dedupe matrix message mock calls 2026-05-12 14:46:43 +01:00
Shakker
eea3e2c0f7 test: record assistant avatar source fields 2026-05-12 14:45:53 +01:00
Peter Steinberger
bfb595b5ce test: dedupe memory narrative mock calls 2026-05-12 14:45:02 +01:00
Peter Steinberger
fce4f10e96 test: dedupe ollama web search mock calls 2026-05-12 14:43:10 +01:00
Peter Steinberger
33568988a6 test: dedupe status scan mock calls 2026-05-12 14:39:18 +01:00
Peter Steinberger
f1ce79ba6c test: dedupe server channel startup mock calls 2026-05-12 14:36:57 +01:00
Peter Steinberger
89cd10157b test: dedupe tools catalog respond calls 2026-05-12 14:34:45 +01:00
Peter Steinberger
1e543fa844 test: dedupe gateway post attach mock calls 2026-05-12 14:32:29 +01:00
Peter Steinberger
cf924fd1e8 test: dedupe heartbeat reply body mock calls 2026-05-12 14:29:12 +01:00
Peter Steinberger
10c09d9b73 test: dedupe bedrock mantle stream mock calls 2026-05-12 14:26:38 +01:00
Peter Steinberger
8f645dba24 test: dedupe browser registration mock calls 2026-05-12 14:24:31 +01:00
Shakker
d08072285c test: bind clawhub detail dialog text 2026-05-12 14:24:15 +01:00
Shakker
4116f8cedf test: target clawhub result fields 2026-05-12 14:22:57 +01:00
Shakker
6f46d12778 test: isolate agent skills tab count 2026-05-12 14:21:42 +01:00
Peter Steinberger
997c28c50c test: dedupe feishu monitor cleanup mock calls 2026-05-12 14:20:45 +01:00
Shakker
831eebfadd test: verify debug security callout text 2026-05-12 14:19:27 +01:00
Peter Steinberger
3303b2fc05 test: dedupe matrix monitor mock calls 2026-05-12 14:18:27 +01:00
Shakker
67267cb2ad test: scope cache hit overview assertion 2026-05-12 14:17:02 +01:00
Peter Steinberger
85e0137472 test: dedupe qa credential lease fetch calls 2026-05-12 14:15:54 +01:00
Shakker
322d9be225 test: tighten sqlite-vec error contracts 2026-05-12 14:15:23 +01:00
Peter Steinberger
fad2484477 fix: canonicalize qualified gemini pro preview refs 2026-05-12 14:12:35 +01:00
Peter Steinberger
45a8a25947 test: dedupe telegram media e2e mock calls 2026-05-12 14:07:05 +01:00
Peter Steinberger
d9f2b64be1 test: dedupe tlon guarded fetch calls 2026-05-12 14:04:38 +01:00
Peter Steinberger
37c38d1756 test: dedupe whatsapp session mock calls 2026-05-12 14:02:47 +01:00
Shakker
d26ab41372 test: require exact http failures 2026-05-12 14:01:56 +01:00
Peter Steinberger
7665b3926c test: dedupe configure auth allowlist calls 2026-05-12 13:59:05 +01:00
Peter Steinberger
a1cae45654 test: dedupe talk handler mock calls 2026-05-12 13:57:06 +01:00
Peter Steinberger
076bf848a1 test: dedupe heartbeat ghost mock calls 2026-05-12 13:54:24 +01:00
Peter Steinberger
8ecdd353ef test: dedupe approval forwarder mock calls 2026-05-12 13:52:24 +01:00
Shakker
e14b54596f test: name default local embedding model 2026-05-12 13:51:13 +01:00
Peter Steinberger
8aca690939 test: dedupe health snapshot mock calls 2026-05-12 13:50:28 +01:00
Peter Steinberger
5ec4573604 test: dedupe codex elicitation mock calls 2026-05-12 13:48:28 +01:00
Peter Steinberger
db79b1cc5e test: dedupe ollama setup mock calls 2026-05-12 13:46:26 +01:00
Peter Steinberger
4b2a502c5b test: dedupe heartbeat reply mock calls 2026-05-12 13:44:30 +01:00
Peter Steinberger
9b07f80559 test: dedupe node event mock calls 2026-05-12 13:40:28 +01:00
Peter Steinberger
fe0e2e6f41 test: dedupe telegram native command mock calls 2026-05-12 13:38:34 +01:00
Shakker
1c44d31aab test: map multilingual query tokens 2026-05-12 13:37:38 +01:00
Peter Steinberger
14b871efd9 test: dedupe codex registration mock calls 2026-05-12 13:36:21 +01:00
Peter Steinberger
e6551e63ba test: dedupe auto-reply delivery mock calls 2026-05-12 13:34:16 +01:00
Peter Steinberger
88714d6803 fix: normalize oauth auth-result config patches 2026-05-12 13:31:42 +01:00
Shakker
a538e58075 test: anchor consult runtime prompt 2026-05-12 13:31:03 +01:00
Shakker
fa97442740 test: freeze voice consult prompt 2026-05-12 13:30:00 +01:00
Shakker
31bdbfe59b test: codify usage chart sizing 2026-05-12 13:28:59 +01:00
Peter Steinberger
0a028a3a8a test: dedupe openai http agent mock calls 2026-05-12 13:22:36 +01:00
Bob
fe79efc31b fix: surface silent model fallback failures (#80917)
Merged via squash.

Prepared head SHA: 59be6e2db5
Co-authored-by: dutifulbob <261991368+dutifulbob@users.noreply.github.com>
Co-authored-by: osolmaz <2453968+osolmaz@users.noreply.github.com>
Reviewed-by: @osolmaz
2026-05-12 15:19:10 +03:00
Shakker
9c125e821f test: enumerate config preset defaults 2026-05-12 13:18:26 +01:00
Peter Steinberger
7187d2754e test: dedupe matrix group history mock calls 2026-05-12 13:18:08 +01:00
Shakker
9e09dfe512 test: parse talk file log fields 2026-05-12 13:17:21 +01:00
Peter Steinberger
258002917b test: dedupe whatsapp delivery mock calls 2026-05-12 13:16:05 +01:00
Shakker
3b5e189125 test: quantify fallback error allocation 2026-05-12 13:15:38 +01:00
Peter Steinberger
8e848919e7 test: dedupe zalo group gating mock calls 2026-05-12 13:14:08 +01:00
Shakker
0746fda37c test: specify session export content 2026-05-12 13:13:20 +01:00
Shakker
c3c72a7cfb test: assert peak error summaries 2026-05-12 13:10:26 +01:00
clawsweeper[bot]
d44553dade fix(gateway): wire max_completion_tokens/max_tokens through openai-http (#81013)
Summary:
- The branch adds Chat Completions token-cap fields to the Gateway request type, forwards them as agent stream parameters, and documents/tests the behavior.
- Reproducibility: yes. Source inspection gives a high-confidence current-main path: send `max_completion_toke ... tokens` to `/v1/chat/completions` and observe that the current handler never sets `streamParams.maxTokens`.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(gateway): wire max_completion_tokens/max_tokens through openai-http

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

Prepared head SHA: a9c39f7d4a
Review: https://github.com/openclaw/openclaw/pull/81013#issuecomment-4430303959

Co-authored-by: Bingsen <dingheng.huang@urbanic.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
2026-05-12 12:08:07 +00:00
Shakker
be7ca5d828 test: lock qmd backend collections 2026-05-12 13:07:56 +01:00
Peter Steinberger
04ee5985c4 test: dedupe control plane response mock calls 2026-05-12 13:06:58 +01:00
Shakker
66f16b81b9 test: pin query expansion expectations 2026-05-12 13:05:53 +01:00
Peter Steinberger
e9431e2dd4 test: dedupe codex run attempt hook mock calls 2026-05-12 13:04:34 +01:00
Peter Steinberger
c9ec1dea71 test: dedupe codex shared client mock calls 2026-05-12 13:01:48 +01:00
Peter Steinberger
f7f9312c7a test: dedupe matrix replies send mock calls 2026-05-12 12:59:22 +01:00
Peter Steinberger
756f9bb2f1 test: dedupe usage sessions mock calls 2026-05-12 12:57:39 +01:00
Peter Steinberger
5940d0d4b1 test: dedupe codex approval gateway mock calls 2026-05-12 12:55:50 +01:00
Peter Steinberger
3c82b144bb test: dedupe mattermost send mock calls 2026-05-12 12:53:52 +01:00
Peter Steinberger
32d5cd9a28 test: dedupe channels list log mock calls 2026-05-12 12:50:26 +01:00
Peter Steinberger
6d10e7d784 test: dedupe gateway hook run mock calls 2026-05-12 12:48:42 +01:00
Peter Steinberger
632c1bc0ba test: dedupe brave fetch mock calls 2026-05-12 12:45:31 +01:00
Super Zheng
4223dd2886 fix: enable native require fast path on Windows for plugin-sdk root alias (#80878)
Merged via squash.

Prepared head SHA: 87446445b6
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-12 04:43:55 -07:00
Super Zheng
a92d5fe77d feat(agents): make run loop retry limits configurable in openclaw.json (#80661)
Merged via squash.

Prepared head SHA: d595d51a5a
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-12 04:43:12 -07:00
Peter Steinberger
8a051395b7 test: dedupe matrix handler send mock calls 2026-05-12 12:42:04 +01:00
Super Zheng
380daf2f50 feat(gateway): inject isHeartbeat into agent event broadcast payload (#80610)
Merged via squash.

Prepared head SHA: cb254108a1
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-12 04:41:14 -07:00
Peter Steinberger
4e29ee516b test: dedupe slack interaction mock calls 2026-05-12 12:39:58 +01:00
Ayaan Zaidi
f506ced2b3 docs(changelog): note onboarding auth fix (#80913) (thanks @rubencu) 2026-05-12 17:08:18 +05:30
Ayaan Zaidi
a6faeecf52 refactor(onboard): simplify model auth candidates 2026-05-12 17:08:18 +05:30
Rubén Cuevas
9600646449 test(onboard): type model check auth mocks 2026-05-12 17:08:18 +05:30
Rubén Cuevas
379ba2e8ae fix(onboard): short-circuit model auth check 2026-05-12 17:08:18 +05:30
Rubén Cuevas
31eaa106c5 fix(onboard): accept Codex auth in model check 2026-05-12 17:08:18 +05:30
Peter Steinberger
74fbbf503f test: dedupe matrix approval mock calls 2026-05-12 12:37:16 +01:00
Peter Steinberger
ed53339f8f test: dedupe mcp transport fetch mock calls 2026-05-12 12:34:57 +01:00
Peter Steinberger
dc0ebdfef8 test: guard codex command mock calls 2026-05-12 12:31:16 +01:00
Peter Steinberger
275acdaeba test: guard feishu reply dispatcher mock calls 2026-05-12 12:29:09 +01:00
Peter Steinberger
0c6cc68eb3 test: guard slack slash mock calls 2026-05-12 12:27:12 +01:00
Peter Steinberger
75f5d6d9b5 test: guard auto reply media mock calls 2026-05-12 12:24:20 +01:00
Peter Steinberger
3e3057509b test: dedupe models auth status mock calls 2026-05-12 12:22:21 +01:00
Peter Steinberger
837cb8f5b0 test: dedupe doctor memory note assertions 2026-05-12 12:20:31 +01:00
Ayaan Zaidi
3718ef1985 docs(agents): distill PR routing guidance 2026-05-12 16:50:29 +05:30
Rubén Cuevas
3fe2c0e71f docs: clarify PR workflow gitcrawl fallback 2026-05-12 16:50:29 +05:30
Peter Steinberger
50c31707fa test: dedupe tools effective mock calls 2026-05-12 12:18:49 +01:00
Peter Steinberger
30c17fed20 test: guard whatsapp send api mock calls 2026-05-12 12:16:20 +01:00
Peter Steinberger
3a4c97c291 test: guard server chat agent event mock calls 2026-05-12 12:14:15 +01:00
Peter Steinberger
8846a2a89f test: guard voice call mock calls 2026-05-12 12:12:14 +01:00
Ayaan Zaidi
5abb4b18c8 fix(telegram): simplify context boundary plumbing 2026-05-12 16:40:42 +05:30
VACInc
afd7339bd2 fix telegram context session start boundary 2026-05-12 16:40:42 +05:30
VACInc
b31afcbc17 fix telegram context reset boundary 2026-05-12 16:40:42 +05:30
Peter Steinberger
d3e39f0c94 test: dedupe models status log parsing 2026-05-12 12:10:08 +01:00
Peter Steinberger
1e5b12ae73 test: guard node invoke wake mock calls 2026-05-12 12:08:05 +01:00
Peter Steinberger
efacb91818 test: guard control ui http mock calls 2026-05-12 12:06:00 +01:00
Ayaan Zaidi
1675b2ff30 docs(changelog): mention docker auth profile key mount (#80991) 2026-05-12 16:35:53 +05:30
Ayaan Zaidi
c025291df7 docs(docker): document auth profile key mount 2026-05-12 16:35:53 +05:30
Ayaan Zaidi
c3e3146639 fix(docker): persist auth profile key mount 2026-05-12 16:35:53 +05:30
Pavan Kumar Gondhi
3aeb55b5e7 fix(node-pairing): replace changed pending requests [AI] (#80894)
* fix: replace changed node pairing requests

* fix: replace changed node pairing requests

* addressing codex review

* addressing codex review

* addressing ci

* fix: complete node pairing permission handling

* addressing review-skill

* addressing codex review

* addressing codex review

* addressing ci

* addressing ci

* addressing ci

* docs: add changelog entry for PR merge
2026-05-12 16:33:55 +05:30
Peter Steinberger
3013369e99 test: guard migrate command mock calls 2026-05-12 12:03:52 +01:00
Pavan Kumar Gondhi
1b22384c11 Rate limit Google Chat webhook requests [AI] (#80974)
* fix: rate limit google chat webhook requests

* addressing claude review

* addressing ci

* addressing ci

* docs: add changelog entry for PR merge
2026-05-12 16:31:28 +05:30
Peter Steinberger
a943e4b766 test: guard model picker mock calls 2026-05-12 12:00:08 +01:00
Peter Steinberger
eb422fe44b test: guard diagnostics otel mock calls 2026-05-12 11:58:43 +01:00
Peter Steinberger
69298b18cf test: guard feishu drive mock calls 2026-05-12 11:57:20 +01:00
Pavan Kumar Gondhi
8c9dbe3e71 fix(feishu): normalize webhook rate-limit client keys [AI] (#80975)
* fix: normalize Feishu webhook rate limit keys

* addressing claude review

* docs: add changelog entry for PR merge
2026-05-12 16:26:12 +05:30
Peter Steinberger
636636ca92 test: guard google meet mock calls 2026-05-12 11:56:05 +01:00
Peter Steinberger
7625a8b6d6 test: guard openresponses mock calls 2026-05-12 11:54:29 +01:00
Peter Steinberger
f82b9adfb1 test: guard matrix send mock calls 2026-05-12 11:52:11 +01:00
Peter Steinberger
0586da70db test: guard telegram bot core mock calls 2026-05-12 11:50:44 +01:00
Peter Steinberger
4ea089b7fe test: guard auto-reply dispatch mock calls 2026-05-12 11:45:09 +01:00
Peter Steinberger
aa9799320d test: guard telegram bot mock calls 2026-05-12 11:42:50 +01:00
Pavan Kumar Gondhi
2d00bedc1e fix(auth): prevent bootstrap pairing scope changes [AI] (#80976)
* fix: prevent bootstrap pairing scope changes before redemption

* docs: add changelog entry for PR merge
2026-05-12 16:11:35 +05:30
Peter Steinberger
abd2ba1fe0 test: guard telegram send mock calls 2026-05-12 11:40:13 +01:00
Peter Steinberger
a12caa8b86 test: guard outbound delivery mock calls 2026-05-12 11:38:39 +01:00
Peter Steinberger
4bc47a3a75 test: guard telegram delivery mock calls 2026-05-12 11:37:03 +01:00
Pavan Kumar Gondhi
5ef8d1ab5e Validate Control UI loopback retry endpoints [AI] (#80900)
* fix: validate loopback retry endpoints

* fix: validate loopback retry endpoints

* docs: add changelog entry for PR merge
2026-05-12 16:06:00 +05:30
Pavan Kumar Gondhi
fd12a48ee1 Harden exported markdown link rendering [AI] (#80902)
* fix: sanitize exported markdown links

* fix: sanitize exported markdown links

* addressing claude review

* docs: add changelog entry for PR merge
2026-05-12 16:05:19 +05:30
Pavan Kumar Gondhi
da6f32bedf fix(gateway): honor minimal discovery mode for wide-area DNS-SD [AI] (#80903)
* fix: respect discovery mode for wide-area cli path

* addressing codex review

* docs: add changelog entry for PR merge
2026-05-12 16:03:50 +05:30
Peter Steinberger
d164f8cc74 test: guard qa matrix mock call assertions 2026-05-12 11:31:18 +01:00
Pavan Kumar Gondhi
889afc7c31 slack: enforce reaction notification policy [AI] (#80907)
* fix: enforce slack reaction notification policy

* addressing claude review

* addressing ci

* docs: add changelog entry for PR merge
2026-05-12 16:00:44 +05:30
Pavan Kumar Gondhi
652f5f9b10 Enforce gateway command scopes by caller context [AI] (#80891)
* fix: enforce gateway command scopes by caller context

* fix: enforce gateway command scopes by caller context

* addressing codex review

* addressing claude review

* addressing claude review

* addressing ci

* docs: add changelog entry for PR merge
2026-05-12 15:59:22 +05:30
Peter Steinberger
be5483f240 test: guard core mock call assertions 2026-05-12 11:29:16 +01:00
Pavan Kumar Gondhi
a4da627da1 Enforce Slack plugin approval button authorization [AI] (#80899)
* fix: enforce slack plugin approval button authorization

* fix: enforce slack plugin approval button authorization

* addressing codex review

* addressing codex review

* docs: add changelog entry for PR merge
2026-05-12 15:56:24 +05:30
Peter Steinberger
97b9d77196 test: guard extension runtime mock calls 2026-05-12 11:24:21 +01:00
Ayaan Zaidi
485e04266c docs(changelog): note telegram html rendering fix (#80977) 2026-05-12 15:54:01 +05:30
Ayaan Zaidi
f6adc78f06 fix(telegram): keep durable html unsanitized 2026-05-12 15:54:01 +05:30
Ayaan Zaidi
b480b29dc7 fix(telegram): preserve supported html replies 2026-05-12 15:54:01 +05:30
Pavan Kumar Gondhi
de47989731 Recognize PowerShell -ec inline commands [AI] (#80893)
* fix: recognize PowerShell -ec inline command flag

* fix: recognize PowerShell -ec inline command flag

* addressing codex review

* addressing codex review

* addressing codex review

* addressing codex review

* addressing codex review

* fix: recognize PowerShell encoded command prefixes

* addressing review-skill

* addressing review-skill

* addressing codex review

* addressing codex review

* docs: add changelog entry for PR merge
2026-05-12 15:53:10 +05:30
Pavan Kumar Gondhi
6e498a1f62 fix(qqbot): authorize approval button callbacks [AI] (#80892)
* fix: authorize qqbot approval buttons

* fix: authorize qqbot approval buttons

* addressing claude review

* docs: add changelog entry for PR merge
2026-05-12 15:51:13 +05:30
Peter Steinberger
2ec1a27c9f test: guard extension channel mock calls 2026-05-12 11:19:53 +01:00
Peter Steinberger
6a230a108a test: guard extension messaging mock calls 2026-05-12 11:15:37 +01:00
Peter Steinberger
ea05be12b4 test: guard extension provider mock calls 2026-05-12 11:11:04 +01:00
Shakker
7bb2d20303 test: remove duplicate gateway startup case 2026-05-12 11:09:49 +01:00
Peter Steinberger
04139a7d44 test: guard extension app mock calls 2026-05-12 11:07:04 +01:00
Peter Steinberger
7215945b06 test: guard gateway infra mock calls 2026-05-12 11:03:37 +01:00
Peter Steinberger
7a9f770a63 test: guard command model mock calls 2026-05-12 11:00:43 +01:00
Pavan Kumar Gondhi
47eb2d48d4 Scrub streamable MCP redirect headers [AI] (#80906)
* fix: scrub streamable mcp redirect headers

* addressing review-skill

* addressing codex review

* addressing claude review

* docs: add changelog entry for PR merge
2026-05-12 15:28:54 +05:30
Peter Steinberger
e196a43694 test: guard auto reply runner mock calls 2026-05-12 10:58:34 +01:00
Peter Steinberger
81b7d670cd test: guard cron infra ui mock calls 2026-05-12 10:56:25 +01:00
Peter Steinberger
067666df90 test: guard gateway call assertions 2026-05-12 10:53:58 +01:00
Ayaan Zaidi
99598284c1 docs(changelog): credit matrix runtime install fix (#80876) (thanks @kinjitakabe) 2026-05-12 15:22:10 +05:30
Ayaan Zaidi
0792223a87 refactor(matrix): simplify dependency availability check 2026-05-12 15:22:10 +05:30
kinjitakabe
760501fc38 fix(matrix): stop runtime npm install from parent-derived cwd
`ensureMatrixSdkInstalled` previously derived an install `cwd` via fixed
two-segment traversal from `import.meta.url` and spawned `npm install`
(or `pnpm install`) when Matrix packages were missing. Under the
externalized plugin layout the derived path is a scope directory like
`<config>/npm/node_modules/@openclaw`, so npm walks up to the managed
project root and prunes undeclared siblings. Under the legacy bundled
layout it would target `<global-prefix>/lib/node_modules` and could
delete unrelated global CLIs.

Matrix is now a pure availability check: if any required package fails
to resolve, it throws an actionable error pointing the operator at the
supported repair commands (`openclaw plugins update matrix`,
`openclaw doctor --fix`). This matches extensions/AGENTS.md:
"Runtime never installs deps; install/update/doctor are repair points."

The exported signature stays backwards-compatible (all params optional;
`confirm` and `runtime` are accepted but ignored). `resolveMissingMatrixPackages`
gains an optional `resolveFn` seam for testability, mirroring the existing
`ensureMatrixCryptoRuntime` injection pattern.

Fixes #80758.
2026-05-12 15:22:10 +05:30
1697 changed files with 63909 additions and 14658 deletions

View File

@@ -0,0 +1,159 @@
---
name: clawdtributor
description: "Use for OpenClaw clawtributors PR/issue triage: Discrawl discovery, live-open rechecks, deep review, topic grouping, and compact @handle/LOC/type/blast/verification summaries."
---
# Clawdtributor
Use for the `#clawtributors` queue: Discord-discovered OpenClaw PRs/issues that need live GitHub status plus maintainer-quality review.
## Compose with other skills
- `$discrawl`: local Discord archive sync/search.
- `$openclaw-pr-maintainer`: live GitHub PR/issue review, duplicate search, close/land rules.
- `$gitcrawl`: related issue/PR and current-main/stale-proof search.
- `$openclaw-testing` / `$crabbox`: proof choice when a candidate needs real validation.
## Archive flow
Local archive first; verify freshness for current questions.
```bash
discrawl status --json
discrawl sync
```
Resolve channel if needed:
```bash
sqlite3 "$HOME/.discrawl/discrawl.db" \
"select id,name from channels where name like '%clawtributor%' order by name;"
```
Current known channel id from prior work: `1458141495701012561`. Re-resolve if it stops matching.
Extract recent refs:
```bash
sqlite3 "$HOME/.discrawl/discrawl.db" "
select m.created_at, coalesce(nullif(mm.username,''), m.author_id), m.content
from messages m
left join members mm on mm.guild_id=m.guild_id and mm.user_id=m.author_id
where m.channel_id='1458141495701012561'
and m.created_at >= '<ISO cutoff>'
order by m.created_at desc;" |
perl -nE 'while(m{github\.com/openclaw/openclaw/(pull|issues)/(\d+)}g){say "$1\t$2\t$_"}'
```
Map a PR/issue back to the Discord handle:
```bash
sqlite3 -separator $'\t' "$HOME/.discrawl/discrawl.db" "
select m.created_at,
coalesce(nullif(mm.username,''), nullif(mm.global_name,''), m.author_id)
from messages m
left join members mm on mm.guild_id=m.guild_id and mm.user_id=m.author_id
where m.channel_id='1458141495701012561'
and m.content like '%github.com/openclaw/openclaw/<pull-or-issues>/<number>%'
order by m.created_at desc
limit 1;"
```
Show only `@handle` in the final list. Do not write the word Discord unless the user asks for source details.
## Live GitHub recheck
Always recheck live state before listing, closing, or saying "open".
```bash
GITHUB_TOKEN= GITHUB_TOKEN_NODIFF= GH_TOKEN= \
gh api repos/openclaw/openclaw/pulls/<number> \
--jq '. | {number,title,state,merged,mergeable,draft,author:.user.login,url:.html_url,updatedAt:.updated_at,additions,deletions,changedFiles:.changed_files}'
```
For issues:
```bash
GITHUB_TOKEN= GITHUB_TOKEN_NODIFF= GH_TOKEN= \
gh api repos/openclaw/openclaw/issues/<number> \
--jq '. | {number,title,state,author:.user.login,url:.html_url,updatedAt:.updated_at,pull_request}'
```
If `gh` says bad credentials, clear env vars with empty assignments as above. Use `--jq '. | {...}'` for object projections.
## Review depth
For each open item, inspect enough to classify risk:
- PR body, linked issue, comments, files, additions/deletions, checks.
- Current `origin/main` code path and adjacent tests.
- Related threads with `gitcrawl neighbors/search`.
- Whether main already fixed it, the PR is obsolete, or the idea is invalid.
- Blast radius: touched runtime surfaces, config/schema, plugin/core boundary, user-visible behavior, release/package surface.
- Verification: say if local unit/docs proof is enough, live/provider proof is needed, or it is not directly verifiable.
Do not close from title alone. If closing as done on main or nonsensical, prove it against current main and comment first when mutation is requested. Bulk close/reopen above 5 requires explicit scope.
## Candidate selection
When asked for `5 new`, exclude refs already surfaced in the session and refill from the archive until there are 5 live-open candidates. If fewer than 5 remain open, list all open ones and say how many short.
When asked to `update`, `refresh`, `recheck`, `check again`, or similar, return an updated live-open candidate list. Do not fill the main list with items that merely merged/closed since the last pass; put those numbers in a short bottom line.
Prefer:
- Fresh, open, external contributor work.
- Small, high-confidence bugfixes.
- Clear repro, tests, or obvious code-path proof.
Demote:
- Broad product/features without owner decision.
- Large rewrites with unclear contract.
- PRs already in progress, merged, closed, duplicate, or fixed on main.
## Topic grouping
Group only when useful or requested:
- Agents/tooling
- Providers/auth/models
- Channels/messaging
- UI/web
- Gateway/protocol/runtime
- Config/memory/cache
- Docker/install/release
- Docs/tests/chore
- Closed/obsolete
Infer topic from labels, touched files, title/body, and actual code path.
## Output format
No Markdown tables. Compact bullets. Use color/risk markers:
- 🟢 low/narrow
- 🟡 medium or needs targeted proof
- 🔴 broad/high runtime risk
- 🟣 security/policy/owner-boundary slow review
- ✅ merged
- ⚪ closed unmerged
Required line shape:
```markdown
- **PR #81244** `@whatsskill.` `+118/-1` `bug` 🟢 verifiable: yes. This prevents chat action buttons from overlapping short assistant replies. Blast: web chat rendering, low.
- **Issue #81245** `@alice` `LOC n/a` `bug` 🟡 verifiable: partial. This reports duplicate Telegram replies when reconnecting after gateway restart. Blast: Telegram channel runtime, medium.
```
Rules:
- Bold the `PR #n` or `Issue #n` marker.
- Use `@handle`, not author bio text.
- PR LOC is `+additions/-deletions`; issue LOC is `LOC n/a`.
- Type: `bug`, `feature`, `perf`, `security`, `docs`, `test`, `chore`, or `refactor`.
- Write a full sentence for what it does.
- Always include blast radius in one phrase.
- Always include `verifiable: yes|partial|no` plus the shortest proof hint when helpful.
- If status is not open, still show it only when the user asked for all surfaced refs; use ✅ or ⚪ and state merged/closed.
- For refresh-style asks, bottom line: `Merged/closed since last pass: #81016 merged, #81026 closed.` Omit if none.

View File

@@ -1,6 +1,6 @@
---
name: crabbox
description: Use Crabbox for OpenClaw remote Linux validation. Default to Blacksmith Testbox; includes direct Blacksmith and owned AWS/Hetzner fallback notes when Crabbox fails.
description: Use Crabbox for OpenClaw remote validation across Linux, macOS, Windows, and WSL2. Default to Blacksmith Testbox for broad Linux proof; includes direct Blacksmith and owned AWS/Hetzner fallback notes when Crabbox fails.
---
# Crabbox
@@ -31,13 +31,16 @@ 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.
- If a warm direct-provider lease smells stale, retry with `--full-resync`
(alias `--fresh-sync`) before replacing the lease. This resets the remote
workdir, skips the fingerprint fast path, reseeds Git when possible, and
uploads the checkout from scratch.
- For live/provider bugs, use the configured secret workflow before downgrading
to mocks. 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
@@ -64,7 +67,8 @@ Crabbox supports static SSH targets:
- `target=macos` and `target=windows --windows-mode wsl2` use the POSIX SSH,
bash, Git, rsync, and tar contract.
- Native Windows uses OpenSSH, PowerShell, Git, and tar; sync is manifest tar
archive transfer into `static.workRoot`.
archive transfer into `static.workRoot`. Direct native Windows runs support
`--script*`, `--env-from-profile`, `--preflight`, and PowerShell `--shell`.
- `crabbox actions hydrate/register` are Linux-only today; use plain
`crabbox run` loops for static macOS and Windows hosts.
- Live proof needs a reachable, operator-managed SSH host. Without one, verify
@@ -144,8 +148,16 @@ blacksmith testbox list
Use these on debugging runs before inventing ad hoc logging:
- `--preflight`: prints run context, workspace mode, SSH target, remote user/cwd,
sudo/apt, Node, pnpm, Docker, and bubblewrap. On `blacksmith-testbox`, this
prints a delegated-unsupported note because the workflow owns setup.
and target-specific tool probes. Defaults cover `git`, `tar`, `node`, `npm`,
`corepack`, `pnpm`, `yarn`, `bun`, `docker`, plus POSIX
`sudo`/`apt`/`bubblewrap` and native Windows
`powershell`/`execution_policy`/`longpaths`/`temp`/`pwsh`. Add
`--preflight-tools node,bun,docker`, `CRABBOX_PREFLIGHT_TOOLS`, or repo
`run.preflightTools` to replace the list. `default` expands built-ins; `none`
prints only the workspace summary. Preflight is diagnostic only; install
toolchains through Actions hydration, images, devcontainer/Nix/mise/asdf, or
the run script. On `blacksmith-testbox`, this prints a delegated-unsupported
note because the workflow owns setup.
- `CRABBOX_ENV_ALLOW=NAME,...`: forwards only listed local env vars for direct
providers and prints `set len=N secret=true` style summaries. On
`blacksmith-testbox`, env forwarding is unsupported; put secrets in the
@@ -154,21 +166,36 @@ Use these on debugging runs before inventing ad hoc logging:
`export NAME=value` / `NAME=value` lines from a local profile without
executing it, then forwards only allowlisted names. `--allow-env` is
repeatable and comma-separated. Profile values override ambient allowlisted
env values for that run.
env values for that run. Direct POSIX, WSL2, and native Windows runs are
supported; delegated providers are not. Crabbox probes the uploaded profile
remotely and prints redacted presence/length metadata before the command.
- `--env-helper <name>`: with `--env-from-profile` on POSIX SSH targets,
persists `.crabbox/env/<name>` and `.crabbox/env/<name>.env` so follow-up
commands on the same lease can run through `./.crabbox/env/<name> <command>`.
Use only on leases you control; the profile stays until cleanup, lease reset,
or `--full-resync`.
- `--script <file>` / `--script-stdin`: upload a local script into
`.crabbox/scripts/` and execute it on the remote box. Shebang scripts execute
directly; scripts without a shebang run through `bash`. Arguments after `--`
become script args.
directly on POSIX; scripts without a shebang run through `bash`. Native
Windows uploads run through Windows PowerShell, and Crabbox appends `.ps1`
when needed. Arguments after `--` become script args.
- `--fresh-pr owner/repo#123|URL|number`: skip dirty local sync and create a
fresh remote checkout of the GitHub PR. Bare numbers use the current repo's
GitHub origin. Add `--apply-local-patch` only when the current local
`git diff --binary HEAD` should be applied on top of that PR checkout.
- `--full-resync` / `--fresh-sync`: reset a stale direct-provider workdir
before syncing. Use after sync fingerprints look wrong, SSH times out before
sync, or rsync watchdog output suggests it. It is redundant with
`--fresh-pr`, incompatible with `--no-sync`, and unsupported by delegated
providers.
- `--capture-stdout <path>` / `--capture-stderr <path>`: write remote streams to
local files and keep binary/noisy output out of retained logs. Parent
directories must already exist. These are direct-provider only.
- `--capture-on-fail`: on non-zero direct-provider exits, downloads
`.crabbox/captures/*.tar.gz` with `test-results`, `playwright-report`,
`coverage`, JUnit XML, and nearby logs. Treat as secret-bearing until reviewed.
- `--keep-on-failure`: leave a failed one-shot lease alive for live debugging
until idle/TTL expiry. Useful on direct providers and delegated one-shots.
- `--timing-json`: final machine-readable timing. Add
`echo CRABBOX_PHASE:install`, `CRABBOX_PHASE:test`, etc. in long shell
commands; direct providers and Blacksmith Testbox both report them as
@@ -180,7 +207,6 @@ Live-provider debug template for direct AWS/Hetzner leases:
mkdir -p .crabbox/logs
pnpm crabbox:run -- --provider aws \
--preflight \
--env-from-profile ~/.profile \
--allow-env OPENAI_API_KEY,OPENAI_BASE_URL \
--timing-json \
--capture-stdout .crabbox/logs/live-provider.stdout.log \
@@ -191,9 +217,10 @@ pnpm crabbox:run -- --provider aws \
```
Do not pass `--capture-*`, `--download`, `--checksum`, `--force-sync-large`, or
`--sync-only` to delegated providers. Also do not pass `--script*` or
`--fresh-pr` there. Crabbox rejects these because the provider owns sync or
command transport.
`--sync-only` to delegated providers. Also do not pass `--script*`,
`--fresh-pr`, `--full-resync`, or `--env-helper` there. Crabbox rejects these
because the provider owns sync or command transport. `--keep-on-failure` is OK
for delegated one-shots when you need to inspect a failed lease.
## Efficient Bug E2E Verification
@@ -206,8 +233,8 @@ 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
- Provider/model/auth bug: prefer true live E2E. Use the configured secret
workflow, 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."
@@ -241,6 +268,8 @@ Keep it efficient:
- Use `--fresh-pr <pr>` when validating an upstream PR in isolation from the
local dirty tree. Add `--apply-local-patch` only when testing a local fixup on
top of that PR.
- Use `--full-resync` before replacing a warmed direct-provider lease when the
remote workdir or sync fingerprint appears stale.
- 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
@@ -336,10 +365,17 @@ Useful WebVNC commands:
```sh
../crabbox/bin/crabbox webvnc --provider hetzner --id <cbx_id-or-slug> --open
../crabbox/bin/crabbox webvnc --provider hetzner --id <cbx_id-or-slug> --daemon --open
../crabbox/bin/crabbox webvnc --provider hetzner --id <cbx_id-or-slug> --status
../crabbox/bin/crabbox webvnc --provider hetzner --id <cbx_id-or-slug> --stop
../crabbox/bin/crabbox screenshot --provider hetzner --id <cbx_id-or-slug> --output desktop.png
../crabbox/bin/crabbox webvnc daemon start --provider hetzner --id <cbx_id-or-slug> --open
../crabbox/bin/crabbox webvnc daemon status --provider hetzner --id <cbx_id-or-slug>
../crabbox/bin/crabbox webvnc daemon stop --provider hetzner --id <cbx_id-or-slug>
../crabbox/bin/crabbox webvnc status --provider hetzner --id <cbx_id-or-slug>
../crabbox/bin/crabbox webvnc reset --provider hetzner --id <cbx_id-or-slug> --open
../crabbox/bin/crabbox desktop doctor --provider hetzner --id <cbx_id-or-slug>
../crabbox/bin/crabbox desktop click --provider hetzner --id <cbx_id-or-slug> --x 640 --y 420
../crabbox/bin/crabbox desktop paste --provider hetzner --id <cbx_id-or-slug> --text "user@example.com"
../crabbox/bin/crabbox desktop key --provider hetzner --id <cbx_id-or-slug> ctrl+l
../crabbox/bin/crabbox artifacts collect --id <cbx_id-or-slug> --all --output artifacts/<slug>
../crabbox/bin/crabbox artifacts publish --dir artifacts/<slug> --pr <number>
```
`desktop launch --webvnc --open` is usually the nicest one-shot: it starts the
@@ -374,7 +410,9 @@ Common Crabbox-only failures:
- Sync/timing bug: add `--debug --timing-json`; capture the final JSON and the
printed Actions URL. Large sync warnings now include top source directories
by file count and a hint to update `.crabboxignore` / `sync.exclude`; inspect
those before reaching for `--force-sync-large`.
those before reaching for `--force-sync-large`. Quiet rsync watchdogs and SSH
timeouts now print `next_action=` hints; follow them, usually `--full-resync`
first and a fresh lease second.
- Cleanup uncertainty: run `blacksmith testbox list` and stop only boxes you
created.
- Testbox queued/capacity pressure: do not convert a broad changed gate or full
@@ -516,7 +554,10 @@ crabbox run --id <lease> --shell -- 'DISPLAY=:99 xdotool search --onlyvisible --
crabbox status --id <id-or-slug> --wait
crabbox inspect --id <id-or-slug> --json
crabbox sync-plan
crabbox history --limit 20
crabbox history --lease <id-or-slug>
crabbox attach <run_id>
crabbox events <run_id> --json
crabbox logs <run_id>
crabbox results <run_id>
crabbox cache stats --id <id-or-slug>

View File

@@ -73,8 +73,9 @@ openclaw logs --follow
tool execution.
- **Worker/dist:** run `pnpm build` when touching workers, dynamic imports,
package exports, lazy runtime boundaries, or published paths.
- **Live keys:** check local `~/.profile` for key presence/length before saying
live proof is blocked. Never print secrets.
- **Live keys:** use the configured secret workflow for missing provider keys
before saying live proof is blocked. Env checks are presence-only; never print
secrets.
## Code Pointers

View File

@@ -42,16 +42,20 @@ Choose the page type before writing:
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.
2. Opening overview: start with a few unheaded sentences that explain what it
is, what it owns, and what it does not own. Do not add a `## Overview`
heading unless the page is itself an overview index.
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.
6. Major subtopics: organize the entity's major concepts, workflows, and
decisions by reader intent. Put each major subtopic under its own heading;
do not wrap them in a generic `## Subtopics` section.
7. Troubleshooting: diagnose common observable failures under an explicit
`## Troubleshooting` heading.
8. Related: link to guides, references, commands, concepts, and adjacent topics.
Topic pages may be longer than quickstarts, but they should not become exhaustive

View File

@@ -56,7 +56,7 @@ Use this skill for Parallels guest workflows and smoke interpretation. Do not lo
- For unpublished targets, pack the candidate on the host, serve the `.tgz` over the harness HTTP server, and point the guest updater at that served package. Prefer `openclaw update --tag http://<host-ip>:<port>/openclaw-<version>.tgz --yes --json`; when channel persistence also matters, pass `--channel <stable|beta>` and set `OPENCLAW_UPDATE_PACKAGE_SPEC` to the same served URL in the guest update environment. The command under test must still be `openclaw update`, not direct npm.
- For unpublished local-fix validation, remember the old baseline updater code still controls the first hop. A fix that lives only in the new updater code cannot change that already-running old process; the served candidate must either keep package/plugin metadata compatible with the baseline host or the baseline itself must include the updater fix.
- For beta/stable verification, resolve the tag immediately before the run (`npm view openclaw@beta version dist.tarball` or `npm view openclaw@latest ...`). Tags can move while a long VM matrix is already running; restart the matrix when the intended prerelease appears after an earlier registry 404/tag-lag check.
- Source Peter's profile in the host shell (`set -a; source "$HOME/.profile"; set +a`) before OpenAI/Anthropic lanes. Do not print profile contents or env dumps; pass provider secrets through the guest exec environment.
- Use the configured secret workflow to inject only the provider keys needed by OpenAI/Anthropic lanes. Do not print secrets or env dumps; pass provider secrets through the guest exec environment.
- Same-guest update verification should set the default model explicitly to `openai/gpt-5.4` before the agent turn and use a fresh explicit `--session-id` so old session model state does not leak into the check.
- The aggregate npm-update wrapper must resolve the Linux VM with the same Ubuntu fallback policy as `parallels-linux-smoke.sh` before both fresh and update lanes. Treat any Ubuntu guest with major version `>= 24` as acceptable when the exact default VM is missing, preferring the closest version match. On Peter's current host today, missing `Ubuntu 24.04.3 ARM64` should fall back to `Ubuntu 25.10`.
- On macOS same-guest update checks, restart the gateway after the npm upgrade before `gateway status` / `agent`; launchd can otherwise report a loaded service while the old process has exited and the fresh process is not RPC-ready yet.

View File

@@ -227,7 +227,9 @@ pnpm openclaw qa manual \
- Treat the concrete Codex model name as user/config input; do not hardcode it in source, docs examples, or scenarios.
- Live QA preserves `CODEX_HOME` so Codex CLI auth/config works while keeping `HOME` and `OPENCLAW_HOME` sandboxed.
- Mock QA should scrub `CODEX_HOME`.
- If Codex returns fallback/auth text every turn, first check `CODEX_HOME`, `~/.profile`, and gateway child logs before changing scenario assertions.
- If Codex returns fallback/auth text every turn, first check `CODEX_HOME`,
relevant secret-backed auth, and gateway child logs before changing
scenario assertions.
- For model comparison, include `codex-cli/<codex-model>` as another candidate in `qa character-eval`; the report should label it as an opaque model name.
## Repo facts

View File

@@ -65,8 +65,8 @@ Use this skill for release and publish-time workflow. Keep ordinary development
stable base version section, for example `v2026.4.20-beta.1` uses
`## 2026.4.20` release notes.
- When any beta or stable release is live, make a best-effort Discord
announcement using Peter's bot token from `.profile`; do not block or roll
back the release if the announcement fails.
announcement using the configured secret workflow; do not block or roll back
the release if the announcement fails.
- When asked to announce on X, use `~/Projects/bird/bird` and follow the
release tweet style below.
@@ -288,13 +288,11 @@ node --import tsx scripts/openclaw-npm-postpublish-verify.ts <published-version>
## Check all relevant release builds
- Always validate the OpenClaw npm release path before creating the tag.
- Source Peter's profile before live release validation so OpenAI and Anthropic
credentials are available without printing secrets:
`set -a; source "$HOME/.profile"; set +a`.
- Use the configured secret workflow before live release validation so OpenAI
and Anthropic credentials are available without printing secrets.
- Parallels validation and any local live model QA for this train must use both
`OPENAI_API_KEY` and `ANTHROPIC_API_KEY`. If either is missing after sourcing
`.profile`, stop before starting those local long lanes and report the
missing key.
`OPENAI_API_KEY` and `ANTHROPIC_API_KEY`. If either cannot be injected, stop
before starting those local long lanes and report the missing key.
- Live credentialed channel QA is the GitHub Actions workflow
`QA-Lab - All Lanes` (`.github/workflows/qa-live-telegram-convex.yml`), not a
local substitute. Dispatch it from Actions against the release tag and wait
@@ -592,8 +590,7 @@ node --import tsx scripts/openclaw-npm-postpublish-verify.ts <published-version>
If a pre-npm lane fails before any tag/package leaves the machine, fix and
rerun the same intended beta attempt. Repeat up to the operator's
authorized beta-attempt limit, normally 4.
24. Announce the beta/stable release on Discord best-effort using Peter's bot
token from `.profile`.
24. Announce the beta/stable release on Discord best-effort using the configured secret workflow.
25. If the operator requested beta only, stop after beta verification and the
announcement.
26. If the stable release was published to `beta`, use the light stable

View File

@@ -28,6 +28,9 @@ OPENCLAW_GATEWAY_TOKEN=
# OPENCLAW_STATE_DIR=~/.openclaw
# OPENCLAW_CONFIG_PATH=~/.openclaw/openclaw.json
# OPENCLAW_HOME=~
# Docker setup stores auth profile encryption key material outside the mounted
# OpenClaw state dir and mounts this host directory into the container.
# OPENCLAW_AUTH_PROFILE_SECRET_DIR=/absolute/path/to/.openclaw-auth-profile-secrets
# Allowlist of extra directories that `$include` directives in openclaw.json may
# resolve files from. Path-list separated (':' on POSIX, ';' on Windows). Each

2
.github/CODEOWNERS vendored
View File

@@ -11,6 +11,8 @@
/.github/workflows/codeql.yml @openclaw/openclaw-secops
/.github/workflows/codeql-android-critical-security.yml @openclaw/openclaw-secops
/.github/workflows/codeql-critical-quality.yml @openclaw/openclaw-secops
/.github/workflows/dependency-change-awareness.yml @openclaw/openclaw-secops
/test/scripts/dependency-change-awareness-workflow.test.ts @openclaw/openclaw-secops
/src/security/ @openclaw/openclaw-secops
/src/secrets/ @openclaw/openclaw-secops
/src/config/*secret*.ts @openclaw/openclaw-secops

88
.github/labeler.yml vendored
View File

@@ -454,3 +454,91 @@
- changed-files:
- any-glob-to-any-file:
- "extensions/gradium/**"
"extensions: amazon-bedrock":
- changed-files:
- any-glob-to-any-file:
- "extensions/amazon-bedrock/**"
"extensions: anthropic-vertex":
- changed-files:
- any-glob-to-any-file:
- "extensions/anthropic-vertex/**"
"extensions: brave":
- changed-files:
- any-glob-to-any-file:
- "extensions/brave/**"
"extensions: chutes":
- changed-files:
- any-glob-to-any-file:
- "extensions/chutes/**"
"extensions: diffs":
- changed-files:
- any-glob-to-any-file:
- "extensions/diffs/**"
"extensions: elevenlabs":
- changed-files:
- any-glob-to-any-file:
- "extensions/elevenlabs/**"
"extensions: firecrawl":
- changed-files:
- any-glob-to-any-file:
- "extensions/firecrawl/**"
"extensions: github-copilot":
- changed-files:
- any-glob-to-any-file:
- "extensions/github-copilot/**"
"extensions: google":
- changed-files:
- any-glob-to-any-file:
- "extensions/google/**"
"extensions: microsoft":
- changed-files:
- any-glob-to-any-file:
- "extensions/microsoft/**"
"extensions: mistral":
- changed-files:
- any-glob-to-any-file:
- "extensions/mistral/**"
"extensions: ollama":
- changed-files:
- any-glob-to-any-file:
- "extensions/ollama/**"
"extensions: opencode":
- changed-files:
- any-glob-to-any-file:
- "extensions/opencode/**"
"extensions: opencode-go":
- changed-files:
- any-glob-to-any-file:
- "extensions/opencode-go/**"
"extensions: openrouter":
- changed-files:
- any-glob-to-any-file:
- "extensions/openrouter/**"
"extensions: openshell":
- changed-files:
- any-glob-to-any-file:
- "extensions/openshell/**"
"extensions: perplexity":
- changed-files:
- any-glob-to-any-file:
- "extensions/perplexity/**"
"extensions: sglang":
- changed-files:
- any-glob-to-any-file:
- "extensions/sglang/**"
"extensions: thread-ownership":
- changed-files:
- any-glob-to-any-file:
- "extensions/thread-ownership/**"
"extensions: vllm":
- changed-files:
- any-glob-to-any-file:
- "extensions/vllm/**"
"extensions: xai":
- changed-files:
- any-glob-to-any-file:
- "extensions/xai/**"
"extensions: zai":
- changed-files:
- any-glob-to-any-file:
- "extensions/zai/**"

View File

@@ -124,5 +124,6 @@ jobs:
- name: Run Testbox
uses: useblacksmith/run-testbox@5ca05834db1d3813554d1dd109e5f2087a8d7cbc
if: always()
continue-on-error: true
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"

View File

@@ -0,0 +1,171 @@
name: Dependency Change Awareness
on:
pull_request_target: # zizmor: ignore[dangerous-triggers] metadata-only workflow; no checkout or untrusted code execution
types: [opened, reopened, synchronize, ready_for_review]
permissions:
pull-requests: write
issues: write
concurrency:
group: dependency-change-awareness-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
dependency-change-awareness:
if: ${{ !github.event.pull_request.draft }}
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- name: Label and comment on dependency changes
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with:
script: |
const marker = "<!-- openclaw:dependency-change-awareness -->";
const labelName = "dependencies-changed";
const maxListedFiles = 25;
const pullRequest = context.payload.pull_request;
if (!pullRequest) {
core.info("No pull_request payload found; skipping.");
return;
}
const isDependencyFile = (filename) =>
filename === "package.json" ||
filename === "pnpm-lock.yaml" ||
filename === "pnpm-workspace.yaml" ||
filename === "ui/package.json" ||
filename.startsWith("patches/") ||
/^packages\/[^/]+\/package\.json$/u.test(filename) ||
/^extensions\/[^/]+\/package\.json$/u.test(filename);
const sanitizeDisplayValue = (value) =>
String(value)
.replace(/[\u0000-\u001f\u007f]/gu, "?")
.slice(0, 240);
const markdownCode = (value) =>
`\`${sanitizeDisplayValue(value).replaceAll("`", "\\`")}\``;
const ignoreUnavailableWritePermission = (action) => (error) => {
if (error?.status === 403) {
core.warning(
`Skipping dependency change ${action}; token does not have issue write permission.`,
);
return;
}
if (error?.status === 404 || error?.status === 422) {
core.warning(`Dependency change ${action} is unavailable.`);
return;
}
throw error;
};
const files = await github.paginate(github.rest.pulls.listFiles, {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pullRequest.number,
per_page: 100,
});
const dependencyFiles = files
.map((file) => file.filename)
.filter((filename) => typeof filename === "string" && isDependencyFile(filename))
.sort((left, right) => left.localeCompare(right));
const comments = await github.paginate(github.rest.issues.listComments, {
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pullRequest.number,
per_page: 100,
});
const existingComment = comments.find(
(comment) =>
comment.user?.login === "github-actions[bot]" && comment.body?.includes(marker),
);
const labels = await github.paginate(github.rest.issues.listLabelsOnIssue, {
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pullRequest.number,
per_page: 100,
});
const hasLabel = labels.some((label) => label.name === labelName);
if (dependencyFiles.length === 0) {
if (hasLabel) {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pullRequest.number,
name: labelName,
}).catch(ignoreUnavailableWritePermission("label removal"));
}
if (existingComment) {
await github.rest.issues.deleteComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existingComment.id,
}).catch(ignoreUnavailableWritePermission("comment deletion"));
}
await core.summary
.addHeading("Dependency Change Awareness")
.addRaw("No dependency-related file changes detected.")
.write();
core.info("No dependency-related file changes detected.");
return;
}
if (!hasLabel) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pullRequest.number,
labels: [labelName],
}).catch(ignoreUnavailableWritePermission(`label "${labelName}" update`));
}
const listedFiles = dependencyFiles.slice(0, maxListedFiles);
const omittedCount = dependencyFiles.length - listedFiles.length;
const fileLines = listedFiles.map((filename) => `- ${markdownCode(filename)}`);
if (omittedCount > 0) {
fileLines.push(`- ${omittedCount} additional dependency-related files not shown`);
}
const body = [
marker,
"",
"### Dependency Changes Detected",
"",
"This PR changes dependency-related files. Maintainers should confirm these changes are intentional.",
"",
"Changed files:",
...fileLines,
"",
"Maintainer follow-up:",
"- Review whether the dependency changes are intentional.",
"- Inspect resolved package deltas when lockfile or workspace dependency policy changes are present.",
"- Run `pnpm deps:changes:report -- --base-ref origin/main --markdown /tmp/dependency-changes.md --json /tmp/dependency-changes.json` locally for detailed release-style evidence.",
].join("\n");
if (existingComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existingComment.id,
body,
}).catch(ignoreUnavailableWritePermission("comment update"));
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pullRequest.number,
body,
}).catch(ignoreUnavailableWritePermission("comment creation"));
}
await core.summary
.addHeading("Dependency Change Awareness")
.addRaw(`Detected ${dependencyFiles.length} dependency-related file change(s).`)
.addList(dependencyFiles.map((filename) => markdownCode(filename)))
.write();
core.notice(`Detected ${dependencyFiles.length} dependency-related file change(s).`);

View File

@@ -297,6 +297,7 @@ jobs:
echo "conclusion=${conclusion}" >> "$GITHUB_OUTPUT"
if [[ "$conclusion" != "success" ]]; then
gh run view "$run_id" --json jobs --jq '.jobs[] | select(.conclusion != "success" and .conclusion != "skipped") | {name, conclusion, url}' || true
exit 1
fi
}
@@ -396,6 +397,7 @@ jobs:
echo "conclusion=${conclusion}" >> "$GITHUB_OUTPUT"
if [[ "$conclusion" != "success" ]]; then
gh run view "$run_id" --json jobs --jq '.jobs[] | select(.conclusion != "success" and .conclusion != "skipped") | {name, conclusion, url}' || true
exit 1
fi
}
@@ -504,6 +506,7 @@ jobs:
echo "conclusion=${conclusion}" >> "$GITHUB_OUTPUT"
if [[ "$conclusion" != "success" ]]; then
gh run view "$run_id" --json jobs --jq '.jobs[] | select(.conclusion != "success" and .conclusion != "skipped") | {name, conclusion, url}' || true
exit 1
fi
}
@@ -726,6 +729,7 @@ jobs:
echo "conclusion=${conclusion}" >> "$GITHUB_OUTPUT"
if [[ "$conclusion" != "success" ]]; then
gh run view "$run_id" --json jobs --jq '.jobs[] | select(.conclusion != "success" and .conclusion != "skipped") | {name, conclusion, url}' || true
exit 1
fi
summary:
@@ -735,62 +739,6 @@ jobs:
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- name: Request private evidence update
env:
RELEASE_PRIVATE_DISPATCH_TOKEN: ${{ secrets.OPENCLAW_RELEASES_PRIVATE_DISPATCH_TOKEN }}
TARGET_REF: ${{ inputs.ref }}
PACKAGE_SPEC: ${{ inputs.evidence_package_spec || inputs.npm_telegram_package_spec }}
GITHUB_RUN_ID_VALUE: ${{ github.run_id }}
RELEASE_CHECKS_RESULT: ${{ needs.release_checks.result }}
run: |
set -euo pipefail
if [[ "$RELEASE_CHECKS_RESULT" == "skipped" ]]; then
echo "Release checks were skipped by rerun group; skipping automatic private evidence update."
exit 0
fi
if [[ -z "${RELEASE_PRIVATE_DISPATCH_TOKEN// }" ]]; then
echo "OPENCLAW_RELEASES_PRIVATE_DISPATCH_TOKEN is not configured; skipping automatic private evidence update."
exit 0
fi
release_id="${TARGET_REF#refs/tags/}"
release_id="${release_id#v}"
if [[ "$PACKAGE_SPEC" =~ ^openclaw@(.+)$ ]]; then
release_id="${BASH_REMATCH[1]}"
fi
release_id="$(printf '%s' "$release_id" | tr '/:@ ' '----' | tr -cd 'A-Za-z0-9._-')"
if [[ -z "$release_id" ]]; then
echo "::error::Could not derive release evidence id from target ref '${TARGET_REF}'."
exit 1
fi
payload="$(
jq -cn \
--arg full_validation_run_id "$GITHUB_RUN_ID_VALUE" \
--arg release_id "$release_id" \
--arg release_ref "$TARGET_REF" \
--arg package_spec "$PACKAGE_SPEC" \
--arg notes "Automatically requested by Full Release Validation ${GITHUB_RUN_ID_VALUE} after child workflows completed; the parent summary re-checks current child run conclusions." \
'{
event_type: "openclaw_full_release_validation_completed",
client_payload: {
full_validation_run_id: $full_validation_run_id,
release_id: $release_id,
release_ref: $release_ref,
package_spec: $package_spec,
notes: $notes
}
}'
)"
curl --fail-with-body \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${RELEASE_PRIVATE_DISPATCH_TOKEN}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/openclaw/releases-private/dispatches \
-d "$payload"
- name: Verify child workflow results
env:
GH_TOKEN: ${{ github.token }}
@@ -969,3 +917,61 @@ jobs:
summarize_child_timing "npm_telegram" "$NPM_TELEGRAM_RUN_ID"
exit "$failed"
- name: Request private evidence update
env:
RELEASE_PRIVATE_DISPATCH_TOKEN: ${{ secrets.OPENCLAW_RELEASES_PRIVATE_DISPATCH_TOKEN }}
TARGET_REF: ${{ inputs.ref }}
PACKAGE_SPEC: ${{ inputs.evidence_package_spec || inputs.npm_telegram_package_spec }}
GITHUB_RUN_ID_VALUE: ${{ github.run_id }}
RELEASE_CHECKS_RESULT: ${{ needs.release_checks.result }}
run: |
set -euo pipefail
if [[ "$RELEASE_CHECKS_RESULT" == "skipped" ]]; then
echo "Release checks were skipped by rerun group; skipping automatic private evidence update."
exit 0
fi
if [[ -z "${RELEASE_PRIVATE_DISPATCH_TOKEN// }" ]]; then
echo "OPENCLAW_RELEASES_PRIVATE_DISPATCH_TOKEN is not configured; skipping automatic private evidence update."
exit 0
fi
release_id="${TARGET_REF#refs/tags/}"
release_id="${release_id#v}"
if [[ "$PACKAGE_SPEC" =~ ^openclaw@(.+)$ ]]; then
release_id="${BASH_REMATCH[1]}"
fi
release_id="$(printf '%s' "$release_id" | tr '/:@ ' '----' | tr -cd 'A-Za-z0-9._-')"
if [[ -z "$release_id" ]]; then
echo "::warning::Could not derive release evidence id from target ref '${TARGET_REF}'; skipping automatic private evidence update."
exit 0
fi
payload="$(
jq -cn \
--arg full_validation_run_id "$GITHUB_RUN_ID_VALUE" \
--arg release_id "$release_id" \
--arg release_ref "$TARGET_REF" \
--arg package_spec "$PACKAGE_SPEC" \
--arg notes "Automatically requested by Full Release Validation ${GITHUB_RUN_ID_VALUE} after child workflows completed; the parent summary re-checks current child run conclusions." \
'{
event_type: "openclaw_full_release_validation_completed",
client_payload: {
full_validation_run_id: $full_validation_run_id,
release_id: $release_id,
release_ref: $release_ref,
package_spec: $package_spec,
notes: $notes
}
}'
)"
if ! curl --fail-with-body \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${RELEASE_PRIVATE_DISPATCH_TOKEN}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/openclaw/releases-private/dispatches \
-d "$payload"; then
echo "::warning::Automatic private release evidence dispatch failed; child workflow validation remains authoritative."
fi

View File

@@ -427,6 +427,7 @@ jobs:
add_profile_suite live-cli-backend-docker "stable full"
add_profile_suite live-acp-bind-docker "stable full"
add_profile_suite live-codex-harness-docker "stable full"
add_profile_suite live-subagent-announce-docker "stable full"
add_profile_suite native-live-extensions-a-k "full"
add_profile_suite native-live-extensions-media-audio "full"
@@ -2291,6 +2292,12 @@ jobs:
timeout_minutes: 40
profile_env_only: false
profiles: stable full
- suite_id: live-subagent-announce-docker
label: Docker live subagent announce
command: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 20m bash .release-harness/scripts/test-live-subagent-announce-docker.sh
timeout_minutes: 25
profile_env_only: false
profiles: stable full
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL }}

View File

@@ -169,12 +169,27 @@ jobs:
- name: Verify release contents
run: pnpm release:check
- name: Generate dependency release evidence
id: dependency_evidence
env:
RELEASE_REF: ${{ inputs.tag }}
RELEASE_NPM_DIST_TAG: ${{ inputs.npm_dist_tag }}
run: |
set -euo pipefail
node scripts/generate-dependency-release-evidence.mjs \
--release-ref "$RELEASE_REF" \
--npm-dist-tag "$RELEASE_NPM_DIST_TAG" \
--output-dir "$RUNNER_TEMP/openclaw-release-dependency-evidence" \
--github-output "$GITHUB_OUTPUT" \
--github-step-summary "$GITHUB_STEP_SUMMARY"
- name: Pack prepared npm tarball
id: packed_tarball
env:
OPENCLAW_PREPACK_PREPARED: "1"
RELEASE_TAG: ${{ inputs.tag }}
RELEASE_NPM_DIST_TAG: ${{ inputs.npm_dist_tag }}
DEPENDENCY_EVIDENCE_DIR: ${{ steps.dependency_evidence.outputs.dir }}
run: |
set -euo pipefail
PACK_OUTPUT="$RUNNER_TEMP/npm-pack-output.txt"
@@ -246,6 +261,7 @@ jobs:
rm -rf "$ARTIFACT_DIR"
mkdir -p "$ARTIFACT_DIR"
cp "$PACK_PATH" "$ARTIFACT_DIR/"
cp -R "$DEPENDENCY_EVIDENCE_DIR" "$ARTIFACT_DIR/dependency-evidence"
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"
@@ -261,6 +277,8 @@ jobs:
packageVersion: process.env.PACKAGE_VERSION,
tarballName: process.env.TARBALL_NAME,
tarballSha256: process.env.TARBALL_SHA256,
dependencyEvidenceDir: "dependency-evidence",
dependencyEvidenceManifest: "dependency-evidence/dependency-evidence-manifest.json",
};
fs.writeFileSync(
path.join(process.env.ARTIFACT_DIR, "preflight-manifest.json"),
@@ -269,6 +287,13 @@ jobs:
NODE
echo "dir=$ARTIFACT_DIR" >> "$GITHUB_OUTPUT"
- name: Upload dependency release evidence
uses: actions/upload-artifact@v7
with:
name: openclaw-release-dependency-evidence-${{ inputs.tag }}
path: ${{ steps.dependency_evidence.outputs.dir }}
if-no-files-found: error
- name: Upload prepared npm publish bundle
uses: actions/upload-artifact@v7
with:

View File

@@ -626,7 +626,7 @@ jobs:
artifact_name: ${{ needs.prepare_release_package.outputs.artifact_name }}
package_sha256: ${{ (needs.resolve_target.outputs.package_acceptance_package_spec == '' && needs.resolve_target.outputs.release_package_spec == '') && needs.prepare_release_package.outputs.package_sha256 || '' }}
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
docker_lanes: doctor-switch update-channel-switch skill-install update-corrupt-plugin upgrade-survivor published-upgrade-survivor root-managed-vps-upgrade 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

View File

@@ -401,6 +401,33 @@ jobs:
echo "- GitHub release: https://github.com/${GITHUB_REPOSITORY}/releases/tag/${RELEASE_TAG}" >> "$GITHUB_STEP_SUMMARY"
}
upload_dependency_evidence_release_asset() {
local release_version download_dir asset_path asset_name
release_version="${RELEASE_TAG#v}"
download_dir="${RUNNER_TEMP}/openclaw-release-dependency-evidence-asset"
asset_name="openclaw-${release_version}-dependency-evidence.zip"
asset_path="${RUNNER_TEMP}/${asset_name}"
rm -rf "${download_dir}" "${asset_path}"
mkdir -p "${download_dir}"
gh run download "${PREFLIGHT_RUN_ID}" \
--repo "${GITHUB_REPOSITORY}" \
--name "openclaw-npm-preflight-${RELEASE_TAG}" \
--dir "${download_dir}"
if [[ ! -d "${download_dir}/dependency-evidence" ]]; then
echo "Dependency evidence is missing from OpenClaw npm preflight artifact." >&2
find "${download_dir}" -maxdepth 2 -type f -print >&2 || true
exit 1
fi
(cd "${download_dir}" && zip -qr "${asset_path}" dependency-evidence)
gh release upload "${RELEASE_TAG}" "${asset_path}#${asset_name}" \
--repo "${GITHUB_REPOSITORY}" \
--clobber
echo "- Dependency evidence asset: \`${asset_name}\`" >> "$GITHUB_STEP_SUMMARY"
}
{
echo "### Publish sequence"
echo
@@ -491,4 +518,5 @@ jobs:
if [[ -n "${openclaw_npm_run_id}" ]]; then
create_or_update_github_release
upload_dependency_evidence_release_asset
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 skill-install 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 root-managed-vps-upgrade update-restart-auth plugins-offline plugin-update"
;;
product)
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"
docker_lanes="npm-onboard-channel-agent doctor-switch update-channel-switch skill-install update-corrupt-plugin upgrade-survivor published-upgrade-survivor root-managed-vps-upgrade update-restart-auth plugins plugin-update mcp-channels cron-mcp-cleanup openai-web-search-minimal openwebui"
include_openwebui=true
;;
full)

View File

@@ -196,7 +196,10 @@ jobs:
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 add public/install.sh public/install-cli.sh public/install.ps1
if git ls-files --error-unmatch public/install.cmd >/dev/null 2>&1; then
git add -u -- public/install.cmd
fi
git commit -m "chore: sync installers from openclaw ${GITHUB_SHA::12}"
git pull --rebase origin main
git push origin HEAD:main

2
.gitignore vendored
View File

@@ -115,6 +115,8 @@ USER.md
!.agents/skills/blacksmith-testbox/**
!.agents/skills/crabbox/
!.agents/skills/crabbox/**
!.agents/skills/clawdtributor/
!.agents/skills/clawdtributor/**
!.agents/skills/gitcrawl/
!.agents/skills/gitcrawl/**
!.agents/skills/openclaw-docs/**

View File

@@ -10,12 +10,12 @@ Skills own workflows; root owns hard policy and routing.
- Docs/user-visible work: `pnpm docs:list`, then read relevant docs only.
- Fix/triage answers need source, tests, current/shipped behavior, and dependency contract proof.
- Dependency-backed behavior: read upstream docs/source/types first. No API/default/error/timing guesses.
- Live-verify when feasible. Check env/`~/.profile` for keys before saying blocked; never print secrets.
- Live-verify when feasible. Never print secrets.
- Missing deps: `pnpm install`, retry once, then report first actionable error.
- CODEOWNERS: maint/refactor/tests ok. Larger behavior/product/security/ownership: owner ask/review.
- Product/docs/UI/changelog wording: "plugin/plugins"; `extensions/` is internal.
- New channel/plugin/app/doc surface: update `.github/labeler.yml` + GH labels.
- New `AGENTS.md`: add sibling `CLAUDE.md` symlink.
- New `AGENTS.md`: add sibling `CLAUDE.md` symlink; edit `AGENTS.md` only.
## Map
@@ -36,6 +36,7 @@ Skills own workflows; root owns hard policy and routing.
- Channels are implementation under `src/channels/**`; plugin authors get SDK seams. Providers own auth/catalog/runtime hooks; core owns generic loop.
- Hot paths should carry prepared facts forward: provider id, model ref, channel id, target, capability family, attachment class. Do not rediscover with broad plugin/provider/channel/capability loaders.
- Do not fix repeated request-time discovery with scattered caches. Move the canonical fact earlier; reuse prepared runtime objects; delete duplicate lookup branches.
- Inline code comments: brief notes for tricky, bug-prone, or previously buggy logic.
- Gateway protocol changes: additive first; incompatible needs versioning/docs/client follow-through.
- Config contract: exported types, schema/help, metadata, baselines, docs aligned. Retired public keys stay retired; compat in raw migration/doctor only.
- Prompt cache: deterministic ordering for maps/sets/registries/plugin lists/files/network results before model/tool payloads. Preserve old transcript bytes when possible.
@@ -66,10 +67,12 @@ Skills own workflows; root owns hard policy and routing.
## GitHub / PRs
- Use `$openclaw-pr-maintainer` immediately for OpenClaw issue/PR URLs/numbers, review, triage, duplicate search, close, labels, landing, comments, or maintainer evidence.
- PR refs: `gh pr view/diff`, not web search. Prefer `gitcrawl` for local candidate discovery; verify live with `gh` before mutation.
- Use `$openclaw-pr-maintainer` immediately for maintainer-side OpenClaw issue/PR review, triage, duplicates, labels, comments, close, land, or evidence. Contributor PR creation/refresh follows the requested contributor workflow; linked refs alone do not require maintainer archive tooling.
- PR refs: `gh pr view/diff` or `gh api`, not web search. Prefer `gitcrawl` for maintainer discovery; missing/stale `gitcrawl` falls through to live `gh`, not contributor setup. Verify live with `gh` before mutation.
- Bare issue/PR URL/number means review/report in chat. Suggest comment/close/merge when appropriate; mutate only when asked.
- No unsolicited PR comments/reviews/labels/retitles/rebases/fixups/landing. Exception: close/duplicate action that needs a reason comment after explicit close/sweep/landing request.
- Maintainer decision closes the cluster: if deciding reported behavior/proposed fix is not planned, comment+close all directly associated open issues/PRs unless explicitly told to keep one open. Associated means linked PRs/issues, duplicates, companion workaround PRs, and the canonical issue for the rejected behavior.
- Do not leave associated issues open for hypothetical future repros. Close with rationale; ask for a new issue or reopen only if concrete new evidence appears. Close comment states: decision, why, supported alternative, and what evidence would change the decision.
- PR review answer: bug/behavior, URL(s), affected surface, best-fix judgment, evidence from code/tests/CI/current or shipped behavior.
- Issue/PR final answer: last line is the full GitHub URL.
- Changelog: PR landings/fixes need one unless pure test/internal. Do not mention missing changelog as a review finding; Codex handles it during fix/landing.
@@ -79,6 +82,7 @@ Skills own workflows; root owns hard policy and routing.
- `ship` that fixes an issue: after push, comment proof + commit link, then close the issue.
- GH comments with backticks, `$`, or shell snippets: use heredoc/body file, not inline double-quoted `--body`.
- PR create: real body required. Include Summary + Verification; mention refs, behavior, and proof.
- Real behavior proof section is parsed. Use exact `field: value` labels: `Behavior addressed`, `Real environment tested`, `Exact steps or command run after this patch`, `Evidence after fix`, `Observed result after fix`, `What was not tested`.
- PR artifacts/screenshots: attach to PR/comment/external artifact store. Do not commit `.github/pr-assets`.
- CI polling: exact SHA, relevant checks only, minimal fields. Skip routine noise (`Auto response`, `Labeler`, docs agents, performance/stale). Logs only after failure/completion or concrete need.
- Maintainers: ignore `Real behavior proof` failures that only say PR body lacks real after-fix evidence.
@@ -134,7 +138,6 @@ Skills own workflows; root owns hard policy and routing.
- Never commit real phone numbers, videos, credentials, live config.
- Secrets: channel/provider creds in `~/.openclaw/credentials/`; model auth profiles in `~/.openclaw/agents/<agentId>/agent/auth-profiles.json`.
- Env keys: check `~/.profile`; redact output.
- Dependency patches/overrides/vendor changes need explicit approval. `pnpm-workspace.yaml` patched dependencies use exact versions only.
- Carbon pins owner-only: do not change `@buape/carbon` unless Shadow (`@thewilloftheshadow`, verified by `gh`) asks.
- Releases/publish/version bumps need explicit approval. Use `$openclaw-release-maintainer`.

View File

@@ -4,19 +4,141 @@ Docs: https://docs.openclaw.ai
## Unreleased
### Changes
- ACP: add `acp.fallbacks` so ACP turns can try configured backup runtime backends when the primary backend is unavailable before any output is emitted. (#69542) Thanks @kaseonedge.
### Fixes
- Sessions/status: classify ACP spawn-child sessions as `kind: "spawn-child"` instead of `"direct"` in `openclaw sessions` and status output; extract the duplicated session-kind classifier into a shared helper (`src/sessions/classify-session-kind.ts`) so both surfaces stay in sync. Fixes catalog #19. (#79544)
- Telegram: delete tool-progress-only draft bubbles before rotating to the real answer, preventing orphaned progress messages in streamed replies.
- Codex app-server: keep per-agent `CODEX_HOME` isolation without rewriting `HOME` by default, so Codex-run subprocesses can still find normal user-home config, tokens, and CLI state unless the launch explicitly overrides `HOME`. Thanks @pashpashpash.
- ACP: preserve redacted numeric JSON-RPC `RequestError` details in runtime failure text, so backend diagnostics are visible instead of only `Internal error`. Fixes #81126. (#81188) Thanks @vyctorbrzezowski.
- Agents: cache unchanged PI model discovery stores and model lookups, reducing repeated model-resolution startup latency under large model configs. Fixes #78851.
- Security/Windows ACL audit: classify Anonymous Logon, Guests, Interactive, Local, and Network SIDs as world-equivalent principals so broadly writable paths stay critical instead of being downgraded to group-writable. Fixes #74350. (#74383) Thanks @dwc1997.
- Media-understanding: retry transient remote attachment fetch failures before audio or vision processing, so Discord voice notes are not lost after one network/CDN blip. Fixes #74316. Thanks @vyctorbrzezowski and @gabrielexito-stack.
- Control UI: order timestamped live stream and tool items before untimestamped history fallbacks, keeping chat history in visible time order. Fixes #80759. (#81016) Thanks @akrimm702.
- iMessage: stop sending visible `<media:image>` placeholder text for media-only native image sends while preserving the internal echo key that prevents self-echo duplicate replies. (#81209) Thanks @homer-byte.
- Agents/sessions: create configured agent main sessions before first `sessions_send` or gateway send, so agent-to-agent messages no longer fail when the target agent has not started yet.
- gateway: pass Talk session scope to resolver [AI]. (#81379) Thanks @pgondhi987.
- Gateway protocol: require v4 clients and stream explicit chat `deltaText`/`replace` frames so SDK clients can consume assistant updates without local diffing. (#80725) Thanks @samzong.
- OpenAI plugin: clarify remote Codex OAuth login copy so tunneled users know sign-in may finish automatically before they paste the redirect URL. (#81301) Thanks @rubencu.
- GitHub Copilot: exchange OAuth tokens for Copilot API tokens on image understanding requests and route Gemini image payloads through Chat Completions, fixing Copilot Gemini image descriptions. (#80393, #80442) Thanks @afunnyhy.
- Gateway: hide pending Node pairing commands, capabilities, and permissions until approval, and refresh the live approved surface when pairings change. (#80741) Thanks @samzong.
- SGLang: preserve replayed reasoning history for OpenAI-compatible chat completions, keeping thinking-capable local models from losing prior reasoning turns. (#81091) Thanks @akrimm702.
- Plugins/Feishu/WhatsApp/Line: enforce inbound media size caps while reading download streams, avoiding full buffering of oversized attachments. (#81044, #81050) Thanks @samzong.
- Plugins/install: limit install-time code safety scans to plugin-owned runtime entrypoints while keeping dependency manifest denylist checks, so trusted packages with large dependency trees no longer get blocked or warned on third-party runtime internals.
- Config: serialize and retry semantic config mutations centrally, so concurrent commands can rebase safe changes instead of clobbering or hand-rolling command-local retry loops. (#76601)
- Require approval for setup-code device pairing [AI]. (#81292) Thanks @pgondhi987.
- Plugins/install: preserve third-party peer dependencies in the managed npm root when later plugin installs or updates recalculate the shared dependency tree. Thanks @shakkernerd.
- Plugins/uninstall: prune managed third-party peer dependencies after their owning npm plugin is removed, without blocking plugin cleanup on peer-prune failures.
- Docker: pin setup-time container paths so stale host `.env` OpenClaw paths cannot leak into Linux containers. Fixes #80381. (#81105) Thanks @brokemac79.
- Channels/WeCom: refresh the official onboarding install to `@wecom/wecom-openclaw-plugin@2026.5.7` and update existing managed npm installs instead of failing on the package directory. Fixes #79884. (#80390) Thanks @brokemac79.
- Control UI/WebChat: keep short assistant replies clear of in-bubble copy/open action buttons by applying the existing reserved action spacing in the grouped chat renderer. Fixes #79509. (#81244) Thanks @JARVIS-Glasses.
- Anthropic: reseed Claude CLI fresh-session retries from bounded OpenClaw transcript history after session rotation, preventing conversation amnesia. Fixes #80905. (#80934) Thanks @bitloi.
- Require explicit browser device pairing [AI]. (#81289) Thanks @pgondhi987.
- Require Control UI pairing before proxy-scoped access [AI]. (#81288) Thanks @pgondhi987.
- Installer: honor `--version` for git installs and install from the checked-in lockfile, preventing recent dependency pins from tripping pnpm's minimum-release-age gate during tag installs.
- Agents: deliver same-process subagent completion handoffs through the in-process agent dispatcher instead of opening a Gateway RPC loopback.
- Harden trusted-proxy source validation [AI]. (#81290) Thanks @pgondhi987.
- Agents: add permissive item schemas to array tool parameters before provider submission, preventing OpenAI-compatible schema validation from rejecting plugin tools that omit `items`. Fixes #81175. (#81217) Thanks @JARVIS-Glasses.
- Agents: escalate LLM idle watchdog timeouts through profile rotation and configured model fallback instead of leaving agent turns stuck after a silent model stream. Fixes #76877. (#80449) Thanks @jimdawdy-hub.
- Discord voice: treat OpenAI Realtime startup auth failures as fatal, suppress duplicate realtime error logs, and stop autoJoin from retrying the same broken voice channel until credentials are fixed.
- ACPX: stop forwarding unsupported timeout config options to Claude ACP while preserving OpenClaw's own turn timeout. (#80812) Thanks @sxxtony.
- Session transcripts: redact sensitive message content in the centralized JSONL append path so CLI turns, gateway transcript injection, transcript mirrors, and guarded tool results use the same configured redaction behavior. Fixes #73565. Refs #73563. (#79645) Thanks @Ziy1-Tan.
- Channels/iMessage: ignore Apple link-preview plugin payload attachments when users paste URLs, keeping the URL text while avoiding phantom media context. (#79374) Thanks @homer-byte.
- Telegram: detect polling stalls from `getUpdates` liveness only, so outbound API calls no longer mask dead inbound polling; log polling-cycle starts after transport rebuilds. Fixes #78473.
- fix(plugins): scan installed dependency runtime code [AI]. (#81066) Thanks @pgondhi987.
- Inherit tool restrictions for delegated sessions [AI]. (#80979) Thanks @pgondhi987.
- Codex harness: make the live test wrapper portable to Windows and defer locked temp cleanup so native Windows and WSL2 live runs complete.
- Telegram: discard legacy long-poll update offsets that cannot be tied to the current bot token, so token rotation no longer leaves bots silently skipping new messages. (#80671) Thanks @sxxtony.
- browser: enforce navigation checks for act interactions [AI]. (#81070) Thanks @pgondhi987.
- Validate node exec event provenance [AI]. (#81071) Thanks @pgondhi987.
- Gateway: keep active reply runs visible to stuck-session diagnostics and clear no-active-work recovery state, preventing stale queued lanes after compaction or tool failures. Fixes #80677. (#81302)
- Codex app-server: rotate incompatible context-engine-managed native threads so Lossless-managed sessions do not resume stale hidden Codex history. (#81223) Thanks @jalehman.
- Codex cron: execute scheduled command-style automation payloads before workspace bootstrap or memory review, preserving existing isolated cron jobs after Codex harness migration. (#81510) Thanks @jalehman.
- Gateway/OpenAI HTTP: return OpenAI-compatible 400 errors for invalid sampling params and provider validation failures instead of collapsing them to 500s. (#81275) Thanks @Lellansin.
- Telegram: publish plugin and skill command description localizations to native command menus while filtering unsupported locale codes and preserving Telegram command limits. (#81351) Thanks @jzakirov.
- Limit hook CLI tool authority [AI]. (#81065) Thanks @pgondhi987.
- Require admin scope for node device token management [AI]. (#81067) Thanks @pgondhi987.
- Restrict chat sender allowlist matching [AI]. (#80898) Thanks @pgondhi987.
- Update: suppress the false newer-config warning during restart health probing after an update handoff, while keeping future-version mutation guards intact. (#78652)
- Sessions: redact persisted tool result detail metadata before writing transcripts so diagnostic secrets do not survive tool output redaction. (#80444) Thanks @nimbleenigma.
- Codex runtime: allow the official installed `@openclaw/codex` package to use its private task-runtime and MCP projection SDK helpers, fixing `MODULE_NOT_FOUND` during migrated OpenAI/Codex beta runs.
- Codex migration: make Enter activate the highlighted checkbox row before continuing, so `Skip for now` and bulk-selection rows work even when planned items start preselected.
- Link understanding: fetch page content through the SSRF guard before running configured CLI summarizers, preventing curl/wget-style link fetchers from reaching private redirect or DNS-rebound targets.
- fix: harden safe-bin argument validation [AI]. (#80999) Thanks @pgondhi987.
- fix: scan plugin runtime entries during install [AI]. (#80998) Thanks @pgondhi987.
- Codex harness: keep auth-profile-backed media tools such as `image_generate` available when OpenAI auth lives in the agent's auth-profile store instead of environment variables.
- Require auth for sandbox browser CDP relay [AI]. (#81002) Thanks @pgondhi987.
- fix: detect carried exec command forms [AI]. (#81000) Thanks @pgondhi987.
- Reject truncated exec approval commands [AI]. (#81001) Thanks @pgondhi987.
- Enforce inline shell wrapper payload matching [AI]. (#80978) Thanks @pgondhi987.
- fix(node-pairing): replace changed pending requests [AI]. (#80894) Thanks @pgondhi987.
- Rate limit Google Chat webhook requests [AI]. (#80974) Thanks @pgondhi987.
- Docker: mount the auth-profile secret key directory so OAuth-backed auth profiles survive container rebuilds. (#80991)
- Onboarding: accept Codex auth profiles for canonical OpenAI model checks, avoiding false missing-auth warnings. (#80913) Thanks @rubencu.
- fix(feishu): normalize webhook rate-limit client keys [AI]. (#80975) Thanks @pgondhi987.
- fix(auth): prevent bootstrap pairing scope changes [AI]. (#80976) Thanks @pgondhi987.
- Validate Control UI loopback retry endpoints [AI]. (#80900) Thanks @pgondhi987.
- Harden exported markdown link rendering [AI]. (#80902) Thanks @pgondhi987.
- fix(gateway): honor minimal discovery mode for wide-area DNS-SD [AI]. (#80903) Thanks @pgondhi987.
- slack: enforce reaction notification policy [AI]. (#80907) Thanks @pgondhi987.
- Enforce gateway command scopes by caller context [AI]. (#80891) Thanks @pgondhi987.
- Telegram/groups: in single-account setups, treat an explicit empty `accounts.<id>.groups: {}` map the same as undefined so the root `channels.telegram.groups` allowlist still applies, instead of silently dropping every group update under the default `groupPolicy: "allowlist"`. Multi-account semantics are unchanged so per-account explicit-empty groups still scope-disable a single account without affecting siblings; the explicit way to block all groups for any account remains `groupPolicy: "disabled"`. Fixes #79427. (#81030) Thanks @kinjitakabe.
- Codex (app-server): project user-configured `mcp.servers` into new Codex thread configs, matching the codex-cli runtime's existing `-c mcp_servers=...` behavior so app-server-runtime agents see the same user MCP servers the CLI runtime already exposes. Plugin-curated apps remain attached via the separate `apps` config patch. Fixes #80814. Thanks @kinjitakabe.
- Enforce Slack plugin approval button authorization [AI]. (#80899) Thanks @pgondhi987.
- Recognize PowerShell -ec inline commands [AI]. (#80893) Thanks @pgondhi987.
- fix(qqbot): authorize approval button callbacks [AI]. (#80892) Thanks @pgondhi987.
- Telegram: render supported HTML tags in streamed and durable replies instead of showing literal markup. (#80977)
- Scrub streamable MCP redirect headers [AI]. (#80906) Thanks @pgondhi987.
- fix(memory-wiki): require admin scope for ingest [AI]. (#80897) Thanks @pgondhi987.
- memory-wiki: require write scope for Obsidian search [AI]. (#80904) Thanks @pgondhi987.
- WhatsApp: externalize the channel as a ClawHub/npm plugin outside the core npm runtime bundle, and bump Baileys to `7.0.0-rc11` so libsignal resolves from the registry instead of a GitHub tarball.
- WhatsApp: keep optional audio decoding dependencies local to the external plugin so the core npm install no longer pulls WhatsApp-only media helpers.
- Build: skip copied metadata for bundled plugins that are excluded from build entries, preventing update/status rebuilds from advertising missing QQ Bot runtime files. (#80925)
- Control UI/sessions: nest subagent sessions under their parent session in the session picker dropdown using a visual `└─ ` prefix, making the parent-child relationship clear. Fixes #77628. (#78623) Thanks @chinar-amrutkar.
- Telegram: limit concurrent startup `getMe` probes across multi-account bots so large Telegram configs do not fan out all account probes at once during gateway startup. Refs #80695. (#80986) Thanks @stainlu.
- fix(config): reject auto-managed meta.lastTouched\* paths in config set/unset (#80856). Thanks @ai-hpc
- Auto-reply: surface a visible error when the configured model backend fails and fallback produces no visible reply, while preserving intentional silent turns and side-effect-only deliveries. (#80917) Thanks @dutifulbob.
- Agents/exec: skip redundant heartbeat wake-ups for subagent session exec completions, preventing spurious LLM invocations on parent sessions. Fixes #66748. (#66749) Thanks @ggzeng.
- Provider streams: keep OpenAI-compatible SSE and JSON fallback streams draining across split chunks and fail Azure Responses streams with a bounded first-event diagnostic instead of stalling. Refs #80926. (#80927) Thanks @galiniliev and @CaptainTimon.
- Agents: rewrite generic provider internal errors with support request IDs into user-friendly transient error copy. (#49401) Thanks @y471823206.
- WhatsApp: finish handling pending debounced inbound messages before closing the socket. (#81246) Thanks @mcaxtr.
- CLI/commitments: write `--json` output to stdout instead of diagnostic logs so automation can parse commitment list and dismiss results. (#81215) Thanks @giodl73-repo.
- Update: allow pnpm GitHub-source OpenClaw updates to approve the OpenClaw package build, so source installs complete their prepare/prepack lifecycle. (#81294) Thanks @fuller-stack-dev.
- Test state: seed isolated auth-profile secret keys for generated homes, preventing helper-backed proof runs from falling back to host Keychain secrets. (#81393) Thanks @altaywtf.
- Plugins/runtime: attribute deprecated runtime config load/write warnings to the plugin id and source that triggered them so logs and plugin doctor runs are actionable. Refs #81394. (#81425) Thanks @BKF-Gitty.
- Plugins/update: clear stale allow/deny entries and selected plugin slots when disabling a plugin after update failure, keeping failed external plugin updates from leaving half-disabled config. (#81512) Thanks @JARVIS-Glasses.
- Memory/LanceDB: make auto-capture recognize short CJK memory phrases and configurable literal triggers, so Chinese, Japanese, and Korean users can capture memories without regex or LLM intent detection. Fixes #75680. Thanks @vyctorbrzezowski and @guokewuming.
- Plugins doctor: report stale plugin config warnings and avoid claiming full plugin health when config warnings remain. (#81515) Thanks @BKF-Gitty.
- Sessions: display `model: "<agentId>-acp"` / `modelProvider: "acpx"` (ACP-runtime sentinel) for ACP control-plane sessions in `openclaw sessions` output, instead of the agent's configured model which was misleading. Catalog finding 20. (#79543)
- Slack: normalize message read `before` and `after` timestamp bounds before calling Slack history or thread reply APIs. Fixes #80835. (#81338) Thanks @honor2030.
### Changes
- Control UI: add a browser-local Text size setting in Appearance and Quick Settings, scaling chat and dense UI text while keeping inputs above the mobile Safari focus-zoom threshold. Fixes #8547. Thanks @BunsDev.
- Docs: add a dedicated ds4 provider page with local DeepSeek V4 Flash config, on-demand startup, context sizing, and live verification steps.
- Release validation: add a package-installed Docker user-journey lane that verifies onboarding, mocked model setup, external plugin install/uninstall, ClickClack outbound/inbound messaging, Gateway restart survival, and doctor.
- Release validation: add package-installed Docker lanes for real TTY onboarding, media and memory persistence, published-package upgrade journeys, and local marketplace plugin install/update/uninstall coverage.
- Maintainers: add a Clawdtributor skill for Discrawl-backed contributor PR triage, live status checks, and compact review formatting.
- Telegram: support Mini App `web_app` buttons in generic message presentation payloads, allowing `openclaw message send --presentation` to render Telegram Web App inline buttons for private chats. (#81356) Thanks @jzakirov.
- Scripts: add `OPENCLAW_HEAVY_CHECK_LOCK_SCOPE=worktree` so high-capacity local worktrees can use independent heavy-check locks while shared locks remain the default. Fixes #80729. (#80734) Thanks @samzong.
- Agents/subagents: deliver native `sessions_spawn` tasks in the child session's first visible `[Subagent Task]` message instead of hiding the task in the sub-agent system prompt, keeping delegation auditable without duplicating tokens. Fixes #78592. Thanks @bradestes and @stainlu.
- Messages/queue: make mid-turn prompts steer active runs by default via `/queue steer`, preserve `/queue followup` and `/queue collect` for users who want messages to queue by default, and make `/steer` continue as a normal prompt when steering is unavailable. (#77023) Thanks @fuller-stack-dev.
- Voice Call/Telnyx: add realtime media-streaming call support for conversational voice calls. (#81024) Thanks @dynamite-bud.
- Gateway/OpenAI HTTP: honor `max_completion_tokens` and `max_tokens` on inbound `/v1/chat/completions` requests so client-provided token caps reach the upstream provider via `streamParams.maxTokens`, with `max_completion_tokens` taking precedence when both are sent. Thanks @Lellansin.
- Models/OpenAI CLI auth: make `openclaw models auth login --provider openai` start the ChatGPT/Codex account login by default, while `--method api-key` remains the explicit OpenAI API-key setup path.
- Google/Gemini: normalize retired Gemini 3 Pro Preview ids inside explicit SDK OAuth auth-result config patches, so provider helpers emit `google/gemini-3.1-pro-preview` for Gemini 3.1 testing.
- Google/Gemini: normalize retired Gemini 3 Pro Preview ids inside SDK OAuth auth-result default config patches, so helper-built provider auth flows emit `google/gemini-3.1-pro-preview` for Gemini 3.1 testing.
- Google/Gemini: normalize retired Gemini 3 Pro Preview ids returned by direct `openclaw models auth login --set-default` provider auth flows before writing config, so Gemini testing targets `google/gemini-3.1-pro-preview`.
- Google/Gemini: normalize retired Gemini 3 Pro Preview ids in per-agent config defaults and auth patches, so agent-specific emitted config keeps targeting `google/gemini-3.1-pro-preview`.
- Google/Gemini: normalize retired Gemini 3 Pro Preview ids in provider catalog rows when API-key onboarding only reapplies the agent default, so emitted config keeps testing `google/gemini-3.1-pro-preview`.
- Google/Gemini: normalize retired Gemini 3 Pro Preview ids in `config set` mutation output for agent overrides and provider catalog rows, so current config emits `google/gemini-3.1-pro-preview`.
- Google/Gemini: canonicalize provider-qualified retired Gemini 3 Pro Preview refs during Google forward-compatible model resolution, so emitted config uses `google/gemini-3.1-pro-preview` for Gemini 3.1 testing.
- Google/Gemini: normalize proxy-prefixed retired Gemini 3 Pro Preview catalog rows, so emitted configs use `google/gemini-3.1-pro-preview` for Gemini 3.1 testing.
- Google/Gemini: normalize retired Gemini 3 Pro Preview ids inside per-agent model overrides before writing config, so agent-specific config emits `google/gemini-3.1-pro-preview` for Gemini 3.1 testing.
- Google/Gemini: normalize retired Gemini 3 Pro Preview ids in subagent, heartbeat, compaction, and subagent-tool model config during writes, so current config keeps emitting `google/gemini-3.1-pro-preview`.
- Docs/subagents: document `agents.defaults.subagents.announceTimeoutMs` in the sub-agent and configuration references. (#75509) Thanks @akrimm702.
- Cron: add direct `cron.get`, `openclaw cron get <id>`, and agent-tool `get` support for inspecting one stored cron job by id. (#75117) Thanks @samzong.
- Agents/tools: add per-sender tool policies with canonical channel-scoped sender keys, so operators can restrict dangerous tools by requester identity across global, agent, group, core, bundled, and plugin tool surfaces. (#66933) Thanks @JerranC.
@@ -66,6 +188,7 @@ Docs: https://docs.openclaw.ai
- Dependencies: refresh workspace pins and patch targets, including ACPX `@agentclientprotocol/claude-agent-acp` `0.33.1`, Codex ACP `0.14.0`, Baileys `7.0.0-rc10`, Google GenAI `2.0.1`, OpenAI `6.37.0`, AWS SDK `3.1045.0`, Kysely `0.29.0`, Tlon skill `0.3.6`, Aimock `1.19.5`, and tsdown `0.22.0`.
- Dependencies: refresh workspace pins for Anthropic SDK, Smithy shared ini loading, Playwright, YAML, Aimock, TypeScript native preview, Vitest, Oxlint/Oxfmt, Vite, and pnpm 11.1.0.
- Dependencies: hard-pin non-peer direct dependency specs across bundled packages and add a changed-check guard so runtime installs resolve the exact versions tested by maintainers.
- Dependencies: add release dependency evidence reports, npm advisory gating, and PR dependency-change awareness so maintainers can review dependency risk before and during releases. Thanks @joshavant.
- Dependencies: move embedded Pi packages to the `@earendil-works` namespace, refresh Twitch Twurple packages, and move `@openclaw/fs-safe` from the GitHub release pin to the published npm package.
- Build: route Testbox changed-check delegation through Crabbox and remove the OpenClaw-specific Blacksmith Testbox helper scripts.
- Agents/compaction: preserve scoped background exec/process session references across embedded compaction and after-turn runtime contexts without exposing sessions from unrelated scopes. Fixes #79284. (#79307) Thanks @TurboTheTurtle.
@@ -78,17 +201,24 @@ Docs: https://docs.openclaw.ai
- Plugin SDK/media-understanding: add `extractStructuredWithModel(...)` plus the optional provider-side `extractStructured(...)` seam so trusted plugins can run bounded image-first structured extraction with optional supplemental text context through provider-owned runtimes such as Codex.
- Exec approvals: add `tools.exec.commandHighlighting` so parser-derived command highlighting in approval prompts can be enabled globally or per agent. (#79348) Thanks @jesse-merhi.
- Codex app-server: mirror native Codex subagent spawn lifecycle events into Task Registry so app-server child agents appear in task/status surfaces without relying on transcript text. (#79512) Thanks @mbelinky.
- Gateway: expose optional `isHeartbeat` metadata on agent event payloads so clients can distinguish scheduled heartbeat runs from ordinary chat runs. (#80610) Thanks @medns.
- Agents: add `agents.defaults.runRetries` and `agents.list[].runRetries` config for embedded Pi runner retry loop limits. (#80661) Thanks @medns.
### Fixes
- Agents/heartbeat: fix seven layered issues that broke multi-agent heartbeat cadence — (1) fan out the scheduler broadcast wake across agents in parallel via `Promise.all` instead of awaiting each `runOnce` sequentially, so one agent doing real work no longer starves every later agent in iteration order; (2) scope `skipWhenBusy` to lanes attributable to the firing agent via session-key parsing of `session:agent:<id>:…` / `nested:agent:<id>:…` lane names, instead of consulting the global `subagent` lane, so a single stuck subagent on one agent no longer silently disables every other agent's heartbeat; (3) always append workspace `HEARTBEAT.md` directives (everything outside an optional `tasks:` block) to the dispatch prompt, so prose-runbook `HEARTBEAT.md` files reach the model directly instead of being silently dropped unless periodic tasks are declared; (4) race the initial stream-establishment promise inside `streamWithIdleTimeout` against the same watchdog timer that previously only guarded inter-token gaps, so SDK requests stuck at TCP/TLS handshake or before the first response byte no longer hang indefinitely (the stalled-session diagnostic's `recovery=none` case); (5) emit an `openclaw doctor` warning when `heartbeat.session` pins a session key that has no entry in the agent's session store, so silently-dropped heartbeat deliveries surface at config-validation time; (6) also route the commitment-only task dispatch path (tasks configured, none due) through `appendHeartbeatFileDirectives` so prose directives outside the `tasks:` block reach the model on this path as well; (7) wrap the synchronous `baseFn(...)` invocation inside `streamWithIdleTimeout` in a try/catch that clears the connect watchdog timer before rethrowing, so a provider stream function that throws during setup no longer leaves a live timer that can fire `onIdleTimeout` later with a stale error and keep the process open past the real failure. Thanks @zeroaltitude.
- Matrix: stop running `npm install`/`pnpm install` at runtime from a parent-derived plugin path; missing Matrix runtime dependencies now fail with repair guidance instead of mutating the wrong `node_modules` tree. Fixes #80758. (#80876) Thanks @kinjitakabe.
- CLI/media: render terminal QR codes with full-block characters by default so the bundled `qrcode` terminal renderer does not emit a pathologically dense ANSI final row in compact half-block mode that breaks scanning in some terminals. Fixes #77820. Thanks @KrasimirKralev.
- Agents/compaction: read post-compaction AGENTS.md refresh context from the queued run workspace instead of the runner process cwd, so CLI-backed follow-up turns re-inject the correct workspace startup rules after compaction. Fixes #70541. (#75532) Thanks @vyctorbrzezowski.
- Agents/read tool: treat positive offsets beyond EOF as empty ranges instead of surfacing the upstream read error, so stale pagination cursors no longer crash tool calls while unrelated read failures still fail loud. Fixes #62466. (#75536) Thanks @vyctorbrzezowski.
- Agents/memory-flush: surface non-abort memory-flush failures (provider timeout, transport error, generic agent failure) as visible reply payloads so the outer reply loop short-circuits and isolated cron runs propagate the error into `meta.error` instead of completing silently with `status: "ok"` and an empty payload. Previously only the specific "Memory flush writes are restricted to ..." message was surfaced. Fixes #80755. Thanks @nailujac.
- Google/Gemini: normalize retired Gemini 3 Pro Preview refs left in Google API-key onboarding model allowlists and fallbacks, so setup-emitted config keeps testing `google/gemini-3.1-pro-preview` instead of `google/gemini-3-pro-preview`.
- Telegram/context: bound selected topic context to the active session so messages from before `/new` or `/reset` are not replayed into later turns. (#80848) Thanks @VACInc.
- Google/Gemini: normalize retired nested Gemini 3 Pro Preview ids when resolving exact configured proxy-provider refs, so `kilocode/google/gemini-3-pro-preview` resolves to `kilocode/google/gemini-3.1-pro-preview` for Gemini 3.1 testing.
- CLI: strip generic OSC terminal escape payloads from sanitized output fields, preventing clipboard/title escape bodies from leaking into commitment tables and other terminal-safe text. Thanks @shakkernerd.
- Codex app-server: match connector-backed plugin approval elicitations by stable connector id so enabled destructive actions no longer fall through to display-name-only rejection.
- Build: replace selected build utility `tsx` preloads with Node native type stripping so Node 26 build paths no longer emit `DEP0205` module loader deprecation warnings. (#78584) Thanks @keshavbotagent.
- Channels/loop-guard: enforce shared per-pair bot loop protection in the core channel-turn kernel, with Discord, Slack, Matrix, and Google Chat supplying bot-pair facts where they can reliably identify accepted bot-authored messages. The generic guard keys on `(scope, conversation, participant pair)`, suppresses every additional bot-to-bot event in either direction once a pair crosses the configured budget, and lifts suppression after `cooldownSeconds`. Defaults are `maxEventsPerWindow: 20`, `windowSeconds: 60`, and `cooldownSeconds: 60` whenever a channel lets bot-authored messages reach dispatch; they can be set globally via `channels.defaults.botLoopProtection` and overridden per channel/account or supported per-conversation config. Fixes #58789. Thanks @pandadev66.
- Media generation: honor configured music and video generation timeouts when tool calls omit `timeoutMs`, matching image generation behavior. (#80687)
- CLI/update/status: label beta-channel plugin fallback and model-pricing refresh failures as warnings, keeping mixed beta/latest plugin cohorts visible without making core update or Gateway reachability look failed. Fixes #80689. Thanks @BKF-Gitty.
- Doctor/plugins: relink managed npm plugin `openclaw` peer dependencies during `doctor --fix`, while refusing to follow package-local `node_modules` symlinks outside the plugin package. (#77412) Thanks @TheCrazyLex.
@@ -203,6 +333,7 @@ Docs: https://docs.openclaw.ai
- System events: dedupe keyed events across the queue while preserving unkeyed, delivery-route, and trust-boundary event identity. (#73040) Thanks @statxc.
- Agents/UI: compact exec and tool progress rows by hiding redundant shell tool names, replacing known workspace paths with short context markers, and preserving Discord trace scrubbing for compact command lines.
- ACPX: run and await the embedded ACP backend startup probe by default so the gateway `ready` signal no longer fires before the acpx runtime has either become usable or reported a probe failure; set `OPENCLAW_ACPX_RUNTIME_STARTUP_PROBE=0` to restore lazy startup. Fixes #79596. Thanks @bzelones.
- Agents/memory-flush: surface non-abort memory-flush failures (provider timeout, transport error, generic agent failure) as visible reply payloads so the outer reply loop short-circuits and isolated cron runs propagate the error into `meta.error` instead of completing silently with `status: "ok"` and an empty payload. Previously only the specific "Memory flush writes are restricted to ..." message was surfaced. Refs #80755. Thanks @kinjitakabe and @nailujac.
- Gateway/status: surface model-pricing bootstrap and refresh failures as degraded health/status warnings while keeping Gateway liveness healthy. Fixes #79599. Thanks @bzelones.
- OpenAI-compatible models: strip prior assistant reasoning fields from replayed Chat Completions history by default, preventing oMLX/vLLM Qwen follow-up turns from rejecting or stalling on stale `reasoning` payloads. Fixes #46637. Thanks @zipzagster and @lexhoefsloot.
- CLI/onboarding: give non-Azure custom providers a safe generated context window and heal legacy 4k wizard entries without overwriting explicit valid small model limits, preventing first-turn compaction loops. Fixes #79428. (#79911) Thanks @Jefsky.
@@ -221,6 +352,7 @@ Docs: https://docs.openclaw.ai
- Control UI/config: remove plugin allowlist entries that the form auto-added when a plugin enable toggle is reverted before saving, so reverting the visible toggle clears dirty state without persisting unintended allowlist changes. (#78329) Thanks @samzong.
- Gateway/mobile: reuse bootstrap-issued device-token scopes on handoff reconnects and surface device-token scope mismatches separately from token mismatches while preserving full shared-token dashboard/native sessions. Fixes #79292. Thanks @BunsDev.
- Media/host-read: allow buffer-verified gzip, tar, and 7z archives in the shared host-local media validator alongside ZIP and document attachments.
- Plugins/install: retry managed npm plugin installs without npm alias overrides after npm's `Invalid comparator: npm:` failure, so older npm versions can install official plugins instead of aborting. (#80539) Thanks @rubencu.
- Plugins/doctor: invalidate persisted plugin registry snapshots when plugin diagnostics point at deleted source paths, so `openclaw doctor` stops repeating stale warnings after a local extension is replaced by a managed npm plugin. Fixes #80087. (#80134) Thanks @hclsys.
- Doctor/OpenAI Codex: preserve Codex auth intent when auto-repairing legacy `openai-codex/*` model refs to canonical `openai/*` by adding provider/model-scoped Codex runtime policy, preventing repaired configs from falling through to direct OpenAI API-key auth. Fixes #78533 and #78570. Thanks @superck110 and @Azmodump.
- CLI/agents: surface durable message delivery status from `sendDurableMessageBatch` in `deliverAgentCommandResult` and `openclaw agent --json --deliver`, preserving suppressed hook outcomes as terminal no-retry results while exposing partial and failed sends for automation. Supersedes #53961 and #57755. Thanks @Kaspre.
@@ -322,6 +454,7 @@ Docs: https://docs.openclaw.ai
- Agents: abort generic repeated no-progress tool loops at the critical threshold when identical calls keep returning identical outcomes. (#80668) Thanks @frankekn.
- Exec approvals: omit generated command highlights for non-POSIX Windows and shell-wrapper approval commands until those command languages have native highlighting support. (#80566) Thanks @jesse-merhi.
- Telegram: keep verbose tool progress and result drafts separate from the final assistant answer so tool output no longer blends into the final Telegram message. (#80294) Thanks @jalehman.
- Plugin SDK/Windows: enable the native require fast path for root `openclaw/plugin-sdk` dist aliases instead of forcing Jiti transforms. (#80878) Thanks @medns.
## 2026.5.9
@@ -374,6 +507,7 @@ Docs: https://docs.openclaw.ai
- Telegram/streaming: continue over-limit draft previews in a new message instead of stopping when rendered preview text crosses Telegram's message limit. (#74508) Thanks @anagnorisis2peripeteia.
- Slack: route handled top-level channel turns in implicit-conversation channels to thread-scoped sessions when Slack reply threading is enabled, keeping the root turn and later thread replies on one OpenClaw session. (#78522) Thanks @zeroth-blip.
- Telegram: re-probe the primary fetch transport after repeated sticky fallback success so transient IPv4 or pinned-IP fallback promotion can recover without a gateway restart. Fixes #77088. (#77157) Thanks @MkDev11.
- Agents/harness: skip tool-result middleware validation when no handler is registered, and sanitize incoming tool result `details` (functions, symbols, bigints, cycles, oversized payloads) before middleware sees them. Tool emitters legitimately produce raw dependency payloads on `details`, and the harness owes any registered middleware a JSON-safe view of that payload; otherwise a no-op middleware (e.g. bundled `tokenjuice` on the `pi` runtime) causes the validator to reject every tool result and silently substitute a failure sentinel, dropping outbound Discord messages, exec output, cron results, and any other tool whose payload carries non-serializable values. Thanks @solomonneas.
- Runtime/install: raise the supported Node 22 floor to `22.16+` so native SQLite query handling can rely on the `node:sqlite` statement metadata API while continuing to recommend Node 24. (#78921)
- Discord/voice: make duplicate same-guild auto-join entries resolve to the last configured channel so moving an agent between voice channels does not keep joining the stale channel.
- Discord/voice: add realtime `/vc` modes so Discord voice channels can run as STT/TTS, a realtime talk buffer with the OpenClaw agent brain, or a bidi realtime session with `openclaw_agent_consult`.
@@ -579,7 +713,7 @@ Docs: https://docs.openclaw.ai
- Control UI/chat: hide retired and non-public Google Gemini model IDs from chat model catalogs and route the bare `gemini-3-pro` alias to Gemini 3.1 Pro Preview instead of the shut-down Gemini 3 Pro Preview. Thanks @BunsDev.
- CLI/infer: canonicalize case-only catalog model refs in `infer model run --model` so mixed-case provider/model strings resolve to the canonical catalog entry instead of failing with `Unknown model`. (#78940) Thanks @ai-hpc.
- CLI/infer: allow explicit local `infer model run --model <provider/model>` probes to use exact bundled static catalog rows before the provider is written to config, surfacing missing credentials as auth errors instead of `Unknown model`.
- CLI/install: refuse state-mutating OpenClaw CLI runs as root by default, keep an explicit `OPENCLAW_ALLOW_ROOT=1` escape hatch for intentional root/container use, and update DigitalOcean setup guidance to run OpenClaw as a non-root user. Fixes #67478. Thanks @Jerry-Xin and @natechicago.
- CLI/install: revert the beta-only global root-refusal guard so existing root-managed VPS installs keep working; the DigitalOcean split-brain protection will move to a narrower image/install-specific path. Refs #67478 and #67509. Thanks @vincentkoc.
- Auto-reply/media: resolve `scp` from `PATH` when staging sandbox media so nonstandard OpenSSH installs can copy remote attachments.
- Agents/PI: route PI-native OpenAI-compatible default streams through OpenClaw boundary-aware transports so local-compatible model runs keep API-key injection and transport policy.
- Gateway/media: require authenticated owner or admin context for managed outgoing image bytes instead of trusting requester-session headers.
@@ -659,6 +793,7 @@ Docs: https://docs.openclaw.ai
- Discord/groups: tell Discord-channel agents to wrap bare URLs as `<https://example.com>` so link previews do not expand into uninvited embeds. (#78614)
- Agents/fallback: fail fast on session write-lock timeouts instead of trying fallback models for local file contention. Fixes #66646. Thanks @sallyom.
- Browser/SSRF: stop closing user-owned Chrome tabs when a read-only operation (snapshot/screenshot/interactions) is rejected by the SSRF guard — only OpenClaw-initiated navigations now close on policy denial. Thanks @scotthuang.
- iMessage: stage native inbound attachments into OpenClaw-managed media and convert HEIC/HEIF images to JPEG before dispatch, so image tools can read photos sent over native iMessage without requiring BlueBubbles.
- Agents/Gateway: throttle and cap live exec command-output events so noisy tool runs cannot flood Gateway WebSocket clients or starve RPC handling. (#78645) Thanks @joshavant.
- Memory Wiki: skip empty and whitespace-only source pages when refreshing generated Related blocks, preventing blank pages from being rewritten into Related-only stubs. Fixes #78121. Thanks @amknight.
- Telegram: keep duplicate message-tool-only Codex turns from posting generic silent-reply fallback text, so private finals stay private after inbound dedupe. Thanks @rubencu.
@@ -2065,6 +2200,7 @@ Docs: https://docs.openclaw.ai
- QQBot: unify slash command auth and c2cOnly gating in the command registry, pass `allowQQBotDataDownloads` when sending slash command file attachments, align clear-storage with actual downloads directory, and add `/bot-me` to display sender user ID. (#73616) Thanks @cxyhhhhh.
- CLI/agents/status: keep `openclaw agents`, text `agents list`, and plain text `status` on read-only metadata paths so human output no longer preloads plugin runtimes or live channel scans before printing. Fixes #74195. Thanks @NianJiuZst.
- Agents/local models: derive context-window guard thresholds from the effective model window with 4k/8k safety floors, so small local models are no longer rejected by fixed 16k/32k preflight cutoffs. Fixes #42999. Thanks @chengjialu8888.
- Providers/media: retry transient provider 5xx, timeout, and selected network failures on the same API key for opted-in media and Google embedding calls while preserving 429 key rotation. Fixes #60422. Thanks @sqsge.
- PDF extraction: resolve PDF.js standard fonts from the installed package root and pass a filesystem path to the Node fallback extractor, so built-in font PDFs render without `file://` URL lookup failures. Fixes #51455; carries forward #70936, #54447, and #62175. Thanks @anyech, @JuanRdBO, and @solomonneas.
- Media: treat legacy Word/OLE attachments with `application/msword` or `application/x-cfb` MIME as binary so printable-looking `.doc` files are not embedded into prompts as text. Fixes #54176; carries forward #54380. Thanks @andyliu.
- Config: accept documented `browser.tabCleanup` keys in strict root config validation, so configured tab cleanup no longer fails before runtime reads it. Fixes #74577. Thanks @lonexreb and @ezdlp.

View File

@@ -1612,15 +1612,6 @@ internal fun resolveOperatorSessionConnectAuth(
)
}
val explicitBootstrapToken = auth.bootstrapToken?.trim()?.takeIf { it.isNotEmpty() }
if (explicitBootstrapToken != null) {
return NodeRuntime.GatewayConnectAuth(
token = null,
bootstrapToken = explicitBootstrapToken,
password = null,
)
}
return null
}

View File

@@ -1,4 +1,4 @@
package ai.openclaw.app.gateway
const val GATEWAY_PROTOCOL_VERSION = 4
const val GATEWAY_MIN_PROTOCOL_VERSION = 3
const val GATEWAY_MIN_PROTOCOL_VERSION = 4

View File

@@ -64,6 +64,7 @@ data class GatewayConnectErrorDetails(
val code: String?,
val canRetryWithDeviceToken: Boolean,
val recommendedNextStep: String?,
val pauseReconnect: Boolean? = null,
val reason: String? = null,
)
@@ -736,6 +737,7 @@ class GatewaySession(
code = it["code"].asStringOrNull(),
canRetryWithDeviceToken = it["canRetryWithDeviceToken"].asBooleanOrNull() == true,
recommendedNextStep = it["recommendedNextStep"].asStringOrNull(),
pauseReconnect = it["pauseReconnect"].asBooleanOrNull(),
reason = it["reason"].asStringOrNull(),
)
}
@@ -1040,20 +1042,17 @@ class GatewaySession(
detailCode == "AUTH_TOKEN_MISMATCH"
}
private fun shouldPauseReconnectAfterAuthFailure(error: ErrorShape): Boolean =
when (error.details?.code) {
"AUTH_TOKEN_MISSING",
"AUTH_BOOTSTRAP_TOKEN_INVALID",
"AUTH_PASSWORD_MISSING",
"AUTH_PASSWORD_MISMATCH",
"AUTH_RATE_LIMITED",
"PAIRING_REQUIRED",
"CONTROL_UI_DEVICE_IDENTITY_REQUIRED",
"DEVICE_IDENTITY_REQUIRED",
-> true
"AUTH_TOKEN_MISMATCH" -> deviceTokenRetryBudgetUsed && !pendingDeviceTokenRetry
else -> false
}
private fun shouldPauseReconnectAfterAuthFailure(error: ErrorShape): Boolean {
val target = desired
return shouldPauseGatewayReconnectAfterAuthFailure(
error = error,
hasBootstrapToken = target?.bootstrapToken?.trim()?.isNotEmpty() == true,
role = target?.options?.role,
scopes = target?.options?.scopes ?: emptyList(),
deviceTokenRetryBudgetUsed = deviceTokenRetryBudgetUsed,
pendingDeviceTokenRetry = pendingDeviceTokenRetry,
)
}
private fun shouldClearStoredDeviceTokenAfterRetry(error: ErrorShape): Boolean = error.details?.code == "AUTH_DEVICE_TOKEN_MISMATCH"
@@ -1068,6 +1067,36 @@ class GatewaySession(
}
}
internal fun shouldPauseGatewayReconnectAfterAuthFailure(
error: GatewaySession.ErrorShape,
hasBootstrapToken: Boolean,
role: String?,
scopes: List<String>,
deviceTokenRetryBudgetUsed: Boolean,
pendingDeviceTokenRetry: Boolean,
): Boolean =
when (error.details?.code) {
"AUTH_TOKEN_MISSING",
"AUTH_BOOTSTRAP_TOKEN_INVALID",
"AUTH_PASSWORD_MISSING",
"AUTH_PASSWORD_MISMATCH",
"AUTH_RATE_LIMITED",
"CONTROL_UI_DEVICE_IDENTITY_REQUIRED",
"DEVICE_IDENTITY_REQUIRED",
-> true
"PAIRING_REQUIRED" ->
!(
hasBootstrapToken &&
role?.trim() == "node" &&
scopes.isEmpty() &&
error.details.reason == "not-paired" &&
(error.details.pauseReconnect == false ||
error.details.recommendedNextStep == "wait_then_retry")
)
"AUTH_TOKEN_MISMATCH" -> deviceTokenRetryBudgetUsed && !pendingDeviceTokenRetry
else -> false
}
internal fun buildGatewayWebSocketUrl(
host: String,
port: Int,

View File

@@ -29,14 +29,14 @@ import java.util.UUID
@Config(sdk = [34])
class GatewayBootstrapAuthTest {
@Test
fun connectsOperatorSessionWhenOnlyBootstrapAuthExists() {
assertTrue(
fun doesNotConnectOperatorSessionWhenOnlyBootstrapAuthExists() {
assertFalse(
shouldConnectOperatorSession(
NodeRuntime.GatewayConnectAuth(token = "", bootstrapToken = "bootstrap-1", password = ""),
storedOperatorToken = "",
),
)
assertTrue(
assertFalse(
shouldConnectOperatorSession(
NodeRuntime.GatewayConnectAuth(token = null, bootstrapToken = "bootstrap-1", password = null),
storedOperatorToken = null,
@@ -84,17 +84,14 @@ class GatewayBootstrapAuthTest {
}
@Test
fun resolveOperatorSessionConnectAuthUsesBootstrapWhenNoStoredOperatorTokenExists() {
fun resolveOperatorSessionConnectAuthIgnoresBootstrapWhenNoStoredOperatorTokenExists() {
val resolved =
resolveOperatorSessionConnectAuth(
auth = NodeRuntime.GatewayConnectAuth(token = null, bootstrapToken = "bootstrap-1", password = null),
storedOperatorToken = null,
)
assertEquals(
NodeRuntime.GatewayConnectAuth(token = null, bootstrapToken = "bootstrap-1", password = null),
resolved,
)
assertNull(resolved)
}
@Test
@@ -174,7 +171,7 @@ class GatewayBootstrapAuthTest {
assertEquals("fp-1", prefs.loadGatewayTlsFingerprint(endpoint.stableId))
assertEquals("setup-bootstrap-token", desiredBootstrapToken(runtime, "nodeSession"))
assertEquals("setup-bootstrap-token", desiredBootstrapToken(runtime, "operatorSession"))
assertNull(desiredBootstrapToken(runtime, "operatorSession"))
}
@Test

View File

@@ -0,0 +1,116 @@
package ai.openclaw.app.gateway
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
class GatewaySessionReconnectTest {
@Test
fun bootstrapNodePairingRequiredKeepsReconnectActive() {
val error =
GatewaySession.ErrorShape(
code = "NOT_PAIRED",
message = "pairing required",
details =
GatewayConnectErrorDetails(
code = "PAIRING_REQUIRED",
canRetryWithDeviceToken = false,
recommendedNextStep = "wait_then_retry",
pauseReconnect = false,
reason = "not-paired",
),
)
assertFalse(
shouldPauseGatewayReconnectAfterAuthFailure(
error = error,
hasBootstrapToken = true,
role = "node",
scopes = emptyList(),
deviceTokenRetryBudgetUsed = false,
pendingDeviceTokenRetry = false,
),
)
}
@Test
fun bootstrapNodePairingRequiredWithoutRetryHintPausesReconnect() {
val error =
GatewaySession.ErrorShape(
code = "NOT_PAIRED",
message = "pairing required",
details =
GatewayConnectErrorDetails(
code = "PAIRING_REQUIRED",
canRetryWithDeviceToken = false,
recommendedNextStep = null,
reason = "not-paired",
),
)
assertTrue(
shouldPauseGatewayReconnectAfterAuthFailure(
error = error,
hasBootstrapToken = true,
role = "node",
scopes = emptyList(),
deviceTokenRetryBudgetUsed = false,
pendingDeviceTokenRetry = false,
),
)
}
@Test
fun nonBootstrapPairingRequiredStillPausesReconnect() {
val error =
GatewaySession.ErrorShape(
code = "NOT_PAIRED",
message = "pairing required",
details =
GatewayConnectErrorDetails(
code = "PAIRING_REQUIRED",
canRetryWithDeviceToken = false,
recommendedNextStep = "wait_then_retry",
reason = "not-paired",
),
)
assertTrue(
shouldPauseGatewayReconnectAfterAuthFailure(
error = error,
hasBootstrapToken = false,
role = "node",
scopes = emptyList(),
deviceTokenRetryBudgetUsed = false,
pendingDeviceTokenRetry = false,
),
)
}
@Test
fun bootstrapRoleUpgradeStillPausesReconnect() {
val error =
GatewaySession.ErrorShape(
code = "NOT_PAIRED",
message = "pairing required",
details =
GatewayConnectErrorDetails(
code = "PAIRING_REQUIRED",
canRetryWithDeviceToken = false,
recommendedNextStep = null,
reason = "role-upgrade",
),
)
assertTrue(
shouldPauseGatewayReconnectAfterAuthFailure(
error = error,
hasBootstrapToken = true,
role = "node",
scopes = emptyList(),
deviceTokenRetryBudgetUsed = false,
pendingDeviceTokenRetry = false,
),
)
}
}

View File

@@ -521,7 +521,8 @@ actor MacNodeRuntime {
let sessionKey = (params.sessionKey?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false)
? params.sessionKey!.trimmingCharacters(in: .whitespacesAndNewlines)
: self.mainSessionKey
let runId = UUID().uuidString
let providedRunId = params.runId?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
let runId = providedRunId.isEmpty ? UUID().uuidString : providedRunId
let envOverrideDiagnostics = HostEnvSanitizer.inspectOverrides(
overrides: params.env,
blockPathOverrides: true)

View File

@@ -14,6 +14,18 @@ struct MacNodeRuntimeTests {
}
}
actor ExecEventProbe {
private var captured: [(event: String, json: String)] = []
func append(event: String, json: String?) {
self.captured.append((event: event, json: json ?? ""))
}
func events() -> [(event: String, json: String)] {
self.captured
}
}
@Test func `handle invoke rejects unknown command`() async {
let runtime = MacNodeRuntime()
let response = await runtime.handleInvoke(
@@ -45,6 +57,40 @@ struct MacNodeRuntimeTests {
#expect(response.ok == false)
}
@Test func `system run denied event preserves gateway run id`() async throws {
let stateDir = FileManager().temporaryDirectory
.appendingPathComponent("openclaw-state-\(UUID().uuidString)", isDirectory: true)
defer { try? FileManager().removeItem(at: stateDir) }
try await TestIsolation.withEnvValues(["OPENCLAW_STATE_DIR": stateDir.path]) {
let probe = ExecEventProbe()
let runtime = MacNodeRuntime()
await runtime.setEventSender { event, json in
await probe.append(event: event, json: json)
}
let params = OpenClawSystemRunParams(
command: ["/bin/sh", "-lc", "printf ok"],
sessionKey: "agent:main:main",
runId: "gateway-run-1")
let json = try String(data: JSONEncoder().encode(params), encoding: .utf8)
let response = await runtime.handleInvoke(
BridgeInvokeRequest(
id: "req-run-id",
command: OpenClawSystemCommand.run.rawValue,
paramsJSON: json))
#expect(response.ok == false)
let denied = try #require((await probe.events()).first { $0.event == "exec.denied" })
struct Payload: Decodable {
var sessionKey: String
var runId: String
}
let payload = try JSONDecoder().decode(Payload.self, from: Data(denied.json.utf8))
#expect(payload.sessionKey == "agent:main:main")
#expect(payload.runId == "gateway-run-1")
}
}
@Test func `handle invoke rejects blocked system run env override before execution`() async throws {
let runtime = MacNodeRuntime()
let params = OpenClawSystemRunParams(

View File

@@ -29,6 +29,7 @@ public struct OpenClawSystemRunParams: Codable, Sendable, Equatable {
public var needsScreenRecording: Bool?
public var agentId: String?
public var sessionKey: String?
public var runId: String?
public var approved: Bool?
public var approvalDecision: String?
@@ -41,6 +42,7 @@ public struct OpenClawSystemRunParams: Codable, Sendable, Equatable {
needsScreenRecording: Bool? = nil,
agentId: String? = nil,
sessionKey: String? = nil,
runId: String? = nil,
approved: Bool? = nil,
approvalDecision: String? = nil)
{
@@ -52,6 +54,7 @@ public struct OpenClawSystemRunParams: Codable, Sendable, Equatable {
self.needsScreenRecording = needsScreenRecording
self.agentId = agentId
self.sessionKey = sessionKey
self.runId = runId
self.approved = approved
self.approvalDecision = approvalDecision
}

View File

@@ -3,7 +3,7 @@
import Foundation
public let GATEWAY_PROTOCOL_VERSION = 4
public let GATEWAY_MIN_PROTOCOL_VERSION = 3
public let GATEWAY_MIN_PROTOCOL_VERSION = 4
private struct GatewayAnyCodingKey: CodingKey, Hashable {
let stringValue: String
@@ -500,6 +500,7 @@ public struct AgentEvent: Codable, Sendable {
public let stream: String
public let ts: Int
public let spawnedby: String?
public let isheartbeat: Bool?
public let data: [String: AnyCodable]
public init(
@@ -508,6 +509,7 @@ public struct AgentEvent: Codable, Sendable {
stream: String,
ts: Int,
spawnedby: String?,
isheartbeat: Bool?,
data: [String: AnyCodable])
{
self.runid = runid
@@ -515,6 +517,7 @@ public struct AgentEvent: Codable, Sendable {
self.stream = stream
self.ts = ts
self.spawnedby = spawnedby
self.isheartbeat = isheartbeat
self.data = data
}
@@ -524,6 +527,7 @@ public struct AgentEvent: Codable, Sendable {
case stream
case ts
case spawnedby = "spawnedBy"
case isheartbeat = "isHeartbeat"
case data
}
}
@@ -971,6 +975,7 @@ public struct NodePairRequestParams: Codable, Sendable {
public let modelidentifier: String?
public let caps: [String]?
public let commands: [String]?
public let permissions: [String: AnyCodable]?
public let remoteip: String?
public let silent: Bool?
@@ -985,6 +990,7 @@ public struct NodePairRequestParams: Codable, Sendable {
modelidentifier: String?,
caps: [String]?,
commands: [String]?,
permissions: [String: AnyCodable]?,
remoteip: String?,
silent: Bool?)
{
@@ -998,6 +1004,7 @@ public struct NodePairRequestParams: Codable, Sendable {
self.modelidentifier = modelidentifier
self.caps = caps
self.commands = commands
self.permissions = permissions
self.remoteip = remoteip
self.silent = silent
}
@@ -1013,6 +1020,7 @@ public struct NodePairRequestParams: Codable, Sendable {
case modelidentifier = "modelIdentifier"
case caps
case commands
case permissions
case remoteip = "remoteIp"
case silent
}
@@ -2090,6 +2098,8 @@ public struct SessionsPatchParams: Codable, Sendable {
public let spawndepth: AnyCodable?
public let subagentrole: AnyCodable?
public let subagentcontrolscope: AnyCodable?
public let inheritedtoolallow: AnyCodable?
public let inheritedtooldeny: AnyCodable?
public let sendpolicy: AnyCodable?
public let groupactivation: AnyCodable?
@@ -2113,6 +2123,8 @@ public struct SessionsPatchParams: Codable, Sendable {
spawndepth: AnyCodable?,
subagentrole: AnyCodable?,
subagentcontrolscope: AnyCodable?,
inheritedtoolallow: AnyCodable?,
inheritedtooldeny: AnyCodable?,
sendpolicy: AnyCodable?,
groupactivation: AnyCodable?)
{
@@ -2135,6 +2147,8 @@ public struct SessionsPatchParams: Codable, Sendable {
self.spawndepth = spawndepth
self.subagentrole = subagentrole
self.subagentcontrolscope = subagentcontrolscope
self.inheritedtoolallow = inheritedtoolallow
self.inheritedtooldeny = inheritedtooldeny
self.sendpolicy = sendpolicy
self.groupactivation = groupactivation
}
@@ -2159,6 +2173,8 @@ public struct SessionsPatchParams: Codable, Sendable {
case spawndepth = "spawnDepth"
case subagentrole = "subagentRole"
case subagentcontrolscope = "subagentControlScope"
case inheritedtoolallow = "inheritedToolAllow"
case inheritedtooldeny = "inheritedToolDeny"
case sendpolicy = "sendPolicy"
case groupactivation = "groupActivation"
}
@@ -3212,6 +3228,7 @@ public struct TalkSessionCancelTurnParams: Codable, Sendable {
public struct TalkSessionCreateParams: Codable, Sendable {
public let sessionkey: String?
public let spawnedby: String?
public let provider: String?
public let model: String?
public let voice: String?
@@ -3226,6 +3243,7 @@ public struct TalkSessionCreateParams: Codable, Sendable {
public init(
sessionkey: String?,
spawnedby: String?,
provider: String?,
model: String?,
voice: String?,
@@ -3239,6 +3257,7 @@ public struct TalkSessionCreateParams: Codable, Sendable {
ttlms: Int?)
{
self.sessionkey = sessionkey
self.spawnedby = spawnedby
self.provider = provider
self.model = model
self.voice = voice
@@ -3254,6 +3273,7 @@ public struct TalkSessionCreateParams: Codable, Sendable {
private enum CodingKeys: String, CodingKey {
case sessionkey = "sessionKey"
case spawnedby = "spawnedBy"
case provider
case model
case voice
@@ -6224,12 +6244,138 @@ public struct ChatInjectParams: Codable, Sendable {
}
}
public struct ChatEvent: Codable, Sendable {
public struct ChatDeltaEvent: Codable, Sendable {
public let runid: String
public let sessionkey: String
public let spawnedby: String?
public let seq: Int
public let state: AnyCodable
public let state: String
public let message: AnyCodable?
public let deltatext: String
public let replace: Bool?
public let usage: AnyCodable?
public init(
runid: String,
sessionkey: String,
spawnedby: String?,
seq: Int,
state: String,
message: AnyCodable?,
deltatext: String,
replace: Bool?,
usage: AnyCodable?)
{
self.runid = runid
self.sessionkey = sessionkey
self.spawnedby = spawnedby
self.seq = seq
self.state = state
self.message = message
self.deltatext = deltatext
self.replace = replace
self.usage = usage
}
private enum CodingKeys: String, CodingKey {
case runid = "runId"
case sessionkey = "sessionKey"
case spawnedby = "spawnedBy"
case seq
case state
case message
case deltatext = "deltaText"
case replace
case usage
}
}
public struct ChatFinalEvent: Codable, Sendable {
public let runid: String
public let sessionkey: String
public let spawnedby: String?
public let seq: Int
public let state: String
public let message: AnyCodable?
public let usage: AnyCodable?
public let stopreason: String?
public init(
runid: String,
sessionkey: String,
spawnedby: String?,
seq: Int,
state: String,
message: AnyCodable?,
usage: AnyCodable?,
stopreason: String?)
{
self.runid = runid
self.sessionkey = sessionkey
self.spawnedby = spawnedby
self.seq = seq
self.state = state
self.message = message
self.usage = usage
self.stopreason = stopreason
}
private enum CodingKeys: String, CodingKey {
case runid = "runId"
case sessionkey = "sessionKey"
case spawnedby = "spawnedBy"
case seq
case state
case message
case usage
case stopreason = "stopReason"
}
}
public struct ChatAbortedEvent: Codable, Sendable {
public let runid: String
public let sessionkey: String
public let spawnedby: String?
public let seq: Int
public let state: String
public let message: AnyCodable?
public let stopreason: String?
public init(
runid: String,
sessionkey: String,
spawnedby: String?,
seq: Int,
state: String,
message: AnyCodable?,
stopreason: String?)
{
self.runid = runid
self.sessionkey = sessionkey
self.spawnedby = spawnedby
self.seq = seq
self.state = state
self.message = message
self.stopreason = stopreason
}
private enum CodingKeys: String, CodingKey {
case runid = "runId"
case sessionkey = "sessionKey"
case spawnedby = "spawnedBy"
case seq
case state
case message
case stopreason = "stopReason"
}
}
public struct ChatErrorEvent: Codable, Sendable {
public let runid: String
public let sessionkey: String
public let spawnedby: String?
public let seq: Int
public let state: String
public let message: AnyCodable?
public let errormessage: String?
public let errorkind: AnyCodable?
@@ -6241,7 +6387,7 @@ public struct ChatEvent: Codable, Sendable {
sessionkey: String,
spawnedby: String?,
seq: Int,
state: AnyCodable,
state: String,
message: AnyCodable?,
errormessage: String?,
errorkind: AnyCodable?,
@@ -6373,6 +6519,43 @@ public enum PluginsSessionActionResult: Codable, Sendable {
}
}
public enum ChatEvent: Codable, Sendable {
case delta(ChatDeltaEvent)
case final(ChatFinalEvent)
case aborted(ChatAbortedEvent)
case error(ChatErrorEvent)
private enum CodingKeys: String, CodingKey {
case discriminator = "state"
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let discriminator = try container.decode(String.self, forKey: .discriminator)
switch discriminator {
case "delta": self = try .delta(ChatDeltaEvent(from: decoder))
case "final": self = try .final(ChatFinalEvent(from: decoder))
case "aborted": self = try .aborted(ChatAbortedEvent(from: decoder))
case "error": self = try .error(ChatErrorEvent(from: decoder))
default:
throw DecodingError.dataCorruptedError(
forKey: .discriminator,
in: container,
debugDescription: "Unknown ChatEvent discriminator value"
)
}
}
public func encode(to encoder: Encoder) throws {
switch self {
case .delta(let value): try value.encode(to: encoder)
case .final(let value): try value.encode(to: encoder)
case .aborted(let value): try value.encode(to: encoder)
case .error(let value): try value.encode(to: encoder)
}
}
}
public enum GatewayFrame: Codable, Sendable {
case req(RequestFrame)
case res(ResponseFrame)

View File

@@ -66,7 +66,6 @@ const rootBundledPluginRuntimeDependencies = [
"@slack/bolt",
"@slack/types",
"@slack/web-api",
"audio-decode",
"grammy",
"linkedom",
"minimatch",

View File

@@ -7,13 +7,16 @@ services:
required: false
environment:
HOME: /home/node
OPENCLAW_HOME: /home/node
TERM: xterm-256color
# Pin container-side workspace and config paths so host values written to
# Pin container-side state, workspace, and config paths so host values written to
# `.env` (used by Compose for the bind-mount source below) cannot leak
# into runtime code that resolves these env vars inside the container.
# Without this override, a macOS host path like /Users/<you>/.openclaw/...
# imported from .env caused first-reply `mkdir '/Users'` EACCES failures
# in Linux Docker (#77436).
OPENCLAW_STATE_DIR: /home/node/.openclaw
OPENCLAW_CONFIG_PATH: /home/node/.openclaw/openclaw.json
OPENCLAW_CONFIG_DIR: /home/node/.openclaw
OPENCLAW_WORKSPACE_DIR: /home/node/.openclaw/workspace
OPENCLAW_GATEWAY_TOKEN: ${OPENCLAW_GATEWAY_TOKEN:-}
@@ -38,6 +41,7 @@ services:
volumes:
- ${OPENCLAW_CONFIG_DIR:-${HOME:-/tmp}/.openclaw}:/home/node/.openclaw
- ${OPENCLAW_WORKSPACE_DIR:-${HOME:-/tmp}/.openclaw/workspace}:/home/node/.openclaw/workspace
- ${OPENCLAW_AUTH_PROFILE_SECRET_DIR:-${HOME:-/tmp}/.openclaw-auth-profile-secrets}:/home/node/.config/openclaw
## Uncomment the lines below to enable sandbox isolation
## (agents.defaults.sandbox). Requires Docker CLI in the image
## (build with --build-arg OPENCLAW_INSTALL_DOCKER_CLI=1) or use
@@ -97,9 +101,12 @@ services:
- no-new-privileges:true
environment:
HOME: /home/node
OPENCLAW_HOME: /home/node
TERM: xterm-256color
# Pin container-side workspace and config paths so host values written to
# Pin container-side state, workspace, and config paths so host values written to
# `.env` cannot leak into runtime code via the env_file import (#77436).
OPENCLAW_STATE_DIR: /home/node/.openclaw
OPENCLAW_CONFIG_PATH: /home/node/.openclaw/openclaw.json
OPENCLAW_CONFIG_DIR: /home/node/.openclaw
OPENCLAW_WORKSPACE_DIR: /home/node/.openclaw/workspace
OPENCLAW_GATEWAY_TOKEN: ${OPENCLAW_GATEWAY_TOKEN:-}
@@ -112,6 +119,7 @@ services:
volumes:
- ${OPENCLAW_CONFIG_DIR:-${HOME:-/tmp}/.openclaw}:/home/node/.openclaw
- ${OPENCLAW_WORKSPACE_DIR:-${HOME:-/tmp}/.openclaw/workspace}:/home/node/.openclaw/workspace
- ${OPENCLAW_AUTH_PROFILE_SECRET_DIR:-${HOME:-/tmp}/.openclaw-auth-profile-secrets}:/home/node/.config/openclaw
stdin_open: true
tty: true
init: true

View File

@@ -1,4 +1,4 @@
f95819d93e9bec5d059440ab54fb4ccb487425cb91d647c8688cd18ef1d4d848 config-baseline.json
3325af3a6292959bb38166e9136c638dce5d2093d2339076742890848088a972 config-baseline.core.json
ad1d3cb596115d66c21e93de95e229c14c585f0dd4799b4ae3cc29b84761adc6 config-baseline.channel.json
c311205806d0eaa3631788dc2c489ece999b70430021ff91b365ce7ccfcba23c config-baseline.json
2e27b71c9ed109767a227f5163917a4468a1969079fc3457a3df7fe74c1fa2b7 config-baseline.core.json
2aa997d48549bd321a478485126a4bd5065ba47333a80e7eb07a0ef6ad75b0a6 config-baseline.channel.json
0dac8944a0d51ae96f97e3809907f8a04d08413434a1a1190240f7e13bb11c4d config-baseline.plugin.json

View File

@@ -1,2 +1,2 @@
f26833e053032e3da94025c8a5a8cb62dcddd275797b527440a19be5886a4783 plugin-sdk-api-baseline.json
429fe1d6d119379b914bf84b15705233dc8d2d9e1a8131bb28ea19b19afbe6a0 plugin-sdk-api-baseline.jsonl
e8c15cff96a0a869cfe3de29679d4296603a16bfa4676940845a484c23db8e56 plugin-sdk-api-baseline.json
a6cbb8dc21b3ed16e0abd23c60a817ddedd65f336427c9fa565a43ca5dcc9a85 plugin-sdk-api-baseline.jsonl

View File

@@ -651,6 +651,26 @@
"source": "Manage plugins",
"target": "管理插件"
},
{
"source": "Plugin inventory",
"target": "插件清单"
},
{
"source": "Plugin reference",
"target": "插件参考"
},
{
"source": "Community plugins",
"target": "社区插件"
},
{
"source": "ClawHub publishing",
"target": "ClawHub 发布"
},
{
"source": "Plugin dependency resolution",
"target": "插件依赖解析"
},
{
"source": "Plugin path ownership",
"target": "插件路径所有权"
@@ -950,5 +970,9 @@
{
"source": "ACP agents setup",
"target": "ACP Agents 设置"
},
{
"source": "ds4 (local DeepSeek V4)",
"target": "ds4本地 DeepSeek V4"
}
]

View File

@@ -109,7 +109,7 @@ See [Hooks](/automation/hooks).
### Heartbeat
Heartbeat is a periodic main-session turn (default every 30 minutes). It batches multiple checks (inbox, calendar, notifications) in one agent turn with full session context. Heartbeat turns do not create task records and do not extend daily/idle session reset freshness. Use `HEARTBEAT.md` for a small checklist, or a `tasks:` block when you want due-only periodic checks inside heartbeat itself. Empty heartbeat files skip as `empty-heartbeat-file`; due-only task mode skips as `no-tasks-due`. Heartbeats defer while cron work is active or queued, and `heartbeat.skipWhenBusy` can also defer them while subagent or nested lanes are busy.
Heartbeat is a periodic main-session turn (default every 30 minutes). It batches multiple checks (inbox, calendar, notifications) in one agent turn with full session context. Heartbeat turns do not create task records and do not extend daily/idle session reset freshness. Use `HEARTBEAT.md` for a small checklist, or a `tasks:` block when you want due-only periodic checks inside heartbeat itself. Empty heartbeat files skip as `empty-heartbeat-file`; due-only task mode skips as `no-tasks-due`. Heartbeats defer while cron work is active or queued, and `heartbeat.skipWhenBusy` can also defer an agent while that same agent's session-keyed subagent or nested lanes are busy.
See [Heartbeat](/gateway/heartbeat).

View File

@@ -0,0 +1,131 @@
---
summary: "Bot-to-bot loop protection defaults and channel overrides"
read_when:
- Configuring bot-authored channel messages
- Tuning bot-to-bot loop protection
title: "Bot loop protection"
sidebarTitle: "Bot loop protection"
---
# Bot loop protection
OpenClaw can accept messages written by other bots on channels that support `allowBots`.
When that path is enabled, pair loop protection prevents two bot identities from
replying to each other indefinitely.
The guard is enforced by the core channel-turn kernel. Each supporting channel
maps its own inbound event into generic facts: account or scope, conversation id,
sender bot id, and receiver bot id. Core then tracks the participant pair in both
directions, applies a sliding-window budget, and suppresses the pair during a
cooldown after the budget is exceeded.
## Defaults
Pair loop protection is active when a channel lets bot-authored messages reach
dispatch. Built-in defaults are:
- `maxEventsPerWindow: 20` - a bot pair can exchange 20 events within the window
- `windowSeconds: 60` - sliding window length
- `cooldownSeconds: 60` - suppression time after the pair exceeds the budget
The guard does not affect normal human-authored messages, single-bot deployments,
self-message filtering, or one-shot bot replies that stay under the budget.
## Configure shared defaults
Set `channels.defaults.botLoopProtection` once to give every supporting channel
the same baseline. Channel and account overrides can still tune individual
surfaces.
```json5
{
channels: {
defaults: {
botLoopProtection: {
maxEventsPerWindow: 20,
windowSeconds: 60,
cooldownSeconds: 60,
},
},
},
}
```
Set `enabled: false` only when your channel policy intentionally allows
bot-to-bot conversations without automatic suppression.
## Override per channel or account
Supporting channels layer their own config over the shared default. Precedence is:
- `channels.<channel>.<room-or-space>.botLoopProtection`, when the channel supports per-conversation overrides
- `channels.<channel>.accounts.<account>.botLoopProtection`, when the channel supports accounts
- `channels.<channel>.botLoopProtection`, when the channel supports top-level defaults
- `channels.defaults.botLoopProtection`
- built-in defaults
```json5
{
channels: {
defaults: {
botLoopProtection: {
maxEventsPerWindow: 20,
},
},
discord: {
botLoopProtection: {
maxEventsPerWindow: 8,
},
accounts: {
molty: {
allowBots: "mentions",
botLoopProtection: {
maxEventsPerWindow: 5,
cooldownSeconds: 90,
},
},
},
},
slack: {
allowBots: "mentions",
botLoopProtection: {
maxEventsPerWindow: 8,
},
},
matrix: {
allowBots: "mentions",
groups: {
"!roomid:example.org": {
botLoopProtection: {
maxEventsPerWindow: 5,
},
},
},
},
googlechat: {
allowBots: true,
groups: {
"spaces/AAAA": {
botLoopProtection: {
maxEventsPerWindow: 5,
},
},
},
},
},
}
```
## Channel support
- Discord: native `author.bot` facts, keyed by Discord account, channel, and bot pair.
- Slack: native `bot_id` facts for accepted bot-authored messages, keyed by Slack account, channel, and bot pair.
- Matrix: configured Matrix bot accounts, keyed by Matrix account, room, and configured bot pair.
- Google Chat: native `sender.type=BOT` facts for accepted bot-authored messages, keyed by account, space, and bot pair.
Channels that do not expose a reliable inbound bot identity keep using their
normal self-message and access-policy filters. They should not opt into this
guard until they can identify both participants in the bot pair.
See [SDK runtime](/plugins/sdk-runtime#reusable-runtime-utilities) for plugin
implementation details.

View File

@@ -1569,10 +1569,39 @@ openclaw logs --follow
If you set `channels.discord.allowBots=true`, use strict mention and allowlist rules to avoid loop behavior.
Prefer `channels.discord.allowBots="mentions"` to only accept bot messages that mention the bot.
OpenClaw also ships shared [bot loop protection](/channels/bot-loop-protection). Whenever `allowBots` lets bot-authored messages reach dispatch, Discord maps the inbound event to `(account, channel, bot pair)` facts and the generic pair guard suppresses the pair after it crosses the configured event budget. The guard prevents runaway two-bot loops that previously had to be stopped by Discord rate limits; it does not affect single-bot deployments or one-shot bot replies that stay under the budget.
Default settings (active when `allowBots` is set):
- `maxEventsPerWindow: 20` -- bot pair can exchange 20 messages within the sliding window
- `windowSeconds: 60` -- sliding window length
- `cooldownSeconds: 60` -- once the budget trips, every additional bot-to-bot message in either direction is dropped for one minute
Configure the shared default once under `channels.defaults.botLoopProtection`, then override Discord when a legitimate workflow needs more headroom. Precedence is:
- `channels.discord.accounts.<account>.botLoopProtection`
- `channels.discord.botLoopProtection`
- `channels.defaults.botLoopProtection`
- built-in defaults
Discord uses the generic `maxEventsPerWindow`, `windowSeconds`, and `cooldownSeconds` keys.
```json5
{
channels: {
defaults: {
botLoopProtection: {
maxEventsPerWindow: 20,
windowSeconds: 60,
cooldownSeconds: 60,
},
},
discord: {
// Optional Discord-wide override. Account blocks override individual
// fields and inherit omitted fields from here.
botLoopProtection: {
maxEventsPerWindow: 4,
},
accounts: {
mantis: {
// Mantis listens to other bots only when they mention her.
@@ -1585,6 +1614,12 @@ openclaw logs --follow
// Lets Molty write "@Mantis" and send a real Discord mention.
Mantis: "MANTIS_DISCORD_USER_ID",
},
botLoopProtection: {
// Allow up to five messages per minute before suppressing the pair.
maxEventsPerWindow: 5,
windowSeconds: 60,
cooldownSeconds: 90,
},
},
},
},

View File

@@ -185,6 +185,7 @@ Use these identifiers for delivery and allowlists:
audience: "https://gateway.example.com/googlechat",
webhookPath: "/googlechat",
botUser: "users/1234567890", // optional; helps mention detection
allowBots: false,
dm: {
policy: "pairing",
allowFrom: ["users/1234567890"],
@@ -216,6 +217,7 @@ Notes:
- Message actions expose `send` for text and `upload-file` for explicit attachment sends. `upload-file` accepts `media` / `filePath` / `path` plus optional `message`, `filename`, and thread targeting.
- `typingIndicator` supports `none`, `message` (default), and `reaction` (reaction requires user OAuth).
- Attachments are downloaded through the Chat API and stored in the media pipeline (size capped by `mediaMaxMb`).
- Bot-authored Google Chat messages are ignored by default. If you intentionally set `allowBots: true`, accepted bot-authored messages use shared [bot loop protection](/channels/bot-loop-protection). Configure `channels.defaults.botLoopProtection`, then override with `channels.googlechat.botLoopProtection` or `channels.googlechat.groups.<space>.botLoopProtection` when one space needs a different budget.
Secrets reference details: [Secrets Management](/gateway/secrets).

View File

@@ -217,7 +217,7 @@ If SIP-disabled isn't acceptable for your threat model:
Allowlist field: `channels.imessage.allowFrom`.
Allowlist entries can be handles, static sender access groups (`accessGroup:<name>`), or chat targets (`chat_id:*`, `chat_guid:*`, `chat_identifier:*`).
Allowlist entries must identify senders: handles or static sender access groups (`accessGroup:<name>`). Use `channels.imessage.groupAllowFrom` for chat targets such as `chat_id:*`, `chat_guid:*`, or `chat_identifier:*`; use `channels.imessage.groups` for numeric `chat_id` registry keys.
</Tab>
@@ -232,7 +232,7 @@ If SIP-disabled isn't acceptable for your threat model:
`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 fallback: if `groupAllowFrom` is unset, iMessage group sender checks use `allowFrom`; set `groupAllowFrom` when DM and group admission should differ.
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>

View File

@@ -16,8 +16,11 @@ Text is supported everywhere; media and reactions vary by channel.
- Slack multi-person DMs route as group chats, so group policy, mention
behavior, and group-session rules apply to MPIM conversations.
- WhatsApp setup is install-on-demand: onboarding can show the setup flow before
the plugin package is installed, and the Gateway loads the WhatsApp runtime
only when the channel is actually active.
the plugin package is installed, and the Gateway loads the external
ClawHub/npm plugin only when the channel is actually active.
- Channels that accept bot-authored inbound messages can use shared
[bot loop protection](/channels/bot-loop-protection) to prevent bot pairs from
replying to each other indefinitely.
## Supported channels

View File

@@ -266,6 +266,7 @@ Use `allowBots` when you intentionally want inter-agent Matrix traffic:
- `allowBots: true` accepts messages from other configured Matrix bot accounts in allowed rooms and DMs.
- `allowBots: "mentions"` accepts those messages only when they visibly mention this bot in rooms. DMs are still allowed.
- `groups.<room>.allowBots` overrides the account-level setting for one room.
- Accepted configured-bot messages use shared [bot loop protection](/channels/bot-loop-protection). Configure `channels.defaults.botLoopProtection`, then override with `channels.matrix.botLoopProtection` or `channels.matrix.groups.<room>.botLoopProtection` when one room needs a different budget.
- OpenClaw still ignores messages from the same Matrix user ID to avoid self-reply loops.
- Matrix does not expose a native bot flag here; OpenClaw treats "bot-authored" as "sent by another configured Matrix account on this OpenClaw gateway".

View File

@@ -123,12 +123,10 @@ The setup code is a base64-encoded JSON payload that contains:
That bootstrap token carries the built-in pairing bootstrap profile:
- primary handed-off `node` token stays `scopes: []`
- any handed-off `operator` token stays bounded to the bootstrap allowlist:
`operator.approvals`, `operator.read`, `operator.talk.secrets`, `operator.write`
- bootstrap scope checks are role-prefixed, not one flat scope pool:
operator scope entries only satisfy operator requests, and non-operator roles
must still request scopes under their own role prefix
- the built-in setup profile allows only the `node` role
- after approval, the handed-off `node` token stays `scopes: []`
- the built-in setup-code flow does not hand off an `operator` token
- operator access requires a separate approved operator pairing or token flow
- later token rotation/revocation remains bounded by both the device's approved
role contract and the caller session's operator scopes

View File

@@ -920,6 +920,8 @@ Current Slack message actions include `send`, `upload-file`, `download-file`, `r
`allowBots` is conservative for channels and private channels: bot-authored room messages are accepted only when the sending bot is explicitly listed in that room's `users` allowlist, or when at least one explicit Slack owner ID from `channels.slack.allowFrom` is currently a room member. Wildcards and display-name owner entries do not satisfy owner presence. Owner presence uses Slack `conversations.members`; make sure the app has the matching read scope for the room type (`channels:read` for public channels, `groups:read` for private channels). If the member lookup fails, OpenClaw drops the bot-authored room message.
Accepted bot-authored Slack messages use shared [bot loop protection](/channels/bot-loop-protection). Configure `channels.defaults.botLoopProtection` for the default budget, then override with `channels.slack.botLoopProtection` or `channels.slack.channels.<id>.botLoopProtection` when a workspace or channel needs a different limit.
</Tab>
</Tabs>

View File

@@ -293,6 +293,7 @@ curl "https://api.telegram.org/bot<bot_token>/getUpdates"
- 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`.
- Multi-account startup bounds concurrent Telegram `getMe` probes so large bot fleets do not fan out every account probe at once.
- Long polling is guarded inside each gateway process so only one active poller can use a bot token at a time. If you still see `getUpdates` 409 conflicts, another OpenClaw gateway, script, or external poller is likely using the same token.
- Long-polling watchdog restarts trigger after 120 seconds without completed `getUpdates` liveness by default. Increase `channels.telegram.pollingStallThresholdMs` only if your deployment still sees false polling-stall restarts during long-running work. The value is in milliseconds and is allowed from `30000` to `600000`; per-account overrides are supported.
- Telegram Bot API has no read-receipt support (`sendReadReceipts` does not apply).
@@ -395,7 +396,7 @@ curl "https://api.telegram.org/bot<bot_token>/getUpdates"
Outbound text uses Telegram `parse_mode: "HTML"`.
- Markdown-ish text is rendered to Telegram-safe HTML.
- Raw model HTML is escaped to reduce Telegram parse failures.
- Supported Telegram HTML tags are preserved; unsupported HTML is escaped.
- If Telegram rejects parsed HTML, OpenClaw retries as plain text.
Link previews are enabled by default and can be disabled with `channels.telegram.linkPreview: false`.
@@ -457,7 +458,7 @@ curl "https://api.telegram.org/bot<bot_token>/getUpdates"
- `/pair approve` when there is only one pending request
- `/pair approve latest` for most recent
The setup code carries a short-lived bootstrap token. Built-in bootstrap handoff keeps the primary node token at `scopes: []`; any handed-off operator token stays bounded to `operator.approvals`, `operator.read`, `operator.talk.secrets`, and `operator.write`. Bootstrap scope checks are role-prefixed, so that operator allowlist only satisfies operator requests; non-operator roles still need scopes under their own role prefix.
The setup code carries a short-lived bootstrap token. Built-in setup-code bootstrap is node-only: the first connect creates a pending node request, and after approval the Gateway returns a durable node token with `scopes: []`. It does not return a handed-off operator token; operator access requires a separate approved operator pairing or token flow.
If a device retries with changed auth details (for example role/scopes/public key), the previous pending request is superseded and the new request uses a different `requestId`. Re-run `/pair pending` before approving.
@@ -526,6 +527,28 @@ curl "https://api.telegram.org/bot<bot_token>/getUpdates"
}
```
Mini App button example:
```json5
{
action: "send",
channel: "telegram",
to: "123456789",
message: "Open app:",
presentation: {
blocks: [
{
type: "buttons",
buttons: [{ label: "Launch", web_app: { url: "https://example.com/app" } }],
},
],
},
}
```
Telegram `web_app` buttons work only in private chats between a user and the
bot.
Callback clicks are passed to the agent as text:
`callback_data: <value>`

View File

@@ -14,27 +14,19 @@ Status: production-ready via WhatsApp Web (Baileys). Gateway owns linked session
- `openclaw channels login --channel whatsapp` also offers the install flow when
the plugin is not present yet.
- Dev channel + git checkout: defaults to the local plugin path.
- Stable/Beta: uses the npm package `@openclaw/whatsapp` on the current official
release tag.
- Stable/Beta: installs the official `@openclaw/whatsapp` plugin from ClawHub
first, with npm as the fallback.
- The WhatsApp runtime is distributed outside the core OpenClaw npm package so
WhatsApp-specific runtime dependencies stay with the external plugin.
Manual install stays available:
```bash
openclaw plugins install @openclaw/whatsapp
openclaw plugins install clawhub:@openclaw/whatsapp
```
Use the bare package to follow the current official release tag. Pin an exact
version only when you need a reproducible install.
On Windows, the WhatsApp plugin needs Git on `PATH` during npm install because
one of its Baileys/libsignal dependencies is fetched from a git URL. Install
Git for Windows, then restart the shell and rerun the install:
```powershell
winget install --id Git.Git -e
```
Portable Git also works if its `bin` directory is on `PATH`.
Use the bare npm package (`@openclaw/whatsapp`) only when you need the registry
fallback. Pin an exact version only when you need a reproducible install.
<CardGroup cols={3}>
<Card title="Pairing" icon="link" href="/channels/pairing">

View File

@@ -520,15 +520,15 @@ openclaw gateway restart
Only gateways with Bonjour discovery enabled (default) advertise the beacon.
Wide-Area discovery records include (TXT):
Wide-area discovery records can include these TXT hints:
- `role` (gateway role hint)
- `transport` (transport hint, e.g. `gateway`)
- `gatewayPort` (WebSocket port, usually `18789`)
- `sshPort` (optional; clients default SSH targets to `22` when it is absent)
- `sshPort` (full discovery mode only; clients default SSH targets to `22` when it is absent)
- `tailnetDns` (MagicDNS hostname, when available)
- `gatewayTls` / `gatewayTlsSha256` (TLS enabled + cert fingerprint)
- `cliPath` (remote-install hint written to the wide-area zone)
- `cliPath` (full discovery mode only)
### `gateway discover`
@@ -553,7 +553,7 @@ openclaw gateway discover --json | jq '.beacons[].wsUrl'
<Note>
- The CLI scans `local.` plus the configured wide-area domain when one is enabled.
- `wsUrl` in JSON output is derived from the resolved service endpoint, not from TXT-only hints such as `lanHost` or `tailnetDns`.
- On `local.` mDNS, `sshPort` and `cliPath` are only broadcast when `discovery.mdns.mode` is `full`. Wide-area DNS-SD still writes `cliPath`; `sshPort` stays optional there too.
- On `local.` mDNS and wide-area DNS-SD, `sshPort` and `cliPath` are only published when `discovery.mdns.mode` is `full`.
</Note>

View File

@@ -284,6 +284,16 @@ openclaw message send --channel telegram --target @mychat --message "Choose:" \
--presentation '{"blocks":[{"type":"buttons","buttons":[{"label":"Yes","value":"cmd:yes"},{"label":"No","value":"cmd:no"}]}]}'
```
Send a Telegram Mini App button through generic presentation:
```
openclaw message send --channel telegram --target 123456789 --message "Open app:" \
--presentation '{"blocks":[{"type":"buttons","buttons":[{"label":"Launch","web_app":{"url":"https://example.com/app"}}]}]}'
```
Telegram `web_app` buttons are supported only in private chats between a user
and the bot.
Send a Teams card through generic presentation:
```bash

View File

@@ -22,6 +22,7 @@ openclaw migrate claude --dry-run
openclaw migrate codex --dry-run
openclaw migrate codex --skill gog-vault77-google-workspace
openclaw migrate codex --plugin google-calendar --dry-run
openclaw migrate codex --plugin google-calendar --verify-plugin-apps --dry-run
openclaw migrate hermes --dry-run
openclaw migrate hermes
openclaw migrate apply codex --yes --skill gog-vault77-google-workspace
@@ -59,6 +60,9 @@ openclaw onboard --import-from hermes --import-source ~/.hermes
<ParamField path="--plugin <name>" type="string">
Select one Codex plugin install item by plugin name or item id. Repeat the flag to migrate multiple Codex plugins. When omitted, interactive Codex migrations show a native Codex plugin checkbox selector and non-interactive migrations keep all planned plugins. This only applies to source-installed `openai-curated` Codex plugins discovered by the Codex app-server inventory.
</ParamField>
<ParamField path="--verify-plugin-apps" type="boolean">
Codex only. Force a fresh source Codex app-server `app/list` traversal before planning native plugin activation. Off by default to keep migration planning fast.
</ParamField>
<ParamField path="--no-backup" type="boolean">
Skip the pre-apply backup. Requires `--force` when local OpenClaw state exists.
</ParamField>
@@ -119,13 +123,15 @@ inventory a specific Codex home.
Use this provider when moving to the OpenClaw Codex harness and you want to
promote useful personal Codex CLI assets deliberately. Local Codex app-server
launches use per-agent `CODEX_HOME` and `HOME` directories, so they do not read
your personal Codex CLI state by default.
launches use a per-agent `CODEX_HOME`, so they do not read your personal Codex
CLI state by default, while subprocesses still inherit the normal process
`HOME` unless the app-server launch explicitly overrides it.
Running `openclaw migrate codex` in an interactive terminal previews the full
plan, then opens checkbox selectors before the final apply confirmation. Skill
copy items are prompted first. Use `Toggle all on` or `Toggle all off` for bulk
selection; planned skills start checked, conflict skills start unchecked, and
selection. Press Space to toggle rows, or press Enter to activate the highlighted
row and continue. Planned skills start checked, conflict skills start unchecked, and
`Skip for now` skips skill copies for this run while still continuing to plugin
selection. When source-installed curated Codex plugins are migratable and
`--plugin` was not supplied, migration then prompts for native Codex plugin
@@ -156,17 +162,36 @@ openclaw migrate apply codex --yes --plugin google-calendar
- Personal AgentSkills under `$HOME/.agents/skills`, copied into the current
OpenClaw agent workspace when you want per-agent ownership.
- Source-installed `openai-curated` Codex plugins discovered through Codex
app-server `plugin/list`. Apply calls app-server `plugin/install` for each
selected plugin, even if the target app-server already reports that plugin as
installed and enabled. Migrated Codex plugins are usable only in sessions that
select the native Codex harness; they are not exposed to Pi, normal OpenAI
provider runs, ACP conversation bindings, or other harnesses.
app-server `plugin/list`. Planning reads `plugin/read` for each enabled
installed plugin. App-backed plugins require the source Codex app-server
account response to be a ChatGPT subscription account; non-ChatGPT or missing
account responses are skipped with `codex_subscription_required`. By default,
migration does not call source `app/list`, so app-backed plugins that pass the
account gate are planned without source app accessibility verification, and
account lookup transport failures skip with `codex_account_unavailable`. Pass
`--verify-plugin-apps` when you want migration to force a fresh source
`app/list` snapshot and require every owned app to be present, enabled, and
accessible before planning native activation. In that mode, account lookup
transport failures fall through to source app inventory verification. The
source app inventory snapshot is kept in memory for the current process; it
is not written to migration output or target config. Disabled plugins,
unreadable plugin details, subscription-gated source accounts, and, when
verification is requested, missing apps, disabled apps, inaccessible apps, or
source app inventory failures become manual skipped items with typed reasons
instead of target config entries.
Apply calls app-server `plugin/install` for each selected eligible plugin,
even if the target app-server already reports that plugin as installed and
enabled. Migrated Codex plugins are usable only in sessions that select the
native Codex harness; they are not exposed to Pi, normal OpenAI provider runs,
ACP conversation bindings, or other harnesses.
### Manual-review Codex state
Codex `config.toml`, native `hooks/hooks.json`, non-curated marketplaces, and
cached plugin bundles that are not source-installed curated plugins are not
activated automatically. They are copied or reported in the migration report for
Codex `config.toml`, native `hooks/hooks.json`, non-curated marketplaces, cached
plugin bundles that are not source-installed curated plugins, and source-installed
plugins that fail the source subscription gate are not activated automatically.
When `--verify-plugin-apps` is set, plugins that fail the source app-inventory
gate are also skipped. They are copied or reported in the migration report for
manual review.
For migrated source-installed curated plugins, apply writes:
@@ -178,7 +203,13 @@ For migrated source-installed curated plugins, apply writes:
`pluginName` for each selected plugin
Migration never writes `plugins["*"]` and never stores local marketplace cache
paths. Auth-required installs are reported on the affected plugin item with
paths. Source-side subscription failures are reported on manual items with typed
reasons such as `codex_subscription_required`, `codex_account_unavailable`,
`plugin_disabled`, or `plugin_read_unavailable`. With `--verify-plugin-apps`,
source app-inventory failures can also appear as `app_inaccessible`,
`app_disabled`, `app_missing`, or `app_inventory_unavailable`. Skipped plugins
are not written to target config.
Target-side auth-required installs are reported on the affected plugin item with
`status: "skipped"`, `reason: "auth_required"`, and sanitized app identifiers.
Their explicit config entries are written disabled until you reauthorize and
enable them. Other install failures are item-scoped `error` results.

View File

@@ -131,9 +131,11 @@ is available, then fall back to `latest`.
<Accordion title="--dangerously-force-unsafe-install">
`--dangerously-force-unsafe-install` is a break-glass option for false positives in the built-in dangerous-code scanner. It allows the install to continue even when the built-in scanner reports `critical` findings, but it does **not** bypass plugin `before_install` hook policy blocks and does **not** bypass scan failures.
Install scans ignore common test files and directories such as `tests/`, `__tests__/`, `*.test.*`, and `*.spec.*` to avoid blocking packaged test mocks; declared plugin runtime entrypoints are still scanned even if they use one of those names.
This CLI flag applies to plugin install/update flows. Gateway-backed skill dependency installs use the matching `dangerouslyForceUnsafeInstall` request override, while `openclaw skills install` remains a separate ClawHub skill download/install flow.
If a plugin you published on ClawHub is blocked by a registry scan, use the publisher steps in [ClawHub](/clawhub/security).
If a plugin you published on ClawHub is hidden or blocked by a registry scan, use the publisher steps in [ClawHub publishing](/clawhub/publishing). `--dangerously-force-unsafe-install` only affects installs on your own machine; it does not ask ClawHub to rescan the plugin or make a blocked release public.
</Accordion>
<Accordion title="Hook packs and npm specs">
@@ -282,7 +284,7 @@ directory remains inert so normal packaged installs still use compiled dist.
For runtime hook debugging:
- `openclaw plugins inspect <id> --runtime --json` shows registered hooks and diagnostics from a module-loaded inspection pass. Runtime inspection never installs dependencies; use `openclaw doctor --fix` to clean legacy dependency state or recover missing downloadable plugins that are referenced by config.
- `openclaw gateway status --deep --require-rpc` confirms the reachable Gateway, service/process hints, config path, and RPC health.
- `openclaw gateway status --deep --require-rpc` confirms the reachable Gateway URL/profile, service/process hints, config path, and RPC health.
- Non-bundled conversation hooks (`llm_input`, `llm_output`, `before_model_resolve`, `before_agent_reply`, `before_agent_run`, `before_agent_finalize`, `agent_end`) require `plugins.entries.<id>.hooks.allowConversationAccess=true`.
Use `--link` to avoid copying a local directory (adds to `plugins.load.paths`):
@@ -384,7 +386,7 @@ The `--json` flag outputs a machine-readable report suitable for scripting and a
openclaw plugins doctor
```
`doctor` reports plugin load errors, manifest/discovery diagnostics, and compatibility notices. When everything is clean it prints `No plugin issues detected.`
`doctor` reports plugin load errors, manifest/discovery diagnostics, compatibility notices, and stale plugin config references such as missing plugin slots. When the install tree and plugin config are clean it prints `No plugin issues detected.` If stale config remains but the install tree is otherwise healthy, the summary says so instead of implying full plugin health.
If a configured plugin is present on disk but blocked by the loader's path-safety checks, config validation keeps the plugin entry and reports it as `present but blocked`. Fix the preceding blocked-plugin diagnostic, such as path ownership or world-writable permissions, instead of removing the `plugins.entries.<id>` or `plugins.allow` config.

View File

@@ -35,9 +35,8 @@ openclaw qr --url wss://gateway.example/ws
- `--token` and `--password` are mutually exclusive.
- The setup code itself now carries an opaque short-lived `bootstrapToken`, not the shared gateway token/password.
- In the built-in node/operator bootstrap flow, the primary node token still lands with `scopes: []`.
- If bootstrap handoff also issues an operator token, it stays bounded to the bootstrap allowlist: `operator.approvals`, `operator.read`, `operator.talk.secrets`, `operator.write`.
- Bootstrap scope checks are role-prefixed. That operator allowlist only satisfies operator requests; non-operator roles still need scopes under their own role prefix.
- Built-in setup-code bootstrap is node-only. After approval, the primary node token lands with `scopes: []`.
- The built-in setup-code flow does not return a handed-off operator token; operator access requires a separate approved operator pairing or token flow.
- Mobile pairing fails closed for Tailscale/public `ws://` gateway URLs. Private LAN addresses and `.local` Bonjour hosts remain supported over `ws://`, but Tailscale/public mobile routes should use Tailscale Serve/Funnel or a `wss://` gateway URL.
- With `--remote`, OpenClaw requires either `gateway.remote.url` or
`gateway.tailscale.mode=serve|funnel`.

View File

@@ -46,7 +46,7 @@ wired end-to-end.
- Runs are serialized per session key (session lane) and optionally through a global lane.
- This prevents tool/session races and keeps session history consistent.
- Messaging channels can choose queue modes (collect/steer/followup) that feed this lane system.
- Messaging channels can choose queue modes (steer/followup/collect/interrupt) that feed this lane system.
See [Command Queue](/concepts/queue).
- Transcript writes are also protected by a session write lock on the session file. The lock is
process-aware and file-based, so it catches writers that bypass the in-process queue or come from

View File

@@ -84,17 +84,15 @@ Legacy session folders from other tools are not read.
## Steering while streaming
When queue mode is `steer`, inbound messages are injected into the current run.
Queued steering is delivered **after the current assistant turn finishes
executing its tool calls**, before the next LLM call. Pi drains all pending
steering messages together for `steer`; legacy `queue` drains one message per
model boundary. Steering no longer skips remaining tool calls from the current
assistant message.
Inbound prompts that arrive mid-run are steered into the current run by default.
Steering is delivered **after the current assistant turn finishes executing its
tool calls**, before the next LLM call, and no longer skips remaining tool calls
from the current assistant message.
When queue mode is `followup` or `collect`, inbound messages are held until the
current turn ends, then a new agent turn starts with the queued payloads. See
[Queue](/concepts/queue) and [Steering queue](/concepts/queue-steering) for mode
and boundary behavior.
`/queue steer` is the default active-run behavior. `/queue followup` and
`/queue collect` make messages wait for a later turn instead of steering.
`/queue interrupt` aborts the active run instead. See [Queue](/concepts/queue)
and [Steering queue](/concepts/queue-steering) for queue and boundary behavior.
Block streaming sends completed assistant blocks as soon as they finish; it is
**off by default** (`agents.defaults.blockStreamingDefault: "off"`).

View File

@@ -125,14 +125,14 @@ default) and per-channel overrides like `channels.slack.historyLimit` or
## Queueing and followups
If a run is already active, inbound messages can be queued, steered into the
current run, or collected for a followup turn.
If a run is already active, inbound messages are steered into the current run by
default. `messages.queue` selects whether active-run messages steer, queue for
later, collect into one later turn, or interrupt the active run.
- Configure via `messages.queue` (and `messages.queue.byChannel`).
- Default mode is `steer`, with a 500ms followup debounce when steering falls
back to queued followup delivery.
- Modes: `steer`, `followup`, `collect`, `steer-backlog`, `interrupt`, and the
legacy one-at-a-time `queue` mode.
- Default mode is `steer`, with a 500ms debounce for Codex steering batches and
followup/collect queues.
- Modes: `steer`, `followup`, `collect`, and `interrupt`.
Details: [Command queue](/concepts/queue) and [Steering queue](/concepts/queue-steering).

View File

@@ -3,14 +3,15 @@ summary: "How active-run steering queues messages at runtime boundaries"
read_when:
- Explaining how steer behaves while an agent is using tools
- Changing active-run queue behavior or runtime steering integration
- Comparing steer, queue, collect, and followup modes
- Comparing steering with followup, collect, and interrupt queue modes
title: "Steering queue"
---
When a message arrives while a session run is already streaming, OpenClaw can
send that message into the active runtime instead of starting another run for
the same session. The public modes are runtime-neutral; Pi and the native Codex
app-server harness implement the delivery details differently.
When a normal prompt arrives while a session run is already streaming, OpenClaw
tries to send that prompt into the active runtime by default when the queue mode
is `steer`. No config entry and no queue directive are required for that default
behavior. Pi and the native Codex app-server harness implement the delivery
details differently.
## Runtime boundary
@@ -27,44 +28,40 @@ This keeps tool results paired with the assistant message that requested them,
then lets the next model call see the latest user input.
The native Codex app-server harness exposes `turn/steer` instead of Pi's
internal steering queue. OpenClaw adapts the same modes there:
- `steer` batches queued messages for the configured quiet window, then sends a
single `turn/steer` request with all collected user input in arrival order.
- `queue` keeps the legacy serialized shape by sending separate `turn/steer`
requests.
- `followup`, `collect`, `steer-backlog`, and `interrupt` stay OpenClaw-owned
queue behavior around the active Codex turn.
internal steering queue. OpenClaw batches queued prompts for the configured
quiet window, then sends a single `turn/steer` request with all collected user
input in arrival order.
Codex review and manual compaction turns reject same-turn steering. When a
runtime cannot accept steering, OpenClaw falls back to the followup queue where
that mode allows it.
runtime cannot accept steering in `steer` mode, OpenClaw waits for the active
run to finish before starting the prompt.
This page explains queue-mode steering for normal inbound messages. For the
explicit `/steer <message>` command, see [Steer](/tools/steer).
This page explains queue-mode steering for normal inbound messages when the mode
is `steer`. If the mode is `followup` or `collect`, normal messages do not enter
this steering path; they wait until the active run finishes. For the explicit
`/steer <message>` command, see [Steer](/tools/steer).
## Modes
| Mode | Active-run behavior | Later followup behavior |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| `steer` | Injects all queued steering messages together at the next runtime boundary. This is the default. | Falls back to followup only when steering is unavailable. |
| `queue` | Legacy one-at-a-time steering. Pi injects one queued message per model boundary; Codex sends separate `turn/steer` requests. | Falls back to followup only when steering is unavailable. |
| `steer-backlog` | Same active-run steering behavior as `steer`. | Also keeps the same message for a later followup turn. |
| `followup` | Does not steer the current run. | Runs queued messages later. |
| `collect` | Does not steer the current run. | Coalesces compatible queued messages into one later turn after the debounce window. |
| `interrupt` | Aborts the active run, then starts the newest message. | None. |
| Mode | Active-run behavior | Later behavior |
| ----------- | ------------------------------------------------------ | ----------------------------------------------------------------------------------- |
| `steer` | Steers the prompt into the active runtime when it can. | Waits for the active run to finish if steering is unavailable. |
| `followup` | Does not steer. | Runs queued messages later after the active run ends. |
| `collect` | Does not steer. | Coalesces compatible queued messages into one later turn after the debounce window. |
| `interrupt` | Aborts the active run instead of steering it. | Starts the newest message after aborting. |
## Burst example
If four users send messages while the agent is executing a tool call:
- `steer`: the active runtime receives all four messages in arrival order before
its next model decision. Pi drains them at the next model boundary; Codex
receives them as one batched `turn/steer`.
- `queue`: legacy serialized steering. Pi injects one queued message at a time;
Codex receives separate `turn/steer` requests.
- `collect`: OpenClaw waits until the active run ends, then creates a followup
turn with compatible queued messages after the debounce window.
- With default behavior, the active runtime receives all four messages in
arrival order before its next model decision. Pi drains them at the next model
boundary; Codex receives them as one batched `turn/steer`.
- With `/queue collect`, OpenClaw does not steer. It waits until the active run
ends, then creates a followup turn with compatible queued messages after the
debounce window.
- With `/queue interrupt`, OpenClaw aborts the active run and starts the newest
message instead of steering.
## Scope
@@ -73,18 +70,17 @@ session, change the active run's tool policy, or split messages by sender. In
multi-user channels, inbound prompts already include sender and route context, so
the next model call can see who sent each message.
Use `collect` when you want OpenClaw to build a later followup turn that can
coalesce compatible messages and preserve followup queue drop policy. Use
`queue` only when you need the older one-at-a-time steering behavior.
Use `followup` or `collect` when you want messages to queue by default instead
of steering the active run. Use `interrupt` when the newest prompt should
replace the active run.
## Debounce
`messages.queue.debounceMs` applies to followup delivery, including `collect`,
`followup`, `steer-backlog`, and `steer` fallback when active-run steering is not
available. For Pi, active `steer` itself does not use the debounce timer because
Pi naturally batches messages until the next model boundary. For the native
Codex harness, OpenClaw uses the same debounce value as the quiet window before
sending the batched `turn/steer`.
`messages.queue.debounceMs` applies to queued `followup` and `collect` delivery.
In `steer` mode with the native Codex harness, it also sets the quiet window
before sending batched `turn/steer`. For Pi, active steering itself does not use
the debounce timer because Pi naturally batches messages until the next model
boundary.
## Related

View File

@@ -30,25 +30,20 @@ When unset, all inbound channel surfaces use:
- `cap: 20`
- `drop: "summarize"`
`steer` is the default because it keeps the active model turn responsive without
starting a second session run. It drains all steering messages that arrived
before the next model boundary. If the current run cannot accept steering,
OpenClaw falls back to a followup queue entry.
Same-turn steering is the default. A prompt that arrives mid-run is injected
into the active runtime when the run can accept steering, so no second session
run is started. If the active run cannot accept steering, OpenClaw waits for the
active run to finish before starting the prompt.
## Queue modes
Inbound messages can steer the current run, wait for a followup turn, or do both:
`/queue` controls what normal inbound messages do while a session already has
an active run:
- `steer`: queue steering messages into the active runtime. Pi delivers all pending steering messages **after the current assistant turn finishes executing its tool calls**, before the next LLM call; Codex app-server receives one batched `turn/steer`. If the run is not actively streaming or steering is unavailable, OpenClaw falls back to a followup queue entry.
- `queue` (legacy): old one-at-a-time steering. Pi delivers one queued steering message at each model boundary; Codex app-server receives separate `turn/steer` requests. Prefer `steer` unless you need the previous serialized behavior.
- `followup`: enqueue each message for a later agent turn after the current run ends.
- `collect`: coalesce queued messages into a **single** followup turn after the quiet window. If messages target different channels/threads, they drain individually to preserve routing.
- `steer-backlog` (aka `steer+backlog`): steer now **and** preserve the same message for a followup turn.
- `interrupt` (legacy): abort the active run for that session, then run the newest message.
Steer-backlog means you can get a followup response after the steered run, so
streaming surfaces can look like duplicates. Prefer `collect`/`steer` if you want
one response per inbound message.
- `steer`: inject messages into the active runtime. Pi delivers all pending steering messages **after the current assistant turn finishes executing its tool calls**, before the next LLM call; Codex app-server receives one batched `turn/steer`. If the run is not actively streaming or steering is unavailable, OpenClaw waits until the active run ends before starting the prompt.
- `followup`: do not steer. Enqueue each message for a later agent turn after the current run ends.
- `collect`: do not steer. Coalesce queued messages into a **single** followup turn after the quiet window. If messages target different channels/threads, they drain individually to preserve routing.
- `interrupt`: abort the active run for that session, then run the newest message.
For runtime-specific timing and dependency behavior, see
[Steering queue](/concepts/queue-steering). For the explicit `/steer <message>`
@@ -72,9 +67,10 @@ Configure globally or per channel via `messages.queue`:
## Queue options
Options apply to `followup`, `collect`, and `steer-backlog` (and to `steer` or legacy `queue` when steering falls back to followup):
Options apply to queued delivery. `debounceMs` also sets the Codex steering
quiet window in `steer` mode:
- `debounceMs`: quiet window before draining queued followups. Bare numbers are milliseconds; units `ms`, `s`, `m`, `h`, and `d` are accepted by `/queue` options.
- `debounceMs`: quiet window before draining queued followups or collect batches; in Codex `steer` mode, quiet window before sending batched `turn/steer`. Bare numbers are milliseconds; units `ms`, `s`, `m`, `h`, and `d` are accepted by `/queue` options.
- `cap`: max queued messages per session. Values below `1` are ignored.
- `drop: "summarize"`: default. Drop the oldest queued entries as needed, keep compact summaries, and inject them as a synthetic followup prompt.
- `drop: "old"`: drop the oldest queued entries as needed, without preserving summaries.
@@ -99,7 +95,7 @@ keys.
## Per-session overrides
- Send `/queue <mode>` as a standalone command to store the mode for the current session.
- Send `/queue <steer|followup|collect|interrupt>` as a standalone command to store the queue mode for the current session.
- Options can be combined: `/queue collect debounce:0.5s cap:25 drop:summarize`
- `/queue default` or `/queue reset` clears the session override.

View File

@@ -134,7 +134,9 @@ sub-agents. It supports:
`sessions_spawn` creates an isolated session for a background task by default.
It is always non-blocking -- it returns immediately with a `runId` and
`childSessionKey`.
`childSessionKey`. Native sub-agent runs receive the delegated task in the
child session's first visible `[Subagent Task]` message, while the system
prompt carries only sub-agent runtime rules and routing context.
Key options:

View File

@@ -1191,11 +1191,12 @@
"tools/plugin",
"plugins/manage-plugins",
"plugins/community",
"plugins/plugin-inventory",
"plugins/reference",
"plugins/bundles",
"plugins/dependency-resolution",
"plugins/install-overrides",
"plugins/bundles"
]
},
{
"group": "Bundled plugin guides",
"pages": [
"plugins/codex-harness",
"plugins/codex-computer-use",
"plugins/google-meet",
@@ -1203,40 +1204,20 @@
"plugins/voice-call",
"plugins/memory-wiki",
"plugins/memory-lancedb",
"plugins/message-presentation",
"plugins/oc-path",
"plugins/skill-workshop",
"plugins/zalouser",
{
"group": "Building plugins",
"pages": [
"plugins/building-plugins",
"plugins/hooks",
"plugins/sdk-channel-plugins",
"plugins/sdk-channel-message",
"plugins/sdk-provider-plugins",
"plugins/cli-backend-plugins",
"plugins/adding-capabilities",
"plugins/compatibility",
"plugins/sdk-migration"
]
},
{
"group": "Plugin SDK reference",
"pages": [
"plugins/sdk-overview",
"plugins/sdk-subpaths",
"plugins/sdk-entrypoints",
"plugins/sdk-runtime",
"plugins/sdk-channel-turn",
"plugins/sdk-agent-harness",
"plugins/sdk-setup",
"plugins/sdk-testing",
"plugins/manifest",
"plugins/architecture",
"plugins/architecture-internals"
]
}
"plugins/zalouser"
]
},
{
"group": "Building plugins",
"pages": [
"plugins/building-plugins",
"plugins/sdk-channel-plugins",
"plugins/sdk-provider-plugins",
"plugins/cli-backend-plugins",
"plugins/hooks",
"plugins/adding-capabilities"
]
},
{
@@ -1353,7 +1334,6 @@
"pages": [
"clawhub/api",
"clawhub/http-api",
"clawhub/security",
"clawhub/acceptable-usage"
]
}
@@ -1387,6 +1367,7 @@
"providers/deepgram",
"providers/deepinfra",
"providers/deepseek",
"providers/ds4",
"providers/elevenlabs",
"providers/fal",
"providers/fireworks",
@@ -1717,6 +1698,41 @@
"plugins/codex-native-plugins"
]
},
{
"group": "Plugin reference",
"pages": [
"plugins/plugin-inventory",
"plugins/reference",
"plugins/dependency-resolution",
"plugins/install-overrides"
]
},
{
"group": "Plugin SDK reference",
"pages": [
"plugins/sdk-overview",
"plugins/sdk-subpaths",
"plugins/sdk-entrypoints",
"plugins/sdk-runtime",
"plugins/sdk-agent-harness",
"plugins/sdk-setup",
"plugins/sdk-testing",
"plugins/manifest"
]
},
{
"group": "Plugin maintainer reference",
"pages": [
"plugins/architecture",
"plugins/architecture-internals",
"plugins/sdk-migration",
"plugins/compatibility",
"plugins/sdk-channel-message",
"plugins/sdk-channel-turn",
"plugins/sdk-channel-ingress",
"plugins/message-presentation"
]
},
{
"group": "Templates",
"pages": [

View File

@@ -100,8 +100,8 @@ The Gateway advertises small non-secret hints to make UI flows convenient:
- `canvasPort=<port>` (only when the canvas host is enabled; currently the same as `gatewayPort`)
- `transport=gateway`
- `tailnetDns=<magicdns>` (mDNS full mode only, optional hint when Tailnet is available)
- `sshPort=<port>` (mDNS full mode only; wide-area DNS-SD may omit it)
- `cliPath=<path>` (mDNS full mode only; wide-area DNS-SD still writes it as a remote-install hint)
- `sshPort=<port>` (full mode only; omitted in minimal and off modes)
- `cliPath=<path>` (full mode only; omitted in minimal and off modes)
Security notes:
@@ -176,9 +176,11 @@ openclaw plugins enable bonjour
```
When enabled, Bonjour uses `discovery.mdns.mode` to decide how much TXT metadata
to publish. The default mode is `minimal`; use `full` only when local clients need
`cliPath` or `sshPort` hints, and use `off` to suppress LAN multicast without
changing plugin enablement.
to publish. The same mode controls optional TXT hints in wide-area DNS-SD records.
The default mode is `minimal`; use `full` only when clients need `cliPath` or
`sshPort` hints. Use `off` to suppress LAN multicast without changing plugin
enablement; wide-area DNS-SD can still publish the minimal Gateway beacon when
`discovery.wideArea.enabled` is true.
## When to disable Bonjour

View File

@@ -542,7 +542,7 @@ Periodic heartbeat runs.
includeSystemPromptSection: true, // default: true; false omits the Heartbeat section from the system prompt
lightContext: false, // default: false; true keeps only HEARTBEAT.md from workspace bootstrap files
isolatedSession: false, // default: false; true runs each heartbeat in a fresh session (no conversation history)
skipWhenBusy: false, // default: false; true also waits for subagent/nested lanes
skipWhenBusy: false, // default: false; true also waits for this agent's subagent/nested lanes
session: "main",
to: "+15555550123",
directPolicy: "allow", // allow (default) | block
@@ -564,7 +564,7 @@ Periodic heartbeat runs.
- `directPolicy`: direct/DM delivery policy. `allow` (default) permits direct-target delivery. `block` suppresses direct-target delivery and emits `reason=dm-blocked`.
- `lightContext`: when true, heartbeat runs use lightweight bootstrap context and keep only `HEARTBEAT.md` from workspace bootstrap files.
- `isolatedSession`: when true, each heartbeat runs in a fresh session with no prior conversation history. Same isolation pattern as cron `sessionTarget: "isolated"`. Reduces per-heartbeat token cost from ~100K to ~2-5K tokens.
- `skipWhenBusy`: when true, heartbeat runs defer on extra busy lanes: subagent or nested command work. Cron lanes always defer heartbeats, even without this flag.
- `skipWhenBusy`: when true, heartbeat runs defer on that agent's extra busy lanes: its own session-keyed subagent or nested command work. Cron lanes always defer heartbeats, even without this flag.
- Per-agent: set `agents.list[].heartbeat`. When any agent defines `heartbeat`, **only those agents** run heartbeats.
- Heartbeats run full agent turns — shorter intervals burn more tokens.
@@ -616,6 +616,36 @@ Periodic heartbeat runs.
- `notifyUser`: when `true`, sends brief notices to the user when compaction starts and when it completes (for example, "Compacting context..." and "Compaction complete"). Disabled by default to keep compaction silent.
- `memoryFlush`: silent agentic turn before auto-compaction to store durable memories. Set `model` to an exact provider/model such as `ollama/qwen3:8b` when this housekeeping turn should stay on a local model; the override does not inherit the active session fallback chain. Skipped when workspace is read-only.
### `agents.defaults.runRetries`
Outer run loop retry iteration boundaries for the embedded Pi runner to prevent infinite execution loops during failure recovery. Note that this setting currently only applies to the embedded agent runtime, not ACP or CLI runtimes.
```json5
{
agents: {
defaults: {
runRetries: {
base: 24,
perProfile: 8,
min: 32,
max: 160,
},
},
list: [
{
id: "main",
runRetries: { max: 50 }, // optional per-agent overrides
},
],
},
}
```
- `base`: base number of run retry iterations for the outer run loop. Default: `24`.
- `perProfile`: additional run retry iterations granted per fallback profile candidate. Default: `8`.
- `min`: minimum absolute limit for run retry iterations. Default: `32`.
- `max`: maximum absolute limit for run retry iterations to prevent runaway execution. Default: `160`.
### `agents.defaults.contextPruning`
Prunes **old tool results** from in-memory context before sending to the LLM. Does **not** modify session history on disk.
@@ -1250,13 +1280,13 @@ See [Multi-Agent Sandbox & Tools](/tools/multi-agent-sandbox-tools) for preceden
ackReactionScope: "group-mentions", // group-mentions | group-all | direct | all
removeAckAfterReply: false,
queue: {
mode: "steer", // steer | queue (legacy one-at-a-time) | followup | collect | steer-backlog | steer+backlog | interrupt
mode: "followup", // steer | followup | collect | interrupt
debounceMs: 500,
cap: 20,
drop: "summarize", // old | new | summarize
byChannel: {
whatsapp: "steer",
telegram: "steer",
whatsapp: "followup",
telegram: "followup",
},
},
inbound: {

View File

@@ -335,6 +335,7 @@ WhatsApp runs through the gateway's web channel (Baileys Web). It starts automat
- Use `user:<id>` (DM) or `channel:<id>` (guild channel) for delivery targets; bare numeric IDs are rejected.
- Guild slugs are lowercase with spaces replaced by `-`; channel keys use the slugged name (no `#`). Prefer guild IDs.
- Bot-authored messages are ignored by default. `allowBots: true` enables them; use `allowBots: "mentions"` to only accept bot messages that mention the bot (own messages still filtered).
- Channels that support bot-authored inbound messages can use shared [bot loop protection](/channels/bot-loop-protection). Set `channels.defaults.botLoopProtection` for baseline pair budgets, then override the channel or account only when one surface needs different limits.
- `channels.discord.guilds.<id>.ignoreOtherMentions` (and channel overrides) drops messages that mention another user or role but not the bot (excluding @everyone/@here).
- `channels.discord.mentionAliases` maps stable outbound `@handle` text to Discord user IDs before sending, so known teammates can be mentioned deterministically even when the transient directory cache is empty. Per-account overrides live under `channels.discord.accounts.<accountId>.mentionAliases`.
- `maxLinesPerMessage` (default 17) splits tall messages even when under 2000 chars.

View File

@@ -113,18 +113,18 @@ Save to `~/.openclaw/openclaw.json` and you can DM the bot from that number.
visibleReplies: "message_tool", // normal final replies stay private in groups/channels
},
queue: {
mode: "steer",
mode: "followup",
debounceMs: 500,
cap: 20,
drop: "summarize",
byChannel: {
whatsapp: "steer",
telegram: "steer",
discord: "steer",
slack: "steer",
signal: "steer",
imessage: "steer",
webchat: "steer",
whatsapp: "followup",
telegram: "followup",
discord: "collect",
slack: "collect",
signal: "followup",
imessage: "followup",
webchat: "followup",
},
},
},

View File

@@ -50,7 +50,7 @@ Example config:
directPolicy: "allow", // default: allow direct/DM targets; set "block" to suppress
lightContext: true, // optional: only inject HEARTBEAT.md from bootstrap files
isolatedSession: true, // optional: fresh session each run (no conversation history)
skipWhenBusy: true, // optional: also defer when subagent or nested lanes are busy
skipWhenBusy: true, // optional: also defer when this agent's subagent or nested lanes are busy
// activeHours: { start: "08:00", end: "24:00" },
// includeReasoning: true, // optional: send separate `Reasoning:` message too
},
@@ -66,7 +66,7 @@ Example config:
- The heartbeat prompt is sent **verbatim** as the user message. The system prompt includes a "Heartbeat" section only when heartbeats are enabled for the default agent, and the run is flagged internally.
- When heartbeats are disabled with `0m`, normal runs also omit `HEARTBEAT.md` from bootstrap context so the model does not see heartbeat-only instructions.
- Active hours (`heartbeat.activeHours`) are checked in the configured timezone. Outside the window, heartbeats are skipped until the next tick inside the window.
- Heartbeats automatically defer while cron work is active or queued. Set `heartbeat.skipWhenBusy: true` to defer on extra busy lanes (subagent or nested command work) as well; this is useful for local Ollama and other constrained single-runtime hosts.
- Heartbeats automatically defer while cron work is active or queued. Set `heartbeat.skipWhenBusy: true` to also defer an agent on its own session-keyed subagent or nested command lanes; sibling agents no longer pause just because another agent has subagent work in flight.
## What the heartbeat prompt is for
@@ -101,7 +101,7 @@ Outside heartbeats, stray `HEARTBEAT_OK` at the start/end of a message is stripp
includeReasoning: false, // default: false (deliver separate Reasoning: message when available)
lightContext: false, // default: false; true keeps only HEARTBEAT.md from workspace bootstrap files
isolatedSession: false, // default: false; true runs each heartbeat in a fresh session (no conversation history)
skipWhenBusy: false, // default: false; true also waits for subagent/nested lanes
skipWhenBusy: false, // default: false; true also waits for this agent's subagent/nested lanes
target: "last", // default: none | options: last | none | <channel id> (core or plugin, e.g. "imessage")
to: "+15551234567", // optional channel-specific override
accountId: "ops-bot", // optional multi-account channel id
@@ -235,7 +235,7 @@ Use `accountId` to target a specific account on multi-account channels like Tele
When true, each heartbeat runs in a fresh session with no prior conversation history. Uses the same isolation pattern as cron `sessionTarget: "isolated"`. Dramatically reduces per-heartbeat token cost. Combine with `lightContext: true` for maximum savings. Delivery routing still uses the main session context.
</ParamField>
<ParamField path="skipWhenBusy" type="boolean" default="false">
When true, heartbeat runs defer on extra busy lanes: subagent or nested command work. Cron lanes always defer heartbeats, even without this flag, so local-model hosts do not run cron and heartbeat prompts at the same time.
When true, heartbeat runs defer on that agent's extra busy lanes: its own session-keyed subagent or nested command work. Cron lanes always defer heartbeats, even without this flag, so local-model hosts do not run cron and heartbeat prompts at the same time.
</ParamField>
<ParamField path="session" type="string">
Optional session key for heartbeat runs.
@@ -295,7 +295,7 @@ Use `accountId` to target a specific account on multi-account channels like Tele
- To deliver to a specific channel/recipient, set `target` + `to`. With `target: "last"`, delivery uses the last external channel for that session.
- Heartbeat deliveries allow direct/DM targets by default. Set `directPolicy: "block"` to suppress direct-target sends while still running the heartbeat turn.
- If the main queue, target session lane, cron lane, or an active cron job is busy, the heartbeat is skipped and retried later.
- If `skipWhenBusy: true`, subagent and nested lanes also defer heartbeat runs.
- If `skipWhenBusy: true`, this agent's session-keyed subagent and nested lanes also defer heartbeat runs. Other agents' busy lanes do not defer this agent.
- If `target` resolves to no external destination, the run still happens but no outbound message is sent.
</Accordion>

View File

@@ -142,6 +142,9 @@ OpenClaw.
## ds4 example
For the full setup, context sizing guidance, and verification commands, see
[ds4](/providers/ds4).
```json5
{
models: {
@@ -152,18 +155,20 @@ OpenClaw.
api: "openai-completions",
timeoutSeconds: 300,
localService: {
command: "/Users/you/Projects/oss/ds4/ds4-server",
command: "<DS4_DIR>/ds4-server",
args: [
"--model",
"/Users/you/Projects/oss/ds4/ds4flash.gguf",
"<DS4_DIR>/ds4flash.gguf",
"--host",
"127.0.0.1",
"--port",
"18000",
"--ctx",
"393216",
"32768",
"--tokens",
"128",
],
cwd: "/Users/you/Projects/oss/ds4",
cwd: "<DS4_DIR>",
healthUrl: "http://127.0.0.1:18000/v1/models",
readyTimeoutMs: 300000,
idleStopMs: 0,

View File

@@ -20,10 +20,11 @@ Aim high: **≥2 maxed-out Mac Studios or an equivalent GPU rig (~$30k+)** for a
| Backend | Use when |
| ---------------------------------------------------- | --------------------------------------------------------------------------- |
| [ds4](/providers/ds4) | Local DeepSeek V4 Flash on macOS Metal with OpenAI-compatible tool calls |
| [LM Studio](/providers/lmstudio) | First-time local setup, GUI loader, native Responses API |
| [Ollama](/providers/ollama) | CLI workflow, model library, hands-off systemd service |
| MLX / vLLM / SGLang | High-throughput self-hosted serving with an OpenAI-compatible HTTP endpoint |
| LiteLLM / OAI-proxy / custom OpenAI-compatible proxy | You front another model API and need OpenClaw to treat it as OpenAI |
| MLX / vLLM / SGLang | High-throughput self-hosted serving with an OpenAI-compatible HTTP endpoint |
| [Ollama](/providers/ollama) | CLI workflow, model library, hands-off systemd service |
Use Responses API (`api: "openai-responses"`) when the backend supports it (LM Studio does). Otherwise stick to Chat Completions (`api: "openai-completions"`).

View File

@@ -201,6 +201,12 @@ Set `stream: true` to receive Server-Sent Events (SSE):
- `tool_choice`: `"auto"`, `"none"`
- `messages[*].role: "tool"` follow-up turns
- `messages[*].tool_call_id` for binding tool results back to a prior tool call
- `max_completion_tokens`: number; per-call cap for total completion tokens (reasoning tokens included). Current OpenAI Chat Completions field name; preferred when both `max_completion_tokens` and `max_tokens` are sent.
- `max_tokens`: number; legacy alias accepted for backwards compatibility. Ignored when `max_completion_tokens` is also present.
- `temperature`: number; best-effort sampling temperature forwarded to the upstream provider via the agent stream-param channel.
- `top_p`: number; best-effort nucleus sampling forwarded to the upstream provider via the agent stream-param channel.
When either token-cap field is set, the value is forwarded to the upstream provider via the agent stream-param channel. The actual wire field name sent to the upstream provider is chosen by the provider transport: `max_completion_tokens` for OpenAI-family endpoints, and `max_tokens` for providers that only accept the legacy name (such as Mistral and Chutes). Sampling fields (`temperature`, `top_p`) follow the same stream-param channel; the ChatGPT-based Codex Responses backend strips them server-side since it uses fixed sampling.
### Unsupported variants

View File

@@ -74,6 +74,8 @@ The request follows the OpenResponses API with item-based input. Current support
- `tool_choice`: filter or require client tools.
- `stream`: enables SSE streaming.
- `max_output_tokens`: best-effort output limit (provider dependent).
- `temperature`: best-effort sampling temperature forwarded to the provider. Ignored by the ChatGPT-based Codex Responses backend, which uses fixed server-side sampling.
- `top_p`: best-effort nucleus sampling forwarded to the provider. Same Codex Responses caveat as `temperature`.
- `user`: stable session routing.
Accepted but **currently ignored**:

View File

@@ -147,32 +147,24 @@ When a device token is issued, `hello-ok` also includes:
}
```
During trusted bootstrap handoff, `hello-ok.auth` may also include additional
bounded role entries in `deviceTokens`:
Built-in QR/setup-code bootstrap is node-only. After the owner approves the
pending node request, `hello-ok.auth` includes the primary node token:
```json
{
"auth": {
"deviceToken": "…",
"role": "node",
"scopes": [],
"deviceTokens": [
{
"deviceToken": "…",
"role": "operator",
"scopes": ["operator.approvals", "operator.read", "operator.talk.secrets", "operator.write"]
}
]
"scopes": []
}
}
```
For the built-in node/operator bootstrap flow, the primary node token stays
`scopes: []` and any handed-off operator token stays bounded to the bootstrap
operator allowlist (`operator.approvals`, `operator.read`,
`operator.talk.secrets`, `operator.write`). Bootstrap scope checks stay
role-prefixed: operator entries only satisfy operator requests, and non-operator
roles still need scopes under their own role prefix.
The built-in setup-code flow does not include additional `deviceTokens` entries
or hand off an operator token. Client authors should treat the optional
`hello-ok.auth.deviceTokens` field as legacy/custom bootstrap extension data:
persist it only when present on a trusted transport, and do not require it for
built-in pairing.
### Node example
@@ -372,7 +364,7 @@ enumeration of `src/gateway/server-methods/*.ts`.
<Accordion title="Talk and TTS">
- `talk.catalog` returns the read-only Talk provider catalog for speech, streaming transcription, and realtime voice. It includes provider ids, labels, configured state, exposed model/voice ids, canonical modes, transports, brain strategies, and realtime audio/capability flags without returning provider secrets or mutating global config.
- `talk.config` returns the effective Talk config payload; `includeSecrets` requires `operator.talk.secrets` (or `operator.admin`).
- `talk.session.create` creates a Gateway-owned Talk session for `realtime/gateway-relay`, `transcription/gateway-relay`, or `stt-tts/managed-room`. `brain: "direct-tools"` requires `operator.admin`.
- `talk.session.create` creates a Gateway-owned Talk session for `realtime/gateway-relay`, `transcription/gateway-relay`, or `stt-tts/managed-room`. For `stt-tts/managed-room`, `operator.write` callers that pass `sessionKey` must also pass `spawnedBy` for scoped session-key visibility; unscoped `sessionKey` creation and `brain: "direct-tools"` require `operator.admin`.
- `talk.session.join` validates a managed-room session token, emits `session.ready` or `session.replaced` events as needed, and returns room/session metadata plus recent Talk events without the plaintext token or stored token hash.
- `talk.session.appendAudio` appends base64 PCM input audio to Gateway-owned realtime relay and transcription sessions.
- `talk.session.startTurn`, `talk.session.endTurn`, and `talk.session.cancelTurn` drive managed-room turn lifecycle with stale-turn rejection before state is cleared.
@@ -476,7 +468,9 @@ enumeration of `src/gateway/server-methods/*.ts`.
### Common event families
- `chat`: UI chat updates such as `chat.inject` and other transcript-only chat
events.
events. In protocol v4, delta payloads carry `deltaText`; `message` remains
the cumulative assistant snapshot. Non-prefix replacements set `replace=true`
and use `deltaText` as the replacement text.
- `session.message` and `session.tool`: transcript/event-stream updates for a
subscribed session.
- `sessions.changed`: session index or metadata changed.
@@ -632,8 +626,8 @@ terminal summary, and sanitized error text.
- `PROTOCOL_VERSION` lives in `src/gateway/protocol/version.ts`.
- Clients send `minProtocol` + `maxProtocol`; the server rejects ranges that
do not include its current protocol. Native clients use a v3 lower bound so
additive v4 clients can still reach v3 gateways.
do not include its current protocol. Current clients and servers require
protocol v4.
- Schemas + models are generated from TypeBox definitions:
- `pnpm protocol:gen`
- `pnpm protocol:gen:swift`
@@ -647,7 +641,7 @@ stable across protocol v4 and are the expected baseline for third-party clients.
| Constant | Default | Source |
| ----------------------------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| `PROTOCOL_VERSION` | `4` | `src/gateway/protocol/version.ts` |
| `MIN_CLIENT_PROTOCOL_VERSION` | `3` | `src/gateway/protocol/version.ts` |
| `MIN_CLIENT_PROTOCOL_VERSION` | `4` | `src/gateway/protocol/version.ts` |
| Request timeout (per RPC) | `30_000` ms | `src/gateway/client.ts` (`requestTimeoutMs`) |
| Preauth / connect-challenge timeout | `15_000` ms | `src/gateway/handshake-timeouts.ts` (config/env can raise the paired server/client budget) |
| Initial reconnect backoff | `1_000` ms | `src/gateway/client.ts` (`backoffMs`) |
@@ -694,9 +688,17 @@ rather than the pre-handshake defaults.
`AUTH_TOKEN_MISMATCH` retry is gated to **trusted endpoints only**
loopback, or `wss://` with a pinned `tlsFingerprint`. Public `wss://`
without pinning does not qualify.
- Additional `hello-ok.auth.deviceTokens` entries are bootstrap handoff tokens.
Persist them only when the connect used bootstrap auth on a trusted transport
such as `wss://` or loopback/local pairing.
- Built-in setup-code bootstrap returns only the primary node
`hello-ok.auth.deviceToken`; clients must not expect an additional operator
token in `hello-ok.auth.deviceTokens`.
- While built-in setup-code bootstrap is waiting for approval, `PAIRING_REQUIRED`
details include `recommendedNextStep: "wait_then_retry"`, `retryable: true`,
and `pauseReconnect: false`. Clients should keep reconnecting with the same
bootstrap token until the request is approved or the token becomes invalid.
- If an older or custom trusted bootstrap flow includes optional
`hello-ok.auth.deviceTokens` entries, persist them only when the connect used
bootstrap auth on a trusted transport such as `wss://` or loopback/local
pairing.
- If a client supplies an **explicit** `deviceToken` or explicit `scopes`, that
caller-requested scope set remains authoritative; cached scopes are only
reused when the client is reusing the stored per-device token.

View File

@@ -1459,7 +1459,7 @@ lives on the [Models FAQ](/help/faq-models).
- On `AUTH_TOKEN_MISMATCH`, trusted clients can attempt one bounded retry with a cached device token when the gateway returns retry hints (`canRetryWithDeviceToken=true`, `recommendedNextStep=retry_with_device_token`).
- That cached-token retry now reuses the cached approved scopes stored with the device token. Explicit `deviceToken` / explicit `scopes` callers still keep their requested scope set instead of inheriting cached scopes.
- Outside that retry path, connect auth precedence is explicit shared token/password first, then explicit `deviceToken`, then stored device token, then bootstrap token.
- Bootstrap token scope checks are role-prefixed. The built-in bootstrap operator allowlist only satisfies operator requests; node or other non-operator roles still need scopes under their own role prefix.
- Built-in setup-code bootstrap is node-only. After approval, it returns a node device token with `scopes: []` and does not return a handed-off operator token.
Fix:
@@ -1941,16 +1941,14 @@ lives on the [Models FAQ](/help/faq-models).
</Accordion>
<Accordion title='Why does it feel like the bot "ignores" rapid-fire messages?'>
Queue mode controls how new messages interact with an in-flight run. Use `/queue` to change modes:
Mid-run prompts are steered into the active run by default. Use `/queue` to choose active-run behavior:
- `steer` - queue all pending steering for the next model boundary in the current run
- `queue` - legacy one-at-a-time steering
- `followup` - run messages one at a time
- `collect` - batch messages and reply once
- `steer-backlog` - steer now, then process backlog
- `steer` - guide the active run at the next model boundary
- `followup` - queue messages and run them one at a time after the current run ends
- `collect` - queue compatible messages and reply once after the current run ends
- `interrupt` - abort current run and start fresh
Default mode is `steer`. You can add options like `debounce:0.5s cap:25 drop:summarize` for followup modes. See [Command queue](/concepts/queue) and [Steering queue](/concepts/queue-steering).
Default mode is `steer`. You can add options like `debounce:0.5s cap:25 drop:summarize` for queued modes. See [Command queue](/concepts/queue) and [Steering queue](/concepts/queue-steering).
</Accordion>
</AccordionGroup>

View File

@@ -13,14 +13,10 @@ For quick start, QA runners, unit/integration suites, and Docker flows, see
suites: model matrix, CLI backends, ACP, and media-provider live tests, plus
credential handling.
## Live: local profile smoke commands
## Live: local smoke commands
Source `~/.profile` before ad hoc live checks so provider keys and local tool
paths match your shell:
```bash
source ~/.profile
```
Export the needed provider key in the process environment before ad hoc live
checks.
Safe media smoke:
@@ -275,9 +271,9 @@ Docker notes:
- The Docker runner lives at `scripts/test-live-acp-bind-docker.sh`.
- By default, it runs the ACP bind smoke against the aggregate live CLI agents in sequence: `claude`, `codex`, then `gemini`.
- Use `OPENCLAW_LIVE_ACP_BIND_AGENTS=claude`, `OPENCLAW_LIVE_ACP_BIND_AGENTS=codex`, `OPENCLAW_LIVE_ACP_BIND_AGENTS=droid`, `OPENCLAW_LIVE_ACP_BIND_AGENTS=gemini`, or `OPENCLAW_LIVE_ACP_BIND_AGENTS=opencode` to narrow the matrix.
- It sources `~/.profile`, stages the matching CLI auth material into the container, then installs the requested live CLI (`@anthropic-ai/claude-code`, `@openai/codex`, Factory Droid via `https://app.factory.ai/cli`, `@google/gemini-cli`, or `opencode-ai`) if missing. The ACP backend itself is the embedded `acpx/runtime` package from the official `acpx` plugin.
- It stages the matching CLI auth material into the container, then installs the requested live CLI (`@anthropic-ai/claude-code`, `@openai/codex`, Factory Droid via `https://app.factory.ai/cli`, `@google/gemini-cli`, or `opencode-ai`) if missing. The ACP backend itself is the embedded `acpx/runtime` package from the official `acpx` plugin.
- The Droid Docker variant stages `~/.factory` for settings, forwards `FACTORY_API_KEY`, and requires that API key because local Factory OAuth/keyring auth is not portable into the container. It uses ACPX's built-in `droid exec --output-format acp` registry entry.
- The OpenCode Docker variant is a strict single-agent regression lane. It writes a temporary `OPENCODE_CONFIG_CONTENT` default model from `OPENCLAW_LIVE_ACP_BIND_OPENCODE_MODEL` (default `opencode/kimi-k2.6`) after sourcing `~/.profile`, and `pnpm test:docker:live-acp-bind:opencode` requires a bound assistant transcript instead of accepting the generic post-bind skip.
- The OpenCode Docker variant is a strict single-agent regression lane. It writes a temporary `OPENCODE_CONFIG_CONTENT` default model from `OPENCLAW_LIVE_ACP_BIND_OPENCODE_MODEL` (default `opencode/kimi-k2.6`), and `pnpm test:docker:live-acp-bind:opencode` requires a bound assistant transcript instead of accepting the generic post-bind skip.
- Direct `acpx` CLI calls are only a manual/workaround path for comparing behavior outside the Gateway. The Docker ACP bind smoke exercises OpenClaw's embedded `acpx` runtime backend.
## Live: Codex app-server harness smoke
@@ -309,7 +305,6 @@ Docker notes:
Local recipe:
```bash
source ~/.profile
OPENCLAW_LIVE_CODEX_HARNESS=1 \
OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=1 \
OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=1 \
@@ -321,15 +316,14 @@ OPENCLAW_LIVE_CODEX_HARNESS=1 \
Docker recipe:
```bash
source ~/.profile
pnpm test:docker:live-codex-harness
```
Docker notes:
- The Docker runner lives at `scripts/test-live-codex-harness-docker.sh`.
- It sources the mounted `~/.profile`, passes `OPENAI_API_KEY`, copies Codex CLI
auth files when present, installs `@openai/codex` into a writable mounted npm
- It passes `OPENAI_API_KEY`, copies Codex CLI auth files when present, installs
`@openai/codex` into a writable mounted npm
prefix, stages the source tree, then runs only the Codex-harness live test.
- Docker enables the image, MCP/tool, and Guardian probes by default. Set
`OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=0` or
@@ -357,7 +351,6 @@ Narrow, explicit allowlists are fastest and least flaky:
- Antigravity (OAuth): `OPENCLAW_LIVE_GATEWAY_MODELS="google-antigravity/claude-opus-4-6-thinking,google-antigravity/gemini-3-pro-high" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts`
- Google adaptive thinking smoke:
- If local keys live in shell profile: `source ~/.profile`
- Gemini 3 dynamic default: `pnpm openclaw qa manual --provider-mode live-frontier --model google/gemini-3.1-pro-preview --alt-model google/gemini-3.1-pro-preview --message '/think adaptive Reply exactly: GEMINI_ADAPTIVE_OK' --timeout-ms 180000`
- Gemini 2.5 dynamic budget: `pnpm openclaw qa manual --provider-mode live-frontier --model google/gemini-2.5-flash --alt-model google/gemini-2.5-flash --message '/think adaptive Reply exactly: GEMINI25_ADAPTIVE_OK' --timeout-ms 180000`
@@ -440,7 +433,8 @@ Live tests discover credentials the same way the CLI does. Practical implication
- Legacy state dir: `~/.openclaw/credentials/` (copied into the staged live home when present, but not the main profile-key store)
- Live local runs copy the active config, per-agent `auth-profiles.json` files, legacy `credentials/`, and supported external CLI auth dirs into a temp test home by default; staged live homes skip `workspace/` and `sandboxes/`, and `agents.*.workspace` / `agentDir` path overrides are stripped so probes stay off your real host workspace.
If you want to rely on env keys (e.g. exported in your `~/.profile`), run local tests after `source ~/.profile`, or use the Docker runners below (they can mount `~/.profile` into the container).
If you want to rely on env keys, export them before local tests or use the
Docker runners below with an explicit `OPENCLAW_PROFILE_FILE`.
## Deepgram live (audio transcription)
@@ -469,7 +463,7 @@ If you want to rely on env keys (e.g. exported in your `~/.profile`), run local
- Harness: `pnpm test:live:media image`
- Scope:
- Enumerates every registered image-generation provider plugin
- Loads missing provider env vars from your login shell (`~/.profile`) before probing
- Uses already-exported provider env vars before probing
- Uses live/env API keys ahead of stored auth profiles by default, so stale test keys in `auth-profiles.json` do not mask real shell credentials
- Skips providers with no usable auth/profile/model
- Runs each configured provider through the shared image-generation runtime:
@@ -517,7 +511,7 @@ request. Plugin dependencies are expected to be present before runtime load.
- Scope:
- Exercises the shared bundled music-generation provider path
- Currently covers Google and MiniMax
- Loads provider env vars from your login shell (`~/.profile`) before probing
- Uses already-exported provider env vars before probing
- Uses live/env API keys ahead of stored auth profiles by default, so stale test keys in `auth-profiles.json` do not mask real shell credentials
- Skips providers with no usable auth/profile/model
- Runs both declared runtime modes when available:
@@ -542,7 +536,7 @@ request. Plugin dependencies are expected to be present before runtime load.
- Exercises the shared bundled video-generation provider path
- Defaults to the release-safe smoke path: non-FAL providers, one text-to-video request per provider, one-second lobster prompt, and a per-provider operation cap from `OPENCLAW_LIVE_VIDEO_GENERATION_TIMEOUT_MS` (`180000` by default)
- Skips FAL by default because provider-side queue latency can dominate release time; pass `--video-providers fal` or `OPENCLAW_LIVE_VIDEO_GENERATION_PROVIDERS="fal"` to run it explicitly
- Loads provider env vars from your login shell (`~/.profile`) before probing
- Uses already-exported provider env vars before probing
- Uses live/env API keys ahead of stored auth profiles by default, so stale test keys in `auth-profiles.json` do not mask real shell credentials
- Skips providers with no usable auth/profile/model
- Runs only `generate` by default
@@ -573,7 +567,7 @@ request. Plugin dependencies are expected to be present before runtime load.
- Command: `pnpm test:live:media`
- Purpose:
- Runs the shared image, music, and video live suites through one repo-native entrypoint
- Auto-loads missing provider env vars from `~/.profile`
- Uses already-exported provider env vars
- Auto-narrows each suite to providers that currently have usable auth by default
- Reuses `scripts/test-live.mjs`, so heartbeat and quiet-mode behavior stay consistent
- Examples:

View File

@@ -721,10 +721,10 @@ Native dependency policy:
- Not CI-stable by design (real networks, real provider policies, quotas, outages)
- Costs money / uses rate limits
- Prefer running narrowed subsets instead of "everything"
- Live runs source `~/.profile` to pick up missing API keys.
- Live runs use already-exported API keys and staged auth profiles.
- By default, live runs still isolate `HOME` and copy config/auth material into a temp test home so unit fixtures cannot mutate your real `~/.openclaw`.
- Set `OPENCLAW_LIVE_USE_REAL_HOME=1` only when you intentionally need live tests to use your real home directory.
- `pnpm test:live` now defaults to a quieter mode: it keeps `[live] ...` progress output, but suppresses the extra `~/.profile` notice and mutes gateway bootstrap logs/Bonjour chatter. Set `OPENCLAW_LIVE_TEST_QUIET=0` if you want the full startup logs back.
- `pnpm test:live` defaults to a quieter mode: it keeps `[live] ...` progress output and mutes gateway bootstrap logs/Bonjour chatter. Set `OPENCLAW_LIVE_TEST_QUIET=0` if you want the full startup logs back.
- API key rotation (provider-specific): set `*_API_KEYS` with comma/semicolon format or `*_API_KEY_1`, `*_API_KEY_2` (for example `OPENAI_API_KEYS`, `ANTHROPIC_API_KEYS`, `GEMINI_API_KEYS`) or per-live override via `OPENCLAW_LIVE_*_KEY`; tests retry on rate limit responses.
- Progress/heartbeat output:
- Live suites now emit progress lines to stderr so long provider calls are visibly active even when Vitest console capture is quiet.
@@ -753,7 +753,7 @@ plugin validation checklist, see
These Docker runners split into two buckets:
- Live-model runners: `test:docker:live-models` and `test:docker:live-gateway` run only their matching profile-key live file inside the repo Docker image (`src/agents/models.profiles.live.test.ts` and `src/gateway/gateway-models.profiles.live.test.ts`), mounting your local config dir and workspace (and sourcing `~/.profile` if mounted). The matching local entrypoints are `test:live:models-profiles` and `test:live:gateway-profiles`.
- Live-model runners: `test:docker:live-models` and `test:docker:live-gateway` run only their matching profile-key live file inside the repo Docker image (`src/agents/models.profiles.live.test.ts` and `src/gateway/gateway-models.profiles.live.test.ts`), mounting your local config dir, workspace, and optional profile env file. The matching local entrypoints are `test:live:models-profiles` and `test:live:gateway-profiles`.
- Docker live runners default to a smaller smoke cap so a full Docker sweep stays practical:
`test:docker:live-models` defaults to `OPENCLAW_LIVE_MAX_MODELS=12`, and
`test:docker:live-gateway` defaults to `OPENCLAW_LIVE_GATEWAY_SMOKE=1`,
@@ -765,7 +765,7 @@ These Docker runners split into two buckets:
- `Package Acceptance` is the GitHub-native package gate for "does this installable tarball work as a product?" It resolves one candidate package from `source=npm`, `source=ref`, `source=url`, or `source=artifact`, uploads it as `package-under-test`, then runs the reusable Docker E2E lanes against that exact tarball instead of repacking the selected ref. Profiles are ordered by breadth: `smoke`, `package`, `product`, and `full`. See [Testing updates and plugins](/help/testing-updates-plugins) for the package/update/plugin contract, published-upgrade survivor matrix, release defaults, and failure triage.
- Build and release checks run `scripts/check-cli-bootstrap-imports.mjs` after tsdown. The guard walks the static built graph from `dist/entry.js` and `dist/cli/run-main.js` and fails if pre-dispatch startup imports package dependencies such as Commander, prompt UI, undici, or logging before command dispatch; it also keeps the bundled gateway run chunk under budget and rejects static imports of known cold gateway paths. Packaged CLI smoke also covers root help, onboard help, doctor help, status, config schema, and a model-list command.
- Package Acceptance legacy compatibility is capped at `2026.4.25` (`2026.4.25-beta.*` included). Through that cutoff, the harness tolerates only shipped-package metadata gaps: omitted private QA inventory entries, missing `gateway install --wrapper`, missing patch files in the tarball-derived git fixture, missing persisted `update.channel`, legacy plugin install-record locations, missing marketplace install-record persistence, and config metadata migration during `plugins update`. For packages after `2026.4.25`, those paths are strict failures.
- Container smoke runners: `test:docker:openwebui`, `test:docker:onboard`, `test:docker:npm-onboard-channel-agent`, `test:docker:skill-install`, `test:docker:update-channel-switch`, `test:docker:upgrade-survivor`, `test:docker:published-upgrade-survivor`, `test:docker:session-runtime-context`, `test:docker:agents-delete-shared-workspace`, `test:docker:gateway-network`, `test:docker:browser-cdp-snapshot`, `test:docker:mcp-channels`, `test:docker:pi-bundle-mcp-tools`, `test:docker:cron-mcp-cleanup`, `test:docker:plugins`, `test:docker:plugin-update`, `test:docker:plugin-lifecycle-matrix`, and `test:docker:config-reload` boot one or more real containers and verify higher-level integration paths.
- Container smoke runners: `test:docker:openwebui`, `test:docker:onboard`, `test:docker:npm-onboard-channel-agent`, `test:docker:release-user-journey`, `test:docker:release-typed-onboarding`, `test:docker:release-media-memory`, `test:docker:release-upgrade-user-journey`, `test:docker:release-plugin-marketplace`, `test:docker:skill-install`, `test:docker:update-channel-switch`, `test:docker:upgrade-survivor`, `test:docker:published-upgrade-survivor`, `test:docker:session-runtime-context`, `test:docker:agents-delete-shared-workspace`, `test:docker:gateway-network`, `test:docker:browser-cdp-snapshot`, `test:docker:mcp-channels`, `test:docker:pi-bundle-mcp-tools`, `test:docker:cron-mcp-cleanup`, `test:docker:plugins`, `test:docker:plugin-update`, `test:docker:plugin-lifecycle-matrix`, and `test:docker:config-reload` boot one or more real containers and verify higher-level integration paths.
The live-model Docker runners also bind-mount only the needed CLI auth homes (or all supported ones when the run is not narrowed), then copy them into the container home before the run so external-CLI OAuth can refresh tokens without mutating the host auth store:
@@ -778,6 +778,12 @@ The live-model Docker runners also bind-mount only the needed CLI auth homes (or
- Open WebUI live smoke: `pnpm test:docker:openwebui` (script: `scripts/e2e/openwebui-docker.sh`)
- Onboarding wizard (TTY, full scaffolding): `pnpm test:docker:onboard` (script: `scripts/e2e/onboard-docker.sh`)
- Npm tarball onboarding/channel/agent smoke: `pnpm test:docker:npm-onboard-channel-agent` installs the packed OpenClaw tarball globally in Docker, configures OpenAI via env-ref onboarding plus Telegram by default, runs doctor, and runs one mocked OpenAI agent turn. Reuse a prebuilt tarball with `OPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz`, skip the host rebuild with `OPENCLAW_NPM_ONBOARD_HOST_BUILD=0`, or switch channel with `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` or `OPENCLAW_NPM_ONBOARD_CHANNEL=slack`.
- Release user journey smoke: `pnpm test:docker:release-user-journey` installs the packed OpenClaw tarball globally in a clean Docker home, runs onboarding, configures a mocked OpenAI provider, runs an agent turn, installs/uninstalls external plugins, configures ClickClack against a local fixture, verifies outbound/inbound messaging, restarts Gateway, and runs doctor.
- Release typed onboarding smoke: `pnpm test:docker:release-typed-onboarding` installs the packed tarball, drives `openclaw onboard` through a real TTY, configures OpenAI as an env-ref provider, verifies no raw key persistence, and runs a mocked agent turn.
- Release media/memory smoke: `pnpm test:docker:release-media-memory` installs the packed tarball, verifies image understanding from a PNG attachment, OpenAI-compatible image generation output, memory search recall, and recall survival across Gateway restart.
- Release upgrade user journey smoke: `pnpm test:docker:release-upgrade-user-journey` installs `openclaw@latest` by default, configures provider/plugin/ClickClack state on the published package, upgrades to the candidate tarball, then reruns the core agent/plugin/channel journey. Override the baseline with `OPENCLAW_RELEASE_UPGRADE_BASELINE_SPEC=openclaw@<version>`.
- Release plugin marketplace smoke: `pnpm test:docker:release-plugin-marketplace` installs from a local fixture marketplace, updates the installed plugin, uninstalls it, and verifies the plugin CLI disappears with install metadata pruned.
- Skill install smoke: `pnpm test:docker:skill-install` installs the packed OpenClaw tarball globally in Docker, disables uploaded archive installs in config, resolves the current live ClawHub skill slug from search, installs it with `openclaw skills install`, and verifies the installed skill plus `.clawhub` origin/lock metadata.
- Update channel switch smoke: `pnpm test:docker:update-channel-switch` installs the packed OpenClaw tarball globally in Docker, switches from package `stable` to git `dev`, verifies the persisted channel and plugin post-update work, then switches back to package `stable` and checks update status.
- Upgrade survivor smoke: `pnpm test:docker:upgrade-survivor` installs the packed OpenClaw tarball over a dirty old-user fixture with agents, channel config, plugin allowlists, stale plugin dependency state, and existing workspace/session files. It runs package update plus non-interactive doctor without live provider or channel keys, then starts a loopback Gateway and checks config/state preservation plus startup/status budgets.
@@ -831,8 +837,8 @@ after Open WebUI sign-in and model discovery, without waiting on a live model
completion.
The first run can be noticeably slower because Docker may need to pull the
Open WebUI image and Open WebUI may need to finish its own cold-start setup.
This lane expects a usable live model key, and `OPENCLAW_PROFILE_FILE`
(`~/.profile` by default) is the primary way to provide it in Dockerized runs.
This lane expects a usable live model key. Provide it through the process
environment, staged auth profiles, or an explicit `OPENCLAW_PROFILE_FILE`.
Successful runs print a small JSON payload like `{ "ok": true, "model":
"openclaw/default", ... }`.
`test:docker:mcp-channels` is intentionally deterministic and does not need a
@@ -862,7 +868,7 @@ Useful env vars:
- `OPENCLAW_CONFIG_DIR=...` (default: `~/.openclaw`) mounted to `/home/node/.openclaw`
- `OPENCLAW_WORKSPACE_DIR=...` (default: `~/.openclaw/workspace`) mounted to `/home/node/.openclaw/workspace`
- `OPENCLAW_PROFILE_FILE=...` (default: `~/.profile`) mounted to `/home/node/.profile` and sourced before running tests
- `OPENCLAW_PROFILE_FILE=...` mounted and sourced before running tests
- `OPENCLAW_DOCKER_PROFILE_ENV_ONLY=1` to verify only env vars sourced from `OPENCLAW_PROFILE_FILE`, using temporary config/workspace dirs and no external CLI auth mounts
- `OPENCLAW_DOCKER_CLI_TOOLS_DIR=...` (default: `~/.cache/openclaw/docker-cli-tools`) mounted to `/home/node/.npm-global` for cached CLI installs inside Docker
- External CLI auth dirs/files under `$HOME` are mounted read-only under `/host-auth...`, then copied into `/home/node/...` before tests start

View File

@@ -126,6 +126,7 @@ All long-lived state must survive restarts, rebuilds, and reboots.
| ------------------- | ------------------------------------------------------ | ---------------------- | ------------------------------------------------------------- |
| Gateway config | `/home/node/.openclaw/` | Host volume mount | Includes `openclaw.json`, `.env` |
| Model auth profiles | `/home/node/.openclaw/agents/` | Host volume mount | `agents/<agentId>/agent/auth-profiles.json` (OAuth, API keys) |
| Auth profile key | `/home/node/.config/openclaw/` | Host volume mount | Local encryption key for OAuth auth profile token material |
| Skill configs | `/home/node/.openclaw/skills/` | Host volume mount | Skill-level state |
| Agent workspace | `/home/node/.openclaw/workspace/` | Host volume mount | Code and agent artifacts |
| WhatsApp session | `/home/node/.openclaw/` | Host volume mount | Preserves QR login |

View File

@@ -51,6 +51,7 @@ Docker is **optional**. Use it only if you want a containerized gateway or to va
- prompt for provider API keys
- generate a gateway token and write it to `.env`
- create the auth-profile secret key directory
- start the gateway via Docker Compose
During setup, pre-start onboarding and config writes run through
@@ -257,13 +258,13 @@ For gotchas and troubleshooting, see [Bonjour discovery](/gateway/bonjour).
### Storage and persistence
Docker Compose bind-mounts `OPENCLAW_CONFIG_DIR` to `/home/node/.openclaw` and
`OPENCLAW_WORKSPACE_DIR` to `/home/node/.openclaw/workspace`, so those paths
survive container replacement. When either variable is unset, the bundled
`docker-compose.yml` falls back to `${HOME}/.openclaw` (and
`${HOME}/.openclaw/workspace` for the workspace mount), or `/tmp/.openclaw`
when `HOME` itself is also missing. That keeps `docker compose up` from
emitting an empty-source volume spec on bare environments.
Docker Compose bind-mounts `OPENCLAW_CONFIG_DIR` to `/home/node/.openclaw`,
`OPENCLAW_WORKSPACE_DIR` to `/home/node/.openclaw/workspace`, and
`OPENCLAW_AUTH_PROFILE_SECRET_DIR` to `/home/node/.config/openclaw`, so those
paths survive container replacement. When any variable is unset, the bundled
`docker-compose.yml` falls back under `${HOME}`, or `/tmp` when `HOME` itself is
also missing. That keeps `docker compose up` from emitting an empty-source
volume spec on bare environments.
That mounted config directory is where OpenClaw keeps:
@@ -271,6 +272,10 @@ That mounted config directory is where OpenClaw keeps:
- `agents/<agentId>/agent/auth-profiles.json` for stored provider OAuth/API-key auth
- `.env` for env-backed runtime secrets such as `OPENCLAW_GATEWAY_TOKEN`
The auth-profile secret key directory stores the local encryption key used for
OAuth-backed auth profile token material. Keep it with your Docker host state,
but separate from `OPENCLAW_CONFIG_DIR`.
Installed downloadable plugins store their package state under the mounted
OpenClaw home, so plugin install records and package roots survive container
replacement. Gateway startup does not generate bundled-plugin dependency trees.

View File

@@ -150,13 +150,14 @@ requests fail closed.
## Queue steering
Active-run queue steering maps onto Codex app-server `turn/steer`. With the
default `messages.queue.mode: "steer"`, OpenClaw batches queued chat messages
for the configured quiet window and sends them as one `turn/steer` request in
arrival order. Legacy `queue` mode sends separate `turn/steer` requests.
default `messages.queue.mode: "steer"`, OpenClaw batches steer-mode chat
messages for the configured quiet window and sends them as one `turn/steer`
request in arrival order.
Codex review and manual compaction turns can reject same-turn steering. In that
case, OpenClaw uses the follow-up queue when the selected mode allows fallback.
See [Steering queue](/concepts/queue-steering).
case, OpenClaw waits for the active run to finish before starting the prompt.
Use `/queue followup` or `/queue collect` when messages should queue by default
instead of steering. See [Steering queue](/concepts/queue-steering).
## Codex feedback upload

View File

@@ -39,6 +39,13 @@ Preview migration from the source Codex home:
openclaw migrate codex --dry-run
```
Use strict source app verification when you want migration to check source app
accessibility before planning native plugin activation:
```bash
openclaw migrate codex --dry-run --verify-plugin-apps
```
Apply the migration when the plan looks right:
```bash
@@ -87,8 +94,19 @@ The integration has three separate states:
- Accessible: Codex app-server confirms the plugin's app entries are available
for the active account and can be mapped to the migrated plugin identity.
Migration is the durable install/eligibility step. Runtime app inventory is the
accessibility check. Codex harness session setup then computes a restrictive
Migration is the durable install/eligibility step. During planning, OpenClaw
reads source Codex `plugin/read` details and checks that the source Codex
app-server account response is a ChatGPT subscription account. Non-ChatGPT or
missing account responses skip app-backed plugins with
`codex_subscription_required`. By default, migration does not call source
`app/list`; app-backed source plugins that pass the account gate are planned
without source app accessibility verification, and account lookup transport
failures skip with `codex_account_unavailable`. With `--verify-plugin-apps`,
migration takes a fresh source `app/list` snapshot and requires every owned app
to be present, enabled, and accessible before planning native activation. In
that mode, account lookup transport failures fall through to the source
app-inventory gate. Runtime app inventory is the target-session accessibility
check after migration. Codex harness session setup then computes a restrictive
thread app config for the enabled and accessible plugin apps.
Thread app config is computed when OpenClaw establishes a Codex harness session
@@ -100,6 +118,12 @@ V1 is intentionally narrow:
- Only `openai-curated` plugins that were already installed in the source Codex
app-server inventory are migration-eligible.
- App-backed source plugins must pass the migration-time subscription gate.
`--verify-plugin-apps` adds the source app-inventory gate. Subscription-gated
accounts plus, in verification mode, inaccessible, disabled, missing source
apps or source app-inventory refresh failures are reported as skipped manual
items instead of enabled config entries. Unreadable plugin details are skipped
before the source app-inventory gate.
- Migration writes explicit plugin identities with `marketplaceName` and
`pluginName`; it does not write local `marketplacePath` cache paths.
- `codexPlugins.enabled` is the global enablement switch.
@@ -111,7 +135,18 @@ V1 is intentionally narrow:
## App inventory and ownership
OpenClaw reads Codex app inventory through app-server `app/list`, caches it for
one hour, and refreshes stale or missing entries asynchronously.
one hour, and refreshes stale or missing entries asynchronously. The cache is
in memory only; restarting the CLI or gateway drops it, and OpenClaw rebuilds it
from the next `app/list` read.
Migration and runtime use separate cache keys:
- Source migration verification uses the source Codex home and source app-server
start options. This runs only when `--verify-plugin-apps` is set, and it
forces a fresh source `app/list` traversal for that planning run.
- Target runtime setup uses the target agent's Codex app-server identity when it
builds the Codex thread app config. Plugin activation invalidates that target
cache key and then force-refreshes it after `plugin/install`.
A plugin app is exposed only when OpenClaw can map it back to the migrated
plugin through stable ownership:
@@ -161,6 +196,27 @@ plugins, while unsafe schemas and ambiguous ownership still fail closed:
needs authentication. The explicit plugin entry is written disabled until you
reauthorize and enable it.
**`app_inaccessible`, `app_disabled`, or `app_missing`:**
migration did not install the plugin because the source Codex app inventory did
not show all owned apps as present, enabled, and accessible while
`--verify-plugin-apps` was set. Reauthorize or enable the app in Codex, then
rerun migration with `--verify-plugin-apps`.
**`app_inventory_unavailable`:** migration did not install the plugin because
strict source app verification was requested and source Codex app inventory
refresh failed. Fix source Codex app-server access or retry without
`--verify-plugin-apps` if you accept the faster account-gated plan.
**`codex_subscription_required`:** migration did not install the app-backed
plugin because the source Codex app-server account was not logged in with a
ChatGPT subscription account. Log in to the Codex app with subscription auth,
then rerun migration.
**`codex_account_unavailable`:** migration did not install the app-backed plugin
because the source Codex app-server account could not be read. Fix source Codex
app-server auth or rerun with `--verify-plugin-apps` if you want source app
inventory to decide eligibility when account lookup fails.
**`marketplace_missing` or `plugin_missing`:** the target Codex app-server
cannot see the expected `openai-curated` marketplace or plugin. Rerun migration
against the target runtime or inspect Codex app-server plugin status.

View File

@@ -148,6 +148,18 @@ observation-only.
- `cron_changed` - observe gateway-owned cron lifecycle changes (added, updated, removed, started, finished, scheduled)
- **`before_install`** - inspect skill or plugin install scans and optionally block
## Debug runtime hooks
Use `before_model_resolve` when a plugin needs to switch the provider or model
for an agent turn. It runs before model resolution; `llm_output` only runs after
a model attempt produces assistant output.
For proof of the effective session model, inspect runtime registrations, then
use `openclaw sessions` or the Gateway session/status surfaces. When debugging
provider payloads, start the Gateway with `--raw-stream` and
`--raw-stream-path <path>`; those flags write raw model stream events to a jsonl
file.
## Tool call policy
`before_tool_call` receives:
@@ -184,7 +196,7 @@ type BeforeToolCallResult = {
};
```
Rules:
Hook guard behavior for typed lifecycle hooks:
- `block: true` is terminal and skips lower-priority handlers.
- `block: false` is treated as no decision.

View File

@@ -1266,7 +1266,11 @@ hook instead.
## Discovery precedence (duplicate plugin ids)
OpenClaw discovers plugins from several roots (bundled, global install, workspace, explicit config-selected paths). If two discoveries share the same `id`, only the **highest-precedence** manifest is kept; lower-precedence duplicates are dropped instead of loading beside it.
OpenClaw discovers plugins from several roots. For the raw filesystem scan
order, see [Plugin scan
order](/gateway/configuration-reference#plugin-scan-order). If two discoveries
share the same `id`, only the **highest-precedence** manifest is kept;
lower-precedence duplicates are dropped instead of loading beside it.
Precedence, highest to lowest:

View File

@@ -196,10 +196,11 @@ in. For example, ZhiPu `embedding-3` uses `2048` dimensions:
`memory-lancedb` has two separate text limits:
| Setting | Default | Range | Applies to |
| ----------------- | ------- | --------- | --------------------------------------------- |
| `recallMaxChars` | `1000` | 100-10000 | text sent to the embedding API for recall |
| `captureMaxChars` | `500` | 100-10000 | assistant message length eligible for capture |
| Setting | Default | Range | Applies to |
| ----------------- | ------- | --------- | --------------------------------------------------------- |
| `recallMaxChars` | `1000` | 100-10000 | text sent to the embedding API for recall |
| `captureMaxChars` | `500` | 100-10000 | message length eligible for auto-capture |
| `customTriggers` | `[]` | 0-50 | literal phrases that make auto-capture consider a message |
`recallMaxChars` controls auto-recall, the `memory_recall` tool, the
`memory_forget` query path, and `openclaw ltm search`. Auto-recall prefers the
@@ -210,6 +211,10 @@ out of the embedding request.
`captureMaxChars` controls whether a response is short enough to be considered
for automatic capture. It does not cap recall query embeddings.
`customTriggers` lets you add literal auto-capture phrases without writing
regular expressions. The built-in triggers include common English, Czech,
Chinese, Japanese, and Korean memory phrases.
## Commands
When `memory-lancedb` is the active memory plugin, it registers the `ltm` CLI

View File

@@ -56,6 +56,8 @@ type MessagePresentationButton = {
label: string;
value?: string;
url?: string;
webApp?: { url: string };
web_app?: { url: string };
style?: "primary" | "secondary" | "success" | "danger";
};
@@ -80,6 +82,8 @@ Button semantics:
- `value` is an application action value routed back through the channel's
existing interaction path when the channel supports clickable controls.
- `url` is a link button. It can exist without `value`.
- `webApp` and `web_app` describe a channel-native web app button. Telegram
renders this as `web_app` and only supports it in private chats.
- `label` is required and is also used in text fallback.
- `style` is advisory. Renderers should map unsupported styles to a safe
default, not fail the send.
@@ -127,6 +131,19 @@ URL-only link button:
}
```
Telegram Mini App button:
```json
{
"blocks": [
{
"type": "buttons",
"buttons": [{ "label": "Launch", "web_app": { "url": "https://example.com/app" } }]
}
]
}
```
Select menu:
```json

View File

@@ -40,11 +40,12 @@ openclaw gateway restart
openclaw plugins inspect discord --runtime --json
```
Bare package specs try ClawHub first, then npm fallback. To force a source, use
`clawhub:@openclaw/discord` or `npm:@openclaw/discord`. After install, follow
the plugin's setup doc, such as [Discord](/channels/discord), to add credentials
and channel config. See [Manage plugins](/plugins/manage-plugins) for update,
uninstall, and publishing commands.
During the launch cutover, ordinary bare package specs still install from npm.
Use `clawhub:@openclaw/discord` or `npm:@openclaw/discord` when you need an
explicit source. After install, follow the plugin's setup doc, such as
[Discord](/channels/discord), to add credentials and channel config. See
[Manage plugins](/plugins/manage-plugins) for update, uninstall, and publishing
commands.
## Core npm package
@@ -166,7 +167,7 @@ uninstall, and publishing commands.
| [tlon](/plugins/reference/tlon) | Adds the Tlon channel surface for sending and receiving OpenClaw messages. | `@openclaw/tlon`<br />npm; ClawHub | channels: tlon; contracts: tools; skills |
| [twitch](/plugins/reference/twitch) | Adds the Twitch channel surface for sending and receiving OpenClaw messages. | `@openclaw/twitch`<br />npm; ClawHub | channels: twitch |
| [voice-call](/plugins/reference/voice-call) | Adds agent-callable tools. | `@openclaw/voice-call`<br />npm; ClawHub | contracts: tools |
| [whatsapp](/plugins/reference/whatsapp) | Adds the WhatsApp channel surface for sending and receiving OpenClaw messages. | `@openclaw/whatsapp`<br />npm; ClawHub | channels: whatsapp |
| [whatsapp](/plugins/reference/whatsapp) | Adds the WhatsApp channel surface for sending and receiving OpenClaw messages. | `@openclaw/whatsapp`<br />ClawHub: `clawhub:@openclaw/whatsapp`; npm | channels: whatsapp |
| [zalo](/plugins/reference/zalo) | Adds the Zalo channel surface for sending and receiving OpenClaw messages. | `@openclaw/zalo`<br />npm; ClawHub | channels: zalo |
| [zalouser](/plugins/reference/zalouser) | Adds the Zalo Personal channel surface for sending and receiving OpenClaw messages. | `@openclaw/zalouser`<br />npm; ClawHub | channels: zalouser; contracts: tools |

View File

@@ -128,7 +128,7 @@ pnpm plugins:inventory:gen
| [vydra](/plugins/reference/vydra) | Adds Vydra model provider support to OpenClaw. | `@openclaw/vydra-provider`<br />included in OpenClaw | providers: vydra; contracts: imageGenerationProviders, speechProviders, videoGenerationProviders |
| [web-readability](/plugins/reference/web-readability) | Extract readable article content from local HTML web fetch responses. | `@openclaw/web-readability-plugin`<br />included in OpenClaw | contracts: webContentExtractors |
| [webhooks](/plugins/reference/webhooks) | Authenticated inbound webhooks that bind external automation to OpenClaw TaskFlows. | `@openclaw/webhooks`<br />included in OpenClaw | plugin |
| [whatsapp](/plugins/reference/whatsapp) | Adds the WhatsApp channel surface for sending and receiving OpenClaw messages. | `@openclaw/whatsapp`<br />npm; ClawHub | channels: whatsapp |
| [whatsapp](/plugins/reference/whatsapp) | Adds the WhatsApp channel surface for sending and receiving OpenClaw messages. | `@openclaw/whatsapp`<br />ClawHub: `clawhub:@openclaw/whatsapp`; npm | channels: whatsapp |
| [xai](/plugins/reference/xai) | Adds xAI model provider support to OpenClaw. | `@openclaw/xai-plugin`<br />included in OpenClaw | providers: xai; contracts: imageGenerationProviders, mediaUnderstandingProviders, realtimeTranscriptionProviders, speechProviders, tools, videoGenerationProviders, webSearchProviders |
| [xiaomi](/plugins/reference/xiaomi) | Adds Xiaomi model provider support to OpenClaw. | `@openclaw/xiaomi-provider`<br />included in OpenClaw | providers: xiaomi; contracts: speechProviders |
| [zai](/plugins/reference/zai) | Adds Z.AI model provider support to OpenClaw. | `@openclaw/zai-provider`<br />included in OpenClaw | providers: zai; contracts: mediaUnderstandingProviders |

View File

@@ -12,22 +12,12 @@ Adds the WhatsApp channel surface for sending and receiving OpenClaw messages.
## Distribution
- Package: `@openclaw/whatsapp`
- Install route: npm; ClawHub
- Install route: ClawHub: `clawhub:@openclaw/whatsapp`; npm
## Surface
channels: whatsapp
## Windows install note
On Windows, the WhatsApp plugin needs Git on `PATH` during npm install because one of its Baileys/libsignal dependencies is fetched from a git URL. Install Git for Windows, then restart the shell and rerun the install:
```powershell
winget install --id Git.Git -e
```
Portable Git also works if its `bin` directory is on `PATH`.
## Related docs
- [whatsapp](/channels/whatsapp)

View File

@@ -54,6 +54,46 @@ Internal OpenClaw runtime code has the same direction: load config once at the C
Provider and channel execution paths must use the active runtime config snapshot, not a file snapshot returned for config readback or editing. File snapshots preserve source values such as SecretRef markers for UI and writes; provider callbacks need the resolved runtime view. When a helper may be called with either the active source snapshot or the active runtime snapshot, route through `selectApplicableRuntimeConfig()` before reading credentials.
## Reusable runtime utilities
Use the channel-turn `botLoopProtection` facts for bot-authored inbound messages. Core applies the shared in-memory sliding-window guard before session record and dispatch, without tying the policy to one channel. The guard tracks `(scopeId, conversationId, participant pair)` keys, counts both directions of a pair together, applies a cooldown once the window budget is exceeded, and prunes inactive entries opportunistically.
Channel plugins that expose this behavior to operators should prefer the shared `channels.defaults.botLoopProtection` shape for baseline budgets, then layer channel/provider-specific overrides on top. The shared config uses seconds because it is user-facing:
```typescript
type ChannelBotLoopProtectionConfig = {
enabled?: boolean;
maxEventsPerWindow?: number;
windowSeconds?: number;
cooldownSeconds?: number;
};
```
Pass normalized bot-pair facts with the resolved turn. Core resolves defaults, unit conversion, and `enabled` semantics:
```typescript
return {
channel: "example",
routeSessionKey,
storePath,
ctxPayload,
recordInboundSession,
runDispatch,
botLoopProtection: {
scopeId: "account-1",
conversationId: "channel-1",
senderId: "bot-a",
receiverId: "bot-b",
config: channelConfig.botLoopProtection,
defaultsConfig: runtimeConfig.channels?.defaults?.botLoopProtection,
defaultEnabled: allowBotsMode !== "off",
},
};
```
Use `openclaw/plugin-sdk/pair-loop-guard-runtime` directly only for custom
two-party event loops that do not go through the shared channel-turn kernel.
## Runtime namespaces
<AccordionGroup>
@@ -502,6 +542,19 @@ Provider and channel execution paths must use the active runtime config snapshot
<Accordion title="api.runtime.channel">
Channel-specific runtime helpers (available when a channel plugin is loaded).
`api.runtime.channel.media` is the preferred surface for channel media downloads and storage:
```typescript
const saved = await api.runtime.channel.media.saveRemoteMedia({
url,
subdir: "inbound",
maxBytes,
filePathHint: fileName,
});
```
Use `saveRemoteMedia(...)` when a remote URL should become OpenClaw media. Use `saveResponseMedia(...)` when the plugin already fetched a `Response` with plugin-owned auth, redirect, or allowlist handling. Use `readRemoteMediaBuffer(...)` only when the plugin needs raw bytes for inspection, transforms, decryption, or reupload. `fetchRemoteMedia(...)` remains a deprecated compatibility alias for `readRemoteMediaBuffer(...)`.
`api.runtime.channel.mentions` is the shared inbound mention-policy surface for bundled channel plugins that use runtime injection:
```typescript

View File

@@ -302,9 +302,9 @@ focused channel/runtime subpaths, `config-contracts`, `string-coerce-runtime`,
<Accordion title="Capability and testing subpaths">
| Subpath | Key exports |
| --- | --- |
| `plugin-sdk/media-runtime` | Shared media fetch/transform/store helpers, ffprobe-backed video dimension probing, and media payload builders |
| `plugin-sdk/media-runtime` | Shared media fetch/transform/store helpers including `saveRemoteMedia`, `saveResponseMedia`, `readRemoteMediaBuffer`, and deprecated `fetchRemoteMedia`; prefer store helpers before buffer reads when a URL should become OpenClaw media |
| `plugin-sdk/media-mime` | Narrow MIME normalization, file-extension mapping, MIME detection, and media-kind helpers |
| `plugin-sdk/media-store` | Narrow media store helpers such as `saveMediaBuffer` |
| `plugin-sdk/media-store` | Narrow media store helpers such as `saveMediaBuffer` and `saveMediaStream` |
| `plugin-sdk/media-generation-runtime` | Shared media-generation failover helpers, candidate selection, and missing-model messaging |
| `plugin-sdk/media-understanding` | Media understanding provider types plus provider-facing image/audio/structured-extraction helper exports |
| `plugin-sdk/text-chunking` | Text and markdown chunking/render helpers, markdown table conversion, directive-tag stripping, and safe-text utilities |

View File

@@ -109,7 +109,7 @@ The bundled plugin usually means you only need the API key. Use explicit `models
```
<Note>
If the Gateway runs as a daemon (launchd, systemd, Docker), make sure `CEREBRAS_API_KEY` is available to that process — for example in `~/.openclaw/.env` or through `env.shellEnv`. A key sitting only in `~/.profile` will not help a managed service unless the env is imported separately.
If the Gateway runs as a daemon (launchd, systemd, Docker), make sure `CEREBRAS_API_KEY` is available to that process — for example in `~/.openclaw/.env` or through `env.shellEnv`. A key exported only in an interactive shell will not help a managed service unless the env is imported separately.
</Note>
## Related

View File

@@ -101,7 +101,7 @@ openclaw onboard --non-interactive \
If the Gateway runs as a daemon (launchd/systemd), make sure `CLOUDFLARE_AI_GATEWAY_API_KEY` is available to that process.
<Warning>
A key sitting only in `~/.profile` will not help a launchd/systemd daemon unless that environment is imported there as well. Set the key in `~/.openclaw/.env` or via `env.shellEnv` to ensure the gateway process can read it.
A key exported only in an interactive shell will not help a launchd/systemd daemon unless that environment is imported there as well. Set the key in `~/.openclaw/.env` or via `env.shellEnv` to ensure the gateway process can read it.
</Warning>
</Accordion>

309
docs/providers/ds4.md Normal file
View File

@@ -0,0 +1,309 @@
---
summary: "Run OpenClaw through ds4, a local DeepSeek V4 Flash OpenAI-compatible server"
read_when:
- You want to run OpenClaw against antirez/ds4
- You want a local DeepSeek V4 Flash backend with tool calls
- You need the OpenClaw config for ds4-server
title: "ds4"
---
[ds4](https://github.com/antirez/ds4) serves DeepSeek V4 Flash from a local
Metal backend with an OpenAI-compatible `/v1` API. OpenClaw connects to ds4
through the generic `openai-completions` provider family.
ds4 is not a bundled OpenClaw provider plugin. Configure it under
`models.providers.ds4`, then select `ds4/deepseek-v4-flash`.
- Provider id: `ds4`
- Plugin: none
- API: OpenAI-compatible Chat Completions (`openai-completions`)
- Suggested base URL: `http://127.0.0.1:18000/v1`
- Model id: `deepseek-v4-flash`
- Tool calls: supported through OpenAI-style `tools` and `tool_calls`
- Reasoning: DeepSeek-style `thinking` and `reasoning_effort`
## Requirements
- macOS with Metal support.
- A working ds4 checkout with `ds4-server` and the DeepSeek V4 Flash GGUF file.
- Enough memory for the context you choose. Larger `--ctx` values allocate more
KV memory when the server starts.
<Warning>
OpenClaw agent turns include tool schemas and workspace context. A tiny context
such as `--ctx 4096` can pass direct curl tests but fail full agent runs with
`500 prompt exceeds context`. Use at least `--ctx 32768` for agent and tool
smoke tests. Use `--ctx 393216` only when you have enough memory and want ds4
Think Max behavior.
</Warning>
## Quickstart
<Steps>
<Step title="Start ds4-server">
Replace `<DS4_DIR>` with your ds4 checkout path.
```bash
<DS4_DIR>/ds4-server \
--model <DS4_DIR>/ds4flash.gguf \
--host 127.0.0.1 \
--port 18000 \
--ctx 32768 \
--tokens 128
```
</Step>
<Step title="Verify the OpenAI-compatible endpoint">
```bash
curl http://127.0.0.1:18000/v1/models
```
The response should include `deepseek-v4-flash`.
</Step>
<Step title="Add the OpenClaw provider config">
Add the config from [Full config](#full-config), then run a one-shot model
check:
```bash
openclaw infer model run \
--local \
--model ds4/deepseek-v4-flash \
--thinking off \
--prompt "Reply with exactly: openclaw-ds4-ok" \
--json
```
</Step>
</Steps>
## Full config
Use this config when ds4 is already running on `127.0.0.1:18000`.
```json5
{
agents: {
defaults: {
model: { primary: "ds4/deepseek-v4-flash" },
models: {
"ds4/deepseek-v4-flash": {
alias: "DS4 local",
},
},
},
},
models: {
mode: "merge",
providers: {
ds4: {
baseUrl: "http://127.0.0.1:18000/v1",
apiKey: "ds4-local",
api: "openai-completions",
timeoutSeconds: 300,
models: [
{
id: "deepseek-v4-flash",
name: "DeepSeek V4 Flash (ds4)",
reasoning: true,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 32768,
maxTokens: 128,
compat: {
supportsUsageInStreaming: true,
supportsReasoningEffort: true,
maxTokensField: "max_tokens",
supportsStrictMode: false,
thinkingFormat: "deepseek",
supportedReasoningEfforts: ["low", "medium", "high", "xhigh"],
},
},
],
},
},
},
}
```
Keep `contextWindow` aligned with the `ds4-server --ctx` value. Keep `maxTokens`
aligned with `--tokens` unless you intentionally want OpenClaw to request less
output than the server default.
## On-demand startup
OpenClaw can start ds4 only when a `ds4/...` model is selected. Add
`localService` to the same provider entry:
```json5
{
models: {
providers: {
ds4: {
baseUrl: "http://127.0.0.1:18000/v1",
apiKey: "ds4-local",
api: "openai-completions",
timeoutSeconds: 300,
localService: {
command: "<DS4_DIR>/ds4-server",
args: [
"--model",
"<DS4_DIR>/ds4flash.gguf",
"--host",
"127.0.0.1",
"--port",
"18000",
"--ctx",
"32768",
"--tokens",
"128",
],
cwd: "<DS4_DIR>",
healthUrl: "http://127.0.0.1:18000/v1/models",
readyTimeoutMs: 300000,
idleStopMs: 0,
},
models: [
{
id: "deepseek-v4-flash",
name: "DeepSeek V4 Flash (ds4)",
reasoning: true,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 32768,
maxTokens: 128,
compat: {
supportsUsageInStreaming: true,
supportsReasoningEffort: true,
maxTokensField: "max_tokens",
supportsStrictMode: false,
thinkingFormat: "deepseek",
supportedReasoningEfforts: ["low", "medium", "high", "xhigh"],
},
},
],
},
},
},
}
```
`command` must be an absolute executable path. Shell lookup and `~` expansion are
not used. See [Local model services](/gateway/local-model-services) for every
`localService` field.
## Think Max
ds4 applies Think Max only when both conditions are true:
- `ds4-server` starts with `--ctx 393216` or higher.
- The request uses `reasoning_effort: "max"` or the equivalent ds4 effort field.
If you run that large context, update both the server flags and OpenClaw model
metadata:
```json5
{
contextWindow: 393216,
maxTokens: 384000,
compat: {
supportsUsageInStreaming: true,
supportsReasoningEffort: true,
maxTokensField: "max_tokens",
supportsStrictMode: false,
thinkingFormat: "deepseek",
supportedReasoningEfforts: ["low", "medium", "high", "xhigh", "max"],
},
}
```
## Test
Start with a direct HTTP check:
```bash
curl http://127.0.0.1:18000/v1/chat/completions \
-H 'content-type: application/json' \
-d '{"model":"deepseek-v4-flash","messages":[{"role":"user","content":"Reply with exactly: ds4-ok"}],"max_tokens":16,"stream":false,"thinking":{"type":"disabled"}}'
```
Then test OpenClaw model routing:
```bash
openclaw infer model run \
--local \
--model ds4/deepseek-v4-flash \
--thinking off \
--prompt "Reply with exactly: openclaw-ds4-ok" \
--json
```
For a full agent and tool-call smoke, use a context of at least 32768:
```bash
openclaw agent \
--local \
--session-id ds4-tool-smoke \
--model ds4/deepseek-v4-flash \
--thinking off \
--message "Use the shell command pwd once, then reply exactly: tool-ok <output>" \
--json \
--timeout 240
```
Expected result:
- `executionTrace.winnerProvider` is `ds4`
- `executionTrace.winnerModel` is `deepseek-v4-flash`
- `toolSummary.calls` is at least `1`
- `finalAssistantVisibleText` starts with `tool-ok`
## Troubleshooting
<AccordionGroup>
<Accordion title="curl /v1/models cannot connect">
ds4 is not running or not bound to the host and port in `baseUrl`. Start
`ds4-server`, then retry:
```bash
curl http://127.0.0.1:18000/v1/models
```
</Accordion>
<Accordion title="500 prompt exceeds context">
The configured `--ctx` is too small for the OpenClaw turn. Raise
`ds4-server --ctx`, then update `models.providers.ds4.models[].contextWindow`
to match. Full agent turns with tools need substantially more context than a
direct one-message curl request.
</Accordion>
<Accordion title="Think Max does not activate">
ds4 only uses Think Max when `--ctx` is at least `393216` and the request
asks for `reasoning_effort: "max"`. Smaller contexts fall back to high
reasoning.
</Accordion>
<Accordion title="The first request is slow">
ds4 has a cold Metal residency and model warmup phase. Use
`localService.readyTimeoutMs: 300000` when OpenClaw starts the server on
demand.
</Accordion>
</AccordionGroup>
## Related
<CardGroup cols={2}>
<Card title="Local model services" href="/gateway/local-model-services" icon="play">
Start local model servers on demand before model requests.
</Card>
<Card title="Local models" href="/gateway/local-models" icon="server">
Choose and operate local model backends.
</Card>
<Card title="Model providers" href="/concepts/model-providers" icon="layers">
Configure provider refs, auth, and failover.
</Card>
<Card title="DeepSeek" href="/providers/deepseek" icon="brain">
Native DeepSeek provider behavior and thinking controls.
</Card>
</CardGroup>

View File

@@ -118,7 +118,7 @@ OpenClaw accepts any Fireworks model or router id at runtime. Use the exact id s
If the Gateway runs as a managed service (launchd, systemd, Docker), the Fireworks key must be visible to that process — not just to your interactive shell.
<Warning>
A key sitting only in `~/.profile` will not help a launchd or systemd daemon unless that environment is imported there too. Set the key in `~/.openclaw/.env` or via `env.shellEnv` to make it readable from the gateway process.
A key exported only in an interactive shell will not help a launchd or systemd daemon unless that environment is imported there too. Set the key in `~/.openclaw/.env` or via `env.shellEnv` to make it readable from the gateway process.
</Warning>
On macOS, `openclaw gateway install` already wires `~/.openclaw/.env` into the LaunchAgent environment file. Re-run install (or `openclaw doctor --fix`) after rotating the key.

View File

@@ -141,7 +141,7 @@ To make Groq the default audio backend:
If the Gateway runs as a managed service (launchd, systemd, Docker), `GROQ_API_KEY` must be visible to that process — not just to your interactive shell.
<Warning>
A key sitting only in `~/.profile` will not help a launchd or systemd daemon unless that environment is imported there too. Set the key in `~/.openclaw/.env` or via `env.shellEnv` to make it readable from the gateway process.
A key exported only in an interactive shell will not help a launchd or systemd daemon unless that environment is imported there too. Set the key in `~/.openclaw/.env` or via `env.shellEnv` to make it readable from the gateway process.
</Warning>
</Accordion>

View File

@@ -36,6 +36,7 @@ Looking for chat channel docs (WhatsApp/Telegram/Discord/Slack/Mattermost (plugi
- [Cloudflare AI Gateway](/providers/cloudflare-ai-gateway)
- [ComfyUI](/providers/comfy)
- [DeepSeek](/providers/deepseek)
- [ds4 (local DeepSeek V4)](/providers/ds4)
- [ElevenLabs](/providers/elevenlabs)
- [fal](/providers/fal)
- [Fireworks](/providers/fireworks)

View File

@@ -89,10 +89,10 @@ When using the native Perplexity API, searches support the following filters:
`PERPLEXITY_API_KEY` is available to that process.
<Warning>
A key set only in `~/.profile` will not be visible to a launchd/systemd
daemon unless that environment is explicitly imported. Set the key in
`~/.openclaw/.env` or via `env.shellEnv` to ensure the gateway process can
read it.
A key exported only in an interactive shell will not be visible to a
launchd/systemd daemon unless that environment is explicitly imported. Set
the key in `~/.openclaw/.env` or via `env.shellEnv` to ensure the gateway
process can read it.
</Warning>
</Accordion>

View File

@@ -20,7 +20,7 @@ SGLang serves open-weight models via an OpenAI-compatible HTTP API. OpenClaw con
| Streaming usage | Yes (`supportsStreamingUsage: true`) |
| Pricing | Marked external-free (`modelPricing.external: false`) |
OpenClaw also **auto-discovers** available models from SGLang when you opt in with `SGLANG_API_KEY` and you do not define an explicit `models.providers.sglang` entry — see [Model discovery (implicit provider)](#model-discovery-implicit-provider) below.
OpenClaw also **auto-discovers** available models from SGLang when you opt in with `SGLANG_API_KEY`. Use `sglang/*` in `agents.defaults.models` to keep discovery dynamic when you also configure a custom SGLang base URL. See [Model discovery (implicit provider)](#model-discovery-implicit-provider) below.
## Getting started
@@ -71,8 +71,10 @@ define `models.providers.sglang`, OpenClaw will query:
and convert the returned IDs into model entries.
<Note>
If you set `models.providers.sglang` explicitly, auto-discovery is skipped and
you must define models manually.
If you set `models.providers.sglang` explicitly, OpenClaw uses your declared
models by default. Add `"sglang/*": {}` to `agents.defaults.models` when you
want OpenClaw to query that configured provider's `/models` endpoint and include
all advertised SGLang models.
</Note>
## Explicit configuration (manual models)

View File

@@ -106,7 +106,7 @@ Rates are per million tokens in USD as advertised by Tencent. Override pricing u
If the Gateway runs as a managed service (launchd, systemd, Docker), `TOKENHUB_API_KEY` must be visible to that process. Set it in `~/.openclaw/.env` or via `env.shellEnv` so launchd, systemd, or Docker exec environments can read it.
<Warning>
Keys set only in `~/.profile` are not visible to managed gateway processes. Use the env file or config seam for persistent availability.
Keys exported only in an interactive shell are not visible to managed gateway processes. Use the env file or config seam for persistent availability.
</Warning>
</Accordion>

View File

@@ -89,10 +89,10 @@ configuration. OpenClaw resolves the canonical form automatically.
`AI_GATEWAY_API_KEY` is available to that process.
<Warning>
A key set only in `~/.profile` will not be visible to a launchd/systemd
daemon unless that environment is explicitly imported. Set the key in
`~/.openclaw/.env` or via `env.shellEnv` to ensure the gateway process can
read it.
A key exported only in an interactive shell will not be visible to a
launchd/systemd daemon unless that environment is explicitly imported. Set
the key in `~/.openclaw/.env` or via `env.shellEnv` to ensure the gateway
process can read it.
</Warning>
</Accordion>

View File

@@ -8,7 +8,7 @@ title: "vLLM"
vLLM can serve open-source (and some custom) models via an **OpenAI-compatible** HTTP API. OpenClaw connects to vLLM using the `openai-completions` API.
OpenClaw can also **auto-discover** available models from vLLM when you opt in with `VLLM_API_KEY` (any value works if your server does not enforce auth) and you do not define an explicit `models.providers.vllm` entry.
OpenClaw can also **auto-discover** available models from vLLM when you opt in with `VLLM_API_KEY` (any value works if your server does not enforce auth). Use `vllm/*` in `agents.defaults.models` to keep discovery dynamic when you also configure a custom vLLM base URL.
OpenClaw treats `vllm` as a local OpenAI-compatible provider that supports
streamed usage accounting, so status/context token counts can update from
@@ -72,7 +72,7 @@ GET http://127.0.0.1:8000/v1/models
and converts the returned IDs into model entries.
<Note>
If you set `models.providers.vllm` explicitly, auto-discovery is skipped and you must define models manually.
If you set `models.providers.vllm` explicitly, OpenClaw uses your declared models by default. Add `"vllm/*": {}` to `agents.defaults.models` when you want OpenClaw to query that configured provider's `/models` endpoint and include all advertised vLLM models.
</Note>
## Explicit configuration (manual models)
@@ -111,6 +111,21 @@ Use explicit config when:
}
```
To keep this provider dynamic without manually listing every model, add a provider
wildcard to the visible model catalog:
```json5
{
agents: {
defaults: {
models: {
"vllm/*": {},
},
},
},
}
```
## Advanced configuration
<AccordionGroup>
@@ -331,7 +346,7 @@ Use explicit config when:
</Accordion>
<Accordion title="No models discovered">
Auto-discovery requires `VLLM_API_KEY` to be set **and** no explicit `models.providers.vllm` config entry. If you have defined the provider manually, OpenClaw skips discovery and uses only your declared models.
Auto-discovery requires `VLLM_API_KEY` to be set. If you have defined `models.providers.vllm`, OpenClaw uses only your declared models unless `agents.defaults.models` includes `"vllm/*": {}`.
</Accordion>
<Accordion title="Tools render as raw text">

View File

@@ -448,9 +448,8 @@ Legacy aliases still normalize to the canonical bundled ids:
## Live testing
The xAI media paths are covered by unit tests and opt-in live suites. The live
commands load secrets from your login shell, including `~/.profile`, before
probing `XAI_API_KEY`.
The xAI media paths are covered by unit tests and opt-in live suites. Export
`XAI_API_KEY` in the process environment before running live probes.
```bash
pnpm test extensions/xai

View File

@@ -68,7 +68,9 @@ the maintainer-only release runbook.
`pnpm build && pnpm ui:build`, and `pnpm release:check`.
6. Run `OpenClaw NPM Release` with `preflight_only=true`. Before a tag exists,
a full 40-character release-branch SHA is allowed for validation-only
preflight. Save the successful `preflight_run_id`.
preflight. The preflight generates dependency release evidence for the
exact checked-out dependency graph and stores it in the npm preflight
artifact. Save the successful `preflight_run_id`.
7. Kick off all pre-release tests with `Full Release Validation` for the
release branch, tag, or full commit SHA. This is the one manual entrypoint
for the four big release test boxes: Vitest, Docker, QA Lab, and Package.
@@ -85,7 +87,10 @@ the maintainer-only release runbook.
matching GitHub release/prerelease page from the complete matching
`CHANGELOG.md` section. Stable releases published to npm `latest` become the
GitHub latest release; stable maintenance releases kept on npm `beta` are
created with GitHub `latest=false`.
created with GitHub `latest=false`. The workflow also uploads the preflight
dependency evidence to the GitHub release as
`openclaw-<version>-dependency-evidence.zip` for post-release incident
response.
ClawHub publishing may still be running while OpenClaw npm publishes, but the
release publish workflow prints the child run IDs immediately. By default it
does not wait for ClawHub after dispatching it, so OpenClaw npm availability
@@ -189,6 +194,17 @@ the maintainer-only release runbook.
span names, bounded attributes, and content/identifier redaction without
requiring Opik, Langfuse, or another external collector.
- Run `pnpm release:check` before every tagged release
- `OpenClaw NPM Release` preflight generates dependency release evidence before
it packs the npm tarball. The npm advisory vulnerability gate is
release-blocking. The transitive manifest risk, dependency ownership/install
surface, and dependency change reports are release evidence only. The
dependency change report compares the release candidate with the previous
reachable release tag.
- The preflight uploads dependency evidence as
`openclaw-release-dependency-evidence-<tag>` and also embeds it under
`dependency-evidence/` inside the prepared npm preflight artifact. The real
publish path reuses that preflight artifact, then attaches the same evidence
to the GitHub release as `openclaw-<version>-dependency-evidence.zip`.
- Run `OpenClaw Release Publish` for the mutating publish sequence after the
tag exists. Dispatch it from `release/YYYY.M.D` (or `main` when publishing a
main-reachable tag), pass the release tag and successful OpenClaw npm

View File

@@ -15,6 +15,7 @@ title: "Tests"
- `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`: explicit broad changed test run. Use it when a test harness/config/package edit should fall back to Vitest's broader changed-test behavior.
- `pnpm changed:lanes`: shows the architectural lanes triggered by the diff against `origin/main`.
- `pnpm check:changed`: runs the smart changed check gate for the diff against `origin/main`. It runs typecheck, lint, and guard commands for the affected architectural lanes, but does not run Vitest tests. Use `pnpm test:changed` or explicit `pnpm test <target>` for test proof.
- `OPENCLAW_HEAVY_CHECK_LOCK_SCOPE=worktree <local-heavy-check command>`: keeps heavy-check serialization inside the current worktree instead of the Git common dir for commands such as `pnpm check:changed` and targeted `pnpm test ...`. Use it only on high-capacity local hosts when you intentionally run independent checks across linked worktrees.
- `pnpm test`: routes explicit file/directory targets through scoped Vitest lanes. Untargeted runs use fixed shard groups and expand to leaf configs for local parallel execution; the extension group always expands to the per-extension shard configs instead of one giant root-project process.
- Test wrapper runs end with a short `[test] passed|failed|skipped ... in ...` summary. Vitest's own duration line stays the per-shard detail.
- Shared OpenClaw test state: use `src/test-utils/openclaw-test-state.ts` from Vitest when a test needs an isolated `HOME`, `OPENCLAW_STATE_DIR`, `OPENCLAW_CONFIG_PATH`, config fixture, workspace, agent dir, or auth-profile store.
@@ -42,7 +43,7 @@ title: "Tests"
- `pnpm test:docker:browser-cdp-snapshot`: Builds a Chromium-backed source E2E container, starts raw CDP plus an isolated Gateway, runs `browser doctor --deep`, and verifies CDP role snapshots include link URLs, cursor-promoted clickables, iframe refs, and frame metadata.
- `pnpm test:docker:skill-install`: Installs the packed OpenClaw tarball in a bare Docker runner, disables `skills.install.allowUploadedArchives`, resolves a current skill slug from live ClawHub search, installs it through `openclaw skills install`, and verifies `SKILL.md`, `.clawhub/origin.json`, `.clawhub/lock.json`, and `skills info --json`.
- CLI backend live Docker probes can be run as focused lanes, for example `pnpm test:docker:live-cli-backend:codex`, `pnpm test:docker:live-cli-backend:codex:resume`, or `pnpm test:docker:live-cli-backend:codex:mcp`. Claude and Gemini have matching `:resume` and `:mcp` aliases.
- `pnpm test:docker:openwebui`: Starts Dockerized OpenClaw + Open WebUI, signs in through Open WebUI, checks `/api/models`, then runs a real proxied chat through `/api/chat/completions`. Requires a usable live model key (for example OpenAI in `~/.profile`), pulls an external Open WebUI image, and is not expected to be CI-stable like the normal unit/e2e suites.
- `pnpm test:docker:openwebui`: Starts Dockerized OpenClaw + Open WebUI, signs in through Open WebUI, checks `/api/models`, then runs a real proxied chat through `/api/chat/completions`. Requires a usable live model key, pulls an external Open WebUI image, and is not expected to be CI-stable like the normal unit/e2e suites.
- `pnpm test:docker:mcp-channels`: Starts a seeded Gateway container and a second client container that spawns `openclaw mcp serve`, then verifies routed conversation discovery, transcript reads, attachment metadata, live event queue behavior, outbound send routing, and Claude-style channel + permission notifications over the real stdio bridge. The Claude notification assertion reads the raw stdio MCP frames directly so the smoke reflects what the bridge actually emits.
- `pnpm test:docker:upgrade-survivor`: Installs the packed OpenClaw tarball over a dirty old-user fixture, runs package update plus non-interactive doctor without live provider or channel keys, then starts a loopback Gateway and checks that agents, channel config, plugin allowlists, workspace/session files, stale legacy plugin dependency state, startup, and RPC status survive.
- `pnpm test:docker:published-upgrade-survivor`: Installs `openclaw@latest` by default, seeds realistic existing-user files without live provider or channel keys, configures that baseline with a baked `openclaw config set` command recipe, updates that published install to the packed OpenClaw tarball, runs non-interactive doctor, writes `.artifacts/upgrade-survivor/summary.json`, then starts a loopback Gateway and checks that configured intents, workspace/session files, stale plugin config and legacy dependency state, startup, `/healthz`, `/readyz`, and RPC status survive or repair cleanly. Override one baseline with `OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPEC`, expand an exact local matrix with `OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPECS` such as `openclaw@2026.5.2 openclaw@2026.4.23 openclaw@2026.4.15`, or add scenario fixtures with `OPENCLAW_UPGRADE_SURVIVOR_SCENARIOS=reported-issues`; the reported-issues set includes `configured-plugin-installs` to verify configured external OpenClaw plugins install automatically during upgrade and `stale-source-plugin-shadow` to keep source-only plugin shadows from breaking startup. Package Acceptance exposes those as `published_upgrade_survivor_baseline`, `published_upgrade_survivor_baselines`, and `published_upgrade_survivor_scenarios`, and resolves meta baseline tokens such as `last-stable-4` or `all-since-2026.4.23` before handing exact package specs to Docker lanes.
@@ -71,7 +72,7 @@ Script: [`scripts/bench-model.ts`](https://github.com/openclaw/openclaw/blob/mai
Usage:
- `source ~/.profile && pnpm tsx scripts/bench-model.ts --runs 10`
- `pnpm tsx scripts/bench-model.ts --runs 10`
- Optional env: `MINIMAX_API_KEY`, `MINIMAX_BASE_URL`, `MINIMAX_MODEL`, `ANTHROPIC_API_KEY`
- Default prompt: "Reply with a single word: ok. No punctuation or extra text."

View File

@@ -322,10 +322,9 @@ Repo wrapper:
pnpm test:live:media music
```
This live file loads missing provider env vars from `~/.profile`, prefers
live/env API keys ahead of stored auth profiles by default, and runs both
`generate` and declared `edit` coverage when the provider enables edit
mode. Coverage today:
This live file uses already-exported provider env vars ahead of stored auth
profiles by default, and runs both `generate` and declared `edit` coverage when
the provider enables edit mode. Coverage today:
- `google`: `generate` plus `edit`
- `minimax`: `generate` only

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