mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-18 19:14:44 +00:00
fix: stabilize Gemini default and Bedrock thinking policy
This commit is contained in:
@@ -181,6 +181,8 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
### Fixes
|
||||
|
||||
- Google/Gemini: default new API-key onboarding to stable `google/gemini-2.5-flash` instead of the preview Pro route, reducing surprise daily quota exhaustion. Fixes #79670. Thanks @HugeBunny.
|
||||
- Amazon Bedrock: expose Claude thinking profiles through the lightweight provider policy surface so `/think:adaptive` validates before the Bedrock runtime plugin is loaded. Fixes #79754. Thanks @phoenixyy and @hclsys.
|
||||
- Codex/transcripts: mirror dynamic tool calls and outputs into Codex app-server transcripts so tool activity is visible alongside assistant text instead of being elided, with per-item output capped at 12,000 characters. (#79952) Thanks @scoootscooob.
|
||||
- Memory: close temp SQLite handles before failed atomic reindex cleanup and retry Windows EBUSY/EPERM/EACCES temp file removals, so `memory index --force` does not abort or leave temp sidecars on locked filesystems. Fixes #79708. Thanks @LobsterFarmerAmp and @hclsys.
|
||||
- Agents/CLI: add an explicit `reseedFromRawTranscriptWhenUncompacted` backend opt-in so safe invalidated CLI sessions can reseed from a bounded raw OpenClaw transcript tail before compaction while auth-boundary resets remain no-raw. Fixes #79713. (#79764) Thanks @hclsys.
|
||||
|
||||
@@ -44,7 +44,7 @@ Choose your preferred auth method and follow the setup steps.
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "google/gemini-3.1-pro-preview" },
|
||||
model: { primary: "google/gemini-2.5-flash" },
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
registerSingleProviderPlugin,
|
||||
} from "openclaw/plugin-sdk/plugin-test-runtime";
|
||||
import { afterAll, afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { withEnvAsync } from "../../src/test-utils/env.js";
|
||||
import { setAwsSharedIniFileLoaderForTest } from "./aws-credential-refresh.js";
|
||||
import { resetBedrockDiscoveryCacheForTest } from "./discovery.js";
|
||||
import amazonBedrockPlugin from "./index.js";
|
||||
@@ -338,28 +339,38 @@ describe("amazon-bedrock provider plugin", () => {
|
||||
});
|
||||
|
||||
it("refreshes AWS shared config cache before Bedrock sends", async () => {
|
||||
const order: string[] = [];
|
||||
refreshSharedConfigCache.mockImplementationOnce(async () => {
|
||||
order.push("refresh");
|
||||
});
|
||||
const provider = await registerSingleProviderPlugin(amazonBedrockPlugin);
|
||||
const wrapped = provider.wrapStreamFn?.({
|
||||
provider: "amazon-bedrock",
|
||||
modelId: ANTHROPIC_MODEL,
|
||||
streamFn: spyStreamFn,
|
||||
} as never);
|
||||
const result = wrapped?.(ANTHROPIC_MODEL_DESCRIPTOR, { messages: [] } as never, {
|
||||
onPayload: () => {
|
||||
order.push("original");
|
||||
await withEnvAsync(
|
||||
{
|
||||
AWS_ACCESS_KEY_ID: undefined,
|
||||
AWS_SECRET_ACCESS_KEY: undefined,
|
||||
AWS_BEARER_TOKEN_BEDROCK: undefined,
|
||||
AWS_BEDROCK_SKIP_AUTH: undefined,
|
||||
},
|
||||
}) as Record<string, unknown> | undefined;
|
||||
async () => {
|
||||
const order: string[] = [];
|
||||
refreshSharedConfigCache.mockImplementationOnce(async () => {
|
||||
order.push("refresh");
|
||||
});
|
||||
const provider = await registerSingleProviderPlugin(amazonBedrockPlugin);
|
||||
const wrapped = provider.wrapStreamFn?.({
|
||||
provider: "amazon-bedrock",
|
||||
modelId: ANTHROPIC_MODEL,
|
||||
streamFn: spyStreamFn,
|
||||
} as never);
|
||||
const result = wrapped?.(ANTHROPIC_MODEL_DESCRIPTOR, { messages: [] } as never, {
|
||||
onPayload: () => {
|
||||
order.push("original");
|
||||
},
|
||||
}) as Record<string, unknown> | undefined;
|
||||
|
||||
await (
|
||||
result?.onPayload as ((p: Record<string, unknown>, model: unknown) => unknown) | undefined
|
||||
)?.({}, ANTHROPIC_MODEL_DESCRIPTOR);
|
||||
await (
|
||||
result?.onPayload as ((p: Record<string, unknown>, model: unknown) => unknown) | undefined
|
||||
)?.({}, ANTHROPIC_MODEL_DESCRIPTOR);
|
||||
|
||||
expect(refreshSharedConfigCache).toHaveBeenCalledWith({ ignoreCache: true });
|
||||
expect(order).toEqual(["refresh", "original"]);
|
||||
expect(refreshSharedConfigCache).toHaveBeenCalledWith({ ignoreCache: true });
|
||||
expect(order).toEqual(["refresh", "original"]);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it("omits temperature for Bedrock Opus 4.7 model ids", async () => {
|
||||
|
||||
41
extensions/amazon-bedrock/provider-policy-api.test.ts
Normal file
41
extensions/amazon-bedrock/provider-policy-api.test.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { resolveThinkingProfile } from "./provider-policy-api.js";
|
||||
|
||||
describe("amazon-bedrock provider-policy-api", () => {
|
||||
it("exposes adaptive thinking for Bedrock Claude 4.6 before runtime registration", () => {
|
||||
expect(
|
||||
resolveThinkingProfile({
|
||||
provider: "amazon-bedrock",
|
||||
modelId: "amazon-bedrock/global.anthropic.claude-opus-4-6-v1",
|
||||
}),
|
||||
).toMatchObject({
|
||||
levels: expect.arrayContaining([{ id: "adaptive" }]),
|
||||
defaultLevel: "adaptive",
|
||||
});
|
||||
});
|
||||
|
||||
it("exposes max thinking for Bedrock Claude Opus 4.7 refs", () => {
|
||||
expect(
|
||||
resolveThinkingProfile({
|
||||
provider: "amazon-bedrock",
|
||||
modelId:
|
||||
"arn:aws:bedrock:us-west-2:123456789012:inference-profile/us.anthropic.claude-opus-4-7",
|
||||
})?.levels.map((level) => level.id),
|
||||
).toEqual(["off", "minimal", "low", "medium", "high", "xhigh", "adaptive", "max"]);
|
||||
});
|
||||
|
||||
it.each(["bedrock", "aws-bedrock"])("accepts provider alias %s", (provider) => {
|
||||
expect(
|
||||
resolveThinkingProfile({
|
||||
provider,
|
||||
modelId: "global.anthropic.claude-opus-4-6-v1",
|
||||
})?.levels.map((level) => level.id),
|
||||
).toContain("adaptive");
|
||||
});
|
||||
|
||||
it("ignores unrelated providers", () => {
|
||||
expect(
|
||||
resolveThinkingProfile({ provider: "anthropic", modelId: "claude-opus-4-6" }),
|
||||
).toBeNull();
|
||||
});
|
||||
});
|
||||
9
extensions/amazon-bedrock/provider-policy-api.ts
Normal file
9
extensions/amazon-bedrock/provider-policy-api.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { normalizeProviderId } from "openclaw/plugin-sdk/provider-model-shared";
|
||||
import { resolveBedrockClaudeThinkingProfile } from "./thinking-policy.js";
|
||||
|
||||
export function resolveThinkingProfile(params: { provider: string; modelId: string }) {
|
||||
if (normalizeProviderId(params.provider) !== "amazon-bedrock") {
|
||||
return null;
|
||||
}
|
||||
return resolveBedrockClaudeThinkingProfile(params.modelId);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { StreamFn } from "@mariozechner/pi-agent-core";
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
|
||||
import { resolvePluginConfigObject } from "openclaw/plugin-sdk/plugin-config-runtime";
|
||||
import type { OpenClawPluginApi, ProviderThinkingProfile } from "openclaw/plugin-sdk/plugin-entry";
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
|
||||
import {
|
||||
ANTHROPIC_BY_MODEL_REPLAY_HOOKS,
|
||||
normalizeProviderId,
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
import { refreshAwsSharedConfigCacheForBedrock } from "./aws-credential-refresh.js";
|
||||
import { mergeImplicitBedrockProvider, resolveBedrockConfigApiKey } from "./discovery-shared.js";
|
||||
import { bedrockMemoryEmbeddingProviderAdapter } from "./memory-embedding-adapter.js";
|
||||
import { isOpus47BedrockModelRef, resolveBedrockClaudeThinkingProfile } from "./thinking-policy.js";
|
||||
|
||||
type GuardrailConfig = {
|
||||
guardrailIdentifier: string;
|
||||
@@ -182,12 +183,6 @@ function resolvedModelSupportsCaching(modelArn: string): boolean {
|
||||
return matchesPiAiPromptCachingModelId(modelArn);
|
||||
}
|
||||
|
||||
function isOpus47BedrockModelRef(modelRef: string): boolean {
|
||||
return /(?:^|[/.:])(?:(?:us|eu|ap|apac|au|jp|global)\.)?anthropic\.claude-opus-4[.-]7(?:$|[-.:/])/i.test(
|
||||
modelRef,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the underlying foundation model for an application inference profile
|
||||
* via GetInferenceProfile. Results are cached so we only call the API once per
|
||||
@@ -344,14 +339,6 @@ export function registerAmazonBedrockPlugin(api: OpenClawPluginApi): void {
|
||||
// Keep registration-local constants inside the function so partial module
|
||||
// initialization during test bootstrap cannot trip TDZ reads.
|
||||
const providerId = "amazon-bedrock";
|
||||
const claude46ModelRe = /claude-(?:opus|sonnet)-4(?:\.|-)6(?:$|[-.])/i;
|
||||
const baseClaudeThinkingLevels = [
|
||||
{ id: "off" },
|
||||
{ id: "minimal" },
|
||||
{ id: "low" },
|
||||
{ id: "medium" },
|
||||
{ id: "high" },
|
||||
] as const satisfies ProviderThinkingProfile["levels"];
|
||||
// Match region from bedrock-runtime (Converse API) URLs.
|
||||
// e.g. https://bedrock-runtime.us-east-1.amazonaws.com
|
||||
const bedrockRegionRe = /bedrock-runtime\.([a-z0-9-]+)\.amazonaws\./;
|
||||
@@ -365,23 +352,6 @@ export function registerAmazonBedrockPlugin(api: OpenClawPluginApi): void {
|
||||
const anthropicByModelReplayHooks = ANTHROPIC_BY_MODEL_REPLAY_HOOKS;
|
||||
const startupPluginConfig = (api.pluginConfig ?? {}) as AmazonBedrockPluginConfig;
|
||||
|
||||
function resolveBedrockClaudeThinkingProfile(modelId: string): ProviderThinkingProfile {
|
||||
const trimmed = modelId.trim();
|
||||
if (isOpus47BedrockModelRef(trimmed)) {
|
||||
return {
|
||||
levels: [...baseClaudeThinkingLevels, { id: "xhigh" }, { id: "adaptive" }, { id: "max" }],
|
||||
defaultLevel: "off",
|
||||
};
|
||||
}
|
||||
if (claude46ModelRe.test(trimmed)) {
|
||||
return {
|
||||
levels: [...baseClaudeThinkingLevels, { id: "adaptive" }],
|
||||
defaultLevel: "adaptive",
|
||||
};
|
||||
}
|
||||
return { levels: baseClaudeThinkingLevels };
|
||||
}
|
||||
|
||||
function resolveCurrentPluginConfig(
|
||||
config: OpenClawConfig | undefined,
|
||||
): AmazonBedrockPluginConfig | undefined {
|
||||
|
||||
32
extensions/amazon-bedrock/thinking-policy.ts
Normal file
32
extensions/amazon-bedrock/thinking-policy.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import type { ProviderThinkingProfile } from "openclaw/plugin-sdk/plugin-entry";
|
||||
|
||||
const BASE_CLAUDE_THINKING_LEVELS = [
|
||||
{ id: "off" },
|
||||
{ id: "minimal" },
|
||||
{ id: "low" },
|
||||
{ id: "medium" },
|
||||
{ id: "high" },
|
||||
] as const satisfies ProviderThinkingProfile["levels"];
|
||||
|
||||
export function isOpus47BedrockModelRef(modelRef: string): boolean {
|
||||
return /(?:^|[/.:])(?:(?:us|eu|ap|apac|au|jp|global)\.)?anthropic\.claude-opus-4[.-]7(?:$|[-.:/])/i.test(
|
||||
modelRef,
|
||||
);
|
||||
}
|
||||
|
||||
export function resolveBedrockClaudeThinkingProfile(modelId: string): ProviderThinkingProfile {
|
||||
const trimmed = modelId.trim();
|
||||
if (isOpus47BedrockModelRef(trimmed)) {
|
||||
return {
|
||||
levels: [...BASE_CLAUDE_THINKING_LEVELS, { id: "xhigh" }, { id: "adaptive" }, { id: "max" }],
|
||||
defaultLevel: "off",
|
||||
};
|
||||
}
|
||||
if (/claude-(?:opus|sonnet)-4(?:\.|-)6(?:$|[-.])/i.test(trimmed)) {
|
||||
return {
|
||||
levels: [...BASE_CLAUDE_THINKING_LEVELS, { id: "adaptive" }],
|
||||
defaultLevel: "adaptive",
|
||||
};
|
||||
}
|
||||
return { levels: BASE_CLAUDE_THINKING_LEVELS };
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
type OpenClawConfig,
|
||||
} from "openclaw/plugin-sdk/provider-onboard";
|
||||
|
||||
export const GOOGLE_GEMINI_DEFAULT_MODEL = "google/gemini-3.1-pro-preview";
|
||||
export const GOOGLE_GEMINI_DEFAULT_MODEL = "google/gemini-2.5-flash";
|
||||
|
||||
export function applyGoogleGeminiModelDefault(cfg: OpenClawConfig): {
|
||||
next: OpenClawConfig;
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
|
||||
type DetectZaiEndpoint = typeof import("../plugins/provider-zai-endpoint.js").detectZaiEndpoint;
|
||||
|
||||
const GOOGLE_GEMINI_DEFAULT_MODEL = "google/gemini-3.1-pro-preview";
|
||||
const GOOGLE_GEMINI_DEFAULT_MODEL = "google/gemini-2.5-flash";
|
||||
const ZAI_CODING_GLOBAL_BASE_URL = "https://api.z.ai/api/coding/paas/v4";
|
||||
const ZAI_CODING_CN_BASE_URL = "https://open.bigmodel.cn/api/coding/paas/v4";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user