Add `ownsNativeCompaction` capability to CliBackendPlugin so backends
that manage their own transcript compaction (e.g. Claude Code) can
declare it once and OpenClaw defers instead of fighting or failing.
Today only Codex declares compaction ownership (via the embedded runner
path + agentHarnessId). Claude-cli never reaches that path because it
runs as a CLI subprocess with no harness id set, so the safeguard
summarizer fires and hard-fails the turn.
This PR:
- Adds `ownsNativeCompaction?: boolean` to the backend plugin type
- Propagates it through all 4 backend resolution paths
- In `runCliTurnCompactionLifecycle`, when a backend declares ownership
but has no harness endpoint, returns a no-op instead of falling
through to the safeguard
- Sets the flag on claude-cli (first adopter)
Codex's existing native-harness path is unchanged: when
`isNativeHarnessCompactionSession` matches, the harness compaction
endpoint is still called as before.
Generalizes the partial fix in #87785 (codex-scoped) to a capability
any backend can opt into.
* fix(qqbot): allow RFC2544 benchmark range for token fetch (#88984)
QQ Bot `bots.qq.com` token-fetch path was failing for users whose DNS resolver maps the hostname into the RFC 2544 benchmark range `198.18.0.0/15` (commonly seen with fake-IP proxy stacks: sing-box, Clash, Surge, WSL2 DNS). The default SSRF guard treats that range as private and blocks the request, surfacing as "Network error getting access_token: Blocked: resolves to private/internal/special-use IP address".
Pass a host-scoped `SsrFPolicy` (`allowRfc2544BenchmarkRange: true`) to the single hard-coded `TOKEN_URL` request, mirroring the existing `QQBOT_MEDIA_SSRF_POLICY` pattern used by the media path. Because `TOKEN_URL` is a const and not user-controlled, the relaxation cannot widen attack surface to other hosts.
Adds a regression test asserting `policy: { allowRfc2544BenchmarkRange: true }` is forwarded into `fetchWithSsrFGuard`, and updates the existing equality assertion accordingly.
Fixes#88984
* fix(qqbot): scope token ssrf policy
Repairs a batch of narrow model/provider edge cases:
- honor OpenAI and Anthropic base URL environment overrides when provider config does not set an explicit base URL
- preserve OpenRouter Anthropic cache retention while stripping unsupported transport options
- allow apply_patch for non-OpenAI providers when the tool config otherwise permits it
- prune stale same-provider model selections from configure/model picker state
- expose GitHub Copilot bundled thinking policy metadata to offline/provider-policy lookups
- repair additive SQLite shared-state upgrades for existing databases
- keep same-size rotated log readers from reusing stale content in CI tooling
Proof:
- GitHub PR checks green on exact head 46514909b0
- Crabbox delegated Blacksmith Testbox tbx_01kt3em5r9vd7g0bnykrff6jdk exited 0
- Focused local Vitest/oxlint/format proof recorded in PR body and land-ready comment
Fixes#80347.
Fixes#88357.
Fixes#45269.
Supersedes #74427, #74432, #79370, #79894, #80366, and #88359.
Summary:
- Adds defensive failed-count reads in auto-reply/ACP accounting and Feishu fallback paths, plus a focused regression test, while keeping `ReplyDispatcher.getFailedCounts` required.
- PR surface: Source +24, Tests +35. Total +59 across 5 files.
- Reproducibility: yes. from source inspection. Current main calls `dispatcher.getFailedCounts().final` and si ... issing that method follows a clear TypeError path; the source PR also supplied terminal before/after proof.
Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(auto-reply): guard missing dispatcher getFailedCounts without wea…
Validation:
- ClawSweeper review passed for head 0bdfb4adeb.
- Required merge gates passed before the squash merge.
Prepared head SHA: 0bdfb4adeb
Review: https://github.com/openclaw/openclaw/pull/89318#issuecomment-4598624344
Co-authored-by: Alix-007 <li.long15@xydigit.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.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>
Fix live model inference edge cases across provider streaming, model switching, outbound delivery, and gateway tool resolution.
Includes live/provider issue fixes and leaves #89100 explicitly partial for the remaining FM-2 group routing case.
Keep iMessage native typing indicators alive through long tool-running gaps by bridging tool-start activity into the existing typing controller, while preserving typingMode and sendPolicy suppression semantics.
Real behavior proof was added from the live iMessage generated-image run: inbound id 5805, outgoing media reply id 5806, and requester-observed typing during the 84s tool path.
Co-authored-by: omarshahine <10343873+omarshahine@users.noreply.github.com>
Reviewed-by: @lobster
Route Slack plugin approval delivery through the shared native approval route gates while preserving Slack Block Kit buttons and plugin resolver semantics.
Verification: Slack/native approval unit tests, Slack QA Lab, and live clawd native plugin approval via Slack desktop.
Revert release-time extension lane isolation for Telegram and memory, and make Telegram timer-flush tests wait for async side effects after manually firing timers.
Verification:
- pnpm test:serial extensions/telegram/src/bot.create-telegram-bot.channel-post-media.test.ts extensions/telegram/src/bot.create-telegram-bot.media-group-skip-warning.test.ts extensions/telegram/src/bot.media.stickers-and-fragments.e2e.test.ts extensions/telegram/src/bot.media.downloads-media-file-path-no-file-download.e2e.test.ts test/vitest-scoped-config.test.ts
- pnpm exec oxfmt --check on touched files
- git diff --check on touched files
* fix(diagnostics): clear embedded-run activity when recovery declares lane idle
Stuck-session recovery transitions a lane to idle via the recovery
coordinator, but only mutated the session-state store. When an aborted
embedded run was removed without markDiagnosticEmbeddedRunEnded, the
activity store kept hasActiveEmbeddedRun set, so the liveness sweep
reported idle/embedded_run and isIdleQueuedRecoverableSessionStall
re-triggered recovery indefinitely.
Reconcile the activity store from the authoritative idle declaration by
clearing the session's embedded-run owners. The existing generation
guard already excludes any newer run that re-armed activity, so a live
requeued run is preserved.
* fix(diagnostics): reconcile tool/model activity on authoritative idle cleanup
clearDiagnosticEmbeddedRunActivityForSession (renamed from
clearDiagnosticEmbeddedRunsForSession) now clears the aborted run's tool and
model markers alongside the embedded-run owners, matching the default
markDiagnosticEmbeddedRunEnded teardown. Clearing only the owner set left the
lane as idle + orphaned tool/model activity, which
isIdleQueuedRecoverableSessionStall still treats as recoverable while work is
queued, so the liveness sweep kept re-triggering recovery instead of converging.
Adds regression cases with stale tool and model markers plus queued work.
* test(phone-control): align service mocks with keyed store API
* fix(diagnostics): preserve rearmed recovery activity
* fix(diagnostics): clear recovered owner markers
* fix(diagnostics): clear recovered embedded work keys
* fix(diagnostics): ignore stale same-key recovery owners
* fix(diagnostics): preserve same-session recovery rearm
* fix(diagnostics): ignore stale queued activity starts
* fix(diagnostics): record recovery cutoffs for empty activity
* fix(diagnostics): preserve fresh recovery markers
* fix(diagnostics): prune stale activity before fresh recovery block
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Make Workboard cards compact by moving expanded task/run metadata, proof, diagnostics, worker logs, automation, protocol state, events, and operator notes into a detail drawer.
Keep execution state simple and safe: active, linked, and archived cards avoid duplicate start paths; stale task cache is ignored when session lifecycle is authoritative; recent proof/events stay visible; dispatcher capacity distinguishes unclaimed review cards from claimed cards.