fix(opencode): expose Claude thinking policy (#76760)

Summary:
- Adds an OpenCode provider-policy public artifact that delegates Claude thinking profiles, plus regression tests and a changelog entry for preserving `xhigh` on `opencode/claude-opus-4-7`.
- Reproducibility: yes. Source inspection on current main shows the model-switch path remaps unsupported store ... vider-policy-api` artifact for the fallback resolver; the proposed test exercises that stored-`xhigh` path.

Automerge notes:
- No ClawSweeper repair was needed after automerge opt-in.

Validation:
- ClawSweeper review passed for head efa152cca5.
- Required merge gates passed before the squash merge.

Prepared head SHA: efa152cca5
Review: https://github.com/openclaw/openclaw/pull/76760#issuecomment-4366483080

Co-authored-by: mkdev11 <MkDev11@users.noreply.github.com>
This commit is contained in:
MkDev11
2026-05-03 08:22:07 -07:00
committed by GitHub
parent 686585eccf
commit 38eea33062
4 changed files with 57 additions and 0 deletions

View File

@@ -44,6 +44,7 @@ Docs: https://docs.openclaw.ai
- Plugins/context-engine: include the selected `plugins.slots.contextEngine` plugin in the gateway startup load plan so external context-engine plugins without `activation.onStartup` in their manifest are loaded before any agent turn resolves the active engine; prevents the "Context engine X is not registered; falling back to default engine legacy" warning after gateway startup. Fixes #76576. Thanks @hclsys.
- Plugins/tools: restore on-demand registry load for path-based plugins (origin "config") so tool factories registered via `plugins.load.paths` are resolved at agent request time when no pre-warmed channel registry is present; prevents "unknown method" errors after gateway startup. Fixes #76598. Thanks @hclsys.
- Plugins/hooks: include explicitly enabled hook-capable plugins in the Gateway startup runtime scope so embedded PI runs can see their `before_prompt_build` and `agent_end` hooks. Fixes #76649. Thanks @wwf3045 and @MkDev11.
- Plugins/OpenCode: expose Claude thinking profiles through the lightweight provider policy surface so directive and session validation keep `xhigh`, `adaptive`, and `max` for `opencode/claude-opus-4-7` instead of remapping `xhigh` to `high`. Fixes #76648. Thanks @aaajiao.
- Channels/QQ Bot: resolve structured `clientSecret` SecretRefs before QQ token exchange, expose the QQ Bot secret contract to secrets tooling, and reject legacy `secretref:/...` marker strings. (#74772) Thanks @xialonglee.
- Agents: keep active streamed provider replies alive by refreshing guarded fetch timeouts on raw body chunks and surface true prompt stream timeouts as explicit errors instead of partial assistant fragments. Fixes #76307. (#76633) Thanks @MkDev11.
- Plugins/externalization: keep official ACPX, Google Chat, and LINE install specs on production package names, leaving beta-tag probing to the explicit OpenClaw beta update channel. Thanks @vincentkoc.

View File

@@ -0,0 +1,29 @@
import { describe, expect, it } from "vitest";
import { resolveThinkingProfile } from "./provider-policy-api.js";
describe("opencode provider policy public artifact", () => {
it("exposes Claude Opus 4.7 thinking levels without loading the full provider plugin", () => {
expect(
resolveThinkingProfile({
provider: "opencode",
modelId: "claude-opus-4-7",
}),
).toMatchObject({
levels: expect.arrayContaining([{ id: "xhigh" }, { id: "adaptive" }, { id: "max" }]),
defaultLevel: "off",
});
});
it("keeps adaptive-only Claude profiles aligned with Anthropic", () => {
const profile = resolveThinkingProfile({
provider: "opencode",
modelId: "claude-opus-4-6",
});
expect(profile).toMatchObject({
levels: expect.arrayContaining([{ id: "adaptive" }]),
defaultLevel: "adaptive",
});
expect(profile.levels.some((level) => level.id === "xhigh" || level.id === "max")).toBe(false);
});
});

View File

@@ -0,0 +1,5 @@
import { resolveClaudeThinkingProfile } from "openclaw/plugin-sdk/provider-model-shared";
export function resolveThinkingProfile(params: { provider?: string; modelId: string }) {
return resolveClaudeThinkingProfile(params.modelId);
}

View File

@@ -985,6 +985,28 @@ describe("handleDirectiveOnly model persist behavior (fixes #1435)", () => {
});
});
it("keeps xhigh when switching to OpenCode Claude Opus 4.7", async () => {
const sessionEntry = createSessionEntry({ thinkingLevel: "xhigh" });
const sessionStore = { [sessionKey]: sessionEntry };
const result = await handleDirectiveOnly(
createHandleParams({
directives: parseInlineDirectives("/model opencode/claude-opus-4-7"),
allowedModelKeys: new Set([...allowedModelKeys, "opencode/claude-opus-4-7"]),
allowedModelCatalog: [
...allowedModelCatalog,
{ provider: "opencode", id: "claude-opus-4-7", name: "Claude Opus 4.7" },
],
sessionEntry,
sessionStore,
}),
);
expect(result?.text).toContain("Model set to opencode/claude-opus-4-7 for this session.");
expect(result?.text ?? "").not.toContain("xhigh not supported");
expect(sessionEntry.thinkingLevel).toBe("xhigh");
});
it("does not request a live restart when /model mutates an active session", async () => {
const directives = parseInlineDirectives("/model openai/gpt-4o");
const sessionEntry = createSessionEntry();