Skip to content

fix(gateway): tolerate transient pre-hello closes in CLI calls#54475

Closed
ruanrrn wants to merge 5 commits into
openclaw:mainfrom
ruanrrn:fix/cron-cli-prehello-close
Closed

fix(gateway): tolerate transient pre-hello closes in CLI calls#54475
ruanrrn wants to merge 5 commits into
openclaw:mainfrom
ruanrrn:fix/cron-cli-prehello-close

Conversation

@ruanrrn

@ruanrrn ruanrrn commented Mar 25, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Problem: One-shot gateway calls from the CLI (for example openclaw cron status / openclaw cron list --json) can fail with gateway closed (1000): when the first WebSocket connection closes with code 1000 and an empty reason before hello-ok, even though the client would immediately reconnect and complete the handshake successfully.
  • Why it matters: This surfaces as a flaky but user-visible failure path for CLI commands while the gateway itself is healthy, which breaks automation and undermines trust in the CLI.
  • What changed: executeGatewayRequestWithScopes(...) now tracks whether hello-ok has been seen and ignores only a pre-hello close with code 1000 and an empty reason; GatewayClient.connect treats that same transient connect error as non-fatal so the existing reconnect logic can complete; added focused tests covering both the one-shot call path and the client reconnect behavior.
  • What did NOT change (scope boundary): No changes to auth/secret handling, no changes to other close codes or non-empty close reasons, no changes to broader reconnect policy, and no config or CLI surface changes.

(AI-assisted: drafted and iterated with an OpenClaw workspace agent; changes and tests were reviewed and verified by a human.)

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • 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: N/A (fixing a locally diagnosed CLI gateway handshake failure that did not yet have a public issue)
  • Related: internal debugging of transient pre-hello 1000 closes on CLI gateway calls
  • This PR fixes a bug or regression

Root Cause / Regression History (if applicable)

  • Root cause: The one-shot gateway request wrapper (executeGatewayRequestWithScopes) treated any onClose event as terminal, even if it happened before hello-ok. In some environments, the underlying WebSocket stack can emit a transient 1000 close with an empty reason during the initial handshake, while GatewayClient reconnects and later completes hello successfully.
  • Missing detection / guardrail: There was no distinction between a transient pre-hello close that can be recovered by reconnect vs. a final close after a completed hello. The wrapper did not track whether hello-ok had been seen and did not special-case this transient 1000 path.
  • Prior context: This shows up as flaky failures on CLI commands like openclaw cron status/list with gateway closed (1000): even though the gateway is reachable and the Control UI can talk to it.
  • Why this regressed now: This is a behavior interaction between the CLI wrapper and gateway/WebSocket behavior that surfaced more often in certain deployments; it is not tied to a single recent refactor, but to the lack of pre-hello vs post-hello distinction in the close handling.
  • If unknown, what was ruled out: Verified that the gateway itself was healthy (Control UI worked, direct WebSocket loopback was fine) and that the failure was in the CLI handshake path, not gateway liveness.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file:
    • src/gateway/call.test.ts: new test ensuring callGateway({ method: "health" }) waits through a transient pre-hello 1000 close and resolves successfully once hello-ok arrives.
    • src/gateway/client.test.ts: new test ensuring GatewayClient suppresses the spurious gateway connect failed: ... (1000) log + onConnectError callback when a pre-hello 1000 close is followed by a successful reconnect and hello-ok.
  • Scenario the test should lock in:
    • A CLI one-shot gateway call that sees a transient pre-hello 1000 + empty-reason close should not fail early; it should wait for the reconnect and complete normally.
    • The same transient close should not be logged as a connect-failed error or reported to onConnectError when the reconnect ultimately succeeds.
  • Why this is the smallest reliable guardrail:
    • The bug is localized to the gateway call wrapper and GatewayClient connect path. Unit-level tests against these two entry points are sufficient to prevent future regressions in this exact transient-close path without requiring heavier end-to-end scenarios.
  • Existing test that already covers this (if any): None.
  • If no new test is added, why not: N/A (tests added).

User-visible / Behavior Changes

  • CLI calls that go through callGateway/executeGatewayRequestWithScopes are more robust against a specific transient handshake pattern: a pre-hello WebSocket close with code 1000 and an empty reason.
  • Commands like openclaw cron status and openclaw cron list --json should no longer fail sporadically with gateway closed (1000): on otherwise healthy gateways.
  • No change to error behavior for other close codes, non-empty close reasons, auth failures, or timeouts.

Security Impact (required)

  • New permissions/capabilities? (Yes/No) No
  • Secrets/tokens handling changed? (Yes/No) No
  • New/changed network calls? (Yes/No) No
  • Command/tool execution surface changed? (Yes/No) No
  • Data access scope changed? (Yes/No) No

If any Yes, explain risk + mitigation: N/A

Repro + Verification

Environment

  • OS: Linux (container/VM environment)
  • Runtime/container: Node 22, pnpm-managed workspace
  • Model/provider: N/A (gateway + CLI path only)
  • Integration/channel (if any): CLI (openclaw cron)
  • Relevant config (redacted): Gateway reachable on local loopback, CLI configured to talk to the local gateway.

Steps

  1. Start a local gateway and configure the CLI against it.
  2. On a build without this fix, run openclaw cron status or openclaw cron list --json repeatedly in an environment where the WebSocket stack occasionally emits a transient pre-hello 1000 + empty-reason close.
  3. Observe intermittent failures with gateway closed (1000): even though the Control UI and direct WebSocket loopback remain healthy.
  4. Apply this change and re-run the same CLI commands.

Expected

  • CLI commands should tolerate the transient pre-hello 1000 + empty-reason close, wait for the reconnect, and succeed normally when the gateway is healthy.

Actual

  • Before: CLI calls can fail immediately with gateway closed (1000): on the first handshake, despite the gateway being healthy and reconnects succeeding under the hood.
  • After: The same commands complete successfully; the transient close is no longer reported as a fatal error, and the new unit tests cover this behavior.

Evidence

  • Failing test/log before + passing after (simulated via new unit tests that reproduce the pre-hello 1000 close pattern and confirm the corrected behavior)
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

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

  • Verified scenarios:
    • corepack pnpm exec vitest run --config vitest.gateway.config.ts src/gateway/call.test.ts src/gateway/client.test.ts on the patched branch.
    • Manual verification on a local install that previously exhibited this bug: openclaw cron status and openclaw cron list --json no longer fail with gateway closed (1000): when the gateway is healthy.
  • Edge cases checked:
    • Only the specific pre-hello + code 1000 + empty reason path is suppressed; other close codes or non-empty reasons still fail the call as before.
    • Timeouts still behave as before; this change does not alter timeout behavior.
  • What you did not verify:
    • Full pnpm build && pnpm check && pnpm test for the entire monorepo; this PR focuses on gateway client + call behavior and is covered by targeted gateway tests.

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. (No prior bot conversations for this PR; marked proactively.)

Compatibility / Migration

  • Backward compatible? (Yes/No) Yes
  • Config/env changes? (Yes/No) No
  • Migration needed? (Yes/No) No

If yes, exact upgrade steps: N/A

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly:
    • Revert commit fbe47e1874 (or the PR merge commit) to restore the prior executeGatewayRequestWithScopes and GatewayClient.connect behavior.
  • Files/config to restore:
    • src/gateway/call.ts
    • src/gateway/client.ts
    • src/gateway/call.test.ts
    • src/gateway/client.test.ts
  • Known bad symptoms reviewers should watch for:
    • If a real, unrecoverable pre-hello 1000 close starts occurring in the wild, CLI callers might now see a timeout instead of an immediate gateway closed (1000): error for that specific pattern.

Risks and Mitigations

  • Risk:
    • Misclassifying a non-recoverable pre-hello 1000 + empty-reason close as transient, causing the CLI to wait for a reconnect that never meaningfully succeeds and eventually hit a timeout instead of failing immediately.
    • Mitigation: The suppression is narrowly scoped to pre-hello + code 1000 + empty reason. Any close with a reason, any non-1000 code, or any close after hello-ok still fails the call as before. Timeouts are unchanged, so a genuinely broken gateway still propagates as a failure rather than silently succeeding.
  • Risk:
    • Future changes to error message formatting could break the GatewayClient.connect string match for the transient gateway closed (1000): error.
    • Mitigation: The new unit tests in src/gateway/client.test.ts exercise this behavior explicitly; if the error message shape changes in the future, the tests should fail and force an update to the matching logic or a move to more structured error signaling.

@openclaw-barnacle openclaw-barnacle Bot added gateway Gateway runtime size: S labels Mar 25, 2026
@greptile-apps

greptile-apps Bot commented Mar 25, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a flaky CLI failure where one-shot gateway calls (callGateway) could immediately throw gateway closed (1000): even on a healthy gateway, because the first WebSocket connection occasionally emits a transient code-1000 close with an empty reason before the hello-ok handshake completes.

Changes:

  • call.tsexecuteGatewayRequestWithScopes now tracks a helloOkSeen flag; a pre-hello close with code 1000 and an empty reason is silently ignored so the existing reconnect logic can complete the handshake.
  • client.tsGatewayClient.sendConnect suppresses the onConnectError callback and the logError call for the same transient pre-hello close, preventing spurious "gateway connect failed" log lines.
  • Two focused unit tests cover both the one-shot wrapper path (call.test.ts) and the GatewayClient reconnect path (client.test.ts).

Notes:

  • The fix is correctly scoped: only pre-hello + code 1000 + empty reason is suppressed; all other close codes, non-empty reasons, and post-hello closes behave exactly as before.
  • The transient-close detection in client.ts relies on regex-matching err.message against the error template that produces it. This is functionally correct today but is a maintenance fragility: if the error message template on line 296 of client.ts is ever changed, the detection would silently stop working. A structured error type or tagged sentinel would be more robust long-term.

Confidence Score: 4/5

  • Safe to merge; the fix is well-scoped and well-tested with one minor maintainability concern in the detection approach.
  • Logic is correct: the helloOkSeen guard in call.ts and the isTransientPreHelloClose guard in client.ts are both correctly implemented and tested. The only non-blocking concern is that client.ts detects the transient close by regex-matching the human-readable error message string rather than using a structured sentinel, making it fragile to future message-copy changes. This does not affect correctness today and the existing tests will catch a regression if the message format changes. No security impact, no auth changes, no new network calls.
  • No files require special attention beyond the regex-matching fragility noted in src/gateway/client.ts lines 523–528.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/gateway/client.ts
Line: 523-528

Comment:
**String-based error detection is fragile**

The transient close detection relies on matching `err.message` against a hardcoded regex that must stay in sync with the error message template two hundred lines away:

```ts
// line 296 – error construction
this.flushPendingErrors(new Error(`gateway closed (${code}): ${reasonText}`));

// line 526 – detection regex
/^gateway closed \(1000\):\s*$/.test(err.message)
```

If the template on line 296 is ever changed (e.g. adding a suffix, changing the separator, or including `reasonText` differently for the empty-string case), the regex would silently stop matching and CLI callers would revert to the pre-fix behaviour — failing immediately on transient pre-hello closes — without any test failure in unrelated paths. The new tests in `client.test.ts` do guard this specific message, but only for the test scenario as written.

A more robust alternative would be to use a structured sentinel (e.g. a typed error subclass `GatewayPreHelloCloseError`, or a tagged `{ isPreHelloClose: true }` field) rather than pattern-matching on a human-readable message string. This would be immune to message-copy changes and would not require the regex to be kept in sync.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix(gateway): tolerate transient pre-hel..." | Re-trigger Greptile

Comment thread src/gateway/client.ts
@ruanrrn
ruanrrn force-pushed the fix/cron-cli-prehello-close branch from 012cb0d to af48d50 Compare March 25, 2026 16:21
@ruanrrn
ruanrrn force-pushed the fix/cron-cli-prehello-close branch from af48d50 to 29473d1 Compare April 27, 2026 13:43
@clawsweeper

clawsweeper Bot commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

Thanks for the context here. I swept through the related work, and this is now duplicate or superseded.

Keep this PR open: current main and the latest release still reject the narrow pre-hello clean-close path, and this branch remains the canonical implementation candidate, but it is not merge-ready because it conflicts with main and still lacks inspectable real behavior proof.

Canonical path: Close this PR as superseded by #85253.

So I’m closing this here and keeping the remaining discussion on #85253.

Review details

Best possible solution:

Close this PR as superseded by #85253.

Do we have a high-confidence way to reproduce the issue?

Yes for the narrow event sequence by source inspection: current main rejects an unsettled onClose before hello-ok, and the PR adds simulated close-then-hello tests. I did not establish a live environment that naturally emits the transient close.

Is this the best way to solve the issue?

Yes if refreshed: the PR keeps the fix in the gateway call/client layer, scopes suppression to pre-hello code 1000 with an empty reason, and preserves fatal behavior for other close cases. It still needs conflict resolution, changed-surface validation, and inspectable real CLI proof before merge.

Security review:

Security review cleared: The diff is limited to gateway close/error handling, tests, and changelog text, with no dependency, workflow, permission, package, install, or secret-handling changes found.

What I checked:

  • linked superseding PR: [Fix] Surface gateway connect assembly failures #85253 ([Fix] Surface gateway connect assembly failures) is merged at 2026-05-22T07:40:07Z.
  • cluster evidence: the durable review links that PR in the work cluster or recommended risk path.
  • no human follow-up: live comments and timeline hydrated by apply contain no non-automation activity after the ClawSweeper review.

Likely related people:

  • steipete: Recent history shows gateway client/call handshake and reconnect work in the affected files, including early connect challenge and websocket auth logging changes. (role: recent gateway handshake contributor; confidence: high; commits: 3243c9b5b064, bf40baaa4dfa, 56b071400418; files: src/gateway/client.ts, src/gateway/client.test.ts, src/gateway/call.ts)
  • samzong: Merged PR [Fix] Surface gateway connect assembly failures #85253 changed the same call/client handshake path for connect assembly failures and now conflicts with this branch's surface. (role: recent adjacent gateway connect-failure contributor; confidence: high; commits: 0e47815e6ec9, 318a3019a7e2, f817d59fb2e5; files: src/gateway/call.ts, src/gateway/client.ts, src/gateway/call.test.ts)
  • vincentkoc: The PR timeline records a narrow repair pushed to this canonical branch, and local history shows recent gateway-adjacent source work in the same files. (role: branch repair author and recent area contributor; confidence: medium; commits: 2a2eb2759ade, e089d02714c2, 935bd6de7fcb; files: src/gateway/call.ts, src/gateway/client.ts, src/gateway/call.test.ts)
  • Takhoffman: History shows bounded unanswered gateway client request work touching the same one-shot call/client request-settlement surface. (role: adjacent gateway call wrapper contributor; confidence: medium; commits: 5fc43ff0ecd8; files: src/gateway/call.ts, src/gateway/call.test.ts, src/gateway/client.ts)

Codex review notes: model gpt-5.5, reasoning high; reviewed against 6d9b3887ea26.

@vincentkoc

Copy link
Copy Markdown
Member

ProjectClownfish pushed a narrow repair to this branch so the original contributor path can stay canonical.

Source PR: #54475
Validation: pnpm check:changed
Contributor credit is preserved in the branch history and PR context.

@ruanrrn
ruanrrn force-pushed the fix/cron-cli-prehello-close branch from 6f5aea4 to e089d02 Compare April 30, 2026 01:42
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels May 19, 2026
@openclaw-barnacle openclaw-barnacle Bot added the triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. label May 19, 2026
@clawsweeper clawsweeper Bot added P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. labels May 19, 2026
@clawsweeper

clawsweeper Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper PR egg

🎁 Pass real behavior proof to wake the egg and unlock a hatchable treat.

Where did the egg go?
  • The egg game starts only after the PR passes the real-behavior proof check.
  • Before that, no creature or rarity is rolled. The treat waits for real proof.
  • This is still just collectible flavor: proof affects review readiness, not creature quality.

@clawsweeper

clawsweeper Bot commented May 24, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper applied the proposed close for this PR.

@clawsweeper clawsweeper Bot closed this May 24, 2026
eleboucher pushed a commit to eleboucher/homelab that referenced this pull request Jun 16, 2026
…26.6.8) (#1144)

This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [ghcr.io/openclaw/openclaw](https://openclaw.ai) ([source](https://github.com/openclaw/openclaw)) | patch | `2026.6.6` → `2026.6.8` |

---

### Release Notes

<details>
<summary>openclaw/openclaw (ghcr.io/openclaw/openclaw)</summary>

### [`v2026.6.8`](https://github.com/openclaw/openclaw/blob/HEAD/CHANGELOG.md#202668)

[Compare Source](openclaw/openclaw@v2026.6.6...v2026.6.8)

##### Highlights

- Telegram and WhatsApp channel delivery are richer and less brittle: Telegram can send structured rich text with tables, lists, expandable blockquotes, prompt-preserving CLI backend delivery, retired native draft migration, and safer rich-media boundaries, while WhatsApp now honors configured ACP bindings. ([#&#8203;92679](openclaw/openclaw#92679), [#&#8203;84082](openclaw/openclaw#84082), [#&#8203;89421](openclaw/openclaw#89421), [#&#8203;92513](openclaw/openclaw#92513)) Thanks [@&#8203;obviyus](https://github.com/obviyus), [@&#8203;jzakirov](https://github.com/jzakirov), [@&#8203;spacegeologist](https://github.com/spacegeologist), and [@&#8203;TurboTheTurtle](https://github.com/TurboTheTurtle).
- Agent and Gateway recovery is sharper across account-scoped DM sends, generated media completions, restart shutdown aborts, yielded subagent pauses, yielded cron media, heartbeat dedupe, session identity prompts, and unknown OpenAI agent selector rejection. ([#&#8203;92788](openclaw/openclaw#92788), [#&#8203;91246](openclaw/openclaw#91246), [#&#8203;91357](openclaw/openclaw#91357), [#&#8203;92631](openclaw/openclaw#92631), [#&#8203;92146](openclaw/openclaw#92146), [#&#8203;91287](openclaw/openclaw#91287), [#&#8203;92468](openclaw/openclaw#92468), [#&#8203;92510](openclaw/openclaw#92510)) Thanks [@&#8203;yetval](https://github.com/yetval), [@&#8203;TurboTheTurtle](https://github.com/TurboTheTurtle), [@&#8203;ooiuuii](https://github.com/ooiuuii), [@&#8203;openperf](https://github.com/openperf), [@&#8203;IWhatsskill](https://github.com/IWhatsskill), [@&#8203;ZengWen-DT](https://github.com/ZengWen-DT), and [@&#8203;zhangguiping-xydt](https://github.com/zhangguiping-xydt).
- Provider/model handling expands and tightens with GLM-5.2, Claude Haiku 4.5 catalog rows, OpenRouter and Google Vertex provider-prefix normalization, managed SecretRef auth, bounded model browse discovery, storeless OpenAI Responses replay gating, and Claude 4.5 Copilot tool-streaming safety. ([#&#8203;92796](openclaw/openclaw#92796), [#&#8203;90116](openclaw/openclaw#90116), [#&#8203;92627](openclaw/openclaw#92627), [#&#8203;91218](openclaw/openclaw#91218), [#&#8203;90686](openclaw/openclaw#90686), [#&#8203;92247](openclaw/openclaw#92247), [#&#8203;90706](openclaw/openclaw#90706), [#&#8203;75393](openclaw/openclaw#75393)) Thanks [@&#8203;arkyu2077](https://github.com/arkyu2077), [@&#8203;liuhao1024](https://github.com/liuhao1024), [@&#8203;bymle](https://github.com/bymle), [@&#8203;rohitjavvadi](https://github.com/rohitjavvadi), [@&#8203;samson910022](https://github.com/samson910022), [@&#8203;snowzlm](https://github.com/snowzlm), and [@&#8203;Kailigithub](https://github.com/Kailigithub).
- `/usage` and reply payload hooks now have a native full footer renderer, default template, fixed-decimal formatting, credential-aware limits, better partial-count handling, and warnings for broken templates instead of silent bad output. ([#&#8203;92657](openclaw/openclaw#92657), [#&#8203;89835](openclaw/openclaw#89835), [#&#8203;89629](openclaw/openclaw#89629)) Thanks [@&#8203;Marvinthebored](https://github.com/Marvinthebored).
- UI and mobile flows are steadier: workspace files can collapse and start collapsed, WebChat backscroll survives streaming, the sidebar session picker remains interactive above the desktop workbench, reset soft args survive UI dispatch, stale dashboard session parent lineage is preserved, and iOS reconnects stale foreground gateways. ([#&#8203;92779](openclaw/openclaw#92779), [#&#8203;92622](openclaw/openclaw#92622), [#&#8203;92705](openclaw/openclaw#92705), [#&#8203;91353](openclaw/openclaw#91353), [#&#8203;90658](openclaw/openclaw#90658), [#&#8203;92552](openclaw/openclaw#92552)) Thanks [@&#8203;shakkernerd](https://github.com/shakkernerd), [@&#8203;TurboTheTurtle](https://github.com/TurboTheTurtle), [@&#8203;NianJiuZst](https://github.com/NianJiuZst), [@&#8203;zhouhe-xydt](https://github.com/zhouhe-xydt), [@&#8203;luoyanglang](https://github.com/luoyanglang), and [@&#8203;Solvely-Colin](https://github.com/Solvely-Colin).
- Memory, state, and diagnostics recover cleaner: oversized OpenAI embedding batches split before 431s, QMD memory search stays available in transient mode, SQLite avoids WAL on NFS state volumes, stuck-session recovery scheduling no longer resets warning backoff, and Infinity chunk limits stay genuinely unbounded. ([#&#8203;92650](openclaw/openclaw#92650), [#&#8203;92618](openclaw/openclaw#92618), [#&#8203;92639](openclaw/openclaw#92639), [#&#8203;91247](openclaw/openclaw#91247), [#&#8203;92752](openclaw/openclaw#92752), [#&#8203;92735](openclaw/openclaw#92735)) Thanks [@&#8203;mushuiyu886](https://github.com/mushuiyu886), [@&#8203;TurboTheTurtle](https://github.com/TurboTheTurtle), [@&#8203;849261680](https://github.com/849261680), [@&#8203;gnanam1990](https://github.com/gnanam1990), and [@&#8203;yhterrance](https://github.com/yhterrance).

##### Changes

- Providers/models: add GLM-5.2 support and Claude Haiku 4.5 catalog entries while keeping provider-qualified model IDs normalized across OpenRouter and Google Vertex paths. ([#&#8203;92796](openclaw/openclaw#92796), [#&#8203;90116](openclaw/openclaw#90116), [#&#8203;92627](openclaw/openclaw#92627), [#&#8203;91218](openclaw/openclaw#91218)) Thanks [@&#8203;arkyu2077](https://github.com/arkyu2077), [@&#8203;liuhao1024](https://github.com/liuhao1024), and [@&#8203;bymle](https://github.com/bymle).
- Channel plugins: ship Telegram rich-message delivery and WhatsApp ACP binding support, including rich prompt handoff to CLI backends and transport fixtures for richer drafts. ([#&#8203;92679](openclaw/openclaw#92679), [#&#8203;92513](openclaw/openclaw#92513)) Thanks [@&#8203;obviyus](https://github.com/obviyus) and [@&#8203;TurboTheTurtle](https://github.com/TurboTheTurtle).
- Agent commands: support `/btw` in CLI-backed sessions and keep CLI usage-error exits classified as usage failures instead of successful runs. ([#&#8203;92669](openclaw/openclaw#92669), [#&#8203;92162](openclaw/openclaw#92162)) Thanks [@&#8203;joshavant](https://github.com/joshavant) and [@&#8203;Pandah97](https://github.com/Pandah97).
- Usage hooks: add built-in full footer rendering, default footer templates, per-turn usage state, credential-aware limits, and fixed-decimal formatting for usage-bar templates. ([#&#8203;92657](openclaw/openclaw#92657), [#&#8203;89835](openclaw/openclaw#89835), [#&#8203;89629](openclaw/openclaw#89629)) Thanks [@&#8203;Marvinthebored](https://github.com/Marvinthebored).
- Docs and operator guidance: document node config examples, clarify before-install hook scope, correct agent default concurrency comments, refresh ZAI provider docs, and update channel/group docs for current Telegram and WhatsApp behavior. ([#&#8203;92677](openclaw/openclaw#92677), [#&#8203;92766](openclaw/openclaw#92766), [#&#8203;92695](openclaw/openclaw#92695)) Thanks [@&#8203;liuhao1024](https://github.com/liuhao1024), [@&#8203;sallyom](https://github.com/sallyom), and [@&#8203;ArielSmoliar](https://github.com/ArielSmoliar).

##### Fixes

- Onboarding/skills: show the Homebrew install recommendation only on macOS and Linux, so FreeBSD and other unsupported platforms no longer get a misleading brew prompt. Fixes [#&#8203;68893](openclaw/openclaw#68893); carries forward [#&#8203;68894](openclaw/openclaw#68894), [#&#8203;68910](openclaw/openclaw#68910), [#&#8203;68941](openclaw/openclaw#68941), [#&#8203;68943](openclaw/openclaw#68943), [#&#8203;69002](openclaw/openclaw#69002), and [#&#8203;69545](openclaw/openclaw#69545). Thanks [@&#8203;yurivict](https://github.com/yurivict), [@&#8203;Sanjays2402](https://github.com/Sanjays2402), [@&#8203;Eruditi](https://github.com/Eruditi), [@&#8203;JustInCache](https://github.com/JustInCache), [@&#8203;nnish16](https://github.com/nnish16), and [@&#8203;Mlightsnow](https://github.com/Mlightsnow).
- Channels and delivery: preserve account-scoped DM channel send policy, rich Telegram final replies, rich Telegram tables and lists, Telegram thread-create CLI remapping, Slack outbound `message_sent` hooks, contributed message-tool schema optionality, same-channel generated media completions, and channel chunking around surrogate pairs and Infinity limits. ([#&#8203;92788](openclaw/openclaw#92788), [#&#8203;92679](openclaw/openclaw#92679), [#&#8203;89421](openclaw/openclaw#89421), [#&#8203;89943](openclaw/openclaw#89943), [#&#8203;91137](openclaw/openclaw#91137), [#&#8203;91246](openclaw/openclaw#91246), [#&#8203;92735](openclaw/openclaw#92735)) Thanks [@&#8203;yetval](https://github.com/yetval), [@&#8203;obviyus](https://github.com/obviyus), [@&#8203;spacegeologist](https://github.com/spacegeologist), [@&#8203;rishitamrakar](https://github.com/rishitamrakar), [@&#8203;lundog](https://github.com/lundog), [@&#8203;TurboTheTurtle](https://github.com/TurboTheTurtle), and [@&#8203;yhterrance](https://github.com/yhterrance).
- Auto-reply/groups: keep ordinary group text replies on automatic final-reply delivery while allowing `message(action=send)` for files, images, and other attachments to the same group or topic. Carries forward [#&#8203;43276](openclaw/openclaw#43276); refs [#&#8203;48004](openclaw/openclaw#48004). Thanks [@&#8203;NayukiChiba](https://github.com/NayukiChiba) and [@&#8203;ShakaRover](https://github.com/ShakaRover).
- Auto-reply/skills: preserve multiline payloads for `/skill` and direct skill slash commands while keeping command-head normalization for aliases, colon syntax, and bot mentions. Fixes [#&#8203;79155](openclaw/openclaw#79155); carries forward [#&#8203;81305](openclaw/openclaw#81305). Thanks [@&#8203;web3blind](https://github.com/web3blind).
- iMessage: normalize leading NUL sent-message echo prefixes while preserving interior NUL bytes and the leading attributedBody marker handling from [#&#8203;73942](openclaw/openclaw#73942). Carries forward [#&#8203;63581](openclaw/openclaw#63581). Thanks [@&#8203;drvoss](https://github.com/drvoss).
- Discord: give generated auto-thread titles a 60-second timeout and 4,096-token reasoning-model output budget, clamped to the selected model output cap. ([#&#8203;64734](openclaw/openclaw#64734)) Thanks [@&#8203;hanamizuki](https://github.com/hanamizuki).
- Agent, cron, and Gateway runtime: mark active main sessions before restart shutdown aborts, pause yielded subagent runs whose terminal also signals abort, preserve yielded media completions, de-duplicate main-session heartbeat events, expose session identity in runtime prompts, reject unknown OpenAI agent selectors, keep generated media completions and slash-command block replies in WebChat, preserve fresh post-compaction usage while clearing stale usage snapshots, and require admin privileges for HTTP session/model override surfaces. ([#&#8203;91357](openclaw/openclaw#91357), [#&#8203;92631](openclaw/openclaw#92631), [#&#8203;92146](openclaw/openclaw#92146), [#&#8203;91287](openclaw/openclaw#91287), [#&#8203;92468](openclaw/openclaw#92468), [#&#8203;92510](openclaw/openclaw#92510), [#&#8203;91246](openclaw/openclaw#91246), [#&#8203;50795](openclaw/openclaw#50795), [#&#8203;50845](openclaw/openclaw#50845), [#&#8203;82874](openclaw/openclaw#82874), [#&#8203;92651](openclaw/openclaw#92651), [#&#8203;92646](openclaw/openclaw#92646)) Thanks [@&#8203;ooiuuii](https://github.com/ooiuuii), [@&#8203;openperf](https://github.com/openperf), [@&#8203;IWhatsskill](https://github.com/IWhatsskill), [@&#8203;ZengWen-DT](https://github.com/ZengWen-DT), [@&#8203;zhangguiping-xydt](https://github.com/zhangguiping-xydt), [@&#8203;Hollychou924](https://github.com/Hollychou924), [@&#8203;leno23](https://github.com/leno23), and [@&#8203;TurboTheTurtle](https://github.com/TurboTheTurtle).
- Agents/exec: default empty-success background completion notices on only for real chat channels, preserving explicit opt-outs and keeping generic providers silent while carrying forward the narrow UX intent from [#&#8203;39726](openclaw/openclaw#39726) and [#&#8203;46926](openclaw/openclaw#46926). Thanks [@&#8203;Sapientropic](https://github.com/Sapientropic) and [@&#8203;wenkang-xie](https://github.com/wenkang-xie).
- Providers and model replay: preserve storeless OpenAI Responses replay compatibility, avoid eager tool streaming for Claude 4.5 in Copilot, honor profile auth for SecretRef model entries, bound model browsing, strip provider prefixes where runtimes need bare IDs, and surface nested embedding fetch failures. ([#&#8203;90706](openclaw/openclaw#90706), [#&#8203;75393](openclaw/openclaw#75393), [#&#8203;90686](openclaw/openclaw#90686), [#&#8203;92247](openclaw/openclaw#92247), [#&#8203;92627](openclaw/openclaw#92627), [#&#8203;91218](openclaw/openclaw#91218), [#&#8203;92628](openclaw/openclaw#92628)) Thanks [@&#8203;snowzlm](https://github.com/snowzlm), [@&#8203;Kailigithub](https://github.com/Kailigithub), [@&#8203;rohitjavvadi](https://github.com/rohitjavvadi), [@&#8203;samson910022](https://github.com/samson910022), [@&#8203;liuhao1024](https://github.com/liuhao1024), [@&#8203;bymle](https://github.com/bymle), and [@&#8203;mushuiyu886](https://github.com/mushuiyu886).
- Memory, state, diagnostics, and config: split header-too-large embedding batches, keep QMD memory search enabled in transient mode, avoid SQLite WAL on NFS volumes, preserve recovery scheduling outside stuck-session warning backoff, and keep shell environment fallbacks contained in config write tests. ([#&#8203;92650](openclaw/openclaw#92650), [#&#8203;92618](openclaw/openclaw#92618), [#&#8203;92639](openclaw/openclaw#92639), [#&#8203;91247](openclaw/openclaw#91247), [#&#8203;92752](openclaw/openclaw#92752)) Thanks [@&#8203;mushuiyu886](https://github.com/mushuiyu886), [@&#8203;TurboTheTurtle](https://github.com/TurboTheTurtle), [@&#8203;849261680](https://github.com/849261680), and [@&#8203;gnanam1990](https://github.com/gnanam1990).
- Workspace setup state: store setup completion outside the workspace dot directory using an OpenClaw-named root file, migrate valid legacy state forward, and avoid clobbering generic root `workspace-state.json` files for TigerFS-style dot-path compatibility. This Clownfish replacement carries forward the focused [#&#8203;53326](openclaw/openclaw#53326) fix idea because the original branch was closed and uneditable. ([#&#8203;53326](openclaw/openclaw#53326), [#&#8203;44783](openclaw/openclaw#44783), [#&#8203;39446](openclaw/openclaw#39446)) Thanks [@&#8203;1qh](https://github.com/1qh).
- UI/mobile/TUI: preserve dashboard session parent lineage, WebChat backscroll, reset soft command args, sidebar session picker interactivity, collapsed workspace files, resolved `/model` confirmation refs, and stale foreground iOS Gateway reconnects. ([#&#8203;90658](openclaw/openclaw#90658), [#&#8203;92622](openclaw/openclaw#92622), [#&#8203;91353](openclaw/openclaw#91353), [#&#8203;92705](openclaw/openclaw#92705), [#&#8203;92779](openclaw/openclaw#92779), [#&#8203;92773](openclaw/openclaw#92773), [#&#8203;92552](openclaw/openclaw#92552)) Thanks [@&#8203;luoyanglang](https://github.com/luoyanglang), [@&#8203;TurboTheTurtle](https://github.com/TurboTheTurtle), [@&#8203;zhouhe-xydt](https://github.com/zhouhe-xydt), [@&#8203;NianJiuZst](https://github.com/NianJiuZst), [@&#8203;shakkernerd](https://github.com/shakkernerd), [@&#8203;NarahariRaghava](https://github.com/NarahariRaghava), and [@&#8203;Solvely-Colin](https://github.com/Solvely-Colin).
- TUI: reload the active session after external `/new` or `/reset` session-change events so stale transcript and stream state clear promptly. Fixes [#&#8203;38966](openclaw/openclaw#38966); carries forward [#&#8203;40472](openclaw/openclaw#40472). Thanks [@&#8203;yizhanzjz](https://github.com/yizhanzjz) and [@&#8203;wsyjh8](https://github.com/wsyjh8).
- Control UI: preserve Gateway Access tokens during same-normalized WebSocket URL edits and reload gateway-scoped tokens when switching endpoints. Fixes [#&#8203;41545](openclaw/openclaw#41545); repairs [#&#8203;42001](openclaw/openclaw#42001) with additional source PRs [#&#8203;41546](openclaw/openclaw#41546), [#&#8203;41552](openclaw/openclaw#41552), and [#&#8203;41718](openclaw/openclaw#41718). Thanks [@&#8203;wsyjh8](https://github.com/wsyjh8), [@&#8203;llagy0020](https://github.com/llagy0020), [@&#8203;llagy007](https://github.com/llagy007), [@&#8203;pingfanfan](https://github.com/pingfanfan), and [@&#8203;zheliu2](https://github.com/zheliu2).
- Gateway CLI: tolerate a single transient clean WebSocket close before `hello-ok` so one-shot RPC calls reconnect instead of failing noisily, while repeated clean pre-hello closes still surface. Carries forward source PRs [#&#8203;54475](openclaw/openclaw#54475) and [#&#8203;54774](openclaw/openclaw#54774); [#&#8203;85253](openclaw/openclaw#85253) covered adjacent connect assembly diagnostics. Thanks [@&#8203;ruanrrn](https://github.com/ruanrrn).
- Gateway/Linux: keep root-owned systemd user service lifecycle commands on root's user manager when a stale `SUDO_USER` remains in a root shell with root's user bus environment. Fixes [#&#8203;81410](openclaw/openclaw#81410). Thanks [@&#8203;Ericksza](https://github.com/Ericksza) and [@&#8203;ChuckClose-tech](https://github.com/ChuckClose-tech).
- Release and test reliability: extend slow Gateway/full-suite watchdogs, split local full-suite shards when throttled, stabilize plugin auth marker fixtures, avoid brittle provider-ref error text, and keep QA Lab bootstrap selection assertions aligned with flow-only scenarios. ([#&#8203;92652](openclaw/openclaw#92652))
- macOS Peekaboo bridge: update the embedded Peekaboo package to 3.5.2 and route bundled-skill CLI commands through the OpenClaw app bridge so they inherit its Screen Recording and Accessibility grants.
- Agent routing: route subagent RPC callbacks addressed to an agent-shaped `--to` target to the correct session key instead of falling back to the main session, so WeChat (and other channel) session-key callbacks reach the intended subagent session. ([#&#8203;90231](openclaw/openclaw#90231)) Thanks [@&#8203;zhangguiping-xydt](https://github.com/zhangguiping-xydt).
- Cron: preserve model, fallback, thinking, timeout, light-context, unsafe-content, and tool allow-list overrides on implicit text payloads by promoting them to agent turns, while explicit system events still prune those fields. Fixes [#&#8203;28905](openclaw/openclaw#28905); carries forward [#&#8203;64060](openclaw/openclaw#64060) and [#&#8203;73946](openclaw/openclaw#73946). Thanks [@&#8203;liaoandi](https://github.com/liaoandi).
- QQBot delivery: keep markdown table chunks self-contained across message boundaries by preserving table state across block deliveries, flushing unfinished table-row fragments as plain text, and detecting short pipe-terminated rows by column count so split rows are not sent as malformed markdown. ([#&#8203;92428](openclaw/openclaw#92428)) Thanks [@&#8203;sliverp](https://github.com/sliverp).

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDEuMSIsInVwZGF0ZWRJblZlciI6IjQzLjEwMS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL3BhdGNoIl19-->

Reviewed-on: https://git.erwanleboucher.dev/eleboucher/homelab/pulls/1144
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clawsweeper Tracked by ClawSweeper automation gateway Gateway runtime merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. P2 Normal backlog priority with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: M status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants