* fix(status): render sub-1000 token counts as plain integers
formatKTokens always divided by 1000 and appended "k", so token counts
below 1000 rendered as misleading fractional k in `openclaw status`
output (e.g. 999 rounded up across the boundary to "1.0k", 420 -> "0.4k",
a 300-token cache write -> "write 0.3k").
Guard value < 1000 to render the plain rounded integer, matching the
canonical formatTokenCount convention (src/utils/usage-format.ts). The
>=1000 "k" behavior is unchanged. Adds focused regression tests for the
0/420/999/1000/12000 boundary and small-session/small-cache status lines.
Fixes#89735
* fix(status): reuse canonical token formatter
* refactor(status): extract lightweight token formatter
---------
Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
Cap configured session context overrides by the selected model's known context window, refresh provider/model metadata consistently, and preserve the fixed Anthropic 1M context contract.
Fixes#39857
Co-authored-by: Kros Dai <7087+xdanger@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(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.
* 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.
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.
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`
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.
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.
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`.
* Mark active main sessions during restart shutdown
* Type restart marker mock in close tests
* fix(gateway): preserve active run ownership across restart
* fix(gateway): preserve active runs across restart
* fix(gateway): close restart recovery edge cases
* fix(cron): preserve lifecycle ownership across restart
* fix(gateway): release rejected run contexts
* fix(gateway): preserve restart lifecycle ownership
* fix(cron): retain overlapping run ownership
* fix(agents): preserve restart terminal precedence
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Fixes#91003
Add explicit generated-media directives to completion handoff prompts and treat real attachment payloads as visible session-only delivery evidence for dashboard/webchat completions. Hardened maintainer follow-up keeps malformed attachment arrays from masking failed delivery and keeps generated MEDIA directive values single-line sanitized.
Proof: focused local format/lint/Vitest, clean final autoreview, Crabbox AWS focused proof run_32499eb46b33, Crabbox AWS check:changed run_af46879ffbd1, and exact-head GitHub CI green for f8e6f4a04e.
Fixes#44922
Preserve heartbeat-owned cron reminders as a single model input during heartbeat runs while keeping normal-turn fallback delivery when a heartbeat is skipped.
Proof: focused local Vitest/oxlint/format, clean autoreview, Crabbox AWS run_67abc286250a, Crabbox AWS check:changed run_bddebf014d58, and exact-head GitHub CI green for 341e807d7a.