Fixes#54909.
Repair #54962 by preserving raw slash-command callbacks while routing generic callback data to agents as `callback_data: <value>`.
Validation:
- pnpm check:changed
- pnpm -s vitest run extensions/telegram/src/bot.create-telegram-bot.test.ts
- Codex /review
- Real behavior proof
- GitHub PR checks
Source PR credit: continues @hnshah's work from #54962 and preserves @timt80's report credit from #54909.
Co-authored-by: Hiten Shah <3155200+hnshah@users.noreply.github.com>
* fix(gateway): preserve active run during plugin finalization
* fix(ui): skip session.message history reload while gateway reports active run
* fix(ui): remove unused eslint-disable directive
* fix(ui): preserve active runs through finalization
---------
Co-authored-by: scotthuang <scotthuang@tencent.com>
Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
* fix(gateway): use resolveNonNegativeNumber for totalTokens to display 0 instead of ?
resolvePositiveNumber requires value > 0, filtering out the valid
totalTokens = 0 case (new session, no usage yet). This caused the TUI
to display 'tokens ?/200k' instead of 'tokens 0/200k (0%)'.
Use resolveNonNegativeNumber (>= 0) for the final totalTokens value
used in session display. The needsTranscriptTotalTokens check at line
2041 still correctly uses resolvePositiveNumber to decide whether to
fetch transcript data.
Fixes#43009
* fix(gateway): preserve fresh zero-token sessions
---------
Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
* fix(macos): defer isOverflowing mutation to break SwiftUI render loop
measuredHeight() mutated model.isOverflowing synchronously during a SwiftUI
view update cycle. The onChange(of: attributed) handler triggered
updateWindowFrame → targetFrame → measuredHeight, which set isOverflowing,
invalidating the view and re-triggering onChange — an infinite render loop
causing 100% CPU pinwheel.
Fix: defer the isOverflowing mutation via DispatchQueue.main.async with an
equality guard to prevent redundant updates. The frame calculation itself
remains synchronous so the window size is correct immediately.
Fixes#43480
* fix(macos): preserve latest overflow measurement
---------
Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
* fix(telegram): skip IPv4 fallback when user configures non-ipv4first dnsResultOrder
When the user explicitly configures channels.telegram.network.dnsResultOrder
to a non-ipv4first value (e.g. verbatim), the sticky IPv4 fallback dispatcher
should not be armed. Forcing autoSelectFamily=false + dnsResultOrder=ipv4first
overrides the user's explicit IPv6-friendly config, causing media downloads to
fail on hosts where IPv4 is broken but IPv6 works.
Fixes#41671
* fix(telegram): respect explicit DNS fallback policy
---------
Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
* fix(doctor): avoid false-positive legacy cron store warning when store was already migrated
When rawJobs.length > 0 and other issues exist (notifyCount, dreamingStaleCount)
but legacyStoreDetected is false (file already removed after migration), the doctor
unconditionally printed 'Legacy cron job storage detected at ...' — misleading users
into thinking the migration was incomplete.
Fix: conditionally use 'Cron store issues detected' heading when no legacy store file
exists, reserving 'Legacy cron job storage detected' for actual legacy store presence.
Fixes#92683
* test(doctor): add test for false-positive legacy cron store warning (#92683)
Follow-up to #92745 after maintainer autoreview found that the skipped recall event widened the shipped MemoryHostEvent union and changed limited legacy reads.
Keep readMemoryHostEvents() source-compatible by filtering diagnostic records before applying limits, and expose skipped recall diagnostics through the opt-in MemoryHostEventRecord/readMemoryHostEventRecords path.
Original skipped-recall behavior landed in #92745 by @mushuiyu886.
Fixes#42156.
Answer Telegram callback queries before per-chat/topic sequentialize can queue the handler behind an active turn, and carry the in-flight answer promise on the grammY context so the normal handler reuses it instead of double-answering.
Proof:
- node scripts/run-vitest.mjs extensions/telegram/src/bot.create-telegram-bot.test.ts -- -t "answers callback queries before same-chat sequentialize delays handlers|sequentializes updates by chat and thread|routes callback_query payloads as messages"
- node scripts/run-vitest.mjs extensions/telegram/src/bot.test.ts extensions/telegram/src/bot-handlers.runtime.test.ts
- node_modules/.bin/oxfmt --check extensions/telegram/src/bot-core.ts extensions/telegram/src/bot-handlers.runtime.ts extensions/telegram/src/callback-query-answer-state.ts extensions/telegram/src/bot.create-telegram-bot.test.ts
- git diff --check origin/main...HEAD
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
- Azure Crabbox cbx_cba20c462ad5 / silver-barnacle: OPENCLAW_TESTBOX=1 node scripts/crabbox-wrapper.mjs run --provider azure --class Standard_D4ads_v6 --idle-timeout 90m --ttl 240m --timing-json -- env OPENCLAW_CHECK_CHANGED_REMOTE_CHILD=1 OPENCLAW_CHANGED_LANES_RAW_SYNC=1 corepack pnpm check:changed
Proof gap: live Telegram Desktop/burner-account proof was not run because openclaw-telegram-user-crabbox-proof is not installed in this shell.
Reject voice media stream start frames when no acceptance validator is configured, preventing fail-open STT/TTS session creation. Verified locally, with autoreview, in a remote Linux dev box, and by green CI.
* fix(gateway): accept image-only input on /v1/responses
The OpenResponses endpoint rejected requests whose `input` contained only
an `input_image` (no `input_text`) with `400 Missing user message in
input.`, even though the image was parsed and collected into `images`.
The guard only checked `prompt.message` and ignored `images`, unlike the
equivalent /v1/chat/completions guard which uses
`!prompt.message && images.length === 0`.
Align the OpenResponses guard with Chat Completions so image-only turns
are forwarded to the agent. Empty input (no text and no image) still
returns 400.
Adds regression tests: image-only base64 input -> 200 with image reaching
the agent, and empty content -> 400.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(gateway): pass image-only /v1/responses turns to the agent
The one-line guard alone was insufficient: even after letting image-only
input past the `Missing user message` check, the downstream agent command
(`prepareAgentCommandExecution`) throws `Message (--message) is required`
for an empty message, so image-only `/v1/responses` returned 500.
Mirror the /v1/chat/completions prompt builder: substitute the shared
IMAGE_ONLY_USER_MESSAGE placeholder for the active image-only user turn so
the turn is not dropped and the real image is still attached via `images`.
Promote the placeholder constant to the shared gateway agent-prompt module
so both endpoints stay in sync, and revert the responses guard back to the
original `!prompt.message` check (responses images are not scoped to the
active turn, so the placeholder is the correct, single source of truth).
Co-authored-by: Cursor <cursoragent@cursor.com>
* chore: retrigger CI (flaky startup-core test timeout, unrelated to change)
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: songwendong <songwendong@shuidi-inc.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Record diagnostic events when memory_search returns durable memory hits that are intentionally excluded from short-term promotion, so users can distinguish eligibility decisions from recall tracking failures.
Keep cron-local transient auth failures from polluting shared cooldowns while preserving real auth/billing/rate-limit propagation. Verified with focused auth/cron tests, type proof, autoreview, and clean CI.
Normalize Windows schtasks default gateway names without hiding similarly prefixed duplicate tasks. Verified with focused daemon tests, type proof, autoreview, and clean CI.
Keep the Tavily public artifact lightweight while lazily executing through the provider runtime. Verified with focused Tavily/provider artifact tests and clean CI.
Limit SSH tunnel classification to actual queried-port forwards and keep SSH-like non-gateway listeners out of stale gateway cleanup. Verified with focused port/restart tests and clean CI.
Validates Matrix CLI numeric option ranges before invoking setup or verification side effects.
`--initial-sync-limit` must now be non-negative, and `--timeout-ms` must now be positive.
Original PR by @rohitjavvadi.
Verification:
- `node scripts/run-vitest.mjs extensions/matrix/src/cli.test.ts --maxWorkers=1`
- autoreview clean
- Crabbox AWS `cbx_5c32f138ab3a` / `swift-lobster`, run `run_6e133b8b82e7`: `check:changed` passed
- exact PR head CI green: `d75f118299029b0516311646276cd2d6582379c5`
Preserves provider-compatible CLI runtime session pins across reply execution, follow-up execution, dispatch visibility, preflight compaction, and memory flush.
This keeps sessions pinned to compatible CLI runtimes such as `claude-cli` from leaking into embedded OpenClaw maintenance paths while still rejecting cross-provider runtime pins.
Original PR by @yu-xin-c; includes maintainer follow-up for the sibling memory paths.
Verification:
- `node scripts/run-vitest.mjs src/auto-reply/reply/agent-runner-execution.test.ts src/auto-reply/reply/agent-runner-memory.test.ts src/agents/model-runtime-aliases.test.ts --maxWorkers=1`
- autoreview clean
- Crabbox AWS `cbx_44400b494e97` / `coral-prawn`, run `run_69dd43475e39`: `check:changed` passed
- exact PR head CI green: `303b2f794f6c01fcf21b62b27c536b5f6eceb421`
Updates the macOS Swift package resolution for patch releases of Peekaboo, Sparkle, and swift-log.
Verification:
- `swift package describe --type json`
- `swift build --target OpenClawIPC`
- `swift build --target OpenClawDiscovery`
- upstream tag/revision checks for Peekaboo 3.4.1, Sparkle 2.9.3, and swift-log 1.13.2
- autoreview clean
- exact PR head CI green for macOS, dependency, and security checks
Remove the stale nested openclaw package, its .bin shim, and the pnpm virtual-store copy from the runtime Docker image before final runtime assets are copied.
Run the package dist import-closure check after the cleanup so the check validates the final runtime-assets tree that the image ships.
Compatibility note: private Docker paths under /app/node_modules/openclaw and /app/node_modules/.bin/openclaw are removed; downstream images should use the documented /usr/local/bin/openclaw launcher or /app/openclaw.mjs.
Fixes#92551.
Thanks @lzyyzznl for the fix and @fxstein for the report.
Derive the channel from canonical account-scoped DM session keys when resolving session.sendPolicy, so channel-scoped allow/deny rules apply to per-account-channel-peer sessions.
Keep derivation limited to canonical channel peer key shapes and add malformed-key regressions so incomplete or non-channel keys do not accidentally match channel rules.
Compatibility note: existing channel-scoped send-policy rules can now block account-scoped DM sends that were previously allowed by this bug.
Thanks @yetval for the fix.
Route OpenAI/OpenAI-compatible request_headers_too_large embedding failures into the existing memory-core batch splitter instead of aborting bulk memory indexing.
Tighten the classifier to require header-too-large wording rather than a bare 431 status token, so unrelated provider errors do not fan out into recursive requests.
Fixes#92465.
Thanks @mushuiyu886 for the fix and @BrettHamlin for the report and proof.
Add a Nodes overview `openclaw.json` example for node pairing, command allow/deny policy, node exec routing, and per-agent node pinning.
Also clarifies exact `denyCommands` matching and links readers to the config reference for pairing and command-policy field details.
Fixes#92662.
Thanks @liuhao1024 for the fix and @ZengWen-DT for the parallel docs wording on exact node command policy.
Correct the exported agent defaults type comments for `maxConcurrent` and `subagents.maxConcurrent` so they match the runtime defaults of 4 and 8.
No runtime behavior changes.
Thanks @ArielSmoliar for the fix.
Fix render-aware markdown chunking so `Number.POSITIVE_INFINITY` is treated as an explicit unbounded chunk limit instead of falling back to `1`.
This preserves full Signal media captions and disabled Signal text chunking while keeping invalid non-finite limits on the existing fallback path.
Fixes#92734.
Thanks @yhterrance for the report and fix.
Summary:
- The branch changes diagnostic stuck/long-running warning backoff so recovery-eligible classifications are still returned during throttled warning ticks and updates the diagnostic tests.
- PR surface: Source +17, Tests +48. Total +65 across 2 files.
- Reproducibility: yes. Current main source shows logSessionAttention can return undefined during stuck or lon ... g backoff before the heartbeat reaches requestStuckSessionRecovery; I did not run a live QQ gateway replay.
Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(diagnostics): keep recovery scheduling out of the stuck-session w…
Validation:
- ClawSweeper review passed for head f61ec3a33f.
- Required merge gates passed before the squash merge.
Prepared head SHA: f61ec3a33f
Review: https://github.com/openclaw/openclaw/pull/92752#issuecomment-4699298908
Co-authored-by: Gnanam <gnanasekaran.sekareee@gmail.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
Uses the canonical model ref returned by `sessions.patch` for the TUI `/model` confirmation so alias inputs report the model that was actually applied. The fallback still shows the raw input when a backend does not return `resolved`, and the display path uses `modelKey` so nested model ids keep the provider prefix without double-prefixing self-prefixed ids.
Proof: local focused TUI Vitest/format/lint; autoreview clean; Crabbox AWS focused TUI test run `run_7d7cc5b040e8`; exact-head GitHub CI green on `6db4acfb08f9d477ee1bdab429bd7189b78ffc92`.
Detects NFS-backed SQLite database paths in the shared WAL helper and uses rollback journaling for those paths while preserving WAL/checkpoint maintenance on local filesystems. The NFS path now verifies SQLite's effective journal mode before disabling WAL maintenance, and core/memory/proxy-capture callers pass database path context into the centralized helper.
Fixes#90491.
Proof: local focused Vitest/format/lint; autoreview clean after fixing the journal-mode verification finding; Crabbox AWS focused test run `run_2ea7014350da`; Crabbox AWS changed gate `run_c828bbfe7d23`; exact-head GitHub CI green on `59674305ecd863d4815eec6098ccd3daab79ca4f`.