Bound gateway model pricing catalog reads through the shared streaming byte-limit helper so no-content-length LiteLLM/OpenRouter responses cannot be fully buffered past the 5 MiB cap before rejection. Adds a regression for streamed LiteLLM overflow while preserving OpenRouter fallback pricing.
Keep the OpenAI Realtime WebRTC smoke's SDP offer request in the browser fetch path while moving the browser-side SDP answer reader into a testable helper. Reject unsafe decimal Content-Length values before acquiring a body reader and preserve streamed byte limiting for responses without a safe declared length.
Proof: direct bounded-reader repro rejects unsafe content-length before getReader and cancels the body; node --check --experimental-strip-types scripts/dev/realtime-talk-live-smoke.ts; node --check --experimental-strip-types test/scripts/dev-tooling-safety.test.ts; git diff --check origin/main...HEAD; autoreview clean overall 0.84; exact-head release gate succeeded at https://github.com/openclaw/openclaw/actions/runs/27848673438.
Reject unsafe decimal Content-Length values in the E2E bounded response text helper before streaming response bodies. Keep non-decimal values on the streaming byte-limit path and add regression coverage proving unsafe declared lengths cancel without starting a read.
Proof: direct patched repro rejects before reading with code ETOOBIG; origin/main comparison entered the reader first; node --check scripts/e2e/lib/bounded-response-text.mjs; git diff --check origin/main...HEAD; autoreview clean overall 0.86; exact-head release gate succeeded at https://github.com/openclaw/openclaw/actions/runs/27846197115.
* feat(cli): add `sessions compact` command and fail loudly on CLI `/compact`
`sessions.compact` was reachable only as an internal Gateway RPC — no CLI
command, no docs — and `openclaw agent --message '/compact'` silently no-opped
with exit 0 because the slash-command handler rejects CLI-originated senders,
so the message fell through to an ordinary agent turn that compacted nothing.
- Add `openclaw sessions compact <key>` wrapping the existing `sessions.compact`
RPC; exit non-zero on a transport error or an `ok:false` payload so automation
never mistakes a silent no-op for success.
- Reject `openclaw agent --message '/compact'` with a redirect to the new
command and exit 1 instead of a silent exit 0. The shared chat-side `/compact`
handler is left untouched (no compatibility / message-delivery blast radius).
- Strictly validate `--max-lines` and `--timeout` (positive integers only).
- Document the command and the `sessions.compact` RPC in docs/cli/sessions.md.
Fixes#90640.
* fix(cli): inherit parent `sessions` options for `compact`
`openclaw sessions compact <key>` did not merge the parent `sessions`
command options the way its sibling subcommands (list/cleanup/info/…) do,
so a parent-level `--agent`/`--json` was silently dropped. In particular
`openclaw sessions --agent work compact <key>` compacted the default
agent's session instead of the work agent's — a wrong-target session-state
mutation.
Merge the parent options in the compact action (parent `--agent`/`--json`,
with the compact-level option taking precedence) and add regression
coverage for parent `--agent`, parent `--json`, and the compact-level
override.
Refs #90640.
* fix(cli): report pending Codex compaction and reject unsupported parent options
Address two ClawSweeper review findings on the `sessions compact` command:
- `sessions-compact.ts`: the Codex app-server `thread/compact/start` path
returns `ok:true / compacted:false` with a pending marker, meaning the
compaction was *started* asynchronously. The formatter collapsed every
non-compacted success into "No compaction needed", so Codex users were told
nothing happened. Report it as a started/pending compaction instead.
- `register.status-health-sessions.ts`: the parent `sessions` command defines
list-only options (`--store`/`--all-agents`/`--active`/`--limit`) that the
compact action previously ignored. Silently dropping a parent `--store` is
dangerous — the gateway resolves the target store itself, so a user could
believe they targeted one store while another is mutated. Reject any
unsupported inherited parent option with a clear error and a non-zero exit.
Add regression tests for the pending-compaction message and the rejected
parent options.
Refs #90640.
* fix(gateway): guard sessions.compact maxLines truncation against active runs
The non-maxLines (LLM) compact branch interrupts an active session run before
compacting, but the maxLines truncate branch read the tail, archived, and
overwrote the transcript in place without that guard. Exposing `--max-lines`
as a documented CLI command (this PR) would make the active-run data-loss mode
tracked by #72765 easy to trigger from ordinary CLI usage.
Run the same interruptSessionRunIfActive guard in the maxLines branch before
reading the tail and truncating, matching the LLM compact path. Add gateway
regression coverage over a real in-process Gateway: with no active run, the
maxLines branch truncates the on-disk transcript 500 -> 50 and preserves the
original 500 lines in the .bak archive; with an active embedded run, the
maxLines branch fires the same interrupt (abort + wait-for-end) before
archiving and truncating.
* docs(cli): move sessions compact section above related links
The new "Compact a session" section was inserted between the cleanup
section's inline "Related:" list and the page's final "## Related"
block, splitting related-link content around the command docs. Move the
compact section above the related-links area and merge the orphaned
"Session config" link into the single final "## Related" block.
* fix(gateway): avoid no-op compact aborts
Signed-off-by: sallyom <somalley@redhat.com>
* fix(gateway): satisfy compact preflight lint
Signed-off-by: sallyom <somalley@redhat.com>
* fix(sessions): preserve compacted transcript structure
---------
Signed-off-by: sallyom <somalley@redhat.com>
Co-authored-by: sallyom <somalley@redhat.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Reject unsafe numeric Content-Length values in the OpenAI chat tools E2E client before waiting on the response stream.
Also hardens Docker E2E heartbeat timing coverage after the exact-head release gate exposed a brittle zero-padded heartbeat assertion.
Verification: direct mock gateway repro, docker heartbeat shell proof, autoreview clean, and exact-head CI release gate https://github.com/openclaw/openclaw/actions/runs/27843455246.