fix(agents): preserve valid CLI session bindings (#128732)

* fix(agents): preserve CLI session binding on format-class failover

shouldClearFailedCliSessionBinding cleared the stored CLI session
binding for every FailoverError, including format-class failures
(output limit exceeded, parser error, unsupported image input). A
format-class failover means the stream could not be read, not that
the CLI session on disk is invalid — clearing the binding silently
lost the conversation context on the next turn.

Narrow the condition to only session-invalidating failover reasons
(session_expired, auth, auth_permanent) using a whitelist so new
reasons default to preserving the binding.

Fixes #128698

* fix(agents): preserve valid CLI session bindings

* fix(agents): retain CLI binding across format recovery

* fix(agents): scope fresh CLI recovery by backend

* docs(plugins): document CLI recovery policy

---------

Co-authored-by: Vincent Koc <vincentkoc@users.noreply.github.com>
This commit is contained in:
SunnyShu
2026-08-25 10:42:39 +08:00
committed by GitHub
parent dca05ea39a
commit e2deb87c30
10 changed files with 324 additions and 31 deletions
+15
View File
@@ -215,8 +215,23 @@ model-alias, session, image, and watchdog fields as the bundled
| `imagePathScope` | Where staged image files live before handoff: `temp` or `workspace` |
| `serialize` | Keep same-backend runs ordered |
| `reseedFromRawTranscriptWhenUncompacted` | Opt in to bounded raw-transcript reseed before compaction for safe session resets |
| `freshSessionRecovery` | Fresh recovery policy after a recoverable resumed-session failure |
| `reliability.watchdog` | No-output timeout tuning, separate for fresh vs resumed runs |
`freshSessionRecovery` is a backend-owned compatibility contract:
- Leave it undefined or set it to `"replace-binding"` to preserve the legacy
clear-and-reseed behavior. OpenClaw clears the persisted binding and retries
with a fresh session when the failure is eligible for recovery.
- Set it to `"invalidated-only"` to suppress fresh replacement unless the
canonical invalidation predicate proves the old session is dead. Currently,
only `session_expired` does so.
Choose the value from the CLI or SDK session contract, not from a provider id
or broad error class. The bundled Anthropic backend uses `"invalidated-only"`;
its Agent SDK contract does not treat non-expiration failures as proof that the
conversation can no longer resume.
Prefer the smallest static config that matches the CLI. Add plugin callbacks
only for behavior that really belongs to the backend.