Compare commits

..

3941 Commits

Author SHA1 Message Date
Peter Steinberger
59b0825d8c fix(memory-host): preserve core resolver exports in sdk shims 2026-04-28 11:54:02 +01:00
Peter Steinberger
b1b9f0094c fix(memory-host): keep sdk shim exports complete 2026-04-28 11:47:52 +01:00
Peter Steinberger
9a6a663d84 test(qa): settle channel before thread memory check 2026-04-28 11:38:31 +01:00
Peter Steinberger
db365d531f fix(logging): honor forced color for subsystem output 2026-04-28 11:38:31 +01:00
Peter Steinberger
b469092d92 test(memory-host): assert package-owned boundary report 2026-04-28 11:38:18 +01:00
Peter Steinberger
064ec5f07c fix(memory-host): harden service overrides 2026-04-28 11:38:18 +01:00
Peter Steinberger
c3f5af897c refactor(memory-host): replace core runtime bridge with services 2026-04-28 11:38:17 +01:00
Vincent Koc
aa1834a3ff fix(gateway): warn on legacy env vars
Fixes #53482.

Supersedes #53667.
2026-04-28 03:37:57 -07:00
Peter Steinberger
d770a3b786 test(memory): stabilize reindex and cron checks 2026-04-28 11:36:28 +01:00
Peter Steinberger
6a387afc53 refactor(memory-host): route sdk shims to package source 2026-04-28 11:36:28 +01:00
Peter Steinberger
94fc91e235 ci: harden clawsweeper dispatch workflow 2026-04-28 11:35:40 +01:00
Peter Steinberger
5a1ff1347d fix(slack): bound inbound media downloads 2026-04-28 11:35:26 +01:00
James Reagan
a722da3ed0 fix(gateway): align session thinking defaults (#63418)
Aligns Gateway history and session list thinking-default resolution so backend session state matches the Control UI default label:

- `chat.history` now falls back through the shared Gateway session thinking-default resolver.
- Explicit session overrides still win, then owning `agents.list[].thinkingDefault`, then global/model/catalog defaults.
- `sessions.list` catalog-aware thinking defaults are covered by focused regressions.

PR by @jpreagan.

Validated in Blacksmith Testbox `tbx_01kq9t1aeqrz1mj598vvqv9dpg`:
- `pnpm test:serial src/gateway/session-utils.test.ts src/gateway/server.sessions.gateway-server-sessions-a.test.ts src/gateway/server.chat.gateway-server-chat.test.ts` (141 passed)
- `OPENCLAW_TESTBOX=1 pnpm check:changed`
2026-04-28 03:34:58 -07:00
Vincent Koc
d70191f8af feat(sandbox): add Docker GPU passthrough
Add opt-in `sandbox.docker.gpus` config plumbing for Docker sandbox containers.

- thread the optional GPU passthrough field through config types, schema, resolution, and Docker create args
- reject empty config values and emit `--gpus` as a separate Docker argv pair
- document the Docker-only behavior and credit the original contributor in the changelog

Fixes #57976.
Carries forward #58124 from @cyan-ember.

Co-authored-by: cyan-ember <5855097+cyan-ember@users.noreply.github.com>
2026-04-28 03:33:28 -07:00
Peter Steinberger
7150acba69 ci: debounce clawsweeper dispatch metadata 2026-04-28 11:31:49 +01:00
Peter Steinberger
35bc13f9ef fix: prefer OpenAI media for Codex defaults 2026-04-28 11:30:17 +01:00
Shakker
32c987626b fix: prune stale plugin runtime mirror entries 2026-04-28 11:25:09 +01:00
Shakker
92016b82ae fix: refresh plugin runtime mirrors in place 2026-04-28 11:25:09 +01:00
Shakker
7727e102a5 fix: scope plugin inspect runtime loading 2026-04-28 11:25:09 +01:00
Shakker
1bd4b7ac4d fix: keep plugin uninstall on metadata path 2026-04-28 11:25:09 +01:00
Vincent Koc
7950a18025 fix(whatsapp): recover stale listener after auth conflict churn (#72621)
* fix(whatsapp): recover stale listener after auth conflict churn

* fix(whatsapp): block symlink auth cleanup escapes

* fix(whatsapp): refuse external auth cleanup
2026-04-28 03:24:57 -07:00
Vincent Koc
e2f3044b8f fix(memory-wiki): route bridge CLI through gateway
Route Memory Wiki bridge-mode status, doctor, and bridge import CLI paths through Gateway RPC when bridge artifact reads are active, while preserving local/offline fallbacks.

Harden Gateway CLI rendering and imported-source writes: validate RPC response shapes, bound response strings before rendering/JSON serialization, sanitize/escape terminal-controlled output, avoid redundant JSON forwarding, and replace imported source pages through a temp-file rename path with symlink and hardlink regressions.

Fixes #65722
Fixes #65976
Fixes #66082
Fixes #67979
Fixes #68371
Fixes #68828
Fixes #69019
Fixes #70181
Fixes #70242
Fixes #70842

Thanks @moorsecopers99, @vincentkoc, and @prasad-yashdeep.
2026-04-28 03:22:12 -07:00
Vincent Koc
f12dedb5c8 fix(tasks): keep media tool runs live 2026-04-28 03:21:00 -07:00
Peter Steinberger
1b13f53047 fix(ollama): reject garbled Kimi symbol output 2026-04-28 11:20:15 +01:00
Vincent Koc
77192572f6 ci: split macos codeql shard
Split the slow macOS CodeQL job into its own weekly/manual workflow and keep the daily CodeQL default on the fast JS/Actions security path.
2026-04-28 03:14:07 -07:00
Peter Steinberger
6cc6996a1c fix(slack): tune socket mode pong timeout 2026-04-28 11:13:03 +01:00
Peter Steinberger
c9ead1b928 test: annotate Docker test-state scenarios 2026-04-28 11:10:30 +01:00
Peter Steinberger
ade9aaae89 fix(cli): classify scope-limited status probes as reachable 2026-04-28 11:09:42 +01:00
Peter Steinberger
1fcf0a422f fix(agents): keep media generation tasks fresh 2026-04-28 10:59:42 +01:00
Peter Steinberger
9da76c4255 test: fix openclaw test state helper types 2026-04-28 10:59:42 +01:00
Gabriel Kripalani
17ef9ef895 feat(openrouter): add video generation provider (#72700)
Adds OpenRouter video generation via video_generate, with hardened async polling/download handling, docs, and regression coverage.

Validation:
- pnpm test src/plugins/plugin-lookup-table.test.ts src/secrets/target-registry.fast-path.test.ts src/gateway/server-startup-post-attach.test.ts extensions/openrouter/video-generation-provider.test.ts src/video-generation/live-test-helpers.test.ts src/media-generation/provider-capabilities.contract.test.ts src/agents/pi-embedded-helpers/failover-matches.test.ts src/plugins/manifest-metadata-scan.test.ts src/agents/openai-transport-stream.test.ts src/media-understanding/openai-compatible-audio.test.ts src/agents/schema-normalization-runtime-contract.test.ts src/agents/provider-request-config.test.ts src/plugin-sdk/provider-stream.test.ts src/agents/pi-embedded-runner/run/attempt.spawn-workspace.websocket.test.ts -- --reporter=verbose
- OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_TEST_QUIET=0 OPENCLAW_LIVE_VIDEO_GENERATION_MODELS=openrouter/google/veo-3.1-fast pnpm test:live src/video-generation/video-generation.live.test.ts -- --runInBand

Co-authored-by: notamicrodose <gabrielkripalani@me.com>
2026-04-28 10:57:31 +01:00
Peter Steinberger
5915489631 test: stabilize tts fast-lane guard 2026-04-28 10:54:23 +01:00
Peter Steinberger
6f8792f3f1 fix(cli): wire image describe prompt options 2026-04-28 10:53:53 +01:00
Peter Steinberger
0bc8b9a95a test: add shared OpenClaw test-state harness 2026-04-28 10:52:47 +01:00
Patrick Erichsen
ab3feca0d5 docs(skills): generalize pre-release testing skill wording (#73468) 2026-04-28 02:50:11 -07:00
Peter Steinberger
9207660c87 test: fix main ci shard routing 2026-04-28 10:48:27 +01:00
Vincent Koc
ae63f76bbd fix(cron): infer session agentId when omitted (#72326)
* fix(cron): infer session agentId when omitted

* fix(clownfish): address review for ghcrawl-165998-agentic-merge (1)
2026-04-28 02:47:20 -07:00
Peter Steinberger
c5cd7aabcf fix(auto-reply): bound pending tool result drain 2026-04-28 10:46:06 +01:00
Vincent Koc
210cccb0fe fix(tasks): index async media tasks by agent 2026-04-28 02:43:17 -07:00
Peter Steinberger
a6bb0265f0 test: speed up unit hotspot routing 2026-04-28 10:42:14 +01:00
Vincent Koc
17811480da docs(skills): add plugin pre-release test plan 2026-04-28 02:40:33 -07:00
Vincent Koc
cfbf4d1fa4 docs: note default sandbox image fail-fast behavior
For 47dc9f7fc0: docs/gateway/sandboxing.md now warns under "Build the default
image" that OpenClaw no longer silently retags plain debian:bookworm-slim as
openclaw-sandbox:bookworm-slim when the default image is missing. Sandbox runs
fail with a build instruction so the python3 tooling required by sandbox
write/edit helpers is preserved instead of being silently dropped.
2026-04-28 02:40:26 -07:00
Vincent Koc
058b57867e fix(qwen): allow explicit qwen3.6-plus on Coding Plan (#72664) 2026-04-28 02:38:47 -07:00
Peter Steinberger
b4ffef5c5f fix(plugins): prune inactive bundled runtime deps 2026-04-28 10:34:24 +01:00
Peter Steinberger
1346a31861 fix(plugins): keep manifestless bundles indexed 2026-04-28 10:34:01 +01:00
Peter Steinberger
f5922e6eb1 fix(agents): trim config write tool responses 2026-04-28 10:32:58 +01:00
Vincent Koc
5820a48fca ci: add plugin boundary codeql quality shard (#73447) 2026-04-28 02:30:33 -07:00
Peter Steinberger
1f1b98e33b fix(auto-reply): keep consumed reset triggers out of prompt 2026-04-28 10:24:04 +01:00
Vincent Koc
aa2f964bda fix(mattermost): keep inspector capture quiet 2026-04-28 02:19:57 -07:00
Vincent Koc
ad954dd1ca test(plugins): fix codex inspector capture regression 2026-04-28 02:19:56 -07:00
Vincent Koc
5f3b8b4100 fix(plugins): harden inspector runtime capture 2026-04-28 02:19:56 -07:00
Peter Steinberger
0f24a8d8e1 test: isolate gateway prewarm scheduling 2026-04-28 10:18:42 +01:00
Peter Steinberger
fac116cfa4 fix: resolve providerless image model refs 2026-04-28 10:18:07 +01:00
ZC
5741e40c14 fix(cron): clarify local timezone cron expressions (#73372)
* fix(cron): clarify local timezone cron expressions

* fix: clarify cron timezone guidance

---------

Co-authored-by: Altay <altay@uinaf.dev>
2026-04-28 12:16:27 +03:00
Peter Steinberger
9cdae734a7 test: stabilize gateway startup prewarm test 2026-04-28 10:14:03 +01:00
Vincent Koc
1912e309f7 fix(ui): confirm button-triggered new session resets (#73361) 2026-04-28 02:10:33 -07:00
Peter Steinberger
62997f7fce fix(deepseek): backfill v4 assistant reasoning replay 2026-04-28 10:07:39 +01:00
Peter Steinberger
0876ff481b test: speed up styled select test 2026-04-28 10:02:20 +01:00
Scott Hanselman
8f277e4b7f fix: allow safe Windows companion node commands (#71884)
Merged via squash.

Prepared head SHA: 24e2b79fe4
Co-authored-by: shanselman <2892+shanselman@users.noreply.github.com>
Co-authored-by: shanselman <2892+shanselman@users.noreply.github.com>
Reviewed-by: @shanselman
2026-04-28 02:01:20 -07:00
Edwin Rivera
bca30b62be fix: defer Claude live MCP cleanup (#73351)
Thanks @edwin-rivera-dev.
2026-04-28 09:59:58 +01:00
Peter Steinberger
249cb54373 fix: keep acp typing for tool-only replies 2026-04-28 09:58:18 +01:00
Vincent Koc
7fd9c152d1 fix(memory): keep pre-compaction flush prompt out of user transcript (#73380) 2026-04-28 01:58:14 -07:00
Vincent Koc
47dc9f7fc0 Fix default sandbox image fallback for python3-dependent mutations (#73362) 2026-04-28 01:57:44 -07:00
Peter Steinberger
6f3b5f8666 fix(agents): pause yielded subagent runs 2026-04-28 09:57:12 +01:00
Peter Steinberger
2790825ae5 test(auto-reply): assert bare reset acknowledgement 2026-04-28 09:56:41 +01:00
Peter Steinberger
11f0244cf4 fix(gateway): start channels before model prewarm 2026-04-28 09:56:16 +01:00
Vincent Koc
b6a21cde34 ci: schedule android codeql shard (#73430) 2026-04-28 01:54:57 -07:00
Vincent Koc
76cd97289b fix(cron): support Telegram thread IDs in cron add/edit
- Add `--thread-id` support to cron add/edit Telegram delivery.
- Reject non-positive thread IDs and guard cron edit lookup pagination against non-progress/max-page loops.
- Preserve existing delivery mode on thread-only cron edit patches.

Carries forward #51581, #60373, and #60890.

Co-authored-by: ChunHao Chen <crazycjh@gmail.com>
2026-04-28 01:50:44 -07:00
Vincent Koc
02908db62b fix(ui): clear webchat pending state only for completed active run (#73368) 2026-04-28 01:47:00 -07:00
Peter Steinberger
3ed3248d7b fix(gateway): preserve config SecretRef env for services 2026-04-28 09:44:51 +01:00
Peter Steinberger
4c61040c52 test: speed up small unit fast cases 2026-04-28 09:44:44 +01:00
Vincent Koc
fe7865aad6 docs: cover Anthropic beta header suppression and claude-cli fallback prelude
- docs/concepts/model-providers.md: add proxy-route shaping rule for the
  09ec5d2c4d fix that suppresses implicit Anthropic beta headers
  (`claude-code-20250219`, `interleaved-thinking-2025-05-14`, OAuth markers)
  on non-direct endpoints, parallel to the existing OpenAI
  `compat.supportsDeveloperRole` rule.
- docs/gateway/cli-backends.md: add a "Fallback prelude from claude-cli
  sessions" section for a96f1fa5ef so users know that non-CLI fallback
  candidates after a claude-cli failure are now seeded with a context prelude
  harvested from Claude Code's `~/.claude/projects/` JSONL (preferring the
  latest `/compact` summary, coalescing tool blocks, skipping same-provider
  `--resume` fallbacks).
2026-04-28 01:42:25 -07:00
Peter Steinberger
8a98c08c8a fix(mattermost): avoid system events for user posts 2026-04-28 09:41:04 +01:00
Peter Steinberger
28bf71d74b fix(auto-reply): preserve silent voice payloads 2026-04-28 09:41:04 +01:00
Peter Steinberger
a3bbcf2792 fix(docker): keep plugin runtime deps off bind mounts 2026-04-28 09:37:59 +01:00
Peter Steinberger
3ee5490c60 fix(auto-reply): avoid duplicate reset hook acknowledgements 2026-04-28 09:37:15 +01:00
Vincent Koc
e2bcec33b3 fix(security): avoid duplicate skill package import 2026-04-28 01:37:01 -07:00
Vincent Koc
7e028917c0 fix(android): remediate app CodeQL alerts 2026-04-28 01:37:01 -07:00
Vincent Koc
5ac6d7661c fix(ci): harden workflow checkouts 2026-04-28 01:37:00 -07:00
Peter Steinberger
f76c8322d3 test: route gateway audit through fast lane 2026-04-28 09:35:34 +01:00
Vincent Koc
474859aaaa test(agents): cover raw model cache trace stage 2026-04-28 01:32:34 -07:00
Peter Steinberger
99ceaaa76e test: fix attempt execution fixture lint 2026-04-28 09:32:02 +01:00
Peter Steinberger
a68ca1ae0b fix(auto-reply): acknowledge bare reset commands 2026-04-28 09:31:14 +01:00
Peter Steinberger
8178b62187 fix(android): include third-party sensitive handlers 2026-04-28 09:27:59 +01:00
Peter Steinberger
2276f660f3 refactor(android): split sensitive features by flavor 2026-04-28 09:27:39 +01:00
Peter Steinberger
8ff0ea50b0 ci: stabilize full release validation 2026-04-28 09:26:50 +01:00
Vincent Koc
bab403d0ee fix(plugins): avoid bundled install load path aliases 2026-04-28 01:26:21 -07:00
Peter Steinberger
169dba2042 fix(skills): require opt-in for coding-agent 2026-04-28 09:24:24 +01:00
Peter Steinberger
4f6dab852e ci: fix main test and boundary checks 2026-04-28 09:23:26 +01:00
Peter Steinberger
09ec5d2c4d fix(agents): suppress Anthropic beta headers for custom endpoints 2026-04-28 09:20:58 +01:00
Peter Steinberger
2a1e47ffcb fix(agents): restore raw model run type coverage 2026-04-28 09:20:58 +01:00
Peter Steinberger
732e5805e3 fix(ollama): preserve configured native thinking 2026-04-28 09:20:44 +01:00
Peter Steinberger
7092313b2f docs: advertise xhigh docs i18n thinking 2026-04-28 09:19:40 +01:00
Peter Steinberger
db40ec404a fix: honor Ollama thinking catalog metadata 2026-04-28 09:15:28 +01:00
Peter Steinberger
67b16a4a6d fix: centralize source reply delivery mode 2026-04-28 09:14:19 +01:00
Peter Steinberger
1257e0e4ae ci: prepare qa channel boundary types 2026-04-28 09:13:49 +01:00
Peter Steinberger
4e921808d1 fix(line): persist inbound media in shared store 2026-04-28 09:12:11 +01:00
Peter Steinberger
fb3ea9efb1 fix: keep gateway model probes raw 2026-04-28 09:11:47 +01:00
Peter Steinberger
bce6c10290 fix: harden docs i18n prompt echoes 2026-04-28 09:11:28 +01:00
Peter Steinberger
725d557de6 fix(plugins): shorten runtime mirror lock hold 2026-04-28 09:10:37 +01:00
Peter Steinberger
0ef6702af3 build(android): update dependencies and lint config 2026-04-28 09:10:13 +01:00
Ayaan Zaidi
8da2fb1920 fix: seed claude-cli fallback context (#72069) (thanks @stainlu) 2026-04-28 13:35:59 +05:30
Ayaan Zaidi
5e4c29e9bc fix(agents): require claude fallback source provider 2026-04-28 13:35:59 +05:30
stainlu
4369c20bfe fix(agents): make originalProvider optional in runAgentAttempt params
The required-typed param introduced in 9987e7797f broke
attempt-execution.cli.test.ts and auth-profile-runtime-contract.test.ts
which construct runAgentAttempt params without an originalProvider field.
Make it optional and explicitly require the typeof check before passing
to isClaudeCliProvider so a missing field correctly skips the seed
(defensive default for fallback paths that didn't plumb the original
provider through, no-op for non-fallback paths).
2026-04-28 13:35:59 +05:30
stainlu
0bfcdcf044 fix(agents): scope claude-cli fallback seed and pair summary with boundary
Addresses review on #72069:

- Codex P1 ("Gate Claude prelude seeding by source provider"): the
  guard checked the *current* fallback candidate but not the failed
  attempt. A session that still carried a stale
  cliSessionBindings["claude-cli"] from an unrelated past run would
  inject Claude transcript context into a fallback chain that started
  on a different provider (e.g. openai -> openai-codex), leaking
  irrelevant prior conversation. Plumb `originalProvider` (the
  user-requested provider for the chain) through to runAgentAttempt
  and require `isClaudeCliProvider(originalProvider)` before reading
  Claude history.

- Codex P2 ("Prefer latest compact boundary when summary is missing"):
  the resolver always preferred the most recent explicit summary, so
  a later compaction without its own summary entry (rare crash case)
  paired stale summary text with post-latest-boundary turns. Restructure
  readClaudeCliFallbackSeed to queue summaries into pendingSummary and
  flush each boundary's pair atomically. A boundary with no preceding
  summary now correctly falls back to the boundary's own content
  rather than serving an older summary alongside fresh turns.

- Greptile P2 (newest-first break vs sparse coverage): the
  formatFallbackTurns walk intentionally stops on the first oversized
  turn so the prelude stays a contiguous "what was happening just
  before the failure" window. Document the design choice inline so a
  future maintainer doesn't reflexively change it to skip-and-continue.

Tests:
- New gateway cases for the boundary-without-summary edge case and
  for trailing summaries written without a paired boundary.
- existing 33 attempt-execution + 14 cli-session-history tests still
  pass; broader src/agents/command suite stays green (63/63).
2026-04-28 13:35:59 +05:30
stainlu
9691399e53 fix(agents): drop unnecessary non-null assertion in fallback prelude formatter
Local default oxlint did not run --type-aware so the warning was missed
on the initial commit; CI surfaced it via check-lint. Hoist the heading
into a named const so its length is read directly without the assertion.
2026-04-28 13:35:59 +05:30
stainlu
a96f1fa5ef fix(agents): seed claude-cli fallback prompts with prior-session context (#69973)
When a claude-cli attempt failed with a fallbackable error (e.g. a 402
billing limit), the next candidate -- typically a non-CLI provider --
ran with no prior conversation context. Claude Code keeps its own
JSONL session under ~/.claude/projects/, but the fallback runner only
sees what OpenClaw assembles from its own transcript, which is empty
for claude-cli sessions. The fallback model therefore behaved as if
the conversation just started, even though Claude later resumed fine.

Resolution mirrors what Claude Code itself does on resume after
compaction: prefer the explicit `/compact` summary, then append the
most recent post-boundary turns up to a char budget. Concretely:

- `readClaudeCliFallbackSeed` (gateway): walks the Claude JSONL with
  awareness of `type: "summary"` and `type: "system",
  subtype: "compact_boundary"` entries. Pre-boundary turns are dropped
  (they are represented by the summary); post-boundary turns become
  the recent-window. Multiple compactions are handled by preferring
  the latest summary. Path safety reuses the existing
  `resolveClaudeCliSessionFilePath` validation.

- `formatClaudeCliFallbackPrelude` / `buildClaudeCliFallbackContext\
Prelude` (agents helpers): format the harvested seed into a labeled
  prelude. Tool blocks are coalesced to compact "(tool call: name)" /
  "(tool result: …)" hints to keep the prompt budget honest. Newest
  turns are kept first when truncating; the summary is clearly
  labeled "(truncated)" if it overflows.

- `resolveFallbackRetryPrompt`: gains an optional
  `priorContextPrelude` that prepends before the existing retry
  marker. Empty/whitespace preludes are ignored; first-attempt prompts
  are unchanged.

- `runAgentAttempt`: builds the prelude when `isFallbackRetry === true`
  AND the new candidate is non-claude-cli AND a Claude-cli session
  binding is present. Same-provider fallbacks (claude-cli to
  claude-cli) are unaffected because Claude's own --resume still works.

Verified the new tests (12 in cli-session-history, 12 added to
attempt-execution) catch the regression: removing the prelude prepend
in resolveFallbackRetryPrompt makes both new prelude cases fail,
restoring the original cold-start behavior.

References:
- https://code.claude.com/docs/en/how-claude-code-works
- "Inside Claude Code: The Session File Format"
  https://databunny.medium.com/inside-claude-code-the-session-file-format-and-how-to-inspect-it-b9998e66d56b
2026-04-28 13:35:59 +05:30
Shakker
290c7ab848 test: add future strict startup benchmark case 2026-04-28 09:05:11 +01:00
Vincent Koc
dbab162abd ci: split codeql quality workflow (#73404) 2026-04-28 01:04:59 -07:00
Peter Steinberger
a811e164e3 ci: speed up full release validation 2026-04-28 09:02:57 +01:00
Peter Steinberger
c7af9c765c ci: tolerate missing clawsweeper dispatch access 2026-04-28 09:02:28 +01:00
Vincent Koc
a9a689ed2a fix(plugins): keep qa sdk aliases private 2026-04-28 01:01:19 -07:00
Peter Steinberger
f3191b7962 fix(agents): abort stalled Anthropic SSE reads 2026-04-28 09:00:37 +01:00
Peter Steinberger
a8b64b7d52 fix(doctor): require confirmation for transcript archive 2026-04-28 08:56:18 +01:00
Peter Steinberger
04e774eeac feat(android): add authenticated presence alive beacons (#73373)
* feat: add Android presence alive beacons

* fix: harden Android presence beacon review findings

* fix: address Android presence review findings
2026-04-28 08:55:06 +01:00
Peter Steinberger
c788aa025e test: route session lifecycle test through fast lane 2026-04-28 08:52:20 +01:00
Peter Steinberger
2d575bc00e fix(onboarding): pin health auth during setup 2026-04-28 08:51:29 +01:00
Peter Steinberger
8b4a5d70e4 fix(build): preserve staged runtime deps on rebuild 2026-04-28 08:45:11 +01:00
Zhang Xiaofeng
a0900926c3 fix: add CJK error patterns to failover classification (#56242)
* fix: add CJK error patterns to failover classification

Chinese LLM providers (ZhipuAI/GLM, Bailian, Kimi/Moonshot, DeepSeek,
etc.) return error messages in Chinese. The existing failover
classification only matches English patterns, causing these errors to
fall through as unclassified — surfacing raw provider errors to users
instead of triggering model fallback.

Real production example: ZhipuAI error code 1234 returns
'网络错误,错误id:xxx,请联系客服。' (network error). This was not
matched by the existing 'network error' English pattern, so no failover
was triggered despite having a configured fallback model.

Changes:
- Add Chinese patterns to all error categories in failover-matches.ts:
  timeout, serverError, rateLimit, billing, auth, overloaded
- Add Chinese network error detection in formatTransportErrorCopy()
  for user-friendly error messages
- Add comprehensive test coverage for all CJK error categories

Follows the existing precedent set by Chinese context overflow patterns
in isContextOverflowError().

* fix: narrow billing pattern and fix placeholder issue URL

- Change '账户余额' to '账户余额不足' to avoid false positives on
  messages that merely mention account balance (per greptile review)
- Replace XXXXX placeholder with actual issue #56242

* fix: wire CJK auth failover patterns

* fix: classify CJK provider failover errors

* fix: place failover changelog entry in unreleased

---------

Co-authored-by: Altay <altay@uinaf.dev>
2026-04-28 10:44:17 +03:00
Peter Steinberger
47b6d3a334 test(video): isolate provider registry mocks 2026-04-28 08:43:20 +01:00
Peter Steinberger
f95f720b25 docs: separate mintlify list closings 2026-04-28 08:43:20 +01:00
Peter Steinberger
a30698166b fix(wizard): pin setup token for health check 2026-04-28 08:43:20 +01:00
Galin Iliev
274d05dfe7 fix(wizard): use setup token for onboarding health check
Fixes #72203

Co-authored-by: OpenClaw Bot <bot@openclaw.dev>
2026-04-28 08:43:20 +01:00
Scott Hanselman
146debf8c1 fix(tui): dedupe ASCII backspace events (#73335)
Merged via squash.

Prepared head SHA: 8f02f48acd
Co-authored-by: shanselman <2892+shanselman@users.noreply.github.com>
Co-authored-by: shanselman <2892+shanselman@users.noreply.github.com>
Reviewed-by: @shanselman
2026-04-28 00:41:55 -07:00
Vincent Koc
0b82a7e718 test(ci): align main test expectations 2026-04-28 00:35:44 -07:00
Peter Steinberger
1dd011984a fix: add pricing bootstrap opt-out and sdk compat exports 2026-04-28 08:35:11 +01:00
Peter Steinberger
f5a7632ffc ci: allow legacy package stamp warnings 2026-04-28 08:31:16 +01:00
Peter Steinberger
b22926601f fix(ui): keep chat attachment payloads out of state 2026-04-28 08:27:53 +01:00
Peter Steinberger
bb7e8624ab fix: keep typing for group message-tool replies 2026-04-28 08:27:23 +01:00
Peter Steinberger
2f3e81fec2 ci: guard docs against poisoned tool text 2026-04-28 08:27:11 +01:00
Peter Steinberger
bcf4628092 ci: use gpt-5.5 for live OpenAI defaults 2026-04-28 08:27:11 +01:00
Peter Steinberger
39cecd6428 ci: avoid unnecessary docker image pulls 2026-04-28 08:24:29 +01:00
Peter Steinberger
04e96c11ea fix(gateway): skip plugin pricing scans when disabled 2026-04-28 08:23:53 +01:00
Peter Steinberger
2cfe8e17f5 test: type channel list plugin stubs 2026-04-28 08:21:35 +01:00
Peter Steinberger
438da9596e test: expand fast lane coverage 2026-04-28 08:19:40 +01:00
Peter Steinberger
78a12706ec fix(docs): make docs formatter mintlify-safe 2026-04-28 08:13:21 +01:00
Peter Steinberger
e4139c3cb6 fix(cli): show configured chat channels in list 2026-04-28 08:12:56 +01:00
Peter Steinberger
bdba90a20b feat: add authenticated iOS background presence beacon (#73330)
* feat: add iOS background presence beacon

Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>

* fix: keep iOS background reconnects ahead of beacon throttle

* build: refresh gateway protocol swift models

* fix: emit swift protocol string enums

---------

Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
2026-04-28 08:10:35 +01:00
Vincent Koc
d525d6486d fix(android): keep camera temp files private
Fix Android CodeQL local temp-file disclosure findings in camera capture.
2026-04-28 00:06:12 -07:00
Peter Steinberger
85fcf16804 ci: align docs formatter with mintlify guard 2026-04-28 08:06:03 +01:00
Peter Steinberger
12962dd883 fix(models): keep agent primaries strict 2026-04-28 08:01:42 +01:00
Peter Steinberger
cd1343c244 docs: fix heartbeat paramfield lists 2026-04-28 08:00:27 +01:00
Thatgfsj
3dff1272e9 fix: harden Windows gateway restart fallback (#69056)
Thanks @Thatgfsj.
2026-04-28 07:57:47 +01:00
Peter Steinberger
07c653e913 test: move pure hotspots to fast lane 2026-04-28 07:56:40 +01:00
Peter Steinberger
acea3f2465 fix(build): stamp runtime postbuild artifacts 2026-04-28 07:56:08 +01:00
Peter Steinberger
3256cf4fc7 docs: clarify group visible replies 2026-04-28 07:55:40 +01:00
Ayaan Zaidi
6b6a049337 fix: collapse nested runtime deps cache roots (#73205) (thanks @SymbolStar) 2026-04-28 12:25:25 +05:30
SymbolStar
dfaa06fe15 fix(bundled-runtime-deps): collapse nested cache pluginRoot to enclosing key
When a bundled plugin (e.g. plugin-sdk loaded transitively) is resolved via a
pluginRoot already inside the existing plugin-runtime-deps cache, its path
does not match the `dist/extensions/<plugin>` shape, so
resolveBundledPluginPackageRoot() returns null and the caller falls back to
the raw pluginRoot. resolveExistingExternalBundledRuntimeDepsRoots() then
rejected the path because the relative segment crossed a directory separator,
causing the resolver to mint a fresh `openclaw-unknown-<pathhash>` cache
beside the real versioned one. The two caches raced replaceNodeModulesDir()
and triggered ENOTEMPTY crash loops.

Treat any descendant of `<base>/openclaw-*` as belonging to that cache key
so nested resolutions return the existing versioned root instead of creating
a self-referential zombie cache.

Fixes #72956
2026-04-28 12:25:25 +05:30
Peter Steinberger
424560c6c2 docs: normalize mintlify component closings 2026-04-28 07:54:15 +01:00
Peter Steinberger
8831d2cf0a fix: normalize docs mintlify components 2026-04-28 07:52:17 +01:00
Peter Steinberger
fb40ed99a7 fix(sessions): remove session store rotation 2026-04-28 07:46:24 +01:00
Peter Steinberger
ad57a6d616 docs: replace reactions cache bust with prose 2026-04-28 07:37:14 +01:00
Peter Steinberger
df4d3fa5a9 fix(logging): redact subsystem console output before colorizing 2026-04-28 07:36:50 +01:00
edwin-rivera-dev
f2df49ab4b fix(logging): redact secrets at subsystem console sink (#73284)
createSubsystemLogger writes through writeConsoleLine, which intentionally
bypasses the patched console.* capture handler in src/logging/console.ts to
avoid recursion. That bypass also skipped the sink-boundary
redactSensitiveText() gate, so secrets reaching subsystem loggers as
message strings or formatted meta could appear verbatim on the terminal —
a follow-up to the file-transport redaction landed in #67953, tracked
under #64046.

Apply redactSensitiveText() at the writeConsoleLine() exit, immediately
after the existing Windows surrogate sanitization and before dispatching
to the rawConsole sink. This covers all subsystem console paths
(trace/debug/info/warn/error/fatal and .raw) because they share the same
writeConsoleLine() exit, matching the redact-at-sink-boundary pattern
already used in console.ts and the file transport.

Closes #73284
2026-04-28 07:36:50 +01:00
scoootscooob
3c636208b0 fix(messages): keep group replies tool-only by default
Rewrites the always-on reply handling so group/channel rooms default to message-tool-visible output, while `messages.groupChat.visibleReplies: \"automatic\"` preserves legacy auto-posting.\n\nThanks @scoootscooob.
2026-04-28 07:36:43 +01:00
Peter Steinberger
e388f289bf docs: refresh reactions source cache key 2026-04-28 07:36:13 +01:00
Ke Wang
a253660385 fix(gateway): accept heartbeat/cron/webhook channel hints in agent params (#73237) (#73282)
* fix(gateway): accept heartbeat/cron/webhook channel hints in agent params (#73237)

* test(gateway): cover internal reply channel hints

* test(openai): include codex mini catalog expectation

* test(openai): follow codex catalog fixture split

---------

Co-authored-by: Ke Wang <ke@pika.art>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-28 07:32:23 +01:00
Peter Steinberger
f321036a00 fix(acpx): tolerate wrapper chmod failures 2026-04-28 07:30:00 +01:00
darkamenosa
cb8b327488 fix(zalouser): persist refreshed session cookies
Persist refreshed `zca-js` session cookies after QR login, session restore, and successful API calls so gateway restarts restore the freshest local Zalo Personal session.

- Adds stable credential cookie signatures so equivalent cookie-jar reorderings do not rewrite credentials.
- Adds regression coverage for reordered live cookie jars preserving credential file content and mtime.
- Updates CHANGELOG.md: (#73277) Thanks @darkamenosa.

Co-authored-by: Tuyen <hxtxmu@gmail.com>
Co-authored-by: Frank Yang <frank.ekn@gmail.com>
2026-04-28 14:26:37 +08:00
Shakker
577a540880 docs: note fireworks together catalog migration 2026-04-28 07:25:03 +01:00
Shakker
7b3d3ce361 feat: declare together model catalog 2026-04-28 07:25:03 +01:00
Shakker
1aa62c0b0a feat: declare fireworks model catalog 2026-04-28 07:25:03 +01:00
Peter Steinberger
c3c8d66acf test: align acp fast-lane routing assertions 2026-04-28 07:22:14 +01:00
Peter Steinberger
4e6c0965cb test: route acp runtime tests through fast lane 2026-04-28 07:17:02 +01:00
Peter Steinberger
84477e014d test(openai): align codex runtime fixture 2026-04-28 07:08:27 +01:00
Frank Yang
e008830d0e fix(agents): clean up local Claude stdio runs (#73292)
Clean up local Claude stdio one-shot runs before returning from embedded `openclaw agent --local`, including bundle MCP loopback teardown for local process resources.

Keeps gateway-owned MCP loopback cleanup internal to the Gateway, documents the local-vs-gateway behavior, and aligns the stale OpenAI provider-runtime fixture with the current unsupported Codex mini route.
2026-04-28 07:06:01 +01:00
Peter Steinberger
9b556291e9 test(openai): split codex catalog fixtures 2026-04-28 07:04:22 +01:00
Vincent Koc
1278f0bcc0 fix(codeql): tune Android pinning profile
Remove noisy missing-certificate-pinning query from the critical Android CodeQL profile; gateway TLS uses custom certificate fingerprint pinning.
2026-04-27 23:04:16 -07:00
Vincent Koc
5828dcdb05 test(gateway): reduce server shard memory pressure (#73317) 2026-04-27 22:58:15 -07:00
Peter Steinberger
870f7d1c0f test(openai): align codex mini contract 2026-04-28 06:56:29 +01:00
Peter Steinberger
b5371bfd63 fix(auth): migrate flat auth profiles in doctor 2026-04-28 06:53:48 +01:00
Peter Steinberger
2f2aee5fe8 ci: retry cross-os agent runtime deps staging 2026-04-28 06:51:05 +01:00
Peter Steinberger
4397717322 fix(telegram): report unauthorized startup tokens 2026-04-28 06:50:51 +01:00
Peter Steinberger
76a07b9a07 fix(cli): reject empty model run prompts 2026-04-28 06:50:44 +01:00
Peter Steinberger
ee75a8ec2c ci: document clawsweeper dispatch trigger 2026-04-28 06:50:33 +01:00
Peter Steinberger
9aa461747a fix(plugin-sdk): restore legacy root alias exports 2026-04-28 06:48:59 +01:00
Peter Steinberger
6f3674c8d0 ci: harden ClawSweeper dispatcher credentials 2026-04-28 06:48:38 +01:00
Peter Steinberger
6543c10ab6 test: route model catalog through fast lane 2026-04-28 06:48:29 +01:00
Peter Steinberger
ba17db96a4 ci: skip clawsweeper without app credentials 2026-04-28 06:48:29 +01:00
Peter Steinberger
0113248d91 fix(gateway): route text-only chat images to media understanding 2026-04-28 06:45:28 +01:00
Peter Steinberger
0fc1cdec45 ci: fix ClawSweeper dispatcher payload 2026-04-28 06:44:26 +01:00
Peter Steinberger
dc6031197b fix(models): hide unsupported codex mini route 2026-04-28 06:43:51 +01:00
Peter Steinberger
23818600bb ci: add ClawSweeper event dispatcher 2026-04-28 06:43:38 +01:00
Ke Wang
b4e9f1bd1c fix(memory-core): cap detached dream narratives (#73287)
Cap detached Dream Diary narrative subagent runs across cron dreaming sweeps so multi-workspace runs cannot fan out unbounded subagent sessions.

Adds regression coverage that queued detached narratives resume and clean up, plus a unit-fast lane correction for the security symlink audit test.
2026-04-28 06:42:07 +01:00
Peter Steinberger
89079a32ef refactor(memory-host): narrow runtime adapters 2026-04-28 06:40:37 +01:00
Vincent Koc
29a34e0a4d fix(android): use absolute logcat path
Fix Android CodeQL relative path command finding in debug log collection.
2026-04-27 22:40:00 -07:00
Peter Steinberger
59a4d7fb06 fix(telegram): normalize bot endpoint api roots 2026-04-28 06:36:38 +01:00
Vincent Koc
27e313053c test(gateway): keep session event suite minimal
Keep the session message websocket suite on the default minimal gateway harness to avoid full startup for event routing coverage.
2026-04-27 22:35:40 -07:00
Peter Steinberger
252cc7eccf test: fix unit-fast config assertion 2026-04-28 06:34:50 +01:00
Peter Steinberger
5916237962 fix(onboard): infer custom model image input 2026-04-28 06:34:16 +01:00
Shakker
d48c3e12a5 feat: gate legacy startup sidecar fallback 2026-04-28 06:31:55 +01:00
Peter Steinberger
583b419827 test(plugins): lock package boundary bridges 2026-04-28 06:30:44 +01:00
Peter Steinberger
833654586e fix(gateway): keep container restarts in-process 2026-04-28 06:30:12 +01:00
roytong9
a3fd97570f Normalize telegram topic targets in delivery resolution (#59069)
* Normalize telegram topic targets in delivery resolution

* fix(cron): preserve explicit Telegram topic targets

* fix(clownfish): address review for ghcrawl-165998-agentic-merge (1)

---------

Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>
2026-04-27 22:27:42 -07:00
Vincent Koc
9577703249 test(gateway): trim cron server memory hotspots
Move pure cron coverage off websocket server RPC loops and clean up timeout listener retention in gateway test helpers.
2026-04-27 22:26:41 -07:00
Vincent Koc
2c58c5d4ec fix(android): avoid trust-all TLS probing
Fix Android CodeQL insecure trust manager finding in gateway TLS probing.
2026-04-27 22:26:27 -07:00
Vincent Koc
ce01b8f250 fix(gateway): keep restart probe auth local (#72405)
* fix(gateway): keep restart probe auth local

* fix(gateway): repair local restart probe auth replacement
2026-04-27 22:25:20 -07:00
Vincent Koc
4c72e605cd fix(feishu): recover mojibake filenames from Content-Disposition (#72388) 2026-04-27 22:23:16 -07:00
Vincent Koc
d7e67b455a fix(tui): clear stale streaming after orphaned finals (#72389)
* fix(tui): clear stale streaming after orphaned finals

* fix(tui): clear stale streaming after orphaned finals

* fix(tui): clear stale streaming after orphaned finals
2026-04-27 22:23:13 -07:00
Shakker
db7cab4a9a fix: simplify volc catalog model builders 2026-04-28 06:21:24 +01:00
Shakker
37324dd112 docs: note byteplus volcengine catalog migration 2026-04-28 06:21:24 +01:00
Shakker
8a3252868f refactor: remove unused volc catalog sdk helper 2026-04-28 06:21:24 +01:00
Shakker
1cfa22acb1 feat: declare volcengine model catalog 2026-04-28 06:21:24 +01:00
Shakker
4513658f59 feat: declare byteplus model catalog 2026-04-28 06:21:24 +01:00
Peter Steinberger
25851e3cae fix(google-meet): harden observe mode speech health (#73256)
* fix(google-meet): harden observe mode speech health

* fix(google-meet): address observe speech review

* docs(google-meet): clarify observe mode guarantees
2026-04-28 06:21:10 +01:00
Jesse Merhi
2633b14914 feat(security): support operator-managed network proxy routing (#70044)
* feat: support operator-managed proxy routing

* docs: add network proxy changelog entry

* fix(proxy): restrict gateway bypass to loopback IPs

* fix(cli): harden container proxy URL checks

* docs(proxy): clarify gateway bypass scope

* docs: remove proxy changelog entry

* fix(proxy): clear startup CI guard failures

* fix(proxy): harden gateway proxy policy parsing

* fix(proxy): honor update shorthand proxy policy

* fix(cli): redact proxy URL suffixes

* test(proxy): keep gateway help off proxy startup

* fix(proxy): keep overlapping lifecycle active

* docs: add proxy changelog entry

---------

Co-authored-by: joshavant <830519+joshavant@users.noreply.github.com>
2026-04-28 00:20:47 -05:00
Peter Steinberger
025081dbc5 refactor(memory-host): consolidate core adapter 2026-04-28 06:20:19 +01:00
Peter Steinberger
82eb90b8a2 fix(agents): preserve trusted tool media metadata 2026-04-28 06:19:41 +01:00
Peter Steinberger
bb97f19396 fix(telegram): preserve streamed generated media 2026-04-28 06:19:41 +01:00
Peter Steinberger
8c8dfa768a refactor(models): share catalog capability lookup 2026-04-28 06:18:54 +01:00
Shakker
defddedbaf fix: carry plugin compat into loader reports 2026-04-28 06:18:46 +01:00
Shakker
d062f8130b feat: warn on implicit startup plugin compatibility 2026-04-28 06:18:45 +01:00
Peter Steinberger
f7e942f571 fix(tasks): ship task registry control runtime 2026-04-28 06:18:30 +01:00
Peter Steinberger
85bdaff418 test: route security audits through fast lane 2026-04-28 06:18:06 +01:00
teamclaw
057b8276cc fix(config): align in-process write sourceConfig with file-watcher (#73267)
Fix config writes so in-process reload notifications use the canonical post-write source snapshot, matching the file watcher path.

Adds regression coverage for the runtime source snapshot and changelog credit.
2026-04-28 06:16:58 +01:00
Peter Steinberger
a644e30245 fix(memory-core): retry unavailable dreaming model 2026-04-28 06:15:28 +01:00
Peter Steinberger
017b8db616 ci: speed up release validation shards 2026-04-28 06:14:23 +01:00
Peter Steinberger
3d53b39917 fix(gateway): honor configured vision models 2026-04-28 06:10:14 +01:00
Peter Steinberger
88bcb64681 test: route acp session mapper through fast lane 2026-04-28 06:10:03 +01:00
Peter Steinberger
526372ea36 fix(gateway): use runtime config for secret-backed talk
* fix(gateway): use runtime config for secret-backed talk

* test(gateway): relax talk config rpc timeout

* refactor(gateway): clarify talk config resolution
2026-04-28 06:05:27 +01:00
Vincent Koc
75deb12606 fix(gateway): avoid approval route config load
Avoid eager runtime config loading in the gateway approval path and unref approval cleanup grace timers.
2026-04-27 22:04:09 -07:00
Peter Steinberger
ece523a2b0 docs(plugin-sdk): refresh api baseline 2026-04-28 06:02:17 +01:00
Peter Steinberger
f7d139dfef refactor(memory-host): localize host utilities 2026-04-28 06:02:17 +01:00
Peter Steinberger
74a667f119 fix(telegram): retry startup control calls on fallback transport 2026-04-28 06:02:05 +01:00
Vincent Koc
c627afe1df fix(ci): restore plugin sdk browser config wrapper 2026-04-27 22:01:55 -07:00
Vincent Koc
2809630036 fix(android): disable app data backup (#73281) 2026-04-27 22:01:28 -07:00
Vincent Koc
7b18bd03bb fix(gateway): allow explicit loopback trusted proxy auth
Fixes #59167.

Supersedes #63379.
2026-04-27 22:01:06 -07:00
Peter Steinberger
1089e8b9e0 fix: stabilize memory host ci tests 2026-04-28 06:00:21 +01:00
Peter Steinberger
a6141a5a41 fix: harden macOS gateway updates 2026-04-28 05:58:05 +01:00
Peter Steinberger
66f80d1ed6 docs: avoid mdx list in sdk overview tip 2026-04-28 05:56:57 +01:00
samzong
25ef9c0c41 [Feat] Gateway: offload non-image attachments on chat.send (#67572)
Merged via squash.

Prepared head SHA: ecbd27fc30
Co-authored-by: samzong <13782141+samzong@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
2026-04-28 12:55:00 +08:00
Peter Steinberger
a68cc94c36 fix: resolve main ci shard failures 2026-04-28 05:52:19 +01:00
Peter Steinberger
540cbe24be fix: allow memory flush model override 2026-04-28 05:50:55 +01:00
Peter Steinberger
dc3df62e67 refactor(memory-host): own package contract surface 2026-04-28 05:49:07 +01:00
Vincent Koc
6fadc56802 fix(media): tighten sanitizeMimeType anchoring (#73229)
* fix(media): tighten sanitizeMimeType anchoring

* fix(media): tighten sanitizeMimeType anchoring

* fix(media): tighten sanitizeMimeType anchoring
2026-04-27 21:48:36 -07:00
Gustavo Madeira Santana
d59f001507 test(qa-matrix): cover allowBots modes 2026-04-28 00:47:40 -04:00
Vincent Koc
6d7901f5c8 fix(acpx): lazy-load startup backend 2026-04-27 21:46:45 -07:00
Peter Steinberger
996818e6af fix: follow up main ci failures 2026-04-28 05:41:49 +01:00
Peter Steinberger
8a48994802 fix(otel): record liveness warnings 2026-04-28 05:41:30 +01:00
Peter Steinberger
66a0aa47e4 docs(google): clarify gemini 3.1 pro alias 2026-04-28 05:41:30 +01:00
Vincent Koc
2bce63cb65 fix(android): harden canvas webview bridge (#73240)
* fix(android): harden canvas webview bridge

* fix(android): make canvas content access hardening explicit

* fix(android): keep webview hardening inline for CodeQL

* fix(android): avoid webview getter false positive
2026-04-27 21:41:01 -07:00
Peter Steinberger
52daf5fbd3 fix(acpx): stage Claude ACP adapter runtime dependency 2026-04-28 05:38:15 +01:00
Peter Steinberger
59bd7e47e8 docs: avoid mdx lists inside callouts 2026-04-28 05:34:44 +01:00
Peter Steinberger
b8c44bfc82 fix: restore main ci and speed tests 2026-04-28 05:34:28 +01:00
Brian Newman
055127425f fix(export): fix broken template placeholders in session export HTML (#41861)
* fix(export): fix broken template placeholders in session export HTML

The {{MARKED_JS}}, {{HIGHLIGHT_JS}}, and {{JS}} placeholders in the
export HTML template were split across multiple lines by a code
formatter, turning them into JS block statements instead of template
tokens. The generateHtml() function uses .replace('{{MARKED_JS}}', ...)
which requires contiguous strings, so the vendor JS and app code were
never injected — producing a 2MB HTML file that opens with styles and
session data but renders blank (no JS to parse/display the data).

Fix: collapse placeholders to single-line {{TOKEN}} format and add
prettier-ignore comments to prevent re-formatting.

Introduced in 9d403fd.

* fix(export): use function replacers for vendor JS injection

String.replace() interprets $ sequences ($&, $$, $', etc.) in
replacement strings. The minified vendor libraries (highlight.min.js,
marked.min.js) and the template JS contain literal $ characters that
get mutated during injection — e.g. $& becomes the matched placeholder
text, $$ becomes a single $.

Fix: use arrow function replacers for JS content so replacement text
is injected verbatim without $ interpretation. CSS and session data
use string replacers since they don't contain problematic $ patterns.

Flagged by Codex review (P2).

* ci: retrigger checks

* fix(export-session): restore inline export scripts

---------

Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>
2026-04-27 21:34:20 -07:00
Peter Steinberger
5826774076 fix(diagnostics-otel): handle liveness warnings 2026-04-28 05:32:40 +01:00
Peter Steinberger
b60eb1711a refactor(plugin-sdk): add managed task flow runtime 2026-04-28 05:32:40 +01:00
Peter Steinberger
d987e153fe docs: fix plugin architecture mdx 2026-04-28 05:32:19 +01:00
Peter Steinberger
03e0f17069 docs(changelog): consolidate 2026.4.27 notes 2026-04-28 05:31:19 +01:00
Shakker
c77aead063 docs: refresh plugin sdk api baseline 2026-04-28 05:30:04 +01:00
Shakker
31e01eb286 fix: narrow stepfun manifest provider keys 2026-04-28 05:30:04 +01:00
Shakker
d76540ff30 docs: update manifest catalog migration note 2026-04-28 05:30:04 +01:00
Shakker
c242f0c35f feat: declare stepfun model catalogs 2026-04-28 05:30:04 +01:00
Shakker
b3dce79af1 feat: declare tencent tokenhub model catalog 2026-04-28 05:30:04 +01:00
Shakker
fd484cf472 refactor: build deepseek catalog from manifest 2026-04-28 05:30:04 +01:00
Shakker
a4eb89c809 refactor: build moonshot catalog from manifest 2026-04-28 05:30:04 +01:00
Shakker
68a1dfb7e3 docs: document manifest provider catalog sdk helper 2026-04-28 05:30:04 +01:00
Shakker
a3ad2723cc fix: fail on dropped manifest catalog rows 2026-04-28 05:30:04 +01:00
Shakker
4168575b88 docs: note manifest provider catalog helper 2026-04-28 05:30:04 +01:00
Shakker
2d8ee0452e fix: normalize raw manifest provider catalogs 2026-04-28 05:30:04 +01:00
Shakker
a047144660 fix: narrow manifest catalog runtime inputs 2026-04-28 05:30:04 +01:00
Shakker
a36aeac072 fix: reject incomplete manifest provider catalogs 2026-04-28 05:30:04 +01:00
Shakker
129d5be507 refactor: build cerebras and mistral catalogs from manifests 2026-04-28 05:30:04 +01:00
Shakker
1f883f3dff refactor: build nvidia catalog from manifest 2026-04-28 05:30:04 +01:00
Shakker
833dcccddf refactor: build qianfan and xiaomi catalogs from manifests 2026-04-28 05:30:04 +01:00
Shakker
5cba55e520 feat: add manifest provider catalog helper 2026-04-28 05:30:04 +01:00
Peter Steinberger
1267a14326 docs: fix plugin architecture mdx 2026-04-28 05:29:26 +01:00
Peter Steinberger
cb1bca1a16 fix(diagnostics): export liveness warning telemetry 2026-04-28 05:28:04 +01:00
Peter Steinberger
001bf47727 chore(release): open 2026.4.27 development 2026-04-28 05:28:04 +01:00
Peter Steinberger
548f946ffd test(macos): remove conflict marker 2026-04-28 05:28:04 +01:00
Peter Steinberger
5dec95f35c test(macos): stabilize gateway control test 2026-04-28 05:28:04 +01:00
Peter Steinberger
35c9dd06b2 fix(cli): respect replace mode in model picker 2026-04-28 05:26:25 +01:00
Peter Steinberger
1a2f60c0a1 chore(browser): remove old security mock path 2026-04-28 05:21:58 +01:00
Peter Steinberger
af7f651db3 refactor(plugin-sdk): retire reserved helper exports 2026-04-28 05:21:57 +01:00
Peter Steinberger
870d993eb8 fix(ui): request configured model list 2026-04-28 05:21:08 +01:00
Peter Steinberger
000d52be37 ci: pin Google live gateway profile models 2026-04-28 05:19:33 +01:00
Vincent Koc
e8b4e39a97 fix(gateway): clear fallback context on close
Fixes gateway fallback request context cleanup on close/startup failure and shards the full gateway Vitest lane to avoid the observed memory hang.\n\nValidation:\n- Testbox: OPENCLAW_TESTBOX=1 pnpm check:changed\n- Testbox: env OPENCLAW_VITEST_MAX_WORKERS=1 /usr/bin/time -v pnpm test:gateway (254 files, 2950 tests, max RSS 4144692 KB)
2026-04-27 21:19:21 -07:00
Peter Steinberger
738f5f7508 fix: prevent channel login exec wedges 2026-04-28 05:16:43 +01:00
Peter Steinberger
ed98762832 fix: seed docs i18n codex auth 2026-04-28 05:15:38 +01:00
Peter Steinberger
843980e173 test: route more fast specs through unit-fast 2026-04-28 05:14:15 +01:00
Peter Steinberger
ab95812d65 fix: record model fallback steps in trajectories 2026-04-28 05:08:34 +01:00
Peter Steinberger
714f3b59cc fix: preserve unknown compaction failure detail 2026-04-28 05:08:34 +01:00
Shakker
34a0a9fd06 chore: benchmark startup-lazy plugins 2026-04-28 05:08:14 +01:00
Omar Shahine
4b760be1dd fix(gateway): strip SecretRef secret inputs from messages.tts.providers before talk.config hands them to speech providers (#73111)
Closes the gap left by #72496 on the parallel `messages.tts.providers.<id>` site. After #72496 landed, `talk.config` still threw `unresolved SecretRef` whenever an operator pinned a TTS apiKey or token as a SecretRef on the messages.tts side — same user-facing symptom (iOS / macOS / Control UI Talk overlays falling back to local AVSpeechSynthesizer).

Adds `stripUnresolvedSecretInputsFromBaseTtsProviders` in `src/gateway/server-methods/talk.ts` that walks each entry in `messages.tts.providers` and strips any unresolved SecretRef wrappers from the configured secret-input keys (`apiKey`, `token`) before handing the base TTS config down to `speechProvider.resolveTalkConfig`. Mirrors the `talk.providers` strip pattern from #72496.

Hardening: rebuilds the providers map with `Object.create(null)` instead of `{}` so an operator-config payload carrying `messages.tts.providers.__proto__` (or `constructor`/`prototype`) cannot mutate Object.prototype via the dynamic `cleaned[providerId] = ...` assignment. Caught by Aisle security review.

Adds three regression tests covering: SecretRef apiKey on messages.tts (the original bug), SecretRef token on messages.tts (Peter's generalization), and `__proto__`-keyed providers (Aisle hardening). All pass; full CI green (57/57) on the rebased branch.

Fixes #73109. Refs #72496.

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 21:06:28 -07:00
Peter Steinberger
97f3e6d3c2 fix: keep docs i18n codex home out of tmp 2026-04-28 05:05:06 +01:00
Peter Steinberger
1e3ce10e27 refactor(plugin-sdk): remove unused reserved helper exports 2026-04-28 05:00:53 +01:00
Peter Steinberger
4d69f81a4e fix: isolate docs i18n codex home 2026-04-28 04:58:51 +01:00
Peter Steinberger
da773cf074 test: fix startup recovery model fixture types 2026-04-28 04:57:57 +01:00
Peter Steinberger
d9a6dd0c36 ci: pin OpenAI live gateway profile model 2026-04-28 04:57:48 +01:00
Vincent Koc
9a19d8b8ea fix(bonjour): classify ciao IPv4 changed assertion
Classify ciao's IPv4 address changed assertion spelling in the Bonjour plugin and cover the exact upstream message.
2026-04-27 20:56:43 -07:00
Peter Steinberger
f6c0aa256e Revert "fix: use API-supported docs i18n model"
This reverts commit d6d0506135.
2026-04-28 04:55:06 +01:00
Peter Steinberger
fed337b164 test: speed media runtime specs 2026-04-28 04:53:57 +01:00
Vincent Koc
6f38425e5c security(gateway): route hook completion events to target agent session (#73228) 2026-04-27 20:53:52 -07:00
Peter Steinberger
0f64887623 test(gateway): preserve startup model allowlist 2026-04-28 04:53:32 +01:00
Peter Steinberger
d6d0506135 fix: use API-supported docs i18n model 2026-04-28 04:53:22 +01:00
Vincent Koc
42de56cc22 fix(ci): trust live docker harness scripts 2026-04-27 20:52:37 -07:00
Peter Steinberger
76d279fe10 docs: note gateway restart version wait 2026-04-28 04:46:32 +01:00
pickaxe
b46ff081f7 Wait for gateway version during restart 2026-04-28 04:46:32 +01:00
SymbolStar
f53ec52e7d fix(bonjour): raise stuck announcing threshold
Raise the Bonjour stuck-announcing watchdog threshold from 8s to 20s and align watchdog timer coverage so healthy 12-13s LAN announcements do not trigger false-positive advertiser teardown.
2026-04-27 20:44:08 -07:00
Peter Steinberger
c17b9fe623 chore(plugins): add SDK retirement plan report 2026-04-28 04:42:55 +01:00
Peter Steinberger
1df48506a7 test: accept codex agent model list 2026-04-28 04:42:07 +01:00
Peter Steinberger
093dba3806 fix(acpx): bundle Codex ACP adapter 2026-04-28 04:39:41 +01:00
Peter Steinberger
4fb543796b refactor(plugin-sdk): annotate dormant reserved subpaths 2026-04-28 04:39:33 +01:00
Peter Steinberger
0ff60d162c test: type heartbeat overflow model fixtures 2026-04-28 04:39:00 +01:00
Vincent Koc
b1439ca527 fix(ci): keep codex live harness helpers trusted 2026-04-27 20:37:57 -07:00
Peter Steinberger
4eb8a7d586 test: align run main commander mock 2026-04-28 04:34:41 +01:00
Peter Steinberger
995b51d309 test: fix qr cli runtime mock hoisting 2026-04-28 04:34:41 +01:00
Doncic
bf60e3ed31 fix(test): resolve vitest mock hoisting in qr-cli.test.ts 2026-04-28 04:34:41 +01:00
Peter Steinberger
0bdc1d0375 ci: hydrate provider env for testbox commands 2026-04-28 04:34:21 +01:00
Peter Steinberger
2860592302 fix(discord): hand off interactions asynchronously 2026-04-28 04:33:57 +01:00
Shakker
6f13982212 test: assert bundled startup plan metadata 2026-04-28 04:33:48 +01:00
Shakker
08cc44b57d feat: lazily load tool result middleware plugins 2026-04-28 04:33:47 +01:00
Shakker
fc3b8ad3ee fix: startup load skill workshop hooks 2026-04-28 04:33:47 +01:00
Shakker
c7b1f1285f test: fix bundled startup guard typing 2026-04-28 04:33:47 +01:00
Shakker
61ddddbe0f test: require bundled startup activation metadata 2026-04-28 04:33:47 +01:00
Shakker
86bdeb0561 perf: mark capability plugins startup lazy 2026-04-28 04:33:47 +01:00
Shakker
97016fbf02 perf: mark channel plugins startup lazy 2026-04-28 04:33:47 +01:00
Shakker
00d2c34889 perf: mark provider plugins startup lazy 2026-04-28 04:33:47 +01:00
Shakker
f1aaa2cd91 feat: declare startup plugin imports explicitly 2026-04-28 04:33:47 +01:00
Peter Steinberger
3945193257 fix: use codex for docs i18n 2026-04-28 04:33:41 +01:00
Peter Steinberger
b2d102109b fix(telegram): retry webhook registration failures 2026-04-28 04:33:22 +01:00
Peter Steinberger
5a2e5446a4 fix: explain heartbeat model bleed overflows 2026-04-28 04:32:55 +01:00
Peter Steinberger
68561a8c94 ci: use trusted codex live harness 2026-04-28 04:29:35 +01:00
Peter Steinberger
dfc14d1653 test: accept current codex status wording 2026-04-28 04:27:29 +01:00
Peter Steinberger
6c0cdf43e4 fix: honor subagent spawn model overrides 2026-04-28 04:25:31 +01:00
Peter Steinberger
e7495e2d92 ci: pass provider secrets to testbox 2026-04-28 04:24:15 +01:00
Peter Steinberger
38ba27834d chore: harden plugin boundary report 2026-04-28 04:23:53 +01:00
Peter Steinberger
073b3fbf88 test: move more runtime specs to fast lane 2026-04-28 04:23:48 +01:00
Vincent Koc
c205577f2c fix(cli): keep gateway run on fast path 2026-04-27 20:22:52 -07:00
Peter Steinberger
758262e1e3 test: keep live shard release partition unique 2026-04-28 04:20:49 +01:00
Peter Steinberger
379c43c754 test: align compatibility guard expectations 2026-04-28 04:20:49 +01:00
Peter Steinberger
070e2427bf test: remove stale root test helper bridges 2026-04-28 04:20:49 +01:00
Peter Steinberger
dab0e57914 style: format sdk helper imports 2026-04-28 04:20:49 +01:00
Peter Steinberger
896b82f430 test: align sdk helper imports 2026-04-28 04:20:49 +01:00
Peter Steinberger
aa6417b93d test: align doctor plugin manifest mocks 2026-04-28 04:20:49 +01:00
Peter Steinberger
993fee4066 fix(agents): avoid empty Anthropic tool result blocks 2026-04-28 04:20:49 +01:00
Vincent Koc
4102f8d28d fix(macos): parse model catalog without JavaScriptCore
Replaces JavaScriptCore catalog evaluation with a bounded fail-closed object-literal parser for the generated macOS model catalog.\n\nValidation: macos-node, macos-swift, security-fast, security-scm-fast, security-dependency-audit, workflow sanity checks passed on PR #73112.
2026-04-27 20:16:51 -07:00
Peter Steinberger
4b4cde7187 fix(memory): back off qmd open failures 2026-04-28 04:16:25 +01:00
Peter Steinberger
4db4d8976d ci: run release validation with trusted harness 2026-04-28 04:14:09 +01:00
Peter Steinberger
343f2d7245 fix: fail closed for invalid cron payload models 2026-04-28 04:12:54 +01:00
Peter Steinberger
00e30ba8d9 chore: add plugin boundary report 2026-04-28 04:12:30 +01:00
Gustavo Madeira Santana
ae616777f3 test(qa-matrix): cover approval metadata scenarios 2026-04-27 23:10:51 -04:00
Gustavo Madeira Santana
795e58acf2 test(matrix): cover approval metadata delivery 2026-04-27 23:10:51 -04:00
Peter Steinberger
b1a36226b1 test: stabilize faster unit lanes 2026-04-28 04:09:41 +01:00
Peter Steinberger
e11eb03182 fix: exclude plugin dependencies from backups 2026-04-28 04:03:20 +01:00
Peter Steinberger
719ec4f292 refactor: share OpenAI-compatible image provider 2026-04-28 04:01:43 +01:00
Peter Steinberger
358579b136 test: guard extension test api exports 2026-04-28 04:00:00 +01:00
Peter Steinberger
a812b8f919 test: use public plugin sdk test fixtures 2026-04-28 03:52:38 +01:00
Peter Steinberger
518d568de5 test: cover staged bundled facade deps 2026-04-28 03:52:24 +01:00
Peter Steinberger
129b996a4e refactor: tighten extension test support boundaries 2026-04-28 03:52:19 +01:00
Peter Steinberger
e5452a9c57 ci: speed up release validation 2026-04-28 03:52:05 +01:00
Peter Steinberger
f549703bed test: route more safe files to unit fast 2026-04-28 03:47:31 +01:00
Peter Steinberger
e9611e74a1 test: fix core support boundary helpers 2026-04-28 03:47:31 +01:00
Peter Steinberger
07494a43fc chore(release): publish 2026.4.26 appcast 2026-04-28 03:47:20 +01:00
Peter Steinberger
65b605569b docs: record release tweet workflow 2026-04-28 03:47:20 +01:00
Peter Steinberger
fc0a2bc87d fix: show banner on gateway fast path 2026-04-28 03:46:05 +01:00
Peter Steinberger
cfca2d4051 refactor: move remaining agent test contract files 2026-04-28 03:40:57 +01:00
Peter Steinberger
2628326264 refactor: expose agent runtime test contracts 2026-04-28 03:40:57 +01:00
Peter Steinberger
c1c9f5f1a3 test: speed up unit fast lane 2026-04-28 03:37:14 +01:00
Peter Steinberger
09a2ffc47a fix: prepare public artifact runtime deps 2026-04-28 03:34:53 +01:00
Peter Steinberger
35685e9960 refactor: centralize plugin gateway message dispatch 2026-04-28 03:28:51 +01:00
Peter Steinberger
7bf08e7344 refactor: move remaining SDK test helper files 2026-04-28 03:28:17 +01:00
Peter Steinberger
e1acb61317 refactor: expose SDK test helper subpaths 2026-04-28 03:28:17 +01:00
Shakker
21528222c3 docs: note static provider catalog manifests 2026-04-28 03:26:57 +01:00
Shakker
a30632eb28 feat: declare cerebras and mistral model catalogs 2026-04-28 03:26:57 +01:00
Shakker
7f87593548 feat: declare nvidia model catalog 2026-04-28 03:26:57 +01:00
Shakker
2d7b16e0db feat: declare qianfan and xiaomi model catalogs 2026-04-28 03:26:57 +01:00
Peter Steinberger
88068b9649 fix: prepare bundled facade runtime deps 2026-04-28 03:25:01 +01:00
Peter Steinberger
4a54682275 fix: tolerate stale plugin index channel metadata 2026-04-28 03:23:45 +01:00
Peter Steinberger
28f88ab2cc test: align extension contracts with dependency refresh 2026-04-28 03:16:12 +01:00
Shakker
13987b726a docs: show explicit startup activation in plugin examples 2026-04-28 03:13:20 +01:00
Shakker
72c4854fa0 docs: document plugin startup activation 2026-04-28 03:13:20 +01:00
Shakker
7754158292 perf: skip explicit startup opt out plugins 2026-04-28 03:13:20 +01:00
Shakker
5d52233c25 refactor: mark implicit startup sidecars deprecated 2026-04-28 03:13:20 +01:00
Shakker
b16fe2b229 feat: add plugin startup activation metadata 2026-04-28 03:13:20 +01:00
Peter Steinberger
a0a0ab4d9e fix(memory): resolve custom embedding provider ids 2026-04-28 03:11:19 +01:00
Peter Steinberger
632b0fd580 chore: update workspace dependencies 2026-04-28 03:09:44 +01:00
Peter Steinberger
bbed4ac096 test: stabilize and speed unit fast lane 2026-04-28 03:08:02 +01:00
Peter Steinberger
0835f9409a fix: route telegram cli sends through gateway 2026-04-28 03:01:22 +01:00
Peter Steinberger
662d5de746 docs: document QQBot groups and Yuanbao 2026-04-28 02:59:36 +01:00
Peter Steinberger
554f36b197 test(release): stabilize release validation waits
(cherry picked from commit a4266be808)
2026-04-28 02:59:34 +01:00
Peter Steinberger
8123db644b fix: break plugin command spec import cycle
(cherry picked from commit ced0e96cf2)
2026-04-28 02:59:16 +01:00
Shakker
197f95c94d docs: clarify refreshable model catalog authority 2026-04-28 02:59:07 +01:00
Shakker
2c1be64d97 fix: keep refreshable manifest catalogs registry backed 2026-04-28 02:59:07 +01:00
Shakker
5280b157f6 feat: declare chutes and kilocode model catalogs 2026-04-28 02:59:07 +01:00
Shakker
973a3226f0 fix: use refreshable manifest rows for provider list fast paths 2026-04-28 02:59:07 +01:00
Shakker
27a8875241 fix: append filtered registry rows in broad model lists 2026-04-28 02:59:07 +01:00
Shakker
53b53ba06b feat: declare refreshable model catalog supplements 2026-04-28 02:59:07 +01:00
Shakker
7231fcfec3 fix: avoid broad runtime catalog supplements 2026-04-28 02:59:06 +01:00
Shakker
8ac10cf164 refactor: support refreshable manifest list rows 2026-04-28 02:59:06 +01:00
Shakker
a0608af2ee docs: note broad model list normalization skip 2026-04-28 02:59:06 +01:00
Shakker
9682f3937e fix: skip runtime normalization for broad model lists 2026-04-28 02:59:06 +01:00
Shakker
8f92239fdb docs: note models list supplement speedup 2026-04-28 02:59:06 +01:00
Shakker
177da2c5a8 fix: skip resolved duplicate catalog supplements 2026-04-28 02:59:06 +01:00
Shakker
495ba0f1be fix: skip duplicate suppression for registry rows 2026-04-28 02:59:06 +01:00
Shakker
f049d9dec2 fix: avoid broad model row runtime resolution 2026-04-28 02:59:06 +01:00
Shakker
f5439a341b fix: skip broad provider runtime catalog listing 2026-04-28 02:59:06 +01:00
Shakker
9df9bbd243 refactor: support broad static catalog reads 2026-04-28 02:59:06 +01:00
Peter Steinberger
f64e4fd8cf test: split agents vitest shards 2026-04-28 02:58:24 +01:00
Peter Steinberger
fe1c7fae99 test: catch transitive gateway cold imports 2026-04-28 02:58:06 +01:00
Peter Steinberger
8b6d960539 test: move hot runtime tests to fast lane 2026-04-28 02:57:47 +01:00
Neerav Makwana
ebfc36ba8d docs(changelog): update memory fix attribution 2026-04-28 02:56:56 +01:00
Neerav Makwana
1106cc7fd2 fix(cli): skip memory eager context warmup 2026-04-28 02:56:56 +01:00
Peter Steinberger
1945389374 test: expose provider media test helpers 2026-04-28 02:52:30 +01:00
Peter Steinberger
7f3dead335 perf: keep gateway cold paths out of startup 2026-04-28 02:50:32 +01:00
Peter Steinberger
2746e2ccef test(telegram): cover handler error boundary 2026-04-28 02:50:03 +01:00
Peter Steinberger
2a3a24ebdc refactor: share media provider asset helpers (#73142)
* refactor: share openai-compatible speech providers

* refactor: tighten openai-compatible speech helper

* refactor: share image generation asset helpers

* fix: keep image helpers off root plugin sdk runtime
2026-04-28 02:44:18 +01:00
Peter Steinberger
4949f23219 docs(changelog): clarify parent CLI memory fix 2026-04-28 02:40:44 +01:00
hclsys
ba80695bba fix(cli): exit 0 when invoking parent commands without a subcommand (#73077)
Several `openclaw <parent>` commands (channels, plugins, approvals, devices,
cron, mcp) were exiting with code 1 when invoked bare, while printing the
same help-style content that `<parent> --help` produces (which exits 0).
This broke `&&` chains and surfaced a misleading
`ELIFECYCLE Command failed with exit code 1.` line under pnpm.

Add a small `applyParentDefaultHelpAction(cmd)` helper in
`src/cli/program/parent-default-help.ts` that attaches a default action
which prints the parent's own help and sets `process.exitCode = 0`. The
helper is a no-op when the parent already has its own action (e.g.
`agents` defaulting to `agents list`), so existing intentional defaults
are preserved.

Apply it to the six core parents listed in #73077.
2026-04-28 02:40:44 +01:00
Peter Steinberger
482c74b724 refactor: remove narrow SwiftLint suppressions 2026-04-28 02:38:44 +01:00
Peter Steinberger
152b9856eb test(ci): update support boundary expectations 2026-04-28 02:38:31 +01:00
Peter Steinberger
2d0cc1ee22 fix(memory): reject empty lancedb embedding config 2026-04-28 02:38:31 +01:00
Peter Steinberger
f8a15a06f2 test(models): drop suppression helper exports 2026-04-28 02:38:31 +01:00
Peter Steinberger
947aae5a99 refactor(models): move suppressions to manifests 2026-04-28 02:38:31 +01:00
Peter Steinberger
c0fdf9923b perf(agents): keep model resolution caches warm 2026-04-28 02:38:31 +01:00
Jochen Roessner
e9be25b554 perf: cache model resolution to avoid repeated plugin-provider loads
On ARM64 devices (e.g. Raspberry Pi 4), resolvePluginProviders takes ~20s
on first call. Three bugs cause this cost to be paid repeatedly:

1. ensureOpenClawModelsJson readyCache fingerprint includes models.json
   mtime. After a write, the stored fingerprint (pre-write mtime) never
   matches again, forcing every caller to re-run planOpenClawModelsJson.

2. readyCache has one entry per file path. Agents with different configs
   (e.g. main agent vs active-memory subagent) overwrite each other's
   entry, so neither benefits from caching.

3. resolveExplicitModelWithRegistry calls shouldSuppressBuiltInModel →
   resolveProviderPluginsForCatalogHooks on every agent run. The internal
   cache key includes the full config, so callers with slightly different
   configs each pay the full provider-load cost.

Fixes:
- Remove modelsFileMtimeMs from fingerprint (bug 1)
- Add noopCache to MODELS_JSON_STATE keyed by (path, mtime) — a noop
  result is config-agnostic, so any caller can reuse it (bug 2)
- Cache resolveExplicitModelWithRegistry by (provider, modelId, agentDir),
  stable for the lifetime of a gateway session (bug 3)

Measured on Raspberry Pi 4 (ARM64):
  active-memory subagent preprocessing: 66-75s → ~3s (warm)
  active-memory total elapsed:           ~96s  → ~14s (warm)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 02:38:31 +01:00
Peter Steinberger
a0c850d188 test: stabilize gateway restart loop signals 2026-04-28 02:37:24 +01:00
Peter Steinberger
3efb444002 fix(discord): skip disabled reaction fetches 2026-04-28 02:36:48 +01:00
Peter Steinberger
7d4da9c610 fix(plugins): ignore inherited npm dry-run for runtime deps 2026-04-28 02:36:48 +01:00
Peter Steinberger
13ff3142bd fix(agents): classify terminal results for fallback 2026-04-28 02:35:51 +01:00
Peter Steinberger
82ca94fdd7 test: curate google live profile signal 2026-04-28 02:32:44 +01:00
Peter Steinberger
43a73d6a31 refactor: separate bundled channel schema surface 2026-04-28 02:31:21 +01:00
Peter Steinberger
1cea04ba0f fix(ci): mock gateway run path helpers 2026-04-28 02:30:39 +01:00
Peter Steinberger
de76ad506c test: stabilize release live e2e lanes 2026-04-28 02:30:36 +01:00
Shakker
d9411f9dc1 perf: reuse startup plugin manifests 2026-04-28 02:29:08 +01:00
Shakker
2aacc4053b refactor: accept supplied plugin manifest registry 2026-04-28 02:29:08 +01:00
Peter Steinberger
8db21cdcde chore: update app Swift package releases 2026-04-28 02:28:05 +01:00
Peter Steinberger
e651809084 perf: slim gateway startup imports 2026-04-28 02:26:27 +01:00
Peter Steinberger
b6a90188e7 test: trim hot test runtime imports 2026-04-28 02:25:55 +01:00
Peter Steinberger
fe15268e5f fix: degrade plugin-local reload invalidity 2026-04-28 02:25:00 +01:00
Peter Steinberger
06a80fa813 fix(ci): use managed temp dir in channel contracts 2026-04-28 02:20:01 +01:00
Peter Steinberger
b891dbb133 test: curate openrouter live profile signal 2026-04-28 02:17:48 +01:00
Peter Steinberger
837c4c5f1b fix: respect external channel owners in doctor blockers 2026-04-28 02:15:43 +01:00
Peter Steinberger
6a338ba67d test(cli): align run-main primary registration expectations 2026-04-28 02:14:27 +01:00
Peter Steinberger
d35ada2f54 refactor: relocate channel contract helpers 2026-04-28 02:14:08 +01:00
Peter Steinberger
a66605bf23 fix(cron): skip isolated runs when local providers are down 2026-04-28 02:12:19 +01:00
Peter Steinberger
4e63f710f1 fix(ci): restore plugin install and tooling checks 2026-04-28 02:09:28 +01:00
Peter Steinberger
7c79f0ac9c fix(telegram): centralize update offset tracking 2026-04-28 02:08:22 +01:00
Peter Steinberger
955f0a692a perf: fast-path gateway foreground startup 2026-04-28 02:07:01 +01:00
Peter Steinberger
6b7886e024 test: refresh memory install config fixture 2026-04-28 02:04:24 +01:00
Peter Steinberger
dc4512ad0c refactor: split channel target test helpers 2026-04-28 02:03:15 +01:00
Peter Steinberger
6c859d8c82 fix(memory-lancedb): use neutral memory host import 2026-04-28 01:59:41 +01:00
Peter Steinberger
53906fd177 test: update run-main env mock 2026-04-28 01:59:25 +01:00
Peter Steinberger
a9bd8bb9b4 fix(gateway): surface clean channel exits 2026-04-28 01:59:10 +01:00
Peter Steinberger
53d213f9cc perf: lazy load hot test imports 2026-04-28 01:57:22 +01:00
Peter Steinberger
f5a48efac5 fix(status): report custom memory plugin status 2026-04-28 01:51:37 +01:00
Peter Steinberger
37ea03dbac fix(memory-lancedb): use scoped config runtime import 2026-04-28 01:50:09 +01:00
Peter Steinberger
75e126ef6a perf: improve gateway startup diagnostics 2026-04-28 01:48:00 +01:00
Peter Steinberger
13d3777cf3 fix(plugins): keep config schema on manifest metadata 2026-04-28 01:47:16 +01:00
Peter Steinberger
45a84b5f95 refactor: expose channel contract test helpers 2026-04-28 01:45:58 +01:00
Peter Steinberger
8d9a2f82a4 fix(gateway): keep bundled channel startup light 2026-04-28 01:44:40 +01:00
Peter Steinberger
983fd775e2 fix(memory-core): stream embedding cache seed during reindex
- stream safe-reindex embedding-cache seeding with SQLite iterate()
- avoid no-op empty-cache transactions and keep regression coverage explicit
- supersedes #73067

Thanks @parkertoddbrooks.
2026-04-28 01:44:03 +01:00
Peter Steinberger
2057713af5 fix(memory): let lancedb use provider embedding auth 2026-04-28 01:42:43 +01:00
Peter Steinberger
b294f7c467 fix: harden ios app build hygiene 2026-04-28 01:42:10 +01:00
Peter Steinberger
2fe213ebf2 perf: avoid global config loads in approval tests 2026-04-28 01:41:16 +01:00
Peter Steinberger
4cc42a1d69 fix: reuse plugin metadata for config schemas 2026-04-28 01:37:38 +01:00
Vincent Koc
d93e6f6158 fix(feishu): repair WebSocket reconnect and heartbeat config (#72411) 2026-04-27 17:32:36 -07:00
Peter Steinberger
fdd2ff02c6 ci: stabilize release validation lanes 2026-04-28 01:31:00 +01:00
Peter Steinberger
6ebe3087fc test: narrow live gateway profile signal 2026-04-28 01:30:59 +01:00
TinyClaw
fb5b46ae48 fix(bonjour): suppress ciao crash when networkInterfaces() is denied
Classify ciao interface-enumeration SystemErrors from restricted sandboxes and suppress mDNS advertising instead of letting the Gateway crash.
2026-04-27 17:30:43 -07:00
Peter Steinberger
c72f8f357b fix: harden mac app computer use docs 2026-04-28 01:25:31 +01:00
Peter Steinberger
864c4f7ff4 fix(memory-core): bound fallback vector chunk scoring
- stream fallback Memory Core vector scoring with SQLite iterate() and a bounded top-K result set
- add regression coverage and live-main lint/boundary helper repairs
- supersedes #73069

Thanks @parkertoddbrooks.
2026-04-28 01:23:40 +01:00
Peter Steinberger
56875c4d32 refactor: split generic plugin test fixtures 2026-04-28 01:21:39 +01:00
Peter Steinberger
e508d81f79 perf: avoid registry loads in hot tests 2026-04-28 01:20:47 +01:00
Peter Steinberger
6b1089ffe5 fix: keep group silence on no-reply path 2026-04-28 01:20:00 +01:00
Peter Steinberger
4d4c7c8ab3 fix(plugins): time out hanging agent end hooks 2026-04-28 01:18:50 +01:00
Peter Steinberger
067888a608 fix: surface npm plugin install errors 2026-04-28 01:18:02 +01:00
Peter Steinberger
f34b41f198 refactor: split plugin sdk test helpers 2026-04-28 01:14:19 +01:00
Vincent Koc
d88610cf2b test: avoid bundled extension boundary false positive 2026-04-27 17:13:21 -07:00
Peter Steinberger
48a0be8ff3 docs(plugins): document channel route sdk 2026-04-28 01:13:01 +01:00
Peter Steinberger
e27c32b9b0 refactor(plugin-sdk): publish route helpers 2026-04-28 01:13:01 +01:00
Peter Steinberger
f368d3b49f refactor(channels): share route identity keys 2026-04-28 01:13:00 +01:00
Peter Steinberger
3eec9e4642 refactor(channels): reuse route context helpers 2026-04-28 01:13:00 +01:00
Peter Steinberger
3876682635 refactor(channels): centralize route normalization 2026-04-28 01:13:00 +01:00
Peter Steinberger
0294aebe6f feat(providers): add DeepInfra provider plugin (#73038)
* feat(providers): add DeepInfra provider plugin

* feat(deepinfra): add media provider surfaces

* fix(deepinfra): satisfy provider boundary checks

* docs: add gitcrawl maintainer skill

* test: include deepinfra in live media sweeps

* fix: remove stale tts contract import
2026-04-28 01:12:54 +01:00
Peter Steinberger
1fde7dbc0e fix(memory): support embedding providers without encoding format 2026-04-28 01:12:34 +01:00
Peter Steinberger
100c595fbc test: fix host hook contract helper import 2026-04-28 01:11:56 +01:00
Peter Steinberger
ae7f365fbc fix: stop native approval auth retry loops 2026-04-28 01:10:04 +01:00
EVA
1adaa28dc8 [plugin sdk] Add generic plugin host-hook contracts (#72287)
Merged via squash.

Prepared head SHA: 68e5f2ce19
Co-authored-by: 100yenadmin <239388517+100yenadmin@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-04-27 17:07:02 -07:00
Peter Steinberger
ef1e97472f fix: remove stale tts contract import 2026-04-28 01:05:54 +01:00
Peter Steinberger
1d3170b16f fix: scope skills cli to active agent workspace 2026-04-28 01:05:36 +01:00
Peter Steinberger
32d76e2429 fix(memory): bound lancedb recall embedding queries 2026-04-28 00:58:30 +01:00
Peter Steinberger
47f40788cf ci: install ffmpeg for live audio media shard 2026-04-28 00:57:43 +01:00
Peter Steinberger
7f77ecff77 chore: refresh plugin sdk api baseline 2026-04-28 00:55:11 +01:00
Peter Steinberger
8057561cee refactor: promote plugin test helpers to sdk 2026-04-28 00:55:11 +01:00
Peter Steinberger
49d069cd94 test: distinguish release live shard partitions 2026-04-28 00:54:28 +01:00
Peter Steinberger
7aeb7c2a14 perf: speed up reset model tests 2026-04-28 00:52:07 +01:00
Peter Steinberger
da3cf1c1a8 fix: preserve bundled facade fallback semantics 2026-04-28 00:50:34 +01:00
Peter Steinberger
b90f29d313 ci: split native live release shards 2026-04-28 00:49:10 +01:00
Peter Steinberger
3f94f25a3c test(plugins): parse boundary import syntax 2026-04-28 00:46:15 +01:00
pashpashpash
a412603bad fix(codex): honor effective stdio env for fallback auth 2026-04-28 00:46:15 +01:00
pashpashpash
401ae38f13 fix(codex): keep env fallback local to stdio app-server 2026-04-28 00:46:15 +01:00
Peter Steinberger
5f15bea6ce fix(codex): bootstrap app-server auth fallback 2026-04-28 00:46:15 +01:00
pashpashpash
a1c88f3ebe fix(codex): hash app-server env values in client keys 2026-04-28 00:46:15 +01:00
pashpashpash
20ff49f7c8 fix(codex): auto-clear api key for subscription auth 2026-04-28 00:46:15 +01:00
pashpashpash
aeb007e4e5 fix(codex): expose app-server env controls 2026-04-28 00:46:15 +01:00
Peter Steinberger
09c39463bb test: tolerate xAI realtime STT brand spelling 2026-04-28 00:45:14 +01:00
Peter Steinberger
f3d53ce22c fix: clarify memory embedding concurrency help 2026-04-28 00:39:18 +01:00
Peter Steinberger
697d85aefe fix: auto-register bundled computer use marketplace 2026-04-28 00:36:19 +01:00
Peter Steinberger
802f13ac15 fix(memory): cap ollama non-batch embedding concurrency 2026-04-28 00:34:18 +01:00
Peter Steinberger
5de3196a60 test: satisfy plugin contract boundaries 2026-04-28 00:33:46 +01:00
Peter Steinberger
0aef33f6c4 perf: reduce persistent dedupe test disk work 2026-04-28 00:31:06 +01:00
Peter Steinberger
fc055e2393 fix: speed up Telegram status diagnostics 2026-04-28 00:28:22 +01:00
Peter Steinberger
3ae796b649 test: keep SDK testing off bundled inventory 2026-04-28 00:28:09 +01:00
Peter Steinberger
0a0d934725 test: relax OpenAI live transcription assertion 2026-04-28 00:27:37 +01:00
Peter Steinberger
90b6665ded refactor: move plugin api test helper to sdk 2026-04-28 00:24:54 +01:00
Peter Steinberger
f71f5bc586 fix: repair packaged plugin runtime mirrors 2026-04-28 00:23:38 +01:00
Peter Steinberger
152e30935f fix: use public provider test helpers in live image test 2026-04-28 00:17:29 +01:00
Peter Steinberger
56ef6334f0 perf: combine pty exec coverage 2026-04-28 00:17:03 +01:00
Peter Steinberger
62f8cff33a fix: avoid full runtime dependency restaging 2026-04-28 00:15:15 +01:00
Peter Steinberger
d462d1faf2 refactor: move plugin contracts onto SDK testing seams 2026-04-28 00:14:58 +01:00
Peter Steinberger
d3e4640bed fix(acpx): ignore Codex ACP timeout config 2026-04-28 00:12:34 +01:00
Peter Steinberger
d74c8423c7 test: fix plugin runtime env test types 2026-04-28 00:11:47 +01:00
Peter Steinberger
1776840c57 fix: preserve typed runtime env casts 2026-04-28 00:08:32 +01:00
Peter Steinberger
05a93c1788 perf: avoid sdk client setup in openai transport test 2026-04-28 00:07:29 +01:00
Peter Steinberger
2fbbc6e2fa docs: clarify plugin disable doctor behavior 2026-04-28 00:07:02 +01:00
Peter Steinberger
f1edd601bc ci: split release qa parity lanes 2026-04-28 00:05:33 +01:00
Peter Steinberger
ff2b2e769f fix(cron): preserve job model fallbacks 2026-04-28 00:03:01 +01:00
Peter Steinberger
da6d8940a0 refactor: clean runtime env helper types 2026-04-28 00:02:24 +01:00
Peter Steinberger
ccc9dd5eef fix: keep session history redaction forced 2026-04-27 23:59:47 +01:00
Peter Steinberger
5e8cc1d9c2 docs: add changelog for plugin disable startup fast path (#73041) 2026-04-27 23:57:31 +01:00
Intern Dev
f07844450c Prevent disabled plugins from warming the gateway plugin graph
A local containment profile uses plugins.enabled=false to stop plugin and channel runtime churn. The previous startup path still built plugin lookup tables and doctor stale scans despite the global disable, which made the switch noisy and slow.

Constraint: plugins.enabled=false must leave channel blocker warnings intact while treating stale plugin config as inert.
Rejected: Clear user plugin config automatically | would mutate a reversible containment setting.
Confidence: high
Scope-risk: narrow
Directive: Do not reintroduce plugin registry discovery before checking plugins.enabled.
Tested: pnpm test src/gateway/server-startup-plugins.test.ts src/config/plugin-auto-enable.core.test.ts src/commands/doctor/shared/stale-plugin-config.test.ts src/commands/doctor/shared/preview-warnings.test.ts
Tested: pnpm check:changed
Tested: pnpm build
2026-04-27 23:57:31 +01:00
Peter Steinberger
5bdfc251ff test(plugins): assert runtime mirror reload stability 2026-04-27 23:57:12 +01:00
Peter Steinberger
c27b82d431 perf: avoid heavy imports in hot tests 2026-04-27 23:57:00 +01:00
Peter Steinberger
39a2d1da96 docs(codex): add computer use guide 2026-04-27 23:56:25 +01:00
Peter Steinberger
78d3fce5f9 fix: preserve OpenAI encrypted reasoning replay 2026-04-27 23:54:16 +01:00
Peter Steinberger
ea2d95e23e refactor(codex): clarify computer use setup state 2026-04-27 23:53:53 +01:00
Peter Steinberger
87345c0667 fix: narrow bundled runtime mirror materialization 2026-04-27 23:52:52 +01:00
Peter Steinberger
9f9bcfe231 perf: reduce hot test imports and duplicate scans 2026-04-27 23:47:26 +01:00
Peter Steinberger
f7815cdd8f fix(codex): harden computer use setup states 2026-04-27 23:46:16 +01:00
Peter Steinberger
f7983a07a4 refactor: move plugin runtime env helper 2026-04-27 23:45:26 +01:00
Peter Steinberger
0df6e5a473 refactor: expose plugin test helpers via sdk 2026-04-27 23:45:26 +01:00
Peter Steinberger
6f09039b0c fix(plugins): reuse unchanged runtime mirrors 2026-04-27 23:45:02 +01:00
JK
323030594e fix(agents): resolve model aliases in sessions_spawn (#59681)
* fix(agents): resolve model aliases in sessions_spawn

normalizeModelSelection() only trims the input — it never resolves
aliases through the model alias index. When a user passes an alias
like 'opus' to sessions_spawn, the child session gets patched with
the raw string, which the gateway cannot match to any provider.

Add resolveModelThroughAliases() to check bare strings against the
configured alias map before returning from
resolveSubagentSpawnModelSelection().

Fixes #57532
Refs #50736

* refactor: address review feedback on alias resolution

- Accept pre-built ModelAliasIndex instead of rebuilding per call
- Narrow helper signature to (string, ModelAliasIndex) → string
- Remove unreachable ?? raw fallback

Co-Authored-By: greptile-apps[bot]

* fix(agents): resolve sessions_spawn model aliases

---------

Co-authored-by: HowdyDooToYou <HowdyDooToYou@users.noreply.github.com>
Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>
2026-04-27 15:44:56 -07:00
Olamiposi
c51e315f3a docs: clarify messaging vs full tool profiles (#39954)
* docs: clarify messaging vs full tool profiles

* docs: normalize tools.profile references

* docs: clarify messaging and full tool profiles

---------

Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>
2026-04-27 15:44:17 -07:00
Vincent Koc
cc80a40d86 fix(ci): preserve mixed macOS CodeQL SARIF findings
Conservatively filter macOS CodeQL SARIF by dropping only findings where every location is SwiftPM build output. Verified with workflow sanity, local jq filtering, PR CI, and a failed-job rerun for an unrelated stalled Vitest shard.
2026-04-27 15:43:53 -07:00
neilofneils404
482ff924ef fix: pass directories to provider stream wrappers (#67843)
* fix: pass directories to provider stream wrappers

* fix: pass directories to provider stream wrappers

---------

Co-authored-by: neilofneils404 <258699186+neilofneils404@users.noreply.github.com>
Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>
2026-04-27 15:43:38 -07:00
Vincent Koc
94f5827c6e docs(logging): note Control UI tool payload redaction
Document the redaction surface added in f3e8c50df3: custom logging.redactPatterns now apply to Control UI tool start args, partial/final result payloads, derived exec output, and patch summaries on top of the built-in defaults.
2026-04-27 15:39:49 -07:00
Peter Steinberger
39e3d8d31d ci: shard release validation reruns 2026-04-27 23:38:13 +01:00
Peter Steinberger
d2320e4d4b fix(models): keep user model switches strict 2026-04-27 23:32:44 +01:00
Peter Steinberger
496a5eb56f fix: dedupe silent reply prompt guidance 2026-04-27 23:31:13 +01:00
Peter Steinberger
ccfa0c1964 docs: clarify hook config and feishu policy 2026-04-27 23:30:57 +01:00
volcano303
f3e8c50df3 fix(agents): redact Control UI tool payload secrets (#72319)
Fixes #72283.

- Redacts Control UI tool start args, partial/final result payloads, derived exec output, and patch summaries before event emission.
- Forces tool/UI payload redaction to include built-in patterns plus configured custom `logging.redactPatterns`.
- Covers object, details-only, primitive string, and top-level array tool-result shapes.

Tests:
- `pnpm test src/agents/pi-embedded-subscribe.tools.test.ts src/agents/pi-embedded-subscribe.handlers.tools.test.ts`
- `pnpm check:changed`

Co-authored-by: volcano303 <75143900+volcano303@users.noreply.github.com>
Co-authored-by: Val Alexander <bunsthedev@gmail.com>
2026-04-27 23:30:50 +01:00
Vincent Koc
24c39de9c1 test(memory): allow packed index suite timeout
Allow the memory index suite to exceed the global 120s test timeout when it runs inside a packed extension shard. The scoped Vitest config is reset after the file.
2026-04-27 15:30:47 -07:00
Peter Steinberger
dd0f5937d2 fix(doctor): avoid companion gateway service false positives 2026-04-27 23:30:29 +01:00
Peter Steinberger
36d3722a96 fix(cli): disable source checkout compile cache 2026-04-27 23:28:17 +01:00
Vincent Koc
6e77c10c6c fix(ci): harden macOS CodeQL SARIF filtering
Harden the macOS CodeQL SARIF filter to drop only findings whose primary location is SwiftPM build output. Verified with workflow sanity, local jq filtering, full PR CI, and profile=macos-security branch proof in 18m44s.
2026-04-27 15:25:38 -07:00
Peter Steinberger
0cc3c027a8 test: avoid slow home lookups in service audit tests 2026-04-27 23:23:15 +01:00
Peter Steinberger
48e91f09d5 fix(cli): fail empty local model probes 2026-04-27 23:16:39 +01:00
Peter Steinberger
81390c643b fix(update): restart Windows startup gateway after update 2026-04-27 23:16:20 +01:00
Peter Steinberger
abf5dea7dd fix(daemon): filter missing service path fallbacks 2026-04-27 23:16:04 +01:00
Peter Steinberger
bf4306d1b0 refactor: route plugin test helpers through sdk 2026-04-27 23:12:21 +01:00
Peter Steinberger
7975305a89 test: cover trusted-proxy secret surfaces 2026-04-27 23:10:22 +01:00
Peter Steinberger
1a98938479 fix: allow trusted-proxy local password fallback 2026-04-27 23:10:22 +01:00
Vincent Koc
61a18e5596 fix(agent): preserve default-agent session routing compatibility (#72414)
* fix(agent): preserve default-agent session routing compatibility

* fix(clownfish): address review for ghcrawl-207038-agentic-merge (1)

* fix(agent): migrate legacy default-agent sessions

* fix(slack): use narrow agent runtime import
2026-04-27 15:09:01 -07:00
Peter Steinberger
5488175b22 test: give xai live search more headroom 2026-04-27 23:07:52 +01:00
Peter Steinberger
42dddbbe78 fix(cli): streamline local model probes 2026-04-27 23:02:26 +01:00
Peter Steinberger
d7dcd0e21e test: stabilize release validation lanes 2026-04-27 23:00:45 +01:00
Peter Steinberger
6f80ba7b78 fix(test): avoid memory provider discovery in registration test 2026-04-27 22:58:55 +01:00
Peter Steinberger
8599fdda4a test: keep extension mocks on sdk seams 2026-04-27 22:55:09 +01:00
Peter Steinberger
c35a96bcbc fix(test): use focused plugin sdk test seams 2026-04-27 22:47:57 +01:00
Peter Steinberger
24b45a038c fix(gateway): bound supervised lock recovery 2026-04-27 22:44:37 +01:00
Peter Steinberger
43ababf96b fix(gateway): keep startup sidecars responsive 2026-04-27 22:44:37 +01:00
Peter Steinberger
75c03b28e0 test(memory): reset timers in index suite 2026-04-27 22:41:56 +01:00
Peter Steinberger
d519dc6976 docs(channels): add channel docking concept 2026-04-27 22:37:58 +01:00
Vincent Koc
2c2a240344 fix(ci): filter macOS CodeQL dependency SARIF
Filter SwiftPM dependency build results from the manual macOS CodeQL shard before upload. Verified with workflow sanity, local jq filtering, and profile=macos-security branch proof in 15m54s. PR CI has the same unrelated extensions/memory-core timeout failure currently present on main.
2026-04-27 14:37:29 -07:00
Peter Steinberger
7807e8118c perf(test): slim codex web search test imports 2026-04-27 22:34:48 +01:00
Peter Steinberger
a8c548f4f3 test: route extension tests through sdk seams 2026-04-27 22:34:21 +01:00
Peter Steinberger
46ba8e7cce feat(plugin-sdk): expose extension test seams 2026-04-27 22:34:21 +01:00
Peter Steinberger
582debbec8 docs(channels): explain dock commands 2026-04-27 22:32:44 +01:00
Peter Steinberger
d24b78e96d test(extensions): use scoped config runtime imports 2026-04-27 22:24:30 +01:00
Peter Steinberger
2216ce3018 test: use narrow config sdk imports 2026-04-27 22:22:34 +01:00
Omar Shahine
da3d17e1ca fix(tts): pre-transcode synthesized audio to opus-in-CAF for native iMessage voice-memo bubbles via BlueBubbles (#72586)
End-to-end testing on macOS + BlueBubbles + ElevenLabs walked through three CAF flavors before landing on the format Apple's Messages.app actually emits when a user records a native iMessage voice memo:

- PCM int16 @ 44.1 kHz CAF: BlueBubbles' internal `afconvert -f m4af -d aac` conversion fails; the original CAF reaches iMessage but renders with 0 s duration.
- AAC @ 22.05 kHz mono CAF: BlueBubbles' conversion succeeds and the server silently downgrades the delivery, sending the converted MP3 as a generic audio attachment.
- **Opus @ 24 kHz mono CAF**: byte-identical to the descriptor block Apple's Messages.app produces; BlueBubbles passes it through unchanged and iMessage renders a native voice-memo bubble with proper duration and waveform UI.

Adds an opt-in `tts.voice.preferAudioFileFormat` channel capability and a macOS `afconvert`-backed pre-transcode in the speech-core pipeline. BlueBubbles declares `preferAudioFileFormat: "caf"`. Other channels are unaffected. Falls back to the original buffer when the host platform, the source/target pair, or the transcoder process can't produce the preferred container — so non-Darwin hosts and unsupported provider combinations are unchanged.

Also adds a `caff` magic-byte sniff in `src/media/mime.ts` so the auto-reply host-local-media validator (which uses `file-type` and didn't recognize CAF natively) accepts the buffer instead of dropping it as "⚠️ Media failed."

Fixes #72506.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 14:15:16 -07:00
Peter Steinberger
fb4d9fc4fb ci: harden npm telegram artifact upload 2026-04-27 22:13:21 +01:00
Peter Steinberger
295d63c331 ci: record package proof in release evidence 2026-04-27 22:00:03 +01:00
Peter Steinberger
1eea534ddb fix(channels): handle generated dock commands 2026-04-27 21:59:15 +01:00
Peter Steinberger
74e62c32c3 test: route extension tests through sdk subpaths 2026-04-27 21:58:48 +01:00
Peter Steinberger
662de55e07 refactor: expose extension sdk boundary seams 2026-04-27 21:58:48 +01:00
Peter Steinberger
3e497f5e2b fix: accept cron delivery thread ids 2026-04-27 21:56:47 +01:00
Peter Steinberger
18ef83c0da fix(feishu): preserve disabled group policy for explicit groups 2026-04-27 21:55:33 +01:00
Peter Steinberger
b3bc60ae25 fix(msteams): unwrap jwt runtime deps 2026-04-27 21:53:51 +01:00
Vincent Koc
bd51f82efa fix(security): harden CodeQL secret ref validation
Remediate current-profile CodeQL findings for file SecretRef id validation and release workflow job permissions. Includes changelog credit. Thanks @vincentkoc.
2026-04-27 13:53:27 -07:00
Peter Steinberger
f2ba8ca927 test: stabilize bundled channel docker smoke 2026-04-27 21:48:26 +01:00
Peter Steinberger
1787d3be07 fix(gateway): scope startup provider discovery 2026-04-27 21:45:54 +01:00
Peter Steinberger
28d9fc5f20 fix(test): include cron delivery thread id in schema keys 2026-04-27 21:43:12 +01:00
Peter Steinberger
db622c67d1 perf(test): slim directive and run-param imports 2026-04-27 21:42:31 +01:00
Vincent Koc
36b5e34fc0 fix(ci): add macOS CodeQL security shard
Add a manual macOS CodeQL security shard scoped to app sources. Verified with profile=macos-security on Blacksmith in 16m55s.
2026-04-27 13:40:34 -07:00
Peter Steinberger
b6be422306 fix(cron): accept threaded delivery in gateway schema 2026-04-27 21:37:18 +01:00
Peter Steinberger
599b1b8462 fix(cloudflare-ai-gateway): strip anthropic thinking prefill 2026-04-27 21:36:50 +01:00
Vincent Koc
013939cfc7 fix(gateway): preserve repeated characters in chat stream merge (#72400)
* fix(gateway): preserve repeated characters in chat stream merge

* fix(gateway): cap live chat stream buffers
2026-04-27 13:35:57 -07:00
Peter Steinberger
59faa023fe fix(gateway): unblock sidecar startup 2026-04-27 21:34:44 +01:00
Peter Steinberger
e60905d754 fix: harden bonjour DNS label truncation (#73022) 2026-04-27 21:33:02 +01:00
Peter Steinberger
7d2d8af3ab fix(plugins): fast-path strict manifest json 2026-04-27 21:27:02 +01:00
Peter Steinberger
11e6928b3e fix: keep runtime context out of user turns 2026-04-27 21:24:56 +01:00
Gustavo Madeira Santana
b9fd13e8d7 qa-matrix: add streaming tool progress scenarios 2026-04-27 16:21:37 -04:00
Gustavo Madeira Santana
3132f4990c qa-lab: generalize tool progress prompts 2026-04-27 16:21:36 -04:00
Gustavo Madeira Santana
24068f19c6 matrix: stream tool progress in previews 2026-04-27 16:21:34 -04:00
MoerAI
01e153986a fix(feishu): admit groups explicitly listed under channels.feishu.groups (#67687)
Feishu config defaults groupPolicy to 'allowlist'. Inbound group handling read groupAllowFrom and called isFeishuGroupAllowed before resolveFeishuReplyPolicy was reached, so a config that only set channels.feishu.groups.<chat_id>.requireMention=false (with no groupAllowFrom) was rejected with 'group not in groupAllowFrom' before per-group requireMention could take effect. Treat the explicit presence of a group entry under channels.feishu.groups as the operator's allowlist signal: if groupConfig is defined, skip the empty-allowlist rejection. resolveFeishuReplyPolicy still owns mention gating, and existing groupConfig.enabled=false / groupAllowFrom-driven rejections are preserved. Adds a regression test that exercises the reporter's exact config shape and confirms inbound text reaches finalize/dispatch.
2026-04-27 21:19:49 +01:00
Peter Steinberger
346d5c28c1 test(acp): use typed attachment root fixture 2026-04-27 21:19:45 +01:00
Peter Steinberger
8cc06fff2c test(acp): cover media agent dir dispatch 2026-04-27 21:19:45 +01:00
luyao618
2b578c3a9e fix(agents): pass agentDir to media understanding in ACP dispatch path
The ACP dispatch path calls applyMediaUnderstanding without the agentDir
parameter. This prevents the media understanding pipeline from locating
agent-specific models.json and auth profiles, causing image understanding
to fail silently for non-visual models configured with a separate image
understanding model.

The non-ACP reply path (get-reply.ts) already passes agentDir correctly.
This aligns the ACP path with the same behavior.

Closes #55046

AI-assisted (built with Hermes orchestration).
2026-04-27 21:19:45 +01:00
Peter Steinberger
be2196c6cb test(plugins): cover hook plugin config context 2026-04-27 21:19:41 +01:00
Ayumi Server
c1187109c8 fix: shallow-copy event to avoid mutating shared hook object
Address review feedback on PR #72888. triggerInternalHook passes the
same event reference to all handlers sequentially. Mutating evt.context
leaks pluginConfig to subsequent handlers and causes cross-plugin
overwrites. Shallow-copy event and context instead.
2026-04-27 21:19:41 +01:00
Ayumi Server
ed0b098d75 fix: inject pluginConfig into hook handler event context
When plugins register hooks via api.registerHook(), pluginConfig from
openclaw.json was not available in the hook event context. Plugins that
accessed ctx.pluginConfig or event.context.pluginConfig received
undefined, causing silent failures or fallback to defaults.

Changes:
- Add pluginConfig parameter to registerHook() function
- Wrap handler to inject pluginConfig into event.context before invocation
- Pass params.pluginConfig through createApi() call site

Fixes #72880
2026-04-27 21:19:41 +01:00
RayWoo
ad6e1cd3a0 fix(memory-core): raise NARRATIVE_TIMEOUT_MS from 15s to 60s
Closes #72837. The 15s narrative-subagent timeout was empirically too
tight for warm-gateway runs across light, REM, and deep phases —
gpt-5.4-mini latency through OpenAI alone routinely brushes 12s+, so the
first sweep after a restart deterministically times out across all three
phases. 60s gives realistic LLM-call headroom while still capping the
worst case at one minute, preserving the original comment's "don't leave
parent cron running for minutes" constraint.

Test: updates the matching toMatchObject assertion in
dreaming-narrative.test.ts from 15_000 to 60_000.
2026-04-27 21:19:38 +01:00
Vincent Koc
16322d5cfc fix(bonjour): harden DNS label truncation 2026-04-27 21:19:26 +01:00
luyao618
9ac0b7edbc fix(bonjour): truncate mDNS service name and hostname to 63-byte DNS label limit
When the system hostname exceeds 63 bytes (common with Kubernetes pod
names), the @homebridge/ciao DNS label encoder throws an AssertionError
that crashes the gateway on startup.

Add truncateToDnsLabel() that safely truncates UTF-8 strings at byte
boundaries, applied to both the service instance name and hostname
before passing them to ciao.

Closes #37705

AI-assisted (built with Hermes orchestration).
2026-04-27 21:19:26 +01:00
ryuhaneul
f5b01c1e0e fix(docker): install ca-certificates in slim runtime base
Commit 2cd23957c0 ("build: use slim docker runtime") switched the
runtime image from `node:24-bookworm` (full) to `node:24-bookworm-slim`.
The slim base does not ship `ca-certificates`, and the runtime stage's
`apt-get install` line was not updated to add it.

Result on the resulting image:
- `/etc/ssl/certs/` is empty (`ls /etc/ssl/certs/ | wc -l` == 0)
- `dpkg -l ca-certificates` reports `un` (not installed)
- `update-ca-certificates` is missing in `$PATH` (exit 127)
- every HTTPS outbound from the gateway dies at TLS handshake with
  `error setting certificate file: /etc/ssl/certs/ca-certificates.crt`
- channel plugins that use `node fetch` (telegram/discord/slack)
  crash-loop with `Network request for 'deleteWebhook' failed!`
  and pin the gateway main thread at ~100% CPU on retry.

Verified by rebuilding the runtime image with this patch and
confirming inside the container:
- `ls /etc/ssl/certs/ | wc -l` -> 285
- `curl -4 https://api.telegram.org/` -> 302
- `curl -4 https://www.google.com/`   -> 200
- channel plugins (telegram/discord/slack) register cleanly,
  gateway main-thread CPU returns to idle.

Add `ca-certificates` to the apt-install list and call
`update-ca-certificates` to populate the CA bundle.

Signed-off-by: ryuhaneul <luj.moonlight@gmail.com>
2026-04-27 21:19:22 +01:00
iot2edge
98928388db fix(cli): clarify completion cache timeout message after openclaw update
When the post-update completion cache refresh times out (slow disk,
large bundled plugin tree, Docker overlayfs), the user previously saw
the opaque 'Completion cache update failed: Error: spawnSync
/usr/bin/node ETIMEDOUT'. Detect ETIMEDOUT specifically, surface
'timed out after 30s', and append a manual refresh hint pointing at
'openclaw completion --write-state' so users know it's non-fatal and
how to recover.

Fixes #72842
2026-04-27 21:19:18 +01:00
Peter Steinberger
cdf88bcad4 test: harden release qa live gates 2026-04-27 21:16:48 +01:00
Peter Steinberger
71c74b766e fix(plugins): avoid hand-built extension path markers 2026-04-27 21:12:09 +01:00
Peter Steinberger
465b621cf1 fix(sessions): avoid guarded route-only entries 2026-04-27 21:11:12 +01:00
Peter Steinberger
d62cb3c681 docs(changelog): credit pending low-risk fixes 2026-04-27 21:09:20 +01:00
Peter Steinberger
911be12648 docs: credit bare reset transcript fix 2026-04-27 21:08:50 +01:00
Maho Pan
1dbc250b1a fix: keep bare reset transcript prompt non-empty 2026-04-27 21:08:50 +01:00
Peter Steinberger
03bfdbb052 fix: stage mirrored bundled runtime deps 2026-04-27 21:07:40 +01:00
Peter Steinberger
ff52e281aa perf(test): slim responses payload policy imports 2026-04-27 21:06:40 +01:00
Peter Steinberger
08e7561972 ci: broaden extension boundary guards 2026-04-27 21:02:53 +01:00
Peter Steinberger
e9b1fbb8c4 refactor: pin remaining extension api surfaces 2026-04-27 21:02:53 +01:00
Peter Steinberger
221bfc8929 docs: credit media MIME sanitizer fix 2026-04-27 21:02:30 +01:00
volcano303
e7b87217a2 fix(media): anchor sanitizeMimeType regex and reject trailing junk
Add an end anchor to the type/subtype match and explicitly accept the
RFC 9110 ;parameter tail. Inputs like "image/png<script>" or
"application/json garbage" now return undefined instead of silently
matching the leading prefix.

Closes #9795
2026-04-27 21:02:30 +01:00
Peter Steinberger
1f256306c9 test: align gateway tests with config io split 2026-04-27 21:02:26 +01:00
Peter Steinberger
5e49e8590d fix(cli): resolve message channel plugin scopes 2026-04-27 21:02:09 +01:00
Peter Steinberger
0c305596a2 fix(channels): skip route updates without session creation 2026-04-27 21:00:49 +01:00
haishmg
d32903c283 docs(providers): sort provider directory 2026-04-27 21:00:04 +01:00
Peter Steinberger
a2b84e98e9 fix: clean up trajectory sidecars 2026-04-27 20:58:28 +01:00
Peter Steinberger
9402bca614 fix: limit session list enrichment 2026-04-27 20:58:02 +01:00
Peter Steinberger
72f3c840c7 fix(cli): narrow message plugin registry loads 2026-04-27 20:55:56 +01:00
Peter Steinberger
161b722303 test(gateway): mock split config modules 2026-04-27 20:54:23 +01:00
Peter Steinberger
930b443c9e fix(ollama): preserve streaming usage compat 2026-04-27 20:54:22 +01:00
Vincent Koc
cff991c88d fix(ui): stabilize WebChat final reload reconciliation (#72325)
* fix(ui): stabilize WebChat final reload reconciliation

* fix(clownfish): address review for ghcrawl-165991-agentic-merge (1)

* fix(ui): keep plain control-token text visible
2026-04-27 12:52:39 -07:00
Peter Steinberger
f56897259e fix(cli): keep route-first json stdout clean 2026-04-27 20:51:50 +01:00
Peter Steinberger
f0000ab72d refactor(plugin-sdk): split infra runtime barrel 2026-04-27 20:50:35 +01:00
Peter Steinberger
d7c3a77b93 fix(telegram): skip polling webhook probe 2026-04-27 20:49:57 +01:00
Peter Steinberger
5a23032adb fix(plugins): detect install root rebinding 2026-04-27 20:47:54 +01:00
Peter Steinberger
f6b2ba4a10 fix(control-ui): coalesce duplicate chat submits 2026-04-27 20:45:28 +01:00
Peter Steinberger
8cddb6ce7d fix(webchat): drop stale optimistic assistant tails 2026-04-27 20:45:28 +01:00
Peter Steinberger
6dc8bd8935 fix(gateway): read active transcript history branch 2026-04-27 20:45:28 +01:00
Peter Steinberger
9645fe72c6 test: harden release validation live shards 2026-04-27 20:45:25 +01:00
Peter Steinberger
f90972d942 fix: install plugins through symlinked extension roots 2026-04-27 20:42:37 +01:00
Peter Steinberger
a6adc5f4f1 test(gateway): mock runtime config io imports 2026-04-27 20:40:54 +01:00
Peter Steinberger
f7d2b396d6 fix(test): restore gateway fixture startup config 2026-04-27 20:36:32 +01:00
Peter Steinberger
1fc19ffe11 refactor: narrow messaging public api barrels 2026-04-27 20:34:36 +01:00
Peter Steinberger
a20f97f728 refactor: narrow extension runtime api barrels 2026-04-27 20:34:35 +01:00
Peter Steinberger
31e529f000 ci: guard extension wildcard reexports 2026-04-27 20:34:35 +01:00
Peter Steinberger
f7d67b8ea8 fix(channels): ignore persisted auth for auto-enable 2026-04-27 20:33:43 +01:00
Peter Steinberger
dec1f68d7e fix(litellm): honor noninteractive custom base url 2026-04-27 20:33:04 +01:00
Vincent Koc
74eccd42d8 fix(ci): add android CodeQL security shard
Add a manual Android CodeQL security shard scoped to app production sources. Verified with profile=android-security on Blacksmith in 4m22s.
2026-04-27 12:32:55 -07:00
Peter Steinberger
4cd68fafbb fix(sessions): ignore future freshness timestamps 2026-04-27 20:30:59 +01:00
Peter Steinberger
54e13d4910 ci: split release validation slow shards 2026-04-27 20:30:17 +01:00
Peter Steinberger
2f488b7e7a docs: clarify ClawHub plugin discovery 2026-04-27 20:26:49 +01:00
Peter Steinberger
dc76963e36 fix(gateway): bind startup cron hook to live state 2026-04-27 20:25:46 +01:00
Peter Steinberger
7829c438a6 fix(tts): keep final webchat audio supplemental 2026-04-27 20:22:18 +01:00
Peter Steinberger
d2b0ff808a fix(gateway): ignore broken pipe crashes 2026-04-27 20:17:04 +01:00
Vincent Koc
3cb460873d fix(ui): stabilize agent model selection on switch (#72328)
* fix(ui): stabilize agent model selection on switch

* docs(changelog): credit projectclownfish fixes
2026-04-27 12:06:02 -07:00
Val Alexander
b393febbfa chore: remove coven changelog entries
Remove the two Unreleased Coven ACP/runtime changelog bullets that were reintroduced after the Coven extension removal.\n\nVerification:\n- rg -n -i "coven" CHANGELOG.md Swabble/CHANGELOG.md extensions/matrix/CHANGELOG.md apps/ios/CHANGELOG.md\n- git diff --check origin/main..HEAD\n- PR checks passed on head 767c274b0f
2026-04-27 14:05:23 -05:00
dependabot[bot]
48f433479d chore(deps): bump github/codeql-action
Bump github/codeql-action from b25d0ebf40e5b63ee81e1bd6e5d2a12b7c2aeb61 to 95e58e9a2cdfd71adc6e0353d5c52f41a045d225.
2026-04-27 12:01:27 -07:00
Vincent Koc
282af9c50a fix(ci): run CodeQL on small Blacksmith runners (#72988) 2026-04-27 11:56:48 -07:00
kakahu
d70808433d Add structured Matrix approval metadata (#72432)
Merged via squash.

Prepared head SHA: 0e06533dff
Co-authored-by: kakahu2015 <17962485+kakahu2015@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-04-27 14:52:02 -04:00
Vincent Koc
d0be08a9a4 fix(github): action manual Barnacle triage labels
Human-applied Barnacle triage candidate labels now trigger the intended auto-response while bot-applied heuristic candidates remain passive.
2026-04-27 11:44:47 -07:00
Vincent Koc
e864fd39cc fix(ci): narrow CodeQL critical scan (#72982) 2026-04-27 11:42:42 -07:00
Vincent Koc
1497425b8d fix(gateway): trim startup config imports 2026-04-27 11:34:24 -07:00
Vincent Koc
acbf57b448 revert(acp): remove Coven bridge
Revert the bundled Coven ACP bridge extension, its ClawHub publishing wiring, and related ACP/proxy runtime changes.
2026-04-27 11:26:05 -07:00
Val Alexander
f7797ca62b chore: remove coven extension 2026-04-27 13:22:32 -05:00
NVIDIAN
dc96886378 fix: clean up bundled LSP process trees on shutdown
Fixes #72357
2026-04-27 11:10:56 -07:00
Vincent Koc
d9bef3fe7c fix(ui): discard stale config state on explicit reload (#72624)
* fix(ui): discard stale config state on explicit reload

* fix(clownfish): address review for ghcrawl-156594-autonomous-smoke (1)

* fix(clownfish): address review for ghcrawl-156594-autonomous-smoke (1)

* test(ui): align channel config host state
2026-04-27 11:10:38 -07:00
Vincent Koc
be6263da4f fix(gateway): preserve runtime-backed health state (#72417)
* fix(gateway): preserve runtime-backed health state

* fix(clownfish): address review for ghcrawl-207035-agentic-merge (1)

* fix(gateway): harden health snapshot exposure
2026-04-27 11:04:59 -07:00
Vincent Koc
2161b46032 fix(feishu): support native interactive card payload sends (#72667)
* fix(feishu): support native interactive card payload sends

* fix(clownfish): address review for ghcrawl-156608-autonomous-smoke (1)

* fix(feishu): harden native card payload rendering
2026-04-27 11:02:15 -07:00
Gustavo Madeira Santana
c5678194d4 docs(qa): document Telegram and Discord QA lanes against code
Both lanes had only one paragraph each in qa-e2e-automation.md. Adds a
"Telegram and Discord QA reference" section verified against
extensions/qa-lab/src/live-transports/{telegram,discord}/* with:

- shared CLI flags table (--scenario, --output-dir, --repo-root, --sut-account,
  --provider-mode, --model, --alt-model, --fast, --credential-source,
  --credential-role) — none of these were enumerated for either lane.
- Telegram QA: 8 scenario ids
  (telegram-canary/-mention-gating/-mentioned-message-reply/-help-command/
  -commands-command/-tools-compact-command/-whoami-command/-context-command),
  output artifact paths (telegram-qa-report.md, -summary.json,
  -observed-messages.json), and the redaction toggle.
- Discord QA: 3 scenario ids
  (discord-canary/-mention-gating/-native-help-command-registration), output
  artifact paths, and the SUT-application-id-must-match-bot-user-id check.
- Convex credential pool: documents Discord support (only Telegram was
  mentioned before) and the per-kind payload shapes for the
  admin/add validator. Cross-links to testing.md for the broker endpoint
  contract.

Slims the duplicate Operator-flow paragraphs for Telegram and Discord into a
single one-block pointer that links to the new reference section.
2026-04-27 13:48:03 -04:00
Peter Steinberger
b39d80835f test: retry transient openai websocket live stream 2026-04-27 18:43:45 +01:00
openclaw-test-performance-agent[bot]
2f909b0b21 test: optimize slow tests 2026-04-27 17:42:22 +00:00
Gustavo Madeira Santana
dd1a94f089 docs(qa): reorg, audit against code, and refresh stale content
Reorg
- Rename the architecture page title to "QA overview" (slug stays
  /concepts/qa-e2e-automation so inbound links keep working).
- Move "Adding a channel to QA" + scenario-helper-name reference from
  testing.md into qa-e2e-automation.md under "Transport adapters". Architecture
  belongs with the architecture page.
- Drop the duplicate live-transport coverage table from testing.md; canonical
  copy stays in qa-e2e-automation.md under a new "Live transport coverage"
  heading so qa-matrix.md can deep-link to it.
- Slim testing.md QA-specific runners section to ops only, with cross-links.

Audit (against extensions/qa-lab/src/cli.ts, qa-channel/src/config-schema.ts,
and live-transport runtimes)
- qa-e2e-automation.md gains a "Command surface" table covering all 14
  openclaw qa <subcommand> forms; previously only ~7 of 14 were named.
- Document missing OPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT and
  OPENCLAW_QA_DISCORD_CAPTURE_CONTENT env vars (Matrix already had it).
- Cross-link qa coverage from the Reporting section.
- qa-channel.md completes the config-key list (enabled, name, accounts,
  defaultAccount were missing from the schema doc) and pollTimeoutMs range.
- Drop stale "Follow-up work" framing in qa-channel.md (provider/model matrix,
  scenario discovery, orchestration) — all three already shipped.
- Replace "vertical slice" language with current behavior; fix misplaced
  debugger-UI paragraph.

Discoverability
- Add a Note callout to testing.md pointing at the three QA pages
  (QA overview, Matrix QA, QA channel) so maintainers landing on testing.md
  see the QA stack in the prologue.

Glossary entries for the renamed/new doc titles.
2026-04-27 13:40:11 -04:00
Gustavo Madeira Santana
abca187df5 docs(qa): add dedicated Matrix QA reference page
Adds a focused reference for the Docker-backed Matrix QA lane (CLI flags,
seven scenario profiles, eight env vars including the redaction toggle and
Tuwunel image override, scenario taxonomy, output artifact layout, and triage
tips). Source-of-truth checked against extensions/qa-matrix/src/cli.ts,
shared/live-transport-cli.ts, runners/contract/{runtime,scenario-catalog}.ts,
and substrate/harness.runtime.ts.

Registered in docs/docs.json alongside QA E2E automation.
2026-04-27 13:40:11 -04:00
Val Alexander
ea92dc9202 chore(coven): enable ClawHub publishing
Mark the Coven ACP runtime bridge as a ClawHub-publishable code plugin and align its workspace lockfile metadata.
2026-04-27 12:35:34 -05:00
Peter Steinberger
8f8ba8af40 test: harden live release validation flakes 2026-04-27 18:32:31 +01:00
Vincent Koc
a2ec5a7d72 fix(plugins): break metadata snapshot cycle 2026-04-27 10:29:27 -07:00
Peter Steinberger
147752ecc3 refactor: split plugin metadata normalizer 2026-04-27 18:27:29 +01:00
Val Alexander
e3ad82d86d fix(control-ui): polish tweakcn theme imports
Summary:
- Improve Control UI tweakcn theme import parsing and labeling.
- Apply imported theme names consistently across appearance controls.
- Document tweakcn share link and slug import flows.

Verification:
- pnpm test ui/src/ui/custom-theme.test.ts ui/src/ui/views/config.browser.test.ts ui/src/ui/views/config-quick.test.ts ui/src/ui/app-settings.test.ts ui/src/ui/storage.node.test.ts
- pnpm check:changed
- pnpm --dir ui build
2026-04-27 12:24:14 -05:00
Val Alexander
fc8ccde542 feat(acp): add opt-in Coven runtime bridge
Add the opt-in Coven ACP runtime bridge as a bundled extension while keeping ACPX as the default path.

Security hardening included before merge:
- fail closed by default instead of silently falling back;
- bounded health/socket requests and daemon response sizes;
- fixed Coven socket trust anchor and symlink/path validation;
- reject untrusted harness/session/event ids before exposing them;
- sanitize daemon-controlled terminal/status/error strings;
- use incremental event polling with bounded dedupe state;
- clean up launched Coven sessions before fallback when daemon ids are invalid.

Validation:
- pnpm test extensions/coven/src/config.test.ts extensions/coven/src/client.test.ts extensions/coven/src/runtime.test.ts
- pnpm check:changed
- GitHub CI green on a64eac20b9
- Greptile Review green
2026-04-27 12:22:29 -05:00
Peter Steinberger
fd6e1c089b test: accept current codex status wording 2026-04-27 18:11:19 +01:00
Shakker
5531502cb0 fix: normalize provider metadata live filters 2026-04-27 18:04:54 +01:00
Shakker
4cd2cabe7f fix: include cli backend owners in provider metadata filters 2026-04-27 18:04:54 +01:00
Shakker
498af508d0 fix: avoid default workspace metadata for agent models 2026-04-27 18:04:54 +01:00
Shakker
51c7f544f3 fix: reject unscoped workspace plugin metadata 2026-04-27 18:04:54 +01:00
Shakker
4ceae8262f fix: scope model provider discovery metadata to workspace 2026-04-27 18:04:54 +01:00
Shakker
4e7de4b5c9 feat: reuse current plugin metadata for provider discovery 2026-04-27 18:04:54 +01:00
Shakker
a478ab3dfa refactor: let provider discovery reuse plugin metadata 2026-04-27 18:04:54 +01:00
Peter Steinberger
f20a295782 test: align release validation expectations 2026-04-27 17:46:31 +01:00
Vincent Koc
efc3a52947 fix(sessions_spawn): tolerate ACP-only fields for subagent runtime
Preserve contributor credit and land the narrowed sessions_spawn ACP-field handling with follow-up transcript redaction and ACP resume ownership hardening. Targeted Blacksmith validation passed for the touched sessions/ACP tests.
2026-04-27 09:42:24 -07:00
Peter Steinberger
aeba1d6b47 test: keep stateful tests out of unit-fast 2026-04-27 17:34:05 +01:00
Shakker
be0c1a9835 test: update model list suppression mocks 2026-04-27 17:13:11 +01:00
Shakker
c896d42cc4 fix: keep manifest suppression on static model lists 2026-04-27 17:13:11 +01:00
Shakker
13feb1b284 fix: narrow manifest alias overrides 2026-04-27 17:13:11 +01:00
Shakker
1056a9ea81 refactor: reuse manifest catalog provider refs 2026-04-27 17:13:11 +01:00
Shakker
e535b313cd docs: document manifest alias suppression behavior 2026-04-27 17:13:11 +01:00
Shakker
df07a89b52 test: cover manifest suppression precedence 2026-04-27 17:13:11 +01:00
Shakker
6e893eaee4 refactor: expose model catalog aliases in plugin lookup 2026-04-27 17:13:11 +01:00
Shakker
03c4c319e3 feat: declare openai catalog suppressions 2026-04-27 17:13:11 +01:00
Shakker
d014b36347 feat: resolve model suppressions from manifests 2026-04-27 17:13:11 +01:00
Shakker
b2685e72c1 refactor: plan manifest catalog aliases and suppressions 2026-04-27 17:13:11 +01:00
Peter Steinberger
6d269f62d6 perf(test): route more stable tests through unit-fast 2026-04-27 17:07:29 +01:00
Shakker
b72414c94e fix: include startup plan in lookup timing 2026-04-27 17:02:57 +01:00
Shakker
94591c3cb3 fix: fingerprint plugin metadata index reuse 2026-04-27 17:02:57 +01:00
Shakker
58b4407cda fix: reject stale plugin metadata inventory 2026-04-27 17:02:57 +01:00
Shakker
197c83138e fix: reuse startup metadata in plugin bootstrap 2026-04-27 17:02:57 +01:00
Shakker
5a72378b27 fix: keep plugin metadata out of config snapshots 2026-04-27 17:02:57 +01:00
Shakker
ab28cfa9d4 fix: guard plugin metadata snapshot reuse 2026-04-27 17:02:57 +01:00
Shakker
5240422f03 docs: describe plugin metadata snapshot 2026-04-27 17:02:57 +01:00
Shakker
d62cc59388 fix: reuse startup metadata for auto enable 2026-04-27 17:02:57 +01:00
Shakker
9de2bc6ffc refactor: reuse startup plugin metadata snapshot 2026-04-27 17:02:57 +01:00
Shakker
ca4f964547 refactor: let config validation use plugin metadata snapshot 2026-04-27 17:02:57 +01:00
Shakker
440fc73448 refactor: extract plugin metadata snapshot 2026-04-27 17:02:57 +01:00
Peter Steinberger
04b5dd097d test: skip bootstrap in release validation onboarding 2026-04-27 17:01:52 +01:00
Peter Steinberger
1fd0802b88 perf(test): route more unit tests through fast lane 2026-04-27 17:01:16 +01:00
Omar Shahine
8ce4f8fc84 fix(gateway): redact SecretRef apiKey through talk.config without throwing
The talk.config discovery RPC was handing the source-snapshot's
talkProviderConfig (with the unresolved SecretRef wrapper still on
apiKey) to speechProvider.resolveTalkConfig. ElevenLabs/OpenAI's
strict normalizeResolvedSecretInputString helper threw 'unresolved
SecretRef' there, so iOS / macOS / Control UI Talk overlays never
learned the configured provider and silently fell back to local
AVSpeechSynthesizer ('robot voice') even though talk.realtime.session
and talk.speak both worked end-to-end with the same SecretRef.

Prefer the runtime-resolved provider config when calling
resolveTalkConfig, strip the apiKey field if it's still a SecretRef
wrapper at the call site, and restore the source-shaped apiKey onto
the response so the UI keeps the SecretRef context. Redaction strips
the value when includeSecrets=false.

Adds a regression test using a strict resolver speech provider that
mirrors ElevenLabs/OpenAI behavior so the path stays covered for
SecretRef apiKeys.

Fixes #72496

Thanks @omarshahine
2026-04-27 08:59:12 -07:00
Peter Steinberger
ee140ae570 perf(test): route memory package tests through unit-fast 2026-04-27 16:43:55 +01:00
Val Alexander
1cf68b9243 fix(control-ui): keep google talk off webrtc
Keep Google Live Talk browser sessions on the supported WebSocket/gateway-relay paths instead of falling back to browser WebRTC, remove stale browser-native voice controls that bypass Talk/TTS provider settings, and harden the Google Live URL plus realtime relay resource controls.

Verification:
- pnpm test ui/src/ui/realtime-talk.test.ts ui/src/ui/realtime-talk-google-live.test.ts src/gateway/talk-realtime-relay.test.ts src/gateway/server-methods/talk.test.ts
- pnpm check:changed
2026-04-27 10:35:34 -05:00
Peter Steinberger
1560e26f3d fix(ci): align yuanbao channel catalog contract 2026-04-27 16:32:21 +01:00
Peter Steinberger
56fa69a48a fix(ci): pin yuanbao official channel catalog source 2026-04-27 16:28:56 +01:00
Peter Steinberger
32bbb5b18f test: harden release validation smokes 2026-04-27 16:28:44 +01:00
cxy
5ccf179a34 feat(qqbot): group chat support, C2C streaming, chunked media upload, and architecture refactor (#70624)
* feat(qqbot): implement unified media upload handling and introduce chunked upload support

This commit enhances the media upload functionality by introducing a unified `sendMedia` method that consolidates the previous separate methods for sending images, voice messages, videos, and files. Key changes include:

- Added `uploadChunked` function for future chunked media uploads, currently marked as not implemented.
- Introduced `MediaSource` abstraction to handle various media types (URLs, base64, local files, buffers) uniformly.
- Updated existing media handling logic to utilize the new `sendMedia` method, ensuring consistent media processing across different types.
- Enhanced error handling and validation for media uploads, including MIME type checks and file size limits.

These changes aim to streamline the media upload process and prepare for future enhancements in handling larger files through chunked uploads.

* feat(qqbot): enhance media upload capabilities with chunked upload support

This commit updates the media upload functionality by implementing chunked upload support for larger files. Key changes include:

- Revised the `SKILL.md` documentation to clarify media file size limits and local file path requirements.
- Introduced a new test suite for the chunked media upload functionality, ensuring robust error handling and upload processes.
- Updated the media handling logic to enforce per-file-type upload ceilings, allowing for seamless integration of chunked uploads.
- Enhanced error handling for daily upload limits, providing user-friendly messages when limits are exceeded.

These improvements aim to streamline the media upload process and accommodate larger files effectively.

* feat(qqbot): add C2C streaming API support for message delivery

This commit introduces support for the QQ C2C official `stream_messages` API, enabling single-message typing-style updates. Key changes include:

- Updated the configuration schema to include a new `c2cStreamApi` boolean option for enabling the C2C streaming API.
- Enhanced the `QQBotAccountConfig` interface to accommodate the new streaming option.
- Implemented a `StreamingController` to manage the lifecycle of C2C stream messages, ensuring proper handling of media tags and message boundaries.
- Updated the outbound dispatch logic to utilize the new streaming capabilities, allowing for more dynamic message delivery in one-to-one chats.

These enhancements aim to improve the responsiveness and interactivity of message delivery within the QQBot framework.

* feat(qqbot): implement group chat support and unify adapter/DI architecture

- Implement group message history tracking with pending history buffer
  (record on skip, render on @-mention reply)
- Add mention detection and gating: explicit @bot, implicit quote-reply,
  ignoreOtherMentions, configurable activation mode (mention/always)
- Add group activation resolution with session store persistence
- Add message queue with per-peer FIFO and group message merging
  (batch multiple rapid messages into one merged payload)
- Add deliver debounce to merge rapid outbound text bursts into
  single messages, with media flush and maxWait cap
- Add group config resolution: per-group prompt, history limit,
  wildcard and specific group overrides
- Enrich history attachments with local paths from processAttachments
  so that history context renders downloaded paths instead of ephemeral
  QQ CDN URLs

- Merge ports/ directory into adapter/ as single entry point
- Expand EngineAdapters to 5 required ports: history, mentionGate,
  audioConvert, outboundAudio, commands
- Remove global register/get singletons in favor of constructor
  injection and one-time init
- Add createEngineAdapters() in bridge/gateway.ts as single assembly point

- Extract monolithic buildInboundContext into 11 discrete stages:
  access, content, quote, refidx, group-gate, envelope, assembly
- Extract group chat modules: history, mention, activation,
  message-gating, deliver-debounce
- Extract config/group.ts, utils/attachment-tags.ts

* feat(qqbot): add /bot-streaming command for C2C message streaming control

This commit introduces the `/bot-streaming` command, allowing users to enable or disable streaming for message delivery in C2C chats. Key changes include:

- Implementation of the `isStreamingConfigEnabled` function to check the current streaming configuration.
- Command handler for `/bot-streaming` that provides usage instructions and manages the streaming state.
- Updates to the command's response messages to inform users of the current streaming status and how to toggle it.

These enhancements aim to improve user experience by providing a straightforward way to manage streaming message delivery in private chats.

* feat(qqbot): extract interaction handler and add remote config query/update support

- Extract INTERACTION_CREATE handler from gateway.ts into a dedicated
  interaction-handler.ts module for better separation of concerns
- Add config query (type=2001) and config update (type=2002) interaction
  branches that read/write claw_cfg via runtime.config API
- Register INTERACTION intent (1<<26) in FULL_INTENTS to receive
  INTERACTION_CREATE events from the gateway
- Add InteractionType constants (CONFIG_QUERY, CONFIG_UPDATE)
- Extend GatewayPluginRuntime with optional config API (loadConfig,
  writeConfigFile) for interaction handler access
- Add QQBotAccountConfigView interface for typed config field access
- Extend acknowledgeInteraction to accept optional data payload for
  rich ACK responses (e.g. claw_cfg snapshot)
- Export getFrameworkVersion from slash-commands-impl for version
  reporting in config snapshots
- Remove unused eslint-disable directive in streaming-media-send.ts

* feat(qqbot): enhance account management and logging capabilities

- Introduced `toGatewayAccount` function to map resolved QQBot accounts to the engine's gateway account structure.
- Added `persistAccountCredentialSnapshot` function to streamline credential backup during gateway events.
- Updated the `qqbotPlugin` to utilize the new account mapping and credential persistence functions, improving the handling of account data.
- Enhanced logging functionality by modifying the `EngineLogger` interface to support metadata in log messages.
- Implemented new commands for managing logs and clearing storage, providing users with better control over their data and system resources.
- Registered multiple built-in commands for improved user interaction, including `/bot-logs` for exporting logs and `/bot-clear-storage` for managing downloaded files.
- Updated configuration schemas to reflect new options and improve clarity for users.

* fix(qqbot): resolve oxlint errors and update raw-fetch allowlist

- Replace unnecessary `else` after `return` in outbound-media-send.ts (6 occurrences)
- Use `Number.parseInt` instead of global `parseInt` in outbound.ts and streaming-media-send.ts
- Use `Number.isNaN` instead of global `isNaN` in register-basic.ts
- Prefer `**` over `Math.pow` in media-chunked.ts
- Convert interface with call signature to function type in commands.port.ts
- Update api-client.ts allowlist line number (108→124) and add media-chunked.ts:552 to raw-fetch allowlist

* docs(qqbot): translate streaming-c2c.ts header comments to English

* feat(qqbot): add voiceMediaTypes

* feat: restore dispatch changes

* fix(qqbot): align test files with updated engine interfaces after rebase

- inbound-attachments.test: replace removed registerAudioConvertAdapter
  with AudioConvertPort, pass audioConvert in ProcessContext
- inbound-pipeline.self-echo.test: add required adapters field to
  InboundPipelineDeps mock (history, mentionGate, audioConvert,
  outboundAudio, commands)
- outbound-dispatch.test: add required skipped field to InboundContext

* fix(qqbot): update test assertions to match refactored engine interfaces

- inbound-pipeline.self-echo.test: self-echo blocking was moved upstream;
  update test to expect non-blocked pipeline behavior
- outbound-dispatch.test: TTS voice path now uses unified sendMedia
  instead of sendVoiceMessage; add sendMedia mock and update assertion
- format-ref-entry.test: attachment format changed from [image: ...]
  to MEDIA: tag syntax via renderAttachmentTags; update expected output

* refactor(qqbot): migrate from deprecated config API to current/replaceConfigFile

Replace all usages of deprecated runtime config methods:
- loadConfig() → current()
- writeConfigFile(cfg) → replaceConfigFile({ nextConfig, afterWrite })

Updated files:
- bridge/narrowing.ts: writeOpenClawConfigThroughRuntime
- adapter/commands.port.ts: ApproveRuntimeGetter type signature
- commands/builtin/register-approve.ts: loadExecConfig, writeExecConfig, reset
- commands/builtin/register-streaming.ts: config read/write
- gateway/interaction-handler.ts: config query/update handlers
- gateway/types.ts: GatewayPluginRuntime.config interface

* feat(qqbot): update package.json

* fix(qqbot): replace deprecated config-runtime import with config-types subpath

Bundled plugin lint requires focused plugin-sdk subpaths.
- gateway.ts: openclaw/plugin-sdk/config-runtime → config-types
- narrowing.ts: openclaw/plugin-sdk/config-runtime → config-types

* feat(qqbot): group chat support, C2C streaming, chunked media upload, and architecture refactor (#70624) (thanks @cxyhhhhh)

---------

Co-authored-by: Bobby <zkd8907@live.com>
Co-authored-by: sliverp <870080352@qq.com>
2026-04-27 23:19:12 +08:00
Peter Steinberger
8304635258 perf(test): route speech provider registry through unit-fast 2026-04-27 16:16:12 +01:00
loongfay
3120401f53 feat(channel) yuanbao (#72756)
* feat(channel) yuanbao

* feat(channel) yuanbao

* docs(changelog): note Yuanbao channel plugin (#72756) (thanks @loongfay)

---------

Co-authored-by: loongzhao <loongzhao@tencent.com>
Co-authored-by: sliverp <870080352@qq.com>
2026-04-27 23:04:33 +08:00
Peter Steinberger
c41126dbbb ci: capture dispatched full validation runs 2026-04-27 15:51:03 +01:00
Peter Steinberger
708b42c4dc docs(changelog): link proxy fix to issue 2026-04-27 15:44:37 +01:00
Peter Steinberger
dc859584a3 fix(gateway): honor all_proxy in env dispatcher 2026-04-27 15:36:12 +01:00
Shakker
fd6c9fc7f5 fix: reuse plugin registry during config validation 2026-04-27 15:35:39 +01:00
Peter Steinberger
42fc176093 test: isolate speech provider registry mocks 2026-04-27 15:30:21 +01:00
Shakker
246fd9d3c0 fix: preserve manifest fallback for derived provider indexes 2026-04-27 15:29:11 +01:00
Shakker
7f316b917b docs: add model source plan changelog 2026-04-27 15:29:11 +01:00
Shakker
4fe7303a1f test: cover model list source planning 2026-04-27 15:29:11 +01:00
Shakker
25dda844b7 refactor: use source plan for models list 2026-04-27 15:29:11 +01:00
Shakker
f5417f626c refactor: add model list source plan 2026-04-27 15:29:11 +01:00
Peter Steinberger
d22ced122d test: isolate speech provider registry test 2026-04-27 15:28:37 +01:00
Shakker
ca444af891 fix: restore npm shims on swap failure 2026-04-27 15:27:43 +01:00
Shakker
2186080963 fix: stage npm updates under global root 2026-04-27 15:27:43 +01:00
Shakker
b0127b9f1f fix: harden npm update staging 2026-04-27 15:27:43 +01:00
Shakker
6985c6751c fix: make npm global updates atomic 2026-04-27 15:27:43 +01:00
Peter Steinberger
9b4c1f0fa3 test: update compaction token test contexts 2026-04-27 15:18:28 +01:00
Peter Steinberger
467ee701ef fix(ci): align tests with runtime barrels 2026-04-27 15:15:07 +01:00
Peter Steinberger
9090457da7 test(plugin-sdk): use narrow config runtime mocks 2026-04-27 15:14:02 +01:00
Peter Steinberger
a2af8054e1 test: harden live release checks 2026-04-27 15:11:46 +01:00
Peter Steinberger
016a0b4de9 fix(gateway): avoid echoing rotated device tokens 2026-04-27 15:10:05 +01:00
Peter Steinberger
dacf43640a fix(ci): repair main test gates 2026-04-27 15:03:39 +01:00
Peter Steinberger
a9648664c1 perf(test): route memory dreaming through unit-fast 2026-04-27 15:03:21 +01:00
Peter Steinberger
22e2e45c57 fix(cli): skip respawn for foreground gateway 2026-04-27 15:01:33 +01:00
Peter Steinberger
d69eeeb2a8 fix: skip test-only plugin install scan findings 2026-04-27 15:00:55 +01:00
Peter Steinberger
82b4049744 refactor: narrow discord slack runtime api barrels 2026-04-27 15:00:03 +01:00
Peter Steinberger
75a96bafcf docs: fix changelog attribution credits 2026-04-27 15:00:03 +01:00
Peter Steinberger
4336a7f3a9 refactor(plugin-sdk): narrow config runtime imports 2026-04-27 14:58:32 +01:00
Peter Steinberger
f3e8a8a319 fix(agents): persist compaction token snapshots 2026-04-27 14:58:15 +01:00
Peter Steinberger
f9946eb069 fix(memory): parse qmd vector status variants 2026-04-27 14:57:28 +01:00
Peter Steinberger
1f7b7c249a fix(google-meet): grant browser media permissions 2026-04-27 14:54:07 +01:00
Peter Steinberger
713cc74bff fix: quiet installed plugin override warnings 2026-04-27 14:53:36 +01:00
Peter Steinberger
2e99c1d227 fix(subagents): enforce explicit spawn allowlists 2026-04-27 14:53:17 +01:00
Peter Steinberger
58a4ca4423 refactor: narrow whatsapp runtime api barrel 2026-04-27 14:52:21 +01:00
Peter Steinberger
1ed6d04014 ci: guard plugin sdk wildcard reexports 2026-04-27 14:52:21 +01:00
Peter Steinberger
877b5a14f1 fix(sessions): batch store cap maintenance 2026-04-27 14:51:53 +01:00
Peter Steinberger
0ac0357486 docs(memory): explain qmd collection compatibility 2026-04-27 14:44:01 +01:00
Peter Steinberger
63011fcbb0 ci: update generated protocol swift models 2026-04-27 14:42:27 +01:00
Peter Steinberger
e035300d8e fix(acp): allow manual spawn with dispatch paused 2026-04-27 14:40:12 +01:00
Peter Steinberger
c3b3da41fe fix: allow trusted openclaw peer symlinks 2026-04-27 14:40:02 +01:00
Peter Steinberger
cbf6ed2b35 chore: publish OpenClaw 2026.4.25 appcast 2026-04-27 14:39:56 +01:00
Peter Steinberger
4c544e649c test: move more stateful tests to unit-fast 2026-04-27 14:37:51 +01:00
Peter Steinberger
4ebec8b5dc fix(memory): group qmd collection searches 2026-04-27 14:37:12 +01:00
Peter Steinberger
eb1a201060 refactor: narrow media core plugin api barrels 2026-04-27 14:34:00 +01:00
Peter Steinberger
0f996ad4b0 ci: enforce changelog attribution policy in pr gates 2026-04-27 14:33:59 +01:00
Peter Steinberger
ad0f600450 fix(gateway): avoid systemd service split-brain 2026-04-27 14:32:49 +01:00
Peter Steinberger
c00ef238be docs(tools): clarify sessions_spawn profile gating 2026-04-27 14:31:54 +01:00
Peter Steinberger
23d047dff5 ci: update generated protocol models 2026-04-27 14:31:13 +01:00
Peter Steinberger
1382fb5bd7 fix(agents): fail closed missing requester completion routes 2026-04-27 14:30:59 +01:00
Peter Steinberger
6956e8406d fix: honor profile plugin install roots 2026-04-27 14:30:12 +01:00
Shakker
f88c330657 fix: preserve runtime config during source plugin activation 2026-04-27 14:29:49 +01:00
Shakker
a964dcbddb fix: honor source plugin activation at startup 2026-04-27 14:29:49 +01:00
Shakker
a88f2ba939 fix: avoid startup auto-enable runtime defaults 2026-04-27 14:29:48 +01:00
Peter Steinberger
6ced6bc4a3 ci: satisfy live shard lint 2026-04-27 14:29:41 +01:00
Peter Steinberger
bbbc80ddcc ci: guard changelog bot attributions 2026-04-27 14:29:41 +01:00
Peter Steinberger
6e8aaef1cc fix(google-meet): avoid duplicate test speech 2026-04-27 14:29:08 +01:00
Peter Steinberger
73ba282b54 docs(memory): clarify qmd mask compatibility 2026-04-27 14:26:56 +01:00
Peter Steinberger
8e09105bd3 test: route more mock-only tests through unit-fast 2026-04-27 14:24:43 +01:00
Peter Steinberger
2243a68a1d ci: shard release live validation 2026-04-27 14:24:10 +01:00
Peter Steinberger
f6bda8d36b refactor(providers): share Claude thinking profiles 2026-04-27 14:23:12 +01:00
Peter Steinberger
93bbbe5e37 feat: add browser realtime talk transports 2026-04-27 14:22:32 +01:00
Peter Steinberger
5dd1e264eb refactor(config): tighten plugin config guardrails 2026-04-27 14:20:27 +01:00
Peter Steinberger
ef9d108436 fix(gateway): include client in hello snapshot 2026-04-27 14:20:27 +01:00
Peter Steinberger
c3c8f25bab fix(memory): report qmd dirty watcher state 2026-04-27 14:20:10 +01:00
Peter Steinberger
28f264034b fix: discover symlinked plugin directories 2026-04-27 14:17:32 +01:00
sfuminya
2c57d70a10 fix: preserve requester route for subagent completion delivery (#72806)
* fix: preserve requester route for subagent completion delivery

* fix(agents): preserve requester subagent completion routes

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-27 14:17:14 +01:00
Peter Steinberger
dfd9dbe4e1 docs: clarify changelog attribution exclusions 2026-04-27 14:16:43 +01:00
Peter Steinberger
4300a6165e test: route more setup-free tests through unit-fast 2026-04-27 14:16:20 +01:00
Peter Steinberger
67a447c175 refactor: tighten plugin runtime sdk boundaries 2026-04-27 14:15:53 +01:00
Peter Steinberger
b181930c23 fix(memory): skip qmd vectors in lexical mode 2026-04-27 14:09:42 +01:00
Peter Steinberger
6a0dc3a9bc fix: cache plugin discovery realpaths 2026-04-27 14:09:15 +01:00
Peter Steinberger
9ca4049861 ci: match package Telegram harness to release ref 2026-04-27 14:06:05 +01:00
Peter Steinberger
52a1cbc1c6 fix(qa-lab): keep gateway client on generic sdk seam 2026-04-27 14:05:09 +01:00
Peter Steinberger
57401f1581 fix(google-meet): use OpenClaw browser for local joins 2026-04-27 14:03:46 +01:00
Peter Steinberger
8de458c6c0 fix(qa-lab): use generic gateway runtime SDK 2026-04-27 14:03:28 +01:00
harish ganeshmurthy
f75d8827f2 fix(opencode): expose Claude thinking levels (#72778)
* fix(opencode): expose claude thinking levels

* test(opencode): cover adaptive claude thinking bounds

* docs(changelog): credit opencode thinking contributor

---------

Co-authored-by: haishmg <4529977+haishmg@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-27 14:03:26 +01:00
Peter Steinberger
1b1916053f ci: inline Docker release planning for old refs 2026-04-27 14:03:17 +01:00
Peter Steinberger
fd4b59a906 ci: keep release checks compatible with stable refs 2026-04-27 13:59:49 +01:00
Peter Steinberger
d0e4472616 test(vitest): keep speech registry out of unit-fast 2026-04-27 13:57:15 +01:00
Peter Steinberger
f15c9f1d5f test: move more setup-free tests to unit-fast 2026-04-27 13:56:21 +01:00
Peter Steinberger
df65a75f92 fix(memory): avoid live embedding probes in status 2026-04-27 13:55:51 +01:00
Peter Steinberger
dc495e6d62 refactor(discord): isolate model picker apply flow 2026-04-27 13:50:43 +01:00
Peter Steinberger
951a0d89d8 fix(discord): persist stale model picker overrides 2026-04-27 13:50:43 +01:00
Peter Steinberger
1fbe83d09f fix: keep link understanding from dropping replies 2026-04-27 13:45:05 +01:00
Peter Steinberger
fa1f670716 test: route setup-free tests through unit-fast 2026-04-27 13:42:32 +01:00
Peter Steinberger
770978b8d3 build(config): refresh generated schema baseline 2026-04-27 13:42:12 +01:00
Peter Steinberger
8e37ee4bf2 fix(voice-call): avoid blocking gateway startup 2026-04-27 13:40:30 +01:00
Peter Steinberger
2d90dbe512 docs: add release feature redirect URLs 2026-04-27 13:40:00 +01:00
Peter Steinberger
f3528e7755 fix(openrouter): retire stealth model catalog entries 2026-04-27 13:36:49 +01:00
Peter Steinberger
9cde9261c6 docs(changelog): move post-release entries to 2026.4.26 2026-04-27 13:34:02 +01:00
Peter Steinberger
cae492374c test: reduce repeated test setup overhead 2026-04-27 13:33:05 +01:00
Peter Steinberger
0931a1f11e ci: fix release validation dispatch and protocol drift 2026-04-27 13:32:03 +01:00
Peter Steinberger
d9b8001502 build(protocol): refresh swift gateway models 2026-04-27 13:31:15 +01:00
Peter Steinberger
252c63429e fix(providers): map native reasoning efforts 2026-04-27 13:27:58 +01:00
Peter Steinberger
4119d65e82 test(doctor): keep repair sequencing unit isolated 2026-04-27 13:27:36 +01:00
Peter Steinberger
3c6d178f4e docs: clarify malformed plugin tool guards 2026-04-27 13:27:19 +01:00
Peter Steinberger
41d5c27894 fix(docker): install runtime ca certificates 2026-04-27 13:24:42 +01:00
Peter Steinberger
98b441edb1 ci: split release docker integration chunks 2026-04-27 13:24:30 +01:00
Peter Steinberger
750c180a6c fix(ollama): warn on WSL2 CUDA crash loop risk 2026-04-27 13:24:04 +01:00
Peter Steinberger
0a076bc0fc fix: isolate malformed plugin tools 2026-04-27 13:22:28 +01:00
Peter Steinberger
7fb2a356e8 fix(nodes): allow removing stale paired nodes 2026-04-27 13:20:52 +01:00
Peter Steinberger
400be3b63f test(agents): align failure-kind protocol expectations 2026-04-27 13:18:16 +01:00
Peter Steinberger
4bd356d03a fix(channels): clarify message target syntax 2026-04-27 13:18:04 +01:00
Peter Steinberger
6fe9285f64 fix(ci): sync locale and cron contract tests 2026-04-27 13:15:59 +01:00
Peter Steinberger
cff1bdb491 ci: trim duplicate release package lanes 2026-04-27 13:15:10 +01:00
Peter Steinberger
4260bb0418 fix: quarantine invalid plugin configs 2026-04-27 13:14:59 +01:00
Alex Knight
b1e530b204 fix(cli): mark embedded agent fallback (#72730)
* fix(cli): mark embedded agent fallback

* refactor(cli): structure embedded fallback metadata

* refactor(cli): move fallback metadata types out of EmbeddedPiRunMeta

---------

Co-authored-by: Alex Knight <15041791+amknight@users.noreply.github.com>
2026-04-27 22:14:11 +10:00
github-actions[bot]
bef28fcf1a chore(ui): refresh th control ui locale 2026-04-27 12:13:31 +00:00
Peter Steinberger
7e45272319 test(ci): align docker scenario guard with sharded sweep 2026-04-27 13:13:04 +01:00
github-actions[bot]
ef87620c5b chore(ui): refresh id control ui locale 2026-04-27 12:12:56 +00:00
github-actions[bot]
973fbcd65b chore(ui): refresh pl control ui locale 2026-04-27 12:12:51 +00:00
github-actions[bot]
a3ef1938b6 chore(ui): refresh uk control ui locale 2026-04-27 12:12:39 +00:00
github-actions[bot]
6c0d9b1642 chore(ui): refresh tr control ui locale 2026-04-27 12:12:32 +00:00
github-actions[bot]
e7d3cfa7ca chore(ui): refresh fr control ui locale 2026-04-27 12:11:55 +00:00
github-actions[bot]
3769a93752 chore(ui): refresh ko control ui locale 2026-04-27 12:11:51 +00:00
github-actions[bot]
1633e38a77 chore(ui): refresh ja-JP control ui locale 2026-04-27 12:11:46 +00:00
github-actions[bot]
1a466d5a44 chore(ui): refresh es control ui locale 2026-04-27 12:11:42 +00:00
github-actions[bot]
1ad36486b8 chore(ui): refresh zh-CN control ui locale 2026-04-27 12:11:01 +00:00
github-actions[bot]
3352f8a569 chore(ui): refresh zh-TW control ui locale 2026-04-27 12:10:55 +00:00
github-actions[bot]
61633b5ca7 chore(ui): refresh pt-BR control ui locale 2026-04-27 12:10:52 +00:00
github-actions[bot]
450eae0ecf chore(ui): refresh de control ui locale 2026-04-27 12:10:48 +00:00
Peter Steinberger
0e586bb48a fix(agents): improve fallback failure observability 2026-04-27 13:10:12 +01:00
Peter Steinberger
63eaf8ea51 fix(models): default local custom providers to completions 2026-04-27 13:09:59 +01:00
Peter Steinberger
b6c8e51dcb fix(gateway): build hello snapshot after presence update 2026-04-27 13:09:30 +01:00
Peter Steinberger
3517b25482 fix: remove duplicate hello snapshot build 2026-04-27 13:09:16 +01:00
Peter Steinberger
c6ebd99a46 fix(control-ui): surface lazy panel load failures 2026-04-27 13:09:02 +01:00
Peter Steinberger
0141471dd5 refactor: move shared helpers off reserved sdk seams 2026-04-27 13:07:54 +01:00
Peter Steinberger
e91f9a3f67 fix: include connected client in hello snapshot 2026-04-27 13:07:45 +01:00
Peter Steinberger
fef4b57b39 fix(gateway): include connected client in hello snapshot 2026-04-27 13:06:30 +01:00
Peter Steinberger
f68ef1ae7c ci: shard bundled plugin release sweep 2026-04-27 13:05:14 +01:00
Peter Steinberger
0dfea099d6 test: speed up focused test setup 2026-04-27 13:00:43 +01:00
Peter Steinberger
e9986aa787 fix(ci): make full validation rerun-aware 2026-04-27 13:00:09 +01:00
Peter Steinberger
6a55a00da4 fix(agents): scope loop detection to runs 2026-04-27 12:59:54 +01:00
Peter Steinberger
d73e2ee774 fix(google-meet): use PCM audio for Chrome realtime 2026-04-27 12:55:00 +01:00
Val Alexander
27a4bba90a fix(ui): render cron markdown summaries
## Summary
- render cron job prompts and run summaries through the sanitized markdown pipeline in the Control UI
- keep system-event cron payloads plain and prevent markdown link clicks from triggering row selection
- handle failed runs with missing or empty summaries without duplicating or hiding the error text

## Verification
- pnpm test ui/src/ui/views/cron.test.ts
- pnpm test src/plugins/doctor-contract-registry.test.ts src/plugins/setup-registry.test.ts
- pnpm check:changed
- GitHub CI green on 251f01a3b0
2026-04-27 06:53:51 -05:00
Peter Steinberger
769d04b4ce docs(models): clarify local chat completions routing 2026-04-27 12:53:46 +01:00
Peter Steinberger
10257114ac test: speed up focused unit tests 2026-04-27 12:52:54 +01:00
Peter Steinberger
a041ea7ca7 docs(plugins): clarify runtime config access 2026-04-27 12:52:20 +01:00
Peter Steinberger
9d5a211019 refactor(plugins): enforce config API deprecations 2026-04-27 12:52:20 +01:00
Peter Steinberger
94a9d3f0be refactor(config): track runtime config revisions 2026-04-27 12:52:20 +01:00
Peter Steinberger
047c03cc88 fix(gateway): drop stale webchat handshakes 2026-04-27 12:51:17 +01:00
Peter Steinberger
eaae63d288 refactor: keep plugin sdk owner seams explicit 2026-04-27 12:50:31 +01:00
Peter Steinberger
189535308f test: align plugin jiti Windows expectations 2026-04-27 12:49:00 +01:00
Peter Steinberger
22a51de422 fix: tolerate stale channel plugin config 2026-04-27 12:48:13 +01:00
Peter Steinberger
c0ea89cfd2 fix(agents): recover unclosed reasoning-only replies 2026-04-27 12:45:11 +01:00
Peter Steinberger
74fb6be716 fix(ui): scope agent identity to active session
Co-authored-by: Sahil Satralkar <62758655+sahilsatralkar@users.noreply.github.com>
2026-04-27 12:45:00 +01:00
Peter Steinberger
d25dd7c2bd test: cache dockerfile fixture reads 2026-04-27 12:42:29 +01:00
Vincent Koc
9be54044eb docs(doctor): document stale channel plugin cleanup (edb3e84898)
Trace to edb3e84898 (fix: clean stale plugin channel config). When
openclaw doctor --fix removes a missing channel plugin, it also cascades
the cleanup to dangling channel config, heartbeat targets, and channel
model overrides, preventing gateway boot loops after failed plugin
reinstalls. Added an Accordion 11d to docs/gateway/doctor.md listing the
exact config keys that get pruned alongside the plugin entry.
2026-04-27 04:40:49 -07:00
Peter Steinberger
9b2f10dcf8 fix(agents): preserve distinct empty exec failures 2026-04-27 12:40:41 +01:00
martingarramon
4f50921e0f fix(gateway/schema): require hello-ok auth
Fixes #68160.

Drops stale optionality from the hello-ok auth schema and keeps generated Swift models, macOS fixtures, browser client types, protocol docs, and merged-base test boundaries aligned.
2026-04-27 06:40:36 -05:00
Peter Steinberger
00d4099526 fix(discord): inherit thread model overrides without transcript fork 2026-04-27 12:40:32 +01:00
Peter Steinberger
b056d594b4 fix(plugins): normalize Windows Jiti paths 2026-04-27 12:39:21 +01:00
Vincent Koc
c85065eb7f fix(cli): tighten Windows restart policy-close health checks
Preserve contributor credit and land the narrowed restart-health fix after ProjectClownfish review/follow-up.
2026-04-27 04:38:29 -07:00
Peter Steinberger
3da6d6ee18 fix(qwen): use plugin test boundary helpers 2026-04-27 12:36:50 +01:00
Peter Steinberger
c59af3caf7 docs(plugins): document runtime config APIs 2026-04-27 12:35:59 +01:00
Peter Steinberger
7f3f108521 refactor(config): migrate plugin config access 2026-04-27 12:35:58 +01:00
Peter Steinberger
48ebed3ed3 fix(plugins): normalize bundled sidecar jiti imports 2026-04-27 12:35:51 +01:00
Peter Steinberger
da8576c0bf test: guard plugin boundary classifications 2026-04-27 12:35:43 +01:00
Peter Steinberger
7ec97c010c test: speed up plugin activation boundary test 2026-04-27 12:35:31 +01:00
Vincent Koc
727927aae0 fix(docker): repair named-volume state directory ownership
Preserve contributor credit and land the narrowed Docker ownership fix after ProjectClownfish review/follow-up.
2026-04-27 04:34:35 -07:00
Peter Steinberger
e9bce3f81c fix(agents): stabilize exec loop outcome hashing 2026-04-27 12:33:37 +01:00
Peter Steinberger
35335214b3 fix(compaction): avoid preserving duplicate user turns 2026-04-27 12:30:59 +01:00
Peter Steinberger
dae09d26b9 test(live): tolerate provider-specific live probe variance 2026-04-27 12:30:12 +01:00
Peter Steinberger
053aff6d35 fix(mcp): normalize streamable http server aliases 2026-04-27 12:29:24 +01:00
Peter Steinberger
3da4b28d1b fix(agents): avoid overload classification for live model switches 2026-04-27 12:28:33 +01:00
Peter Steinberger
82e164c018 test: speed up acp rate-limit coverage 2026-04-27 12:28:09 +01:00
Peter Steinberger
db087a4be7 fix(doctor): stream bundled runtime dep repair progress 2026-04-27 12:27:44 +01:00
Shakker
05fce28ec0 docs: document installed manifest fallback cache 2026-04-27 12:26:10 +01:00
Peter Steinberger
7363fb4a44 refactor: move telegram poll visibility out of core 2026-04-27 12:25:57 +01:00
Peter Steinberger
3bc29dd604 fix(sqlite): bound WAL sidecar growth 2026-04-27 12:25:10 +01:00
Peter Steinberger
bbfdb38e4e fix: show doctor runtime dependency install progress 2026-04-27 12:25:05 +01:00
Peter Steinberger
5afa24a9fc fix(qwen): preserve custom modelstudio providers 2026-04-27 12:24:25 +01:00
Peter Steinberger
dca9fa471f fix(ui): preserve session assistant identity 2026-04-27 12:20:36 +01:00
Shakker
6f6e2765e2 test: reset installed manifest cache in web search provider tests 2026-04-27 12:19:51 +01:00
Shakker
ac7aef6c5b docs: frame installed manifest cache as fallback 2026-04-27 12:19:51 +01:00
Marcus Castro
b7a1bfd2d7 fix(plugins): cache installed manifest registry 2026-04-27 12:19:51 +01:00
Peter Steinberger
e59e0393f5 fix(acpx): mark claude acp package test-only 2026-04-27 12:18:59 +01:00
Peter Steinberger
da822a56d8 refactor(vllm): own nemotron thinking payloads 2026-04-27 12:15:54 +01:00
Peter Steinberger
22bb53ac9a docs(changelog): note tool cache channel invalidation 2026-04-27 12:14:51 +01:00
Peter Steinberger
2cfe6bf4e5 fix(ollama): dedupe latest models during setup 2026-04-27 12:14:10 +01:00
Peter Steinberger
78577ac147 fix: route tasks json through lean cli path 2026-04-27 12:13:51 +01:00
Peter Steinberger
e20f755ac5 fix(gateway): invalidate tool inventory on channel registry changes 2026-04-27 12:13:39 +01:00
Peter Steinberger
277cc640b1 fix(acp): wait for claude results before idle completion 2026-04-27 12:12:48 +01:00
Peter Steinberger
eebdda92f0 fix(media): keep audio input repair in doctor 2026-04-27 12:12:41 +01:00
Peter Steinberger
e98f976a70 refactor: centralize provider stream fallback ownership 2026-04-27 12:11:29 +01:00
清秋
8200d878a3 fix(ui): harden webchat input history behavior
Harden WebChat input history handling so draft, navigation, and render-state behavior stay consistent across the chat UI.

Validated locally on the rebased PR head 742a5f22f1:
- CI=true OPENCLAW_LOCAL_CHECK=0 pnpm check:changed
- CI=true OPENCLAW_LOCAL_CHECK=0 pnpm test:changed

Closes #38702.
2026-04-27 06:08:55 -05:00
Peter Steinberger
1971db0dc5 fix(media): expand legacy audio input placeholder 2026-04-27 12:06:58 +01:00
Peter Steinberger
8e14f5c749 fix(agents): drop malformed reasoning before orphan close tags 2026-04-27 12:06:37 +01:00
Egor Dementyev
b081b195a3 feat(hooks): emit gateway shutdown lifecycle events (#63084)
Merged via squash.

Prepared head SHA: 188d6fef24
Co-authored-by: eyev0 <22837926+eyev0@users.noreply.github.com>
Co-authored-by: BunsDev <68980965+BunsDev@users.noreply.github.com>
Reviewed-by: @BunsDev
2026-04-27 06:05:43 -05:00
Peter Steinberger
45bc7f69f2 fix(gateway): cache effective tool inventory 2026-04-27 12:04:40 +01:00
Peter Steinberger
496964fced test: speed up subagent announce format e2e 2026-04-27 12:03:54 +01:00
Peter Steinberger
a3144b6bfd fix(agents): preserve explicit Ollama local auth marker 2026-04-27 12:00:51 +01:00
Peter Steinberger
9dd01b5e49 fix: align plugin runtime dependency contracts 2026-04-27 11:58:28 +01:00
Peter Steinberger
9bc703213b fix(control-ui): preserve loopback client version labels 2026-04-27 11:56:58 +01:00
Peter Steinberger
7ef899ad96 test: speed up channel onboarding e2e 2026-04-27 11:55:16 +01:00
Peter Steinberger
583f32f56f test: align auth and config help expectations 2026-04-27 11:52:54 +01:00
Peter Steinberger
4f7498f6df chore: update config help baseline 2026-04-27 11:51:55 +01:00
Peter Steinberger
6ae2e9e9dc fix(gateway): keep effective tools on hot registry path 2026-04-27 11:51:15 +01:00
Peter Steinberger
9dcd53c0b6 fix(memory): avoid watchers for memory CLI commands 2026-04-27 11:50:44 +01:00
Peter Steinberger
c9b9887583 test: speed up embedded runner e2e mocks 2026-04-27 11:50:37 +01:00
Peter Steinberger
836d4b4105 refactor(vllm): own qwen thinking payloads 2026-04-27 11:50:25 +01:00
Peter Steinberger
4f7038ae33 fix(anthropic): drop prefill with thinking 2026-04-27 11:50:25 +01:00
Peter Steinberger
75c8c1bebe fix(agents): honor qwen chat-template thinking compat 2026-04-27 11:50:24 +01:00
Peter Steinberger
3db407da40 test(security): cover bundled plugin allowlist audit 2026-04-27 11:50:24 +01:00
Peter Steinberger
4a65b69073 fix: accept local markers for custom ollama providers 2026-04-27 11:47:09 +01:00
Peter Steinberger
5a81c4000c chore: tighten plugin boundary export audit 2026-04-27 11:47:09 +01:00
Peter Steinberger
236ca49998 docs: clarify memory search input type help 2026-04-27 11:47:06 +01:00
Peter Steinberger
f487ed160e test(agents): fix compatible retry fixture 2026-04-27 11:44:56 +01:00
Peter Steinberger
769994eb04 test(agents): cover compatible empty retries 2026-04-27 11:44:55 +01:00
Peter Steinberger
fd9d32f022 fix(agents): retry empty compatible turns 2026-04-27 11:44:55 +01:00
Peter Steinberger
edb3e84898 fix: clean stale plugin channel config 2026-04-27 11:41:53 +01:00
harish ganeshmurthy
fa0f7d1e73 fix(webchat): hide reset startup prompt from history
Closes #72369.

Remote validation (Blacksmith Testbox tbx_01kq7874j733m8pxesmgvfz1x1):
- pnpm test src/auto-reply/reply/get-reply-run.media-only.test.ts src/gateway/server-methods/server-methods.test.ts
- node scripts/run-vitest.mjs run --config test/vitest/vitest.unit-ui.config.ts ui/src/ui/controllers/chat.test.ts
- pnpm check:changed

Co-authored-by: haishmg <4529977+haishmg@users.noreply.github.com>
2026-04-27 11:41:33 +01:00
Peter Steinberger
ae86541364 fix: export tts runtime plugin sdk subpath 2026-04-27 11:40:56 +01:00
Vincent Koc
9ef0131e1c docs(local-models): note LAN-local auth marker support (fee16865b2 + 0dd2844991)
Trace to fee16865b2 (fix(agents): accept LAN local auth markers) and the
companion 0dd2844991 (fix: preserve Ollama local marker auth). The fix
extends ollama-local marker handling to any custom OpenAI-compatible
provider whose baseUrl resolves to loopback, a private LAN, .local, or a
bare hostname, so persisted local markers no longer fail with missing-auth
errors for non-Ollama-typed local providers (LM Studio, vLLM, LiteLLM).

The Ollama provider page already covers ollama-local for Ollama-typed
providers; this note lives in docs/gateway/local-models.md where custom
OpenAI-compatible local stacks are documented.
2026-04-27 03:39:26 -07:00
Peter Steinberger
7688b696de refactor: remove bundled plugin sdk self imports 2026-04-27 11:36:08 +01:00
Peter Steinberger
8a8cc8dc9f fix(memory): refresh tool config at execution 2026-04-27 11:36:02 +01:00
Peter Steinberger
fa468d0c2d fix(bonjour): default mdns host to system hostname 2026-04-27 11:35:19 +01:00
Vincent Koc
3a73826e28 fix(docs-sync): prune orphan locale docs whose English source no longer exists
The publish workflow rsyncs source docs/ into the publish repo with --delete,
but explicitly protects locale directories so translation files survive
non-translation-pipeline syncs. When an English source file is renamed (for
example install/migrating-matrix.md -> channels/matrix-migration.md), the
locale copies at <locale>/install/migrating-matrix.md become orphans:
deleted from the English nav but still present on disk.

Mintlify's hosted build appears to silently fall back to the previous
deployment when nav references a path with mixed locale availability, so
recent docs changes (the migration hub rework, matrix-migration move) are
not propagating to docs.openclaw.ai even though every CI run reports
success and the publish repo has the right English content.

Add a pruneOrphanLocaleDocs() pass that walks every generated-locale
directory in the publish target and removes any .md/.mdx file whose
matching English path no longer exists in source docs. Runs after rsync
and before composing docs.json so the regenerated nav and the on-disk
files stay consistent. Verified the logic against the live publish repo:
identifies all ja-JP/es/pt-BR/ko/de/fr/ar/it/tr/uk/id/pl/zh-CN orphans of
install/migrating-matrix.md (12 entries) and would also catch any future
renames the same way.
2026-04-27 03:34:57 -07:00
Peter Steinberger
ca88daad1e test(agents): keep openai image cache probe non-blocking 2026-04-27 11:34:15 +01:00
Peter Steinberger
169d33ded2 test: speed up auth rotation e2e 2026-04-27 11:33:36 +01:00
Peter Steinberger
d337fa8946 test: align build profile guard expectations 2026-04-27 11:31:57 +01:00
Peter Steinberger
f50fb73560 fix(whatsapp): honor env proxy during QR login 2026-04-27 11:30:29 +01:00
Bartok
f0b327cf68 fix(media): gate markdown image extraction by channel (#72718)
Closes #72642

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-27 11:27:35 +01:00
Peter Steinberger
775ed36c16 feat(memory): support asymmetric embedding input types 2026-04-27 11:25:40 +01:00
Peter Steinberger
0dd2844991 fix: preserve Ollama local marker auth 2026-04-27 11:25:06 +01:00
Peter Steinberger
a421e0be84 test: fix plugin registry CI contracts 2026-04-27 11:25:06 +01:00
Peter Steinberger
a0aedea63d fix: guard cli bootstrap imports 2026-04-27 11:24:35 +01:00
Peter Steinberger
fa0d81ed13 fix(agents): retry empty openai-compatible turns 2026-04-27 11:24:14 +01:00
Peter Steinberger
f820f89f14 test(agents): align local marker auth expectation 2026-04-27 11:23:56 +01:00
Peter Steinberger
f6ee2877e0 refactor: share memory dreaming cron constants 2026-04-27 11:19:09 +01:00
Peter Steinberger
9b0a0fb0a7 refactor: tighten plugin boundary surfaces 2026-04-27 11:19:09 +01:00
Peter Steinberger
c4fe72b8d6 ci: pin full release validation child refs 2026-04-27 11:16:16 +01:00
Peter Steinberger
bc0b02b2a6 fix(channels): avoid bundled plugin load paths 2026-04-27 11:15:42 +01:00
Peter Steinberger
4067d78a4c fix(exec): enforce default timeout on node runs 2026-04-27 11:15:33 +01:00
Peter Steinberger
c20bcc59a8 fix(git-hooks): skip ignored staged paths 2026-04-27 11:12:55 +01:00
Vincent Koc
0e4be1e3d3 docs(matrix): move migration guide from install/ to channels/
The Matrix migration guide is plugin-upgrade content (encrypted-state recovery,
device verification, room-key restore) rather than a cross-system import or
machine move, so it belongs alongside the Matrix channel docs rather than under
Install > Maintenance > Migrating.

- Move docs/install/migrating-matrix.md to docs/channels/matrix-migration.md
- Update inbound link in docs/channels/matrix.md
- Update the migrating.md hub: replace the Matrix Card with a one-line link in 'Upgrade a plugin in place'
- Refresh Related list on the moved page (link Matrix push rules and Migration guide hub)
- docs.json: remove install/migrating-matrix from Maintenance > Migrating, slot channels/matrix-migration between channels/matrix and channels/matrix-push-rules in the Mainstream channels group, and add a /install/migrating-matrix -> /channels/matrix-migration redirect
2026-04-27 03:12:32 -07:00
Peter Steinberger
7630322f64 docs: format migration guides 2026-04-27 11:11:27 +01:00
Peter Steinberger
6778e44333 test(exec): cover background timeout opt-out 2026-04-27 11:10:51 +01:00
Shakker
07946a404d chore: update a2ui bundle hash 2026-04-27 11:10:12 +01:00
Shakker
06de1d2080 fix: reuse web provider candidate manifests 2026-04-27 11:10:12 +01:00
Peter Steinberger
4003e4389a fix(memory-core): support dreaming model override 2026-04-27 11:08:21 +01:00
Peter Steinberger
b8a9dc9d78 test(moonshot): avoid redundant live result type 2026-04-27 11:07:21 +01:00
Peter Steinberger
9d52b615ad feat(ollama): prefix memory embedding queries 2026-04-27 11:07:20 +01:00
Peter Steinberger
92100efa04 fix(exec): honor default timeout for background runs 2026-04-27 11:06:23 +01:00
Peter Steinberger
ca882aeb42 test: remove discord sdk path references 2026-04-27 11:03:14 +01:00
Peter Steinberger
9f62c73893 fix(cron): verify delivery before clearing message warnings 2026-04-27 11:02:09 +01:00
Peter Steinberger
a4b97075ae fix: align support URL redaction 2026-04-27 11:00:42 +01:00
Peter Steinberger
5757d1bb69 ci: harden live release validation lane 2026-04-27 10:59:25 +01:00
Peter Steinberger
fee16865b2 fix(agents): accept LAN local auth markers 2026-04-27 10:57:35 +01:00
Vincent Koc
a6eb051b3a docs(migration): convert migrating.md to a hub, nest per-source guides, reorder nav
- install/migrating: convert to a hub page with three clear paths (CardGroup for cross-system imports linking Claude+Hermes, machine-to-machine move with Steps and AccordionGroup, plugin upgrade Card linking Matrix)
- install/migrating-claude: align with Hermes page structure (add Restart-and-verify Step, JSON output for automation, Troubleshooting AccordionGroup with 4 entries, cross-link to Hermes guide)
- cli/migrate: tighten intro to mention both bundled providers and link the migration hub
- docs.json: move Maintenance group to immediately after Install overview, nest the four migrating pages (migrating, migrating-claude, migrating-hermes, migrating-matrix) under a 'Migrating' subgroup so they collapse into a dropdown
2026-04-27 02:57:15 -07:00
Peter Steinberger
a0023f4978 fix(logging): redact URL query secrets 2026-04-27 10:56:47 +01:00
Peter Steinberger
1b581b4c71 fix(ci): stabilize live release validation 2026-04-27 10:56:35 +01:00
Peter Steinberger
e7432ae01d fix: redact URL query credentials in diagnostics 2026-04-27 10:55:22 +01:00
Peter Steinberger
d33eebd050 fix(cron): ignore delivered presentation warnings 2026-04-27 10:53:35 +01:00
VACInc
614a2846a2 fix: continue Google Live consult responses (#72189) (thanks @VACInc)
Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
2026-04-27 10:52:00 +01:00
Peter Steinberger
8f262211ee docs(ollama): clarify qwen stability settings 2026-04-27 10:49:44 +01:00
Peter Steinberger
7dc9a367ef fix: avoid persisting proxy env in gateway services 2026-04-27 10:46:31 +01:00
Shakker
021ef1220d fix: reuse provider discovery plugin metadata 2026-04-27 10:46:09 +01:00
Peter Steinberger
c9e6f371e4 fix(memory-core): quiet request-scoped fallback 2026-04-27 10:45:55 +01:00
Peter Steinberger
dfe58a1b8e fix(agents): treat TUI client label as current session 2026-04-27 10:45:26 +01:00
ziyitan
27ee5c0098 fix(gateway): redact secrets in skills.update response (#69998)
Merged via squash.

Prepared head SHA: 61fc06f33f
Co-authored-by: Ziy1-Tan <49604965+Ziy1-Tan@users.noreply.github.com>
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
Reviewed-by: @hxy91819
2026-04-27 17:45:16 +08:00
Peter Steinberger
16eae4b4b4 fix(memory-core): skip cleanup after narrative fallback 2026-04-27 10:44:21 +01:00
Val Alexander
14a27e11f7 feat(ui): show raw config pending changes
Adds a raw config pending-changes diff panel in Control UI raw mode, with JSON5 parsing, sensitive-value redaction until explicit reveal, bounded diff work, and tests for redaction/reveal and stale reveal-state reset.

Also aligns provider manifest contract coverage for google-vertex and Qwen aliases to unblock the rebased CI matrix.

Supersedes stale PRs #48621 and #46654. PR #48621 had gone stale without maintainer follow-up, so this maintainer-authored PR carries the implementation forward transparently while preserving changelog credit for the original contributor and @BunsDev.
2026-04-27 04:42:10 -05:00
Peter Steinberger
531a0ddfe4 fix(config): repair retired llm timeout key 2026-04-27 10:39:56 +01:00
Vincent Koc
a50edbdc60 fix(cli): keep nodes list aligned with nodes status (#72619)
* fix(cli): keep nodes list aligned with nodes status

* fix(clownfish): address review for ghcrawl-156588-autonomous-smoke (1)

* fix(cli): keep nodes list aligned with nodes status
2026-04-27 02:39:33 -07:00
Vincent Koc
af03f9248d docs(feishu): clarify @all is not a bot mention (b642ebece9)
Trace to b642ebece9 (fix(feishu): do not treat @all as a bot mention).
Document the new behavior in the mention requirement section: broadcast-only
@all/@_all messages no longer wake the bot, while messages that combine @all
with a direct bot mention still count as a bot mention.
2026-04-27 02:38:52 -07:00
Peter Steinberger
733aaa0117 docs(cli): disambiguate migration import headings 2026-04-27 10:38:47 +01:00
Peter Steinberger
e862e0acb5 fix(providers): guard self-hosted model discovery 2026-04-27 10:38:17 +01:00
Peter Steinberger
f9b78fb08e docs(models): clarify local tool call workaround 2026-04-27 10:37:52 +01:00
Vincent Koc
59fb5fd3a7 fix(mattermost): prevent DM replies from creating threads (#72659)
* fix(mattermost): prevent DM replies from creating threads

* fix(mattermost): prevent DM replies from creating threads

* fix(mattermost): prevent DM replies from creating threads
2026-04-27 02:37:47 -07:00
Peter Steinberger
72f7d7e4ea fix(gateway): scope plugin subagent cleanup ownership 2026-04-27 10:36:33 +01:00
Vincent Koc
600df95c8c feat(migrate): add Claude importer
Add a bundled Claude migration provider for Claude Code and Claude Desktop imports.\n\nIncludes source discovery, preview/apply behavior for instructions, MCP servers, skills and command prompts, archive/manual handling for unsafe Claude state, docs, labeler, and tests.
2026-04-27 02:35:44 -07:00
Peter Steinberger
cf499101a2 fix(agents): normalize Windows runtime imports (#72731)
* fix(agents): normalize Windows runtime imports

* test(providers): align manifest contract coverage
2026-04-27 10:34:25 +01:00
Peter Steinberger
8b85f2c163 test: align provider contract aliases 2026-04-27 10:33:56 +01:00
Peter Steinberger
1ee885123f docs(models): document required tool choice workaround 2026-04-27 10:32:20 +01:00
Shakker
7d9dc8cf24 fix: reuse plugin manifests for model pricing refresh 2026-04-27 10:25:41 +01:00
Peter Steinberger
3af34316f2 fix: preserve clawhub install selectors 2026-04-27 10:25:21 +01:00
Peter Steinberger
1b81f75654 docs(providers): document cerebras setup 2026-04-27 10:22:21 +01:00
Peter Steinberger
4de235f908 feat(providers): add cerebras plugin 2026-04-27 10:22:20 +01:00
Peter Steinberger
08a002d8ab docs: document npm-only plugin installs 2026-04-27 10:20:30 +01:00
Peter Steinberger
13f9deb619 fix: audit windows task managed env drift 2026-04-27 10:19:50 +01:00
Peter Steinberger
cb9955dd5c fix: support npm-only plugin installs 2026-04-27 10:16:59 +01:00
Peter Steinberger
e899b32e1d fix(agents): collapse local model timeout knobs 2026-04-27 10:16:50 +01:00
Peter Steinberger
67f1266fe8 fix: repair managed service env install migration 2026-04-27 10:13:01 +01:00
Vincent Koc
b642ebece9 fix(feishu): do not treat @all as a bot mention (#72658)
* fix(feishu): do not treat @all as a bot mention

* fix(feishu): do not treat @all as a bot mention
2026-04-27 02:10:17 -07:00
Val Alexander
14ab00755f feat(ui): display agent identities in session list
Display friendly agent identity labels in the Control UI Sessions key column when identity data is available, keep raw-key fallback behavior, and allow filtering by agent identity name.

This is the maintainer-owned replacement for #54212 by @dingtao416. Thanks @dingtao416 for the original feature idea and implementation direction.

Includes follow-up fixes from maintainer review automation: normalized key-cell classes, own-property identity lookup, and friendly-label tooltips.

Validation:
- pnpm test ui/src/ui/format.test.ts ui/src/ui/views/sessions.test.ts
- pnpm check:changed

Closes #54163.
Supersedes #54212.
2026-04-27 04:09:39 -05:00
Peter Steinberger
9f450dcf06 fix: reject malformed clawhub plugin specs 2026-04-27 10:08:27 +01:00
Samuel Rodda
6c252cc54c fix(update): require applied gateway restarts
Require Control UI updates to observe a real gateway process replacement, surface skipped/error update outcomes, and verify the running gateway version after restart.\n\nAdds update.status restart-sentinel plumbing, docs, generated protocol model updates, and changelog attribution.\n\nLocal verification:\n- pnpm test src/gateway/server-methods/update.test.ts src/cli/gateway-cli/run-loop.test.ts src/infra/restart-sentinel.test.ts src/infra/process-respawn.test.ts src/infra/update-runner.test.ts ui/src/ui/app-gateway.node.test.ts ui/src/ui/controllers/config.test.ts\n- git diff --check\n- pnpm exec oxfmt --check --threads=1 CHANGELOG.md docs/gateway/protocol.md docs/gateway/configuration.md docs/web/control-ui.md\n- pnpm docs:check-mdx
2026-04-27 04:07:43 -05:00
Peter Steinberger
b74f35ee6f refactor(plugins): move provider routing metadata to manifests 2026-04-27 10:06:30 +01:00
Peter Steinberger
57092a1794 ci: harden cross-os release harness on Windows 2026-04-27 10:03:38 +01:00
Peter Steinberger
3f895e5b49 test: dedupe hot unit fast coverage 2026-04-27 10:02:46 +01:00
Peter Steinberger
edbab0e2db fix: harden Google Live tool responses (#72426) (thanks @BsnizND) 2026-04-27 09:58:23 +01:00
BSnizND
409e762810 Fix Google Live tool response names 2026-04-27 09:58:23 +01:00
Peter Steinberger
b4b21cbc93 fix(browser): circuit-break managed launch failures 2026-04-27 09:58:14 +01:00
Vincent Koc
36a936af66 fix(update): add auto-update kill switch 2026-04-27 01:58:02 -07:00
Vincent Koc
caba05b94a fix(plugins): harden bundled install/uninstall sweep
Fix bundled plugin install/uninstall sweep coverage and avoid persisting invalid placeholder config for config-gated bundled plugins.
2026-04-27 01:57:40 -07:00
Peter Steinberger
7421112898 fix(agents): pass OpenAI SDK request timeouts 2026-04-27 09:55:39 +01:00
Peter Steinberger
cb45f16330 docs: clarify cron concurrency lanes 2026-04-27 09:54:58 +01:00
Peter Steinberger
04f76a8fdb test: remove duplicate plugin enable mock 2026-04-27 09:54:58 +01:00
Vincent Koc
b81eaf8a4e fix(agents): keep claude live streams valid 2026-04-27 01:53:37 -07:00
Peter Steinberger
6fddf17632 fix: accept clawhub plugin api wildcards 2026-04-27 09:48:01 +01:00
Peter Steinberger
6c8f0d04c3 test: trim unit-fast hotspots 2026-04-27 09:46:06 +01:00
Peter Steinberger
981cb89ea3 fix(agents): strip stale gemini assistant prefill 2026-04-27 09:41:37 +01:00
Peter Steinberger
a35ad200d1 test: shrink image sanitizer fixtures 2026-04-27 09:39:28 +01:00
Peter Steinberger
7d74c29dcc fix: isolate cron nested lane concurrency 2026-04-27 09:39:10 +01:00
Vincent Koc
231eb7b52a docs(migrating-hermes): note partial-apply guard introduced by 8bdfa58cbb
Trace to 8bdfa58cbb (fix(migrations): avoid partial Hermes config apply after
conflict). Hermes apply now marks remaining dependent config items as
"blocked by earlier apply conflict" when a conflict surfaces mid-apply,
instead of writing them partially. Document the user-visible reason string
and where to find blocked items in the migration report.
2026-04-27 01:38:49 -07:00
Peter Steinberger
f97cc58760 fix(browser): auto-start configured browser plugin 2026-04-27 09:37:10 +01:00
Shakker
e792f96a84 fix: cache capability provider manifest ids 2026-04-27 09:36:53 +01:00
Peter Steinberger
e21c909bd0 fix(agents): strip stale anthropic assistant prefill 2026-04-27 09:36:25 +01:00
Peter Steinberger
3be8e68898 test: dedupe fast lane imports 2026-04-27 09:35:41 +01:00
Vincent Koc
56ca4e2269 fix(daemon): handle sudo user-systemd gateway install failures
* fix(daemon): handle sudo user-systemd gateway install failures

* fix(daemon): harden sudo systemctl user scope

* fix(plugins): remove static type-cycle edges

* test(plugins): update bundle command config mock
2026-04-27 01:34:57 -07:00
Peter Steinberger
c25082f92e fix: apply cron concurrency to nested lane 2026-04-27 09:33:26 +01:00
Peter Steinberger
b9b15bec85 fix(ci): stabilize full validation probes 2026-04-27 09:30:53 +01:00
BsnizND
916eda16c1 fix(google-meet): keep tool sessions gateway-owned
Routes stateful Google Meet tool actions through the gateway-owned runtime so create/join/status/speak/leave share the same session owner instead of losing tool-created realtime sessions after the agent turn.

Also preserves structured gateway error details for missing session ids and tightens node-host child cleanup for already-closed sessions.

Fixes #72440.

Co-authored-by: BSnizND <199837910+BsnizND@users.noreply.github.com>
2026-04-27 09:28:14 +01:00
Peter Steinberger
b09afa2993 fix: keep auto model fallbacks pinned until reset 2026-04-27 09:27:19 +01:00
Peter Steinberger
a60f15c611 refactor(gateway): move model pricing policy to manifests 2026-04-27 09:26:53 +01:00
Vincent Koc
a494eea6d4 fix(gateway): defer hook request handler imports 2026-04-27 01:26:38 -07:00
Peter Steinberger
a95da5b52d fix(models): enrich local transport failure diagnostics 2026-04-27 09:25:38 +01:00
Peter Steinberger
c2d82b87ee test(plugins): mock registry contribution seam 2026-04-27 09:23:59 +01:00
Peter Steinberger
444acde1de feat: support layered plugin runtime deps 2026-04-27 09:21:25 +01:00
Peter Steinberger
9611260225 fix: retry primary after auto model fallback 2026-04-27 09:19:03 +01:00
Peter Steinberger
983bac7afa fix(plugins): keep registry lookup types acyclic 2026-04-27 09:16:43 +01:00
Peter Steinberger
3eb6a5b209 docs: format migration docs 2026-04-27 09:16:36 +01:00
Peter Steinberger
f9181835e8 fix(agents): warn on fake local tool calls 2026-04-27 09:14:59 +01:00
Shakker
51bd95fff3 fix: reuse extractor manifest resolution pass 2026-04-27 09:12:51 +01:00
Shakker
c60581740a fix: reuse manifest pass for runtime contract owners 2026-04-27 09:12:51 +01:00
Shakker
e547070ba9 fix: avoid repeated plugin metadata load for channel command defaults 2026-04-27 09:12:50 +01:00
Peter Steinberger
3913aa999d test: lighten fast lane imports 2026-04-27 09:12:17 +01:00
github-actions[bot]
b09345e3f6 chore(ui): refresh th control ui locale 2026-04-27 08:12:10 +00:00
Peter Steinberger
d76f924be3 fix(plugins): avoid registry barrel topology cycle 2026-04-27 09:09:31 +01:00
Peter Steinberger
5b616e2bec fix(agents): narrow session lock scope 2026-04-27 09:09:19 +01:00
Peter Steinberger
5ff49ae03e fix(gateway): skip local model pricing refreshes 2026-04-27 09:09:19 +01:00
bbddbb
563718c2e4 feat(control-ui): confirm dreaming restart changes
Require explicit confirmation before applying restart-impacting Dreaming mode changes in the Control UI.

- Add pending/confirm/loading state for the Dreaming toggle path
- Render a restart confirmation dialog before sending the config patch
- Sync Control UI locale metadata and cover the confirmation flow in browser tests

Fixes #63804
2026-04-27 03:08:59 -05:00
Peter Steinberger
276291d399 fix: hide bonjour Windows ARP shell probe 2026-04-27 09:08:40 +01:00
Peter Steinberger
8bdfa58cbb fix(migrations): avoid partial Hermes config apply after conflict 2026-04-27 09:07:59 +01:00
Vincent Koc
0055e404cf docs(hermes): rework CLI migrate page and add user-facing migration guide
- cli/migrate: convert flat reference into structured Mintlify page (Tip pointer, ParamField for flags, AccordionGroup for safety model, sub-sections for Hermes provider with what's imported, .env keys, archive-only state, and plugin contract)
- install/migrating-hermes: new dedicated user guide modeled after migrating-matrix.md (Tabs for onboarding vs CLI, AccordionGroup for what gets imported, Steps for recommended flow, Warning for --overwrite, Troubleshooting accordions)
- docs.json: add install/migrating-hermes to Maintenance group alongside migrating and migrating-matrix
2026-04-27 01:04:00 -07:00
Peter Steinberger
184b024fb6 test(migrate-hermes): keep config runtime stateful 2026-04-27 09:02:14 +01:00
Peter Steinberger
87b8072a85 test: cover qqbot channel guardrails 2026-04-27 08:58:13 +01:00
Peter Steinberger
f7081a3879 fix(lmstudio): trust configured local endpoints 2026-04-27 08:55:45 +01:00
Peter Steinberger
9510906669 fix: stop hook fallback after security blocks 2026-04-27 08:55:38 +01:00
Peter Steinberger
5a3d01e480 docs: format plugin sdk subpaths 2026-04-27 08:53:31 +01:00
Peter Steinberger
f21c8c3f0c test(migrate-hermes): use OpenClaw temp root 2026-04-27 08:53:27 +01:00
Peter Steinberger
58037cc89d fix: resolve browser playwright runtime deps 2026-04-27 08:50:56 +01:00
Peter Steinberger
c1d827844c test: speed up unit fast lane 2026-04-27 08:49:09 +01:00
Shakker
45b0d5ccc2 chore: add plugin lookup startup trace metrics 2026-04-27 08:48:18 +01:00
Shakker
bed76c26e7 fix: reuse lookup table for deferred plugin reload 2026-04-27 08:48:18 +01:00
Shakker
e068165036 docs: note plugin lookup reuse followups 2026-04-27 08:48:18 +01:00
Shakker
8b396bcfd2 docs: document plugin lookup table 2026-04-27 08:48:18 +01:00
Shakker
7c985890af refactor: reuse lookup table during gateway plugin load 2026-04-27 08:48:18 +01:00
Shakker
b2deb74694 fix: include setup cli backends in plugin lookup 2026-04-27 08:48:18 +01:00
Shakker
5228b24927 fix: avoid spread in provider owner lookup 2026-04-27 08:48:18 +01:00
Shakker
af29ccd98f fix: copy lookup startup plugin ids for gateway load 2026-04-27 08:48:18 +01:00
Shakker
f41126bc2e refactor: resolve contribution owners from lookup maps 2026-04-27 08:48:17 +01:00
Shakker
fbf0a29195 refactor: expand plugin lookup owner maps 2026-04-27 08:48:17 +01:00
Shakker
dc6ac472db refactor: use plugin lookup table for gateway load fallback 2026-04-27 08:48:17 +01:00
Shakker
123dee0513 fix: avoid duplicate plugin lookup diagnostics 2026-04-27 08:48:17 +01:00
Shakker
635af612d5 refactor: expose plugin lookup table normalizer 2026-04-27 08:48:17 +01:00
Shakker
354eb37ff5 refactor: reuse manifest registry for plugin id normalization 2026-04-27 08:48:17 +01:00
Shakker
b8c9426911 refactor: reuse plugin lookup table for contribution owners 2026-04-27 08:48:17 +01:00
Shakker
e985acbc1c docs: note plugin startup lookup table 2026-04-27 08:48:17 +01:00
Shakker
3f38d3af88 refactor: add plugin lookup table 2026-04-27 08:48:17 +01:00
Peter Steinberger
66f4b52db3 fix(docker): route local provider setup to host gateway 2026-04-27 08:46:33 +01:00
Alex Knight
4e19bc80c9 Fix null params for parameterless tools (#72673)
* fix tool null params for parameterless schemas

* guard composite required tool schemas
2026-04-27 17:45:59 +10:00
Vincent Koc
f4ca0612b2 Merge branch 'main' of https://github.com/openclaw/openclaw
* 'main' of https://github.com/openclaw/openclaw:
  docs: point maintainer triage at gitcrawl
  fix: clean runtime deps backup owner marker
  test(browser): close hanging attach-only sockets
  fix(plugins): normalize windows override imports
  fix: preserve live runtime deps temp dirs
  fix(lmstudio): promote bracketed tool calls
  Add Google Meet realtime consult agentId (#72381)
  fix: normalize lazy service override imports
  test: split ui unit tests from generic lane
  feat(migrations): add plugin-owned Hermes import
  fix(ci): expose package deps to Telegram QA harness (#72680)
  fix: hide bundled runtime npm windows
2026-04-27 00:44:30 -07:00
Vincent Koc
0286bb9817 docs: point maintainer triage at gitcrawl
Update the OpenClaw PR maintainer skill to use gitcrawl for local triage commands.
2026-04-27 00:43:07 -07:00
Peter Steinberger
84929bf85b fix: clean runtime deps backup owner marker 2026-04-27 08:43:03 +01:00
Peter Steinberger
bfdee5fa72 test(browser): close hanging attach-only sockets 2026-04-27 08:40:25 +01:00
Peter Steinberger
15e634d50c fix(plugins): normalize windows override imports 2026-04-27 08:39:42 +01:00
Peter Steinberger
4514a73170 fix: preserve live runtime deps temp dirs 2026-04-27 08:39:35 +01:00
Peter Steinberger
da55212c6e fix(lmstudio): promote bracketed tool calls 2026-04-27 08:38:53 +01:00
BsnizND
d5e6abcb3d Add Google Meet realtime consult agentId (#72381)
Remote proof:
- CI run 24982271745 passed on 6122e13c9f.
- Blacksmith Testbox tbx_01kq6vwehcszjfpp52f0pb3v1q passed focused Google Meet formatting, docs/link checks, realtime consult runtime tests, Google Meet tests, extension test typecheck, the core-unit-fast-support shard, and the core support boundary shard.

Thanks @BsnizND.

Co-authored-by: BSnizND <199837910+BsnizND@users.noreply.github.com>
2026-04-27 08:36:59 +01:00
Vincent Koc
29f4cdfcbb docs: point maintainer triage at gitcrawl 2026-04-27 00:36:32 -07:00
Peter Steinberger
f6db86f9a0 fix: normalize lazy service override imports 2026-04-27 08:35:45 +01:00
Peter Steinberger
98e7242b53 test: split ui unit tests from generic lane 2026-04-27 08:35:04 +01:00
Vincent Koc
1fc5b2b703 feat(migrations): add plugin-owned Hermes import
* feat: add migration providers

* feat: offer Hermes migration during onboarding

* feat(hermes): map imported config surfaces

* feat(onboard): require fresh migration imports

* docs(cli): clarify Hermes import coverage

* chore(migrations): rename Hermes importer package

* chore(migrations): rewire Hermes importer id

* fix(migrations): redact migration JSON details

* fix(hermes): use provider runtime for config imports

* test(hermes): cover missing source planning

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-27 00:34:29 -07:00
Vincent Koc
75c52b6c41 fix(ci): expose package deps to Telegram QA harness (#72680)
* fix(ci): expose package deps to telegram QA harness

* fix(ci): link QA package runtime deps

* fix(agents): guard replay metadata in empty retries

* fix(ci): keep plugin update smoke migration-stable
2026-04-27 00:33:29 -07:00
Peter Steinberger
d23ee2f702 fix: hide bundled runtime npm windows 2026-04-27 08:31:07 +01:00
Peter Steinberger
720ea766e6 fix(release): stabilize release validation probes 2026-04-27 08:27:45 +01:00
Vincent Koc
3200378ab4 fix(gateway): defer hook agent runner imports 2026-04-27 00:26:55 -07:00
Peter Steinberger
556c3e87df fix(agents): strip Gemma reasoning from local replay 2026-04-27 08:26:28 +01:00
Peter Steinberger
f427ddc220 fix(cli): keep update completion refresh lightweight 2026-04-27 08:24:26 +01:00
Vincent Koc
1ee893bc5f fix(gateway): defer http auth imports 2026-04-27 00:22:36 -07:00
Peter Steinberger
735890d955 fix(agents): dedupe subagent startup task 2026-04-27 08:20:45 +01:00
Peter Steinberger
daf8e14874 docs: fix msteams federated auth anchor 2026-04-27 08:20:20 +01:00
Peter Steinberger
708d833a76 test(ui): reuse ui test module environment 2026-04-27 08:19:24 +01:00
Peter Steinberger
646a268d27 fix: stage mirrored logger runtime deps 2026-04-27 08:17:18 +01:00
Peter Steinberger
729147dcb5 fix(cron): start isolated timeout after execution begins 2026-04-27 08:15:59 +01:00
Peter Steinberger
45778a840d fix(lmstudio): allow keyless local onboarding 2026-04-27 08:15:17 +01:00
Peter Steinberger
37cd6027cf test(gateway): harden session event setup timeout 2026-04-27 08:11:11 +01:00
Peter Steinberger
d1a8e2b17c docs: note vitest serial flag 2026-04-27 08:08:09 +01:00
Peter Steinberger
ec9b20263c fix(docker): expose QA harness exports for package Telegram 2026-04-27 08:07:27 +01:00
Vincent Koc
5333b1e2cc fix(gateway): defer channel runtime imports 2026-04-27 00:07:13 -07:00
Peter Steinberger
49ce7fe90c test: cover slack bolt auth verification suppression 2026-04-27 08:03:38 +01:00
Vincent Koc
baace37fef docs: sentence-case sweep across 10 more pages
- tools/plugin: Package Entrypoints
- tools/code-execution: How To Use It
- tools/browser-linux-troubleshooting: Root Cause, Config Reference
- install/bun: Lifecycle Scripts
- nodes/audio: Mention Detection in Groups
- nodes/images: Inbound Media to Commands (Pi)
- platforms/android: Connection Runbook
- plugins/building-plugins: Beta Release Testing
- web/control-ui: Content Security Policy
- security/THREAT-MODEL-ATLAS: Framework Attribution
2026-04-27 00:03:18 -07:00
Peter Steinberger
9d33da6ddf fix(agents): sanitize blank Bedrock user replay 2026-04-27 08:03:02 +01:00
Peter Steinberger
3d6d08116d fix(release): expose QA package exports in Telegram acceptance 2026-04-27 08:02:23 +01:00
Vincent Koc
2a17abcf5d docs: sentence-case sweep across 4 more pages
- platforms/digitalocean: Cost Comparison (2026), Oracle Cloud Free Alternative
- gateway/remote-gateway-readme: Quick Setup, How It Works
- cli/crestodian: Setup Bootstrap
- plugins/codex-harness: Computer Use
(Brand-named headings preserved across azure.md, web.md, firecrawl.md, clawhub.md, config-channels.md, security/index.md.)
2026-04-27 00:01:52 -07:00
Vincent Koc
6a03b76c9a docs: full-page sentence-case sweep across 6 pages
- platforms/oracle: Cost Comparison (2026), Still Recommended, Verify Security Posture
- install/exe-dev: Automated Install with Shelley, Remote Access
- platforms/mac/dev-setup: Build Fails: Toolchain or SDK Mismatch, App Crashes on Permission Grant
- reference/AGENTS.default: What OpenClaw Does, Core Skills, Usage Notes
- install/docker: Containerized Gateway, Agent Sandbox
- ci: Package Acceptance, Job Overview, Local Equivalents
2026-04-27 00:00:31 -07:00
Vincent Koc
89230f2480 fix(gateway): defer mcp loopback imports 2026-04-27 00:00:04 -07:00
Peter Steinberger
090063bd43 fix(ci): harden cron and Docker validation 2026-04-27 07:59:28 +01:00
Vincent Koc
41268ded2d docs: full-page sentence-case sweep across 5 worst-offender pages
- channels/msteams: 8 H2/H3 (Federated Authentication, Local Development, Known Limitations, Reply Style, Presentation Cards, Private Channels, etc.)
- auth-credential-semantics: 4 H2 (Stable Probe Reason Codes, Token Credentials, Explicit Auth Order Filtering, Probe Target Resolution)
- tools/browser: preserve brand-named headings (Browserless, WebSocket CDP, Chrome MCP, Control API, Brave); minor cleanup
- security/CONTRIBUTING-THREAT-MODEL: 4 H2/H3 (What We Use, Risk Levels, Review Process; Threat IDs preserved as branded label)
- gateway/multiple-gateways: 4 H2 (Best Recommended Setup, Why This Works, General Multi-Gateway Setup, Isolation Checklist)
2026-04-26 23:58:35 -07:00
Peter Steinberger
f89d0f7c53 fix(cron): preserve telegram direct thread inference 2026-04-27 07:58:03 +01:00
Vincent Koc
ca9a04b271 docs: full-page readability pass on 5 worst-offender pages
- automation/standing-orders: sentence-case all H2/H3 headings (Why Standing Orders, Anatomy, Execute-Verify-Report Pattern, Multi-Program Architecture, Best Practices, etc.) and clean up Related link styling
- platforms/raspberry-pi: sentence-case 10 headings (Hardware Requirements, Performance Optimizations, Cost Comparison, etc.)
- install/fly: sentence-case troubleshooting and Private Deployment headings
- pi-dev: drop 'this guide summarizes' filler, sentence-case 4 H2 headings, restore brand-cased Pi
- concepts/model-providers: sentence-case Kimi Coding (other brand-named providers preserved as-is: Google Gemini, Google Vertex, Kilo Gateway, Volcano Engine)
2026-04-26 23:57:10 -07:00
Peter Steinberger
37d37d3779 fix(cron): tolerate legacy flat schedule identity 2026-04-27 07:56:26 +01:00
Peter Steinberger
53f536b368 fix: avoid slack startup auth rejection leak 2026-04-27 07:55:57 +01:00
Peter Steinberger
725938f0f5 test: avoid heavy registry imports in web provider tests 2026-04-27 07:53:09 +01:00
Vincent Koc
d43bf6de0a docs: batch sentence-case headings across high-Title-Case offenders
- pi.md: 9 H2 + 14 H3 (Package Dependencies, File Structure, Tool Pipeline, etc.)
- cli/hooks.md: 6 H2 (List All Hooks, Get Hook Information, etc.)
- plugins/message-presentation.md: 8 H2 (Producer Examples, Renderer Contract, etc.)
- plan/ui-channels.md: 7 H2 (Non Goals, Target Model, Refactor Steps, etc.)
- install/ansible.md: 6 H2 + 1 H3 (What You Get, Quick Start, etc.)

Mintlify anchor generation prefers sentence case for predictable URLs.
2026-04-26 23:52:28 -07:00
Peter Steinberger
18b6c3bb61 fix(docker): recognize current gateway readiness logs 2026-04-27 07:51:59 +01:00
Vincent Koc
4a30ae182b fix(gateway): defer embedded runner imports 2026-04-26 23:51:08 -07:00
Vincent Koc
69c30e37d9 fix(memory-lancedb): skip processed auto-capture messages safely (#72663) 2026-04-26 23:51:04 -07:00
Peter Steinberger
9ced682a9d fix(cron): omit disabled delivery trace errors 2026-04-27 07:50:50 +01:00
Peter Steinberger
4db1faaafc chore: install discord clawd skill 2026-04-27 07:50:15 +01:00
Peter Steinberger
c754370100 docs: document maintainer testbox opt-in 2026-04-27 07:49:28 +01:00
BsnizND
2785be2604 Fix Google Meet realtime interruption playback (#72524)
Fixes #72523.

Remote proof:
- CI run 24980529154 passed on 29f825bea5.
- Blacksmith Testbox tbx_01kq6tsgbaxgstxmtearwy9n4w passed focused formatting, Google Meet tests, Google realtime provider tests, and extension test typecheck.

Thanks @BsnizND.

Co-authored-by: BSnizND <199837910+BsnizND@users.noreply.github.com>
2026-04-27 07:49:10 +01:00
Peter Steinberger
8811112ab3 fix(release): stabilize full validation lanes 2026-04-27 07:46:44 +01:00
Peter Steinberger
ddcd9d62c4 fix(cron): invalidate stale external schedule slots 2026-04-27 07:46:08 +01:00
Peter Steinberger
3173842913 fix: keep staged plugin mirrors idempotent 2026-04-27 07:44:15 +01:00
Peter Steinberger
566295cd34 fix: materialize stale runtime mirror symlinks 2026-04-27 07:42:47 +01:00
Peter Steinberger
04be516926 fix(gateway): keep liveness probes independent of config load 2026-04-27 07:42:14 +01:00
Peter Steinberger
7559845597 fix(ollama): avoid implicit native num_ctx override 2026-04-27 07:42:14 +01:00
Vincent Koc
c4194b8345 docs(voice-call): note SecretRef support for twilio.authToken and tts.providers.*.apiKey
Trace to db09f68ce5 (Support SecretRef for voice-call credentials and bundled
plugin SecretInputs #72607). The reference page docs/reference/secretref-credential-surface.md
listed the new entries in the same SHA, but docs/plugins/voice-call.md showed
only plain-string credentials without pointing to the SecretRef surface.
2026-04-26 23:39:51 -07:00
Vincent Koc
015f7dc747 fix(agents): refresh bootstrap snapshot when workspace files change (#72406)
* fix(agents): refresh bootstrap snapshot when workspace files change

* fix(clownfish): address review for ghcrawl-207042-agentic-merge (1)
2026-04-26 23:39:33 -07:00
Peter Steinberger
c110f8c028 fix(docker): stabilize bundled channel release lanes 2026-04-27 07:37:28 +01:00
BsnizND
f2a17b2991 Fix Google Meet chrome-node bridge cleanup (#72372)
Fixes #72371.

Remote proof:
- CI run 24980121791 passed on d583a6b615.
- Blacksmith Testbox tbx_01kq6t5jk2f51gxq30j9veyjhy passed focused Google Meet formatting and tests.

Thanks @BsnizND.

Co-authored-by: BSnizND <199837910+BsnizND@users.noreply.github.com>
2026-04-27 07:37:18 +01:00
Vincent Koc
5c591a4e13 fix(test): build missing Docker images in Testbox 2026-04-26 23:33:43 -07:00
Peter Steinberger
67e6410e0f ci: accept legacy bundled docker lane 2026-04-27 07:31:18 +01:00
Peter Steinberger
4bca42d933 fix(cron): alert on persistent skipped runs 2026-04-27 07:31:04 +01:00
Vincent Koc
b246c06fa5 fix(daemon): surface systemd user-bus hints during gateway install (#72617) 2026-04-26 23:30:54 -07:00
Vincent Koc
dcff28d285 fix(telegram): hide acknowledged failed-tool warnings from chat (#72410)
* fix(telegram): hide acknowledged failed-tool warnings from chat

* fix(clownfish): address review for ghcrawl-207034-agentic-merge (1)

* fix(clownfish): address review for ghcrawl-207034-agentic-merge (1)
2026-04-26 23:29:19 -07:00
Peter Steinberger
ca44ab65e6 ci(release): allow live E2E actions reads 2026-04-27 07:26:33 +01:00
Peter Steinberger
9313554a8d test: stabilize matrix block streaming prompt 2026-04-27 07:25:52 +01:00
Peter Steinberger
edf43dfc88 ci: fix update channel package version probe 2026-04-27 07:23:23 +01:00
Peter Steinberger
cf04fa24d8 test(openai): prefer exact live registry models 2026-04-27 07:22:26 +01:00
Bek
aac83e00cf fix: Slack inbound thread session routing (#72498)
Normalize actionable Slack thread roots and follow-up replies onto the same thread parent session key.
2026-04-27 02:19:27 -04:00
Peter Steinberger
93ac2cefaa ci(docker): resolve short refs before checkout 2026-04-27 07:18:57 +01:00
Peter Steinberger
a3fcb8db79 ci(docker): split bundled release lanes 2026-04-27 07:17:14 +01:00
Josh Avant
db09f68ce5 Support SecretRef for voice-call credentials and bundled plugin SecretInputs (#72607)
* fix: support voice-call secretrefs

* test: classify plugin secretref targets

* docs: credit voice-call secretref change

* fix: keep plugin secret target discovery lightweight
2026-04-27 01:16:50 -05:00
Vincent Koc
ab237fe7b0 fix(gateway): defer chat startup helpers 2026-04-26 23:15:26 -07:00
Peter Steinberger
1dac448ff0 fix: wait for qa gateway restart boundary 2026-04-27 07:13:39 +01:00
Vincent Koc
1427c3a78d fix(sessions_spawn): tolerate ACP-only fields for subagent runtime (#72331) 2026-04-26 23:11:42 -07:00
Peter Steinberger
44a504cd39 ci: time-box package acceptance legacy compat 2026-04-27 07:11:14 +01:00
Vincent Koc
e6d2c9b080 fix(process): decode Windows command output with console codepage awareness (#72393)
* fix(process): decode Windows command output with console codepage awareness

* fix(clownfish): address review for ghcrawl-199248-agentic-merge (1)
2026-04-26 23:10:59 -07:00
Peter Steinberger
5cc06c69a9 fix(discord): preserve explicit delivery target kind 2026-04-27 07:09:45 +01:00
Peter Steinberger
ca67762b88 fix(image): honor media timeouts 2026-04-27 07:09:36 +01:00
Peter Steinberger
19cb9ca6bf fix: materialize staged plugin runtime chunks 2026-04-27 07:08:44 +01:00
Vincent Koc
8440f67935 fix(gateway): defer chat event imports 2026-04-26 23:07:05 -07:00
Peter Steinberger
6175309c01 fix: normalize openai legacy image sizes 2026-04-27 07:05:56 +01:00
Vincent Koc
b1812387a0 fix(agent): harden empty attempt retry handling 2026-04-26 23:04:40 -07:00
Josh Avant
b3d9948c4c fix: use runtime snapshot for TTS SecretRefs (#72581)
* fix: use runtime snapshot for tts secrets

* fix: keep tts secret snapshot selection local

* docs: add tts secretref changelog entry
2026-04-27 01:02:17 -05:00
Peter Steinberger
ac5a1d1622 ci: forward package acceptance live secrets 2026-04-27 07:00:11 +01:00
Peter Steinberger
2a6fab9d22 docs: point release evidence at public checks 2026-04-27 06:57:47 +01:00
Vincent Koc
c7d77f8c7b fix(gateway): defer plugin HTTP dispatch 2026-04-26 22:55:26 -07:00
Peter Steinberger
32aa631e19 test: relax matrix block streaming qa timeout 2026-04-27 06:54:43 +01:00
Peter Steinberger
8de02c318b fix: reclaim orphan session write locks 2026-04-27 06:54:43 +01:00
Peter Steinberger
e962381dbf ci: fix plugin update smoke quoting 2026-04-27 06:50:59 +01:00
Vincent Koc
b02cca4e00 fix(gateway): trim startup imports 2026-04-26 22:48:31 -07:00
Alex Knight
06b3e4ef8a Fail invalid plugin registration gates loudly (#72577)
* fix plugin registration gate failures
2026-04-27 15:46:50 +10:00
Peter Steinberger
85148f3b20 refactor(cron): split notification routing 2026-04-27 06:44:53 +01:00
Peter Steinberger
4b9c85776d ci: allow package plugin metadata migrations 2026-04-27 06:42:14 +01:00
Vincent Koc
6bbb1b79e1 fix(doctor): treat gateway memory probe timeout as inconclusive (#72618) 2026-04-26 22:40:26 -07:00
Peter Steinberger
45bdfb5f72 ci(docker): keep release path at three chunks 2026-04-27 06:39:46 +01:00
Vincent Koc
60d4d5e1fa fix(daemon): reconcile macOS LaunchAgent supervision state (#72616) 2026-04-26 22:39:15 -07:00
Peter Steinberger
8c2f894d3a docs(ollama): expand setup recipes 2026-04-27 06:37:49 +01:00
Josh Avant
510718bedf fix(runtime): resolve web search SecretRefs from snapshots (#72563) 2026-04-27 00:35:21 -05:00
Peter Steinberger
332cdd7aca fix(cron): route failure alerts via target session 2026-04-27 06:34:38 +01:00
Peter Steinberger
422fa99197 fix(models): honor provider context defaults 2026-04-27 06:32:24 +01:00
Peter Steinberger
5e9a96fafb ci(docker): reuse cached e2e images for reruns 2026-04-27 06:29:09 +01:00
Peter Steinberger
679e476183 ci: always shard full Matrix QA 2026-04-27 06:28:35 +01:00
Vincent Koc
3d59e8192b fix(cli): restore help registration and descriptor graph 2026-04-26 22:26:59 -07:00
Peter Steinberger
02dae3e1d1 ci: fix telegram package acceptance harness 2026-04-27 06:26:44 +01:00
Peter Steinberger
835c6bc0c1 ci: tolerate legacy package acceptance metadata 2026-04-27 06:26:08 +01:00
Peter Steinberger
52249927ac fix(ollama): skip localhost discovery for remote providers 2026-04-27 06:24:43 +01:00
Peter Steinberger
b94ad7c9d8 fix(ollama): retry non-visible reasoning turns 2026-04-27 06:19:22 +01:00
Peter Steinberger
32b1f0ce74 ci: narrow package acceptance to artifact lanes 2026-04-27 06:17:05 +01:00
Peter Steinberger
1ea12fe3e2 fix: stage bundled plugin runtime deps safely 2026-04-27 06:16:26 +01:00
Vincent Koc
6038725501 docs: batch convert remaining prose callouts to Mintlify components
- platforms/android: blockquote Note for Android app status, Note for canvas host port
- platforms/macos: Tip component for app vs CLI discovery comparison
- plugins/zalouser, channels/zalouser: blockquote Warning components for unofficial automation risk
- channels/pairing: convert two Important paragraphs to Note components for DM-vs-group scope and silent-upgrade behavior
2026-04-26 22:15:11 -07:00
Vincent Koc
a108169127 fix(gateway): lazy-load setup wizard runtime 2026-04-26 22:12:46 -07:00
Vincent Koc
5bba899a70 docs: batch fix filler Note/page openers and one TUI auth Warning
- gateway/authentication: tighten model-provider Note opener
- help/debugging: drop 'this page covers' filler
- reference/session-management-compaction: rephrase end-to-end intro
- reference/transcript-hygiene: drop 'this document describes' filler
- web/index: collapse 'this page focuses' filler
- web/tui: convert prose --url Note to Warning component
2026-04-26 22:12:17 -07:00
Vincent Koc
9df7fe3986 docs: fix live docs callout formatting 2026-04-26 22:08:22 -07:00
Vincent Koc
5c3e2a6b44 docs: batch fix filler openings across providers, platforms, install, tools, and pi
- platforms/mac/dev-setup: sentence-case heading and direct opener
- tools/browser-wsl2-windows-remote-cdp-troubleshooting: collapse three-bullet split-host setup into one direct sentence
- install/migrating-matrix: drop 'this page covers' filler
- providers/perplexity-provider: rephrase Note opener
- pi: drop 'this document describes' filler
2026-04-26 22:07:47 -07:00
Vincent Koc
51dbda3f3d docs(automation+start): batch fix filler openings and prose Tip
- start/openclaw: workspace-as-memory Tip component
- automation/tasks: drop 'this page covers' filler in Note
- automation/auth-monitoring, clawflow, cron-vs-heartbeat: collapse 'this page moved... See X' redirects to single direct sentences
2026-04-26 22:04:56 -07:00
Peter Steinberger
488a1ee146 fix(cron): preserve silent tool results 2026-04-27 06:04:27 +01:00
Vincent Koc
a167e687ce docs: fix live docs CI 2026-04-26 22:04:16 -07:00
Peter Steinberger
2dcc4605d4 fix(llm-task): normalize provider-prefixed model overrides 2026-04-27 06:02:16 +01:00
Vincent Koc
05ebfa4146 docs(help+tools): batch convert prose callouts to Mintlify components
- testing-live: Tip components for model-discovery and authoritative-list guidance
- debugging: --dev flag Note and non-dev gateway stop Tip
- testing: narrowing live tests Tip
- tools/lobster: optional-plugin allowlist Note
- tools/acp-agents-setup: blockquote Important to Warning component
2026-04-26 22:01:55 -07:00
Peter Steinberger
86da88c120 ci: request release evidence after full validation 2026-04-27 06:01:06 +01:00
Vincent Koc
9624d81bb3 docs(install): batch convert callouts and sentence-case headings
- macos-vm: download-time Note component
- hetzner: community-maintained Note component
- exe-dev: stateful-VM Tip component
- development-channels: parallel clones Tip component
- migrating: sentence-case top heading and section headings, replace bullet -- separators with em-dashes, drop 'this guide' filler
2026-04-26 21:59:42 -07:00
Peter Steinberger
751c7f32a5 fix(cli): preserve Matrix QA profile flag 2026-04-27 05:57:37 +01:00
Vincent Koc
6c49039a23 docs(gateway): batch convert callouts and fix JSON5 smart quotes
- security/index: 3 prose callouts (Note/Warning) for remote credential rules, sandbox scope, elevated mode
- tailscale: loopback Note component
- pairing: bulleted Important warning to Warning component
- openshell: host-edit warning to Warning component
- local-models: replace 13 smart quotes inside the LM Studio JSON5 example so it parses
2026-04-26 21:56:59 -07:00
Vincent Koc
91e835ebe0 docs(concepts): batch readability and Mintlify component pass
- memory: replace en-dash list separators with em-dashes, sentence-case Further reading link titles
- messages: rewrite filler 'this page ties together' opener to a direct one
- delegate-architecture: convert 4 blockquote security warnings to Warning and Note components
- system-prompt: convert blockquote daily-memory note to Note component
2026-04-26 21:54:23 -07:00
Peter Steinberger
5d5c37775e fix(ollama): estimate usage when counters are omitted 2026-04-27 05:54:03 +01:00
Peter Steinberger
377553e41a ci: link package deps for telegram acceptance 2026-04-27 05:52:13 +01:00
Gustavo Madeira Santana
241d0cb88e chore(docs): dedupe and simplify matrix docs 2026-04-27 00:52:04 -04:00
Vincent Koc
dc8b881c11 fix(gateway): defer startup runtime imports 2026-04-26 21:50:50 -07:00
Vincent Koc
f4129cdd2b docs(channels): batch convert prose callouts to Mintlify components
- msteams: 5 callouts (Note/Warning) for preview status, devtunnel auth, group policy, multi-tenant deprecation, user-prefix targeting
- slack: replyToMode threading note
- whatsapp: dms vs direct prompt override note
- group-messages: mentionPatterns cross-channel note
- signal: signal-cli main session de-auth warning
2026-04-26 21:49:56 -07:00
Vincent Koc
6908bd3167 docs(cli): batch readability pass for 5 CLI pages
- channels: convert Tip prose to component, fix /channels/index link, sentence-case heading
- configure: convert Note and Tip prose to components
- devices: convert Note and Warning prose to components
- models: sentence-case scan/status subheadings
- agents: clean up related links and Title Case body link
2026-04-26 21:47:29 -07:00
Peter Steinberger
7564af24e6 fix(providers): preserve configured model input modalities 2026-04-27 05:46:53 +01:00
Peter Steinberger
748daa4857 ci: make package acceptance legacy-safe 2026-04-27 05:46:06 +01:00
Peter Steinberger
6987132aed ci: add Matrix QA profiles 2026-04-27 05:43:14 +01:00
Peter Steinberger
382e03a2d8 fix(cron): fail isolated runs on run-level errors 2026-04-27 05:42:59 +01:00
Peter Steinberger
390b965460 docs: document release evidence workflow 2026-04-27 05:40:21 +01:00
Vincent Koc
edbcfe1a1d docs(agents): keep testbox policy out of root rules 2026-04-26 21:39:23 -07:00
Vincent Koc
e2ecf292bc docs(doctor): document models.providers.api migration and stale-enum skip
Add the legacy `models.providers.*.api: "openai"` → `"openai-completions"`
migration to doctor's Current migrations list, and note the gateway startup
behavior that skips providers with future or unknown api enum values instead
of failing closed.

Traces to:
- 6a7980e984 fix(doctor): migrate legacy OpenAI provider api
- 147f4f50f5 fix(gateway): skip stale model provider api entries
2026-04-26 21:39:00 -07:00
Peter Steinberger
fd06aeac04 test(docker): fixture ClawHub plugin smoke 2026-04-27 05:38:27 +01:00
Vincent Koc
f83e424a5d docs: fix onboarding docs formatting 2026-04-26 21:33:58 -07:00
Vincent Koc
0eac6432c3 docs: fix docs formatting drift 2026-04-26 21:29:38 -07:00
Vincent Koc
ebbc7dcfeb docs(updating): group advanced npm topics in AccordionGroup 2026-04-26 21:29:03 -07:00
Vincent Koc
8cd68487d9 docs(remote): rename numbered headings and use Note components 2026-04-26 21:29:03 -07:00
Vincent Koc
4519b29419 docs(update): convert flow steps to Steps component 2026-04-26 21:29:02 -07:00
Vincent Koc
c881d8da48 docs(sandbox): replace bold-callout patterns with Note and Tip components 2026-04-26 21:29:02 -07:00
Vincent Koc
00300b85d0 docs(onboard): convert related-guides to CardGroup and group flow notes 2026-04-26 21:29:01 -07:00
Peter Steinberger
7c0fdae9b9 docs(providers): document local model request timeout 2026-04-27 05:27:41 +01:00
Gustavo Madeira Santana
e0956a0853 fix(cli): skip startup work for positional help 2026-04-27 00:24:06 -04:00
Vincent Koc
9c07579a95 docs(testbox): align maintainer testbox mode 2026-04-26 21:23:28 -07:00
Vincent Koc
166a6d9088 docs(feishu): convert blockquote callouts to Note components 2026-04-26 21:22:58 -07:00
Vincent Koc
5a88d8502f docs(gateway): split lifecycle notes accordion 2026-04-26 21:22:57 -07:00
Vincent Koc
4db066d102 docs(ollama): restructure auth rules and fix duplicate card titles 2026-04-26 21:22:57 -07:00
Vincent Koc
3f1ce689a1 docs(compaction): dedupe sections and consolidate config 2026-04-26 21:22:57 -07:00
Vincent Koc
d4bb4912fc docs(cron): regroup notes into themed sections 2026-04-26 21:22:56 -07:00
Peter Steinberger
02455c0c52 ci: include telegram in release package acceptance 2026-04-27 05:14:19 +01:00
Peter Steinberger
d857989111 docs: clarify package acceptance release role 2026-04-27 05:13:41 +01:00
Vincent Koc
4c3c3abe1a fix(cli): keep startup help metadata on fast path 2026-04-26 21:11:23 -07:00
Vincent Koc
716b3faf7e Revert "docs(agents): document testbox maintainer workflow"
This reverts commit 4340cb74c2.
2026-04-26 21:10:09 -07:00
Vincent Koc
3e95927df7 Merge branches 'main' and 'main' of https://github.com/openclaw/openclaw
* 'main' of https://github.com/openclaw/openclaw:
  docs: explain telegram package artifact testing
  ci: let telegram e2e use package artifacts
  docs: explain release validation entrypoints
  ci: tolerate legacy qa inventory entries
  ci(testbox): save build artifact cache before wait
  fix: allow heavyweight docker lanes at low parallelism
  test(docker): use packaged gateway expect-final smoke
  test(live): accept current Codex status text

* 'main' of https://github.com/openclaw/openclaw:
  docs: explain telegram package artifact testing
  ci: let telegram e2e use package artifacts
  docs: explain release validation entrypoints
  ci: tolerate legacy qa inventory entries
  ci(testbox): save build artifact cache before wait
  fix: allow heavyweight docker lanes at low parallelism
  test(docker): use packaged gateway expect-final smoke
  test(live): accept current Codex status text
2026-04-26 21:09:46 -07:00
Peter Steinberger
cc79f4982c docs: explain telegram package artifact testing 2026-04-27 05:09:17 +01:00
Peter Steinberger
09107e0b7f ci: let telegram e2e use package artifacts 2026-04-27 05:09:16 +01:00
Peter Steinberger
720ab99307 docs: explain release validation entrypoints 2026-04-27 05:07:22 +01:00
Peter Steinberger
0ff0c7ce57 ci: tolerate legacy qa inventory entries 2026-04-27 05:07:15 +01:00
Vincent Koc
a33a2c97a3 ci(testbox): save build artifact cache before wait 2026-04-26 21:07:02 -07:00
Vincent Koc
4cc572a813 ci(testbox): save build artifact cache before wait 2026-04-26 21:06:29 -07:00
Peter Steinberger
3c8760f16d fix: allow heavyweight docker lanes at low parallelism 2026-04-27 05:04:52 +01:00
Peter Steinberger
940f67e524 test(docker): use packaged gateway expect-final smoke 2026-04-27 05:01:36 +01:00
Vincent Koc
ef828d55af test(live): accept current Codex status text
Accept current Codex harness status prose while still requiring the OpenClaw status shape, active model, and live harness session.
2026-04-26 21:01:22 -07:00
Vincent Koc
9626ef274a ci(testbox): add build artifact cache warmup 2026-04-26 20:58:14 -07:00
Val Alexander
5e8cb77e79 Polish Control UI quick settings layout
Polish the Control UI quick settings dashboard layout.

- Rework quick settings into a 12-column desktop grid with matched top-row card heights.
- Pair Personal with a right-side Appearance/Automations stack on large screens while preserving tablet/mobile ordering.
- Add render/style guards plus an Unreleased changelog entry crediting @BunsDev.

Validated with focused UI tests, formatting, git diff checks, local changed gate, and full PR CI.
2026-04-26 22:56:35 -05:00
Val Alexander
461c10bb51 feat(onboard): support non-interactive GitHub Copilot token auth
Add manifest-owned GitHub Copilot token support for non-interactive onboarding, including documented env fallback, ref-mode tokenRef storage, saved-profile reuse, and default model wiring that preserves existing primary model configuration.

Validation:
- pnpm test extensions/github-copilot/index.test.ts src/plugins/contracts/registry.contract.test.ts src/commands/onboard-non-interactive/local/auth-choice-inference.test.ts
- pnpm check:changed
- CI green on aadac2c8d4
2026-04-26 22:56:20 -05:00
Peter Steinberger
18b76e3995 fix(ollama): scope request timeouts to providers 2026-04-27 04:55:11 +01:00
joshavant
6b6f8ab1aa Revert "fix: resolve tts secret refs for local infer (#72549)"
This reverts commit 4878d3e059.
2026-04-26 22:54:08 -05:00
Peter Steinberger
36c08e0288 test(docker): keep web search smoke on one gateway connection 2026-04-27 04:51:55 +01:00
Peter Steinberger
6590e0e872 docs: expand release validation runbook 2026-04-27 04:50:51 +01:00
Vincent Koc
4340cb74c2 docs(agents): document testbox maintainer workflow 2026-04-26 20:49:56 -07:00
Peter Steinberger
5f9506f7fd ci: avoid inherited package acceptance secrets 2026-04-27 04:44:29 +01:00
Gustavo Madeira Santana
e1cdaa3c88 docs(matrix): note E2EE setup improvements 2026-04-26 23:42:32 -04:00
Gustavo Madeira Santana
2b40416314 test(matrix): speed up CLI metadata entry test 2026-04-26 23:40:53 -04:00
Gustavo Madeira Santana
3b74b913e3 fix(matrix): avoid device cleanup sync races 2026-04-26 23:40:52 -04:00
Gustavo Madeira Santana
99159f89da fix(matrix): stabilize e2ee qa flows 2026-04-26 23:40:52 -04:00
Peter Steinberger
02d266c6c4 ci: split package acceptance refs 2026-04-27 04:39:19 +01:00
Ayaan Zaidi
34f81c6a8a docs(changelog): note model provider api recovery 2026-04-27 09:07:31 +05:30
Ayaan Zaidi
147f4f50f5 fix(gateway): skip stale model provider api entries 2026-04-27 09:07:31 +05:30
Ayaan Zaidi
6a7980e984 fix(doctor): migrate legacy OpenAI provider api 2026-04-27 09:07:31 +05:30
Vincent Koc
831f03b814 fix(cli): speed up gateway status config reads 2026-04-26 20:34:49 -07:00
Peter Steinberger
b0c70786fd fix(cron): preserve structured denial failures 2026-04-27 04:34:38 +01:00
Peter Steinberger
e6eea6cfe2 docs: clarify package acceptance npm selection 2026-04-27 04:34:13 +01:00
Peter Steinberger
67650c4c0a fix(ollama): resolve custom local provider auth 2026-04-27 04:33:18 +01:00
Vincent Koc
f60378519c test(plugins): cover bundled dependency edge cases 2026-04-26 20:31:54 -07:00
Josh Avant
4878d3e059 fix: resolve tts secret refs for local infer (#72549) 2026-04-26 22:31:39 -05:00
Peter Steinberger
6a05b9eec5 ci: fix package acceptance permissions 2026-04-27 04:27:45 +01:00
Peter Steinberger
2c092a0eff docs: document release validation test workflows 2026-04-27 04:27:07 +01:00
Peter Steinberger
76de167ca1 ci: add package acceptance workflow 2026-04-27 04:25:31 +01:00
jnuyao
2a08848dd1 feat(feishu): display group names in session labels
Resolve Feishu group chat labels through getChatInfo so session labels prefer human-readable group names over raw chat IDs.\n\nPreserve topic/thread label priority and defer the lookup until after broadcast dedup claims to avoid duplicate account API calls.\n\nValidation:\n- pnpm test extensions/feishu/src/bot-group-name.test.ts extensions/feishu/src/bot.broadcast.test.ts\n- pnpm check:changed\n- GitHub CI green on c154dc0a41fd715dce95ef1fb5d0c269533b8c22\n\nCloses #35675
2026-04-26 22:22:51 -05:00
Peter Steinberger
d3fd275aa5 test: cover gateway wrapper persistence in docker e2e 2026-04-27 04:15:33 +01:00
Peter Steinberger
6c1cffa7f8 ci: fix targeted live model provider run 2026-04-27 04:08:16 +01:00
Peter Steinberger
e0141946b2 ci: allow targeted live model providers 2026-04-27 04:04:38 +01:00
Peter Steinberger
cbbd860ef9 test(docker): isolate installer smoke sessions 2026-04-27 04:01:46 +01:00
Peter Steinberger
9bd4200f3c docs: prefer targeted test reruns 2026-04-27 04:00:05 +01:00
Peter Steinberger
a72522d05d test: prefer glm 5 in live sweeps 2026-04-27 03:56:16 +01:00
Peter Steinberger
313a19c940 fix(ollama): scope auth to local hosts 2026-04-27 03:54:12 +01:00
Peter Steinberger
29af4add2a feat: trigger compaction for oversized transcripts 2026-04-27 03:46:11 +01:00
Vincent Koc
d5063d5b16 fix(telegram): avoid materializing tool-progress drafts
Address Clownfish follow-up on Telegram native draft finalization. Requires real streamed assistant partials before materializing drafts, clears stale native draft previews, and keeps media/buttons on normal send path.
2026-04-26 19:43:23 -07:00
Peter Steinberger
6d0e84aadb test(docker): skip bootstrap ritual in install smoke 2026-04-27 03:41:47 +01:00
Peter Steinberger
ef31a333f7 docs: add gateway wrapper install examples 2026-04-27 03:40:32 +01:00
Peter Steinberger
0b3f13b337 fix: preserve wrapper env during gateway reinstall 2026-04-27 03:40:32 +01:00
Peter Steinberger
9f9bd41f40 fix: persist gateway service wrappers 2026-04-27 03:40:32 +01:00
Peter Steinberger
414fd41a1f fix(ollama): avoid timing out active model pulls 2026-04-27 03:40:28 +01:00
Peter Steinberger
8b27c489f5 test: bound openai websocket live e2e 2026-04-27 03:39:24 +01:00
Vincent Koc
f39f4629d9 docs(changelog): credit update fixture repair
Add the missing Unreleased changelog credit for the Docker update-channel fixture repair.
2026-04-26 19:38:07 -07:00
Peter Steinberger
348728c28c fix(providers): bound native fetch timeouts 2026-04-27 03:33:51 +01:00
Peter Steinberger
dc78d58448 fix(ollama): honor baseURL provider aliases 2026-04-27 03:28:23 +01:00
Vincent Koc
ae89d44760 chore(plugin-sdk): refresh api baseline 2026-04-26 19:24:37 -07:00
Vincent Koc
ead76f61d8 fix(cli): skip plugin preload for plugin updates 2026-04-26 19:24:37 -07:00
Vincent Koc
a5f6603e61 fix(release): clarify control ui build requirement 2026-04-26 19:24:37 -07:00
Vincent Koc
a313c4db92 chore(config): refresh bundled channel metadata 2026-04-26 19:24:36 -07:00
Peter Steinberger
b72c0bdfad ci: force gemini api key auth in acp bind 2026-04-27 03:23:00 +01:00
Peter Steinberger
bd42f35097 fix(ui): show configured thinking defaults 2026-04-27 03:21:49 +01:00
Peter Steinberger
90ad79cbcd test(docker): generate update fixture ui asset 2026-04-27 03:13:51 +01:00
Peter Steinberger
0b46227d6c fix(ollama): keep configured max thinking compatible 2026-04-27 03:13:15 +01:00
Peter Steinberger
1882a8e5ea fix: refresh preflight rotated runs 2026-04-27 03:12:45 +01:00
Vincent Koc
f5f4f514d8 docs(changelog): backfill gateway memory fixes 2026-04-26 19:11:13 -07:00
Vincent Koc
0c30d0d0b8 fix(gateway): resolve configured thinking default in session rows (#72324)
* fix(gateway): resolve configured thinking default in session rows

* fix(gateway): preserve model thinking precedence
2026-04-26 19:10:21 -07:00
Peter Steinberger
de0ece20d1 test: accept live release validation variance 2026-04-27 03:08:29 +01:00
Peter Steinberger
aa071e0b60 fix(ollama): forward native model params 2026-04-27 03:08:11 +01:00
Peter Steinberger
f4cf7e3b4f test(docker): recreate update fixture ui asset after install 2026-04-27 03:06:07 +01:00
Peter Steinberger
2dba9e6a76 fix(ollama): honor configured num_ctx params 2026-04-27 03:02:24 +01:00
Peter Steinberger
fc3abc139b fix(cron): classify denied isolated runs 2026-04-27 03:01:55 +01:00
Peter Steinberger
22c9e82e83 test(docker): track update fixture control ui asset 2026-04-27 02:58:24 +01:00
Vincent Koc
8c2bc951a9 fix(plugins): hydrate bundled channel config metadata
Hydrate bundled channel schema metadata through opt-in registry schema paths while keeping ordinary manifest registry loads lightweight.
2026-04-26 18:58:04 -07:00
Peter Steinberger
c45a7d7a7a ci: use available macOS release runner 2026-04-27 02:56:19 +01:00
Vincent Koc
b96a75c95b fix(gateway): scope memory runtime plugin loading 2026-04-26 18:54:59 -07:00
Peter Steinberger
20b71e18b2 test(docker): seed update fixture control ui asset 2026-04-27 02:50:48 +01:00
Peter Steinberger
9b79eef750 fix(memory-core): honor configured index concurrency 2026-04-27 02:47:39 +01:00
Vincent Koc
988cb1ebfe fix(test): stabilize restart sentinel mocks 2026-04-26 18:45:13 -07:00
Vincent Koc
3e020a1650 fix(memory-lancedb): force float embedding encoding (#72391) 2026-04-27 02:43:31 +01:00
Peter Steinberger
5176dba8a0 test(docker): stub update fixture lint preflight 2026-04-27 02:43:15 +01:00
Peter Steinberger
d8c1140235 ci: fix full release validation gh repo context 2026-04-27 02:36:20 +01:00
Peter Steinberger
69daef8246 fix: honor Ollama Modelfile num_ctx discovery 2026-04-27 02:32:30 +01:00
Shadow
3f59cd0a09 Adjust message for stale workflow 2026-04-26 20:31:00 -05:00
pashpashpash
90de4bd855 fix: address successor transcript review follow-ups
Fixes the post-merge review follow-ups from #72471 by deduping stale pre-compaction state entries and preserving parent-before-child ordering for successor transcripts.
2026-04-26 18:27:38 -07:00
Vincent Koc
6a5ecb955c refactor(plugins): drop provider discovery alias 2026-04-26 18:19:05 -07:00
Vincent Koc
eed7b13b62 fix(doctor): scope bundled runtime deps to active plugins 2026-04-26 18:17:56 -07:00
Peter Steinberger
efec8a4a84 docs: note Vitest cache race footgun 2026-04-27 02:17:02 +01:00
Peter Steinberger
bf08dc2ed6 test(docker): fix packaged docker harness lanes 2026-04-27 02:13:56 +01:00
Peter Steinberger
110fa97f2a fix: repair release validation follow-up checks 2026-04-27 02:09:40 +01:00
Peter Steinberger
8c18df02f3 docs: update Ollama fix changelog 2026-04-27 02:08:01 +01:00
Peter Steinberger
e28ad0f84f fix: list configured provider models 2026-04-27 02:08:01 +01:00
Peter Steinberger
c6617c3155 fix: silence Ollama memory doctor key warning 2026-04-27 02:08:00 +01:00
Peter Steinberger
1316ca9aa8 fix: gate Ollama ambient discovery 2026-04-27 02:08:00 +01:00
Peter Steinberger
acfa9877b3 fix: parse Ollama tool call arguments 2026-04-27 02:07:59 +01:00
Peter Steinberger
6a20c83cf7 docs: clarify Ollama web search auth 2026-04-27 02:07:59 +01:00
Peter Steinberger
f0b758fba2 test(docker): stub package-derived update fixture builds 2026-04-27 02:07:29 +01:00
pashpashpash
b99540964c Fix compaction rotation follow-ups 2026-04-26 18:06:57 -07:00
Vincent Koc
b9c7a4306b fix(ci): declare Lobster Ajv runtime dependency 2026-04-26 18:04:46 -07:00
Peter Steinberger
658240de74 ci: add full release validation workflow 2026-04-27 02:02:34 +01:00
Vincent Koc
67d00826b2 fix(gateway): bound Lobster Ajv schema compilation 2026-04-26 17:57:59 -07:00
Peter Steinberger
3c95327b34 Fix compacted session transcript rotation 2026-04-26 17:51:00 -07:00
Vincent Koc
0a117b5960 test(plugins): guard persisted status replay 2026-04-26 17:47:41 -07:00
Peter Steinberger
ddac6f73e5 fix(approvals): accept allowlist metadata 2026-04-27 01:46:30 +01:00
Peter Steinberger
ffbb4d4ae7 test(docker): fix update preflight fixture patches 2026-04-27 01:43:55 +01:00
Peter Steinberger
3937d16c44 fix(exec): fallback when node lacks run prepare 2026-04-27 01:43:03 +01:00
Peter Steinberger
b109c1f99c ci: limit node 22 compatibility to manual ci 2026-04-27 01:39:32 +01:00
Peter Steinberger
92c1924d27 ci: remove duplicate extension fast lane 2026-04-27 01:36:45 +01:00
Peter Steinberger
acd1bd7d31 fix(exec): skip node approval prepare in yolo mode 2026-04-27 01:27:58 +01:00
Peter Steinberger
11e17793e1 ci: include node22 compat in manual full ci 2026-04-27 01:27:27 +01:00
Peter Steinberger
90b3cdb6a7 test(docker): fix update fixture pnpm patch config 2026-04-27 01:25:00 +01:00
Peter Steinberger
7ca2f9fed5 test(docker): align package harness image 2026-04-27 01:22:58 +01:00
Vincent Koc
732a5842ee fix(gateway): defer implicit qmd memory startup 2026-04-26 17:21:50 -07:00
Vincent Koc
d7c173b694 fix(gateway): harden macOS launchd service startup 2026-04-26 17:18:49 -07:00
Peter Steinberger
6fed787297 test: align release boundary expectations 2026-04-27 01:16:15 +01:00
Vincent Koc
7cecbe1002 test(plugins): guard cold status snapshots
Add a reusable cold plugin fixture and status snapshot guard proving read-only plugin metadata paths do not import plugin runtime entries.
2026-04-26 17:15:39 -07:00
Peter Steinberger
0f672dcc73 fix(ollama): align web search endpoint routing 2026-04-27 01:10:41 +01:00
Peter Steinberger
b825c8d34b test: fix full ci suite follow-ups 2026-04-27 01:10:32 +01:00
Peter Steinberger
3b514ad5f3 test(docker): run mounted harnesses with image tsx 2026-04-27 01:05:20 +01:00
Peter Steinberger
82b928232e test(docker): stabilize package update lanes 2026-04-27 01:02:36 +01:00
Peter Steinberger
30d9e70988 test(gateway): stabilize session cleanup gates 2026-04-27 01:02:13 +01:00
Peter Steinberger
a3e0674261 fix(ollama): harden native provider routing 2026-04-27 01:02:13 +01:00
Peter Steinberger
be56f172ab fix: scope qmd root memory collection 2026-04-27 01:01:58 +01:00
Peter Steinberger
d2786fb969 test(docker): run observability harness with global tsx 2026-04-27 00:57:55 +01:00
Peter Steinberger
fa0729e145 test: auto-discover vitest suites 2026-04-27 00:55:06 +01:00
Peter Steinberger
21c51bc140 test(docker): resolve otel decoder from plugin runtime 2026-04-27 00:51:47 +01:00
Vincent Koc
265bc6b6ea test(plugins): guard command cold registry paths
Add command-level sentinel coverage proving channel setup metadata, onboarding auth choices, and models-list provider ownership stay on manifest/registry paths without importing plugin runtime.\n\nLocal verification:\n- pnpm exec oxfmt --check --threads=1 src/commands/plugin-control-plane-cold-imports.test.ts\n- OPENCLAW_LOCAL_CHECK_MODE=throttled pnpm test:serial src/commands/plugin-control-plane-cold-imports.test.ts\n- OPENCLAW_LOCAL_CHECK_MODE=throttled pnpm check:changed\n- clean rebase sanity: git diff --check origin/main...HEAD\n\nPR CI had known unrelated main-red failures matching latest main run 24970053892; the new sentinel test passed in CI.
2026-04-26 16:51:36 -07:00
Peter Steinberger
42db865673 test(docker): run observability on shared image 2026-04-27 00:49:36 +01:00
Vincent Koc
5d7c6e6bda test(docker): add observability smoke
Add Docker aggregate observability coverage for QA-lab OTEL and Prometheus diagnostics.
2026-04-26 16:43:56 -07:00
Tak Hoffman
560ddd2f9b Fail package update on unhealthy restart (#72422) 2026-04-26 18:38:23 -05:00
Peter Steinberger
998e37fcb3 ci: allow installer smoke baseline override 2026-04-27 00:31:30 +01:00
Vincent Koc
3cc52d9050 docs(changelog): note codex usage accounting fix 2026-04-26 16:27:23 -07:00
Vincent Koc
7902c769da fix(codex): normalize cached harness input tokens 2026-04-26 16:27:23 -07:00
Peter Steinberger
9be8d43c31 docs: document installer recovery cleanup 2026-04-27 00:26:02 +01:00
Peter Steinberger
eccb79db99 build: remove private QA package compat shims 2026-04-27 00:26:02 +01:00
Peter Steinberger
09a635a28b test: fix main release validation forward-port 2026-04-27 00:07:31 +01:00
Peter Steinberger
5b257cb352 test(qa): drop brittle telegram workflow assertions
(cherry picked from commit b02fdb8264)
2026-04-27 00:07:31 +01:00
Peter Steinberger
efe940e9cb ci(qa): remove telegram beta approval gate
(cherry picked from commit 5e04b0f97a)
2026-04-27 00:07:31 +01:00
Peter Steinberger
8d909ed0da ci(docker): pass beta env to installer e2e
(cherry picked from commit 7677b4ca24)
2026-04-27 00:07:31 +01:00
Peter Steinberger
1bb46ce68a ci(docker): test release installer against beta
(cherry picked from commit d8c4dcb6a4)
2026-04-27 00:07:31 +01:00
Peter Steinberger
54e77a9ec4 ci(docker): use resolved pnpm for scheduled lanes
(cherry picked from commit 61a539a1b7)
2026-04-27 00:07:31 +01:00
Peter Steinberger
43e651db9a ci(docker): preserve pnpm path in scheduler lanes
(cherry picked from commit 2e8a089836)
2026-04-27 00:07:31 +01:00
Peter Steinberger
e7d069edcf test(qa): relax telegram mention reply assertion
(cherry picked from commit 7109251318)
2026-04-27 00:07:31 +01:00
Peter Steinberger
17094640f8 ci(release): trust release branch docker checks
(cherry picked from commit abf0ef9cd3)
2026-04-27 00:07:31 +01:00
Peter Steinberger
16c6a92c53 ci(release): allow npm telegram e2e from release branch
(cherry picked from commit 53f8e9de13)
2026-04-27 00:07:31 +01:00
Peter Steinberger
ef3309a986 fix(release): harden beta validation lanes
(cherry picked from commit 218bceaa14)
2026-04-27 00:07:31 +01:00
Peter Steinberger
95ae3c00bd docs: explain test routing model 2026-04-27 00:05:27 +01:00
Vincent Koc
97e64196a0 fix(hooks): use local timezone for session-memory filenames (#72408) 2026-04-26 16:04:10 -07:00
Peter Steinberger
41ad03dda4 fix(test): allow legacy qa inventory entry 2026-04-27 00:02:33 +01:00
Peter Steinberger
4a578740a2 refactor: deduplicate changed lane detection 2026-04-27 00:02:00 +01:00
Peter Steinberger
20d6daaeaa docs: document automatic bonjour container policy 2026-04-27 00:00:22 +01:00
Peter Steinberger
6018f29dbf ci: keep docker bonjour setting automatic 2026-04-27 00:00:22 +01:00
Peter Steinberger
989cfd1e33 fix(bonjour): auto-disable advertising in containers 2026-04-27 00:00:22 +01:00
Peter Steinberger
89ab39ca64 test: simplify changed test routing 2026-04-26 23:58:13 +01:00
Peter Steinberger
199d5f765f docs(test): explain cheap docker reruns 2026-04-26 23:56:14 +01:00
Peter Steinberger
2fe11020d2 refactor(test): split bundled channel docker scenarios 2026-04-26 23:56:14 +01:00
Peter Steinberger
1ddf6b4e39 ci: skip existing docker e2e images 2026-04-26 23:56:14 +01:00
Peter Steinberger
1a02d00eb4 test: add docker e2e rerun helpers 2026-04-26 23:56:14 +01:00
Peter Steinberger
cfe58387a7 docs: update changelog attribution guidance 2026-04-26 23:51:51 +01:00
Peter Steinberger
6077941d0b fix: restart package updates through updated install 2026-04-26 23:51:51 +01:00
Peter Steinberger
b5714b90ed refactor(test): share docker e2e shell helpers 2026-04-26 23:48:32 +01:00
Peter Steinberger
7a86448a6e ci: reuse docker e2e plan action 2026-04-26 23:48:32 +01:00
Peter Steinberger
6cba12caae test: add docker e2e planner guards 2026-04-26 23:48:32 +01:00
Rubén Cuevas
a08b65a90a fix(telegram): send fresh finals for stale previews (#72038)
* fix(telegram): send fresh finals for stale previews

* test(telegram): cover stale preview send fallback

* fix(telegram): keep stale archived preview fallback

* fix(telegram): clear stale active previews

* fix(telegram): reset preview state after fresh finals
2026-04-26 15:44:30 -07:00
Peter Steinberger
084dde89fd docs: clarify extension ownership boundaries 2026-04-26 23:39:18 +01:00
Peter Steinberger
2efc4a8233 docs(test): document docker e2e layout 2026-04-26 23:36:31 +01:00
Peter Steinberger
cd417f3b68 ci: derive docker e2e artifacts from plan 2026-04-26 23:36:31 +01:00
Peter Steinberger
a2adb05f74 refactor(test): split docker e2e planner 2026-04-26 23:36:31 +01:00
Peter Steinberger
c9c0ab3a44 fix(bonjour): keep ciao failure handling extension-owned 2026-04-26 23:29:40 +01:00
Peter Steinberger
0472b6197a chore: clarify bonjour fatal guard naming 2026-04-26 23:27:35 +01:00
Peter Steinberger
8a60e57846 fix: keep bonjour failures non-fatal 2026-04-26 23:27:08 +01:00
Vincent Koc
c6cf37068c fix(feishu): repair interactive card content extraction (#72397) 2026-04-26 15:26:53 -07:00
Peter Steinberger
ff6044f441 docs(changelog): note Ollama thinking validation fix 2026-04-26 23:25:05 +01:00
Peter Steinberger
5aa3779d8c ci: disable bonjour in install e2e docker 2026-04-26 23:20:08 +01:00
Peter Steinberger
ff9fefb79b fix(agents): validate thinking with model catalog 2026-04-26 23:16:05 +01:00
Peter Steinberger
3746e5b969 ci: cap Telegram E2E build cache 2026-04-26 23:11:21 +01:00
Peter Steinberger
9f5bc5465c style: format codex and loader tests 2026-04-26 23:10:33 +01:00
Peter Steinberger
d108110a89 ci: use packaged tarball for docker e2e 2026-04-26 23:10:33 +01:00
Peter Steinberger
1b1eea238c ci: preserve docker test runner path 2026-04-26 23:04:21 +01:00
Vincent Koc
d9e9e61e77 fix(logging): skip unserializable file log message parts 2026-04-26 15:01:19 -07:00
Vincent Koc
fc0e6e4650 docs(logging): document structured file fields 2026-04-26 15:01:19 -07:00
Vincent Koc
e8df081a1f feat(logging): add file log correlation fields 2026-04-26 15:01:19 -07:00
github-actions[bot]
5c4c33c7de chore(ui): refresh th control ui locale 2026-04-26 22:01:03 +00:00
Vincent Koc
070b55f336 UI: localize command palette labels (#72378) 2026-04-26 14:58:16 -07:00
Vincent Koc
364d49889e fix: allow trusted exec approvals home symlinks (#72377) 2026-04-26 14:57:01 -07:00
Peter Steinberger
baaad52389 ci: split docker e2e images 2026-04-26 22:55:00 +01:00
Peter Steinberger
3a8961af0f test: copy docker build helper in setup e2e 2026-04-26 22:54:27 +01:00
Peter Steinberger
ff570f3a61 fix(ollama): expose native thinking efforts 2026-04-26 22:49:13 +01:00
Peter Steinberger
2cd23957c0 build: use slim docker runtime 2026-04-26 22:47:48 +01:00
Vincent Koc
43a003b8a0 fix: short-circuit live model switch fallback redirects (#72375) 2026-04-26 14:45:02 -07:00
Vincent Koc
fa85e6c26e docs(changelog): note acp stdout fix 2026-04-26 14:42:37 -07:00
Vincent Koc
d46de6cff7 fix(acp): keep server logs off stdout 2026-04-26 14:42:22 -07:00
Peter Steinberger
018f2e78ba build: skip docker apt upgrades 2026-04-26 22:40:44 +01:00
Peter Steinberger
b61954919c ci: verify docker release attestations 2026-04-26 22:40:44 +01:00
Peter Steinberger
5abb717112 docs: add OpenClaw testing skill 2026-04-26 22:40:32 +01:00
Vincent Koc
8226238765 refactor(plugins): share lookup cache eviction 2026-04-26 14:28:15 -07:00
Peter Steinberger
b68b4b9151 ci: add targeted docker lane reruns 2026-04-26 22:27:45 +01:00
Josh Lehman
a3c51f91c5 fix: isolate cron context-engine session keys (#72292) 2026-04-26 14:21:01 -07:00
Vincent Koc
2edbdc42ae refactor(plugins): isolate loader cache state 2026-04-26 14:16:35 -07:00
Peter Steinberger
b28de9a7d9 ci: centralize docker build wrapper 2026-04-26 22:14:36 +01:00
Peter Steinberger
824c3e2b71 ci: enable docker image attestations 2026-04-26 22:14:36 +01:00
Vincent Koc
2194a8c64c docs(logging): document request trace scopes 2026-04-26 14:13:15 -07:00
Vincent Koc
410783c126 fix(diagnostics): chain run traces to request scope 2026-04-26 14:13:15 -07:00
Vincent Koc
3ae6f01d61 feat(logging): propagate request trace scopes 2026-04-26 14:13:14 -07:00
Peter Steinberger
e3cbad4fb6 ci: fix ACPX Docker update repair target 2026-04-26 22:13:00 +01:00
Peter Steinberger
c082cf892a docs: codify formatter tooling 2026-04-26 22:02:31 +01:00
Peter Steinberger
b4a9ac3516 ci: run release Docker chunks through scheduler 2026-04-26 22:02:31 +01:00
Vincent Koc
f0566e410a docs(diagnostics): document model call size timing 2026-04-26 13:43:22 -07:00
Vincent Koc
c6e9849351 feat(diagnostics): capture model call size timing 2026-04-26 13:43:22 -07:00
Vincent Koc
8e1755928c refactor(plugins): split plugin registry facade 2026-04-26 13:43:22 -07:00
Vincent Koc
9eb071c3f1 perf(plugins): reuse persisted registry fallback read 2026-04-26 13:43:22 -07:00
Vincent Koc
522eedc754 refactor(plugins): make provider discovery runtime explicit 2026-04-26 13:43:21 -07:00
Vincent Koc
71e361af8a refactor(plugins): split installed plugin index modules 2026-04-26 13:43:21 -07:00
Peter Steinberger
487f8c5d3a test(gateway): skip codex acp bind when auth is unavailable 2026-04-26 21:42:49 +01:00
Peter Steinberger
7a4574376a fix(ollama): honor native model capabilities 2026-04-26 21:40:22 +01:00
Josh Lehman
8ba82534e6 fix: preserve cron telegram topic delivery after timeout (#72317) 2026-04-26 13:30:54 -07:00
Peter Steinberger
ffa84cdc02 ci: chunk release Docker e2e jobs 2026-04-26 21:23:08 +01:00
pash-openai
67ffa3df8b Add Codex Computer Use setup for Codex mode (#71842)
* Add Codex Computer Use setup

* Tighten Codex Computer Use setup checks

* Handle fresh Codex Computer Use marketplace setup

* Fix channel setup manifest fixture

* Match Codex Computer Use marketplace loading

* Harden plugin manifest test fixtures

* Isolate auth choice legacy manifest test

* Update aggregate shard test expectation

* Improve Codex Computer Use first-run setup

* Harden Codex Computer Use auto-install

* Fix plugin auto-enable test fixture roots
2026-04-26 13:21:56 -07:00
Vincent Koc
df542f75a9 fix(logging): expose trace fields in file logs 2026-04-26 12:52:04 -07:00
Peter Steinberger
edf40ab6c9 test(gateway): retry gemini acp startup warmup timeout 2026-04-26 20:50:06 +01:00
Vincent Koc
406ae72fd2 fix(logging): redact persisted transcript text 2026-04-26 12:12:44 -07:00
Peter Steinberger
f99fb2af86 test(gateway): wait longer for codex harness subagent start 2026-04-26 20:11:16 +01:00
Peter Steinberger
244628f467 docs: clarify PR triage comments 2026-04-26 19:48:22 +01:00
Sally O'Malley
637bd33e69 fix(diagnostics): defer OTEL run span finalization (#72260) 2026-04-26 11:29:05 -07:00
Vincent Koc
e53c068d78 fix: repair skills and memory watcher refresh paths 2026-04-26 11:21:21 -07:00
Peter Steinberger
4e181d30fa test(gateway): classify stream fallback as empty live response 2026-04-26 19:15:00 +01:00
Peter Steinberger
e60cc50dff test(gateway): harden acp bind docker smoke 2026-04-26 19:14:58 +01:00
Peter Steinberger
f2dab9b334 fix(agents): keep responses web search reasoning compatible 2026-04-26 19:14:55 +01:00
Peter Steinberger
fc6cfbd418 fix(agents): honor bundle mcp tool allowlist 2026-04-26 19:14:51 +01:00
Vincent Koc
480a3f66c9 fix: shortcut live session model redirects during fallback 2026-04-26 11:14:05 -07:00
Vincent Koc
19e41a1e69 docs(logging): clarify redaction surfaces 2026-04-26 11:09:56 -07:00
Vincent Koc
b4cdd55f62 fix(discord): escalate repeated health-monitor restarts 2026-04-26 11:09:03 -07:00
Vincent Koc
6b6dcafcee fix(webchat): support non-image file attachments 2026-04-26 10:58:24 -07:00
Vincent Koc
303cde8f60 fix(auto-reply): poison inbound dedupe after partial turn failure
* fix(auto-reply): poison inbound dedupe after replay-unsafe failures

* fix(clownfish): address review for ghcrawl-165980-agentic-merge (1)
2026-04-26 10:58:19 -07:00
Vincent Koc
e672b61417 fix(whatsapp): stop reconnecting quiet sockets
Fixes #70678.\n\nKeeps quiet but healthy WhatsApp linked-device sessions connected by tracking WhatsApp Web transport activity, while retaining a longer app-silence cap so frame activity cannot mask a stuck session forever. Also cleans up transport activity listeners on failed connection-open paths.\n\nCarries forward the focused #71466 approach and keeps #63939 as related configurable-timeout follow-up. Thanks @vincentkoc and @oromeis.\n\nValidation:\n- pnpm test:serial extensions/whatsapp/src/auto-reply.web-auto-reply.connection-and-logging.e2e.test.ts extensions/whatsapp/src/connection-controller.test.ts\n- pnpm check:changed\n- codex review --base origin/main
2026-04-26 09:51:41 -07:00
Peter Steinberger
4a3030df9e fix: avoid PowerShell error variable collision 2026-04-26 16:26:31 +01:00
Peter Steinberger
30aa1b5223 fix(release): stabilize beta validation lanes 2026-04-26 16:22:12 +01:00
Peter Steinberger
b438a9cc08 test: align Parallels smoke guards 2026-04-26 16:20:58 +01:00
Peter Steinberger
a87edd732d fix: harden Windows Parallels smoke 2026-04-26 16:13:13 +01:00
Peter Steinberger
79ad635515 fix: pass Linux clock sync as epoch 2026-04-26 16:13:13 +01:00
Peter Steinberger
7e51866d23 fix: sync Parallels Linux clock 2026-04-26 16:13:13 +01:00
Peter Steinberger
73affb491a fix: bound dev update cleanup 2026-04-26 16:13:13 +01:00
Peter Steinberger
ddc2036956 fix: stabilize Parallels plugin smoke paths 2026-04-26 16:13:13 +01:00
Peter Steinberger
631552c554 perf: speed up dispatch-from-config tests 2026-04-26 14:14:12 +01:00
Peter Steinberger
dce35b90fe test(release): wait longer for dashboard smoke 2026-04-26 13:53:59 +01:00
Peter Steinberger
fc666cf42a test(qa): allow slower gateway rpc startup retries 2026-04-26 13:51:40 +01:00
Peter Steinberger
67b9167b80 test(extensions): restore transformed dynamic imports 2026-04-26 13:16:05 +01:00
Peter Steinberger
e97bd70264 perf: speed up slow test imports 2026-04-26 13:10:57 +01:00
Peter Steinberger
9089e6b595 fix(cli): keep channel add plugin install noninteractive
# Conflicts:
#	CHANGELOG.md
2026-04-26 12:59:19 +01:00
Peter Steinberger
7e13f3f514 test(plugin-sdk): tighten channel runtime shim scan 2026-04-26 12:17:49 +01:00
Peter Steinberger
760a1525fb docs(plugin-sdk): refresh api baseline 2026-04-26 12:15:14 +01:00
Peter Steinberger
760dd98ddc fix(ci): repair main type and lint failures 2026-04-26 12:09:35 +01:00
Peter Steinberger
ecf71da888 fix(voice-call): avoid duplicate webhook logs 2026-04-26 12:05:34 +01:00
Vincent Koc
8a63c898c8 Merge branch 'main' of https://github.com/openclaw/openclaw
* 'main' of https://github.com/openclaw/openclaw:
  fix(plugins): satisfy doctor compat lint
  chore(plugins): inventory doctor deprecation compat
  fix(plugins): record crabpot compat deprecations
  docs(dreaming): rewrite with AccordionGroup for phases and backfill, Tabs for quick start and CLI workflow, ParamField for dreaming defaults
2026-04-26 04:05:11 -07:00
Vincent Koc
efaa66f70d fix(plugins): satisfy doctor compat lint 2026-04-26 04:04:27 -07:00
Vincent Koc
4c40cf8783 chore(plugins): inventory doctor deprecation compat 2026-04-26 04:04:26 -07:00
Vincent Koc
6dfb03ab2e fix(plugins): record crabpot compat deprecations 2026-04-26 04:04:26 -07:00
Vincent Koc
3a54bbb617 fix(plugins): persist synthetic auth refs in index 2026-04-26 04:04:11 -07:00
Vincent Koc
2a5d3ad5b9 docs(dreaming): rewrite with AccordionGroup for phases and backfill, Tabs for quick start and CLI workflow, ParamField for dreaming defaults 2026-04-26 04:04:09 -07:00
Peter Steinberger
a97ee5c1d3 fix(google-meet): recover local chrome tabs 2026-04-26 12:04:00 +01:00
Vincent Koc
647e557869 docs(agent-workspace): rewrite with AccordionGroup for file map, Steps and Tabs for git backup, Warning callouts for sandbox and secret risks 2026-04-26 04:03:00 -07:00
Peter Steinberger
2a26c96000 docs(release): refine beta validation guidance 2026-04-26 12:02:26 +01:00
Vincent Koc
fa4bd05a3a docs(models): rewrite with CardGroup, Steps for selection order, AccordionGroup for picker behavior and merge precedence, ParamField for list/scan flags 2026-04-26 04:01:42 -07:00
Vincent Koc
209522e2e0 docs(model-failover): rewrite with Steps for runtime flow and rotation, AccordionGroup for cooldown buckets and chain rules, Tabs for which errors advance fallback 2026-04-26 03:59:53 -07:00
Vincent Koc
652e8af81e docs(multi-agent): rewrite with Steps for routing tiers, Tabs for common patterns, AccordionGroup for platform examples and tie-breaking 2026-04-26 03:57:19 -07:00
Vincent Koc
c7a0d9b188 Merge branch 'main' of https://github.com/openclaw/openclaw
* 'main' of https://github.com/openclaw/openclaw:
  test(models): stabilize provider index list mocks
  test(cli): cover lazy plugin inspect mocks
  fix(cli): lazy load plugin maintenance paths
  fix(models): keep cold catalog lookup registry indexed
  fix(models): avoid registry for configured list
  fix(cli): lazy load model commands
  fix(ui): remove ineffective dynamic imports
  test: type setup provider mocks
  fix(update): complete channel switch follow-up work
  test(parallels): harden smoke agent model setup
  fix: preserve provider-scoped model options
  fix: keep post-auth model policy cold
  docs: note faster onboarding auth setup
  test: cover setup provider auth selection
  refactor: keep openai setup auth lightweight
  fix: use setup providers for auth choices
  fix: scope provider auth runtime loading
  fix: keep onboarding setup paths cold
  fix: keep onboarding model prompts scoped
2026-04-26 03:51:08 -07:00
Vincent Koc
3013916232 Update docker.md 2026-04-26 03:50:31 -07:00
Vincent Koc
5411f9d217 test(models): stabilize provider index list mocks 2026-04-26 03:49:57 -07:00
Vincent Koc
be388084c2 test(cli): cover lazy plugin inspect mocks 2026-04-26 03:49:57 -07:00
Vincent Koc
e76bac5d14 fix(cli): lazy load plugin maintenance paths 2026-04-26 03:49:56 -07:00
Vincent Koc
aec1bfa0bb fix(models): keep cold catalog lookup registry indexed 2026-04-26 03:49:43 -07:00
Vincent Koc
8740ca7dee fix(models): avoid registry for configured list 2026-04-26 03:49:43 -07:00
Vincent Koc
23710167cd fix(cli): lazy load model commands 2026-04-26 03:49:43 -07:00
Vincent Koc
3a9463edac test(models): stabilize provider index list mocks 2026-04-26 03:47:25 -07:00
Vincent Koc
fc483ef5d0 test(cli): cover lazy plugin inspect mocks 2026-04-26 03:47:24 -07:00
Vincent Koc
38ea99ec74 fix(cli): lazy load plugin maintenance paths 2026-04-26 03:47:23 -07:00
Vincent Koc
9c25c697dd fix(models): keep cold catalog lookup registry indexed 2026-04-26 03:45:46 -07:00
Vincent Koc
b7533f5112 fix(models): avoid registry for configured list 2026-04-26 03:45:45 -07:00
Vincent Koc
c3a81166fc fix(cli): lazy load model commands 2026-04-26 03:45:45 -07:00
Peter Steinberger
ab0d0f677b fix(ui): remove ineffective dynamic imports
(cherry picked from commit b4ff947206)
2026-04-26 11:45:29 +01:00
Peter Steinberger
06fe67d719 test: type setup provider mocks
(cherry picked from commit ea9da71f03)
2026-04-26 11:41:14 +01:00
Peter Steinberger
6a00be5f90 fix(update): complete channel switch follow-up work 2026-04-26 11:38:44 +01:00
Peter Steinberger
cd8187d7ce test(parallels): harden smoke agent model setup 2026-04-26 11:38:33 +01:00
Shakker
8344fae387 fix: preserve provider-scoped model options 2026-04-26 11:36:32 +01:00
Shakker
3fe0718932 fix: keep post-auth model policy cold 2026-04-26 11:36:32 +01:00
Shakker
cd3b871122 docs: note faster onboarding auth setup 2026-04-26 11:36:32 +01:00
Shakker
edcb2326a1 test: cover setup provider auth selection 2026-04-26 11:36:32 +01:00
Shakker
b11dbb49f9 refactor: keep openai setup auth lightweight 2026-04-26 11:36:32 +01:00
Shakker
44183de706 fix: use setup providers for auth choices 2026-04-26 11:36:32 +01:00
Shakker
3fffa78164 fix: scope provider auth runtime loading 2026-04-26 11:36:32 +01:00
Shakker
2f81c5f580 fix: keep onboarding setup paths cold 2026-04-26 11:36:32 +01:00
Shakker
26b203e573 fix: keep onboarding model prompts scoped 2026-04-26 11:36:32 +01:00
Peter Steinberger
c74fb78194 test: harden cron MCP Docker smoke 2026-04-26 11:33:26 +01:00
Peter Steinberger
cd79e01be3 fix: load default memory plugin at startup 2026-04-26 11:32:58 +01:00
Peter Steinberger
0e490a3c26 fix(plugins): serialize bundled runtime mirrors 2026-04-26 11:32:07 +01:00
Peter Steinberger
4506bb2e02 fix: stabilize channel MCP Docker smoke 2026-04-26 11:31:25 +01:00
Peter Steinberger
74a4ff1adc fix: prefer mounted bundled plugin sources 2026-04-26 11:28:41 +01:00
Peter Steinberger
8a52c7b3d9 test: cover ClawHub plugin install uninstall 2026-04-26 11:28:18 +01:00
Peter Steinberger
3979fce4f9 test: satisfy compat registry lint 2026-04-26 11:28:07 +01:00
Peter Steinberger
8f4f33be78 test: keep compat registry guard-safe 2026-04-26 11:25:02 +01:00
Peter Steinberger
46d74c8f09 docs: update changelog for native require loader (#71122) (thanks @Effet) 2026-04-26 11:23:42 +01:00
Effet
75c9b216e5 fixup! perf(plugins): native-require fast path respects tryNative=false
Review feedback from @chatgpt-codex-connector (P1): callers that pass
`tryNative: false` rely on jiti's alias rewriting (e.g.
`bundled-capability-runtime` in Vitest+dist mode narrows the SDK
slice through shim aliases). Route everything through the jiti
loader when `tryNative` is false so those rewrites still apply.

Review feedback from @greptile-apps (P2): forward the full argument
tuple through to the jiti fallback with `...rest` so any future
loader option argument is not silently dropped by the wrapper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 11:23:42 +01:00
Effet
b40b85c21a perf(plugins): use native require for compiled JS before jiti
Every CLI invocation reads the config snapshot, which pulls bundled
channel doctor contracts and setup surfaces through
`getCachedPluginJitiLoader`. jiti's TS→JS transform pipeline adds
several seconds of per-load overhead on slower hosts (NAS profiling
shows ~78% of `openclaw config get` wall time spent inside the jiti
library), and that overhead is pure waste for the already-compiled
`.js` artifacts shipped in dist/.

Wrap the loader returned by `getCachedPluginJitiLoader` so that
compiled JS targets go through `tryNativeRequireJavaScriptModule`
first. Jiti stays on the hot path for:
- TS/TSX/MTS/CTS sources
- paths the native-require helper declines (Windows by default, or
  module-resolution fallbacks)

This centralises the fast path that already existed — inside
`doctor-contract-registry` and `channel-entry-contract` — and extends
it to every caller that goes through the jiti loader cache.

Benchmark on a modest NAS (Node 22.22, ZFS, telegram + discord
configured):

| command          | before | after |
|------------------|-------:|------:|
| config get X     |    24s |    6s |
| status           |    45s |   18s |
| devices list     |    55s |   26s |
| nodes status     |    55s |   26s |

Fixes the slow config/status/devices/nodes read paths reported in
openclaw#62842. Remaining time is dominated by non-jiti code paths
(config schema validation, eager provider-plugin module eval) that
are out of scope for this patch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 11:23:42 +01:00
Vincent Koc
6d60b035b4 chore(plugins): finish compat registry cleanup 2026-04-26 03:17:25 -07:00
Peter Steinberger
bc49fb1cdf test: fix extension dynamic imports 2026-04-26 11:15:45 +01:00
Peter Steinberger
9694c0611c ci: fix main gate 2026-04-26 11:15:45 +01:00
Peter Steinberger
4b2056fcc1 docs: document plugin package entrypoints 2026-04-26 11:12:09 +01:00
Peter Steinberger
a75c3adc4f refactor: centralize plugin update outcome logging 2026-04-26 11:11:58 +01:00
Peter Steinberger
b7404399ef perf: cache bundled runtime dep manifests 2026-04-26 11:11:58 +01:00
Peter Steinberger
f337c9019c refactor: share plugin package entry resolution 2026-04-26 11:11:58 +01:00
Peter Steinberger
8ba9c9098a fix(agents): avoid provider startup scans 2026-04-26 11:11:37 +01:00
Peter Steinberger
8bc4d4bcd4 fix: prevent duplicate chat attachment send races 2026-04-26 11:10:42 +01:00
Vincent Koc
dc05c93c02 chore(docker): expose diagnostics observability settings 2026-04-26 03:05:10 -07:00
Peter Steinberger
4ed97f7e35 docs: update changelog for plugin fixes 2026-04-26 11:01:10 +01:00
Peter Steinberger
f33a812c07 fix: validate plugin package extension entries 2026-04-26 11:01:10 +01:00
Peter Steinberger
d22d6aed16 fix: respect plugin allowlist for bundled deps 2026-04-26 11:01:10 +01:00
Peter Steinberger
93f2d42259 fix: fail plugin update on update errors 2026-04-26 11:01:10 +01:00
Vincent Koc
861cd026d1 docs(release): add plugin deprecation sweep 2026-04-26 02:59:29 -07:00
Peter Steinberger
9a529ca78b chore: update dependencies 2026-04-26 10:54:58 +01:00
Vincent Koc
9f0cd3514c test(plugins): make compat window guard type-safe 2026-04-26 02:52:45 -07:00
Vincent Koc
bb2425e612 test(plugins): enforce compat removal window 2026-04-26 02:51:48 -07:00
Vincent Koc
5baf90ffef chore(plugins): cap compat removal windows 2026-04-26 02:51:48 -07:00
Vincent Koc
3308347a43 fix(security): keep web search credential checks cold 2026-04-26 02:51:48 -07:00
Vincent Koc
22044af066 fix(config): keep command alias validation cold 2026-04-26 02:51:48 -07:00
Vincent Koc
a9d243327c chore(plugins): complete compat registry inventory 2026-04-26 02:51:47 -07:00
Peter Steinberger
975fd5bc8d docs: add gif asset hygiene guidance 2026-04-26 10:48:06 +01:00
Peter Steinberger
bd95baa4f7 fix(bonjour): suppress ciao process crashes 2026-04-26 10:47:36 +01:00
Peter Steinberger
1be39ac847 fix: increase update step timeout 2026-04-26 10:46:55 +01:00
Peter Steinberger
b67d9bf7f0 fix: propagate update timeout to plugin installs 2026-04-26 10:45:11 +01:00
Vincent Koc
d1f40731e3 chore(ci): tune stale assigned triage 2026-04-26 02:42:09 -07:00
Peter Steinberger
4bc5e183ef fix: avoid CLI startup warmup leaks 2026-04-26 10:41:03 +01:00
Vincent Koc
64af2feda0 docs(context-engine): note that uninstalling the selected context engine plugin resets plugins.slots.contextEngine to the default (c6b7444d16) 2026-04-26 02:39:07 -07:00
Vincent Koc
8314b83f9d docs(agents): scope docs-only validation 2026-04-26 02:35:14 -07:00
Peter Steinberger
2aa375149f test: speed up agent hotspot tests 2026-04-26 10:28:04 +01:00
Peter Steinberger
0b301e9af4 fix: avoid eager channel setup loading 2026-04-26 10:27:35 +01:00
Peter Steinberger
6bc5fe6952 fix: harden plugin install and uninstall transactions 2026-04-26 10:27:23 +01:00
Vincent Koc
893f070560 docs(prometheus): rewrite with Steps quick start, Tabs for enable methods and pull-vs-push, AccordionGroup for label policy and troubleshooting; document the 2048-series cap and trusted-operator scope from the diagnostics-prometheus plugin code 2026-04-26 02:26:08 -07:00
Peter Steinberger
9eb0934492 test: tighten changed test routing 2026-04-26 10:25:04 +01:00
Peter Steinberger
87ac8b0456 refactor(discord): use Carbon request client for proxy fetch 2026-04-26 10:20:49 +01:00
Peter Steinberger
a3483acaab fix: stabilize gpt55 qa lab scenarios 2026-04-26 10:18:42 +01:00
Vincent Koc
0f2e7510cb feat(diagnostics-prometheus): add protected metrics exporter 2026-04-26 02:15:33 -07:00
Peter Steinberger
6cd047e7c2 refactor: clean up update and plugin uninstall helpers 2026-04-26 10:07:39 +01:00
Peter Steinberger
d58ede1b34 docs(changelog): keep discord fix scoped 2026-04-26 10:06:38 +01:00
Peter Steinberger
775c61ef5f fix(discord): ignore stale exec approval clicks 2026-04-26 10:06:38 +01:00
Vincent Koc
57a77ecdf9 docs(multi-agent-sandbox-tools): rewrite with CardGroup, AccordionGroup for examples and troubleshooting, Tabs for restrictions, Steps for filter order 2026-04-26 02:00:56 -07:00
Peter Steinberger
382c554786 docs(release): keep 2026.4.26 changelog marker empty 2026-04-26 09:59:42 +01:00
Peter Steinberger
e6c9123262 docs(release): codify beta train backport scan
(cherry picked from commit b7733c48c0)
2026-04-26 09:59:42 +01:00
Vincent Koc
e400295969 docs(cli-gateway): rewrite with CardGroup, ParamField for run/probe/install flags, AccordionGroup for status semantics and probe interpretation 2026-04-26 01:59:27 -07:00
Vincent Koc
da000ce511 docs(changelog): note subagent completion fallback 2026-04-26 01:58:01 -07:00
Vincent Koc
a911eb748b test(qa): cover subagent completion fallback 2026-04-26 01:58:01 -07:00
Vincent Koc
a1b6567059 fix(agents): fallback subagent completion delivery 2026-04-26 01:58:00 -07:00
Vincent Koc
8741a86f93 docs(broadcast-groups): rewrite with AccordionGroup for use cases and best practices, Tabs for strategy and contexts, Steps for message flow 2026-04-26 01:56:29 -07:00
Vincent Koc
ed537edacf docs(twitch): rewrite with Steps for setup, Tabs for install/auth/access patterns, ParamField for account config, AccordionGroup for troubleshooting 2026-04-26 01:55:13 -07:00
Vincent Koc
91666fe194 docs(cli-plugins): rewrite with CardGroup, AccordionGroup for install/update behavior, ParamField for list flags, Tabs for marketplace sources 2026-04-26 01:53:57 -07:00
Peter Steinberger
c6b7444d16 fix(plugins): reset context engine slot on uninstall 2026-04-26 09:50:34 +01:00
Peter Steinberger
42487d0dac fix(update): retry npm updates without optional deps 2026-04-26 09:50:27 +01:00
Peter Steinberger
832bdbc777 fix(update): repair package config after update 2026-04-26 09:50:19 +01:00
Peter Steinberger
d9c5040fc5 docs(tailscale): clarify Control UI pairing 2026-04-26 09:46:59 +01:00
Peter Steinberger
6f50253a4d fix: clarify install switching 2026-04-26 09:46:41 +01:00
Peter Steinberger
aad7b678b0 fix: pass config to plugin command specs 2026-04-26 09:45:05 +01:00
Peter Steinberger
e29d3516bf fix(gateway): skip Tailscale Control UI pairing 2026-04-26 09:42:25 +01:00
Peter Steinberger
5ab5b75348 fix: update Docker plugin registry smokes 2026-04-26 09:42:14 +01:00
Vincent Koc
2652c9eacf fix(configure): defer web search setup runtime
Keep web-search configure and channel command defaults on cold plugin metadata, harden persisted registry reads, and require active config for manifest command defaults.\n\nThanks @vincentkoc
2026-04-26 01:41:57 -07:00
Peter Steinberger
218636a0ea docs(changelog): split 2026.4.25 and 2026.4.26 notes 2026-04-26 09:40:00 +01:00
Vincent Koc
f164b8b357 docs(webchat): note that reasoning-flagged payloads are excluded from WebChat assistant content, transcript text, and audio blocks (4823288b3b) 2026-04-26 01:39:34 -07:00
Vincent Koc
abd5ec98ab fix(runtime): harden dependency install surfaces (#71997)
* fix(runtime): harden dependency surfaces

* fix(runtime): harden dependency install surfaces

* fix(runtime): address dependency surface review

* fix(runtime): address dependency surface review

* fix(channels): avoid read-only plugin loader cycle

* fix(channels): allow optional read-only loader workspace

* test(commands): refresh current main checks

* test(commands): keep provider metadata mock unique

* test(commands): keep doctor security read-only mock unique
2026-04-26 01:38:21 -07:00
Vincent Koc
eb6b35671a docs(changelog): flatten 27 multi-line bullets into single lines per AGENTS.md rule 2026-04-26 01:35:42 -07:00
Peter Steinberger
3b5463591b chore: bump version to 2026.4.26 2026-04-26 09:28:52 +01:00
Peter Steinberger
4ad8b613c9 test: update npm telegram workflow expectations 2026-04-26 09:24:10 +01:00
Peter Steinberger
1969452c3f fix: hide raw agent failures in group chats 2026-04-26 09:19:27 +01:00
Peter Steinberger
134cc64aff fix: keep host plugin registry out of live Docker state 2026-04-26 09:17:38 +01:00
Peter Steinberger
0c020cdb7a test: update ci expectation drift 2026-04-26 09:16:53 +01:00
Peter Steinberger
2f5e5e9a71 fix: break plugin command spec import cycle 2026-04-26 09:15:47 +01:00
Peter Steinberger
1323683d72 fix: stabilize qa lab capture store cleanup 2026-04-26 09:13:30 +01:00
Ayaan Zaidi
7e376e5aba ci: build npm telegram e2e image after approval 2026-04-26 13:39:18 +05:30
Peter Steinberger
e2ef5e2329 test: keep path alias temp dirs out of repo 2026-04-26 09:09:07 +01:00
Peter Steinberger
c99d72575e fix(release): reject staged runtime deps in packs 2026-04-26 09:08:54 +01:00
Shakker
5c0dc93d1e fix(doctor): keep service repair policy scoped 2026-04-26 09:08:36 +01:00
Shakker
6cf5a5fbcd docs: document external service repair policy 2026-04-26 09:08:36 +01:00
Shakker
0b6ebf3343 fix(doctor): honor external service repair policy 2026-04-26 09:08:35 +01:00
Vincent Koc
d24c6095ce docs(sdk-setup): rewrite with Tabs for package metadata and install paths, ParamField for openclaw fields, AccordionGroup for setup-entry rules and helpers 2026-04-26 01:07:59 -07:00
Vincent Koc
64a7a34c83 docs(trusted-proxy-auth): rewrite with Steps for handshake, Tabs for TLS, AccordionGroup for proxy examples and troubleshooting 2026-04-26 01:04:51 -07:00
Vincent Koc
f2744978a0 docs(slash-commands): rewrite with ParamField for config keys, AccordionGroup for command groups and surface notes 2026-04-26 01:02:55 -07:00
Shakker
5037298d82 test: update channel status label fixtures 2026-04-26 09:01:39 +01:00
Shakker
0a82c819bb fix: keep status channel metadata cold 2026-04-26 09:01:39 +01:00
Peter Steinberger
a434133aac fix: fail update on plugin sync errors 2026-04-26 09:01:18 +01:00
Peter Steinberger
4823288b3b fix(gateway): hide webchat reasoning payloads 2026-04-26 09:00:56 +01:00
Peter Steinberger
164aaa48db style: format gateway imports 2026-04-26 09:00:33 +01:00
Peter Steinberger
878e1a2201 fix(plugins): preload cli backend runtime owners 2026-04-26 08:59:41 +01:00
Vincent Koc
6360e1146f docs(media-understanding): rewrite with Steps for behavior and auto-detect, Tabs for config examples and entries, ParamField for attachments 2026-04-26 00:58:31 -07:00
Peter Steinberger
626313a397 fix: satisfy diagnostic trace lint 2026-04-26 08:57:49 +01:00
Peter Steinberger
606a7dbc75 test: stabilize telegram command pagination retry 2026-04-26 08:57:49 +01:00
Peter Steinberger
7cbe271d08 fix: keep channel command defaults read-only 2026-04-26 08:57:49 +01:00
Vincent Koc
06d409dc27 docs(mattermost): rewrite with Steps for setup and HMAC, Tabs for chatmodes, AccordionGroup for slash commands and troubleshooting 2026-04-26 00:56:05 -07:00
Shakker
295bcde7b8 test: update channel metadata mocks 2026-04-26 08:41:34 +01:00
Peter Steinberger
8d50cd82d3 docs(changelog): finalize 2026.4.25 release notes 2026-04-26 08:41:14 +01:00
Vincent Koc
32d3a820c8 docs(sdk-runtime): rewrite with AccordionGroup for runtime namespaces, Steps for store wiring, ParamField for top-level api fields 2026-04-26 00:40:41 -07:00
Vincent Koc
1dc57d4c31 docs(groups): rewrite with Tabs for sandbox patterns and copy-paste intents, AccordionGroup for per-channel notes, Steps for evaluation order 2026-04-26 00:38:20 -07:00
Vincent Koc
fe69b02951 docs(sandboxing): rewrite with Tabs for modes/backends/workspace, AccordionGroup for SSH/OpenShell details, Steps for image setup 2026-04-26 00:35:52 -07:00
Vincent Koc
3e2e26549a docs(cli-config): rewrite with Tabs for set modes, AccordionGroup for builder flags and dry-run details, Steps for the repair loop 2026-04-26 00:32:59 -07:00
Peter Steinberger
4c7a94aac4 fix: quote Windows UI runner paths 2026-04-26 08:31:00 +01:00
Vincent Koc
434c8a1c91 docs(heartbeat): rewrite with Steps for quick start, ParamField for field notes, AccordionGroup for delivery and tasks behavior 2026-04-26 00:30:47 -07:00
Shakker
04575333d3 chore: ignore local agent skills 2026-04-26 08:26:28 +01:00
Shakker
50558e0d56 docs: note channel runtime laziness fixes 2026-04-26 08:26:28 +01:00
Shakker
8fe449c883 fix: avoid channel runtime in format summaries 2026-04-26 08:26:27 +01:00
Shakker
8b32c31252 fix: keep thread placement metadata cold 2026-04-26 08:26:27 +01:00
Shakker
2e101e8413 fix: keep channel security checks cold 2026-04-26 08:26:27 +01:00
Vincent Koc
a77996dc56 fix(diagnostics): propagate trusted traceparent headers 2026-04-26 00:24:47 -07:00
Vincent Koc
5e8fda4c64 docs(memory-config): rewrite with CardGroup overview links, Steps for auto-detect, AccordionGroup for provider configs and QMD subsections 2026-04-26 00:21:28 -07:00
Peter Steinberger
76cf013df5 test: remove slow reply bypass from docker smoke 2026-04-26 08:19:23 +01:00
Vincent Koc
450dc3a206 docs(control-ui): rewrite with Steps for pairing, AccordionGroup for capabilities and chat behavior, Tabs for tailnet access 2026-04-26 00:18:47 -07:00
Peter Steinberger
7b438965bd test: stabilize docker mcp readiness smokes 2026-04-26 08:17:28 +01:00
Peter Steinberger
c5bbf83904 fix: skip unresolved delivery targets for no-deliver cron 2026-04-26 08:17:28 +01:00
Peter Steinberger
f4f74a2391 docs(changelog): organize unreleased notes 2026-04-26 08:15:34 +01:00
Vincent Koc
0c8f0aacf5 docs(plugin-architecture): rewrite with AccordionGroup for shapes and ownership, Steps for the architecture pipeline, Tabs for layering 2026-04-26 00:15:25 -07:00
Peter Steinberger
1de4aff06d fix: cover Windows pnpm and Lobster install regressions 2026-04-26 08:14:28 +01:00
Peter Steinberger
5b9be2cdb1 fix: migrate agent runtime config 2026-04-26 08:12:44 +01:00
Vincent Koc
9d6e79019f docs(secrets): rewrite with Tabs for SecretRef sources, AccordionGroup for providers and exec examples, Steps for the audit flow 2026-04-26 00:12:05 -07:00
Shakker
b5e4e2f257 Revert "fix(plugins): persist registry contribution metadata"
This reverts commit 1ee5654220.
2026-04-26 08:11:09 +01:00
Shakker
59d1fa65df docs: note plugin uninstall file cleanup 2026-04-26 08:11:09 +01:00
Shakker
6428440086 fix: remove plugins from recorded install roots 2026-04-26 08:11:09 +01:00
Peter Steinberger
d419fb561d feat(tts): resolve channel account config generically 2026-04-26 08:10:36 +01:00
Vincent Koc
6c60cd2b72 docs(mcp): rewrite with Steps for lifecycle, Tabs for client modes, ParamField for serve options, AccordionGroup for tools 2026-04-26 00:08:16 -07:00
Vincent Koc
1ee5654220 fix(plugins): persist registry contribution metadata 2026-04-26 00:03:21 -07:00
Peter Steinberger
54f8e4145e test: speed up provider and security tests 2026-04-26 07:59:32 +01:00
Peter Steinberger
d1e5f4bd3c fix(update): bound Windows scheduled task stop 2026-04-26 07:56:46 +01:00
Shakker
3ad29972d0 docs: note read-only channel command discovery 2026-04-26 07:55:00 +01:00
Shakker
43557b16a6 fix: keep channel command discovery read-only 2026-04-26 07:55:00 +01:00
Shakker
fd97f530e3 docs: note cold session metadata fix 2026-04-26 07:55:00 +01:00
Shakker
bbed91bf71 fix: avoid session metadata channel runtime fallback 2026-04-26 07:55:00 +01:00
Shakker
49b106d357 docs: note cold native command defaults 2026-04-26 07:55:00 +01:00
Shakker
7a7728db13 fix: keep native command auto defaults cold 2026-04-26 07:55:00 +01:00
Shakker
aee4c92344 docs: note provider index disablement fix 2026-04-26 07:55:00 +01:00
Shakker
78fb0ade09 fix: honor plugin disablement in provider index rows 2026-04-26 07:55:00 +01:00
Vincent Koc
f48dc96d43 docs(opentelemetry): document harness lifecycle metric, span, and diagnostic events from 82ddcf24f5 2026-04-25 23:54:30 -07:00
Vincent Koc
ff7f0df871 docs(config-tools): rewrite with AccordionGroup for provider examples and field details, ParamField for loop detectors 2026-04-25 23:51:26 -07:00
Peter Steinberger
4ee537a04a fix(node-runtime): keep node-host recovering after gateway restarts 2026-04-26 07:49:45 +01:00
Vincent Koc
c7ead7d8a9 fix(cli): lazy-load model auth runtime 2026-04-25 23:49:06 -07:00
Vincent Koc
62869c8502 docs(bluebubbles): rewrite with Steps for setup, Tabs for DM/groups and coalescing, AccordionGroup for actions and config 2026-04-25 23:48:13 -07:00
Vincent Koc
bb0ef5ef18 docs(troubleshooting): rewrite with AccordionGroup for symptom signatures, Steps for fix flows, and Warning callouts 2026-04-25 23:44:25 -07:00
Harry Xie
77719899f3 fix(gateway): refresh stale embedded service tokens
Refresh loaded gateway service installs when the current service embeds stale gateway auth instead of returning already-installed, avoiding LaunchAgent token-mismatch loops after token rotation.

Fixes #70752.
Thanks @hyspacex.

Co-authored-by: Harry Xie <harryhsieh963@yahoo.com>
2026-04-26 07:42:14 +01:00
Vincent Koc
8c87a637e9 docs(doctor): rewrite with Tabs for headless flags and AccordionGroup for the 19+ detailed behaviors 2026-04-25 23:40:24 -07:00
Vincent Koc
c4a39a6819 docs(model-providers): rewrite with AccordionGroup, CardGroup, Tabs, and Steps for cleaner provider scan 2026-04-25 23:36:01 -07:00
Vincent Koc
82ddcf24f5 feat(diagnostics): add harness lifecycle telemetry 2026-04-25 23:34:34 -07:00
Peter Steinberger
8bbb143ab8 fix: enforce device token scope containment 2026-04-26 07:28:21 +01:00
Peter Steinberger
26e4eb8e40 fix(update): ignore plugin install stages in dist verify 2026-04-26 07:28:02 +01:00
Peter Steinberger
8368026986 fix(installer): preserve PowerShell host on failure 2026-04-26 07:23:48 +01:00
Peter Steinberger
1fae716a04 fix: recover stale cron task records 2026-04-26 07:23:39 +01:00
Ayaan Zaidi
9d21200049 test(e2e): cover npm onboarding runtime deps 2026-04-26 11:53:17 +05:30
Peter Steinberger
7091dbe2bf docs: prefer ghcrawl for OpenClaw issue triage 2026-04-26 07:19:00 +01:00
Vincent Koc
1f267de142 docs(changelog): note cold provider setup guidance 2026-04-25 23:16:59 -07:00
Vincent Koc
585784643e fix(providers): keep setup guidance cold 2026-04-25 23:16:59 -07:00
Peter Steinberger
b979f2964c fix: warn on low disk before runtime dependency staging 2026-04-26 07:16:26 +01:00
Ayaan Zaidi
e633f43c53 fix: strip antml thinking tags in streaming (#69288) (thanks @xialonglee) 2026-04-26 11:46:06 +05:30
Ayaan Zaidi
4bfa7d17a3 refactor(agents): dedupe thinking tag scanner 2026-04-26 11:46:06 +05:30
xialonglee
d7da3d470e fix(agents): strip antml thinking tags in streaming 2026-04-26 11:46:06 +05:30
Peter Steinberger
40e5d9adc7 fix(plugins): update external plugins in recorded root 2026-04-26 07:14:30 +01:00
Vincent Koc
1b99f8aedb docs(diffs): rewrite with Steps, Tabs, ParamField, and AccordionGroup for clearer mode and security guidance 2026-04-25 23:11:13 -07:00
Vincent Koc
eb769ee4ec docs(context-engine): rewrite with Steps, Tabs, AccordionGroup, and ParamField for engine lifecycle clarity 2026-04-25 23:09:26 -07:00
Peter Steinberger
7c6c0a8d54 fix: avoid persisted-auth channel startup probes 2026-04-26 07:09:21 +01:00
Ayaan Zaidi
1ed8c41f33 fix: clear deselected model fallbacks (#71596) (thanks @rubencu) 2026-04-26 11:39:17 +05:30
Ayaan Zaidi
6cc74595e3 refactor(configure): distill fallback selection merge 2026-04-26 11:39:17 +05:30
Ruben Cuevas
1377baee1a fix(configure): clear deselected model fallbacks 2026-04-26 11:39:17 +05:30
Vincent Koc
ce04866019 docs(tasks): rewrite with Tabs for quick start and AccordionGroup for CLI reference and runtime relationships 2026-04-25 23:07:58 -07:00
Peter Steinberger
57c1c7d886 fix(protocol): refresh generated swift models 2026-04-26 07:07:28 +01:00
Vincent Koc
48d83b7566 docs(cron-jobs): rewrite around Steps, Tabs, ParamField, AccordionGroup, and Warning callouts 2026-04-25 23:05:57 -07:00
Peter Steinberger
5a89330c33 fix(installer): fall back from stale nvm dir 2026-04-26 07:04:40 +01:00
Peter Steinberger
e67093f333 chore(plugin-sdk): refresh api baseline 2026-04-26 07:03:25 +01:00
Peter Steinberger
d613c8e29b refactor(tts): resolve voice delivery from channel capabilities 2026-04-26 07:03:25 +01:00
Vincent Koc
2784710f4d docs(acp-agents): rewrite around Steps, Tabs, ParamField, and AccordionGroup for operator runbook clarity 2026-04-25 23:03:14 -07:00
Peter Steinberger
ee2ab9a644 fix(plugins): install optional plugin dependencies 2026-04-26 07:00:16 +01:00
Peter Steinberger
54f4c45e5d fix: stabilize model run probes 2026-04-26 06:59:22 +01:00
Peter Steinberger
6ff7a30b9f fix(providers): guard optional provider index installs 2026-04-26 06:56:42 +01:00
Vincent Koc
cd89adf0ac fix(logging): rotate file logs instead of suppressing 2026-04-25 22:55:33 -07:00
Vincent Koc
e54f5c4068 docs(clawhub): rewrite around Steps Tabs and AccordionGroup
The clawhub doc was 358 lines mixing two install-command bullet
blocks, a 'beginner-friendly' prose walkthrough, six sequential
flat CLI command sections (Auth, Search, Install, Update, List,
Publish skills, Publish plugins, Delete, Sync), and a workflow
section that repeated the same commands a third time.

Restructure for scan-first reading without losing reference detail:

- Wrap Quick start in a 4-step Steps component (search -> install
  -> use -> publish optional CLI install).
- Convert the duplicate native-OpenClaw skills/plugins blocks into
  a single Tabs component with one tab per surface, keeping the
  validation/safety notes inline.
- Convert the service-features bullet list to a 7-row table.
- Move reporting and moderation rules into a 2-panel
  AccordionGroup.
- Convert the eight CLI command sections into one AccordionGroup
  (Auth / Search / Install update list / Publish skills / Publish
  plugins / Delete undelete / Sync) so the flat command catalog
  collapses.
- Convert the global-options bullet list into ParamField
  definitions.
- Consolidate the duplicate workflows section into a single Tabs
  component (Search / Install / Update all / Publish single /
  Sync many / Publish plugin from GitHub).
- Move versioning, lockfile, sync fallback, storage, and telemetry
  notes into a dedicated AccordionGroup.
- Convert the env vars bullet list into a 5-row table.
- Drop the duplicate 'How it works / What you can do / Quick start
  (non-technical)' prose; the same content lives in the new Quick
  start Steps and 'What ClawHub is' summary.
- Sentence-case the Related list and add a missing 'Plugins' link.
- Add sidebarTitle for explicit nav.

CLI flags, command parameters, registry semantics, lockfile path,
moderation thresholds (1-week account age, 20-report cap, 3-report
auto-hide), telemetry env var, and required plugin package.json
metadata are unchanged. Pure restructure plus Mintlify upgrades.
2026-04-25 22:53:54 -07:00
Vincent Koc
50c427efc8 fix(providers): export provider index install types 2026-04-25 22:52:21 -07:00
Vincent Koc
62a5963d24 feat(providers): add provider index install metadata 2026-04-25 22:52:21 -07:00
Vincent Koc
194818960c fix(providers): keep setup flow on cold metadata 2026-04-25 22:52:21 -07:00
Vincent Koc
fd35ba2cad docs(exec-approvals): rewrite around ParamField, Steps, and tables
The exec-approvals doc was 379 lines mixing inspection commands as
free bullets, bullet-list policy knobs (security/ask/askFallback/
strictInlineEval), a long YOLO-mode walkthrough split between two
shell blocks, and a stray dangling HTML comment from a prior split
to the advanced page.

Restructure for scan-first reading without losing operational detail:

- Convert 'Inspecting the effective policy' command bullets into a
  command/result table.
- Convert each policy knob (security, ask, askFallback,
  strictInlineEval) into a ParamField definition so type/values are
  visually distinct.
- Wrap the persistent gateway-host YOLO setup in a Steps component
  (config -> approvals file).
- Move the YOLO 'pick which layer' note and 'auto vs YOLO'
  distinctions into a Warning callout instead of buried inline
  bullets.
- Convert the YOLO layer summary into a 3-row layer/setting table.
- Move the local-only exec-policy limitations into a Note callout.
- Convert allowlist entry fields (id, lastUsedAt, lastUsedCommand,
  lastResolvedPath) into a 4-row table.
- Surface Auto-allow trust caveats as a Warning callout.
- Drop the dangling HTML comment '<!-- moved to /tools/exec-approvals-advanced -->'.
- Sentence-case 'YOLO mode (no-approval)' replacing the inverted
  quote variant ('No-approval YOLO mode').
- Add sidebarTitle for explicit nav.

Trust model, schema example, host approvals JSON shape, allowlist
glob rules, ask-fallback semantics, system-event names, deny-rerun
guard, and the trailing CardGroup of related entries are unchanged.
Pure restructure plus Mintlify component upgrades.
2026-04-25 22:51:59 -07:00
Peter Steinberger
db0864ad41 fix(installer): warn about duplicate global installs 2026-04-26 06:50:33 +01:00
Shakker
d5eae0d959 fix: keep agent provider status on plugin index 2026-04-26 06:49:48 +01:00
Vincent Koc
bf2c992a86 docs(subagents): rewrite around AccordionGroup, ParamField, and Steps
The sub-agents doc was 412 lines of dense bullet lists describing
spawn behavior, tool params, thread binding flow, allowlist rules,
auto-archive behavior, announce semantics, and the sessions_history
sanitization pipeline.

Restructure for scan-first reading without losing reference detail:

- Move spawn-behavior bullets into an AccordionGroup with four
  panels (Non-blocking + push-based; Manual-spawn delivery
  resilience; Completion handoff metadata; Modes and ACP runtime).
- Convert sessions_spawn tool params into ParamField definitions so
  type/default/required render visually.
- Wrap the thread-binding flow in a Steps component (spawn -> bind
  -> route -> inspect timeouts -> detach).
- Convert manual thread controls into a 5-row table.
- Convert allowlist fields (allowAgents, requireAgentId) into
  ParamField definitions.
- Convert announce-context fields into a 6-row source/field table.
- Surface the cost-budget guidance, sessions_spawn delivery-param
  exclusion, operational guidance, and the PAIRING_REQUIRED caller
  caveat as Note/Warning callouts where they were buried inline.
- Sentence-case 'Tool Policy' to 'Tool policy' (heading-case fix).
- Sentence-case 'Configuration Reference' link.
- Alphabetize the Related list and add 'Background tasks' which was
  referenced inline but missing from Related.
- Add sidebarTitle for explicit nav.

Tool surface, depth tables, slash commands, defaults, allowlist
semantics, sandbox-inheritance guard, per-depth tool policy,
auto-archive timing, announce status sourcing, sessions_history
normalization steps, concurrency lane, recovery rules, and
limitations are unchanged. Pure restructure plus Mintlify upgrades.
2026-04-25 22:49:14 -07:00
Peter Steinberger
e69c2853b2 fix(cli): handle Volta shim respawns 2026-04-26 06:48:50 +01:00
Peter Steinberger
e4e69c5bc6 fix: retry systemd unit activation after reload 2026-04-26 06:47:29 +01:00
Vincent Koc
2b29594611 docs(skills): rewrite around tables, ParamField, and AccordionGroup
The skills doc was 409 lines of nested bullet lists describing
precedence, allowlist rules, gating fields, installer specs, and
config overrides. Heavy reference content but no Mintlify structure.

Restructure for scan-first reading without losing reference detail:

- Convert 'Locations and precedence' from a numbered list + arrow
  string into a 6-row precedence table.
- Convert 'Per-agent vs shared skills' bullet/paragraph mix into a
  scope/path/visibility table.
- Move agent-allowlist rules into an AccordionGroup so the example
  config is the headline and the rules collapse on demand.
- Convert ClawHub install/update/sync bullets into a 3-row command
  table.
- Convert SKILL.md frontmatter optional keys (homepage, user-invocable,
  disable-model-invocation, command-dispatch, command-tool,
  command-arg-mode) into ParamField definitions.
- Convert metadata.openclaw fields (always, emoji, homepage, os,
  requires.bins, requires.anyBins, requires.env, requires.config,
  primaryEnv, install) into ParamField definitions.
- Move installer-selection rules and per-installer details (Go, download)
  into an AccordionGroup so the gating section reads as the canonical
  schema plus collapsible operational notes.
- Convert skills.entries config-override rules (enabled, apiKey, env,
  config, allowBundled) into ParamField definitions.
- Surface security caveats as a Warning callout up top instead of a
  bullet list.
- Move 'Looking for more skills?' into the trailing Related list and
  drop the dangling --- separator.
- Sentence-case headings (Format, Gating, Config overrides, Token
  impact) and the Related entries (Creating skills, Skills config,
  Slash commands).
- Drop the redundant 'Skill Workshop' Title-Case heading variant.
- Add sidebarTitle 'Skills' for explicit nav.

Skill source paths, frontmatter parser rules, gating semantics,
installer selection logic, sandboxing notes, env-injection scope,
snapshot/refresh behaviour, remote-node behaviour, and token-impact
formula are unchanged. Pure restructure plus Mintlify components.
2026-04-25 22:45:35 -07:00
Vincent Koc
d54d2d6b9b docs(voice-call): rewrite around Steps Tabs and provider Tabs
The voice-call plugin doc was 664 lines with a flat install/setup
walkthrough, three flat 'Realtime' / 'Streaming' / 'TTS' provider
config blocks each shown twice, an italicised webhook-security
section in Title Case, and a duplicate-Voice Call body H1.

Restructure for scan-first reading without losing operational detail:

- Wrap Quick start in a Steps component (install -> configure ->
  verify -> smoke), with the 'install from npm' vs 'install from
  local folder' choice as a nested Tabs.
- Surface the public-webhook-URL constraint as a Warning at the top
  of Quick start so readers see it before they hit setup.
- Move provider exposure caveats, streaming connection caps, and
  legacy config migration notes into a single AccordionGroup so
  the Configuration section reads as the canonical config plus
  collapsible operational details.
- Convert the Realtime, Streaming, and TTS provider examples to
  Tabs with one tab per provider (Google/OpenAI for realtime;
  OpenAI/xAI for streaming; Core/ElevenLabs/OpenAI override for TTS),
  removing the previous duplicate-block-per-provider pattern.
- Convert the realtime tool-policy bullet list to a 3-row table.
- Convert the agent tool action list and gateway RPC list into
  small tables (action -> args).
- Surface inboundPolicy caller-ID weakness, microsoft-not-supported
  for telephony, and realtime+streaming exclusivity as Warning
  callouts where they were previously buried inline.
- Sentence-case 'Webhook security' (was Title Case), drop the
  duplicate body H1, and refresh the Related list to alphabetical
  sentence-case.

Provider names, env vars, defaults, models, voice ids, command
flags, and field semantics are unchanged. Pure restructure plus
Mintlify component upgrades.
2026-04-25 22:42:47 -07:00
VACInc
78c7292c95 fix: keep telegram tool progress without preview (#71825) (thanks @VACInc)
* fix(telegram): keep default tool progress without preview

* fix: keep telegram tool progress without preview (#71825) (thanks @VACInc)

---------

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-04-26 11:11:18 +05:30
hcl
c5c40b22af fix(codex): translate minimal thinking for modern models
Fixes #71946
2026-04-25 22:40:53 -07:00
Peter Steinberger
036b422fc6 fix(installer): load nvm before node detection 2026-04-26 06:39:26 +01:00
Peter Steinberger
cbf9c60f1d fix(installer): handle macos gum node failures 2026-04-26 06:37:33 +01:00
Peter Steinberger
be8a3617d9 fix: verify updated gateway version after package restart 2026-04-26 06:37:26 +01:00
Peter Steinberger
142577d9b2 fix(browser): recover stale remote CDP reads safely 2026-04-26 06:35:53 +01:00
Peter Steinberger
eca9f46824 fix: honor node systemd unit activation 2026-04-26 06:35:01 +01:00
Peter Steinberger
33b6962273 fix(installer): fail fast on missing Homebrew Node 2026-04-26 06:33:08 +01:00
Peter Steinberger
257e767e5b fix(telegram): include native quote excerpts for replies 2026-04-26 06:32:46 +01:00
Vincent Koc
639cd50261 fix(models): preserve provider index catalog fallback (#71985)
* fix(models): preserve provider index catalog fallback

* fix(models): mark provider index rows as previews
2026-04-25 22:31:52 -07:00
Shakker
a57d681db9 fix: keep plugin command status on cold index 2026-04-26 06:28:54 +01:00
Vincent Koc
6e3eeb526f docs(video-generation): rewrite around Steps, ParamField, AZ providers
The video-generation page was 454 lines with a 3-step Quick start
written as flat numbered prose, four separate parameter tables (Required,
Content inputs, Style controls, Advanced), the task lifecycle as a
numbered list, and a Related list mixing alphabetic and recency order.

Restructure for scan-first reading without losing technical content:

- Wrap Quick start in a Steps component (auth -> default model ->
  ask the agent).
- Convert all four parameter tables into ParamField definitions grouped
  under their existing sub-section headings (Required / Content inputs /
  Style controls / Advanced), so types, defaults, and required flags
  show as visual chips and long descriptions wrap cleanly.
- Convert the task lifecycle from a numbered list to a 4-row table for
  at-a-glance scanning.
- Convert Yes/No checkmarks in both the Supported providers and
  Capability matrix tables to ✓ and em-dash, matching the rest of the
  media docs.
- Convert the bullet list under Actions into a 3-row table.
- Sentence-case Related entries and alphabetize the Related list.
- Add sidebarTitle so the nav reads 'Video generation' explicitly.

Schema fields, defaults, model refs, env vars, capability declarations,
fallback rules, and provider notes are unchanged. AccordionGroup of 14
provider notes was already alphabetized and is preserved verbatim.
2026-04-25 22:27:56 -07:00
Peter Steinberger
503a3aa125 fix: defer bedrock discovery sdk import 2026-04-26 06:27:09 +01:00
Peter Steinberger
9f4b155c47 fix(docker): include patch files in runtime image 2026-04-26 06:26:37 +01:00
Peter Steinberger
0e58654dba fix(agents): silence empty group model turns 2026-04-26 06:25:59 +01:00
Vincent Koc
d531760898 docs(music-generation): rewrite around Steps, Tabs, and provider Accordion
The music-generation page was 291 lines with two side-by-side
'Quick start' subsections (shared provider-backed vs. ComfyUI
workflow), a flat parameter table, two prose paragraphs explaining
async behaviour and task lifecycle, and a 'Provider notes' bullet
list mixed with a separate 'Choosing the right path' section.

Restructure for scan-first reading without losing technical content:

- Wrap Quick start in a top-level Tabs with two child Steps blocks
  (Shared provider-backed | ComfyUI workflow), so readers pick a path
  first and only see the matching steps.
- Convert the tool parameter list to ParamField definitions with
  type signatures and required flags surfaced visually.
- Convert the four async-behaviour bullets to a labelled bullet list
  and the four-state task lifecycle to a table for at-a-glance
  scanning.
- Change Capability matrix Yes/No values to checkmarks/em-dashes for
  alignment with the rest of the media docs.
- Convert the 'Provider notes' free-form paragraphs into an
  AccordionGroup keyed by provider (ComfyUI / Google Lyria 3 /
  MiniMax), keeping wording faithful.
- Sentence-case Related entries and add sidebarTitle so the nav reads
  'Music generation' explicitly.

Provider rows already alphabetized in the supported providers table
(ComfyUI / Google / MiniMax), kept that order. Wording, model refs,
defaults, env vars, and capability declarations are unchanged.
2026-04-25 22:24:58 -07:00
Peter Steinberger
af8648e00e fix(installer): make apt installs noninteractive 2026-04-26 06:23:41 +01:00
Peter Steinberger
58a31b12f7 fix(agents): keep runtime wakeups out of chat transcript 2026-04-26 06:23:27 +01:00
Vincent Koc
f0ea901a0d docs(image-generation): rewrite around Steps, Tabs, and AZ providers
The image-generation page was 395 lines with a 3-step quick-start
written as plain numbered prose, a sprawling 'OpenAI gpt-image-2'
section that mixed routing/legacy/OpenAI options with five inline
slash-command examples, and provider tables that mixed alphabetic
and recency order.

Restructure for scan-first reading without losing technical content:

- Wrap Quick start in a Steps component (auth -> default model ->
  ask the agent), pulling the Codex OAuth note inline with the model
  step where it belongs and surfacing the LAN/SSRF caveat as a
  Warning callout.
- Alphabetize the Supported providers table (ComfyUI, fal, Google,
  LiteLLM, MiniMax, OpenAI, OpenRouter, Vydra, xAI) and the Provider
  capabilities table (same order across both). Convert the Yes/No
  capability table to checkmarks plus exact counts for readability.
- Replace the long inline OpenAI / OpenRouter / MiniMax / xAI prose
  with a 'Provider deep dives' AccordionGroup so each backend's
  routing, legacy URL handling, and provider-specific knobs collapse
  by default.
- Move the four provider-selection-order notes into a small
  AccordionGroup ('Per-call overrides are exact', 'Auto-detection is
  auth-aware', 'Timeouts', 'Inspect at runtime').
- Collapse the five flat slash-command examples into a single Tabs
  component (4K landscape / transparent PNG / two-square /
  edit-one-ref / edit-multi-ref) with the matching CLI variant inline
  on the transparent-PNG tab.
- Sentence-case the Related list (Tools overview, Configuration
  reference) and drop the redundant generic introductory wording.
- Add sidebarTitle so the nav reads 'Image generation' explicitly.

Wording, schema fields, defaults, model refs, env vars, and the
detailed OpenAI/OpenRouter/Codex routing rules are unchanged.
2026-04-25 22:23:09 -07:00
Vincent Koc
5d3168c343 fix(logging): read config path in bundled runtime 2026-04-25 22:21:15 -07:00
Vincent Koc
d1502c2ba1 docs(media-overview): rewrite around CardGroup, sync/async split, and AZ providers
The media overview was a 91-line page that opened with a redundant
Title-Case body H1 ('# Media Generation and Understanding'), then
mixed a capability table, a Yes/Yes/Yes provider matrix, dense prose
about async behaviour and STT/Voice Call surfaces, plus duplicate
'Quick links' and 'Related' sections at the end.

Restructure for scan-first reading without losing any content:

- Drop the redundant body H1; lead with a one-paragraph summary.
- Replace the 'Capabilities at a glance' table with a CardGroup of six
  entry cards (Image / Video / Music / TTS / Media understanding / STT)
  each linking directly to its dedicated page. Mode (sync/async) is
  noted on the card so readers see latency expectations up front.
- Convert the provider matrix to checkmarks for readability and align
  the column header names. Provider rows already alphabetized.
- Pull async vs synchronous behaviour into a 5-row table that names
  why each capability is sync or async, then keep the operator-facing
  paragraph that explains task-id handoff.
- Move the long 'Google maps to ... OpenAI maps to ... xAI maps to ...'
  paragraph into a per-vendor AccordionGroup so each mapping is a
  collapsible panel instead of one large prose block.
- Drop duplicate 'Quick links' section in favour of a single Related
  list, sentence-cased to match the rest of the docs.
2026-04-25 22:20:35 -07:00
Peter Steinberger
eb5bb67e04 style(macos): satisfy swiftformat 2026-04-26 06:19:35 +01:00
Peter Steinberger
113794f277 fix(voicewake): harden trigger routing rebase 2026-04-26 06:19:35 +01:00
Longbiao CHEN
96988914ff test(gateway): align sessionId voicewake assertion 2026-04-26 06:19:35 +01:00
Longbiao CHEN
dfaa9ee87e fix(gateway): keep explicit agent main sessions stable 2026-04-26 06:19:35 +01:00
Longbiao CHEN
4cc2ffce09 fix(gateway): respect explicit voicewake session targets 2026-04-26 06:19:35 +01:00
Longbiao CHEN
ef7ad8229a fix(voicewake): drop stale sdk collateral 2026-04-26 06:19:35 +01:00
Longbiao CHEN
cbcc1227d3 fix(voicewake): require token boundaries for filler-prefix matches 2026-04-26 06:19:35 +01:00
Longbiao CHEN
e74c079b22 fix(gateway): remove duplicate ws client import 2026-04-26 06:19:35 +01:00
Longbiao CHEN
afe1abc297 feat(voicewake): refresh trigger routing on main 2026-04-26 06:19:35 +01:00
Peter Steinberger
a7382ec563 test: cover older-binary service guard 2026-04-26 06:18:37 +01:00
Vincent Koc
724e92505a docs(tts): add sidebarTitle 'Text to speech (TTS)' for the nav
Default sidebar label fell back to title 'Text-to-speech', which is fine
on the page header but readers scanning the Tools sidebar look for the
acronym 'TTS'. Add a sidebarTitle so Mintlify renders 'Text to speech
(TTS)' in the sidebar while keeping the canonical page title intact.

Sentence case matches the rest of the Tools sidebar group (e.g.
'Image generation', 'Music generation', 'Video generation').
2026-04-25 22:11:31 -07:00
Peter Steinberger
15ea0e1f83 fix(gateway): reserve health probes before route stages 2026-04-26 06:10:49 +01:00
Rubén Cuevas
f9146cabfc fix(telegram): preserve native quote replies
Preserve exact Telegram selected quote text for native quote replies, share Telegram reply parameter construction between bot delivery and direct outbound sends, and retry with legacy replies when Telegram rejects native quote parameters.\n\nThanks @rubencu.
2026-04-26 06:09:43 +01:00
Peter Steinberger
edc3504c77 fix(gateway): accept fnm default path on Linux 2026-04-26 06:09:02 +01:00
Peter Steinberger
8c35e45c00 fix: guard gateway mutations from older binaries 2026-04-26 06:07:55 +01:00
Vincent Koc
fbd6b3ce3c docs(tts): A-Z order providers and add tools/tts to Tools nav group
- docs/tools/tts.md: alphabetize providers in three places that listed
  them: the supported-providers table (Azure Speech ... Xiaomi MiMo),
  the configuration Tabs (12 provider presets in A-Z), and the field
  reference AccordionGroup. Top-level fields stay first; provider
  tabs/accordions follow strict alphabetical order. Wording, schema,
  and defaults unchanged.
- docs/docs.json: add tools/tts to the main Tools sidebar group
  (slotted between trajectory and video-generation, matching the
  alphabetical neighborhood with image-generation, music-generation,
  video-generation). Previously tts only appeared under
  Nodes > Media capabilities, which was a discoverability gap for
  readers looking for TTS alongside the other generation tools.
2026-04-25 22:05:46 -07:00
Vincent Koc
71b79f49ad docs(tts): rewrite tts.md around personas with Mintlify components
The TTS doc had grown to 1008 lines with 11 separate flat 'X primary'
config blocks, a 100-line dense 'Notes on fields' bullet list, and
the new provider-personas feature (#70748) buried near the bottom.
Restructure for readability and feature visibility:

- Lead with a Steps-based 'Quick start' so first-time readers can
  enable TTS in 4 explicit steps.
- Replace the 13-bullet provider list with a single 'Supported
  providers' table that names auth env vars and per-provider notes
  inline. Add a Warning callout for the Microsoft/edge legacy alias.
- Collapse the 11 'X primary' config blocks into one Tabs component
  ('OpenAI + ElevenLabs', 'Google Gemini', 'Azure Speech',
  'Microsoft (no key)', 'MiniMax', 'Inworld', 'xAI', 'Volcengine',
  'Xiaomi MiMo', 'OpenRouter', 'Gradium', 'Local CLI') so users see
  one preset at a time and the page is scannable.
- Promote 'Personas' to its own top-level section with two examples
  (minimal and the Alfred provider-neutral persona), and add a new
  'How providers use persona prompts' AccordionGroup covering Google
  (promptTemplate audio-profile-v1, personaPrompt), OpenAI
  (instructions auto-mapping), and Other providers, plus a fallback
  policy table.
- Note that agents.list[].tts.persona overrides global persona
  per-agent (covers the recent feat(tts) per-agent voice-override
  work).
- Convert the 100-line 'Notes on fields' wall into a per-provider
  AccordionGroup using ParamField, so the field reference is
  scannable and field types/defaults are visually distinct.
- Sentence-case headings, drop redundant body H1, fold the flow
  diagram inline with Auto-TTS behavior, and refresh the Output
  formats section to a table-first layout.
- Schema fields (label/description/provider/fallbackPolicy/prompt
  with profile/scene/sampleContext/style/accent/pacing/constraints
  and providers map) verified against src/config/types.tts.ts; all
  defaults and env-var fallbacks preserved verbatim.

Net diff: 585 insertions, 684 deletions across the same surface
area.
2026-04-25 22:00:19 -07:00
Peter Steinberger
73e2151107 fix: fail updates on activated plugin load errors 2026-04-26 05:57:31 +01:00
Peter Steinberger
ad5c00b8e0 docs: expand bonjour disable troubleshooting 2026-04-26 05:56:25 +01:00
Peter Steinberger
d1a5ea2024 fix(docker): disable bonjour by default for compose 2026-04-26 05:51:05 +01:00
Vincent Koc
4cba24a4c3 fix(logging): redact console and file sinks 2026-04-25 21:50:00 -07:00
Vincent Koc
1a8f765147 docs(changelog): note scoped plugin metadata reads 2026-04-25 21:49:09 -07:00
Vincent Koc
b7340ec6a9 fix(plugins): scope metadata manifest reads 2026-04-25 21:48:47 -07:00
Shakker
3ea20d1413 fix: harden cold plugin metadata paths 2026-04-26 05:48:10 +01:00
Vincent Koc
9c8245b178 docs(agents): clarify clean rebase gate reuse 2026-04-25 21:47:55 -07:00
Peter Steinberger
27aedcfd56 style: format repository 2026-04-26 05:47:12 +01:00
Peter Steinberger
6a67f65568 fix(voice): reuse preflight transcripts across channels 2026-04-26 05:42:04 +01:00
Vincent Koc
46b9044c3f docs: update model input modalities and OTEL token-metric attrs
Two recent commits added user-facing surface that left signature-style
references in docs stale:

- 4428661779 Alvin Tang (#20721, thanks @alvinttang) extends the
  configured model 'input' modality set to also accept 'audio' and
  'video', matching what providers like LM Studio already report.
  docs/plugins/manifest.md model-fields table listed only
  'text | image | document', so add 'audio' and 'video'.
- 44da034516 Vincent (thanks @oc-factus) adds a bounded openclaw.agent
  attribute on the openclaw.tokens counter so per-agent dashboards can
  group usage. docs/gateway/opentelemetry.md metric reference omitted
  it; add it to the attrs list.
2026-04-25 21:39:44 -07:00
Peter Steinberger
9b93b7df62 fix(whatsapp): remove ack reactions after replies 2026-04-26 05:36:14 +01:00
Peter Steinberger
427e485f76 fix(update): verify restarted gateway version 2026-04-26 05:35:45 +01:00
Peter Steinberger
6893e8f5f4 test(gateway): stabilize agent wait lifecycle test 2026-04-26 05:34:33 +01:00
Peter Steinberger
5f2273e81e fix(gateway): unify chat display projection 2026-04-26 05:33:58 +01:00
Neerav Makwana
dc9ce2a1bf fix: honor agent for models auth writes (#71933)
Honor the parent `models auth --agent <id>` flag across auth write commands: `add`, `login`, `setup-token`, `paste-token`, and `login-github-copilot`.

The auth helpers now resolve the requested configured agent before choosing the auth-profile store and provider workspace, while preserving default-agent behavior when `--agent` is omitted.

Validation:
- `pnpm test src/cli/models-cli.test.ts src/commands/models/auth.test.ts`
- `pnpm test src/commands/models/auth.test.ts`
- `pnpm docs:check-mdx`
- `pnpm check:changed`
- `pnpm check`
- `pnpm build`
- `pnpm test src/cli/run-main.test.ts`

Full `pnpm test` was also run; it failed in unrelated `src/cli/run-main.test.ts` assertions during the full-suite order, while the exact file passes on both latest main and this branch. The PR diff only touches models auth CLI/auth files, docs, and changelog.

Fixes #71864.

Thanks @neeravmakwana.
2026-04-26 05:30:47 +01:00
Vincent Koc
1252da325f fix(tests): remove duplicate config mock key 2026-04-25 21:27:39 -07:00
Peter Steinberger
ae45eebef1 fix: route remote mac browser through node host 2026-04-26 05:25:59 +01:00
Peter Steinberger
b8aef04ccd docs(config): refresh config baseline hash 2026-04-26 05:20:45 +01:00
Alvin Tang
4428661779 fix(config): accept video and audio model inputs
Preserve configured audio/video model input modalities through provider catalog normalization.\n\nFixes #20721.\nThanks @alvinttang.
2026-04-26 05:18:54 +01:00
Peter Steinberger
f1eef47839 fix(agents): treat empty group replies as silent 2026-04-26 05:17:02 +01:00
Shakker
c953e98c59 docs: clarify provider index foundation scope 2026-04-26 05:14:51 +01:00
Shakker
89f368e2f9 test: exercise unsafe provider index keys 2026-04-26 05:14:51 +01:00
Shakker
e827778129 fix: keep provider index previews authoritative 2026-04-26 05:14:51 +01:00
Shakker
911172e1e6 fix: avoid provider index preview row spread 2026-04-26 05:14:51 +01:00
Shakker
f1e28370c4 docs: explain provider index authority 2026-04-26 05:14:51 +01:00
Shakker
96ac51d23d feat: add model catalog provider index contract 2026-04-26 05:14:51 +01:00
Peter Steinberger
ac0fa474f8 fix(gateway): tolerate void agent command results 2026-04-26 05:14:36 +01:00
Eulices
008e4ca81f fix: add placeholder transcript for silent voice notes (#49131)
* fix: add placeholder transcript for silent voice notes

* fix: handle placeholder transcripts per skipped attachment

* fix: preserve synthetic transcript attachment order

* fix: scope synthetic audio merge to audio slice only, preserve cross-capability and prefer ordering

Replace the global outputs.sort() with a targeted merge that:
1. Only sorts within the audio output slice (real + synthetic),
   preserving CAPABILITY_ORDER and per-capability attachments.prefer
   ordering for non-audio outputs.
2. Excludes synthetic placeholder indexes from audioAttachmentIndexes
   used by extractFileBlocks, so tiny audio-MIME files with text
   extensions can still be recovered via forcedTextMime.

Adds mergeAudioOutputsPreservingAttachmentOrder helper.

* fix: remove unused function and use toSorted() for oxlint compliance

* fix(media-understanding): preserve selected audio order for synthetic placeholders

- merge synthetic skipped-audio placeholders using audio decision order
  instead of raw attachmentIndex sorting, preserving attachments.prefer
- insert synthetic-only audio outputs at the audio capability slot
  (before video) when no real audio outputs were produced

* fix(media-understanding): use neutral too-small placeholder text

Clarify that this synthetic transcript path is triggered by attachment size,
not by a silence/no-speech detection result.

* test(media-understanding): update too-small audio placeholder expectations

* test(media-understanding): cover mixed too-small audio placeholder

* test(media-understanding): cover too-small audio context

* fix(tasks): preserve visible task title before internal context

* Revert "fix(tasks): preserve visible task title before internal context"

This reverts commit dc536fb4d3c8a01168de5d05e8562193dd68a88e.

---------

Co-authored-by: Eulices Lopez <eulices@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-26 05:14:01 +01:00
Ayaan Zaidi
bcc9fc4cf5 docs: move TTS persona changelog entry 2026-04-26 09:42:38 +05:30
Ayaan Zaidi
cc2044633c fix(tts): compose personas with agent config 2026-04-26 09:42:38 +05:30
Barron Roth
f801fe7d27 test: update provider HTTP mocks 2026-04-26 09:42:38 +05:30
Barron Roth
9975de89d1 test: fix PR CI shards 2026-04-26 09:42:38 +05:30
Barron Roth
f7c837b374 TTS: remove persona rewrite placeholder 2026-04-26 09:42:38 +05:30
Barron Roth
0594fa3c4d TTS: add provider personas 2026-04-26 09:42:38 +05:30
Peter Steinberger
80219ed1b3 fix(channels): tolerate sparse channel metadata during validation 2026-04-26 05:06:52 +01:00
likewen-tech
86328585fa fix(tasks): terminalize gateway agent run ledger
Terminalize Gateway-backed async task records from the run result while preserving aborted, failed, cancelled, and lost outcomes.\n\nThanks @likewen-tech.
2026-04-26 05:06:33 +01:00
Ayaan Zaidi
f9c8a5107c fix(cli): cap fresh session reseed size 2026-04-26 09:34:24 +05:30
Ayaan Zaidi
8559a84e4e fix(cli): bound fresh session reseed 2026-04-26 09:34:24 +05:30
Ayaan Zaidi
12e4841d96 fix(cli): preserve prompt hooks in history reseed 2026-04-26 09:34:24 +05:30
Ayaan Zaidi
0ba28c0911 docs(changelog): note CLI compaction fix 2026-04-26 09:34:24 +05:30
Ayaan Zaidi
3eff589ac0 test(cli): cover transcript compaction reseed 2026-04-26 09:34:24 +05:30
Ayaan Zaidi
dfd5940c34 fix(cli): compact persisted CLI transcripts 2026-04-26 09:34:24 +05:30
Peter Steinberger
b277eac656 fix: pin macos ssh remote url to loopback 2026-04-26 05:01:25 +01:00
Peter Steinberger
9ed11d6c49 fix: steer agents to safe gateway config flow 2026-04-26 05:00:17 +01:00
Vincent Koc
44da034516 fix(otel): add agent label to token metrics 2026-04-25 20:57:47 -07:00
Shakker
d251932fcf refactor: keep manifest contracts on plugin index 2026-04-26 04:55:12 +01:00
Vincent Koc
948c32dd33 fix(channels): lazy-load setup fallback runtime 2026-04-25 20:53:44 -07:00
Ayaan Zaidi
acd3d2b197 fix: reflect Claude CLI auth status (#71332) (thanks @neeravmakwana) 2026-04-26 09:21:06 +05:30
Ayaan Zaidi
76dc66f5fa fix(models): use synthetic auth expiry for status 2026-04-26 09:21:06 +05:30
Neerav Makwana
ad27e0069d fix(models): avoid externalizing Claude CLI auth 2026-04-26 09:21:06 +05:30
Neerav Makwana
911fcb47f1 fix(models): reflect Claude CLI auth status 2026-04-26 09:21:06 +05:30
Peter Steinberger
c9e7bfd1fc fix(mac): implement swift-log event handler 2026-04-26 04:48:43 +01:00
Peter Steinberger
29741f696a fix(feishu): transcribe inbound voice notes 2026-04-26 04:47:45 +01:00
Peter Steinberger
38e61e0046 test(plugins): drop duplicate bundle command mock 2026-04-26 04:46:05 +01:00
Peter Steinberger
540c70d166 fix(plugins): ignore bundled load path aliases 2026-04-26 04:46:05 +01:00
Shakker
42f87c07e9 docs: add model list catalog changelog 2026-04-26 04:41:51 +01:00
Shakker
26a647d4bb docs: scope manifest model list note 2026-04-26 04:41:51 +01:00
Shakker
0f27f2b351 feat: use indexed manifests for static model catalog rows 2026-04-26 04:41:51 +01:00
Shakker
469bd5f51e docs: mention manifest model list rows 2026-04-26 04:41:51 +01:00
Shakker
4a195b37d5 feat: declare deepseek manifest model catalog 2026-04-26 04:41:51 +01:00
Shakker
8749f1deb4 feat: declare moonshot manifest model catalog 2026-04-26 04:41:51 +01:00
Shakker
35171f4e47 feat: use manifest catalog rows for provider list fast path 2026-04-26 04:41:51 +01:00
Shakker
82a529aaaf feat: carry manifest catalog discovery mode 2026-04-26 04:41:51 +01:00
Peter Steinberger
9e4a0e7f3c fix(qqbot): ignore bot self-echo events 2026-04-26 04:40:53 +01:00
Peter Steinberger
e40094a9ef test(browser): add CDP snapshot Docker smoke 2026-04-26 04:40:26 +01:00
Peter Steinberger
4edf22f63f fix(acpx): avoid startup agent probes by default 2026-04-26 04:40:26 +01:00
Peter Steinberger
ed1ac2fc44 feat(browser): add CDP role snapshot fallback 2026-04-26 04:40:26 +01:00
Peter Steinberger
0ca9c4dcb0 fix(cli): preserve lazy placeholder options 2026-04-26 04:40:26 +01:00
Peter Steinberger
e74f2e1501 test: remove duplicate plugin enable mock 2026-04-26 04:39:54 +01:00
Shakker
2d68fda31f fix: defer onboarding install record commits 2026-04-26 04:39:12 +01:00
Shakker
34bd66d929 fix: keep read-only channels off setup runtime 2026-04-26 04:39:12 +01:00
Shakker
2e7635f4f9 fix: scope web provider ownership to plugin index 2026-04-26 04:39:12 +01:00
Peter Steinberger
6d4f65c9d4 docs: clarify codex runtime routing 2026-04-26 04:38:39 +01:00
Peter Steinberger
6336ed4166 fix: gate codex acp route hints 2026-04-26 04:36:26 +01:00
Peter Steinberger
b58223510c fix(providers): support zai preserved thinking 2026-04-26 04:35:50 +01:00
Peter Steinberger
844d2bd515 test: mock browser cleanup in heartbeat session tests 2026-04-26 04:33:37 +01:00
Colin Johnson
21082d2ede fix(plugins): verify bundled runtime deps installs
Verify bundled runtime dependency installs before reporting success, so a clean npm exit cannot hide packages missing from the managed runtime-deps root.

Also updates the bundle command test mock for the current plugin enable-state API.

Local proof:
- `pnpm test src/plugins/bundle-commands.test.ts`
- `pnpm test src/plugins/bundled-runtime-deps.test.ts src/commands/doctor-bundled-plugin-runtime-deps.test.ts src/plugins/loader.test.ts`
- `pnpm check:changed`

Co-authored-by: Colin <colin@solvely.net>
2026-04-26 04:32:33 +01:00
Peter Steinberger
96d90091c4 test: align task title sanitization expectation 2026-04-26 04:30:13 +01:00
Peter Steinberger
2c8c79de5c fix(tts): normalize streamed tts voice media 2026-04-26 04:28:19 +01:00
Peter Steinberger
f4e6322649 test: align runtime schema registry mock count 2026-04-26 04:25:41 +01:00
Peter Steinberger
924e132d96 test: add manifests to npm install fixtures 2026-04-26 04:22:28 +01:00
Pinghuachiu
7b943667a0 fix: expose image edit geometry flags in capability cli
Expose image edit geometry flags in the capability CLI and document the new infer options.\n\nThanks @Pinghuachiu.
2026-04-26 04:22:22 +01:00
Peter Steinberger
ee8f41f56e fix(channels): strip copied inbound metadata from replies 2026-04-26 04:21:20 +01:00
Vincent Koc
7fef13abbc docs(anthropic): note context1m param applies to Claude CLI backend
Ayaan's 28e4cd81a9 (#70863, thanks @bidadh, source from Arthur Kazemi
8abbae0101) extended params.context1m:true so the configured 1M
context window override now applies to eligible Claude CLI Opus and
Sonnet models, not only direct API calls. CHANGELOG entry covered
the change but docs/providers/anthropic.md '1M context window (beta)'
Accordion only described direct-API behavior, so Claude CLI users had
no signal the same param works for their backend. Add a sentence
inside the same Accordion.
2026-04-25 20:18:51 -07:00
Peter Steinberger
b3ac316e0b fix: preserve indexed plugin diagnostics 2026-04-26 04:17:15 +01:00
Shakker
862b39976d fix: remove managed plugin files on uninstall 2026-04-26 04:16:33 +01:00
Shakker
48ba3a4198 fix: clean migrated plugin install config 2026-04-26 04:16:33 +01:00
Shakker
f5f4477bae fix: reject manifestless plugin archives 2026-04-26 04:16:33 +01:00
Ayaan Zaidi
28e4cd81a9 fix: enable claude cli context1m window (#70863) (thanks @bidadh) 2026-04-26 08:45:59 +05:30
Ayaan Zaidi
64630e1c39 test: fix claude cli context1m fixture 2026-04-26 08:45:59 +05:30
Arthur Kazemi
8abbae0101 fix: enable claude-cli 1m context override 2026-04-26 08:45:59 +05:30
Arthur Kazemi
bb389a37d0 test: cover claude-cli context1m context-window behavior 2026-04-26 08:45:59 +05:30
Peter Steinberger
a91baa16de fix(tts): honor explicit directive providers 2026-04-26 04:14:48 +01:00
Peter Steinberger
969a3757b9 test: harden plugin registry mocks 2026-04-26 04:10:48 +01:00
Peter Steinberger
cf834e2a21 fix(tts): clean streamed directive text 2026-04-26 04:09:56 +01:00
Vincent Koc
2261918c8c fix(plugins): resolve activation plans from plugin registry 2026-04-25 20:06:06 -07:00
Peter Steinberger
6df120fb39 fix: keep internal completion wakes out of chat memory 2026-04-26 04:01:45 +01:00
Shakker
d0d93d0fde test: harden bundle index reconstruction 2026-04-26 03:58:29 +01:00
Peter Steinberger
8748ae3bb7 fix(skills): parse remote which bin maps 2026-04-26 03:58:22 +01:00
Peter Steinberger
18a638ceae test: isolate cold plugin registry metadata mocks 2026-04-26 03:57:38 +01:00
Ayaan Zaidi
a8b4be0b48 fix: unwrap nested Claude CLI results (#66819) (thanks @mraleko) 2026-04-26 08:27:33 +05:30
Ayaan Zaidi
1c77515396 fix(agents): scope Claude JSON unwrapping 2026-04-26 08:27:33 +05:30
Alec Hrdina
1b41513b3b agents/cli: scope nested result unwrapping 2026-04-26 08:27:33 +05:30
Alec Hrdina
015e39e3cf agents/cli: unwrap nested claude result json 2026-04-26 08:27:33 +05:30
Peter Steinberger
c3833f7729 fix(providers): satisfy vllm chat kwargs lint 2026-04-26 03:54:20 +01:00
Peter Steinberger
ed5276f9b9 fix(providers): keep vllm nemotron replies visible 2026-04-26 03:54:20 +01:00
Peter Steinberger
7a85c1a822 fix(tts): surface voice status and harden providers 2026-04-26 03:51:30 +01:00
Peter Steinberger
1231f21679 fix(plugins): tolerate partial manifest registry records
# Conflicts:
#	src/plugins/installed-plugin-index.ts
2026-04-26 03:50:40 +01:00
Peter Steinberger
f5812aa64d test: complete plugin install manifest fixtures 2026-04-26 03:50:40 +01:00
Peter Steinberger
0cf30b6a65 docs(tasks): document retained lost task audit 2026-04-26 03:50:40 +01:00
Likewen
de5b173546 fix(tasks): normalize task timestamps and retained lost audit
Normalize task lifecycle timestamps on create, update, and restore so startedAt/lastEventAt/endedAt cannot precede createdAt in audit-visible records.

Downgrade retained lost tasks with future cleanupAfter from audit errors to warnings while keeping expired or unstamped lost tasks as errors.

Verification: pnpm exec oxfmt --write --threads=1 src/tasks/task-registry.ts src/tasks/task-registry.test.ts src/tasks/task-registry.audit.ts src/tasks/task-registry.audit.test.ts

Verification: node scripts/test-projects.mjs src/tasks/task-registry.test.ts src/tasks/task-registry.audit.test.ts (task-registry.audit.test.ts 4 passed; task-registry.test.ts 45 passed)
2026-04-26 03:50:40 +01:00
Shakker
d955bf0ff8 fix: scope cold plugin manifests to index 2026-04-26 03:47:46 +01:00
Shakker
1a193b2d96 fix: scope cold plugin manifests to index 2026-04-26 03:47:45 +01:00
Peter Steinberger
f8a677bcfd docs: reduce changelog rebase churn 2026-04-26 03:46:31 +01:00
Peter Steinberger
0ddbae171d test: cover codex app-server subagents 2026-04-26 03:46:30 +01:00
Vincent Koc
c149de7750 fix(plugins): resolve runtime metadata fallbacks cold 2026-04-25 19:45:59 -07:00
Peter Steinberger
07877d71cd fix(control-ui): preserve optimistic messages on empty history 2026-04-26 03:45:07 +01:00
Peter Steinberger
97ae1c7c2e feat(tts): add read-latest voice command 2026-04-26 03:44:44 +01:00
Vincent Koc
2235a13dab fix(plugins): resolve capability metadata cold 2026-04-25 19:43:07 -07:00
Peter Steinberger
3989510251 docs: expand ACP agents guide 2026-04-26 03:42:44 +01:00
Peter Steinberger
e23d17da79 test: update full-suite planner expectation 2026-04-26 03:39:52 +01:00
Vincent Koc
d8ed49f651 fix(plugins): keep config alias normalization cold 2026-04-25 19:39:41 -07:00
Peter Steinberger
f0fa35082b fix: keep ACP completion prompts harness-safe 2026-04-26 03:39:24 +01:00
Vincent Koc
4fbc490fca fix(agents): resolve provider attribution metadata cold 2026-04-25 19:36:28 -07:00
Ayaan Zaidi
23fbdc1ec2 fix: allow large Claude live JSONL lines (#71897) 2026-04-26 08:06:06 +05:30
Ayaan Zaidi
09e60e496b fix(agents): allow large Claude live JSONL lines 2026-04-26 08:06:06 +05:30
Ayaan Zaidi
78e0976f93 test(agents): cover large Claude live JSONL output 2026-04-26 08:06:06 +05:30
Peter Steinberger
802a73a382 test: isolate legacy auth choice aliases 2026-04-26 03:34:11 +01:00
Vincent Koc
10763781fd fix(config): resolve plugin contracts cold 2026-04-25 19:33:56 -07:00
Vincent Koc
a0ca546997 test(qa): add local otel smoke harness 2026-04-25 19:30:46 -07:00
Vincent Koc
476bb38527 fix(setup): plan setup metadata from plugin registry 2026-04-25 19:30:20 -07:00
Peter Steinberger
72d8600eb5 test: fix plugin skills mock typing 2026-04-26 03:28:59 +01:00
Peter Steinberger
6855b33255 docs(tts): clarify WhatsApp voice-note delivery 2026-04-26 03:28:51 +01:00
Vincent Koc
bc24b547d0 fix(agents): resolve plugin skill metadata cold 2026-04-25 19:26:21 -07:00
Peter Steinberger
0796a888ae fix: tolerate partial plugin registry records 2026-04-26 03:26:11 +01:00
Peter Steinberger
9b91040053 fix(tts): route WhatsApp MP3 TTS as voice notes 2026-04-26 03:26:00 +01:00
Peter Steinberger
90cd9fce85 fix(agents): handle empty Claude stop turns 2026-04-26 03:23:16 +01:00
Vincent Koc
a44a3f9171 fix(auth): resolve plugin auth metadata cold 2026-04-25 19:22:31 -07:00
Ayaan Zaidi
bbd9702077 ci: fix Docker E2E image build 2026-04-26 07:49:04 +05:30
Vincent Koc
6afac5208a fix(secrets): resolve plugin env metadata cold 2026-04-25 19:18:30 -07:00
Peter Steinberger
c14d2b0c1f fix: harden plugin registry contribution lookup 2026-04-26 03:17:31 +01:00
Peter Steinberger
2d9a0d9cf0 fix: preserve image history while pruning replay context 2026-04-26 03:16:00 +01:00
Peter Steinberger
69e7e499b1 docs(tts): document per-agent tts config 2026-04-26 03:13:43 +01:00
Vincent Koc
690046637f fix(web): resolve provider candidates from plugin registry 2026-04-25 19:13:15 -07:00
Peter Steinberger
9b4f0779ce fix(tts): honor per-agent config in tts commands 2026-04-26 03:12:30 +01:00
Vincent Koc
6a688e33f6 docs(agents): require single-line changelog bullets
Add an explicit rule under Docs / Changelog that bullets must stay on
one line — no wrapping or continuation across multiple lines.
Justification: dedupe, PR-ref, and credit-audit tooling assumes
single-line entries, and the rest of the file is already uniform
single-line. The recent flatten pass collapsed 80 multi-line bullets
in last two releases plus Unreleased; this rule prevents that drift
from coming back through new entries.
2026-04-25 19:10:21 -07:00
Peter Steinberger
0e1f53f020 fix: clear system events on session reset 2026-04-26 03:09:15 +01:00
Vincent Koc
d65f28f962 docs(changelog): flatten 80 multi-line bullets in last two releases and unreleased
Many bullets in Unreleased, 2026.4.25 (Unreleased), 2026.4.24, and
2026.4.23 wrapped across two to five lines, mixing single-line and
multi-line entries within the same section. The repo convention is
single-line bullets — that is what every author/PR reformatter aims
at, what the dedupe and PR-ref scanners assume, and what readers
scrolling the file see in the rest of the changelog.

Reflow each multi-line bullet to a single line by joining
continuation lines on a single space and collapsing redundant
whitespace. Wording, casing, links, PR refs, and Thanks credits are
unchanged — the only edit is layout.

Skipped 2026.4.22 and earlier on purpose; this pass is scoped to
'last two releases plus unreleased' as requested.
2026-04-25 19:07:57 -07:00
Vincent Koc
e4199379ff fix(channels): resolve cold channel presence from registry 2026-04-25 19:07:05 -07:00
Peter Steinberger
94316334fe test: use agent wait for OpenAI web search smoke 2026-04-26 03:06:09 +01:00
Peter Steinberger
a6d9926d1d fix: keep acp management commands local 2026-04-26 03:02:04 +01:00
Peter Steinberger
9123c8158d test: stabilize main ci provider tests 2026-04-26 03:00:57 +01:00
Shakker
0f343ad568 fix: make plugin install config migration atomic 2026-04-26 02:56:44 +01:00
Peter Steinberger
04e08cea62 chore(tts): refresh plugin sdk api baseline 2026-04-26 02:54:13 +01:00
Peter Steinberger
0ca952cdd5 feat(tts): add per-agent voice overrides 2026-04-26 02:54:13 +01:00
Peter Steinberger
1bc9bada65 test: speed up security audit tests 2026-04-26 02:51:19 +01:00
Peter Steinberger
ec56dd3116 fix(pairing): preserve corrupt pairing stores 2026-04-26 02:50:19 +01:00
Vincent Koc
5469740170 fix(github): exempt maintainers from barnacle candidate labels 2026-04-25 18:49:44 -07:00
Shakker
105785a1be fix: preserve channel plugin install records 2026-04-26 02:48:29 +01:00
Peter Steinberger
e3be66ddda test: align plugin docker smoke with install ledger 2026-04-26 02:46:04 +01:00
Peter Steinberger
75a8f5863c test: speed up chat UI tests 2026-04-26 02:45:31 +01:00
Vincent Koc
526fd9d545 test: stabilize pty and agentic test lanes 2026-04-25 18:44:18 -07:00
Vincent Koc
d74f897c1c fix(status): keep channel status reads cold 2026-04-25 18:40:38 -07:00
Vincent Koc
839e7c98ff fix(channels): keep read-only plugin listing cold 2026-04-25 18:40:38 -07:00
Vincent Koc
e40157013f fix(diagnostics): complete early model stream closes 2026-04-25 18:40:00 -07:00
Vincent Koc
c7b336d83e docs(hooks): document new ctx.jobId field on plugin hook contexts
Scott Glover's commit 371b69b3e2 ('Expose cron jobId in plugin hook
context') added an optional jobId field on PluginHookAgentContext,
populated for cron-driven runs. The commit shipped without a docs
update or CHANGELOG entry, so plugin authors had no visible signal
that the new ctx.jobId field exists.

Surface ctx.jobId in two existing hook context references in
docs/plugins/hooks.md: the before_tool_call ctx-fields list, and the
runId/agent-lifecycle paragraph that already names ctx.runId — extend
it to note ctx.jobId on cron-driven runs and what plugins can do with
it (scope metrics, side effects, or state to a scheduled job).
2026-04-25 18:38:27 -07:00
Peter Steinberger
8ed52c1463 fix: bound configured acp binding readiness 2026-04-26 02:36:58 +01:00
Shakker
29463b9c47 fix: persist pending onboarding plugin installs 2026-04-26 02:35:04 +01:00
Vincent Koc
2495585a32 feat(diagnostics-otel): add exporter health diagnostics
Adds diagnostics-otel exporter health events and signal-specific endpoint wiring, with docs and config schema coverage.
2026-04-25 18:34:44 -07:00
Shakker
25ecb2895a fix: preserve bundle format in plugin index 2026-04-26 02:31:02 +01:00
Shakker
4e3b860e60 refactor: scope plugin capabilities to manifests 2026-04-26 02:31:02 +01:00
Shivanker Goel
a932a58e87 feat(fal): support Seedance reference video
Adds fal Seedance 2.0 reference-to-video support with model-aware reference input limits.
2026-04-26 02:30:23 +01:00
Peter Steinberger
566d2d73a3 fix: keep system events from extending session resets (#71845) 2026-04-26 02:29:44 +01:00
Peter Steinberger
1cce439c9c fix(ui): hide chat skeleton during reload 2026-04-26 02:27:04 +01:00
pashpashpash
e989f3c868 Respect retryable Codex app-server errors
Codex app-server sends retryable stream error notifications while a turn is still recovering. OpenClaw now ignores retryable app-server errors and preserves nested terminal error messages instead of replacing them with a generic fallback.
2026-04-25 18:26:27 -07:00
91wan
a35d259719 fix(acpx): isolate Codex ACP config from desktop hooks
Isolate Codex ACP launches with an OpenClaw-managed CODEX_HOME/config wrapper so global Codex desktop notify hooks do not leak into acpx sessions.\n\nValidation:\n- OPENCLAW_LOCAL_CHECK=0 OPENCLAW_VITEST_MAX_WORKERS=1 pnpm check:changed\n- pnpm test extensions/acpx/src/codex-auth-bridge.test.ts\n\nThanks @91wan.
2026-04-26 02:23:55 +01:00
Vincent Koc
8c3b1366ce chore(tokenjuice): bump bundled runtime to 0.6.3 2026-04-25 18:22:44 -07:00
Peter Steinberger
d513dc7146 fix: bootstrap gateway env proxy dispatcher
Co-authored-by: mjamiv <74088820+mjamiv@users.noreply.github.com>
2026-04-26 02:22:21 +01:00
Peter Steinberger
c43ce254e1 fix: wait for acp backend before startup reconcile 2026-04-26 02:21:16 +01:00
Peter Steinberger
00d2fbfda4 test(cron): cover delivery context edge cases 2026-04-26 02:20:39 +01:00
Peter Steinberger
e309fd485e fix(cron): preserve current delivery target context 2026-04-26 02:11:00 +01:00
Peter Steinberger
0731fc1942 test: keep packaged provider setup discoverable 2026-04-26 02:07:08 +01:00
Scott Glover
371b69b3e2 Expose cron jobId in plugin hook context 2026-04-26 02:06:48 +01:00
Peter Steinberger
264d6f6aef docs: note GitHub search boolean fallback 2026-04-26 02:02:35 +01:00
Shakker
921ffad7c7 fix: commit pending plugin install records in config flows 2026-04-26 01:59:48 +01:00
Peter Steinberger
87142b5fb1 test: narrow live Docker package script changes 2026-04-26 01:59:12 +01:00
Peter Steinberger
57f05128cb docs: clarify Crestodian rescue audit metadata 2026-04-26 01:56:59 +01:00
pashpashpash
5404bbbb71 Avoid duplicate generated media attachments
Generated media can be produced in intermediate tool results before the assistant chooses which assets to share in its final reply. This change keeps those intermediate files from being appended a second time when the final reply already names the assets to deliver, and tightens the media directive parsing around unsafe or ambiguous URLs.
2026-04-25 17:56:29 -07:00
Peter Steinberger
099d18f432 test: narrow live Docker ACP changed gate 2026-04-26 01:48:33 +01:00
Peter Steinberger
1fe0e6fc4a fix(status): clarify tailscale exposure state 2026-04-26 01:47:03 +01:00
Vincent Koc
2f6615d2ee fix(triage): extract barnacle workflow 2026-04-25 17:43:08 -07:00
Peter Steinberger
5b80d0c15e feat(tts): add Azure Speech provider
Co-authored-by: Leon Chui <84605354+leonchui@users.noreply.github.com>
2026-04-26 01:42:51 +01:00
Peter Steinberger
753ccf615c fix: preserve LM Studio quant model refs (#71486) 2026-04-26 01:41:08 +01:00
Bartok9
5bb78ea7ed fix(model): preserve LM Studio '@' quant suffixes in model name resolution
stripModelProfileSuffix() in providers.ts naively truncated model names at
the first '@', discarding quant variants like @iq3_xxs, @iq4_xs, @q4_k_xl
that LM Studio uses to distinguish quantization levels.

This caused two user-facing bugs (fixes #71474):
1. /model lmstudio/qwen3.6-27b@iq3_xxs → 'model not allowed: lmstudio/qwen3.6-27b'
2. API requests sent truncated model name → LM Studio picked a random quant

Changes:
- Replace the naive indexOf('@') strip in providers.ts with
  splitTrailingAuthProfile() which already handles quant suffixes
- Extend the quant-suffix regex (q\d+...) to also match importance-
  quantization tags (iq3_xxs, iq4_xs, ...) via i?q\d+ pattern
- Add tests for @iq* quant suffixes and auth-profile-after-iq combos
2026-04-26 01:41:08 +01:00
Shakker
94ceb2bbe9 test: fix doctor symlink cleanup 2026-04-26 01:38:21 +01:00
Shakker
140ac29172 fix: defer onboarding plugin install records 2026-04-26 01:38:21 +01:00
Peter Steinberger
5edfbca6e5 fix(ci): hide configured workspace setup candidates 2026-04-26 01:34:01 +01:00
Peter Steinberger
78cfd2a512 fix: seed gateway control UI origins from runtime bind 2026-04-26 01:33:43 +01:00
Peter Steinberger
81c2a1de26 test: add Droid ACP bind Docker lane 2026-04-26 01:31:27 +01:00
Peter Steinberger
650dc59b6f fix: skip checkpoint transcripts in memory dreaming 2026-04-26 01:30:50 +01:00
Peter Steinberger
b565e6e963 fix(ci): repair plugin registry test lanes 2026-04-26 01:29:47 +01:00
Shakker
e7c131d6de fix: roll back plugin index for update channel writes 2026-04-26 01:25:26 +01:00
Val Alexander
41282fcb13 refactor(control-ui): keep quick settings personal card balanced (#71585) 2026-04-25 19:23:43 -05:00
Peter Steinberger
e6ee4d6e68 fix(browser): preserve tabs across target swaps 2026-04-26 01:21:59 +01:00
Vincent Koc
f3accc753c feat(plugins): add before agent finalize hook (#71765) 2026-04-25 17:21:17 -07:00
Vincent Koc
727e0e013e fix(triage): classify low-signal prs 2026-04-25 17:19:50 -07:00
Shakker
be1d656514 fix: roll back plugin index on config write conflicts 2026-04-26 01:13:29 +01:00
Peter Steinberger
ca0232ff0e fix(bonjour): bound stuck advertiser restarts 2026-04-26 01:11:53 +01:00
Peter Steinberger
3a4325b285 fix: prevent duplicate channel plugin tools 2026-04-26 01:06:11 +01:00
Shakker
6ed642a86d fix: rank plugin duplicates with pending install records 2026-04-26 01:03:13 +01:00
Shakker
569d489383 fix: preserve install records during registry refresh 2026-04-26 01:03:13 +01:00
Shakker
babbad81a9 fix: preserve plugin install records without manifests 2026-04-26 01:03:13 +01:00
Shakker
1848d0dd38 fix: block config writes when plugin install migration fails 2026-04-26 01:03:13 +01:00
Shakker
194c26bcd2 fix: migrate shipped plugin install config records 2026-04-26 01:03:13 +01:00
Shakker
14e2760835 docs: fix plugin reference indentation 2026-04-26 01:03:13 +01:00
Shakker
0a41fc3ef8 test: expect plugin install index records on refresh 2026-04-26 01:03:13 +01:00
Shakker
dcf7f8f44c fix: model plugin index records in cli tests 2026-04-26 01:03:13 +01:00
Shakker
1d141c39a9 docs: update plugin index changelog entries 2026-04-26 01:03:13 +01:00
Shakker
df7348e586 fix: guide config users to plugin commands 2026-04-26 01:03:12 +01:00
Shakker
ebbefd6903 fix: type plugin install config strip test 2026-04-26 01:03:12 +01:00
Shakker
b018272fa1 fix: strip plugin install records before config validation 2026-04-26 01:03:12 +01:00
Shakker
56f4264f1b fix: keep plugin audit check ids stable 2026-04-26 01:03:12 +01:00
Shakker
c79399dc68 fix: preserve plugin index records in update flows 2026-04-26 01:03:12 +01:00
Shakker
9e086d6ed8 refactor: split plugin index record reader 2026-04-26 01:03:12 +01:00
Shakker
57c4279c4a fix: remove unused plugin index import 2026-04-26 01:03:12 +01:00
Shakker
37ce39b5c5 docs: describe plugin install index store 2026-04-26 01:03:12 +01:00
Shakker
d0dafd9dca refactor: remove plugin install config fallback 2026-04-26 01:03:12 +01:00
Shakker
c19f8a5223 refactor: consolidate plugin install index store 2026-04-26 01:03:12 +01:00
Peter Steinberger
f8123e4b68 fix(ci): stabilize media and gateway tests 2026-04-26 01:01:08 +01:00
Peter Steinberger
8e12c24d17 fix: prefer native codex app-server controls 2026-04-26 00:59:02 +01:00
Peter Steinberger
77d04a39d8 fix(feishu): separate synthetic ids from reply targets 2026-04-26 00:57:38 +01:00
Peter Steinberger
e918e5f75c fix: hide runtime context from submitted prompts 2026-04-26 00:57:04 +01:00
pash-openai
edb618c6c4 Manage the Codex app-server binary in OpenClaw (#71808)
* Manage Codex app-server binary

* Use plugin deps for Codex app-server binary

* Stabilize media model registry test

* Exclude checkpoint transcripts from memory ingestion
2026-04-25 16:51:14 -07:00
Vincent Koc
fc334cda13 chore(pr-triage): route low-signal cleanup to ClawHub 2026-04-25 16:49:15 -07:00
Vincent Koc
7741dbb759 docs: split OpenTelemetry export into its own page under gateway
Logging.md had grown to 487 lines with ~300 lines dedicated to
OpenTelemetry export — wire protocol, full metric/span catalog, env
vars, captureContent shape, sampling, the diagnostic event catalog,
and protocol notes — leaving the genuine logging overview buried
behind exporter reference material.

Move the OTEL surface to a dedicated page and slim logging.md to a
focused logs overview:

- Add docs/gateway/opentelemetry.md (OpenTelemetry export). Same
  content reorganized: how it fits together, quick start, signals,
  configuration reference + env vars table, privacy/captureContent,
  sampling/flushing, full metric and span catalog, diagnostic event
  catalog, no-exporter mode, diagnostics flags pointer, disable.
- docs/logging.md: drop the OTEL section in favor of a short
  'Diagnostics and OpenTelemetry' summary that cross-links the new
  page and the diagnostics-flags page. Drops 273 lines net. Also
  drops the redundant body H1, retitles to 'Logging' (was 'Logging
  overview' which mismatched sidebar usage), and refreshes the
  Related list.
- docs/docs.json: insert gateway/opentelemetry into the
  'Health and diagnostics' sidebar group, reorder pages so the user-
  facing health/run pages come before exporter/internals pages, and
  put logging next to opentelemetry where readers naturally
  associate them.
- docs/gateway/diagnostics.md, docs/gateway/logging.md,
  docs/gateway/configuration-reference.md: cross-link the new page
  and sentence-case stale Title-Cased Related entries on
  diagnostics.md.
2026-04-25 16:46:53 -07:00
Peter Steinberger
a1090b6043 fix(feishu): accept v2 card action callbacks 2026-04-26 00:41:16 +01:00
Peter Steinberger
12c16576cd fix: gate acp spawn affordances 2026-04-26 00:30:27 +01:00
Vincent Koc
d228463120 fix(onboarding): refresh plugin registry after plugin installs 2026-04-25 16:27:56 -07:00
Peter Steinberger
435be06cde test(exec): cover control ui approval turn-source resolution 2026-04-26 00:27:01 +01:00
Peter Steinberger
41b27024bb docs(gateway): clarify backend RPC pairing 2026-04-26 00:26:35 +01:00
Vincent Koc
d74b6359fd fix(channels): refresh plugin registry after on-demand installs 2026-04-25 16:22:14 -07:00
MrBrain
28497515fe fix(qqbot): schedule reminders through cron gateway (#70937)
* fix(qqbot): schedule reminders through cron gateway

* fix(qqbot): update reminder cron instruction

* fix(qqbot): schedule reminders directly (#70937) (thanks @GaosCode)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-26 00:15:28 +01:00
Vincent Koc
73cacebac3 fix(plugins): normalize registry migration env flags 2026-04-25 16:12:01 -07:00
Peter Steinberger
c2ea0ce5a9 docs: update changelog for memory fixes 2026-04-26 00:11:35 +01:00
Peter Steinberger
1c6911c01f fix: ignore compaction checkpoints in session usage 2026-04-26 00:11:35 +01:00
Peter Steinberger
956cb1c7db fix: keep local embedding batches from flooding providers 2026-04-26 00:11:35 +01:00
Peter Steinberger
3f90005e56 build: bump bundled acpx to 0.6.1 2026-04-26 00:11:05 +01:00
Peter Steinberger
6b0c72bec8 fix(image): resolve provider-prefixed configured models
Closes #33185
2026-04-26 00:08:27 +01:00
EVA
2c35a6e599 [codex] Consolidate RuntimePlan and Harness V2 package (#71722)
* refactor: centralize runtime plan policy surface

* refactor: route embedded attempts through runtime plan

* feat: add agent harness v2 lifecycle adapter

* docs: document agent harness runtime plan

---------

Co-authored-by: Eva <eva@100yen.org>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-25 16:07:04 -07:00
Peter Steinberger
114c9a2f3e test: stabilize cron mcp cleanup docker smoke 2026-04-25 23:51:40 +01:00
Peter Steinberger
76a0abc768 fix(agents): keep queued announces session-only without route 2026-04-25 23:49:06 +01:00
Peter Steinberger
496d90c3b5 ci: split auto-reply shard timing 2026-04-25 23:47:00 +01:00
Rui Xu
1531123d35 feat(tts): add BytePlus Seed Speech provider
Add Volcengine/BytePlus Seed Speech as a bundled TTS provider with current API-key auth, legacy AppID/token fallback, native Ogg/Opus voice-note output, and MP3 audio-file output.

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-25 23:46:04 +01:00
Peter Steinberger
b1b29a8fc2 fix: stabilize remote skill node probes 2026-04-25 23:42:02 +01:00
Peter Steinberger
e4bfc8066e fix(openai): extend Azure image timeout
Closes #71705
2026-04-25 23:34:18 +01:00
Peter Steinberger
e640c0a95f fix(gateway): decouple backend RPC from CLI pairing 2026-04-25 23:23:52 +01:00
zhang-guiping
91adb69c57 fix(image): resolve configured image models 2026-04-25 23:19:28 +01:00
Peter Steinberger
8f78932059 test: harden QA cleanup and update preflight 2026-04-25 23:16:30 +01:00
Peter Steinberger
81a41fe5be test: retry cli backend live cleanup 2026-04-25 23:10:32 +01:00
Peter Steinberger
309f7f1873 test(ui): split chat avatar render coverage 2026-04-25 23:07:44 +01:00
Peter Steinberger
cf303b3101 fix(cli): trim plugin preloads for setup-safe commands 2026-04-25 23:06:05 +01:00
Peter Steinberger
8d08e86f42 fix(gateway): keep diagnostic probes non-mutating 2026-04-25 23:02:39 +01:00
Peter Steinberger
bd796d1c85 docs(plugins): clarify local dependency installs 2026-04-25 22:59:09 +01:00
RoomWithOutRoof
be51c98c5d fix(onboarding): scope video-only provider auth choices 2026-04-25 22:53:00 +01:00
Peter Steinberger
ce364121aa test(ui): split tool card render coverage 2026-04-25 22:49:25 +01:00
Peter Steinberger
f1b1c3dc99 chore: update workspace dependencies 2026-04-25 22:48:44 +01:00
Gustavo Madeira Santana
d5166718bc test(matrix): cover destructive E2EE backup recovery flows (#71311)
Merged via squash.

Prepared head SHA: fd5fc06007
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-04-25 17:48:18 -04:00
Peter Steinberger
cbe5515b70 fix(plugins): force dependency installs local 2026-04-25 22:46:50 +01:00
Peter Steinberger
1dfa52d071 test(i18n): load registry locale fixtures concurrently 2026-04-25 22:43:17 +01:00
Peter Steinberger
f62a054ef1 perf(ui): split chat role normalization imports 2026-04-25 22:43:16 +01:00
Peter Steinberger
265b97bbba fix(cli): avoid plugin preload for agent bindings 2026-04-25 22:38:30 +01:00
Peter Steinberger
9a2dfe0c7e docs: update changelog for Discord triage fixes 2026-04-25 22:34:43 +01:00
Peter Steinberger
f731e3754c fix: lazy-load Microsoft Edge TTS runtime 2026-04-25 22:34:43 +01:00
Peter Steinberger
ce884a8dae fix: keep agents list JSON config-only 2026-04-25 22:34:43 +01:00
Peter Steinberger
b721f1dbad fix: update Ollama web search endpoint 2026-04-25 22:34:43 +01:00
Cale Shapera
0bcb4c95c1 feat(tts): add Inworld speech provider (#55972)
Adds the bundled Inworld speech provider with docs, config surface, SSRF-guarded fetches, directive overrides, native voice-note/telephony output coverage, and live `.profile` verification.

Co-authored-by: cshape <cshape@users.noreply.github.com>
2026-04-25 22:33:21 +01:00
Peter Steinberger
167588cb4f test(infra): import diagnostic duplicate from source url 2026-04-25 22:19:09 +01:00
Peter Steinberger
9d22061e3e test(discord): mock message process dependencies narrowly 2026-04-25 22:19:09 +01:00
Peter Steinberger
8a731c1ef7 perf(plugin-sdk): add narrow outbound send deps entry 2026-04-25 22:19:09 +01:00
Aamir Jawaid
969f8bfd9f docs(msteams): add Teams CLI setup instructions (#71747)
* docs(msteams): add Teams CLI setup instructions

Replace manual Azure Bot setup as primary path with
@microsoft/teams.cli workflow. Manual steps collapsed
into <details> blocks for users who can't use the CLI.

* docs(msteams): fix devtunnel instructions to use persistent tunnels

Use devtunnel create + host for stable URLs across sessions
instead of throwaway tunnels that change each time.

* docs(msteams): address PR feedback

- Remove "Abandon all hope" quote (showed as net-addition in diff)
- Add preview disclaimer for @microsoft/teams.cli
- Add security note for --allow-anonymous devtunnel flag
- Clarify where to find teamsAppId from create output
- Link to official devtunnel getting started guide

* docs(msteams): fix oxfmt formatting

* docs(msteams): clarify install step references create prompt

* docs(msteams): drop --env flag, use terminal output instead

Avoids writing secrets to a file that could be accidentally committed.

* docs(msteams): remove redundant H1, match other channel docs
2026-04-25 14:18:09 -07:00
kevinlin-openai
289ed9830a Add TUI context mode selector (#71760)
Co-authored-by: kevinlin-openai <kevin@dendron.so>
Co-authored-by: Codex <noreply@openai.com>
2026-04-25 17:16:03 -04:00
Sebastien Tardif
ea4da7dfcc Add startup progress indicators (#71720)
* Add startup progress indicators

* Narrow startup progress scope

* Revert startup spinner delay to immediate feedback

* Improve install.sh progress feedback for quiet steps

* Show progress for installer download phases
2026-04-25 17:16:00 -04:00
Peter Steinberger
8f1a214a23 fix: resolve oneshot ACP identities before close 2026-04-25 22:15:52 +01:00
Shakker
cbfc0ddfd1 fix: preserve disabled plugin registry migration 2026-04-25 22:14:53 +01:00
Peter Steinberger
7d343b0b10 fix(plugins): resolve bundled channel doctor metadata from package root 2026-04-25 22:13:04 +01:00
Peter Steinberger
20223e02d9 fix(plugins): anchor runtime dependency installs 2026-04-25 22:12:26 +01:00
Peter Steinberger
0f58a6597d test: extend Windows Parallels agent turn timeout 2026-04-25 22:11:55 +01:00
Ted Li
8e83e52213 fix(memory-core): skip stale dreaming recall sources (#71695)
* fix(memory-core): skip stale dreaming recall sources

* fix(memory-core): parallelize live recall filtering
2026-04-25 17:10:38 -04:00
Yao
fbefbf05bd fix(active-memory): enforce timeoutMs as hard deadline via Promise.race (#71687)
Wrap runRecallSubagent() with Promise.race so maybeResolveActiveRecall
returns a timeout result at the configured timeoutMs even when the
embedded run has not cooperatively checked the abort signal. Late
subagent rejections are caught silently to prevent unhandled promise
errors.

Fixes #71629
2026-04-25 17:10:34 -04:00
Mara 🌿
7f5789575e fix(memory-wiki): skip bridge pruning when memory-core is not loaded (#71764)
When memory-core plugin is not registered (e.g. CLI context),
listActiveMemoryPublicArtifacts returns an empty array. The previous code
would then call pruneImportedSourceEntries with an empty activeKeys Set,
which removes ALL bridge-imported entries.

Now checks getMemoryCapabilityRegistration() instead of relying on artifact
count as a proxy, correctly distinguishing between 'plugin not loaded' and
'plugin loaded with no artifacts'.

Fixes #68373
2026-04-25 17:10:31 -04:00
Poo-Squirry
a1cb8d50ba fix: allow route bindings to override DM session scope (#71750)
Co-authored-by: 따온이네 맥북프로 <tulisy@ttaon-ine-ui-MacBookPro.local>
2026-04-25 17:08:59 -04:00
pashpashpash
bf7d156bb0 Bound native hook permission fingerprints (#71758)
* fix: bound native hook permission fingerprints

* fix: address native hook fingerprint review

* test: isolate native jiti runtime assertions
2026-04-25 17:08:56 -04:00
hcl
4a72e1b990 fix(process): skip kill-tree group kill when child wasn't detached (#71662) (#71681)
* fix(process): skip kill-tree group kill when child wasn't detached (#71662)

When the supervisor spawns a child with detached:false (service-managed
runtime under launchd/systemd), the child shares the gateway's process
group. On session abort or SIGKILL, killProcessTree was unconditionally
issuing process.kill(-pid, 'SIGTERM') — which targets the entire process
GROUP (negative pid is POSIX group-kill semantics) and therefore
SIGTERMs the gateway parent along with the child.

Reporter saw this on macOS (LaunchAgent + KeepAlive=true): aborting a
claude-cli/claude-opus-4-7 session caused the gateway to receive
SIGTERM, then auto-restart, dropping all in-flight sessions. Switching
the primary model to a non-cli provider eliminated it because the
non-cli paths don't go through this kill-tree call. Did not occur on
Linux VPS where the gateway runs detached, because there
useDetached === true and the child got its own process group.

Fix:
- killProcessTree now accepts opts.detached?: boolean. When detached:false,
  killProcessTreeUnix skips the `-pid` group-kill and goes straight to
  direct-pid SIGTERM/SIGKILL. Group-kill default (detached:true) is
  preserved so all existing callers behave exactly as before.
- supervisor/adapters/child.ts:286 now threads the spawn-time `useDetached`
  flag into killProcessTree, so the kill-tree path matches the spawn-time
  detachment decision (line 45 of the same file already computes
  useDetached = process.platform !== 'win32' && !isServiceManagedRuntime()).

Tests:
- new: detached:false skips group kill and uses direct pid SIGTERM only.
- new: default behaviour (detached:true) still uses group kill (regression
  guard so the existing test case isn't accidentally weakened).

Existing tests still pass (6/6 in kill-tree.test.ts). Lint clean.

Out of scope: other killProcessTree callers (mcp-stdio-transport,
bash-tools.process, etc.) keep the default group-kill behaviour because
those processes are typically detached from the gateway. Only the
supervisor/adapters/child.ts path threads `detached` through, since it's
the path that knows whether the child was actually spawned detached.

* fixup(process): also gate kill-tree group-kill on the no-detach spawn fallback (#71662)

Greptile review on the original PR caught a P1 gap: when
spawnWithFallback's initial detached spawn fails and it retries with the
no-detach fallback (label: "no-detach", options.detached: false), the
child runs detached:false but my variable useDetached was still true.
The kill closure then passed `detached: useDetached` = true to
killProcessTree, which still group-killed the gateway — same bug, just
on the fallback path.

Compute the actual detachment as
`useDetached && !spawned.usedFallback` after spawn returns, and pass
that through. This closes the gap: the kill path now correctly skips
group-kill in BOTH:
1. Service-managed runtime (useDetached=false from the start, original case)
2. Detached-spawn fallback to no-detach (useDetached=true at intent
   time but spawned.usedFallback=true)

Tests:
- existing 'uses process-tree kill for default SIGKILL' updated to
  assert the new {detached} option is forwarded.
- new: passes detached:false to killProcessTree when spawn fell back.
- new: passes detached:false in service-managed mode (regression guard
  for the original fix).

11/11 tests pass in child.test.ts. 6/6 in kill-tree.test.ts.
2026-04-25 17:08:53 -04:00
Evgeniy
1841dd9977 fix(subagent-announce): defer drain while parent session is busy (#71706)
When a subagent finishes while its parent main session is still running
(executing tools or awaiting model output), the announce queue would
follow the configured debounce and immediately attempt to deliver the
completion event back into the parent session via callGateway. The
gateway treats the parent as busy and the announce can either get
buffered until the next external user message or surface only as a
delayed echo, breaking the natural sessions_spawn -> sessions_yield
workflow where the parent expects the result to arrive as the next
turn.

This change adds an optional shouldDefer hook on the announce queue
state. The delivery layer wires it to the existing requester session
activity probe (resolveRequesterSessionActivity), so while the parent
session is still active the drain loop sleeps for max(250ms,
debounceMs) and re-checks instead of pushing the announce. As soon as
the parent goes idle, the queue drains normally.

- Plumbs shouldDefer through getAnnounceQueue / enqueueAnnounce.
- Skips drain step in scheduleAnnounceDrain when shouldDefer says the
  target is still busy, with a bounded re-check sleep.
- Updates maybeQueueSubagentAnnounce to pass the activity probe.
- Adds a unit test that holds drain while parent is busy and resumes
  when it goes idle.

No behavior change for callers that do not pass shouldDefer.
2026-04-25 17:08:50 -04:00
sudhindrat
ca1a6e29cb test(config): cover allowConversationAccess in plugin hooks schema validation (#71621) (#71679)
* fix(model-ref): re-add nvidia/ prefix in normalizeStaticProviderModelId (#71552)

* fix(test): use nvidia-prefixed model fixture for double-prefix guard

* test(config): cover allowConversationAccess in plugin hooks schema validation (#71621)

---------

Co-authored-by: Sudhindra Tatti <sudhi@sudhindras-mini.lan>
2026-04-25 17:08:07 -04:00
Mara 🌿
4038f734f7 fix(memory-core): add runtime cron service fallback for dreaming reconciliation (#71694)
* fix(memory-core): add runtime cron service fallback for dreaming reconciliation

When the cron service is unavailable during gateway_start (e.g., due to
a startup timing race or deferred initialization), the startupCronSource
is captured as null and never refreshed. All subsequent runtime
reconciliation attempts fail with 'cron service unavailable', even when
the cron service is fully operational.

This adds a fallback path in the runtime reconciliation that attempts to
obtain the cron service from the plugin API runtime when the startup
capture was null. This handles the case where the cron service becomes
available after the initial startup event.

Fixes #67362

* fix(memory-core): hold gateway context for runtime cron resolution

The previous attempt tried to access api.runtime.cron which doesn't exist
on the PluginRuntime type. The cron service is only accessible through
PluginHookGatewayContext.getCron().

This fix stores the gateway context from the gateway_start event and uses
it to retry cron resolution at runtime when the initial capture was null.
This handles the race condition where the cron service isn't available
during gateway_start (250ms deferred init) but is ready later.

Also refreshes the startupCron capture when the runtime retry succeeds,
so subsequent reconciliation calls resolve immediately.

Addresses review feedback on #71694
2026-04-25 17:07:45 -04:00
hcl
a97fe41a9e perf(cli): skip plugin load on agents list --json (#71739) (#71746)
Reporter measured `agents list --json` at ~7-9s on a fast host (~11s in
container) on 2026.4.23, while peer `--json` commands like
`channels list`, `cron list --all`, and `sessions ... --all-agents`
stay sub-second. Their cold-call dashboard endpoint dropped from 27s to
~2s after a local dist patch — they could even retire the 5-min cache
TTL workaround they had shipped to dodge it.

Root cause: `agents list` inherits `loadPlugins: 'always'` from the
parent `agents` policy in command-catalog, then `agentsListCommand`
calls `buildProviderStatusIndex(cfg)` unconditionally — both paths
trigger the bundled-extension import waterfall (~60+ extension index.js
modules).

`channels list` already uses `loadPlugins: 'never'` and proves the
shape is right; this PR matches that shape with the safer `text-only`
variant so human invocations are unchanged.

Two-line fix per reporter:

1. `src/cli/command-catalog.ts` — opt agents list into `text-only`,
   the same plugin-preload policy bucket that already exists. Plugin
   preload runs for human text output, skips for `--json`.

2. `src/commands/agents.commands.list.ts` — skip
   `buildProviderStatusIndex` (and the per-summary provider
   enrichment loop) when `opts.json`. Provider info is only rendered
   in human text output via `formatSummary`, so dropping it from JSON
   has no observable effect on existing callers that consume `id`,
   `name`, `model`, `bindings`, `isDefault`, `identity*`, `workspace`,
   or `agentDir`. `routes` is config-derived and continues to be set
   in both modes.

Tests:
- new assertion in command-startup-policy.test.ts: `agents list` with
  jsonOutputMode:true now resolves to `loadPlugins: false` (was
  effectively `true` via the parent `agents` 'always' policy).
- existing assertion that human (jsonOutputMode:false) still triggers
  plugin load is preserved verbatim.

6/6 tests pass. Lint clean.

Out of scope:
- `--bindings` flag opt-in for restoring providers in JSON output:
  worth adding later if any consumer needs it; reporter said dashboard
  consumers don't.
- Broader plugin-discovery cache work (#67040, #71690) which addresses
  the same family of cold-start cost.
2026-04-25 17:07:42 -04:00
sudhindrat
f92a8ae9f3 fix(model-ref): re-add nvidia/ prefix in normalizeStaticProviderModelId (#71552) (#71660)
* fix(model-ref): re-add nvidia/ prefix in normalizeStaticProviderModelId (#71552)

* fix(test): use nvidia-prefixed model fixture for double-prefix guard

---------

Co-authored-by: Sudhindra Tatti <sudhi@sudhindras-mini.lan>
2026-04-25 17:07:39 -04:00
Peter Steinberger
2febe72108 fix: isolate ACP spawned runs 2026-04-25 22:06:53 +01:00
Seungwoo hong
63fac653ed fix(talk): Talk Mode TTS improvements for CJK languages (#53553)
* feat(talk): add distinct system sounds for each Talk Mode phase

Play a short system sound on phase transitions to give the user
audible feedback:
- thinking: Tink
- speaking: Pop
- listening (after speech interrupted): Bottle
- listening (after thinking): Submarine

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

* feat(talk): add right Shift key to interrupt Talk Mode speech

Add TalkSpeechInterruptMonitor — a dedicated global key monitor that
listens for right Shift (keyCode 60) to interrupt Talk Mode speech.
Independent of Push-to-Talk, so it works even when PTT is disabled.

Stops only the current response; the next conversation cycle
continues normally via sendAndSpeak's resumeListeningIfNeeded flow.

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

* feat(talk): increase silence detection timeout for CJK locales

Korean, Japanese, and Chinese speakers need longer pauses between
phrases. When the app locale is CJK, enforce a minimum 2000ms
silence window (vs the default 1500ms) to avoid premature
transcript submission.

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

* fix(talk): remove force-unwraps and log CJK silence clamp in reloadConfig

Replace non-idiomatic force-unwraps (cfg.voiceId!, cfg.modelId!) with
safe flatMap unwrapping, and add an info log when CJK locale clamps the
silence timeout so the override is observable in diagnostics.

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

* feat(talk): add settings toggle to mute phase-transition sounds

Add a "Play phase-transition sounds" checkbox to Voice Wake settings.
When disabled, Talk Mode phase transitions (Tink/Pop/Bottle/Submarine)
are silent. Defaults to enabled to preserve existing behavior.

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

* feat(talk): add toggle for Right Option speech interrupt

Add a "Press Right Option to stop speech" checkbox to Voice Wake
settings. Also change the interrupt key from right Shift to right
Option (keyCode 61) to avoid conflicts with typing.
Defaults to enabled to preserve existing behavior.

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

* fix(talk): disable Push-to-Talk while Talk Mode is active

Talk Mode and Push-to-Talk both use the right Option key (keyCode 61).
Disable PTT when Talk Mode is enabled to prevent conflicting handlers,
and restore PTT when Talk Mode is disabled.

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

* fix(talk): show info when PTT is paused during Talk Mode

Display a footnote under the Push-to-Talk toggle when both PTT and
Talk Mode are enabled, explaining that PTT is paused while Talk Mode
is active and resumes when Talk Mode is turned off.

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

* fixup: SwiftFormat lint on TalkModeController phase sound switch

Resolves macos-swift CI lint failures introduced by Korean
comment formatting in 'feat(talk): add distinct system sounds for each Talk Mode phase'.
- Collapse consecutive spaces between sound name and comment
- Move floating comments above the listening case expression so
  they're at the correct indent level

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

---------

Co-authored-by: hongsw <hongsw@hongswui-Macmini.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Fabian Williams <fabian@adotob.com>
2026-04-25 17:05:51 -04:00
Fabian Williams
d6a179bcd9 fix(macos): SwiftFormat wrapMultilineStatementBraces on 2 main files (#71763)
Pre-existing lint errors blocking the macos-swift CI check on every
PR that touches Swift code. Apply the wrapMultilineStatementBraces
rule by moving the opening brace of the multi-line if/else if to its
own line.

- apps/macos/Sources/OpenClaw/ExecAllowlistMatcher.swift:17
- apps/macos/Sources/OpenClaw/ExecApprovals.swift:621

Pure formatting change; no behavioral effect.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 17:02:13 -04:00
Vincent Koc
cdcc457d2e test(i18n): make registry test sparse-safe 2026-04-25 13:57:07 -07:00
Vincent Koc
74059aaa29 fix(secrets): honor plugin install ledger for web fetch discovery 2026-04-25 13:55:00 -07:00
Peter Steinberger
9e9e024188 docs: clarify ACP model override support 2026-04-25 21:52:36 +01:00
周辉
23a818fa2d docs: enforce background mode & direct completion in coding-agent (#53585) 2026-04-25 16:50:50 -04:00
Vincent Koc
70d1871db7 fix(secrets): honor plugin install ledger in web search risk 2026-04-25 13:50:44 -07:00
Peter Steinberger
90218364b4 test: update bundled setup-entry docker prompt 2026-04-25 21:47:24 +01:00
Peter Steinberger
9d2254be06 test(agents): make Gemini MCP smoke local 2026-04-25 21:45:57 +01:00
Peter Steinberger
17a213f080 refactor(agents): split bundle MCP CLI adapters 2026-04-25 21:45:57 +01:00
Peter Steinberger
bf672d1f2c test: harden Parallels smoke timing 2026-04-25 21:41:55 +01:00
Peter Steinberger
b49d499b45 fix: stabilize native Windows onboarding 2026-04-25 21:41:47 +01:00
Peter Steinberger
dcfd5913fd refactor(agents): share bundle MCP config merging 2026-04-25 21:36:22 +01:00
Peter Steinberger
c3a3ceefbe fix(plugins): keep mirrored runtime deps on staged root 2026-04-25 21:36:06 +01:00
pashpashpash
34fb96622e Support MCP hooks in the Codex harness (#71707)
* codex harness mcp hook parity

* tighten codex hook parity floor

* prove security-style mcp hook blocking

* bound native hook relay key handling

* clarify permission relay defers to provider

* harden native hook relay approvals

* fix(agents): bound native hook relay JSON work budget

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-25 21:35:47 +01:00
Peter Steinberger
e2fd3dcee9 fix(google): emit opus voice-note tts 2026-04-25 21:33:33 +01:00
Tars
d5b6667823 fix(minimax): enable portal music and video generation 2026-04-25 21:30:10 +01:00
Peter Steinberger
a8e25d9307 docs: guard maintainer-owned triage 2026-04-25 21:26:05 +01:00
Peter Steinberger
607bc53ff3 fix: import missing shell env keys 2026-04-25 21:23:45 +01:00
Peter Steinberger
6a7b76e119 fix(acp): guard sessions_spawn runtime targets 2026-04-25 21:23:24 +01:00
Vincent Koc
20c3177281 fix(plugins): satisfy setup cli fallback lint 2026-04-25 13:22:29 -07:00
Vincent Koc
07796c9fb5 fix(plugins): use registry for setup cli fallback 2026-04-25 13:22:29 -07:00
Peter Steinberger
4069c81b15 test: guard bundled runtime deps against home npm projects 2026-04-25 21:16:53 +01:00
Peter Steinberger
afabbc01b2 fix: keep bundled runtime deps in managed stage 2026-04-25 21:08:16 +01:00
Blockchain Oracle
b40df76c18 fix(cli-runtime): translate MCP transports for CLI backends
Translate OpenClaw `mcp.servers.*.transport` entries into the downstream Claude/Gemini CLI `type` field before writing bundle MCP config.

Also keeps the plugin-sdk bundled-entry fast-path fixture unambiguously CommonJS on Node 24 after runtime-deps mirroring adds a `type: "module"` boundary.

Co-authored-by: Blockchain-Oracle <ajweb3dev@gmail.com>
2026-04-25 21:08:04 +01:00
Peter Steinberger
02f3e9cfa2 fix(talk): honor configured speech locale 2026-04-25 21:05:24 +01:00
Peter Steinberger
8fb24ac3ce test: cover Google telephony TTS private network opt-in 2026-04-25 21:02:06 +01:00
Rohan Shiralkar
cab66c5556 fix(google): honor models.providers.google.request.allowPrivateNetwork in TTS
Image generation and media understanding both thread the
sanitized models.providers.google.request config (including
allowPrivateNetwork) into resolveGoogleGenerativeAiHttpRequestConfig.
Speech synthesis omitted that arg, so TTS always saw
allowPrivateNetwork: false regardless of config — silently falling
back to a different speech provider when the configured Google TTS
endpoint resolved to a private/internal IP (proxies, custom backends,
test mocks).

Mirror the image-generation-provider pattern: thread request through
synthesizeGoogleTtsPcm at both call sites (synthesize and
synthesizeTelephony).

Follow-up to #67216.
2026-04-25 21:02:06 +01:00
Peter Steinberger
6e1017d88a fix: allow native app metadata reconnects 2026-04-25 21:00:31 +01:00
Vincent Koc
89c52988c5 fix(diagnostics): gate traceparent propagation on trusted metadata 2026-04-25 12:55:39 -07:00
InvalidPanda ツ
b64bfc5d9a fix(github-copilot): preserve reasoning IDs for Copilot Codex models (#71684)
* fix(github-copilot): preserve all reasoning IDs and add gpt-5.3-codex support

The existing guard (8fd15ed0e5) only skipped rewriting reasoning item IDs
when encrypted_content was a non-null string. When gpt-5.3-codex is used
via GitHub Copilot, the model falls through to the forward-compat catch-all
with reasoning:false, so encrypted_content is never requested and arrives
as null — bypassing the guard and causing a rewrite. Copilot validates
reasoning item IDs server-side regardless of whether the client includes
encrypted_content, so the rewritten id triggers the 400 error.

Two changes:

1. connection-bound-ids.ts: skip ALL reasoning items unconditionally.
   Reasoning items always reference server-side state bound to their
   original ID; rewriting any of them breaks Copilot's lookup.

2. models.ts + index.ts: extend the forward-compat cloning logic to
   cover gpt-5.3-codex (adds it to the template-target set and to
   CODEX_TEMPLATE_MODEL_IDS so it can also serve as a template source
   for gpt-5.4). Adds gpt-5.3-codex to COPILOT_XHIGH_MODEL_IDS for
   the thinking profile.

Thanks @InvalidPandaa.

* docs(github-copilot): clarify gpt-5.3-codex is a no-op template for itself

https://claude.ai/code/session_01EAFmq4WyKkiUkVAqRXp4Bm

* fix(github-copilot): remove dead reasoning prefix branch in deriveReplacementId

https://claude.ai/code/session_01EAFmq4WyKkiUkVAqRXp4Bm

* fix(github-copilot): align reasoning id replay tests

* test(plugin-sdk): use cjs sidecar for require fast path

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-25 20:52:07 +01:00
Vincent Koc
1d49b8cdaa fix(plugins): honor registry migration disable in doctor 2026-04-25 12:45:44 -07:00
Vincent Koc
d2046beb40 fix(plugins): stabilize registry package paths 2026-04-25 12:45:44 -07:00
Vincent Koc
958146bbac fix(plugins): satisfy registry repair lint 2026-04-25 12:45:44 -07:00
Vincent Koc
793b58b3f1 fix(plugins): add doctor registry repair 2026-04-25 12:45:43 -07:00
Vincent Koc
5c3eecfea7 fix(codex): require approvals for image-understanding turns (#71703) 2026-04-25 12:45:33 -07:00
Peter Steinberger
fb7b798f96 fix(android): prevent duplicate talk playback 2026-04-25 20:43:25 +01:00
Vincent Koc
346a72ddb9 fix(codex): require authorized inbound claims for bound turns (#71702)
* fix(codex): require authorized inbound claims for bound turns

* fix(codex): consume unauthorized bound turns
2026-04-25 12:42:23 -07:00
Vincent Koc
84f183b7ad test(diagnostics-otel): cover trace self-parent guard 2026-04-25 12:42:07 -07:00
Peter Steinberger
8f49c59d6d chore(release): publish 2026.4.24 appcast 2026-04-25 20:39:57 +01:00
Vincent Koc
b6af40f1f1 docs(minimax): note MINIMAX_API_HOST applies to image generation, baseUrl is ignored
mushuiyu_xydt's commit 0e1ef93e84 (#61155) routes MiniMax image
generation requests to the dedicated image endpoint
(api.minimax.io/v1/image_generation), ignoring models.providers.minimax.baseUrl
(which targets the chat/Anthropic-compatible API), and adds
MINIMAX_API_HOST support for the CN api.minimaxi.com endpoint. The
CHANGELOG entry covered it but docs/providers/minimax.md image-generation
section did not. Add a paragraph naming both endpoints and the
MINIMAX_API_HOST override.
2026-04-25 12:39:07 -07:00
Peter Steinberger
a5f5608d06 docs(agents): forbid self-thanks in changelog 2026-04-25 20:37:36 +01:00
Peter Steinberger
3593beee81 test(gateway): tolerate codex image probe diagnostics 2026-04-25 20:37:31 +01:00
Peter Steinberger
a5a438a17c fix: relax pricing fetch timeout 2026-04-25 20:35:29 +01:00
Vincent Koc
1915b29a3c fix(slack): stop block-based sender rehydration on assistant message edits (#71700)
* fix(slack): stop block-based sender rehydration on message edits

* docs(changelog): note Slack sender attribution fix
2026-04-25 12:34:55 -07:00
Peter Steinberger
bb6cf75463 refactor: centralize context prompt token resolution 2026-04-25 20:34:27 +01:00
Vincent Koc
5fe06f3cdc test(diagnostics-otel): cover untrusted trace parent rejection 2026-04-25 12:34:16 -07:00
Peter Steinberger
9d764ea075 test(plugins): preserve child_process exports in runtime deps mock 2026-04-25 20:33:11 +01:00
Vincent Koc
64582bb3a7 docs(diagnostics-otel): clarify genai semconv exports 2026-04-25 12:30:14 -07:00
Peter Steinberger
d4971aad2c docs: require feasible live verification 2026-04-25 20:27:21 +01:00
Peter Steinberger
30325f567c fix: use prompt snapshots for live context diagnostics 2026-04-25 20:25:44 +01:00
Peter Steinberger
b732f21a86 fix: clarify voice-call setup diagnostics 2026-04-25 20:24:36 +01:00
Vincent Koc
44648440a5 fix(diagnostics-otel): stabilize genai token metric model attr 2026-04-25 12:22:55 -07:00
Peter Steinberger
75d64cd4b8 feat: expose generic image background option 2026-04-25 20:21:46 +01:00
Peter Steinberger
03fd7df929 fix: remove duplicate diagnostic stability case 2026-04-25 20:21:39 +01:00
Peter Steinberger
d757396785 test(ui): consolidate chat jsdom suites 2026-04-25 20:17:23 +01:00
Peter Steinberger
7436e395d5 test(node-host): cache native binary fixture lookup 2026-04-25 20:17:23 +01:00
Peter Steinberger
f34513ac66 perf(memory): avoid duplicate session store reads 2026-04-25 20:17:22 +01:00
Vincent Koc
5815ca93d9 fix(diagnostics-otel): honor genai usage semconv opt-in 2026-04-25 12:13:50 -07:00
Peter Steinberger
86d897cfaa feat(android): expose talk mode
Co-authored-by: alex-latitude <213670856+alex-latitude@users.noreply.github.com>
2026-04-25 20:12:38 +01:00
Peter Steinberger
791ad0864a fix: strip invalid thinking replay signatures
Fixes #45010.
Supersedes #70054.

Co-authored-by: Chris Staples <chris.staples@sophos.com>
Co-authored-by: Fourier <yang.fourier@gmail.com>
2026-04-25 20:12:30 +01:00
Peter Steinberger
47a63f7acf fix(logging): merge duplicate context diagnostic case 2026-04-25 20:11:08 +01:00
Peter Steinberger
e6ab61762a fix(check): pass lock env to changed lint lanes 2026-04-25 20:11:08 +01:00
Peter Steinberger
1e7ae07772 fix(cli): dedupe onboard auth flags for completion cache 2026-04-25 20:11:08 +01:00
Peter Steinberger
d9486c683b fix: stabilize macos npm update smoke 2026-04-25 20:09:32 +01:00
Peter Steinberger
17401e31de fix: avoid changed gate lint self-lock 2026-04-25 20:09:00 +01:00
mushuiyu_xydt
0e1ef93e84 fix(minimax): use dedicated image generation endpoint (#61155)
* fix(minimax): use dedicated image generation endpoint

MiniMax image generation uses a dedicated API endpoint
(api.minimax.io/v1/image_generation) that is separate from the
text/chat API endpoint (api.minimax.io/anthropic).

Previously, the resolveMinimaxImageBaseUrl function would extract
the origin from the provider's configured baseUrl. If a user had
configured their baseUrl to the chat endpoint (e.g.,
api.minimax.chat/anthropic), the image generation would incorrectly
use that endpoint, resulting in "invalid api key" errors.

This fix always uses the dedicated image generation endpoint,
ignoring the provider's baseUrl configuration for image generation.

Fixes #61149

* fix(minimax): support CN endpoint for image generation

Respect MINIMAX_API_HOST environment variable to determine whether
to use the global (api.minimax.io) or CN (api.minimaxi.com) endpoint
for image generation.

This ensures that CN users who configure MINIMAX_API_HOST to use
api.minimaxi.com will continue to use the CN endpoint for image
generation, while global users continue to use api.minimax.io.

The original bug was caused by the code extracting the origin from
the provider's configured baseUrl, which could be set to incorrect
endpoints like api.minimax.chat. This fix uses the dedicated image
generation endpoints instead.

Fixes #61149

* fix(minimax): infer CN endpoint from provider config when env is unset

When MINIMAX_API_HOST is not set, fall back to checking the provider's
configured baseUrl to determine whether to use the CN or global image
endpoint. This ensures CN users who went through onboarding (which sets
models.providers.minimax.baseUrl to https://api.minimaxi.com/anthropic)
are correctly routed to the CN image endpoint.

The isMinimaxCnHost check ensures we only use the baseUrl origin for
CN detection - invalid endpoints like api.minimax.chat would not match
minimaxi.com and would correctly fall through to the global default.

Fixes #61149

* test(minimax): cover dedicated image endpoints

* fix(logging): handle context assembly diagnostics

* Revert "fix(logging): handle context assembly diagnostics"

This reverts commit f51d2f7d67f8193268dd37553ac77e80a0423390.

* test(minimax): isolate image endpoint env

* docs(changelog): credit minimax image fix

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-25 20:07:52 +01:00
Quratulain-bilal
7d58362f3f docs(browser): note tilde expansion also covers per-profile paths (#71601)
* docs(browser): note tilde expansion also covers per-profile paths

The 95a2c9b fix expanded "~" for both `browser.executablePath` and
per-profile `profiles.<name>.executablePath` (config.ts:382 calls
`normalizeExecutablePath` for profile overrides). Per-profile
`userDataDir` on existing-session profiles is also tilde-expanded
(config.ts:391 via `resolveUserPath`). The configuration reference
only mentioned the top-level `browser.executablePath` case.

* docs(browser): align tilde path config help

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-25 20:05:03 +01:00
Vincent Koc
5671fdca87 feat(diagnostics-otel): add genai usage span identity 2026-04-25 12:03:10 -07:00
Peter Steinberger
5eab16e086 fix: improve google meet setup diagnostics 2026-04-25 20:01:24 +01:00
Peter Steinberger
e36b77c13e docs(changelog): drop self-thanks 2026-04-25 20:01:00 +01:00
Peter Steinberger
d68574653e docs(changelog): split 2026.4.24 and 2026.4.25 notes 2026-04-25 19:59:54 +01:00
Quratulain-bilal
8170df9127 docs(browser): document local startup timeout bounds (#71672)
* docs(browser): document local startup timeout bounds

The new browser.localLaunchTimeoutMs and browser.localCdpReadyTimeoutMs
options are clamped to MAX_BROWSER_STARTUP_TIMEOUT_MS (120000 ms) by
normalizeStartupTimeoutMs in extensions/browser/src/browser/config.ts,
and zero/negative/non-finite values fall back to the defaults. Without
this in the configuration reference, users setting a higher value see
no error and silently get the 120 s ceiling, or set 0 expecting 'no
timeout' and silently get the default.

* docs(browser): clarify startup timeout validation

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-25 19:59:53 +01:00
Peter Steinberger
b66f01bdca fix: expose transparent image infer options 2026-04-25 19:58:41 +01:00
Vincent Koc
cd7a8f870b feat(diagnostics-otel): add genai usage span attrs 2026-04-25 11:56:13 -07:00
91wan
bb2b68b34e fix(acp): pass Codex ACP model thinking overrides
Fix ACP Codex model/thinking override propagation.\n\nThanks @91wan.
2026-04-25 19:56:03 +01:00
Peter Steinberger
e9d9726f2d fix: handle context assembled diagnostics 2026-04-25 19:54:28 +01:00
Peter Steinberger
a018db771d fix: preserve omitted thinking replay turns 2026-04-25 19:54:28 +01:00
Peter Steinberger
690c98ad99 test(plugins): align install ledger mocks 2026-04-25 19:54:12 +01:00
Vincent Koc
c410e48382 fix(plugins): keep onboarding install records out of config 2026-04-25 11:52:19 -07:00
Peter Steinberger
bbc0884e23 docs(changelog): restore 2026.4.24 release notes 2026-04-25 19:51:11 +01:00
Vincent Koc
9bd348fdec fix(plugins): harden install ledger path handling 2026-04-25 11:48:17 -07:00
Vincent Koc
dc19069d71 feat(diagnostics-otel): add genai operation duration metric 2026-04-25 11:48:10 -07:00
Peter Steinberger
81307fc11d test: hoist backup archive mocks 2026-04-25 19:48:03 +01:00
Peter Steinberger
599ae7fed8 docs: clarify tool result details persistence 2026-04-25 19:47:19 +01:00
Peter Steinberger
fecf1e9b8f fix: align plugin install tests with ledger store 2026-04-25 19:44:11 +01:00
Peter Steinberger
4c0e9a4b2e fix(plugins): honor inferred agent model defaults 2026-04-25 19:40:32 +01:00
Peter Steinberger
cd8cb8254a fix(logging): remove duplicate context diagnostic case 2026-04-25 19:39:20 +01:00
Peter Steinberger
2055e6ceba fix(logging): include context assembly diagnostics in stability log 2026-04-25 19:39:20 +01:00
Peter Steinberger
8ea3099cd3 test(codex): accept visible session model reply 2026-04-25 19:39:20 +01:00
Peter Steinberger
e4f544790c test: isolate gateway live model sessions 2026-04-25 19:39:20 +01:00
Peter Steinberger
02639d3ec8 fix(plugins): alias wildcard runtime dependency exports 2026-04-25 19:39:20 +01:00
Peter Steinberger
14c9cfb637 fix(plugins): alias runtime dependency export subpaths 2026-04-25 19:39:20 +01:00
Peter Steinberger
9e9aa4722a fix(plugins): load mirrored runtime deps through ESM-safe aliases 2026-04-25 19:39:20 +01:00
Peter Steinberger
d2ab6b4fd5 fix(plugins): preserve package deps for runtime mirrors 2026-04-25 19:39:19 +01:00
Troy Hitch
63241bf1e0 fix(bonjour): suppress ciao cancellation across plugin runtime copies
Fix the bundled Bonjour gateway discovery crash-loop caused by ciao probe cancellation rejections after the Bonjour plugin migration.

The plugin entry now wires the existing rejection handler into the advertiser, and the unhandled-rejection handler registry is anchored on globalThis so staged plugin SDK module copies register into the same process-level handler set used by the host.

Verification:
- pnpm test:serial extensions/bonjour/src/advertiser.test.ts src/infra/unhandled-rejections.fatal-detection.test.ts
- OPENCLAW_LOCAL_CHECK_MODE=throttled pnpm check:changed partially completed: conflict markers plus core/core-test/extensions/extension-test typecheck passed; local lint lane hit a self-lock and was stopped.
2026-04-25 11:38:30 -07:00
Vincent Koc
888448facc feat(plugins): move install records to managed ledger 2026-04-25 11:37:10 -07:00
Peter Steinberger
e473577eaa test(voice): harden live STT transcript checks 2026-04-25 19:36:01 +01:00
Vincent Koc
f204f0c999 docs(logging): document new OTEL metrics and spans from recent diagnostics-otel feats
Five recent diagnostics-otel feat commits added user-facing OpenTelemetry
surfaces but did not update docs/logging.md, so the listed metrics and
spans drifted out of sync with what the plugin actually exports:

- 7bbd47349e adds gen_ai.client.token.usage histogram (GenAI semconv)
- b8a41739d5 adds memory heap/rss histograms, pressure counter and span
- d6ef1fcf24 adds openclaw.tool.loop counters and span
- ff172f46a5 adds openclaw.context.assembled span
- 44114328b4 adds openclaw.provider.request_id_hash attr on
  openclaw.model.call spans

Append the new metrics under existing model-usage and exec sections,
add a 'Diagnostics internals' subsection for memory + tool-loop
metrics, and add the three new spans (context.assembled, tool.loop,
memory.pressure) plus the request-id-hash attribute to the spans
listing.
2026-04-25 11:35:20 -07:00
Vincent Koc
7bbd47349e feat(diagnostics-otel): add genai token usage metric 2026-04-25 11:31:45 -07:00
Peter Steinberger
73706ca244 test: stabilize QA session memory ranking 2026-04-25 19:30:28 +01:00
Peter Steinberger
de0097a23c fix: support transparent OpenAI image generation 2026-04-25 19:28:56 +01:00
Peter Steinberger
0bf4876add fix: sanitize assembled diagnostic context 2026-04-25 19:23:51 +01:00
Peter Steinberger
a00c225899 test: split pure tool-card coverage 2026-04-25 19:23:51 +01:00
Peter Steinberger
e1495c3372 test: streamline memory and tts suites 2026-04-25 19:23:51 +01:00
Peter Steinberger
75fcb8c56d perf: lazy-load heavy test imports 2026-04-25 19:23:51 +01:00
Peter Steinberger
31456e3326 fix(providers): handle proxied DeepSeek V4 replay 2026-04-25 19:23:15 +01:00
Vincent Koc
b8a41739d5 feat(diagnostics-otel): export memory diagnostics 2026-04-25 11:22:19 -07:00
Peter Steinberger
1380dc170e fix(browser): avoid restart hint for external profiles 2026-04-25 19:18:06 +01:00
Vincent Koc
d6ef1fcf24 feat(diagnostics-otel): export tool loop events 2026-04-25 11:11:56 -07:00
Peter Steinberger
830bd2e236 fix: recover stale runtime deps locks 2026-04-25 19:09:09 +01:00
Poo-Squirry
fd3840cb00 Fix context usage display and active-run reload interruptions
Fixes context usage display regressions and prevents active runs from being interrupted by channel reloads. Adds persisted tool-result detail bounds so large tool metadata stays out of model/session payloads.
2026-04-25 19:07:52 +01:00
Chris Zhang
c3bfd328ad feat(litellm): add image generation provider (#70246)
* feat(litellm): add image generation provider

Registers litellm as an image-generation provider so model refs like
litellm/gpt-image-2 route through the LiteLLM proxy, and
agents.defaults.imageGenerationModel.fallbacks entries of the form
litellm/... resolve without "No image-generation provider registered
for litellm" errors.

Implementation uses the OpenAI-compatible /images/generations and
/images/edits endpoints that LiteLLM proxies for. BaseUrl resolves from
models.providers.litellm.baseUrl (default http://localhost:4000). Private
network is auto-allowed when baseUrl is a loopback/RFC1918 address, which
covers the common self-hosted LiteLLM proxy case without needing
OPENCLAW_PROVIDER_ALLOW_PRIVATE_NETWORK. Public baseUrls keep normal SSRF
defaults.

Default model is gpt-image-2 (matching upstream 4.21+ OpenAI default).
Advertises the same 2K/4K sizes OpenAI now exposes, plus legacy
256/512/1024 for dall-e-3. Supports both generate and edit.

Local patch. LiteLLM has no upstream image-generation support yet; revisit
if upstream adds one.

* ci: rerun after upstream main hot-fix

* fix(litellm): harden image generation provider

---------

Co-authored-by: Chris Zhang <chris@ChrisdeMac-mini.local>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-25 19:06:51 +01:00
Chunyue Wang
930d81aa41 fix(agents): prevent Bedrock replay death loop on empty assistant content (#71627)
* fix(agents): prevent Bedrock replay death loop on empty assistant content

  Fixes #71572

* docs: document Bedrock replay repair (#71627) (thanks @openperf)

* fix(diagnostics): share diagnostic event state across sdk graphs

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-25 19:04:40 +01:00
Vincent Koc
ff172f46a5 feat(diagnostics-otel): add context assembly spans 2026-04-25 11:03:46 -07:00
Peter Steinberger
afd6b5d6fc fix(opencode-go): route DeepSeek V4 through OpenAI transport 2026-04-25 18:58:08 +01:00
Vincent Koc
275c128e99 feat(plugins): add sanitized model call hooks 2026-04-25 10:56:40 -07:00
Peter Steinberger
9ffe764416 fix(whatsapp): send voice note text separately 2026-04-25 18:55:03 +01:00
Peter Steinberger
617e1dd6bf fix(browser): honor remote CDP open timeouts 2026-04-25 18:52:57 +01:00
Peter Steinberger
d623354a0e fix(infra): share diagnostic event state across loaders 2026-04-25 18:52:38 +01:00
Vincent Koc
44114328b4 feat(diagnostics): surface provider request id hashes 2026-04-25 10:46:10 -07:00
Peter Steinberger
2e0ae56b1a test(plugins): satisfy readonly index lint 2026-04-25 18:44:29 +01:00
Peter Steinberger
cd6c64d2ee test(plugins): avoid readonly index mutation 2026-04-25 18:42:25 +01:00
Peter Steinberger
649a645492 test(core): trim sync test overhead 2026-04-25 18:41:21 +01:00
Peter Steinberger
39488dfd68 test(pairing): reduce fixture io overhead 2026-04-25 18:41:20 +01:00
Peter Steinberger
8c93745f0f test(memory): speed up host fixture setup 2026-04-25 18:41:20 +01:00
Vincent Koc
f56bf63b06 fix(plugins): reject stale registry policy reads 2026-04-25 10:35:36 -07:00
Vincent Koc
61b3c04424 test(plugins): cover registry refresh mutations 2026-04-25 10:35:36 -07:00
Vincent Koc
3ec92dfac0 fix(plugins): deprecate registry disable break glass 2026-04-25 10:35:36 -07:00
Vincent Koc
4324855a9d docs(plugins): document persisted registry repair 2026-04-25 10:35:35 -07:00
Vincent Koc
fd8a8789d0 fix(plugins): satisfy registry lint 2026-04-25 10:35:35 -07:00
Vincent Koc
2f622acec6 fix(plugins): normalize startup config from registry 2026-04-25 10:35:35 -07:00
Vincent Koc
f14aa65bcc fix(plugins): refresh registry after chat toggles 2026-04-25 10:35:35 -07:00
Vincent Koc
29988335fc feat(plugins): resolve provider owners from registry 2026-04-25 10:35:35 -07:00
Vincent Koc
674d188153 feat(plugins): plan gateway startup from registry 2026-04-25 10:35:35 -07:00
Vincent Koc
feb8d3a4bd fix(plugins): label registry list state as enabled 2026-04-25 10:35:34 -07:00
Vincent Koc
5677a26385 docs(changelog): note registry-backed plugin list 2026-04-25 10:35:34 -07:00
Vincent Koc
5859dcd298 feat(plugins): list from registry snapshot 2026-04-25 10:35:34 -07:00
Vincent Koc
caf25fac91 feat(plugins): add registry repair command 2026-04-25 10:35:34 -07:00
Vincent Koc
521e75dea0 feat(plugins): prefer persisted registry reads 2026-04-25 10:35:09 -07:00
Vincent Koc
a7de722f4f fix(diagnostics-otel): align GenAI semconv attrs 2026-04-25 10:33:13 -07:00
Peter Steinberger
5f4bc6ec02 fix: surface external agent errors 2026-04-25 18:30:16 +01:00
Peter Steinberger
f545872cbc test(ui): streamline session controls async tests 2026-04-25 18:27:23 +01:00
Peter Steinberger
847c00d409 test(ui): speed up chat icon mocks 2026-04-25 18:27:23 +01:00
Peter Steinberger
88df8fe09d fix(browser): clarify Browserless CDP attach handling 2026-04-25 18:26:57 +01:00
Peter Steinberger
0bbb0eb735 fix(image): honor generation timeout config 2026-04-25 18:25:26 +01:00
Peter Steinberger
80739731dd docs: clarify pi-ai generic failover (#71647) 2026-04-25 18:22:06 +01:00
willamhou
4b5c2f9aa3 fix(agents/failover): classify bare pi-ai stream wrapper as timeout regardless of provider (#71620) 2026-04-25 18:22:06 +01:00
Vincent Koc
dcdf97685b fix(diagnostics): trust internal trace parents (#71574)
* fix(diagnostics): trust internal trace parents

* fix(diagnostics): harden trusted trace metadata

* fix(tooling): honor explicit oxlint threads

* fix(agents): use stable nonmutating sort helpers

* chore(plugin-sdk): refresh api baseline

* fix(diagnostics): gate internal event subscriptions

* fix(diagnostics): isolate listener event copies

* chore(plugin-sdk): refresh internal diagnostics baseline

* chore(plugin-sdk): refresh diagnostics event baseline

* fix(diagnostics): keep event state module local

* fix(diagnostics): harden internal subscription capability

* fix(diagnostics): freeze listener metadata
2026-04-25 10:18:52 -07:00
Peter Steinberger
8e7d382c37 refactor(tts): clarify text media directives 2026-04-25 18:18:34 +01:00
Peter Steinberger
67506ac2a9 fix(xai): support video reference images 2026-04-25 18:14:51 +01:00
Peter Steinberger
768bbc7cc0 docs: update OpenAI GPT-5.5 API guidance 2026-04-25 18:14:10 +01:00
Peter Steinberger
390be8138f fix: add OpenCode Go DeepSeek V4 models 2026-04-25 18:11:59 +01:00
Vincent Koc
0d274ef6c2 docs(control-ui): note assistant avatar uploads stay browser-local
Val Alexander's c65aa1d2a6 (#71639) changed assistant avatar uploads
from gateway config persistence to localStorage, mirroring the existing
user-avatar pattern. CHANGELOG covered it but docs/web/control-ui.md
'Personal identity (browser-local)' section only documented the user
identity. Add a paragraph noting the assistant avatar override follows
the same browser-local pattern, while keeping the ui.assistant.avatar
config field reachable for non-UI clients writing the field directly.
2026-04-25 10:08:59 -07:00
Peter Steinberger
6b3e4b88d6 test: update QA parity fixtures for GPT-5.5 2026-04-25 18:05:28 +01:00
Peter Steinberger
39343088ed fix(tts): keep media-only no-reply payloads 2026-04-25 18:04:54 +01:00
Peter Steinberger
f3ba962fd0 fix(subagents): explain browser tool profile filtering 2026-04-25 17:59:05 +01:00
Peter Steinberger
e27e29c66e refactor: split Crestodian planner backend selection 2026-04-25 17:56:46 +01:00
Peter Steinberger
60f9358348 fix(tts): preserve legacy tool voice hints 2026-04-25 17:56:37 +01:00
Peter Steinberger
dc7c703425 test: lazy-load global cleanup helpers 2026-04-25 17:49:16 +01:00
Peter Steinberger
8bead989da fix(telegram): frame audio transcripts as untrusted 2026-04-25 17:45:40 +01:00
Peter Steinberger
8659495384 test: make live cron probe agent-generic 2026-04-25 17:42:32 +01:00
Val Alexander
c65aa1d2a6 fix(control-ui): persist assistant avatar override locally (#71639)
* fix(control-ui): rebalance quick settings into stable 3-col bento

Pair Appearance with Automations and let Channels stand alone in the
middle column so all three top-row columns reach similar heights.
Promote Personal to a full-width row with a horizontal body
(identity tiles | emoji + actions) so the avatar block stops fighting
for half-width space. Drops the unused .qs-stack--wide hook.

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

* refactor(control-ui): rebalance Personal card with symmetric User↔Assistant identity pair

Restructure Personal card layout to present User and Assistant as 2 balanced identity cards instead of separate User tile + form controls. Mirrors the visual hierarchy and UI pattern across both identities.

Changes:
- Move User avatar text input into User identity card's .__repair section (mirroring Assistant's structure)
- Inline "Choose image" and "Clear avatar" buttons as flex-wrapped action group
- Remove .qs-personal-body and .qs-personal-form wrapper divs
- Update Personal card's .qs-identity-grid to 2-column layout with balanced spacing
- Responsive collapse to 1-column at ≤760px

Tests:
- config-quick.test.ts updated to expect 2 stacks (no longer wrapping Personal in form)
- config-quick.test.ts validates identity card layout now has symmetric User↔Assistant structure
- All 10 quick settings view tests passing
- All 20 schema regression tests passing

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>

* chore: ignore .vmux worktree paths

* fix(control-ui): persist assistant avatar override locally instead of via gateway config

Mirrors the user-avatar pattern: assistant avatar uploads now go to
localStorage and overlay the gateway-resolved identity at bootstrap and on
agent.identity.get refreshes. Sidesteps the ui.assistant.avatar zod cap
that rejected uploaded data URLs as 'Too big: expected string to have
<=200 characters', removes one config.patch RPC from the avatar path, and
collapses the upload handler from a 44-line async/loadConfig dance into a
plain synchronous setter.

Also lifts the gateway-side ui.assistant.avatar schema cap from 200 to
2,000,000 to match the user-avatar size budget for non-UI clients writing
the field directly, and adds a content-aware text/image normalizer in
ui/src/ui/assistant-identity.ts so short-text avatars stay short while
data URLs survive round-tripping.

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-25 11:17:48 -05:00
Darshan Paccha
95b7a85f06 fix(ui): remove duplicate config section headers
Fix duplicate section title and description rendering in single-section Control UI config pages.\n\nKeeps root multi-section card headers intact, keeps single-section hero copy as the only visible section title, and adds browser coverage for both single-section and root views.\n\nFixes #68003.\n\nThanks @d1rshan.
2026-04-25 09:43:50 -05:00
Vincent Koc
c070509b7f fix(security): bound archive and MIME parser work (#71561)
* fix(security): bound archive and MIME parser work

* fix(security): harden zip preflight accounting

* fix(plugins): keep update channel sync on bundled path helpers

* fix(lint): avoid boolean literal comparisons

* fix(lint): keep agent spawn assertion immutable

* test(auto-reply): relax slow model directive regression timeout
2026-04-25 06:22:56 -07:00
Peter Steinberger
4e3bf7ce6a test: scope gateway restart signal assertion 2026-04-25 14:09:31 +01:00
Peter Steinberger
5c6a5afe81 test: use non-mutating sort in cli runner spec 2026-04-25 14:07:24 +01:00
Peter Steinberger
cd392b947c test: dedupe memory and context suites 2026-04-25 14:06:26 +01:00
Peter Steinberger
2413c0f5a5 perf: split chat UI test dependencies 2026-04-25 14:06:26 +01:00
Peter Steinberger
3db60f7eab perf: trim agent workspace imports 2026-04-25 14:06:26 +01:00
Vincent Koc
9b1dd9e573 docs(browser): document Chrome MCP per-profile mcpCommand/mcpArgs and cdpUrl mapping
Vincent's commit ab1d1a5c9e (#71560) added user-facing config keys to
existing-session profiles for the Chrome DevTools MCP launch path:

- browser.profiles.<name>.mcpCommand
- browser.profiles.<name>.mcpArgs

Plus runtime behavior changes:

- cdpUrl http(s) -> --browserUrl, cdpUrl ws(s) -> --wsEndpoint
- endpoint flags and userDataDir are mutually exclusive

The CHANGELOG entry covered the change, but docs/tools/browser.md
existing-session reference did not. Add a 'Custom Chrome MCP launch'
subsection describing the new fields and the cdpUrl endpoint mapping
rules.
2026-04-25 05:54:54 -07:00
Chunyue Wang
bc73141e82 fix(cli): key gemini cli auth epoch on google account identity (#71076)
Fixes openclaw#70973. Adds a \`google-gemini-cli\` branch to \`getLocalCliCredentialFingerprint\` that lifts OpenID \`id_token\` \`sub\`/\`email\` claims from \`~/.gemini/oauth_creds.json\` onto \`GeminiCliCredential\` so the shared \`encodeOAuthIdentity\` produces an identity-keyed auth-epoch matching the Claude/Codex contract, plus bumps \`CLI_AUTH_EPOCH_VERSION\` from 3 to 4 so existing v3 Gemini bindings without an \`authEpoch\` ride the existing \`cli-session.ts\` version-gate instead of forcing a one-time invalidation.
2026-04-25 20:47:58 +08:00
Vincent Koc
ab1d1a5c9e fix(browser): configure Chrome MCP existing-session launch (#71560) 2026-04-25 05:46:39 -07:00
Peter Steinberger
dd78b7f773 fix: harden OpenCode ACP bind dispatch 2026-04-25 13:38:58 +01:00
Peter Steinberger
42514156e0 fix: yield while waiting for subagent completions 2026-04-25 13:29:47 +01:00
skylee-01
f7b71abf48 fix(agents): pass Claude system prompt via file 2026-04-25 17:59:25 +05:30
Vincent Koc
ed650b652f fix(test): detect partial sparse core roots 2026-04-25 05:18:25 -07:00
Peter Steinberger
b26367e22f test: add Crestodian QA lab setup scenario 2026-04-25 13:15:11 +01:00
Peter Steinberger
c977643460 perf(browser): precompute browser help 2026-04-25 13:07:15 +01:00
Sahil Satralkar
3064ea78ab fix(telegram): recover incomplete preview finalization (#71554)
Fix Telegram partial-stream preview finalization so ambiguous final edit failures fall back to a final send when the visible preview is a strict prefix of the answer.

Includes archived-preview regression coverage and generated config metadata refresh.

Thanks @sahilsatralkar.

Co-authored-by: Sahil Satralkar <62758655+sahilsatralkar@users.noreply.github.com>
2026-04-25 13:01:10 +01:00
Peter Steinberger
e25b3c6056 fix(browser): align bare ws cdp readiness 2026-04-25 13:00:22 +01:00
Vincent Koc
2b822f6ed0 fix(plugins): preserve default enablement for relocation 2026-04-25 04:59:53 -07:00
Vincent Koc
f70d77b0bd docs(plugins): clarify registry-derived relocations 2026-04-25 04:59:53 -07:00
Vincent Koc
0abb2a571f fix(plugins): derive bundled relocation from registry 2026-04-25 04:59:53 -07:00
Vincent Koc
7177492487 fix(plugins): keep enabled-only registry migration fresh 2026-04-25 04:59:53 -07:00
Vincent Koc
0cc2b0e283 feat(plugins): refresh registry after plugin mutations 2026-04-25 04:59:53 -07:00
Vincent Koc
53c3c949d0 feat(plugins): bridge externalized bundled updates 2026-04-25 04:59:52 -07:00
Vincent Koc
ad8296e685 fix(plugins): harden registry migration guards 2026-04-25 04:59:52 -07:00
Vincent Koc
f22a2f7e8b fix(plugins): migrate only enabled registry entries 2026-04-25 04:59:52 -07:00
Vincent Koc
d7cf803705 fix(plugins): preflight registry install migration 2026-04-25 04:59:52 -07:00
Vincent Koc
81aefb9a18 feat(plugins): migrate plugin registry on install 2026-04-25 04:59:52 -07:00
Peter Steinberger
a48998d8c8 test(qqbot): cover voice utility contracts 2026-04-25 12:57:23 +01:00
Peter Steinberger
c307700db0 test(whatsapp): cover group generated media delivery 2026-04-25 12:56:53 +01:00
Peter Steinberger
d6e9ae53fe perf: split chat strip helper 2026-04-25 12:52:27 +01:00
Peter Steinberger
56573185f2 perf: split canvas a2ui shared imports 2026-04-25 12:52:27 +01:00
Peter Steinberger
40e4a00c8e perf: slim crestodian rescue tests 2026-04-25 12:52:27 +01:00
Peter Steinberger
2b8105598e perf: lazy load support bundle zip 2026-04-25 12:52:27 +01:00
Peter Steinberger
1888242bd3 perf: split trajectory export paths 2026-04-25 12:52:27 +01:00
Peter Steinberger
4a76a66872 perf: slim memory host imports 2026-04-25 12:52:27 +01:00
Peter Steinberger
6eec38ad5a feat(discord): allow voice model override 2026-04-25 12:47:46 +01:00
Ayaan Zaidi
d0ed938351 fix: make subagent session errors actionable (#67790) (thanks @stainlu) 2026-04-25 17:15:36 +05:30
stainlu
835f768036 fix(agents): make sessions_spawn mode=session errors actionable when thread binding is unavailable 2026-04-25 17:15:36 +05:30
Peter Steinberger
3507efa4ec fix(media): preserve oversized video generation delivery 2026-04-25 12:41:43 +01:00
Roman Godz
150f3e472b fix: sync Claude CLI OAuth credentials (#70902) (thanks @starvex) 2026-04-25 17:07:27 +05:30
Peter Steinberger
84dc9f12f1 test(agents): cover single image generation media delivery 2026-04-25 12:32:43 +01:00
Vincent Koc
e174d96cc0 refactor(media): move sharp image ops into media runtime (#71519)
* refactor(media): move sharp image ops into plugin

* fix(media): pass image pixel budget to sharp plugin

* refactor(media): reuse media understanding sharp runtime

* test(build): allow staged runtime core graphs
2026-04-25 04:31:10 -07:00
Peter Steinberger
b2b898c2a8 feat(browser): configure local startup timeouts 2026-04-25 12:30:35 +01:00
Peter Steinberger
4ac6729d12 test: expand Crestodian first-run Docker smoke 2026-04-25 12:30:26 +01:00
Peter Steinberger
9ab51bb66e test: stabilize qa lab live scenarios 2026-04-25 12:30:08 +01:00
Peter Steinberger
c5fe80ad58 fix: make qa config apply retries idempotent 2026-04-25 12:30:07 +01:00
Peter Steinberger
67436918f3 fix: deliver subagent completions via external requester route 2026-04-25 12:30:07 +01:00
Vincent Koc
924271385b fix(cron): record interrupted startup runs
* fix(cron): record interrupted startup runs

* test(cron): update interrupted startup expectations
2026-04-25 04:28:11 -07:00
Val Alexander
fc5920fb51 fix(ui): polish assistant identity settings
Polishes the basic config identity layout, aligns assistant avatar rendering with chat, and adds a Control UI assistant avatar override with IDENTITY.md fallback.
2026-04-25 06:27:22 -05:00
Vincent Koc
443b837bd5 fix(build): harden bundled plugin runtime staging
Copy bundled plugin skill trees into dist-runtime, broaden Windows symlink-copy fallbacks, and harden runtime-deps fingerprinting.
2026-04-25 04:27:17 -07:00
Donetta Flatley
f408bba9de fix(memory-host-sdk): use TRUSTED_ENV_PROXY mode for remote embeddings in proxy environments (#71506)
* fix(memory-host-sdk): use TRUSTED_ENV_PROXY mode in withRemoteHttpResponse

When a HTTP/HTTPS proxy is configured via environment variables
(HTTPS_PROXY, HTTP_PROXY, ALL_PROXY), the withRemoteHttpResponse
function now passes mode=TRUSTED_ENV_PROXY to fetchWithSsrFGuard.

This causes DNS resolution to skip the local resolver and route
through the configured proxy, fixing 'fetch failed' errors for
remote memory embeddings (including GitHub Copilot embeddings) in
proxy environments (e.g. Clash TUN, corporate proxies).

Previously, without an explicit mode, fetchWithSsrFGuard defaulted
to STRICT mode which performs local DNS pre-resolution via
resolvePinnedHostnameWithPolicy(), failing in proxy environments
where DNS must go through the proxy.

Fixes: openclaw/openclaw#52162

* fix: harden memory env proxy guard (#71506) (thanks @DhtIsCoding)

---------

Co-authored-by: Dht <dht@openclaw.ai>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-25 12:24:09 +01:00
Peter Steinberger
f1470b52fb fix(agents): fall back for threadless completion delivery 2026-04-25 12:23:42 +01:00
Ayaan Zaidi
bdba4fa1bf fix: isolate active memory auth health (#71539)
* fix(agents): scope helper auth failures

* fix(active-memory): isolate recall auth health

* fix: isolate active memory auth health (#71539)

* fix: avoid auth policy import cycle (#71539)
2026-04-25 16:50:38 +05:30
Peter Steinberger
be1d716427 refactor(plugin-sdk): narrow CLI runtime exports 2026-04-25 12:20:34 +01:00
Vincent Koc
f8a41e5e9c fix(test): serialize changed checks locally 2026-04-25 04:19:09 -07:00
Peter Steinberger
b511250e5c feat(media): add voice conversion and speech plugins 2026-04-25 12:12:33 +01:00
Peter Steinberger
16b7dee1ef test(crestodian): complete tui overview mock 2026-04-25 12:07:52 +01:00
Peter Steinberger
de652afffd fix: use random restart intent temp suffix 2026-04-25 12:04:37 +01:00
Peter Steinberger
e6fd1ccfd7 perf(ui): trim chat test imports 2026-04-25 12:04:17 +01:00
Peter Steinberger
4484772e7d test(logger): isolate rolling file cleanup 2026-04-25 12:04:17 +01:00
Peter Steinberger
4d00c47072 perf(crestodian): reduce test import overhead 2026-04-25 12:04:17 +01:00
Vincent Koc
84a22a64be fix(feishu): finish streaming card closeout 2026-04-25 04:04:03 -07:00
Peter Steinberger
935cd34e9f fix(openai): omit Azure image deployment model body 2026-04-25 12:02:26 +01:00
Peter Steinberger
89755d1c79 refactor(browser): simplify lazy CLI placeholders 2026-04-25 11:48:59 +01:00
deepkilo
df6c58cf30 fix(gateway): use secure dashboard links when TLS is enabled (#71499)
Fixes #71494.

- Render Control UI links with https:// when gateway TLS is enabled.
- Render websocket links with wss:// through the shared link resolver.
- Add daemon status handoff coverage and TLS scheme docs.

Co-authored-by: deepkilord <wang_hgang@msn.com>
2026-04-25 11:45:15 +01:00
Peter Steinberger
8cbb62d93c docs(browser): document headless start override 2026-04-25 11:42:04 +01:00
Peter Steinberger
c52ec520c7 feat(browser): add one-shot headless start override 2026-04-25 11:42:03 +01:00
Peter Steinberger
51e6f9c27e fix(reply): narrow empty-body history guard 2026-04-25 11:41:36 +01:00
jindongfu
1559e28d6b fix(get-reply): include inboundUserContext in empty-body guard (#71489)
The empty-body guard only checked baseBodyFinal (current message body)
and softResetTail, ignoring inboundUserContext which includes
InboundHistory from group chat context. This caused the bot to reject
bare @mentions in Feishu group chats where prior messages provided the
conversation context via InboundHistory.

Now hasUserBody also checks whether inboundUserContext has content,
matching the behavior before the 2026.4.12 refactor.
2026-04-25 11:41:36 +01:00
Vincent Koc
1549ded4ac docs(control-ui): document PWA install and web push
Eduardo Cruz's PWA web push feat (21b7ad5805, #44590) added a substantial
user-facing surface — manifest.webmanifest, sw.js, gateway push.web.*
methods, persisted vapid-keys.json/web-push-subscriptions.json, and
OPENCLAW_VAPID_* env overrides — but did not touch any docs/.

Add a 'PWA install and web push' section to docs/web/control-ui.md
covering the new persisted state files, env vars, and the four scope-gated
gateway methods (push.web.vapidPublicKey, push.web.subscribe,
push.web.unsubscribe, push.web.test). Distinguish from the existing
APNS relay-backed iOS push path.
2026-04-25 03:40:38 -07:00
Peter Steinberger
776d2ab65d fix(browser): lazy-load browser CLI runtime
Co-authored-by: pandego <7780875+pandego@users.noreply.github.com>
Co-authored-by: Tianworld <3580442280@qq.com>
2026-04-25 11:40:20 +01:00
Ayaan Zaidi
27aae62d99 fix: stop heartbeat prompt leaking into user runs (#69278) (thanks @stainlu) 2026-04-25 16:09:56 +05:30
stainlu
06c058b21d fix(agents): stop injecting heartbeat system prompt on non-heartbeat runs (#69079) 2026-04-25 16:09:56 +05:30
Val Alexander
151befb90b chore: keep superpowers plans local (#71530)
* docs: add control ui setup guidance design

* chore: keep superpowers plans local
2026-04-25 05:35:23 -05:00
Vincent Koc
0c9dacf902 fix(test): ignore local check opt-out in dev wrappers 2026-04-25 03:32:01 -07:00
Peter Steinberger
87aa0f813c fix(cli): forward video generation options 2026-04-25 11:31:09 +01:00
Val Alexander
b85b106b10 docs: add application modernization plan (#71528)
* docs: add application modernization plan

* docs: clarify frontend skill target
2026-04-25 05:29:57 -05:00
Vincent Koc
e0546edd98 fix(cron): normalize flat legacy job rows 2026-04-25 03:29:30 -07:00
Ayaan Zaidi
bbd6dfbe92 fix: cover CLI session prompt hash reuse (#69236) (thanks @stainlu) 2026-04-25 15:58:19 +05:30
Peter Steinberger
7711df0669 fix: default proxy completions tool choice (#71472) (thanks @Speed-maker) 2026-04-25 11:23:33 +01:00
Speed-maker
9a6b769e6e fix(agents): default proxy completions tool choice 2026-04-25 11:23:33 +01:00
Peter Steinberger
6a71c19839 fix: simplify Crestodian startup greeting 2026-04-25 11:20:59 +01:00
Peter Steinberger
a0c70c4f5a fix(google): guard veo rest polling 2026-04-25 11:17:23 +01:00
Peter Steinberger
9b48e4c0b6 fix(browser): fall back to headless on Linux without display 2026-04-25 11:13:42 +01:00
Peter Steinberger
b5a1b7d44d fix(google): guard veo video downloads 2026-04-25 11:12:49 +01:00
Peter Steinberger
978f869fcd fix(google): type veo fallback operation state 2026-04-25 11:11:14 +01:00
Peter Steinberger
94686c63fb fix(google): fall back to rest for veo sdk 404 2026-04-25 11:11:14 +01:00
Vincent Koc
814409a3b3 fix(test): keep local Vitest checks serialized 2026-04-25 03:07:27 -07:00
Peter Steinberger
5e0cca5e24 fix(google): narrow veo api key for uri download 2026-04-25 11:07:16 +01:00
Peter Steinberger
c11337149b fix(google): download direct veo video uri 2026-04-25 11:07:16 +01:00
Vincent Koc
455eba7f94 fix(feishu): coalesce streaming card final delivery 2026-04-25 03:06:38 -07:00
Peter Steinberger
38703ed9a1 fix(discord): identify voice attachment metadata 2026-04-25 11:05:38 +01:00
Peter Steinberger
5985e1d8b9 test: speed up import-heavy tests 2026-04-25 11:04:16 +01:00
Peter Steinberger
b9ea631b4b fix(openai): use gpt 5.5 for codex image responses 2026-04-25 11:03:53 +01:00
Eduardo Cruz
21b7ad5805 feat: add Control UI PWA web push support (#44590)
Adds browser PWA manifest and service worker support for the Control UI, plus gateway RPC methods and persisted Web Push subscription handling.

Maintainer verification:
- OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test src/infra/push-web.test.ts src/gateway/server-methods/push.test.ts src/gateway/control-ui.test.ts src/gateway/protocol/push.test.ts
- pnpm check:changed passed before final GitHub update-branch merge commit
- pnpm build

Source head: 0720024368
2026-04-25 05:03:00 -05:00
Peter Steinberger
385da2db60 feat: run Crestodian in TUI shell 2026-04-25 10:59:49 +01:00
Peter Steinberger
9fe35a0c62 fix(discord): restore voice note audio preflight 2026-04-25 10:57:37 +01:00
Peter Steinberger
936f27dcab docs: clarify minimax music changelog scope 2026-04-25 10:55:54 +01:00
Peter Steinberger
e6713c0a61 test(minimax): cover default music model normalization 2026-04-25 10:55:54 +01:00
Peter Steinberger
ed8384d32d fix(minimax): default music generation to music 2.6 2026-04-25 10:55:54 +01:00
Vincent Koc
c1f359c276 fix(test): reuse heavy-check lock in boundary prep 2026-04-25 02:49:45 -07:00
Vincent Koc
678d2c327c docs(changelog): backfill missing PR refs and reporter credits in top Unreleased
Three of my (vincentkoc) entries were missing closing PR refs, and
several maintainer-fix entries were missing credit for the user who
reported the underlying issue:

- Diagnostics/OTEL outbound delivery: add (#71471) and credit @jlapenna
  whose #70424 framed the broader tracing work.
- Cron malformed legacy jobs: add (#71509).
- OpenAI/Codex OAuth region failures: add (#71501) and credit reporter
  @wulala-xjj (#51175).
- Telegram duplicate pollers: credit reporter @Co-Messi (#56230).
- MCP/CLI one-shot retire: credit reporter @spartoviMD (#71457).
- OpenAI/Codex image baseUrl canonicalize: credit reporter @GodsBoy
  (#71460).
- Feishu TTS Ogg/Opus: credit reporters @sg1416-zg (#61249) and
  @ycjlb2023-peteryi (#37868).
- MiniMax TTS portal OAuth: credit reporter @zx15210404690-hash
  (#55017).
- MCP config reload disposal: credit reporter @xieyuanqing (#60656).
2026-04-25 02:49:37 -07:00
Peter Steinberger
815e9b493c fix: improve openrouter model scan fallback 2026-04-25 10:46:20 +01:00
Peter Steinberger
da2c61fe6e fix: render authenticated control ui avatars 2026-04-25 10:46:14 +01:00
Yunsu
9c64a0ca23 fix(google): avoid doubled media generation API version
Strip configured trailing /v1beta from Google music/video generation base URLs before calling the Google GenAI SDK.\n\nFixes #63240.\n\nThanks @Hybirdss.
2026-04-25 10:45:38 +01:00
Val Alexander
0bef73d151 chore: remove repo PR assets (#71510) 2026-04-25 04:40:29 -05:00
Vincent Koc
2896107153 fix(cron): tolerate malformed legacy jobs 2026-04-25 02:39:06 -07:00
Peter Steinberger
a7604f8170 fix(minimax): support token plan tts auth 2026-04-25 10:36:12 +01:00
Peter Steinberger
7fcefd56b7 chore: bump version to 2026.4.25 2026-04-25 10:31:52 +01:00
Vincent Koc
65ea6a0d94 fix(auth): clarify Codex OAuth region failures (#71501) 2026-04-25 02:31:42 -07:00
Peter Steinberger
c6770d3694 fix: align native think menus with session models 2026-04-25 10:30:49 +01:00
Peter Steinberger
4f91d81e1d fix(googlechat): preserve reply text after typing update failures
Preserve Google Chat reply text when typing indicator cleanup or update fails.

- Extract Google Chat reply delivery into a focused module
- Retry the failed first text chunk as a new message after placeholder update failure
- Cover media caption and chunk fallback regressions

Thanks @colin-lgtm.
2026-04-25 10:30:41 +01:00
Vincent Koc
0ee9e8188d Merge branch 'main' of https://github.com/openclaw/openclaw
* 'main' of https://github.com/openclaw/openclaw:
  feat: add crestodian local planner fallback
  fix(control-ui): clarify chat context details
  fix(telegram): keep polling watchdog active for wedged runner
2026-04-25 02:22:02 -07:00
Peter Steinberger
9056d4f708 feat: add crestodian local planner fallback 2026-04-25 10:20:02 +01:00
Val Alexander
388270ffce fix(control-ui): clarify chat context details
Summary:
- Show full date and time in Control UI chat message footers.
- Collapse assistant model/token/context metadata behind an explicit Context disclosure.
- Update changelog attribution guidance to allow multi-author credited entries.

Validation:
- OPENCLAW_LOCAL_CHECK=0 pnpm test ui/src/ui/chat/grouped-render.test.ts
- OPENCLAW_LOCAL_CHECK=0 pnpm test src/commands/gateway-status/helpers.test.ts
- OPENCLAW_LOCAL_CHECK=0 pnpm check:changed
- GitHub CI passed on f071a38177
2026-04-25 04:19:56 -05:00
Vincent Koc
c52c161f5a refactor(plugins): compact package json index metadata 2026-04-25 02:18:56 -07:00
Vincent Koc
c959c18fc7 fix(plugins): persist registry enabled snapshot 2026-04-25 02:18:56 -07:00
Vincent Koc
00f47f01fe refactor(plugins): trim persisted plugin registry state 2026-04-25 02:18:56 -07:00
Vincent Koc
3556f8441a feat(plugins): add plugin registry facade 2026-04-25 02:18:56 -07:00
Vincent Koc
36219b0ffc fix(plugins): invalidate index on policy changes 2026-04-25 02:18:56 -07:00
Vincent Koc
b001b8c947 feat(plugins): inspect persisted plugin index state 2026-04-25 02:18:55 -07:00
Vincent Koc
74a384d887 feat(plugins): persist installed plugin index snapshots 2026-04-25 02:18:55 -07:00
Vincent Koc
dfac36ee01 feat(plugins): add cold installed index owner APIs 2026-04-25 02:18:55 -07:00
Vincent Koc
ceace83556 fix(telegram): keep polling watchdog active for wedged runner 2026-04-25 02:18:49 -07:00
Peter Steinberger
f6a3b42cfa fix(browser): keep transient fetch errors retryable
Co-authored-by: jriff <jriff@users.noreply.github.com>
2026-04-25 10:09:15 +01:00
Peter Steinberger
2483d1dc12 fix(browser): drop redundant setuid sandbox flag
Co-authored-by: Sebastian Krueger <150018+sebykrueger@users.noreply.github.com>
2026-04-25 10:09:15 +01:00
Peter Steinberger
41ed7fa535 fix(browser): manage isolated downloads
Co-authored-by: Pearce Kieser <5055971+Pearcekieser@users.noreply.github.com>
2026-04-25 10:09:13 +01:00
Peter Steinberger
b756dfcb2b perf: speed up boundary and provider tests 2026-04-25 10:08:46 +01:00
Vincent Koc
c5e6f4bbc0 docs(agents): document sparse changed gate 2026-04-25 02:07:15 -07:00
Peter Steinberger
2377f1a4cd test(elevenlabs): cover eleven_v3 tts catalog 2026-04-25 10:06:42 +01:00
itsuzef
0fc68a5ed4 feat(elevenlabs): register eleven_v3 in TTS model allowlist
eleven_v3 already works end-to-end (model_id passes through to the API
without validation), but was missing from ELEVENLABS_TTS_MODELS so it
never appeared in the in-product model picker or catalog metadata.
2026-04-25 10:06:42 +01:00
hcl
fd74fc5a4f fix(heartbeat): clamp scheduler delay to Node setTimeout cap (#71414) (#71478)
* fix(heartbeat): clamp scheduler delay to Node setTimeout cap (#71414)

When `agents.defaults.heartbeat.every` resolves to >2_147_483_647 ms
(~24.85d), the previous scheduleNext() called setTimeout with the raw
delay. Node clamps any delay > 2^31-1 to 1 ms, fires the callback, and
the heartbeat re-arms with the same oversized value - a tight loop that
floods the log with TimeoutOverflowWarning and crashes the gateway with
exit code 1.

Clamp the computed delay to HEARTBEAT_MAX_TIMEOUT_MS (2_147_483_647)
before calling setTimeout. The worst case is now one heartbeat every
~24.85d instead of crash-loop. Warn once per process when clamping
fires, so a misconfigured "365d" remains visible without flooding.

This is a defense-in-depth fix at the scheduler layer; loadConfig-level
rejection is a broader change with more blast radius and a separate
question (some users may legitimately want "every: 365d" to mean
"effectively never"). The clamped behaviour is closer to that intent
than the crash is.

Test: new scheduler test sets heartbeat.every="365d" with fake timers,
advances 60s, and asserts runSpy was never called (with the bug, it
would be called ~60_000 times).

* style: format heartbeat scheduler clamp

* fix: share safe timeout delay clamp (#71478) (thanks @hclsys)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-25 10:03:43 +01:00
Vincent Koc
a33f7b7d05 fix(test): make changed typechecks sparse-safe 2026-04-25 02:02:57 -07:00
Peter Steinberger
ed0210a187 test: streamline slow import-heavy suites 2026-04-25 10:02:02 +01:00
Peter Steinberger
f7d276b842 perf: cache guard inventory checks 2026-04-25 10:02:02 +01:00
Peter Steinberger
70b3ba2fed test: speed up Docker live scheduling 2026-04-25 10:01:50 +01:00
Val Alexander
6bdf87de87 fix(ui): remove quick config API keys card
Remove the misleading API Keys card from the quick settings page.

The card was hardcoded to a fixed env-var provider list and routed all actions to the broad Environment config section, which made the Add/Change affordances look more precise than they were. This removes the dead surface and keeps the quick settings grid focused on meaningful controls.

Verified:
- pnpm test ui/src/ui/views/config-quick.test.ts
- CI passed on PR #71496
2026-04-25 04:00:53 -05:00
Chinar Amrutkar
bf34fde235 fix(telegram): remove offset confirmation getUpdates call
Remove the startup persisted-offset getUpdates preflight so polling restarts do not self-conflict before the grammY runner starts.\n\nFixes #69304.\n\nThanks @chinar-amrutkar.
2026-04-25 09:53:50 +01:00
Peter Steinberger
19017bad96 docs(browser): explain actionable aria snapshot refs 2026-04-25 09:51:34 +01:00
Peter Steinberger
ec8dbc4595 feat(tts): add xiaomi mimo speech provider 2026-04-25 09:48:05 +01:00
Peter Steinberger
e10f20032a fix(browser): resolve aria snapshot refs via DOM markers
Co-authored-by: MrKipler <mrkipler@kiphausen.com>
2026-04-25 09:44:31 +01:00
Behnam Shahbazi
207f0341e0 docs: use target flag in README message example 2026-04-25 01:44:21 -07:00
Vincent Koc
01bf61fcfd fix(media): remove express from media host (#71436)
* fix(media): remove express from media host

* fix(media): harden media host responses

* fix(msteams): stage express runtime dependency

* fix(browser): align profile facade exports

* fix(msteams): keep setup entry narrow

* fix(types): satisfy extension setup gates

* fix(msteams): use generic setup config type
2026-04-25 01:39:42 -07:00
Peter Steinberger
3169886a21 fix(telegram): guard duplicate polling leases 2026-04-25 09:38:51 +01:00
Vincent Koc
c88c2328c2 docs: align Node minimum requirement 2026-04-25 01:36:01 -07:00
Vincent Koc
ec1f72b6c5 fix(gateway): preserve restart drain for active runs
Fixes https://github.com/openclaw/openclaw/issues/65485
2026-04-25 01:35:47 -07:00
Vincent Koc
734748d4f4 fix(test): cap native worker pools for serial Vitest 2026-04-25 01:31:30 -07:00
Peter Steinberger
bc21f500d4 fix: align Codex Responses instructions payload 2026-04-25 09:30:34 +01:00
Peter Steinberger
bf0221c5b3 fix(plugins): preserve bundled cli metadata skip 2026-04-25 09:29:16 +01:00
Peter Steinberger
87e92c71a4 docs(release): require changelog rewrite from commits 2026-04-25 09:29:16 +01:00
Peter Steinberger
689a353621 fix(plugins): load packaged runtime mirrors from canonical sources 2026-04-25 09:29:16 +01:00
Peter Steinberger
8503935a21 test: speed up changed unit checks 2026-04-25 09:27:59 +01:00
Peter Steinberger
9ad14f3639 fix: restore msteams channel plugin api type 2026-04-25 09:27:59 +01:00
Vincent Koc
bf0d2d70be fix(session): clean up rollover resources 2026-04-25 01:27:16 -07:00
Peter Steinberger
b0c55eb659 fix(feishu): transcode voice TTS audio 2026-04-25 09:26:42 +01:00
Vincent Koc
bd32b1a906 feat(diagnostics): add outbound delivery lifecycle events
Add bounded outbound message delivery lifecycle diagnostics and OTEL export without message body, recipient, room, media path, or raw channel result data.
2026-04-25 01:26:34 -07:00
Peter Steinberger
9e149519fe fix: keep control ui bundle browser-safe 2026-04-25 09:22:49 +01:00
Peter Steinberger
65b607245a fix(browser): ignore handled route navigation races
Co-authored-by: Richard Steadman <198648604+Steady-ai@users.noreply.github.com>
2026-04-25 09:22:31 +01:00
Val Alexander
af56926e2f Polish markdown preview chrome
Polish the Control UI markdown preview chrome and sidebar raw-text behavior.

- Add the upgraded preview dialog/sidebar chrome and tighten related CSS coverage.
- Show workspace-relative paths in the markdown preview dialog instead of absolute filesystem paths.
- Preserve raw markdown source for idempotent raw-text toggles.
- Align browser plugin-sdk facade export parity for DEFAULT_BROWSER_ACTION_TIMEOUT_MS.
- Stabilize the gateway update channel test by waiting for the async update runner call.

Validation:
- OPENCLAW_LOCAL_CHECK=0 pnpm test ui/src/ui/views/agents.test.ts ui/src/ui/views/chat.test.ts src/plugins/contracts/plugin-sdk-subpaths.test.ts src/gateway/server.roles-allowlist-update.test.ts
- OPENCLAW_LOCAL_CHECK=0 pnpm check:changed
- GitHub checks green on ebbe96fc88
2026-04-25 03:16:54 -05:00
Peter Steinberger
0e9156d205 test: stabilize Docker CLI backend lane 2026-04-25 09:12:48 +01:00
Peter Steinberger
5ac36c9719 fix(browser): detect more Linux Chromium installs (#48563)
Co-authored-by: Catalin Lupuleti <105351510+lupuletic@users.noreply.github.com>
2026-04-25 09:12:09 +01:00
Vincent Koc
0da58302cf docs(changelog): restore co-credits I dropped on Diagnostics/OTEL and tool-result pruning entries
Three entries were missing co-credits I should have preserved:

- Diagnostics/OTEL exec-process spans (#71451): @vincentkoc implemented,
  but @jlapenna's #70424 proposed the broader tracing work this entry
  builds on. Now credits both.
- Diagnostics/OTEL preloaded SDK (#71450): same pattern — credits
  @vincentkoc and @jlapenna.
- Agents/tool-result pruning (#51267): @cgdusek's PR explicitly built
  on prior work in #39331 by @alvinttang and #34980 by @coffeexcoin.
  Now credits all three.
2026-04-25 01:11:47 -07:00
Vincent Koc
56fbd72171 docs(changelog): correct PR refs and credits in top Unreleased section
- Two Diagnostics/OTEL Changes entries credited issue #70424 (jlapenna's
  open meta-tracing proposal) as the PR ref. The actual implementing
  PRs landed as #71451 (exec-process telemetry) and #71450 (preloaded
  SDK mode), both authored by @vincentkoc — corrected.
- Telegram/webhook fix had no Thanks credit. Issue #71392 reporter
  @joelforsberg46-source identified the delivery-retry behaviour, so
  credit them on the entry.
2026-04-25 01:07:48 -07:00
Peter Steinberger
24e9924d6a docs: credit blank reply recovery 2026-04-25 09:02:23 +01:00
Sanjay Santhanam
1f06dbd04c fix(agent): recover blank streamed replies from final answer 2026-04-25 09:02:23 +01:00
Quratulain-bilal
bc2d53dacd test(browser): cover tilde edge cases for executablePath (#71439)
* test(browser): cover tilde edge cases for executablePath

Adds coverage for cases the original tilde-expansion fix in 95a2c9b
intentionally supports but does not assert:

- bare "~" expands to the home directory
- Windows-style "~\AppData\..." expands to $HOME on Windows
- a stray "~" mid-path (e.g. /opt/~chromium/chrome) is preserved verbatim,
  guarding the regex anchor against future regressions

No production code changes; tests only.

* test(browser): skip Windows-style ~\ tilde test on POSIX

path.resolve treats backslashes as literal characters on POSIX, so
"~\AppData\..." cannot resolve to "$HOME/AppData/..." on Linux/macOS.
Gate that case to win32 to keep the assertion meaningful.
2026-04-25 09:01:57 +01:00
Peter Steinberger
a4fc6c2409 test: speed up slow unit checks 2026-04-25 08:59:53 +01:00
Peter Steinberger
2011de69d3 feat: add Crestodian setup helper 2026-04-25 08:58:21 +01:00
Peter Steinberger
e0bee76fb0 fix: retire one-shot agent MCP runtimes 2026-04-25 08:58:02 +01:00
a410979729-sys
8fd15ed0e5 fix(github-copilot): preserve encrypted reasoning ids with encrypted_content (#71448)
Preserve encrypted Copilot Responses reasoning item IDs during replay and harden the live Copilot replay probe.

Thanks @a410979729-sys.
2026-04-25 08:57:47 +01:00
github-actions[bot]
10ed007fb4 chore(ui): refresh th control ui locale 2026-04-25 07:57:39 +00:00
github-actions[bot]
4714a134d2 chore(ui): refresh pl control ui locale 2026-04-25 07:57:31 +00:00
github-actions[bot]
fb3efcf659 chore(ui): refresh id control ui locale 2026-04-25 07:57:27 +00:00
github-actions[bot]
6b4d8924eb chore(ui): refresh uk control ui locale 2026-04-25 07:57:12 +00:00
github-actions[bot]
4ca173a41c chore(ui): refresh tr control ui locale 2026-04-25 07:57:04 +00:00
github-actions[bot]
3019163e2e chore(ui): refresh ja-JP control ui locale 2026-04-25 07:56:53 +00:00
github-actions[bot]
e699b184af chore(ui): refresh fr control ui locale 2026-04-25 07:56:49 +00:00
github-actions[bot]
390f0487e8 chore(ui): refresh ko control ui locale 2026-04-25 07:56:45 +00:00
github-actions[bot]
2536fec538 chore(ui): refresh es control ui locale 2026-04-25 07:56:35 +00:00
github-actions[bot]
02ea62917e chore(ui): refresh zh-CN control ui locale 2026-04-25 07:56:10 +00:00
github-actions[bot]
812bc2a441 chore(ui): refresh de control ui locale 2026-04-25 07:56:06 +00:00
github-actions[bot]
7b58ffde85 chore(ui): refresh pt-BR control ui locale 2026-04-25 07:56:05 +00:00
github-actions[bot]
9dc608f54b chore(ui): refresh zh-TW control ui locale 2026-04-25 07:56:01 +00:00
Vincent Koc
ebb08dc70e fix(ui): use current context usage in Control UI 2026-04-25 00:54:33 -07:00
Vincent Koc
73d72204a0 fix(tooling): harden changed checks for sparse worktrees 2026-04-25 00:51:34 -07:00
Peter Steinberger
1ca029e888 fix: clean up infer MCP runtimes 2026-04-25 08:49:27 +01:00
Peter Steinberger
2b2a300b35 fix: align browser profile facade exports 2026-04-25 08:46:13 +01:00
Peter Steinberger
0f4b6f81d9 fix: canonicalize Codex image base URLs 2026-04-25 08:45:41 +01:00
Peter Steinberger
5163a2fbf7 docs: document Talk MLX config 2026-04-25 08:42:27 +01:00
Peter Steinberger
eafb25afc1 docs(google-meet): document dry run exports 2026-04-25 08:42:06 +01:00
Peter Steinberger
d78cef1d71 feat(google-meet): add export dry run manifests 2026-04-25 08:42:06 +01:00
Peter Steinberger
4a80e61680 fix: reap MCP runtimes on config reload 2026-04-25 08:40:45 +01:00
Peter Steinberger
7251551960 docs(google-meet): document export manifests 2026-04-25 08:38:43 +01:00
Peter Steinberger
388e0eb605 feat(google-meet): add export manifests and tool parity 2026-04-25 08:38:43 +01:00
Vincent Koc
13f4657b88 test(plugins): cover install ledger reload indexing 2026-04-25 00:37:06 -07:00
Vincent Koc
8fd3f4cef2 test(plugins): lock installed index source contract 2026-04-25 00:37:06 -07:00
Vincent Koc
28eb56dd21 fix(plugins): index install ledger source facts 2026-04-25 00:37:05 -07:00
Vincent Koc
15d27d1527 feat(channels): read setup discovery from installed index 2026-04-25 00:37:05 -07:00
Vincent Koc
0b2bc8c5f6 feat(models): read provider owners from installed index 2026-04-25 00:37:05 -07:00
Vincent Koc
ea3e390346 feat(plugins): split cold provider contributions 2026-04-25 00:37:05 -07:00
Vincent Koc
fb4eec54a7 feat(plugins): add installed plugin index 2026-04-25 00:37:04 -07:00
Peter Steinberger
7a71a66571 perf: cache provider env var lookups 2026-04-25 08:35:57 +01:00
Peter Steinberger
e9b27ed2a6 perf: speed up auth choice tests 2026-04-25 08:31:40 +01:00
Peter Steinberger
5fe333ada8 docs(google-meet): update export workflow notes 2026-04-25 08:28:34 +01:00
Peter Steinberger
03484b74ab feat(google-meet): polish exports and calendar previews 2026-04-25 08:28:34 +01:00
Peter Steinberger
e0beea97aa perf: speed up focused tests 2026-04-25 08:26:28 +01:00
Peter Steinberger
7132ca5766 feat(browser): include safe tab urls in agent responses 2026-04-25 08:24:46 +01:00
Peter Steinberger
e8191e5b8f fix: ack Telegram webhooks before update handling 2026-04-25 08:23:03 +01:00
Peter Steinberger
a44800e929 fix(google-meet): preserve lazy cli import 2026-04-25 08:17:55 +01:00
Peter Steinberger
e1cf94f49a docs(google-meet): document export and calendar lookup 2026-04-25 08:17:54 +01:00
Peter Steinberger
d3595d7c3f feat(google-meet): add calendar export attendance workflows 2026-04-25 08:17:54 +01:00
Peter Steinberger
9577de2da7 docs: reference fixed MCP lifecycle reports 2026-04-25 08:15:16 +01:00
Vincent Koc
3e3bba4f30 feat(diagnostics): emit exec process telemetry (#71451) 2026-04-25 00:12:58 -07:00
Peter Steinberger
188bce424b perf: speed up google meet tests 2026-04-25 08:12:26 +01:00
wzp
845040214e fix: recover subagent waits after transport drops
Fix subagent recovery and session state reconciliation.

Thanks @ZiPengWei.
2026-04-25 08:12:20 +01:00
Peter Steinberger
5376a4a5d6 fix(browser): default act timeout budget
Co-authored-by: Andy Lin <andyylin@users.noreply.github.com>
2026-04-25 08:11:48 +01:00
Peter Steinberger
712f7b218c test: cover bundled MCP runtime cleanup gates 2026-04-25 08:10:34 +01:00
Vincent Koc
9895ecead3 fix(memory): keep llama runtime optional (#71425)
* fix(memory): keep llama runtime optional

* fix(memory): harden optional llama runtime guard
2026-04-25 00:09:12 -07:00
Peter Steinberger
4005a4f731 feat(google-meet): default artifacts to latest record 2026-04-25 08:07:48 +01:00
Peter Steinberger
459d277076 feat(google-meet): add latest conference command 2026-04-25 08:04:29 +01:00
Vincent Koc
dfa52aaab0 docs(changelog): clean up top Unreleased section formatting and dedupe
- Remove duplicate #66884 alexlomt entry from top Unreleased > Fixes;
  the canonical entry already lives under 2026.4.24 (Unreleased) per
  Mason Huang's earlier 'move #66884 entry to 2026.4.24' commit.
- Reflow the wrapped 3-line Tool Access bullet (#71405) onto a single
  line so it matches every other bullet in the section.
2026-04-25 00:00:02 -07:00
Vincent Koc
d8a70a7e49 docs(changelog): add missing entries for 3 external-contributor PRs
Three external-contributor commits from the last day landed without
CHANGELOG entries:

- Alex Fries (#68286, @ajfonthemove): hybrid memory search component
  scores. Added under Unreleased > Changes (feat).
- Charles Dusek (#51267, @cgdusek): malformed tool-result text-block
  guard. Added under Unreleased > Fixes.
- Jerome Benoit (#59935, @jerome-benoit): Nix Home Manager daemon PATH
  support. Added under Unreleased > Fixes.

Also drop a duplicate raw-subject changelog line for #66884 that
restated alexlomt's already-formatted entry one line above.
2026-04-24 23:56:46 -07:00
Ayaan Zaidi
8e40bdba90 fix(cli): scope dev reset to active profile 2026-04-25 12:25:45 +05:30
Vincent Koc
56eb1ffabf fix(diagnostics-otel): support preloaded sdk mode (#71450) 2026-04-24 23:55:34 -07:00
Peter Steinberger
417b1c5507 feat(google-meet): export artifacts reports 2026-04-25 07:53:31 +01:00
Peter Steinberger
bb5e278f63 fix(feishu): stabilize topic group session keys 2026-04-25 07:53:05 +01:00
Peter Steinberger
d068cb960d fix: stabilize qa lab memory and thinking scenarios 2026-04-25 07:50:04 +01:00
Peter Steinberger
b34ece705f fix: retire idle bundled MCP runtimes 2026-04-25 07:49:12 +01:00
Alex Fries
66e66f19c6 feat(memory-core): expose hybrid search component scores
Expose raw `vectorScore` and `textScore` alongside the combined hybrid memory search `score`.

- Preserve vector/text component scores from `mergeHybridResults` output.
- Add optional component-score fields to both memory host SDK type surfaces.
- Extend hybrid merge tests for vector-only, text-only, and overlapping result cases.
- Document that component scores remain raw retrieval diagnostics while temporal decay/MMR only adjust or reorder the combined ranking `score`.

Closes #68166.

Maintainer verification:
- `pnpm test extensions/memory-core/src/memory/hybrid.test.ts`
- `pnpm check:changed`
- Fresh GitHub checks passed.

Co-authored-by: Alex Fries <alex@engramlabs.io>
2026-04-25 01:46:03 -05:00
Peter Steinberger
a983ea61ac feat(google-meet): include transcript entries in artifacts 2026-04-25 07:43:49 +01:00
Ayaan Zaidi
356530598a docs(changelog): note restart continuation recovery (#70780) (thanks @fuller-stack-dev) 2026-04-25 12:12:52 +05:30
Ayaan Zaidi
a903df02f5 fix(gateway): bound restart continuation recovery 2026-04-25 12:12:52 +05:30
FullerStackDev
03addfe9ba fix(gateway): tighten session delivery recovery 2026-04-25 12:12:52 +05:30
FullerStackDev
2261550633 fix(gateway): address restart continuation review comments 2026-04-25 12:12:52 +05:30
FullerStackDev
0ac81d41b6 fix(gateway): durably hand off restart continuations 2026-04-25 12:12:52 +05:30
Vincent Koc
4df0e10623 fix(feishu): back off failed streaming card starts 2026-04-24 23:41:01 -07:00
Peter Steinberger
d37f165bee feat(google-meet): add oauth doctor 2026-04-25 07:40:25 +01:00
Peter Steinberger
2ff7eb36cf fix(models): expose codex runtime context caps 2026-04-25 07:38:31 +01:00
Vincent Koc
3d554aefdf fix(logging): keep log transport internals private (#71322)
* fix(logging): share transports across module instances

* fix(logging): share transports across module instances

* fix(logging): share transports across module instances

* fix(logging): remove global log transport hooks

* test(agents): capture diagnostic logs after module reset
2026-04-24 23:36:57 -07:00
Charles Dusek
6b38714cb9 fix(agents): guard malformed tool result text blocks
Harden context pruning and tool-result character estimation against malformed `{ type: "text" }` blocks created by void/undefined tool handler results.

- Require text blocks to carry a string before using `.length` in the tool-result estimator.
- Guard context-pruning text/image loops against malformed and null content entries.
- Serialize malformed non-string text blocks for pruning size accounting so they cannot bypass trimming as zero-sized.
- Add regression coverage for malformed text blocks, null entries, and non-string text payloads.

Closes #34979.

Maintainer verification:
- `pnpm test src/agents/pi-embedded-runner/tool-result-char-estimator.test.ts src/agents/pi-hooks/context-pruning/pruner.test.ts`
- `pnpm check:changed`
- GitHub checks passed, including the OpenAI / Opus 4.6 parity gate.

Based on prior work by #39331 and #34980.

Co-authored-by: Charles Dusek <cgdusek@gmail.com>
Co-authored-by: alvinttang <alvinttang@users.noreply.github.com>
Co-authored-by: coffeexcoin <coffeexcoin@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-25 01:36:40 -05:00
Peter Steinberger
1752b15a21 feat(google-meet): add artifacts and attendance commands 2026-04-25 07:36:10 +01:00
Peter Steinberger
209d50b52c feat(browser): add coordinate click action
Co-authored-by: Daniel Lutts <daniellutts@10-19-94-204.dynapool.wireless.nyu.edu>
2026-04-25 07:31:33 +01:00
Val Alexander
982230f460 Refine tool access controls (#71405)
* feat(ui): refine tool access controls

* fix(ui): tighten tool access scanning

* fix(ui): keep tool access toggles visible (#71405)

* test(daemon): cover launchd restart fallback plist reads (#71405)

* test(daemon): drop duplicate launchd read mock (#71405)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-25 07:22:53 +01:00
Vincent Koc
d7fae7a5e7 docs(changelog): note Feishu streaming dedupe fix (#71431) 2026-04-24 23:21:40 -07:00
Vincent Koc
b59ba1dc8e docs: cover new contextInjection 'never' mode and Nix daemon PATH support
Two recent code changes lacked or had only partial doc coverage:

- contextInjection 'never' (#65006, xDarkicex): the new mode is now
  documented under agents.defaults.contextInjection, alongside the
  existing 'continuation-skip' mode, with guidance on when to use it
  (custom context engines, native runtimes that own their prompt).
- Nix Home Manager daemon PATH (#44402, jerome.benoit): document the
  service PATH auto-discovery (NIX_PROFILES right-to-left precedence
  and ~/.nix-profile/bin fallback) under the Nix install page.

Also sentence-case three Title-Cased headings on the Nix page ('What
You Get', 'Quick Start', 'Nix Mode Runtime Behavior') and drop a
duplicate body H1 that restated the frontmatter title.
2026-04-24 23:19:06 -07:00
ToToKr
2aa313cd90 fix(feishu): prevent duplicate message after streaming card close (#67791) (#68491)
* fix(feishu): prevent duplicate message after streaming card close (#67791)

When onIdle closed the streaming card before the final delivery arrived, the streamed text was not tracked in deliveredFinalTexts. The subsequent final payload bypassed the streaming?.isActive() guard (already closed) and fell through to the non-streaming path, sending the same content as a redundant text/card message. Track raw streamText in deliveredFinalTexts when closeStreaming finalizes the card so the duplicate-final check catches it.

* test(feishu): cover idle streaming final dedupe

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-04-24 23:18:10 -07:00
Peter Steinberger
36eae5a2c7 fix: tighten silent cron exec notifications 2026-04-25 07:15:08 +01:00
Mark Goldenstein
bd60df3e53 fix: silence cron exec completion noise 2026-04-25 07:15:08 +01:00
Peter Steinberger
017252e4f8 test(daemon): remove duplicate launchd read mock 2026-04-25 07:12:17 +01:00
Jérôme Benoit
b8b270d5b8 fix(daemon): add Nix Home Manager PATH support
Add Nix Home Manager profile bin directories to generated gateway service PATHs on macOS and Linux.

Includes ~/.nix-profile/bin fallback when NIX_PROFILES is absent, honors NIX_PROFILES right-to-left precedence when present, and covers the service PATH resolver with focused unit tests.

Closes #44402.
2026-04-25 01:12:10 -05:00
Peter Steinberger
33d5ebbff7 test(daemon): read launchd fixture files 2026-04-25 07:11:33 +01:00
Peter Steinberger
2a96ea4d72 test(agents): cover committed delivery fallback 2026-04-25 07:11:33 +01:00
Peter Steinberger
07cf1dd65c test: remove duplicate launchd read mock 2026-04-25 07:10:32 +01:00
Peter Steinberger
85cab8b516 test: fix launchd restart mock state 2026-04-25 07:09:47 +01:00
Peter Steinberger
22aa402b64 test(daemon): mock launchd plist reads 2026-04-25 07:08:36 +01:00
Peter Steinberger
d957401c7e test(daemon): type launchd kickstart code fake 2026-04-25 07:08:36 +01:00
Peter Steinberger
a7c8a1ba0d fix(browser): finish existing-session attach port (#57245) 2026-04-25 07:08:36 +01:00
Peter Steinberger
998e09ee00 docs(changelog): note browser existing-session fixes (#57245) 2026-04-25 07:08:36 +01:00
Peter Steinberger
ad8737af2c fix(browser): tighten WS3 status probes
# Conflicts:
#	extensions/browser/src/browser/chrome-mcp.test.ts
#	extensions/browser/src/browser/chrome-mcp.ts
#	extensions/browser/src/browser/routes/basic.ts
2026-04-25 07:08:35 +01:00
Peter Steinberger
3c31facfa2 Fix sticky Chrome MCP status probes
# Conflicts:
#	extensions/browser/src/browser/chrome-mcp.ts
#	extensions/browser/src/browser/server-context.ts
2026-04-25 07:08:35 +01:00
Peter Steinberger
8e18b3cc20 fix(browser): report attach-only profile transport truthfully
# Conflicts:
#	extensions/browser/src/browser/routes/basic.ts
2026-04-25 07:08:35 +01:00
Peter Steinberger
0ff7aa5c3d fix(browser): retry stale cached playwright attach once
(cherry picked from commit ec252ebd7b45d54e431e0d7599532e5a0c1a9b73)

# Conflicts:
#	extensions/browser/src/browser/pw-session.ts
2026-04-25 07:08:35 +01:00
Peter Steinberger
d6a9165b9e test: stabilize gateway and TTS tests 2026-04-25 07:07:58 +01:00
Peter Steinberger
996ec2dd76 fix(agents): key fallback on committed delivery 2026-04-25 07:06:46 +01:00
Valentinws
4a68fa3962 fix(ui): keep tmp-dir resolver browser-import safe
Defers the Node fs.constants lookup until tmp-dir resolution actually runs, adds browser-shim import regression coverage, and records the fix in the changelog.\n\nLocal verification:\n- pnpm test src/infra/tmp-openclaw-dir.browser-import.test.ts src/infra/tmp-openclaw-dir.test.ts src/logging/logger.browser-import.test.ts\n- pnpm test src/infra/run-node.test.ts -t "serializes runtime postbuild restaging|forwards wrapper SIGTERM"\n- pnpm build\n\nCo-authored-by: Valentinws <Valentinws@users.noreply.github.com>
2026-04-25 07:02:10 +01:00
Vincent Koc
f5868ad1f8 fix(daemon): refresh launchd plist before restart bootstrap (#71421) 2026-04-24 22:59:21 -07:00
xDarkicex
cc0992564b fix: add contextInjection never mode (#65006) (thanks @xDarkicex) 2026-04-25 11:26:21 +05:30
Peter Steinberger
18ffa81564 fix(agents): suppress delivered messaging fallback 2026-04-25 06:55:47 +01:00
Vincent Koc
47a4124dc3 fix(daemon): tolerate loaded launchctl bootstrap (#71413) 2026-04-24 22:54:12 -07:00
Peter Steinberger
cfb551c709 test(openrouter): cover DeepSeek live cache hits 2026-04-25 06:49:08 +01:00
Peter Steinberger
2cd2732ab6 docs: document trusted CIDR node auto-approval 2026-04-25 06:46:26 +01:00
Peter Steinberger
537a8e25ed fix(signal): classify filename-only voice notes 2026-04-25 06:45:54 +01:00
Peter Steinberger
f44759073b feat(gateway): auto-approve trusted CIDR node pairing (#61004) (thanks @sahilsatralkar) 2026-04-25 06:40:25 +01:00
Sukhdeep
6c1d4414d9 fix(browser): dedupe concurrent lazy start (#61772) (#61772)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-25 06:39:14 +01:00
Peter Steinberger
d79b9e0af4 fix(openrouter): allow DeepSeek cache-ttl eligibility 2026-04-25 06:38:34 +01:00
Peter Steinberger
29f7a2f441 docs(cron): clarify isolated session context 2026-04-25 06:37:18 +01:00
Peter Steinberger
f2745aa03a refactor(cron): clarify ambient session context rollover 2026-04-25 06:37:18 +01:00
Ziy
eaf6d3c146 fix(dashboard): keep bearer token out of runtime logs
Avoid logging tokenized Control UI URLs or SSH hints while preserving clipboard/browser token handoff.\n\nThanks @Ziy1-Tan!
2026-04-25 06:36:11 +01:00
Peter Steinberger
c2a2a481b2 fix(whatsapp): preserve audio-as-voice payload intent 2026-04-25 06:35:57 +01:00
monsonego
80b6da72f5 test(ui): cover nested qualified chat model refs (#65340)
Adds regression coverage for provider-qualified nested model ids such as nvidia/deepseek-ai/deepseek-v3.2.

Validated:
- pnpm test ui/src/ui/chat-model-ref.test.ts ui/src/ui/chat-model-select-state.test.ts

Thanks @monsonego.
2026-04-25 06:32:47 +01:00
Peter Steinberger
0970fc5da7 ci: relax bundled channel fast smoke timeout 2026-04-25 06:31:39 +01:00
Mason Huang
d4ed19dafc chore(changelog): move #66884 entry to 2026.4.24 (#71410) 2026-04-25 13:31:33 +08:00
Peter Steinberger
5b59079fd4 fix(tts): preserve audio-only hook transcript 2026-04-25 06:28:54 +01:00
Vincent Koc
88ea3d839b docs: sentence-case Title Case table headers in Codex/runtime docs
Three table headers introduced in recent agent-runtime / Codex-harness
doc commits used Title Case despite the surrounding house style:

- agent-runtimes.md L17: 'What It Means' -> 'What it means'
- agent-runtimes.md L100: 'Why It Matters' -> 'Why it matters'
- codex-harness.md L615: 'V1 Boundary' / 'Future Path' ->
  'V1 boundary' / 'Future path' (V1 stays as the recognized acronym)
2026-04-24 22:27:10 -07:00
Vincent Koc
57f5b3b201 fix(daemon): harden launchd restart handoff (#71409) 2026-04-24 22:27:05 -07:00
Vincent Koc
44ad970e48 docs: replace generic 'this page covers' intros with direct openings
Four pages started with weak meta-descriptions ('This page covers...')
that restate the frontmatter summary. Replace with direct content-first
openings, and sentence-case a stray 'Slash Commands' link in
configuration-reference.
2026-04-24 22:25:03 -07:00
Vincent Koc
93346b00fb docs: drop redundant body H1s that duplicated frontmatter title
- concepts/streaming.md: remove '# Streaming + chunking'.
- reference/session-management-compaction.md: remove Title Case H1
  '# Session Management & Compaction (Deep Dive)'.
- plugins/voice-call.md: remove '# Voice Call (plugin)'.

CLI pages keep their command-formatted body H1s since that is the repo
convention and the formatting is not expressible in frontmatter.
2026-04-24 22:23:45 -07:00
Peter Steinberger
f9c268cf56 ci: keep fast fixture edits on narrow path 2026-04-25 06:22:57 +01:00
Peter Steinberger
576c6c240f fix(discord): collapse cron announce text 2026-04-25 06:22:30 +01:00
Vincent Koc
ee3c32c103 docs(plugins): clarify inspector package boundary 2026-04-24 22:21:53 -07:00
Sean Coley
a35333abe1 fix(browser): recover stale Chromium profile locks (#62935) (#62935)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-25 06:21:49 +01:00
Peter Steinberger
f00d65a304 test: align status scan compatibility fixture 2026-04-25 06:18:32 +01:00
Peter Steinberger
2f097c47f8 ci: route narrow ci changes through fast path 2026-04-25 06:18:32 +01:00
Vincent Koc
c948c63bbd docs: unify casing and replace path-as-text links across recent doc surfaces
Sweep recent (last ~5h) doc edits for two readability/uniformity issues:

- Replace 42 path-as-text links of the form '[/foo/bar](/foo/bar)' with
  descriptive labels derived from each target page's frontmatter title
  (e.g. '[Anthropic]', '[Token use and costs]', '[OpenAI-compatible
  endpoints]'). Affected files include gateway/troubleshooting,
  concepts/oauth, reference/session-management-compaction, and
  reference/transcript-hygiene.
- Sentence-case Title-Cased headings and link text in Related sections
  across codex-harness, model-providers, tools/plugin, sdk-runtime,
  sdk-setup, prompt-caching, ci, cli/config, google-meet, browser,
  rich-output-protocol, subagents, web/control-ui, while preserving
  brand and proper-noun capitalization (OpenAI, Codex, Chrome, Parallels,
  Z.AI, etc.).
2026-04-24 22:18:22 -07:00
Peter Steinberger
88ca1859ed fix(discord): use undici multipart form data (#71383) 2026-04-25 06:18:10 +01:00
Peter Steinberger
439f353cf6 fix(discord): bridge undici multipart types 2026-04-25 06:18:10 +01:00
TC500
52ebdabcfd fix(discord): use undici form data for multipart uploads 2026-04-25 06:18:10 +01:00
Peter Steinberger
1afbfdf451 fix(control-ui): preserve optimistic chat tail 2026-04-25 06:15:55 +01:00
Vincent Koc
86dc820560 feat(plugins): add compatibility registry 2026-04-24 22:15:41 -07:00
Vincent Koc
f0ceb4b68f fix(cron): isolate fresh cron session state
* fix(cron): isolate fresh cron session state

* fix(cron): deep-copy isolated session state

* fix(cron): reset isolated session context

* test(providers): avoid shared mock races

* test(providers): type injected stream fakes

* ci: refresh package boundary on reply runtime changes

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-24 22:15:19 -07:00
alexlomt
7a9584f0f9 fix(ci): harden release checks workflow inputs (#66884)
Merged via squash.

Prepared head SHA: d4e0097301
Co-authored-by: alexlomt <181166594+alexlomt@users.noreply.github.com>
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
Reviewed-by: @hxy91819
2026-04-25 13:13:30 +08:00
Peter Steinberger
8acc92c881 feat(google): support Gemini TTS style profile 2026-04-25 06:11:23 +01:00
Peter Steinberger
3f63ba8fd8 fix(webchat): hide heartbeat history artifacts 2026-04-25 06:10:57 +01:00
Peter Steinberger
a2a49b430c test(plugins): route tts contract helper changes narrowly 2026-04-25 06:05:00 +01:00
Mason Huang
b79272baad CI: increase CodeQL JavaScript runner size (#71402)
* CI: increase CodeQL JavaScript runner size

* CI: trim CodeQL JavaScript scope further

* ci: keep CodeQL extension coverage

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-25 13:04:48 +08:00
Peter Steinberger
104a8f3f52 test(browser): handle oom wrapper in chrome launch assertion 2026-04-25 06:02:03 +01:00
Peter Steinberger
fa22ca8883 test(qa): cover stale subagent child links 2026-04-25 05:59:42 +01:00
Peter Steinberger
7f6452897e fix(agents): repair strict provider tool replay 2026-04-25 05:56:13 +01:00
Peter Steinberger
e31aef7e19 fix(tts): migrate legacy edge config in doctor 2026-04-25 05:55:54 +01:00
Peter Steinberger
b0e834b2d9 fix(browser): support per-profile executable paths
Co-authored-by: nobrainer-tech <nobrainer-tech@users.noreply.github.com>
2026-04-25 05:50:20 +01:00
Peter Steinberger
759fe0bf95 docs: cover reply media and voice-call fixes 2026-04-25 05:48:29 +01:00
Peter Steinberger
938b53698e test(voice-call): cover tunnel startup 2026-04-25 05:43:42 +01:00
Peter Steinberger
2b87d9f3ec fix(voice-call): reject local webhook fallback 2026-04-25 05:41:29 +01:00
Peter Steinberger
2f39e6df59 fix(tts): prefer active speech provider lookup 2026-04-25 05:39:10 +01:00
Peter Steinberger
2033075570 fix(sessions): hide stale subagent child links 2026-04-25 05:39:10 +01:00
Peter Steinberger
c11730fd09 fix(tts): keep speech fallback discovery scoped 2026-04-25 05:38:45 +01:00
Peter Steinberger
b8239be46b fix(voice-call): settle cleared tts queue 2026-04-25 05:38:36 +01:00
Jamil Zakirov
52267a6b75 fix(auto-reply): run message_sending before inbound delivery
Run inbound auto-reply delivery through message_sending hooks before sending replies.

Co-authored-by: Jamil Zakirov <15848838+jzakirov@users.noreply.github.com>
2026-04-25 10:07:35 +05:30
Peter Steinberger
04c5bbf33d fix(reply): dedupe block-streamed media 2026-04-25 05:35:31 +01:00
Peter Steinberger
98a99765af fix(gateway): invoke plugin-backed catalog tools
Co-authored-by: chat2way <chat2way@users.noreply.github.com>
2026-04-25 05:28:03 +01:00
Peter Steinberger
6602092a40 fix(browser): require admin scope for browser request
Co-authored-by: RichardCao <RichardCao@users.noreply.github.com>
2026-04-25 05:27:20 +01:00
Peter Steinberger
b84e57fca3 fix(tts): use resolved config for tool synthesis 2026-04-25 05:18:49 +01:00
Peter Steinberger
c2139635ff fix: format acpx doctor details safely 2026-04-25 05:15:00 +01:00
Peter Steinberger
757aee4cdd fix(subagents): retire stale unended runs
Co-authored-by: HCL <chenglunhu@gmail.com>
2026-04-25 05:14:41 +01:00
Peter Steinberger
97fd45a8c1 fix: honor acp allowed agents for acpx probe 2026-04-25 05:10:49 +01:00
Peter Steinberger
14eab13ab4 fix(agents): keep voice media with no-reply sentinel 2026-04-25 05:09:58 +01:00
Peter Steinberger
85db7af8d9 test: cover opencode-go image default pairing 2026-04-25 05:06:17 +01:00
Peter Steinberger
fa976e5b93 feat: update opencode-go default model
Co-authored-by: masrlinu <5259918+masrlinu@users.noreply.github.com>
2026-04-25 05:03:32 +01:00
Ted Li
8cc38c1b86 fix: stop session lock failover (#68700) (thanks @MonkeyLeeT)
* fix(agents): stop treating session lock waits as timeout

* fix(agents): ignore abort-wrapped session lock waits

* fix(agents): keep explicit failover metadata authoritative

* fix(agents): respect inferred failover metadata

* fix(agents): ignore generic abort codes for lock waits

* fix(agents): suppress cause-based lock wait fallback

* fix(agents): type session lock timeout errors

* fix: stop session lock failover (#68700) (thanks @MonkeyLeeT)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-04-25 09:33:19 +05:30
Peter Steinberger
c03e5b3c3a docs(tts): clarify legacy provider migration 2026-04-25 05:01:09 +01:00
Michiel van den Donker
2c716f5677 fix: enforce memory search session visibility (#70761) (thanks @nefainl)
* [EV-001] memory-core: filter memory_search session hits by visibility

- Move session visibility + listSpawnedSessionKeys to plugin-sdk; sync test
  hook with sessions-resolution __testing.setDepsForTest
- Extract loadCombinedSessionStoreForGateway to config/sessions; re-export
  from gateway session-utils
- Add session-transcript-hit stem resolver for builtin + QMD paths
- Post-filter memory_search results before citations/recall; fail closed when
  requester session key missing; optional corpus=sessions
- Tests: stem extraction, visibility filter smoke, existing suites green

* chore: sync plugin-sdk exports for session-transcript-hit and session-visibility

Run pnpm plugin-sdk:sync-exports so package.json exports match
scripts/lib/plugin-sdk-entrypoints.json. Fixes contract tests and
lint:plugins:plugin-sdk-subpaths-exported for memory-core imports.

* fix(EV-001): cross-agent session memory hits + hoist combined store load

- resolveTranscriptStemToSessionKeys: stop filtering by requester agentId so
  keys from other agents reach createSessionVisibilityGuard (a2a + visibility=all).
- Re-export loadCombinedSessionStoreForGateway from session-transcript-hit;
  filterMemorySearchHitsBySessionVisibility loads the combined store once per pass.
- Drop unused agentId from filter params; extend tests (Greptile/Codex review).

* fix(memory_search): honor corpus=sessions before maxResults cap

Pass sources into MemoryIndexManager.search so FTS/vector queries add
source IN (...) before ranking and top-N slice (Codex: non-session hits
could fill the window).

QMD path: oversample fetch limit for single-source recall, filter by
source, then diversify/clamp to the requested maxResults.

Wire corpus=sessions from tools; extend MemorySearchManager opts and
wrappers.

* fix(memory_search): apply corpus=memory source filter like sessions

Pass sources: ["memory"] into manager.search so maxResults applies only
within the memory index; post-filter for defense in depth. Document
corpus=memory in the tool description.

* fix: scope qmd session memory search

* fix: enforce memory search session visibility (#70761) (thanks @nefainl)

---------

Co-authored-by: NefAI <info@nefai.nl>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-04-25 09:30:21 +05:30
Peter Steinberger
978a50a3c5 fix(minimax): normalize tts pitch for api 2026-04-25 04:58:20 +01:00
Peter Steinberger
5d724863bb test: show live Docker profile mount 2026-04-25 04:57:20 +01:00
Peter Steinberger
b9da7cbf01 test: strip live gateway reasoning wrappers 2026-04-25 04:57:20 +01:00
Peter Steinberger
0f0c855a8b fix(google-meet): surface browser create manual actions 2026-04-25 04:57:06 +01:00
Peter Steinberger
70fd1c91aa fix(channels): harden tool progress previews 2026-04-25 04:54:29 +01:00
Peter Steinberger
da89108b82 docs(minimax): document tts env vars 2026-04-25 04:53:33 +01:00
Peter Steinberger
225ff9a866 fix(minimax): transcode voice-note tts to opus 2026-04-25 04:52:25 +01:00
Ayaan Zaidi
f3cc74ec5d fix: include exec completion payloads (#71213) (thanks @GodsBoy) 2026-04-25 09:21:29 +05:30
Ayaan Zaidi
a8f9e29e1a fix(heartbeat): classify untrusted exec completions 2026-04-25 09:21:29 +05:30
GodsBoy
724692bb8c chore(ci): refresh raw fetch allowlist 2026-04-25 09:21:29 +05:30
GodsBoy
349749f73d fix(heartbeat): include exec completion payloads 2026-04-25 09:21:29 +05:30
Peter Steinberger
7e52223d32 fix: register opencode image understanding 2026-04-25 04:50:01 +01:00
Ayaan Zaidi
398496c45b test(config): cover agent context token validation 2026-04-25 09:17:47 +05:30
statxc
ed03d91ae0 fix(config): allow per-agent contextTokens override in agents.list 2026-04-25 09:17:47 +05:30
Peter Steinberger
391289564c fix(media): validate managed reply media aliases 2026-04-25 04:47:25 +01:00
Peter Steinberger
a31374f097 fix: allow managed media from sandbox replies 2026-04-25 04:39:11 +01:00
Peter Steinberger
7875092f4d feat(openrouter): add tts provider 2026-04-25 04:36:49 +01:00
Peter Steinberger
c7f18a6b9d test(agents): cover Gemini incomplete-turn guard 2026-04-25 04:35:53 +01:00
Peter Steinberger
6f72b74cec fix: strip opencode image reasoning none 2026-04-25 04:35:12 +01:00
Peter Steinberger
96515891a2 fix: keep agent json stdout clean 2026-04-25 04:32:18 +01:00
Peter Steinberger
b0709a894d test(deepseek): cover V4 replay live 2026-04-25 04:30:38 +01:00
pashpashpash
6cfe810402 Refresh the Codex runtime docs
Refresh the Codex runtime docs and cross-link the Codex harness, OpenAI provider, agent runtime, plugin hook, ACP agent, and status pages.
2026-04-24 20:30:33 -07:00
Peter Steinberger
05fbdd4b28 fix: handle missing tailscale binary 2026-04-25 04:28:32 +01:00
Peter Steinberger
678ed5d512 fix(deepseek): normalize V4 tool-call replay 2026-04-25 04:25:44 +01:00
Peter Steinberger
c81b3ab6b9 fix(minimax): mark tts output voice-compatible 2026-04-25 04:25:12 +01:00
Ayaan Zaidi
de07739e40 docs: update changelog for gateway status perf 2026-04-25 08:52:52 +05:30
Ayaan Zaidi
2bf2fd6c3d fix(cli): preserve gateway status rpc probe semantics 2026-04-25 08:52:52 +05:30
Andy Lin
43beceaee7 perf(cli): trim gateway status startup work 2026-04-25 08:52:52 +05:30
Peter Steinberger
cc0f3e0e40 docs: add changelog for Gemini incomplete-turn recovery (#71362) 2026-04-25 04:21:35 +01:00
Neerav Makwana
0ec3b79c07 refactor: reuse model-id prefix helper for Gemini guard 2026-04-25 04:21:35 +01:00
Neerav Makwana
0ce93c9f1a fix: enable incomplete-turn recovery for Gemini 2026-04-25 04:21:35 +01:00
Peter Steinberger
73a6a2a6ab fix(tts): merge allowlisted speech providers 2026-04-25 04:20:04 +01:00
Peter Steinberger
cf07f01d0d docs(plugin-sdk): document browser tab cleanup config type 2026-04-25 04:19:50 +01:00
Peter Steinberger
5699209d00 fix: match bare exec allowlist commands
Co-authored-by: Kengwei Lu <kengwei@kvvlu.com>
Co-authored-by: ZC <chenzhangcode@163.com>
Co-authored-by: dengluozhang <275862143+dengluozhang@users.noreply.github.com>
2026-04-25 04:18:24 +01:00
Peter Steinberger
cb9c927ca6 docs: document config recovery policy 2026-04-25 04:18:24 +01:00
Peter Steinberger
0764f86e18 test(memory): keep embedding provider selection isolated 2026-04-25 04:17:27 +01:00
Peter Steinberger
8b31ba93b5 fix(plugin-sdk): align browser profile facade exports 2026-04-25 04:17:27 +01:00
Peter Steinberger
f1154fc5ed docs: note codex elicitation approval sanitization (#71343) (thanks @Lucenx9) 2026-04-25 04:17:27 +01:00
Lucenx9
e098a439c4 fix(codex): sanitize elicitation approval text 2026-04-25 04:17:27 +01:00
Peter Steinberger
972d8fc1cf fix(agents): keep reply tool snapshots aligned 2026-04-25 04:15:47 +01:00
Peter Steinberger
b13545355d fix(tts): parse bare tags and ignore code examples 2026-04-25 04:13:12 +01:00
Peter Steinberger
a126a9013d feat(plugins): expose nodes runtime to cli commands 2026-04-25 04:12:50 +01:00
Peter Steinberger
3731a7c8f2 fix(macos): retry talk tts via gateway 2026-04-25 04:09:43 +01:00
Peter Steinberger
9a0b26cafc test: cover config recovery policy edges 2026-04-25 04:06:35 +01:00
Josh Lehman
f369939fed fix: avoid plugin-local config recovery rollback (#71289) 2026-04-25 04:06:35 +01:00
Shakker
306c0f73bf feat: add manifest model catalog planner (#71368) (thanks @shakkernerd) 2026-04-25 04:05:30 +01:00
Shakker
b6c24e5322 fix: report model catalog manifest conflicts 2026-04-25 04:05:30 +01:00
Shakker
9e190f1f6a test: cover manifest model catalog planner 2026-04-25 04:05:30 +01:00
Shakker
dabdc779be feat: add manifest model catalog planner 2026-04-25 04:05:30 +01:00
Peter Steinberger
7920f8d4fd fix(compaction): honor manual keepRecentTokens 2026-04-25 04:03:09 +01:00
Peter Steinberger
92b17af817 fix(tts): honor legacy edge voice config 2026-04-25 04:02:17 +01:00
Peter Steinberger
5569d6d9d3 fix: accept singular tool_call finish reason 2026-04-25 04:00:03 +01:00
Shakker
8a14328c69 fix: normalize manifest catalog provider ids 2026-04-25 03:58:44 +01:00
Peter Steinberger
455e84f776 fix(voice-call): start listening after telnyx greetings 2026-04-25 03:57:47 +01:00
Peter Steinberger
344ee3782d fix(google-meet): guide timeout recovery 2026-04-25 03:57:26 +01:00
Peter Steinberger
37c2450124 fix: support draft 2020 mcp tool schemas 2026-04-25 03:56:35 +01:00
Peter Steinberger
9fbfedf12a fix: skip invalid completions stream chunks 2026-04-25 03:55:21 +01:00
Peter Steinberger
5381625f45 fix(voice-call): terminate expired restored calls 2026-04-25 03:55:01 +01:00
Peter Steinberger
fe930b987e fix(plugin-sdk): align browser tab cleanup type exports 2026-04-25 03:53:21 +01:00
Peter Steinberger
250acdd2a2 test(voice-call): cover cloudflare twilio signatures 2026-04-25 03:52:31 +01:00
Peter Steinberger
355c92d69b fix(sessions): honor load-time maintenance config 2026-04-25 03:52:25 +01:00
Peter Steinberger
26f06afb90 fix: forward completions prompt cache keys 2026-04-25 03:51:51 +01:00
Peter Steinberger
24fdfdba6e test: disable Docker CLI image probe by default 2026-04-25 03:51:41 +01:00
Peter Steinberger
a669ba7df1 fix(voice-call): reap stale pre-answer calls 2026-04-25 03:50:27 +01:00
Peter Steinberger
a98a0b94d1 fix: isolate browser proxy routing
Co-authored-by: Sanjays2402 <Sanjays2402@users.noreply.github.com>
2026-04-25 03:49:06 +01:00
Peter Steinberger
9e5d09c962 fix(config): reject legacy secretref env markers 2026-04-25 03:48:11 +01:00
Peter Steinberger
7dc005fab6 fix(voice-call): honor telephony tts timeout 2026-04-25 03:47:56 +01:00
Peter Steinberger
e5babbb5e7 test: cover openai-compatible usage chunks 2026-04-25 03:45:16 +01:00
Ada
413e407fb8 fix(whatsapp): deliver tool replies that include media (#60968)
Merged via squash.

Prepared head SHA: 26704020a4
Co-authored-by: adaclaw <266167987+adaclaw@users.noreply.github.com>
Co-authored-by: mcaxtr <7562095+mcaxtr@users.noreply.github.com>
Reviewed-by: @mcaxtr
2026-04-24 23:44:59 -03:00
Peter Steinberger
8f11e5ad18 fix(voice-call): scope sandbox session to agent 2026-04-25 03:43:01 +01:00
Peter Steinberger
460720d0a1 perf(feishu): avoid unconditional lifecycle waits 2026-04-25 03:41:18 +01:00
Peter Steinberger
a6d16a2153 perf(plugins): skip registry expansion for explicit document extractor allowlists 2026-04-25 03:41:18 +01:00
Peter Steinberger
28de3e1e5c perf(test): isolate core test hotspots 2026-04-25 03:41:17 +01:00
Peter Steinberger
c150110e02 test(voice-call): cover inbound transcript response handoff 2026-04-25 03:39:07 +01:00
Peter Steinberger
893c1d61ee fix: honor sandbox browser SSRF policy 2026-04-25 03:37:08 +01:00
Peter Steinberger
1906dc01bf fix(elevenlabs): omit mp3 accept for pcm tts 2026-04-25 03:36:54 +01:00
Peter Steinberger
7d5a7c4343 test(openai): preserve zero realtime transcription vad config 2026-04-25 03:34:41 +01:00
Shakker
55d3e7bc47 refactor: centralize model catalog normalization (#71360) (thanks @shakkernerd) 2026-04-25 03:34:36 +01:00
Shakker
c0bda91641 refactor: use shared model catalog normalization in manifests 2026-04-25 03:34:36 +01:00
Shakker
31f4991205 test: cover model catalog normalization 2026-04-25 03:34:36 +01:00
Shakker
b9da940813 feat: add model catalog normalizer 2026-04-25 03:34:36 +01:00
Shakker
efcd96a8eb feat: add model catalog shared types 2026-04-25 03:34:36 +01:00
Peter Steinberger
9a3dece879 fix(voice-call): allow dedicated response agent 2026-04-25 03:32:09 +01:00
Peter Steinberger
e442065970 feat(google-meet): add browser recovery diagnostics 2026-04-25 03:31:11 +01:00
Peter Steinberger
996e9226e5 fix(skills): restore legacy skill metadata fallback (#71346) 2026-04-25 03:30:51 +01:00
chen-zhang-cs-code
bb5f523068 fix(skills): honor legacy clawdbot metadata 2026-04-25 03:30:51 +01:00
Peter Steinberger
49f72b332f fix: harden openai-compatible completions payloads 2026-04-25 03:29:26 +01:00
Peter Steinberger
4302f6ea20 docs: credit codex bound-turn fix (#71317) 2026-04-25 03:29:14 +01:00
Lucenx9
cc87c9b120 fix(codex): reject unscoped bound turn events 2026-04-25 03:29:14 +01:00
Peter Steinberger
f7caf83da4 fix(voice-call): coalesce webhook server starts 2026-04-25 03:27:33 +01:00
Gustavo Madeira Santana
53618cca0d docs: clarify plugin discovery loading 2026-04-24 22:26:52 -04:00
Peter Steinberger
1bdf5307d9 refactor(discord): split outbound payload helpers 2026-04-25 03:24:42 +01:00
Peter Steinberger
30aa7e0d4d fix: harden Windows browser open 2026-04-25 03:24:00 +01:00
Peter Steinberger
31d8fdb525 fix(voice-call): answer telnyx inbound calls 2026-04-25 03:23:45 +01:00
Gustavo Madeira Santana
282c32db7c fix(cli): sanitize plugin command descriptors 2026-04-24 22:23:28 -04:00
Peter Steinberger
4da25d0125 fix: keep session store live during rotation 2026-04-25 03:21:49 +01:00
Peter Steinberger
f29e15c05d fix(telegram): bound tool progress preview formatting
Co-authored-by: Neerav Makwana <261249544+neeravmakwana@users.noreply.github.com>
2026-04-25 03:19:01 +01:00
Neerav Makwana
e54a37a91e fix(telegram): harden progress preview rendering 2026-04-25 03:19:01 +01:00
Neerav Makwana
c4a8b80dfa fix(telegram): hide tool progress by default 2026-04-25 03:19:01 +01:00
Peter Steinberger
95a2c9bcdc fix: expand browser executable home paths 2026-04-25 03:16:14 +01:00
Peter Steinberger
4a7ddd7ff5 test(agents): slim embedded runner hotspot coverage 2026-04-25 03:15:23 +01:00
Vincent Koc
f9ac92d1cc fix(deps): keep plugin ownership records live (#71331) 2026-04-24 19:15:12 -07:00
Peter Steinberger
f550aa7622 refactor(outbound): plan text and media sends 2026-04-25 03:12:59 +01:00
Peter Steinberger
a3862ffdf1 feat(voice-call): add setup smoke checks 2026-04-25 03:12:21 +01:00
Peter Steinberger
f9f7d6ffb5 fix(google-meet): reuse meet tabs across retries 2026-04-25 03:11:58 +01:00
Peter Steinberger
ba4cd90dbc fix(voice-call): share webhook runtime across contexts 2026-04-25 03:11:21 +01:00
Peter Steinberger
250d13de53 fix(agents): trust-gate tts transcript suppression
Co-authored-by: Neerav Makwana <261249544+neeravmakwana@users.noreply.github.com>
2026-04-25 03:11:17 +01:00
Neerav Makwana
628f0e8055 fix: gate tts output suppression on deliverable media 2026-04-25 03:11:17 +01:00
Neerav Makwana
db8f7478b4 fix: suppress tts transcript tool output 2026-04-25 03:11:17 +01:00
Gustavo Madeira Santana
6abab7555e test(plugins): align loader channel entry fixture 2026-04-24 22:10:58 -04:00
Peter Steinberger
713807b55d fix: harden openai auth and reasoning replay 2026-04-25 03:10:24 +01:00
Peter Steinberger
ae5c657367 fix: clean up idle browser tabs 2026-04-25 03:08:24 +01:00
Peter Steinberger
d99d9eda37 fix: honor media SSRF policy for PDF inputs (#71321) 2026-04-25 03:08:19 +01:00
Neerav Makwana
f9cb942aa9 fix(music): bound reference image fetches 2026-04-25 03:08:19 +01:00
Neerav Makwana
1bb5a96577 fix(media): cover generation reference media ssrf policy 2026-04-25 03:08:19 +01:00
Neerav Makwana
86556fcd47 fix(media): apply web fetch ssrf policy to media 2026-04-25 03:08:19 +01:00
Gustavo Madeira Santana
a5db42862d fix(plugins): expose channel CLI metadata in discovery (#71309)
Merged via squash.

Prepared head SHA: ce6bb35812
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-04-24 22:06:57 -04:00
Peter Steinberger
7ef4ecf499 refactor(outbound): share reply fanout policy 2026-04-25 03:05:22 +01:00
Peter Steinberger
2f23511ffa test: accept staged bundled runtime deps proof 2026-04-25 03:05:04 +01:00
Peter Steinberger
a5ab488691 fix(voice-call): pin response model sessions 2026-04-25 03:02:30 +01:00
Mason Huang
5d4931cc3f CI: trim CodeQL JavaScript scope (#71347) 2026-04-25 09:57:12 +08:00
Peter Steinberger
5e640b93da fix(discord): preserve outbound reply threading 2026-04-25 02:54:37 +01:00
Shakker
6d271762ab feat: add modelCatalog manifest contract (#71342) (thanks @shakkernerd) 2026-04-25 02:54:32 +01:00
Shakker
1f4dab2c37 fix: tighten model catalog manifest normalization 2026-04-25 02:54:32 +01:00
Shakker
a5d46c4567 fix: require complete model catalog pricing tiers 2026-04-25 02:54:32 +01:00
Shakker
8fa1052838 fix: tighten model catalog manifest validation 2026-04-25 02:54:32 +01:00
Shakker
d39e89e6b0 docs: document model catalog manifest metadata 2026-04-25 02:54:32 +01:00
Shakker
5e715de6c5 test: preserve model catalog manifest metadata 2026-04-25 02:54:32 +01:00
Shakker
61fcbe7dce feat: add model catalog manifest contract 2026-04-25 02:54:32 +01:00
Gustavo Madeira Santana
fd65caf4b0 chore: tighten changelog unreleased detection 2026-04-24 21:52:00 -04:00
Peter Steinberger
2a0a76f876 fix(browser): extend existing-session manage timeouts 2026-04-25 02:50:36 +01:00
Peter Steinberger
2ec70e6770 fix(browser): recover stale chrome mcp sessions 2026-04-25 02:50:11 +01:00
Luka Dolenc
325e5e921f fix: preserve thread-bound subagent completion fallback
Preserve the requester-agent announce path for thread-bound subagent completions, while falling back to direct thread delivery only when the announce fails or produces no visible output.\n\nThanks @DolencLuka.
2026-04-25 02:49:50 +01:00
Peter Steinberger
5865197ec1 test: relax bundled channel Docker readiness 2026-04-25 02:48:02 +01:00
Peter Steinberger
1eef6df5f5 test(auto-reply): reset inbound dedupe for acp abort 2026-04-25 02:47:52 +01:00
Peter Steinberger
69c258f9dc test(auto-reply): keep hook runner mock aligned 2026-04-25 02:47:52 +01:00
Peter Steinberger
f70e439699 fix(amazon-bedrock): skip auto memory embeddings without credentials (#71245)
Co-authored-by: bitloi <raphaelaloi.eth@gmail.com>
2026-04-25 02:47:52 +01:00
pashpashpash
42ec7a868f Document agent runtimes and the Codex v1 contract (#71270)
* Document agent runtimes and Codex v1 contract

* Document agent runtimes and Codex v1 contract

* Clarify Codex runtime fallback docs

* Clarify runtime and harness terminology
2026-04-25 10:46:24 +09:00
Peter Steinberger
0970507078 test(auto-reply): allow ACP abort dispatch in regression test 2026-04-25 02:45:07 +01:00
Peter Steinberger
56de930628 fix: honor codex approval decisions (#71338) (thanks @Lucenx9) 2026-04-25 02:44:55 +01:00
Lucenx9
453789914b fix(codex): respect command approval decisions 2026-04-25 02:44:55 +01:00
Peter Steinberger
d4a9b28d0c test: add agents delete Docker smoke 2026-04-25 02:43:11 +01:00
Peter Steinberger
32dd1ffc5a refactor(approvals): unify structured path display 2026-04-25 02:41:24 +01:00
Peter Steinberger
52ea8eadcb fix(codex): normalize compacted Windows permission paths 2026-04-25 02:40:57 +01:00
Peter Steinberger
e68b2269b9 test(telegram): avoid current marker in model display regression (#71016) (thanks @iskim77) 2026-04-25 02:38:14 +01:00
Peter Steinberger
a9c46d5b1a test(telegram): cover model picker display names (#71016) (thanks @iskim77) 2026-04-25 02:38:14 +01:00
Atlas Bot
d1386ada5a fix(telegram): pass modelNames to buildModelsKeyboard in button-click callback
When navigating the /models picker via provider button click, the model
list showed raw model IDs (e.g. gemini-3.1-pro-preview) instead of
configured display names (e.g. Gemini 3.1 Pro (Bridge)).

Root cause: the button-click callback handler destructured modelData as
{ byProvider, providers } omitting modelNames, then called
buildModelsKeyboard() without it. buildModelsKeyboard falls back to the
raw model ID via modelNames?.get(...) ?? model when modelNames is absent.

The text-command path (/models <provider>) already passes modelNames
correctly through buildTelegramModelsListChannelData, confirming the fix.

Fix: destructure modelNames from modelData and forward it to
buildModelsKeyboard in the button-click callback handler.

Closes #70560
2026-04-25 02:38:14 +01:00
Val Alexander
ead8be96fd Add tweakcn custom theme import
Adds a browser-local custom tweakcn theme slot while preserving the existing built-in themes.

Includes:
- tweakcn share-link import, validation, persistence, and custom theme rendering
- Custom option in Appearance and Quick Settings
- responsive/config toolbar and chat tool-card polish from follow-up review
- security hardening for bounded fetches, CSS token validation, redirect handling, and fail-closed unreadable payloads

Verification:
- OPENCLAW_LOCAL_CHECK=0 pnpm check:changed
- GitHub CI clean on 6ff13a1b33
2026-04-24 20:36:45 -05:00
Peter Steinberger
835c4e053c test: stabilize Docker live service lanes 2026-04-25 02:33:10 +01:00
Peter Steinberger
3a7ee209c9 fix: harden browser screenshot timeouts 2026-04-25 02:32:29 +01:00
Peter Steinberger
41f9768cd8 fix: preserve context engine safeguard compaction 2026-04-25 02:30:41 +01:00
Peter Steinberger
a9a308becd fix: recover restart-aborted main sessions 2026-04-25 02:25:54 +01:00
Peter Steinberger
50d3bd638a docs(changelog): note codex permission path compaction 2026-04-25 02:24:31 +01:00
Peter Steinberger
f86f8400f5 fix(codex): compact home permission paths 2026-04-25 02:24:00 +01:00
Peter Steinberger
0d3a5c3101 fix(codex): preserve approval permission paths 2026-04-25 02:24:00 +01:00
edge_kase
2cacd2097b fix: retain shared agent workspaces (#70897)
Fixes #70889 and #70890.

Retains overlapping/shared agent workspaces during `openclaw agents delete`, keeps `--json` output machine-readable, and repairs the stale hook-runner test harness mock that blocked CI.

Thanks @kaseonedge.
2026-04-25 02:22:06 +01:00
Peter Steinberger
52cc1ebac7 fix(google-meet): surface chrome node readiness in setup 2026-04-25 02:18:08 +01:00
Peter Steinberger
d9bd010e5e test: cover codex harness session history pinning 2026-04-25 02:15:33 +01:00
Vincent Koc
0bd8d0bba0 fix(plugins): remove Pi tool result compat 2026-04-24 18:13:35 -07:00
Roger Deng
ea168c22ce WhatsApp: add preflight audio transcription for DM voice notes (#64120)
Merged via squash.

Prepared head SHA: 7480b339da
Co-authored-by: rogerdigital <13251150+rogerdigital@users.noreply.github.com>
Co-authored-by: mcaxtr <7562095+mcaxtr@users.noreply.github.com>
Reviewed-by: @mcaxtr
2026-04-24 22:13:25 -03:00
Peter Steinberger
c018e73475 docs: document google adaptive thinking 2026-04-25 02:10:49 +01:00
Peter Steinberger
e2ade56952 test(deepseek): cover v4 reasoning replay payload 2026-04-25 02:09:51 +01:00
Peter Steinberger
8262735354 fix(plugins): harden runtime dependency repair 2026-04-25 02:07:19 +01:00
Peter Steinberger
cc0f3067a0 fix: map google adaptive thinking dynamically 2026-04-25 02:04:40 +01:00
Vincent Koc
f3330f5db6 docs(changelog): backfill 91 author credits and dedupe duplicate Thanks lines
- Expand author->handle map with maintainers from docs/CONTRIBUTING.md
  (Robin Waslander/@hydro13, Josh Lehman/@jalehman, Radek/@velvet-shark,
  Muhammed/@mukhtharcm, Tengji/@odysseus0, Sliverp, Mason Huang/@hxy91819)
  and PR-author lookups via gh for two dozen one-off contributors.
- Strip duplicate trailing 'Thanks @x' lines that prior backfill chunks
  had introduced when an existing lowercase 'thanks @y' credit was already
  present (case-sensitive skip check missed them); preserve the original
  contributor credit.
- Dedupe doubled '(#NNNN)' tokens introduced by the same bug.
2026-04-24 18:04:06 -07:00
Peter Steinberger
019ef71fe8 docs: require source-backed maintainer answers 2026-04-25 02:02:22 +01:00
Peter Steinberger
9ca1f1a64e fix(plugins): refresh gateway hooks before inbound dispatch 2026-04-25 02:01:48 +01:00
Peter Steinberger
fde4bf7fc1 docs: document packaged runtime dependency staging 2026-04-25 01:59:13 +01:00
Peter Steinberger
d42b0e043c fix: stage packaged bundled runtime deps externally 2026-04-25 01:58:44 +01:00
Vincent Koc
2d2402cee8 test(plugins): assert legacy channel schema exports 2026-04-24 17:58:04 -07:00
Vincent Koc
3a14a95085 fix(plugins): harden manifest channel metadata 2026-04-24 17:58:04 -07:00
Matt Van Horn
b33eb93aac fix(cron): default missing sessionTarget on load and guard assertSupportedJobSpec (#70367)
* fix(cron): default missing sessionTarget on load and guard assertSupportedJobSpec

* fix(cron): use Object.hasOwn for payload.kind check and log the backfill

Address review feedback on #70367:
- Switch the new payload.kind lookup from `in` to `Object.hasOwn` so
  prototype pollution cannot drive the defaulter (Aisle Low finding).
- Log a warning when a job is auto-defaulted at load time, matching the
  adjacent legacyJobIdIssue pattern so operators can run `openclaw
  doctor --fix` to persist the canonical shape (Greptile P2).

* fix(cron): dedupe sessionTarget backfill warn per jobId and sharpen crash site reference

Address deep-review feedback on #70367:

- The code comment referenced assertSupportedJobSpec as the tick-time
  crash site, but that function is only called from create/patch
  (jobs.ts:607, 686) and manual-run preflight (ops.ts:516). The actual
  on-tick TypeError surfaces in runIsolatedAgentJob (server-cron.ts).
  Update the comment to say so.

- ensureLoaded runs with forceReload:true on every onTimer tick (~60s).
  Before this change, a persistent legacy job missing sessionTarget
  produced one warn line per tick, forever. Add a per-jobId dedupe set
  on CronServiceState (mirroring the existing warnedDisabled flag) so
  the warn fires once per job per process.

- Drop the 'run openclaw doctor --fix' remediation from the warn
  message. Doctor's cron-store migration has no trackIssue entry for
  missing sessionTarget (doctor-cron-store-migration.ts CronStoreIssueKey),
  so doctor --fix on a store whose only defect is missing sessionTarget
  silently returns without writing anything. Point operators at
  jobs.json directly until that gap is closed.

* docs(changelog): note cron session target repair

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-04-24 17:57:39 -07:00
Peter Steinberger
c9b9d33451 docs(changelog): mark 2026.4.24 unreleased 2026-04-25 01:56:22 +01:00
Peter Steinberger
5086069c94 fix(cli-runtime): merge user mcp servers 2026-04-25 01:56:22 +01:00
Kei Shingu
b86a04262d fix(cli-runtime): replace overlapping user mcp servers 2026-04-25 01:56:22 +01:00
kei shingu
d8ae63e7a2 test(cli-runtime): add coverage for user mcp.servers merge in prepareCliBundleMcpConfig 2026-04-25 01:56:22 +01:00
kei shingu
61250e2bea fix(cli-runtime): merge user mcp.servers into claude-cli bundle config
prepareCliBundleMcpConfig was not including cfg.mcp.servers when building
the temporary mcp.json that gets passed to claude-cli via --mcp-config.
This meant user-defined MCP servers (e.g. mcp.servers.omi in openclaw.json)
were silently dropped, even though --strict-mcp-config prevents any other
path for those servers to reach the CLI session.

The Pi runtime path (loadEmbeddedPiMcpConfig) already merges cfg.mcp.servers
after the bundle layer. This commit applies the same merge to the CLI runtime
path, with identical precedence: bundle defaults < user mcp.servers <
additionalConfig (loopback). The loopback entry remains last so it cannot be
overridden by user config.

Fixes: user-configured MCP servers not appearing as mcp__<name>__* tools in
claude-cli sessions started by OpenClaw.
2026-04-25 01:56:22 +01:00
Vincent Koc
718dffd2f2 fix(diagnostics): harden capture redaction and discord metadata fetch (#71303) 2026-04-24 17:51:12 -07:00
Peter Steinberger
25a02825a5 test(google-meet): share plugin harness 2026-04-25 01:50:28 +01:00
Gforce10-design
5a202f6f90 fix(auth): bootstrap codex cli credential without clobbering local (#71310)
* fix(auth): bootstrap codex cli credential without clobbering local

readCodexCliCredentialsCached was imported but never registered in
EXTERNAL_CLI_SYNC_PROVIDERS, so overlayExternalAuthProfiles could not
seed openai-codex:default on fresh agents and runtime surfaced
"No API key found for provider openai-codex" even after a successful
codex login.

Register the provider with a new bootstrapOnly flag. Providers flagged
bootstrapOnly are adopted only to fill an empty slot: the overlay skips
them when a local OAuth credential already exists for the profile, and
readExternalCliBootstrapCredential returns null so the refresh path
never replaces the locally stored canonical refresh token with stale
CLI state. Minimax keeps its existing replace-on-expiry behavior.

* test(auth): cover codex cli bootstrap

---------

Co-authored-by: sudol <sudol@A8Max.localdomain>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-25 01:50:01 +01:00
Vincent Koc
6d49681a62 docs(changelog): backfill 104 more author credits with expanded handle map 2026-04-24 17:49:39 -07:00
Peter Steinberger
d610e2cc6c feat(browser): support per-profile headless
Co-authored-by: nakamotoliu <nakamotoliu2026@gmail.com>
Co-authored-by: Nakamoto <nakamoto@claude.ai>
2026-04-25 01:49:22 +01:00
Vincent Koc
5ea0ded5a5 docs(changelog): backfill 1471 author credits across all releases via git blame 2026-04-24 17:47:52 -07:00
Peter Steinberger
664b9fe7eb docs: note safe GitHub comment quoting 2026-04-25 01:44:55 +01:00
Peter Steinberger
867b4c2a32 fix(plugins): log runtime deps staging progress 2026-04-25 01:42:54 +01:00
Peter Steinberger
f9207e5d39 test(agents): cover defaults fallback timeout 2026-04-25 01:42:38 +01:00
Peter Steinberger
63dc5089b2 refactor(google-meet): split create browser flow 2026-04-25 01:40:50 +01:00
Peter Steinberger
8a0cb03300 fix(agents): skip empty embedded prompts 2026-04-25 01:39:28 +01:00
Peter Steinberger
ae57a7998e fix(telegram): persist accepted update offsets 2026-04-25 01:35:05 +01:00
Peter Steinberger
7c0549bd9f fix(google-meet): join created meetings by default 2026-04-25 01:31:51 +01:00
Peter Steinberger
d12987d725 fix(agents): fail fast on terminal provider 429s 2026-04-25 01:31:01 +01:00
Peter Steinberger
26bc5e47ee fix(browser): stabilize doctor diagnostics 2026-04-25 01:30:47 +01:00
Vincent Koc
df5abf9a98 docs(changelog): backfill 40 more 2026.4.22 authors via CHANGELOG diff matching 2026-04-24 17:27:45 -07:00
Peter Steinberger
554f93a999 fix(providers): keep minimax chat models text-only 2026-04-25 01:27:34 +01:00
Peter Steinberger
377e254f6a fix(config): avoid env-ref reload restarts 2026-04-25 01:23:15 +01:00
Peter Steinberger
8a490f4509 fix(browser): break doctor client import cycle 2026-04-25 01:22:47 +01:00
Peter Steinberger
4e42a4cfe8 fix(browser): preserve explicit ai snapshot refs
Fixes #62550.

Co-authored-by: ly85206559 <ly85206559@163.com>
2026-04-25 01:20:42 +01:00
Val Alexander
da773175f2 fix(control-ui): keep context usage fresh (#71297)
Patch live session usage metadata into the Control UI session list, coalesce overlapping refreshes, and add a compact action when fresh context usage is high.

Keep session refresh loading separate from session mutation ownership so background refreshes cannot re-enable mutation UI or overwrite delete/restore state mid-flight.

Co-authored-by: Val Alexander <68980965+BunsDev@users.noreply.github.com>
2026-04-25 01:20:12 +01:00
Peter Steinberger
d399ac74f7 fix(slack): hash token cache keys 2026-04-25 01:17:55 +01:00
Vincent Koc
b7c8c53af2 docs(plugins): define config ownership contract
* fix(plugins): flag channel config metadata gaps

* docs(plugins): clarify config ownership
2026-04-24 17:17:10 -07:00
Chris Zhang
de8a00d922 fix(plugins): preserve tokenjuice runtime rule data
Preserve tokenjuice runtime rule JSON under dist/rules/tests during bundled plugin runtime dependency staging while continuing to prune unrelated tests directories.
2026-04-24 17:16:06 -07:00
Peter Steinberger
30aa1f890a feat(browser): expose doctor diagnostics to agents
Co-authored-by: Sean Coley <github@seancoley.me>
2026-04-25 01:15:31 +01:00
Vincent Koc
b5a5b59742 docs(changelog): backfill 2026.4.21 + 2026.4.20 authors (gpt-image-2, presentation SDK, Kimi K2.6, wizard, LINE media, avatar auth, thread routing, YOLO exec, anthropic-messages, DevToolsActivePort) 2026-04-24 17:15:27 -07:00
Vincent Koc
e3cba98f39 refactor(pdf): move document extraction to plugin
* refactor(pdf): move document extraction to plugin

* fix(deps): sync document extract lockfile

* fix(pdf): harden document extraction plugin
2026-04-24 17:15:05 -07:00
Peter Steinberger
915931aa38 fix(agents): use captured cli lifecycle hook runner 2026-04-25 01:14:16 +01:00
Peter Steinberger
b69e3b633b refactor(slack): reuse default write clients 2026-04-25 01:13:55 +01:00
Vincent Koc
492dfdc7f2 docs(changelog): backfill 2026.4.22 authors (WeCom, Matrix DM, Claude CLI verify, LanceDB retry, Codex serviceTier) 2026-04-24 17:12:57 -07:00
Peter Steinberger
61ee67aecc fix(agents): fail empty explicit tool allowlists 2026-04-25 01:11:36 +01:00
Peter Steinberger
107d2b7a09 fix(slack): preserve rapid send ordering
Co-authored-by: nightq <zengwei@nightq.cn>
Co-authored-by: xydt cqh <cui.qianhong@xydigit.com>
2026-04-25 01:11:10 +01:00
Peter Steinberger
5f81147c4d fix: persist embedded runtime context budget 2026-04-25 01:09:45 +01:00
Vincent Koc
59f8a2c3fa docs(changelog): backfill 2026.4.22 authors (streaming STT, onboarding, Pi, Thai, status, transcript locks, uuid, MCP cleanup, Jiti) 2026-04-24 17:09:34 -07:00
Peter Steinberger
db958463f6 fix(codex): emit app-server final chat events (#71293)
Fix live webchat finalization for Codex app-server runs by emitting standard assistant and lifecycle completion events on the global agent event bus, instead of relying on a message-less chat.final fallback.

Replaces #70815. Closes #71183.

Co-authored-by: Lēsa <260982214+lesaai@users.noreply.github.com>
2026-04-25 01:09:11 +01:00
Peter Steinberger
f4add8047b test: relax Docker service command timeouts 2026-04-25 01:07:23 +01:00
Marcus Castro
a580db58ca docs(whatsapp): correct replyToMode values 2026-04-24 21:06:00 -03:00
Coy Geek
8ca66cad68 fix(browser): scope control auth to active gateway mode (#65639)
Browser control now authorizes only the resolved active gateway credential and fails closed when password mode lacks a resolved password.

Also removes the duplicate Slack test-helper middleware stub that kept current CI red after the base rebase.

Fixes #65626.

Co-authored-by: Coy Geek <65363919+coygeek@users.noreply.github.com>
2026-04-25 01:03:39 +01:00
Peter Steinberger
ea74e01ed6 fix(slack): resolve native approval buttons
Co-authored-by: Motoki Maruyama <motoki.maruyama@kiconiaworks.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-25 01:02:51 +01:00
Vincent Koc
e625651de8 feat(plugins): derive setup auth choices
* feat(plugins): derive setup auth choices

* fix(plugins): sanitize derived provider auth choices

* fix(plugins): clean up extension gate regressions
2026-04-24 16:57:39 -07:00
Peter Steinberger
fb80405693 test: fix slack bolt mock middleware 2026-04-25 00:57:09 +01:00
Peter Steinberger
829ace53d3 docs: note inbound media ref handling 2026-04-25 00:57:09 +01:00
Peter Steinberger
ddedcac54a test: stabilize full-suite lanes 2026-04-25 00:57:08 +01:00
Peter Steinberger
741d5d3231 fix(providers): narrow staged anthropic client type 2026-04-25 00:57:08 +01:00
Peter Steinberger
45730f6117 fix(gateway): resolve inbound assistant media refs 2026-04-25 00:57:07 +01:00
Peter Steinberger
14e0a8c2bc fix(agents): accept inbound media refs across tools 2026-04-25 00:57:07 +01:00
Peter Steinberger
4e9c83d4d8 fix(media): centralize inbound media reference resolution 2026-04-25 00:57:07 +01:00
Vincent Koc
aa27e27f36 fix(models): normalize provider runtime selection (#71259)
* fix(models): normalize provider runtime selection

* fix(models): reverse codex-only runtime migration

* fix(models): default runtime selection to pi

* fix(status): label model runtime clearly

* fix(status): align pi runtime label

* fix(plugins): align tool result middleware runtime naming

* fix(models): validate runtime overrides
2026-04-24 16:56:49 -07:00
Peter Steinberger
60e7b692cc docs(browser): document inspection diagnostics 2026-04-25 00:56:35 +01:00
Peter Steinberger
1d4859dc53 feat(browser): add doctor and richer inspection helpers 2026-04-25 00:56:35 +01:00
Peter Steinberger
d1cc54866d fix(slack): return non-image downloads as files 2026-04-25 00:55:57 +01:00
Peter Steinberger
cc2b4cf125 test(parallels): update npm smoke guard expectation 2026-04-25 00:53:01 +01:00
Peter Steinberger
b9b97f2653 test: raise Docker aggregate resource caps 2026-04-25 00:52:52 +01:00
Peter Steinberger
a1087ea7a6 fix(parallels): harden npm update smoke 2026-04-25 00:49:57 +01:00
Peter Steinberger
c12af80b5b fix(github-copilot): move pi-ai to dev dependency 2026-04-25 00:44:29 +01:00
Peter Steinberger
a57fbc8026 test(slack): cover fast draft preview finalization 2026-04-25 00:42:55 +01:00
Vincent Koc
d4d4a8c14e feat(diagnostics-otel): add content capture controls
Add opt-in diagnostics OTEL content capture controls, keep raw content export default-off, and guard the content-capture tests against magic truncation bounds.
2026-04-24 16:41:28 -07:00
Peter Steinberger
fbf8b216c6 fix: keep explicit image generation model exact 2026-04-25 00:39:07 +01:00
Peter Steinberger
e40d7abda9 fix(slack): preserve real thread anchors 2026-04-25 00:38:19 +01:00
Peter Steinberger
82020bd787 feat(browser): prefer suggested tab targets 2026-04-25 00:35:26 +01:00
Peter Steinberger
acb10cd21c fix(skills): honor default-enabled plugin skills 2026-04-25 00:35:26 +01:00
Vincent Koc
f6504ceb1d fix(discord): guard gateway metadata fetches 2026-04-24 16:33:54 -07:00
Peter Steinberger
b3db7c6987 fix: expose dynamic thinking options to UI 2026-04-25 00:33:42 +01:00
Peter Steinberger
5dab0dae56 test(cli): mock runtime plugin registry resolver 2026-04-25 00:32:02 +01:00
Peter Steinberger
0376987691 fix(plugins): preserve gateway hook runner
Co-authored-by: lanzhi-lee <36190508+lanzhi-lee@users.noreply.github.com>
2026-04-25 00:28:51 +01:00
Peter Steinberger
2b5c719a62 fix(slack): process thread broadcasts as messages 2026-04-25 00:26:31 +01:00
Peter Steinberger
dea05aae6b docs(browser): explain automation skill and tab handles 2026-04-25 00:24:33 +01:00
Peter Steinberger
45e2a15e29 feat(browser): add stable tab handles and automation skill 2026-04-25 00:23:55 +01:00
Peter Steinberger
86856b88e3 fix(slack): suppress reasoning in native streams 2026-04-25 00:23:16 +01:00
wei
3dba3d8b35 fix(discord): run message_sending hooks for replies
Fixes Discord reply delivery so `message_sending` plugin hooks can transform or cancel outbound Discord replies, including DM targets.

Fixes #59350.
Thanks @wei840222.
2026-04-25 00:19:24 +01:00
Peter Steinberger
4693d20cad fix(slack): keep block replies in first thread 2026-04-25 00:17:56 +01:00
Peter Steinberger
989193b4b4 test(discord): share empty config fixture 2026-04-25 00:16:18 +01:00
Peter Steinberger
0270428645 fix(plugins): reuse gateway boot registry for runtime ensures
Co-authored-by: Mark Ramos <6416874+markthebest12@users.noreply.github.com>
2026-04-25 00:14:31 +01:00
Peter Steinberger
c735b59043 fix(browser): remove stale snapshotForAI references 2026-04-25 00:10:03 +01:00
Peter Steinberger
5d9941c36d fix(discord): require runtime config in helpers 2026-04-25 00:09:45 +01:00
Peter Steinberger
beefcda68f fix: keep copilot on boundary-aware stream path 2026-04-25 00:06:40 +01:00
Peter Steinberger
1787ae0f5d fix(google-meet): reuse create tabs on retry 2026-04-25 00:04:01 +01:00
Peter Steinberger
50e484b22e fix(browser): use current aria snapshot refs 2026-04-25 00:04:01 +01:00
Peter Steinberger
272a72b716 test: relax Docker host command caps 2026-04-25 00:03:52 +01:00
Peter Steinberger
2a4fa8ffe8 fix(slack): scope assistant self-event bypass 2026-04-25 00:03:23 +01:00
Peter Steinberger
893a18ff5c fix(slack): accept assistant dm message edits 2026-04-25 00:00:17 +01:00
Peter Steinberger
3a6d50deb3 fix: satisfy Discord gateway fetch boundary (#70945) 2026-04-24 23:55:48 +01:00
Peter Steinberger
21162233d5 fix: harden Discord subagent thread config (#70945) 2026-04-24 23:55:48 +01:00
Jai Govindani
84571e45ce fix(discord): pass config to subagent thread binding 2026-04-24 23:55:48 +01:00
Peter Steinberger
0c46e8000e fix(plugins): cache discovery registration snapshots
Co-authored-by: junpei.o <14040213+livingghost@users.noreply.github.com>
Co-authored-by: Yoshiaki Okuyama <okuyam2y@gmail.com>
Co-authored-by: Shion Eria <shioneria@foxmail.com>
Co-authored-by: Billy Shih <1472300+bbshih@users.noreply.github.com>
2026-04-24 23:55:29 +01:00
Peter Steinberger
9eeceaca43 fix: send copilot headers during compaction 2026-04-24 23:54:58 +01:00
Devin Robison
a35c166348 fix(gateway): restart channels after secret reload (#70720)
* fix(gateway): restart channels after secret reload

* fix(gateway): serialize secrets.reload and isolate channel restart errors

Address review feedback from Greptile (P1), Codex (P2), and Aisle (Medium,
CWE-362) on #70720:

- Serialize the entire secrets.reload path through a promise tail lock so
  concurrent callers cannot overlap the stop/start loop or diff against a
  stale pre-activation snapshot.
- Wrap each channel's stop/start pair in a try/catch so one channel failing
  to restart does not leave other changed channels unrestarted.
- Register slack/zalo/discord channel plugins with reload.configPrefixes in
  the test setup so channels.<id>.* diff paths actually match a restart rule
  (without this, the diff falls through to restart-gateway and the handler
  never enters the per-channel restart branch).
- Add tests covering concurrent-reload serialization and per-channel
  restart-failure isolation.

* fix(gateway): surface channel restart failures from secrets.reload

Address review feedback on the previous commit:

- Codex P1: `secrets.reload` swallowed per-channel restart failures and
  still returned `{ ok: true }`, so a rotation that left a channel on the
  old secret looked successful to the caller. The handler now collects
  restart failures during the loop and throws an aggregate error after
  attempting every channel, so the client-side RPC response surfaces the
  partial failure while unaffected channels still restart (preserving the
  original Greptile P1 non-cascading semantic).
- Greptile P2: test mock-call assertions sorted the captured channel
  arguments so they no longer depend on `Set`/object-key iteration order,
  which is not a stable contract of the handler.

* fix(gateway): harden secrets reload followups

* docs(changelog): note secret-backed channel restart on secrets.reload

* test(gateway): align secrets reload snapshot activation

* test(gateway): reset plugin runtime state in aux handlers

* fix(gateway): refresh reload rules and roll back channels

* fix(gateway): harden secrets.reload rollback tests

* test(gateway): inject aux handler reload plan

* test(gateway): avoid resettable reload-plan mocks

* test(gateway): isolate aux handler tests from skip env-var leakage

test-helpers.mocks.ts and test-helpers.server.ts set
OPENCLAW_SKIP_CHANNELS=1 / OPENCLAW_SKIP_PROVIDERS=1 at module load. When
a shared vitest worker imports those helpers before this file's tests
run, the leaked env vars route the secrets.reload skip-mode branch and
the channel restart loop never fires. Add a beforeEach that clears both
env vars so the suite is independent of worker import order.

* fix(gateway): restore required generation on secrets.reload rollback

setCurrentSharedGatewaySessionGeneration can clear `required` as a side
effect of activating a new generation. The previous rollback path
restored only `current`, leaving `required` cleared and weakening
shared-gateway auth-generation enforcement after a failed reload (Aisle
CWE-287). Capture both fields before activation and restore both in the
catch block. Add a focused regression test that locks in the contract.

* fix(gateway): track restart channels for rollback before stopChannel awaits

Pushing to stoppedChannels only after `await stopChannel` succeeded meant
that if stopChannel rejected mid-call (for example, a plugin stopAccount
hook throws after the runtime already closed the socket), the rollback
loop skipped that channel entirely. A failed secrets.reload could then
leave the channel down. Track the channel before awaiting so rollback
always attempts to bring it back, and add a regression test.
2026-04-24 16:54:16 -06:00
Vincent Koc
2d53ad5cb6 fix(channels): harden manifest read-only metadata 2026-04-24 15:50:46 -07:00
Peter Steinberger
0c54254231 fix(discord): record gateway transport activity 2026-04-24 23:48:41 +01:00
Peter Steinberger
719d6df156 fix: align github copilot request headers 2026-04-24 23:47:43 +01:00
Peter Steinberger
304126ad79 refactor(realtime-voice): centralize consult policy helpers 2026-04-24 23:45:49 +01:00
Peter Steinberger
a7696b496a test: improve Docker aggregate scheduling 2026-04-24 23:44:02 +01:00
Peter Steinberger
99cfa50451 test(slack): cover first native stream thread target 2026-04-24 23:42:50 +01:00
Patrick Erichsen
137f5c3a8b fix(agents): repair stale bootstrap completion (#71230)
* fix(agents): repair stale bootstrap completion

* fix: reconcile stale workspace bootstrap explicitly

* fix: keep bootstrap reconciliation in workspace lifecycle
2026-04-24 15:41:11 -07:00
Vincent Koc
5d1568963b docs(changelog): backfill 2026.4.23 authors (media-image routing, codex oauth, approvals) 2026-04-24 15:39:56 -07:00
Vincent Koc
adccd0d75e docs(changelog): backfill Thanks @ on confirmed 2026.4.23 authors 2026-04-24 15:38:07 -07:00
Altay
9d3c56d236 fix: don't classify 400/422 with no body as format error (#67024)
* fix: keep no-body 400/422 failover errors out of format

* fix: keep failover changelog entry in unreleased fixes
2026-04-25 01:37:28 +03:00
Peter Steinberger
9613a0759c refactor(google-meet): tidy browser create control 2026-04-24 23:34:33 +01:00
Peter Steinberger
5c445f7842 fix(slack): suppress block streaming during previews 2026-04-24 23:34:04 +01:00
Vincent Koc
5009c588d9 docs(changelog): backfill missing authors on 2026.4.24 security, setup, browser, Meet, fallback, Telnyx, Codex, sidecar entries 2026-04-24 15:32:27 -07:00
Vincent Koc
ee3bb1f36b docs(changelog): backfill missing Thanks @ and PR links (Control UI, Google Meet, DeepSeek, Pi, Models) 2026-04-24 15:29:29 -07:00
Vincent Koc
5394efe71f feat(channels): use manifest configs for read-only discovery 2026-04-24 15:18:45 -07:00
Peter Steinberger
d4a8fdb6ce fix(discord): supervise gateway registration failures 2026-04-24 23:15:28 +01:00
Vincent Koc
4de80807b9 fix(plugins): bound tool result middleware details 2026-04-24 15:11:51 -07:00
Peter Steinberger
e2f13959d4 feat(voice-call): share realtime agent consult tool
Centralize the shared realtime agent consult tool for browser Talk, Google Meet, and Voice Call.
2026-04-24 23:11:18 +01:00
Peter Steinberger
900ba7cf33 fix(google-meet): handle browser mic prompt 2026-04-24 23:06:58 +01:00
Peter Steinberger
8a7d67f305 docs: require PR review evidence checklist 2026-04-24 23:06:31 +01:00
Peter Steinberger
535a1d699e fix(plugins): preserve interactive dedupe on cache restore 2026-04-24 23:02:21 +01:00
Gustavo Madeira Santana
2f23b84dc4 fix(changelog): remove duplicate diagnostics entry 2026-04-24 18:01:18 -04:00
Gustavo Madeira Santana
72731a37d2 Require full Matrix identity trust (#70401)
Merged via squash.

Prepared head SHA: d13a729681
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-04-24 17:58:57 -04:00
Peter Steinberger
0cce4cf8f6 refactor(slack): share stream fallback delivery bookkeeping 2026-04-24 22:55:39 +01:00
Peter Steinberger
4cca309657 docs: update changelog for PR 71242 2026-04-24 22:54:36 +01:00
RenzoMXD
bad38150cb fix(gateway): fall back to lastCallUsage on /v1/chat/completions 2026-04-24 22:54:36 +01:00
Vincent Koc
139dfd97bb fix(diagnostics-otel): export logs from diagnostic events
Export diagnostics OTEL logs through bounded diagnostic log events while keeping core log records off the public plugin diagnostic stream.\n\nIncludes security hardening for log payload redaction, bounded attributes, prototype-pollution keys, OTEL export failure reporting, and extension SDK seam usage.
2026-04-24 14:51:45 -07:00
martingarramon
150053bc86 fix(slack): route stream-fallback delivery through chunked sender (follow-up to #70370) (#71124)
* fix(slack): route stream-fallback delivery through chunked sender

deliverPendingStreamFallback was calling chat.postMessage directly for
err.pendingText, which bypasses the chunked reply path used everywhere
else. For Slack Connect cases where appendSlackStream throws
SlackStreamNotDeliveredError with a large pending buffer, the single
raw post could fail (msg_too_long) and drop the unsent tail.

Two changes:

1. deliverPendingStreamFallback now routes through deliverReplies so
   long pendingText is chunked by the normal sender and the fallback
   honors the configured replyToMode / identity.

2. The non-benign streaming-error branch in deliverWithStreaming now
   clears the session via markSlackStreamFallbackDelivered before
   falling back to deliverNormally. Without this, pendingText stays
   populated and the post-loop finalize (stopSlackStream →
   SlackStreamNotDeliveredError → fallback) re-posts the same chunk
   that deliverNormally already sent.

Addresses the three Codex P1 findings on #70370 about bypassing the
chunked sender, and the related "avoid reposting buffered text after
append fallback" P1 about duplicate delivery. Tests updated to assert
deliverReplies routing (instead of raw postMessage) and a new case
covers the non-benign-error dedup.

Follow-up to #70370.

* fix(slack): preserve pending buffered text on non-benign stream errors

Address Codex P1 on #71124: `markSlackStreamFallbackDelivered` was
clearing `pendingText` before `deliverNormally` ran, so any earlier
buffered chunk was lost. E.g. chunk A buffered in the SDK, then
appending chunk B throws a generic network error → previous fix
dropped A+B and only sent B via `deliverNormally`, silently truncating
the final reply.

Route the full buffered `pendingText` through
`deliverPendingStreamFallback` with a synthetic
`SlackStreamNotDeliveredError`, then skip `deliverNormally` entirely
(pendingText already contains this payload's text, per
`appendSlackStream` accumulating before throw). If the chunked
fallback fails, fall back to `deliverNormally` so at least the current
payload lands.

Test updated to assert the full pendingText ("first buffered\nsecond
payload") gets routed through the chunked sender, not the
chunk-B-only partial send.

* fix(slack): harden stream fallback docs and chunking test (#71124)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-24 22:50:18 +01:00
Peter Steinberger
b0c9810b0f fix(plugins): restore cached command registries 2026-04-24 22:49:40 +01:00
Peter Steinberger
cabdf5bbc4 fix: match codex openai websocket continuation 2026-04-24 22:47:25 +01:00
Peter Steinberger
95a2b0d799 docs(changelog): prepare 2026.4.24 notes 2026-04-24 22:41:12 +01:00
Peter Steinberger
55318df83f fix(slack): share HTTP route registry across module loads
Fixes #67955, #46245, #46246.

Co-authored-by: Axel <axel@kaleidoscope.studio>

Co-authored-by: Cesar Arevalo <cesar@cesararevalo.com>
2026-04-24 22:41:12 +01:00
pashpashpash
11804a484d Fail closed when an explicit agent harness is missing (#71265)
* Fail closed for explicit agent harness selection

* Scope explicit harness fallback opt in
2026-04-25 06:39:57 +09:00
IVY
5adf9d2619 fix(discord): prevent identify race (#68159)
Verified against Carbon 0.16.0 source:
- Client constructor calls plugin.registerClient(this) without awaiting it.
- GatewayPlugin.registerClient publishes client before its awaited metadata fetch.
- identify() silently returns when client is missing.

This patch matches Carbon's ordering in OpenClaw's subclass, avoids a second super.registerClient call if lifecycle connect already opened the socket during metadata loading, and keeps regression coverage for both ws and isConnecting cases.

Local proof:
- pnpm test extensions/discord/src/monitor/provider.proxy.test.ts extensions/discord/src/monitor/gateway-plugin.test.ts
- pnpm lint:tmp:no-raw-channel-fetch
- pnpm check:changed
- pnpm check
- pnpm test

GitHub checks green for 72547825e1.
2026-04-24 22:39:44 +01:00
Peter Steinberger
78b9890ae1 feat(google-meet): add browser create fallback 2026-04-24 22:36:22 +01:00
Peter Steinberger
8a9d02dd82 fix(voice-call): keep outbound realtime streams attached (#71266)
Fixes outbound Twilio realtime conversations so the TwiML fetch returns the realtime <Connect><Stream> path for outbound directions and the answered-call path does not overwrite it with legacy <Say> TwiML.

Local proof:
- pnpm test extensions/voice-call/src/manager.notify.test.ts extensions/voice-call/src/webhook.test.ts
- pnpm check:changed
- pnpm check
- pnpm build
- local VoiceCallWebhookServer + CallManager smoke for Direction=outbound-api

Closes #68713.
2026-04-24 22:35:26 +01:00
Vincent Koc
5b8bd6371c feat(plugins): warn on ignored setup runtime (#71253)
* feat(plugins): warn on ignored setup runtime

* fix(plugins): avoid fallback setup runtime diagnostics

* refactor(plugins): clarify setup runtime lookup
2026-04-24 14:23:19 -07:00
Peter Steinberger
6e985a421d fix(webchat): keep runtime context out of visible transcripts
Keep WebChat runtime context available to the model while persisting only the transcript-facing user prompt across gateway, CLI, queued follow-up, and embedded Pi paths.

Adds regression coverage for history sanitization, CLI transcript persistence, media-only auto-reply prompts, and embedded Pi prompt rewrite against a real SessionManager file.

Co-authored-by: 91wan <91wan@users.noreply.github.com>
2026-04-24 22:17:03 +01:00
Peter Steinberger
b20208fa4c feat(google-meet): create meeting spaces 2026-04-24 22:11:16 +01:00
Val Alexander
86f8c826e2 fix(ui): render assistant identity avatars in chat
Render assistant text avatars from IDENTITY.md consistently in the Control UI chat welcome state and transcript groups.

Also supports authenticated blob avatar URLs in grouped messages and rejects bidi/invisible controls in assistant text avatars.

Verification:
- pnpm test ui/src/ui/chat/grouped-render.test.ts ui/src/ui/views/chat.test.ts ui/src/styles/chat/layout.test.ts
- pnpm check:changed
- GitHub CI green
- Review threads resolved
2026-04-24 15:50:27 -05:00
Peter Steinberger
af46830927 test: split bundled Docker aggregate shards 2026-04-24 21:43:43 +01:00
Val Alexander
245451b6a9 fix(whatsapp): keep QR login state in sync
Keep WhatsApp QR login state synced across gateway, macOS, and UI wait flows.

- Preserve the latest QR data URL/version while login polling rotates codes.
- Keep the wait-result protocol bounded to current QR metadata.
- Stabilize QR rendering and media fixture coverage after rebasing on main.

Validation:
- pnpm test extensions/whatsapp/src/login-qr.test.ts extensions/whatsapp/src/media.test.ts extensions/whatsapp/src/agent-tools-login.test.ts src/gateway/protocol/channels.schema.test.ts src/gateway/server-methods/web.start.test.ts ui/src/ui/controllers/channels.test.ts
- pnpm test:extension whatsapp
- cd apps/macos && swift test --filter ChannelsSettingsSmokeTests
- GitHub PR checks: 62 success, 5 skipped
2026-04-24 15:37:16 -05:00
Vincent Koc
86099ec62a refactor(web-fetch): move readability extraction to plugin
* refactor(web-fetch): move readability extraction to plugin

* fix(web-fetch): cache extractor resolution by config

* fix(test): remove redundant stat assertions
2026-04-24 13:34:37 -07:00
github-actions[bot]
f102ddad0c chore(ui): refresh th control ui locale 2026-04-24 20:30:42 +00:00
github-actions[bot]
b885aa7cd3 chore(ui): refresh pl control ui locale 2026-04-24 20:30:15 +00:00
github-actions[bot]
4b1395b251 chore(ui): refresh uk control ui locale 2026-04-24 20:30:12 +00:00
github-actions[bot]
a7f48b6c6c chore(ui): refresh id control ui locale 2026-04-24 20:30:10 +00:00
github-actions[bot]
58a2bfeb7a chore(ui): refresh tr control ui locale 2026-04-24 20:29:58 +00:00
github-actions[bot]
e228c92e84 chore(ui): refresh fr control ui locale 2026-04-24 20:29:35 +00:00
github-actions[bot]
105aeac48e chore(ui): refresh ko control ui locale 2026-04-24 20:29:28 +00:00
github-actions[bot]
5e14663ed9 chore(ui): refresh ja-JP control ui locale 2026-04-24 20:29:08 +00:00
github-actions[bot]
db551c4274 chore(ui): refresh es control ui locale 2026-04-24 20:27:56 +00:00
github-actions[bot]
967c6bd785 chore(ui): refresh zh-TW control ui locale 2026-04-24 20:27:09 +00:00
github-actions[bot]
ffd76d6aee chore(ui): refresh pt-BR control ui locale 2026-04-24 20:27:06 +00:00
github-actions[bot]
bcd915dab1 chore(ui): refresh de control ui locale 2026-04-24 20:27:02 +00:00
github-actions[bot]
913f4e61a9 chore(ui): refresh zh-CN control ui locale 2026-04-24 20:26:35 +00:00
Vincent Koc
7bd74758c5 fix(plugins): harden tool result middleware (#71241) 2026-04-24 13:23:18 -07:00
547895019
272313877d fix(comfy): read config from plugins.entries instead of models.providers (openclaw#63058)
Verified:
- pnpm test -- extensions/comfy/image-generation-provider.test.ts extensions/comfy/music-generation-provider.test.ts extensions/comfy/video-generation-provider.test.ts
- rg -n "models\\.providers\\.comfy" docs extensions/comfy src -g '*.{ts,md,json}'
- pnpm check -- --help
- gh pr checks 63058 --repo openclaw/openclaw --watch --fail-fast

Co-authored-by: 547895019 <7350824+547895019@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-04-24 15:23:13 -05:00
Patrick Erichsen
f896c3935e ci: centralize workflow openai model defaults (#70845) 2026-04-24 13:22:35 -07:00
Vincent Koc
cf858258c7 feat(plugins): surface manifest provider setup choices (#71240) 2026-04-24 13:14:49 -07:00
Vincent Koc
8154337cb6 fix(whatsapp): emit message received hooks (#71217)
* fix(whatsapp): emit message received hooks

* fix(whatsapp): harden message received hooks
2026-04-24 13:05:10 -07:00
Peter Steinberger
7a168150e6 test: tune Docker aggregate service pressure 2026-04-24 21:04:39 +01:00
Vincent Koc
ff8b7145d7 docs(plugins): catalog active deprecations in sdk-migration and cross-link from hooks 2026-04-24 13:04:07 -07:00
Michael Yagudaev
c997a9f978 feat(gateway): add VoiceClaw realtime brain endpoint (#70938)
Adds the VoiceClaw-compatible realtime brain WebSocket endpoint backed by Gemini Live, with owner-auth gating, async OpenClaw tool handoff, docs, and lifecycle tests.

Maintainer fixup: terminal upstream errors now send the error, emit session.ended while the client socket is still open, then close the client-facing socket.

Co-authored-by: Michael Yagudaev <1386966+yagudaev@users.noreply.github.com>
2026-04-24 21:00:04 +01:00
Vincent Koc
7536993397 feat(plugins): read setup provider env vars (#71226)
* feat(plugins): read setup provider env vars

* fix(plugins): mark provider env compat deprecation
2026-04-24 12:59:02 -07:00
Peter Steinberger
b4d756c746 docs: trim root agent guide 2026-04-24 20:54:59 +01:00
Peter Steinberger
037d12974c test: bound Docker smoke host commands 2026-04-24 20:54:06 +01:00
Peter Steinberger
0e23107ffb feat(google-meet): format setup status by default 2026-04-24 20:52:39 +01:00
Peter Steinberger
02112803b5 test: cover OpenAI thinking payload contract 2026-04-24 20:51:58 +01:00
Peter Steinberger
7425cb0549 fix: guard speech provider fetches 2026-04-24 20:51:18 +01:00
Peter Steinberger
25ad66520b docs: add ci wait matrix 2026-04-24 20:50:17 +01:00
Peter Steinberger
ecac696643 docs: condense agent instructions 2026-04-24 20:47:21 +01:00
Peter Steinberger
588e59db26 docs: clarify post-land ci waiting 2026-04-24 20:45:55 +01:00
Peter Steinberger
c3f4c75d39 ci: give lint enough blacksmith cpu 2026-04-24 20:45:32 +01:00
Peter Steinberger
d43b3b3b70 fix: preserve live runtime dependency locks 2026-04-24 20:44:56 +01:00
Peter Steinberger
56e299cbca fix: serialize bundled runtime dependency repair 2026-04-24 20:44:56 +01:00
Peter Steinberger
def392ad7d test: add provider HTTP live coverage 2026-04-24 20:44:56 +01:00
Peter Steinberger
2c516fe516 refactor: share provider HTTP error parsing 2026-04-24 20:44:56 +01:00
Yao
37d5c34749 fix(matrix): pass loaded cfg to verify CLI subcommands (#70992) [AI-assisted] (#71102)
Merged via squash.

Prepared head SHA: 9fffdf2ca6
Co-authored-by: luyao618 <17723416+luyao618@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-04-24 15:44:22 -04:00
Patrick Erichsen
8226a3f8fe feat(onboard): add skip bootstrap flag (#71218) 2026-04-24 12:42:00 -07:00
Peter Steinberger
0f689d22f4 test: add weighted Docker aggregate scheduler 2026-04-24 20:41:27 +01:00
Peter Steinberger
88c91675e2 test: stabilize qa suite concurrency 2026-04-24 20:39:33 +01:00
Vincent Koc
47f6a98909 feat(plugins): add harness tool result middleware (#71021) 2026-04-24 12:39:13 -07:00
Peter Steinberger
e471d40942 ci: run preflight on github hosted ubuntu 2026-04-24 20:37:02 +01:00
Peter Steinberger
c2a353a3bd perf: shorten extension ci tail 2026-04-24 20:35:55 +01:00
BillChirico
51dd4f288f fix(config): allow plugin conversation access hook policy (#71221) 2026-04-24 20:28:42 +01:00
Peter Steinberger
ef9ca09b8e docs(google-meet): add setup troubleshooting 2026-04-24 20:28:00 +01:00
Peter Steinberger
b9cc293167 test: wait for ACPX in cron Docker smoke 2026-04-24 20:27:24 +01:00
Peter Steinberger
14934f0b7c test(google-meet): verify twilio setup readiness 2026-04-24 20:25:46 +01:00
Tak Hoffman
5c8a5fa8fa fix: tweak group silent caution prompt (#71209)
* Tighten group silent caution prompt

* Deduplicate group silent caution prompt
2026-04-24 14:20:01 -05:00
Peter Steinberger
e6d04682d3 ci: tune oxlint threads 2026-04-24 20:17:42 +01:00
Michael Appel
8b76392e3e fix(gateway): enforce owner-only tool policy and before-tool-call hook on MCP loopback surface (#71159)
* fix: address issue

* fix: address review feedback

* fix: address PR review feedback

* changelog: PR #71159 MCP loopback owner-only policy + before-tool-call hook

---------

Co-authored-by: Devin Robison <drobison@nvidia.com>
2026-04-24 13:16:45 -06:00
bitloi
8cae2ed645 fix(gateway): allow chat.abort to stop agent RPC runs
Register agent RPC runs in the shared abort controller map so chat.abort and sessions.abort can interrupt them like chat.send runs.

Also centralize abort-controller registration/owned cleanup, preserve agent timeout semantics for maintenance expiry, and cover pre-dispatch failure cleanup with regression tests.

Fixes #71128.
2026-04-24 20:15:56 +01:00
Yao
0e50fee996 fix(googlechat): log webhook auth reject reasons and warn on appPrincipal misconfig (#71145)
* fix(googlechat): log webhook auth reject reasons and warn on appPrincipal misconfig

Closes #71078

Webhook auth failures previously returned 401 with no log line, leaving
operators no signal to diagnose. Additionally, app-url audience requires
a numeric OAuth 2.0 client ID as appPrincipal, but a misconfigured email
or empty value silently caused all requests to be rejected.

Changes:
- Log a WARN with accountId and reject reason when verifyGoogleChatRequest fails.
- Add warnAppPrincipalMisconfiguration() called at provider init: warns when
  audienceType=app-url and appPrincipal is missing or contains '@'.

Tests: +9 cases in monitor-webhook.test.ts (3 reject-reason scenarios + 4 warner cases).

* fix(googlechat): defer auth rejection logs

* docs: note googlechat webhook auth fix

---------

Co-authored-by: luyao618 <luyao618@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-24 20:10:57 +01:00
Peter Steinberger
0651e5dc97 fix: restore reliable live Docker staging 2026-04-24 20:10:28 +01:00
Peter Steinberger
65c9cb852e ci: keep only fast core on blacksmith 2026-04-24 20:07:56 +01:00
Peter Steinberger
ed7ea75fc0 perf: speed up live Docker staging 2026-04-24 20:03:08 +01:00
Peter Steinberger
c9998af44d ci: move node fanout to blacksmith 2026-04-24 20:02:48 +01:00
Peter Steinberger
7b5307acfc ci: move fast bundled checks to blacksmith 2026-04-24 20:00:12 +01:00
Peter Steinberger
d12b523611 fix(elevenlabs): use guarded TTS fetch 2026-04-24 19:55:20 +01:00
Sathvik-1007
8d57d745cf fix: wizard no clobber model.primary on re-run
two bugs. both squash user model choice silently.

bug 1: applyDefaultModel() unconditional primary: model overwrite.
wizard calls with setDefaultModel=true, provider returns its default
(e.g. openrouter/auto), bam user primary gone. fix: existingPrimary ?? model.

bug 2: applyModelFallbacksFromSelection() phantom primary injection.
when no primary configured, resolvedKey (hardcoded default) written as
primary via nullish coalescing fallback. fix: conditional spread — only
include primary key when one actually existed.

tests for both. closes #70696
2026-04-24 19:55:20 +01:00
Vincent Koc
d795000377 refactor(anthropic-vertex): move SDK runtime to plugin (#71174)
* refactor(anthropic-vertex): move sdk runtime to plugin

* fix(anthropic-vertex): stage provider runtime deps

* fix(anthropic-vertex): reuse stream factory wrapper
2026-04-24 11:52:35 -07:00
Peter Steinberger
07f33b2909 test: speed up embedded run orchestration specs 2026-04-24 19:47:53 +01:00
Peter Steinberger
59523e66da refactor: remove old provider error utility path 2026-04-24 19:40:25 +01:00
Peter Steinberger
70f5c26a71 refactor: move provider HTTP errors out of tts 2026-04-24 19:40:25 +01:00
Peter Steinberger
bc0f54bd04 fix(models): separate Codex harness from model choices (#71193)
* fix: separate Codex harness from model choices

* docs: note Codex harness model choice fix
2026-04-24 19:40:23 +01:00
Peter Steinberger
dcf01ce72f perf: speed up Docker aggregate smokes 2026-04-24 19:38:25 +01:00
Vincent Koc
3bd2ee78b6 feat(plugins): expose hook correlation fields
Expose first-class hook correlation fields for plugin message and run lifecycle hooks, including frozen diagnostic trace copies for plugin-facing events.
2026-04-24 11:37:34 -07:00
Peter Steinberger
a43c1f8807 refactor: share provider HTTP errors with google 2026-04-24 19:33:44 +01:00
Peter Steinberger
b1016c39fd refactor: share speech provider HTTP errors 2026-04-24 19:33:44 +01:00
Peter Steinberger
e54c04f495 test: stabilize qa lab scenarios 2026-04-24 19:23:37 +01:00
Vincent Koc
6bc0dc8fb6 feat(plugins): report setup descriptor drift (#71194) 2026-04-24 11:15:30 -07:00
Peter Steinberger
3ffd944e6b test: isolate doctor switch shell profiles 2026-04-24 19:10:15 +01:00
Peter Steinberger
926068b14f test(deepseek): add live model smoke 2026-04-24 19:07:41 +01:00
Vincent Koc
5d7d5ca2a9 docs(plugins/hooks): regroup hook catalog by surface, mark decision hooks, sync before_tool_call result type with code 2026-04-24 11:02:46 -07:00
Vincent Koc
7418adf875 fix(plugins): honor descriptor-only setup flag
Honor explicit setup.requiresRuntime: false as a descriptor-only setup contract while preserving omitted values as the legacy setup-api fallback path.
2026-04-24 11:02:38 -07:00
Peter Steinberger
a16f8dff15 test: fold tiny media fallback specs 2026-04-24 19:01:18 +01:00
Peter Steinberger
7a63dd3f12 ci: rebase docs sync with source preference 2026-04-24 18:58:53 +01:00
Peter Steinberger
f07b00de66 refactor(gateway): rename startup sidecar deferral option 2026-04-24 18:58:36 +01:00
Peter Steinberger
3bc99bc70e docs: add reliable taskflow workflow pattern 2026-04-24 18:55:05 +01:00
Peter Steinberger
6fea42fc2d ci: skip stale docs sync publishes 2026-04-24 18:54:01 +01:00
Vincent Koc
9439d633ef docs(nav): surface orphan pages in sidebar (message-presentation, skill-workshop, qa-e2e-automation, proxy, gpt54-codex-agentic-parity) 2026-04-24 10:53:32 -07:00
Peter Steinberger
c2bffc6033 docs: clarify google meet mode choice 2026-04-24 18:51:39 +01:00
Peter Steinberger
94275f13fb fix: keep disabled channel doctor probes lazy 2026-04-24 18:51:19 +01:00
Vincent Koc
1042b893f6 docs: drop parenthetical H1s across gateway, channels, providers, concepts, and reference pages 2026-04-24 10:49:23 -07:00
Peter Steinberger
a155b84cda test: remove duplicate direct chat mock 2026-04-24 18:45:32 +01:00
Peter Steinberger
8207567cba docs(release): prefer npm token workflow for dist-tags 2026-04-24 18:45:06 +01:00
Peter Steinberger
62adf6349d docs(release): require tmux for 1password fallback 2026-04-24 18:44:43 +01:00
Laurent Mazare
d7e2939791 feat: add Gradium text-to-speech provider (#64958)
Adds the Gradium bundled plugin with TTS and speech-provider registration, docs, label routing, and focused/live coverage.

Also carries the current main lint cleanup needed for the rebased CI lane.

Co-authored-by: laurent <laurent.mazare@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-24 18:43:53 +01:00
Peter Steinberger
2495886287 perf: shrink Docker dependency build contexts 2026-04-24 18:42:25 +01:00
Peter Steinberger
67a2b187b7 docs: fix gateway security accordion 2026-04-24 18:42:07 +01:00
Peter Steinberger
80608ae26c fix: prevent malformed docs accordions 2026-04-24 18:42:07 +01:00
Peter Steinberger
1cfebfe0e1 test: cover Telegram topic model switches 2026-04-24 18:36:23 +01:00
EVA
860dad268d [codex] Add contract-first Pi/Codex runtime plan suite (#71096)
* test: add pi codex runtime contract coverage

* test: expand pi codex tool runtime contracts

* test: tighten tool runtime contracts

* test: reset tool contract param cache

* test: document codex tool middleware fixture

* test: type pi tool contract events

* test: satisfy pi tool contract test types

* test: cover tool media telemetry contracts

* test: reset plugin runtime after tool contracts

* test: add auth profile runtime contracts

* test: strengthen auth profile runtime contracts

* test: clarify auth profile contract fixtures

* test: expand auth profile contract matrix

* test: assert unrelated cli auth isolation

* test: expand auth profile contract matrix

* test: tighten auth profile contract expectations

* test: add outcome fallback runtime contracts

* test: strengthen outcome fallback contracts

* test: isolate outcome fallback contracts

* test: cover codex terminal outcome signals

* test: expand terminal fallback contracts

* test: add delivery no reply runtime contracts

* test: document json no-reply delivery gap

* test: align delivery contract fixtures

* test: add transcript repair runtime contracts

* test: tighten transcript repair contracts

* test: add prompt overlay runtime contracts

* test: tighten prompt overlay contract scope

* test: type prompt overlay contracts

* test: add schema normalization runtime contracts

* test: clarify schema normalization contract gaps

* test: simplify schema normalization contracts

* test: tighten schema normalization contract gaps

* test: cover compaction schema contract

* test: satisfy schema contract lint

* test: add transport params runtime contracts

* test: tighten transport params contract scope

* test: isolate transport params contracts

* test: lock exact transport defaults

* feat: add agent runtime plan foundation

* fix: preserve codex harness auth profiles

* fix: route followup delivery through runtime plan

* fix: normalize parameter-free openai tool schemas

* fix: satisfy runtime plan type checks

* fix: narrow followup delivery runtime planning

* fix: apply codex app-server auth profiles

* fix: classify codex terminal outcomes

* fix: prevent harness auth leakage into unrelated cli providers

* feat: expand agent runtime plan policy contract

* fix: route pi runtime policy through runtime plan

* fix: route codex runtime policy through runtime plan

* fix: route fallback outcome classification through runtime plan

* refactor: make runtime plan contracts topology-safe

* fix: restore runtime plan test type coverage

* fix: align runtime plan schema contract assertions

* fix: stabilize incomplete turn runtime tests

* fix: stabilize codex native web search test

* fix: preserve codex auth profile secret refs

* fix: keep runtime resolved refs canonical

* fix: preserve permissive nested openai schemas

* fix: accept Codex auth provider aliases

* test: update media-only groups mock

* fix: resolve runtime plan rebase checks

* fix: resolve runtime plan rebase checks

---------

Co-authored-by: Eva <eva@100yen.org>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-24 18:34:01 +01:00
Peter Steinberger
ec3dbd22a4 test: type legacy codex model fixture 2026-04-24 18:30:51 +01:00
Peter Steinberger
0c70cb3b9c fix: report google meet manual actions 2026-04-24 18:26:51 +01:00
Peter Steinberger
cba92f893d fix(gateway): await startup sidecars by default
Co-authored-by: 忻役 <xinyi@mininglamp.com>
2026-04-24 18:25:50 +01:00
Peter Steinberger
129f548c44 fix: export diagnostic error category once 2026-04-24 18:24:24 +01:00
Peter Steinberger
95db5966a0 docs: add plugin hook glossary labels 2026-04-24 18:23:44 +01:00
Peter Steinberger
7330a0c7e0 docs: add plugin hooks reference 2026-04-24 18:22:47 +01:00
Peter Steinberger
342583348d test: fix models list e2e static catalog mock
(cherry picked from commit 3385d10ee5)
2026-04-24 18:22:24 +01:00
Peter Steinberger
5738201b22 test: make bundled channel docker lane resumable
(cherry picked from commit 5b1bd58bd0)
2026-04-24 18:22:24 +01:00
Peter Steinberger
712b7c6637 ci(release): configure shared docker e2e builder
(cherry picked from commit 6f948d925e)
2026-04-24 18:22:24 +01:00
Peter Steinberger
6b4f6ca20c fix(plugins): avoid plugin sdk alias rewrite races 2026-04-24 18:22:24 +01:00
Peter Steinberger
bbef1c5557 fix(release): harden subagent completion delivery
(cherry picked from commit 855872986e)
2026-04-24 18:22:24 +01:00
Peter Steinberger
da36c1967f fix(release): accept logged cross-os agent output
(cherry picked from commit a58ee7c8bc)
2026-04-24 18:22:24 +01:00
Peter Steinberger
042c031c5c ci(release): parse logged agent payload text
(cherry picked from commit c52a16989e)
2026-04-24 18:22:24 +01:00
Peter Steinberger
f191dd3d53 fix(release): preserve plugin-local runtime deps in postpublish verify 2026-04-24 18:22:24 +01:00
Peter Steinberger
5b0ee04c0d fix(release): harden packed runtime smoke
(cherry picked from commit 5ab5dc3900)
2026-04-24 18:22:24 +01:00
Peter Steinberger
3eb7605318 docs(release): restore 2026.4.23 notes on main 2026-04-24 18:22:23 +01:00
Tak Hoffman
59e2825274 fix: deprecate models add command (#71175) 2026-04-24 12:20:59 -05:00
Peter Steinberger
e35e6e1d15 ci: try blacksmith preflight runner 2026-04-24 18:20:36 +01:00
Peter Steinberger
78a431ed22 fix(discord): require real gateway readiness 2026-04-24 18:16:58 +01:00
Peter Steinberger
a08a2e381f fix: resolve bare fallback model providers 2026-04-24 18:16:25 +01:00
Peter Steinberger
1981622b92 test: update ci shard and reply mocks 2026-04-24 18:14:24 +01:00
Peter Steinberger
560b04d4c6 perf: avoid slow Docker live lane cleanup 2026-04-24 18:09:04 +01:00
Tak Hoffman
cc57d56b92 fix: Align silent reply prompt guidance (#70954)
* Align silent reply prompt guidance

* Pass explicit silent reply conversation types

* Handle dm alias in direct prompt guidance

* Respect policy session type for routed replies

* Preserve routed silent reply policy type

* Propagate silent reply dispatcher chat type

* Align prompt silent reply target policy

* Avoid direct silent fallback prompt token

* Use inbound key for prompt silent policy

* Rewrite direct silent replies in dispatcher
2026-04-24 12:06:54 -05:00
Peter Steinberger
c9f2403547 ci: pass node shard runner overrides 2026-04-24 18:05:29 +01:00
Peter Steinberger
660cea680a ci: move tail node shards to blacksmith 2026-04-24 18:03:29 +01:00
Peter Steinberger
11cffb2300 fix: remove duplicate diagnostic category export 2026-04-24 17:58:22 +01:00
Peter Steinberger
afc0c32bd0 ci: try larger blacksmith lint lane 2026-04-24 17:55:44 +01:00
Peter Steinberger
b2352c3e24 docs: improve 2026.4.23 release docs 2026-04-24 17:55:03 +01:00
Peter Steinberger
51c11cfd90 fix: export diagnostic error category 2026-04-24 17:54:44 +01:00
Peter Steinberger
769ab4a91c docs: clarify beta Telegram release verification 2026-04-24 17:52:13 +01:00
Peter Steinberger
c15edc3641 ci: try smaller blacksmith support lanes 2026-04-24 17:50:46 +01:00
Peter Steinberger
f6dcf968ca fix: honor disabled plugin runtime deps 2026-04-24 17:46:35 +01:00
Ron Cohen
3de44fe593 fix(whatsapp): setting systemPrompt to "" suppresses the wildcard prompt (#70381)
* fix(whatsapp): setting systemPrompt to "" suppresses the wildcard instead of falling through to it

* test(whatsapp): reset mocks instead of only clearing call history

* docs(changelog): note WhatsApp empty systemPrompt suppresses wildcard

* test(whatsapp): preserve real module exports in process-message mocks

* test(whatsapp): whitespace-only systemPrompt also suppresses wildcard

---------

Co-authored-by: Omar Shahine <10343873+omarshahine@users.noreply.github.com>
2026-04-24 09:45:58 -07:00
Peter Steinberger
11ad1919ed test: stabilize Docker MCP lanes under load 2026-04-24 17:41:37 +01:00
Peter Steinberger
5deef28b7a ci: split docs-only push checks 2026-04-24 17:41:04 +01:00
Peter Steinberger
11abe5ec49 docs: clarify plugin api extension path 2026-04-24 17:36:39 +01:00
Vincent Koc
f8573fe9c2 feat(diagnostics): export lifecycle OTEL spans
Export diagnostics OTEL lifecycle spans for runs, model calls, and tool executions while avoiding retained live span state and high-cardinality/sensitive exported attributes.
2026-04-24 09:36:35 -07:00
Peter Steinberger
0340321c12 docs: clarify plugin style preference 2026-04-24 17:35:00 +01:00
Peter Steinberger
2fe7c6fed4 docs: simplify mcp vision 2026-04-24 17:34:15 +01:00
Peter Steinberger
f738b73107 docs: clarify clawhub plugin promotion 2026-04-24 17:31:49 +01:00
Vincent Koc
4d1ee3a73e fix(plugins): warn on install source package drift
Warn when provider or channel catalog package identity drifts from openclaw.install.npmSpec while keeping compatible catalogs non-fatal.
2026-04-24 09:31:40 -07:00
Peter Steinberger
90877e0d42 docs: update mcp vision 2026-04-24 17:29:42 +01:00
Peter Steinberger
3df9fd4354 ci: keep preflight off congested blacksmith 2026-04-24 17:28:11 +01:00
Vincent Koc
06d46869f8 refactor(tui): remove cli-highlight dependency
Remove direct cli-highlight usage from the TUI renderer and drop the now-unused root ownership record.
2026-04-24 09:25:25 -07:00
Peter Steinberger
f4ffed8482 ci: reduce ubuntu preflight queue 2026-04-24 17:24:37 +01:00
Peter Steinberger
27b348b3e5 perf: reuse Docker aggregate package tarball 2026-04-24 17:20:56 +01:00
Vincent Koc
1cf79803d7 docs: normalize Title Case H2 headings to sentence case in recent files 2026-04-24 09:17:47 -07:00
Vincent Koc
c1ad8076a3 docs(standing-orders): drop duplicate H1 where frontmatter title already covers it 2026-04-24 09:17:16 -07:00
Vincent Koc
32163e0e98 docs(google-meet): drop duplicate H1 and merge intro sentences 2026-04-24 09:16:27 -07:00
Peter Steinberger
16c7de085c ci: move long tail checks to blacksmith 2026-04-24 17:16:18 +01:00
Peter Steinberger
d9c5479029 fix: remove google meet sync await 2026-04-24 17:16:18 +01:00
Vincent Koc
12f7de3ef3 docs(capability-cookbook): normalize Provider and Harness Seams heading to sentence case 2026-04-24 09:15:22 -07:00
Peter Steinberger
7e49cc87f9 perf: parallelize Docker aggregate image builds 2026-04-24 17:10:50 +01:00
Peter Steinberger
d3e66e36f6 fix: export model diagnostic error category 2026-04-24 17:10:46 +01:00
Peter Steinberger
d5880ae6a5 fix: restore diagnostic error export 2026-04-24 17:09:22 +01:00
Peter Steinberger
23c7a7d557 test: harden Docker lanes for 10-way runs 2026-04-24 17:08:18 +01:00
Peter Steinberger
cbfc21badb test: shard Docker aggregate lanes 2026-04-24 17:08:18 +01:00
Vincent Koc
58f54801b7 feat(deps): add SBOM risk report
* feat(deps): add sbom risk report

* feat(deps): add sbom risk report
2026-04-24 09:08:07 -07:00
Peter Steinberger
c05791f619 ci: split blacksmith node lanes by runner size 2026-04-24 17:05:09 +01:00
Peter Steinberger
f7a426d516 fix: stage WhatsApp runtime deps before setup login 2026-04-24 17:04:31 +01:00
Vincent Koc
7ba13fbc2b fix(diagnostics): harden event emission (#71164) 2026-04-24 09:02:14 -07:00
Peter Steinberger
bda391e4c2 fix: use browser automation for Google Meet join 2026-04-24 17:01:57 +01:00
Vincent Koc
bbe0234720 fix(plugins): warn on orphan install integrity (#71163) 2026-04-24 09:01:15 -07:00
Vincent Koc
5dfc1b90e1 fix(plugins): warn on invalid install default choice (#71011) 2026-04-24 08:56:42 -07:00
Peter Steinberger
1b997bebd0 build(a2ui): refresh bundled canvas host asset 2026-04-24 16:55:08 +01:00
Peter Steinberger
27c61ed0d4 chore(deps): update workspace dependencies 2026-04-24 16:55:08 +01:00
pashpashpash
7a958d920c Bridge Codex native hooks into OpenClaw
Bridge Codex-native tool events into the OpenClaw plugin hook surface, including native permission approval routing, bounded relay payloads, approval spam protection, and docs/changelog updates.\n\nCo-authored-by: pashpashpash <nik@vault77.ai>
2026-04-24 16:48:26 +01:00
Peter Steinberger
3a64aa49a9 docs(deepseek): expand v4 testing notes 2026-04-24 16:30:35 +01:00
Peter Steinberger
aef0bb4915 test(deepseek): add live v4 model coverage 2026-04-24 16:30:35 +01:00
Peter Steinberger
6b618f0635 ci: offload selected node lanes to blacksmith 2026-04-24 16:23:24 +01:00
Peter Steinberger
f3bcea8732 build: preserve staged plugin runtime deps 2026-04-24 16:18:26 +01:00
Peter Steinberger
2b45a112cb feat: harden Google Meet realtime join 2026-04-24 16:18:26 +01:00
Peter Steinberger
2c701ab296 test: speed discord queue waits 2026-04-24 16:14:15 +01:00
lsdsjy
7d1891e6e6 feat(deepseek): support v4 models
Add DeepSeek V4 Flash/Pro support, update Pi packages to 0.70.2, and handle disabled thinking/None by stripping replayed reasoning content.
2026-04-24 16:09:36 +01:00
Peter Steinberger
4f4288e3b5 test: speed zalo polling waits 2026-04-24 16:07:53 +01:00
Peter Steinberger
50667db297 test: speed matrix verification waits 2026-04-24 16:04:51 +01:00
wangshu94
1ff07245f3 fix(gateway): surface chat.send lifecycle errors to clients (#69747)
Merged via squash.

Prepared head SHA: 75b403b2de
Co-authored-by: wangshu94 <53429538+wangshu94@users.noreply.github.com>
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
Reviewed-by: @hxy91819
2026-04-24 22:59:47 +08:00
Peter Steinberger
7130e56f87 ci: avoid scarce runners for node fanout 2026-04-24 15:54:44 +01:00
Peter Steinberger
a3ae336c51 perf: slim browser test imports 2026-04-24 15:42:52 +01:00
Peter Steinberger
d3d9b5738f docs: clarify live plugin runtime reloads 2026-04-24 15:38:56 +01:00
Peter Steinberger
5ca6b3568c perf: slim whatsapp test imports 2026-04-24 15:27:52 +01:00
Peter Steinberger
34896839ba perf: slim irc inbound imports 2026-04-24 15:12:37 +01:00
Peter Steinberger
a6aa151653 perf: avoid redundant device pairing writes 2026-04-24 15:01:38 +01:00
Peter Steinberger
8f64cd3e4d test: wait for ACPX runtime in MCP docker lane 2026-04-24 14:00:20 +01:00
Peter Steinberger
8866544ffe test: slim browser and msteams imports 2026-04-24 13:33:48 +01:00
Peter Steinberger
60f7a59f5e test: bridge xai test helper imports 2026-04-24 13:18:21 +01:00
Peter Steinberger
aa3a5f9ff7 test: narrow xai test helper imports 2026-04-24 13:07:35 +01:00
Peter Steinberger
55c45307d0 test: narrow matrix client runtime import 2026-04-24 13:04:45 +01:00
Peter Steinberger
577ff767fa test: extend Open WebUI docker startup wait 2026-04-24 13:02:40 +01:00
Peter Steinberger
608c08fc54 test: narrow slack inbound contract imports 2026-04-24 13:00:05 +01:00
Peter Steinberger
0783090da0 test: split slack client option imports 2026-04-24 12:58:28 +01:00
Peter Steinberger
04a54cf54e test: slim slack media imports 2026-04-24 12:56:16 +01:00
Peter Steinberger
6944d7025d test: narrow mattermost nested runtime barrel 2026-04-24 12:43:06 +01:00
Peter Steinberger
68b9ad4205 test: slim feishu monitor handler imports 2026-04-24 12:36:50 +01:00
Peter Steinberger
ebd7f19a3b test: avoid whatsapp setup jiti load 2026-04-24 12:26:48 +01:00
Peter Steinberger
11fa1d2dc7 test: mock secrets apply runtime preflight 2026-04-24 12:22:49 +01:00
Peter Steinberger
9faa9d33e6 test: mock web tools manifest lookup 2026-04-24 12:19:50 +01:00
Peter Steinberger
9b7f6250f4 test: bypass discord monitor barrel in tests 2026-04-24 12:13:44 +01:00
Peter Steinberger
2e2a134489 perf: lazy load bluebubbles catchup 2026-04-24 12:08:34 +01:00
Peter Steinberger
4514691300 test: narrow provider discovery test imports 2026-04-24 12:03:50 +01:00
Peter Steinberger
fcaf6a23dd test: retry Claude capacity failures in live backend 2026-04-24 12:00:39 +01:00
Peter Steinberger
9ece33c505 test: slim google oauth project discovery 2026-04-24 11:50:12 +01:00
Peter Steinberger
320d52a23e test: narrow oauth lock timeout coverage 2026-04-24 11:43:22 +01:00
Peter Steinberger
3814dc860b test: mock acp spawn config load 2026-04-24 11:35:56 +01:00
Peter Steinberger
f3c37a946c test: fold sandbox skill sync coverage 2026-04-24 11:30:49 +01:00
Peter Steinberger
daed93dd30 test: harden live docker aggregate flakes 2026-04-24 11:25:27 +01:00
Peter Steinberger
a8edf29bd0 test: slim pty fallback coverage 2026-04-24 11:19:31 +01:00
Peter Steinberger
01bc49c88c test: move pty cleanup coverage to adapter 2026-04-24 11:09:55 +01:00
cxy
4013c65853 fix(qqbot): enable qqbot plugin by default so runtime deps install be… (#71051)
* fix(qqbot): enable qqbot plugin by default so runtime deps install before QR-code setup

The qqbot plugin manifest was missing the enabledByDefault: true flag.
Without it, ensureBundledPluginRuntimeDeps treats qqbot as bundled-but-
disabled-by-default (isBundledPluginConfiguredForRuntimeDeps returns
false when no qqbot channel/account is configured yet), so
@tencent-connect/qqbot-connector is never installed into
dist/extensions/qqbot/node_modules on first launch.

This creates a chicken-and-egg failure for the QR-code binding flow:
finalize.ts dynamically imports @tencent-connect/qqbot-connector to run
qrConnect(), but the package isn't present yet because no account is
configured — binding is exactly the step that configures the first
account. Users hit:

  QQ Bot 绑定失败: Error [ERR_MODULE_NOT_FOUND]: Cannot find package
  '@tencent-connect/qqbot-connector' imported from
  .../dist/extensions/qqbot/channel-*.js

Adding enabledByDefault: true makes the host install qqbot's runtime
deps eagerly on first launch, mirroring the pattern already used by
mistral / groq / deepgram / amazon-bedrock-mantle and other bundled
plugins whose providers must be available before any channel config
exists. No code changes required; the existing runtime-deps install
pipeline handles everything once the gate is opened.

* fix(qqbot): changelog for enable-by-default fix (#71051) (thanks @cxyhhhhh)

---------

Co-authored-by: sliverp <870080352@qq.com>
2026-04-24 17:58:14 +08:00
Peter Steinberger
ed51963c47 test: slim pi auth discovery tests 2026-04-24 10:50:43 +01:00
Peter Steinberger
b453293349 test: isolate provider provenance aliases 2026-04-24 10:45:42 +01:00
Peter Steinberger
83370f0021 test: remove duplicate qianfan auth marker case 2026-04-24 10:37:49 +01:00
Peter Steinberger
d38ed0831d perf: slim sandbox registry tests 2026-04-24 10:33:50 +01:00
Frank Yang
934dd5b3a7 [codex] fix agent session-id routing (#70985)
Merged via squash.

Prepared head SHA: f092b0c5c8
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
2026-04-24 17:31:34 +08:00
Vincent Koc
0e7250f37b feat(diagnostics): emit model call events
Emit structured diagnostic events for embedded run and model-call lifecycle with trace context, duration, and safe error categories.
2026-04-24 02:17:07 -07:00
Peter Steinberger
e5f55dd024 docs: document Google realtime voice support 2026-04-24 10:14:55 +01:00
Peter Steinberger
6831579267 perf: skip provider plugin loading in extra param tests 2026-04-24 10:02:57 +01:00
Peter Steinberger
b7b66a6047 test: relax live cli backend wording 2026-04-24 09:51:48 +01:00
Peter Steinberger
56fe2aab9c fix: attach Google Meet realtime bridge 2026-04-24 09:41:33 +01:00
Peter Steinberger
b5e5f2cede feat(google): add realtime voice provider 2026-04-24 09:36:20 +01:00
EVA
c138368040 feat: add Codex harness extension seams
Co-authored-by: Eva <100yenadmin@users.noreply.github.com>
2026-04-24 09:32:27 +01:00
Peter Steinberger
d85dc46e37 perf: narrow telegram reply imports 2026-04-24 09:31:47 +01:00
Peter Steinberger
a79c40a789 test: harden docker live readiness 2026-04-24 09:28:59 +01:00
Peter Steinberger
f03252aaf9 fix: keep telegram dispatch eager 2026-04-24 09:17:33 +01:00
Vincent Koc
cead2ea4b1 feat(diagnostics): emit tool execution events
Emit structured diagnostic events for tool execution lifecycle, with trace context, safe parameter summaries, and non-message error metadata.
2026-04-24 01:16:13 -07:00
Peter Steinberger
447105a278 perf: slim telegram bot imports 2026-04-24 09:12:28 +01:00
Peter Steinberger
028b6c9b13 perf: trim sandbox context tests 2026-04-24 08:56:32 +01:00
EVA
40be5ad581 fix: harden GPT-5 runtime paths
Co-authored-by: EVA <100yenadmin@users.noreply.github.com>
2026-04-24 08:55:52 +01:00
Vincent Koc
4630ce3d9e fix(diagnostics): make otel service restart safe
Make diagnostics-otel startup restart-safe by tearing down stale SDK, log transport, and diagnostic-event listener handles before reinitializing or disabling the service. Adds regression coverage for repeated start and disabled restart paths.\n\nThanks @vincentkoc.
2026-04-24 00:53:04 -07:00
Peter Steinberger
cc92699ff7 fix: guard openai tts fetch 2026-04-24 08:50:35 +01:00
Peter Steinberger
6a61cb73c5 build: exclude docker test artifacts 2026-04-24 08:50:07 +01:00
Vincent Koc
a52b50ef3c docs(changelog): note plugin architecture source work 2026-04-24 00:48:44 -07:00
Peter Steinberger
0a3da5cd8a perf: slim auth profile test imports 2026-04-24 08:45:26 +01:00
Peter Steinberger
38caa6832d test: stagger docker aggregate starts 2026-04-24 08:38:41 +01:00
Peter Steinberger
665cc3d537 fix: guard openai tts fetch 2026-04-24 08:37:41 +01:00
Vincent Koc
c1b9aa7d96 fix(plugins): pin official external channel source (#70997) 2026-04-24 00:35:03 -07:00
Peter Steinberger
a437666a37 fix(browser): reject existing-session type timeouts 2026-04-24 08:29:25 +01:00
Peter Steinberger
aa21d4ea7e fix(browser): clarify existing-session timeout limits 2026-04-24 08:27:12 +01:00
Vincent Koc
1e8dc2389e feat(plugins): record local onboarding installs
Record onboarding plugin install source metadata for npm and local paths, while keeping local path install records portable and preserving uninstall cleanup for relative source paths.
2026-04-24 00:27:09 -07:00
Peter Steinberger
69196670b7 refactor: dedupe shared helpers 2026-04-24 08:26:37 +01:00
Peter Steinberger
661f11b947 test: align codex auth hint expectation 2026-04-24 08:25:07 +01:00
Vincent Koc
bcdacfa1b3 feat(diagnostics): carry trace context through hooks
Pass immutable diagnostic trace contexts through agent and tool hook surfaces, emit model usage with the run trace, and parent OTEL spans/logs from validated trace context without retained global state.\n\nThanks @vincentkoc.
2026-04-24 00:24:32 -07:00
Peter Steinberger
33c0cd1378 fix: improve codex model discovery 2026-04-24 08:17:01 +01:00
pashpashpash
81666e586a fix codex dynamic tool hooks (#70965) 2026-04-24 16:14:06 +09:00
Peter Steinberger
4e4aeacae4 perf: slim hot test imports 2026-04-24 08:13:51 +01:00
Peter Steinberger
50e36983bb fix: harden codex verbose tool progress (#70966) (thanks @jalehman) 2026-04-24 08:10:04 +01:00
Ayaan Zaidi
f353a61bab ci(release): use blacksmith docker cache for npm telegram 2026-04-24 12:36:50 +05:30
Ayaan Zaidi
e30837910b ci(release): set up buildx for npm telegram image 2026-04-24 12:33:42 +05:30
Ayaan Zaidi
512d3d2287 ci(release): prebuild npm telegram docker image 2026-04-24 12:29:54 +05:30
Peter Steinberger
28fc03c386 perf: slim reset model selection imports 2026-04-24 07:56:32 +01:00
Peter Steinberger
9f8b400630 perf: slim directive parse test imports 2026-04-24 07:50:46 +01:00
Ayaan Zaidi
a02a54ff13 ci(release): clarify npm telegram approval label 2026-04-24 12:20:14 +05:30
Peter Steinberger
5b3952e857 test: relax live tail readiness checks 2026-04-24 07:48:36 +01:00
Ayaan Zaidi
8ba22ca0dc ci(release): use release approval for npm telegram e2e 2026-04-24 12:15:09 +05:30
pashpashpash
41c5ffc5d5 Project Codex hook notifications into agent events (#70969)
* project codex hook notifications

* keep codex hook duration strict

* include thread scoped codex hook notifications
2026-04-24 15:43:03 +09:00
Josh Lehman
925d11d890 fix: match codex verbose tool logs to pi (#70966) 2026-04-23 23:42:09 -07:00
Vincent Koc
8fade9df27 feat(diagnostics): attach trace context to otel logs (#70961)
* feat(diagnostics): attach trace context to otel logs

* fix(diagnostics): satisfy trace flags lint
2026-04-23 23:40:42 -07:00
Vincent Koc
48b9452c07 docs(faq): tighten FAQ stub pointers and Related cards 2026-04-23 23:37:56 -07:00
Vincent Koc
bc195b8f53 docs(help): rewrite help index to match new tab structure, drop redundant troubleshooting H1 2026-04-23 23:36:49 -07:00
Ayaan Zaidi
972c7112a2 refactor(release): distill npm telegram docker runner 2026-04-24 12:06:33 +05:30
Ayaan Zaidi
02d7215005 ci(release): gate npm telegram e2e by release team 2026-04-24 12:06:33 +05:30
Ayaan Zaidi
ed6b487e20 ci(release): harden npm telegram beta e2e 2026-04-24 12:06:33 +05:30
Ayaan Zaidi
5dd3c37fce test(release): address npm telegram e2e review 2026-04-24 12:06:33 +05:30
Ayaan Zaidi
3d8e6a3aa3 test(release): avoid docker argv secret values 2026-04-24 12:06:33 +05:30
Ayaan Zaidi
0baa8c1763 ci(release): add manual npm telegram beta e2e 2026-04-24 12:06:33 +05:30
Ayaan Zaidi
bd1b8448a5 test(release): support convex npm telegram credentials 2026-04-24 12:06:33 +05:30
Peter Steinberger
b7fba2100f docs: clarify private ws node setup 2026-04-24 07:32:29 +01:00
Peter Steinberger
f85806b6d7 fix: filter gateway node list locally 2026-04-24 07:32:28 +01:00
Vincent Koc
cb4fc58547 feat(plugins): move Bonjour discovery into bundled plugin
* fix(deps): detect constant dynamic imports in ownership audit

* feat(plugins): move bonjour discovery into bundled plugin

* test(plugins): remove moved bonjour core tests

* fix(plugins): harden bonjour disable and console restore

* fix(plugins): split gateway discovery ids from services

* fix(plugins): harden bonjour advertiser shutdown

* fix(plugins): clean up bonjour split lint
2026-04-23 23:29:51 -07:00
Peter Steinberger
564f820efa perf: reuse subagent spawn test module 2026-04-24 07:26:15 +01:00
Peter Steinberger
fa139b4fca fix(voice-call): handle Telnyx callback payloads 2026-04-24 07:25:44 +01:00
Peter Steinberger
ad0fcf9143 perf: tighten auto-reply command tests 2026-04-24 07:22:08 +01:00
Vincent Koc
37c37eecfb feat(plugins): expose install source facts
* feat(plugins): expose install source facts

* fix(plugins): normalize install integrity facts

* fix(plugins): guard install source string fields

* fix(plugins): keep install source facts additive
2026-04-23 23:21:43 -07:00
Peter Steinberger
b588b5a230 fix(channels): accept setup aliases for add 2026-04-24 07:20:45 +01:00
Patrick Erichsen
d29eaeafc1 fix(cli-runner): fire before_agent_reply on cron-triggered turns (#70950)
* test(cli-runner): RED — assert before_agent_reply fires on cron triggers

Mirrors src/agents/pi-embedded-runner/run.before-agent-reply-cron.test.ts
for the CLI runner. Asserts:

1. When trigger=cron and a before_agent_reply hook claims the turn
   (handled: true), runCliAgent must NOT invoke the codex subprocess and
   must return the hook's reply text in payloads[0].
2. When the hook claims without a reply body, the synthesized payload
   uses SILENT_REPLY_TOKEN.
3. Non-cron triggers do not invoke the hook (no behavior change for
   normal user/heartbeat traffic).
4. Without a registered hook, falls through to the CLI subprocess.

Currently fails (RED): tests 1 and 2 fail because runCliAgent never
fires before_agent_reply — the hook gate exists only in the embedded PI
runner (src/agents/pi-embedded-runner/run.ts:326). This is the
CLI-backed-agent dreaming gap reported in #70940 and identified in
PR #70737 review.

Next commit: implement the hook gate in runPreparedCliAgent (GREEN).

* fix(cli-runner): GREEN — fire before_agent_reply for cron-triggered turns

Mirrors the embedded PI runner gate from
src/agents/pi-embedded-runner/run.ts:326 so plugin-managed cron jobs
(notably memory-core dreaming) can short-circuit a CLI-backed agent
turn before the codex/claude/gemini subprocess is spawned.

Without this, configuring a default agent's model to a CLI backend
(codex-cli, claude-cli, gemini-cli, or any third-party
`registerCliBackend` provider) silently broke dreaming: the cron
sentinel was sent to the underlying LLM as a literal user prompt and
the dreaming hook never executed. See openclaw/openclaw#70940 for the
empirical repro (codex-cli observed sending the dream-token to GPT-5.5
with no `memory-core: dreaming promotion complete` line).

Also extracts `buildHandledReplyPayloads` locally; eventually that
should be unified with the embedded PI runner's helper, but that's a
mechanical refactor for a follow-up.

Closes #70940 once both this PR and #70737 land — this fix is only
useful if cron-driven dreaming exists, which is what #70737 introduces.

TDD trail:
- prior commit: RED test asserting the hook gate (4 cases)
- this commit: implementation that turns those tests green (4/4 pass).

Verified: pnpm test src/agents/cli-runner.before-agent-reply-cron.test.ts
4/4 passed; pnpm test src/agents/cli-runner 21/21 passed; lint clean
on touched files; pre-existing tsgo failure in
src/plugin-sdk/provider-tools.ts is unrelated to these changes.
2026-04-23 23:16:26 -07:00
Peter Steinberger
7d9172d5e0 perf: speed up slow extension tests 2026-04-24 07:13:46 +01:00
Peter Steinberger
bcea5e75eb test: harden Docker E2E readiness 2026-04-24 07:10:56 +01:00
Peter Steinberger
7ac35b4f69 perf: merge cron direct delivery tests 2026-04-24 06:54:36 +01:00
Vincent Koc
350d322180 fix(diagnostics): harden trace context parsing (#70955) 2026-04-23 22:47:54 -07:00
Peter Steinberger
bae7b54a85 fix(agents): detect codex cli auth in status
Fixes #70688.
Co-authored-by: Jon Brown <801241+jb510@users.noreply.github.com>
2026-04-24 06:47:28 +01:00
Peter Steinberger
a53fea3905 test: skip ACP marker probes without transcript 2026-04-24 06:42:28 +01:00
Peter Steinberger
c3138e372c chore: remove dead registry aliases 2026-04-24 06:41:49 +01:00
Peter Steinberger
bff212822c fix: restore models list registry fallback 2026-04-24 06:40:38 +01:00
Peter Steinberger
73288c20bd fix(channels): defer setup runtime deps until login 2026-04-24 06:40:25 +01:00
Peter Steinberger
6c509d8d4b docs: clarify codex plugin auto-enable boundary 2026-04-24 06:38:54 +01:00
Peter Steinberger
cc28989b4b test(config): cover codex plugin auto-enable boundaries 2026-04-24 06:38:54 +01:00
Peter Steinberger
4f4d2ef1df chore: remove dead compat barrels 2026-04-24 06:37:43 +01:00
Peter Steinberger
e94c0bf515 perf: trim control ui auth tests 2026-04-24 06:29:12 +01:00
Patrick Erichsen
aca92b2906 memory/dreaming: decouple managed cron from heartbeat (#70737)
* Revert "fix(memory/dreaming): surface blocked status when heartbeat is disabled for main (#69875)"

This reverts commit 529577e045.

Making way for the dreaming-vs-heartbeat decoupling from Josh's
josh/dreaming-isolated-cron-fix branch, which moves the managed dreaming
cron to isolated agent turns (sessionTarget: "isolated") so dreaming no
longer requires heartbeat to fire. Once the cron no longer rides the
heartbeat path, the blocked-reason observability has nothing left to
report — removing it cleanly here before the cherry-picks land.

* openclaw-3ba.1: move managed dreaming cron to isolated agent turns

* openclaw-46d: claim cron runs before embedded attempts

* openclaw-575: disable managed dreaming cron delivery

* openclaw-575: accept wrapped dreaming cron tokens

* openclaw-ccd: filter cron and wrapper transcript noise from dreaming corpus

* openclaw-cd9: filter archived, cron, and heartbeat transcript noise from dreaming corpus

* openclaw-cd9: suppress role-label reflection tags in rem dreaming

* openclaw-b49: stop narrative timeouts from blocking dreaming cron

* openclaw-b49: keep managed dreaming cron out of diary subagents

* openclaw-ff9: restore cron dream diary generation without serial waits

* openclaw-ff9: run dreaming narratives with lightweight isolated subagent lanes

* openclaw-ff9: detach cron dream diary generation from run completion

* openclaw-ff9: defer cron diary task startup until after cron completion

* doctor/cron: migrate stale managed dreaming jobs to isolated agent turns

After the dreaming cron moved off the heartbeat path to sessionTarget:
"isolated" + payload.kind: "agentTurn" (see the preceding memory-core
changes), users with existing ~/.openclaw/cron/jobs.json entries in the
old sessionTarget: "main" + payload.kind: "systemEvent" shape still
carry stale jobs until the gateway restart reconcile rewrites them.

Add a dreaming-specific cron migration to the existing
maybeRepairLegacyCronStore doctor path so "openclaw doctor" (and
"openclaw doctor --fix") rewrites those jobs without needing a gateway
restart. Match lives in a new doctor-cron-dreaming-payload-migration
helper alongside the existing legacy-delivery and store-migration files.

The matching uses the memory-core managed-job name and description tag
plus the short-term-promotion payload token. Constants are mirrored
from extensions/memory-core/src/dreaming.ts and commented so a future
rename in memory-core is a visible drift point here too.

* memory/dreaming: tighten cron-token match to known wrapper, not substring

The previous match relaxed the line check from 'trimmed line equals token'
to 'line contains token anywhere as a substring' to accept the
`[cron:<id>] <token>` wrapper that isolated-cron turns add. Substring
matching also let any user message embedding the token mid-sentence
trigger the dream-promotion hook, and was flagged by both Greptile and
Aisle on PR #70737.

Replace it with strip-the-known-prefix-then-exact-match: keep the
`[cron:<id>]` wrapper case working, reject every other variant. Add
focused unit coverage that the bare token, the wrapped token, and bare
multiline cases match while embedded / code-fenced / arbitrarily-wrapped
variants do not.

* memory/dreaming: drop assistant followup only on assistant-side signals

Per PR #70737 review (aisle-research-bot, Medium): the previous logic
suppressed the next assistant message whenever the prior user message
matched a 'generated prompt' pattern (`[cron:...]`,
`System (untrusted): ...`, heartbeat prompts, exec-completion events).
Real users can type those same patterns, which let a user exfiltrate
real assistant replies from the dreaming corpus by prefixing their own
prompt — the assistant's reply would be silently dropped.

Remove the cross-message coupling. Assistant-side machinery (silent
replies, system wrappers) is already dropped by sanitizeSessionText,
which is the right layer for that filter. Add an explicit assistant-side
HEARTBEAT_TOKEN check to keep the legitimate `HEARTBEAT_OK` ack drop
working without depending on the prior user message. Add a regression
test exercising the spoofing scenario.

* doctor/cron: assert mirrored dreaming constants stay in sync

Per PR #70737 review (greptile-apps): the doctor migration mirrors three
constants (MANAGED_DREAMING_CRON_NAME, MANAGED_DREAMING_CRON_TAG,
DREAMING_SYSTEM_EVENT_TEXT) from extensions/memory-core/src/dreaming.ts.
A future rename in either file would silently break the migration.

Add a vitest unit that reads both files and asserts the literals match.
Manually verified the assertion fires with a clear error when one side
diverges. Adds no runtime cost; sits in the regular test pipeline.

* fix(memory): stabilize dreaming CI checks

* memory/dreaming: skip eager narrative session cleanup when detached

Per PR #70737 review (chatgpt-codex-connector, P2): runDreamingSweepPhases
called deleteNarrativeSessionBestEffort synchronously right after each
phase. Once narrative generation moved to detached mode (queued via
queueMicrotask), the eager cleanup races the writer: the session is
deleted before the queued subagent run reads it, silently dropping cron
diary entries.

Skip the eager cleanup branch when params.detachNarratives is true.
generateAndAppendDreamNarrative still runs its own deleteSession in the
finally{} block, so the cleanup intent is preserved without the race.
Heartbeat-driven (non-detached) runs keep the original eager-cleanup
behavior.

* fix(plugin-sdk): restore heartbeat-summary re-export

Per PR #70737 review (chatgpt-codex-connector, P1): the revert of
PR #69875 dropped the `heartbeat-summary` re-export from
`openclaw/plugin-sdk/infra-runtime`. That subpath shipped publicly two
days earlier, so removing it is technically a breaking change to a
public SDK surface — third-party plugins importing
`isHeartbeatEnabledForAgent` / `resolveHeartbeatIntervalMs` from this
path would fail with no replacement contract introduced.

Restore the re-export. Costs nothing to keep; the helpers are already
public via `../infra/heartbeat-summary.ts`. SDK additions are by
default backwards-compatible (CLAUDE.md), so removing within days of
introduction violates that intent.

* changelog: note dreaming decoupling from heartbeat

Refs PR #70737.

---------

Co-authored-by: Josh Lehman <josh@martian.engineering>
2026-04-23 22:23:19 -07:00
Peter Steinberger
acbceb8a76 docs(qa): record convex telegram live testing notes 2026-04-24 06:22:30 +01:00
Peter Steinberger
b0d2003fe6 docs: document Meet node command allowlist 2026-04-24 06:19:12 +01:00
Peter Steinberger
99d8f699aa fix: use absolute system profiler for Meet audio checks 2026-04-24 06:18:43 +01:00
Vincent Koc
0ad058a9cb feat(diagnostics): add trace context carrier (#70924) 2026-04-23 22:18:21 -07:00
Peter Steinberger
5f702b464b test: skip ACP bind probes without transcript 2026-04-24 06:12:46 +01:00
Peter Steinberger
a62a7f2945 test(channels): cover staged setup entry dependency loading 2026-04-24 06:10:07 +01:00
Peter Steinberger
d32fdcebc1 fix(channels): keep bundled setup entries dependency-light 2026-04-24 06:10:07 +01:00
Peter Steinberger
d91f6a05c6 docs(qa): note tmux op credential lookup 2026-04-24 06:09:52 +01:00
Peter Steinberger
9f4ef6162d test(gateway): trust codex guardian status 2026-04-24 06:07:36 +01:00
Peter Steinberger
d4e93e791b fix: persist private ws opt-in for node services 2026-04-24 06:07:22 +01:00
Peter Steinberger
171322644d fix: use openclaw temp root for telegram live preflight 2026-04-24 06:07:17 +01:00
Vincent Koc
799a42bd13 feat(plugins): expose activation plan reasons (#70943) 2026-04-23 22:06:07 -07:00
Peter Steinberger
b2840b93c8 test(gateway): harden codex live harness 2026-04-24 06:00:45 +01:00
Peter Steinberger
6f80082028 test: default live model concurrency 2026-04-24 05:57:57 +01:00
Peter Steinberger
0304d0ce4e test: stabilize gateway test helpers 2026-04-24 05:55:27 +01:00
Peter Steinberger
c45e4c3cf4 fix: pass Gemini trust flag 2026-04-24 05:55:27 +01:00
Peter Steinberger
1e83357abe test: harden live docker lanes 2026-04-24 05:55:27 +01:00
Peter Steinberger
01e4824fd3 test: parallelize docker aggregate lanes 2026-04-24 05:55:27 +01:00
Peter Steinberger
960f3b07b1 fix: refresh protocol models and cron test lint 2026-04-24 05:54:13 +01:00
Ayaan Zaidi
63653f51d8 test(qa): wait for lab abort marker content 2026-04-24 10:23:56 +05:30
Ayaan Zaidi
da129727c5 test(release): forward gemini key to npm telegram smoke 2026-04-24 10:23:56 +05:30
Ayaan Zaidi
864de4a2e9 test(qa): decouple mock telegram preflight auth 2026-04-24 10:23:56 +05:30
Ayaan Zaidi
f7157958de test(release): harden npm telegram smoke inputs 2026-04-24 10:23:56 +05:30
Ayaan Zaidi
9755c8a05f test(release): add npm telegram live smoke 2026-04-24 10:23:56 +05:30
Ayaan Zaidi
95f6697bd7 test(qa): support packaged gateway live lanes 2026-04-24 10:23:56 +05:30
Peter Steinberger
b98a6a46fb docs: raise live model sweep concurrency 2026-04-24 05:52:06 +01:00
Peter Steinberger
bfa6708c03 perf: narrow gateway runtime reset imports 2026-04-24 05:48:32 +01:00
Peter Steinberger
24bf56ce60 test: stabilize live model sweeps 2026-04-24 05:48:01 +01:00
Shakker
9d445f4d68 perf: speed up provider-filtered models list (#70632) (thanks @shakkernerd) 2026-04-24 05:46:25 +01:00
Shakker
a29233c9af test: fix gateway session lint 2026-04-24 05:46:25 +01:00
Shakker
da6c29b3d9 fix: bound unscoped provider discovery fallback 2026-04-24 05:46:25 +01:00
Shakker
d3fe591853 test: update models list static fast path expectation 2026-04-24 05:46:25 +01:00
Shakker
2e45218ae8 fix: keep live catalog providers on registry path 2026-04-24 05:46:25 +01:00
Shakker
9941393c7a fix: keep third party provider filters on registry path 2026-04-24 05:46:25 +01:00
Shakker
6f04eee2a1 fix: keep static provider entries out of live discovery 2026-04-24 05:46:25 +01:00
Shakker
4737a86071 fix: preserve provider filtered catalog correctness 2026-04-24 05:46:25 +01:00
Shakker
3254e961e9 refactor: expose bundled static provider catalogs 2026-04-24 05:46:25 +01:00
Shakker
29d0e930bb test: cover provider-filtered catalog fast path 2026-04-24 05:46:25 +01:00
Shakker
a50aef82ba perf: generalize provider-filtered catalog fast path 2026-04-24 05:46:25 +01:00
Vincent Koc
959dedb7cf docs(help): move help/scripts out of Testing group into Reference/Release and CI 2026-04-23 21:45:53 -07:00
Peter Steinberger
a903438707 perf: trim chat history limit fixture 2026-04-24 05:43:03 +01:00
Peter Steinberger
bfc9cb92c5 perf: bypass gateway server in cron validation tests 2026-04-24 05:40:47 +01:00
Peter Steinberger
22f23fa5ab perf: speed up gateway session tests 2026-04-24 05:38:06 +01:00
Peter Steinberger
cb2c36b049 fix: lock realtime talk instructions 2026-04-24 05:33:11 +01:00
Peter Steinberger
569290c36d feat: add Google Meet paired-node Chrome transport 2026-04-24 05:31:32 +01:00
Simone
098557623f fix(codex): require final approval decisions (#70751)
Require the Codex app-server bridge to wait for the final two-phase approval decision, while preserving the explicit no-route sentinel behavior.

Local gate on rebased branch: pnpm check:changed (20 files, 157 tests).

Thanks @Lucenx9.

Co-authored-by: Lucenx9 <185146821+Lucenx9@users.noreply.github.com>
2026-04-24 05:30:59 +01:00
Simone
ed6094b301 fix(codex): sanitize approval preview text (#70569)
Harden Codex app-server approval preview text sanitization and truncation handling.

Thanks @Lucenx9.

Co-authored-by: Lucenx9 <185146821+Lucenx9@users.noreply.github.com>
2026-04-24 05:23:29 +01:00
Peter Steinberger
d3dd61f2c5 perf: slim whatsapp test helper imports 2026-04-24 05:22:02 +01:00
Peter Steinberger
c971c58fc7 docs: clarify control ui talk status 2026-04-24 05:21:40 +01:00
Patrick Erichsen
4d7c4b3298 fix(memory-core): harden singleton cache recovery (#70925)
* fix memory cache singleton hardening

* refactor(memory-core): simplify singleton cache repair

Co-authored-by: BirdSong <88885494+fire-mirror@users.noreply.github.com>

---------

Co-authored-by: BirdSong <88885494+fire-mirror@users.noreply.github.com>
2026-04-23 21:21:04 -07:00
Peter Steinberger
84fc00afda perf: narrow whatsapp test imports 2026-04-24 05:19:36 +01:00
Peter Steinberger
a7c1376b20 fix(block-streaming): dedupe aborted final text 2026-04-24 05:18:45 +01:00
Vincent Koc
deb300d905 docs(nav): normalize sidebar group names to sentence case 2026-04-23 21:16:27 -07:00
Vincent Koc
1e24d95c54 docs(nav): sub-group macOS companion app pages (Setup / Runtime / Features), add qwen_modelstudio redirect 2026-04-23 21:15:17 -07:00
Vincent Koc
5aa5c4eff2 docs: tidy nav — macOS app sub-groups, drop qwen_modelstudio stub with redirect 2026-04-23 21:15:17 -07:00
Peter Steinberger
1a002b021f fix(codex): sanitize context-engine assemble warnings (#70809) (thanks @jalehman)
Co-authored-by: Josh Lehman <josh@martian.engineering>
2026-04-24 05:13:23 +01:00
Peter Steinberger
c7ee5d8ecf perf: narrow inbound debounce sdk imports 2026-04-24 05:07:28 +01:00
Josh Lehman
51186d2725 feat(codex): run context-engine lifecycle in app-server harness (#70809)
Port the Codex app-server harness onto the context-engine lifecycle, add Codex context projection and compaction integration, and cover bootstrap/history/compaction fallback behavior.

Thanks @jalehman.
2026-04-24 05:06:45 +01:00
Peter Steinberger
ac063568d3 test: speed up live model sweeps 2026-04-24 05:05:28 +01:00
Vincent Koc
d717dbba51 Merge branch 'main' of https://github.com/openclaw/openclaw
* 'main' of https://github.com/openclaw/openclaw:
  fix(whatsapp): canonicalize outbound media delivery (#69813)
2026-04-23 21:05:10 -07:00
Marcus Castro
18c98316f7 fix(whatsapp): canonicalize outbound media delivery (#69813)
* fix(whatsapp): normalize outbound media payloads

* fix(embedded-runner): preserve final media directives

* fix(auto-reply): keep non-streaming media on final path

* fix(auto-reply): warn when reply media is dropped

* fix(whatsapp): align auto-reply media delivery

* docs(changelog): note whatsapp media normalization
2026-04-24 01:04:28 -03:00
Vincent Koc
e2c3225636 Merge branch 'main' of https://github.com/openclaw/openclaw
* 'main' of https://github.com/openclaw/openclaw:
  fix(codex): resolve Windows app-server shims
2026-04-23 21:02:11 -07:00
Vincent Koc
7acaebeaac Revert "refactor(plugins): track activation compat hints"
This reverts commit b1d0c14d38.
2026-04-23 21:01:53 -07:00
Peter Steinberger
5b34082106 fix(codex): resolve Windows app-server shims 2026-04-24 05:01:46 +01:00
Vincent Koc
b1d0c14d38 refactor(plugins): track activation compat hints 2026-04-23 20:59:34 -07:00
Peter Steinberger
76a4c167f7 fix(slack): suppress verbose progress in rooms 2026-04-24 04:52:21 +01:00
Vincent Koc
c1dfaef0a0 docs(channels,gateway): split heavy sidebar groups (channels by region, gateway config by concern) 2026-04-23 20:50:25 -07:00
Vincent Koc
38bb4fefb9 docs(help): restructure Help tab sidebar and shorten FAQ / live-tests titles 2026-04-23 20:48:42 -07:00
Peter Steinberger
c21c8f3059 perf: narrow mattermost setup imports 2026-04-24 04:45:29 +01:00
Vincent Koc
627c19c5cb docs: add Related sections to remaining CLI, gateway API, and help pages 2026-04-23 20:41:35 -07:00
Peter Steinberger
53aac30f51 fix: bridge codex request user input 2026-04-24 04:40:47 +01:00
Peter Steinberger
eb6e1245ac perf: narrow zalo monitor imports 2026-04-24 04:40:42 +01:00
Vincent Koc
2fb9c7e3e5 docs: add Related sections to remaining platform, reference template, and misc pages 2026-04-23 20:40:15 -07:00
Vincent Koc
ed286078d6 docs(concepts): expand agent runtime opening with contract orientation 2026-04-23 20:36:40 -07:00
Patrick Erichsen
88fb6518c2 test(qa): validate Discord Convex credential payloads (#70910) 2026-04-23 20:35:54 -07:00
Vincent Koc
ae609e0249 docs(gateway): split configuration-reference by extracting tools and custom providers into config-tools 2026-04-23 20:34:46 -07:00
Dranbo Fieldston
977a4b24af fix: propagate timeoutMs to guarded dispatchers (local LLM 60s timeout) (#70831)
* fix: propagate timeoutMs to guarded dispatchers

Thread timeoutMs through the dispatcher creation chain so that
per-request (guarded) dispatchers honor the configured LLM timeout
instead of falling back to undici's hardcoded 60s bodyTimeout/headersTimeout.

Changes:
- undici-runtime.ts: createHttp1Agent/ProxyAgent/EnvHttpProxyAgent now accept
  timeoutMs and apply bodyTimeout/headersTimeout to dispatcher options
- ssrf.ts: createPinnedDispatcher accepts timeoutMs and passes it through
- fetch-guard.ts: fetchWithSsrFGuard reads timeout from params or falls back
  to global dispatcher bodyTimeout via getGlobalDispatcher()
- provider-transport-fetch.ts: buildGuardedModelFetch accepts optional
  timeoutMs and passes it to fetchWithSsrFGuard

The global dispatcher timeout (set by ensureGlobalUndiciStreamTimeouts)
is still applied to non-guarded requests. Guarded requests (used by LLM
transports) now also receive the timeout via a fallback to the global
dispatcher when not explicitly provided.

Fixes #70829

* fix: resolve fallback timeout via module-level bridge variable

Replace dead-code .options.bodyTimeout read in resolveDispatcherTimeoutMs
with a module-level bridge (_globalUndiciStreamTimeoutMs) set by
ensureGlobalUndiciStreamTimeouts. This avoids reliance on Undici's
non-public .options field and ensures guarded dispatchers inherit the
configured stream timeout instead of falling back to undici's 60s default.

Fixes Greptile P1 and Codex comments on PR #70831

* chore: re-run CI smoke tests

* test: cover guarded dispatcher timeout propagation

* test: align timeout bridge expectation

* docs: note guarded dispatcher timeout fix

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-04-24 04:34:11 +01:00
Vincent Koc
86fa8eeb68 docs: add Related to google-meet, fix Remote control title case 2026-04-23 20:33:01 -07:00
Vincent Koc
867714ca45 docs(help): split FAQ by extracting models, failover, and auth profiles Q&A into faq-models 2026-04-23 20:31:27 -07:00
Peter Steinberger
55389f4be2 perf: narrow msteams attachment imports 2026-04-24 04:29:12 +01:00
Vincent Koc
248baba54b docs(faq): fix stale openai fast-mode anchor 2026-04-23 20:29:01 -07:00
Peter Steinberger
88b53b7f0a docs: align talk silence defaults 2026-04-24 04:26:47 +01:00
Peter Steinberger
9ac52e0737 test: remove duplicate telegram retry tests 2026-04-24 04:26:31 +01:00
Vincent Koc
031c3b22de docs: clarify pruning behavior and setup TL;DR orientation 2026-04-23 20:26:26 -07:00
Peter Steinberger
a42bd94b21 ci: keep install smoke off pull requests 2026-04-24 04:24:58 +01:00
Peter Steinberger
b5779b992f fix(plugins): mirror SDK alias for staged sidecars 2026-04-24 04:24:58 +01:00
Peter Steinberger
e0d3256311 test(codex): cover app-server Docker flows 2026-04-24 04:24:08 +01:00
Peter Steinberger
69566e43cb feat(codex): add app-server protocol bridge 2026-04-24 04:24:08 +01:00
Peter Steinberger
553162c998 feat(agents): support Codex app-server runs 2026-04-24 04:24:07 +01:00
Peter Steinberger
5d0887574b feat(plugin-sdk): add conversation binding hooks 2026-04-24 04:24:07 +01:00
Vincent Koc
ffa5f4514f docs: unify See also/Related headings across remaining pages 2026-04-23 20:23:06 -07:00
Peter Steinberger
e93113db09 perf: lazy reply dispatch sdk runtime 2026-04-24 04:22:56 +01:00
Vincent Koc
34f7a93c04 docs(channels): rewrite passive-voice notes in msteams UPN and whatsapp fromMe bullets 2026-04-23 20:20:36 -07:00
Vincent Koc
3a5e535bed docs(help): split FAQ by extracting quick start and first-run Q&A into faq-first-run 2026-04-23 20:19:28 -07:00
Peter Steinberger
7d47183736 docs: fix config agent defaults link 2026-04-24 04:15:52 +01:00
Peter Steinberger
dbdf2863d6 docs: fix broken internal links 2026-04-24 04:13:20 +01:00
Vincent Koc
ed7033bc0a docs(providers): add Related sections to remaining provider pages 2026-04-23 20:12:50 -07:00
Vincent Koc
f051204bea docs(gateway): split configuration-reference by extracting channels cluster into config-channels 2026-04-23 20:12:09 -07:00
Vincent Koc
07cee914aa docs(gateway): split configuration-reference by extracting agent-defaults cluster into config-agents 2026-04-23 20:11:12 -07:00
Vincent Koc
72a8e4e5db docs(codex): clarify hook layering
Clarify Codex hook layering in the harness docs.
2026-04-23 20:09:46 -07:00
Peter Steinberger
60956ba6ac perf: narrow telegram bot test imports 2026-04-24 04:09:13 +01:00
Vincent Koc
8d1f98ef08 docs(gateway,platforms,cli): add Related sections to entry and reference pages 2026-04-23 20:08:26 -07:00
Vincent Koc
f0b6c65e3b docs(install,reference): add Related sections to pages missing them 2026-04-23 20:07:25 -07:00
Vincent Koc
b5120ab22a docs(platforms): link Bun warning to the Bun install page for context 2026-04-23 20:06:34 -07:00
Vincent Koc
78e4f5188a docs(install): move system requirements above the installer script section 2026-04-23 20:06:06 -07:00
Vincent Koc
1dfc84d0a4 docs(video-generation): convert provider notes table to accordion for scannability 2026-04-23 20:05:13 -07:00
Vincent Koc
9153598e65 docs(plugins): split architecture by extracting internals (load pipeline, runtime hooks, HTTP routes, schemas) 2026-04-23 20:03:22 -07:00
Peter Steinberger
47372a5567 fix: point minimax live docs test at split guide 2026-04-24 03:55:06 +01:00
Peter Steinberger
c6684af682 fix: guard openai realtime browser fetch 2026-04-24 03:50:43 +01:00
Patrick Erichsen
3a18801343 Add Discord live QA lane (#70792)
* Add Discord live QA lane

* Add Discord native command QA coverage
2026-04-23 19:48:37 -07:00
Peter Steinberger
1616510996 perf: narrow memory core test imports 2026-04-24 03:46:18 +01:00
Peter Steinberger
feb3cc70fb perf: narrow qa bus test imports 2026-04-24 03:44:56 +01:00
Peter Steinberger
85a2d1d05e fix: update realtime protocol swift models 2026-04-24 03:44:52 +01:00
Peter Steinberger
913f97c956 perf: lazy codex app server test imports 2026-04-24 03:42:00 +01:00
Vincent Koc
d3f6783b16 docs(tools): convert perplexity-search params to ParamField 2026-04-23 19:41:09 -07:00
Vincent Koc
5f19e288b1 docs(tools): convert search and web-fetch param tables to ParamField 2026-04-23 19:40:05 -07:00
Vincent Koc
f4b61e7277 docs(help): split testing by extracting live (network-touching) test suites 2026-04-23 19:38:59 -07:00
Vincent Koc
f4d73e1dcd docs(tools): split ACP agents by extracting acpx harness, plugin setup, and permissions 2026-04-23 19:36:19 -07:00
Vincent Koc
743b69d307 docs(tools): split browser docs by extracting control API and CLI reference 2026-04-23 19:34:50 -07:00
Vincent Koc
60d892d700 fix(reply): parse markdown image replies as media
* fix(reply): parse markdown image replies as media

* fix(reply): preserve inline markdown image captions

* fix(reply): harden markdown image parsing
2026-04-23 19:34:30 -07:00
Peter Steinberger
04066d246a feat: add browser realtime talk 2026-04-24 03:33:36 +01:00
Vincent Koc
d42069b11e fix(replay): preserve synthetic tool repair aliases
* fix(replay): preserve synthetic tool repair aliases

* test(replay): cover Bedrock repair ownership
2026-04-23 19:33:05 -07:00
Truffle
a958b6e723 fix(runner): surface provider errors to webchat (#70848)
Surface non-retryable assistant provider failures from the embedded runner instead of letting surface_error fall through to continue_normal.

- Preserve external abort and plain timeout fall-through paths.
- Preserve raw provider error diagnostics on surfaced FailoverError.
- Add regression coverage for billing/auth/rate-limit/null-reason/error fall-through cases.
- Update changelog.

Fixes #70124.
Thanks @truffle-dev.
2026-04-24 03:28:38 +01:00
Peter Steinberger
7c18b765e8 perf: reduce discord provider test imports 2026-04-24 03:27:31 +01:00
Peter Steinberger
dd1576204a docs(changelog): credit bundled runtime deps fix 2026-04-24 03:27:04 +01:00
Peter Steinberger
0daf51d645 fix(plugins): mirror sdk alias for external bundled deps 2026-04-24 03:27:04 +01:00
Peter Steinberger
49c95b31c0 test(e2e): run root-owned gateway logging as appuser 2026-04-24 03:27:04 +01:00
Peter Steinberger
b0244f613e fix(plugins): clean bundled runtime install stage 2026-04-24 03:27:04 +01:00
simonemacario
02a9dd0ddc fix(plugins): stage bundled-plugin runtime-dep install outside the plugin root
When a packaged bundled plugin's `pluginRoot` is used directly as the npm
execution cwd, `npm install <specs>` resolves the plugin's own
`package.json` as the project manifest and fails with
`EUNSUPPORTEDPROTOCOL: Unsupported URL Type "workspace:": workspace:*`
whenever that manifest declares a `workspace:` runtime dep (e.g.
`"@openclaw/plugin-sdk": "workspace:*"`). This takes out every plugin
with any runtime deps at gateway startup.

`ensureBundledPluginRuntimeDeps` already filters `workspace:` specs from
the CLI arguments, but npm's own resolver reads the cwd manifest
regardless, so the filter alone is not enough. The existing isolated
execution-root + `replaceNodeModulesDir` machinery handles this exact
problem for source-checkout + cache-hit installs. This change activates
the same staging path for the packaged case: when `installRoot ===
pluginRoot` and we are not in the source-checkout cache path, stage the
install inside `<pluginRoot>/.openclaw-install-stage` (which has a
minimal generated `package.json`) and move the produced `node_modules/`
back to the plugin root as before.

- Add regression test `stages plugin-root install when the plugin's own
  package.json declares workspace:* deps` covering the Docker scenario
  (mixed `workspace:*` + concrete runtime dep, e.g. anthropic-style
  `@openclaw/plugin-sdk` + `@anthropic-ai/sdk`).
- Update existing plugin-root-install expectations (`installs
  plugin-local runtime deps when one is missing`, `skips workspace-only
  runtime deps before npm install`, `installs deps that are only present
  in the package root`, `does not trust runtime deps that only resolve
  from the package root`, `does not treat sibling extension runtime deps
  as satisfying a plugin`) to assert the new `installExecutionRoot`.

Reported in #70844; same root cause as #70701, #70756, #70773, #70818,
#70839 which see the downstream "Cannot find package 'openclaw' from
plugin-runtime-deps" symptom because their
`resolveBundledRuntimeDependencyInstallRoot` resolves to an external
stage dir (clean manifest) so the install succeeds but the resulting
node_modules tree cannot satisfy the filtered-out workspace packages at
ESM import time.

## AI assistance

This PR was AI-assisted with Claude Code.

Testing degree: fully tested for the touched `bundled-runtime-deps`
install staging surface.

- `pnpm exec vitest run --config test/vitest/vitest.plugins.config.ts src/plugins/bundled-runtime-deps.test.ts` (31/31)
- `pnpm exec vitest run --config test/vitest/vitest.plugins.config.ts src/plugins/` (43/43 across 8 files)
- `pnpm exec tsgo --noEmit -p tsconfig.core.json`, `pnpm exec tsgo --noEmit -p tsconfig.core.test.json` (clean)
- `pnpm exec oxlint src/plugins/bundled-runtime-deps.ts src/plugins/bundled-runtime-deps.test.ts` (0 warnings, 0 errors)
- `node scripts/check-src-extension-import-boundary.mjs --json` and `node scripts/check-sdk-package-extension-import-boundary.mjs --json` (both `[]`)

I understand the code path changed here: packaged bundled plugins now
stage their runtime-dep install one directory below `pluginRoot` so npm
never reads the plugin's `workspace:*`-containing manifest during
install; after install completes, the produced `node_modules/` is moved
back to `pluginRoot` via the existing `replaceNodeModulesDir` helper.

Signed-off-by: Simone Macario <simone@sharly.ai>
2026-04-24 03:27:04 +01:00
Shakker
64ed439ad0 perf: avoid broad models list enumeration (#70883) (thanks @shakkernerd) 2026-04-24 03:25:26 +01:00
Shakker
c93f053f80 test: cover default models list registry narrowing 2026-04-24 03:25:26 +01:00
Shakker
a6a2516cd8 perf: narrow default models list registry loading 2026-04-24 03:25:26 +01:00
Peter Steinberger
f9b33b7d96 fix: disable bundled plugins during Parallels update 2026-04-24 03:23:14 +01:00
Peter Steinberger
a59d1bd46d perf: narrow slack test imports 2026-04-24 03:17:32 +01:00
Peter Steinberger
3aa3551491 test: cover OpenAI server compaction docs 2026-04-24 03:15:47 +01:00
Peter Steinberger
467f839198 docs(plugins): explain google meet audio install 2026-04-24 03:14:25 +01:00
Peter Steinberger
2af88fab6c docs: document local memory embedding provider 2026-04-24 03:11:22 +01:00
Matt Znoj Assist
e069d03945 fix(memory-core): declare local memoryEmbeddingProviders contract (#70873)
Fix standalone memory CLI resolution for the built-in local embedding provider by declaring the memory-core capability contract.\n\nFixes #70836.\nThanks @mattznojassist.
2026-04-24 03:09:49 +01:00
Peter Steinberger
272bd59e7a docs(plugins): clarify google meet quick start 2026-04-24 03:05:42 +01:00
Peter Steinberger
0c9659b70c feat(plugins): simplify google meet realtime defaults 2026-04-24 03:03:21 +01:00
Peter Steinberger
28299a94ba fix: escape Parallels config scrub script 2026-04-24 03:02:12 +01:00
Peter Steinberger
e41298f501 docs(plugins): expand google meet realtime consult docs 2026-04-24 02:56:25 +01:00
Peter Steinberger
e314190403 feat(plugins): give google meet realtime agent consult 2026-04-24 02:55:43 +01:00
Peter Steinberger
3361593442 perf: reduce feishu monitor import drag 2026-04-24 02:55:09 +01:00
Peter Steinberger
68e2d6f088 fix: use node for Parallels config scrub 2026-04-24 02:50:42 +01:00
Peter Steinberger
903308dbf2 fix: stabilize qa lab mock suite 2026-04-24 02:46:33 +01:00
Peter Steinberger
2779020cbe perf: lazy load browser test server 2026-04-24 02:45:25 +01:00
Peter Steinberger
86f69ba5a0 fix: preserve gateway image refs for text-only models 2026-04-24 02:40:10 +01:00
Peter Steinberger
92a42413df perf: lazy load discord inbound runtimes 2026-04-24 02:36:36 +01:00
Peter Steinberger
1a8a6f8fba feat(ui): steer queued chat messages 2026-04-24 02:35:40 +01:00
Shakker
7dc1aeebbf refactor: split models list row sources (#70867) (thanks @shakkernerd) 2026-04-24 02:34:36 +01:00
Shakker
a606838b4b refactor: plan models list registry loading 2026-04-24 02:34:36 +01:00
Shakker
0af56c8ba6 refactor: split models list row sources 2026-04-24 02:34:36 +01:00
Peter Steinberger
07cb18ca04 fix: scrub future plugin entries in Parallels update smoke 2026-04-24 02:33:21 +01:00
Peter Steinberger
794437a730 ci: keep full install smoke off merge pushes 2026-04-24 02:31:36 +01:00
Peter Steinberger
754acc4478 perf: reduce telegram test import drag 2026-04-24 02:28:38 +01:00
Peter Steinberger
d268c850e6 fix: honor explicit media image model routing 2026-04-24 02:21:30 +01:00
Vincent Koc
c0a7b6a510 fix(plugins): align provider auth metadata 2026-04-23 18:16:20 -07:00
Peter Steinberger
8129ac0f26 docs: add Google Meet changelog entry 2026-04-24 02:15:53 +01:00
Peter Steinberger
e63b16cf46 refactor: centralize realtime voice resolution 2026-04-24 02:15:53 +01:00
Peter Steinberger
09a79bf499 refactor: share realtime voice bridge sessions 2026-04-24 02:15:53 +01:00
Peter Steinberger
15a82d4536 refactor: share provider selection runtime helper 2026-04-24 02:15:53 +01:00
Peter Steinberger
051c543bcb fix: guard Google Meet API fetches 2026-04-24 02:15:53 +01:00
Peter Steinberger
59a8afe6fa feat: add Google Meet participant plugin 2026-04-24 02:15:53 +01:00
Peter Steinberger
e0072ef91a chore: bump version to 2026.4.24 2026-04-24 02:13:50 +01:00
Peter Steinberger
b2cface9d5 perf: consolidate browser test entrypoints 2026-04-24 02:08:38 +01:00
Peter Steinberger
27b8aa1ddf perf: consolidate extension test entrypoints 2026-04-24 02:03:00 +01:00
Shakker
c42ae0afd8 docs: update changelog for models list 2026-04-24 02:01:58 +01:00
Shakker
19f9b69586 fix: include configured provider rows in all models list 2026-04-24 02:01:58 +01:00
Shakker
d289e400d5 fix: keep model catalog reads read-only 2026-04-24 02:01:58 +01:00
Shakker
097a81fbe7 docs: document read-only models list 2026-04-24 02:01:58 +01:00
Shakker
dcc180f14f test: cover read-only models list 2026-04-24 02:01:58 +01:00
Shakker
c7af4dcb31 fix: make models list read-only 2026-04-24 02:01:58 +01:00
Peter Steinberger
93e95a2057 perf: speed up cli prepare tests 2026-04-24 01:55:02 +01:00
Peter Steinberger
b164bb3717 refactor: centralize realtime voice resolution 2026-04-24 01:50:43 +01:00
Peter Steinberger
57e139100b refactor: share realtime voice bridge sessions 2026-04-24 01:50:43 +01:00
Peter Steinberger
958afeb397 refactor: share provider selection runtime helper 2026-04-24 01:50:43 +01:00
Peter Steinberger
3caaba79bc ci: keep installer smoke dependencies installed 2026-04-24 01:50:43 +01:00
Peter Steinberger
d1ea58fdbf ci: limit bun install smoke to release gates 2026-04-24 01:50:42 +01:00
Peter Steinberger
3a2f0e7a1a ci: split install smoke fast path 2026-04-24 01:50:42 +01:00
Peter Steinberger
4ca5ef694f test: restore split docs CI parity 2026-04-24 01:50:42 +01:00
Peter Steinberger
8e87768419 ci: run telegram extension-fast with forks 2026-04-24 01:50:42 +01:00
Peter Steinberger
b22bf36bc4 ci: throttle telegram extension-fast tests 2026-04-24 01:50:42 +01:00
Peter Steinberger
7c19c31144 feat: support DTMF for voice-call 2026-04-24 01:50:42 +01:00
Peter Steinberger
79066f5cab fix(openai): synthesize codex gpt-5.5 oauth model 2026-04-24 01:49:00 +01:00
Peter Steinberger
cec3482175 fix: support codex app-server image understanding 2026-04-24 01:43:30 +01:00
Peter Steinberger
df58839a59 perf: fold slack http route test 2026-04-24 01:43:04 +01:00
Peter Steinberger
382952a9e1 docs: mark auto-response non-blocking 2026-04-24 01:42:14 +01:00
Gabriel Kripalani
0f026addaa feat: add OpenRouter image generation (#67668)
Adds OpenRouter image generation support for image_generate. Fixes #55066. Thanks @notamicrodose.
2026-04-24 01:39:19 +01:00
Peter Steinberger
3c5ee63c66 perf: consolidate feishu lifecycle test entry 2026-04-24 01:33:24 +01:00
Peter Steinberger
a2221d6b47 test: extend changed-check watchdog 2026-04-24 01:31:32 +01:00
Peter Steinberger
d4d307e07a test: cover OpenAI GPT xhigh reasoning 2026-04-24 01:30:44 +01:00
Peter Steinberger
f04a3dced0 build: update Pi model dependencies 2026-04-24 01:24:46 +01:00
Peter Steinberger
7e16e3d077 perf: narrow slack monitor imports 2026-04-24 01:09:28 +01:00
Peter Steinberger
716a3a5865 fix: honor Google image private-network opt-in 2026-04-24 01:04:13 +01:00
Peter Steinberger
cc295fb8c9 perf: dedupe telegram dispatch tests 2026-04-24 00:59:44 +01:00
Peter Steinberger
37c250695b perf: mock vllm provider setup contract 2026-04-24 00:52:53 +01:00
Peter Steinberger
b312e2e617 perf: split slack reply action constants 2026-04-24 00:47:52 +01:00
Peter Steinberger
cd8822cc5f fix: preserve OpenAI-compatible image parts 2026-04-24 00:45:42 +01:00
Peter Steinberger
178a314a4c fix: restore OpenRouter vision prompts 2026-04-24 00:42:45 +01:00
Peter Steinberger
d16b879334 fix: allow private OpenAI image endpoints 2026-04-24 00:36:00 +01:00
Peter Steinberger
5be5233250 perf: narrow slack command imports 2026-04-24 00:35:52 +01:00
Peter Steinberger
a3aa13df9b fix: prevent embedded runs from lowering undici timeouts 2026-04-24 00:34:47 +01:00
Patrick Erichsen
ef88cabe39 fix(control ui): accept paired device token for assistant media auth (#70741)
* fix control ui assistant media auth

* test control ui device token read routes

* defer assistant attachment blob downloads

* fix grouped render rebase merge

* evict stale assistant attachment blob urls

* fix assistant media device token query auth
2026-04-23 16:31:11 -07:00
Peter Steinberger
d3997bcf7a perf: narrow slack prepare ack import 2026-04-24 00:30:30 +01:00
Peter Steinberger
f7c4d7a5f0 ci: throttle docs agent workflow 2026-04-24 00:27:01 +01:00
Peter Steinberger
1e24bee879 perf: slim telegram target normalization import 2026-04-24 00:24:56 +01:00
Peter Steinberger
697fc38d1a perf: remove telegram dispatch polling waits 2026-04-24 00:21:12 +01:00
Peter Steinberger
db17b8cc4a docs: clarify landpr docs CI wait scope 2026-04-24 00:18:04 +01:00
Otto Deng
de3f3b8f93 feat(openai): pass image output options (#70503)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Otto Deng <ottodeng@users.noreply.github.com>
2026-04-24 00:17:12 +01:00
Peter Steinberger
b9a0795761 fix: route slack media auth fetch through runtime 2026-04-24 00:13:37 +01:00
Peter Steinberger
6f139dee2e perf: trim msteams authz graph mock 2026-04-24 00:09:16 +01:00
Peter Steinberger
0ad82bbbd1 chore(plugin-sdk): update API baseline 2026-04-24 00:05:38 +01:00
Peter Steinberger
f0a7a85e7a feat(agents): add generation tool timeouts 2026-04-24 00:05:38 +01:00
Peter Steinberger
bd49117a50 perf: slim msteams hot test imports 2026-04-24 00:04:48 +01:00
Tak Hoffman
07049c8eba fix(models): support Codex model add metadata (#70820) 2026-04-23 18:02:04 -05:00
Peter Steinberger
8549ddce81 docs: mark background workflows non-blocking 2026-04-23 23:59:47 +01:00
Peter Steinberger
9cc67fecaf docs(openai): clarify image generation oauth auth 2026-04-23 23:59:10 +01:00
Vincent Koc
3ce326168a docs(plugins): split SDK overview by moving subpath catalog into sdk-subpaths 2026-04-23 15:57:39 -07:00
Vincent Koc
0054818772 docs(tools): split exec-approvals into core + advanced (safe bins, forwarding, native delivery) 2026-04-23 15:56:08 -07:00
Peter Steinberger
e28fca2e11 chore: separate commit formatting from changed gate 2026-04-23 23:55:52 +01:00
Peter Steinberger
d8eb5ffef0 docs: fix typebox rpc link 2026-04-23 23:51:50 +01:00
Vincent Koc
c843c5b4ac docs: tighten passive voice and hedging on context-engine, xai, anthropic, building-plugins 2026-04-23 15:50:43 -07:00
Vincent Koc
c72329a1bb docs(pdf): convert Input reference to ParamField 2026-04-23 15:49:33 -07:00
Peter Steinberger
14c4143723 docs: clarify OpenAI GPT-5.5 auth routes 2026-04-23 23:49:17 +01:00
Vincent Koc
367b9721b6 docs(concepts,automation,plugins): add Related sections to pages missing them 2026-04-23 15:48:46 -07:00
Peter Steinberger
6259f6addc fix: harden provider and gateway test seams 2026-04-23 23:48:04 +01:00
Peter Steinberger
0999fec19b perf: slim slack media test imports 2026-04-23 23:48:02 +01:00
Vincent Koc
789e71cdb8 docs: remove H1 on pages where frontmatter + summary already cover the parenthetical 2026-04-23 15:47:48 -07:00
Vincent Koc
41448da417 docs: gloss agentDir, BOOT.md, and ambiguous dashboard pronoun 2026-04-23 15:45:29 -07:00
Vincent Koc
ac76c5aba7 docs(tools): convert exec and image-generation params to ParamField 2026-04-23 15:44:41 -07:00
Vincent Koc
d71518b1eb docs(channels,nodes): add Related sections to pages missing them 2026-04-23 15:43:47 -07:00
Vincent Koc
ba55448163 docs(providers): standardize models-section heading to Built-in catalog 2026-04-23 15:42:56 -07:00
Vincent Koc
6667f66fd8 docs(tools): add Related sections and unify See also to Related 2026-04-23 15:41:56 -07:00
Vincent Koc
1daa552d5f refactor(qr): share PNG data URL helpers (#70784) 2026-04-23 15:41:45 -07:00
Peter Steinberger
707e13f966 perf: slim vllm discovery contract test 2026-04-23 23:39:59 +01:00
Peter Steinberger
c2cf3c49d3 fix(openai): harden image auth fallback
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-04-23 23:38:04 +01:00
openclaw-docs-agent[bot]
539083811e docs: refresh documentation 2026-04-23 22:36:56 +00:00
Peter Steinberger
28484c71bb perf: trim telegram dispatch test imports 2026-04-23 23:29:20 +01:00
Peter Steinberger
dfe75db09d fix(discord): surface final reply permission context 2026-04-23 23:28:16 +01:00
Peter Steinberger
5d3aba2052 fix: preserve codex raw assistant replies 2026-04-23 23:22:31 +01:00
Peter Steinberger
7ec48b24a3 perf: inline browser ws decoder 2026-04-23 23:20:27 +01:00
Peter Steinberger
467fcb1791 test(openai): add docker image auth e2e 2026-04-23 23:13:19 +01:00
Peter Steinberger
f523bbfcd1 fix: align claude cli permissions with exec policy
Derive Claude CLI bypass mode from OpenClaw exec YOLO policy, preserve raw Claude permission-mode overrides, update docs/changelog, and cover global/per-agent policy behavior.
2026-04-23 23:11:34 +01:00
Peter Steinberger
999caf530b perf: slim browser test imports 2026-04-23 23:09:39 +01:00
openclaw-docs-agent[bot]
452a1b6341 docs: refresh documentation 2026-04-23 22:08:58 +00:00
Peter Steinberger
ededff4bc3 fix(memory): recreate stale qmd collections 2026-04-23 23:00:55 +01:00
Peter Steinberger
38f157a148 fix(openai): prefer configured Codex OAuth for images 2026-04-23 22:49:37 +01:00
Peter Steinberger
68cb054d20 perf: slim telegram sticker tests 2026-04-23 22:48:47 +01:00
Devin Robison
36c4a372a0 fix(webhooks): reload route secrets per request (#70727)
* fix(webhooks): reload route secrets per request

* docs(changelog): note webhook secret reload fix
2026-04-23 15:48:10 -06:00
Peter Steinberger
e64da8bde0 ci: rebase test performance agent updates 2026-04-23 22:46:38 +01:00
openclaw-docs-agent[bot]
58dc22c099 docs: refresh documentation 2026-04-23 21:43:52 +00:00
Peter Steinberger
9632283d5d test: update browser changed-run expectation 2026-04-23 22:35:33 +01:00
Vincent Koc
f718ba6601 fix(agents): preserve Codex model capacity guidance 2026-04-23 14:29:34 -07:00
Peter Steinberger
f0300253c1 fix: add agent hook history helpers 2026-04-23 22:29:26 +01:00
Vincent Koc
51f9f94cc3 fix(hooks): harden cli transcript loading (#70786) 2026-04-23 14:25:27 -07:00
Devin Robison
bceda6089a fix(gateway): fail closed on runtime config edits (#70726)
* fix(gateway): fail closed on runtime config edits

* changelog + telegram topic requireMention depth

Append a user-facing Unreleased/Fixes entry describing the fail-closed
gateway config-mutation allowlist, and extend the allowlist so Telegram
topic-level paths like
channels.telegram.groups.<group>.topics.<topic>.requireMention stay
agent-tunable instead of being rejected as protected after this change.
2026-04-23 15:23:44 -06:00
Peter Steinberger
02a8c13501 fix(codex): stop materializing auth bridges 2026-04-23 22:23:21 +01:00
Peter Steinberger
908335025f test: route browser changed tests to browser lane 2026-04-23 22:22:49 +01:00
Peter Steinberger
34c14843af perf: avoid browser text runtime import 2026-04-23 22:22:49 +01:00
Peter Steinberger
096d2688b7 test: fix openai image auth mock typing 2026-04-23 22:22:49 +01:00
aalekh-sarvam
d40dd9088e feat(memory): configurable local embedding contextSize (default 4096) (#70544)
node-llama-cpp defaults contextSize to "auto", which on large embedding
models like Qwen3-Embedding-8B (trained context 40,960) inflates gateway
VRAM from ~8.8 GB to ~32 GB and causes OOM on single-GPU hosts that share
the gateway with an LLM runtime.

Expose memorySearch.local.contextSize in openclaw.json (number | "auto"),
default to 4096 which comfortably covers typical memory-search chunks
(128–512 tokens) while keeping non-weight VRAM bounded.

Closes #69667.
2026-04-23 14:21:53 -07:00
Peter Steinberger
88b3fa14f0 test(openai): type image auth readiness mock 2026-04-23 22:19:13 +01:00
Peter Steinberger
5867207521 docs: balance skill descriptions 2026-04-23 22:18:56 +01:00
Peter Steinberger
2f14461976 test(openai): cover automatic image auth readiness 2026-04-23 22:14:55 +01:00
Peter Steinberger
c952379419 perf: split feishu lifecycle tests 2026-04-23 22:12:27 +01:00
Peter Steinberger
58bde71908 fix: collapse qmd startup memory log 2026-04-23 22:12:01 +01:00
Peter Steinberger
f3aaafbd70 ci: use latest stable install smoke baseline 2026-04-23 22:11:53 +01:00
Olabode Felix Akinyemi
b686f56b23 fix(ui): add aria-label to STT button and aria-expanded to pinned toggle (#70593)
- Voice input button had title= but no aria-label, so screen readers
  announced it without context. Add aria-label mirroring the title,
  toggling between "Voice input" and "Stop recording".
- Pinned messages toggle lacked aria-expanded, so screen readers could
  not announce the collapsed/expanded state of the section.

Co-authored-by: akinshaywai <akinshaywai@users.noreply.github.com>
2026-04-23 14:10:59 -07:00
cathywzeng
5a97c0d5fd fix(ui): add position: relative; z-index: 1 to .dreams-diary__daychips (#70705)
Fix synthesis tab button being clipped/hidden at certain viewport zoom levels.

Co-authored-by: cathz <14934105@qq.com>
2026-04-23 14:10:07 -07:00
Vincent Koc
d4f2edbe70 docs(changelog): note OpenAI capacity error copy 2026-04-23 14:07:01 -07:00
Peter Steinberger
ddcc39de91 fix(openai): reuse Codex OAuth for OpenAI images 2026-04-23 22:06:36 +01:00
Vincent Koc
f1ad5e27e0 fix(agents): surface OpenAI model capacity errors 2026-04-23 14:04:35 -07:00
openclaw-docs-agent[bot]
76276b876d docs: refresh documentation 2026-04-23 21:04:33 +00:00
EVA
137dbc71f0 feat: expose harness selection decisions (#70760)
Codex harness selection now keeps the decision helper internal, logs debug-only selection reasons and candidates, and documents `/status` as the primary user-facing signal.

Thanks @100yenadmin.

Co-authored-by: Eva <eva@100yen.org>
2026-04-23 21:57:09 +01:00
Peter Steinberger
235e17a08f docs: update config baseline 2026-04-23 21:55:36 +01:00
Peter Steinberger
10202f9279 fix(codex): approve bundled MCP loopback tools 2026-04-23 21:55:36 +01:00
Peter Steinberger
5314042990 fix(gateway): normalize MCP object schemas 2026-04-23 21:55:36 +01:00
Peter Steinberger
61c25704e6 fix: harden realtime voice setup (#70764) 2026-04-23 21:54:50 +01:00
Peter Steinberger
11e95a49d0 test: name contract vitest projects 2026-04-23 21:54:05 +01:00
Peter Steinberger
e1f5494636 ci: fix test performance agent run lookup 2026-04-23 21:52:31 +01:00
Devin Robison
873dce178d fix(gateway): block webchat session compaction mutations (#70716)
* fix(gateway): block webchat session compaction mutations

* docs(changelog): note webchat compaction guard (#70716)
2026-04-23 14:50:35 -06:00
Peter Steinberger
8af3d91668 docs(openai): clarify codex oauth image generation 2026-04-23 21:47:33 +01:00
Peter Steinberger
59cffb43f7 perf: avoid broad testing barrel in moonshot test 2026-04-23 21:44:17 +01:00
Peter Steinberger
d9aacbd3f9 ci: skip duplicate npm global install smoke 2026-04-23 21:43:06 +01:00
Peter Steinberger
a5ea24757c fix: enforce silent group replies after reactions 2026-04-23 21:42:17 +01:00
Peter Steinberger
e66a08658a perf: stub unused msteams handlers in invoke tests 2026-04-23 21:41:48 +01:00
Peter Steinberger
3fbe191ecc perf: narrow slack tool result test import 2026-04-23 21:38:30 +01:00
Peter Steinberger
c84a2f5244 feat(openai): add codex oauth image generation 2026-04-23 21:34:24 +01:00
Peter Steinberger
7ce36b4d12 ci: isolate non-root install smoke cache 2026-04-23 21:31:13 +01:00
Peter Steinberger
8b9e46a099 perf: slim mattermost helper imports 2026-04-23 21:29:35 +01:00
Peter Steinberger
f5042adf27 feat: add forked subagent context 2026-04-23 21:28:58 +01:00
Peter Steinberger
abedf9c1f4 fix(acpx): remove codex auth file fallback 2026-04-23 21:26:46 +01:00
Peter Steinberger
fc39f10130 docs(changelog): note removed Codex Spark model 2026-04-23 21:21:12 +01:00
Peter Steinberger
78fe353995 ci: harden install smoke npm cache cleanup 2026-04-23 21:19:20 +01:00
Vincent Koc
c5c163d078 docs: standardize frontmatter field order (summary before title) 2026-04-23 13:18:17 -07:00
Peter Steinberger
79112f207d ci: keep test performance agent focused on failures 2026-04-23 21:18:02 +01:00
Peter Steinberger
bb63f3c26b docs: document embedded harness status indicator 2026-04-23 21:17:20 +01:00
Peter Steinberger
1ea02db8a3 perf: skip browser routes in auth tests 2026-04-23 21:17:15 +01:00
Vincent Koc
82a847f3b4 docs(providers): standardize Related card titles, config-reference links, and Advanced heading 2026-04-23 13:16:53 -07:00
Peter Steinberger
f6336c5521 fix(openai): retire removed Codex Spark model 2026-04-23 21:16:46 +01:00
Vincent Koc
2777b089b5 docs: normalize frontmatter titles to sentence case 2026-04-23 13:15:17 -07:00
Peter Steinberger
831d6c3bbe docs: fix msteams federated auth link 2026-04-23 21:12:00 +01:00
Vincent Koc
4a2cd533ac docs: remove duplicate H1 where frontmatter title already sets it 2026-04-23 13:11:14 -07:00
Vincent Koc
219a11d2bd docs: fix googlechat entity and dedup gateway multiple-gateways section 2026-04-23 13:08:13 -07:00
Vincent Koc
0905e5f7b6 docs(channels): msteams - drop duplicate minimal-setup block, cardify related, accordion env vars, remove H1 and dante quote 2026-04-23 13:07:23 -07:00
Peter Steinberger
8407c60824 perf: slim browser tab tests 2026-04-23 21:07:11 +01:00
Vincent Koc
ea25d7ed5b fix(qr): replace qrcode-terminal with qrcode-tui
Replace legacy qrcode-terminal usage with shared qrcode-tui media helpers, bound QR PNG rendering options, and raise bundled plugin host floors for the new SDK runtime surface.
2026-04-23 13:06:14 -07:00
Peter Steinberger
6f74763f1d perf: slim msteams store imports 2026-04-23 21:04:40 +01:00
Peter Steinberger
058e6f588a fix(openai): align Codex fallback with GPT-5.5 2026-04-23 21:03:26 +01:00
Peter Steinberger
956350bb9c ci: share npm cache in install smoke 2026-04-23 20:57:31 +01:00
Vincent Koc
f02fcba21f fix(test): throttle local vitest under memory pressure 2026-04-23 12:56:28 -07:00
Peter Steinberger
629ed9f702 ci: run test performance agent on hosted ubuntu 2026-04-23 20:51:40 +01:00
Peter Steinberger
648422a6c1 fix(openai): send image edits as multipart uploads (#70657) 2026-04-23 20:48:55 +01:00
Peter Steinberger
ff56a9d41b test(openai): prefer canonical GPT refs 2026-04-23 20:47:39 +01:00
Peter Steinberger
384eb6bc66 feat(openai): use canonical GPT refs for Codex OAuth 2026-04-23 20:47:38 +01:00
Peter Steinberger
a8173276bf docs(openai): canonicalize GPT model refs 2026-04-23 20:47:38 +01:00
Peter Steinberger
17830983ce perf: slim feishu debounce test imports 2026-04-23 20:46:27 +01:00
Peter Steinberger
6471e0cdce ci: isolate manual install smoke runs 2026-04-23 20:44:11 +01:00
Peter Steinberger
010b13e6e9 test: update lint suppression allowlist 2026-04-23 20:43:42 +01:00
Peter Steinberger
6586cfa6f5 perf: avoid heavy slack provider chunk import 2026-04-23 20:42:24 +01:00
Peter Steinberger
360cb3dbf1 ci: add test performance agent 2026-04-23 20:40:52 +01:00
Peter Steinberger
6fc8913223 refactor(auto-reply): extract effective reply route resolution 2026-04-23 20:40:27 +01:00
Peter Steinberger
72b0e3d033 ci: run install smoke on manual dispatch 2026-04-23 20:40:14 +01:00
Vincent Koc
5930292524 fix(format): cap oxfmt threads 2026-04-23 12:36:46 -07:00
Peter Steinberger
fd581b849d perf: slim slack provider helper tests 2026-04-23 20:36:05 +01:00
Vincent Koc
f40f8a60cc fix(agents): harden cli runner hook followups (#70747)
* fix(agents): harden cli runner hook followups

* fix(agents): harden cli runner hook followups

* fix(agents): harden cli runner hook followups

* fix(agents): harden cli runner hook followups

* fix(agents): harden cli runner hook followups

* fix(agents): harden cli runner hook followups
2026-04-23 12:32:30 -07:00
Peter Steinberger
e93b3f60fa fix: harden openclaw peer dependency installs (#70462) 2026-04-23 20:28:02 +01:00
Anish Kataria
44820f859e fix(plugin-sdk): scan dependency tree before materialising openclaw symlink
The dependency-tree security scan rejects node_modules symlinks whose
targets resolve outside the install root. Our trusted host-to-plugin
symlink violates that rule by design, so running the scan AFTER
linkOpenClawPeerDependencies would fail every install with
SECURITY_SCAN_FAILED.

Reorder afterInstall so the scan runs first (walking only the plugin's
own staged source, catching any pre-existing malicious openclaw-named
symlink a source might smuggle in), then the trusted link is
materialised on the now-safe tree.

Also use braces on guard clauses in the new unit tests to satisfy the
oxlint no-unreachable-single-statement-if rule.
2026-04-23 20:28:02 +01:00
Anish Kataria
56dd249a07 test(plugin-sdk): add unit tests for linkOpenClawPeerDependencies
Tests three cases via installPluginFromDir:
- symlink created when peerDependencies declares openclaw
- no symlink when peer list is empty
- idempotent re-install replaces existing symlink
- warns and skips when host root cannot be resolved

Also removes the single-element Set in favour of a direct name
comparison (peerName === "openclaw"), and adds Closes #54428 to
address the same root cause in the weixin connector.

Closes #54428
2026-04-23 20:28:02 +01:00
anish k
2e9c1faef6 fix(plugin-sdk): symlink openclaw peerDependencies after plugin install
## Summary

Signed-off-by: anish k <ak8686@princeton.edu>
2026-04-23 20:28:02 +01:00
Peter Steinberger
2b45bc1fd3 fix(auto-reply): restore exec-event route replies (#70258) 2026-04-23 20:27:39 +01:00
Peter Steinberger
ce933f3bbc fix(auto-reply): honor recovered system-event reply routes 2026-04-23 20:27:39 +01:00
wzfukui
87a08dd4c2 fix(auto-reply): route exec-event replies via persisted delivery context 2026-04-23 20:27:39 +01:00
Peter Steinberger
aad31817ef ci: add bun global install smoke 2026-04-23 20:27:04 +01:00
Vincent Koc
6896692111 docs(sidebar): sort tools group alphabetically 2026-04-23 12:25:25 -07:00
Vincent Koc
ba890a4578 docs(channels): telegram - collapse prose field list into accordion summary, cardify related, remove H1 2026-04-23 12:22:02 -07:00
Vincent Koc
c43a447b38 docs(channels): slack - collapse duplicate HTTP slash-commands JSON, cardify related, accordion config pointers, remove H1 2026-04-23 12:20:25 -07:00
Peter Steinberger
89051c6bf6 docs(openai): document GPT-5.5 defaults 2026-04-23 20:19:15 +01:00
Peter Steinberger
cd5bc2fc93 test(openai): cover GPT-5.5 defaults 2026-04-23 20:19:15 +01:00
Peter Steinberger
a36903b94c feat(openai): default to GPT-5.5 2026-04-23 20:19:15 +01:00
Peter Steinberger
54731492a2 fix(gateway): persist webchat images as managed media (#70719)
* fix(gateway): persist webchat images as managed media

* fix(ui): keep managed image auth same-origin

* docs: note managed webchat image fix
2026-04-23 20:17:41 +01:00
Peter Steinberger
f2f475e869 perf: run ui node tests without jsdom 2026-04-23 20:17:37 +01:00
Peter Steinberger
b957493ef7 docs: update changelog for plugin setup fix (#70718) 2026-04-23 20:17:21 +01:00
Devin Robison
4c09f4a812 test(plugins): place shadow setup-api where the old cwd-fallback would actually resolve it 2026-04-23 20:17:21 +01:00
Devin Robison
993781e6e6 fix(plugins): ignore cwd setup-api fallback 2026-04-23 20:17:21 +01:00
Vincent Koc
15ff8619d1 fix(qa-channel): reject non-http attachment urls 2026-04-23 12:15:22 -07:00
Peter Steinberger
44144cbd06 fix: use module path for bundled jiti loads (#70073) (thanks @yidianyiko) 2026-04-23 20:13:13 +01:00
YDYK
61e9e86d69 fix(plugins): use module path for bundled jiti loads 2026-04-23 20:13:13 +01:00
Peter Steinberger
1d980cca6f perf: trim cli prepare hook tests 2026-04-23 20:07:35 +01:00
Vincent Koc
e1840b8581 fix(msteams): bind global audience tokens to app id 2026-04-23 12:05:35 -07:00
Vincent Koc
7d30894c4a fix(anthropic): stop forcing claude permission bypass 2026-04-23 12:03:00 -07:00
Peter Steinberger
8a4761fe95 test: align approval and pairing expectations 2026-04-23 20:01:57 +01:00
Vincent Koc
b122a325cd fix(android): require loopback cleartext gateways 2026-04-23 11:59:17 -07:00
Peter Steinberger
efd5eb231a perf: trim feishu extension tests 2026-04-23 19:57:08 +01:00
Vincent Koc
cad102c3ca fix(android): require private IP cleartext pairing 2026-04-23 11:56:47 -07:00
Deepak Jain
a63939d295 fix(logging): tolerate malformed subsystem labels (#70502) (#70535)
* fix(logging): tolerate malformed subsystem labels

Guard console subsystem filtering and probe suppression against malformed subsystem labels, and normalize bad subsystem names to a stable fallback during console emission.

Fixes #70502

* test(plugins): ignore extension test-support helpers in seam guardrail

Exclude extension files named *.test-support.ts from the plugin sdk seam guardrail so test-only helpers do not trip public seam enforcement on unrelated PRs.
2026-04-23 11:51:54 -07:00
Vincent Koc
b201589ae1 fix(discord): require explicit native approval enablement 2026-04-23 11:51:17 -07:00
Vincent Koc
527d7211e0 fix(approvals): require explicit chat exec enablement 2026-04-23 11:51:17 -07:00
Tak Hoffman
7651a03424 Add packed CLI smoke checks for release packaging (#70685)
* Add packed CLI smoke release checks

* Address PR review feedback

* Harden packed CLI smoke checks

* Tighten release verifier parsing

* Scan root dist module files in release verifier
2026-04-23 13:50:15 -05:00
Peter Steinberger
c151956782 refactor(discord): simplify native command auth selection 2026-04-23 19:50:12 +01:00
Peter Steinberger
1f06073fe8 perf: trim slack extension test setup 2026-04-23 19:45:53 +01:00
Peter Steinberger
bfcae63373 fix: harden Discord native command auth (#70711) (thanks @vincentkoc) 2026-04-23 19:44:12 +01:00
Peter Steinberger
6590bc9037 fix: harden image generation directive output (#70710)
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-04-23 19:44:06 +01:00
Peter Steinberger
e2f2deae78 fix: fail fast on silent changed-test hangs 2026-04-23 19:40:25 +01:00
Peter Steinberger
e9405318b4 fix(openai): default realtime voice to gpt-realtime-1.5 2026-04-23 19:39:24 +01:00
Peter Steinberger
42d1ff8433 perf: narrow grouped render test imports 2026-04-23 19:36:32 +01:00
Peter Steinberger
c96da8ea18 docs: update PR closure instructions 2026-04-23 19:35:08 +01:00
Vincent Koc
a32fe807f4 fix(discord): block channel policy auth bypass 2026-04-23 11:34:44 -07:00
Andrey Gerasimov
9cae47a956 fix: preserve Kimi tool call ids (#70693) (#70693)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: geri4 <2748115+geri4@users.noreply.github.com>
2026-04-23 19:34:09 +01:00
Vincent Koc
f7537faa21 fix(agents): emit cli runner llm lifecycle hooks (#70731) 2026-04-23 11:33:27 -07:00
zhang-guiping
c1f423f845 fix(secrets): harden Windows ACL fallback and strip BOM (#70662)
Fail closed when Windows ACL checks cannot be verified for file and exec secret providers unless the provider explicitly opts into allowInsecurePath. Strip UTF-8 BOMs from file-backed secrets and document the trusted-path override.\n\nThanks @zhanggpcsu.
2026-04-23 19:32:15 +01:00
Peter Steinberger
884d7929d1 docs: format testing accordion notes 2026-04-23 19:28:24 +01:00
Peter Steinberger
e03b9647ad perf: split acp client test helpers 2026-04-23 19:26:30 +01:00
Vincent Koc
5b3e73e099 fix(android): disable auto-send for ASK_OPENCLAW 2026-04-23 11:26:10 -07:00
Peter Steinberger
fd1d6b0241 ci: serialize extension shard batches 2026-04-23 19:25:14 +01:00
Peter Steinberger
f9da326c88 fix: repair generated docs accordion indentation 2026-04-23 19:20:35 +01:00
Vincent Koc
314041a885 docs(channels): discord - drop duplicate developer-portal block, cardify related, accordion config pointers, remove H1 2026-04-23 11:19:28 -07:00
Peter Steinberger
36c89ecaf6 ci: cap extension shard vitest workers 2026-04-23 19:14:15 +01:00
Peter Steinberger
95448d27ae fix: narrow Mintlify accordion guard 2026-04-23 19:14:12 +01:00
Vincent Koc
e4534efe8e docs(help): testing - drop redundant H1, progressive-disclose unit/integration maintainer notes into AccordionGroup 2026-04-23 11:13:14 -07:00
Chinar Amrutkar
8513a14406 fix: queue chat aborts across reconnect (#70673) (thanks @chinar-amrutkar) 2026-04-23 19:12:39 +01:00
Vincent Koc
b0efa8d43d docs(gateway): security — sentence-case headings, remove manual TOC and H1, drop custom anchors, tuck triage notes into Accordion 2026-04-23 11:09:33 -07:00
Peter Steinberger
a89d4ab979 test: stabilize acp bind live probe 2026-04-23 19:07:10 +01:00
Peter Steinberger
3e2bc28e51 fix: forward chat images to acp dispatch 2026-04-23 19:06:19 +01:00
Peter Steinberger
32a38f125e fix: keep codex cli images in workspace 2026-04-23 19:06:19 +01:00
Peter Steinberger
feecc53b6b test: stabilize codex harness probes 2026-04-23 19:06:19 +01:00
Peter Steinberger
802646e004 fix: catch Mintlify accordion parse hazards 2026-04-23 19:04:35 +01:00
Peter Steinberger
43c5650475 perf: avoid eager trajectory session manager import 2026-04-23 19:00:35 +01:00
Peter Steinberger
cbc88fb92d test: trim system run runtime duplicate 2026-04-23 18:55:19 +01:00
Peter Steinberger
75df14cbbc test: mark video capability mirror intentional 2026-04-23 18:54:33 +01:00
Peter Steinberger
ccbc3bc3ff test: share export command session mocks 2026-04-23 18:54:33 +01:00
Peter Steinberger
c7408f1cf2 test: trim system run handler coverage 2026-04-23 18:53:53 +01:00
Peter Steinberger
bcde76a898 docs: add efficient gh triage guide 2026-04-23 18:53:31 +01:00
Peter Steinberger
7a9df89d26 test: trim skill scanner branch coverage 2026-04-23 18:51:20 +01:00
Peter Steinberger
393a71991f fix: decouple approval startup from replay 2026-04-23 18:49:57 +01:00
Peter Steinberger
62a0cd8acd test: slim status fast-mode label coverage 2026-04-23 18:49:25 +01:00
Peter Steinberger
310b1eea4a test: stabilize full-suite flakes 2026-04-23 18:48:07 +01:00
Peter Steinberger
d0303e2a97 test: reuse CLI runtime mock in daemon tests 2026-04-23 18:46:43 +01:00
Peter Steinberger
42c6e2d031 test: reuse CLI runtime mock in gateway tests 2026-04-23 18:46:43 +01:00
Peter Steinberger
140a8cf5fb test: share CLI runtime mock helper 2026-04-23 18:46:43 +01:00
Peter Steinberger
bd2553e126 test: share gateway live env helpers 2026-04-23 18:46:43 +01:00
Peter Steinberger
9d8690d6b3 test: share temp plugin extension fixtures 2026-04-23 18:46:42 +01:00
Peter Steinberger
fd3bb6f084 test: reuse channel plugin fixture 2026-04-23 18:46:42 +01:00
Peter Steinberger
961ab165ad test: dedupe coding tool session store fixtures 2026-04-23 18:46:42 +01:00
Peter Steinberger
ce681be084 test: dedupe subagent announcement fixtures 2026-04-23 18:46:42 +01:00
Peter Steinberger
844f1dd87a test: dedupe session lock symlink fixtures 2026-04-23 18:46:42 +01:00
Peter Steinberger
359a656fdf test: dedupe Anthropic cache policy fixtures 2026-04-23 18:46:42 +01:00
Vincent Koc
9694a4501f fix(qqbot): require auth for bot-approve 2026-04-23 10:45:30 -07:00
Peter Steinberger
604ce85ce0 test: use lightweight install version fixture 2026-04-23 18:45:06 +01:00
Peter Steinberger
7c974ca1af perf: reduce installer version parsing overhead 2026-04-23 18:44:26 +01:00
Andrej Trogrlić
23c90aeed4 fix(feishu): keep setup entry off runtime SDK (#70339)
Load Feishu setup surfaces through a setup-only barrel so onboarding does not import the Lark SDK before bundled runtime deps are staged.\n\nThanks @andrejtr.\n\nCo-authored-by: andrejtr <64274971+andrejtr@users.noreply.github.com>
2026-04-23 18:42:06 +01:00
Peter Steinberger
184c4e3788 ci: add duplicate PR cleanup workflow 2026-04-23 18:41:32 +01:00
Vincent Koc
12de62bfd8 docs(plugins): architecture — sentence-case title, CardGroup intro, dedup provider-hook prose list, progressive-disclose bundled-provider examples 2026-04-23 10:39:57 -07:00
Peter Steinberger
bff9f10ea6 test: remove canvas reload sleep 2026-04-23 18:37:29 +01:00
Tak Hoffman
d39e34d31f fix(gateway): disarm wrapper timeout before teardown (#70704) 2026-04-23 12:36:30 -05:00
Peter Steinberger
5c229e32b7 test: remove websocket polling waits 2026-04-23 18:30:30 +01:00
Peter Steinberger
09331543db test: dedupe gateway hook session key cases 2026-04-23 18:29:32 +01:00
Peter Steinberger
4e97b57c17 refactor: share interactive payload normalizers 2026-04-23 18:29:32 +01:00
Peter Steinberger
61ab68f5c9 refactor: share MCP tools stdio server 2026-04-23 18:29:32 +01:00
Peter Steinberger
73e247321b test: share channel audit plugin fixtures 2026-04-23 18:29:32 +01:00
Peter Steinberger
9ee800e81d test: share security audit temp fixtures 2026-04-23 18:29:32 +01:00
Peter Steinberger
4acae5b281 test: dedupe skill scanner stat mocks 2026-04-23 18:29:32 +01:00
Peter Steinberger
fc3aa07fbc test: dedupe CLI attempt setup 2026-04-23 18:29:32 +01:00
Peter Steinberger
060467ef83 test: dedupe OpenAI stream wrapper assertions 2026-04-23 18:29:32 +01:00
Peter Steinberger
50acb50fb5 test: dedupe reply media fixtures 2026-04-23 18:29:32 +01:00
Peter Steinberger
1630607463 test: dedupe cron and channel fixtures 2026-04-23 18:29:32 +01:00
Peter Steinberger
0397cad89b test: normalize safe-bin docs parity indentation 2026-04-23 18:27:56 +01:00
Peter Steinberger
b3d32a995d docs: align safe-bin denied flag list 2026-04-23 18:27:56 +01:00
Vincent Koc
8f3b99c512 fix(mcp): block owner-only tools in ACPX bridge 2026-04-23 10:24:36 -07:00
Peter Steinberger
91a165c6af test: align group prompt invariant 2026-04-23 18:21:05 +01:00
Peter Steinberger
5ebef46183 perf: speed up hot test paths 2026-04-23 18:17:09 +01:00
Vincent Koc
27d6b8db5b docs(plugins): sdk-overview — sentence-case title, tighten intro into Warning, Related as CardGroup, progressive-disclose embedded-factory note 2026-04-23 10:15:58 -07:00
Peter Steinberger
e0f5961e28 fix: harden group chat prompt metadata 2026-04-23 18:15:49 +01:00
ZC
6415e35f55 fix(ui): include cached tokens in context usage (#70532)
Fixes #70491.

Includes cached prompt tokens in the Control UI context percent and keeps output tokens out of the percentage.

Thanks @chen-zhang-cs-code.
2026-04-23 18:13:31 +01:00
Vincent Koc
4792a50710 docs(tools): exec-approvals — sentence-case title, restructure intro, dedup Related, progressive-disclose safe-bins nuances 2026-04-23 10:09:25 -07:00
Peter Steinberger
23b751b112 test: dedupe command fixtures 2026-04-23 18:09:20 +01:00
Peter Steinberger
7a8d304a65 refactor: share core helper logic 2026-04-23 18:09:20 +01:00
Peter Steinberger
2045c0977e refactor: dedupe tooling helpers 2026-04-23 18:09:20 +01:00
Peter Steinberger
f98f93c29a test: cover non-command pairing auth 2026-04-23 18:06:05 +01:00
Peter Steinberger
eb937089d5 docs: update security triage discussion flow 2026-04-23 18:06:05 +01:00
Vincent Koc
1f5df4fbfd docs(gateway): protocol — sentence-case title, collapse RPC method families into AccordionGroup 2026-04-23 10:04:37 -07:00
Tak Hoffman
77a1cbd5ff fix(cli): wait for gateway client teardown before exit (#70691)
Verified:
- pnpm test src/gateway/call.test.ts

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-04-23 12:03:37 -05:00
Peter Steinberger
fb47c1d6bf fix: harden WhatsApp structured object prompts 2026-04-23 18:03:16 +01:00
Peter Steinberger
3ae15cd746 test: cover codex transport fallback path 2026-04-23 17:58:19 +01:00
Sk7n4k3d
f4891b083d fix(agents/failover): classify undici terminated and codex Request failed as timeout (#69368) 2026-04-23 17:58:19 +01:00
Peter Steinberger
79d8ce730a docs: fix OpenAI provider compaction reference 2026-04-23 17:53:36 +01:00
Vincent Koc
c7d1f532a2 docs(plugins): manifest — sentence-case title, compress What-this-file-does, prune trailing Notes duplication, CardGroup Related 2026-04-23 09:50:17 -07:00
Vincent Koc
b3ca4e088e docs(providers): openai — drop stray anchor tag, consolidate trailing azure notes 2026-04-23 09:48:48 -07:00
Peter Steinberger
8997df5c45 ci: increase checkout retry budget 2026-04-23 17:48:21 +01:00
Peter Steinberger
0da17e4f74 ci: retry docs publish clone failures 2026-04-23 17:44:41 +01:00
Vincent Koc
94ff5a93c0 docs(plugins): fix broken provider-hook table, tabulate family bundled examples, progressive-disclose extra capabilities 2026-04-23 09:41:43 -07:00
Peter Steinberger
884c117785 ci: harden docs agent fetch retries 2026-04-23 17:31:32 +01:00
Peter Steinberger
a10c495f29 ci: retry docs publish fetch failures 2026-04-23 17:26:31 +01:00
Vincent Koc
ed52e2ec91 docs(concepts): compress model-providers reference — move SDK hook list to provider plugins doc, tabulate bundled providers 2026-04-23 09:20:59 -07:00
Peter Steinberger
382c87c5f2 fix: preserve Gemini compat tool signatures 2026-04-23 17:17:07 +01:00
Vincent Koc
167eee19af docs(tools): trim ACP agents reference, merge quick-start flows, accordion smoke test, dedupe command cookbook 2026-04-23 09:13:38 -07:00
Peter Steinberger
32de558f47 docs(changelog): align 2026.4.22 and unreleased notes 2026-04-23 16:58:59 +01:00
Peter Steinberger
d913fd57a2 test: skip remaining stale live probe routes 2026-04-23 16:58:36 +01:00
Peter Steinberger
bc6cefd2ac fix: repair 2026.4.22 appcast list item 2026-04-23 16:56:58 +01:00
Peter Steinberger
b75a80f6d1 chore(release): prepare 2026.4.23 2026-04-23 16:56:44 +01:00
Peter Steinberger
47f131f6ae test(gateway): harden live docker harness probes 2026-04-23 16:56:44 +01:00
Peter Steinberger
af03832134 test(docker): make e2e temp logs portable 2026-04-23 16:56:44 +01:00
Peter Steinberger
e204a31831 fix(discord): keep subagent hooks lazy in channel entry 2026-04-23 16:56:44 +01:00
Peter Steinberger
4df0d55f06 fix: skip stale opencode live file probes 2026-04-23 16:55:36 +01:00
Peter Steinberger
1713839288 fix: pin embedded harness selection per session 2026-04-23 16:53:32 +01:00
Peter Steinberger
7248a7749f docs(release): clarify mac source variation policy 2026-04-23 16:51:06 +01:00
Peter Steinberger
baab065f05 test(qa): isolate matrix stale sync replay 2026-04-23 16:49:53 +01:00
Peter Steinberger
248b1b420a ci(qa): trust release branch heads 2026-04-23 16:49:53 +01:00
Peter Steinberger
f96a8f6e4f docs(release): document mac source ref fallback 2026-04-23 16:49:53 +01:00
Peter Steinberger
eecd029f17 fix(macos): derive correction sparkle build 2026-04-23 16:49:53 +01:00
Peter Steinberger
9fe74e391d fix(macos): sign mlx tts helper before app binary 2026-04-23 16:49:53 +01:00
Peter Steinberger
bdb6aebff4 docs(release): document npm dist-tag fallback auth 2026-04-23 16:49:53 +01:00
Peter Steinberger
edb466ee16 docs(release): document light stable promotion testing 2026-04-23 16:49:53 +01:00
Peter Steinberger
64fc449591 ci(release): use github runner for npm release gate 2026-04-23 16:49:53 +01:00
Peter Steinberger
599dd383e6 docs(release): decouple npm publish from mac release 2026-04-23 16:49:53 +01:00
Peter Steinberger
2be2b24b37 docs(release): require full GitHub release notes 2026-04-23 16:49:53 +01:00
Peter Steinberger
53cc5085c7 docs: refine release tweet guidance 2026-04-23 16:49:43 +01:00
Vincent Koc
ecefe1c39c fix(scripts): reap child check processes 2026-04-23 08:44:58 -07:00
Peter Steinberger
5071c58346 ci: run live model matrix on github runners 2026-04-23 16:44:11 +01:00
Vincent Koc
f58e0176ca docs(start): rewrite showcase with standard Mintlify components, sentence case, and trimmed hero noise 2026-04-23 08:44:04 -07:00
Peter Steinberger
deb1364dfb refactor: centralize root memory file policy 2026-04-23 16:40:41 +01:00
Peter Steinberger
14808371a6 test: improve macos parallels update smoke 2026-04-23 16:35:39 +01:00
Vincent Koc
f1662bff92 docs(tools): restructure browser reference with tabs/accordions and trim redundant prose 2026-04-23 08:34:16 -07:00
Peter Steinberger
c5ab0963c9 fix: tolerate post-update json in install smoke 2026-04-23 16:33:41 +01:00
Peter Steinberger
226e116de6 docs: expand Tencent Hy3 provider guide 2026-04-23 16:28:03 +01:00
Peter Steinberger
d8c724c60f test: skip flaky live probe routes 2026-04-23 16:25:10 +01:00
Peter Steinberger
4064c9b75c docs: add gateway diagnostics guide 2026-04-23 16:21:23 +01:00
Peter Steinberger
6c090c5150 chore(release): update appcast for 2026.4.22 2026-04-23 16:20:20 +01:00
Vincent Koc
fda09c4806 docs(plugins): trim skill-workshop headings and collapse example variants; tighten codex-harness guardian explainer 2026-04-23 08:16:26 -07:00
Mariano
10a9acbf29 fix: keep root memory uppercase (#70621)
Thanks @mbelinky.
2026-04-23 16:10:36 +01:00
Peter Steinberger
645294510c fix: restore bundled plugin SDK alias 2026-04-23 16:10:23 +01:00
Peter Steinberger
0fd0a69399 test: skip additional stale live probe routes 2026-04-23 16:10:04 +01:00
Vincent Koc
b7cc9d2d28 docs: msteams restructure - Azure Bot Steps, sentence-case headings, grouped config 2026-04-23 08:02:24 -07:00
Peter Steinberger
7b6b7d53fc build: update tsgo native preview 2026-04-23 15:59:49 +01:00
Vincent Koc
da3e9ded19 docs: collapse Slack manifest duplication and trim noise bullets 2026-04-23 07:57:04 -07:00
Peter Steinberger
be87068f02 test: skip stale live probe routes 2026-04-23 15:54:38 +01:00
Vincent Koc
99e8ede76c docs: extract Matrix push rules runbook, table verify CLI, merge E2EE H3s 2026-04-23 07:51:42 -07:00
Peter Steinberger
e460afd654 docs: add GitHub API polling guidance 2026-04-23 15:51:22 +01:00
Peter Steinberger
5feedbf4b6 fix: honor explicit CI timing run id 2026-04-23 15:43:50 +01:00
Peter Steinberger
3fa089de19 ci: validate docs mdx before publish 2026-04-23 15:41:47 +01:00
Peter Steinberger
dbd7966cfd ci: remove runner caps after timing review 2026-04-23 15:41:32 +01:00
Mariano
3e956a4982 fix: align claude-cli prompt hooks (#70625)
Merged via squash.

Prepared head SHA: 3de89da38f
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-04-23 16:34:16 +02:00
Peter Steinberger
74bb617889 ci: reduce live model runner size 2026-04-23 15:31:13 +01:00
Peter Steinberger
8435cb80ac test: stop macOS VM after Discord smoke 2026-04-23 15:29:34 +01:00
Peter Steinberger
b2bbe61571 ci: trigger runner fanout measurement 2026-04-23 15:28:00 +01:00
Peter Steinberger
1e1aaa51e1 test: harden live model extra probes 2026-04-23 15:27:50 +01:00
Peter Steinberger
6532ee0c39 ci: reduce node runner fanout 2026-04-23 15:25:28 +01:00
Peter Steinberger
b4d1992338 test: accept current web search reasoning floor 2026-04-23 15:11:32 +01:00
Peter Steinberger
3e834f2f83 perf(test): skip sandbox prune in context smoke 2026-04-23 15:09:49 +01:00
Peter Steinberger
e050e18945 test: add live model file and image probes 2026-04-23 15:09:43 +01:00
Peter Steinberger
4a4e56e8f3 perf(test): lazy load sandbox context helpers 2026-04-23 15:07:00 +01:00
Peter Steinberger
63a88ff1df perf(test): slim exec preflight imports 2026-04-23 15:04:20 +01:00
Pengfei Ni
be4920f9bc fix(anthropic-vertex): resolve model discovery and auth for GCP ADC (openclaw#65716)
Verified:
- pnpm test extensions/anthropic-vertex/index.test.ts extensions/anthropic-vertex/region.adc.test.ts src/plugins/manifest-registry.test.ts src/plugins/provider-runtime.synthetic-auth-discovery.test.ts

Co-authored-by: feiskyer <676637+feiskyer@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-04-23 09:03:16 -05:00
Peter Steinberger
5743d7c8f5 perf(test): narrow subagent spawn limit tests 2026-04-23 15:01:24 +01:00
Peter Steinberger
0839617711 perf(test): drop obsolete docker fs bridge smoke 2026-04-23 14:58:08 +01:00
Peter Steinberger
c1ba7f718b perf(test): remove docker from fs bridge smoke 2026-04-23 14:57:40 +01:00
Peter Steinberger
4dcd6b8dc4 perf(test): slim gateway live connect smoke 2026-04-23 14:45:06 +01:00
Peter Steinberger
7dd37bda4f perf(test): trim hot gateway and infra tests 2026-04-23 14:33:37 +01:00
Peter Steinberger
1bbca1d910 ci: run full docker checks daily 2026-04-23 14:32:30 +01:00
Peter Steinberger
be81fa4424 test: stabilize live docker probes 2026-04-23 14:31:18 +01:00
Peter Steinberger
e98331b0be test: parallelize docker aggregate 2026-04-23 14:31:18 +01:00
Peter Steinberger
d3dc890821 fix: allow installed plugins through allowlist 2026-04-23 14:31:18 +01:00
Sliverp
e6d1ce943c fix:update wecom blurb (#70614) 2026-04-23 21:18:14 +08:00
openclaw-docs-agent[bot]
70d41130ff docs: refresh documentation 2026-04-23 13:08:56 +00:00
Tak Hoffman
87eee6e640 fix(thinking): default implicit reasoning models to medium (#70601)
* fix(thinking): default implicit reasoning models to medium

* fix(thinking): preserve reasoning metadata during default resolution
2026-04-23 07:55:47 -05:00
Otto Deng
bc01cbb8a2 docs(providers/openai): document Azure OpenAI endpoint usage for image generation (#70501)
Verified:
- pnpm lint:docs
- Resolved bot review comments around Azure docs scope and accuracy
2026-04-23 07:48:54 -05:00
openclaw-docs-agent[bot]
0372f4d540 docs: refresh documentation 2026-04-23 12:39:50 +00:00
Tak Hoffman
03477ccb82 fix: Add runner label to /status (#70595)
* Add runner label to status output

* Add changelog entry for status runner label

* Fix status runner detection and sanitization
2026-04-23 07:30:09 -05:00
Peter Steinberger
d330ad65e5 test(line): trim outbound payload coverage 2026-04-23 13:16:41 +01:00
Peter Steinberger
2e0e0654ce test(extensions): trim hot extension imports 2026-04-23 13:06:19 +01:00
Peter Steinberger
547b0c201d test(config): avoid ignored baseline artifact 2026-04-23 12:56:23 +01:00
Peter Steinberger
c5b7810563 test(config): read generated talk baseline 2026-04-23 12:52:13 +01:00
Peter Steinberger
09a118c57e test(config): avoid module resets in pruning tests 2026-04-23 12:46:41 +01:00
Peter Steinberger
5c9233c64e ci: shorten gateway watch readiness wait 2026-04-23 12:39:51 +01:00
zhang-guiping
62262d493b fix #70487: OpenAI image generation provider does not support Azure OpenAI endpoints (openclaw#70570)
Verified:
- pnpm install --frozen-lockfile
- pnpm check:changed
- pnpm test extensions/openai/image-generation-provider.test.ts

Co-authored-by: zhang-guiping <275915537+zhanggpcsu@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-04-23 06:36:57 -05:00
Peter Steinberger
818d903caa test: align build artifact profile expectation 2026-04-23 12:32:56 +01:00
Peter Steinberger
57ce4fb402 ci: keep sdk export check with build artifacts 2026-04-23 12:28:16 +01:00
Peter Steinberger
bd8fc86cf3 ci: skip duplicate strict smoke build 2026-04-23 12:24:21 +01:00
Peter Steinberger
b3ebbe5ba0 test(slack): narrow event runtime mocks 2026-04-23 11:50:48 +01:00
Peter Steinberger
aa95428265 test(msteams): mock oauth token network guard 2026-04-23 11:44:24 +01:00
Peter Steinberger
477a77284a test(mattermost): drop duplicate api smoke 2026-04-23 11:38:51 +01:00
Peter Steinberger
7b5b21c0e1 test(agents): avoid auth cache module resets 2026-04-23 11:33:56 +01:00
Peter Steinberger
1412ee8a85 test(hooks): remove duplicate loader cases 2026-04-23 11:31:47 +01:00
Peter Steinberger
39a907d7f4 test(hooks): drop unobservable loader smoke 2026-04-23 11:30:15 +01:00
Peter Steinberger
158a0d4ab4 test: trim duplicate runtime smoke work 2026-04-23 11:28:26 +01:00
Peter Steinberger
0da53b54a0 test(browser): drop flaky duplicate cdp health case 2026-04-23 11:20:02 +01:00
Peter Steinberger
8084bbf8ed ci: save pnpm store cache explicitly 2026-04-23 11:09:37 +01:00
Peter Steinberger
9191fbe2b5 perf(test): reuse plugin validation fixtures 2026-04-23 11:04:07 +01:00
Sliverp
d634380304 fix (#70562) 2026-04-23 17:58:16 +08:00
Peter Steinberger
a11bb792e4 perf(test): use gateway harness for cli connect smoke 2026-04-23 10:54:13 +01:00
Peter Steinberger
a8d337b360 perf(test): remove gateway method wait debt 2026-04-23 10:37:42 +01:00
Peter Steinberger
007fb0458e perf(test): speed up secrets and mattermost lanes 2026-04-23 10:27:28 +01:00
Peter Steinberger
d1ff0caecb test(telegram): reduce reply runtime imports 2026-04-23 10:20:53 +01:00
Peter Steinberger
0a7668595c test(telegram): reset forum metadata cache 2026-04-23 10:11:12 +01:00
Peter Steinberger
e880eab486 test(tui): narrow embedded backend mocks 2026-04-23 10:05:32 +01:00
Ayaan Zaidi
57f28285be fix: place telegram rtt changelog entry (#70550) 2026-04-23 14:33:17 +05:30
Ayaan Zaidi
ed4c3cb484 fix: finalize telegram rtt changelog (#70550) 2026-04-23 14:33:17 +05:30
Ayaan Zaidi
8a078acaa6 perf(telegram): bound forum metadata cache 2026-04-23 14:33:17 +05:30
Ayaan Zaidi
1bd8c5f362 fix(qa): timestamp telegram update batches 2026-04-23 14:33:17 +05:30
Ayaan Zaidi
50e6c0a3b2 perf(telegram): cache forum metadata lookup 2026-04-23 14:33:17 +05:30
Ayaan Zaidi
c22a21759b test(qa): report telegram reply rtt 2026-04-23 14:33:17 +05:30
Peter Steinberger
6e971454ec perf(test): skip unused binding placement hints 2026-04-23 09:56:38 +01:00
Peter Steinberger
df2f025194 fix: verify pinned macOS smoke baseline 2026-04-23 09:52:48 +01:00
openclaw-docs-agent[bot]
c45026e5cc docs: refresh documentation 2026-04-23 08:50:54 +00:00
Peter Steinberger
885bf1c5d8 ci: parallelize core test configs 2026-04-23 09:42:14 +01:00
Peter Steinberger
7f64a3c4ca fix: accept Discord smoke nonce directly 2026-04-23 09:40:59 +01:00
Vincent Koc
68e7db753b docs: trim Telegram webhook/exec approvals/forum topic ACP verbosity 2026-04-23 01:39:05 -07:00
Peter Steinberger
855912b25c test(matrix): harden live QA waits 2026-04-23 09:36:48 +01:00
Peter Steinberger
6094358311 ci: avoid blacksmith queue for core checks 2026-04-23 09:36:29 +01:00
Peter Steinberger
4b1577b339 fix: harden Discord roundtrip smoke 2026-04-23 09:28:28 +01:00
Peter Steinberger
3110840eba test: skip stale openrouter live routes 2026-04-23 09:27:00 +01:00
Peter Steinberger
461deb8d8a test(feishu): coalesce lifecycle monitor cases 2026-04-23 09:25:58 +01:00
Vincent Koc
2b292faece docs: merge Discord Voice sections and trim thread/streaming/ACP verbosity 2026-04-23 01:23:22 -07:00
openclaw-docs-agent[bot]
e69e90786d docs: refresh documentation 2026-04-23 08:18:14 +00:00
Vincent Koc
a2d91a1a9a docs: trim gateway configuration and plugin architecture reference dumps 2026-04-23 01:12:16 -07:00
Peter Steinberger
1263d4278e fix(sessions): preserve active route updates during maintenance 2026-04-23 09:10:51 +01:00
Eliot
94f703a845 fix(sessions): updateLastRoute must not bump updatedAt (#49515) (#49588)
updateLastRoute() used mergeSessionEntry which bumps updatedAt to
Date.now() on every inbound message. This prevented session idle
and daily reset from ever firing, since evaluateSessionFreshness()
always saw a fresh updatedAt.

The fix from #32379 patched recordSessionMetaFromInbound to use
mergeSessionEntryPreserveActivity, but missed updateLastRoute() in
the same inbound pipeline.

Changes:
- Remove explicit updatedAt from updateLastRoute basePatch
- Switch from mergeSessionEntry to mergeSessionEntryPreserveActivity
- Add regression test verifying updatedAt is preserved
- Update existing test assertion to match corrected behavior

Fixes #49515
2026-04-23 03:05:05 -05:00
Peter Steinberger
60341689fe test(telegram): keep session support inside package 2026-04-23 09:04:57 +01:00
Peter Steinberger
c1f777fed2 fix: update Discord smoke channel config 2026-04-23 09:03:52 +01:00
Vincent Koc
b7506521e6 docs: restructure gateway security page and extract audit checks reference 2026-04-23 01:01:12 -07:00
Peter Steinberger
25039e973e test(gateway): avoid send handler reimports 2026-04-23 08:59:41 +01:00
Peter Steinberger
eb4bd4de5d test(whatsapp): coalesce monitor inbox cases 2026-04-23 08:56:47 +01:00
Peter Steinberger
4100bea888 test(telegram): hide split message context files 2026-04-23 08:54:09 +01:00
Peter Steinberger
40b40752be test(telegram): coalesce message context cases 2026-04-23 08:54:09 +01:00
Peter Steinberger
98c8920729 ci: add focused live model dispatch 2026-04-23 08:47:44 +01:00
Peter Steinberger
f8894d5b3e docs: align cli index with command surface 2026-04-23 08:46:14 +01:00
Peter Steinberger
d85819d867 perf(config): skip redundant setup auto-enable probes 2026-04-23 08:44:01 +01:00
Vincent Koc
d1f91b52fa docs: restructure cli index and active memory pages 2026-04-23 00:42:08 -07:00
Peter Steinberger
14e69146e6 ci: use smaller live model runners 2026-04-23 08:41:23 +01:00
Peter Steinberger
dbcee0bc76 ci: shard docker live model checks 2026-04-23 08:40:18 +01:00
Peter Steinberger
fc4295f562 perf(whatsapp): narrow inbound dedupe imports 2026-04-23 08:37:56 +01:00
Peter Steinberger
1ea058345a ci: simplify docs agent node restore 2026-04-23 08:37:18 +01:00
Peter Steinberger
107fbe88a8 test(zalo): cache lifecycle monitor imports 2026-04-23 08:31:07 +01:00
Peter Steinberger
ceadb9ddc4 ci: document docs agent workflow-run guard 2026-04-23 08:30:48 +01:00
Vincent Koc
ce4bb8f638 fix(onboarding): surface official WeCom channel install 2026-04-23 00:29:34 -07:00
Peter Steinberger
1f91af17fd ci: let docs agent runs finish 2026-04-23 08:29:06 +01:00
scoootscooob
46a70a7992 docs: add trajectory export changelog entry 2026-04-23 00:28:45 -07:00
Peter Steinberger
6129dfe590 test(matrix): extend live QA waits 2026-04-23 08:25:32 +01:00
Vincent Koc
daaedf37b7 docs: prune recent additions for readability 2026-04-23 00:23:18 -07:00
Peter Steinberger
252e4dde39 ci: add docs agent workflow 2026-04-23 08:22:47 +01:00
Peter Steinberger
e88d8512a7 perf(discord): narrow monitor runtime imports 2026-04-23 08:21:01 +01:00
Peter Steinberger
966e814c5e fix: defer model pricing refresh 2026-04-23 08:15:36 +01:00
Peter Steinberger
8714badc0c fix: show fast mode in status 2026-04-23 08:04:24 +01:00
Vincent Koc
2d7a4edba3 test(plugins): pin live provider config guards 2026-04-23 00:00:32 -07:00
Peter Steinberger
dfca707e4b fix: resolve implicit default Telegram status sessions 2026-04-23 07:57:38 +01:00
Peter Steinberger
9dd097a7a5 test: harden docker live backend probes 2026-04-23 07:57:00 +01:00
Vincent Koc
91c795cee0 docs: MCP + cron + plugin lifecycle plus channel env-block cross-links 2026-04-22 23:56:53 -07:00
Peter Steinberger
dd17dea761 docs: align pairing metadata upgrade approval 2026-04-23 07:56:16 +01:00
Vincent Koc
526a8bdc3f fix(codex): refresh live discovery config 2026-04-22 23:53:41 -07:00
Vincent Koc
c8aec6b951 docs: Control UI identity + gateway pairing hardening + release verification 2026-04-22 23:52:37 -07:00
Vincent Koc
ea3970f138 docs: CLI + gateway + plugin harness coverage for 48h changes 2026-04-22 23:49:06 -07:00
Peter Steinberger
eb2cb7834e fix(amazon-bedrock): type live plugin config 2026-04-23 07:47:59 +01:00
Vincent Koc
02da7350ad test(telegram): pin outbound hook routing fields 2026-04-22 23:47:06 -07:00
Peter Steinberger
a3b6f9dc73 ci: cover OpenAI web search minimal smoke 2026-04-23 07:46:08 +01:00
Peter Steinberger
5b39be3653 fix(agents): preserve raw fallback schema errors 2026-04-23 07:44:39 +01:00
Vincent Koc
da8993203c fix(amazon-bedrock): refresh live discovery and guardrail config 2026-04-22 23:41:27 -07:00
Peter Steinberger
d8db122a23 docs: document trajectory bundles 2026-04-23 07:39:49 +01:00
Vincent Koc
30a5c441f3 docs(channels): cover WhatsApp replyToMode, Discord inheritParent, Slack HTTP/ACP/downloadFile, Telegram webhook+picker auth, Mattermost reasoning suppression, workspace .env block for channel endpoints 2026-04-22 23:39:38 -07:00
Peter Steinberger
6929fa764c test(browser): avoid flaky CDP SSRF timeout 2026-04-23 07:37:50 +01:00
Vincent Koc
abb32e39b5 fix(openai): refresh live prompt overlay config 2026-04-22 23:37:16 -07:00
Peter Steinberger
938af16289 docs: deep audit documentation against source 2026-04-23 07:32:58 +01:00
Peter Steinberger
9f19e5be52 feat(i18n): add Thai control UI locale 2026-04-23 07:32:58 +01:00
Vincent Koc
9be0601b20 fix(ollama): refresh live discovery config 2026-04-22 23:30:28 -07:00
Peter Steinberger
a81c475731 fix(openai): raise minimal reasoning for native web search 2026-04-23 07:29:44 +01:00
Vincent Koc
21a16349f2 docs(providers): cover Opus 4.7 1M, Mantle Anthropic Messages, Codex device-code/CLI-import removal, Moonshot tool-id sanitization, LM Studio streaming-usage, Tencent bundled plugin 2026-04-22 23:29:36 -07:00
scoootscooob
a3d9c53db2 feat: add trajectory bundle export and default-on runtime capture (#70291)
* Trajectory: export session bundles by default

* Harden trajectory export diagnostics integration

* Address trajectory export review feedback

* Share diagnostics and trajectory bundle plumbing

* Harden trajectory recording and export

* Confine trajectory export outputs

* Document trajectory export command

* Harden trajectory export bundle privacy

* Redact trajectory sidecar paths

* Fix plugin install checks after rebase

* Keep queued writers working without O_NOFOLLOW

* Keep Codex trajectory writes without O_NOFOLLOW

* Harden trajectory export path handling

* Redact mixed trajectory export paths
2026-04-22 23:29:01 -07:00
Vincent Koc
6dba5cc2a0 fix(copilot): refresh live discovery config 2026-04-22 23:28:27 -07:00
Peter Steinberger
834fdc4832 docs: align documentation with current surfaces 2026-04-23 07:25:06 +01:00
Shakker
25451c9639 docs: add models provider changelog 2026-04-23 07:24:49 +01:00
Alex Knight
d75725e658 fix: clear embedded runs before lifecycle end (#70187)
* fix: clear embedded runs before lifecycle end

* fix: guard onBeforeLifecycleTerminal against synchronous throws

Wrap the hook invocation in try/catch so a synchronous exception
cannot skip emitLifecycleTerminal() after lifecycleTerminalEmitted
is already set to true. This preserves the best-effort contract
documented in the JSDoc.
2026-04-23 16:23:52 +10:00
Shakker
a92fe5ee40 fix: harden external auth fallback loading 2026-04-23 07:22:24 +01:00
Shakker
d87587b136 fix: align models provider help and auth warnings 2026-04-23 07:22:24 +01:00
Shakker
0e1407362d docs: mark external oauth hook deprecated 2026-04-23 07:22:24 +01:00
Shakker
bd4cfe0e7e docs: document provider ids and auth contracts 2026-04-23 07:22:24 +01:00
Shakker
db1e4f811d perf: scope models list discovery by provider 2026-04-23 07:22:24 +01:00
Shakker
3ec5558f53 fix: preserve external auth hook compatibility 2026-04-23 07:22:24 +01:00
Shakker
47ae15c059 feat: add external auth provider contracts 2026-04-23 07:22:24 +01:00
Peter Steinberger
4d1d0cd021 fix: stabilize gateway watch runtime deps 2026-04-23 07:22:10 +01:00
Peter Steinberger
33d9e1aa83 perf(test): narrow security audit plugin scope test 2026-04-23 07:21:46 +01:00
Vincent Koc
a35ed6b170 fix(ci): avoid duplicate install smoke docker build 2026-04-22 23:17:27 -07:00
Peter Steinberger
96ad6f53a2 test(models/auth): mark migration replacement fixture 2026-04-23 07:16:24 +01:00
Peter Steinberger
a7871d8212 fix(models/auth): sanitize replacement config patches 2026-04-23 07:16:24 +01:00
Neerav Makwana
a849283f80 harden: drop prototype-pollution keys in configPatch merge
Skip `__proto__`, `prototype`, and `constructor` keys while recursively
merging provider-auth `configPatch` payloads. Plugins construct the
patch in-process today, but JSON-parsed sources can preserve these keys
and the assignment `next[key] = value` would otherwise mutate the
merge target's prototype chain.

Made-with: Cursor
2026-04-23 07:16:24 +01:00
Neerav Makwana
14d1c9c4f0 fix(models/auth): merge agents.defaults.models on provider login
`openclaw models auth login` was replacing `agents.defaults.models`
wholesale whenever a provider returned a `configPatch` with that key,
even if the patch only listed the new default model. Re-authenticating
an OAuth provider such as OpenAI Codex wiped aliases and per-model
params for every other provider.

Make replacement opt-in via `ProviderAuthResult.replaceDefaultModels`.
Ordinary logins merge their allowlist patch so unrelated entries
survive; the Anthropic -> Claude CLI migration opts in because it
renames keys the merge path would otherwise keep stale.

Fixes #69414.

Made-with: Cursor
2026-04-23 07:16:24 +01:00
Peter Steinberger
5bd8254f61 fix(docs): keep source dirs in i18n route index 2026-04-23 07:15:46 +01:00
Peter Steinberger
3ccaa1b2f1 docs: prepare 2026.4.22 changelog 2026-04-23 07:15:23 +01:00
Vincent Koc
a3d0b4307b docs(release): use QA Lab all lanes gate 2026-04-22 23:13:29 -07:00
Peter Steinberger
c23ad91a14 fix(matrix): keep DM allowlist out of room commands 2026-04-23 07:09:34 +01:00
Vincent Koc
912dcfbc2b test(plugins): guard startup-gated hook wiring 2026-04-22 23:08:08 -07:00
Vincent Koc
3dc3bf65d2 fix(memory): support live lancedb hook enablement 2026-04-22 23:06:39 -07:00
Peter Steinberger
4e259b0461 fix: harden parallels update smoke 2026-04-23 07:05:37 +01:00
Peter Steinberger
cc343febfb fix: tolerate runtime deps temp cleanup races 2026-04-23 07:01:27 +01:00
Peter Steinberger
acb8fe986d build: keep runtime dep stamps out of dist 2026-04-23 06:55:07 +01:00
Peter Steinberger
bb55e23c67 test(e2e): cover OpenAI web search minimal reasoning 2026-04-23 06:51:29 +01:00
Peter Steinberger
f600e98e5b fix(agents): handle OpenAI web search schema rejects 2026-04-23 06:51:29 +01:00
Peter Steinberger
87c85c507a fix: align docs with cli and provider surfaces 2026-04-23 06:39:11 +01:00
joshavant
d3a8480093 qa-live: simplify telegram pass progress log lines 2026-04-23 00:37:03 -05:00
Peter Steinberger
2194be201d test(slack,line): reduce hot extension test imports 2026-04-23 06:28:06 +01:00
Peter Steinberger
a46d41156d fix(matrix): ignore stale no-reply events 2026-04-23 06:27:20 +01:00
Peter Steinberger
6b126cd0de feat(docs): add Thai translation support 2026-04-23 06:23:02 +01:00
Peter Steinberger
ebf351b138 fix(test): prevent Vitest shard stalls 2026-04-23 06:20:34 +01:00
joshavant
e6d0342629 qa-live: stream telegram scenario progress logs in realtime 2026-04-23 00:19:43 -05:00
Peter Steinberger
c78562d8a2 ci: fan out qa lab lanes 2026-04-23 06:15:01 +01:00
Peter Steinberger
76ab7c5b05 test: align channel plugin install fixtures 2026-04-23 06:13:31 +01:00
Vincent Koc
4955e57024 fix(skill-workshop): support live hook enablement 2026-04-22 22:09:10 -07:00
Peter Steinberger
db332aa8e9 ci: schedule qa lab gates 2026-04-23 06:08:29 +01:00
Peter Steinberger
e62431fd7f test: type onboarding plugin enable mock 2026-04-23 06:07:35 +01:00
Vincent Koc
f67e48e6a0 feat(onboarding): auto-install missing provider and channel plugins
Squash-merge PR 70012.
2026-04-22 22:05:00 -07:00
Peter Steinberger
86ace805b7 fix(qa): align telegram commands live assertion 2026-04-23 06:04:06 +01:00
Peter Steinberger
a2db4c9cdd ci: reuse docker e2e image across matrix 2026-04-23 06:02:51 +01:00
Peter Steinberger
66f94104c6 test: trim slow CI hotspot coverage 2026-04-23 06:02:26 +01:00
Peter Steinberger
e3caacd530 lint: enforce exhaustive switches 2026-04-23 06:02:12 +01:00
Peter Steinberger
4aa35d85fa test: clean up voice-call event timers 2026-04-23 06:02:12 +01:00
Vincent Koc
9f437549d3 fix(scripts): guard core test tsgo in sparse worktrees 2026-04-22 22:00:17 -07:00
Peter Steinberger
404c4c1f86 docs: document fast committer escape hatch 2026-04-23 05:57:53 +01:00
Peter Steinberger
112f6e1622 test: reuse prebuilt docker e2e image 2026-04-23 05:55:42 +01:00
Peter Steinberger
61dfbd78d5 test: add npm tarball onboarding docker e2e 2026-04-23 05:52:43 +01:00
joshavant
c2f0559829 qa-live: tag telegram observed messages with scenario context 2026-04-22 23:52:06 -05:00
Peter Steinberger
6163cfffdf test: update misc extension routing expectation 2026-04-23 05:50:57 +01:00
Peter Steinberger
69a4977fc7 fix(tooling): keep gitignore changes scoped 2026-04-23 05:50:14 +01:00
Peter Steinberger
e763ea1119 fix(plugins): stop tracking runtime deps manifests 2026-04-23 05:48:49 +01:00
Vincent Koc
ccde1c4707 fix(tooling): drop stale oxlint unicorn rule 2026-04-22 21:46:29 -07:00
Peter Steinberger
56c7ed0f8a test(codex): mock lightweight app-server runtime 2026-04-23 05:46:00 +01:00
Vincent Koc
d5c0f70e95 refactor(hooks): share live config fallback handling 2026-04-22 21:42:53 -07:00
Vincent Koc
4984cad5ae fix(test): route misc extension targets to the misc shard 2026-04-22 21:42:53 -07:00
joshavant
754577b43e qa-live: keep telegram failure details with public metadata redaction 2026-04-22 23:36:07 -05:00
Peter Steinberger
0be2b85951 test: avoid slow followup fallback fixture 2026-04-23 05:35:34 +01:00
Peter Steinberger
01ba0fa663 docs: update changelog for codex fixes 2026-04-23 05:35:18 +01:00
Peter Steinberger
d88d6a3c8b fix: complete codex app-server turns in docker 2026-04-23 05:35:17 +01:00
Peter Steinberger
20b05f220e fix: expose codex provider catalog 2026-04-23 05:35:17 +01:00
Peter Steinberger
0585e181f8 fix(media): prefer provider stt before local whisper 2026-04-23 05:30:57 +01:00
Peter Steinberger
fdf97a8784 chore: enable additional oxlint rules 2026-04-23 05:30:49 +01:00
Peter Steinberger
0b0662b1c9 chore: apply extension lint cleanups 2026-04-23 05:30:49 +01:00
Peter Steinberger
596b88986d chore: apply core lint cleanups 2026-04-23 05:30:49 +01:00
Peter Steinberger
cc9dcd3d69 fix(gateway): prefer linux child OOM victims
Raise eligible Linux child processes own oom_score_adj from a child-side /bin/sh exec shim so cgroup memory pressure prefers transient workers over the long-lived gateway. Cover supervisor children, PTY shells, MCP stdio servers, and OpenClaw-launched browser processes through the shared process runtime seam.

Harden the wrapper for distroless images, shell startup env, per-child and process-level opt-outs, dash-compatible exec, and leading-dash command names. Document Linux verification and OOM behavior.

Fixes #70404.

Co-authored-by: Neerav Makwana <261249544+neeravmakwana@users.noreply.github.com>
2026-04-23 05:23:40 +01:00
Peter Steinberger
d3a2e993a8 test(gateway): stabilize codex acp bind live 2026-04-23 05:22:37 +01:00
Peter Steinberger
3105ff2dda fix(acpx): preserve codex acp auth env 2026-04-23 05:22:37 +01:00
Peter Steinberger
e29abb2606 test: slim live auth staging 2026-04-23 05:22:37 +01:00
Peter Steinberger
f3c60e9c0d fix(lint): remove unsupported no-empty-pattern options 2026-04-23 05:22:37 +01:00
Peter Steinberger
4ad8ed2cbe refactor: type config schemas as typebox-compatible 2026-04-23 05:22:16 +01:00
Peter Steinberger
cf1e48672b fix: clean up acpx probe agent config 2026-04-23 05:20:53 +01:00
Peter Steinberger
6fb55f8959 extensions/acpx: align probeAgent with current config surface
Keep the acpx runtime type shim compatible with upstream probeAgent support and de-duplicate the rebased config/service wiring against current main. Normalize probeAgent the same way agent registry keys are normalized so mixed-case config resolves consistently.

Refs #68409
2026-04-23 05:20:53 +01:00
Sean Sun
eab26aca9b extensions/acpx: expose probeAgent config so non-codex ACP stacks stay available
Add optional probeAgent field to acpx plugin config, carry through
resolveAcpxPluginConfig, forward to AcpxRuntime constructor so users
can set plugins.entries.acpx.config.probeAgent to any configured agent
id instead of hardcoding codex.

Refs #68409
2026-04-23 05:20:53 +01:00
Marcus Castro
f5f0235bb1 feat(whatsapp): adopt replyToMode quoting (#62305)
* fix(core): align auto-reply threading behavior

* fix(core): propagate reply threading through outbound and gateway

* fix(whatsapp): use cached metadata for native quoted replies

* feat(whatsapp): add configurable native reply quoting
2026-04-23 01:19:47 -03:00
Shakker
728c644e4b cli: add temporary debug timing helper (#70469) (thanks @shakkernerd) 2026-04-23 05:17:17 +01:00
Shakker
d60eb9a4a4 fix: harden CLI debug timing helper 2026-04-23 05:17:17 +01:00
Shakker
106f0f0821 docs: document temporary CLI debug timing 2026-04-23 05:17:17 +01:00
Shakker
8273f5fc0a feat: add CLI debug timing helper 2026-04-23 05:17:17 +01:00
Josh Avant
01e18b6e3b Add maintainer-gated Telegram live QA workflow with Convex hardening (#70427) 2026-04-22 23:17:09 -05:00
Peter Steinberger
6317eda3fe ci: rebalance browser extension shard 2026-04-23 05:16:54 +01:00
Peter Steinberger
b5a7532022 build: finish typebox runtime migration 2026-04-23 05:12:32 +01:00
Peter Steinberger
33aea44fe5 refactor: tighten tool schema types 2026-04-23 05:06:58 +01:00
Peter Steinberger
675cf823fd fix(protocol): keep Swift array item types stable 2026-04-23 05:06:50 +01:00
Peter Steinberger
2c25e1d58d fix(openai): align auth picker copy metadata 2026-04-23 05:06:16 +01:00
Peter Steinberger
9937452405 build: enable more zero-baseline oxlint rules 2026-04-23 05:03:58 +01:00
Peter Steinberger
b2472d6560 build: migrate schema deps to typebox 2026-04-23 04:59:42 +01:00
Peter Steinberger
dd1ba0296c test: update lint suppression allowlist 2026-04-23 04:59:19 +01:00
Peter Steinberger
35ec4a9991 fix: make session write locks non-reentrant by default 2026-04-23 04:57:30 +01:00
Neerav Makwana
d878cf026c fix(pi-embedded-runner): address greptile review on incomplete-turn gate
- Drop redundant !lastToolError check from the messaging-tool clean-stop
  early return; the earlier lastToolError early return already handles
  that case, so the extra condition was dead and misleading.
- Update the CHANGELOG entry to reference only stopReason=stop; the pi-ai
  StopReason type does not include end_turn, so the earlier mention was
  a documentation-only discrepancy.
2026-04-23 04:57:09 +01:00
Neerav Makwana
6cd9136f2d fix(pi-embedded-runner): suppress incomplete-turn warning after clean messaging-tool delivery
The agent runner was surfacing a '⚠️ Agent couldn't generate a response'
warning even when the assistant had already sent user-visible content
through a messaging tool and the turn ended cleanly. Treat that path as
a successful delivery and skip the warning while keeping real failure
modes (tool errors, stopReason=error, interrupted tool use) intact.

Fixes #70396.
2026-04-23 04:57:09 +01:00
Peter Steinberger
93a1f5b3fa test(discord,zalo): trim slow extension tests 2026-04-23 04:54:49 +01:00
tm.lxrd
edea0cba7a fix(openai): align auth picker labels for API key vs Codex OAuth
Lock regression coverage for current OpenAI API key, Codex browser login, and Codex device pairing auth picker labels.\n\nThanks @tmlxrd.
2026-04-23 04:48:55 +01:00
Peter Steinberger
fab76f3d70 build: refresh bundled plugin runtime deps 2026-04-23 04:43:25 +01:00
Peter Steinberger
e61eba11e6 fix: avoid plugin normalization in status model refs 2026-04-23 04:43:25 +01:00
Peter Steinberger
2e40ca2c15 build: enable additional oxlint rules 2026-04-23 04:42:54 +01:00
Ayaan Zaidi
dc5ab602df docs(cli): credit oauth session continuity PR 2026-04-23 09:06:56 +05:30
Ayaan Zaidi
97e9e05f8c docs(cli): clarify oauth session continuity 2026-04-23 09:06:56 +05:30
Ayaan Zaidi
3eb6edc67c fix(cli): key oauth session epochs on identity 2026-04-23 09:06:56 +05:30
Peter Steinberger
c866820fed refactor(stt): share transcription helpers 2026-04-23 04:29:35 +01:00
Super Zheng
a58633d809 test: fix ui presenter next run test for multi-language environments (#60231)
Merged via squash.

Prepared head SHA: 88e7c3c95b
Co-authored-by: medns <1575008+medns@users.noreply.github.com>
Co-authored-by: odysseus0 <8635094+odysseus0@users.noreply.github.com>
Reviewed-by: @odysseus0
2026-04-22 20:26:44 -07:00
Peter Steinberger
576dbdeef7 build: enable new oxlint rules 2026-04-23 04:23:34 +01:00
Peter Steinberger
2908190ba2 fix(agents): recover streamed timings usage (#41056) (thanks @xaeon2026) 2026-04-23 04:23:27 +01:00
Peter Steinberger
137a3629cc fix: harden acpx openclaw bridge routing 2026-04-23 04:22:32 +01:00
alexlomt
0bcd390546 fix(acpx): avoid per-session MCP on openclaw bridge 2026-04-23 04:22:32 +01:00
Peter Steinberger
f79c6ab607 test: update bundled runtime mirror expectations 2026-04-23 04:22:20 +01:00
Peter Steinberger
d0d018bdad fix(qa): restore agentic parity tool runtime 2026-04-23 04:22:03 +01:00
Peter Steinberger
ca8a6e811c docs: note TTS transcript fix (#68869) (thanks @zqchris) 2026-04-23 04:22:03 +01:00
zqchris
0020a327b9 fix(agents): defuse unicode-whitespace MEDIA lines 2026-04-23 04:22:03 +01:00
zqchris
c165af97d7 fix(agents): defuse TTS transcript fence markers 2026-04-23 04:22:03 +01:00
Chris Zhang
7b51b7b26f fix(agents): preserve spoken text in tts tool result
The tts tool previously returned a fixed "Generated audio reply."
string in its content, so session transcripts lost what was actually
spoken. Across every channel, a voice-only reply left no text record
for future turns, forcing users to recover transcripts from the
provider's API. Echo the synthesized text back in the tool result
content (audio still delivered via details.media).

Sanitize the transcript before embedding so crafted utterances cannot
inject reply directives when tool output is rendered in verbose mode:
MEDIA: at line start and [[…]] markers are interrupted with a
zero-width word joiner (U+2060) that defuses parseReplyDirectives
without altering the visible text.
2026-04-23 04:22:03 +01:00
Peter Steinberger
f0cc29af9a test(build): align runtime mirror guard expectations 2026-04-23 04:18:55 +01:00
Peter Steinberger
ff260ce67b build: fix bundled plugin runtime mirror guard 2026-04-23 04:15:39 +01:00
Super Zheng
87c6aaff3e build: verify bundled plugin runtime mirrors in postpublish checks (#60112)
Merged via squash.

Prepared head SHA: 79bbb105a8
Co-authored-by: medns <1575008+medns@users.noreply.github.com>
Co-authored-by: odysseus0 <8635094+odysseus0@users.noreply.github.com>
Reviewed-by: @odysseus0
2026-04-22 20:12:23 -07:00
Peter Steinberger
1e8564cb13 fix(auth-profiles): repair stale codex oauth profiles 2026-04-23 04:03:47 +01:00
Mason Huang
c545416498 docs(changelog): remove Token Plan from Tencent provider entry (#68460) (#70450) 2026-04-23 11:02:57 +08:00
Peter Steinberger
9660cb705b fix(memory): preserve KNN filter limits (#69680) (thanks @aalekh-sarvam) 2026-04-23 04:01:47 +01:00
aalekh-sarvam
7cd051d7f7 fix(memory): use sqlite-vec KNN for searchVector (190x speedup)
Replace full-table scan via vec_distance_cosine() + ORDER BY LIMIT with
sqlite-vec's native MATCH + k = ? KNN operator. Keep vec_distance_cosine()
in the SELECT so score = 1 - dist preserves the existing cosine [0,1]
semantics the downstream merge pipeline depends on.

Fixes #69666.

Benchmark on 10,827 chunks, 4096-dim embeddings:
- Before (full scan):  ~8490 ms/query
- After  (KNN + join): ~50 ms/query

No behavioral changes: returned ids and ordering are identical to the
previous query on all tested queries. The LIMIT ? binding is replaced by
k = ? which caps sqlite-vec's candidate set to the same count.
2026-04-23 04:01:47 +01:00
Peter Steinberger
06308e21f7 build: update dependencies 2026-04-23 04:00:17 +01:00
Peter Steinberger
1c91f3f09f fix: route btw provider streams by workspace (#70413) (thanks @suboss87) 2026-04-23 03:59:11 +01:00
Subash
bc3c8eee2c fix(agents): route /btw through the provider's stream fn so Ollama URLs build correctly 2026-04-23 03:59:11 +01:00
Peter Steinberger
da8621df0d fix(openai-completions): enable local streaming usage compat (#68711) (thanks @gaineyllc) 2026-04-23 03:57:04 +01:00
Peter Steinberger
d968749c4d ci: split discord telegram extension shards 2026-04-23 03:56:39 +01:00
Peter Steinberger
728e29a898 test(agents): cover openai-completions tool-call arg repair 2026-04-23 03:54:16 +01:00
Peter Steinberger
6b765f58d3 docs(changelog): clarify realtime stt entries 2026-04-23 03:53:14 +01:00
Peter Steinberger
84e0c2f0ea ci: rebalance slack extension shard 2026-04-23 03:49:43 +01:00
Peter Steinberger
90a34cc242 docs: credit openai-completions repair PR (#70294) (thanks @MonkeyLeeT) 2026-04-23 03:49:04 +01:00
Peter Steinberger
7503d4859f fix(plugin-sdk): fall back for provider auth runtime 2026-04-23 03:49:04 +01:00
Peter Steinberger
5e172b3888 fix(qa): preserve image parity plugin allowlist 2026-04-23 03:49:04 +01:00
Peter Steinberger
f78fc61768 fix(agents): pass embedded tool allowlist to pi sessions 2026-04-23 03:49:04 +01:00
Ted Li
2ba43f5d27 fix(agents): keep tool-call repair scoped by transport 2026-04-23 03:49:04 +01:00
Ted Li
49c7319ea5 fix(agents): repair malformed tool-call args on openai-completions 2026-04-23 03:49:04 +01:00
Peter Steinberger
e54d0634c5 fix: harden removed Codex auth choice guidance (#70390) (thanks @pashpashpash) 2026-04-23 03:45:01 +01:00
Peter Steinberger
84aa35e9b2 ci: split slow extension shard pairs 2026-04-23 03:43:55 +01:00
Peter Steinberger
35c9f96878 test: wait for gateway restart sentinel 2026-04-23 03:42:34 +01:00
Ayaan Zaidi
2a4514afca fix: preserve restart hooks during async prep (#70269) 2026-04-23 08:07:53 +05:30
Ayaan Zaidi
ab32c53103 fix(gateway): preserve restart hooks across coalescing 2026-04-23 08:07:53 +05:30
Ayaan Zaidi
46ce666b04 fix(gateway): keep restart emitting after ack prep failure 2026-04-23 08:07:53 +05:30
Ayaan Zaidi
fe5f0cddb9 fix(gateway): bind restart continuation to emitted restart 2026-04-23 08:07:53 +05:30
Ayaan Zaidi
f5173589a4 fix(gateway): harden restart acknowledgements 2026-04-23 08:07:53 +05:30
Ayaan Zaidi
95ecb0526e docs(gateway): document restart acknowledgement default 2026-04-23 08:07:53 +05:30
Ayaan Zaidi
b982d9e669 fix(gateway): default restart acknowledgement continuations 2026-04-23 08:07:53 +05:30
Peter Steinberger
0e7bcf7588 feat(plugin-sdk): share realtime transcription websocket sessions 2026-04-23 03:35:32 +01:00
Peter Steinberger
86b160869d ci: rebalance extension test shards 2026-04-23 03:34:44 +01:00
Peter Steinberger
b09aed8271 fix: cap long SDK retry waits (#68474) (thanks @jetd1) 2026-04-23 03:32:35 +01:00
Peter Steinberger
41715b56af ci: rebalance agentic test shard 2026-04-23 03:28:21 +01:00
pashpashpash
c71f07ba43 Fail fast for removed Codex import auth choice 2026-04-22 19:27:52 -07:00
pashpashpash
788fd14118 Preserve removed Codex import auth choice 2026-04-22 19:27:52 -07:00
pashpashpash
103d7af458 Fix legacy update compat sidecars 2026-04-22 19:27:52 -07:00
pashpashpash
93a2143384 Remove stale Codex import auth choice 2026-04-22 19:27:52 -07:00
pashpashpash
6f6fa5c90b Remove Codex CLI auth import 2026-04-22 19:27:52 -07:00
Peter Steinberger
5a22d16bde ci: collapse built artifact test consumers 2026-04-23 03:24:48 +01:00
Peter Steinberger
aa27a9474f fix(outbound): centralize active delivery claims 2026-04-23 03:23:38 +01:00
Neerav Makwana
ca83f0fd7a fix(outbound): bail live delivery when a concurrent drain wins the claim
If a reconnect/startup drain observes the newly enqueued queue entry and
calls claimRecoveryEntry before the live delivery path reaches
tryClaimActiveDelivery, tryClaimActiveDelivery returns false. Previously
the live path still proceeded to deliverOutboundPayloadsCore and then
ack/fail, which would race the drain's own delivery and ack/fail for the
same entry id and produce duplicate outbound messages.

Treat a failed claim acquisition as "another in-process owner is already
handling this queue entry" and bail out with an empty result array, leaving
the queue entry in place for the drain to deliver and clean up. This closes
the narrow residual race called out by the Aisle security review on
openclaw/openclaw#70428.

Made-with: Cursor
2026-04-23 03:23:38 +01:00
Neerav Makwana
c94a8702c7 fix(outbound): hold active-delivery claim so reconnect drain skips live sends
Reconnect drain (drainPendingDeliveries) matches fresh pending entries by
design to preserve crash-replay, but the live delivery path in
deliverOutboundPayloads held no in-memory claim while the send was running.
A reconnect firing mid-send therefore re-drove the same queue entry and
produced duplicate outbound messages (e.g. WhatsApp cron sends going out
7-12x when the 30-minute inbound-silence watchdog fired during delivery).

Claim the queueId against the existing entriesInProgress set right after
enqueueDelivery and release it in the finally branch around ack/fail. Drain
already skips claimed ids via claimRecoveryEntry, so no drain-side change is
needed. The claim is process-local on purpose: a crashed owner leaves no
claim behind, so startup recovery still reclaims orphaned entries.

Fixes #70386.

Made-with: Cursor
2026-04-23 03:23:38 +01:00
Peter Steinberger
adda0dcf20 test: cover bundled plugin dependency activation 2026-04-23 03:17:06 +01:00
Peter Steinberger
90696bffff fix: defer bundled plugin runtime deps until enabled 2026-04-23 03:17:06 +01:00
Peter Steinberger
4479d4d437 ci: fold gateway watch into build artifacts 2026-04-23 03:15:56 +01:00
Peter Steinberger
688a6ef4fd ci: keep gateway watch skip-build artifact fresh 2026-04-23 03:11:51 +01:00
Peter Steinberger
bae057fd77 fix: accept Codex MCP approval elicitations (#68807) 2026-04-23 03:11:26 +01:00
Peter Steinberger
24f5198caf ci: trust restored gateway watch artifacts 2026-04-23 03:09:40 +01:00
8230 changed files with 566924 additions and 115585 deletions

View File

@@ -1,11 +1,6 @@
---
name: blacksmith-testbox
description: >
Validate code changes against real CI when local execution is not
enough. Use for CI-parity checks, secrets/services, migrations, or
builds/tests that cannot run reliably on the local machine. Do not
replace repo-documented local test/build loops just because this
skill exists.
description: Run Blacksmith Testbox for CI-parity checks, secrets, hosted services, migrations, or builds local cannot reproduce.
---
# Blacksmith Testbox
@@ -21,6 +16,19 @@ warm caches, local build state, and fast feedback.
Testbox is the expensive path. Reach for it deliberately.
OpenClaw maintainers can opt into Testbox-first validation by setting
`OPENCLAW_TESTBOX=1` in their environment or standing agent rules. This mode is
maintainers-only and requires Blacksmith access.
When `OPENCLAW_TESTBOX=1` is set in OpenClaw:
- Pre-warm a Testbox early for longer, wider, or uncertain work.
- Prefer Testbox for `pnpm` gates, e2e, package-like proof, and broad suites.
- Reuse the same Testbox ID for every run command in the same task/session.
- Use local commands only when the task explicitly sets
`OPENCLAW_LOCAL_CHECK_MODE=throttled|full`, or when the user asks for local
proof.
## Install the CLI
If `blacksmith` is not installed, install it:
@@ -86,7 +94,8 @@ Prefer Testbox when:
- you are reproducing CI-only failures
- you need the exact workflow image/job environment from GitHub Actions
For OpenClaw specifically, normal local iteration should stay local:
For OpenClaw specifically, normal local iteration stays local unless maintainer
Testbox mode is enabled with `OPENCLAW_TESTBOX=1`:
- `pnpm check:changed`
- `pnpm test:changed`
@@ -94,27 +103,49 @@ For OpenClaw specifically, normal local iteration should stay local:
- `pnpm test:serial`
- `pnpm build`
Only use Testbox in OpenClaw when the user explicitly wants CI-parity or the
check truly depends on remote secrets/services that the local repo loop cannot
provide.
If `OPENCLAW_TESTBOX=1` is enabled, run those same repo commands inside the
warm Testbox. If the user wants laptop-friendly local proof for one command, use
the explicit escape hatch `OPENCLAW_LOCAL_CHECK_MODE=throttled`.
For installable-package product proof, prefer the GitHub `Package Acceptance`
workflow over an ad hoc Testbox command. It resolves one package candidate
(`source=npm`, `source=ref`, `source=url`, or `source=artifact`), uploads it as
`package-under-test`, and runs the reusable Docker E2E lanes against that exact
tarball on GitHub/Blacksmith runners. Use `workflow_ref` for the trusted
workflow/harness code and `package_ref` for the source ref to pack when testing
an older trusted branch, tag, or SHA.
## Setup: Warmup before coding
If you decided Testbox is actually warranted, warm one up early. This returns
an ID instantly and boots the CI environment in the background while you work:
If you decided Testbox is warranted, warm one up early. This returns an ID
instantly and boots the CI environment in the background while you work:
blacksmith testbox warmup ci-check-testbox.yml
# → tbx_01jkz5b3t9...
Save this ID. You need it for every `run` command.
For OpenClaw maintainer Testbox mode, pre-warm at the start of longer or wider
tasks:
blacksmith testbox warmup ci-check-testbox.yml --ref main --idle-timeout 90
Use the build-artifact warmup when e2e/package/build proof benefits from seeded
`dist/`, `dist-runtime/`, and build-all caches:
blacksmith testbox warmup ci-build-artifacts-testbox.yml --ref main --idle-timeout 90
Warmup dispatches a GitHub Actions workflow that provisions a VM with the
full CI environment: dependencies installed, services started, secrets
injected, and a clean checkout of the repo at the default branch.
In OpenClaw, raw commit SHAs are not reliable dispatch refs for `warmup --ref`;
use a branch or tag. The build-artifact workflow resolves `openclaw@beta` and
`openclaw@latest` to SHA cache keys internally.
Options:
--ref <branch> Git ref to dispatch against (default: repo's default branch)
--ref <branch|tag> Git ref to dispatch against (default: repo's default branch)
--job <name> Specific job within the workflow (if it has multiple)
--idle-timeout <min> Idle timeout in minutes (default: 30)
@@ -231,6 +262,11 @@ services, CI-only runners, or reproducibility against the workflow image.
If the repo says local tests/builds are the normal path, follow the repo.
OpenClaw maintainer exception: if `OPENCLAW_TESTBOX=1` is set by the user or
agent environment, treat Testbox as the normal validation path for this repo.
Use `OPENCLAW_LOCAL_CHECK_MODE=throttled|full` as the explicit local escape
hatch.
## When to use
Use Testbox when:
@@ -247,18 +283,25 @@ checks that need parity or remote state.
## Workflow
1. Decide whether the repo's local loop is the right default.
2. Only if Testbox is warranted, warm up early:
`blacksmith testbox warmup ci-check-testbox.yml` → save the ID
1. Decide whether the repo's local loop is the right default. For OpenClaw,
`OPENCLAW_TESTBOX=1` makes Testbox the maintainer default.
2. If Testbox is warranted, warm up early:
`blacksmith testbox warmup ci-check-testbox.yml --ref main --idle-timeout 90` → save the ID
3. Write code while the testbox boots in the background.
4. Run the remote command when needed:
`blacksmith testbox run --id <ID> "npm test"`
`blacksmith testbox run --id <ID> "pnpm check:changed"`
5. If tests fail, fix code and re-run against the same warm box.
6. If you changed dependency manifests (package.json, etc.), prepend
the install command: `blacksmith testbox run --id <ID> "npm install && npm test"`
7. If you need artifacts (coverage reports, build outputs, etc.), download them:
7. If a narrow PR reports a full sync or the box was reused/expired, sanity
check the remote copy before a slow gate:
`blacksmith testbox run --id <ID> "pnpm testbox:sanity"`.
If it reports missing root files or mass tracked deletions, stop the box and
warm a fresh one. Use `OPENCLAW_TESTBOX_ALLOW_MASS_DELETIONS=1` only for an
intentional large deletion PR.
8. If you need artifacts (coverage reports, build outputs, etc.), download them:
`blacksmith testbox download --id <ID> coverage/ ./coverage/`
8. Once green, commit and push.
9. Once green, commit and push.
## OpenClaw full test suite
@@ -273,9 +316,15 @@ Observed full-suite time on Blacksmith Testbox is about 3-4 minutes:
- 173-180s on a warmed box
- 219s on a fresh 32-vCPU box
When validating before commit/push, run `pnpm check:changed` first when
appropriate, then the full suite with the profile above if broad confidence is
needed.
When validating before commit/push in maintainer Testbox mode, run
`pnpm check:changed` inside the warmed box first when appropriate, then the full
suite with the profile above if broad confidence is needed.
Run `pnpm testbox:sanity` inside the warmed box before the broad command when
the sync looks suspicious. It checks that root files such as `pnpm-lock.yaml`
still exist and fails on 200 or more tracked deletions. That catches stale or
corrupted rsync state before dependency install or Vitest failures hide the real
problem.
## Examples
@@ -329,12 +378,14 @@ timeout is reached). Default timeout is 5m; use `--wait-timeout` for longer
blacksmith testbox stop --id <ID>
Testboxes automatically shut down after being idle (default: 30 minutes).
If you need a longer session, increase the timeout at warmup time:
If you need a longer session, increase the timeout at warmup time. For OpenClaw
maintainer work, use 90 minutes for long-running sessions:
blacksmith testbox warmup ci-check-testbox.yml --idle-timeout 60
blacksmith testbox warmup ci-check-testbox.yml --idle-timeout 90
blacksmith testbox warmup ci-build-artifacts-testbox.yml --idle-timeout 90
## With options
blacksmith testbox warmup ci-check-testbox.yml --ref main
blacksmith testbox warmup ci-check-testbox.yml --idle-timeout 60
blacksmith testbox warmup ci-check-testbox.yml --idle-timeout 90
blacksmith testbox run --id <ID> "go test ./..."

View File

@@ -0,0 +1,37 @@
---
name: discord-clawd
description: Use to talk to the Discord-backed OpenClaw agent/session; not for archive search.
---
# Discord Clawd
Use this when the task is to talk with the Discord-backed agent/session, ask it a question, or post through that route.
For Discord archive/history/search, use `$discrawl` instead.
## Transport
Use the OpenClaw relay helper:
```bash
cd ~/Projects/agent-scripts
python3 skills/openclaw-relay/scripts/openclaw_relay.py targets
python3 skills/openclaw-relay/scripts/openclaw_relay.py resolve --target maintainers
```
If the target alias exists, prefer a private ask first:
```bash
python3 skills/openclaw-relay/scripts/openclaw_relay.py ask \
--target maintainers \
--message "Reply with exactly OK."
```
Use `publish` when the session should decide whether to post. Use `force-send` only when the user explicitly wants a message posted.
## Guardrails
- Resolve the target before sending real content.
- Report the target and delivery mode used.
- Do not use this for local Discord archive queries.
- Do not expose gateway tokens or session secrets.

View File

@@ -0,0 +1,4 @@
interface:
display_name: "Discord Clawd"
short_description: "Talk to the Discord-backed OpenClaw agent"
default_prompt: "Use $discord-clawd to route a private ask or explicit post through the Discord-backed OpenClaw agent/session."

View File

@@ -0,0 +1,68 @@
---
name: gitcrawl
description: Use gitcrawl for OpenClaw issue and PR archive search, duplicate discovery, related-thread clustering, and local GitHub mirror freshness checks.
metadata:
openclaw:
requires:
bins:
- gitcrawl
---
# Gitcrawl
Use this skill before live GitHub search when triaging OpenClaw issues or PRs.
`gitcrawl` is the local candidate-discovery layer. It is fast, includes open and closed threads, and can surface duplicate attempts, related issues, and already-landed fixes. It is not the final source of truth for comments, labels, merges, closes, or current CI.
## Default Flow
1. Check local state:
```bash
gitcrawl doctor --json
```
2. Read the target from the local archive:
```bash
gitcrawl threads openclaw/openclaw --numbers <issue-or-pr-number> --include-closed --json
```
3. Find related candidates:
```bash
gitcrawl neighbors openclaw/openclaw --number <issue-or-pr-number> --limit 12 --json
gitcrawl search openclaw/openclaw --query "<scope or title keywords>" --mode hybrid --limit 20 --json
```
4. Inspect relevant clusters:
```bash
gitcrawl cluster-detail openclaw/openclaw --id <cluster-id> --member-limit 20 --body-chars 280 --json
```
5. Verify anything actionable with live GitHub and the checkout:
```bash
gh pr view <number> --json number,title,state,mergedAt,body,files,comments,reviews,statusCheckRollup
gh issue view <number> --json number,title,state,body,comments,closedAt
```
## Freshness Rules
- Treat `gitcrawl` as stale if `doctor` shows no target thread, an old `last_sync_at`, missing embeddings for neighbor/search commands, or a clearly wrong open/closed state.
- If stale data blocks the decision, refresh the portable store first:
```bash
gitcrawl init --portable-store git@github.com:openclaw/gitcrawl-store.git --json
```
- Run expensive update commands such as `gitcrawl sync --include-comments` only when the user asked to update the local store or stale data is blocking the decision.
- The sync default is all GitHub thread states; pass `--state open`, `--state closed`, or `--state all` only when a task requires a narrower or explicit scope.
## Boundaries
- Use `gitcrawl` for candidates, clusters, and historical context.
- Use `gh`, `gh api`, and the current checkout for live state before commenting, labeling, closing, reopening, merging, or filing a PR review.
- Do not close or label based only on `gitcrawl` similarity. Require matching problem intent plus live verification.
- If `gitcrawl` is unavailable, say so and fall back to targeted `gh search` rather than blocking normal maintainer work.

View File

@@ -0,0 +1,4 @@
interface:
display_name: "Gitcrawl"
short_description: "Search local OpenClaw issue and PR history before live GitHub triage"
default_prompt: "Use $gitcrawl to inspect OpenClaw issue and PR history, find related threads and duplicate candidates, then verify actionable decisions with live GitHub."

View File

@@ -1,6 +1,6 @@
---
name: openclaw-ghsa-maintainer
description: Maintainer workflow for OpenClaw GitHub Security Advisories (GHSA). Use when Codex needs to inspect, patch, validate, or publish a repo advisory, verify private-fork state, prepare advisory Markdown or JSON payloads safely, handle GHSA API-specific publish constraints, or confirm advisory publish success.
description: Inspect, patch, validate, publish, or confirm OpenClaw GHSA security advisories and private-fork state.
---
# OpenClaw GHSA Maintainer

View File

@@ -1,6 +1,6 @@
---
name: openclaw-parallels-smoke
description: End-to-end Parallels smoke, upgrade, and rerun workflow for OpenClaw across macOS, Windows, and Linux guests. Use when Codex needs to run, rerun, debug, or interpret VM-based install, onboarding, gateway smoke tests, latest-release-to-main upgrade checks, fresh snapshot retests, or optional Discord roundtrip verification under Parallels.
description: Run, rerun, debug, or interpret OpenClaw Parallels install, onboarding, gateway smoke, and upgrade checks.
---
# OpenClaw Parallels Smoke
@@ -45,6 +45,9 @@ Use this skill for Parallels guest workflows and smoke interpretation. Do not lo
## npm install then update
- Preferred entrypoint: `pnpm test:parallels:npm-update`
- For a macOS-only published release update check, use:
- `timeout --foreground 75m pnpm test:parallels:npm-update -- --platform macos --package-spec openclaw@<old-version> --update-target <target-version-or-tag> --json`
This keeps the same-guest `openclaw update --tag ...` coverage and uses the shared macOS current-user/sudo fallback without starting Windows/Linux lanes.
- Required coverage: every release/update regression run must include both lanes:
- fresh snapshot -> install requested package/baseline -> smoke
- same guest baseline -> run the guest's installed `openclaw update ...` command -> smoke again
@@ -75,6 +78,7 @@ Use this skill for Parallels guest workflows and smoke interpretation. Do not lo
## macOS flow
- Preferred entrypoint: `pnpm test:parallels:macos`
- `parallels-macos-smoke.sh --mode fresh --target-package-spec openclaw@<version>` is an install smoke only. For published old-version -> new-version update coverage on macOS, prefer the npm-update wrapper with `--platform macos`; `parallels-macos-smoke.sh --mode upgrade --target-package-spec ...` installs the target package and does not exercise the baseline CLI's updater.
- Default upgrade coverage on macOS should now include: fresh snapshot -> site installer pinned to the latest stable tag -> `openclaw update --channel dev` on the guest. Treat this as part of the default Tahoe regression plan, not an optional side quest.
- `parallels-macos-smoke.sh --mode upgrade` should run that release-to-dev lane by default. Keep the older host-tgz upgrade path only when the caller explicitly passes `--target-package-spec`.
- Because the default upgrade lane no longer needs a host tgz, skip `npm pack` + host HTTP server startup for `--mode upgrade` unless `--target-package-spec` is set. Keep the pack/server path for `fresh` and `both`.
@@ -144,6 +148,7 @@ Use this skill for Parallels guest workflows and smoke interpretation. Do not lo
- `--discord-token-env`
- `--discord-guild-id`
- `--discord-channel-id`
- After a successful Discord smoke/roundtrip, shut down the guest VM before handoff (`prlctl stop "$VM_NAME"` or the concrete VM name). The macOS smoke harness should do this automatically after successful Discord proof; still stop the VM manually after ad-hoc Discord checks. Do not leave the Discord-configured guest running; it can keep reading/posting in `#maintainer` and spam Discord after the proof is complete.
- Keep the Discord token only in a host env var.
- Use installed `openclaw message send/read`, not `node openclaw.mjs message ...`.
- Set `channels.discord.guilds` as one JSON object, not dotted config paths with snowflakes.

View File

@@ -1,12 +1,29 @@
---
name: openclaw-pr-maintainer
description: Maintainer workflow for reviewing, triaging, preparing, closing, or landing OpenClaw pull requests and related issues. Use when Codex needs to validate bug-fix claims, search for related issues or PRs, apply or recommend close/reason labels, prepare GitHub comments safely, check review-thread follow-up, or perform maintainer-style PR decision making before merge or closure.
description: Review, triage, close, label, comment on, or land OpenClaw PRs/issues with maintainer evidence checks.
---
# OpenClaw PR Maintainer
Use this skill for maintainer-facing GitHub workflow, not for ordinary code changes.
## Start issue and PR triage with gitcrawl
- Use `$gitcrawl` first anytime you inspect OpenClaw issues or PRs.
- Check local `gitcrawl` data first for related threads, duplicate attempts, and already-landed fixes.
- Use `gitcrawl` for candidate discovery and clustering; use `gh`, `gh api`, and the current checkout to verify live state before commenting, labeling, closing, or landing.
- If `gitcrawl` is missing, stale, lacks the target thread, or has no embeddings for neighbor/search commands, fall back to the GitHub search workflow below.
- Do not run expensive/update commands such as `gitcrawl sync --include-comments`, future enrichment commands, or broad reclustering unless the user asked to update the local store or stale data is blocking the decision.
Common read-only path:
```bash
gitcrawl threads openclaw/openclaw --numbers <issue-or-pr-number> --include-closed --json
gitcrawl neighbors openclaw/openclaw --number <issue-or-pr-number> --limit 12 --json
gitcrawl search openclaw/openclaw --query "<scope or title keywords>" --mode hybrid --json
gitcrawl cluster-detail openclaw/openclaw --id <cluster-id> --member-limit 20 --body-chars 280 --json
```
## Apply close and triage labels correctly
- If an issue or PR matches an auto-close reason, apply the label and let `.github/workflows/auto-response.yml` handle the comment/close/lock flow.
@@ -35,6 +52,21 @@ Use this skill for maintainer-facing GitHub workflow, not for ordinary code chan
- If the claim is unsubstantiated or likely wrong, request evidence or changes instead of merging.
- If the linked issue appears outdated or incorrect, correct triage first. Do not merge a speculative fix.
## Close low-signal manual PRs carefully
- Do not close for red CI alone. Require a clear low-signal category plus stale or failed validation.
- Good manual-close categories:
- blank or mostly untouched PR template with no concrete OpenClaw problem/fix
- random docs-only churn such as root README translations, generic wording tweaks, or community-plugin discoverability docs that should go through ClawHub
- test-only coverage without a linked bug, owner request, or behavior change
- refactor-only cleanup, variable renames, formatting, or generated/baseline churn without maintainer request
- third-party channel/provider/tool/skill/plugin work that belongs on ClawHub instead of core
- risky ops/infra drive-bys such as new external CI services, release workflows, host upgrade scripts, Docker base migrations, or apt retry/fix-missing tweaks without owner request and green validation
- dirty branches where a narrow stated change includes unrelated docs/generated/runtime/extension files
- repeated bot-review spam or copied bot output without author-owned fixes
- Keep or escalate plausible focused bug fixes, green PRs, active maintainer discussions, assigned work, recent author follow-up, and unique reproduction details.
- For third-party capabilities, prefer the `r: third-party-extension` auto-response label when it applies; it points contributors to publish on ClawHub.
## Handle GitHub text safely
- For issue comments and PR comments, use literal multiline strings or `-F - <<'EOF'` for real newlines. Never embed `\n`.
@@ -44,9 +76,9 @@ Use this skill for maintainer-facing GitHub workflow, not for ordinary code chan
## Search broadly before deciding
- Prefer targeted keyword search before proposing new work or closing something as duplicate.
- Use `--repo openclaw/openclaw` with `--match title,body` first.
- Add `--match comments` when triaging follow-up discussion.
- Prefer `gitcrawl` first. Then use targeted GitHub keyword search to verify gaps, live status, comments, and candidates not present in the local store.
- Use `--repo openclaw/openclaw` with `--match title,body` first when using `gh search`.
- Add `--match comments` when triaging follow-up discussion or closed-as-duplicate chains.
- Do not stop at the first 500 results when the task requires a full search.
Examples:
@@ -68,6 +100,7 @@ gh search issues --repo openclaw/openclaw --match title,body --limit 50 \
- Keep commit messages concise and action-oriented.
- Group related changes; avoid bundling unrelated refactors.
- Use `.github/pull_request_template.md` for PR submissions and `.github/ISSUE_TEMPLATE/` for issues.
- Do not commit PR-only artifacts such as screenshots under `.github/pr-assets`; attach them to the PR/comment or use an external artifact store instead.
## Extra safety

View File

@@ -0,0 +1,234 @@
---
name: openclaw-pre-release-plugin-testing
description: Plan and run pre-release OpenClaw plugin validation across bundled plugins, package artifacts, lifecycle commands, doctor/fix, config round-trip, gateway startup, SDK compatibility, Docker E2E, Package Acceptance, and Testbox proof.
---
# OpenClaw Pre-Release Plugin Testing
Use this skill when the user asks for plugin release confidence, plugin lifecycle
sweeps, package-artifact plugin proof, or "what else should we test before
release?" It complements `openclaw-testing`; use that skill too when choosing
the cheapest safe runner or debugging a failing lane.
## Goal
Prove the plugin system as a product surface, not just as source tests:
- bundled plugin lifecycle: install, inspect, enable, disable, uninstall
- package artifact behavior from a clean `HOME`
- doctor/fix/config validation and idempotence
- config discovery and config round-trip
- status/log visibility and diagnostics
- gateway startup/bootstrap with plugin metadata snapshots
- public SDK compatibility for real external plugins
- live-ish provider/channel probes only when safe credentials exist
## First Checks
From the OpenClaw repo root:
```bash
pnpm docs:list
git status --short --branch
readlink node_modules
pnpm changed:lanes --json
```
In Codex worktrees under `.codex/worktrees`, `node_modules` must be a symlink to
the main OpenClaw checkout. Do not run `pnpm install` there. For broad or
package-heavy proof, use Blacksmith Testbox or GitHub Actions.
## Runner Choice
Prefer this order:
1. **GitHub Package Acceptance** for installable-package product proof.
2. **`ci-build-artifacts-testbox.yml` Testbox** when Docker/package lanes need
seeded `dist`, `dist-runtime`, and package caches.
3. **`ci-check-testbox.yml` Testbox** for source checks, targeted Vitest,
package-boundary checks, or focused Docker lanes.
4. **Local targeted commands only** for small format/static/unit probes.
Avoid long package Docker runs from a stale sparse worktree. If Testbox sync
reports hundreds of changed files or starts deleting package inputs, stop and
warm a fresh box from current `main`, or switch to Package Acceptance.
## Existing Baseline
Run or verify these before inventing new coverage:
```bash
OPENCLAW_TESTBOX=1 pnpm check:changed
pnpm run test:extensions:package-boundary:canary
pnpm run test:extensions:package-boundary:compile
pnpm test:docker:plugins
OPENCLAW_PLUGINS_E2E_CLAWHUB=0 pnpm test:docker:plugins
pnpm test:docker:plugin-update
pnpm test:docker:bundled-channel-deps:fast
```
For full bundled install/uninstall proof, shard the packaged sweep:
```bash
OPENCLAW_BUNDLED_PLUGIN_SWEEP_TOTAL=8 \
OPENCLAW_BUNDLED_PLUGIN_SWEEP_INDEX=<0-7> \
pnpm test:docker:bundled-plugin-install-uninstall
```
Expected current packaged scope: 116 public bundled plugins over shards `0-7`.
Private QA plugins are source-mode only unless a package explicitly includes
them.
## Confidence Matrix
Use this matrix for pre-release signoff. Record pass/fail, run URL/Testbox ID,
package SHA/version, and skipped-live reason.
| Surface | Proof | Preferred runner |
| --- | --- | --- |
| Package artifact | Package Acceptance `suite_profile=package` or custom lanes | GitHub Actions |
| Bundled lifecycle | 8-shard `test:docker:bundled-plugin-install-uninstall` | Testbox or release Docker |
| External plugins | `test:docker:plugins` and `plugins-offline` | Testbox/package acceptance |
| Update no-op | `test:docker:plugin-update` | Testbox/package acceptance |
| Channel runtime deps | `test:docker:bundled-channel-deps:fast` plus key channels | Testbox/package acceptance |
| Doctor/fix | seeded bad configs + `doctor --fix --non-interactive` | new Docker/Testbox harness |
| Config round-trip | `config set/get`, inspect, doctor, reload, diff hash | new Docker/Testbox harness |
| Gateway bootstrap | clean `HOME`, plugin groups enabled/disabled, status JSON | new Docker/Testbox harness |
| SDK compatibility | directory, tgz, and `file:` external plugins using SDK subpaths | `test:docker:plugins` plus new smoke |
| Live-ish | redacted provider/channel probes only for present env | Testbox live lanes |
## Package Acceptance Plan
Use this when validating a release branch, beta, or candidate package:
```bash
gh workflow run package-acceptance.yml \
--repo openclaw/openclaw \
--ref main \
-f workflow_ref=main \
-f source=ref \
-f package_ref=<branch-or-sha> \
-f suite_profile=custom \
-f docker_lanes='plugins-offline plugin-update bundled-channel-deps-compat doctor-switch update-channel-switch config-reload mcp-channels npm-onboard-channel-agent' \
-f telegram_mode=mock-openai
```
Use `source=npm -f package_spec=openclaw@beta` for published beta proof. Keep
`workflow_ref` as trusted current harness code unless the release process says
otherwise.
## New Testbox Harness Plan
If more certainty is needed, add or run a `plugin-lifecycle-matrix` Docker lane
that uses one package tarball and sharded plugin lists. Per plugin:
1. Start with a clean `HOME`.
2. Capture `plugins list --json`.
3. `plugins install <id>`.
4. `plugins inspect <id> --json`.
5. `plugins disable <id>`, then assert disabled visibility.
6. `plugins enable <id>`, except config-required plugins without config.
7. `plugins registry --refresh`.
8. `doctor --non-interactive`.
9. `plugins uninstall <id> --force`.
10. Assert no config entry, allow/deny residue, install record, managed dir, or
bundled `dist/extensions/...` load path remains.
11. Assert diagnostics contain no `level: "error"` and output redacts
secret-looking values.
Keep `memory-lancedb` special: it is config-required. First assert install does
not enable it without embedding config, then run a second configured case.
## Doctor/Fix Matrix
Seed bad states and require `doctor --fix --non-interactive` to repair them,
then run doctor again and require idempotence:
- stale `plugins.allow`
- stale `plugins.entries`
- stale channel config for missing channel plugin
- invalid `plugins.entries.<id>.config`
- packaged bundled path in `plugins.load.paths`
- legacy `plugins.installs`
- disabled channel/plugin config that must not stage runtime deps
- root-owned global package tree that must remain unmodified
## Gateway Bootstrap Matrix
Start packaged OpenClaw in Docker with clean state:
- provider plugins enabled, no credentials: ready with warnings, no crash
- channel plugins configured disabled: no runtime deps staged
- startup-activation plugins enabled: ready and reflected in status
- invalid single plugin config: bad plugin skipped/quarantined, others remain
Assert:
- gateway reaches ready
- `openclaw status --json` includes plugin diagnostics
- `openclaw plugins inspect --all --json` is parseable
- package tree is not mutated
- logs contain no raw tokens
## Config Round-Trip Representatives
Use representative plugin families instead of every plugin for deep config
round-trip:
- providers: `openai`, `anthropic`, `mistral`, `openrouter`
- channels: `telegram`, `discord`, `slack`, `whatsapp`
- memory: `memory-lancedb`
- feature/runtime: `browser`, `acpx`, `tokenjuice`
For each representative:
1. Write config through CLI when possible.
2. Read it back through `config get` or JSON.
3. Run `plugins inspect`.
4. Run `doctor --non-interactive`.
5. Trigger gateway config reload if applicable.
6. Compare config hash before/after no-op commands.
## External SDK Smoke
In a package Docker lane, create tiny external plugins and install them from:
- local directory
- `.tgz`
- `file:` npm spec
Cover CJS and ESM shapes, plus at least one plugin importing focused
`openclaw/plugin-sdk/*` subpaths. Assert `plugins inspect` sees its tool,
gateway method, CLI command, or service.
## Live-Ish Probe Rules
Before live-ish work, source allowed env in Testbox and generate a redacted
availability matrix: present/missing only, never values.
Only run probes for credentials that exist. Prefer auth/catalog/status probes
over sending user-visible messages. If a probe might contact an external user,
channel, or workspace, stop and ask the user.
## Reporting
Report in this shape:
```text
package/ref:
tbx ids / run urls:
matrix:
bundled lifecycle:
package acceptance:
doctor/fix:
gateway bootstrap:
config round-trip:
sdk external:
live-ish:
failures:
skips:
next highest-value gap:
```
Say clearly when a failure is Testbox sync/env damage rather than product
behavior, and prove that with a clean rerun or current-main comparison.

View File

@@ -0,0 +1,4 @@
interface:
display_name: "OpenClaw Plugin Pre-Release Testing"
short_description: "Plan plugin release validation"
default_prompt: "Use $openclaw-pre-release-plugin-testing to plan or run pre-release OpenClaw plugin validation across package, lifecycle, doctor, gateway, SDK, and live-ish proof."

View File

@@ -1,6 +1,6 @@
---
name: openclaw-qa-testing
description: Run, watch, debug, and extend OpenClaw QA testing with qa-lab and qa-channel. Use when Codex needs to execute the repo-backed QA suite, inspect live QA artifacts, debug failing scenarios, add new QA scenarios, or explain the OpenClaw QA workflow. Prefer the live OpenAI lane with regular openai/gpt-5.4 in fast mode; do not use gpt-5.4-pro or gpt-5.4-mini unless the user explicitly overrides that policy.
description: Run, watch, debug, extend, or explain OpenClaw qa-lab and qa-channel scenarios, artifacts, and live lanes.
---
# OpenClaw QA Testing
@@ -49,6 +49,97 @@ pnpm openclaw qa suite \
5. If the user wants to watch the live UI, find the current `openclaw-qa` listen port and report `http://127.0.0.1:<port>`.
6. If a scenario fails, fix the product or harness root cause, then rerun the full lane.
## OTEL smoke
For local QA-lab OpenTelemetry validation, use:
```bash
pnpm qa:otel:smoke
```
This starts a local OTLP/HTTP trace receiver, runs the `otel-trace-smoke`
scenario through qa-channel, decodes the emitted protobuf spans, and verifies
the exported trace names and privacy contract. It does not require Opik,
Langfuse, or external collector credentials.
## Matrix live profiles
`pnpm openclaw qa matrix` defaults to the full `all` profile. Use explicit
profiles for faster CI/release proof:
```bash
OPENCLAW_QA_MATRIX_NO_REPLY_WINDOW_MS=3000 \
pnpm openclaw qa matrix --profile fast --fail-fast
```
- `fast`: release-critical transport contract, excluding generated image and
deep E2EE recovery inventory.
- `transport`, `media`, `e2ee-smoke`, `e2ee-deep`, `e2ee-cli`: sharded full
Matrix coverage.
- `QA-Lab - All Lanes` uses explicit `fast` Matrix on scheduled runs. Manual
dispatch keeps `matrix_profile=all` as the default and always shards that full
Matrix selection.
## QA credentials and 1Password
- Use `op` only inside `tmux` for QA secret lookup in this repo.
- Quick auth check inside tmux:
```bash
op account list
```
- Direct Telegram npm live test secrets currently live in 1Password item:
- vault: `OpenClaw`
- item: `Telegram E2E`
- That item is the first place to look for:
- `OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN`
- `OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`
- `OPENCLAW_QA_PROVIDER_MODE`
- `OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC`
- Convex QA secrets currently live in 1Password items:
- vault: `OpenClaw`
- item: `OPENCLAW_QA_CONVEX_SITE_URL`
- item: `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER`
- item: `OPENCLAW_QA_CONVEX_SECRET_CI`
- Additional related notes/login items seen during QA credential work:
- vault: `Private`
- items: `OPENCLAW QA`, `Convex`, `Telegram`
- If a required value is missing from those notes:
- do not guess
- ask the maintainer/operator for the current value or the current 1Password item name
- for Telegram direct runs, `OPENCLAW_QA_TELEGRAM_GROUP_ID` may be stored separately from `Telegram E2E`
- for Convex runs, the leased Telegram credential should provide the Telegram group id and bot tokens together; do not require a separate `OPENCLAW_QA_TELEGRAM_GROUP_ID`
- for Convex runs, prefer `OpenClaw/OPENCLAW_QA_CONVEX_SITE_URL`; if that is stale or unclear, ask for the active pool URL before running
- Prefer direct Telegram envs for the npm Telegram Docker lane when available:
```bash
OPENCLAW_QA_TELEGRAM_GROUP_ID="..." \
OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN="..." \
OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN="..." \
OPENCLAW_QA_PROVIDER_MODE="mock-openai" \
OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC="openclaw@beta" \
pnpm test:docker:npm-telegram-live
```
- Prefer Convex mode when the goal is stable shared QA infra:
- round-robin credential leasing
- thinner wrapper for channel-specific setup
- CLI/admin flows around the pooled credentials
- Live npm Telegram Docker lane note:
- `scripts/e2e/npm-telegram-live-runner.ts` reads `OPENCLAW_NPM_TELEGRAM_PROVIDER_MODE`
- do not assume `OPENCLAW_QA_PROVIDER_MODE` is consumed by that wrapper
- if a 1Password note only gives `OPENCLAW_QA_PROVIDER_MODE`, map it explicitly to `OPENCLAW_NPM_TELEGRAM_PROVIDER_MODE` before running the Docker lane
- Verified live shape:
- Convex mode can pass the real Docker lane without direct Telegram env vars
- leased Telegram payload includes the group id coupled to the driver/SUT tokens
- a real run of `pnpm test:docker:npm-telegram-live` passed with:
- `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`
- `OPENCLAW_QA_CREDENTIAL_ROLE=maintainer`
- `OPENCLAW_QA_CONVEX_SITE_URL`
- `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER`
- `OPENCLAW_NPM_TELEGRAM_PROVIDER_MODE=mock-openai`
## Character evals
Use `qa character-eval` for style/persona/vibe checks across multiple live models.

View File

@@ -1,6 +1,6 @@
---
name: openclaw-release-maintainer
description: Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.
description: Prepare or verify OpenClaw stable/beta releases, changelogs, release notes, publish commands, and artifacts.
---
# OpenClaw Release Maintainer
@@ -25,15 +25,36 @@ Use this skill for release and publish-time workflow. Keep ordinary development
- Before release branching, commit any dirty files in coherent groups, push,
pull/rebase, then run `/changelog` on `main` and commit/push/pull that
changelog rewrite immediately before creating the release branch.
- During release planning, inspect both `src/plugins/compat/registry.ts` and
`src/commands/doctor/shared/deprecation-compat.ts` before branching and again
before final publish. For every deprecated or removal-pending compatibility
record whose `removeAfter` date is on or before the release date, either
remove the compatibility path where safe and validate the affected tests, or
write down why removal is blocked and get explicit maintainer approval before
shipping the expired compatibility path.
- When removing deprecated runtime/config compatibility, preserve any doctor
migration, repair, or hint that is still needed by supported upgrade paths.
Doctor-side compatibility should stay tracked in
`src/commands/doctor/shared/deprecation-compat.ts` until maintainers confirm
the repair is no longer needed.
- Revalidate compatibility replacement text during release planning. The
recommended replacement can shift as plugin ownership, externalization, and
config footprint move, so do not blindly copy stale replacement annotations
into release notes.
- Do not delete or rewrite beta tags after they leave the machine. If a
published or pushed 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 full pre-npm test roster before publishing
each beta. After a beta is published, run the smaller published-install roster
focused on install/update/Docker/Parallels. If anything fails, fix it on the
release branch, commit/push/pull, increment beta number, and repeat. Operators
may authorize up to 4 autonomous beta attempts; after 4 failed beta attempts,
stop and report.
- 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.
- Use `/changelog` before version/tag preparation so the top changelog section
is deduped and ordered by user impact.
- Do not create beta-specific `CHANGELOG.md` headings. Beta releases use the
@@ -70,6 +91,27 @@ Use this skill for release and publish-time workflow. Keep ordinary development
- 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.
- 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
npm install/update, Docker, and Parallels verification while mac artifacts
continue.
- After a beta is published, overlap remote/manual release rosters where useful,
but avoid piling local Docker, Parallels, and QA-Lab work onto the same host
when it would create system-load noise. Use selective reruns after failures or
fixes, but keep proof that Docker, Parallels, and QA-Lab each passed at least
once before stable/latest promotion.
- Mac packaging may be built from a slight release-branch variation of the
tagged commit when the delta is mac packaging, signing, workflow, or
validation-only release machinery. If mac packaging needs release-branch-only
fixes after the stable npm package or GitHub tag is already published, do not
create a `vYYYY.M.D-N` correction tag just to change the workflow source.
Dispatch the private mac workflows for the original `tag=vYYYY.M.D` with
`source_ref=release/YYYY.M.D` and `public_release_branch=release/YYYY.M.D`;
provenance checks must prove the source SHA descends from the tag and
validation/preflight use the same source. Reserve `vYYYY.M.D-N` correction
tags for emergency hotfixes that must publish a new npm package/release
identity, not for ordinary mac-only packaging recovery.
- The production Sparkle feed lives at `https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml`, and the canonical published file is `appcast.xml` on `main` in the `openclaw` repo.
- That shared production Sparkle feed is stable-only. Beta mac releases may
upload assets to the GitHub prerelease, but they must not replace the shared
@@ -81,7 +123,23 @@ Use this skill for release and publish-time workflow. Keep ordinary development
## Build changelog-backed release notes
- Before release branching or tagging, rewrite the target `CHANGELOG.md`
section from commit history, not just from existing notes: scan commits since
the last reachable release tag, add missed user-facing changes, dedupe
overlapping entries, and sort each section from most to least interesting for
users.
- Changelog entries should be user-facing, not internal release-process notes.
- GitHub release and prerelease bodies must use the full matching
`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.
- 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.
Add an `Upcoming deprecations` note to the release notes when any exist,
including the compatibility code, target date, replacement, and a link to the
record's `docsPath` or `/plugins/compatibility` when no more specific
deprecation page exists.
- When cutting a mac release with a beta GitHub prerelease:
- tag `vYYYY.M.D-beta.N` from the release commit
- create a prerelease titled `openclaw YYYY.M.D-beta.N`
@@ -104,14 +162,36 @@ live`; keep it clearly beta and avoid implying stable promotion.
- Lead with user-visible capabilities, then important integrations, then
reliability/security/install fixes. Compress "lots of fixes" into one
readable bullet.
- Read the full changelog section before drafting. Do not lead with coverage,
CI, validation, or internal release mechanics unless the release is explicitly
about those. Peter prefers concrete user wins: features, integrations,
workflow improvements, and practical reliability fixes.
- Tone: high-signal, slightly cheeky, confident, not corporate. One joke is
enough. Avoid punching down, insulting users, or promising what was not
verified.
- Length: release tweets are always standard tweets under 280 characters. Trim
to 3-4 bullets and count the final text before posting.
- Links/media: include the GitHub release or changelog link at the end. Add a
short docs follow-up reply only when there is a standout feature that needs
setup instructions.
- Peter likes dry, compact taglines when they feel earned. Good example:
`Big release, tiny release notes... kidding.` Keep the joke short and let the
feature bullets carry the tweet; do not turn the punchline into a second
paragraph or a forced bit.
- Length: release tweets are always standard tweets under 280 characters, with
room for one URL. Trim to 3-4 bullets and count the final text before posting.
- Links/media: include the GitHub release or changelog link at the end of the
first release tweet.
- Thread follow-ups: if doing a thread, keep the first release tweet as the
compact launch post, then publish one focused feature explainer per reply.
Follow-up replies should not repeat "new in VERSION" or the version number
when the thread context already makes it obvious.
- Peter's preferred thread workflow: first agree on the generic launch tweet,
then proceed through follow-up tweets one by one. When he says `next`, provide
or copy the next follow-up only; do not dump the full thread again unless asked.
- Every follow-up tweet should include a docs URL for that specific feature.
Prefer a bare URL over `Docs: <url>` unless the label is needed for clarity.
Keep follow-ups concise: around 160-220 raw characters is usually the sweet
spot; under 280 is the hard cap. If a URL makes a tweet fail, trim prose
before dropping the URL.
Prefer explaining diagnostics, trajectory/export, provider setup, model
commands, or other setup-heavy features in follow-ups instead of overloading
the first release tweet.
- Hotfix/correction: be direct and accountable. State what slipped, what is
fixed, and the new version. Keep jokes out of incident-style posts.
@@ -158,10 +238,16 @@ Before tagging or publishing, run:
pnpm check:architecture
pnpm build
pnpm ui:build
pnpm qa:otel:smoke
pnpm release:check
pnpm test:install:smoke
```
- Use `pnpm qa:otel:smoke` when release validation needs telemetry coverage.
It starts a local OTLP/HTTP trace receiver, runs QA-lab's
`otel-trace-smoke`, and checks span names plus content/identifier redaction
without external Opik or Langfuse credentials.
For a non-root smoke path:
```bash
@@ -201,9 +287,18 @@ node --import tsx scripts/openclaw-npm-postpublish-verify.ts <published-version>
- Source Peter's profile before live release validation so OpenAI and Anthropic
credentials are available without printing secrets:
`set -a; source "$HOME/.profile"; set +a`.
- Release QA and Parallels validation for this train must use both
- Parallels validation and any local live model QA for this train must use both
`OPENAI_API_KEY` and `ANTHROPIC_API_KEY`. If either is missing after sourcing
`.profile`, stop before starting the long lanes and report the missing key.
`.profile`, stop before starting those local long lanes and report the
missing key.
- Live credentialed channel QA is the GitHub Actions workflow
`QA-Lab - All Lanes` (`.github/workflows/qa-live-telegram-convex.yml`), not a
local substitute. Dispatch it from Actions against the release tag and wait
for it to pass before npm preflight/publish readiness. Use a SHA only when it
satisfies the workflow's secret-bearing trust gate: main ancestor or open PR
head. It runs the QA Lab mock parity gate plus live Matrix and live Telegram
lanes using the `qa-live-shared` environment; Telegram uses Convex CI
credential leases.
- Default release checks:
- `pnpm check`
- `pnpm check:test-types`
@@ -221,23 +316,44 @@ node --import tsx scripts/openclaw-npm-postpublish-verify.ts <published-version>
- all Parallels install/update tests:
`pnpm test:parallels:npm-update -- --json` plus any needed individual
rerun lanes from `openclaw-parallels-smoke`
- all QA release validation:
OpenAI live suite with `openai/gpt-5.4` in fast mode, Anthropic live suite
with `anthropic/claude-opus-4-6`, and the repo-backed character evals
- all QA release validation: dispatch GitHub Actions > `QA-Lab - All Lanes`
against the release tag and require success. This is the release gate for
live credentialed Matrix/Telegram channel coverage. Use a SHA only when it
satisfies the workflow trust gate. Run local OpenAI/Anthropic suites or
repo-backed character evals only when the operator asks for extra model
coverage or a failure needs local debugging.
- Post-published beta verification roster:
- `node --import tsx scripts/openclaw-npm-postpublish-verify.ts <beta-version>`
- install/update smoke against the published beta channel
- Docker install/update coverage that exercises the published beta package
- published npm Telegram proof: dispatch Actions > `NPM Telegram Beta E2E`
from `main` with `package_spec=openclaw@<beta-version>` and
`provider_mode=mock-openai`, and require success. This workflow is
maintainer-dispatched and intentionally has no `npm-release` approval gate;
`qa-live-shared` only supplies the shared QA secrets. This is the default
button path for installed-package onboarding, Telegram setup, and real
Telegram E2E against the published npm package.
Use the local `pnpm test:docker:npm-telegram-live` lane with the matching
`OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC` and Convex CI env only as a fallback
or debugging path.
- Parallels published beta install/update coverage with both OpenAI and
Anthropic provider keys available
- Parallels install/update proof must keep plugin installs enabled unless the
operator explicitly scopes a harness-only isolation check; a lane that
disables bundled plugin installs is not valid plugin/dependency release
evidence.
- targeted QA reruns only for areas touched by fixes after the full pre-npm
roster, unless the operator requests the full QA roster again
roster, unless the operator requests the full QA roster again. If the fix
touches live channel QA, credential plumbing, Matrix, Telegram, or the QA
harness, rerun Actions > `QA-Lab - All Lanes`.
- Check all release-related build surfaces touched by the release, not only the npm package.
- For beta-style full e2e batteries, hard-cap top-level long lanes instead of letting them run indefinitely. Use host `timeout --foreground`/`gtimeout --foreground` caps such as:
- `45m` for `OPENCLAW_INSTALL_SMOKE_SKIP_NONROOT=1 pnpm test:install:smoke`
- `90m` for `pnpm test:docker:all`
- `60m` each for standalone Docker live lanes
- `180m` for the full QA live OpenAI + Anthropic roster
- `180m` for local full QA live OpenAI + Anthropic rosters when explicitly
requested; the default release channel QA gate is Actions >
`QA-Lab - All Lanes`
- Parallels caps from the `openclaw-parallels-smoke` skill
If a lane hits its cap, stop and inspect/fix the affected lane before continuing; do not continue to wait on the same process.
- Actual npm install/update phases are capped at 5 minutes. If `npm install -g`, installer package install, or `openclaw update` takes longer than 300s in release e2e, stop treating the run as healthy progress and debug the installer/updater or harness.
@@ -257,7 +373,14 @@ node --import tsx scripts/openclaw-npm-postpublish-verify.ts <published-version>
public release assets so the updater feed cannot lag the published binaries.
- Serialize stable appcast-producing runs across tags so two releases do not
generate replacement `appcast.xml` files from the same stale seed.
- For stable releases, confirm the latest beta already passed the broader release workflows before cutting stable.
- For stable releases, rely primarily on the latest beta's broader release
workflow confidence. When promoting the matching non-beta build to npm
`latest`, prefer a light time-bounded verification pass: published npm
postpublish verify, Docker install/update smoke, macOS-only Parallels
install/update smoke, and required QA signal. Do not rerun the full
Docker/Parallels matrix unless the beta evidence is stale, the stable build
differs materially from beta, or the operator explicitly asks for full
retesting.
- If any required build, packaging step, or release workflow is red, do not say the release is ready.
## Use the right auth flow
@@ -267,6 +390,29 @@ node --import tsx scripts/openclaw-npm-postpublish-verify.ts <published-version>
`openclaw/releases-private/.github/workflows/openclaw-npm-dist-tags.yml`
workflow because `npm dist-tag` management needs `NPM_TOKEN`, while the
public npm release workflow stays OIDC-only.
- Prefer fixing the private workflow token path over any local 1Password
fallback. The desired setup is a granular npm token stored as the private
repo's `NPM_TOKEN` secret, scoped to the `openclaw` package with read/write
and 2FA bypass for automation.
- If the private dist-tag workflow cannot promote because `NPM_TOKEN` is absent
or stale, use the local tmux + 1Password fallback:
- Start or reuse a tmux session so interactive `npm login` and OTP prompts
are observable and recoverable.
- Hard rule: never run `op` directly in the main agent shell during release
work. Any 1Password CLI use must happen inside that tmux session so prompts
and alerts are contained and observable.
- Use the 1Password item `op://Private/Npmjs` for npm credentials and OTP.
Do not print passwords, tokens, or OTPs to the transcript; send them through
tmux buffers, env vars scoped to the tmux command, or `expect` with
`log_user 0`.
- Re-authenticate npm inside that tmux session with
`npm login --auth-type=legacy`, then confirm `npm whoami` reports
`steipete`.
- Promote with a fresh OTP:
`npm dist-tag add openclaw@YYYY.M.D latest --otp "$OTP"`.
- Verify with a cache-bypassed registry read, for example:
`npm view openclaw dist-tags --json --prefer-online --cache /tmp/openclaw-npm-cache-verify-$$`
and `npm view openclaw@latest version dist.tarball --json --prefer-online`.
- Direct stable publishes can also use that private dist-tag workflow to point
`beta` at the already-published `latest` version when the operator wants both
tags aligned immediately.
@@ -383,73 +529,90 @@ node --import tsx scripts/openclaw-npm-postpublish-verify.ts <published-version>
6. Create `release/YYYY.M.D` from that post-changelog `main` commit.
7. Make every repo version location match the beta tag before creating it.
8. Commit release preparation changes on the release branch and push the branch.
9. Run the full pre-npm beta test roster from the release branch before any npm
preflight or publish.
9. Run the fast local beta preflight from the release branch before any npm
preflight or publish. Keep expensive Docker, Parallels, and published-package
install/update lanes for after the beta is live unless the operator asks to
run them before beta publication.
10. For beta releases, skip mac app build/sign/notarize unless beta scope or a
release blocker specifically requires it. For stable releases, include the
mac app, signing, notarization, and appcast path.
11. Confirm the target npm version is not already published.
12. Create and push the git tag from the release branch.
13. Create or refresh the matching GitHub release.
14. Start `.github/workflows/openclaw-npm-release.yml` from the release branch
14. Dispatch Actions > `QA-Lab - All Lanes` against the release tag and wait
for the mock parity, live Matrix, and live Telegram credentialed-channel
lanes to pass.
15. Start `.github/workflows/openclaw-npm-release.yml` from the release branch
with `preflight_only=true`
and choose the intended `npm_dist_tag` (`beta` default; `latest` only for
an intentional direct stable publish). Wait for it to pass. Save that run id
because the real publish requires it to reuse the prepared npm tarball.
15. For stable releases, start `.github/workflows/macos-release.yml` in
16. For stable releases, start `.github/workflows/macos-release.yml` in
`openclaw/openclaw` and wait for the public validation-only run to pass.
16. For stable releases, start
17. For stable releases, start
`openclaw/releases-private/.github/workflows/openclaw-macos-validate.yml`
with the same tag and wait for the private mac validation lane to pass.
17. For stable releases, start
18. For stable releases, start
`openclaw/releases-private/.github/workflows/openclaw-macos-publish.yml`
with `preflight_only=true` and wait for it to pass. Save that run id because
the real publish requires it to reuse the notarized mac artifacts.
18. If any preflight or validation run fails, fix the issue on a new commit,
19. If any preflight or validation run fails, fix the issue on a new commit,
delete the tag and matching GitHub release, recreate them from the fixed
commit, and rerun all relevant preflights from scratch before continuing.
Never reuse old preflight results after the commit changes. For pushed or
published beta tags, do not delete/recreate; increment to the next beta tag.
19. Start `.github/workflows/openclaw-npm-release.yml` from the same branch with
20. Start `.github/workflows/openclaw-npm-release.yml` from the same branch with
the same tag for the real publish, choose `npm_dist_tag` (`beta` default,
`latest` only when you intentionally want direct stable publish), keep it
the same as the preflight run, and pass the successful npm
`preflight_run_id`.
20. Wait for `npm-release` approval from `@openclaw/openclaw-release-managers`.
21. Run postpublish verification:
21. Wait for `npm-release` approval from `@openclaw/openclaw-release-managers`.
22. Run postpublish verification:
`node --import tsx scripts/openclaw-npm-postpublish-verify.ts <published-version>`.
22. Run the post-published beta verification roster. If any lane fails after
the beta tag/package is pushed or published, fix, commit/push/pull,
increment to the next beta tag, and restart at the full pre-npm beta test
roster for the new beta. If a pre-npm lane fails before any tag/package
leaves the machine, fix and rerun the same intended beta attempt. Repeat up
to the operator's authorized beta-attempt limit, normally 4.
23. Announce the beta/stable release on Discord best-effort using Peter's bot
23. Run the post-published beta verification roster. First scan current `main`
for critical fixes that landed after the release branch cut; backport only
important low-risk fixes before starting expensive lanes, or increment to
the next beta if the fix must change the already-published package. If any
lane fails after the beta tag/package is pushed or published, fix,
commit/push/pull, increment to the next beta tag, and rerun the affected
beta evidence. Once the beta is live, start remote/manual rosters where they
can overlap safely, but keep local Docker and Parallels load controlled.
Ensure the full expensive roster has passed at least once before
stable/latest promotion. The roster includes the manual Actions >
`NPM Telegram Beta E2E` workflow against the exact published beta package.
If a pre-npm lane fails before any tag/package leaves the machine, fix and
rerun the same intended beta attempt. Repeat up to the operator's
authorized beta-attempt limit, normally 4.
24. Announce the beta/stable release on Discord best-effort using Peter's bot
token from `.profile`.
24. If the operator requested beta only, stop after beta verification and the
25. If the operator requested beta only, stop after beta verification and the
announcement.
25. If the stable release was published to `beta`, start the private
26. If the stable release was published to `beta`, use the light stable
promotion roster when the matching beta already carried the full confidence
pass: published npm postpublish verify, Docker install/update smoke,
macOS-only Parallels install/update smoke, and required QA signal.
Then start the private
`openclaw/releases-private/.github/workflows/openclaw-npm-dist-tags.yml`
workflow after beta validation passes to promote that stable version from
`beta` to `latest`, then verify `latest` now points at that version.
26. If the stable release was published directly to `latest` and `beta` should
workflow to promote that stable version from `beta` to `latest`, then
verify `latest` now points at that version.
27. If the stable release was published directly to `latest` and `beta` should
follow it, start that same private dist-tag workflow to point `beta` at the
stable version, then verify both `latest` and `beta` point at that version.
27. For stable releases, start
28. For stable releases, start
`openclaw/releases-private/.github/workflows/openclaw-macos-publish.yml`
for the real publish with the successful private mac `preflight_run_id` and
wait for success.
28. Verify the successful real private mac run uploaded the `.zip`, `.dmg`,
29. Verify the successful real private mac run uploaded the `.zip`, `.dmg`,
and `.dSYM.zip` artifacts to the existing GitHub release in
`openclaw/openclaw`.
29. For stable releases, download `macos-appcast-<tag>` from the successful
30. For stable releases, download `macos-appcast-<tag>` from the successful
private mac run, update `appcast.xml` on `main`, and verify the feed. Merge
or cherry-pick release branch changes back to `main` after stable succeeds.
30. For beta releases, publish the mac assets only when intentionally requested;
31. For beta releases, publish the mac assets only when intentionally requested;
expect no shared production
`appcast.xml` artifact and do not update the shared production feed unless a
separate beta feed exists.
31. After publish, verify npm and the attached release artifacts.
32. After publish, verify npm and the attached release artifacts.
## GHSA advisory work

View File

@@ -1,6 +1,6 @@
---
name: openclaw-secret-scanning-maintainer
description: Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.
description: Triage, redact, clean up, and resolve OpenClaw GitHub Secret Scanning alerts in issues or PRs.
---
# OpenClaw Secret Scanning Maintainer

View File

@@ -1,6 +1,6 @@
---
name: openclaw-test-heap-leaks
description: Investigate `pnpm test` memory growth, Vitest worker OOMs, and suspicious RSS increases in OpenClaw using the `scripts/test-parallel.mjs` heap snapshot tooling. Use when Codex needs to reproduce test-lane memory growth, collect repeated `.heapsnapshot` files, compare snapshots from the same worker PID, triage likely transformed-module retention versus likely runtime leaks, and fix or reduce the impact by patching cleanup logic or isolating hotspot tests.
description: Investigate OpenClaw pnpm test memory growth, Vitest OOMs, RSS spikes, and heap snapshot deltas.
---
# OpenClaw Test Heap Leaks

View File

@@ -1,6 +1,6 @@
---
name: openclaw-test-performance
description: Benchmark, diagnose, and optimize OpenClaw test performance without losing coverage. Use when Codex needs to reassess `pnpm test`, compare grouped Vitest reports, identify CPU/memory/import hotspots, fix slow tests or cold runtime paths, preserve behavior proofs, update the performance report, add AGENTS guardrails, and make scoped commits/pushes for OpenClaw test-speed work.
description: Benchmark, diagnose, and optimize OpenClaw test runtime, import hotspots, CPU/RSS, and slow coverage paths.
---
# OpenClaw Test Performance

View File

@@ -0,0 +1,603 @@
---
name: openclaw-testing
description: Choose, run, rerun, or debug OpenClaw tests, CI checks, Docker E2E lanes, release validation, and the cheapest safe verification path.
---
# OpenClaw Testing
Use this skill when deciding what to test, debugging failures, rerunning CI,
or validating a change without wasting hours.
## Read First
- `docs/reference/test.md` for local test commands.
- `docs/ci.md` for CI scope, release checks, Docker chunks, and runner behavior.
- Scoped `AGENTS.md` files before editing code under a subtree.
## Default Rule
Prove the touched surface first. Do not reflexively run the whole suite.
1. Inspect the diff and classify the touched surface:
- source: `pnpm changed:lanes --json`, then `pnpm check:changed`
- tests only: `pnpm test:changed`
- one failing file: `pnpm test <path-or-filter> -- --reporter=verbose`
- 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
2. Reproduce narrowly before fixing.
3. Fix root cause.
4. Rerun the same narrow proof.
5. Broaden only when the touched contract demands it.
## Guardrails
- Do not kill unrelated processes or tests. If something is running elsewhere, treat it as owned by the user or another agent.
- Do not run expensive local Docker, full release checks, full `pnpm test`, or full `pnpm check` unless the user asks or the change genuinely requires it.
- Prefer GitHub Actions for release/Docker proof when the workflow already has the prepared image and secrets.
- Use `scripts/committer "<msg>" <paths...>` when committing; stage only your files.
- If deps are missing, run `pnpm install`, retry once, then report the first actionable error.
## Local Test Shortcuts
```bash
pnpm changed:lanes --json
pnpm check:changed # changed typecheck/lint/guards; no Vitest
pnpm test:changed # cheap smart changed Vitest targets
OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed
pnpm test <path-or-filter> -- --reporter=verbose
OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test <path-or-filter>
```
Use targeted file paths whenever possible. Avoid raw `vitest`; use the repo
`pnpm test` wrapper so project routing, workers, and setup stay correct.
## Command Semantics
- `pnpm check` and `pnpm check:changed` do not run Vitest tests. They are for
typecheck, lint, and guard proof.
- `pnpm test` and `pnpm test:changed` run Vitest tests.
- `pnpm test:changed` is intentionally cheap by default: direct test edits,
sibling tests, explicit source mappings, and import-graph dependents.
- `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed` is the explicit broad
fallback for harness/config/package edits that genuinely need it.
- Do not run extension sweeps just because core changed. If a core edit is for a
specific plugin bug, run that plugin's tests explicitly. If a public SDK or
contract change needs consumer proof, choose the smallest representative
plugin/contract tests first, then broaden only when the risk justifies it.
- The test wrapper prints a short `[test] passed|failed|skipped ... in ...`
line. Vitest's own duration is still the per-shard detail.
## Routing Model
- `pnpm changed:lanes --json` answers "which check lanes does this diff touch?"
It is used by `pnpm check:changed` for typecheck/lint/guard selection.
- `pnpm test:changed` answers "which Vitest targets are worth running now?" It
uses the same changed path list, but applies a cheaper test-target resolver.
- Direct test edits run themselves. Source edits prefer explicit mappings,
sibling `*.test.ts`, then import-graph dependents. Shared harness/config/root
edits are skipped by default unless they have precise mapped tests.
- Shared group-room delivery config and source-reply prompt edits are precise
mapped tests: they run the core auto-reply regressions plus Discord and Slack
delivery tests so cross-channel default changes fail before a PR push.
- Public SDK or contract edits do not automatically run every plugin test.
`check:changed` proves extension type contracts; the agent chooses the
smallest plugin/contract Vitest proof that matches the actual risk.
- Use `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed` only when a harness,
config, package, or unknown-root edit really needs the broad Vitest fallback.
## CI Debugging
Start with current run state, not logs for everything:
```bash
gh run list --branch main --limit 10
gh run view <run-id> --json status,conclusion,headSha,url,jobs
gh run view <run-id> --job <job-id> --log
```
- Check exact SHA. Ignore newer unrelated `main` unless asked.
- For cancelled same-branch runs, confirm whether a newer run superseded it.
- Fetch full logs only for failed or relevant jobs.
## GitHub Release Workflows
Use the smallest workflow that proves the current risk. The full umbrella is
available, but it is usually the last step after narrower proof, not the first
rerun after a focused patch.
### Full Release Validation
`Full Release Validation` (`.github/workflows/full-release-validation.yml`) is
the manual "everything before release" umbrella. It resolves a target ref, then
dispatches:
- manual `CI` for the full normal CI graph
- `OpenClaw Release Checks` for install smoke, cross-OS release checks, live and
E2E checks, Docker release-path suites, OpenWebUI, QA Lab, fast Matrix, and
Telegram release lanes
- optional post-publish Telegram E2E when a package spec is supplied
Run it only when validating an actual release candidate, after broad shared CI
or release orchestration changes, or when explicitly asked:
```bash
gh workflow run full-release-validation.yml \
--repo openclaw/openclaw \
--ref main \
-f ref=<branch-or-sha> \
-f provider=openai \
-f mode=both \
-f release_profile=stable
```
Run the workflow itself from the trusted current ref, normally `--ref main`;
child workflows are dispatched from that same ref even when `ref` points at an
older release branch or tag. Full Release Validation has no separate child
workflow ref input; choose the trusted harness by choosing the workflow run ref.
Use `release_profile=minimum|stable|full` to control live/provider breadth:
`minimum` keeps the fastest OpenAI/core release-critical set, `stable` adds the
stable provider/backend set, and `full` adds the broad advisory provider/media
matrix. Do not make `full` faster by silently dropping suites; optimize setup,
artifact reuse, and sharding instead. The parent verifier job appends
slowest-job tables for child runs; rerun only that verifier after a child rerun
turns green.
If a full run is already active on a newer `origin/main`, prefer watching that
run over dispatching a duplicate. If you accidentally dispatch a stale duplicate,
cancel it and monitor the current run.
The child-dispatch jobs record the child run ids. The final
`Verify full validation` job re-queries those child runs and is the canonical
parent gate. If a child workflow failed but was later rerun successfully, rerun
only the failed parent verifier job; do not dispatch a new full umbrella unless
the release evidence is stale.
For bounded recovery after a focused fix, pass `-f rerun_group=<group>`.
Supported umbrella groups are `all`, `ci`, `release-checks`, `install-smoke`,
`cross-os`, `live-e2e`, `package`, `qa`, `qa-parity`, `qa-live`, and
`npm-telegram`. Use the narrowest group that covers the failed box.
### Release Evidence
After release-candidate validation or before a release decision, record the
important run ids in the private `openclaw/releases-private` evidence ledger.
Use the manual `OpenClaw Release Evidence`
(`openclaw-release-evidence.yml`) workflow there. It writes durable summaries
under `evidence/<release-id>/` and commits:
- `release-evidence.md`
- `release-evidence.json`
- `index.json`
- `runs/<label>.json`
Use one run per line:
```text
full-release-validation openclaw/openclaw <run-id> blocking
package-acceptance openclaw/openclaw <run-id> blocking
release-checks openclaw/openclaw <run-id> blocking
```
Store summaries, run URLs, artifact metadata, timings, pass/fail state, and
short release-manager notes there. Do not store raw logs, provider
prompts/responses, channel transcripts, signing material, or secret-bearing
config in git; raw logs stay in Actions artifacts.
When `Full Release Validation` completes and
`OPENCLAW_RELEASES_PRIVATE_DISPATCH_TOKEN` is configured in the public repo, it
requests the private `OpenClaw Release Evidence From Full Validation` workflow.
That private workflow reads the parent full-validation run, extracts the child
CI/release-checks/Telegram run ids from the parent logs, and opens the evidence
PR automatically. If the token is absent or the run predates this wiring, trigger
that private workflow manually with the full-validation run id.
### Release Checks
`OpenClaw Release Checks` (`openclaw-release-checks.yml`) is the release child
workflow. It is broader than normal CI but narrower than the umbrella because it
does not dispatch the separate full normal CI child. It runs Package Acceptance
with artifact-native delta lanes and `telegram_mode=mock-openai`, so the release
package tarball also goes through offline plugin proof, bundled-channel compat,
and Telegram package QA. The Docker release-path chunks cover the overlapping
package/update/plugin lanes. Use it when release-path validation is needed
without rerunning the entire umbrella.
```bash
gh workflow run openclaw-release-checks.yml \
--repo openclaw/openclaw \
--ref main \
-f ref=<branch-or-sha> \
-f provider=openai \
-f mode=both \
-f release_profile=stable \
-f rerun_group=all
```
Release-check rerun groups are `all`, `install-smoke`, `cross-os`, `live-e2e`,
`package`, `qa`, `qa-parity`, and `qa-live`.
`OpenClaw Release Checks` uses the trusted workflow ref to resolve the selected
ref once as `release-package-under-test` and passes that artifact into cross-OS
release checks, release-path Docker live/E2E checks, and Package Acceptance.
When `Full Release Validation` dispatches release checks, it passes the requested
branch/tag plus an `expected_sha` so branch/tag refs resolve through the fast
remote-ref path while the package and QA jobs still validate the exact SHA.
The release Docker path intentionally shards the plugin/runtime tail. The
workflow uses `plugins-runtime-plugins`, `plugins-runtime-services`, and
`plugins-runtime-install-a` through `plugins-runtime-install-d`; aggregate
aliases such as `plugins-runtime-core`, `plugins-runtime`, and
`plugins-integrations` remain for manual reruns.
The release QA parity box is internally split into candidate and baseline lane
jobs, followed by a report job that downloads both artifacts and runs
`pnpm openclaw qa parity-report`. For parity failures, inspect the failed lane
first; inspect the report job when both lane summaries exist but the comparison
fails.
### QA Lab Matrix Profiles
`pnpm openclaw qa matrix` defaults to `--profile all`. Do not assume the CLI
default is the fast release path. Use explicit profiles:
- `--profile fast`: release-critical Matrix transport contract; add
`--fail-fast` only when the target CLI supports it
- `--profile transport|media|e2ee-smoke|e2ee-deep|e2ee-cli`: sharded full
Matrix proof
- `OPENCLAW_QA_MATRIX_NO_REPLY_WINDOW_MS=3000`: CI-friendly no-reply quiet
window when paired with fast or sharded gates
`QA-Lab - All Lanes` uses explicit fast Matrix on scheduled runs; manual
dispatch keeps `matrix_profile=all` as the default and always shards that full
Matrix selection. `OpenClaw Release Checks` uses explicit fast Matrix; run the
all-lanes workflow when release investigation needs full Matrix media/E2EE
inventory.
### Reusable Live/E2E Checks
`OpenClaw Live And E2E Checks (Reusable)`
(`openclaw-live-and-e2e-checks-reusable.yml`) is the preferred entry point for
targeted live, Docker, model, and E2E proof. Inputs let you turn off unrelated
lanes:
```bash
gh workflow run openclaw-live-and-e2e-checks-reusable.yml \
--repo openclaw/openclaw \
--ref main \
-f ref=<sha> \
-f include_repo_e2e=false \
-f include_release_path_suites=false \
-f include_openwebui=false \
-f include_live_suites=true \
-f live_models_only=true \
-f live_model_providers=fireworks
```
Useful knobs:
- `docker_lanes='<lane[,lane]>'`: run selected Docker scheduler lanes against
prepared artifacts instead of the release chunk matrix. Multiple selected
lanes fan out as parallel targeted Docker jobs after one shared package/image
preparation step.
- `include_live_suites=false`: skip live/provider suites when testing Docker
scheduler or release packaging only.
- `live_models_only=true`: run only Docker live model coverage.
- `live_model_providers=fireworks` (or comma/space separated providers): run one
targeted Docker live model job instead of the full provider matrix.
- blank `live_model_providers`: run the full live-model provider matrix.
Release-path Docker chunks are currently `core`, `package-update-openai`,
`package-update-anthropic`, `package-update-core`,
`plugins-runtime-plugins`, `plugins-runtime-services`,
`plugins-runtime-install-a`, `plugins-runtime-install-b`,
`plugins-runtime-install-c`, `plugins-runtime-install-d`,
`bundled-channels-core`, `bundled-channels-update-a`,
`bundled-channels-update-b`, and `bundled-channels-contracts`. The aggregate
`bundled-channels`, `plugins-runtime-core`, `plugins-runtime`, and
`plugins-integrations` chunks remain valid for manual one-shot reruns, but
release checks use the split chunks.
When live suites are enabled, the workflow shards broad native `pnpm test:live`
coverage through `scripts/test-live-shard.mjs` instead of one serial `live-all`
job:
- `native-live-src-agents`
- `native-live-src-gateway-core`
- `native-live-src-gateway-profiles` (release CI runs this with provider
filters such as `OPENCLAW_LIVE_GATEWAY_PROVIDERS=anthropic`)
- `native-live-src-gateway-backends`
- `native-live-test`
- `native-live-extensions-a-k`
- `native-live-extensions-l-n`
- `native-live-extensions-openai`
- `native-live-extensions-o-z`
- `native-live-extensions-o-z-other`
- `native-live-extensions-xai`
- `native-live-extensions-media`
- `native-live-extensions-media-audio`
- `native-live-extensions-media-music`
- `native-live-extensions-media-music-google`
- `native-live-extensions-media-music-minimax`
- `native-live-extensions-media-video`
Use `node scripts/test-live-shard.mjs <shard> --list` to see the exact files
before rerunning a failed native live shard. The aggregate `o-z` and `media`
shards remain useful locally; release CI uses the smaller provider/media shards
so one live-provider flake does not force a broad native live rerun.
For model-list or provider-selection fixes, use `live_models_only=true` plus the
specific `live_model_providers` allowlist. Confirm logs show the expected
`OPENCLAW_LIVE_PROVIDERS` and selected model ids before declaring proof.
## Docker
Docker is expensive. First inspect the scheduler without running Docker:
```bash
OPENCLAW_DOCKER_ALL_DRY_RUN=1 pnpm test:docker:all
OPENCLAW_DOCKER_ALL_DRY_RUN=1 OPENCLAW_DOCKER_ALL_LANES=install-e2e pnpm test:docker:all
OPENCLAW_DOCKER_ALL_LANES=install-e2e node scripts/test-docker-all.mjs --plan-json
```
Run one failed lane locally only when explicitly asked or when GitHub is not
usable:
```bash
OPENCLAW_DOCKER_ALL_LANES=<lane> \
OPENCLAW_DOCKER_ALL_BUILD=0 \
OPENCLAW_DOCKER_ALL_PREFLIGHT=0 \
OPENCLAW_SKIP_DOCKER_BUILD=1 \
OPENCLAW_DOCKER_E2E_BARE_IMAGE='<prepared-bare-image>' \
OPENCLAW_DOCKER_E2E_FUNCTIONAL_IMAGE='<prepared-functional-image>' \
pnpm test:docker:all
```
For release validation, prefer the reusable GitHub workflow input:
```yaml
docker_lanes: install-e2e
```
Multiple lanes are allowed:
```yaml
docker_lanes: install-e2e bundled-channel-update-acpx
```
That skips the release chunk matrix and runs one targeted Docker job against the
prepared GHCR images and the selected package artifact. Rerun commands
generated inside GitHub artifacts include `package_artifact_run_id`,
`package_artifact_name`, `docker_e2e_bare_image`, and
`docker_e2e_functional_image` when available, so failed lanes can reuse the
exact tarball and prepared images from the failed run. When the fix changes
package contents, omit those reuse inputs so the workflow packs a new tarball.
Live-only targeted reruns skip the E2E images and build only the live-test
image. Release-path normal mode fans out into smaller Docker chunk jobs:
- `core`
- `package-update-openai`
- `package-update-anthropic`
- `package-update-core`
- `plugins-runtime-plugins`
- `plugins-runtime-services`
- `plugins-runtime-install-a`
- `plugins-runtime-install-b`
- `plugins-runtime-install-c`
- `plugins-runtime-install-d`
- `bundled-channels`
OpenWebUI is folded into `plugins-runtime-services` for full release-path
coverage and keeps a standalone `openwebui` chunk only for OpenWebUI-only
dispatches. The legacy `package-update`, `plugins-runtime-core`,
`plugins-runtime`, and `plugins-integrations` chunks still work as aggregate
aliases for manual reruns, but the release workflow uses the split chunks so
provider installer checks, plugin runtime checks, bundled plugin
install/uninstall shards, and bundled-channel checks can run on separate
machines. The bundled-channel runtime-dependency coverage
inside `bundled-channels`
uses the split `bundled-channel-*` and `bundled-channel-update-*` lanes rather
than the serial `bundled-channel-deps` lane, so failures produce cheap targeted
reruns for the exact channel/update scenario. The bundled plugin
install/uninstall sweep is also split into
`bundled-plugin-install-uninstall-0` through
`bundled-plugin-install-uninstall-7`; selecting the legacy
`bundled-plugin-install-uninstall` lane expands to all eight shards.
## Package Acceptance
Use the manual `Package Acceptance` workflow when the question is "does this
installable package work as a product?" rather than "does this source diff pass
Vitest?"
In release validation, treat Package Acceptance as the package-candidate shard
inside the larger release umbrella, not as a competing full-test path. Full
Release Validation and private release gauntlets should call Package Acceptance
for tarball resolution, Docker product/package proof, and optional Telegram QA
against the same resolved `package-under-test` artifact; keep orchestration,
secret policy, blocking/advisory status, and evidence rollup in the caller.
Good defaults:
```bash
gh workflow run package-acceptance.yml --ref main \
-f source=npm \
-f workflow_ref=main \
-f package_spec=openclaw@beta \
-f suite_profile=product \
-f telegram_mode=mock-openai
```
Npm candidate selection:
- Resolve the registry immediately before dispatch:
`npm view openclaw dist-tags --json --prefer-online --cache /tmp/openclaw-npm-cache-verify-$$`
and `npm view openclaw@beta version dist.tarball dist.integrity --json --prefer-online --cache /tmp/openclaw-npm-cache-verify-$$`.
- If Peter asks for "latest beta", use `source=npm` with
`package_spec=openclaw@beta`, then record the resolved version from `npm view`
or the workflow summary.
- For reruns, release proof, or comparing one known package, prefer the exact
immutable spec: `package_spec=openclaw@YYYY.M.D-beta.N` or
`package_spec=openclaw@YYYY.M.D`.
- For stable package proof, use `package_spec=openclaw@latest` only when the
question is explicitly the current stable dist-tag; otherwise pin the exact
version.
- `source=npm` only accepts registry specs for `openclaw@beta`,
`openclaw@latest`, or exact OpenClaw release versions. Do not pass semver
ranges, git refs, file paths, tarball URLs, or plugin package names there.
- If the candidate is a tarball URL, use `source=url` with `package_sha256`. If
it is an Actions tarball artifact, use `source=artifact`. If it is an
unpublished source candidate, use `source=ref` with a trusted ref or SHA.
- Package acceptance tests exactly the selected package candidate. Do not apply
`openclaw update --channel beta` fallback semantics here; if `beta` is absent,
stale, older than `latest`, or points at a broken tarball, report that tag
state instead of silently testing `latest`.
Profiles:
- `smoke`: quick confidence that the tarball installs, can onboard a channel,
can run an agent turn, and basic gateway/config lanes work.
- `package`: release-package contract. Adds installer/update, doctor install
switching, bundled plugin runtime deps, plugin install/update, and package
repair lanes. This is the default native replacement for most Parallels
package/update coverage.
- `product`: package profile plus broader product surfaces: MCP channels,
cron/subagent cleanup, OpenAI web search, and OpenWebUI.
- `full`: split Docker release-path chunks with OpenWebUI.
- `custom`: exact `docker_lanes` list for a focused rerun.
Candidate sources:
- `source=npm`: `openclaw@beta`, `openclaw@latest`, or an exact release version.
- `source=ref`: pack `package_ref` using the trusted `workflow_ref` harness.
This intentionally separates old package commits from new workflow/test code.
- `source=url`: HTTPS `.tgz` plus required `package_sha256`.
- `source=artifact`: download one `.tgz` from `artifact_run_id`/`artifact_name`.
Ref model:
- `gh workflow run ... --ref <workflow-ref>` selects the workflow file revision
GitHub executes.
- `workflow_ref` is the trusted harness/script ref passed to reusable Docker
E2E.
- `package_ref` is the source ref to build when `source=ref`. It can be an
older branch/tag/SHA as long as it is reachable from an OpenClaw branch or
release tag.
Example: run latest package acceptance harness against an older trusted commit:
```bash
gh workflow run package-acceptance.yml --ref main \
-f workflow_ref=main \
-f source=ref \
-f package_ref=<branch-or-sha> \
-f suite_profile=package \
-f telegram_mode=mock-openai
```
Use `telegram_mode=mock-openai` or `telegram_mode=live-frontier` when the same
resolved `package-under-test` tarball should also run through the Telegram QA
workflow in the `qa-live-shared` environment. The standalone Telegram workflow
still accepts a published npm spec for post-publish checks, but Package
Acceptance passes the resolved artifact for `source=npm`, `ref`, `url`, and
`artifact`. Use `telegram_mode=none` only when intentionally skipping Telegram
credentialed package proof for a focused rerun.
Docker E2E images never copy repo sources as the app under test: the bare image
is a Node/Git runner, and the functional image installs the same prebuilt npm
tarball that bare lanes mount. `scripts/package-openclaw-for-docker.mjs` is the
single packer for local scripts and CI and validates the tarball inventory
before Docker consumes it. `scripts/test-docker-all.mjs --plan-json` is the
scheduler-owned CI plan for image kind, package, live image, lane, and
credential needs. Docker lane definitions live in the single scenario catalog
`scripts/lib/docker-e2e-scenarios.mjs`; planner logic lives in
`scripts/lib/docker-e2e-plan.mjs`. `scripts/docker-e2e.mjs` converts plan and
summary JSON into GitHub outputs and step summaries. Every scheduler run writes
`.artifacts/docker-tests/**/summary.json` plus `failures.json`. Read those
before rerunning. Lane entries include `command`, `rerunCommand`, status,
timing, timeout state, image kind, and log file path. The summary also includes
top-level phase timings for preflight, image build, package prep, lane pools,
and cleanup. Use `pnpm test:docker:timings <summary.json>` to rank slow lanes
and phases before deciding whether a broader rerun is justified.
## Cheap Docker Reruns
First derive the smallest rerun command from artifacts:
```bash
pnpm test:docker:rerun <github-run-id>
pnpm test:docker:rerun .artifacts/docker-tests/<run>/failures.json
```
The script downloads Docker E2E artifacts for a GitHub run, reads
`summary.json`/`failures.json`, and prints a combined targeted workflow command
plus per-lane commands. Prefer the combined targeted command when several lanes
failed for the same patch:
```bash
gh workflow run openclaw-live-and-e2e-checks-reusable.yml \
-f ref=<sha> \
-f include_repo_e2e=false \
-f include_release_path_suites=false \
-f include_openwebui=false \
-f docker_lanes='install-e2e bundled-channel-update-acpx' \
-f include_live_suites=false \
-f live_models_only=false
```
That path still runs the prepare job, so it creates a new tarball for `<sha>`.
If the SHA-tagged GHCR bare/functional image already exists, CI skips rebuilding
that image and only uploads the fresh package artifact before the targeted lane
job. Do not rerun the full release path unless the failed lane list
or touched surface really requires it.
## Docker Expected Timings
Treat these as ballpark. Blacksmith queue time, GHCR pull speed, provider
latency, npm cache state, and Docker daemon health can dominate.
Current local timing artifact (`.artifacts/docker-tests/lane-timings.json`) has
these rough bands:
- Tiny lanes, seconds to under 1 minute:
`agents-delete-shared-workspace` ~3s, `plugin-update` ~7s,
`config-reload` ~14s, `pi-bundle-mcp-tools` ~15s, `onboard` ~18s,
`session-runtime-context` ~20s, `gateway-network` ~34s, `qr` ~44s.
- Medium deterministic lanes, ~1-5 minutes:
`npm-onboard-channel-agent` ~96s, `openai-image-auth` ~99s,
bundled channel/update lanes usually ~90-300s when split, `openwebui` ~225s,
`mcp-channels` ~274s.
- Heavy deterministic lanes, ~6-10 minutes:
`bundled-channel-root-owned` ~429s,
`bundled-channel-setup-entry` ~420s,
`bundled-channel-load-failure` ~383s,
`cron-mcp-cleanup` ~567s.
- Live provider lanes, often ~15-20 minutes:
`live-gateway` ~958s, `live-models` ~1054s.
- Installer/release lanes:
`install-e2e` and package-update paths can vary widely with npm, provider,
and package registry behavior. Budget tens of minutes; prefer GitHub targeted
reruns over local repeats.
Default fallback lane timeout is 120 minutes. A timeout usually means debug the
lane log/artifacts first, not “run the whole thing again.”
## Failure Workflow
1. Identify exact failing job, SHA, lane, and artifact path.
2. Read `failures.json`, `summary.json`, and the failed lane log tail.
3. Use `pnpm test:docker:rerun <run-id|failures.json>` to generate targeted
GitHub rerun commands.
4. If the lane has `rerunCommand`, use that only as a local starting point.
5. For Docker release failures, dispatch targeted `docker_lanes=<failed-lane>`
on GitHub before considering local Docker.
6. Patch narrowly, then rerun the failed file/lane only.
7. Broaden to `pnpm check:changed` or CI only after the isolated proof passes.
## When To Escalate
- Public SDK/plugin contract changes: run changed gate plus relevant extension
validation.
- Build output, lazy imports, package boundaries, or published surfaces:
include `pnpm build`.
- Workflow edits: run `pnpm check:workflows`.
- Release branch or tag validation: use release docs and GitHub workflows; avoid
local Docker unless Peter explicitly asks.

View File

@@ -0,0 +1,4 @@
interface:
display_name: "OpenClaw Testing"
short_description: "Choose cheap, targeted OpenClaw validation"
default_prompt: "Use $openclaw-testing to choose the cheapest safe test or CI verification path, inspect failures, and rerun only the relevant OpenClaw lane."

View File

@@ -1,6 +1,6 @@
---
name: optimizetests
description: Optimize OpenClaw test runtime end to end. Use when the user asks for /optimizetests, slow-test review, import optimization, deduping tests, moving misplaced core coverage to extensions, or reducing CI/test wall time without adding shards or dropping coverage.
description: Optimize OpenClaw slow tests, imports, misplaced coverage, and CI wall time without dropping coverage.
---
# Optimize Tests

View File

@@ -1,6 +1,6 @@
---
name: parallels-discord-roundtrip
description: Run the macOS Parallels smoke harness with Discord end-to-end roundtrip verification, including guest send, host verification, host reply, and guest readback.
description: Run macOS Parallels smoke with Discord send, host verification, host reply, and guest readback proof.
---
# Parallels Discord Roundtrip
@@ -50,6 +50,7 @@ pnpm test:parallels:macos \
- Avoid `prlctl enter` / expect for long Discord setup scripts; it line-wraps/corrupts long commands. Use `prlctl exec --current-user /bin/sh -lc ...` for the Discord config phase.
- Full 3-OS sweeps: the shared build lock is safe in parallel, but snapshot restore is still a Parallels bottleneck. Prefer serialized Windows/Linux restore-heavy reruns if the host is already under load.
- Harness cleanup deletes the temporary Discord smoke messages at exit.
- After a successful Discord roundtrip, shut down the macOS guest before handoff (`prlctl stop "macOS Tahoe"`). The macOS smoke harness should do this automatically after successful Discord proof; still stop the VM manually after ad-hoc Discord checks. Do not leave the Discord-configured VM running; it can keep reading/posting in `#maintainer` and spam Discord after the proof is complete.
- Per-phase logs: `/tmp/openclaw-parallels-smoke.*`
- Machine summary: pass `--json`
- If roundtrip flakes, inspect `fresh.discord-roundtrip.log` and `discord-last-readback.json` in the run dir first.

View File

@@ -1,6 +1,6 @@
---
name: security-triage
description: Triage GitHub security advisories for OpenClaw with high-confidence close/keep decisions, exact tag and commit verification, trust-model checks, optional hardening notes, and a final reply ready to post and copy to clipboard.
description: Triage OpenClaw security advisories, drafts, and GHSA reports with shipped-tag and trust-model proof.
---
# Security Triage
@@ -45,6 +45,17 @@ For each advisory, decide:
- `keep open`
- `keep open but narrow`
Default to one advisory at a time when comments/closures are involved:
1. Review exactly one GHSA.
2. Print the GHSA URL first.
3. Summarize the decision and evidence for discussion.
4. Draft one maintainer-ready comment.
5. Copy only that one comment to the clipboard.
6. Stop and wait for Peter to post/discuss before moving to the next GHSA.
Do not batch multiple close comments unless Peter explicitly asks for a batch.
Check in this order:
1. Trust model
@@ -60,6 +71,11 @@ Check in this order:
4. Functional tradeoff
- If a hardening change would reduce intended user functionality, call that out before proposing it.
- Prefer fixes that preserve user workflows over deny-by-default regressions unless the boundary demands it.
5. Hardening follow-up
- Even when the GHSA should close, ask whether a narrow hardening change would reduce footguns without changing the documented trust boundary.
- Separate hardening from vulnerability status. Phrase it as "not required for GHSA closure, but worth considering".
- Bring up hardening only if it is concrete, low-risk, and preserves intended maintainer/operator workflows.
- If hardening would require a product/security model change, say that explicitly and do not imply it is a required fix for closure.
## Response Format
@@ -76,9 +92,22 @@ When preparing a maintainer-ready close reply:
Keep tone firm, specific, non-defensive.
## Discussion Mode
When Peter is manually posting GHSA comments, use this flow:
1. Show the URL.
2. Give a terse verdict (`close`, `keep open`, or `keep open but narrow`).
3. List the strongest evidence bullets.
4. State any optional hardening follow-up separately from the close reason.
5. Copy the proposed comment body with `pbcopy`.
6. End the reply after the one advisory. Do not continue to the next advisory until Peter says to continue.
If the GitHub API cannot post comments for private advisories, say so once and keep using clipboard/UI paste.
## Clipboard Step
After drafting the final post body, copy it:
After drafting the final post body for the current advisory, copy it:
```bash
pbcopy <<'EOF'
@@ -86,7 +115,7 @@ pbcopy <<'EOF'
EOF
```
Tell the user that the clipboard now contains the proposed response.
Tell the user that the clipboard now contains the proposed response for that advisory.
## Useful Commands

View File

@@ -1,6 +1,6 @@
---
name: tag-duplicate-prs-issues
description: Maintainer workflow for deciding whether an OpenClaw pull request or issue is a duplicate, gathering evidence with ghreplica and pr-search-cli, grouping related work in prtags, and syncing the duplicate grouping back to GitHub through prtags. Use when Codex needs to search for duplicate PRs or issues, create or reuse a duplicate group, enforce one-group-per-target discipline, save duplicate judgments in prtags, or prepare group state for comment sync.
description: Use gitcrawl to search duplicate OpenClaw PRs/issues, group related work in prtags, and sync duplicate state to GitHub.
---
# Tag Duplicate PRs and Issues
@@ -12,43 +12,25 @@ It is not for reviewing the implementation quality of a PR.
## Required Setup
Do not start duplicate triage until this setup is complete.
Do not write duplicate groups or annotations until this setup is complete.
Read-only discovery can still proceed with `gitcrawl` and live `gh`.
### Install the companion skills
### Companion Skills
Install these skills first because they teach the agent how to use the two main CLIs correctly:
- `ghreplica` skill from the `ghreplica` repo at `skills/ghreplica/SKILL.md`
- `prtags` skill from the `prtags` repo at `skills/prtags/SKILL.md`
This skill assumes those two skills are available and can be used during the same run.
Use `$gitcrawl` first for local candidate discovery.
Use the `prtags` skill from the `prtags` repo at `skills/prtags/SKILL.md` when it is available.
### Install the CLIs
Install `ghreplica` and `prtags` from their latest GitHub releases.
Install `prtags` from its latest GitHub release.
Do not rely on an old local build unless the maintainer explicitly wants to test unreleased behavior.
`ghreplica` CLI install path:
```bash
curl -fsSL https://raw.githubusercontent.com/dutifuldev/ghreplica/main/scripts/install-ghr.sh | bash -s -- --bin-dir "$HOME/.local/bin"
```
`prtags` CLI install path:
```bash
curl -fsSL https://raw.githubusercontent.com/dutifuldev/prtags/main/scripts/install-prtags.sh | bash -s -- --bin-dir "$HOME/.local/bin"
```
Use the `pr-search-cli` project with `uvx`.
The command itself is `pr-search`.
Do not require a permanent install unless the maintainer explicitly wants one.
```bash
uvx --from pr-search-cli pr-search status
uvx --from pr-search-cli pr-search code similar 67144
```
### Authenticate prtags
`prtags` should be logged in with the maintainer's own GitHub account through OAuth device flow.
@@ -66,20 +48,15 @@ The expected outcome is that `prtags` stores the logged-in maintainer identity l
Do not require an up-front preflight before starting the workflow.
Proceed with the normal steps until you actually need a tool or account state.
As soon as you discover that a required CLI is missing or `prtags` is not logged in, stop immediately.
Do not continue in a partial mode after that point.
As soon as you discover that `prtags` is missing or not logged in at the write step, stop immediately.
Do not continue in a partial write mode after that point.
If `ghr` is missing, ask the user to run the `ghreplica` install command.
If `prtags` is missing, ask the user to run both CLI install commands:
If `prtags` is missing, ask the user to run:
```bash
curl -fsSL https://raw.githubusercontent.com/dutifuldev/ghreplica/main/scripts/install-ghr.sh | bash -s -- --bin-dir "$HOME/.local/bin"
curl -fsSL https://raw.githubusercontent.com/dutifuldev/prtags/main/scripts/install-prtags.sh | bash -s -- --bin-dir "$HOME/.local/bin"
```
If `uvx --from pr-search-cli pr-search ...` fails because `uvx` or the `pr-search` launcher is not available, ask the user to make that command work before continuing.
If `prtags auth status` shows that the user is not logged in, ask the user to run:
```bash
@@ -90,19 +67,19 @@ Resume only after the missing tool or login state has been fixed.
## Read-Path Default
For read-only GitHub operations in this workflow, use `ghr` as the default CLI.
Treat it as a drop-in replacement for the `gh` read operations you would normally use for PRs, issues, comments, reviews, and duplicate-search evidence.
For candidate discovery in this workflow, use `gitcrawl` first.
Treat it as the local history and clustering layer for related issues, duplicate attempts, and closed threads.
Only fall back to `gh` when `ghr` is failing for a concrete reason, such as:
Use live `gh` or `gh api` for the target thread and for any candidate before making an actionable judgment.
Use live GitHub when `gitcrawl` is missing or stale for a concrete reason, such as:
- the mirrored object is not present yet
- the mirror data is clearly stale or incomplete for the decision you need to make
- the `ghr` command errors, times out, or does not expose the specific read you need
- the target or candidate is not present yet
- the local data is clearly stale or incomplete for the decision you need to make
- `gitcrawl` errors, times out, or lacks the needed neighbor/search data
When you fall back to `gh`, note that you did so and why.
When you fall back to live GitHub search, note that you did so and why.
If `ghr` is missing a fresh PR or issue but `gh` can read it, you may use `gh` for the read-side judgment.
If a later `prtags` target-level write fails because the same object is still missing from `ghreplica`, stop and report that the mirror has not caught up yet instead of forcing the write.
If a later `prtags` target-level write fails because its own mirror has not caught up, stop and report that the curation backend is missing the target object instead of forcing a fallback write.
## Goal
@@ -118,14 +95,12 @@ For each target PR or issue:
Use the tools with these boundaries:
- `ghreplica` is the raw evidence source
- use `ghr` first for normal GitHub read operations in this workflow
- use it for title/body/comment search, related PRs, overlapping files, overlapping ranges, and current PR or issue status
- resort to `gh` only when `ghr` cannot provide the needed read cleanly
- `pr-search-cli` is candidate generation and ranking
- use it to suggest likely duplicate PRs or issue-cluster context
- do not treat it as final truth
- do not create or expand a duplicate group only because `pr-search-cli` put multiple PRs in the same issue or duplicate cluster
- `gitcrawl` is candidate generation and historical context
- use it first for local title/body search, neighbors, clusters, and closed-thread discovery
- treat every candidate as a lead until live GitHub confirms it
- `gh` is live GitHub truth
- use it for target state, body, comments, reviews, files, linked issues, and current open/closed/merged status
- use `gh search` only when `gitcrawl` is stale, missing data, or cannot express the needed query
- `prtags` is the maintainer curation layer
- use it to create or reuse one duplicate group
- use it to save the duplicate status, confidence, rationale, and group summary
@@ -182,7 +157,7 @@ Examples:
## Evidence Checklist
Before declaring a duplicate, gather evidence from at least two categories.
Same-issue or same-cluster output from `pr-search-cli` counts only as candidate generation, not as one of the required proof categories by itself.
`gitcrawl` neighbors, search hits, and cluster membership count as candidate generation, not as enough proof by themselves.
For PRs:
@@ -205,21 +180,18 @@ If you only have wording similarity, that is not enough.
## Step 1: Read The Target
Start by reading the target itself.
Use `ghr` first for this step even if you would normally reach for `gh`.
Use live GitHub for current target state.
For a PR:
```bash
ghr pr view -R openclaw/openclaw <number> --comments
ghr pr reviews -R openclaw/openclaw <number>
ghr pr comments -R openclaw/openclaw <number>
gh pr view <number> --json number,title,state,mergedAt,body,closingIssuesReferences,files,comments,reviews,statusCheckRollup
```
For an issue:
```bash
ghr issue view -R openclaw/openclaw <number> --comments
ghr issue comments -R openclaw/openclaw <number>
gh issue view <number> --json number,title,state,body,comments,closedAt
```
Record:
@@ -232,74 +204,56 @@ Record:
- whether it is open, closed, or merged
- whether there is already a likely duplicate thread mentioned by humans
## Step 2: Search Broadly With ghreplica
## Step 2: Search Broadly With Gitcrawl
Use `ghreplica` first because it is the most direct evidence source.
Do not switch to `gh` for ordinary reads unless `ghr` is missing data or failing.
Use `gitcrawl` first because it is the local OpenClaw history and clustering source.
Do not switch to broad live GitHub search unless `gitcrawl` is missing data, stale, or failing.
### PR duplicate search
Run all of these when the target is a PR:
Start with the target and nearby threads:
```bash
ghr search related-prs -R openclaw/openclaw <pr-number> --mode path_overlap --state all
ghr search related-prs -R openclaw/openclaw <pr-number> --mode range_overlap --state all
ghr search mentions -R openclaw/openclaw --query "<key phrase from title or body>" --mode fts --scope pull_requests --state all
ghr search mentions -R openclaw/openclaw --query "<subsystem or error phrase>" --mode fts --scope issues --state all
gitcrawl threads openclaw/openclaw --numbers <issue-or-pr-number> --include-closed --json
gitcrawl neighbors openclaw/openclaw --number <issue-or-pr-number> --limit 20 --json
```
Use `prs-by-paths` or `prs-by-ranges` when the likely duplicate surface is already known:
Then search key phrases and subsystem terms:
```bash
ghr search prs-by-paths -R openclaw/openclaw --path src/example.ts --state all
ghr search prs-by-ranges -R openclaw/openclaw --path src/example.ts --start 20 --end 80 --state all
gitcrawl search openclaw/openclaw --query "<key phrase from title or body>" --mode hybrid --limit 20 --json
gitcrawl search openclaw/openclaw --query "<subsystem or error phrase>" --mode hybrid --limit 20 --json
```
### Issue duplicate search
`ghreplica` does not have a special issue-to-issue “related issues” command.
For issues, search mirrored text and linked PR context instead.
Run targeted text searches:
Inspect likely clusters:
```bash
ghr search mentions -R openclaw/openclaw --query "<issue title phrase>" --mode fts --scope issues --state all
ghr search mentions -R openclaw/openclaw --query "<error message or symptom>" --mode fts --scope issues --state all
ghr search mentions -R openclaw/openclaw --query "<subsystem phrase>" --mode fts --scope pull_requests --state all
gitcrawl cluster-detail openclaw/openclaw --id <cluster-id> --member-limit 20 --body-chars 280 --json
```
Then inspect the candidate PRs or issues those searches uncover.
## Step 3: Use pr-search-cli As A Hint Layer
Use `pr-search-cli` after `ghreplica`.
It is good at surfacing candidates quickly, but it is not the final decision-maker.
Run it through the `pr-search` command.
For a PR:
For PRs, verify likely code overlap with live file data:
```bash
uvx --from pr-search-cli pr-search -R openclaw/openclaw code similar <pr-number>
uvx --from pr-search-cli pr-search -R openclaw/openclaw code clusters for-pr <pr-number>
uvx --from pr-search-cli pr-search -R openclaw/openclaw issues for-pr <pr-number>
uvx --from pr-search-cli pr-search -R openclaw/openclaw issues duplicate-prs
gh pr view <candidate-pr> --json number,title,state,mergedAt,files,body,comments,reviews
```
Interpretation:
For issues, verify likely duplicate issue state and comments live:
- `code similar` suggests PRs with similar change shape
- `code clusters for-pr` shows the PRs nearby code cluster
- `issues for-pr` shows which issue clusters the PR appears to belong to
- `issues duplicate-prs` is useful for spotting already-known duplicate PR patterns
```bash
gh issue view <candidate-issue> --json number,title,state,body,comments,closedAt
```
Treat every `pr-search-cli` result as a hint to investigate, not as enough evidence to create or widen a duplicate group.
Multiple PRs can share the same issue or issue cluster while still taking meaningfully different fix paths.
## Step 3: Use Live GitHub Search For Gaps
For an issue:
Use targeted live GitHub search after `gitcrawl` when:
- use `ghreplica` first to find candidate PRs or issue wording
- if the issue has linked PRs or a likely implementation PR, run `pr-search-cli` on those PRs
- treat issue-cluster output as supporting context, not as enough by itself to call the issue a duplicate
- the target is too new for the local store
- comments or reviews matter and the local store lacks them
- the exact phrase did not appear in local results but the issue/PR is current enough that GitHub should know it
```bash
gh search prs --repo openclaw/openclaw --match title,body --limit 50 -- "<key phrase>"
gh search issues --repo openclaw/openclaw --match title,body --limit 50 -- "<key phrase>"
gh search issues --repo openclaw/openclaw --match comments --limit 50 -- "<error or maintainer phrase>"
```
## Step 4: Decide The Outcome
@@ -344,7 +298,7 @@ Reuse an existing group when:
- it already contains clearly related members
- adding the target would keep the group coherent
Do not widen an existing group just because `pr-search-cli` placed several PRs under the same issue or duplicate cluster.
Do not widen an existing group just because `gitcrawl` placed several PRs or issues near each other.
Confirm that the actual implementation path and maintainer intent still match before adding the new member.
Create a new group only when no existing group clearly fits.
@@ -423,8 +377,8 @@ prtags annotation group set <group-id> \
When the evidence is incomplete, set `duplicate_status=candidate` and lower the confidence.
If a per-PR or per-issue annotation write fails because `prtags` cannot resolve the target through `ghreplica`, do not force a fallback write path.
Keep the group state you were able to write, report that the mirror is still missing the target object, and defer the target-level annotation until `ghreplica` catches up.
If a per-PR or per-issue annotation write fails because `prtags` cannot resolve the target, do not force a fallback write path.
Keep the group state you were able to write, report that the curation backend is still missing the target object, and defer the target-level annotation until `prtags` catches up.
## Step 8: Let prtags Sync The Group Comment

View File

@@ -1,4 +1,4 @@
interface:
display_name: "Tag Duplicate PRs and Issues"
short_description: "Find duplicate PRs and issues, group them in prtags, and let prtags sync the GitHub comment"
default_prompt: "Use $tag-duplicate-prs-issues to decide whether an OpenClaw PR or issue is a duplicate, gather evidence with ghreplica and pr-search-cli, group related items in prtags, and save the duplicate judgment."
short_description: "Find duplicate PRs and issues with gitcrawl, group them in prtags, and let prtags sync the GitHub comment"
default_prompt: "Use $tag-duplicate-prs-issues to decide whether an OpenClaw PR or issue is a duplicate, gather candidates with gitcrawl, verify live state with GitHub, group related items in prtags, and save the duplicate judgment."

View File

@@ -8,6 +8,14 @@
.bun-cache
.bun
.artifacts
**/.artifacts
.local
**/.local
.pi
**/.pi
__openclaw_vitest__
**/__openclaw_vitest__
.tmp
**/.tmp
.DS_Store
@@ -38,6 +46,9 @@ docs/.generated
*.log
tmp
**/tmp
dist-runtime
**/dist-runtime
openclaw-path-alias-*
# build artifacts
dist

View File

@@ -82,4 +82,5 @@ OPENCLAW_GATEWAY_TOKEN=
# ELEVENLABS_API_KEY=...
# XI_API_KEY=... # alias for ElevenLabs
# INWORLD_API_KEY=...
# DEEPGRAM_API_KEY=...

2
.github/CODEOWNERS vendored
View File

@@ -9,6 +9,8 @@
/.github/dependabot.yml @openclaw/secops
/.github/codeql/ @openclaw/secops
/.github/workflows/codeql.yml @openclaw/secops
/.github/workflows/codeql-android-critical-security.yml @openclaw/secops
/.github/workflows/codeql-critical-quality.yml @openclaw/secops
/src/security/ @openclaw/secops
/src/secrets/ @openclaw/secops
/src/config/*secret*.ts @openclaw/secops

View File

@@ -0,0 +1,149 @@
name: Docker E2E plan and hydrate
description: >
Create a Docker E2E lane plan, expose GitHub outputs, and optionally hydrate
the prebuilt package artifact plus shared Docker images needed by the plan.
inputs:
mode:
description: prepare, chunk, or targeted.
required: true
chunk:
description: Release-path chunk for mode=chunk.
required: false
default: ""
lanes:
description: Comma/space separated lane names for targeted or prepare mode.
required: false
default: ""
include-openwebui:
description: Whether Open WebUI is included when planning release/prepare coverage.
required: false
default: "true"
include-release-path-suites:
description: Whether prepare mode should plan all release-path suites.
required: false
default: "false"
hydrate-artifacts:
description: Whether to download/pull artifacts required by the plan.
required: false
default: "true"
package-artifact-name:
description: Workflow artifact name containing openclaw-current.tgz.
required: false
default: docker-e2e-package
outputs:
credentials:
description: Comma-separated credential groups required by selected lanes.
value: ${{ steps.plan.outputs.credentials }}
needs_bare_image:
description: "1 when selected lanes require the bare Docker E2E image."
value: ${{ steps.plan.outputs.needs_bare_image }}
needs_e2e_image:
description: "1 when selected lanes require any Docker E2E image."
value: ${{ steps.plan.outputs.needs_e2e_image }}
needs_functional_image:
description: "1 when selected lanes require the functional Docker E2E image."
value: ${{ steps.plan.outputs.needs_functional_image }}
needs_live_image:
description: "1 when selected lanes require building the live Docker image."
value: ${{ steps.plan.outputs.needs_live_image }}
needs_package:
description: "1 when selected lanes require the OpenClaw package tarball."
value: ${{ steps.plan.outputs.needs_package }}
plan_json:
description: Path to the generated plan JSON.
value: ${{ steps.plan.outputs.plan_json }}
runs:
using: composite
steps:
- name: Plan Docker E2E lanes
id: plan
shell: bash
env:
MODE: ${{ inputs.mode }}
CHUNK: ${{ inputs.chunk }}
LANES: ${{ inputs.lanes }}
INCLUDE_OPENWEBUI: ${{ inputs.include-openwebui }}
INCLUDE_RELEASE_PATH_SUITES: ${{ inputs.include-release-path-suites }}
run: |
set -euo pipefail
mkdir -p .artifacts/docker-tests
case "$MODE" in
prepare)
plan_path=".artifacts/docker-tests/plan.json"
if [[ "$INCLUDE_RELEASE_PATH_SUITES" == "true" ]]; then
export OPENCLAW_DOCKER_ALL_PROFILE=release-path
export OPENCLAW_DOCKER_ALL_PLAN_RELEASE_ALL=1
elif [[ -n "$LANES" ]]; then
export OPENCLAW_DOCKER_ALL_LANES="$LANES"
elif [[ "$INCLUDE_OPENWEBUI" == "true" ]]; then
export OPENCLAW_DOCKER_ALL_LANES=openwebui
fi
;;
chunk)
if [[ -z "$CHUNK" ]]; then
echo "chunk input is required for Docker E2E chunk planning." >&2
exit 1
fi
export OPENCLAW_DOCKER_ALL_PROFILE=release-path
export OPENCLAW_DOCKER_ALL_CHUNK="$CHUNK"
plan_path=".artifacts/docker-tests/release-${CHUNK}-plan.json"
;;
targeted)
if [[ -z "$LANES" ]]; then
echo "lanes input is required for Docker E2E targeted planning." >&2
exit 1
fi
export OPENCLAW_DOCKER_ALL_LANES="$LANES"
plan_path=".artifacts/docker-tests/targeted-plan.json"
;;
*)
echo "mode must be prepare, chunk, or targeted. Got: $MODE" >&2
exit 1
;;
esac
export OPENCLAW_DOCKER_ALL_INCLUDE_OPENWEBUI="$INCLUDE_OPENWEBUI"
node scripts/test-docker-all.mjs --plan-json > "$plan_path"
node scripts/docker-e2e.mjs github-outputs "$plan_path" >> "$GITHUB_OUTPUT"
echo "plan_json=$plan_path" >> "$GITHUB_OUTPUT"
- name: Download OpenClaw Docker E2E package
if: inputs.hydrate-artifacts == 'true' && steps.plan.outputs.needs_package == '1'
uses: actions/download-artifact@v8
with:
name: ${{ inputs.package-artifact-name }}
path: .artifacts/docker-e2e-package
- name: Pull shared bare Docker E2E image
if: inputs.hydrate-artifacts == 'true' && steps.plan.outputs.needs_bare_image == '1'
shell: bash
run: |
set -euo pipefail
docker pull "${OPENCLAW_DOCKER_E2E_BARE_IMAGE}"
- name: Pull shared functional Docker E2E image
if: inputs.hydrate-artifacts == 'true' && steps.plan.outputs.needs_functional_image == '1'
shell: bash
run: |
set -euo pipefail
docker pull "${OPENCLAW_DOCKER_E2E_FUNCTIONAL_IMAGE}"
- name: Validate Docker E2E credentials
if: inputs.hydrate-artifacts == 'true'
shell: bash
env:
CREDENTIALS: ${{ steps.plan.outputs.credentials }}
run: |
set -euo pipefail
credentials=",$CREDENTIALS,"
if [[ "$credentials" == *",openai,"* ]]; then
[[ -n "${OPENAI_API_KEY:-}" ]] || {
echo "OPENAI_API_KEY is required for selected Docker E2E lanes." >&2
exit 1
}
fi
if [[ "$credentials" == *",anthropic,"* && -z "${ANTHROPIC_API_TOKEN:-}" && -z "${ANTHROPIC_API_KEY:-}" ]]; then
echo "ANTHROPIC_API_TOKEN or ANTHROPIC_API_KEY is required for selected Docker E2E lanes." >&2
exit 1
fi

View File

@@ -37,6 +37,7 @@ runs:
check-latest: false
- name: Setup pnpm + cache store
id: pnpm-cache
uses: ./.github/actions/setup-pnpm-store-cache
with:
pnpm-version: ${{ inputs.pnpm-version }}
@@ -97,3 +98,11 @@ runs:
install_args+=("$LOCKFILE_FLAG")
fi
pnpm "${install_args[@]}" || pnpm "${install_args[@]}"
- name: Save pnpm store cache
if: inputs.install-deps == 'true' && steps.pnpm-cache.outputs.cache-enabled == 'true' && steps.pnpm-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v5
continue-on-error: true
with:
path: ${{ steps.pnpm-cache.outputs.store-path }}
key: ${{ steps.pnpm-cache.outputs.primary-key }}

View File

@@ -14,9 +14,25 @@ inputs:
required: false
default: "true"
use-actions-cache:
description: Whether to restore/save pnpm store with actions/cache.
description: Whether to restore pnpm store with actions/cache.
required: false
default: "true"
outputs:
cache-enabled:
description: Whether actions/cache restore was enabled.
value: ${{ steps.pnpm-cache-config.outputs.enabled }}
cache-hit:
description: Whether the pnpm store cache had an exact key hit.
value: ${{ steps.pnpm-cache-restore.outputs.cache-hit }}
cache-matched-key:
description: Cache key matched by restore, if any.
value: ${{ steps.pnpm-cache-restore.outputs.cache-matched-key }}
primary-key:
description: Primary pnpm store cache key.
value: ${{ steps.pnpm-cache-config.outputs.primary-key }}
store-path:
description: Resolved pnpm store path.
value: ${{ steps.pnpm-store.outputs.path }}
runs:
using: composite
steps:
@@ -46,18 +62,29 @@ runs:
shell: bash
run: echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
- name: Restore pnpm store cache (exact key only)
if: inputs.use-actions-cache == 'true' && inputs.use-restore-keys != 'true'
uses: actions/cache@v5
with:
path: ${{ steps.pnpm-store.outputs.path }}
key: ${{ runner.os }}-pnpm-store-${{ inputs.cache-key-suffix }}-${{ hashFiles('pnpm-lock.yaml') }}
- name: Resolve pnpm store cache keys
id: pnpm-cache-config
shell: bash
env:
CACHE_KEY_SUFFIX: ${{ inputs.cache-key-suffix }}
LOCKFILE_HASH: ${{ hashFiles('pnpm-lock.yaml') }}
USE_ACTIONS_CACHE: ${{ inputs.use-actions-cache }}
USE_RESTORE_KEYS: ${{ inputs.use-restore-keys }}
run: |
set -euo pipefail
echo "enabled=$USE_ACTIONS_CACHE" >> "$GITHUB_OUTPUT"
echo "primary-key=${RUNNER_OS}-pnpm-store-${CACHE_KEY_SUFFIX}-${LOCKFILE_HASH}" >> "$GITHUB_OUTPUT"
if [ "$USE_RESTORE_KEYS" = "true" ]; then
echo "restore-keys=${RUNNER_OS}-pnpm-store-${CACHE_KEY_SUFFIX}-" >> "$GITHUB_OUTPUT"
else
echo "restore-keys=" >> "$GITHUB_OUTPUT"
fi
- name: Restore pnpm store cache (with fallback keys)
if: inputs.use-actions-cache == 'true' && inputs.use-restore-keys == 'true'
uses: actions/cache@v5
- name: Restore pnpm store cache
id: pnpm-cache-restore
if: inputs.use-actions-cache == 'true'
uses: actions/cache/restore@v5
with:
path: ${{ steps.pnpm-store.outputs.path }}
key: ${{ runner.os }}-pnpm-store-${{ inputs.cache-key-suffix }}-${{ hashFiles('pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-${{ inputs.cache-key-suffix }}-
key: ${{ steps.pnpm-cache-config.outputs.primary-key }}
restore-keys: ${{ steps.pnpm-cache-config.outputs.restore-keys }}

View File

@@ -0,0 +1,8 @@
name: openclaw-codeql-actions-critical-security
paths:
- .github/actions
- .github/workflows
paths-ignore:
- .github/workflows/stale.yml

View File

@@ -0,0 +1,30 @@
name: openclaw-codeql-android-critical-security
disable-default-queries: true
queries:
- uses: security-extended
query-filters:
# Android canvas intentionally runs trusted A2UI JavaScript; keep this profile focused on exploitable WebView edges.
- exclude:
id: java/android/websettings-javascript-enabled
# Gateway TLS already pins verified certificate SHA-256 fingerprints. OkHttp CertificatePinner pins SPKI hashes,
# so this query is noisy for OpenClaw's TOFU/local-gateway trust model and does not belong in the critical profile.
- exclude:
id: java/android/missing-certificate-pinning
paths:
- apps/android/app/src/main
paths-ignore:
- "**/.gradle"
- "**/build"
- "**/node_modules"
- "**/coverage"
- "**/*.generated.*"
- "**/*Test.kt"
- "**/*Test.java"
- "**/*Benchmark.kt"
- apps/android/app/src/test
- apps/android/benchmark

View File

@@ -0,0 +1,54 @@
name: openclaw-codeql-javascript-typescript-critical-quality
disable-default-queries: true
queries:
- uses: security-and-quality
query-filters:
- include:
problem.severity:
- error
- exclude:
tags:
- security
paths:
- src/agents/*auth*.ts
- src/agents/**/*auth*.ts
- src/agents/auth-health*.ts
- src/agents/auth-profiles
- src/agents/bash-tools.exec-host-shared.ts
- src/agents/sandbox
- src/agents/sandbox.ts
- src/agents/sandbox-*.ts
- src/config
- src/cron/service/jobs.ts
- src/cron/stagger.ts
- src/gateway/*auth*.ts
- src/gateway/**/*auth*.ts
- src/gateway/*secret*.ts
- src/gateway/**/*secret*.ts
- src/gateway/protocol/**/*secret*.ts
- src/gateway/resolve-configured-secret-input-string*.ts
- src/gateway/security-path*.ts
- src/gateway/server-methods/secrets*.ts
- src/infra/secret-file*.ts
- src/secrets
- src/security
paths-ignore:
- "**/node_modules"
- "**/coverage"
- "**/*.generated.ts"
- "**/*.bundle.js"
- "**/*-runtime.js"
- "**/*.test.ts"
- "**/*.test.tsx"
- "**/*.e2e.test.ts"
- "**/*.e2e.test.tsx"
- "**/*test-support*"
- "**/*test-helper*"
- "**/*mock*"
- "**/*fixture*"
- "**/*bench*"

View File

@@ -0,0 +1,57 @@
name: openclaw-codeql-javascript-typescript-critical-security
disable-default-queries: true
queries:
- uses: security-extended
query-filters:
- include:
precision:
- high
- very-high
- exclude:
problem.severity:
- recommendation
- warning
paths:
- src/agents/*auth*.ts
- src/agents/**/*auth*.ts
- src/agents/auth-health*.ts
- src/agents/auth-profiles
- src/agents/bash-tools.exec-host-shared.ts
- src/agents/sandbox
- src/agents/sandbox.ts
- src/agents/sandbox-*.ts
- src/config/*secret*.ts
- src/config/**/*secret*.ts
- src/cron/service/jobs.ts
- src/cron/stagger.ts
- src/gateway/*auth*.ts
- src/gateway/**/*auth*.ts
- src/gateway/*secret*.ts
- src/gateway/**/*secret*.ts
- src/gateway/protocol/**/*secret*.ts
- src/gateway/resolve-configured-secret-input-string*.ts
- src/gateway/security-path*.ts
- src/gateway/server-methods/secrets*.ts
- src/infra/secret-file*.ts
- src/secrets
- src/security
paths-ignore:
- "**/node_modules"
- "**/coverage"
- "**/*.generated.ts"
- "**/*.bundle.js"
- "**/*-runtime.js"
- "**/*.test.ts"
- "**/*.test.tsx"
- "**/*.e2e.test.ts"
- "**/*.e2e.test.tsx"
- "**/*test-support*"
- "**/*test-helper*"
- "**/*mock*"
- "**/*fixture*"
- "**/*bench*"

View File

@@ -1,18 +0,0 @@
name: openclaw-codeql-javascript-typescript
paths:
- src
- extensions
- ui/src
- skills
paths-ignore:
- apps
- dist
- docs
- "**/node_modules"
- "**/coverage"
- "**/*.test.ts"
- "**/*.test.tsx"
- "**/*.e2e.test.ts"
- "**/*.e2e.test.tsx"

View File

@@ -0,0 +1,17 @@
name: openclaw-codeql-macos-critical-security
disable-default-queries: true
queries:
- uses: security-extended
paths:
- apps/macos/Sources
paths-ignore:
- "**/.build"
- "**/.build/**"
- "**/DerivedData"
- "**/DerivedData/**"
- "**/*.generated.swift"
- "**/*Tests.swift"

View File

@@ -0,0 +1,76 @@
name: openclaw-codeql-plugin-boundary-critical-quality
disable-default-queries: true
queries:
- uses: security-and-quality
query-filters:
- include:
problem.severity:
- error
- exclude:
tags:
- security
paths:
- src/plugins/activation-planner.ts
- src/plugins/api-builder.ts
- src/plugins/bundled-compat.ts
- src/plugins/bundled-dir.ts
- src/plugins/bundled-plugin-metadata.ts
- src/plugins/bundled-public-surface-runtime-root.ts
- src/plugins/bundled-runtime-deps.ts
- src/plugins/bundled-runtime-root.ts
- src/plugins/captured-registration.ts
- src/plugins/config-activation-shared.ts
- src/plugins/config-contracts.ts
- src/plugins/config-normalization-shared.ts
- src/plugins/config-policy.ts
- src/plugins/config-schema.ts
- src/plugins/config-state.ts
- src/plugins/discovery.ts
- src/plugins/effective-plugin-ids.ts
- src/plugins/externalized-bundled-plugins.ts
- src/plugins/installed-plugin-index*.ts
- src/plugins/loader*.ts
- src/plugins/manifest*.ts
- src/plugins/module-export.ts
- src/plugins/package-entrypoints.ts
- src/plugins/plugin-registry*.ts
- src/plugins/provider-contract-public-artifacts.ts
- src/plugins/provider-public-artifacts.ts
- src/plugins/public-surface*.ts
- src/plugins/registry.ts
- src/plugins/registry-types.ts
- src/plugins/runtime
- src/plugins/runtime-state.ts
- src/plugins/runtime.ts
- src/plugins/sdk-alias.ts
- src/plugins/source-loader.ts
- src/plugins/types.ts
- src/plugins/validation-diagnostics.ts
- src/plugins/web-provider-public-artifacts*.ts
- src/plugin-sdk/*entry*.ts
- src/plugin-sdk/*facade*.ts
- src/plugin-sdk/api-baseline.ts
- src/plugin-sdk/config-schema.ts
- src/plugin-sdk/config-types.ts
- src/plugin-sdk/core.ts
- src/plugin-sdk/extension-shared.ts
paths-ignore:
- "**/node_modules"
- "**/coverage"
- "**/*.generated.ts"
- "**/*.bundle.js"
- "**/*-runtime.js"
- "**/*.test.ts"
- "**/*.test.tsx"
- "**/*.e2e.test.ts"
- "**/*.e2e.test.tsx"
- "**/*test-support*"
- "**/*test-helper*"
- "**/*mock*"
- "**/*fixture*"
- "**/*bench*"

33
.github/codex/prompts/docs-agent.md vendored Normal file
View File

@@ -0,0 +1,33 @@
# OpenClaw Docs Agent
You are maintaining OpenClaw documentation after a main-branch commit.
Goal: inspect the code changes and existing documentation, then update existing docs only when they are stale, incomplete, or misleading.
Hard limits:
- Edit existing files only.
- Do not create new docs pages, images, assets, scripts, code files, or workflow files.
- Do not delete or rename files.
- Do not change production code, tests, package metadata, generated baselines, lockfiles, or CI config.
- Keep changes minimal and factual.
- Use "plugin/plugins" in user-facing docs/UI/changelog; `extensions/` is only the internal workspace layout.
- Do not add a changelog entry unless the docs update describes a user-facing behavior/API change from the triggering commit.
Allowed paths:
- `docs/**`
- `README.md`
- `CHANGELOG.md`
Required workflow:
1. Run `pnpm docs:list` if available and read relevant docs based on `read_when` hints.
2. Inspect the triggering event via `$GITHUB_EVENT_PATH`, then review `$DOCS_AGENT_BASE_SHA..$DOCS_AGENT_HEAD_SHA` and its changed files. If either env var is missing, fall back to the event payload.
3. Update stale existing documentation, if needed.
4. Run `pnpm check:docs` if dependencies are available.
5. Leave the worktree clean if no docs need changes.
If `pnpm docs:check-mdx` or `pnpm check:docs` reports MDX parse errors, fix only the syntax needed for the listed existing docs files. Preserve prose meaning, frontmatter, code fences, and links; do not broadly rewrite translated or source content while repairing parser failures.
When uncertain, prefer no edit and explain the uncertainty in the final message.

View File

@@ -0,0 +1,25 @@
# OpenClaw Docs MDX Repair Agent
You are repairing generated OpenClaw documentation after a fast MDX validation failure.
Goal: fix only the MDX syntax errors reported by the checker.
Hard limits:
- Edit only existing Markdown/MDX files under the locale path named by `LOCALE`.
- Do not edit source English docs unless `LOCALE=en`.
- Do not edit code, workflows, package metadata, generated sync metadata, translation memory, or assets.
- Do not add, delete, or rename files.
- Preserve the meaning of translated prose.
- Preserve frontmatter, `x-i18n.source_hash`, links, code fences, JSX component names, and existing page structure.
- Avoid broad formatting or retranslation.
Required workflow:
1. Read `.openclaw-sync/mdx/${LOCALE}.json` when it exists.
2. Inspect only the listed files and nearby lines.
3. Fix the minimal syntax issue, such as broken JSX attribute quoting, mismatched component closing tags, raw `<` text, raw HTML comments, or accidental top-level `import`/`export` text.
4. Run `node source/scripts/check-docs-mdx.mjs "docs/${LOCALE}" --json-out ".openclaw-sync/mdx/${LOCALE}.json"`.
5. Leave no changes outside `docs/${LOCALE}`.
When uncertain, prefer the smallest escaping fix: backticks for literal words, `&lt;` for literal `<`, double quotes around JSX attribute values, and balanced component tags.

View File

@@ -0,0 +1,44 @@
# OpenClaw Test Performance Agent
You are maintaining OpenClaw test performance after a trusted main-branch CI run.
Goal: inspect the full-suite test performance report, then make small, coverage-preserving improvements to slow tests when the fix is clear. If the baseline report shows failing tests and the fix is obvious, fix those too.
Inputs:
- Baseline grouped report: `.artifacts/test-perf/baseline-before.json`
- Per-config Vitest JSON reports: `.artifacts/test-perf/baseline-before/vitest-json/`
- Per-config logs: `.artifacts/test-perf/baseline-before/logs/`
Hard limits:
- Preserve test coverage and behavioral intent.
- Do not delete, skip, weaken, or narrow test cases to make the suite faster.
- Do not add `test.skip`, `it.skip`, `describe.skip`, `test.only`, `it.only`, or `describe.only`.
- Do not update snapshots, generated baselines, inventories, ignore files, lockfiles, package metadata, CI workflows, or release metadata.
- Do not add dependencies.
- Do not create, delete, or rename files.
- Do not do broad refactors or style-only rewrites.
- Keep changes minimal and focused on the slow or failing tests you can justify from the report.
- Prefer no edit when a performance improvement is speculative.
- If `.artifacts/test-perf/baseline-before.json` has `"failed": true`, do not make performance-only edits. First inspect the failed config logs. Edit only when the test failure has an obvious, coverage-preserving fix. If no obvious failure fix exists, leave the worktree clean.
Good fixes:
- Replace broad partial module mocks, especially `importOriginal()` mocks, with narrow injected dependencies or local runtime seams.
- Avoid importing heavy barrels in hot tests when a narrow module or helper covers the same behavior.
- Add or adjust a production lazy/injection seam only when that is the narrowest way to preserve coverage while removing expensive imports or fixing an obvious mock/import failure.
- Move expensive setup from per-test hooks to shared setup only when state isolation remains correct.
- Reuse existing fixtures/builders instead of recreating expensive work per case.
- Mock expensive runtime boundaries directly: filesystem crawls, package registries, provider SDKs, network/process launch, browser/runtime scanners.
- Keep one integration smoke per boundary and test pure helpers directly, but only when the same behavior remains covered.
Required workflow:
1. Run `pnpm docs:list` if available, then read `docs/reference/test.md` and `docs/help/testing.md` sections about test performance.
2. Inspect `.artifacts/test-perf/baseline-before.json`. If `failed` is true, inspect the failed config logs before looking at slow files.
3. Pick at most a few low-risk files. When baseline failed, pick only files needed for the obvious failure fix; otherwise focus on the slowest files/configs. Explain the coverage-preserving reason in comments only if the code would otherwise be unclear.
4. Run targeted tests for changed files where possible. Use `pnpm test <path>` and optionally `pnpm test:perf:imports <path>`.
5. Leave the worktree clean if no safe improvement exists.
When uncertain, make no edit and explain the uncertainty in the final message.

70
.github/labeler.yml vendored
View File

@@ -3,6 +3,12 @@
- any-glob-to-any-file:
- "extensions/bluebubbles/**"
- "docs/channels/bluebubbles.md"
"plugin: azure-speech":
- changed-files:
- any-glob-to-any-file:
- "extensions/azure-speech/**"
- "docs/providers/azure-speech.md"
- "docs/tools/tts.md"
"channel: discord":
- changed-files:
- any-glob-to-any-file:
@@ -24,6 +30,27 @@
- any-glob-to-any-file:
- "extensions/googlechat/**"
- "docs/channels/googlechat.md"
"plugin: google-meet":
- changed-files:
- any-glob-to-any-file:
- "extensions/google-meet/**"
- "docs/plugins/google-meet.md"
"plugin: migrate-hermes":
- changed-files:
- any-glob-to-any-file:
- "extensions/migrate-hermes/**"
- "docs/cli/migrate.md"
"plugin: migrate-claude":
- changed-files:
- any-glob-to-any-file:
- "extensions/migrate-claude/**"
- "docs/cli/migrate.md"
- "docs/install/migrating-claude.md"
"plugin: bonjour":
- changed-files:
- any-glob-to-any-file:
- "extensions/bonjour/**"
- "docs/gateway/bonjour.md"
"channel: imessage":
- changed-files:
- any-glob-to-any-file:
@@ -85,6 +112,11 @@
- any-glob-to-any-file:
- "extensions/slack/**"
- "docs/channels/slack.md"
"channel: synology-chat":
- changed-files:
- any-glob-to-any-file:
- "extensions/synology-chat/**"
- "docs/channels/synology-chat.md"
"channel: telegram":
- changed-files:
- any-glob-to-any-file:
@@ -217,6 +249,10 @@
- changed-files:
- any-glob-to-any-file:
- "extensions/diagnostics-otel/**"
"extensions: diagnostics-prometheus":
- changed-files:
- any-glob-to-any-file:
- "extensions/diagnostics-prometheus/**"
"extensions: llm-task":
- changed-files:
- any-glob-to-any-file:
@@ -269,10 +305,20 @@
- changed-files:
- any-glob-to-any-file:
- "extensions/byteplus/**"
"extensions: cerebras":
- changed-files:
- any-glob-to-any-file:
- "extensions/cerebras/**"
- "docs/providers/cerebras.md"
"extensions: deepseek":
- changed-files:
- any-glob-to-any-file:
- "extensions/deepseek/**"
"extensions: deepinfra":
- changed-files:
- any-glob-to-any-file:
- "extensions/deepinfra/**"
- "docs/providers/deepinfra.md"
"extensions: tencent":
- changed-files:
- any-glob-to-any-file:
@@ -297,6 +343,11 @@
- changed-files:
- any-glob-to-any-file:
- "extensions/huggingface/**"
"extensions: inworld":
- changed-files:
- any-glob-to-any-file:
- "extensions/inworld/**"
- "docs/providers/inworld.md"
"extensions: kilocode":
- changed-files:
- any-glob-to-any-file:
@@ -305,6 +356,11 @@
- changed-files:
- any-glob-to-any-file:
- "extensions/lmstudio/**"
"extensions: litellm":
- changed-files:
- any-glob-to-any-file:
- "extensions/litellm/**"
- "docs/providers/litellm.md"
"extensions: openai":
- changed-files:
- any-glob-to-any-file:
@@ -341,6 +397,11 @@
- changed-files:
- any-glob-to-any-file:
- "extensions/qianfan/**"
"extensions: senseaudio":
- changed-files:
- any-glob-to-any-file:
- "extensions/senseaudio/**"
- "docs/providers/senseaudio.md"
"extensions: synthetic":
- changed-files:
- any-glob-to-any-file:
@@ -357,6 +418,11 @@
- changed-files:
- any-glob-to-any-file:
- "extensions/together/**"
"extensions: tts-local-cli":
- changed-files:
- any-glob-to-any-file:
- "extensions/tts-local-cli/**"
- "docs/tools/tts.md"
"extensions: venice":
- changed-files:
- any-glob-to-any-file:
@@ -377,3 +443,7 @@
- changed-files:
- any-glob-to-any-file:
- "extensions/fal/**"
"extensions: gradium":
- changed-files:
- any-glob-to-any-file:
- "extensions/gradium/**"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

View File

@@ -5,8 +5,8 @@ on:
types: [opened, edited, labeled]
issue_comment:
types: [created]
pull_request_target: # zizmor: ignore[dangerous-triggers] maintainer-owned label automation; no untrusted checkout or code execution
types: [labeled]
pull_request_target: # zizmor: ignore[dangerous-triggers] maintainer-owned label automation; trusted base checkout only, no untrusted PR code execution
types: [opened, edited, synchronize, reopened, labeled]
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
@@ -20,10 +20,15 @@ permissions: {}
jobs:
auto-response:
permissions:
contents: read
issues: write
pull-requests: write
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.sha }}
persist-credentials: false
- uses: actions/create-github-app-token@v3
id: app-token
continue-on-error: true
@@ -36,499 +41,15 @@ jobs:
with:
app-id: "2971289"
private-key: ${{ secrets.GH_APP_PRIVATE_KEY_FALLBACK }}
- name: Handle labeled items
- name: Run Barnacle auto-response
uses: actions/github-script@v9
with:
github-token: ${{ steps.app-token.outputs.token || steps.app-token-fallback.outputs.token }}
script: |
// Labels prefixed with "r:" are auto-response triggers.
const activePrLimit = 10;
const rules = [
{
label: "r: skill",
close: true,
message:
"Thanks for the contribution! New skills should be published to [Clawhub](https://clawhub.ai) for everyone to use. Were keeping the core lean on skills, so Im closing this out.",
},
{
label: "r: support",
close: true,
message:
"Please use [our support server](https://discord.gg/clawd) and ask in #help or #users-helping-users to resolve this, or follow the stuck FAQ at https://docs.openclaw.ai/help/faq#im-stuck-whats-the-fastest-way-to-get-unstuck.",
},
{
label: "r: no-ci-pr",
close: true,
message:
"Please don't make PRs for test failures on main.\n\n" +
"The team is aware of those and will handle them directly on the codebase, not only fixing the tests but also investigating what the root cause is. Having to sift through test-fix-PRs (including some that have been out of date for weeks...) on top of that doesn't help. There are already way too many PRs for humans to manage; please don't make the flood worse.\n\n" +
"Thank you.",
},
{
label: "r: too-many-prs",
close: true,
message:
`Closing this PR because the author has more than ${activePrLimit} active PRs in this repo. ` +
"Please reduce the active PR queue and reopen or resubmit once it is back under the limit. You can close your own PRs to get back under the limit.",
},
{
label: "r: testflight",
close: true,
commentTriggers: ["testflight"],
message: "Not available, build from source.",
},
{
label: "r: third-party-extension",
close: true,
message:
"Please make this as a third-party plugin that you maintain yourself in your own repo. Docs: https://docs.openclaw.ai/plugin. Feel free to open a PR after to add it to our community plugins page: https://docs.openclaw.ai/plugins/community",
},
{
label: "r: moltbook",
close: true,
lock: true,
lockReason: "off-topic",
commentTriggers: ["moltbook"],
message:
"OpenClaw is not affiliated with Moltbook, and issues related to Moltbook should not be submitted here.",
},
];
const maintainerTeam = "maintainer";
const pingWarningMessage =
"Please dont spam-ping multiple maintainers at once. Be patient, or join our community Discord for help: https://discord.gg/clawd";
const mentionRegex = /@([A-Za-z0-9-]+)/g;
const maintainerCache = new Map();
const normalizeLogin = (login) => login.toLowerCase();
const bugSubtypeLabelSpecs = {
regression: {
color: "D93F0B",
description: "Behavior that previously worked and now fails",
},
"bug:crash": {
color: "B60205",
description: "Process/app exits unexpectedly or hangs",
},
"bug:behavior": {
color: "D73A4A",
description: "Incorrect behavior without a crash",
},
};
const bugTypeToLabel = {
"Regression (worked before, now fails)": "regression",
"Crash (process/app exits or hangs)": "bug:crash",
"Behavior bug (incorrect output/state without crash)": "bug:behavior",
};
const bugSubtypeLabels = Object.keys(bugSubtypeLabelSpecs);
const extractIssueFormValue = (body, field) => {
if (!body) {
return "";
}
const escapedField = field.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const regex = new RegExp(
`(?:^|\\n)###\\s+${escapedField}\\s*\\n([\\s\\S]*?)(?=\\n###\\s+|$)`,
"i",
);
const match = body.match(regex);
if (!match) {
return "";
}
for (const line of match[1].split("\n")) {
const trimmed = line.trim();
if (trimmed) {
return trimmed;
}
}
return "";
};
const ensureLabelExists = async (name, color, description) => {
try {
await github.rest.issues.getLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name,
});
} catch (error) {
if (error?.status !== 404) {
throw error;
}
await github.rest.issues.createLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name,
color,
description,
});
}
};
const syncBugSubtypeLabel = async (issue, labelSet) => {
if (!labelSet.has("bug")) {
return;
}
const selectedBugType = extractIssueFormValue(issue.body ?? "", "Bug type");
const targetLabel = bugTypeToLabel[selectedBugType];
if (!targetLabel) {
return;
}
const targetSpec = bugSubtypeLabelSpecs[targetLabel];
await ensureLabelExists(targetLabel, targetSpec.color, targetSpec.description);
for (const subtypeLabel of bugSubtypeLabels) {
if (subtypeLabel === targetLabel) {
continue;
}
if (!labelSet.has(subtypeLabel)) {
continue;
}
try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
name: subtypeLabel,
});
labelSet.delete(subtypeLabel);
} catch (error) {
if (error?.status !== 404) {
throw error;
}
}
}
if (!labelSet.has(targetLabel)) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
labels: [targetLabel],
});
labelSet.add(targetLabel);
}
};
const isMaintainer = async (login) => {
if (!login) {
return false;
}
const normalized = normalizeLogin(login);
if (maintainerCache.has(normalized)) {
return maintainerCache.get(normalized);
}
let isMember = false;
try {
const membership = await github.rest.teams.getMembershipForUserInOrg({
org: context.repo.owner,
team_slug: maintainerTeam,
username: normalized,
});
isMember = membership?.data?.state === "active";
} catch (error) {
if (error?.status !== 404) {
throw error;
}
}
maintainerCache.set(normalized, isMember);
return isMember;
};
const countMaintainerMentions = async (body, authorLogin) => {
if (!body) {
return 0;
}
const normalizedAuthor = authorLogin ? normalizeLogin(authorLogin) : "";
if (normalizedAuthor && (await isMaintainer(normalizedAuthor))) {
return 0;
}
const haystack = body.toLowerCase();
const teamMention = `@${context.repo.owner.toLowerCase()}/${maintainerTeam}`;
if (haystack.includes(teamMention)) {
return 3;
}
const mentions = new Set();
for (const match of body.matchAll(mentionRegex)) {
mentions.add(normalizeLogin(match[1]));
}
if (normalizedAuthor) {
mentions.delete(normalizedAuthor);
}
let count = 0;
for (const login of mentions) {
if (await isMaintainer(login)) {
count += 1;
}
}
return count;
};
const triggerLabel = "trigger-response";
const activePrLimitLabel = "r: too-many-prs";
const activePrLimitOverrideLabel = "r: too-many-prs-override";
const target = context.payload.issue ?? context.payload.pull_request;
if (!target) {
return;
}
const labelSet = new Set(
(target.labels ?? [])
.map((label) => (typeof label === "string" ? label : label?.name))
.filter((name) => typeof name === "string"),
const { pathToFileURL } = require("node:url");
const moduleUrl = pathToFileURL(
`${process.env.GITHUB_WORKSPACE}/scripts/github/barnacle-auto-response.mjs`,
);
const { runBarnacleAutoResponse } = await import(moduleUrl.href);
const issue = context.payload.issue;
const pullRequest = context.payload.pull_request;
const comment = context.payload.comment;
if (comment) {
const authorLogin = comment.user?.login ?? "";
if (comment.user?.type === "Bot" || authorLogin.endsWith("[bot]")) {
return;
}
const commentBody = comment.body ?? "";
const responses = [];
const mentionCount = await countMaintainerMentions(commentBody, authorLogin);
if (mentionCount >= 3) {
responses.push(pingWarningMessage);
}
const commentHaystack = commentBody.toLowerCase();
const commentRule = rules.find((item) =>
(item.commentTriggers ?? []).some((trigger) =>
commentHaystack.includes(trigger),
),
);
if (commentRule) {
responses.push(commentRule.message);
}
if (responses.length > 0) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: target.number,
body: responses.join("\n\n"),
});
}
return;
}
if (issue) {
const action = context.payload.action;
if (action === "opened" || action === "edited") {
const issueText = `${issue.title ?? ""}\n${issue.body ?? ""}`.trim();
const authorLogin = issue.user?.login ?? "";
const mentionCount = await countMaintainerMentions(
issueText,
authorLogin,
);
if (mentionCount >= 3) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
body: pingWarningMessage,
});
}
await syncBugSubtypeLabel(issue, labelSet);
}
}
const hasTriggerLabel = labelSet.has(triggerLabel);
if (hasTriggerLabel) {
labelSet.delete(triggerLabel);
try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: target.number,
name: triggerLabel,
});
} catch (error) {
if (error?.status !== 404) {
throw error;
}
}
}
const isLabelEvent = context.payload.action === "labeled";
if (!hasTriggerLabel && !isLabelEvent) {
return;
}
if (issue) {
const title = issue.title ?? "";
const body = issue.body ?? "";
const haystack = `${title}\n${body}`.toLowerCase();
const hasMoltbookLabel = labelSet.has("r: moltbook");
const hasTestflightLabel = labelSet.has("r: testflight");
const hasSecurityLabel = labelSet.has("security");
if (title.toLowerCase().includes("security") && !hasSecurityLabel) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
labels: ["security"],
});
labelSet.add("security");
}
if (title.toLowerCase().includes("testflight") && !hasTestflightLabel) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
labels: ["r: testflight"],
});
labelSet.add("r: testflight");
}
if (haystack.includes("moltbook") && !hasMoltbookLabel) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
labels: ["r: moltbook"],
});
labelSet.add("r: moltbook");
}
}
const invalidLabel = "invalid";
const spamLabel = "r: spam";
const dirtyLabel = "dirty";
const badBarnacleLabel = "bad-barnacle";
const noisyPrMessage =
"Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch.";
if (pullRequest) {
if (labelSet.has(badBarnacleLabel)) {
core.info(`Skipping PR auto-response checks for #${pullRequest.number} because ${badBarnacleLabel} is present.`);
return;
}
if (labelSet.has(dirtyLabel)) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pullRequest.number,
body: noisyPrMessage,
});
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pullRequest.number,
state: "closed",
});
return;
}
const labelCount = labelSet.size;
if (labelCount > 20) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pullRequest.number,
body: noisyPrMessage,
});
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pullRequest.number,
state: "closed",
});
return;
}
if (labelSet.has(spamLabel)) {
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pullRequest.number,
state: "closed",
});
await github.rest.issues.lock({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pullRequest.number,
lock_reason: "spam",
});
return;
}
if (labelSet.has(invalidLabel)) {
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pullRequest.number,
state: "closed",
});
return;
}
}
if (issue && labelSet.has(spamLabel)) {
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
state: "closed",
state_reason: "not_planned",
});
await github.rest.issues.lock({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
lock_reason: "spam",
});
return;
}
if (issue && labelSet.has(invalidLabel)) {
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
state: "closed",
state_reason: "not_planned",
});
return;
}
if (pullRequest && labelSet.has(activePrLimitOverrideLabel)) {
labelSet.delete(activePrLimitLabel);
}
const rule = rules.find((item) => labelSet.has(item.label));
if (!rule) {
return;
}
const issueNumber = target.number;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
body: rule.message,
});
if (rule.close) {
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
state: "closed",
});
}
if (rule.lock) {
await github.rest.issues.lock({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
lock_reason: rule.lockReason ?? "resolved",
});
}
await runBarnacleAutoResponse({ github, context, core });

View File

@@ -0,0 +1,224 @@
name: Blacksmith Build Artifacts 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"
jobs:
build-artifacts:
permissions:
contents: read
name: "build-artifacts"
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 35
steps:
- name: Begin Testbox
uses: useblacksmith/begin-testbox@d0e04585c26905fdd92c94a09c159544c7ee1b67
with:
testbox_id: ${{ inputs.testbox_id }}
- name: Checkout
shell: bash
env:
CHECKOUT_REPO: ${{ github.repository }}
CHECKOUT_SHA: ${{ github.sha }}
CHECKOUT_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
workdir="$GITHUB_WORKSPACE"
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 30s git -C "$workdir" \
-c protocol.version=2 \
-c "http.https://github.com/.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: Resolve release dist cache seeds
id: dist-cache-seeds
shell: bash
run: |
set -euo pipefail
cache_prefix="${RUNNER_OS}-dist-build-"
declare -A seen=()
resolve_tag_sha() {
local tag="$1"
local direct=""
local peeled=""
while read -r sha ref; do
if [[ "$ref" == "refs/tags/${tag}^{}" ]]; then
peeled="$sha"
elif [[ "$ref" == "refs/tags/${tag}" ]]; then
direct="$sha"
fi
done < <(git ls-remote --tags origin "refs/tags/${tag}" "refs/tags/${tag}^{}")
printf '%s\n' "${peeled:-$direct}"
}
{
echo "restore-keys<<EOF"
for dist_tag in beta latest; do
version="$(npm view "openclaw@${dist_tag}" version 2>/dev/null || true)"
if [[ -z "$version" ]]; then
echo "Could not resolve npm dist-tag ${dist_tag}; skipping cache seed." >&2
continue
fi
sha="$(resolve_tag_sha "v${version}")"
if [[ -z "$sha" ]]; then
echo "Could not resolve git tag v${version}; skipping cache seed." >&2
continue
fi
key="${cache_prefix}${sha}"
if [[ -z "${seen[$key]+x}" ]]; then
echo "$key"
seen[$key]=1
fi
done
echo "${cache_prefix}"
echo "EOF"
} >> "$GITHUB_OUTPUT"
- name: Restore dist build cache
id: dist-cache
uses: actions/cache/restore@v5
with:
path: |
.artifacts/build-all-cache/
dist/
dist-runtime/
key: ${{ runner.os }}-dist-build-${{ github.sha }}
restore-keys: ${{ steps.dist-cache-seeds.outputs.restore-keys }}
- name: Build dist on cache miss
if: steps.dist-cache.outputs.cache-hit != 'true'
run: pnpm build:ci-artifacts
- name: Build Control UI on cache miss
if: steps.dist-cache.outputs.cache-hit != 'true'
run: pnpm ui:build
- name: Verify build artifacts
shell: bash
run: |
set -euo pipefail
test -d dist
test -d dist-runtime
if [[ ! -f dist/index.js && ! -f dist/index.mjs ]]; then
echo "Missing dist/index.js or dist/index.mjs" >&2
exit 1
fi
test -f dist/build-info.json
test -f dist/control-ui/index.html
- name: Save dist build cache
if: steps.dist-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v5
with:
path: |
.artifacts/build-all-cache/
dist/
dist-runtime/
key: ${{ runner.os }}-dist-build-${{ github.sha }}
- name: Prepare Testbox shell
shell: bash
run: |
set -euo pipefail
git fetch --no-tags --depth=50 origin "+refs/heads/main:refs/remotes/origin/main"
node_bin="$(dirname "$(node -p 'process.execPath')")"
pnpm_bin="$(command -v pnpm)"
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 ln -sf "$pnpm_bin" /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 }}
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: always()
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"

View File

@@ -25,7 +25,7 @@ jobs:
timeout-minutes: 30
steps:
- name: Begin Testbox
uses: useblacksmith/begin-testbox@v2
uses: useblacksmith/begin-testbox@d0e04585c26905fdd92c94a09c159544c7ee1b67
with:
testbox_id: ${{ inputs.testbox_id }}
- name: Checkout
@@ -62,18 +62,18 @@ jobs:
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}/2 succeeded"
echo "checkout attempt ${attempt}/5 succeeded"
}
for attempt in 1 2; do
for attempt in 1 2 3 4 5; do
if checkout_attempt "$attempt"; then
exit 0
fi
echo "checkout attempt ${attempt}/2 failed"
echo "checkout attempt ${attempt}/5 failed"
sleep $((attempt * 5))
done
echo "checkout failed after 2 attempts" >&2
echo "checkout failed after 5 attempts" >&2
exit 1
- name: Setup Node environment
uses: ./.github/actions/setup-node-env
@@ -93,8 +93,35 @@ jobs:
sudo ln -sf "$node_bin/npx" /usr/local/bin/npx
sudo ln -sf "$node_bin/corepack" /usr/local/bin/corepack
sudo ln -sf "$pnpm_bin" /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 }}
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@v2
uses: useblacksmith/run-testbox@5ca05834db1d3813554d1dd109e5f2087a8d7cbc
if: always()
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,66 @@
name: ClawSweeper Dispatch
on:
issues:
types: [opened, reopened, edited, labeled, unlabeled]
pull_request_target: # zizmor: ignore[dangerous-triggers] maintainer-owned external dispatch; no checkout or untrusted PR code execution
types: [opened, reopened, synchronize, ready_for_review, edited, labeled, unlabeled]
permissions:
contents: read
concurrency:
group: clawsweeper-dispatch-${{ github.repository }}-${{ github.event.issue.number || github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
jobs:
dispatch:
runs-on: ubuntu-latest
if: ${{ !(endsWith(github.actor, '[bot]') && (github.event.action == 'labeled' || github.event.action == 'unlabeled')) }}
env:
HAS_CLAWSWEEPER_APP_PRIVATE_KEY: ${{ secrets.CLAWSWEEPER_APP_PRIVATE_KEY != '' }}
CLAWSWEEPER_APP_CLIENT_ID: Iv23liOECG0slfuhz093
SUPERSEDES_IN_PROGRESS: ${{ (github.event.action == 'edited' || github.event.action == 'synchronize' || github.event.action == 'ready_for_review') && 'true' || 'false' }}
steps:
- name: Debounce bursty metadata events
if: ${{ github.event.action == 'labeled' || github.event.action == 'unlabeled' }}
run: sleep 20
- name: Create ClawSweeper dispatch token
id: token
if: ${{ env.HAS_CLAWSWEEPER_APP_PRIVATE_KEY == 'true' }}
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
with:
client-id: ${{ env.CLAWSWEEPER_APP_CLIENT_ID }}
private-key: ${{ secrets.CLAWSWEEPER_APP_PRIVATE_KEY }}
owner: openclaw
repositories: clawsweeper
- name: Dispatch exact ClawSweeper review
env:
GH_TOKEN: ${{ steps.token.outputs.token || secrets.OPENCLAW_GH_TOKEN }}
TARGET_REPO: ${{ github.repository }}
ITEM_NUMBER: ${{ github.event.issue.number || github.event.pull_request.number }}
ITEM_KIND: ${{ github.event_name == 'pull_request_target' && 'pull_request' || 'issue' }}
SOURCE_EVENT: ${{ github.event_name }}
SOURCE_ACTION: ${{ github.event.action }}
run: |
if [ -z "$GH_TOKEN" ]; then
echo "::notice::Skipping ClawSweeper dispatch because no dispatch credential is configured."
exit 0
fi
payload="$(jq -nc \
--arg target_repo "$TARGET_REPO" \
--argjson item_number "$ITEM_NUMBER" \
--arg item_kind "$ITEM_KIND" \
--arg source_event "$SOURCE_EVENT" \
--arg source_action "$SOURCE_ACTION" \
--argjson supersedes_in_progress "$SUPERSEDES_IN_PROGRESS" \
'{event_type:"clawsweeper_item",client_payload:{target_repo:$target_repo,item_number:$item_number,item_kind:$item_kind,source_event:$source_event,source_action:$source_action,supersedes_in_progress:$supersedes_in_progress}}')"
if gh api repos/openclaw/clawsweeper/dispatches \
--method POST \
--input - <<< "$payload"; then
echo "Dispatched ClawSweeper review."
else
echo "::warning::Skipping ClawSweeper dispatch because the configured credential could not dispatch to openclaw/clawsweeper."
fi

View File

@@ -0,0 +1,51 @@
name: CodeQL Android Critical Security
on:
workflow_dispatch:
schedule:
- cron: "0 7 * * *"
concurrency:
group: codeql-android-critical-security-${{ github.workflow }}-${{ github.event_name == 'workflow_dispatch' && github.run_id || github.sha }}
cancel-in-progress: false
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
permissions:
actions: read
contents: read
security-events: write
jobs:
android:
name: Critical Security (android)
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 45
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
submodules: false
- name: Setup Java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: temurin
java-version: "21"
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
with:
languages: java-kotlin
build-mode: manual
config-file: ./.github/codeql/codeql-android-critical-security.yml
- name: Build Android for CodeQL
working-directory: apps/android
run: ./gradlew --no-daemon :app:assemblePlayDebug
- name: Analyze
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
with:
category: "/codeql-critical-security/android"

View File

@@ -0,0 +1,61 @@
name: CodeQL Critical Quality
on:
workflow_dispatch:
schedule:
- cron: "30 6 * * *"
concurrency:
group: codeql-critical-quality-${{ github.workflow }}-${{ github.event_name == 'workflow_dispatch' && github.run_id || github.sha }}
cancel-in-progress: false
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
permissions:
actions: read
contents: read
security-events: write
jobs:
javascript-typescript:
name: Critical Quality (javascript-typescript)
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
submodules: false
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
with:
languages: javascript-typescript
config-file: ./.github/codeql/codeql-javascript-typescript-critical-quality.yml
- name: Analyze
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
with:
category: "/codeql-critical-quality/javascript-typescript"
plugin-boundary:
name: Critical Quality (plugin-boundary)
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 25
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
submodules: false
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
with:
languages: javascript-typescript
config-file: ./.github/codeql/codeql-plugin-boundary-critical-quality.yml
- name: Analyze
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
with:
category: "/codeql-critical-quality/plugin-boundary"

View File

@@ -0,0 +1,89 @@
name: CodeQL macOS Critical Security
on:
workflow_dispatch:
schedule:
- cron: "0 8 * * 1"
concurrency:
group: codeql-macos-critical-security-${{ github.workflow }}-${{ github.event_name == 'workflow_dispatch' && github.run_id || github.sha }}
cancel-in-progress: false
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
permissions:
actions: read
contents: read
security-events: write
jobs:
macos:
name: Critical Security (macOS)
runs-on: blacksmith-6vcpu-macos-latest
timeout-minutes: 45
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
submodules: false
- name: Select Xcode
run: |
sudo xcode-select -s /Applications/Xcode_26.1.app
xcodebuild -version
swift --version
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
with:
languages: swift
build-mode: manual
config-file: ./.github/codeql/codeql-macos-critical-security.yml
- name: Build macOS for CodeQL
run: swift build --package-path apps/macos --product OpenClaw
- name: Analyze
id: analyze
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
with:
output: sarif-results
upload: failure-only
category: "/codeql-critical-security/macos"
- name: Remove dependency build results
env:
SARIF_OUTPUT: sarif-results
run: |
set -euo pipefail
shopt -s nullglob
if [ ! -d "$SARIF_OUTPUT" ]; then
echo "SARIF output directory not found: $SARIF_OUTPUT" >&2
exit 1
fi
mkdir -p sarif-results-filtered
files=("$SARIF_OUTPUT"/*.sarif)
if [ "${#files[@]}" -eq 0 ]; then
echo "No SARIF files found in $SARIF_OUTPUT" >&2
exit 1
fi
for file in "${files[@]}"; do
jq '
def in_dependency_build:
((.locations // []) | length > 0)
and all(.locations[]; (.physicalLocation.artifactLocation.uri? // "") | test("^apps/macos/\\.build/"));
.runs |= map(.results = ((.results // []) | map(select(in_dependency_build | not))))
' "$file" > "sarif-results-filtered/$(basename "$file")"
done
- name: Upload filtered SARIF
uses: github/codeql-action/upload-sarif@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
with:
sarif_file: sarif-results-filtered
category: "/codeql-critical-security/macos"

View File

@@ -2,12 +2,21 @@ name: CodeQL
on:
workflow_dispatch:
inputs:
profile:
description: CodeQL security profile to run
required: false
default: all
type: choice
options:
- all
- security
schedule:
- cron: "0 6 * * *"
concurrency:
group: codeql-${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
group: codeql-${{ github.workflow }}-${{ github.event_name == 'workflow_dispatch' && github.run_id || github.sha }}
cancel-in-progress: false
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
@@ -18,121 +27,36 @@ permissions:
security-events: write
jobs:
analyze:
name: Analyze (${{ matrix.language }})
critical-security:
name: Critical Security (${{ matrix.language }})
if: ${{ github.event_name != 'workflow_dispatch' || inputs.profile == 'all' || inputs.profile == 'security' }}
runs-on: ${{ matrix.runs_on }}
timeout-minutes: ${{ matrix.timeout_minutes }}
strategy:
fail-fast: false
matrix:
include:
- language: javascript-typescript
runs_on: blacksmith-16vcpu-ubuntu-2404
needs_node: true
needs_python: false
needs_java: false
needs_swift_tools: false
needs_manual_build: false
needs_autobuild: false
config_file: ./.github/codeql/codeql-javascript-typescript.yml
runs_on: blacksmith-8vcpu-ubuntu-2404
timeout_minutes: 25
config_file: ./.github/codeql/codeql-javascript-typescript-critical-security.yml
- language: actions
runs_on: blacksmith-16vcpu-ubuntu-2404
needs_node: false
needs_python: false
needs_java: false
needs_swift_tools: false
needs_manual_build: false
needs_autobuild: false
config_file: ""
- language: python
runs_on: blacksmith-16vcpu-ubuntu-2404
needs_node: false
needs_python: true
needs_java: false
needs_swift_tools: false
needs_manual_build: false
needs_autobuild: false
config_file: ""
- language: java-kotlin
runs_on: blacksmith-16vcpu-ubuntu-2404
needs_node: false
needs_python: false
needs_java: true
needs_swift_tools: false
needs_manual_build: true
needs_autobuild: false
config_file: ""
- language: swift
runs_on: ${{ github.repository == 'openclaw/openclaw' && 'blacksmith-12vcpu-macos-latest' || 'macos-latest' }}
needs_node: false
needs_python: false
needs_java: false
needs_swift_tools: true
needs_manual_build: true
needs_autobuild: false
config_file: ""
runs_on: blacksmith-8vcpu-ubuntu-2404
timeout_minutes: 10
config_file: ./.github/codeql/codeql-actions-critical-security.yml
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
submodules: false
- name: Setup Node environment
if: matrix.needs_node
uses: ./.github/actions/setup-node-env
with:
install-bun: "false"
- name: Setup Python
if: matrix.needs_python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
with:
python-version: "3.12"
- name: Setup Java
if: matrix.needs_java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: temurin
java-version: "21"
- name: Setup Swift build tools
if: matrix.needs_swift_tools
run: |
sudo xcode-select -s /Applications/Xcode_26.1.app
xcodebuild -version
brew install xcodegen swiftlint swiftformat
swift --version
- name: Initialize CodeQL
uses: github/codeql-action/init@b25d0ebf40e5b63ee81e1bd6e5d2a12b7c2aeb61 # v4
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
with:
languages: ${{ matrix.language }}
queries: security-and-quality
config-file: ${{ matrix.config_file || '' }}
- name: Autobuild
if: matrix.needs_autobuild
uses: github/codeql-action/autobuild@b25d0ebf40e5b63ee81e1bd6e5d2a12b7c2aeb61 # v4
- name: Build Android for CodeQL
if: matrix.language == 'java-kotlin'
working-directory: apps/android
run: ./gradlew --no-daemon :app:assemblePlayDebug
- name: Build Swift for CodeQL
if: matrix.language == 'swift'
run: |
set -euo pipefail
swift build --package-path apps/macos --configuration release
cd apps/ios
xcodegen generate
xcodebuild build \
-project OpenClaw.xcodeproj \
-scheme OpenClaw \
-destination "generic/platform=iOS Simulator" \
CODE_SIGNING_ALLOWED=NO
config-file: ${{ matrix.config_file }}
- name: Analyze
uses: github/codeql-action/analyze@b25d0ebf40e5b63ee81e1bd6e5d2a12b7c2aeb61 # v4
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4
with:
category: "/language:${{ matrix.language }}"
category: "/codeql-critical-security/${{ matrix.language }}"

View File

@@ -49,7 +49,7 @@ jobs:
run: |
set -euo pipefail
all_locales_json='["zh-CN","zh-TW","pt-BR","de","es","ja-JP","ko","fr","tr","uk","id","pl"]'
all_locales_json='["zh-CN","zh-TW","pt-BR","de","es","ja-JP","ko","fr","tr","uk","id","pl","th"]'
if [ "$EVENT_NAME" != "push" ]; then
echo "has_locales=true" >> "$GITHUB_OUTPUT"
@@ -137,7 +137,7 @@ jobs:
env:
OPENAI_API_KEY: ${{ secrets.OPENCLAW_DOCS_I18N_OPENAI_API_KEY || secrets.OPENAI_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
OPENCLAW_CONTROL_UI_I18N_MODEL: gpt-5.4
OPENCLAW_CONTROL_UI_I18N_MODEL: ${{ vars.OPENCLAW_CI_OPENAI_MODEL_BARE }}
OPENCLAW_CONTROL_UI_I18N_THINKING: low
LOCALE: ${{ matrix.locale }}
run: node --import tsx scripts/control-ui-i18n.ts sync --locale "${LOCALE}" --write

View File

@@ -55,6 +55,7 @@ jobs:
# WARNING: KEEP MANUAL BACKFILLS GATED BY THE docker-release ENVIRONMENT.
runs-on: ubuntu-24.04
environment: docker-release
permissions: {}
steps:
- name: Approve Docker backfill
env:
@@ -63,7 +64,7 @@ jobs:
# KEEP THIS WORKFLOW ON GITHUB-HOSTED RUNNERS.
# DO NOT MOVE IT BACK TO BLACKSMITH WITHOUT RE-VALIDATING TAG BUILDS AND BACKFILLS.
# Build amd64 images (default + slim share the build stage cache)
# Build amd64 image. Default and slim tags point to the same slim runtime.
build-amd64:
needs: [approve_manual_backfill]
if: ${{ always() && (github.event_name != 'workflow_dispatch' || needs.approve_manual_backfill.result == 'success') }}
@@ -74,7 +75,6 @@ jobs:
contents: read
outputs:
digest: ${{ steps.build.outputs.digest }}
slim-digest: ${{ steps.build-slim.outputs.digest }}
steps:
- name: Checkout
uses: actions/checkout@v6
@@ -117,12 +117,7 @@ jobs:
fi
{
echo "value<<EOF"
printf "%s\n" "${tags[@]}"
echo "EOF"
} >> "$GITHUB_OUTPUT"
{
echo "slim<<EOF"
printf "%s\n" "${slim_tags[@]}"
printf "%s\n" "${tags[@]}" "${slim_tags[@]}"
echo "EOF"
} >> "$GITHUB_OUTPUT"
@@ -159,28 +154,15 @@ jobs:
platforms: linux/amd64
cache-from: type=gha,scope=docker-release-amd64
cache-to: type=gha,mode=max,scope=docker-release-amd64
build-args: |
OPENCLAW_EXTENSIONS=diagnostics-otel
tags: ${{ steps.tags.outputs.value }}
labels: ${{ steps.labels.outputs.value }}
provenance: false
sbom: true
provenance: mode=max
push: true
- name: Build and push amd64 slim image
id: build-slim
# WARNING: KEEP THE OFFICIAL DOCKER ACTION HERE; DO NOT SWITCH THIS BACK TO BLACKSMITH BLINDLY.
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
with:
context: .
platforms: linux/amd64
cache-from: type=gha,scope=docker-release-amd64
cache-to: type=gha,mode=max,scope=docker-release-amd64
build-args: |
OPENCLAW_VARIANT=slim
tags: ${{ steps.tags.outputs.slim }}
labels: ${{ steps.labels.outputs.value }}
provenance: false
push: true
# Build arm64 images (default + slim share the build stage cache)
# Build arm64 image. Default and slim tags point to the same slim runtime.
build-arm64:
needs: [approve_manual_backfill]
if: ${{ always() && (github.event_name != 'workflow_dispatch' || needs.approve_manual_backfill.result == 'success') }}
@@ -191,7 +173,6 @@ jobs:
contents: read
outputs:
digest: ${{ steps.build.outputs.digest }}
slim-digest: ${{ steps.build-slim.outputs.digest }}
steps:
- name: Checkout
uses: actions/checkout@v6
@@ -234,12 +215,7 @@ jobs:
fi
{
echo "value<<EOF"
printf "%s\n" "${tags[@]}"
echo "EOF"
} >> "$GITHUB_OUTPUT"
{
echo "slim<<EOF"
printf "%s\n" "${slim_tags[@]}"
printf "%s\n" "${tags[@]}" "${slim_tags[@]}"
echo "EOF"
} >> "$GITHUB_OUTPUT"
@@ -276,25 +252,12 @@ jobs:
platforms: linux/arm64
cache-from: type=gha,scope=docker-release-arm64
cache-to: type=gha,mode=max,scope=docker-release-arm64
build-args: |
OPENCLAW_EXTENSIONS=diagnostics-otel
tags: ${{ steps.tags.outputs.value }}
labels: ${{ steps.labels.outputs.value }}
provenance: false
push: true
- name: Build and push arm64 slim image
id: build-slim
# WARNING: KEEP THE OFFICIAL DOCKER ACTION HERE; DO NOT SWITCH THIS BACK TO BLACKSMITH BLINDLY.
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
with:
context: .
platforms: linux/arm64
cache-from: type=gha,scope=docker-release-arm64
cache-to: type=gha,mode=max,scope=docker-release-arm64
build-args: |
OPENCLAW_VARIANT=slim
tags: ${{ steps.tags.outputs.slim }}
labels: ${{ steps.labels.outputs.value }}
provenance: false
sbom: true
provenance: mode=max
push: true
# Create multi-platform manifests
@@ -351,16 +314,11 @@ jobs:
fi
{
echo "value<<EOF"
printf "%s\n" "${tags[@]}"
echo "EOF"
} >> "$GITHUB_OUTPUT"
{
echo "slim<<EOF"
printf "%s\n" "${slim_tags[@]}"
printf "%s\n" "${tags[@]}" "${slim_tags[@]}"
echo "EOF"
} >> "$GITHUB_OUTPUT"
- name: Create and push default manifest
- name: Create and push manifest
shell: bash
env:
TAGS: ${{ steps.tags.outputs.value }}
@@ -378,20 +336,94 @@ jobs:
"${AMD64_DIGEST}" \
"${ARM64_DIGEST}"
- name: Create and push slim manifest
verify-attestations:
needs: [create-manifest]
if: ${{ always() && needs.create-manifest.result == 'success' }}
runs-on: ubuntu-24.04
permissions:
contents: read
packages: read
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 1
- name: Set up Docker Builder
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4
- name: Login to GitHub Container Registry
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Resolve image refs
id: refs
shell: bash
env:
SLIM_TAGS: ${{ steps.tags.outputs.slim }}
AMD64_SLIM_DIGEST: ${{ needs.build-amd64.outputs.slim-digest }}
ARM64_SLIM_DIGEST: ${{ needs.build-arm64.outputs.slim-digest }}
IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
SOURCE_REF: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
IS_MANUAL_BACKFILL: ${{ github.event_name == 'workflow_dispatch' && '1' || '0' }}
run: |
set -euo pipefail
mapfile -t tags <<< "${SLIM_TAGS}"
args=()
for tag in "${tags[@]}"; do
[ -z "$tag" ] && continue
args+=("-t" "$tag")
done
docker buildx imagetools create "${args[@]}" \
"${AMD64_SLIM_DIGEST}" \
"${ARM64_SLIM_DIGEST}"
multi_refs=()
slim_multi_refs=()
amd64_refs=()
arm64_refs=()
if [[ "${SOURCE_REF}" == "refs/heads/main" ]]; then
multi_refs+=("${IMAGE}:main")
slim_multi_refs+=("${IMAGE}:main-slim")
amd64_refs+=("${IMAGE}:main-amd64" "${IMAGE}:main-slim-amd64")
arm64_refs+=("${IMAGE}:main-arm64" "${IMAGE}:main-slim-arm64")
fi
if [[ "${SOURCE_REF}" == refs/tags/v* ]]; then
version="${SOURCE_REF#refs/tags/v}"
multi_refs+=("${IMAGE}:${version}")
slim_multi_refs+=("${IMAGE}:${version}-slim")
amd64_refs+=("${IMAGE}:${version}-amd64" "${IMAGE}:${version}-slim-amd64")
arm64_refs+=("${IMAGE}:${version}-arm64" "${IMAGE}:${version}-slim-arm64")
if [[ "${IS_MANUAL_BACKFILL}" != "1" && "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+)?$ ]]; then
multi_refs+=("${IMAGE}:latest")
slim_multi_refs+=("${IMAGE}:slim")
fi
fi
if [[ ${#multi_refs[@]} -eq 0 || ${#amd64_refs[@]} -eq 0 || ${#arm64_refs[@]} -eq 0 ]]; then
echo "::error::No Docker image refs resolved for ref ${SOURCE_REF}"
exit 1
fi
{
echo "multi<<EOF"
printf "%s\n" "${multi_refs[@]}" "${slim_multi_refs[@]}"
echo "EOF"
echo "amd64<<EOF"
printf "%s\n" "${amd64_refs[@]}"
echo "EOF"
echo "arm64<<EOF"
printf "%s\n" "${arm64_refs[@]}"
echo "EOF"
} >> "$GITHUB_OUTPUT"
- name: Verify Docker attestations
shell: bash
env:
MULTI_REFS: ${{ steps.refs.outputs.multi }}
AMD64_REFS: ${{ steps.refs.outputs.amd64 }}
ARM64_REFS: ${{ steps.refs.outputs.arm64 }}
run: |
set -euo pipefail
mapfile -t multi_refs <<< "${MULTI_REFS}"
mapfile -t amd64_refs <<< "${AMD64_REFS}"
mapfile -t arm64_refs <<< "${ARM64_REFS}"
node scripts/verify-docker-attestations.mjs \
--platform linux/amd64 \
--platform linux/arm64 \
"${multi_refs[@]}"
node scripts/verify-docker-attestations.mjs \
--platform linux/amd64 \
"${amd64_refs[@]}"
node scripts/verify-docker-attestations.mjs \
--platform linux/arm64 \
"${arm64_refs[@]}"

251
.github/workflows/docs-agent.yml vendored Normal file
View File

@@ -0,0 +1,251 @@
name: Docs Agent
on:
workflow_run: # zizmor: ignore[dangerous-triggers] main-only docs repair after trusted CI; job gates repository, event, branch, actor, conclusion, exact current main SHA, and hourly cadence before using write token
workflows:
- CI
types:
- completed
workflow_dispatch:
permissions:
actions: read
contents: write
concurrency:
group: docs-agent-main
cancel-in-progress: false
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
jobs:
update-docs:
if: >
github.repository == 'openclaw/openclaw' &&
github.actor != 'github-actions[bot]' &&
(github.event_name != 'workflow_run' ||
(github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.event == 'push' &&
github.event.workflow_run.head_branch == 'main' &&
github.event.workflow_run.actor.login != 'github-actions[bot]'))
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@v6
with:
ref: main
fetch-depth: 0
persist-credentials: false
submodules: false
- name: Gate trusted main activity and hourly cadence
id: gate
env:
EVENT_NAME: ${{ github.event_name }}
GH_TOKEN: ${{ github.token }}
WORKFLOW_HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
run: |
set -euo pipefail
if [ "$EVENT_NAME" != "workflow_run" ]; then
head_sha="$(git rev-parse HEAD)"
review_base="$(git rev-parse "${head_sha}^" 2>/dev/null || printf '%s' "$head_sha")"
{
echo "run_agent=true"
echo "base_sha=${head_sha}"
echo "review_base_sha=${review_base}"
echo "review_head_sha=${head_sha}"
} >> "$GITHUB_OUTPUT"
exit 0
fi
for attempt in 1 2 3 4 5; do
if git fetch --no-tags origin main; then
break
fi
if [ "$attempt" = "5" ]; then
echo "Failed to fetch main after retries." >&2
exit 1
fi
echo "Fetch attempt ${attempt} failed; retrying."
sleep $((attempt * 2))
done
remote_main="$(git rev-parse origin/main)"
if [ "$remote_main" != "$WORKFLOW_HEAD_SHA" ]; then
echo "CI run is superseded by ${remote_main}; skipping docs agent for ${WORKFLOW_HEAD_SHA}."
echo "run_agent=false" >> "$GITHUB_OUTPUT"
exit 0
fi
runs_json="$RUNNER_TEMP/docs-agent-runs.json"
gh api --method GET "repos/${GITHUB_REPOSITORY}/actions/workflows/docs-agent.yml/runs" \
-f branch=main \
-f event=workflow_run \
-f per_page=100 > "$runs_json"
one_hour_ago="$(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ)"
recent_runs="$(
jq -r \
--argjson current_run_id "$GITHUB_RUN_ID" \
--arg one_hour_ago "$one_hour_ago" \
'.workflow_runs[]
| select(.database_id != $current_run_id)
| select(.created_at >= $one_hour_ago)
| select(.status != "cancelled")
| select((.conclusion // "") != "skipped")
| [.database_id, .status, (.conclusion // ""), .created_at, .head_sha]
| @tsv' "$runs_json"
)"
if [ -n "$recent_runs" ]; then
echo "Docs agent already ran or is running within the last hour; skipping."
printf '%s\n' "$recent_runs"
echo "run_agent=false" >> "$GITHUB_OUTPUT"
exit 0
fi
review_base="$(
jq -r \
--argjson current_run_id "$GITHUB_RUN_ID" \
--arg remote_main "$remote_main" \
'.workflow_runs[]
| select(.database_id != $current_run_id)
| select(.status != "cancelled")
| select((.conclusion // "") != "skipped")
| .head_sha
| select(. != null and . != "")
| select(. != $remote_main)
' "$runs_json" | head -n 1
)"
if [ -z "$review_base" ] || ! git cat-file -e "${review_base}^{commit}" 2>/dev/null; then
review_base="$(git rev-parse "${remote_main}^" 2>/dev/null || printf '%s' "$remote_main")"
fi
{
echo "run_agent=true"
echo "base_sha=${remote_main}"
echo "review_base_sha=${review_base}"
echo "review_head_sha=${remote_main}"
} >> "$GITHUB_OUTPUT"
- name: Setup Node environment
if: steps.gate.outputs.run_agent == 'true'
uses: ./.github/actions/setup-node-env
with:
install-bun: "false"
- name: Ensure docs agent key exists
if: steps.gate.outputs.run_agent == 'true'
env:
OPENAI_API_KEY: ${{ secrets.OPENCLAW_DOCS_AGENT_OPENAI_API_KEY || secrets.OPENAI_API_KEY }}
run: |
set -euo pipefail
if [ -z "${OPENAI_API_KEY:-}" ]; then
echo "Missing OPENCLAW_DOCS_AGENT_OPENAI_API_KEY or OPENAI_API_KEY secret." >&2
exit 1
fi
- name: Run Codex docs agent
if: steps.gate.outputs.run_agent == 'true'
uses: openai/codex-action@5c3f4ccdb2b8790f73d6b21751ac00e602aa0c02
env:
DOCS_AGENT_BASE_SHA: ${{ steps.gate.outputs.review_base_sha }}
DOCS_AGENT_HEAD_SHA: ${{ steps.gate.outputs.review_head_sha }}
with:
openai-api-key: ${{ secrets.OPENCLAW_DOCS_AGENT_OPENAI_API_KEY || secrets.OPENAI_API_KEY }}
prompt-file: .github/codex/prompts/docs-agent.md
model: ${{ vars.OPENCLAW_CI_OPENAI_MODEL_BARE }}
effort: medium
sandbox: workspace-write
safety-strategy: drop-sudo
codex-args: '["--full-auto"]'
- name: Enforce existing-docs-only patch
if: steps.gate.outputs.run_agent == 'true'
run: |
set -euo pipefail
untracked="$(git ls-files --others --exclude-standard)"
if [ -n "$untracked" ]; then
echo "Docs agent created untracked files; forbidden:"
printf '%s\n' "$untracked"
exit 1
fi
added_or_deleted="$(git diff --name-status --diff-filter=AD)"
if [ -n "$added_or_deleted" ]; then
echo "Docs agent added or deleted tracked files; forbidden:"
printf '%s\n' "$added_or_deleted"
exit 1
fi
bad_paths="$(
git diff --name-only | while IFS= read -r path; do
case "$path" in
docs/*|README.md|CHANGELOG.md) ;;
*) printf '%s\n' "$path" ;;
esac
done
)"
if [ -n "$bad_paths" ]; then
echo "Docs agent touched non-doc paths; forbidden:"
printf '%s\n' "$bad_paths"
exit 1
fi
- name: Restore Node 24 path
if: steps.gate.outputs.run_agent == 'true'
run:
| # zizmor: ignore[github-env] NODE_BIN is set by the trusted local setup-node-env action in this same job
set -euo pipefail
export PATH="${NODE_BIN}:${PATH}"
echo "${NODE_BIN}" >> "$GITHUB_PATH"
node -v
corepack enable
pnpm -v
- name: Check docs
if: steps.gate.outputs.run_agent == 'true'
run: pnpm check:docs
- name: Commit docs updates
if: steps.gate.outputs.run_agent == 'true'
env:
BASE_SHA: ${{ steps.gate.outputs.base_sha }}
GITHUB_TOKEN: ${{ github.token }}
TARGET_BRANCH: main
run: |
set -euo pipefail
if git diff --quiet; then
echo "No docs changes."
exit 0
fi
git config user.name "openclaw-docs-agent[bot]"
git config user.email "openclaw-docs-agent[bot]@users.noreply.github.com"
git add docs README.md CHANGELOG.md
git commit --no-verify -m "docs: refresh documentation"
for attempt in 1 2 3 4 5; do
if ! git fetch --no-tags origin "${TARGET_BRANCH}"; then
echo "Fetch attempt ${attempt} failed; retrying."
sleep $((attempt * 2))
continue
fi
if git push "https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" HEAD:"${TARGET_BRANCH}"; then
exit 0
fi
remote_main="$(git rev-parse "origin/${TARGET_BRANCH}")"
if [ "$remote_main" != "$BASE_SHA" ]; then
echo "main advanced from ${BASE_SHA} to ${remote_main}; skipping stale docs update."
exit 0
fi
echo "Docs update attempt ${attempt} failed; retrying."
sleep $((attempt * 2))
done
echo "Failed to push docs updates after retries." >&2
exit 1

View File

@@ -32,9 +32,19 @@ jobs:
OPENCLAW_DOCS_SYNC_TOKEN: ${{ secrets.OPENCLAW_DOCS_SYNC_TOKEN }}
run: |
set -euo pipefail
git clone \
"https://x-access-token:${OPENCLAW_DOCS_SYNC_TOKEN}@github.com/openclaw/docs.git" \
publish
for attempt in 1 2 3 4 5; do
rm -rf publish
if git clone \
"https://x-access-token:${OPENCLAW_DOCS_SYNC_TOKEN}@github.com/openclaw/docs.git" \
publish; then
exit 0
fi
echo "Clone attempt ${attempt} failed; retrying."
sleep $((attempt * 2))
done
echo "Failed to clone publish repo after retries." >&2
exit 1
- name: Sync docs into publish repo
run: |
@@ -43,26 +53,56 @@ jobs:
--source-repo "$GITHUB_REPOSITORY" \
--source-sha "$GITHUB_SHA"
- name: Install docs MDX checker dependency
run: npm install --no-save --package-lock=false @mdx-js/mdx@3.1.1
- name: Check publish docs MDX
run: node "$GITHUB_WORKSPACE/publish/.openclaw-sync/check-docs-mdx.mjs" "$GITHUB_WORKSPACE/publish/docs"
- name: Commit publish repo sync
working-directory: publish
run: |
set -euo pipefail
remote_source_sha() {
git show refs/remotes/origin/main:.openclaw-sync/source.json 2>/dev/null \
| node -e 'const fs = require("node:fs"); try { const data = JSON.parse(fs.readFileSync(0, "utf8")); if (data.sha) process.stdout.write(data.sha); } catch {}' \
|| true
}
skip_stale_source() {
current_source_sha="$(remote_source_sha)"
if [ -z "$current_source_sha" ] || [ "$current_source_sha" = "$GITHUB_SHA" ]; then
return
fi
if git -C "$GITHUB_WORKSPACE" merge-base --is-ancestor "$GITHUB_SHA" "$current_source_sha"; then
echo "Skipping stale publish sync for $GITHUB_SHA; origin/main already mirrors $current_source_sha."
exit 0
fi
}
if git diff --quiet -- docs .openclaw-sync; then
echo "No publish-repo changes."
exit 0
fi
if git fetch origin main:refs/remotes/origin/main; then
skip_stale_source
fi
git config user.name "openclaw-docs-sync[bot]"
git config user.email "openclaw-docs-sync[bot]@users.noreply.github.com"
git add docs .openclaw-sync
git commit -m "chore(sync): mirror docs from $GITHUB_REPOSITORY@$GITHUB_SHA"
for attempt in 1 2 3 4 5; do
git fetch origin main
git rebase origin/main
if git push origin HEAD:main; then
exit 0
if git fetch origin main:refs/remotes/origin/main; then
skip_stale_source
if git rebase -X theirs origin/main && git push origin HEAD:main; then
exit 0
fi
fi
echo "Push attempt ${attempt} failed; retrying."
git rebase --abort >/dev/null 2>&1 || true
echo "Publish sync attempt ${attempt} failed; retrying."
sleep $((attempt * 2))
done

View File

@@ -31,7 +31,8 @@ jobs:
translate-tr-release \
translate-uk-release \
translate-id-release \
translate-pl-release
translate-pl-release \
translate-th-release
do
gh api repos/openclaw/docs/dispatches \
--method POST \

39
.github/workflows/docs.yml vendored Normal file
View File

@@ -0,0 +1,39 @@
name: Docs
on:
push:
branches: [main]
paths:
- "**/*.md"
- "docs/**"
permissions:
contents: read
concurrency:
group: ${{ format('{0}-{1}', github.workflow, github.ref) }}
cancel-in-progress: true
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
jobs:
docs:
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 1
fetch-tags: false
persist-credentials: false
submodules: false
- name: Setup Node environment
uses: ./.github/actions/setup-node-env
with:
install-bun: "false"
- name: Check docs
run: pnpm check:docs

View File

@@ -0,0 +1,59 @@
name: Duplicate PRs After Merge
on:
workflow_dispatch:
inputs:
landed_pr:
description: "Merged PR number that supersedes the duplicates"
required: true
type: string
duplicate_prs:
description: "Comma or whitespace separated duplicate PR numbers to close"
required: true
type: string
apply:
description: "When true, label/comment/close; otherwise dry-run only"
required: true
type: boolean
default: false
permissions:
contents: read
issues: write
pull-requests: write
concurrency:
group: duplicate-after-merge-${{ github.event.inputs.landed_pr }}
cancel-in-progress: false
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
GH_TOKEN: ${{ github.token }}
jobs:
close-duplicates:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Close confirmed duplicates
env:
APPLY: ${{ inputs.apply }}
DUPLICATE_PRS: ${{ inputs.duplicate_prs }}
LANDED_PR: ${{ inputs.landed_pr }}
REPO: ${{ github.repository }}
run: |
set -euo pipefail
args=(
--repo "$REPO"
--landed-pr "$LANDED_PR"
--duplicates "$DUPLICATE_PRS"
)
if [[ "$APPLY" == "true" ]]; then
args+=(--apply)
fi
node scripts/close-duplicate-prs-after-merge.mjs "${args[@]}"

View File

@@ -0,0 +1,564 @@
name: Full Release Validation
on:
workflow_dispatch:
inputs:
ref:
description: Branch, tag, or full commit SHA to validate
required: true
default: main
type: string
provider:
description: Provider lane for cross-OS onboarding and the end-to-end agent turn
required: false
default: openai
type: choice
options:
- openai
- anthropic
- minimax
mode:
description: Which cross-OS release lanes to run
required: false
default: both
type: choice
options:
- fresh
- upgrade
- both
release_profile:
description: Release coverage profile for live/Docker/provider breadth
required: false
default: full
type: choice
options:
- minimum
- stable
- full
rerun_group:
description: Validation group to run
required: false
default: all
type: choice
options:
- all
- ci
- release-checks
- install-smoke
- cross-os
- live-e2e
- package
- qa
- qa-parity
- qa-live
- npm-telegram
npm_telegram_package_spec:
description: Optional published package spec for the post-publish Telegram E2E lane
required: false
default: ""
type: string
evidence_package_spec:
description: Optional published package spec to prove in the private release evidence report
required: false
default: ""
type: string
npm_telegram_provider_mode:
description: Provider mode for the optional post-publish Telegram E2E lane
required: false
default: mock-openai
type: choice
options:
- mock-openai
- live-frontier
npm_telegram_scenario:
description: Optional comma-separated Telegram scenario ids for the post-publish lane
required: false
default: ""
type: string
permissions:
actions: write
contents: read
concurrency:
group: full-release-validation-${{ inputs.ref }}
cancel-in-progress: false
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
GH_REPO: ${{ github.repository }}
jobs:
resolve_target:
name: Resolve target ref
runs-on: ubuntu-24.04
timeout-minutes: 10
outputs:
sha: ${{ steps.resolve.outputs.sha }}
steps:
- name: Checkout trusted workflow helper
uses: actions/checkout@v6
with:
ref: ${{ github.ref_name }}
path: workflow
fetch-depth: 1
persist-credentials: false
submodules: false
- name: Resolve target SHA
id: resolve
env:
TARGET_REF: ${{ inputs.ref }}
run: |
bash workflow/scripts/github/resolve-openclaw-ref.sh \
--ref "$TARGET_REF" \
--github-output "$GITHUB_OUTPUT"
- name: Summarize target
env:
TARGET_REF: ${{ inputs.ref }}
TARGET_SHA: ${{ steps.resolve.outputs.sha }}
CHILD_WORKFLOW_REF: ${{ github.ref_name }}
NPM_TELEGRAM_PACKAGE_SPEC: ${{ inputs.npm_telegram_package_spec }}
EVIDENCE_PACKAGE_SPEC: ${{ inputs.evidence_package_spec }}
RERUN_GROUP: ${{ inputs.rerun_group }}
run: |
{
echo "## Full release validation"
echo
echo "- Target ref: \`${TARGET_REF}\`"
echo "- Target SHA: \`${TARGET_SHA}\`"
echo "- Child workflow ref: \`${CHILD_WORKFLOW_REF}\`"
echo "- Rerun group: \`${RERUN_GROUP}\`"
if [[ "$RERUN_GROUP" == "all" || "$RERUN_GROUP" == "ci" ]]; then
echo "- Normal CI: \`CI\` with \`target_ref=${TARGET_SHA}\`"
else
echo "- Normal CI: skipped by rerun group"
fi
if [[ "$RERUN_GROUP" != "ci" && "$RERUN_GROUP" != "npm-telegram" ]]; then
echo "- Release/live/Docker/package/QA: \`OpenClaw Release Checks\`"
else
echo "- Release/live/Docker/package/QA: skipped by rerun group"
fi
if [[ -n "${NPM_TELEGRAM_PACKAGE_SPEC// }" ]]; then
echo "- Post-publish Telegram E2E: \`${NPM_TELEGRAM_PACKAGE_SPEC}\`"
else
echo "- Post-publish Telegram E2E: skipped because no published package spec was provided"
fi
if [[ -n "${EVIDENCE_PACKAGE_SPEC// }" ]]; then
echo "- Private evidence package proof: \`${EVIDENCE_PACKAGE_SPEC}\`"
fi
} >> "$GITHUB_STEP_SUMMARY"
normal_ci:
name: Run normal full CI
needs: [resolve_target]
if: contains(fromJSON('["all","ci"]'), inputs.rerun_group)
runs-on: ubuntu-24.04
timeout-minutes: 240
outputs:
run_id: ${{ steps.dispatch.outputs.run_id }}
url: ${{ steps.dispatch.outputs.url }}
conclusion: ${{ steps.dispatch.outputs.conclusion }}
steps:
- name: Dispatch and monitor CI
id: dispatch
env:
GH_TOKEN: ${{ github.token }}
TARGET_REF: ${{ inputs.ref }}
TARGET_SHA: ${{ needs.resolve_target.outputs.sha }}
CHILD_WORKFLOW_REF: ${{ github.ref_name }}
run: |
set -euo pipefail
dispatch_and_wait() {
local workflow="$1"
shift
local before_json dispatch_output run_id status conclusion url
before_json="$(gh run list --workflow "$workflow" --event workflow_dispatch --limit 100 --json databaseId --jq '[.[].databaseId]')"
dispatch_output="$(gh workflow run "$workflow" --ref "$CHILD_WORKFLOW_REF" "$@" 2>&1)"
printf '%s\n' "$dispatch_output"
run_id="$(
printf '%s\n' "$dispatch_output" |
sed -nE 's#.*actions/runs/([0-9]+).*#\1#p' |
tail -n 1
)"
if [[ -z "$run_id" ]]; then
for _ in $(seq 1 60); do
run_id="$(
BEFORE_IDS="$before_json" gh run list --workflow "$workflow" --event workflow_dispatch --limit 50 --json databaseId,createdAt \
--jq 'map(select(.databaseId as $id | (env.BEFORE_IDS | fromjson | index($id) | not))) | sort_by(.createdAt) | reverse | .[0].databaseId // empty'
)"
if [[ -n "$run_id" ]]; then
break
fi
sleep 5
done
fi
if [[ -z "${run_id:-}" ]]; then
echo "Could not find dispatched run for ${workflow}." >&2
exit 1
fi
echo "Dispatched ${workflow}: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${run_id}"
echo "run_id=${run_id}" >> "$GITHUB_OUTPUT"
while true; do
status="$(gh run view "$run_id" --json status --jq '.status')"
if [[ "$status" == "completed" ]]; then
break
fi
sleep 30
done
conclusion="$(gh run view "$run_id" --json conclusion --jq '.conclusion')"
url="$(gh run view "$run_id" --json url --jq '.url')"
echo "${workflow} finished with ${conclusion}: ${url}"
echo "url=${url}" >> "$GITHUB_OUTPUT"
echo "conclusion=${conclusion}" >> "$GITHUB_OUTPUT"
if [[ "$conclusion" != "success" ]]; then
gh run view "$run_id" --json jobs --jq '.jobs[] | select(.conclusion != "success" and .conclusion != "skipped") | {name, conclusion, url}' || true
fi
}
{
echo "### Normal CI"
echo
echo "- Target ref: \`${TARGET_REF}\`"
echo "- Target SHA: \`${TARGET_SHA}\`"
} >> "$GITHUB_STEP_SUMMARY"
dispatch_and_wait ci.yml -f target_ref="$TARGET_SHA"
release_checks:
name: Run release/live/Docker/QA validation
needs: [resolve_target]
if: contains(fromJSON('["all","release-checks","install-smoke","cross-os","live-e2e","package","qa","qa-parity","qa-live"]'), inputs.rerun_group)
runs-on: ubuntu-24.04
timeout-minutes: 720
outputs:
run_id: ${{ steps.dispatch.outputs.run_id }}
url: ${{ steps.dispatch.outputs.url }}
conclusion: ${{ steps.dispatch.outputs.conclusion }}
steps:
- name: Dispatch and monitor release checks
id: dispatch
env:
GH_TOKEN: ${{ github.token }}
TARGET_REF: ${{ inputs.ref }}
TARGET_SHA: ${{ needs.resolve_target.outputs.sha }}
CHILD_WORKFLOW_REF: ${{ github.ref_name }}
PROVIDER: ${{ inputs.provider }}
MODE: ${{ inputs.mode }}
RELEASE_PROFILE: ${{ inputs.release_profile }}
RERUN_GROUP: ${{ inputs.rerun_group }}
run: |
set -euo pipefail
dispatch_and_wait() {
local workflow="$1"
shift
local before_json dispatch_output run_id status conclusion url
before_json="$(gh run list --workflow "$workflow" --event workflow_dispatch --limit 100 --json databaseId --jq '[.[].databaseId]')"
dispatch_output="$(gh workflow run "$workflow" --ref "$CHILD_WORKFLOW_REF" "$@" 2>&1)"
printf '%s\n' "$dispatch_output"
run_id="$(
printf '%s\n' "$dispatch_output" |
sed -nE 's#.*actions/runs/([0-9]+).*#\1#p' |
tail -n 1
)"
if [[ -z "$run_id" ]]; then
for _ in $(seq 1 60); do
run_id="$(
BEFORE_IDS="$before_json" gh run list --workflow "$workflow" --event workflow_dispatch --limit 50 --json databaseId,createdAt \
--jq 'map(select(.databaseId as $id | (env.BEFORE_IDS | fromjson | index($id) | not))) | sort_by(.createdAt) | reverse | .[0].databaseId // empty'
)"
if [[ -n "$run_id" ]]; then
break
fi
sleep 5
done
fi
if [[ -z "${run_id:-}" ]]; then
echo "Could not find dispatched run for ${workflow}." >&2
exit 1
fi
echo "Dispatched ${workflow}: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${run_id}"
echo "run_id=${run_id}" >> "$GITHUB_OUTPUT"
while true; do
status="$(gh run view "$run_id" --json status --jq '.status')"
if [[ "$status" == "completed" ]]; then
break
fi
sleep 30
done
conclusion="$(gh run view "$run_id" --json conclusion --jq '.conclusion')"
url="$(gh run view "$run_id" --json url --jq '.url')"
echo "${workflow} finished with ${conclusion}: ${url}"
echo "url=${url}" >> "$GITHUB_OUTPUT"
echo "conclusion=${conclusion}" >> "$GITHUB_OUTPUT"
if [[ "$conclusion" != "success" ]]; then
gh run view "$run_id" --json jobs --jq '.jobs[] | select(.conclusion != "success" and .conclusion != "skipped") | {name, conclusion, url}' || true
fi
}
{
echo "### Release/live/Docker/QA validation"
echo
echo "- Target ref: \`${TARGET_REF}\`"
echo "- Target SHA: \`${TARGET_SHA}\`"
echo "- Provider: \`${PROVIDER}\`"
echo "- Cross-OS mode: \`${MODE}\`"
echo "- Release profile: \`${RELEASE_PROFILE}\`"
echo "- Rerun group: \`${RERUN_GROUP}\`"
} >> "$GITHUB_STEP_SUMMARY"
child_rerun_group="$RERUN_GROUP"
if [[ "$child_rerun_group" == "release-checks" ]]; then
child_rerun_group=all
fi
dispatch_and_wait openclaw-release-checks.yml \
-f ref="$TARGET_SHA" \
-f expected_sha="$TARGET_SHA" \
-f provider="$PROVIDER" \
-f mode="$MODE" \
-f release_profile="$RELEASE_PROFILE" \
-f rerun_group="$child_rerun_group"
npm_telegram:
name: Run post-publish Telegram E2E
needs: [resolve_target]
if: inputs.npm_telegram_package_spec != '' && contains(fromJSON('["all","npm-telegram"]'), inputs.rerun_group)
runs-on: ubuntu-24.04
timeout-minutes: 120
outputs:
run_id: ${{ steps.dispatch.outputs.run_id }}
url: ${{ steps.dispatch.outputs.url }}
conclusion: ${{ steps.dispatch.outputs.conclusion }}
steps:
- name: Dispatch and monitor npm Telegram E2E
id: dispatch
env:
GH_TOKEN: ${{ github.token }}
CHILD_WORKFLOW_REF: ${{ github.ref_name }}
TARGET_SHA: ${{ needs.resolve_target.outputs.sha }}
PACKAGE_SPEC: ${{ inputs.npm_telegram_package_spec }}
PROVIDER_MODE: ${{ inputs.npm_telegram_provider_mode }}
SCENARIO: ${{ inputs.npm_telegram_scenario }}
run: |
set -euo pipefail
before_json="$(gh run list --workflow npm-telegram-beta-e2e.yml --event workflow_dispatch --limit 100 --json databaseId --jq '[.[].databaseId]')"
args=(-f package_spec="$PACKAGE_SPEC" -f harness_ref="$TARGET_SHA" -f provider_mode="$PROVIDER_MODE")
if [[ -n "${SCENARIO// }" ]]; then
args+=(-f scenario="$SCENARIO")
fi
gh workflow run npm-telegram-beta-e2e.yml --ref "$CHILD_WORKFLOW_REF" "${args[@]}"
run_id=""
for _ in $(seq 1 60); do
run_id="$(
BEFORE_IDS="$before_json" gh run list --workflow npm-telegram-beta-e2e.yml --event workflow_dispatch --limit 50 --json databaseId,createdAt \
--jq 'map(select(.databaseId as $id | (env.BEFORE_IDS | fromjson | index($id) | not))) | sort_by(.createdAt) | reverse | .[0].databaseId // empty'
)"
if [[ -n "$run_id" ]]; then
break
fi
sleep 5
done
if [[ -z "$run_id" ]]; then
echo "Could not find dispatched run for npm-telegram-beta-e2e.yml." >&2
exit 1
fi
echo "Dispatched npm-telegram-beta-e2e.yml: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${run_id}"
echo "run_id=${run_id}" >> "$GITHUB_OUTPUT"
while true; do
status="$(gh run view "$run_id" --json status --jq '.status')"
if [[ "$status" == "completed" ]]; then
break
fi
sleep 30
done
conclusion="$(gh run view "$run_id" --json conclusion --jq '.conclusion')"
url="$(gh run view "$run_id" --json url --jq '.url')"
echo "npm-telegram-beta-e2e.yml finished with ${conclusion}: ${url}"
echo "url=${url}" >> "$GITHUB_OUTPUT"
echo "conclusion=${conclusion}" >> "$GITHUB_OUTPUT"
if [[ "$conclusion" != "success" ]]; then
gh run view "$run_id" --json jobs --jq '.jobs[] | select(.conclusion != "success" and .conclusion != "skipped") | {name, conclusion, url}' || true
fi
summary:
name: Verify full validation
needs: [normal_ci, release_checks, npm_telegram]
if: always()
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- name: Request private evidence update
env:
RELEASE_PRIVATE_DISPATCH_TOKEN: ${{ secrets.OPENCLAW_RELEASES_PRIVATE_DISPATCH_TOKEN }}
TARGET_REF: ${{ inputs.ref }}
PACKAGE_SPEC: ${{ inputs.evidence_package_spec || inputs.npm_telegram_package_spec }}
GITHUB_RUN_ID_VALUE: ${{ github.run_id }}
RELEASE_CHECKS_RESULT: ${{ needs.release_checks.result }}
run: |
set -euo pipefail
if [[ "$RELEASE_CHECKS_RESULT" == "skipped" ]]; then
echo "Release checks were skipped by rerun group; skipping automatic private evidence update."
exit 0
fi
if [[ -z "${RELEASE_PRIVATE_DISPATCH_TOKEN// }" ]]; then
echo "OPENCLAW_RELEASES_PRIVATE_DISPATCH_TOKEN is not configured; skipping automatic private evidence update."
exit 0
fi
release_id="${TARGET_REF#refs/tags/}"
release_id="${release_id#v}"
if [[ "$PACKAGE_SPEC" =~ ^openclaw@(.+)$ ]]; then
release_id="${BASH_REMATCH[1]}"
fi
release_id="$(printf '%s' "$release_id" | tr '/:@ ' '----' | tr -cd 'A-Za-z0-9._-')"
if [[ -z "$release_id" ]]; then
echo "::error::Could not derive release evidence id from target ref '${TARGET_REF}'."
exit 1
fi
payload="$(
jq -cn \
--arg full_validation_run_id "$GITHUB_RUN_ID_VALUE" \
--arg release_id "$release_id" \
--arg release_ref "$TARGET_REF" \
--arg package_spec "$PACKAGE_SPEC" \
--arg notes "Automatically requested by Full Release Validation ${GITHUB_RUN_ID_VALUE} after child workflows completed; the parent summary re-checks current child run conclusions." \
'{
event_type: "openclaw_full_release_validation_completed",
client_payload: {
full_validation_run_id: $full_validation_run_id,
release_id: $release_id,
release_ref: $release_ref,
package_spec: $package_spec,
notes: $notes
}
}'
)"
curl --fail-with-body \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${RELEASE_PRIVATE_DISPATCH_TOKEN}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/openclaw/releases-private/dispatches \
-d "$payload"
- name: Verify child workflow results
env:
GH_TOKEN: ${{ github.token }}
NORMAL_CI_RUN_ID: ${{ needs.normal_ci.outputs.run_id }}
RELEASE_CHECKS_RUN_ID: ${{ needs.release_checks.outputs.run_id }}
NPM_TELEGRAM_RUN_ID: ${{ needs.npm_telegram.outputs.run_id }}
NORMAL_CI_RESULT: ${{ needs.normal_ci.result }}
RELEASE_CHECKS_RESULT: ${{ needs.release_checks.result }}
NPM_TELEGRAM_RESULT: ${{ needs.npm_telegram.result }}
run: |
set -euo pipefail
check_child() {
local label="$1"
local run_id="$2"
local required="$3"
if [[ -z "${run_id// }" ]]; then
if [[ "$required" == "0" ]]; then
echo "${label}: skipped"
return 0
fi
echo "::error::${label} did not record a child run id."
return 1
fi
local status conclusion url attempt
status="$(gh run view "$run_id" --json status --jq '.status')"
conclusion="$(gh run view "$run_id" --json conclusion --jq '.conclusion')"
url="$(gh run view "$run_id" --json url --jq '.url')"
attempt="$(gh run view "$run_id" --json attempt --jq '.attempt')"
echo "${label}: ${status}/${conclusion} attempt ${attempt}: ${url}"
if [[ "$status" != "completed" || "$conclusion" != "success" ]]; then
echo "::error::${label} child run ended with ${status}/${conclusion}: ${url}"
gh run view "$run_id" --json jobs --jq '.jobs[] | select(.conclusion != "success" and .conclusion != "skipped") | {name, status, conclusion, url}' || true
return 1
fi
}
summarize_child_timing() {
local label="$1"
local run_id="$2"
if [[ -z "${run_id// }" ]]; then
return 0
fi
{
echo
echo "### Slowest jobs: ${label}"
echo
gh run view "$run_id" --json jobs --jq '
def ts: fromdateiso8601;
"| Job | Result | Minutes |",
"| --- | --- | ---: |",
([.jobs[]
| select(.startedAt != "0001-01-01T00:00:00Z" and .completedAt != "0001-01-01T00:00:00Z")
| . + {durationMin: ((((.completedAt | ts) - (.startedAt | ts)) / 60) * 10 | round / 10)}
| {name, conclusion, durationMin}]
| sort_by(.durationMin)
| reverse
| .[0:10]
| map("| `" + (.name | gsub("\\|"; "\\|")) + "` | `" + ((.conclusion // "") | tostring) + "` | " + (.durationMin | tostring) + " |")
| .[])
' || echo "_Unable to summarize jobs for run ${run_id}._"
} >> "$GITHUB_STEP_SUMMARY"
}
failed=0
if [[ "$NORMAL_CI_RESULT" == "skipped" && -z "${NORMAL_CI_RUN_ID// }" ]]; then
check_child "normal_ci" "" 0 || failed=1
else
check_child "normal_ci" "$NORMAL_CI_RUN_ID" 1 || failed=1
fi
if [[ "$RELEASE_CHECKS_RESULT" == "skipped" && -z "${RELEASE_CHECKS_RUN_ID// }" ]]; then
check_child "release_checks" "" 0 || failed=1
else
check_child "release_checks" "$RELEASE_CHECKS_RUN_ID" 1 || failed=1
fi
if [[ "$NPM_TELEGRAM_RESULT" == "skipped" && -z "${NPM_TELEGRAM_RUN_ID// }" ]]; then
check_child "npm_telegram" "" 0 || failed=1
else
check_child "npm_telegram" "$NPM_TELEGRAM_RUN_ID" 1 || failed=1
fi
summarize_child_timing "normal_ci" "$NORMAL_CI_RUN_ID"
summarize_child_timing "release_checks" "$RELEASE_CHECKS_RUN_ID"
summarize_child_timing "npm_telegram" "$NPM_TELEGRAM_RUN_ID"
exit "$failed"

View File

@@ -1,17 +1,42 @@
name: Install Smoke
on:
push:
branches: [main]
pull_request:
types: [opened, reopened, synchronize, ready_for_review, converted_to_draft]
schedule:
- cron: "17 3 * * *"
workflow_dispatch:
inputs:
run_bun_global_install_smoke:
description: Run the Bun global install image-provider smoke
required: false
default: false
type: boolean
update_baseline_version:
description: Baseline openclaw version or dist-tag for installer update smoke
required: false
default: latest
type: string
workflow_call:
inputs:
ref:
description: Git ref to validate
required: false
type: string
run_bun_global_install_smoke:
description: Run the Bun global install image-provider smoke
required: false
default: true
type: boolean
update_baseline_version:
description: Baseline openclaw version or dist-tag for installer update smoke
required: false
default: latest
type: string
permissions:
contents: read
concurrency:
group: ${{ github.event_name == 'pull_request' && format('{0}-{1}', github.workflow, github.event.pull_request.number) || format('{0}-{1}', github.workflow, github.ref) }}
group: ${{ github.event_name == 'workflow_dispatch' && format('{0}-manual-{1}', github.workflow, github.run_id) || format('{0}-{1}', github.workflow, github.ref) }}
cancel-in-progress: true
env:
@@ -19,65 +44,54 @@ env:
jobs:
preflight:
if: github.event_name != 'pull_request' || !github.event.pull_request.draft
runs-on: ubuntu-24.04
outputs:
docs_only: ${{ steps.manifest.outputs.docs_only }}
run_install_smoke: ${{ steps.manifest.outputs.run_install_smoke }}
run_fast_install_smoke: ${{ steps.manifest.outputs.run_fast_install_smoke }}
run_full_install_smoke: ${{ steps.manifest.outputs.run_full_install_smoke }}
run_bun_global_install_smoke: ${{ steps.manifest.outputs.run_bun_global_install_smoke }}
steps:
- name: Checkout
uses: actions/checkout@v6
with:
ref: ${{ inputs.ref || github.ref }}
fetch-depth: 1
fetch-tags: false
persist-credentials: false
submodules: false
- name: Ensure preflight base commit
uses: ./.github/actions/ensure-base-commit
with:
base-sha: ${{ github.event_name == 'push' && github.event.before || github.event.pull_request.base.sha }}
fetch-ref: ${{ github.event_name == 'push' && github.ref_name || github.event.pull_request.base.ref }}
- name: Detect docs-only changes
id: docs_scope
uses: ./.github/actions/detect-docs-changes
- name: Detect changed smoke scope
id: changed_scope
if: steps.docs_scope.outputs.docs_only != 'true'
shell: bash
run: |
set -euo pipefail
if [ "${{ github.event_name }}" = "push" ]; then
BASE="${{ github.event.before }}"
else
BASE="${{ github.event.pull_request.base.sha }}"
fi
node scripts/ci-changed-scope.mjs --base "$BASE" --head HEAD
- name: Build install-smoke CI manifest
id: manifest
env:
OPENCLAW_CI_DOCS_ONLY: ${{ steps.docs_scope.outputs.docs_only }}
OPENCLAW_CI_RUN_CHANGED_SMOKE: ${{ steps.changed_scope.outputs.run_changed_smoke || 'false' }}
OPENCLAW_CI_EVENT_NAME: ${{ github.event_name }}
OPENCLAW_CI_WORKFLOW_BUN_GLOBAL_INSTALL_SMOKE: ${{ inputs.run_bun_global_install_smoke || 'false' }}
run: |
docs_only="${OPENCLAW_CI_DOCS_ONLY:-false}"
run_changed_smoke="${OPENCLAW_CI_RUN_CHANGED_SMOKE:-false}"
run_install_smoke=false
if [ "$docs_only" != "true" ] && [ "$run_changed_smoke" = "true" ]; then
run_install_smoke=true
event_name="${OPENCLAW_CI_EVENT_NAME:-}"
workflow_bun_global_install_smoke="${OPENCLAW_CI_WORKFLOW_BUN_GLOBAL_INSTALL_SMOKE:-false}"
docs_only=false
run_fast_install_smoke=true
run_full_install_smoke=true
run_bun_global_install_smoke=false
run_install_smoke=true
if [ "$event_name" = "schedule" ]; then
run_bun_global_install_smoke=true
elif [ "$event_name" = "workflow_dispatch" ] || [ "$event_name" = "workflow_call" ]; then
if [ "$workflow_bun_global_install_smoke" = "true" ]; then
run_bun_global_install_smoke=true
fi
fi
{
echo "docs_only=$docs_only"
echo "run_install_smoke=$run_install_smoke"
echo "run_fast_install_smoke=$run_fast_install_smoke"
echo "run_full_install_smoke=$run_full_install_smoke"
echo "run_bun_global_install_smoke=$run_bun_global_install_smoke"
} >> "$GITHUB_OUTPUT"
install-smoke:
install-smoke-fast:
needs: [preflight]
if: needs.preflight.outputs.run_install_smoke == 'true'
if: needs.preflight.outputs.run_fast_install_smoke == 'true' && needs.preflight.outputs.run_full_install_smoke != 'true'
runs-on: blacksmith-16vcpu-ubuntu-2404
env:
DOCKER_BUILD_SUMMARY: "false"
@@ -85,6 +99,115 @@ jobs:
steps:
- name: Checkout CLI
uses: actions/checkout@v6
with:
ref: ${{ inputs.ref || github.ref }}
- name: Set up Blacksmith Docker Builder
uses: useblacksmith/setup-docker-builder@ac083cc84672d01c60d5e8561d0a939b697de542 # v1
# Blacksmith's builder owns the Docker layer cache; keep smoke builds off
# explicit gha cache directives so local tags still load cleanly.
- name: Build root Dockerfile smoke image
uses: useblacksmith/build-push-action@cbd1f60d194a98cb3be5523b15134501eaf0fbf3 # v2
with:
context: .
file: ./Dockerfile
build-args: |
OPENCLAW_EXTENSIONS=matrix
tags: |
openclaw-dockerfile-smoke:local
openclaw-ext-smoke:local
load: true
push: false
provenance: false
- name: Run root Dockerfile CLI smoke
run: |
docker run --rm --entrypoint sh openclaw-dockerfile-smoke:local -lc '
which openclaw &&
openclaw --version &&
node -e "
const fs = require(\"node:fs\");
const path = require(\"node:path\");
const pkg = require(\"/app/package.json\");
for (const [dep, rel] of Object.entries(pkg.pnpm?.patchedDependencies ?? {})) {
const absolute = path.join(\"/app\", rel);
if (!fs.existsSync(absolute)) {
throw new Error(`missing patch for ${dep}: ${rel}`);
}
}
"
'
- name: Run agents delete shared workspace Docker CLI smoke
env:
OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_IMAGE: openclaw-dockerfile-smoke:local
OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_SKIP_BUILD: "1"
run: bash scripts/e2e/agents-delete-shared-workspace-docker.sh
- name: Run Docker gateway network e2e
env:
OPENCLAW_GATEWAY_NETWORK_E2E_IMAGE: openclaw-dockerfile-smoke:local
OPENCLAW_GATEWAY_NETWORK_E2E_SKIP_BUILD: "1"
run: bash scripts/e2e/gateway-network-docker.sh
- name: Smoke test Dockerfile with matrix extension build arg
run: |
docker run --rm --entrypoint sh openclaw-ext-smoke:local -lc '
which openclaw &&
openclaw --version &&
node -e "
const Module = require(\"node:module\");
const matrixPackage = require(\"/app/extensions/matrix/package.json\");
const requireFromMatrix = Module.createRequire(\"/app/extensions/matrix/package.json\");
const runtimeDeps = Object.keys(matrixPackage.dependencies ?? {});
if (runtimeDeps.length === 0) {
throw new Error(
\"matrix package has no declared runtime dependencies; smoke cannot validate install mirroring\",
);
}
for (const dep of runtimeDeps) {
requireFromMatrix.resolve(dep);
}
const { spawnSync } = require(\"node:child_process\");
const run = spawnSync(\"openclaw\", [\"plugins\", \"list\", \"--json\"], { encoding: \"utf8\" });
if (run.status !== 0) {
process.stderr.write(run.stderr || run.stdout || \"plugins list failed\\n\");
process.exit(run.status ?? 1);
}
const parsed = JSON.parse(run.stdout);
const matrix = (parsed.plugins || []).find((entry) => entry.id === \"matrix\");
if (!matrix) {
throw new Error(\"matrix plugin missing from bundled plugin list\");
}
const matrixDiag = (parsed.diagnostics || []).filter(
(diag) =>
typeof diag.source === \"string\" &&
diag.source.includes(\"/extensions/matrix\") &&
typeof diag.message === \"string\" &&
diag.message.includes(\"extension entry escapes package directory\"),
);
if (matrixDiag.length > 0) {
throw new Error(
\"unexpected matrix diagnostics: \" +
matrixDiag.map((diag) => diag.message).join(\"; \"),
);
}
"
'
install-smoke:
needs: [preflight]
if: needs.preflight.outputs.run_full_install_smoke == 'true'
runs-on: blacksmith-16vcpu-ubuntu-2404
env:
DOCKER_BUILD_SUMMARY: "false"
DOCKER_BUILD_RECORD_UPLOAD: "false"
steps:
- name: Checkout CLI
uses: actions/checkout@v6
with:
ref: ${{ inputs.ref || github.ref }}
- name: Set up Blacksmith Docker Builder
uses: useblacksmith/setup-docker-builder@ac083cc84672d01c60d5e8561d0a939b697de542 # v1
@@ -96,14 +219,18 @@ jobs:
OPENCLAW_QR_SMOKE_FORCE_INSTALL: "1"
run: bash scripts/e2e/qr-import-docker.sh
# Build once with the matrix extension and tag both smoke names. This
# keeps the build-arg coverage without a second Blacksmith build action.
- name: Build root Dockerfile smoke image
uses: useblacksmith/build-push-action@cbd1f60d194a98cb3be5523b15134501eaf0fbf3 # v2
with:
context: .
file: ./Dockerfile
build-args: |
OPENCLAW_DOCKER_APT_UPGRADE=0
tags: openclaw-dockerfile-smoke:local
OPENCLAW_EXTENSIONS=matrix
tags: |
openclaw-dockerfile-smoke:local
openclaw-ext-smoke:local
load: true
push: false
provenance: false
@@ -112,28 +239,18 @@ jobs:
run: |
docker run --rm --entrypoint sh openclaw-dockerfile-smoke:local -lc 'which openclaw && openclaw --version'
- name: Run agents delete shared workspace Docker CLI smoke
env:
OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_IMAGE: openclaw-dockerfile-smoke:local
OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_SKIP_BUILD: "1"
run: bash scripts/e2e/agents-delete-shared-workspace-docker.sh
- name: Run Docker gateway network e2e
env:
OPENCLAW_GATEWAY_NETWORK_E2E_IMAGE: openclaw-dockerfile-smoke:local
OPENCLAW_GATEWAY_NETWORK_E2E_SKIP_BUILD: "1"
run: bash scripts/e2e/gateway-network-docker.sh
# This smoke validates that the build-arg path preinstalls the matrix
# runtime deps declared by the plugin and that matrix discovery stays
# healthy in the final runtime image.
- name: Build extension Dockerfile smoke image
uses: useblacksmith/build-push-action@cbd1f60d194a98cb3be5523b15134501eaf0fbf3 # v2
with:
context: .
file: ./Dockerfile
build-args: |
OPENCLAW_DOCKER_APT_UPGRADE=0
OPENCLAW_EXTENSIONS=matrix
tags: openclaw-ext-smoke:local
load: true
push: false
provenance: false
- name: Smoke test Dockerfile with matrix extension build arg
run: |
docker run --rm --entrypoint sh openclaw-ext-smoke:local -lc '
@@ -190,7 +307,6 @@ jobs:
provenance: false
- name: Build installer non-root image
if: github.event_name != 'pull_request'
uses: useblacksmith/build-push-action@cbd1f60d194a98cb3be5523b15134501eaf0fbf3 # v2
with:
context: ./scripts/docker
@@ -200,12 +316,19 @@ jobs:
push: false
provenance: false
- name: Setup Node environment for local pack smoke
- name: Setup Node environment for installer smoke
uses: ./.github/actions/setup-node-env
with:
install-bun: "false"
install-bun: ${{ needs.preflight.outputs.run_bun_global_install_smoke }}
install-deps: "true"
- name: Run Bun global install image-provider smoke
if: needs.preflight.outputs.run_bun_global_install_smoke == 'true'
env:
OPENCLAW_BUN_GLOBAL_SMOKE_DIST_IMAGE: openclaw-dockerfile-smoke:local
OPENCLAW_BUN_GLOBAL_SMOKE_HOST_BUILD: "0"
run: bash scripts/e2e/bun-global-install-smoke.sh
- name: Run installer docker tests
env:
OPENCLAW_INSTALL_URL: https://openclaw.ai/install.sh
@@ -213,16 +336,18 @@ jobs:
OPENCLAW_NO_ONBOARD: "1"
OPENCLAW_INSTALL_SMOKE_SKIP_CLI: "1"
OPENCLAW_INSTALL_SMOKE_SKIP_IMAGE_BUILD: "1"
OPENCLAW_INSTALL_NONROOT_SKIP_IMAGE_BUILD: ${{ github.event_name == 'pull_request' && '0' || '1' }}
OPENCLAW_INSTALL_SMOKE_SKIP_NONROOT: ${{ github.event_name == 'pull_request' && '1' || '0' }}
OPENCLAW_INSTALL_NONROOT_SKIP_IMAGE_BUILD: "1"
OPENCLAW_INSTALL_SMOKE_SKIP_NONROOT: "0"
OPENCLAW_INSTALL_SMOKE_SKIP_NPM_GLOBAL: "1"
OPENCLAW_INSTALL_SMOKE_SKIP_PREVIOUS: "1"
OPENCLAW_INSTALL_SMOKE_UPDATE_BASELINE: ${{ inputs.update_baseline_version || 'latest' }}
OPENCLAW_INSTALL_SMOKE_UPDATE_DIST_IMAGE: openclaw-dockerfile-smoke:local
OPENCLAW_INSTALL_SMOKE_UPDATE_SKIP_LOCAL_BUILD: "1"
run: bash scripts/test-install-sh-docker.sh
docker-e2e-fast:
needs: [preflight]
if: needs.preflight.outputs.run_install_smoke == 'true'
if: needs.preflight.outputs.run_fast_install_smoke == 'true' || needs.preflight.outputs.run_full_install_smoke == 'true'
runs-on: blacksmith-16vcpu-ubuntu-2404
timeout-minutes: 8
env:
@@ -231,6 +356,8 @@ jobs:
steps:
- name: Checkout CLI
uses: actions/checkout@v6
with:
ref: ${{ inputs.ref || github.ref }}
- name: Set up Blacksmith Docker Builder
uses: useblacksmith/setup-docker-builder@ac083cc84672d01c60d5e8561d0a939b697de542 # v1
@@ -244,4 +371,5 @@ jobs:
- name: Run fast bundled plugin Docker E2E
env:
OPENCLAW_BUNDLED_CHANNEL_DEPS_E2E_IMAGE: openclaw-bundled-channel-fast:local
run: timeout 120s pnpm test:docker:bundled-channel-deps:fast
OPENCLAW_BUNDLED_CHANNEL_DOCKER_RUN_TIMEOUT: 90s
run: timeout 240s pnpm test:docker:bundled-channel-deps:fast

View File

@@ -0,0 +1,230 @@
name: NPM Telegram Beta E2E
on:
workflow_dispatch:
inputs:
package_spec:
description: Published OpenClaw package spec to test when no artifact is supplied
required: true
default: openclaw@beta
type: string
package_label:
description: Optional display label for an artifact-backed package candidate
required: false
default: ""
type: string
package_artifact_name:
description: Advanced package-under-test artifact name; leave blank for registry install
required: false
default: ""
type: string
harness_ref:
description: Source ref for the private QA harness; defaults to the dispatched workflow ref
required: false
default: ""
type: string
provider_mode:
description: QA provider mode
required: true
default: mock-openai
type: choice
options:
- mock-openai
- live-frontier
scenario:
description: Optional comma-separated Telegram scenario ids
required: false
type: string
workflow_call:
inputs:
package_spec:
description: Published OpenClaw package spec to test when no artifact is supplied
required: true
type: string
package_artifact_name:
description: Optional package-under-test artifact from the current workflow run
required: false
default: ""
type: string
package_label:
description: Optional display label for an artifact-backed package candidate
required: false
default: ""
type: string
harness_ref:
description: Source ref for the private QA harness; defaults to the called workflow ref
required: false
default: ""
type: string
provider_mode:
description: QA provider mode
required: false
default: mock-openai
type: string
scenario:
description: Optional comma-separated Telegram scenario ids
required: false
default: ""
type: string
secrets:
OPENAI_API_KEY:
required: false
OPENCLAW_QA_CONVEX_SITE_URL:
required: false
OPENCLAW_QA_CONVEX_SECRET_CI:
required: false
permissions:
contents: read
concurrency:
group: npm-telegram-beta-e2e-${{ github.run_id }}
cancel-in-progress: false
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
NODE_VERSION: "24.x"
PNPM_VERSION: "10.33.0"
jobs:
run_package_telegram_e2e:
name: Run package Telegram E2E
runs-on: blacksmith-32vcpu-ubuntu-2404
timeout-minutes: 60
environment: qa-live-shared
permissions:
contents: read
env:
DOCKER_BUILD_SUMMARY: "false"
DOCKER_BUILD_RECORD_UPLOAD: "false"
steps:
- name: Checkout dispatch ref
uses: actions/checkout@v6
with:
ref: ${{ inputs.harness_ref || github.sha }}
fetch-depth: 1
- name: Set up Blacksmith Docker Builder
uses: useblacksmith/setup-docker-builder@ac083cc84672d01c60d5e8561d0a939b697de542 # v1
with:
max-cache-size-mb: 800000
- name: Build Docker E2E image
uses: useblacksmith/build-push-action@cbd1f60d194a98cb3be5523b15134501eaf0fbf3 # v2
with:
context: .
file: ./scripts/e2e/Dockerfile
target: build
platforms: linux/amd64
tags: openclaw-docker-e2e:local
load: true
push: false
provenance: false
- name: Setup Node environment
uses: ./.github/actions/setup-node-env
with:
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
install-bun: "true"
- name: Validate inputs and secrets
env:
PACKAGE_SPEC: ${{ inputs.package_spec }}
PACKAGE_ARTIFACT_NAME: ${{ inputs.package_artifact_name || '' }}
PROVIDER_MODE: ${{ inputs.provider_mode }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENCLAW_QA_CONVEX_SITE_URL: ${{ secrets.OPENCLAW_QA_CONVEX_SITE_URL }}
OPENCLAW_QA_CONVEX_SECRET_CI: ${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }}
shell: bash
run: |
set -euo pipefail
if [[ -z "${PACKAGE_ARTIFACT_NAME// }" ]]; then
if [[ ! "${PACKAGE_SPEC}" =~ ^openclaw@(beta|latest|[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*(-[1-9][0-9]*|-beta\.[1-9][0-9]*)?)$ ]]; then
echo "package_spec must be openclaw@beta, openclaw@latest, or an exact OpenClaw release version; got: ${PACKAGE_SPEC}" >&2
exit 1
fi
fi
case "${PROVIDER_MODE}" in
mock-openai | live-frontier) ;;
*)
echo "provider_mode must be mock-openai or live-frontier; got: ${PROVIDER_MODE}" >&2
exit 1
;;
esac
require_var() {
local key="$1"
if [[ -z "${!key:-}" ]]; then
echo "Missing required ${key}." >&2
exit 1
fi
}
require_var OPENCLAW_QA_CONVEX_SITE_URL
require_var OPENCLAW_QA_CONVEX_SECRET_CI
if [[ "${PROVIDER_MODE}" == "live-frontier" ]]; then
require_var OPENAI_API_KEY
fi
- name: Download package-under-test artifact
if: inputs.package_artifact_name != ''
uses: actions/download-artifact@v8
with:
name: ${{ inputs.package_artifact_name }}
path: .artifacts/telegram-package-under-test
- name: Run package Telegram E2E
id: run_lane
shell: bash
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENCLAW_SKIP_DOCKER_BUILD: "1"
OPENCLAW_DOCKER_E2E_IMAGE: openclaw-docker-e2e:local
OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC: ${{ inputs.package_spec }}
OPENCLAW_NPM_TELEGRAM_PACKAGE_LABEL: ${{ inputs.package_label }}
OPENCLAW_NPM_TELEGRAM_PROVIDER_MODE: ${{ inputs.provider_mode }}
OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE: convex
OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE: ci
OPENCLAW_QA_CONVEX_SITE_URL: ${{ secrets.OPENCLAW_QA_CONVEX_SITE_URL }}
OPENCLAW_QA_CONVEX_SECRET_CI: ${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }}
OPENCLAW_QA_REDACT_PUBLIC_METADATA: "1"
OPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT: "1"
INPUT_SCENARIO: ${{ inputs.scenario }}
PACKAGE_ARTIFACT_NAME: ${{ inputs.package_artifact_name || '' }}
run: |
set -euo pipefail
output_dir=".artifacts/qa-e2e/npm-telegram-beta-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
echo "output_dir=${output_dir}" >> "$GITHUB_OUTPUT"
export OPENCLAW_NPM_TELEGRAM_OUTPUT_DIR="${output_dir}"
if [[ -n "${PACKAGE_ARTIFACT_NAME// }" ]]; then
mapfile -t package_tgzs < <(find .artifacts/telegram-package-under-test -type f -name "*.tgz" | sort)
if [[ "${#package_tgzs[@]}" -ne 1 ]]; then
echo "package artifact ${PACKAGE_ARTIFACT_NAME} must contain exactly one .tgz; found ${#package_tgzs[@]}" >&2
exit 1
fi
export OPENCLAW_NPM_TELEGRAM_PACKAGE_TGZ="${package_tgzs[0]}"
if [[ -z "${OPENCLAW_NPM_TELEGRAM_PACKAGE_LABEL// }" ]]; then
export OPENCLAW_NPM_TELEGRAM_PACKAGE_LABEL="$(basename "${package_tgzs[0]}")"
fi
elif [[ -z "${OPENCLAW_NPM_TELEGRAM_PACKAGE_LABEL// }" ]]; then
export OPENCLAW_NPM_TELEGRAM_PACKAGE_LABEL="${OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC}"
fi
if [[ -n "${INPUT_SCENARIO// }" ]]; then
export OPENCLAW_NPM_TELEGRAM_SCENARIOS="${INPUT_SCENARIO}"
fi
pnpm test:docker:npm-telegram-live
- name: Upload npm Telegram E2E artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: npm-telegram-beta-e2e-${{ github.run_id }}-${{ github.run_attempt }}
path: .artifacts/qa-e2e/
retention-days: 14
if-no-files-found: warn

View File

@@ -51,6 +51,31 @@ on:
required: false
default: ""
type: string
candidate_artifact_name:
description: Optional current-run artifact name containing the candidate OpenClaw tarball
required: false
default: ""
type: string
candidate_artifact_run_id:
description: Optional workflow run id for candidate_artifact_name
required: false
default: ""
type: string
candidate_file_name:
description: Optional candidate tarball file name inside candidate_artifact_name
required: false
default: ""
type: string
candidate_version:
description: Optional candidate OpenClaw package version
required: false
default: ""
type: string
candidate_source_sha:
description: Optional source SHA used to build the candidate tarball
required: false
default: ""
type: string
workflow_call:
inputs:
ref:
@@ -90,6 +115,31 @@ on:
required: false
default: ""
type: string
candidate_artifact_name:
description: Optional current-run artifact name containing the candidate OpenClaw tarball
required: false
default: ""
type: string
candidate_artifact_run_id:
description: Optional workflow run id for candidate_artifact_name
required: false
default: ""
type: string
candidate_file_name:
description: Optional candidate tarball file name inside candidate_artifact_name
required: false
default: ""
type: string
candidate_version:
description: Optional candidate OpenClaw package version
required: false
default: ""
type: string
candidate_source_sha:
description: Optional source SHA used to build the candidate tarball
required: false
default: ""
type: string
secrets:
OPENAI_API_KEY:
required: false
@@ -119,7 +169,7 @@ env:
jobs:
prepare:
runs-on: ubuntu-latest
runs-on: blacksmith-8vcpu-ubuntu-2404
outputs:
baseline_file_name: ${{ steps.baseline_metadata.outputs.file_name }}
baseline_spec: ${{ steps.baseline.outputs.value }}
@@ -260,6 +310,7 @@ jobs:
persist-credentials: false
- name: Checkout public source ref
if: inputs.candidate_artifact_name == ''
uses: actions/checkout@v6
with:
repository: ${{ env.OPENCLAW_REPOSITORY }}
@@ -270,7 +321,7 @@ jobs:
submodules: recursive
- name: Setup pnpm
uses: pnpm/action-setup@v4
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1
with:
version: ${{ env.PNPM_VERSION }}
run_install: false
@@ -280,17 +331,64 @@ jobs:
with:
node-version: ${{ env.NODE_VERSION }}
cache: pnpm
cache-dependency-path: source/pnpm-lock.yaml
cache-dependency-path: ${{ inputs.candidate_artifact_name == '' && 'source/pnpm-lock.yaml' || 'workflow/pnpm-lock.yaml' }}
- name: Build candidate artifact once
if: inputs.candidate_artifact_name == ''
env:
OUTPUT_DIR: ${{ runner.temp }}/openclaw-cross-os-release-checks/prepare
run: |
pnpm dlx "tsx@${TSX_VERSION}" workflow/scripts/openclaw-cross-os-release-checks.ts \
bash workflow/scripts/github/run-openclaw-cross-os-release-checks.sh \
--prepare-only \
--source-dir source \
--output-dir "${OUTPUT_DIR}"
- name: Download provided candidate artifact
if: inputs.candidate_artifact_name != ''
uses: actions/download-artifact@v8
with:
name: ${{ inputs.candidate_artifact_name }}
run-id: ${{ inputs.candidate_artifact_run_id || github.run_id }}
github-token: ${{ github.token }}
path: ${{ runner.temp }}/openclaw-cross-os-release-checks/prepare/package
- name: Capture provided candidate artifact metadata
if: inputs.candidate_artifact_name != ''
env:
PACKAGE_DIR: ${{ runner.temp }}/openclaw-cross-os-release-checks/prepare/package
INPUT_CANDIDATE_FILE_NAME: ${{ inputs.candidate_file_name }}
INPUT_CANDIDATE_VERSION: ${{ inputs.candidate_version }}
INPUT_CANDIDATE_SOURCE_SHA: ${{ inputs.candidate_source_sha }}
CANDIDATE_JSON: ${{ runner.temp }}/openclaw-cross-os-release-checks/prepare/candidate.json
run: |
node <<'NODE'
const fs = require("node:fs");
const path = require("node:path");
const packageDir = process.env.PACKAGE_DIR;
const requestedFileName = process.env.INPUT_CANDIDATE_FILE_NAME.trim();
const files = fs.readdirSync(packageDir).filter((file) => file.endsWith(".tgz"));
const candidateFileName = requestedFileName || (files.length === 1 ? files[0] : "");
if (!candidateFileName) {
throw new Error(`Expected exactly one candidate .tgz in ${packageDir}; found ${files.length}.`);
}
if (!fs.existsSync(path.join(packageDir, candidateFileName))) {
throw new Error(`Provided candidate artifact does not contain ${candidateFileName}.`);
}
const candidateVersion = process.env.INPUT_CANDIDATE_VERSION.trim();
if (!candidateVersion) {
throw new Error("candidate_version is required when candidate_artifact_name is provided.");
}
const sourceSha = process.env.INPUT_CANDIDATE_SOURCE_SHA.trim();
if (!/^[0-9a-f]{40}$/iu.test(sourceSha)) {
throw new Error("candidate_source_sha must be a full commit SHA when candidate_artifact_name is provided.");
}
fs.writeFileSync(
process.env.CANDIDATE_JSON,
`${JSON.stringify({ candidateFileName, candidateVersion, sourceSha }, null, 2)}\n`,
);
NODE
- name: Resolve baseline package spec
if: ${{ inputs.mode != 'fresh' }}
id: baseline
@@ -370,7 +468,7 @@ jobs:
VAR_WINDOWS_RUNNER: ${{ vars.OPENCLAW_RELEASE_CHECKS_WINDOWS_RUNNER }}
VAR_MACOS_RUNNER: ${{ vars.OPENCLAW_RELEASE_CHECKS_MACOS_RUNNER }}
run: |
MATRIX_JSON="$(pnpm dlx "tsx@${TSX_VERSION}" workflow/scripts/openclaw-cross-os-release-checks.ts \
MATRIX_JSON="$(bash workflow/scripts/github/run-openclaw-cross-os-release-checks.sh \
--resolve-matrix \
--ref "${INPUT_REF}" \
--mode "${INPUT_MODE}" \
@@ -398,7 +496,7 @@ jobs:
persist-credentials: false
- name: Setup pnpm
uses: pnpm/action-setup@v4
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1
with:
version: ${{ env.PNPM_VERSION }}
run_install: false
@@ -432,24 +530,35 @@ jobs:
OPENCLAW_DISCORD_SMOKE_CHANNEL_ID: ${{ secrets.OPENCLAW_DISCORD_SMOKE_CHANNEL_ID }}
OPENCLAW_RELEASE_CHECK_OS: ${{ matrix.os_id }}
OPENCLAW_RELEASE_CHECK_RUNNER: ${{ matrix.runner }}
CANDIDATE_TGZ: ${{ runner.temp }}/openclaw-cross-os-release-checks/candidate/${{ needs.prepare.outputs.candidate_file_name }}
CANDIDATE_VERSION: ${{ needs.prepare.outputs.candidate_version }}
SOURCE_SHA: ${{ needs.prepare.outputs.source_sha }}
BASELINE_SPEC: ${{ needs.prepare.outputs.baseline_spec }}
PREVIOUS_VERSION: ${{ inputs.previous_version }}
BASELINE_TGZ: ${{ runner.temp }}/openclaw-cross-os-release-checks/baseline/${{ needs.prepare.outputs.baseline_file_name }}
PROVIDER: ${{ inputs.provider }}
MODE: ${{ matrix.lane }}
SUITE: ${{ matrix.suite }}
REF: ${{ inputs.ref }}
OUTPUT_DIR: ${{ runner.temp }}/openclaw-cross-os-release-checks/${{ matrix.artifact_name }}-${{ matrix.suite }}
run: |
DISCORD_ARGS=()
if [[ -n "${OPENCLAW_DISCORD_SMOKE_BOT_TOKEN}" ]] && [[ -n "${OPENCLAW_DISCORD_SMOKE_GUILD_ID}" ]] && [[ -n "${OPENCLAW_DISCORD_SMOKE_CHANNEL_ID}" ]]; then
DISCORD_ARGS+=(--run-discord-roundtrip true)
fi
pnpm dlx "tsx@${TSX_VERSION}" workflow/scripts/openclaw-cross-os-release-checks.ts \
--candidate-tgz "$RUNNER_TEMP/openclaw-cross-os-release-checks/candidate/${{ needs.prepare.outputs.candidate_file_name }}" \
--candidate-version "${{ needs.prepare.outputs.candidate_version }}" \
--source-sha "${{ needs.prepare.outputs.source_sha }}" \
--baseline-spec "${{ needs.prepare.outputs.baseline_spec }}" \
--previous-version "${{ inputs.previous_version }}" \
--baseline-tgz "$RUNNER_TEMP/openclaw-cross-os-release-checks/baseline/${{ needs.prepare.outputs.baseline_file_name }}" \
--provider "${{ inputs.provider }}" \
--mode "${{ matrix.lane }}" \
--suite "${{ matrix.suite }}" \
--ref "${{ inputs.ref }}" \
bash workflow/scripts/github/run-openclaw-cross-os-release-checks.sh \
--candidate-tgz "${CANDIDATE_TGZ}" \
--candidate-version "${CANDIDATE_VERSION}" \
--source-sha "${SOURCE_SHA}" \
--baseline-spec "${BASELINE_SPEC}" \
--previous-version "${PREVIOUS_VERSION}" \
--baseline-tgz "${BASELINE_TGZ}" \
--provider "${PROVIDER}" \
--mode "${MODE}" \
--suite "${SUITE}" \
--ref "${REF}" \
"${DISCORD_ARGS[@]}" \
--output-dir "$RUNNER_TEMP/openclaw-cross-os-release-checks/${{ matrix.artifact_name }}-${{ matrix.suite }}"
--output-dir "${OUTPUT_DIR}"
- name: Summarize release checks
if: always()

File diff suppressed because it is too large Load Diff

View File

@@ -43,7 +43,7 @@ jobs:
# so this public workflow can stay focused on OIDC publish only.
preflight_openclaw_npm:
if: ${{ inputs.preflight_only }}
runs-on: blacksmith-32vcpu-ubuntu-2404
runs-on: ubuntu-latest
permissions:
contents: read
steps:
@@ -252,7 +252,7 @@ jobs:
validate_publish_request:
if: ${{ !inputs.preflight_only }}
runs-on: blacksmith-32vcpu-ubuntu-2404
runs-on: ubuntu-latest
permissions:
contents: read
steps:

View File

@@ -4,9 +4,14 @@ on:
workflow_dispatch:
inputs:
ref:
description: Existing release tag or current full 40-character workflow-branch commit SHA to validate (for example v2026.4.12 or 0123456789abcdef0123456789abcdef01234567)
description: Branch, tag, or full commit SHA to validate
required: true
type: string
expected_sha:
description: Optional full SHA that ref must resolve to
required: false
default: ""
type: string
provider:
description: Provider lane for cross-OS onboarding and the end-to-end agent turn
required: false
@@ -25,6 +30,29 @@ on:
- fresh
- upgrade
- both
release_profile:
description: Release coverage profile for live/Docker/provider breadth
required: false
default: full
type: choice
options:
- minimum
- stable
- full
rerun_group:
description: Release check group to run
required: false
default: all
type: choice
options:
- all
- install-smoke
- cross-os
- live-e2e
- package
- qa
- qa-parity
- qa-live
concurrency:
group: openclaw-release-checks-${{ inputs.ref }}
@@ -32,6 +60,9 @@ concurrency:
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
NODE_VERSION: "24.x"
PNPM_VERSION: "10.33.0"
OPENCLAW_CI_OPENAI_MODEL: ${{ vars.OPENCLAW_CI_OPENAI_MODEL }}
jobs:
resolve_target:
@@ -41,9 +72,11 @@ jobs:
contents: read
outputs:
ref: ${{ steps.inputs.outputs.ref }}
sha: ${{ steps.ref.outputs.sha }}
revision: ${{ steps.ref.outputs.sha }}
provider: ${{ steps.inputs.outputs.provider }}
mode: ${{ steps.inputs.outputs.mode }}
release_profile: ${{ steps.inputs.outputs.release_profile }}
rerun_group: ${{ steps.inputs.outputs.rerun_group }}
steps:
- name: Require main or release workflow ref for release checks
env:
@@ -58,80 +91,233 @@ jobs:
- name: Validate ref input
env:
RELEASE_REF: ${{ inputs.ref }}
EXPECTED_SHA: ${{ inputs.expected_sha }}
run: |
set -euo pipefail
if [[ ! "${RELEASE_REF}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*((-beta\.[1-9][0-9]*)|(-[1-9][0-9]*))?$ ]] && [[ ! "${RELEASE_REF}" =~ ^[0-9a-fA-F]{40}$ ]]; then
echo "Expected an existing release tag or current full 40-character workflow-branch commit SHA, got: ${RELEASE_REF}" >&2
if [[ -z "${RELEASE_REF// }" ]] || [[ "${RELEASE_REF}" == -* ]]; then
echo "Expected a branch, tag, or full commit SHA; got: ${RELEASE_REF}" >&2
exit 1
fi
if [[ -n "${EXPECTED_SHA// }" ]] && [[ ! "${EXPECTED_SHA}" =~ ^[0-9a-fA-F]{40}$ ]]; then
echo "Expected expected_sha to be a full commit SHA; got: ${EXPECTED_SHA}" >&2
exit 1
fi
- name: Checkout selected ref
- name: Checkout trusted workflow helper
uses: actions/checkout@v6
with:
ref: ${{ inputs.ref }}
fetch-depth: 0
persist-credentials: false
ref: ${{ github.ref_name }}
path: workflow
fetch-depth: 1
- name: Resolve checked-out SHA
id: ref
run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
- name: Validate selected ref is on workflow branch
- name: Fast-resolve selected ref
id: fast_ref
env:
RELEASE_REF: ${{ inputs.ref }}
EXPECTED_SHA: ${{ inputs.expected_sha }}
run: |
bash workflow/scripts/github/resolve-openclaw-ref.sh \
--ref "$RELEASE_REF" \
--expected-sha "$EXPECTED_SHA" \
--fallback-ok \
--github-output "$GITHUB_OUTPUT"
- name: Checkout selected ref for reachability fallback
if: steps.fast_ref.outputs.fallback == 'true'
uses: actions/checkout@v6
with:
persist-credentials: false
ref: ${{ inputs.ref }}
path: source
fetch-depth: 0
- name: Resolve checked-out fallback SHA
if: steps.fast_ref.outputs.fallback == 'true'
id: fallback_ref
working-directory: source
run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
- name: Validate selected ref belongs to this repository
if: steps.fast_ref.outputs.fallback == 'true'
working-directory: source
env:
RELEASE_REF: ${{ inputs.ref }}
WORKFLOW_REF_NAME: ${{ github.ref_name }}
run: |
set -euo pipefail
RELEASE_BRANCH_REF="refs/remotes/origin/${WORKFLOW_REF_NAME}"
git fetch --no-tags origin "+refs/heads/${WORKFLOW_REF_NAME}:refs/remotes/origin/${WORKFLOW_REF_NAME}"
if [[ "${RELEASE_REF}" =~ ^[0-9a-fA-F]{40}$ ]]; then
BRANCH_SHA="$(git rev-parse "${RELEASE_BRANCH_REF}")"
if [[ "$(git rev-parse HEAD)" != "${BRANCH_SHA}" ]]; then
echo "Commit SHA mode only supports the current ${WORKFLOW_REF_NAME} HEAD. Use a release tag for older commits." >&2
exit 1
fi
else
git merge-base --is-ancestor HEAD "${RELEASE_BRANCH_REF}"
SELECTED_SHA="$(git rev-parse HEAD)"
git fetch --no-tags origin '+refs/heads/*:refs/remotes/origin/*'
git fetch --tags origin '+refs/tags/*:refs/tags/*'
if git tag --points-at "${SELECTED_SHA}" | grep -Eq '^v'; then
exit 0
fi
if git for-each-ref --format='%(refname:short)' --contains "${SELECTED_SHA}" refs/remotes/origin | grep -Eq '^origin/'; then
exit 0
fi
echo "Ref '${RELEASE_REF}' resolved to ${SELECTED_SHA}, but that commit is not reachable from an OpenClaw branch or release tag." >&2
echo "Secret-bearing release checks only run repository-owned branch/tag history, not arbitrary unreferenced commits." >&2
exit 1
- name: Finalize resolved SHA
id: ref
env:
FAST_SHA: ${{ steps.fast_ref.outputs.sha }}
FALLBACK_SHA: ${{ steps.fallback_ref.outputs.sha }}
EXPECTED_SHA: ${{ inputs.expected_sha }}
USED_FALLBACK: ${{ steps.fast_ref.outputs.fallback }}
run: |
set -euo pipefail
selected_sha="$FAST_SHA"
if [[ "$USED_FALLBACK" == "true" ]]; then
selected_sha="$FALLBACK_SHA"
fi
if [[ -z "$selected_sha" ]]; then
echo "Failed to resolve selected ref SHA." >&2
exit 1
fi
if [[ -n "${EXPECTED_SHA// }" ]] && [[ "${selected_sha,,}" != "${EXPECTED_SHA,,}" ]]; then
echo "Ref resolved to ${selected_sha}, expected ${EXPECTED_SHA}." >&2
exit 1
fi
echo "sha=${selected_sha,,}" >> "$GITHUB_OUTPUT"
- name: Capture selected inputs
id: inputs
env:
RELEASE_REF_INPUT: ${{ inputs.ref }}
RELEASE_PROVIDER_INPUT: ${{ inputs.provider }}
RELEASE_MODE_INPUT: ${{ inputs.mode }}
RELEASE_PROFILE_INPUT: ${{ inputs.release_profile }}
RELEASE_RERUN_GROUP_INPUT: ${{ inputs.rerun_group }}
run: |
set -euo pipefail
{
printf 'ref=%s\n' "$RELEASE_REF_INPUT"
printf 'provider=%s\n' "$RELEASE_PROVIDER_INPUT"
printf 'mode=%s\n' "$RELEASE_MODE_INPUT"
printf 'release_profile=%s\n' "$RELEASE_PROFILE_INPUT"
printf 'rerun_group=%s\n' "$RELEASE_RERUN_GROUP_INPUT"
} >> "$GITHUB_OUTPUT"
- name: Summarize validated ref
env:
RELEASE_REF: ${{ inputs.ref }}
RELEASE_SHA: ${{ steps.ref.outputs.sha }}
RELEASE_REF_FAST_PATH: ${{ steps.fast_ref.outputs.fast }}
RELEASE_PROVIDER: ${{ inputs.provider }}
RELEASE_MODE: ${{ inputs.mode }}
RELEASE_PROFILE: ${{ inputs.release_profile }}
RELEASE_RERUN_GROUP: ${{ inputs.rerun_group }}
run: |
{
echo "## Release checks"
echo
echo "- Requested ref: \`${RELEASE_REF}\`"
echo "- Validated SHA: \`${RELEASE_SHA}\`"
echo "- Ref resolution fast path: \`${RELEASE_REF_FAST_PATH}\`"
echo "- Cross-OS provider: \`${RELEASE_PROVIDER}\`"
echo "- Cross-OS mode: \`${RELEASE_MODE}\`"
echo "- This run will execute cross-OS release validation plus the non-Parallels Docker/live/openwebui coverage from the CI migration plan."
echo "- Release profile: \`${RELEASE_PROFILE}\`"
echo "- Rerun group: \`${RELEASE_RERUN_GROUP}\`"
echo "- This run will execute cross-OS release validation, install smoke, QA Lab parity, Matrix, and Telegram lanes, and the non-Parallels Docker/live/openwebui coverage from the CI migration plan."
} >> "$GITHUB_STEP_SUMMARY"
cross_os_release_checks:
prepare_release_package:
name: Prepare release package artifact
needs: [resolve_target]
if: contains(fromJSON('["all","cross-os","live-e2e","package"]'), needs.resolve_target.outputs.rerun_group)
runs-on: blacksmith-32vcpu-ubuntu-2404
timeout-minutes: 60
permissions:
contents: read
outputs:
artifact_name: ${{ steps.artifact.outputs.name }}
package_sha256: ${{ steps.package.outputs.sha256 }}
package_version: ${{ steps.package.outputs.package_version }}
source_sha: ${{ steps.package.outputs.source_sha }}
steps:
- name: Checkout trusted workflow ref
uses: actions/checkout@v6
with:
persist-credentials: false
ref: ${{ github.ref_name }}
fetch-depth: 0
- name: Set artifact metadata
id: artifact
run: echo "name=release-package-under-test" >> "$GITHUB_OUTPUT"
- name: Setup Node environment
uses: ./.github/actions/setup-node-env
with:
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
install-bun: "true"
install-deps: "false"
- name: Resolve release package artifact
id: package
shell: bash
env:
PACKAGE_REF: ${{ needs.resolve_target.outputs.revision }}
run: |
set -euo pipefail
node scripts/resolve-openclaw-package-candidate.mjs \
--source ref \
--package-ref "$PACKAGE_REF" \
--output-dir .artifacts/docker-e2e-package \
--output-name openclaw-current.tgz \
--metadata .artifacts/docker-e2e-package/package-candidate.json \
--github-output "$GITHUB_OUTPUT"
digest="$(node -p "JSON.parse(require('fs').readFileSync('.artifacts/docker-e2e-package/package-candidate.json', 'utf8')).sha256")"
version="$(node -p "JSON.parse(require('fs').readFileSync('.artifacts/docker-e2e-package/package-candidate.json', 'utf8')).version")"
source_sha="$(node -p "JSON.parse(require('fs').readFileSync('.artifacts/docker-e2e-package/package-candidate.json', 'utf8')).packageSourceSha")"
echo "source_sha=$source_sha" >> "$GITHUB_OUTPUT"
{
echo "## Release package artifact"
echo
echo "- Artifact: \`release-package-under-test\`"
echo "- Package ref: \`$PACKAGE_REF\`"
echo "- SHA-256: \`$digest\`"
echo "- Version: \`$version\`"
echo "- Source SHA: \`$source_sha\`"
} >> "$GITHUB_STEP_SUMMARY"
- name: Upload release package artifact
uses: actions/upload-artifact@v7
with:
name: release-package-under-test
path: .artifacts/docker-e2e-package/openclaw-current.tgz
retention-days: 14
if-no-files-found: error
install_smoke_release_checks:
needs: [resolve_target]
if: contains(fromJSON('["all","install-smoke"]'), needs.resolve_target.outputs.rerun_group)
permissions:
contents: read
uses: ./.github/workflows/install-smoke.yml
with:
ref: ${{ needs.resolve_target.outputs.revision }}
run_bun_global_install_smoke: true
cross_os_release_checks:
needs: [resolve_target, prepare_release_package]
if: contains(fromJSON('["all","cross-os"]'), needs.resolve_target.outputs.rerun_group)
permissions: read-all
uses: ./.github/workflows/openclaw-cross-os-release-checks-reusable.yml
with:
ref: ${{ needs.resolve_target.outputs.ref }}
provider: ${{ needs.resolve_target.outputs.provider }}
mode: ${{ needs.resolve_target.outputs.mode }}
candidate_artifact_name: ${{ needs.prepare_release_package.outputs.artifact_name }}
candidate_artifact_run_id: ${{ github.run_id }}
candidate_file_name: openclaw-current.tgz
candidate_version: ${{ needs.prepare_release_package.outputs.package_version }}
candidate_source_sha: ${{ needs.prepare_release_package.outputs.source_sha }}
secrets:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
@@ -141,17 +327,23 @@ jobs:
OPENCLAW_DISCORD_SMOKE_CHANNEL_ID: ${{ secrets.OPENCLAW_DISCORD_SMOKE_CHANNEL_ID }}
live_and_e2e_release_checks:
needs: [resolve_target]
needs: [resolve_target, prepare_release_package]
if: contains(fromJSON('["all","live-e2e"]'), needs.resolve_target.outputs.rerun_group)
permissions:
actions: read
contents: read
packages: write
pull-requests: read
uses: ./.github/workflows/openclaw-live-and-e2e-checks-reusable.yml
with:
ref: ${{ needs.resolve_target.outputs.ref }}
ref: ${{ needs.resolve_target.outputs.revision }}
include_repo_e2e: true
include_release_path_suites: true
include_openwebui: true
include_openwebui: ${{ needs.resolve_target.outputs.release_profile != 'minimum' }}
include_live_suites: true
release_test_profile: ${{ needs.resolve_target.outputs.release_profile }}
package_artifact_name: ${{ needs.prepare_release_package.outputs.artifact_name }}
package_artifact_run_id: ${{ github.run_id }}
secrets:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL }}
@@ -160,6 +352,7 @@ jobs:
ANTHROPIC_API_TOKEN: ${{ secrets.ANTHROPIC_API_TOKEN }}
BYTEPLUS_API_KEY: ${{ secrets.BYTEPLUS_API_KEY }}
CEREBRAS_API_KEY: ${{ secrets.CEREBRAS_API_KEY }}
DEEPINFRA_API_KEY: ${{ secrets.DEEPINFRA_API_KEY }}
DASHSCOPE_API_KEY: ${{ secrets.DASHSCOPE_API_KEY }}
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
KIMI_API_KEY: ${{ secrets.KIMI_API_KEY }}
@@ -196,3 +389,421 @@ jobs:
OPENCLAW_CLAUDE_SETTINGS_JSON: ${{ secrets.OPENCLAW_CLAUDE_SETTINGS_JSON }}
OPENCLAW_CLAUDE_SETTINGS_LOCAL_JSON: ${{ secrets.OPENCLAW_CLAUDE_SETTINGS_LOCAL_JSON }}
OPENCLAW_GEMINI_SETTINGS_JSON: ${{ secrets.OPENCLAW_GEMINI_SETTINGS_JSON }}
FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }}
package_acceptance_release_checks:
name: Run package acceptance
needs: [resolve_target, prepare_release_package]
if: contains(fromJSON('["all","package"]'), needs.resolve_target.outputs.rerun_group)
permissions:
actions: read
contents: read
packages: write
pull-requests: read
uses: ./.github/workflows/package-acceptance.yml
with:
workflow_ref: ${{ github.ref_name }}
source: artifact
artifact_run_id: ${{ github.run_id }}
artifact_name: ${{ needs.prepare_release_package.outputs.artifact_name }}
package_sha256: ${{ needs.prepare_release_package.outputs.package_sha256 }}
suite_profile: custom
docker_lanes: bundled-channel-deps-compat plugins-offline
telegram_mode: mock-openai
telegram_scenarios: telegram-help-command,telegram-commands-command,telegram-tools-compact-command,telegram-whoami-command,telegram-context-command,telegram-mention-gating
secrets:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
ANTHROPIC_API_KEY_OLD: ${{ secrets.ANTHROPIC_API_KEY_OLD }}
ANTHROPIC_API_TOKEN: ${{ secrets.ANTHROPIC_API_TOKEN }}
BYTEPLUS_API_KEY: ${{ secrets.BYTEPLUS_API_KEY }}
CEREBRAS_API_KEY: ${{ secrets.CEREBRAS_API_KEY }}
DEEPINFRA_API_KEY: ${{ secrets.DEEPINFRA_API_KEY }}
DASHSCOPE_API_KEY: ${{ secrets.DASHSCOPE_API_KEY }}
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
KIMI_API_KEY: ${{ secrets.KIMI_API_KEY }}
MODELSTUDIO_API_KEY: ${{ secrets.MODELSTUDIO_API_KEY }}
MOONSHOT_API_KEY: ${{ secrets.MOONSHOT_API_KEY }}
MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }}
MINIMAX_API_KEY: ${{ secrets.MINIMAX_API_KEY }}
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
OPENCODE_ZEN_API_KEY: ${{ secrets.OPENCODE_ZEN_API_KEY }}
OPENCLAW_LIVE_BROWSER_CDP_URL: ${{ secrets.OPENCLAW_LIVE_BROWSER_CDP_URL }}
OPENCLAW_LIVE_SETUP_TOKEN: ${{ secrets.OPENCLAW_LIVE_SETUP_TOKEN }}
OPENCLAW_LIVE_SETUP_TOKEN_MODEL: ${{ secrets.OPENCLAW_LIVE_SETUP_TOKEN_MODEL }}
OPENCLAW_LIVE_SETUP_TOKEN_PROFILE: ${{ secrets.OPENCLAW_LIVE_SETUP_TOKEN_PROFILE }}
OPENCLAW_LIVE_SETUP_TOKEN_VALUE: ${{ secrets.OPENCLAW_LIVE_SETUP_TOKEN_VALUE }}
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
QWEN_API_KEY: ${{ secrets.QWEN_API_KEY }}
FAL_KEY: ${{ secrets.FAL_KEY }}
RUNWAY_API_KEY: ${{ secrets.RUNWAY_API_KEY }}
DEEPGRAM_API_KEY: ${{ secrets.DEEPGRAM_API_KEY }}
TOGETHER_API_KEY: ${{ secrets.TOGETHER_API_KEY }}
VYDRA_API_KEY: ${{ secrets.VYDRA_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 }}
BYTEPLUS_ACCESS_KEY_ID: ${{ secrets.BYTEPLUS_ACCESS_KEY_ID }}
BYTEPLUS_SECRET_ACCESS_KEY: ${{ secrets.BYTEPLUS_SECRET_ACCESS_KEY }}
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
OPENCLAW_CODEX_AUTH_JSON: ${{ secrets.OPENCLAW_CODEX_AUTH_JSON }}
OPENCLAW_CODEX_CONFIG_TOML: ${{ secrets.OPENCLAW_CODEX_CONFIG_TOML }}
OPENCLAW_CLAUDE_JSON: ${{ secrets.OPENCLAW_CLAUDE_JSON }}
OPENCLAW_CLAUDE_CREDENTIALS_JSON: ${{ secrets.OPENCLAW_CLAUDE_CREDENTIALS_JSON }}
OPENCLAW_CLAUDE_SETTINGS_JSON: ${{ secrets.OPENCLAW_CLAUDE_SETTINGS_JSON }}
OPENCLAW_CLAUDE_SETTINGS_LOCAL_JSON: ${{ secrets.OPENCLAW_CLAUDE_SETTINGS_LOCAL_JSON }}
OPENCLAW_GEMINI_SETTINGS_JSON: ${{ secrets.OPENCLAW_GEMINI_SETTINGS_JSON }}
FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }}
OPENCLAW_QA_CONVEX_SITE_URL: ${{ secrets.OPENCLAW_QA_CONVEX_SITE_URL }}
OPENCLAW_QA_CONVEX_SECRET_CI: ${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }}
qa_lab_parity_lane_release_checks:
name: Run QA Lab parity lane (${{ matrix.lane }})
needs: [resolve_target]
if: contains(fromJSON('["all","qa","qa-parity"]'), needs.resolve_target.outputs.rerun_group)
runs-on: blacksmith-32vcpu-ubuntu-2404
timeout-minutes: 30
permissions:
contents: read
strategy:
fail-fast: false
matrix:
include:
- lane: candidate
output_dir: gpt54
- lane: baseline
output_dir: opus46
env:
QA_PARITY_CONCURRENCY: "1"
OPENCLAW_QA_TRANSPORT_READY_TIMEOUT_MS: "180000"
OPENAI_API_KEY: ""
ANTHROPIC_API_KEY: ""
OPENCLAW_LIVE_OPENAI_KEY: ""
OPENCLAW_LIVE_ANTHROPIC_KEY: ""
OPENCLAW_LIVE_GEMINI_KEY: ""
OPENCLAW_LIVE_SETUP_TOKEN_VALUE: ""
OPENCLAW_BUILD_PRIVATE_QA: "1"
OPENCLAW_ENABLE_PRIVATE_QA_CLI: "1"
steps:
- name: Checkout selected ref
uses: actions/checkout@v6
with:
persist-credentials: false
ref: ${{ needs.resolve_target.outputs.revision }}
fetch-depth: 1
- name: Setup Node environment
uses: ./.github/actions/setup-node-env
with:
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
install-bun: "true"
- name: Build private QA runtime
run: pnpm build
- name: Run parity lane
env:
QA_PARITY_LANE: ${{ matrix.lane }}
QA_PARITY_OUTPUT_DIR: ${{ matrix.output_dir }}
run: |
set -euo pipefail
case "${QA_PARITY_LANE}" in
candidate)
model="${OPENCLAW_CI_OPENAI_MODEL}"
alt_model="openai/gpt-5.4-alt"
;;
baseline)
model="anthropic/claude-opus-4-6"
alt_model="anthropic/claude-sonnet-4-6"
;;
*)
echo "Unknown QA parity lane: ${QA_PARITY_LANE}" >&2
exit 1
;;
esac
pnpm openclaw qa suite \
--provider-mode mock-openai \
--parity-pack agentic \
--concurrency "${QA_PARITY_CONCURRENCY}" \
--model "${model}" \
--alt-model "${alt_model}" \
--output-dir ".artifacts/qa-e2e/${QA_PARITY_OUTPUT_DIR}"
- name: Upload parity lane artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: release-qa-parity-${{ matrix.lane }}-${{ needs.resolve_target.outputs.revision }}
path: .artifacts/qa-e2e/
retention-days: 14
if-no-files-found: warn
qa_lab_parity_report_release_checks:
name: Run QA Lab parity report
needs: [resolve_target, qa_lab_parity_lane_release_checks]
if: contains(fromJSON('["all","qa","qa-parity"]'), needs.resolve_target.outputs.rerun_group)
runs-on: blacksmith-32vcpu-ubuntu-2404
timeout-minutes: 20
permissions:
contents: read
actions: read
env:
OPENCLAW_BUILD_PRIVATE_QA: "1"
OPENCLAW_ENABLE_PRIVATE_QA_CLI: "1"
steps:
- name: Checkout selected ref
uses: actions/checkout@v6
with:
persist-credentials: false
ref: ${{ needs.resolve_target.outputs.revision }}
fetch-depth: 1
- name: Setup Node environment
uses: ./.github/actions/setup-node-env
with:
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
install-bun: "true"
- name: Download parity lane artifacts
uses: actions/download-artifact@v4
with:
pattern: release-qa-parity-*-${{ needs.resolve_target.outputs.revision }}
path: .artifacts/qa-e2e/
merge-multiple: true
- name: Build private QA runtime
run: pnpm build
- name: Generate parity report
run: |
pnpm openclaw qa parity-report \
--repo-root . \
--candidate-summary .artifacts/qa-e2e/gpt54/qa-suite-summary.json \
--baseline-summary .artifacts/qa-e2e/opus46/qa-suite-summary.json \
--candidate-label "${OPENCLAW_CI_OPENAI_MODEL}" \
--baseline-label anthropic/claude-opus-4-6 \
--output-dir .artifacts/qa-e2e/parity
- name: Upload parity artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: release-qa-parity-${{ needs.resolve_target.outputs.revision }}
path: .artifacts/qa-e2e/
retention-days: 14
if-no-files-found: warn
qa_live_matrix_release_checks:
name: Run QA Lab live Matrix lane
needs: [resolve_target]
if: contains(fromJSON('["all","qa","qa-live"]'), needs.resolve_target.outputs.rerun_group)
runs-on: blacksmith-32vcpu-ubuntu-2404
timeout-minutes: 60
permissions:
contents: read
pull-requests: read
environment: qa-live-shared
env:
OPENCLAW_BUILD_PRIVATE_QA: "1"
OPENCLAW_ENABLE_PRIVATE_QA_CLI: "1"
steps:
- name: Checkout selected ref
uses: actions/checkout@v6
with:
persist-credentials: false
ref: ${{ needs.resolve_target.outputs.revision }}
fetch-depth: 1
- name: Setup Node environment
uses: ./.github/actions/setup-node-env
with:
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
install-bun: "true"
- name: Validate required QA credential env
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
shell: bash
run: |
set -euo pipefail
if [[ -z "${OPENAI_API_KEY:-}" ]]; then
echo "Missing required OPENAI_API_KEY." >&2
exit 1
fi
- name: Build private QA runtime
run: pnpm build
- name: Run Matrix live lane
id: run_lane
shell: bash
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENCLAW_QA_REDACT_PUBLIC_METADATA: "1"
OPENCLAW_QA_MATRIX_NO_REPLY_WINDOW_MS: "3000"
run: |
set -euo pipefail
output_dir=".artifacts/qa-e2e/matrix-live-release-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
echo "output_dir=${output_dir}" >> "$GITHUB_OUTPUT"
matrix_args=(
--repo-root . \
--output-dir "${output_dir}" \
--provider-mode live-frontier \
--model "${OPENCLAW_CI_OPENAI_MODEL}" \
--alt-model "${OPENCLAW_CI_OPENAI_MODEL}" \
--profile fast \
--fast
)
if pnpm openclaw qa matrix --help 2>/dev/null | grep -F -q -- "--fail-fast"; then
matrix_args+=(--fail-fast)
fi
pnpm openclaw qa matrix "${matrix_args[@]}"
- name: Upload Matrix QA artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: release-qa-live-matrix-${{ needs.resolve_target.outputs.revision }}
path: .artifacts/qa-e2e/
retention-days: 14
if-no-files-found: warn
qa_live_telegram_release_checks:
name: Run QA Lab live Telegram lane
needs: [resolve_target]
if: contains(fromJSON('["all","qa","qa-live"]'), needs.resolve_target.outputs.rerun_group)
runs-on: blacksmith-32vcpu-ubuntu-2404
timeout-minutes: 60
permissions:
contents: read
pull-requests: read
environment: qa-live-shared
env:
OPENCLAW_BUILD_PRIVATE_QA: "1"
OPENCLAW_ENABLE_PRIVATE_QA_CLI: "1"
steps:
- name: Checkout selected ref
uses: actions/checkout@v6
with:
persist-credentials: false
ref: ${{ needs.resolve_target.outputs.revision }}
fetch-depth: 1
- name: Setup Node environment
uses: ./.github/actions/setup-node-env
with:
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
install-bun: "true"
- name: Validate required QA credential env
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENCLAW_QA_CONVEX_SITE_URL: ${{ secrets.OPENCLAW_QA_CONVEX_SITE_URL }}
OPENCLAW_QA_CONVEX_SECRET_CI: ${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }}
shell: bash
run: |
set -euo pipefail
require_var() {
local key="$1"
if [[ -z "${!key:-}" ]]; then
echo "Missing required ${key}." >&2
exit 1
fi
}
require_var OPENAI_API_KEY
require_var OPENCLAW_QA_CONVEX_SITE_URL
require_var OPENCLAW_QA_CONVEX_SECRET_CI
- name: Build private QA runtime
run: pnpm build
- name: Run Telegram live lane
id: run_lane
shell: bash
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENCLAW_QA_CONVEX_SITE_URL: ${{ secrets.OPENCLAW_QA_CONVEX_SITE_URL }}
OPENCLAW_QA_CONVEX_SECRET_CI: ${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }}
OPENCLAW_QA_REDACT_PUBLIC_METADATA: "1"
OPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT: "1"
run: |
set -euo pipefail
output_dir=".artifacts/qa-e2e/telegram-live-release-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
echo "output_dir=${output_dir}" >> "$GITHUB_OUTPUT"
pnpm openclaw qa telegram \
--repo-root . \
--output-dir "${output_dir}" \
--provider-mode live-frontier \
--model "${OPENCLAW_CI_OPENAI_MODEL}" \
--alt-model "${OPENCLAW_CI_OPENAI_MODEL}" \
--fast \
--credential-source convex \
--credential-role ci
- name: Upload Telegram QA artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: release-qa-live-telegram-${{ needs.resolve_target.outputs.revision }}
path: .artifacts/qa-e2e/
retention-days: 14
if-no-files-found: warn
summary:
name: Verify release checks
needs:
- prepare_release_package
- install_smoke_release_checks
- cross_os_release_checks
- live_and_e2e_release_checks
- package_acceptance_release_checks
- qa_lab_parity_lane_release_checks
- qa_lab_parity_report_release_checks
- qa_live_matrix_release_checks
- qa_live_telegram_release_checks
if: always()
runs-on: ubuntu-24.04
permissions: {}
timeout-minutes: 5
steps:
- name: Verify release check results
shell: bash
run: |
set -euo pipefail
failed=0
for item in \
"prepare_release_package=${{ needs.prepare_release_package.result }}" \
"install_smoke_release_checks=${{ needs.install_smoke_release_checks.result }}" \
"cross_os_release_checks=${{ needs.cross_os_release_checks.result }}" \
"live_and_e2e_release_checks=${{ needs.live_and_e2e_release_checks.result }}" \
"package_acceptance_release_checks=${{ needs.package_acceptance_release_checks.result }}" \
"qa_lab_parity_lane_release_checks=${{ needs.qa_lab_parity_lane_release_checks.result }}" \
"qa_lab_parity_report_release_checks=${{ needs.qa_lab_parity_report_release_checks.result }}" \
"qa_live_matrix_release_checks=${{ needs.qa_live_matrix_release_checks.result }}" \
"qa_live_telegram_release_checks=${{ needs.qa_live_telegram_release_checks.result }}"
do
name="${item%%=*}"
result="${item#*=}"
if [[ "$result" != "success" && "$result" != "skipped" ]]; then
echo "::error::${name} ended with ${result}"
failed=1
fi
done
exit "$failed"

View File

@@ -7,6 +7,7 @@ on:
permissions:
contents: read
packages: write
pull-requests: read
concurrency:
@@ -20,12 +21,13 @@ jobs:
live_and_openwebui_checks:
permissions:
contents: read
packages: write
pull-requests: read
uses: ./.github/workflows/openclaw-live-and-e2e-checks-reusable.yml
with:
ref: ${{ github.sha }}
include_repo_e2e: true
include_release_path_suites: false
include_release_path_suites: true
include_openwebui: true
include_live_suites: true
secrets:
@@ -36,6 +38,7 @@ jobs:
ANTHROPIC_API_TOKEN: ${{ secrets.ANTHROPIC_API_TOKEN }}
BYTEPLUS_API_KEY: ${{ secrets.BYTEPLUS_API_KEY }}
CEREBRAS_API_KEY: ${{ secrets.CEREBRAS_API_KEY }}
DEEPINFRA_API_KEY: ${{ secrets.DEEPINFRA_API_KEY }}
DASHSCOPE_API_KEY: ${{ secrets.DASHSCOPE_API_KEY }}
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
KIMI_API_KEY: ${{ secrets.KIMI_API_KEY }}
@@ -72,3 +75,4 @@ jobs:
OPENCLAW_CLAUDE_SETTINGS_JSON: ${{ secrets.OPENCLAW_CLAUDE_SETTINGS_JSON }}
OPENCLAW_CLAUDE_SETTINGS_LOCAL_JSON: ${{ secrets.OPENCLAW_CLAUDE_SETTINGS_LOCAL_JSON }}
OPENCLAW_GEMINI_SETTINGS_JSON: ${{ secrets.OPENCLAW_GEMINI_SETTINGS_JSON }}
FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }}

532
.github/workflows/package-acceptance.yml vendored Normal file
View File

@@ -0,0 +1,532 @@
name: Package Acceptance
on:
workflow_dispatch:
inputs:
workflow_ref:
description: Trusted repo ref for workflow scripts and Docker E2E harness
required: true
default: main
type: string
source:
description: Package candidate source
required: true
default: npm
type: choice
options:
- npm
- ref
- url
- artifact
package_ref:
description: Trusted package source ref when source=ref
required: true
default: main
type: string
package_spec:
description: Published package spec when source=npm
required: false
default: openclaw@beta
type: string
package_url:
description: HTTPS .tgz URL when source=url
required: false
default: ""
type: string
package_sha256:
description: Expected package SHA-256; required for source=url
required: false
default: ""
type: string
artifact_run_id:
description: GitHub Actions run id when source=artifact
required: false
default: ""
type: string
artifact_name:
description: Artifact name containing one .tgz when source=artifact
required: false
default: package-under-test
type: string
suite_profile:
description: Acceptance profile
required: true
default: package
type: choice
options:
- smoke
- package
- product
- full
- custom
docker_lanes:
description: Comma/space separated Docker lanes when suite_profile=custom
required: false
default: ""
type: string
telegram_mode:
description: Optional Telegram QA lane for the resolved package candidate
required: true
default: none
type: choice
options:
- none
- mock-openai
- live-frontier
telegram_scenarios:
description: Optional comma-separated Telegram scenario ids
required: false
default: ""
type: string
workflow_call:
inputs:
workflow_ref:
description: Trusted repo ref for workflow scripts and Docker E2E harness
required: false
default: main
type: string
source:
description: "Package candidate source: npm, ref, url, or artifact"
required: true
type: string
package_ref:
description: Trusted package source ref when source=ref
required: false
default: main
type: string
package_spec:
description: Published package spec when source=npm
required: false
default: openclaw@beta
type: string
package_url:
description: HTTPS .tgz URL when source=url
required: false
default: ""
type: string
package_sha256:
description: Expected package SHA-256; required for source=url
required: false
default: ""
type: string
artifact_run_id:
description: GitHub Actions run id when source=artifact
required: false
default: ""
type: string
artifact_name:
description: Artifact name containing one .tgz when source=artifact
required: false
default: package-under-test
type: string
suite_profile:
description: "Acceptance profile: smoke, package, product, full, or custom"
required: false
default: package
type: string
docker_lanes:
description: Comma/space separated Docker lanes when suite_profile=custom
required: false
default: ""
type: string
telegram_mode:
description: Optional Telegram QA lane for the resolved package candidate
required: false
default: none
type: string
telegram_scenarios:
description: Optional comma-separated Telegram scenario ids
required: false
default: ""
type: string
secrets:
OPENAI_API_KEY:
required: false
OPENAI_BASE_URL:
required: false
ANTHROPIC_API_KEY:
required: false
ANTHROPIC_API_KEY_OLD:
required: false
ANTHROPIC_API_TOKEN:
required: false
BYTEPLUS_API_KEY:
required: false
CEREBRAS_API_KEY:
required: false
DEEPINFRA_API_KEY:
required: false
DASHSCOPE_API_KEY:
required: false
GROQ_API_KEY:
required: false
KIMI_API_KEY:
required: false
MODELSTUDIO_API_KEY:
required: false
MOONSHOT_API_KEY:
required: false
MISTRAL_API_KEY:
required: false
MINIMAX_API_KEY:
required: false
OPENCODE_API_KEY:
required: false
OPENCODE_ZEN_API_KEY:
required: false
OPENCLAW_LIVE_BROWSER_CDP_URL:
required: false
OPENCLAW_LIVE_SETUP_TOKEN:
required: false
OPENCLAW_LIVE_SETUP_TOKEN_MODEL:
required: false
OPENCLAW_LIVE_SETUP_TOKEN_PROFILE:
required: false
OPENCLAW_LIVE_SETUP_TOKEN_VALUE:
required: false
GEMINI_API_KEY:
required: false
GOOGLE_API_KEY:
required: false
OPENROUTER_API_KEY:
required: false
QWEN_API_KEY:
required: false
FAL_KEY:
required: false
RUNWAY_API_KEY:
required: false
DEEPGRAM_API_KEY:
required: false
TOGETHER_API_KEY:
required: false
VYDRA_API_KEY:
required: false
XAI_API_KEY:
required: false
ZAI_API_KEY:
required: false
Z_AI_API_KEY:
required: false
BYTEPLUS_ACCESS_KEY_ID:
required: false
BYTEPLUS_SECRET_ACCESS_KEY:
required: false
CLAUDE_CODE_OAUTH_TOKEN:
required: false
OPENCLAW_CODEX_AUTH_JSON:
required: false
OPENCLAW_CODEX_CONFIG_TOML:
required: false
OPENCLAW_CLAUDE_JSON:
required: false
OPENCLAW_CLAUDE_CREDENTIALS_JSON:
required: false
OPENCLAW_CLAUDE_SETTINGS_JSON:
required: false
OPENCLAW_CLAUDE_SETTINGS_LOCAL_JSON:
required: false
OPENCLAW_GEMINI_SETTINGS_JSON:
required: false
FIREWORKS_API_KEY:
required: false
OPENCLAW_QA_CONVEX_SITE_URL:
required: false
OPENCLAW_QA_CONVEX_SECRET_CI:
required: false
permissions:
actions: read
contents: read
packages: write
pull-requests: read
concurrency:
group: package-acceptance-${{ github.run_id }}
cancel-in-progress: false
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
NODE_VERSION: "24.x"
PNPM_VERSION: "10.33.0"
PACKAGE_ARTIFACT_NAME: package-under-test
jobs:
resolve_package:
name: Resolve package candidate
runs-on: ubuntu-24.04
timeout-minutes: 60
outputs:
docker_lanes: ${{ steps.profile.outputs.docker_lanes }}
include_live_suites: ${{ steps.profile.outputs.include_live_suites }}
include_openwebui: ${{ steps.profile.outputs.include_openwebui }}
include_release_path_suites: ${{ steps.profile.outputs.include_release_path_suites }}
package_artifact_name: ${{ steps.profile.outputs.package_artifact_name }}
package_sha256: ${{ steps.resolve.outputs.sha256 }}
package_version: ${{ steps.resolve.outputs.package_version }}
telegram_enabled: ${{ steps.profile.outputs.telegram_enabled }}
telegram_mode: ${{ steps.profile.outputs.telegram_mode }}
steps:
- name: Checkout package workflow ref
uses: actions/checkout@v6
with:
ref: ${{ inputs.workflow_ref }}
fetch-depth: 0
- name: Setup Node environment
uses: ./.github/actions/setup-node-env
with:
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
install-bun: ${{ inputs.source == 'ref' && 'true' || 'false' }}
install-deps: "false"
- name: Download package artifact input
if: inputs.source == 'artifact'
env:
GH_TOKEN: ${{ github.token }}
ARTIFACT_RUN_ID: ${{ inputs.artifact_run_id }}
ARTIFACT_NAME: ${{ inputs.artifact_name }}
shell: bash
run: |
set -euo pipefail
if [[ -z "${ARTIFACT_RUN_ID// }" ]]; then
echo "artifact_run_id is required when source=artifact." >&2
exit 1
fi
if [[ -z "${ARTIFACT_NAME// }" ]]; then
echo "artifact_name is required when source=artifact." >&2
exit 1
fi
mkdir -p .artifacts/package-candidate-input
gh run download "$ARTIFACT_RUN_ID" -n "$ARTIFACT_NAME" -D .artifacts/package-candidate-input
- name: Resolve package candidate
id: resolve
env:
SOURCE: ${{ inputs.source }}
PACKAGE_REF: ${{ inputs.package_ref }}
PACKAGE_SPEC: ${{ inputs.package_spec }}
PACKAGE_URL: ${{ inputs.package_url }}
PACKAGE_SHA256: ${{ inputs.package_sha256 }}
shell: bash
run: |
set -euo pipefail
artifact_dir=""
if [[ "$SOURCE" == "artifact" ]]; then
artifact_dir=".artifacts/package-candidate-input"
fi
node scripts/resolve-openclaw-package-candidate.mjs \
--source "$SOURCE" \
--package-ref "$PACKAGE_REF" \
--package-spec "$PACKAGE_SPEC" \
--package-url "$PACKAGE_URL" \
--package-sha256 "$PACKAGE_SHA256" \
--artifact-dir "${artifact_dir:-.}" \
--output-dir .artifacts/docker-e2e-package \
--output-name openclaw-current.tgz \
--metadata .artifacts/docker-e2e-package/package-candidate.json \
--github-output "$GITHUB_OUTPUT"
- name: Select acceptance profile
id: profile
env:
SOURCE: ${{ inputs.source }}
SUITE_PROFILE: ${{ inputs.suite_profile }}
CUSTOM_DOCKER_LANES: ${{ inputs.docker_lanes }}
TELEGRAM_MODE: ${{ inputs.telegram_mode }}
shell: bash
run: |
set -euo pipefail
include_release_path_suites=false
include_openwebui=false
include_live_suites=false
docker_lanes=""
case "$SUITE_PROFILE" in
smoke)
docker_lanes="npm-onboard-channel-agent gateway-network config-reload"
;;
package)
docker_lanes="npm-onboard-channel-agent doctor-switch update-channel-switch bundled-channel-deps-compat plugins-offline plugin-update"
;;
product)
docker_lanes="npm-onboard-channel-agent doctor-switch update-channel-switch bundled-channel-deps-compat plugins plugin-update mcp-channels cron-mcp-cleanup openai-web-search-minimal openwebui"
include_openwebui=true
;;
full)
include_release_path_suites=true
include_openwebui=true
;;
custom)
docker_lanes="$CUSTOM_DOCKER_LANES"
if [[ -z "${docker_lanes// }" ]]; then
echo "docker_lanes is required when suite_profile=custom." >&2
exit 1
fi
if [[ "$docker_lanes" == *"openwebui"* ]]; then
include_openwebui=true
fi
;;
*)
echo "Unknown suite_profile: $SUITE_PROFILE" >&2
exit 1
;;
esac
telegram_enabled=false
if [[ "$TELEGRAM_MODE" != "none" ]]; then
telegram_enabled=true
fi
{
echo "docker_lanes=$docker_lanes"
echo "include_release_path_suites=$include_release_path_suites"
echo "include_openwebui=$include_openwebui"
echo "include_live_suites=$include_live_suites"
echo "telegram_enabled=$telegram_enabled"
echo "telegram_mode=$TELEGRAM_MODE"
echo "package_artifact_name=${PACKAGE_ARTIFACT_NAME}"
} >> "$GITHUB_OUTPUT"
- name: Upload package-under-test artifact
uses: actions/upload-artifact@v7
with:
name: ${{ env.PACKAGE_ARTIFACT_NAME }}
path: |
.artifacts/docker-e2e-package/openclaw-current.tgz
.artifacts/docker-e2e-package/package-candidate.json
retention-days: 14
if-no-files-found: error
- name: Summarize package candidate
env:
PACKAGE_SHA256: ${{ steps.resolve.outputs.sha256 }}
PACKAGE_VERSION: ${{ steps.resolve.outputs.package_version }}
PACKAGE_REF: ${{ inputs.package_ref }}
SOURCE: ${{ inputs.source }}
SUITE_PROFILE: ${{ inputs.suite_profile }}
WORKFLOW_REF: ${{ inputs.workflow_ref }}
shell: bash
run: |
{
echo "## Package acceptance"
echo
echo "- Source: \`${SOURCE}\`"
echo "- Workflow ref: \`${WORKFLOW_REF}\`"
if [[ "${SOURCE}" == "ref" ]]; then
echo "- Package ref: \`${PACKAGE_REF}\`"
fi
echo "- Version: \`${PACKAGE_VERSION}\`"
echo "- SHA-256: \`${PACKAGE_SHA256}\`"
echo "- Profile: \`${SUITE_PROFILE}\`"
} >> "$GITHUB_STEP_SUMMARY"
docker_acceptance:
name: Docker product acceptance
needs: resolve_package
uses: ./.github/workflows/openclaw-live-and-e2e-checks-reusable.yml
with:
ref: ${{ inputs.workflow_ref }}
include_repo_e2e: false
include_release_path_suites: ${{ needs.resolve_package.outputs.include_release_path_suites == 'true' }}
include_openwebui: ${{ needs.resolve_package.outputs.include_openwebui == 'true' }}
docker_lanes: ${{ needs.resolve_package.outputs.docker_lanes }}
package_artifact_name: ${{ needs.resolve_package.outputs.package_artifact_name }}
include_live_suites: ${{ needs.resolve_package.outputs.include_live_suites == 'true' }}
live_models_only: false
secrets:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
ANTHROPIC_API_KEY_OLD: ${{ secrets.ANTHROPIC_API_KEY_OLD }}
ANTHROPIC_API_TOKEN: ${{ secrets.ANTHROPIC_API_TOKEN }}
BYTEPLUS_API_KEY: ${{ secrets.BYTEPLUS_API_KEY }}
CEREBRAS_API_KEY: ${{ secrets.CEREBRAS_API_KEY }}
DEEPINFRA_API_KEY: ${{ secrets.DEEPINFRA_API_KEY }}
DASHSCOPE_API_KEY: ${{ secrets.DASHSCOPE_API_KEY }}
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
KIMI_API_KEY: ${{ secrets.KIMI_API_KEY }}
MODELSTUDIO_API_KEY: ${{ secrets.MODELSTUDIO_API_KEY }}
MOONSHOT_API_KEY: ${{ secrets.MOONSHOT_API_KEY }}
MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }}
MINIMAX_API_KEY: ${{ secrets.MINIMAX_API_KEY }}
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
OPENCODE_ZEN_API_KEY: ${{ secrets.OPENCODE_ZEN_API_KEY }}
OPENCLAW_LIVE_BROWSER_CDP_URL: ${{ secrets.OPENCLAW_LIVE_BROWSER_CDP_URL }}
OPENCLAW_LIVE_SETUP_TOKEN: ${{ secrets.OPENCLAW_LIVE_SETUP_TOKEN }}
OPENCLAW_LIVE_SETUP_TOKEN_MODEL: ${{ secrets.OPENCLAW_LIVE_SETUP_TOKEN_MODEL }}
OPENCLAW_LIVE_SETUP_TOKEN_PROFILE: ${{ secrets.OPENCLAW_LIVE_SETUP_TOKEN_PROFILE }}
OPENCLAW_LIVE_SETUP_TOKEN_VALUE: ${{ secrets.OPENCLAW_LIVE_SETUP_TOKEN_VALUE }}
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
QWEN_API_KEY: ${{ secrets.QWEN_API_KEY }}
FAL_KEY: ${{ secrets.FAL_KEY }}
RUNWAY_API_KEY: ${{ secrets.RUNWAY_API_KEY }}
DEEPGRAM_API_KEY: ${{ secrets.DEEPGRAM_API_KEY }}
TOGETHER_API_KEY: ${{ secrets.TOGETHER_API_KEY }}
VYDRA_API_KEY: ${{ secrets.VYDRA_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 }}
BYTEPLUS_ACCESS_KEY_ID: ${{ secrets.BYTEPLUS_ACCESS_KEY_ID }}
BYTEPLUS_SECRET_ACCESS_KEY: ${{ secrets.BYTEPLUS_SECRET_ACCESS_KEY }}
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
OPENCLAW_CODEX_AUTH_JSON: ${{ secrets.OPENCLAW_CODEX_AUTH_JSON }}
OPENCLAW_CODEX_CONFIG_TOML: ${{ secrets.OPENCLAW_CODEX_CONFIG_TOML }}
OPENCLAW_CLAUDE_JSON: ${{ secrets.OPENCLAW_CLAUDE_JSON }}
OPENCLAW_CLAUDE_CREDENTIALS_JSON: ${{ secrets.OPENCLAW_CLAUDE_CREDENTIALS_JSON }}
OPENCLAW_CLAUDE_SETTINGS_JSON: ${{ secrets.OPENCLAW_CLAUDE_SETTINGS_JSON }}
OPENCLAW_CLAUDE_SETTINGS_LOCAL_JSON: ${{ secrets.OPENCLAW_CLAUDE_SETTINGS_LOCAL_JSON }}
OPENCLAW_GEMINI_SETTINGS_JSON: ${{ secrets.OPENCLAW_GEMINI_SETTINGS_JSON }}
FIREWORKS_API_KEY: ${{ secrets.FIREWORKS_API_KEY }}
package_telegram:
name: Telegram package acceptance
needs: resolve_package
if: needs.resolve_package.outputs.telegram_enabled == 'true'
uses: ./.github/workflows/npm-telegram-beta-e2e.yml
with:
package_spec: ${{ inputs.package_spec }}
package_artifact_name: ${{ needs.resolve_package.outputs.package_artifact_name }}
package_label: openclaw@${{ needs.resolve_package.outputs.package_version }}
harness_ref: ${{ inputs.source == 'ref' && inputs.package_ref || inputs.workflow_ref }}
provider_mode: ${{ needs.resolve_package.outputs.telegram_mode }}
scenario: ${{ inputs.telegram_scenarios }}
secrets:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENCLAW_QA_CONVEX_SITE_URL: ${{ secrets.OPENCLAW_QA_CONVEX_SITE_URL }}
OPENCLAW_QA_CONVEX_SECRET_CI: ${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }}
summary:
name: Verify package acceptance
needs: [resolve_package, docker_acceptance, package_telegram]
if: always()
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- name: Verify package acceptance results
env:
DOCKER_RESULT: ${{ needs.docker_acceptance.result }}
PACKAGE_TELEGRAM_RESULT: ${{ needs.package_telegram.result }}
RESOLVE_RESULT: ${{ needs.resolve_package.result }}
shell: bash
run: |
set -euo pipefail
failed=0
for item in \
"resolve_package=${RESOLVE_RESULT}" \
"docker_acceptance=${DOCKER_RESULT}" \
"package_telegram=${PACKAGE_TELEGRAM_RESULT}"
do
name="${item%%=*}"
result="${item#*=}"
if [[ "$result" != "success" && "$result" != "skipped" ]]; then
echo "::error::${name} ended with ${result}"
failed=1
fi
done
exit "$failed"

View File

@@ -13,6 +13,7 @@ on:
- "src/gateway/**"
- "src/media/**"
- ".github/workflows/parity-gate.yml"
workflow_dispatch:
permissions:
contents: read
@@ -23,7 +24,7 @@ concurrency:
jobs:
parity-gate:
name: Run the GPT-5.4 / Opus 4.6 parity gate against the qa-lab mock
name: Run the OpenAI / Opus 4.6 parity gate against the qa-lab mock
if: ${{ github.event.pull_request.draft != true }}
runs-on: blacksmith-32vcpu-ubuntu-2404
timeout-minutes: 30
@@ -41,6 +42,7 @@ jobs:
# followthrough gate that expects a fast post-approval read within a 30s
# agent.wait timeout.
QA_PARITY_CONCURRENCY: "1"
OPENCLAW_CI_OPENAI_MODEL: ${{ vars.OPENCLAW_CI_OPENAI_MODEL }}
OPENCLAW_QA_TRANSPORT_READY_TIMEOUT_MS: "180000"
OPENAI_API_KEY: ""
ANTHROPIC_API_KEY: ""
@@ -55,9 +57,11 @@ jobs:
steps:
- name: Checkout PR
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Install pnpm
uses: pnpm/action-setup@v4
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1
- name: Setup Node
uses: actions/setup-node@v6
@@ -74,13 +78,13 @@ jobs:
# The approval-turn sentinel still runs inside the full parity pack below.
# Keep the exact mock read-plan contract in deterministic unit tests instead
# of paying for a separate full-runtime preflight that has been flaky in CI.
- name: Run GPT-5.4 lane
- name: Run OpenAI candidate lane
run: |
pnpm openclaw qa suite \
--provider-mode mock-openai \
--parity-pack agentic \
--concurrency "${QA_PARITY_CONCURRENCY}" \
--model openai/gpt-5.4 \
--model "${OPENCLAW_CI_OPENAI_MODEL}" \
--alt-model openai/gpt-5.4-alt \
--output-dir .artifacts/qa-e2e/gpt54
@@ -100,7 +104,7 @@ jobs:
--repo-root . \
--candidate-summary .artifacts/qa-e2e/gpt54/qa-suite-summary.json \
--baseline-summary .artifacts/qa-e2e/opus46/qa-suite-summary.json \
--candidate-label openai/gpt-5.4 \
--candidate-label "${OPENCLAW_CI_OPENAI_MODEL}" \
--baseline-label anthropic/claude-opus-4-6 \
--output-dir .artifacts/qa-e2e/parity

View File

@@ -35,7 +35,7 @@ jobs:
permissions:
contents: read
outputs:
ref_sha: ${{ steps.ref.outputs.sha }}
ref_revision: ${{ steps.ref.outputs.sha }}
has_candidates: ${{ steps.plan.outputs.has_candidates }}
candidate_count: ${{ steps.plan.outputs.candidate_count }}
skipped_published_count: ${{ steps.plan.outputs.skipped_published_count }}
@@ -44,6 +44,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v6
with:
persist-credentials: false
ref: ${{ github.sha }}
fetch-depth: 0
@@ -150,7 +151,8 @@ jobs:
- name: Checkout
uses: actions/checkout@v6
with:
ref: ${{ needs.preview_plugins_clawhub.outputs.ref_sha }}
persist-credentials: false
ref: ${{ needs.preview_plugins_clawhub.outputs.ref_revision }}
fetch-depth: 1
- name: Setup Node environment
@@ -164,6 +166,7 @@ jobs:
- name: Checkout ClawHub CLI source
uses: actions/checkout@v6
with:
persist-credentials: false
repository: ${{ env.CLAWHUB_REPOSITORY }}
ref: ${{ env.CLAWHUB_REF }}
path: clawhub-source
@@ -187,7 +190,7 @@ jobs:
env:
CLAWHUB_REGISTRY: ${{ env.CLAWHUB_REGISTRY }}
SOURCE_REPO: ${{ github.repository }}
SOURCE_COMMIT: ${{ needs.preview_plugins_clawhub.outputs.ref_sha }}
SOURCE_COMMIT: ${{ needs.preview_plugins_clawhub.outputs.ref_revision }}
SOURCE_REF: ${{ github.ref }}
PACKAGE_TAG: ${{ matrix.plugin.publishTag }}
PACKAGE_DIR: ${{ matrix.plugin.packageDir }}
@@ -209,7 +212,8 @@ jobs:
- name: Checkout
uses: actions/checkout@v6
with:
ref: ${{ needs.preview_plugins_clawhub.outputs.ref_sha }}
persist-credentials: false
ref: ${{ needs.preview_plugins_clawhub.outputs.ref_revision }}
fetch-depth: 1
- name: Setup Node environment
@@ -223,6 +227,7 @@ jobs:
- name: Checkout ClawHub CLI source
uses: actions/checkout@v6
with:
persist-credentials: false
repository: ${{ env.CLAWHUB_REPOSITORY }}
ref: ${{ env.CLAWHUB_REF }}
path: clawhub-source
@@ -266,7 +271,7 @@ jobs:
env:
CLAWHUB_REGISTRY: ${{ env.CLAWHUB_REGISTRY }}
SOURCE_REPO: ${{ github.repository }}
SOURCE_COMMIT: ${{ needs.preview_plugins_clawhub.outputs.ref_sha }}
SOURCE_COMMIT: ${{ needs.preview_plugins_clawhub.outputs.ref_revision }}
SOURCE_REF: ${{ github.ref }}
PACKAGE_TAG: ${{ matrix.plugin.publishTag }}
PACKAGE_DIR: ${{ matrix.plugin.packageDir }}

View File

@@ -46,7 +46,7 @@ jobs:
permissions:
contents: read
outputs:
ref_sha: ${{ steps.ref.outputs.sha }}
ref_revision: ${{ steps.ref.outputs.sha }}
has_candidates: ${{ steps.plan.outputs.has_candidates }}
candidate_count: ${{ steps.plan.outputs.candidate_count }}
matrix: ${{ steps.plan.outputs.matrix }}
@@ -54,6 +54,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v6
with:
persist-credentials: false
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.ref || github.sha }}
fetch-depth: 0
@@ -151,7 +152,8 @@ jobs:
- name: Checkout
uses: actions/checkout@v6
with:
ref: ${{ needs.preview_plugins_npm.outputs.ref_sha }}
persist-credentials: false
ref: ${{ needs.preview_plugins_npm.outputs.ref_revision }}
fetch-depth: 1
- name: Setup Node environment
@@ -185,7 +187,8 @@ jobs:
- name: Checkout
uses: actions/checkout@v6
with:
ref: ${{ needs.preview_plugins_npm.outputs.ref_sha }}
persist-credentials: false
ref: ${{ needs.preview_plugins_npm.outputs.ref_revision }}
fetch-depth: 1
- name: Setup Node environment

View File

@@ -0,0 +1,556 @@
name: QA-Lab - All Lanes
on:
schedule:
- cron: "41 4 * * *"
workflow_dispatch:
inputs:
ref:
description: Ref, tag, or SHA to run
required: true
default: main
type: string
scenario:
description: Optional comma-separated Telegram scenario ids
required: false
type: string
discord_scenario:
description: Optional comma-separated Discord scenario ids
required: false
type: string
matrix_profile:
description: Matrix QA profile for the live Matrix lane
required: false
default: all
type: choice
options:
- fast
- all
- transport
- media
- e2ee-smoke
- e2ee-deep
- e2ee-cli
permissions:
contents: read
pull-requests: read
concurrency:
group: qa-lab-all-lanes-${{ github.event_name == 'workflow_dispatch' && inputs.ref || github.sha }}
cancel-in-progress: false
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
NODE_VERSION: "24.x"
PNPM_VERSION: "10.33.0"
OPENCLAW_CI_OPENAI_MODEL: ${{ vars.OPENCLAW_CI_OPENAI_MODEL }}
OPENCLAW_BUILD_PRIVATE_QA: "1"
OPENCLAW_ENABLE_PRIVATE_QA_CLI: "1"
jobs:
authorize_actor:
name: Authorize workflow actor
runs-on: blacksmith-8vcpu-ubuntu-2404
steps:
- name: Require maintainer-level repository access
uses: actions/github-script@v8
with:
script: |
if (context.eventName === "schedule") {
core.info("Scheduled default-branch QA run; actor permission check is only required for manual dispatch.");
return;
}
const allowed = new Set(["admin", "maintain", "write"]);
const { owner, repo } = context.repo;
const { data } = await github.rest.repos.getCollaboratorPermissionLevel({
owner,
repo,
username: context.actor,
});
const permission = data.permission;
core.info(`Actor ${context.actor} permission: ${permission}`);
if (!allowed.has(permission)) {
core.setFailed(
`Workflow requires write/maintain/admin access. Actor "${context.actor}" has "${permission}".`,
);
}
validate_selected_ref:
name: Validate selected ref
needs: authorize_actor
runs-on: blacksmith-8vcpu-ubuntu-2404
outputs:
selected_revision: ${{ steps.validate.outputs.selected_revision }}
trusted_reason: ${{ steps.validate.outputs.trusted_reason }}
steps:
- name: Checkout selected ref
uses: actions/checkout@v6
with:
persist-credentials: false
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.ref || github.sha }}
fetch-depth: 0
- name: Validate selected ref
id: validate
env:
GH_TOKEN: ${{ github.token }}
INPUT_REF: ${{ github.event_name == 'workflow_dispatch' && inputs.ref || github.sha }}
shell: bash
run: |
set -euo pipefail
selected_revision="$(git rev-parse HEAD)"
trusted_reason=""
git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main
if git merge-base --is-ancestor "$selected_revision" refs/remotes/origin/main; then
trusted_reason="main-ancestor"
elif git tag --points-at "$selected_revision" | grep -Eq '^v'; then
trusted_reason="release-tag"
elif [[ "$INPUT_REF" =~ ^release/[0-9]{4}\.[0-9]+\.[0-9]+$ ]]; then
git fetch --no-tags origin "+refs/heads/${INPUT_REF}:refs/remotes/origin/${INPUT_REF}"
release_branch_sha="$(git rev-parse "refs/remotes/origin/${INPUT_REF}")"
if [[ "$selected_revision" == "$release_branch_sha" ]]; then
trusted_reason="release-branch-head"
fi
else
pr_head_count="$(
gh api \
-H "Accept: application/vnd.github+json" \
"repos/${GITHUB_REPOSITORY}/commits/${selected_revision}/pulls" \
--jq '[.[] | select(.state == "open" and .head.repo.full_name == "'"${GITHUB_REPOSITORY}"'" and .head.sha == "'"${selected_revision}"'")] | length'
)"
if [[ "$pr_head_count" != "0" ]]; then
trusted_reason="open-pr-head"
fi
fi
if [[ -z "$trusted_reason" ]]; then
echo "Ref '${INPUT_REF}' resolved to $selected_revision, which is not trusted for this secret-bearing QA run." >&2
echo "Allowed refs must be on main, point to a release tag, match a release branch head, or match an open PR head in ${GITHUB_REPOSITORY}." >&2
exit 1
fi
echo "selected_revision=$selected_revision" >> "$GITHUB_OUTPUT"
echo "trusted_reason=$trusted_reason" >> "$GITHUB_OUTPUT"
{
echo "Validated ref: \`${INPUT_REF}\`"
echo "Resolved SHA: \`$selected_revision\`"
echo "Trust reason: \`$trusted_reason\`"
} >> "$GITHUB_STEP_SUMMARY"
run_mock_parity:
name: Run QA Lab parity gate
needs: [validate_selected_ref]
runs-on: blacksmith-32vcpu-ubuntu-2404
timeout-minutes: 30
env:
QA_PARITY_CONCURRENCY: "1"
OPENCLAW_QA_TRANSPORT_READY_TIMEOUT_MS: "180000"
OPENAI_API_KEY: ""
ANTHROPIC_API_KEY: ""
OPENCLAW_LIVE_OPENAI_KEY: ""
OPENCLAW_LIVE_ANTHROPIC_KEY: ""
OPENCLAW_LIVE_GEMINI_KEY: ""
OPENCLAW_LIVE_SETUP_TOKEN_VALUE: ""
steps:
- name: Checkout selected ref
uses: actions/checkout@v6
with:
persist-credentials: false
ref: ${{ needs.validate_selected_ref.outputs.selected_revision }}
fetch-depth: 1
- name: Setup Node environment
uses: ./.github/actions/setup-node-env
with:
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
install-bun: "true"
- name: Build private QA runtime
run: pnpm build
- name: Run OpenAI candidate lane
run: |
pnpm openclaw qa suite \
--provider-mode mock-openai \
--parity-pack agentic \
--concurrency "${QA_PARITY_CONCURRENCY}" \
--model "${OPENCLAW_CI_OPENAI_MODEL}" \
--alt-model openai/gpt-5.4-alt \
--output-dir .artifacts/qa-e2e/gpt54
- name: Run Opus 4.6 lane
run: |
pnpm openclaw qa suite \
--provider-mode mock-openai \
--parity-pack agentic \
--concurrency "${QA_PARITY_CONCURRENCY}" \
--model anthropic/claude-opus-4-6 \
--alt-model anthropic/claude-sonnet-4-6 \
--output-dir .artifacts/qa-e2e/opus46
- name: Generate parity report
run: |
pnpm openclaw qa parity-report \
--repo-root . \
--candidate-summary .artifacts/qa-e2e/gpt54/qa-suite-summary.json \
--baseline-summary .artifacts/qa-e2e/opus46/qa-suite-summary.json \
--candidate-label "${OPENCLAW_CI_OPENAI_MODEL}" \
--baseline-label anthropic/claude-opus-4-6 \
--output-dir .artifacts/qa-e2e/parity
- name: Upload parity artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: qa-parity-${{ github.run_id }}-${{ github.run_attempt }}
path: .artifacts/qa-e2e/
retention-days: 14
if-no-files-found: warn
run_live_matrix:
name: Run Matrix live QA lane
needs: [authorize_actor, validate_selected_ref]
if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.matrix_profile == 'all') }}
runs-on: blacksmith-32vcpu-ubuntu-2404
timeout-minutes: 60
environment: qa-live-shared
steps:
- name: Checkout selected ref
uses: actions/checkout@v6
with:
persist-credentials: false
ref: ${{ needs.validate_selected_ref.outputs.selected_revision }}
fetch-depth: 1
- name: Setup Node environment
uses: ./.github/actions/setup-node-env
with:
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
install-bun: "true"
- name: Validate required QA credential env
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
shell: bash
run: |
set -euo pipefail
if [[ -z "${OPENAI_API_KEY:-}" ]]; then
echo "Missing required OPENAI_API_KEY." >&2
exit 1
fi
- name: Build private QA runtime
run: pnpm build
- name: Run Matrix live lane
id: run_lane
shell: bash
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
INPUT_MATRIX_PROFILE: ${{ github.event_name == 'workflow_dispatch' && inputs.matrix_profile || 'fast' }}
OPENCLAW_QA_REDACT_PUBLIC_METADATA: "1"
OPENCLAW_QA_MATRIX_NO_REPLY_WINDOW_MS: "3000"
run: |
set -euo pipefail
output_dir=".artifacts/qa-e2e/matrix-live-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
echo "output_dir=${output_dir}" >> "$GITHUB_OUTPUT"
matrix_args=(
--repo-root . \
--output-dir "${output_dir}" \
--provider-mode live-frontier \
--model "${OPENCLAW_CI_OPENAI_MODEL}" \
--alt-model "${OPENCLAW_CI_OPENAI_MODEL}" \
--profile "${INPUT_MATRIX_PROFILE}" \
--fast
)
if pnpm openclaw qa matrix --help 2>/dev/null | grep -F -q -- "--fail-fast"; then
matrix_args+=(--fail-fast)
fi
pnpm openclaw qa matrix "${matrix_args[@]}"
- name: Upload Matrix QA artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: qa-live-matrix-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ steps.run_lane.outputs.output_dir }}
retention-days: 14
if-no-files-found: warn
run_live_matrix_sharded:
name: Run Matrix live QA lane (${{ matrix.profile }})
needs: [authorize_actor, validate_selected_ref]
if: ${{ github.event_name == 'workflow_dispatch' && inputs.matrix_profile == 'all' }}
runs-on: blacksmith-32vcpu-ubuntu-2404
timeout-minutes: 60
environment: qa-live-shared
strategy:
fail-fast: false
matrix:
profile:
- transport
- media
- e2ee-smoke
- e2ee-deep
- e2ee-cli
steps:
- name: Checkout selected ref
uses: actions/checkout@v6
with:
persist-credentials: false
ref: ${{ needs.validate_selected_ref.outputs.selected_revision }}
fetch-depth: 1
- name: Setup Node environment
uses: ./.github/actions/setup-node-env
with:
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
install-bun: "true"
- name: Validate required QA credential env
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
shell: bash
run: |
set -euo pipefail
if [[ -z "${OPENAI_API_KEY:-}" ]]; then
echo "Missing required OPENAI_API_KEY." >&2
exit 1
fi
- name: Build private QA runtime
run: pnpm build
- name: Run Matrix live lane shard
id: run_lane
shell: bash
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENCLAW_QA_REDACT_PUBLIC_METADATA: "1"
OPENCLAW_QA_MATRIX_NO_REPLY_WINDOW_MS: "3000"
run: |
set -euo pipefail
output_dir=".artifacts/qa-e2e/matrix-live-${{ matrix.profile }}-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
echo "output_dir=${output_dir}" >> "$GITHUB_OUTPUT"
matrix_args=(
--repo-root . \
--output-dir "${output_dir}" \
--provider-mode live-frontier \
--model "${OPENCLAW_CI_OPENAI_MODEL}" \
--alt-model "${OPENCLAW_CI_OPENAI_MODEL}" \
--profile "${{ matrix.profile }}" \
--fast
)
if pnpm openclaw qa matrix --help 2>/dev/null | grep -F -q -- "--fail-fast"; then
matrix_args+=(--fail-fast)
fi
pnpm openclaw qa matrix "${matrix_args[@]}"
- name: Upload Matrix QA shard artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: qa-live-matrix-${{ matrix.profile }}-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ steps.run_lane.outputs.output_dir }}
retention-days: 14
if-no-files-found: warn
run_live_telegram:
name: Run Telegram live QA lane with Convex leases
needs: [authorize_actor, validate_selected_ref]
runs-on: blacksmith-32vcpu-ubuntu-2404
timeout-minutes: 60
environment: qa-live-shared
steps:
- name: Checkout selected ref
uses: actions/checkout@v6
with:
persist-credentials: false
ref: ${{ needs.validate_selected_ref.outputs.selected_revision }}
fetch-depth: 1
- name: Setup Node environment
uses: ./.github/actions/setup-node-env
with:
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
install-bun: "true"
- name: Validate required QA credential env
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENCLAW_QA_CONVEX_SITE_URL: ${{ secrets.OPENCLAW_QA_CONVEX_SITE_URL }}
OPENCLAW_QA_CONVEX_SECRET_CI: ${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }}
shell: bash
run: |
set -euo pipefail
require_var() {
local key="$1"
if [[ -z "${!key:-}" ]]; then
echo "Missing required ${key}." >&2
exit 1
fi
}
require_var OPENAI_API_KEY
require_var OPENCLAW_QA_CONVEX_SITE_URL
require_var OPENCLAW_QA_CONVEX_SECRET_CI
- name: Build private QA runtime
run: pnpm build
- name: Run Telegram live lane
id: run_lane
shell: bash
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENCLAW_QA_CONVEX_SITE_URL: ${{ secrets.OPENCLAW_QA_CONVEX_SITE_URL }}
OPENCLAW_QA_CONVEX_SECRET_CI: ${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }}
OPENCLAW_QA_REDACT_PUBLIC_METADATA: "1"
OPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT: "1"
INPUT_SCENARIO: ${{ github.event_name == 'workflow_dispatch' && inputs.scenario || '' }}
run: |
set -euo pipefail
output_dir=".artifacts/qa-e2e/telegram-live-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
scenario_args=()
if [[ -n "${INPUT_SCENARIO// }" ]]; then
IFS=',' read -r -a raw_scenarios <<<"${INPUT_SCENARIO}"
for raw in "${raw_scenarios[@]}"; do
scenario="$(printf '%s' "${raw}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
if [[ -n "${scenario}" ]]; then
scenario_args+=(--scenario "${scenario}")
fi
done
fi
echo "output_dir=${output_dir}" >> "$GITHUB_OUTPUT"
pnpm openclaw qa telegram \
--repo-root . \
--output-dir "${output_dir}" \
--provider-mode live-frontier \
--model "${OPENCLAW_CI_OPENAI_MODEL}" \
--alt-model "${OPENCLAW_CI_OPENAI_MODEL}" \
--fast \
--credential-source convex \
--credential-role ci \
"${scenario_args[@]}"
- name: Upload Telegram QA artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: qa-live-telegram-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ steps.run_lane.outputs.output_dir }}
retention-days: 14
if-no-files-found: warn
run_live_discord:
name: Run Discord live QA lane with Convex leases
needs: [authorize_actor, validate_selected_ref]
runs-on: blacksmith-32vcpu-ubuntu-2404
timeout-minutes: 60
environment: qa-live-shared
steps:
- name: Checkout selected ref
uses: actions/checkout@v6
with:
persist-credentials: false
ref: ${{ needs.validate_selected_ref.outputs.selected_revision }}
fetch-depth: 1
- name: Setup Node environment
uses: ./.github/actions/setup-node-env
with:
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
install-bun: "true"
- name: Validate required QA credential env
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENCLAW_QA_CONVEX_SITE_URL: ${{ secrets.OPENCLAW_QA_CONVEX_SITE_URL }}
OPENCLAW_QA_CONVEX_SECRET_CI: ${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }}
shell: bash
run: |
set -euo pipefail
require_var() {
local key="$1"
if [[ -z "${!key:-}" ]]; then
echo "Missing required ${key}." >&2
exit 1
fi
}
require_var OPENAI_API_KEY
require_var OPENCLAW_QA_CONVEX_SITE_URL
require_var OPENCLAW_QA_CONVEX_SECRET_CI
- name: Build private QA runtime
run: pnpm build
- name: Run Discord live lane
id: run_lane
shell: bash
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENCLAW_QA_CONVEX_SITE_URL: ${{ secrets.OPENCLAW_QA_CONVEX_SITE_URL }}
OPENCLAW_QA_CONVEX_SECRET_CI: ${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }}
OPENCLAW_QA_REDACT_PUBLIC_METADATA: "1"
OPENCLAW_QA_DISCORD_CAPTURE_CONTENT: "1"
INPUT_SCENARIO: ${{ github.event_name == 'workflow_dispatch' && inputs.discord_scenario || '' }}
run: |
set -euo pipefail
output_dir=".artifacts/qa-e2e/discord-live-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
scenario_args=()
if [[ -n "${INPUT_SCENARIO// }" ]]; then
IFS=',' read -r -a raw_scenarios <<<"${INPUT_SCENARIO}"
for raw in "${raw_scenarios[@]}"; do
scenario="$(printf '%s' "${raw}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
if [[ -n "${scenario}" ]]; then
scenario_args+=(--scenario "${scenario}")
fi
done
fi
echo "output_dir=${output_dir}" >> "$GITHUB_OUTPUT"
pnpm openclaw qa discord \
--repo-root . \
--output-dir "${output_dir}" \
--provider-mode live-frontier \
--model openai/gpt-5.4 \
--alt-model openai/gpt-5.4 \
--fast \
--credential-source convex \
--credential-role ci \
"${scenario_args[@]}"
- name: Upload Discord QA artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: qa-live-discord-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ steps.run_lane.outputs.output_dir }}
retention-days: 14
if-no-files-found: warn

View File

@@ -29,7 +29,7 @@ jobs:
with:
app-id: "2971289"
private-key: ${{ secrets.GH_APP_PRIVATE_KEY_FALLBACK }}
- name: Mark stale issues and pull requests (primary)
- name: Mark stale unassigned issues and pull requests (primary)
id: stale-primary
continue-on-error: true
uses: actions/stale@v10
@@ -41,7 +41,7 @@ jobs:
days-before-pr-close: 3
stale-issue-label: stale
stale-pr-label: stale
exempt-issue-labels: enhancement,maintainer,pinned,security,no-stale
exempt-issue-labels: enhancement,maintainer,pinned,security,no-stale,bad-barnacle
exempt-pr-labels: maintainer,no-stale,bad-barnacle
operations-per-run: 2000
ascending: true
@@ -56,11 +56,59 @@ jobs:
close-issue-message: |
Closing due to inactivity.
If this is still an issue, please retry on the latest OpenClaw release and share updated details.
If you are absolutely sure it still happens on the latest release, open a new issue with fresh repro steps.
If you are absolutely sure it still happens on the latest release, open a new issue with fresh steps to reproduce.
close-issue-reason: not_planned
close-pr-message: |
Closing due to inactivity.
If you believe this PR should be revived, post in #pr-thunderdome-dangerzone on Discord to talk to a maintainer.
If you believe this PR should be revived, post in #clawtributors on Discord to talk to a maintainer.
That channel is the escape hatch for high-quality PRs that get auto-closed.
- name: Mark stale assigned issues (primary)
id: assigned-issue-stale-primary
continue-on-error: true
uses: actions/stale@v10
with:
repo-token: ${{ steps.app-token.outputs.token || steps.app-token-fallback.outputs.token }}
days-before-issue-stale: 30
days-before-issue-close: 10
days-before-pr-stale: -1
days-before-pr-close: -1
stale-issue-label: stale
exempt-issue-labels: enhancement,maintainer,pinned,security,no-stale,bad-barnacle
operations-per-run: 2000
ascending: true
include-only-assigned: true
remove-stale-when-updated: true
stale-issue-message: |
This assigned issue has been automatically marked as stale after 30 days of inactivity.
Please add updates or it will be closed.
close-issue-message: |
Closing due to inactivity.
If this is still an issue, please retry on the latest OpenClaw release and share updated details.
If you are absolutely sure it still happens on the latest release, open a new issue with fresh steps to reproduce.
close-issue-reason: not_planned
- name: Mark stale assigned pull requests (primary)
id: assigned-stale-primary
continue-on-error: true
uses: actions/stale@v10
with:
repo-token: ${{ steps.app-token.outputs.token || steps.app-token-fallback.outputs.token }}
days-before-issue-stale: -1
days-before-issue-close: -1
days-before-pr-stale: 27
days-before-pr-close: 3
stale-pr-label: stale
exempt-pr-labels: maintainer,no-stale,bad-barnacle
operations-per-run: 2000
ascending: true
include-only-assigned: true
ignore-pr-updates: true
remove-stale-when-updated: true
stale-pr-message: |
This assigned pull request has been automatically marked as stale after being open for 27 days.
Please add updates or it will be closed.
close-pr-message: |
Closing due to inactivity.
If you believe this PR should be revived, post in #clawtributors on Discord to talk to a maintainer.
That channel is the escape hatch for high-quality PRs that get auto-closed.
- name: Check stale state cache
id: stale-state
@@ -86,7 +134,7 @@ jobs:
core.warning(`Failed to check stale state cache: ${message}`);
core.setOutput("has_state", "false");
}
- name: Mark stale issues and pull requests (fallback)
- name: Mark stale unassigned issues and pull requests (fallback)
if: (steps.stale-primary.outcome == 'failure' || steps.stale-state.outputs.has_state == 'true') && steps.app-token-fallback.outputs.token != ''
uses: actions/stale@v10
with:
@@ -97,7 +145,7 @@ jobs:
days-before-pr-close: 3
stale-issue-label: stale
stale-pr-label: stale
exempt-issue-labels: enhancement,maintainer,pinned,security,no-stale
exempt-issue-labels: enhancement,maintainer,pinned,security,no-stale,bad-barnacle
exempt-pr-labels: maintainer,no-stale,bad-barnacle
operations-per-run: 2000
ascending: true
@@ -112,11 +160,57 @@ jobs:
close-issue-message: |
Closing due to inactivity.
If this is still an issue, please retry on the latest OpenClaw release and share updated details.
If you are absolutely sure it still happens on the latest release, open a new issue with fresh repro steps.
If you are absolutely sure it still happens on the latest release, open a new issue with fresh steps to reproduce.
close-issue-reason: not_planned
close-pr-message: |
Closing due to inactivity.
If you believe this PR should be revived, post in #pr-thunderdome-dangerzone on Discord to talk to a maintainer.
If you believe this PR should be revived, post in #clawtributors on Discord to talk to a maintainer.
That channel is the escape hatch for high-quality PRs that get auto-closed.
- name: Mark stale assigned issues (fallback)
if: (steps.assigned-issue-stale-primary.outcome == 'failure' || steps.stale-state.outputs.has_state == 'true') && steps.app-token-fallback.outputs.token != ''
uses: actions/stale@v10
with:
repo-token: ${{ steps.app-token-fallback.outputs.token }}
days-before-issue-stale: 30
days-before-issue-close: 10
days-before-pr-stale: -1
days-before-pr-close: -1
stale-issue-label: stale
exempt-issue-labels: enhancement,maintainer,pinned,security,no-stale,bad-barnacle
operations-per-run: 2000
ascending: true
include-only-assigned: true
remove-stale-when-updated: true
stale-issue-message: |
This assigned issue has been automatically marked as stale after 30 days of inactivity.
Please add updates or it will be closed.
close-issue-message: |
Closing due to inactivity.
If this is still an issue, please retry on the latest OpenClaw release and share updated details.
If you are absolutely sure it still happens on the latest release, open a new issue with fresh steps to reproduce.
close-issue-reason: not_planned
- name: Mark stale assigned pull requests (fallback)
if: (steps.assigned-stale-primary.outcome == 'failure' || steps.stale-state.outputs.has_state == 'true') && steps.app-token-fallback.outputs.token != ''
uses: actions/stale@v10
with:
repo-token: ${{ steps.app-token-fallback.outputs.token }}
days-before-issue-stale: -1
days-before-issue-close: -1
days-before-pr-stale: 27
days-before-pr-close: 3
stale-pr-label: stale
exempt-pr-labels: maintainer,no-stale,bad-barnacle
operations-per-run: 2000
ascending: true
include-only-assigned: true
ignore-pr-updates: true
remove-stale-when-updated: true
stale-pr-message: |
This assigned pull request has been automatically marked as stale after being open for 27 days.
Please add updates or it will be closed.
close-pr-message: |
Closing due to inactivity.
If you believe this PR should be revived, post in #clawtributors on Discord to talk to a maintainer.
That channel is the escape hatch for high-quality PRs that get auto-closed.
lock-closed-issues:

View File

@@ -0,0 +1,279 @@
name: Test Performance Agent
on:
workflow_run: # zizmor: ignore[dangerous-triggers] main-only test optimization after trusted CI; job gates repository, event, branch, actor, conclusion, current main SHA, and daily cadence before using write token
workflows:
- CI
types:
- completed
workflow_dispatch:
permissions:
actions: read
contents: write
concurrency:
group: test-performance-agent-main
cancel-in-progress: false
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
TEST_PERF_BEFORE: .artifacts/test-perf/baseline-before.json
TEST_PERF_AFTER: .artifacts/test-perf/after-agent.json
TEST_PERF_COMPARE: .artifacts/test-perf/agent-compare.json
jobs:
optimize-tests:
if: >
github.repository == 'openclaw/openclaw' &&
(github.event_name == 'workflow_dispatch' ||
(github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.event == 'push' &&
github.event.workflow_run.head_branch == 'main' &&
!endsWith(github.event.workflow_run.actor.login, '[bot]')))
runs-on: ubuntu-24.04
timeout-minutes: 240
steps:
- name: Checkout
uses: actions/checkout@v6
with:
ref: main
fetch-depth: 0
persist-credentials: false
submodules: false
- name: Gate trusted main activity and daily cadence
id: gate
env:
EVENT_NAME: ${{ github.event_name }}
GH_TOKEN: ${{ github.token }}
WORKFLOW_HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
run: |
set -euo pipefail
if [ "$EVENT_NAME" != "workflow_run" ]; then
echo "run_agent=true" >> "$GITHUB_OUTPUT"
echo "base_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
exit 0
fi
for attempt in 1 2 3 4 5; do
if git fetch --no-tags origin main; then
break
fi
if [ "$attempt" = "5" ]; then
echo "Failed to fetch main after retries." >&2
exit 1
fi
echo "Fetch attempt ${attempt} failed; retrying."
sleep $((attempt * 2))
done
remote_main="$(git rev-parse origin/main)"
if [ "$remote_main" != "$WORKFLOW_HEAD_SHA" ]; then
echo "CI run is superseded by ${remote_main}; skipping test performance agent for ${WORKFLOW_HEAD_SHA}."
echo "run_agent=false" >> "$GITHUB_OUTPUT"
exit 0
fi
day_start="$(date -u +%Y-%m-%dT00:00:00Z)"
runs_json="$RUNNER_TEMP/test-performance-agent-runs.json"
gh api --method GET "repos/${GITHUB_REPOSITORY}/actions/workflows/test-performance-agent.yml/runs" \
-f branch=main \
-f event=workflow_run \
-f per_page=50 > "$runs_json"
prior_runs="$(
jq -r \
--argjson current_run_id "$GITHUB_RUN_ID" \
--arg day_start "$day_start" \
'.workflow_runs[]
| select(.database_id != $current_run_id)
| select(.created_at >= $day_start)
| select(.status != "cancelled")
| select((.conclusion // "") != "skipped")
| [.database_id, .status, (.conclusion // ""), .created_at, .head_sha]
| @tsv' "$runs_json"
)"
if [ -n "$prior_runs" ]; then
echo "Test performance agent already ran or is running today; skipping."
printf '%s\n' "$prior_runs"
echo "run_agent=false" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "run_agent=true" >> "$GITHUB_OUTPUT"
echo "base_sha=${remote_main}" >> "$GITHUB_OUTPUT"
- name: Setup Node environment
if: steps.gate.outputs.run_agent == 'true'
uses: ./.github/actions/setup-node-env
with:
install-bun: "false"
- name: Ensure test performance agent key exists
if: steps.gate.outputs.run_agent == 'true'
env:
OPENAI_API_KEY: ${{ secrets.OPENCLAW_TEST_PERF_AGENT_OPENAI_API_KEY || secrets.OPENAI_API_KEY }}
run: |
set -euo pipefail
if [ -z "${OPENAI_API_KEY:-}" ]; then
echo "Missing OPENCLAW_TEST_PERF_AGENT_OPENAI_API_KEY or OPENAI_API_KEY secret." >&2
exit 1
fi
- name: Build baseline full-suite performance report
if: steps.gate.outputs.run_agent == 'true'
run: pnpm test:perf:groups --full-suite --allow-failures --output "$TEST_PERF_BEFORE" --limit 20 --top-files 40
- name: Run Codex test performance agent
if: steps.gate.outputs.run_agent == 'true'
uses: openai/codex-action@5c3f4ccdb2b8790f73d6b21751ac00e602aa0c02
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
model: ${{ vars.OPENCLAW_CI_OPENAI_MODEL_BARE }}
effort: high
sandbox: workspace-write
safety-strategy: drop-sudo
codex-args: '["--full-auto"]'
- name: Enforce focused test performance patch
if: steps.gate.outputs.run_agent == 'true'
id: patch
run: |
set -euo pipefail
untracked="$(git ls-files --others --exclude-standard)"
if [ -n "$untracked" ]; then
echo "Test performance agent created untracked files; forbidden:"
printf '%s\n' "$untracked"
exit 1
fi
added_deleted_or_renamed="$(git diff --name-status --diff-filter=ADR)"
if [ -n "$added_deleted_or_renamed" ]; then
echo "Test performance agent added, deleted, or renamed tracked files; forbidden:"
printf '%s\n' "$added_deleted_or_renamed"
exit 1
fi
bad_paths="$(
git diff --name-only | while IFS= read -r path; do
case "$path" in
apps/*|extensions/*|packages/*|scripts/*|src/*|Swabble/*|test/*|ui/*) ;;
*) printf '%s\n' "$path" ;;
esac
done
)"
if [ -n "$bad_paths" ]; then
echo "Test performance agent touched forbidden paths:"
printf '%s\n' "$bad_paths"
exit 1
fi
if git diff --quiet; then
echo "has_changes=false" >> "$GITHUB_OUTPUT"
else
echo "has_changes=true" >> "$GITHUB_OUTPUT"
fi
- name: Restore Node 24 path
if: steps.gate.outputs.run_agent == 'true' && steps.patch.outputs.has_changes == 'true'
run:
| # zizmor: ignore[github-env] NODE_BIN is set by the trusted local setup-node-env action in this same job
set -euo pipefail
export PATH="${NODE_BIN}:${PATH}"
echo "${NODE_BIN}" >> "$GITHUB_PATH"
node -v
corepack enable
pnpm -v
- name: Run full-suite performance report after agent changes
if: steps.gate.outputs.run_agent == 'true' && steps.patch.outputs.has_changes == 'true'
run: pnpm test:perf:groups --full-suite --output "$TEST_PERF_AFTER" --limit 20 --top-files 40
- name: Compare test performance reports
if: steps.gate.outputs.run_agent == 'true' && steps.patch.outputs.has_changes == 'true'
run: pnpm test:perf:groups:compare "$TEST_PERF_BEFORE" "$TEST_PERF_AFTER" --output "$TEST_PERF_COMPARE" --limit 20 --top-files 40
- name: Enforce coverage-preserving test count
if: steps.gate.outputs.run_agent == 'true' && steps.patch.outputs.has_changes == 'true'
run: |
set -euo pipefail
node <<'NODE'
const fs = require("node:fs");
const before = JSON.parse(fs.readFileSync(process.env.TEST_PERF_BEFORE, "utf8"));
const after = JSON.parse(fs.readFileSync(process.env.TEST_PERF_AFTER, "utf8"));
if (before.failed) {
console.log("Baseline had failing configs; skipping total test-count comparison against partial report.");
process.exit(0);
}
const beforeTests = before.totals?.testCount ?? 0;
const afterTests = after.totals?.testCount ?? 0;
if (afterTests < beforeTests) {
console.error(`Test count decreased from ${beforeTests} to ${afterTests}; refusing coverage-reducing patch.`);
process.exit(1);
}
console.log(`Test count preserved: ${beforeTests} -> ${afterTests}.`);
NODE
- name: Check changed lanes
if: steps.gate.outputs.run_agent == 'true' && steps.patch.outputs.has_changes == 'true'
run: pnpm check:changed
- name: Commit test performance updates
if: steps.gate.outputs.run_agent == 'true' && steps.patch.outputs.has_changes == 'true'
env:
GITHUB_TOKEN: ${{ github.token }}
TARGET_BRANCH: main
run: |
set -euo pipefail
if git diff --quiet; then
echo "No test performance changes."
exit 0
fi
git config user.name "openclaw-test-performance-agent[bot]"
git config user.email "openclaw-test-performance-agent[bot]@users.noreply.github.com"
git add apps extensions packages scripts src Swabble test ui
git commit --no-verify -m "test: optimize slow tests"
for attempt in 1 2 3 4 5; do
if ! git fetch --no-tags origin "${TARGET_BRANCH}"; then
echo "Fetch attempt ${attempt} failed; retrying."
sleep $((attempt * 2))
continue
fi
if git push "https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" HEAD:"${TARGET_BRANCH}"; then
exit 0
fi
remote_main="$(git rev-parse "origin/${TARGET_BRANCH}")"
if [ "$remote_main" != "$(git rev-parse HEAD^)" ]; then
echo "main advanced; rebasing test performance update onto ${remote_main}."
if ! git rebase "origin/${TARGET_BRANCH}"; then
echo "Test performance update no longer applies cleanly; skipping stale update."
git rebase --abort || true
exit 0
fi
pnpm check:changed
fi
echo "Test performance update attempt ${attempt} failed; retrying."
sleep $((attempt * 2))
done
echo "Failed to push test performance updates after retries." >&2
exit 1
- name: Upload test performance artifacts
if: steps.gate.outputs.run_agent == 'true' && always()
uses: actions/upload-artifact@v7
with:
name: test-performance-agent-${{ github.run_id }}
path: .artifacts/test-perf/
if-no-files-found: ignore
retention-days: 14

44
.gitignore vendored
View File

@@ -97,6 +97,40 @@ USER.md
# local tooling
.serena/
# Local project-agent skill installs. Only repo-owned skills are visible by
# default; promoting a new repo skill should require an intentional `git add -f`.
.agents/skills/*
!.agents/skills/blacksmith-testbox/
!.agents/skills/blacksmith-testbox/**
!.agents/skills/gitcrawl/
!.agents/skills/gitcrawl/**
!.agents/skills/openclaw-ghsa-maintainer/
!.agents/skills/openclaw-ghsa-maintainer/**
!.agents/skills/openclaw-parallels-smoke/
!.agents/skills/openclaw-parallels-smoke/**
!.agents/skills/openclaw-pr-maintainer/
!.agents/skills/openclaw-pr-maintainer/**
!.agents/skills/openclaw-qa-testing/
!.agents/skills/openclaw-qa-testing/**
!.agents/skills/openclaw-release-maintainer/
!.agents/skills/openclaw-release-maintainer/**
!.agents/skills/openclaw-secret-scanning-maintainer/
!.agents/skills/openclaw-secret-scanning-maintainer/**
!.agents/skills/openclaw-test-heap-leaks/
!.agents/skills/openclaw-test-heap-leaks/**
!.agents/skills/openclaw-test-performance/
!.agents/skills/openclaw-test-performance/**
!.agents/skills/openclaw-testing/
!.agents/skills/openclaw-testing/**
!.agents/skills/optimizetests/
!.agents/skills/optimizetests/**
!.agents/skills/parallels-discord-roundtrip/
!.agents/skills/parallels-discord-roundtrip/**
!.agents/skills/security-triage/
!.agents/skills/security-triage/**
!.agents/skills/tag-duplicate-prs-issues/
!.agents/skills/tag-duplicate-prs-issues/**
# Agent credentials and memory (NEVER COMMIT)
/memory/
.agent/*.json
@@ -128,15 +162,14 @@ dist/protocol.schema.json
# Synthing
**/.stfolder/
.dev-state
docs/superpowers/plans/2026-03-10-collapsed-side-nav.md
docs/superpowers/specs/2026-03-10-collapsed-side-nav-design.md
docs/superpowers
.superpowers/
.gitignore
test/config-form.analyze.telegram.test.ts
ui/src/ui/theme-variants.browser.test.ts
ui/src/ui/__screenshots__
ui/src/ui/views/__screenshots__
ui/.vitest-attachments
docs/superpowers
# Generated docs baseline artifacts (locally generated, only hashes tracked)
docs/.generated/*.json
@@ -147,8 +180,13 @@ changelog/fragments/
# Local scratch workspace
.tmp/
.vmux*
.artifacts/
test/fixtures/openclaw-vitest-unit-report.json
analysis/
.artifacts/qa-e2e/
extensions/qa-lab/web/dist/
# Generated bundled plugin runtime dependency manifests
extensions/**/.openclaw-runtime-deps.json
extensions/**/.openclaw-runtime-deps-stamp.json

View File

@@ -39,7 +39,12 @@
"details",
"summary",
"p",
"div",
"strong",
"span",
"iframe",
"h2",
"h3",
"picture",
"source",
"Tooltip",

View File

@@ -11,24 +11,53 @@
"eslint-plugin-unicorn/prefer-array-find": "error",
"eslint/no-array-constructor": "error",
"eslint/no-await-in-loop": "off",
"eslint/no-constructor-return": "error",
"eslint/no-div-regex": "error",
"eslint/no-extra-label": "error",
"eslint/no-empty-pattern": "error",
"eslint/no-lone-blocks": "error",
"eslint/no-multi-str": "error",
"eslint/no-new": "error",
"eslint/no-object-constructor": "error",
"eslint/no-proto": "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-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-warning-comments": "error",
"eslint/no-unmodified-loop-condition": "error",
"eslint/no-new-wrappers": "error",
"eslint/no-else-return": "error",
"eslint/no-case-declarations": "error",
"eslint/prefer-exponentiation-operator": "error",
"eslint/prefer-numeric-literals": "error",
"eslint/radix": "error",
"eslint/unicode-bom": "error",
"eslint/yoda": "error",
"import/no-absolute-path": "error",
"import/no-empty-named-blocks": "error",
"import/no-self-import": "error",
"node/no-exports-assign": "error",
"eslint-plugin-unicorn/prefer-set-size": "error",
"oxc/no-accumulating-spread": "error",
"oxc/no-async-endpoint-handlers": "error",
"oxc/no-map-spread": "error",
"promise/no-new-statics": "error",
"typescript/adjacent-overload-signatures": "error",
"typescript/ban-tslint-comment": "error",
"typescript/consistent-return": "error",
"typescript/no-empty-object-type": ["error", { "allowInterfaces": "with-single-extends" }],
"typescript/no-explicit-any": "error",
"typescript/no-extraneous-class": "error",
"typescript/no-meaningless-void-operator": "error",
"typescript/no-non-null-asserted-nullish-coalescing": "error",
"typescript/no-unnecessary-qualifier": "error",
"typescript/no-unnecessary-type-assertion": "error",
"typescript/no-unnecessary-type-arguments": "error",
"typescript/no-unnecessary-type-constraint": "error",
@@ -36,15 +65,52 @@
"typescript/no-unnecessary-type-parameters": "error",
"typescript/no-unsafe-type-assertion": "off",
"typescript/no-useless-default-assignment": "error",
"typescript/switch-exhaustiveness-check": [
"error",
{ "considerDefaultExhaustiveForUnions": true }
],
"typescript/prefer-return-this-type": "error",
"typescript/prefer-find": "error",
"typescript/prefer-function-type": "error",
"typescript/prefer-includes": "error",
"typescript/prefer-reduce-type-parameter": "error",
"typescript/prefer-ts-expect-error": "error",
"unicorn/consistent-date-clone": "error",
"unicorn/consistent-empty-array-spread": "error",
"unicorn/consistent-function-scoping": "off",
"unicorn/no-console-spaces": "error",
"unicorn/no-length-as-slice-end": "error",
"unicorn/no-instanceof-array": "error",
"unicorn/no-negation-in-equality-check": "error",
"unicorn/no-new-buffer": "error",
"unicorn/no-typeof-undefined": "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/prefer-date-now": "error",
"unicorn/prefer-dom-node-text-content": "error",
"unicorn/prefer-keyboard-event-key": "error",
"unicorn/prefer-array-some": "error",
"unicorn/prefer-math-min-max": "error",
"unicorn/prefer-node-protocol": "error",
"unicorn/prefer-number-properties": "error",
"unicorn/prefer-negative-index": "error",
"unicorn/prefer-optional-catch-binding": "error",
"unicorn/prefer-prototype-methods": "error",
"unicorn/prefer-regexp-test": "error",
"unicorn/prefer-set-size": "error",
"unicorn/require-post-message-target-origin": "error"
"unicorn/prefer-string-slice": "error",
"unicorn/require-array-join-separator": "error",
"unicorn/require-number-to-fixed-digits-argument": "error",
"unicorn/require-post-message-target-origin": "error",
"unicorn/throw-new-error": "error",
"vitest/no-import-node-test": "error",
"vitest/consistent-vitest-vi": "error",
"vitest/prefer-called-once": "error",
"vitest/prefer-called-times": "error",
"vitest/prefer-expect-type-of": "error"
},
"ignorePatterns": [
"assets/",

300
AGENTS.md
View File

@@ -1,201 +1,191 @@
# AGENTS.MD
Telegraph style. Root rules only. Read scoped `AGENTS.md` before touching a subtree.
Telegraph style. Root rules only. Read scoped `AGENTS.md` before subtree work.
## Start
- Repo: `https://github.com/openclaw/openclaw`
- Replies: repo-root file refs only, e.g. `extensions/telegram/src/index.ts:80`. No absolute paths, no `~/`.
- CODEOWNERS: maintenance/refactors/tests are ok. For larger behavior, product, security, or ownership-sensitive changes, get a listed owner request/review first.
- First pass: run docs list (`pnpm docs:list`; ignore if unavailable), then read only relevant docs/guides.
- Missing deps: run `pnpm install`, rerun once, then report first actionable error.
- Use "plugin/plugins" in docs/UI/changelog. `extensions/` remains internal workspace layout.
- Add channel/plugin/app/doc surface: update `.github/labeler.yml` and matching GitHub labels.
- New `AGENTS.md`: add sibling `CLAUDE.md` symlink to it.
- Replies: repo-root refs only: `extensions/telegram/src/index.ts:80`. No absolute paths, no `~/`.
- Run docs list first: `pnpm docs:list` if available; read relevant docs only.
- High-confidence answers only when fixing/triaging: verify source, tests, shipped/current behavior, and dependency contracts before deciding.
- Dependency-backed behavior: read upstream dependency docs/source/types first. Do not assume APIs, defaults, errors, timing, or runtime behavior.
- Live-verify when feasible. Check env/`~/.profile` for keys before assuming live tests are blocked; keep secret output redacted.
- Missing deps: `pnpm install`, retry once, then report first actionable error.
- CODEOWNERS: maint/refactor/tests ok. Larger behavior/product/security/ownership: owner ask/review.
- Wording: product/docs/UI/changelog say "plugin/plugins"; `extensions/` is internal.
- New channel/plugin/app/doc surface: update `.github/labeler.yml` + GH labels.
- New `AGENTS.md`: add sibling `CLAUDE.md` symlink.
## Repo Map
## Map
- Core TS: `src/`, `ui/`, `packages/`
- Bundled plugins: `extensions/`
- Plugin SDK/public contract: `src/plugin-sdk/*`
- Core channel internals: `src/channels/*`
- Plugin loader/registry/contracts: `src/plugins/*`
- Gateway protocol: `src/gateway/protocol/*`
- Docs: `docs/`
- Apps: `apps/`, `Swabble/`
- Installers served from `openclaw.ai`: sibling `../openclaw.ai`
Scoped guides:
- `extensions/AGENTS.md`: bundled plugin rules
- `src/plugin-sdk/AGENTS.md`: public SDK rules
- `src/channels/AGENTS.md`: channel core rules
- `src/plugins/AGENTS.md`: plugin loader/registry rules
- `src/gateway/AGENTS.md`, `src/gateway/protocol/AGENTS.md`: gateway/protocol rules
- `src/agents/AGENTS.md`: agent import/test perf rules
- `test/helpers/AGENTS.md`, `test/helpers/channels/AGENTS.md`: shared test helpers
- `docs/AGENTS.md`, `ui/AGENTS.md`, `scripts/AGENTS.md`: docs/UI/scripts
- Core TS: `src/`, `ui/`, `packages/`; plugins: `extensions/`; SDK: `src/plugin-sdk/*`; channels: `src/channels/*`; loader: `src/plugins/*`; protocol: `src/gateway/protocol/*`; docs/apps: `docs/`, `apps/`, `Swabble/`.
- Installers: sibling `../openclaw.ai`.
- Scoped guides exist in: `extensions/`, `src/{plugin-sdk,channels,plugins,gateway,gateway/protocol,agents}/`, `test/helpers*/`, `docs/`, `ui/`, `scripts/`.
## Architecture
- Core must stay extension-agnostic. No core special cases for bundled plugin/provider/channel ids when manifest/registry/capability contracts can express it.
- Extensions cross into core only via `openclaw/plugin-sdk/*`, manifest metadata, injected runtime helpers, and documented local barrels (`api.ts`, `runtime-api.ts`).
- Extension production code must not import core `src/**`, `src/plugin-sdk-internal/**`, another extension's `src/**`, or relative paths outside its package.
- Core code/tests must not deep-import plugin internals (`extensions/*/src/**`, `onboard.js`). Use plugin `api.ts` / public SDK facade / generic contract.
- Extension-owned behavior stays in the extension: legacy repair, detection, onboarding, auth/provider defaults, provider tools/settings.
- Legacy config repair: prefer doctor/fix paths over startup/load-time core migrations.
- If a core test asserts extension-specific behavior, move it to the owning extension or a generic contract test.
- Core stays extension-agnostic. No bundled ids in core when manifest/registry/capability contracts work.
- Extensions cross into core only via `openclaw/plugin-sdk/*`, manifest metadata, injected runtime helpers, documented barrels (`api.ts`, `runtime-api.ts`).
- Extension prod code: no core `src/**`, `src/plugin-sdk-internal/**`, other extension `src/**`, or relative outside package.
- Core/tests: no deep plugin internals (`extensions/*/src/**`, `onboard.js`). Use `api.ts`, SDK facade, generic contracts.
- Extension-owned behavior stays extension-owned: repair, detection, onboarding, auth/provider defaults, provider tools/settings.
- Owner boundary: fix owner-specific behavior in the owner module. Shared/core gets generic seams only; no owner ids, dependency strings, defaults, migrations, or recovery policy. If a bug names an extension or its dependency, start in that extension and add a generic core seam only when multiple owners need it.
- Legacy config repair: doctor/fix paths, not startup/load-time core migrations.
- Core test asserting extension-specific behavior: move to owner extension or generic contract test.
- New seams: backwards-compatible, documented, versioned. Third-party plugins exist.
- Channels: `src/channels/**` is implementation. Plugin authors get SDK seams, not channel internals.
- Providers: core owns generic inference loop; provider plugins own provider-specific auth/catalog/runtime hooks.
- Gateway protocol changes are contract changes: additive first; incompatible needs versioning/docs/client follow-through.
- Config contract: keep exported types, schema/help, generated metadata, baselines, docs aligned. Retired public keys stay retired; compatibility belongs in raw migration/doctor paths.
- Plugin architecture direction: manifest-first control plane; targeted runtime loaders; no hidden paths around declared contracts; broad mutable registries are transitional.
- Prompt-cache rule: deterministic ordering for maps/sets/registries/plugin lists/files/network results before model/tool payloads. Preserve old transcript bytes when possible.
- Channels: `src/channels/**` is implementation; plugin authors get SDK seams.
- Providers: core owns generic loop; provider plugins own auth/catalog/runtime hooks.
- Gateway protocol changes: additive first; incompatible needs versioning/docs/client follow-through.
- Config contract: exported types, schema/help, metadata, baselines, docs aligned. Retired public keys stay retired; compat in raw migration/doctor.
- Direction: manifest-first control plane; targeted runtime loaders; no hidden contract bypasses; broad mutable registries transitional.
- Prompt cache: deterministic ordering for maps/sets/registries/plugin lists/files/network results before model/tool payloads. Preserve old transcript bytes when possible.
## Commands
- Runtime: Node 22+. Keep Node and Bun paths working.
- Install: `pnpm install` (Bun supported; keep lockfiles/patches aligned if touched).
- Dev CLI: `pnpm openclaw ...` or `pnpm dev`.
- Build: `pnpm build`
- Smart local gate: `pnpm check:changed` (scoped typecheck/lint/guards + relevant tests)
- Explain smart gate: `pnpm changed:lanes --json`
- Pre-commit view: `pnpm check:changed --staged`
- Normal full prod sweep: `pnpm check` (prod typecheck/lint/guards, no tests)
- Full tests: `pnpm test`
- Changed tests only: `pnpm test:changed`
- Local serial loop: `pnpm test:serial`
- Extension tests: `pnpm test:extensions` or `pnpm test extensions` = all extension shards; `pnpm test extensions/<id>` = one extension lane. Heavy channels/OpenAI have dedicated shards.
- Shard timing artifact: `.artifacts/vitest-shard-timings.json`; auto-used for balanced shard ordering. Disable with `OPENCLAW_TEST_PROJECTS_TIMINGS=0`.
- Targeted tests: `pnpm test <path-or-filter> [vitest args...]`; do not call raw `vitest`.
- Coverage: `pnpm test:coverage`
- Format check/fix: `pnpm format:check` / `pnpm format`
- Typecheck:
- `pnpm tsgo`: fastest core prod graph
- `pnpm tsgo:prod`: core + extensions prod graphs; used by `pnpm check`
- `pnpm check:test-types` / `pnpm tsgo:test`: all test graphs
- `pnpm tsgo:all`: all prod + test project refs
- Debug slices exist; do not present as normal user flow.
- Profile: `pnpm tsgo:profile [core-test|extensions-test|--all]`
- Type policy: use `tsgo`; do not add `tsc --noEmit`, `typecheck`, or `check:types` lanes. `tsc` only for declaration/package-boundary emit gaps.
- Lint:
- `pnpm lint`: core/extensions/scripts shards
- `pnpm lint:core`, `pnpm lint:extensions`, `pnpm lint:scripts`
- `pnpm lint:apps`: Swift/app surface, separate from TS lint
- `pnpm lint:all`: legacy comparison lane
- Local heavy-check behavior: `OPENCLAW_LOCAL_CHECK=1` default; `OPENCLAW_LOCAL_CHECK_MODE=throttled|full`; `OPENCLAW_LOCAL_CHECK=0` for CI/shared runs.
- Local validation is local-first. Do not default to Blacksmith/Testbox for routine OpenClaw iteration; it burns warm caches and startup time. Use repo `pnpm` lanes first, then reach for remote CI/Testbox only for parity-only failures, secrets/services, or when explicitly requested.
- Runtime: Node 22+. Keep Node + Bun paths working.
- Install: `pnpm install` (keep Bun lock/patches aligned if touched).
- CLI: `pnpm openclaw ...` or `pnpm dev`; build: `pnpm build`.
- Smart gate: `pnpm check:changed`; explain `pnpm changed:lanes --json`; staged preview `pnpm check:changed --staged`.
- Sparse worktrees: `pnpm check:changed` is sparse-safe and may skip sparse-missing typecheck projects; do not expand sparse checkout just to satisfy changed-gate tsgo. Direct `pnpm tsgo*` remains strict; use a fuller worktree when you need direct typecheck proof.
- Prod sweep: `pnpm check`; tests: `pnpm test`, `pnpm test:changed`, `pnpm test:serial`, `pnpm test:coverage`.
- Extension tests: `pnpm test:extensions`, `pnpm test extensions`, `pnpm test extensions/<id>`.
- Targeted tests: `pnpm test <path-or-filter> [vitest args...]`; never raw `vitest`.
- Vitest flags only; no Jest flags like `--runInBand`. For serial runs use `pnpm test:serial` or `OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test ...`.
- Typecheck: `tsgo` lanes only (`pnpm tsgo*`, `pnpm check:test-types`); do not add `tsc --noEmit`, `typecheck`, `check:types`.
- Formatting: use `oxfmt`, not Prettier. Prefer `pnpm format:check` / `pnpm format`; for targeted files use `pnpm exec oxfmt --check --threads=1 <files...>` or `pnpm exec oxfmt --write --threads=1 <files...>`.
- Linting: use repo wrappers (`pnpm lint:*`, `scripts/run-oxlint.mjs`); do not invoke generic JS formatters/lints unless a repo script uses them.
- Heavy checks: `OPENCLAW_LOCAL_CHECK=1`, mode `OPENCLAW_LOCAL_CHECK_MODE=throttled|full`; CI/shared use `OPENCLAW_LOCAL_CHECK=0`.
- Blacksmith/Testbox: on maintainer machines with Blacksmith access, broad/shared validation defaults to Testbox. This includes `pnpm check`, `pnpm check:changed`, `pnpm test`, `pnpm test:changed`, Docker/E2E/live/package/build gates, and any command likely to fan out across many Vitest projects. Do not start those broad gates locally unless the user explicitly asks for local proof or sets `OPENCLAW_LOCAL_CHECK_MODE=throttled|full`.
- Local validation: targeted edit loops only, such as `pnpm test <specific-file>`, targeted formatter checks, and small lint/type probes. If a local command expands beyond targeted proof, stop it and move the broad gate to Testbox.
- Testbox use: run from repo root, pre-warm early with `blacksmith testbox warmup ci-check-testbox.yml --ref main --idle-timeout 90`, reuse the returned `tbx_...` id for all `run`/`download` commands, and stop boxes you created before handoff. Timeout bins: `90` minutes default, `240` multi-hour, `720` all-day, `1440` overnight; anything above `1440` needs explicit approval and cleanup.
- Testbox full-suite profile: `blacksmith testbox run --id <ID> "env NODE_OPTIONS=--max-old-space-size=4096 OPENCLAW_TEST_PROJECTS_PARALLEL=6 OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test"`. For installable package proof, prefer the GitHub `Package Acceptance` workflow over ad hoc Testbox commands.
## GitHub / CI
- Triage: list first, hydrate few. Use bounded `gh --json --jq`; avoid repeated full comment scans.
- Automatic PR/issue discovery: skip maintainer-owned items unless directly relevant. Do not comment, close, label, retitle, rebase, fix up, or land them without Peter asking.
- PR scan/triage: no unsolicited PR comments/reviews. Report in chat only unless explicitly asked, or a close/duplicate action needs a reason comment.
- Search/dedupe: prefer `gh search issues 'repo:openclaw/openclaw is:open <terms>' --json number,title,state,updatedAt --limit 20`.
- GitHub search boolean text is fussy. If `OR` queries return empty, split exact terms and search title/body/comments separately before concluding no hits.
- PR shortlist: `gh pr list ...`; then `gh pr view <n> --json number,title,body,closingIssuesReferences,files,statusCheckRollup,reviewDecision`.
- After landing PR: search duplicate open issues/PRs. Before closing: comment why + canonical link.
- GH comments with markdown backticks, `$`, or shell snippets: avoid inline double-quoted `--body`; use single quotes or `--body-file`.
- PR execution artifacts/screenshots: attach them to the PR, comment, or an external artifact store. Do not add `.github/pr-assets` or other PR-only assets to the repo.
- PR review answer must explicitly cover: what bug/behavior we are trying to fix; PR/issue URL(s) and affected endpoint/surface; whether this is the best possible fix, with high-certainty evidence from code, tests, CI, and shipped/current behavior.
- CI polling: exact SHA, needed fields only. Example: `gh api repos/<owner>/<repo>/actions/runs/<id> --jq '{status,conclusion,head_sha,updated_at,name,path}'`.
- Post-land wait: minimal. Exact landed SHA only. If superseded on `main`, same-branch `cancel-in-progress` cancellations are expected; stop once local touched-surface proof exists. Never wait for newer unrelated `main` unless asked.
- Wait matrix:
- never: `Auto response`, `Labeler`, `Docs Sync Publish Repo`, `Docs Agent`, `Test Performance Agent`, `Stale`.
- conditional: `CI` exact SHA only; `Docs` only docs task/no local docs proof; `Workflow Sanity` only workflow/composite/CI-policy edits; `Plugin NPM Release` only plugin package/release metadata.
- release/manual only: `Docker Release`, `OpenClaw NPM Release`, `macOS Release`, `OpenClaw Release Checks`, `Cross-OS Release Checks`, `NPM Telegram Beta E2E`.
- explicit/surface only: `QA-Lab - All Lanes`, `Scheduled Live And E2E`, `Install Smoke`, `CodeQL`, `Sandbox Common Smoke`, `Parity gate`, `Blacksmith Testbox`, `Control UI Locale Refresh`.
- `/landpr`: do not idle on `auto-response` or `check-docs`. Treat docs as local proof unless `check-docs` already failed with actionable relevant error.
- Poll 30-60s. Fetch jobs/logs/artifacts only after failure/completion or concrete need.
## Gates
- Pre-commit hook: staged format/lint, then `pnpm check:changed --staged`; docs/markdown-only skips changed-scope check; `FAST_COMMIT=1` skips changed-scope check only.
- Pre-commit hook: staged formatting only. Validation explicit.
- Changed lanes:
- core prod => core prod typecheck + core tests
- core tests => core test typecheck/tests only
- extension prod => extension prod typecheck + extension tests
- extension tests => extension test typecheck/tests only
- public SDK/plugin contract => extension prod/test validation too
- unknown root/config => all lanes
- Local loop: prefer `pnpm check:changed`; use `pnpm test:changed` for tests only; use `pnpm check` for full prod TS/lint sweep without tests.
- Landing on `main`: verify touched surface near landing; default bar is `pnpm check` + `pnpm test` when feasible.
- Hard build gate: run/pass `pnpm build` before push if build output, packaging, lazy/module boundaries, or published surfaces can change.
- Do not land related failing format/lint/type/build/tests. If failures are unrelated on latest `origin/main`, say so and give scoped proof.
- CI architecture gate: `check-additional`; local equivalent `pnpm check:architecture`.
- Config docs drift: `pnpm config:docs:gen/check`
- Plugin SDK API drift: `pnpm plugin-sdk:api:gen/check`
- Generated docs baselines: tracked `docs/.generated/*.sha256`; full JSON ignored.
- core prod: core prod typecheck + core tests
- core tests: core test typecheck/tests
- extension prod: extension prod typecheck + extension tests
- extension tests: extension test typecheck/tests
- public SDK/plugin contract: extension prod/test too
- unknown root/config: all lanes
- Before handoff/push for code/test/runtime/config changes: run `pnpm check:changed` in Testbox by default on maintainer machines. Tests-only: run `pnpm test:changed` in Testbox by default. Full prod sweep: run `pnpm check` in Testbox. Use local only for narrow targeted proof or when explicitly requested.
- If `pnpm test:changed` or `pnpm check:changed` selects broad/shared lanes, it belongs in Testbox; do not let it continue locally after it fans out.
- Docs/changelog-only and CI/workflow metadata-only changes are not changed-gate work by default. Use `git diff --check` plus the relevant formatter/docs/workflow sanity check; escalate to `pnpm check:changed` only when scripts, test config, generated docs/API, package metadata, or runtime/build behavior changed.
- Rebase sanity: after a green `pnpm check:changed`, a clean rebase onto current
`origin/main` does not require rerunning the full changed gate when the rebase
has no conflicts and the branch diff is materially unchanged. Do a quick
`git status`, `git diff --check`, and diff/stat sanity check; rerun targeted or
full checks only if conflict resolution, upstream overlap, generated drift,
dependency/config changes, or touched-file content changes make the prior
result stale.
- Landing on `main`: verify touched surface near landing. Default feasible bar: `pnpm check` + `pnpm test`.
- Hard build gate: `pnpm build` before push if build output, packaging, lazy/module boundaries, or published surfaces can change.
- Do not land related failing format/lint/type/build/tests. If unrelated on latest `origin/main`, say so with scoped proof.
- Generated/API drift: `pnpm check:architecture`, `pnpm config:docs:gen/check`, `pnpm plugin-sdk:api:gen/check`. Track `docs/.generated/*.sha256`; full JSON ignored.
## Code Style
## Code
- TypeScript ESM. Strict types. Avoid `any`; prefer real types/`unknown`/narrow adapters.
- No `@ts-nocheck`. No lint suppressions unless intentional and explained.
- TS ESM, strict. Avoid `any`; prefer real types, `unknown`, narrow adapters.
- No `@ts-nocheck`. Lint suppressions only intentional + explained.
- External boundaries: prefer `zod` or existing schema helpers.
- Runtime branching: prefer discriminated unions / closed codes over freeform strings.
- Avoid magic sentinels like `?? 0`, empty object/string when semantics change.
- Dynamic import: do not mix static and dynamic import for same module in prod path. Use dedicated `*.runtime.ts` lazy boundary. After lazy-boundary edits, run `pnpm build` and check `[INEFFECTIVE_DYNAMIC_IMPORT]`.
- Cycles: keep `pnpm check:import-cycles` and architecture/madge cycle checks green.
- Classes: no prototype mixins/mutations. Use explicit inheritance/composition. Tests prefer per-instance stubs.
- Comments: brief only for non-obvious logic.
- File size: split around ~700 LOC when it improves clarity/testability.
- Product naming: **OpenClaw** product/docs; `openclaw` CLI/package/path/config.
- Written English: American spelling.
- Runtime branching: discriminated unions/closed codes over freeform strings.
- Avoid semantic sentinels: `?? 0`, empty object/string, etc.
- Dynamic import: no static+dynamic import for same prod module. Use `*.runtime.ts` lazy boundary. After edits: `pnpm build`; check `[INEFFECTIVE_DYNAMIC_IMPORT]`.
- Cycles: keep `pnpm check:import-cycles` + architecture/madge green.
- Classes: no prototype mixins/mutations. Prefer inheritance/composition. Tests prefer per-instance stubs.
- Comments: brief, only non-obvious logic.
- Split files around ~700 LOC when clarity/testability improves.
- Naming: **OpenClaw** product/docs; `openclaw` CLI/package/path/config.
- English: American spelling.
## Tests
- Vitest. Tests colocated `*.test.ts`; e2e `*.e2e.test.ts`.
- Example models in tests: `sonnet-4.6`, `gpt-5.4`.
- Clean up timers/env/globals/mocks/sockets/temp dirs/module state; `--isolate=false` must stay safe.
- Hot tests: avoid per-test `vi.resetModules()` + fresh heavy imports; prefer static or `beforeAll` imports and reset state directly.
- Measure first: `pnpm test:perf:imports <file>` for import drag; `pnpm test:perf:hotspots --limit N` for suite targets.
- Keep tests at seam depth: unit-test pure helpers/contracts; one integration smoke per boundary, not per branch.
- Mock expensive runtime seams directly: scanners, manifests, package registries, filesystem crawls, provider SDKs, network/process launch.
- Prefer injected deps over module mocks; if mocking modules, mock narrow local `*.runtime.ts` seams, not broad barrels.
- Share fixtures/builders; do not recreate temp dirs, package manifests, or plugin workspaces in every case unless state isolation needs it.
- Delete duplicate assertions when another test owns the boundary; assert only the behavior that can regress here.
- Avoid broad `importOriginal()` / broad `openclaw/plugin-sdk/*` partial mocks in hot tests. Add narrow local `*.runtime.ts` seam and mock it.
- Use existing deps/callback/runtime injection seams before module mocks.
- Import-dominated test time is a boundary smell; shrink import surface before adding cases.
- Replacing slow integration coverage: extract production composition into a named helper and test that helper.
- Do not modify baseline/inventory/ignore/snapshot/expected-failure files to silence checks without explicit approval.
- Do not set test workers above 16. For memory pressure: `OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test`.
- Live: `OPENCLAW_LIVE_TEST=1 pnpm test:live`; full logs `OPENCLAW_LIVE_TEST_QUIET=0`.
- Full testing guide: `docs/help/testing.md`.
- Vitest. Colocated `*.test.ts`; e2e `*.e2e.test.ts`; example models `sonnet-4.6`, `gpt-5.4`.
- Avoid brittle tests that grep workflow/docs strings for operator policy. Prefer executable behavior, parsed config/schema checks, or live run proof; put release/CI policy reminders in AGENTS/docs instead.
- Clean timers/env/globals/mocks/sockets/temp dirs/module state; `--isolate=false` safe.
- Hot tests: avoid per-test `vi.resetModules()` + heavy imports. Measure with `pnpm test:perf:imports <file>` / `pnpm test:perf:hotspots --limit N`.
- Seam depth: pure helper/contract unit tests; one integration smoke per boundary.
- Mock expensive seams directly: scanners, manifests, registries, fs crawls, provider SDKs, network/process launch.
- Prefer injection; if module mocking, mock narrow local `*.runtime.ts`, not broad barrels or `openclaw/plugin-sdk/*`.
- Share fixtures/builders; delete duplicate assertions; assert behavior that can regress here.
- Do not edit baseline/inventory/ignore/snapshot/expected-failure files to silence checks without explicit approval.
- Do not run multiple independent `pnpm test`/Vitest commands concurrently in the same worktree. They can race on `node_modules/.experimental-vitest-cache` and fail with `ENOTEMPTY`. Use one grouped `pnpm test ...` invocation, run targeted lanes sequentially, or set distinct `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH` values when true parallel Vitest processes are needed.
- Test workers max 16. Memory pressure: `OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test`.
- Live: `OPENCLAW_LIVE_TEST=1 pnpm test:live`; verbose `OPENCLAW_LIVE_TEST_QUIET=0`.
- Guide: `docs/help/testing.md`.
## Docs / Changelog
- Update docs when behavior/API changes. Use docs list/read_when hints.
- Docs links: see `docs/AGENTS.md`.
- Changelog: user-facing only. Pure test/internal changes usually no entry.
- Changelog placement: append to active version `### Changes`/`### Fixes`; at most one contributor mention, prefer `Thanks @user`.
- Docs change with behavior/API. Use docs list/read_when hints; docs links per `docs/AGENTS.md`.
- Changelog user-facing only; pure test/internal usually no entry.
- Changelog placement: active version `### Changes`/`### Fixes`; every added entry must include at least one `Thanks @author` attribution, using credited GitHub username(s). Never add `Thanks @codex`, `Thanks @openclaw`, or `Thanks @steipete`.
- Changelog bullets are always single-line. No wrapping/continuation across multiple lines. Long entries stay on one long line so dedupe, PR-ref, and credit-audit tooling work and so the visual style stays uniform.
## Git
- Use `scripts/committer "<msg>" <file...>`; stage only intended files.
- Commits: conventional-ish, concise/action-oriented. Group related changes.
- No manual stash/autostash unless explicitly requested. No branch/worktree changes unless requested.
- No merge commits on `main`; rebase on latest `origin/main` before push.
- User says "commit": commit your changes only. "commit all": commit everything in grouped chunks. "push": may `git pull --rebase` first.
- Do not delete/rename unexpected files; ask if it blocks. Otherwise ignore unrelated WIP.
- If bulk PR close/reopen affects >5 PRs, ask with exact count/scope.
- PR/issue workflows: use `$openclaw-pr-maintainer`.
- `/landpr`: use `~/.codex/prompts/landpr.md`.
- Commit via `scripts/committer "<msg>" <file...>`; stage intended files only. It formats staged files; still run gates.
- Commits: conventional-ish, concise, grouped.
- No manual stash/autostash unless explicit. No branch/worktree changes unless requested.
- `main`: no merge commits; rebase on latest `origin/main` before push. Do not
keep chasing `main` with repeated full gates after one green run plus a clean
rebase sanity pass.
- User says `commit`: your changes only. `commit all`: all changes in grouped chunks. `push`: may `git pull --rebase` first.
- Do not delete/rename unexpected files; ask if blocking, else ignore.
- Bulk PR close/reopen >5: ask with count/scope.
- PR/issue workflows: `$openclaw-pr-maintainer`. `/landpr`: `~/.codex/prompts/landpr.md`.
## Security / Release
- Never commit real phone numbers, videos, credentials, live config.
- Secrets: channel/provider credentials under `~/.openclaw/credentials/`; model auth profiles under `~/.openclaw/agents/<agentId>/agent/auth-profiles.json`.
- Secrets: channel/provider creds in `~/.openclaw/credentials/`; model auth profiles in `~/.openclaw/agents/<agentId>/agent/auth-profiles.json`.
- Env keys: check `~/.profile`.
- Dependency patches/overrides/vendor changes require explicit approval. `pnpm.patchedDependencies` must use exact versions.
- Carbon pins owner-only: do not change `@buape/carbon` versions unless Shadow (`@thewilloftheshadow`, verified by `gh`) asks.
- Releases/publish/version bumps require explicit approval.
- Release docs: `docs/reference/RELEASING.md`; use `$openclaw-release-maintainer`.
- GHSA/advisories: use `$openclaw-ghsa-maintainer`.
- Beta tag/version must match, e.g. `vYYYY.M.D-beta.N` => npm `YYYY.M.D-beta.N --tag beta`.
- Dependency patches/overrides/vendor changes need explicit approval. `pnpm.patchedDependencies` exact versions only.
- Carbon pins owner-only: do not change `@buape/carbon` unless Shadow (`@thewilloftheshadow`, verified by `gh`) asks.
- Releases/publish/version bumps need explicit approval. Release docs: `docs/reference/RELEASING.md`; use `$openclaw-release-maintainer`.
- GHSA/advisories: `$openclaw-ghsa-maintainer`.
- Beta tag/version match: `vYYYY.M.D-beta.N` -> npm `YYYY.M.D-beta.N --tag beta`.
## Apps / Platform
- Before simulator/emulator testing, check connected real iOS/Android devices first.
- Before simulator/emulator testing, check real iOS/Android devices.
- "restart iOS/Android apps" = rebuild/reinstall/relaunch, not kill/launch.
- SwiftUI: prefer Observation (`@Observable`, `@Bindable`) over new `ObservableObject`.
- mac gateway: use app or `openclaw gateway restart/status --deep`; avoid ad-hoc tmux gateway sessions. Rebuild mac app locally, not over SSH.
- mac logs: `./scripts/clawlog.sh`.
- Version bump touches: `package.json`, `apps/android/app/build.gradle.kts`, `apps/ios/version.json` then `pnpm ios:version:sync`, `apps/macos/.../Info.plist`, `docs/install/updating.md`. Appcast only for Sparkle release.
- iOS Team ID: `security find-identity -p codesigning -v`; fallback `defaults read com.apple.dt.Xcode IDEProvisioningTeamIdentifiers`.
- Mobile LAN pairing: plaintext `ws://` is loopback-only by default. Trusted private-network `ws://` needs `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1`; Tailscale/public use `wss://` or a tunnel.
- SwiftUI: Observation (`@Observable`, `@Bindable`) over new `ObservableObject`.
- Mac gateway: use app or `openclaw gateway restart/status --deep`; no ad-hoc tmux gateway. Logs: `./scripts/clawlog.sh`.
- Version bump touches: `package.json`, `apps/android/app/build.gradle.kts`, `apps/ios/version.json` + `pnpm ios:version:sync`, macOS `Info.plist`, `docs/install/updating.md`. Appcast only for Sparkle release.
- Mobile LAN pairing: plaintext `ws://` loopback-only. Private-network `ws://` needs `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1`; Tailscale/public use `wss://` or tunnel.
- A2UI hash `src/canvas-host/a2ui/.bundle.hash`: generated; ignore unless running `pnpm canvas:a2ui:bundle`; commit separately.
## External Ops
- Remote install docs: `docs/install/exe-dev.md`, `docs/install/fly.md`, `docs/install/hetzner.md`.
- Parallels smoke: `$openclaw-parallels-smoke`; Discord roundtrip: `parallels-discord-roundtrip`.
## Misc Footguns
## Ops / Footguns
- Remote install docs: `docs/install/{exe-dev,fly,hetzner}.md`. Parallels smoke: `$openclaw-parallels-smoke`; Discord roundtrip: `parallels-discord-roundtrip`.
- Rebrand/migration/config warnings: run `openclaw doctor`.
- Never edit `node_modules`.
- Local-only `.agents` ignores: use `.git/info/exclude`, not repo `.gitignore`.
- CLI progress: use `src/cli/progress.ts`; status tables: `src/terminal/table.ts`.
- Local-only `.agents` ignores: `.git/info/exclude`, not repo `.gitignore`.
- CLI progress: `src/cli/progress.ts`; status tables: `src/terminal/table.ts`.
- Connection/provider additions: update all UI surfaces + docs + status/config forms.
- Provider-facing tool schemas: prefer flat string enum helpers over `Type.Union([Type.Literal(...)])`; some providers reject generated `anyOf`. Do not treat this as a repo-wide protocol/schema ban.
- External messaging surfaces: no token-delta channel messages. Follow `docs/concepts/streaming.md`; preview/block streaming uses message edits/chunks and must preserve final/fallback delivery.
- Provider tool schemas: prefer flat string enum helpers over `Type.Union([Type.Literal(...)])`; some providers reject `anyOf`. Not a repo-wide protocol/schema ban.
- External messaging: no token-delta channel messages. Follow `docs/concepts/streaming.md`; preview/block streaming uses edits/chunks and preserves final/fallback delivery.

File diff suppressed because it is too large Load Diff

View File

@@ -77,7 +77,7 @@ Welcome to the lobster tank! 🦞
- **Tengji (George) Zhang** - Chinese model APIs, cloud, pi
- GitHub: [@odysseus0](https://github.com/odysseus0) · X: [@odysseus0z](https://x.com/odysseus0z)
- **Sliverp** - Chinese Channel: QQ, WeChat, Wecom, Dingtalk, Feishu
- **Sliverp** - Chinese Channel: QQ, WeChat, Wecom, Yuanbao, Dingtalk, Feishu
- GitHub: [@sliverp](https://github.com/sliverp) · X: [@sliver01234](https://x.com/sliver01234)
- **Mason Huang** - Stability, Security, Speed

View File

@@ -9,29 +9,26 @@
# bundled plugin workspace tree, so the main build layer is not invalidated by
# unrelated plugin source changes.
#
# Two runtime variants:
# Default (bookworm): docker build .
# Slim (bookworm-slim): docker build --build-arg OPENCLAW_VARIANT=slim .
# Build stages use full bookworm; the runtime image is always bookworm-slim.
ARG OPENCLAW_EXTENSIONS=""
ARG OPENCLAW_VARIANT=default
ARG OPENCLAW_BUNDLED_PLUGIN_DIR=extensions
ARG OPENCLAW_DOCKER_APT_UPGRADE=1
ARG OPENCLAW_NODE_BOOKWORM_IMAGE="node:24-bookworm@sha256:3a09aa6354567619221ef6c45a5051b671f953f0a1924d1f819ffb236e520e6b"
ARG OPENCLAW_NODE_BOOKWORM_DIGEST="sha256:3a09aa6354567619221ef6c45a5051b671f953f0a1924d1f819ffb236e520e6b"
ARG OPENCLAW_NODE_BOOKWORM_SLIM_IMAGE="node:24-bookworm-slim@sha256:e8e2e91b1378f83c5b2dd15f0247f34110e2fe895f6ca7719dbb780f929368eb"
ARG OPENCLAW_NODE_BOOKWORM_SLIM_DIGEST="sha256:e8e2e91b1378f83c5b2dd15f0247f34110e2fe895f6ca7719dbb780f929368eb"
# Base images are pinned to SHA256 digests for reproducible builds.
# Trade-off: digests must be updated manually when upstream tags move.
# To update, run: docker buildx imagetools inspect node:24-bookworm (or podman)
# and replace the digest below with the current multi-arch manifest list entry.
# 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
# current multi-arch manifest list entries.
FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS ext-deps
ARG OPENCLAW_EXTENSIONS
ARG OPENCLAW_BUNDLED_PLUGIN_DIR
COPY ${OPENCLAW_BUNDLED_PLUGIN_DIR} /tmp/${OPENCLAW_BUNDLED_PLUGIN_DIR}
# Copy package.json for opted-in extensions so pnpm resolves their deps.
RUN mkdir -p /out && \
RUN --mount=type=bind,source=${OPENCLAW_BUNDLED_PLUGIN_DIR},target=/tmp/${OPENCLAW_BUNDLED_PLUGIN_DIR},readonly \
mkdir -p /out && \
for ext in $OPENCLAW_EXTENSIONS; do \
if [ -f "/tmp/${OPENCLAW_BUNDLED_PLUGIN_DIR}/$ext/package.json" ]; then \
mkdir -p "/out/$ext" && \
@@ -75,10 +72,20 @@ RUN --mount=type=cache,id=openclaw-pnpm-store,target=/root/.local/share/pnpm/sto
NODE_OPTIONS=--max-old-space-size=2048 pnpm install --frozen-lockfile
# pnpm v10+ may append peer-resolution hashes to virtual-store folder names; do not hardcode `.pnpm/...`
# paths. Fail fast here if the Matrix native binding did not materialize after install.
RUN echo "==> Verifying critical native addons..." && \
# paths. Matrix's native downloader can hit transient release CDN errors while
# still exiting successfully, so retry the package downloader before failing.
RUN set -eux; \
echo "==> Verifying critical native addons..."; \
for attempt in 1 2 3 4 5; do \
if find /app/node_modules -name "matrix-sdk-crypto*.node" 2>/dev/null | grep -q .; then \
exit 0; \
fi; \
echo "matrix-sdk-crypto native addon missing; retrying download (${attempt}/5)"; \
node /app/node_modules/@matrix-org/matrix-sdk-crypto-nodejs/download-lib.js || true; \
sleep $((attempt * 2)); \
done; \
find /app/node_modules -name "matrix-sdk-crypto*.node" 2>/dev/null | grep -q . || \
(echo "ERROR: matrix-sdk-crypto native addon missing (pnpm install may have silently failed on this arch)" >&2 && exit 1)
(echo "ERROR: matrix-sdk-crypto native addon missing after retries" >&2 && exit 1)
COPY . .
@@ -125,22 +132,15 @@ RUN printf 'packages:\n - .\n - ui\n' > /tmp/pnpm-workspace.runtime.yaml && \
node scripts/postinstall-bundled-plugins.mjs && \
find dist -type f \( -name '*.d.ts' -o -name '*.d.mts' -o -name '*.d.cts' -o -name '*.map' \) -delete
# ── Runtime base images ─────────────────────────────────────────
FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS base-default
ARG OPENCLAW_NODE_BOOKWORM_DIGEST
LABEL org.opencontainers.image.base.name="docker.io/library/node:24-bookworm" \
org.opencontainers.image.base.digest="${OPENCLAW_NODE_BOOKWORM_DIGEST}"
FROM ${OPENCLAW_NODE_BOOKWORM_SLIM_IMAGE} AS base-slim
# ── Runtime base image ─────────────────────────────────────────
FROM ${OPENCLAW_NODE_BOOKWORM_SLIM_IMAGE} AS base-runtime
ARG OPENCLAW_NODE_BOOKWORM_SLIM_DIGEST
LABEL org.opencontainers.image.base.name="docker.io/library/node:24-bookworm-slim" \
org.opencontainers.image.base.digest="${OPENCLAW_NODE_BOOKWORM_SLIM_DIGEST}"
# ── Stage 3: Runtime ────────────────────────────────────────────
FROM base-${OPENCLAW_VARIANT}
ARG OPENCLAW_VARIANT
FROM base-runtime
ARG OPENCLAW_BUNDLED_PLUGIN_DIR
ARG OPENCLAW_DOCKER_APT_UPGRADE
# OCI base-image metadata for downstream image consumers.
# If you change these annotations, also update:
@@ -155,24 +155,24 @@ LABEL org.opencontainers.image.source="https://github.com/openclaw/openclaw" \
WORKDIR /app
# Install system utilities present in bookworm but missing in bookworm-slim.
# On the full bookworm image these are already installed (apt-get is a no-op).
# Smoke workflows can opt out of distro upgrades to cut repeated CI time while
# keeping the default runtime image behavior unchanged.
# Install runtime system utilities missing from bookworm-slim.
# `ca-certificates` ships in `bookworm` (full) but not in `bookworm-slim`,
# so it must be installed explicitly here. Without it `/etc/ssl/certs/`
# stays empty and every HTTPS outbound dies at TLS handshake with
# `error setting certificate file`.
RUN --mount=type=cache,id=openclaw-bookworm-apt-cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,id=openclaw-bookworm-apt-lists,target=/var/lib/apt,sharing=locked \
apt-get update && \
if [ "${OPENCLAW_DOCKER_APT_UPGRADE}" != "0" ]; then \
DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends; \
fi && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
procps hostname curl git lsof openssl
ca-certificates procps hostname curl git lsof openssl && \
update-ca-certificates
RUN chown node:node /app
COPY --from=runtime-assets --chown=node:node /app/dist ./dist
COPY --from=runtime-assets --chown=node:node /app/node_modules ./node_modules
COPY --from=runtime-assets --chown=node:node /app/package.json .
COPY --from=runtime-assets --chown=node:node /app/patches ./patches
COPY --from=runtime-assets --chown=node:node /app/openclaw.mjs .
COPY --from=runtime-assets --chown=node:node /app/${OPENCLAW_BUNDLED_PLUGIN_DIR} ./${OPENCLAW_BUNDLED_PLUGIN_DIR}
COPY --from=runtime-assets --chown=node:node /app/skills ./skills
@@ -258,6 +258,13 @@ RUN --mount=type=cache,id=openclaw-bookworm-apt-cache,target=/var/cache/apt,shar
RUN ln -sf /app/openclaw.mjs /usr/local/bin/openclaw \
&& chmod 755 /app/openclaw.mjs
# Pre-create the default state and runtime-deps dirs so first-run Docker named
# volumes mounted here inherit node ownership instead of root-owned state.
RUN install -d -m 0700 -o node -g node /home/node/.openclaw && \
install -d -m 0700 -o node -g node /var/lib/openclaw/plugin-runtime-deps && \
stat -c '%U:%G %a' /home/node/.openclaw | grep -qx 'node:node 700' && \
stat -c '%U:%G %a' /var/lib/openclaw/plugin-runtime-deps | grep -qx 'node:node 700'
ENV NODE_ENV=production
# Security hardening: Run as non-root user

View File

@@ -7,7 +7,6 @@ ENV DEBIAN_FRONTEND=noninteractive
RUN --mount=type=cache,id=openclaw-sandbox-bookworm-apt-cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,id=openclaw-sandbox-bookworm-apt-lists,target=/var/lib/apt,sharing=locked \
apt-get update \
&& apt-get upgrade -y --no-install-recommends \
&& apt-get install -y --no-install-recommends \
bash \
ca-certificates \

View File

@@ -7,7 +7,6 @@ ENV DEBIAN_FRONTEND=noninteractive
RUN --mount=type=cache,id=openclaw-sandbox-bookworm-apt-cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,id=openclaw-sandbox-bookworm-apt-lists,target=/var/lib/apt,sharing=locked \
apt-get update \
&& apt-get upgrade -y --no-install-recommends \
&& apt-get install -y --no-install-recommends \
bash \
ca-certificates \

View File

@@ -24,7 +24,6 @@ ENV PATH=${BUN_INSTALL_DIR}/bin:${BREW_INSTALL_DIR}/bin:${BREW_INSTALL_DIR}/sbin
RUN --mount=type=cache,id=openclaw-sandbox-common-apt-cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,id=openclaw-sandbox-common-apt-lists,target=/var/lib/apt,sharing=locked \
apt-get update \
&& apt-get upgrade -y --no-install-recommends \
&& apt-get install -y --no-install-recommends ${PACKAGES}
RUN if [ "${INSTALL_PNPM}" = "1" ]; then npm install -g pnpm; fi

View File

@@ -96,7 +96,7 @@ Model note: while many providers and models are supported, prefer a current flag
## Install (recommended)
Runtime: **Node 24 (recommended) or Node 22.16+**.
Runtime: **Node 24 (recommended) or Node 22.14+**.
```bash
npm install -g openclaw@latest
@@ -109,7 +109,7 @@ OpenClaw Onboard installs the Gateway daemon (launchd/systemd user service) so i
## Quick start (TL;DR)
Runtime: **Node 24 (recommended) or Node 22.16+**.
Runtime: **Node 24 (recommended) or Node 22.14+**.
Full beginner guide (auth, pairing, channels): [Getting started](https://docs.openclaw.ai/start/getting-started)
@@ -119,7 +119,7 @@ openclaw onboard --install-daemon
openclaw gateway --port 18789 --verbose
# Send a message
openclaw message send --to +1234567890 --message "Hello from OpenClaw"
openclaw message send --target +1234567890 --message "Hello from OpenClaw"
# Talk to the assistant (optionally deliver back to any connected channel: WhatsApp/Telegram/Slack/Discord/Google Chat/Signal/iMessage/BlueBubbles/IRC/Microsoft Teams/Matrix/Feishu/LINE/Mattermost/Nextcloud Talk/Nostr/Synology Chat/Tlon/Twitch/Zalo/Zalo Personal/WeChat/QQ/WebChat)
openclaw agent --message "Ship checklist" --thinking high

View File

@@ -288,7 +288,7 @@ OpenClaw's web interface (Gateway Control UI + HTTP endpoints) is intended for *
### Node.js Version
OpenClaw requires **Node.js 22.12.0 or later** (LTS). This version includes important security patches:
OpenClaw requires **Node.js 22.14.0 or later** (LTS). This version includes important security patches:
- CVE-2025-59466: async_hooks DoS vulnerability
- CVE-2026-21636: Permission model bypass vulnerability
@@ -296,7 +296,7 @@ OpenClaw requires **Node.js 22.12.0 or later** (LTS). This version includes impo
Verify your Node.js version:
```bash
node --version # Should be v22.12.0 or later
node --version # Should be v22.14.0 or later
```
### Docker Security

View File

@@ -1,31 +1,13 @@
{
"originHash" : "24a723309d7a0039d3df3051106f77ac1ed7068a02508e3a6804e41d757e6c72",
"originHash" : "e6910acc97de62dc423c0a391985c1c2f28207951e356081539abde41f9ffc72",
"pins" : [
{
"identity" : "commander",
"kind" : "remoteSourceControl",
"location" : "https://github.com/steipete/Commander.git",
"state" : {
"revision" : "9e349575c8e3c6745e81fe19e5bb5efa01b078ce",
"version" : "0.2.1"
}
},
{
"identity" : "elevenlabskit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/steipete/ElevenLabsKit",
"state" : {
"revision" : "7e3c948d8340abe3977014f3de020edf221e9269",
"version" : "0.1.0"
}
},
{
"identity" : "swift-concurrency-extras",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-concurrency-extras",
"state" : {
"revision" : "5a3825302b1a0d744183200915a47b508c828e6f",
"version" : "1.3.2"
"revision" : "ae2ce746b386ff94b26648cfe5625cfa8d02639b",
"version" : "0.2.2"
}
},
{
@@ -45,24 +27,6 @@
"revision" : "399f76dcd91e4c688ca2301fa24a8cc6d9927211",
"version" : "0.99.0"
}
},
{
"identity" : "swiftui-math",
"kind" : "remoteSourceControl",
"location" : "https://github.com/gonzalezreal/swiftui-math",
"state" : {
"revision" : "0b5c2cfaaec8d6193db206f675048eeb5ce95f71",
"version" : "0.1.0"
}
},
{
"identity" : "textual",
"kind" : "remoteSourceControl",
"location" : "https://github.com/gonzalezreal/textual",
"state" : {
"revision" : "5b06b811c0f5313b6b84bbef98c635a630638c38",
"version" : "0.3.1"
}
}
],
"version" : 3

View File

@@ -13,7 +13,7 @@ let package = Package(
.executable(name: "swabble", targets: ["SwabbleCLI"]),
],
dependencies: [
.package(url: "https://github.com/steipete/Commander.git", exact: "0.2.1"),
.package(url: "https://github.com/steipete/Commander.git", exact: "0.2.2"),
.package(url: "https://github.com/apple/swift-testing", from: "0.99.0"),
],
targets: [
@@ -43,7 +43,6 @@ let package = Package(
],
swiftSettings: [
.enableUpcomingFeature("StrictConcurrency"),
.enableExperimentalFeature("SwiftTesting"),
]),
.testTarget(
name: "swabbleTests",

View File

@@ -45,6 +45,15 @@ extension AttributedString {
}
return ranges.compactMap { range in
guard #available(macOS 26.0, iOS 26.0, *) else {
return AttributedString(self[range].characters)
}
return self.sentenceWithAudioTimeRange(range)
}
}
@available(macOS 26.0, iOS 26.0, *)
private func sentenceWithAudioTimeRange(_ range: Range<AttributedString.Index>) -> AttributedString? {
let audioTimeRanges = self[range].runs.filter {
!String(self[$0.range].characters)
.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
@@ -57,6 +66,5 @@ extension AttributedString {
start: start,
end: end)
return AttributedString(self[range].characters, attributes: attributes)
}
}
}

View File

@@ -17,29 +17,35 @@ public enum OutputFormat: String {
case .txt:
return String(transcript.characters)
case .srt:
func format(_ timeInterval: TimeInterval) -> String {
let ms = Int(timeInterval.truncatingRemainder(dividingBy: 1) * 1000)
let s = Int(timeInterval) % 60
let m = (Int(timeInterval) / 60) % 60
let h = Int(timeInterval) / 60 / 60
return String(format: "%0.2d:%0.2d:%0.2d,%0.3d", h, m, s, ms)
}
return transcript.sentences(maxLength: maxLength).compactMap { (sentence: AttributedString) -> (
CMTimeRange,
String)? in
guard let timeRange = sentence.audioTimeRange else { return nil }
return (timeRange, String(sentence.characters))
}.enumerated().map { index, run in
let (timeRange, text) = run
return """
\(index + 1)
\(format(timeRange.start.seconds)) --> \(format(timeRange.end.seconds))
\(text.trimmingCharacters(in: .whitespacesAndNewlines))
"""
}.joined().trimmingCharacters(in: .whitespacesAndNewlines)
guard #available(macOS 26.0, iOS 26.0, *) else { return "" }
return self.srtText(for: transcript, maxLength: maxLength)
}
}
@available(macOS 26.0, iOS 26.0, *)
private func srtText(for transcript: AttributedString, maxLength: Int) -> String {
func format(_ timeInterval: TimeInterval) -> String {
let ms = Int(timeInterval.truncatingRemainder(dividingBy: 1) * 1000)
let s = Int(timeInterval) % 60
let m = (Int(timeInterval) / 60) % 60
let h = Int(timeInterval) / 60 / 60
return String(format: "%0.2d:%0.2d:%0.2d,%0.3d", h, m, s, ms)
}
return transcript.sentences(maxLength: maxLength).compactMap { (sentence: AttributedString) -> (
CMTimeRange,
String)? in
guard let timeRange = sentence.audioTimeRange else { return nil }
return (timeRange, String(sentence.characters))
}.enumerated().map { index, run in
let (timeRange, text) = run
return """
\(index + 1)
\(format(timeRange.start.seconds)) --> \(format(timeRange.end.seconds))
\(text.trimmingCharacters(in: .whitespacesAndNewlines))
"""
}.joined().trimmingCharacters(in: .whitespacesAndNewlines)
}
}

View File

@@ -13,7 +13,9 @@ public struct WakeWordSegment: Sendable, Equatable {
self.range = range
}
public var end: TimeInterval { start + duration }
public var end: TimeInterval {
self.start + self.duration
}
}
public struct WakeWordGateConfig: Sendable, Equatable {
@@ -24,7 +26,8 @@ public struct WakeWordGateConfig: Sendable, Equatable {
public init(
triggers: [String],
minPostTriggerGap: TimeInterval = 0.45,
minCommandLength: Int = 1) {
minCommandLength: Int = 1)
{
self.triggers = triggers
self.minPostTriggerGap = minPostTriggerGap
self.minCommandLength = minCommandLength
@@ -35,11 +38,18 @@ public struct WakeWordGateMatch: Sendable, Equatable {
public let triggerEndTime: TimeInterval
public let postGap: TimeInterval
public let command: String
public let trigger: String?
public init(triggerEndTime: TimeInterval, postGap: TimeInterval, command: String) {
public init(
triggerEndTime: TimeInterval,
postGap: TimeInterval,
command: String,
trigger: String? = nil)
{
self.triggerEndTime = triggerEndTime
self.postGap = postGap
self.command = command
self.trigger = trigger
}
}
@@ -53,13 +63,17 @@ public enum WakeWordGate {
}
private struct TriggerTokens {
let source: String
let tokens: [String]
}
private struct MatchCandidate {
let index: Int
let endIndex: Int
let tokenCount: Int
let triggerEnd: TimeInterval
let gap: TimeInterval
let trigger: String
}
public static func match(
@@ -67,10 +81,10 @@ public enum WakeWordGate {
segments: [WakeWordSegment],
config: WakeWordGateConfig)
-> WakeWordGateMatch? {
let triggerTokens = normalizeTriggers(config.triggers)
let triggerTokens = self.normalizeTriggers(config.triggers)
guard !triggerTokens.isEmpty else { return nil }
let tokens = normalizeSegments(segments)
let tokens = self.normalizeSegments(segments)
guard !tokens.isEmpty else { return nil }
var best: MatchCandidate?
@@ -87,17 +101,31 @@ public enum WakeWordGate {
let gap = nextToken.start - triggerEnd
if gap < config.minPostTriggerGap { continue }
if let best, i <= best.index { continue }
let endIndex = i + count - 1
if let best {
if endIndex < best.endIndex { continue }
if endIndex == best.endIndex, count <= best.tokenCount { continue }
}
best = MatchCandidate(index: i, triggerEnd: triggerEnd, gap: gap)
best = MatchCandidate(
index: i,
endIndex: endIndex,
tokenCount: count,
triggerEnd: triggerEnd,
gap: gap,
trigger: trigger.source)
}
}
guard let best else { return nil }
let command = commandText(transcript: transcript, segments: segments, triggerEndTime: best.triggerEnd)
let command = self.commandText(transcript: transcript, segments: segments, triggerEndTime: best.triggerEnd)
.trimmingCharacters(in: Self.whitespaceAndPunctuation)
guard command.count >= config.minCommandLength else { return nil }
return WakeWordGateMatch(triggerEndTime: best.triggerEnd, postGap: best.gap, command: command)
return WakeWordGateMatch(
triggerEndTime: best.triggerEnd,
postGap: best.gap,
command: command,
trigger: best.trigger)
}
public static func commandText(
@@ -120,7 +148,7 @@ public enum WakeWordGate {
guard !text.isEmpty else { return false }
let normalized = text.lowercased()
for trigger in triggers {
let token = trigger.trimmingCharacters(in: whitespaceAndPunctuation).lowercased()
let token = trigger.trimmingCharacters(in: self.whitespaceAndPunctuation).lowercased()
if token.isEmpty { continue }
if normalized.contains(token) { return true }
}
@@ -130,11 +158,11 @@ public enum WakeWordGate {
public static func stripWake(text: String, triggers: [String]) -> String {
var out = text
for trigger in triggers {
let token = trigger.trimmingCharacters(in: whitespaceAndPunctuation)
let token = trigger.trimmingCharacters(in: self.whitespaceAndPunctuation)
guard !token.isEmpty else { continue }
out = out.replacingOccurrences(of: token, with: "", options: [.caseInsensitive])
}
return out.trimmingCharacters(in: whitespaceAndPunctuation)
return out.trimmingCharacters(in: self.whitespaceAndPunctuation)
}
private static func normalizeTriggers(_ triggers: [String]) -> [TriggerTokens] {
@@ -142,17 +170,17 @@ public enum WakeWordGate {
for trigger in triggers {
let tokens = trigger
.split(whereSeparator: { $0.isWhitespace })
.map { normalizeToken(String($0)) }
.map { self.normalizeToken(String($0)) }
.filter { !$0.isEmpty }
if tokens.isEmpty { continue }
output.append(TriggerTokens(tokens: tokens))
output.append(TriggerTokens(source: tokens.joined(separator: " "), tokens: tokens))
}
return output
}
private static func normalizeSegments(_ segments: [WakeWordSegment]) -> [Token] {
segments.compactMap { segment in
let normalized = normalizeToken(segment.text)
let normalized = self.normalizeToken(segment.text)
guard !normalized.isEmpty else { return nil }
return Token(
normalized: normalized,
@@ -165,7 +193,7 @@ public enum WakeWordGate {
private static func normalizeToken(_ token: String) -> String {
token
.trimmingCharacters(in: whitespaceAndPunctuation)
.trimmingCharacters(in: self.whitespaceAndPunctuation)
.lowercased()
}

View File

@@ -5,6 +5,7 @@ import Speech
import Swabble
@MainActor
@available(macOS 26.0, *)
struct TranscribeCommand: ParsableCommand {
@Argument(help: "Path to audio/video file") var inputFile: String = ""
@Option(name: .long("locale"), help: "Locale identifier", parsing: .singleValue) var locale: String = Locale.current

View File

@@ -1,9 +1,9 @@
import Foundation
import SwabbleKit
import Testing
import XCTest
@Suite struct WakeWordGateTests {
@Test func matchRequiresGapAfterTrigger() {
final class WakeWordGateTests: XCTestCase {
func testMatchRequiresGapAfterTrigger() {
let transcript = "hey clawd do thing"
let segments = makeSegments(
transcript: transcript,
@@ -14,10 +14,10 @@ import Testing
("thing", 0.5, 0.1),
])
let config = WakeWordGateConfig(triggers: ["clawd"], minPostTriggerGap: 0.3)
#expect(WakeWordGate.match(transcript: transcript, segments: segments, config: config) == nil)
XCTAssertNil(WakeWordGate.match(transcript: transcript, segments: segments, config: config))
}
@Test func matchAllowsGapAndExtractsCommand() {
func testMatchAllowsGapAndExtractsCommand() {
let transcript = "hey clawd do thing"
let segments = makeSegments(
transcript: transcript,
@@ -29,10 +29,10 @@ import Testing
])
let config = WakeWordGateConfig(triggers: ["clawd"], minPostTriggerGap: 0.3)
let match = WakeWordGate.match(transcript: transcript, segments: segments, config: config)
#expect(match?.command == "do thing")
XCTAssertEqual(match?.command, "do thing")
}
@Test func matchHandlesMultiWordTriggers() {
func testMatchHandlesMultiWordTriggers() {
let transcript = "hey clawd do it"
let segments = makeSegments(
transcript: transcript,
@@ -44,10 +44,25 @@ import Testing
])
let config = WakeWordGateConfig(triggers: ["hey clawd"], minPostTriggerGap: 0.3)
let match = WakeWordGate.match(transcript: transcript, segments: segments, config: config)
#expect(match?.command == "do it")
XCTAssertEqual(match?.command, "do it")
}
@Test func commandTextHandlesForeignRangeIndices() {
func testMatchPrefersMostSpecificTriggerWhenOverlapping() {
let transcript = "hey clawd do it"
let segments = makeSegments(
transcript: transcript,
words: [
("hey", 0.0, 0.1),
("clawd", 0.2, 0.1),
("do", 0.8, 0.1),
("it", 1.0, 0.1),
])
let config = WakeWordGateConfig(triggers: ["clawd", "hey clawd"], minPostTriggerGap: 0.3)
let match = WakeWordGate.match(transcript: transcript, segments: segments, config: config)
XCTAssertEqual(match?.trigger, "hey clawd")
}
func testCommandTextHandlesForeignRangeIndices() {
let transcript = "hey clawd do thing"
let other = "do thing"
let foreignRange = other.range(of: "do")
@@ -63,7 +78,7 @@ import Testing
segments: segments,
triggerEndTime: 0.3)
#expect(command == "do thing")
XCTAssertEqual(command, "do thing")
}
}

View File

@@ -1,23 +1,22 @@
import Foundation
import Testing
@testable import Swabble
import XCTest
@Test
func configRoundTrip() throws {
var cfg = SwabbleConfig()
cfg.wake.word = "robot"
let url = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString + ".json")
defer { try? FileManager.default.removeItem(at: url) }
final class ConfigTests: XCTestCase {
func testConfigRoundTrip() throws {
var cfg = SwabbleConfig()
cfg.wake.word = "robot"
let url = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString + ".json")
defer { try? FileManager.default.removeItem(at: url) }
try ConfigLoader.save(cfg, at: url)
let loaded = try ConfigLoader.load(at: url)
#expect(loaded.wake.word == "robot")
#expect(loaded.hook.prefix.contains("Voice swabble"))
}
try ConfigLoader.save(cfg, at: url)
let loaded = try ConfigLoader.load(at: url)
XCTAssertEqual(loaded.wake.word, "robot")
XCTAssertTrue(loaded.hook.prefix.contains("Voice swabble"))
}
@Test
func configMissingThrows() {
#expect(throws: ConfigError.missingConfig) {
_ = try ConfigLoader.load(at: FileManager.default.temporaryDirectory.appendingPathComponent("nope.json"))
func testConfigMissingThrows() {
XCTAssertThrowsError(
try ConfigLoader.load(at: FileManager.default.temporaryDirectory.appendingPathComponent("nope.json")))
}
}

View File

@@ -53,12 +53,24 @@ We prioritize secure defaults, but also expose clear knobs for trusted high-powe
OpenClaw has an extensive plugin API.
Core stays lean; optional capability should usually ship as plugins.
We are generally slimming down core while expanding what plugins can do.
If a useful feature cannot be built as a plugin yet, we welcome PRs and design discussions that extend the plugin API instead of adding one-off core behavior.
There are two broad plugin styles:
- Code plugins run OpenClaw plugin code and are appropriate for deeper runtime extension.
- Bundle-style plugins package stable external surfaces such as skills, MCP servers, and related configuration.
Prefer bundle-style plugins when they can express the capability.
They have a smaller, more stable interface and better security boundaries.
Use code plugins when the capability needs runtime hooks, providers, channels, tools, or other in-process extension points.
Preferred plugin path is npm package distribution plus local extension loading for development.
If you build a plugin, host and maintain it in your own repository.
The bar for adding optional plugins to core is intentionally high.
Plugin docs: [`docs/tools/plugin.md`](docs/tools/plugin.md)
Community plugin listing + PR bar: https://docs.openclaw.ai/plugins/community
Plugin discovery, official publisher status, provenance, and security review live in [ClawHub](https://clawhub.ai/).
OpenClaw docs should document core extension points; plugin promotion belongs in ClawHub, preferably under vetted org publishers for official plugins.
Memory is a special plugin slot where only one memory plugin can be active at a time.
Today we ship multiple memory options; over time we plan to converge on one recommended default path.
@@ -66,21 +78,16 @@ Today we ship multiple memory options; over time we plan to converge on one reco
### Skills
We still ship some bundled skills for baseline UX.
New skills should be published to ClawHub first (`clawhub.ai`), not added to core by default.
Core skill additions should be rare and require a strong product or security reason.
New skills should be published through [ClawHub](https://clawhub.ai/) first, not added to core by default.
Official or bundled promotion should require a clear product, security, or maintainer-ownership reason.
### MCP Support
OpenClaw supports MCP through `mcporter`: https://github.com/steipete/mcporter
OpenClaw supports MCP as both a server and a runtime integration surface.
MCP details live in [`docs/cli/mcp.md`](docs/cli/mcp.md).
This keeps MCP integration flexible and decoupled from core runtime:
- add or change MCP servers without restarting the gateway
- keep core tool/context surface lean
- reduce MCP churn impact on core stability and security
For now, we prefer this bridge model over building first-class MCP runtime into core.
If there is an MCP server or feature `mcporter` does not support yet, please open an issue there.
The project goal is pragmatic MCP support without duplicating existing agent,
tool, ACPX, plugin, or ClawHub paths.
### Setup
@@ -98,11 +105,11 @@ It is widely known, fast to iterate in, and easy to read, modify, and extend.
## What We Will Not Merge (For Now)
- New core skills when they can live on ClawHub
- New core skills when they can live on [ClawHub](https://clawhub.ai/)
- Full-doc translation sets for all docs (deferred; we plan AI-generated translations later)
- Commercial service integrations that do not clearly fit the model-provider category
- Wrapper channels around already supported channels without a clear capability or security gap
- First-class MCP runtime in core when `mcporter` already provides the integration path
- MCP work that duplicates existing MCP, ACPX, plugin, or ClawHub paths without a clear product or security gap
- Agent-hierarchy frameworks (manager-of-managers / nested planner trees) as a default architecture
- Heavy orchestration layers that duplicate existing agent and tool infrastructure

View File

@@ -3,318 +3,691 @@
<channel>
<title>OpenClaw</title>
<item>
<title>2026.4.20</title>
<pubDate>Tue, 21 Apr 2026 19:53:52 +0000</pubDate>
<title>2026.4.26</title>
<pubDate>Tue, 28 Apr 2026 02:40:27 +0000</pubDate>
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
<sparkle:version>2026042090</sparkle:version>
<sparkle:shortVersionString>2026.4.20</sparkle:shortVersionString>
<sparkle:version>2026042690</sparkle:version>
<sparkle:shortVersionString>2026.4.26</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[<h2>OpenClaw 2026.4.20</h2>
<description><![CDATA[<h2>OpenClaw 2026.4.26</h2>
<h3>Changes</h3>
<ul>
<li>Onboard/wizard: restyle the setup security disclaimer with a single yellow warning banner, section headings and bulleted checklists, and un-dim the note body so key guidance is easy to scan; add a loading spinner during the initial model catalog load so the wizard no longer goes blank while it runs; add an "API key" placeholder to provider API key prompts. (#69553) Thanks @Patrick-Erichsen.</li>
<li>Agents/prompts: strengthen the default system prompt and OpenAI GPT-5 overlay with clearer completion bias, live-state checks, weak-result recovery, and verification-before-final guidance.</li>
<li>Models/costs: support tiered model pricing from cached catalogs and configured models, and include bundled Moonshot Kimi K2.6/K2.5 cost estimates for token-usage reports. (#67605) Thanks @sliverp.</li>
<li>Sessions/Maintenance: enforce the built-in entry cap and age prune by default, and prune oversized stores at load time so accumulated cron/executor session backlogs cannot OOM the gateway before the write path runs. (#69404) Thanks @bobrenze-bot.</li>
<li>Plugins/tests: reuse plugin loader alias and Jiti config resolution across repeated same-context loads, reducing import-heavy test overhead. (#69316) Thanks @amknight.</li>
<li>Cron: split runtime execution state into <code>jobs-state.json</code> so <code>jobs.json</code> stays stable for git-tracked job definitions. (#63105) Thanks @Feelw00.</li>
<li>Agents/compaction: send opt-in start and completion notices during context compaction. (#67830) Thanks @feniix.</li>
<li>Moonshot/Kimi: default bundled Moonshot setup, web search, and media-understanding surfaces to <code>kimi-k2.6</code> while keeping <code>kimi-k2.5</code> available for compatibility. (#69477) Thanks @scoootscooob.</li>
<li>Moonshot/Kimi: allow <code>thinking.keep = "all"</code> on <code>moonshot/kimi-k2.6</code>, and strip it for other Moonshot models or requests where pinned <code>tool_choice</code> disables thinking. (#68816) Thanks @aniaan.</li>
<li>BlueBubbles/groups: forward per-group <code>systemPrompt</code> config into inbound context <code>GroupSystemPrompt</code> so configured group-specific behavioral instructions (for example threaded-reply and tapback conventions) are injected on every turn. Supports <code>"*"</code> wildcard fallback matching the existing <code>requireMention</code> pattern. Closes #60665. (#69198) Thanks @omarshahine.</li>
<li>Plugins/tasks: add a detached runtime registration contract so plugin executors can own detached task lifecycle and cancellation without reaching into core task internals. (#68915) Thanks @mbelinky.</li>
<li>Terminal/logging: optimize <code>sanitizeForLog()</code> by replacing the iterative control-character stripping loop with a single regex pass while preserving the existing ANSI-first sanitization behavior. (#67205) Thanks @bulutmuf.</li>
<li>QA/CI: make <code>openclaw qa suite</code> and <code>openclaw qa telegram</code> fail by default when scenarios fail, add <code>--allow-failures</code> for artifact-only runs, and tighten live-lane defaults for CI automation. (#69122) Thanks @joshavant.</li>
<li>Mattermost: stream thinking, tool activity, and partial reply text into a single draft preview post that finalizes in place when safe. (#47838) thanks @ninjaa.</li>
<li>Channels/QQBot: add full group chat support (history tracking, @-mention gating, activation modes, per-group config, FIFO message queue with deliver debounce), C2C <code>stream_messages</code> streaming with a <code>StreamingController</code> lifecycle manager, unified <code>sendMedia</code> with chunked upload for large files, and refactor the engine into pipeline stages, focused outbound submodules, builtin slash-command modules, and explicit DI ports via <code>createEngineAdapters()</code>. (#70624) Thanks @cxyhhhhh.</li>
<li>Channels/Yuanbao: register the Tencent Yuanbao external channel plugin (<code>openclaw-plugin-yuanbao</code>) in the official channel catalog, contract suites, and community plugin docs, with a new <code>docs/channels/yuanbao.md</code> quick-start guide for WebSocket bot DMs and group chats. (#72756) Thanks @loongfay.</li>
<li>Control UI/Talk: add a generic browser realtime transport contract, Google Live browser Talk sessions with constrained ephemeral tokens, and a Gateway relay for backend-only realtime voice plugins. Thanks @VACInc.</li>
<li>CLI/models: route provider-filtered model listing through an explicit source plan so user config, installed manifest rows, Provider Index previews, and scoped runtime fallbacks keep a stable authority order without adding another catalog cache. Thanks @shakkernerd.</li>
<li>Providers: add Cerebras as a bundled plugin with onboarding, static model catalog, docs, and manifest-owned endpoint metadata.</li>
<li>Memory/OpenAI-compatible: add optional <code>memorySearch.inputType</code>, <code>queryInputType</code>, and <code>documentInputType</code> config for asymmetric embedding endpoints, including direct query embeddings and provider batch indexing. Carries forward #63313 and #60727. Thanks @HOYALIM and @prospect1314521.</li>
<li>Ollama/memory: add model-specific retrieval query prefixes for <code>nomic-embed-text</code>, <code>qwen3-embedding</code>, and <code>mxbai-embed-large</code> memory-search queries while leaving document batches unchanged. Carries forward #45013. Thanks @laolin5564.</li>
<li>Plugins/providers: move pre-runtime model-id normalization, endpoint host metadata, OpenAI-compatible request-family hints, model-catalog aliases/suppressions, OpenAI stale Spark suppression, and reusable startup metadata snapshots into plugin manifests so core no longer carries bundled-provider routing tables or repeated manifest rebuilds. Thanks @shakkernerd.</li>
<li>Plugins/config: deprecate direct plugin config load/write helpers in favor of passed runtime snapshots plus transactional mutation helpers with explicit restart follow-up policy, scanner guardrails, runtime warnings, and revision-based cache invalidation.</li>
<li>Plugins/install: allow <code>OPENCLAW_PLUGIN_STAGE_DIR</code> to contain layered runtime-dependency roots, resolving read-only preinstalled deps before installing missing deps into the final writable root. Fixes #72396. Thanks @liorb-mountapps.</li>
<li>Control UI: add a raw config pending-changes diff panel that parses JSON5, redacts sensitive values until reveal, and avoids fake raw-edit callbacks when opening the panel. Refs #39831; supersedes #48621 and #46654. Thanks @JiajunBernoulli and @BunsDev.</li>
<li>Control UI: polish the quick settings dashboard grid so common cards align across desktop, tablet, and mobile layouts without wasting horizontal space. Thanks @BunsDev.</li>
<li>Matrix/E2EE: add <code>openclaw matrix encryption setup</code> to enable Matrix encryption, bootstrap recovery, and print verification status from one setup flow. Thanks @gumadeiras.</li>
<li>Agents/compaction: add an opt-in <code>agents.defaults.compaction.maxActiveTranscriptBytes</code> preflight trigger that runs normal local compaction when the active JSONL grows too large, requiring transcript rotation so successful compaction moves future turns onto a smaller successor file instead of raw byte-splitting history. Thanks @vincentkoc.</li>
<li>CLI/migration: add <code>openclaw migrate</code> with plan, dry-run, JSON, pre-migration backup, onboarding detection, archive-only reports, a Claude Code/Desktop importer, and a Hermes importer for configuration, memory/plugin hints, model providers, MCP servers, skills, commands, and supported credentials. Thanks @vincentkoc and @NousResearch.</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Exec/YOLO: stop rejecting gateway-host exec in <code>security=full</code> plus <code>ask=off</code> mode via the Python/Node script preflight hardening path, so promptless YOLO exec once again runs direct interpreter stdin and heredoc forms such as <code>node <<'NODE' ... NODE</code>.</li>
<li>OpenAI Codex: normalize legacy <code>openai-completions</code> transport overrides on default OpenAI/Codex and GitHub Copilot-compatible hosts back to the native Codex Responses transport while leaving custom proxies untouched. (#45304, #42194) Thanks @dyss1992 and @DeadlySilent.</li>
<li>Anthropic/plugins: scope Anthropic <code>api: "anthropic-messages"</code> defaulting to Anthropic-owned providers, so <code>openai-codex</code> and other providers without an explicit <code>api</code> no longer get rewritten to the wrong transport. Fixes #64534.</li>
<li>fix(qqbot): add SSRF guard to direct-upload URL paths in uploadC2CMedia and uploadGroupMedia [AI-assisted]. (#69595) Thanks @pgondhi987.</li>
<li>fix(gateway): enforce allowRequestSessionKey gate on template-rendered mapping sessionKeys. (#69381) Thanks @pgondhi987.</li>
<li>Browser/Chrome MCP: surface <code>DevToolsActivePort</code> attach failures as browser-connectivity errors instead of a generic "waiting for tabs" timeout, and point signed-out fallbacks toward the managed <code>openclaw</code> profile.</li>
<li>Webchat/images: treat inline image attachments as media for empty-turn gating while still ignoring metadata-only blank turns. (#69474) Thanks @Jaswir.</li>
<li>Discord/think: only show <code>adaptive</code> in <code>/think</code> autocomplete for provider/model pairs that actually support provider-managed adaptive thinking, so GPT/OpenAI models no longer advertise an Anthropic-only option.</li>
<li>Thinking: only expose <code>max</code> for models that explicitly support provider max reasoning, and remap stored <code>max</code> settings to the largest supported thinking mode when users switch to another model.</li>
<li>Gateway/usage: bound the cost usage cache with FIFO eviction so date/range lookups cannot grow unbounded. (#68842) Thanks @Feelw00.</li>
<li>OpenAI/Responses: resolve <code>/think</code> levels against each GPT model's supported reasoning efforts so <code>/think off</code> no longer becomes high reasoning or sends unsupported <code>reasoning.effort: "none"</code> payloads.</li>
<li>Lobster/TaskFlow: allow managed approval resumes to use <code>approvalId</code> without a resume token, and persist that id in approval wait state. (#69559) Thanks @kirkluokun.</li>
<li>Plugins/startup: install bundled runtime dependencies into each plugin's own runtime directory, reuse source-checkout repair caches after rebuilds, and log only packages that were actually installed so repeated Gateway starts stay quiet once deps are present.</li>
<li>Plugins/startup: ignore pnpm's <code>npm_execpath</code> when repairing bundled plugin runtime dependencies and skip workspace-only package specs so npm-only install flags or local workspace links do not break packaged plugin startup.</li>
<li>MCP: block interpreter-startup env keys such as <code>NODE_OPTIONS</code> for stdio servers while preserving ordinary credential and proxy env vars. (#69540) Thanks @drobison00.</li>
<li>Agents/shell: ignore non-interactive placeholder shells like <code>/usr/bin/false</code> and <code>/sbin/nologin</code>, falling back to <code>sh</code> so service-user exec runs no longer exit immediately. (#69308) Thanks @sk7n4k3d.</li>
<li>Setup/TUI: relaunch the setup hatch TUI in a fresh process while preserving the configured gateway target and auth source, so onboarding recovers terminal state cleanly without exposing gateway secrets on command-line args. (#69524) Thanks @shakkernerd.</li>
<li>Codex: avoid re-exposing the image-generation tool on native vision turns with inbound images, and keep bare image-model overrides on the configured image provider. (#65061) Thanks @zhulijin1991.</li>
<li>Sessions/reset: clear auto-sourced model, provider, and auth-profile overrides on <code>/new</code> and <code>/reset</code> while preserving explicit user selections, so channel sessions stop staying pinned to runtime fallback choices. (#69419) Thanks @sk7n4k3d.</li>
<li>Sessions/costs: snapshot <code>estimatedCostUsd</code> like token counters so repeated persist paths no longer compound the same run cost by up to dozens of times. (#69403) Thanks @MrMiaigi.</li>
<li>OpenAI Codex: route ChatGPT/Codex OAuth Responses requests through the <code>/backend-api/codex</code> endpoint so <code>openai-codex/gpt-5.4</code> no longer hits the removed <code>/backend-api/responses</code> alias. (#69336) Thanks @mzogithub.</li>
<li>OpenAI/Responses: omit disabled reasoning payloads when <code>/think off</code> is active, so GPT reasoning models no longer receive unsupported <code>reasoning.effort: "none"</code> requests. (#61982) Thanks @a-tokyo.</li>
<li>Gateway/pairing: treat loopback shared-secret node-host, TUI, and gateway clients as local for pairing decisions, so trusted local tools no longer reconnect as remote clients and fail with <code>pairing required</code>. (#69431) Thanks @SARAMALI15792.</li>
<li>Active Memory: degrade gracefully when memory recall fails during prompt building, logging a warning and letting the reply continue without memory context instead of failing the whole turn. (#69485) Thanks @Magicray1217.</li>
<li>Ollama: add provider-policy defaults for <code>baseUrl</code> and <code>models</code> so implicit local discovery can run before config validation rejects a minimal Ollama provider config. (#69370) Thanks @PratikRai0101.</li>
<li>Agents/model selection: clear transient auto-failover session overrides before each turn so recovered primary models are retried immediately without emitting user-override reset warnings. (#69365) Thanks @hitesh-github99.</li>
<li>Auto-reply: apply silent <code>NO_REPLY</code> policy per conversation type, so direct chats get a helpful rewritten reply while groups and internal deliveries can remain quiet. (#68644) Thanks @Takhoffman.</li>
<li>Telegram/status reactions: honor <code>messages.removeAckAfterReply</code> when lifecycle status reactions are enabled, clearing or restoring the reaction after success/error using the configured hold timings. (#68067) Thanks @poiskgit.</li>
<li>Web search/plugins: resolve plugin-scoped SecretRef API keys for bundled Exa, Firecrawl, Gemini, Kimi, Perplexity, Tavily, and Grok web-search providers when they are selected through the shared web-search config. (#68424) Thanks @afurm.</li>
<li>Telegram/polling: raise the default polling watchdog threshold from 90s to 120s and add configurable <code>channels.telegram.pollingStallThresholdMs</code> (also per-account) so long-running Telegram work gets more room before polling is treated as stalled. (#57737) Thanks @Vitalcheffe.</li>
<li>Telegram/polling: bound the persisted-offset confirmation <code>getUpdates</code> probe with a client-side timeout so a zombie socket cannot hang polling recovery before the runner watchdog starts. (#50368) Thanks @boticlaw.</li>
<li>Agents/Pi runner: retry silent <code>stopReason=error</code> turns with no output when no side effects ran, so non-frontier providers that briefly return empty error turns get another chance instead of ending the session early. (#68310) Thanks @Chased1k.</li>
<li>Plugins/memory: preserve the active memory capability when read-only snapshot plugin loads run, so status and provider discovery paths no longer wipe memory public artifacts. (#69219) Thanks @zeroaltitude.</li>
<li>Plugins: keep only the highest-precedence manifest when distinct discovered plugins share an id, so lower-precedence global or workspace duplicates no longer load beside bundled or config-selected plugins. (#41626) Thanks @Tortes.</li>
<li>fix(security): block MINIMAX_API_HOST workspace env injection and remove env-driven URL routing [AI-assisted]. (#67300) Thanks @pgondhi987.</li>
<li>Cron/delivery: treat explicit <code>delivery.mode: "none"</code> runs as not requested even if the runner reports <code>delivered: false</code>, so no-delivery cron jobs no longer persist false delivery failures or errors. (#69285) Thanks @matsuri1987.</li>
<li>Plugins/install: repair active and default-enabled bundled plugin runtime dependencies before import in packaged installs, so bundled Discord, WhatsApp, Slack, Telegram, and provider plugins work without putting their dependency trees in core.</li>
<li>BlueBubbles: raise the outbound <code>/api/v1/message/text</code> send timeout default from 10s to 30s, and add a configurable <code>channels.bluebubbles.sendTimeoutMs</code> (also per-account) so macOS 26 setups where Private API iMessage sends stall for 60+ seconds no longer silently lose messages at the 10s abort. Probes, chat lookups, and health checks keep the shorter 10s default. Fixes #67486. (#69193) Thanks @omarshahine.</li>
<li>Agents/bootstrap: budget truncation markers against per-file caps, preserve source content instead of silently wasting bootstrap bytes, and avoid marker-only output in tiny-budget truncation cases. (#69114) Thanks @BKF-Gitty.</li>
<li>Context engine/plugins: stop rejecting third-party context engines whose <code>info.id</code> differs from the registered plugin slot id. The strict-match contract added in 2026.4.14 broke <code>lossless-claw</code> and other plugins whose internal engine id does not equal the slot id they are registered under, producing repeated <code>info.id must match registered id</code> lane failures on every turn. Fixes #66601. (#66678) Thanks @GodsBoy.</li>
<li>Agents/compaction: rename embedded Pi compaction lifecycle events to <code>compaction_start</code> / <code>compaction_end</code> so OpenClaw stays aligned with <code>pi-coding-agent</code> 0.66.1 event naming. (#67713) Thanks @mpz4life.</li>
<li>Security/dotenv: block all <code>OPENCLAW_*</code> keys from untrusted workspace <code>.env</code> files so workspace-local env loading fails closed for new runtime-control variables instead of silently inheriting them. (#473)</li>
<li>Gateway/device pairing: restrict non-admin paired-device sessions (device-token auth) to their own pairing list, approve, and reject actions so a paired device cannot enumerate other devices or approve/reject pairing requests authored by another device. Admin and shared-secret operator sessions retain full visibility. (#69375) Thanks @eleqtrizit.</li>
<li>Agents/gateway tool: extend the agent-facing <code>gateway</code> tool's config mutation guard so model-driven <code>config.patch</code> and <code>config.apply</code> cannot rewrite operator-trusted paths (sandbox, plugin trust, gateway auth/TLS, hook routing and tokens, SSRF policy, MCP servers, workspace filesystem hardening) and cannot bypass the guard by editing per-agent sandbox, tools, or embedded-Pi overrides in place under <code>agents.list[]</code>. (#69377) Thanks @eleqtrizit.</li>
<li>Gateway/websocket broadcasts: require <code>operator.read</code> (or higher) for chat, agent, and tool-result event frames so pairing-scoped and node-role sessions no longer passively receive session chat content, and scope-gate unknown broadcast events by default. Plugin-defined <code>plugin.*</code> broadcasts are scoped to operator.write/admin, and status/transport events (<code>heartbeat</code>, <code>presence</code>, <code>tick</code>, etc.) remain unrestricted. Per-client sequence numbers preserve per-connection monotonicity. (#69373) Thanks @eleqtrizit.</li>
<li>Agents/compaction: always reload embedded Pi resources through an explicit loader and reapply reserve-token overrides so runs without extension factories no longer silently lose compaction settings before session start. (#67146) Thanks @ly85206559.</li>
<li>Memory-core/dreaming: normalize sweep timestamps and reuse hashed narrative session keys for fallback cleanup so Dreaming narrative sub-sessions stop leaking. (#67023) Thanks @chiyouYCH.</li>
<li>Gateway/startup: delay HTTP bind until websocket handlers are attached, so immediate post-startup websocket health/connect probes no longer hit the startup race window. (#43392) Thanks @dalefrieswthat.</li>
<li>Codex/app-server: release the session lane when a downstream consumer throws while draining the <code>turn/completed</code> notification, so follow-up messages after a Codex plugin reply stop queueing behind a stale lane lock. Fixes #67996. (#69072) Thanks @ayeshakhalid192007-dev.</li>
<li>Codex/app-server: default approval handling to <code>on-request</code> so Codex harness sessions do not start with overly permissive tool approvals. (#68721) Thanks @Lucenx9.</li>
<li>Cron/delivery: keep isolated cron chat delivery tools available, resolve <code>channel: "last"</code> targets from the gateway, show delivery previews in <code>cron list/show</code>, and avoid duplicate fallback sends after direct message-tool delivery. (#69587) Thanks @obviyus.</li>
<li>Cron/Telegram: key isolated direct-delivery dedupe to each cron execution instead of the reused session id, so recurring Telegram announce runs no longer report delivered while silently skipping later sends. (#69000) Thanks @obviyus.</li>
<li>Models/Kimi: default bundled Kimi thinking to off and normalize Anthropic-compatible <code>thinking</code> payloads so stale session <code>/think</code> state no longer silently re-enables reasoning on Kimi runs. (#68907) Thanks @frankekn.</li>
<li>Control UI/cron: keep the runtime-only <code>last</code> delivery sentinel from being materialized into persisted cron delivery and failure-alert channel configs when jobs are created or edited. (#68829) Thanks @tianhaocui.</li>
<li>OpenAI/Responses: strip orphaned reasoning blocks before outbound Responses API calls so compacted or restored histories no longer fail on standalone reasoning items. (#55787) Thanks @suboss87.</li>
<li>Cron/CLI: parse PowerShell-style <code>--tools</code> allow-lists the same way as comma-separated input, so <code>cron add</code> and <code>cron edit</code> no longer persist <code>exec read write</code> as one combined tool entry on Windows. (#68858) Thanks @chen-zhang-cs-code.</li>
<li>Browser/user-profile: let existing-session <code>profile="user"</code> tool calls auto-route to a connected browser node or use explicit <code>target="node"</code>, while still honoring explicit <code>target="host"</code> pinning. (#48677)</li>
<li>Discord/slash commands: tolerate partial Discord channel metadata in slash-command and model-picker flows so partial channel objects no longer crash when channel names, topics, or thread parent metadata are unavailable. (#68953) Thanks @dutifulbob.</li>
<li>BlueBubbles: consolidate outbound HTTP through a typed <code>BlueBubblesClient</code> that resolves the SSRF policy once at construction so image attachments stop getting blocked on localhost and reactions stop getting blocked on private-IP BB deployments. Fixes #34749 and #59722. (#68234) Thanks @omarshahine.</li>
<li>Cron/gateway: reject ambiguous announce delivery config at add/update time so invalid multi-channel or target-id provider settings fail early instead of persisting broken cron jobs. (#69015) Thanks @obviyus.</li>
<li>Cron/main-session delivery: preserve <code>heartbeat.target="last"</code> through deferred wake queuing, gateway wake forwarding, and same-target wake coalescing so queued cron replies still return to the last active chat. (#69021) Thanks @obviyus.</li>
<li>Cron/gateway: ignore disabled channels when announce delivery ambiguity is checked, and validate main-session delivery patches against the live cron service default agent so hot-reloaded agent config does not falsely reject valid updates. (#69040) Thanks @obviyus.</li>
<li>Matrix/allowlists: hot-reload <code>dm.allowFrom</code> and <code>groupAllowFrom</code> entries on inbound messages while keeping config removals authoritative, so Matrix allowlist changes no longer require a channel restart to add or revoke a sender. (#68546) Thanks @johnlanni.</li>
<li>BlueBubbles: always set <code>method</code> explicitly on outbound text sends (<code>"private-api"</code> when available, <code>"apple-script"</code> otherwise), and prefer Private API on macOS 26 even for plain text. Fixes silent delivery failure on macOS setups without Private API where an omitted <code>method</code> let BB Server fall back to version-dependent default behavior that silently drops the message (#64480), and the AppleScript <code>-1700</code> error on macOS 26 Tahoe plain text sends (#53159). (#69070) Thanks @xqing3.</li>
<li>Matrix/commands: recognize slash commands that are prefixed with the bot's Matrix mention, so room messages like <code>@bot:server /new</code> trigger the command path without requiring custom mention regexes. (#68570) Thanks @nightq and @johnlanni.</li>
<li>Gateway/pairing: return reason-specific <code>PAIRING_REQUIRED</code> details, remediation hints, and request ids so unapproved-device and scope-upgrade failures surface actionable recovery guidance in the CLI and Control UI. (#69227) Thanks @obviyus.</li>
<li>Agents/subagents: include requested role and runtime timing on subagent failure payloads so parent agents can correlate failed or timed-out child work. (#68726) Thanks @BKF-Gitty.</li>
<li>Gateway/sessions: reject stale agent-scoped sessions after an agent is removed from config while preserving legacy default-agent main-session aliases. (#65986) Thanks @bittoby.</li>
<li>Doctor/gateway: surface pending device pairing requests, scope-upgrade approval drift, and stale device-token mismatch repair steps so <code>openclaw doctor --fix</code> no longer leaves pairing/auth setup failures unexplained. (#69210) Thanks @obviyus.</li>
<li>Cron/isolated-agent: preserve explicit <code>delivery.mode: "none"</code> message targets for isolated runs without inheriting implicit <code>last</code> routing, so agent-initiated Telegram sends keep their authored destination while bare <code>mode:none</code> jobs stay targetless. (#69153) Thanks @obviyus.</li>
<li>Cron/isolated-agent: keep <code>delivery.mode: "none"</code> account-only or thread-only configs from inheriting a stale implicit recipient, so isolated runs only resolve message routing when the job authored an explicit <code>to</code> target. (#69163) Thanks @obviyus.</li>
<li>Gateway/TUI: retry session history while the local gateway is still finishing startup, so <code>openclaw tui</code> reconnects no longer fail on transient <code>chat.history unavailable during gateway startup</code> errors. (#69164) Thanks @shakkernerd.</li>
<li>BlueBubbles/reactions: fall back to <code>love</code> when an agent reacts with an emoji outside the iMessage tapback set (<code>love</code>/<code>like</code>/<code>dislike</code>/<code>laugh</code>/<code>emphasize</code>/<code>question</code>), so wider-vocabulary model reactions like <code>👀</code> still produce a visible tapback instead of failing the whole reaction request. Configured ack reactions still validate strictly via the new <code>normalizeBlueBubblesReactionInputStrict</code> path. (#64693) Thanks @zqchris.</li>
<li>BlueBubbles: prefer iMessage over SMS when both chats exist for the same handle, honor explicit <code>sms:</code> targets, and never silently downgrade iMessage-available recipients. (#61781) Thanks @rmartin.</li>
<li>Telegram/setup: require numeric <code>allowFrom</code> user IDs during setup instead of offering unsupported <code>@username</code> DM resolution, and point operators to <code>from.id</code>/<code>getUpdates</code> for discovery. (#69191) Thanks @obviyus.</li>
<li>GitHub Copilot/onboarding: default GitHub Copilot setup to <code>claude-opus-4.6</code> and keep the bundled default model list aligned, so new Copilot setups no longer start on the older <code>gpt-4o</code> default. (#69207) Thanks @obviyus.</li>
<li>Gateway/status: separate reachability, capability, and read-probe reporting so connect-only or scope-limited sessions no longer look fully healthy, and normalize SSH targets entered as <code>ssh user@host</code>. (#69215) Thanks @obviyus.</li>
<li>Slack: fix outbound replies failing with "unresolved SecretRef" for accounts configured via <code>file</code> or <code>exec</code> secret sources; the send path now tolerates the runtime snapshot retaining an unresolved channel SecretRef when a boot-resolved token override is already available. (#68954) Thanks @openperf.</li>
<li>Control UI/device pairing: explain scope and role approval upgrades during reconnects, and show requested versus approved access in the Control UI and <code>openclaw devices</code> so broader reconnects no longer look like lost pairings. (#69221) Thanks @obviyus.</li>
<li>Gateway/Control UI: surface pending scope, role, and device-metadata pairing approvals in auth errors and Control UI hints so broader reconnects no longer look like random auth breakage. (#69226) Thanks @obviyus.</li>
<li>Agents/LSP: terminate bundled stdio LSP process trees during runtime disposal and Gateway shutdown, so nested children such as <code>tsserver</code> do not survive stop or restart. Fixes #72357. Thanks @ai-hpc and @bittoby.</li>
<li>Gateway/device tokens: stop echoing rotated bearer tokens from shared/admin <code>device.token.rotate</code> responses while preserving the same-device token handoff needed by token-only clients before reconnect. (#66773) Thanks @MoerAI.</li>
<li>Control UI/Talk: keep Google Live browser sessions on the WebSocket transport instead of falling back to WebRTC, validate browser Google Live WebSocket endpoints, cap Gateway relay sessions per browser connection, and remove stale browser-native voice buttons that did not use the configured Talk/TTS provider. Thanks @BunsDev.</li>
<li>Gateway/startup: reuse config snapshot plugin manifests for startup auto-enable, config validation, and plugin bootstrap planning, including authored source config and disabled setup-probe handling, so restrictive allowlists avoid duplicate manifest/config passes during boot. Thanks @shakkernerd.</li>
<li>Agents/subagents: enforce <code>subagents.allowAgents</code> for explicit same-agent <code>sessions_spawn(agentId=...)</code> calls instead of auto-allowing requester self-targets. Fixes #72827. Thanks @oiGaDio.</li>
<li>ACP/sessions_spawn: let explicit <code>sessions_spawn(runtime="acp")</code> bootstrap turns run while <code>acp.dispatch.enabled=false</code> still blocks automatic ACP thread dispatch. Fixes #63591. Thanks @moeedahmed.</li>
<li>CLI/update: install npm global updates into a verified temporary prefix before swapping the package tree into place, preventing mixed old/new installs and stale packaged files from breaking <code>openclaw update</code> verification. Thanks @shakkernerd.</li>
<li>Gateway: skip CLI startup self-respawn for foreground gateway runs so low-memory Linux/Node 24 hosts start through the same path as direct <code>dist/index.js</code> without hanging before logs. Fixes #72720. Thanks @sign-2025.</li>
<li>Google Meet: route local Chrome joins through OpenClaw browser control, grant Meet media permissions, pin local Chrome audio defaults to <code>BlackHole 2ch</code>, and use the configured OpenClaw browser profile so joined agents no longer show <code>Permission needed</code> or use raw/default Chrome state. Thanks @DougButdorf and @oromeis.</li>
<li>Plugins/discovery: follow symlinked plugin directories in global and workspace plugin roots while keeping broken links ignored and existing package safety checks in place. Fixes #36754; carries forward #72695 and #63206. Thanks @Quackstro, @ming1523, and @xsfX20.</li>
<li>Plugins/install: skip test files and directories during install security scans while still force-scanning declared runtime entrypoints, so packaged test mocks no longer block plugin installs. Fixes #66840; carries forward #67050. Thanks @saurabhjain1592 and @Magicray1217.</li>
<li>Plugins/install: allow exact package-manager peer links back to the trusted OpenClaw host package during install security scans while continuing to block spoofed or nested escaping <code>node_modules</code> symlinks. Carries forward #70819. Thanks @fgabelmannjr.</li>
<li>Plugins/install: resolve plugin install destinations from the active profile state dir across CLI, ClawHub, marketplace, local path, and channel setup installs, so <code>openclaw --profile <name> plugins install ...</code> no longer writes into the default profile. Fixes #69960; carries forward #69971. Thanks @FrancisLyman and @Sanjays2402.</li>
<li>Plugins/registry: suppress duplicate-plugin startup warnings when a tracked npm-installed plugin intentionally overrides the bundled plugin with the same id. Carries forward #48673. Thanks @abdushsk.</li>
<li>Plugins/startup: reuse canonical realpath lookups throughout each plugin discovery pass, including package and manifest boundary checks, so Windows npm-global startups no longer repeat expensive path resolution for the same plugin roots. Fixes #65733. Thanks @welfo-beo.</li>
<li>Gateway/proxy: pass <code>ALL_PROXY</code> / <code>all_proxy</code> into the global Undici env-proxy dispatcher and provider proxy-fetch helper while keeping SSRF trusted-proxy auto-upgrade on <code>HTTP_PROXY</code> / <code>HTTPS_PROXY</code> only, so gateway/provider calls honor all-proxy setups without weakening guarded fetches. Fixes #43821; carries forward #43919. Thanks @RickyTong1.</li>
<li>Reply/link understanding: keep media and link preprocessing on stable runtime entrypoints and continue with raw message content if optional enrichment fails, so URL-bearing messages are no longer dropped after stale runtime chunk upgrades. Fixes #68466. Thanks @songshikang0111.</li>
<li>Discord: persist routed model-picker overrides when the hidden <code>/model</code> dispatch succeeds but the bound thread session store is still stale, including LM Studio suffixed model ids. Carries forward #61473. Thanks @Nanako0129.</li>
<li>Nodes/CLI: add <code>openclaw nodes remove --node <id|name|ip></code> and <code>node.pair.remove</code> so stale gateway-owned node pairing records can be cleaned without hand-editing state files.</li>
<li>Gateway: include the connecting client and fresh presence version in the initial <code>hello-ok</code> snapshot, so clients no longer need a follow-up event before seeing themselves online.</li>
<li>Docker: install the CA certificate bundle in the slim runtime image so HTTPS calls from containerized gateways no longer fail TLS setup after the <code>bookworm-slim</code> base switch. Fixes #72787. Thanks @ryuhaneul.</li>
<li>Providers/OpenRouter: remove retired Hunter Alpha and Healer Alpha static catalog rows and disable proxy reasoning injection for stale Hunter Alpha configs, so replies are not hidden when OpenRouter returns answer text in reasoning fields. Fixes #43942. Thanks @EvanDataForge.</li>
<li>Providers/reasoning: let Groq and LM Studio declare provider-native reasoning effort values, so Qwen thinking models receive <code>none</code>/<code>default</code> or <code>off</code>/<code>on</code> instead of OpenAI-only <code>low</code>/<code>medium</code> values. Fixes #32638. Thanks @Aqu1bp, @mgoulart, @Norpps, and @BSTail.</li>
<li>Local models: default custom providers with only <code>baseUrl</code> to the Chat Completions adapter and trust loopback model requests automatically, so local OpenAI-compatible proxies receive <code>/v1/chat/completions</code> without timing out. Fixes #40024. Thanks @parachuteshe.</li>
<li>Channels/message tool: surface Discord, Slack, and Mattermost <code>user:</code>/<code>channel:</code> target syntax in the shared message target schema and Discord ambiguity errors, so DM sends by numeric id stop burning retries before finding <code>user:<id></code>. Fixes #72401. Thanks @garyd9, @hclsys, and @praveen9354.</li>
<li>Agents/tools: scope tool-loop detection history to the active run when available, so scheduled heartbeat cycles no longer inherit stale repeated-call counts from previous runs. Fixes #40144. Thanks @mattbrown319.</li>
<li>Agents/subagents: preserve requester delivery for completion announces across different channel accounts, keep same-channel thread completions routed to the child thread, and fail closed instead of guessing a child binding when requester conversation signal is missing. Thanks @sfuminya and @suyua9.</li>
<li>Agents/status: persist the post-compaction token estimate from auto-compaction when providers omit usage metadata, so <code>/status</code> and session lists keep showing fresh context usage after compaction. Fixes #67667; carries forward #72822. Thanks @Jimmy-xuzimo and @skylight-9.</li>
<li>Control UI: show loading, reload, and retry states when a lazy dashboard panel cannot load after an upgrade, so the Logs tab no longer appears blank on stale browser bundles. Fixes #72450. Thanks @sobergou.</li>
<li>Gateway/plugins: start the Gateway in degraded mode when a single plugin entry has invalid schema config, and let <code>openclaw doctor --fix</code> quarantine that plugin config instead of crash-looping every channel. Fixes #62976 and #70371. Thanks @Doraemon-Claw and @pksidekyk.</li>
<li>Agents/plugins: skip malformed plugin tools with missing schema objects and report plugin diagnostics, so one broken tool no longer crashes Anthropic agent runs. Fixes #69423. Thanks @jmnickels.</li>
<li>Agents/reasoning: recover fully wrapped unclosed <code><think></code> replies that would otherwise sanitize to empty text while keeping strict stripping for closed reasoning blocks and unclosed tails after visible text. Fixes #37696; supersedes #51915. Thanks @druide67 and @okuyam2y.</li>
<li>Control UI/Gateway: bind WebChat handshakes to their active socket and reject post-close server registrations, so aborted connects no longer leave zombie clients or misleading duplicate WebSocket connection logs. Fixes #72753. Thanks @LumenFromTheFuture.</li>
<li>Agents/fallback: split ambiguous provider failures into <code>empty_response</code>, <code>no_error_details</code>, and <code>unclassified</code>, and add flat fallback-step fields to structured fallback logs so primary-model failures stay visible when later fallbacks also fail. Fixes #71922; refs #71744. Thanks @andyk-ms and @nikolaykazakovvs-ux.</li>
<li>Plugins/Windows: normalize Windows absolute paths before handing bundled plugin modules to Jiti, so Feishu/Lark message sending no longer fails with unsupported <code>c:</code> ESM loader URLs. Fixes #72783. Thanks @jackychen-png.</li>
<li>CLI/doctor: run bundled plugin runtime-dependency repairs through the async npm installer with spinner/line progress and heartbeat updates, so long <code>openclaw doctor --fix</code> installs no longer look hung in TTY or piped output. Fixes #72775. Thanks @dfpalhano.</li>
<li>Feishu/Windows: normalize bundled channel sidecar loads before Jiti evaluates them, so Feishu outbound sends no longer fail with raw <code>C:</code> ESM loader errors on Windows. Fixes #72783. Thanks @jackychen-png.</li>
<li>Agents/tools: ignore volatile <code>exec</code> runtime metadata when comparing tool-loop outcomes, so enabled loop detection can stop repeated identical shell-command results instead of resetting on duration, PID, session, or cwd changes. Fixes #34574; supersedes #41502. Thanks @gucasbrg and @Zcg2021.</li>
<li>Agents/fallback: classify internal live-session model switch conflicts as unknown fallback failures instead of provider overloads, preventing local vLLM endpoints from receiving misleading overloaded cooldowns. Refs #63229. Thanks @clawdia-lobster.</li>
<li>Discord: let thread sessions inherit the parent channel's session-level <code>/model</code> override as a model-only fallback without enabling parent transcript inheritance. Fixes #72755. Thanks @solavrc.</li>
<li>Gateway/plugins: skip stale configured channels whose matching plugin is no longer discoverable, point cleanup at <code>openclaw doctor --fix</code>, and keep unrelated channel typos fatal so one missing channel plugin no longer crash-loops the Gateway. Fixes #53311. Thanks @futhgar.</li>
<li>Control UI: keep session-specific assistant identity loads authoritative after WebSocket connect, so non-main agent chat sessions do not show the main agent name in the header after bootstrap refreshes. Fixes #72776. Thanks @rockytian-top.</li>
<li>Agents/Qwen: preserve exact custom <code>modelstudio</code> provider configs with foreign <code>api</code> owners so explicit OpenAI-compatible Model Studio endpoints no longer get normalized into the bundled Qwen plugin path. Fixes #64483. Thanks @FiredMosquito831.</li>
<li>MCP/bundle-mcp: normalize CLI-native <code>type: "http"</code> MCP server entries to OpenClaw <code>transport: "streamable-http"</code> on save, repair existing configs with doctor, and keep embedded Pi from falling back to legacy SSE GET-first startup for those servers. Fixes #72757. Thanks @Studioscale.</li>
<li>OpenCode: expose Anthropic Opus/Sonnet 4.x thinking levels for proxied Claude models, so <code>/think xhigh</code>, <code>/think adaptive</code>, and <code>/think max</code> validate consistently with the direct Anthropic provider. Fixes #72729. Thanks @haishmg and @aaajiao.</li>
<li>Media-understanding/audio: migrate deprecated <code>{input}</code> placeholders in legacy <code>audio.transcription.command</code> configs to <code>{{MediaPath}}</code>, so custom audio transcribers no longer receive the literal placeholder after doctor repair. Fixes #72760. Thanks @krisfanue3-hash.</li>
<li>Ollama/WSL2: warn when GPU-backed WSL2 installs combine CUDA visibility with an autostarting <code>ollama.service</code> using <code>Restart=always</code>, and document the systemd, <code>.wslconfig</code>, and keep-alive mitigation for crash loops. Carries forward #61022; fixes #61185. Thanks @yhyatt.</li>
<li>Ollama/onboarding: de-dupe suggested bare local models against installed <code>:latest</code> tags and skip redundant pulls, so setup shows the installed model once and no longer says it is downloading an already available model. Fixes #68952. Thanks @tleyden.</li>
<li>Memory-core/doctor: keep <code>doctor.memory.status</code> on the cached path by default and only run live embedding pings for explicit deep probes, preventing slow local embedding backends from blocking Gateway status checks. Fixes #71568. Thanks @apex-system.</li>
<li>Memory/QMD: group same-source collections into one QMD search invocation when the installed QMD supports multiple <code>-c</code> filters, while keeping older QMD builds on the per-collection fallback. Fixes #72484; supersedes #72485 and #69583. Thanks @BsnizND and @zeroaltitude.</li>
<li>Memory/QMD: accept QMD status vector-count variants such as <code>Vectors = 42</code>, <code>Vectors:42</code>, and <code>Vectors: 42 embedded</code>, so <code>memory status --deep</code> no longer reports embeddings unavailable for healthy QMD wrappers. Fixes #63652; carries forward #63678. Thanks @apoapostolov and @WarrenJones.</li>
<li>Memory/QMD: skip QMD vector status probes and embedding maintenance in lexical <code>searchMode: "search"</code>, so BM25-only QMD setups on ARM do not trigger llama.cpp/Vulkan builds during status checks or embed cycles. Fixes #59234 and #67113. Thanks @PrinceOfEgypt, @Vksh07, @Snipe76, @NomLom, @t4r3e2q1-commits, and @dmak.</li>
<li>Memory/QMD: report the live watcher dirty state in memory status, so changed QMD-backed memory files show as dirty until the queued sync finishes. Fixes #60244. Thanks @xinzf.</li>
<li>Compaction: skip oversized pre-compaction checkpoint snapshots and prune duplicate long user turns from compaction input and rotated successor transcripts, preventing retry storms from being preserved across checkpoint cycles. Fixes #72780. Thanks @SweetSophia.</li>
<li>Control UI/Cron: render cron job prompts and run summaries as sanitized markdown in the dashboard, with full-width block content, safer link clicks, and no duplicate error text when a failed run has no summary. Supersedes #48504. Thanks @garethdaine.</li>
<li>Control UI/Gateway: preserve WebChat client version labels across localhost, 127.0.0.1, and IPv6 loopback aliases on the same port, avoiding misleading <code>vcontrol-ui</code> connection logs while investigating duplicate-message reports. Refs #72753 and #72742. Thanks @LumenFromTheFuture and @allesgutefy.</li>
<li>Agents/reasoning: treat orphan closing reasoning tags with following answer text as a privacy boundary across delivery, history, streaming, and Control UI sanitizers so malformed local-model output cannot leak chain-of-thought text. Fixes #67092. Thanks @AnildoSilva.</li>
<li>Memory-core: run one-shot memory CLI commands through transient builtin and QMD managers so <code>memory index</code>, <code>memory status --index</code>, and <code>memory search</code> no longer start long-lived file watchers that can hit macOS <code>EMFILE</code> limits. Fixes #59101; carries forward #49851. Thanks @mbear469210-coder and @maoyuanxue.</li>
<li>Agents/ACP: ship the Claude ACP adapter with OpenClaw and require Claude result messages before idle can complete a prompt, preventing parent agents from waking early on long-running <code>sessions_spawn(runtime: "acp", agentId: "claude")</code> children. Fixes #72080. Thanks @siavash-saki and @iannwu.</li>
<li>CLI/tasks: route <code>tasks --json</code>, <code>tasks list --json</code>, and <code>tasks audit --json</code> through a lean JSON path so read-only task inspection no longer loads unrelated plugin/runtime command graphs. Fixes #66238. Thanks @ChuckChambers.</li>
<li>Memory-core: re-resolve the active runtime config whenever <code>memory_search</code> or <code>memory_get</code> executes, so provider changes made by <code>config.patch</code> stop leaving stale embedding backends behind in existing tool instances. Fixes #61098. Thanks @BradGroux and @Linux2010.</li>
<li>WebChat: keep bare <code>/new</code> and <code>/reset</code> startup instructions out of visible chat history while preserving <code>/reset <note></code> as user-visible transcript text. Fixes #72369. Thanks @collynes and @haishmg.</li>
<li>Tasks/memory: checkpoint and truncate SQLite WAL sidecars on a timer and before close for task, Task Flow, proxy capture, and builtin memory databases, bounding long-running gateway <code>*.sqlite-wal</code> growth. Fixes #72774. Thanks @dfpalhano.</li>
<li>CLI/doctor: remove dangling channel config, heartbeat targets, and channel model overrides when stale plugin repair removes a missing channel plugin, preventing Gateway boot loops after failed plugin reinstalls. Fixes #65293. Thanks @yidecode.</li>
<li>Control UI/Gateway: cache, coalesce, stale-refresh, and invalidate effective tool inventory on channel registry changes while reusing the gateway-bound plugin registry and avoiding model/auth discovery, so chat runs no longer stall Control UI requests on repeated plugin/model setup. Fixes #72365; supersedes #72558. Thanks @Gabiii2398 and @1yihui.</li>
<li>Channels/setup: treat bundled channel plugins as already bundled during <code>channels add</code> and onboarding, enabling them without writing redundant <code>plugins.load.paths</code> entries or path install records. Fixes #72740. Thanks @iCodePoet.</li>
<li>WhatsApp: honor gateway <code>HTTPS_PROXY</code> / <code>HTTP_PROXY</code> env vars for QR-login WebSocket connections, while respecting <code>NO_PROXY</code>, so proxied networks no longer fall back to direct <code>mmg.whatsapp.net</code> connections that time out with 408. Fixes #72547; supersedes #72692. Thanks @mebusw and @SymbolStar.</li>
<li>Bonjour: default mDNS advertisements to the system hostname when it is DNS-safe, avoiding <code>openclaw.local</code> probing conflicts and Gateway restart loops on hosts such as <code>Lobster</code> or <code>ubuntu</code>. Fixes #72355 and #72689; supersedes #72694. Thanks @mscheuerlein-bot, @gcusms, @moyuwuhen601, @pavan987, @zml-0912, @hhq365, and @SymbolStar.</li>
<li>Agents/OpenAI-compatible: retry replay-safe empty <code>stop</code> turns once for <code>openai-completions</code> endpoints, so transient empty local backend responses no longer surface as “Agent couldn't generate a response” when a continuation succeeds, and restore <code>openclaw agent --model</code> for one-shot CLI runs. Fixes #72751. Thanks @moooV252.</li>
<li>Git hooks: skip ignored staged paths when formatting and restaging pre-commit files, so merge commits no longer abort when <code>.gitignore</code> newly ignores staged merged content. Fixes #72744. Thanks @100yenadmin.</li>
<li>Memory-core/dreaming: add a supported <code>dreaming.model</code> knob for Dream Diary narrative subagents, wired through phase config and the existing plugin subagent model-override trust gate. Refs #65963. Thanks @esqandil and @mjamiv.</li>
<li>Agents/Anthropic: remove trailing assistant prefill payloads when extended thinking is enabled, so Opus 4.7/Sonnet 4.6 requests do not fail Anthropic's user-final-turn validation. Fixes #72739. Thanks @superandylin.</li>
<li>Agents/vLLM/Qwen: add plugin-owned Qwen thinking controls for vLLM chat-template kwargs and DashScope-style top-level <code>enable_thinking</code> flags, including preserved thinking for agent loops. Fixes #72329. Thanks @stavrostzagadouris.</li>
<li>Memory-core/dreaming: treat request-scoped narrative fallback as expected, skip session cleanup when no subagent run was created, and remove duplicate phase-level cleanup so fallback no longer emits warning noise. Fixes #67152. Thanks @jsompis.</li>
<li>Agents/exec: apply configured <code>tools.exec.timeoutSec</code> to background, <code>yieldMs</code>, and node <code>system.run</code> commands when no per-call timeout is set, preventing auto-backgrounded and remote node commands from running indefinitely. Fixes #67600; supersedes #67603. Thanks @dlmpx and @kagura-agent.</li>
<li>Config/doctor: stop masking unknown-key validation diagnostics such as <code>agents.defaults.llm</code>, and have <code>openclaw doctor --fix</code> remove the retired <code>agents.defaults.llm</code> timeout block. Thanks @aidiffuser.</li>
<li>CLI/startup: keep the built pre-dispatch CLI graph free of package-level imports and extend packaged CLI smoke coverage to onboard and doctor help paths, preventing missing runtime dependencies such as tslog from killing onboarding before repair code can run. Fixes #63024. Thanks @hu19940121.</li>
<li>CLI/plugins: preserve unversioned ClawHub install specs so <code>plugins update</code> can follow newer ClawHub releases instead of pinning to the initially resolved version. Fixes #63010; supersedes #58426. Thanks @kangsen1234 and @robinspt.</li>
<li>Memory-core/subagents: tag plugin-created subagent sessions with their plugin owner so dreaming narrative cleanup can delete its own ephemeral sessions without granting broad admin session deletion. Fixes #72712. Thanks @BSG2000.</li>
<li>Gateway/models: move local-provider pricing opt-outs, OpenRouter/LiteLLM aliases, and proxy passthrough pricing lookup into plugin manifest metadata so core no longer carries extension-specific pricing tables.</li>
<li>CLI/update: honor <code>OPENCLAW_NO_AUTO_UPDATE=1</code> as a gateway startup kill-switch for configured background package auto-updates, so operators can hold a deliberate downgrade during incident recovery without editing config first. Fixes #72715. Thanks @Xivi08.</li>
<li>Agents/Claude CLI: force live-session launches to include <code>--output-format stream-json</code> whenever OpenClaw adds <code>--input-format stream-json</code>, so new Claude CLI sessions no longer fail immediately while reusable sessions keep working. Fixes #72206. Thanks @kwangwonkoh and @Xivi08.</li>
<li>CLI/plugins: accept ClawHub plugin API wildcard ranges such as <code>*</code> without rejecting compatible plugin installs, while still requiring a valid runtime API version. Fixes #56446; supersedes #56466. Thanks @darconada and @claygeo.</li>
<li>CLI/plugins: add an explicit <code>npm:<package></code> install prefix that skips ClawHub lookup for known npm packages while keeping bare package specs ClawHub-first. Fixes #55805; supersedes #54377. Thanks @Zeoy2020 and @vagusX.</li>
<li>CLI/plugins: let config-gated bundled plugins install without persisting invalid placeholder config entries, so install/uninstall sweeps can cover plugins such as memory-lancedb before the user configures credentials. Thanks @vincentkoc.</li>
<li>CLI/plugins: reject malformed ClawHub plugin specs with trailing <code>@</code> before registry lookup, so empty-version typos report as invalid specs instead of package-not-found errors. Fixes #56579; supersedes #56582. Thanks @Kansodata.</li>
<li>Agents/sessions: acquire the session write lock only after cold bootstrap, plugin, and tool setup so fallback runs are not blocked by stalled pre-model startup work.</li>
<li>Browser/plugins: auto-start the bundled browser plugin when root <code>browser</code> config is present, including restrictive plugin allowlists, and ignore stale persisted plugin registries whose package paths no longer exist.</li>
<li>Browser: circuit-break repeated managed Chrome launch failures per profile so browser requests stop spawning Chromium indefinitely when CDP cannot start. Fixes #64271. Thanks @TheophilusChinomona.</li>
<li>Gateway/models: skip external OpenRouter and LiteLLM pricing refreshes for local/self-hosted model endpoints so startup does not wait on remote pricing catalogs for local-only Ollama, vLLM, and compatible providers.</li>
<li>CLI/plugins: stop security-blocked plugin installs from retrying as hook packs, so normal plugin packages report the scanner failure without a misleading "not a valid hook pack" follow-up. Fixes #61175; supersedes #64102. Thanks @KonsultDigital and @ziyincody.</li>
<li>Agents/Anthropic: strip stale trailing assistant prefill turns from outbound replay so context-engine short circuits cannot send unsupported assistant-prefill payloads to provider APIs. Fixes #72556. Thanks @Veda-openclaw.</li>
<li>Agents/Google: strip stale trailing assistant/model prefill turns from Gemini outbound replay so Google Generative AI requests end with a user turn or function response. Follow-up to #72556. Thanks @Veda-openclaw.</li>
<li>Control UI/Dreaming: require explicit confirmation before applying restart-impacting Dreaming mode changes, with restart warning copy and loading feedback. Fixes #63804. (#63807) Thanks @bbddbb1.</li>
<li>CLI/agent: mark Gateway-to-embedded fallback runs with <code>meta.transport: "embedded"</code> and <code>meta.fallbackFrom: "gateway"</code> in JSON output, and make the terminal diagnostic explicit so scripts and operators can distinguish fallback runs from Gateway runs. Fixes #71416. Thanks @amknight.</li>
<li>Agents/tools: normalize <code>null</code> or missing tool-call arguments to <code>{}</code> for parameterless object schemas before Pi validation, so empty-argument tools run instead of failing argument validation. Fixes #72587. Thanks @amknight.</li>
<li>Agents/subagents: clear active embedded-run state before terminal lifecycle events so post-completion cleanup no longer treats finished child runs as still active and skips archive or announcement bookkeeping. (#70187) Thanks @amknight.</li>
<li>CLI/update: keep the automatic post-update completion refresh on the core-command tree so it no longer stages bundled plugin runtime deps before the Gateway restart path, avoiding <code>.24</code> update hangs and 1006 disconnect cascades. Fixes #72665. Thanks @sakalaboator and @He-Pin.</li>
<li>Control UI: make explicit Reload Config actions discard stale local config edits while passive refreshes and failed-save recovery keep pending drafts intact. Fixes #40352; carries forward #40443. Thanks @realmikechong-dotcom.</li>
<li>Agents/Bedrock: stop heartbeat runs from persisting blank user transcript turns and repair existing blank user text messages before replay, preventing AWS Bedrock <code>ContentBlock</code> blank-text validation failures. Fixes #72640 and #72622. Thanks @goldzulu.</li>
<li>Agents/LM Studio: promote standalone bracketed local-model tool requests into registered tool calls and hide unsupported bracket blocks from visible replies, so MemPalace MCP lookups do not print raw <code>[tool]</code> JSON scaffolding in chat. Fixes #66178. Thanks @detroit357.</li>
<li>Local models: warn when an assistant reply looks like a tool call but the provider emitted plain text instead of a structured tool invocation, making fake/non-executed tool calls visible in logs. Fixes #51332. Thanks @emilclaw.</li>
<li>Local models: accept persisted non-secret local auth markers for private-LAN custom OpenAI-compatible providers, so LAN Ollama configs no longer fail with missing auth when <code>ollama-local</code> is saved as the key. Fixes #49736. Thanks @charles-zh.</li>
<li>TUI/local models: treat visible gateway client labels such as <code>openclaw-tui</code> as the current requester session for session-aware tools, so Ollama tool calls no longer fail by resolving the UI label as a session id. Fixes #66391. Thanks @kickingzebra.</li>
<li>Local models: route self-hosted OpenAI-compatible model discovery through the guarded fetch path pinned to the configured host, covering vLLM and SGLang setup without reopening local/LAN SSRF probes. Supersedes #46359. Thanks @cdxiaodong.</li>
<li>Local models: classify terminated, reset, closed, timeout, and aborted model-call failures and attach a process memory snapshot to the diagnostic event, making LM Studio/Ollama RAM-pressure failures easier to prove from stability bundles. Refs #65551. Thanks @BigWiLLi111.</li>
<li>Local models: pass configured provider request timeouts through OpenAI SDK transports and the model idle watchdog so long-running local or custom OpenAI-compatible streams use one timeout knob instead of hitting the SDK's 10-minute default or the 120s idle default. Fixes #63663. Thanks @aidiffuser.</li>
<li>LM Studio: trust configured LM Studio loopback, LAN, and tailnet endpoints for guarded model requests by default, preserving explicit private-network opt-outs. Refs #60994. Thanks @tnowakow.</li>
<li>Docker/setup: route Docker onboarding defaults for host-side LM Studio and Ollama through <code>host.docker.internal</code> and add the Linux host-gateway mapping to the bundled Compose file, so containerized gateways can reach local providers without using container loopback. Fixes #68684; supersedes #68702. Thanks @safrano9999 and @skolez.</li>
<li>Agents/LM Studio: strip prior-turn Gemma 4 reasoning from OpenAI-compatible replay while preserving active tool-call continuation reasoning. Fixes #68704. Thanks @chip-snomo and @Kailigithub.</li>
<li>LM Studio: allow interactive onboarding to leave the API key blank for unauthenticated local servers, using local synthetic auth while clearing stale LM Studio auth profiles. Fixes #66937. Thanks @olamedia.</li>
<li>Plugins/startup/registry: reuse a Gateway <code>PluginLookUpTable</code> and one manifest registry pass across startup plugin IDs, plugin loading, deferred channel reloads, model pricing, read-only channel defaults, capability/provider/media resolution, manifest contracts, extractors, web fallback discovery, owner maps, and cold provider-discovery caches, with new startup-trace timing/count metrics for installed-index, manifest, startup-plan, and owner-map work. Thanks @shakkernerd and @mcaxtr.</li>
<li>Mattermost: keep direct-message replies top-level by suppressing reply roots for DM delivery while preserving channel and group thread roots, and derive inbound chat kind from the trusted channel lookup instead of the websocket event channel type. Carries forward #60115, #55186, #72305, and #72659; refs #59758, #59981, #59791, and #57565. Thanks @vincentkoc, @jwchmodx, and @hnykda.</li>
<li>Docker: pre-create <code>/home/node/.openclaw</code> with node ownership and private permissions so first-run Docker Compose named volumes no longer fail startup with EACCES. (#48072, #63959; fixes #61279) Thanks @timoxue and @jeanibarz.</li>
<li>CLI/Gateway: treat local restart probe policy closes for connect, exact <code>device required</code>, pairing, and auth failures as Gateway reachability proof without accepting empty, broad standalone token/password/scope/role, or pair-substring 1008 close reasons. Fixes #48771; carries forward #48801; related #63491. Thanks @MarsDoge and @genoooool.</li>
<li>Feishu: send outgoing interactive reply payloads as native cards with clickable buttons while preserving text, media, and document-comment fallbacks. Fixes #13175 and #58298; carries forward #47891. Thanks @Horacehxw.</li>
<li>Process/Windows: decode command stdout and stderr from raw bytes with console-codepage awareness, while preserving valid UTF-8 output and multibyte characters split across chunks. Fixes #50519. Thanks @iready, @kevinten10, @zhangyongjie1997, @knightplat-blip, @heiqishi666, and @slepybear.</li>
<li>Bonjour/Windows: hide the bundled mDNS advertiser's Windows ARP shell probe so Gateway startup no longer flashes command-prompt windows. Fixes #70238. Thanks @alexandre-leng, @PratikRai0101, @infinitypacific, and @tomerpeled.</li>
<li>Agents/bootstrap: dedupe hook-injected bootstrap context files by workspace-relative path and store normalized resolved paths so duplicate relative and absolute hook paths no longer depend on the process cwd. (#59344; fixes #59319; related #56721, #56725, and #57587) Thanks @koen666.</li>
<li>Agents/bootstrap: refresh cached workspace bootstrap snapshots on long-lived main-session turns when <code>AGENTS.md</code>, <code>SOUL.md</code>, <code>MEMORY.md</code>, or <code>TOOLS.md</code> change on disk, while preserving unchanged snapshot identity through the workspace file cache. (#64871; related #43901, #26497, #28594, #30896) Thanks @aimqwest and @mikejuyoon.</li>
<li>macOS Gateway: detect installed-but-unloaded LaunchAgent split-brain states during status, doctor, and restart, and re-bootstrap launchd supervision before falling back to unmanaged listener restarts. Fixes #67335, #53475, and #71060; refs #58890, #60885, and #70801. Thanks @ze1tgeist88, @dafacto, and @vishutdhar.</li>
<li>Plugins/install: treat mirrored core logger dependencies as staged bundled runtime deps so packaged Gateway starts do not crash when the external plugin-runtime-deps root is missing <code>tslog</code>. Fixes #72228; supersedes #72493. Thanks @deepujain.</li>
<li>Build/plugins: preserve active bundled runtime-dependency staging temp directories owned by live build processes so overlapping postbuild runs no longer delete each other's staged deps mid-prune. Supersedes #72220. Thanks @VACInc.</li>
<li>Plugins/install: hide bundled runtime-dependency npm child windows on Windows across Gateway startup, postinstall, and packaged staging paths so Telegram/Anthropic dependency repair no longer flashes shell windows. Fixes #72315. Thanks @athuljayaram and @joshfeng.</li>
<li>Agents/Windows: normalize lazy agent runtime imports before Node ESM loading so Windows drive-letter <code>subagent-registry</code> runtime paths no longer fail every agent task with <code>ERR_UNSUPPORTED_ESM_URL_SCHEME</code>. Fixes #72636; carries forward #72716. Thanks @Andyz-CData and @xialonglee.</li>
<li>Plugins/Windows: normalize lazy plugin service override imports before Node ESM loading so drive-letter browser-control module paths no longer fail with <code>ERR_UNSUPPORTED_ESM_URL_SCHEME</code>. Fixes #72573; supersedes #72599 and #72582. Thanks @llzzww316, @feineryonah-byte, and @WuKongAI-CMU.</li>
<li>Browser/plugins: load <code>playwright-core</code> through the browser runtime shim so packaged installs can run Playwright actions from staged plugin runtime deps after doctor/startup repair. Fixes #72168; supersedes #72238. Thanks @zdg1110 and @yetval.</li>
<li>Plugins/install: stage bundled plugin runtime dependencies before Gateway startup, drain update restarts, and materialize plugin-owned root chunks in external mirrors so staged deps resolve under native ESM. Fixes #72058; supersedes #72084. Thanks @amnesia106 and @drvoss.</li>
<li>TTS/SecretRef: resolve <code>messages.tts.providers.*.apiKey</code> from the active runtime snapshot so SecretRef-backed MiniMax and other TTS provider keys work in runtime reply/audio paths. Fixes #68690. Thanks @joshavant.</li>
<li>Gateway/install: surface systemd user-bus recovery hints during Linux service activation and retry via the target user scope when <code>systemctl --user</code> reports no-medium bus failures, without letting stale <code>SUDO_USER</code> override <code>sudo -u</code> installs. Fixes #39673; refs #44417 and #63561. Thanks @Arbor4, @myrsu, @mssteuer, and @boyuaner.</li>
<li>CLI/nodes: make unfiltered <code>openclaw nodes list</code> prefer the effective paired-node view used by <code>nodes status</code> while preserving pending rows, pairing-scope fallback, terminal-safe table rendering, and paired JSON metadata. Fixes #46871; carries forward #65772 through the ProjectClownfish #72619 repair. Thanks @skainguyen1412.</li>
<li>CLI/startup: read generated startup metadata from the bundled <code>dist</code> layout before falling back to live help rendering, so root/browser help and channel-option bootstrap stay on the fast path. Thanks @vincentkoc.</li>
<li>Feishu/Lark: stop treating broadcast-only <code>@all</code>/<code>@_all</code> messages as bot mentions while preserving direct bot mentions, including messages that also include <code>@all</code>. Fixes #37706. Thanks @JosepLee.</li>
<li>CLI/help: treat positional <code>help</code> invocations like <code>openclaw channels help</code> as help paths for startup gating, avoiding model/auth warmup while preserving positional arguments such as <code>openclaw docs help</code>. Thanks @gumadeiras.</li>
<li>Web search: route plugin-scoped web_search SecretRefs through the active runtime config snapshot so provider execution receives resolved credentials across app/runtime paths, including <code>plugins.entries.brave.config.webSearch.apiKey</code>. Fixes #68690. Thanks @VACInc.</li>
<li>Voice Call: allow SecretRef-backed Twilio auth tokens and call-specific OpenAI/ElevenLabs TTS API keys through the plugin config surface. Fixes #68690. Thanks @joshavant.</li>
<li>Google Meet/Voice Call: clean stale chrome-node realtime bridges before rejoining, expose bridge inspection, tolerate transient node input pull failures, default Chrome command-pair audio to 24 kHz PCM16 while preserving legacy 8 kHz G.711 mu-law pairs, handle Gemini Live interruptions/VAD and function-response names correctly, route stateful <code>google_meet</code> tools through the gateway runtime, support <code>realtime.agentId</code>, and send non-blocking consult continuations before long tool-backed answers finish. Fixes #72371, #72525, #72523, #72440, and #72425; (#72372, #72524, #72381, #72441, #72189, #72426) Thanks @BsnizND and @VACInc.</li>
<li>Discord/media: keep incidental Markdown image badges in final replies as text unless a channel opts into Markdown-image media extraction, while preserving Telegram Markdown-image media replies and explicit <code>MEDIA:</code> attachments. Fixes #72642. Thanks @solavrc and @Bartok9.</li>
<li>Matrix/E2EE: stabilize recovery and broken-device QA flows while avoiding Matrix device-cleanup sync races that could leave shutdown-time crypto work running. Thanks @gumadeiras.</li>
<li>Cron: apply <code>cron.maxConcurrentRuns</code> to the nested isolated-agent lane, start isolated execution timeouts only after the runner enters that lane, keep legacy flat <code>jobs.json</code> rows loadable, invalidate stale pending runtime slots after schedule edits, and preserve due slots for formatting-only rewrites. Fixes #72707, #27996, #71607, and #41783; carries forward #71651. Thanks @kagura-agent, @xialonglee, @fagnersouza666, @ayanesakura, and @Hurray0.</li>
<li>Cron/delivery: classify isolated successes, quiet <code>NO_REPLY</code> turns, model/provider failures, execution denials, <code>--no-deliver</code> traces, skipped-job alerts, and verified delivery outcomes correctly so cron history, retries, and failure counters reflect what actually happened. Fixes #72732, #50170, #43604, #68452, #60846, #72210, and #67172; follow-up to #54188; carries forward #43631, #68453, #72219, and #67186. Thanks @zNatix, @pixeldyn, @ChickenEggRoll, @SPFAdvisors, @anyech, @slideshow-dingo, @hatemclawbot-collab, @xydigit-sj, @oc-gh-dr, @hclsys, and @1yihui.</li>
<li>Cron/routing: preserve direct Telegram thread/account IDs, explicit Discord <code>user:</code>/<code>channel:</code> delivery targets, and <code>session:<id></code> failure-destination routing so reminders, cron announcements, and failure alerts keep the intended recipient kind across direct and group chats. Fixes #44270; refs #62777; carries forward #44325, #44351, #44412, #72657, #68535, and #62798. Thanks @RunMintOn, @arkyu2077, @0xsline, @vincentkoc, @slideshow-dingo, @likewen-tech, and @neeravmakwana.</li>
<li>Subagents: keep the delegated task only in the subagent system prompt and send a short initial kickoff message, avoiding duplicate task tokens while preserving multiline task formatting. Fixes #72019; carries forward #72053. Thanks @Wizongod and @ly85206559.</li>
<li>Onboarding/GitHub Copilot: add manifest-owned <code>--github-copilot-token</code> support for non-interactive setup, including env fallback, tokenRef storage in ref mode, saved-profile reuse, and current Copilot default-model wiring. Refs #50002 and supersedes #50003. Thanks @scottgl9.</li>
<li>Gateway/install: add a validated <code>--wrapper</code>/<code>OPENCLAW_WRAPPER</code> service install path that persists executable LaunchAgent/systemd wrappers across forced reinstalls, updates, and doctor repairs instead of falling back to raw node/bun <code>ProgramArguments</code>. Fixes #69400. (#72445) Thanks @willtmc.</li>
<li>Plugins: fail plugin registration when loader-owned acceptance gates reject missing hook names or memory-only capability registration from non-memory plugins, surfacing the issue through plugin status and doctor instead of silently dropping the registration. Fixes #72459. Thanks @amknight.</li>
<li>macOS Gateway: write launchd services with a state-dir <code>WorkingDirectory</code>, use a durable state-dir temp path instead of freezing macOS session <code>TMPDIR</code>, create that temp directory before bootstrap, and label abort-shaped launchd exits as <code>SIGABRT/abort</code> in status output. Fixes #53679 and #70223; refs #71848. Thanks @dlturock, @stammi922, and @palladius.</li>
<li>Control UI/update: make <code>Update now</code> require a real gateway process replacement, report skipped/error update outcomes with stable reasons, and verify the running gateway version after restart so global installs cannot silently keep old code in memory. Fixes #62492; addresses #64892 and #63562. Thanks @IAMSamuelRodda.</li>
<li>Exec approvals: accept runtime-owned <code>source: "allow-always"</code> and <code>commandText</code> allowlist metadata in gateway and node approval-set payloads so Control UI round-trips no longer fail with <code>unexpected property 'source'</code>. Fixes #60000; carries forward #60064. Thanks @sd1471123, @sharkqwy, and @luoyanglang.</li>
<li>Exec/node: skip approval-plan preparation for full-trust <code>host=node</code> runs so interpreter and script commands no longer fail with <code>SYSTEM_RUN_DENIED: approval cannot safely bind</code> when effective policy is <code>security=full</code> and <code>ask=off</code>. Fixes #48457 and duplicate #69251. Thanks @ajtran303, @jaserNo1, @Blakeshannon, @lesliefag, and @AvIsBeastMC.</li>
<li>Exec/node: synthesize a local approval plan when a paired node advertises <code>system.run</code> without <code>system.run.prepare</code>, unblocking approval-required <code>host=node</code> exec on current macOS companion nodes while preserving remote prepare for node hosts that support it. Fixes #37591 and duplicate #66839; carries forward #69725. Thanks @soloclz.</li>
<li>Memory/QMD: prefer QMD's <code>--mask</code> collection pattern flag so root memory indexing stays scoped to <code>MEMORY.md</code> instead of widening to every markdown file in the workspace. Fixes #65480; supersedes #65481 and #66259. Thanks @ccage-simp, @Bortlesboat, @seank-com, and @crazyscience.</li>
<li>Memory/doctor: treat the specific <code>gateway timeout after ...</code> gateway memory probe result as inconclusive instead of reporting embeddings not ready, while preserving warnings for explicit failures. Fixes #44426; carries forward #46576 with the Greptile review feedback applied. Thanks Cengiz (@ghost).</li>
<li>Gateway/startup: defer QMD, core request handlers, setup wizard, CLI outbound senders, plugin HTTP routes, chat/session projection, node session runtime validation, embedded-run activity reads, MCP loopback server imports, channel runtime helpers, HTTP/canvas/plugin auth helpers, isolated cron imports, and hook dispatch parsing until their request or shutdown paths, while making plain <code>gateway status</code> use a parse-only config snapshot so no-plugin boots and status reads avoid broad runtime fanout. Thanks @vincentkoc.</li>
<li>Lobster/Gateway: memoize repeated Ajv schema compilation before loading the embedded Lobster runtime so scheduled workflows and <code>llm.invoke</code> loops stop growing gateway heap on content-identical schemas. Fixes #71148. Thanks @cmi525, @vsolaz, and @vincentkoc.</li>
<li>Codex harness: normalize cached input tokens before session/context accounting so prompt cache reads are not double-counted in <code>/status</code>, <code>session_status</code>, or persisted <code>sessionEntry.totalTokens</code>. Fixes #69298. Thanks @richardmqq.</li>
<li>Hooks/session-memory: use the host local timezone for memory filenames, fallback timestamp slugs, and markdown headers instead of UTC dates. Fixes #46703. (#46721) Thanks @Astro-Han.</li>
<li>Gateway health: preserve live runtime-backed channel/account state in <code>gateway.health</code> snapshots and cached refreshes while keeping raw probe payloads on sensitive/admin paths only. (#39921, #42586, #46527, #52770, #42543) Thanks @FAL1989, @rstar327, @0xble, and @ajayr.</li>
<li>Feishu: extract quoted/replied interactive-card text across schema 1.0, schema 2.0, i18n, template-variable, and post-format fallback shapes without carrying broad generated/config churn from related parser experiments. (#38776, #60383, #42218, #45936) Thanks @lishuaigit, @lskun, @just2gooo, and @Br1an67.</li>
<li>Telegram/agents: hide raw failed write/edit warning messages in Telegram when the assistant already explicitly acknowledges the failed action, while keeping warnings when the reply claims success or omits the failure; #39406 remains the broader configurable delivery-policy follow-up. Fixes #51065; covers #39631. Thanks @Bartok9 and @Bortlesboat.</li>
<li>Exec approvals: accept a symlinked <code>OPENCLAW_HOME</code> as the trusted approvals root while still rejecting symlinked <code>.openclaw</code> path components below it. (#64663) Thanks @FunJim.</li>
<li>Logging: add top-level <code>hostname</code>, flattened <code>message</code>, and available <code>agent_id</code>, <code>session_id</code>, and <code>channel</code> fields to file-log JSONL records for multi-agent filtering without removing existing structured log arguments. Fixes #51075. Thanks @stevengonsalvez.</li>
<li>ACP: route server logs to stderr before Gateway config/bootstrap work so ACP stdout remains JSON-RPC only for IDE integrations. Fixes #49060. Thanks @Hollychou924.</li>
<li>Logging: propagate internal request trace scopes through Gateway HTTP requests and WebSocket frames so file logs, diagnostic events, agent run traces, model-call traces, OTEL spans, and trusted provider <code>traceparent</code> headers share a correlatable <code>traceId</code> without logging raw request or model content. Fixes #40353. Thanks @liangruochong44-ui.</li>
<li>Diagnostics/OTEL: capture privacy-safe model-call request payload bytes, streamed response bytes, first-response latency, and total duration in diagnostic events, plugin hooks, stability snapshots, and OTEL model-call spans/metrics without logging raw model content. Fixes #33832. Thanks @wwh830.</li>
<li>Logging: write validated diagnostic trace context as top-level <code>traceId</code>, <code>spanId</code>, <code>parentSpanId</code>, and <code>traceFlags</code> fields in file-log JSONL records so traced requests and model calls are easier to correlate in log processors. Refs #40353. Thanks @liangruochong44-ui.</li>
<li>Logging/sessions: apply configured redaction patterns to persisted session transcript text and accept escaped character classes in safe custom redaction regexes, so transcript JSONL no longer keeps matching sensitive text in the clear. Fixes #42982. Thanks @panpan0000.</li>
<li>Agents/sessions: let <code>sessions_spawn runtime="subagent"</code> ignore ACP-only <code>streamTo</code> and <code>resumeSessionId</code> fields while keeping ACP passthrough and documenting <code>streamTo</code> as ACP-only. Fixes #43556 and #63120; covers #56326, #61724, #64714, and #67248; carries forward #68397, #65282, #58686, #56342, and #40102. Thanks @skernelx, @damselem, @Br1an67, @Mintalix, @IsaacAPerez, @vvitovec, @Sanjays2402, @shenkq97, and @1034378361.</li>
<li>Providers/Ollama: honor <code>/api/show</code> capabilities, custom Modelfile <code>PARAMETER num_ctx</code>, configured provider/model context defaults, whitelisted native params such as <code>temperature</code>, <code>top_p</code>, and <code>think</code>, and native thinking effort levels so local models get accurate tools, context, and thinking behavior without forcing full-context VRAM use. Fixes #64710, duplicate #65343, #68344, #44550, #52206, #49684, #68662, #48010, #71584, and #44786; supersedes #69464; carries forward #44955. Thanks @yuan-b, @netherby, @xilopaint, @Diyforfun2026, @neeravmakwana, @taitruong, @armi0024, @LokiCode404, @zhouZcong, @dshenster-byte, @tangzhi, @pandego, @maweibin, @Adam-Researchh, @EmpireCreator, @g0st1n, and @voltwake.</li>
<li>Image tool/media: honor <code>tools.media.image.timeoutSeconds</code> and matching per-model image timeouts in explicit image analysis, including the MiniMax VLM fallback path, so slow local vision models are not capped by hardcoded 30s/60s aborts. Fixes #67889; supersedes #67929. Thanks @AllenT22 and @alchip.</li>
<li>Providers/Ollama: strip custom provider prefixes before native chat/embedding requests, skip ambient localhost discovery unless config/auth opts in, handle custom remote <code>api: "ollama"</code> providers, accept OpenAI SDK-style <code>baseURL</code>, scope synthetic local auth and embedding bearer headers to declared host boundaries, resolve custom-named local providers for subagents, add provider-scoped model request timeouts, preserve explicit input modalities, and document <code>params.keep_alive</code> plus local/LAN/cloud/multi-host/web-search/embedding/thinking setup recipes. Fixes #72353, #56939, #62533, #43945, #64541, #68796, and #39690; supersedes #57116, #62549, #69261, #69857, #65143, and #66511; refs #43945; carries forward #43224 and #39785. Thanks @maximus-dss, @hclsys, @IanxDev, @tsukhani, @issacthekaylon, @Julien-BKK, @Linux2010, @hyspacex, @maxramsay, @Meli73, @LittleJakub, @Juankcba, @uninhibite-scholar, @yfge, @Skrblik, and @Mriris.</li>
<li>Providers/Ollama: move memory embeddings to <code>/api/embed</code> with batched <code>input</code>, route local web search through Ollama's signed daemon proxy while keeping cloud auth scoped, treat Ollama memory embeddings as key-optional in doctor, and keep model usage visible by estimating native transcript usage when <code>/api/chat</code> omits counters. Fixes #39983, #69132, and #46584; carries forward #39112. Thanks @sskkcc, @LiudengZhang, @yoon1012, @hyspacex, @fengly78, and @TylonHH.</li>
<li>Agents/Ollama: parse stringified native tool-call arguments, retry native empty/thinking-only turns, accept already-prefixed LLM task model overrides, apply provider-owned replay normalization for Cloud models, validate explicit <code>--thinking max</code>, show resolved thinking defaults in Control UI, and include configured provider models in <code>models list --provider</code>. Fixes #69735, #50052, #71697, #71584, #72407, and #65207; supersedes #69910; carries forward #66552 and #61223. Thanks @rongshuzhao, @yfge, @L3G, @ralphy-maplebots, @Hollychou924, @ismael-81, @g0st1n, @NotecAG, and @drzeast-png.</li>
<li>Providers/PDF/Ollama: add bounded network timeouts for Ollama model pulls and native Anthropic/Gemini PDF analysis requests so unresponsive provider endpoints no longer hang sessions indefinitely. Fixes #54142; supersedes #54144 and #54145. Thanks @jinduwang1001-max and @arkyu2077.</li>
<li>Docker/QA: add observability coverage to the normal Docker aggregate so QA-lab OTEL and Prometheus diagnostics run inside Docker. Thanks @vincentkoc.</li>
<li>Auto-reply: poison inbound message dedupe after replay-unsafe provider/runtime failures so retries stay safe before visible progress but cannot duplicate messages after block output, tool side effects, or session progress. Fixes #69303; keeps #58549 and #64606 as duplicate validation. Thanks @martingarramon, @NikolaFC, and @zeroth-blip.</li>
<li>Agents/model fallback: keep auto-persisted fallback model overrides selected across turns until <code>/new</code> or reset clears them, avoiding repeated probes of a known-bad primary while <code>/status</code> shows the selected and active models. Thanks @kibedu.</li>
<li>Agents/model fallback: jump directly to a known later live-session model redirect instead of walking unrelated fallback candidates, while preserving the already-landed live-session/fallback loop guard. Fixes #57471; related loop family already closed via #58496. Thanks @yuxiaoyang2007-prog.</li>
<li>Gateway/Bonjour: keep @homebridge/ciao cancellation handlers registered across advertiser restarts so late probing cancellations cannot crash Linux and other mDNS-churned gateways.</li>
<li>Plugins/startup: load the default <code>memory-core</code> slot during Gateway startup when permitted so active-memory recall can call <code>memory_search</code> and <code>memory_get</code> without requiring an explicit <code>plugins.slots.memory</code> entry, while preserving <code>plugins.slots.memory: "none"</code>.</li>
<li>Plugins/CLI: prefer native require for compiled bundled plugin JavaScript before jiti so read-only config, status, device, and node commands avoid unnecessary transform overhead on slow hosts. Fixes #62842. Thanks @Effet.</li>
<li>Plugins/compat/CLI: inventory doctor-side deprecation migrations separately from runtime plugin compatibility, add dated records for legacy extension-api, memory registration, provider hook/type aliases, runtime aliases, channel SDK helpers, and approval/test utility shims, refresh the persisted registry after managed plugin removals, make plugin install/uninstall writes conflict-aware, clear stale denylists, and fail tracked plugin/hook updates or unloadable package installs instead of leaving stale state. Thanks @vincentkoc.</li>
<li>WebChat/Control UI: support non-video file attachments in chat uploads while preserving the existing image attachment path and MIME-sniff fallback for generic image uploads. (#70947) Thanks @IAMSamuelRodda.</li>
<li>Skills/memory: restore Chokidar v5 hot reloads by watching concrete skill and memory roots with filters, including SKILL.md removals and deleted skill folders without broad workspace recursion. Fixes #27404, #33585, and #41606. Thanks @shelvenzhou, @08820048, and @rocke2020.</li>
<li>Gateway/chat: keep duplicate attachment-backed <code>chat.send</code> retries with the same idempotency key on the documented in-flight path so aborts still target the real active run. Fixes #70139. Thanks @Feelw00.</li>
<li>Gateway/session rows: report the same config-resolved thinking default that runtime sessions use, including global and per-agent defaults, so Control UI and TUI default labels stay aligned. (#71779, #70981, #71033, #70302) Thanks @chen-zhang-cs-code, @SymbolStar, and @cholaolu-boop.</li>
<li>Plugins: share package entrypoint resolution between install and discovery, reject mismatched <code>runtimeExtensions</code>, and cache bundled runtime-dependency manifest reads during scans.</li>
<li>WhatsApp/Web: keep quiet but healthy linked-device sessions connected by basing the watchdog on WhatsApp Web transport activity, while retaining a longer app-silence cap so frame activity cannot mask a stuck session forever. Fixes #70678; carries forward the focused #71466 approach and keeps #63939 as related configurable-timeout follow-up. Thanks @vincentkoc and @oromeis.</li>
<li>Discord/gateway: count failed health-monitor restart attempts toward cooldown and hourly caps, and evict stale account lifecycle state during channel reloads so repeated Discord gateway recovery cannot loop on old status. Fixes #38596. (#40413) Thanks @jellyAI-dev and @vashquez.</li>
<li>Cron/context engine: run isolated cron jobs under run-scoped context-engine session keys so prior runs of the same job are not inherited unless the job is explicitly session-bound. (#72292) Thanks @jalehman.</li>
<li>Control UI: localize command palette labels, categories, skill shortcuts, footer hints, and connect-command copy labels while preserving localized command palette search matching. (#61130, #61119) Thanks @rubensfox20.</li>
<li>Plugins/memory-lancedb: request float embedding responses from OpenAI-compatible servers so local providers that default SDK requests to base64 no longer return dimension-mismatched LanceDB vectors while preserving configured dimensions. Fixes #45982. (#59048, #46069, #45986) Thanks @deep-introspection, @xiaokhkh, @caicongyang, and @thiswind.</li>
<li>Plugins/memory-lancedb: advance auto-capture cursors per session only after messages are processed or intentionally skipped, retry failed messages, survive compacted histories, and clear cursor state on session end. Fixes #71349; carries forward #42083. Thanks @as775116191.</li>
<li>Plugins/memory-core: respect configured memory-search embedding concurrency during non-batch indexing so local Ollama embedding backends can serialize indexing instead of flooding the server. Fixes #66822. (#66931) Thanks @oliviareid-svg and @LyraInTheFlesh.</li>
<li>Docker/update smoke: keep the package-derived update-channel fixture on package-shipped files and make its UI build stub create the asset the updater verifies. Thanks @vincentkoc.</li>
<li>Gateway/models: repair legacy <code>models.providers.*.api = "openai"</code> config values to <code>openai-completions</code>, and skip providers with future stale API enum values during startup instead of bricking the gateway. Fixes #72477. (#72542) Thanks @JooyoungChoi14 and @obviyus.</li>
<li>Gateway/skills: redact <code>apiKey</code> and secret-named <code>env</code> values from the <code>skills.update</code> RPC response to prevent leaking credentials into WebSocket traffic, client logs, or session transcripts. Config is still written to disk in full; only the response payload is redacted. (#69998) Thanks @Ziy1-Tan.</li>
<li>Plugins/CLI: let flag-driven <code>openclaw channels add</code> install the selected channel plugin from its default source without opening an interactive prompt, fixing published npm Telegram setup in stdin-closed automation.</li>
<li>Onboarding/setup: keep first-run config reads, plugin compatibility notices, OpenAI Codex auth, post-auth default-model policy lookup, skip-auth, provider-scoped model pickers, and post-model sanity checks on cold manifest/setup metadata unless the user chooses to browse all models, avoiding full plugin/provider runtime loads between prompts. Thanks @shakkernerd.</li>
<li>Gateway/Bonjour: suppress known @homebridge/ciao cancellation and network assertion failures through scoped process handlers so malformed mDNS packets or restricted VPS networking disable/restart Bonjour instead of crashing the gateway. Fixes #67578. Thanks @zenassist26-create.</li>
<li>Discord: keep late clicks on already-resolved exec approval buttons quiet when elevated mode auto-resolved the request, while still surfacing real approval submission failures. Fixes #66906. Thanks @rlerikse.</li>
<li>Telegram: send a fresh final message for long-lived preview-streamed replies so the visible Telegram timestamp reflects completion time instead of the preview creation time. Thanks @rubencu.</li>
</ul>
<p><a href="https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md">View full changelog</a></p>
]]></description>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.4.20/OpenClaw-2026.4.20.zip" length="47535600" type="application/octet-stream" sparkle:edSignature="D7XcNGxmc10IIayYY91RZBoascFSnXyd4dg6cSpC3+PTIwVrWYs/FwSBc/1J+1P53LlnTHKDGQYMkWVNMnRSAQ=="/>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.4.26/OpenClaw-2026.4.26.zip" length="48222029" type="application/octet-stream" sparkle:edSignature="6wgFZUyyU09Y6nvD9T1Ufq7Plo0Wzfg+L9r80DCaNMMuwebcKWAsMVSP3RvhRhTxVMax8toUDYg3gb/vOiE5BA=="/>
</item>
<item>
<title>2026.4.15</title>
<pubDate>Thu, 16 Apr 2026 23:33:29 +0000</pubDate>
<title>2026.4.25</title>
<pubDate>Mon, 27 Apr 2026 13:34:25 +0000</pubDate>
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
<sparkle:version>2026041590</sparkle:version>
<sparkle:shortVersionString>2026.4.15</sparkle:shortVersionString>
<sparkle:version>2026042590</sparkle:version>
<sparkle:shortVersionString>2026.4.25</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[<h2>OpenClaw 2026.4.15</h2>
<description><![CDATA[<h2>OpenClaw 2026.4.25</h2>
<h3>Highlights</h3>
<ul>
<li>Voice replies get a full TTS upgrade: <code>/tts latest</code>, chat-scoped auto-TTS controls, personas, per-agent/per-account overrides, and new Azure Speech, Xiaomi, Local CLI, Inworld, Volcengine, and ElevenLabs v3 provider coverage. Thanks @leonchui, @zoujiejun, @solar2ain, @cshape, @xuruiray, @itsuzef, and @barronlroth.</li>
<li>Plugin startup and install paths move to the cold persisted registry, cutting broad manifest scans while making plugin update, repair, provider discovery, and install metadata more deterministic. Thanks @vincentkoc and @shakkernerd.</li>
<li>OpenTelemetry coverage expands across model calls, token usage, tool loops, harness runs, exec processes, outbound delivery, context assembly, and memory pressure with bounded low-cardinality attributes. Thanks @vincentkoc, @jlapenna, @Lidang-Jiang, and @oc-factus.</li>
<li>Browser automation gets safer tab URLs, iframe-aware role snapshots, CDP readiness tuning, headless one-shot launch, and deeper browser doctor probes for slow hosts. Thanks @beat843796 and @BenediktSchackenberg.</li>
<li>Control UI and setup flows add PWA/Web Push support, Crestodian first-run repair, TUI setup, context mode selection, and a shorter startup greeting. Thanks @eduardocruz, @SebTardif, and @kevinlin-openai.</li>
<li>Install/update hardening covers Windows, macOS, Linux, Docker, bundled plugin runtime deps, Node service restarts, LaunchAgent token rotation, and mixed-version gateway verification. Thanks @Kobevictor, @igormf, @abhinas90, @jsompis, @Solvely-Colin, and @gucasbrg.</li>
</ul>
<h3>Changes</h3>
<ul>
<li>Anthropic/models: default Anthropic selections, <code>opus</code> aliases, Claude CLI defaults, and bundled image understanding to Claude Opus 4.7.</li>
<li>Google/TTS: add Gemini text-to-speech support to the bundled <code>google</code> plugin, including provider registration, voice selection, WAV reply output, PCM telephony output, and setup/docs guidance. (#67515) Thanks @barronlroth.</li>
<li>Control UI/Overview: add a Model Auth status card showing OAuth token health and provider rate-limit pressure at a glance, with attention callouts when OAuth tokens are expiring or expired. Backed by a new <code>models.authStatus</code> gateway method that strips credentials and caches for 60s. (#66211) Thanks @omarshahine.</li>
<li>Memory/LanceDB: add cloud storage support to <code>memory-lancedb</code> so durable memory indexes can run on remote object storage instead of local disk only. (#63502) Thanks @rugvedS07.</li>
<li>GitHub Copilot/memory search: add a GitHub Copilot embedding provider for memory search, and expose a dedicated Copilot embedding host helper so plugins can reuse the transport while honoring remote overrides, token refresh, and safer payload validation. (#61718) Thanks @feiskyer and @vincentkoc.</li>
<li>Agents/local models: add experimental <code>agents.defaults.experimental.localModelLean: true</code> to drop heavyweight default tools like <code>browser</code>, <code>cron</code>, and <code>message</code>, reducing prompt size for weaker local-model setups without changing the normal path. (#66495) Thanks @ImLukeF.</li>
<li>Packaging/plugins: localize bundled plugin runtime deps to their owning extensions, trim the published docs payload, and tighten install/package-manager guardrails so published builds stay leaner and core stops carrying extension-owned runtime baggage. (#67099) Thanks @vincentkoc.</li>
<li>QA/Matrix: split Matrix live QA into a source-linked <code>qa-matrix</code> runner and keep repo-private <code>qa-*</code> surfaces out of packaged and published builds. (#66723) Thanks @gumadeiras.</li>
<li>Docs/showcase: add a scannable hero, complete section jump links, and a responsive video grid for community examples. (#48493) Thanks @jchopard69.</li>
<li>TTS/WhatsApp: add <code>/tts latest</code> read-aloud support with duplicate suppression and <code>/tts chat on|off|default</code> session-scoped auto-TTS overrides, completing the on-demand voice-note UX for current-chat replies. Fixes #66032.</li>
<li>TTS/channels: resolve channel and account TTS overrides generically, enabling Feishu and QQBot accounts to deep-merge <code>channels.<channel>.accounts.<id>.tts</code> over global and per-agent TTS config. Thanks @sahilsatralkar.</li>
<li>TTS/agents: allow <code>agents.list[].tts</code> to override global <code>messages.tts</code> for per-agent voices, and make <code>/tts audio</code>, <code>/tts status</code>, and the <code>tts</code> agent tool honor the active voice/provider override while keeping shared provider credentials and preferences in the existing TTS config surface.</li>
<li>Providers/Azure Speech: add Azure Speech as a bundled TTS provider with Speech-resource auth, voice listing, SSML escaping, native Ogg/Opus voice-note output, and telephony output. (#51776) Thanks @leonchui.</li>
<li>Google Meet: add calendar-backed attendance export workflows, export manifests, dry-run previews, and tool parity for meeting records.</li>
<li>Control UI: add PWA install support and Web Push notifications for Gateway chat. (#44590) Thanks @eduardocruz.</li>
<li>Browser automation: add safe tab URLs in agent responses plus a CDP-native role snapshot fallback with iframe-aware refs, cursor-clickable detection, target attach preparation, and <code>openclaw browser doctor --deep</code> live snapshot probing.</li>
<li>CLI/image generation: expose generic <code>--background</code> on <code>openclaw infer image generate</code> and <code>openclaw infer image edit</code>, keep <code>--openai-background</code> as an OpenAI alias, and let fal image generation honor <code>--output-format png|jpeg</code>.</li>
<li>Browser/config: allow local managed Chrome launch discovery and post-launch CDP readiness timeouts to be raised for slower hosts such as Raspberry Pi. Fixes #66803. Thanks @beat843796.</li>
<li>Discord: allow <code>channels.discord.voice.model</code> to override the LLM used for voice channel responses while keeping STT and TTS on their existing media settings. (#64368) Thanks @mrdavey.</li>
<li>Browser/CLI: add <code>openclaw browser start --headless</code> as a one-shot local managed browser launch override without rewriting persisted browser config. Thanks @BenediktSchackenberg.</li>
<li>CLI/Crestodian/TUI: add the first-run setup helper, local planner fallback, full-TUI interactive Crestodian, startup progress indicators, context mode selector, and a shorter startup greeting. (#71720, #71760) Thanks @SebTardif and @kevinlin-openai.</li>
<li>Plugins: migrate the local plugin registry automatically during package install/update, keeping install metadata in the plugin index while indexing existing plugin manifests for the new cold registry path. Thanks @vincentkoc and @shakkernerd.</li>
<li>Plugins/doctor: make <code>openclaw doctor --fix</code> refresh the plugin index and cold registry index when needed without treating plugin install records as authored config. Thanks @vincentkoc and @shakkernerd.</li>
<li>Plugins/hooks: add before-agent-finalize hooks, cron <code>jobId</code> hook context, bounded native permission fingerprints, and Codex MCP hook relay support. (#71765, #71758, #71707) Thanks @vincentkoc and @pashpashpash.</li>
<li>Plugins/tokenjuice: bump the bundled tokenjuice runtime to 0.6.3. Thanks @vincentkoc.</li>
<li>Diagnostics/OTEL: align model-call GenAI span attributes with OpenTelemetry stability opt-in semantics, keeping legacy <code>gen_ai.system</code> by default while emitting <code>gen_ai.provider.name</code> under <code>OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental</code>. Thanks @vincentkoc.</li>
<li>Diagnostics/OTEL: support signal-specific OTLP endpoint overrides for traces, metrics, and logs via config or standard OTEL environment variables. Thanks @vincentkoc.</li>
<li>Diagnostics/OTEL: emit bounded telemetry exporter health diagnostics for startup and log-export failures without exporting raw error text. Thanks @vincentkoc.</li>
<li>Diagnostics/OTEL: export agent harness lifecycle telemetry as bounded <code>openclaw.harness.run</code> spans and <code>openclaw.harness.duration_ms</code> metrics so QA-lab, Codex, and future harnesses share one trace shape. Thanks @vincentkoc.</li>
<li>Diagnostics/trace: propagate W3C <code>traceparent</code> headers from trusted model-call trace context to provider transports while replacing caller-supplied traceparent values. Thanks @vincentkoc.</li>
<li>Diagnostics/Prometheus: add a bundled <code>diagnostics-prometheus</code> plugin with a protected gateway scrape route for low-cardinality diagnostics metrics. Thanks @vincentkoc.</li>
<li>Plugins/CLI: add <code>openclaw plugins registry</code> for explicit persisted-registry inspection and <code>--refresh</code> repair without making normal startup rescan plugin locations. Thanks @vincentkoc.</li>
<li>Plugins/CLI: make <code>openclaw plugins list</code> read the cold persisted registry snapshot by default, leaving module-aware diagnostics to <code>plugins doctor</code> and <code>plugins inspect</code>. Thanks @vincentkoc.</li>
<li>Plugins/startup: move gateway startup plugin planning onto the versioned cold registry index, with postinstall repair for older registry files that predate startup metadata. Thanks @vincentkoc.</li>
<li>Plugins/startup: normalize startup and provider plugin enablement through registry aliases so boot paths do not need the legacy manifest alias scan. Thanks @vincentkoc.</li>
<li>Providers/plugins: resolve provider ownership, provider discovery scopes, and catalog-hook provider ids from the cold plugin registry instead of rescanning manifests on those paths. Thanks @vincentkoc.</li>
<li>Plugins/registry: keep installed plugin index records focused on install/state/load paths and resolve plugin capabilities from manifests scoped to indexed plugins. Thanks @shakkernerd.</li>
<li>Plugins/registry: route cold manifest and capability lookups through the installed plugin index so setup, channels, config, secrets, doctor, and provider metadata paths avoid broad plugin-root scans before runtime execution. Thanks @shakkernerd.</li>
<li>CLI/models: speed up <code>models list --all --provider <id></code> for static manifest-backed providers by loading catalog rows through the installed plugin index instead of broad manifest scans or runtime suppression hooks. Thanks @shakkernerd.</li>
<li>CLI/models: use OpenClaw Provider Index preview rows as the final cold fallback for installable providers, while keeping user config, installed manifests, and refreshed cache rows above provider-index metadata. Thanks @vincentkoc.</li>
<li>Providers/plugins: keep onboarding and auth-choice setup lists on cold manifest/install metadata and add Provider Index install metadata for not-yet-installed provider plugins. Thanks @vincentkoc.</li>
<li>Providers/plugins: keep provider setup guidance and configure auth imports on cold manifest metadata, with a regression guard against static provider-runtime imports on setup/configure list paths. Thanks @vincentkoc.</li>
<li>CLI/capabilities: keep capability command registration from importing the models auth runtime until <code>model auth login</code> actually runs. Thanks @vincentkoc.</li>
<li>CLI/configure: keep web-search configure prompts on cold plugin registry metadata until the user chooses managed search setup. Thanks @vincentkoc.</li>
<li>Plugins/chat commands: refresh the persisted plugin registry after <code>/plugins enable</code> and <code>/plugins disable</code>, matching the CLI mutation path. Thanks @vincentkoc.</li>
<li>Plugins/compat: mark <code>OPENCLAW_DISABLE_PERSISTED_PLUGIN_REGISTRY</code> as a deprecated break-glass switch and point operators at registry repair instead. Thanks @vincentkoc.</li>
<li>Plugins/compat: expand the central compatibility registry with dated owners, replacements, and maximum three-month removal targets for legacy SDK, manifest, setup, registry-migration, and agent-runtime surfaces. Thanks @vincentkoc.</li>
<li>Plugins/registry: ignore stale persisted registry reads when plugin policy no longer matches current config, and stamp generated registry files with a do-not-edit warning. Thanks @vincentkoc.</li>
<li>Config/plugins: keep plugin command-alias validation on cold manifest metadata instead of importing the runtime alias resolver. Thanks @vincentkoc.</li>
<li>Security/plugins: keep web-search credential presence checks on cold config, env, and manifest metadata instead of importing web-search provider runtime. Thanks @vincentkoc.</li>
<li>Diagnostics/OTEL: surface provider request identifiers as bounded hashes on model-call diagnostics and span events, without exporting raw request IDs or metric labels. Thanks @Lidang-Jiang and @vincentkoc.</li>
<li>Plugins/diagnostics: add metadata-only <code>model_call_started</code> and <code>model_call_ended</code> hooks for provider/model call telemetry without exposing prompts, responses, headers, request bodies, or raw provider request IDs. Thanks @vincentkoc.</li>
<li>Diagnostics/OTEL: emit bounded context assembly diagnostics and export <code>openclaw.context.assembled</code> spans with prompt/history sizes but no prompt, history, response, or session-key content. Thanks @vincentkoc.</li>
<li>Diagnostics/OTEL: export existing tool-loop diagnostics as <code>openclaw.tool.loop</code> counters and spans without loop messages, session identifiers, params, or tool output. Thanks @vincentkoc.</li>
<li>Diagnostics/OTEL: export diagnostic memory samples and pressure as bounded memory histograms, counters, and pressure spans to help spot leak regressions without session or payload data. Thanks @vincentkoc.</li>
<li>Diagnostics/OTEL: add the GenAI <code>gen_ai.client.token.usage</code> histogram for input/output model usage while keeping session identifiers and aggregate cache counters out of the semantic metric. Thanks @vincentkoc.</li>
<li>Diagnostics/OTEL: add a bounded <code>openclaw.agent</code> label to OpenClaw token metrics so per-agent Grafana dashboards can group usage without exporting session identifiers. Thanks @oc-factus.</li>
<li>Plugins/install: consolidate managed plugin install metadata into the state-managed plugin index at <code>plugins/installs.json</code>, replacing the temporary <code>plugins/installed-index.json</code> path and removing <code>plugins.installs</code> as an authored config surface. Thanks @vincentkoc and @shakkernerd.</li>
<li>Diagnostics/OTEL: add the GenAI <code>gen_ai.client.operation.duration</code> histogram for model-call latency in seconds with bounded provider/model/API and error attributes. Thanks @vincentkoc.</li>
<li>Diagnostics/OTEL: add GenAI usage token attributes to model-usage spans, including cache read/write input token counts without session identifiers or prompt/response content. Thanks @vincentkoc.</li>
<li>Diagnostics/OTEL: include bounded GenAI operation, provider, and request-model attributes on model-usage spans so token usage remains self-describing without diagnostic identifiers. Thanks @vincentkoc.</li>
<li>Diagnostics/OTEL: keep model-usage span GenAI provider attributes aligned with the existing semantic-convention opt-in policy, using legacy <code>gen_ai.system</code> unless latest experimental GenAI conventions are enabled. Thanks @vincentkoc.</li>
<li>Diagnostics/OTEL: keep <code>gen_ai.request.model</code> present on GenAI token usage metrics with a bounded <code>unknown</code> fallback when model usage events do not include a model. Thanks @vincentkoc.</li>
<li>Docs/OTEL: document the GenAI token and model-call duration metrics, model-usage span attributes, and <code>OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental</code> provider-attribute behavior. Thanks @vincentkoc.</li>
<li>Docs: refresh the MCP, model provider, doctor, troubleshooting, BlueBubbles, media generation, TTS, subagents, skills, cron/tasks, exec approvals, and voice-call guides with structured Steps, Tabs, and Accordion content.</li>
<li>Diagnostics/trace: add an internal traceparent propagation helper that only formats trusted dispatcher metadata, keeping plugin-emitted diagnostic traces out of outbound propagation by default. Thanks @vincentkoc.</li>
<li>Diagnostics/OTEL: add bounded outbound message delivery lifecycle diagnostics and export them as low-cardinality delivery spans/metrics without message body, recipient, room, or media-path data. (#71471) Thanks @vincentkoc and @jlapenna.</li>
<li>Diagnostics/OTEL: emit bounded exec-process diagnostics and export them as <code>openclaw.exec</code> spans without exposing command text, working directories, or container identifiers. (#71451) Thanks @vincentkoc and @jlapenna.</li>
<li>Diagnostics/OTEL: support <code>OPENCLAW_OTEL_PRELOADED=1</code> so the plugin can reuse an already-registered OpenTelemetry SDK while keeping OpenClaw diagnostic listeners wired. (#71450) Thanks @vincentkoc and @jlapenna.</li>
<li>Providers/Xiaomi: add MiMo TTS as a bundled speech provider with MP3/WAV output and voice-note Opus transcoding. Fixes #52376. (#55614) Thanks @zoujiejun.</li>
<li>Providers/ElevenLabs: include <code>eleven_v3</code> in the bundled TTS model catalog so model selection surfaces can offer ElevenLabs v3. (#68321) Thanks @itsuzef.</li>
<li>Providers/Local CLI TTS: add a bundled local command speech provider with file/stdout input, voice-note Opus conversion, and telephony PCM output. (#56239) Thanks @solar2ain.</li>
<li>Providers/Inworld: add Inworld as a bundled speech provider with streaming TTS synthesis, voice listing, voice-note output, and PCM telephony output. (#55972) Thanks @cshape.</li>
<li>Providers/Volcengine: add Volcengine/BytePlus Seed Speech as a bundled TTS provider with API-key auth, native Ogg/Opus voice-note output, and MP3 audio-file output. (#55641) Thanks @xuruiray.</li>
<li>Android/Talk Mode: expose Talk Mode in the Voice tab with runtime-owned voice capture modes and microphone foreground-service escalation. Thanks @alex-latitude.</li>
<li>Providers/LiteLLM: register <code>litellm</code> as an image-generation provider so <code>image_generate model=litellm/...</code> calls and <code>agents.defaults.imageGenerationModel.fallbacks</code> entries resolve through the LiteLLM proxy. Thanks @zqchris.</li>
<li>Providers/fal: add Seedance 2.0 reference-to-video models with multi-image, video, and audio reference input mapping plus model-specific capability limits for <code>video_generate</code>. Thanks @shivanker.</li>
<li>Codex harness: require Codex app-server <code>0.125.0</code> or newer and cover native MCP <code>PreToolUse</code>, <code>PostToolUse</code>, and <code>PermissionRequest</code> payloads through the OpenClaw hook relay.</li>
<li>Agents/Codex: teach prompts and <code>agents_list</code> to surface native Codex app-server availability so agents prefer <code>/codex ...</code> over Codex ACP unless ACP/acpx is explicit. Thanks @vincentkoc.</li>
<li>ACPX/Droid: add Factory Droid to the live ACP bind Docker matrix, including <code>.factory</code> settings staging, <code>FACTORY_API_KEY</code> forwarding, and the single-agent <code>test:docker:live-acp-bind:droid</code> recipe.</li>
<li>TTS/personas: add provider-aware TTS personas with deterministic provider binding merges, <code>/tts persona</code> controls, gateway/CLI persona state, Google Gemini <code>audio-profile-v1</code> prompt wrapping, and OpenAI instruction mapping. (#70748) Thanks @barronlroth.</li>
<li>Voice Wake: add trigger-based routing so macOS voice wake phrases can select a configured agent or session target, with Gateway routing APIs and node update events. (#30354) Thanks @longbiaochen.</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Gateway/tools: anchor trusted local <code>MEDIA:</code> tool-result passthrough on the exact raw name of this run's registered built-in tools, and reject client tool definitions whose names normalize-collide with a built-in or with another client tool in the same request (<code>400 invalid_request_error</code> on both JSON and SSE paths), so a client-supplied tool named like a built-in can no longer inherit its local-media trust. (#67303)</li>
<li>Agents/replay recovery: classify the provider wording <code>401 input item ID does not belong to this connection</code> as replay-invalid, so users get the existing <code>/new</code> session reset guidance instead of a raw 401-style failure. (#66475) Thanks @dallylee.</li>
<li>Gateway/webchat: enforce localRoots containment on webchat audio embedding path [AI-assisted]. (#67298) Thanks @pgondhi987.</li>
<li>Matrix/pairing: block DM pairing-store entries from authorizing room control commands [AI-assisted]. (#67294) Thanks @pgondhi987.</li>
<li>Docker/build: verify <code>@matrix-org/matrix-sdk-crypto-nodejs</code> native bindings with <code>find</code> under <code>node_modules</code> instead of a hardcoded <code>.pnpm/...</code> path so pnpm v10+ virtual-store layouts no longer fail the image build. (#67143) thanks @ly85206559.</li>
<li>Matrix/E2EE: keep startup bootstrap conservative for passwordless token-auth bots, still attempt the guarded repair pass without requiring <code>channels.matrix.password</code>, and document the remaining password-UIA limitation. (#66228) Thanks @SARAMALI15792.</li>
<li>Cron/announce delivery: suppress mixed-content isolated cron announce replies that end with <code>NO_REPLY</code> so trailing silent sentinels no longer leak summary text to the target channel. (#65004) thanks @neo1027144-creator.</li>
<li>Plugins/bundled channels: partition bundled channel lazy caches by active bundled root so <code>OPENCLAW_BUNDLED_PLUGINS_DIR</code> flips stop reusing stale plugin, setup, secrets, and runtime state. (#67200) Thanks @gumadeiras.</li>
<li>Packaging/plugins: prune common test/spec cargo from bundled plugin runtime dependencies and fail npm release validation if packaged test cargo reappears, keeping published tarballs leaner without plugin-specific special cases. (#67275) thanks @gumadeiras.</li>
<li>Agents/context + Memory: trim default startup/skills prompt budgets, cap <code>memory_get</code> excerpts by default with explicit continuation metadata, and keep QMD reads aligned with the same bounded excerpt contract so long sessions pull less context by default without losing deterministic follow-up reads.</li>
<li>Matrix/commands: skip DM pairing-store reads on room traffic now that room control-command authorization ignores pairing-store entries, keeping the room path narrower without changing room auth behavior. (#67325) Thanks @gumadeiras.</li>
<li>Memory-core/dreaming: skip dreaming narrative transcripts from session-store metadata before bootstrap records land so dream diary prompt/prose lines do not pollute session ingestion. (#67315) thanks @jalehman.</li>
<li>Agents/local models: clarify low-context preflight hints for self-hosted models, point config-backed caps at the relevant OpenClaw setting, and stop suggesting larger models when <code>agents.defaults.contextTokens</code> is the real limit. (#66236) Thanks @ImLukeF.</li>
<li>Dreaming/memory-core: change the default <code>dreaming.storage.mode</code> from <code>inline</code> to <code>separate</code> so Dreaming phase blocks (<code>## Light Sleep</code>, <code>## REM Sleep</code>) land in <code>memory/dreaming/{phase}/YYYY-MM-DD.md</code> instead of being injected into <code>memory/YYYY-MM-DD.md</code>. Daily memory files no longer get dominated by structured candidate output, and the daily-ingestion scanner that already strips dream marker blocks no longer has to compete with hundreds of phase-block lines on every run. Operators who want the previous behavior can opt in by setting <code>plugins.entries.memory-core.config.dreaming.storage.mode: "inline"</code>. (#66412) Thanks @mjamiv.</li>
<li>Control UI/Overview: fix false-positive "missing" alerts on the Model Auth status card for aliased providers, env-backed OAuth with auth.profiles, and unresolvable env SecretRefs. (#67253) Thanks @omarshahine.</li>
<li>Dashboard: constrain exec approval modal overflow on desktop so long command content no longer pushes action buttons out of view. (#67082) Thanks @Ziy1-Tan.</li>
<li>Agents/CLI transcripts: persist successful CLI-backed turns into the OpenClaw session transcript so google-gemini-cli replies appear in session history and the Control UI again. (#67490) Thanks @obviyus.</li>
<li>Discord/tool-call text: strip standalone Gemma-style <code><function>...</function></code> tool-call payloads from visible assistant text without truncating prose examples or trailing replies. (#67318) Thanks @joelnishanth.</li>
<li>WhatsApp/web-session: drain the pending per-auth creds save queue before reopening sockets so reconnect-time auth bootstrap no longer races in-flight <code>creds.json</code> writes and falsely restores from backup. (#67464) Thanks @neeravmakwana.</li>
<li>BlueBubbles/catchup: add a per-message retry ceiling (<code>catchup.maxFailureRetries</code>, default 10) so a persistently-failing message with a malformed payload no longer wedges the catchup cursor forever. After N consecutive <code>processMessage</code> failures against the same GUID, catchup logs a WARN, skips that message on subsequent sweeps, and lets the cursor advance past it. Transient failures still retry from the same point as before. Also fixes a lost-update race in the persistent dedupe file lock that silently dropped inbound GUIDs on concurrent writes, a dedupe file naming migration gap on version upgrade, and a balloon-event bypass that let catchup replay debouncer-coalesced events as standalone messages. (#67426, #66870) Thanks @omarshahine.</li>
<li>Ollama/chat: strip the <code>ollama/</code> provider prefix from Ollama chat request model ids so configured refs like <code>ollama/qwen3:14b-q8_0</code> stop 404ing against the Ollama API. (#67457) Thanks @suboss87.</li>
<li>Agents/tools: resolve non-workspace host tilde paths against the OS home directory and keep edit recovery aligned with that same path target, so <code>~/...</code> host edit/write operations stop failing or reading back the wrong file when <code>OPENCLAW_HOME</code> differs. (#62804) Thanks @stainlu.</li>
<li>Speech/TTS: auto-enable the bundled Microsoft and ElevenLabs speech providers, and route generic TTS directive tokens through the explicit or active provider first so overrides like <code>[[tts:speed=1.2]]</code> stop silently landing on the wrong provider. (#62846) Thanks @stainlu.</li>
<li>OpenAI Codex/models: normalize stale native transport metadata in both runtime resolution and discovery/listing so legacy <code>openai-codex</code> rows with missing <code>api</code> or <code>https://chatgpt.com/backend-api/v1</code> self-heal to the canonical Codex transport instead of routing requests through broken HTML/Cloudflare paths, combining the original fixes proposed in #66969 (saamuelng601-pixel) and #67159 (hclsys). (#67635)</li>
<li>Agents/failover: treat HTML provider error pages as upstream transport failures for CDN-style 5xx responses without misclassifying embedded body text as API rate limits, while still preserving auth remediation for HTML 401/403 pages and proxy remediation for HTML 407 pages. (#67642) Thanks @stainlu.</li>
<li>Gateway/skills: bump the cached skills-snapshot version whenever a config write touches <code>skills.*</code> (for example <code>skills.allowBundled</code>, <code>skills.entries.<id>.enabled</code>, or <code>skills.profile</code>). Existing agent sessions persist a <code>skillsSnapshot</code> in <code>sessions.json</code> that reuses the skill list frozen at session creation; without this invalidation, removing a bundled skill from the allowlist left the old snapshot live and the model kept calling the disabled tool, producing <code>Tool <name> not found</code> loops that ran until the embedded-run timeout. (#67401) Thanks @xantorres.</li>
<li>Agents/tool-loop: enable the unknown-tool stream guard by default. Previously <code>resolveUnknownToolGuardThreshold</code> returned <code>undefined</code> unless <code>tools.loopDetection.enabled</code> was explicitly set to <code>true</code>, which left the protection off in the default configuration. A hallucinated or removed tool (for example <code>himalaya</code> after it was dropped from <code>skills.allowBundled</code>) would then loop "Tool X not found" attempts until the full embedded-run timeout. The guard has no false-positive surface because it only triggers on tools that are objectively not registered in the run, so it now stays on regardless of <code>tools.loopDetection.enabled</code> and still accepts <code>tools.loopDetection.unknownToolThreshold</code> as a per-run override (default 10). (#67401) Thanks @xantorres.</li>
<li>TUI/streaming: add a client-side streaming watchdog to <code>tui-event-handlers</code> so the <code>streaming · Xm Ys</code> activity indicator resets to <code>idle</code> after 30s of delta silence on the active run. Guards against lost or late <code>state: "final"</code> chat events (WS reconnects, gateway restarts, etc.) leaving the TUI stuck on <code>streaming</code> indefinitely; a new system log line surfaces the reset so users know to send a new message to resync. The window is configurable via the new <code>streamingWatchdogMs</code> context option (set to <code>0</code> to disable), and the handler now exposes a <code>dispose()</code> that clears the pending timer on shutdown. (#67401) Thanks @xantorres.</li>
<li>Extensions/lmstudio: add exponential backoff to the inference-preload wrapper so an LM Studio model-load failure (for example the built-in memory guardrail rejecting a load because the swap is saturated) no longer produces a WARN line every ~2s for every chat request. The wrapper now records consecutive preload failures per <code>(baseUrl, modelKey, contextLength)</code> tuple with a 5s → 10s → 20s → … → 5min cooldown and skips the preload step entirely while a cooldown is active, letting chat requests proceed directly to the stream (the model is often already loaded via the LM Studio UI). The combined <code>preload failed</code> log line now reports consecutive-failure count and remaining cooldown so operators can act on the real issue instead of drowning in repeated warnings. (#67401) Thanks @xantorres.</li>
<li>Agents/replay: re-run tool/result pairing after strict replay tool-call ID sanitization on outbound requests so Anthropic-compatible providers like MiniMax no longer receive malformed orphan tool-result IDs such as <code>...toolresult1</code> during compaction and retry flows. (#67620) Thanks @stainlu.</li>
<li>Gateway/startup: fix spurious SIGUSR1 restart loop on Linux/systemd when plugin auto-enable is the only startup config write; the config hash guard was not captured for that write path, causing chokidar to treat each boot write as an external change and trigger a reload → restart cycle that corrupts manifest.db after repeated cycles. Fixes #67436. (#67557) thanks @openperf</li>
<li>Codex/harness: auto-enable the Codex plugin when <code>codex</code> is selected as an embedded agent harness runtime, including forced default, per-agent, and <code>OPENCLAW_AGENT_RUNTIME</code> paths. (#67474) Thanks @duqaXxX.</li>
<li>OpenAI Codex/CLI: keep resumed <code>codex exec resume</code> runs on the safe non-interactive path without reintroducing the removed dangerous bypass flag by passing the supported <code>--skip-git-repo-check</code> resume arg plus Codex's native <code>sandbox_mode="workspace-write"</code> config override. (#67666) Thanks @plgonzalezrx8.</li>
<li>Codex/app-server: parse Desktop-originated app-server user agents such as <code>Codex Desktop/0.118.0</code>, keeping the version gate working when the Codex CLI inherits a multi-word originator. (#64666) Thanks @cyrusaf.</li>
<li>Cron/announce delivery: keep isolated announce <code>NO_REPLY</code> stripping case-insensitive across direct and text delivery, preserve structured media-only sends when a caption strips silent, and derive main-session awareness from the cleaned payloads so silent captions no longer leak stale <code>NO_REPLY</code> text. (#65016) Thanks @BKF-Gitty.</li>
<li>Sessions/Codex: skip redundant <code>delivery-mirror</code> transcript appends only when the latest assistant message has the same visible text, preventing duplicate visible replies on Codex-backed turns without suppressing repeated answers across turns. (#67185) Thanks @andyylin.</li>
<li>Auto-reply/prompt-cache: keep volatile inbound chat IDs out of the stable system prompt so task-scoped adapters can reuse prompt caches across runs, while preserving conversation metadata for the user turn and media-only messages. (#65071) Thanks @MonkeyLeeT.</li>
<li>BlueBubbles/inbound: restore inbound image attachment downloads on Node 22+ by stripping incompatible bundled-undici dispatchers from the non-SSRF fetch path, accept <code>updated-message</code> webhooks carrying attachments, use event-type-aware dedup keys so attachment follow-ups are not rejected as duplicates, and retry attachment fetch from the BB API when the initial webhook arrives with an empty array. (#64105, #61861, #65430, #67510) Thanks @omarshahine.</li>
<li>Agents/skills: sort prompt-facing <code>available_skills</code> entries by skill name after merging sources so <code>skills.load.extraDirs</code> order no longer changes prompt-cache prefixes. (#64198) Thanks @Bartok9.</li>
<li>Agents/OpenAI Responses: add <code>models.providers.*.models.*.compat.supportsPromptCacheKey</code> so OpenAI-compatible proxies that forward <code>prompt_cache_key</code> can keep prompt caching enabled while incompatible endpoints can still force stripping. (#67427) Thanks @damselem.</li>
<li>Agents/context engines: keep loop-hook and final <code>afterTurn</code> prompt-cache touch metadata aligned with the current assistant turn so cache-aware context engines retain accurate cache TTL state during tool loops. (#67767) thanks @jalehman.</li>
<li>Memory/dreaming: strip AI-facing inbound metadata envelopes from session-corpus user turns before normalization so REM topic extraction sees the user's actual message text, including array-shaped split envelopes. (#66548) Thanks @zqchris.</li>
<li>Agents/errors: detect standalone Cloudflare/CDN HTML challenge pages before transport DNS classification so provider block pages no longer appear as local DNS lookup failures. (#67704) Thanks @chris-yyau.</li>
<li>Security/approvals: redact secrets in exec approval prompts so inline approval review can no longer leak credential material in rendered prompt content. (#61077, #64790)</li>
<li>CLI/configure: re-read the persisted config hash after writes so config updates stop failing with stale-hash races. (#64188, #66528)</li>
<li>CLI/update: prune stale packaged <code>dist</code> chunks after npm upgrades and keep downgrade/verify inventory checks compat-safe so global upgrades stop failing on stale chunk imports. (#66959) Thanks @obviyus.</li>
<li>Onboarding/CLI: fix channel-selection crashes on globally installed CLI setups during onboarding. (#66736)</li>
<li>Video generation/live tests: bound provider polling for live video smoke, default to the fast non-FAL text-to-video path, and use a one-second lobster prompt so release validation no longer waits indefinitely on slow provider queues.</li>
<li>Memory-core/QMD <code>memory_get</code>: reject reads of arbitrary workspace markdown paths and only allow canonical memory files (<code>MEMORY.md</code>, <code>memory.md</code>, <code>DREAMS.md</code>, <code>dreams.md</code>, <code>memory/**</code>) plus exact paths of active indexed QMD workspace documents, so the QMD memory backend can no longer be used as a generic workspace-file read shim that bypasses <code>read</code> tool-policy denials. (#66026) Thanks @eleqtrizit.</li>
<li>Cron/agents: forward embedded-run tool policy and internal event params into the attempt layer so <code>--tools</code> allowlists, cron-owned message-tool suppression, explicit message targeting, and command-path internal events all take effect at runtime again. (#62675) Thanks @hexsprite.</li>
<li>Setup/providers: guard preferred-provider lookup during setup so malformed plugin metadata with a missing provider id no longer crashes the wizard with <code>Cannot read properties of undefined (reading 'trim')</code>. (#66649) Thanks @Tianworld.</li>
<li>Matrix/security: normalize sandboxed profile avatar params, preserve <code>mxc://</code> avatar URLs, and surface gmail watcher stop failures during reload. (#64701) Thanks @slepybear.</li>
<li>Telegram/documents: drop leaked binary caption bytes from inbound Telegram text handling so document uploads like <code>.mobi</code> or <code>.epub</code> no longer explode prompt token counts. (#66663) Thanks @joelnishanth.</li>
<li>Gateway/auth: resolve the active gateway bearer per-request on the HTTP server and the HTTP upgrade handler via <code>getResolvedAuth()</code>, mirroring the WebSocket path, so a secret rotated through <code>secrets.reload</code> or config hot-reload stops authenticating on <code>/v1/*</code>, <code>/tools/invoke</code>, plugin HTTP routes, and the canvas upgrade path immediately instead of remaining valid on HTTP until gateway restart. (#66651) Thanks @mmaps.</li>
<li>Agents/compaction: cap the compaction reserve-token floor to the model context window so small-context local models (e.g. Ollama with 16K tokens) no longer trigger context-overflow errors or infinite compaction loops on every prompt. (#65671) Thanks @openperf.</li>
<li>Agents/OpenAI Responses: classify the exact <code>Unknown error (no error details in response)</code> transport failure as failover reason <code>unknown</code> so assistant/model fallback still runs for that no-details failure path. (#65254) Thanks @OpenCodeEngineer.</li>
<li>Models/probe: surface invalid-model probe failures as <code>format</code> instead of <code>unknown</code> in <code>models list --probe</code>, and lock the invalid-model fallback path in with regression coverage. (#50028) Thanks @xiwuqi.</li>
<li>Agents/failover: classify OpenAI-compatible <code>finish_reason: network_error</code> stream failures as timeout so model fallback retries continue instead of stopping with an unknown failover reason. (#61784) thanks @lawrence3699.</li>
<li>Onboarding/channels: normalize channel setup metadata before discovery and validation so malformed or mixed-shape channel plugin metadata no longer breaks setup and onboarding channel lists. (#66706) Thanks @darkamenosa.</li>
<li>Slack/native commands: fix option menus for slash commands such as <code>/verbose</code> when Slack renders native buttons by giving each button a unique action ID while still routing them through the shared <code>openclaw_cmdarg*</code> listener. Thanks @Wangmerlyn.</li>
<li>Feishu/webhook: harden the webhook transport and card-action replay guards to fail closed on missing <code>encryptKey</code> and blank callback tokens — refuse to start the webhook transport without an <code>encryptKey</code>, reject unsigned requests when no key is present instead of accepting them, and drop blank card-action tokens before the dedupe claim and dispatcher. Defense-in-depth over the already-closed monitor-account layer. (#66707) Thanks @eleqtrizit.</li>
<li>Agents/workspace files: route <code>agents.files.get</code>, <code>agents.files.set</code>, and workspace listing through the shared <code>fs-safe</code> helpers (<code>openFileWithinRoot</code>/<code>readFileWithinRoot</code>/<code>writeFileWithinRoot</code>), reject symlink aliases for allowlisted agent files, and have <code>fs-safe</code> resolve opened-file real paths from the file descriptor before falling back to path-based <code>realpath</code> so a symlink swap between <code>open</code> and <code>realpath</code> can no longer redirect the validated path off the intended inode. (#66636) Thanks @eleqtrizit.</li>
<li>Gateway/MCP loopback: switch the <code>/mcp</code> bearer comparison from plain <code>!==</code> to constant-time <code>safeEqualSecret</code> (matching the convention every other auth surface in the codebase uses), and reject non-loopback browser-origin requests via <code>checkBrowserOrigin</code> before the auth gate runs. Loopback origins (<code>127.0.0.1:*</code>, <code>localhost:*</code>, same-origin) still go through, including the <code>localhost</code>↔<code>127.0.0.1</code> host mismatch that browsers flag as <code>Sec-Fetch-Site: cross-site</code>. (#66665) Thanks @eleqtrizit.</li>
<li>Auto-reply/billing: classify pure billing cooldown fallback summaries from structured fallback reasons so users see billing guidance instead of the generic failure reply. (#66363) Thanks @Rohan5commit.</li>
<li>Agents/fallback: preserve the original prompt body on model fallback retries with session history so the retrying model keeps the active task instead of only seeing a generic continue message. (#66029) Thanks @WuKongAI-CMU.</li>
<li>Reply/secrets: resolve active reply channel/account SecretRefs before reply-run message-action discovery so channel token SecretRefs (for example Discord) do not degrade into discovery-time unresolved-secret failures. (#66796) Thanks @joshavant.</li>
<li>Agents/Anthropic: ignore non-positive Anthropic Messages token overrides and fail locally when no positive token budget remains, so invalid <code>max_tokens</code> values no longer reach the provider API. (#66664) thanks @jalehman</li>
<li>Agents/context engines: preserve prompt-only token counts, not full request totals, when deferred maintenance reuses after-turn runtime context so background compaction bookkeeping matches the active prompt window. (#66820) thanks @jalehman.</li>
<li>BlueBubbles/inbound: add a persistent file-backed GUID dedupe so MessagePoller webhook replays after BB Server restart or reconnect no longer cause the agent to re-reply to already-handled messages. (#19176, #12053, #66816) Thanks @omarshahine.</li>
<li>Secrets/plugins/status: align SecretRef inspect-vs-strict handling across plugin preload, read-only status/agents surfaces, and runtime auth paths so unresolved refs no longer crash read-only CLI flows while runtime-required non-env refs stay strict. (#66818) Thanks @joshavant.</li>
<li>Memory/dreaming: stop ordinary transcripts that merely quote the dream-diary prompt from being classified as internal dreaming runs and silently dropped from session recall ingestion. (#66852) Thanks @gumadeiras.</li>
<li>Telegram/documents: sanitize binary reply context and ZIP-like archive extraction so <code>.epub</code> and <code>.mobi</code> uploads can no longer leak raw binary into prompt context through reply metadata or archive-to-<code>text/plain</code> coercion. (#66877) Thanks @martinfrancois.</li>
<li>Telegram/native commands: restore plugin-registry-backed auto defaults for native commands and native skills so Telegram slash commands keep registering when <code>commands.native</code> and <code>commands.nativeSkills</code> stay on <code>auto</code>. (#66843) Thanks @kashevk0.</li>
<li>OpenRouter/Qwen3: parse <code>reasoning_details</code> stream deltas as thinking content without skipping same-chunk tool calls, so Qwen3 replies no longer fail empty on OpenRouter and mixed reasoning/tool-call chunks still execute normally. (#66905) Thanks @bladin.</li>
<li>BlueBubbles/catchup: replay missed webhook messages after gateway restart via a persistent per-account cursor and <code>/api/v1/message/query?after=<ts></code> pass, so messages delivered while the gateway was down no longer disappear. Uses the existing <code>processMessage</code> path and is deduped by #66816's inbound GUID cache. (#66857, #66721) Thanks @omarshahine.</li>
<li>Telegram/native commands: keep Telegram command-sync cache process-local so gateway restarts re-register the menu instead of trusting stale on-disk sync state after Telegram cleared commands out-of-band. (#66730) Thanks @nightq.</li>
<li>Audio/self-hosted STT: restore <code>models.providers.*.request.allowPrivateNetwork</code> for audio transcription so private or LAN speech-to-text endpoints stop tripping SSRF blocks after the v2026.4.14 regression. (#66692) Thanks @jhsmith409.</li>
<li>Auto-reply/media: allow workspace-rooted absolute media paths in auto-reply send flows so valid local media references no longer fail path validation. (#66689)</li>
<li>WhatsApp/Baileys media upload: harden encrypted upload handling so large outbound media sends avoid buffer spikes and reliability regressions. (#65966) Thanks @frankekn.</li>
<li>QQBot/cron: guard against undefined <code>event.content</code> in <code>parseFaceTags</code> and <code>filterInternalMarkers</code> so cron-triggered agent turns with no content payload no longer crash with <code>TypeError: Cannot read properties of undefined (reading 'startsWith')</code>. (#66302) Thanks @xinmotlanthua.</li>
<li>CLI/plugins: stop <code>--dangerously-force-unsafe-install</code> plugin installs from falling back to hook-pack installs after security scan failures, while still preserving non-security fallback behavior for real hook packs. (#58909) Thanks @hxy91819.</li>
<li>Claude CLI/sessions: classify <code>No conversation found with session ID</code> as <code>session_expired</code> so expired CLI-backed conversations clear the stale binding and recover on the next turn. (#65028) thanks @Ivan-Fn.</li>
<li>Context Engine: gracefully fall back to the legacy engine when a third-party context engine plugin fails at resolution time (unregistered id, factory throw, or contract violation), preventing a full gateway outage on every channel. (#66930) Thanks @openperf.</li>
<li>Control UI/chat: keep optimistic user message cards visible during active sends by deferring same-session history reloads until the active run ends, including aborted and errored runs. (#66997) Thanks @scotthuang and @vincentkoc.</li>
<li>Media/Slack: allow host-local CSV and Markdown uploads only when the fallback buffer actually decodes as text, so real plain-text files work without letting opaque non-text blobs renamed to <code>.csv</code> or <code>.md</code> slip past the host-read guard. (#67047) Thanks @Unayung.</li>
<li>Ollama/onboarding: split setup into <code>Cloud + Local</code>, <code>Cloud only</code>, and <code>Local only</code>, support direct <code>OLLAMA_API_KEY</code> cloud setup without a local daemon, and keep Ollama web search on the local-host path. (#67005) Thanks @obviyus.</li>
<li>Webchat/security: reject remote-host <code>file://</code> URLs in the media embedding path. (#67293) Thanks @pgondhi987.</li>
<li>Dreaming/memory-core: use the ingestion day, not the source file day, for daily recall dedupe so repeat sweeps of the same daily note can increment <code>dailyCount</code> across days instead of stalling at <code>1</code>. (#67091) Thanks @Bartok9.</li>
<li>Node-host/tools.exec: let approval binding distinguish known native binaries from mutable shell payload files, while still fail-closing unknown or racy file probes so absolute-path node-host commands like <code>/usr/bin/whoami</code> no longer get rejected as unsafe interpreter/runtime commands. (#66731) Thanks @tmimmanuel.</li>
<li>Auto-reply: poison inbound message dedupe after replay-unsafe provider/runtime failures so retries stay safe before visible progress but cannot duplicate messages after block output, tool side effects, or session progress. Fixes #69303; keeps #58549 and #64606 as duplicate validation. Thanks @martingarramon, @NikolaFC, and @zeroth-blip.</li>
<li>Logging/sessions: apply configured redaction patterns to persisted session transcript text and accept escaped character classes in safe custom redaction regexes, so transcript JSONL no longer keeps matching sensitive text in the clear. Fixes #42982. Thanks @panpan0000.</li>
<li>Agents/OpenAI: keep Responses web search compatible with minimal thinking by raising <code>web_search</code> requests to the lowest supported reasoning effort instead of sending a rejected minimal payload.</li>
<li>Agents/tools: honor the <code>bundle-mcp</code> allowlist token when deciding whether bundled MCP tools are available, so restricted tool policies can still enable bundled MCP without exposing unrelated tools.</li>
<li>Agents/model fallback: jump directly to a known later live-session model redirect instead of walking unrelated fallback candidates, while preserving the already-landed live-session/fallback loop guard. Fixes #57471; related loop family already closed via #58496. Thanks @yuxiaoyang2007-prog.</li>
<li>Skills/memory: restore Chokidar v5 hot reloads by watching concrete skill and memory roots with filters, including SKILL.md removals and deleted skill folders without broad workspace recursion. Fixes #27404, #33585, and #41606. Thanks @shelvenzhou, @08820048, and @rocke2020.</li>
<li>Discord/gateway: count failed health-monitor restart attempts toward cooldown and hourly caps, and evict stale account lifecycle state during channel reloads so repeated Discord gateway recovery cannot loop on old status. Fixes #38596. (#40413) Thanks @jellyAI-dev and @vashquez.</li>
<li>Plugins/CLI: let flag-driven <code>openclaw channels add</code> install the selected channel plugin from its default source without opening an interactive prompt, fixing published npm Telegram setup in stdin-closed automation.</li>
<li>Plugins/startup: load the default <code>memory-core</code> slot during Gateway startup when permitted so active-memory recall can call <code>memory_search</code> and <code>memory_get</code> without requiring an explicit <code>plugins.slots.memory</code> entry, while preserving <code>plugins.slots.memory: "none"</code>.</li>
<li>Plugins/install: materialize plugin-owned root chunks in external bundled-runtime mirrors so staged plugin dependencies resolve under native ESM in packaged installs. Fixes #72058; supersedes #72084. Thanks @amnesia106 and @drvoss.</li>
<li>Plugins/CLI: prefer native require for compiled bundled plugin JavaScript before jiti so read-only config, status, device, and node commands avoid unnecessary transform overhead on slow hosts. Fixes #62842. Thanks @Effet.</li>
<li>Plugins/compat: inventory doctor-side deprecation migrations separately from runtime plugin compatibility so release sweeps preserve needed repairs while enforcing dated removal windows. Thanks @vincentkoc.</li>
<li>Plugins/compat: add missing dated compatibility records for legacy extension-api, memory registration, provider hook/type aliases, runtime aliases, channel SDK helpers, and approval/test utility shims. Thanks @vincentkoc.</li>
<li>Plugins/CLI: refresh the persisted registry after managed plugin files are removed so ClawHub uninstall cannot leave stale <code>plugins list</code> entries.</li>
<li>Plugins/CLI: make plugin install and uninstall config writes conflict-aware, clear stale denylist entries on explicit reinstall/removal, and delete managed plugin files only after config/index commit succeeds.</li>
<li>Plugins: fail <code>plugins update</code> when tracked plugin or hook updates error, keep bundled runtime-dependency repair behind restrictive allowlists, and reject package installs with unloadable extension entries.</li>
<li>Gateway/chat: keep duplicate attachment-backed <code>chat.send</code> retries with the same idempotency key on the documented in-flight path so aborts still target the real active run. Fixes #70139. Thanks @Feelw00.</li>
<li>Plugins: share package entrypoint resolution between install and discovery, reject mismatched <code>runtimeExtensions</code>, and cache bundled runtime-dependency manifest reads during scans.</li>
<li>WhatsApp/Web: keep quiet but healthy linked-device sessions connected by basing the watchdog on WhatsApp Web transport activity, while retaining a longer app-silence cap so frame activity cannot mask a stuck session forever. Fixes #70678; carries forward the focused #71466 approach and keeps #63939 as related configurable-timeout follow-up. Thanks @vincentkoc and @oromeis.</li>
<li>Onboarding/setup: keep first-run config reads, plugin compatibility notices, and post-model sanity checks on cold metadata paths unless the user chooses to browse all models, avoiding full plugin/runtime catalog work between prompts. Thanks @shakkernerd.</li>
<li>Onboarding/auth: run manifest-owned provider auth choices through scoped setup providers so selecting OpenAI Codex browser/device auth no longer loads every provider runtime before OAuth starts. Thanks @shakkernerd.</li>
<li>Onboarding/auth: keep the post-auth default-model policy lookup on manifest/setup metadata so the next prompt appears without loading broad provider runtime. Thanks @shakkernerd.</li>
<li>Onboarding/models: keep skip-auth and provider-scoped model picker prompts off the full global model catalog path, and cache provider catalog hook resolution so setup no longer stalls after auth on large plugin registries. Thanks @shakkernerd.</li>
<li>Gateway/Bonjour: suppress known @homebridge/ciao cancellation and network assertion failures through scoped process handlers so malformed mDNS packets or restricted VPS networking disable/restart Bonjour instead of crashing the gateway. Fixes #67578. Thanks @zenassist26-create.</li>
<li>Discord: keep late clicks on already-resolved exec approval buttons quiet when elevated mode auto-resolved the request, while still surfacing real approval submission failures. Fixes #66906. Thanks @rlerikse.</li>
<li>Agents/subagents: deliver completed yielded-subagent results back to no-thread requester routes via direct fallback when the dormant parent announce turn produces no visible reply, and add QA-lab coverage for the regression. Thanks @vincentkoc.</li>
<li>Gateway/Tailscale: let Tailscale-authenticated Control UI operator sessions with browser device identity skip the device-pairing round trip while still rejecting device-less and node-role connections. Refs #71986. Thanks @jokedul.</li>
<li>Doctor: honor <code>OPENCLAW_SERVICE_REPAIR_POLICY=external</code> by reporting gateway service health while skipping service install/start/restart/bootstrap, supervisor rewrites, and legacy service cleanup for externally managed environments. Thanks @shakkernerd.</li>
<li>CLI/update: run package post-update doctor with <code>--fix</code> so package updates repair config migrations before restart. Thanks @shakkernerd.</li>
<li>CLI/update: retry failed npm global updates with <code>--omit=optional</code> and ignore the superseded first failure when the fallback succeeds. Thanks @shakkernerd.</li>
<li>Plugins/uninstall: migrate and reset <code>plugins.slots.contextEngine</code> alongside memory slots when plugin ids change or selected plugins are removed. Thanks @shakkernerd.</li>
<li>Agents/Discord: keep raw <code>Agent failed before reply</code> runner failures out of Discord group/channel chats and show detailed runner errors in direct chats only when <code>/verbose</code> is enabled.</li>
<li>UI/Windows: quote resolved pnpm <code>.cmd</code> launcher paths before spawning UI install/build/test commands so Node installs under <code>C:\Program Files</code> no longer fail as <code>C:\Program</code>. Fixes #45275. Thanks @Kobevictor, @stoppieboy, and @iubns.</li>
<li>Codex/agent: translate <code>--thinking minimal</code> to <code>low</code> for modern Codex models (gpt-5.5, gpt-5.4, gpt-5.4-mini, gpt-5.2) at request build time so the first turn is accepted instead of paying a wasted call + retry-with-low fallback. Older Codex models still receive <code>minimal</code> directly. Fixes #71946. Thanks @hclsys.</li>
<li>Plugins/uninstall: remove tracked plugin files from their recorded managed extensions root even when the current state directory points somewhere else, so <code>openclaw plugins uninstall --force</code> does not leave the plugin discoverable. Thanks @shakkernerd.</li>
<li>Agents/runtime: add <code>agentRuntime.id</code> as the canonical config key, migrate legacy runtime-policy configs with <code>openclaw doctor --fix</code>, route canonical Anthropic models through <code>claude-cli</code> without passing CLI backend aliases to embedded harness selection, and load CLI backend owner plugins before channel startup. Fixes #71957. Thanks @WolvenRA.</li>
<li>CLI/update: guard Windows scheduled-task stops by state and timeout so auto-update restart cannot hang indefinitely on <code>schtasks /End</code> before stale-listener cleanup. Fixes #69970. Thanks @yangswld and @sherlock-huang.</li>
<li>Windows install/Lobster: execute <code>pnpm.exe</code> directly when <code>npm_execpath</code> points at the native pnpm binary, add an installed-package fallback for the Lobster embedded runtime, and include the Lobster runner regression test in Windows CI. Fixes #69456. Thanks @igormf.</li>
<li>Gateway/install: refresh loaded gateway service installs when the current service embeds stale gateway auth instead of returning already-installed, avoiding LaunchAgent token-mismatch loops after token rotation. Fixes #70752. Thanks @hyspacex.</li>
<li>Update: ignore bundled plugin <code>.openclaw-install-stage</code> directories during global install verification and packaged dist pruning so leftover runtime-dep staging files do not turn successful updates into <code>unexpected packaged dist file</code> failures. Fixes #71752. Thanks @waynegault.</li>
<li>CLI/update: fail package updates when post-update plugin sync fails and refresh legacy npm plugin install records before trusting unchanged artifacts, preventing successful updates from restarting with stale or failed plugin state. Thanks @vincentkoc and @shakkernerd.</li>
<li>Release/update: reject pre-populated bundled plugin <code>.openclaw-install-stage</code> directories, including mixed-case path variants, before package inventory generation so release tarballs cannot ship poisoned runtime-dependency staging debris. Fixes #71752. Thanks @hclsys.</li>
<li>Node runtime: keep node-host retry timers alive across Gateway restarts and exit on terminal credential pauses so supervised nodes do not become silent zombies. Fixes #69800. Thanks @meroli28.</li>
<li>Gateway/plugins: stop persisted WhatsApp auth state from activating bundled channel runtime-dependency repair during startup when <code>channels.whatsapp</code> is absent, avoiding npm/git stalls on packaged Linux installs. Fixes #71994. Thanks @xiao398008.</li>
<li>Gateway/device tokens: enforce caller-scope containment inside token rotation and revocation so pairing-only sessions cannot mutate higher-scope operator tokens. Fixes #71990. Thanks @coygeek.</li>
<li>Plugins/channels: keep security checks, thread-binding placement, provider summaries, health formatting, and message action labels on read-only or already-loaded channel metadata instead of importing full channel runtime. Thanks @shakkernerd.</li>
<li>Plugins/status: keep config-only channel labels and status security summaries from importing plugin runtime modules just to render metadata. Thanks @shakkernerd.</li>
<li>Sessions/channels: stop group-session metadata from loading bundled channel runtime just to classify <code>#channel</code> subjects, using only already-loaded channel capabilities on that path. Thanks @shakkernerd.</li>
<li>Plugins/channels: keep native command and native skill <code>auto</code> defaults on static channel metadata so config, audit, and command-list checks do not load channel runtime just to read those defaults. Thanks @shakkernerd.</li>
<li>CLI/channels: keep channel remove selection and all-channel capabilities summaries on read-only plugin metadata, loading channel runtime only for the selected mutation path. Thanks @shakkernerd.</li>
<li>CLI/models: keep Provider Index preview rows out of <code>models list --all --provider <id></code> when the owning provider plugin is disabled, preserving config authority for cold catalog fallbacks. Thanks @shakkernerd.</li>
<li>CLI/model runs: keep <code>openclaw infer model run</code> on explicit OpenRouter models from loading the full provider catalog or inheriting chat-agent silent-reply policy, restoring non-empty one-shot probe output. Fixes #68791. Thanks @limpredator.</li>
<li>Installer/macOS: rerun Homebrew install steps without the gum spinner when raw-mode ioctl failures occur, and avoid claiming <code>node@24</code> was installed when the Homebrew keg binary is missing. Fixes #70411. Thanks @1fanwang and @dad-io.</li>
<li>Installer: load nvm before Node.js detection so <code>curl | bash</code> installs respect nvm-managed Node instead of stale system Node. Fixes #49556. Thanks @heavenlxj.</li>
<li>Installer/Windows: route PowerShell install failures through a top-level handler so <code>iwr ... | iex</code> returns control to the current shell while direct script-file runs still exit non-zero. Fixes #38054. Thanks @PwrSrg.</li>
<li>CLI/Volta: respawn raw <code>openclaw</code> CLI runs through the named <code>node</code> shim when the current Node executable resolves to <code>volta-shim</code>, avoiding direct shim execution failures in non-interactive shells. Fixes #68672. Thanks @sanchezm86.</li>
<li>Installer: warn when multiple npm global roots contain OpenClaw installs, showing active Node/npm/openclaw plus each install path and version so stale version-manager installs are visible. Fixes #40839. Thanks @zhixianio.</li>
<li>Cron/tasks: recover completed cron task ledger records from durable run logs and job state before marking them <code>lost</code>, reducing false <code>backing session missing</code> audit errors for isolated cron runs and keeping offline CLI audit from treating its empty local cron active-job set as authoritative. Fixes #71963.</li>
<li>Docker: copy patched dependency files into runtime images so downstream <code>pnpm install</code> layers keep working. Fixes #69224. Thanks @gucasbrg.</li>
<li>Package: include patched dependency files in the published npm package so downstream installs can resolve <code>patchedDependencies</code>. (#69224) Thanks @gucasbrg and @vincentkoc.</li>
<li>Plugins/channels: treat malformed bundled channel plugin loaders that return <code>undefined</code> as unavailable instead of crashing config and help paths. Fixes #69044. Thanks @frankhli843 and @vincentkoc.</li>
<li>Scripts/watch: show corrupted dependency package-config recovery guidance when <code>gateway:watch</code> fails during watcher startup, without double-logging unrelated import failures. (#58780) Thanks @roytong9 and @vincentkoc.</li>
<li>Signal: read signal-cli RPC, health checks, and SSE events through Node's HTTP client so Node 24/25 fetch regressions do not break Signal sends or inbound events. Fixes #51716 and #53040. Thanks @Barukimang, @minupla, and @vincentkoc.</li>
<li>Skills/Docker: run npm-backed skill dependency installs with an OpenClaw-managed user prefix so non-root Docker images do not write to <code>/usr/local</code>. Fixes #59601. Thanks @chanjarster and @vincentkoc.</li>
<li>Agents/runtime: submit heartbeat, cron, and exec wakeups as transient runtime context instead of visible user prompts, keeping synthetic system work out of chat transcripts. Fixes #66496 and #66814. Thanks @jeades and @mandomaker.</li>
<li>Telegram: include native quote excerpts automatically for threaded replies and reply tags when the original Telegram text is available, without adding another config knob. Fixes #6975. Thanks @rex05ai.</li>
<li>Node/Linux: make <code>openclaw node install</code> enable and restart the <code>openclaw-node</code> systemd unit instead of the gateway unit on node-only VMs. Fixes #68287. Thanks @dlebee-agent.</li>
<li>Browser/CDP: retry transient raw-CDP WebSocket handshake failures before any browser command is sent, and reconnect stale persistent Playwright CDP sessions for safe tab-list reads without replaying mutating browser actions. Fixes #67728.</li>
<li>Gateway/Linux: retry <code>systemctl --user enable</code> after a second daemon reload when the freshly written gateway unit is not visible yet on migrated systemd installs. Fixes #65184. Thanks @liushuaiiu.</li>
<li>Telegram: preserve exact selected quote text when sending native quote replies, and retry with legacy replies if Telegram rejects quote parameters. (#71952) Thanks @rubencu.</li>
<li>Plugins/CLI: preserve manifest name, description, format, and source metadata in cold <code>openclaw plugins list</code> output without importing plugin runtime. Thanks @shakkernerd.</li>
<li>Security/audit: read channel exposure and plugin allowlist ownership from read-only plugin index metadata so cold audits do not depend on loaded channel runtime. Thanks @shakkernerd.</li>
<li>Plugins/chat: keep <code>/plugins list</code>, <code>/plugins enable</code>, and <code>/plugins disable</code> on the persisted plugin index path so chat plugin management does not load diagnostic/runtime plugin registries before execution. Thanks @shakkernerd.</li>
<li>Plugins/doctor: read workspace plugin status and legacy web-search ownership through installed-index manifest metadata instead of broad manifest registry scans. Thanks @shakkernerd.</li>
<li>CLI/agents: read channel provider status from read-only plugin index metadata for text <code>agents list</code> output instead of the loaded channel registry. Thanks @shakkernerd.</li>
<li>Logging: redact configured secret patterns at console and file-log sink exits so credentials that reach the logger are masked before terminal display or JSONL persistence. Fixes #67953. Thanks @Ziy1-Tan.</li>
<li>Gateway/services: refuse process and service mutations from an older OpenClaw binary when the config was last written by a newer version, preventing split-brain installs from stopping or rewriting newer gateway services. Fixes #57079.</li>
<li>Gateway: reserve <code>/healthz</code> and <code>/readyz</code> ahead of plugin, canvas, and Control UI HTTP stages so liveness/readiness probes still answer when a later route handler stalls. Fixes #69674. Thanks @Xike-Creek.</li>
<li>Logging: load <code>logging.file</code> and redaction settings directly from the active OpenClaw config path in bundled runtimes, so packaged gateways stop falling back to <code>/tmp/openclaw</code>. Fixes #59370, #67168, and #61295. Thanks @KeaneYan, @Pan9hu, and @zsjlovelike.</li>
<li>Logging: rotate file logs at <code>logging.maxFileBytes</code>, keep bounded numbered archives, and make long-lived rolling loggers follow the current-day file instead of suppressing diagnostics or writing stale dated files. Fixes #58583 and #62381. Thanks @jpeghead and @zhaoleink.</li>
<li>Agents/groups: treat clean empty assistant stops as silent <code>NO_REPLY</code> only for always-on groups where silent replies are allowed, while keeping direct and mention-gated sessions on the incomplete-turn retry path. Thanks @MagnaAI.</li>
<li>macOS/Node: keep native remote app nodes from advertising <code>browser.proxy</code>, start browser-capable CLI node services through the restored <code>openclaw node start</code> command, and show an actionable browser-control error when the local control service is missing. Fixes #66637.</li>
<li>Gateway/update: fail package updates when the restarted managed gateway reports the wrong version, including fallback restarts and JSON mode, avoiding false-success mixed-version restarts after macOS LaunchAgent updates. Fixes #71835. Thanks @abhinas90 and @jsompis.</li>
<li>Gateway/update: warn before package updates and bundled plugin runtime-dependency repairs when the target volume appears low on disk space, without blocking installs on best-effort filesystem checks. Fixes #71835. Thanks @abhinas90 and @jsompis.</li>
<li>Plugins/runtime deps: surface activated plugin load failures in health and fail package-update restart verification or doctor repair when bundled runtime deps still cannot load, avoiding false-success repairs. (#71883) Thanks @Solvely-Colin.</li>
<li>Gateway/Linux: include fnm <code>aliases/default/bin</code> in generated service PATHs and let doctor accept either modern fnm aliases or the legacy <code>current/bin</code> symlink, avoiding false PATH repair prompts. Fixes #68169. Thanks @richard-scott.</li>
<li>Installer/Linux: run apt installs with noninteractive dpkg and needrestart settings so fresh Ubuntu 24.04 <code>curl | bash</code> installs do not hang while installing Node.js, Git, or build tools. Fixes #41146. Thanks @iht76, @alexcarv318, @cs3gallery, @firofame, and @cgdusek.</li>
<li>Providers/Bedrock: defer the AWS SDK import until Bedrock discovery actually runs so plugin registration and setup stay lightweight on cold start. Fixes #71690. Thanks @jarvis-ai-gregmoser.</li>
<li>Installer/macOS: stop immediately when Homebrew <code>node@24</code> installation fails and avoid printing PATH advice for missing Homebrew Node installs. Fixes #70411. Thanks @1fanwang.</li>
<li>WhatsApp: remove ack reactions after a visible reply when <code>messages.removeAckAfterReply</code> is enabled, matching other reaction-capable channels. Fixes #26183. Thanks @MrUnforsaken.</li>
<li>Providers/Z.AI: map OpenClaw thinking controls to Z.AI's <code>thinking</code> payload and add opt-in preserved thinking replay via <code>params.preserveThinking</code>, so GLM 5.x can keep prior <code>reasoning_content</code> when requested. Fixes #58680. Thanks @xuanmingguo.</li>
<li>Channels/status: keep read-only channel lists on manifest and package metadata by default, loading setup runtime only for explicit fallback callers. Thanks @shakkernerd.</li>
<li>Plugins: scope setup and web-provider metadata manifest reads to explicit plugin ids when callers already know the owning plugin set. Thanks @vincentkoc.</li>
<li>Plugins/onboarding: defer onboarding install-record index writes until the guarded config commit so setup failures cannot leave the plugin index ahead of <code>openclaw.json</code>. Thanks @shakkernerd.</li>
<li>Plugins/registry: resolve web provider ownership from the installed plugin index instead of broad manifest scans on secret, tool, and pricing paths. Thanks @shakkernerd.</li>
<li>Config/providers: accept <code>video</code> and <code>audio</code> in configured model <code>input</code> values and preserve them in provider catalog entries. Fixes #20721. Thanks @alvinttang.</li>
<li>Models/auth: honor the parent <code>--agent</code> flag for auth write commands (<code>add</code>, <code>login</code>, <code>setup-token</code>, <code>paste-token</code>, and the GitHub Copilot shortcut) so OAuth/API-key/token results are written to the requested agent store instead of the default agent. Fixes #71864. (#71933) Thanks @balric-seo.</li>
<li>TTS: strip model-emitted TTS directives from streamed block text before channel delivery, including directives split across adjacent blocks, while preserving the accumulated raw reply for final-mode synthesis. Fixes #38937.</li>
<li>TTS: keep explicit <code>provider=...</code> directive keys scoped to that provider and warn on unsupported keys instead of letting another speech provider consume overlapping keys. Fixes #60131.</li>
<li>TTS/Feishu: normalize final-mode streamed TTS-only audio before delivery so generated voice-note files use the same safe media path and native voice routing as normal final replies. Fixes #71920.</li>
<li>Feishu: transcribe inbound voice-note audio with the shared media audio path before agent dispatch and keep raw Feishu <code>file_key</code> payloads out of message text. Fixes #67120 and #61876.</li>
<li>Tasks: terminalize async Gateway agent task records from the Gateway run result while preserving aborted, failed, and cancelled outcomes instead of leaving completed runs stuck as active or lost. (#71905) Thanks @likewen-tech.</li>
<li>WhatsApp: let authorized group voice-note transcripts satisfy mention gating before reply dispatch, while keeping unmentioned transcripts in pending group history. Fixes #44908.</li>
<li>Media understanding: carry channel voice-note preflight state into attachment selection so WhatsApp, Feishu, Telegram, and Discord do not transcribe the same inbound audio twice. Fixes #70580.</li>
<li>TTS/BlueBubbles: deliver compatible auto-TTS audio as iMessage voice memo bubbles instead of plain MP3/CAF file attachments. Fixes #16848.</li>
<li>TTS: resolve voice-note and voice-memo routing from channel plugin capabilities instead of speech-core-owned channel id lists.</li>
<li>ACP: send subagent and async-task completion wakes to external ACP harnesses as plain prompts instead of OpenClaw internal runtime-context envelopes, while keeping those envelopes out of ACP transcripts.</li>
<li>TTS/status: show configured TTS model, voice, and sanitized custom endpoint in <code>/status</code>, preserve OpenAI-compatible TTS instructions on custom endpoints, and retry empty Microsoft/Edge TTS output once. Addresses #46602, #47232, and #43936. Thanks @leekuangtao, @Huntterxx, and @rex993.</li>
<li>Agents/Gateway: steer agent-driven config edits and restarts through the owner-only <code>gateway</code> tool, document <code>config.schema.lookup</code> as the field-doc source, and warn against using <code>gateway stop && gateway start</code> as a restart substitute on macOS. Fixes #71929. Thanks @ygc3817922006-sketch.</li>
<li>Media understanding/audio: inject a deterministic transcript placeholder for too-small voice notes so agents do not hallucinate transcription or provider failures. Fixes #48944. Thanks @eulicesl.</li>
<li>Providers/vLLM: send Nemotron 3 chat-template kwargs when thinking is off and honor configured <code>params.chat_template_kwargs</code> for OpenAI-compatible completions, so vLLM/Nemotron replies stay visible instead of becoming thinking-only. Fixes #71891. Thanks @jmystaki-create and @dennis-lynch.</li>
<li>Channels/replies: strip copied inbound metadata blocks from user-facing assistant replies and model replay history, so Discord/vLLM sessions do not leak <code>Conversation info</code> / <code>UNTRUSTED ... message body</code> envelopes after a model echoes them. Fixes #71847. Thanks @jmystaki-create.</li>
<li>Subagents/memory: keep inter-session completion wakes out of memory and dreaming session exports, and strip internal runtime-context blocks from realtime Control UI chat events.</li>
<li>Agents/Claude: treat zero-token empty <code>stop</code> turns as failed provider output, retry once, repair replay, and allow configured model fallback instead of preserving them as successful silent replies. Fixes #71880. Thanks @MagnaAI.</li>
<li>Tasks: normalize task lifecycle timestamps at create, update, and restore time, and report retained lost tasks as audit warnings until their cleanup window expires. (#71871) Thanks @likewen-tech.</li>
<li>Diagnostics/OTEL: treat normal early model stream cleanup as a completed model call instead of exporting a misleading <code>StreamAbandoned</code> error span. Thanks @vincentkoc.</li>
<li>Gateway/pairing: stop corrupt or unreadable device/node pairing stores from being treated as empty state, preserving <code>paired.json</code> for repair instead of overwriting approved pairings. Fixes #71873. Thanks @iret77.</li>
<li>ACP: keep <code>/acp</code> management commands, plus local <code>/status</code> and <code>/unfocus</code>, on the Gateway path inside ACP-bound threads so they are not consumed as ACP prompt text. Fixes #66298. Thanks @kindomLee.</li>
<li>ACPX: stop probing ACP agents during normal Gateway startup; the embedded backend now registers without spawning Codex/ACP child processes unless <code>OPENCLAW_ACPX_RUNTIME_STARTUP_PROBE=1</code> is explicitly set.</li>
<li>CLI/image edit: accept <code>--size</code>, <code>--aspect-ratio</code>, and <code>--resolution</code> on <code>openclaw infer image edit</code> and report all supported edit flags from <code>capability inspect image.edit</code>. Thanks @Pinghuachiu.</li>
<li>ACP: wait for the configured runtime backend to become healthy before startup identity reconciliation, avoiding transient acpx warnings during Gateway boot. Fixes #40566.</li>
<li>Channels/ACP bindings: time out configured binding readiness checks instead of letting Discord preflight hang forever when an ACP target never settles. Fixes #68776.</li>
<li>Control UI: hide the chat loading skeleton during background history reloads when existing messages or active stream content are already visible, avoiding reload flashes on high-latency local gateways. Fixes #71844. Thanks @WolvenRA.</li>
<li>Control UI: keep locally optimistic chat messages visible when a history reload temporarily returns empty, avoiding lost first-turn messages on high-latency gateways. Fixes #71878. Thanks @WolvenRA.</li>
<li>Control UI: keep chat history limits based on visible messages after filtering heartbeat and control-only transcript rows, so recent hidden entries no longer make older visible replies disappear. Thanks @WolvenRA.</li>
<li>Agents/images: scrub old <code>[media attached: ...]</code>, <code>[Image: source: ...]</code>, and <code>media://inbound/...</code> markers from pruned model replay context so stale media refs are not rehydrated as fresh prompt images. Fixes #71868. Thanks @jmeadlock.</li>
<li>Docker/Bonjour: disable Bonjour/mDNS advertising by default for bundled Compose gateways on bridge networking, while keeping host/macvlan opt-in with <code>OPENCLAW_DISABLE_BONJOUR=0</code>. Fixes #71879. Thanks @gbballpack.</li>
<li>CLI/status: label the OpenClaw Serve/Funnel setting as <code>Tailscale exposure</code> and show daemon state separately when available, so <code>gateway.tailscale.mode: "off"</code> no longer reads like the Tailscale daemon is stopped. Fixes #71790. Thanks @pesvobodak.</li>
<li>Plugins/Bonjour: stop ciao mDNS watchdog failures from looping forever when the advertiser stays stuck in <code>probing</code> or <code>announcing</code>; Bonjour now disables itself for the current Gateway process after repeated failed restarts while the Gateway keeps running. Fixes #69011. Thanks @siddharthaagarwalofficial-ux, @FiredMosquito831, and @spikefcz.</li>
<li>Gateway/Fly.io: seed Control UI allowed origins from the actual runtime bind and port so CLI-driven non-loopback starts do not crash before config exists. Fixes #71823.</li>
<li>macOS/remote SSH: keep discovered gateway hosts in <code>gateway.remote.sshTarget</code> while pinning SSH transport URLs to the local loopback tunnel, so browser automation does not regress into blocked non-loopback <code>ws://</code> endpoints. Fixes #67336.</li>
<li>Gateway/proxy: bootstrap env proxy dispatching from direct Gateway startup so provider and plugin network requests honor <code>HTTPS_PROXY</code>/<code>HTTP_PROXY</code> before the first embedded agent attempt runs. (#71833) Thanks @mjamiv.</li>
<li>Plugins/runtime deps: verify clean npm installs actually place requested bundled runtime packages in the managed install root, reporting exact missing specs instead of a false successful repair. (#71883) Thanks @Solvely-Colin.</li>
<li>Plugins/discovery: ignore stale <code>plugins.load.paths</code> aliases that point back at packaged bundled plugin directories and have doctor remove them, keeping bundled plugins on the runtime-deps staging path.</li>
<li>Models/LM Studio: preserve <code>@iq*</code> quant suffixes in model refs and provider matching so <code>/model lmstudio/...@iq3_xxs</code> keeps the exact LM Studio variant. Fixes #71474. (#71486) Thanks @Bartok9, @XinwuC, and @Sanjays2402.</li>
<li>Matrix/cron: preserve the live Matrix delivery target when creating implicit announce reminder jobs so mixed-case room IDs are not reconstructed from lowercased session keys. Fixes #71798.</li>
<li>Feishu: accept Schema 2.0 card action callbacks that report <code>context.open_chat_id</code> instead of legacy <code>context.chat_id</code>, so button callbacks no longer drop as malformed. Fixes #71670. Thanks @eddy1068.</li>
<li>Feishu: keep synthetic card-action and bot-menu ids out of platform reply targets, using the real card callback message id when Feishu provides one and plain-sending otherwise. Fixes #71673. Thanks @eddy1068.</li>
<li>Plugins/QQ Bot: prefer an installed QQ Bot plugin that declares it replaces the bundled <code>qqbot</code> channel, preventing duplicate <code>qqbot_channel_api</code> and <code>qqbot_remind</code> tool registration noise. Fixes #63102.</li>
<li>Browser automation: keep stable tab ids and labels attached when Chromium replaces the raw target after form submissions or other action-triggered navigations, and return the replacement <code>targetId</code> from <code>/act</code> when the match is provable. Fixes #46137.</li>
<li>QQ Bot: make <code>qqbot_remind</code> schedule, list, and remove Gateway cron jobs directly for owner-authorized senders instead of returning <code>cronParams</code> and relying on a follow-up generic <code>cron</code> tool call. Fixes #70865. (#70937) Thanks @GaosCode.</li>
<li>Agents/ACP: hide <code>sessions_spawn</code> ACP runtime options unless an ACP backend is loaded, and make <code>/acp doctor</code> call out <code>plugins.allow</code> blocking bundled <code>acpx</code>. Thanks @vincentkoc.</li>
<li>Agents/Codex: keep ACP prompt/skill routing hidden unless an ACP runtime backend is available, and warn in doctor when enabled Codex plugin configs still route <code>openai-codex/*</code> models through PI. Thanks @vincentkoc.</li>
<li>Media delivery: avoid sending generated image attachments twice when the assistant reply already includes explicit <code>MEDIA:</code> lines for the same turn, and reject unsafe remote <code>MEDIA:</code> URLs before delivery. Thanks @pashpashpash.</li>
<li>Codex harness: ignore retryable app-server error notifications after Codex recovers, and preserve the real nested error message for terminal app-server failures instead of replacing it with a generic failure. Thanks @pashpashpash.</li>
<li>Agents/Codex: prepare native Codex sub-agent session metadata without a nested Gateway session patch and add a focused Docker smoke for the app-server sub-agent path. Thanks @vincentkoc.</li>
<li>Agents/subagents: keep queued subagent announces session-only when the requester has no external channel target, avoiding ambiguous multi-channel delivery failures. Fixes #59201. Thanks @larrylhollan.</li>
<li>Image understanding: preserve configured provider-prefixed vision model metadata when callers request the model without the provider prefix, so custom image models keep their <code>input: ["text", "image"]</code> capability. Fixes #33185. Thanks @Kobe9312 and @vincentkoc.</li>
<li>Plugins/install: restore the previous plugin index records if a concurrent config write conflict interrupts install, update, or uninstall metadata commits. Thanks @shakkernerd.</li>
<li>Plugins/install: reject native plugin archives that do not include a valid <code>openclaw.plugin.json</code>, preventing manifestless archives from writing install records that later show missing-manifest diagnostics. Thanks @shakkernerd.</li>
<li>Plugins/uninstall: remove tracked managed plugin install directories even when the persisted install path differs from the default id-derived target, while still refusing deletes outside the managed extensions root. Thanks @shakkernerd.</li>
<li>Plugins/update: restore previous plugin index records if core update or channel setup hits a concurrent config write conflict after plugin metadata changes. Thanks @shakkernerd.</li>
<li>Plugins/onboarding: defer channel/provider plugin install records until the owning config write commits, keeping setup failures from advancing the plugin index ahead of <code>openclaw.json</code>. Thanks @shakkernerd.</li>
<li>Plugins/config: route configure and agent setup writes with pending plugin install records through the plugin index commit helper so provider onboarding metadata is not stripped by plain config writes. Thanks @shakkernerd.</li>
<li>Plugins/channels: merge pending channel plugin install records with the existing plugin index before config writes, preserving unrelated tracked installs during channel setup, resolve, remove, and capability repair flows. Thanks @shakkernerd.</li>
<li>Plugins/config: defer shipped <code>plugins.installs</code> index migration during config writes until the guarded config commit window and roll it back if the config write fails before commit. Thanks @shakkernerd.</li>
<li>Sessions: keep embedded runtime context out of the visible user prompt by sending it as a hidden next-turn custom message, and teach doctor to repair affected 2026.4.24 transcripts with duplicated prompt-rewrite branches. Fixes #71761.</li>
<li>Gateway/subagents: keep direct-loopback backend RPCs authenticated with the shared gateway token/password off stale CLI paired-device scope baselines, so internal calls no longer hit <code>scope-upgrade</code> pairing prompts while remote, browser, node, device-token, and explicit-device paths still require normal pairing approval. Fixes #63548.</li>
<li>Providers/Azure OpenAI: give deployment-scoped image generation requests a longer 600s default timeout so slow <code>gpt-image-2</code> generations can complete without a per-call <code>timeoutMs</code>. Fixes #71705. Thanks @voytas75.</li>
<li>Gateway/plugins: link source-checkout bundled runtime dependency caches instead of recursively copying <code>node_modules</code> on the gateway main thread, preventing local status, node, and skill probes from timing out during startup cache restores.</li>
<li>Skills/remote nodes: only expose remote macOS skill bins for connected nodes, clear stale bin matches when node probes fail, and include probe command, timeout, bin count, and connection state in timeout logs.</li>
<li>Skills/remote nodes: recognize <code>system.which</code> object-map responses when probing connected macOS nodes, so Linux gateways can expose macOS-only skills such as Apple Notes when the required binaries are installed remotely. Fixes #71877. Thanks @miguelarios.</li>
<li>CLI/gateway: keep diagnostic probes from creating first-time read-only device pairings, while still reusing cached device tokens for detailed read probes. Fixes #71766. Thanks @SunboZ.</li>
<li>CLI/plugins: keep <code>message</code> startup, <code>channels logs</code>, <code>agents delete</code>, and <code>agents set-identity</code> off broad plugin preloading; message delivery still loads plugins when the action actually runs.</li>
<li>Image understanding: resolve configured image models such as local LM Studio vision entries before reporting <code>Unknown model</code> when the discovery registry has not registered that provider. Fixes #66486. Thanks @zhanggpcsu.</li>
<li>QQ Bot: ignore self-echoed bot messages using the outbound ref-index marker, preventing mirrored replies from re-entering the agent loop while still allowing users to quote bot replies. Fixes #71912. Thanks @wangyc6003.</li>
<li>Sessions: separate reset freshness from session-store <code>updatedAt</code>, so heartbeat, cron, exec, and gateway bookkeeping no longer prevent configured daily/idle resets from rolling long-running channel sessions. Fixes #68315, #63732, #63820, and #69083. Thanks @maxatv, @longhairedsi, @bradfreels, and @akessel56.</li>
<li>Sessions: clear queued system-event notices during <code>/new</code>, <code>/reset</code>, gateway <code>sessions.reset</code>, and daily/idle rollover so stale background updates cannot leak into the first prompt of the fresh session. Fixes #66864. Thanks @opeyio, @Magicray1217, and @cedillarack.</li>
<li>CLI/agents: keep <code>agents bind</code>, <code>agents unbind</code>, and <code>agents bindings</code> on setup-safe channel metadata paths so they do not preload bundled plugin runtimes or stage runtime dependencies. Fixes #71743.</li>
<li>Plugins/registry: preserve explicit disabled plugin records during registry migration without persisting every unused bundled plugin discovered on disk. Thanks @shakkernerd.</li>
<li>Windows/native: keep CLI startup and bundled provider plugin loading off Windows ESM raw-path failure paths, fixing native onboarding/install smoke on Node 24.</li>
<li>Plugins/doctor: read bundled channel doctor capabilities through the same packaged plugin directory resolver used by plugin loading, so published installs keep Matrix DM allowlist repairs on <code>channels.matrix.dm.*</code> instead of writing invalid top-level <code>dmPolicy</code> keys. Fixes #71757.</li>
<li>Plugins/Windows: keep bundled plugin Jiti loaders off the native import path on Windows so channel plugins such as Telegram no longer crash with <code>ERR_UNSUPPORTED_ESM_URL_SCHEME</code> on <code>C:\...</code> paths. Fixes #71749. Thanks @smeyer9.</li>
<li>Providers/Ollama: use Ollama's current <code>/api/web_search</code> endpoint and honor <code>https://ollama.com</code> model-provider base URLs for Ollama Web Search. Fixes #71741. Thanks @madhvidua.</li>
<li>Memory/Ollama: serialize Ollama memory embedding batches and add an inline batch timeout override, with longer defaults for local/self-hosted embedding providers.</li>
<li>Sessions/usage: exclude compaction checkpoint transcript snapshots from usage totals and session discovery, while keeping old checkpoint files removable.</li>
<li>CLI/agents: keep <code>openclaw agents list --json</code> on the config-only path by default, avoiding bundled plugin loading unless callers request <code>--bindings</code>. Fixes #71739. Thanks @kaloster.</li>
<li>Plugins/install: force plugin dependency installs to stay project-local even when inherited npm config requests global installs, so successful installs still materialize the plugin's staged <code>node_modules</code>.</li>
<li>Providers/Google: transcode Gemini TTS PCM to Opus for voice-note targets so WhatsApp and other native voice-note replies can play as voice messages.</li>
<li>TTS/WhatsApp: mark non-Opus provider output as voice-note intent so channel delivery transcodes MP3/WebM replies to Ogg/Opus PTT audio.</li>
<li>Plugins/runtime deps: reuse existing external bundled-plugin stage roots when mirrored plugin roots are inspected again, avoiding second-generation <code>openclaw-unknown-*</code> stages and repeated first-turn restaging. Fixes #71599.</li>
<li>iOS/macOS Talk Mode: allow <code>talk.speechLocale</code> to set the speech recognition locale for non-English voice conversations. Fixes #44688.</li>
<li>Plugins/providers: honor explicit plugin candidate lists instead of reading a persisted registry snapshot from local state, keeping candidate-scoped provider discovery hermetic.</li>
<li>Plugins/doctor: keep bundled plugin runtime-dependency repairs inside the managed OpenClaw stage even when user npm prefix/global config points npm at <code>$HOME/node_modules</code>. Fixes #71730.</li>
<li>ACP/sessions_spawn: reject normal OpenClaw config agent ids when callers explicitly request <code>runtime="acp"</code>, while allowing agents configured with <code>runtime.type="acp"</code> to resolve to their ACP harness id. Fixes #63914.</li>
<li>ACP/sessions_spawn: apply <code>runTimeoutSeconds</code> to ACP child turns and dispatch those turns on the background subagent lane, so quota-stalled ACP harnesses do not occupy the main agent lane indefinitely. Fixes #68823.</li>
<li>ACP/oneshot: reconcile runtime session identity before closing completed oneshot ACP runs, so finished <code>sessions.json</code> entries do not stay stuck with <code>acp.identity.state="pending"</code>.</li>
<li>ACPX: bundle <code>acpx@0.6.1</code> so unsupported generic model overrides fail clearly instead of silently falling back to the target adapter default.</li>
<li>ACP/models: document that non-Codex ACP model overrides require adapter support for ACP <code>models</code> plus <code>session/set_model</code>, so unsupported harnesses fail clearly instead of silently falling back to their defaults.</li>
<li>Plugins/Voice Call: treat missing provider credentials as setup-incomplete during Gateway startup and log the missing keys as a warning instead of a runtime startup error, while keeping explicit command/tool errors when used.</li>
<li>Android/Talk Mode: prevent duplicate TTS playback when fast or repeated final chat events arrive while Talk Mode is waiting for its own response. Fixes #46546.</li>
<li>Tooling/check:changed: pass parent heavy-check lock markers to lint lanes so <code>pnpm check:changed</code> no longer waits on its own <code>lint:extensions</code> child.</li>
<li>CLI/completion: dedupe provider auth flags before registering <code>openclaw onboard</code> options, so completion-cache refresh during update no longer fails when stale core fallback flags overlap plugin manifest flags. Fixes #71667.</li>
<li>Diagnostics/trace: report live context usage from the current prompt snapshot instead of provider turn totals, avoiding false near-full context spikes on cached or tool-heavy runs.</li>
<li>Providers/Google: honor <code>models.providers.google.request.allowPrivateNetwork</code> for Gemini TTS and telephony TTS, matching Google image generation and media understanding. (#71723) Thanks @ro-hansolo.</li>
<li>Providers/MiniMax: register <code>minimax-portal</code> for music and video generation, preserving OAuth auth and regional MiniMax base URLs across the shared <code>music_generate</code> and <code>video_generate</code> tools. (#63241) Thanks @tars90percent.</li>
<li>Providers/onboarding: keep Runway and Alibaba Model Studio out of the text-inference setup picker by scoping their video-generation auth choices to the media setup flow. (#65856) Thanks @Jah-yee.</li>
<li>Plugins/Bonjour: stop the gateway from crash-looping on <code>CIAO PROBING CANCELLED</code> when the mDNS watchdog cancels a stuck probe. Restores the rejection-handler wiring dropped during the bonjour plugin migration and shares unhandled-rejection state across module instances so plugin-staged copies of <code>openclaw/plugin-sdk/runtime</code> register into the same handler set the host consults. Especially affects Docker on macOS, where mDNS probing reliably hits the watchdog. Thanks @troyhitch.</li>
<li>Google Meet: report pinned Chrome nodes as offline or missing capabilities in setup/join diagnostics, keep inaccessible nodes out of auto-selection, and preflight local BlackHole/SoX requirements before agents try local Chrome.</li>
<li>Providers/MiniMax: route <code>image-01</code> requests to the dedicated image generation endpoint while preserving CN endpoint selection. Fixes #61149. Thanks @mushuiyu886.</li>
<li>Plugins/startup: remove ownerless bundled runtime-dependency install locks after a short grace window and include lock owner details when startup times out waiting for a plugin runtime-deps lock.</li>
<li>Plugins/install: anchor bundled runtime-dependency npm installs with an OpenClaw-owned package manifest so Linux updates cannot accidentally write to a parent <code>$HOME/node_modules</code> tree. Fixes #71730.</li>
<li>Plugins/install: pass onboarding plugin config into plugin index writes so local plugin installs outside default discovery roots keep their install records. Thanks @shakkernerd.</li>
<li>Plugins/install: migrate shipped <code>plugins.installs</code> config records into the plugin index while stripping them from runtime config and future writes. Thanks @shakkernerd.</li>
<li>Plugins/install: durably remove shipped <code>plugins.installs</code> from <code>openclaw.json</code> after its records are copied into the plugin index, while rolling back the index write if config cleanup fails. Thanks @shakkernerd.</li>
<li>Plugins/install: keep migrated plugin install records in the plugin index even when the plugin manifest is missing or invalid, so update, uninstall, inspect, and audit can still recover broken installs. Thanks @shakkernerd.</li>
<li>Plugins/security: keep plugin audit JSON check ids stable while reporting plugin index install-record findings with updated wording. Thanks @shakkernerd.</li>
<li>CLI/config: reject direct <code>plugins.installs</code> edits with guidance to use <code>openclaw plugins install</code>, <code>openclaw plugins update</code>, or <code>openclaw plugins uninstall</code> instead. Thanks @shakkernerd.</li>
<li>Live tests/voice: accept common STT variants for OpenClaw and ElevenLabs brand names so provider smoke tests fail on real regressions rather than equivalent transcripts.</li>
<li>Agents/replies: forward sanitized underlying agent failure details on external channels instead of replacing unknown failures with a generic retry message.</li>
<li>CLI/MCP: translate OpenClaw <code>mcp.servers.*.transport</code> entries into Claude/Gemini CLI <code>type</code> fields so streamable HTTP MCP servers load in CLI backend sessions. (#71724) Thanks @Blockchain-Oracle.</li>
<li>Browser/CDP: honor configured remote and <code>attachOnly</code> CDP HTTP/WebSocket timeouts when opening tabs through raw CDP or <code>/json/new</code> fallback. (#54238) Thanks @FuncWei.</li>
<li>WhatsApp/TTS: send visible text separately from PTT voice-note audio instead of relying on hidden voice-note captions. Fixes #51081.</li>
<li>Browser/client: avoid telling agents to restart OpenClaw for dispatcher timeouts on external browser profiles such as <code>attachOnly</code>, remote CDP, and existing-session. (#40815) Thanks @0xsline.</li>
<li>Agents/TTS: preserve <code>[[audio_as_voice]]</code> directives on trusted text tool-result <code>MEDIA:</code> payloads so generated audio still delivers as a voice note. (#46535) Thanks @azade-c.</li>
<li>Agents/TTS: keep queued tool media when an assistant ends with <code>NO_REPLY</code> on non-block delivery paths, so media-only generated audio replies still send. (#60025) Thanks @bradlind1.</li>
<li>Telegram/STT: frame inbound voice-note transcripts as machine-generated, untrusted text in agent context while preserving raw transcript mention detection. Closes #33360. Thanks @smartchainark.</li>
<li>Subagents/browser: show an actionable <code>/tools</code> notice when browser automation is configured but filtered out by the active tool profile, and document that coding-profile agents should use <code>tools.alsoAllow: ["browser"]</code> rather than subagent allowlists alone.</li>
<li>Control UI/Quick Settings: persist the assistant avatar override to browser local storage (mirroring the user avatar) so uploaded image data URLs no longer fail config validation with "Too big: expected string to have <=200 characters". Also lift the gateway-side <code>ui.assistant.avatar</code> length cap to match the user avatar size budget for non-UI clients writing the field directly. Thanks @BunsDev.</li>
<li>Plugin SDK: share diagnostic event subscriptions across duplicate source/dist module graphs so legacy root SDK imports still receive runtime diagnostic events.</li>
<li>Agents/Bedrock: prevent empty assistant stream-error turns from poisoning Converse replay by persisting, repairing, and replaying a non-empty fallback block. Fixes #71572. (#71627) Thanks @openperf.</li>
<li>Agents/Anthropic/Bedrock: strip thinking blocks with missing, empty, or blank replay signatures before provider conversion, falling back to non-empty omitted-reasoning text when needed so corrupted signed-thinking history no longer poisons subsequent turns. Fixes #45010. (#70054) Thanks @castaples.</li>
<li>Agents/Anthropic/Bedrock: preserve stripped thinking-only assistant replay turns with non-empty omitted-reasoning text so provider adapters keep strict user/assistant turn shape. Thanks @wujiaming88.</li>
<li>ACP/Codex: pass <code>sessions_spawn(runtime="acp")</code> model and thinking overrides into Codex ACP startup, normalize <code>openai-codex/*</code> refs and slash reasoning suffixes, and recognize managed Codex ACP wrapper commands without blocking current <code>gpt-5.5</code> sessions. Fixes #40393. (#71643) Thanks @91wan.</li>
<li>Browser/CDP: make readiness diagnostics use the same discovery-first fallback as reachability for bare <code>ws://</code> Browserless and Browserbase CDP URLs. Fixes #69532.</li>
<li>Browser/CDP: explain that loopback Browserless or other externally managed CDP services need <code>attachOnly: true</code> and matching Browserless <code>EXTERNAL</code> endpoint when reporting local port ownership conflicts, and fall back to the configured bare WebSocket root when a discovered Browserless endpoint rejects CDP. Fixes #49815.</li>
<li>Gateway/reload: preserve indefinite <code>gateway.reload.deferralTimeoutMs: 0</code> semantics for channel hot reload deferrals so active agent runs are not interrupted by a forced channel restart. (#71637) Thanks @Poo-Squirry.</li>
<li>Agents/tool results: cap persisted Pi tool-result details and strip hidden diagnostics before provider conversion, preventing large debug payloads from bloating session transcripts. (#71637) Thanks @Poo-Squirry.</li>
<li>ACP/OpenCode: update the bundled acpx runtime to 0.6.0 and cover the OpenCode ACP bind path in Docker live tests.</li>
<li>Providers/OpenCode Go: add DeepSeek V4 Pro and DeepSeek V4 Flash to the Go catalog while the bundled Pi registry catches up. Fixes #71587.</li>
<li>Providers/OpenCode Go: route DeepSeek V4 Pro/Flash through the OpenAI-compatible Go endpoint and suppress invalid <code>reasoning_effort: "off"</code> payloads, fixing tool-enabled requests for <code>opencode-go/deepseek-v4-flash</code>. Fixes #71683.</li>
<li>Plugins/model defaults: run Skill Workshop review, Active Memory recall, and session-memory slug generation on the configured agent default model instead of the hardcoded OpenAI SDK fallback when hook context lacks model metadata. Fixes #71659.</li>
<li>Providers/Venice: fill the required DeepSeek V4 <code>reasoning_content</code> placeholder for <code>venice/deepseek-v4-pro</code> and <code>venice/deepseek-v4-flash</code> replay turns without sending native DeepSeek <code>thinking</code> controls that Venice rejects. Fixes #71628.</li>
<li>Browser/existing-session: support per-profile Chrome MCP command/args, map <code>cdpUrl</code> to <code>--browserUrl</code> or <code>--wsEndpoint</code>, and avoid combining endpoint flags with <code>--userDataDir</code>. Fixes #47879, #48037, and #62706. Thanks @puneet1409, @zhehao, and @madkow1001.</li>
<li>Media/plugins: bound MIME sniffing and ZIP archive preflight before handing untrusted files to <code>file-type</code> or <code>jszip</code>, reducing parser CPU and memory exposure for attachments and ClawHub plugin archives. Thanks @vincentkoc.</li>
<li>Memory-host SDK: use trusted env-proxy mode for remote embedding and batch HTTP calls only when Undici will proxy that target, preserving SSRF DNS pinning for <code>ALL_PROXY</code>-only and <code>NO_PROXY</code> bypass cases. Fixes #52162. (#71506) Thanks @DhtIsCoding.</li>
<li>Gateway/dashboard: render Control UI and WebSocket links with <code>https://</code>/<code>wss://</code> when <code>gateway.tls.enabled=true</code>, including <code>openclaw gateway status</code>. Fixes #71494. (#71499) Thanks @deepkilo.</li>
<li>Agents/OpenAI-compatible: default proxy/local completions tool requests to <code>tool_choice: "auto"</code> when tools are present, so providers enter native tool-calling mode instead of replying with plain-text tool directives. (#71472) Thanks @Speed-maker.</li>
<li>OpenAI image generation: use <code>gpt-5.5</code> for the Codex OAuth responses transport instead of the retired <code>gpt-5.4</code> model, fixing 500s from ChatGPT Codex image generation. Fixes #71513. Thanks @baolongl.</li>
<li>OpenAI image generation: route transparent-background default-model requests to <code>gpt-image-1.5</code>, document the expected <code>image_generate</code> call shape, and keep Azure/custom OpenAI-compatible deployment names untouched.</li>
<li>Google video generation: download direct MLDev Veo <code>video.uri</code> results instead of passing them through the Files API path, fixing 404s after successful generation/polling. Fixes #71200. Thanks @panhaishan.</li>
<li>Google video generation: fall back to the REST <code>predictLongRunning</code> Veo endpoint for text-only SDK 404s while keeping reference image/video generation on the SDK path. Fixes #62309 and #63008. (#62343) Thanks @leoleedev.</li>
<li>MiniMax music generation: switch the bundled default model from the unsupported <code>music-2.5+</code> id to the current <code>music-2.6</code> API model. Fixes #64870 and addresses the music default from #62315. Thanks @noahclanman and @edwardzheng1.</li>
<li>Cron: record jobs interrupted by a gateway restart as failed at their original <code>runningAtMs</code>, skip unsafe startup replay, and disable interrupted one-shot jobs so they show a visible failure instead of silently disappearing or duplicating work. Fixes #59056, #61343, #63657, and #59301. Thanks @ponchoooPenguin, @daemic24, @myradon, and @hikiwibot.</li>
<li>Cron tool: recover flat top-level schedule shorthand such as <code>cron</code>, <code>tz</code>, and <code>staggerMs</code> before gateway validation, so model-generated cron add/update calls preserve cron jitter settings. Thanks @tyxben.</li>
<li>Cron: hydrate flat legacy job rows with top-level <code>cron</code>, <code>tz</code>, <code>session</code>, and <code>message</code> fields into canonical schedule, target, and payload objects before startup recomputes run times. Fixes #43351.</li>
<li>Agents/replies: let pending group chat history trigger bare mentioned turns without treating metadata-only inbound context as user input. Fixes #71489. (#71520) Thanks @SymbolStar.</li>
<li>Google media generation: strip a configured trailing <code>/v1beta</code> from Google music/video provider base URLs before calling the Google GenAI SDK, preventing doubled <code>/v1beta/v1beta</code> paths. Fixes #63240. (#63258) Thanks @Hybirdss.</li>
<li>Discord: restore direct-message voice-note preflight transcription and classify URL-only Ogg/Opus voice attachments as audio while skipping partial attachments without usable URLs. Fixes #61314 and #64803.</li>
<li>Plugins/build: copy bundled plugin skill trees into <code>dist-runtime</code>, broaden Windows symlink-copy fallbacks, and fingerprint runtime dependencies from <code>lstat</code> so symlink-like directory entries cannot crash staging.</li>
<li>Google Chat: preserve reply text when a typing indicator message is deleted or can no longer be updated, so media captions and first text chunks are resent instead of silently disappearing. (#71498) Thanks @colin-lgtm.</li>
<li>Cron: tolerate malformed legacy job rows in startup, main-session system-event payloads, and human-readable <code>cron list</code> output so missing <code>state</code>, <code>payload.text</code>, or display fields no longer crash the scheduler or CLI. Fixes #66016, #65916, #64137, #57872, #59968, #63813, #52804, and #43163. (#71509) Thanks @vincentkoc.</li>
<li>CLI/models: make <code>openclaw models scan</code> fall back to public OpenRouter free-model metadata when no <code>OPENROUTER_API_KEY</code> is configured, avoid config secret resolution for explicit <code>--no-probe</code> scans, and apply the scan timeout to the OpenRouter catalog request.</li>
<li>Feishu: keep streaming cards to one live card per turn, flush throttled card edits after meaningful text boundaries, and skip exact block/partial repeats so tool-heavy replies do not duplicate card output. Thanks @allan0509.</li>
<li>Feishu: finish the streaming-card duplicate closeout by stripping leaked reasoning tags, preserving cross-block partial snapshots, enabling topic-thread streaming cards, omitting the generic <code>main</code> card header, surfacing transient tool/compaction status, and cleaning streaming state after close failures. Thanks @sesame437, @Vicky-v7, @maoku-family, @Pengxiao-Wang, and @Maple778.</li>
<li>Telegram: recover incomplete partial-stream previews by falling back to a final send when an ambiguous final edit failure would otherwise retain a strict prefix of the answer. Fixes #71525. (#71554) Thanks @sahilsatralkar.</li>
<li>Control UI/chat: collapse assistant token/model context details behind an explicit Context disclosure and show full dates in message footers, making historical transcript timing clear without noisy default metadata. (#71337) Thanks @BunsDev.</li>
<li>OpenAI/Codex OAuth: explain <code>unsupported_country_region_territory</code> token-exchange failures with a proxy/region hint instead of surfacing a generic OAuth error. Fixes #51175. (#71501) Thanks @vincentkoc and @wulala-xjj.</li>
<li>Browser/Linux: fall back to headless mode for local managed profiles on hosts without a display server, while preserving explicit per-profile headed overrides and reporting the headless source. (#60953) Thanks @rrpsantos.</li>
<li>Telegram: remove the startup persisted-offset <code>getUpdates</code> preflight so polling restarts do not self-conflict before the runner starts. Fixes #69304. (#69779) Thanks @chinar-amrutkar.</li>
<li>Telegram: keep the polling stall watchdog active even when grammY reports the runner as not running while its task is still pending, so a rebuilt transport cannot leave <code>getUpdates</code> silent until a manual gateway restart. Fixes #69064. Thanks @LDLoeb.</li>
<li>Subagents: fall back to direct completion delivery when the parent announce turn finishes without a visible payload, so child results still reach channel-backed requester sessions.</li>
<li>Subagents: tell parent agents to use <code>sessions_yield</code> while waiting for child completion events, preventing GPT-5 fast runs from ending silently after spawning workers.</li>
<li>Browser/Playwright: ignore benign already-handled route races during guarded navigation so browser-page tasks no longer fail when Playwright tears down a route mid-flight. (#68708) Thanks @Steady-ai.</li>
<li>Browser/CLI: lazy-load browser command groups and plugin runtime services so <code>openclaw browser --help</code> can render without loading the full browser automation stack. Fixes #65400. (#65460, #66640) Thanks @pandego and @Tianworld.</li>
<li>Browser/CLI: serve precomputed <code>openclaw browser --help</code> text from CLI startup metadata, avoiding the full plugin/config startup path for the common help invocation.</li>
<li>Browser/downloads: seed managed Chrome profiles with OpenClaw download prefs and capture unmanaged click-triggered downloads under the guarded downloads directory, while explicit download waiters still own their target file. (#64558) Thanks @Pearcekieser.</li>
<li>Browser/Chrome: stop passing redundant <code>--disable-setuid-sandbox</code> when <code>browser.noSandbox</code> is enabled; <code>--no-sandbox</code> remains the effective sandbox opt-out. (#67939) Thanks @sebykrueger.</li>
<li>Browser/client: stop telling agents to permanently avoid the browser after transient timeout or cancellation failures; keep the no-retry hint for persistent unavailable/rate-limit cases. (#46505) Thanks @jriff.</li>
<li>Browser/aria snapshots: bind <code>format=aria</code> <code>axN</code> refs to live DOM nodes through backend DOM ids when Playwright is available, so follow-up browser actions can use those refs without timing out. (#62434) Thanks @MrKipler.</li>
<li>Telegram: prevent duplicate in-process long pollers for the same bot token and add clearer <code>getUpdates</code> conflict diagnostics for external duplicate pollers. Fixes #56230. Thanks @Co-Messi.</li>
<li>Browser/Linux: detect Chromium-based installs under <code>/opt/google</code>, <code>/opt/brave.com</code>, <code>/usr/lib/chromium</code>, and <code>/usr/lib/chromium-browser</code> before asking users to set <code>browser.executablePath</code>. (#48563) Thanks @lupuletic.</li>
<li>Sessions/browser: close tracked browser tabs when idle, daily, <code>/new</code>, or <code>/reset</code> session rollover archives the previous transcript, preventing tabs from leaking past the old session. Thanks @jakozloski.</li>
<li>Sessions/forking: fall back to transcript-estimated parent token counts when cached totals are stale or missing, so oversized thread forks start fresh instead of cloning the full parent transcript. Thanks @jalehman.</li>
<li>OpenAI/Codex: send Codex Responses system prompts through top-level <code>instructions</code> while preserving the existing native Codex payload controls.</li>
<li>MCP/CLI: retire bundled MCP runtimes at the end of one-shot <code>openclaw agent</code> and <code>openclaw infer model run</code> gateway/local executions, so repeated scripted runs do not accumulate stdio MCP child processes. Fixes #71457. Thanks @spartoviMD.</li>
<li>OpenAI/Codex image generation: canonicalize legacy <code>openai-codex.baseUrl</code> values such as <code>https://chatgpt.com/backend-api</code> to the Codex Responses backend before calling <code>gpt-image-2</code>, matching the chat transport. Fixes #71460. Thanks @GodsBoy.</li>
<li>Control UI: make <code>/usage</code> use the fresh context snapshot for context percentage, and include cache-write tokens in the Usage overview cache-hit denominator. Fixes #47885. Thanks @imwyvern and @Ante042.</li>
<li>GitHub Copilot: preserve encrypted Responses reasoning item IDs during replay so Copilot can validate encrypted reasoning payloads across requests. (#71448) Thanks @a410979729-sys.</li>
<li>GitHub Copilot: never rewrite connection-bound reasoning item IDs regardless of whether <code>encrypted_content</code> is present, fixing a 400 "Encrypted content item_id did not match" error with <code>gpt-5.3-codex</code> and future Codex models that fall through to the forward-compat catch-all with <code>reasoning: false</code>. Also recognize Codex-named models as reasoning-capable so they inherit the correct capability flags. Refs #68735. Thanks @InvalidPandaa.</li>
<li>Agents/replies: recover final-answer text when streamed assistant chunks contain only whitespace, preventing completed turns from surfacing as empty-payload errors. Fixes #71454. (#71467) Thanks @Sanjays2402.</li>
<li>Feishu/TTS: transcode voice-intent MP3 and other audio replies to Ogg/Opus before sending native Feishu audio bubbles, while keeping ordinary MP3 attachments as files. Fixes #61249 and #37868. Thanks @sg1416-zg and @ycjlb2023-peteryi.</li>
<li>WhatsApp/TTS: transcode MP3/WebM audio, including Microsoft Edge TTS output, to Ogg/Opus before sending PTT voice notes.</li>
<li>QQBot/TTS: honor plain <code>audioAsVoice</code> replies by synthesizing TTS to native QQ voice messages, and mark inbound voice-only messages as audio media without exposing raw voice paths to generic media context.</li>
<li>Providers/SenseAudio: add bundled SenseAudio batch audio transcription through <code>tools.media.audio</code> with <code>SENSEAUDIO_API_KEY</code> auth. (#66943) Thanks @Fl0rencess720.</li>
<li>Providers/MiniMax: let TTS use MiniMax portal OAuth and Token Plan credentials before falling back to <code>MINIMAX_API_KEY</code>, and include current TTS HD model ids. Fixes #55017. Thanks @zx15210404690-hash.</li>
<li>Telegram/webhook: acknowledge validated webhook updates before running bot middleware, keeping slow agent turns from tripping Telegram delivery retries while preserving per-chat processing lanes. Fixes #71392. Thanks @joelforsberg46-source.</li>
<li>MCP/config reload: hot-apply <code>mcp.*</code> changes by disposing cached session MCP runtimes, and dispose bundled MCP runtimes during gateway shutdown so removed <code>mcp.servers</code> entries reap child processes promptly. Fixes #60656. Thanks @xieyuanqing.</li>
<li>Active Memory: keep silent recall sub-agent billing/auth failures out of shared auth-profile cooldown state, so a Claude CLI extra-usage rejection cannot disable normal Claude-backed turns. Fixes #71284. (#71539) Thanks @vishutdhar and @obviyus.</li>
<li>Auth/Claude CLI: sync refreshed Claude CLI OAuth credentials into the managed auth profile so long-running Claude CLI runs stop falling back to stale OpenClaw snapshots. (#70902) Thanks @starvex.</li>
<li>Sessions: make <code>sessions_spawn(mode="session")</code> errors name usable alternatives when the current channel cannot bind subagent threads. Fixes #67400. (#67790) Thanks @stainlu.</li>
<li>Agents/Claude CLI: pass the OpenClaw system prompt through Claude's prompt-file flag so Windows runs avoid argv length failures without changing system prompt semantics. Fixes #69158. (#69211) Thanks @skylee-01, @cassioanorte, @Syu0, and @Stache73.</li>
<li>Agents/CLI sessions: bind <code>google-gemini-cli</code> session auth-epoch to the Google account identity in <code>~/.gemini/oauth_creds.json</code>, so Gemini-backed agents resume their conversation after gateway restart instead of minting a fresh session, and stale bindings are invalidated when the authenticated Google account changes. Fixes #70973. (#71076) Thanks @openperf.</li>
<li>Slack: stop treating user mentions in assistant-authored message edit blocks as sender attribution, preventing edited bot messages from spoofing a mentioned DM user. (#71700) Thanks @vincentkoc.</li>
<li>Codex: consume unauthorized bound conversation inbound claims before they can fall through to other claim handlers or enqueue Codex turns. (#71702) Thanks @vincentkoc.</li>
<li>Codex media understanding: require approval-checked app-server image turns while explicitly declining tool, file, permission, and elicitation approval requests for the bounded image worker. (#71703) Thanks @vincentkoc.</li>
<li>Agents/Claude CLI: allow large live <code>stream-json</code> JSONL lines up to the existing per-turn raw limit, preventing large Telegram, WebChat, MCP, and image turns from aborting on the old stdout buffer cap. Fixes #71793, #71080, and #70766. (#71897) Thanks @chacher86, @shivamgrover21, and @tpjordan.</li>
<li>Agents/Claude CLI: unwrap nested Claude result envelopes in CLI JSON output so delegated agent responses surface as final text instead of raw result JSON. (#66819) Thanks @mraleko.</li>
<li>Agents/Claude CLI: apply the configured 1M context window override to eligible Claude CLI Opus and Sonnet models when <code>context1m</code> is enabled. (#70863) Thanks @bidadh.</li>
<li>Models/status: report fresh Claude CLI native auth instead of stale stored <code>anthropic:claude-cli</code> profile expiry when local credentials are current. Fixes #71256. (#71332) Thanks @matthiasjanke and @neeravmakwana.</li>
<li>CLI backends: compact OpenClaw transcripts after over-budget CLI turns and reseed fresh CLI sessions from the compacted transcript instead of stale external resume state. Fixes #68329. (#71916) Thanks @obviyus.</li>
<li>Telegram: keep default tool progress messages visible when answer preview streaming is disabled. (#71825) Thanks @VACInc.</li>
<li>Configure/models: clear deselected model fallbacks when updating the model picker allowlist, including provider-scoped setup flows. (#71596) Thanks @rubencu.</li>
<li>Agents/streaming: strip namespaced <code><antml:thinking></code> reasoning tags from streamed assistant replies before user-visible text is emitted. (#69288) Thanks @xialonglee.</li>
</ul>
<p><a href="https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md">View full changelog</a></p>
]]></description>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.4.15/OpenClaw-2026.4.15.zip" length="47501638" type="application/octet-stream" sparkle:edSignature="JUG3cicpJqCQDvp7VYoN6qBuN4Kn4s0+QQFjlMR69OZlwViLdiStPIHa+1vpuoR4miYhJc9knSDVCFzSfQuYCQ=="/>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.4.25/OpenClaw-2026.4.25.zip" length="48125363" type="application/octet-stream" sparkle:edSignature="RnQ01wCFgupauUdwOFan+XPGZhBJi/w3sgJYA5EaasbeGrduDHBGw1e9Zj2Lqb4ud8e6Q+tRcJVfxh5KKSEIDg=="/>
</item>
<item>
<title>2026.4.14</title>
<pubDate>Tue, 14 Apr 2026 14:08:09 +0000</pubDate>
<title>2026.4.24</title>
<pubDate>Sat, 25 Apr 2026 19:34:45 +0000</pubDate>
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
<sparkle:version>2026041490</sparkle:version>
<sparkle:shortVersionString>2026.4.14</sparkle:shortVersionString>
<sparkle:version>2026042490</sparkle:version>
<sparkle:shortVersionString>2026.4.24</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[<h2>OpenClaw 2026.4.14</h2>
<h3>Changes</h3>
<description><![CDATA[<h2>OpenClaw 2026.4.24</h2>
<h3>Highlights</h3>
<ul>
<li>OpenAI Codex/models: add forward-compat support for <code>gpt-5.4-pro</code>, including Codex pricing/limits and list/status visibility before the upstream catalog catches up. (#66453) Thanks @jepson-liu.</li>
<li>Telegram/forum topics: surface human topic names in agent context, prompt metadata, and plugin hook metadata by learning names from Telegram forum service messages. (#65973) Thanks @ptahdunbar.</li>
<li>Google Meet joins OpenClaw as a bundled participant plugin, with personal Google auth, Chrome/Twilio realtime sessions, paired-node Chrome support, artifact/attendance exports, and recovery tooling for already-open Meet tabs.</li>
<li>DeepSeek V4 Flash and V4 Pro are in the bundled catalog, V4 Flash is the onboarding default, and DeepSeek thinking/replay behavior is fixed for follow-up tool-call turns.</li>
<li>Talk, Voice Call, and Google Meet can use realtime voice loops that consult the full OpenClaw agent for deeper tool-backed answers.</li>
<li>Browser automation gets coordinate clicks, longer default action budgets, per-profile headless overrides, and steadier tab reuse/recovery.</li>
<li>Plugin and model infrastructure is lighter at startup: static model catalogs, manifest-backed model rows, lazy provider dependencies, and external runtime-dependency repair for packaged installs.</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Agents/Ollama: forward the configured embedded-run timeout into the global undici stream timeout tuning so slow local Ollama runs no longer inherit the default stream cutoff instead of the operator-set run timeout. (#63175) Thanks @mindcraftreader and @vincentkoc.</li>
<li>Models/Codex: include <code>apiKey</code> in the codex provider catalog output so the Pi ModelRegistry validator no longer rejects the entry and silently drops all custom models from every provider in <code>models.json</code>. (#66180) Thanks @hoyyeva.</li>
<li>Tools/image+pdf: normalize configured provider/model refs before media-tool registry lookup so image and PDF tool runs stop rejecting valid Ollama vision models as unknown just because the tool path skipped the usual model-ref normalization step. (#59943) Thanks @yqli2420 and @vincentkoc.</li>
<li>Slack/interactions: apply the configured global <code>allowFrom</code> owner allowlist to channel block-action and modal interactive events, require an expected sender id for cross-verification, and reject ambiguous channel types so interactive triggers can no longer bypass the documented allowlist intent in channels without a <code>users</code> list. Open-by-default behavior is preserved when no allowlists are configured. (#66028) Thanks @eleqtrizit.</li>
<li>Media-understanding/attachments: fail closed when a local attachment path cannot be canonically resolved via <code>realpath</code>, so a <code>realpath</code> error can no longer downgrade the canonical-roots allowlist check to a non-canonical comparison; attachments that also have a URL still fall back to the network fetch path. (#66022) Thanks @eleqtrizit.</li>
<li>Agents/gateway-tool: reject <code>config.patch</code> and <code>config.apply</code> calls from the model-facing gateway tool when they would newly enable any flag enumerated by <code>openclaw security audit</code> (for example <code>dangerouslyDisableDeviceAuth</code>, <code>allowInsecureAuth</code>, <code>dangerouslyAllowHostHeaderOriginFallback</code>, <code>hooks.gmail.allowUnsafeExternalContent</code>, <code>tools.exec.applyPatch.workspaceOnly: false</code>); already-enabled flags pass through unchanged so non-dangerous edits in the same patch still apply, and direct authenticated operator RPC behavior is unchanged. (#62006) Thanks @eleqtrizit.</li>
<li>Google image generation: strip a trailing <code>/openai</code> suffix from configured Google base URLs only when calling the native Gemini image API so Gemini image requests stop 404ing without breaking explicit OpenAI-compatible Google endpoints. (#66445) Thanks @dapzthelegend.</li>
<li>Telegram/forum topics: persist learned topic names to the Telegram session sidecar store so agent context can keep using human topic names after a restart instead of relearning from future service metadata. (#66107) Thanks @obviyus.</li>
<li>Doctor/systemd: keep <code>openclaw doctor --repair</code> and service reinstall from re-embedding dotenv-backed secrets in user systemd units, while preserving newer inline overrides over stale state-dir <code>.env</code> values. (#66249) Thanks @tmimmanuel.</li>
<li>Ollama/OpenAI-compat: send <code>stream_options.include_usage</code> for Ollama streaming completions so local Ollama runs report real usage instead of falling back to bogus prompt-token counts that trigger premature compaction. (#64568) Thanks @xchunzhao and @vincentkoc.</li>
<li>Doctor/plugins: cache external <code>preferOver</code> catalog lookups within each plugin auto-enable pass so large <code>agents.list</code> configs no longer peg CPU and repeatedly reread plugin catalogs during doctor/plugins resolution. (#66246) Thanks @yfge.</li>
<li>GitHub Copilot/thinking: allow <code>github-copilot/gpt-5.4</code> to use <code>xhigh</code> reasoning so Copilot GPT-5.4 matches the rest of the GPT-5.4 family. (#50168) Thanks @jakepresent and @vincentkoc.</li>
<li>Memory/embeddings: preserve non-OpenAI provider prefixes when normalizing OpenAI-compatible embedding model refs so proxy-backed memory providers stop failing with <code>Unknown memory embedding provider</code>. (#66452) Thanks @jlapenna.</li>
<li>Agents/local models: clarify low-context preflight hints for self-hosted models, point config-backed caps at the relevant OpenClaw setting, and stop suggesting larger models when <code>agents.defaults.contextTokens</code> is the real limit. (#66236) Thanks @ImLukeF.</li>
<li>Browser/SSRF: restore hostname navigation under the default browser SSRF policy while keeping explicit strict mode reachable from config, and keep managed loopback CDP <code>/json/new</code> fallback requests on the local CDP control policy so browser follow-up fixes stop regressing normal navigation or self-blocking local CDP control. (#66386) Thanks @obviyus.</li>
<li>Models/Codex: canonicalize the legacy <code>openai-codex/gpt-5.4-codex</code> runtime alias to <code>openai-codex/gpt-5.4</code> while still honoring alias-specific and canonical per-model overrides. (#43060) Thanks @Sapientropic and @vincentkoc.</li>
<li>Browser/SSRF: preserve explicit strict browser navigation mode for legacy <code>browser.ssrfPolicy.allowPrivateNetwork: false</code> configs by normalizing the legacy alias to the canonical strict marker instead of silently widening those installs to the default non-strict hostname-navigation path.</li>
<li>Onboarding/custom providers: use <code>max_tokens=16</code> for OpenAI-compatible verification probes so stricter custom endpoints stop rejecting onboarding checks that only need a tiny completion. (#66450) Thanks @WuKongAI-CMU.</li>
<li>Agents/subagents: emit the subagent registry lazy-runtime stub on the stable dist path that both source and bundled runtime imports resolve, so the follow-up dist fix no longer still fails with <code>ERR_MODULE_NOT_FOUND</code> at runtime. (#66420) Thanks @obviyus.</li>
<li>Media-understanding/proxy env: auto-upgrade provider HTTP helper requests to trusted env-proxy mode only when <code>HTTP_PROXY</code>/<code>HTTPS_PROXY</code> is active and the target is not bypassed by <code>NO_PROXY</code>, so remote media-understanding and transcription requests stop failing local DNS pre-resolution in proxy-only environments without widening SSRF bypasses. (#52162) Thanks @mjamiv and @vincentkoc.</li>
<li>Telegram/media downloads: let Telegram media fetches trust an operator-configured explicit proxy for target DNS resolution after hostname-policy checks, so proxy-backed installs stop failing <code>could not download media</code> on Bot API file downloads after the DNS-pinning regression. (#66245) Thanks @dawei41468 and @vincentkoc.</li>
<li>Browser: keep loopback CDP readiness checks reachable under strict SSRF defaults so OpenClaw can reconnect to locally started managed Chrome. (#66354) Thanks @hxy91819.</li>
<li>Agents/context engine: compact engine-owned sessions from the first tool-loop delta and preserve ingest fallback when <code>afterTurn</code> is absent, so long-running tool loops can stay bounded without dropping engine state. (#63555) Thanks @Bikkies.</li>
<li>OpenAI Codex/auth: keep malformed Codex CLI auth-file diagnostics on the debug logger instead of stdout so interactive command output stays clean while auth read failures remain traceable. (#66451) Thanks @SimbaKingjoe.</li>
<li>Discord/native commands: return the real status card for native <code>/status</code> interactions instead of falling through to the synthetic <code>✅ Done.</code> ack when the generic dispatcher produces no visible reply. (#54629) Thanks @tkozzer and @vincentkoc.</li>
<li>Hooks/Ollama: let LLM-backed session-memory slug generation honor an explicit <code>agents.defaults.timeoutSeconds</code> override instead of always aborting after 15 seconds, so slow local Ollama runs stop silently dropping back to generic filenames. (#66237) Thanks @dmak and @vincentkoc.</li>
<li>Media/transcription: remap <code>.aac</code> filenames to <code>.m4a</code> for OpenAI-compatible audio uploads so AAC voice notes stop failing MIME-sensitive transcription endpoints. (#66446) Thanks @ben-z.</li>
<li>UI/chat: replace marked.js with markdown-it so maliciously crafted markdown can no longer freeze the Control UI via ReDoS. (#46707) Thanks @zhangfnf.</li>
<li>Auto-reply/send policy: keep <code>sendPolicy: "deny"</code> from blocking inbound message processing, so the agent still runs its turn while all outbound delivery is suppressed for observer-style setups. (#65461, #53328) Thanks @omarshahine.</li>
<li>BlueBubbles: lazy-refresh the Private API server-info cache on send when reply threading or message effects are requested but status is unknown, so sends no longer silently degrade to plain messages when the 10-minute cache expires. (#65447, #43764) Thanks @omarshahine.</li>
<li>Heartbeat/security: force owner downgrade for untrusted <code>hook:wake</code> system events [AI-assisted]. (#66031) Thanks @pgondhi987.</li>
<li>Browser/security: enforce SSRF policy on snapshot, screenshot, and tab routes [AI]. (#66040) Thanks @pgondhi987.</li>
<li>Microsoft Teams/security: enforce sender allowlist checks on SSO signin invokes [AI]. (#66033) Thanks @pgondhi987.</li>
<li>Config/security: redact <code>sourceConfig</code> and <code>runtimeConfig</code> alias fields in <code>redactConfigSnapshot</code> [AI]. (#66030) Thanks @pgondhi987.</li>
<li>Agents/context engines: run opt-in turn maintenance as idle-aware background work so the next foreground turn no longer waits on proactive maintenance. (#65233) Thanks @100yenadmin.</li>
<li>Plugins/status: report the registered context-engine IDs in <code>plugins inspect</code> instead of the owning plugin ID, so non-matching engine IDs and multi-engine plugins are classified correctly. (#58766) Thanks @zhuisDEV.</li>
<li>Context engines: reject resolved plugin engines whose reported <code>info.id</code> does not match their registered slot id, so malformed engines fail fast before id-based runtime branches can misbehave. (#63222) Thanks @fuller-stack-dev.</li>
<li>WhatsApp: patch installed Baileys media encryption writes during OpenClaw postinstall so the default npm/install.sh delivery path waits for encrypted media files to finish flushing before readback, avoiding transient <code>ENOENT</code> crashes on image sends. (#65896) Thanks @frankekn.</li>
<li>Gateway/update: unify service entrypoint resolution around the canonical bundled gateway entrypoint so update, reinstall, and doctor repair stop drifting between stale <code>dist/entry.js</code> and current <code>dist/index.js</code> paths. (#65984) Thanks @mbelinky.</li>
<li>Heartbeat/Telegram topics: keep isolated heartbeat replies on the bound forum topic when <code>target=last</code>, instead of dropping them into the group root chat. (#66035) Thanks @mbelinky.</li>
<li>Browser/CDP: let managed local Chrome readiness, status probes, and managed loopback CDP control bypass browser SSRF policy for their own loopback control plane, so OpenClaw no longer misclassifies a healthy child browser as "not reachable after start". (#65695, #66043) Thanks @mbelinky.</li>
<li>Gateway/sessions: stop heartbeat, cron-event, and exec-event turns from overwriting shared-session routing and origin metadata, preventing synthetic <code>heartbeat</code> targets from poisoning later cron or user delivery. (#66073, #63733, #35300) Thanks @mbelinky.</li>
<li>Browser/CDP: let local attach-only <code>manual-cdp</code> profiles reuse the local loopback CDP control plane under strict default policy and remote-class probe timeouts, so tabs/snapshot stop falsely reporting a live local browser session as not running. (#65611, #66080) Thanks @mbelinky.</li>
<li>Cron/scheduler: stop inventing short retries when cron next-run calculation returns no valid future slot, and keep a maintenance wake armed so enabled unscheduled jobs recover without entering a refire loop. (#66019, #66083) Thanks @mbelinky.</li>
<li>Cron/scheduler: preserve the active error-backoff floor when maintenance repair recomputes a missing cron next-run, so recurring errored jobs do not resume early after a transient next-run resolution failure. (#66019, #66083, #66113) Thanks @mbelinky.</li>
<li>Outbound/delivery-queue: persist the originating outbound <code>session</code> context on queued delivery entries and replay it during recovery, so write-ahead-queued sends keep their original outbound media policy context after restart instead of evaluating against a missing session. (#66025) Thanks @eleqtrizit.</li>
<li>Memory/Ollama: restore the built-in <code>ollama</code> embedding adapter in memory-core so explicit <code>memorySearch.provider: "ollama"</code> works again, and include endpoint-aware cache keys so different Ollama hosts do not reuse each other's embeddings. (#63429, #66078, #66163) Thanks @nnish16 and @vincentkoc.</li>
<li>Auto-reply/queue: split collect-mode followup drains into contiguous groups by per-message authorization context (sender id, owner status, exec/bash-elevated overrides), so queued items from different senders or exec configs no longer execute under the last queued run's owner-only and exec-approval context. (#66024) Thanks @eleqtrizit.</li>
<li>Dreaming/memory-core: require a live queued Dreaming cron event before the heartbeat hook runs the sweep, so managed Dreaming no longer replays on later heartbeats after the scheduled run was already consumed. (#66139) Thanks @mbelinky.</li>
<li>Control UI/Dreaming: stop Imported Insights and Memory Palace from calling optional <code>memory-wiki</code> gateway methods when the plugin is off, and refresh config before wiki reloads so the Dreaming tab stops showing misleading unknown-method failures. (#66140) Thanks @mbelinky.</li>
<li>Agents/tools: only mark streamed unknown-tool retries as counted when a streamed message actually classifies an unavailable tool, and keep incomplete streamed tool names from resetting the retry streak before the final assistant message arrives. (#66145) Thanks @dutifulbob.</li>
<li>Memory/active-memory: move recalled memory onto the hidden untrusted prompt-prefix path instead of system prompt injection, label the visible Active Memory status line fields, and include the resolved recall provider/model in gateway debug logs so trace/debug output matches what the model actually saw. (#66144) Thanks @Takhoffman.</li>
<li>Memory/QMD: stop treating legacy lowercase <code>memory.md</code> as a second default root collection, so QMD recall no longer searches phantom <code>memory-alt-*</code> collections and builtin/QMD root-memory fallback stays aligned. (#66141) Thanks @mbelinky.</li>
<li>Agents/subagents: ship <code>dist/agents/subagent-registry.runtime.js</code> in npm builds so <code>runtime: "subagent"</code> runs stop stalling in <code>queued</code> after the registry import fails. (#66189) Thanks @yqli2420 and @vincentkoc.</li>
<li>Agents/OpenAI: map <code>minimal</code> thinking to OpenAI's supported <code>low</code> reasoning effort for GPT-5.4 requests, so embedded runs stop failing request validation. Thanks @steipete.</li>
<li>Voice-call/media-stream: resolve the source IP from trusted forwarding headers for per-IP pending-connection limits when <code>webhookSecurity.trustForwardingHeaders</code> and <code>trustedProxyIPs</code> are configured, and reserve <code>maxConnections</code> capacity for in-flight WebSocket upgrades so concurrent handshakes can no longer momentarily exceed the operator-set cap. (#66027) Thanks @eleqtrizit.</li>
<li>Feishu/allowlist: canonicalize allowlist entries by explicit <code>user</code>/<code>chat</code> kind, strip repeated <code>feishu:</code>/<code>lark:</code> provider prefixes, and stop folding opaque Feishu IDs to lowercase, so allowlist matching no longer crosses user/chat namespaces or widens to case-insensitive ID matches the operator did not intend. (#66021) Thanks @eleqtrizit.</li>
<li>Telegram/status commands: let read-only status slash commands bypass busy topic turns, while keeping <code>/export-session</code> on the normal lane so it cannot interleave with an in-flight session mutation. (#66226) Thanks @VACInc and @vincentkoc.</li>
<li>TTS/reply media: persist OpenClaw temp voice outputs into managed outbound media and allow them through reply-media normalization, so voice-note replies stop silently dropping. (#63511) Thanks @jetd1.</li>
<li>Agents/tools: treat Windows drive-letter paths (<code>C:\\...</code>) as absolute when resolving sandbox and read-tool paths so workspace root is not prepended under POSIX path rules. (#54039) Thanks @ly85206559 and @vincentkoc.</li>
<li>Agents/OpenAI: recover embedded GPT-style runs when reasoning-only or empty turns need bounded continuation, with replay-safe retry gating and incomplete-turn fallback when no visible answer arrives. (#66167) thanks @jalehman</li>
<li>Outbound/relay-status: suppress internal relay-status placeholder payloads (<code>No channel reply.</code>, <code>Replied in-thread.</code>, <code>Replied in #...</code>, wiki-update status variants ending in <code>No channel reply.</code>) before channel delivery so internal housekeeping text does not leak to users.</li>
<li>Slack/doctor: add a dedicated doctor-contract sidecar so config warmup paths such as <code>openclaw cron</code> no longer fall back to Slack's broader contract surface, which could trigger Slack-related config-read crashes on affected setups. (#63192) Thanks @shhtheonlyperson.</li>
<li>Hooks/session-memory: pass the resolved agent workspace into gateway <code>/new</code> and <code>/reset</code> session-memory hooks so reset snapshots stay scoped to the right agent workspace instead of leaking into the default workspace. (#64735) Thanks @suboss87 and @vincentkoc.</li>
<li>CLI/approvals: raise the default <code>openclaw approvals get</code> gateway timeout and report config-load timeouts explicitly, so slow hosts stop showing a misleading <code>Config unavailable.</code> note when the approvals snapshot succeeds but the follow-up config RPC needs more time. (#66239) Thanks @neeravmakwana.</li>
<li>Media/store: honor configured agent media limits when saving generated media and persisting outbound reply media, so the store no longer hard-stops those flows at 5 MB before the configured limit applies. (#66229) Thanks @neeravmakwana and @vincentkoc.</li>
<li>Packaged installs: preserve package-root runtime dependencies and their exported subpaths when bundled plugin runtime mirrors fall back to copying shared chunks, fixing Windows npm updates that could fail to load copied <code>dist</code> modules.</li>
<li>Heartbeat: clamp oversized scheduler delays through the shared safe timer helper, preventing <code>every</code> values over Node's timeout cap from becoming a 1 ms crash loop. Fixes #71414. (#71478) Thanks @hclsys.</li>
<li>Telegram: remove the startup persisted-offset <code>getUpdates</code> preflight so polling restarts do not self-conflict before the runner starts. Fixes #69304. (#69779) Thanks @chinar-amrutkar.</li>
<li>Browser/Playwright: ignore benign already-handled route races during guarded navigation so browser-page tasks no longer fail when Playwright tears down a route mid-flight. (#68708) Thanks @Steady-ai.</li>
<li>Browser/aria snapshots: bind <code>format=aria</code> <code>axN</code> refs to live DOM nodes through backend DOM ids when Playwright is available, so follow-up browser actions can use those refs without timing out. (#62434) Thanks @MrKipler.</li>
<li>Telegram: prevent duplicate in-process long pollers for the same bot token and add clearer <code>getUpdates</code> conflict diagnostics for external duplicate pollers. Fixes #56230.</li>
<li>Browser/Linux: detect Chromium-based installs under <code>/opt/google</code>, <code>/opt/brave.com</code>, <code>/usr/lib/chromium</code>, and <code>/usr/lib/chromium-browser</code> before asking users to set <code>browser.executablePath</code>. (#48563) Thanks @lupuletic.</li>
<li>Sessions/browser: close tracked browser tabs when idle, daily, <code>/new</code>, or <code>/reset</code> session rollover archives the previous transcript, preventing tabs from leaking past the old session. Thanks @jakozloski.</li>
<li>Sessions/forking: fall back to transcript-estimated parent token counts when cached totals are stale or missing, so oversized thread forks start fresh instead of cloning the full parent transcript. Thanks @jalehman.</li>
<li>OpenAI/Codex: send Codex Responses system prompts through top-level</li>
</ul>
<code>instructions</code> while preserving the existing native Codex payload controls.
<ul>
<li>MCP/CLI: retire bundled MCP runtimes at the end of one-shot <code>openclaw agent</code> and <code>openclaw infer model run</code> gateway/local executions, so repeated scripted runs do not accumulate stdio MCP child processes. Fixes #71457.</li>
<li>OpenAI/Codex image generation: canonicalize legacy <code>openai-codex.baseUrl</code> values such as <code>https://chatgpt.com/backend-api</code> to the Codex Responses backend before calling <code>gpt-image-2</code>, matching the chat transport. Fixes #71460.</li>
<li>Control UI: make <code>/usage</code> use the fresh context snapshot for context percentage, and include cache-write tokens in the Usage overview cache-hit denominator. Fixes #47885. Thanks @imwyvern and @Ante042.</li>
<li>GitHub Copilot: preserve encrypted Responses reasoning item IDs during replay so Copilot can validate encrypted reasoning payloads across requests. (#71448) Thanks @a410979729-sys.</li>
<li>Agents/replies: recover final-answer text when streamed assistant chunks contain only whitespace, preventing completed turns from surfacing as empty-payload errors. Fixes #71454. (#71467) Thanks @Sanjays2402.</li>
<li>Feishu/TTS: transcode voice-intent MP3 and other audio replies to Ogg/Opus before sending native Feishu audio bubbles, while keeping ordinary MP3 attachments as files. Fixes #61249 and #37868.</li>
<li>Telegram/webhook: acknowledge validated webhook updates before running bot middleware, keeping slow agent turns from tripping Telegram delivery retries while preserving per-chat processing lanes. Fixes #71392. Thanks @joelforsberg46-source.</li>
<li>MCP: retire one-shot embedded bundled MCP runtimes at run end, skip bundle-MCP startup when a runtime tool allowlist cannot reach bundle-MCP tools, and add <code>mcp.sessionIdleTtlMs</code> idle eviction for leaked session runtimes. Fixes #71106, #71110, #70389, and #70808.</li>
<li>MCP/config reload: hot-apply <code>mcp.*</code> changes by disposing cached session MCP runtimes, and dispose bundled MCP runtimes during gateway shutdown so removed <code>mcp.servers</code> entries reap child processes promptly. Fixes #60656.</li>
<li>Gateway/restart continuation: durably hand restart continuations to a session-delivery queue before deleting the restart sentinel, recover queued continuation work after crashy restarts, and fall back to a session-only wake when no channel route survives reboot. (#70780) Thanks @fuller-stack-dev.</li>
<li>Agents/tool-result pruning: harden the tool-result character estimator and context-pruning loops against malformed <code>{ type: "text" }</code> blocks created by void or undefined tool handler results, serializing non-string text payloads for size accounting so they cannot bypass trimming as zero-sized. Fixes #34979. (#51267) Thanks @cgdusek, @alvinttang, and @coffeexcoin.</li>
<li>Daemon/service-env: add Nix Home Manager profile bin directories to generated gateway service PATHs on macOS and Linux, honoring <code>NIX_PROFILES</code> right-to-left precedence and falling back to <code>~/.nix-profile/bin</code> when unset. Fixes #44402. (#59935) Thanks @jerome-benoit.</li>
</ul>
<p><a href="https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md">View full changelog</a></p>
]]></description>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.4.14/OpenClaw-2026.4.14.zip" length="47490719" type="application/octet-stream" sparkle:edSignature="KW4gq3qjhKPSQebRVL/mSgttTOhLVKtnWz7pNCZt29oEZ96yU14OnxxSsmtNHmDi4m7G7gfVOfndp80XKFQlCw=="/>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.4.24/OpenClaw-2026.4.24.zip" length="48033180" type="application/octet-stream" sparkle:edSignature="wxOfxadSZ/9iXMitaC6SA9J6YPZC3P2tkeK7HZPHzjUIlzQTvOl7EjR4aRyXzaYt1N1AK5ba+YhuCwEngrTdCQ=="/>
</item>
</channel>
</rss>

View File

@@ -0,0 +1,16 @@
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.{kt,kts}]
indent_style = space
indent_size = 2
max_line_length = off
ktlint_standard_filename = disabled
ktlint_standard_function-naming = disabled
ktlint_standard_max-line-length = disabled
ktlint_standard_property-naming = disabled

View File

@@ -15,6 +15,7 @@ Status: **extremely alpha**. The app is actively being rebuilt from the ground u
- [x] Request camera/location and other permissions in onboarding/settings flow
- [x] Push notifications for gateway/chat status updates
- [x] Security hardening (biometric lock, token handling, safer defaults)
- [x] Authenticated background presence beacons
- [x] Voice tab full functionality
- [x] Screen tab full functionality
- [ ] Full end-to-end QA and release hardening

View File

@@ -7,284 +7,274 @@ val androidStorePassword = providers.gradleProperty("OPENCLAW_ANDROID_STORE_PASS
val androidKeyAlias = providers.gradleProperty("OPENCLAW_ANDROID_KEY_ALIAS").orNull?.takeIf { it.isNotBlank() }
val androidKeyPassword = providers.gradleProperty("OPENCLAW_ANDROID_KEY_PASSWORD").orNull?.takeIf { it.isNotBlank() }
val resolvedAndroidStoreFile =
androidStoreFile?.let { storeFilePath ->
if (storeFilePath.startsWith("~/")) {
"${System.getProperty("user.home")}/${storeFilePath.removePrefix("~/")}"
} else {
storeFilePath
}
androidStoreFile?.let { storeFilePath ->
if (storeFilePath.startsWith("~/")) {
"${System.getProperty("user.home")}/${storeFilePath.removePrefix("~/")}"
} else {
storeFilePath
}
}
val hasAndroidReleaseSigning =
listOf(resolvedAndroidStoreFile, androidStorePassword, androidKeyAlias, androidKeyPassword).all { it != null }
listOf(resolvedAndroidStoreFile, androidStorePassword, androidKeyAlias, androidKeyPassword).all { it != null }
val wantsAndroidReleaseBuild =
gradle.startParameter.taskNames.any { taskName ->
taskName.contains("Release", ignoreCase = true) ||
Regex("""(^|:)(bundle|assemble)$""").containsMatchIn(taskName)
}
gradle.startParameter.taskNames.any { taskName ->
taskName.contains("Release", ignoreCase = true) ||
Regex("""(^|:)(bundle|assemble)$""").containsMatchIn(taskName)
}
if (wantsAndroidReleaseBuild && !hasAndroidReleaseSigning) {
error(
"Missing Android release signing properties. Set OPENCLAW_ANDROID_STORE_FILE, " +
"OPENCLAW_ANDROID_STORE_PASSWORD, OPENCLAW_ANDROID_KEY_ALIAS, and " +
"OPENCLAW_ANDROID_KEY_PASSWORD in ~/.gradle/gradle.properties.",
)
error(
"Missing Android release signing properties. Set OPENCLAW_ANDROID_STORE_FILE, " +
"OPENCLAW_ANDROID_STORE_PASSWORD, OPENCLAW_ANDROID_KEY_ALIAS, and " +
"OPENCLAW_ANDROID_KEY_PASSWORD in ~/.gradle/gradle.properties.",
)
}
plugins {
id("com.android.application")
id("org.jlleitschuh.gradle.ktlint")
id("org.jetbrains.kotlin.plugin.compose")
id("org.jetbrains.kotlin.plugin.serialization")
alias(libs.plugins.android.application)
alias(libs.plugins.ktlint)
alias(libs.plugins.kotlin.compose)
alias(libs.plugins.kotlin.serialization)
}
android {
namespace = "ai.openclaw.app"
compileSdk = 36
namespace = "ai.openclaw.app"
compileSdk = 36
// Release signing is local-only; keep the keystore path and passwords out of the repo.
signingConfigs {
if (hasAndroidReleaseSigning) {
create("release") {
storeFile = project.file(checkNotNull(resolvedAndroidStoreFile))
storePassword = checkNotNull(androidStorePassword)
keyAlias = checkNotNull(androidKeyAlias)
keyPassword = checkNotNull(androidKeyPassword)
}
}
// Release signing is local-only; keep the keystore path and passwords out of the repo.
signingConfigs {
if (hasAndroidReleaseSigning) {
create("release") {
storeFile = project.file(checkNotNull(resolvedAndroidStoreFile))
storePassword = checkNotNull(androidStorePassword)
keyAlias = checkNotNull(androidKeyAlias)
keyPassword = checkNotNull(androidKeyPassword)
}
}
}
sourceSets {
getByName("main") {
assets.directories.add("../../shared/OpenClawKit/Sources/OpenClawKit/Resources")
}
sourceSets {
getByName("main") {
assets.directories.add("../../shared/OpenClawKit/Sources/OpenClawKit/Resources")
}
}
defaultConfig {
applicationId = "ai.openclaw.app"
minSdk = 31
targetSdk = 36
versionCode = 2026042200
versionName = "2026.4.22"
ndk {
// Support all major ABIs — native libs are tiny (~47 KB per ABI)
abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
}
defaultConfig {
applicationId = "ai.openclaw.app"
minSdk = 31
targetSdk = 36
versionCode = 2026042700
versionName = "2026.4.27"
ndk {
// Support all major ABIs — native libs are tiny (~47 KB per ABI)
abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
}
}
flavorDimensions += "store"
flavorDimensions += "store"
productFlavors {
create("play") {
dimension = "store"
buildConfigField("boolean", "OPENCLAW_ENABLE_SMS", "false")
buildConfigField("boolean", "OPENCLAW_ENABLE_CALL_LOG", "false")
}
create("thirdParty") {
dimension = "store"
buildConfigField("boolean", "OPENCLAW_ENABLE_SMS", "true")
buildConfigField("boolean", "OPENCLAW_ENABLE_CALL_LOG", "true")
}
productFlavors {
create("play") {
dimension = "store"
}
buildTypes {
release {
if (hasAndroidReleaseSigning) {
signingConfig = signingConfigs.getByName("release")
}
isMinifyEnabled = true
isShrinkResources = true
ndk {
debugSymbolLevel = "SYMBOL_TABLE"
}
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
debug {
isMinifyEnabled = false
}
create("thirdParty") {
dimension = "store"
}
}
buildFeatures {
compose = true
buildConfig = true
buildTypes {
release {
if (hasAndroidReleaseSigning) {
signingConfig = signingConfigs.getByName("release")
}
isMinifyEnabled = true
isShrinkResources = true
ndk {
debugSymbolLevel = "SYMBOL_TABLE"
}
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
debug {
isMinifyEnabled = false
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
buildFeatures {
compose = true
buildConfig = true
}
packaging {
resources {
excludes +=
setOf(
"/META-INF/{AL2.0,LGPL2.1}",
"/META-INF/*.version",
"/META-INF/LICENSE*.txt",
"DebugProbesKt.bin",
"kotlin-tooling-metadata.json",
"org/bouncycastle/pqc/crypto/picnic/lowmcL1.bin.properties",
"org/bouncycastle/pqc/crypto/picnic/lowmcL3.bin.properties",
"org/bouncycastle/pqc/crypto/picnic/lowmcL5.bin.properties",
"org/bouncycastle/x509/CertPathReviewerMessages*.properties",
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
lint {
disable +=
setOf(
"AndroidGradlePluginVersion",
"GradleDependency",
"IconLauncherShape",
"NewerVersionAvailable",
)
warningsAsErrors = true
packaging {
resources {
excludes +=
setOf(
"/META-INF/{AL2.0,LGPL2.1}",
"/META-INF/*.version",
"/META-INF/LICENSE*.txt",
"DebugProbesKt.bin",
"kotlin-tooling-metadata.json",
"org/bouncycastle/pqc/crypto/picnic/lowmcL1.bin.properties",
"org/bouncycastle/pqc/crypto/picnic/lowmcL3.bin.properties",
"org/bouncycastle/pqc/crypto/picnic/lowmcL5.bin.properties",
"org/bouncycastle/x509/CertPathReviewerMessages*.properties",
)
}
}
testOptions {
unitTests.isIncludeAndroidResources = true
}
lint {
lintConfig = file("lint.xml")
warningsAsErrors = true
}
testOptions {
unitTests.isIncludeAndroidResources = true
}
}
androidComponents {
onVariants { variant ->
variant.outputs
.filterIsInstance<VariantOutputImpl>()
.forEach { output ->
val versionName = output.versionName.orNull ?: "0"
val buildType = variant.buildType
val flavorName = variant.flavorName?.takeIf { it.isNotBlank() }
val outputFileName =
if (flavorName == null) {
"openclaw-$versionName-$buildType.apk"
} else {
"openclaw-$versionName-$flavorName-$buildType.apk"
}
output.outputFileName = outputFileName
}
}
onVariants { variant ->
variant.outputs
.filterIsInstance<VariantOutputImpl>()
.forEach { output ->
val versionName = output.versionName.orNull ?: "0"
val buildType = variant.buildType
val flavorName = variant.flavorName?.takeIf { it.isNotBlank() }
val outputFileName =
if (flavorName == null) {
"openclaw-$versionName-$buildType.apk"
} else {
"openclaw-$versionName-$flavorName-$buildType.apk"
}
output.outputFileName = outputFileName
}
}
}
kotlin {
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17)
allWarningsAsErrors.set(true)
}
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17)
allWarningsAsErrors.set(true)
}
}
ktlint {
android.set(true)
ignoreFailures.set(false)
filter {
exclude("**/build/**")
}
android.set(true)
ignoreFailures.set(false)
filter {
exclude("**/build/**")
}
}
dependencies {
val composeBom = platform("androidx.compose:compose-bom:2026.03.01")
implementation(composeBom)
androidTestImplementation(composeBom)
val composeBom = platform(libs.androidx.compose.bom)
implementation(composeBom)
androidTestImplementation(composeBom)
implementation("androidx.core:core-ktx:1.17.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.10.0")
implementation("androidx.activity:activity-compose:1.13.0")
implementation("androidx.webkit:webkit:1.15.0")
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.webkit)
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material3:material3")
// material-icons-extended pulled in full icon set (~20 MB DEX). Only ~18 icons used.
// R8 will tree-shake unused icons when minify is enabled on release builds.
implementation("androidx.compose.material:material-icons-extended")
implementation(libs.androidx.compose.ui)
implementation(libs.androidx.compose.ui.tooling.preview)
implementation(libs.androidx.compose.material3)
// material-icons-extended pulled in full icon set (~20 MB DEX). Only ~18 icons used.
// R8 will tree-shake unused icons when minify is enabled on release builds.
implementation(libs.androidx.compose.material.icons.extended)
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation(libs.androidx.compose.ui.tooling)
// Material Components (XML theme + resources)
implementation("com.google.android.material:material:1.13.0")
// Material Components (XML theme + resources)
implementation(libs.material)
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.2")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.11.0")
implementation(libs.kotlinx.coroutines.android)
implementation(libs.kotlinx.serialization.json)
implementation("androidx.security:security-crypto:1.1.0")
implementation("androidx.exifinterface:exifinterface:1.4.2")
implementation("com.squareup.okhttp3:okhttp:5.3.2")
implementation("org.bouncycastle:bcprov-jdk18on:1.84")
implementation("org.commonmark:commonmark:0.28.0")
implementation("org.commonmark:commonmark-ext-autolink:0.28.0")
implementation("org.commonmark:commonmark-ext-gfm-strikethrough:0.28.0")
implementation("org.commonmark:commonmark-ext-gfm-tables:0.28.0")
implementation("org.commonmark:commonmark-ext-task-list-items:0.28.0")
implementation(libs.androidx.security.crypto)
implementation(libs.androidx.exifinterface)
implementation(libs.okhttp)
implementation(libs.bcprov)
implementation(libs.commonmark)
implementation(libs.commonmark.ext.autolink)
implementation(libs.commonmark.ext.gfm.strikethrough)
implementation(libs.commonmark.ext.gfm.tables)
implementation(libs.commonmark.ext.task.list.items)
// CameraX (for node.invoke camera.* parity)
implementation("androidx.camera:camera-core:1.5.2")
implementation("androidx.camera:camera-camera2:1.5.2")
implementation("androidx.camera:camera-lifecycle:1.5.2")
implementation("androidx.camera:camera-video:1.5.2")
implementation("com.google.android.gms:play-services-code-scanner:16.1.0")
// CameraX (for node.invoke camera.* parity)
implementation(libs.androidx.camera.core)
implementation(libs.androidx.camera.camera2)
implementation(libs.androidx.camera.lifecycle)
implementation(libs.androidx.camera.video)
implementation(libs.play.services.code.scanner)
// Unicast DNS-SD (Wide-Area Bonjour) for tailnet discovery domains.
implementation("dnsjava:dnsjava:3.6.4")
// Unicast DNS-SD (Wide-Area Bonjour) for tailnet discovery domains.
implementation(libs.dnsjava)
testImplementation("junit:junit:4.13.2")
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.10.2")
testImplementation("io.kotest:kotest-runner-junit5-jvm:6.1.11")
testImplementation("io.kotest:kotest-assertions-core-jvm:6.1.11")
testImplementation("com.squareup.okhttp3:mockwebserver:5.3.2")
testImplementation("org.robolectric:robolectric:4.16.1")
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:6.0.3")
testImplementation(libs.junit)
testImplementation(libs.kotlinx.coroutines.test)
testImplementation(libs.kotest.runner.junit5)
testImplementation(libs.kotest.assertions.core)
testImplementation(libs.mockwebserver)
testImplementation(libs.robolectric)
testRuntimeOnly(libs.junit.vintage.engine)
}
tasks.withType<Test>().configureEach {
useJUnitPlatform()
useJUnitPlatform()
}
androidComponents {
onVariants(selector().withBuildType("release")) { variant ->
val variantName = variant.name
val variantNameCapitalized = variantName.replaceFirstChar(Char::titlecase)
val stripTaskName = "strip${variantNameCapitalized}DnsjavaServiceDescriptor"
val mergeTaskName = "merge${variantNameCapitalized}JavaResource"
val minifyTaskName = "minify${variantNameCapitalized}WithR8"
val mergedJar =
layout.buildDirectory.file(
"intermediates/merged_java_res/$variantName/$mergeTaskName/base.jar",
)
onVariants(selector().withBuildType("release")) { variant ->
val variantName = variant.name
val variantNameCapitalized = variantName.replaceFirstChar(Char::titlecase)
val stripTaskName = "strip${variantNameCapitalized}DnsjavaServiceDescriptor"
val mergeTaskName = "merge${variantNameCapitalized}JavaResource"
val minifyTaskName = "minify${variantNameCapitalized}WithR8"
val mergedJar =
layout.buildDirectory.file(
"intermediates/merged_java_res/$variantName/$mergeTaskName/base.jar",
)
val stripTask =
tasks.register(stripTaskName) {
inputs.file(mergedJar)
outputs.file(mergedJar)
val stripTask =
tasks.register(stripTaskName) {
inputs.file(mergedJar)
outputs.file(mergedJar)
doLast {
val jarFile = mergedJar.get().asFile
if (!jarFile.exists()) {
return@doLast
}
doLast {
val jarFile = mergedJar.get().asFile
if (!jarFile.exists()) {
return@doLast
}
val unpackDir = temporaryDir.resolve("merged-java-res")
delete(unpackDir)
copy {
from(zipTree(jarFile))
into(unpackDir)
exclude(dnsjavaInetAddressResolverService)
}
delete(jarFile)
ant.invokeMethod(
"zip",
mapOf(
"destfile" to jarFile.absolutePath,
"basedir" to unpackDir.absolutePath,
),
)
}
}
tasks.matching { it.name == mergeTaskName }.configureEach {
finalizedBy(stripTask)
}
tasks.matching { it.name == minifyTaskName }.configureEach {
dependsOn(stripTask)
val unpackDir = temporaryDir.resolve("merged-java-res")
delete(unpackDir)
copy {
from(zipTree(jarFile))
into(unpackDir)
exclude(dnsjavaInetAddressResolverService)
}
delete(jarFile)
ant.invokeMethod(
"zip",
mapOf(
"destfile" to jarFile.absolutePath,
"basedir" to unpackDir.absolutePath,
),
)
}
}
tasks.matching { it.name == mergeTaskName }.configureEach {
finalizedBy(stripTask)
}
tasks.matching { it.name == minifyTaskName }.configureEach {
dependsOn(stripTask)
}
}
}

13
apps/android/app/lint.xml Normal file
View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<lint>
<issue id="AndroidGradlePluginVersion" severity="ignore" />
<issue id="GradleDependency" severity="ignore" />
<issue id="IconLauncherShape" severity="ignore" />
<issue id="NewerVersionAvailable" severity="ignore" />
<!-- OpenClaw uses date-based version codes (yyyyMMddNN), which are high but still below the Android max. -->
<issue id="HighAppVersionCode" severity="ignore" />
<!-- Target SDK follows the current release train; bump only after platform compatibility testing. -->
<issue id="OldTargetApi" severity="ignore" />
</lint>

View File

@@ -3,6 +3,7 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission
android:name="android.permission.NEARBY_WIFI_DEVICES"
@@ -11,8 +12,6 @@
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
<uses-permission
@@ -20,7 +19,6 @@
android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
@@ -40,7 +38,7 @@
<application
android:name=".NodeApp"
android:allowBackup="true"
android:allowBackup="false"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
@@ -52,7 +50,7 @@
<service
android:name=".NodeForegroundService"
android:exported="false"
android:foregroundServiceType="dataSync" />
android:foregroundServiceType="dataSync|microphone" />
<service
android:name=".node.DeviceNotificationListenerService"
android:label="@string/app_name"

View File

@@ -34,7 +34,7 @@ fun parseAssistantLaunchIntent(intent: Intent?): AssistantLaunchRequest? {
AssistantLaunchRequest(
source = "app_action",
prompt = prompt,
autoSend = prompt != null,
autoSend = false,
)
}

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