* fix(agents): resolve "current" session alias locally without gateway round-trip
The system prompt tells agents to use sessionKey="current" to refer to
their own session. Previously, resolveSessionReference sent the literal
string "current" to the gateway sessions.resolve action, which rejected
it with INVALID_REQUEST and logged a noisy error line on every tool call.
The wrapper fell back to requesterInternalKey and succeeded, so the tool
worked — but the gateway error was spurious.
Add "current" to the well-known client alias check in
resolveCurrentSessionClientAlias so it is resolved locally to the
requester's session key, matching how TUI/CLI/WebChat client labels are
handled. This eliminates the unnecessary gateway round-trip and the
error log line.
Fixes#78424
* test: update session_status tests for local current-key resolution
* test: update session_status tests for local current-key resolution
* Revert "test: update session_status tests for local current-key resolution"
This reverts commit d9f6c8b5248921c99f43dc222667ffa429b34401.
* Revert "test: update session_status tests for local current-key resolution"
This reverts commit 40bf77d06711833c1beaeedf562b60a765a559d6.
* Revert "fix(agents): resolve "current" session alias locally without gateway round-trip"
This reverts commit d92bc9b91e0840ea5823cd44223c139e434c5ec4.
* fix(agents): preserve literal current session resolution
---------
Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
Adds a required database-first legacy-store guard and regression coverage for legacy runtime state write patterns.
The guard is wired into architecture/preflight/changed checks, narrows the documented guard contract to the implemented filesystem-write scope, and tightens extension migration exemptions to explicit owner APIs. Also includes a small memory-core lint unblocker after current CI flagged an unnecessary non-null assertion.
Verification:
- pnpm check:database-first-legacy-stores
- pnpm lint:scripts
- node scripts/run-vitest.mjs test/scripts/check-database-first-legacy-stores.test.ts -- --reporter=verbose
- node scripts/run-oxlint.mjs extensions/memory-core/src/memory/manager-embedding-ops.ts
- git diff --check
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
- GitHub CI green for PR head 34dde2c620Closes#91628.
Quarantine unreadable and invalid Anthropic-family tool schemas before OpenAI-compatible serialization, keep tool choices aligned with surviving tools, and preserve provider metadata.
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
* feat(moonshot): add Kimi K2.7 Code support
* test(moonshot): surface K2.7 live provider errors
* ci(live): accept Kimi key for Moonshot sweeps
* test(moonshot): verify K2.7 across API regions
Adds a SQLite state query-plan regression test and smoke benchmark, wires the smoke artifact into source performance evidence, validates SQLite smoke output in the performance summary, and removes a retired ClawHub nav entry that broke docs link checks.
Fixes#91616
Delay public GitHub release publication until postpublish verification, dependency evidence upload, proof append, and required plugin publish gates pass.
Also updates release-maintainer instructions so newly publishable plugins are minted/prepublished through an owner-approved path without consuming the next auto-bumped beta version unless that path is the actual release publish.
* fix(thinking): apply Claude profile to anthropic-messages catalog rows
When a custom provider (e.g. `jdcloud-anthropic`) fronted Claude Opus over
the native anthropic-messages adapter, `--thinking xhigh` was silently
clamped to `off`. The thinking-profile dispatcher resolves bundled plugin
policy surfaces by exact provider id, so a renamed Anthropic-compatible
provider never reached the anthropic plugin's policy and `xhigh` was not
in the resulting profile.
`auto-reply/thinking.ts` already had a fallback keyed on
`context.api === "anthropic-messages"` that attached
`CLAUDE_FABLE_5_THINKING_PROFILE` for Fable models. Generalize it to use
`resolveClaudeThinkingProfile(modelId, params)` instead — the same
canonical helper the anthropic plugin uses — which still returns the Fable
profile for Fable models and now returns the correct Opus 4.7/4.8 profile
(with `xhigh`/`adaptive`/`max`) for Claude Opus regardless of provider id.
Non-Claude models on anthropic-messages routes still get the base
profile, and a Claude id on a non-Anthropic transport (e.g. an
openai-completions catalog row) is unaffected.
Fixes#91975
* fix(thinking): match native Anthropic includeNativeMax in fallback
Address ClawSweeper P2 review on #92053. The anthropic-messages fallback
in `resolveThinkingProfile` calls `resolveClaudeThinkingProfile` but
omits the `{ includeNativeMax: true }` option that the bundled anthropic
plugin uses (extensions/anthropic/provider-policy-api.ts:38,45).
For native-xhigh Claude families (Opus 4.7/4.8) this had no effect since
the native-xhigh branch already exposes `max`. But adaptive Claude
families that take the adaptive-default branch (e.g. claude-sonnet-4-6,
claude-opus-4-6) silently lost `max` parity on custom anthropic-messages
providers compared to native Anthropic policy.
Also add a regression test on `claude-sonnet-4-6` that verifies the
adaptive-branch path keeps `max` for custom providers.
* docs(thinking): document deliberate compat.xhigh bypass on anthropic-messages
Self-review surfaced a subtle behavior change worth documenting: when the
anthropic-messages fallback was generalized, non-Claude models on this
transport stop honoring catalog `compat.supportedReasoningEfforts: ["xhigh"]`
because they take the Claude base profile instead of falling through to the
later `catalogSupportsXHigh` upgrade path.
This is intentional — anthropic-messages does not carry a generic xhigh
contract; xhigh on this protocol is a Claude-family capability. Add an
inline comment at the resolver site and a regression test that locks the
suppression so the next reader (or a future patch) doesn't accidentally
restore the upgrade path.
* fix(thinking): extract Claude profile to leaf to break import cycle
The previous commits added a `resolveClaudeThinkingProfile` import from
`auto-reply/thinking.ts` to `plugin-sdk/provider-model-shared.ts`. The
shared barrel re-exports `provider-replay-helpers` and `plugins/types`,
which transitively reach back into `auto-reply` via the gateway server
methods chain — creating the madge cycle reported by
`check:madge-import-cycles`:
auto-reply/thinking.ts
-> ... -> plugin-sdk/provider-model-shared.ts
-> plugins/{config-schema, host-hooks, ...} -> plugins/types.ts
Move `BASE_CLAUDE_THINKING_LEVELS`, `isClaudeAdaptiveThinkingDefaultModelId`,
and `resolveClaudeThinkingProfile` to a new leaf module
`src/plugins/provider-claude-thinking.ts` whose only imports are
`@openclaw/llm-core` and the existing leaf `provider-thinking.types`.
`provider-model-shared.ts` continues to re-export both helpers so existing
consumers (`extensions/anthropic/*`, the public test surface) are
unaffected. `auto-reply/thinking.ts` now imports the leaf directly,
breaking the cycle.
* test(thinking): add live proof harness for #91975 anthropic-messages clamp
---------
Co-authored-by: wanglu241 <wanglu241@jd.com>
* fix(cli-runner): scope claude-cli queue to live-session owner identity
Fresh claude-cli runs without a stored cliSessionId previously collapsed
onto a single workspace-scoped queue key, serializing all fan-out within
one workspace regardless of subagent lane configuration.
Replace the workspace fallback with the same owner identity that
claude-live-session.ts already uses for its live-session map
(agentAccountId + agentId + authProfileId + sessionId + sessionKey),
keeping per-session resume safety while letting independent OpenClaw
sessions in the same workspace run concurrently.
Refactor buildClaudeLiveKey() to share the new buildClaudeOwnerKey()
helper so the queue key and the live-session key cannot drift.
Refs: #91946
* test(cli-runner): pin owner-key hash + document buildClaudeOwnerKey contract
Add a golden-hash regression test for buildClaudeOwnerKey using the
exact legacy fixture, so a future refactor that reorders fields or
flips the JSON encoding can't silently orphan every deployed Claude
live session at upgrade. Hash verified empirically against the prior
inline sha256(JSON.stringify(...)) in buildClaudeLiveKey.
Add a JSDoc on buildClaudeOwnerKey explaining the cross-module contract
between the CLI run queue and the live-session map.
Refs: #91946
* docs(cli-runner): tighten buildClaudeOwnerKey contract comment
The previous comment claimed an encoding mismatch would orphan deployed
live sessions across upgrades. The Claude live-session registry is
process-local, so any restart already discards every entry — the real
invariant is that the queue path and live-session path produce
byte-identical owner keys *within a single process*, so a fresh queued
turn picks up the same live session the registry already holds. Update
the helper docstring and the golden-hash test description accordingly;
the pinned hash and behavior are unchanged.
* test(cli-runner): add owner-key concurrency demo script
A pure-Node, no-test-runner demo that reproduces the PR-head queue
behavior end-to-end: BEFORE-PR collapse (workspace lane), distinct-owner
overlap, and identical-owner serialization, all in one run with
millisecond-stamped event ordering. Useful as a low-overhead regression
check for the owner-key contract and as a maintainer-runnable proof
artifact for #91946.
* test(cli-runner): satisfy oxlint curly + no-promise-executor-return
Wrap single-statement if/for-of bodies in braces and rewrite the
sleep helper so its Promise executor is a void block instead of an
arrow with an implicit return. No behavior change; demo output and
the byte-equivalent slice fingerprints are unchanged.
---------
Co-authored-by: wanglu241 <wanglu241@jd.com>
Capture the originating sessionKey and agentId for cron wake tool calls so non-main session and multi-agent wakes return to the conversation lane that requested them.
Carry stored delivery context through queued wake events so topic/thread replies route correctly, while preserving the default no-origin wake behavior and explicit target:none opt-out.
Refs #46886.
Refs #64556.
Thanks @anagnorisis2peripeteia.
Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>