Skip to content

fix(session): preserve lastAccountId and lastThreadId on session reset#44773

Merged
obviyus merged 2 commits intoopenclaw:mainfrom
Lanfei:fix/session-reset-account-id
Mar 13, 2026
Merged

fix(session): preserve lastAccountId and lastThreadId on session reset#44773
obviyus merged 2 commits intoopenclaw:mainfrom
Lanfei:fix/session-reset-account-id

Conversation

@Lanfei
Copy link
Copy Markdown
Contributor

@Lanfei Lanfei commented Mar 13, 2026

Summary

  • Problem: performGatewaySessionReset omitted lastAccountId and lastThreadId when constructing nextEntry, causing both fields to be lost after a session reset.
  • Why it matters: These fields identify the source account and thread for message routing; losing them after reset can cause replies to fail to route back to the original conversation.
  • What changed: Added lastAccountId and lastThreadId to the nextEntry construction in session-reset-service.ts, consistent with how lastChannel and lastTo are already handled.
  • What did NOT change: No other fields, reset flow steps, or ACP cleanup behavior are affected.

Change Type

  • Bug fix

Scope

  • Gateway / orchestration

Linked Issue/PR

  • Closes #

User-visible / Behavior Changes

After a session reset, lastAccountId and lastThreadId are now correctly preserved, restoring proper message routing behavior.

Security Impact

  • 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

Repro + Verification

Environment

  • OS:
  • Runtime/container:
  • Model/provider:
  • Integration/channel (if any):
  • Relevant config (redacted):

Steps

  1. Establish an active session with lastAccountId / lastThreadId set (e.g. via a Discord thread message)
  2. Trigger a session reset (/reset or equivalent)
  3. Send a new message

Expected

  • Reply is routed back to the original account/thread

Actual (before fix)

  • lastAccountId / lastThreadId were cleared on reset, causing routing failure or lost replies

Evidence

  • Code diff directly shows the omitted fields

Human Verification

  • Verified scenarios: code review confirmed fields were missing from nextEntry
  • Edge cases checked: currentEntry being undefined is handled safely via optional chaining
  • What you did not verify: end-to-end Discord/Telegram thread reset flow

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.

Compatibility / Migration

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

Failure Recovery

  • How to disable/revert this change quickly: git revert this commit
  • Files/config to restore: src/gateway/session-reset-service.ts
  • Known bad symptoms reviewers should watch for: None

Risks and Mitigations

None

@openclaw-barnacle openclaw-barnacle bot added gateway Gateway runtime size: XS labels Mar 13, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 13, 2026

Greptile Summary

This PR fixes a bug in performGatewaySessionReset where lastAccountId and lastThreadId were omitted from the nextEntry object, causing those fields to be cleared on every session reset and breaking reply-routing back to the originating account/thread.

  • The two-line fix in session-reset-service.ts is correct, minimal, and symmetric with how lastChannel and lastTo are already preserved.
  • Both fields are properly declared as optional properties in SessionEntry (src/config/sessions/types.ts), so no type changes are needed.
  • No existing test exercises performGatewaySessionReset with these fields set; the only test file that references the function mocks it out entirely. A regression test for this specific preservation behaviour would strengthen confidence.

Confidence Score: 4/5

  • Safe to merge — the fix is minimal, correct, and consistent with existing field-preservation patterns.
  • The change is a two-line addition that mirrors how lastChannel/lastTo are already handled; the fields are properly typed; and no unrelated logic is touched. The small score deduction reflects the absence of a dedicated unit or integration test verifying the preserved behaviour post-reset.
  • No files require special attention beyond the missing test coverage noted in src/gateway/session-reset-service.ts.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/gateway/session-reset-service.ts
Line: 341-342

Comment:
**No unit test covers the preserved fields after reset**

The fix is correct and symmetric with `lastChannel`/`lastTo`, but no test was added to verify that `lastAccountId` and `lastThreadId` survive a `performGatewaySessionReset` call. The existing test suite mocks out `performGatewaySessionReset` entirely (`agent.test.ts`) and the sessions integration test (`server.sessions.gateway-server-sessions-a.test.ts`) doesn't exercise the reset path with these fields set.

Consider adding a test that:
1. Seeds a session store entry with `lastAccountId` and `lastThreadId` populated.
2. Calls `performGatewaySessionReset`.
3. Asserts both fields are present and equal on the returned `entry`.

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

Last reviewed commit: 4166db7

Comment on lines +341 to +342
lastAccountId: currentEntry?.lastAccountId,
lastThreadId: currentEntry?.lastThreadId,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No unit test covers the preserved fields after reset

The fix is correct and symmetric with lastChannel/lastTo, but no test was added to verify that lastAccountId and lastThreadId survive a performGatewaySessionReset call. The existing test suite mocks out performGatewaySessionReset entirely (agent.test.ts) and the sessions integration test (server.sessions.gateway-server-sessions-a.test.ts) doesn't exercise the reset path with these fields set.

Consider adding a test that:

  1. Seeds a session store entry with lastAccountId and lastThreadId populated.
  2. Calls performGatewaySessionReset.
  3. Asserts both fields are present and equal on the returned entry.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/gateway/session-reset-service.ts
Line: 341-342

Comment:
**No unit test covers the preserved fields after reset**

The fix is correct and symmetric with `lastChannel`/`lastTo`, but no test was added to verify that `lastAccountId` and `lastThreadId` survive a `performGatewaySessionReset` call. The existing test suite mocks out `performGatewaySessionReset` entirely (`agent.test.ts`) and the sessions integration test (`server.sessions.gateway-server-sessions-a.test.ts`) doesn't exercise the reset path with these fields set.

Consider adding a test that:
1. Seeds a session store entry with `lastAccountId` and `lastThreadId` populated.
2. Calls `performGatewaySessionReset`.
3. Asserts both fields are present and equal on the returned `entry`.

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

@Lanfei
Copy link
Copy Markdown
Contributor Author

Lanfei commented Mar 13, 2026

Hey @jalehman @obviyus — could you take a look when you have a moment? CI is green and the change is small. I currently have several open PRs waiting for review, which is making it hard for me to continue contributing. Any feedback or a quick merge would be much appreciated. Thanks!

@obviyus obviyus self-assigned this Mar 13, 2026
@obviyus obviyus force-pushed the fix/session-reset-account-id branch from 4166db7 to 22947a4 Compare March 13, 2026 07:09
@obviyus obviyus merged commit d40a4e3 into openclaw:main Mar 13, 2026
28 checks passed
@obviyus
Copy link
Copy Markdown
Contributor

obviyus commented Mar 13, 2026

Landed on main.

Thanks @Lanfei.

@Lanfei Lanfei deleted the fix/session-reset-account-id branch March 13, 2026 07:11
@Lanfei
Copy link
Copy Markdown
Contributor Author

Lanfei commented Mar 13, 2026

Landed on main.

Thanks @Lanfei.

Thanks @obviyus

frankekn pushed a commit to jmcte/openclaw that referenced this pull request Mar 13, 2026
Jerry-Xin pushed a commit to Jerry-Xin/openclaw that referenced this pull request Mar 13, 2026
ecochran76 pushed a commit to ecochran76/openclaw that referenced this pull request Mar 14, 2026
Interstellar-code pushed a commit to Interstellar-code/operator1 that referenced this pull request Mar 16, 2026
alexey-pelykh pushed a commit to remoteclaw/remoteclaw that referenced this pull request Mar 24, 2026
alexey-pelykh added a commit to remoteclaw/remoteclaw that referenced this pull request Mar 24, 2026
…1959)

* refactor: share gateway client auth retry helpers

(cherry picked from commit 5f34391)

* Gateway: preserve discovered session store paths

(cherry picked from commit 60c1577)

* refactor: share node pending test client

(cherry picked from commit 644fb76)

* fix: add null guards to usage sort comparators

Prevents crash when totals is undefined in byModel/byProvider/byAgent
sort comparators. Fixes 'Cannot read properties of undefined (reading
totalTokens)' crash that causes context overflow in active sessions.

(cherry picked from commit 6921716)

* refactor: share gateway credential secretref assertions

(cherry picked from commit 6cc86ad)

* fix: force-stop lingering gateway client sockets

(cherry picked from commit 727fc79)

* Gateway: lazily resolve channel runtime

(cherry picked from commit 776e5d8)

* test: stabilize gateway alias coverage

(cherry picked from commit 7b00a06)

* Gateway: preserve trusted-proxy browser scopes

(cherry picked from commit 8661c27)

* test: simplify control ui http coverage

(cherry picked from commit 91d4f5c)

* test: tighten server method helper coverage

(cherry picked from commit 91f1894)

* fix(gateway): remove re-introduced auth.mode=none pairing bypass

The revert of openclaw#43478 (commit 39b4185) was silently undone by
3704293 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.

(cherry picked from commit 92fc806)

* fix(gateway): avoid probe false negatives after connect

(cherry picked from commit 93df5f6)

* fix(gateway): skip device pairing when auth.mode=none

Fixes openclaw#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 openclaw#42931

(cherry picked from commit 9bffa34)

* Gateway: cover lazy channel runtime resolution

(cherry picked from commit 9ee0fb5)

* 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

(cherry picked from commit a1520d7)

* refactor: share control ui hardlink asset setup

(cherry picked from commit a3ece09)

* test(gateway): avoid hoisted reply mock tdz

(cherry picked from commit a60a4b4)

* fix(gateway): pin plugin webhook route registry (openclaw#47902)

(cherry picked from commit a69f619)

* test(gateway): stabilize suite session-store config (openclaw#52193)

* test(gateway): stabilize suite session-store config

* test(gateway): preserve seeded config semantics

* test(gateway): update seeded session store overrides

(cherry picked from commit ad24fcc)

* test: share plugin http auth helpers

(cherry picked from commit b644669)

* refactor: deduplicate push test fixtures

(cherry picked from commit b6b5e5c)

* test: share gateway reload helpers

(cherry picked from commit b72ac79)

* test: dedupe cron config setup

(cherry picked from commit ba34266)

* test: simplify talk config and path env coverage

(cherry picked from commit bec76be)

* refactor: share agent wait dedupe cleanup

(cherry picked from commit c889803)

* test(gateway): restore agent request route mock

(cherry picked from commit ccba943)

* fix: add gateway session reset routing coverage (openclaw#44773) (thanks @Lanfei)

(cherry picked from commit d40a4e3)

* 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

(cherry picked from commit dafd61b)

* refactor: share readiness test harness

(cherry picked from commit db9c755)

* test: simplify method scope coverage

(cherry picked from commit e1b9250)

* refactor: share node wake test apns fixtures

(cherry picked from commit e351a86)

* refactor: reuse gateway talk provider schema fields

(cherry picked from commit e94ac57)

* 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

(cherry picked from commit ebed3bb)

* refactor(security): reuse hook agent routing normalization

(cherry picked from commit eece586)

* Hardening: tighten preauth WebSocket handshake limits (openclaw#44089)

* Gateway: tighten preauth handshake limits

* Changelog: note WebSocket preauth hardening

* Gateway: count preauth frame bytes accurately

* Gateway: cap WebSocket payloads before auth

(cherry picked from commit eff0d5a)

* test: share gateway chat run helpers

(cherry picked from commit f8efa30)

* refactor: share shared auth scope assertion

(cherry picked from commit feba7ea)

* fix: adapt cherry-picks for fork TS strictness and naming

* fix: resolve remaining TS errors from cherry-picks

* fix: revert push test to fork version — no relay transport in fork

* fix: remove duplicate function declarations in cron test

* fix: remove TalkSpeak schema refs removed by upstream refactoring

* fix: remove remaining TalkSpeak refs after upstream schema refactoring

* fix: add missing clampProbeTimeoutMs and fix testCase ref in control-ui test

* fix: resolve final TS type errors in cherry-picked tests

* fix: use InstanceType for GatewayClient type refs in test

* fix: resolve CI lint and test failures (no-explicit-any, hook audit finding ID)

---------

Co-authored-by: Peter Steinberger <[email protected]>
Co-authored-by: Gustavo Madeira Santana <[email protected]>
Co-authored-by: Stephen Schoettler <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>
Co-authored-by: Andrew Demczuk <[email protected]>
Co-authored-by: Robin Waslander <[email protected]>
Co-authored-by: Peter Steinberger <[email protected]>
Co-authored-by: Luke <[email protected]>
Co-authored-by: Ayaan Zaidi <[email protected]>
0x666c6f added a commit to 0x666c6f/openclaw that referenced this pull request Mar 26, 2026
…claw#57)

* fix(gateway): run before_tool_call for HTTP tools

* test(gateway): widen before tool hook mock typing (#43476)

* test(gateway): widen before tool hook mock typing

* chore: update pnpm.lock

* Gateway/Dashboard: surface config validation issues (#42664)

Merged via squash.

Prepared head SHA: 43f66cdcf04a14d5381a5a2f14e291a52a8b7389
Co-authored-by: huntharo <[email protected]>
Co-authored-by: huntharo <[email protected]>
Reviewed-by: @huntharo

* Memory: add multimodal image and audio indexing (#43460)

Merged via squash.

Prepared head SHA: a994c07190a2062322f459c928b6cd74f9803d88
Co-authored-by: gumadeiras <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras

* fix(hooks): add missing trigger and channelId to agent_end, llm_input, and llm_output hook contexts (#42362)

Merged via squash.

Prepared head SHA: e6d7b7e31aa6ae12813b4609adb6e569a4084d08
Co-authored-by: zhoulf1006 <[email protected]>
Co-authored-by: hydro13 <[email protected]>
Reviewed-by: @hydro13

* Memory: revalidate multimodal files before indexing

* preserve openai phase param

* chore: bump version to 2026.3.10

* 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>

* fix: repair bundled plugin dirs after npm install

* 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

* 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

* fix: harden state dir permissions during onboard

* 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.

* 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

* 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

* fix(cli): handle scheduled gateway restarts consistently

* test(cli): update daemon coverage restart contract

* fix: harden openai websocket replay

* fix(discord): enforce users/roles allowlist in reaction ingress

References GHSA-9vvh-2768-c8vp.

* test: fix websocket tool shape coverage

* fix: isolate plugin discovery env from global state

* fix(sandbox): anchor fs-bridge writeFile commit to canonical parent path

Refs: GHSA-xvx8-77m6-gwg6

* feat: expose runtime version in gateway status

* fix(acp): rehydrate restarted main ACP sessions (#43285)

Merged via squash.

Prepared head SHA: f06318e58fe3e3fedd70426ca7eeecf6d71bb604
Co-authored-by: frankekn <[email protected]>
Co-authored-by: frankekn <[email protected]>
Reviewed-by: @frankekn

* fix(context-engine): guard compact() throw + fire hooks for ownsCompaction engines (#41361)

Merged via squash.

Prepared head SHA: 0957b32dc63b16d710403565953b77bfbd2bd987
Co-authored-by: davidrudduck <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* docs: reorder unreleased changelog by user impact

* 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 <[email protected]>

* docs: update 2026.3.11 release examples

* build: sync versions to 2026.3.11

* fix(telegram): avoid polling restart hang after stall detection

* fix: clear telegram polling cleanup timers

* build: bump openclaw to 2026.3.11-beta.1

* 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 <[email protected]>
Co-authored-by: Ayaan Zaidi <[email protected]>

* build: prepare 2026.3.11 release

* 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

* Infra: block GIT_EXEC_PATH in host env sanitizer (#43685)

* Infra: block GIT_EXEC_PATH in host env sanitizer

* Changelog: note host env hardening

* 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

* Infra: cap device tokens to approved scopes (#43686)

* Infra: cap device tokens to approved scopes

* Changelog: note device token hardening

* Update CHANGELOG.md

* Update CHANGELOG.md

* Tests: clean up temp git helper directory

* Infra: fail closed without device scope baseline

* style: format changelog

* 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 e5774471c851b773dd2bffd51dd5d28d95a8a7ca)

* Changelog: note Reminders permission fix

* 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

* 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

* 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 <[email protected]>
Co-Authored-By: Happy <[email protected]>

* Changelog: add TUI duplicate-render fix entry

---------

Co-authored-by: 沐沐 <[email protected]>
Co-authored-by: Claude <[email protected]>
Co-authored-by: Happy <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>

* 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 <[email protected]>

* 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

* 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 <[email protected]>

* 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 <[email protected]>

* Replies: keep block-pipeline reply targets distinct

* Tests: cover block reply target-aware dedupe

* Update CHANGELOG.md

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>

* Models: enforce source-managed SecretRef markers in models.json (#43759)

Merged via squash.

Prepared head SHA: 4a065ef5d849273756ceb0dd241ca24ca9e621ca
Co-authored-by: joshavant <[email protected]>
Co-authored-by: joshavant <[email protected]>
Reviewed-by: @joshavant

* BlueBubbles: require confirmed outbound for self-chat cache

* 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

* Infra: tighten exec allowlist glob matching (#43798)

* Infra: tighten exec allowlist glob matching

* Changelog: note GHSA-f8r2 exec allowlist fix

* 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)

* 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 <[email protected]>

* Agents: clear invalidated Kimi tool arg repair (#43824)

* Tests: extend exec allowlist glob coverage

* 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

* 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

* feat(llm-task): add thinking override

Co-authored-by: Xaden Ryan <[email protected]>

* 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 <[email protected]>

* Docs: clarify llm-task thinking presets

* 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

* 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

* fix(failover): add missing network errno patterns to text-based timeout classifier (#42830)

Merged via squash.

Prepared head SHA: 91761487e8825c0fd6582a762d04bba04f726a85
Co-authored-by: jnMetaCode <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

* fix: preserve sandbox write payload stdin (#43876)

Merged via squash.

Prepared head SHA: a10fd4b21c78ec57411e6a4f387f16b1441660c2
Co-authored-by: glitch418x <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

* fix: stop main-session UI replies inheriting channel routes

* fix: stop main-session UI replies inheriting channel routes (#43918)

* fix: add zalouser outbound chunker

* fix(doctor): canonicalize gateway service entrypoint paths (#43882)

Merged via squash.

Prepared head SHA: 9f530d2a86b5d30822d4419db7cffae6a560ddca
Co-authored-by: ngutman <[email protected]>
Co-authored-by: ngutman <[email protected]>
Reviewed-by: @ngutman

* docs: add Kubernetes install guide, setup script, and manifests (#34492)

* add docs and manifests for k8s install

Signed-off-by: sallyom <[email protected]>

* changelog

Signed-off-by: sallyom <[email protected]>

---------

Signed-off-by: sallyom <[email protected]>

* feat(mattermost): add replyToMode support (off | first | all) (#29587)

Merged via squash.

Prepared head SHA: 4a67791f53b1109959082738429471b7a5bc93b8
Co-authored-by: teconomix <[email protected]>
Co-authored-by: mukhtharcm <[email protected]>
Reviewed-by: @mukhtharcm

* fix(telegram): allow fallback models in /model validation (#40105)

Merged via squash.

Prepared head SHA: de07585e03cba06897d50c1d79fbe09d326c6ac9
Co-authored-by: avirweb <[email protected]>
Co-authored-by: velvet-shark <[email protected]>
Reviewed-by: @velvet-shark

* fix: carry observed overflow token counts into compaction (#40357)

Merged via squash.

Prepared head SHA: b99eed4329bda45083cdedc2386c2c4041c034be
Co-authored-by: rabsef-bicrym <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* fix(status): resolve context window by provider-qualified key, prefer max on bare-id collision, solve #35976 (#36389)

Merged via squash.

Prepared head SHA: f8cf752c59708fb388fd200276115277e8b217d6
Co-authored-by: haoruilee <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* Agents: adapt pi-ai oauth and payload hooks

* build: default to Node 24 and keep Node 22 compat

* build: raise Node 22 compatibility floor to 22.16

* build: align Node 22 guidance with 22.16 minimum

* ci: harden pnpm sticky cache on PRs

* ci: restore PR pnpm cache fallback

* ci: tighten cache docs and node22 gate

* fix(mattermost): pass mediaLocalRoots through reply delivery (#44021)

Merged via squash.

Prepared head SHA: 856f11f129f7d6a4bc8f23e8d13c786ecb871f52
Co-authored-by: LyleLiu666 <[email protected]>
Co-authored-by: mukhtharcm <[email protected]>
Reviewed-by: @mukhtharcm

* 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

* 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

* 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

* 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

* 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

* 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

* 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.

* Compaction Runner: emit transcript updates post-compact (#25558)

Merged via squash.

Prepared head SHA: 8a858436ed31805124a9d096bd93ab90e5423672
Co-authored-by: rodrigouroz <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* Plugins: fix env-aware root resolution and caching (#44046)

Merged via squash.

Prepared head SHA: 6e8852a188b0eaa4d6cf0bb71829023e0e0ed82b
Co-authored-by: gumadeiras <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras

* feat: add sessions_yield tool for cooperative turn-ending (#36537)

Merged via squash.

Prepared head SHA: 75d9204c863792226389a4d33eeb40c4e842528d
Co-authored-by: jriff <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* 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)

* 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

* 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 <[email protected]>

* Tests: use Kimi implicit provider harness

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Vincent Koc <[email protected]>

* 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)

* fix(ios): add live activity horizontal padding

* 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

* docs: clarify gateway HTTP trust boundary

* Gateway: harden custom session-store discovery (#44176)

Merged via squash.

Prepared head SHA: 52ebbf5188b47386f2a78ac4715993bc082e911b
Co-authored-by: gumadeiras <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras

* fix(ci): harden docker builds and unblock config docs

* fix: make node-llama-cpp optional for npm installs

* fix: canonicalize openrouter native model keys

* runner: infer names from malformed toolCallId variants (#34485)

Merged via squash.

Prepared head SHA: 150ea1a7c90de3232f72498d851719c4dfb00b43
Co-authored-by: yuweuii <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* Gateway: preserve discovered session store paths

* docs: reorder unreleased changelog

* 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

* 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

* 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 <[email protected]>

* 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

* 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)

* 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

* 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

* 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

* fix: format CSS files for oxfmt (#44313)

* 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

* 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 <[email protected]>

* fix(sandbox): restore spawned workspace handoff (#44307)

* feat(context-engine): plumb sessionKey into all ContextEngine methods (#44157)

Merged via squash.

Prepared head SHA: 0b341f6f4ce487055d8bc0c0d335c42577941592
Co-authored-by: jalehman <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* docs: codify American English spelling convention (#44159)

* fix(failover): classify z.ai network_error stop reason as retryable timeout (#43884)

Merged via squash.

Prepared head SHA: 9660f6cd5bcb8d073fc5575bbba2bf3792b29de3
Co-authored-by: hougangdev <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

* fix(failover): classify ZenMux quota-refresh 402 as rate_limit (#43917)

Merged via squash.

Prepared head SHA: 1d58a36a774d06b1493971e8f14f9abc806be6b0
Co-authored-by: bwjoke <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

* Compaction Runner: wire post-compaction memory sync (#25561)

Merged via squash.

Prepared head SHA: 6d2bc02cc16429a19b041acd353c08dd2404335f
Co-authored-by: rodrigouroz <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* fix(gateway): honor trusted proxy hook auth rate limits

* fix(security): audit unrestricted hook agent routing

* refactor(gateway): move request client ip resolution to net

* refactor(gateway): cache hook proxy config in runtime state

* refactor(security): reuse hook agent routing normalization

* refactor(test): share hook request handler fixtures

* fix(failover): classify HTTP 422 as format and OpenRouter credits as billing (#43823)

Merged via squash.

Prepared head SHA: 4f48e977fe06c5662753d3900fe94f1835cc2dce
Co-authored-by: jnMetaCode <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

* fix: skip cache-ttl append after compaction to prevent double compaction (#28548)

Merged via squash.

Prepared head SHA: a4114a52bcff6ed4057cc54d3c629bd723f3d420
Co-authored-by: MoerAI <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* fix: switch pairing setup codes to bootstrap tokens

* feat: modularize provider plugin architecture

* docs: explain plugin architecture

* 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.

* fix(security): harden nodes owner-only tool gating

* refactor: share openai-compatible local discovery

* refactor: remove legacy provider apply shims

* refactor: split non-interactive auth choice providers

* refactor: split simple api-key auth providers

* test: cover provider plugin boundaries

* refactor: unify gateway connect auth selection

* refactor: trim bootstrap token metadata

* refactor: extract websocket handshake auth helpers

* refactor: clarify pairing setup auth labels

* 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.

* fix: harden windows npm runtime path

* 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.

* fix(node-host): fail closed on ruby approval preload flags

* feat: add fast mode toggle for OpenAI models

* Revert "feat: add --no-test flag to prepare-gates"

This reverts commit ee6bdb3bab26f2796943c6cac03d8f62a5664937.

* feat: add Anthropic fast mode support

* fix: harden windows native updates

* feat: add windows update package spec override

* 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

* 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

* fix(models): keep codex spark codex-only

* test(live): add codex instructions to spark probe

* fix(security): strip Mongolian selectors in exec obfuscation detector

* Gateway: preserve trusted-proxy browser scopes

* build: update deps and fix vitest 4 regressions

* build: sync bundled plugin versions

* refactor: add non-interactive provider plugin setup

* refactor: validate provider plugin metadata

* fix(zalouser): require ids for group allowlist auth

* fix: avoid ineffective dynamic imports

* 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 <[email protected]>
Co-authored-by: Luke <[email protected]>

* test: resolve rebase conflicts in gateway coverage

* chore: prepare 2026.3.12 release

* refactor(zalouser): reuse shared name matching helper

* feat(zalouser): audit mutable group allowlists

* fix(routing): require ids for slack and msteams allowlists

* fix: quiet Telegram command overflow retry logs

* fix(memory): fail closed for Windows qmd wrappers

* docs(ollama): update onboarding flow

Co-Authored-By: Jeffrey Morgan <[email protected]>
(cherry picked from commit e8ca2ff4e522f2d971801a537b3c4fdfecde0711)

* fix: align Ollama onboarding docs before landing (#43473) (thanks @BruceMacD)

(cherry picked from commit 19fa274343a102ca85c7679ec28c5a3503a99f55)

* docs: reorder latest release changelog

* test: stabilize hooks loader log assertion on Windows

* fix: import oauth types from the oauth entrypoint

* refactor(agents): replace console.warn with SubsystemLogger in compaction-safeguard.ts (#9974)

Merged via squash.

Prepared head SHA: 35dcc5ba354ad7f058d796846bda9d1f8a416e04
Co-authored-by: dinakars777 <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* fix: clarify windows onboarding gateway health

* fix(gateway): strip unbound scopes for shared-auth connects

* test(commands): align slash-command config persistence coverage

* fix: use build-stage image for docker live tests

* test: harden plugin env-scoped fixtures

* fix(cron): avoid false legacy payload kind migrations

* fix(cron): compare raw value not trimmed in normalizePayloadKind

* fix: stop false cron payload-kind warnings in doctor (#44012) (thanks @shuicici)

* fix(memory): stop forcing Windows qmd cmd shims

* test: harden plugin fixture permissions on macos

* fix(feishu): fail closed on webhook signature checks

* test(qmd): make windows cli fixtures explicit

* test(gateway): avoid hoisted reply mock tdz

* fix: fall back to a startup entry for windows gateway install

* 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

* fix: enable fast mode for isolated cron runs

* 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 <[email protected]>

* fix: narrow Slack outbound blocks opt type

* changelog: move ACP final-snapshot entry to active 2026.3.12 section

* fix(ci): restore full gate

* UI: fix control chat logo fallback

* test(qmd): make windows cli fixtures explicit

* UI: fix mounted avatar meta fallback

* fix(ui): resolve control chat avatar fallback

* fix(ui): harden avatar fallback regressions

* test(ui): add jsdom runtime for vitest dom suites

* fix(ui): restore native web /status

* feat: show status reaction during context compaction (#35474)

Merged via squash.

Prepared head SHA: 145a7b7c4e1939718c41a300899ae813bd9c511b
Co-authored-by: Cypherm <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* fix(plugins): normalize bundled provider ids

* test(proxy): make env proxy tests windows-safe

* chore: update appcast for 2026.3.12 release

* fix(compaction): use full-session token count for post-compaction sanity check (#28347)

Merged via squash.

Prepared head SHA: cf4eab1c51e6b8890e23c2d7172313c40cd2fe04
Co-authored-by: efe-arv <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* chore: bump version to 2026.3.13

* test(utils): await temp dir cleanup in async tests

* 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)

* fix: handle Discord gateway metadata fetch failures (#44397)

Merged via squash.

Prepared head SHA: edd17c0effe4f90887ac94ce549f44a69fe19eb2
Co-authored-by: jalehman <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

* fix: harden windows gateway fallback launch

* test: fix windows startup fallback mock typing

* 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).

* fix(android): clip CommandBlock accent bar to rounded container bounds

* fix: recover outbound plugins from the active registry

* test: stabilize sanitize session history smoke checks

* 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

* fix(session): preserve `lastAccountId` and `lastThreadId` on session reset

* fix: add gateway session reset routing coverage (#44773) (thanks @Lanfei)

* 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: c372ba691b9964dc986c3a4880a7413ab8fb23f7
Co-authored-by: jrrcdev <[email protected]>
Co-authored-by: dvrshil <[email protected]>
Reviewed-by: @dvrshil

* fix: address delivery dedupe review follow-ups (#44666)

Merged via squash.

Prepared head SHA: 8e6d254cc4781df66ee02b683c4ad72b5a633502
Co-authored-by: frankekn <[email protected]>
Co-authored-by: frankekn <[email protected]>
Reviewed-by: @frankekn

* CLI: align xhigh thinking help text (#44819)

Merged via squash.

Prepared head SHA: ff1f12717692d7745b34c5aef7c1dde3c6a4500d
Co-authored-by: frankekn <[email protected]>
Co-authored-by: frankekn <[email protected]>
Reviewed-by: @frankekn

* docs: fix changelog credit for xhigh help (#44874)

* fix(sre:PLA-815): drop accidental node_modules from sync branch

* 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 <[email protected]>

* docs: fix session key :dm: → :direct (#26506)

* ci(sre:PLA-815): remove secrets job from ci workflow

* 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.

* 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.

* 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.

* 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.

* feat(android): consolidate Settings…
sbezludny pushed a commit to sbezludny/openclaw that referenced this pull request Mar 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gateway Gateway runtime size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants