Compare commits

..

3072 Commits

Author SHA1 Message Date
Vincent Koc
51488bf914 test(gateway): add small model live profile
Add the small-model selector to the gateway live-model profile harness and document the OPENCLAW_LIVE_GATEWAY_MODELS=small recipe.\n\nVerification: node scripts/run-vitest.mjs run --config test/vitest/vitest.live.config.ts src/gateway/gateway-models.profiles.live.test.ts; GitHub Actions CI run 27064309683; CodeQL run 27064309687; OpenGrep PR Diff run 27064309689.
2026-06-06 07:10:26 -07:00
Vincent Koc
4af444ab30 fix(agents): count streamed model deltas incrementally
Count streamed text/thinking/tool-call deltas incrementally in model diagnostics instead of repeatedly estimating full event payloads. Updates diagnostics docs and OTEL wording for the new response byte baseline.\n\nVerification: node scripts/run-vitest.mjs run src/agents/embedded-agent-runner/run/attempt.model-diagnostic-events.test.ts; GitHub Actions CI run 27064304709; CodeQL run 27064304710; OpenGrep PR Diff run 27064304716.
2026-06-06 07:09:49 -07:00
Vincent Koc
5b84ebfc56 test(agents): keep camera media service mock complete 2026-06-06 16:00:30 +02:00
Vincent Koc
4ee50ce18e fix(agents): stream phased text deltas incrementally
Stream same-item phased final-answer deltas incrementally without rereading full partial assistant text on every token. Preserves sanitizer context for split hidden tool-call payloads and keeps full partial reads for item boundaries and text_end finalization.\n\nRefs https://github.com/openclaw/openclaw/issues/86599.
2026-06-06 06:38:28 -07:00
Vincent Koc
31c3e0c3f3 test(live): keep voice-note preflight inside plugins 2026-06-06 06:24:29 -07:00
Vincent Koc
f5eddc2b6d fix(gateway): dedupe delivery mirror history rows 2026-06-06 06:19:35 -07:00
Nimrod Gutman
a547010a95 fix(talk): resolve realtime provider secret refs (#90914)
Merged via squash.

Prepared head SHA: c5a52049be
Reviewed-by: @ngutman
2026-06-06 15:47:13 +03:00
Onur Solmaz
0aea58ab66 fix(memory): fail fast when embeddings provider is unavailable
Fixes #89691.

Memory search now treats explicitly configured non-local embedding providers as required. When that provider is unavailable, search and sync surface an unavailable memory-search result instead of silently returning FTS-only recall.

Unset/default/local/none-style paths keep FTS fallback so existing workflows do not lose keyword recall entirely. The fallback state is now surfaced in diagnostics/status instead of being hidden.

Maintainer merge note: current CI still has unrelated baseline boundary failures in extensions/google/google.live.test.ts and extensions/minimax/minimax.live.test.ts. This PR does not touch those files; the PR-specific memory, docs, lint, type, security, and ClawSweeper checks were reviewed before merge.
2026-06-06 20:39:38 +08:00
Vincent Koc
6b2af6c1ee fix(agents): keep safe tool images without native backend 2026-06-06 05:11:55 -07:00
Vincent Koc
0a08625d79 fix(agents): emit terminal abort lifecycle metadata
Carry terminal abort state into embedded agent lifecycle events before agent_end emits, and include terminal stopReason from the last assistant message when runner metadata is not available yet.

Fixes #66534
2026-06-06 04:54:11 -07:00
Vincent Koc
74331f632b test(live): tolerate ARM provider drift 2026-06-06 03:47:24 -07:00
joshavant
f4a5e5762e feat(android): brand onboarding welcome screen 2026-06-06 05:03:37 -05:00
joshavant
1098063783 fix(android): clarify nearby gateway discovery state 2026-06-06 05:03:37 -05:00
joshavant
b80893f30d chore(android): simplify onboarding entry actions 2026-06-06 05:03:37 -05:00
joshavant
72b387ad48 fix(android): show configured provider readiness 2026-06-06 05:03:37 -05:00
joshavant
44a72cde58 chore(android): remove provider setup footer 2026-06-06 05:03:37 -05:00
joshavant
81312e7aa3 chore(android): remove model catalog section 2026-06-06 05:03:37 -05:00
joshavant
53e50ec127 fix(android): reconnect saved gateway after disconnect 2026-06-06 05:03:37 -05:00
joshavant
485446af8c fix(android): keep sent chat messages in history 2026-06-06 05:03:37 -05:00
joshavant
81f4fe6c11 fix(android): pause gateway pairing retries 2026-06-06 05:03:37 -05:00
joshavant
a2455fcc09 fix(android): keep gateway pairing off main thread 2026-06-06 05:03:37 -05:00
joshavant
e4583b4f57 fix(android): show flavor channel in about 2026-06-06 05:03:37 -05:00
joshavant
9413a5aba5 fix(android): defer runtime startup after first draw 2026-06-06 05:03:36 -05:00
joshavant
b7cafb56fa fix(android): surface voice provider attention 2026-06-06 05:03:36 -05:00
joshavant
efea9ca0f5 chore(android): fix ktlint formatting 2026-06-06 05:03:36 -05:00
Vincent Koc
98f52dcc00 test(live): skip DeepInfra V4 Flash tool sentinel drift 2026-06-06 03:00:12 -07:00
joshavant
32b0b58868 style(ios): use app logo on onboarding intro 2026-06-06 04:41:33 -05:00
joshavant
9942428df0 fix(ios): disable chat composer while offline 2026-06-06 04:41:33 -05:00
joshavant
f40680c826 style(ios): align command section header padding 2026-06-06 04:41:33 -05:00
joshavant
a6582f787c fix(ios): remove extra root tab bottom insets 2026-06-06 04:41:33 -05:00
joshavant
a9a2c34293 fix(ios): stop marking scheduled agents busy 2026-06-06 04:41:33 -05:00
joshavant
2ef0d274fa fix(ios): hide agent sessions from recent sessions 2026-06-06 04:41:33 -05:00
joshavant
dc5c24fbe6 fix(ios): keep chat messages above composer 2026-06-06 04:41:33 -05:00
joshavant
0b87990328 fix(ios): remove command live activity section 2026-06-06 04:41:33 -05:00
joshavant
14f018e794 fix(ios): move approvals to settings 2026-06-06 04:41:33 -05:00
joshavant
81d099f0e9 fix(ios): remove command start work button 2026-06-06 04:41:33 -05:00
joshavant
e8c0d92015 fix(ios): clarify agent chat session 2026-06-06 04:41:32 -05:00
joshavant
67dc71983c fix(ios): show focused session agent 2026-06-06 04:41:32 -05:00
joshavant
be537060ce fix(ios): show recent sessions preview 2026-06-06 04:41:32 -05:00
joshavant
ea7e214bd4 Fix chat history races across agent switches 2026-06-06 04:41:32 -05:00
joshavant
7478e6e485 Fix chat session sync ownership 2026-06-06 04:41:32 -05:00
joshavant
83a6bce835 Fix iOS chat background presentation 2026-06-06 04:41:32 -05:00
joshavant
5c07f7ccf0 Fix iOS selected agent chat routing 2026-06-06 04:41:32 -05:00
joshavant
af50a5959d fix ios onboarding success screen 2026-06-06 04:41:32 -05:00
joshavant
472a30bd3f fix ios skill editor toggle hit target 2026-06-06 04:41:32 -05:00
joshavant
8f6f18b6e7 fix ios operator recovery live activity 2026-06-06 04:41:32 -05:00
joshavant
1746319db5 fix ios operator scope upgrade state 2026-06-06 04:41:32 -05:00
joshavant
19e827c969 fix ios operator admin scope requests 2026-06-06 04:41:32 -05:00
joshavant
f1cf898460 fix ios onboarding tls toggle hit targets 2026-06-06 04:41:32 -05:00
joshavant
7e6134cb12 fix ios onboarding developer toggle hit target 2026-06-06 04:41:32 -05:00
joshavant
2fb5ff3034 fix ios settings bottom scroll inset 2026-06-06 04:41:32 -05:00
joshavant
fbaa5a6f0a fix ios gateway settings control hit targets 2026-06-06 04:41:32 -05:00
joshavant
33cb1c18ac fix ios diagnostics toggle hit targets 2026-06-06 04:41:31 -05:00
joshavant
0ee7cf970c fix ios quick setup suppression toggle 2026-06-06 04:41:31 -05:00
joshavant
762540aa04 fix ios talk controls hit targets 2026-06-06 04:41:31 -05:00
joshavant
73f056a0a4 fix ios chat error banner overlap 2026-06-06 04:41:31 -05:00
joshavant
88f6857c2e fix ios onboarding mode row hit targets 2026-06-06 04:41:31 -05:00
joshavant
c29cc7f82f fix(ios): use safe area inset for settings scroll 2026-06-06 04:41:31 -05:00
Vincent Koc
d4b4a65809 fix(plugins): preserve core embedding providers 2026-06-06 00:30:48 -07:00
Vincent Koc
f94e4f85f0 test(pairing): isolate store state tests 2026-06-05 23:46:11 -07:00
Vincent Koc
c72c82726f fix(installer): print npm debug logs on Windows install failure 2026-06-05 23:16:39 -07:00
Vincent Koc
92242f4f68 fix(test): route extension tests through scoped paths 2026-06-05 22:59:54 -07:00
xydigit-sj
743051d400 fix(uninstall): refuse to remove current working directory during cleanup (#90813)
* fix(uninstall): refuse to remove current working directory during cleanup

* fix(uninstall): guard cleanup ancestors of cwd

---------

Co-authored-by: sallyom <somalley@redhat.com>
2026-06-06 01:51:16 -04:00
Vincent Koc
153a2badb0 fix(release): extend live Docker image pull timeout 2026-06-05 22:34:22 -07:00
Omar Shahine
37aaa5cc2b fix(imessage): frame rpc stdout on LF only (#90845)
Merged via squash.

Prepared head SHA: c62a2dcbf1
Co-authored-by: omarshahine <10343873+omarshahine@users.noreply.github.com>
Co-authored-by: omarshahine <10343873+omarshahine@users.noreply.github.com>
Reviewed-by: @omarshahine
2026-06-05 22:31:50 -07:00
Kevin Lin
ab7c922825 fix(codex): report completion timeout diagnostics
Surface Codex-specific completion-timeout outcomes and structural diagnostics while preserving the existing replay-safe retry behavior.\n\nVerified with focused Vitest coverage, live forced-timeout Showboat proof, and green PR CI.
2026-06-05 22:00:38 -07:00
Vincent Koc
2fc4511eeb fix(release): retry provider-throttled cross-os agent turns 2026-06-05 21:58:46 -07:00
Vincent Koc
9313471fa5 fix(plugins): strengthen registry root memo fingerprint 2026-06-05 21:23:55 -07:00
brokemac79
2f46a27b40 fix(codex): preserve completed replies after client close (#90790)
Merged via squash.

Prepared head SHA: d948b3543c
Co-authored-by: brokemac79 <255583030+brokemac79@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-06-05 21:22:10 -07:00
Vincent Koc
8e9c377971 test(gateway): stabilize channel restart fake timers 2026-06-05 21:16:41 -07:00
Glucksberg
6f909f6454 Fix OpenAI audio auth to use API keys (#90793)
* fix(media): require api key auth for OpenAI audio

* fix(media): narrow OpenAI audio auth API scope

* fix(media): align OpenAI audio auth selection

Signed-off-by: sallyom <somalley@redhat.com>

---------

Signed-off-by: sallyom <somalley@redhat.com>
Co-authored-by: sallyom <somalley@redhat.com>
2026-06-06 00:11:05 -04:00
Vincent Koc
092075534e docs(changelog): complete 2026.6.5 release refs 2026-06-05 20:36:28 -07:00
Vincent Koc
04ecc1aae9 docs(changelog): complete 2026.6.5 notes 2026-06-05 20:23:13 -07:00
Vincent Koc
af4ba6221b docs(changelog): refresh 2026.6.5 notes 2026-06-05 20:04:04 -07:00
clawsweeper[bot]
9cbf18293b fix #90668: [Bug]: macOS node mode can silently self-reconnect in a healthy direct gateway session (#90815)
Summary:
- Adds a macOS node-mode TLS session cache keyed by gateway URL and TLS pin parameters, with Swift tests for reuse and rebuild behavior.
- PR surface: Other +78. Total +78 across 2 files.
- Reproducibility: yes. The source path is clear: current main supplies a fresh TLS session identity into `Gat ... inked macOS WSS proof demonstrates repeated connected callbacks before the cache and one callback after it.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(macos): make TLS session cache lint-safe
- PR branch already contained follow-up commit before automerge: fix #90668: [Bug]: macOS node mode can silently self-reconnect in a h…

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

Prepared head SHA: 1496eac8c1
Review: https://github.com/openclaw/openclaw/pull/90815#issuecomment-4637057530

Co-authored-by: 张贵萍0668001030 <zhang.guiping@xydigit.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-06-06 02:44:59 +00:00
clawsweeper[bot]
50aaf1f9b6 fix(memory): resolve adapter default model in plain status identity check (#90816)
Summary:
- This PR updates memory-core index identity resolution to treat an empty configured model as the embedding adapter default and adds a regression test for plain memory status.
- PR surface: Source +5, Tests +33. Total +38 across 2 files.
- Reproducibility: yes. from source and inherited proof: current main compares identity against an unresolved empty model in the plain status path, and the source PR shows the before/after CLI behavior on the same index.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(memory): resolve adapter default model in plain status identity c…

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

Prepared head SHA: 9741437564
Review: https://github.com/openclaw/openclaw/pull/90816#issuecomment-4637058847

Co-authored-by: 宇宙熊Yzx <53250620+849261680@users.noreply.github.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-06-06 02:34:29 +00:00
Chunyue Wang
aa8070a76f fix(llm): defer Anthropic stream start event until after message_start (#90697)
Summary:
- The branch moves Anthropic `start` emission into `message_start` handling for the provider and transport stream paths and adds focused ordering/error tests.
- PR surface: Source +5, Tests +149. Total +154 across 4 files.
- Reproducibility: Do we have a high-confidence way to reproduce the issue? Yes from source: current main emit ... ecovery intentionally refuses to retry after any non-error output; no live expired-cache run was performed.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(agents): defer Anthropic transport stream start event until after…

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

Prepared head SHA: 399a243c64
Review: https://github.com/openclaw/openclaw/pull/90697#issuecomment-4632866448

Co-authored-by: openperf <16864032@qq.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-06-06 02:17:54 +00:00
Yzx
b1e4b6b65e fix(agents): coerce non-text/image MCP tool-result blocks to text (fixes #90710) (#90728)
Summary:
- The PR converts wider MCP CallToolResult content blocks into text/image AgentToolResult blocks at the bundle-MCP materialization boundary and adds regression tests.
- PR surface: Source +36, Tests +66. Total +102 across 2 files.
- Reproducibility: yes. Source inspection shows current main lets MCP resource/audio blocks cross into a text/ ...  a spawned stdio MCP server; I did not run a live hosted Anthropic API round trip in this read-only review.

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

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

Prepared head SHA: f70dccf33e
Review: https://github.com/openclaw/openclaw/pull/90728#issuecomment-4634126025

Co-authored-by: 宇宙熊Yzx <53250620+849261680@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-06-06 02:16:10 +00:00
Sahibzada
9e29375cec fix(voice-call): track Twilio streams after connect (#90607)
Summary:
- The PR moves Twilio inbound active-stream tracking from TwiML generation to `registerCallStream` and updates provider tests for connected-stream and no-stream cases.
- PR surface: Source -3, Tests +23. Total +20 across 2 files.
- Reproducibility: yes. from source inspection and supplied before/after output: on current main, one inbound  ... nd inbound parse queues even when no media stream registered. I did not run tests in this read-only review.

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

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

Prepared head SHA: 22575a9f27
Review: https://github.com/openclaw/openclaw/pull/90607#issuecomment-4630012870

Co-authored-by: Sahibzada Allahyar <sahibzada@fastino.ai>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-06-06 02:15:00 +00:00
keshavbotagent
3a2f54e6a8 fix(telegram): suppress post-final tool error noise
Suppress non-actionable text-only tool/progress noise after Telegram final delivery while preserving terminal final warnings, media payloads, and exec approval prompts.

Use the core nonTerminalToolErrorWarning marker for recovered final tool warnings, and cover suppression plus preservation cases with regression tests.
2026-06-05 18:24:09 -07:00
Harjoth Khara
e5d1fadea7 test(codex): cover thread abandonment after completion-idle timeout (#90027)
Regression coverage for #89974. Confirms that after a
turn_completion_idle_timeout, OpenClaw clears the timed-out Codex
app-server thread binding and the next turn starts a fresh thread instead
of resuming the thread that may hold Codex's generic <turn_aborted> /
user-interrupted marker. No runtime behavior changes.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 17:41:52 -07:00
Josh Lehman
bbfe8ccaf6 fix: refresh prompt fence after compaction writes
Fix embedded attempts falsely reporting session takeover after OpenClaw-owned auto-compaction writes a compaction entry while the prompt fence is released.

The compaction append path now publishes an owned session-file fence only when the guarded SessionManager append produced the expected compaction entry. External or interleaved session-file edits remain takeover errors.

Closes #90729
2026-06-05 17:05:35 -07:00
Yzx
a4f7e4cbb9 fix(google): preserve Vertex ADC catalog auth (#90609)
* fix: preserve Google Vertex ADC catalog auth

* fix: register Google Vertex ADC config marker

* fix: fill Vertex ADC static catalog auth
2026-06-05 18:16:34 -04:00
Yzx
6da3b1f6a3 fix(agents): re-probe single-provider primary during cooldown (#90717)
Fixes #90702.

Allow a single-provider primary to periodically probe through the existing cooldown throttle even when no fallback chain is configured. This lets WHAM/subscription-limit cooldown state recover without waiting for a far-future provider reset timestamp.

Verified:
- node scripts/run-vitest.mjs src/agents/model-fallback.probe.test.ts
- git diff --check
- cherry-pick onto current origin/main and rerun focused regression
2026-06-05 14:20:57 -07:00
dependabot[bot]
2ab4eaa2b1 build(deps): bump docker/login-action from 3.6.0 to 4.1.0 (#74980)
Bumps [docker/login-action](https://github.com/docker/login-action) from 3.6.0 to 4.1.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v3.6.0...4907a6ddec9925e35a0a9e82d7399ccc52663121)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: 4.1.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-05 14:12:53 -07:00
dependabot[bot]
c965141d67 chore(deps): bump the android-deps group across 1 directory with 9 updates (#86481)
Bumps the android-deps group with 9 updates in the /apps/android directory:

| Package | From | To |
| --- | --- | --- |
| [gradle-wrapper](https://github.com/gradle/gradle) | `9.4.1` | `9.5.1` |
| androidx.compose:compose-bom | `2026.04.01` | `2026.05.01` |
| [dnsjava:dnsjava](https://github.com/dnsjava/dnsjava) | `3.6.4` | `3.6.5` |
| [org.junit.vintage:junit-vintage-engine](https://github.com/junit-team/junit-framework) | `6.0.3` | `6.1.0` |
| [org.jetbrains.kotlinx:kotlinx-coroutines-android](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.2` | `1.11.0` |
| [org.jetbrains.kotlinx:kotlinx-coroutines-test](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.2` | `1.11.0` |
| [com.google.android.material:material](https://github.com/material-components/material-components-android) | `1.13.0` | `1.14.0` |
| com.android.application | `9.2.0` | `9.2.1` |
| com.android.test | `9.2.0` | `9.2.1` |



Updates `gradle-wrapper` from 9.4.1 to 9.5.1
- [Release notes](https://github.com/gradle/gradle/releases)
- [Commits](https://github.com/gradle/gradle/compare/v9.4.1...v9.5.1)

Updates `androidx.compose:compose-bom` from 2026.04.01 to 2026.05.01

Updates `dnsjava:dnsjava` from 3.6.4 to 3.6.5
- [Release notes](https://github.com/dnsjava/dnsjava/releases)
- [Changelog](https://github.com/dnsjava/dnsjava/blob/master/Changelog)
- [Commits](https://github.com/dnsjava/dnsjava/commits)

Updates `org.junit.vintage:junit-vintage-engine` from 6.0.3 to 6.1.0
- [Release notes](https://github.com/junit-team/junit-framework/releases)
- [Commits](https://github.com/junit-team/junit-framework/compare/r6.0.3...r6.1.0)

Updates `org.jetbrains.kotlinx:kotlinx-coroutines-android` from 1.10.2 to 1.11.0
- [Release notes](https://github.com/Kotlin/kotlinx.coroutines/releases)
- [Changelog](https://github.com/Kotlin/kotlinx.coroutines/blob/master/CHANGES.md)
- [Commits](https://github.com/Kotlin/kotlinx.coroutines/compare/1.10.2...1.11.0)

Updates `org.jetbrains.kotlinx:kotlinx-coroutines-test` from 1.10.2 to 1.11.0
- [Release notes](https://github.com/Kotlin/kotlinx.coroutines/releases)
- [Changelog](https://github.com/Kotlin/kotlinx.coroutines/blob/master/CHANGES.md)
- [Commits](https://github.com/Kotlin/kotlinx.coroutines/compare/1.10.2...1.11.0)

Updates `org.jetbrains.kotlinx:kotlinx-coroutines-test` from 1.10.2 to 1.11.0
- [Release notes](https://github.com/Kotlin/kotlinx.coroutines/releases)
- [Changelog](https://github.com/Kotlin/kotlinx.coroutines/blob/master/CHANGES.md)
- [Commits](https://github.com/Kotlin/kotlinx.coroutines/compare/1.10.2...1.11.0)

Updates `com.google.android.material:material` from 1.13.0 to 1.14.0
- [Release notes](https://github.com/material-components/material-components-android/releases)
- [Commits](https://github.com/material-components/material-components-android/compare/1.13.0...1.14.0)

Updates `com.android.application` from 9.2.0 to 9.2.1

Updates `com.android.test` from 9.2.0 to 9.2.1

Updates `com.android.test` from 9.2.0 to 9.2.1

---
updated-dependencies:
- dependency-name: androidx.compose:compose-bom
  dependency-version: 2026.05.01
  dependency-type: direct:production
  dependency-group: android-deps
- dependency-name: com.android.application
  dependency-version: 9.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: android-deps
- dependency-name: com.android.test
  dependency-version: 9.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: android-deps
- dependency-name: com.android.test
  dependency-version: 9.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: android-deps
- dependency-name: com.google.android.material:material
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: android-deps
- dependency-name: dnsjava:dnsjava
  dependency-version: 3.6.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: android-deps
- dependency-name: gradle-wrapper
  dependency-version: 9.5.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: android-deps
- dependency-name: org.jetbrains.kotlinx:kotlinx-coroutines-android
  dependency-version: 1.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: android-deps
- dependency-name: org.jetbrains.kotlinx:kotlinx-coroutines-test
  dependency-version: 1.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: android-deps
- dependency-name: org.jetbrains.kotlinx:kotlinx-coroutines-test
  dependency-version: 1.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: android-deps
- dependency-name: org.junit.vintage:junit-vintage-engine
  dependency-version: 6.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: android-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-05 14:07:08 -07:00
dependabot[bot]
c6972a0664 chore(deps): bump github.com/apple/swift-testing (#81757)
Bumps the swift-deps group with 1 update in the /apps/swabble directory: [github.com/apple/swift-testing](https://github.com/apple/swift-testing).


Updates `github.com/apple/swift-testing` from 6.3.1 to 6.3.2
- [Release notes](https://github.com/apple/swift-testing/releases)
- [Commits](https://github.com/apple/swift-testing/compare/6.3.1...6.3.2)

---
updated-dependencies:
- dependency-name: github.com/apple/swift-testing
  dependency-version: 6.3.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swift-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-05 14:05:15 -07:00
dependabot[bot]
662d366f01 chore(deps): bump the actions group across 1 directory with 4 updates (#90601)
Bumps the actions group with 4 updates in the / directory: [github/codeql-action](https://github.com/github/codeql-action), [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action), [docker/build-push-action](https://github.com/docker/build-push-action) and [openai/codex-action](https://github.com/openai/codex-action).


Updates `github/codeql-action` from 4 to 4.36.1
- [Release notes](https://github.com/github/codeql-action/releases)
- [Commits](https://github.com/github/codeql-action/compare/v4...v4.36.1)

Updates `docker/setup-buildx-action` from 4.0.0 to 4.1.0
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](4d04d5d948...d7f5e7f509)

Updates `docker/build-push-action` from 7.1.0 to 7.2.0
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](bcafcacb16...f9f3042f7e)

Updates `openai/codex-action` from 1.7 to 1.8
- [Changelog](https://github.com/openai/codex-action/blob/main/CHANGELOG.md)
- [Commits](5c3f4ccdb2...e0fdf01220)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.36.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: docker/setup-buildx-action
  dependency-version: 4.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: docker/build-push-action
  dependency-version: 7.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: openai/codex-action
  dependency-version: '1.8'
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-05 13:37:40 -07:00
dependabot[bot]
aee45f5f73 chore(deps): bump the swift-deps group across 1 directory with 3 updates (#86483)
Bumps the swift-deps group with 3 updates in the /apps/macos directory: [github.com/apple/swift-log](https://github.com/apple/swift-log), [github.com/sparkle-project/sparkle](https://github.com/sparkle-project/Sparkle) and [github.com/steipete/peekaboo](https://github.com/steipete/Peekaboo).


Updates `github.com/apple/swift-log` from 1.12.0 to 1.13.1
- [Release notes](https://github.com/apple/swift-log/releases)
- [Commits](https://github.com/apple/swift-log/compare/1.12.0...1.13.1)

Updates `github.com/sparkle-project/sparkle` from 2.9.1 to 2.9.2
- [Release notes](https://github.com/sparkle-project/Sparkle/releases)
- [Commits](https://github.com/sparkle-project/Sparkle/compare/2.9.1...2.9.2)

Updates `github.com/steipete/peekaboo` from 3.2.1 to 3.3.0
- [Release notes](https://github.com/steipete/Peekaboo/releases)
- [Commits](https://github.com/steipete/Peekaboo/compare/v3.2.1...v3.3.0)

---
updated-dependencies:
- dependency-name: github.com/apple/swift-log
  dependency-version: 1.12.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swift-deps
- dependency-name: github.com/sparkle-project/sparkle
  dependency-version: 2.9.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swift-deps
- dependency-name: github.com/steipete/peekaboo
  dependency-version: 3.2.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swift-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-05 13:10:45 -07:00
Dallin Romney
ac9a219692 fix(tui): stabilize optimistic user messages across history reloads, runId reassignment, and abort (#86205)
* fix(tui): preserve optimistic user messages

* refactor(tui): drop unused pending-user chat-log helpers

* fix(tui): reconcile optimistic user row across runId reassignment and abort

* refactor(tui): reuse asDateTimestampMs for history timestamp coercion

* test(tui): fix event-handler chatLog render mock arity
2026-06-05 12:09:24 -07:00
Matt H
db7d70ae4d feat(parallel): add Parallel as a bundled web_search provider (#85158)
- New extensions/parallel package modeled on extensions/exa
- Wires Parallel's POST /v1/search through the generic web_search contract,
  exposing Parallel's recommended {objective, search_queries} shape (plus
  optional count, session_id, client_model) so the model can supply both the
  natural-language goal and 2-3 short keyword queries as Parallel docs advise
- client_model lets the model report its own slug so Parallel can tailor
  optimizations for the consuming model's capabilities; partitions the cache
  by client_model so different models do not silently share ranked excerpts
- Honors top-level tools.web.search.{maxResults,timeoutSeconds,cacheTtlMinutes}
  via the shared SDK helpers (mergeScopedSearchConfig, withTrustedWebSearchEndpoint,
  buildSearchCacheKey, read/writeCachedSearchPayload)
- Auto-detect order 75; auth via PARALLEL_API_KEY or
  plugins.entries.parallel.config.webSearch.apiKey
- Optional baseUrl override for proxies (e.g. Cloudflare AI Gateway)
- Threads caller-supplied session_id through follow-up calls; strips
  auto-generated session_id from the shared cache to avoid cross-task leaks
- Always sends advanced_settings.max_results so result volume matches the
  OpenClaw web_search default (5) instead of Parallel's default (10)
- Identifies the plugin via User-Agent header built from package version
- Runtime accepts the generic `query` arg as a fallback so the operator
  CLI (openclaw capability web.search) keeps working when Parallel is the
  active provider: it is promoted into the lone `search_queries` entry.
  `objective` stays optional and is never synthesized from a keyword
  query (Parallel documents it as natural-language intent). Agent callers
  using the native objective+search_queries shape take precedence; the
  schema still advertises only the native keys
- Updates the agent tool-display extractor (src/agents/tool-display-common.ts)
  to recognize Parallel's objective+search_queries shape so calls render with
  query context in CLI progress and Codex activity metadata
- Adds /tools/parallel-search docs page, web.md provider listing, docs nav,
  labeler entry, per-plugin registration contract test, and minimal core
  touch-points (legacy migrate, registration cases, providers contract list,
  runtime bundled list, vitest extension paths)
2026-06-05 12:01:58 -07:00
Jason (Json)
36d9241cf7 docs: prefer web_fetch in weather skill (#90250)
* docs: prefer web_fetch in weather skill

* docs: use compact wttr json in weather skill
2026-06-05 14:35:55 -04:00
zenglingbiao
d896a4c7a3 fix(context-engine): forward isHeartbeat to afterTurn (fixes #89302) (#90632)
Merged via squash.

Prepared head SHA: 2f6da84c4b
Co-authored-by: zenglingbiao <290951975+zenglingbiao@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-06-05 11:27:37 -07:00
Gio Della-Libera
b3eba2ff38 fix(gateway): dedupe probe warnings by gateway identity (#85791)
Merged via squash.

Prepared head SHA: 13e3c00f56
Co-authored-by: giodl73-repo <235387111+giodl73-repo@users.noreply.github.com>
Co-authored-by: giodl_microsoft <115749436+giodl_microsoft@users.noreply.github.com>
Reviewed-by: @giodl_microsoft
2026-06-05 10:23:12 -07:00
Ted Li
21aa297434 fix(cron): auto-migrate legacy cron store (#90208)
Merged via squash.

Prepared head SHA: f5aa1b6759
Co-authored-by: MonkeyLeeT <6754057+MonkeyLeeT@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-06-05 10:22:02 -07:00
Shakker
4752e9a67d test: bracket provider worker env 2026-06-05 17:09:55 +01:00
Shakker
ec91dce0b8 test: scope internal transcript state env 2026-06-05 17:08:30 +01:00
Shakker
fbbb88925a test: scope openrouter capability env 2026-06-05 17:06:09 +01:00
Shakker
9235c25d33 test: clean model cache state env 2026-06-05 17:04:19 +01:00
Shakker
6ce71737e5 test: manage workspace state fixture 2026-06-05 17:02:10 +01:00
Shakker
935c80d6e1 test: use managed skill workshop state 2026-06-05 17:01:20 +01:00
Vincent Koc
286772e930 test: shorten vitest no-output heartbeat 2026-06-05 09:00:02 -07:00
Shakker
b19904931e test: contain sessions tool state env 2026-06-05 16:58:37 +01:00
Shakker
415272d17e test: isolate pdf media state env 2026-06-05 16:56:05 +01:00
Shakker
002aa1061b test: narrow media tool state env 2026-06-05 16:54:58 +01:00
Shakker
8a83c13389 test: bound sandbox media state env 2026-06-05 16:53:44 +01:00
Shakker
a16b6c02ce test: pair cron task state env 2026-06-05 16:52:47 +01:00
Peter Steinberger
2514980118 feat(matrix): handle voice preflight and threads (#90415)
* feat(matrix): handle voice preflight and threads

Co-authored-by: Frank Dierolf <frank_dierolf@web.de>
Co-authored-by: marc.wilson <marcwilson@gazasrv15i5.globaladvisors.biz>

* test(matrix): satisfy ci guards

* fix(matrix): preserve thread relations on edits

* chore: annotate deprecated compatibility aliases

* fix(matrix): include poll thread roots in reads

* test(matrix): enable audio preflight qa config

* test(matrix): make voice preflight QA mention deterministic

---------

Co-authored-by: Frank Dierolf <frank_dierolf@web.de>
Co-authored-by: marc.wilson <marcwilson@gazasrv15i5.globaladvisors.biz>
2026-06-05 08:49:35 -07:00
Shakker
c85b0ee3db test: scope subagent sqlite state env 2026-06-05 16:48:32 +01:00
Shakker
1e683ff245 test: scope auth path state env 2026-06-05 16:46:55 +01:00
Shakker
fc0b141445 test: contain launch restart home env 2026-06-05 16:45:08 +01:00
Shakker
a0840cad8f test: scope restart sentinel state env 2026-06-05 16:43:32 +01:00
Shakker
03b35b53e3 test: delegate media redirect state env 2026-06-05 16:43:00 +01:00
Peter Steinberger
797bcd5bdb fix: propagate ClickClack toolsAllow through replies
Propagate ClickClack account-level runtime tool allowlists through inbound reply dispatch so restricted ClickClack accounts keep their tool policy when model/agent replies are generated.

This threads `toolsAllow` through shared dispatch, provider wrappers, embedded agent execution, and ACP hook events. ACP-bound sessions now fail closed for restrictive runtime allowlists because ACPX cannot enforce per-turn tool allowlists on reused persistent sessions.

Verification:
- Live ClickClack E2E on Crabbox AWS `run_6a0472ed7e71`, provider `aws`, id `cbx_dace25addcaa`.
- `node scripts/run-vitest.mjs run src/auto-reply/reply/dispatch-acp.test.ts src/plugin-sdk/acp-runtime.test.ts src/auto-reply/reply/dispatch-from-config.reply-dispatch.test.ts src/auto-reply/dispatch.test.ts src/auto-reply/reply/agent-runner-execution.test.ts src/auto-reply/reply/provider-dispatcher.test.ts extensions/clickclack/src/inbound.test.ts --reporter=verbose`
- Crabbox changed gate `run_d32af37fb265`, provider `aws`, id `cbx_8236876017c9`: `corepack pnpm check:changed`
- Autoreview clean: `.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main`

Supersedes #89500.

Co-authored-by: Michael Appel <mappel@nvidia.com>
2026-06-05 08:40:35 -07:00
Shakker
5a0f9cb03c test: scope logging config path env 2026-06-05 16:39:50 +01:00
Shakker
e4de53a460 test: snapshot flows state env 2026-06-05 16:38:23 +01:00
Shakker
d1fe0184b9 test: preserve secrets state env snapshot 2026-06-05 16:37:09 +01:00
Vincent Koc
da88940c6c fix(android): skip gradle resource tasks on linux arm 2026-06-05 08:14:42 -07:00
Ayaan Zaidi
520992a1de test(gateway): avoid future session fixture timestamps 2026-06-05 18:19:19 +05:30
Ayaan Zaidi
00d21a4720 test(telegram): align transcript append mock 2026-06-05 18:19:19 +05:30
Ayaan Zaidi
3d68f7e5f7 test(gateway): stabilize live session metadata fixture 2026-06-05 18:19:19 +05:30
Ayaan Zaidi
ceee4c6b01 fix(sessions): mark transcript rewrites in registry 2026-06-05 18:19:19 +05:30
Fermin Quant
e22e857ddd fix(sessions): keep transcript append result discriminant 2026-06-05 18:19:19 +05:30
Fermin Quant
57bed6ae0c fix(sessions): cover terminal transcript markers 2026-06-05 18:19:19 +05:30
Fermin Quant
0c9ac48d2c fix(sessions): reconcile stale terminal main transcripts 2026-06-05 18:19:19 +05:30
Ayaan Zaidi
afa04d6454 fix(gateway): share codex model visibility 2026-06-05 17:14:34 +05:30
Ayaan Zaidi
85343ea546 fix(gateway): fail closed for unknown model auth 2026-06-05 17:14:34 +05:30
Ayaan Zaidi
d6dbcb2f4b fix(android): surface expiring providers in palette 2026-06-05 17:14:34 +05:30
Ayaan Zaidi
61d121f1ca fix(android): show unavailable model rows as attention 2026-06-05 17:14:34 +05:30
Ayaan Zaidi
21512a696f fix(gateway): preserve codex alias model availability 2026-06-05 17:14:34 +05:30
Ayaan Zaidi
ea1ef72394 fix(gateway): keep unresolved profile refs unknown 2026-06-05 17:14:34 +05:30
Ayaan Zaidi
7c885528ba fix(gateway): recognize env profile refs in model availability 2026-06-05 17:14:34 +05:30
Ayaan Zaidi
cec5e36a39 fix(gateway): avoid resolving auth during models list 2026-06-05 17:14:34 +05:30
Ayaan Zaidi
e404ce98f5 fix(gateway): require resolved auth for model availability 2026-06-05 17:14:34 +05:30
Ayaan Zaidi
30160933f0 refactor(android): distill provider availability cleanup 2026-06-05 17:14:34 +05:30
Tosko4
8b66003a0b fix(android): clarify provider attention state 2026-06-05 17:14:34 +05:30
Chunyue Wang
12a569109b fix(agents): detect unsigned thinking-only stall when reasoning payload inflates payloadCount (#89874)
Summary:
- Merged fix(agents): detect unsigned thinking-only stall when reasoning payload inflates payloadCount after ClawSweeper review.

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

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

Prepared head SHA: c613c3884f
Review: https://github.com/openclaw/openclaw/pull/89874#issuecomment-4630564594

Co-authored-by: openperf <16864032@qq.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-06-05 10:29:18 +00:00
Chunyue Wang
1a3ce7c2a8 fix(qqbot): sanitize outbound text to strip reasoning/thinking content (#90132)
Summary:
- Adds QQBot outbound `sanitizeText` wired to `sanitizeAssistantVisibleText` plus a regression test for stripping `<thinking>` and `<think>` blocks.
- PR surface: Source +2, Tests +19. Total +21 across 2 files.
- Reproducibility: yes. source-reproducible: current main QQBot outbound lacks `sanitizeText`, and shared deli ... nnel text sanitization when that hook exists. I did not run a live Tencent QQBot plus MiniMax reproduction.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(qqbot): add curly braces for eslint(curly) compliance

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

Prepared head SHA: 17cf140183
Review: https://github.com/openclaw/openclaw/pull/90132#issuecomment-4618527026

Co-authored-by: openperf <16864032@qq.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-06-05 06:57:16 +00:00
ooiuuii
560b77a4af test: add Codex session route migration coverage (#90319)
* Add Codex session route migration coverage

* Use synthetic Telegram session id in Codex test
2026-06-04 23:28:08 -07:00
ooiuuii
cfd5f1ad13 Add Codex multi-agent migration coverage (#90317) 2026-06-04 23:27:34 -07:00
Kevin Lin
d7759c6a35 feat(googlechat): add native approval cards
## Summary

- Adds native Google Chat approval cards for exec and plugin approval requests that originate from Google Chat spaces or threads.
- Uses opaque server-side action tokens for Google Chat `cardsV2` button callbacks and updates delivered approval messages after resolution or expiry.
- Preserves the shipped Google Chat typing-message default while keeping approval cards on the channel-local native path.
- Suppresses duplicate manual `/approve ...` follow-up delivery inside `extensions/googlechat/` when the native card path owns the approval prompt.
- Documents Google Chat native approval behavior and the `typingIndicator: "message"` default.

## Linked context

Which issue does this close?

Closes #

Which issues, PRs, or discussions are related?

Related Spec 24.8: Google Chat native approval cards.

Was this requested by a maintainer or owner?

Requested by maintainer in the Codex task thread.

## Real behavior proof (required for external PRs)

- Behavior addressed: Google Chat exec and plugin approvals render as native cards and resolve through Google Chat button clicks. The latest change verifies an exec approval card is not accompanied by a duplicate manual `/approve` instruction bubble.
- Real environment tested: OpenClaw dev profile with a real Google Chat DM to the OpenClaw app, local gateway behind a temporary Cloudflare quick tunnel, and Arc/Computer Use against the signed-in Google Chat session.
- Exact steps or command run after this patch: Rebuilt the gateway runtime, started the dev-profile gateway with the Google Chat webhook routed through the tunnel, sent a fresh exec request from Google Chat, verified only the native approval card appeared, clicked `Allow Once` in Google Chat, and checked the command output reply plus marker file.
- Evidence after fix (screenshot, recording, terminal capture, console output, redacted runtime log, linked artifact, or copied live output): Latest proof used nonce `GCHAT_NODOUBLE_LIVE_20260604070730`, approval id `949bc08c-9e57-47c0-b045-137603782292`, and proof directory `.mem/main/proofs/demo-89502-dev-gchat-exec-approval-no-double-send-channel-race/`. `raw/google-chat-gchat-nodouble-request-card-only-clean.png` shows the fresh user message followed by a single native `Exec Approval Required` card with `Allow Once`/`Deny` and no manual `/approve` follow-up bubble. `raw/google-chat-gchat-nodouble-resolved-clean.png` shows the card edited to `Exec Approval: Allowed once` and the final successful command reply. `raw/gchat-nodouble-live-filtered-log.txt` contains `googlechat approval resolved id=949bc08c-9e57-47c0-b045-137603782292 decision=allow-once`. `raw/marker-file-check.txt` records `/tmp/openclaw-gchat-no-double-GCHAT_NODOUBLE_LIVE_20260604070730` as created.
- Observed result after fix: The approval prompt posted as a native Google Chat card only. No duplicate manual approval-instruction bubble was sent. Clicking `Allow Once` resolved the approval through the gateway and OpenClaw replied with the successful exec output in the same Google Chat DM.
- What was not tested: A persistent production Google Chat app URL; live proof used a temporary Cloudflare tunnel for the local dev callback.
- Proof limitations or environment constraints: Video was not captured for the final resumed manual UI run; still screenshots, gateway/proxy logs, a marker-file artifact, and Showboat verification were captured.
- Before evidence (optional but encouraged): Before the final channel-local suppression path, Google Chat could show both the native approval card and a separate manual `/approve` instruction bubble.

## Tests and validation

Which commands did you run?

- `node scripts/build-all.mjs gatewayWatch`
- `node scripts/run-vitest.mjs extensions/googlechat/src/monitor-webhook.test.ts extensions/googlechat/src/monitor.test.ts extensions/googlechat/src/monitor.reply-delivery.test.ts extensions/googlechat/src/monitor-durable.test.ts extensions/googlechat/src/approval-card-actions.test.ts extensions/googlechat/src/approval-handler.runtime.test.ts extensions/googlechat/src/approval-native.test.ts extensions/googlechat/src/approval-card-click.test.ts extensions/googlechat/src/channel-config.test.ts extensions/googlechat/src/targets.test.ts`
- `git diff --check`
- `pnpm docs:list`
- `uvx showboat --workdir .mem/main/proofs/demo-89502-dev-gchat-exec-approval-no-double-send-channel-race verify .mem/main/proofs/demo-89502-dev-gchat-exec-approval-no-double-send-channel-race/raw/showboat-summary.md`
- Live dev-profile Google Chat proof described above.

What regression coverage was added or updated?

- Added Google Chat native approval capability, runtime delivery, card token, and card-click resolver tests.
- Added in-flight native card send suppression coverage so manual follow-up text is suppressed while native card delivery is pending.
- Added cleanup coverage so manual follow-ups are restored if native card send fails.
- Updated webhook ACK coverage for card-click events and default typing-indicator behavior coverage.

What failed before this fix, if known?

Google Chat could deliver the native approval card and still allow a model/message-tool manual `/approve` follow-up to appear as a second visible bubble.

If no test was added, why not?

Tests were added for the changed runtime and webhook behavior.

## Risk checklist

Did user-visible behavior change? (`Yes/No`)

Yes.

Did config, environment, or migration behavior change? (`Yes/No`)

No migration. The shipped Google Chat `typingIndicator: "message"` default is preserved.

Did security, auth, secrets, network, or tool execution behavior change? (`Yes/No`)

Yes.

What is the highest-risk area?

Approval authorization and callback token handling for native Google Chat card actions.

How is that risk mitigated?

Callbacks carry opaque action tokens only, token bindings check account, space, message, expiry, allowed decision, and in-flight state, and actor authorization reuses the existing Google Chat approver allowlist adapter based on stable `users/<id>` principals.

## Current review state

What is the next action?

Merge after current-head CI for `5923f2af46`.

What is still waiting on author, maintainer, CI, or external proof?

Current-head CI is green for `5923f2af46`; live dev-profile proof is complete.

Which bot or reviewer comments were addressed?

Addressed duplicate approval delivery by keeping the final suppression path inside `extensions/googlechat/`, preserving default typing-message behavior, and proving the current Google Chat surface sends only the native approval card.
2026-06-04 23:05:06 -07:00
Vincent Koc
e0018382eb fix(agents): reject empty completion handoffs 2026-06-04 21:33:42 -07:00
clawsweeper[bot]
69d1d78649 fix(mattermost): anchor slash state on globalThis (#68113) (#90534)
Summary:
- The branch stores Mattermost slash-command account state in a process-wide Symbol.for/globalThis Map and adds module-reload regression coverage.
- PR surface: Source +21, Tests +43. Total +64 across 2 files.
- Reproducibility: yes. at source level: current main's route handler returns 503 when its module-local accoun ... pulate state through a separate loader path. I did not run a live Mattermost POST in this read-only review.

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

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

Prepared head SHA: 3cf28a1f96
Review: https://github.com/openclaw/openclaw/pull/90534#issuecomment-4627897262

Co-authored-by: ben.li <ly85206559@163.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-06-05 04:10:43 +00:00
Peter Steinberger
cb5bb9b936 docs: document e2e helpers 2026-06-05 00:04:03 -04:00
Peter Steinberger
bafe17e60b docs: document vitest routing maps 2026-06-04 23:59:11 -04:00
Peter Steinberger
613a2835cb docs: document scoped script helpers 2026-06-04 23:57:22 -04:00
Peter Steinberger
a59eba3ee1 docs: document test project scripts 2026-06-04 23:55:54 -04:00
Peter Steinberger
9b1a01e4f9 docs: document test wrapper scripts 2026-06-04 23:54:19 -04:00
Peter Steinberger
29746cf7a9 docs: document smoke test scripts 2026-06-04 23:53:10 -04:00
joshavant
17ab517047 fix(ios): use dynamic settings bottom margin 2026-06-04 22:52:52 -05:00
joshavant
697eeb8bab fix(ios): keep diagnostics action reachable 2026-06-04 22:52:52 -05:00
joshavant
853f1c0d9e fix(ios): keep gateway row grouped and tappable 2026-06-04 22:52:52 -05:00
joshavant
1447a4507a fix(ios): keep talk unavailable without config 2026-06-04 22:52:52 -05:00
joshavant
748881e0a8 fix(ios): label chat attachment button 2026-06-04 22:52:52 -05:00
Peter Steinberger
ff83d4d164 docs: document runner scripts 2026-06-04 23:52:06 -04:00
Vincent Koc
13078d24ab chore(release): refresh plugin sdk api baseline 2026-06-04 20:50:17 -07:00
Vincent Koc
48c19590eb fix(test): install playwright deps after host validation failure 2026-06-04 20:50:17 -07:00
Peter Steinberger
72547a1ac6 docs: document release audit scripts 2026-06-04 23:49:34 -04:00
Peter Steinberger
26bc069308 docs: document profiling scripts 2026-06-04 23:48:20 -04:00
Peter Steinberger
57f8d71c50 docs: document release runner scripts 2026-06-04 23:46:55 -04:00
Peter Steinberger
980c91d293 docs: document ci dependency docs scripts 2026-06-04 23:42:32 -04:00
Peter Steinberger
6b0ffa2106 docs: document package boundary scripts 2026-06-04 23:37:42 -04:00
Peter Steinberger
056421f4f8 docs: document root runtime guard scripts 2026-06-04 23:34:16 -04:00
Dallin Romney
fb750e6eed Fix main CI guard drift (#90532) 2026-06-04 20:31:41 -07:00
Peter Steinberger
978fdd7d2a docs: document root guard scripts 2026-06-04 23:30:59 -04:00
Peter Steinberger
74f3baebb7 docs: document root build check scripts 2026-06-04 23:28:04 -04:00
Peter Steinberger
deff9ea180 docs: document cjs bridge headers 2026-06-04 23:26:24 -04:00
Peter Steinberger
9fd5f9ee7c docs: document source bridge files 2026-06-04 23:25:42 -04:00
Vincent Koc
4dd7bc6d88 fix(test): stage live docker home credentials 2026-06-04 20:22:35 -07:00
Onur Solmaz
0dbf17471b feat(memory): support qmd query rerank toggle
Add memory.qmd.rerank as an opt-out for QMD query reranking when searchMode is query.

When set to false, direct QMD query calls pass --no-rerank and the mcporter unified query tool receives rerank:false. Search and vsearch modes keep their existing behavior.

Refs #61834.
2026-06-05 11:18:57 +08:00
Peter Steinberger
f3abe61b78 docs: document script lib test helpers 2026-06-04 23:08:26 -04:00
Peter Steinberger
92cdcae500 docs: document script lib report helpers 2026-06-04 23:07:12 -04:00
Peter Steinberger
3cf1bd22f9 docs: document script lib runtime package helpers 2026-06-04 23:05:22 -04:00
Peter Steinberger
44cd0ec13f docs: document script lib plugin helpers 2026-06-04 23:03:25 -04:00
Peter Steinberger
d77bac8911 docs: document script lib package helpers 2026-06-04 23:01:02 -04:00
Peter Steinberger
1da49dcfd0 docs: document script lib process helpers 2026-06-04 22:59:33 -04:00
Peter Steinberger
ee74fff7ad docs: document script lib inventory helpers 2026-06-04 22:57:30 -04:00
Peter Steinberger
1de46bb425 docs: document script lib extension helpers 2026-06-04 22:56:09 -04:00
Peter Steinberger
e662435067 docs: document script lib guard helpers 2026-06-04 22:54:18 -04:00
Peter Steinberger
62a6fd8139 docs: document script lib scan helpers 2026-06-04 22:52:34 -04:00
Peter Steinberger
88158525a7 docs: document script lib helper contracts 2026-06-04 22:51:08 -04:00
Peter Steinberger
c8bb7330b5 docs: add headers to build check scripts 2026-06-04 22:49:21 -04:00
Peter Steinberger
8732ef2f28 docs: document channel sdk core contracts 2026-06-04 22:46:51 -04:00
Peter Steinberger
8f6e71087b docs: document agent harness sdk contracts 2026-06-04 22:45:30 -04:00
Peter Steinberger
9448f91e6f docs: document memory runtime contracts 2026-06-04 22:44:01 -04:00
Peter Steinberger
5613a0fb6e docs: document discord sdk facade contracts 2026-06-04 22:42:23 -04:00
Peter Steinberger
82710b4f1f docs: document lmstudio runtime contracts 2026-06-04 22:41:26 -04:00
Peter Steinberger
d23558e691 docs: document qa runtime facade contracts 2026-06-04 22:40:12 -04:00
Peter Steinberger
2f00fbf28e docs: document tts runtime contracts 2026-06-04 22:39:02 -04:00
Peter Steinberger
86872e0880 docs: document channel approval ingress contracts 2026-06-04 22:38:03 -04:00
Peter Steinberger
506c2ee181 docs: document qa video gateway sdk contracts 2026-06-04 22:34:53 -04:00
Peter Steinberger
1e6fb5089b docs: document approval reaction reply contracts 2026-06-04 22:32:37 -04:00
Peter Steinberger
14690904f0 docs: document browser session oauth sdk contracts 2026-06-04 22:31:20 -04:00
Peter Steinberger
99bb94589b docs: document sdk facade loader contracts 2026-06-04 22:29:06 -04:00
Peter Steinberger
de4571da4b docs: document sdk dedupe and group contracts 2026-06-04 22:27:50 -04:00
Peter Steinberger
a4087c54b5 docs: document provider facade constants 2026-06-04 22:26:17 -04:00
Peter Steinberger
4756d6a42a docs: document sdk migration and approval contracts 2026-06-04 22:24:26 -04:00
Peter Steinberger
9e22b8560c docs: document sdk facade contracts 2026-06-04 22:22:21 -04:00
Peter Steinberger
c1b49bb1d0 docs: document sdk payload and fetch contracts 2026-06-04 22:20:19 -04:00
Peter Steinberger
d6c0f9ccb8 docs: document sdk utility contracts 2026-06-04 22:18:33 -04:00
Peter Steinberger
5d350e785a docs: document sdk single-export contracts 2026-06-04 22:16:29 -04:00
Peter Steinberger
de68623ffe docs: document sdk runtime helper contracts 2026-06-04 22:14:54 -04:00
Peter Steinberger
848f39e70d docs: document public sdk contract helpers 2026-06-04 22:13:13 -04:00
Peter Steinberger
b311fd607f docs: document generated locale bundles 2026-06-04 22:11:11 -04:00
Patrick Erichsen
8f85f94946 feat: install GitHub-backed ClawHub skills (#90478)
* feat: install GitHub-backed ClawHub skills

* fix: satisfy ClawHub install type checks

* fix: harden github-backed skill installs

* fix: keep heartbeat template non-actionable

* feat: support forcing pending ClawHub installs
2026-06-04 19:10:02 -07:00
Peter Steinberger
5380d11977 docs: document scoped extension sources 2026-06-04 22:07:59 -04:00
Peter Steinberger
23716de446 docs: document discord extension sources 2026-06-04 22:06:01 -04:00
Peter Steinberger
efd1a9ace6 docs: document messaging extension sources 2026-06-04 22:03:15 -04:00
Sally O'Malley
7ac1eeb122 fix service env placeholder collection (#90488)
Signed-off-by: sallyom <somalley@redhat.com>
2026-06-04 22:02:24 -04:00
Peter Steinberger
58912f8fd8 docs: document channel extension sources 2026-06-04 21:59:00 -04:00
Peter Steinberger
6868cde4d4 docs: document large extension sources 2026-06-04 21:40:44 -04:00
Peter Steinberger
3c7c25afd2 fix: accept codex app-server auth aliases 2026-06-04 21:40:36 -04:00
Peter Steinberger
96e5812426 docs: document medium extension sources 2026-06-04 21:33:54 -04:00
Shakker
126ebfc997 test: share probe target env cleanup 2026-06-05 02:20:14 +01:00
Shakker
4b151593e2 test: scope model scan key env 2026-06-05 02:18:51 +01:00
Shakker
56f652b499 test: pin oauth tls brew env 2026-06-05 02:17:15 +01:00
Shakker
5a704d26a1 test: localize control ui home env 2026-06-05 02:15:55 +01:00
Shakker
e7bcbd3e7e test: isolate windows acl system root 2026-06-05 02:14:03 +01:00
Shakker
afcf1ddb9d test: confine web fetch key env 2026-06-05 02:12:53 +01:00
Shakker
85e16da2b4 test: scope preauth budget env 2026-06-05 02:11:44 +01:00
Shakker
38e142657b test: bound proxy resolver env 2026-06-05 02:10:43 +01:00
Shakker
4dd00347fc test: contain web media home env 2026-06-05 02:09:30 +01:00
Shakker
0973eb61c3 test: snapshot pairing gateway env 2026-06-05 02:07:35 +01:00
Shakker
e282cb2af5 test: contain media roots state env 2026-06-05 02:05:18 +01:00
Shakker
6f419b3853 test: narrow media proxy env scope 2026-06-05 02:04:56 +01:00
Peter Steinberger
4fa5092cdc docs: document small extension sources 2026-06-04 21:02:07 -04:00
Shakker
53a3d58d62 test: isolate npm update smoke env 2026-06-05 02:00:29 +01:00
Shakker
cef423d066 test: isolate group report planner env 2026-06-05 01:58:47 +01:00
Shakker
5cf63f295b test: snapshot exec audit home env 2026-06-05 01:57:47 +01:00
Shakker
86d958647f test: scope embedded shutdown grace env 2026-06-05 01:57:25 +01:00
Peter Steinberger
12a56d4d46 docs: document control ui sources 2026-06-04 20:57:09 -04:00
Shakker
39cc11ad28 test: scope tui shutdown grace env 2026-06-05 01:56:16 +01:00
Peter Steinberger
4df95d3c3f docs: document package sources 2026-06-04 20:54:41 -04:00
Peter Steinberger
b8d08f0cfd docs: document repository scripts 2026-06-04 20:52:50 -04:00
Shakker
95d51c5fe8 test: snapshot redact config env 2026-06-05 01:51:48 +01:00
Shakker
5c6a501269 test: snapshot log tail config env 2026-06-05 01:51:48 +01:00
Shakker
dc4c9030fc test: snapshot diagnostic state env 2026-06-05 01:51:48 +01:00
Shakker
8ede9e0e07 test: scope doctor gateway token env 2026-06-05 01:51:48 +01:00
Shakker
9739249043 test: scope channel prompts locale 2026-06-05 01:51:48 +01:00
Shakker
dbb80f3bb7 test: scope search setup locale 2026-06-05 01:51:27 +01:00
Shakker
61d9ac8c5d test: scope channel status locale 2026-06-05 01:51:27 +01:00
Shakker
abc00f4c98 test: snapshot logging config env 2026-06-05 01:51:27 +01:00
Shakker
28737a0b09 test: snapshot console settings env 2026-06-05 01:51:27 +01:00
Shakker
28b63e69e9 test: snapshot logger settings env 2026-06-05 01:51:27 +01:00
Shakker
5392cb7139 test: snapshot logger level env 2026-06-05 01:51:27 +01:00
Shakker
55c414ca81 test: reuse parallels env helper 2026-06-05 01:51:27 +01:00
Shakker
74680e3484 test: reuse release env helper 2026-06-05 01:51:27 +01:00
Shakker
d6e1ca997b test: snapshot openai provider env 2026-06-05 01:51:27 +01:00
Shakker
c4ed850f9b test: snapshot tts prefs env 2026-06-05 01:51:27 +01:00
Shakker
4957e3b02f test: share brew env helpers 2026-06-05 01:51:27 +01:00
Shakker
323c8aa87f test: snapshot npm global config env 2026-06-05 01:51:27 +01:00
Shakker
442a2107b5 test: scope bun install detection env 2026-06-05 01:51:27 +01:00
Shakker
ed52d27d78 test: share env api key snapshot 2026-06-05 01:51:27 +01:00
Shakker
cb17c84410 test: let flow registry helper own state env 2026-06-05 01:51:27 +01:00
Shakker
f57adba400 test: snapshot task executor env 2026-06-05 01:51:27 +01:00
Shakker
9f6ed16a6d test: snapshot task flow maintenance env 2026-06-05 01:51:27 +01:00
Shakker
99a838fac4 test: snapshot task registry store env 2026-06-05 01:51:27 +01:00
Shakker
064182aff8 test: snapshot task flow audit env 2026-06-05 01:51:26 +01:00
Shakker
0f9bb59b73 test: snapshot task owner state env 2026-06-05 01:51:26 +01:00
Shakker
79b6dd049e test: scope inherited agent dir fixture 2026-06-05 01:51:26 +01:00
Peter Steinberger
58c663920d docs: document script tests 2026-06-04 20:49:50 -04:00
Marcus Castro
dd2083c7ec fix(whastapp): bound connection startup waits (#90486)
* fix: add timeout to waitForWaConnection to prevent indefinite hangs

If Baileys fails to emit a 'connection.update' event with either 'open'
or 'close' status (e.g. due to network issues or internal errors), the
waitForWaConnection promise hangs forever, blocking the entire monitor
loop.

Add a configurable timeout (default 60s) that rejects the promise and
cleans up the event listener if no connection state is received in time.
The timeout is backward-compatible as an optional parameter with a
sensible default.

* test: add coverage for waitForWaConnection timeout path

- Test that promise rejects with descriptive error after timeout
- Test that event listener is cleaned up after timeout
- Test that timer is cleared when connection opens before timeout

* fix: default timeoutMs to 0 to preserve QR login behavior

The 60s default broke the QR login flow in login-qr.ts, which calls
waitForWaConnection without a timeout and expects to wait up to 3 minutes
while the user scans. Change the default to 0 (wait forever, matching
original behavior) and pass the 60s timeout explicitly at the monitor
callsite where it's actually needed.

* fix: bound whatsapp connection startup waits

* fix: align web channel wait contract

* fix: retry whatsapp setup timeouts

* fix: satisfy whatsapp status lint

* fix: preserve whatsapp wait compatibility

---------

Co-authored-by: MMMMSSSS8899 <praelovk@gmail.com>
2026-06-04 21:45:43 -03:00
Peter Steinberger
29f5e9d35c docs: document test helpers 2026-06-04 20:42:26 -04:00
Peter Steinberger
25211167e8 docs: document vitest config files 2026-06-04 20:40:11 -04:00
Peter Steinberger
ecb6779a16 docs: document root test files 2026-06-04 20:37:28 -04:00
Peter Steinberger
edb920b857 docs: document remaining src helpers 2026-06-04 20:34:26 -04:00
Peter Steinberger
b2e320dfb1 docs: document support test files 2026-06-04 20:31:55 -04:00
Peter Steinberger
1bdf210b43 docs: document rescue and trajectory tests 2026-06-04 20:29:59 -04:00
Peter Steinberger
d8326f13c3 docs: document proxy and mcp helpers 2026-06-04 20:27:46 -04:00
Peter Steinberger
9b30ff181c docs: document routing helpers 2026-06-04 20:25:55 -04:00
Peter Steinberger
4f79f2419c docs: document video generation helpers 2026-06-04 20:24:49 -04:00
Peter Steinberger
65546f0158 docs: document tui components 2026-06-04 20:23:23 -04:00
Peter Steinberger
6d58ff3562 docs: document session helpers 2026-06-04 20:22:09 -04:00
Peter Steinberger
47bae66415 docs: document session config tests 2026-06-04 20:20:20 -04:00
Peter Steinberger
f5b6a977d7 docs: document tts helpers 2026-06-04 20:19:15 -04:00
Peter Steinberger
85e6940202 docs: document talk helpers 2026-06-04 20:17:42 -04:00
Peter Steinberger
5ba4eeceac docs: document daemon tests 2026-06-04 20:16:21 -04:00
Peter Steinberger
a628a66e4d docs: document process helpers 2026-06-04 20:14:34 -04:00
Peter Steinberger
ef08c83e17 docs: document utility helpers 2026-06-04 20:12:49 -04:00
Peter Steinberger
b6ce59d367 docs: document wizard helpers 2026-06-04 20:11:22 -04:00
Peter Steinberger
c8665c66ba docs: document flow helpers 2026-06-04 20:10:01 -04:00
Peter Steinberger
4c3b4f8ad8 docs: document hook helpers 2026-06-04 20:08:40 -04:00
Peter Steinberger
e6f85453dc docs: document llm helpers 2026-06-04 20:07:13 -04:00
Peter Steinberger
f1bdc91b64 docs: document media helpers 2026-06-04 20:05:16 -04:00
Peter Steinberger
add135d238 docs: document logging helpers 2026-06-04 20:04:06 -04:00
Vincent Koc
563dac5989 test(core): remove stale unused test bindings 2026-06-04 17:03:40 -07:00
Vincent Koc
5bc300a1df test(agents): align pdf default model expectation 2026-06-04 17:03:40 -07:00
Vincent Koc
1d19d7ec46 fix(auto-reply): skip commented heartbeat scaffolding 2026-06-04 17:03:40 -07:00
Peter Steinberger
87d053c0cb docs: document shared helpers 2026-06-04 20:02:33 -04:00
Peter Steinberger
5b53cddc75 docs: document cron test files 2026-06-04 20:01:05 -04:00
Peter Steinberger
6c48a12562 docs: document skill runtime files 2026-06-04 19:58:44 -04:00
Peter Steinberger
43cee29f70 docs: document skill loading files 2026-06-04 19:57:11 -04:00
Peter Steinberger
725ddd11cc docs: document remaining plugin runtime files 2026-06-04 19:54:07 -04:00
Peter Steinberger
d2d14d5793 docs: document plugin contract tests 2026-06-04 19:52:26 -04:00
Peter Steinberger
f25c246f6b docs: document plugin runtime helpers 2026-06-04 19:48:26 -04:00
Peter Steinberger
6486fc1c0d docs: document model command tests 2026-06-04 19:46:17 -04:00
Peter Steinberger
81eee47045 docs: document doctor command tests 2026-06-04 19:44:23 -04:00
Peter Steinberger
4499b24781 docs: document cli program tests 2026-06-04 19:41:55 -04:00
Peter Steinberger
b59b34f9d5 docs: document cli service tests 2026-06-04 19:39:51 -04:00
Shakker
912e70acbd test: scope system run helper env 2026-06-05 00:38:28 +01:00
Shakker
16147e16e3 test: isolate approval path token cases 2026-06-05 00:38:28 +01:00
Shakker
638be00f4b test: scope fake runtime path setup 2026-06-05 00:38:28 +01:00
Shakker
695e09d360 test: scope proof temp dir env 2026-06-05 00:38:28 +01:00
Shakker
69ddcc00e6 test: scope invoke prepare path env 2026-06-05 00:38:28 +01:00
Shakker
a18c60e141 test: scope sandbox audit home env 2026-06-05 00:38:28 +01:00
Shakker
ec048ae693 test: restore cron state dir through helper 2026-06-05 00:38:28 +01:00
Shakker
7675b10223 test: capture usage format env setup 2026-06-05 00:38:28 +01:00
Shakker
25a1b0c240 test: cover allowlist tilde expansion 2026-06-05 00:38:28 +01:00
Shakker
c006ed5e16 test: restore reply harness temp home 2026-06-05 00:38:27 +01:00
Shakker
b4e048e60a test: reset gateway token env per case 2026-06-05 00:38:27 +01:00
Shakker
f365568f1b test: shorten tool metadata home paths 2026-06-05 00:38:27 +01:00
Shakker
e2c23d8a5e test: verify model status agent-dir env 2026-06-05 00:38:27 +01:00
Peter Steinberger
408ba4c8a0 docs: document remaining cli tests 2026-06-04 19:37:38 -04:00
Peter Steinberger
4995907541 docs: document cli support tests 2026-06-04 19:35:08 -04:00
Peter Steinberger
8cb093e7a9 docs: document cli test batch 2026-06-04 19:32:43 -04:00
Peter Steinberger
3e29885c83 docs: document channel subdir tests 2026-06-04 19:30:09 -04:00
Peter Steinberger
867d7898df docs: document channel plugin contracts 2026-06-04 19:28:31 -04:00
Peter Steinberger
fa46138047 docs: document channel plugin tests 2026-06-04 19:24:55 -04:00
Peter Steinberger
c135624c69 docs: document root channel tests 2026-06-04 19:23:04 -04:00
Peter Steinberger
048f307695 docs: document remaining plugin sdk files 2026-06-04 19:21:04 -04:00
Peter Steinberger
feffb6d02f docs: document plugin sdk runtime helpers 2026-06-04 19:16:24 -04:00
Peter Steinberger
a16c6ca94b docs: document plugin sdk public helpers 2026-06-04 19:14:41 -04:00
Vincent Koc
7fb748462e fix(ci): classify live installer docker lanes 2026-06-04 16:13:27 -07:00
Peter Steinberger
50dcaad71a docs: document remaining command tests 2026-06-04 19:11:43 -04:00
Peter Steinberger
7a7ca15776 docs: document command setup batch 2026-06-04 19:07:41 -04:00
Peter Steinberger
bf19d198d9 docs: document command cleanup batch 2026-06-04 19:05:16 -04:00
Peter Steinberger
eaad487c42 docs: document command report batch 2026-06-04 19:03:19 -04:00
Peter Steinberger
12ade5c5e8 docs: document command scan batch 2026-06-04 19:01:12 -04:00
Peter Steinberger
076bf2a361 docs: document command status batch 2026-06-04 18:59:04 -04:00
Peter Steinberger
0156de5c34 docs: document command onboarding batch 2026-06-04 18:57:02 -04:00
Shakker
646eb00112 test: pin acp prompt home redaction 2026-06-04 23:55:53 +01:00
Shakker
06f95f9a65 test: anchor auth sqlite agent dirs 2026-06-04 23:55:53 +01:00
Shakker
9a78886c78 test: localize logger env overrides 2026-06-04 23:55:53 +01:00
Shakker
66212260ef test: seal crestodian rescue stores 2026-06-04 23:55:53 +01:00
Shakker
dda0a98b76 test: bracket agent directory fixtures 2026-06-04 23:55:53 +01:00
Shakker
c71d3e45a1 test: isolate tts status fixture homes 2026-06-04 23:55:53 +01:00
Shakker
986025afe4 test: guard fs-safe tilde fixtures 2026-06-04 23:55:53 +01:00
Peter Steinberger
0d393ba6b4 docs: document command diagnostics batch 2026-06-04 18:54:31 -04:00
Peter Steinberger
0de924b35c docs: document command support batch 2026-06-04 18:52:07 -04:00
Peter Steinberger
4a47a9db98 docs: document command test batch 2026-06-04 18:50:37 -04:00
Peter Steinberger
5fa55d93f7 docs: document command helper tests 2026-06-04 18:48:22 -04:00
Peter Steinberger
64008398d1 docs: document noninteractive onboarding tests 2026-06-04 18:47:21 -04:00
Peter Steinberger
5c362884f3 docs: document channel setup tests 2026-06-04 18:46:23 -04:00
Peter Steinberger
71b09b99f8 docs: document migrate command tests 2026-06-04 18:45:28 -04:00
Peter Steinberger
3f31b62cd4 docs: document channels capability tests 2026-06-04 18:44:22 -04:00
Peter Steinberger
4927388580 docs: document gateway status tests 2026-06-04 18:43:35 -04:00
Peter Steinberger
19da9d8832 docs: document status-all command tests 2026-06-04 18:42:37 -04:00
Peter Steinberger
bea27678b4 docs: document link understanding 2026-06-04 18:41:10 -04:00
Peter Steinberger
ba28f7b018 docs: document model catalog planners 2026-06-04 18:40:10 -04:00
Peter Steinberger
571179c80b docs: document gateway live tests 2026-06-04 18:38:44 -04:00
Peter Steinberger
f0e5fdc064 docs: document gateway connection helpers 2026-06-04 18:36:52 -04:00
Peter Steinberger
f24ae91842 docs: document gateway server runtime 2026-06-04 18:35:26 -04:00
Peter Steinberger
ec22756340 docs: document gateway method descriptors 2026-06-04 18:34:05 -04:00
Peter Steinberger
e1b5fd2716 docs: document gateway test helpers 2026-06-04 18:33:25 -04:00
Peter Steinberger
437a5a71ae docs: document gateway runtime helpers 2026-06-04 18:30:41 -04:00
Peter Steinberger
a8154f425c docs: document gateway tool methods 2026-06-04 18:28:04 -04:00
Peter Steinberger
a6ecc4bd89 docs: document gateway session methods 2026-06-04 18:25:03 -04:00
Peter Steinberger
8c94131c0d docs: document gateway send methods 2026-06-04 18:22:31 -04:00
Peter Steinberger
e825301393 docs: document gateway node methods 2026-06-04 18:21:03 -04:00
Peter Steinberger
a84910be91 docs: document gateway diagnostics methods 2026-06-04 18:18:51 -04:00
Peter Steinberger
390a35d441 docs: document gateway chat methods 2026-06-04 18:17:28 -04:00
Peter Steinberger
f4c448f65b docs: document gateway agents methods 2026-06-04 18:15:10 -04:00
Peter Steinberger
c5d6764f56 docs: document gateway agent methods 2026-06-04 18:13:20 -04:00
Peter Steinberger
7f6af117f2 docs: document gateway tool test suites 2026-06-04 18:11:47 -04:00
Peter Steinberger
f0cb1a93e5 docs: document gateway session test suites 2026-06-04 18:10:05 -04:00
Peter Steinberger
d89d352971 docs: document gateway auth test suites 2026-06-04 18:08:07 -04:00
Shakker
3f6268ebd7 test: scope utility home env 2026-06-04 23:06:33 +01:00
Shakker
f3128f92d0 test: scope qqbot path env 2026-06-04 23:06:33 +01:00
Shakker
ec56a94ba3 test: scope sandbox env checks 2026-06-04 23:06:33 +01:00
Shakker
f0256be48d test: fence oauth manager env 2026-06-04 23:06:33 +01:00
Shakker
9de73ab6d2 test: scope agent auth copy state 2026-06-04 23:06:33 +01:00
Shakker
6bb91b2971 test: fence embedding provider secrets env 2026-06-04 23:06:33 +01:00
Shakker
840eaf9c19 test: centralize task flow state env 2026-06-04 23:06:33 +01:00
Shakker
2f6d4b811c test: isolate cleanup plan env 2026-06-04 23:06:33 +01:00
Shakker
509fa621de test: contain completion cache env 2026-06-04 23:06:33 +01:00
Peter Steinberger
6a95c8724a docs: document gateway chat test suites 2026-06-04 18:05:57 -04:00
Peter Steinberger
82de5903d7 docs: document gateway server test suites 2026-06-04 18:04:23 -04:00
Peter Steinberger
64b288be64 docs: document gateway probe test suites 2026-06-04 18:02:27 -04:00
Peter Steinberger
768143af06 docs: document gateway http test suites 2026-06-04 18:01:05 -04:00
Peter Steinberger
1e311058bc docs: document gateway config test suites 2026-06-04 17:58:55 -04:00
Peter Steinberger
7d216c2945 docs: document gateway client test suites 2026-06-04 17:57:26 -04:00
Peter Steinberger
fd8c789d42 docs: document gateway root test suites 2026-06-04 17:56:00 -04:00
Vincent Koc
deb9f11897 test(docker): harden live acp bind probes 2026-06-04 14:55:05 -07:00
Peter Steinberger
41d5e685ef docs: document gateway probe test helpers 2026-06-04 17:52:50 -04:00
Peter Steinberger
ca72d2706e docs: document gateway live runtime helpers 2026-06-04 17:50:37 -04:00
Shakker
81d9c2f41f test: scope session history state 2026-06-04 22:49:01 +01:00
Shakker
a0a115d466 test: wrap managed image attachment env 2026-06-04 22:49:01 +01:00
Shakker
501adb2524 test: isolate command secret env values 2026-06-04 22:49:01 +01:00
Shakker
1a4732410a test: scope host hook contract state 2026-06-04 22:49:01 +01:00
Peter Steinberger
8779bc49e0 docs: document gateway test helper fixtures 2026-06-04 17:47:12 -04:00
Peter Steinberger
15afc1d34c docs: document gateway auth ui runtime helpers 2026-06-04 17:45:49 -04:00
Peter Steinberger
8b4d12e161 docs: document gateway node startup helpers 2026-06-04 17:43:37 -04:00
Peter Steinberger
4c5b423fb8 docs: document gateway history runtime helpers 2026-06-04 17:41:47 -04:00
Peter Steinberger
bd76296c21 docs: document gateway runtime helpers 2026-06-04 17:38:20 -04:00
Peter Steinberger
360b2c9699 docs: document gateway session utility helpers 2026-06-04 17:36:25 -04:00
Peter Steinberger
aa9cc80060 docs: document gateway shutdown session helpers 2026-06-04 17:34:36 -04:00
Peter Steinberger
861bf541c2 docs: document gateway client auth helpers 2026-06-04 17:32:38 -04:00
Peter Steinberger
c8ac4c8aea docs: document gateway reload helpers 2026-06-04 17:30:08 -04:00
Peter Steinberger
8e371cfea1 docs: document gateway channel helpers 2026-06-04 17:27:42 -04:00
Peter Steinberger
dc23e924ef docs: document gateway runtime startup 2026-06-04 17:26:02 -04:00
Peter Steinberger
a3f495eb09 docs: document gateway node helpers 2026-06-04 17:23:48 -04:00
Peter Steinberger
1e438739bc docs: document gateway mcp helpers 2026-06-04 17:22:27 -04:00
Peter Steinberger
4d8502804d docs: document gateway state helpers 2026-06-04 17:20:55 -04:00
Peter Steinberger
d72184d3e0 docs: document gateway auth helpers 2026-06-04 17:18:36 -04:00
Peter Steinberger
7e0ee6d5c8 docs: document gateway utility policies 2026-06-04 17:16:36 -04:00
Peter Steinberger
2da49ef4ac docs: document gateway node policies 2026-06-04 17:14:38 -04:00
Peter Steinberger
fba99cddc1 docs: document gateway session utilities 2026-06-04 17:13:14 -04:00
Peter Steinberger
d76301e0ab docs: document gateway http helpers 2026-06-04 17:10:56 -04:00
Peter Steinberger
043929e76d docs: document gateway auth helpers 2026-06-04 17:09:08 -04:00
Peter Steinberger
c9c8125941 docs: document time formatting helpers 2026-06-04 17:06:59 -04:00
Peter Steinberger
b4a63886af docs: document outbound action runner 2026-06-04 17:06:05 -04:00
Peter Steinberger
5a6eddf5d0 docs: document outbound delivery queue 2026-06-04 17:04:07 -04:00
Peter Steinberger
ba72fb5b43 docs: document outbound message policy 2026-06-04 17:02:49 -04:00
Peter Steinberger
fc1848a28b docs: document outbound channel resolution 2026-06-04 17:01:45 -04:00
Peter Steinberger
aa12e7cda9 docs: document outbound action helpers 2026-06-04 17:00:31 -04:00
Peter Steinberger
9093556647 docs: document outbound session bindings 2026-06-04 16:59:17 -04:00
Peter Steinberger
ffc6bc0be0 docs: document outbound target helpers 2026-06-04 16:58:07 -04:00
Peter Steinberger
1f52854c0d docs: document command analysis infra 2026-06-04 16:56:05 -04:00
Peter Steinberger
170df6612e docs: document managed proxy net helpers 2026-06-04 16:54:14 -04:00
Peter Steinberger
eb6be3cf62 docs: document proxy network helpers 2026-06-04 16:52:20 -04:00
Peter Steinberger
53aa5232bc docs: document guarded fetch net helpers 2026-06-04 16:50:29 -04:00
Peter Steinberger
ba82257e37 docs: document media runner scenario tests 2026-06-04 16:48:42 -04:00
Peter Steinberger
5f7095f8be docs: document media runner core 2026-06-04 16:47:26 -04:00
Peter Steinberger
d6e4c879e8 docs: document media audio helpers 2026-06-04 16:46:02 -04:00
Peter Steinberger
ef6f4c1544 docs: document media attachment runtime 2026-06-04 16:45:01 -04:00
Peter Steinberger
9b42f399a1 docs: document media understanding defaults 2026-06-04 16:43:48 -04:00
Peter Steinberger
347ed87a96 docs: document agent instruction files 2026-06-04 16:42:36 -04:00
Peter Steinberger
3d168074b4 docs: document sandbox ssh tests 2026-06-04 16:41:43 -04:00
Peter Steinberger
cc296f3a46 docs: document subagent tests 2026-06-04 16:40:43 -04:00
Peter Steinberger
f39aff1558 docs: document remaining agent tool tests 2026-06-04 16:39:32 -04:00
Peter Steinberger
ea9f791a68 docs: document image and pdf tool tests 2026-06-04 16:38:27 -04:00
Peter Steinberger
d5ce1edf7e docs: document core agent tool tests 2026-06-04 16:37:10 -04:00
Peter Steinberger
5c71f2190b docs: document media cron tool tests 2026-06-04 16:35:06 -04:00
Peter Steinberger
c70e2bd2b3 docs: document sandbox helper tests 2026-06-04 16:33:10 -04:00
Peter Steinberger
ba02f12464 docs: document sandbox policy tests 2026-06-04 16:31:29 -04:00
Peter Steinberger
4e6fbf73a2 docs: document sandbox filesystem tests 2026-06-04 16:30:09 -04:00
Peter Steinberger
a0fa579cdc docs: document docker sandbox tests 2026-06-04 16:28:39 -04:00
Peter Steinberger
a98f292a11 docs: document status tool tests 2026-06-04 16:26:49 -04:00
Peter Steinberger
56ae6d3c1a docs: document common agent tool tests 2026-06-04 16:25:47 -04:00
Peter Steinberger
0e427e6cdc docs: document web runtime tests 2026-06-04 16:24:37 -04:00
Peter Steinberger
caa9078e70 docs: document web search fetch tests 2026-06-04 16:23:34 -04:00
Peter Steinberger
099584676b docs: document extension loader tests 2026-06-04 16:22:24 -04:00
Peter Steinberger
1ad9109a6c docs: document agent session infra tests 2026-06-04 16:21:30 -04:00
Peter Steinberger
1e8609af5d docs: document pdf web tool tests 2026-06-04 16:20:29 -04:00
Peter Steinberger
a3f21d03e8 docs: document sandbox config tests 2026-06-04 16:18:47 -04:00
Peter Steinberger
d045deb79d docs: document session tool tests 2026-06-04 16:17:22 -04:00
Peter Steinberger
c65eacae17 docs: document agent session tests 2026-06-04 16:16:25 -04:00
Chunyue Wang
6c259af759 fix(agents): strip stale compaction thinking signatures before Anthropic replay (#90163)
Pre-compaction assistant messages carry thinkingSignature values bound to the
original conversation prefix. After compaction the prefix changes (summarized
content is replaced by the compaction summary), so Anthropic rejects those
signatures with "Invalid signature in thinking block", permanently stalling the
session through gateway restarts.

stripInvalidThinkingSignatures only catches absent/blank signatures; this adds
stripStaleThinkingSignaturesForCompactionReplay (thinking.ts) which identifies
pre-compaction assistant messages by timestamp comparison against the latest
compaction summary and strips their signature fields. Called in
sanitizeSessionHistory (replay-history.ts) before stripInvalidThinkingSignatures
for all signed-thinking providers (Anthropic, Bedrock, Vertex). Also fixes
buildSuccessorEntries (compaction-successor-transcript.ts) to strip only
pre-compaction kept entries when writing the rotation successor JSONL; uses
strict < timestamp boundary so same-instant post-compaction messages are not
affected.

Docs: update transcript-hygiene.md Anthropic and Bedrock sections.
Tests: 8 new cases for stripStaleThinkingSignaturesForCompactionReplay; 1 new
case for buildSuccessorEntries verifying pre/post-compaction signature boundary.

Fixes #90108
2026-06-04 16:15:44 -04:00
Peter Steinberger
266dcf33f2 docs: document gateway web tool tests 2026-06-04 16:15:21 -04:00
Peter Steinberger
b380cdc84e docs: document media generation tests 2026-06-04 16:13:06 -04:00
Peter Steinberger
0f73e09769 docs: document sessions tools tests 2026-06-04 16:11:19 -04:00
Peter Steinberger
2d3b378876 docs: document tool guard tests 2026-06-04 16:09:36 -04:00
Peter Steinberger
3ac506a887 docs: document agent utility tests 2026-06-04 16:08:01 -04:00
Peter Steinberger
22f21ed7e6 docs: document runtime plan type tests 2026-06-04 16:06:12 -04:00
Shakker
bca7d18c60 test: scope chat directive transcript state 2026-06-04 21:06:04 +01:00
Shakker
9932ba7359 test: wrap session projection stores 2026-06-04 21:06:04 +01:00
Shakker
53978b358a test: isolate auth profile state dirs 2026-06-04 21:06:04 +01:00
Shakker
3f16f2e9a5 test: contain config write env state 2026-06-04 21:06:04 +01:00
Shakker
4a6dc1b830 test: scope task registry env setup 2026-06-04 21:06:04 +01:00
Peter Steinberger
7766d2b65b docs: document runtime plan tests 2026-06-04 16:04:45 -04:00
Peter Steinberger
01eefa7f96 docs: document transcript tool tests 2026-06-04 16:03:01 -04:00
Peter Steinberger
ff254a44c9 docs: document workspace transport tests 2026-06-04 16:01:19 -04:00
Peter Steinberger
22f2a91c2d docs: document system prompt tests 2026-06-04 15:59:59 -04:00
Peter Steinberger
1f57a946ca docs: document tool policy tests 2026-06-04 15:58:11 -04:00
Peter Steinberger
a09594b4ac docs: document subagent spawn tests 2026-06-04 15:56:34 -04:00
Peter Steinberger
e7de27f8b0 docs: document subagent registry persistence tests 2026-06-04 15:55:31 -04:00
Peter Steinberger
ec4a871f91 docs: document subagent registry lifecycle tests 2026-06-04 15:54:32 -04:00
Peter Steinberger
7af2673965 docs: document subagent registry helpers 2026-06-04 15:53:22 -04:00
Peter Steinberger
a9224f6f5d docs: document subagent control tests 2026-06-04 15:52:23 -04:00
Peter Steinberger
ca24dd7793 docs: document subagent announce tests 2026-06-04 15:51:15 -04:00
Peter Steinberger
f4ac968577 docs: document simple completion tests 2026-06-04 15:50:27 -04:00
Peter Steinberger
939fe702a6 docs: document session shell tests 2026-06-04 15:48:20 -04:00
Peter Steinberger
dca200ade5 docs: document session guard tests 2026-06-04 15:46:45 -04:00
Peter Steinberger
58f00707ed docs: document sandbox path tests 2026-06-04 15:45:12 -04:00
Peter Steinberger
3da0803ab4 docs: document sandbox runtime tests 2026-06-04 15:43:40 -04:00
Vincent Koc
40661e9d19 fix(test): use API-key auth for Codex live Docker lanes 2026-06-04 12:43:30 -07:00
Peter Steinberger
57ec0b236f docs: document runtime utility tests 2026-06-04 15:42:07 -04:00
Peter Steinberger
88a0fc69f0 docs: document provider transport tests 2026-06-04 15:40:23 -04:00
Peter Steinberger
4a93974a90 docs: document provider policy tests 2026-06-04 15:39:01 -04:00
Peter Steinberger
d3e5959669 docs: document subagent tool harness tests 2026-06-04 15:37:17 -04:00
Peter Steinberger
f8f7ba8f01 docs: document subagent spawn tests 2026-06-04 15:35:43 -04:00
Peter Steinberger
1a8d237369 docs: document openclaw session tool tests 2026-06-04 15:34:42 -04:00
Peter Steinberger
b491058e88 docs: document openclaw tool tests 2026-06-04 15:33:39 -04:00
Peter Steinberger
1df9bca8e2 docs: document openai transport tests 2026-06-04 15:32:37 -04:00
Peter Steinberger
48d67e88d0 docs: document openai live compat tests 2026-06-04 15:31:22 -04:00
Peter Steinberger
8605076a6f docs: document models config serialization tests 2026-06-04 15:30:20 -04:00
Peter Steinberger
c1b54fe01e docs: document provider policy tests 2026-06-04 15:29:14 -04:00
Peter Steinberger
117bb3c61c docs: document provider config tests 2026-06-04 15:28:05 -04:00
Peter Steinberger
c31877464c docs: document models config tests 2026-06-04 15:25:52 -04:00
Peter Steinberger
4653454c91 docs: document model selection tests 2026-06-04 15:24:14 -04:00
Peter Steinberger
287a62c2fd docs: document model runtime tests 2026-06-04 15:22:18 -04:00
Peter Steinberger
a0cdd4e305 docs: document model fallback tests 2026-06-04 15:20:42 -04:00
Peter Steinberger
3140bb695d docs: document model auth tests 2026-06-04 15:18:53 -04:00
Josh Lehman
ab0a633ab9 fix: tolerate missing streamed response content type
Fixes the OpenAI-compatible stream transport regression where a valid ChatGPT Codex HTTP 200 stream could arrive without a `content-type` header and be rejected before the OpenAI SDK consumed it.

Prepared head SHA: 0d7f8abb17

Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
2026-06-04 12:17:22 -07:00
Peter Steinberger
d4523cba74 docs: document model transport tests 2026-06-04 15:16:44 -04:00
Peter Steinberger
0d2a9073f5 docs: document mcp session tests 2026-06-04 15:14:28 -04:00
Peter Steinberger
4c5b2cf2e2 docs: document live model tests 2026-06-04 15:13:12 -04:00
Jacob Tomlinson
829847292e feat(nvidia): default to nemotron ultra
Add NVIDIA Nemotron 3 Ultra to the bundled NVIDIA provider catalog and make it the bundled fallback default. Keep successful NVIDIA featured-model feeds authoritative, while treating the first live feed row as the setup default option. Update NVIDIA provider docs and focused provider/model-picker tests for the new Ultra behavior.

Verification:
- node scripts/run-vitest.mjs src/commands/model-picker.test.ts extensions/nvidia/provider-catalog.test.ts extensions/nvidia/index.test.ts extensions/nvidia/onboard.test.ts
- pnpm exec oxfmt --check src/flows/model-picker.ts src/commands/model-picker.test.ts
- pnpm format:docs:check
- pnpm docs:check-mdx
- git diff --check upstream/main...HEAD
- .agents/skills/autoreview/scripts/autoreview --mode branch --base upstream/main --parallel-tests "node scripts/run-vitest.mjs src/commands/model-picker.test.ts extensions/nvidia/provider-catalog.test.ts extensions/nvidia/index.test.ts extensions/nvidia/onboard.test.ts"
2026-06-04 20:13:06 +01:00
Peter Steinberger
8048ceca71 docs: document agent identity tests 2026-06-04 15:10:14 -04:00
Peter Steinberger
a1c6a6e36f docs: document harness lifecycle tests 2026-06-04 15:08:47 -04:00
Peter Steinberger
bc2294b413 docs: document agent harness tests 2026-06-04 15:07:36 -04:00
Shakker
b4e47ae395 docs: document env mutation report 2026-06-04 20:06:24 +01:00
Shakker
51f9082873 test: add env mutation report 2026-06-04 20:06:24 +01:00
Peter Steinberger
85b4bd6c7b docs: document agent policy tests 2026-06-04 15:06:09 -04:00
Vincent Koc
023427b1d5 test(docker): cap npm scheduler concurrency 2026-06-04 12:04:45 -07:00
Peter Steinberger
5864669b3b docs: document embedded subscribe tools 2026-06-04 15:04:14 -04:00
Peter Steinberger
e0fe08ccce docs: document embedded subscribe lifecycle 2026-06-04 15:03:07 -04:00
Peter Steinberger
a5880a3747 docs: document embedded subscribe chunking 2026-06-04 15:02:04 -04:00
Peter Steinberger
60cb5d633f docs: document embedded subscribe text streaming 2026-06-04 15:00:33 -04:00
Peter Steinberger
fc7f96c826 docs: document embedded subscribe reply regressions 2026-06-04 14:59:30 -04:00
Peter Steinberger
6cde30a77c docs: document embedded subscribe handlers 2026-06-04 14:58:34 -04:00
Peter Steinberger
82d4d989d0 docs: document embedded runner helper tests 2026-06-04 14:57:12 -04:00
Peter Steinberger
69df4c9136 docs: document embedded runner registry tests 2026-06-04 14:54:59 -04:00
Peter Steinberger
689bafd16f docs: document embedded payload prompt tests 2026-06-04 14:53:23 -04:00
Peter Steinberger
d91f645d28 docs: document embedded failover image tests 2026-06-04 14:51:49 -04:00
Peter Steinberger
c7c67fc790 docs: document embedded attempt auth tests 2026-06-04 14:49:17 -04:00
Peter Steinberger
9dcf42472b docs: document embedded attempt spawn tests 2026-06-04 14:46:45 -04:00
Peter Steinberger
0f53d0000c docs: document embedded attempt workspace tests 2026-06-04 14:44:56 -04:00
Peter Steinberger
6365951160 docs: document embedded attempt helper tests 2026-06-04 14:43:03 -04:00
Peter Steinberger
838bc724ec docs: document embedded attempt tests 2026-06-04 14:41:17 -04:00
Peter Steinberger
ff39de4806 docs: document embedded runner overflow tests 2026-06-04 14:39:46 -04:00
Shakker
dfde0ce1a6 test: explain skipped changed vitest targets 2026-06-04 19:38:06 +01:00
Shakker
dd8f491040 test: expose changed fallback skip metadata 2026-06-04 19:38:06 +01:00
Peter Steinberger
a31d3355cd docs: document embedded runner run tests 2026-06-04 14:38:00 -04:00
Peter Steinberger
cd26595d6f docs: document embedded runner cache tests 2026-06-04 14:36:52 -04:00
Peter Steinberger
810f29b5f6 docs: document embedded runner model tests 2026-06-04 14:35:43 -04:00
Peter Steinberger
0b6aad58f2 docs: document embedded runner routing tests 2026-06-04 14:33:55 -04:00
Peter Steinberger
e78ef6fbad docs: document embedded runner extra params tests 2026-06-04 14:32:48 -04:00
Peter Steinberger
315cdd42fb docs: document embedded runner compaction tests 2026-06-04 14:31:27 -04:00
Peter Steinberger
85df2e1f85 docs: document embedded runner history tests 2026-06-04 14:29:25 -04:00
Peter Steinberger
94555a5898 docs: document embedded runner guard tests 2026-06-04 14:26:32 -04:00
Peter Steinberger
998adc707f docs: document embedded runner extra params tests 2026-06-04 14:24:17 -04:00
Peter Steinberger
77d0792e02 docs: document embedded helper classifier tests 2026-06-04 14:22:41 -04:00
Peter Steinberger
0241665795 docs: document embedded helper tests 2026-06-04 14:19:48 -04:00
Peter Steinberger
100be0e55a docs: document context lookup tests 2026-06-04 14:18:08 -04:00
Peter Steinberger
31b4575172 docs: document compaction tests 2026-06-04 14:16:34 -04:00
Peter Steinberger
17fc1c430f docs: document command session tests 2026-06-04 14:14:07 -04:00
Peter Steinberger
a767c6d1df docs: document agent command tests 2026-06-04 14:12:48 -04:00
Peter Steinberger
8fb70a90bd docs: document cli runner preparation tests 2026-06-04 14:11:04 -04:00
Peter Steinberger
429bf9fe84 docs: document cli runner bundle mcp tests 2026-06-04 14:07:58 -04:00
Peter Steinberger
a44c5ee3f7 docs: document cli runner tests 2026-06-04 14:06:45 -04:00
Peter Steinberger
bb6c3ce262 docs: document agent cli tests 2026-06-04 14:04:32 -04:00
Peter Steinberger
ddc832ead1 docs: document agent cache auth tests 2026-06-04 14:03:39 -04:00
Peter Steinberger
d216322640 docs: document agent bootstrap tests 2026-06-04 14:02:28 -04:00
Peter Steinberger
2761e8cc3b docs: document daemon systemd helpers 2026-06-04 14:00:34 -04:00
Peter Steinberger
407f4777d2 docs: document daemon service env helpers 2026-06-04 13:58:33 -04:00
Peter Steinberger
a3c44d53d1 docs: document daemon audit helpers 2026-06-04 13:57:21 -04:00
Peter Steinberger
feeaff20ab docs: document daemon runtime helpers 2026-06-04 13:55:33 -04:00
Peter Steinberger
975d40d474 docs: document launchd daemon helpers 2026-06-04 13:54:21 -04:00
Peter Steinberger
0d35da9cc4 docs: document daemon command helpers 2026-06-04 13:51:23 -04:00
Peter Steinberger
d1bf769dbd docs: document cron store helpers 2026-06-04 13:50:06 -04:00
Peter Steinberger
77f09f2575 docs: document cron service state and timer 2026-06-04 13:47:51 -04:00
Peter Steinberger
f51126f0fa docs: document cron service operations 2026-06-04 13:45:55 -04:00
Peter Steinberger
31ce6dfc4c docs: document cron schedule helpers 2026-06-04 13:44:43 -04:00
Peter Steinberger
875c9fd96d docs: document cron normalization and run logs 2026-06-04 13:42:58 -04:00
Peter Steinberger
03a2f6f89d docs: document isolated cron run helpers 2026-06-04 13:41:33 -04:00
Peter Steinberger
93e75f646f docs: document isolated cron delivery helpers 2026-06-04 13:38:54 -04:00
Peter Steinberger
9d2c7bcb66 docs: document cron delivery helpers 2026-06-04 13:37:20 -04:00
Peter Steinberger
a10dfb7185 docs: document crestodian helpers 2026-06-04 13:35:15 -04:00
Peter Steinberger
a0e19507e3 docs: document context engine helpers 2026-06-04 13:33:05 -04:00
Peter Steinberger
c74fd6f015 docs: document session transcript helpers 2026-06-04 13:31:05 -04:00
Peter Steinberger
fbac4a2ec7 docs: document session store facade 2026-06-04 13:29:18 -04:00
Peter Steinberger
3f16b96ddc docs: document session store helpers 2026-06-04 13:27:40 -04:00
Peter Steinberger
0e3f7a82fd docs: document session path helpers 2026-06-04 13:26:14 -04:00
Mason Huang
8b29ff5f16 fix(ci): scope PR merge diff checks to first parent (#90287)
Summary:
- This PR adds opt-in first-parent merge-head diff-base handling for CI changed-scope, changed-lanes, and OpenGrep PR scans, plus synthetic merge coverage and small lint/type cleanups.
- PR surface: Source +6, Tests +204, Config +1, Other +179. Total +390 across 15 files.
- Reproducibility: yes. The synthetic merge tests and PR body live-ref proof show the stale payload-base path can include main-only files, and first-parent mode narrows it to PR-owned paths.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(ci): update workflow guard expectations
- PR branch already contained follow-up commit before automerge: fix(ci): resolve plugin guardrail lint failures
- PR branch already contained follow-up commit before automerge: fix(ci): preserve plugin run context typing
- PR branch already contained follow-up commit before automerge: fix(ci): scope PR merge diff checks to first parent

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

Prepared head SHA: 40235e8c3d
Review: https://github.com/openclaw/openclaw/pull/90287#issuecomment-4621155576

Co-authored-by: Mason Huang <masonxhuang@tencent.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: hxy91819
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
2026-06-04 17:24:03 +00:00
Peter Steinberger
fff04af46d docs: document session metadata helpers 2026-06-04 13:23:36 -04:00
Peter Steinberger
c87c1569d5 docs: document session cleanup helpers 2026-06-04 13:21:00 -04:00
Peter Steinberger
d00d10f172 docs: document command test helpers 2026-06-04 13:18:37 -04:00
Peter Steinberger
8d65e78a07 docs: document task command helpers 2026-06-04 13:17:07 -04:00
Peter Steinberger
726bc2b6c7 docs: document status summary helpers 2026-06-04 13:15:41 -04:00
joshavant
cb4f6af504 fix ios canvas presentation 2026-06-04 10:15:32 -07:00
joshavant
81c8f525eb fix ios gateway forced reconnect 2026-06-04 10:15:32 -07:00
Peter Steinberger
1794efbba1 docs: document status scan core 2026-06-04 13:13:46 -04:00
Peter Steinberger
9b7ad2441f docs: document status scan helpers 2026-06-04 13:12:00 -04:00
Peter Steinberger
976ea3ff50 docs: document status command wiring 2026-06-04 13:10:25 -04:00
Peter Steinberger
f0b3c4164f docs: document status runtime helpers 2026-06-04 13:09:09 -04:00
Peter Steinberger
ea6d3232ca docs: document status overview helpers 2026-06-04 13:07:17 -04:00
Peter Steinberger
abb09b93cb docs: document status json helpers 2026-06-04 13:05:43 -04:00
Peter Steinberger
e11e4e8935 docs: document status report helpers 2026-06-04 13:04:21 -04:00
Peter Steinberger
2939ac6b72 docs: document status channel helpers 2026-06-04 13:02:30 -04:00
Peter Steinberger
ae948fa429 docs: document setup command helpers 2026-06-04 13:00:10 -04:00
Peter Steinberger
d09e0740e5 docs: document session display commands 2026-06-04 12:58:22 -04:00
Peter Steinberger
09467b1b87 docs: document sandbox session utilities 2026-06-04 12:55:08 -04:00
Peter Steinberger
97cdf8e7ac docs: document plugin install utilities 2026-06-04 12:52:51 -04:00
Vincent Koc
7dead6537a test(e2e): keep tui pty smoke off arm gateway runs 2026-06-04 09:50:57 -07:00
Peter Steinberger
d3cabb0fc6 docs: document onboard command surface 2026-06-04 12:50:31 -04:00
Peter Steinberger
c100ae1f36 docs: document noninteractive onboarding entrypoints 2026-06-04 12:48:25 -04:00
Peter Steinberger
3bae50af7f docs: document local onboarding helpers 2026-06-04 12:46:22 -04:00
Peter Steinberger
fe70a2f5a6 docs: document noninteractive auth choice helpers 2026-06-04 12:44:26 -04:00
Peter Steinberger
6c89ef9c3a docs: document noninteractive onboarding helpers 2026-06-04 12:42:33 -04:00
Peter Steinberger
0812b7e3a8 docs: document custom onboarding comments 2026-06-04 12:40:58 -04:00
Peter Steinberger
d4ed8964d3 docs: document onboarding helper comments 2026-06-04 12:37:56 -04:00
Peter Steinberger
12efbcaa7e docs: document daemon oauth command seams 2026-06-04 12:36:05 -04:00
Peter Steinberger
47f0af0d2d docs: document model command comments 2026-06-04 12:33:53 -04:00
Peter Steinberger
9d7f83b175 docs: document model list source comments 2026-06-04 12:32:05 -04:00
Peter Steinberger
73752f07f2 docs: document model list runtime comments 2026-06-04 12:29:16 -04:00
Peter Steinberger
feb6dc6bb6 docs: document model list comments 2026-06-04 12:27:15 -04:00
Peter Steinberger
865bd10bda docs: document model auth fallback comments 2026-06-04 12:25:03 -04:00
Peter Steinberger
945a7fdb36 docs: document migrate picker comments 2026-06-04 12:22:26 -04:00
Peter Steinberger
c6a6f56699 docs: document message migrate helpers 2026-06-04 12:20:26 -04:00
Peter Steinberger
09df56ee1f docs: document gateway status health comments 2026-06-04 12:18:52 -04:00
Peter Steinberger
473f651e09 docs: document gateway helper comments 2026-06-04 12:17:02 -04:00
Peter Steinberger
4912342dd7 docs: document doctor command entrypoints 2026-06-04 12:13:46 -04:00
Peter Steinberger
d4ac91d8f0 docs: document doctor state checks 2026-06-04 12:10:56 -04:00
Peter Steinberger
c0b3c8cdb9 docs: document doctor session checks 2026-06-04 12:08:24 -04:00
Peter Steinberger
0913b6989c docs: document doctor repair policy helpers 2026-06-04 12:06:06 -04:00
Peter Steinberger
9d6e8b872a docs: document doctor plugin checks 2026-06-04 12:04:28 -04:00
Peter Steinberger
f1e6177331 docs: document doctor heartbeat checks 2026-06-04 12:02:48 -04:00
Peter Steinberger
3b914ca40b docs: document doctor gateway checks 2026-06-04 12:01:00 -04:00
Peter Steinberger
688777ca79 docs: document doctor config preflight checks 2026-06-04 11:59:11 -04:00
Peter Steinberger
d2ff1c31d6 docs: document doctor configuration checks 2026-06-04 11:57:47 -04:00
Peter Steinberger
c0e9797644 docs: document doctor auth repair helpers 2026-06-04 11:56:19 -04:00
Peter Steinberger
3e2d56469b docs: document doctor stale warning helpers 2026-06-04 11:53:40 -04:00
Peter Steinberger
3e6978770a docs: document doctor plugin repair helpers 2026-06-04 11:51:25 -04:00
Peter Steinberger
51f7844c43 docs: document legacy web and auth helpers 2026-06-04 11:48:55 -04:00
Peter Steinberger
2016d32187 docs: document legacy migration registry 2026-06-04 11:46:48 -04:00
Peter Steinberger
90f9f2c2e4 docs: document runtime legacy migrations 2026-06-04 11:44:36 -04:00
Peter Steinberger
8dc5b9afcd docs: document legacy config normalizers 2026-06-04 11:43:03 -04:00
Peter Steinberger
4fcc7537ff docs: document doctor legacy repair helpers 2026-06-04 11:41:21 -04:00
Peter Steinberger
7beeedbe73 docs: document doctor warning helpers 2026-06-04 11:39:28 -04:00
Peter Steinberger
6a6da54062 docs: document codex doctor helpers 2026-06-04 11:37:55 -04:00
Peter Steinberger
efda5918b5 docs: document channel doctor helpers 2026-06-04 11:36:22 -04:00
Peter Steinberger
5e8190b779 docs: document doctor allowlist repairs 2026-06-04 11:34:47 -04:00
Peter Steinberger
98df83079d docs: document doctor allowlist warnings 2026-06-04 11:33:51 -04:00
Peter Steinberger
0c4ea11b06 docs: document doctor repair orchestration 2026-06-04 11:32:42 -04:00
Peter Steinberger
695e181179 docs: document doctor cron repair helpers 2026-06-04 11:31:17 -04:00
Peter Steinberger
4eb3d1fae9 docs: document daemon install helpers 2026-06-04 11:27:53 -04:00
Peter Steinberger
118060157d docs: document configure wizard helpers 2026-06-04 11:25:31 -04:00
Peter Steinberger
14962b2825 docs: document cleanup and configure helpers 2026-06-04 11:22:51 -04:00
Peter Steinberger
7385c611fc docs: document channel command helpers 2026-06-04 11:20:59 -04:00
Peter Steinberger
b9aade4b12 refactor: move MS Teams state migration to doctor 2026-06-04 08:20:39 -07:00
Peter Steinberger
3a335c6df1 refactor: remove Feishu runtime dedupe JSON fallback 2026-06-04 08:20:28 -07:00
Peter Steinberger
0a351cdf7f docs: document channel setup commands 2026-06-04 11:18:50 -04:00
Vincent Koc
52b07b4a46 test(ci): stabilize ARM changed-test guards 2026-06-04 08:18:15 -07:00
Jesse Merhi
fa3901e665 fix(message-tool): stabilize send idempotency keys 2026-06-04 20:47:41 +05:30
Peter Steinberger
4c32553875 docs: document backup and channel setup helpers 2026-06-04 11:16:37 -04:00
Peter Steinberger
63dfa848a6 docs: document auth choice command helpers 2026-06-04 11:14:36 -04:00
Peter Steinberger
03490ba1b9 docs: document agent management commands 2026-06-04 11:12:55 -04:00
Vincent Koc
367be94676 test(agents): stabilize compaction worker timing 2026-06-04 08:11:39 -07:00
Peter Steinberger
4af066b013 docs: document update and agent cli helpers 2026-06-04 11:11:07 -04:00
Peter Steinberger
20c4e9475a docs: document cli startup helpers 2026-06-04 11:07:54 -04:00
Peter Steinberger
98187f3277 docs: document cli program helpers 2026-06-04 11:05:42 -04:00
Peter Steinberger
f7e54acec1 docs: document plugin program cli helpers 2026-06-04 11:03:24 -04:00
Peter Steinberger
169a4159de docs: document plugin cli helpers 2026-06-04 11:01:13 -04:00
Peter Steinberger
a94a939626 docs: document cli command runtimes 2026-06-04 10:58:50 -04:00
Peter Steinberger
69c27677f6 docs: document gateway cli helpers 2026-06-04 10:56:59 -04:00
Peter Steinberger
cb5d43ba95 docs: document cli utility helpers 2026-06-04 10:55:01 -04:00
Peter Steinberger
8946648ace docs: document daemon cli helpers 2026-06-04 10:53:30 -04:00
Peter Steinberger
09cee22249 docs: document cli config and cron helpers 2026-06-04 10:52:10 -04:00
Vincent Koc
5522268b24 test(ci): align lint suppression guard 2026-06-04 07:51:28 -07:00
Peter Steinberger
e2a5823c83 docs: document cli startup policy helpers 2026-06-04 10:50:04 -04:00
Peter Steinberger
dd0dd662a1 docs: document cli command helpers 2026-06-04 10:48:30 -04:00
Peter Steinberger
ca9249e357 docs: document channel core helpers 2026-06-04 10:47:00 -04:00
Peter Steinberger
cc73ef8ba5 docs: document channel plugin setup types 2026-06-04 10:42:48 -04:00
Peter Steinberger
67ddda2a21 docs: document channel plugin runtime helpers 2026-06-04 10:39:46 -04:00
Peter Steinberger
15f3903b6f docs: document channel plugin contract helpers 2026-06-04 10:36:02 -04:00
Vincent Koc
ecb30fece4 fix(ci): stabilize include permission checks 2026-06-04 07:35:25 -07:00
Vincent Koc
71bda851d1 test(ui): harden control ui vitest setup 2026-06-04 07:35:02 -07:00
Peter Steinberger
08fd123906 docs: document channel plugin binding helpers 2026-06-04 10:31:28 -04:00
Peter Steinberger
7d3f1963d3 docs: document channel message access helpers 2026-06-04 10:28:38 -04:00
Peter Steinberger
6aed185ccb docs: document channel utility helpers 2026-06-04 10:26:27 -04:00
Peter Steinberger
041fab7b72 docs: document session web tools 2026-06-04 10:22:14 -04:00
Peter Steinberger
1ce11fbf42 docs: document media session tools 2026-06-04 10:17:38 -04:00
Peter Steinberger
2cbaacda43 docs: document built-in tool helpers 2026-06-04 10:14:36 -04:00
Peter Steinberger
bf1634b17a docs: document tool utility helpers 2026-06-04 10:11:57 -04:00
Peter Steinberger
3894fe11ca docs: document subagent registry helpers 2026-06-04 10:08:39 -04:00
Peter Steinberger
589b1f6aec docs: document subagent helpers 2026-06-04 10:05:53 -04:00
Peter Steinberger
600a57e60f docs: document session tools 2026-06-04 10:03:05 -04:00
Peter Steinberger
f84460e625 docs: document session services 2026-06-04 10:01:18 -04:00
Ayaan Zaidi
735587dde0 docs(acp): document parent commentary default 2026-06-04 19:30:46 +05:30
Ayaan Zaidi
8fdfb2d7e3 fix(acp): default parent commentary in progress mode 2026-06-04 19:30:46 +05:30
Peter Steinberger
88f78190ee docs: document sandbox helpers 2026-06-04 09:58:14 -04:00
Peter Steinberger
15361bfe07 docs: document provider tool helpers 2026-06-04 09:55:11 -04:00
Peter Steinberger
e8895f0a99 docs: document model selection helpers 2026-06-04 09:51:42 -04:00
Vincent Koc
8e9a4e99f5 test(gateway): extend vitest idle watchdog 2026-06-04 06:49:43 -07:00
Peter Steinberger
b031913031 docs: document agent runtime helpers 2026-06-04 09:48:36 -04:00
Peter Steinberger
585e89adbe docs: document exec and harness helpers 2026-06-04 09:46:22 -04:00
Peter Steinberger
46b826944c docs: document embedded subscribe helpers 2026-06-04 09:43:42 -04:00
Peter Steinberger
33bda2629a docs: document runner root helpers 2026-06-04 09:41:21 -04:00
Peter Steinberger
e95e51a24f docs: document runner message helpers 2026-06-04 09:38:52 -04:00
Peter Steinberger
fa6be505ef docs: document runner failover helpers 2026-06-04 09:36:19 -04:00
Peter Steinberger
20577f0b3b docs: document runner attempt runtime helpers 2026-06-04 09:34:34 -04:00
Peter Steinberger
f5ccfb7319 docs: document runner attempt helpers 2026-06-04 09:32:25 -04:00
Peter Steinberger
6719528316 docs: document runner model helpers 2026-06-04 09:30:31 -04:00
Peter Steinberger
dea0be4f11 docs: document runner utility helpers 2026-06-04 09:28:31 -04:00
Ayaan Zaidi
e59a7680e6 test(acp): keep streaming off regression typed (#89505) (thanks @100yenadmin) 2026-06-04 18:55:55 +05:30
Ayaan Zaidi
448e67bd8b fix(config): accept shared progress commentary (#89505) (thanks @100yenadmin) 2026-06-04 18:55:55 +05:30
Ayaan Zaidi
1f4b08ad2a fix(acp): preserve parent streaming off overrides (#89505) (thanks @100yenadmin) 2026-06-04 18:55:55 +05:30
Ayaan Zaidi
afb8d80ce7 fix(acp): satisfy relay lint checks (#89505) (thanks @100yenadmin) 2026-06-04 18:55:55 +05:30
Ayaan Zaidi
bd065c1154 fix(acp): harden parent commentary progress (#89505) (thanks @100yenadmin) 2026-06-04 18:55:55 +05:30
Ayaan Zaidi
4c9b724987 fix(acp): relay codex parent commentary 2026-06-04 18:55:55 +05:30
Ayaan Zaidi
2bf886b7dd fix(acp): reuse progress commentary config 2026-06-04 18:55:55 +05:30
Eva
9ac94568f3 fix(acp): honor tag visibility for status progress 2026-06-04 18:55:55 +05:30
Eva
ca0789ee8f fix(acp): type status progress relay metadata 2026-06-04 18:55:55 +05:30
Eva
0d44d970a9 Handle ACP status progress commentary 2026-06-04 18:55:55 +05:30
Eva
0c272958cf Add opt-in ACP commentary relay 2026-06-04 18:55:55 +05:30
Peter Steinberger
d07cce7bd1 docs: document runner compaction helpers 2026-06-04 09:25:41 -04:00
Peter Steinberger
dbfe5a252c docs: document embedded agent helpers 2026-06-04 09:22:40 -04:00
Peter Steinberger
550f707565 docs: document agent config helpers 2026-06-04 09:19:21 -04:00
Peter Steinberger
2173d1bf47 docs: document compaction planning helpers 2026-06-04 09:17:00 -04:00
Peter Steinberger
e12776037f docs: document agent command helpers 2026-06-04 09:15:00 -04:00
Peter Steinberger
a4550c5769 docs: document agent attempt helpers 2026-06-04 09:12:59 -04:00
Peter Steinberger
e996956c29 docs: document codex search helpers 2026-06-04 09:11:36 -04:00
Peter Steinberger
31a1034cb5 docs: document code mode helpers 2026-06-04 09:10:13 -04:00
Peter Steinberger
087fcf4085 docs: document cli runner history helpers 2026-06-04 09:08:46 -04:00
Peter Steinberger
1d7d8a1658 docs: document cli runner execution helpers 2026-06-04 09:06:53 -04:00
Peter Steinberger
f178c31305 docs: document cli runner shared helpers 2026-06-04 09:05:29 -04:00
Peter Steinberger
e6ec78ede4 docs: document cli runner mcp helpers 2026-06-04 09:04:02 -04:00
Peter Steinberger
34f7d78449 docs: document cli agent helpers 2026-06-04 09:02:44 -04:00
Peter Steinberger
258373717a docs: document chutes oauth helpers 2026-06-04 09:01:15 -04:00
Vincent Koc
383d214c7c test(plugin-sdk): restore testing facade guard 2026-06-04 15:00:21 +02:00
Vincent Koc
59777971d2 fix(plugins): remove stale run context generic 2026-06-04 15:00:21 +02:00
Vincent Koc
f187bec815 fix(cli): skip plugin loader cache clear on short-lived commands 2026-06-04 15:00:21 +02:00
Peter Steinberger
0dea7eab37 docs: document agent cache helpers 2026-06-04 09:00:00 -04:00
Peter Steinberger
b53c6eae62 docs: document bundle mcp helpers 2026-06-04 08:59:21 -04:00
Peter Steinberger
67ff2f8c95 docs: document btw side-question helpers 2026-06-04 08:58:19 -04:00
Peter Steinberger
1e1a966651 docs: document agent bootstrap helpers 2026-06-04 08:57:18 -04:00
Peter Steinberger
9b9d4883c3 docs: document codex command helpers 2026-06-04 08:55:39 -04:00
Peter Steinberger
796ed1b501 docs: document codex approval roundtrip 2026-06-04 08:53:19 -04:00
Peter Steinberger
ff867fcb7f docs: document codex protocol validators 2026-06-04 08:51:38 -04:00
Peter Steinberger
e72447de40 docs: document codex app-server support helpers 2026-06-04 08:50:13 -04:00
Peter Steinberger
bd94eda53a docs: document codex trajectory progress helpers 2026-06-04 08:48:00 -04:00
Peter Steinberger
d99268ae51 docs: document codex plugin app config 2026-06-04 08:46:41 -04:00
Peter Steinberger
22efdfa904 docs: document codex app-server runtime utilities 2026-06-04 08:45:03 -04:00
Peter Steinberger
b91ed087c8 docs: document codex app-server small utilities 2026-06-04 08:42:50 -04:00
Peter Steinberger
e4a775567c docs: document codex sandbox process bridge 2026-06-04 08:41:11 -04:00
Peter Steinberger
e1c7f228d6 docs: document codex sandbox fs policy 2026-06-04 08:40:26 -04:00
Peter Steinberger
226f5ac17f docs: document codex sandbox exec server 2026-06-04 08:39:30 -04:00
Peter Steinberger
29e9625b18 docs: document codex sandbox exec fs http 2026-06-04 08:37:41 -04:00
Peter Steinberger
b1c47dabd9 docs: document codex sandbox exec protocol 2026-06-04 08:36:28 -04:00
Peter Steinberger
2ff83d3023 docs: document codex app-server utilities 2026-06-04 08:35:15 -04:00
Peter Steinberger
121ee3f555 docs: document codex native subagent helpers 2026-06-04 08:33:42 -04:00
Peter Steinberger
7a2aa68960 docs: document codex app-server helpers 2026-06-04 08:32:30 -04:00
Peter Steinberger
c67491cbaf docs: document codex dynamic tool build 2026-06-04 08:31:20 -04:00
Peter Steinberger
7139f47333 docs: document codex dynamic tool bridge 2026-06-04 08:29:21 -04:00
Peter Steinberger
381a51b2d4 docs: document codex compaction projection 2026-06-04 08:27:05 -04:00
Peter Steinberger
0dc1d6a989 docs: document codex app-server client helpers 2026-06-04 08:25:40 -04:00
Peter Steinberger
0b5298d24e docs: document codex attempt context 2026-06-04 08:22:45 -04:00
Peter Steinberger
d249e25a64 docs: document codex attempt lifecycle helpers 2026-06-04 08:21:04 -04:00
Peter Steinberger
0050f6b165 docs: document codex notification helpers 2026-06-04 08:19:31 -04:00
Peter Steinberger
23258c86be docs: document codex app-server cleanup modules 2026-06-04 08:18:04 -04:00
Peter Steinberger
f60943717e docs: document codex root plugin modules 2026-06-04 08:16:35 -04:00
Peter Steinberger
8b477d2887 docs: document cloudflare and codex supervisor plugins 2026-06-04 08:14:22 -04:00
Peter Steinberger
802cdc7783 docs: document clickclack plugin 2026-06-04 08:12:22 -04:00
Peter Steinberger
a4a27517ff docs: document cerebras and chutes providers 2026-06-04 08:09:34 -04:00
Peter Steinberger
4726aaa08c docs: document canvas plugin 2026-06-04 08:07:38 -04:00
Peter Steinberger
18ecb82034 docs: document byteplus provider 2026-06-04 08:03:04 -04:00
Peter Steinberger
e900428a47 docs: document repo support scripts 2026-06-04 08:01:15 -04:00
Peter Steinberger
f07ee23d23 docs: document browser root modules 2026-06-04 08:00:12 -04:00
Peter Steinberger
f750029c72 docs: document browser support modules 2026-06-04 07:58:03 -04:00
Peter Steinberger
0d7f8051d0 docs: document browser cli modules 2026-06-04 07:56:15 -04:00
Peter Steinberger
5ab430fa11 docs: document browser server context 2026-06-04 07:53:45 -04:00
Peter Steinberger
29ddb9d926 docs: document browser utility helpers 2026-06-04 07:50:05 -04:00
Peter Steinberger
383531da96 docs: document browser playwright tools 2026-06-04 07:47:51 -04:00
Peter Steinberger
44ceccd2be docs: document browser playwright session 2026-06-04 07:45:58 -04:00
Peter Steinberger
3720ecaf52 docs: document browser config paths 2026-06-04 07:42:57 -04:00
Peter Steinberger
e8e57f9395 docs: document browser config support 2026-06-04 07:40:44 -04:00
Peter Steinberger
3dcdfee1e1 docs: document browser client APIs 2026-06-04 07:37:59 -04:00
Peter Steinberger
b24979cc30 docs: document browser chrome helpers 2026-06-04 07:36:15 -04:00
Peter Steinberger
c32748bc28 docs: document browser cdp runtime 2026-06-04 07:34:30 -04:00
Peter Steinberger
a3af426353 docs: document browser route support 2026-06-04 07:31:50 -04:00
Peter Steinberger
7fe6c16f03 docs: document browser route handlers 2026-06-04 07:29:19 -04:00
Peter Steinberger
ce56fc176a docs: document browser act routes 2026-06-04 07:27:43 -04:00
Peter Steinberger
5dcb072f7f docs: document browser cdp policies 2026-06-04 07:26:23 -04:00
Peter Steinberger
a982f798ca docs: document browser tool runtime 2026-06-04 07:24:31 -04:00
Peter Steinberger
83e4cfba30 docs: document browser plugin entrypoints 2026-06-04 07:22:35 -04:00
Peter Steinberger
2ad6314d72 docs: document small provider plugins 2026-06-04 07:20:32 -04:00
Peter Steinberger
caf930e65e docs: document anthropic runtime provider 2026-06-04 07:17:20 -04:00
Peter Steinberger
d89ad16124 docs: document anthropic cli config helpers 2026-06-04 07:15:05 -04:00
Peter Steinberger
c46610472f docs: document anthropic vertex plugin 2026-06-04 07:13:17 -04:00
Peter Steinberger
8cfc09238f docs: document bedrock provider plugins 2026-06-04 07:11:24 -04:00
Peter Steinberger
8c02521c47 docs: document active memory admin alibaba plugins 2026-06-04 07:07:49 -04:00
Peter Steinberger
bac84c5858 docs: document acpx runtime internals 2026-06-04 07:06:08 -04:00
Peter Steinberger
198d0b36a2 docs: document acpx process runtime helpers 2026-06-04 07:04:59 -04:00
Peter Steinberger
33c284ca0d docs: document acpx entry contracts 2026-06-04 07:03:35 -04:00
Peter Steinberger
1cbbfe8ed2 docs: document workspace policy helpers 2026-06-04 07:02:08 -04:00
Peter Steinberger
7ef836812b docs: document runtime plan contracts 2026-06-04 06:59:48 -04:00
Peter Steinberger
6ca104d129 docs: document runtime config helpers 2026-06-04 06:57:27 -04:00
Peter Steinberger
1a8263c2f5 docs: document auth redaction helpers 2026-06-04 06:55:31 -04:00
Peter Steinberger
18ed27bf5f docs: document provider planning helpers 2026-06-04 06:53:58 -04:00
Peter Steinberger
8edd7e84ad docs: document session output helpers 2026-06-04 06:52:02 -04:00
Peter Steinberger
7fb74310f0 docs: document agent policy helpers 2026-06-04 06:50:26 -04:00
Peter Steinberger
eb48b6bd06 docs: document agent utility contracts 2026-06-04 06:48:45 -04:00
Peter Steinberger
511f114138 docs: document models config runtime 2026-06-04 06:47:40 -04:00
Peter Steinberger
7913b6cd27 docs: document agent control helpers 2026-06-04 06:46:16 -04:00
Peter Steinberger
f3a2488ab0 docs: document agent test helpers 2026-06-04 06:44:16 -04:00
Peter Steinberger
f5f046a736 docs: document provider auth helpers 2026-06-04 06:42:49 -04:00
Peter Steinberger
e533ff4c4a docs: document runtime helper contracts 2026-06-04 06:40:26 -04:00
Peter Steinberger
fbf3e009d4 docs: document failover utility helpers 2026-06-04 06:37:21 -04:00
Peter Steinberger
21031c2243 docs: document model policy helpers 2026-06-04 06:34:39 -04:00
Peter Steinberger
5181a93391 docs: document agent utility helpers 2026-06-04 06:32:31 -04:00
Peter Steinberger
a8f6e7601b docs: document live model helpers 2026-06-04 06:30:11 -04:00
Peter Steinberger
76f2a12ad7 docs: document auth marker helpers 2026-06-04 06:28:22 -04:00
Peter Steinberger
88eb405491 docs: document tool utility helpers 2026-06-04 06:26:19 -04:00
Peter Steinberger
36ae3dd235 docs: document transcript policy helpers 2026-06-04 06:24:59 -04:00
Peter Steinberger
53d08d4aef docs: document agent helper contracts 2026-06-04 06:23:32 -04:00
Peter Steinberger
d2d2dfd9f2 docs: document process tool controls 2026-06-04 06:21:15 -04:00
Peter Steinberger
ac7ef5b8c6 style: restore exec approval e2e formatting 2026-06-04 06:18:55 -04:00
Peter Steinberger
bc88f735cd style: restore exec approval e2e formatting 2026-06-04 06:17:53 -04:00
Peter Steinberger
2feb81249f docs: document exec tool entry 2026-06-04 06:16:34 -04:00
Peter Steinberger
045145c700 docs: document exec runtime 2026-06-04 06:13:45 -04:00
Peter Steinberger
ec6cf6a2ac docs: document node exec host 2026-06-04 06:12:10 -04:00
Peter Steinberger
6537080674 docs: document gateway exec host 2026-06-04 06:09:49 -04:00
Peter Steinberger
8cd4d74d94 docs: document exec approval requests 2026-06-04 06:08:28 -04:00
Peter Steinberger
e5f3bf99cc docs: document exec approval followups 2026-06-04 06:07:16 -04:00
Peter Steinberger
11eb9ac1b9 docs: document bash tool helpers 2026-06-04 06:06:03 -04:00
Peter Steinberger
41cefdff8f docs: document bash process registry 2026-06-04 06:04:28 -04:00
Peter Steinberger
7b8da19302 docs: document auth profile usage 2026-06-04 06:03:18 -04:00
Peter Steinberger
db7a228e6c docs: document auth profile state store 2026-06-04 06:01:47 -04:00
Peter Steinberger
f9613ff01e docs: document auth profile persistence 2026-06-04 05:59:18 -04:00
Ayaan Zaidi
9ed9af4f39 fix(agents): restore Anthropic system cache boundary 2026-06-04 15:27:23 +05:30
Ayaan Zaidi
01cc68ee0d fix(agents): bound Anthropic cache markers 2026-06-04 15:27:23 +05:30
Ayaan Zaidi
2454952544 fix(agents): keep Anthropic tool cache breakpoint advancing 2026-06-04 15:27:23 +05:30
Ayaan Zaidi
77c383d1e0 refactor(agents): distill Anthropic cache marker cleanup 2026-06-04 15:27:23 +05:30
Peter Lindsey
ca9ab97427 fix: stabilize Anthropic cache marker through tool loops 2026-06-04 15:27:23 +05:30
Peter Steinberger
e1da5a36d4 docs: document oauth profile resolution 2026-06-04 05:57:01 -04:00
Peter Steinberger
d581d9d733 docs: document oauth refresh manager 2026-06-04 05:54:47 -04:00
Peter Steinberger
9d20ad261a docs: document oauth identity helpers 2026-06-04 05:52:57 -04:00
Peter Steinberger
81516ca1a4 docs: document external auth overlays 2026-06-04 05:51:25 -04:00
Peter Steinberger
474d6e520a docs: document auth health helpers 2026-06-04 05:49:50 -04:00
Vincent Koc
2cba10a49f test(infra): remove empty skipped builtin placeholder 2026-06-04 11:48:40 +02:00
Peter Steinberger
f7ef52e66d docs: document apply patch helpers 2026-06-04 05:47:45 -04:00
Peter Steinberger
479df18caf docs: document anthropic agent transports 2026-06-04 05:46:46 -04:00
Peter Steinberger
523537a627 docs: document agent tool assembly 2026-06-04 05:45:05 -04:00
Peter Steinberger
c25800ccc1 docs: document agent tool guards 2026-06-04 05:43:42 -04:00
Peter Steinberger
60e0d2a7b9 docs: document agent tool adapters 2026-06-04 05:41:50 -04:00
Peter Steinberger
634174f050 docs: document agent model settings 2026-06-04 05:38:58 -04:00
Peter Steinberger
6c113837b8 docs: document agent command hooks 2026-06-04 05:36:39 -04:00
Peter Steinberger
f2d8facb48 docs: document agent bundle runtimes 2026-06-04 05:34:48 -04:00
Peter Steinberger
b851ba2f98 docs: document agents acp auth helpers 2026-06-04 05:32:57 -04:00
Peter Steinberger
e112fb939a docs: document acp translator bridge 2026-06-04 05:31:15 -04:00
Peter Steinberger
61fdc7bf34 docs: document acp runtime bridge 2026-06-04 05:29:10 -04:00
Peter Steinberger
fc64494b03 docs: document acp events and bindings 2026-06-04 05:27:58 -04:00
Peter Steinberger
05289f1aa0 docs: document acp turn control plane 2026-06-04 05:26:08 -04:00
Peter Steinberger
d88b06cb75 docs: document acp runtime handles 2026-06-04 05:24:49 -04:00
Peter Steinberger
c782e8e44f docs: document acp control plane failover 2026-06-04 05:23:42 -04:00
Peter Steinberger
5a350aeaf5 docs: document acp client helpers 2026-06-04 05:22:29 -04:00
Peter Steinberger
053fbf0209 docs: document web fetch runtime 2026-06-04 05:21:16 -04:00
Peter Steinberger
3c1e9984e0 docs: document secrets surface helpers 2026-06-04 05:20:16 -04:00
Peter Steinberger
bea35d0902 docs: document secrets resolution helpers 2026-06-04 05:17:28 -04:00
Peter Steinberger
d28ac4dbdb docs: document secrets target registry 2026-06-04 05:13:24 -04:00
Peter Steinberger
a720a1f9de docs: document secrets runtime state 2026-06-04 05:09:51 -04:00
Peter Steinberger
5a869eea5a docs: document node host runtime 2026-06-04 05:06:54 -04:00
Peter Steinberger
0135a0a780 docs: document image generation runtime 2026-06-04 05:00:21 -04:00
Peter Steinberger
f4d2748ca5 docs: document plugin metadata utilities 2026-06-04 04:57:48 -04:00
Vincent Koc
72bb5cd692 fix(e2e): bound release journey output assertions 2026-06-04 10:55:37 +02:00
Peter Steinberger
7c1deea5fa docs: document plugin setup state 2026-06-04 04:54:37 -04:00
Peter Steinberger
f875b519e5 docs: document plugin host contracts 2026-06-04 04:51:24 -04:00
Peter Steinberger
040ebadfc5 docs: document plugin runtime contracts 2026-06-04 04:48:42 -04:00
Peter Steinberger
f91fab8b18 docs: document plugin manifest helpers 2026-06-04 04:46:27 -04:00
Peter Steinberger
a77f20a6d6 docs: document plugin registry helpers 2026-06-04 04:44:12 -04:00
Peter Steinberger
4d54d196c9 docs: document plugin discovery helpers 2026-06-04 04:41:47 -04:00
Peter Steinberger
fffd72f36d docs: document plugin compatibility helpers 2026-06-04 04:38:31 -04:00
Peter Steinberger
21572415c8 docs: document plugin lifecycle helpers 2026-06-04 04:36:44 -04:00
Peter Steinberger
f6049db20f docs: document plugin discovery helpers 2026-06-04 04:34:19 -04:00
Vincent Koc
d77d231507 fix(e2e): ignore stale agent output markers 2026-06-04 10:32:31 +02:00
Peter Steinberger
6de517cbcb docs: document plugin registry helpers 2026-06-04 04:31:52 -04:00
Peter Steinberger
507e237d8c docs: document plugin command helpers 2026-06-04 04:29:53 -04:00
Peter Steinberger
6082f01b97 docs: document plugin loader helpers 2026-06-04 04:27:23 -04:00
Peter Steinberger
d33664aef0 docs: document plugin provider helpers 2026-06-04 04:25:18 -04:00
Peter Steinberger
8975f75c8b docs: document plugin public surface helpers 2026-06-04 04:22:45 -04:00
Peter Steinberger
463e9f2704 docs: document plugin install metadata helpers 2026-06-04 04:21:07 -04:00
Vincent Koc
10b9df6d8a fix(release): bound cross-os agent log fallback reads 2026-06-04 10:19:21 +02:00
Peter Steinberger
ee282c6de5 docs: document plugin auth helpers 2026-06-04 04:19:03 -04:00
Peter Steinberger
6d6aba2be5 docs: document plugin runtime helpers 2026-06-04 04:17:40 -04:00
Peter Steinberger
a6d084113a docs: document plugin install helpers 2026-06-04 04:15:33 -04:00
Peter Steinberger
6a2b1b2198 docs: document plugin metadata helpers 2026-06-04 04:14:06 -04:00
Peter Steinberger
e8e6c684bb docs: document tui and plugin helpers 2026-06-04 04:12:38 -04:00
Peter Steinberger
4ed2fb75f2 docs: document tui runtime helpers 2026-06-04 04:10:14 -04:00
Peter Steinberger
bced79b63d docs: document security policy helpers 2026-06-04 04:08:10 -04:00
Mrunal Patel
d522e02fe4 fix(docker): qualify base image refs for podman short-name mode (#90058)
* fix(docker): qualify base image refs for podman short-name mode

Podman with short-name-mode=enforcing (the Fedora/RHEL default) blocked
the build: `FROM oven/bun:1.3.13...` is an ambiguous short name with no
alias, so Podman prompted interactively for a registry (the apparent
"hang") or, headless, failed with "short-name resolution enforced but
cannot prompt without a TTY". `node:*` only resolved because a `node`
short-name alias ships in registries.conf.d.

Fully-qualify the node and bun base images with docker.io/ so registry
resolution is deterministic. Pinned digests are unchanged, so resolved
image content is identical, and Docker/Buildx builds are unaffected.

Also qualify the docker.io/ prefix in the digest-refresh maintenance
comments so the documented update path matches the defaults and does not
reintroduce the same short-name ambiguity for Podman users.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(docker): expect qualified base image refs

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: sallyom <somalley@redhat.com>
2026-06-04 04:06:20 -04:00
Peter Steinberger
961759c08b docs: document security finding helpers 2026-06-04 04:06:08 -04:00
Peter Steinberger
0e8c5fd85d docs: document security audit helpers 2026-06-04 04:04:43 -04:00
Peter Steinberger
8408c16da4 docs: document config diagnostics helpers 2026-06-04 04:03:16 -04:00
Peter Steinberger
40c8ed0dff docs: document config provider helpers 2026-06-04 04:01:24 -04:00
Peter Steinberger
838644b989 docs: document config policy helpers 2026-06-04 04:00:03 -04:00
Peter Steinberger
0796e992e4 docs: document config schema runtime helpers 2026-06-04 03:58:47 -04:00
mushuiyu_xydt
1f1ce8a1fe fix(feishu): preserve streaming card content (#90181)
* fix(feishu): preserve streaming card content

* fix(feishu): preserve streaming card content (#90181) (thanks @mushuiyu886)

---------

Co-authored-by: sliverp <870080352@qq.com>
2026-06-04 15:57:37 +08:00
Peter Steinberger
9572267f64 docs: document config recovery helpers 2026-06-04 03:57:07 -04:00
Peter Steinberger
edc6042c65 docs: document config validation helpers 2026-06-04 03:55:53 -04:00
Peter Steinberger
186e966483 docs: document config agent helpers 2026-06-04 03:54:37 -04:00
Peter Steinberger
51474b6f15 docs: document config mutation helpers 2026-06-04 03:52:12 -04:00
Peter Steinberger
54fe5dc842 docs: document config runtime helpers 2026-06-04 03:51:01 -04:00
Peter Steinberger
6989d6283a docs: document config io helpers 2026-06-04 03:49:54 -04:00
Peter Steinberger
43190f5248 docs: document config schema helpers 2026-06-04 03:47:57 -04:00
Peter Steinberger
6f358fd8e0 docs: document config and commitments helpers 2026-06-04 03:46:55 -04:00
Peter Steinberger
bff849b874 docs: document tool and model helpers 2026-06-04 03:45:53 -04:00
Peter Steinberger
606e3d7866 docs: document task execution helpers 2026-06-04 03:44:45 -04:00
Peter Steinberger
cca24cc78b docs: document task registry helpers 2026-06-04 03:43:46 -04:00
Peter Steinberger
4930766711 docs: document infra flow helpers 2026-06-04 03:42:18 -04:00
Peter Steinberger
2e8b444da8 docs: document infra storage helpers 2026-06-04 03:40:45 -04:00
Peter Steinberger
d13a431860 docs: document infra install runtime helpers 2026-06-04 03:37:48 -04:00
Peter Steinberger
117aca7f4e docs: document infra approval runtime helpers 2026-06-04 03:34:47 -04:00
Peter Steinberger
ec3aa5def4 docs: document infra transport helpers 2026-06-04 03:32:06 -04:00
Peter Steinberger
73b6de1011 docs: document infra socket helpers 2026-06-04 03:29:58 -04:00
Peter Steinberger
5780aa1cd6 docs: document infra heartbeat helpers 2026-06-04 03:27:16 -04:00
Peter Steinberger
cfe31ca3b2 docs: document infra policy helpers 2026-06-04 03:24:36 -04:00
Peter Steinberger
25eb63885d docs: document infra event helpers 2026-06-04 03:22:42 -04:00
Peter Steinberger
79dc565825 docs: document infra database helpers 2026-06-04 03:20:32 -04:00
Peter Steinberger
5dcb2ab40e docs: document infra push helpers 2026-06-04 03:17:57 -04:00
Peter Steinberger
d3b38311b0 docs: document infra approval helpers 2026-06-04 03:16:06 -04:00
Peter Steinberger
59fca2d738 docs: document infra runtime helpers 2026-06-04 03:14:19 -04:00
Peter Steinberger
1275368151 docs: document infra install helpers 2026-06-04 03:12:47 -04:00
Peter Steinberger
a881181fd8 docs: document infra update helpers 2026-06-04 03:11:12 -04:00
Peter Steinberger
f542e23a2f docs: document infra pairing helpers 2026-06-04 03:09:43 -04:00
Pavan Kumar Gondhi
3c6259ebb7 fix: guard mcp http redirects (#89732) 2026-06-04 12:38:25 +05:30
Peter Steinberger
6851dc9505 docs: document infra config helpers 2026-06-04 03:08:12 -04:00
Vincent Koc
cce1a14795 fix(e2e): bound parallels package progress extraction 2026-06-04 09:06:35 +02:00
Peter Steinberger
2f814c6c92 docs: document infra execution helpers 2026-06-04 03:06:18 -04:00
Peter Steinberger
dc3f2bd1d9 docs: document infra process helpers 2026-06-04 03:03:13 -04:00
Peter Steinberger
d819ef3e32 docs: document infra status helpers 2026-06-04 03:00:57 -04:00
Peter Steinberger
334a1dd716 docs: document infra package helpers 2026-06-04 02:58:15 -04:00
Vincent Koc
5c08fb225a fix(e2e): stream docker stats resource scans 2026-06-04 08:57:47 +02:00
Peter Steinberger
0d109750ae docs: document infra runtime helpers 2026-06-04 02:55:39 -04:00
Peter Steinberger
a9a386dee1 docs: document test utils and infra helpers 2026-06-04 02:53:43 -04:00
Peter Steinberger
4295329ec3 docs: document test utility helpers 2026-06-04 02:51:28 -04:00
Peter Steinberger
b4f16c7bcb docs: document pairing and transcript helpers 2026-06-04 02:49:38 -04:00
Vincent Koc
e17bfc4938 fix(e2e): tighten kitchen sink plugin log allowlist 2026-06-04 08:48:58 +02:00
Peter Steinberger
2db057423b docs: document root and music generation helpers 2026-06-04 02:47:44 -04:00
Peter Steinberger
c1aa424d6b docs: document src root entry helpers 2026-06-04 02:45:34 -04:00
Peter Steinberger
b18a05ae3e docs: document auto reply queue and acp helpers 2026-06-04 02:43:05 -04:00
Peter Steinberger
29f057b242 docs: document auto reply admission helpers 2026-06-04 02:41:04 -04:00
Peter Steinberger
119bb57627 docs: document auto reply command gates 2026-06-04 02:39:12 -04:00
Vincent Koc
21c3d6993b fix(e2e): tighten kitchen sink error log allowlist 2026-06-04 08:37:59 +02:00
Peter Steinberger
e71e585969 docs: document auto reply fast path helpers 2026-06-04 02:37:27 -04:00
Peter Steinberger
ea6d3a35ff docs: document auto reply dispatch helpers 2026-06-04 02:35:34 -04:00
Peter Steinberger
26355cc35d docs: document auto reply delivery runtime 2026-06-04 02:33:09 -04:00
Peter Steinberger
25e9097af0 docs: document auto reply session routing 2026-06-04 02:31:18 -04:00
Vincent Koc
d0f05d98d2 fix(e2e): share gateway websocket request handling 2026-06-04 08:29:33 +02:00
Peter Steinberger
88b27c378d docs: document auto reply directive helpers 2026-06-04 02:29:18 -04:00
Peter Steinberger
a66462b583 docs: document auto reply runner support 2026-06-04 02:28:00 -04:00
Peter Steinberger
e61fb145fc docs: document auto reply runtime helpers 2026-06-04 02:26:38 -04:00
Peter Steinberger
afeab32780 docs: document auto reply routing helpers 2026-06-04 02:25:21 -04:00
Peter Steinberger
4e5752631c docs: document auto reply behavior tests 2026-06-04 02:23:56 -04:00
Peter Steinberger
08b1b06aab docs: document auto reply reply tests 2026-06-04 02:21:46 -04:00
Peter Steinberger
0289b046da docs: document auto reply command tests 2026-06-04 02:18:51 -04:00
Peter Steinberger
1053a76dd8 docs: document auto reply top-level tests 2026-06-04 02:16:34 -04:00
Peter Steinberger
82e5dd4da7 docs: document auto reply runner internals 2026-06-04 02:13:57 -04:00
Peter Steinberger
a70e618b20 docs: document auto reply routing helpers 2026-06-04 02:11:29 -04:00
Peter Steinberger
20d7c7ae02 docs: document auto reply run helpers 2026-06-04 02:09:32 -04:00
Peter Steinberger
1c0fb5768b docs: document auto reply command helpers 2026-06-04 02:06:38 -04:00
Peter Steinberger
25c0699fe9 docs: document auto reply delivery helpers 2026-06-04 02:04:44 -04:00
Vincent Koc
ce0d5117bf fix(e2e): fail codex app server log errors 2026-06-04 08:03:24 +02:00
Peter Steinberger
826cdd884c docs: document auto reply command contracts 2026-06-04 02:01:00 -04:00
Peter Steinberger
4503560084 docs: document auto reply top-level helpers 2026-06-04 01:58:27 -04:00
Peter Steinberger
bf1056c554 docs: document gateway helper contracts 2026-06-04 01:54:01 -04:00
Peter Steinberger
344417c0de docs: document media and sdk package facades 2026-06-04 01:51:12 -04:00
Peter Steinberger
86150a3e51 docs: document shared test helpers 2026-06-04 01:48:32 -04:00
Peter Steinberger
d8b5e22e8b docs: document voice call runtime surfaces 2026-06-04 01:45:11 -04:00
Peter Steinberger
5dd026f3f7 docs: document voice call manager helpers 2026-06-04 01:42:32 -04:00
Peter Steinberger
ae5376a599 docs: document voice call helper APIs 2026-06-04 01:41:07 -04:00
Vincent Koc
cc122956df fix(qa): bound malformed otlp receiver requests 2026-06-04 07:39:30 +02:00
Peter Steinberger
eaf803b223 docs: document shared package contracts 2026-06-04 01:39:12 -04:00
Peter Steinberger
d14fe163b5 docs: document terminal core helpers 2026-06-04 01:36:23 -04:00
Peter Steinberger
5b98f03c64 docs: document memory host runtime helpers 2026-06-04 01:34:57 -04:00
Peter Steinberger
eecec7495f docs: document memory remote helpers 2026-06-04 01:32:51 -04:00
Peter Steinberger
c40dd6ff5c docs: document memory batch helpers 2026-06-04 01:31:52 -04:00
Peter Steinberger
8b6bed9c9c docs: document memory host sdk helpers 2026-06-04 01:30:42 -04:00
Peter Steinberger
5a10f46c56 docs: document sdk package facades 2026-06-04 01:26:12 -04:00
Peter Steinberger
bdfeece562 docs: document agent core package 2026-06-04 01:23:43 -04:00
Peter Steinberger
aafdf67d39 docs: document speech core facades 2026-06-04 01:22:31 -04:00
Peter Steinberger
55bde6750f docs: document embedded agent barrels 2026-06-04 01:21:09 -04:00
Peter Steinberger
546f44f395 docs: document ssh sandbox helpers 2026-06-04 01:20:33 -04:00
Peter Steinberger
9877f31fdd docs: document code mode bridge 2026-06-04 01:19:45 -04:00
Peter Steinberger
9bc7712c40 docs: document model selection reconciliation 2026-06-04 01:18:43 -04:00
Peter Steinberger
ba445e0e3f docs: document tool search surfaces 2026-06-04 01:17:16 -04:00
Peter Steinberger
f1ec2605b7 docs: document subscribe helper seams 2026-06-04 01:16:17 -04:00
Peter Steinberger
81f359ec5b docs: document transcript state harness 2026-06-04 01:15:25 -04:00
Peter Steinberger
d8a67ef39a docs: document sandbox backend bridges 2026-06-04 01:14:14 -04:00
Peter Steinberger
cf36b9456d docs: document subagent display seams 2026-06-04 01:12:08 -04:00
Peter Steinberger
376bf65d8e docs: document session list web search tools 2026-06-04 01:10:37 -04:00
Peter Steinberger
b7b069c4d6 docs: document Claude CLI runner helpers 2026-06-04 01:08:59 -04:00
Peter Steinberger
340fca0a45 docs: document embedded compaction helpers 2026-06-04 01:07:28 -04:00
Peter Steinberger
c768a9e6ca docs: document e2e helper mocks 2026-06-04 01:05:37 -04:00
Peter Steinberger
ce1ef04efe docs: document schema media planning helpers 2026-06-04 01:04:21 -04:00
Peter Steinberger
79f6c5a8ad docs: document media generation actions 2026-06-04 01:02:54 -04:00
Peter Steinberger
3a5baf1229 docs: document embedded attempt helpers 2026-06-04 01:01:38 -04:00
Peter Steinberger
fe52654d2e docs: document agent test helpers 2026-06-04 01:00:05 -04:00
Peter Steinberger
45144ce2e8 docs: document model helper normalization 2026-06-04 00:58:43 -04:00
Peter Steinberger
5b36bbf83e docs: document sandbox lifecycle registry 2026-06-04 00:57:14 -04:00
Peter Steinberger
9b4e2fa8a8 docs: document session tool bridges 2026-06-04 00:55:22 -04:00
Peter Steinberger
cc191e8021 docs: document sandbox support types 2026-06-04 00:53:43 -04:00
Peter Steinberger
64b9b60d94 docs: document runner guard helpers 2026-06-04 00:52:32 -04:00
Vincent Koc
68307afb5b fix(e2e): fail parallels host log write errors 2026-06-04 06:51:27 +02:00
Peter Steinberger
5a557b5e10 docs: document embedded runner state helpers 2026-06-04 00:51:06 -04:00
Peter Steinberger
7e85ba6139 docs: document sandbox helper utilities 2026-06-04 00:49:00 -04:00
Peter Steinberger
edd3870d53 docs: document session helper metadata 2026-06-04 00:47:48 -04:00
Peter Steinberger
a590fd24a9 docs: document agent harness helpers 2026-06-04 00:46:44 -04:00
Peter Steinberger
8f14a1c59a docs: document embedded runner helpers 2026-06-04 00:45:31 -04:00
Peter Steinberger
e1db0f01fe docs: document image pdf model helpers 2026-06-04 00:42:21 -04:00
Peter Steinberger
b1053ef9e9 docs: document session reply sentinels 2026-06-04 00:41:04 -04:00
Peter Steinberger
35d801a1e5 docs: document goal planning tools 2026-06-04 00:40:08 -04:00
Peter Steinberger
d901f85abb docs: document sandbox backend contracts 2026-06-04 00:38:23 -04:00
Vincent Koc
61d16dd173 fix(e2e): fail mock openai request log errors 2026-06-04 06:37:24 +02:00
Peter Steinberger
bb8e0ab5dc docs: document sandbox hash helpers 2026-06-04 00:37:11 -04:00
Peter Steinberger
1c640622dd docs: document sandbox safety helpers 2026-06-04 00:36:17 -04:00
Peter Steinberger
918d5afd67 docs: document embedded gateway helpers 2026-06-04 00:34:26 -04:00
Peter Steinberger
5820d105c9 docs: document media generation task helpers 2026-06-04 00:33:39 -04:00
Pavan Kumar Gondhi
3f1e0ebb86 Rate limit node pairing requests [AI] (#90147)
* fix: rate limit node pairing requests

* fix: preserve paired node reconnects
2026-06-04 10:02:55 +05:30
Peter Steinberger
52f96fab51 docs: document subagent tool step helpers 2026-06-04 00:31:53 -04:00
Peter Steinberger
9c10ef2ffa docs: document web fetch helpers 2026-06-04 00:30:14 -04:00
Peter Steinberger
4cd8b5eb78 docs: document tool runtime availability helpers 2026-06-04 00:29:25 -04:00
Peter Steinberger
07676fbb44 docs: document subagent registry read helpers 2026-06-04 00:28:29 -04:00
Peter Steinberger
bb1f3e8eaf docs: document session tool render helpers 2026-06-04 00:26:52 -04:00
Peter Steinberger
fd3cc7d224 docs: document session support helpers 2026-06-04 00:26:08 -04:00
Peter Steinberger
5a62a896b2 docs: document subagent announce runtime helpers 2026-06-04 00:25:03 -04:00
Pavan Kumar Gondhi
85b26bd206 fix: protect global agent config defaults (#90145) 2026-06-04 09:53:56 +05:30
Peter Steinberger
6f08a1a3dd docs: document session tool helpers 2026-06-04 00:23:38 -04:00
Peter Steinberger
20c3736dae docs: document web search helper config 2026-06-04 00:22:49 -04:00
Peter Steinberger
3c21fdad3c docs: document subagent session helpers 2026-06-04 00:22:08 -04:00
Peter Steinberger
5960549816 docs: document session keybinding helpers 2026-06-04 00:20:46 -04:00
Vincent Koc
2baa9d550e fix(e2e): fail pty transcript log errors 2026-06-04 06:20:02 +02:00
Peter Steinberger
b90fb1ef71 docs: document tool inventory helpers 2026-06-04 00:19:46 -04:00
Peter Steinberger
301c6d0043 docs: document exec utility helpers 2026-06-04 00:18:22 -04:00
Peter Steinberger
ed4c133c2c docs: document tool policy helpers 2026-06-04 00:17:34 -04:00
Peter Steinberger
f4369d225a docs: document model auth helpers 2026-06-04 00:15:57 -04:00
Peter Steinberger
b77c272fb9 docs: document tool model helpers 2026-06-04 00:13:55 -04:00
Peter Steinberger
46f3efe7ce docs: document harness hook helpers 2026-06-04 00:12:10 -04:00
Peter Steinberger
87b5796649 docs: document agent test fixtures 2026-06-04 00:10:47 -04:00
Peter Steinberger
2bb3132a5c docs: document harness classification helpers 2026-06-04 00:09:28 -04:00
Vincent Koc
54c3f53de5 fix(e2e): fail vanished crabbox sync checkouts 2026-06-04 06:08:04 +02:00
Peter Steinberger
73a81d1d6a docs: document harness helpers 2026-06-04 00:07:49 -04:00
Peter Steinberger
7b02080fa1 docs: document runtime utility helpers 2026-06-04 00:05:49 -04:00
Peter Steinberger
c90f42dbae docs: document dispatch report helpers 2026-06-04 00:04:19 -04:00
Peter Steinberger
32282418eb docs: document schema status helpers 2026-06-03 23:47:47 -04:00
Peter Steinberger
3eaab8632e docs: document mcp plugin helpers 2026-06-03 23:46:22 -04:00
Peter Steinberger
ff43ede887 docs: document cli compat helpers 2026-06-03 23:45:12 -04:00
Peter Steinberger
e4f6dd3440 docs: document agent utility helpers 2026-06-03 23:43:45 -04:00
Peter Steinberger
48557cecff docs: document model tool helpers 2026-06-03 23:41:43 -04:00
Peter Steinberger
6439b64c90 docs: document shared runtime helpers 2026-06-03 23:40:46 -04:00
Peter Steinberger
2fb968a425 docs: document runtime system helpers 2026-06-03 23:39:30 -04:00
Peter Steinberger
ddaa2c5dc8 docs: document status capability helpers 2026-06-03 23:38:32 -04:00
Peter Steinberger
fba1e49083 docs: document live provider probes 2026-06-03 23:37:21 -04:00
Peter Steinberger
059277f83b docs: document provider error helpers 2026-06-03 23:35:55 -04:00
Peter Steinberger
ae8b868342 docs: document oauth test helpers 2026-06-03 23:32:59 -04:00
Peter Steinberger
48d6c75111 docs: document text transform helpers 2026-06-03 23:30:53 -04:00
Mukunda Rao Katta
d966486242 fix(whatsapp): restart channel when a per-account config field changes so disabled accounts are torn down (#87965)
Merged via squash.

Prepared head SHA: 4142d5562e
Co-authored-by: MukundaKatta <99349238+MukundaKatta@users.noreply.github.com>
Co-authored-by: mcaxtr <7562095+mcaxtr@users.noreply.github.com>
Reviewed-by: @mcaxtr
2026-06-04 00:30:29 -03:00
Peter Steinberger
e98b864752 docs: document agent contract helpers 2026-06-03 23:28:53 -04:00
Marcus Castro
88dc177afc fix(auto-reply): count message tool sends as delivery (#90123) 2026-06-04 00:26:45 -03:00
Peter Steinberger
06fee678e1 docs: document runtime timeout helpers 2026-06-03 23:26:32 -04:00
Peter Steinberger
1d2e91e20d docs: document mcp workspace helpers 2026-06-03 23:24:30 -04:00
Peter Steinberger
5169d19ce8 docs: document agent test helpers 2026-06-03 23:21:21 -04:00
Peter Steinberger
86c071035d docs: document provider config helpers 2026-06-03 23:19:46 -04:00
Peter Steinberger
c635716297 docs: document model normalization helpers 2026-06-03 23:17:44 -04:00
Peter Steinberger
0df6292ab3 docs: document live provider helpers 2026-06-03 23:16:10 -04:00
Peter Steinberger
dd555073d0 docs: document provider tool helpers 2026-06-03 23:13:43 -04:00
Vincent Koc
8c74fd4e23 fix(e2e): keep parallels json output parseable 2026-06-04 05:12:13 +02:00
Peter Steinberger
59768909ba docs: document runtime test helpers 2026-06-03 23:11:45 -04:00
Peter Steinberger
1b35d46257 docs: document prompt routing helpers 2026-06-03 23:10:06 -04:00
Peter Steinberger
20e443b965 docs: document model tool utilities 2026-06-03 23:09:20 -04:00
Peter Steinberger
d714803e6d docs: document subagent session helpers 2026-06-03 23:07:58 -04:00
Peter Steinberger
18d036326c docs: document codex context helpers 2026-06-03 23:05:41 -04:00
Peter Steinberger
8b47fa5a76 docs: document runtime utility helpers 2026-06-03 23:02:33 -04:00
Peter Steinberger
e168a82367 docs: document cli runner mcp helpers 2026-06-03 22:59:39 -04:00
Peter Steinberger
83eab79d15 docs: document bootstrap cache helpers 2026-06-03 22:56:27 -04:00
Peter Steinberger
c7a8114f54 docs: document bash process helpers 2026-06-03 22:54:12 -04:00
Peter Steinberger
ef17cecca9 docs: document auth profile store helpers 2026-06-03 22:51:20 -04:00
Peter Steinberger
8835787ed6 docs: document tool hook helpers 2026-06-03 22:47:45 -04:00
Vincent Koc
b12114e45c fix(e2e): abort kitchen sink readiness on gateway exit 2026-06-04 04:46:34 +02:00
Peter Steinberger
32e51f250f docs: document auth redaction helpers 2026-06-03 22:43:51 -04:00
Peter Steinberger
8f7808d1e6 docs: document agent diagnostics helpers 2026-06-03 22:42:05 -04:00
Peter Steinberger
3788a2fd3d docs: document agent steering helpers 2026-06-03 22:40:24 -04:00
Peter Steinberger
b6d6ed34ed docs: document runtime tool helpers 2026-06-03 22:37:59 -04:00
Peter Steinberger
44bcaf00b7 docs: document model auth helpers 2026-06-03 22:36:19 -04:00
Vincent Koc
546aa5770a fix(e2e): report gauntlet log write failures 2026-06-04 04:34:50 +02:00
Peter Steinberger
658f90f845 docs: document subagent model helpers 2026-06-03 22:34:29 -04:00
Peter Steinberger
155260eb04 docs: document model path helpers 2026-06-03 22:33:13 -04:00
Peter Steinberger
7ce1487f33 docs: document auth profile oauth helpers 2026-06-03 22:30:03 -04:00
Peter Steinberger
ac2dbfcfca docs: document auth profile persistence helpers 2026-06-03 22:28:03 -04:00
Vincent Koc
d6ab1fdfe4 test: read codex on-demand auth store from sqlite 2026-06-04 04:26:51 +02:00
Vincent Koc
50c3995894 fix(e2e): fail secret provider startup exits fast 2026-06-04 04:25:53 +02:00
Peter Steinberger
ad958fd97a docs: document auth profile selection helpers 2026-06-03 22:25:34 -04:00
Vincent Koc
0451dcdc56 test(codex): isolate app-server auth fixtures 2026-06-03 19:23:57 -07:00
Peter Steinberger
003bb8546d docs: document auth profile discovery helpers 2026-06-03 22:23:37 -04:00
Peter Steinberger
a2a4924679 docs: document auth profile path state helpers 2026-06-03 22:21:50 -04:00
Peter Steinberger
2ff2ed4099 docs: document agent tool policy helpers 2026-06-03 22:19:38 -04:00
Peter Steinberger
fc5cb461c9 docs: document agent runtime preset helpers 2026-06-03 22:15:52 -04:00
Peter Steinberger
c86eb20dc5 docs: document agent routing state helpers 2026-06-03 22:13:26 -04:00
Peter Steinberger
0d0632d88d docs: document agent runtime utility helpers 2026-06-03 22:11:33 -04:00
Peter Steinberger
2e89655a03 docs: document agent command exec helpers 2026-06-03 22:09:31 -04:00
Peter Steinberger
233666366f docs: document agent command shared helpers 2026-06-03 22:07:59 -04:00
Vincent Koc
474be452a7 test: align dependency override guard with workspace metadata 2026-06-04 04:07:15 +02:00
Peter Steinberger
076178adc6 docs: document agent provider request helpers 2026-06-03 22:06:48 -04:00
Peter Steinberger
eda170f328 docs: document agent inventory recovery helpers 2026-06-03 22:04:42 -04:00
Peter Steinberger
d4867ec20d docs: document agent runtime tool policies 2026-06-03 22:03:35 -04:00
Vincent Koc
d26cef4249 fix(ci): preserve crabbox hydrate pnpm store 2026-06-04 03:59:51 +02:00
Peter Steinberger
e1e095d020 docs: document agent catalog helpers 2026-06-03 21:59:30 -04:00
Vincent Koc
7e5ea598c5 fix(e2e): fail gateway frame waits on socket close 2026-06-04 03:52:52 +02:00
Peter Steinberger
0328f29707 docs: document subagent sqlite registry 2026-06-03 21:51:50 -04:00
Peter Steinberger
9dce23f295 docs: document agent workspace helpers 2026-06-03 21:50:11 -04:00
Peter Steinberger
caa6102144 docs: document agent provider auth helpers 2026-06-03 21:48:41 -04:00
Peter Steinberger
ca3250a3c1 docs: document agent schema and outcome helpers 2026-06-03 21:46:11 -04:00
Vincent Koc
dcfd033746 test: seed auto-reply auth profiles through store 2026-06-04 03:44:04 +02:00
Peter Steinberger
45f4875613 docs: document agent model auth helpers 2026-06-03 21:43:58 -04:00
Peter Steinberger
51e279153f docs: document agent safety helpers 2026-06-03 21:42:04 -04:00
Peter Steinberger
d54addcd28 docs: document agent helper barrels 2026-06-03 21:40:38 -04:00
Peter Steinberger
9eb525de0e docs: document fetch header normalization 2026-06-03 21:38:41 -04:00
Peter Steinberger
d0bf656a3f docs: document session helper APIs 2026-06-03 21:37:49 -04:00
Peter Steinberger
604597d825 docs: document daemon process helpers 2026-06-03 21:35:27 -04:00
Vincent Koc
c286f56167 test: align e2e fixtures with current runtime stores 2026-06-04 03:29:37 +02:00
Vincent Koc
036b730321 fix(scripts): run deadcode knip through pnpm runner 2026-06-04 03:23:45 +02:00
Vincent Koc
deea78da72 perf(gateway): bypass config facade for config handlers 2026-06-04 03:23:45 +02:00
Vincent Koc
eb5d6c7294 perf(gateway): delay provider auth warmup 2026-06-04 03:23:45 +02:00
Vincent Koc
009d7335b5 fix(scripts): run RPC RTT probe without pnpm 2026-06-04 03:23:45 +02:00
Vincent Koc
25f3d2d714 perf(gateway): avoid heavy chat imports in history tests 2026-06-04 03:23:45 +02:00
Peter Steinberger
0416117168 docs: document channel helper APIs 2026-06-03 21:21:02 -04:00
Shakker
4cb34f3999 fix: refresh generated gateway protocol 2026-06-04 02:10:38 +01:00
Shakker
0059f5c24a fix: suppress commands for revision handoff sends 2026-06-04 02:10:38 +01:00
Shakker
4bcae169e2 refactor: centralize chat command interpretation 2026-06-04 02:10:38 +01:00
Shakker
3da05d01a7 fix: namespace chat dedupe by system context 2026-06-04 02:10:38 +01:00
Shakker
f7e44ac6b5 fix: treat Skill Workshop slash drafts as revisions 2026-06-04 02:10:38 +01:00
Shakker
25e3162cce fix: route Skill Workshop revisions through request RPC 2026-06-04 02:10:38 +01:00
Shakker
7150c3c957 fix: separate Skill Workshop revision target agent 2026-06-04 02:10:38 +01:00
Shakker
bf08234ee3 feat: add Skill Workshop revision request 2026-06-04 02:10:38 +01:00
Peter Steinberger
179ff9b423 docs: document plugin registry helper APIs 2026-06-03 21:03:43 -04:00
Peter Steinberger
9b6cd2ea75 docs: document plugin security channel helpers 2026-06-03 21:01:33 -04:00
Vincent Koc
4fbc318e30 ci: stabilize live e2e resource lanes 2026-06-04 02:59:52 +02:00
Brian
7b5f75eb98 Pin official npm plugin install records (#88585)
* fix(plugins): pin official npm install records

* fix(infra): tolerate equivalent plugin install migrations

* fix(plugins): preserve manual exact plugin pins

* fix(infra): remove stale migration imports

* chore: unblock ci guards

* fix: preserve official sync integrity checks

* fix: avoid prerelease integrity carryover

* fix: preserve manual official npm specs

* fix: preserve beta fallback integrity checks

* fix: preserve trusted prerelease fallback integrity

* fix: preserve prerelease-only integrity checks

* fix: pin unchanged official npm records

* fix: allow official compatible fallback updates

* fix: preserve fallback integrity after prerelease resolution

* fix: skip incompatible fallback integrity pins

* fix: preserve pin-only install provenance

* fix: check integrity when repairing missing official pins

---------

Co-authored-by: Lilac <lilac@Lilacs-iMac.local>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-06-03 17:58:09 -07:00
Peter Steinberger
d1fef1d50d docs: document plugin runtime config helpers 2026-06-03 20:54:08 -04:00
Vincent Koc
392af2e612 fix(deps): keep managed overrides in workspace metadata 2026-06-03 17:43:09 -07:00
Vincent Koc
b4234d4028 test: preserve version exports in partial mocks 2026-06-03 17:43:09 -07:00
Peter Steinberger
69c8097dd1 docs: document plugin overlay memory helpers 2026-06-03 20:41:35 -04:00
Val Alexander
60104fe254 fix(workboard): isolate stale lifecycle bulk patches
Follow-up to #89600 for #88592.

- Keep stale lifecycle bulk updates from mutating shared Workboard patch objects.
- Preserve non-status updates while suppressing stale lifecycle status/provenance writes.
- Tighten current-main migrate-hermes test assertions against the canonical auth-profile store shape.

Verification:
- node scripts/run-vitest.mjs ui/src/ui/controllers/workboard.test.ts ui/src/ui/views/workboard.test.ts extensions/workboard/src/store.test.ts extensions/workboard/src/gateway.test.ts --reporter=verbose
- node scripts/run-vitest.mjs --config test/vitest/vitest.ui-e2e.config.ts --configLoader runner ui/src/ui/e2e/workboard-status-persistence.e2e.test.ts ui/src/ui/e2e/workboard.e2e.test.ts --reporter=verbose
- node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.core.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core-test.tsbuildinfo
- node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.extensions.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/extensions-test.tsbuildinfo
- node scripts/run-vitest.mjs extensions/migrate-hermes/files-and-skills.test.ts extensions/migrate-hermes/secrets.test.ts --reporter=verbose
- corepack pnpm deadcode:unused-files
- git diff --name-only origin/main...HEAD | xargs node scripts/run-oxlint.mjs
- git diff --check origin/main...HEAD
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main --no-web-search
- GitHub CI for 5ee8b3dd5f
2026-06-03 17:40:07 -07:00
Peter Steinberger
fd5dc5bb3a docs: document plugin catalog install helpers 2026-06-03 20:39:16 -04:00
Peter Steinberger
f6aa2c02d1 docs: document plugin runtime load context 2026-06-03 20:36:52 -04:00
Peter Steinberger
7b4d14f786 docs: document plugin runtime helper APIs 2026-06-03 20:34:17 -04:00
Vincent Koc
822ebb4c94 test(e2e): read onboard auth profiles from sqlite 2026-06-04 02:33:56 +02:00
Peter Steinberger
58f7d7e5f8 docs: document plugin scope state helpers 2026-06-03 20:30:38 -04:00
Peter Steinberger
0ad13b714e docs: document plugin manifest install helpers 2026-06-03 20:28:45 -04:00
Peter Steinberger
bb8192ff7c docs: document plugin hook provider helpers 2026-06-03 20:26:18 -04:00
Peter Steinberger
c5d52bf2a7 docs: document plugin runtime utilities 2026-06-03 20:22:56 -04:00
Peter Steinberger
06ad1d0d74 docs: document plugin public artifact helpers 2026-06-03 20:21:16 -04:00
Peter Steinberger
27b1d05a1d docs: document plugin runtime status helpers 2026-06-03 20:19:17 -04:00
Peter Steinberger
02c6630f11 docs: document plugin install helpers 2026-06-03 20:17:55 -04:00
Peter Steinberger
c821ef274b docs: document plugin test helpers 2026-06-03 20:16:51 -04:00
Vincent Koc
6d84fb35c7 test(plugins): read migrated auth profiles from sqlite store 2026-06-04 02:15:52 +02:00
Peter Steinberger
335f045393 docs: document plugin manifest helpers 2026-06-03 20:15:37 -04:00
Peter Steinberger
371777ad14 docs: document plugin runtime loaders 2026-06-03 20:13:51 -04:00
Peter Steinberger
ca7c2714f6 docs: document plugin auth runtime helpers 2026-06-03 20:12:42 -04:00
Peter Steinberger
b1d434b666 docs: document plugin provider helpers 2026-06-03 20:11:25 -04:00
Vincent Koc
a7f442ffd8 test(infra): follow active npm override pins 2026-06-04 02:07:49 +02:00
Peter Steinberger
bbff951880 docs: document plugin index policy helpers 2026-06-03 20:04:38 -04:00
Peter Steinberger
9a4d28695b docs: document plugin host helpers 2026-06-03 20:01:47 -04:00
Vincent Koc
96136e6d71 fix(plugins): align auth profile tests with sqlite store 2026-06-04 02:00:35 +02:00
Peter Steinberger
e993e1c334 docs: document auto-reply final helpers 2026-06-03 19:57:58 -04:00
Vincent Koc
99e627b283 fix(deps): align root override metadata 2026-06-03 16:54:52 -07:00
Vincent Koc
edc9be1b7f test(release): read auth refs from sqlite store 2026-06-03 16:54:52 -07:00
Peter Steinberger
01d69041a2 docs: document auto-reply session runtime helpers 2026-06-03 19:54:16 -04:00
Peter Steinberger
6baa5ca5b1 docs: document auto-reply runtime facades 2026-06-03 19:51:54 -04:00
joshavant
d5d3e9983e fix: harden mobile a2ui bridge trust 2026-06-03 16:50:08 -07:00
Peter Steinberger
0b6fff44f5 docs: document auto-reply policy helpers 2026-06-03 19:48:48 -04:00
Val Alexander
e07dbb27d9 Fix Workboard status persistence
Summary:
- Persist Workboard lifecycle status provenance so stale linked session/task lifecycle updates cannot overwrite newer manual or non-default creation status.
- Add focused Workboard store/controller regressions for lifecycle-vs-manual precedence and creation-status precedence.
- Add mocked Control UI browser E2E proof for create/edit/reopen, running move, lifecycle sync, reload persistence, and read-only operator behavior.

Verification:
- `node scripts/run-vitest.mjs extensions/workboard/src/store.test.ts extensions/workboard/src/gateway.test.ts --reporter=verbose`
- `node scripts/run-vitest.mjs ui/src/ui/controllers/workboard.test.ts ui/src/ui/views/workboard.test.ts --reporter=verbose`
- `node scripts/run-vitest.mjs --config test/vitest/vitest.ui-e2e.config.ts --configLoader runner ui/src/ui/e2e/workboard-status-persistence.e2e.test.ts ui/src/ui/e2e/workboard.e2e.test.ts --reporter=verbose`
- `corepack pnpm tsgo:core:test`
- `corepack pnpm tsgo:extensions:test`
- `node scripts/run-oxlint.mjs extensions/workboard/src/sqlite-store.ts extensions/workboard/src/store.test.ts extensions/workboard/src/store.ts extensions/workboard/src/types.ts ui/src/ui/controllers/workboard.test.ts ui/src/ui/controllers/workboard.ts ui/src/ui/e2e/workboard-status-persistence.e2e.test.ts ui/src/ui/e2e/workboard.e2e.test.ts ui/src/ui/views/workboard.test.ts ui/src/ui/views/workboard.ts`
- `git diff --check`
- `.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main` clean
- GitHub PR checks green on head `6d05d6edd5ca6cbb2e625f3e478e973feba5e4cf`

Proof:
- E2E manifest: `/Users/buns/.codex/worktrees/74e7/openclaw/.artifacts/control-ui-e2e/workboard/manifest.json`
- Live Gateway success proof: `/Users/buns/.codex/worktrees/74e7/openclaw/.artifacts/live-workboard/proof/12-live-review-success.png`
- Remaining gap: read-only operator behavior is covered by mocked browser E2E, not live Gateway.
2026-06-03 16:46:14 -07:00
Peter Steinberger
d9d4514c00 docs: document auto-reply directive helpers 2026-06-03 19:31:07 -04:00
Peter Steinberger
05d92d8761 docs: document auto-reply queue exec helpers 2026-06-03 19:29:12 -04:00
Peter Steinberger
90b1ab1c70 docs: document auto-reply block helpers 2026-06-03 19:25:58 -04:00
Peter Steinberger
93917413de docs: document auto-reply dispatch helpers 2026-06-03 19:23:08 -04:00
Peter Steinberger
9a1e896c96 docs: document auto-reply queue helpers 2026-06-03 19:21:12 -04:00
Josh Lehman
208fec6ddc docs: clarify legacy openai-codex auth (#90028) 2026-06-03 16:18:51 -07:00
Peter Steinberger
6d4d313d44 docs: document auto-reply runtime helpers 2026-06-03 19:16:37 -04:00
Peter Steinberger
8129fc0f3a docs: document auto-reply top-level helpers 2026-06-03 19:14:43 -04:00
Peter Steinberger
e16ac04330 refactor(auth): store auth profiles in sqlite (#89102) 2026-06-03 16:14:15 -07:00
Peter Steinberger
116bc2a0f0 docs: surface Windows Hub across docs 2026-06-03 16:09:24 -07:00
Peter Steinberger
1878ca0820 chore(release): prepare 2026.6.2 beta 2026-06-04 00:06:52 +01:00
B.K.
c96a12d3c8 fix(update): surface plugin channel fallbacks (#81422)
* fix: surface plugin update channel fallbacks

* fix: clarify dry-run plugin fallback output

* fix: preserve failed plugin fallback metadata

* chore: mark compatibility aliases deprecated

* chore: fix channel runtime lint directive

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-06-03 16:00:40 -07:00
Vincent Koc
28a2e795da test(canvas): pin a2ui compatibility assets 2026-06-04 00:58:33 +02:00
Peter Steinberger
46f015a627 docs: document gateway server methods 2026-06-03 18:55:58 -04:00
Vincent Koc
1fde4ae3b1 fix(test): keep explicit ui tests scoped 2026-06-04 00:53:18 +02:00
Peter Steinberger
3ad7049cba docs: document gateway general helpers 2026-06-03 18:53:08 -04:00
Peter Steinberger
190fd034d5 docs: refresh Windows Hub platform guide 2026-06-03 15:52:00 -07:00
Peter Steinberger
59366ca420 docs: document gateway utility helpers 2026-06-03 18:48:32 -04:00
Shakker
0771a8ab6f fix: restore Skill Workshop current chat toggle 2026-06-03 23:46:43 +01:00
Shakker
03c730c48f test: cover awaited chat session switching 2026-06-03 23:46:43 +01:00
Shakker
8c91980123 refactor: add awaitable chat session switch 2026-06-03 23:46:43 +01:00
Vincent Koc
8fe67e4b70 test(canvas): verify a2ui compatibility assets 2026-06-04 00:45:34 +02:00
Peter Steinberger
a53a545542 docs: document remaining plugin sdk helpers 2026-06-03 18:45:11 -04:00
Vincent Koc
41e56d56fc fix(plugin-sdk): stabilize API baseline source paths 2026-06-03 15:44:08 -07:00
Peter Steinberger
381c5e0762 docs: document remaining cli helpers 2026-06-03 18:43:23 -04:00
Peter Steinberger
e254346bc2 chore(release): prepare 2026.6.3 beta 2026-06-03 23:42:34 +01:00
Ted Li
308114e148 fix(browser): honor Chrome MCP tab timeouts
Fixes #88213.

Browser tab routes now use the configured action timeout for Chrome MCP existing-session reachability checks instead of failing through the old 300ms probe. Non-Chrome-MCP profiles keep the short probe, and configured timeout values are clamped to the safe timer range.

Proof: autoreview clean; node scripts/run-vitest.mjs extensions/browser/src/browser/routes/tabs.test.ts; merge-base git diff --check; PR CI green.

Co-authored-by: Ted Li <tl2493@columbia.edu>
2026-06-03 15:36:09 -07:00
Kevin Lin
fce002ad03 revert(codex): revert first-party marketplace allowlist
Reverts openclaw/openclaw#82219.
2026-06-03 15:35:35 -07:00
Ted Li
d5c8e90e28 fix(agents): repair context-engine tool-result pairing
Context-engine assembly could replace an already-repaired attempt transcript with a view containing orphaned tool results. Reuse the attempt-level tool-use/tool-result pairing repair after initial assembly and ownsCompaction loop assembly so strict OpenAI-compatible replay does not emit free-floating tool messages.

Fixes #88561.

Verification:
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
- git diff --check origin/main...HEAD
- PR CI: https://github.com/openclaw/openclaw/actions/runs/26766745554
- Real behavior proof: https://github.com/openclaw/openclaw/actions/runs/26767235053

Co-authored-by: Ted Li <tl2493@columbia.edu>
2026-06-03 15:34:27 -07:00
Vincent Koc
2ecd1d3299 docs(changelog): restore 2026.6.2 package notes 2026-06-04 00:33:30 +02:00
scotthuang
7f1a920a89 fix: keep stream-to-parent ACP spawns registered
Keep ACP sessions_spawn runs that request streamTo=parent in the subagent registry so completion handoffs can announce back to users while inline delivery suppression still prevents double delivery.

Fixes stream-to-parent child completions dropping in direct-session channels.

Thanks @scotthuang.
2026-06-03 15:32:22 -07:00
Glucksberg
32acef01b3 fix(agents): classify read-only shell commands as non-mutating
Classify clearly read-only exec/bash shell probes as non-mutating so failed inspection commands no longer add misleading final tool-warning messages after a useful assistant reply. Ambiguous or mutating shell forms still fail closed as mutating, including redirects, pipes, heredocs, mutating git/gh forms, and gh web-launch flags.

Verification:
- pnpm test src/agents/tool-mutation.test.ts
- pnpm test src/agents/embedded-agent-runner/run/payloads.test.ts src/agents/embedded-agent-runner/run/payloads.errors.test.ts
- CI/check rollup for head 346853fb07 had no pending or failing checks; historical cancelled/skipped Mantis proof jobs were non-blocking.

Co-authored-by: Markus <markuscontasul@gmail.com>
2026-06-03 15:28:39 -07:00
Peter Steinberger
95045b1d5b docs: document cli gateway plugin helpers 2026-06-03 18:25:21 -04:00
Peter Steinberger
4f4cd2e8ae docs: document cli shared helpers 2026-06-03 18:23:39 -04:00
Peter Steinberger
90b8b41c41 docs(changelog): expand 2026.6.3 release notes 2026-06-03 23:21:43 +01:00
Peter Steinberger
0b8aabe864 docs: document auth profile failure policy contract (#89613)
* docs: document markdown marker renderer

* docs: document rendered markdown chunking

* docs: document markdown text chunking

* docs: document shared text chunking

* docs: document plugin text chunking exports

* docs: document avatar policy constants

* docs: document node match candidates

* docs: document scoped expiring id cache

* docs: document runtime import normalization

* docs: document string sample summaries

* docs: document session usage timeseries types

* docs: document session usage response types

* docs: document manifest frontmatter shapes

* docs: document channel route input metadata

* docs: document pair loop guard settings

* docs: document migration config patch helpers

* docs: document api provider registry

* docs: document tool call repair payloads

* docs: document plugin tool payload helpers

* docs: document lazy promise loader

* docs: document store writer queue state

* docs: document thread binding lifecycle

* docs: document concurrency helper contract

* docs: document gateway client info contract

* docs: document delivery context contracts

* docs: document secret ref defaults contract

* docs: document command gating contract

* docs: document avatar policy contract

* docs: document node match policy

* docs: document message channel normalization

* docs: document boolean parsing contract

* docs: document zod parse helpers

* docs: document direct dm guard policy

* docs: document fixed window limiter contract

* docs: document node presence event contract

* docs: document secret normalization contract

* docs: document progress draft line removal

* docs: document usage formatting contracts

* docs: document agent run status contract

* docs: document runtime import helpers

* docs: document provider utility ownership

* docs: document invalid config helpers

* docs: document json compat parser

* docs: document channel config metadata ownership

* docs: document channel logging helpers

* docs: document sender identity validation ownership

* docs: document string sampling helper

* docs: document global singleton helpers

* docs: document transcript tool helpers

* docs: document exec safe-bin normalization

* docs: document reaction level resolver

* docs: document account snapshot redaction boundary

* docs: document messaging target helpers

* docs: document thread binding messages

* docs: document conversation binding context

* docs: document conversation resolution helper

* docs: document owner display secret retention

* docs: document provider request config types

* docs: document skills config types

* docs: document memory config types

* docs: document imessage config types

* docs: document crestodian config types

* docs: document tools config policies

* docs: document shared config base types

* docs: document channel config contracts

* docs: document openclaw config state types

* docs: document model config contracts

* docs: document shared agent config types

* docs: document agent defaults config types

* docs: document secret input contracts

* docs: document auth config contracts

* docs: document gateway config contracts

* docs: document tool call stream repair contracts

* docs: document memory host facades

* docs: document llm core contracts

* docs: document markdown core contracts

* docs: document gateway connect error contracts

* docs: document gateway protocol primitives

* docs: document gateway frame schemas

* docs: document gateway device schemas

* docs: document gateway environment schemas

* docs: document gateway push schemas

* docs: document gateway plugin schemas

* docs: document gateway artifact schemas

* docs: document gateway command schemas

* docs: document gateway task schemas

* docs: document gateway exec approval schemas

* docs: document gateway secret schemas

* docs: document gateway config schemas

* docs: document gateway snapshot schemas

* docs: document gateway chat schemas

* docs: document gateway wizard schemas

* docs: document gateway node schemas

* docs: document gateway plugin approval schemas

* docs: document gateway talk schemas

* docs: document gateway agent schemas

* docs: document gateway session schemas

* docs: document gateway cron schemas

* docs: document gateway agent model skill schemas

* docs: document gateway skill proposal tool schemas

* docs: document gateway protocol registry

* docs: document gateway channel status schemas

* docs: document gateway schema regression tests

* docs: document gateway schema barrel

* docs: document gateway validator tests

* docs: document gateway primitive push tests

* docs: document gateway contract tests

* docs: document native protocol guard

* docs: document channel schema tests

* docs: document gateway protocol smoke tests

* docs: document gateway protocol entrypoint

* docs: document gateway protocol type exports

* docs: document gateway error codes

* docs: document protocol schema registry

* docs: document talk audio codec

* docs: document talk activation names

* docs: document talk consult questions

* docs: document talk consult tool

* docs: document talk run control contracts

* docs: document talk run control adapter

* docs: document talkback consult queue

* docs: document talk consult transcript guard

* docs: document talk fast context runtime

* docs: document forced talk consult coordinator

* docs: document talk output activity tracker

* docs: document talk event metrics

* docs: document talk diagnostics

* docs: document talk observability hook

* docs: document talk provider resolver

* docs: document talk provider registry

* docs: document talk runtime primitives

* docs: document talk consult controller logs

* docs: document channel identity helpers

* docs: document channel account allowlist helpers

* docs: document channel metadata draft controls

* docs: document channel ingress policy

* docs: document channel sender access gates

* docs: document channel catalog message contracts

* docs: document channel account plugin helpers

* docs: document configured binding helpers

* docs: document channel acp approval config helpers

* docs: document channel bundled config write helpers

* docs: document channel plugin utility contracts

* docs: document channel config access helpers

* docs: document channel message action helpers

* docs: document channel outbound runtime helpers

* docs: document channel pairing promotion helpers

* docs: document channel registry helpers

* docs: document channel setup wizard helpers

* docs: document channel lifecycle status helpers

* docs: document channel target thread helpers

* docs: document channel session binding helpers

* docs: document channel package module probes

* docs: document channel setup wizard contracts

* docs: document channel plugin API barrels

* docs: document channel contract test helpers

* docs: document channel core helpers

* docs: document small core facades

* docs: document provider runtime helpers

* docs: document persistence and realtime helpers

* docs: document mcp and state helpers

* docs: document tool planner contracts

* docs: document music generation runtime

* docs: document crestodian command flow

* docs: document utility helpers

* docs: document node host helpers

* docs: document transcript contracts

* docs: document trajectory export contracts

* docs: document image generation contracts

* docs: document routing helper contracts

* docs: document session helper contracts

* docs: document video generation contracts

* docs: document model catalog contracts

* docs: document proxy capture contracts

* docs: document status rendering contracts

* docs: document test helper contracts

* docs: document wizard setup contracts

* docs: document process contracts

* docs: document memory host sdk contracts

* docs: document tts contracts

* docs: document secrets runtime contracts

* docs: document shared helper contracts

* docs: document hook runtime contracts

* docs: document security audit contracts

* docs: document flow contracts

* docs: document media understanding contracts

* docs: document tui contracts

* docs: document logging contracts

* docs: document llm contracts

* docs: document cron contracts

* docs: document daemon contracts

* docs: document task contracts

* docs: document acp contracts

* docs: document test utility contracts

* docs: document skill contracts

* docs: document config contracts

* docs: document outbound infra contracts

* docs: document command analysis contracts

* docs: document provider usage infra contracts

* docs: document file safety infra contracts

* docs: document exec approval infra contracts

* docs: document gateway runtime infra contracts

* docs: document infra utility contracts

* docs: document infra queue storage contracts

* docs: document heartbeat infra contracts

* docs: document remaining infra contracts

* docs: document gateway auth contracts

* docs: document gateway display helpers

* docs: document gateway http helpers

* docs: document gateway node helpers

* docs: document gateway mcp helpers

* docs: document gateway support helpers

* docs: document gateway server runtime helpers

* docs: document gateway runtime bootstrap helpers

* docs: document gateway session events

* docs: document gateway utility helpers

* docs: document gateway talk helpers

* docs: document gateway helper contracts

* docs: document gateway server method helpers

* docs: document gateway server auth helpers

* docs: document gateway server tests

* docs: document gateway test helpers

* docs: document gateway node tests

* docs: document gateway channel tests

* docs: document gateway session tests

* docs: document gateway server startup tests

* docs: document gateway tool test helpers

* docs: document gateway server test helpers

* docs: document gateway server method tests

* docs: document remaining gateway tests

* docs: document plugin sdk public subpaths

* docs: document plugin sdk runtime helpers

* docs: document plugin sdk memory provider helpers

* docs: document plugin sdk runtime facades

* docs: document plugin sdk command approval helpers

* docs: document plugin sdk runtime types

* docs: document plugin sdk browser account helpers

* docs: document plugin sdk media memory helpers

* docs: document plugin sdk core tests

* docs: document plugin sdk contract helpers

* docs: document plugin sdk test helpers

* docs: document remaining plugin sdk tests

* docs: document cli utility helpers

* docs: document cli runtime helpers

* docs: document cli command registration helpers

* docs: document node cli helpers

* docs: document cli program registration

* docs: document message cli registration

* docs: document daemon cli helpers

* docs: document cli route parsers
2026-06-03 15:20:39 -07:00
Peter Steinberger
8de37e1ce4 docs(changelog): normalize 2026.6.3 unreleased notes 2026-06-03 23:02:01 +01:00
Peter Steinberger
20fa8a92a7 docs(changelog): add 2026.6.3 notes 2026-06-03 23:01:03 +01:00
joshavant
10830bc4a7 docs: warn about install policy plugin update footguns 2026-06-03 14:51:45 -07:00
Vincent Koc
2b31ad2ee5 docs(plugin-sdk): refresh API baseline hash 2026-06-03 14:48:00 -07:00
Peter Steinberger
ed283490b5 docs(release): require verified Windows asset links 2026-06-03 22:42:53 +01:00
Peter Steinberger
bf368e7609 ci(release): promote Windows node installers 2026-06-03 22:39:58 +01:00
Vincent Koc
0756680421 docs(changelog): add 2026.6.2 notes 2026-06-03 14:33:40 -07:00
Peter Steinberger
639ff98509 chore(release): update appcast for 2026.6.1
Updates the stable Sparkle appcast generated by macOS publish for v2026.6.1.
2026-06-03 14:30:15 -07:00
Vincent Koc
0f05aff312 docs(config): refresh channel config baseline hash 2026-06-03 14:27:38 -07:00
Peter Steinberger
e9379ef22b docs(release): document GitHub release note edits 2026-06-03 22:25:43 +01:00
Peter Steinberger
b411c53248 docs(changelog): publish 2026.6.1 notes on main 2026-06-03 22:18:53 +01:00
Josh Avant
154f439c81 Add operator install policy and remove dangerous-code install scanners (#89516)
* feat: add operator install policy

* test: cover plain-file plugin install code

* fix: preserve locationless install policy findings

* refactor: remove install-time plugin scanner

* test: remove stale plugin install helper

* fix: preserve before-install builtin scan type

* fix: preserve plugin dependency denylist

---------

Co-authored-by: Mainframe <mainframe@MainfraacStudio.localdomain>
2026-06-03 14:17:29 -07:00
Vincent Koc
7b82901e58 ci(crabbox): keep hydrated modules under node_modules 2026-06-03 13:50:10 -07:00
Vincent Koc
932034f1fc test(live): keep cache prereq skips provider-aware 2026-06-03 13:45:27 -07:00
Vincent Koc
a0717ef61c fix(testing): speed channel contract loading 2026-06-03 21:14:05 +02:00
Dallin Romney
f0237caf27 fix(memory): warn after startup watcher pressure check (#89244)
* fix(config): warn only for large memory watch paths

* fix(config): align memory watch warning scan roots

* fix(config): import memory search config type

* fix(config): align memory watch warning sources

* fix(config): match memory source fallback

* fix(memory): warn from runtime watcher pressure

* fix(memory): warn after watcher fallback pressure

* fix(memory): keep watcher pressure warning startup scoped

* fix(memory): delay startup watcher pressure sample

* chore(memory): clarify watcher pressure comments

* test(memory): remove redundant watcher assertion

* refactor(memory): share watcher pressure warning policy

* refactor(memory): trim watcher pressure duplication

* refactor(memory): flatten watcher pressure calls

* docs(readme): use contributor-facing community wording

* Revert "docs(readme): use contributor-facing community wording"

This reverts commit 796bc03913.
2026-06-03 11:57:35 -07:00
Vincent Koc
892602eaba test(live): harden ARM live harness defaults 2026-06-03 11:27:21 -07:00
Dallin Romney
79a8dec44d test(channels): fix guardrail regex lint (#89960) 2026-06-03 11:01:28 -07:00
Vincent Koc
7098e335bf fix(models): recover bundled provider aliases 2026-06-03 19:38:54 +02:00
Vincent Koc
6d5061c234 fix(testing): harden bundled channel contract loading 2026-06-03 19:22:57 +02:00
Vincent Koc
286e5ffe07 test(startup): make cli startup budgets arch-aware 2026-06-03 09:50:04 -07:00
Vincent Koc
158c4d7540 fix(discord): match libopus error shape 2026-06-03 18:37:18 +02:00
Vincent Koc
344e04b5d5 fix(testing): route source targets through test planner 2026-06-03 18:07:32 +02:00
Vincent Koc
ec47d1cdd5 fix(canvas): restore A2UI compatibility assets 2026-06-03 17:31:15 +02:00
Vincent Koc
8c89d35a8a fix(gateway): cancel stop terminate fallback 2026-06-03 17:28:00 +02:00
Vincent Koc
d358294f89 test(plugins): anchor provider family inventory to source roots 2026-06-03 17:20:10 +02:00
Vincent Koc
3480832614 test(ui): defer control ui vite import 2026-06-03 08:13:30 -07:00
Vincent Koc
e0ab71d3dc fix(scripts): guard codex protocol generation disk headroom 2026-06-03 17:01:16 +02:00
Vincent Koc
21b262f507 fix(e2e): fail timed rpc commands 2026-06-03 16:48:50 +02:00
Vincent Koc
3a64302585 test(canvas): cover A2UI static asset compatibility 2026-06-03 16:42:55 +02:00
Vincent Koc
38f1db6d67 fix(e2e): rethrow lifecycle shutdown promptly 2026-06-03 16:36:37 +02:00
Vincent Koc
8f6f2617ec test(vitest): extend full agentic watchdog 2026-06-03 07:35:39 -07:00
Vincent Koc
f4868b79e3 fix(testing): keep plugin gauntlet pnpm noninteractive 2026-06-03 16:34:54 +02:00
Vincent Koc
d3ab7e92ef fix(ci): harden ARM smoke and browser checks 2026-06-03 07:30:12 -07:00
Vincent Koc
acacd32415 test(codex): cover bad dynamic tool schemas 2026-06-03 16:20:49 +02:00
Ayaan Zaidi
0b26a1bca7 fix(telegram): cancel clean restart stop timers 2026-06-03 19:49:12 +05:30
Ayaan Zaidi
0bcdb9c0d1 refactor(telegram): distill polling restart stops 2026-06-03 19:49:12 +05:30
Andy Ye
946eed685d fix(telegram): slow polling restart storms 2026-06-03 19:49:12 +05:30
Vincent Koc
c219c62598 refactor(gateway): share duplicated test helpers
Consolidate repeated gateway test setup into shared helpers and keep the preauth WebSocket fixture bounded with maxPayload.\n\nVerification: focused gateway Vitest passed, autoreview clean, and ready-state GitHub Actions CI passed on c6f6957e55.
2026-06-03 06:57:18 -07:00
Pavan Kumar Gondhi
5483ff705f fix(telegram): require admin for target writeback [AI] (#88973)
* fix: require admin for Telegram target writeback

* fix(telegram): preserve internal target writeback

* fix: scope Telegram target writeback authority

* fix: infer internal writeback for durable sends

* fix: preserve scoped Telegram writeback boundaries

* fix: preserve direct Telegram writeback

* test: make Telegram writeback scope intent explicit

* fix(telegram): keep target writeback authority local

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-06-03 19:25:40 +05:30
Vincent Koc
70a989a97a test(e2e): tighten onboard status assertions 2026-06-03 15:54:03 +02:00
Vincent Koc
b7450f83a1 ci(docker): disable alpha image publishes 2026-06-03 06:46:42 -07:00
Vincent Koc
ff5667a582 fix(installer): fail on onboarding exit code 2026-06-03 15:39:31 +02:00
Vincent Koc
d6bea4c5ac fix(e2e): clean clawhub install temp home 2026-06-03 15:30:02 +02:00
clawsweeper[bot]
79896a24d9 fix(outbound): keep channel send durable when transcript mirror fails (#89626) (#89812)
Summary:
- The PR wraps outbound post-delivery transcript mirroring in warning-only error handling and adds regression tests for thrown and not-ok mirror append failures.
- PR surface: Source +16, Tests +61. Total +77 across 2 files.
- Reproducibility: yes. A high-confidence source reproduction is to make appendAssistantMessageToSessionTransc ... a/outbound/deliver.ts:1970 and the caller retry path treats that exception as a failed direct announcement.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(outbound): keep channel send durable when transcript mirror fails…

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

Prepared head SHA: dfe0fd7119
Review: https://github.com/openclaw/openclaw/pull/89812#issuecomment-4611974387

Co-authored-by: harjoth <harjoth.khara@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-06-03 13:20:52 +00:00
Vincent Koc
a7d5ae1872 fix(scripts): force stop memory fd gateway child 2026-06-03 15:19:29 +02:00
Vincent Koc
446a2b24c3 fix(e2e): require kitchen sink command rss samples 2026-06-03 15:11:40 +02:00
jmao
e4993ec00f fix(telegram): prevent preview duplication in partial and block streaming modes
Fix Telegram streamed replies so preview chunks are finalized once in partial and block streaming modes.

Fixes #87624. Thanks @jmao0001.
2026-06-03 18:36:08 +05:30
Vincent Koc
90493ee8e2 fix(scripts): stop rpc rtt process groups 2026-06-03 15:03:32 +02:00
zhang-guiping
60dcaa3cf5 fix #88773: [Bug]: Telegram DM exec requires approval despite allowlist + ask:off — works in webchat, not in Telegram (#89035)
* fix exec ask policy source

* fix gateway test type fixtures

* docs: update exec ask parameter docs to match runtime behavior

* fix: preserve trusted per-call exec ask hardening while blocking model-supplied overrides for channel runs

* docs: align exec ask contract with runtime

* refactor(agents): simplify exec ask policy cleanup

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-06-03 18:33:08 +05:30
Ayaan Zaidi
b3b203bf67 test(telegram): simplify preview race harness 2026-06-03 18:28:13 +05:30
张贵萍0668001030
0a4927d0b8 fix(telegram): retain preview on generation race 2026-06-03 18:28:13 +05:30
clawsweeper[bot]
a61c94b1f1 fix(feishu): wire setup runtime setter (#89814)
Summary:
- The PR adds a narrow Feishu runtime-setter entrypoint, wires it into the Feishu setup entry, and adds regression coverage for setup-only runtime registration.
- PR surface: Source +7, Tests +22. Total +29 across 4 files.
- Reproducibility: yes. source inspection gives a high-confidence reproduction path: current Feishu setup-only ... ate when that setter is present. I did not run a live Feishu tenant message repro in this read-only review.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(feishu): wire setup runtime setter

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

Prepared head SHA: befd074ca6
Review: https://github.com/openclaw/openclaw/pull/89814#issuecomment-4612032021

Co-authored-by: Glenn-Agent <glenn_agent@163.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-06-03 12:36:42 +00:00
Vincent Koc
a9f099d279 test(qa): require channel scenario markers 2026-06-03 14:27:25 +02:00
Vincent Koc
2fa60af960 test(vitest): make channel helper config runnable 2026-06-03 05:23:44 -07:00
clawsweeper[bot]
07006943de fix(telegram): isolate verbose status after streamed finals (#89813)
Summary:
- The branch updates Telegram dispatch so a verbose/status final arriving after a streamed final answer uses a fresh answer-lane message, with default and progress-mode regression tests.
- PR surface: Source +14, Tests +52. Total +66 across 2 files.
- Reproducibility: yes. The linked bug report gives a concrete Telegram `/reset`, `/v on`, short-prompt path, and source inspection shows current main can route a second final payload through the finalized answer lane.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(telegram): isolate verbose status after streamed finals

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

Prepared head SHA: 4d476a957f
Review: https://github.com/openclaw/openclaw/pull/89813#issuecomment-4612006920

Co-authored-by: kesslerio <martin@kessler.io>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-06-03 12:21:08 +00:00
Vincent Koc
9dc1694eb7 test: lengthen ARM contracts shard watchdog 2026-06-03 05:05:35 -07:00
Vincent Koc
98ff56d70e perf(ui): trace chat send server milestones
Add operator-only Control UI chat send timing milestones across gateway dispatch, model selection, agent-run start, dispatch completion, and post-dispatch completion. The Control UI records these server phases into the existing chat send timing buffer, and the gateway broadcast guard now scopes the new timing event with other read-visible chat events.
2026-06-03 05:02:06 -07:00
Vincent Koc
03ccdb9fbc test(e2e): assert mcp reconnect temp state 2026-06-03 13:59:34 +02:00
Vincent Koc
6d7b80fa1c test(gateway): shard default gateway vitest config 2026-06-03 04:57:27 -07:00
clawsweeper[bot]
409d1a7135 fix(agents): release session write lock if fence read throws on prompt release (#89811)
Summary:
- The PR makes prompt-release fence bookkeeping exception-safe so the session write lock is released even when fence reads throw, and adds a regression test for that path.
- PR surface: Source +6, Tests +27. Total +33 across 2 files.
- Reproducibility: yes. source-reproducible with provided real-output proof: current main clears `heldLock` be ... ire timing out after an injected `EIO`. I did not run the harness locally because this review is read-only.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(agents): release session write lock if fence read throws on promp…

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

Prepared head SHA: 394d978437
Review: https://github.com/openclaw/openclaw/pull/89811#issuecomment-4611966479

Co-authored-by: Spencer Fuller <spencer.p.fuller@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-06-03 11:51:43 +00:00
Vincent Koc
d31f4e2d62 fix(e2e): stop interrupted docker builds 2026-06-03 13:48:31 +02:00
Ayaan Zaidi
e5e6cf04a2 fix(android): hide nav under command palette 2026-06-03 17:02:10 +05:30
Ayaan Zaidi
4f8740029a refactor(android): distill companion shell cleanup 2026-06-03 17:02:10 +05:30
Tosko4
9159b3bf8e Improve Android companion-first shell UX 2026-06-03 17:02:10 +05:30
Vincent Koc
eddf1c776d test(e2e): require kitchen sink tool coverage 2026-06-03 13:25:50 +02:00
Vincent Koc
6ec579a0c2 docs(web): document chat ack timing metadata (#89802) 2026-06-03 04:18:51 -07:00
Vincent Koc
87eaac4010 fix(e2e): bound image auth mock bodies 2026-06-03 13:15:51 +02:00
Val Alexander
529282dcff fix(ui): harden Workboard dialog accessibility
Harden Workboard modal and drawer accessibility.

Summary:
- Add Workboard dialog focus lifecycle handling for initial focus, Tab/Shift+Tab containment, Escape close, and opener restore.
- Mark Workboard background content inert/aria-hidden while modal or drawer dialogs are active.
- Add focused unit and Chromium browser smoke coverage for the audited modal/drawer accessibility requirements.
- Keep UI browser test aliases able to resolve shared workspace packages used by the Workboard view.

Verification:
- node scripts/run-vitest.mjs ui/src/ui/views/workboard.test.ts
- node scripts/run-vitest.mjs ui/src/ui/views/workboard.browser.test.ts
- (cd ui && pnpm exec vitest run --config vitest.config.ts --project browser src/ui/views/workboard.browser.test.ts)
- GitHub checks green at 6557012430
2026-06-03 06:14:40 -05:00
Vincent Koc
b1fccd0605 perf(ui): surface chat ack server timing (#89801) 2026-06-03 04:11:14 -07:00
Vincent Koc
287dee4593 fix(e2e): settle credential shutdown promptly 2026-06-03 13:01:58 +02:00
Vincent Koc
b96c0d932f test(codex): stabilize app-server startup races 2026-06-03 03:48:45 -07:00
Vincent Koc
a46181f168 test: stabilize timing-sensitive ARM suites 2026-06-03 03:47:48 -07:00
Vincent Koc
1b5cb4a0d3 fix(e2e): bound clickclack fixture bodies 2026-06-03 12:45:59 +02:00
Vincent Koc
9947a26768 test(ui): cover control chat send timing phases 2026-06-03 03:44:44 -07:00
Vincent Koc
2accf3875b test(e2e): assert channel credential fields 2026-06-03 12:25:14 +02:00
Vincent Koc
76c8b36031 fix(e2e): stop tracked process groups 2026-06-03 12:17:05 +02:00
Vincent Koc
44fea3c94a fix(tooling): cancel oversized audit responses 2026-06-03 12:05:39 +02:00
Vincent Koc
c68938c19e perf(gateway): overlap chat catalog startup
Start optional model catalog loading earlier during chat history/startup hydration so catalog discovery overlaps history projection without changing the metadata contract. The response still awaits catalog-backed session/default/agents metadata before replying.

Verification:
- git diff --check
- autoreview local caught and rejected the short-timeout variant; fixed to overlap-only
- autoreview commit clean
- Testbox tbx_01kt6edf5d328vqr43epy0cs0b targeted gateway/UI shards passed
- Testbox tbx_01kt6eh4fk409g4ar1kpa0edhz check:changed lanes core, coreTests passed
2026-06-03 03:02:47 -07:00
Vincent Koc
a7c8b2a46a fix(e2e): bound mock readiness probes 2026-06-03 11:58:45 +02:00
Vincent Koc
5a0d9d6326 fix(codex): retire abandoned app-server startups 2026-06-03 02:55:12 -07:00
Vincent Koc
7cee0bca0b fix(e2e): isolate plugin lifecycle artifacts 2026-06-03 11:50:33 +02:00
Vincent Koc
7074cf8e23 perf(ui): label delayed chat sends in telemetry (#89777) 2026-06-03 02:41:58 -07:00
Vincent Koc
26301f318f fix(ui): scroll pending sends into view 2026-06-03 02:30:22 -07:00
Vincent Koc
f49f5973b0 perf(ui): start chat refresh before bootstrap
Start the active Control UI chat refresh after Gateway hello without waiting for the slower bootstrap fetch. Keep startup canvas embeds fail-closed until bootstrap config arrives, and recreate preview iframes when sandbox policy changes.
2026-06-03 02:27:25 -07:00
Vincent Koc
1e4ff80604 fix(e2e): clean failed tarball extracts 2026-06-03 11:18:54 +02:00
Vincent Koc
84dca54ef2 fix(e2e): fail package worktree cleanup leaks 2026-06-03 11:12:02 +02:00
Vincent Koc
4a67e4b976 fix(test): avoid empty script changed runs 2026-06-03 11:05:04 +02:00
Ayaan Zaidi
41ee6b1dd6 feat(telegram): show commentary in progress drafts 2026-06-03 14:30:30 +05:30
Ayaan Zaidi
04f93c2fb4 refactor(channels): share progress draft primitives 2026-06-03 14:30:30 +05:30
Vincent Koc
3cdb87be86 fix(test): route parallels helper changes 2026-06-03 10:57:44 +02:00
Onur Solmaz
17a285f298 fix(ui): preserve visible chat stream text
Fix WebChat stream/history reconciliation so visible assistant text survives stale history reloads, tool-history catch-up, and terminal final/error/abort events.\n\nRefactors the UI path into stream reconciliation, stream text, and typed tool-message helpers so persisted history and live stream state use the same matching rules.\n\nCloses #67035.
2026-06-03 16:56:33 +08:00
zhang-guiping
c2d7b4a486 fix(ui): clear chat stream before terminal commits
Fix the Control UI WebChat race where terminal assistant messages could be committed while chatStream was still live, causing history and active stream to render the same reply twice. Terminal final/aborted handling now snapshots fallback text, clears the active run/stream through the lifecycle owner, then appends the visible assistant message.\n\nFixes #71992.\n\nVerification: node scripts/run-vitest.mjs run ui/src/ui/controllers/chat.test.ts ui/src/ui/chat/run-lifecycle.test.ts ui/src/ui/chat/build-chat-items.test.ts; node scripts/run-vitest.mjs run ui/src/ui/app-chat.test.ts ui/src/ui/controllers/sessions.test.ts; node scripts/run-vitest.mjs run --config test/vitest/vitest.ui-e2e.config.ts --configLoader runner ui/src/ui/e2e/chat-flow.e2e.test.ts; Blacksmith Testbox tbx_01kt6a4zn7awkdy12d6b0q2d1q / run 26873514898; autoreview clean; PR CI 121 pass / 10 skipped.
2026-06-03 01:45:59 -07:00
zhang-guiping
0b98aea71a fix(ui): reconcile completed chat sends
Fixes #87699.\n\nRoutes ACK-completed Control UI chat sends through the existing run lifecycle reconciliation path so stale selected-session rows cannot re-enable the composer/Stop state after the conversation has already completed.\n\nVerification: focused UI/unit tests, Control UI E2E chat-flow test, autoreview clean, Testbox changed gate tbx_01kt68xvz17fcnmd3wj6f7pk6f, and PR CI run 26872484363 green after failed-job rerun for transient runner setup failures.
2026-06-03 01:34:13 -07:00
Vincent Koc
114864185b fix(e2e): fail kitchen sink cleanup leaks 2026-06-03 10:28:19 +02:00
Ayaan Zaidi
1bd1483b62 refactor(auto-reply): unify transient failure visibility 2026-06-03 13:55:36 +05:30
FullerStackDev
a5ef086e3c test(auto-reply): cover channel-agnostic failure routing 2026-06-03 13:55:36 +05:30
FullerStackDev
a10faca06f fix(auto-reply): surface fatal channel errors 2026-06-03 13:55:36 +05:30
Vincent Koc
380a8f140e fix(e2e): fail rpc rtt cleanup leaks 2026-06-03 10:20:22 +02:00
Vincent Koc
34c3827290 fix(e2e): close rpc rtt gateway log handles 2026-06-03 10:10:39 +02:00
Vincent Koc
54fe0e7f71 fix(e2e): keep cleanup retries covered 2026-06-03 10:10:39 +02:00
Yzx
932d6ea8e5 fix(webchat): show sessions_send handoffs as forwarded
Fix WebChat display projection for sessions_send inter-session handoffs. Forwarded messages now render assistant-side with source attribution while keeping transcript user-role semantics, stripping generated inter-session envelopes from display text, and preserving heartbeat/TTS/message-tool cleanup boundaries. Fixes #89161.
2026-06-03 01:09:45 -07:00
Vincent Koc
d004b80c91 fix(e2e): surface secret proof cleanup failures 2026-06-03 09:48:54 +02:00
Vincent Koc
5820378b90 fix(e2e): isolate telegram package artifacts 2026-06-03 09:43:16 +02:00
Vincent Koc
d5df1a1cd6 fix(e2e): isolate multi-node artifacts 2026-06-03 09:36:43 +02:00
Vincent Koc
175cfe4846 fix(gateway): stabilize webchat prompt cache affinity
Keep WebChat run/idempotency ids per message while threading a stable hashed promptCacheKey through chat.send into embedded runs. Fixes #89139.
2026-06-03 00:33:02 -07:00
Alexzhu
85e5d486df perf(control-ui): render chat history incrementally
Render dashboard chat history incrementally; preserve Talk settings callback contracts, native Talk select labels, and raw-copy baseline after rebase.
2026-06-03 00:16:32 -07:00
Vincent Koc
b6cee3fc35 fix(scripts): clean run-with-env process groups 2026-06-03 09:10:09 +02:00
Dallin Romney
d48b9274d8 fix: report gateway health auth diagnostics (#89337)
* fix: handle gateway health credential errors

* fix: diagnose gateway health credential state
2026-06-03 00:04:47 -07:00
Vincent Koc
6d788a237c fix(ci): isolate ARM Testbox workflow 2026-06-03 00:04:12 -07:00
Vincent Koc
7ccbffcb1b fix(testing): bound rpc readiness probes 2026-06-03 08:46:17 +02:00
Vincent Koc
2c92973398 fix(release): bound cross-os discord fetches 2026-06-03 08:35:14 +02:00
Vincent Koc
ed4c4afc0f fix(release): bound candidate GitHub requests 2026-06-03 08:19:03 +02:00
Vincent Koc
a462601f05 fix(e2e): isolate release journey artifacts 2026-06-03 08:08:44 +02:00
Vincent Koc
f472778717 fix(codex): close startup client on timeout 2026-06-02 23:04:41 -07:00
Vincent Koc
7c1a83ff2e fix(build): externalize optional baileys image backends 2026-06-03 07:50:25 +02:00
Vincent Koc
f8fcb35064 fix(ui): lazy load usage dashboard 2026-06-03 07:41:43 +02:00
Vincent Koc
c0b05a2100 perf(control-ui): coalesce chat metadata startup
Add a coalesced chat.metadata Gateway method so the Control UI can fetch model and command metadata without blocking a clean first message path. Reuses existing models/commands builders, keeps compatibility fallback for older gateways, updates protocol artifacts, and adds focused gateway/UI/e2e coverage.
2026-06-02 22:34:54 -07:00
Ayaan Zaidi
2a512025ad feat(telegram): compose progress draft reasoning 2026-06-03 10:54:19 +05:30
Ayaan Zaidi
7f79bd8683 refactor(discord): use shared progress compositor 2026-06-03 10:54:19 +05:30
Ayaan Zaidi
a4b09d72b9 refactor(channels): share progress draft compositor 2026-06-03 10:54:19 +05:30
Dallin Romney
58160094e8 fix: allowlist pending agent sqlite scaffold (#89705) 2026-06-02 22:22:13 -07:00
Dallin Romney
c0c4156b6d fix(exec): reject corrupt shell snapshots (#89701) 2026-06-02 21:58:28 -07:00
Vincent Koc
3f66797578 Merge branch 'main' of https://github.com/openclaw/openclaw
* 'main' of https://github.com/openclaw/openclaw:
  fix(ci): trim docker e2e heartbeat latency
2026-06-02 21:57:21 -07:00
Vincent Koc
f02c1209aa fix(ui): narrow workboard dependency fixtures 2026-06-02 21:56:51 -07:00
Vincent Koc
5056dd47ca chore(scripts): add gateway rpc rtt probe 2026-06-02 21:56:51 -07:00
Vincent Koc
97dde19577 test(extensions): reset fake timers before tests 2026-06-02 21:56:51 -07:00
Vincent Koc
7cbdebc4ed feat(ui): tighten workboard card operations 2026-06-02 21:56:50 -07:00
Vincent Koc
17795c6c4c fix(ci): trim docker e2e heartbeat latency 2026-06-03 06:54:52 +02:00
Vincent Koc
6b25b78800 fix(ci): show docker build heartbeats 2026-06-03 06:36:06 +02:00
Vincent Koc
78b3f60dbd fix(ci): reset crabbox pnpm hydrate state 2026-06-03 05:33:59 +02:00
Ayaan Zaidi
8f1ae5967e fix(discord): sanitize tool progress scaffolding 2026-06-03 08:03:57 +05:30
Ayaan Zaidi
d82bfcecb1 fix(discord): cover compact gh failure traces 2026-06-03 08:03:57 +05:30
FullerStackDev
5629c44547 fix(discord): preserve channel-label suppression 2026-06-03 08:03:57 +05:30
FullerStackDev
a8bf14da84 fix(discord): suppress internal agent failure traces 2026-06-03 08:03:57 +05:30
Ayaan Zaidi
a9f014e9df refactor(telegram): fold reset boundary lookup 2026-06-03 08:01:57 +05:30
Ted Li
d76f2c0c3b perf: avoid broad Telegram reset boundary scan 2026-06-03 08:01:57 +05:30
Vincent Koc
f2a46b0661 fix(tooling): bound deadcode knip subprocesses 2026-06-03 03:47:27 +02:00
Vincent Koc
0fa384c6f6 fix(tooling): run knip through pnpm package dlx 2026-06-03 02:52:16 +02:00
Vincent Koc
6d643ccd11 fix(tooling): reject malformed release command limits 2026-06-03 02:52:16 +02:00
Gabriel F.
8b546facaf fix(outbound): stop schema-padded poll modifiers from blocking send (#89601)
Summary:
- The PR changes shared poll-intent detection so `pollDurationHours` and `pollMulti` alone no longer make `send` actions fail, with focused unit and outbound validation coverage.
- PR surface: Source -2, Tests +40. Total +38 across 3 files.
- Reproducibility: yes. Source inspection shows current main and `v2026.5.28` expose `pollDurationHours` throu ... d message schema, classify non-zero shared duration as poll intent, and throw before a `send` can dispatch.

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

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

Prepared head SHA: 0fd95756cd
Review: https://github.com/openclaw/openclaw/pull/89601#issuecomment-4606487310

Co-authored-by: Gabriel Fratica <gabriel@codez.ro>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-06-03 00:30:02 +00:00
Vincent Koc
1f35ad12b3 fix(test): reject malformed parallels smoke limits 2026-06-03 02:19:49 +02:00
Vincent Koc
3d4d30fd5a fix(release): reject malformed beta smoke limits 2026-06-03 02:06:40 +02:00
Vincent Koc
dd46fd36a3 fix(tooling): reject malformed cross-os release timeouts 2026-06-03 01:59:48 +02:00
Vincent Koc
85633eb615 chore(tooling): drop stale deadcode allowlist entries 2026-06-03 01:49:25 +02:00
Vincent Koc
2a3421a0da fix(tooling): reject malformed crabbox sync limits 2026-06-03 01:07:41 +02:00
Vincent Koc
e38b8f6a20 fix(test): reject malformed cron cleanup limits 2026-06-03 00:07:24 +02:00
Gio Della-Libera
646974b7d8 fix(policy): reject unsupported policy keys (#87074)
Merged via squash.

Prepared head SHA: 3ab4ff1d8f
Co-authored-by: giodl73-repo <235387111+giodl73-repo@users.noreply.github.com>
Co-authored-by: giodl73-repo <235387111+giodl73-repo@users.noreply.github.com>
Reviewed-by: @giodl73-repo
2026-06-02 15:01:57 -07:00
Vincent Koc
a86a1de849 fix(tooling): reject malformed tsdown watchdog limits 2026-06-02 23:43:09 +02:00
Val Alexander
be336cc1e4 feat(ui): add workboard keyboard movement controls
Add compact keyboard-accessible Workboard status movement controls for writable operators. The control reuses the existing workboard.cards.move path, preserves drag/drop as the pointer enhancement, and suppresses mutation controls for read-only operators.\n\nVerification:\n- node scripts/run-vitest.mjs ui/src/ui/views/workboard.test.ts\n- corepack pnpm exec oxfmt --check --threads=1 ui/src/ui/views/workboard.ts ui/src/ui/views/workboard.test.ts ui/src/styles/workboard.css docs/plugins/workboard.md\n- git diff --check origin/main...HEAD\n- Chromium Control UI mock Gateway keyboard movement proof\n- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main --no-web-search
2026-06-02 16:08:29 -05:00
Vincent Koc
8cecf2c7ea fix(test): reject malformed local check limits 2026-06-02 22:48:12 +02:00
Vincent Koc
6af047c7f6 fix(test): reject malformed boundary prep timeouts 2026-06-02 22:26:15 +02:00
Vincent Koc
ac8338bb02 fix(tooling): reject malformed topology limits 2026-06-02 22:19:10 +02:00
Vincent Koc
0188c541de fix(test): reject malformed extension boundary concurrency 2026-06-02 22:12:01 +02:00
Vincent Koc
97509ed1d7 fix(test): reject malformed extension batch parallelism 2026-06-02 22:05:44 +02:00
Vincent Koc
432a5978b9 fix(test): reject malformed extension shard counts 2026-06-02 21:59:42 +02:00
Vincent Koc
5f6a8083bf fix(perf): reject malformed cpuprofile limits 2026-06-02 21:53:34 +02:00
Vincent Koc
36d7ac31c2 fix(ci): reject malformed ci timing limits 2026-06-02 21:47:28 +02:00
Vincent Koc
aed3743630 fix(docker): reject malformed timing limits 2026-06-02 21:38:21 +02:00
Vincent Koc
28b1ea7c0d fix(test): reject malformed group report numeric flags 2026-06-02 21:31:16 +02:00
Vincent Koc
661c763b28 fix(docs): reject malformed mdx max error limits 2026-06-02 21:25:23 +02:00
Vincent Koc
36a596aa9f fix(ci): reject malformed targeted docker group size 2026-06-02 21:18:52 +02:00
Michael Appel
c208a10619 Harden node exec approval precheck env [AI] (#81488)
* fix: align node exec approval precheck env

* addressing ci

* fix: preserve node allow-always prechecks

* fix: finalize node exec approval port

* fix: align node prepare approval env

* test: tighten node marker reuse coverage proof

* test: fix node allow-always coverage mock typing

---------

Co-authored-by: Devin Robison <drobison@nvidia.com>
Co-authored-by: Devin Robison <drobison00@users.noreply.github.com>
2026-06-02 13:15:41 -06:00
Vincent Koc
e59e65be67 fix(test): reject malformed boundary check env 2026-06-02 21:12:42 +02:00
Vincent Koc
054e734e53 fix(lint): reject malformed oxlint shard env 2026-06-02 21:06:14 +02:00
Vincent Koc
d007b9aba3 fix(test): reject malformed full-suite parallel env 2026-06-02 20:59:02 +02:00
Vincent Koc
5d4868c036 fix(scripts): validate gateway watch numeric options 2026-06-02 20:36:46 +02:00
Vincent Koc
8bf6206a3e test(rpc): enforce kitchen sink command rss ceiling 2026-06-02 20:09:10 +02:00
Gio Della-Libera
1d3cfc4b01 Policy: add data handling conformance checks (#87056)
Merged via squash.

Prepared head SHA: 6a0e9730aa
Co-authored-by: giodl73-repo <
>
Co-authored-by: giodl73-repo <235387111+giodl73-repo@users.noreply.github.com>
Reviewed-by: @giodl73-repo
2026-06-02 10:48:07 -07:00
Vincent Koc
1ff2ffa160 chore(scripts): drop legacy moltbot rpc alias 2026-06-02 19:37:07 +02:00
Vincent Koc
d07ba5f265 fix(providers): avoid custom provider runtime fanout 2026-06-02 19:23:38 +02:00
Vincent Koc
f789081bae test(gateway): abort accepted agent run in e2e 2026-06-02 18:12:54 +02:00
Vincent Koc
388dc56ba5 test(gateway): defer sidecars in tools invoke e2e 2026-06-02 17:41:19 +02:00
Vincent Koc
6c7644268f fix(test): stabilize ARM extension timer tests 2026-06-02 07:53:25 -07:00
Peter Steinberger
c8d21fe7f0 fix: recover suspicious gateway startup configs (#89480) 2026-06-02 10:12:35 -04:00
Bryan Tegomoh, MD, MPH
00d846daf7 fix(kimi): strip anthropic cache markers
Closes #76612

Co-authored-by: Bryan Tegomoh <bryan.tegomoh@gmail.com>
2026-06-02 09:59:36 -04:00
Shakker
1b9860aa56 fix: restore Skill Workshop view switcher 2026-06-02 14:59:19 +01:00
Peter Steinberger
97d4d5effb docs(changelog): note update repair stall handling 2026-06-02 14:57:01 +01:00
Peter Steinberger
12c6ef6d57 fix(update): keep plugin repair fetch failures nonblocking 2026-06-02 14:55:55 +01:00
Vincent Koc
96277245dc fix(test): isolate gateway CPU QA state 2026-06-02 15:27:16 +02:00
Peter Steinberger
eef24d452f fix(models): preserve provider prompt cache boundaries
Split Anthropic system prompts at the cache boundary so only stable prefixes get cache_control, strip the internal marker when cache control is disabled, and keep OpenAI-compatible Anthropic cache-control routes from caching dynamic suffixes.\n\nFixes #89386.
2026-06-02 09:19:52 -04:00
Peter Steinberger
c3baec7136 docs: clarify autoreview follow-up scope 2026-06-02 06:15:51 -07:00
Coder
4bb86877e2 fix(google): forward Gemini stop sequences
Forward configured stop sequences to Gemini generationConfig.stopSequences in the bundled Google transport, matching the shared Google provider behavior and the @google/genai request contract.\n\nThanks @coder999999999.
2026-06-02 09:02:27 -04:00
Coy Geek
3509f7613e fix: audit and repair hooks token reuse with Gateway auth
Keep startup non-breaking for existing installs when hooks.token reuses Gateway auth, but surface a startup warning, critical security audit finding, and doctor --fix repair that rotates persisted hooks.token.

Closes #87376.

Co-authored-by: Coy Geek <65363919+coygeek@users.noreply.github.com>
2026-06-02 08:58:40 -04:00
Vincent Koc
36c1a3e006 fix(memory): avoid optional vector status dereference 2026-06-02 14:53:35 +02:00
Vincent Koc
212eaead01 fix(memory): force provider-none indexes to FTS-only vectors 2026-06-02 14:53:35 +02:00
Vincent Koc
984c3ded9a fix(scripts): avoid dead child assignment in fd repro 2026-06-02 14:53:35 +02:00
Vincent Koc
0b7c94a5e1 fix(memory): initialize provider-none lifecycle during sync 2026-06-02 14:53:35 +02:00
Vincent Koc
0b61add479 fix(memory): report provider-none probes as FTS-only 2026-06-02 14:53:35 +02:00
Vincent Koc
2d11402208 fix(scripts): avoid spread in runtime output collection 2026-06-02 14:53:35 +02:00
Vincent Koc
f6e8a1b2a8 fix(scripts): clean memory fd temp dirs after preindex failures 2026-06-02 14:53:35 +02:00
Vincent Koc
5a4f868de0 fix(memory): scope provider-none FTS bypass 2026-06-02 14:53:34 +02:00
Vincent Koc
4115f0c82f fix(scripts): keep watch proof asset copies out of idle window 2026-06-02 14:53:34 +02:00
Vincent Koc
cd0af35e5c fix(memory): keep FTS-only sync offline 2026-06-02 14:53:34 +02:00
Alix-007
1824aa07a0 fix(mistral): enable prompt cache keys
Enable Mistral prompt cache keys without long-retention forwarding. Update cached-read pricing and doctor migration for existing Mistral provider config. Fixes #83709.
2026-06-02 08:52:12 -04:00
Peter Steinberger
5259fa4495 fix(llm): keep OpenAI-compatible reasoning streams active 2026-06-02 08:40:03 -04:00
Peter Steinberger
2ffeca1d78 docs: document Android notification picker helpers 2026-06-02 08:38:23 -04:00
NVIDIAN
895dccd058 fix(agents): gate finalize hooks before delivery
Run `before_agent_finalize` for embedded agents before terminal delivery so revise decisions can retry without leaking a final assistant reply.

The embedded subscription now defers terminal assistant events, block replies, and lifecycle delivery until the pre-terminal gate resolves; accepted revise decisions suppress delivery, while hook failures and continue decisions finalize normally. It also preserves existing replay-invalid liveness behavior while still preventing revise after side-effecting turns.

Closes #87585

Co-authored-by: ai-hpc <mail.speedy.hpc@hotmail.com>
2026-06-02 08:27:36 -04:00
Peter Steinberger
06434d85a0 fix(llm): gate OpenAI-compatible reasoning output
Replaces #89343 because the contributor fork did not allow maintainer edits.

Co-authored-by: zz327455573 <327455573@qq.com>
2026-06-02 08:24:34 -04:00
Peter Steinberger
a326faa10c fix: recover corrupt managed npm installs 2026-06-02 05:21:19 -07:00
Peter Steinberger
6467ddd7ed fix(qqbot): migrate state stores to sqlite kv
Move QQBot credential backups, gateway sessions, known-user records, and ref-index rows into plugin SQLite KV stores. Import shipped JSON/JSONL state files on first use and keep auxiliary known-user/ref-index state best-effort so message delivery is not blocked by cache persistence failures.
2026-06-02 08:15:19 -04:00
Peter Steinberger
95880ae21c fix: align auth health status after Codex sidecar merge 2026-06-02 05:14:52 -07:00
Vincent Koc
d830e4affc fix(testing): probe plugin CLI help while installed 2026-06-02 14:01:18 +02:00
兰之
10d10faa25 feat(plugin-sdk): add resolve_exec_env hook
Summary:
- Add the plugin SDK `resolve_exec_env` hook for bounded exec environment contributions.
- Wire resolved exec env through exec preparation/final execution without exposing plugin env values to generic tool hooks.
- Cover lazy exec loading, host and command rewrites, node/gateway execution, filtering, and EXEC shell snapshot cache behavior.

Verification:
- `pnpm changed:lanes --json`
- `node scripts/run-vitest.mjs src/agents/bash-tools.exec.resolve-env-hook.test.ts src/agents/agent-tool-definition-adapter.test.ts src/agents/agent-tool-definition-adapter.after-tool-call.test.ts src/agents/shell-snapshot.test.ts src/plugins/hook-resolve-exec-env.test.ts`
- `pnpm check:test-types`
- `pnpm lint src/agents/bash-tools.exec.ts src/agents/bash-tools.exec.resolve-env-hook.test.ts`
- `.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main`
- PR CI clean on 1bbad8d071: https://github.com/openclaw/openclaw/actions/runs/26817910293

Co-authored-by: Lanzhi <lizhan3@xiaomi.com>
2026-06-02 08:00:42 -04:00
Andy Ye
e992af4b6e fix: surface unresolved OAuth sidecar auth failures
Surface stale Codex OAuth sidecar references as unresolved auth failures in auth health, model status, and gateway status instead of hiding them as generic missing auth.

Also refresh the running gateway after doctor auth-profile repairs by reloading secrets/runtime auth snapshots and then refreshing the model auth-status cache.

Thanks @TurboTheTurtle.

Fixes #84252.
2026-06-02 07:56:14 -04:00
Yzx
b1bdc29d33 fix(providers): use native reasoning mode for Gemini instead of tagged (#89379)
* fix(providers): use native reasoning mode for direct Gemini API, keep CLI tagged

Gemini 2.5+ delivers reasoning via native thinkingParts (thinkingConfig.
includeThoughts). Having tagged mode active at the same time injects a
<think>…</think>/<final>…</final> directive into the system prompt; the
model opens a <think> block before a tool call, never closes it, and
returns an empty post-tool turn (content:[], payloads=0 error, #69220).

Fix: override resolveReasoningOutputMode in buildGoogleProvider() only —
not in the shared GOOGLE_GEMINI_PROVIDER_HOOKS. The Gemini CLI backend
(google-gemini-cli) runs gemini --output-format json and parses a text
response field, not native thought parts; it must stay on tagged mode.
A regression test confirms google-gemini-cli remains "tagged".

Also remove the dead BUILTIN_REASONING_OUTPUT_MODES entry keyed on
"google-generative-ai" from provider-utils.ts — that string is only
ever the transport model.api value, never the provider id passed to
resolveReasoningOutputMode, so the map was unreachable.

Fixes #69220

* docs: clarify Gemini reasoning output modes

* fix(google): keep Antigravity reasoning tagged

* fix(google): default direct reasoning checks to native

* fix(google): import reasoning context from plugin entry

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-06-02 07:46:08 -04:00
Sebastien Tardif
e7aac172d5 fix(codex): clear stale context-engine projection after overflow retry
Fixes #88355.

When a resumed Codex context-engine thread overflows and OpenClaw retries on a fresh native thread, clear the stale thread-bootstrap projection metadata from the fresh binding. This prevents later turns from treating that fresh thread as already projected when it only received the bare retry prompt.

Verification:
- Autoreview clean: no accepted/actionable findings reported.
- CI run 26717883204 green on head 5438f8ad34.
2026-06-02 07:33:48 -04:00
Vincent Koc
4b7f39e406 refactor(gateway): derive connection auth options 2026-06-02 13:24:17 +02:00
Vincent Koc
335c3a8d31 refactor(gateway): share node agent dispatch 2026-06-02 13:24:17 +02:00
Vincent Koc
fd6b3255f8 refactor(gateway): share embedding remote options 2026-06-02 13:24:17 +02:00
Dirk
355cbc5071 fix(google): add missing gemini-3.1-flash-lite to google-vertex catalog (#89400)
* fix(google): add gemini-3.1-flash-lite to provider catalog

Adds the missing gemini-3.1-flash-lite model definition to the
GOOGLE_GEMINI_TEXT_MODELS array. This resolves the ProviderFailoverError
when configuring google-vertex/gemini-3.1-flash-lite.

Fixes #89390

* test(google): cover Gemini flash lite catalog row

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-06-02 07:21:50 -04:00
Peter Steinberger
b4dfa950b5 refactor: tighten agent harness surfaces
Refactor the agent harness surface after PR #88821 by moving compaction dispatch into its own module, splitting the harness type into explicit capability interfaces, and renaming the private agent-core class declaration to `CoreAgentHarness` while preserving the exported `AgentHarness` contract.

Verification:
- `node scripts/run-vitest.mjs src/agents/harness/selection.test.ts src/agents/command/cli-compaction.test.ts src/agents/embedded-agent-runner/compact.hooks.test.ts packages/agent-core/src/agent-loop.test.ts packages/agent-core/src/harness/messages.test.ts`
- `pnpm build`
- autoreview clean
- `pnpm check:changed` passed on Testbox `tbx_01kt407hq8sv1csm287pdj3fmp`
- PR CI merge state `CLEAN`
2026-06-02 07:20:43 -04:00
Mukunda Rao Katta
2d61521bd3 fix(update): pin post-core plugin compatibility to the downgraded core version (#87914) (#87952)
* fix(update): pin post-core plugin compatibility to the downgraded core version (#87914)

* fix(update): force plugin compatibility repair on rollback

* style(update): clarify downgrade compatibility note

* fix(plugins): resolve compatible prerelease plugin downgrades

* fix(plugins): honor host gates during npm downgrade repair

* fix(plugins): keep prerelease downgrade fallback on channel

---------

Co-authored-by: Gio Della-Libera <giodl73@gmail.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-06-02 07:13:26 -04:00
Dallin Romney
30b9e123b8 fix: repeat doctor state migration repairs
Stabilize repeated `openclaw doctor --fix` state repairs for legacy plugin state and installed plugin index migrations.

- Import legacy-only plugin-state sidecar rows before deciding whether live conflicts require keeping the sidecar.
- Drop expired sidecar rows only when the sidecar can be archived, avoiding repeated false migration changes.
- Let richer current install records cover legacy records only when durable legacy fields are actually preserved, without erasing npm selector intent or malformed legacy metadata.

Proof:
- `node scripts/run-vitest.mjs src/commands/doctor-state-migrations.test.ts`
- `git diff --check origin/main...HEAD`
- `.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main`
- PR CI clean for head `5f3a7e0749372a40cabd7a090cae155997481b71`

Co-authored-by: Dallin Romney <dallinromney@gmail.com>
2026-06-02 07:13:02 -04:00
Coy Geek
a14be505ff fix(qqbot): isolate credential backups by state root
QQBot credential backups now resolve under the active OpenClaw state directory instead of the old home-global QQBot data path. This keeps isolated gateway profiles from restoring each other's QQBot appId/clientSecret backups while preserving per-state-root recovery.

Proof: focused QQBot path/storage-laziness Vitest suite passed on Node 24.15.0, focused oxlint passed, source-runtime two-root backup proof passed, exact-head CI run 26814565282 passed, and ClawSweeper re-review run 26815054980 marked proof sufficient.

Closes #84313.

Co-authored-by: Coy Geek <65363919+coygeek@users.noreply.github.com>
2026-06-02 07:11:01 -04:00
charles-openclaw
2c48dd2277 fix(sessions): preserve corrupt-header transcripts
Fixes #89037.

Co-authored-by: Charles <charles-openclaw@9bcfae.inboxapi.ai>
2026-06-02 07:02:09 -04:00
Hussein Nourelddine
4a285d529a feat(status): detect external plugin version drift
Surface active official external plugin version drift in gateway status diagnostics so users can see when a host/package update left npm or ClawHub plugins behind the running local gateway. The advisory uses the daemon service install records, compares against the running gateway version, gives detailed fix commands in deep status, and avoids local-state drift checks for remote gateway mode or explicit status probe URLs.

Co-authored-by: Hussein Nourelddine <hussein@gptc.com.kw>
2026-06-02 06:59:23 -04:00
Vincent Koc
07821e4bb8 refactor(gateway): share secret ref input resolution 2026-06-02 12:52:02 +02:00
Vincent Koc
4bae78858f refactor(gateway): share runtime service helpers 2026-06-02 12:52:02 +02:00
Andy Ye
1db2c2a3e0 Treat soft plugin repair warnings as nonfatal (#84431)
* Treat soft plugin repair warnings as nonfatal

* fix: scope plugin repair convergence failures

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-06-02 06:51:11 -04:00
NVIDIAN
eb417bc672 fix(messages): preserve inbound audio for message-tool TTS
Preserve inbound-audio context for message-tool TTS across embedded reply runs, CLI MCP loopback, and queued follow-up paths.

Thanks @ai-hpc.

Co-authored-by: ai-hpc <mail.speedy.hpc@hotmail.com>
2026-06-02 06:45:34 -04:00
Peter Steinberger
5d6216a7f1 fix: detect shrinkwrapped npm installs
Fixes status/update detection for npm-installed OpenClaw packages that ship npm-shrinkwrap while preserving pnpm and Bun install ownership.

Fixes #87732.
Supersedes #88283.

Proof: focused infra Vitest shard, autoreview clean, Crabbox install matrix, and PR CI all green.
2026-06-02 06:39:22 -04:00
Bek
bce3d5bf92 trace: Correlate channel diagnostics into one trace
Correlates channel receive, agent lifecycle, model attempt diagnostics, and outbound delivery diagnostics into one trace waterfall so channel message runs can be inspected end-to-end.

Maintainer follow-up removed the internal `AgentHarnessV2` adapter surface and kept the harness path canonical through `src/agents/harness/lifecycle.ts`.

Proof:
- PR checks passed on `04e9189c15480d53663d533a04c9883164b4dd54`.
- `node scripts/run-vitest.mjs src/agents/harness/lifecycle.test.ts src/agents/harness/selection.test.ts src/channels/turn/kernel.test.ts`
- `pnpm check:changed` Testbox `tbx_01kt3xtrm70qc7nb90cqv5rah1`

Thanks @bek91.

Co-authored-by: Bek <bek.akhmedov@gmail.com>
2026-06-02 06:38:00 -04:00
LiLan0125
ad9f7f9a59 fix(diagnostics): requeue stuck session lane after recovery
Reset the session command lane when stuck-session recovery aborts and drains a ghost embedded run but queued lane work remains. This preserves pending user messages by using the existing lane recovery pump instead of leaving them stranded after recovery reports success.

Adds focused regression coverage for the abort=true, drained=true, queuedCount=1 path.

Fixes #89208.
Supersedes #89293.
Thanks @LiLan0125.

Co-authored-by: 李兰 0668001394 <li.lan3@xydigit.com>
2026-06-02 06:36:19 -04:00
Gio Della-Libera
a25338f2b7 fix(discord): accumulate reasoning progress deltas
Fix Discord progress-mode reasoning streams so delta chunks accumulate before display formatting, preserving raw Thinking/Reasoning-prefixed content and balanced truncation.\n\nFixes #83983.\n\nThanks @giodl73-repo for the fix and live Discord proof.
2026-06-02 06:35:29 -04:00
Bek
6997453098 fix: guard in-band macOS launchd stop
Summary:
- guard macOS launchd stop/restart against in-band service relaunch loops
- centralize current-service detection for launchd stop and restart handoff
- preserve external launchd label stop overrides while fixing inherited XPC restart handoff

Verification:
- node scripts/run-vitest.mjs src/daemon/launchd.test.ts src/daemon/launchd-current-service.test.ts src/daemon/launchd-restart-handoff.test.ts
- .agents/skills/autoreview/scripts/autoreview --mode local
- pnpm check:changed via Blacksmith Testbox through Crabbox: tbx_01kt3xkmfqhnzghfxdn62fa8qm

Closes #89174

Co-authored-by: Bek <bek.akhmedov@gmail.com>
2026-06-02 06:27:36 -04:00
Vincent Koc
c35fda3cfa refactor(gateway): derive websocket runtime params 2026-06-02 12:20:48 +02:00
Vincent Koc
8ea6b5d5b2 fix(scripts): clean package-boundary prep process groups 2026-06-02 12:15:53 +02:00
NVIDIAN
a02a7aaddb fix(codex): trace app-server thread lifecycle timing
Fixes #84640.
2026-06-02 06:11:58 -04:00
Pavan Kumar Gondhi
19fb9f1299 fix: redact trajectory exports consistently (#89354)
* fix trajectory export redaction

* fix trajectory export top-level redaction

* fix trajectory export key redaction

* fix trajectory export structural key redaction
2026-06-02 15:41:44 +05:30
兰之
2664f59519 fix(cron): reject blank delivery targets
Reject whitespace-only cron delivery target strings before cron input normalization can trim and drop them, so bad delivery targets return INVALID_REQUEST instead of behaving as omitted fields.

Keep explicit null update clears for delivery, failure destination, and completion destination fields.

Co-authored-by: gaozixiang1 <gaozixiang1@xiaomi.com>
Co-authored-by: Lanzhi <lizhan3@xiaomi.com>
2026-06-02 06:10:19 -04:00
兰之
1cca70940c fix: hide sessions_spawn timeout overrides
Remove model-facing per-call timeout overrides from sessions_spawn while keeping operator-controlled timeout behavior through agents.defaults.subagents.runTimeoutSeconds.

Reject stale camelCase and snake_case timeout arguments, update ACP/native timeout propagation, refresh docs and prompt snapshots, and cap ACP runtime option timeouts to the ACP control-plane maximum without shortening gateway dispatch or registry tracking.

Proof:
- node --import tsx - runtime probe against src/agents/tools/sessions-spawn-tool.ts
- node scripts/run-vitest.mjs src/agents/tools/sessions-spawn-tool.test.ts src/agents/acp-spawn.test.ts src/agents/openclaw-tools.subagents.sessions-spawn.lifecycle.test.ts
- pnpm docs:list
- git diff --check origin/main...HEAD
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
- .agents/skills/autoreview/scripts/autoreview --mode local
- GitHub checks: 132 pass, 30 skipped

Co-authored-by: Lanzhi <lizhan3@xiaomi.com>
Co-authored-by: chenhaoqiang <chenhaoqiang@xiaomi.com>
2026-06-02 06:09:02 -04:00
兰之
43d0aaec3d fix(agents): honor provider idle timeout for unlimited runs
Honor explicit provider/model request timeoutSeconds when the agent run timeout is the no-timeout sentinel, and keep explicit run timeout overrides from being capped by agent defaults.

Verification:
- pnpm test src/agents/embedded-agent-runner/run/llm-idle-timeout.test.ts -- --reporter=verbose
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
- CI run 26812803642 passed on the rebased PR head
- Real behavior proof run 26812917801 passed after maintainer proof override

Co-authored-by: zhongqiongbo1 <zhongqiongbo1@xiaomi.com>
Co-authored-by: Lanzhi <lizhan3@xiaomi.com>
2026-06-02 06:08:56 -04:00
Vincent Koc
5487855815 refactor(gateway): share talk relay session lifecycle 2026-06-02 11:57:08 +02:00
Vincent Koc
45f7aec156 refactor(gateway): share transcript path comparison 2026-06-02 11:57:08 +02:00
Vincent Koc
286c8e3632 fix(build): parallelize startup metadata rendering 2026-06-02 11:50:49 +02:00
Vincent Koc
e24582d53c fix(crabbox): preflight sparse sync disk space 2026-06-02 11:42:14 +02:00
Vincent Koc
3e9b197bd0 test(gateway): share node invoke acknowledgement 2026-06-02 11:24:01 +02:00
Vincent Koc
601ab84f35 test(gateway): share configured global session stores 2026-06-02 11:13:36 +02:00
clawsweeper[bot]
abc3fa0396 fix(memory-core): keep startup cron retries quiet (#89075)
Summary:
- The branch adds a memory-core `startup_retry` reconciliation mode and regression tests for quiet startup retries, retry-window exhaustion, and live-config retry semantics.
- PR surface: Source +9, Tests +114. Total +123 across 2 files.
- Reproducibility: yes. from source: current main routes the first startup retry through runtime reconciliatio ... st expects the warn-level `cron service unavailable` log. I did not execute tests in this read-only review.

Automerge notes:
- Ran the ClawSweeper repair loop before final review.
- Included post-review commit in the final squash: fix(memory-core): keep startup cron retries quiet

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

Prepared head SHA: 7220f940d0
Review: https://github.com/openclaw/openclaw/pull/89075#issuecomment-4592446250

Co-authored-by: bennewell35 <newelljben@gmail.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-06-02 09:09:52 +00:00
Ayaan Zaidi
db576c4a2d refactor(agents): trim native compaction ownership follow-up 2026-06-02 14:39:35 +05:30
Cameron Beeley
5e52a9b513 docs(cli-backends): document ownsNativeCompaction opt-out contract 2026-06-02 14:39:35 +05:30
Cameron Beeley
3d7523b618 feat(agents): generalized native compaction ownership for CLI backends
Add `ownsNativeCompaction` capability to CliBackendPlugin so backends
that manage their own transcript compaction (e.g. Claude Code) can
declare it once and OpenClaw defers instead of fighting or failing.

Today only Codex declares compaction ownership (via the embedded runner
path + agentHarnessId). Claude-cli never reaches that path because it
runs as a CLI subprocess with no harness id set, so the safeguard
summarizer fires and hard-fails the turn.

This PR:
- Adds `ownsNativeCompaction?: boolean` to the backend plugin type
- Propagates it through all 4 backend resolution paths
- In `runCliTurnCompactionLifecycle`, when a backend declares ownership
  but has no harness endpoint, returns a no-op instead of falling
  through to the safeguard
- Sets the flag on claude-cli (first adopter)

Codex's existing native-harness path is unchanged: when
`isNativeHarnessCompactionSession` matches, the harness compaction
endpoint is still called as before.

Generalizes the partial fix in #87785 (codex-scoped) to a capability
any backend can opt into.
2026-06-02 14:39:35 +05:30
Vincent Koc
afbf895af0 test(gateway): share runtime state fixture 2026-06-02 10:55:01 +02:00
Vincent Koc
af9bad9fe7 fix(gateway): avoid sync Control UI asset reads 2026-06-02 10:53:31 +02:00
Vincent Koc
3995d57797 refactor(gateway): share fast-path secrets prepare args 2026-06-02 10:44:55 +02:00
Vincent Koc
dcf21ac3ad fix(e2e): isolate release scenario mock state 2026-06-02 10:42:22 +02:00
Vincent Koc
e128efa13a fix(e2e): isolate OpenAI web search smoke logs 2026-06-02 10:34:44 +02:00
Vincent Koc
7f1c991e44 fix(scripts): forward wrapper hangup signals 2026-06-02 10:23:18 +02:00
Vincent Koc
a682e64813 refactor(gateway): share plugin install diff walk 2026-06-02 10:15:06 +02:00
Ayaan Zaidi
e31f351923 fix(android): classify updated system apps 2026-06-02 13:44:45 +05:30
Tosko4
5f505236a6 docs(android): document device apps command 2026-06-02 13:44:45 +05:30
Tosko4
3d1ec37129 feat(android): add installed apps node command 2026-06-02 13:44:45 +05:30
Vincent Koc
6c8e065e3b test(gateway): share scheduled service activation setup 2026-06-02 09:59:09 +02:00
Vincent Koc
cd3887c28a fix(scripts): cancel timed-out response bodies 2026-06-02 09:49:02 +02:00
Vincent Koc
92d363773e test(gateway): reuse record assertions in artifact tests 2026-06-02 09:39:01 +02:00
Vincent Koc
4d3411349b test(gateway): reuse deferred helper in lane tests 2026-06-02 09:28:53 +02:00
Vincent Koc
5912b9e738 fix(gateway): return mcp oversized body errors 2026-06-02 09:25:38 +02:00
Vincent Koc
64d01ff8a8 test(gateway): share deferred helper 2026-06-02 09:12:31 +02:00
Vincent Koc
06f973dd4f test(gateway): share record assertion helpers 2026-06-02 09:02:54 +02:00
Sliverp
0552ec899f fix(qqbot): allow RFC2544 benchmark range for token fetch (#88984) (#89015)
* fix(qqbot): allow RFC2544 benchmark range for token fetch (#88984)

QQ Bot `bots.qq.com` token-fetch path was failing for users whose DNS resolver maps the hostname into the RFC 2544 benchmark range `198.18.0.0/15` (commonly seen with fake-IP proxy stacks: sing-box, Clash, Surge, WSL2 DNS). The default SSRF guard treats that range as private and blocks the request, surfacing as "Network error getting access_token: Blocked: resolves to private/internal/special-use IP address".

Pass a host-scoped `SsrFPolicy` (`allowRfc2544BenchmarkRange: true`) to the single hard-coded `TOKEN_URL` request, mirroring the existing `QQBOT_MEDIA_SSRF_POLICY` pattern used by the media path. Because `TOKEN_URL` is a const and not user-controlled, the relaxation cannot widen attack surface to other hosts.

Adds a regression test asserting `policy: { allowRfc2544BenchmarkRange: true }` is forwarded into `fetchWithSsrFGuard`, and updates the existing equality assertion accordingly.

Fixes #88984

* fix(qqbot): scope token ssrf policy
2026-06-02 15:00:39 +08:00
Vincent Koc
f37ce4ed9b fix(gateway): report pending drain pruning revisions 2026-06-02 08:55:47 +02:00
Dallin Romney
20e0d068a7 fix: bundle private llm core declarations (#89336) 2026-06-01 23:51:38 -07:00
Vincent Koc
c0400397df test(gateway): share agent image request helpers 2026-06-02 08:38:48 +02:00
Peter Steinberger
732d6972d7 fix: repair model provider edge cases
Repairs a batch of narrow model/provider edge cases:

- honor OpenAI and Anthropic base URL environment overrides when provider config does not set an explicit base URL
- preserve OpenRouter Anthropic cache retention while stripping unsupported transport options
- allow apply_patch for non-OpenAI providers when the tool config otherwise permits it
- prune stale same-provider model selections from configure/model picker state
- expose GitHub Copilot bundled thinking policy metadata to offline/provider-policy lookups
- repair additive SQLite shared-state upgrades for existing databases
- keep same-size rotated log readers from reusing stale content in CI tooling

Proof:

- GitHub PR checks green on exact head 46514909b0
- Crabbox delegated Blacksmith Testbox tbx_01kt3em5r9vd7g0bnykrff6jdk exited 0
- Focused local Vitest/oxlint/format proof recorded in PR body and land-ready comment

Fixes #80347.
Fixes #88357.
Fixes #45269.
Supersedes #74427, #74432, #79370, #79894, #80366, and #88359.
2026-06-02 02:35:12 -04:00
Vincent Koc
438eb26d39 fix(ci): keep crabbox sync checkouts alive 2026-06-02 08:29:50 +02:00
Vincent Koc
fd1e314e59 test(gateway): share boot run helpers 2026-06-02 08:23:03 +02:00
Onur Solmaz
a4b4fed412 fix(memory): validate memory index identity
* docs: add memory index identity plan

* fix(memory): validate memory index identity

* fix(memory): align status index identity with vector probe

* fix(memory): fail closed on stale fts-only search

* fix(memory): clear sessions-only identity reindex dirty state

* fix(memory): gate targeted session sync by index identity

* fix(memory): clear resolved index identity dirtiness

* fix(memory): block search on missing index identity

* fix(memory): preserve dirty events during identity reindex

* fix(memory): resolve provider aliases for index identity

* fix(memory): report missing identity states accurately

* fix(memory): mark missing session index identity dirty

* test(memory): expose provider alias resolver in mocks

* chore(memory): remove scratch implementation plan

* fix(memory): avoid automatic full reindex on provider cutover

* docs(memory): plan no-schema cutover repair

* fix(memory): pause vector search on index identity mismatch

* fix(memory): freeze dirty identity sync writes

* fix(memory): skip paused-index search retry

* test(memory): keep retry tests on same provider identity

* fix(memory): surface paused index recall

* chore(memory): remove scratch plan from pr

* fix(memory): preserve paused session dirtiness

* fix(memory): make paused recall warning explicit

* docs(memory): document explicit index repair
2026-06-02 14:22:25 +08:00
Abner Shang
5be282e459 fix(backup): accept root-relative hardlink targets (#89328) 2026-06-01 23:09:21 -07:00
Vincent Koc
4df832412e fix(ci): normalize macos crabbox locale 2026-06-02 08:06:54 +02:00
Vincent Koc
3901f48b0e test(gateway): share channel health fixtures 2026-06-02 07:57:14 +02:00
Vincent Koc
85d2dd8ed2 refactor(gateway): share session history snapshot build 2026-06-02 07:46:38 +02:00
Vincent Koc
46bd5ebd11 refactor(gateway): share realtime tool result broadcast 2026-06-02 07:37:52 +02:00
Vincent Koc
5c93de3e7f refactor(gateway): share hook dispatch session policy 2026-06-02 07:28:31 +02:00
Vincent Koc
b579c0a65b fix(llm): normalize streaming json args 2026-06-02 07:24:19 +02:00
Vincent Koc
94adfc8d10 test(gateway): share node catalog fixtures 2026-06-02 07:13:17 +02:00
Vincent Koc
6883351085 fix(e2e): detect same-size log rotation 2026-06-02 07:11:57 +02:00
Vincent Koc
93fd17447a fix(talk): preserve null lifecycle payloads 2026-06-02 07:05:05 +02:00
Vincent Koc
ebf20241bd test(gateway): share deferred test helper 2026-06-02 06:53:31 +02:00
Vincent Koc
16808524cb refactor: share mcp loopback scope params 2026-06-02 06:44:47 +02:00
Vincent Koc
58de2b689f fix(nodes): preserve falsy event payloads 2026-06-02 06:39:00 +02:00
Vincent Koc
55467f0b94 refactor: share config write response flow 2026-06-02 06:32:06 +02:00
Vincent Koc
6ba25c10dc fix(build): cap tsdown heap on native Windows 2026-06-02 06:25:27 +02:00
Vincent Koc
3419cf5a0d fix(codex): preserve null sandbox rpc results 2026-06-02 06:23:53 +02:00
Peter Steinberger
265926aa47 fix: honor channel model overrides in agent ingress 2026-06-02 00:20:21 -04:00
clawsweeper[bot]
63ed9adfe9 fix(auto-reply): guard missing dispatcher getFailedCounts without weakening the SDK type (#89318)
Summary:
- Adds defensive failed-count reads in auto-reply/ACP accounting and Feishu fallback paths, plus a focused regression test, while keeping `ReplyDispatcher.getFailedCounts` required.
- PR surface: Source +24, Tests +35. Total +59 across 5 files.
- Reproducibility: yes. from source inspection. Current main calls `dispatcher.getFailedCounts().final` and si ... issing that method follows a clear TypeError path; the source PR also supplied terminal before/after proof.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(auto-reply): guard missing dispatcher getFailedCounts without wea…

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

Prepared head SHA: 0bdfb4adeb
Review: https://github.com/openclaw/openclaw/pull/89318#issuecomment-4598624344

Co-authored-by: Alix-007 <li.long15@xydigit.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-06-02 04:16:58 +00:00
Vincent Koc
e6b5083660 refactor: share gateway misc test helpers 2026-06-02 06:15:56 +02:00
WJzz1
6349af6502 docs: add ClawHub CLI page (#89297)
Summary:
- Adds `docs/clawhub/cli.md` documenting OpenClaw skill/plugin ClawHub commands plus standalone ClawHub publish, sync, and transfer workflows.
- PR surface: Docs +82. Total +82 across 1 file.
- Reproducibility: not applicable. this is a docs-only missing-route repair rather than a runtime bug. Source  ... rrent main lacks `docs/clawhub/cli.md` while navigation and existing docs already reference `/clawhub/cli`.

Automerge notes:
- PR branch already contained follow-up commit before automerge: docs: add ClawHub CLI page
- PR branch already contained follow-up commit before automerge: fix(clawsweeper): address review for automerge-openclaw-openclaw-8929…

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

Prepared head SHA: 11e071c344
Review: https://github.com/openclaw/openclaw/pull/89297#issuecomment-4598332147

Co-authored-by: Wang-Yeah623 <205193123+Wang-Yeah623@users.noreply.github.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-06-02 04:13:50 +00:00
Vincent Koc
ffbd02fe8e fix(agents): preserve null node payloads 2026-06-02 06:03:06 +02:00
Vincent Koc
75bc80bb42 refactor: share exec approval iOS push fixtures 2026-06-02 06:02:15 +02:00
Vincent Koc
1e7a0d8987 refactor: share startup auth test helpers 2026-06-02 05:47:24 +02:00
Vincent Koc
39f319c7a4 fix(e2e): preserve gateway null payloads 2026-06-02 05:44:37 +02:00
Vincent Koc
7c4fb1bd2c refactor: share session search test helpers 2026-06-02 05:42:38 +02:00
Vincent Koc
7d5d62511f fix(e2e): preserve null rpc results 2026-06-02 05:33:07 +02:00
Vincent Koc
cc6a6f5682 refactor: share readiness test fixtures 2026-06-02 05:32:25 +02:00
Vincent Koc
7a8d307bdc refactor: share node invoke approval test helpers 2026-06-02 05:24:23 +02:00
Peter Steinberger
b7d363cadf fix(agents): bypass stale auth for plugin harnesses
Explicit non-Codex plugin harness runtimes now bypass stale OpenClaw provider auth cooldowns before harness startup, while Codex/OpenClaw and missing-harness gates remain fail-closed. Fixes #85105.
2026-06-01 23:22:54 -04:00
Vincent Koc
68b4dd1816 fix(crabbox): serialize macos node bootstrap 2026-06-02 05:21:16 +02:00
Vincent Koc
0e16e72091 refactor: share session reset hook test helpers 2026-06-02 05:16:03 +02:00
Peter Steinberger
9ead0ae921 fix: repair live model inference edge cases
Fix live model inference edge cases across provider streaming, model switching, outbound delivery, and gateway tool resolution.

Includes live/provider issue fixes and leaves #89100 explicitly partial for the remaining FM-2 group routing case.
2026-06-01 23:03:27 -04:00
Vincent Koc
3128ec9858 refactor: share gateway probe test helpers 2026-06-02 04:59:36 +02:00
Vincent Koc
1ec291c682 fix(ios): require explicit gateway log target 2026-06-02 04:52:50 +02:00
Vincent Koc
9d9a6140a3 refactor: share sessions list changed test helpers 2026-06-02 04:48:54 +02:00
Vincent Koc
674bd6fc93 fix(mac): isolate build run logs 2026-06-02 04:47:00 +02:00
Peter Steinberger
b2a55a282a fix(update): do not fail core update on plugin repair fetch 2026-06-02 03:42:54 +01:00
Vincent Koc
3cf4c1ad69 refactor: share connect policy test helpers 2026-06-02 04:38:59 +02:00
Vincent Koc
fa9ce6ea0e fix(mac): isolate dmg resize limits 2026-06-02 04:32:38 +02:00
Vincent Koc
0f1f1a1fd7 refactor: share startup config recovery test helpers 2026-06-02 04:29:40 +02:00
Vincent Koc
d944aaa9ec fix(test): reject retired live shard 2026-06-02 04:20:53 +02:00
Vincent Koc
baade28397 refactor: share subagent delivery context test helpers 2026-06-02 04:20:09 +02:00
Vincent Koc
883c0f1254 fix(mac): scope restart log by worktree 2026-06-02 04:11:23 +02:00
Vincent Koc
793ab78ebb refactor: share cron validation test helpers 2026-06-02 04:08:21 +02:00
Peter Steinberger
57ea5aff81 test(release): expect cheap docker preflight 2026-06-02 03:03:48 +01:00
Vincent Koc
f1d65b3cd6 fix(e2e): isolate trash shim bin dir 2026-06-02 04:01:47 +02:00
Vincent Koc
e6b951a6a6 refactor: share operator approval client test setup 2026-06-02 03:58:27 +02:00
Vincent Koc
55e9194a4c perf(scripts): avoid duplicate build cache input hashing 2026-06-02 03:50:19 +02:00
Vincent Koc
8929838159 refactor: share gateway credentials test fixtures 2026-06-02 03:49:48 +02:00
Peter Steinberger
a355c8897d ci(release): keep docker preflight cheap 2026-06-02 02:48:41 +01:00
Vincent Koc
b06dc17537 refactor: share gateway e2e test setup 2026-06-02 03:40:29 +02:00
Vincent Koc
7967a3582c fix(e2e): isolate onboard gateway logs 2026-06-02 03:39:10 +02:00
Vincent Koc
2e6016fdec fix(ci): keep crabbox pnpm hydrate off tmpfs 2026-06-02 03:38:51 +02:00
Peter Steinberger
8a1a8ea8a3 ci(release): wait out live provider rate limits 2026-06-02 02:38:22 +01:00
Vincent Koc
4608f7dcf9 refactor: share probe auth test fixtures 2026-06-02 03:29:33 +02:00
Vincent Koc
49ac93bda6 refactor: share talk session response helpers 2026-06-02 03:20:00 +02:00
Peter Steinberger
f6653b9b35 fix(ci): retry live Docker image pulls 2026-06-02 02:08:26 +01:00
Vincent Koc
2f92fddef0 refactor: share node invoke wake test helpers 2026-06-02 03:02:03 +02:00
Vincent Koc
489efc8f5e refactor: share device token authz test fixtures 2026-06-02 02:58:38 +02:00
Vincent Koc
459abfc26b fix(e2e): isolate plugin sweep scratch files 2026-06-02 02:50:41 +02:00
Vincent Koc
340cc2c1e4 refactor: share session history test fixtures 2026-06-02 02:41:09 +02:00
Vincent Koc
be8cb5d4ea refactor: share agent wait dedupe test fixtures 2026-06-02 02:37:48 +02:00
Vincent Koc
222ade9fa6 fix(e2e): clean kitchen sink sweep state 2026-06-02 02:29:52 +02:00
Peter Steinberger
6667b9734a fix(ci): avoid rg dependency in changelog gate 2026-06-02 01:29:15 +01:00
Vincent Koc
ebbb2e8f01 refactor: share handshake auth helper test fixtures 2026-06-02 02:20:52 +02:00
Vincent Koc
dea3e835c5 refactor: share channel health policy test fixtures 2026-06-02 02:16:09 +02:00
Peter Steinberger
722af385d2 test(release): accept gateway schema rejection wrapper 2026-06-02 01:10:00 +01:00
Vincent Koc
dacd18a8aa refactor: share chat attachment test helpers 2026-06-02 02:00:15 +02:00
Vincent Koc
8a9acd2940 test(mac): exercise codesign entitlement use 2026-06-02 01:56:24 +02:00
Vincent Koc
bd8353dbaa fix(testing): fail plugin gauntlet on failed qa summaries 2026-06-02 01:52:00 +02:00
Vincent Koc
3baf78dd0a refactor: share node invoke approval test helpers 2026-06-02 01:51:08 +02:00
Vincent Koc
1ed7692d2f test(changelog): exercise attribution gate policy 2026-06-02 01:46:34 +02:00
Omar Shahine
12798eb789 fix(agents): avoid duplicate generated media fallback (#89220)
Treat targetless current-chat message-tool media telemetry as delivered for generated-media completion dedupe while preserving fallback delivery for mismatched provider/account/thread evidence.

Real behavior proof was added from the live iMessage generated-image run: inbound id 5805, exactly one outgoing media reply id 5806, and no follow-up generated-image fallback.

Co-authored-by: omarshahine <10343873+omarshahine@users.noreply.github.com>
Reviewed-by: @lobster
2026-06-01 16:46:14 -07:00
Omar Shahine
02192bd27f fix(imessage): keep typing active during tool work (#88948)
Keep iMessage native typing indicators alive through long tool-running gaps by bridging tool-start activity into the existing typing controller, while preserving typingMode and sendPolicy suppression semantics.

Real behavior proof was added from the live iMessage generated-image run: inbound id 5805, outgoing media reply id 5806, and requester-observed typing during the 84s tool path.

Co-authored-by: omarshahine <10343873+omarshahine@users.noreply.github.com>
Reviewed-by: @lobster
2026-06-01 16:45:46 -07:00
Vincent Koc
086274fd7e test(e2e): exercise onboard wizard exit status 2026-06-02 01:38:46 +02:00
Vincent Koc
ed07a7a2de refactor: share node pairing authz test setup 2026-06-02 01:33:11 +02:00
Vincent Koc
829fb5dcb3 fix(e2e): clean generated docker client state 2026-06-02 01:30:10 +02:00
Peter Steinberger
4c6285e8ff test(release): retry google tool-read failovers 2026-06-02 00:26:55 +01:00
Vincent Koc
7c52969d49 fix(e2e): clean plugin fixture servers on timeout 2026-06-02 01:17:08 +02:00
Vincent Koc
42d3acfc99 refactor: share ios approval push delivery 2026-06-02 01:09:58 +02:00
Vincent Koc
32f98d7fe8 fix(e2e): forward sighup in node watchdogs 2026-06-02 01:05:29 +02:00
Vincent Koc
4bd7421182 refactor: share gateway auth request guards 2026-06-02 00:56:06 +02:00
Vincent Koc
d91d8ff060 refactor: share chat abort test setup 2026-06-02 00:47:43 +02:00
Vincent Koc
af44fb9b6c fix(test): preserve vitest batch wrapper signals 2026-06-02 00:46:55 +02:00
Vincent Koc
45e0545e82 refactor: share gateway shutdown abort helpers 2026-06-02 00:44:16 +02:00
Peter Steinberger
2d17cb295d fix(discord): use libopus structured decode errors 2026-06-01 23:43:31 +01:00
Peter Steinberger
e8120a72e1 ci(release): retry quiet node shard stalls 2026-06-01 23:43:03 +01:00
Dallin Romney
0904f3e553 revert: undo gateway memory watch warning (#89246) 2026-06-01 15:32:42 -07:00
Vincent Koc
2770aa5f4c fix(scripts): clean boundary step process groups 2026-06-02 00:29:22 +02:00
Vincent Koc
285401ced8 refactor: share cli session history test helpers 2026-06-02 00:25:39 +02:00
Vincent Koc
64697fbe24 chore(release): add matrix plugin changelog 2026-06-02 00:23:41 +02:00
Vincent Koc
e9aae26b22 fix(test): clean live wrapper children 2026-06-02 00:19:53 +02:00
Vincent Koc
cb12a9af94 refactor: share node pairing request test helpers 2026-06-02 00:17:07 +02:00
Peter Steinberger
65d7fa2420 fix(memory): reattach Linux watchers on directory rename
(cherry picked from commit 0db7781514cc84fac4f3a999d24b4b747fc871f9)
2026-06-01 23:15:00 +01:00
Peter Steinberger
bd4a7f4119 fix(discord): classify corrupt opus packets structurally 2026-06-01 23:14:23 +01:00
Vincent Koc
14f61d0637 fix(test): clean delegated vitest runners 2026-06-02 00:09:20 +02:00
Vincent Koc
0f3a63b12e refactor: share preauth hardening test helpers 2026-06-02 00:07:53 +02:00
Peter Steinberger
a14eacf372 chore(release): set version 2026.6.2 2026-06-01 23:06:55 +01:00
Colin
646df2da83 fix skill workshop filtered fallback 2026-06-01 23:00:40 +01:00
Colin
211321ce5c address skill workshop review comments 2026-06-01 23:00:40 +01:00
Colin
a34e822cd4 fix skill workshop filtered navigation 2026-06-01 23:00:40 +01:00
Colin
8c180c9153 fix(ui): render skill workshop tab 2026-06-01 23:00:40 +01:00
Vincent Koc
990f0baff9 fix(e2e): scope gateway cleanup to tracked pid 2026-06-01 23:59:03 +02:00
Peter Steinberger
bd8baeb323 perf(gateway): narrow plugin lookup memo key 2026-06-01 22:58:46 +01:00
Vincent Koc
0771bbbd20 refactor: share discovery runtime test setup 2026-06-01 23:50:24 +02:00
Vincent Koc
74cf5c7e7d refactor: share session permission client setup 2026-06-01 23:48:17 +02:00
Vincent Koc
0cfd6b0504 fix(e2e): clean timed-out docker harness containers 2026-06-01 23:45:56 +02:00
Peter Steinberger
4e45010203 ci(release): fail fast on red release children
(cherry picked from commit 8d7038775f0a0a1bb5354ba6b6b708c6b2c3167b)
2026-06-01 22:42:53 +01:00
Vincent Koc
afdf9aaea0 refactor: share talk config test helpers 2026-06-01 23:34:51 +02:00
Vincent Koc
72ed2121f8 fix(scripts): guard delayed docker package kills 2026-06-01 23:33:00 +02:00
Dallin Romney
2405bbcbaf fix(memory): warn on gateway watcher FD risk (#89185)
* fix(memory): default gateway memory watch off

* fix(memory): warn on gateway watcher fd risk

* fix(config): avoid warning helper narrowing

* fix(config): remove redundant warning boolean cast

* docs(memory): clarify watcher default wording

* docs(memory): simplify watcher warning copy

* fix(config): scope watcher warning to local gateway
2026-06-01 14:23:25 -07:00
Vincent Koc
403190572b fix(e2e): isolate release media memory artifacts 2026-06-01 23:19:47 +02:00
Vincent Koc
67983a00c8 refactor: share session reset model test helpers 2026-06-01 23:12:52 +02:00
Vincent Koc
61aa499b53 test(scripts): trap test-state temp homes 2026-06-01 23:09:58 +02:00
Vincent Koc
420450b5cb fix(ci): timeout dependency guard GitHub requests 2026-06-01 22:59:55 +02:00
Kevin Lin
f8491b0fcf enhance(slack): route plugin approvals through native UI
Route Slack plugin approval delivery through the shared native approval route gates while preserving Slack Block Kit buttons and plugin resolver semantics.

Verification: Slack/native approval unit tests, Slack QA Lab, and live clawd native plugin approval via Slack desktop.
2026-06-01 13:55:59 -07:00
Vincent Koc
98e943ebdd refactor: share voicewake model test helpers 2026-06-01 22:53:29 +02:00
Vincent Koc
f8d5f162a1 fix(ui): terminate child on wrapper shutdown 2026-06-01 22:37:25 +02:00
Vincent Koc
a2fdd5bc70 refactor: share session delete lifecycle test helpers 2026-06-01 22:31:06 +02:00
Vincent Koc
2af2111ae0 refactor: share session history test helpers 2026-06-01 22:28:14 +02:00
Vincent Koc
c9d35c7172 fix(scripts): forward run-with-env termination 2026-06-01 22:24:34 +02:00
Dallin Romney
50b69e16dc fix(agents): dispatch auth failures by type (#89181) 2026-06-01 13:23:05 -07:00
Vincent Koc
fe97c6000c refactor: share browser auth test helpers 2026-06-01 22:19:07 +02:00
Dallin Romney
a99cbf29bd test: reset gateway timers at test boundaries (#89212) 2026-06-01 13:13:08 -07:00
Vyctor H. Brzezowski
05ea36a81f docs: refresh ClawHub showcase cards (#88734) 2026-06-01 13:08:56 -07:00
Vincent Koc
eb58c88598 refactor: share model catalog test helpers 2026-06-01 21:58:49 +02:00
Dallin Romney
5a67c5c556 fix(memory-core): reduce Linux watcher fan-out (#89188)
* fix(memory-core): reduce Linux watcher fan-out

* fix(memory-core): satisfy watcher type and lint checks

* fix(memory-core): harden Linux watcher subtree races
2026-06-01 12:54:30 -07:00
NianJiu
5a55135146 fix(memory): retry transient FileProvider-backed reads (#85351) 2026-06-01 12:40:20 -07:00
Vincent Koc
193988bc5b fix(e2e): isolate onboard temp artifacts 2026-06-01 21:25:03 +02:00
Vincent Koc
a20f57bf2e refactor: share startup auth test assertions 2026-06-01 21:16:55 +02:00
Vincent Koc
66f797b22c fix(e2e): wait for plugin update registry cleanup 2026-06-01 21:01:26 +02:00
Vincent Koc
65a805ac28 fix(e2e): harden web search cleanup 2026-06-01 20:35:33 +02:00
Vincent Koc
b18bab0bcc refactor: share session kill http test fixtures 2026-06-01 20:35:08 +02:00
Alexzhu
9ac30b587e Keep machine-readable CLI startup output parseable (#88689)
Constraint: CLI startup progress can render before Commander resolves a command's JSON output contract.

Rejected: Leaving Clack on its default stdout | contaminates JSON stdout when startup progress appears.

Confidence: high

Scope-risk: narrow

Directive: Keep progress output off stdout before full command parsing for machine-readable invocations.

Tested: git diff --check origin/main; OPENCLAW_HEAVY_CHECK_LOCK_SCOPE=worktree OPENCLAW_VITEST_MAX_WORKERS=1 node scripts/run-vitest.mjs src/cli/progress.test.ts src/cli/run-main.exit.test.ts; source CLI sessions --json parse proof.

Not-tested: broad pnpm check.
2026-06-01 11:33:22 -07:00
Peter Steinberger
82de264710 test(release): tolerate MiniMax portal nonce drift 2026-06-01 19:30:46 +01:00
Vincent Koc
7f7f0775ed fix(testing): keep crabbox sync checkouts durable 2026-06-01 20:30:08 +02:00
Vincent Koc
30819ed3da refactor: share http endpoint test scaffolding 2026-06-01 20:25:40 +02:00
Vincent Koc
1c3095e029 test(deps): clean dependency evidence temp roots 2026-06-01 20:20:42 +02:00
Vincent Koc
62cfc613f1 refactor: share startup early test inputs 2026-06-01 20:17:30 +02:00
Dallin Romney
64a946ac21 fix(agents): actionable copy for exhausted auth-profile failover (#85798)
* fix(agents): actionable copy for exhausted auth-profile failover

The pi-embedded runner threw a generic "No available auth profile for
<provider> (all in cooldown or unavailable)" message whenever every
configured profile was in cooldown, even though the failover machinery
had already resolved a concrete reason (auth, billing, rate_limit,
session_expired, etc.). The user-facing copy never used that reason and
never told the user how to recover.

Route the resolved reason through a single presenter
(`formatAuthProfileFailureMessage`) that composes a reason-specific
sentence with `buildProviderAuthRecoveryHint`, so FailoverError.message
ships with the right `openclaw models auth login --provider <id>` hint
when the cause is authentication/session/billing, and falls back to the
underlying provider error text otherwise. Helper moved out of
`src/commands/` into `src/agents/` because `src/agents/` cannot depend
on `src/commands/`.

* fix(agents): soften auth-profile failure copy for non-technical users

* refactor(agents): drop guidance re-export shim and de-brittle failure-copy tests

- Delete `src/commands/provider-auth-guidance.ts` and point doctor-auth, auth-choice.model-check, and models/list.status-command directly at `src/agents/provider-auth-recovery-hint.ts`. The cold-imports test moves with it.
- Rewrite `failure-copy.test.ts` to assert behavior (recovery-hint dispatch, provider mention, cause-suffix dedup) instead of pinning exact long copy strings, so wording tweaks no longer require a test update in two places.
2026-06-01 11:16:25 -07:00
Vincent Koc
96187089d4 refactor: share session history message fixtures 2026-06-01 20:05:18 +02:00
Vincent Koc
965e680603 test(control-ui): clean i18n timeout temp dirs 2026-06-01 20:03:05 +02:00
Vincent Koc
1cf39a2d6f refactor: table-drive lifecycle state tests 2026-06-01 19:57:35 +02:00
Vincent Koc
92b3d52e8a fix(e2e): isolate release media temp files 2026-06-01 19:56:05 +02:00
Dallin Romney
8ba6dfeaf6 fix(ci): restore dist cache before artifact builds (#89169) 2026-06-01 10:55:27 -07:00
Peter Steinberger
bddcf4448c fix(subagents): rotate steered restart sessions 2026-06-01 18:50:36 +01:00
Vincent Koc
c8a67768e3 fix(e2e): require expected web search rejection 2026-06-01 19:49:11 +02:00
Vincent Koc
26e61b2087 refactor: share single-row cache test helpers 2026-06-01 19:48:19 +02:00
Vincent Koc
ee48028028 fix(dev): clean tui pty watch children 2026-06-01 19:40:42 +02:00
Vincent Koc
3c324590ae refactor: share compaction checkpoint test helpers 2026-06-01 19:33:41 +02:00
Vincent Koc
ba88b7a178 fix(e2e): clean plugin lifecycle temp state 2026-06-01 19:27:04 +02:00
Vincent Koc
d767e296e2 refactor: share plugin node auth test helpers 2026-06-01 19:26:59 +02:00
Vincent Koc
83cd3cbe2a fix(e2e): bound bundled plugin lifecycle commands 2026-06-01 19:18:26 +02:00
Vincent Koc
16807824cc refactor: share node invoke approval test helpers 2026-06-01 19:18:14 +02:00
Dallin Romney
e3d24faecd fix: allow admins to approve dependency guard (#88966)
* fix: allow admins to approve dependency guard

* fix: auto-bypass trusted dependency authors
2026-06-01 10:17:14 -07:00
Peter Steinberger
469bec97ef test(codex): keep live subagent smoke lightweight 2026-06-01 18:09:48 +01:00
Vincent Koc
101db565ca refactor: share startup plugin test helpers 2026-06-01 19:09:39 +02:00
Vincent Koc
ef26e8dfce fix(repro): clean webchat tts proof artifacts 2026-06-01 19:04:12 +02:00
Vincent Koc
25c19e013a refactor: share startup memory test helpers 2026-06-01 19:00:26 +02:00
Vincent Koc
f2eea90dac fix(e2e): bound cron mcp probe waits 2026-06-01 18:52:13 +02:00
Vincent Koc
3113fe95ea refactor: share startup secrets test helpers 2026-06-01 18:49:58 +02:00
Vincent Koc
4e1f8b8ac7 fix(e2e): clean timed-out runtime commands 2026-06-01 18:43:25 +02:00
Vincent Koc
0b8f6b81e6 refactor: share probe request dispatch helper 2026-06-01 18:35:38 +02:00
Vincent Koc
ab1042d115 refactor: share talk transcription relay test setup 2026-06-01 18:34:05 +02:00
Peter Steinberger
9153aab037 fix(codex): abort app-server thread startup cleanly 2026-06-01 17:33:00 +01:00
Vincent Koc
285a792aa8 refactor: share maintenance test fixtures 2026-06-01 18:25:54 +02:00
Vincent Koc
a8bc1716dd fix(usage): skip empty timeseries scans 2026-06-01 18:20:52 +02:00
Vincent Koc
373ef81e83 refactor: share codex harness model assertions 2026-06-01 18:12:11 +02:00
Vincent Koc
c053b90290 refactor: share shared auth rotation test helpers 2026-06-01 18:10:57 +02:00
Pavan Kumar Gondhi
fbdf593778 fix: bound remote media reference reads [AI] (#88974)
* fix: bound remote media reference reads

* fix: remove unreachable video timeout wiring

* test: cover remote video reference handoff
2026-06-01 21:35:40 +05:30
Vincent Koc
488b65ab87 refactor: share session reset test helpers 2026-06-01 18:00:39 +02:00
Peter Steinberger
6668eb8225 test(codex): drop unused live harness helper 2026-06-01 16:56:48 +01:00
Vincent Koc
72436217ff fix(e2e): isolate MCP channel client temp state 2026-06-01 17:51:04 +02:00
Peter Steinberger
460cf7ed75 test(codex): avoid sessions list wait in live harness start probe 2026-06-01 16:49:20 +01:00
Vincent Koc
461999c060 fix(dev): clean Telegram flow previews on failure 2026-06-01 17:37:15 +02:00
Vincent Koc
9cb347e4c3 fix(dev): close gateway smoke websocket on failures 2026-06-01 17:26:15 +02:00
Vincent Koc
1d7e5f48ed fix(dev): close stalled gateway websocket handshakes 2026-06-01 17:18:40 +02:00
Vincent Koc
1fd2259e28 refactor: share config patch test helpers 2026-06-01 17:15:48 +02:00
Peter Steinberger
3f54d150b3 test(openrouter): stabilize music timeout clamp assertion 2026-06-01 16:09:23 +01:00
Vincent Koc
a9866a405c test(agents): align provider auth alias fixtures 2026-06-01 17:08:31 +02:00
Vincent Koc
0b9187c780 test(gateway): fix node invoke capture race 2026-06-01 17:08:31 +02:00
Vincent Koc
b1ec23e05f fix(e2e): escalate stuck PTY children 2026-06-01 17:07:42 +02:00
Vincent Koc
050f0c0af6 refactor: share device pair authz test helpers 2026-06-01 16:58:10 +02:00
Vincent Koc
dfeb5b81ca fix(e2e): harden Parallels helper cleanup 2026-06-01 16:57:27 +02:00
Vincent Koc
d9f6e03e32 refactor: share silent reconnect test helpers 2026-06-01 16:54:10 +02:00
Peter Steinberger
fed7d1f385 test(release): stabilize beta validation regressions 2026-06-01 15:47:56 +01:00
Vincent Koc
0a9e594420 fix(scripts): clean Anthropic prompt probe temp state 2026-06-01 16:47:27 +02:00
Sally O'Malley
c1ce51546e fix(ui): clear chat composer after send (#89106) 2026-06-01 10:42:35 -04:00
Vincent Koc
1b928592ef refactor: share startup recovery test helpers 2026-06-01 16:37:09 +02:00
Vincent Koc
12087ac9d4 test(e2e): exercise Parallels smoke cleanup path 2026-06-01 16:33:11 +02:00
Peter Steinberger
00caead80a test: close oxlint signal readiness race 2026-06-01 10:26:08 -04:00
Peter Steinberger
4b54a423f0 test: harden changed-gate assertions 2026-06-01 10:26:08 -04:00
Peter Steinberger
bdd6cf3d5e test: stabilize order-sensitive assertions 2026-06-01 10:26:08 -04:00
Peter Steinberger
cb7a4239ef fix: stabilize full-suite regressions 2026-06-01 10:26:08 -04:00
Peter Steinberger
b226a752a1 test: stabilize slow shard regressions 2026-06-01 10:26:08 -04:00
Vincent Koc
110f7d55e3 fix(scripts): clean Z.AI fallback repro temp state 2026-06-01 16:25:05 +02:00
Vincent Koc
645c7dc40b refactor: share gateway misc test helpers 2026-06-01 16:18:22 +02:00
Vincent Koc
a4847297b8 fix(ci): clean check-changed pnpm shim temp dirs 2026-06-01 16:16:26 +02:00
Vincent Koc
4253517070 refactor: share node allowlist test helpers 2026-06-01 16:14:59 +02:00
Peter Steinberger
e8c126eaf2 fix(ci): use QA runtime build for release checks 2026-06-01 15:12:50 +01:00
Peter Steinberger
2075d19923 test(gateway): scope lazy server mock 2026-06-01 15:12:50 +01:00
Vincent Koc
9e58ef1c82 test(scripts): clean session log temp roots 2026-06-01 16:00:41 +02:00
Vincent Koc
eaeccf5fdf refactor: share node registry system run test helpers 2026-06-01 16:00:36 +02:00
Vincent Koc
2c0e835b48 test(codex): clean up fake timer spies 2026-06-01 14:57:47 +01:00
Vincent Koc
b942a958b3 test(qa): cover QA lab help runtime boundary 2026-06-01 15:54:16 +02:00
Vincent Koc
42bcf9cd0b fix(test): keep runtime tests raw-sync safe 2026-06-01 15:53:37 +02:00
Vincent Koc
a0fbb6cfe2 fix(test): keep app parity checks sparse safe 2026-06-01 15:53:37 +02:00
Vincent Koc
408fa6e951 fix(test): stabilize watch-node shutdown tests 2026-06-01 15:53:37 +02:00
Vincent Koc
671909d6d3 refactor: share server aux reload test helpers 2026-06-01 15:51:05 +02:00
Vincent Koc
409f78a1ea fix(e2e): clean OTEL collector startup failures 2026-06-01 15:46:02 +02:00
Vincent Koc
3e592a8bd7 refactor: share mcp http loopback test helpers 2026-06-01 15:39:28 +02:00
Vincent Koc
e895479a21 fix(ci): fail gateway watch spawn errors promptly 2026-06-01 15:38:16 +02:00
Peter Steinberger
930bc9691b fix(ci): page CI timing job reads 2026-06-01 14:33:39 +01:00
Vincent Koc
b9f181635f fix(ci): fail gateway CPU spawn errors 2026-06-01 15:27:13 +02:00
Vincent Koc
c2aaf8afec refactor: share sessions patch test helpers 2026-06-01 15:17:55 +02:00
Vincent Koc
cbc5f277bb refactor: share session reset hook test helpers 2026-06-01 15:11:10 +02:00
Vincent Koc
44b388f863 fix(e2e): keep kitchen-sink process snapshots wide 2026-06-01 15:09:33 +02:00
Vincent Koc
c0e49a2c52 fix(e2e): catch runtime package-manager descendants 2026-06-01 14:58:39 +02:00
Peter Steinberger
c1e132195d test(release): activate manifest channels in bundle smoke 2026-06-01 13:51:38 +01:00
Vincent Koc
5bd8dbd0b8 refactor: share system run approval test helpers 2026-06-01 14:44:46 +02:00
Vincent Koc
421ea1f458 fix(e2e): bound Parallels host VM commands 2026-06-01 14:41:46 +02:00
Vincent Koc
1f91e97353 refactor: share startup secrets test helpers 2026-06-01 14:31:58 +02:00
Vincent Koc
d4f6e0a1f2 fix(docs): clean link audit temp docs 2026-06-01 14:26:21 +02:00
Peter Steinberger
ec2455a842 test(memory): drive timeout tests with explicit fake clocks
(cherry picked from commit d75eea53c9)
2026-06-01 13:12:07 +01:00
Vincent Koc
1742f3f77c refactor: share mcp http test helpers 2026-06-01 14:10:41 +02:00
Vincent Koc
5117f457bb fix(ci): clean gateway watch temp home 2026-06-01 14:09:58 +02:00
Vincent Koc
8fe5e83462 refactor: share sessions list changed test helpers 2026-06-01 14:00:20 +02:00
Vincent Koc
27097bed65 fix(ci): bound deadcode knip scan 2026-06-01 13:57:16 +02:00
Vincent Koc
1849a86dd2 refactor: share session history revocation helpers 2026-06-01 13:47:39 +02:00
Vincent Koc
5280d1d95d fix(e2e): stream Parallels phase logs 2026-06-01 13:46:21 +02:00
Vincent Koc
bcdc93d651 refactor: share auth compat backend scope assertion 2026-06-01 13:31:03 +02:00
Vincent Koc
0751b6f2c9 fix(e2e): bound upgrade survivor config commands 2026-06-01 13:30:23 +02:00
Peter Steinberger
7d9fae5b3a fix(memory): keep embedding timeout watchdog active
(cherry picked from commit 591f310869)
2026-06-01 12:29:27 +01:00
Vincent Koc
a595aba60e refactor: share sessions send result assertions 2026-06-01 13:21:09 +02:00
Vincent Koc
75645aec08 fix(e2e): clean Telegram proof child processes 2026-06-01 13:20:03 +02:00
Vincent Koc
d10d71cdb6 fix(codex): stabilize app-server cleanup tests 2026-06-01 13:15:05 +02:00
Vincent Koc
c69a8d633d perf(control-ui): hydrate chat startup state
Add a combined chat.startup gateway method for Control UI startup hydration so first chat load can receive history and agents in one RPC, while falling back to chat.history for older/unadvertised gateways. Verified with focused UI/gateway tests, tsgo/oxlint/diff checks, clean autoreview, and Testbox changed gate tbx_01kt1dt6fqdtdbprsk48z8fn71.
2026-06-01 12:14:19 +01:00
Vincent Koc
d8ebbedf45 refactor: share plugin http auth request assertions 2026-06-01 13:10:09 +02:00
Peter Steinberger
9ed1766696 test(whatsapp): align direct last-route envelope
(cherry picked from commit 5d902b0f20)
2026-06-01 12:04:51 +01:00
Vincent Koc
bed0fb7bad refactor: share session resolve assertions 2026-06-01 13:00:51 +02:00
Vincent Koc
db6fc20559 fix(e2e): clean Windows background smoke timeouts 2026-06-01 12:55:15 +02:00
Vincent Koc
1364acbe4c refactor: share gateway http stage error assertions 2026-06-01 12:45:20 +02:00
Vincent Koc
d2988e0248 refactor: share preview resolve alias fixtures 2026-06-01 12:42:30 +02:00
Vincent Koc
8c8c8c8e32 perf(control-ui): prioritize first connect startup (#89030)
* perf(control-ui): prioritize first connect startup

* fix(control-ui): close connect timing gaps

* fix(control-ui): default embeds strict before bootstrap

* fix(control-ui): keep bootstrap identity deferred

* fix(control-ui): gate startup chat on bootstrap

* fix(control-ui): restore composer after hello

* fix(control-ui): restore drafts before hello
2026-06-01 11:41:22 +01:00
Vincent Koc
8bee3be90a fix(e2e): bound Parallels fresh lanes 2026-06-01 12:34:29 +02:00
Vincent Koc
87d890003d refactor: share shutdown drain session setup 2026-06-01 12:31:32 +02:00
Peter Steinberger
aed7de306e fix(qa-matrix): detect sqlite dedupe commits by payload
(cherry picked from commit 2fc497e67b)
2026-06-01 11:27:10 +01:00
Vincent Koc
859cb52b44 refactor: share unauthorized response assertions 2026-06-01 12:22:58 +02:00
Vincent Koc
4685a84e9b fix(e2e): bound bundled runtime gateway cleanup 2026-06-01 12:19:37 +02:00
Vincent Koc
f30235bed2 test: fix gateway test type fixtures 2026-06-01 12:13:36 +02:00
Vincent Koc
4f8f6c7693 refactor: share thinking e2e session setup 2026-06-01 12:13:36 +02:00
Peter Steinberger
055063f06b fix(qa-matrix): read sqlite inbound dedupe state 2026-06-01 11:07:53 +01:00
Vincent Koc
dac33c8ecb fix(e2e): cap pty transcript output 2026-06-01 11:49:58 +02:00
Vincent Koc
75ebf1c870 refactor: share device token authz test helpers 2026-06-01 11:49:06 +02:00
Vincent Koc
e4a32b9e8e lint(e2e): remove redundant channel fallback 2026-06-01 11:38:28 +02:00
Vincent Koc
22e3b2e94e fix(dev): wait for watch-node shutdown 2026-06-01 11:38:28 +02:00
Peter Steinberger
729420c34a test: split slow vitest shards 2026-06-01 05:34:59 -04:00
Peter Steinberger
0b5be66ef7 perf(gateway): trim startup plugin planning work 2026-06-01 10:33:28 +01:00
Peter Steinberger
8e28c773fe chore(release): prepare 2026.6.1 2026-06-01 10:30:15 +01:00
Vincent Koc
2dcb681f38 refactor: share session search test fixtures 2026-06-01 11:28:59 +02:00
Peter Steinberger
e733774e3c fix(test): repair telegram prerelease blockers 2026-06-01 10:26:12 +01:00
Mason Huang
004835f4c7 fix(plugins): block untrusted workspace setup-only channel loads (#86953)
Summary:
- This PR blocks disabled workspace-origin channel plugins from setup-only scoped imports, rejects their channel registrations at registry assembly, documents the trust rule, and adds regression coverage.
- PR surface: Source +46, Tests +610, Docs +13. Total +669 across 22 files.
- Reproducibility: yes. source inspection gives a high-confidence reproduction path: current main's setup-only ... ce channel plugin can be imported before this PR. I did not run the repro locally in this read-only review.

Automerge notes:
- PR branch already contained follow-up commit before automerge: test(plugins): cover workspace channel registry guard
- PR branch already contained follow-up commit before automerge: fix(plugins): isolate setup channel registration errors
- PR branch already contained follow-up commit before automerge: fix(channels): mark raw catalog listing internal
- PR branch already contained follow-up commit before automerge: test(channels): cover trusted catalog filtering
- PR branch already contained follow-up commit before automerge: test(channels): mock raw catalog helper
- PR branch already contained follow-up commit before automerge: docs(changelog): credit setup channel hardening

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

Prepared head SHA: 11438bc1a0
Review: https://github.com/openclaw/openclaw/pull/86953#issuecomment-4545730044

Co-authored-by: masonxhuang <masonxhuang@tencent.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Mason Huang <masonxhuang@tencent.com>
Co-authored-by: Sebastien Tardif <sebtardif@ncf.ca>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: hxy91819
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
2026-06-01 09:25:56 +00:00
Vincent Koc
97d373ff37 perf(ui): speed up first global chat sends
Speed up Control UI first global chat sends by letting safe literal-global startup refresh use the fresh hello default before agents.list finishes, while keeping stale carried/cached agent ids out of that fast path. Adds chat history/send and gateway chat.send timing markers for the next latency pass.
2026-06-01 10:25:22 +01:00
Vincent Koc
3119f08009 fix(scripts): bound shrinkwrap npm commands 2026-06-01 11:23:20 +02:00
Peter Steinberger
9d55fc4579 fix(plugins): skip peer links in rollback snapshots 2026-06-01 10:18:30 +01:00
Vincent Koc
2bac970abc refactor: share node invoke policy test setup 2026-06-01 11:17:38 +02:00
Vincent Koc
f8e9ba3718 fix(codex): prevent aborted app-server turn handles 2026-06-01 10:12:36 +01:00
Vincent Koc
26aaf03719 fix(scripts): clean control ui i18n timeouts 2026-06-01 11:10:57 +02:00
Vincent Koc
e85be626a4 refactor: share plugin runtime scope test setup 2026-06-01 11:07:29 +02:00
Vincent Koc
9cb052ccef refactor: share plugin http route test setup 2026-06-01 10:56:09 +02:00
Peter Steinberger
637b073119 test(ui): update gateway session chat mock 2026-06-01 04:53:51 -04:00
Vincent Koc
174e7711f3 fix(build): clean CLI startup metadata timeouts 2026-06-01 10:52:27 +02:00
Vincent Koc
b13af38f99 perf(ui): trace chat first output latency
Add chat-send first visible assistant output telemetry in the Control UI, plus Gateway diagnostics correlation attributes for chat.send dispatch spans. Verified with focused UI/Gateway tests, tsgo, oxlint, autoreview, PR checks, and Testbox-through-Crabbox check:changed.
2026-06-01 09:47:45 +01:00
Vincent Koc
4094c94a8f refactor: share event loop health expectation 2026-06-01 10:47:05 +02:00
Peter Steinberger
32113e38ab perf(ci): speed up prompt snapshot checks 2026-06-01 04:44:41 -04:00
Peter Steinberger
07a425aa14 fix: preserve colon slash commands 2026-06-01 09:41:19 +01:00
Vincent Koc
db5bb1cbe7 refactor: share auth state test setup 2026-06-01 10:38:12 +02:00
Vincent Koc
947dde976c fix(release): bound plugin npm verification commands 2026-06-01 10:36:46 +02:00
Peter Steinberger
1d4c1ba56d fix: harden memory envelope sanitization
Co-authored-by: amittell <mittell@me.com>
2026-06-01 09:30:08 +01:00
Vincent Koc
de3ee3daa6 refactor: share auth context test helpers 2026-06-01 10:24:04 +02:00
Vincent Koc
61574eb50b perf(ui): keep chat draft local while typing (#88998) 2026-06-01 09:19:53 +01:00
Vincent Koc
e680604577 fix(e2e): clean telegram credential timeouts 2026-06-01 10:13:57 +02:00
Vincent Koc
2ea7c518a5 test(agents): avoid provider runtime in subagent spawn tests 2026-06-01 09:13:36 +01:00
Vincent Koc
7f95733bee refactor: share handshake locality test inputs 2026-06-01 10:12:30 +02:00
Peter Steinberger
a4196a4445 fix(ci): cache plugin sdk declarations safely 2026-06-01 04:09:07 -04:00
Vincent Koc
688634ccb9 refactor: share ws health test harness setup 2026-06-01 10:01:27 +02:00
Vincent Koc
060d4a4d2d test(gateway): widen live helper connect budget 2026-06-01 09:00:47 +01:00
Vincent Koc
f2d0fe6417 fix(release): clean cross-os process groups 2026-06-01 10:00:23 +02:00
Vincent Koc
6627b4fbdd perf(ui): guard chat composer controls
Reduce Control UI draft-update work by guarding chat composer controls while keeping locale, session, model, settings, and busy-state invalidation. Verification: focused UI tests, format/lint/typecheck, autoreview clean, and changed gate tbx_01kt12rgjs8c077p2s0wmcsbyf.
2026-06-01 08:56:14 +01:00
Peter Steinberger
3b64ea83e8 fix: migrate legacy OpenAI Codex lastGood auth state 2026-06-01 03:47:43 -04:00
Vincent Koc
1d62f4c014 fix(ci): satisfy scripts lint spread rule 2026-06-01 08:45:42 +01:00
Vincent Koc
3feeb95668 refactor: share minimal gateway test helpers 2026-06-01 09:44:48 +02:00
Vincent Koc
402e2bb81a perf(ui): guard chat transcript rerenders
Reduce Control UI draft-update work by guarding transcript group rendering while preserving assistant attachment availability invalidation. Verification: focused UI tests, format/lint/typecheck, autoreview clean, and changed gate tbx_01kt11qyc20ejbsbt8kd79bamx.
2026-06-01 08:41:04 +01:00
Peter Steinberger
bc470713bb fix(e2e): enable smoke-tested plugin channels 2026-06-01 08:38:50 +01:00
Vincent Koc
3322212f14 fix(ci): tolerate pnpm workspace state on Windows hydrate 2026-06-01 09:36:41 +02:00
Peter Steinberger
7591dc6f4b test(telegram): reset spooled polling handler state 2026-06-01 08:36:32 +01:00
Vincent Koc
6640d57b64 refactor: share websocket connection test harness 2026-06-01 09:29:43 +02:00
Vincent Koc
ac734d8e16 fix(e2e): clean package candidate timeouts 2026-06-01 09:22:07 +02:00
Vincent Koc
0ece07cc20 fix(test): wait for telegram timer flushes
Revert release-time extension lane isolation for Telegram and memory, and make Telegram timer-flush tests wait for async side effects after manually firing timers.

Verification:
- pnpm test:serial extensions/telegram/src/bot.create-telegram-bot.channel-post-media.test.ts extensions/telegram/src/bot.create-telegram-bot.media-group-skip-warning.test.ts extensions/telegram/src/bot.media.stickers-and-fragments.e2e.test.ts extensions/telegram/src/bot.media.downloads-media-file-path-no-file-download.e2e.test.ts test/vitest-scoped-config.test.ts
- pnpm exec oxfmt --check on touched files
- git diff --check on touched files
2026-06-01 08:17:33 +01:00
Vincent Koc
5e09113ede refactor: share selected global session test setup 2026-06-01 09:14:31 +02:00
Vincent Koc
bff66a3e49 perf(ui): skip closed slash menu rerenders
Reduce Control UI typing work by avoiding slash-menu rerenders for ordinary non-command drafts. Verification: focused UI tests, format/lint/typecheck, autoreview clean, and changed gate tbx_01kt1086xrbxfzm85vynsf25hq.
2026-06-01 08:14:16 +01:00
Vincent Koc
8071b06634 perf(ui): debounce chat draft persistence
Debounce draft-only Control UI chat composer persistence while snapshotting pending drafts so session changes and teardown still flush the correct state. Verified with focused UI lifecycle/composer tests, format, oxlint, tsgo core/UI test, clean autoreview, and PR checks.
2026-06-01 08:04:23 +01:00
Vincent Koc
61ffd6bc66 fix(ci): bootstrap raw changed gates from clean checkouts 2026-06-01 08:01:11 +01:00
Vincent Koc
474ec157bc test(scripts): use runner vitest resolver in expectations 2026-06-01 08:01:11 +01:00
Vincent Koc
1377fd82a9 refactor: share openai compat http test helpers 2026-06-01 08:55:28 +02:00
Vincent Koc
8fdb1d0f55 fix(e2e): stream Parallels fresh logs 2026-06-01 08:54:22 +02:00
Vincent Koc
68bfacae03 test(ci): wait for MCP tools list log 2026-06-01 07:49:01 +01:00
Vincent Koc
371617f9ed refactor: share gateway error response assertions 2026-06-01 08:42:59 +02:00
Vincent Koc
69b2c8bd15 perf(ui): record pending send paint timing (#88960) 2026-06-01 07:42:24 +01:00
Vincent Koc
c11ff35841 fix(e2e): bound Parallels update logs 2026-06-01 08:42:08 +02:00
Vincent Koc
ddbd595f2f fix(ci): link Windows hydrate node modules 2026-06-01 08:38:25 +02:00
Vincent Koc
01124cfca9 fix(e2e): clean secret proof timeouts 2026-06-01 08:30:17 +02:00
Vincent Koc
e8f3bce9f0 fix(ci): exempt child process test helper from sdk guard 2026-06-01 07:27:47 +01:00
Vincent Koc
cb0ad281ce perf(ui): cache chat transcript renders (#88952) 2026-06-01 07:27:08 +01:00
Vincent Koc
c429a3c472 fix(codex): skip stale bootstrap history without engine 2026-06-01 07:26:08 +01:00
Vincent Koc
444bdc4286 refactor: share child process test mock helper 2026-06-01 08:22:25 +02:00
Vincent Koc
28550c3847 fix(e2e): harden Parallels host timeouts 2026-06-01 08:15:34 +02:00
Vincent Koc
3e91c688ae fix(ui): scroll pending sends into view
Scroll the chat thread as soon as a submitted pending send is enqueued, so delayed `chat.send` ACKs no longer leave the user's just-sent message below the viewport.

Verification:
- focused UI Vitest suite: 86 tests passed
- oxlint, core tsgo, core-test tsgo, diff check
- Testbox changed gate: tbx_01kt0wspy1ks5wpb6kp5gr0512
- branch autoreview clean
2026-06-01 07:14:07 +01:00
Vincent Koc
4d49a76039 test(secrets): secure plugin exec fixtures 2026-06-01 07:11:28 +01:00
Vincent Koc
988ec0234e fix(agents): validate shell snapshots with trusted env 2026-06-01 07:11:28 +01:00
Vincent Koc
9a7e0d43da fix(codex): accept legacy app-server auth provider 2026-06-01 07:11:28 +01:00
Vincent Koc
f55ff8dd1b fix(codex): skip stale bootstrap history without engine 2026-06-01 07:11:28 +01:00
Vincent Koc
5314a39ee5 refactor: share usage UTC range assertions 2026-06-01 08:03:23 +02:00
Vincent Koc
44cad6f8a4 refactor: simplify wake APNs test mock 2026-06-01 07:59:17 +02:00
Vincent Koc
275caeb5f5 fix(ui): render pending sends in chat thread
Render submitted Control UI sends directly in the chat thread before the Gateway acknowledges `chat.send`.

Pending sends now share acknowledged user-message content rendering for text and attachments, stay searchable with active chat filters, and failed queued sends remain queue-only.

Verification:
- focused UI Vitest suite: 201 tests passed
- oxlint, core tsgo, core-test tsgo, diff check
- Testbox changed gate: tbx_01kt0vnr2bv55aa6x588r77x0z
- autoreview clean
2026-06-01 06:57:05 +01:00
Peter Steinberger
0f2732b066 test(release): isolate telegram extension vitest lane 2026-06-01 06:54:55 +01:00
Vincent Koc
59f1472bd5 refactor: share error coercion helper 2026-06-01 07:41:19 +02:00
Vincent Koc
630f0d6938 refactor: share push test response assertions 2026-06-01 07:36:51 +02:00
Peter Steinberger
6173a4babb docs(plugin-sdk): refresh API baseline 2026-06-01 06:29:51 +01:00
Vincent Koc
6a1b2e6463 refactor: share skills handler test helper 2026-06-01 07:27:52 +02:00
Vincent Koc
fb9e091852 fix(e2e): harden plugin gauntlet cleanup 2026-06-01 07:27:35 +02:00
Peter Steinberger
00399d6c75 test(release): repair beta validation blockers 2026-06-01 06:27:02 +01:00
Peter Steinberger
b23ace1d04 fix(agents): strip streamed reasoning tags (#88924) 2026-06-01 01:26:29 -04:00
Peter Steinberger
db4990d260 refactor: compact copilot sessions through sdk state
Route Copilot compaction through SDK-backed state, remove marker sidecars, preserve auth/session binding behavior in SQLite-backed plugin state, and route Copilot CLI budget compaction through native harness compaction.
2026-06-01 01:18:46 -04:00
Vincent Koc
4550cfa6a7 fix(qa): run plugin MCP probes from repo root 2026-06-01 07:13:24 +02:00
Chunyue Wang
c0195f7ed5 fix(diagnostics): clear embedded-run activity when recovery declares lane idle (#88820)
* fix(diagnostics): clear embedded-run activity when recovery declares lane idle

Stuck-session recovery transitions a lane to idle via the recovery
coordinator, but only mutated the session-state store. When an aborted
embedded run was removed without markDiagnosticEmbeddedRunEnded, the
activity store kept hasActiveEmbeddedRun set, so the liveness sweep
reported idle/embedded_run and isIdleQueuedRecoverableSessionStall
re-triggered recovery indefinitely.

Reconcile the activity store from the authoritative idle declaration by
clearing the session's embedded-run owners. The existing generation
guard already excludes any newer run that re-armed activity, so a live
requeued run is preserved.

* fix(diagnostics): reconcile tool/model activity on authoritative idle cleanup

clearDiagnosticEmbeddedRunActivityForSession (renamed from
clearDiagnosticEmbeddedRunsForSession) now clears the aborted run's tool and
model markers alongside the embedded-run owners, matching the default
markDiagnosticEmbeddedRunEnded teardown. Clearing only the owner set left the
lane as idle + orphaned tool/model activity, which
isIdleQueuedRecoverableSessionStall still treats as recoverable while work is
queued, so the liveness sweep kept re-triggering recovery instead of converging.
Adds regression cases with stale tool and model markers plus queued work.

* test(phone-control): align service mocks with keyed store API

* fix(diagnostics): preserve rearmed recovery activity

* fix(diagnostics): clear recovered owner markers

* fix(diagnostics): clear recovered embedded work keys

* fix(diagnostics): ignore stale same-key recovery owners

* fix(diagnostics): preserve same-session recovery rearm

* fix(diagnostics): ignore stale queued activity starts

* fix(diagnostics): record recovery cutoffs for empty activity

* fix(diagnostics): preserve fresh recovery markers

* fix(diagnostics): prune stale activity before fresh recovery block

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-06-01 01:07:35 -04:00
Tosko4
785849d395 fix(android): add notification app picker 2026-06-01 10:37:19 +05:30
Vincent Koc
12d5043913 refactor: share chat parentid test helpers 2026-06-01 07:06:05 +02:00
Peter Steinberger
d925249ac0 docs(plugin-sdk): refresh API baseline hash 2026-06-01 06:05:37 +01:00
Vincent Koc
74a075077c fix(e2e): harden docker all cleanup 2026-06-01 07:05:15 +02:00
Peter Steinberger
4e57546a87 test(memory): isolate qmd timer state in prerelease shard 2026-06-01 06:03:43 +01:00
Neerav Makwana
711ab45025 fix(agents): clear legacy auto fallback pins (#87484)
* fix(agents): clear legacy auto fallback pins

* fix(agents): repair legacy auto-fallback test mock and tighten review feedback

Add hasLegacyAutoFallbackWithoutOrigin to the live-model-switch agent-scope mock so the agents-core lane runs, simplify the redundant hasSessionModelOverride guard, use a single source of truth for the legacy-pin staleness check with a comment on the load-bearing modelKey guard, and add preservation/edge-case/guard regression coverage. Rename the misleading primary-probe agent test.

* style(agents): format rebased fallback fix

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-06-01 01:03:31 -04:00
Vincent Koc
e7e21caa20 fix(ui): keep first control chat sends responsive
Make first Control UI chat sends visibly queue during pending model saves, preserve early streaming deltas that arrive before chat.send ACK, and keep model-wait queued prompts scoped/retryable across session switches.
2026-06-01 05:59:04 +01:00
amittell
945faf8e67 fix(memory-lancedb): reject envelope metadata sludge
Summary:
- Strip memory-lancedb envelope and metadata sludge before auto-capture/recall, including pending history wrappers, current-message reply context, message-tool delivery hints, media annotations, and marker-free channel envelopes.
- Expose bundled chat-channel IDs/prefixes through the plugin SDK so sanitizer matching follows the channel catalog.
- Refactor cron tool schemas to fresh factory instances while preserving runtime nullable clears and provider-facing OpenAPI projection.

Verification:
- git diff --check origin/main...HEAD
- ./node_modules/.bin/oxfmt --check src/plugin-sdk/chat-channel-ids.ts src/plugin-sdk/chat-channel-ids.test.ts extensions/memory-lancedb/index.ts extensions/memory-lancedb/index.test.ts src/agents/tools/cron-tool.ts src/agents/tools/cron-tool.schema.test.ts
- pnpm plugin-sdk:api:check
- node scripts/run-vitest.mjs run src/plugin-sdk/chat-channel-ids.test.ts extensions/memory-lancedb src/agents/tools/cron-tool.schema.test.ts src/agents/tools/cron-tool.test.ts --reporter=dot
- pnpm lint:extensions --threads=8
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
- GitHub checks on 62d1da1257: 139 pass, 0 pending, 0 fail, 22 skipped.
2026-06-01 00:57:25 -04:00
Vincent Koc
1aa1a70ac5 test(installer): isolate install shell HOME 2026-06-01 05:55:34 +01:00
Vincent Koc
abe2145153 refactor: share cron delivery test fixture 2026-06-01 06:52:52 +02:00
Vincent Koc
0ae0051ae7 feat(ui): improve Workboard task details
Make Workboard cards compact by moving expanded task/run metadata, proof, diagnostics, worker logs, automation, protocol state, events, and operator notes into a detail drawer.

Keep execution state simple and safe: active, linked, and archived cards avoid duplicate start paths; stale task cache is ignored when session lifecycle is authoritative; recent proof/events stay visible; dispatcher capacity distinguishes unclaimed review cards from claimed cards.
2026-06-01 05:52:40 +01:00
Vincent Koc
5957bfdc54 fix(e2e): fail bundled smoke on missing channels 2026-06-01 06:45:58 +02:00
Vincent Koc
e843a3612b refactor: inline secrets error response guard 2026-06-01 06:40:17 +02:00
Vincent Koc
8cab0f23f8 fix(e2e): clean bundled runtime smoke state 2026-06-01 06:35:28 +02:00
Vincent Koc
296cd8c912 fix(plugin-sdk): isolate provider catalog projection failures (#88767)
* fix(plugin-sdk): isolate provider catalog projection failures

* fix(plugin-sdk): share safe provider catalog projection

* fix(cron): preserve raw null clear schema

* fix(plugin-sdk): copy provider catalog model rows safely

* fix(plugin-sdk): keep id-only catalog models

* fix(plugin-sdk): require readable provider catalog base url

* fix(ci): satisfy cron and matrix lint checks

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-06-01 00:35:19 -04:00
Vincent Koc
3386bf989f refactor: share secrets resolve test helper 2026-06-01 06:31:03 +02:00
Peter Steinberger
5b79e81569 fix: harden CLI and plugin edge cases (#88896)
* fix: harden CLI and plugin edge cases

* fix: preserve explicit TTS provider credentials

* fix: preserve direct TTS credentials

* fix: type TTS credential hydration config

* fix: preserve scoped TTS channel credentials

* fix: pin hydrated TTS runtime config

* fix: satisfy TTS hydration lint

* fix: preserve inherited TTS provider keys

* fix: read resolved TTS provider keys
2026-06-01 00:30:12 -04:00
Vincent Koc
ec6ad888a4 fix(e2e): bound telegram proof commands 2026-06-01 06:26:44 +02:00
Kip
c213827aa5 fix(cron): include job name when reading single-job run history (#88294)
* fix(cron): include job name in single-job run history

The cron.runs gateway handler enriches log entries with jobName in the all-jobs scope, but the single-job scope did not pass any job-name lookup into the SQLite run-log reader. Entries returned for one job could therefore reach Control UI without jobName, making the run-history title fall back to the raw job id.

Build a one-entry jobNameById map for the current job and pass it through the same reader enrichment path used by all-jobs history. If the job no longer exists, the map stays undefined and existing fallback behavior is unchanged.

* test(cron): cover single-job run history job name enrichment

Asserts that readCronRunLogEntriesPage stamps a supplied jobNameById map onto single-job page entries, matching the gateway data shape used for both all-jobs and single-job cron.runs responses.

Addresses review feedback on #88294.

* test(cron): preserve nullable tool schema validation

* test(cron): assert runtime nullable tool schema

* test(cron): refresh prompt snapshots

---------

Co-authored-by: Kip Claw <kip@kipclaw.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-06-01 00:25:39 -04:00
Vincent Koc
dc9e67d2d4 refactor: share tools catalog test helpers 2026-06-01 06:13:33 +02:00
Peter Steinberger
b2a1c5caa8 test(matrix): keep async monitor callbacks lint-clean 2026-06-01 05:11:28 +01:00
Vincent Koc
51bad9b319 refactor: share config open file test helpers 2026-06-01 06:08:13 +02:00
Vincent Koc
fb17986af5 fix(ci): preserve hydrated Windows test deps 2026-06-01 06:08:10 +02:00
Vincent Koc
17245a0890 fix(test): bound qa otel smoke runs 2026-06-01 06:04:30 +02:00
Peter Steinberger
3b802a7fbc docs(plugin-sdk): refresh API baseline hash 2026-06-01 04:59:39 +01:00
Vincent Koc
e9c7a64c5e refactor: share update test helpers 2026-06-01 05:58:33 +02:00
Peter Steinberger
817c4ce4fc test(release): stabilize installer and matrix async checks 2026-06-01 04:55:21 +01:00
Vincent Koc
d4240cde5b refactor: share native hook relay test helpers 2026-06-01 05:48:14 +02:00
Ted Li
6cb06f5fbc fix(reply): preserve sessions_send external routes (#88803)
* fix(reply): preserve sessions_send external routes

* fix(reply): preserve inherited route thread ids

* fix(reply): keep sessions_send delivery single-owner

* fix(reply): satisfy dispatch route lint

* fix(reply): preserve inherited ACP route metadata

* test(reply): type inherited route event assertions

* test(ci): satisfy current lint rules

* fix(reply): avoid stale inherited route threads

* fix(reply): trust explicit inherited route threads

* fix(reply): require trusted route thread sources

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-31 23:43:05 -04:00
Firas Alswihry
70c59f59b2 feat(dreaming): score candidates with shadow trial results
Add report-only memory-core dreaming shadow trial scoring and ranking helpers. Keep rank lookup keyed by durable candidate keys and document the advisory behavior. Thanks @iFiras-Max1.
2026-05-31 23:40:20 -04:00
Vincent Koc
a30c12e711 refactor: share restart test helpers 2026-06-01 05:38:35 +02:00
Vincent Koc
56a7000b3e fix(mattermost): route send attachments through upload
Routes Mattermost send attachments through the upload path so local file paths and structured attachment media are uploaded instead of being posted as plain text. Preserves scoped media access for local uploads, rejects unsupported or ambiguous attachment payloads, and keeps HTTP media fallback behavior.

Fixes #87930.

Proof:
- autoreview clean
- node scripts/run-vitest.mjs extensions/mattermost/src/channel.test.ts extensions/mattermost/src/channel.message-adapter.test.ts extensions/mattermost/src/mattermost/send.test.ts src/infra/outbound/message-action-params.test.ts src/infra/outbound/outbound-send-service.test.ts src/infra/outbound/message-action-runner.media.test.ts src/media/load-options.test.ts
- pnpm prompt:snapshots:check
- GitHub Actions completed with no pending/failing checks for head 2a65cbb1ee
2026-05-31 23:38:17 -04:00
Vincent Koc
5054b20832 fix(test): harden secret provider proof cleanup 2026-06-01 05:37:45 +02:00
Vincent Koc
a5ee3569d3 test(ci): refresh cron prompt snapshots 2026-06-01 04:33:39 +01:00
Peter Steinberger
33349269fd fix: wake legacy cron jobs without enabled 2026-05-31 23:31:44 -04:00
Vincent Koc
2dcee8ac2b refactor: share webchat media audio fixture 2026-06-01 05:28:03 +02:00
Peter Steinberger
e2c9c06de1 fix: advance exact-boundary every schedules 2026-05-31 23:27:24 -04:00
Peter Steinberger
ebcdb637bb perf(memory-core): defer embedding engine startup imports 2026-06-01 04:22:22 +01:00
Peter Steinberger
592b6e2916 docs(config): refresh config baseline hash 2026-06-01 04:20:57 +01:00
Peter Steinberger
45b5f876dd fix: reject blank cron payloads 2026-05-31 23:20:04 -04:00
Vincent Koc
76fa1b99c3 fix(test): bound test group report runs 2026-06-01 05:17:27 +02:00
Vincent Koc
aab1e727c6 refactor: share chat abort authorization helpers 2026-06-01 05:16:37 +02:00
Vincent Koc
a46d331723 fix(ci): reword durable final alias comment 2026-06-01 04:12:46 +01:00
Vincent Koc
916ee82814 test(installer): isolate install shell snippets 2026-06-01 04:11:22 +01:00
Vincent Koc
fcc279e233 fix(test): avoid Vite runtime import in UI config helpers 2026-06-01 04:08:53 +01:00
Vincent Koc
9dd7f04b71 fix(ci): repair phone control and cron schema gates 2026-06-01 04:06:25 +01:00
Vincent Koc
6e985931de refactor: share models list test helper 2026-06-01 05:05:20 +02:00
Vincent Koc
dc1cfcc28d refactor: share tasks handler test helpers 2026-06-01 05:05:20 +02:00
Peter Steinberger
ee6373aa5f fix: preserve cron failure destination clears 2026-05-31 23:04:31 -04:00
Peter Steinberger
6deded6698 fix: raise bootstrap file default limit 2026-06-01 04:02:51 +01:00
Peter Steinberger
f879e3d6a0 docs(plugin-sdk): refresh API baseline hash 2026-06-01 04:01:25 +01:00
Vincent Koc
f42cf9059e fix(ci): repair phone control and cron schema gates 2026-06-01 04:00:18 +01:00
Andy Ye
c317fd2bd7 docs(imessage): document SSH wrapper TCC send failure (#88758) 2026-05-31 23:00:08 -04:00
Vincent Koc
be967545c5 fix(plugins): fail closed on trusted policy errors
Fail closed when bundled trusted tool policy registry, registration, owner id, evaluation, or decision reads fail, so malformed trusted-policy state cannot crash diagnostics or accidentally allow a tool call.

Route before-tool-call diagnostics through guarded trusted-policy readers and keep healthy no-op policy behavior unchanged.

Add focused host-hook contract and before-tool-call e2e coverage for the new fail-closed paths.

PR: #88394
2026-05-31 22:57:38 -04:00
Nayrosk
388ba3218b fix(ui): bypass service worker for top-level navigations
HTTP auth challenges (basic, digest, negotiate) only fire the browser's
native credentials dialog when the response comes straight from the
network. Service worker responses bypass the WWW-Authenticate flow, so
reverse-proxy deployments with HTTP auth in front of the gateway show
a bare 401 after the browser's HTTP-auth memory cache expires (e.g. on
full browser restart) — forcing users to clear site data to recover.

Skip event.request.mode === "navigate" so the browser handles those
requests natively. Offline navigation of the app shell is lost, but
the SPA cannot function without network (all API calls go to the
network), so the trade-off is acceptable.

Refs: #85939, #71669, #53274
2026-05-31 22:57:27 -04:00
Peter Steinberger
7722ade22e test(install): clear node lookup cache in floor check 2026-06-01 03:56:37 +01:00
Vincent Koc
b2b9fbe033 fix(test): bound mock OpenAI request bodies 2026-06-01 04:48:32 +02:00
Peter Steinberger
551c9637d8 fix(ios): polish iPad gateway setup 2026-06-01 03:47:09 +01:00
Vincent Koc
c5eddadd9d refactor: share channel start test helpers 2026-06-01 04:40:21 +02:00
Vincent Koc
98b8e85beb refactor: share agent wait dedupe test helpers 2026-06-01 04:35:37 +02:00
Vincent Koc
a9938907dc fix(test): harden MCP E2E proof checks 2026-06-01 04:34:25 +02:00
Peter Steinberger
4c824aa809 perf(phone-control): use startup config for expiry guard 2026-06-01 03:32:38 +01:00
Peter Steinberger
1e7510ae10 docs: continue inline comment pass (#88849)
Adds broad inline comments and JSDoc for CLI, cron, outbound/channel, plugin SDK, ACP, shared helpers, net policy, and related utility contracts. Proof: git diff --check on latest exact head plus focused cron tests passed; CI had no failing checks observed before merge attempt.
2026-05-31 22:32:28 -04:00
Peter Steinberger
4932391e8a fix(ui): scope global agent model controls 2026-05-31 22:25:43 -04:00
Vincent Koc
822864c539 refactor: share channel status test helpers 2026-06-01 04:24:57 +02:00
Vincent Koc
a7ae3f6707 refactor: share usage session test state setup 2026-06-01 04:24:57 +02:00
Dallin Romney
78165cc387 docs: clarify diffs language pack additions (#88865) 2026-05-31 19:24:45 -07:00
Peter Steinberger
44765cfabe fix(acpx): seed Codex ACP auth from API key 2026-05-31 22:24:29 -04:00
Vincent Koc
0c3644cb24 perf(ui): stream stable markdown blocks 2026-06-01 03:23:47 +01:00
Peter Steinberger
53a7545ae3 perf(phone-control): avoid disarmed startup state lookup 2026-06-01 03:19:08 +01:00
Andy Ye
921598442a fix(hooks): expose inbound reply metadata before dispatch
Fixes #88521.

Expose finalized inbound reply metadata on plugin-visible hook payloads so before_dispatch and message hooks can implement reply-aware behavior without channel-specific workarounds.
2026-05-31 22:15:17 -04:00
Peter Steinberger
e72def6983 Persist Discord thread bindings in SQLite (#88866)
* refactor: persist discord thread bindings in sqlite

* test: read discord thread bindings from sqlite smoke
2026-05-31 22:10:30 -04:00
ksj3421
45bdaa2f7b fix(agents): return schema lookup misses in-band
Return unknown config.schema.lookup paths as an in-band agent gateway tool result instead of throwing into channel warning surfaces.

The direct gateway RPC still reports INVALID_REQUEST, preserving the existing protocol contract, while the agent-facing gateway tool returns schema_path_not_found for exploratory misses.

Fixes #88813.
Thanks @ksj3421.
Reported by @cjalden.
2026-05-31 22:10:02 -04:00
Vincent Koc
91ca036717 test(agents): use neutral tool schema fixtures (#88848) 2026-05-31 22:09:48 -04:00
Ted Li
c002887223 fix(memory): rehydrate daily list promotions
* fix(memory): rehydrate daily list promotions

* fix(memory): preserve multi-line daily list promotions

* fix(memory): preserve daily list promotion context

* fix(memory): rehydrate capped daily list promotions

* test(memory): cover capped daily list promotion

* test(agents): update model selection mocks

* ci: ignore lazy three dependency

* fix(memory): skip heading-only rehydration

* fix(memory): preserve list rehydration mode

* fix(memory): match capped renamed heading bodies

* fix(memory): avoid duplicate tail heading matches

* fix(microsoft-foundry): satisfy provider lint

* perf(memory): precompute promotion heading context

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-31 22:08:35 -04:00
Peter Steinberger
912ea4897f fix: scope global in-flight history to default agent 2026-06-01 03:08:29 +01:00
Peter Steinberger
6ad73e173b fix: keep hidden runs out of visible chat state 2026-06-01 03:08:29 +01:00
Vincent Koc
6c73ffc51a fix(test): bound MCP code mode client responses 2026-06-01 04:05:23 +02:00
Dallin Romney
632447d66d test(ui): remove stylesheet grep tests (#88847) 2026-05-31 19:05:02 -07:00
Dallin Romney
4b56c44c02 test: consolidate plugin registration contracts (#88824) 2026-05-31 19:04:53 -07:00
Peter Steinberger
d86b6da012 fix: allow cron delivery clears 2026-05-31 22:04:25 -04:00
Vincent Koc
d2c5ad2b36 refactor: share commands test helpers 2026-06-01 04:01:02 +02:00
Dallin Romney
b097cec219 fix(microsoft-foundry): satisfy extension lint (#88855) 2026-05-31 18:58:56 -07:00
Vincent Koc
207359a056 fix(ci): repair current main checks
Summary:
- Guard child-session candidate lookup when the session store is absent.
- Refresh Talk UI and compaction rotation tests for current main.
- Clean up Microsoft Foundry provider lint that blocked the refreshed CI lane.

Verification:
- node scripts/run-vitest.mjs src/gateway/session-utils.test.ts ui/src/ui/views/chat.test.ts src/agents/agent-command.compaction-rotation.test.ts --reporter=dot
- node scripts/run-vitest.mjs extensions/microsoft-foundry/index.test.ts --reporter=dot
- node_modules/.bin/oxfmt --check --threads=1 extensions/microsoft-foundry/provider.ts src/gateway/session-utils.ts ui/src/ui/views/chat.test.ts src/agents/agent-command.compaction-rotation.test.ts
- node scripts/run-oxlint.mjs extensions/microsoft-foundry/provider.ts src/gateway/session-utils.ts ui/src/ui/views/chat.test.ts src/agents/agent-command.compaction-rotation.test.ts
- pnpm lint --threads=8
- autoreview clean
- GitHub checks on f96270ed7e: 135 success, 29 skipped, 1 neutral, 0 pending/failing

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-05-31 21:57:07 -04:00
Rohit
3fc485ca92 fix(browser): isolate Chrome MCP pending attach aborts (#88305)
* fix(browser): isolate Chrome MCP pending attach aborts

* fix(browser): evict closing Chrome MCP sessions

* fix(browser): clean chrome mcp pending session lifecycle

* fix(browser): handle stale chrome mcp pending sessions

* fix(browser): serialize stale chrome mcp replacement

* fix(browser): skip cancelled chrome mcp attach

* fix(browser): retire timed-out chrome mcp pending sessions

* fix(browser): retire stale chrome mcp after readiness

* fix(browser): keep shared chrome mcp timeouts isolated

* fix(browser): bound stale chrome mcp ready retries

* fix(browser): narrow pending session lease release

* fix(browser): keep ephemeral probes out of pending attaches

* fix(foundry): satisfy provider lint

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-31 21:55:38 -04:00
Peter Steinberger
2b184ac3a0 docs(changelog): refresh 2026.5.31 notes 2026-06-01 02:52:49 +01:00
Vincent Koc
be1273182e refactor: share models auth status test helpers 2026-06-01 03:49:46 +02:00
Vincent Koc
c764eb96c4 fix(test): tolerate vanished RPC gateway teardown 2026-06-01 03:48:59 +02:00
Peter Steinberger
0369672691 feat(minimax): add m3 model support (#88860) 2026-05-31 21:47:47 -04:00
Vincent Koc
9919e4601f refactor: share skills clawhub test helpers 2026-06-01 03:38:39 +02:00
Vincent Koc
b6bac3cc2b test(agents): include Ollama in small live model matrix (#87838)
* test(agents): include Ollama in small live model matrix

* test: avoid Ollama cloud key in local live runs

* test: recognize Ollama env secret refs

* test: type Ollama live key fixtures

* test: prevent Ollama cloud auth in local live probes

* test: preserve equivalent Ollama live credentials

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-31 21:38:31 -04:00
Peter Steinberger
72bc9ae952 fix: keep cron update delivery validation scoped 2026-05-31 21:32:23 -04:00
Peter Steinberger
d2f1c0eac8 fix: harden cron validation and restart state 2026-05-31 21:32:23 -04:00
kiranmagic7
cc97eca9b1 test(installer): keep Node floor tied to package engine
Adds a focused installer regression test tying install.sh's accepted Node 22 floor to the package engine floor. Thanks @kiranmagic7.
2026-05-31 21:32:00 -04:00
Vincent Koc
dbc83b4213 refactor: share chat reply media test helpers 2026-06-01 03:29:30 +02:00
Vincent Koc
2d0c755013 fix(test): order unit-fast fake-timer project 2026-06-01 02:24:48 +01:00
Peter Steinberger
fb64546d9e fix: preserve no-policy native hook fallback
Keep selected no-policy Codex PreToolUse relay hooks installed with an explicit unavailable no-op marker, while unknown unavailable PreToolUse and PermissionRequest still fail closed.

Refs #87543.
Replaces #88620.

Verification:
- pnpm test extensions/codex/src/app-server/native-hook-relay.test.ts src/agents/harness/native-hook-relay.test.ts src/cli/native-hook-relay-cli.test.ts
- pnpm lint --threads=8
- autoreview --mode branch --base origin/main
- GitHub CI run 26729700996, Real behavior proof 26729874455, OpenGrep 26729701010, CodeQL high 26729701003

Co-authored-by: woodym-dotcom <266261448+woodym-dotcom@users.noreply.github.com>
2026-05-31 21:24:09 -04:00
EmpX2025
83f290005a feat(ios): support native iPad display
Make the iOS app a universal iPhone+iPad app by targeting device family 1,2 in the XcodeGen source of truth.

Update iOS docs and App Store metadata so user-facing copy no longer describes the app as iPhone-only.

Verification:
- git diff --check
- cd apps/ios && xcodegen generate
- xcodebuild -project apps/ios/OpenClaw.xcodeproj -scheme OpenClaw -configuration Debug -destination 'platform=iOS Simulator,id=410B81D3-784E-4A01-B69C-490B79EAFCEA' CODE_SIGNING_ALLOWED=NO build
- GitHub CI: Real behavior proof, macos-swift, macos-node, check-docs, preflight, security-fast, actionlint, no-tabs, dependency-guard, OpenGrep

Thanks @EmpX2025.
2026-05-31 21:23:33 -04:00
William Liu AI
8eeb9300df fix: restore in-flight TUI run switch-back
Restore TUI switch-back adoption for backgrounded visible chat-send runs by surfacing a bounded `chat.history.inFlightRun` snapshot.

The snapshot keeps the run id even when buffered text is empty or over budget, filters live text through the same projection path as streaming chat, scopes bare global history to the default agent, and excludes hidden internal agent runs.

Proof:
- node scripts/run-vitest.mjs run src/gateway/chat-abort.test.ts src/tui/tui-session-actions.test.ts
- node scripts/run-tsgo.mjs -p tsconfig.core.json
- pnpm --silent exec oxfmt --check src/gateway/chat-abort.ts src/gateway/chat-abort.test.ts src/gateway/server-methods/chat.ts src/tui/tui-session-actions.ts src/tui/tui-session-actions.test.ts
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
- CI: Real behavior proof, TUI PTY, dependency guard, OpenGrep precise diff, workflow sanity passed on PR head 2b8bf5f214.

Co-authored-by: William Liu <william@williamliu.ai>
2026-05-31 21:22:52 -04:00
Vincent Koc
52c809a759 fix(infra): bridge WSL clipboard through shell
* fix(infra): bridge WSL2 clipboard through shell

* test(infra): assert wsl clipboard argv stays token-free

* fix(infra): keep wsl clipboard timeout ownership
2026-05-31 21:22:08 -04:00
elfka toruviel
f22e39823d fix(doctor): respect explicit PI runtime policy
Respect explicit PI/OpenClaw runtime policy when deciding whether Codex plugin diagnostics are actionable.

Diagnostics now use the resolved OpenAI route: intentional PI and custom OpenAI-compatible routes suppress only the missing `plugins.entries.codex` noise, while enabled/stale Codex policy still warns.

Proof: focused doctor/config/agent routing Vitest coverage, full lint, test types, dependency checks, isolated live doctor configs, autoreview clean, and GitHub CI green at c5a84de4ca.

Fixes #88706.

Co-authored-by: Elfka Toruviel <aeb31988340aa87b@toruviel.online>
2026-05-31 21:21:11 -04:00
Vincent Koc
30bde29893 refactor: share config auth test helpers 2026-06-01 03:20:04 +02:00
Peter Steinberger
6b940ed3ca perf: streamline chat startup metadata (#88825)
* perf: streamline chat startup metadata

* fix: defer global queued agent selection

* style: format gateway startup refresh
2026-05-31 21:18:41 -04:00
Andy Ye
1b10739d60 fix(agents): guard vanished workspaces
Fixes #88333

Preserves contributor workspace contents when an attested workspace disappears or is partially regenerated, and clears OpenClaw-owned attestation state on delete/reset/uninstall.

Co-authored-by: Andy Ye <35905412+TurboTheTurtle@users.noreply.github.com>
2026-05-31 21:14:54 -04:00
Vincent Koc
efd5d07734 fix(ci): preserve lint cleanup behavior 2026-06-01 03:12:53 +02:00
Peter Steinberger
1d4277b071 refactor: persist openrouter model cache in sqlite (#88851) 2026-05-31 21:12:43 -04:00
Vincent Koc
b029634bd6 refactor: share cron validation test helpers 2026-06-01 03:08:54 +02:00
Vincent Koc
af927038cc test(gateway): fail strict codex subagent timeouts 2026-06-01 03:08:02 +02:00
Peter Steinberger
5b0c4c0491 fix: align Foundry chat reasoning metadata 2026-06-01 02:05:38 +01:00
Vincent Koc
570e2db252 fix(plugins): isolate cached tool runtime siblings 2026-05-31 21:05:23 -04:00
Vincent Koc
53990d5bbf fix(plugins): isolate web provider factory failures (#88807) 2026-05-31 21:04:18 -04:00
NVIDIAN
37169697d7 fix(status): resolve gateway auth secrets for deep audit
Resolve gateway auth SecretRef targets in status deep audit.

The static secret target coverage now includes gateway auth and remote token/password keys for both status and security audit scans. Focused status/secret-target tests passed, Auto Review reported no actionable findings, and CI is running on rebased head 41b052a181.

Fixes #87815
2026-05-31 21:02:11 -04:00
Alix-007
909c24e3b7 fix(config): skip state-dir dotenv values that are unresolved shell references (#88288)
* fix(config): skip state-dir dotenv values that are unresolved shell references

readStateDirDotEnvVarsFromStateDir accepted any non-empty value from the
state-dir .env file and passed it into the managed service env. When a value
contains an unresolved shell variable reference such as "${SUPERMEMORY_KEY}"
or "$MY_VAR", dotenv preserves the literal string. The value then reaches
the LaunchAgent/systemd wrapper as a single-quoted literal, so the credential
is never resolved.

Add containsUnresolvedShellReference() and skip any value matching
$IDENTIFIER, ${...}, or $(...) in parseStateDirDotEnvContent(). Real credential
values (e.g. "sm_abc123") are unaffected.

Fixes #88274

* fix(config): narrow shell-reference detector to whole-value patterns only

The previous /$[\w{(]/ regex matched any value containing $ followed by
a word character, which would incorrectly drop real credentials that merely
contain a dollar sign (e.g. a password like abc$2!xyz).

Replace with isUnresolvedShellReference() that only matches values whose
ENTIRE content is a recognised reference form:
  - $VAR_NAME (simple reference)
  - ${VAR_NAME} (brace-form reference)
  - $(command) (command substitution)

Add a regression test that verifies dollar-bearing real secrets are kept.

* fix(config): use letter/underscore-anchored pattern to avoid matching dollar-numbers

$100, $2, etc. are NOT shell variable references — shell variable names must
begin with a letter or underscore. The previous /^$[\w_]/ would match them.

Change to /^$[A-Za-z_]\w*$/ so only genuine named-variable references like
$MY_VAR are rejected. Dollar-number sequences are now preserved.

* fix(daemon): drop stale systemd env-file refs for skipped state-dir dotenv keys

When a state-dir .env value is an unresolved shell reference ($VAR/${VAR}/$(cmd))
the parser skips it from the managed environment. A prior install could have
written that literal reference into gateway.systemd.env; because the skipped key
no longer appeared in the incoming env or the managed-key removal sets, the stale
literal survived re-stage and could override fresh inline Environment= values.

Surface the skipped shell-reference keys from the state-dir dotenv parser and add
them to the systemd env-file managed-key removal set so re-staging strips the
obsolete literal while preserving operator-only secrets that were never managed
via state-dir .env. launchd regenerates its env file wholesale, so it is
unaffected.

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

* fix(config): skip quoted shell parameter dotenv refs

* fix(config): preserve lowercase dollar-prefixed dotenv literals

* fix(daemon): clear stale unresolved systemd env refs

* fix(daemon): avoid re-staging unresolved file env refs

* fix(daemon): drop unresolved file env refs inline

* fix(daemon): drop inline-and-file unresolved env refs

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-31 21:01:33 -04:00
Vincent Koc
732748c8c5 perf(ui): skip markdown parsing while chat streams 2026-06-01 02:00:06 +01:00
Brian
fda5254e99 fix: preserve npm plugin root on blocked install (#77237)
Preserve the active per-plugin managed npm project when npm-backed install validation blocks a candidate after npm has already mutated local state.

This snapshots package.json, package-lock.json, and node_modules before managed npm installs, restores that exact project state on failed validation, and rolls back staged npm-pack archives so blocked pack installs do not leave candidate debris.

Validation:
- OPENCLAW_VITEST_MAX_WORKERS=1 node scripts/run-vitest.mjs src/plugins/install.npm-spec.test.ts
- pnpm tsgo:core && pnpm tsgo:core:test
- node scripts/run-oxlint.mjs src/plugins/install.ts src/plugins/install.npm-spec.test.ts
- .agents/skills/autoreview/scripts/autoreview --mode local
- GitHub CI 26729255950
- Crabbox run_26e9f9f7591c

Thanks @zhuisDEV.

Co-authored-by: Brian <95547369+zhuisDEV@users.noreply.github.com>
2026-05-31 20:59:32 -04:00
Vincent Koc
9da4835cdf refactor: share artifacts test helpers 2026-06-01 02:57:01 +02:00
Vincent Koc
43ced7bc49 fix(ui): preserve startup chat sends during history load 2026-06-01 01:52:58 +01:00
Vincent Koc
49b62079f7 fix(ui): unblock initial control chat send 2026-06-01 01:52:58 +01:00
Andy Ye
432312a17c test: cover Vertex API key model config
Adds regression coverage for Google Vertex API-key model config planning when the credential comes from an env-backed auth profile. This keeps the planner-level guard around the Vertex static catalog rows that fixed #88816 on main.

Verification:
- `node scripts/run-vitest.mjs src/agents/models-config.applies-config-env-vars.test.ts extensions/google/provider-catalog.test.ts extensions/google/provider-models.test.ts`
- `./node_modules/.bin/oxfmt --check --threads=1 src/agents/models-config.applies-config-env-vars.test.ts extensions/ollama/src/stream.ts extensions/qa-lab/src/mantis/slack-desktop-smoke.runtime.ts extensions/qa-lab/src/mantis/telegram-desktop-builder.runtime.ts extensions/qa-lab/src/mantis/visual-task.runtime.ts`
- `git diff --check`
- `pnpm deadcode:dependencies`

CI note: PR CI had an unrelated `check-dependencies` failure for `ui/package.json: three`; the PR diff is one `src/agents` test file.

Refs #88816
2026-05-31 20:51:50 -04:00
Peter Steinberger
5443baa852 Persist plugin install index in SQLite (#88794)
* refactor: persist plugin install index in sqlite

* fix: merge legacy plugin index records into sqlite

* test: update plugin index sqlite fixtures

* fix: migrate custom plugin install indexes

* test: update plugin index sentinel

* fix: exclude migrated plugin index archives

* fix: read post-upgrade plugin index from sqlite

* fix: migrate legacy plugin index before agent runs

* fix: respect disabled persisted plugin registry reads

* test: type plugin install record fixtures

* fix: simplify plugin index record reader type

* test: fix sqlite plugin index CI fallout

* test: mock provider normalization in agent command tests

# Conflicts:
#	src/commands/agent-command.test-mocks.ts

* build: remove unused ui three dependency
2026-05-31 20:51:33 -04:00
Vincent Koc
b475de834a refactor: share plugin approval test helpers 2026-06-01 02:45:37 +02:00
Matthew Schleder
6a96058f50 fix(minimax): use account oauth endpoints
Routes MiniMax OAuth device-code and token polling directly to account-hosted OAuth2 endpoints for global and CN regions, avoiding guarded-fetch cross-origin redirect body stripping. Keeps provider API base URLs unchanged and adds regression coverage for both endpoint pairs.

Proof: local minimax OAuth tests, oxfmt check, lint, autoreview clean, official MiniMax CLI/source check, live MiniMax endpoint probes, and CI run 26729242892 on 6bfe20eb06.

Co-authored-by: Matt Schleder <schledermatthew@gmail.com>
2026-05-31 20:44:41 -04:00
Vincent Koc
82d24b26ea fix(workboard): wire task-backed board runs
Summary:
- remove the leftover Workboard mini-game/prototype surface
- wire autonomous Workboard card starts through Gateway task-backed agent runs
- reconcile card task/session lifecycle for starts, stops, stale tasks, reassignment, and default-agent sessions
- clarify dispatch summary copy and admin-only model override behavior

Verification:
- autoreview clean: no accepted/actionable findings
- targeted Workboard/UI Vitest: 72 tests passed
- Workboard extension Vitest: 9 tests passed
- UI build, docs list, docs format, diff check, and focused oxlint passed
- PR CI checks: 50 ok, 0 attention
- Testbox tbx_01kt07mk5sjyj2whjq2sc967hg: pnpm verify check phase passed; broad test phase exposed unrelated latest-main failures/stalls in memory, Codex app-server, provider timeout, command daemon env, Telegram worker OOM, and gateway-client timeout suites
2026-06-01 01:41:21 +01:00
Vincent Koc
015c6b40ae fix(ci): clear extension lint regressions 2026-06-01 01:36:16 +01:00
Vincent Koc
915c156115 refactor: share tools effective test helpers 2026-06-01 02:33:47 +02:00
Vincent Koc
b3742b9edb fix(ui): stream chat deltas incrementally 2026-06-01 01:32:48 +01:00
Vincent Koc
bcaf326c3a refactor: share sessions abort scope test helpers 2026-06-01 02:21:44 +02:00
Vincent Koc
3c7c03f236 test(ci): update agent command model-selection mocks 2026-06-01 01:18:09 +01:00
Peter Steinberger
7562afdca3 fix(ollama): suppress disabled reasoning output 2026-06-01 01:16:47 +01:00
Peter Steinberger
27dde7a4d6 chore(lint): enable stricter error rules 2026-06-01 01:12:21 +01:00
Vincent Koc
0bfba7e26d fix(ui): detect system chromium for e2e 2026-06-01 01:09:46 +01:00
Vincent Koc
d95471afef test: type manifest catalog mock 2026-06-01 02:06:26 +02:00
Vincent Koc
69c948a752 refactor: share web start test snapshot 2026-06-01 02:06:26 +02:00
Andy Ye
002c1d2d5a test(agents): cover nonfatal trajectory flush timeout
Fixes #88520.

Adds focused regression coverage for the embedded attempt trajectory recorder cleanup boundary so a stalled trajectory flush resolves after the cleanup timeout and logs pending write details instead of rejecting attempt cleanup.

Verification:
- node scripts/run-vitest.mjs src/agents/run-cleanup-timeout.test.ts
- git diff --check origin/main...origin/pr/88802
- PR CI green: https://github.com/openclaw/openclaw/actions/runs/26727232564

Co-authored-by: Andy Ye <35905412+TurboTheTurtle@users.noreply.github.com>
2026-05-31 20:01:12 -04:00
Vincent Koc
2fc5072021 fix(ci): repair Copilot thinking compat types 2026-06-01 00:53:35 +01:00
Vincent Koc
160aad6fb3 fix(agents): preserve exact custom provider models 2026-06-01 01:50:30 +02:00
Vincent Koc
dd8d52c7d9 refactor: share optional model catalog loading 2026-06-01 01:49:51 +02:00
Peter Steinberger
219d854178 fix: keep tool detail redaction canonical 2026-06-01 00:49:43 +01:00
Vincent Koc
37d79a4303 test(ui): make chat sessions e2e deterministic 2026-06-01 00:45:29 +01:00
Ted Li
6316648bab fix(openai): keep stop-finished tool calls
Preserve silent structured OpenAI-compatible tool calls when providers stream tool_calls but finish with finish_reason stop, while keeping visible-text stop responses and unfinished streams from executing spurious tool calls.

Fixes #88791.

Verification:
- pnpm tsgo:prod
- node scripts/run-vitest.mjs src/llm/providers/openai-completions.test.ts src/agents/openai-transport-stream.test.ts
- loopback OpenAI-compatible SSE proof against createOpenAICompletionsTransportStreamFn
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
2026-05-31 19:41:23 -04:00
Gio Della-Libera
bf777b9af2 fix(doctor): quiet tool policy audits during probes
Keep runtime tool-policy removal audits at the normal info level, but lower diagnostic-only doctor tool-schema probes to debug so expected profile filtering does not clutter normal doctor output.

Also updates current-base test expectations for the Talk custom select and a promise-executor lint rule so the PR remains green on the latest base.

Fixes #87798.

Proof:
- CI https://github.com/openclaw/openclaw/actions/runs/26727664397
- Real behavior proof https://github.com/openclaw/openclaw/actions/runs/26727667473
- Local focused Vitest, broad lint, touched-file format/lint, and autoreview clean.

Co-authored-by: Gio Della-Libera <40915808+giodl73-repo@users.noreply.github.com>
2026-05-31 19:37:13 -04:00
Peter Steinberger
fba9eac7eb fix(google): register Vertex static catalog rows 2026-06-01 00:36:31 +01:00
Peter Steinberger
5965522af5 fix(copilot): preserve Claude 1M capabilities 2026-06-01 00:36:31 +01:00
Peter Steinberger
f18fd2094f fix(agents): match provider-scoped context ids 2026-06-01 00:36:30 +01:00
Peter Steinberger
770ee8eba6 fix(models): refresh provider catalog metadata 2026-06-01 00:36:30 +01:00
Vincent Koc
b891d42f3a refactor: share talk session turn handling 2026-06-01 01:32:06 +02:00
Vincent Koc
705bdcec70 fix(gateway): harden MCP loopback tool schemas 2026-05-31 19:30:02 -04:00
github-actions[bot]
db7aff8843 chore(ui): refresh fa control ui locale 2026-05-31 23:23:45 +00:00
github-actions[bot]
d30329fb0e chore(ui): refresh nl control ui locale 2026-05-31 23:23:37 +00:00
github-actions[bot]
c7f3d60722 chore(ui): refresh vi control ui locale 2026-05-31 23:23:13 +00:00
github-actions[bot]
0ffaeb1273 chore(ui): refresh th control ui locale 2026-05-31 23:23:06 +00:00
github-actions[bot]
c43a571170 chore(ui): refresh pl control ui locale 2026-05-31 23:23:02 +00:00
github-actions[bot]
dd8b9bdcb8 chore(ui): refresh id control ui locale 2026-05-31 23:22:48 +00:00
github-actions[bot]
399f55e511 chore(ui): refresh uk control ui locale 2026-05-31 23:22:29 +00:00
github-actions[bot]
7e654b40b8 chore(ui): refresh tr control ui locale 2026-05-31 23:22:18 +00:00
github-actions[bot]
7b119ec60d chore(ui): refresh it control ui locale 2026-05-31 23:22:15 +00:00
github-actions[bot]
c1fffe1074 chore(ui): refresh ar control ui locale 2026-05-31 23:22:05 +00:00
github-actions[bot]
530f3aaab7 chore(ui): refresh fr control ui locale 2026-05-31 23:21:43 +00:00
github-actions[bot]
3ec1a25de4 chore(ui): refresh ja-JP control ui locale 2026-05-31 23:21:30 +00:00
github-actions[bot]
5a6ec67eb0 chore(ui): refresh es control ui locale 2026-05-31 23:21:27 +00:00
github-actions[bot]
0fdca6974d chore(ui): refresh ko control ui locale 2026-05-31 23:21:24 +00:00
Jerry-Xin
dc344a33fb fix(cron): retire MCP runtimes on isolated cron cleanup
Retire isolated cron session MCP runtimes on timeout and dispose so orphaned MCP servers do not accumulate after cron cleanup. Bound MCP session disposal to 5 seconds and force-close hung transports, including streamable-HTTP DELETE hangs, to prefer gateway availability over unbounded teardown.

Fixes #87821.
PR: #87981.
Proof: latest Real behavior proof check passed after body fix; local autoreview clean with focused cron/gateway/MCP tests covering 108 tests.

Co-authored-by: 忻役 <xinyi@mininglamp.com>
Co-authored-by: Jerry-Xin <jerryxin0@gmail.com>
2026-06-01 00:21:14 +01:00
github-actions[bot]
e4a766f2f4 chore(ui): refresh zh-TW control ui locale 2026-05-31 23:20:54 +00:00
github-actions[bot]
ad07ba141d chore(ui): refresh pt-BR control ui locale 2026-05-31 23:20:46 +00:00
github-actions[bot]
bd78737f94 chore(ui): refresh de control ui locale 2026-05-31 23:20:41 +00:00
github-actions[bot]
5f6e608c60 chore(ui): refresh zh-CN control ui locale 2026-05-31 23:20:37 +00:00
Vincent Koc
ddbd16a04a fix(ui): honor chromium executable override 2026-06-01 00:20:10 +01:00
Vincent Koc
03151a2ebe test(release): repair stale e2e mocks 2026-06-01 00:20:10 +01:00
Vincent Koc
1b69e7a005 fix(plugin-sdk): keep llm core alias on source graph 2026-06-01 00:20:10 +01:00
Vincent Koc
227530f906 test(imessage): align service-qualified target expectations 2026-06-01 00:20:10 +01:00
Vincent Koc
6df3fd5730 fix(gateway): list commands from gateway plugin registry 2026-06-01 00:20:10 +01:00
Vincent Koc
7c315252d6 test(whatsapp): wait on inbox delivery in monitor helper 2026-06-01 00:20:10 +01:00
Vincent Koc
0d7abcc94f test(telegram): exercise blocked spooled timeout lane 2026-06-01 00:20:09 +01:00
Vincent Koc
344773ba09 fix(openrouter): cap music stream request timeouts 2026-06-01 00:20:09 +01:00
Vincent Koc
ae4550f48b test(qa-lab): preserve cleanup phase labels 2026-06-01 00:20:09 +01:00
Vincent Koc
fdd02444b7 ci: add ARM Testbox lane 2026-06-01 00:20:09 +01:00
Peter Steinberger
3491834d49 Migrate iMessage monitor state to SQLite (#88797)
* refactor: move imessage monitor state to sqlite

* test: use OpenClaw temp root in iMessage state helper

* test: avoid pending promise lint in chat tests

* test: harden gateway ci flakes

* test: align session list merge expectation
2026-06-01 00:19:51 +01:00
Vincent Koc
12cf34a8ea refactor: share send inflight helpers 2026-06-01 01:18:38 +02:00
Peter Steinberger
d328a0d7a0 feat: calm chat composer controls 2026-06-01 00:18:04 +01:00
colmbrogan
421ad93203 fix(imessage): tolerate self-chat timestamp skew
Fixes iMessage self-chat reflection dedupe when reflected rows arrive with sub-second `created_at` skew, while keeping ambiguous normal-DM suppression exact-match only.

Maintainer follow-ups scoped skew tolerance to confirmed self-chat remembered rows and bounded cache cleanup so TTL-only expiry cannot leave the insertion-order queue growing indefinitely.

Verification:
- `node scripts/run-vitest.mjs extensions/imessage/src/monitor/self-chat-cache.test.ts extensions/imessage/src/monitor/self-chat-dedupe.test.ts extensions/imessage/src/monitor/inbound-processing.test.ts`
- `pnpm oxlint extensions/imessage/src/monitor/self-chat-cache.ts extensions/imessage/src/monitor/self-chat-cache.test.ts extensions/imessage/src/monitor/self-chat-dedupe.test.ts`
- `git diff --check origin/main...HEAD`
- autoreview clean on branch tip
- CI run 26727192244 green; Real behavior proof run 26727196218 green

Co-authored-by: Colm O Brogain <73212305+colmbrogan@users.noreply.github.com>
2026-06-01 00:14:47 +01:00
Vincent Koc
dc05f598bb fix(doctor): report runtime tool schema errors 2026-06-01 00:14:36 +01:00
Alix-007
3171278372 fix(gateway): hide phantom agent store rows from sessions.list
Fixes #57376.

Hide placeholder agent store keys from sessions.list while preserving real agent-scoped sessions.

Co-authored-by: Alix-007 <li.long15@xydigit.com>
2026-06-01 00:14:09 +01:00
Feelw00
01193dea26 fix: make task persistence failures explicit
Preserve task and TaskFlow durability by persisting before in-memory registry mutation and surfacing explicit persistence failures instead of reporting fake success.

Adds non-throwing try-create runtime helpers while keeping existing throwing public create APIs compatible. Maintainer follow-up keeps task/TaskFlow sync repair bounded, prevents split task/delivery-state writes, and keeps CI green on the current base.

Thanks @Feelw00.
2026-06-01 00:12:28 +01:00
Coder
cb9847968a fix(subagents): roll token usage formatters over to m
Roll both subagent token usage formatters over to the million unit when rounded thousands reach the next unit.

The original fix covers `formatTokenShort`, which feeds the subagent list usage line. The maintainer follow-up applies the same unit-boundary rule to compact subagent announcement stats, preserving that formatter's one-decimal style while preventing `1000.0k` output.

Verification:
- focused runtime probe for list and compact announce stats at 999,999 tokens
- `oxfmt --check` on touched formatter/test files
- `git diff --check origin/main..HEAD`
- `node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.core.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core-test-pr88209.tsbuildinfo`
- autoreview local closeout clean
- exact-head CI passed for Real behavior proof, check-test-types, check-prod-types, check-guards, security-fast, and preflight

Known unrelated current-main reds at merge: `check-lint`, `checks-node-agentic-gateway-methods`, and `checks-node-agentic-control-plane-agent-chat`.

Co-authored-by: coder999999999 <coder999999999@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 00:07:45 +01:00
Vincent Koc
54987715f3 fix(ci): repair main lint and gateway session tests 2026-06-01 00:05:41 +01:00
Silvester
0c74f18a1c fix(microsoft-foundry): skip DeepSeek V4 thinking params on Foundry fallback
Skip the generic DeepSeek V4 OpenAI-compatible `thinking` payload wrapper for Microsoft Foundry fallback models. Foundry's OpenAI-compatible gateway rejects the non-standard top-level `thinking` argument, while the rest of the DeepSeek proxy path still keeps the wrapper.

Proof:
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main --parallel-tests "node scripts/run-vitest.mjs src/agents/embedded-agent-runner-extraparams.test.ts"
- node scripts/run-vitest.mjs src/agents/embedded-agent-runner-extraparams.test.ts passed, 130/130
- CI run 26681069909 passed for c950ac112e

Thanks @silvesterxm.
2026-06-01 00:03:32 +01:00
Vincent Koc
59122812c0 refactor: share agent id resolver 2026-06-01 01:03:07 +02:00
Alix-007
bc95af1b7c fix(memory-core): stop dream diary fallback leaks
Stop memory-core dream diary fallback paths from persisting raw memory staging snippets or promotions into DREAMS.md when narrative generation times out, returns empty output, or fails in request-scoped runtime. Successful generated narratives are unchanged.

Maintainer fixup: align current gateway session-list tests with the full loadSessionEntry mock shape and model-derived context token behavior on main.

Fixes #88391

Co-authored-by: Alix-007 <li.long15@xydigit.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 00:00:22 +01:00
yozakura-ava
144405e562 fix(agents): cap bootstrap snapshot cache
Cap the in-memory workspace bootstrap snapshot cache to 64 session keys so long-lived gateway processes do not retain one loaded bundle per distinct session key indefinitely. Older entries are evicted while active keys continue refreshing against the guarded workspace loader.

Verification:
- node scripts/run-vitest.mjs src/agents/bootstrap-cache.test.ts

PR: #88149
2026-05-31 23:56:47 +01:00
Vincent Koc
290b19275b refactor: share cron request helpers 2026-06-01 00:53:00 +02:00
Rain
72f74b33e1 fix(agents): guard transport payload sanitizer against non-string input
sanitizeTransportPayloadText() called text.replace() directly, so runtime-undefined content from malformed replay/error handling could crash embedded agent transport serialization with "Cannot read properties of undefined (reading 'replace')".

Return an empty string for non-string runtime payloads at the shared sanitizer boundary, preserving existing unpaired-surrogate cleanup for strings. Empty values still degrade through sanitizeNonEmptyTransportPayloadText() to "(no output)" where that non-empty fallback is required.

Proof:
- pnpm test src/agents/transport-stream-shared.test.ts
- pnpm exec oxfmt --check --threads=1 src/agents/transport-stream-shared.ts src/agents/transport-stream-shared.test.ts
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main --parallel-tests "pnpm test src/agents/transport-stream-shared.test.ts"

Fixes #60113

Co-authored-by: Pluviobyte <Pluviobyte@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-31 23:45:39 +01:00
Vincent Koc
bb673f47b2 refactor: share agent run snapshot shape 2026-06-01 00:39:13 +02:00
Vincent Koc
16ef9c1435 fix(ci): use reliable Azure Crabbox capacity 2026-06-01 00:38:11 +02:00
Peter Steinberger
2b30951b80 feat: calm composer controls (#88772) 2026-05-31 23:37:27 +01:00
Peter Steinberger
56b8030cd9 fix(qa-lab): avoid returning timer from promise executor 2026-05-31 23:34:13 +01:00
DocNR
5706619068 fix(nostr): decode npub allowFrom entries to hex correctly
Fix Nostr allowFrom npub normalization by returning the decoded hex string from nostr-tools instead of iterating the hex string as bytes.

Proof:
- node scripts/run-vitest.mjs extensions/nostr/src/nostr-bus.test.ts
- PR CI green at head 7c3433435b

Co-authored-by: DocNR <danieljwyler@gmail.com>
2026-05-31 23:33:45 +01:00
Vincent Koc
edc0a22179 fix(agents): quarantine tools before schema normalization 2026-05-31 23:33:03 +01:00
Peter Steinberger
2682c02774 perf: hydrate chat history session metadata
Use chat.history metadata to hydrate TUI and web startup state without the extra sessions.list refresh, with guards for aliases, stale active rows, blank-session defaults, and lightweight TUI usage metadata.
2026-05-31 23:31:15 +01:00
Vincent Koc
59683978e1 refactor: share voice-call config extraction 2026-06-01 00:19:33 +02:00
Peter Steinberger
c8f8907f15 fix(feishu): guard webhook readiness fetch 2026-05-31 23:18:09 +01:00
Vincent Koc
8eb1838dfa refactor: share web login unavailable response 2026-06-01 00:13:34 +02:00
Jason O'Neal
01f6ad6056 fix: suppress raw provider errors in channel delivery
Fixes #69737.

Suppresses raw and raw-derived provider error text at the user-facing assistant lifecycle and reply-payload boundaries, including structured provider payloads, escaped JSON payloads, and aborted turns carrying provider failures. Keeps safe schema rejection and rate-limit guidance while preserving internal diagnostics.

Proof:
- OPENCLAW_VITEST_MAX_WORKERS=1 node scripts/run-vitest.mjs run src/agents/embedded-agent-helpers.formatassistanterrortext.test.ts src/agents/embedded-agent-runner/run/payloads.errors.test.ts src/agents/embedded-agent-subscribe.handlers.lifecycle.test.ts src/agents/embedded-agent-helpers/errors.test.ts
- oxfmt --check on touched files
- git diff --check origin/main...HEAD
- autoreview --mode branch --base origin/main clean
- GitHub exact-head checks green on b46e197f62

Co-authored-by: Jason O'Neal <jason.allen.oneal@gmail.com>
2026-05-31 23:10:46 +01:00
Peter Steinberger
b7f657b3b0 chore(lint): fix app render promise executor 2026-05-31 23:10:00 +01:00
Peter Steinberger
22cb7fb6b7 chore(lint): enable no-promise-executor-return 2026-05-31 23:06:13 +01:00
Vincent Koc
48afba96a3 refactor: share agents handler helpers 2026-06-01 00:02:22 +02:00
github-actions[bot]
470a1ae8d1 chore(ui): refresh nl control ui locale 2026-05-31 21:59:56 +00:00
github-actions[bot]
a2acfc5049 chore(ui): refresh fa control ui locale 2026-05-31 21:59:48 +00:00
github-actions[bot]
fe8c781d67 chore(ui): refresh vi control ui locale 2026-05-31 21:59:18 +00:00
github-actions[bot]
ac2484f23e chore(ui): refresh pl control ui locale 2026-05-31 21:59:13 +00:00
github-actions[bot]
cabfbdfe0d chore(ui): refresh id control ui locale 2026-05-31 21:59:11 +00:00
github-actions[bot]
5e2472567a chore(ui): refresh th control ui locale 2026-05-31 21:59:07 +00:00
github-actions[bot]
79c4ac73d7 chore(ui): refresh tr control ui locale 2026-05-31 21:58:33 +00:00
github-actions[bot]
2a1882ebcc chore(ui): refresh uk control ui locale 2026-05-31 21:58:31 +00:00
github-actions[bot]
3bb04b67e9 chore(ui): refresh it control ui locale 2026-05-31 21:58:25 +00:00
github-actions[bot]
cd0a7b10e2 chore(ui): refresh ar control ui locale 2026-05-31 21:58:21 +00:00
github-actions[bot]
bc45c36dbc chore(ui): refresh fr control ui locale 2026-05-31 21:57:51 +00:00
github-actions[bot]
7184522fae chore(ui): refresh ko control ui locale 2026-05-31 21:57:45 +00:00
github-actions[bot]
aa74d93aff chore(ui): refresh es control ui locale 2026-05-31 21:57:40 +00:00
github-actions[bot]
be0d3489a6 chore(ui): refresh ja-JP control ui locale 2026-05-31 21:57:38 +00:00
github-actions[bot]
f06b4b9aab chore(ui): refresh pt-BR control ui locale 2026-05-31 21:57:10 +00:00
github-actions[bot]
0700f13d62 chore(ui): refresh zh-TW control ui locale 2026-05-31 21:57:05 +00:00
github-actions[bot]
3c6c247e0a chore(ui): refresh de control ui locale 2026-05-31 21:57:01 +00:00
github-actions[bot]
2e42b1372e chore(ui): refresh zh-CN control ui locale 2026-05-31 21:56:58 +00:00
Shakker
f78bb34cb4 fix: translate Skill Workshop locale strings 2026-05-31 22:55:03 +01:00
Shakker
85c7490f72 fix: refresh Skill Workshop i18n outputs 2026-05-31 22:55:03 +01:00
Shakker
63d93db867 fix: refresh Skill Workshop protocol models 2026-05-31 22:55:03 +01:00
Shakker
2976db4b2c fix: address Skill Workshop UI check failures 2026-05-31 22:55:03 +01:00
Shakker
025bb01268 fix: constrain Skill Workshop navigation 2026-05-31 22:55:03 +01:00
Shakker
7a292bb16e fix: improve Skill Workshop empty states 2026-05-31 22:55:03 +01:00
Shakker
a9e3eade5d fix: tighten Skill Workshop today actions 2026-05-31 22:55:03 +01:00
Shakker
3733cd8d63 fix: clarify Skill Workshop proposal preview 2026-05-31 22:55:03 +01:00
Shakker
190f935b53 fix: address Skill Workshop review findings 2026-05-31 22:55:03 +01:00
Shakker
c21e16c73d fix: add Skill Workshop empty state 2026-05-31 22:55:03 +01:00
Shakker
d52f1ea5ec fix: tighten Skill Workshop today actions 2026-05-31 22:55:03 +01:00
Shakker
13967e17e6 fix: distinguish created Skill Workshop proposals 2026-05-31 22:55:03 +01:00
Shakker
7ad2aa44dd fix: show assistant name in Skill Workshop 2026-05-31 22:55:03 +01:00
Shakker
874b3f921e fix: polish Skill Workshop revision handoff 2026-05-31 22:55:03 +01:00
Shakker
c11d5d6d65 feat: stage Skill Workshop revision handoff 2026-05-31 22:55:03 +01:00
Shakker
11631bf044 feat: animate Skill Workshop chat landing 2026-05-31 22:55:03 +01:00
Shakker
561e993282 fix: stabilize Skill Workshop revise handoff 2026-05-31 22:55:03 +01:00
Shakker
23bf48e69e feat: add reusable Control UI tooltip 2026-05-31 22:55:03 +01:00
Shakker
7d65ea3513 feat: style Skill Workshop revision controls 2026-05-31 22:55:03 +01:00
Shakker
bfac12a184 feat: route Skill Workshop revisions through reusable sessions 2026-05-31 22:55:03 +01:00
Shakker
cdcc151145 feat: attach agent session origin to workshop tool 2026-05-31 22:55:03 +01:00
Shakker
7681b95199 feat: persist Skill Workshop proposal origin 2026-05-31 22:55:03 +01:00
Shakker
caa08a6dc0 feat: show real Skill Workshop proposals 2026-05-31 22:55:03 +01:00
Shakker
4339d7c1d8 feat: add Skill Workshop revision dialog 2026-05-31 22:55:03 +01:00
Shakker
aa187c6496 feat: add Skill Workshop today view 2026-05-31 22:55:03 +01:00
Shakker
34010894c1 feat: preview Skill Workshop actions 2026-05-31 22:55:03 +01:00
Shakker
c74bb4475a feat: resize Skill Workshop proposal list 2026-05-31 22:55:03 +01:00
Shakker
299a023bd1 fix: track reviewed workshop proposals 2026-05-31 22:55:03 +01:00
Shakker
0c852036c7 fix: refine Skill Workshop action bar 2026-05-31 22:55:03 +01:00
Shakker
9cc759dd37 fix: hide Skill Workshop actions after pending 2026-05-31 22:55:03 +01:00
Shakker
d1378650bb fix: keep file preview row focus clean 2026-05-31 22:55:03 +01:00
Shakker
40f99e474a fix: keep file preview keyboard focus modal 2026-05-31 22:55:03 +01:00
Shakker
dc71b5867e fix: align live tool stream labels 2026-05-31 22:55:03 +01:00
Shakker
fd2c65f59b refactor: extract file preview modal component 2026-05-31 22:55:03 +01:00
Shakker
575f74293e feat: search Skill Workshop preview files 2026-05-31 22:55:03 +01:00
Shakker
b27ae3f6e7 fix: remove Skill Workshop modal search focus chrome 2026-05-31 22:55:03 +01:00
Shakker
b388d3dc71 style: add Skill Workshop file preview modal 2026-05-31 22:55:03 +01:00
Shakker
01b7ef9e88 feat: add Skill Workshop file preview modal 2026-05-31 22:55:03 +01:00
Shakker
4b89def277 fix: align Skill Workshop pane surface 2026-05-31 22:55:03 +01:00
Shakker
fabd9469cd fix: tighten Skill Workshop page spacing 2026-05-31 22:55:03 +01:00
Shakker
d3025b4007 fix: resolve Control UI public assets from base path 2026-05-31 22:55:03 +01:00
Shakker
c06096eabc fix: keep Control UI logo root-relative 2026-05-31 22:55:03 +01:00
Shakker
9577e0be5a feat: style Skill Workshop UI 2026-05-31 22:55:03 +01:00
Shakker
b12724b79b feat: add Skill Workshop demo view 2026-05-31 22:55:03 +01:00
Shakker
0de60cec12 feat: add Skill Workshop navigation tab 2026-05-31 22:55:03 +01:00
Vincent Koc
c6232347dc refactor: share exec approvals node invoke 2026-05-31 23:50:30 +02:00
xin zhuang
b73e135f97 fix: resolve google provider default API to google-generative-ai (#88480) (#88512)
When a configured Google provider/model row had no explicit
but had a baseUrl set, the fallback defaulted to openai-completions,
causing Gemini requests to route through the OpenAI Responses
transport instead of the native @google/genai transport.

Made resolveConfiguredProviderDefaultApi provider-aware: for the
google provider, the default API is now google-generative-ai.

Root cause: the generic fallback assumed any provider with a baseUrl
should use openai-completions, which is incorrect for Google's native
Gemini API.

Co-authored-by: xin <1052326311+xin@users.noreply.github.com>
2026-05-31 22:48:48 +01:00
github-actions[bot]
9b6c981260 chore(ui): refresh fa control ui locale 2026-05-31 21:46:04 +00:00
github-actions[bot]
02ac0ec48b chore(ui): refresh nl control ui locale 2026-05-31 21:46:00 +00:00
github-actions[bot]
d8329dedf6 chore(ui): refresh pl control ui locale 2026-05-31 21:45:39 +00:00
github-actions[bot]
b86e8bf359 chore(ui): refresh id control ui locale 2026-05-31 21:45:30 +00:00
github-actions[bot]
3bb9224836 chore(ui): refresh vi control ui locale 2026-05-31 21:45:24 +00:00
github-actions[bot]
fdc10a64e9 chore(ui): refresh th control ui locale 2026-05-31 21:45:20 +00:00
github-actions[bot]
87174c80b6 chore(ui): refresh uk control ui locale 2026-05-31 21:44:45 +00:00
github-actions[bot]
97c040f946 chore(ui): refresh it control ui locale 2026-05-31 21:44:40 +00:00
github-actions[bot]
f833e96a31 chore(ui): refresh tr control ui locale 2026-05-31 21:44:38 +00:00
github-actions[bot]
9a32c0f85d chore(ui): refresh ar control ui locale 2026-05-31 21:44:35 +00:00
github-actions[bot]
d306f5bf2e chore(ui): refresh fr control ui locale 2026-05-31 21:44:02 +00:00
github-actions[bot]
65d5f7436c chore(ui): refresh ko control ui locale 2026-05-31 21:43:55 +00:00
github-actions[bot]
b78ce079a3 chore(ui): refresh ja-JP control ui locale 2026-05-31 21:43:51 +00:00
github-actions[bot]
6c6cf41b14 chore(ui): refresh es control ui locale 2026-05-31 21:43:42 +00:00
github-actions[bot]
0d79cbab4e chore(ui): refresh pt-BR control ui locale 2026-05-31 21:43:18 +00:00
github-actions[bot]
b04c3e96d6 chore(ui): refresh zh-CN control ui locale 2026-05-31 21:43:11 +00:00
github-actions[bot]
3854a61bea chore(ui): refresh de control ui locale 2026-05-31 21:43:07 +00:00
github-actions[bot]
0d07e30725 chore(ui): refresh zh-TW control ui locale 2026-05-31 21:43:01 +00:00
Ted Li
bfc151e9d3 fix(feishu): preserve long streaming replies
Preserve long Feishu streaming replies by falling oversized finals back to chunked message/static-card delivery instead of closing through an over-limit streaming CardKit payload.

Keeps late-final suppression after a streaming card closes, and uses markdown-aware chunking for static card fallback replies.

Fixes #88631.

Co-authored-by: Ted Li <tl2493@columbia.edu>
2026-05-31 22:41:38 +01:00
Peter Steinberger
b653d94918 chore(lint): enable no-useless-assignment 2026-05-31 22:40:48 +01:00
Andy Ye
49e5091f18 fix(update): recognize manual-update launchd jobs (#88764)
* Recognize manual update launchd jobs

* fix(update): avoid stale launchd false positives

* fix(update): filter stale doctor launchd checks

* fix(update): narrow manual launchd updater labels

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-31 22:39:37 +01:00
zhang-guiping
cbdb59b255 fix(agents): keep light isolated subagents lightweight
Keep native subagent spawns with `lightContext=true` and resolved isolated context out of context-engine pre-spawn preparation so they remain lightweight.

The normal isolated and forked context-engine lifecycle stays intact, and docs now call out the lightweight isolated exception.

Fixes #81214
2026-05-31 22:37:59 +01:00
Vincent Koc
2ac2a8d210 refactor: share channel operation validation 2026-05-31 23:35:19 +02:00
Shubhankar Tripathy
d042452d20 fix(logging): refresh file log hostname per write
Fix JSONL file-log hostnames getting pinned to `unknown` when the first hostname read returns an empty value. The logger now retries empty hostname reads and caches the first non-empty value, keeping the top-level `hostname` and `_meta.hostname` fields aligned.

Fixes #87258.
Thanks @lonexreb for the fix.

Verification:
- `node scripts/run-vitest.mjs src/logging/logger-redaction-behavior.test.ts src/logger.test.ts`
- `node_modules/.bin/oxfmt --check --threads=1 src/logging/logger.ts src/logging/logger-redaction-behavior.test.ts`
- `.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main`
- `gh pr checks 88131 --watch=false`

Co-authored-by: lonexreb <reach2shubhankar@gmail.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-31 22:35:04 +01:00
Peter Steinberger
50f27ee91d docs: document code-mode MCP API files 2026-05-31 22:33:06 +01:00
charles-openclaw
84266cd30e fix(models): strip remaining provider self prefixes (#88781)
* fix(models): strip remaining provider self prefixes

* fix(models): keep catalog refs prefix-preserving

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-31 22:29:47 +01:00
David
61e9961abb fix(agents): expose session status route context
Expose session status route context so agents can distinguish session origin, active live route, and persisted delivery route.

Add maintainer fixup to keep active route metadata on the real live run key when policy and run keys differ.

Thanks @nxmxbbd.

Closes #84544
2026-05-31 22:25:47 +01:00
Ashd.LW.
7c04ce3a79 fix(daemon): preserve container service env across regen
Preserve the current container-related service opt-in environment when regenerating daemon service files, while continuing to drop stale or arbitrary `OPENCLAW_*` variables.

Verification:
- `git diff --check`
- `node scripts/run-vitest.mjs src/commands/daemon-install-helpers.test.ts -t "operator opt-in allowlist"`
- `.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main --prompt "Review PR #82828 fixup for daemon service env preservation. Focus on whether the allowlist should include only current container opt-in env keys and whether tests cover stale/arbitrary OPENCLAW_* filtering."`
- GitHub CI on `2e4b7f7fccbc46541c9c0ac271b1c97f1a6aa071`

Co-authored-by: wAngByg <281221101+wAngByg@users.noreply.github.com>
2026-05-31 22:22:24 +01:00
Vincent Koc
2ff9e27d4e refactor: share skill proposal workspace handling 2026-05-31 23:21:27 +02:00
Peter Steinberger
5ee3e5d8c0 docs: require real Crabbox visual proof 2026-05-31 22:18:31 +01:00
waterblue
03dec8bb3a fix(openai): avoid replay ids when Responses store is disabled
Avoid replaying prior OpenAI Responses reasoning/message/function-call item ids when the outgoing request disables store, while preserving encrypted reasoning and normalized summary arrays for stateless replay. Keep explicit store-enabled OpenAI wrapper paths opted into item-id replay, and cover shared/simple Responses, ChatGPT/Codex Responses, and GitHub Copilot sanitizer behavior.

Regression tests cover store-disabled id omission, encrypted reasoning preservation, idless Copilot reasoning replay, and direct builder payloads. Local proof included focused Vitest, broad lint, broad test-types, bundled-extension lint, plugin boundary checks, autoreview clean, and live OpenAI Responses gpt-5.5 proof.

Co-authored-by: hang <zhanghang02@gmail.com>
2026-05-31 22:17:32 +01:00
Arnab Saha
5bc80dbe27 fix(diagnostics): carry session UUID on interactive dispatch events
Carry the canonical session UUID from the session store into interactive dispatch diagnostic lifecycle events, matching the cron path so downstream diagnostic consumers can join events back to the JSONL transcript id.

Guard native command redirects by only attaching the UUID when the lifecycle session key matches the session-store lookup key, avoiding a target UUID under a source conversation key.

Verification:
- `pnpm test src/auto-reply/reply/dispatch-from-config.test.ts -t "carries the session store UUID|does not stamp a command target"`
- `.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main --prompt ...`
- synthetic merge-tree against current `origin/main`

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 22:15:15 +01:00
Peter Steinberger
8383e2e4d9 fix(doctor): keep post-upgrade JSON stable 2026-05-31 22:12:38 +01:00
Arnab Saha
7f93755206 fix(doctor): post-upgrade entry probe now delegates to install resolver
Address Codex review (P2 x3): replace the duplicate fs.access-based entry
checks in runPostUpgradeProbes with a call to
validatePackageExtensionEntriesForInstall so the doctor probe enforces the
same contract as plugin install/discovery:

- runtimeExtensions shape and length-mismatch validation
- plugin-root boundary enforcement (rejects absolute paths and ../ escapes)
- inferred dist/*.js peer for TypeScript entries; TS source-only entries
  without compiled output are now flagged

Adds 4 regression tests covering the boundary-escape, dist-peer accept,
TS-source-only reject, and runtimeExtensions length-mismatch cases.

Refs: https://github.com/openclaw/openclaw/pull/79260#issuecomment-4403594002
2026-05-31 22:12:38 +01:00
Arnab Saha
7dd1bd894b fix(doctor): drop unused listBuiltRuntimeEntryCandidates import and brace bare if continue 2026-05-31 22:12:38 +01:00
Arnab Saha
6ed6120977 docs(doctor): document --post-upgrade and --json flags 2026-05-31 22:12:38 +01:00
Arnab Saha
0f396368a9 fix(doctor): honor runtimeExtensions before flagging entry_unresolved 2026-05-31 22:12:38 +01:00
Arnab Saha
72679b16eb fix(doctor): resolve plugin index via state-dir helper 2026-05-31 22:12:38 +01:00
Arnab Saha
4a09fd43e2 docs(changelog): note doctor --post-upgrade --json 2026-05-31 22:12:38 +01:00
Arnab Saha
026ab6b882 feat(doctor): expose --post-upgrade and --json CLI flags 2026-05-31 22:12:38 +01:00
Arnab Saha
730492867f feat(doctor): branch into post-upgrade probe runner when --post-upgrade 2026-05-31 22:12:38 +01:00
Arnab Saha
ceda284845 feat(doctor): add plugin.manifest_drift post-upgrade probe 2026-05-31 22:12:38 +01:00
Arnab Saha
8da6b67607 fix(doctor): clean up post-upgrade probe test temp dirs and skip plugins with unreadable package.json 2026-05-31 22:12:38 +01:00
Arnab Saha
e0d3c78042 feat(doctor): add plugin.entry_unresolved post-upgrade probe 2026-05-31 22:12:38 +01:00
Arnab Saha
af7749123b feat(doctor): add post-upgrade finding types 2026-05-31 22:12:38 +01:00
alkor2000
9d97e683d4 feat(doctor): add disk space health check
Add a Doctor health contribution that checks free space on the partition containing the active OpenClaw state directory. Doctor now warns below 500 MB and reports critical below 100 MB so disk pressure is visible before config writes, session transcripts, or log rotation start failing.

The contribution reuses the shared `src/infra/disk-space.ts` probe, runs before state integrity, and is registered in the Doctor health conversion plan with focused coverage for thresholds, formatting, and note behavior.

PR: #59196
Proof: `pnpm test src/commands/doctor-disk-space.test.ts src/flows/doctor-health-conversion-plan.test.ts`; `git diff --check origin/main...HEAD`; `git merge-tree --write-tree origin/main refs/remotes/pr/59196`; GitHub CI run `26720861380`; Real behavior proof run `26720996848`.

Co-authored-by: alkor2000 <200923177@qq.com>
2026-05-31 22:09:36 +01:00
Vincent Koc
e2c745fc58 refactor: share agent wait terminal snapshot 2026-05-31 23:08:28 +02:00
Andy Ye
5df0ed3b9f fix(agents): publish owned announcement session writes
Forward prompt-submission owned session write publication into the embedded session lock controller so same-process announcement/completion writes can advance the requester fence while external edits still trigger takeover protection.

Adds regression coverage for a second controller publishing an owned announcement write and for preserving rejection of a later unowned edit.

Closes #88703.

Thanks @TurboTheTurtle.
2026-05-31 22:00:37 +01:00
Ted Li
e5acae4453 fix(ui): show Workboard comments in edit modal
Show existing Workboard card comments in the edit modal and allow operators to append a new comment through the existing `workboard.cards.comment` gateway method.

Refs #88592.

Verification:
- node scripts/run-vitest.mjs ui/src/ui/views/workboard.test.ts
- pnpm tsgo:test:ui
- git diff --check origin/main...HEAD
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main

Co-authored-by: Ted Li <tl2493@columbia.edu>
2026-05-31 21:54:26 +01:00
Peter Steinberger
8076eead77 test(channels): narrow pending ingress duplicate 2026-05-31 21:53:42 +01:00
Peter Steinberger
f6365d07c4 fix(agents): wait for cron media completions
Keep cron media generation detached while making cron runs wait for image/music/video completion before final closeout. Records async task IDs, falls back to the task registry for active run-scoped media work, handles timeout races, and scopes no-target generated-media delivery. Fixes #88001.
2026-05-31 21:51:38 +01:00
Sebastien Tardif
9a3e7d4f51 fix(hooks): pass media metadata to internal message_received hook
Forward canonical inbound media metadata to internal message:received hook consumers, matching the plugin received hook mapper and inbound-claim metadata path.

This fixes internal hook handlers losing mediaPath, mediaUrl, mediaType, mediaPaths, mediaUrls, and mediaTypes for received messages with attachments.

Verification:
- node scripts/run-vitest.mjs src/hooks/message-hook-mappers.test.ts
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main

Refs: https://github.com/openclaw/openclaw/pull/88740
Thanks @SebTardif.
Co-authored-by: Sebastien Tardif <sebtardif@ncf.ca>
2026-05-31 21:49:36 +01:00
Peter Steinberger
ce1165afda fix: repair providerless Codex session overrides
Co-authored-by: Earl Vanze <earlvanze@gmail.com>
2026-05-31 21:45:39 +01:00
brokemac79
90712f6d5e [codex] Surface disabled Codex plugin routes in doctor lint (#88761)
Merged via squash.

Prepared head SHA: 41bcde2d7d
Co-authored-by: brokemac79 <255583030+brokemac79@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-05-31 13:34:53 -07:00
ArthurNie
7c15c2765e fix(feishu): fallback when accepted turns send no visible reply (#87896)
* fix(feishu): fallback when accepted turns send no visible reply

* fix(feishu): cover no-visible-reply fallback gaps

* fix(feishu): mark media replies visible

* fix(feishu): honor suppressed delivery fallback

* test(auto-reply): trim fallback test churn

* fix(feishu): gate empty fallback eligibility

* test(auto-reply): expect fallback metadata after denied dispatch

* fix(feishu): fallback after failed visible final sends

* test(feishu): keep reply dispatcher mock shape aligned

* fix(auto-reply): respect silent policy for no-visible fallback

* fix(feishu): wait for streaming close before fallback

* fix(feishu): clear silent skip before later finals

* fix(feishu): preserve visible state across keepalives

* test(feishu): align lifecycle dispatcher mocks

* fix(feishu): require accepted streaming content for fallback

---------

Co-authored-by: ArthurNie <264332276+ArthurNie@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-31 21:33:13 +01:00
Peter Steinberger
e681569536 feat: add code-mode MCP API files
* feat: add code-mode MCP API files

* fix: satisfy code-mode MCP lint
2026-05-31 21:29:06 +01:00
Peter Steinberger
b0679d1f13 refactor(channels): store inbound queues in SQLite 2026-05-31 21:15:29 +01:00
Peter Steinberger
80b7f56603 ci: pin Azure crabbox lane to eastus2 2026-05-31 21:11:43 +01:00
Peter Steinberger
995a9bd702 chore(ui): refresh notification i18n metadata 2026-05-31 21:09:37 +01:00
Peter Steinberger
92b9cd21ec test: avoid positional CI check assertion 2026-05-31 16:00:04 -04:00
Peter Steinberger
d62bfab946 ci: split startup and shrinkwrap checks 2026-05-31 15:55:43 -04:00
Peter Steinberger
7aa309319f test(auto-reply): align debounce timer tests 2026-05-31 20:48:02 +01:00
Peter Steinberger
2df95c0b10 chore(lint): enable no-misused-promises 2026-05-31 20:42:13 +01:00
Peter Steinberger
6f58a71582 test(voice-call): install state runtime for events 2026-05-31 20:41:14 +01:00
stain lu
55fc3c10b0 fix(openai/tts): handle speed directives (#74089)
Adds OpenAI speech speed directive parsing with official OpenAI range validation and custom endpoint passthrough. Closes #12163.
2026-05-31 20:35:46 +01:00
Peter Steinberger
b4a6244ef4 ci: split agents core test shard 2026-05-31 15:35:36 -04:00
Peter Steinberger
6b2cb4db67 fix: polish notifications settings UI 2026-05-31 20:35:10 +01:00
Vincent Koc
0715081990 test(agents): narrow bundle mcp e2e setup 2026-05-31 21:31:52 +02:00
WT-WSL
462b52f62c fix(ci): guard workflow template injection
Guard the remaining Windows Testbox workflow ref logging against GitHub Actions template injection by moving `target_ref` through step env before PowerShell reads it.

Extend the local workflow check wrapper to run pinned `zizmor` across every workflow file, and keep Workflow Sanity's CI audit explicit with trusted-base pre-commit and zizmor configs for pull-request runs.

Thanks @WT-WSL for the original report and patch.

Co-authored-by: dev111-actor <captaintobb@outlook.com>
2026-05-31 20:28:40 +01:00
Peter Steinberger
118b9cacf6 refactor: split ACP manager session flows
Split ACP manager session-flow ownership into focused helpers for initialization, status reads, cancellation, and startup identity reconciliation.

Verification:
- `node scripts/run-oxlint.mjs src/acp/control-plane/manager.core.ts src/acp/control-plane/manager.initialize-session.ts src/acp/control-plane/manager.status.ts src/acp/control-plane/manager.cancel-session.ts src/acp/control-plane/manager.startup-identity-reconcile.ts src/acp/control-plane/manager.close-session.ts src/acp/control-plane/manager.turn-runner.ts src/acp/control-plane/manager.runtime-options-commands.ts src/acp/control-plane/manager.types.ts src/acp/control-plane/manager.test.ts src/acp/control-plane/manager.initialize-session.test.ts src/acp/control-plane/manager.cancel-session.test.ts src/acp/control-plane/manager.startup-identity-reconcile.test.ts src/acp/control-plane/manager.runtime-config.test.ts`
- `pnpm tsgo:prod`
- `pnpm test src/acp/control-plane/manager.test.ts src/acp/control-plane/manager.initialize-session.test.ts src/acp/control-plane/manager.cancel-session.test.ts src/acp/control-plane/manager.startup-identity-reconcile.test.ts src/acp/control-plane/manager.runtime-config.test.ts src/acp/control-plane/manager.runtime-handles.test.ts`
- `pnpm format:check src/acp/control-plane/manager.core.ts src/acp/control-plane/manager.initialize-session.ts src/acp/control-plane/manager.status.ts src/acp/control-plane/manager.cancel-session.ts src/acp/control-plane/manager.startup-identity-reconcile.ts src/acp/control-plane/manager.close-session.ts src/acp/control-plane/manager.turn-runner.ts src/acp/control-plane/manager.runtime-options-commands.ts src/acp/control-plane/manager.types.ts src/acp/control-plane/manager.test.ts src/acp/control-plane/manager.initialize-session.test.ts src/acp/control-plane/manager.cancel-session.test.ts src/acp/control-plane/manager.startup-identity-reconcile.test.ts src/acp/control-plane/manager.runtime-config.test.ts`
- `git diff --check`
- `pnpm check:test-types`
- `.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main`
- GitHub PR checks for #88752 passed

Real behavior proof:
Behavior addressed: ACP manager session-flow ownership is split out of `AcpSessionManager` without changing initialization, status, cancel, startup identity reconciliation, close, turn, or runtime-option behavior.
Real environment tested: Local OpenClaw checkout, Node/pnpm repo toolchain, GitHub Actions PR CI.
Exact steps or command run after this patch: Focused ACP manager/runtime config/runtime handle tests plus prod/test type checks, lint, format check, diff check, autoreview, and PR CI.
Evidence after fix: All listed local commands passed, autoreview reported no accepted/actionable findings, and GitHub PR checks passed.
Observed result after fix: `manager.core.ts` is down to 612 LOC, with init/status/cancel/startup identity flows in focused modules and matching focused tests.
What was not tested: Live ACP backend session initialization/cancel/status against a real external ACP provider.
2026-05-31 20:26:04 +01:00
Peter Steinberger
8cfccca4de docs(changelog): refresh 2026.5.31 notes 2026-05-31 20:24:49 +01:00
Peter Steinberger
01603bbbf4 docs: require WebVNC screenshot verification 2026-05-31 20:21:47 +01:00
Carmen Fernández Ruiz
2e1ae531bd fix: skip disabled skill snapshot env overrides (#79173)
Co-authored-by: hera8939 <279459669+hera8939@users.noreply.github.com>
2026-05-31 20:20:13 +01:00
Peter Steinberger
9c6f7553be test(gateway): widen tailscale hostname mock 2026-05-31 20:13:34 +01:00
Peter Steinberger
ccb50f89da fix(plugins): clarify loader failure guidance 2026-05-31 15:12:22 -04:00
Peter Steinberger
7c5a412b38 fix(whatsapp): satisfy baileys audio peer 2026-05-31 20:10:28 +01:00
Simon Peck
6653193fdb fix(openai): avoid orphan Responses message id replay
Omit provider-owned OpenAI Responses assistant message ids unless the paired reasoning item was replayed immediately before the message. Preserve commentary/final_answer phase metadata so replay quality stays intact without sending orphan msg_* ids that OpenAI rejects.

Verification:
- node scripts/run-vitest.mjs src/agents/openai-transport-stream.test.ts src/agents/openai-responses.reasoning-replay.test.ts src/llm/providers/openai-responses-shared.test.ts
- node scripts/run-oxlint.mjs on touched files
- git diff --check
- live OpenAI Responses API proof with gpt-5.5
- autoreview clean
- PR CI clean on d6902ed1a0

Co-authored-by: latensified <880715+latensified@users.noreply.github.com>
2026-05-31 20:08:33 +01:00
Feelw00
7a3a52cda9 fix(agents): atomic auth.json writes
Persist agent auth files via atomic sibling-temp replacement instead of truncating `auth.json` in place, preventing crash-time credential lockout. Preserve the existing auth directory mode during replacement and keep the credential file at `0600`.

Proof:
- `node scripts/run-vitest.mjs src/agents/sessions/auth-storage.test.ts` passed, 2 tests.
- `git diff --check` passed.
- `autoreview --mode local` clean.
- `autoreview --mode branch --base origin/main` clean.
- GitHub checks green on head `3fb1d767e70118a0e8db5b0fd64d807d456721a8`.

Closes #88028.

Co-authored-by: Feelw00 <dhrtn1006@naver.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 20:06:50 +01:00
Peter Steinberger
fa2b2ffab4 fix(channels): recover failed progress draft starts (#88749) 2026-05-31 20:06:28 +01:00
charles-openclaw
a6f4de4a66 feat(gateway): support Tailscale Serve service names
Adds optional `gateway.tailscale.serviceName` support for Tailscale Serve so the Gateway Control UI can be exposed through a named Tailscale Service while existing hostname-based Serve and Funnel behavior stays unchanged.

The implementation validates `svc:<dns-label>`, passes the Service name to `tailscale serve`, clears named Service config with `tailscale serve clear <service>` when resetOnExit runs, and uses the derived Service hostname in startup logs, status output, and pairing URLs.

Verification:
- node scripts/run-vitest.mjs src/infra/tailscale.test.ts src/gateway/server-tailscale.test.ts src/config/config.gateway-tailscale-bind.test.ts src/gateway/startup-auth.test.ts src/commands/status.scan.shared.test.ts src/pairing/setup-code.test.ts
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main --parallel-tests "node scripts/run-vitest.mjs src/infra/tailscale.test.ts src/gateway/server-tailscale.test.ts src/config/config.gateway-tailscale-bind.test.ts src/gateway/startup-auth.test.ts src/commands/status.scan.shared.test.ts src/pairing/setup-code.test.ts"
- git diff --check
- git merge-tree --write-tree origin/main origin/pr/88691

Closes #88629.
Co-authored-by: Charles OpenClaw <charles-openclaw@9bcfae.inboxapi.ai>
2026-05-31 20:05:02 +01:00
Peter Steinberger
b02c448585 docs(plugins): add npm readmes for channel providers 2026-05-31 20:02:45 +01:00
Vladyslav Levchuk
a93240e2c6 fix(ui): show communication notifications tab (#74715)
Expose the existing virtual Communication > Notifications settings tab for Web Push controls, while keeping it out of the unscoped root settings view. Adds browser regression coverage for the scoped virtual tab.

Thanks @VladyslavLevchuk.

Co-authored-by: Vladyslav Levchuk <32742736+VladyslavLevchuk@users.noreply.github.com>
2026-05-31 19:58:55 +01:00
Peter Steinberger
720071a6c6 refactor: extract ACP runtime option commands
Extract ACP runtime-option command flows from `AcpSessionManager` into `manager.runtime-options-commands.ts`.

Verification:
- `pnpm format:fix src/acp/control-plane/manager.core.ts src/acp/control-plane/manager.runtime-options-commands.ts`
- `node scripts/run-oxlint.mjs src/acp/control-plane/manager.core.ts src/acp/control-plane/manager.runtime-options-commands.ts`
- `pnpm tsgo:prod`
- `pnpm test src/acp/control-plane/manager.runtime-config.test.ts src/acp/control-plane/manager.runtime-handles.test.ts src/acp/control-plane/manager.test.ts`
- `pnpm format:check src/acp/control-plane/manager.core.ts src/acp/control-plane/manager.runtime-options-commands.ts`
- `git diff --check`
- `pnpm check:test-types`
- `.agents/skills/autoreview/scripts/autoreview --mode local`
- GitHub PR checks for #88747 passed

Real behavior proof:
Behavior addressed: ACP runtime-option mutation ownership moved out of `AcpSessionManager` without changing set-mode, set-config-option, raw update, reset, persistence, or runtime-cache invalidation semantics.
Real environment tested: Local OpenClaw checkout, Node/pnpm repo toolchain, GitHub Actions PR CI.
Exact steps or command run after this patch: Focused ACP runtime config/handle/manager tests plus prod/test type checks, lint, format, diff check, autoreview, and PR CI.
Evidence after fix: All listed local commands passed, autoreview reported no accepted/actionable findings, and GitHub PR checks passed.
Observed result after fix: `manager.core.ts` is down to 885 LOC, with runtime-option command logic isolated in `manager.runtime-options-commands.ts`.
What was not tested: Live ACP backend mode/config option mutation against a real external ACP provider.
2026-05-31 19:56:43 +01:00
Roee Jukin
2155450ed7 fix(acp): prefer clean command text for local bypass
Prefer the clean channel command body when ACP decides whether an inbound message should bypass the agent loop for local OpenClaw commands.

This keeps envelope-wrapped channel text, such as WhatsApp display bodies, from hiding commands like /status when the channel already provided a normalized command body. The ACP runtime prefilter now uses the same command-text resolution as dispatch, and dispatch still requires registry-backed local commands before bypassing.

Co-authored-by: RoeeJ <RoeeJ@users.noreply.github.com>
2026-05-31 19:56:04 +01:00
Jason
e74931778c fix: preserve workspaces during state-only uninstall
Preserve workspace directories when `openclaw uninstall --state` removes local state, including configured workspaces and implicit per-agent workspaces resolved by the runtime. State-only uninstall now uses a cleanup plan that keeps those workspace roots unless `--workspace` is selected.

Fixes #75052.

Proof:
- `git diff --check origin/main...HEAD`
- `pnpm exec oxfmt --check --threads=1 src/commands/cleanup-utils.ts src/commands/cleanup-utils.test.ts src/commands/uninstall.ts src/commands/uninstall.test.ts docs/cli/uninstall.md docs/install/uninstall.md`
- `node scripts/run-vitest.mjs src/commands/uninstall.test.ts src/commands/cleanup-utils.test.ts src/commands/reset.test.ts src/commands/agents.delete.test.ts`
- `node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.core.test.json --incremental --tsBuildInfoFile /tmp/openclaw-pr75061-core-test-final-rebase2.tsbuildinfo`
- `pnpm docs:list`
- `node scripts/check-docs-mdx.mjs docs/cli/uninstall.md docs/install/uninstall.md`
- `.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main`
- CI: https://github.com/openclaw/openclaw/actions/runs/26721260691

Co-authored-by: Jason-Bai <boybai.work@gmail.com>
2026-05-31 19:54:34 +01:00
ArthurNie
9d54285b0d fix: force preflight compaction before oversized agent turns
Force required preflight context compaction before oversized turns can enter the agent runtime. Treat required preflight compaction as a hard gate: compact, skip only explicit harmless no-op reasons, or surface a visible recovery message when compaction cannot recover.

Fixes #87234.

Co-authored-by: ArthurNie <264332276+ArthurNie@users.noreply.github.com>
2026-05-31 19:48:49 +01:00
Peter Steinberger
3ff86f3350 refactor: migrate voice-call call logs through doctor (#88731) 2026-05-31 19:43:03 +01:00
Peter Steinberger
2f449285b9 refactor: extract ACP close session flow
Refactor ACP close-session ownership by extracting the runtime close/recovery lifecycle into `manager.close-session.ts`.

Verification:
- `pnpm test src/acp/control-plane/manager.test.ts src/acp/control-plane/manager.runtime-config.test.ts src/acp/control-plane/manager.runtime-handles.test.ts`
- `pnpm tsgo:prod`
- `pnpm check:test-types`
- `node scripts/run-oxlint.mjs src/acp/control-plane/manager.core.ts src/acp/control-plane/manager.close-session.ts`
- `pnpm format:check src/acp/control-plane/manager.core.ts src/acp/control-plane/manager.close-session.ts`
- `git diff --check`
- `.agents/skills/autoreview/scripts/autoreview --mode local`
- GitHub PR checks for #88744 passed

Real behavior proof:
Behavior addressed: ACP close-session ownership moved out of `AcpSessionManager` without changing close/recovery behavior.
Real environment tested: Local OpenClaw checkout, Node/pnpm repo toolchain, GitHub Actions PR CI.
Exact steps or command run after this patch: Focused ACP manager tests covering close-session behavior, runtime config, and runtime handles, plus prod/test type checks, lint, format, diff check, autoreview, and PR CI.
Evidence after fix: All listed local commands passed, autoreview reported no accepted/actionable findings, and GitHub PR checks passed.
Observed result after fix: `manager.core.ts` dropped from 1149 LOC to 1038 LOC while close-session runtime lifecycle handling lives in `manager.close-session.ts`.
What was not tested: Live ACP backend close/recovery against a real external ACP provider.
2026-05-31 19:42:46 +01:00
Peter Steinberger
465a5456fe fix(agents): preserve disabled subagent delivery state 2026-05-31 19:42:00 +01:00
Federico Kamelhar
ecbd97e968 fix(gateway): rate-limit bootstrap-token verification
Gateway/security: rate-limits pre-auth bootstrap-token verification and serializes per-IP attempts to prevent mutex-stall DoS while preserving device-token fallback.

Fixes #77978.

Co-authored-by: Federico Kamelhar <federico.kamelhar@oracle.com>
2026-05-31 19:40:22 +01:00
Peter Steinberger
ef04c72f08 docs: require live external API tests 2026-05-31 19:39:41 +01:00
Federico Kamelhar
e76df691fe fix(skills): bound watcher workspace state
Bounds skills watcher subscriptions and workspace snapshot-version state to active workspaces on the current `src/skills/runtime` implementation.

The fix keeps shared path watchers as the owner boundary, evicts idle workspace subscriptions after 1 hour without closing watchers still used by other workspaces, and clears per-workspace version keys only after preserving/advancing invalidation so cached skill snapshots cannot miss changes across teardown or re-enable.

Thanks @fede-kamel.

Fixes #77997.

Co-authored-by: Federico Kamelhar <federico.kamelhar@oracle.com>
2026-05-31 19:35:42 +01:00
Vincent Koc
f983111166 perf(scripts): parallelize test group reports 2026-05-31 20:32:54 +02:00
Vincent Koc
7e0d275f7a fix(agents): preserve skipped subagent delivery state 2026-05-31 19:30:32 +01:00
Peter Steinberger
faae7529fd refactor: extract ACP turn runner
Refactor ACP turn execution ownership by extracting the backend attempt and cleanup loop into `manager.turn-runner.ts`.

Verification:
- `pnpm test src/acp/control-plane/manager.test.ts src/acp/control-plane/manager.turn-results.test.ts src/acp/control-plane/manager.failover.test.ts src/acp/control-plane/manager.runtime-handles.test.ts src/acp/control-plane/manager.runtime-config.test.ts`
- `pnpm tsgo:prod`
- `pnpm check:test-types`
- `node scripts/run-oxlint.mjs src/acp/control-plane/manager.core.ts src/acp/control-plane/manager.turn-runner.ts`
- `pnpm format:check src/acp/control-plane/manager.core.ts src/acp/control-plane/manager.turn-runner.ts`
- `git diff --check`
- `.agents/skills/autoreview/scripts/autoreview --mode local`
- GitHub PR checks for #88739 passed

Real behavior proof:
Behavior addressed: ACP turn execution ownership moved out of `AcpSessionManager` without changing runtime behavior.
Real environment tested: Local OpenClaw checkout, Node/pnpm repo toolchain, GitHub Actions PR CI.
Exact steps or command run after this patch: Focused ACP manager tests covering turn results, failover, runtime handles, runtime config, plus prod/test type checks, lint, format, diff check, autoreview, and PR CI.
Evidence after fix: All listed local commands passed, autoreview reported no accepted/actionable findings, and GitHub PR checks passed.
Observed result after fix: `manager.core.ts` dropped from 1495 LOC to 1149 LOC while turn execution lives in `manager.turn-runner.ts`.
What was not tested: Live ACP backend process recovery against a real external ACP provider.
2026-05-31 19:29:47 +01:00
Jeff
01ef169004 fix(agents): sanitize raw HTTP 401 provider errors
Sanitize credential-shaped provider HTTP 401 failures in embedded-agent replies so chat users see a re-authentication hint instead of raw provider text such as `HTTP 401: "Invalid token"`.

The classifier now requires auth classification plus positive 401 evidence, and it stays narrow to credential-shaped failures so billing, scope, replay-invalid, schema, message-only auth, and plain 403 paths keep their existing behavior.

Fixes #56197. Thanks @lokamir.

Co-authored-by: jeffrey701 <jeffreyconradtucker@gmail.com>
2026-05-31 19:26:42 +01:00
zhang-guiping
2fbddce881 fix(cli): avoid catalog validation in agents add (#88314)
Fixes #76284.

Thanks @zhangguiping-xydt.

Co-authored-by: 张贵萍0668001030 <zhang.guiping@xydigit.com>
2026-05-31 19:22:16 +01:00
Ben Newell
a88e4fb7e0 fix(memory-core): preserve phase signals on read errors
Phase-signal store reads now recover only missing files and corrupt JSON. Nonrecoverable filesystem read failures propagate so dreaming aborts before overwriting existing phase-signal history with an empty replacement.

Fixes #77881.
Thanks @bennewell35.

Co-authored-by: bennewell35 <newelljben@gmail.com>
2026-05-31 19:18:56 +01:00
Peter Steinberger
90329e2848 refactor: extract ACP runtime resume state
Extract ACP runtime resume/discard recovery helpers from `AcpSessionManager` into `manager.runtime-resume-state.ts`, and share the manager session-meta writer callback type from `manager.types.ts`. Keeps close-time fresh-session recovery, early-turn retry, persisted resume identifier clearing, and discard-persistent-state behavior intact while reducing `manager.core.ts` from 1655 LOC to 1495 LOC.

Proof: focused ACP manager runtime-handle/runtime-config/turn-result tests, prod + test type checks, narrow oxlint, format check, diff check, autoreview clean, PR CI green.
2026-05-31 19:18:18 +01:00
Vincent Koc
454a69a048 test(gateway): align startup refactor expectations 2026-05-31 19:10:25 +01:00
Federico Kamelhar
78f2a89e95 fix(discord): bound REST entity cache growth
Bound DiscordEntityCache entries with a write-time expired-entry sweep and a default 5,000-entry cap while preserving current safe expiry timestamp normalization. This prevents high-cardinality Discord user/channel/guild/member fetches from retaining stale Map entries for the gateway lifetime.

Fixes #77975.
Thanks @fede-kamel.

Co-authored-by: Federico Kamelhar <federico.kamelhar@oracle.com>
2026-05-31 19:08:27 +01:00
Peter Steinberger
3613981579 test(gateway): refresh startup assertions 2026-05-31 19:07:31 +01:00
Sebuh Honarchian
a129b912a4 fix(gateway): guard direct session display names
Guard group display-name generation behind group/channel classification so direct Telegram sessions fall back to their explicit or origin labels. Keep session-list search aligned with that visible fallback.

Fixes #55354.
Thanks @sebuh-infsol.
2026-05-31 19:03:42 +01:00
Peter Steinberger
2a30b937cb refactor: extract ACP runtime handle ensure flow
Extract ACP runtime-handle ensure/reuse/recreate flow into `manager.runtime-handle-ensure.ts`. Keeps `AcpSessionManager` focused on orchestration while preserving backend resolution, resume identity retry, metadata persistence, cache replacement, and concurrency-limit behavior.

Proof: focused ACP manager runtime-handle/runtime-config/turn-result tests, narrow oxlint, prod + test type checks, autoreview clean, PR CI green.
2026-05-31 19:01:59 +01:00
Mert Başar
0ff5fe3a80 fix(auth): add force re-login recovery and fallback auth skips
Summary:
- Add forced provider re-login support that clears cached auth profiles before running provider login again.
- Add provider-auth remediation guidance and a session-scoped skip cache for known-bad fallback auth attempts.
- Wire session ids through agent command, auto-reply, and embedded compaction fallback callers so the skip cache applies on real run paths.
- Fail closed when forced auth profile removal cannot update the profile store.

Verification:
- Local format, lint, diff-check, focused Vitest shards, and autoreview passed.
- PR CI, CodeQL Security High, and Critical Quality agent-runtime-boundary passed on head 1b4e9e753e.

Co-authored-by: Mert Basar <MertBasar0@users.noreply.github.com>
2026-05-31 19:01:51 +01:00
Vincent Koc
db0209ac5d perf(scripts): parallelize remote core oxlint shards 2026-05-31 20:01:41 +02:00
Peter Steinberger
3bac0bcbfb fix(codex): stream final answer partials (#88730) 2026-05-31 19:00:44 +01:00
Youssef Hemimy
beb499b4d1 fix(approvals): interpolate request id in fallback command
Fix approval fallback text so exec and plugin approval messages render a concrete request id in the chat copy-paste command instead of the literal <id> placeholder.

This makes the Reply with: /approve ... line directly usable for owners while keeping the existing approval resolver contract unchanged.

Proof:
- git diff --check origin/main...HEAD
- pnpm test src/infra/exec-approval-forwarder.test.ts src/infra/plugin-approval-forwarder.test.ts src/plugin-sdk/approval-renderers.test.ts
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
- CI run 26720052738 passed

Thanks @itsuzef.
2026-05-31 18:59:43 +01:00
Peter Steinberger
7617d062fd chore(lint): fix rebased lint violations 2026-05-31 18:59:02 +01:00
Peter Steinberger
304e2c83c0 chore(lint): enable stricter oxlint rules 2026-05-31 18:59:02 +01:00
Peter Steinberger
cb569f6ad9 docs: clarify superseded PR close policy 2026-05-31 18:57:32 +01:00
Chunyue Wang
b8f25e9648 fix(memory): serialize qmd writes across processes (#85931)
Serialize QMD update and embed writes with one per-agent store lock so foreground memory search/index and gateway background QMD work do not write the same index.sqlite concurrently.

The embed path now waits for global embed capacity before taking the per-store lock, so queued embeds do not block same-agent foreground updates while no store write is active.

Fixes #66339
Thanks @openperf.

Co-authored-by: Chunyue Wang <16864032@qq.com>
2026-05-31 18:57:15 +01:00
Peter Steinberger
6b0ad98d62 test(extensions): update pairing challenge assertions 2026-05-31 18:56:20 +01:00
Alex Ho
d88767e819 fix(docker): refresh Node base image digests (#84988)
Refresh pinned node:24-bookworm and node:24-bookworm-slim manifest-list digests across the root, smoke, and e2e Dockerfiles. Update digest pin assertions to cover the plugin-binding e2e Dockerfile.

Verified with live Docker digest inspection, targeted Dockerfile tests, root base-runtime build, install-sh smoke build, and plugin-binding e2e build.

Thanks @LibraHo.
2026-05-31 18:55:33 +01:00
Yuval Dinodia
b988e2f92b fix(daemon): detect system-scope systemd gateway units on Linux
Detect OpenClaw gateway units installed in the system systemd scope, including marker-owned custom unit names such as `openclaw.service`. Route status/restart/stop through the system manager when appropriate, and show non-root users the matching `sudo systemctl ...` command instead of falling back to unmanaged process signaling.

Fixes #87577.
Thanks @yetval.

Verification:
- `node scripts/run-vitest.mjs src/daemon/systemd.test.ts src/cli/daemon-cli/lifecycle.test.ts src/daemon/inspect.test.ts src/cli/daemon-cli/lifecycle-core.test.ts src/cli/daemon-cli/status.gather.test.ts src/cli/daemon-cli/response.test.ts src/commands/doctor-gateway-daemon-flow.test.ts src/cli/update-cli/restart-helper.test.ts src/infra/outbound/message-action-runner.core-send.test.ts`
- AWS Crabbox `cbx_69f97dff5e5c`, run `run_a68431b3dad6`: exact SHA checkout, focused tests, real `/etc/systemd/system/openclaw.service` status/restart/stop proof.
2026-05-31 18:52:02 +01:00
Peter Steinberger
e014145ac1 docs: mention markdown host-local media sends (#79658) 2026-05-31 18:51:45 +01:00
Clever
14dbf80c74 Fix explicit text alias extension check 2026-05-31 18:51:45 +01:00
Clever
a9eefeea71 Remove changelog entry from text media PR 2026-05-31 18:51:45 +01:00
Clever
9f7eaf06e1 docs: clarify host-local text media boundary 2026-05-31 18:51:45 +01:00
Clever
7d3fc6f924 docs: update host-local media text policy 2026-05-31 18:51:45 +01:00
Clever
b454677874 Restrict plain text media sends to txt 2026-05-31 18:51:45 +01:00
Clever
d729811224 Add changelog for text document media sends 2026-05-31 18:51:45 +01:00
Clever
1e14f4400f Allow validated text document media sends 2026-05-31 18:51:45 +01:00
Peter Steinberger
d641126c1d feat(plugin-sdk): add typed presentation command actions (#88721)
* feat(plugin-sdk): add typed presentation command actions

* test: use shared env helper in telegram bot tests

* test: expect typed approval actions

* test: expect typed sdk approval actions
2026-05-31 18:48:45 +01:00
Peter Steinberger
4b1d2faa99 docs: harden Codex dependency review gate 2026-05-31 18:48:15 +01:00
Peter Steinberger
058152cf69 refactor: extract ACP manager runtime handle cache
Extract ACP manager runtime-handle cache ownership into a dedicated helper. Keeps the session manager focused on lifecycle orchestration while preserving cached handle reuse, close/clear, idle eviction, matching, and observability behavior.

Proof: focused ACP manager runtime-handle/runtime-config tests, narrow oxlint, pnpm check:test-types, autoreview clean, PR CI green.
2026-05-31 18:46:07 +01:00
Jerry-Xin
56362524ed fix(agents): prefer real tool results over repair synthetics
Ref #84134.

Prefer real tool results over generated missing-result placeholders during transcript repair, including late results after later assistant turns and explicitly marked custom-text repair placeholders. Keep real error outputs such as aborted when they are not generated repair placeholders.

Thanks @Jerry-Xin.

Co-authored-by: 忻役 <xinyi@mininglamp.com>
Co-authored-by: Jerry-Xin <jerryxin0@gmail.com>
2026-05-31 18:44:37 +01:00
Peter Steinberger
05b3f1c29d docs: require deeper PR review evidence 2026-05-31 18:42:39 +01:00
Sunjae Kim
201bf125af fix(session-store): rewrite generated transcript paths on rollover
Rewrite generated session transcript paths at the shared session-store merge boundary when a persisted session rolls from one session id to another. This prevents patches that carry a stale generated `sessionFile` from leaving a new logical session id attached to the old transcript file, while preserving custom transcript paths.

Refs #65564.

Proof:
- `node scripts/run-vitest.mjs src/config/sessions/sessions.test.ts`
- `node scripts/run-vitest.mjs src/agents/command/session-store.test.ts`
- `git diff --check origin/main...HEAD`
- `.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main`
- CI run 26719583889 attempt 2

Co-authored-by: Sunjae Kim <sunjaekim@bigvalue.co.kr>
2026-05-31 18:41:56 +01:00
Peter Steinberger
db40fde88c fix: persist ACP metadata in SQLite (#88724)
* fix: persist acp metadata in sqlite

* test: align session store acp expectations
2026-05-31 18:38:51 +01:00
Peter Steinberger
cdff174ce6 docs: note OpenAI Codex canonical provider 2026-05-31 18:37:30 +01:00
Vincent Koc
1ba9af1693 fix(ui): improve danger callout contrast 2026-05-31 18:36:14 +01:00
Peter Steinberger
bb5b6f38f4 test: harden release CI ordering 2026-05-31 18:33:26 +01:00
Vincent Koc
a3fa5b6577 test(vitest): classify Crabbox shared dependencies 2026-05-31 19:31:17 +02:00
Peter Steinberger
7061c1e5fd docs: raise bulk close confirmation threshold 2026-05-31 18:29:31 +01:00
Peter Steinberger
af58ed9554 docs: require external api proof search 2026-05-31 18:27:49 +01:00
Peter Steinberger
090ca19c05 refactor: make Telegram message cache SQLite-only
Remove Telegram runtime JSON sidecar read/write fallback for the prompt-context message cache. Keep legacy sidecar parsing for doctor import into SQLite plugin state and update docs/tests to match.
2026-05-31 18:27:24 +01:00
zhang-guiping
b6e9473e9f fix(auth): skip Anthropic API keys for usage status
Fixes #85124.

Anthropic standard API keys no longer resolve as provider usage auth for `openclaw status --usage`, so valid inference keys are not sent to Anthropic's OAuth usage endpoint and surfaced as misleading invalid bearer-token errors.

The provider usage-auth SDK result now has an explicit handled/no-token shape so provider hooks can suppress generic fallback without widening the OAuth helper contract. Docs, Plugin SDK API baseline, and extension package-boundary cache inputs were updated with the new contract.

Thanks @zhangguiping-xydt.

Proof:
- node scripts/run-vitest.mjs src/infra/provider-usage.auth.normalizes-keys.test.ts src/infra/provider-usage.auth.plugin.test.ts extensions/anthropic/index.test.ts
- pnpm plugin-sdk:api:check
- pnpm plugin-sdk:check-exports
- git diff --check origin/main...HEAD
- pnpm docs:list
- pnpm run test:extensions:package-boundary:compile
- autoreview clean: no accepted/actionable findings
- PR CI rollup green: 131 success, 22 skipped, 1 neutral, 0 failures

Co-authored-by: 张贵萍0668001030 <zhang.guiping@xydigit.com>
2026-05-31 18:26:03 +01:00
Peter Steinberger
fbc611ab4c docs: require fresh autoreview before landing code 2026-05-31 18:25:11 +01:00
Peter Steinberger
2b4f3e47b6 test(msteams): add keyed store to file consent runtime stub 2026-05-31 18:24:51 +01:00
Peter Steinberger
1a65425a6e refactor: extract ACP translator session updates
Extract ACP translator session-update and event-ledger emission into a dedicated helper. Keeps translator orchestration intact while preserving replay, recording, and fallback behavior.\n\nProof: focused ACP translator tests, narrow oxlint, pnpm check:test-types, autoreview clean, PR CI green.
2026-05-31 18:24:26 +01:00
Rain
301f17fb58 fix(agents): validate context engine assemble result shape
Validate context-engine assemble results at the shared harness boundary before embedded or Codex runners consume them.

Malformed plugins that return an object without a `messages` array now throw a descriptive engine-scoped error and use the existing runner fallback to pipeline messages, rather than poisoning session state and crashing prompt assembly on `.length`.

Proof:
- `node scripts/run-vitest.mjs src/agents/harness/context-engine-lifecycle.test.ts`
- `node scripts/run-vitest.mjs src/agents/embedded-agent-runner/run/attempt.spawn-workspace.context-engine.test.ts`
- `pnpm exec oxfmt --check src/agents/harness/context-engine-lifecycle.ts src/agents/harness/context-engine-lifecycle.test.ts`
- `git diff --check origin/main...HEAD`
- GitHub CI on `5b6b7b1bf69b8f30329fdf749161a192d3d016fe`: https://github.com/openclaw/openclaw/actions/runs/26719202811

Thanks @Pluviobyte.

Fixes #75541
2026-05-31 18:21:59 +01:00
Peter Steinberger
86ff92e7a8 docs: require best-fix PR review judgment 2026-05-31 13:21:15 -04:00
wAngByg
6c5cd7177f fix(doctor): detect stale gateway service version metadata 2026-05-31 18:17:30 +01:00
Peter Steinberger
6f2fbaaaf8 fix(gateway): track plugin subagent runs in agent handler
Plugin SDK subagent runs now register at the Gateway agent acceptance boundary so subagent_ended hooks fire without creating duplicate CLI task rows.

The registration stays best-effort: if the subagent registry cannot persist tracking state, the run still dispatches and falls back to the existing CLI task tracking path.

Closes #59164

Co-authored-by: Cornna <96944678+ymylive@users.noreply.github.com>
2026-05-31 18:16:00 +01:00
Peter Steinberger
21dcf2dd99 chore: stop tracking package dist output 2026-05-31 18:15:40 +01:00
Vincent Koc
938841cff3 fix(agents): count stream deltas incrementally
Count model stream diagnostic response bytes from snapshotless stream chunks, excluding accumulated partial snapshots on delta events. This avoids repeatedly serializing answer-so-far snapshots during streamed model calls and updates OTEL/docs wording for the new metric baseline.

Refs #86599.

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-05-31 18:13:58 +01:00
Peter Steinberger
a053ae5d65 test: align release CI expectations 2026-05-31 18:13:02 +01:00
Peter Steinberger
33c246dbba refactor: move plugin state slices to sqlite
* refactor: move plugin state slices to sqlite

* fix: keep legacy plugin state migration out of runtime

* fix: add doctor migrations for plugin sqlite state

* fix: preserve teams feedback learning migration keys

* fix: merge teams legacy feedback learnings

* fix: guard doctor imports against plugin state caps

* fix: leave lossy teams learning filenames unmigrated

* fix: preserve teams feedback learning scope

* fix: load plugin doctor contracts from package dist

* fix: satisfy plugin state migration gates
2026-05-31 18:09:27 +01:00
Peter Steinberger
12d4dda1bb perf(plugins): avoid duplicate provider hook load probes
Avoid duplicate provider hook load probes.

Summary:
- Route provider hook-list resolution through the existing provider resolver skip path instead of pre-checking provider load state separately.
- Preserve the provider runtime in-flight/reentrant guard because existing tests prove it prevents cached misses and nested provider-load recursion.

Verification:
- node scripts/run-vitest.mjs src/plugins/providers.runtime.consult-current-snapshot.test.ts
- node scripts/run-vitest.mjs src/plugins/provider-runtime.test.ts
- node scripts/run-vitest.mjs src/plugins/providers.test.ts
- pnpm exec oxfmt --check src/plugins/providers.runtime.ts src/plugins/provider-hook-runtime.ts
- git diff --check
- pnpm changed:lanes --json
- autoreview --mode local --prompt-file /tmp/provider-hotpath-cleanup-review.md
- Live E2E: https://github.com/openclaw/openclaw/actions/runs/26718818705
2026-05-31 18:08:13 +01:00
Peter Steinberger
f80a1e9e85 refactor: clean up ACP translator and manager tests (#88677)
* test: split ACP translator bridge coverage

* refactor: extract ACP translator session helpers

* refactor: extract ACP manager backend failover helpers

* test: split ACP manager failover coverage

* test: split ACP manager runtime config coverage

* test: split ACP manager turn result coverage

* test: split ACP manager runtime handle coverage

* test: keep ACP manager helpers within task boundaries

* ci: split gateway runtime state test shard
2026-05-31 18:04:28 +01:00
Sebastien Tardif
66bbcfdade fix(telegram): handle ENOENT race in spool drain recovery rename
Handle the Telegram isolated-polling spool recovery race where a stale `.processing` claim can disappear between discovery and the final rename back to pending. Recovery now treats `ENOENT` as benign and mirrors the existing duplicate-pending cleanup path for `EEXIST`, avoiding noisy drain-failure logs and spurious failure counters without changing claim ownership semantics.

Adds a regression test that removes the claim from inside `shouldRecover`, after recovery has discovered the entry and before the final rename path, so the old code would hit the reported `ENOENT` window.

Fixes #87847

Co-authored-by: Sebastien Tardif <sebtardif@ncf.ca>
2026-05-31 18:02:55 +01:00
alkor2000
3ceaafb2b3 fix: extend CA bundle auto-injection to all 8 Node version managers
Expand Linux CA bundle auto-injection to recognize fnm, Volta, asdf, mise, n, nodenv, nodebrew, and nvs paths in addition to nvm. Adds regression coverage for the new version-manager path layouts.

Fixes #59494.
Thanks @alkor2000.

Co-authored-by: alkor2000 <200923177@qq.com>
2026-05-31 18:02:34 +01:00
Vincent Koc
01a5e492b7 test(discord): fast-forward voice fallback timers 2026-05-31 19:02:16 +02:00
Peter Steinberger
772d13c19d fix: handle iOS global agent transcripts 2026-05-31 18:01:17 +01:00
Vincent Koc
0f6be951e0 fix(agents): avoid full stream replay on text deltas (#88252)
Prevent streaming assistant text updates from reparsing the full accumulated reply for plain deltas, avoiding repeated work for small-model streams while preserving full cleanup for directives, media, and final events.

Also load the normal Control UI Vite config in the mock browser server so browser E2E uses the same workspace aliases as dev.

Thanks @vincentkoc.
2026-05-31 17:59:45 +01:00
alkor2000
723d09ff85 fix(cli): extend holiday tagline dates through 2030
Extend the CLI holiday tagline tables for Lunar New Year, Eid al-Fitr, Easter, Diwali, and Hanukkah through 2030 so those taglines do not silently disappear after 2027.

Maintainer fixup: corrected the 2030 Diwali row to October 25 and added explicit regression coverage for that date.

Verification:
- node scripts/run-vitest.mjs src/cli/tagline.test.ts
- Direct pickTagline() probe confirmed 2030-10-25 activates Diwali and 2030-10-26 does not.

Co-authored-by: alkor2000 <200923177@qq.com>
2026-05-31 17:59:43 +01:00
Peter Steinberger
0ee5f47fba fix(feishu): enforce bitable account gates 2026-05-31 17:51:35 +01:00
OpenClaw Updater
73bb84e4bf fix: preserve explicit Feishu bitable gates 2026-05-31 17:51:35 +01:00
Gorin Lee
5cfb578cba plugin: gate Feishu bitable tools by config 2026-05-31 17:51:35 +01:00
Peter Steinberger
4150c6ff82 feat: add typed MCP code-mode API (#88678)
* feat: add typed MCP code-mode API

* fix: stabilize code-mode namespace drain

* fix: preserve code-mode run cap

* fix: reserve code-mode snapshot capacity
2026-05-31 17:51:22 +01:00
Peter Steinberger
d1b514af2e fix: remove webchat config surface 2026-05-31 12:49:18 -04:00
Masato Hoshino
3ef02ca818 fix(plugins): reuse current metadata snapshot in provider hot paths
Refactor provider metadata lookup so hot paths consult the current process snapshot before falling back to a metadata load.

Centralize provider metadata lookup in the provider runtime and update the focused tests/mocks that exercise embedded-agent and provider loading paths.

Verification:
- node scripts/run-vitest.mjs src/plugins/providers.runtime.consult-current-snapshot.test.ts
- node scripts/run-vitest.mjs src/agents/embedded-agent-runner/run/attempt.cwd-split.test.ts
- node scripts/run-vitest.mjs src/plugins/providers.test.ts
- autoreview --mode branch --base origin/main
- CPU profile loop: current-snapshot resolve 0.459 us/call vs warm direct metadata load 131.493 us/call
- GitHub CI on 728bd53510

Co-authored-by: masatohoshino <g515hoshino@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 17:48:58 +01:00
Jerry-Xin
4e84d0eaa5 fix(auto-reply): track memory flush failure exhaustion
Add durable memoryFlush failure metadata and lifecycle events so provider failures during memory flush no longer leave a session with no recorded recovery state.

After three consecutive non-abort flush failures, mark the current compaction cycle as exhausted so later messages can proceed without deleting transcript history. Successful flushes clear the failure metadata, and plugin session-entry slot reservations now protect the new fields.

Release-note: memoryFlush sessions can now fail open after repeated provider-side flush failures instead of retrying indefinitely before normal replies.

Refs #85645

Co-authored-by: 忻役 <xinyi@mininglamp.com>
2026-05-31 17:47:12 +01:00
Peter Steinberger
5bce222b0c docs(agents): require related issue search 2026-05-31 17:46:19 +01:00
Peter Steinberger
1af4c035e4 refactor: move delivery queues to SQLite (#88665)
* refactor: move delivery queues to sqlite

* fix: satisfy delivery queue sqlite boundaries

* test: remove stale reasoning replay assertion

* fix: migrate failed delivery queue entries

* test: stabilize exec shell snapshot mocks

* fix: clean legacy delivery queue markers
2026-05-31 17:43:03 +01:00
Vincent Koc
c7b190beec fix(ollama): yield during dense stream processing (#87818)
Co-authored-by: uday <udaymanish.thumma@gmail.com>
2026-05-31 17:38:13 +01:00
Yuval Dinodia
be29096081 fix(agents): resolve Codex static-catalog cold start
Fixes Codex/plugin-harness cold starts for exact static-catalog model ids such as openai/gpt-5.3-codex without adding a second resolver retry loop. The embedded runner now performs the normal provider-runtime attempt with agent discovery skipped, then consults the bundled static catalog before falling back to generic configured-provider synthesis when plugin harness owns transport.

The OpenAI static catalog row carries the Codex ChatGPT transport metadata, dynamic provider metadata still wins for runtime-owned models, and focused regression coverage exercises both paths.

Fixes #88510.

Co-authored-by: yetval <yetvald@gmail.com>
2026-05-31 17:38:10 +01:00
litang9
d446c26acb feat(deepseek): show provider balance in usage status
Show DeepSeek API-key account balance in status/auth-status usage surfaces by adding a summary-only provider usage snapshot path, a DeepSeek balance fetcher, SDK/docs coverage, and focused regression tests.

Maintainer verification accepted the additive provider-usage/status contract and the DeepSeek balance visibility boundary for authenticated status surfaces.

Proof:
- Live DeepSeek balance proof via 1Password-backed DEEPSEEK_API_KEY against https://api.deepseek.com/user/balance; key and balance amount redacted.
- GitHub CI run 26717953383 passed on the current head.
- Real behavior proof run 26718215605 passed after the PR body was refreshed.
- Local clean PR clone: git diff --check; node --max-old-space-size=8192 --import tsx scripts/generate-plugin-sdk-api-baseline.ts --check; node scripts/run-vitest.mjs run src/agents/bash-tools.exec.path.test.ts.

Co-authored-by: Alex Tang <tangli1987118@hotmail.com>
Co-authored-by: litang9 <141409885+litang9@users.noreply.github.com>
2026-05-31 17:35:41 +01:00
vortexopenclaw
fa0a323ebd fix(secrets): treat Codex app-server marker as non-secret
Treat the synthetic Codex app-server auth marker as a core non-secret marker so secrets audit does not flag it when bundled plugin discovery is disabled.\n\nVerified with focused model-auth marker tests, isolated secrets-audit CLI proof, autoreview, and green CI.\n\nThanks @vortexopenclaw.
2026-05-31 17:35:13 +01:00
Vincent Koc
dd79c8836a perf(scripts): parallelize startup metadata help rendering 2026-05-31 18:35:01 +02:00
Peter Steinberger
2e3650d5b3 fix: inset iOS onboarding action buttons 2026-05-31 17:31:17 +01:00
Peter Steinberger
d76627f232 ci: add crabbox prewarm jobs 2026-05-31 17:30:26 +01:00
Ron Cohen
5152d8beb4 fix(whatsapp): suppress silent-run typing indicators
Suppress WhatsApp typing indicators only for silent message-tool-only unmentioned group runs. Automatic visible replies and authorized group commands still show composing normally.

Fixes the autoreview regression risk by narrowing suppressTyping and adding coverage for both silent and visible group paths.

Proof:
- pnpm test src/auto-reply/reply/reply-utils.test.ts extensions/whatsapp/src/auto-reply/monitor/inbound-dispatch.test.ts
- .agents/skills/autoreview/scripts/autoreview --mode local
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
- CI run 26717880577 green

Thanks @Bluetegu.
2026-05-31 17:28:58 +01:00
Yuval Dinodia
a6ee3dbbdd fix(ios): update group chats in realtime
Subscribe the iOS gateway chat transport to per-session transcript events so group chats update when other clients send messages. Constrain local user echo adoption to the optimistic row tied to the still-pending send run, so repeated same-content user messages from other clients append instead of replacing history.

Fixes #80231.

Co-authored-by: Yuval Dinodia <yetvald@gmail.com>
2026-05-31 17:24:59 +01:00
Gavin Zeng
4ab2eb45d0 fix(doctor): repair stale session snapshot paths
Fixes #85689.

Summary:
- Repair stale bundled skill paths in inline prompts, prompt blobs, resolved skill metadata, and resolved skill sourceInfo metadata.
- Keep repair scoped to cached snapshot fields and preserve unrelated session content.
- Replace the root reproduction script with colocated Vitest coverage.

Verification:
- pnpm test src/commands/doctor-session-snapshots.test.ts -- --reporter=verbose
- pnpm check:test-types
- pnpm lint --threads=8
- pnpm dup:check:coverage
- pnpm tsgo:prod
- pnpm check:changed (Testbox tbx_01kszd25ad7x81j0f1r7kfsqc6, Actions run 26717761222)
- PR CI green on 540b1a387e

Co-authored-by: GavinZ <zengganghui@zgh123.space>
2026-05-31 17:24:29 +01:00
samzong
5b310a7b27 fix(agents): release abandoned provider streams
Fix streamed provider cleanup so abandoned managed fetch bodies no longer keep undici sockets open, and cancel Anthropic/Gemini SSE readers deterministically when parsing exits early.

Keep the FinalizationRegistry abort path as a last-resort GC safety net for unmanaged/abandoned responses, while parser-owned paths cancel readers explicitly on thrown errors or malformed events.

Also records the browser-only Control UI redactor alias in the optional deadcode allowlist and keeps mocked exec supervisor tests off shell snapshot wrapping after the branch was rebased onto default shell snapshots.

Fixes #67461

Verification:
- node scripts/run-vitest.mjs src/agents/provider-transport-fetch.test.ts src/agents/anthropic-transport-stream.test.ts extensions/google/transport-stream.test.ts src/agents/bash-tools.test.ts src/agents/bash-tools.exec.path.test.ts test/scripts/test-live-shard.test.ts
- pnpm check:test-types
- node scripts/run-oxlint-shards.mjs --threads=8
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main --parallel-tests "node scripts/run-vitest.mjs src/agents/provider-transport-fetch.test.ts src/agents/anthropic-transport-stream.test.ts extensions/google/transport-stream.test.ts src/agents/bash-tools.test.ts src/agents/bash-tools.exec.path.test.ts test/scripts/test-live-shard.test.ts"
- git diff --check origin/main...HEAD
- PR CI on a1db789652

Co-authored-by: samzong <samzong.lu@gmail.com>
Signed-off-by: samzong <samzong.lu@gmail.com>
2026-05-31 17:17:53 +01:00
Peter Steinberger
31c83c6be1 chore(plugin-sdk): refresh API baseline 2026-05-31 17:17:02 +01:00
Peter Steinberger
fbfbe45fc6 fix(agents): use static shell snapshot temp prefix 2026-05-31 17:12:24 +01:00
Mike Harrison
63d0c1d513 fix(slack): keep progress drafts in one message (#85612)
Keep Slack progress-mode drafts on one rolling preview message across assistant and reasoning boundaries while preserving boundary cleanup and the latest visible tool-progress lines. Partial/replace modes still start a fresh draft at assistant boundaries.

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-31 17:07:41 +01:00
Peter Steinberger
71a516d644 ci: narrow legacy webchat migration value 2026-05-31 12:07:36 -04:00
Syu
63621eead2 fix(discord): route thread bindings to plugin owners
Route Discord thread follow-up messages to plugin-owned bindings by the raw thread id while retaining parent channel fallback matching. This fixes `/codex bind` follow-ups in Discord threads being claimed by the parent OpenClaw route instead of the bound Codex session.

Verification:
- `node scripts/run-vitest.mjs extensions/discord/src/channel.conversation.test.ts src/hooks/message-hook-mappers.test.ts extensions/discord/src/monitor/message-handler.process.test.ts -t "prefers bound session keys|passes Discord thread parent only|routes Discord thread plugin-owned bindings|passes thread parent ids|thread binding"`
- `node scripts/run-vitest.mjs src/auto-reply/reply/dispatch-from-config.test.ts -t "routes Discord thread plugin-owned bindings by raw thread id"`
- `pnpm build`
- `pnpm lint --threads=8`
- `CI=true FORCE_COLOR=0 pnpm lint --threads=8`
- `.agents/skills/autoreview/scripts/autoreview --mode local`
- GitHub: Real behavior proof, check-test-types, check-dependencies, check-prod-types, auto-reply dispatch shard, hooks shard, and extension package boundary passed on head 1e896d9835.

Known unrelated CI noise at merge: broad opengrep/test/lint CI failures are outside the touched Discord/session-binding surface and contradicted by focused local proof where applicable.

Co-authored-by: Hex <hex@openclaw.ai>
2026-05-31 17:03:55 +01:00
saju01
fbb776d92c feat(github-copilot): add Claude Opus 4.8 to default model catalog
Add Claude Opus 4.8 to the GitHub Copilot static model catalog and default model IDs.

Updates provider manifest metadata and regression coverage so fallback/default discovery includes claude-opus-4.8.

PR: #88547
Co-authored-by: saju01 <saju@coderedcorp.com>
2026-05-31 17:00:24 +01:00
Peter Steinberger
6f4ba7c80e ci: fix acp spawn defaults lint 2026-05-31 12:00:09 -04:00
Ho Lim
044f7f3790 fix: route iMessage DM media through attachment handoff (#87904)
* fix: route iMessage DM media through attachment handoff

* fix: close iMessage caption follow-up clients

* test: stabilize iMessage timeout recovery checks

* fix(imessage): keep attachment reply-cache identifiers aligned

* fix(imessage): preserve service for media handoff

* fix(imessage): prefer caption ids for placeholder attachments

* fix(imessage): preserve region fallback for media handles

* fix(imessage): retain chat id attachment cache scope

* fix(imessage): avoid premature caption echoes

---------

Co-authored-by: Omar Shahine <10343873+omarshahine@users.noreply.github.com>
2026-05-31 09:00:00 -07:00
Peter Steinberger
d07f508020 fix: retire webchat channel config 2026-05-31 11:58:54 -04:00
Peter Steinberger
e5097b3b09 fix(tlon): avoid bundling native skill packages 2026-05-31 16:58:46 +01:00
Jayesh Betala
29dd7847fd fix(terminal): clamp wide graphemes in narrow table cells
Clamps ANSI-aware terminal table cells before padding so width-2 graphemes cannot push borders out of alignment in width-1/narrow columns.

Fixes #88556.

Proof:
- node scripts/run-vitest.mjs run packages/terminal-core/src/ansi.test.ts packages/terminal-core/src/table.test.ts
- CI run 26717035619; check-dependencies red only for unrelated current-main deadcode issue ui/src/ui/browser-redact.ts, also red on main run 26717029674. checks-node-agentic-agents-core rerun failed in unrelated src/agents/bash-tools*.test.ts outside this PR diff.

Co-authored-by: Jayesh Betala <jayesh.betala7@gmail.com>
2026-05-31 16:54:47 +01:00
Alix-007
2870a28aa9 fix(memory-core): reclaim orphaned dreaming sessions
When dreaming narrative cleanup calls subagent.deleteSession() in the finally block and it throws, the store row can be left behind referencing a still-present transcript. The scrubber only pruned dreaming rows whose transcript was missing, so these orphans lingered in the recent sessions sidebar with no kind/status/endedAt and accumulated across restarts.

Reclaim a dreaming store row when its transcript is missing OR has aged past DREAMING_ORPHAN_MIN_AGE_MS, then leave the transcript unreferenced so the orphan-transcript pass archives it.

Fixes #88322

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 16:52:11 +01:00
Vincent Koc
9850ee65c9 test(doctor): cache default command in e2e 2026-05-31 17:50:38 +02:00
Peter Steinberger
d1c4c3344e ci: mark browser redactor as UI entry 2026-05-31 11:47:40 -04:00
Peter Steinberger
a3c6164a8d test: add ACP spawn defaults live Docker test 2026-05-31 16:46:20 +01:00
Franco Viotti
a71b121c69 fix(googlechat): preserve thread for message tool replies (#80996)
Use the Google Chat thread resource as the ambient message-tool reply target so replies stay in the inbound thread. Normalize the current Google Chat space target and let plugin threading adapters explicitly suppress the generic message-id fallback when a provider needs a thread resource instead of a message resource.

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Franco Viotti <franco-viotti@users.noreply.github.com>
2026-05-31 16:43:46 +01:00
Peter Steinberger
ed74fa692b test(ui): narrow vite resolve hook in config test 2026-05-31 16:42:13 +01:00
Peter Steinberger
210adf1d11 fix(agents): retry transient stale session locks
Follow-up to #88658. Retries transient stale session-lock acquire failures when diagnostics show the old stale report disappeared, was replaced by a fresh valid lock, or was replaced by a fresh payload-less lock still inside the mtime/orphan grace window.

Preserves typed `SessionWriteLockStaleError` diagnostics for still-present live OpenClaw-owned stale locks.

Proof: 53 focused session-write-lock tests passed locally and in the agents-core CI shard; `pnpm tsgo:test:src`, touched-file oxlint, `git diff --check`, and autoreview passed locally. CI run 26716843811 has unrelated failures in UI deadcode/types and bash-tools tests; session-write-lock tests passed in that run.

Refs #87217.
2026-05-31 16:41:37 +01:00
clawSean
51228aecd4 fix(sms): cover native proof follow-ups (#88601)
Remove the duplicate plain approve command from pairing replies so SMS/native pairing shows one copyable owner approval command in the fenced block.

Add regression coverage for the single approve-command occurrence, plus Twilio guarded-egress release coverage for non-2xx and malformed-success send responses.

Verification:
- pnpm exec oxfmt --check src/pairing/pairing-messages.ts src/pairing/pairing-messages.test.ts extensions/sms/src/twilio.test.ts
- node scripts/run-vitest.mjs src/pairing/pairing-messages.test.ts src/pairing/pairing-challenge.test.ts src/plugin-sdk/channel-pairing.test.ts
- node scripts/run-vitest.mjs extensions/sms/src/twilio.test.ts

Thanks @clawSean.
2026-05-31 16:41:24 +01:00
Peter Steinberger
63de51ab96 refactor(cron): clarify sqlite store internals 2026-05-31 16:38:49 +01:00
Sanjay Santhanam
e0e7bae612 fix(discord): handle PluralKit DM pairing ids
Fix Discord DM pairing for PluralKit senders by storing the pairing identity with the same `pk:<member-id>` form used at inbound lookup time. Also recognizes both canonical direct DM session keys and account-scoped direct DM session keys as DM approval sessions.

Focused proof: `node scripts/run-vitest.mjs extensions/discord/src/approval-native.test.ts extensions/discord/src/monitor/dm-command-auth.test.ts extensions/discord/src/monitor/dm-command-decision.test.ts extensions/discord/src/monitor/message-handler.preflight.test.ts` passed with 4 files and 82 tests.

Closes #86332

Co-authored-by: Sanjays2402 <51058514+Sanjays2402@users.noreply.github.com>
2026-05-31 16:35:48 +01:00
Peter Steinberger
b9dc3c3894 perf: trim tui startup and refresh work 2026-05-31 16:30:04 +01:00
Lawrence Tran
507c6fd5ca fix(slack): avoid forced threads for replyToMode off
Slack top-level channel mentions with replyToMode off now reply at the channel root instead of inheriting stale or auto-created thread targets.

Existing Slack thread replies and Slack assistant DM thread targets continue to preserve their thread target.

Thanks @lawrencetran.
2026-05-31 16:29:34 +01:00
Alexander Falk
e18099b8c3 fix(macos): prevent duplicate menu bar icons
Fix macOS menu bar status-item storms during rapid gateway connection churn by removing stale SwiftUI-vended status items before adopting replacements and debouncing transient control-channel states.

Surface: macOS menu bar app, `MenuBarExtra` status item ownership, `ControlChannel` UI-observed connection state.

Proof:
- `git diff --check origin/main...pr/82739`
- `swift test --package-path apps/macos --filter ControlChannelStateDebouncerTests`
- PR CI: preflight, security-fast, macos-node, macos-swift, dependency-guard, changed-path scan, real behavior proof, Socket checks

Co-authored-by: Alexander Falk <al@falk.us>
2026-05-31 16:18:37 +01:00
Vincent Koc
a52c4d101a perf(agents): avoid full setup registry for runtime aliases 2026-05-31 17:14:09 +02:00
Peter Steinberger
4ef141d525 fix(agents): prevent embedded runtime shadowing 2026-05-31 16:13:01 +01:00
Peter Steinberger
1955f42bfe fix(outbound): route source replies through configured channels 2026-05-31 16:12:52 +01:00
Peter Steinberger
cd3b467f3c refactor(cron): split tool and doctor repair helpers 2026-05-31 16:11:45 +01:00
Peter Steinberger
45ab822918 perf: reduce tui refresh work 2026-05-31 16:10:09 +01:00
Peter Steinberger
6b1b2ff20a feat: default exec shell snapshots 2026-05-31 16:09:43 +01:00
Peter Steinberger
89cdf164ca fix(ui): keep chat usable during session loading 2026-05-31 16:08:56 +01:00
Peter Steinberger
972d2b66d1 fix(cron): guard flat atMs canonicalization 2026-05-31 16:02:06 +01:00
Peter Steinberger
a84819a639 refactor(cron): keep runtime on canonical sqlite rows 2026-05-31 16:02:06 +01:00
Peter Steinberger
827ceb55d0 fix(codex): restore bounded recovery continuity
Restore bounded Codex native recovery continuity without replaying covered mirrored transcript history. Closes #88352. Closes #88354.
2026-05-31 15:55:32 +01:00
Peter Steinberger
7b78941ea5 refactor: clean up ACP package metadata and helpers (#88659)
* refactor: derive acp core package subpath maps

* refactor: split acp manager task and timeout helpers

* refactor: split acp translator presentation helpers

* fix: keep packaged acp core plugin aliases

* ci: split gateway control plane runtime shard
2026-05-31 15:53:14 +01:00
Chunyue Wang
a5d8f09fd4 fix(discord): ping mention-bearing final replies
Fixes #88360.

Route Discord live-preview final replies containing targeted user or role mentions through fresh message delivery instead of edit finalization, preserving mention alias rewriting and notification behavior. Plain, broadcast-only, and mixed targeted-plus-broadcast replies keep the existing preview edit path.

Proof: CI run 26708866609 green for relevant lanes; Real behavior proof run 26708866194 successful; local git diff --check and git merge-tree clean.
2026-05-31 15:52:59 +01:00
Peter Steinberger
8f941ea0ac fix(telegram): preserve usage footer for tool-only replies
Route implicit message_tool_only current-source sends through the internal source-reply sink for non-webchat transports, preserving the final reply payload path where usage decoration runs. Also keep reply payload metadata when appending usage text so transcript mirror text matches the delivered footer-bearing reply.

Recreated from PR #87425 because the fork branch is draft, dirty against main, and not maintainer-pushable.

Co-authored-by: Gio Della-Libera <giodl73@gmail.com>
2026-05-31 15:51:41 +01:00
Vincent Koc
b334e7ef29 fix(agents): avoid alias setup load for matching refs 2026-05-31 16:48:27 +02:00
Peter Steinberger
d5ac97652a chore(ui): translate thinking default label 2026-05-31 15:47:58 +01:00
Vincent Koc
4d135ae28b fix(agents): preserve runtime tools in lean mode (#88381)
fix(agents): preserve runtime tools in lean mode

Keep runtime-required tools, especially `message`, available when local-model lean filtering is enabled. This preserves `forceMessageTool`, `message_tool_only` source replies, explicit runtime allowlists, and schema projection without disabling lean filtering for ordinary denied tools.

Proof: focused Vitest passed 190 tests; `git diff --check origin/main...HEAD` passed; PR CI had no failing or pending checks.
2026-05-31 15:43:48 +01:00
xiaotian
f547ea7668 fix(messages): use best-effort for implicit tool-only source replies (#84232)
fix(messages): use best-effort for implicit tool-only source replies

Preserve durable required-send semantics for explicit non-current targets while allowing current-source `message_tool_only` replies to be delivered through best-effort outbound sends. This fixes Slack source replies that otherwise fail when the adapter has no `reconcileUnknownSend` hook.

Fixes #84078.
2026-05-31 15:41:30 +01:00
Peter Steinberger
66775c037e docs: raise bulk PR close threshold 2026-05-31 15:40:16 +01:00
Peter Steinberger
c389839d30 feat: add exec shell snapshot cache
Add an opt-in bash/zsh shell snapshot cache for host exec runs, consolidate shell helper ownership into src/agents/shell-utils.ts, document OPENCLAW_EXEC_SHELL_SNAPSHOT, and keep Windows config command execution on the bash resolver. Also removes a redundant Discord gateway close-code type branch that was blocking test type checks.
2026-05-31 15:39:53 +01:00
Peter Steinberger
50c651900e fix: use typed tui empty session defaults 2026-05-31 15:38:55 +01:00
Peter Steinberger
18dc6e5cd4 perf: speed up tui session refresh 2026-05-31 15:38:54 +01:00
Peter Steinberger
9a4b631a1d fix(ci): align agent thinking default surfaces 2026-05-31 15:38:32 +01:00
Peter Steinberger
832b6487e0 docs: require live batch issue verification 2026-05-31 15:37:36 +01:00
Peter Steinberger
d689893a6f ci(release): extend QA runtime parity timeout 2026-05-31 15:36:35 +01:00
Peter Steinberger
d1bec469af ci: stabilize Testbox changed checks 2026-05-31 15:34:23 +01:00
Peter Steinberger
7ca77124fe fix(agents): report stale session locks without cleanup
Report live-owned stale session locks as typed acquisition failures instead of auto-removing them, while preserving safe reclaim for dead/orphaned lock files. Propagate stale lock acquisition through embedded runner takeover handling, failover/cache/delivery classifiers, and QA retry detection.

Refs #87779
2026-05-31 15:28:54 +01:00
Peter Steinberger
fb7e21796d fix(gateway): reject stale lifecycle session updates
Fixes #88538. Carry the owning run sessionId through lifecycle events, skip stale persistence and sessions.changed projection when sessions.reset rotated the row, and register the persisted owning id across session-backed run paths. Also aligns per-agent subagent thinking typing with existing runtime/test usage.\n\nCo-authored-by: openperf <16864032@qq.com>
2026-05-31 15:27:01 +01:00
Peter Steinberger
88c99ddf5f docs(agents): require typed presentation actions 2026-05-31 15:19:45 +01:00
Peter Steinberger
1bfae9d458 fix(models): keep auth login out of main config
Store provider login profiles in auth-state, preserve configured auth order/profile constraints, and keep legacy credential/keyRef normalization durable. Fixes #88565.
2026-05-31 15:14:16 +01:00
Peter Steinberger
2b61d38a45 fix: guard stale lifecycle snapshots (#88583) 2026-05-31 15:08:36 +01:00
openperf
613f51a7aa fix(gateway): reject pre-reset run lifecycle events from clobbering rotated session
sessions.reset rotates a channel session to a fresh sessionId under the same
sessionKey, but an old in-flight run could still emit late start/end/error
lifecycle events. persistGatewaySessionLifecycleEvent resolved the row purely
by sessionKey, so those stale events overwrote the new row's status
(running/failed with hasActiveRun=false).

Stamp the owning run's sessionId onto lifecycle events in emitAgentEvent and
skip persistence when it differs from the current row's sessionId. The embedded
runner refreshes the run context's sessionId on every live-session rotation
(mid-run compaction), so a legitimately rotated run's terminal event still
matches the rotated row; only an external sessions.reset stays mismatched.
Matching and unknown-owner events are unaffected.

Fixes #88538
2026-05-31 15:08:36 +01:00
Peter Steinberger
ff22b1e9e6 fix: apply ACP spawn model defaults 2026-05-31 15:07:33 +01:00
Logan Ye
fdf6092494 fix(agents): accept disabled thinking params
Fixes #74374.

Normalizes params.thinking false, disabled, and none to the existing off state for agent and auto-reply model selection. Thanks @yelog.

Known proof gap: build-artifacts is failing in an unrelated plugin prerelease plan assertion that expects an old Docker stats helper string; targeted tests, diff check, autoreview, and all touched-path checks pass.
2026-05-31 15:07:18 +01:00
Jayesh Betala
f8f52592c5 fix(gateway): expose agent thinking defaults
Fixes #81760.

Exposes existing agent and model thinking defaults through agents.list, including protocol and Swift model support. Thanks @jbetala7.
2026-05-31 15:05:55 +01:00
Peter Steinberger
d99934aacd ci: use normal node_modules for Blacksmith Testbox 2026-05-31 15:04:49 +01:00
Steven
13d2800489 fix(agents): inherit subagent thinking defaults
Fixes #55790.

Adds tested subagent thinking precedence for explicit tool input, requester agent subagent defaults, global subagent defaults, and inherited caller thinking. Thanks @stevenepalmer.
2026-05-31 15:03:10 +01:00
Peter Steinberger
82a0ba8c4c fix(plugins): remove redundant proxy assertion 2026-05-31 15:02:44 +01:00
Peter Steinberger
4d69fc23d0 fix(codex): clear completed dynamic tool release blockers 2026-05-31 15:02:44 +01:00
Peter Steinberger
1e82263492 fix(codex): let async media coexist with terminal batches 2026-05-31 15:02:44 +01:00
Peter Steinberger
d99c824ac1 fix(plugins): delegate wrapped tool properties 2026-05-31 15:02:44 +01:00
Peter Steinberger
3ebbf9a0c1 fix(agents): keep async media starts nonterminal 2026-05-31 15:02:44 +01:00
Peter Steinberger
f62a22ce56 fix(plugins): preserve wrapped tool descriptors 2026-05-31 15:02:44 +01:00
Peter Steinberger
643633c1e5 fix(plugins): scope tool callbacks during materialization 2026-05-31 15:02:44 +01:00
Lellansin Huang
0dfcf73a57 fix(gateway): enforce OpenAI tool_choice contracts
Enforce OpenAI-compatible `tool_choice` contracts for Gateway HTTP Chat Completions and Responses client function tools.

- Add shared request normalization and post-run enforcement for required and pinned client function tool choices.
- Buffer streaming output until the tool-choice contract is satisfied, so failed runs do not leak partial assistant prose.
- Document the client-function-tool scope and add regression coverage for Chat/Responses success and failure cases.

Thanks @Lellansin for the contribution.

Proof: exact-head CI passed for `79fa0947360d307cf4ecffe713489cdf5db61093` in run `26714604449`; focused gateway tests passed locally.
2026-05-31 15:02:29 +01:00
Peter Steinberger
ec8cb8bcbf feat: add MCP code-mode namespace (#88636)
* feat: add MCP code-mode namespace

* fix: unblock mcp namespace ci gates
2026-05-31 15:02:19 +01:00
Andy Ye
44c65de17a fix(agents): avoid synthetic tool results during parallel races
Fixes the session transcript race where a newer assistant tool-call turn could force pending older tool calls to be written as synthetic missing-result entries while real parallel tool results were still in flight.

The guard no longer synthesizes at that racing boundary when synthetic repair is enabled, and transcript repair now moves late real results back beside their matching assistant tool-call turn before adding any placeholder. This keeps provider replay strict while preserving useful tool output.

Regression coverage: focused guard and transcript-repair tests for late parallel results.

Closes #88168.
Follow-up lock-lifetime report tracked in #88647.
Thanks @TurboTheTurtle for the fix and @jhartman00 for the report.

Co-authored-by: Andy Ye <35905412+TurboTheTurtle@users.noreply.github.com>
2026-05-31 15:00:44 +01:00
Vincent Koc
0833c68b1b fix(e2e): show plugins docker sweep progress 2026-05-31 15:57:19 +02:00
Peter Steinberger
f2ace9ff4e docs: require gh comment drafts 2026-05-31 09:56:56 -04:00
Peter Steinberger
036acbd358 docs: require codex source citations 2026-05-31 09:55:07 -04:00
Peter Steinberger
95890fe150 fix(agents): release session lock on manual abort
Release the embedded attempt session lock on manual aborts through the same best-effort abort cleanup path used by timeout aborts.

Proof: focused Vitest for abort/session-lock cleanup, `pnpm check:test-types`, oxfmt, `git diff --check`, branch autoreview, and full PR CI on 56fa5420d6.

Fixes #88600
2026-05-31 14:53:42 +01:00
Peter Steinberger
a7075f3634 docs: clarify autoreview refactor follow-up 2026-05-31 14:52:45 +01:00
Chunyue Wang
582fea942b fix(agents): scope timeout cooldowns by model
Fixes #87462.

Timeout transport failures now record cooldowns against the attempted model when available. Model-scoped cooldown bypasses continue to respect profile-wide blocked/disabled windows, and timeout expiry selection stays per profile while rate-limit expiry keeps shared reset aggregation.

Verification:
- pnpm exec oxfmt --check --threads=1 src/agents/auth-profiles/usage-state.ts src/agents/auth-profiles/usage.test.ts src/agents/auth-profiles.getsoonestcooldownexpiry.test.ts src/agents/auth-profiles.markauthprofilefailure.test.ts src/agents/embedded-agent-runner/run.ts
- pnpm check:test-types
- pnpm test src/agents/auth-profiles.getsoonestcooldownexpiry.test.ts src/agents/auth-profiles/usage.test.ts src/agents/auth-profiles.markauthprofilefailure.test.ts src/agents/embedded-agent-runner/run.incomplete-turn.test.ts
- autoreview clean
- GitHub Actions green on PR head d64e2a4d2f
2026-05-31 14:51:20 +01:00
Peter Steinberger
d927e73609 test(discord): drive application id retry timer 2026-05-31 14:50:08 +01:00
Peter Steinberger
b36ed41559 docs: strengthen review dependency inspection rules 2026-05-31 09:49:03 -04:00
Peter Steinberger
7dea283756 refactor: expand acp core package (#88618)
* refactor: expand acp core package

* chore: drop acp core package symlink

* fix: keep acp core dependency graph stable

* fix: add acp core tsconfig subpaths

* fix: sync acp core boundary path artifacts

* fix: use kysely for cron run-log queries

* fix: resolve acp core subpaths in loaders
2026-05-31 14:48:57 +01:00
Vincent Koc
cc290050b4 fix(doctor): diagnose malformed provider catalogs
Move malformed static provider catalog diagnostics into `openclaw doctor` instead of adding fallback behavior to runtime projection.

Doctor now validates full provider registrations for malformed static catalog hooks, result containers, provider keys, model arrays, model iteration, model ids/names, invalid catalog order, and proxy/access errors. Runtime unified text provider catalog projection remains strict on the typed provider catalog contract.

Verification:
- `node scripts/run-vitest.mjs src/flows/doctor-core-checks.runtime.test.ts src/flows/doctor-core-checks.test.ts src/flows/doctor-health-contributions.test.ts src/flows/doctor-health-conversion-plan.test.ts src/plugin-sdk/provider-entry.test.ts`
- `node_modules/.bin/oxfmt --check src/plugins/provider-catalog-unified-text.ts src/flows/doctor-core-checks.ts src/flows/doctor-core-checks.test.ts src/flows/doctor-core-checks.runtime.ts src/flows/doctor-core-checks.runtime.test.ts src/flows/doctor-health-contributions.ts src/flows/doctor-health-contributions.test.ts src/flows/doctor-health-conversion-plan.ts src/flows/doctor-health-conversion-plan.test.ts`
- `node scripts/run-oxlint.mjs src/flows/doctor-core-checks.runtime.ts src/flows/doctor-core-checks.runtime.test.ts src/plugins/provider-catalog-unified-text.ts`
- `pnpm tsgo:test`
- `git diff --check origin/main...HEAD`
- `.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main --prompt-file /tmp/provider-catalog-doctor-review-context.txt`
- GitHub PR checks green on head `876fdda5a352b0f15bfbe2abe9be43ebada7c596`

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-05-31 14:48:15 +01:00
Andy Ye
826b378452 fix(agents): normalize prefixed Anthropic model ids (#88587) 2026-05-31 14:47:40 +01:00
Peter Steinberger
0d17623f00 chore: bump OpenClaw version to 2026.5.31
Bumps OpenClaw release metadata to 2026.5.31 across package manifests, app version files, plugin metadata, changelog headings, and generated shrinkwraps.

Verification:
- pnpm plugins:sync:check
- pnpm ios:version:check
- pnpm deps:shrinkwrap:check
- git diff --check
- stale 2026.5.30/build-code scan across changed files
- autoreview clean: no accepted/actionable findings
- PR CI green for real gates: Checks, security scans, dependency guard, app lanes, real behavior proof

Known non-code workflow issue:
- label workflow failed because this PR hits GitHub's 100-label issue cap before the size-label step.
2026-05-31 14:46:17 +01:00
Soham Patankar
400be62f76 feat(codex): add portable Codex command pickers (#82224)
Refactor Codex slash-command pickers so the Codex plugin owns the native command tree and returns portable presentation buttons for channels to render. Telegram now maps portable slash-command buttons to `tgcmd:` native callbacks while preserving approval callback shortening/bypass behavior, and the old Telegram-specific Codex callback menu path is gone.

Verification:
- `node scripts/run-vitest.mjs extensions/codex/src/command-plugins-management.test.ts extensions/codex/src/commands.test.ts extensions/telegram/src/button-types.test.ts`
- `node scripts/run-vitest.mjs extensions/telegram/src/bot.test.ts extensions/telegram/src/button-types.test.ts extensions/telegram/src/bot-native-commands.test.ts extensions/telegram/src/shared.test.ts`
- `node scripts/run-vitest.mjs run --config test/vitest/vitest.media-understanding.config.ts --reporter=verbose`
- `pnpm check:test-types`
- `pnpm tsgo:prod`
- `pnpm lint --threads=8`
- `git diff --check`
- `.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main`
- CI `26714121462`

Co-authored-by: Soham Patankar <102520430+yaanfpv@users.noreply.github.com>
2026-05-31 14:45:10 +01:00
Nao
5a0e67791f fix(tui): preserve pending local runs during session sync (#87959)
* fix(tui): preserve pending local runs during session sync

* fix(tui): guard optimistic run ownership

* fix(tui): consume early accepted run finals

* fix(tui): preserve deferred pending history reloads

---------

Co-authored-by: nao860226-rgb <nao860226-rgb@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-05-31 14:39:24 +01:00
Peter Steinberger
85beee613c docs: clarify inline code comments
Comment-only follow-up documenting reusable gateway, auth, proxy, device, Talk, session, and agent helper contracts.\n\nVerification: git diff --check plus targeted tests recorded in PR body.
2026-05-31 14:37:41 +01:00
yaoyi1222
75e0053cf9 fix(auto-reply): warn on substantive private message-tool finals
Warn operators when message_tool_only produces unusually substantive private final text without a delivered source reply. Keeps short/NO_REPLY silence quiet, avoids logging response bodies, and distinguishes unrelated side effects from source-reply delivery.
2026-05-31 14:35:58 +01:00
Sebastien Tardif
81b9da0bb0 fix(tui): use middle truncation for paths and commands in tool display (#88050)
* fix(tui): use middle truncation for paths and commands in tool display

Closes #87936

* fix(test): update channel-streaming test for middle truncation output

Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>

* chore: retrigger CI (vitest env teardown flake)

Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>

* fix(tui): redact tool details before middle truncation

Apply redactToolDetail() to command and generic string text before
middle truncation so credential-like suffixes are masked while full
flag/key context is still available. Previously, truncation could
remove the --flag prefix while preserving the raw secret at the tail,
causing redaction patterns to miss the value.

Add regression tests for sk- prefixed tokens in commands and ghp_
tokens in generic string details.

Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>

---------

Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
2026-05-31 14:35:55 +01:00
Mukunda Rao Katta
e452d16cea fix(webchat): suppress stale active session rows (#87962) 2026-05-31 14:35:50 +01:00
Sebastien Tardif
9a1b95c1e6 fix(tui): skip history reload when final event has displayable output (#88004)
* fix(tui): skip history reload when final event has displayable output

On external/gateway runs, handleChatEvent fires void loadHistory() on
every final event. loadHistory() does clearAll() + rebuild from server
data, but the server may not have persisted the just-finished message
yet, causing the rendered final message to vanish.

Add a hasDisplayableFinal option to maybeRefreshHistoryForRun that skips
the destructive reload when the final text is already rendered locally.
This mirrors the existing local-run guard. Compute finalText before the
reload decision so the guard has the information it needs.

Closes #87922

Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>

* retrigger proof check

Signed-off-by: Seb Tardif <sebtardif@ncf.ca>

---------

Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
Signed-off-by: Seb Tardif <sebtardif@ncf.ca>
2026-05-31 14:35:44 +01:00
Peter Steinberger
5dc4531fdf test(discord): isolate timer-sensitive request tests 2026-05-31 14:31:10 +01:00
Vincent Koc
9518d1f27c fix(auth): coerce persisted device auth tokens 2026-05-31 15:22:44 +02:00
Vincent Koc
fbde572491 fix(e2e): heartbeat resource-sampled docker lanes 2026-05-31 15:22:44 +02:00
Peter Steinberger
f24a138790 refactor: unify subagent handoffs into agent steering queue
Refactor the subagent completion handoff path into the generic agent steering queue, preserving legacy persisted handoff lease fields by normalizing them into steering lease fields on restore.

Also allowlists the split cron run-log SQLite boundary in the Kysely guardrail after rebasing onto current main.

Refs #88407.
2026-05-31 14:21:20 +01:00
Chunyue Wang
02c7b5b82f fix(tasks): reclaim ACP zombie runs blocking gateway restart (#88281)
* fix(tasks): reclaim ACP zombie runs blocking gateway restart (#88205)

hasBackingSession treated an ACP task as backed whenever its persisted
session-store entry existed, so a crashed mid-turn ACP run left a
status=running record that survived the crash and wedged gateway
restart/update forever.

Gate ACP backing on in-process live-turn liveness instead of entry
existence, behind the existing authoritative-process flag (generalized
from cron-only) so a standalone maintenance CLI with an empty live-turn
map stays conservative and never reclaims. The liveness signal lives in a
core-internal active-turns registry (mirroring cron active-jobs) so it
stays off the SDK-exported AcpSessionManager surface. It is marked once
before the backend loop and cleared when the task is marked terminal, so
a slow init or backend failover cleanup cannot let the sweep reclaim a
still-live turn.

* fix(tasks): preserve cron operator JSON diagnostic reason

Split the merged runtime_not_authoritative reason back into the existing cron_runtime_not_authoritative (shipped, consumed by openclaw tasks maintenance --json operator scripts) and a new acp_runtime_not_authoritative for the ACP branch. Strengthen the cron non-authoritative test to lock the reason string contract.

* fix(tasks): clear ACP turn liveness on retry failures

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-31 14:19:56 +01:00
Peter Steinberger
100dd79468 test(release): wait for bundled runtime commands 2026-05-31 14:09:27 +01:00
Chunyue Wang
318cae1500 fix(hooks): isolate slug-generator auth failures
Summary:
- route slug-generator embedded runs through lane-local auth profile failure handling
- add regression coverage for the run option
- repair current landing checks for media auth mocks, device auth parsing, transcript sanitizer harness typing, and lint

Verification:
- node scripts/run-vitest.mjs src/hooks/llm-slug-generator.test.ts src/agents/embedded-agent-runner/run/auth-profile-failure-policy.test.ts
- node scripts/run-vitest.mjs run --config test/vitest/vitest.media-understanding.config.ts --reporter=verbose
- pnpm check:test-types
- pnpm lint --threads=8
- git diff --check
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main

Fixes #71709.
Co-authored-by: openperf <16864032@qq.com>
2026-05-31 14:09:03 +01:00
Peter Steinberger
17c8602a9c docs: require issue summaries in agent replies 2026-05-31 14:07:08 +01:00
Peter Steinberger
3ca4e5f616 docs: clarify agent workflow rules 2026-05-31 14:06:22 +01:00
Peter Steinberger
7423e9cb66 refactor(openai): confine legacy codex repair to doctor
Confine retired OpenAI Codex identifiers to doctor repair and migration paths while keeping runtime OpenAI surfaces canonical.\n\nProof: focused Vitest; autoreview clean; AWS Crabbox check:changed run_3789cbe12413 (cbx_2c88b700810b) passed.
2026-05-31 14:03:17 +01:00
tynamite
2f7e6ec196 fix(auto-reply): honor per-model thinking params
Auto-reply now uses the existing per-model model params thinking value before falling back to the global thinkingDefault, matching gateway/shared model selection behavior.\n\nVerified with targeted auto-reply and agents Vitest coverage plus formatting and diff checks.\n\nThanks @tynamite for the fix.
2026-05-31 14:01:25 +01:00
Peter Steinberger
b222b5f6fa refactor(cron): keep legacy notify migration in doctor 2026-05-31 14:00:47 +01:00
Peter Steinberger
2fe019ccae fix(exec): allow predicate shell builtins in allowlist mode 2026-05-31 14:00:12 +01:00
Peter Steinberger
657a668d94 test(voice-call): drive Twilio stream failure timers 2026-05-31 13:59:48 +01:00
Peter Steinberger
c797f02ff7 fix(diagnostics): surface Bonjour state in support exports 2026-05-31 13:57:17 +01:00
Peter Steinberger
32c0279cec perf(cli): narrow gateway dispatch startup 2026-05-31 13:56:27 +01:00
Peter Steinberger
44512b5297 docs: tighten refactor storage policy 2026-05-31 13:51:43 +01:00
Peter Steinberger
f1fc204f5c docs: require PR review transparency 2026-05-31 08:50:47 -04:00
Peter Steinberger
c8f7e9102b docs: clarify runtime migration boundary 2026-05-31 13:42:59 +01:00
Peter Steinberger
cf315ddef6 fix(agents): preserve reasoning replay from model metadata
Preserve OpenAI-compatible replay reasoning when the selected custom or self-hosted model already has reasoning metadata enabled.

The transcript policy now treats existing model metadata as the replay contract instead of requiring a new provider config knob, and the OpenAI-compatible serializer preserves reasoning_content for those routes while keeping stock OpenAI, Gemma 4, and known non-replayable OpenRouter safeguards.

Fixes #88068.
Replaces #88071.
2026-05-31 13:41:44 +01:00
Peter Steinberger
7a22515972 test(release): harden beta validation gates 2026-05-31 13:39:48 +01:00
kinjitakabe
fee4e52f22 fix(exec): allow known safe shell builtins in allowlist mode
Treat pathless POSIX shell builtins (`:`, `cd`, `false`, `pwd`, `true`) as internally safe only during shell allowlist evaluation. This avoids approval prompts for chains like `cd /tmp && git status` when the executable segment is already allowlisted, without adding a `tools.exec.safeBuiltins` config knob.

Environment-mutating builtins (`export`, `unset`), code-evaluating builtins (`eval`, `source`, `.`), unknown commands, and direct argv execution remain approval-gated unless separately allowlisted.

Proof: `pnpm test src/infra/exec-safe-builtins.test.ts src/agents/bash-tools.exec.security-floor.test.ts -- --reporter=verbose`; `pnpm changed:lanes --json`; `pnpm check:no-conflict-markers`; `git diff --check origin/main...HEAD`. CI related failures were resolved on the final SHA; remaining `checks-node-core-runtime-media-ui` failure is unrelated to this PR.

Fixes #46056.
Thanks @kinjitakabe.

Co-authored-by: kevinkang-ai <273844887+kevinkang-ai@users.noreply.github.com>
2026-05-31 13:39:13 +01:00
Peter Steinberger
ca166a85d4 docs: explain per-agent model params 2026-05-31 13:38:17 +01:00
Peter Steinberger
e5c61383e5 refactor: move plugin state stores to sqlite (#88609) 2026-05-31 13:37:11 +01:00
Peter Steinberger
fd88f34a8f fix: preserve discord policy close narrowing 2026-05-31 13:28:53 +01:00
Peter Steinberger
1e54e908e2 fix: queue subagent completion handoffs (#88613) 2026-05-31 13:25:23 +01:00
Peter Steinberger
729712d194 docs(codex): clarify first-party plugin marketplaces 2026-05-31 13:22:00 +01:00
Peter Steinberger
97a97aded7 docs: tighten env surface policy 2026-05-31 13:21:12 +01:00
Peter Steinberger
2e254005a0 docs: tighten config surface policy 2026-05-31 13:14:53 +01:00
Peter Steinberger
703fae16a9 fix(devices): refresh paired device last-seen metadata
Refresh paired-device last-seen metadata on successful device-token auth, paired reconnect, and first silent auto-approved connect.

Centralize approved paired-device record construction so normal and bootstrap approvals preserve existing last-seen state unless the gateway passes explicit access metadata.

Fixes #81169.
Supersedes #81189.

Proof:
- node scripts/run-vitest.mjs src/infra/device-pairing.test.ts --reporter=verbose
- node scripts/run-vitest.mjs src/gateway/server.auth.control-ui.test.ts --reporter=verbose
- git diff --check
- pnpm exec oxfmt --check --threads=1 src/infra/device-pairing.ts src/infra/device-pairing.test.ts src/gateway/server/ws-connection/message-handler.ts src/gateway/server.auth.control-ui.suite.ts
- pnpm check:changed passed before final rebase; post-rebase rerun blocked before checks by local Crabbox 0.21.0 needing >=0.22.0
- autoreview clean: .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main

Known unrelated CI failure on latest origin/main/PR base: extensions/discord/src/monitor/gateway-plugin.ts TS2367 in check-prod-types/check-lint/check-test-types/extension-channel checks.

Co-authored-by: vyctorbrzezowski <krzyszchweski@gmail.com>
2026-05-31 13:12:55 +01:00
clawsweeper[bot]
fdf8dddf0a fix(agents): classify expired thinking signatures (#88340)
Summary:
- The branch adds thinking-signature replay-invalid classification, retries matching terminal stream-error eve ... output, preserves static fallback model params, and updates related tests including a Copilot hook fixture.
- PR surface: Source +57, Tests +177. Total +234 across 6 files.
- Reproducibility: yes. for the classifier boundary: current main lacks a thinking-signature replay-invalid ma ... ort supplies the exact provider error payload. The time-dependent live expiry path was not reproduced here.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(agents): classify expired thinking signatures
- PR branch already contained follow-up commit before automerge: fix(agents): recover thinking signature stream errors
- PR branch already contained follow-up commit before automerge: fix(agents): recover expired thinking signatures
- PR branch already contained follow-up commit before automerge: fix(clawsweeper): address review for automerge-openclaw-openclaw-8807…

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

Prepared head SHA: b65f2b8bda
Review: https://github.com/openclaw/openclaw/pull/88340#issuecomment-4582955790

Co-authored-by: Bryan Tegomoh <bryan.tegomoh@gmail.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-05-31 12:11:30 +00:00
FMLS
3a88142ddd fix(browser): document stable tab references (#88393)
Summary:
- The branch documents friendly browser tab references across docs, the browser skill, CLI help, and tool schema descriptions, and adds tests for target reference resolution and tab alias behavior.
- PR surface: Source +24, Tests +328, Docs +9. Total +361 across 21 files.
- Reproducibility: yes. for the documentation mismatch by source inspection: current main supports friendly ta ... schema/help surfaces still emphasize raw CDP target ids. Runtime behavior itself is not a new failing path.

Automerge notes:
- PR branch already contained follow-up commit before automerge: refactor(browser): share tab reference CLI help

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

Prepared head SHA: 118af80b0b
Review: https://github.com/openclaw/openclaw/pull/88393#issuecomment-4583558133

Co-authored-by: FMLS <kfliuyang@gmail.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: hxy91819
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
2026-05-31 12:09:50 +00:00
Peter Steinberger
94b1427fdf fix(discord): log gateway websocket close details 2026-05-31 13:03:23 +01:00
Peter Steinberger
f83886c12d chore(lint): trim remaining suppressions 2026-05-31 13:01:19 +01:00
Peter Steinberger
63c6252389 test(release): stabilize beta validation after rebase 2026-05-31 13:00:09 +01:00
Ayaan Zaidi
4de9b79d30 refactor(agents): simplify stale cli retry cleanup 2026-05-31 17:28:05 +05:30
brokemac79
afe9826fc1 Stabilize lint suppression guard in CI 2026-05-31 17:28:05 +05:30
brokemac79
0b02148656 Fix stale CLI retry CI contracts 2026-05-31 17:28:05 +05:30
brokemac79
e8c7c933f8 Retry stale CLI sessions in runner lifecycle 2026-05-31 17:28:05 +05:30
Peter Steinberger
00d17e9df7 refactor: make OpenAI Codex legacy doctor-only (#88605) 2026-05-31 12:58:01 +01:00
Vincent Koc
5976f14832 docs(skills): full rewrite of skills section with Mintlify components
Rewrites all skills documentation pages with rich Mintlify components
(Steps, CardGroup, AccordionGroup, ParamField, Note, Warning, Tip) and
code-verified accuracy throughout.

- tools/skills.md: CardGroup quick-nav, verified precedence table from
  workspace.ts, Security accordions, Steps for env injection, token
  impact formula, Related CardGroup
- tools/creating-skills.md: Steps walkthrough, gating accordion,
  propose-update command (was missing), Best practices Tip, ClawHub
  publish flow, Related CardGroup
- tools/skills-config.md: ParamField for every config key, agent
  allowlist section, Workshop config, sandbox Warning
- tools/slash-commands.md: CardGroup for 3 command types, command tables
  in AccordionGroup sections, ParamFields for all config keys, dedicated
  sections for /tools /model /config /mcp /debug /plugins /trace /btw
- prose.md: Steps for install, CardGroup quick-nav, AccordionGroup for
  state backends, runtime mapping table

docs.json: adds skill-workshop nav entry and redirects
(/skill-workshop, /tools/skills-workshop -> /tools/skill-workshop)
2026-05-31 12:57:16 +01:00
Peter Steinberger
242eab9d20 fix(media): use typed auth for no-auth media providers 2026-05-31 12:56:38 +01:00
WhatsSkiLL
f59113cfd3 fix(gateway): avoid restarts for auth cooldown reloads
Fixes #88443.

Cooldown-only edits under auth.cooldowns now hot reload the active runtime config instead of scheduling a gateway restart. This avoids dropping active gateway work while preserving restart-required behavior for gateway.auth.* credential changes.

Verification:
- pnpm test src/gateway/config-reload.test.ts -- --reporter=verbose
- env -u OPENCLAW_TESTBOX pnpm check:changed
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main --prompt 'Review PR 88474 after rebase. Focus on whether auth.cooldowns hot reload correctly refreshes active runtime config without weakening gateway auth/token restart behavior. Treat no-op vs hot reload semantics as central.'
- GitHub CI, Real behavior proof, CodeQL, Dependency Guard, OpenGrep PR Diff, and Workflow Sanity passed on 51232ff66c.

Thanks @IWhatsskill.
2026-05-31 12:54:19 +01:00
Peter Steinberger
fde87f475f perf(cli): defer shell env for gateway dispatch 2026-05-31 12:42:35 +01:00
Vincent Koc
823c38a1f9 fix(e2e): keep plugin binding escape smoke focused 2026-05-31 13:37:41 +02:00
Sally O'Malley
1cb5a57631 fix: transient banner showing lastError leak into page headers (#88463)
Signed-off-by: sallyom <somalley@redhat.com>
2026-05-31 07:33:58 -04:00
Sally O'Malley
615f71a88f fix(gateway): guide dashboard auth after service repair (#88466)
Signed-off-by: sallyom <somalley@redhat.com>
2026-05-31 07:31:44 -04:00
Peter Steinberger
899dc5f248 fix(memory): retry transient embedding failures
Retry live query embeddings on transient provider transport failures and split eligible batch embedding socket failures after bounded retries.

Fixes #71784
Fixes #44166
Supersedes #44167

Co-authored-by: MrGeDiao <MrGeDiao@users.noreply.github.com>
2026-05-31 12:30:26 +01:00
stain lu
95b2f9c6f9 fix(boot): suppress fallback BOOT.md echoes
Suppress BOOT.md/internal-runtime-context echoes in fallback boot sends.

Wrap boot prompts as internal runtime context, track the active boot prompt during boot runs, and sanitize message-tool visible payloads before dispatch so fallback models cannot deliver copied BOOT.md instructions or leak them through raw-params errors. Preserves media/presentation sends that still contain non-text payload content after sanitization.

Fixes #53732.

Co-authored-by: stainlu <stainlu@newtype-ai.org>
2026-05-31 12:25:41 +01:00
sqsge
a76db8cff3 fix(media): allow explicit synthetic auth for media providers
Allow media understanding providers to opt into synthetic non-secret auth for local or self-hosted no-auth audio/video execution.

This preserves configured env/profile/literal provider credentials first, keeps explicit profile failures hard-fail, and leaves unmarked remote providers fail-closed.

Fixes #74644.
2026-05-31 12:20:50 +01:00
Peter Steinberger
9f5c981f9f perf: speed up chat hydration and add 3d workboard 2026-05-31 12:18:08 +01:00
Peter Steinberger
2bd07eead7 Refactor cron SQLite runtime paths (#88582)
* refactor: clean cron sqlite runtime paths

* fix: preserve legacy cron sqlite delivery migration

* fix: keep legacy cron notify fallback for invalid webhooks

* test: handle packaged lint suppression files

* fix: keep invalid cron notify migrations retryable

* test: fix ui timer lint
2026-05-31 12:14:48 +01:00
Peter Steinberger
3525a965ed test(release): stabilize beta validation lanes 2026-05-31 12:09:49 +01:00
WhatsSkiLL
22b8e1cf4f fix(plugins): scope startup metadata manifest reads
Limit plugin metadata snapshots to the channel, provider, and startup surfaces that need them, while preserving unscoped fallback for incomplete index data and provider runtime resolution.

Refs #70533.
Refs #84628.

Co-authored-by: IWhatsskill <IWhatsskill@users.noreply.github.com>
2026-05-31 11:58:56 +01:00
Peter Steinberger
1e08af453a fix(sms): add Twilio webhook diagnostics
* fix(sms): diagnose Twilio webhook setup

* test(sms): satisfy diagnostic lint gates

* fix(sms): redact recent probe participants

* docs(sms): refresh SecretRef credential matrix

* fix(sms): probe Messaging Service webhooks

* fix(sms): resolve env-backed SecretRefs
2026-05-31 11:44:39 +01:00
Vincent Koc
6d76acc258 fix(test): repair e2e standalone regressions 2026-05-31 12:42:17 +02:00
kinjitakabe
f7a1d3f3f6 fix(model-auth): resolve per-entry apiKey profile references
Fixes #67423.

Resolve provider-entry apiKey fields that intentionally reference model auth profiles through centralized binding logic, so runtime auth and status labeling agree. Preserve env-first precedence, SecretRef handling, provider/baseUrl compatibility checks, and model auth-mode guards.

Verification:
- node scripts/run-vitest.mjs src/agents/model-auth.profiles.test.ts src/agents/model-auth-label.test.ts
- PATH=/tmp/openclaw-corepack-shim.XXXXXX:$PATH CI=true pnpm check:changed
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
- GitHub CI run 26710260760 and related CodeQL/proof checks on f55dec154d

Co-authored-by: kinjitakabe <273844887+kinjitakabe@users.noreply.github.com>
2026-05-31 11:39:55 +01:00
Peter Steinberger
7d8fdef995 ci(release): run npm preflight on larger runner 2026-05-31 11:37:04 +01:00
Peter Steinberger
9dc4c9ec2e fix: expose Feishu tools for named accounts 2026-05-31 11:36:48 +01:00
Peter Steinberger
77f1359612 refactor: extract media and ACP core packages (#88534)
* refactor: extract media and acp core packages

* refactor: remove relocated media and acp sources

* build: wire new core packages into dependency checks

* test: alias new core packages in vitest

* build: keep media sniffer runtime dependency

* docs: refresh plugin sdk api baseline

* fix: keep normalized proposal queries non-empty

* test: keep channel timer tests isolated

* fix: keep rebased plugin checks green

* fix: preserve sms numeric allowlist entries

* test: harden exec foreground timeout failure

* test: remove duplicate skill workshop assertion

* fix: remove channel config lint suppression

* test: refresh lint suppression allowlist
2026-05-31 11:30:33 +01:00
stain lu
4b1e5b7943 fix(cli): stabilize claude auth epochs on token rotation
Stabilizes Claude CLI reusable sessions when Claude token rotation causes transient token-shaped credential reads. Local Claude CLI OAuth and token credential encodings now share the same identity-only auth-epoch, while ref-backed token auth profiles ignore refreshed token material and plaintext token profiles remain epoch-sensitive on manual token replacement.

Fixes #74312.

Proof: focused local Vitest, autoreview, Testbox-through-Crabbox tbx_01ksyrcknbt743x32x6k1s95qw, and GitHub CI run 26709864094 all passed.

Co-authored-by: stainlu <stainlu@newtype-ai.org>
2026-05-31 11:19:42 +01:00
Ted Li
92b6af76d9 fix(reply): deliver plugin binding replies
Deliver plugin-owned bound-thread replies even when the source room is configured for `message_tool` visible replies. Normal agent final text still stays private unless the agent calls `message(action=send)`.

Document the distinction in the group/channel docs and root routing policy, and keep ambient room-event plus unauthorized text-slash suppression covered by regression tests.

Fixes #87721.
2026-05-31 11:17:45 +01:00
Peter Steinberger
53a9f13cf4 chore(lint): reduce lint suppressions 2026-05-31 11:17:16 +01:00
Firas Alswihry
b2f71db7bb feat(dreaming): add report-only shadow trial runner
Adds a report-only memory-core dreaming shadow-trial runner that writes inspectable artifacts without mutating durable memory. The public helper now stores default reports under daily directories with opaque content-hash filenames, so multiple same-day trials coexist without leaking candidate text into paths.

Verification:
- OPENCLAW_VITEST_MAX_WORKERS=1 node scripts/run-vitest.mjs run --config test/vitest/vitest.extension-memory.config.ts extensions/memory-core/src/dreaming-shadow-trial.test.ts --reporter=verbose --maxWorkers=1
- git diff --check
- pnpm exec oxfmt --check extensions/memory-core/src/dreaming-shadow-trial.ts extensions/memory-core/src/dreaming-shadow-trial.test.ts
- pnpm tsgo:extensions
- autoreview clean: no accepted/actionable findings
- GitHub CI run 26709794635 passed
- Real behavior proof run 26709798698 passed
- Dependency Guard run 26709794113 passed

Co-authored-by: Firas Alswihry <itzfiras@gmail.com>
2026-05-31 11:16:33 +01:00
Peter Steinberger
6fb1f386c6 perf(cli): slim agent command registration 2026-05-31 11:14:26 +01:00
Peter Steinberger
ae4ab2a41f refactor(logging): share stuck recovery session refs 2026-05-31 11:10:06 +01:00
Soham Patankar
4f3d8a57dd fix(codex): accept first-party OpenAI plugin marketplaces
Allow Codex native plugin config to target first-party OpenAI marketplaces, including openai-curated, openai-bundled, and openai-primary-runtime.

Fixes #82216.
Thanks @yaanfpv for the contribution.

Verification:
- node scripts/run-vitest.mjs test/scripts/lint-suppressions.test.ts
- pnpm build:ci-artifacts
- OPENCLAW_VITEST_MAX_WORKERS=2 node scripts/run-vitest.mjs run --config test/vitest/vitest.full-core-support-boundary.config.ts test/scripts/lint-suppressions.test.ts
- node scripts/run-vitest.mjs extensions/codex/src/app-server/config.test.ts extensions/codex/src/app-server/plugin-activation.test.ts extensions/codex/src/app-server/session-binding.test.ts extensions/codex/src/migration/provider.test.ts extensions/sms/src/channel.test.ts extensions/sms/src/inbound.test.ts
- git diff --check
- ./.agents/skills/autoreview/scripts/autoreview --mode local
- GitHub PR CI on head 896640060b, including build-artifacts run 26709647050
2026-05-31 11:08:42 +01:00
Ayaan Zaidi
f454d6202f fix(agents): preserve explicit active run aborts 2026-05-31 15:31:48 +05:30
Ayaan Zaidi
1556e3c68c fix(agents): surface internal abort incomplete turns 2026-05-31 15:31:48 +05:30
Ayaan Zaidi
a4d3add6da fix(agents): classify internal aborts as non-deliverable 2026-05-31 15:31:48 +05:30
Feelw00
b4cdc33fc9 fix(logging): align diagnostic recovery dedup keys
Align diagnostic stuck-session recovery in-flight dedup with the runtime recovery key. The coordinator now dedups by logical session ref only, so a mid-flight generation bump cannot emit a phantom `session.recovery.requested` event that runtime recovery skips as already in flight.

Adds a regression test for the idle-queued stall path where a queued message bumps generation while recovery is pending.

Fixes #88010
2026-05-31 11:00:42 +01:00
Chinar Amrutkar
c2c20a0b0d fix(ui): pair sequential tool results by fallback order
Fixes #70746 by pairing nameless same-name tool results with the earliest unmatched Control UI tool card while preserving exact ID matches. Empty fallback results now count as consumed, so later results do not overwrite the first card.

Focused regression coverage covers sequential same-name calls and empty-result fallback pairing. Thanks @chinar-amrutkar.

Co-authored-by: Chinar Amrutkar <chinar.amrutkar@gmail.com>
2026-05-31 11:00:00 +01:00
Vincent Koc
a753e6bc86 fix(test): extend e2e vitest watchdog 2026-05-31 11:50:18 +02:00
tanshanshan
425a4ab2f2 chore(lint): enable object-shorthand (#81808)
* fix: narrow current-main core type guards

* fix: preserve query and test guard narrowing

* fix(copilot): align client options with sdk rename

* test(sms): type fetch mocks

* fix(sms): preserve numeric allowlist entries

* test(sms): preserve pairing send count assertion

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-31 10:46:10 +01:00
Peter Steinberger
724160b7eb docs: clarify package guard policy 2026-05-31 10:45:28 +01:00
Peter Steinberger
6699e7331a docs: document scoped mention patterns
## Summary

- Document scoped configured mention-pattern policy on the Groups page, including allow/deny mode semantics, supported conversation IDs, account-level precedence, and native-mention behavior.
- Add config UI help for `mentionPatterns.mode`, `allowIn`, and `denyIn` on Discord, Matrix, Slack, Telegram, and WhatsApp.
- Regenerate channel config/docs/plugin SDK metadata baselines for the new hint copy.

Refs #70864.

## Verification

- git diff --check
- pnpm format:docs:check
- pnpm docs:check-mdx
- pnpm docs:check-links
- pnpm config:channels:check
- pnpm config:docs:check
- pnpm plugin-sdk:api:check
- node scripts/run-vitest.mjs src/config/schema.hints.test.ts
- .agents/skills/autoreview/scripts/autoreview --mode local

## Real behavior proof

Behavior addressed: Documentation and config UI metadata for scoped configured mention-pattern policy.
Real environment tested: Local OpenClaw checkout on macOS.
Exact steps or command run after this patch: The verification commands listed above.
Evidence after fix: Docs formatting, MDX, link audit, generated config/channel/API baselines, and config hint tests passed; autoreview reported no accepted/actionable findings.
Observed result after fix: The Groups page now explains how to scope `messages.groupChat.mentionPatterns` with `channels.<channel>.mentionPatterns`, and config metadata exposes field help for the supported channels.
What was not tested: Live Discord, Matrix, Slack, Telegram, or WhatsApp inbound messages; this PR is documentation/config metadata only and follows the already-landed runtime behavior from #70864.
2026-05-31 10:44:20 +01:00
Vincent Koc
b0625bdd1c fix(agents): strip malformed arg-value suffixes
Strip malformed terminal `</arg_value>>` suffixes from selected agent read/path and exec routing arguments before validation.

This keeps valid literal `</arg_value>` text intact, preserves payload fields such as write content and edit replacements, and prevents read/exec failures caused by malformed tool XML suffixes.

Fixes #48780.
Thanks @vincentkoc for the original fix.

Verification:
- `node scripts/run-vitest.mjs src/agents/agent-tools.params.test.ts src/agents/agent-tools.read.arg-value-suffix.test.ts src/agents/agent-tools.read.workspace-root-guard.test.ts src/agents/agent-tools.workspace-only-false.test.ts src/agents/bash-tools.exec.path.test.ts src/agents/bash-tools.exec-foreground-failures.test.ts`
- `node_modules/.bin/oxfmt --check src/agents/agent-tools.params.ts src/agents/agent-tools.params.test.ts src/agents/bash-tools.exec.path.test.ts`
- `node scripts/run-oxlint.mjs src/agents/agent-tools.params.ts src/agents/agent-tools.params.test.ts src/agents/bash-tools.exec.path.test.ts`
- `pnpm check:test-types`
- `.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main`
- GitHub Actions green on PR head `f1d8026352`.

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-05-31 10:44:12 +01:00
stain lu
4ca22b95bc test(plugins): cover Link agent wallet bundle shape (#75181)
* test(plugins): cover Link agent wallet bundle shape

* test(plugins): add bundle fixture helpers

* test(plugins): align Link manifest fixture expectation

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-31 10:43:12 +01:00
Peter Steinberger
3950605561 chore(lint): tighten lint exception coverage 2026-05-31 10:42:59 +01:00
Peter Steinberger
2c6a3f6b04 fix(gateway): make bare reset commands fast 2026-05-31 10:38:20 +01:00
Peter Steinberger
7bf6667d6c docs: update crabbox skill cache-volume guidance 2026-05-31 10:38:05 +01:00
David
778c4f90b9 fix(agents): route per-turn media task hints below the cache boundary (#87998)
* fix(agents): route media task hints below the system-prompt cache boundary

Per-turn image/video/music generation task hints were injected into the
static prependSystemContext slot, landing above the cache boundary inside the
cacheable prefix. The hints are present only on user/manual turns and vary
with active media tasks, so the cacheable prefix shifted turn-to-turn and
defeated Anthropic/OpenAI prompt caching (#85203).

Split the per-turn media hints out of the prepend resolver into
resolveAttemptMediaTaskSystemPromptAddition and route them below the boundary
via the existing prependSystemPromptAddition helper, matching how subagent and
context-engine system-prompt additions are already routed. The static plugin
prependSystemContext / appendSystemContext hook fields are unchanged and
remain in the cacheable prefix. Applied at both consumers (embedded agent
runner and CLI runner).

* fix(agents): keep media task hints below the cache boundary for hook systemPrompt overrides

A before_prompt_build hook that returns a full systemPrompt override replaces
the base prompt with marker-free text. Per-turn media-generation task hints
were then front-prepended into that marker-free prompt, which providers cache
as a single block, so the cached prefix still shifted turn-to-turn on the
override path (#85203).

Wrap the base with ensureSystemPromptCacheBoundary at both media-routing sites
(embedded agent runner and CLI runner) so a marker-free override gets an
appended boundary and the hint routes into the uncached suffix. The helper is
idempotent, so marker-bearing prompts are unchanged. The shared
prependSystemPromptAddition wrapper and the static prependSystemContext /
appendSystemContext hook fields are untouched.

* fix(agents): keep marker-free idle prompts cacheable below the boundary

A marker-free hook systemPrompt override only had the cache boundary
ensured on turns with an active media task. On idle turns the later
appendModelIdentitySystemPrompt landed above the absent boundary, so the
idle cached system prefix diverged from active turns and prompt caching
broke across active/idle transitions. Ensure the boundary regardless of
media state in both the embedded and CLI runners, and extend the
regression to cover the model-identity append across active->idle.

* fix(agents): scope cache-boundary ensure to the model-identity append

Ensuring the boundary unconditionally on media-idle turns appended a
boundary marker to empty raw/gateway system prompts (turning "" into a
marker-only prompt) and to prompts with nothing below the boundary.
Instead ensure the boundary only when a model identity line is actually
appended to a non-empty prompt, in both the embedded and CLI runners.
This still keeps the identity below the boundary for marker-free hook
systemPrompt overrides (the #85203 idle-cache regression) while leaving
empty and identity-less prompts untouched.

* test: refresh stale type and lint expectations

* test: stabilize CI timeout checks

* test: satisfy channel entry lint

* fix(agents): skip cache boundary for blank prompts

* fix(channels): keep draft flush timer referenced

* test(agents): tolerate failed exec timeout setup

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-31 10:35:53 +01:00
Peter Steinberger
75ea8b5094 docs: clarify message-tool-only visible replies 2026-05-31 10:35:20 +01:00
Patrick Star
9c1adf4e51 feat: scope group mention patterns by channel
Provider-scoped configured regex mention patterns for Discord, Matrix, Slack, Telegram, and WhatsApp.

Native platform mentions keep their existing behavior, and unsupported channels do not opt into the new regex policy path. The new policy supports per-channel allow/deny routing through mentionPatterns.mode with allowIn and denyIn so group auto-reply regexes can be limited without broad global blast radius.

Refs #70864.
Supersedes #87200.
Thanks @patrick-slimelab.
2026-05-31 10:34:56 +01:00
giming
f94512cd7f fix(xiaomi): support MiMo voicedesign TTS
Adds Xiaomi MiMo voicedesign TTS support by registering the v2.5 voicedesign model and omitting audio.voice for that model's prompt-driven voice design flow.

Also accepts generic TTS aliases modelId, speakerVoice, and speakerVoiceId for Xiaomi provider config and request overrides.

Fixes exec timeout classification so a process that exits after a missed timeout callback is still reported as timed out, using monotonic deadlines to avoid wall-clock skew.

Verification:
- node scripts/run-vitest.mjs extensions/xiaomi/speech-provider.test.ts
- node scripts/run-vitest.mjs src/process/supervisor/supervisor.test.ts
- node scripts/run-vitest.mjs src/agents/bash-tools.exec-foreground-failures.test.ts
- git diff --check
- autoreview --mode local
- live Xiaomi MiMo voicedesign call returned wav RIFF/WAVE output, 169004 bytes
- GitHub CI success on fb3018ef31: CI 26708919072, CodeQL Critical Quality 26708919082, CodeQL 26708919091, OpenGrep PR Diff 26708919089, Workflow Sanity 26708919083, Dependency Guard 26708918574, Real behavior proof 26708921767

Thanks @GimingRao.

Co-authored-by: Raoyu <2425198313@qq.com>
Co-authored-by: giming <53329020+GimingRao@users.noreply.github.com>
2026-05-31 10:34:51 +01:00
Coder
d9d5d97dbc fix(cron): accept sub-second --at datetimes resolved in a timezone (#88185)
getTimeZoneOffsetMs built localAsUtc via Date.UTC() without the millisecond
argument, so for a sub-second instant the computed timezone offset was wrong by
that fraction. That corrupts resolvedMs and fails the exact-millisecond
re-validation in matchesOffsetlessIsoDateTimeParts, so parseOffsetlessIsoDateTimeInTimeZone
returned null for valid fractional input.

User impact: openclaw cron --at "<ISO>.<ms>" --tz <zone> was silently rejected
even though the parser's regex explicitly accepts fractional seconds (\.\d+).

Pass parts.millisecond (carried from utcMs via getUTCMilliseconds) into Date.UTC
so the offset is exact. Add fractional-second regression rows.

Co-authored-by: coder999999999 <coder999999999@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 10:32:17 +01:00
Feelw00
056bc46a67 fix(infra): guard against overwriting corrupt target session store during migration (#88018)
* fix(infra): guard against overwriting corrupt target session store during migration

migrateLegacySessions reads the target agents/{id}/sessions/sessions.json
and merges it with the legacy sessions dir. When the target file is
corrupt, readSessionStoreJson5 swallows the parse error and returns
{store:{}, ok:false}, so the merge becomes legacy-only. The save gate
(legacyParsed.ok || targetParsed.ok) passes on legacyParsed.ok alone and
never checks targetParsed.ok, so the corrupt target is atomically
overwritten with the legacy-only store. Target-only session records (keys
with no legacy counterpart) are lost permanently and the corrupt file can
no longer be recovered by hand. Legacy corruption is already guarded
(warn + skip delete); target corruption was asymmetrically unprotected.

Skip the save (and the legacy delete) when the target store exists but is
unreadable, leaving the corrupt file and the legacy store both in place,
and push a warning mirroring the legacy-unreadable path. saveSessionStore
and readSessionStoreJson5 signatures are untouched.

AI-assisted: drafted with claude code (claude-opus-4-8).

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

* fix(infra): report direct-chat session migration only after target save commits

Addresses ClawSweeper review on #88018. The `Migrated latest direct-chat session`
result.changes entry was pushed before the targetReadable guard, so the
corrupt-target skip path (which intentionally does not save) still reported a
session migration in doctor/startup logs. Defer that report into the
save-committed block (keeping its existing position before `Merged sessions
store`) and assert its absence in the corrupt-target regression test.

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

* fix(infra): add explicit corrupt session recovery

* fix(infra): keep legacy sessions retryable

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-31 10:31:59 +01:00
Peter Steinberger
ed46e62bcc feat(workboard): add worker dispatch CLI
* feat(workboard): add worker dispatch CLI

* fix(workboard): avoid new unsafe assertions

* fix(workboard): keep remote dispatch failures remote
2026-05-31 10:31:56 +01:00
shawnduggan
1d55caa162 fix(memory): respect QMD status timeout
Respect the configured QMD status timeout during vector availability probes and skip checkpoint-style session transcript exports while preserving valid session IDs that merely contain checkpoint words.

Includes maintainer fixups for latest-main timer-dependent CI and SMS status/test drift.

Thanks @shawnduggan.

Verification:
- `mise exec node@24.13.0 -- node scripts/run-vitest.mjs run --config test/vitest/vitest.agents-core.config.ts src/agents/bash-tools.exec-foreground-failures.test.ts --maxWorkers=1`
- `mise exec node@24.16.0 -- node scripts/run-vitest.mjs run src/channels/draft-stream-loop.test.ts --maxWorkers=1`
- `mise exec node@24.16.0 -- node scripts/run-vitest.mjs run extensions/sms/src/channel.test.ts extensions/sms/src/inbound.test.ts extensions/sms/src/twilio.test.ts extensions/sms/src/gateway.test.ts --maxWorkers=1`
- `mise exec node@24.16.0 -- node scripts/run-vitest.mjs run --config test/vitest/vitest.gateway-server.config.ts src/gateway/server.agent.gateway-server-agent-b.test.ts --maxWorkers=1`
- `mise exec node@24.16.0 -- node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.extensions.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/extensions-test.tsbuildinfo`
- `mise exec node@24.16.0 -- node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.core.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core-test.tsbuildinfo`
- `mise exec node@24.16.0 -- node scripts/run-oxlint-shards.mjs --threads=8`
- `git diff --check`
- GitHub Actions: run `26708853296` and required checks passed on `0c97217a9de501cb861fee731d5c008781da056c`.
2026-05-31 10:29:45 +01:00
Andy Ye
17c2e95334 fix(ui): prefer Talk source-reply final text
Fix Control UI Talk consults so an empty final chat event no longer forces the no-text realtime tool result when a later source-reply or delivery-mirror final contains the answer displayed in the UI.

Also makes agent.wait use the chat-side terminal snapshot while a same-runId chat.send is active, so lifecycle completion cannot beat chat post-dispatch/source-reply delivery.

Adds regression coverage for delayed source replies, agent.wait failure/timeout handling, the wait-before-source-reply race, gateway wait ordering, and punctuation-only skill searches.

Fixes #85275.

Co-authored-by: Andy Ye <35905412+TurboTheTurtle@users.noreply.github.com>
2026-05-31 10:29:19 +01:00
Evan Newman
a0d2febe6b fix(scripts): timeout crabbox wrapper sanity checks
Add bounded timeouts for Crabbox wrapper sanity probes so a stale or hung selected binary cannot block the wrapper indefinitely. The wrapper now maps timed-out sanity probes to a deterministic failure and keeps provider/help parsing behavior intact.

Also add regression coverage for a binary whose `--version` probe hangs while `run --help` still responds.

Co-authored-by: Evan Newman <evanjames010101@gmail.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-31 10:29:12 +01:00
Peter Steinberger
70c8abdca1 refactor(telegram): keep topic thread mapping plugin-local
* refactor(telegram): keep topic thread mapping plugin-local

* fix(telegram): preserve native topic ids for username targets
2026-05-31 10:25:54 +01:00
Peter Steinberger
9e2bd8b2f7 fix(memory): fail open when embedding recall stalls
Preserve custom OpenAI-compatible memory embedding provider ids from #81170.
Fixes #47884.
Fixes #49524.
Refs #56532.

Co-authored-by: adone0 <vladyslav.yavorskyi@outlook.com>
2026-05-31 10:21:17 +01:00
Gio Della-Libera
2d3fa4832f feat(doctor): expose UI freshness health findings
Expose UI freshness doctor findings through the structured health contribution path so lint JSON and dry-run repair output include stale UI asset guidance.

Keep legacy positional repair filtering stable while excluding health checks that already own their structured repair output. Maintainer fixups also avoid stale UI warnings when git history cannot prove changed sources, and make the foreground timeout regression test deterministic.

Verification:
- Local: `git diff --check origin/main...HEAD`
- Local: `node_modules/.bin/oxfmt --check --threads=1 src/agents/bash-tools.exec-foreground-failures.test.ts src/commands/doctor-ui.test.ts src/commands/doctor-ui.ts src/flows/doctor-core-checks.ts src/flows/doctor-health-contributions.test.ts src/flows/doctor-health-contributions.ts src/flows/doctor-health-conversion-plan.ts`
- Local: `node_modules/.bin/oxlint --tsconfig config/tsconfig/oxlint.core.json src/agents/bash-tools.exec-foreground-failures.test.ts src/commands/doctor-ui.test.ts src/commands/doctor-ui.ts src/flows/doctor-core-checks.ts src/flows/doctor-health-contributions.test.ts src/flows/doctor-health-contributions.ts src/flows/doctor-health-conversion-plan.ts`
- Local: `node scripts/run-vitest.mjs src/commands/doctor-ui.test.ts src/flows/doctor-health-contributions.test.ts src/commands/doctor-lint.test.ts src/agents/bash-tools.exec-foreground-failures.test.ts --reporter=dot --pool=forks --testTimeout=30000 --hookTimeout=30000`
- Local: `GOMAXPROCS=4 node scripts/run-tsgo.mjs -p tsconfig.core.json --noEmit --incremental false --pretty false`
- Local: `GOMAXPROCS=4 node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.core.test.json --noEmit --incremental false --pretty false`
- Local: `GOMAXPROCS=4 node scripts/run-tsgo.mjs -p tsconfig.extensions.json --noEmit --incremental false --pretty false`
- Autoreview: `.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main`
- GitHub Actions: CI `26708647282`, Real behavior proof `26708646476`, CodeQL `26708647258`, CodeQL Critical Quality `26708647230`, OpenGrep PR Diff `26708647214`, Workflow Sanity `26708647232`, Dependency Guard `26708646489`, ClawSweeper Dispatch `26708646475`, Labeler `26708646480`

Co-authored-by: Gio Della-Libera <giodl73@gmail.com>
2026-05-31 10:20:12 +01:00
Peter Steinberger
7606e1dd3d docs: expand MCP operator guide 2026-05-31 10:12:44 +01:00
github-actions[bot]
ef7854abbc chore(ui): refresh fa control ui locale 2026-05-31 09:12:28 +00:00
github-actions[bot]
53e063962d chore(ui): refresh nl control ui locale 2026-05-31 09:12:16 +00:00
github-actions[bot]
cef86c1748 chore(ui): refresh vi control ui locale 2026-05-31 09:11:52 +00:00
github-actions[bot]
ee39aa84b2 chore(ui): refresh pl control ui locale 2026-05-31 09:11:49 +00:00
github-actions[bot]
e93e2a0f18 chore(ui): refresh th control ui locale 2026-05-31 09:11:42 +00:00
github-actions[bot]
fce45a2178 chore(ui): refresh id control ui locale 2026-05-31 09:11:33 +00:00
github-actions[bot]
2a58d92655 chore(ui): refresh uk control ui locale 2026-05-31 09:10:59 +00:00
github-actions[bot]
b335018c3c chore(ui): refresh tr control ui locale 2026-05-31 09:10:54 +00:00
github-actions[bot]
80294a4f6b chore(ui): refresh ar control ui locale 2026-05-31 09:10:48 +00:00
github-actions[bot]
20ab73e7d4 chore(ui): refresh it control ui locale 2026-05-31 09:10:43 +00:00
github-actions[bot]
a041e393c1 chore(ui): refresh fr control ui locale 2026-05-31 09:10:15 +00:00
github-actions[bot]
2e0d191725 chore(ui): refresh ko control ui locale 2026-05-31 09:10:13 +00:00
github-actions[bot]
ec949a856e chore(ui): refresh ja-JP control ui locale 2026-05-31 09:10:03 +00:00
github-actions[bot]
0b9193c0b7 chore(ui): refresh es control ui locale 2026-05-31 09:09:55 +00:00
github-actions[bot]
aa56f592bb chore(ui): refresh pt-BR control ui locale 2026-05-31 09:09:24 +00:00
github-actions[bot]
10b4057c36 chore(ui): refresh zh-TW control ui locale 2026-05-31 09:09:22 +00:00
github-actions[bot]
ecef6ae626 chore(ui): refresh zh-CN control ui locale 2026-05-31 09:09:18 +00:00
github-actions[bot]
f456114b12 chore(ui): refresh de control ui locale 2026-05-31 09:09:13 +00:00
Peter Steinberger
617c658498 feat: improve MCP operator controls (#88536)
* feat: improve MCP operator controls

* test: stabilize draft stream loop background errors

* fix: prune empty MCP server enablement stubs

* fix: ignore disabled MCP overrides in doctor

* fix: keep MCP doctor saved-config warnings

* fix: redact malformed MCP URLs in UI

* fix: harden MCP UI command actions

* fix: allow MCP logout after auth removal
2026-05-31 10:06:55 +01:00
Peter Steinberger
3258338ec8 chore(lint): clean sms lint fallout 2026-05-31 10:04:48 +01:00
Peter Steinberger
3a4943ef87 fix(ci): repair sms channel checks 2026-05-31 05:02:18 -04:00
Vincent Koc
84b025eb62 fix(e2e): make plugin sweep wrappers executable 2026-05-31 10:42:50 +02:00
Jason O'Neal
a776de25e8 fix(auto-reply): redact secrets in config show output (#88496)
* fix(auto-reply): redact config show secrets

* fix(auto-reply): use schema redaction for config show

* fix(auto-reply): redact config set acknowledgements

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-31 09:36:24 +01:00
Peter Steinberger
b4aaca3365 fix(ci): repair copilot sdk drift 2026-05-31 04:34:54 -04:00
Peter Steinberger
f5eca3f84c chore(lint): enable object and reassignment rules 2026-05-31 09:32:52 +01:00
Peter Steinberger
ea11b8ad3d docs: expand SMS channel setup guide 2026-05-31 09:31:00 +01:00
Peter Steinberger
d4f78c9339 ci: harden Crabbox Testbox runs 2026-05-31 09:29:56 +01:00
Zee Zheng
15ae2deb30 fix(webchat): preserve refresh-visible history and composer state (#83992)
WebChat now stores/restores composer draft and queued sends across refresh, scoped by gateway/session/agent. It skips in-flight/steered sends, restores after agent scope hydration, waits for fresh idle session proof before draining restored sends, and backfills visible chat history when the raw tail contains silent/context entries.

Refs #83344

Co-authored-by: Zee Zheng <zheng.zuo0@gmail.com>
2026-05-31 09:23:58 +01:00
Vincent Koc
e6ce83487c fix(check): restore core typecheck 2026-05-31 10:23:33 +02:00
Peter Steinberger
3513e8bfd9 feat: add Twilio SMS channel
Add a bundled SMS channel backed by Twilio inbound webhooks and outbound text delivery.

Includes signed webhook validation, pairing/allowlist access, Messaging Service sender support, chunked plain-text SMS delivery, default target support, docs, config metadata, labeler updates, and focused SMS coverage.

Verification:
- pnpm exec tsgo -p extensions/sms/tsconfig.json --noEmit
- OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/tmp/openclaw-vitest-sms-land-fix2 node scripts/run-vitest.mjs extensions/sms/src/phone.test.ts extensions/sms/src/accounts.test.ts extensions/sms/src/twilio.test.ts extensions/sms/src/inbound.test.ts extensions/sms/src/gateway.test.ts extensions/sms/src/channel.test.ts extensions/sms/src/send.test.ts extensions/sms/src/webhook.test.ts --reporter=verbose
- pnpm config:channels:check
- pnpm plugins:inventory:check
- git diff --check
- .agents/skills/autoreview/scripts/autoreview --mode local
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
2026-05-31 09:22:31 +01:00
Andy Ye
0f1767a26a fix(telegram): support media message edits
Fixes #86161.

Route Telegram media-message edits through the Telegram caption/reply-markup APIs instead of always calling `editMessageText`. Button-only edits now update reply markup, explicit captions use `editMessageCaption`, and text edits can fall back to caption edits when Telegram reports the message has no editable text.

Also documents the edit behavior, adds regression coverage, tightens timer-spy cleanup for the affected agents test lane, and removes a stale loader helper from the current base that broke core typecheck.

Co-authored-by: Andy Ye <35905412+TurboTheTurtle@users.noreply.github.com>
2026-05-31 09:22:20 +01:00
Peter Steinberger
63a95930ca chore: remove stale unsafe assertion suppressions 2026-05-31 09:11:28 +01:00
Peter Steinberger
b81adc6202 fix(ci): keep unsafe assertion lint disabled 2026-05-31 04:09:48 -04:00
Peter Steinberger
0ac725278d Revert "fix(ci): annotate unsafe boundary casts"
This reverts commit 8a40f90f62.
2026-05-31 04:09:48 -04:00
Peter Steinberger
4471335d26 Revert "fix(ci): clean core unsafe assertions"
This reverts commit 88203c9b10.
2026-05-31 04:09:48 -04:00
Peter Steinberger
b78dd6a9ca test: remove channel test isolation hack
Remove isolate: true from the channel Vitest config and fix the leaking fake-timer/mock tests so the lane runs under the shared non-isolated runner. Verified with focused scoped-config/channel tests, the full channel Vitest config, git diff --check, and branch-mode autoreview.
2026-05-31 09:09:10 +01:00
Frank Yang
15c1511817 fix(agents): clear stale compaction bindings 2026-05-31 13:38:52 +05:30
Frank Yang
5e1e029d91 fix(agents): skip below-target CLI compaction failures 2026-05-31 13:38:52 +05:30
Peter Steinberger
48ccc50282 chore: update dependencies 2026-05-31 09:07:53 +01:00
Shakker
5a8bb1a7d2 docs: add Skill Workshop guide 2026-05-31 09:05:03 +01:00
Peter Steinberger
e1ad5f5170 docs: remove divider comments (#88115) 2026-05-31 09:03:18 +01:00
Peter Steinberger
88203c9b10 fix(ci): clean core unsafe assertions 2026-05-31 03:58:58 -04:00
Steven
b48c72cd19 fix(discord): deliver same-session channel replies
Deliver same-session channel replies directly while preserving stale-reply guards.

The fix bypasses the announce decider only when the requester and target are the same source channel, carries reply baselines into fire-and-forget follow-up delivery, and keeps history reads best-effort so timeout-zero sends still dispatch. It also includes focused regression coverage for delayed same-session replies, stale snapshots, retry timer caps, and the current strict-null/package-boundary blockers fixed while preparing the PR.
2026-05-31 08:52:01 +01:00
Peter Steinberger
8a40f90f62 fix(ci): annotate unsafe boundary casts 2026-05-31 03:51:18 -04:00
Peter Steinberger
ae651e7210 docs: add permission modes page 2026-05-31 08:47:02 +01:00
Peter Steinberger
4d95ae39d4 fix(ci): repair extension type drift 2026-05-31 03:40:32 -04:00
Peter Steinberger
e6782254e4 perf: avoid blocking gateway bind on control ui build 2026-05-31 08:36:30 +01:00
Peter Steinberger
59694e86d9 chore(lint): enable structured clone rules 2026-05-31 08:34:28 +01:00
Ayaan Zaidi
87664ed096 Fix iMessage startup watch replay (#88406)
* fix(imessage): start watch after existing local rows

* test(imessage): cover stale startup watch rows

* fix(imessage): keep watch startup tolerant of db probes

* fix(imessage): watermark default local watch startup

* fix(imessage): tolerate missing sqlite startup probe

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-31 08:33:22 +01:00
Peter Steinberger
1fd9fe2b33 fix(ci): isolate timer-sensitive tests 2026-05-31 03:30:37 -04:00
Peter Steinberger
122ae5db9e perf: lazy-load agent reply payload formatter 2026-05-31 08:29:32 +01:00
Peter Steinberger
930b371a2f refactor(telegram): persist plugin state in sqlite
Move Telegram plugin-local state from JSON sidecars into plugin-state SQLite. Keep legacy JSON handling in startup and doctor migration plans, with runtime state now reading and writing SQLite directly. Stabilize the channel Vitest lane by cleaning up typing timers and isolating that lane.
2026-05-31 08:28:53 +01:00
Peter Steinberger
b9fe0894a6 chore(lint): enable additional cleanup rules 2026-05-31 08:16:11 +01:00
Peter Steinberger
444562b3de chore: remove stale dead code 2026-05-31 03:04:25 -04:00
Peter Steinberger
ce547bfd44 fix(ci): stabilize ui paste and telegram types 2026-05-31 02:56:46 -04:00
Peter Steinberger
d4d7fdbc59 fix(ci): satisfy strict nullish guards 2026-05-31 02:50:24 -04:00
mochiexists
096bd13962 build(OpenClawKit): make ElevenLabsKit optional behind Talk trait
Adds a default-enabled SwiftPM Talk trait for OpenClawKit so chat-only consumers can opt out with traits: [] and avoid resolving ElevenLabsKit. Default traits preserve existing talk/TTS API and bundled app behavior; macOS CI now verifies the trait-off dependency graph and build.

Verification:
- CI at 85f00ebc04 passed macos-swift and Real behavior proof.
- Local Swift 6.3.2: trait-off dependency graph omitted ElevenLabsKit; full swift build with default traits disabled built through OpenClawChatUI; default dependency graph still included ElevenLabsKit; trait-off OpenClawKit target build passed.
- merge-tree against latest origin/main 4eba3e5d7d was clean.
- Current main already fails plugin-SDK declaration gates in unrelated TS files; reproduced locally with node scripts/run-tsgo.mjs -p tsconfig.plugin-sdk.dts.json --declaration true.

Thanks @mochiexists.

Co-authored-by: mochiexists <259077624+mochiexists@users.noreply.github.com>
Co-authored-by: atlascodesai <76924051+atlascodesai@users.noreply.github.com>
2026-05-31 07:40:35 +01:00
Peter Steinberger
4eba3e5d7d chore(lint): enable more readability rules 2026-05-31 07:38:33 +01:00
Peter Steinberger
9c3cf35e08 fix(ci): stop channel timers holding vitest open 2026-05-31 02:33:48 -04:00
Peter Steinberger
deb7bc6539 chore(lint): enable readability lint rules 2026-05-31 07:17:57 +01:00
Peter Steinberger
0211a3aa9f fix(ci): restore main validation 2026-05-31 02:13:10 -04:00
Peter Steinberger
ade6e7769b perf: prewarm gateway runtime plugins 2026-05-31 07:09:42 +01:00
guanbear
f1cb9f2f6a fix(slack): keep DM thread turns out of active steering
Keep Slack direct-message sessions stable while tracking routed Slack thread ids on active reply operations. Different top-level Slack DM threads from the same sender no longer steer into or block each other, while ordinary same-thread follow-ups and non-Slack direct-message behavior keep their existing semantics.

Verification:
- `git diff --check origin/main...FETCH_HEAD`
- `/Users/steipete/Projects/agent-scripts/skills/autoreview/scripts/autoreview --mode branch --base origin/main --output /tmp/pr85904-autoreview.txt --json-output /tmp/pr85904-autoreview.json`
- GitHub CI green for head `6703e166545bcb96c1a50de93a42446212cca9a7`, including Real behavior proof and auto-reply reply routing/dispatch shards.

Co-authored-by: guanbear <123guan@gmail.com>
2026-05-31 07:05:50 +01:00
Ted Li
667393be8f fix(commands): make /skill load workspace skills
Fixes #88056.

Reload workspace skill commands for `/skill <name>` when directive resolution supplied only an empty placeholder list, so the generic skill wrapper can invoke the same command-visible skills as direct slash commands.

Keep stale-message cutoff and empty-config channel suppression ahead of skill discovery and tool dispatch so suppressed `/skill` messages cannot trigger side-effecting skill tools.

Co-authored-by: Ted Li <tl2493@columbia.edu>
2026-05-31 07:04:59 +01:00
brokemac79
72c61bc123 fix(telegram): align DM topic session routing
Align Telegram proactive DM-topic outbound session routing with inbound reply routing.

The Telegram plugin now uses the chat-scoped DM-topic suffix for direct-topic outbound sessions, so cron/proactive sends and replies reuse the same session. Delivery metadata is kept as the numeric Telegram topic id so visible sends still target the correct private topic.

Refs #80212.
Thanks @brokemac79.

Verification:
- PR head d904115e4c
- GitHub CI/checks green on PR head; Real behavior proof passed; OpenGrep passed; CodeQL neutral/pass
- git diff --check origin/main...pr/88421 -- extensions/telegram/src/channel.ts extensions/telegram/src/session-route.test.ts
- git merge-tree $(git merge-base origin/main pr/88421) origin/main pr/88421
2026-05-31 06:54:51 +01:00
Peter Steinberger
b372af6b81 test: keep timeout clamp checks under one second 2026-05-31 06:51:35 +01:00
Peter Steinberger
04b68e8fa4 fix(shared): restore number coercion barrel 2026-05-31 06:51:34 +01:00
Peter Steinberger
9f99acf12d test: restore marketplace cleanup coverage 2026-05-31 06:51:34 +01:00
Peter Steinberger
23dac6c263 test: keep vitest cases under one second 2026-05-31 06:51:34 +01:00
Peter Steinberger
8a4679026c fix: clarify generated media reply prompts (#88458)
* fix: clarify generated media reply prompts

* fix: hide media compat aliases from message schema

* fix: hide message media url aliases

* test: refresh media prompt snapshots
2026-05-31 06:45:57 +01:00
Peter Steinberger
0303f3a8f0 fix(qa): clamp transport wait intervals 2026-05-31 01:37:46 -04:00
Peter Steinberger
bb680a845b fix(onboard): clamp gateway reachability polling 2026-05-31 01:37:46 -04:00
Peter Steinberger
5de0d873ed fix(qa): clamp gateway restart polling 2026-05-31 01:37:46 -04:00
Peter Steinberger
83597b7f95 fix(qa): clamp cron run poll intervals 2026-05-31 01:37:46 -04:00
Peter Steinberger
edd8aa2f4e fix(agents): clamp embedded run drain polling 2026-05-31 01:37:46 -04:00
Peter Steinberger
fab8d29d21 fix(feishu): clamp sequential queue timeouts 2026-05-31 01:37:46 -04:00
Peter Steinberger
7595d52e56 fix(auth): bound profile usage window expiries 2026-05-31 01:37:46 -04:00
Peter Steinberger
11c050d0d0 fix(agents): clamp session suspension TTLs 2026-05-31 01:37:46 -04:00
Peter Steinberger
764321d3d3 fix(channels): clamp draft stream throttles 2026-05-31 01:37:46 -04:00
Peter Steinberger
54a27f4e57 fix(gateway): clamp auth limiter durations 2026-05-31 01:37:46 -04:00
Peter Steinberger
84061c1f8e fix(memory): clamp batch timeout minutes 2026-05-31 01:37:46 -04:00
Peter Steinberger
5c38c0c76d fix(memory): clamp sync interval timers 2026-05-31 01:37:46 -04:00
Peter Steinberger
db94eac5c0 fix(auto-reply): clamp typing timers 2026-05-31 01:37:46 -04:00
Peter Steinberger
92f1d90e0f fix(channels): clamp typing timers 2026-05-31 01:37:46 -04:00
Peter Steinberger
a1d7a7536a fix(gateway): clamp auth limiter prune intervals 2026-05-31 01:37:46 -04:00
Peter Steinberger
287f531de6 fix(sqlite): clamp WAL checkpoint intervals 2026-05-31 01:37:46 -04:00
Peter Steinberger
d06e1b2c71 fix(gateway): bound health monitor intervals 2026-05-31 01:37:46 -04:00
Peter Steinberger
5b0036ffde fix(nostr): bound seen tracker capacity 2026-05-31 01:37:46 -04:00
Peter Steinberger
dca53afd53 fix(openai): convert realtime secret expiry 2026-05-31 01:37:46 -04:00
Peter Steinberger
604339ebf9 fix(clickclack): normalize reconnect intervals 2026-05-31 01:37:46 -04:00
Peter Steinberger
74c5548c0d fix(github-copilot): chunk device polling waits 2026-05-31 01:37:46 -04:00
Peter Steinberger
33c44626d2 fix(memory): bound embedding batch poll intervals 2026-05-31 01:37:46 -04:00
Peter Steinberger
68b5371fca fix(discord): bound transport activity timestamps 2026-05-31 01:37:46 -04:00
Peter Steinberger
9417b9cea8 fix(discord): bound ACP activity timestamps 2026-05-31 01:37:46 -04:00
Peter Steinberger
0c97922e23 fix(codex): bound synthesized hook start times 2026-05-31 01:37:46 -04:00
Peter Steinberger
2bdb2e8e02 fix(gateway-client): clamp readiness intervals 2026-05-31 01:37:46 -04:00
Peter Steinberger
984951f55c fix(gateway-client): clamp tick watchdog intervals 2026-05-31 01:37:46 -04:00
Peter Steinberger
59f96078b2 fix(sessions): bound lifecycle timestamps 2026-05-31 01:37:45 -04:00
Peter Steinberger
f0c0181b10 fix(sandbox): prune invalid registry timestamps 2026-05-31 01:37:45 -04:00
Peter Steinberger
84dec338e7 fix(sandbox): bound fs bridge mtimes 2026-05-31 01:37:45 -04:00
Peter Steinberger
66a4410095 fix(memory): bound session export timestamps 2026-05-31 01:37:45 -04:00
Peter Steinberger
b26f89213e fix(usage): bound minimax usage epochs 2026-05-31 01:37:45 -04:00
Peter Steinberger
ae4ddece91 fix(agents): bound model scan created timestamps 2026-05-31 01:37:45 -04:00
Peter Steinberger
9161db534e fix(zalouser): bound inbound timestamp normalization 2026-05-31 01:37:45 -04:00
Peter Steinberger
cae98c1daf fix(gateway): centralize plugin approval timeout bounds 2026-05-31 01:37:45 -04:00
Peter Steinberger
3d0dc15904 fix(codex): bound native hook cleanup grace 2026-05-31 01:37:45 -04:00
Peter Steinberger
f71df664c9 fix(synology-chat): bound rate limit windows 2026-05-31 01:37:45 -04:00
Peter Steinberger
4ca218246e fix(diffs): cap artifact ttl normalization 2026-05-31 01:37:45 -04:00
Peter Steinberger
11b5968534 fix(channels): bound thread binding lifecycle durations 2026-05-31 01:37:45 -04:00
Peter Steinberger
5e139e32dc fix(agents): centralize subagent timeout math 2026-05-31 01:37:45 -04:00
Peter Steinberger
620acafb15 fix(browser): bound tab cleanup timer config 2026-05-31 01:37:45 -04:00
Peter Steinberger
8247f824b9 fix(google-meet): bound timer config values 2026-05-31 01:37:45 -04:00
Peter Steinberger
c767b37e3b fix(discord): bound identify limiter clock skew 2026-05-31 01:37:45 -04:00
Peter Steinberger
21478cab93 fix(agents): clamp abortable sleep helper 2026-05-31 01:37:45 -04:00
Peter Steinberger
dbddf4093f fix(utils): clamp shared sleep timers 2026-05-31 01:37:45 -04:00
Peter Steinberger
1cf264c468 fix(infra): clamp abortable sleep timers 2026-05-31 01:37:45 -04:00
Peter Steinberger
9d866d8b2a fix(cli): clamp port wait timers 2026-05-31 01:37:45 -04:00
Peter Steinberger
0e3cc2e5ad fix(cli): clamp cron wait poll timers 2026-05-31 01:37:45 -04:00
Peter Steinberger
1670b970ee fix(gateway): clamp lock poll timers 2026-05-31 01:37:45 -04:00
Peter Steinberger
37fbc8cd8f fix(memory): clamp remote batch timers 2026-05-31 01:37:45 -04:00
Peter Steinberger
7eeea30d8c fix(minimax): clamp oauth poll interval 2026-05-31 01:37:45 -04:00
Peter Steinberger
cdab5fc16a fix(infra): clamp provider usage timeout 2026-05-31 01:37:45 -04:00
Peter Steinberger
aa42905354 fix(agents): clamp idle flush timeout 2026-05-31 01:37:45 -04:00
Peter Steinberger
fbee4d56c4 fix(web): clamp shared tool timeout 2026-05-31 01:37:45 -04:00
Peter Steinberger
ed59533574 fix(feishu): clamp abortable delay timers 2026-05-31 01:37:45 -04:00
Peter Steinberger
1f92a3e351 fix(mattermost): clamp probe timeout 2026-05-31 01:37:45 -04:00
Peter Steinberger
ac4ebc053a fix(cli): clamp progress delay timers 2026-05-31 01:37:45 -04:00
Peter Steinberger
9b2146775f fix(browser): clamp client action timeouts 2026-05-31 01:37:45 -04:00
Peter Steinberger
bc38a929aa fix(plugins): clamp hook timeouts 2026-05-31 01:37:44 -04:00
Peter Steinberger
8e12c6ea1f fix(plugin-sdk): clamp oauth callback timeout 2026-05-31 01:37:44 -04:00
Peter Steinberger
65167c9637 fix(tlon): clamp sse reconnect delays 2026-05-31 01:37:44 -04:00
Peter Steinberger
87eae7f811 fix(memory): clamp lancedb recall timeout 2026-05-31 01:37:44 -04:00
Peter Steinberger
b4e331fe81 fix(health): clamp probe timeout 2026-05-31 01:37:44 -04:00
Peter Steinberger
c8d458d13d fix(outbound): clamp message gateway timeouts 2026-05-31 01:37:44 -04:00
Peter Steinberger
2cbfb910f2 fix(commands): clamp gateway agent timeout 2026-05-31 01:37:44 -04:00
Peter Steinberger
1c1f42a74a fix(secrets): clamp provider timeouts 2026-05-31 01:37:44 -04:00
Peter Steinberger
3734ed6402 fix(agents): clamp compaction worker timeout 2026-05-31 01:37:44 -04:00
Peter Steinberger
5e11c85c0a fix(codex): clamp app-server timer config 2026-05-31 01:37:44 -04:00
Peter Steinberger
4135771adf fix(codex): clamp app-server watch timers 2026-05-31 01:37:44 -04:00
Peter Steinberger
58db38e088 fix(voice-call): clamp telephony tts timeout 2026-05-31 01:37:44 -04:00
Peter Steinberger
e500f401ea fix(voice-call): clamp pre-start stream timeout 2026-05-31 01:37:44 -04:00
Peter Steinberger
1ff52b2786 fix(voice-call): clamp continue poll timeout 2026-05-31 01:37:44 -04:00
Peter Steinberger
2b3f09659c fix(qa): clamp cli child timeout 2026-05-31 01:37:44 -04:00
Peter Steinberger
0d391bacf7 fix(qa): clamp bus wait timers 2026-05-31 01:37:44 -04:00
Peter Steinberger
85c8e7f89f fix(qa): clamp browser runtime timeouts 2026-05-31 01:37:44 -04:00
Peter Steinberger
1987d364b5 fix(qa): clamp web runtime timeouts 2026-05-31 01:37:44 -04:00
Peter Steinberger
971cb2d4bd fix(discord): clamp rest scheduler delay 2026-05-31 01:37:44 -04:00
Peter Steinberger
c66b21662d fix(discord): clamp rest request timeout 2026-05-31 01:37:44 -04:00
Peter Steinberger
6e318684c1 fix(discord): clamp component wait timeout 2026-05-31 01:37:44 -04:00
Peter Steinberger
89022023a3 fix(talk): clamp forced consult delay 2026-05-31 01:37:44 -04:00
Peter Steinberger
10e8426aa5 fix(hooks): clamp fire-and-forget timeout 2026-05-31 01:37:44 -04:00
Peter Steinberger
79d3083eb6 fix(agents): clamp catalog browse timeout 2026-05-31 01:37:44 -04:00
Peter Steinberger
95e2427189 fix(provider): clamp poll wait timers 2026-05-31 01:37:44 -04:00
Peter Steinberger
29a67f4d11 fix(media): clamp saved response idle timeout 2026-05-31 01:37:44 -04:00
Peter Steinberger
2d2ab6d480 fix(media): clamp response idle timeout 2026-05-31 01:37:44 -04:00
Peter Steinberger
cb79864cb9 fix(tts): clamp summarization timeout 2026-05-31 01:37:44 -04:00
Peter Steinberger
0530596eef fix(codex): clamp turn collector timeout 2026-05-31 01:37:44 -04:00
Peter Steinberger
417022864b fix(codex): clamp media turn timeout 2026-05-31 01:37:43 -04:00
Peter Steinberger
2833d4b347 fix(agents): clamp embedded run wait timers 2026-05-31 01:37:43 -04:00
Peter Steinberger
490a155f15 fix(auto-reply): clamp reply idle wait timers 2026-05-31 01:37:43 -04:00
Peter Steinberger
5f7217db2c fix(gateway): bound exec approval timers 2026-05-31 01:37:43 -04:00
Peter Steinberger
de1c4f8aec fix(infra): clamp restart deferral poll 2026-05-31 01:37:43 -04:00
Peter Steinberger
3a31b34151 fix(infra): clamp heartbeat wake delay 2026-05-31 01:37:43 -04:00
Peter Steinberger
8ef5b5ddba fix(auto-reply): bound session lifecycle expiries 2026-05-31 01:37:43 -04:00
Peter Steinberger
0adf3220b8 fix(auto-reply): bound auth label expiries 2026-05-31 01:37:43 -04:00
Peter Steinberger
edb2c498d5 fix(auth): bound profile unusable windows 2026-05-31 01:37:43 -04:00
Peter Steinberger
00831cf8ff fix(gateway): bound model auth expiry rollups 2026-05-31 01:37:43 -04:00
Peter Steinberger
b0ca5d7407 fix(auth): adopt main oauth over invalid local expiry 2026-05-31 01:37:43 -04:00
Peter Steinberger
c9311ef0a9 fix(auth): bound stored oauth replacement expiry 2026-05-31 01:37:43 -04:00
Peter Steinberger
1a4d2f7cca fix(auth): bound inherited oauth expiry 2026-05-31 01:37:43 -04:00
Peter Steinberger
9d31cbbd6a refactor(cron): split service timer helpers
Split cron timer helper concerns into focused service modules for agent watchdog cleanup, execution error text, failure alerts, task-run ledger handling, and wake dispatch.

Verification: focused cron Vitest, oxfmt check, git diff check, autoreview clean, and GitHub PR checks green.
2026-05-31 06:31:27 +01:00
Peter Steinberger
bbc4bee7a2 fix(heartbeat): advance stale scheduler deferrals
Fix stale heartbeat scheduler deferrals so disabled/non-retry skips and flood deferrals advance the due slot instead of rearming a 0 ms timer loop.

Fixes #79380.
Supersedes #79418.

Proof:
- pnpm test src/infra/heartbeat-runner.scheduler.test.ts -- --reporter=verbose
- pnpm check:changed via Testbox tbx_01ksxfavykc7qyve4ysnxg3smh
- autoreview clean
- GitHub CI green for 213003a854, including Real behavior proof
2026-05-31 06:26:44 +01:00
Vincent Koc
ef9e9bf6b9 fix(build): preserve fresh startup metadata across rebuilds 2026-05-31 07:16:13 +02:00
Peter Steinberger
51dee73a5d perf: cache log timestamp formatters 2026-05-31 06:09:22 +01:00
Peter Steinberger
b858d418aa fix(ui): localize tool error card label 2026-05-31 06:04:55 +01:00
Vincent Koc
e1a9817141 fix(e2e): preflight openai chat tools auth 2026-05-31 05:20:33 +02:00
Peter Steinberger
4dad7bd93b fix(release): tolerate npm README metadata lag 2026-05-31 02:49:06 +01:00
Vincent Koc
26913e60a4 fix(codex): preserve public OpenAI app-server provider 2026-05-31 03:39:03 +02:00
Shakker
5c5711f061 fix: keep tool card actions inline 2026-05-31 02:11:53 +01:00
Shakker
1e3542bbe7 fix: label collapsed tool cards by tool 2026-05-31 02:07:52 +01:00
Shakker
9a00d74044 fix: share skill workshop prompt with codex 2026-05-31 01:53:01 +01:00
Shakker
e9d01320d7 fix: isolate dev source plugin aliases 2026-05-31 01:47:11 +01:00
Shakker
ae800e160d fix: prefer source plugins in dev runs 2026-05-31 01:47:11 +01:00
Peter Steinberger
e086bfeb91 chore(release): refresh plugin sdk api baseline 2026-05-31 01:45:54 +01:00
Peter Steinberger
dd72b104ac fix(qa): use auth credential type for OpenAI live model selection 2026-05-31 01:39:36 +01:00
NianJiu
199a1b9014 fix(webchat): fetch full sidebar content for truncated history
Add a bounded `chat.message.get` gateway method so Control UI can fetch one display-normalized transcript message by id when an assistant history preview was truncated. Keep `chat.history` lightweight, reject oversized/hidden/missing rows with explicit unavailable reasons, and wire the WebChat side reader to request full content only for visible truncated assistant messages.

Also refresh the generated Swift gateway protocol models and document the new assistant-message side-reader behavior.

Closes #84651.
Related #53242.

Co-authored-by: NianJiuZst <3235467914@qq.com>
2026-05-31 01:33:52 +01:00
Peter Steinberger
00d8d7ead0 refactor: extract normalization core package
Extract shared normalization/coercion helpers into private @openclaw/normalization-core workspace package while preserving existing plugin SDK helper subpaths.\n\nAlso keeps direct normalization-core imports internal, wires UI/build/loader resolution, and replaces the slow PR network CodeQL lane with a fast added-line boundary scan while retaining full CodeQL for scheduled/manual runs.\n\nVerification: local moved tests, plugin SDK boundary tests, extension loader tests, agents-support shard, UI build/test, build artifacts, lint, workflow guards, autoreview, and GitHub CI passed on PR head 963d893715.
2026-05-31 01:33:00 +01:00
Peter Steinberger
94814f3516 fix(qa): restore OpenAI OAuth release contracts 2026-05-31 01:25:48 +01:00
Peter Steinberger
9caefeaf08 fix(ui): satisfy vite alias lint guard 2026-05-31 01:08:42 +01:00
Peter Steinberger
16bae70af4 fix(release): align prerelease contracts after provider rename 2026-05-31 00:52:22 +01:00
Vincent Koc
6270d5326f fix(e2e): prove gateway health after websocket connect 2026-05-31 01:39:28 +02:00
Shakker
6561bdc41d fix: resolve root aliases in ui dev 2026-05-31 00:36:02 +01:00
Shakker
54d42c7c9a fix: vertically center tool summary labels 2026-05-31 00:36:01 +01:00
Peter Steinberger
ab35dcd333 fix(release): repair 2026.5.30 beta prerelease gates 2026-05-31 00:32:02 +01:00
Peter Steinberger
4c33aaa86c refactor: unify OpenAI provider identity (#88451)
* refactor: unify OpenAI provider identity

* refactor: move legacy oauth sidecar doctor helpers

* test: align OpenAI fixtures after rebase

* test: clean OpenAI provider unification

* fix: finish OpenAI provider cleanup

* fix: finish OpenAI cleanup follow-through

* fix: finish OpenAI CI cleanup
2026-05-31 00:29:44 +01:00
Peter Steinberger
8d6a6e9d03 feat: move workboard to relational sqlite
Move Workboard durable data into a relational SQLite database and add extension doctor migration for .28 plugin-state rows. Preserve attachment lifecycle behavior, SQLite permissions/WAL settings, and scoped plugin migration access.
2026-05-31 00:02:23 +01:00
Vincent Koc
7fc02d36b3 fix(scripts): assert lifecycle inspect output 2026-05-31 01:00:58 +02:00
scotthuang
7920af0c9e refactor: route browser screenshot vision through shared media understanding
* feat(browser): add optional vision understanding to screenshot tool

* fix(browser): wrap vision output as external content, enforce maxBytes, forward auth profiles

* fix(browser): remove no-op scope/attachments config, drop profile pass-through lacking runtime support

* feat(media-understanding): add profile/preferredProfile to DescribeImageFileWithModelParams and forward to describeImage

* style(browser): add curly braces to satisfy eslint curly rule

* fix(browser): correct tools.browser.enabled help text to match actual behavior

* fix(browser): thread agentDir/workspaceDir from plugin tool context into browser vision

* refactor(browser): move vision config from tools.browser to browser.models

The browser plugin's vision configuration now lives on the top-level
`browser` config namespace (browser.models, browser.visionEnabled,
browser.visionPrompt, etc.) instead of `tools.browser`. This aligns
with the plugin's existing config location and avoids confusion between
tool-level and plugin-level settings.

- Remove tools.browser from ToolsSchema and ToolsConfig
- Add models/vision* fields to BrowserConfig and its zod schema
- Update getBrowserVisionConfig to read from cfg.browser
- Update schema help, labels, and quality test
- Update vision.test.ts to use new config shape

* docs(browser): add screenshot vision configuration section

Document the new browser.models config for automatic screenshot
description via vision models, enabling text-only main models to
reason about web page content.

* fix(browser): remove deliverable media markers from vision result, drop unused import

P1: Vision-success path no longer exposes the raw screenshot as
deliverable media (removes MEDIA: line and details.media.mediaUrl).
This prevents channel delivery from auto-sending sensitive page content
when the intended output is a text description.

P2: Remove unused ToolsMediaUnderstandingSchema import that would fail
noUnusedLocals typecheck.

* fix(browser): add command/args fields to browser models schema

The browser vision model schema uses .strict(), so CLI-type entries
with command/args were rejected by TypeScript. Add these fields to
align with MediaUnderstandingModelSchema.

* chore(browser): remove debug console.log statements

* fix(browser): harden screenshot vision result against MEDIA: directive injection and restore image sanitization on failure fallback

ClawSweeper #84247 review round 2:

P1 (security, high): neutralize line-start MEDIA: directives in vision descriptions
before wrapping with wrapExternalContent. The agent media extractor scans every
browser tool-result text block via splitMediaFromOutput which treats line-start
MEDIA: as a trusted local-media delivery directive, and browser is on the
trusted-media allowlist. Without neutralization, page or vision-provider output
containing 'MEDIA:/tmp/secret.png' could synthesize a channel-deliverable media
artifact from untrusted content. wrapExternalContent itself does not strip
line-start directives. Introduce neutralizeMediaDirectives in vision.ts that
prepends '[neutralized] ' to any line whose trimStart() begins with MEDIA:
(case-insensitive), defanging the parser anchor while keeping the original
text human-readable.

P2 (compatibility): pass resolveRuntimeImageSanitization() to imageResultFromFile
in the vision-failure catch fallback. The non-vision screenshot path already
forwards this option (d5cc0d53b7) so configured agents.defaults.imageMaxDimensionPx
takes effect. Without this fix, any provider timeout/error silently bypasses the
sanitization guard and returns a raw full-resolution screenshot.

Regression coverage:
- vision.test.ts: 6 unit cases for neutralizeMediaDirectives (no-op fast path,
  mid-line MEDIA: untouched, line-start defanged, leading-whitespace defanged,
  case-insensitive, multiple directives per blob).
- browser-tool.test.ts: 2 integration cases that drive the full screenshot
  tool execute path:
    - 'neutralizes MEDIA: directives in vision text and does not attach media'
      asserts no line matches /^\s*MEDIA:/i in returned text, secret path text
      is preserved verbatim, details.media is absent, and imageResultFromFile
      is not called on the success path.
    - 'preserves screenshot image sanitization on vision failure fallback'
      mocks describeImageFileWithModel to reject and asserts the fallback
      imageResultFromFile call receives imageSanitization: {maxDimensionPx:1600}
      plus the 'browser screenshot vision failed' extraText.

* fix(browser): apply clawsweeper fallback media fix from PR #84247

* refactor: reuse media image understanding for browser screenshots

* refactor: use structured media delivery

* test: update music completion media instruction expectation

* fix: trim buffered reply directive padding

* test: refresh codex prompt snapshots for message media aliases

---------

Co-authored-by: scotthuang <scotthuang@tencent.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-31 00:00:19 +01:00
Peter Steinberger
3e7f74505c fix(release): harden beta doctor and RTT credential deadlines 2026-05-30 23:54:06 +01:00
Peter Steinberger
38d3d11cbc feat: improve MCP operator workflows
Add MCP server add/configure/login/reload flows plus config/runtime support for enablement, filters, timeouts, OAuth, TLS, and parallel execution hints. Update docs and tests for the expanded MCP operator surface.
2026-05-30 23:51:40 +01:00
Zee Zheng
8be581cbf8 fix(browser): allow inbound media uploads
Allow the browser upload tool to resolve OpenClaw-managed inbound media refs such as `media://inbound/<id>` and sandbox-relative `media/inbound/<id>` while preserving the existing upload-root path contract.

Keep upload-root files ahead of sandbox-relative inbound fallback, reject nested absolute inbound media files, and validate raw `media://` paths before URL normalization so traversal-shaped refs cannot resolve to direct media ids.

Verification:
- `OPENCLAW_VITEST_MAX_WORKERS=1 node scripts/run-vitest.mjs extensions/browser/src/browser/paths.test.ts --reporter=verbose`
- `OPENCLAW_VITEST_MAX_WORKERS=1 node scripts/run-vitest.mjs extensions/browser/src/browser/paths.test.ts --reporter=dot`
- `OPENCLAW_HEAVY_CHECK_LOCK_SCOPE=worktree node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.extensions.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/extensions-test.tsbuildinfo`
- `pnpm lint --threads=8`
- `.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main`
- `git diff --check`
- GitHub PR checks on be08e6c8a8: dependency-guard, check-lint, check-test-types, check-additional-extension-bundled, checks-fast-contracts-plugins-a, checks-fast-contracts-plugins-b all passed.

Fixes #83544.

Co-authored-by: Zee Zheng <zheng.zuo0@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-30 23:49:07 +01:00
Peter Steinberger
d05e4a4bc6 fix(feishu): use full gateway channel runtime 2026-05-30 23:46:04 +01:00
Vincent Koc
0b0edcdf1c fix(scripts): fail gauntlet on missing qa summaries 2026-05-31 00:37:48 +02:00
Peter Steinberger
57c88dd46e chore: remove more unused internal helpers 2026-05-30 23:26:29 +01:00
Peter Steinberger
654de643e4 perf: skip idle channel shutdown enumeration 2026-05-30 23:21:54 +01:00
Vincent Koc
ee2b90b4e2 perf(scripts): prebuild qa runtime assets 2026-05-31 00:17:39 +02:00
Jerry-Xin
f59fc0d477 fix(gateway): strip spurious tool calls on non-tool stops
Treat OpenAI-compatible streaming tool deltas as executable only when the final finish reason is `tool_calls`. This prevents malformed provider streams from triggering spurious tool execution while preserving normal tool-call responses.

Fixes #85161.

Verification:
- Local OpenAI-compatible SSE replay: spurious stop stream `finalToolCalls: 0`; valid tool-call stream `finalToolCalls: 1`.
- `pnpm test src/agents/openai-transport-stream.test.ts src/llm/providers/openai-completions.test.ts -- --reporter=verbose`
- PR CI green on `cdc2fc34753492c862cae99b37f8cf3761d9bbed`.

Co-authored-by: 忻役 <xinyi@mininglamp.com>
Co-authored-by: Jerry-Xin <jerryxin0@gmail.com>
2026-05-30 23:14:16 +01:00
Ted Li
1cab722fe0 fix(ci): ignore fenced headings in proof parser (#87390)
Harden real behavior proof parsing for fenced transcript Markdown. Ref #87341. Thanks @MonkeyLeeT.
2026-05-30 23:14:06 +01:00
Peter Steinberger
4739f0cfe2 chore: remove old unused helpers 2026-05-30 23:13:43 +01:00
Andy Ye
2442e9c178 fix(cron): preserve plugin delivery targets
Preserve plugin-resolved cron delivery targets after target resolution so provider-looking canonical target prefixes are not stripped before outbound delivery.

Adds regression coverage for plugin canonical targets returned directly and via aliases, plus a guard that generic normalized fallback targets still strip the selected prefix.

Fixes #87905

Co-authored-by: Andy Ye <35905412+TurboTheTurtle@users.noreply.github.com>
2026-05-30 23:12:45 +01:00
Peter Steinberger
0ac61072b8 Refactor cron migrations under doctor (#88455)
* refactor: move cron migrations under doctor

* fix: break cron run log parser type cycle
2026-05-30 23:09:09 +01:00
Peter Steinberger
31099ccb1f docs(changelog): refresh 2026.5.30 notes 2026-05-30 23:04:23 +01:00
Peter Steinberger
2d23519c77 fix(agents): preserve generated media fallback routing 2026-05-30 23:03:32 +01:00
Peter Steinberger
bbd2854c45 fix: show chat errors as visible messages
Surface gateway chat failures as visible assistant messages in the Control UI, with regression coverage and Crabbox/WebVNC proof.

(cherry picked from commit 31a46638ad)
2026-05-30 23:03:32 +01:00
Josh Avant
5d3a6909fb fix subagent dm completion delivery (#88182)
(cherry picked from commit 00d87c7b5d)
2026-05-30 23:03:32 +01:00
Peter Steinberger
1e0c9d8174 test(wizard): include tokenjuice optional plugin
(cherry picked from commit dd658474a5)
2026-05-30 23:03:32 +01:00
Peter Steinberger
4c16bd2453 fix(codex-supervisor): satisfy release lint
(cherry picked from commit bac13419a6)
2026-05-30 23:03:32 +01:00
Steven
cd3d960ec5 fix(ui): add agent selector to dreaming tab (#78748)
Fixes #63558.

Adds a Dreaming-tab agent selector and propagates the selected agent through Dreaming status, diary, and diary actions while preserving default-agent fallback when agentId is omitted. Also keeps report Memory Palace cards in the Control UI wiki-preview flow and documents the optional Dreaming agentId gateway parameters.

Verification:
- GitHub CI run 26693682975 passed on 43a2b17243.
- CodeQL Critical Quality run 26693682971 passed.
- CodeQL / Security High run 26693682957 passed.
- Workflow Sanity run 26693682949 passed.
- OpenGrep PR Diff run 26693682947 passed.
- Dependency Guard run 26693682003 passed.
- Real behavior proof run 26693860539 passed.
- git diff --check origin/main...refs/remotes/origin/pr/78748 passed.
- git merge-tree --write-tree origin/main refs/remotes/origin/pr/78748 passed.

Thanks @stevenepalmer.

Co-authored-by: Steven Palmer <6134396+stevenepalmer@users.noreply.github.com>
2026-05-30 22:58:00 +01:00
Peter Steinberger
d93394e29b perf: cache validated session prompt blobs 2026-05-30 22:57:30 +01:00
Peter Steinberger
83dff5855e docs: trim release performance report tail 2026-05-30 22:54:35 +01:00
Peter Steinberger
3402477314 chore: remove unused infra helpers 2026-05-30 22:45:22 +01:00
Peter Steinberger
71b3bc87ca perf: cache serialized session prompt refs 2026-05-30 22:44:11 +01:00
Peter Steinberger
0be3ef5a38 chore: remove unused agent helpers 2026-05-30 22:43:09 +01:00
Peter Steinberger
287687da20 feat: add internal code mode namespaces (#88043)
* feat: add internal code mode namespaces

* test: add code mode namespace live proof

* test: add live code mode Docker repro

* chore: keep code mode docker repro out of package scripts

* fix: break code mode namespace type cycle

* fix: clean code mode namespace ci drift

* fix: route code mode namespaces through tools

* fix: preserve explicit agent global sessions

* docs: explain code mode namespace registry

* test: cap realtime websocket payload

* fix: normalize code mode timeout results

* fix: satisfy code mode timeout lint

* chore: rerun code mode CI

* ci: extend node shard silence watchdog

* test: avoid child process mock deadlocks

* test: fix code mode repro shebang

* fix: scope explicit agent sentinel sessions

* test: preserve child process mock actual loader

* fix: dispatch namespace tools by exact id

* test: satisfy restart execFile mock type
2026-05-30 22:42:57 +01:00
Peter Steinberger
22e4289d3f chore(release): update appcast for 2026.5.28
Promote the Sparkle appcast generated by macOS publish for v2026.5.28.
2026-05-30 22:39:55 +01:00
Vincent Koc
5367ef7bd3 fix(scripts): accept forwarded otel smoke args 2026-05-30 23:37:27 +02:00
Peter Steinberger
598e177e12 chore: remove unused changelog helper 2026-05-30 22:36:09 +01:00
Peter Steinberger
0ed9fb48c4 docs: refresh release performance sweep for 2026.5.28 2026-05-30 22:35:45 +01:00
Jason (Json)
3ea911558c fix: promote serialized tool calls via repair package
Extracts serialized plaintext tool-call parsing, scrubbing, stream normalization, and standalone promotion into the private internal @openclaw/tool-call-repair package.

Provider wrappers and the embedded runner now share one repair path for standalone serialized tool calls, including adjacent text-block splits, while preserving exact argument bytes when already valid. The public plugin SDK payload module remains as the compatibility facade.

Verification:
- pnpm test src/plugin-sdk/provider-stream-shared.test.ts src/plugin-sdk/tool-payload.test.ts src/agents/embedded-agent-runner/run/attempt.tool-call-normalization.test.ts -- --reporter=verbose
- env -u OPENCLAW_TESTBOX pnpm check:changed
- PR CI: all reported checks green/skipped/neutral on ff0b3c0a5c

Refs #86924

Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
2026-05-30 22:34:57 +01:00
Yossi Eliaz
443255461c fix(slack): preserve assistant DM root thread context (#63840)
Preserve Slack Agents & Assistants DM root thread context for tool and subagent replies even when Slack omits or misreports `channel_type`, while leaving non-DM self-thread roots top-level.

Fixes #63659.

Thanks @zozo123.
2026-05-30 22:28:49 +01:00
Vincent Koc
7dde396d4d fix(scripts): accept forwarded watch regression args 2026-05-30 23:20:16 +02:00
Jason (Json)
89975eea24 feat: pass structured provider error signals to hooks
Summary:
- Pass provider status/code/type descriptors through failover hook classification.
- Keep structured provider hook dispatch scoped, while preserving legacy broad message-hook fallback for unresolved custom provider ids.
- Isolate long commands/infra Vitest lanes in fork workers and update config expectations.

Verification:
- node scripts/run-vitest.mjs src/agents/embedded-agent-helpers/errors-provider-structured-signals.test.ts src/agents/failover-error.test.ts
- OPENCLAW_VITEST_MAX_WORKERS=1 node scripts/run-vitest.mjs src/plugins/provider-runtime.test.ts
- node scripts/run-vitest.mjs src/agents/embedded-agent-helpers/errors-provider-structured-signals.test.ts src/agents/embedded-agent-helpers/provider-error-patterns.test.ts src/agents/failover-error.test.ts src/plugins/provider-runtime.test.ts test/vitest-projects-config.test.ts test/vitest-scoped-config.test.ts src/infra/vitest-config.test.ts
- pnpm tsgo:prod
- autoreview --mode branch --base origin/main --no-web-search --thinking low
- GitHub required dependency-guard: pass
- GitHub Real behavior proof: pass
- GitHub broad CI/checks visible on PR: pass

Co-authored-by: Jason (Json) <fuller-stack-dev@users.noreply.github.com>
2026-05-30 22:14:46 +01:00
zhang-guiping
dbd3e10312 fix(ui): filter sidebar recent sessions by selected agent
Fixes #88214.

Control UI dashboard Recent sessions now follows the selected agent, preserves legacy main sessions under stale identity, keeps unknown sessions unscoped, and scopes agent/default session refreshes before the session-list limit. Completed run refreshes now use the run's original session/agent target, global New Chat creates under the selected agent, and the agent switcher preserves last known target sessions across scoped refreshes without resurrecting deleted or archived sessions while accepting newer out-of-scope live rows into the switch cache. Also fixes a current-main lint issue around trusted approval params.

Co-authored-by: 张贵萍0668001030 <zhang.guiping@xydigit.com>
2026-05-30 22:13:37 +01:00
Vincent Koc
8b50cdd151 ci: update remaining Testbox actions 2026-05-30 22:11:51 +01:00
Peter Steinberger
a825b5576b refactor: simplify sqlite cron persistence 2026-05-30 22:11:17 +01:00
summerview1997
76b300babc Fix /acp spawn cwd inheritance for target agent workspaces (#82415)
* Fix ACP spawn cwd inheritance

* Share ACP spawn cwd guard with command path

* Fix ACP spawn cwd typing and temp dir test

* test: stabilize crabbox wrapper provider fixtures

---------

Co-authored-by: Thomas Yao <thomas@local>
2026-05-30 22:11:06 +01:00
Vincent Koc
ada22739be perf(build): skip dts for runtime build profiles 2026-05-30 23:06:25 +02:00
Peter Steinberger
8fe50a2136 build: classify release dependency ownership
Classify release dependency ownership metadata so release evidence no longer reports current root dependencies as missing ownership metadata. Also recognizes command-explainer package-file lookups for tree-sitter-bash.

Verification: jq empty scripts/lib/dependency-ownership.json; node scripts/dependency-ownership-surface-report.mjs --check; node scripts/root-dependency-ownership-audit.mjs --check; targeted Vitest for root dependency ownership and ownership surface reports; git diff --check; autoreview clean; PR CI green including Real behavior proof.
2026-05-30 22:04:54 +01:00
Peter Steinberger
b374505e7a refactor: source model catalog types from core
Source model catalog SDK types from @openclaw/model-catalog-core while preserving released compat fields and sanitized routing normalization.
2026-05-30 22:00:51 +01:00
zhang-guiping
653292901a fix(tui): surface terminal lifecycle errors
Surface terminal TUI lifecycle errors after the chat stream ends, deduplicate delayed chat errors, and allow explicit runnable Vitest config targets to run through the target planner.

Fixes #85782.

Verification:
- pnpm exec oxfmt --check src/tui/tui-event-handlers.ts src/tui/tui-event-handlers.test.ts test/scripts/test-projects.test.ts scripts/test-projects.test-support.mjs src/agents/model-catalog-visibility.test.ts
- node scripts/run-vitest.mjs src/tui/tui-event-handlers.test.ts
- node scripts/run-vitest.mjs src/tui/tui-event-handlers.test.ts src/tui/tui-command-handlers.test.ts test/scripts/test-projects.test.ts src/agents/model-catalog-visibility.test.ts
- git diff --check
- autoreview --mode local: no accepted/actionable findings
- autoreview --mode branch --base origin/main: no accepted/actionable findings
- Required CI check dependency-guard passed

Co-authored-by: 张贵萍0668001030 <zhang.guiping@xydigit.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-05-30 21:59:27 +01:00
Peter Steinberger
3f50485156 perf: cache manifest model suppression resolver 2026-05-30 21:56:38 +01:00
Vincent Koc
9c2744f1e1 test(scripts): require usable memory search in fd repro 2026-05-30 22:48:50 +02:00
brokemac79
3aa460409e fix: route denied exec approval followups to sessions
Routes denied async exec approval followups through the originating main session before using direct external fallback. Keeps strict inline-eval timeout denials fail-closed, while preserving suppression for subagent, cron, and no-session denial cases.

Refs #88167.

Verification:
- git diff --check origin/main...refs/remotes/pr/88417
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
- gh pr checks 88417 --repo openclaw/openclaw --watch=false

Co-authored-by: brokemac79 <martin_cleary@yahoo.co.uk>
2026-05-30 21:45:16 +01:00
Thomas Krohnfuß
48980a0f41 fix(responses): drop orphaned assistant msg_* id when reasoning is dropped (#88019) (#88067)
* fix(responses): drop orphaned assistant msg_* id when reasoning is dropped (#88019)

When an Azure/OpenAI Responses session falls back to a non-Responses model
and later resumes a Responses model, sanitizeSessionHistory drops the
replayable reasoning (rs_*) item via downgradeOpenAIReasoningBlocks. The
paired assistant text block still carried its textSignature (the msg_* id),
so the transport replayed an assistant message item referencing msg_* with
no accompanying rs_* reasoning item. Azure Responses then rejected the next
turn with:

  400 Item 'msg_...' provided without its required 'reasoning' item: 'rs_...'

permanently poisoning the session.

Fix:
- downgradeOpenAIReasoningBlocks now strips the textSignature from a turn's
  text blocks whenever it drops a replayable reasoning item, so the msg_* id
  and its rs_* reasoning are removed together. The transport then falls back
  to a synthetic, unpaired id that Azure accepts.
- Because the synthetic fallback id is derived from the per-message msgIndex,
  multiple id-less text blocks in one assistant turn (e.g. commentary +
  final_answer) would collide on the same id. Make the fallback unique per
  text block in both Responses conversion sites
  (openai-transport-stream.ts and the shared llm provider
  openai-responses-shared.ts).

Tests:
- sanitize-session-history: model-switch path drops the paired msg_* id.
- embedded-agent-helpers: downgrade strips paired text signature(s).
- reasoning-replay: multiple id-less text blocks get distinct item ids.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(responses): preserve phase metadata and guard malformed blocks (#88019)

Address PR review feedback on the orphaned msg_* replay fix:

- Preserve Responses phase metadata: dropping the paired msg_* id when its
  rs_* reasoning is removed previously stripped the entire textSignature,
  which also discarded the phase (commentary/final_answer). Phased text now
  keeps a phase-only signature ({v:1,phase}) so commentary is not replayed
  as user-visible output. Both parseTextSignature copies (shared provider and
  embedded transport) now accept id-less phase-only signatures and fall back
  to a synthetic id while preserving the phase.
- Guard malformed content blocks: the post-drop map no longer dereferences
  contentBlock.type unconditionally, so a corrupted transcript with a
  null/primitive block can still sanitize through a model switch.

Tests:
- sanitize-session-history: phase metadata is preserved while the paired id
  is dropped on a model switch.
- reasoning-replay: id-less phase-only signatures get distinct synthetic ids
  and retain their phase.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-30 21:45:08 +01:00
Ashd.LW.
eb170a0adb fix(agents): extend payload-less session lock grace
Payload-less session write-lock files now get a 30s grace for default/long acquire timeouts and cleanup sweeps, while short acquire timeouts keep 5s recovery. This avoids reclaiming a lock while the owner is suspended between exclusive create and metadata write.

Verified with:
- git diff --check origin/main...HEAD
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main --parallel-tests "node scripts/run-vitest.mjs src/agents/session-write-lock.test.ts"
- gh pr checks 80686 --repo openclaw/openclaw --watch=false

Thanks @wAngByg.
2026-05-30 21:42:57 +01:00
Han Kim
b7232db1b0 test(gateway): avoid brittle shutdown timer assertion
Co-authored-by: Han Kim <han.kim@Bowcaster.local>
Co-authored-by: Peter Steinberger <peter@steipete.me>
2026-05-30 21:39:49 +01:00
Peter Steinberger
a20b2dc740 refactor: extract web content core package (#88346)
Extract web-content shared runtime helpers into packages/web-content-core, move the focused tests with the new package, and split quiet CI shards so the node matrix no longer stalls past the no-output watchdog.\n\nVerification: node scripts/run-vitest.mjs test/scripts/ci-node-test-plan.test.ts test/scripts/run-vitest.test.ts src/infra/restart.test.ts src/infra/os-summary.test.ts src/infra/gateway-processes.test.ts src/infra/inline-option-token.test.ts src/infra/map-size.test.ts src/infra/machine-name.test.ts src/commands/doctor-whatsapp-responsiveness.test.ts; autoreview clean; manual CI https://github.com/openclaw/openclaw/actions/runs/26693962844; dependency guard https://github.com/openclaw/openclaw/actions/runs/26693959937. Admin merge used because optional Mantis Telegram Desktop proof was cancelled after blocking merge outside this PR's required proof.
2026-05-30 21:38:29 +01:00
Feelw00
c6b1fede5a fix(mcp): bound channel bridge pending approvals
Bound MCP channel bridge pending Claude permission and approval maps with TTL sweep and close cleanup.
Also sweep before listing pending approvals so expired requests are not exposed between periodic ticks.

Fixes #71646.
Thanks @Feelw00.
2026-05-30 21:36:50 +01:00
Zee Zheng
c80ec43325 feat(cli): add sessions tail progress view
Adds `openclaw sessions tail` as an operator-facing progress view over session trajectory events, with conservative redaction for prompt text, tool arguments, and tool result bodies. The command supports explicit session keys, store/agent scope, follow mode, relocated trajectory pointer files, and cursor-safe follow across bounded trajectory window rewrites.

Documents the new sessions tail CLI surface in `docs/cli/sessions.md`.

Fixes #83441.

Co-authored-by: zhengzuo0-ai <zheng.zuo0@gmail.com>
2026-05-30 21:29:39 +01:00
Peter Steinberger
b6891d284d docs(changelog): restore 2026.5.28 release credits 2026-05-30 21:29:16 +01:00
Peter Steinberger
ec78a21e0b docs(changelog): require complete release credits 2026-05-30 21:28:11 +01:00
Peter Steinberger
be3af54f98 perf: fast path session store json parsing 2026-05-30 21:22:14 +01:00
Peter Steinberger
3fc0df953c refactor(agents): bind subagent threads in core (#88416)
Move subagent thread binding ownership into core so session-mode spawns prepare channel bindings before launching the child agent. Deprecate the legacy subagent_spawning SDK hook in code, compatibility metadata, diagnostics, and plugin docs; plugin authors should observe subagent_spawned instead.

Verification:
- node scripts/run-vitest.mjs src/agents/sessions-spawn-hooks.test.ts src/agents/subagent-spawn.thread-binding.test.ts src/agents/subagent-spawn.workspace.test.ts src/agents/subagent-spawn.mode-session-diagnostics.test.ts
- node scripts/run-tsgo.mjs -p tsconfig.core.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core.tsbuildinfo
- git diff --check
- .agents/skills/autoreview/scripts/autoreview --mode local
- CI run 26693808952 green, including checks-node-agentic-agents-core and checks-node-agentic-plugin-sdk
2026-05-30 21:19:09 +01:00
Nicolas
4ac90a5b48 fix: skip browser cleanup when browser is disabled
Skip browser lifecycle cleanup when root browser support or the browser plugin entry is disabled, and make the browser maintenance facade respect activation before cached surface use.

Also stabilize the resource-only MCP runtime test by waiting for the async rejection log that CI can observe late.

Verification:
- pnpm test src/plugin-sdk/browser-maintenance.test.ts src/browser-lifecycle-cleanup.test.ts src/auto-reply/reply/session.test.ts src/gateway/server.sessions.reset-cleanup.test.ts src/agents/auth-profiles/usage.test.ts
- pnpm test src/agents/agent-bundle-mcp-runtime.test.ts
- git diff --check
- pnpm build
- autoreview local: no accepted/actionable findings
- GitHub Actions: CI 26693713166, CodeQL 26693713159, CodeQL Critical Quality 26693713157, OpenGrep PR Diff 26693713125, Workflow Sanity 26693713149, Dependency Guard 26693712478

Co-authored-by: Nicolas Van Eenaeme <nicolas@poison.be>
2026-05-30 21:16:47 +01:00
Peter Steinberger
39e987314a perf: skip unnecessary setup auth fallback 2026-05-30 21:16:36 +01:00
Peter Steinberger
427df01d4e ci(release): checkout approval helper 2026-05-30 21:13:19 +01:00
Peter Steinberger
50b7a2ffa1 ci(release): allow direct publish recovery 2026-05-30 21:13:19 +01:00
Vincent Koc
b93ed3f93f test(scripts): expose kitchen sink command RSS 2026-05-30 22:10:25 +02:00
Peter Steinberger
a2b2c4a76c refactor(msteams): persist conversation and poll stores in sqlite
Move MSTeams conversation and poll plugin-local stores to plugin-state SQLite. Legacy JSON stores import once without overwriting existing SQLite state; conversation and poll IDs are hashed for plugin-state keys; poll votes are sharded with bounded row-cap headroom and prune cleanup; MSTeams docs now describe SQLite storage. SSO and delegated token stores are unchanged. Verified with focused MSTeams tests, docs sanity, autoreview, Testbox check:changed, and green PR CI.
2026-05-30 21:08:39 +01:00
Feelw00
a9a86f788b fix(agents): dedupe subagent browser session cleanup
Deduplicate the browser lifecycle cleanup wrapper for embedded subagent completions while preserving retire and announce finalization for duplicate callers.\n\nAdds regression coverage for parallel completion callers and the held-first-cleanup duplicate-tail path.\n\nFixes #68668.\n\nCo-authored-by: Feelw00 <dhrtn1006@naver.com>
2026-05-30 21:04:37 +01:00
keshavbotagent
371a8abe9d fix(build): avoid stale agent-core dts warnings (#87915)
* fix(build): avoid stale agent-core dts warnings

* test(secrets): secure plugin entrypoint fixtures

* fix(agent-core): normalize compaction summary timestamps

* test(secrets): secure platform preset fixture

* fix(build): preserve tracked package dts on skip builds

* test(secrets): secure platform preset resolver fixture

* fix(build): keep declarations during skip dts clean

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-30 21:03:49 +01:00
Peter Steinberger
005da57957 Move cron persistence to SQLite (#88285)
* refactor: move cron persistence to sqlite

* fix: repair sqlite cron migration regressions

* fix: move cron legacy migration to doctor

* test: align cron sqlite migration fixtures

* test: fix cron sqlite rebase gates

* test: align cron sqlite runtime tests

* test: fix doctor e2e migration mock

* test: fix doctor shard e2e isolation

* test: fix infra child-process mocks
2026-05-30 21:03:41 +01:00
brokemac79
d11e82aeea fix(ui): keep selected chat model visible after session switch
Fixes #86597. Thanks @brokemac79.
2026-05-30 20:53:47 +01:00
Coder
adcac404e1 fix(llm): repair invalid streaming unicode escapes
Repair invalid \u escapes during streaming JSON parsing without changing valid Unicode escapes. Split oversized node CI doctor/infra shards and fix the restart test mock deadlock so PR CI stays under the no-output threshold.\n\nCo-authored-by: Coder <83845889+coder999999999@users.noreply.github.com>
2026-05-30 20:53:26 +01:00
Vincent Koc
eb5e80f58a ci: update Blacksmith Testbox actions 2026-05-30 20:51:31 +01:00
Peter Steinberger
5891cfec3e refactor: move model catalog normalization into core package
Move model catalog normalization and package-owned catalog schema/types into model-catalog-core while keeping public plugin SDK model catalog declarations on the existing SDK surface. Verified focused tests, package-boundary compile, full build, changed gate, declaration leak grep, CI, and autoreview.
2026-05-30 20:51:11 +01:00
Abner Shang
961691def2 fix(codex): keep app-server continuation turns alive
Keep Codex app-server continuation turns alive after post-tool, raw assistant, and progress notifications, and reschedule continuation idle watches when shorter progress timeouts apply.

Add regression coverage for the plugin-sdk child_process mock helper deadlock that blocked CI shards on this PR.

Co-authored-by: abnershang <abner.shang@gmail.com>
2026-05-30 20:41:04 +01:00
Vincent Koc
2780f540f8 test(agents): wait for MCP method-not-found log 2026-05-30 20:39:52 +01:00
Vincent Koc
37058ad75a fix(scripts): quiet minimal runtime asset copies
Stop minimal cliStartup and gatewayWatch builds from copying generated plugin static assets they intentionally do not build.\n\nVerified with focused Vitest, autoreview, AWS Crabbox startup-memory proof, and AWS Crabbox changed gate run_bd9ea01e6a12 plus rebased changed gate run_bd9ea01e6a12.
2026-05-30 20:38:19 +01:00
Peter Steinberger
37c6e2dfa0 ci: skip codeql network shard for test-only changes 2026-05-30 20:29:19 +01:00
Shakker
473993f73a fix: remove redundant unknown union 2026-05-30 20:28:29 +01:00
Peter Steinberger
e24a9c5457 ci: keep harness changes on fast checks (#88429) 2026-05-30 20:27:59 +01:00
Shakker
d9c0d09f1a chore: remove inert skill workshop package 2026-05-30 20:15:31 +01:00
Peter Steinberger
0c7ab411e5 fix(auth): bound oauth mirror expiry 2026-05-30 15:11:14 -04:00
Alix-007
5811693c7f fix(export-html): guard msg.content and result.content filter/iteration paths against non-array values (#88271)
* fix(export-html): guard all msg.content and result.content filter/iteration paths

Three call sites in the export HTML template called `.filter()` or iterated
with `for...of` directly on `msg.content` or `result.content` without first
checking `Array.isArray`. When a transcript message row carries a non-array
content value (null, undefined, or any scalar), those paths throw:

  TypeError: msg.content.filter is not a function

Fix: normalize with `Array.isArray(x) ? x : []` before every unguarded
filter and iteration on `msg.content` (computeStats stats path and the
renderEntry assistant render loops) and `result.content` (renderToolCall
text/image accessors).

Regression test added: renderTemplate resolves without throwing for assistant
messages with null, undefined, string, and numeric content values.

Closes #88255

* fix(export-html): guard user message text extraction path against non-array content

The user-message render path in the export HTML template extracted text with
`content.filter(...)` without checking whether `content` is an array. A
persisted user message row with null, undefined, or any non-string scalar
content crashed during export with the same TypeError class as the assistant
path.

Fix: normalize the ternary so a non-string, non-array value falls through to
an empty string rather than calling `.filter` on it.

Regression test added for null, undefined, and numeric user message content.

Addresses feedback from ClawSweeper review on #88271.

* fix(export-html): preserve string content guards

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-30 20:10:43 +01:00
Peter Steinberger
445ff22018 fix(agents): bound auth health expiry 2026-05-30 15:09:37 -04:00
Peter Steinberger
602364f1c7 ci: stabilize changed checks 2026-05-30 20:07:38 +01:00
Peter Steinberger
c73e8eedf4 fix(agents): bound discovery auth expiry 2026-05-30 15:07:04 -04:00
Shakker
dcc329ac09 chore: keep skill workshop package manifest inert 2026-05-30 20:04:52 +01:00
Shakker
515d4ffc21 fix: refresh skill workshop CI expectations 2026-05-30 20:04:52 +01:00
Shakker
28290a496f fix: allow concise skill update descriptions 2026-05-30 20:04:52 +01:00
Shakker
3cd368edec fix: approve final skill workshop tool params 2026-05-30 20:04:52 +01:00
Shakker
908fc35b97 fix: preserve trusted policy checks for skill workshop 2026-05-30 20:04:52 +01:00
Shakker
d6d1cc2a3e fix: serialize skill proposal creation limits 2026-05-30 20:04:52 +01:00
Shakker
41044a207c fix: serialize skill proposal lifecycle mutations 2026-05-30 20:04:52 +01:00
Shakker
7d19f89094 fix: harden skill workshop proposal results 2026-05-30 20:04:52 +01:00
Shakker
43e4b9dc1c fix: keep autonomous skill capture opt-in 2026-05-30 20:04:52 +01:00
Shakker
77c6bee421 fix: refresh skill workshop generated surfaces 2026-05-30 20:04:52 +01:00
Shakker
0b49710e8d fix: preserve auto-captured skill updates 2026-05-30 20:04:52 +01:00
Shakker
3a9e7dfa1a fix: bound skill workshop descriptions 2026-05-30 20:04:52 +01:00
Shakker
e4905ce4c9 fix: enforce skill workshop proposal bounds 2026-05-30 20:04:52 +01:00
Shakker
131e662924 fix: scan skill proposal prompt content 2026-05-30 20:04:52 +01:00
Shakker
7051bf16f0 fix: align skill proposal revise validation 2026-05-30 20:04:52 +01:00
Shakker
6eb6730137 refactor: move skill research capture logic 2026-05-30 20:04:52 +01:00
Shakker
2383cfd303 refactor: rename skill workshop agent tool 2026-05-30 20:04:52 +01:00
Shakker
c09e1efe99 fix: clean up skill workshop lint issues 2026-05-30 20:04:52 +01:00
Shakker
308fdbe7fb refactor: remove skill workshop plugin package 2026-05-30 20:04:52 +01:00
Shakker
c5af09e378 refactor: route agent end side effects through harness 2026-05-30 20:04:52 +01:00
Shakker
3037646d22 feat: add skill workshop runtime policy 2026-05-30 20:04:52 +01:00
Shakker
3ea82adf97 fix: show skill proposal support files on inspect 2026-05-30 20:04:52 +01:00
Shakker
bc6d570659 fix: reject non-text skill proposal files 2026-05-30 20:04:52 +01:00
Shakker
f7729028ae fix: guard skill proposal apply writes 2026-05-30 20:04:52 +01:00
Shakker
11d6ce15e8 fix: harden skill proposal boundaries 2026-05-30 20:04:52 +01:00
Shakker
897a7efe15 fix: preserve skill proposal target state 2026-05-30 20:04:52 +01:00
Shakker
fafa4c8b65 fix: scope skill workshop proposal access 2026-05-30 20:04:52 +01:00
Shakker
186182fe9e feat: let skill research manage proposal lifecycle 2026-05-30 20:04:52 +01:00
Shakker
e5455b61c3 feat: let skill research manage proposal discovery 2026-05-30 20:04:52 +01:00
Shakker
e89417d77b fix: keep skill research available to agents 2026-05-30 20:04:52 +01:00
Shakker
e9b0a5f69e feat: revise pending skill proposals 2026-05-30 20:04:52 +01:00
Shakker
339e212c85 fix: expose skill proposal gateway methods 2026-05-30 20:04:52 +01:00
Shakker
199cdc1052 fix: enforce canonical workshop skill names 2026-05-30 20:04:52 +01:00
Shakker
ab0613c9d3 feat: support skill proposal files 2026-05-30 20:04:52 +01:00
Shakker
91ba5fd4fe fix: store skill workshop proposals in state 2026-05-30 20:04:52 +01:00
Shakker
9da7498d31 fix: satisfy skill workshop lint 2026-05-30 20:04:52 +01:00
Shakker
67298c4bd8 fix: satisfy skill workshop changed checks 2026-05-30 20:04:52 +01:00
Shakker
9417a3f39f fix: rebuild corrupt skill proposal manifests 2026-05-30 20:04:52 +01:00
Shakker
1609fcaff3 docs: document skill workshop proposals 2026-05-30 20:04:52 +01:00
Shakker
5205b94d84 feat: expose skill workshop gateway methods 2026-05-30 20:04:52 +01:00
Shakker
7f48ee1e57 feat: add skill research proposal tool 2026-05-30 20:04:52 +01:00
Shakker
c4be8d8730 feat: add skill workshop cli commands 2026-05-30 20:04:52 +01:00
Shakker
bc1c3701c4 feat: add skill workshop proposal store 2026-05-30 20:04:52 +01:00
Peter Steinberger
4e8b74568f refactor: move model catalog refs into core package
Move model catalog ref helpers into @openclaw/model-catalog-core/model-catalog-refs and update internal callers/package-boundary aliases. Also fix the timestamp predicate typing that blocked prod type checks on current main.
2026-05-30 20:04:16 +01:00
Peter Steinberger
b80dcbd650 fix(plugin-sdk): bound copilot token expiry 2026-05-30 15:04:03 -04:00
Peter Steinberger
417aba7b9b fix(infra): bound session delivery recovery deadline 2026-05-30 15:02:02 -04:00
Peter Steinberger
ed63523db9 test(release): expect public latest in installer smoke 2026-05-30 20:01:22 +01:00
Peter Steinberger
677f7c80dc fix(plugin-sdk): bound oauth result expiry 2026-05-30 14:59:59 -04:00
Vincent Koc
231d0b28bd fix(agents): harden message dts and block timestamps 2026-05-30 20:58:21 +02:00
Peter Steinberger
979907e004 fix(outbound): bound delivery recovery deadline 2026-05-30 14:57:47 -04:00
Peter Steinberger
9eb17a0277 fix(shared): bound epoch expiry helpers 2026-05-30 14:55:37 -04:00
Peter Steinberger
06e0fd3347 fix(media): bound provider operation deadlines 2026-05-30 14:54:03 -04:00
Peter Steinberger
51cceaf70c fix(agents): bound run drain deadlines 2026-05-30 14:51:59 -04:00
Peter Steinberger
471164afbd fix(github-copilot): bound device code expiry 2026-05-30 14:49:34 -04:00
Peter Steinberger
99ce71ddbb feat: improve MCP operability
Summary:
- Add MCP status, probe, and projected-tools CLI surfaces.
- Add per-server MCP tool filters plus resource/prompt utility projection.
- Harden MCP runtime discovery, listChanged invalidation, request-failure backoff, and metadata sanitization.
- Preserve current main type health by narrowing the shared future timestamp guard.

Verification:
- pnpm test src/shared/number-coercion.test.ts src/agents/auth-profiles/usage.test.ts src/cli/mcp-cli.test.ts src/agents/agent-bundle-mcp-runtime.test.ts src/agents/agent-bundle-mcp-tools.materialize.test.ts -- --reporter=verbose
- pnpm lint
- pnpm tsgo:prod
- pnpm build
- git diff --check origin/main...HEAD
- GitHub Actions: dependency-guard, real behavior proof, security high MCP boundary, build/lint/types/guards/docs, gateway/plugin/agent shards green on PR head.

Known proof gap:
- Existing checks-node-agentic-commands-doctor no-output watchdog reproduced locally outside touched paths.
2026-05-30 19:48:52 +01:00
Peter Steinberger
9cb9851bf8 fix(models): bound pasted token expiry 2026-05-30 14:47:41 -04:00
Peter Steinberger
2b31c02163 fix(plugins): bound scheduled turn delays 2026-05-30 14:44:24 -04:00
Coder
878e433d81 fix(skill-creator): sort .skill entries deterministically
Fixes #37748.

Sort skill package archive entries by relative POSIX archive name so generated `.skill` bundles are reproducible regardless of filesystem traversal order.

Verification:
- `PYTHONDONTWRITEBYTECODE=1 python3 skills/skill-creator/scripts/test_package_skill.py`
- `git diff --check origin/main...HEAD`
- GitHub CI run 26690938925 on `43a0fdf7175f33a5c74bc7ff92723ebf5efc4df9`: all checks passed except repeated unrelated no-output timeouts in `checks-node-agentic-commands-doctor` and `checks-node-core-runtime-infra-state` after visible tests passed.
2026-05-30 19:42:55 +01:00
Peter Steinberger
dfbed5053a fix(qqbot): bound reminder schedule time 2026-05-30 14:41:39 -04:00
Peter Steinberger
caac9733a7 fix(memory): bound qmd embed backoff 2026-05-30 14:39:33 -04:00
Peter Steinberger
6399b6a445 fix(discord): bound timeout member expiry 2026-05-30 14:34:40 -04:00
Peter Steinberger
472606de9b fix(qqbot): skip token cache on invalid clock 2026-05-30 14:33:04 -04:00
Peter Steinberger
177496552b fix(infra): bound device bootstrap expiry 2026-05-30 14:31:30 -04:00
Peter Steinberger
e0248fc11f fix(cron): bound relative at timestamps 2026-05-30 14:29:39 -04:00
Peter Steinberger
6a753ade78 fix(crestodian): bound rescue approval expiry 2026-05-30 14:28:25 -04:00
Peter Steinberger
53812bd8aa fix(agents): bound codex cli fallback expiry 2026-05-30 14:26:17 -04:00
Lellansin Huang
fe3c3ac5cd fix(gateway): forward stop sequences across providers
Forward OpenAI-compatible stop sequences from gateway chat completions through the agent runner into provider transports.

The gateway now normalizes stop into sampling extras, agent transports pass it into the shared stream options, and OpenAI, Anthropic, Mistral, Google, and Vertex-backed simple providers map it to their native request fields. Provider/gateway/agent coverage plus Crabbox live gateway proof verify valid stop dispatch and invalid stop rejection.

Refs #87920
2026-05-30 19:24:21 +01:00
Peter Steinberger
5435b453ca feat: expand workboard orchestration metadata (#88408) 2026-05-30 19:22:19 +01:00
Peter Steinberger
abc26b072b fix(discord): bound rest rate-limit deadlines 2026-05-30 14:22:16 -04:00
Jiatai Wang
64533bab65 fix(agents): show exec target node in tool display
Show the remote node name in exec tool transparency details when an exec call targets `host=node`, while ignoring stray `node` values for gateway, sandbox, and auto-host calls.

Covers node-only, cwd+node, absent-node, and non-node-host regression cases in the tool display tests.

Fixes #77719.

Co-authored-by: JiataiWang <wangjiatai@proton.me>
2026-05-30 19:19:17 +01:00
Peter Steinberger
7d4bf8f285 fix(telegram): bound transport cooldown expiry 2026-05-30 14:16:57 -04:00
Peter Steinberger
bdb0fde0ea test(release): harden live release checks 2026-05-30 19:14:27 +01:00
Peter Steinberger
926a165a52 fix(anthropic): bound setup token expiry 2026-05-30 14:14:13 -04:00
Peter Steinberger
70b6fdd149 fix(bedrock): bound mantle runtime token expiry 2026-05-30 14:09:59 -04:00
Peter Steinberger
9ad7f5bbde fix(agents): bound sqlite cache expiry 2026-05-30 14:07:32 -04:00
Peter Steinberger
1ee751ddb1 fix(agents): bound google prompt cache expiry 2026-05-30 14:02:50 -04:00
Peter Steinberger
30e3ca08a5 fix(agents): bound auth profile block expiry 2026-05-30 14:00:46 -04:00
Peter Steinberger
1f6c1eacf0 fix(telegram): bound error cooldown expiry 2026-05-30 13:59:06 -04:00
Peter Steinberger
8654353be8 fix(discord): bound component registry expiry 2026-05-30 13:57:13 -04:00
Peter Steinberger
c5aa3ff02f fix(msteams): bound delegated token probe expiry 2026-05-30 13:54:56 -04:00
Peter Steinberger
5fde637ba8 fix(codex): bound app inventory cache expiry 2026-05-30 13:53:13 -04:00
guanbear
044f5a814e Expose subagent resolved model metadata (#80037)
Co-authored-by: guanbear <guanbear@macmini.bearhome>
2026-05-30 18:52:21 +01:00
Peter Steinberger
3ae521745e fix(voice-call): bound webhook replay cache expiry 2026-05-30 13:51:12 -04:00
Peter Steinberger
f89f5d930f fix(gateway): bound system run event expiry 2026-05-30 13:49:03 -04:00
Vincent Koc
13c77f00c3 fix(agents): classify code mode deadline interrupts 2026-05-30 18:47:42 +01:00
chuanchuan
3b8ab4e112 fix(feishu): stream plain replies as cards
Feishu `channels.feishu.streaming=true` now streams ordinary assistant replies through CardKit in auto mode, while keeping tool-summary delivery on the existing message path.

Also discards stale partial previews when final delivery intentionally suppresses text for voice media or duplicate final text, and preserves streamed partial text for regular media-only finals.

Verification:
- `node scripts/run-vitest.mjs run extensions/feishu/src/reply-dispatcher.test.ts`
- `pnpm tsgo:extensions`
- `pnpm test:extensions:package-boundary:compile`
- `pnpm exec oxfmt --check extensions/feishu/src/reply-dispatcher.ts extensions/feishu/src/reply-dispatcher.test.ts extensions/feishu/src/streaming-card.ts`
- `git diff --check`
- `.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main`
- GitHub PR checks on run 26689677607 passed except repeated unrelated broad Vitest no-output timeouts in `checks-node-agentic-commands-doctor` and `checks-node-core-runtime-infra-state`.

Co-authored-by: 传妈 <chuanmother@chuanMac-Mini.local>
2026-05-30 18:47:03 +01:00
Peter Steinberger
ca4a12381a fix(gateway): bound chat abort expiry registration 2026-05-30 13:46:16 -04:00
Steven
86e33d6985 fix(models): preserve exact provider refs before aliases
Fixes #88218.

Preserves exact configured provider/model defaults before bare alias target reverse matches, while retaining slash-form aliases and auth-profile alias behavior.

Co-authored-by: Steven Palmer <palmer.e.steven@gmail.com>
2026-05-30 18:46:11 +01:00
Peter Steinberger
9ef699fedc fix(gateway): bound maintenance run expiry checks 2026-05-30 13:43:21 -04:00
Peter Steinberger
912a276ca1 fix(gateway): bound talk handoff expiry 2026-05-30 13:41:14 -04:00
Brian
6f20f29688 fix(discord): carry reply typing feedback through queue
Carry Discord reply typing feedback through preflight, queued dispatch, and cleanup so delayed accepted replies keep typing alive at the actual dispatch target without duplicate keepalives. Adds focused Discord queue/process policy coverage and stronger lifecycle invariant comments.
2026-05-30 18:39:39 +01:00
Merlin
b6d253eefb fix(discord): omit undefined component registry fields
Prunes undefined Discord component and modal registry metadata before persisting it so SQLite-backed plugin state never receives JSON-incompatible undefined values. Adds direct regression coverage for undefined own properties on component, modal, and nested field entries.
2026-05-30 18:39:26 +01:00
Peter Steinberger
0a87f6e4ad fix(gateway): bound node pending work expiry 2026-05-30 13:38:54 -04:00
Ashd.LW.
bc77f7a00a fix(gateway): explain ignored restart signal
Add actionable operator guidance when an unauthorized SIGUSR1 gateway restart is ignored because unmanaged restart is disabled.

The change is log-only: restart authorization and scheduling semantics are unchanged, and the existing run-loop test now asserts both the reason warning and the recovery hint.

Refs #79577
Refs #78110
Refs #82433

Co-authored-by: wAngByg <281221101+wAngByg@users.noreply.github.com>
2026-05-30 18:38:35 +01:00
ToToKr
9e3d5310cc fix(media): dedupe duplicate inbound media path urls
Dedupe prompt-side inbound media note suffixes when sanitized MediaPath and MediaUrl render to the same value, while preserving genuinely distinct remote URLs.\n\nFixes #47587.\nThanks @MoerAI for the patch and @yzjJosh for the report.
2026-05-30 18:37:42 +01:00
Peter Steinberger
4d9366fecb fix(gateway): bound plugin node capability expiry 2026-05-30 13:35:43 -04:00
Sebastien Tardif
1c9851e115 fix(install): show npm install progress without gum
Show the same Installing OpenClaw package progress line in the no-gum npm install fallback before redirecting npm output to the temp log.

Fixes #82305

Co-authored-by: Sebastien Tardif <sebtardif@ncf.ca>
2026-05-30 18:35:32 +01:00
Peter Steinberger
a4f62400a7 fix(commitments): bound terminal failure cooldown expiry 2026-05-30 13:33:06 -04:00
吴杨帆
8d3fe21b53 test(tasks): cover task domain view mappers (#86755)
Adds focused coverage for task-domain view mapper DTO contracts, including summary cloning, task run/detail mapping, flow view/detail mapping, and implicit summary computation.

Test-only PR. Verified with git diff --check and PNPM_CONFIG_VERIFY_DEPS_BEFORE_RUN=false pnpm test src/tasks/task-domain-views.test.ts on the current-main merge result.

Thanks @leno23.

Co-authored-by: wuyangfan <yangfan.wu@succaiss.com>
2026-05-30 18:30:36 +01:00
Peter Steinberger
becd45325b fix(imessage): bound private api negative cache expiry 2026-05-30 13:28:17 -04:00
Peter Steinberger
84a965a1a2 refactor(matrix): move ephemeral state to plugin sqlite (#88387)
* refactor(matrix): persist ephemeral state in plugin sqlite

* test(channels): wire matrix contract plugin state
2026-05-30 18:26:29 +01:00
Peter Steinberger
f4d461bbff fix(imessage): bound approval reaction poll expiry 2026-05-30 13:25:45 -04:00
Peter Steinberger
cbad1b6e69 fix(agents): bound exec followup handoff expiry 2026-05-30 13:23:03 -04:00
Peter Steinberger
f4cd5e4050 fix(sandbox): bound novnc observer token expiry 2026-05-30 13:21:26 -04:00
Peter Steinberger
0e7773d1a6 test(release): wait for live probe cleanup 2026-05-30 18:21:01 +01:00
Peter Steinberger
d8e7734d27 fix(agents): bound exec approval request expiry 2026-05-30 13:19:42 -04:00
Peter Steinberger
da7fb64aa4 fix(google): bound realtime browser session expiry 2026-05-30 13:16:22 -04:00
Peter Steinberger
3fffb34ba0 fix(msteams): bound delegated token expiry 2026-05-30 13:13:56 -04:00
Peter Steinberger
0dd67e2f25 fix(workboard): bound claim expiry checks 2026-05-30 13:11:14 -04:00
Peter Steinberger
4df27b9626 fix(browser): bound armed dialog expiry 2026-05-30 13:08:52 -04:00
Peter Steinberger
e708a872a1 fix(commands): bound private approval route expiry 2026-05-30 13:06:29 -04:00
zhang-guiping
2dacc6da28 fix(agents): hide sessions_send alias normalization
Co-authored-by: 张贵萍0668001030 <zhang.guiping@xydigit.com>
2026-05-30 18:06:22 +01:00
Peter Steinberger
9660e42fe2 fix(plugin-state): bound ttl expiry writes 2026-05-30 13:03:24 -04:00
Peter Steinberger
522da25932 fix(skills): bound upload expiry checks 2026-05-30 13:00:52 -04:00
Peter Steinberger
d44621b544 fix(exec): bound approval pending expiry 2026-05-30 12:58:59 -04:00
Peter Steinberger
6fe0539992 test(release): skip unavailable anthropic live models 2026-05-30 17:58:01 +01:00
Peter Steinberger
283238fd77 fix(matrix): bound allowlist store cache expiry 2026-05-30 12:56:54 -04:00
Peter Steinberger
5568ecc7aa fix(discord): bound unbound webhook echo expiry 2026-05-30 12:54:25 -04:00
Peter Steinberger
743d5378d2 fix(zalouser): bound group context cache expiry 2026-05-30 12:52:24 -04:00
史启明(QimingShi)
63a3676d3c fix(tui): distinguish /new and /reset descriptions
Fixes #49517.

Updates the TUI command catalog so /new describes spawning an isolated session while /reset describes resetting the current session. Adds a focused regression test for the two descriptions.

Co-authored-by: KhanCold <119404710+KhanCold@users.noreply.github.com>
2026-05-30 17:50:14 +01:00
Peter Steinberger
2a39c217c8 fix(voice-call): bound realtime stream token expiry 2026-05-30 12:49:36 -04:00
NianJiu
a2fc4ca7ad feat(ui): add collapsible recent sessions section
Adds a persisted collapse state for the Control UI Recent sessions sidebar group, including storage and browser coverage.

Also narrows gateway run miss cache expiry typing so the rebased branch stays clean against current main.

Closes #85510

Co-authored-by: NianJiuZst <3235467914@qq.com>
2026-05-30 17:48:29 +01:00
Peter Steinberger
8eeaa45729 refactor: route model catalog imports to core package
Route internal model catalog imports to the extracted @openclaw/model-catalog-core package and delete obsolete internal facades.

Keep public SDK declarations self-contained by wrapping core helpers at public boundaries instead of leaking private package imports.

Verification:
- pnpm test src/plugins/contracts/model-catalog-core-imports.test.ts src/plugins/sdk-alias.test.ts packages/model-catalog-core/src/configured-model-refs.test.ts packages/model-catalog-core/src/provider-model-id-normalize.test.ts packages/model-catalog-core/src/provider-model-id-normalization.test.ts src/config/config.model-ref-validation.test.ts src/agents/model-selection.test.ts src/plugin-sdk/provider-model-shared.test.ts -- --reporter=verbose
- pnpm check:test-types
- pnpm test:extensions:package-boundary:compile
- pnpm build
- rg "@openclaw/model-catalog-core" dist/plugin-sdk packages/plugin-sdk/dist -n --glob '*.d.ts' || true
- git diff --check
- autoreview clean after fix

CI note: merged with admin override because checks-node-agentic-commands-doctor and checks-node-core-runtime-infra-state failed twice with exit 143/no-output watchdog termination after prior passing test output, while relevant local proof and the rest of CI were green.
2026-05-30 17:48:18 +01:00
Vincent Koc
4d13055ca5 fix(sessions): repair prompt blobs on fast updates 2026-05-30 17:47:07 +01:00
Peter Steinberger
bfceffa2f7 fix(qqbot): bound upload cache expiry 2026-05-30 12:46:56 -04:00
Peter Steinberger
031583e8f5 fix(gateway): bound exec approval expiry 2026-05-30 12:44:39 -04:00
Vincent Koc
2ccbc673df fix(scripts): prebuild gateway cpu private qa artifacts 2026-05-30 18:42:17 +02:00
Peter Steinberger
11b5728faa fix(agents): bound code mode snapshot expiry 2026-05-30 12:42:07 -04:00
samzong
4decdf6245 [Fix] Deliver restart recovery replies (#86089)
* fix(agents): deliver restart recovery replies

* fix(auto-reply): import session entry updater

* test(auto-reply): use current embedded agent mock

* test(feishu): refresh typed account fixture

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-30 17:39:43 +01:00
Peter Steinberger
ac0fb976c8 fix(feishu): bound card action token expiry 2026-05-30 12:37:24 -04:00
Vincent Koc
1de9f99ea8 fix(ci): repair current test type fixtures 2026-05-30 17:35:02 +01:00
Peter Steinberger
60f8e18372 fix(nvidia): bound featured model cache expiry 2026-05-30 12:34:53 -04:00
Peter Steinberger
e52b4bce01 fix(bedrock): bound discovery cache expiry 2026-05-30 12:33:07 -04:00
mushuiyu_xydt
f93a558892 fix(plugins): ignore helper files in extension roots
Fixes #88198.

Ignore top-level helper scripts in auto-discovered global/workspace extension roots so they do not become manifestless plugin candidates during config validation. Standalone plugin files remain supported when explicitly configured through `plugins.load.paths`, and docs now call out the supported path.

Verification:
- `node scripts/run-vitest.mjs src/plugins/discovery.test.ts src/config/config.plugin-validation.test.ts`
- `node scripts/run-oxlint.mjs src/plugins/discovery.ts src/plugins/discovery.test.ts src/config/config.plugin-validation.test.ts`
- `git diff --check`
- GitHub CI green at `93073bfa85ee294e644c623881ba59ba71d90975`
- `.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main`

Thanks @mushuiyu886 for the fix and @mmhzlrj for the report.
2026-05-30 17:31:53 +01:00
Peter Steinberger
5ba3505fed fix(bedrock): bound mantle iam token expiry 2026-05-30 12:31:08 -04:00
Peter Steinberger
18e7d28b21 perf(gateway): reuse stable turn metadata 2026-05-30 17:30:47 +01:00
Peter Steinberger
02ca283716 fix(outbound): bound current conversation expiry 2026-05-30 12:27:26 -04:00
Peter Steinberger
4f0e3cb621 fix(plugin-sdk): bound live catalog cache expiry 2026-05-30 12:25:14 -04:00
Martin Kessler
73a69d9e64 fix(outbound): pack newline-mode paragraphs up to limit
Pack newline-mode outbound paragraphs up to the configured text limit instead of sending one message per blank-line-separated paragraph. Preserves markdown fence guardrails and adds focused chunking plus outbound delivery regressions.\n\nVerified: autoreview clean; node scripts/run-vitest.mjs src/auto-reply/chunk.test.ts src/infra/outbound/deliver.test.ts; git diff --check origin/main...HEAD.\n\nThanks @kesslerio.
2026-05-30 17:24:57 +01:00
Peter Steinberger
b1911a7cd3 fix(gateway): bound run session miss cache expiry 2026-05-30 12:22:24 -04:00
Peter Steinberger
450642a897 fix(agents): bound native permission approval expiry 2026-05-30 12:20:29 -04:00
Vincent Koc
f7a1903bfc fix(discord): avoid private test session intersection 2026-05-30 17:18:51 +01:00
Peter Steinberger
61cf22f147 fix(agents): bound native hook relay expiry 2026-05-30 12:17:36 -04:00
Peter Steinberger
55505776fb fix(gateway): bound transcription relay session expiry 2026-05-30 12:15:06 -04:00
brokemac79
3c91928bae fix(codex): refresh stale managed runtime plugin
Refresh stale managed Codex runtime plugin installs during doctor repair and restore Codex status usage attribution. Thanks @brokemac79.
2026-05-30 17:15:04 +01:00
Peter Steinberger
6ac7564918 fix(gateway): bound realtime relay session expiry 2026-05-30 12:13:10 -04:00
Peter Steinberger
23e1aac9b2 fix(feishu): bound sender name cache expiry 2026-05-30 12:10:19 -04:00
Peter Steinberger
c65af78853 fix(discord): bound realtime wake followup expiry 2026-05-30 12:06:57 -04:00
Vincent Koc
4155ac1c0d fix(scripts): make kitchen sink rpc help inert 2026-05-30 18:04:44 +02:00
Peter Steinberger
cfe5544b30 fix(qqbot): honor legacy c2c stream progress 2026-05-30 17:02:41 +01:00
Peter Steinberger
d7b901a1e7 fix(discord): bound speaker context cache expiry 2026-05-30 12:02:18 -04:00
Peter Steinberger
5225a8c644 fix(gateway): bound config schema cache expiry 2026-05-30 12:00:37 -04:00
Peter Steinberger
fc50f949d4 Add per-agent SQLite cache store (#88349)
* feat: add per-agent sqlite cache store

* fix: preserve sqlite cache adapter scope

* chore: mark sqlite cache scaffold intentional
2026-05-30 17:00:24 +01:00
samzong
f6b40861f7 fix(qqbot): deliver partial tool progress
Fixes #66509.

QQBot now sends text-only tool progress immediately when partial streaming is enabled instead of buffering it until a fallback timer that is cleared by the final block. Immediate progress uses QQ plain-text sends so markdown-enabled accounts do not reinterpret media-like progress text, while streaming-off behavior remains final-only.

Thanks @gabrielduartesignart for the report.

Co-authored-by: samzong <samzong.lu@gmail.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-05-30 17:00:09 +01:00
Peter Steinberger
f491d420f7 fix(tailscale): bound whois cache expiry 2026-05-30 11:58:07 -04:00
Peter Steinberger
ef0882e17e fix(google): bound gemini oauth token expiry 2026-05-30 11:55:02 -04:00
Peter Steinberger
697bafa9c9 fix(google): bound vertex adc token cache expiry 2026-05-30 11:52:19 -04:00
Peter Steinberger
77761f4a3e fix(msteams): bound parent thread cache expiry 2026-05-30 11:49:47 -04:00
Peter Steinberger
0e2694ff47 fix(msteams): bound team id cache expiry 2026-05-30 11:47:00 -04:00
Peter Steinberger
5eb71927b7 fix(whatsapp): bound group metadata cache expiry 2026-05-30 11:45:05 -04:00
Vincent Koc
cbd8049b9f fix(scripts): parse forwarded package script options 2026-05-30 17:44:14 +02:00
Peter Steinberger
19f22b5924 fix(feishu): bound approval card expiry 2026-05-30 11:41:43 -04:00
Peter Steinberger
05634708e0 fix(feishu): bound quick action launcher expiry 2026-05-30 11:38:50 -04:00
Vincent Koc
536c00991f fix(gateway): guard traced channel handoff stops 2026-05-30 16:36:43 +01:00
Peter Steinberger
c94c43d3bb fix(feishu): bound card action chat cache clocks 2026-05-30 11:36:19 -04:00
Nimrod Gutman
8a99c0d17a feat(ios): refresh app store metadata (#88235)
Merged via squash.

Prepared head SHA: a54d2ffad2
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Reviewed-by: @ngutman
2026-05-30 18:36:01 +03:00
Peter Steinberger
30e1556cda refactor: extract model catalog core package
* refactor: extract model catalog core package

* refactor: route model catalog imports through package boundary

* build: include model catalog in plugin sdk package dts

* fix: preserve static fallback model metadata
2026-05-30 16:33:45 +01:00
Peter Steinberger
ec15f90a55 fix(feishu): bound group name cache clocks 2026-05-30 11:33:30 -04:00
Peter Steinberger
3da34a4673 fix(feishu): bound probe cache expiry clocks 2026-05-30 11:31:16 -04:00
Peter Steinberger
f91ddefbfb fix(zalo): bound hosted media expiry clocks 2026-05-30 11:29:33 -04:00
Vincent Koc
84385898ec fix(deps): remove photon root runtime 2026-05-30 16:27:48 +01:00
Peter Steinberger
6c7642b532 fix(workboard): bound claim expiry timestamps 2026-05-30 11:27:09 -04:00
Peter Steinberger
9988a37d37 fix(phone-control): bound arm expiry timestamps 2026-05-30 11:24:36 -04:00
Peter Steinberger
37b33d11ce test: isolate channel manager teardown 2026-05-30 16:24:34 +01:00
Peter Steinberger
7086e34533 feat(workboard): persist orchestration metadata in sqlite
Persist Workboard orchestration data in plugin SQLite KV storage, including board metadata, cards, notification subscriptions, decomposition history, and board lifecycle/RPC support.
2026-05-30 16:24:14 +01:00
Peter Steinberger
20fbb8bd14 fix(mattermost): bound slash validation cache clocks 2026-05-30 11:22:25 -04:00
Peter Steinberger
8e90a1cad9 fix(slack): bound subteam member cache clocks 2026-05-30 11:19:34 -04:00
Peter Steinberger
7e3ebb8e10 fix(slack): bound external menu cache clocks 2026-05-30 11:17:13 -04:00
Peter Steinberger
06b2bf1c0a fix(telegram): bound forum flag cache clocks 2026-05-30 11:15:03 -04:00
Peter Steinberger
d649548a7a fix(active-memory): bound recall cache clocks 2026-05-30 11:13:04 -04:00
Vincent Koc
5adc681238 refactor: share approval lookup state 2026-05-30 17:12:03 +02:00
Vincent Koc
53e8dc6a54 fix(scripts): stop parsing after option terminators 2026-05-30 17:10:36 +02:00
Peter Steinberger
2d0a0c5e43 test: clear channel manager restart timers 2026-05-30 16:09:38 +01:00
Peter Steinberger
b668ffe7ca fix(slack): bound thread resolution cache clocks 2026-05-30 11:09:21 -04:00
Peter Steinberger
6736936cbc fix(slack): bound thread starter cache clocks 2026-05-30 11:06:47 -04:00
Peter Steinberger
8539e0283a fix(slack): bound app mention retry clocks 2026-05-30 11:04:24 -04:00
Peter Steinberger
ef88f0f949 perf(sessions): skip prompt hydration for metadata reads 2026-05-30 16:03:39 +01:00
Peter Steinberger
816c692035 fix(slack): bound member cache clocks 2026-05-30 11:01:19 -04:00
Peter Steinberger
c635e560d0 build: update rastermill to 0.3.1 2026-05-30 16:01:14 +01:00
Vincent Koc
ccb59d989b fix(scripts): honor memory fd option terminator 2026-05-30 17:00:54 +02:00
Vincent Koc
642f85dc5b test(sdk): resolve local package deps in pack smoke 2026-05-30 15:57:18 +01:00
Vincent Koc
53300a5c1a refactor: share skills method validation 2026-05-30 16:56:36 +02:00
Vincent Koc
b51610a1c3 fix(ci): serialize gateway server vitest project 2026-05-30 15:56:25 +01:00
Peter Steinberger
5269924ff8 fix(imessage): bound probe cache clocks 2026-05-30 10:55:53 -04:00
Peter Steinberger
62fa5692cb fix(imessage): bound chat list cache clocks 2026-05-30 10:52:38 -04:00
Peter Steinberger
2d4369d176 fix(signal): bound api mode cache clocks 2026-05-30 10:50:44 -04:00
Peter Steinberger
99e8cf22a8 fix(web): bound tool cache expiry clocks 2026-05-30 10:47:46 -04:00
Vincent Koc
e780a6b7ba fix(agents): type configured fallback model metadata 2026-05-30 16:45:53 +02:00
Vincent Koc
313554059c fix(docs): route anchor audit through pnpm runner 2026-05-30 16:45:52 +02:00
Peter Steinberger
77b334a984 fix(mattermost): bound reaction cache clocks 2026-05-30 10:43:44 -04:00
Peter Steinberger
ab67a198c1 fix(mattermost): bound monitor cache clocks 2026-05-30 10:41:19 -04:00
Peter Steinberger
9ef5a9afdc fix(discord): bound REST entity cache clocks 2026-05-30 10:38:26 -04:00
Vincent Koc
c39fbdb698 refactor: share web login request validation 2026-05-30 16:37:35 +02:00
Peter Steinberger
d33d6bfafa fix(discord): bound channel info cache clocks 2026-05-30 10:34:45 -04:00
Peter Steinberger
2209f71a78 fix(oauth): reject date-invalid token expiries 2026-05-30 10:31:36 -04:00
Peter Steinberger
f13a615036 fix(foundry): bound entra token expiry clocks 2026-05-30 10:29:26 -04:00
Peter Steinberger
5660b67062 fix(google-meet): bound oauth fallback expiry clocks 2026-05-30 10:26:07 -04:00
Vincent Koc
1d21646e96 fix(ci): type static catalog runtime metadata 2026-05-30 15:23:48 +01:00
Peter Steinberger
55d4456751 fix(webhook): bound replay response expiry timestamps 2026-05-30 10:21:50 -04:00
Peter Steinberger
a80d9f00f1 test(imessage): align SMS route expectations 2026-05-30 15:18:30 +01:00
Peter Steinberger
22d635080d fix(feishu): guard streaming token expiry clocks 2026-05-30 10:14:14 -04:00
Peter Steinberger
d5be702f86 fix(gateway): guard assistant media ticket clocks 2026-05-30 10:08:32 -04:00
Vincent Koc
3d66d203d0 test(daemon): keep systemd tests off real systemctl 2026-05-30 15:03:37 +01:00
Peter Steinberger
a918e93421 fix(cron): keep out-of-range atMs invalid 2026-05-30 10:00:45 -04:00
Vincent Koc
56eadf36d0 refactor: share approval resolve param parsing 2026-05-30 15:57:57 +02:00
Peter Steinberger
912f663173 fix(agents): guard compaction successor timestamps 2026-05-30 09:56:55 -04:00
Peter Steinberger
f44af7eebf fix(gateway): guard live probe schedule timestamps 2026-05-30 09:52:20 -04:00
Peter Steinberger
65fe2b7e91 ci: tolerate release branches without llm core package 2026-05-30 14:48:08 +01:00
Peter Steinberger
941e04e9f3 fix: clamp configured OpenAI-compatible output tokens 2026-05-30 14:46:30 +01:00
AI-HUB
f327073fb3 fix: classify ws pre-handshake close as benign
Classify the exact `ws` pre-handshake close-before-open error as a benign uncaught network exception so transient Feishu WebSocket cleanup does not crash the gateway process.

The classifier now keeps the upstream `ws` message as an exact contract and rejects broader prefixed WebSocket messages, with regression coverage for direct, wrapped, and non-exact cases.

Fixes #88257.
Thanks @akrimm702.

Co-authored-by: AI-HUB <144416483+akrimm702@users.noreply.github.com>
2026-05-30 15:45:23 +02:00
Peter Steinberger
41e5acbb6c perf(gateway): skip unchanged auth persistence writes 2026-05-30 14:44:45 +01:00
Peter Steinberger
2333d47a1e fix(matrix): guard verification timestamps 2026-05-30 09:43:09 -04:00
Vincent Koc
c9e481ac48 refactor: share approval request registration 2026-05-30 15:40:49 +02:00
scotthuang
462e315953 fix(ui): stop pulsing completed stream segments
Completed WebChat stream segment bubbles now render without the active streaming animation after live output has moved on. The UI chat item contract now marks completed stream segments as non-streaming and the active stream as streaming, so the renderer applies the pulsing class only to live output.

Verified with:
- node scripts/run-vitest.mjs ui/src/ui/chat/build-chat-items.test.ts ui/src/ui/chat/grouped-render.test.ts ui/src/ui/views/chat.test.ts
- node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.test.ui.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/test-ui-stream-artifacts.tsbuildinfo
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main

PR: #88225
Credit: @scotthuang
2026-05-30 15:40:12 +02:00
Peter Steinberger
6b14df7792 fix(qqbot): guard token expiry logging 2026-05-30 09:38:58 -04:00
Vincent Koc
e449392c4f fix(e2e): route telegram proof through pnpm runner 2026-05-30 15:33:38 +02:00
Peter Steinberger
326db58229 fix(gateway): guard hook job timestamps 2026-05-30 09:33:19 -04:00
Vincent Koc
3caf4facec fix(test): include workflow lint target in routing expectation (#88310) 2026-05-30 14:29:26 +01:00
Peter Steinberger
c9a97f54e0 fix(discord): preserve preference recency under invalid clocks 2026-05-30 09:29:02 -04:00
Vincent Koc
85506c36a0 fix(e2e): route secret proof through pnpm runner 2026-05-30 15:25:15 +02:00
Ayaan Zaidi
a176b8ec2f perf(cli): compact resumed room-event prompts 2026-05-30 18:53:59 +05:30
Ayaan Zaidi
2b726457d8 fix(cli): persist first room-event session binding 2026-05-30 18:53:59 +05:30
Vincent Koc
6464f8d1d9 refactor: share visible approval list mapping 2026-05-30 15:19:10 +02:00
Peter Steinberger
a17c7a56da fix(sessions): guard transcript append timestamps 2026-05-30 09:08:20 -04:00
Peter Steinberger
98a1aa491f fix(gateway): guard lock payload timestamps 2026-05-30 09:04:34 -04:00
Vincent Koc
25b87b111d refactor: share find tool result builder 2026-05-30 15:00:22 +02:00
Peter Steinberger
f823123aa5 fix(time): centralize date timestamp fallback 2026-05-30 08:59:36 -04:00
Vincent Koc
d717ff71bf fix(live): reject loose heartbeat intervals 2026-05-30 14:56:58 +02:00
Peter Steinberger
840192caa9 fix(diffs): cap artifact expiry overflow 2026-05-30 08:54:56 -04:00
Vincent Koc
61ef6b12dd test(agents): harden code mode wait timeout 2026-05-30 13:53:25 +01:00
Peter Steinberger
660a6dec7f fix(cron): reject out-of-range cli relative times 2026-05-30 08:52:47 -04:00
Peter Steinberger
e49ef86945 fix(cron): guard timestamp validation clocks 2026-05-30 08:49:58 -04:00
Peter Steinberger
d2f69ecc3b fix(migrate): guard report timestamp formatting 2026-05-30 08:46:55 -04:00
Vincent Koc
a89abcb1e9 fix(release): reject loose npm verifier retry limits 2026-05-30 14:46:28 +02:00
Peter Steinberger
8bf7bc5b5c fix(sessions): guard archive timestamp formatting 2026-05-30 08:43:22 -04:00
Vincent Koc
4e2ef87c31 refactor: share git url parsing helpers 2026-05-30 14:42:17 +02:00
Vincent Koc
ec58491f75 fix(e2e): reject loose upgrade probe limits 2026-05-30 14:40:12 +02:00
Peter Steinberger
0840fea50d fix(matrix): guard startup verification timestamps 2026-05-30 08:38:12 -04:00
Vincent Koc
cf60e83118 fix(e2e): scope strict ClawHub preflight limits 2026-05-30 14:33:56 +02:00
Peter Steinberger
7ad2ebb515 fix(google): guard realtime browser session expiries 2026-05-30 08:33:06 -04:00
Peter Steinberger
3c41e1722f fix(discord): guard timeout expiry dates 2026-05-30 08:29:15 -04:00
Vincent Koc
dd5b70bcc4 refactor: share web search provider load context 2026-05-30 14:25:30 +02:00
Peter Steinberger
30c0422a8e fix(commitments): guard extraction prompt timestamps 2026-05-30 08:24:27 -04:00
Vincent Koc
6d43200248 fix(e2e): reject loose Telegram proof log limits 2026-05-30 14:23:40 +02:00
Peter Steinberger
be3153cabb fix(update): guard startup timestamps 2026-05-30 08:18:55 -04:00
Vincent Koc
56995069f1 fix(ci): preserve goal continuation prompts 2026-05-30 13:17:57 +01:00
Vincent Koc
2238e0ce76 fix(e2e): reject loose tool search fetch limits 2026-05-30 14:17:15 +02:00
Vincent Koc
38a463fe93 fix(deps): remove sharp from root package 2026-05-30 13:15:05 +01:00
Vincent Koc
e1f462b352 fix(e2e): reject loose Telegram Bot API limits 2026-05-30 14:11:43 +02:00
Peter Steinberger
ccd635fdb9 fix(memory-core): guard short-term recall timestamps 2026-05-30 08:10:54 -04:00
Vincent Koc
27dce6c6bb refactor: share embedded run abort loop 2026-05-30 14:09:15 +02:00
Peter Steinberger
9c08d8cd35 fix(memory-core): guard injected timestamps 2026-05-30 08:06:42 -04:00
Vincent Koc
dc5b3ecc4c fix(tui): continue goal commands after creation 2026-05-30 13:03:33 +01:00
Ayaan Zaidi
95f66a34e7 fix(gateway): honor queued manual restarts 2026-05-30 17:33:18 +05:30
Ayaan Zaidi
1695ee2f43 fix(gateway): defer recovery restarts to callers 2026-05-30 17:33:18 +05:30
Ayaan Zaidi
801520b0f0 fix(gateway): consume recovery restart edge cases 2026-05-30 17:33:18 +05:30
Ayaan Zaidi
8ba79d72b4 test(gateway): cover reload stop timeout restart 2026-05-30 17:33:18 +05:30
Ayaan Zaidi
5876ba6152 fix(gateway): restart channels after timed-out reload stop 2026-05-30 17:33:18 +05:30
Peter Steinberger
5b895f2592 fix(memory-wiki): guard injected timestamps 2026-05-30 08:02:26 -04:00
Peter Steinberger
fb61363763 fix(auto-reply): guard date stamp formatting 2026-05-30 07:58:51 -04:00
Vincent Koc
07e0af44b3 fix(e2e): reject loose MCP channel limits 2026-05-30 13:55:39 +02:00
Peter Steinberger
059d5405fe fix(infra): guard backup creation timestamps 2026-05-30 07:53:55 -04:00
Vincent Koc
cd37dbd4e5 refactor: share block reply coalescer enqueue 2026-05-30 13:51:47 +02:00
Vincent Koc
3e8d06a6be fix(ci): include workflow guard target 2026-05-30 12:50:38 +01:00
Peter Steinberger
2f07e4e6c0 fix(agents): guard current time context timestamp 2026-05-30 07:47:11 -04:00
Peter Steinberger
15fb3314de fix(discord): guard model picker legacy dates 2026-05-30 07:43:47 -04:00
Peter Steinberger
5a019e7725 fix(auto-reply): guard subagent info timestamps 2026-05-30 07:34:01 -04:00
Vincent Koc
aea31934d4 refactor: share directory id collection 2026-05-30 13:32:27 +02:00
Peter Steinberger
8ec7e80cb2 fix(agents): bound cli oauth jwt expiries 2026-05-30 07:29:59 -04:00
Peter Steinberger
6c3533d8c4 fix(ui): guard debug event timestamps 2026-05-30 07:23:02 -04:00
Vincent Koc
9c313a7826 fix(test): preserve live test passthrough flags 2026-05-30 13:20:02 +02:00
Peter Steinberger
368a719879 fix(ui): guard dreaming next-cycle timestamps 2026-05-30 07:19:22 -04:00
Peter Steinberger
ec7e3eaf64 fix(ui): guard chat picker session timestamps 2026-05-30 07:15:40 -04:00
Vincent Koc
8bcdab8933 refactor: share oauth identity safety check 2026-05-30 13:14:10 +02:00
Peter Steinberger
c2f0d811e7 fix(ui): guard next run weekday formatting 2026-05-30 07:12:51 -04:00
Peter Steinberger
8f3d3a549d fix(ui): guard usage chart timestamps 2026-05-30 07:10:21 -04:00
Peter Steinberger
d389a52494 fix(ui): centralize invalid date formatting 2026-05-30 07:07:13 -04:00
Vincent Koc
346b14a51a fix(test): route conventional script tests 2026-05-30 13:00:33 +02:00
Vincent Koc
ffa2da8478 fix(test): skip broad changed import scans 2026-05-30 13:00:33 +02:00
Vincent Koc
61a768be75 fix(test): route script library changes 2026-05-30 13:00:33 +02:00
Vincent Koc
3d8a77a113 fix(test): route package tooling changes 2026-05-30 13:00:33 +02:00
Vincent Koc
a6a358f1a6 fix(test): route ci tooling changes 2026-05-30 13:00:33 +02:00
Vincent Koc
131dc4eaeb fix(test): route workflow helper changes 2026-05-30 13:00:33 +02:00
Vincent Koc
022fd55bad fix(test): route crabbox changed tests 2026-05-30 13:00:33 +02:00
Vincent Koc
d9820e4098 fix(ci): disable crabbox on-demand fallback 2026-05-30 13:00:33 +02:00
Vincent Koc
a4ebdc9aa1 fix(test): guard run-with-env help 2026-05-30 13:00:32 +02:00
Vincent Koc
cf2461f7f6 fix(test): guard live runner help 2026-05-30 13:00:32 +02:00
Vincent Koc
f5f829db79 fix(test): guard tsdown runner help 2026-05-30 13:00:32 +02:00
Vincent Koc
a06daab97e fix(test): guard build runner help 2026-05-30 13:00:32 +02:00
Vincent Koc
09f094057a fix(test): guard verify runner help 2026-05-30 13:00:32 +02:00
Vincent Koc
9def042fab fix(test): guard check runner help 2026-05-30 13:00:32 +02:00
Vincent Koc
f6adea5757 fix(test): guard force runner help 2026-05-30 13:00:32 +02:00
Vincent Koc
78f4a5c05f fix(tooling): ignore inline type-only re-exports 2026-05-30 13:00:32 +02:00
Vincent Koc
731a7af9c5 fix(test): keep wrapper help metadata-only 2026-05-30 13:00:32 +02:00
Vincent Koc
ffa4342a6a fix(test): route docker e2e script targets 2026-05-30 13:00:32 +02:00
Vincent Koc
550a134cf9 fix(tooling): forward oxlint shard cancellation 2026-05-30 13:00:32 +02:00
Vincent Koc
1b43e84d0d fix(test): batch explicit source route resolution 2026-05-30 13:00:32 +02:00
Vincent Koc
31f0635f4f fix(test): route explicit source targets narrowly 2026-05-30 13:00:31 +02:00
Vincent Koc
1c65e2e7c1 fix(tooling): bound oxlint shard stalls 2026-05-30 13:00:31 +02:00
Vincent Koc
b6f3fe7938 fix(test): route explicit helper targets narrowly 2026-05-30 13:00:31 +02:00
Vincent Koc
d65b3a68aa perf(cli): keep plugins JSON list on snapshot path 2026-05-30 13:00:31 +02:00
Vincent Koc
e2b54fecd8 fix(doctor): reuse lazy state migration import 2026-05-30 13:00:31 +02:00
Vincent Koc
b8067d073a fix(extensions): keep subagent hook facades lazy 2026-05-30 13:00:31 +02:00
Vincent Koc
e420c001d0 perf(policy): cache doctor file reads 2026-05-30 13:00:31 +02:00
Vincent Koc
44b6b79a66 perf(plugin-sdk): cache runtime helper imports 2026-05-30 13:00:31 +02:00
Vincent Koc
3ef2935ac9 perf(browser): reuse chrome mcp import 2026-05-30 13:00:31 +02:00
Vincent Koc
fced29de17 perf(extensions): cache meeting runtime loaders 2026-05-30 13:00:31 +02:00
Vincent Koc
4f074c3235 perf(extensions): cache plugin runtime loaders 2026-05-30 13:00:31 +02:00
Vincent Koc
5df00520cb perf(extensions): cache provider runtime imports 2026-05-30 13:00:30 +02:00
Vincent Koc
b2c85bc0a2 perf(browser): cache registration runtime import 2026-05-30 13:00:30 +02:00
Vincent Koc
5e2e78a75a perf(wizard): cache setup migration imports 2026-05-30 13:00:30 +02:00
Vincent Koc
2196f107da perf(gateway): cache post-attach startup imports 2026-05-30 13:00:30 +02:00
Vincent Koc
ff56a2d7b3 perf(gateway): cache plugin bootstrap imports 2026-05-30 13:00:30 +02:00
Vincent Koc
24cff8a3bc perf(gateway): share model catalog module loader 2026-05-30 13:00:30 +02:00
Vincent Koc
b495ac2abb perf(gateway): cache remote skills startup import 2026-05-30 13:00:30 +02:00
Vincent Koc
3f2585424d perf(gateway): cache plugin HTTP imports 2026-05-30 13:00:30 +02:00
Vincent Koc
9d1a3007d9 perf(gateway): cache model catalog imports 2026-05-30 13:00:30 +02:00
Vincent Koc
b5c163dffa test(doctor): complete browser health mock 2026-05-30 13:00:30 +02:00
Vincent Koc
ee0cf9e5bb perf(gateway): cache session event imports 2026-05-30 13:00:30 +02:00
Vincent Koc
37fdfa0e0b perf(doctor): cache health contribution imports 2026-05-30 13:00:30 +02:00
Vincent Koc
d550b804b8 perf(doctor): cache core check imports 2026-05-30 13:00:30 +02:00
Vincent Koc
05988500bc perf(crestodian): cache operation imports 2026-05-30 13:00:29 +02:00
Vincent Koc
b01290cf64 perf(cli): cache command ownership imports 2026-05-30 13:00:29 +02:00
Vincent Koc
117f6fb254 test(agents): complete provider runtime mock 2026-05-30 13:00:29 +02:00
Vincent Koc
c363816fea perf(cli): cache runtime startup imports 2026-05-30 13:00:29 +02:00
Vincent Koc
aeed31cdb1 perf(cli): cache root help imports 2026-05-30 13:00:29 +02:00
Vincent Koc
58c8c022c5 perf(entry): cache root help module imports 2026-05-30 13:00:29 +02:00
Vincent Koc
2cfae61743 perf(onboarding): split ClawHub install error codes 2026-05-30 13:00:29 +02:00
Vincent Koc
c6b4daf426 perf(health): remove duplicate config import 2026-05-30 13:00:29 +02:00
Vincent Koc
348fabe04d perf(auto-reply): remove reset model duplicate import 2026-05-30 13:00:29 +02:00
Vincent Koc
6c83e8e7e4 perf(models): cache provider index catalog import 2026-05-30 13:00:29 +02:00
Vincent Koc
817b6259c4 perf(agents): cache live model runtime import 2026-05-30 13:00:29 +02:00
Vincent Koc
959af0fa5b perf(cli): cache secrets command imports 2026-05-30 13:00:29 +02:00
Vincent Koc
669b26a3dc perf(cli): cache routed command imports 2026-05-30 13:00:28 +02:00
Vincent Koc
67c139fc36 perf(cli): cache status command imports 2026-05-30 13:00:28 +02:00
Vincent Koc
8b6829e1bc perf(cli): cache plugin runtime imports 2026-05-30 13:00:28 +02:00
Vincent Koc
86e6fbcf52 perf(cli): cache agent bind command import 2026-05-30 13:00:28 +02:00
Vincent Koc
9b4b3aa348 perf(cli): cache plugins command imports 2026-05-30 13:00:28 +02:00
Vincent Koc
51ab2c0d79 perf(cli): cache models runtime import 2026-05-30 13:00:28 +02:00
Vincent Koc
bdd9c70787 perf(cli): cache devices runtime import 2026-05-30 13:00:28 +02:00
Vincent Koc
1ff95ff3e6 perf(doctor): cache health config import 2026-05-30 13:00:28 +02:00
Peter Steinberger
7c5b55c5ff fix(ui): ignore invalid reset timestamps 2026-05-30 07:00:01 -04:00
Vincent Koc
b0d6076208 refactor: share setup dashboard open flow 2026-05-30 12:55:19 +02:00
Peter Steinberger
4385e57dce fix(doctor): tolerate invalid cron atMs 2026-05-30 06:54:58 -04:00
Vincent Koc
eb45c1c623 fix(scripts): report missing workflow linter fallback 2026-05-30 12:52:54 +02:00
Peter Steinberger
adf981de89 fix(imessage): tolerate invalid catchup cursor timestamps 2026-05-30 06:46:09 -04:00
Peter Steinberger
023a101b91 fix(heartbeat): tolerate invalid commitment due timestamps 2026-05-30 06:41:16 -04:00
Peter Steinberger
8b92aca27f refactor: extract media understanding common package (#88297)
* refactor: extract media understanding common package

* test: move media understanding format test
2026-05-30 12:40:49 +02:00
Peter Steinberger
b13fb788b5 fix(commitments): tolerate invalid due timestamps 2026-05-30 06:36:49 -04:00
Vincent Koc
87c0ee7685 refactor: share config observe recovery restore helpers 2026-05-30 12:35:36 +02:00
Peter Steinberger
eef32e94c7 fix(memory-wiki): tolerate invalid source mtimes 2026-05-30 06:33:13 -04:00
Peter Steinberger
1350efcfd8 fix(acp): tolerate invalid status timestamps 2026-05-30 06:27:44 -04:00
Peter Steinberger
e7ef051149 fix(slack): tolerate invalid interaction datetimes 2026-05-30 06:23:39 -04:00
Peter Steinberger
2b5ddf8f2a fix(acp): tolerate invalid session timestamps 2026-05-30 06:19:44 -04:00
Vincent Koc
6f655573d3 refactor: share parallels smoke lifecycle 2026-05-30 12:18:46 +02:00
Peter Steinberger
8aabf45ddb fix(memory-wiki): tolerate invalid chatgpt timestamps 2026-05-30 06:16:03 -04:00
Peter Steinberger
4d4748e807 fix(voice-call): tolerate invalid ended timestamps 2026-05-30 06:10:40 -04:00
Peter Steinberger
439c09668e fix(ui): ignore invalid usage export timestamps 2026-05-30 06:06:19 -04:00
Peter Steinberger
54bbe87cd5 fix(ui): ignore invalid chat export timestamps 2026-05-30 06:02:38 -04:00
Peter Steinberger
6804b7cb71 fix(matrix): ignore invalid device timestamps 2026-05-30 05:59:10 -04:00
Peter Steinberger
63470e99f0 fix(session): tolerate invalid lifecycle expiry 2026-05-30 05:53:24 -04:00
16902 changed files with 424898 additions and 112044 deletions

View File

@@ -22,6 +22,8 @@ Use when:
- Read dependency docs/source/types when the finding depends on external behavior.
- Reject unrealistic edge cases, speculative risks, broad rewrites, and fixes that over-complicate the codebase.
- Prefer small fixes at the right ownership boundary; no refactor unless it clearly improves the bug class.
- When an accepted finding shows a bug class or repeated pattern, inspect the current PR scope for sibling instances before fixing.
- Fix the scoped bug class at once when practical; stop at touched surfaces, owner boundaries, and clear follow-up territory.
- Keep going until structured review returns no accepted/actionable findings.
- If a review-triggered fix changes code, rerun focused tests and rerun the structured review helper.
- For security-audit suppression changes, verify accepted findings remain auditable: suppressed findings stay in structured output, active output keeps an unsuppressible suppression notice, and aggregate findings cannot hide unrelated active risk.

View File

@@ -223,6 +223,21 @@ Read the JSON summary and the Testbox line. Useful fields:
- Actions run URL/id from the Testbox output
- `exitCode`
Use provider-backed cache volumes only for rebuildable caches, not secrets or
checkout state. On Blacksmith, Crabbox forwards them as sticky disks:
```sh
node scripts/crabbox-wrapper.mjs run \
--provider blacksmith-testbox \
--cache-volume pnpm-store=openclaw-node24-pnpm-lock:/tmp/openclaw-pnpm-store \
--timing-json \
-- \
corepack pnpm check:changed
```
The selected provider must advertise cache-volume support. If not, omit
`--cache-volume` and rely on kept-lease caches.
`blacksmith testbox list` may hide hydrating or ready boxes. Use:
```sh
@@ -590,7 +605,8 @@ Crabbox Blacksmith backend delegates setup to:
The hydration workflow owns checkout, Node/pnpm setup, dependency install,
secrets, ready marker, and keepalive. Crabbox owns dispatch, sync, SSH command
execution, timing, logs/results, and cleanup.
execution, timing, logs/results, cleanup, and cache-volume requests. Blacksmith
implements cache volumes as sticky disks.
Minimal Blacksmith-backed Crabbox run, from repo root:
@@ -685,6 +701,7 @@ crabbox events <run_id> --json
crabbox logs <run_id>
crabbox results <run_id>
crabbox cache stats --id <id-or-slug>
crabbox cache volumes
crabbox ssh --id <id-or-slug>
blacksmith testbox list
```

View File

@@ -52,17 +52,29 @@ attribution.
- keep `#issue`, `(#PR)`, `Fixes #...`, and `Thanks @...`
- every human-authored merged PR represented by a user-facing entry needs
its PR ref and `Thanks @author`, even when the PR had no linked issue
- every human issue reporter for a `Fixes #...` or referenced bug issue
represented by a user-facing entry needs `Thanks @reporter` unless the
same handle is already thanked in that bullet
- every human `Co-authored-by` contributor on represented user-facing work
needs `Thanks @handle` when a GitHub handle is known
- when grouping multiple PRs/issues in one bullet, include every relevant
PR/issue ref and every human contributor handle in that same bullet
- multiple `Thanks @...` handles in one bullet are expected; do not drop or
collapse contributor credit just because the note is grouped
- if one grouped bullet covers both direct commits and PRs, keep all PR refs
and thanks, plus any issue refs from the direct commits
- before finalizing, audit the final release-note body:
- extract all `#NNN` refs from the notes
- resolve which refs are PRs and collect human PR authors
- resolve issue refs used as bug/report refs and collect human reporters
- scan represented commits for `Co-authored-by`
- compare those handles to the final `Thanks @...` set
- fix every missing human credit or explicitly record why it is omitted
- do not add GHSA references, advisory IDs, or security advisory slugs to
changelog entries or GitHub release-note text unless explicitly requested
- never thank bots, `@openclaw`, `@clawsweeper`, or `@steipete`
- if grouping multiple entries, carry all relevant refs and thanks into the
grouped bullet
- do not use GitHub's release contributor count as the source of truth; the
changelog must carry the complete human credit set itself
7. Sorting preference:
- security/data-loss and content-boundary fixes
- transcript/replay/reply delivery correctness

View File

@@ -187,11 +187,37 @@ gh pr view <number> --json additions,deletions,changedFiles \
## Read beyond the diff
- Review the surrounding code path, not just changed lines. Open the caller, callee, data contracts, adjacent tests, and owner module.
- Before any verdict, read enough code to fill this map: changed surface, runtime entry point, owner boundary, one caller, one callee, sibling implementations sharing the invariant, adjacent tests, current `main` behavior, and shipped/dependency/Codex contracts when relevant.
- For large-codebase PRs, sample enough related files to understand the runtime boundary before deciding. Default to more code reading when the change touches agents, gateway, plugins, auth, sessions, process, config, or provider/runtime seams.
- Compare the PR against current `origin/main` behavior. Check whether recent main already changed the same surface.
- Dependency-backed behavior: MUST read upstream docs/source/types before judging API use, defaults, output shapes, errors, timeouts, memory behavior, or compatibility. Do not assume dependency contracts from memory or PR text.
- Judge solution quality, not only correctness. Ask whether the PR is the clean owner-boundary fix or a wart/workaround that should be replaced by a small refactor, moved seam, contract change, or deletion of duplicate logic.
- Mention the main files read when the verdict depends on code-path evidence.
- If the user challenges the verdict or asks whether the idea is really good, resume code reading first. Do not defend, soften, or reverse the verdict until the missing caller/callee/sibling/dependency path is checked.
## Best-fix review loop
Every PR review must explicitly answer: "Is this the best fix, or only a plausible fix?"
Before verdict:
1. Reconstruct the bug, feature need, or behavior claim from issue/PR/proof.
2. Trace current behavior from entry point to failure or decision point.
3. Read touched files, callers, callees, owner modules, adjacent tests, and relevant docs.
4. Read sibling surfaces that should share the invariant or could be broken by a one-sided fix.
5. Compare against current `origin/main` and shipped behavior when regression/compat matters.
6. Inspect upstream dependency/Codex source or docs for dependency-backed behavior.
7. Identify at least one alternative fix location or shape, then reject it with evidence.
8. If any required path above is uninspected, keep reading or mark `Remaining uncertainty`; do not call the PR best, blocked, proof-sufficient, or merge-ready.
Review output must include:
- `Best-fix verdict:` best / acceptable mitigation / wrong layer / too narrow / too broad.
- `Alternatives considered:` 1-3 concrete alternatives and why rejected.
- `Code read:` compact list of main files/contracts checked.
- `Remaining uncertainty:` what was not proven.
If the best-fix answer is only "maybe", keep reading or state the missing evidence. Do not call proof sufficient until the best-fix judgment is explicit.
## Enforce the bug-fix evidence bar

View File

@@ -1,8 +1,10 @@
#!/usr/bin/env node
// Secret scanning alert handler for OpenClaw maintainers.
// Usage: node secret-scanning.mjs <command> [options]
/**
* Secret scanning alert handler for OpenClaw maintainers.
* Usage: node secret-scanning.mjs <command> [options]
*/
import { execFileSync, spawnSync } from "node:child_process";
import { spawnSync } from "node:child_process";
import crypto from "node:crypto";
import fs from "node:fs";
import os from "node:os";
@@ -39,7 +41,9 @@ function gh(args, { json = true, allowFailure = false } = {}) {
stderr: proc.stderr,
};
}
if (!json) return proc.stdout;
if (!json) {
return proc.stdout;
}
try {
return JSON.parse(proc.stdout);
} catch {
@@ -55,6 +59,7 @@ function isBodyLocationType(locationType) {
return locationType === "issue_body" || locationType === "pull_request_body";
}
/** Decides whether redacting an issue/PR body requires notifying the reporter. */
export function decideBodyRedaction(currentBody, redactedBody) {
const bodyChanged = String(currentBody) !== String(redactedBody);
return {
@@ -63,6 +68,7 @@ export function decideBodyRedaction(currentBody, redactedBody) {
};
}
/** Loads redaction-result metadata for issue/PR body secret locations. */
export function loadBodyRedactionResult(locationType, resultFile) {
if (!isBodyLocationType(locationType)) {
return { notify_required: true };
@@ -70,7 +76,9 @@ export function loadBodyRedactionResult(locationType, resultFile) {
if (!resultFile) {
fail("Body notifications require a redaction result file from redact-body-if-needed");
}
if (!fs.existsSync(resultFile)) fail(`File not found: ${resultFile}`);
if (!fs.existsSync(resultFile)) {
fail(`File not found: ${resultFile}`);
}
const result = JSON.parse(fs.readFileSync(resultFile, "utf8"));
if (typeof result.notify_required !== "boolean") {
@@ -182,10 +190,11 @@ function fetchDiscussionComment(discussionNumber, discussionCommentDbId) {
failOnGraphQLFailure(gql, `Failed to fetch discussion #${discussionNumber}`);
const discussion = gql?.data?.repository?.discussion;
if (!discussion)
if (!discussion) {
fail(
`Discussion #${discussionNumber} not found — it may have been deleted. The alert cannot be processed via this skill.`,
);
}
discussionId = discussion.id;
@@ -205,15 +214,18 @@ function fetchDiscussionComment(discussionNumber, discussionCommentDbId) {
`Failed to fetch replies for discussion comment ${topLevelComment.id}`,
);
const replies = replyPage?.data?.node?.replies;
if (!replies)
if (!replies) {
fail(`Failed to paginate replies for discussion comment ${topLevelComment.id}`);
}
reply = findDiscussionCommentNode(replies.nodes, discussionCommentDbId);
hasMoreReplies = replies.pageInfo.hasNextPage;
replyCursor = replies.pageInfo.endCursor;
}
if (reply) return { discussionId, comment: reply };
if (reply) {
return { discussionId, comment: reply };
}
}
hasNextPage = discussion.comments.pageInfo.hasNextPage;
@@ -241,7 +253,9 @@ function createDiscussionComment(discussionNodeId, body, replyToNodeId) {
* Fetch alert metadata + locations. Never exposes .secret.
*/
function cmdFetchAlert(alertNumber) {
if (!alertNumber) fail("Usage: fetch-alert <number>");
if (!alertNumber) {
fail("Usage: fetch-alert <number>");
}
const alert = gh(["api", `repos/${REPO}/secret-scanning/alerts/${alertNumber}?hide_secret=true`]);
@@ -280,17 +294,23 @@ function cmdFetchAlert(alertNumber) {
* Saves full body to a temp file. Prints metadata + file path to stdout.
*/
function cmdFetchContent(locationJson) {
if (!locationJson) fail("Usage: fetch-content '<location-json>'");
if (!locationJson) {
fail("Usage: fetch-content '<location-json>'");
}
const location = JSON.parse(locationJson);
const type = location.type;
const details = location.details;
if (type === "discussion_comment") {
const commentUrl = details.discussion_comment_url;
if (!commentUrl) fail("No discussion_comment_url in location details");
if (!commentUrl) {
fail("No discussion_comment_url in location details");
}
const urlMatch = commentUrl.match(/discussions\/(\d+)#discussioncomment-(\d+)/);
if (!urlMatch) fail(`Cannot parse discussion comment URL: ${commentUrl}`);
if (!urlMatch) {
fail(`Cannot parse discussion comment URL: ${commentUrl}`);
}
const discussionNumber = urlMatch[1];
const discussionCommentDbId = urlMatch[2];
@@ -298,10 +318,11 @@ function cmdFetchContent(locationJson) {
discussionNumber,
discussionCommentDbId,
);
if (!comment)
if (!comment) {
fail(
`Discussion comment #${discussionCommentDbId} not found in discussion #${discussionNumber}`,
);
}
const bodyFile = tmpFile("body.md");
fs.writeFileSync(bodyFile, comment.body || "");
@@ -334,7 +355,9 @@ function cmdFetchContent(locationJson) {
details.issue_comment_url ||
details.pull_request_comment_url ||
details.pull_request_review_comment_url;
if (!commentUrl) fail(`No comment URL in location details`);
if (!commentUrl) {
fail(`No comment URL in location details`);
}
const comment = gh(["api", commentUrl]);
const bodyFile = tmpFile("body.md");
@@ -378,7 +401,9 @@ function cmdFetchContent(locationJson) {
);
} else if (type === "issue_body") {
const issueUrl = details.issue_body_url || details.issue_url;
if (!issueUrl) fail("No issue URL in location details");
if (!issueUrl) {
fail("No issue URL in location details");
}
const issue = gh(["api", issueUrl]);
const bodyFile = tmpFile("body.md");
@@ -414,7 +439,9 @@ function cmdFetchContent(locationJson) {
);
} else if (type === "pull_request_body") {
const prUrl = details.pull_request_body_url || details.pull_request_url;
if (!prUrl) fail("No PR URL in location details");
if (!prUrl) {
fail("No PR URL in location details");
}
const pr = gh(["api", prUrl]);
const bodyFile = tmpFile("body.md");
@@ -490,7 +517,9 @@ function cmdRedactBody(kind, number, bodyFile) {
if (!kind || !number || !bodyFile) {
fail("Usage: redact-body <issue|pr> <number> <redacted-body-file>");
}
if (!fs.existsSync(bodyFile)) fail(`File not found: ${bodyFile}`);
if (!fs.existsSync(bodyFile)) {
fail(`File not found: ${bodyFile}`);
}
const endpoint =
kind === "pr" ? `repos/${REPO}/pulls/${number}` : `repos/${REPO}/issues/${number}`;
@@ -509,8 +538,12 @@ function cmdRedactBodyIfNeeded(kind, number, currentBodyFile, redactedBodyFile,
"Usage: redact-body-if-needed <issue|pr> <number> <current-body-file> <redacted-body-file> <result-file>",
);
}
if (!fs.existsSync(currentBodyFile)) fail(`File not found: ${currentBodyFile}`);
if (!fs.existsSync(redactedBodyFile)) fail(`File not found: ${redactedBodyFile}`);
if (!fs.existsSync(currentBodyFile)) {
fail(`File not found: ${currentBodyFile}`);
}
if (!fs.existsSync(redactedBodyFile)) {
fail(`File not found: ${redactedBodyFile}`);
}
const currentBody = fs.readFileSync(currentBodyFile, "utf8");
const redactedBody = fs.readFileSync(redactedBodyFile, "utf8");
@@ -541,7 +574,9 @@ function cmdRedactBodyIfNeeded(kind, number, currentBodyFile, redactedBodyFile,
* Delete a comment (and all its edit history).
*/
function cmdDeleteComment(commentId) {
if (!commentId) fail("Usage: delete-comment <comment-id>");
if (!commentId) {
fail("Usage: delete-comment <comment-id>");
}
gh(["api", `repos/${REPO}/issues/comments/${commentId}`, "-X", "DELETE"], { json: false });
console.log(JSON.stringify({ ok: true, deleted_comment_id: Number(commentId) }));
}
@@ -551,7 +586,9 @@ function cmdDeleteComment(commentId) {
* Delete a discussion comment via GraphQL (and all its edit history).
*/
function cmdDeleteDiscussionComment(nodeId) {
if (!nodeId) fail("Usage: delete-discussion-comment <node-id>");
if (!nodeId) {
fail("Usage: delete-discussion-comment <node-id>");
}
const result = ghGraphQL(
`mutation { deleteDiscussionComment(input: { id: "${nodeId}" }) { comment { id } } }`,
);
@@ -566,9 +603,12 @@ function cmdDeleteDiscussionComment(nodeId) {
* Create a new discussion comment via GraphQL.
*/
function cmdRecreateDiscussionComment(discussionNodeId, bodyFile, replyToNodeId) {
if (!discussionNodeId || !bodyFile)
if (!discussionNodeId || !bodyFile) {
fail("Usage: recreate-discussion-comment <discussion-node-id> <body-file> [reply-to-node-id]");
if (!fs.existsSync(bodyFile)) fail(`File not found: ${bodyFile}`);
}
if (!fs.existsSync(bodyFile)) {
fail(`File not found: ${bodyFile}`);
}
const body = fs.readFileSync(bodyFile, "utf8");
const newComment = createDiscussionComment(discussionNodeId, body, replyToNodeId);
@@ -586,8 +626,12 @@ function cmdRecreateDiscussionComment(discussionNodeId, bodyFile, replyToNodeId)
* Create a new comment from a file.
*/
function cmdRecreateComment(issueNumber, bodyFile) {
if (!issueNumber || !bodyFile) fail("Usage: recreate-comment <issue-number> <body-file>");
if (!fs.existsSync(bodyFile)) fail(`File not found: ${bodyFile}`);
if (!issueNumber || !bodyFile) {
fail("Usage: recreate-comment <issue-number> <body-file>");
}
if (!fs.existsSync(bodyFile)) {
fail(`File not found: ${bodyFile}`);
}
const result = gh([
"api",
@@ -715,7 +759,9 @@ function cmdNotify(target, author, locationType, secretTypes, replyToNodeId) {
* Close a secret scanning alert.
*/
function cmdResolve(alertNumber, resolution, comment) {
if (!alertNumber) fail("Usage: resolve <alert-number> [resolution] [comment]");
if (!alertNumber) {
fail("Usage: resolve <alert-number> [resolution] [comment]");
}
const res = resolution || "revoked";
const resComment = comment || "Content redacted and author notified to rotate credentials.";
@@ -773,8 +819,12 @@ function cmdListOpen() {
* Print a formatted summary table from a JSON results file.
*/
function cmdSummary(jsonFile) {
if (!jsonFile) fail("Usage: summary <json-file>");
if (!fs.existsSync(jsonFile)) fail(`File not found: ${jsonFile}`);
if (!jsonFile) {
fail("Usage: summary <json-file>");
}
if (!fs.existsSync(jsonFile)) {
fail(`File not found: ${jsonFile}`);
}
const results = JSON.parse(fs.readFileSync(jsonFile, "utf8"));
const lines = [];

View File

@@ -1,4 +1,7 @@
#!/usr/bin/env node
/**
* Heap snapshot diff utility for OpenClaw test memory leak investigations.
*/
import fs from "node:fs";
import path from "node:path";

View File

@@ -19,7 +19,7 @@ or validating a change without wasting hours.
Prove the touched surface first. Do not reflexively run the whole suite.
1. Inspect the diff and classify the touched surface:
- normal source checkout, source change: `pnpm changed:lanes --json`, then `pnpm check:changed`
- normal source checkout, source change: `pnpm changed:lanes --json`, then `pnpm check:changed` (delegates to Crabbox/Testbox)
- normal source checkout, tests only: `pnpm test:changed`
- normal source checkout, one failing file: `pnpm test <path-or-filter> -- --reporter=verbose`
- Codex worktree or linked/sparse checkout, one/few explicit files: `node scripts/run-vitest.mjs <path-or-filter>`
@@ -27,7 +27,7 @@ Prove the touched surface first. Do not reflexively run the whole suite.
use the Crabbox wrapper with the provider that matches the proof surface.
For maintainer heavy `pnpm` gates, that is usually delegated Blacksmith
Testbox through Crabbox, e.g. `node scripts/crabbox-wrapper.mjs run
--provider blacksmith-testbox ... -- pnpm check:changed`. For direct AWS
--provider blacksmith-testbox ... -- env OPENCLAW_CHECK_CHANGED_REMOTE_CHILD=1 OPENCLAW_CHANGED_LANES_RAW_SYNC=1 corepack pnpm check:changed`. For direct AWS
Crabbox proof, omit `--provider` and let `.crabbox.yaml` choose AWS.
- workflow-only: `git diff --check`, workflow syntax/lint (`actionlint` when available)
- docs-only: `pnpm docs:list`, docs formatter/lint only if docs tooling changed or requested
@@ -66,7 +66,7 @@ scripts/crabbox-wrapper.mjs` for Testbox, and `git commit --no-verify` only
```bash
pnpm changed:lanes --json
pnpm check:changed # changed typecheck/lint/guards; no Vitest
pnpm check:changed # Crabbox/Testbox changed typecheck/lint/guards; no Vitest
pnpm test:changed # cheap smart changed Vitest targets
pnpm verify # full check, then full Vitest
OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed

View File

@@ -16,6 +16,10 @@ Use this with `$release-openclaw-maintainer` and `$openclaw-testing` when a rele
- Watch one parent run plus compact child summaries. Avoid broad `gh run view` polling loops; REST quota is easy to burn.
- Fetch logs only for failed or currently-blocking jobs. If quota is low, stop polling and wait for reset.
- Treat live-provider flakes separately from code failures: prove key validity, provider HTTP status, retry evidence, and exact failing lane before editing code.
- Full Release Validation parent monitors fail fast: once a required child job
fails, the parent cancels the remaining child matrix and prints the failed
job summary. Inspect that first red job instead of waiting for unrelated
matrix tails.
## Preflight
@@ -73,6 +77,9 @@ gh workflow run full-release-validation.yml \
```
Use `release_profile=stable` unless the operator explicitly asks for the broad advisory provider/media matrix. Use narrow `rerun_group` after focused fixes.
Publish with `openclaw-release-publish.yml` using `release_profile=from-validation`
unless a maintainer intentionally wants to cross-check a specific profile; the
publish workflow reads the effective profile from the full-validation manifest.
## Watch

View File

@@ -1,4 +1,8 @@
#!/usr/bin/env node
/**
* Release CI summary helper that prints parent and child workflow status for a
* full release run.
*/
import { execFileSync } from "node:child_process";
import process from "node:process";

View File

@@ -1,4 +1,8 @@
#!/usr/bin/env node
/**
* Release preflight helper that verifies required provider API keys can reach
* their model-list endpoints without printing secret values.
*/
import process from "node:process";
const args = new Map();

View File

@@ -49,17 +49,21 @@ Use this skill for release and publish-time workflow. Load `$release-private` if
the next beta number until the matching npm package has actually published.
If a published beta needs a fix, commit the fix on the release branch and
increment to the next `-beta.N`.
- For a beta release train, run the fast local preflight first, publish the
beta to npm `beta`, then run the expensive published-package roster focused
on install/update/Docker/Parallels/NPM Telegram. If anything fails, fix it on
the release branch, commit/push/pull, increment beta number, and repeat. Run
the full expensive roster at least once before stable/latest promotion; for
later beta attempts, rerun only lanes whose evidence changed unless the fix
touches broad release, install/update, plugin, Docker, Parallels, or live QA
behavior. After each beta is published, scan current `main` once for critical
fixes that landed after the release branch cut and backport only important
low-risk fixes. Operators may authorize up to 4 autonomous beta attempts;
after 4 failed beta attempts, stop and report.
- For a beta release train, keep Full Release Validation as a pre-publish gate
unless the operator explicitly waives it. Run the fast local preflight, npm
preflight, full release validation, and performance in parallel where safe.
If anything fails before npm publish, fix it on the release branch,
forward-port the fix to `main`, move the unpublished beta tag/prerelease to
the fixed commit, and rerun the affected pre-publish gates. If anything fails
after npm publish, fix it, forward-port to `main`, increment beta number, and
repeat. After each beta publish, run the published-package roster focused on
install/update/Docker/Parallels/NPM Telegram. For later beta attempts, rerun
only lanes whose evidence changed unless the fix touches broad release,
install/update, plugin, Docker, Parallels, or live QA behavior. After each
beta is live, scan current `main` once for critical fixes that landed after
the release branch cut and backport only important low-risk fixes. Operators
may authorize up to 4 autonomous beta attempts; after 4 failed beta attempts,
stop and report.
- As soon as the release candidate SHA exists, dispatch `OpenClaw Performance`
with `target_ref=<release-sha>` in parallel with the other release work. Do
not wait for full release validation to start the performance signal.
@@ -107,9 +111,10 @@ Use this skill for release and publish-time workflow. Load `$release-private` if
- For fallback correction tags like `vYYYY.M.D-N`, the repo version locations still stay at `YYYY.M.D`.
- “Bump version everywhere” means all version locations above except `appcast.xml`.
- Release signing and notary credentials live outside the repo in the private maintainer docs.
- Every stable OpenClaw release ships the npm package and macOS app together.
Beta releases normally ship npm/package artifacts first and skip mac app
build/sign/notarize unless the operator requests mac beta validation.
- Every stable OpenClaw release ships the npm package, macOS app, and signed
Windows Hub installers together. Beta releases normally ship npm/package
artifacts first and skip native app build/sign/notarize/promote unless the
operator requests native beta validation.
- Do not let the slower macOS signing/notary path block npm publication once
the npm preflight has passed. Keep mac validation/publish running in
parallel, publish npm from the successful npm preflight, then start published
@@ -139,6 +144,17 @@ Use this skill for release and publish-time workflow. Load `$release-private` if
at `YYYY.M.D`, but the mac release must use a strictly higher numeric
`APP_BUILD` / Sparkle build than the original release so existing installs
see it as newer.
- Stable Windows Hub release closeout requires the signed
`OpenClawCompanion-Setup-x64.exe`, `OpenClawCompanion-Setup-arm64.exe`, and
`OpenClawCompanion-SHA256SUMS.txt` assets on the canonical
`openclaw/openclaw` GitHub Release. Use the public `Windows Node Release`
workflow after the matching `openclaw/openclaw-windows-node` release exists;
it verifies Authenticode signatures on Windows before uploading assets.
- Website Windows Hub download links should target exact canonical
`openclaw/openclaw/releases/download/vYYYY.M.D/...` assets for the current
stable release, or `releases/latest/download/...` only after verifying the
redirect resolves to that same tag, so the installable signed Windows artifact
is visible from both the GitHub release page and openclaw.ai.
## Build changelog-backed release notes
@@ -174,6 +190,13 @@ Use this skill for release and publish-time workflow. Load `$release-private` if
`CHANGELOG.md` version section, not highlights or an excerpt. When creating
or editing a release, extract from `## YYYY.M.D` through the line before the
next level-2 heading and use that complete block as the release notes.
- To update an existing GitHub Release body, resolve the numeric release id and
patch that resource with the notes file as the `body` field:
`gh api repos/openclaw/openclaw/releases/tags/vYYYY.M.D --jq .id`, then
`gh api -X PATCH repos/openclaw/openclaw/releases/<id> -F body=@/tmp/notes.md`.
Do not trust `gh release edit --notes-file` or `--input` JSON if verification
disagrees; verify with `gh api repos/openclaw/openclaw/releases/<id>` because
the tag lookup and `gh release view` can lag or show stale body text.
- When preparing release notes, scan `src/plugins/compat/registry.ts` and
`src/commands/doctor/shared/deprecation-compat.ts` for compatibility records
with `warningStarts` or `removeAfter` within 7 days after the release date.
@@ -468,8 +491,10 @@ node --import tsx scripts/openclaw-npm-postpublish-verify.ts <published-version>
- The npm workflow and the private mac publish workflow accept
`preflight_only=true` to run validation/build/package steps without uploading
public release assets.
- Real npm publish requires a prior successful npm preflight run id so the
publish job promotes the prepared tarball instead of rebuilding it.
- Real npm publish requires a prior successful npm preflight run id and the
successful Full Release Validation run id for the same tag/SHA so the publish
job promotes the prepared tarball instead of rebuilding it and attaches the
correct release evidence.
- Real private mac publish requires a prior successful private mac preflight
run id so the publish job promotes the prepared artifacts instead of
rebuilding or renotarizing them again.
@@ -499,11 +524,12 @@ node --import tsx scripts/openclaw-npm-postpublish-verify.ts <published-version>
instead of uploading public GitHub release assets.
- Private smoke-test runs upload ad-hoc, non-notarized build artifacts as
workflow artifacts and intentionally skip stable `appcast.xml` generation.
- For stable releases, npm preflight, public mac validation, private mac
validation, and private mac preflight must all pass before any real publish
run starts. For beta releases, npm preflight plus the selected Docker,
install/update, Parallels, and release-check lanes are sufficient unless mac
beta validation was explicitly requested.
- For stable releases, npm preflight, Full Release Validation, public mac
validation, private mac validation, and private mac preflight must all pass
before any real publish run starts. For beta releases, npm preflight and Full
Release Validation must pass before npm publish unless the operator explicitly
waives the full gate; mac beta validation is still only required when
requested.
- Real publish runs may be dispatched from `main` or from a
`release/YYYY.M.D` branch. For release-branch runs, the tag must be contained
in that release branch, and the real publish must reuse a successful preflight

View File

@@ -4,20 +4,12 @@ profile: openclaw-check
provider: azure
class: standard
capacity:
market: spot
market: on-demand
strategy: most-available
fallback: on-demand-after-120s
# The Azure-backed billing account carries the OpenClaw runner credits; use
# explicit on-demand capacity instead of low-priority spot, whose regional
# quota is too small for broad maintainer proof or parallel Crabbox lanes.
hints: true
availabilityZones:
- eu-west-1a
- eu-west-1b
- eu-west-1c
regions:
- eu-west-1
- eu-west-2
- eu-central-1
- us-east-1
- us-west-2
actions:
workflow: .github/workflows/crabbox-hydrate.yml
# Default AWS hydration uses local Actions replay. Use
@@ -36,9 +28,30 @@ blacksmith:
workflow: .github/workflows/ci-check-testbox.yml
job: check
ref: main
cache:
pnpm: true
npm: true
git: true
volumes:
- name: pnpm
key: openclaw-linux-node24-pnpm
path: /var/cache/crabbox/pnpm
sizeGB: 80
required: false
- name: npm
key: openclaw-linux-node24-npm
path: /var/cache/crabbox/npm
sizeGB: 40
required: false
aws:
# AWS-specific overrides still pin direct `--provider aws` runs without
# leaking AWS region names into the Azure default capacity fallback list.
region: eu-west-1
rootGB: 400
azure:
# The OpenClaw Azure subscription is reliable in eastus2; eastus rejects the
# same SKUs and can stall provisioning.
location: eastus2
sync:
delete: true
checksum: false
@@ -58,4 +71,64 @@ env:
- OPENCLAW_*
ssh:
user: crabbox
port: "2222"
# Azure coordinator leases expose SSH on 22. The run wrapper can fall back
# from 2222, but `crabbox job run` hydrates via the configured port directly.
port: "22"
jobs:
prewarm:
provider: azure
target: linux
class: standard
type: Standard_D4ads_v6
market: on-demand
idleTimeout: 90m
hydrate:
actions: true
waitTimeout: 20m
actions:
workflow: .github/workflows/crabbox-hydrate.yml
job: hydrate
ref: main
noSync: true
shell: true
command: "true"
stop: never
changed:
provider: azure
target: linux
class: standard
type: Standard_D4ads_v6
market: on-demand
idleTimeout: 90m
hydrate:
actions: true
waitTimeout: 20m
actions:
workflow: .github/workflows/crabbox-hydrate.yml
job: hydrate
ref: main
shell: true
command: |
set -euo pipefail
if ! git status --short >/dev/null 2>&1; then
rm -rf .git
git init -q
git add -A
if ! git diff --cached --quiet; then
git -c user.name=OpenClaw -c user.email=ci@openclaw.local commit -q --no-gpg-sign -m remote-check-tree
fi
fi
env CI=1 corepack pnpm check --timed
stop: always
testbox-changed:
provider: blacksmith-testbox
target: linux
idleTimeout: 90m
hydrate:
actions: false
actions:
workflow: .github/workflows/ci-check-testbox.yml
job: check
ref: main
command: env OPENCLAW_CHECK_CHANGED_REMOTE_CHILD=1 OPENCLAW_CHANGED_LANES_RAW_SYNC=1 CI=1 corepack pnpm check:changed
stop: always

View File

@@ -128,6 +128,7 @@ runs:
if [ -n "${PNPM_CONFIG_MODULES_DIR:-}" ]; then
mkdir -p "$PNPM_CONFIG_MODULES_DIR"
ln -sfn . "$PNPM_CONFIG_MODULES_DIR/node_modules"
export NODE_PATH="$PNPM_CONFIG_MODULES_DIR${NODE_PATH:+:$NODE_PATH}"
fi
pnpm "${install_args[@]}" || pnpm "${install_args[@]}"
if [ -n "${PNPM_CONFIG_MODULES_DIR:-}" ]; then

View File

@@ -7,8 +7,16 @@ queries:
- uses: ./.github/codeql/openclaw-boundary/queries/managed-proxy-runtime-mutation.ql
paths:
- src
- extensions
- src/cli/gateway-cli/run-loop.ts
- src/infra/gateway-lock.ts
- src/infra/jsonl-socket.ts
- src/infra/net
- src/infra/push-apns-http2.ts
- src/infra/ssh-tunnel.ts
- src/proxy-capture
- extensions/codex-supervisor/src/json-rpc-client.ts
- extensions/irc/src
- extensions/qa-lab/src
- packages/net-policy/src
paths-ignore:

9
.github/labeler.yml vendored
View File

@@ -132,6 +132,11 @@
- any-glob-to-any-file:
- "extensions/slack/**"
- "docs/channels/slack.md"
"channel: sms":
- changed-files:
- any-glob-to-any-file:
- "extensions/sms/**"
- "docs/channels/sms.md"
"channel: synology-chat":
- changed-files:
- any-glob-to-any-file:
@@ -569,6 +574,10 @@
- changed-files:
- any-glob-to-any-file:
- "extensions/openshell/**"
"extensions: parallel":
- changed-files:
- any-glob-to-any-file:
- "extensions/parallel/**"
"extensions: perplexity":
- changed-files:
- any-glob-to-any-file:

View File

@@ -27,7 +27,7 @@ jobs:
timeout-minutes: 35
steps:
- name: Begin Testbox
uses: useblacksmith/begin-testbox@d0e04585c26905fdd92c94a09c159544c7ee1b67
uses: useblacksmith/begin-testbox@233448af4bfdc6fca509a7f0974411ac6d8a8043
with:
testbox_id: ${{ inputs.testbox_id }}
@@ -231,7 +231,7 @@ jobs:
run: bash scripts/ci-hydrate-testbox-env.sh
- name: Run Testbox
uses: useblacksmith/run-testbox@5ca05834db1d3813554d1dd109e5f2087a8d7cbc
uses: useblacksmith/run-testbox@3f60ff9ceb2c10c3feefa87dc0c6490cffae059d
if: success()
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"

View File

@@ -0,0 +1,156 @@
name: Blacksmith ARM Testbox
on:
workflow_dispatch:
inputs:
testbox_id:
type: string
description: "Testbox session ID"
required: true
pull_request:
paths:
- ".github/workflows/**"
permissions:
contents: read
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
PNPM_CONFIG_STORE_DIR: "/tmp/openclaw-pnpm-store"
PNPM_CONFIG_VERIFY_DEPS_BEFORE_RUN: "false"
jobs:
check-arm:
if: ${{ github.event_name != 'pull_request' || !github.event.pull_request.draft }}
permissions:
contents: read
name: "check-arm"
runs-on: blacksmith-16vcpu-ubuntu-2404-arm
timeout-minutes: 120
steps:
- name: Begin Testbox
uses: useblacksmith/begin-testbox@d0e04585c26905fdd92c94a09c159544c7ee1b67
with:
testbox_id: ${{ inputs.testbox_id }}
- name: Verify ARM runner
shell: bash
run: |
set -euo pipefail
runner_arch="$(uname -m)"
echo "check-arm runner architecture: ${runner_arch}"
case "$runner_arch" in
aarch64 | arm64)
;;
*)
echo "check-arm requires an ARM64 runner; got ${runner_arch}" >&2
exit 1
;;
esac
- name: Checkout
shell: bash
env:
CHECKOUT_REPO: ${{ github.repository }}
CHECKOUT_SHA: ${{ github.sha }}
CHECKOUT_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
workdir="$GITHUB_WORKSPACE"
if [[ -z "$CHECKOUT_TOKEN" ]]; then
echo "checkout token is missing" >&2
exit 1
fi
auth_header="$(printf 'x-access-token:%s' "$CHECKOUT_TOKEN" | base64 | tr -d '\n')"
reset_checkout_dir() {
mkdir -p "$workdir"
find "$workdir" -mindepth 1 -maxdepth 1 -exec rm -rf {} +
}
checkout_attempt() {
local attempt="$1"
reset_checkout_dir
git init "$workdir" >/dev/null
git config --global --add safe.directory "$workdir"
git -C "$workdir" remote add origin "https://github.com/${CHECKOUT_REPO}"
git -C "$workdir" config gc.auto 0
timeout --signal=TERM --kill-after=10s 30s git -C "$workdir" \
-c protocol.version=2 \
-c "http.extraheader=AUTHORIZATION: basic ${auth_header}" \
fetch --no-tags --prune --no-recurse-submodules --depth=1 origin \
"+${CHECKOUT_SHA}:refs/remotes/origin/ci-target" || return 1
git -C "$workdir" checkout --force --detach "$CHECKOUT_SHA" || return 1
test -f "$workdir/.github/actions/setup-node-env/action.yml" || return 1
echo "checkout attempt ${attempt}/5 succeeded"
}
for attempt in 1 2 3 4 5; do
if checkout_attempt "$attempt"; then
exit 0
fi
echo "checkout attempt ${attempt}/5 failed"
sleep $((attempt * 5))
done
echo "checkout failed after 5 attempts" >&2
exit 1
- name: Setup Node environment
uses: ./.github/actions/setup-node-env
with:
install-bun: "false"
- name: Prepare Testbox shell
shell: bash
run: |
set -euo pipefail
timeout --signal=TERM --kill-after=10s 30s git \
-c protocol.version=2 \
fetch --no-tags --prune --no-recurse-submodules --depth=50 origin \
"+refs/heads/main:refs/remotes/origin/main"
node_bin="$(dirname "$(node -p 'process.execPath')")"
sudo ln -sf "$node_bin/node" /usr/local/bin/node
sudo ln -sf "$node_bin/npm" /usr/local/bin/npm
sudo ln -sf "$node_bin/npx" /usr/local/bin/npx
sudo ln -sf "$node_bin/corepack" /usr/local/bin/corepack
sudo tee /usr/local/bin/pnpm >/dev/null <<'PNPM'
#!/usr/bin/env bash
exec /usr/local/bin/corepack pnpm "$@"
PNPM
sudo chmod 0755 /usr/local/bin/pnpm
- name: Hydrate Testbox provider env helper
shell: bash
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
ANTHROPIC_API_KEY_OLD: ${{ secrets.ANTHROPIC_API_KEY_OLD }}
ANTHROPIC_API_TOKEN: ${{ secrets.ANTHROPIC_API_TOKEN }}
CEREBRAS_API_KEY: ${{ secrets.CEREBRAS_API_KEY }}
DEEPINFRA_API_KEY: ${{ secrets.DEEPINFRA_API_KEY }}
FACTORY_API_KEY: ${{ secrets.FACTORY_API_KEY }}
FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }}
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
KIMI_API_KEY: ${{ secrets.KIMI_API_KEY }}
MINIMAX_API_KEY: ${{ secrets.MINIMAX_API_KEY }}
MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }}
MOONSHOT_API_KEY: ${{ secrets.MOONSHOT_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL }}
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
QWEN_API_KEY: ${{ secrets.QWEN_API_KEY }}
TOGETHER_API_KEY: ${{ secrets.TOGETHER_API_KEY }}
XAI_API_KEY: ${{ secrets.XAI_API_KEY }}
ZAI_API_KEY: ${{ secrets.ZAI_API_KEY }}
Z_AI_API_KEY: ${{ secrets.Z_AI_API_KEY }}
run: bash scripts/ci-hydrate-testbox-env.sh
- name: Run Testbox
uses: useblacksmith/run-testbox@5ca05834db1d3813554d1dd109e5f2087a8d7cbc
if: success()
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"

View File

@@ -15,6 +15,8 @@ permissions:
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
PNPM_CONFIG_STORE_DIR: "/tmp/openclaw-pnpm-store"
PNPM_CONFIG_VERIFY_DEPS_BEFORE_RUN: "false"
jobs:
check:
@@ -26,7 +28,7 @@ jobs:
timeout-minutes: 30
steps:
- name: Begin Testbox
uses: useblacksmith/begin-testbox@d0e04585c26905fdd92c94a09c159544c7ee1b67
uses: useblacksmith/begin-testbox@233448af4bfdc6fca509a7f0974411ac6d8a8043
with:
testbox_id: ${{ inputs.testbox_id }}
- name: Checkout
@@ -133,7 +135,7 @@ jobs:
run: bash scripts/ci-hydrate-testbox-env.sh
- name: Run Testbox
uses: useblacksmith/run-testbox@5ca05834db1d3813554d1dd109e5f2087a8d7cbc
uses: useblacksmith/run-testbox@3f60ff9ceb2c10c3feefa87dc0c6490cffae059d
if: success()
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"

View File

@@ -92,7 +92,7 @@ jobs:
for attempt in 1 2 3; do
timeout --signal=TERM --kill-after=10s 30s git -C "$GITHUB_WORKSPACE" \
-c protocol.version=2 \
fetch --no-tags --prune --no-recurse-submodules --depth=1 origin \
fetch --no-tags --prune --no-recurse-submodules --depth=2 origin \
"+${ref}:refs/remotes/origin/checkout" && return 0
fetch_status="$?"
if [ "$fetch_status" != "124" ] && [ "$fetch_status" != "137" ]; then
@@ -146,12 +146,12 @@ jobs:
if [ "${{ github.event_name }}" = "push" ]; then
BASE="${{ github.event.before }}"
node scripts/ci-changed-scope.mjs --base "$BASE" --head HEAD
else
BASE="${{ github.event.pull_request.base.sha }}"
node scripts/ci-changed-scope.mjs --base "$BASE" --head HEAD --merge-head-first-parent
fi
node scripts/ci-changed-scope.mjs --base "$BASE" --head HEAD
- name: Build CI manifest
id: manifest
env:
@@ -601,11 +601,23 @@ jobs:
uses: actions/cache@v5
with:
path: .artifacts/build-all-cache
key: ${{ runner.os }}-build-all-v3-${{ hashFiles('package.json', 'pnpm-lock.yaml', 'npm-shrinkwrap.json', 'packages/plugin-sdk/package.json', 'packages/llm-core/package.json', 'packages/memory-host-sdk/package.json', 'scripts/build-all.mjs', 'scripts/write-plugin-sdk-entry-dts.ts', 'scripts/lib/plugin-sdk-entries.mjs', 'tsconfig.json', 'tsconfig.plugin-sdk.dts.json', 'src/plugin-sdk/**', 'packages/llm-core/src/**', 'packages/memory-host-sdk/src/**', 'src/types/**', 'src/video-generation/dashscope-compatible.ts', 'src/video-generation/types.ts', 'scripts/copy-export-html-templates.ts', 'scripts/lib/copy-assets.ts', 'src/auto-reply/reply/export-html/**') }}
key: ${{ runner.os }}-build-all-v3-${{ hashFiles('package.json', 'pnpm-lock.yaml', 'npm-shrinkwrap.json', 'packages/plugin-sdk/package.json', 'packages/llm-core/package.json', 'packages/model-catalog-core/package.json', 'packages/memory-host-sdk/package.json', 'scripts/build-all.mjs', 'scripts/write-plugin-sdk-entry-dts.ts', 'scripts/lib/plugin-sdk-entries.mjs', 'tsconfig.json', 'tsconfig.plugin-sdk.dts.json', 'src/plugin-sdk/**', 'packages/llm-core/src/**', 'packages/model-catalog-core/src/**', 'packages/memory-host-sdk/src/**', 'src/types/**', 'src/video-generation/dashscope-compatible.ts', 'src/video-generation/types.ts', 'scripts/copy-export-html-templates.ts', 'scripts/lib/copy-assets.ts', 'src/auto-reply/reply/export-html/**') }}
restore-keys: |
${{ runner.os }}-build-all-v3-
- name: Restore dist build cache
id: dist_build_cache
uses: actions/cache/restore@v5
with:
path: |
dist/
dist-runtime/
extensions/*/src/host/**/.bundle.hash
extensions/*/src/host/**/*.bundle.js
key: ${{ runner.os }}-dist-build-${{ needs.preflight.outputs.checkout_revision }}
- name: Build dist
if: steps.dist_build_cache.outputs.cache-hit != 'true'
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build:ci-artifacts
@@ -614,14 +626,6 @@ jobs:
if: needs.preflight.outputs.run_control_ui_i18n == 'true'
run: pnpm ui:i18n:check
- name: Cache dist build
uses: actions/cache@v5
with:
path: |
dist/
dist-runtime/
key: ${{ runner.os }}-dist-build-${{ needs.preflight.outputs.checkout_revision }}
- name: Pack built runtime artifacts
run: tar --posix -cf dist-runtime-build.tar.zst --use-compress-program zstdmt dist dist-runtime
@@ -751,6 +755,18 @@ jobs:
done
exit "$failures"
- name: Save dist build cache
if: steps.dist_build_cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v5
continue-on-error: true
with:
path: |
dist/
dist-runtime/
extensions/*/src/host/**/.bundle.hash
extensions/*/src/host/**/*.bundle.js
key: ${{ steps.dist_build_cache.outputs.cache-primary-key }}
- name: Upload gateway watch regression artifacts
if: always() && needs.preflight.outputs.run_check_additional == 'true'
uses: actions/upload-artifact@v7
@@ -834,10 +850,10 @@ jobs:
;;
contracts-plugins-ci-routing)
pnpm test:contracts:plugins
pnpm test src/commands/status.scan-result.test.ts src/scripts/ci-changed-scope.test.ts test/scripts/test-projects.test.ts
pnpm test src/commands/status.scan-result.test.ts src/scripts/ci-changed-scope.test.ts test/scripts/changed-lanes.test.ts test/scripts/run-vitest.test.ts test/scripts/test-projects.test.ts
;;
ci-routing)
pnpm test src/commands/status.scan-result.test.ts src/scripts/ci-changed-scope.test.ts test/scripts/test-projects.test.ts
pnpm test src/commands/status.scan-result.test.ts src/scripts/ci-changed-scope.test.ts test/scripts/changed-lanes.test.ts test/scripts/run-vitest.test.ts test/scripts/test-projects.test.ts
;;
bun-launcher)
OPENCLAW_TEST_BUN_LAUNCHER=1 pnpm test test/openclaw-launcher.e2e.test.ts
@@ -1151,6 +1167,8 @@ jobs:
OPENCLAW_NODE_TEST_CONFIGS_JSON: ${{ toJson(matrix.configs) }}
OPENCLAW_NODE_TEST_INCLUDE_PATTERNS_JSON: ${{ toJson(matrix.includePatterns) }}
OPENCLAW_VITEST_SHARD_NAME: ${{ matrix.shard_name }}
OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS: "300000"
OPENCLAW_VITEST_NO_OUTPUT_RETRY: "1"
OPENCLAW_TEST_PROJECTS_PARALLEL: "2"
shell: bash
run: |
@@ -1201,6 +1219,9 @@ jobs:
- check_name: check-guards
task: guards
runner: blacksmith-4vcpu-ubuntu-2404
- check_name: check-shrinkwrap
task: shrinkwrap
runner: blacksmith-4vcpu-ubuntu-2404
- check_name: check-prod-types
task: prod-types
runner: blacksmith-4vcpu-ubuntu-2404
@@ -1276,7 +1297,6 @@ jobs:
pnpm tool-display:check
pnpm check:host-env-policy:swift
pnpm dup:check:coverage
pnpm deps:shrinkwrap:check
pnpm deps:patches:check
pnpm lint:webhook:no-low-level-body-read
pnpm lint:auth:no-pairing-store-group
@@ -1285,6 +1305,9 @@ jobs:
# build-artifacts already runs the tsdown/runtime build for the same Node-relevant changes.
NODE_OPTIONS=--max-old-space-size=8192 pnpm build:plugin-sdk:strict-smoke
;;
shrinkwrap)
pnpm deps:shrinkwrap:check
;;
prod-types)
pnpm tsgo:prod
;;
@@ -1403,7 +1426,7 @@ jobs:
packages/plugin-sdk/dist
extensions/*/dist/.boundary-tsc.tsbuildinfo
extensions/*/dist/.boundary-tsc.stamp
key: ${{ runner.os }}-extension-package-boundary-v1-${{ hashFiles('tsconfig.json', 'tsconfig.plugin-sdk.dts.json', 'packages/plugin-sdk/tsconfig.json', 'packages/llm-core/package.json', 'scripts/check-extension-package-tsc-boundary.mjs', 'scripts/prepare-extension-package-boundary-artifacts.mjs', 'scripts/write-plugin-sdk-entry-dts.ts', 'scripts/lib/plugin-sdk-entrypoints.json', 'scripts/lib/plugin-sdk-entries.mjs', 'src/plugin-sdk/**', 'src/auto-reply/**', 'packages/llm-core/src/**', 'src/video-generation/dashscope-compatible.ts', 'src/video-generation/types.ts', 'src/types/**', 'extensions/**', 'extensions/tsconfig.package-boundary*.json', 'package.json', 'pnpm-lock.yaml') }}
key: ${{ runner.os }}-extension-package-boundary-v1-${{ hashFiles('tsconfig.json', 'tsconfig.plugin-sdk.dts.json', 'packages/plugin-sdk/tsconfig.json', 'packages/llm-core/package.json', 'packages/model-catalog-core/package.json', 'scripts/check-extension-package-tsc-boundary.mjs', 'scripts/prepare-extension-package-boundary-artifacts.mjs', 'scripts/write-plugin-sdk-entry-dts.ts', 'scripts/lib/plugin-sdk-entrypoints.json', 'scripts/lib/plugin-sdk-entries.mjs', 'src/plugin-sdk/**', 'src/plugins/types.ts', 'src/auto-reply/**', 'packages/llm-core/src/**', 'packages/model-catalog-core/src/**', 'src/video-generation/dashscope-compatible.ts', 'src/video-generation/types.ts', 'src/types/**', 'extensions/**', 'extensions/tsconfig.package-boundary*.json', 'package.json', 'pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-extension-package-boundary-v1-
@@ -1420,14 +1443,22 @@ jobs:
find src \
-type f \( -name '*.ts' -o -name '*.tsx' -o -name '*.mts' -o -name '*.cts' -o -name '*.js' -o -name '*.mjs' -o -name '*.json' \) \
-exec touch -t 200001010000 {} +
find packages/llm-core/src \
-type f \( -name '*.ts' -o -name '*.tsx' -o -name '*.mts' -o -name '*.cts' -o -name '*.js' -o -name '*.mjs' -o -name '*.json' \) \
-exec touch -t 200001010000 {} +
touch -t 200001010000 \
if [ -d packages/llm-core/src ]; then
find packages/llm-core/src \
-type f \( -name '*.ts' -o -name '*.tsx' -o -name '*.mts' -o -name '*.cts' -o -name '*.js' -o -name '*.mjs' -o -name '*.json' \) \
-exec touch -t 200001010000 {} +
fi
if [ -d packages/model-catalog-core/src ]; then
find packages/model-catalog-core/src \
-type f \( -name '*.ts' -o -name '*.tsx' -o -name '*.mts' -o -name '*.cts' -o -name '*.js' -o -name '*.mjs' -o -name '*.json' \) \
-exec touch -t 200001010000 {} +
fi
cache_inputs=(
tsconfig.json \
tsconfig.plugin-sdk.dts.json \
packages/plugin-sdk/tsconfig.json \
packages/llm-core/package.json \
packages/model-catalog-core/package.json \
scripts/check-extension-package-tsc-boundary.mjs \
scripts/prepare-extension-package-boundary-artifacts.mjs \
scripts/write-plugin-sdk-entry-dts.ts \
@@ -1435,6 +1466,12 @@ jobs:
scripts/lib/plugin-sdk-entries.mjs \
package.json \
pnpm-lock.yaml
)
for cache_input in "${cache_inputs[@]}"; do
if [ -e "$cache_input" ]; then
touch -t 200001010000 "$cache_input"
fi
done
- name: Run additional check shard
env:
@@ -1957,6 +1994,21 @@ jobs:
done
exit 1
- name: OpenClawKit Talk-trait opt-out (no ElevenLabsKit when default traits disabled)
run: |
set -euo pipefail
# Guard: chat-only consumers build OpenClawKit with the Talk trait
# disabled and must NOT link ElevenLabsKit. Assert that future sources
# under OpenClawKit cannot silently reintroduce an unconditional
# ElevenLabsKit dependency while the manifest still looks correct.
deps="$(swift package --package-path apps/shared/OpenClawKit show-dependencies --disable-default-traits)"
echo "$deps"
if grep -qi 'elevenlabs' <<<"$deps"; then
echo "::error::ElevenLabsKit resolved with the Talk trait disabled; keep it gated behind the Talk trait."
exit 1
fi
swift build --package-path apps/shared/OpenClawKit --target OpenClawKit --disable-default-traits
- name: Swift test
run: |
set -euo pipefail

View File

@@ -35,7 +35,7 @@ jobs:
java-version: "21"
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/init@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
languages: java-kotlin
build-mode: manual
@@ -46,6 +46,6 @@ jobs:
run: ./gradlew --no-daemon :app:assemblePlayDebug
- name: Analyze
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/analyze@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
category: "/codeql-critical-security/android"

View File

@@ -210,6 +210,9 @@ jobs:
else
while IFS= read -r file; do
case "${file}" in
.github/codeql/codeql-network-runtime-boundary-critical-quality.yml|.github/codeql/openclaw-boundary/queries/raw-socket-callsite-classification.ql|.github/codeql/openclaw-boundary/queries/managed-proxy-runtime-mutation.ql)
network_runtime=true
;;
.github/codeql/*|.github/workflows/codeql-critical-quality.yml)
agent=true
channel=true
@@ -222,7 +225,6 @@ jobs:
plugin_sdk_package=true
plugin_sdk_reply=true
provider=true
network_runtime=true
session_diagnostics=true
;;
src/agents/sessions/tools/*)
@@ -302,7 +304,9 @@ jobs:
esac
case "${file}" in
src/*.ts|src/**/*.ts|extensions/*.ts|extensions/**/*.ts|packages/net-policy/src/*|packages/net-policy/src/**/*)
src/**/*.test.ts|src/**/*.test.tsx|extensions/**/*.test.ts|extensions/**/*.test.tsx)
;;
packages/net-policy/src/*|packages/net-policy/src/**/*|src/cli/gateway-cli/run-loop.ts|src/infra/net/*|src/infra/net/**/*|src/infra/ssh-tunnel.ts|src/infra/gateway-lock.ts|src/infra/jsonl-socket.ts|src/infra/push-apns-http2.ts|src/proxy-capture/*|src/proxy-capture/**/*|extensions/codex-supervisor/src/json-rpc-client.ts|extensions/irc/src/*|extensions/qa-lab/src/*)
network_runtime=true
;;
esac
@@ -338,13 +342,13 @@ jobs:
submodules: false
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/init@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
languages: javascript-typescript
config-file: ./.github/codeql/codeql-core-auth-secrets-critical-quality.yml
- name: Analyze
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/analyze@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
category: "/codeql-critical-quality/core-auth-secrets"
@@ -361,13 +365,13 @@ jobs:
submodules: false
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/init@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
languages: javascript-typescript
config-file: ./.github/codeql/codeql-config-boundary-critical-quality.yml
- name: Analyze
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/analyze@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
category: "/codeql-critical-quality/config-boundary"
@@ -384,13 +388,13 @@ jobs:
submodules: false
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/init@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
languages: javascript-typescript
config-file: ./.github/codeql/codeql-gateway-runtime-boundary-critical-quality.yml
- name: Analyze
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/analyze@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
category: "/codeql-critical-quality/gateway-runtime-boundary"
@@ -407,13 +411,13 @@ jobs:
submodules: false
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/init@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
languages: javascript-typescript
config-file: ./.github/codeql/codeql-channel-runtime-boundary-critical-quality.yml
- name: Analyze
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/analyze@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
category: "/codeql-critical-quality/channel-runtime-boundary"
@@ -429,20 +433,48 @@ jobs:
with:
submodules: false
- name: Fast PR network boundary diff scan
if: ${{ github.event_name == 'pull_request' }}
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.pull_request.number }}
REPOSITORY: ${{ github.repository }}
run: |
set -euo pipefail
added_lines="$(mktemp)"
gh api --paginate "repos/${REPOSITORY}/pulls/${PR_NUMBER}/files" --jq '
.[]
| select(.filename | test("^(src/cli/gateway-cli/run-loop\\.ts|src/infra/(gateway-lock|jsonl-socket|push-apns-http2|ssh-tunnel)\\.ts|src/infra/net/|src/proxy-capture/|extensions/codex-supervisor/src/json-rpc-client\\.ts|extensions/irc/src/|extensions/qa-lab/src/|packages/net-policy/src/)"))
| .filename as $file
| (.patch // "")
| split("\n")[]
| select(startswith("+") and (startswith("+++") | not))
| "\($file): \(.)"
' > "$added_lines"
if grep -En '(from|require\().*["'\''](node:)?(net|tls|http2)["'\'']|\b(net|tls|http2)\.(connect|createConnection)\b|new Socket\(|HTTP_PROXY|HTTPS_PROXY|NO_PROXY|GLOBAL_AGENT_|OPENCLAW_PROXY_' "$added_lines"; then
echo "Network runtime boundary-sensitive added lines require full CodeQL review." >&2
exit 1
fi
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
if: ${{ github.event_name != 'pull_request' }}
uses: github/codeql-action/init@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
languages: javascript-typescript
config-file: ./.github/codeql/codeql-network-runtime-boundary-critical-quality.yml
- name: Analyze
id: analyze
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
if: ${{ github.event_name != 'pull_request' }}
uses: github/codeql-action/analyze@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
output: sarif-results
category: "/codeql-critical-quality/network-runtime-boundary"
- name: Fail on network runtime boundary findings
if: ${{ github.event_name != 'pull_request' }}
env:
SARIF_OUTPUT: sarif-results
run: |
@@ -486,13 +518,13 @@ jobs:
submodules: false
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/init@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
languages: javascript-typescript
config-file: ./.github/codeql/codeql-agent-runtime-boundary-critical-quality.yml
- name: Analyze
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/analyze@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
category: "/codeql-critical-quality/agent-runtime-boundary"
@@ -509,13 +541,13 @@ jobs:
submodules: false
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/init@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
languages: javascript-typescript
config-file: ./.github/codeql/codeql-mcp-process-runtime-boundary-critical-quality.yml
- name: Analyze
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/analyze@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
category: "/codeql-critical-quality/mcp-process-runtime-boundary"
@@ -532,13 +564,13 @@ jobs:
submodules: false
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/init@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
languages: javascript-typescript
config-file: ./.github/codeql/codeql-memory-runtime-boundary-critical-quality.yml
- name: Analyze
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/analyze@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
category: "/codeql-critical-quality/memory-runtime-boundary"
@@ -555,13 +587,13 @@ jobs:
submodules: false
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/init@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
languages: javascript-typescript
config-file: ./.github/codeql/codeql-session-diagnostics-boundary-critical-quality.yml
- name: Analyze
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/analyze@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
category: "/codeql-critical-quality/session-diagnostics-boundary"
@@ -578,13 +610,13 @@ jobs:
submodules: false
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/init@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
languages: javascript-typescript
config-file: ./.github/codeql/codeql-plugin-sdk-reply-runtime-critical-quality.yml
- name: Analyze
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/analyze@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
category: "/codeql-critical-quality/plugin-sdk-reply-runtime"
@@ -601,13 +633,13 @@ jobs:
submodules: false
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/init@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
languages: javascript-typescript
config-file: ./.github/codeql/codeql-provider-runtime-boundary-critical-quality.yml
- name: Analyze
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/analyze@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
category: "/codeql-critical-quality/provider-runtime-boundary"
@@ -623,13 +655,13 @@ jobs:
submodules: false
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/init@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
languages: javascript-typescript
config-file: ./.github/codeql/codeql-ui-control-plane-critical-quality.yml
- name: Analyze
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/analyze@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
category: "/codeql-critical-quality/ui-control-plane"
@@ -645,13 +677,13 @@ jobs:
submodules: false
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/init@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
languages: javascript-typescript
config-file: ./.github/codeql/codeql-web-media-runtime-boundary-critical-quality.yml
- name: Analyze
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/analyze@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
category: "/codeql-critical-quality/web-media-runtime-boundary"
@@ -668,13 +700,13 @@ jobs:
submodules: false
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/init@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
languages: javascript-typescript
config-file: ./.github/codeql/codeql-plugin-boundary-critical-quality.yml
- name: Analyze
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/analyze@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
category: "/codeql-critical-quality/plugin-boundary"
@@ -691,12 +723,12 @@ jobs:
submodules: false
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/init@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
languages: javascript-typescript
config-file: ./.github/codeql/codeql-plugin-sdk-package-contract-critical-quality.yml
- name: Analyze
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/analyze@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
category: "/codeql-critical-quality/plugin-sdk-package-contract"

View File

@@ -35,7 +35,7 @@ jobs:
swift --version
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/init@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
languages: swift
build-mode: manual
@@ -46,7 +46,7 @@ jobs:
- name: Analyze
id: analyze
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/analyze@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
output: sarif-results
upload: failure-only
@@ -83,7 +83,7 @@ jobs:
done
- name: Upload filtered SARIF
uses: github/codeql-action/upload-sarif@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/upload-sarif@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
sarif_file: sarif-results-filtered
category: "/codeql-critical-security/macos"

View File

@@ -101,12 +101,12 @@ jobs:
.github/codeql
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/init@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
languages: ${{ matrix.language }}
config-file: ${{ matrix.config_file }}
- name: Analyze
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
uses: github/codeql-action/analyze@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4
with:
category: "/codeql-security-high/${{ matrix.category }}"

View File

@@ -32,11 +32,11 @@ permissions:
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
PNPM_CONFIG_CHILD_CONCURRENCY: "1"
PNPM_CONFIG_MODULES_DIR: "/tmp/openclaw-pnpm-node-modules"
PNPM_CONFIG_MODULES_DIR: "/var/tmp/openclaw-pnpm/node_modules"
PNPM_CONFIG_NETWORK_CONCURRENCY: "1"
PNPM_CONFIG_STORE_DIR: "/tmp/openclaw-pnpm-store"
PNPM_CONFIG_STORE_DIR: "/var/cache/crabbox/pnpm/store"
PNPM_CONFIG_VERIFY_DEPS_BEFORE_RUN: "false"
PNPM_CONFIG_VIRTUAL_STORE_DIR: "/tmp/openclaw-pnpm-virtual-store"
PNPM_CONFIG_VIRTUAL_STORE_DIR: "/var/tmp/openclaw-pnpm/virtual-store"
jobs:
hydrate:
@@ -120,9 +120,31 @@ jobs:
append_pnpm_option_arg PNPM_CONFIG_MODULES_DIR modules-dir
append_pnpm_option_arg PNPM_CONFIG_NETWORK_CONCURRENCY network-concurrency
append_pnpm_option_arg PNPM_CONFIG_VIRTUAL_STORE_DIR virtual-store-dir
require_safe_writable_dir() {
local dir="$1"
if [ -L "$dir" ] || [ ! -d "$dir" ] || [ ! -w "$dir" ]; then
echo "::error::Refusing unsafe pnpm directory: $dir"
exit 1
fi
}
prepare_crabbox_pnpm_dirs() {
local volatile_root="/var/tmp/openclaw-pnpm"
case "${PNPM_CONFIG_MODULES_DIR:?}" in "$volatile_root"/*) ;; *) echo "::error::PNPM_CONFIG_MODULES_DIR must stay under $volatile_root"; exit 1 ;; esac
case "${PNPM_CONFIG_VIRTUAL_STORE_DIR:?}" in "$volatile_root"/*) ;; *) echo "::error::PNPM_CONFIG_VIRTUAL_STORE_DIR must stay under $volatile_root"; exit 1 ;; esac
rm -rf -- "$volatile_root"
mkdir -p "$volatile_root" "$PNPM_CONFIG_STORE_DIR"
require_safe_writable_dir "$volatile_root"
require_safe_writable_dir "$PNPM_CONFIG_STORE_DIR"
mkdir -p "$PNPM_CONFIG_MODULES_DIR" "$PNPM_CONFIG_VIRTUAL_STORE_DIR"
}
prepare_crabbox_pnpm_dirs
if [ -L node_modules ] && [ "$(readlink node_modules)" = "${PNPM_CONFIG_MODULES_DIR:-}" ]; then
rm -f node_modules
fi
if [ -n "${PNPM_CONFIG_MODULES_DIR:-}" ]; then
mkdir -p "$PNPM_CONFIG_MODULES_DIR"
ln -sfn . "$PNPM_CONFIG_MODULES_DIR/node_modules"
export NODE_PATH="$PNPM_CONFIG_MODULES_DIR${NODE_PATH:+:$NODE_PATH}"
fi
pnpm "${install_args[@]}" || pnpm "${install_args[@]}"
if [ -n "${PNPM_CONFIG_MODULES_DIR:-}" ]; then
@@ -356,9 +378,10 @@ jobs:
$env:XDG_CACHE_HOME = Join-Path $cacheRoot "cache"
$env:COREPACK_HOME = Join-Path $env:XDG_CACHE_HOME "corepack"
$env:PNPM_HOME = Join-Path $cacheRoot "pnpm-home"
$env:PNPM_CONFIG_STORE_DIR = Join-Path $cacheRoot "openclaw-pnpm-store"
$env:PNPM_CONFIG_MODULES_DIR = Join-Path $workspace "node_modules"
$env:PNPM_CONFIG_VIRTUAL_STORE_DIR = Join-Path $workspace "node_modules\.pnpm"
$pnpmCacheRoot = Join-Path $cacheRoot "openclaw-pnpm"
$env:PNPM_CONFIG_STORE_DIR = Join-Path $pnpmCacheRoot "store"
$env:PNPM_CONFIG_MODULES_DIR = Join-Path $pnpmCacheRoot "node_modules"
$env:PNPM_CONFIG_VIRTUAL_STORE_DIR = Join-Path $pnpmCacheRoot "virtual-store"
$env:PNPM_CONFIG_CHILD_CONCURRENCY = "4"
$env:PNPM_CONFIG_NETWORK_CONCURRENCY = "8"
$env:PNPM_CONFIG_VERIFY_DEPS_BEFORE_RUN = "false"
@@ -430,6 +453,25 @@ jobs:
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
$workspaceNodeModules = Join-Path $workspace "node_modules"
if (Test-Path $workspaceNodeModules) {
$workspaceNodeModulesItem = Get-Item $workspaceNodeModules -Force
if (($workspaceNodeModulesItem.Attributes -band [System.IO.FileAttributes]::ReparsePoint) -eq 0) {
$nodeModulesChildren = @(Get-ChildItem -LiteralPath $workspaceNodeModules -Force)
$hasOnlyPnpmWorkspaceState = $nodeModulesChildren.Count -eq 1 -and $nodeModulesChildren[0].Name -eq ".pnpm-workspace-state-v1.json"
if ($nodeModulesChildren.Count -ne 0 -and -not $hasOnlyPnpmWorkspaceState) {
throw "workspace node_modules exists and is not a link: $workspaceNodeModules"
}
foreach ($nodeModulesChild in $nodeModulesChildren) {
Remove-Item -LiteralPath $nodeModulesChild.FullName -Force
}
Remove-Item -LiteralPath $workspaceNodeModules -Force
New-Item -ItemType Junction -Path $workspaceNodeModules -Target $env:PNPM_CONFIG_MODULES_DIR | Out-Null
}
} else {
New-Item -ItemType Junction -Path $workspaceNodeModules -Target $env:PNPM_CONFIG_MODULES_DIR | Out-Null
}
$corepackShimDir = Join-Path $nodeBin "node_modules\corepack\shims"
if (Test-Path $corepackShimDir) {
$env:PNPM_HOME = $corepackShimDir

View File

@@ -4,6 +4,7 @@ on:
push:
tags:
- "v*"
- "!v*-alpha.*"
paths-ignore:
- "docs/**"
- "**/*.md"
@@ -38,7 +39,11 @@ jobs:
RELEASE_TAG: ${{ inputs.tag }}
run: |
set -euo pipefail
if [[ ! "${RELEASE_TAG}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*(-(alpha|beta)\.[1-9][0-9]*)?$ ]]; then
if [[ "${RELEASE_TAG}" == *"-alpha."* ]]; then
echo "Docker alpha image publishing is disabled."
exit 1
fi
if [[ ! "${RELEASE_TAG}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*(-beta\.[1-9][0-9]*)?$ ]]; then
echo "Invalid release tag: ${RELEASE_TAG}"
exit 1
fi
@@ -84,7 +89,7 @@ jobs:
fetch-depth: 0
- name: Set up Docker Builder
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4
- name: Login to GitHub Container Registry
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
@@ -156,7 +161,7 @@ jobs:
- name: Build and push amd64 image
id: build
# WARNING: KEEP THE OFFICIAL DOCKER ACTION HERE; DO NOT SWITCH THIS BACK TO BLACKSMITH BLINDLY.
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .
platforms: linux/amd64
@@ -174,7 +179,7 @@ jobs:
id: build-browser
if: steps.tags.outputs.browser != ''
# WARNING: KEEP THE OFFICIAL DOCKER ACTION HERE; DO NOT SWITCH THIS BACK TO BLACKSMITH BLINDLY.
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .
platforms: linux/amd64
@@ -275,7 +280,7 @@ jobs:
fetch-depth: 0
- name: Set up Docker Builder
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4
- name: Login to GitHub Container Registry
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
@@ -347,7 +352,7 @@ jobs:
- name: Build and push arm64 image
id: build
# WARNING: KEEP THE OFFICIAL DOCKER ACTION HERE; DO NOT SWITCH THIS BACK TO BLACKSMITH BLINDLY.
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .
platforms: linux/arm64
@@ -365,7 +370,7 @@ jobs:
id: build-browser
if: steps.tags.outputs.browser != ''
# WARNING: KEEP THE OFFICIAL DOCKER ACTION HERE; DO NOT SWITCH THIS BACK TO BLACKSMITH BLINDLY.
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .
platforms: linux/arm64
@@ -557,7 +562,7 @@ jobs:
fetch-depth: 1
- name: Set up Docker Builder
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4
- name: Login to GitHub Container Registry
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4

View File

@@ -149,7 +149,7 @@ jobs:
- name: Run Codex docs agent
if: steps.gate.outputs.run_agent == 'true'
uses: openai/codex-action@5c3f4ccdb2b8790f73d6b21751ac00e602aa0c02
uses: openai/codex-action@e0fdf01220eb9a88167c4898839d273e3f2609d1
env:
DOCS_AGENT_BASE_SHA: ${{ steps.gate.outputs.review_base_sha }}
DOCS_AGENT_HEAD_SHA: ${{ steps.gate.outputs.review_head_sha }}

View File

@@ -229,7 +229,7 @@ jobs:
needs: [resolve_target]
if: inputs.rerun_group == 'all'
runs-on: ubuntu-24.04
timeout-minutes: 45
timeout-minutes: 20
permissions:
contents: read
steps:
@@ -245,54 +245,11 @@ jobs:
DOCKER_BUILDKIT: "1"
run: |
set -euo pipefail
timeout --kill-after=30s 35m docker build \
timeout --kill-after=30s 15m docker build \
--target runtime-assets \
--build-arg OPENCLAW_EXTENSIONS="diagnostics-otel,codex" \
.
- name: Build and smoke test final Docker runtime image
env:
DOCKER_BUILDKIT: "1"
TARGET_SHA: ${{ needs.resolve_target.outputs.sha }}
run: |
set -euo pipefail
image_ref="openclaw-release-runtime-smoke:${TARGET_SHA}"
timeout --kill-after=30s 35m docker build \
--build-arg OPENCLAW_EXTENSIONS="diagnostics-otel,codex" \
-t "${image_ref}" \
.
docker run --rm --entrypoint /bin/sh "${image_ref}" -lc '
set -eu
test -f /app/src/agents/templates/HEARTBEAT.md
temp_root="$(mktemp -d)"
trap "rm -rf \"${temp_root}\"" EXIT
mkdir -p "${temp_root}/home" "${temp_root}/cwd"
cd "${temp_root}/cwd"
set +e
HOME="${temp_root}/home" \
USERPROFILE="${temp_root}/home" \
OPENCLAW_HOME="${temp_root}/home" \
OPENCLAW_NO_ONBOARD=1 \
OPENCLAW_SUPPRESS_NOTES=1 \
OPENCLAW_DISABLE_BUNDLED_PLUGINS=1 \
OPENCLAW_DISABLE_BUNDLED_ENTRY_SOURCE_FALLBACK=1 \
AWS_EC2_METADATA_DISABLED=true \
AWS_SHARED_CREDENTIALS_FILE="${temp_root}/home/.aws/credentials" \
AWS_CONFIG_FILE="${temp_root}/home/.aws/config" \
node /app/openclaw.mjs agent --message "workspace bootstrap smoke" --session-id "workspace-bootstrap-smoke" --local --timeout 1 --json \
>"${temp_root}/out.log" 2>&1
status="$?"
set -e
if grep -F "Missing workspace template:" "${temp_root}/out.log"; then
cat "${temp_root}/out.log"
exit 1
fi
test -f "${temp_root}/home/.openclaw/workspace/HEARTBEAT.md"
if [ "${status}" -ne 0 ]; then
cat "${temp_root}/out.log"
fi
'
normal_ci:
name: Run normal full CI
needs: [resolve_target, docker_runtime_assets_preflight]
@@ -380,6 +337,21 @@ jobs:
gh_with_retry api --paginate "repos/${GITHUB_REPOSITORY}/actions/runs/${run_id}/jobs?per_page=100" --jq '.jobs[]'
}
fail_fast_failed_jobs() {
local failed_jobs_json
failed_jobs_json="$(
fetch_child_jobs |
jq -s '[.[] | select(.status == "completed" and .conclusion != "success" and .conclusion != "skipped")]'
)"
if jq -e 'length > 0' <<< "$failed_jobs_json" >/dev/null; then
echo "::error::${workflow} has failed child jobs before the workflow completed; cancelling the remaining matrix."
jq '.[] | {name, conclusion, url: .html_url}' <<< "$failed_jobs_json"
cancel_child
trap - EXIT INT TERM
exit 1
fi
}
cancel_child() {
if [[ -n "${run_id:-}" ]]; then
echo "Cancelling child workflow ${workflow}: ${run_id}" >&2
@@ -395,6 +367,9 @@ jobs:
break
fi
poll_count=$((poll_count + 1))
if (( poll_count % 2 == 0 )); then
fail_fast_failed_jobs
fi
if (( poll_count % 10 == 0 )); then
echo "Still waiting on ${workflow}: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${run_id}"
fetch_child_jobs | jq 'select(.status != "completed") | {name, status, url: .html_url}' || true
@@ -510,6 +485,21 @@ jobs:
gh_with_retry api --paginate "repos/${GITHUB_REPOSITORY}/actions/runs/${run_id}/jobs?per_page=100" --jq '.jobs[]'
}
fail_fast_failed_jobs() {
local failed_jobs_json
failed_jobs_json="$(
fetch_child_jobs |
jq -s '[.[] | select(.status == "completed" and .conclusion != "success" and .conclusion != "skipped")]'
)"
if jq -e 'length > 0' <<< "$failed_jobs_json" >/dev/null; then
echo "::error::${workflow} has failed child jobs before the workflow completed; cancelling the remaining matrix."
jq '.[] | {name, conclusion, url: .html_url}' <<< "$failed_jobs_json"
cancel_child
trap - EXIT INT TERM
exit 1
fi
}
cancel_child() {
if [[ -n "${run_id:-}" ]]; then
echo "Cancelling child workflow ${workflow}: ${run_id}" >&2
@@ -525,6 +515,9 @@ jobs:
break
fi
poll_count=$((poll_count + 1))
if (( poll_count % 2 == 0 )); then
fail_fast_failed_jobs
fi
if (( poll_count % 10 == 0 )); then
echo "Still waiting on ${workflow}: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${run_id}"
fetch_child_jobs | jq 'select(.status != "completed") | {name, status, url: .html_url}' || true
@@ -690,6 +683,24 @@ jobs:
[[ "$saw_advisory" == "1" && "$failed" == "0" ]]
}
fail_fast_failed_jobs() {
local failed_jobs_json
if [[ "$workflow" == "openclaw-release-checks.yml" && "$CHILD_WORKFLOW_REF" =~ ^tideclaw/alpha/[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{4}Z$ ]]; then
return 0
fi
failed_jobs_json="$(
fetch_child_jobs |
jq -s '[.[] | select(.status == "completed" and .conclusion != "success" and .conclusion != "skipped")]'
)"
if jq -e 'length > 0' <<< "$failed_jobs_json" >/dev/null; then
echo "::error::${workflow} has failed child jobs before the workflow completed; cancelling the remaining matrix."
jq '.[] | {name, conclusion, url: .html_url}' <<< "$failed_jobs_json"
cancel_child
trap - EXIT INT TERM
exit 1
fi
}
cancel_child() {
if [[ -n "${run_id:-}" ]]; then
echo "Cancelling child workflow ${workflow}: ${run_id}" >&2
@@ -705,6 +716,9 @@ jobs:
break
fi
poll_count=$((poll_count + 1))
if (( poll_count % 2 == 0 )); then
fail_fast_failed_jobs
fi
if (( poll_count % 10 == 0 )); then
echo "Still waiting on ${workflow}: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${run_id}"
fetch_child_jobs | jq 'select(.status != "completed") | {name, status, url: .html_url}' || true
@@ -962,6 +976,21 @@ jobs:
}
trap cancel_child EXIT INT TERM
fail_fast_failed_jobs() {
local failed_jobs_json
failed_jobs_json="$(
gh_with_retry run view "$run_id" --json jobs \
--jq '[.jobs[] | select(.status == "completed" and .conclusion != "success" and .conclusion != "skipped")]'
)"
if jq -e 'length > 0' <<< "$failed_jobs_json" >/dev/null; then
echo "::error::npm-telegram-beta-e2e.yml has failed child jobs before the workflow completed; cancelling the remaining run."
jq '.[] | {name, conclusion, url}' <<< "$failed_jobs_json"
cancel_child
trap - EXIT INT TERM
exit 1
fi
}
poll_count=0
while true; do
status="$(gh_with_retry run view "$run_id" --json status --jq '.status')"
@@ -969,6 +998,9 @@ jobs:
break
fi
poll_count=$((poll_count + 1))
if (( poll_count % 2 == 0 )); then
fail_fast_failed_jobs
fi
if (( poll_count % 10 == 0 )); then
echo "Still waiting on npm-telegram-beta-e2e.yml: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${run_id}"
gh_with_retry run view "$run_id" --json jobs --jq '.jobs[] | select(.status != "completed") | {name, status, url}' || true

View File

@@ -29,7 +29,7 @@ jobs:
uses: actions/checkout@v6
- name: Login to GHCR
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
registry: ghcr.io
username: ${{ github.actor }}

View File

@@ -445,7 +445,7 @@ jobs:
sudo chown -R codex:codex "$GITHUB_WORKSPACE"
- name: Run Codex Mantis Telegram agent
uses: openai/codex-action@5c3f4ccdb2b8790f73d6b21751ac00e602aa0c02
uses: openai/codex-action@e0fdf01220eb9a88167c4898839d273e3f2609d1
env:
BASELINE_REF: ${{ needs.resolve_request.outputs.baseline_ref }}
BASELINE_SHA: ${{ needs.validate_refs.outputs.baseline_revision }}

View File

@@ -563,7 +563,7 @@ jobs:
needs: validate_selected_ref
if: inputs.include_repo_e2e && inputs.live_suite_filter == ''
continue-on-error: ${{ inputs.advisory }}
runs-on: ${{ inputs.use_github_hosted_runners && 'ubuntu-24.04' || 'blacksmith-8vcpu-ubuntu-2404' }}
runs-on: ${{ inputs.use_github_hosted_runners && 'ubuntu-24.04' || 'blacksmith-32vcpu-ubuntu-2404' }}
timeout-minutes: ${{ inputs.release_test_profile == 'full' && 90 || 60 }}
env:
OPENCLAW_VITEST_MAX_WORKERS: "2"
@@ -595,7 +595,7 @@ jobs:
needs: validate_selected_ref
if: inputs.include_repo_e2e && (inputs.live_suite_filter == '' || inputs.live_suite_filter == 'openshell-e2e')
continue-on-error: ${{ inputs.advisory }}
runs-on: ${{ inputs.use_github_hosted_runners && 'ubuntu-24.04' || 'blacksmith-8vcpu-ubuntu-2404' }}
runs-on: ${{ inputs.use_github_hosted_runners && 'ubuntu-24.04' || 'blacksmith-32vcpu-ubuntu-2404' }}
timeout-minutes: ${{ matrix.timeout_minutes }}
strategy:
fail-fast: false
@@ -1953,7 +1953,7 @@ jobs:
profiles: stable full
- suite_id: native-live-src-gateway-profiles-minimax
label: Native live gateway profiles MiniMax
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=minimax,minimax-portal OPENCLAW_LIVE_GATEWAY_MODELS=minimax/MiniMax-M2.7,minimax-portal/MiniMax-M2.7 OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2 node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=minimax,minimax-portal OPENCLAW_LIVE_GATEWAY_MODELS=minimax/MiniMax-M3,minimax-portal/MiniMax-M3 OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2 node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
timeout_minutes: 60
profile_env_only: false
profiles: stable full
@@ -2252,7 +2252,7 @@ jobs:
profiles: stable full
- suite_id: live-gateway-minimax-docker
label: Docker live gateway MiniMax
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=minimax,minimax-portal OPENCLAW_LIVE_GATEWAY_MODELS=minimax/MiniMax-M2.7,minimax-portal/MiniMax-M2.7 OPENCLAW_LIVE_GATEWAY_MAX_MODELS=1 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=90000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=180000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 35m bash .release-harness/scripts/test-live-gateway-models-docker.sh
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=minimax,minimax-portal OPENCLAW_LIVE_GATEWAY_MODELS=minimax/MiniMax-M3,minimax-portal/MiniMax-M3 OPENCLAW_LIVE_GATEWAY_MAX_MODELS=1 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=90000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=180000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 35m bash .release-harness/scripts/test-live-gateway-models-docker.sh
timeout_minutes: 40
profile_env_only: false
profiles: stable full

View File

@@ -51,7 +51,8 @@ jobs:
# so this source workflow can stay focused on OIDC publish only.
preflight_openclaw_npm:
if: ${{ inputs.preflight_only }}
runs-on: ubuntu-latest
# Preflight builds the full release package before publish; ubuntu-latest can OOM in tsdown.
runs-on: blacksmith-16vcpu-ubuntu-2404
permissions:
contents: read
steps:
@@ -256,7 +257,8 @@ jobs:
return -1;
}
for (let start = input.indexOf("["); start !== -1; start = input.indexOf("[", start + 1)) {
for (const match of input.matchAll(/\[/g)) {
const start = match.index;
const end = arrayEndFrom(start);
if (end === -1) {
continue;
@@ -372,6 +374,11 @@ jobs:
actions: read
contents: read
steps:
- name: Checkout
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Require trusted workflow ref for publish
env:
RELEASE_TAG: ${{ inputs.tag }}
@@ -429,12 +436,13 @@ jobs:
echo "Direct OpenClaw npm publish; relying on this workflow's npm-release environment approval."
exit 0
fi
direct_recovery=false
if [[ "${GITHUB_ACTOR}" != "github-actions[bot]" ]]; then
echo "OpenClaw npm publish must be dispatched by the OpenClaw Release Publish workflow, not directly by ${GITHUB_ACTOR}." >&2
exit 1
direct_recovery=true
echo "Direct OpenClaw npm recovery with release_publish_run_id; relying on this workflow's npm-release environment approval."
fi
RUN_JSON="$(gh run view "$RELEASE_PUBLISH_RUN_ID" --repo "$GITHUB_REPOSITORY" --json workflowName,headBranch,event,status,conclusion,url)"
printf '%s' "$RUN_JSON" | node -e 'const fs = require("node:fs"); const run = JSON.parse(fs.readFileSync(0, "utf8")); const checks = [["workflowName", "OpenClaw Release Publish"], ["headBranch", process.env.EXPECTED_WORKFLOW_BRANCH], ["event", "workflow_dispatch"]]; for (const [key, expected] of checks) { if (run[key] !== expected) { console.error(`Referenced release publish run ${process.env.RELEASE_PUBLISH_RUN_ID} must have ${key}=${expected}, got ${run[key] ?? "<missing>"}.`); process.exit(1); } } if (run.status !== "in_progress") { console.error(`Referenced release publish run ${process.env.RELEASE_PUBLISH_RUN_ID} must still be in_progress, got ${run.status ?? "<missing>"}.`); process.exit(1); } if (run.conclusion) { console.error(`Referenced release publish run ${process.env.RELEASE_PUBLISH_RUN_ID} already concluded ${run.conclusion}.`); process.exit(1); } console.log(`Using release publish approval run ${process.env.RELEASE_PUBLISH_RUN_ID}: ${run.url}`);'
printf '%s' "$RUN_JSON" | DIRECT_RELEASE_RECOVERY="${direct_recovery}" node scripts/validate-release-publish-approval.mjs
publish_openclaw_npm:
# KEEP THE REAL RELEASE/PUBLISH PATH ON A GITHUB-HOSTED RUNNER.

View File

@@ -798,7 +798,7 @@ jobs:
- name: Build private QA runtime
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build
run: node scripts/build-all.mjs qaRuntime
- name: Run parity lane
env:
@@ -876,7 +876,7 @@ jobs:
- name: Build private QA runtime
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build
run: node scripts/build-all.mjs qaRuntime
- name: Generate parity report
run: |
@@ -903,7 +903,7 @@ jobs:
if: contains(fromJSON('["all","qa","qa-parity"]'), needs.resolve_target.outputs.rerun_group)
continue-on-error: true
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 30
timeout-minutes: 45
permissions:
contents: read
env:
@@ -934,7 +934,7 @@ jobs:
- name: Build private QA runtime
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build
run: node scripts/build-all.mjs qaRuntime
- name: Run runtime parity lane
id: runtime_parity_lane
@@ -1075,7 +1075,7 @@ jobs:
needs: [resolve_target]
if: contains(fromJSON('["all","qa","qa-live"]'), needs.resolve_target.outputs.rerun_group) && needs.resolve_target.outputs.qa_live_matrix_enabled == 'true'
continue-on-error: true
runs-on: ubuntu-24.04
runs-on: blacksmith-16vcpu-ubuntu-2404
timeout-minutes: 60
permissions:
contents: read
@@ -1101,7 +1101,7 @@ jobs:
- name: Build private QA runtime
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build
run: node scripts/build-all.mjs qaRuntime
- name: Run Matrix live lane
id: run_lane
@@ -1199,7 +1199,7 @@ jobs:
- name: Build private QA runtime
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build
run: node scripts/build-all.mjs qaRuntime
- name: Run Telegram live lane
id: run_lane
@@ -1295,7 +1295,7 @@ jobs:
- name: Build private QA runtime
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build
run: node scripts/build-all.mjs qaRuntime
- name: Run Discord live lane
id: run_lane
@@ -1393,7 +1393,7 @@ jobs:
- name: Build private QA runtime
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build
run: node scripts/build-all.mjs qaRuntime
- name: Run WhatsApp live lane
id: run_lane
@@ -1488,7 +1488,7 @@ jobs:
- name: Build private QA runtime
env:
NODE_OPTIONS: --max-old-space-size=8192
run: pnpm build
run: node scripts/build-all.mjs qaRuntime
- name: Run Slack live lane
id: run_lane

View File

@@ -46,11 +46,12 @@ on:
default: true
type: boolean
release_profile:
description: Release coverage profile used for release evidence summaries
description: Release coverage profile used for release evidence summaries; default reads it from the validation manifest
required: false
default: beta
default: from-validation
type: choice
options:
- from-validation
- beta
- stable
- full
@@ -135,9 +136,9 @@ jobs:
exit 1
fi
case "$RELEASE_PROFILE" in
beta|stable|full) ;;
from-validation|beta|stable|full) ;;
*)
echo "release_profile must be one of: beta, stable, full" >&2
echo "release_profile must be one of: from-validation, beta, stable, full" >&2
exit 1
;;
esac
@@ -259,6 +260,7 @@ jobs:
echo "sha=$release_sha" >> "$GITHUB_OUTPUT"
- name: Validate full release validation manifest
id: full_manifest
if: ${{ inputs.publish_openclaw_npm }}
env:
GH_TOKEN: ${{ github.token }}
@@ -289,7 +291,7 @@ jobs:
echo "Full release validation target SHA mismatch: expected $EXPECTED_SHA, got $target_sha" >&2
exit 1
fi
if [[ "$release_profile" != "$EXPECTED_RELEASE_PROFILE" ]]; then
if [[ "$EXPECTED_RELEASE_PROFILE" != "from-validation" && "$release_profile" != "$EXPECTED_RELEASE_PROFILE" ]]; then
echo "Full release validation profile mismatch: expected $EXPECTED_RELEASE_PROFILE, got $release_profile" >&2
exit 1
fi
@@ -297,6 +299,7 @@ jobs:
echo "Full release validation must run rerun_group=all before npm publish; got $rerun_group" >&2
exit 1
fi
echo "release_profile=$release_profile" >> "$GITHUB_OUTPUT"
- name: Validate release tag is reachable from a trusted release branch
env:
@@ -332,7 +335,7 @@ jobs:
env:
RELEASE_TAG: ${{ inputs.tag }}
TARGET_SHA: ${{ steps.manifest.outputs.sha || steps.ref.outputs.sha }}
RELEASE_PROFILE: ${{ inputs.release_profile }}
RELEASE_PROFILE: ${{ steps.full_manifest.outputs.release_profile || inputs.release_profile }}
FULL_RELEASE_VALIDATION_RUN_ID: ${{ inputs.full_release_validation_run_id }}
run: |
{
@@ -501,7 +504,7 @@ jobs:
wait_for_run() {
local workflow="$1"
local run_id="$2"
local status conclusion url updated_at created_at duration_seconds duration_label last_state
local status conclusion url updated_at created_at duration_seconds duration_label last_state failed_json
last_state=""
while true; do
@@ -510,6 +513,14 @@ jobs:
if [[ "$status" == "completed" ]]; then
break
fi
failed_json="$(gh run view --repo "$GITHUB_REPOSITORY" "$run_id" --json jobs \
--jq '[.jobs[] | select(.status == "completed" and .conclusion != "success" and .conclusion != "skipped")]' || true)"
if [[ -n "${failed_json}" ]] && jq -e 'length > 0' <<< "$failed_json" >/dev/null; then
echo "${workflow} has failed jobs before the workflow completed: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${run_id}" >&2
jq '.[] | {name, conclusion, url}' <<< "$failed_json" >&2 || true
print_failed_run_summary "${run_id}"
return 1
fi
url="$(printf '%s' "$run_json" | jq -r '.url')"
updated_at="$(printf '%s' "$run_json" | jq -r '.updatedAt')"
state="${status}:${updated_at}"

View File

@@ -53,7 +53,7 @@ jobs:
scripts/run-opengrep.sh --sarif --error
- name: Upload SARIF to GitHub Code Scanning
uses: github/codeql-action/upload-sarif@v4
uses: github/codeql-action/upload-sarif@v4.36.1
# Only upload if the scan actually produced a SARIF file.
if: always() && hashFiles('.opengrep-out/precise.sarif') != ''
with:

View File

@@ -44,7 +44,7 @@ jobs:
uses: actions/checkout@v6
with:
ref: ${{ github.sha }}
fetch-depth: 1
fetch-depth: 2
fetch-tags: false
persist-credentials: false
submodules: false
@@ -74,6 +74,7 @@ jobs:
- name: Run opengrep on PR diff
env:
OPENCLAW_OPENGREP_BASE_REF: ${{ github.event.pull_request.base.sha }}...HEAD
OPENCLAW_OPENGREP_MERGE_HEAD_FIRST_PARENT: "1"
# Findings from precise rules block this workflow. Pull requests scan
# changed first-party source paths only so findings stay attributable to
# the PR diff. Test/fixture/QA path exclusions live in `.semgrepignore`
@@ -83,7 +84,7 @@ jobs:
scripts/run-opengrep.sh --changed --sarif --error
- name: Upload SARIF to GitHub Code Scanning
uses: github/codeql-action/upload-sarif@v4
uses: github/codeql-action/upload-sarif@v4.36.1
# Only upload if the scan actually produced a SARIF file.
if: always() && hashFiles('.opengrep-out/precise.sarif') != ''
with:

View File

@@ -207,6 +207,11 @@ jobs:
actions: read
contents: read
steps:
- name: Checkout
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Validate release publish approval run
env:
GH_TOKEN: ${{ github.token }}
@@ -222,12 +227,13 @@ jobs:
echo "Direct Plugin ClawHub Release dispatch; relying on this workflow's clawhub-plugin-release environment approval."
exit 0
fi
direct_recovery=false
if [[ "${GITHUB_ACTOR}" != "github-actions[bot]" ]]; then
echo "Plugin ClawHub publish must be dispatched by the OpenClaw Release Publish workflow, not directly by ${GITHUB_ACTOR}." >&2
exit 1
direct_recovery=true
echo "Direct Plugin ClawHub Release recovery with release_publish_run_id; relying on this workflow's clawhub-plugin-release environment approval."
fi
RUN_JSON="$(gh run view "$RELEASE_PUBLISH_RUN_ID" --repo "$GITHUB_REPOSITORY" --json workflowName,headBranch,event,status,conclusion,url)"
printf '%s' "$RUN_JSON" | node -e 'const fs = require("node:fs"); const run = JSON.parse(fs.readFileSync(0, "utf8")); const checks = [["workflowName", "OpenClaw Release Publish"], ["headBranch", process.env.EXPECTED_WORKFLOW_BRANCH], ["event", "workflow_dispatch"]]; for (const [key, expected] of checks) { if (run[key] !== expected) { console.error(`Referenced release publish run ${process.env.RELEASE_PUBLISH_RUN_ID} must have ${key}=${expected}, got ${run[key] ?? "<missing>"}.`); process.exit(1); } } if (run.status !== "in_progress") { console.error(`Referenced release publish run ${process.env.RELEASE_PUBLISH_RUN_ID} must still be in_progress, got ${run.status ?? "<missing>"}.`); process.exit(1); } if (run.conclusion) { console.error(`Referenced release publish run ${process.env.RELEASE_PUBLISH_RUN_ID} already concluded ${run.conclusion}.`); process.exit(1); } console.log(`Using release publish approval run ${process.env.RELEASE_PUBLISH_RUN_ID}: ${run.url}`);'
printf '%s' "$RUN_JSON" | DIRECT_RELEASE_RECOVERY="${direct_recovery}" node scripts/validate-release-publish-approval.mjs
preview_plugin_pack:
needs: preview_plugins_clawhub

View File

@@ -184,6 +184,11 @@ jobs:
actions: read
contents: read
steps:
- name: Checkout
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Validate release publish approval run
env:
GH_TOKEN: ${{ github.token }}
@@ -199,12 +204,13 @@ jobs:
echo "Direct Plugin NPM Release dispatch; relying on this workflow's npm-release environment approval."
exit 0
fi
direct_recovery=false
if [[ "${GITHUB_ACTOR}" != "github-actions[bot]" ]]; then
echo "Plugin npm publish must be dispatched by the OpenClaw Release Publish workflow, not directly by ${GITHUB_ACTOR}." >&2
exit 1
direct_recovery=true
echo "Direct Plugin NPM Release recovery with release_publish_run_id; relying on this workflow's npm-release environment approval."
fi
RUN_JSON="$(gh run view "$RELEASE_PUBLISH_RUN_ID" --repo "$GITHUB_REPOSITORY" --json workflowName,headBranch,event,status,conclusion,url)"
printf '%s' "$RUN_JSON" | node -e 'const fs = require("node:fs"); const run = JSON.parse(fs.readFileSync(0, "utf8")); const checks = [["workflowName", "OpenClaw Release Publish"], ["headBranch", process.env.EXPECTED_WORKFLOW_BRANCH], ["event", "workflow_dispatch"]]; for (const [key, expected] of checks) { if (run[key] !== expected) { console.error(`Referenced release publish run ${process.env.RELEASE_PUBLISH_RUN_ID} must have ${key}=${expected}, got ${run[key] ?? "<missing>"}.`); process.exit(1); } } if (run.status !== "in_progress") { console.error(`Referenced release publish run ${process.env.RELEASE_PUBLISH_RUN_ID} must still be in_progress, got ${run.status ?? "<missing>"}.`); process.exit(1); } if (run.conclusion) { console.error(`Referenced release publish run ${process.env.RELEASE_PUBLISH_RUN_ID} already concluded ${run.conclusion}.`); process.exit(1); } console.log(`Using release publish approval run ${process.env.RELEASE_PUBLISH_RUN_ID}: ${run.url}`);'
printf '%s' "$RUN_JSON" | DIRECT_RELEASE_RECOVERY="${direct_recovery}" node scripts/validate-release-publish-approval.mjs
preview_plugin_pack:
needs: preview_plugins_npm

View File

@@ -818,6 +818,7 @@ jobs:
OPENCLAW_QA_CONVEX_SECRET_CI: ${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }}
OPENCLAW_QA_REDACT_PUBLIC_METADATA: "1"
OPENCLAW_QA_SLACK_CAPTURE_CONTENT: "1"
OPENCLAW_QA_TRANSPORT_READY_TIMEOUT_MS: "180000"
INPUT_SCENARIO: ${{ github.event_name == 'workflow_dispatch' && inputs.slack_scenario || '' }}
run: |
set -euo pipefail

View File

@@ -35,7 +35,7 @@ jobs:
submodules: false
- name: Set up Docker Builder
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4
- name: Build minimal sandbox base (USER sandbox)
shell: bash

View File

@@ -129,7 +129,7 @@ jobs:
- name: Run Codex test performance agent
if: steps.gate.outputs.run_agent == 'true'
uses: openai/codex-action@5c3f4ccdb2b8790f73d6b21751ac00e602aa0c02
uses: openai/codex-action@e0fdf01220eb9a88167c4898839d273e3f2609d1
with:
openai-api-key: ${{ secrets.OPENCLAW_TEST_PERF_AGENT_OPENAI_API_KEY || secrets.OPENAI_API_KEY }}
prompt-file: .github/codex/prompts/test-performance-agent.md

View File

@@ -27,7 +27,9 @@ env:
jobs:
tui-pty:
runs-on: ubuntu-24.04
timeout-minutes: 5
timeout-minutes: 8
env:
OPENCLAW_TUI_PTY_INCLUDE_LOCAL: "1"
steps:
- name: Checkout
uses: actions/checkout@v6
@@ -38,4 +40,4 @@ jobs:
install-bun: "false"
- name: Run TUI PTY tests
run: timeout --kill-after=30s 120s node scripts/run-vitest.mjs run --config test/vitest/vitest.tui-pty.config.ts
run: timeout --kill-after=30s 240s node scripts/run-vitest.mjs run --config test/vitest/vitest.tui-pty.config.ts

View File

@@ -43,4 +43,4 @@ jobs:
published_upgrade_survivor_baselines: ${{ inputs.baselines }}
published_upgrade_survivor_scenarios: ${{ inputs.scenarios }}
telegram_mode: none
secrets: inherit
secrets: inherit # zizmor: ignore[secrets-inherit] Maintainer-dispatched package acceptance lane intentionally forwards its declared live-test secret matrix.

View File

@@ -197,4 +197,4 @@ jobs:
- name: Testbox action marker
if: ${{ false }}
uses: useblacksmith/run-testbox@5ca05834db1d3813554d1dd109e5f2087a8d7cbc
uses: useblacksmith/run-testbox@3f60ff9ceb2c10c3feefa87dc0c6490cffae059d

View File

@@ -0,0 +1,126 @@
name: Windows Node Release
on:
workflow_dispatch:
inputs:
tag:
description: Existing OpenClaw release tag to receive Windows Hub installers, for example v2026.6.1
required: true
type: string
windows_node_tag:
description: openclaw-windows-node release tag to promote, or latest
required: true
default: latest
type: string
permissions:
contents: write
concurrency:
group: windows-node-release-${{ inputs.tag }}
cancel-in-progress: false
jobs:
promote_signed_windows_installers:
name: Promote signed Windows installers
runs-on: windows-latest
timeout-minutes: 30
steps:
- name: Validate inputs
shell: pwsh
env:
RELEASE_TAG: ${{ inputs.tag }}
WINDOWS_NODE_TAG: ${{ inputs.windows_node_tag }}
GH_TOKEN: ${{ github.token }}
run: |
if ($env:RELEASE_TAG -notmatch '^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*((-(alpha|beta)\.[1-9][0-9]*)|(-[1-9][0-9]*))?$') {
throw "Invalid OpenClaw release tag: $env:RELEASE_TAG"
}
if ($env:WINDOWS_NODE_TAG -ne "latest" -and $env:WINDOWS_NODE_TAG -notmatch '^v[0-9]+\.[0-9]+\.[0-9]+([-.][0-9A-Za-z.-]+)?$') {
throw "Invalid openclaw-windows-node release tag: $env:WINDOWS_NODE_TAG"
}
gh release view $env:RELEASE_TAG --repo $env:GITHUB_REPOSITORY | Out-Null
- name: Download Windows Hub release installers
shell: pwsh
env:
WINDOWS_NODE_TAG: ${{ inputs.windows_node_tag }}
GH_TOKEN: ${{ github.token }}
run: |
New-Item -ItemType Directory -Force -Path dist | Out-Null
$tagArgs = @()
if ($env:WINDOWS_NODE_TAG -ne "latest") {
$tagArgs += $env:WINDOWS_NODE_TAG
}
gh release download @tagArgs `
--repo openclaw/openclaw-windows-node `
--pattern "OpenClawCompanion-Setup-*.exe" `
--dir dist
$expected = @(
"dist/OpenClawCompanion-Setup-x64.exe",
"dist/OpenClawCompanion-Setup-arm64.exe"
)
foreach ($file in $expected) {
if (-not (Test-Path -LiteralPath $file)) {
throw "Missing expected Windows installer: $file"
}
}
- name: Verify Authenticode signatures
shell: pwsh
run: |
Get-ChildItem -LiteralPath dist -Filter "OpenClawCompanion-Setup-*.exe" | ForEach-Object {
$signature = Get-AuthenticodeSignature -LiteralPath $_.FullName
if ($signature.Status -ne "Valid") {
throw "$($_.Name) Authenticode signature was $($signature.Status)."
}
if (-not $signature.SignerCertificate) {
throw "$($_.Name) has no signer certificate."
}
[pscustomobject]@{
File = $_.Name
Signer = $signature.SignerCertificate.Subject
Thumbprint = $signature.SignerCertificate.Thumbprint
} | Format-List
}
- name: Write SHA-256 manifest
shell: pwsh
run: |
Get-ChildItem -LiteralPath dist -Filter "OpenClawCompanion-Setup-*.exe" |
Sort-Object Name |
ForEach-Object {
$hash = Get-FileHash -Algorithm SHA256 -LiteralPath $_.FullName
"$($hash.Hash.ToLowerInvariant()) $($_.Name)"
} | Set-Content -Encoding utf8NoBOM -Path dist/OpenClawCompanion-SHA256SUMS.txt
- name: Upload to OpenClaw release
shell: pwsh
env:
RELEASE_TAG: ${{ inputs.tag }}
GH_TOKEN: ${{ github.token }}
run: |
gh release upload $env:RELEASE_TAG `
dist/OpenClawCompanion-Setup-x64.exe `
dist/OpenClawCompanion-Setup-arm64.exe `
dist/OpenClawCompanion-SHA256SUMS.txt `
--repo $env:GITHUB_REPOSITORY `
--clobber
- name: Summary
shell: pwsh
env:
RELEASE_TAG: ${{ inputs.tag }}
WINDOWS_NODE_TAG: ${{ inputs.windows_node_tag }}
run: |
@"
## Windows Hub installers promoted
OpenClaw release: $env:RELEASE_TAG
Source release: openclaw/openclaw-windows-node@$env:WINDOWS_NODE_TAG
- https://github.com/openclaw/openclaw/releases/download/$env:RELEASE_TAG/OpenClawCompanion-Setup-x64.exe
- https://github.com/openclaw/openclaw/releases/download/$env:RELEASE_TAG/OpenClawCompanion-Setup-arm64.exe
- https://github.com/openclaw/openclaw/releases/download/$env:RELEASE_TAG/OpenClawCompanion-SHA256SUMS.txt
"@ >> $env:GITHUB_STEP_SUMMARY

View File

@@ -61,12 +61,14 @@ jobs:
submodules: false
- name: Probe native Windows
env:
TARGET_REF: ${{ inputs.target_ref || github.ref }}
run: |
$ErrorActionPreference = "Stop"
Write-Host "runner=$env:RUNNER_NAME"
Write-Host "machine=$env:COMPUTERNAME"
Write-Host "workspace=$env:GITHUB_WORKSPACE"
Write-Host "target_ref=${{ inputs.target_ref || github.ref }}"
Write-Host "target_ref=$env:TARGET_REF"
Write-Host ("os=" + [System.Environment]::OSVersion.VersionString)
Write-Host ("arch=" + [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)
Write-Host ("powershell=" + $PSVersionTable.PSVersion.ToString())

View File

@@ -84,6 +84,65 @@ jobs:
"+${CHECKOUT_SHA}:refs/remotes/origin/checkout"
git -C "$GITHUB_WORKSPACE" checkout --detach refs/remotes/origin/checkout
- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Prepare trusted workflow audit configs
if: github.event_name == 'pull_request'
env:
BASE_REF: ${{ github.event.pull_request.base.ref }}
BASE_SHA: ${{ github.event.pull_request.base.sha }}
run: |
set -euo pipefail
trusted_config="$RUNNER_TEMP/pre-commit-base.yaml"
trusted_zizmor_config="$RUNNER_TEMP/zizmor-base.yml"
if ! git cat-file -e "${BASE_SHA}^{commit}" 2>/dev/null; then
timeout --signal=TERM --kill-after=10s 30s git fetch --no-tags --depth=1 origin \
"+${BASE_SHA}:refs/remotes/origin/security-base" ||
timeout --signal=TERM --kill-after=10s 30s git fetch --no-tags --depth=1 origin \
"+refs/heads/${BASE_REF}:refs/remotes/origin/${BASE_REF}"
fi
if git cat-file -e "${BASE_SHA}:.pre-commit-config.yaml" 2>/dev/null; then
git show "${BASE_SHA}:.pre-commit-config.yaml" > "$trusted_config"
elif git show "refs/remotes/origin/${BASE_REF}:.pre-commit-config.yaml" \
> "$trusted_config" 2>/dev/null; then
echo "Base SHA ${BASE_SHA} does not expose .pre-commit-config.yaml; using origin/${BASE_REF} instead."
else
echo "::error title=trusted pre-commit config unavailable::Could not read .pre-commit-config.yaml from ${BASE_SHA} or origin/${BASE_REF}."
exit 1
fi
if git cat-file -e "${BASE_SHA}:.github/zizmor.yml" 2>/dev/null; then
git show "${BASE_SHA}:.github/zizmor.yml" > "$trusted_zizmor_config"
elif git show "refs/remotes/origin/${BASE_REF}:.github/zizmor.yml" \
> "$trusted_zizmor_config" 2>/dev/null; then
echo "Base SHA ${BASE_SHA} does not expose .github/zizmor.yml; using origin/${BASE_REF} instead."
else
echo "::error title=trusted zizmor config unavailable::Could not read .github/zizmor.yml from ${BASE_SHA} or origin/${BASE_REF}."
exit 1
fi
python3 - "$trusted_config" "$trusted_zizmor_config" <<'PY'
from pathlib import Path
import sys
config_path = Path(sys.argv[1])
zizmor_config_path = sys.argv[2]
text = config_path.read_text()
if ".github/zizmor.yml" not in text:
raise SystemExit("trusted pre-commit config does not reference .github/zizmor.yml")
config_path.write_text(text.replace(".github/zizmor.yml", zizmor_config_path))
PY
echo "PRE_COMMIT_CONFIG_PATH=$trusted_config" >> "$GITHUB_ENV"
- name: Install pre-commit
run: python -m pip install --disable-pip-version-check pre-commit==4.2.0
- name: Install actionlint
shell: bash
run: |
@@ -103,6 +162,15 @@ jobs:
- name: Lint workflows
run: actionlint
- name: Audit all workflows with zizmor
shell: bash
run: |
set -euo pipefail
mapfile -t workflow_files < <(
find .github/workflows -maxdepth 1 -type f \( -name '*.yml' -o -name '*.yaml' \) | sort
)
pre-commit run --config "${PRE_COMMIT_CONFIG_PATH:-.pre-commit-config.yaml}" zizmor --files "${workflow_files[@]}"
- name: Disallow direct inputs interpolation in composite run blocks
run: python3 scripts/check-composite-action-input-interpolation.py

1
.gitignore vendored
View File

@@ -42,6 +42,7 @@ apps/macos-mlx-tts/.build/
apps/shared/MoltbotKit/.build/
apps/shared/OpenClawKit/.build/
apps/shared/*/.build/
packages/*/dist/
apps/shared/OpenClawKit/Package.resolved
**/ModuleCache/
bin/

View File

@@ -20,34 +20,46 @@
"eslint/no-multi-str": "error",
"eslint/no-new": "error",
"eslint/no-object-constructor": "error",
"eslint/no-param-reassign": "error",
"eslint/no-proto": "error",
"eslint/no-promise-executor-return": "error",
"eslint/no-regex-spaces": "error",
"eslint/no-return-assign": "error",
"eslint/no-sequences": "error",
"eslint/no-self-compare": "error",
"eslint/no-shadow": "off",
"eslint/no-shadow": "error",
"eslint/no-implicit-coercion": "error",
"eslint/no-var": "error",
"eslint/no-useless-call": "error",
"eslint/no-useless-computed-key": "error",
"eslint/no-useless-concat": "error",
"eslint/no-useless-constructor": "error",
"eslint/no-unused-vars": "off",
"eslint/no-useless-rename": "error",
"eslint/no-useless-return": "error",
"eslint/no-useless-assignment": "error",
"eslint/no-unused-vars": "error",
"eslint/no-warning-comments": "error",
"eslint/no-unmodified-loop-condition": "error",
"eslint/no-new-wrappers": "error",
"eslint/no-else-return": "error",
"eslint/no-lonely-if": "error",
"eslint/no-case-declarations": "error",
"eslint/default-case-last": "error",
"eslint/default-param-last": "error",
"eslint/prefer-exponentiation-operator": "error",
"eslint/prefer-const": "error",
"eslint/prefer-numeric-literals": "error",
"eslint/prefer-object-has-own": "error",
"eslint/object-shorthand": "error",
"eslint/prefer-rest-params": "error",
"eslint/prefer-spread": "error",
"eslint/radix": "error",
"eslint/unicode-bom": "error",
"eslint/yoda": "error",
"import/no-absolute-path": "error",
"import/first": "error",
"import/no-empty-named-blocks": "error",
"import/no-duplicates": "error",
"import/no-self-import": "error",
"node/no-exports-assign": "error",
"eslint-plugin-unicorn/prefer-set-size": "error",
@@ -66,8 +78,14 @@
"typescript/no-empty-object-type": ["error", { "allowInterfaces": "with-single-extends" }],
"typescript/no-explicit-any": "error",
"typescript/no-extraneous-class": "error",
"typescript/no-import-type-side-effects": "error",
"typescript/no-meaningless-void-operator": "error",
"typescript/no-misused-promises": "error",
"typescript/no-inferrable-types": "error",
"typescript/only-throw-error": "error",
"typescript/no-non-null-asserted-nullish-coalescing": "error",
"typescript/prefer-promise-reject-errors": "error",
"typescript/restrict-plus-operands": "error",
"typescript/no-unnecessary-qualifier": "error",
"typescript/no-unnecessary-type-assertion": "error",
"typescript/no-unnecessary-type-arguments": "error",
@@ -86,6 +104,7 @@
"typescript/prefer-namespace-keyword": "error",
"typescript/prefer-return-this-type": "error",
"typescript/prefer-find": "error",
"typescript/prefer-for-of": "error",
"typescript/prefer-function-type": "error",
"typescript/prefer-includes": "error",
"typescript/prefer-reduce-type-parameter": "error",
@@ -93,6 +112,8 @@
"typescript/require-array-sort-compare": "error",
"typescript/restrict-template-expressions": "error",
"typescript/triple-slash-reference": "error",
"typescript/unbound-method": "error",
"typescript/use-unknown-in-catch-callback-variable": "error",
"unicorn/consistent-date-clone": "error",
"unicorn/consistent-empty-array-spread": "error",
"unicorn/consistent-function-scoping": "off",
@@ -106,14 +127,18 @@
"unicorn/no-new-buffer": "error",
"unicorn/no-thenable": "error",
"unicorn/no-typeof-undefined": "error",
"unicorn/no-unreadable-array-destructuring": "error",
"unicorn/no-unnecessary-array-flat-depth": "error",
"unicorn/no-unnecessary-array-splice-count": "error",
"unicorn/no-unnecessary-slice-end": "error",
"unicorn/no-useless-error-capture-stack-trace": "error",
"unicorn/no-useless-promise-resolve-reject": "error",
"unicorn/no-useless-switch-case": "error",
"unicorn/no-zero-fractions": "error",
"unicorn/prefer-date-now": "error",
"unicorn/prefer-dom-node-text-content": "error",
"unicorn/prefer-keyboard-event-key": "error",
"unicorn/prefer-array-flat": "error",
"unicorn/prefer-array-some": "error",
"unicorn/prefer-math-min-max": "error",
"unicorn/prefer-node-protocol": "error",
@@ -123,6 +148,8 @@
"unicorn/prefer-prototype-methods": "error",
"unicorn/prefer-regexp-test": "error",
"unicorn/prefer-set-size": "error",
"unicorn/prefer-set-has": "error",
"unicorn/prefer-structured-clone": "error",
"unicorn/prefer-string-starts-ends-with": "error",
"unicorn/prefer-string-slice": "error",
"unicorn/require-array-join-separator": "error",
@@ -183,6 +210,7 @@
"docs/_layouts/",
"extensions/diffs/assets/viewer-runtime.js",
"extensions/diffs-language-pack/assets/viewer-runtime.js",
"extensions/canvas/src/host/a2ui/a2ui.bundle.js",
"node_modules/",
"patches/",
"pnpm-lock.yaml",
@@ -199,13 +227,6 @@
"**/node_modules/**"
],
"overrides": [
{
"files": ["src/security/**"],
"rules": {
"eslint/no-warning-comments": "off",
"oxc/no-map-spread": "off"
}
},
{
"files": [
"**/*.test.ts",
@@ -217,9 +238,7 @@
"**/*test-support.ts"
],
"rules": {
"typescript/no-explicit-any": "off",
"typescript/unbound-method": "off",
"eslint/no-unsafe-optional-chaining": "off"
"typescript/no-explicit-any": "off"
}
}
]

View File

@@ -9,7 +9,11 @@ Skills own workflows; root owns hard policy and routing.
- Replies: repo-root refs only: `extensions/telegram/src/index.ts:80`. No absolute paths, no `~/`.
- 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.
- Reviews/answers: high confidence required. Default to exhaustive relevant codebase search/read, including owners, callers, siblings, tests, docs, and upstream/dependency contracts before verdict. Diff-only review is insufficient.
- Review default: read the whole changed function/module plus callers, callees, sibling implementations, adjacent tests, scoped docs, and dependency/Codex contracts before saying `good`, `bad`, `best fix`, `proof sufficient`, or posting a comment. If challenged, keep reading first; do not defend the earlier verdict until the missing path is checked.
- Dependency-touching work: direct dependency inspection is mandatory when feasible; do not rely on assumptions, wrappers, or memory. Most dependencies are OSS, so read their source/docs/types. Codex-related work has a hard gate: the acting agent must personally inspect sibling `../codex` source for the exact protocol/runtime behavior before any verdict, comment, approval, merge recommendation, code change, or `proof sufficient` claim. If missing, clone `https://github.com/openai/codex.git` there first. Subagent reports, PR text, OpenClaw wrappers, generated schemas, memory, and prior bot reviews do not satisfy this gate. No direct `../codex` check means no Codex verdict. Cite Codex files/lines checked in final/review/comment.
- Dependency-backed behavior: read upstream docs/source/types first. No API/default/error/timing guesses.
- External API work: live test required. Google/search for additional proof. Prefer official docs/source/types; cite current proof. No memory-only API claims.
- 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.
@@ -26,6 +30,8 @@ Skills own workflows; root owns hard policy and routing.
- Plugin APIs, provider routing, auth/session state, persisted preferences, config loading, config/default additions, migrations, setup, startup checks, and fallback behavior are compatibility/upgrade-sensitive. Treat config breaks, new config/default surfaces, removed fallbacks, fail-closed changes, stricter validation, or new operator action as merge risk even with green CI when they can affect existing users, upgrades, provider/plugin behavior, or maintainer operations.
- For PRs that add, remove, or change config/default surfaces with possible compatibility, upgrade, provider/plugin, operator, setup, startup, or fallback impact, ClawSweeper review should emit a `reviewMetrics` entry when practical. The metric should name the count and direction of the changes, such as added, changed, or removed config/default surfaces, and explain why the metric matters before merge. When the metric indicates concrete merge risk, also surface the concern in `risks`, use `mergeRiskLabels` when the risk matches the label rubric, make `bestSolution` name the desired pre-merge state, and ensure `labelJustifications` explain the specific reason rather than restating the label.
- Review whole decision surfaces, not only the touched runtime, provider, channel, harness, plugin seam, or context path. Check sibling Codex/Pi-style runtimes, provider/model routing, channel delivery, gateway/protocol, plugin SDK, and context-management paths when relevant.
- Every PR review must explicitly ask whether the PR is the best fix, not merely a plausible fix. Verdicts need a best-fix judgment backed by enough code reading to compare owner boundaries, callers, siblings, tests, docs, current `main`, shipped behavior when relevant, and dependency/Codex contracts when involved.
- Before a PR verdict, build a small evidence map: changed surface, entry point, owner boundary, at least one caller and callee, sibling surfaces that share the invariant, existing tests, and current `main` behavior. If any cell is missing, say the gap instead of concluding.
- One-sided fixes need sibling-surface proof, an explanation for why siblings are unaffected, or explicit follow-up work.
- Changelog findings: see Docs / Changelog.
- Public ClawSweeper comments prefer `https://docs.openclaw.ai/...` when a public docs page exists; structured evidence still cites repo files, lines, SHAs.
@@ -57,12 +63,25 @@ Skills own workflows; root owns hard policy and routing.
- External official plugins own package/deps and are excluded from core dist; core uses registry-aware `facade-runtime` or generic contracts.
- Externalizing a bundled plugin: update package excludes, official catalogs, docs, tests, and prove core runtime paths resolve installed plugin roots before root-dep removal.
- Runtime reads canonical config only. No silent compat for old/malformed config keys. If a config change invalidates existing files, add a matching `openclaw doctor --fix` migration. Core/auth config repairs live in core doctor; plugin-owned config repairs live in that plugin's doctor contract (`legacyConfigRules` / `normalizeCompatibilityConfig`).
- OpenAI Codex is folded into `openai`. No new/live `openai-codex` provider/plugin/auth/model routes; treat them as legacy input only. Runtime/setup/auth/catalog use `openai` + `openai/*`; doctor/migrations repair stale `openai-codex/*` profiles/metadata.
- Config/env surface bar is high; `openclaw.json` and environment variables are already large. Before adding a config option or env var, first prove existing product behavior, provider selection, defaults, or doctor migration cannot solve it. Prefer removing or consolidating config/env options when touching these surfaces. Core supports only the latest config shape; `openclaw doctor --fix` migrates older shipped shapes into the current one.
- CLI setup flows are public API when external docs, installers, or integrations can copy them. Changes to `openclaw onboard`, `openclaw configure`, their documented flags, non-interactive behavior, or generated config shape are compatibility-sensitive API contract changes; prefer additive flags/aliases, deprecation windows, and backward-preserving migrations over breaking existing snippets.
- Fix shape: default to clean bounded refactor, not smallest patch. Move ownership to right boundary; delete stale abstractions, duplicate policy, dead branches, wrappers, fallback stacks.
- Fix observed local failures with generic product rules; do not hardcode names, ids, log phrases, or user examples in prod code unless they are an explicit contract.
- Tests may use observed examples, but prod literals need a short contract reason.
- Compatibility is opt-in. "Shipped" means reachable from a release Git tag; main/GitHub/PR/unreleased code is not shipped.
- Refactor default: one canonical path. Delete the old path unless user explicitly wants compat or the shipped public contract is obvious and cited.
- Core runtime consumes only current canonical shapes/config/data. Legacy or retired shapes normalize only in doctor/migration code before runtime; no runtime shims, aliases, or fallback readers.
- State/storage migrations are database-first. Runtime reads/writes the canonical store only. Old file stores, sidecars, aliases, and fallback readers belong in `openclaw doctor --fix` migration code only, never steady-state runtime.
- Storage default: SQLite only. Do not add JSON/JSONL/TXT/sidecar files for OpenClaw-owned runtime state, caches, queues, registries, indexes, cursors, checkpoints, or plugin scratch data.
- SQLite runtime access uses Kysely helpers, not raw SQL statement strings, except schema DDL, migrations, low-level DB bootstrap, or narrowly justified SQLite primitives.
- Use the shared state DB (`state/openclaw.sqlite`) for global runtime state and plugin KV data. Use the per-agent DB (`agents/<agentId>/agent/openclaw-agent.sqlite`) for agent-scoped state/cache. Use a dedicated SQLite DB only when schema, volume, or lifecycle clearly does not fit those stores.
- Legacy state/cache files are migration debt. When touching code that reads/writes them, prefer moving the data into SQLite or calling out the refactor follow-up; do not add parallel file paths.
- File storage must be a named product artifact: import/export, user attachment, log, backup, or external tool contract. If it is app state or cache, it belongs in SQLite.
- Before adding any path under state dirs, choose one: shared state DB, plugin KV, agent DB, or dedicated SQLite schema. If none fits, design the SQLite owner/schema first.
- Cache/transient state gets no compat migration unless a shipped user contract is cited. Prefer delete/drop/rebuild over import. If old state can be lost without user-visible data loss, remove the old path entirely.
- Persistent user state gets one migration owner. Doctor migrates, verifies, and then runtime assumes the new shape. No dual-write, read-through fallback, lazy import, or "if SQLite fails use JSON" branches.
- Fallback is a product decision, not an implementation convenience. Before adding one, name the shipped contract, failure mode, removal plan, and why doctor cannot solve it. Otherwise delete it.
- Keep old behavior only for an explicit public API/config/plugin SDK/data contract, tagged upgrade path, security/migration boundary, dependency contract, or observed prod state.
- If unsure, ask before preserving compat. Do not keep aliases, shims, fallback stacks, stale names, or obsolete tests just in case.
- Tests alone do not make internals contracts. If compat stays, name the contract and migration/removal plan in code, test, or PR.
@@ -72,13 +91,16 @@ Skills own workflows; root owns hard policy and routing.
- Plugin SDK exception: shipped external API gets new API first plus named compat/deprecation, small tests/docs if useful, removal plan.
- Migrate internal/bundled callers to modern API in the same change. Do not let internal compat become permanent architecture.
- Channels are implementation under `src/channels/**`; plugin authors get SDK seams. Providers own auth/catalog/runtime hooks; core owns generic loop.
- Message/channel plugins stay transport-only. They render portable presentation/actions, enforce transport limits, and map native callback envelopes. They do not own product command trees, plugin/provider policy, or feature-specific menus.
- Portable command UI must use typed presentation actions, not raw string inference. Do not make channels guess that `value` starting with `/` means a native command; core/owner plugins declare command actions, channels map them when supported.
- Raw callback data is transport/private. Approval, command, URL, web-app, and select actions must stay distinguishable before channel encoding so transport adapters do not special-case product strings.
- Agent run terminal state: normalize/merge via `src/agents/agent-run-terminal-outcome.ts`; do not rederive timeout/cancel precedence in projections.
- Hot paths should carry prepared facts forward: provider id, model ref, channel id, target, capability family, attachment class. Do not rediscover with broad plugin/provider/channel/capability loaders.
- Do not fix repeated request-time discovery with scattered caches. Move the canonical fact earlier; reuse prepared runtime objects; delete duplicate lookup branches.
- Gateway/plugin metadata is process-stable: installs, manifests, catalogs, generated paths, bundled metadata. Changes require restart or explicit owner reload/install/doctor flow.
- Runtime hot paths: no freshness polling (`stat`/`realpath`/JSON reread/hash). Reuse current snapshots, install records, discovery, lookup tables, root scopes, resolved paths.
- Process-local metadata caches ok when lifecycle-owned and bounded/single-slot. Freshness exceptions need named owner + tests.
- Inline comments: preserve reviewer context at the code site. Use for cross-path/state invariants, platform/dependency caps, deterministic ordering, compact encoded state, lifecycle ordering, ownership boundaries, session/id adoption, queue-depth symmetry, fallbacks, or intentional caller differences.
- Inline comments: preserve reviewer context at the code site. Required for non-obvious cross-path/state invariants, lifecycle ordering, ownership boundaries, queue/dedupe symmetry, TTL/cache expiry, cleanup/release coupling, session/id adoption, fallback behavior, platform/dependency caps, deterministic ordering, compact encoded state, or intentional caller differences.
- Comment shape: 1-3 short lines; state why the branch/helper exists, what contract it protects, and the bad outcome if removed. Cite nearby constants/helpers when useful. No syntax narration, PR/user-specific lore, or obvious mechanics.
- Gateway protocol changes: additive first; incompatible needs versioning/docs/client follow-through.
- Protocol version bumps: explicit owner confirmation only; never automatic/generated.
@@ -95,8 +117,8 @@ Skills own workflows; root owns hard policy and routing.
- Tests in a normal source checkout: `pnpm test <path-or-filter> [vitest args...]`, `pnpm test:changed`, `pnpm test:serial`, `pnpm test:coverage`; never raw `vitest`.
- If raw Vitest is unavoidable, use `vitest run ...`; bare `vitest ...` starts local watch mode and will not exit on its own.
- Tests in a Codex worktree or linked/sparse checkout: avoid direct local `pnpm test*`; use `node scripts/run-vitest.mjs <path-or-filter>` for tiny explicit-file proof, or Crabbox/Testbox for anything broader.
- Checks in a normal source checkout: `pnpm check:changed`; lanes: `pnpm changed:lanes --json`; staged: `pnpm check:changed --staged`; full: `pnpm check`.
- Checks in a Codex worktree or linked/sparse checkout: avoid direct local `pnpm check*`; use `node scripts/crabbox-wrapper.mjs run ... --shell -- "pnpm check:changed"` so pnpm runs inside Testbox, not locally.
- Checks in a normal source checkout: `pnpm check:changed` delegates to Crabbox/Testbox; lanes: `pnpm changed:lanes --json`; staged: `pnpm check:changed --staged`; full: `pnpm check`.
- Checks in a Codex worktree or linked/sparse checkout: avoid direct local `pnpm check*`; use `node scripts/crabbox-wrapper.mjs run ... -- env OPENCLAW_CHECK_CHANGED_REMOTE_CHILD=1 OPENCLAW_CHANGED_LANES_RAW_SYNC=1 corepack pnpm check:changed` so pnpm runs inside Testbox, not locally.
- Extension tests: `pnpm test:extensions`, `pnpm test extensions`, `pnpm test extensions/<id>`.
- Typecheck: `tsgo` lanes only (`pnpm tsgo*`, `pnpm check:test-types`); never add `tsc --noEmit`, `typecheck`, `check:types`.
- Formatting: `oxfmt`, not Prettier. Use repo wrappers (`pnpm format:*`, `pnpm lint:*`, `scripts/run-oxlint.mjs`).
@@ -106,12 +128,13 @@ Skills own workflows; root owns hard policy and routing.
- Use `$openclaw-testing` for test/CI choice and `$crabbox` for remote/full/E2E proof.
- Crabbox request means real scenario proof: install/update/call/repro user path; not just copy tests and run them remotely.
- Visual proof: use Crabbox, set up like a user, then screenshot-verify. No harness/bypass/shortcut unless explicitly asked.
- Small/narrow tests, lints, format checks, and type probes are fine locally only in a healthy normal checkout.
- In Codex worktrees, direct local `pnpm test*`, `pnpm check*`, `pnpm crabbox:run`, and `scripts/committer` can trigger pnpm dependency reconciliation or install prompts. Prefer `node` wrappers locally and Crabbox/Testbox for pnpm-gated proof.
- Full suites, broad changed gates, Docker/package/E2E/live/cross-OS proof, or anything that bogs down the Mac: Crabbox/Testbox.
- One/few files local. If a local command fans out, stop and move broad proof to Crabbox/Testbox.
- Before handoff/push: prove touched surface. Before landing to `main`: issue proof plus appropriate full/broad proof unless scope is clearly narrow.
- Pre-land/pre-commit code changes: use `$autoreview` until no accepted/actionable findings remain, unless equivalent manual review already done, trivial/docs-only, or user opts out.
- Pre-land/pre-commit code changes: mandatory fresh `$autoreview` until no accepted/actionable findings remain. Do not land code on CI, ClawSweeper, prior review comments, or your own manual review alone unless user explicitly opts out or scope is truly trivial/docs-only. If findings want refactor, refactor; no ugly fixes.
- If proof is blocked, say exactly what is missing and why.
- Do not land related failing format/lint/type/build/tests. If unrelated on latest `origin/main`, say so with scoped proof.
- Docs/changelog-only and CI/workflow metadata-only: `git diff --check` plus relevant docs/workflow sanity; escalate only if scripts/config/generated/package/runtime behavior changed.
@@ -120,27 +143,35 @@ Skills own workflows; root owns hard policy and routing.
## GitHub / PRs
- 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.
- Pasted GitHub issue/PR: first `git status -sb`; if dirty, yell; then `git push` + `git pull --ff-only`.
- Issue/PR start: `git status -sb`; if clean, `git pull --ff-only`; if dirty, yell before pull/rebase.
- 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.
- Bare issue/PR URL/number: inspect live and take the efficient maintainer path; switch branches/refs when useful.
- No unsolicited PR labels/retitles/rebases/fixups/landing. Comments/reviews ok only for reviewable findings, pre-merge proof, or close/duplicate reason 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.
- Issue/PR work: search strong related issues/PRs before final; close proven dupes/fixed siblings. If none close, suggest one next related follow-up.
- PR superseded by `main`: if code proof shows `main` already has same-or-better behavior, comment canonical commit/PR + focused proof, then close. Bar high: inspect PR diff, current code/tests, linked issue, caller/sibling path. If unsure, leave open.
- Issue/PR numbers need a short summary every time; assume the reader has not opened or read them.
- Before presenting a batch of issues/PRs, use smart subagents to verify live state and current `main`; omit closed/fixed items, and comment+close items already fixed on `main` when maintainer action is authorized.
- PR review answer: bug/behavior, URL(s), affected surface, provenance for regressions when traceable, best-fix judgment, evidence from code/tests/CI/current or shipped behavior.
- PR reviewable findings: post them on the PR, not chat-only, so author sees actionable feedback.
- Issue/PR final answer: last line is the full GitHub URL.
- PR verification: before merge, post exact local commands, CI/Testbox run IDs, before/after proof when used, and known proof gaps.
- PR verification: before merge, post land-ready work done, exact local commands, CI/Testbox run IDs, before/after proof when used, and known proof gaps.
- Issue fixed on `main` with proof: comment proof + commit/PR, then close.
- After landing or requested close/sweep: search duplicates; comment proof + canonical commit/PR/release before closing.
- After landing/ship final: include 2-5 sentence recap of what landed: behavior change, key files/surface, proof run, issue/PR state. Do not answer with only status/links.
- `ship` that fixes an issue: after push, comment proof + commit link, then close the issue.
- Public GH comments: show draft in chat first unless user explicitly asked to post/comment/reply/close/merge/land. After work starts and changes/proof exist, post the review/proof/commit comment.
- Representing user: if user already has a comment/thread for the point, update/reply there when possible; avoid duplicate PR/issue comments.
- No surprise GH writes: chat must mention every posted/updated public comment with URL.
- 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.
- PR create/refresh: keep PR branches takeover-ready. Use a branch maintainers can push to, or for fork PRs ensure `maintainer_can_modify` / GitHub's `Allow edits by maintainers` is enabled unless explicitly told otherwise or GitHub's Actions/secrets warning makes that unsafe.
- GitHub issue/PR create: read `$agent-transcript`; ask about sanitized transcript logs when available.
- 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`.
- Contributor PRs: parsed `Real behavior proof` uses 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. Never push screenshots, videos, proof images, or proof assets to OpenClaw or any product repo branch, including temp artifact branches. Use Crabbox artifact publishing plus the manifest URL. 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: may skip/ignore `Real behavior proof` when local tests or Crabbox verified behavior; record proof in PR verification.
- OpenClaw write-access maintainers may skip `Real behavior proof` when local tests or Crabbox verified behavior; record proof in PR verification.
- `/landpr`: use `~/.codex/prompts/landpr.md`; do not idle on `auto-response` or `check-docs`.
## Code
@@ -156,12 +187,17 @@ Skills own workflows; root owns hard policy and routing.
- Use named intermediates only for domain meaning or readability; avoid temp-variable soup.
- Code size matters. Prefer small clear code; maintainability includes not growing LOC without payoff.
- Refactors should delete about as much local complexity as they add. If LOC grows, the new ownership/API needs to clearly pay for it.
- Refactors should reduce non-test LOC unless they remove a larger architectural cost. Treat positive prod LOC as a smell. Before closeout, run `git diff --numstat`; if non-test LOC grew, trim or explicitly justify why fewer paths now exist.
- Prefer deleting branches, modes, adapters, and tests over preserving them. A refactor that adds a second path has probably failed unless the old path is a cited shipped contract.
- New helpers/files must pay rent immediately: fewer call paths, fewer concepts, or less repeated logic. No helpers for one-off compat, naming translation, or speculative resilience.
- Before adding helpers/files, check whether existing code can absorb the behavior with less new surface.
- Keep APIs narrow: export only current caller needs; keep types/helpers local by default.
- Return the smallest useful shape. Avoid broad result objects, flags, metadata unless callers use them.
- Avoid adapter layers that only rename fields. Move real responsibility or leave code local.
- Inline simple one-use objects/spreads when clearer. Extract only when it removes duplication or hard logic.
- Tests prove behavior/regressions, not every internal branch.
- Tests are welcome, but review them before landing for duplication and value. Delete useless tests, such as assertions for behavior or paths just removed.
- Tests protect canonical behavior and migration boundaries, not obsolete internals. Delete tests for removed fallback paths instead of updating them.
- For non-trivial refactors, check `git diff --numstat` before closeout. If LOC grew, trim or explain why.
- Prefer existing narrow helpers over repeated casts/guards. Add local helpers when 2+ nearby call sites share real boundary logic.
- Prefer ctor parameter properties for injected deps/config. Do not ban them for erasable-syntax purity.
@@ -191,7 +227,7 @@ Skills own workflows; root owns hard policy and routing.
- Use `$technical-documentation` for docs writing/review. Docs change with behavior/API.
- Codex harness upgrade (`extensions/codex/package.json` `@openai/codex`): refresh `docs/plugins/codex-harness.md` model snapshot from the new harness `model/list`.
- Docs final answers: include relevant full `https://docs.openclaw.ai/...` URL(s). If issue/PR work too, GitHub URL last.
- `CHANGELOG.md`: release-owned. Do not edit for normal PRs, direct `main` fixes, or `ship it`; only explicit release/changelog generation may rewrite it. Do not ask contributors/agents for changelog edits.
- `CHANGELOG.md`: release-only. Do not edit for normal PRs, direct `main` fixes, or `ship it`; release generation owns it. Do not ask contributors/agents for changelog edits.
- User-facing `fix`/`feat`/`perf`: put release-note context in PR body, squash message, or direct commit: behavior, surface, issue/PR refs, credited human author/reporter.
- Release generation: derive `CHANGELOG.md` from merged PRs + all direct `main` commits. Entries: active `### Changes`/`### Fixes`, single-line, thank credited humans; never thank bots/forbidden handles: `@openclaw`, `@clawsweeper`, `@codex`, `@steipete`.
@@ -199,18 +235,19 @@ Skills own workflows; root owns hard policy and routing.
- Commit via `scripts/committer "<msg>" <file...>`; stage intended files only.
- Commits: conventional-ish, concise, grouped.
- No manual stash/autostash unless explicit. No branch/worktree changes unless requested.
- No manual stash/autostash unless explicit. Branch switches ok when useful; no new worktrees unless requested.
- `main`: no merge commits; rebase on latest `origin/main` before push. After one green run plus clean rebase sanity, do not chase moving `main` with repeated full gates.
- User says `commit`: your changes only. `commit all`: all changes in grouped chunks. `push`: may `git pull --rebase` first.
- User says `ship it`: commit intended changes, pull --rebase, push.
- Do not delete/rename unexpected files; ask if blocking, else ignore.
- Bulk PR close/reopen >5: ask with count/scope.
- Bulk PR close/reopen >50: ask with count/scope.
## Security / Release
- 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`.
- Dependency patches/overrides/vendor changes need explicit approval. `pnpm-workspace.yaml` patched dependencies use exact versions only.
- Release/package guards: no hard-coded retired-package denylists; use generic artifact/dependency checks or fix build source.
- Lockfiles/shrinkwrap are security surface: review `pnpm-lock.yaml`, `npm-shrinkwrap.json`, `package-lock.json`; root/plugin npm packages ship shrinkwrap, not package-lock.
- Carbon pins owner-only: do not change `@buape/carbon` unless Shadow (`@thewilloftheshadow`, verified by `gh`) asks.
- Releases/publish/version bumps need explicit approval. Use `$release-openclaw-maintainer`.
@@ -228,8 +265,10 @@ Skills own workflows; root owns hard policy and routing.
- Version bump surfaces live in `$release-openclaw-maintainer`.
- Parallels: `$openclaw-parallels-smoke`; Discord roundtrip: `$parallels-discord-roundtrip`.
- Crabbox/WebVNC human demos: keep remote desktop visible/windowed; no fullscreen remote browser unless video/capture-style output.
- Before sharing WebVNC links, use Crabbox screenshot first; verify real app/path works and target UI is not broken.
- ClawSweeper ops: `$clawsweeper`. Deployed hook sessions may post one concise `#clawsweeper` note only when surprising/actionable/risky; if using message tool, reply exactly `NO_REPLY`.
- Generated-media completions wake the requester agent first. Requester visible-reply config decides final text vs message tool; direct media send is fallback/recovery only.
- `message_tool_only`: normal agent final visible reply = current-source `message(action=send)` only. No `NO_REPLY` prompt/contract; no message call = no source reply. Plugin-owned bound-thread reply = plugin return value; no message tool needed. Never auto-publish private final.
- Memory wiki prompt digest stays tiny; prefer `wiki_search` / `wiki_get`; verify contact data before use; source-class provenance for generated people facts.
- Rebrand/migration/config warnings: run `openclaw doctor`.
- Never edit `node_modules`.

View File

@@ -2,48 +2,219 @@
Docs: https://docs.openclaw.ai
## 2026.5.30
## 2026.6.5
### Highlights
- Agents and CLI-backed runtimes recover more cleanly from interrupted tool calls, stale session bindings, compaction handoffs, and media delivery retries. (#88129, #88136, #88141, #88162, #88182)
- Channels and mobile delivery are steadier across Telegram, WhatsApp, iMessage, Slack, Discord, Microsoft Teams, Google Chat, Google Meet, and iOS realtime Talk. (#88096, #88105, #88183, #88231)
- Provider and plugin requests now bound more timers, retries, OAuth/device-code lifetimes, media downloads, local service probes, and generated-content polling paths before they can hang a run.
- Skills, session metadata, gateway runtime state, plugin metadata, and store writes do less repeated work on hot paths while keeping config and dispatch behavior stable.
- Workboard, SecretRef plugin manifests, hosted iOS push relay, and external Copilot/Tokenjuice packaging add broader orchestration, integration, and plugin delivery surfaces. (#82326, #87469, #87796, #88107, #88117)
- Release, CI, Docker, E2E, and diagnostics lanes now cap more logs, response bodies, readiness probes, artifact checks, and status polling so failures report bounded proof instead of stalling.
- QQBot now strips model reasoning/thinking scaffolding before native delivery, preventing raw `<thinking>` content from leaking into channel replies. (#89913, #90132) Thanks @openperf.
- MCP tool results now coerce `resource_link`, `resource`, `audio`, malformed image, and future non-text/image blocks at the materialize boundary, preventing Anthropic 400s and poisoned session history after a tool returns richer MCP content. (#90710, #90728) Thanks @RanSHammer and @849261680.
- Anthropic extended-thinking sessions recover after prompt-cache expiry or Gateway restart because stream start events wait for `message_start`, letting pre-generation signature errors trigger the existing recovery retry. (#90667, #90697) Thanks @openperf.
- Parallel is now a bundled `web_search` provider with `PARALLEL_API_KEY` discovery, guarded endpoint handling, cache-safe session ids, onboarding picker support, and docs. (#85158) Thanks @NormallyGaussian.
- Google Vertex ADC users get static catalog rows and runtime model resolution again, while single-provider cooldown recovery and memory adapter status checks are more reliable. (#90506, #90609, #90717, #90816) Thanks @849261680.
- Matrix can preflight voice notes before mention gating, preserve thread reads/replies through Matrix relations pagination, and carry QA coverage for voice and thread flows. (#78016, #90415)
- Auth and plugin install state is more durable: auth profiles now live in SQLite, official npm plugin install records keep their trusted pins, and prerelease fallback integrity checks avoid carrying stale integrity forward. (#89102, #88585)
- macOS node mode no longer silently self-reconnects away from a healthy direct Gateway session, reducing unexpected companion app session churn. (#90668, #90815) Thanks @vrurg.
- Upgrade and service paths are safer: cron legacy JSON stores migrate during doctor preflight, service env placeholders no longer mask state-dir secrets, WhatsApp startup waits are bounded, and disabled WhatsApp accounts tear down on config reload. (#90072, #90208, #90277, #90488, #90486, #87951, #87965) Thanks @MonkeyLeeT, @sallyom, @mcaxtr, and @MukundaKatta.
### Changes
- Search/providers: add the Parallel bundled web-search plugin, live provider tests, registration contracts, onboarding/docs wiring, and guarded `api.parallel.ai/v1/search` support. (#85158) Thanks @NormallyGaussian.
- Matrix/channels: add voice-message preflight and thread-aware read/reply behavior, including Matrix QA scenario wiring and docs for voice-message behavior. (#78016, #90415)
- Skills/ClawHub: install ClawHub skills backed by GitHub repositories through the resolved install API, download the pinned GitHub commit, keep install-policy checks, and report install telemetry after success. (#90478) Thanks @Patrick-Erichsen.
- Google Chat/channels: add native approval card actions and click handling so Google Chat approvals use platform-native cards instead of generic message flow.
- Mobile: Android provider/model screens now surface expiring, unavailable, unresolved, and attention states more clearly, while iOS settings and Talk tabs keep diagnostics, gateway rows, attachment labels, and unavailable Talk controls reachable.
- Memory: QMD search can use the new rerank toggle, and memory adapter status uses the resolved default model identity when checking plain status. (#61834)
- Docs/tooling: add Parallel search docs, refresh weather-skill guidance toward `web_fetch`, clarify legacy `openai-codex` auth, document release/test helper scripts, and tighten changed-test routing docs for CI/debugging work. (#90028, #90250) Thanks @fuller-stack-dev.
- Platform maintenance: refresh Android, Swift/macOS, Docker, CodeQL, Buildx, Docker build/push, and Codex Action dependencies for this release train. (#74980, #81757, #86481, #86483, #90601)
### Fixes
- Channel content boundaries: QQBot now strips reasoning/thinking tags before sending, preserving final answers while hiding internal model narration from users. (#89913, #90132) Thanks @openperf.
- Agents/MCP/providers: coerce non-text/image MCP tool-result blocks before they reach provider converters, preserving valid images and turning richer MCP content into text instead of malformed image blocks. (#90710, #90728) Thanks @RanSHammer and @849261680.
- Anthropic/Codex/ACP/agent recovery: defer Anthropic stream start events until `message_start`, strip stale compaction thinking signatures before Anthropic replay, detect unsigned thinking-only stalls, refresh prompt fences after compaction writes, reject empty completion handoffs, preserve parent streaming-off overrides/shared progress commentary, forward heartbeat metadata to context-engine hooks, and cover Codex session/thread migration edge cases. (#90667, #90697, #90163, #90108, #89874, #89505, #90632, #89302, #90729, #90317, #90319) Thanks @openperf, @100yenadmin, and @ooiuuii.
- Provider/model resolution: preserve Google Vertex ADC auth markers in generated catalogs, re-probe a single-provider primary after cooldown, share Codex model visibility, fail closed for unknown model auth, preserve Codex alias availability, keep unresolved profile refs unknown, and avoid resolving auth while listing models. (#90506, #90609, #90717, #90702) Thanks @849261680.
- Gateway/macOS/mobile: avoid duplicate Gateway probe warnings by identity, rate-limit node pairing requests while preserving paired-node reconnects, keep macOS node mode on a healthy direct Gateway session, keep iOS diagnostics and gateway rows reachable, and avoid Linux ARM Gradle resource tasks during Android builds. (#85791, #90147, #90668, #90815) Thanks @giodl73-repo and @vrurg.
- TUI/chat/Workboard/auto-reply: optimistic user messages stay stable across stale history reloads, runId reassignment, and abort windows instead of disappearing, jumping, or lingering as ghost rows; Workboard stale lifecycle bulk updates no longer overwrite newer status/provenance; message-tool sends now count as delivery. (#86205, #89600, #88592, #90123) Thanks @RomneyDa.
- Cron/update/service env: doctor config preflight now migrates legacy cron JSON stores into SQLite before runtime reads, service env planning skips unresolved placeholders that would mask state-dir `.env` values, and session transcript rewrites keep registry markers/discriminants consistent. (#90072, #90208, #90277, #90488) Thanks @MonkeyLeeT and @sallyom.
- Security/config/tooling: guard MCP HTTP redirects, protect global agent config defaults, and keep release/test/tooling proof failures bounded and explicit. (#89732, #90145)
- Channels: WhatsApp restarts when per-account config changes, bounds background startup waits, closes failed sockets, and preserves reconnect behavior; Mattermost slash commands keep their state on `globalThis`; Feishu streaming cards preserve full merged content; voice-call tracks Twilio streams after connect; ClickClack reply tools respect `toolsAllow`. (#87951, #87965, #90486, #68113, #90534, #90181, #90607, #89500) Thanks @MukundaKatta, @mcaxtr, @infoanton, @mushuiyu886, and @sahibzada-allahyar.
- Release/CI/E2E: main CI guard drift, PR merge diff scoping, live Docker credential staging, base-image qualification, installer Docker classification, Playwright dependency install recovery, API-key auth for Codex live Docker lanes, Parallels option terminators, and JSON-mode progress handling are tighter so release proof fails cleaner. (#90532, #90287, #90058) Thanks @RomneyDa, @hxy91819, and @mrunalp.
- Tests/state isolation: provider, media, auth, cron, task, session, sandbox, Gateway, and Codex timeout fixtures now scope more home/state/env data per test, reducing cross-test leakage and making release validation failures less noisy. (#90027, #89974)
## 2026.6.2
### Highlights
- Plugin and skill installs now use an operator install policy instead of the old dangerous-code scanner path, with clearer doctor, CLI, ClawHub, and troubleshooting surfaces for package, archive, source, upload, and marketplace installs. (#89516) Thanks @joshavant.
- Telegram, Feishu, Discord, WhatsApp, and outbound delivery paths got safer around duplicate transcript mirrors, Telegram admin writeback, streamed-final previews, approval allowlists, setup runtime state, poll modifiers, Discord voice errors, and internal progress traces. (#88973, #89626, #89812, #89035, #89814, #89813, #89601) Thanks @pgondhi987, @Petru2224, @zhangguiping-xydt, @codezz, and @takhoffman.
- Chat, Control UI, Skill Workshop, Workboard, Android companion shell, and WebChat flows now preserve visible streaming text, reconcile completed sends, expose ACK timing, add Workboard keyboard movement, harden dialog accessibility, lazy-load usage views, keep current chat toggles working, and improve Android companion-first shell navigation. (#89801, #89777, #89802) Thanks @vincentkoc.
- Security, policy, and config recovery now reject corrupt shell snapshots, unsupported policy keys, unsafe exec approval precheck environments, malformed script limits, and suspicious gateway startup configs while adding data-handling conformance checks. (#89701, #87074, #81488, #87056, #89480) Thanks @RomneyDa, @giodl73-repo, and @mmaps.
- Gateway, agent, Codex, provider, model, and memory paths now recover session write-lock release failures, abandoned Codex app-server startups, stream-to-parent ACP spawns, custom-provider runtime fanout, bundled provider aliases, prompt-cache boundaries, Gemini stop sequences, Kimi cache markers, and watcher pressure warnings. (#89811, #89244) Thanks @RomneyDa and @takhoffman.
- Release, CI, Docker, Crabbox/Testbox, package, and E2E validation lanes now bound more network calls, malformed numeric limits, process groups, cleanup leaks, package hydration paths, Windows installer publishing, release asset verification, and log drains so failures produce bounded proof instead of hanging.
### Changes
- Plugins/security: replace dangerous-code scanner enforcement with operator install policy, install-policy context, doctor checks, install/update CLI wiring, ClawHub metadata paths, and package/archive/source/upload lifecycle coverage. (#89516) Thanks @joshavant.
- Policy: add data-handling conformance checks and reject unsupported policy keys. (#87056, #87074) Thanks @giodl73-repo.
- Telegram/channels: show commentary and reasoning in progress drafts, share progress draft compositors across channel plugins, and keep Telegram polling stop/reset boundaries cheaper and more reliable.
- UI/mobile: add Workboard keyboard movement controls, tighten Workboard card operations, improve Android companion-first shell UX, and document chat ACK timing metadata. (#89802) Thanks @vincentkoc.
- Release metadata: align the root package, publishable plugin manifests, generated shrinkwraps, appcast, iOS, Android, macOS, Matrix plugin changelog, and docs/generated baselines with the 2026.6.2 beta train.
- Release/packaging: promote Windows node installer publishing, require verified Windows release asset links, and document GitHub release-note edits.
- Docs: refresh Windows Hub setup guidance and document Gateway, CLI, and plugin SDK helper contracts.
### Fixes
- Channels/outbound: keep channel sends durable when transcript mirroring fails, stop schema-padded poll modifiers from blocking normal sends, preserve WebChat `sessions_send` handoffs, preserve Discord channel-label suppression while hiding internal agent failure traces, match Discord libopus error shapes, and sanitize Discord tool progress scaffolding. (#89626, #89812, #89601) Thanks @Petru2224, @codezz, and @takhoffman.
- Telegram/Feishu: require admin rights for Telegram target writeback, keep Telegram DM exec approval allowlists working with `ask:off`, prevent Telegram preview duplication across streaming modes, isolate verbose status after streamed finals, cancel clean restart stop timers, slow polling restart storms, and wire Feishu setup runtime setters. (#88973, #89035, #89813, #89814) Thanks @pgondhi987, @zhangguiping-xydt, and @takhoffman.
- Feishu: preserve full streaming card content by sending the merged text on each update instead of only the latest delta, so card readers see complete output when intermediate frames are missed. (#90181) Thanks @mushuiyu886.
- Chat/UI/Gateway: preserve visible chat stream text, clear stale stream buffers before terminal commits, reconcile completed sends, scroll pending sends into view, harden Workboard dialog accessibility, stabilize WebChat prompt-cache affinity, overlap chat catalog startup, render chat history incrementally, lazy-load usage dashboard, and report gateway health auth diagnostics. (#89337) Thanks @RomneyDa.
- Agents/Codex/providers/models: release session write locks when prompt-release fence reads fail, retire abandoned Codex app-server startups, keep stream-to-parent ACP spawns registered, close Codex startup clients on timeout, recover bundled provider aliases, avoid custom-provider runtime fanout, preserve provider prompt-cache boundaries, forward Gemini stop sequences, and strip Kimi-incompatible Anthropic cache markers. (#89811) Thanks @takhoffman.
- Memory/build/update: warn after startup watcher pressure checks, externalize optional Baileys image backends, restore and pin Canvas A2UI compatibility assets, keep plugin repair fetch failures nonblocking, restore Skill Workshop view switching, and keep the current chat toggle active after awaited session switches. (#89244) Thanks @RomneyDa.
- Plugins/auth: keep Hermes migration reports pointed at SQLite auth-profile stores and keep plugin auth-profile reuse tests on the current store path.
- Plugins/CLI: avoid importing the runtime plugin loader only to clear in-process caches after short-lived plugin install, enable, disable, update, and uninstall commands refresh registry metadata.
- Security/config/tooling: reject corrupt shell snapshots, suspicious gateway startup configs, malformed release/test/tooling/Docker/perf numeric limits, oversized audit responses, unsafe exec precheck env, and invalid pending-agent SQLite scaffold denials. (#89701, #89705, #89480, #81488) Thanks @RomneyDa and @mmaps.
- Release/CI/E2E: restore package changelog extraction after the post-2026.6.1 version bump, keep hydrated pnpm modules under `node_modules` for ARM/Linux package lifecycle scripts, keep OpenAI live-cache prerequisites advisory while Anthropic prerequisites stay blocking, retry Windows Parallels background log appends on transient file-lock errors, bound candidate GitHub and cross-OS Discord fetches, harden ARM smoke/browser checks, show Docker build heartbeats, reset Crabbox pnpm hydrate state, and isolate Testbox/Docker/release journey artifacts.
- Release/CI/E2E: keep Crabbox hydrate pnpm stores on the persistent cache volume while still resetting volatile modules, reducing cold installs and runner memory churn.
- Release/CI/E2E: fail secret-provider proof startup immediately when the gateway exits by signal instead of waiting for the readiness timeout.
- Release/CI/E2E: report plugin gateway gauntlet command-log write failures as failed rows instead of crashing the harness from child-process callbacks.
- Release/CI/E2E: abort stalled Kitchen Sink RPC readiness probes as soon as the gateway exits so proof failures return promptly.
- Release/CI/E2E: keep Parallels JSON-mode progress on stderr so macOS, Linux, Windows, and aggregate update smoke summaries stay parseable on stdout.
- Release/CI/E2E: fail Crabbox sparse-sync runs clearly when their temporary full checkout disappears while the child process is running, instead of pretending the child's deleted cwd can be repaired.
- Release/CI/E2E: fail PTY-backed E2E commands when transcript logs cannot be written instead of letting missing proof capture crash around a live child process.
- Release/CI/E2E: fail mock OpenAI request-log write errors with clear HTTP responses instead of leaving provider proof clients waiting on a broken socket.
- Release/CI/E2E: fail Parallels host-command log write errors through the command result path instead of leaving streaming smoke phases unresolved.
## 2026.6.1
### Highlights
- Agents and CLI-backed runtimes recover more cleanly from interrupted tool calls, stale session bindings, compaction handoffs, auth-profile failover, reasoning-tag cleanup, and media delivery retries. (#85798, #87484, #88129, #88136, #88141, #88162, #88182, #88924, #89220) Thanks @RomneyDa, @neeravmakwana, and @omarshahine.
- Channels and mobile delivery are steadier across Telegram, WhatsApp, iMessage, Slack, Discord, Microsoft Teams, Google Chat, Google Meet, QQBot, and iOS realtime Talk. (#88096, #88105, #88183, #88749, #88866, #88948, #88984, #89015, #88231) Thanks @omarshahine, @Jensenwgd, and @sliverp.
- Provider and plugin requests now bound more timers, retries, OAuth/device-code lifetimes, media downloads, local service probes, generated-content polling, provider-catalog failures, reasoning output, and model catalog paths before they can hang a run. (#88480, #88512, #88767, #88781, #88851, #88860, #89343, #89379, #89400) Thanks @vincentkoc, @charles-openclaw, @zz327455573, @849261680, and @XuZehan-iCenter.
- Skills, Skill Workshop, and plugin loading now handle proposal review, stale disabled snapshots, support-file approvals, locale/routing fixes, and loader failures more clearly, so channel turns avoid disabled SecretRefs and operators get better recovery guidance. (#79072, #79173, #88734) Thanks @zeus1959 and @shakkernerd.
- Workboard, SecretRef plugin manifests, hosted iOS push relay, typed presentation command actions, and external Copilot/Tokenjuice packaging add broader orchestration, integration, SDK, and plugin delivery surfaces. (#82326, #87469, #87796, #88107, #88117, #88721, #89336) Thanks @RomneyDa.
- Chat and Control UI startup paths keep sends alive through history loading, stream deltas incrementally, skip markdown work while streaming, keep drafts local while typing, clear the composer after sends, trace first-output latency, cache transcript renders, prioritize first connect, and expose calmer composer controls and notification settings. (#74715, #88772, #88825, #88952, #88960, #88998, #89030, #89106) Thanks @VladyslavLevchuk, @vincentkoc, and @sallyom.
- iMessage monitor state, inbound queues, Discord thread bindings, plugin install ledgers, session metadata, gateway runtime state, plugin metadata, memory watchers, and store writes moved toward SQLite-backed or cached state so restarts and hot paths do less repeated work. (#88794, #88797, #88866, #89075, #89185, #89188, #85351) Thanks @RomneyDa and @NianJiuZst.
- Release, CI, Docker, E2E, plugin install, update, doctor, diagnostics, and security lanes now cap more logs, response bodies, readiness probes, artifact checks, status polling, child workflow waits, docker package cleanup, quiet test stalls, downgrade repair, and health probes so failures report bounded proof instead of stalling. (#84988, #87914, #87952, #88966, #89169, #89701, #89731) Thanks @LibraHo, @Niriakot, @MukundaKatta, and @RomneyDa.
### Changes
- Docs: add a dedicated Skill Workshop guide covering governed skill creation, reviewable proposals, CLI, Gateway, agent tool behavior, approval policy, support files, and recovery; refresh ClawHub cards; and add ClawHub CLI, iMessage SSH-wrapper TCC, Android helper, diff-language, and host-local media-send guidance. (#79658, #88734, #88758, #88865, #89297) Thanks @simplyclever914, @shakkernerd, @vyctorbrzezowski, @TurboTheTurtle, @RomneyDa, and @Wang-Yeah623.
- Skills: let the `skill_workshop` agent tool apply, reject, and quarantine explicit proposals through the guarded review flow. Thanks @shakkernerd.
- Skills: let proposals carry approved support files under standard skill folders, with scanner, hash, and rollback safeguards. Thanks @shakkernerd.
- Skills: let pending proposals be revised in place with versioned, dated proposal frontmatter before approval. Thanks @shakkernerd.
- Skills: add Skill Workshop with pending proposals, CLI/Gateway review actions, rollback metadata, and the `skill_workshop` agent tool. Thanks @shakkernerd.
- Skill Workshop: add the Control UI navigation, styled dashboard, proposal today view, revision dialog, file preview modal, searchable preview files, reusable session handoff, and localized strings.
- Plugins: externalize Tokenjuice as the official `@openclaw/tokenjuice` plugin with npm and ClawHub publish metadata.
- Plugins: externalize the GitHub Copilot agent runtime as the official `@openclaw/copilot` plugin with npm and ClawHub publish metadata.
- iOS: add hosted push relay defaults, realtime Talk playback, and a guarded WebSocket ping path for more reliable mobile sessions. (#88096, #88105, #88231)
- iOS: support native iPad display layouts.
- Android: add installed-app inspection commands, notification picker helpers, and updated-system-app classification.
- Workboard: add orchestration primitives and agent coordination tools for multi-agent planning and run tracking. (#87469)
- Workboard: wire task-backed board runs and show task comments in the edit modal.
- Code mode: add internal namespaces for scoped agent/global sessions and exact namespace tool dispatch. (#88043)
- Code mode: add MCP API files and docs for code-mode integrations.
- Gateway: support Tailscale Serve service names for local service routing.
- Control UI: add a Dreaming-tab agent selector and propagate the selected agent through Dreaming status, diary, and diary actions. (#78748) Thanks @stevenepalmer.
- Control UI: add calmer chat composer controls, local draft typing state, and first-output latency instrumentation for active chat entry. (#88772, #88998) Thanks @vincentkoc.
- Plugins: add a SecretRef provider integration manifest contract and extract shared LLM core packages for provider/plugin reuse. (#82326, #88117)
- Plugin SDK: add typed presentation command actions and the bounded `resolve_exec_env` hook for plugin-provided exec environment contributions. (#88721)
- Plugins: persist the plugin install index in SQLite so installed package lookup survives reloads with less filesystem scanning. (#88794)
- Providers: add MiniMax M3 model support. (#88860)
- Tools/media: allow validated host-local text document media sends while keeping unsafe plain-text media sends blocked. (#79658) Thanks @simplyclever914.
- Doctor: add disk space health checks and stabilize post-upgrade JSON probes.
- Channels: store inbound queues in SQLite and migrate iMessage monitor state to SQLite-backed tracking. (#88797)
- Skills: add the core skills index and centralize skills runtime loading, status, filtering, and prompt formatting.
### Fixes
- Release/CI/E2E: fail early when Crabbox sparse-sync full checkouts do not have enough local disk, with guidance for moving the sync root.
- Build: render independent CLI startup metadata help snapshots concurrently to cut cold build-all metadata time.
- Plugins: stop timed-out package-boundary prep steps by process group so descendant TypeScript/helper processes do not survive local check cleanup.
- Control UI: serve static assets asynchronously after safe-open checks so large UI files do not block Gateway request handling.
- Scripts/UI: forward direct wrapper SIGHUP shutdown to child processes so terminal hangups do not leave wrapped dev commands running.
- Gateway: return the post-expiration pending-work revision from node drains so reconnecting nodes do not observe stale queue revisions after expired items are pruned.
- Release/CI/E2E: keep temporary full-sync checkouts alive while slow Crabbox leases boot, so sparse worktree runs do not lose their sync source before file-list generation.
- Release/CI/E2E: normalize inherited Linux `C.UTF-8` locale settings before raw AWS macOS Crabbox bootstrap commands, avoiding macOS locale warnings during package-manager hydration.
- Release/CI/E2E: keep gateway watch regression checks from copying large static plugin assets inside the measured idle window.
- Update: keep core updates nonblocking when missing external plugin repair downloads or soft plugin repair warnings would otherwise stall, pin post-core plugin compatibility to the downgraded core version, and still block installed active plugin payload smoke failures. (#84431, #87914, #87952) Thanks @TurboTheTurtle, @Niriakot, and @MukundaKatta.
- Agents/providers: keep streaming tool-call argument parsing record-shaped when providers emit valid non-object JSON such as `null` or arrays.
- Release/CI/E2E: reset incremental log readers when watched log files rotate without shrinking, so same-size replacements do not hide new readiness or RPC lines.
- Talk: preserve explicit `null` payloads on controller-created turn and output-audio lifecycle events.
- Agents/TUI: keep local custom provider runs from loading plugin runtime and auth alias metadata when plugins are disabled.
- Agents/TUI: restore in-flight TUI run switch-back behavior, keep no-policy native hook fallback available, guard vanished workspaces, and keep lightweight isolated subagents lightweight.
- Agents/media: keep async image, music, and video generation starts from ending the Codex turn, avoid duplicate generated-media fallbacks, and let mixed requests continue with summaries or other work while media renders in the background. (#89220) Thanks @omarshahine.
- Agents/Codex: keep public OpenAI API-key profiles from being treated as native Codex app-server auth while preserving persisted Codex OAuth sessions.
- Agents/Codex: stream Codex app-server final-answer partials to live reply previews, preserve ACP metadata in SQLite, prefer real tool results over synthetic repair output, prevent aborted app-server turn handles from lingering, migrate legacy OpenAI Codex `lastGood` auth state, and preserve workspace/session metadata through ACP runtime refactors. (#88405, #88724, #88730) Thanks @vincentkoc.
- Control UI: keep collapsed tool cards labeled with the tool name and action instead of generic output text. Thanks @shakkernerd.
- Agents/Codex: surface Skill Workshop guidance in Codex app-server prompts when `skill_workshop` is available. Thanks @shakkernerd.
- Skill Workshop: restore and localize the Control UI board/today view switcher so review workflows keep their intended layout toggle across locales. Thanks @shakkernerd.
- Agents/auth: write auth profiles atomically, dispatch auth failures by type, add force re-login and exhausted-failover recovery, clear legacy auto fallback pins, preserve workspaces during state-only uninstall, and compact before oversized turns so recovery paths avoid partial state. (#85798, #87484, #89181) Thanks @RomneyDa and @neeravmakwana.
- Skills: skip disabled skill env overrides from stale persisted snapshots so disabled skill `apiKey` SecretRefs cannot abort embedded or channel turns. (#79072, #79173) Thanks @zeus1959.
- Skill Workshop: render the Control UI tab from filtered navigation state and keep filtered fallback routing stable.
- CLI: avoid live catalog validation during `openclaw agents add`, so adding a secondary agent no longer depends on provider catalog availability. (#76284, #88314) Thanks @zhangguiping-xydt.
- CLI: harden CLI and plugin edge cases, and keep `plugins list --json` on the snapshot-only path so plugin sweeps avoid loading the full runtime status graph. (#88896)
- CLI/desktop: bridge WSL clipboard operations through the shell, recognize manual-update launchd jobs, and keep machine-readable startup output parseable during progress setup. (#88764, #88689) Thanks @alexzhu0.
- Plugins: make PixVerse external-plugin ClawHub metadata explicit and keep it out of bundled dist builds.
- Plugins: clarify plugin loader failure guidance and treat soft plugin repair warnings as nonfatal so missing or incompatible plugin packages point operators at the right repair path without blocking unrelated work. (#84431) Thanks @TurboTheTurtle.
- Plugins: preserve npm plugin roots after blocked installs, skip plugin-local `openclaw` peer symlinks during rollback snapshots, relink those peers after restore, isolate cached tool runtime siblings, isolate provider catalog projections and web-provider factory failures, and keep private LLM-core declarations bundled so one bad plugin does not poison sibling runtime paths. (#77237, #88767, #88807, #89336) Thanks @vincentkoc and @RomneyDa.
- Cron: keep SQLite cron migrations compatible with legacy run-log tables, archived job stores, diagnostic cron names, single-job run-history names, startup cron retries, and legacy one-shot delete-after-run behavior. (#88285, #88294, #89075) Thanks @kip-claw.
- Cron: keep update delivery validation scoped, harden restart state, and retire MCP runtimes on isolated cron cleanup.
- Auto-reply: guard dispatcher failure-count probes so missing optional counters do not break SDK-typed recovery paths. (#89318) Thanks @Alix-007 and @takhoffman.
- Memory: serialize QMD update/embed writes per store, reduce Linux watcher fan-out, avoid noisy gateway watcher warnings, retry transient FileProvider-backed reads, preserve phase signals on read errors, harden envelope metadata sanitization, reattach Linux native watchers when directories are recreated, and rewrite generated transcript paths on rollover so memory/search state survives concurrent gateway and CLI activity. (#66339, #85931, #89185, #89188, #89246, #85351) Thanks @openperf, @amittell, @RomneyDa, and @NianJiuZst.
- Memory: keep vector-disabled FTS indexes from resolving embedding providers during sync and search.
- Providers: bound generated media downloads from OpenAI, Runway, xAI, MiniMax, BytePlus, DashScope-compatible, FAL, OpenRouter, Google, Vydra, and Comfy providers.
- Providers: resolve Google defaults to `google-generative-ai`, register Vertex static catalog rows and `gemini-3.1-flash-lite`, align Foundry reasoning metadata, skip DeepSeek V4 thinking params on Foundry fallback, use MiniMax account OAuth endpoints, preserve Copilot Claude 1M capabilities, suppress disabled Ollama reasoning output, forward Gemini stop sequences, switch direct Gemini reasoning to native mode, strip provider self-prefixes and Kimi-incompatible Anthropic cache markers, keep OpenAI stop-finished tool calls, and avoid replay ids when the Responses store is disabled. (#88480, #88512, #88781, #89343, #89379, #89400, #76612) Thanks @coder999999999, @BryanTegomoh, @vliuyt, @charles-openclaw, @zz327455573, @849261680, and @XuZehan-iCenter.
- Providers: cap GitHub Copilot OAuth request timeouts before creating abort signals.
- Cron: retry recurring jobs after transient model rate limits before waiting for the next scheduled slot.
- Agents/Codex: keep live session locks during cleanup, recover interrupted CLI tool transcripts, preserve Codex auth and compaction session identity, clear orphan tool state, cap app-server idle timers, and keep media completion delivery retryable. (#88129, #88136, #88141, #88162, #88182)
- Channels: cap Telegram, Discord, WhatsApp, Signal, Feishu, Google Chat, Microsoft Teams, QQBot, Nostr, Zalo, Zalouser, and Nextcloud-style request/retry timers; preserve SMS approval reply routes; and retry WhatsApp QR login 408 timeouts. (#88183)
- Security/config parsing: reject unsafe OAuth/token lifetimes, retry-after delays, inbound timestamps, response body sizes, command timeout config, sandbox observer token TTLs, and gateway WebSocket calls after close.
- Chat/UI: show Gateway chat failures as visible assistant messages in the Control UI instead of only setting an invisible error state.
- Channels: cap Telegram, Discord, WhatsApp, Signal, Feishu, Google Chat, Microsoft Teams, QQBot, Nostr, Zalo, Zalouser, and Nextcloud-style request/retry timers; preserve SMS approval reply routes; keep iMessage typing active during tool work; allow RFC2544 benchmark ranges for QQBot token fetches; and retry WhatsApp QR login 408 timeouts. (#88183, #88948, #88984, #89015) Thanks @omarshahine, @Jensenwgd, and @sliverp.
- Security/config parsing: reject unsafe OAuth/token lifetimes, retry-after delays, inbound timestamps, response body sizes, command timeout config, sandbox observer token TTLs, corrupt shell snapshots, untrusted workspace setup-only channel loads, remote media reference overreads, trajectory export leaks, hooks-token auth reuse, and gateway WebSocket calls after close. (#86953, #87376, #88974, #89354, #89701) Thanks @hxy91819, @coygeek, @pgondhi987, and @RomneyDa.
- Providers/media: cap local service, model, usage, queue, generated media, TTS, music, workflow polling, and provider OAuth request timers across hosted and local providers.
- Release/CI/E2E: bound release candidate reads, beta smoke REST calls, changelog restore, kitchen-sink and bundled plugin readiness probes, secret-provider probes, Vitest routing, and mainline test flakes. (#88127, #88137, #88155, #88160)
- Performance: reuse prepared provider handles, strict tool schemas, gateway runtime metadata, session maintenance config, plugin metadata, bundled skill allowlists, package-local plugin artifacts, and single-entry store writes.
- Release/CI/E2E: bound release candidate reads, beta smoke REST calls, plugin npm verification commands, changelog restore, cross-OS process groups, kitchen-sink and bundled plugin readiness probes, secret-provider probes, Telegram credential timeouts, Control UI i18n and CLI startup metadata generation, Vitest routing, dependency guard admin approvals, child workflow failure detection, quiet Node test shard stalls, dist cache restores, Docker base-image/package cleanup, and mainline test flakes. (#84988, #88127, #88137, #88155, #88160, #88966, #89169) Thanks @LibraHo and @RomneyDa.
- Release/CI/E2E: keep Kitchen Sink live plugin MCP probes resolving source-checkout workspace packages and align the live gauntlet with current Kitchen Sink diagnostics.
- Backup: accept root-relative hardlink targets during backup verification. (#89328) Thanks @abnershang.
- Release/CI/E2E: run the secret-provider integration proof through the repo pnpm runner so native macOS and Windows validation use the hydrated package-manager shim.
- Release/CI/E2E: run the Telegram desktop proof gateway through the repo pnpm runner so native macOS proof uses the hydrated package-manager shim.
- Docs/CI: run Mintlify anchor checks through the repo pnpm runner so docs link validation works when pnpm is only available through the hydrated package-manager shim.
- Agents: keep configured fallback model metadata typed so provider params, context-token caps, and media input limits do not break changed-gate typechecks.
- Agents: accept hidden `sessions_send` body aliases before validation while keeping the model-facing `message` schema canonical. (#88229) Thanks @zhangguiping-xydt.
- Chat/UI: preserve startup chat sends during history loading, unblock the initial Control UI chat send, stream chat deltas incrementally, skip markdown parsing while streaming, keep drafts local while typing, guard composer rerenders, cache chat transcript renders, record pending-send paint timing, show the Communication Notifications tab, honor Chromium executable overrides, and detect system Chromium for E2E. (#74715, #88952, #88960, #88998) Thanks @VladyslavLevchuk and @vincentkoc.
- Channels: stop schema-padded poll modifiers from turning normal `send` actions into invalid poll sends. (#89601) Thanks @codezz and @takhoffman.
- Channels: preserve long Feishu streaming replies, recover failed progress draft starts, send visible fallbacks when accepted Feishu turns produce no final reply, preserve external `sessions_send` routes, persist Discord thread bindings in SQLite, tolerate iMessage self-chat timestamp skew, preserve colon-prefixed slash commands in mention parsing, decode Nostr `npub` allowlists correctly, and suppress raw provider errors during channel delivery. (#87896, #88749, #88803, #88866) Thanks @MonkeyLeeT.
- Config/status/doctor: skip unresolved shell references in state-dir dotenv files, resolve gateway auth secrets during deep status audits, surface disabled Codex plugin routes in doctor lint, respect explicit PI runtime policy, report runtime tool-schema and gateway health credential errors, clear recovered embedded-run activity, migrate voice-call call logs through doctor, and keep post-upgrade JSON stable. (#88731, #88761, #88820, #88288, #89731) Thanks @brokemac79, @openperf, and @RomneyDa.
- Gateway/session state: list commands from the Gateway plugin registry, harden MCP loopback tool schemas, hide phantom agent-store rows from `sessions.list`, make task persistence failures explicit, support Tailscale Serve service names, guard Browser/Chrome pending attach aborts, and carry session UUIDs on interactive dispatch events. (#88305) Thanks @rohitjavvadi.
- Gateway/plugins: narrow plugin lookup memoization to the stable plugin/runtime inputs, avoiding repeated lookup work without mixing disabled or filtered plugin state.
- OpenAI/TTS: handle speed directives for OpenAI TTS voices. (#74089)
- CI/Crabbox: keep default runner capacity on the Azure credit-backed on-demand D4 lane with the Azure SSH port and a Git-independent full check job, so broad validation avoids low-priority spot quota stalls, hydrate port mismatches, non-Git hydrated workspaces, and stale AWS region hints.
- CI/Crabbox: route Crabbox wrapper and Testbox workflow edits to their regression tests so changed-test gates do not silently run zero specs.
- CI/workflows: route workflow sanity helper edits to their guard tests and cover composite-action input interpolation checks.
- CI/tooling: route CI scope, dependency, changelog, and docs helper edits to their owner tests instead of silently skipping changed-test coverage.
- CI/tooling: route package, release, and install helper edits to their owner tests so changed-test gates cover publish and installer script changes.
- CI/tooling: route shared script library edits through their owner tests so lock, process, safety, and scan helpers do not skip changed-test coverage.
- CI/tooling: skip expensive import-graph scans once a changed diff already requires broad fallback, keeping local changed-test planning fast while still collecting explicit owner tests.
- CI/tooling: route script edits through conventional owner tests when matching `test/scripts` or `src/scripts` coverage already exists.
- CI/tooling: honor option terminators in the memory FD repro script so follow-on arguments are not reparsed.
- Release/CI/E2E: assert plugin lifecycle runtime inspect output instead of only capturing it.
- Release/CI/E2E: make gateway-network prove the advertised health RPC and retry early WebSocket closes without burning full open timeouts.
- Release/CI/E2E: honor option terminators across release, Parallels smoke, plugin gauntlet, and extension-memory scripts.
- Release/CI/E2E: fail plugin gateway gauntlet QA chunks when the requested suite summary is missing or invalid.
- Performance: prebuild QA runtime probes with generated plugin assets but without CLI startup metadata.
- Performance: skip declaration bundling for runtime-only CLI startup and gateway watch build profiles.
- Performance: reuse prepared provider handles, strict tool schemas, gateway runtime metadata, session maintenance config, plugin metadata, bundled skill allowlists, package-local plugin artifacts, single-entry store writes, and validated/serialized session prompt blobs.
## 2026.5.28
### Highlights
- Agent and Codex runtime recovery is steadier: subagents keep cwd/workspace separation, hook context stays prompt-local, session locks release on timeout abort, stale restart continuations are avoided, and Codex app-server/helper failures no longer tear down shared runtime state. (#87218, #86875, #87409, #87399, #87375)
- Channel delivery and session identity got safer across outbound plugin hooks, Matrix room ids, iMessage reactions/approvals, Slack final replies, Discord recovered tool warnings, and Microsoft Teams service URL trust checks. (#73706, #75670, #87366, #87451, #87334)
- Mobile and chat surfaces got a broader refresh: the iOS Pro UI, Gateway chat transport, onboarding, Talk permissions, WebChat reconnect delivery, and session picker behavior now preserve more state across reconnects and empty searches. (#87367, #87531, #87682)
- CLI, auth, doctor, and provider paths fail faster and recover more clearly: malformed numeric/version options are rejected, OAuth and local service startup requests are bounded, legacy `api_key` auth profiles migrate to canonical form, and restart guidance is actionable. (#87398, #86281, #87361)
- Plugin and Gateway hot paths do less repeated work while preserving cache correctness for install records, config JSON parsing, tool search catalogs, session stores, manifest model rows, auto-enabled plugin config, browser tokens, and viewer assets. (#86699)
- Agent and Codex runtime recovery is steadier: subagents keep cwd/workspace separation, hook context stays prompt-local, session locks release on timeout abort while live OpenClaw locks survive cleanup, stale restart continuations are avoided, and Codex app-server/helper failures no longer tear down shared runtime state. (#87218, #86875, #87409, #87399, #87375, #88129)
- Channel delivery and session identity got safer across outbound plugin hooks, Matrix room ids, iMessage reactions/approvals, Slack final replies, Discord recovered tool warnings, runtime-config message actions, WhatsApp profile auth roots, Telegram polling, and Microsoft Teams service URL trust checks. (#73706, #75670, #87366, #87451, #87334, #84535, #82492, #83304, #87160)
- Mobile and chat surfaces got a broader refresh: the iOS Pro UI, hosted push relay default, realtime Talk tab playback, Gateway chat transport, onboarding, Talk permissions, WebChat reconnect delivery, and session picker behavior now preserve more state across reconnects and empty searches. (#87367, #87531, #87682, #88096, #88105) Thanks @ngutman and @BunsDev.
- Browser, channel, and automation inputs are stricter: Browser tool timeouts, viewport/tab indices, Gateway ports, cron retry handling, Discord component ids, schema array refs, Telegram callback pages, and channel progress callbacks now reject malformed values earlier and preserve the intended delivery context. (#82887)
- Provider, media, and document coverage expands with Claude Opus 4.8, Fal Krea image schemas, NVIDIA featured models, MiniMax streaming music responses, encrypted PDF extraction, voice model catalogs, GitHub Copilot agent runtime support, and a Codex Supervisor plugin path for delegated Codex workflows. (#87845, #87890, #80775, #84764, #87751, #87794)
- CLI, auth, doctor, and provider paths fail faster and recover more clearly: malformed numeric/version options are rejected, workspace dotenv provider credentials are ignored, heartbeat defaults, OAuth/token lifetimes, and local service startup requests are bounded, agent auth health labels are clearer, legacy `api_key` auth profiles migrate to canonical form, and restart guidance is actionable. (#87398, #86281, #87361, #88133, #83655, #87559, #88088, #85924) Thanks @vincentkoc and @giodl73-repo.
- Plugin and Gateway hot paths do less repeated work while preserving cache correctness for install records, config JSON parsing, tool search catalogs, session stores, manifest model rows, auto-enabled plugin config, browser tokens, viewer assets, and release-split external plugin packages. (#86699)
- Release, QA, and E2E validation now bound more log, artifact, harness, and cross-OS waits so failing lanes produce proof instead of hanging or false-greening.
### Changes
@@ -51,25 +222,41 @@ Docs: https://docs.openclaw.ai
- Status: show active subagent details in status output.
- Diffs: split the default language pack and expand default Diffs language coverage while keeping the host floor aligned. (#87370, #87372) Thanks @RomneyDa.
- ClawHub: add plugin display names plus skill verification and trust surfaces. (#87354, #86699) Thanks @thewilloftheshadow and @Patrick-Erichsen.
- iOS: refresh the dev app with Pro Command, Chat, Agents, and Settings tabs wired to gateway sessions, diagnostics, chat, and realtime Talk. (#87367) Thanks @Solvely-Colin.
- Docs: clarify Codex computer-use setup, paste-token stdin auth setup, macOS gateway sleep troubleshooting, native Codex hook relay recovery, container model auth, install deployment cards, device-token admin gating, and backport targets. (#87313, #63050) Thanks @bdjben, @liaoandi, and @thewilloftheshadow.
- PDF/tools: use ClawPDF for PDF extraction and surface MCP structured content in agent tool results. (#87670)
- iOS: refresh the dev app with Pro Command, Chat, Agents, Settings, hosted push relay defaults, and realtime Talk playback wired to gateway sessions, diagnostics, chat, and realtime Talk. (#87367, #88096, #88105) Thanks @Solvely-Colin and @ngutman.
- Docs: clarify Codex computer-use setup, paste-token stdin auth setup, macOS gateway sleep troubleshooting, native Codex hook relay recovery, container model auth, install deployment cards, device-token admin gating, CLI setup flow compatibility, Notte cloud browser CDP setup, and backport targets. (#87313, #63050, #87685) Thanks @bdjben, @liaoandi, and @thewilloftheshadow.
- PDF/tools: use ClawPDF for PDF extraction, support encrypted PDF extraction, and surface MCP structured content in agent tool results. (#87670, #87751)
- Providers: add Claude Opus 4.8 support, Fal Krea image model schemas, NVIDIA featured model catalogs, MiniMax streaming music responses, and provider-backed voice model catalogs. (#87845, #87890, #80775, #84764, #87794) Thanks @eleqtrizit and @vincentkoc.
- Codex/GitHub: add the GitHub Copilot agent runtime and the Codex Supervisor plugin package.
- Plugins: externalize GitHub Copilot and Tokenjuice as official install-on-demand plugins with npm and ClawHub publish metadata.
- Workboard: add agent coordination tools for tracking and handing off active agent work.
- Discord: show commentary in progress drafts so live Discord runs expose useful in-progress context. (#85200)
- Plugin SDK: add a reply payload sending hook for plugins that need to deliver channel-owned replies and flatten package types for SDK declarations. (#82823, #87165) Thanks @piersonr and @RomneyDa.
- Policy: add policy comparison, ingress-channel conformance, and sandbox-posture conformance checks. (#85572, #85744, #86768)
### Fixes
- Agents: fall back to local config pruning when the optional `agents delete` Gateway probe cannot authenticate, so offline installs can still delete agents without removing shared workspaces.
- Tighten phone-control mutation authorization [AI]. (#87150) Thanks @pgondhi987.
- Clarify directive persistence authorization policy [AI]. (#86369) Thanks @pgondhi987.
- Agents/Codex: keep spawned agent cwd/workspace state separated, keep hook context prompt-local, release session locks on timeout abort, avoid session event queue self-wait, preserve shared app-server state across startup or helper failures, keep native hook relay alive across restarts, route workspace memory through tools, resolve Codex runtime models first, report quarantined dynamic tools, format `skills` command output, and bound compaction/steering retries. (#87218, #86875, #86123, #87399, #87375, #87383, #87400) Thanks @mbelinky, @Alix-007, @luoyanglang, @yetval, and @sjf.
- Codex Supervisor: keep real-home app-server MCP session listing on the loaded/state-DB path, bound stored history scans, and close WebSocket probes cleanly.
- Channels: thread canonical session keys into outbound hooks, preserve Matrix room-id case, keep fallback tool warnings mention-inert, retain delivered Slack final replies during late cleanup, continue iMessage polling after denied reactions, suppress duplicate native exec approvals, preserve Telegram SecretRef prompt config, suppress Discord recovered tool warnings, and block untrusted Teams service URLs. (#73706, #75670, #87366, #87451, #87334) Thanks @zeroaltitude, @lukeboyett, @xiaotian, and @eleqtrizit.
- CLI/auth/doctor/providers: reject malformed numeric/timeout/subcommand-version inputs, wait for respawn child shutdown, bound Codex and GitHub Copilot OAuth/token requests, warm provider auth off the main thread, honor Codex response timeouts, bound local service startup, resolve GPT-5.5 without cached catalog, migrate legacy memory auto-provider config, rewrite non-canonical `api_key` auth profiles, and make doctor restart follow-ups actionable. (#87398, #86281, #87361) Thanks @Patrick-Erichsen, @samzong, @giodl73-repo, and @alkor2000.
- Gateway/security/session state: expire browser tokens after auth rotation, scope assistant idempotency dedupe, drain probe client closes, avoid stale restart continuation reuse, preserve retry-after fallbacks, bound webchat image and artifact transcript scans, include seconds in inbound metadata timestamps, and evict current plugin-state namespaces at row caps.
- Config/parsing/network: reject partial numeric parsing, parse provider/Discord retry headers and dates strictly, honor IPv6 and bare IPv6 `no_proxy` entries, canonicalize secret target array indexes, and reject malformed media content lengths, inspected TCP ports, marketplace content lengths, cron epochs, and sandbox stat fields.
- Providers/agents: preserve seeded Anthropic signatures, concatenate signature-delta chunks, preserve DeepSeek `reasoning_content` replay across tier suffixes, apply OpenRouter strict9 ids to Mistral routes, promote Ollama plain-text tool calls, and recover empty preflight compaction. (#87593)
- Agents/Codex: keep spawned agent cwd/workspace state separated, forward ACP spawn attachments, keep hook context prompt-local, release session locks on timeout abort and runtime teardown without deleting live OpenClaw-owned locks during cleanup, avoid session event queue self-wait, clean up exec abort listeners, stream assistant deltas incrementally, recover raw missing-thread compaction failures, preserve rotated compaction session identity, keep compaction-timeout snapshots continuable, preserve shared app-server state across startup or helper failures, keep native hook relay alive across restarts and prune stale bridge files, close native hook relay replacement races, keep Claude live tool progress visible for watchdog recovery, suppress abandoned requester completion handoff, route workspace memory through tools, resolve Codex runtime models first, report quarantined dynamic tools, format `skills` command output, bind node auto-review to prepared plans, retry Claude CLI transcript probes, and bound compaction/steering retries. (#87218, #86875, #86123, #88129, #87399, #87375, #72574, #87383, #87400, #83022, #87671, #87738, #87747, #87706, #87546, #87541, #81048) Thanks @mbelinky, @Alix-007, @luoyanglang, @yetval, @sjf, @joshavant, @benjamin1492, @c19354837, @fuller-stack-dev, @pfrederiksen, and @dodge1218.
- Codex Supervisor: keep real-home app-server MCP session listing on the loaded state path, bound stored history scans, and close WebSocket probes cleanly.
- Channels: thread canonical session keys into outbound hooks, preserve Matrix room-id case, keep fallback tool warnings mention-inert, retain delivered Slack final replies during late cleanup, continue iMessage polling after denied reactions, suppress duplicate native exec approvals, resolve Gateway message actions against the active runtime config, preserve Telegram SecretRef prompt config and polling keepalives, preserve WhatsApp profile auth roots, QR display, document filenames, and plugin hook config, suppress Discord recovered tool warnings, preserve the Discord voice outbound helper, cap Discord/Signal/Zalo channel request and container timeouts, and block untrusted Teams service URLs while keeping TeamsSDK patterns aligned. (#73706, #75670, #87366, #87451, #87465, #87334, #84535, #76262, #83304, #82492, #87581, #77114, #86426, #85529, #87160) Thanks @zeroaltitude, @lukeboyett, @jarvis-mns1, @xiaotian, @funmerlin, @joshavant, @eleqtrizit, @heyitsaamir, @amittell, @lidge-jun, @liorb-mountapps, @masatohoshino, @bladin, and @giodl73-repo.
- CLI/auth/doctor/providers: reject malformed numeric/timeout/subcommand-version inputs, ignore workspace dotenv provider credentials, wait for respawn child shutdown, bound heartbeat defaults plus Codex, GitHub Copilot, OpenAI, Anthropic, Google, Feishu, LM Studio, MiniMax, Xiaomi TTS, and local-provider OAuth/token/model requests, harden Codex auth probes, label auth health by agent, preserve explicit agentRuntime pins during Codex model migration, warm provider auth off the main thread, honor Codex response timeouts, stop migrating current Claude Haiku 4.5 profiles to Sonnet, bound local service startup, resolve GPT-5.5 without cached catalog, migrate legacy memory auto-provider config, rewrite non-canonical `api_key` auth profiles, and make doctor restart follow-ups actionable. (#87398, #86281, #87361, #88133, #83655, #87559, #87719, #88088, #85924, #84362) Thanks @Patrick-Erichsen, @samzong, @giodl73-repo, @alkor2000, @mmaps, @nxmxbbd, and @vincentkoc.
- Gateway/security/session state: expire browser tokens after auth rotation, scope assistant idempotency dedupe, drain probe client closes, avoid stale restart continuation reuse, preserve retry-after fallbacks and stale rate-limit cooldown probes, bound webchat image and artifact transcript scans, include seconds in inbound metadata timestamps, clear completed session active runs, clear stale chat stream buffers, and evict current plugin-state namespaces at row caps. (#87810, #87833, #75089) Thanks @joshavant and @litang9.
- Config/parsing/network: reject partial numeric parsing, parse provider/Discord retry headers and dates strictly, honor IPv6 and bare IPv6 `no_proxy` entries, preserve empty plugin allowlists, canonicalize secret target array indexes, and reject malformed media content lengths, inspected TCP ports, marketplace content lengths, cron epochs, sandbox stat fields, unsafe duration values, empty config path segments, noncanonical schema array refs, unsafe Telegram callback pages, and invalid Teams attachment-fetch DNS targets. (#87883) Thanks @zhangguiping-xydt.
- Browser/input hardening: reject invalid tab indexes, excessive viewport resizes, explicit zero CDP ports, malformed geolocation options, unsafe screenshot or permission-grant timeouts, loose response-body limits, invalid cookie expiries, and non-finite Browser tool delays/timeouts.
- Cron/automation: retry recurring jobs after transient model rate limits before waiting for the next scheduled slot, and preflight model fallbacks before skipping scheduled work. (#82887) Thanks @chen-zhang-cs-code.
- Auto-reply/directives: respect provider and relayed channel metadata during directive persistence so channel-originated decisions keep their intended context. (#87683)
- WhatsApp: resolve the auth directory from the active profile so profile-scoped WhatsApp installs do not drift to the wrong credential root. (#82492) Thanks @lidge-jun.
- Gateway/session state: clear completed session active runs, avoid cold-loading providers for MCP inventory, cache single-session child indexes, cap handshake timers, and bound preauth, auth-guard, media, transcript, readiness, and port options.
- Channels/replies: preserve channel-owned progress callbacks when verbose output is off, keep group-room progress suppression intact, prefer external session delivery context, escape Discord component id delimiters, force final TUI chat repaints, show Slack reasoning previews, and normalize Discord/Matrix/Mattermost channel numeric options. (#87476, #87423)
- Agents/tool args: harden smart-quoted argument repair for edit arrays and exact escaped arguments so model-produced tool calls recover without corrupting valid input. (#86611) Thanks @ferminquant.
- Providers/agents: preserve seeded Anthropic signatures, preserve signed thinking payloads, concatenate signature-delta chunks, preserve DeepSeek `reasoning_content` replay across tier suffixes, apply OpenRouter strict9 ids to Mistral routes, promote Ollama plain-text tool calls, load NVIDIA featured model catalogs, stream MiniMax music generation responses, and recover empty preflight compaction. (#87593, #87493, #80775, #84764) Thanks @Pluviobyte and @eleqtrizit.
- Media/images: skip CLI image cache refs when resolving generated images, allow trusted generated HTML attachments, and bound generated video downloads so stale refs and slow providers fail cleanly. (#87523, #87982)
- File transfer: handle late tar stdin pipe errors after archive validation or unpacking has already settled.
- Performance: trust install-record caches between reloads, prefer native JSON parsing, reuse unchanged tool-search catalogs, skip unchanged store serialization, add precomputed session patch writers, reduce store clone allocations, cache manifest model catalog rows and auto-enabled plugin config, and slim current metadata identity caches.
- Docker/release/QA: package runtime workspace templates, stream cross-OS served artifacts, preserve sparse Crabbox run artifacts, bound OpenClaw instance logs, plugin gauntlet relay logs, MCP channel buffers, kitchen-sink scans, agent-turn assertions, and release scenario logs, and keep release/google live guards current.
- Performance: trust install-record caches between reloads, prefer native JSON parsing, reuse unchanged tool-search catalogs, reuse gateway session and plugin metadata paths, skip unchanged store serialization, patch single-entry session writes, add precomputed session patch writers, reduce store clone allocations, cache manifest model catalog rows and auto-enabled plugin config, avoid full session snapshots for entry reads, defer configured Slack full startup, prefer bundled plugin dist entries, and slim current metadata identity caches. (#87760)
- Docker/release/QA: package runtime workspace templates, stream cross-OS served artifacts, preserve sparse Crabbox run artifacts, isolate npm plugin installs per package, reject incompatible package plugin API installs, drop the leftover root Sharp dependency from package manifests after the Rastermill migration, bound OpenClaw instance logs, plugin gauntlet relay logs, MCP channel buffers, kitchen-sink scans, agent-turn assertions, QA-Lab credential broker calls, QA Matrix substrate requests, and release scenario logs, and keep release/google live guards current. (#87647, #87477) Thanks @rohitjavvadi and @vincentkoc.
- Release/CI: bound manual git fetches, ClawHub verifier responses, ClawHub owner metadata, dependency-guard error bodies, Parallels limits, startup/test/memory budget parsing, and diffs viewer build warnings so release lanes fail with useful proof instead of hanging. (#87839)
## 2026.5.27
@@ -573,6 +760,7 @@ Docs: https://docs.openclaw.ai
- Gateway/sessions: allow shared-secret bearer callers to read and stream session history without an explicit scope header. (#81815) Thanks @medns.
- Agents/embedded runner: classify HTML auth provider responses as `auth_html` and return a re-authentication hint instead of the CDN-blocked copy that `upstream_html` returns. Cloudflare Access login pages, nginx basic-auth challenges, and gateway login walls all produce HTML auth bodies that were previously misdiagnosed as transient CDN blocks. (#79900) Thanks @martingarramon.
- TUI/streaming watchdog: dismiss the `This response is taking longer than expected` notice as soon as a chat event for the same run arrives, so the message no longer sits next to the recovered response when the run was only briefly silent. Refs #67052, #69081 (closed), prior attempt #69026. Thanks @jpruit20 and @romneyda.
- Agents/auth profiles: replace the bare `No available auth profile for <provider> (all in cooldown or unavailable)` TUI error with plain-language copy that explains what happened in user terms (sign-in expired, provider asking us to slow down, billing issue on the account, etc.) and suggests the matching `openclaw models auth login --provider <provider>` recovery command for sign-in and billing causes, while falling back to the underlying provider error for cases without a clear recovery path. Thanks @romneyda.
- Agents/Pi: tolerate OpenClaw-owned transcript writes while embedded prompts are released for model I/O, keeping long-running Feishu, Slack, Telegram, and cron turns from failing with false session-takeover errors. Fixes #84059. (#84250) Thanks @tianxiaochannel-oss88.
## 2026.5.20

View File

@@ -9,18 +9,18 @@
# Build stages use full bookworm; the runtime image is always bookworm-slim.
ARG OPENCLAW_EXTENSIONS=""
ARG OPENCLAW_BUNDLED_PLUGIN_DIR=extensions
ARG OPENCLAW_NODE_BOOKWORM_IMAGE="node:24-bookworm@sha256:3a09aa6354567619221ef6c45a5051b671f953f0a1924d1f819ffb236e520e6b"
ARG OPENCLAW_NODE_BOOKWORM_SLIM_IMAGE="node:24-bookworm-slim@sha256:e8e2e91b1378f83c5b2dd15f0247f34110e2fe895f6ca7719dbb780f929368eb"
ARG OPENCLAW_NODE_BOOKWORM_SLIM_DIGEST="sha256:e8e2e91b1378f83c5b2dd15f0247f34110e2fe895f6ca7719dbb780f929368eb"
ARG OPENCLAW_NODE_BOOKWORM_IMAGE="docker.io/library/node:24-bookworm@sha256:8530f76a96d88820d288761f022e318970dda93d01536919fbc16076b7983e63"
ARG OPENCLAW_NODE_BOOKWORM_SLIM_IMAGE="docker.io/library/node:24-bookworm-slim@sha256:242549cd46785b480c832479a730f4f2a20865d61ea2e404fdb2a5c3d3b73ecf"
ARG OPENCLAW_NODE_BOOKWORM_SLIM_DIGEST="sha256:242549cd46785b480c832479a730f4f2a20865d61ea2e404fdb2a5c3d3b73ecf"
# Keep in sync with .github/actions/setup-node-env/action.yml bun-version.
# To update: docker buildx imagetools inspect oven/bun:<version> and use the manifest-list digest.
ARG OPENCLAW_BUN_IMAGE="oven/bun:1.3.13@sha256:87416c977a612a204eb54ab9f3927023c2a3c971f4f345a01da08ea6262ae30e"
# To update: docker buildx imagetools inspect docker.io/oven/bun:<version> and use the manifest-list digest.
ARG OPENCLAW_BUN_IMAGE="docker.io/oven/bun:1.3.13@sha256:87416c977a612a204eb54ab9f3927023c2a3c971f4f345a01da08ea6262ae30e"
# Base images are pinned to SHA256 digests for reproducible builds.
# Dependabot refreshes these blessed digests; release builds consume the
# reviewed base snapshot instead of mutating distro state on every build.
# To update, run: docker buildx imagetools inspect node:24-bookworm and
# node:24-bookworm-slim (or podman) and replace the digests below with the
# To update, run: docker buildx imagetools inspect docker.io/library/node:24-bookworm and
# docker.io/library/node:24-bookworm-slim (or podman) and replace the digests below with the
# current multi-arch manifest list entries.
FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS workspace-deps

View File

@@ -30,7 +30,8 @@ Supported channels include: WhatsApp, Telegram, Slack, Discord, Google Chat, Sig
New install? Start here: [Getting started](https://docs.openclaw.ai/start/getting-started)
Preferred setup: run `openclaw onboard` in your terminal.
OpenClaw Onboard guides you step by step through setting up the gateway, workspace, channels, and skills. It is the recommended CLI setup path and works on **macOS, Linux, and Windows (via WSL2; strongly recommended)**.
OpenClaw Onboard guides you step by step through setting up the gateway, workspace, channels, and skills. It is the recommended CLI setup path and works on **macOS, Linux, and Windows**.
Windows desktop users can start with the native [Windows Hub](https://docs.openclaw.ai/platforms/windows) companion app for setup, tray status, chat, node mode, and local MCP mode.
Works with npm, pnpm, or bun.
## Sponsors
@@ -164,7 +165,7 @@ Run `openclaw doctor` to surface risky/misconfigured DM policies.
- **[Voice Wake](https://docs.openclaw.ai/nodes/voicewake) + [Talk Mode](https://docs.openclaw.ai/nodes/talk)** — wake words on macOS/iOS and continuous voice on Android (ElevenLabs + system TTS fallback).
- **[Live Canvas](https://docs.openclaw.ai/platforms/mac/canvas)** — agent-driven visual workspace with [A2UI](https://docs.openclaw.ai/platforms/mac/canvas#canvas-a2ui).
- **[First-class tools](https://docs.openclaw.ai/tools)** — browser, canvas, nodes, cron, sessions, and Discord/Slack actions.
- **[Companion apps](https://docs.openclaw.ai/platforms/macos)** — macOS menu bar app + iOS/Android [nodes](https://docs.openclaw.ai/nodes).
- **[Companion apps](https://docs.openclaw.ai/platforms)** — Windows Hub, macOS menu bar app, and iOS/Android [nodes](https://docs.openclaw.ai/nodes).
- **[Onboarding](https://docs.openclaw.ai/start/wizard) + [skills](https://docs.openclaw.ai/tools/skills)** — onboarding-driven setup with bundled/managed/workspace skills.
## Security model (important)
@@ -185,7 +186,7 @@ Run `openclaw doctor` to surface risky/misconfigured DM policies.
- New here: [Getting started](https://docs.openclaw.ai/start/getting-started), [Onboarding](https://docs.openclaw.ai/start/wizard), [Updating](https://docs.openclaw.ai/install/updating)
- Channel setup: [Channels index](https://docs.openclaw.ai/channels), [WhatsApp](https://docs.openclaw.ai/channels/whatsapp), [Telegram](https://docs.openclaw.ai/channels/telegram), [Discord](https://docs.openclaw.ai/channels/discord), [Slack](https://docs.openclaw.ai/channels/slack)
- Apps + nodes: [macOS](https://docs.openclaw.ai/platforms/macos), [iOS](https://docs.openclaw.ai/platforms/ios), [Android](https://docs.openclaw.ai/platforms/android), [Nodes](https://docs.openclaw.ai/nodes)
- Apps + nodes: [Windows Hub](https://docs.openclaw.ai/platforms/windows), [macOS](https://docs.openclaw.ai/platforms/macos), [iOS](https://docs.openclaw.ai/platforms/ios), [Android](https://docs.openclaw.ai/platforms/android), [Nodes](https://docs.openclaw.ai/nodes)
- Config + security: [Configuration](https://docs.openclaw.ai/gateway/configuration), [Security](https://docs.openclaw.ai/gateway/security), [Exposure runbook](https://docs.openclaw.ai/gateway/security/exposure-runbook), [Sandboxing](https://docs.openclaw.ai/gateway/sandboxing)
- Remote + web: [Gateway](https://docs.openclaw.ai/gateway), [Remote access](https://docs.openclaw.ai/gateway/remote), [Tailscale](https://docs.openclaw.ai/gateway/tailscale), [Web surfaces](https://docs.openclaw.ai/web)
- Tools + automation: [Tools](https://docs.openclaw.ai/tools), [Skills](https://docs.openclaw.ai/tools/skills), [Cron jobs](https://docs.openclaw.ai/automation/cron-jobs), [Webhooks](https://docs.openclaw.ai/automation/webhook), [Gmail Pub/Sub](https://docs.openclaw.ai/automation/gmail-pubsub)

View File

@@ -2,6 +2,197 @@
<rss xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" version="2.0">
<channel>
<title>OpenClaw</title>
<item>
<title>2026.6.1</title>
<pubDate>Wed, 03 Jun 2026 21:26:22 +0000</pubDate>
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
<sparkle:version>2026060190</sparkle:version>
<sparkle:shortVersionString>2026.6.1</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[<h2>OpenClaw 2026.6.1</h2>
<h3>Highlights</h3>
<ul>
<li>Agents and CLI-backed runtimes recover more cleanly from interrupted tool calls, stale session bindings, compaction handoffs, and media delivery retries. (#88129, #88136, #88141, #88162, #88182)</li>
<li>Channels and mobile delivery are steadier across Telegram, WhatsApp, iMessage, Slack, Discord, Microsoft Teams, Google Chat, Google Meet, and iOS realtime Talk. (#88096, #88105, #88183, #88231)</li>
<li>Provider and plugin requests now bound more timers, retries, OAuth/device-code lifetimes, media downloads, local service probes, and generated-content polling paths before they can hang a run.</li>
<li>Skills, session metadata, gateway runtime state, plugin metadata, memory watchers, and store writes do less repeated work on hot paths while keeping config, dispatch, and Linux file-watch behavior stable. (#89185, #89188, #85351) Thanks @RomneyDa and @NianJiuZst.</li>
<li>Skills and plugin loading now handle stale disabled snapshots and loader failures more clearly, so channel turns avoid disabled SecretRefs and operators get better recovery guidance. (#79072, #79173) Thanks @zeus1959.</li>
<li>Workboard, SecretRef plugin manifests, hosted iOS push relay, and external Copilot/Tokenjuice packaging add broader orchestration, integration, and plugin delivery surfaces. (#82326, #87469, #87796, #88107, #88117)</li>
<li>Skill Workshop now has a fuller Control UI flow with proposal lists, today actions, revision handoff, searchable file previews, review states, locale coverage, and reusable session routing.</li>
<li>Chat and Control UI startup paths keep sends alive through history loading, stream deltas incrementally, skip markdown work while streaming, keep drafts local while typing, clear the composer after sends, trace first-output latency, prioritize first connect, and expose calmer composer controls. (#88772, #88825, #88998, #89030, #89106) Thanks @vincentkoc and @sallyom.</li>
<li>Provider coverage and model metadata now include MiniMax M3, account OAuth endpoints, Google/Vertex catalog fixes, OpenRouter SQLite model caching, Copilot Claude 1M capabilities, Foundry reasoning alignment, and OpenAI response replay guards. (#88480, #88512, #88851, #88860)</li>
<li>iMessage monitor state, inbound queues, and plugin install ledgers moved toward SQLite-backed state so restarts and local monitors recover with less duplicate filesystem scanning. (#88794, #88797)</li>
<li>Release, CI, Docker, E2E, plugin install, and diagnostics lanes now cap more logs, response bodies, readiness probes, artifact checks, status polling, child workflow waits, docker package cleanup, quiet test stalls, and rollback snapshots so failures report bounded proof instead of stalling. (#88966) Thanks @RomneyDa.</li>
</ul>
<h3>Changes</h3>
<ul>
<li>Docs: add a dedicated Skill Workshop guide covering governed skill creation, reviewable proposals, CLI, Gateway, agent tool behavior, approval policy, support files, and recovery, and refresh the ClawHub showcase cards. (#88734) Thanks @shakkernerd and @vyctorbrzezowski.</li>
<li>Skills: let the <code>skill_workshop</code> agent tool apply, reject, and quarantine explicit proposals through the guarded review flow. Thanks @shakkernerd.</li>
<li>Skills: let proposals carry approved support files under standard skill folders, with scanner, hash, and rollback safeguards. Thanks @shakkernerd.</li>
<li>Skills: let pending proposals be revised in place with versioned, dated proposal frontmatter before approval. Thanks @shakkernerd.</li>
<li>Skills: add Skill Workshop with pending proposals, CLI/Gateway review actions, rollback metadata, and the <code>skill_workshop</code> agent tool. Thanks @shakkernerd.</li>
<li>Skill Workshop: add the Control UI navigation, styled dashboard, proposal today view, revision dialog, file preview modal, searchable preview files, reusable session handoff, and localized strings.</li>
<li>Plugins: externalize Tokenjuice as the official <code>@openclaw/tokenjuice</code> plugin with npm and ClawHub publish metadata.</li>
<li>Plugins: externalize the GitHub Copilot agent runtime as the official <code>@openclaw/copilot</code> plugin with npm and ClawHub publish metadata.</li>
<li>iOS: add hosted push relay defaults, realtime Talk playback, and a guarded WebSocket ping path for more reliable mobile sessions. (#88096, #88105, #88231)</li>
<li>iOS: support native iPad display layouts.</li>
<li>Workboard: add orchestration primitives and agent coordination tools for multi-agent planning and run tracking. (#87469)</li>
<li>Workboard: wire task-backed board runs and show task comments in the edit modal.</li>
<li>Code mode: add internal namespaces for scoped agent/global sessions and exact namespace tool dispatch. (#88043)</li>
<li>Code mode: add MCP API files and docs for code-mode integrations.</li>
<li>Control UI: add a Dreaming-tab agent selector and propagate the selected agent through Dreaming status, diary, and diary actions. (#78748) Thanks @stevenepalmer.</li>
<li>Control UI: add calmer chat composer controls, local draft typing state, and first-output latency instrumentation for active chat entry. (#88772, #88998) Thanks @vincentkoc.</li>
<li>Plugins: add a SecretRef provider integration manifest contract and extract shared LLM core packages for provider/plugin reuse. (#82326, #88117)</li>
<li>Plugins: persist the plugin install index in SQLite so installed package lookup survives reloads with less filesystem scanning. (#88794)</li>
<li>Providers: add MiniMax M3 model support. (#88860)</li>
<li>Doctor: add disk space health checks and stabilize post-upgrade JSON probes.</li>
<li>Channels: store inbound queues in SQLite and migrate iMessage monitor state to SQLite-backed tracking. (#88797)</li>
<li>Skills: add the core skills index and centralize skills runtime loading, status, filtering, and prompt formatting.</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Release/CI/E2E: fail early when Crabbox sparse-sync full checkouts do not have enough local disk, with guidance for moving the sync root.</li>
<li>Build: render independent CLI startup metadata help snapshots concurrently to cut cold build-all metadata time.</li>
<li>Plugins: stop timed-out package-boundary prep steps by process group so descendant TypeScript/helper processes do not survive local check cleanup.</li>
<li>Control UI: serve static assets asynchronously after safe-open checks so large UI files do not block Gateway request handling.</li>
<li>Scripts/UI: forward direct wrapper SIGHUP shutdown to child processes so terminal hangups do not leave wrapped dev commands running.</li>
<li>Gateway: return the post-expiration pending-work revision from node drains so reconnecting nodes do not observe stale queue revisions after expired items are pruned.</li>
<li>Release/CI/E2E: keep temporary full-sync checkouts alive while slow Crabbox leases boot, so sparse worktree runs do not lose their sync source before file-list generation.</li>
<li>Release/CI/E2E: normalize inherited Linux <code>C.UTF-8</code> locale settings before raw AWS macOS Crabbox bootstrap commands, avoiding macOS locale warnings during package-manager hydration.</li>
<li>Release/CI/E2E: keep gateway watch regression checks from copying large static plugin assets inside the measured idle window.</li>
<li>Update: keep core updates nonblocking when a missing external plugin repair download stalls, while still blocking installed active plugin payload smoke failures.</li>
<li>Agents/providers: keep streaming tool-call argument parsing record-shaped when providers emit valid non-object JSON such as <code>null</code> or arrays.</li>
<li>Release/CI/E2E: reset incremental log readers when watched log files rotate without shrinking, so same-size replacements do not hide new readiness or RPC lines.</li>
<li>Talk: preserve explicit <code>null</code> payloads on controller-created turn and output-audio lifecycle events.</li>
<li>Agents/TUI: keep local custom provider runs from loading plugin runtime and auth alias metadata when plugins are disabled.</li>
<li>Agents/TUI: restore in-flight TUI run switch-back behavior, keep no-policy native hook fallback available, guard vanished workspaces, and keep lightweight isolated subagents lightweight.</li>
<li>Agents/media: keep async image, music, and video generation starts from ending the Codex turn, so mixed requests can continue with summaries or other work while media renders in the background.</li>
<li>Agents/Codex: keep public OpenAI API-key profiles from being treated as native Codex app-server auth while preserving persisted Codex OAuth sessions.</li>
<li>Agents/Codex: stream Codex app-server final-answer partials to live reply previews, preserve ACP metadata in SQLite, prefer real tool results over synthetic repair output, prevent aborted app-server turn handles from lingering, migrate legacy OpenAI Codex <code>lastGood</code> auth state, and preserve workspace/session metadata through ACP runtime refactors. (#88405, #88724, #88730) Thanks @vincentkoc.</li>
<li>Control UI: keep collapsed tool cards labeled with the tool name and action instead of generic output text. Thanks @shakkernerd.</li>
<li>Agents/Codex: surface Skill Workshop guidance in Codex app-server prompts when <code>skill_workshop</code> is available. Thanks @shakkernerd.</li>
<li>Skill Workshop: restore and localize the Control UI board/today view switcher so review workflows keep their intended layout toggle across locales. Thanks @shakkernerd.</li>
<li>Agents/auth: write auth profiles atomically, dispatch auth failures by type, add force re-login recovery, preserve workspaces during state-only uninstall, and compact before oversized turns so recovery paths avoid partial state. (#89181) Thanks @RomneyDa.</li>
<li>Skills: skip disabled skill env overrides from stale persisted snapshots so disabled skill <code>apiKey</code> SecretRefs cannot abort embedded or channel turns. (#79072, #79173) Thanks @zeus1959.</li>
<li>Skill Workshop: render the Control UI tab from filtered navigation state and keep filtered fallback routing stable.</li>
<li>CLI: avoid live catalog validation during <code>openclaw agents add</code>, so adding a secondary agent no longer depends on provider catalog availability. (#76284, #88314) Thanks @zhangguiping-xydt.</li>
<li>CLI: keep <code>plugins list --json</code> on the snapshot-only path so plugin sweeps avoid loading the full runtime status graph.</li>
<li>CLI/desktop: bridge WSL clipboard operations through the shell, recognize manual-update launchd jobs, and keep machine-readable startup output parseable during progress setup. (#88764, #88689) Thanks @alexzhu0.</li>
<li>Plugins: make PixVerse external-plugin ClawHub metadata explicit and keep it out of bundled dist builds.</li>
<li>Plugins: clarify plugin loader failure guidance so missing or incompatible plugin packages point operators at the right repair path.</li>
<li>Plugins: preserve npm plugin roots after blocked installs, skip plugin-local <code>openclaw</code> peer symlinks during rollback snapshots, relink those peers after restore, isolate cached tool runtime siblings, and isolate web-provider factory failures so one bad plugin does not poison sibling runtime paths. (#77237, #88807)</li>
<li>Cron: keep SQLite cron migrations compatible with legacy run-log tables, archived job stores, diagnostic cron names, and legacy one-shot delete-after-run behavior. (#88285)</li>
<li>Cron: keep update delivery validation scoped, harden restart state, and retire MCP runtimes on isolated cron cleanup.</li>
<li>Memory: serialize QMD update/embed writes per store, reduce Linux watcher fan-out, retry transient FileProvider-backed reads, preserve phase signals on read errors, harden envelope metadata sanitization, reattach Linux native watchers when directories are recreated, and rewrite generated transcript paths on rollover so memory/search state survives concurrent gateway and CLI activity. (#66339, #85931, #89185, #89188, #85351) Thanks @openperf, @amittell, @RomneyDa, and @NianJiuZst.</li>
<li>Memory: keep vector-disabled FTS indexes from resolving embedding providers during sync and search.</li>
<li>Providers: bound generated media downloads from OpenAI, Runway, xAI, MiniMax, BytePlus, DashScope-compatible, FAL, OpenRouter, Google, Vydra, and Comfy providers.</li>
<li>Providers: resolve Google defaults to <code>google-generative-ai</code>, register Vertex static catalog rows, align Foundry reasoning metadata, skip DeepSeek V4 thinking params on Foundry fallback, use MiniMax account OAuth endpoints, preserve Copilot Claude 1M capabilities, suppress disabled Ollama reasoning output, forward Gemini stop sequences, strip Kimi-incompatible Anthropic cache markers, keep OpenAI stop-finished tool calls, and avoid replay ids when the Responses store is disabled. (#88480, #88512, #76612) Thanks @coder999999999, @BryanTegomoh, and @vliuyt.</li>
<li>Providers: cap GitHub Copilot OAuth request timeouts before creating abort signals.</li>
<li>Cron: retry recurring jobs after transient model rate limits before waiting for the next scheduled slot.</li>
<li>Agents/Codex: keep live session locks during cleanup, recover interrupted CLI tool transcripts, preserve Codex auth and compaction session identity, clear orphan tool state, cap app-server idle timers, and keep media completion delivery retryable. (#88129, #88136, #88141, #88162, #88182)</li>
<li>Chat/UI: show Gateway chat failures as visible assistant messages in the Control UI instead of only setting an invisible error state.</li>
<li>Channels: cap Telegram, Discord, WhatsApp, Signal, Feishu, Google Chat, Microsoft Teams, QQBot, Nostr, Zalo, Zalouser, and Nextcloud-style request/retry timers; preserve SMS approval reply routes; and retry WhatsApp QR login 408 timeouts. (#88183)</li>
<li>Security/config parsing: reject unsafe OAuth/token lifetimes, retry-after delays, inbound timestamps, response body sizes, command timeout config, sandbox observer token TTLs, and gateway WebSocket calls after close.</li>
<li>Providers/media: cap local service, model, usage, queue, generated media, TTS, music, workflow polling, and provider OAuth request timers across hosted and local providers.</li>
<li>Release/CI/E2E: bound release candidate reads, beta smoke REST calls, plugin npm verification commands, changelog restore, cross-OS process groups, kitchen-sink and bundled plugin readiness probes, secret-provider probes, Telegram credential timeouts, Control UI i18n and CLI startup metadata generation, Vitest routing, dependency guard admin approvals, child workflow failure detection, quiet Node test shard stalls, docker package cleanup, and mainline test flakes. (#88127, #88137, #88155, #88160, #88966) Thanks @RomneyDa.</li>
<li>Release/CI/E2E: keep Kitchen Sink live plugin MCP probes resolving source-checkout workspace packages and align the live gauntlet with current Kitchen Sink diagnostics.</li>
<li>Release/CI/E2E: run the secret-provider integration proof through the repo pnpm runner so native macOS and Windows validation use the hydrated package-manager shim.</li>
<li>Release/CI/E2E: run the Telegram desktop proof gateway through the repo pnpm runner so native macOS proof uses the hydrated package-manager shim.</li>
<li>Docs/CI: run Mintlify anchor checks through the repo pnpm runner so docs link validation works when pnpm is only available through the hydrated package-manager shim.</li>
<li>Agents: keep configured fallback model metadata typed so provider params, context-token caps, and media input limits do not break changed-gate typechecks.</li>
<li>Agents: accept hidden <code>sessions_send</code> body aliases before validation while keeping the model-facing <code>message</code> schema canonical. (#88229) Thanks @zhangguiping-xydt.</li>
<li>Chat/UI: preserve startup chat sends during history loading, unblock the initial Control UI chat send, stream chat deltas incrementally, skip markdown parsing while streaming, keep drafts local while typing, guard composer rerenders, honor Chromium executable overrides, and detect system Chromium for E2E. (#88998) Thanks @vincentkoc.</li>
<li>Channels: stop schema-padded poll modifiers from turning normal <code>send</code> actions into invalid poll sends. (#89601) Thanks @codezz.</li>
<li>Channels: preserve long Feishu streaming replies, send visible fallbacks when accepted Feishu turns produce no final reply, tolerate iMessage self-chat timestamp skew, preserve colon-prefixed slash commands in mention parsing, decode Nostr <code>npub</code> allowlists correctly, and suppress raw provider errors during channel delivery. (#87896)</li>
<li>Config/status/doctor: skip unresolved shell references in state-dir dotenv files, resolve gateway auth secrets during deep status audits, respect explicit PI runtime policy, report runtime tool-schema errors, and keep post-upgrade JSON stable. (#88288)</li>
<li>Gateway/session state: list commands from the Gateway plugin registry, harden MCP loopback tool schemas, hide phantom agent-store rows from <code>sessions.list</code>, make task persistence failures explicit, and carry session UUIDs on interactive dispatch events.</li>
<li>Gateway/plugins: narrow plugin lookup memoization to the stable plugin/runtime inputs, avoiding repeated lookup work without mixing disabled or filtered plugin state.</li>
<li>OpenAI/TTS: handle speed directives for OpenAI TTS voices. (#74089)</li>
<li>CI/Crabbox: keep default runner capacity on the Azure credit-backed on-demand D4 lane with the Azure SSH port and a Git-independent full check job, so broad validation avoids low-priority spot quota stalls, hydrate port mismatches, non-Git hydrated workspaces, and stale AWS region hints.</li>
<li>CI/Crabbox: route Crabbox wrapper and Testbox workflow edits to their regression tests so changed-test gates do not silently run zero specs.</li>
<li>CI/workflows: route workflow sanity helper edits to their guard tests and cover composite-action input interpolation checks.</li>
<li>CI/tooling: route CI scope, dependency, changelog, and docs helper edits to their owner tests instead of silently skipping changed-test coverage.</li>
<li>CI/tooling: route package, release, and install helper edits to their owner tests so changed-test gates cover publish and installer script changes.</li>
<li>CI/tooling: route shared script library edits through their owner tests so lock, process, safety, and scan helpers do not skip changed-test coverage.</li>
<li>CI/tooling: skip expensive import-graph scans once a changed diff already requires broad fallback, keeping local changed-test planning fast while still collecting explicit owner tests.</li>
<li>CI/tooling: route script edits through conventional owner tests when matching <code>test/scripts</code> or <code>src/scripts</code> coverage already exists.</li>
<li>CI/tooling: honor option terminators in the memory FD repro script so follow-on arguments are not reparsed.</li>
<li>Release/CI/E2E: assert plugin lifecycle runtime inspect output instead of only capturing it.</li>
<li>Release/CI/E2E: make gateway-network prove the advertised health RPC and retry early WebSocket closes without burning full open timeouts.</li>
<li>Release/CI/E2E: honor option terminators across release, Parallels smoke, plugin gauntlet, and extension-memory scripts.</li>
<li>Release/CI/E2E: fail plugin gateway gauntlet QA chunks when the requested suite summary is missing or invalid.</li>
<li>Performance: prebuild QA runtime probes with generated plugin assets but without CLI startup metadata.</li>
<li>Performance: skip declaration bundling for runtime-only CLI startup and gateway watch build profiles.</li>
<li>Performance: reuse prepared provider handles, strict tool schemas, gateway runtime metadata, session maintenance config, plugin metadata, bundled skill allowlists, package-local plugin artifacts, single-entry store writes, and validated/serialized session prompt blobs.</li>
</ul>
<p><a href="https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md">View full changelog</a></p>
]]></description>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.6.1/OpenClaw-2026.6.1.zip" length="55062100" type="application/octet-stream" sparkle:edSignature="PVp8E2HBCvikB/0LCr36lFEyHPAzoFA2ScT6LW27FlzvP+m4r1AEuVN2UrtgWlpkGSsn4Eav0kPJe32u4ObNBw=="/>
</item>
<item>
<title>2026.5.28</title>
<pubDate>Sat, 30 May 2026 21:21:09 +0000</pubDate>
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
<sparkle:version>2026052890</sparkle:version>
<sparkle:shortVersionString>2026.5.28</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[<h2>OpenClaw 2026.5.28</h2>
<h3>Highlights</h3>
<ul>
<li>Agent and Codex runtime recovery is steadier: subagents keep cwd/workspace separation, hook context stays prompt-local, session locks release on timeout abort while live OpenClaw locks survive cleanup, stale restart continuations are avoided, and Codex app-server/helper failures no longer tear down shared runtime state. (#87218, #86875, #87409, #87399, #87375, #88129)</li>
<li>Channel delivery and session identity got safer across outbound plugin hooks, Matrix room ids, iMessage reactions/approvals, Slack final replies, Discord recovered tool warnings, runtime-config message actions, WhatsApp profile auth roots, Telegram polling, and Microsoft Teams service URL trust checks. (#73706, #75670, #87366, #87451, #87334, #84535, #82492, #83304, #87160)</li>
<li>Mobile and chat surfaces got a broader refresh: the iOS Pro UI, hosted push relay default, realtime Talk tab playback, Gateway chat transport, onboarding, Talk permissions, WebChat reconnect delivery, and session picker behavior now preserve more state across reconnects and empty searches. (#87367, #87531, #87682, #88096, #88105) Thanks @ngutman.</li>
<li>Browser, channel, and automation inputs are stricter: Browser tool timeouts, viewport/tab indices, Gateway ports, cron retry handling, Discord component ids, schema array refs, Telegram callback pages, and channel progress callbacks now reject malformed values earlier and preserve the intended delivery context. (#82887)</li>
<li>Provider, media, and document coverage expands with Claude Opus 4.8, Fal Krea image schemas, NVIDIA featured models, MiniMax streaming music responses, encrypted PDF extraction, voice model catalogs, GitHub Copilot agent runtime support, and a Codex Supervisor plugin path for delegated Codex workflows. (#87845, #87890, #80775, #84764, #87751, #87794)</li>
<li>CLI, auth, doctor, and provider paths fail faster and recover more clearly: malformed numeric/version options are rejected, workspace dotenv provider credentials are ignored, heartbeat defaults, OAuth/token lifetimes, and local service startup requests are bounded, agent auth health labels are clearer, legacy <code>api_key</code> auth profiles migrate to canonical form, and restart guidance is actionable. (#87398, #86281, #87361, #88133, #83655, #87559, #88088, #85924) Thanks @vincentkoc and @giodl73-repo.</li>
<li>Plugin and Gateway hot paths do less repeated work while preserving cache correctness for install records, config JSON parsing, tool search catalogs, session stores, manifest model rows, auto-enabled plugin config, browser tokens, viewer assets, and release-split external plugin packages. (#86699)</li>
<li>Release, QA, and E2E validation now bound more log, artifact, harness, and cross-OS waits so failing lanes produce proof instead of hanging or false-greening.</li>
</ul>
<h3>Changes</h3>
<ul>
<li>Status: show active subagent details in status output.</li>
<li>Diffs: split the default language pack and expand default Diffs language coverage while keeping the host floor aligned. (#87370, #87372) Thanks @RomneyDa.</li>
<li>ClawHub: add plugin display names plus skill verification and trust surfaces. (#87354, #86699) Thanks @thewilloftheshadow and @Patrick-Erichsen.</li>
<li>iOS: refresh the dev app with Pro Command, Chat, Agents, Settings, hosted push relay defaults, and realtime Talk playback wired to gateway sessions, diagnostics, chat, and realtime Talk. (#87367, #88096, #88105) Thanks @Solvely-Colin and @ngutman.</li>
<li>Docs: clarify Codex computer-use setup, paste-token stdin auth setup, macOS gateway sleep troubleshooting, native Codex hook relay recovery, container model auth, install deployment cards, device-token admin gating, CLI setup flow compatibility, Notte cloud browser CDP setup, and backport targets. (#87313, #63050, #87685) Thanks @bdjben, @liaoandi, and @thewilloftheshadow.</li>
<li>PDF/tools: use ClawPDF for PDF extraction, support encrypted PDF extraction, and surface MCP structured content in agent tool results. (#87670, #87751)</li>
<li>Providers: add Claude Opus 4.8 support, Fal Krea image model schemas, NVIDIA featured model catalogs, MiniMax streaming music responses, and provider-backed voice model catalogs. (#87845, #87890, #80775, #84764, #87794) Thanks @eleqtrizit and @vincentkoc.</li>
<li>Codex/GitHub: add the GitHub Copilot agent runtime and the Codex Supervisor plugin package.</li>
<li>Plugins: externalize GitHub Copilot and Tokenjuice as official install-on-demand plugins with npm and ClawHub publish metadata.</li>
<li>Workboard: add agent coordination tools for tracking and handing off active agent work.</li>
<li>Discord: show commentary in progress drafts so live Discord runs expose useful in-progress context. (#85200)</li>
<li>Plugin SDK: add a reply payload sending hook for plugins that need to deliver channel-owned replies and flatten package types for SDK declarations. (#82823, #87165) Thanks @RomneyDa.</li>
<li>Policy: add policy comparison, ingress-channel conformance, and sandbox-posture conformance checks. (#85572, #85744, #86768)</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Agents: fall back to local config pruning when the optional <code>agents delete</code> Gateway probe cannot authenticate, so offline installs can still delete agents without removing shared workspaces.</li>
<li>Tighten phone-control mutation authorization [AI]. (#87150) Thanks @pgondhi987.</li>
<li>Clarify directive persistence authorization policy [AI]. (#86369) Thanks @pgondhi987.</li>
<li>Agents/Codex: keep spawned agent cwd/workspace state separated, forward ACP spawn attachments, keep hook context prompt-local, release session locks on timeout abort and runtime teardown without deleting live OpenClaw-owned locks during cleanup, avoid session event queue self-wait, clean up exec abort listeners, stream assistant deltas incrementally, recover raw missing-thread compaction failures, preserve rotated compaction session identity, keep compaction-timeout snapshots continuable, preserve shared app-server state across startup or helper failures, keep native hook relay alive across restarts and prune stale bridge files, close native hook relay replacement races, keep Claude live tool progress visible for watchdog recovery, suppress abandoned requester completion handoff, route workspace memory through tools, resolve Codex runtime models first, report quarantined dynamic tools, format <code>skills</code> command output, bind node auto-review to prepared plans, retry Claude CLI transcript probes, and bound compaction/steering retries. (#87218, #86875, #86123, #88129, #87399, #87375, #72574, #87383, #87400, #83022, #87671, #87738, #87747, #87706, #87546, #87541, #81048) Thanks @mbelinky, @Alix-007, @luoyanglang, @yetval, @sjf, @joshavant, and @benjamin1492.</li>
<li>Codex Supervisor: keep real-home app-server MCP session listing on the loaded state path, bound stored history scans, and close WebSocket probes cleanly.</li>
<li>Channels: thread canonical session keys into outbound hooks, preserve Matrix room-id case, keep fallback tool warnings mention-inert, retain delivered Slack final replies during late cleanup, continue iMessage polling after denied reactions, suppress duplicate native exec approvals, resolve Gateway message actions against the active runtime config, preserve Telegram SecretRef prompt config and polling keepalives, preserve WhatsApp profile auth roots, QR display, document filenames, and plugin hook config, suppress Discord recovered tool warnings, preserve the Discord voice outbound helper, cap Discord/Signal/Zalo channel request and container timeouts, and block untrusted Teams service URLs while keeping TeamsSDK patterns aligned. (#73706, #75670, #87366, #87451, #87465, #87334, #84535, #76262, #83304, #82492, #87581, #77114, #86426, #85529, #87160) Thanks @zeroaltitude, @lukeboyett, @xiaotian, @funmerlin, @joshavant, @eleqtrizit, @heyitsaamir, @amittell, @liorb-mountapps, @masatohoshino, @bladin, and @giodl73-repo.</li>
<li>CLI/auth/doctor/providers: reject malformed numeric/timeout/subcommand-version inputs, ignore workspace dotenv provider credentials, wait for respawn child shutdown, bound heartbeat defaults plus Codex, GitHub Copilot, OpenAI, Anthropic, Google, Feishu, LM Studio, MiniMax, Xiaomi TTS, and local-provider OAuth/token/model requests, harden Codex auth probes, label auth health by agent, preserve explicit agentRuntime pins during Codex model migration, warm provider auth off the main thread, honor Codex response timeouts, stop migrating current Claude Haiku 4.5 profiles to Sonnet, bound local service startup, resolve GPT-5.5 without cached catalog, migrate legacy memory auto-provider config, rewrite non-canonical <code>api_key</code> auth profiles, and make doctor restart follow-ups actionable. (#87398, #86281, #87361, #88133, #83655, #87559, #87719, #88088, #85924, #84362) Thanks @Patrick-Erichsen, @samzong, @giodl73-repo, @alkor2000, @mmaps, @nxmxbbd, and @vincentkoc.</li>
<li>Gateway/security/session state: expire browser tokens after auth rotation, scope assistant idempotency dedupe, drain probe client closes, avoid stale restart continuation reuse, preserve retry-after fallbacks and stale rate-limit cooldown probes, bound webchat image and artifact transcript scans, include seconds in inbound metadata timestamps, clear completed session active runs, clear stale chat stream buffers, and evict current plugin-state namespaces at row caps. (#87810, #87833, #75089) Thanks @joshavant and @litang9.</li>
<li>Config/parsing/network: reject partial numeric parsing, parse provider/Discord retry headers and dates strictly, honor IPv6 and bare IPv6 <code>no_proxy</code> entries, preserve empty plugin allowlists, canonicalize secret target array indexes, and reject malformed media content lengths, inspected TCP ports, marketplace content lengths, cron epochs, sandbox stat fields, unsafe duration values, empty config path segments, noncanonical schema array refs, unsafe Telegram callback pages, and invalid Teams attachment-fetch DNS targets. (#87883) Thanks @zhangguiping-xydt.</li>
<li>Browser/input hardening: reject invalid tab indexes, excessive viewport resizes, explicit zero CDP ports, malformed geolocation options, unsafe screenshot or permission-grant timeouts, loose response-body limits, invalid cookie expiries, and non-finite Browser tool delays/timeouts.</li>
<li>Cron/automation: retry recurring jobs after transient model rate limits before waiting for the next scheduled slot, and preflight model fallbacks before skipping scheduled work. (#82887)</li>
<li>Auto-reply/directives: respect provider and relayed channel metadata during directive persistence so channel-originated decisions keep their intended context. (#87683)</li>
<li>WhatsApp: resolve the auth directory from the active profile so profile-scoped WhatsApp installs do not drift to the wrong credential root. (#82492)</li>
<li>Gateway/session state: clear completed session active runs, avoid cold-loading providers for MCP inventory, cache single-session child indexes, cap handshake timers, and bound preauth, auth-guard, media, transcript, readiness, and port options.</li>
<li>Channels/replies: preserve channel-owned progress callbacks when verbose output is off, keep group-room progress suppression intact, prefer external session delivery context, escape Discord component id delimiters, force final TUI chat repaints, show Slack reasoning previews, and normalize Discord/Matrix/Mattermost channel numeric options. (#87476, #87423)</li>
<li>Agents/tool args: harden smart-quoted argument repair for edit arrays and exact escaped arguments so model-produced tool calls recover without corrupting valid input. (#86611)</li>
<li>Providers/agents: preserve seeded Anthropic signatures, preserve signed thinking payloads, concatenate signature-delta chunks, preserve DeepSeek <code>reasoning_content</code> replay across tier suffixes, apply OpenRouter strict9 ids to Mistral routes, promote Ollama plain-text tool calls, load NVIDIA featured model catalogs, stream MiniMax music generation responses, and recover empty preflight compaction. (#87593, #87493, #80775, #84764) Thanks @eleqtrizit.</li>
<li>Media/images: skip CLI image cache refs when resolving generated images, allow trusted generated HTML attachments, and bound generated video downloads so stale refs and slow providers fail cleanly. (#87523, #87982)</li>
<li>File transfer: handle late tar stdin pipe errors after archive validation or unpacking has already settled.</li>
<li>Performance: trust install-record caches between reloads, prefer native JSON parsing, reuse unchanged tool-search catalogs, reuse gateway session and plugin metadata paths, skip unchanged store serialization, patch single-entry session writes, add precomputed session patch writers, reduce store clone allocations, cache manifest model catalog rows and auto-enabled plugin config, avoid full session snapshots for entry reads, defer configured Slack full startup, prefer bundled plugin dist entries, and slim current metadata identity caches. (#87760)</li>
<li>Docker/release/QA: package runtime workspace templates, stream cross-OS served artifacts, preserve sparse Crabbox run artifacts, isolate npm plugin installs per package, reject incompatible package plugin API installs, drop the leftover root Sharp dependency from package manifests after the Rastermill migration, bound OpenClaw instance logs, plugin gauntlet relay logs, MCP channel buffers, kitchen-sink scans, agent-turn assertions, QA-Lab credential broker calls, QA Matrix substrate requests, and release scenario logs, and keep release/google live guards current. (#87647, #87477) Thanks @rohitjavvadi and @vincentkoc.</li>
<li>Release/CI: bound manual git fetches, ClawHub verifier responses, ClawHub owner metadata, dependency-guard error bodies, Parallels limits, startup/test/memory budget parsing, and diffs viewer build warnings so release lanes fail with useful proof instead of hanging. (#87839)</li>
</ul>
<p><a href="https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md">View full changelog</a></p>
]]></description>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.5.28/OpenClaw-2026.5.28.zip" length="54750142" type="application/octet-stream" sparkle:edSignature="U4O55uMdPU+OqSx9QR1ApUJ8wg65wxTydzD7iyCn1GHtm1MBK9noEeiA/yoUKkqb/bx0hzi1gNhn+ye19RXnCA=="/>
</item>
<item>
<title>2026.5.27</title>
<pubDate>Thu, 28 May 2026 12:12:19 +0000</pubDate>
@@ -49,493 +240,5 @@
]]></description>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.5.27/OpenClaw-2026.5.27.zip" length="54488811" type="application/octet-stream" sparkle:edSignature="c5w2T1UO6vpPs70hyYH93cIyWEOd5sl5z2NkhU53E+XQBSd+jAr+xd0qf3KzWbeX2mfXYMQmnx+VMls3L22EDg=="/>
</item>
<item>
<title>2026.5.26</title>
<pubDate>Wed, 27 May 2026 12:24:26 +0000</pubDate>
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
<sparkle:version>2026052690</sparkle:version>
<sparkle:shortVersionString>2026.5.26</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[<h2>OpenClaw 2026.5.26</h2>
<h3>Highlights</h3>
<ul>
<li>Faster Gateway and replies: startup avoids repeated plugin, channel, session, usage-cost, warning, scheduled-service, and filesystem scans; visible replies separate user-facing sends from slower follow-up work; Gateway runtime/session caches churn less under load.</li>
<li>Transcripts are core: transcript-backed meeting summaries, source-provider chunks, cleaned user turns, media provenance, Codex mirrors, WebChat replies, and CLI/TUI replay now use one more reliable transcript path.</li>
<li>More channels are production-ready: Telegram keeps typing/progress context and forum topics, iMessage handles attachment roots, remote media staging, and duplicate local Messages sources, WhatsApp restores group/media behavior, Discord improves voice playback and model picking, and Signal/iMessage/WhatsApp get reaction approvals.</li>
<li>Better voice and Talk: realtime Talk runs can be inspected, steered, cancelled, or followed up from Web UI and Discord voice; wake-name handling is more tolerant without letting ambient speech trigger agents.</li>
<li>Safer content boundaries: Browser snapshot reads honor SSRF policy, system-event text cannot spoof nested prompt markers, fetched file text is wrapped as external content, ClickClack inbound sender allowlists run before agent dispatch, stale device tokens are rejected, and serialized tool-call text is scrubbed from replies.</li>
<li>Providers, Codex, and local models are steadier: named auth profiles, OpenAI sampling params, Codex app-server resume/timeout/usage-limit recovery, dynamic tool-schema guards, xAI usage-limit surfacing, Ollama top-p normalization, and local approval resolution reduce provider-specific dead ends.</li>
<li>More reliable install/update/release paths: Alpine installs, trusted runtime fallback roots, stable update channels, Docker/package timeouts, Windows Scheduled Tasks, Windows/macOS proof lanes, Testbox/Crabbox delegation, plugin publish checks, and macOS runner bootstraps all got hardened.</li>
<li>Better observability: Activity tab, gateway secret-prep traces, tool/model stream progress, explicit fast-mode status, systemd Gateway hygiene, OpenTelemetry LLM spans, release performance evidence, and richer telemetry signals make failures easier to inspect.</li>
</ul>
<h3>Changes</h3>
<ul>
<li>Transcripts: add core transcript capture and source-provider support for transcript-backed meeting summaries, including the renamed Transcripts docs, CLI surface, source-provider chunks, and cleaned user-turn persistence.</li>
<li>Auth: add named model login profiles and supported credential migration for Hermes, OpenCode, and Codex auth profiles, with explicit opt-out and non-interactive controls. (#85667) Thanks @fuller-stack-dev.</li>
<li>Diagnostics: trace gateway secret preparation, classify skill/tool usage, surface model stream progress, add OpenTelemetry LLM content spans, and expose alertable telemetry for blocked tools, failover, stale sessions, liveness, oversized payloads, and webhook ingress. (#83019, #80370, #86191)</li>
<li>Channels: add Signal reaction approvals, iMessage thumb approval reactions, and WhatsApp thumb approval reaction support so mobile approval flows work without textual <code>/approve</code> commands. (#85894, #85952, #85477)</li>
<li>Agents/API: forward OpenAI sampling params through the Gateway and expose estimated context-budget status for active agent runs. (#84094)</li>
<li>TUI/status: queue prompts submitted while an agent is busy and show explicit fast-mode state plus richer systemd Gateway hygiene in status output. (#86722, #87115, #86976)</li>
<li>Exec approvals: hide durable approval actions that are unavailable for the current prompt and keep approval runtime tokens local-only so stale prompts cannot offer misleading controls. (#86270, #86359)</li>
<li>Plugin SDK: add reaction approval helpers and keep diagnostic event root exports discoverable across function-name and alias-bound module graphs. (#86735, #87084)</li>
<li>Android/iOS: add the Android pair-new-gateway action and improve mobile Talk mode surfaces, including iOS realtime Talk mode and Android offline voice/gateway recovery. (#86798, #86355) Thanks @ngutman.</li>
<li>Performance: cache plugin metadata snapshots, package realpaths, stable gateway metadata, model cost indexes, channel resolution, usage-cost indexes, and session/auth hot-path facts so common Gateway and reply paths do less rediscovery. (#84649, #85843, #86517, #86678)</li>
<li>Voice: expose shared realtime turn-context tracking through the realtime voice SDK and reuse it for Discord speaker attribution and wake-name context recovery.</li>
<li>Voice: reuse shared realtime output activity tracking in Google Meet command and node audio bridges, including recent-output checks for local barge-in detection.</li>
<li>Voice: expose shared realtime output activity tracking through the realtime voice SDK and reuse it for Discord playback activity and barge-in decisions.</li>
<li>Voice: expose shared realtime consult question matching, speakable-result extraction, and alias-aware forced-consult coordination through the realtime voice SDK, then reuse it in Gateway Talk, Voice Call, and Discord voice paths.</li>
<li>Voice: share activation-name matching and consult-transcript screening through the realtime voice SDK so Discord, browser voice, and meeting surfaces can reuse one implementation.</li>
<li>Cron: default <code>cron.maxConcurrentRuns</code> to 8 so scheduled automations and their isolated agent turns can make progress in parallel without explicit configuration.</li>
<li>QA-Lab: add <code>qa coverage --match <query></code> so focused proof selection can discover matching scenarios from existing metadata before running live or remote lanes.</li>
<li>Discord/model picker: surface an alpha-bucket select (e.g. <code>AG (12) · HN (18) · OZ (5)</code>) when the provider list or a provider's model list exceeds 25 items, so configs with <code>provider/*</code> wildcards stay one click from the right page instead of paginating through prev/next; falls back to numeric chunks when every item shares the same first letter.</li>
<li>Control UI: add an ephemeral Activity tab for sanitized live tool activity summaries without persisting raw telemetry. Fixes #12831. Thanks @BunsDev.</li>
<li>Build: include <code>ui:build</code> in the <code>full</code> and <code>ciArtifacts</code> profiles of <code>scripts/build-all.mjs</code> so <code>pnpm build</code> always rebuilds <code>dist/control-ui</code> after <code>tsdown</code> cleans <code>dist</code>, removing the second-command requirement and the missing-asset failure mode for source/runtime installs and CI artifact uploads. (#85206)</li>
<li>iOS: improve Talk mode with direct realtime voice sessions, compact toolbar status, and responsive voice waveform feedback. (#86355) Thanks @ngutman.</li>
<li>Media: replace the Sharp image backend with Rastermill for metadata, resizing, EXIF orientation, and PNG alpha-preserving optimization so OpenClaw no longer installs Sharp or the WhatsApp Jimp fallback for image processing. (#86437)</li>
<li>Codex: update the bundled Codex CLI to 0.134.0 and keep native compaction disabled for budget-triggered app-server turns so OpenClaw owns the recovery boundary. (#86772)</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Memory/security: reject prompt-like text submitted through the explicit <code>memory_store</code> tool before embedding or storage, matching the existing auto-capture prompt-injection filter. (#87142)</li>
<li>Gateway/security: enable the default auth rate limiter for remote non-browser and HTTP gateway auth failures when <code>gateway.auth.rateLimit</code> is unset, while preserving the loopback exemption. (#87148)</li>
<li>Security/content boundaries: validate Browser snapshot tab URLs against SSRF policy before ChromeMCP or direct CDP reads, sanitize queued system-event text so untrusted plugin/channel labels cannot spoof nested prompt markers, wrap fetched file text and metadata as external content, apply ClickClack <code>allowFrom</code> sender allowlists before agent dispatch, reject RPCs from invalidated device-token clients during rotation, require staged sandbox media refs, and scrub serialized tool-call text from replies. (#78526, #87094, #87062, #83741, #70707, #86924) Thanks @zsxsoft, @ttzero25, and @mmaps.</li>
<li>Transcripts/user turns: persist CLI, WebChat, media, follow-up, hook, and Codex-mirror user turns to the admitted session target; keep cleaned transcript text, inline image routing, provenance metadata, replay hooks, and fallback paths idempotent when runtimes fail or restart.</li>
<li>TUI/status/onboarding/UI: queue busy TUI prompts instead of dropping them, preserve the configured default model during onboarding, show failed tool results as errors, show config-open failures in Control UI, keep status JSON plugin scans healthy, preserve xAI usage-limit errors locally, and expose explicit fast-mode/systemd state. (#86722, #87000, #85786, #87108, #87001, #86614, #87115, #86976)</li>
<li>Plugin commands/SDK: preserve plugin LLM command auth, bind native plugin command dispatch to the host agent's LLM auth, keep <code>onDiagnosticEvent</code> exports discoverable through <code>Function.name</code>, stabilize diagnostic event root aliases, correlate pathless read diagnostics, suppress transient runner failures in channel command paths, and repair local approval resolution. (#85936, #87084, #86977, #87069, #86771)</li>
<li>Codex/providers: keep WebChat delivery hints out of user prompts, avoid false queued-terminal idle timeouts, share the native hook relay registry, quarantine unsupported dynamic tool schemas, preserve Claude resumed-session system prompts, normalize greedy Ollama <code>top_p</code>, preserve per-agent thinking defaults for ingress runs, and avoid native compaction takeover on budget-triggered Codex turns. (#87096, #73950, #87049, #86689, #86772)</li>
<li>Gateway/perf/release: reuse startup-warning metadata and prepared auth stores, avoid cloning live-switch and lifecycle session caches on read paths, defer warning and scheduled-service fallback imports, trim Gateway session/startup/runtime CPU churn, skip duplicate turn session touches, stop chat timeout fallback cascades, drop stale subagent announce history, bound benchmark/watch/kitchen-sink teardown waits, bound macOS/package/onboarding/plugin smoke commands, bound install finalization probes, resolve Parallels npm-update commands from guest <code>PATH</code>, and bootstrap raw AWS macOS Node/pnpm commands through <code>/usr/bin/env</code>. (#86997)</li>
<li>Reply/perf: reduce visible reply delivery latency by preserving Telegram typing/progress context, lazy-loading slash-command startup metadata, avoiding hot-path model hydration, flag-gating Codex profiler timing, deferring context compaction maintenance, and tracking delivery timing. (#86989, #86990, #86991, #86992, #86993, #86994) Thanks @keshavbotagent.</li>
<li>Reply/source delivery: keep TUI, Control UI, media, TTS, transcript, and Codex source-reply finals live without duplicate terminal events or stale replay artifacts.</li>
<li>Agents/replay: repair legacy tool results before replay, preserve <code>sessions_spawn</code> transcript payloads, restore current guard checks, stage sandboxed workspace media, and keep duplicate transcripts tool display metadata from reappearing. (#82203, #86934, #87025) Thanks @martingarramon, @vincentkoc, and @joshavant.</li>
<li>Agents/sessions: handle active-fallback failures in <code>sessions_send</code> so fallback routing reports the real failure and does not leave callers with an ambiguous dropped send. (#86638)</li>
<li>Agents/hooks/subagents: enforce default hook agent allowlists, recover failed subagent lifecycle completions, and keep node task lifecycle cleanup from closing the Gateway listener. (#86101)</li>
<li>Codex: project newer OpenClaw chat history into resumed app-server threads and keep Codex turn timeouts inside the Codex runtime boundary so timeouts do not poison shared app-server clients or fall through to unrelated provider fallback. (#86677, #86476) Thanks @TurboTheTurtle and @pashpashpash.</li>
<li>Config/doctor/update: narrow profiled tool-section doctor repair, keep runtime-injected legacy web-search provider config out of user-authored config validation, and keep prerelease tags excluded from stable updater resolution. (#87030, #86818, #86559) Thanks @joshavant, @luoyanglang, and @stevenepalmer.</li>
<li>CLI/Windows: add a Windows-only stack-size respawn for stack-heavy startup paths, default CLI logs to local timestamps, and validate timeout/banner TTY state more strictly. (#87031, #85387) Thanks @giodl73-repo and @vincentkoc.</li>
<li>Locking/security: require owner identity proof before stale plugin lock removal, memoize session lock owner arguments, and avoid writing default exec approval stores unless policy state actually changed. (#86814, #86964) Thanks @Alix-007 and @vincentkoc.</li>
<li>Install/release: bound Docker package build, inventory, pack, and tarball preparation with process-group timeouts; pin shrinkwrap patch drift to the pnpm lock; harden macOS restart and dSYM packaging; and run release Docker/live timeout wrappers in the foreground so child processes cannot wedge gates.</li>
<li>Telegram/network: treat <code>ENETDOWN</code> as a transient pre-connect network failure so Telegram sends, gateway unhandled-rejection handling, and cron network retries follow the same recovery path as sibling network outages. (#86762) Thanks @TurboTheTurtle.</li>
<li>Telegram: preserve inbound text entities, overlapping DM replies, account topic cache sidecars, outbound reply context, targeted bot-command mentions, durable group retry targets, forum topic names, and native progress callbacks. (#83873, #85361, #85555, #85656, #85709, #86299, #86553) Thanks @SebTardif, @luoyanglang, and @neeravmakwana.</li>
<li>iMessage: read image attachments from local Messages attachment roots, dedupe duplicate local Messages-source accounts, seed direct DM history, fix image/group media attachment commands, advance catchup cursors after live handling, and keep slash-command acknowledgements in the source conversation. (#82642, #85475, #86569, #86705, #86706, #86770) Thanks @homer-byte, @TurboTheTurtle, @swang430, and @OmarShahine.</li>
<li>WhatsApp/QQ/Twitch/IRC/Slack: restore WhatsApp ack identity and group-drop warnings, make QQ Bot media respect <code>OPENCLAW_HOME</code>, serialize Twitch auth disconnects, store IRC channel routes canonically, and keep Slack downloaded files out of reply media. (#83833, #85309, #85777, #85794, #85906, #86318, #86697) Thanks @sliverp, @neeravmakwana, and @Kailigithub.</li>
<li>Discord/voice: improve voice playback and wake replies, bucket large model picker menus, merge media captions into one message, route metadata through configured proxies, restore numeric channel sends, suppress self-reply echoes, and tighten wake matching without breaking fuzzy wake phrases. (#80227, #86238, #86487, #86571, #86595, #86601)</li>
<li>Codex: preserve native web-search metadata, keep oversized native thread reuse, bridge CLI API-key auth into the app server, preserve sandbox bootstrap path style, recover context-window prompt errors, honor yolo approval policy, disable native thread personality, and route compaction through Codex auth. (#85378, #85542, #85891, #85909, #86408)</li>
<li>Agents/runtime: enforce session lock max-hold reclaim, release embedded-attempt locks on all exits, treat aborted subagent runs as terminal, avoid runtime model hydration on hot paths, disclose scoped session list counts, derive overflow budgets from provider errors, and keep fallback errors scoped to the active model candidate. (#70473, #85764, #86014, #86134, #86427, #86944) Thanks @openperf, @fuller-stack-dev, @zhangguiping-xydt, and @ferminquant.</li>
<li>Config/update/doctor: retry config recovery after failed backup restore, skip shell env fallback on Windows, exclude prerelease tags from the stable git channel, support deep config edits, warn instead of aborting on unreadable cron stores, prune stale bundled plugin paths, and avoid duplicate restart prompts when the Gateway is already healthy. (#85739, #85787, #86060, #86260, #86384, #86533) Thanks @liaoyl830.</li>
<li>Install/release: support Alpine CLI installs and runtime floors, prefer trusted startup argv runtime fallback roots, reject stale CLI node runtimes, avoid npm <code>min-release-age</code> installer failures, bound npm/package/Docker install phases, restore config parent ownership in Docker, seed Docker lockfile package tarballs before prune, make release/plugin prerelease checks fail closed instead of hanging or false-greening, and use host-visible Crabbox local work roots for Docker-backed proof. (#85491)</li>
<li>Windows daemon: keep Scheduled Task gateway launches running on battery power and avoid workgroup-machine prompts for a domain user during task installation. (#59299)</li>
<li>Security: avoid printing Gateway tokens in Docker, validate plugin model-pattern regexes safely, escape transcript metadata field names, harden session allowlist glob matching, audit Claude permission overrides under YOLO, and require explicit allow for ACP auto approvals. (#85849, #85934, #86046, #86557)</li>
<li>Media/images: replace Sharp with Rastermill, keep EXIF normalization best-effort, normalize HEIC/HEIF before image descriptions, route Codex image API keys through OpenAI, preserve image compression metadata, and auto-scale live tool result caps. (#85776, #86037, #86437, #86857, #86923)</li>
<li>Memory: prevent semantic vector indexes from silently degrading when embeddings are unavailable, stop doctor OOMs on large session stores, preserve sidecar hooks/artifacts, write fallback dream diaries, use CJK-aware dreaming dedupe, and avoid per-file watcher FD fan-out. (#80613, #82928, #85060, #85704, #85967, #86701) Thanks @brokemac79, @openperf, and @yaaboo-gif.</li>
<li>Agents/sessions: include visibility metadata on restricted <code>sessions_list</code> results so scoped counts are clearly reported without widening access or exposing hidden-session counts. (#86944) Thanks @ferminquant.</li>
<li>Gateway/DNS: validate wide-area discovery domains before deriving zone paths or writing zone files, so invalid <code>discovery.wideArea.domain</code> and <code>dns setup --domain</code> values fail with a DNS-name diagnostic instead of falling through to unrelated configuration errors. Thanks @mmaps.</li>
<li>Agents/BTW: route fallback side-question streams through the embedded stream resolver so Anthropic-compatible MiniMax requests use the same capped transport as normal chat. (#86312) Thanks @neeravmakwana.</li>
<li>Telegram: treat <code>/command@TargetBot</code> bot-command entities as explicit mentions for the addressed bot so <code>requireMention</code> groups no longer drop targeted commands or captions. Fixes #84462. (#86553) Thanks @luoyanglang.</li>
<li>CI: bound Docker/Bash E2E tarball npm installs with <code>OPENCLAW_E2E_NPM_INSTALL_TIMEOUT</code> so package, onboarding, plugin, and upgrade lanes fail instead of hanging on a stuck npm install.</li>
<li>CI: fail Parallels npm-update smoke jobs after the guest command timeout and cleanup backstop instead of only logging a timeout line.</li>
<li>CI: bound kitchen-sink RPC HTTP probes so stalled gateway readiness or response bodies fail and retry instead of wedging the walker.</li>
<li>CI: keep <code>OPENCLAW_TESTBOX=1 pnpm check:changed</code> delegating to Blacksmith Testbox through Crabbox without forwarding local Testbox or worker env into the remote command.</li>
<li>CI: send KILL after the TERM grace period for manual checkout fetch timeouts so stuck Testbox and workflow checkout retries cannot hang behind a wedged <code>git fetch</code>.</li>
<li>CI: send KILL after the TERM grace period for Bun global install smoke command timeouts so trapped <code>openclaw</code> child processes cannot wedge the scheduled install smoke.</li>
<li>iMessage: thread current channel/account inbound attachment roots into the image tool so iMessage-saved attachments under <code>~/Library/Messages/Attachments</code> (including the wildcard <code>/Users/*/Library/Messages/Attachments</code> root) are read through the existing inbound path policy instead of being rejected as <code>path-not-allowed</code>. Literal <code>localRoots</code> stays workspace-scoped. Fixes #30170. (#86569)</li>
<li>QQ Bot: respect <code>OPENCLAW_HOME</code> for outbound media path resolution so <code><qqmedia></code> sends no longer silently fail when <code>HOME</code> and <code>OPENCLAW_HOME</code> differ (Docker / multi-user hosts). Persisted QQ Bot data (sessions, known users, refs) stays anchored on the OS home for upgrade compatibility. Fixes #83562. Thanks @sliverp.</li>
<li>Update: report the primary malformed <code>openclaw.extensions</code> payload error without adding a duplicate missing-main diagnostic. (#86596) Thanks @ferminquant.</li>
<li>Control UI: keep host-local Markdown file paths inert while preserving app-relative links. (#86620) Thanks @BryanTegomoh.</li>
<li>Gateway: dampen repeated unauthenticated device-required probes per URL while preserving explicit-auth and paired recovery paths. (#86575) Thanks @ferminquant.</li>
<li>IRC: store inbound channel routes with the canonical <code>channel:#name</code> target and join transient channel sends before writing. (#85906) Thanks @Kailigithub.</li>
<li>Usage: surface unknown all-zero model pricing as missing cost entries instead of a confident <code>$0</code> total. (#85882) Thanks @MichaelZelbel.</li>
<li>Agents/Codex: honor yolo app-server approval policy only for the full <code>never</code> plus <code>danger-full-access</code> case. (#85909) Thanks @earlvanze.</li>
<li>Gateway/Gmail: clear Gmail watcher renewal intervals on re-entry so hot reloads do not leak lifecycle timers. (#82947) Thanks @SebTardif.</li>
<li>Logging: exit cleanly on broken stdout/stderr pipes without masking existing failure exit codes. (#80059) Thanks @pavelzak.</li>
<li>Gateway/security: escape transcript metadata field names while extracting oversized session line prefixes. (#85934) Thanks @SebTardif.</li>
<li>Plugins/security: validate manifest model pattern regexes with the safe-regex compiler so unsafe patterns are ignored before matching. (#86046) Thanks @SebTardif.</li>
<li>Discord: route gateway metadata REST lookups through the configured Discord proxy so proxied accounts do not fall back to direct <code>discord.com</code> connections before opening the WebSocket. Fixes #80227. Thanks @Clivilwalker.</li>
<li>Agents/media: hydrate current-turn image attachments from filename-derived MIME types so active vision can see generated or forwarded images whose source omitted an image content type. (#84812) Thanks @marchpure.</li>
<li>Agents/fs: point workspace-only scratch-path guidance at in-workspace temp directories while keeping host-root writes rejected by the tool guard. (#86501) Thanks @tianxiaochannel-oss88.</li>
<li>Agents/media: keep async cron media completions scoped to their run session while preserving direct delivery for stale generated-media success and failure notifications. (#86529) Thanks @ai-hpc.</li>
<li>Gateway: emit plugin <code>session_end</code>/<code>session_start</code> hooks when <code>agent.send</code> rotates or replaces a session id, keeping hook lifecycle state aligned with <code>sessions.changed</code> notifications. Fixes #83507. (#85875) Thanks @brokemac79.</li>
<li>OpenShell/SSH: reject malformed generated exec commands before sandbox/session setup so unresolved workflow placeholders fail fast instead of reaching the remote shell. Fixes #72373. Thanks @brokemac79.</li>
<li>Google: stop normalizing <code>gemini-3.1-flash-lite</code> to the retired preview endpoint and update Flash Lite alias guidance to the GA model id. Fixes #86151. (#86240) Thanks @SebTardif.</li>
<li>Installer: make Alpine apk installs cover Git, verify the Node runtime floor, try <code>nodejs-current</code>, and report Alpine version guidance when repositories only provide older Node packages.</li>
<li>Agents/status: prefer the active Claude CLI OAuth auth label over an unused Anthropic env API-key label for equivalent runtime aliases. Fixes #80184. (#86570) Thanks @brokemac79.</li>
<li>Agents/media: send direct fallback for generated media still missing after an active requester wake fails. (#85489) Thanks @fuller-stack-dev.</li>
<li>Agents: derive overflow compaction budgets from provider-reported and synthetic over-budget token counts so confirmed context overflows compact before retrying. (#70473) Thanks @fuller-stack-dev.</li>
<li>Agents/Codex: recover Codex context-window prompt errors through overflow compaction and surface reset guidance when recovery is exhausted. (#85542) Thanks @fuller-stack-dev.</li>
<li>Agents/Codex: allow Codex app-server runs to bootstrap from <code>CODEX_API_KEY</code> or <code>OPENAI_API_KEY</code> when no Codex auth profile is configured.</li>
<li>Agents/Codex: keep selected Codex runtime routing on OpenAI-Codex while preserving direct OpenAI API-key compaction fallback. (#86408) Thanks @funmerlin and @VACInc.</li>
<li>Agent transcript: include OpenClaw agent session logs when finding local transcript candidates.</li>
<li>Crabbox: bootstrap raw AWS macOS shell commands wrapped in absolute <code>time</code> paths so RSS probes can run Node and pnpm on fresh macOS runners.</li>
<li>Crabbox: bootstrap raw AWS macOS shell commands even when setup statements precede Node or pnpm usage.</li>
<li>TUI/local: skip unnecessary secret resolution, gateway model catalog loading, bootstrap, and skill scans in explicit local-model runs so startup reaches the model request faster.</li>
<li>Sessions/doctor: load large session stores without clone amplification during read-only doctor checks and reclaim stale <code>sessions.json.*.tmp</code> sidecars. Fixes #56827. Thanks @openperf.</li>
<li>Tests: clean successful plugin gateway gauntlet isolated temp roots while keeping an explicit preservation switch for failed/debug runs.</li>
<li>Plugins/perf: reuse derived plugin metadata snapshots for the lifetime of the process so reply-time skill setup no longer rescans plugin metadata on every turn.</li>
<li>Discord/OpenAI voice: keep wake-name master consults using the current speaker context after ignored ambient transcripts and shorten the default capture silence grace.</li>
<li>Doctor: skip redundant Gateway restart prompts when a recent supervisor restart leaves the Gateway healthy. Fixes #86518. (#86533) Thanks @liaoyl830.</li>
<li>Cron: restore suspended cron lanes to the configured/default concurrency instead of falling back to one after quota or circuit-breaker auto-resume.</li>
<li>Gateway: keep session-only Control UI tool-start mirrors flowing during diagnostic queue pressure instead of silently dropping non-terminal tool updates.</li>
<li>Agents/memory: return optional not-found context for missing date-only daily memory reads instead of logging benign first-run <code>ENOENT</code> failures. Fixes #82928. Thanks @galiniliev.</li>
<li>Discord: merge streamed text captions into following media block replies so captions and attachments send as one message. (#86487) Thanks @neeravmakwana.</li>
<li>Gateway: avoid sending duplicate tool-event frames to Control UI connections that are subscribed by both run and session.</li>
<li>Discord/OpenAI voice: accept broader edge-position fuzzy wake-name transcripts while keeping ambient speech gated.</li>
<li>Discord/OpenAI voice: accept longer leading wake-name mistranscripts such as "Open Club" for OpenClaw.</li>
<li>Agents/OpenAI-compatible: stop ModelStudio-compatible chat requests before sending system/tool-only payloads that have no usable user or assistant turn. (#86177) Thanks @TurboTheTurtle.</li>
<li>Gateway/plugins: reuse plugin package realpath checks while building installed plugin indexes so startup avoids repeated filesystem resolution work.</li>
<li>Kilo Gateway: send string <code>stop</code> sequences as arrays so Kilo accepts OpenAI-compatible chat completions. (#86461) Thanks @SebTardif.</li>
<li>Discord/OpenAI voice: accept leading fuzzy wake-name transcripts such as "Monty" or "Moti" for a Molty agent while keeping ambient speech gated.</li>
<li>Media understanding: convert HEIC and HEIF images to JPEG before image description providers run so iPhone photos work in direct and configured image-description flows. (#86037)</li>
<li>Agents: release embedded-attempt session locks from outer teardown so post-prompt exceptions cannot wedge later requests behind <code>SessionWriteLockTimeoutError</code>. Fixes #86014. Thanks @openperf.</li>
<li>Discord/OpenAI voice: rotate Realtime sessions at provider max duration without logging the expected session-expiry event as an error.</li>
<li>Sessions: skip metadata-only entries during QMD-slugified session lookup so one incomplete row does not block transcript hit resolution. (#86327) Thanks @abnershang.</li>
<li>Agents/media: derive bundled plugin local-media trust from plugin tool metadata instead of importing the full plugin registry on subscription paths. (#84409) Thanks @samzong.</li>
<li>Image tool: keep config-backed custom-provider API keys usable for auto-discovered vision models, including deferred image-tool execution without env keys or auth profiles. (#85733)</li>
<li>Memory/local embeddings: run local GGUF embeddings in an isolated worker sidecar and degrade to configured fallback or keyword search on worker failure so native embedding crashes do not take down the Gateway. (#85348) Thanks @osolmaz.</li>
<li>Gateway: clear the runtime config snapshot before <code>SIGUSR1</code> in-process restarts so config changes survive the next gateway loop. (#86388) Thanks @XuZehan-iCenter.</li>
<li>Models: show OAuth delegation markers as configured <code>models.json</code> auth while keeping runtime route usability checks strict. (#86378) Thanks @rohitjavvadi.</li>
<li>Cron: seed active scheduled and manual cron task rows with a progress summary so status surfaces do not look blank while jobs run. (#86313) Thanks @ferminquant.</li>
<li>Cron: preserve unsupported persisted cron payload rows during routine store writes while keeping those rows non-runnable. Fixes #84922. (#86415) Thanks @IWhatsskill.</li>
<li>Updater: exclude prerelease git tags from stable channel resolution so source updates do not check out newer alpha/rc/preview/canary tags. (#86260) Thanks @stevenepalmer.</li>
<li>Security/Audit: flag webhook <code>hooks.token</code> reuse of active Gateway password auth in <code>openclaw security audit</code> while keeping password-mode startup compatibility. (#84338) Thanks @coygeek.</li>
<li>QQBot: derive the outbound reply watchdog from configured agent and provider timeouts so slow local model replies are not cut off at five minutes. Fixes #85267. (#85271) Thanks @SymbolStar.</li>
<li>Agents/heartbeat: stop heartbeat turns after the first valid <code>heartbeat_respond</code> so repeated response loops do not burn tokens. (#86357) Thanks @udaymanish6.</li>
<li>Tasks: keep retained lost tasks out of default status health counts, explain their cleanup window during maintenance, and prune lost task records after 24 hours instead of the general 7-day terminal retention.</li>
<li>Memory-core: keep REM dreaming focused on live light-staged memories and mark staged entries as considered so old recall history no longer dominates fresh candidates. (#86302) Thanks @SebTardif.</li>
<li>Memory: abort sync instead of downgrading an existing semantic vector index to FTS-only when the configured embedding provider is temporarily unavailable. (#85704) Thanks @yaaboo-gif.</li>
<li>Telegram: propagate forum topic names through the account-scoped topic cache for native command context and topic create/edit actions. (#86299) Thanks @SebTardif.</li>
<li>Slack: keep downloaded read-only files out of reply media so Slack file reads do not echo files back to the conversation. (#86318) Thanks @neeravmakwana.</li>
<li>Cron: accept leading-plus relative durations such as <code>+5m</code> for one-shot <code>--at</code> schedules. (#86341) Thanks @mushuiyu886.</li>
<li>Agents/media: preserve async-started media tool metadata so background generation starts no longer surface generic incomplete-turn warnings while replay stays unsafe. (#85933) Thanks @fuller-stack-dev.</li>
<li>Docker E2E: dedupe scheduler lane resources so npm/service package lanes are not over-counted and serialized unnecessarily.</li>
<li>QA/diagnostics: add a collector-backed OpenTelemetry smoke lane, make the OTLP payload leak check scenario-aware, and keep source QA builds from failing on optional dependency imports resolved through pnpm's temp module path.</li>
<li>Crabbox: bootstrap Git metadata for sparse remote changed gates so raw synced workspaces can run <code>pnpm check:changed</code> from the intended diff.</li>
<li>xAI/LM Studio: avoid buffering ordinary bracketed or <code>final</code> prose until stream completion while watching for plain-text tool-call fallbacks.</li>
<li>Doctor: warn and continue when the cron job store exists but cannot be read so later health checks still run. Fixes #86102. (#86384) Thanks @1052326311.</li>
<li>Discord: suppress a bot's previous reply body and referenced media from prompt context when a user replies to that bot message, while keeping reply metadata for routing. (#86238) Thanks @fuller-stack-dev.</li>
<li>Discord: restore bare numeric channel IDs for outbound message-tool sends while keeping explicit DM targets unambiguous. (#86571) Thanks @joshavant.</li>
<li>Docker E2E: avoid rebuilding the Control UI twice while preparing the shared OpenClaw package tarball for package-backed scenario runs.</li>
<li>Tests: avoid rebuilding the Control UI twice during the installer Docker smoke now that <code>pnpm build</code> includes <code>ui:build</code>.</li>
<li>Tests: give QA config mutation RPCs enough native Windows budget to finish gateway config writes and restart settle after hot scenario runs.</li>
<li>Tests: keep the gateway restart-inflight QA scenario focused on restart recovery on native Windows by allowing expected embedded prompt handoff errors and using the Windows-safe timeout budget.</li>
<li>QA-Lab: make the synthetic OpenAI provider honor generic <code>reply exactly:</code> directives after required kickoff reads so restart-recovery scenarios do not fall through to generic repo-summary prose.</li>
<li>Gateway: abort active <code>agent</code> RPC runs during forced restart shutdown so stale in-process turns cannot keep writing a session after the Gateway lifecycle restarts.</li>
<li>Crabbox: sync clean sparse worktrees through a temporary full checkout even when reusing an existing lease so tracked build-time files are not omitted.</li>
<li>Build: route <code>scripts/ui.js</code> through the shared pnpm runner and keep Control UI chunking helpers in sparse-included source so native Windows Corepack builds can produce <code>dist/control-ui</code>.</li>
<li>Tests: give the memory fallback QA scenario enough turn budget to exercise native Windows gateway runs instead of failing on the client timeout while the mock agent is still dispatching.</li>
<li>Tests: collect QA gateway CPU/RSS metrics on native Windows and give the channel baseline enough turn budget to report slow gateway runs instead of timing out before proof.</li>
<li>Install/update: bypass npm <code>min-release-age</code> policies with <code>--min-release-age=0</code> instead of <code>--before</code> so hosted installers keep working on npm versions that reject the combined config. (#84749) Thanks @TeodoroRodrigo.</li>
<li>Diagnostics: reclaim wedged session lanes when stale active-run bookkeeping blocks queued work despite no forward progress. Fixes #85639. Thanks @openperf.</li>
<li>WebChat: keep message-tool replies visible in the chat while still summarizing internal tool results for the model. Fixes #86347. Thanks @shakkernerd.</li>
<li>Gateway/perf: fail startup benchmark samples when the Gateway process exits before benchmark teardown, including signal deaths after readiness probes.</li>
<li>Gateway/perf: fail restart benchmark samples when the Gateway exits before benchmark teardown, including clean exits and signal deaths after successful restart probes.</li>
<li>Agents/tests: keep model catalog visibility on static selection helpers so catalog visibility checks avoid the broad model-selection barrel import.</li>
<li>Agents/commitments: serialize commitment store load-modify-save writes so concurrent heartbeat and CLI updates no longer lose dismissal, sent, or attempt state. (#81153) Thanks @ai-hpc.</li>
<li>xAI/LM Studio: promote plain-text tool-call fallbacks into structured tool calls and strip leaked internal tool syntax before user-facing delivery. (#86222) Thanks @fuller-stack-dev.</li>
<li>CLI: suppress benign self-update version-skew warnings during package post-update finalization.</li>
<li>Gateway/perf: tighten restart and startup benchmark failure handling so long profiling runs, failed probes, and fresh Linux runners no longer produce false passing or <code>n/a</code> results.</li>
<li>Checks: keep intentional Knip unused-file findings optional so full CI and sparse proof workspaces stay aligned.</li>
<li>Docker: restore writable <code>~/.config</code> in runtime images. Fixes #85968. Thanks @hkoessler and @Bartok9.</li>
<li>Plugin SDK: keep legacy root diagnostic subscriptions connected when built plugin SDK aliases resolve diagnostic helpers through a separate module graph.</li>
<li>Diagnostics: export alertable OTel and Prometheus signals for blocked tools, model failover, stale sessions, liveness warnings, oversized payloads, and webhook ingress while fixing shared OTLP endpoints with query strings.</li>
<li>Tests: normalize macOS canonical temp paths in exec allowlists, fs-safe trash assertions, installed plugin matching, Telegram topic-name stores, and built ACPX MCP server expectations so native macOS proof runners cover the intended behavior.</li>
<li>Codex/app-server: preserve message-tool-only source reply delivery mode on active runs so sub-agent completion wakeups can steer the active Codex turn instead of being rejected. (#86287) Thanks @ferminquant.</li>
<li>Tests: sample the Windows kitchen-sink RPC gateway directly and serialize RSS probes so native runs keep the memory guard active.</li>
<li>Tests: normalize bundled plugin lifecycle probe paths and state-root lookup so native Windows release sweeps accept valid packaged plugin installs.</li>
<li>Agents/Claude CLI: route live native Bash permission requests through OpenClaw exec policy so Claude turns no longer stall on <code>control_request</code>, and document that OpenClaw exec policy is authoritative. Fixes #80819. (#86330, from #81971) Thanks @guthirry and @sallyom.</li>
<li>Security audit: warn when YOLO OpenClaw exec policy overrides a restrictive raw Claude <code>--permission-mode</code> for managed live sessions. (#86557) Thanks @sallyom.</li>
<li>Config: keep benign legacy metadata write anomalies out of default doctor and config command output while preserving explicit anomaly logging for diagnostics.</li>
<li>Codex: log when implicit app-server <code>never</code> approvals are promoted for OpenClaw tool policy, including whether the trigger was a <code>before_tool_call</code> hook or trusted tool policy.</li>
<li>Codex harness: make subscription usage-limit errors without reset times explain that OpenClaw cannot determine the reset and point users to wait until Codex is available, use another Codex account, or switch to another configured model/provider. Thanks @amknight.</li>
<li>Google Vertex: support production ADC modes such as Workload Identity Federation, service-account credentials, and metadata-server ADC for the native Vertex transport. (#83971) Thanks @damianFelixPago.</li>
<li>Telegram: route normal <code>[telegram][diag]</code> polling diagnostics through <code>runtime.log</code> while keeping non-diag warnings and persistence failures on <code>runtime.error</code>, so healthy polling startup no longer looks like an error. Fixes #82957. (#82958) Thanks @galiniliev.</li>
<li>Providers/Ollama: strip inline Kimi cloud reasoning prefixes from streamed and final visible replies while keeping ordinary Kimi answers append-only. (#86286) Thanks @jason-allen-oneal.</li>
</ul>
<ul>
<li>Gateway: require Talk secret authority before setup-code handoff can include Talk secrets. (#85690) Thanks @ngutman.</li>
<li>Agents: keep fallback error reporting scoped to the active model candidate so stale prior-provider quota/auth text is not reported for later fallback attempts. (#86134) Thanks @zhangguiping-xydt.</li>
<li>iMessage: dedupe watcher startup when <code>channels.imessage.accounts</code> lists both <code>default</code> and a named account that point at the same local Messages source, so the gateway no longer spawns two <code>imsg rpc</code> processes or doubles inbound replies; the dedupe is scoped to watcher startup, leaving duplicate accounts addressable for outbound sends, status, and capability listings, and <code>openclaw doctor</code> flags the redundant account with a rebinding hint. Fixes #65141. (#86705) Thanks @swang430.</li>
</ul>
<p><a href="https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md">View full changelog</a></p>
]]></description>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.5.26/OpenClaw-2026.5.26.zip" length="54484748" type="application/octet-stream" sparkle:edSignature="y4WXG7JT8ktJ+K7YDgllY7u5Z9BSKR/SwGiwEh0gikOJ/SWqwcQd+z2tWa2zgwvCJKWsAUFwJs1ATor880SUBg=="/>
</item>
<item>
<title>2026.5.22</title>
<pubDate>Sun, 24 May 2026 01:41:27 +0000</pubDate>
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
<sparkle:version>2026052290</sparkle:version>
<sparkle:shortVersionString>2026.5.22</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[<h2>OpenClaw 2026.5.22</h2>
<h3>Changes</h3>
<ul>
<li>Gateway/perf: reuse process-stable channel catalog reads, avoid repeated bundled-channel boundary checks, and rotate gateway watch CPU profiles so benchmark runs do not accumulate unbounded artifacts.</li>
<li>Gateway/perf: reuse immutable plugin metadata snapshots across startup, config, model, channel, setup, and secret metadata readers so hot paths avoid repeated plugin file stats and manifest registry reloads.</li>
<li>Gateway/perf: lazy-load startup-idle plugin work, core gateway method handlers, and the embedded ACPX runtime so Gateway health and ready signals no longer wait on unused handler trees or ACPX probes.</li>
<li>Gateway/perf: cache plugin SDK public-surface alias maps and skip irrelevant macOS Linuxbrew PATH probes so Gateway startup avoids repeated filesystem walks and slow missing-directory stats.</li>
<li>Meeting Notes: add a source-only external meeting-notes plugin and SDK source-provider contract outside the core npm package, with auto-start capture config, manual transcript imports, read-only <code>openclaw meeting-notes</code> CLI access, and Discord voice as the first live source.</li>
<li>Docs/channels/config: add Signal <code>configPath</code>, Telegram wildcard topic defaults, local-time backup archive names, Termux home fallback, include-path validation, secret-scanner-safe placeholder guidance, Gemini CLI/Antigravity media guidance, and macOS VM auto-login guidance. Thanks @NorseGaud, @yudistiraashadi, @huangqian8, @VibhorGautam, @maweibin, @tianxingleo, @IgnacioPro, and @xzcxzcyy-claw.</li>
<li>Docs: clarify model-usage portability, Codex migration prerequisites, status bootstrap wording, thread-bound subagent limits, hook ownership, and config-preserving safety guidance. Thanks @aniruddhaadak80, @leno23, @TomDjerry, @matthewxmurphy, @vincentkoc, and @stablegenius49.</li>
<li>Docs: clarify README onboarding and Gateway startup paths, WhatsApp QR/408 recovery, cron output language prompts, skill advanced features, gateway upstream 403 troubleshooting, and plugin fallback override guidance. Thanks @deepujain, @Zacxxx, @Jah-yee, @neyric, @usimic, @Renu-Cybe, @BigUncle, and @SeashoreShi.</li>
<li>Docs: clarify context-pruning ratio bounds, local dashboard recovery, CLI env markers, remote onboarding token behavior, and Peekaboo Bridge permissions for subprocess agents. Thanks @ayesha-aziz123, @dishraters, @hougangdev, and @brandonlipman.</li>
<li>Docs: clarify browser CDP diagnostics, Plugin SDK allowlist imports, status-reaction timing defaults, queue steering behavior, limited-tool troubleshooting, cron HEARTBEAT handling, Telegram multi-agent groups, Bitwarden SecretRef setup, and EasyRunner deployments. Thanks @Quratulain-bilal, @mbelinky, @Mickey-, @vancece, @xenouzik, @posigit, @surlymochan, @janaka, and @choiking.</li>
<li>Crabbox/Testbox: run clean sparse-checkout Testbox syncs from a temporary full checkout and route remote changed gates through Corepack pnpm.</li>
<li>Docs: clarify IPv4-only Gateway BYOH binding, trusted-proxy scope clearing, Android pairing approval, macOS Accessibility grants, Zalo profile env vars, password-store SecretRef setup, and Chinese memory navigation. Thanks @itskai-dev, @gwh7078, @longstoryscott, @MoeJaberr, and @yuaiccc.</li>
<li>Docs: consolidate GLM under Z.AI, add the Upstash Box install guide and Gateway exposure runbook, clarify MEDIA directives, Copilot and Voyage setup, config path quoting, real behavior proof, and memory-file write guidance. Thanks @BobDu, @alitariksahin, @Jefsky, @musaabhasan, @OmerZeyveli, @leno23, @WuKongAI-CMU, @luoyanglang, and @majin1102.</li>
<li>Docs: clarify media provider credentials, Codex/OpenClaw code-mode boundaries, Slack and Telegram ack reactions, Feishu dynamic agents, secrets plaintext boundaries, memory guidance, and Chinese glossary terms. Thanks @nielskaspers, @cosmopolitan033, @drclaw-iq, @alexgduarte, @zccyman, @chengoak, and @cassthebandit.</li>
<li>Packaging: exclude documentation images and assets from the npm tarball, reducing published package size without affecting runtime docs search or CLI behavior. Thanks @SebTardif.</li>
<li>Media understanding: stop auto-probing Gemini CLI and use Antigravity CLI only as a lower-priority image/video fallback after configured provider APIs.</li>
<li>Agents/subagents: limit default sub-agent bootstrap context to <code>AGENTS.md</code> and <code>TOOLS.md</code>, keeping persona, identity, user, memory, heartbeat, and setup files out of delegated workers by default. (#85283) Thanks @100yenadmin.</li>
<li>Maintainer skills: exclude plugin SDK/API boundary work from <code>openclaw-landable-bug-sweep</code> so bugbash sweeps stay focused on small paper-cut fixes.</li>
<li>QA-Lab/diagnostics: extend the OpenTelemetry smoke harness to prove trace, metric, and log export, and add first-class Prometheus and observability smoke aliases.</li>
<li>Plugin SDK: add a generic channel-message poll sender so channel plugins can expose poll delivery without depending on channel-specific SDK facades.</li>
<li>Crabbox: keep the local wrapper's provider validation synced with the installed Crabbox binary while preserving supported aliases such as <code>docker</code> and <code>blacksmith</code>. (#85302) Thanks @hxy91819.</li>
<li>Maintainer skills: add <code>openclaw-landable-bug-sweep</code> for producing five small, reviewed, CI-green OpenClaw bugfix PRs from issue/PR sweeps.</li>
<li>Control UI/chat: add search and Load More pagination to the chat session picker, keeping initial session loads bounded while making older conversations reachable. (#85237) Thanks @amknight.</li>
<li>CLI/onboarding: start classic onboarding when bare <code>openclaw</code> runs before an authored config exists, while keeping configured installs on Crestodian. (#72343) Thanks @fuller-stack-dev.</li>
<li>Discord: allow configuring a bounded <code>agentComponents.ttlMs</code> callback registry lifetime for long-running component workflows, with per-account overrides and a 24-hour cap. (#84189) Thanks @100menotu001.</li>
<li>xAI/Grok: reuse xAI OAuth auth profiles for Grok <code>web_search</code>, thread active-agent auth through web search, add Grok model aliases, and let media providers declare default operation timeouts. (#85182) Thanks @fuller-stack-dev.</li>
<li>Plugin SDK: add row-level session workflow helpers and deprecate <code>loadSessionStore</code> so plugins can read and patch sessions without depending on the legacy whole-store shape. (#84693) Thanks @efpiva.</li>
<li>Gateway/plugins: reuse a compatible Gateway startup plugin registry during dispatch so safe plugin dispatches avoid redundant registry loading. (#84324) Thanks @ai-hpc.</li>
<li>Plugins/SDK: add a general <code>embeddingProviders</code> capability contract and registration API so embeddings can become a reusable provider surface outside memory-specific adapters.</li>
<li>Dependencies: refresh provider, plugin, UI, and tooling packages, update <code>protobufjs</code> to 8.4.0 to clear the current npm advisory, and carry the Claude ACP completion patch forward to <code>@agentclientprotocol/claude-agent-acp</code> 0.36.1.</li>
<li>Agents/tools: remove the old sender-owner tool gating path so configured tools stay visible for trusted sessions while command and channel-action auth still carry real sender identity.</li>
<li>QA-Lab: add curated mock JSONL replay fixtures and first-drift reporting for runtime-parity audits. (#80323, refs #80176) Thanks @100yenadmin.</li>
<li>QA-Lab: add a QA bus tool-trace visibility scenario for sanitized tool-call assertions.</li>
<li>QA-Lab: replace generic evidence framing in seeded scenario prompts with concrete observed QA behavior.</li>
<li>QA-Lab: list named scenario packs in the coverage report so personal-agent privacy coverage stays visible in audits.</li>
<li>QA-Lab: list live transport lane membership in the coverage report so real transport checks stay separate from seeded qa-channel scenarios.</li>
<li>Release/package: run package integrity checks before package acceptance lanes so public install/update validation fails before private QA assets can leak into the package.</li>
<li>QA-Lab: include the optional 100-turn runtime parity soak in release-soak artifacts so long-run Codex/Pi transcript drift stays visible outside the default gate. (#80395) Thanks @100yenadmin.</li>
<li>QA-Lab: add a live-only long-context progress watchdog scenario for Codex app-server timeout and stalled-run sentinels. (#80323) Thanks @100yenadmin.</li>
<li>QA-Lab: tag gateway restart recovery and streaming final-integrity scenarios as live-only runtime parity lanes. (#80323) Thanks @100yenadmin.</li>
<li>QA-Lab: add a personal-agent failure recovery scenario that checks honest partial status, retry boundaries, and local recovery artifacts. (#83872) Thanks @iFiras-Max1.</li>
<li>QA-Lab: include an opt-in <code>update.run</code> package self-upgrade sentinel for destructive latest-package recovery checks.</li>
<li>QA-Lab: add Codex plugin lifecycle and auth-profile fixture coverage for missing installs, pinned-version drift, first-turn install ordering, and doctor migration safety. (#80323, refs #80174) Thanks @100yenadmin.</li>
<li>Models/perf: pre-warm the provider auth-state map at gateway startup so <code>/models</code> and every model-listing call short-circuits the per-provider plugin / external-CLI discovery on the hot path. Per-call cost drops from ~20 s to ~5 ms (~4,100×); the one-time startup warm resets and re-warms after hot reloads. (#84816) Thanks @sjf.</li>
<li>Release/security: ship the root npm package and OpenClaw-owned npm plugins with generated shrinkwrap, support bundled plugin runtime dependencies for suitable plugin tarballs, and require review for lockfile/shrinkwrap changes so published installs use locked dependency graphs.</li>
<li>Tests/perf: isolate doctor core health check unit coverage from real skills/workspace discovery so <code>doctor-core-checks</code> no longer dominates unit perf while keeping one real skills-readiness smoke. (#84493) Thanks @frankekn.</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>WebChat: summarize internal message-tool source replies so tool cards no longer duplicate the visible reply body. (#84773) Thanks @jason-allen-oneal.</li>
<li>Gateway: preserve deferred lifecycle-error cleanup across later non-terminal events so provider timeouts can persist failed session state instead of leaving sessions stuck running. (#85256, fixes #63819) Thanks @samzong.</li>
<li>Agents/subagents: report tool-only child progress during timeout summaries instead of showing no visible output.</li>
<li>Telegram/ACP: preserve explicit <code>:topic:</code> conversation suffixes when inbound ACP targets do not carry a separate thread id.</li>
<li>Browser/proxy: bypass the managed proxy for the exact local managed Chrome CDP readiness and DevTools WebSocket endpoints, so <code>openclaw browser start</code> works when the operator proxy blocks loopback egress. (#83255) Thanks @lightcap.</li>
<li>Ollama: bypass the managed proxy for configured local embedding origins while keeping SSRF guardrails on unconfigured targets. Thanks @Kaspre.</li>
<li>OpenAI/images: route Codex API-key image generation through the native OpenAI Images API instead of the Codex OAuth streaming backend, avoiding 401s from valid API keys.</li>
<li>Agents/OpenAI completions: omit empty tool payload fields for proxy-like OpenAI-compatible endpoints so strict vLLM-style servers accept tool-free turns. (#85835) Thanks @rendrag-git.</li>
<li>Checks/Windows: route full <code>pnpm check</code> stage commands through the managed child runner so Windows avoids Node shell-argv deprecation warnings there too.</li>
<li>Checks/Windows: run managed child commands through explicit <code>cmd.exe</code> wrapping instead of Node shell mode with argv, avoiding Node 24 subprocess deprecation warnings during changed checks.</li>
<li>Gateway: omit internal stream-error placeholder entries from agent prompt history so failed assistant turns are not replayed as model-authored text. (#85652) Thanks @anyech.</li>
<li>Sessions: enforce the session write-lock max-hold policy during lock acquisition so long-held locks can be reclaimed before the stale-lock window. (#85764) Thanks @njuboy11.</li>
<li>Models: prune retired Groq, GitHub Copilot, OpenAI, xAI, and old Claude catalog entries, with doctor migration to upgrade existing configs to current provider refs.</li>
<li>Doctor/update: recognize junction-backed source checkouts as git installs by comparing canonical paths before showing package-manager update guidance. Fixes #82215. Thanks @igormf.</li>
<li>Channels: honor <code>/verbose on</code> for tool/progress summaries across direct chats, groups, channels, and forum topics while preserving quiet default behavior. (#85488) Thanks @kurplunkin.</li>
<li>CLI/skills: show an all-ready note with next-step commands when skill setup has no missing dependencies to install. (#85032) Thanks @aniruddhaadak80.</li>
<li>Microsoft Foundry: route DeepSeek V4 Pro and Flash models through the Foundry Responses API while keeping older DeepSeek models on their existing path. (#85549) Thanks @roslinmahmud.</li>
<li>Status/usage: show configured cost estimates for AWS SDK models in full usage output while keeping token-only usage replies cost-free. (#85619) Thanks @ItsOtherMauridian.</li>
<li>Agents/OpenAI Responses: retry non-visible reasoning-only turns for OpenAI Responses API families instead of treating them as empty failed turns. (#85603) Thanks @SebTardif.</li>
<li>Directive tags: preserve message and content-part object identity when display stripping makes no directive-tag changes. (#85682) Thanks @willamhou.</li>
<li>Telegram: send local <code>path</code>/<code>filePath</code> and structured attachment media from <code>sendMessage</code> actions instead of dropping them or sending text-only messages. (#85219) Thanks @keshavbotagent.</li>
<li>Sessions/status: show the estimated context budget when fresh provider usage is unavailable and clear stale estimates across session resets and compaction boundaries. (#84830) Thanks @giodl73-repo.</li>
<li>Gateway/config: pin relative <code>OPENCLAW_STATE_DIR</code> overrides to an absolute path at startup so later working-directory changes cannot retarget gateway state. (#52264) Thanks @PerfectPan.</li>
<li>Release/package: run npm release, prepublish, and postpublish verification through Windows-safe npm command shims so native Windows checks can execute <code>npm.cmd</code> instead of treating it as a binary.</li>
<li>Agents/harness: pass CLI runtime aliases through harness selection so provider-owned CLI aliases no longer get rejected before reaching the right runtime. (#85631) Thanks @potterdigital.</li>
<li>Secrets: show the irreversible apply warning after interactive <code>secrets configure</code> confirmation so confirmed migrations still get the final safety prompt. (#85638) Thanks @alkor2000.</li>
<li>Agents/CLI output: ignore cumulative Claude <code>stream-json</code> result usage when assistant usage events are present, preventing inflated cache-read accounting. (#85625) Thanks @zhouhe-xydt.</li>
<li>CLI: keep <code>waitForever()</code> alive by leaving its keep-alive interval ref'd so the public helper no longer exits immediately with Node's unsettled-await code. (#85694) Thanks @m1qaweb.</li>
<li>Agents/bootstrap: guard bootstrap name checks against missing file names so malformed bootstrap entries warn and truncate instead of crashing. Fixes #85523. (#85615) Thanks @zhouhe-xydt.</li>
<li>CLI/tasks: reject partially numeric <code>openclaw tasks audit --limit</code> values so audit limits must be real positive integers instead of accepting strings like <code>5abc</code>. (#84901) Thanks @jbetala7.</li>
<li>Status/diagnostics: bound deep Docker audit probes so <code>openclaw status --deep</code> reports slow container checks instead of hanging behind unbounded inspection. (#85476) Thanks @giodl73-repo.</li>
<li>Providers/Anthropic: migrate 1M context handling to GA-capable Claude 4.x models by sizing eligible models at 1M without the retired <code>context-1m-2025-08-07</code> beta, ignoring that retired beta in older configs, and preserving OAuth-required Anthropic beta headers. (#45613) Thanks @haoyu-haoyu.</li>
<li>Cron/Telegram: parse forum-topic delivery targets through the Telegram plugin instead of cron core, including <code>:topic:</code> and <code>:topicId</code> forms for announce delivery. Thanks @etticat.</li>
<li>Twitch: keep stale message-handler cleanup callbacks from removing newer handler registrations for the same account, preserving inbound message delivery after reconnects. Fixes #83888. (#85425) Thanks @alkor2000.</li>
<li>Memory/LanceDB: expose public memory artifacts through the active memory provider bridge so memory-wiki imports durable memory files, daily notes, dream reports, and event logs without depending on memory-core internals. Fixes #83604. (#85060) Thanks @brokemac79.</li>
<li>Crabbox: keep AWS hydration compatible with local Actions replay by inlining the hydrate workflow's Node/pnpm setup instead of invoking repo-local composite actions.</li>
<li>Agents/subagents: simplify native sub-agent completion handoff so children report their latest visible assistant result to the requester without using <code>message</code>, while keeping parent-owned message-tool delivery policy intact. Fixes #85070. (#85089) Thanks @brokemac79.</li>
<li>Docker setup: stop printing the Gateway bearer token in setup logs and printed follow-up commands.</li>
<li>Agents: let embedded compaction fallback retries proceed when PI-compatible candidates do not need agent harness plugin preparation.</li>
<li>Agents/tools: honor configured custom provider API keys when deciding whether media, image-generation, video-generation, music-generation, and PDF tools are available. (#85570)</li>
<li>StepFun: stop advertising stale generic API key auth choices so onboarding only offers runtime-backed Standard and Step Plan choices.</li>
<li>Diagnostics: keep OpenTelemetry log bodies behind explicit content capture and scrub scoped agent-session keys from OpenTelemetry and Prometheus labels while preserving bounded queue-lane prefixes.</li>
<li>Windows installer: fail Git checkout installs when <code>pnpm install</code> or <code>pnpm build</code> fails instead of writing a wrapper to a missing CLI build.</li>
<li>Sessions: surface previous-transcript archive failures during <code>/new</code> rotation so disk rename errors are logged instead of silently hiding stranded transcript files. Fixes #81984. (#85586, from #82081) Thanks @0xghost42.</li>
<li>TUI/agents: mirror internal-ui message-tool replies into final chat output so message-tool-only agents remain visible in <code>openclaw tui</code>. Fixes #85538. Thanks @danpolasek.</li>
<li>Agents: keep parallel OpenAI-compatible tool-call deltas in separate argument buffers so interleaved tool calls no longer corrupt streamed arguments. (#82263) Thanks @luna-system.</li>
<li>Memory/doctor: report missing or unusable QMD workspace directories as workspace failures instead of generic binary failures. (#63167) Thanks @sercada.</li>
<li>Debug proxy: record CONNECT client-socket errors and destroy the paired upstream socket so abrupt client disconnects no longer leak tunnel resources. (#82444) Thanks @SebTardif.</li>
<li>Diffs: continue hydrating later diff cards when one card fails so a single broken card no longer blanks the whole diff viewer. (#84775) Thanks @cosmopolitan033.</li>
<li>Mac app: use the native settings sidebar window chrome so the sidebar toggle stays on the left and content no longer clips under oversized titlebar padding.</li>
<li>QA-Lab/Codex: bundle auth/plugin fixture imports for flow scenarios and let terminal async media tools end Codex app-server turns without timing out. (#80397, refs #80323) Thanks @100yenadmin.</li>
<li>Gateway/agents: preserve fresh session overrides and metadata when stale cached agent-session entries race with store updates, so subagent model/provider overrides and routing policy survive concurrent writes. (#19328) Thanks @CodeReclaimers.</li>
<li>Control UI/chat: keep chat session search inline with the session selector so the header no longer shows a duplicate standalone search row.</li>
<li>Control UI/chat: collapse focused-mode header chrome and suppress hidden-header scroll updates so focus mode no longer jumps while scrolling. Thanks @amknight.</li>
<li>Codex app-server: restart the native app-server and retry once when server-side compaction times out, so preflight compaction stalls recover instead of failing every dispatch. (#85500)</li>
<li>Restore Control UI gateway token pairing [AI]. (#85459) Thanks @pgondhi987.</li>
<li>OpenAI video: honor configured provider request private-network opt-in for local/custom video endpoints so explicitly trusted mock and self-hosted providers are not blocked. Thanks @shakkernerd.</li>
<li>OpenAI video: send uploaded video edit requests to the documented <code>/videos/edits</code> endpoint with a <code>video</code> file instead of posting MP4 references to <code>/videos</code>. Thanks @shakkernerd.</li>
<li>Agents/channels: preserve message-tool delivery evidence through gateway agent completion handoffs so successful generated media sends are not followed by false failure messages. Thanks @shakkernerd.</li>
<li>CLI/update: repair managed npm plugin <code>openclaw</code> peer links during post-core convergence and reject stale or wrong-target peer links before restart. (#83794) Thanks @fuller-stack-dev.</li>
<li>CLI/agents: default new omitted-account bindings to all accounts when the channel has multiple configured accounts, and clarify account-scope docs. (#49769) Thanks @Gcaufy.</li>
<li>Codex app-server: let authorized <code>/codex</code> control commands such as <code>/codex detach</code> escape plugin-owned conversation bindings while keeping unknown or unauthorized slash text routed to the bound plugin. Fixes #85157. (#85188) Thanks @TurboTheTurtle.</li>
<li>Auto-reply/models: keep <code>/models</code> browse replies fast by sharing the bounded read-only catalog path with Gateway model listing. (#84735) Thanks @safrano9999.</li>
<li>Codex app-server: disable native Code Mode when the effective exec host is <code>node</code> and keep OpenClaw <code>exec</code>/<code>process</code> available, so <code>/exec host=node</code> routes shell commands through the selected node instead of the gateway. Fixes #85012. (#85090) Thanks @sahilsatralkar.</li>
<li>Agents: bound embedded auto-compaction session write-lock watchdogs to the compaction timeout instead of the full run timeout, so stuck compaction cannot hold the live session lock for the whole run window. (#84949) Thanks @luoyanglang.</li>
<li>Gateway/agents: return phase-aware <code>agent.wait</code> timeout attribution and only cool auth profiles on provider-started timeouts. Refs #65504. Thanks @100yenadmin.</li>
<li>Gateway: defer provider auth-state prewarm until after startup readiness so early gateway tool/session requests are not blocked by provider auth discovery. (#85272) Thanks @dutifulbob.</li>
<li>Gateway/models: coalesce provider auth-state rewarms after auth-profile failures and log event-loop delay for warm/rewarm work, so provider auth bursts no longer stack full auth sweeps behind channel replies.</li>
<li>Gateway/models: stop cancelled provider auth-state prewarms from continuing full provider sweeps, so reload and auth-failure bursts no longer keep startup busy.</li>
<li>Agents/Codex: show the first plan update as a transient chat status notice without counting it as final assistant content.</li>
<li>CLI/update: walk the macOS process ancestry and honor the inherited Gateway runtime PID before package updates stop the managed Gateway service, so nested in-band updater children can refuse instead of killing the LaunchAgent-supervised Gateway that owns them. Fixes #85120.</li>
<li>Gateway/LaunchAgent: wait for launchd reload bootout to finish and fall back to kickstart when bootstrap races, so reload handoff does not leave the service deregistered. Fixes #84630. (#84641) Thanks @NianJiuZst.</li>
<li>Gateway/LaunchAgent: treat a concurrent launchd bootstrap as a successful restart when the service is already loaded, avoiding false macOS Gateway restart failures. Fixes #84721. (#84722) Thanks @googlerest.</li>
<li>Gateway/service: include the active <code>openclaw</code> command bin directory in managed service PATH generation and doctor audit expectations for npm-global macOS installs. Fixes #84201. (#84475) Thanks @jbetala7.</li>
<li>Control UI/chat: disable the thinking selector for known non-reasoning models instead of showing duplicate Off choices. Fixes #84069. Thanks @DrippingMellow.</li>
<li>Memory: expand <code>~</code> in configured extra memory paths before resolving them, so home-relative folders are not treated as workspace-relative. Fixes #58026. Thanks @stadman.</li>
<li>Skills: treat <code>openclaw.os: macos</code> as Darwin when checking skill requirements, so macOS-only skills no longer report as missing on macOS hosts. Fixes #61338. Thanks @Jessecq1995.</li>
<li>Control UI/logs: strip ANSI escape sequences from displayed Gateway log messages so color codes no longer appear as raw text. Fixes #64399. Thanks @guguangxin-eng.</li>
<li>Docker: pre-create the workspace and auth-profile config mount points with <code>node</code> ownership so first-run named volumes do not start root-owned. Fixes #85076. Thanks @Noerr.</li>
<li>Telegram: pass configured markdown table mode through outbound markdown chunking so chunked sends render tables consistently. Fixes #85085. Thanks @ShuaiHui.</li>
<li>CLI/update: preserve managed Gateway service environment during package cutovers so macOS LaunchAgent repair/restart reads the pre-update service state instead of caller shell state. (#83026)</li>
<li>Agents/providers: honor per-model <code>api</code> and <code>baseUrl</code> overrides in custom provider auth hooks and transport selection. Fixes #80487. (#80488) Thanks @huveewomg.</li>
<li>Gateway/restart: eager-load the lifecycle runtime before in-place upgrade signal handling so package replacement does not deadlock restart imports. (#84890) Thanks @myps6415.</li>
<li>CLI/update: start managed Gateway update handoff helpers from a stable existing directory and tolerate deleted cwd/package roots during macOS LaunchAgent handoff. Fixes #83808. (#83875) Thanks @jason-allen-oneal.</li>
<li>Skills: watch each shared skill directory once across agent workspaces instead of once per agent, preventing file-descriptor exhaustion (<code>EMFILE</code>) that disposed bundle-mcp processes and stalled sessions on multi-agent gateways. Fixes #84968. (#85130) Thanks @openperf.</li>
<li>Release/security: keep generated npm shrinkwrap package versions inside the pnpm lock graph so published package locks cannot bypass pnpm dependency age and override policy.</li>
<li>Cron: honor <code>cron.retry.retryOn: ["network"]</code> for common network error codes such as <code>EAI_AGAIN</code>, <code>EHOSTUNREACH</code>, and <code>ENETUNREACH</code>.</li>
<li>Gateway chat: broadcast returned agent-run error payloads after an agent starts so ACP/WebChat clients receive terminal idle-timeout errors. Fixes #84945.</li>
<li>Gateway chat display: preserve OpenAI-compatible <code>prompt_tokens</code>, <code>completion_tokens</code>, and <code>total_tokens</code> usage fields in sanitized chat history so llama.cpp sessions keep context counts. Fixes #77992. Thanks @MarTT79.</li>
<li>Dashboard/CLI: allow macOS browser launching through <code>open</code> even when SSH environment variables are present, while preserving Linux SSH no-display protection. Fixes #67088. Thanks @theglove44.</li>
<li>Codex app-server: keep native web search observations out of mirrored chat transcripts while preserving tool progress telemetry. Fixes #85109. Thanks @ugitmebaby.</li>
<li>OpenCode Go: strip unsupported Kimi reasoning replay fields before provider requests so repeated <code>kimi-k2.6</code> turns do not fail schema validation. Fixes #83812. Thanks @Sleeck.</li>
<li>Browser/CDP: add a WSL2 portproxy self-loop hint when Chrome DevTools endpoints accept connections but return an empty HTTP reply. Fixes #59209. Thanks @Owlock.</li>
<li>Agents/OpenAI: preserve structured provider error code, type, and redacted body metadata on boundary-aware transport failures.</li>
<li>Doctor/Codex: point native Codex asset warnings at the canonical <code>openclaw migrate plan codex</code> preview command. Fixes #84948. Thanks @markoa.</li>
<li>CLI/models: make <code>capability model auth logout --agent</code> remove auth profiles from the selected non-default agent store. Fixes #85092. Thanks @islandpreneur007.</li>
<li>Gateway/models: reuse prepared provider auth metadata during model-listing auth checks so repeated lookups avoid broad plugin discovery while preserving synthetic local auth.</li>
<li>CLI/status: suppress systemd user-service setup hints when <code>openclaw status --deep</code> can already reach a running Gateway RPC service. Fixes #85094. Thanks @islandpreneur007.</li>
<li>CLI/devices: recover local approval when a same-device repair request replaces the request ID being approved.</li>
<li>CLI/agents: retry transient normal-close Gateway handshakes before falling back to embedded <code>openclaw agent</code> execution.</li>
<li>CLI/update: keep managed Gateway service stop/restart status lines out of <code>openclaw update --json</code> stdout so package-update automation can parse the JSON payload.</li>
<li>Plugins: resolve OpenClaw plugin SDK subpaths for native external plugin runtimes without mutating package installs or broadening process-wide module resolution.</li>
<li>Agents/OpenAI: preserve Responses and Chat Completions <code>reasoning_tokens</code> usage metadata without double-counting it in aggregate output tokens. (#85319)</li>
<li>Control UI/chat: convert pasted <code>data:image/...;base64,...</code> clipboard text into an image attachment instead of dumping the payload into the composer. Fixes #62604. Thanks @cpwilhelmi.</li>
<li>Providers/Gemini: strip fractional seconds from web-search time range filters so Gemini accepts freshness-bound search requests. (#85071) Thanks @Noerr.</li>
<li>OpenAI Codex: preserve image input support for sparse <code>openai-codex/gpt-5.5</code> catalog rows. (#85095) Thanks @sercada.</li>
<li>CLI/models: add a piped or pasted API-key path for OpenAI Codex auth and warn when API keys are pasted into token-mode auth. (#85533) Thanks @joshavant.</li>
<li>Telegram: dead-letter missing-harness isolated ingress failures so a poisoned spooled update no longer blocks later same-lane messages. Fixes #85470. (#85605) Thanks @joshavant.</li>
<li>Plugins/discovery: strip <code>-plugin</code> package suffixes when deriving plugin id hints so package names line up with manifest ids. (#85170) Thanks @JulyanXu.</li>
<li>Tlon: stop advertising a non-existent agent tool contract in the plugin manifest.</li>
<li>Telegram: preserve fenced code block languages through Markdown rendering so Telegram receives <code>language-*</code> code classes. (#85209) Thanks @leno23.</li>
<li>Windows installer: run npm and Corepack command shims from a Windows-local directory so installs launched from WSL2 UNC paths do not fail before OpenClaw is installed.</li>
<li>Windows updates: roll back git-backed updates to the previous checkout when dependency install, build, UI build, or doctor repair fails.</li>
<li>Windows installer: persist user-local portable Git on PATH and activate the repo-pinned pnpm version for git-backed installs and updates.</li>
<li>Windows installer: bootstrap a user-local portable Node.js when native Windows has no Node and no winget, Chocolatey, or Scoop, so first-run installs can continue on raw hosts.</li>
<li>Windows installer: extract the downloaded portable Node.js directory with native <code>tar</code> before falling back to .NET zip extraction, avoiding PowerShell 5.1 archive and path-length failures.</li>
<li>fix(integrations): enforce channel read target allowlists [AI]. (#84982) Thanks @pgondhi987.</li>
<li>Agents/heartbeat: route single-owner <code>session.dmScope=main</code> direct-message exec and cron event wakes back to the agent main session so async completions no longer strand context in orphan direct-DM queues. Fixes #71581. (#83743) Thanks @Kaspre.</li>
<li>Agents/code-mode: expose outer code-mode <code>exec</code> source through the <code>command</code> hook alias with <code>toolKind</code>/<code>toolInputKind</code> discriminators so exec-shaped policies can distinguish code-mode cells. (#83483) Thanks @Kaspre.</li>
<li>Agents/code mode: return structured timeout and runtime-unavailable error codes for known worker failures. Fixes #83389. (#83444) Thanks @Kaspre.</li>
<li>QA-Lab: isolate multi-scenario suite workers when scenarios need startup config patches, preventing message-routing config from leaking into unrelated scenarios.</li>
<li>QA-Lab: make the commitments heartbeat-target-none scenario request an immediate heartbeat instead of waiting for the next scheduled heartbeat.</li>
<li>Codex/Plugin SDK: deliver Codex-native subagent completions through a generic harness task runtime so harness-backed plugins can mirror durable task lifecycle and completion delivery without Codex-specific SDK imports. (#83445) Thanks @bryanpearson.</li>
<li>Gateway CLI: surface local post-challenge connect assembly failures immediately instead of waiting for the wrapper timeout. Fixes #68944. (#85253) Thanks @samzong.</li>
<li>Messages: strip unsupported web-search citation control markers from outbound replies before they reach WebChat or external channels. Fixes #85193. (#85204) Thanks @neeravmakwana.</li>
<li>Agents/exec: treat denied exec approvals as terminal instead of feeding them back into agent follow-up work, and recognize Chinese stop phrases in abort handling. Fixes #69386. (#85194) Thanks @samzong.</li>
<li>CLI/agents: abort accepted Gateway-backed <code>openclaw agent</code> runs on SIGINT/SIGTERM so cron and supervisor timeouts do not leave remote agent work alive. Fixes #71710. (#84381) Thanks @Kaspre.</li>
<li>Codex app-server: retry replay-safe stdio client-close turns once using structured failure metadata, while surfacing idle <code>turn/completed</code> timeouts instead of blindly replaying active shared-server turns. Thanks @VACInc.</li>
<li>Codex app-server: reject command overrides that embed Node or package-manager arguments and point users to <code>appServer.args</code>, so Windows startup avoids shell parsing failures. (#84417) Thanks @TurboTheTurtle.</li>
<li>Agents/Copilot: drop unsafe GitHub Copilot Responses reasoning replay items before send so Telegram direct sessions no longer fail on overlong replay IDs. Fixes #85197. (#85198) Thanks @galiniliev.</li>
<li>UI: add accessible tooltips to the topbar color-mode buttons so System, Light, and Dark choices are labeled on hover and focus. (#85227) Thanks @amknight.</li>
<li>fix: constrain Windows task script names [AI]. (#85064) Thanks @pgondhi987.</li>
<li>Control UI: keep the chat session picker from hiding older or cross-agent configured conversations while preserving the bounded configured-agent refresh. (#85211) Thanks @amknight.</li>
<li>Agents/Anthropic: preserve unsafe integer tool-call input values in streamed Anthropic tool-use JSON, preventing Discord-style IDs from being rounded before dispatch. Fixes #47229. (#83063) Thanks @leno23.</li>
<li>Agents/Codex: estimate tool-heavy prompt pressure at the LLM boundary before provider submission, so persistent sessions compact before overflowing context windows. (#85541) Thanks @fuller-stack-dev and @joshavant.</li>
<li>Agents/hooks: wait for local one-shot CLI and Codex <code>agent_end</code> plugin hooks before process cleanup so terminal observability flushes reliably. (#85007)</li>
<li>Providers/Google: preserve Gemini 3 cron <code>thinkingDefault: "low"</code> when stale catalog metadata says <code>reasoning:false</code>, so scheduled runs keep provider-supported thinking instead of downgrading to off. (#85185) Thanks @neeravmakwana.</li>
<li>CLI/agents: allow <code>openclaw agent --session-key</code> to target explicit session keys, including agent-scoped legacy keys. (#85121) Thanks @Kaspre.</li>
<li>Auto-reply/ACP: wait for same-channel block reply delivery before starting tool work, while still honoring ACP dispatch aborts so stopped turns do not wait on slow channel sends. (#83722) Thanks @IWhatsskill.</li>
<li>Codex/ACP: mark required child-run completions that only report progress, omit a final deliverable, or fail requester delivery as blocked while preserving real final reports. (#85110) Thanks @IWhatsskill.</li>
<li>Channels: treat bare abort messages such as <code>stop</code>, <code>abort</code>, and <code>wait</code> as immediate control commands in inbound debounce paths so stop requests are not delayed behind pending message coalescing. (#83348) Thanks @IWhatsskill.</li>
<li>Channels/message tool: resolve configured external channel plugins during in-agent channel selection, so <code>openclaw agent --local</code> message-tool sends no longer report an available channel as unavailable. (#85022) Thanks @Kaspre.</li>
<li>Agents/heartbeat: honor group/channel <code>message_tool</code> visible-reply policy and model-specific Codex runtime config for scheduled heartbeat runs, so failed internal tool output stays private. Fixes #85310. (#85357) Thanks @neeravmakwana.</li>
<li>Gateway/ACP: close child ACP sessions spawned via <code>sessions_spawn</code> when their parent session is reset or deleted, instead of leaving orphaned <code>claude-agent-acp</code> processes that accumulate and exhaust memory. Fixes #68916. (#85190) Thanks @openperf.</li>
<li>Codex app-server: block native execution paths when OpenClaw exec resolves to a node host while preserving the first-party CLI node binding path. Fixes #85012. (#85534) Thanks @joshavant.</li>
<li>Diagnostics: bound cleanup timeout detail logs, emit drop summaries when async diagnostic bursts exceed the queue cap, and surface async queue drops through diagnostic telemetry.</li>
<li>Agents/subagents: surface blocked child-run completions as errors instead of successful subagent finishes. (#80886) Thanks @TurboTheTurtle.</li>
<li>Context engines: fail closed with a descriptive error when the selected agent runtime cannot satisfy declared context-engine host requirements.</li>
<li>Agents/Pi: treat accepted embedded <code>sessions_spawn</code> child-session handoffs as terminal progress so parent turns no longer report false non-deliverable failures. (#85054) Thanks @samzong.</li>
<li>CLI/models: resolve <code>openclaw models set</code> aliases from the runtime config while keeping authored aliases ahead of runtime-only defaults. (#83262) Thanks @IWhatsskill.</li>
<li>Doctor: show personal Codex CLI asset notices as info instead of warnings. Fixes #84859.</li>
<li>WhatsApp: update Baileys to <code>7.0.0-rc13</code> and drop the obsolete logger type patch.</li>
<li>CLI/update: pre-pack GitHub/git package update targets before the staged npm install, restoring <code>openclaw update --tag main</code> for one-off package updates. (#81296) Thanks @fuller-stack-dev.</li>
<li>Gateway: mirror successful same-source message-tool sends into session transcripts so delivered replies stay in later history/context. (#84837) Thanks @iFiras-Max1.</li>
<li>Media generation: keep image, music, and video completion delivery from duplicating or losing task ownership when generated media finishes through active session replies. (#84006) Thanks @fuller-stack-dev.</li>
<li>Infra/json: retry transient <code>File changed during read</code> races while loading JSON state so config and state reads recover instead of failing the turn. (#84285)</li>
<li>Plugins/providers: fail closed for workspace provider plugins during setup-mode discovery unless explicitly trusted, preventing untrusted workspace plugin code from running during provider setup. (#81069) Thanks @mmaps.</li>
<li>Providers/Ollama: resolve configured Ollama Cloud <code>OLLAMA_API_KEY</code> markers to the real discovery key so cloud provider entries keep authenticated model catalog access. (#85037)</li>
<li>Discord: keep persistent component registry fallback warnings actionable by forwarding structured error and cause metadata through the runtime logger. Fixes #84185. (#84190) Thanks @100menotu001.</li>
<li>Gateway/sessions: preserve compatible session auth profile overrides when switching models within the same provider, including provider-auth aliases. Fixes #81837. (#81886) Thanks @TurboTheTurtle.</li>
<li>Gateway/status: surface inbound delivery telemetry counters and transport-liveness warnings in <code>openclaw status --all</code>. Fixes #49577. (#72724)</li>
<li>Docker: prune package-excluded plugin source workspaces and dependency closures so runtime images do not keep packages for plugins that were not opted in.</li>
<li>Providers/Ollama: treat Docker/OrbStack host aliases as local Ollama endpoints so <code>ollama-local</code> marker auth works when OpenClaw runs inside a VM/container and Ollama runs on the host. Fixes #84875.</li>
<li>QA-Lab: keep explicitly searchable/deferred OpenClaw dynamic tool rows report-only by default so tool-coverage gates do not treat mock discovery gaps as hard product failures. (#80319) Thanks @100yenadmin.</li>
<li>Agents/config: keep non-Google provider model refs from being rewritten by Google Gemini preview-id normalization. (#84762) Thanks @zhangguiping-xydt.</li>
<li>Installer: require a real controlling terminal before launching onboarding so headless <code>curl | bash</code> installs finish cleanly after installing the CLI.</li>
<li>Agents/Codex: promote a completed final assistant response when a prompt timeout races Codex app-server completion instead of returning an empty timeout envelope. Refs #84516.</li>
<li>Codex app-server: keep interrupted turn statuses from being treated as OpenClaw aborts by themselves, so tool-only turns remain eligible for no-visible-answer recovery. Fixes #84492.</li>
<li>Agents: cap heartbeat model bleed context hints by the stored session window when runtime model metadata is unavailable, so overflow recovery advice does not suggest a larger window than the active session actually has.</li>
<li>Control UI/Web Push: use <code>https://openclaw.ai</code> as the generated default VAPID subject instead of the old localhost mailbox so iOS PWA push setup uses an Apple-acceptable subject when <code>OPENCLAW_VAPID_SUBJECT</code> is unset. Fixes #83134. (#83317) Thanks @IWhatsskill.</li>
<li>Control UI: distinguish inherited thinking-off settings from explicit Off selections so the thinking selector no longer shows two identical Off rows. (#85223) Thanks @amknight.</li>
<li>Agents/Pi: keep embedded session transcript writes from tripping false takeover detection after packaged npm onboarding agent turns.</li>
<li>Codex/TUI: surface Codex-native post-turn compaction failures instead of continuing uncompacted, and keep successful native compaction serialized before local idle/next-turn handling. Fixes #84305. (#85160) Thanks @joshavant.</li>
<li>Memory/search: stop recall tracking from writing dreaming side-effect artifacts when <code>dreaming.enabled=false</code>, while preserving normal search results. Fixes #84436. (#84444) Thanks @NianJiuZst.</li>
<li>Diffs: render viewer toolbar icons from a closed icon-name map instead of HTML strings, removing the toolbar icon XSS sink. (#83955) Thanks @tanshanshan.</li>
<li>QA: keep <code>pnpm qa:e2e</code> self-check runs inside the private QA runtime envelope even when inherited shell env disables bundled plugins.</li>
<li>fix(config): validate browser sandbox bind sources [AI]. (#84799) Thanks @pgondhi987.</li>
<li>doctor: constrain legacy plugin cleanup paths [AI]. (#84801) Thanks @pgondhi987.</li>
<li>Update/doctor: prune stale local bundled plugin install records that point at old compiled bundled output so current bundled plugin schemas win after upgrade. (#84863) Thanks @fuller-stack-dev.</li>
<li>Providers/Ollama: preserve native Ollama tool-call IDs across assistant replay so Gemini over Ollama Cloud can keep its hidden function-call thought-signature handle.</li>
<li>Discord: keep session recovery and <code>/stop</code> abort ownership on the source dispatch lane while bound ACP turns continue routing to their target session, so stalled pre-run work and late replies are cleared instead of leaking after stop. Fixes #84477. (#85100) Thanks @joshavant.</li>
<li>Codex app-server: mark missing turn completion after observed execution as replay-unsafe and release the session so follow-up turns can run. Fixes #84076. (#85107) Thanks @joshavant.</li>
<li>Codex app-server: give visible <code>message</code> dynamic tool sends a longer timeout budget so slow channel delivery can return its own result or error instead of hitting the 30-second Codex wrapper. (#85216) Thanks @amknight.</li>
<li>Codex app-server: add a dedicated post-tool raw assistant completion idle timeout config so trusted heavy turns can wait longer after tool handoff without weakening final assistant release.</li>
<li>Matrix: keep explicitly configured two-person rooms on the room route before stale <code>m.direct</code> or strict two-member DM fallback can bypass mention gating. Fixes #85017. (#85137) Thanks @joshavant.</li>
<li>Agents/subagents: require explicit subagent allowlist targets to be configured agents so stale deleted-agent ids are omitted from <code>agents_list</code> and rejected by <code>sessions_spawn</code>. Fixes #84811. (#85154) Thanks @joshavant.</li>
<li>PDF tool: time out idle remote PDF body reads after 120 seconds so stalled remote documents return an error instead of wedging the session. Fixes #68649. (#84768) Thanks @luoyanglang.</li>
<li>Diagnostics/OpenTelemetry plugin: suppress handled OTLP exporter promise rejections so collector shutdowns no longer crash the Gateway. (#81085) Thanks @luoyanglang.</li>
<li>Agents/exec: omit raw command text and env values from denied exec failure logs while keeping safe correlation metadata. Fixes #85049. (#85140) Thanks @joshavant.</li>
<li>Media/audio: skip empty structured sherpa-onnx transcripts instead of treating the raw JSON payload as spoken text. (#84667) Thanks @TurboTheTurtle.</li>
<li>Agents/exec: preserve inherited XDG base-directory environment values for subprocesses while still rejecting agent-supplied XDG overrides. Fixes #84854. (#85139) Thanks @joshavant.</li>
<li>Node/Linux: keep <code>OPENCLAW_GATEWAY_TOKEN</code> out of generated systemd unit files by writing node service token values to a node-specific env file. (#84408)</li>
<li>Memory-core/dreaming: reuse stable narrative subagent session keys per workspace and phase while keeping per-run idempotency and bounded cleanup, so stale <code>dreaming-narrative-*</code> sessions do not accumulate. Fixes #68252, #69187, and #70402. (#70464) Thanks @chiyouYCH.</li>
<li>Trajectory/support: tolerate partial skill snapshot entries when building support metadata so rejected skill path scans no longer abort trajectory capture. (#71185) Thanks @lukeboyett.</li>
<li>TUI: coalesce repeated idle Esc abort notices into a single <code>no active run xN</code> system row instead of appending duplicate rows.</li>
<li>Telegram: honor <code>channels.telegram.pollingStallThresholdMs</code> in the default isolated polling path, restarting silent workers instead of leaving inbound updates wedged. Fixes #83950. (#84861) Thanks @joshavant.</li>
<li>Telegram: dedupe replayed message dispatches by Telegram chat/message identity so isolated-ingress replays do not trigger duplicate model dispatches. Fixes #84886. (#85208) Thanks @joshavant.</li>
<li>Slack: suppress reasoning payloads before reply delivery and dispatch accounting, so Slack monitor, slash-command, fallback, and direct reply paths do not leak model reasoning. Fixes #84319. (#84322) Thanks @ffluk3 and @joshavant.</li>
<li>Slack: deliver native plugin approval prompts and updates when Slack native approvals are enabled, while keeping plugin approval authorization separate from exec approvers.</li>
<li>Slack: keep native plugin approval prompts in the originating app conversation thread when the live Slack turn source is a <code>D...</code> conversation.</li>
<li>Agents/Pi: disable the embedded pi-coding-agent runtime auto-retry so OpenClaw's own retry and failover loop does not replay failed tool calls through a nested SDK retry. Fixes #73781. (#74434) Thanks @yelog.</li>
<li>CLI/perf: keep <code>setup --help</code>, <code>onboard --help</code>, and <code>configure --help</code> out of the full wizard runtime while preserving the existing help output. (#84488) Thanks @frankekn.</li>
<li>CLI/perf: keep <code>agents --help</code> out of agents action/runtime imports so help, completion, and command discovery paths avoid loading the full agents runtime. (#84483) Thanks @frankekn.</li>
<li>CLI/perf: keep <code>secrets --help</code> and <code>nodes --help</code> on the precomputed help path so parent help avoids loading action-heavy command runtime modules. (#84818) Thanks @frankekn.</li>
<li>CLI/perf: serve <code>doctor</code>, <code>gateway</code>, <code>models</code>, and <code>plugins</code> parent help from startup metadata so common subcommand help avoids full CLI program construction. (#84786) Thanks @frankekn.</li>
<li>Codex/Lossless: keep context-engine history on the canonical run session when Telegram DMs use per-peer runtime policy keys. Fixes #84936. (#84954) Thanks @neeravmakwana.</li>
<li>Codex: keep heartbeat response tool schemas durable without exposing dynamic tools disabled by turn policy, so heartbeat wakeups can reuse threads while scoped tool allowlists stay enforced. (#84681) Thanks @jalehman.</li>
<li>Auth/OAuth: skip the refresh adapter when a stored OAuth credential has no refresh token so agent turns fail fast on missing-key instead of waiting on the 120s refresh timeout. Thanks @romneyda.</li>
<li>Auth/Codex: load legacy OAuth sidecar credentials in the embedded runner's secrets-runtime auth loaders so Telegram replies, cron-triggered turns, and other isolated sub-agent lanes can reach the existing #83312 refresh-and-rewrite migration instead of failing with <code>No API key found for provider "openai-codex"</code> until the user runs <code>openclaw doctor</code>. Thanks @Totalsolutionsync and @romneyda.</li>
<li>Codex/failover: classify <code>deactivated_workspace</code> as a permanent auth failure so configured fallback models can advance when a Codex workspace is deactivated. (#55893) Thanks @litang9.</li>
<li>Exec: keep configured <code>tools.exec.pathPrepend</code> entries ahead of user shell startup PATH changes on POSIX gateway runs. (#81403) Thanks @medns.</li>
<li>Gateway/sessions: allow shared-secret bearer callers to read and stream session history without an explicit scope header. (#81815) Thanks @medns.</li>
<li>Agents/embedded runner: classify HTML auth provider responses as <code>auth_html</code> and return a re-authentication hint instead of the CDN-blocked copy that <code>upstream_html</code> returns. Cloudflare Access login pages, nginx basic-auth challenges, and gateway login walls all produce HTML auth bodies that were previously misdiagnosed as transient CDN blocks. (#79900) Thanks @martingarramon.</li>
<li>TUI/streaming watchdog: dismiss the <code>This response is taking longer than expected</code> notice as soon as a chat event for the same run arrives, so the message no longer sits next to the recovered response when the run was only briefly silent. Refs #67052, #69081 (closed), prior attempt #69026. Thanks @jpruit20 and @romneyda.</li>
<li>Agents/Pi: tolerate OpenClaw-owned transcript writes while embedded prompts are released for model I/O, keeping long-running Feishu, Slack, Telegram, and cron turns from failing with false session-takeover errors. Fixes #84059. (#84250) Thanks @tianxiaochannel-oss88.</li>
</ul>
<p><a href="https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md">View full changelog</a></p>
]]></description>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.5.22/OpenClaw-2026.5.22.zip" length="54409357" type="application/octet-stream" sparkle:edSignature="am1mwLOmUHor9QuQWtxSsKoBOCySUBo4fB+0Qdcrz0E3wf6ESIMTfOC0k+dKJSh9gtLZw5jzpWVqTBzEdU36Aw=="/>
</item>
</channel>
</rss>

View File

@@ -218,6 +218,7 @@ Current OpenClaw Android implication:
- Google Play build excludes SMS send/search, Call Log search, and recent-photo access unless the product is intentionally positioned and approved under the relevant policy exception.
- The repo now ships this split as Android product flavors:
- `play`: removes `READ_SMS`, `SEND_SMS`, `READ_CALL_LOG`, `READ_MEDIA_IMAGES`, `READ_MEDIA_VISUAL_USER_SELECTED`, and `READ_EXTERNAL_STORAGE`; hides SMS, Call Log, and Photos surfaces in onboarding, settings, and advertised node capabilities.
- Installed-app listing is user controlled. `device.apps` is advertised only after the user enables **Settings > Phone Capabilities > Installed Apps**. The command defaults to launcher-visible apps and does not require `QUERY_ALL_PACKAGES`.
- `thirdParty`: keeps the full permission set and the existing SMS / Call Log / Photos functionality.
Policy links:
@@ -252,9 +253,9 @@ Pre-req checklist:
4) Open the app **Screen** tab and keep it active during the run (canvas/A2UI commands require the canvas WebView attached there).
5) Grant runtime permissions for capabilities you expect to pass (camera/mic/location/notification listener/location, etc.).
6) No interactive system dialogs should be pending before test start.
7) Canvas host is enabled and reachable from the device (do not run gateway with `OPENCLAW_SKIP_CANVAS_HOST=1`; startup logs should include `canvas host mounted at .../__openclaw__/`).
7) Canvas host is enabled and reachable from the device for remote Canvas checks (do not run gateway with `OPENCLAW_SKIP_CANVAS_HOST=1`; startup logs should include `canvas host mounted at .../__openclaw__/`).
8) Local operator test client pairing is approved. If first run fails with `pairing required`, preview the latest pending request, approve the printed request ID, then rerun:
9) For A2UI checks, keep the app on **Screen** tab; the node now auto-refreshes canvas capability once on first A2UI reachability failure (TTL-safe retry).
9) For A2UI checks, keep the app on **Screen** tab; the node uses its bundled app-owned A2UI page for message application.
```bash
openclaw devices list
@@ -286,8 +287,8 @@ Common failure quick-fixes:
- `pairing required` before tests start:
- list pending requests (`openclaw devices list`), then approve with the exact ID (`openclaw devices approve <requestId>`) and rerun.
- `A2UI host not reachable` / `A2UI_HOST_NOT_CONFIGURED`:
- ensure the Canvas plugin host is running and reachable, keep the app on the **Screen** tab. The app refreshes the Canvas plugin surface URL once before failing; if it still fails, reconnect app and rerun.
- `A2UI host not reachable` / `A2UI_HOST_UNAVAILABLE`:
- keep the app foregrounded on the **Screen** tab and rerun. A2UI commands use the bundled app-owned A2UI page; the Gateway Canvas host is still needed for remote Canvas checks, but not for A2UI message application.
- `NODE_BACKGROUND_UNAVAILABLE: canvas unavailable`:
- app is not effectively ready for canvas commands; keep app foregrounded and **Screen** tab active.

View File

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

View File

@@ -2,10 +2,18 @@ package ai.openclaw.app
import android.content.Intent
/** Android Assistant entry point used by manifest-declared app actions. */
const val actionAskOpenClaw = "ai.openclaw.app.action.ASK_OPENCLAW"
/** Debug action that opens the Voice tab directly for Android E2E automation. */
const val actionOpenVoiceE2e = "ai.openclaw.app.debug.OPEN_VOICE_E2E"
/** Intent extra that carries an optional assistant prompt for app actions. */
const val extraAssistantPrompt = "prompt"
/**
* Top-level home destinations that external actions may request.
*/
enum class HomeDestination {
Connect,
Chat,
@@ -14,20 +22,30 @@ enum class HomeDestination {
Settings,
}
/**
* Normalized launch request from Android Assistant or explicit app actions.
*/
data class AssistantLaunchRequest(
val source: String,
val prompt: String?,
val autoSend: Boolean,
)
/**
* Parses app-owned navigation actions that should open a specific home tab.
*/
fun parseHomeDestinationIntent(intent: Intent?): HomeDestination? {
val action = intent?.action ?: return null
return when {
// Debug-only shortcut keeps E2E navigation out of release builds.
BuildConfig.DEBUG && action == actionOpenVoiceE2e -> HomeDestination.Voice
else -> null
}
}
/**
* Parse external assistant entry points without starting any UI side effects.
*/
fun parseAssistantLaunchIntent(intent: Intent?): AssistantLaunchRequest? {
val action = intent?.action ?: return null
return when (action) {

View File

@@ -1,5 +1,6 @@
package ai.openclaw.app
/** Camera HUD state categories shown over the Android UI during capture. */
enum class CameraHudKind {
Photo,
Recording,
@@ -7,6 +8,7 @@ enum class CameraHudKind {
Error,
}
/** One-shot camera HUD message keyed by token so repeated text still replays. */
data class CameraHudState(
val token: Long,
val kind: CameraHudKind,

View File

@@ -5,6 +5,7 @@ import android.os.Build
import android.provider.Settings
object DeviceNames {
/** Prefers the user-visible Android device name, then falls back to manufacturer/model text. */
fun bestDefaultNodeName(context: Context): String {
val deviceName =
runCatching {
@@ -15,6 +16,8 @@ object DeviceNames {
if (deviceName.isNotEmpty()) return deviceName
// Manufacturer/model are best-effort platform fields; keep the final
// fallback stable so stored default names do not become blank.
val model =
listOfNotNull(Build.MANUFACTURER?.takeIf { it.isNotBlank() }, Build.MODEL?.takeIf { it.isNotBlank() })
.joinToString(" ")

View File

@@ -1,5 +1,8 @@
package ai.openclaw.app
/**
* Persisted location capture mode advertised to the gateway.
*/
enum class LocationMode(
val rawValue: String,
) {
@@ -8,8 +11,10 @@ enum class LocationMode(
;
companion object {
/** Parses persisted location mode text while migrating old always-on configs to while-using. */
fun fromRawValue(raw: String?): LocationMode {
val normalized = raw?.trim()?.lowercase()
// Older configs used "always"; Android node currently exposes while-using location only.
if (normalized == "always") return WhileUsing
return entries.firstOrNull { it.rawValue.lowercase() == normalized } ?: Off
}

View File

@@ -2,34 +2,117 @@ package ai.openclaw.app
import ai.openclaw.app.ui.OpenClawTheme
import ai.openclaw.app.ui.RootScreen
import android.content.Intent
import android.os.Bundle
import android.view.WindowManager
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.withFrameNanos
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
import androidx.core.view.WindowCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
/**
* Main Android activity that owns Compose UI attachment and runtime UI wiring.
*/
class MainActivity : ComponentActivity() {
private val viewModel: MainViewModel by viewModels()
private lateinit var permissionRequester: PermissionRequester
private var initializedViewModel: MainViewModel? = null
private var didAttachRuntimeUi = false
private var didStartNodeService = false
private var didStartViewModelCollectors = false
private var foreground = false
private var pendingIntent: Intent? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
handleAssistantIntent(intent)
pendingIntent = intent
WindowCompat.setDecorFitsSystemWindows(window, false)
permissionRequester = PermissionRequester(this)
setContent {
var activeViewModel by remember { mutableStateOf<MainViewModel?>(null) }
LaunchedEffect(Unit) {
withFrameNanos { }
withContext(Dispatchers.Default) {
(application as NodeApp).prefs
}
val readyViewModel = viewModel
activateViewModel(readyViewModel)
activeViewModel = readyViewModel
}
OpenClawTheme {
activeViewModel?.let { RootScreen(viewModel = it) } ?: StartupSurface()
}
}
}
override fun onStart() {
super.onStart()
foreground = true
initializedViewModel?.setForeground(true)
}
override fun onStop() {
foreground = false
initializedViewModel?.setForeground(false)
super.onStop()
}
override fun onNewIntent(intent: android.content.Intent) {
super.onNewIntent(intent)
setIntent(intent)
pendingIntent = intent
initializedViewModel?.let { handleAssistantIntent(viewModel = it, intent = intent) }
}
/**
* Wires MainViewModel only after Activity first draw and background prefs warm-up.
*/
private fun activateViewModel(readyViewModel: MainViewModel) {
if (initializedViewModel != null) return
initializedViewModel = readyViewModel
readyViewModel.setForeground(foreground)
startViewModelCollectors(readyViewModel)
pendingIntent?.let { initialIntent ->
handleAssistantIntent(viewModel = readyViewModel, intent = initialIntent)
pendingIntent = null
}
}
/**
* Starts lifecycle collectors after ViewModel construction so they cannot force early startup.
*/
private fun startViewModelCollectors(readyViewModel: MainViewModel) {
if (didStartViewModelCollectors) return
didStartViewModelCollectors = true
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.preventSleep.collect { enabled ->
readyViewModel.preventSleep.collect { enabled ->
if (enabled) {
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
} else {
@@ -41,9 +124,10 @@ class MainActivity : ComponentActivity() {
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.runtimeInitialized.collect { ready ->
readyViewModel.runtimeInitialized.collect { ready ->
if (!ready || didAttachRuntimeUi) return@collect
viewModel.attachRuntimeUi(owner = this@MainActivity, permissionRequester = permissionRequester)
// Runtime UI helpers need an Activity owner, so attach once after NodeRuntime is ready.
readyViewModel.attachRuntimeUi(owner = this@MainActivity, permissionRequester = permissionRequester)
didAttachRuntimeUi = true
if (!didStartNodeService) {
NodeForegroundService.start(this@MainActivity)
@@ -52,33 +136,15 @@ class MainActivity : ComponentActivity() {
}
}
}
setContent {
OpenClawTheme {
Surface(modifier = Modifier) {
RootScreen(viewModel = viewModel)
}
}
}
}
override fun onStart() {
super.onStart()
viewModel.setForeground(true)
}
override fun onStop() {
viewModel.setForeground(false)
super.onStop()
}
override fun onNewIntent(intent: android.content.Intent) {
super.onNewIntent(intent)
setIntent(intent)
handleAssistantIntent(intent)
}
private fun handleAssistantIntent(intent: android.content.Intent?) {
/**
* Routes assistant/app-action intents into ViewModel state without recreating the activity.
*/
private fun handleAssistantIntent(
viewModel: MainViewModel,
intent: Intent?,
) {
parseHomeDestinationIntent(intent)?.let { destination ->
viewModel.requestHomeDestination(destination)
return
@@ -87,3 +153,23 @@ class MainActivity : ComponentActivity() {
viewModel.handleAssistantLaunch(request)
}
}
@Composable
private fun StartupSurface() {
Surface(
modifier = Modifier.fillMaxSize(),
color = Color.Black,
contentColor = Color.White,
) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center,
) {
Text(
text = "OPENCLAW",
fontSize = 22.sp,
fontWeight = FontWeight.Medium,
)
}
}
}

View File

@@ -4,6 +4,8 @@ import ai.openclaw.app.chat.ChatMessage
import ai.openclaw.app.chat.ChatPendingToolCall
import ai.openclaw.app.chat.ChatSessionEntry
import ai.openclaw.app.chat.OutgoingAttachment
import ai.openclaw.app.gateway.DeviceAuthStore
import ai.openclaw.app.gateway.DeviceIdentityStore
import ai.openclaw.app.gateway.GatewayEndpoint
import ai.openclaw.app.gateway.GatewayUpdateAvailableSummary
import ai.openclaw.app.node.CameraCaptureManager
@@ -14,6 +16,7 @@ import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
@@ -21,7 +24,11 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
/**
* UI-facing bridge that exposes NodeRuntime and preference state as Compose-friendly StateFlows.
*/
@OptIn(ExperimentalCoroutinesApi::class)
class MainViewModel(
app: Application,
@@ -29,7 +36,11 @@ class MainViewModel(
private val nodeApp = app as NodeApp
private val prefs = nodeApp.prefs
private val runtimeRef = MutableStateFlow<NodeRuntime?>(null)
private var foreground = true
@Volatile private var foreground = false
@Volatile private var runtimeStartupQueued = false
private val _requestedHomeDestination = MutableStateFlow<HomeDestination?>(null)
val requestedHomeDestination: StateFlow<HomeDestination?> = _requestedHomeDestination
private val _startOnboardingAtGatewaySetup = MutableStateFlow(false)
@@ -39,6 +50,9 @@ class MainViewModel(
private val _pendingAssistantAutoSend = MutableStateFlow<String?>(null)
val pendingAssistantAutoSend: StateFlow<String?> = _pendingAssistantAutoSend
/**
* Lazily starts NodeRuntime and preserves the current foreground bit across startup.
*/
private fun ensureRuntime(): NodeRuntime {
runtimeRef.value?.let { return it }
val runtime = nodeApp.ensureRuntime()
@@ -47,6 +61,22 @@ class MainViewModel(
return runtime
}
/**
* Starts the node runtime off the main thread so fresh installs can render
* the shell before encrypted prefs, device identity, and gateway setup warm up.
*/
private fun queueRuntimeStartup() {
if (runtimeRef.value != null || runtimeStartupQueued) return
runtimeStartupQueued = true
viewModelScope.launch(Dispatchers.Default) {
runCatching { ensureRuntime() }
runtimeStartupQueued = false
}
}
/**
* Adapts a runtime StateFlow to a stable ViewModel StateFlow before runtime startup.
*/
private fun <T> runtimeState(
initial: T,
selector: (NodeRuntime) -> StateFlow<T>,
@@ -82,6 +112,7 @@ class MainViewModel(
val isConnected: StateFlow<Boolean> = runtimeState(initial = false) { it.isConnected }
val isNodeConnected: StateFlow<Boolean> = runtimeState(initial = false) { it.nodeConnected }
val statusText: StateFlow<String> = runtimeState(initial = "Offline") { it.statusText }
val gatewayConnectionProblem: StateFlow<GatewayConnectionProblem?> = runtimeState(initial = null) { it.gatewayConnectionProblem }
val serverName: StateFlow<String?> = runtimeState(initial = null) { it.serverName }
val remoteAddress: StateFlow<String?> = runtimeState(initial = null) { it.remoteAddress }
val gatewayVersion: StateFlow<String?> = runtimeState(initial = null) { it.gatewayVersion }
@@ -139,6 +170,7 @@ class MainViewModel(
val gatewayBootstrapToken: StateFlow<String> = prefs.gatewayBootstrapToken
val onboardingCompleted: StateFlow<Boolean> = prefs.onboardingCompleted
val canvasDebugStatusEnabled: StateFlow<Boolean> = prefs.canvasDebugStatusEnabled
val installedAppsSharingEnabled: StateFlow<Boolean> = prefs.installedAppsSharingEnabled
val speakerEnabled: StateFlow<Boolean> = prefs.speakerEnabled
val voiceCaptureMode: StateFlow<VoiceCaptureMode> = runtimeState(initial = VoiceCaptureMode.Off) { it.voiceCaptureMode }
val micEnabled: StateFlow<Boolean> = runtimeState(initial = false) { it.micEnabled }
@@ -170,12 +202,6 @@ class MainViewModel(
val chatSessions: StateFlow<List<ChatSessionEntry>> = runtimeState(initial = emptyList()) { it.chatSessions }
val pendingRunCount: StateFlow<Int> = runtimeState(initial = 0) { it.pendingRunCount }
init {
if (prefs.onboardingCompleted.value) {
ensureRuntime()
}
}
val canvas: CanvasController
get() = ensureRuntime().canvas
@@ -185,6 +211,9 @@ class MainViewModel(
val sms: SmsManager
get() = ensureRuntime().sms
/**
* Attaches Activity-owned permission and lifecycle seams after runtime initialization.
*/
fun attachRuntimeUi(
owner: LifecycleOwner,
permissionRequester: PermissionRequester,
@@ -195,15 +224,15 @@ class MainViewModel(
runtime.sms.attachPermissionRequester(permissionRequester)
}
/**
* Starts runtime on foreground entry only after onboarding has completed.
*/
fun setForeground(value: Boolean) {
foreground = value
val runtime =
if (value && prefs.onboardingCompleted.value) {
ensureRuntime()
} else {
runtimeRef.value
}
runtime?.setForeground(value)
if (value && prefs.onboardingCompleted.value) {
queueRuntimeStartup()
}
runtimeRef.value?.setForeground(value)
}
fun setDisplayName(value: String) {
@@ -254,10 +283,54 @@ class MainViewModel(
prefs.setGatewayPassword(value)
}
fun resetGatewaySetupAuth() {
ensureRuntime().resetGatewaySetupAuth()
/** Clears setup credentials without starting the runtime just to discard first-run pairing auth. */
private fun resetGatewaySetupAuth() {
runtimeRef.value?.resetGatewaySetupAuth() ?: resetGatewaySetupAuthWithoutRuntime()
}
private fun resetGatewaySetupAuthWithoutRuntime() {
prefs.clearGatewaySetupAuth()
val deviceId = DeviceIdentityStore(nodeApp).loadOrCreate().deviceId
val deviceAuthStore = DeviceAuthStore(prefs)
deviceAuthStore.clearToken(deviceId, "node")
deviceAuthStore.clearToken(deviceId, "operator")
}
fun saveGatewayConfigAndConnect(
host: String,
port: Int,
tls: Boolean,
token: String,
bootstrapToken: String,
password: String,
resetSetupAuth: Boolean,
) {
// Gateway pairing touches encrypted prefs, identity files, and sockets; keep
// the whole sequence off the Compose thread so retries cannot trigger ANRs.
viewModelScope.launch(Dispatchers.Default) {
if (resetSetupAuth) {
resetGatewaySetupAuth()
}
prefs.setManualEnabled(true)
prefs.setManualHost(host)
prefs.setManualPort(port)
prefs.setManualTls(tls)
prefs.setGatewayBootstrapToken(bootstrapToken)
prefs.setGatewayToken(token)
prefs.setGatewayPassword(password)
ensureRuntime()
.connect(
GatewayEndpoint.manual(host = host, port = port),
NodeRuntime.GatewayConnectAuth(
token = token.ifEmpty { null },
bootstrapToken = bootstrapToken.ifEmpty { null },
password = password.ifEmpty { null },
),
)
}
}
/** Marks onboarding complete and starts the runtime before UI observes connected-state flows. */
fun setOnboardingCompleted(value: Boolean) {
if (value) {
ensureRuntime()
@@ -265,13 +338,17 @@ class MainViewModel(
prefs.setOnboardingCompleted(value)
}
/** Re-enters gateway setup after disconnecting and clearing one-time setup credentials. */
fun pairNewGateway() {
runtimeRef.value?.disconnect()
resetGatewaySetupAuth()
_startOnboardingAtGatewaySetup.value = true
prefs.setOnboardingCompleted(false)
viewModelScope.launch(Dispatchers.Default) {
runtimeRef.value?.disconnect()
resetGatewaySetupAuth()
prefs.setOnboardingCompleted(false)
_startOnboardingAtGatewaySetup.value = true
}
}
/** Acknowledges the one-shot request that opens onboarding at the gateway setup step. */
fun clearGatewaySetupStartRequest() {
_startOnboardingAtGatewaySetup.value = false
}
@@ -280,6 +357,10 @@ class MainViewModel(
prefs.setCanvasDebugStatusEnabled(value)
}
fun setInstalledAppsSharingEnabled(value: Boolean) {
ensureRuntime().setInstalledAppsSharingEnabled(value)
}
fun setNotificationForwardingEnabled(value: Boolean) {
ensureRuntime().setNotificationForwardingEnabled(value)
}
@@ -315,6 +396,7 @@ class MainViewModel(
ensureRuntime().setVoiceScreenActive(active)
}
/** Routes assistant intents into chat, either as a draft or queued auto-send prompt. */
fun handleAssistantLaunch(request: AssistantLaunchRequest) {
_requestedHomeDestination.value = HomeDestination.Chat
if (request.autoSend) {
@@ -359,13 +441,25 @@ class MainViewModel(
}
fun refreshGatewayConnection() {
ensureRuntime().refreshGatewayConnection()
viewModelScope.launch(Dispatchers.Default) {
ensureRuntime().refreshGatewayConnection()
}
}
fun startGatewayDiscovery() {
queueRuntimeStartup()
}
fun connect(endpoint: GatewayEndpoint) {
ensureRuntime().connect(endpoint)
}
fun connectInBackground(endpoint: GatewayEndpoint) {
viewModelScope.launch(Dispatchers.Default) {
ensureRuntime().connect(endpoint)
}
}
fun connect(
endpoint: GatewayEndpoint,
token: String?,

View File

@@ -3,11 +3,17 @@ package ai.openclaw.app
import android.app.Application
import android.os.StrictMode
/**
* Android Application singleton that owns process-wide secure prefs and lazy NodeRuntime startup.
*/
class NodeApp : Application() {
val prefs: SecurePrefs by lazy { SecurePrefs(this) }
@Volatile private var runtimeInstance: NodeRuntime? = null
/**
* Returns the single NodeRuntime for this process, creating it on first use.
*/
fun ensureRuntime(): NodeRuntime {
runtimeInstance?.let { return it }
return synchronized(this) {
@@ -15,6 +21,9 @@ class NodeApp : Application() {
}
}
/**
* Reads the runtime without forcing startup, used by lifecycle probes and services.
*/
fun peekRuntime(): NodeRuntime? = runtimeInstance
override fun onCreate() {

View File

@@ -19,6 +19,7 @@ import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
/** Foreground service that keeps the Android node connection and voice capture visible to the OS. */
class NodeForegroundService : Service() {
private val scope: CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
private var notificationJob: Job? = null
@@ -36,6 +37,8 @@ class NodeForegroundService : Service() {
stopSelf()
return
}
// Split connection and capture flows before combining so notification text
// can update without restarting runtime-owned connection work.
notificationJob =
scope.launch {
combine(
@@ -181,6 +184,7 @@ class NodeForegroundService : Service() {
private fun startForegroundWithTypes(notification: Notification) {
val serviceTypes = foregroundServiceTypesForVoiceMode(voiceCaptureMode)
if (didStartForeground) {
// Re-issue startForeground when Talk mode toggles so Android sees the microphone service type.
ServiceCompat.startForeground(this, NOTIFICATION_ID, notification, serviceTypes)
return
}
@@ -196,16 +200,19 @@ class NodeForegroundService : Service() {
private const val ACTION_SET_VOICE_CAPTURE_MODE = "ai.openclaw.app.action.SET_VOICE_CAPTURE_MODE"
private const val EXTRA_VOICE_CAPTURE_MODE = "ai.openclaw.app.extra.VOICE_CAPTURE_MODE"
/** Starts the persistent node foreground service from UI lifecycle code. */
fun start(context: Context) {
val intent = Intent(context, NodeForegroundService::class.java)
context.startForegroundService(intent)
}
/** Requests disconnect through the service action path so notification actions and UI share behavior. */
fun stop(context: Context) {
val intent = Intent(context, NodeForegroundService::class.java).setAction(ACTION_STOP)
context.startService(intent)
}
/** Updates Android's foreground-service type before voice capture mode changes require microphone access. */
fun setVoiceCaptureMode(
context: Context,
mode: VoiceCaptureMode,
@@ -215,6 +222,7 @@ class NodeForegroundService : Service() {
.setAction(ACTION_SET_VOICE_CAPTURE_MODE)
.putExtra(EXTRA_VOICE_CAPTURE_MODE, mode.name)
if (mode == VoiceCaptureMode.TalkMode) {
// Microphone foreground service type must be declared before Talk capture starts.
ContextCompat.startForegroundService(context, intent)
} else {
context.startService(intent)
@@ -223,6 +231,9 @@ class NodeForegroundService : Service() {
}
}
/**
* Foreground-service type mask required by Android for the current voice capture mode.
*/
internal fun foregroundServiceTypesForVoiceMode(mode: VoiceCaptureMode): Int {
val base = ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
return if (mode == VoiceCaptureMode.TalkMode) {
@@ -232,6 +243,9 @@ internal fun foregroundServiceTypesForVoiceMode(mode: VoiceCaptureMode): Int {
}
}
/**
* Compact notification suffix for voice state; kept pure for service-notification tests.
*/
internal fun voiceNotificationSuffix(
mode: VoiceCaptureMode,
manualMicEnabled: Boolean,
@@ -260,6 +274,7 @@ private fun String?.toVoiceCaptureMode(): VoiceCaptureMode =
it.name == this
} ?: VoiceCaptureMode.Off
/** Connection fields that drive foreground notification title/body text. */
private data class VoiceNotificationBase(
val status: String,
val server: String?,
@@ -267,6 +282,7 @@ private data class VoiceNotificationBase(
val mode: VoiceCaptureMode,
)
/** Voice capture fields that affect foreground-service type and suffix. */
private data class VoiceNotificationCapture(
val micEnabled: Boolean,
val micListening: Boolean,
@@ -274,6 +290,7 @@ private data class VoiceNotificationCapture(
val talkSpeaking: Boolean,
)
/** Aggregated notification state from runtime flows. */
private data class VoiceNotificationState(
val base: VoiceNotificationBase,
val capture: VoiceNotificationCapture,

View File

@@ -75,11 +75,36 @@ import kotlinx.serialization.json.buildJsonObject
import java.util.UUID
import java.util.concurrent.atomic.AtomicLong
/**
* Process runtime that owns gateway sessions, node command handlers, capture managers, and UI-facing state.
*/
data class GatewayConnectionProblem(
val code: String?,
val message: String,
val reason: String?,
val requestId: String?,
val recommendedNextStep: String?,
val pauseReconnect: Boolean,
val retryable: Boolean,
) {
val isPairingRequired: Boolean = code == "PAIRING_REQUIRED"
val canAutoRetry: Boolean =
isPairingRequired &&
(
retryable ||
!pauseReconnect ||
recommendedNextStep == "wait_then_retry"
)
}
class NodeRuntime(
context: Context,
val prefs: SecurePrefs = SecurePrefs(context.applicationContext),
private val tlsFingerprintProbe: suspend (String, Int) -> GatewayTlsProbeResult = ::probeGatewayTlsFingerprint,
) {
/**
* Authentication material supplied by setup/manual connect flows before gateway session routing.
*/
data class GatewayConnectAuth(
val token: String?,
val bootstrapToken: String?,
@@ -183,8 +208,6 @@ class NodeRuntime(
A2UIHandler(
canvas = canvas,
json = json,
getNodeCanvasHostUrl = { nodeSession.currentCanvasHostUrl() },
getOperatorCanvasHostUrl = { operatorSession.currentCanvasHostUrl() },
)
private val connectionManager: ConnectionManager =
@@ -201,6 +224,7 @@ class NodeRuntime(
callLogAvailable = { SensitiveFeatureConfig.callLogEnabled },
photosAvailable = { SensitiveFeatureConfig.photosEnabled },
hasRecordAudioPermission = { hasRecordAudioPermission() },
installedAppsSharingEnabled = { installedAppsSharingEnabled.value },
manualTls = { manualTls.value },
)
@@ -239,6 +263,7 @@ class NodeRuntime(
smsTelephonyAvailable = { sms.hasTelephonyFeature() },
callLogAvailable = { SensitiveFeatureConfig.callLogEnabled },
photosAvailable = { SensitiveFeatureConfig.photosEnabled },
installedAppsSharingEnabled = { installedAppsSharingEnabled.value },
debugBuild = { BuildConfig.DEBUG },
onCanvasA2uiPush = {
_canvasA2uiHydrated.value = true
@@ -246,11 +271,13 @@ class NodeRuntime(
_canvasRehydrateErrorText.value = null
},
onCanvasA2uiReset = { _canvasA2uiHydrated.value = false },
refreshCanvasHostUrl = { nodeSession.refreshCanvasHostUrl() },
motionActivityAvailable = { motionHandler.isActivityAvailable() },
motionPedometerAvailable = { motionHandler.isPedometerAvailable() },
)
/**
* Pending TLS trust decision when a gateway certificate is new or has changed.
*/
data class GatewayTrustPrompt(
val endpoint: GatewayEndpoint,
val fingerprintSha256: String,
@@ -277,11 +304,16 @@ class NodeRuntime(
private val _statusText = MutableStateFlow("Offline")
val statusText: StateFlow<String> = _statusText.asStateFlow()
private val _gatewayConnectionProblem = MutableStateFlow<GatewayConnectionProblem?>(null)
val gatewayConnectionProblem: StateFlow<GatewayConnectionProblem?> = _gatewayConnectionProblem.asStateFlow()
private val _pendingGatewayTrust = MutableStateFlow<GatewayTrustPrompt?>(null)
val pendingGatewayTrust: StateFlow<GatewayTrustPrompt?> = _pendingGatewayTrust.asStateFlow()
private val connectAttemptSeq = AtomicLong(0)
/**
* Builds the node-owned session key from stable device identity plus optional active agent.
*/
private fun resolveNodeMainSessionKey(agentId: String? = null): String {
val deviceId = identityStore.loadOrCreate().deviceId
return buildNodeMainSessionKey(deviceId, agentId)
@@ -399,6 +431,7 @@ class NodeRuntime(
identityStore = identityStore,
deviceAuthStore = deviceAuthStore,
onConnected = { hello ->
_gatewayConnectionProblem.value = null
operatorConnected = true
operatorStatusText = "Connected"
_serverName.value = hello.serverName
@@ -446,6 +479,7 @@ class NodeRuntime(
updateStatus()
micCapture.onGatewayConnectionChanged(false)
},
onConnectFailure = ::handleGatewayConnectFailure,
onEvent = { event, payloadJson ->
handleGatewayEvent(event, payloadJson)
},
@@ -457,6 +491,7 @@ class NodeRuntime(
identityStore = identityStore,
deviceAuthStore = deviceAuthStore,
onConnected = {
_gatewayConnectionProblem.value = null
_nodeConnected.value = true
nodeStatusText = "Connected"
didAutoRequestCanvasRehydrate = false
@@ -482,6 +517,7 @@ class NodeRuntime(
updateStatus()
showLocalCanvasOnDisconnect()
},
onConnectFailure = ::handleGatewayConnectFailure,
onEvent = { _, _ -> },
onInvoke = { req ->
invokeDispatcher.handleInvoke(req.command, req.paramsJson)
@@ -676,6 +712,23 @@ class NodeRuntime(
updateHomeCanvasState()
}
private fun handleGatewayConnectFailure(
error: GatewaySession.ErrorShape,
pauseReconnect: Boolean,
) {
val details = error.details
_gatewayConnectionProblem.value =
GatewayConnectionProblem(
code = details?.code ?: error.code,
message = error.message,
reason = details?.reason,
requestId = details?.requestId,
recommendedNextStep = details?.recommendedNextStep,
pauseReconnect = pauseReconnect || details?.pauseReconnect == true,
retryable = details?.retryable == true,
)
}
private fun resolveMainSessionKey(): String {
val trimmed = _mainSessionKey.value.trim()
return if (trimmed.isEmpty()) "main" else trimmed
@@ -841,6 +894,7 @@ class NodeRuntime(
fun setGatewayPassword(value: String) = prefs.setGatewayPassword(value)
/** Clears setup credentials plus paired device tokens for both Android gateway roles. */
fun resetGatewaySetupAuth() {
prefs.clearGatewaySetupAuth()
val deviceId = identityStore.loadOrCreate().deviceId
@@ -848,10 +902,12 @@ class NodeRuntime(
deviceAuthStore.clearToken(deviceId, "operator")
}
/** Persists onboarding state; callers decide whether runtime startup is needed first. */
fun setOnboardingCompleted(value: Boolean) = prefs.setOnboardingCompleted(value)
val lastDiscoveredStableId: StateFlow<String> = prefs.lastDiscoveredStableId
val canvasDebugStatusEnabled: StateFlow<Boolean> = prefs.canvasDebugStatusEnabled
val installedAppsSharingEnabled: StateFlow<Boolean> = prefs.installedAppsSharingEnabled
val notificationForwardingEnabled: StateFlow<Boolean> = prefs.notificationForwardingEnabled
val notificationForwardingMode: StateFlow<NotificationPackageFilterMode> =
prefs.notificationForwardingMode
@@ -917,6 +973,7 @@ class NodeRuntime(
updateHomeCanvasState()
}
/** Updates foreground state and triggers reconnect/presence behavior on app visibility changes. */
fun setForeground(value: Boolean) {
_isForeground.value = value
if (value) {
@@ -1006,6 +1063,8 @@ class NodeRuntime(
if (didAutoConnect) return
if (_isConnected.value) return
val endpoint = resolvePreferredGatewayEndpoint() ?: return
// Only attempt the stored preferred gateway once per runtime lifetime; users
// can still reconnect explicitly from the UI after a failed auto attempt.
didAutoConnect = true
connect(endpoint)
}
@@ -1060,6 +1119,12 @@ class NodeRuntime(
prefs.setCanvasDebugStatusEnabled(value)
}
fun setInstalledAppsSharingEnabled(value: Boolean) {
if (prefs.installedAppsSharingEnabled.value == value) return
prefs.setInstalledAppsSharingEnabled(value)
refreshNodeSurfaceAfterSharingChange()
}
fun setNotificationForwardingEnabled(value: Boolean) {
prefs.setNotificationForwardingEnabled(value)
}
@@ -1387,16 +1452,24 @@ class NodeRuntime(
}
fun refreshGatewayConnection() {
val endpoint =
connectedEndpoint ?: run {
_statusText.value = "Failed: no cached gateway endpoint"
return
}
val endpoint = connectedEndpoint
if (endpoint == null) {
resolvePreferredGatewayEndpoint()?.let(::connect)
?: run {
_statusText.value = "Failed: no saved gateway endpoint"
}
return
}
operatorStatusText = "Connecting…"
updateStatus()
connectWithAuth(endpoint = endpoint, auth = resolveGatewayConnectAuth(), reconnect = true)
}
private fun refreshNodeSurfaceAfterSharingChange() {
val endpoint = connectedEndpoint ?: return
connectWithAuth(endpoint = endpoint, auth = resolveGatewayConnectAuth(), reconnect = true)
}
private fun connectWithAuth(
endpoint: GatewayEndpoint,
auth: GatewayConnectAuth,
@@ -1496,6 +1569,7 @@ class NodeRuntime(
connectAttemptId: Long,
) {
if (!isCurrentConnectAttempt(connectAttemptId)) return
_gatewayConnectionProblem.value = null
connectedEndpoint = endpoint
operatorStatusText = "Connecting…"
nodeStatusText = "Connecting…"
@@ -1592,6 +1666,7 @@ class NodeRuntime(
stopActiveVoiceSession()
connectedEndpoint = null
activeGatewayAuth = null
_gatewayConnectionProblem.value = null
_pendingGatewayTrust.value = null
operatorSession.disconnect()
nodeSession.disconnect()
@@ -1830,7 +1905,7 @@ class NodeRuntime(
return
}
try {
val modelsRes = operatorSession.request("models.list", """{"view":"all"}""")
val modelsRes = operatorSession.request("models.list", "{}")
val modelsRoot = json.parseToJsonElement(modelsRes).asObjectOrNull()
_modelCatalog.value = parseGatewayModels(modelsRoot?.get("models") as? JsonArray)
@@ -2057,6 +2132,7 @@ class NodeRuntime(
id = id,
name = obj["name"].asStringOrNull()?.trim()?.takeIf { it.isNotEmpty() } ?: id,
provider = provider,
available = obj.optionalBoolean("available"),
supportsVision = "image" in inputTypes,
supportsAudio = "audio" in inputTypes,
supportsDocuments = "document" in inputTypes,
@@ -2673,6 +2749,7 @@ data class GatewayModelSummary(
val id: String,
val name: String,
val provider: String,
val available: Boolean?,
val supportsVision: Boolean,
val supportsAudio: Boolean,
val supportsDocuments: Boolean,
@@ -2855,6 +2932,15 @@ private fun JsonObject?.double(key: String): Double? = (this?.get(key) as? JsonP
private fun JsonObject?.boolean(key: String): Boolean = (this?.get(key) as? JsonPrimitive)?.content?.trim() == "true"
private fun JsonObject?.optionalBoolean(key: String): Boolean? =
(this?.get(key) as? JsonPrimitive)?.content?.trim()?.lowercase()?.let { value ->
when (value) {
"true" -> true
"false" -> false
else -> null
}
}
internal fun cronJobLastRunStatus(state: JsonObject?): String? =
state
.cronStatus("lastStatus")
@@ -2871,7 +2957,7 @@ fun providerDisplayName(provider: String): String =
when (provider.trim().lowercase()) {
"openai" -> "OpenAI"
"openrouter" -> "OpenRouter"
"openai-codex", "codex" -> "Codex"
"codex" -> "Codex"
"ollama", "ollama-local" -> "Ollama Local"
else ->
provider

View File

@@ -3,6 +3,7 @@ package ai.openclaw.app
import java.time.Instant
import java.time.ZoneId
/** Package-filter mode used before notification events are forwarded to the gateway. */
enum class NotificationPackageFilterMode(
val rawValue: String,
) {
@@ -11,10 +12,12 @@ enum class NotificationPackageFilterMode(
;
companion object {
/** Parses persisted filter mode text, defaulting to blocklist for safer forwarding. */
fun fromRawValue(raw: String?): NotificationPackageFilterMode = entries.firstOrNull { it.rawValue == raw?.trim()?.lowercase() } ?: Blocklist
}
}
/** Runtime policy used before forwarding notification events to a node session. */
internal data class NotificationForwardingPolicy(
val enabled: Boolean,
val mode: NotificationPackageFilterMode,
@@ -26,6 +29,7 @@ internal data class NotificationForwardingPolicy(
val sessionKey: String?,
)
/** Applies the operator-configured package allow/block list after trimming input. */
internal fun NotificationForwardingPolicy.allowsPackage(packageName: String): Boolean {
val normalized = packageName.trim()
if (normalized.isEmpty()) {
@@ -37,6 +41,7 @@ internal fun NotificationForwardingPolicy.allowsPackage(packageName: String): Bo
}
}
/** Returns true for both same-day and overnight quiet-hour windows. */
internal fun NotificationForwardingPolicy.isWithinQuietHours(
nowEpochMs: Long,
zoneId: ZoneId = ZoneId.systemDefault(),
@@ -64,12 +69,14 @@ internal fun NotificationForwardingPolicy.isWithinQuietHours(
private val localHourMinuteRegex = Regex("""^([01]\d|2[0-3]):([0-5]\d)$""")
/** Normalizes persisted or user-entered local times to strict HH:mm form. */
internal fun normalizeLocalHourMinute(raw: String): String? {
val trimmed = raw.trim()
val match = localHourMinuteRegex.matchEntire(trimmed) ?: return null
return "${match.groupValues[1]}:${match.groupValues[2]}"
}
/** Converts strict local HH:mm text to minutes since midnight for window checks. */
internal fun parseLocalHourMinute(raw: String): Int? {
val normalized = normalizeLocalHourMinute(raw) ?: return null
val parts = normalized.split(':')
@@ -78,11 +85,13 @@ internal fun parseLocalHourMinute(raw: String): Int? {
return hour * 60 + minute
}
/** Fixed-window limiter that bounds notification bursts per wall-clock minute. */
internal class NotificationBurstLimiter {
private val lock = Any()
private var windowStartMs: Long = -1L
private var eventsInWindow: Int = 0
/** Returns true when the current minute bucket still has forwarding capacity. */
fun allow(
nowEpochMs: Long,
maxEventsPerMinute: Int,
@@ -90,6 +99,8 @@ internal class NotificationBurstLimiter {
if (maxEventsPerMinute <= 0) {
return false
}
// Align all callers to the same minute bucket so concurrent notifications
// share the quota even when they arrive with slightly different timestamps.
val currentWindow = nowEpochMs - (nowEpochMs % 60_000L)
synchronized(lock) {
if (currentWindow != windowStartMs) {

View File

@@ -26,6 +26,9 @@ import kotlinx.coroutines.withTimeout
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.coroutines.resume
/**
* Serializes Android runtime-permission prompts behind coroutine-friendly request calls.
*/
class PermissionRequester internal constructor(
private val activity: ComponentActivity,
launcherFactory: ((Map<String, Boolean>) -> Unit) -> ActivityResultLauncher<Array<String>>,
@@ -50,8 +53,13 @@ class PermissionRequester internal constructor(
private val mutex = Mutex()
private val requestSlotsLock = Any()
private val mainHandler = Handler(Looper.getMainLooper())
// ActivityResult launchers cannot be registered after start; pre-register a small pool for nested UI flows.
private val launchers = List(4) { createPermissionRequestSlot(launcherFactory) }
/**
* Request missing Android runtime permissions and return the final grant state for every requested permission.
*/
suspend fun requestIfMissing(
permissions: List<String>,
timeoutMs: Long = 20_000,
@@ -93,6 +101,7 @@ class PermissionRequester internal constructor(
try {
withTimeout(timeoutMs) { deferred.await() }
} catch (err: TimeoutCancellationException) {
// Late ActivityResult callbacks are ignored by completePermissionRequest.
request.timedOut = true
throw err
}
@@ -130,6 +139,7 @@ class PermissionRequester internal constructor(
private fun reservePermissionRequestSlot(request: PendingPermissionRequest): PermissionRequestSlot =
synchronized(requestSlotsLock) {
// The outer mutex serializes normal callers; this guard catches accidental concurrent launchers in tests.
val slot = launchers.firstOrNull { it.request == null } ?: error("permission request launcher busy")
slot.request = request
slot
@@ -145,6 +155,7 @@ class PermissionRequester internal constructor(
slot.request = null
}
} ?: return
// Timed-out requests have already resumed callers with failure; ignore any late platform callback.
if (request.timedOut) return
request.deferred.complete(result)
}
@@ -186,6 +197,7 @@ class PermissionRequester internal constructor(
val actualObserver =
LifecycleEventObserver { _, event ->
if (event != Lifecycle.Event.ON_DESTROY) return@LifecycleEventObserver
// Do not resume a destroyed Activity with a positive result.
finish(false)
}
observer = actualObserver

View File

@@ -15,6 +15,9 @@ import kotlinx.serialization.json.JsonNull
import kotlinx.serialization.json.JsonPrimitive
import java.util.UUID
/**
* Reactive settings facade for Android node preferences and encrypted gateway credentials.
*/
class SecurePrefs(
context: Context,
private val securePrefsOverride: SharedPreferences? = null,
@@ -37,14 +40,18 @@ class SecurePrefs(
private const val notificationsForwardingMaxEventsPerMinuteKey =
"notifications.forwarding.maxEventsPerMinute"
private const val notificationsForwardingSessionKeyKey = "notifications.forwarding.sessionKey"
private const val installedAppsSharingEnabledKey = "device.apps.sharing.enabled"
private const val voiceMicEnabledKey = "voice.micEnabled"
}
private val appContext = context.applicationContext
private val json = Json { ignoreUnknownKeys = true }
// Non-secret UI/runtime preferences stay readable for migration and backup behavior.
private val plainPrefs: SharedPreferences =
appContext.getSharedPreferences(plainPrefsName, Context.MODE_PRIVATE)
// Gateway credentials and arbitrary secret strings are isolated behind EncryptedSharedPreferences.
private val masterKey by lazy {
MasterKey
.Builder(appContext)
@@ -109,6 +116,10 @@ class SecurePrefs(
MutableStateFlow(plainPrefs.getBoolean("canvas.debugStatusEnabled", false))
val canvasDebugStatusEnabled: StateFlow<Boolean> = _canvasDebugStatusEnabled
private val _installedAppsSharingEnabled =
MutableStateFlow(plainPrefs.getBoolean(installedAppsSharingEnabledKey, false))
val installedAppsSharingEnabled: StateFlow<Boolean> = _installedAppsSharingEnabled
private val _notificationForwardingEnabled =
MutableStateFlow(plainPrefs.getBoolean(notificationsForwardingEnabledKey, defaultNotificationForwardingEnabled))
val notificationForwardingEnabled: StateFlow<Boolean> = _notificationForwardingEnabled
@@ -247,12 +258,18 @@ class SecurePrefs(
_canvasDebugStatusEnabled.value = value
}
fun setInstalledAppsSharingEnabled(value: Boolean) {
plainPrefs.edit { putBoolean(installedAppsSharingEnabledKey, value) }
_installedAppsSharingEnabled.value = value
}
internal fun getNotificationForwardingPolicy(appPackageName: String): NotificationForwardingPolicy {
val modeRaw = plainPrefs.getString(notificationsForwardingModeKey, null)
val mode = NotificationPackageFilterMode.fromRawValue(modeRaw)
val configuredPackages = loadNotificationForwardingPackages()
val normalizedAppPackage = appPackageName.trim()
// Always block OpenClaw's own notifications in blocklist mode to prevent forwarding loops.
val defaultBlockedPackages =
if (normalizedAppPackage.isNotEmpty()) setOf(normalizedAppPackage) else emptySet()
@@ -311,6 +328,7 @@ class SecurePrefs(
.toSet()
.toList()
.sorted()
// Persist deterministic JSON so settings diffs and state restoration are stable.
val encoded = JsonArray(sanitized.map { JsonPrimitive(it) }).toString()
plainPrefs.edit { putString(notificationsForwardingPackagesKey, encoded) }
_notificationForwardingPackages.value = sanitized.toSet()
@@ -355,6 +373,7 @@ class SecurePrefs(
_notificationForwardingSessionKey.value = normalized
}
/** Loads manual or instance-scoped gateway token material from encrypted preferences. */
fun loadGatewayToken(): String? {
val manual =
_gatewayToken.value.trim().ifEmpty {
@@ -363,16 +382,19 @@ class SecurePrefs(
stored
}
if (manual.isNotEmpty()) return manual
// Per-instance tokens keep reused Android installs from sharing stale gateway auth.
val key = "gateway.token.${_instanceId.value}"
val stored = securePrefs.getString(key, null)?.trim()
return stored?.takeIf { it.isNotEmpty() }
}
/** Saves the paired gateway token under the current Android instance id. */
fun saveGatewayToken(token: String) {
val key = "gateway.token.${_instanceId.value}"
securePrefs.edit { putString(key, token.trim()) }
}
/** Loads the bootstrap token used during gateway setup and device-token handoff. */
fun loadGatewayBootstrapToken(): String? {
val key = "gateway.bootstrapToken.${_instanceId.value}"
val stored =
@@ -404,9 +426,11 @@ class SecurePrefs(
securePrefs.edit { putString(key, password.trim()) }
}
/** Clears manual/setup credentials without removing persisted role-specific device tokens. */
fun clearGatewaySetupAuth() {
val instanceId = _instanceId.value
securePrefs.edit {
// Clear both current manual credentials and instance-scoped setup credentials after pairing/reset.
remove("gateway.manual.token")
remove("gateway.token.$instanceId")
remove("gateway.bootstrapToken.$instanceId")
@@ -416,11 +440,13 @@ class SecurePrefs(
_gatewayBootstrapToken.value = ""
}
/** Loads the pinned gateway TLS fingerprint for a discovered/manual stable endpoint id. */
fun loadGatewayTlsFingerprint(stableId: String): String? {
val key = "gateway.tls.$stableId"
return plainPrefs.getString(key, null)?.trim()?.takeIf { it.isNotEmpty() }
}
/** Persists the gateway TLS fingerprint captured through TOFU or explicit trust. */
fun saveGatewayTlsFingerprint(
stableId: String,
fingerprint: String,
@@ -457,6 +483,7 @@ class SecurePrefs(
private fun loadOrCreateInstanceId(): String {
val existing = plainPrefs.getString("node.instanceId", null)?.trim()
if (!existing.isNullOrBlank()) return existing
// Instance id is not secret; it scopes local credentials and survives display-name changes.
val fresh = UUID.randomUUID().toString()
plainPrefs.edit { putString("node.instanceId", fresh) }
return fresh
@@ -466,6 +493,7 @@ class SecurePrefs(
val existing = plainPrefs.getString(displayNameKey, null)?.trim().orEmpty()
if (existing.isNotEmpty() && existing != "Android Node") return existing
// Replace the historical generic name with a device-specific default once.
val candidate = DeviceNames.bestDefaultNodeName(context).trim()
val resolved = candidate.ifEmpty { "Android Node" }
@@ -473,6 +501,7 @@ class SecurePrefs(
return resolved
}
/** Persists sanitized voice wake triggers and updates the reactive settings flow. */
fun setWakeWords(words: List<String>) {
val sanitized = WakeWords.sanitize(words, defaultWakeWords)
val encoded =
@@ -521,7 +550,7 @@ class SecurePrefs(
val raw = plainPrefs.getString(voiceWakeModeKey, null)
val resolved = VoiceWakeMode.fromRawValue(raw)
// Default ON (foreground) when unset.
// Default ON (foreground) when unset, but keep "always" opt-in through explicit settings.
if (raw.isNullOrBlank()) {
plainPrefs.edit { putString(voiceWakeModeKey, resolved.rawValue) }
}
@@ -533,6 +562,7 @@ class SecurePrefs(
val raw = plainPrefs.getString(locationModeKey, "off")
val resolved = LocationMode.fromRawValue(raw)
if (raw?.trim()?.lowercase() == "always") {
// Migrate old "always" configs to the current while-using contract.
plainPrefs.edit { putString(locationModeKey, resolved.rawValue) }
}
return resolved

View File

@@ -1,10 +1,12 @@
package ai.openclaw.app
/** Normalizes blank gateway session keys to the legacy main session alias. */
internal fun normalizeMainKey(raw: String?): String {
val trimmed = raw?.trim()
return if (!trimmed.isNullOrEmpty()) trimmed else "main"
}
/** Accepts only gateway session keys that can represent the main chat stream. */
internal fun isCanonicalMainSessionKey(raw: String?): Boolean {
val trimmed = raw?.trim().orEmpty()
if (trimmed.isEmpty()) return false
@@ -12,6 +14,7 @@ internal fun isCanonicalMainSessionKey(raw: String?): Boolean {
return trimmed.startsWith("agent:")
}
/** Extracts the agent id from canonical agent-scoped main session keys. */
internal fun resolveAgentIdFromMainSessionKey(raw: String?): String? {
val trimmed = raw?.trim().orEmpty()
if (!trimmed.startsWith("agent:")) return null
@@ -22,6 +25,7 @@ internal fun resolveAgentIdFromMainSessionKey(raw: String?): String? {
.ifEmpty { null }
}
/** Builds the node session key shape consumed by gateway chat and presence APIs. */
internal fun buildNodeMainSessionKey(
deviceId: String,
agentId: String?,

View File

@@ -1,5 +1,8 @@
package ai.openclaw.app
/**
* Persisted voice capture mode that controls foreground-service microphone requirements.
*/
enum class VoiceCaptureMode {
Off,
ManualMic,

View File

@@ -1,5 +1,8 @@
package ai.openclaw.app
/**
* Persisted wake-word mode; raw values are stored in secure preferences.
*/
enum class VoiceWakeMode(
val rawValue: String,
) {
@@ -9,6 +12,9 @@ enum class VoiceWakeMode(
;
companion object {
/**
* Invalid stored values fall back to foreground wake so hands-free behavior stays opt-in.
*/
fun fromRawValue(raw: String?): VoiceWakeMode = entries.firstOrNull { it.rawValue == raw?.trim()?.lowercase() } ?: Foreground
}
}

View File

@@ -1,11 +1,16 @@
package ai.openclaw.app
/**
* Wake-word parsing limits and sanitizers shared by settings and voice runtime paths.
*/
object WakeWords {
const val maxWords: Int = 32
const val maxWordLength: Int = 64
/** Splits comma-separated user input into non-empty wake-word entries. */
fun parseCommaSeparated(input: String): List<String> = input.split(",").map { it.trim() }.filter { it.isNotEmpty() }
/** Returns null when edited text normalizes to the current wake-word list. */
fun parseIfChanged(
input: String,
current: List<String>,
@@ -14,6 +19,7 @@ object WakeWords {
return if (parsed == current) null else parsed
}
/** Applies persisted-list bounds and falls back to defaults when all entries are empty. */
fun sanitize(
words: List<String>,
defaults: List<String>,

View File

@@ -61,12 +61,17 @@ class ChatController(
private val pendingRuns = mutableSetOf<String>()
private val pendingRunTimeoutJobs = ConcurrentHashMap<String, Job>()
// Preserve sent messages locally until chat.history includes the gateway-confirmed copy.
private val optimisticMessagesByRunId = LinkedHashMap<String, ChatMessage>()
private val pendingRunTimeoutMs = 120_000L
// Drops stale history responses after session switches or refresh races.
private val historyLoadGeneration = AtomicLong(0)
private var lastHealthPollAtMs: Long? = null
/** Clears transient chat state when the operator gateway session disconnects. */
fun onDisconnected(message: String) {
_healthOk.value = false
_errorText.value = null
@@ -78,6 +83,7 @@ class ChatController(
_sessionId.value = null
}
/** Loads a chat session, normalizing "main" to the current gateway-provided main session key. */
fun load(sessionKey: String) {
val key = normalizeRequestedSessionKey(sessionKey)
val generation = beginHistoryLoad(key, clearMessages = key != _sessionKey.value)
@@ -86,6 +92,7 @@ class ChatController(
}
}
/** Rebinds chat to a new canonical main session key after gateway hello/agent changes. */
fun applyMainSessionKey(mainSessionKey: String) {
val trimmed = mainSessionKey.trim()
if (trimmed.isEmpty()) return
@@ -108,6 +115,7 @@ class ChatController(
}
}
/** Refreshes current chat history and session list without clearing optimistic messages first. */
fun refresh() {
val key = normalizeRequestedSessionKey(_sessionKey.value)
val generation = beginHistoryLoad(key, clearMessages = false)
@@ -120,12 +128,14 @@ class ChatController(
scope.launch { fetchSessions(limit = limit) }
}
/** Persists the normalized thinking level used for subsequent chat sends. */
fun setThinkingLevel(thinkingLevel: String) {
val normalized = normalizeThinking(thinkingLevel)
if (normalized == _thinkingLevel.value) return
_thinkingLevel.value = normalized
}
/** Switches to another gateway chat session and starts a fresh history load. */
fun switchSession(sessionKey: String) {
val key = normalizeRequestedSessionKey(sessionKey)
if (key.isEmpty()) return
@@ -163,6 +173,7 @@ class ChatController(
return key
}
/** Queues a chat send without waiting for gateway acceptance. */
fun sendMessage(
message: String,
thinkingLevel: String,
@@ -177,6 +188,7 @@ class ChatController(
}
}
/** Sends a chat message and returns once the gateway accepts or rejects the request. */
suspend fun sendMessageAwaitAcceptance(
message: String,
thinkingLevel: String,
@@ -194,7 +206,7 @@ class ChatController(
val sessionKey = _sessionKey.value
val thinking = normalizeThinking(thinkingLevel)
// Optimistic user message.
// Optimistic user message keeps the composer responsive while chat.send and history refresh complete.
val userContent =
buildList {
add(ChatMessageContent(type = "text", text = text))
@@ -215,6 +227,7 @@ class ChatController(
role = "user",
content = userContent,
timestampMs = System.currentTimeMillis(),
idempotencyKey = "$runId:user",
)
optimisticMessagesByRunId[runId] = optimisticMessage
_messages.value = _messages.value + optimisticMessage
@@ -257,6 +270,7 @@ class ChatController(
val res = session.request("chat.send", params.toString())
val actualRunId = parseRunId(res) ?: runId
if (actualRunId != runId) {
// Gateway may return a canonical run id; move all pending bookkeeping to that id.
optimisticMessagesByRunId[actualRunId] = optimisticMessagesByRunId.remove(runId) ?: optimisticMessage
clearPendingRun(runId)
armPendingRunTimeout(actualRunId)
@@ -274,6 +288,7 @@ class ChatController(
}
}
/** Sends best-effort abort requests for every currently pending gateway run. */
fun abort() {
val runIds =
synchronized(pendingRuns) {
@@ -296,6 +311,7 @@ class ChatController(
}
}
/** Applies gateway chat/agent stream events to local transcript and pending-run state. */
fun handleGatewayEvent(
event: String,
payloadJson: String?,
@@ -337,6 +353,7 @@ class ChatController(
)
if (!isCurrentHistoryLoad(sessionKey, _sessionKey.value, generation, historyLoadGeneration.get())) return
val history = parseHistory(historyJson, sessionKey = sessionKey, previousMessages = _messages.value)
prunePersistedOptimisticMessages(history.messages)
_messages.value = mergeOptimisticMessages(incoming = history.messages, optimistic = optimisticMessagesByRunId.values)
_sessionId.value = history.sessionId
_historyLoading.value = false
@@ -396,7 +413,7 @@ class ChatController(
val state = payload["state"].asStringOrNull()
when (state) {
"delta" -> {
// Only show streaming text for runs we initiated
// Only show streaming text for runs we initiated in this controller.
if (!isPending) return
val text = parseAssistantDeltaText(payload)
if (!text.isNullOrEmpty()) {
@@ -409,10 +426,8 @@ class ChatController(
}
if (runId != null) {
clearPendingRun(runId)
optimisticMessagesByRunId.remove(runId)
} else {
clearPendingRuns()
optimisticMessagesByRunId.clear()
clearPendingRuns(clearOptimisticMessages = false)
}
pendingToolCallsById.clear()
publishPendingToolCalls()
@@ -442,6 +457,7 @@ class ChatController(
sessionKey = currentSessionKey,
previousMessages = _messages.value,
)
prunePersistedOptimisticMessages(history.messages)
_messages.value = mergeOptimisticMessages(incoming = history.messages, optimistic = optimisticMessagesByRunId.values)
_sessionId.value = history.sessionId
history.thinkingLevel
@@ -548,12 +564,14 @@ class ChatController(
}
}
private fun clearPendingRuns() {
private fun clearPendingRuns(clearOptimisticMessages: Boolean = true) {
for ((_, job) in pendingRunTimeoutJobs) {
job.cancel()
}
pendingRunTimeoutJobs.clear()
optimisticMessagesByRunId.clear()
if (clearOptimisticMessages) {
optimisticMessagesByRunId.clear()
}
synchronized(pendingRuns) {
pendingRuns.clear()
_pendingRunCount.value = 0
@@ -565,6 +583,15 @@ class ChatController(
_messages.value = _messages.value.filterNot { it.id == message.id }
}
private fun prunePersistedOptimisticMessages(incoming: List<ChatMessage>) {
val retained =
retainUnmatchedOptimisticMessages(
incoming = incoming,
optimistic = optimisticMessagesByRunId.values,
).toSet()
optimisticMessagesByRunId.entries.removeAll { entry -> entry.value !in retained }
}
private fun parseHistory(
historyJson: String,
sessionKey: String,
@@ -579,13 +606,14 @@ class ChatController(
array.mapNotNull { item ->
val obj = item.asObjectOrNull() ?: return@mapNotNull null
val role = obj["role"].asStringOrNull() ?: return@mapNotNull null
val content = obj["content"].asArrayOrNull()?.mapNotNull(::parseChatMessageContent) ?: emptyList()
val content = parseChatMessageContents(obj)
val ts = obj["timestamp"].asLongOrNull()
ChatMessage(
id = UUID.randomUUID().toString(),
role = role,
content = content,
timestampMs = ts,
idempotencyKey = obj["idempotencyKey"].asStringOrNull(),
)
}
@@ -637,6 +665,9 @@ internal fun isCurrentHistoryLoad(
activeGeneration: Long,
): Boolean = requestedSessionKey == currentSessionKey && requestGeneration == activeGeneration
/**
* Convert gateway chat content parts into Android UI content parts.
*/
internal fun parseChatMessageContent(el: JsonElement): ChatMessageContent? {
val obj = el.asObjectOrNull() ?: return null
return when (obj["type"].asStringOrNull() ?: "text") {
@@ -658,11 +689,27 @@ internal fun parseChatMessageContent(el: JsonElement): ChatMessageContent? {
}
}
internal fun parseChatMessageContents(obj: JsonObject): List<ChatMessageContent> {
obj["content"].asArrayOrNull()?.let { content ->
return content.mapNotNull(::parseChatMessageContent)
}
obj["content"].asStringOrNull()?.let { text ->
return listOf(ChatMessageContent(type = "text", text = text))
}
obj["text"].asStringOrNull()?.let { text ->
return listOf(ChatMessageContent(type = "text", text = text))
}
return emptyList()
}
internal data class MainSessionState(
val currentSessionKey: String,
val appliedMainSessionKey: String,
)
/**
* Rewrite only the active "main" alias when the gateway publishes a new canonical main session key.
*/
internal fun applyMainSessionKey(
currentSessionKey: String,
appliedMainSessionKey: String,
@@ -680,6 +727,9 @@ internal fun applyMainSessionKey(
)
}
/**
* Keep Compose item identity stable across history refreshes by matching existing messages to incoming copies.
*/
internal fun reconcileMessageIds(
previous: List<ChatMessage>,
incoming: List<ChatMessage>,
@@ -710,26 +760,41 @@ internal fun mergeOptimisticMessages(
): List<ChatMessage> {
if (optimistic.isEmpty()) return incoming
val unmatchedIncoming = incoming.toMutableList()
val missingOptimistic =
optimistic.filter { message ->
val matchIndex =
unmatchedIncoming.indexOfFirst { incomingMessage ->
incomingMessageConsumesOptimistic(incomingMessage, message)
}
if (matchIndex >= 0) {
unmatchedIncoming.removeAt(matchIndex)
false
} else {
true
}
}
val missingOptimistic = retainUnmatchedOptimisticMessages(incoming = incoming, optimistic = optimistic)
if (missingOptimistic.isEmpty()) return incoming
return (incoming + missingOptimistic).sortedWith(compareBy<ChatMessage> { it.timestampMs ?: Long.MAX_VALUE }.thenBy { it.id })
}
internal fun retainUnmatchedOptimisticMessages(
incoming: List<ChatMessage>,
optimistic: Collection<ChatMessage>,
): List<ChatMessage> {
if (optimistic.isEmpty()) return emptyList()
val unmatchedIncoming = incoming.toMutableList()
return optimistic.filter { message ->
val matchIndex =
unmatchedIncoming.indexOfFirst { incomingMessage ->
incomingMessageConsumesOptimistic(incomingMessage, message)
}
if (matchIndex >= 0) {
unmatchedIncoming.removeAt(matchIndex)
false
} else {
true
}
}
}
/**
* Message identity used only for refresh reconciliation; it avoids exposing gateway ids as UI keys.
*/
internal fun messageIdentityKey(message: ChatMessage): String? {
val idempotencyKey = message.idempotencyKey?.trim().orEmpty()
if (idempotencyKey.isNotEmpty()) {
return listOf(message.role.trim().lowercase(), idempotencyKey).joinToString(separator = "|")
}
val contentKey = messageContentIdentityKey(message) ?: return null
val timestamp = message.timestampMs?.toString().orEmpty()
if (timestamp.isEmpty() && contentKey.isEmpty()) return null
@@ -742,6 +807,10 @@ private fun incomingMessageConsumesOptimistic(
incoming: ChatMessage,
optimistic: ChatMessage,
): Boolean {
val optimisticIdempotencyKey = optimistic.idempotencyKey?.trim().orEmpty()
if (optimisticIdempotencyKey.isNotEmpty()) {
return incoming.idempotencyKey?.trim() == optimisticIdempotencyKey
}
if (optimisticMessageIdentityKey(incoming) != optimisticMessageIdentityKey(optimistic)) return false
val incomingTimestamp = incoming.timestampMs ?: return false
val optimisticTimestamp = optimistic.timestampMs ?: return true

View File

@@ -1,12 +1,19 @@
package ai.openclaw.app.chat
/**
* Chat transcript item as delivered by gateway chat history and live chat events.
*/
data class ChatMessage(
val id: String,
val role: String,
val content: List<ChatMessageContent>,
val timestampMs: Long?,
val idempotencyKey: String? = null,
)
/**
* One content part in a chat message; binary parts carry base64 plus their MIME metadata.
*/
data class ChatMessageContent(
val type: String = "text",
val text: String? = null,
@@ -15,6 +22,9 @@ data class ChatMessageContent(
val base64: String? = null,
)
/**
* Tool call placeholder shown while a gateway run is still streaming.
*/
data class ChatPendingToolCall(
val toolCallId: String,
val name: String,
@@ -23,12 +33,18 @@ data class ChatPendingToolCall(
val isError: Boolean? = null,
)
/**
* Stable session selector row; [key] is the gateway session key used in chat requests.
*/
data class ChatSessionEntry(
val key: String,
val updatedAtMs: Long?,
val displayName: String? = null,
)
/**
* Snapshot of one chat session, including optional thinking level selected on the gateway.
*/
data class ChatHistory(
val sessionKey: String,
val sessionId: String?,
@@ -36,6 +52,9 @@ data class ChatHistory(
val messages: List<ChatMessage>,
)
/**
* User-selected attachment payload sent to the gateway as inline base64.
*/
data class OutgoingAttachment(
val type: String,
val mimeType: String,

View File

@@ -1,6 +1,10 @@
package ai.openclaw.app.gateway
/**
* Decoder for Bonjour DNS-SD service names returned with decimal byte escapes.
*/
object BonjourEscapes {
/** Decodes Bonjour DNS-SD decimal escapes while preserving ordinary UTF-8. */
fun decode(input: String): String {
if (input.isEmpty()) return input
@@ -15,6 +19,7 @@ object BonjourEscapes {
val value =
((d0.code - '0'.code) * 100) + ((d1.code - '0'.code) * 10) + (d2.code - '0'.code)
if (value in 0..255) {
// Bonjour escape bytes are decimal octets, not Unicode code points.
bytes.add(value.toByte())
i += 4
continue

View File

@@ -1,6 +1,10 @@
package ai.openclaw.app.gateway
/**
* Canonical device-auth payload builder shared with gateway verification rules.
*/
internal object DeviceAuthPayload {
/** Builds the canonical v3 auth string signed by device registration flows. */
fun buildV3(
deviceId: String,
clientId: String,
@@ -32,6 +36,7 @@ internal object DeviceAuthPayload {
).joinToString("|")
}
/** Normalizes signed metadata fields without locale-sensitive lowercasing. */
internal fun normalizeMetadataField(value: String?): String {
val trimmed = value?.trim().orEmpty()
if (trimmed.isEmpty()) {

View File

@@ -5,6 +5,7 @@ import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
/** Stored gateway device-token material scoped by device id and role. */
data class DeviceAuthEntry(
val token: String,
val role: String,
@@ -18,17 +19,21 @@ private data class PersistedDeviceAuthMetadata(
val updatedAtMs: Long = 0L,
)
/** Persistence interface used by gateway pairing/session code for role tokens. */
interface DeviceAuthTokenStore {
/** Loads the stored token plus metadata for one device/role pair. */
fun loadEntry(
deviceId: String,
role: String,
): DeviceAuthEntry?
/** Loads only the bearer token when callers do not need scope metadata. */
fun loadToken(
deviceId: String,
role: String,
): String? = loadEntry(deviceId, role)?.token
/** Persists a role token and deterministic scope metadata under normalized keys. */
fun saveToken(
deviceId: String,
role: String,
@@ -36,12 +41,14 @@ interface DeviceAuthTokenStore {
scopes: List<String> = emptyList(),
)
/** Removes both token and metadata for the normalized device/role pair. */
fun clearToken(
deviceId: String,
role: String,
)
}
/** SecurePrefs-backed implementation of Android gateway device-token storage. */
class DeviceAuthStore(
private val prefs: SecurePrefs,
) : DeviceAuthTokenStore {
@@ -103,6 +110,8 @@ class DeviceAuthStore(
): String {
val normalizedDevice = normalizeDeviceId(deviceId)
val normalizedRole = normalizeRole(role)
// Keep key normalization shared with metadata keys so token and metadata
// are added/removed as one logical auth entry.
return "gateway.deviceToken.$normalizedDevice.$normalizedRole"
}
@@ -115,14 +124,19 @@ class DeviceAuthStore(
return "gateway.deviceTokenMeta.$normalizedDevice.$normalizedRole"
}
/** Normalizes device ids before they become encrypted preference key segments. */
private fun normalizeDeviceId(deviceId: String): String = deviceId.trim().lowercase()
/** Normalizes role names so node/operator token slots are stable across callers. */
private fun normalizeRole(role: String): String = role.trim().lowercase()
/** Stores scopes in deterministic order for display and restart comparisons. */
private fun normalizeScopes(scopes: List<String>): List<String> =
scopes
.map { it.trim() }
.filter { it.isNotEmpty() }
// Persist deterministic scope lists because they are displayed and may be
// compared across process restarts.
.distinct()
.sorted()
}

View File

@@ -7,6 +7,7 @@ import kotlinx.serialization.json.Json
import java.io.File
import java.security.MessageDigest
/** Persistent Ed25519 identity used to register this Android node with gateways. */
@Serializable
data class DeviceIdentity(
val deviceId: String,
@@ -15,6 +16,7 @@ data class DeviceIdentity(
val createdAtMs: Long,
)
/** Owns device identity generation, persistence, and auth payload signatures. */
class DeviceIdentityStore(
context: Context,
) {
@@ -23,6 +25,7 @@ class DeviceIdentityStore(
@Volatile private var cachedIdentity: DeviceIdentity? = null
/** Loads the persisted identity or creates one, repairing old device-id drift. */
@Synchronized
fun loadOrCreate(): DeviceIdentity {
cachedIdentity?.let { return it }
@@ -44,12 +47,13 @@ class DeviceIdentityStore(
return fresh
}
/** Signs gateway connect payload text with the persisted Ed25519 private key. */
fun signPayload(
payload: String,
identity: DeviceIdentity,
): String? =
try {
// Use BC lightweight API directly JCA provider registration is broken by R8
// Use BC lightweight API directly; R8 can break JCA provider registration.
val privateKeyBytes = Base64.decode(identity.privateKeyPkcs8Base64, Base64.DEFAULT)
val pkInfo =
org.bouncycastle.asn1.pkcs.PrivateKeyInfo
@@ -74,6 +78,7 @@ class DeviceIdentityStore(
null
}
/** Verifies a signature against the persisted public key for debug diagnostics. */
fun verifySelfSignature(
payload: String,
signatureBase64Url: String,
@@ -97,12 +102,16 @@ class DeviceIdentityStore(
false
}
/** Decodes gateway URL-safe base64 signatures, accepting unpadded input. */
private fun base64UrlDecode(input: String): ByteArray {
val normalized = input.replace('-', '+').replace('_', '/')
// Android Base64 expects padded input; gateway signatures are URL-safe
// unpadded strings.
val padded = normalized + "=".repeat((4 - normalized.length % 4) % 4)
return Base64.decode(padded, Base64.DEFAULT)
}
/** Returns the public key in the gateway's unpadded URL-safe base64 format. */
fun publicKeyBase64Url(identity: DeviceIdentity): String? =
try {
val raw = Base64.decode(identity.publicKeyRawBase64, Base64.DEFAULT)
@@ -142,7 +151,7 @@ class DeviceIdentityStore(
}
private fun generate(): DeviceIdentity {
// Use BC lightweight API directly to avoid JCA provider issues with R8
// Use BC lightweight API directly to avoid JCA provider issues with R8.
val kpGen =
org.bouncycastle.crypto.generators
.Ed25519KeyPairGenerator()
@@ -155,7 +164,8 @@ class DeviceIdentityStore(
val privKey = kp.private as org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters
val rawPublic = pubKey.encoded // 32 bytes
val deviceId = sha256Hex(rawPublic)
// Encode private key as PKCS8 for storage
// Store private key as PKCS8 so signPayload can parse the same persisted
// shape after app restarts and upgrades.
val privKeyInfo =
org.bouncycastle.crypto.util.PrivateKeyInfoFactory
.createPrivateKeyInfo(privKey)
@@ -168,6 +178,7 @@ class DeviceIdentityStore(
)
}
/** Re-derives the stable device id from the raw Ed25519 public key bytes. */
private fun deriveDeviceId(publicKeyRawBase64: String): String? =
try {
val raw = Base64.decode(publicKeyRawBase64, Base64.DEFAULT)

View File

@@ -49,6 +49,9 @@ import java.util.concurrent.Executors
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
/**
* Watches local DNS-SD and optional wide-area DNS-SD for reachable OpenClaw gateways.
*/
class GatewayDiscovery(
context: Context,
private val scope: CoroutineScope,
@@ -63,9 +66,13 @@ class GatewayDiscovery(
private val localById = ConcurrentHashMap<String, GatewayEndpoint>()
private val unicastById = ConcurrentHashMap<String, GatewayEndpoint>()
private val _gateways = MutableStateFlow<List<GatewayEndpoint>>(emptyList())
/** Current discovered gateway list, merged from local DNS-SD and optional wide-area DNS-SD. */
val gateways: StateFlow<List<GatewayEndpoint>> = _gateways.asStateFlow()
private val _statusText = MutableStateFlow("Searching…")
/** Short diagnostic text shown by connect UI while discovery is running. */
val statusText: StateFlow<String> = _statusText.asStateFlow()
private var unicastJob: Job? = null
@@ -130,6 +137,8 @@ class GatewayDiscovery(
val cm = connectivity ?: return
cm.activeNetwork?.let(availableNetworks::add)
try {
// Track all networks so wide-area DNS can prefer VPN/split-DNS answers
// even when Android's active network is not the VPN.
cm.registerNetworkCallback(NetworkRequest.Builder().build(), networkCallback)
} catch (_: Throwable) {
// ignore (best-effort)
@@ -168,6 +177,7 @@ class GatewayDiscovery(
private fun resolve(serviceInfo: NsdServiceInfo) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
// Android 14+ streams service updates; older releases require one-shot resolve calls.
resolveWithServiceInfoCallback(serviceInfo)
} else {
resolveLegacy(serviceInfo)
@@ -255,6 +265,7 @@ class GatewayDiscovery(
val tlsEnabled = txtBool(resolved, "gatewayTls")
val tlsFingerprint = txt(resolved, "gatewayTlsSha256")
val id = stableId(serviceName, "local.")
// Local NSD gives the socket host/port; TXT ports are retained as gateway metadata only.
localById[id] =
GatewayEndpoint(
stableId = id,
@@ -288,6 +299,7 @@ class GatewayDiscovery(
private fun publish() {
_gateways.value =
// Merge local and wide-area results deterministically for stable UI selection.
(localById.values + unicastById.values).sortedBy { it.name.lowercase() }
_statusText.value = buildStatusText()
}
@@ -369,6 +381,7 @@ class GatewayDiscovery(
?: resolveHostUnicast(targetFqdn)
?: continue
// Wide-area DNS-SD may put TXT in additional records; fall back to a direct TXT query.
val txtFromPtr =
recordsByName(ptrMsg, Section.ADDITIONAL)[keyName(instanceFqdn)]
.orEmpty()
@@ -454,6 +467,7 @@ class GatewayDiscovery(
val system = queryViaSystemDns(query)
if (records(system, Section.ANSWER).any { it.type == type }) return system
// Android's DnsResolver can miss split-DNS answers; retry with dnsjava against network DNS servers.
val direct = createDirectResolver() ?: return system
return try {
val msg = direct.send(query)
@@ -548,6 +562,7 @@ class GatewayDiscovery(
val candidateNetworks =
buildList {
// Put VPN DNS first so Tailscale split-horizon names win over public DNS.
trackedNetworks(cm)
.firstOrNull { n ->
val caps = cm.getNetworkCapabilities(n) ?: return@firstOrNull false

View File

@@ -1,5 +1,6 @@
package ai.openclaw.app.gateway
/** Resolved gateway address and optional metadata discovered from Bonjour/manual entry. */
data class GatewayEndpoint(
val stableId: String,
val name: String,
@@ -13,6 +14,7 @@ data class GatewayEndpoint(
val tlsFingerprintSha256: String? = null,
) {
companion object {
/** Builds a stable manual endpoint key that survives display-name changes. */
fun manual(
host: String,
port: Int,

View File

@@ -4,6 +4,7 @@ import android.os.Build
import java.net.InetAddress
import java.util.Locale
/** Returns true only for loopback hosts safe to treat as local gateway origins. */
internal fun isLoopbackGatewayHost(
rawHost: String?,
allowEmulatorBridgeAlias: Boolean = isAndroidEmulatorRuntime(),
@@ -18,9 +19,12 @@ internal fun isLoopbackGatewayHost(
host = host.dropLast(1)
}
val zoneIndex = host.indexOf('%')
// Scoped IPv6 literals are not stable origin identifiers; reject them for
// loopback trust instead of guessing which interface the zone names.
if (zoneIndex >= 0) return false
if (host.isEmpty()) return false
if (host == "localhost") return true
// Android emulator maps host loopback through this bridge alias.
if (allowEmulatorBridgeAlias && host == "10.0.2.2") return true
parseIpv4Address(host)?.let { ipv4 ->
@@ -44,6 +48,7 @@ internal fun isLoopbackGatewayHost(
return isMappedIpv4 && address[12] == 127.toByte()
}
/** Allows cleartext only for loopback and private/link-local network ranges. */
internal fun isLocalCleartextGatewayHost(
rawHost: String?,
allowEmulatorBridgeAlias: Boolean = isAndroidEmulatorRuntime(),
@@ -59,6 +64,8 @@ internal fun isLocalCleartextGatewayHost(
}
val zoneIndex = host.indexOf('%')
if (zoneIndex >= 0) {
// Link-local cleartext policy is about the address range; strip the
// interface zone before InetAddress parsing rejects otherwise valid hosts.
host = host.substring(0, zoneIndex)
}
if (host.isEmpty()) return false
@@ -107,6 +114,7 @@ private fun isAndroidEmulatorRuntime(): Boolean {
product.contains("simulator")
}
/** Parses strict dotted-quad IPv4, rejecting shorthand and out-of-range octets. */
private fun parseIpv4Address(host: String): ByteArray? {
val parts = host.split('.')
if (parts.size != 4) return null
@@ -119,4 +127,5 @@ private fun parseIpv4Address(host: String): ByteArray? {
return bytes
}
/** Cheap prefilter before handing potential IPv6 literals to InetAddress. */
private fun isIpv6LiteralChar(char: Char): Boolean = char in '0'..'9' || char in 'a'..'f' || char == ':' || char == '.'

View File

@@ -1,4 +1,7 @@
package ai.openclaw.app.gateway
/** Gateway protocol version emitted by Android node clients. */
const val GATEWAY_PROTOCOL_VERSION = 4
/** Oldest gateway protocol version this Android client can speak safely. */
const val GATEWAY_MIN_PROTOCOL_VERSION = 4

View File

@@ -33,6 +33,9 @@ import java.util.UUID
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicBoolean
/**
* Identity advertised during gateway connect; these fields become the device row users approve.
*/
data class GatewayClientInfo(
val id: String,
val displayName: String?,
@@ -44,6 +47,9 @@ data class GatewayClientInfo(
val modelIdentifier: String?,
)
/**
* Role, scopes, commands, and permission snapshot sent with the connect frame.
*/
data class GatewayConnectOptions(
val role: String,
val scopes: List<String>,
@@ -62,14 +68,22 @@ private enum class GatewayConnectAuthSource {
NONE,
}
/**
* Structured auth failure guidance from the gateway, preserved for reconnect and UI decisions.
*/
data class GatewayConnectErrorDetails(
val code: String?,
val canRetryWithDeviceToken: Boolean,
val recommendedNextStep: String?,
val pauseReconnect: Boolean? = null,
val reason: String? = null,
val requestId: String? = null,
val retryable: Boolean = false,
)
/**
* Server hello fields cached by the Android runtime after a successful connect.
*/
data class GatewayHelloSummary(
val serverName: String?,
val remoteAddress: String?,
@@ -99,12 +113,16 @@ private class GatewayConnectFailure(
val gatewayError: GatewaySession.ErrorShape,
) : IllegalStateException(gatewayError.message)
/**
* WebSocket RPC session that maintains gateway connection lifecycle, auth, events, and node invokes.
*/
class GatewaySession(
private val scope: CoroutineScope,
private val identityStore: DeviceIdentityStore,
private val deviceAuthStore: DeviceAuthTokenStore,
private val onConnected: (GatewayHelloSummary) -> Unit,
private val onDisconnected: (message: String) -> Unit,
private val onConnectFailure: (error: ErrorShape, pauseReconnect: Boolean) -> Unit = { _, _ -> },
private val onEvent: (event: String, payloadJson: String?) -> Unit,
private val onInvoke: (suspend (InvokeRequest) -> InvokeResult)? = null,
private val onTlsFingerprint: ((stableId: String, fingerprint: String) -> Unit)? = null,
@@ -112,8 +130,12 @@ class GatewaySession(
private companion object {
// Keep connect timeout above observed gateway unauthorized close on lower-end devices.
private const val CONNECT_RPC_TIMEOUT_MS = 12_000L
private val PAIRING_REQUEST_ID_PATTERN = Regex("^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$")
}
/**
* Gateway node.invoke request routed to Android command handlers.
*/
data class InvokeRequest(
val id: String,
val nodeId: String,
@@ -143,6 +165,9 @@ class GatewaySession(
val details: GatewayConnectErrorDetails? = null,
)
/**
* Structured RPC result used by callers that need error codes without exceptions.
*/
data class RpcResult(
val ok: Boolean,
val payloadJson: String?,
@@ -174,12 +199,15 @@ class GatewaySession(
@Volatile private var currentConnection: Connection? = null
// One reconnect can retry a shared-token mismatch by pairing the shared token with the stored device token.
@Volatile private var pendingDeviceTokenRetry = false
// Keep the mismatch retry single-shot so an invalid stored token cannot create an auth loop.
@Volatile private var deviceTokenRetryBudgetUsed = false
@Volatile private var reconnectPausedForAuthFailure = false
/** Starts or replaces the desired gateway connection and launches the reconnect loop. */
fun connect(
endpoint: GatewayEndpoint,
token: String?,
@@ -202,6 +230,7 @@ class GatewaySession(
connectionToClose?.closeQuietly()
}
/** Clears desired connection state, closes the socket, and stops reconnect attempts. */
fun disconnect() {
val jobToCancel: Job?
val connectionToClose: Connection?
@@ -225,6 +254,7 @@ class GatewaySession(
}
}
/** Forces the current socket closed so the loop reconnects to the current desired endpoint. */
fun reconnect() {
reconnectPausedForAuthFailure = false
currentConnection?.closeQuietly()
@@ -232,6 +262,7 @@ class GatewaySession(
fun currentCanvasHostUrl(): String? = pluginSurfaceUrls["canvas"]
/** Refreshes the canvas plugin surface URL and caches the normalized Android-reachable URL. */
suspend fun refreshCanvasHostUrl(timeoutMs: Long = 8_000): String? {
val refreshed =
refreshPluginSurfaceUrl(
@@ -247,6 +278,7 @@ class GatewaySession(
fun currentMainSessionKey(): String? = mainSessionKey
/** Sends a best-effort node.event and returns false instead of throwing on failure. */
suspend fun sendNodeEvent(
event: String,
payloadJson: String?,
@@ -287,6 +319,7 @@ class GatewaySession(
}
}
/** Sends node.event and preserves the gateway RPC error shape for callers that need diagnostics. */
suspend fun sendNodeEventDetailed(
event: String,
payloadJson: String?,
@@ -319,9 +352,11 @@ class GatewaySession(
): JsonObject =
buildJsonObject {
put("event", JsonPrimitive(event))
// Gateway node events carry payloadJSON as a string for compatibility with non-JSON payload producers.
put("payloadJSON", JsonPrimitive(payloadJson ?: "{}"))
}
/** Sends an RPC request and throws a code-prefixed exception when the gateway returns an error. */
suspend fun request(
method: String,
paramsJson: String?,
@@ -333,6 +368,7 @@ class GatewaySession(
throw IllegalStateException("${err?.code ?: "UNAVAILABLE"}: ${err?.message ?: "request failed"}")
}
/** Sends an RPC request and returns the structured success/error payload. */
suspend fun requestDetailed(
method: String,
paramsJson: String?,
@@ -349,6 +385,7 @@ class GatewaySession(
return RpcResult(ok = res.ok, payloadJson = res.payloadJson, error = res.error)
}
/** Sends an RPC request frame and reports errors asynchronously through [onError]. */
suspend fun sendRequestFrame(
method: String,
paramsJson: String?,
@@ -705,6 +742,7 @@ class GatewaySession(
persistIssuedDeviceToken(authSource, deviceId, authRole, deviceToken, authScopes)
}
if (shouldPersistBootstrapHandoffTokens(authSource)) {
// Bootstrap connects can mint role-specific device tokens; store only locally trusted handoffs.
authObj
?.get("deviceTokens")
.asArrayOrNull()
@@ -725,6 +763,7 @@ class GatewaySession(
val rawPluginSurfaceUrls = obj["pluginSurfaceUrls"].asObjectOrNull()
val normalizedPluginSurfaceUrls =
rawPluginSurfaceUrls?.mapNotNull { (surface, value) ->
// Canvas URLs may be loopback gateway metadata; normalize them to the reachable Android endpoint.
normalizeCanvasHostUrl(value.asStringOrNull(), endpoint, isTlsConnection = tls != null)
?.let { normalized -> surface to normalized }
} ?: emptyList()
@@ -797,6 +836,7 @@ class GatewaySession(
val connectScopes = resolveConnectScopes(selectedAuth)
val signedAtMs = System.currentTimeMillis()
// V3 signatures bind the auth token, nonce, role, and scopes so replayed connect frames fail.
val payload =
DeviceAuthPayload.buildV3(
deviceId = identity.deviceId,
@@ -887,6 +927,8 @@ class GatewaySession(
recommendedNextStep = it["recommendedNextStep"].asStringOrNull(),
pauseReconnect = it["pauseReconnect"].asBooleanOrNull(),
reason = it["reason"].asStringOrNull(),
requestId = normalizePairingRequestId(it["requestId"].asStringOrNull()),
retryable = it["retryable"].asBooleanOrNull() == true,
)
}
ErrorShape(code, msg, details)
@@ -912,6 +954,11 @@ class GatewaySession(
onEvent(event, payloadJson)
}
private fun normalizePairingRequestId(requestId: String?): String? {
val trimmed = requestId?.trim()?.takeIf { it.isNotEmpty() } ?: return null
return trimmed.takeIf { PAIRING_REQUEST_ID_PATTERN.matches(it) }
}
private suspend fun awaitConnectNonce(): String =
try {
withTimeout(2_000) { connectNonceDeferred.await() }
@@ -966,6 +1013,7 @@ class GatewaySession(
if (parsedPayload != null) {
put("payload", parsedPayload)
} else if (result.payloadJson != null) {
// Preserve malformed/non-object payloads as payloadJSON so the gateway can report handler output.
put("payloadJSON", JsonPrimitive(result.payloadJson))
}
result.error?.let { err ->
@@ -1024,10 +1072,14 @@ class GatewaySession(
} catch (err: Throwable) {
attempt += 1
onDisconnected("Gateway error: ${err.message ?: err::class.java.simpleName}")
if (
err is GatewayConnectFailure &&
shouldPauseReconnectAfterAuthFailure(err.gatewayError)
) {
val gatewayConnectFailure = err as? GatewayConnectFailure
val pauseForAuthFailure =
gatewayConnectFailure
?.let { shouldPauseReconnectAfterAuthFailure(it.gatewayError) } == true
if (gatewayConnectFailure != null) {
onConnectFailure(gatewayConnectFailure.gatewayError, pauseForAuthFailure)
}
if (pauseForAuthFailure) {
reconnectPausedForAuthFailure = true
continue
}
@@ -1189,6 +1241,7 @@ class GatewaySession(
if (!isTrustedDeviceRetryEndpoint(endpoint, tls)) return false
val detailCode = error.details?.code
val recommendedNextStep = error.details?.recommendedNextStep
// New gateways set canRetryWithDeviceToken; older builds expose equivalent string codes.
return error.details?.canRetryWithDeviceToken == true ||
recommendedNextStep == "retry_with_device_token" ||
detailCode == "AUTH_TOKEN_MISMATCH"
@@ -1213,10 +1266,13 @@ class GatewaySession(
tls: GatewayTlsParams?,
): Boolean {
if (isLocalCleartextGatewayHost(endpoint.host)) return true
// Retrying a stored device token alongside a shared token is only safe for
// remote gateways when an existing TLS pin already identifies the endpoint.
return tls?.expectedFingerprint?.trim()?.isNotEmpty() == true
}
}
/** Decides whether auth failures should stop reconnect churn until the user changes credentials. */
internal fun shouldPauseGatewayReconnectAfterAuthFailure(
error: GatewaySession.ErrorShape,
hasBootstrapToken: Boolean,
@@ -1249,6 +1305,7 @@ internal fun shouldPauseGatewayReconnectAfterAuthFailure(
else -> false
}
/** Builds the gateway WebSocket URL from endpoint authority and TLS policy. */
internal fun buildGatewayWebSocketUrl(
host: String,
port: Int,
@@ -1258,6 +1315,7 @@ internal fun buildGatewayWebSocketUrl(
return "$scheme://${formatGatewayAuthority(host, port)}"
}
/** Formats host/port for gateway URLs, including IPv6 bracket wrapping. */
internal fun formatGatewayAuthority(
host: String,
port: Int,
@@ -1308,6 +1366,7 @@ private fun parseJsonOrNull(payload: String): JsonElement? {
}
}
/** Keeps invoke-result ack waits inside the gateway-supported timeout window. */
internal fun resolveInvokeResultAckTimeoutMs(invokeTimeoutMs: Long?): Long {
val normalized = invokeTimeoutMs?.takeIf { it > 0L } ?: 15_000L
return normalized.coerceIn(15_000L, 120_000L)

View File

@@ -25,6 +25,7 @@ import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.TrustManagerFactory
import javax.net.ssl.X509TrustManager
/** TLS pinning inputs for a discovered or manually configured gateway endpoint. */
data class GatewayTlsParams(
val required: Boolean,
val expectedFingerprint: String?,
@@ -32,22 +33,26 @@ data class GatewayTlsParams(
val stableId: String,
)
/** SSL primitives installed into OkHttp when a gateway needs TLS pinning/TOFU. */
data class GatewayTlsConfig(
val sslSocketFactory: SSLSocketFactory,
val trustManager: X509TrustManager,
val hostnameVerifier: HostnameVerifier,
)
/** Distinguishes non-TLS endpoints from unreachable endpoints during probing. */
enum class GatewayTlsProbeFailure {
TLS_UNAVAILABLE,
ENDPOINT_UNREACHABLE,
}
/** Result of probing a gateway TLS endpoint for first-use fingerprint capture. */
data class GatewayTlsProbeResult(
val fingerprintSha256: String? = null,
val failure: GatewayTlsProbeFailure? = null,
)
/** Builds a TLS config that supports pinned fingerprints and trust-on-first-use. */
fun buildGatewayTlsConfig(
params: GatewayTlsParams?,
onStore: ((String) -> Unit)? = null,
@@ -82,6 +87,9 @@ fun buildGatewayTlsConfig(
return
}
if (params.allowTOFU) {
// Store only after the TLS stack presents a concrete server cert; the
// caller persists the fingerprint against the endpoint's stable id,
// and later connects must come back through the pinned branch above.
onStore?.invoke(fingerprint)
return
}
@@ -107,6 +115,7 @@ fun buildGatewayTlsConfig(
)
}
/** Connects with a probe trust manager that captures the presented cert hash. */
suspend fun probeGatewayTlsFingerprint(
host: String,
port: Int,
@@ -132,6 +141,7 @@ suspend fun probeGatewayTlsFingerprint(
) {
if (chain.isEmpty()) throw CertificateException("empty certificate chain")
fingerprintRef.set(sha256Hex(chain[0].encoded))
// Abort validation after capture; the probe is not deciding trust.
throw CertificateException("gateway TLS probe captured fingerprint")
}
@@ -154,7 +164,8 @@ suspend fun probeGatewayTlsFingerprint(
socket.sslParameters = params
}
} catch (_: Throwable) {
// ignore
// SNI is only a probe hint. IP literals and odd Bonjour names should
// still be probed instead of failing before the TLS handshake.
}
socket.startHandshake()
@@ -203,6 +214,7 @@ private fun sha256Hex(data: ByteArray): String {
return out.toString()
}
/** Normalizes user-visible fingerprint text to lowercase bare SHA-256 hex. */
fun normalizeGatewayTlsFingerprint(raw: String): String {
val stripped =
raw

View File

@@ -5,10 +5,15 @@ data class ParsedInvokeError(
val message: String,
val hadExplicitCode: Boolean,
) {
/** Gateway-facing form expected by UI and retry copy. */
val prefixedMessage: String
get() = "$code: $message"
}
/**
* Parses gateway invoke errors encoded as CODE: message while preserving legacy
* plain-text errors as UNAVAILABLE.
*/
fun parseInvokeErrorMessage(raw: String): ParsedInvokeError {
val trimmed = raw.trim()
if (trimmed.isEmpty()) {
@@ -30,6 +35,7 @@ fun parseInvokeErrorMessage(raw: String): ParsedInvokeError {
return ParsedInvokeError(code = "UNAVAILABLE", message = trimmed, hadExplicitCode = false)
}
/** Extracts an invoke error from a throwable without exposing blank messages. */
fun parseInvokeErrorFromThrowable(
err: Throwable,
fallbackMessage: String = "error",

View File

@@ -6,48 +6,36 @@ import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
/**
* Android bridge for applying gateway A2UI messages to the canvas WebView.
*/
class A2UIHandler(
private val canvas: CanvasController,
private val json: Json,
private val getNodeCanvasHostUrl: () -> String?,
private val getOperatorCanvasHostUrl: () -> String?,
) {
fun isTrustedCanvasActionUrl(rawUrl: String?): Boolean =
CanvasActionTrust.isTrustedCanvasActionUrl(
rawUrl = rawUrl,
trustedA2uiUrls = listOfNotNull(resolveA2uiHostUrl()),
)
fun isTrustedCanvasActionUrl(rawUrl: String?): Boolean = CanvasActionTrust.isTrustedCanvasActionUrl(rawUrl)
fun resolveA2uiHostUrl(): String? {
val nodeRaw = getNodeCanvasHostUrl()?.trim().orEmpty()
val operatorRaw = getOperatorCanvasHostUrl()?.trim().orEmpty()
val raw = if (nodeRaw.isNotBlank()) nodeRaw else operatorRaw
if (raw.isBlank()) return null
val base = raw.trimEnd('/')
return "$base/__openclaw__/a2ui/?platform=android"
}
suspend fun ensureA2uiReady(a2uiUrl: String): Boolean {
try {
val already = canvas.eval(a2uiReadyCheckJS)
if (already == "true") return true
} catch (_: Throwable) {
// ignore
suspend fun ensureA2uiReady(): Boolean {
if (canvas.currentUrl()?.trim() == CanvasActionTrust.localA2uiAssetUrl && isA2uiReady()) {
return true
}
canvas.navigate(a2uiUrl)
canvas.showLocalA2ui()
// The bundled A2UI host bootstraps asynchronously after navigation; poll briefly before failing the command.
repeat(50) {
try {
val ready = canvas.eval(a2uiReadyCheckJS)
if (ready == "true") return true
} catch (_: Throwable) {
// ignore
}
if (isA2uiReady()) return true
delay(120)
}
return false
}
private suspend fun isA2uiReady(): Boolean =
try {
canvas.eval(a2uiReadyCheckJS) == "true"
} catch (_: Throwable) {
false
}
fun decodeA2uiMessages(
command: String,
paramsJson: String?,
@@ -65,6 +53,7 @@ class A2UIHandler(
if (command == "canvas.a2ui.pushJSONL" || (!hasMessagesArray && jsonlField.isNotBlank())) {
val jsonl = jsonlField
if (jsonl.isBlank()) throw IllegalArgumentException("INVALID_REQUEST: jsonl required")
// JSONL keeps large A2UI streams model-friendly while still validating each message.
val messages =
jsonl
.lineSequence()
@@ -98,6 +87,7 @@ class A2UIHandler(
lineNumber: Int,
) {
if (msg.containsKey("createSurface")) {
// Android scaffold currently implements A2UI v0.8, not the v0.9 createSurface shape.
throw IllegalArgumentException(
"A2UI JSONL line $lineNumber: looks like A2UI v0.9 (`createSurface`). Canvas supports v0.8 messages only.",
)

View File

@@ -20,12 +20,18 @@ import java.util.TimeZone
private const val DEFAULT_CALENDAR_LIMIT = 50
/**
* Parsed calendar.events request; times are epoch millis for CalendarContract queries.
*/
internal data class CalendarEventsRequest(
val startMs: Long,
val endMs: Long,
val limit: Int,
)
/**
* Parsed calendar.add request before resolving the target Android calendar.
*/
internal data class CalendarAddRequest(
val title: String,
val startMs: Long,
@@ -37,6 +43,9 @@ internal data class CalendarAddRequest(
val calendarTitle: String?,
)
/**
* Normalized calendar event returned through gateway calendar commands.
*/
internal data class CalendarEventRecord(
val identifier: String,
val title: String,
@@ -47,6 +56,9 @@ internal data class CalendarEventRecord(
val calendarTitle: String?,
)
/**
* Injectable CalendarProvider facade for command tests and Android runtime access.
*/
internal interface CalendarDataSource {
fun hasReadPermission(context: Context): Boolean
@@ -78,6 +90,7 @@ private object SystemCalendarDataSource : CalendarDataSource {
): List<CalendarEventRecord> {
val resolver = context.contentResolver
val builder = CalendarContract.Instances.CONTENT_URI.buildUpon()
// Instances expands recurring events inside the requested time window.
ContentUris.appendId(builder, request.startMs)
ContentUris.appendId(builder, request.endMs)
val projection =
@@ -155,10 +168,12 @@ private object SystemCalendarDataSource : CalendarDataSource {
calendarTitle: String?,
): Long {
if (calendarId != null) {
// Explicit id wins over title/default selection and must already exist.
if (calendarExists(resolver, calendarId)) return calendarId
throw IllegalArgumentException("CALENDAR_NOT_FOUND: no calendar id $calendarId")
}
if (!calendarTitle.isNullOrEmpty()) {
// Title lookup is exact to avoid adding events to a similarly named calendar.
findCalendarByTitle(resolver, calendarTitle)?.let { return it }
throw IllegalArgumentException("CALENDAR_NOT_FOUND: no calendar named $calendarTitle")
}
@@ -209,6 +224,7 @@ private object SystemCalendarDataSource : CalendarDataSource {
projection,
"${CalendarContract.Calendars.VISIBLE}=1",
null,
// Prefer Android's primary visible calendar, then lowest id for deterministic fallback.
"${CalendarContract.Calendars.IS_PRIMARY} DESC, ${CalendarContract.Calendars._ID} ASC",
).use { cursor ->
if (cursor == null || !cursor.moveToFirst()) return null
@@ -342,6 +358,7 @@ class CalendarHandler private constructor(
if (paramsJson.isNullOrBlank()) {
val start = Instant.now()
val end = start.plus(7, ChronoUnit.DAYS)
// Default calendar read is a one-week window, not the full calendar store.
return CalendarEventsRequest(startMs = start.toEpochMilli(), endMs = end.toEpochMilli(), limit = DEFAULT_CALENDAR_LIMIT)
}
val params =
@@ -354,6 +371,7 @@ class CalendarHandler private constructor(
val end = parseISO((params["endISO"] as? JsonPrimitive)?.content)
val resolvedStart = start ?: Instant.now()
val resolvedEnd = end ?: resolvedStart.plus(7, ChronoUnit.DAYS)
// Keep model-driven calendar reads bounded.
val limit = ((params["limit"] as? JsonPrimitive)?.content?.toIntOrNull() ?: DEFAULT_CALENDAR_LIMIT).coerceIn(1, 500)
return CalendarEventsRequest(
startMs = resolvedStart.toEpochMilli(),
@@ -390,6 +408,7 @@ class CalendarHandler private constructor(
private fun parseISO(raw: String?): Instant? {
val value = raw?.trim().orEmpty()
if (value.isEmpty()) return null
// Gateway calendar payloads use UTC ISO-8601 instants for unambiguous Android storage.
return try {
Instant.parse(value)
} catch (_: Throwable) {

View File

@@ -41,19 +41,25 @@ import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.math.roundToInt
/**
* CameraX-backed capture service used by gateway camera commands.
*/
class CameraCaptureManager(
private val context: Context,
) {
/** Base64 JSON response for camera.snap after resize and JPEG budget enforcement. */
data class Payload(
val payloadJson: String,
)
/** Temporary MP4 response for camera.clip before CameraHandler validates invoke size. */
data class FilePayload(
val file: File,
val durationMs: Long,
val hasAudio: Boolean,
)
/** Camera device metadata exposed through camera.list. */
data class CameraDeviceInfo(
val id: String,
val name: String,
@@ -65,14 +71,19 @@ class CameraCaptureManager(
@Volatile private var permissionRequester: PermissionRequester? = null
/** Supplies the foreground Activity lifecycle required by CameraX use-case binding. */
fun attachLifecycleOwner(owner: LifecycleOwner) {
// CameraX binds use cases to an Activity lifecycle; background services cannot capture alone.
lifecycleOwner = owner
}
/** Supplies the Activity-owned permission launcher used by camera and microphone commands. */
fun attachPermissionRequester(requester: PermissionRequester) {
// Permission prompts must be launched by the Activity that owns the ActivityResult registry.
permissionRequester = requester
}
/** Lists CameraX devices with stable Camera2 ids where available. */
suspend fun listDevices(): List<CameraDeviceInfo> =
withContext(Dispatchers.Main) {
val provider = context.cameraProvider()
@@ -107,6 +118,7 @@ class CameraCaptureManager(
}
}
/** Captures one still image and returns a gateway-sized JPEG payload. */
suspend fun snap(paramsJson: String?): Payload =
withContext(Dispatchers.Main) {
ensureCameraPermission()
@@ -122,6 +134,7 @@ class CameraCaptureManager(
val selector = resolveCameraSelector(provider, facing, deviceId)
provider.unbindAll()
// Bind only the still capture use case; CameraX owns camera open/close through the lifecycle owner.
provider.bindToLifecycle(owner, selector, capture)
val (bytes, orientation) = capture.takeJpegWithExif(context.mainExecutor(), context.cacheDir)
@@ -179,6 +192,7 @@ class CameraCaptureManager(
}
}
/** Records a short MP4 clip into a temporary cache file for the caller to encode/delete. */
@SuppressLint("MissingPermission")
suspend fun clip(paramsJson: String?): FilePayload =
withContext(Dispatchers.Main) {
@@ -303,6 +317,7 @@ class CameraCaptureManager(
orientation: Int,
): Bitmap {
val matrix = Matrix()
// CameraX JPEG bytes keep sensor orientation in EXIF; normalize before resizing/encoding.
when (orientation) {
ExifInterface.ORIENTATION_ROTATE_90 -> matrix.postRotate(90f)
ExifInterface.ORIENTATION_ROTATE_180 -> matrix.postRotate(180f)
@@ -365,6 +380,7 @@ class CameraCaptureManager(
}
return CameraSelector
.Builder()
// CameraX selectors are filters over CameraInfo; pin by Camera2 id for stable device selection.
.addCameraFilter { infos -> infos.filter { cameraIdOrNull(it) == deviceId } }
.build()
}
@@ -419,7 +435,9 @@ private suspend fun Context.cameraProvider(): ProcessCameraProvider =
)
}
/** Returns (jpegBytes, exifOrientation) so caller can rotate the decoded bitmap. */
/**
* Returns JPEG bytes plus EXIF orientation so callers can normalize the decoded bitmap.
*/
private suspend fun ImageCapture.takeJpegWithExif(
executor: Executor,
tempDir: File,

View File

@@ -16,8 +16,14 @@ import kotlinx.serialization.json.put
internal const val CAMERA_CLIP_MAX_RAW_BYTES: Long = 18L * 1024L * 1024L
/**
* Raw MP4 size guard before base64 encoding the clip into a node.invoke response.
*/
internal fun isCameraClipWithinPayloadLimit(rawBytes: Long): Boolean = rawBytes in 0L..CAMERA_CLIP_MAX_RAW_BYTES
/**
* Gateway camera command adapter that adds HUD feedback and payload-size enforcement.
*/
class CameraHandler(
private val appContext: Context,
private val camera: CameraCaptureManager,
@@ -26,6 +32,7 @@ class CameraHandler(
private val triggerCameraFlash: () -> Unit,
private val invokeErrorFromThrowable: (err: Throwable) -> Pair<String, String>,
) {
/** Handles camera.list by exposing CameraX devices through gateway metadata. */
suspend fun handleList(_paramsJson: String?): GatewaySession.InvokeResult =
try {
val devices = camera.listDevices()
@@ -53,6 +60,7 @@ class CameraHandler(
GatewaySession.InvokeResult.error(code = code, message = message)
}
/** Handles camera.snap with HUD progress, flash feedback, and normalized invoke errors. */
suspend fun handleSnap(paramsJson: String?): GatewaySession.InvokeResult {
val logFile = if (BuildConfig.DEBUG) java.io.File(appContext.cacheDir, "camera_debug.log") else null
@@ -92,6 +100,7 @@ class CameraHandler(
}
}
/** Handles camera.clip and keeps external audio capture paused while camera audio is active. */
suspend fun handleClip(paramsJson: String?): GatewaySession.InvokeResult {
val clipLogFile = if (BuildConfig.DEBUG) java.io.File(appContext.cacheDir, "camera_debug.log") else null
@@ -124,6 +133,7 @@ class CameraHandler(
val rawBytes = filePayload.file.length()
if (!isCameraClipWithinPayloadLimit(rawBytes)) {
clipLog("payload too large: bytes=$rawBytes max=$CAMERA_CLIP_MAX_RAW_BYTES")
// Delete oversized clips before returning so cache files do not accumulate after failed invokes.
withContext(Dispatchers.IO) { filePayload.file.delete() }
showCameraHud("Clip too large", CameraHudKind.Error, 2400)
return GatewaySession.InvokeResult.error(
@@ -152,6 +162,7 @@ class CameraHandler(
clipLog("stack: ${err.stackTraceToString().take(2000)}")
return GatewaySession.InvokeResult.error(code = "UNAVAILABLE", message = err.message ?: "camera clip failed")
} finally {
// Prevent talk/transcription capture from competing with camera audio after every exit path.
if (includeAudio) externalAudioCaptureActive.value = false
}
}

View File

@@ -1,61 +1,21 @@
package ai.openclaw.app.node
import java.net.URI
/**
* Trust helper for WebView-originated canvas/A2UI actions.
*/
object CanvasActionTrust {
/** Local canvas scaffold is the only trusted file URL. */
const val scaffoldAssetUrl: String = "file:///android_asset/CanvasScaffold/scaffold.html"
fun isTrustedCanvasActionUrl(
rawUrl: String?,
trustedA2uiUrls: List<String>,
): Boolean {
/** Local bundled A2UI is the only action-capable A2UI host. */
const val localA2uiAssetUrl: String = "file:///android_asset/CanvasA2UI/index.html"
/** Accepts only app-owned bundled pages. Remote WebView content is render-only. */
fun isTrustedCanvasActionUrl(rawUrl: String?): Boolean {
val candidate = rawUrl?.trim().orEmpty()
if (candidate.isEmpty()) return false
if (candidate == scaffoldAssetUrl) return true
val candidateUri = parseUri(candidate) ?: return false
if (candidateUri.scheme.equals("file", ignoreCase = true)) {
return false
}
val normalizedCandidate = normalizeTrustedRemoteA2uiUri(candidateUri) ?: return false
return trustedA2uiUrls.any { trusted ->
matchesTrustedRemoteA2uiUrlExact(normalizedCandidate, trusted)
}
if (candidate == localA2uiAssetUrl) return true
return false
}
private fun matchesTrustedRemoteA2uiUrlExact(
candidateUri: URI,
trustedUrl: String,
): Boolean {
val trustedUri = parseUri(trustedUrl) ?: return false
val normalizedTrusted = normalizeTrustedRemoteA2uiUri(trustedUri) ?: return false
return candidateUri == normalizedTrusted
}
private fun normalizeTrustedRemoteA2uiUri(uri: URI): URI? {
// Keep Android trust normalization aligned with iOS ScreenController:
// exact remote URL match, scheme/host normalized, fragment ignored.
val scheme = uri.scheme?.lowercase() ?: return null
if (scheme != "http" && scheme != "https") return null
val host =
uri.host
?.trim()
?.takeIf { it.isNotEmpty() }
?.lowercase() ?: return null
return try {
URI(scheme, uri.userInfo, host, uri.port, uri.rawPath, uri.rawQuery, null)
} catch (_: Throwable) {
null
}
}
private fun parseUri(raw: String): URI? =
try {
URI(raw)
} catch (_: Throwable) {
null
}
}

View File

@@ -23,6 +23,9 @@ import org.json.JSONObject
import java.io.ByteArrayOutputStream
import kotlin.coroutines.resume
/**
* Owns the Android WebView canvas surface used by canvas and A2UI commands.
*/
class CanvasController {
enum class SnapshotFormat(
val rawValue: String,
@@ -45,7 +48,8 @@ class CanvasController {
private val _currentUrl = MutableStateFlow<String?>(null)
val currentUrl: StateFlow<String?> = _currentUrl.asStateFlow()
private val scaffoldAssetUrl = "file:///android_asset/CanvasScaffold/scaffold.html"
private val scaffoldAssetUrl = CanvasActionTrust.scaffoldAssetUrl
private val localA2uiAssetUrl = CanvasActionTrust.localA2uiAssetUrl
private fun clampJpegQuality(quality: Double?): Int {
val q = (quality ?: 0.82).coerceIn(0.1, 1.0)
@@ -60,19 +64,23 @@ class CanvasController {
return scale(maxWidth, scaledHeight)
}
/** Attaches the active WebView and replays state that may have arrived before the view existed. */
fun attach(webView: WebView) {
this.webView = webView
// Replay persisted state because WebView attachment can happen after gateway events arrive.
reload()
applyDebugStatus()
applyHomeCanvasState()
}
/** Detaches only the currently attached WebView instance. */
fun detach(webView: WebView) {
if (this.webView === webView) {
this.webView = null
}
}
/** Navigates the canvas to a remote URL or back to the bundled scaffold for blank/root input. */
fun navigate(url: String) {
val trimmed = url.trim()
this.url = if (trimmed.isBlank() || trimmed == "/") null else trimmed
@@ -80,6 +88,13 @@ class CanvasController {
reload()
}
/** Shows the app-owned A2UI renderer that is allowed to dispatch native actions. */
fun showLocalA2ui() {
this.url = localA2uiAssetUrl
_currentUrl.value = localA2uiAssetUrl
reload()
}
fun currentUrl(): String? = url
fun isDefaultCanvas(): Boolean = url == null
@@ -113,6 +128,7 @@ class CanvasController {
if (Looper.myLooper() == Looper.getMainLooper()) {
block(wv)
} else {
// WebView APIs must run on the main thread.
wv.post { block(wv) }
}
}
@@ -178,6 +194,7 @@ class CanvasController {
}
}
/** Evaluates JavaScript against the attached WebView on the main thread. */
suspend fun eval(javaScript: String): String =
withContext(Dispatchers.Main) {
val wv = webView ?: throw IllegalStateException("no webview")
@@ -206,6 +223,7 @@ class CanvasController {
}
}
/** Captures the WebView as PNG/JPEG base64 with optional width and quality bounds. */
suspend fun snapshotBase64(
format: SnapshotFormat,
quality: Double?,
@@ -246,17 +264,22 @@ class CanvasController {
}
companion object {
/**
* Parsed canvas.snapshot options used by invoke dispatch.
*/
data class SnapshotParams(
val format: SnapshotFormat,
val quality: Double?,
val maxWidth: Int?,
)
/** Parses canvas.navigate params and returns blank when the payload is missing or invalid. */
fun parseNavigateUrl(paramsJson: String?): String {
val obj = parseParamsObject(paramsJson) ?: return ""
return obj.string("url").trim()
}
/** Parses non-blank JavaScript from canvas.eval params. */
fun parseEvalJs(paramsJson: String?): String? {
val obj = parseParamsObject(paramsJson) ?: return null
val js = obj.string("javaScript").trim()
@@ -286,9 +309,11 @@ class CanvasController {
if (!obj.containsKey("quality")) return null
val q = obj.double("quality") ?: Double.NaN
if (!q.isFinite()) return null
// Keep JPEG quality inside encoder-safe bounds; PNG ignores it.
return q.coerceIn(0.1, 1.0)
}
/** Parses canvas.snapshot params using JPEG defaults and encoder-safe bounds. */
fun parseSnapshotParams(paramsJson: String?): SnapshotParams =
SnapshotParams(
format = parseSnapshotFormat(paramsJson),

View File

@@ -12,6 +12,9 @@ import ai.openclaw.app.gateway.isLocalCleartextGatewayHost
import ai.openclaw.app.gateway.isLoopbackGatewayHost
import android.os.Build
/**
* Builds gateway connect metadata from current Android permissions, settings, and device identity.
*/
class ConnectionManager(
private val prefs: SecurePrefs,
private val cameraEnabled: () -> Boolean,
@@ -25,9 +28,13 @@ class ConnectionManager(
private val callLogAvailable: () -> Boolean,
private val photosAvailable: () -> Boolean,
private val hasRecordAudioPermission: () -> Boolean,
private val installedAppsSharingEnabled: () -> Boolean,
private val manualTls: () -> Boolean,
) {
companion object {
/**
* Decide whether a discovered/manual endpoint must use pinned TLS or can stay local cleartext.
*/
internal fun resolveTlsParamsForEndpoint(
endpoint: GatewayEndpoint,
storedFingerprint: String?,
@@ -44,6 +51,7 @@ class ConnectionManager(
}
if (isManual) {
// Manual remote hosts default to TLS; only local manual hosts may honor the cleartext toggle.
if (!manualTlsEnabled && cleartextAllowedHost) return null
if (!stored.isNullOrBlank()) {
return GatewayTlsParams(
@@ -83,6 +91,7 @@ class ConnectionManager(
}
if (!cleartextAllowedHost) {
// Non-loopback discovered hosts require TLS even without TXT hints.
return GatewayTlsParams(
required = true,
expectedFingerprint = null,
@@ -107,13 +116,19 @@ class ConnectionManager(
voiceWakeEnabled = voiceWakeMode() != VoiceWakeMode.Off && hasRecordAudioPermission(),
motionActivityAvailable = motionActivityAvailable(),
motionPedometerAvailable = motionPedometerAvailable(),
installedAppsSharingEnabled = installedAppsSharingEnabled(),
debugBuild = BuildConfig.DEBUG,
)
/** Builds the gateway-advertised node.invoke command list from current permission and feature state. */
fun buildInvokeCommands(): List<String> = InvokeCommandRegistry.advertisedCommands(runtimeFlags())
/** Builds the gateway-advertised capability list from current permission and feature state. */
fun buildCapabilities(): List<String> = InvokeCommandRegistry.advertisedCapabilities(runtimeFlags())
/**
* Debug Android builds advertise a dev version so gateway logs do not look like release clients.
*/
fun resolvedVersionName(): String {
val versionName = BuildConfig.VERSION_NAME.trim().ifEmpty { "dev" }
return if (BuildConfig.DEBUG && !versionName.contains("dev", ignoreCase = true)) {
@@ -123,12 +138,16 @@ class ConnectionManager(
}
}
/** Human-readable Android device model used in gateway client metadata. */
fun resolveModelIdentifier(): String? =
listOfNotNull(Build.MANUFACTURER, Build.MODEL)
.joinToString(" ")
.trim()
.ifEmpty { null }
/**
* User-Agent used for gateway telemetry and troubleshooting.
*/
fun buildUserAgent(): String {
val version = resolvedVersionName()
val release =
@@ -139,6 +158,7 @@ class ConnectionManager(
return "OpenClawAndroid/$version (Android $releaseLabel; SDK ${Build.VERSION.SDK_INT})"
}
/** Client identity block shared by node and operator gateway sessions. */
fun buildClientInfo(
clientId: String,
clientMode: String,
@@ -154,6 +174,7 @@ class ConnectionManager(
modelIdentifier = resolveModelIdentifier(),
)
/** Connect options for the Android node session that exposes phone capabilities. */
fun buildNodeConnectOptions(): GatewayConnectOptions =
GatewayConnectOptions(
role = "node",
@@ -165,6 +186,7 @@ class ConnectionManager(
userAgent = buildUserAgent(),
)
/** Connect options for the Android operator session that drives approvals and UI actions. */
fun buildOperatorConnectOptions(): GatewayConnectOptions =
GatewayConnectOptions(
role = "operator",
@@ -181,6 +203,7 @@ class ConnectionManager(
userAgent = buildUserAgent(),
)
/** Resolves persisted TLS pin policy for a concrete gateway endpoint. */
fun resolveTlsParams(endpoint: GatewayEndpoint): GatewayTlsParams? {
val stored = prefs.loadGatewayTlsFingerprint(endpoint.stableId)
return resolveTlsParamsForEndpoint(endpoint, storedFingerprint = stored, manualTlsEnabled = manualTls())

View File

@@ -17,6 +17,9 @@ import kotlinx.serialization.json.put
private const val DEFAULT_CONTACTS_LIMIT = 25
/**
* Normalized Android contact row returned through the contacts commands.
*/
internal data class ContactRecord(
val identifier: String,
val displayName: String,
@@ -27,11 +30,17 @@ internal data class ContactRecord(
val emails: List<String>,
)
/**
* Parsed contacts.search request with bounded result count.
*/
internal data class ContactsSearchRequest(
val query: String?,
val limit: Int,
)
/**
* Parsed contacts.add request before ContentProviderOperation batching.
*/
internal data class ContactsAddRequest(
val givenName: String?,
val familyName: String?,
@@ -41,6 +50,9 @@ internal data class ContactsAddRequest(
val emails: List<String>,
)
/**
* Injectable ContactsProvider facade for command tests and Android runtime access.
*/
internal interface ContactsDataSource {
fun hasReadPermission(context: Context): Boolean
@@ -82,6 +94,7 @@ private object SystemContactsDataSource : ContactsDataSource {
selection = null
selectionArgs = null
} else {
// Escape wildcard characters so user text remains a substring search, not a LIKE pattern.
selection = "${ContactsContract.Contacts.DISPLAY_NAME_PRIMARY} LIKE ? ESCAPE '\\'"
selectionArgs = arrayOf("%${escapeLikePattern(request.query)}%")
}
@@ -119,6 +132,7 @@ private object SystemContactsDataSource : ContactsDataSource {
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null)
.build()
// Subsequent Data rows use back-reference 0 to attach to the RawContact inserted above.
if (!request.givenName.isNullOrEmpty() || !request.familyName.isNullOrEmpty() || !request.displayName.isNullOrEmpty()) {
operations +=
ContentProviderOperation
@@ -168,6 +182,7 @@ private object SystemContactsDataSource : ContactsDataSource {
rawContactUri.lastPathSegment?.toLongOrNull()
?: throw IllegalStateException("contact insert failed")
val contactId =
// Android returns the RawContact id; resolve the aggregate Contact id used by search APIs.
resolveContactIdForRawContact(resolver, rawContactId)
?: throw IllegalStateException("contact insert failed")
return loadContactRecord(
@@ -330,12 +345,16 @@ private object SystemContactsDataSource : ContactsDataSource {
}
}
/**
* Handles contacts.search and contacts.add gateway commands through Android ContactsProvider.
*/
class ContactsHandler private constructor(
private val appContext: Context,
private val dataSource: ContactsDataSource,
) {
constructor(appContext: Context) : this(appContext = appContext, dataSource = SystemContactsDataSource)
/** Searches contacts by optional display-name substring with bounded result count. */
fun handleContactsSearch(paramsJson: String?): GatewaySession.InvokeResult {
if (!dataSource.hasReadPermission(appContext)) {
return GatewaySession.InvokeResult.error(
@@ -369,6 +388,7 @@ class ContactsHandler private constructor(
}
}
/** Adds a local contact after validating that at least one user-visible field is present. */
fun handleContactsAdd(paramsJson: String?): GatewaySession.InvokeResult {
if (!dataSource.hasWritePermission(appContext)) {
return GatewaySession.InvokeResult.error(
@@ -418,6 +438,7 @@ class ContactsHandler private constructor(
null
} ?: return null
val query = (params["query"] as? JsonPrimitive)?.content?.trim()?.ifEmpty { null }
// Keep gateway-driven searches bounded even if the model asks for a large contact dump.
val limit = ((params["limit"] as? JsonPrimitive)?.content?.toIntOrNull() ?: DEFAULT_CONTACTS_LIMIT).coerceIn(1, 200)
return ContactsSearchRequest(query = query, limit = limit)
}
@@ -435,6 +456,7 @@ class ContactsHandler private constructor(
organizationName = (params["organizationName"] as? JsonPrimitive)?.content?.trim()?.ifEmpty { null },
displayName = (params["displayName"] as? JsonPrimitive)?.content?.trim()?.ifEmpty { null },
phoneNumbers = stringArray(params["phoneNumbers"] as? JsonArray),
// Store emails case-normalized so repeated model calls do not create casing-only duplicates.
emails = stringArray(params["emails"] as? JsonArray).map { it.lowercase() },
)
}
@@ -458,6 +480,7 @@ class ContactsHandler private constructor(
}
companion object {
/** Creates a handler with an injected contacts source for parser and payload tests. */
internal fun forTesting(
appContext: Context,
dataSource: ContactsDataSource,

View File

@@ -8,15 +8,21 @@ import kotlinx.serialization.json.JsonPrimitive
private const val LOGCAT_PATH = "/system/bin/logcat"
/**
* Debug-only node.invoke commands for Android cryptography and log diagnostics.
*/
class DebugHandler(
private val appContext: Context,
private val identityStore: DeviceIdentityStore,
) {
/**
* Runs an Ed25519 self-test and returns redacted diagnostics for debug builds.
*/
fun handleEd25519(): GatewaySession.InvokeResult {
if (!BuildConfig.DEBUG) {
return GatewaySession.InvokeResult.error(code = "UNAVAILABLE", message = "debug commands are disabled in release builds")
}
// Self-test Ed25519 signing and return diagnostic info
// Self-test Ed25519 signing without returning full private/public key material.
try {
val identity = identityStore.loadOrCreate()
val testPayload = "test|${identity.deviceId}|${System.currentTimeMillis()}"
@@ -25,15 +31,14 @@ class DebugHandler(
results.add("publicKeyRawBase64: ${identity.publicKeyRawBase64.take(20)}...")
results.add("privateKeyPkcs8Base64: ${identity.privateKeyPkcs8Base64.take(20)}...")
// Test publicKeyBase64Url
// Public-key URL encoding must match the gateway device-auth payload contract.
val pubKeyUrl = identityStore.publicKeyBase64Url(identity)
results.add("publicKeyBase64Url: ${pubKeyUrl ?: "NULL (FAILED)"}")
// Test signing
// Sign/verify through DeviceIdentityStore to catch provider and key-format failures together.
val signature = identityStore.signPayload(testPayload, identity)
results.add("signPayload: ${if (signature != null) "${signature.take(20)}... (OK)" else "NULL (FAILED)"}")
// Test self-verify
if (signature != null) {
val verifyOk = identityStore.verifySelfSignature(testPayload, signature, identity)
results.add("verifySelfSignature: $verifyOk")
@@ -74,6 +79,9 @@ class DebugHandler(
}
}
/**
* Returns a filtered logcat snapshot plus CameraX debug log for debug builds.
*/
fun handleLogs(): GatewaySession.InvokeResult {
if (!BuildConfig.DEBUG) {
return GatewaySession.InvokeResult.error(code = "UNAVAILABLE", message = "debug commands are disabled in release builds")
@@ -81,7 +89,7 @@ class DebugHandler(
val pid = android.os.Process.myPid()
val rt = Runtime.getRuntime()
val info = "v6 pid=$pid thread=${Thread.currentThread().name} free=${rt.freeMemory() / 1024}K total=${rt.totalMemory() / 1024}K max=${rt.maxMemory() / 1024}K uptime=${android.os.SystemClock.elapsedRealtime() / 1000}s sdk=${android.os.Build.VERSION.SDK_INT} device=${android.os.Build.MODEL}\n"
// Run logcat on current dispatcher thread (no withContext) with file redirect
// Capture only this process and redirect through a temp file to avoid blocking on pipe backpressure.
val logResult =
try {
val tmpFile = java.io.File(appContext.cacheDir, "debug_logs.txt")
@@ -123,6 +131,7 @@ class DebugHandler(
if (line.isBlank()) continue
if (spamPatterns.any { line.contains(it) }) continue
if (sb.length + line.length > 16000) {
// Keep debug.invoke responses small enough for the gateway WebSocket frame budget.
sb.append("\n(truncated)")
break
}
@@ -133,7 +142,7 @@ class DebugHandler(
} catch (e: Throwable) {
"(logcat error: ${e::class.java.simpleName}: ${e.message})"
}
// Also include camera debug log if it exists
// Camera capture writes a separate debug file because CameraX failures often happen off logcat's hot path.
val camLogFile = java.io.File(appContext.cacheDir, "camera_debug.log")
val camLog =
if (camLogFile.exists() && camLogFile.length() > 0) {

View File

@@ -8,6 +8,7 @@ import android.app.ActivityManager
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
@@ -24,13 +25,123 @@ import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put
import java.util.Locale
class DeviceHandler(
private const val DEFAULT_DEVICE_APPS_LIMIT = 100
private const val MAX_DEVICE_APPS_LIMIT = 200
private const val DEVICE_APPS_SYSTEM_FLAGS =
ApplicationInfo.FLAG_SYSTEM or ApplicationInfo.FLAG_UPDATED_SYSTEM_APP
internal fun isSystemDeviceApp(appInfo: ApplicationInfo): Boolean = (appInfo.flags and DEVICE_APPS_SYSTEM_FLAGS) != 0
internal data class DeviceAppEntry(
val label: String,
val packageName: String,
val system: Boolean,
val enabled: Boolean,
val launchable: Boolean,
)
internal interface DeviceAppSource {
fun listApps(includeNonLaunchable: Boolean): List<DeviceAppEntry>
}
private class AndroidDeviceAppSource(
private val appContext: Context,
) : DeviceAppSource {
override fun listApps(includeNonLaunchable: Boolean): List<DeviceAppEntry> {
val packageManager = appContext.packageManager
val launcherIntent = Intent(Intent.ACTION_MAIN).apply { addCategory(Intent.CATEGORY_LAUNCHER) }
val launchablePackages =
packageManager
.queryIntentActivities(launcherIntent, PackageManager.MATCH_ALL)
.asSequence()
.mapNotNull {
it.activityInfo
?.packageName
?.trim()
?.takeIf(String::isNotEmpty)
}.toSet()
val appInfos =
if (includeNonLaunchable) {
packageManager.getInstalledApplications(PackageManager.MATCH_ALL)
} else {
launchablePackages.mapNotNull { packageName ->
runCatching { packageManager.getApplicationInfo(packageName, 0) }.getOrNull()
}
}
return appInfos
.asSequence()
.mapNotNull { appInfo ->
appInfo.packageName
?.trim()
?.takeIf(String::isNotEmpty)
?.let { packageName ->
val label = packageManager.getApplicationLabel(appInfo).toString().trim()
DeviceAppEntry(
label = label.ifEmpty { packageName },
packageName = packageName,
system = isSystemDeviceApp(appInfo),
enabled = appInfo.enabled,
launchable = packageName in launchablePackages,
)
}
}.distinctBy { it.packageName }
.sortedWith(compareBy<DeviceAppEntry> { it.label.lowercase() }.thenBy { it.packageName })
.toList()
}
}
private data class DeviceAppsRequest(
val includeSystem: Boolean,
val includeDisabled: Boolean,
val includeNonLaunchable: Boolean,
val query: String?,
val limit: Int,
)
/**
* Gateway device command adapter for Android status, info, permission, and health snapshots.
*/
class DeviceHandler private constructor(
private val appContext: Context,
private val smsEnabled: Boolean = SensitiveFeatureConfig.smsEnabled,
private val callLogEnabled: Boolean = SensitiveFeatureConfig.callLogEnabled,
private val photosEnabled: Boolean = SensitiveFeatureConfig.photosEnabled,
private val appSource: DeviceAppSource = AndroidDeviceAppSource(appContext),
) {
constructor(
appContext: Context,
smsEnabled: Boolean = SensitiveFeatureConfig.smsEnabled,
callLogEnabled: Boolean = SensitiveFeatureConfig.callLogEnabled,
photosEnabled: Boolean = SensitiveFeatureConfig.photosEnabled,
) : this(
appContext = appContext,
smsEnabled = smsEnabled,
callLogEnabled = callLogEnabled,
photosEnabled = photosEnabled,
appSource = AndroidDeviceAppSource(appContext),
)
companion object {
internal fun forTesting(
appContext: Context,
appSource: DeviceAppSource,
smsEnabled: Boolean = SensitiveFeatureConfig.smsEnabled,
callLogEnabled: Boolean = SensitiveFeatureConfig.callLogEnabled,
photosEnabled: Boolean = SensitiveFeatureConfig.photosEnabled,
): DeviceHandler =
DeviceHandler(
appContext = appContext,
smsEnabled = smsEnabled,
callLogEnabled = callLogEnabled,
photosEnabled = photosEnabled,
appSource = appSource,
)
/**
* SMS is available only when the feature flag, telephony hardware, and at least one SMS permission align.
*/
internal fun hasAnySmsCapability(
smsEnabled: Boolean,
telephonyAvailable: Boolean,
@@ -38,6 +149,9 @@ class DeviceHandler(
smsReadGranted: Boolean,
): Boolean = smsEnabled && telephonyAvailable && (smsSendGranted || smsReadGranted)
/**
* Prompt only when Android can grant a missing SMS permission that this build can use.
*/
internal fun isSmsPromptable(
smsEnabled: Boolean,
telephonyAvailable: Boolean,
@@ -53,14 +167,60 @@ class DeviceHandler(
val temperatureC: Double?,
)
/** Returns battery, storage, network, and uptime state for device.status. */
fun handleDeviceStatus(_paramsJson: String?): GatewaySession.InvokeResult = GatewaySession.InvokeResult.ok(statusPayloadJson())
/** Returns stable Android hardware, OS, app, and locale metadata for device.info. */
fun handleDeviceInfo(_paramsJson: String?): GatewaySession.InvokeResult = GatewaySession.InvokeResult.ok(infoPayloadJson())
/** Returns permission and promptability state for Android capabilities exposed to the gateway. */
fun handleDevicePermissions(_paramsJson: String?): GatewaySession.InvokeResult = GatewaySession.InvokeResult.ok(permissionsPayloadJson())
/** Returns coarse device health for memory, power, thermal, battery, and security patch state. */
fun handleDeviceHealth(_paramsJson: String?): GatewaySession.InvokeResult = GatewaySession.InvokeResult.ok(healthPayloadJson())
fun handleDeviceApps(paramsJson: String?): GatewaySession.InvokeResult {
val request = parseDeviceAppsRequest(paramsJson)
val matchingApps =
appSource
.listApps(includeNonLaunchable = request.includeNonLaunchable)
.asSequence()
.filter { request.includeSystem || !it.system }
.filter { request.includeDisabled || it.enabled }
.filter { app ->
val query = request.query ?: return@filter true
app.label.contains(query, ignoreCase = true) || app.packageName.contains(query, ignoreCase = true)
}.toList()
val limitedApps = matchingApps.take(request.limit)
return GatewaySession.InvokeResult.ok(
buildJsonObject {
put("count", JsonPrimitive(limitedApps.size))
put("totalMatched", JsonPrimitive(matchingApps.size))
put("truncated", JsonPrimitive(matchingApps.size > limitedApps.size))
put("visibility", JsonPrimitive(if (request.includeNonLaunchable) "android-visible" else "launcher"))
put("includeSystem", JsonPrimitive(request.includeSystem))
put("includeDisabled", JsonPrimitive(request.includeDisabled))
put(
"apps",
buildJsonArray {
for (app in limitedApps) {
add(
buildJsonObject {
put("label", JsonPrimitive(app.label))
put("packageName", JsonPrimitive(app.packageName))
put("system", JsonPrimitive(app.system))
put("enabled", JsonPrimitive(app.enabled))
put("launchable", JsonPrimitive(app.launchable))
},
)
}
},
)
}.toString(),
)
}
private fun statusPayloadJson(): String {
val battery = readBatterySnapshot()
val powerManager = appContext.getSystemService(PowerManager::class.java)
@@ -71,6 +231,7 @@ class DeviceHandler(
val connectivity = appContext.getSystemService(ConnectivityManager::class.java)
val activeNetwork = connectivity?.activeNetwork
val caps = activeNetwork?.let { connectivity.getNetworkCapabilities(it) }
// elapsedRealtime is monotonic device uptime, not wall-clock time.
val uptimeSeconds = SystemClock.elapsedRealtime() / 1_000.0
return buildJsonObject {
@@ -154,6 +315,7 @@ class DeviceHandler(
if (!photosEnabled) {
false
} else if (Build.VERSION.SDK_INT >= 33) {
// Android 13 split media permissions; earlier versions use external storage.
hasPermission(Manifest.permission.READ_MEDIA_IMAGES)
} else {
hasPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
@@ -161,6 +323,7 @@ class DeviceHandler(
val motionGranted = hasPermission(Manifest.permission.ACTIVITY_RECOGNITION)
val notificationsGranted =
if (Build.VERSION.SDK_INT >= 33) {
// POST_NOTIFICATIONS exists only on Android 13+.
hasPermission(Manifest.permission.POST_NOTIFICATIONS)
} else {
true
@@ -295,6 +458,7 @@ class DeviceHandler(
if (currentNowUa == null || currentNowUa == Long.MIN_VALUE) {
null
} else {
// BatteryManager reports microamps; expose milliamps in the gateway payload.
currentNowUa.toDouble() / 1_000.0
}
@@ -348,7 +512,26 @@ class DeviceHandler(
}.toString()
}
private fun parseDeviceAppsRequest(paramsJson: String?): DeviceAppsRequest {
val params = parseJsonParamsObject(paramsJson)
val includeSystem = parseJsonBooleanFlag(params, "includeSystem") ?: false
val includeDisabled = parseJsonBooleanFlag(params, "includeDisabled") ?: false
val includeNonLaunchable = parseJsonBooleanFlag(params, "includeNonLaunchable") ?: false
val query = parseJsonString(params, "query")?.trim()?.takeIf { it.isNotEmpty() }
val limit =
(parseJsonInt(params, "limit") ?: DEFAULT_DEVICE_APPS_LIMIT)
.coerceIn(1, MAX_DEVICE_APPS_LIMIT)
return DeviceAppsRequest(
includeSystem = includeSystem,
includeDisabled = includeDisabled,
includeNonLaunchable = includeNonLaunchable,
query = query,
limit = limit,
)
}
private fun readBatterySnapshot(): BatterySnapshot {
// ACTION_BATTERY_CHANGED is sticky; registerReceiver(null, ...) reads the last system snapshot.
val intent = appContext.registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
val status =
intent?.getIntExtra(BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_UNKNOWN)
@@ -410,6 +593,7 @@ class DeviceHandler(
if (caps == null) return "unsatisfied"
return when {
caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) -> "satisfied"
// Internet without validation mirrors iOS "requiresConnection" for captive or unproven networks.
caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) -> "requiresConnection"
else -> "unsatisfied"
}
@@ -436,6 +620,7 @@ class DeviceHandler(
if (totalBytes <= 0L) return if (lowMemory) "critical" else "unknown"
if (lowMemory) return "critical"
val freeRatio = availableBytes.toDouble() / totalBytes.toDouble()
// Thresholds intentionally mirror coarse OS health labels instead of exact memory pressure.
return when {
freeRatio <= 0.05 -> "critical"
freeRatio <= 0.15 -> "high"

View File

@@ -21,11 +21,18 @@ import kotlinx.serialization.json.put
private const val MAX_NOTIFICATION_TEXT_CHARS = 512
private const val NOTIFICATIONS_CHANGED_EVENT = "notifications.changed"
/**
* Trims notification text and caps payload size before it enters gateway-visible state.
*/
internal fun sanitizeNotificationText(value: CharSequence?): String? {
val normalized = value?.toString()?.trim().orEmpty()
// Notification extras can include long previews; cap before sending over node events.
return normalized.take(MAX_NOTIFICATION_TEXT_CHARS).ifEmpty { null }
}
/**
* Stable notification snapshot entry exposed through the Android notifications command.
*/
data class DeviceNotificationEntry(
val key: String,
val packageName: String,
@@ -53,24 +60,36 @@ internal fun DeviceNotificationEntry.toJsonObject(): JsonObject =
channelId?.let { put("channelId", JsonPrimitive(it)) }
}
/**
* Listener state exposed to the gateway, including whether Android has connected the service.
*/
data class DeviceNotificationSnapshot(
val enabled: Boolean,
val connected: Boolean,
val notifications: List<DeviceNotificationEntry>,
)
/**
* Gateway-supported notification actions mapped to Android listener operations.
*/
enum class NotificationActionKind {
Open,
Dismiss,
Reply,
}
/**
* Gateway action request; [key] must match Android's StatusBarNotification key.
*/
data class NotificationActionRequest(
val key: String,
val kind: NotificationActionKind,
val replyText: String? = null,
)
/**
* Normalized notification action result returned through node.invoke.
*/
data class NotificationActionResult(
val ok: Boolean,
val code: String? = null,
@@ -79,6 +98,9 @@ data class NotificationActionResult(
internal fun actionRequiresClearableNotification(kind: NotificationActionKind): Boolean = kind == NotificationActionKind.Dismiss
/**
* Process-local cache of active notifications mirrored from Android listener callbacks.
*/
private object DeviceNotificationStore {
private val lock = Any()
private var connected = false
@@ -109,6 +131,7 @@ private object DeviceNotificationStore {
synchronized(lock) {
connected = value
if (!value) {
// Android invalidates activeNotifications when the listener disconnects.
byKey.clear()
}
}
@@ -127,6 +150,9 @@ private object DeviceNotificationStore {
}
}
/**
* Android notification listener that mirrors notification state and executes gateway actions.
*/
class DeviceNotificationListenerService : NotificationListenerService() {
private val securePrefs by lazy { SecurePrefs(applicationContext) }
private val forwardingLimiter = NotificationBurstLimiter()
@@ -226,6 +252,7 @@ class DeviceNotificationListenerService : NotificationListenerService() {
if (policy.isWithinQuietHours(nowEpochMs = nowEpochMs)) {
return null
}
// Apply burst limits after package/quiet-hour filters so blocked notifications do not consume quota.
if (!forwardingLimiter.allow(nowEpochMs, policy.maxEventsPerMinute)) {
return null
}
@@ -288,6 +315,7 @@ class DeviceNotificationListenerService : NotificationListenerService() {
private fun serviceComponent(context: Context): ComponentName = ComponentName(context, DeviceNotificationListenerService::class.java)
/** Installs the node event sink used to emit filtered notification change events. */
fun setNodeEventSink(sink: ((event: String, payloadJson: String?) -> Unit)?) {
nodeEventSink = sink
}
@@ -299,6 +327,7 @@ class DeviceNotificationListenerService : NotificationListenerService() {
val hasNew = prefs.contains(recentPackagesPref)
val legacy = prefs.getString(legacyRecentPackagesPref, null)?.trim().orEmpty()
if (!hasNew && legacy.isNotEmpty()) {
// Keep recent package suggestions across the preference-key rename.
prefs.edit {
putString(recentPackagesPref, legacy)
remove(legacyRecentPackagesPref)
@@ -308,6 +337,7 @@ class DeviceNotificationListenerService : NotificationListenerService() {
}
}
/** Returns recent third-party packages seen by the listener for settings suggestions. */
fun recentPackages(context: Context): List<String> {
migrateLegacyRecentPackagesIfNeeded(context)
val prefs = recentPackagesPrefs(context)
@@ -319,22 +349,26 @@ class DeviceNotificationListenerService : NotificationListenerService() {
.distinct()
}
/** Checks whether Android has granted listener access to this service component. */
fun isAccessEnabled(context: Context): Boolean {
val manager = context.getSystemService(NotificationManager::class.java) ?: return false
return manager.isNotificationListenerAccessGranted(serviceComponent(context))
}
/** Reads the current mirrored notification snapshot without forcing service startup. */
fun snapshot(
context: Context,
enabled: Boolean = isAccessEnabled(context),
): DeviceNotificationSnapshot = DeviceNotificationStore.snapshot(enabled = enabled)
/** Asks Android to rebind the listener after settings grant access but callbacks have not arrived. */
fun requestServiceRebind(context: Context) {
runCatching {
NotificationListenerService.requestRebind(serviceComponent(context))
}
}
/** Executes an open, dismiss, or reply action through the active listener instance. */
fun executeAction(
context: Context,
request: NotificationActionRequest,
@@ -376,6 +410,7 @@ class DeviceNotificationListenerService : NotificationListenerService() {
.map { it.trim() }
.filter { it.isNotEmpty() && it != normalized }
.take(recentPackagesLimit - 1)
// Most recent package first keeps settings suggestions useful without storing notification content.
val updated = listOf(normalized) + existing
prefs.edit { putString(recentPackagesPref, updated.joinToString(",")) }
}
@@ -449,6 +484,7 @@ class DeviceNotificationListenerService : NotificationListenerService() {
val action =
sbn.notification.actions
?.firstOrNull { candidate ->
// Android reply actions are identified by RemoteInput, not by a stable action title.
candidate.actionIntent != null && !candidate.remoteInputs.isNullOrEmpty()
}
?: return NotificationActionResult(

View File

@@ -9,6 +9,9 @@ import kotlinx.coroutines.launch
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray
/**
* Handles gateway-originated events that need to update local Android preferences.
*/
class GatewayEventHandler(
private val scope: CoroutineScope,
private val prefs: SecurePrefs,
@@ -19,12 +22,14 @@ class GatewayEventHandler(
private var suppressWakeWordsSync = false
private var wakeWordsSyncJob: Job? = null
/** Applies gateway wake words locally without echoing the same change back to the gateway. */
fun applyWakeWordsFromGateway(words: List<String>) {
suppressWakeWordsSync = true
prefs.setWakeWords(words)
suppressWakeWordsSync = false
}
/** Debounces local wake-word edits before sending voicewake.set to the operator session. */
fun scheduleWakeWordsSyncIfNeeded() {
if (suppressWakeWordsSync) return
if (!isConnected()) return
@@ -44,6 +49,7 @@ class GatewayEventHandler(
}
}
/** Loads gateway wake words on connect so Android settings show server truth. */
suspend fun refreshWakeWordsFromGateway() {
if (!isConnected()) return
try {
@@ -57,6 +63,7 @@ class GatewayEventHandler(
}
}
/** Applies voicewake.changed event payloads emitted by the gateway. */
fun handleVoiceWakeChangedEvent(payloadJson: String?) {
if (payloadJson.isNullOrBlank()) return
try {

View File

@@ -16,6 +16,7 @@ import ai.openclaw.app.protocol.OpenClawSmsCommand
import ai.openclaw.app.protocol.OpenClawSystemCommand
import ai.openclaw.app.protocol.OpenClawTalkCommand
/** Runtime feature flags used to decide which node tools are advertised. */
data class NodeRuntimeFlags(
val cameraEnabled: Boolean,
val locationEnabled: Boolean,
@@ -27,9 +28,11 @@ data class NodeRuntimeFlags(
val voiceWakeEnabled: Boolean,
val motionActivityAvailable: Boolean,
val motionPedometerAvailable: Boolean,
val installedAppsSharingEnabled: Boolean,
val debugBuild: Boolean,
)
/** Per-command availability gates checked before advertising invoke methods. */
enum class InvokeCommandAvailability {
Always,
CameraEnabled,
@@ -41,9 +44,11 @@ enum class InvokeCommandAvailability {
PhotosAvailable,
MotionActivityAvailable,
MotionPedometerAvailable,
InstalledAppsSharingEnabled,
DebugBuild,
}
/** Per-capability availability gates for the node capabilities manifest. */
enum class NodeCapabilityAvailability {
Always,
CameraEnabled,
@@ -55,11 +60,13 @@ enum class NodeCapabilityAvailability {
MotionAvailable,
}
/** Capability entry reported to the gateway when its availability gate passes. */
data class NodeCapabilitySpec(
val name: String,
val availability: NodeCapabilityAvailability = NodeCapabilityAvailability.Always,
)
/** Invoke method entry advertised to gateway plus foreground routing metadata. */
data class InvokeCommandSpec(
val name: String,
val requiresForeground: Boolean = false,
@@ -67,6 +74,7 @@ data class InvokeCommandSpec(
)
object InvokeCommandRegistry {
/** Capabilities mirror gateway protocol ids and are filtered by device state. */
val capabilityManifest: List<NodeCapabilitySpec> =
listOf(
NodeCapabilitySpec(name = OpenClawCapability.Canvas.rawValue),
@@ -106,6 +114,7 @@ object InvokeCommandRegistry {
),
)
/** Complete Android node command catalog before runtime availability filtering. */
val all: List<InvokeCommandSpec> =
listOf(
InvokeCommandSpec(
@@ -186,6 +195,10 @@ object InvokeCommandRegistry {
InvokeCommandSpec(
name = OpenClawDeviceCommand.Health.rawValue,
),
InvokeCommandSpec(
name = OpenClawDeviceCommand.Apps.rawValue,
availability = InvokeCommandAvailability.InstalledAppsSharingEnabled,
),
InvokeCommandSpec(
name = OpenClawNotificationsCommand.List.rawValue,
),
@@ -240,8 +253,10 @@ object InvokeCommandRegistry {
private val byNameInternal: Map<String, InvokeCommandSpec> = all.associateBy { it.name }
/** Finds the command metadata used by dispatch and advertised-method builders. */
fun find(command: String): InvokeCommandSpec? = byNameInternal[command]
/** Returns gateway capability ids the current Android device can actually serve. */
fun advertisedCapabilities(flags: NodeRuntimeFlags): List<String> =
capabilityManifest
.filter { spec ->
@@ -257,6 +272,7 @@ object InvokeCommandRegistry {
}
}.map { it.name }
/** Returns gateway invoke method ids available under current permissions/build flags. */
fun advertisedCommands(flags: NodeRuntimeFlags): List<String> =
all
.filter { spec ->
@@ -271,6 +287,7 @@ object InvokeCommandRegistry {
InvokeCommandAvailability.PhotosAvailable -> flags.photosAvailable
InvokeCommandAvailability.MotionActivityAvailable -> flags.motionActivityAvailable
InvokeCommandAvailability.MotionPedometerAvailable -> flags.motionPedometerAvailable
InvokeCommandAvailability.InstalledAppsSharingEnabled -> flags.installedAppsSharingEnabled
InvokeCommandAvailability.DebugBuild -> flags.debugBuild
}
}.map { it.name }

View File

@@ -15,12 +15,16 @@ import ai.openclaw.app.protocol.OpenClawSmsCommand
import ai.openclaw.app.protocol.OpenClawSystemCommand
import ai.openclaw.app.protocol.OpenClawTalkCommand
/** Runtime state for SMS search, split so permission prompts are not reported as hard unavailability. */
internal enum class SmsSearchAvailabilityReason {
Available,
PermissionRequired,
Unavailable,
}
/**
* Distinguish permanent SMS search unavailability from permission-gated search.
*/
internal fun classifySmsSearchAvailability(
readSmsAvailable: Boolean,
smsFeatureEnabled: Boolean,
@@ -53,6 +57,9 @@ internal fun smsSearchAvailabilityError(
)
}
/**
* Gateway node.invoke command router for Android-owned capabilities.
*/
class InvokeDispatcher(
private val canvas: CanvasController,
private val cameraHandler: CameraHandler,
@@ -78,13 +85,14 @@ class InvokeDispatcher(
private val smsTelephonyAvailable: () -> Boolean,
private val callLogAvailable: () -> Boolean,
private val photosAvailable: () -> Boolean,
private val installedAppsSharingEnabled: () -> Boolean,
private val debugBuild: () -> Boolean,
private val onCanvasA2uiPush: () -> Unit,
private val onCanvasA2uiReset: () -> Unit,
private val refreshCanvasHostUrl: suspend () -> String?,
private val motionActivityAvailable: () -> Boolean,
private val motionPedometerAvailable: () -> Boolean,
) {
/** Dispatches one gateway node.invoke command after foreground and availability gates pass. */
suspend fun handleInvoke(
command: String,
paramsJson: String?,
@@ -96,6 +104,7 @@ class InvokeDispatcher(
message = "INVALID_REQUEST: unknown command",
)
if (spec.requiresForeground && !isForeground()) {
// Canvas, camera, and screen-backed commands need an active Activity/WebView surface.
return GatewaySession.InvokeResult.error(
code = "NODE_BACKGROUND_UNAVAILABLE",
message = "NODE_BACKGROUND_UNAVAILABLE: canvas/camera/screen commands require foreground",
@@ -103,6 +112,7 @@ class InvokeDispatcher(
}
availabilityError(spec.availability)?.let { return it }
// Command strings come from OpenClawProtocolConstants; the registry above owns advertised availability.
return when (command) {
// Canvas commands
OpenClawCanvasCommand.Present.rawValue -> {
@@ -183,6 +193,7 @@ class InvokeDispatcher(
OpenClawDeviceCommand.Info.rawValue -> deviceHandler.handleDeviceInfo(paramsJson)
OpenClawDeviceCommand.Permissions.rawValue -> deviceHandler.handleDevicePermissions(paramsJson)
OpenClawDeviceCommand.Health.rawValue -> deviceHandler.handleDeviceHealth(paramsJson)
OpenClawDeviceCommand.Apps.rawValue -> deviceHandler.handleDeviceApps(paramsJson)
// Notifications command
OpenClawNotificationsCommand.List.rawValue -> notificationsHandler.handleNotificationsList(paramsJson)
@@ -230,23 +241,11 @@ class InvokeDispatcher(
}
private suspend fun withReadyA2ui(block: suspend () -> GatewaySession.InvokeResult): GatewaySession.InvokeResult {
var a2uiUrl =
a2uiHandler.resolveA2uiHostUrl()
?: refreshCanvasHostUrl().let { a2uiHandler.resolveA2uiHostUrl() }
?: return GatewaySession.InvokeResult.error(
code = "A2UI_HOST_NOT_CONFIGURED",
message = "A2UI_HOST_NOT_CONFIGURED: gateway did not advertise canvas host",
)
val readyOnFirstCheck = a2uiHandler.ensureA2uiReady(a2uiUrl)
if (!readyOnFirstCheck) {
refreshCanvasHostUrl()
a2uiUrl = a2uiHandler.resolveA2uiHostUrl() ?: a2uiUrl
if (!a2uiHandler.ensureA2uiReady(a2uiUrl)) {
return GatewaySession.InvokeResult.error(
code = "A2UI_HOST_UNAVAILABLE",
message = "A2UI_HOST_UNAVAILABLE: A2UI host not reachable",
)
}
if (!a2uiHandler.ensureA2uiReady()) {
return GatewaySession.InvokeResult.error(
code = "A2UI_HOST_UNAVAILABLE",
message = "A2UI_HOST_UNAVAILABLE: bundled A2UI host not reachable",
)
}
return block()
}
@@ -255,6 +254,7 @@ class InvokeDispatcher(
try {
block()
} catch (_: Throwable) {
// WebView calls throw when the Activity is backgrounded between the foreground check and execution.
GatewaySession.InvokeResult.error(
code = "NODE_BACKGROUND_UNAVAILABLE",
message = "NODE_BACKGROUND_UNAVAILABLE: canvas unavailable",
@@ -312,6 +312,7 @@ class InvokeDispatcher(
InvokeCommandAvailability.ReadSmsAvailable,
InvokeCommandAvailability.RequestableSmsSearchAvailable,
->
// SMS search may still be advertised as promptable; runtime invoke fails only on permanent unavailability.
smsSearchAvailabilityError(
readSmsAvailable = readSmsAvailable(),
smsFeatureEnabled = smsFeatureEnabled(),
@@ -335,6 +336,15 @@ class InvokeDispatcher(
message = "PHOTOS_UNAVAILABLE: photos not available on this build",
)
}
InvokeCommandAvailability.InstalledAppsSharingEnabled ->
if (installedAppsSharingEnabled()) {
null
} else {
GatewaySession.InvokeResult.error(
code = "INSTALLED_APPS_SHARING_DISABLED",
message = "INSTALLED_APPS_SHARING_DISABLED: enable Installed Apps in Settings",
)
}
InvokeCommandAvailability.DebugBuild ->
if (debugBuild()) {
null
@@ -347,12 +357,19 @@ class InvokeDispatcher(
}
}
/**
* Talk-mode command adapter implemented by the voice subsystem.
*/
interface TalkHandler {
/** Starts a push-to-talk capture session and keeps it open until stop or cancel. */
suspend fun handlePttStart(paramsJson: String?): GatewaySession.InvokeResult
/** Finishes the active push-to-talk capture and submits recognized speech. */
suspend fun handlePttStop(paramsJson: String?): GatewaySession.InvokeResult
/** Aborts the active push-to-talk capture without submitting speech. */
suspend fun handlePttCancel(paramsJson: String?): GatewaySession.InvokeResult
/** Runs a bounded one-shot push-to-talk capture. */
suspend fun handlePttOnce(paramsJson: String?): GatewaySession.InvokeResult
}

View File

@@ -4,6 +4,9 @@ import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt
/**
* Result of a JPEG compression attempt after quality and scale reductions.
*/
internal data class JpegSizeLimiterResult(
val bytes: ByteArray,
val width: Int,
@@ -11,7 +14,11 @@ internal data class JpegSizeLimiterResult(
val quality: Int,
)
/**
* Utility that searches quality/scale combinations until a JPEG fits a byte budget.
*/
internal object JpegSizeLimiter {
/** Compresses with the caller-provided encoder, reducing quality before image dimensions. */
fun compressToLimit(
initialWidth: Int,
initialHeight: Int,

View File

@@ -14,6 +14,9 @@ import kotlinx.coroutines.withTimeout
import java.time.Instant
import java.time.format.DateTimeFormatter
/**
* Android LocationManager-backed capture used by gateway location commands.
*/
class LocationCaptureManager(
private val context: Context,
) {
@@ -35,6 +38,7 @@ class LocationCaptureManager(
throw IllegalStateException("LOCATION_UNAVAILABLE: no location providers enabled")
}
// Prefer a recent cached fix before waking GPS/network providers.
val cached = bestLastKnown(manager, desiredProviders, maxAgeMs)
val location =
cached ?: requestCurrent(manager, desiredProviders, timeoutMs)
@@ -81,6 +85,7 @@ class LocationCaptureManager(
val candidates =
providers.mapNotNull { provider -> manager.getLastKnownLocation(provider) }
val freshest = candidates.maxByOrNull { it.time } ?: return null
// maxAgeMs is a caller contract; stale cached fixes force a live provider request.
if (maxAgeMs != null && now - freshest.time > maxAgeMs) return null
return freshest
}
@@ -102,6 +107,7 @@ class LocationCaptureManager(
val resolved =
providers.firstOrNull { manager.isProviderEnabled(it) }
?: throw IllegalStateException("LOCATION_UNAVAILABLE: no providers available")
// getCurrentLocation can return null; the handler maps timeout/null fixes to gateway error shapes.
val location =
withTimeout(timeoutMs.coerceAtLeast(1)) {
suspendCancellableCoroutine<Location?> { cont ->

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