12311 Commits

Author SHA1 Message Date
Hiago Silva
07307a7973
style: fix indentation 2026-03-15 12:50:28 -03:00
Hiago Silva
133fb1a300
style: fix indentation 2026-03-15 11:40:30 -03:00
Hiago Silva
91d96821b0
style: fix formatter issues 2026-03-15 08:56:36 -03:00
Hiago Silva
d251551998
fix: avoid breaking behavior for empty text 2026-03-15 08:52:05 -03:00
Hiago Silva
bb506c4db1
style: fix formatter issues 2026-03-15 08:42:39 -03:00
Hiago Silva
729ef4f267
fix: address review comments (guard order + error message) 2026-03-15 08:27:42 -03:00
Hiago Silva
e179a3291b
improve: add empty-text guard and retry for Edge TTS
Follow-up to PR #43385

Implements reviewer suggestions:

- Add pre-check for empty or whitespace-only text
- Retry once if Edge TTS produces a zero-byte file
- Include file size in error message for debugging
2026-03-15 08:02:49 -03: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: d791190f8303c664cea8737046eb653c0514e939
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: 20fe05fe747821455c020521e5c2072b368713d8
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
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
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
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
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: 56b25a9fb3acc1a3befbf33c28a6d27df8aca8ef
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
Tak Hoffman
774b40467b
fix(zalouser): stop inheriting dm allowlist for groups (#46663) 2026-03-14 19:10:11 -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: e5432ec4e1685a78ca7251bc71f26c1f17355a15
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 bb06dc7cc9e71fbac29d7888d64323db2acec7ca.
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
ufhy
3928b4872a
fix: persist context-engine auto-compaction counts (#42629)
Merged via squash.

Prepared head SHA: df8f292039e27edec45b8ed2ad65ab0ac7f56194
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
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
George Zhang
b1d8737017
browser: drop chrome-relay auto-creation, simplify to user profile only (#46596)
Merged via squash.

Prepared head SHA: 74becc8f7dac245a345d2c7d549f604344df33fd
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: 9bffa3422c4dc13f5c72ab5d2813cc287499cc14 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
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
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
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
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
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
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
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