style: format stale source files

This commit is contained in:
Peter Steinberger
2026-04-23 02:14:29 +01:00
parent 0ada97d513
commit de95e414d1
9 changed files with 97 additions and 101 deletions

View File

@@ -24,9 +24,9 @@ describe("amazon-bedrock-mantle provider plugin", () => {
expect(
provider.classifyFailoverReason?.({ errorMessage: "some other error" } as never),
).toBeUndefined();
expect(
provider.classifyFailoverReason?.({ errorMessage: "overloaded_error" } as never),
).toBe("overloaded");
expect(provider.classifyFailoverReason?.({ errorMessage: "overloaded_error" } as never)).toBe(
"overloaded",
);
});
it("provides a custom stream only for Mantle Anthropic models", async () => {

View File

@@ -1,11 +1,11 @@
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
import { createMantleAnthropicStreamFn } from "./mantle-anthropic.runtime.js";
import {
mergeImplicitMantleProvider,
resolveImplicitMantleProvider,
resolveMantleBearerToken,
resolveMantleRuntimeBearerToken,
} from "./discovery.js";
import { createMantleAnthropicStreamFn } from "./mantle-anthropic.runtime.js";
export function registerBedrockMantlePlugin(api: OpenClawPluginApi): void {
const providerId = "amazon-bedrock-mantle";

View File

@@ -132,7 +132,8 @@ describe("bedrock discovery", () => {
type: "SYSTEM_DEFINED",
models: [
{
modelArn: "arn:aws:bedrock:ap-northeast-1::foundation-model/example.unknown-text-v1:0",
modelArn:
"arn:aws:bedrock:ap-northeast-1::foundation-model/example.unknown-text-v1:0",
},
],
},

View File

@@ -395,9 +395,10 @@ function resolveInferenceProfiles(
reasoning: baseModel?.reasoning ?? false,
input: baseModel?.input ?? ["text"],
cost: baseModel?.cost ?? DEFAULT_COST,
contextWindow: baseModel?.contextWindow
?? resolveKnownContextWindow(baseModelId ?? profile.inferenceProfileId ?? "")
?? defaults.contextWindow,
contextWindow:
baseModel?.contextWindow ??
resolveKnownContextWindow(baseModelId ?? profile.inferenceProfileId ?? "") ??
defaults.contextWindow,
maxTokens: baseModel?.maxTokens ?? defaults.maxTokens,
});
}

View File

@@ -7,9 +7,7 @@ import type { PluginRuntime } from "../../src/plugins/runtime/types.js";
import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js";
import amazonBedrockPlugin from "./index.js";
type InferenceProfileResult =
| { models?: Array<{ modelArn?: string }> }
| Error;
type InferenceProfileResult = { models?: Array<{ modelArn?: string }> } | Error;
const inferenceProfileResults: InferenceProfileResult[] = [];
const bedrockClientConfigs: Array<Record<string, unknown>> = [];
@@ -376,10 +374,11 @@ describe("amazon-bedrock provider plugin", () => {
streamFn: spyStreamFn,
} as never);
const result = wrapped?.(modelDescriptor, { messages: [] } as never, options) as unknown as Record<
string,
unknown
>;
const result = wrapped?.(
modelDescriptor,
{ messages: [] } as never,
options,
) as unknown as Record<string, unknown>;
if (typeof result?.onPayload === "function") {
await (
@@ -393,9 +392,7 @@ describe("amazon-bedrock provider plugin", () => {
const provider = await registerWithConfig(undefined);
const payload: Record<string, unknown> = {
system: [{ text: "You are helpful." }],
messages: [
{ role: "user", content: [{ text: "Hello" }] },
],
messages: [{ role: "user", content: [{ text: "Hello" }] }],
};
await callWrappedStreamWithPayload(
@@ -410,7 +407,10 @@ describe("amazon-bedrock provider plugin", () => {
expect(system).toHaveLength(2);
expect(system[1]).toEqual({ cachePoint: { type: "default" } });
const messages = payload.messages as Array<{ role: string; content: Array<Record<string, unknown>> }>;
const messages = payload.messages as Array<{
role: string;
content: Array<Record<string, unknown>>;
}>;
const lastUserContent = messages[0].content;
expect(lastUserContent).toHaveLength(2);
expect(lastUserContent[1]).toEqual({ cachePoint: { type: "default" } });
@@ -420,9 +420,7 @@ describe("amazon-bedrock provider plugin", () => {
const provider = await registerWithConfig(undefined);
const payload: Record<string, unknown> = {
system: [{ text: "You are helpful." }],
messages: [
{ role: "user", content: [{ text: "Hello" }] },
],
messages: [{ role: "user", content: [{ text: "Hello" }] }],
};
await callWrappedStreamWithPayload(
@@ -441,9 +439,7 @@ describe("amazon-bedrock provider plugin", () => {
const provider = await registerWithConfig(undefined);
const payload: Record<string, unknown> = {
system: [{ text: "You are helpful." }],
messages: [
{ role: "user", content: [{ text: "Hello" }] },
],
messages: [{ role: "user", content: [{ text: "Hello" }] }],
};
await callWrappedStreamWithPayload(
@@ -478,7 +474,10 @@ describe("amazon-bedrock provider plugin", () => {
const system = payload.system as Array<Record<string, unknown>>;
expect(system).toHaveLength(2);
const messages = payload.messages as Array<{ role: string; content: Array<Record<string, unknown>> }>;
const messages = payload.messages as Array<{
role: string;
content: Array<Record<string, unknown>>;
}>;
expect(messages[0].content).toHaveLength(2);
});
@@ -486,9 +485,7 @@ describe("amazon-bedrock provider plugin", () => {
const provider = await registerWithConfig(undefined);
const payload: Record<string, unknown> = {
system: [{ text: "You are helpful." }],
messages: [
{ role: "user", content: [{ text: "Hello" }] },
],
messages: [{ role: "user", content: [{ text: "Hello" }] }],
};
// Regular model IDs contain "claude" so pi-ai handles caching natively.
@@ -517,9 +514,7 @@ describe("amazon-bedrock provider plugin", () => {
const oldClaudeModel = "anthropic.claude-3-opus-20240229-v1:0";
const payload: Record<string, unknown> = {
system: [{ text: "You are helpful." }],
messages: [
{ role: "user", content: [{ text: "Hello" }] },
],
messages: [{ role: "user", content: [{ text: "Hello" }] }],
};
// Claude 3 Opus is not in pi-ai's supportsPromptCaching list, but it's
@@ -546,9 +541,7 @@ describe("amazon-bedrock provider plugin", () => {
const provider = await registerWithConfig(undefined);
const payload: Record<string, unknown> = {
system: [{ text: "You are helpful." }],
messages: [
{ role: "user", content: [{ text: "Hello" }] },
],
messages: [{ role: "user", content: [{ text: "Hello" }] }],
};
await callWrappedStreamWithPayload(
@@ -584,7 +577,10 @@ describe("amazon-bedrock provider plugin", () => {
payload,
);
const messages = payload.messages as Array<{ role: string; content: Array<Record<string, unknown>> }>;
const messages = payload.messages as Array<{
role: string;
content: Array<Record<string, unknown>>;
}>;
// First user message should NOT have a cache point
expect(messages[0].content).toHaveLength(1);
// Assistant message untouched
@@ -661,17 +657,14 @@ describe("amazon-bedrock provider plugin", () => {
it("retries opaque profile lookup after a transient failure instead of caching the fallback", async () => {
const modelId =
"arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/z27qyso459dc";
inferenceProfileResults.push(
new Error("throttled"),
{
models: [
{
modelArn:
"arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-sonnet-4-6-20250514-v1:0",
},
],
},
);
inferenceProfileResults.push(new Error("throttled"), {
models: [
{
modelArn:
"arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-sonnet-4-6-20250514-v1:0",
},
],
});
const provider = await registerWithConfig(undefined);
const firstPayload: Record<string, unknown> = {
system: [{ text: "You are helpful." }],

View File

@@ -96,7 +96,8 @@ function piAiWouldInjectCachePoints(modelId: string): boolean {
* System-defined profiles (us., eu., global.) and base model IDs always
* contain the model name and are handled by pi-ai natively.
*/
const BEDROCK_APP_INFERENCE_PROFILE_RE = /^arn:aws(-cn|-us-gov)?:bedrock:.*:application-inference-profile\//i;
const BEDROCK_APP_INFERENCE_PROFILE_RE =
/^arn:aws(-cn|-us-gov)?:bedrock:.*:application-inference-profile\//i;
function isBedrockAppInferenceProfile(modelId: string): boolean {
return BEDROCK_APP_INFERENCE_PROFILE_RE.test(modelId);
@@ -172,9 +173,7 @@ async function resolveAppProfileCacheEligible(
const models = resp.models ?? [];
const eligible =
models.length > 0 &&
models.every((m: { modelArn?: string }) =>
resolvedModelSupportsCaching(m.modelArn ?? ""),
);
models.every((m: { modelArn?: string }) => resolvedModelSupportsCaching(m.modelArn ?? ""));
appProfileCacheEligibleCache.set(modelId, eligible);
return eligible;
} catch {
@@ -374,9 +373,8 @@ export function registerAmazonBedrockPlugin(api: OpenClawPluginApi): void {
// to also teach resolveAnthropicCacheRetentionFamily about opaque profiles
// (tracked separately). In practice, users with app inference profiles
// want caching enabled, so defaulting to "short" is the safer behavior.
const cacheRetention = typeof merged.cacheRetention === "string"
? merged.cacheRetention
: "short";
const cacheRetention =
typeof merged.cacheRetention === "string" ? merged.cacheRetention : "short";
if (heuristicMatch) {
// Fast path: ARN heuristic already identified this as Claude.

View File

@@ -382,7 +382,9 @@ describe("openshell fs bridges", () => {
const { createOpenShellFsBridge } = await import("./fs-bridge.js");
const bridge = createOpenShellFsBridge({ sandbox, backend });
const readlinkSpy = vi.spyOn(fs, "readlink").mockRejectedValue(new Error("fd path unavailable"));
const readlinkSpy = vi
.spyOn(fs, "readlink")
.mockRejectedValue(new Error("fd path unavailable"));
try {
await expect(bridge.readFile({ filePath: "subdir/secret.txt" })).resolves.toEqual(
@@ -401,43 +403,45 @@ describe("openshell fs bridges", () => {
it.skipIf(process.platform === "win32")(
"rejects fallback reads when path stats report an unknown device id",
async () => {
const workspaceDir = await makeTempDir("openclaw-openshell-fs-");
const targetPath = path.join(workspaceDir, "subdir", "secret.txt");
await fs.mkdir(path.join(workspaceDir, "subdir"), { recursive: true });
await fs.writeFile(targetPath, "inside", "utf8");
const workspaceDir = await makeTempDir("openclaw-openshell-fs-");
const targetPath = path.join(workspaceDir, "subdir", "secret.txt");
await fs.mkdir(path.join(workspaceDir, "subdir"), { recursive: true });
await fs.writeFile(targetPath, "inside", "utf8");
const backend = createMirrorBackendMock();
const sandbox = createSandboxTestContext({
overrides: {
backendId: "openshell",
workspaceDir,
agentWorkspaceDir: workspaceDir,
containerWorkdir: "/sandbox",
},
});
const backend = createMirrorBackendMock();
const sandbox = createSandboxTestContext({
overrides: {
backendId: "openshell",
workspaceDir,
agentWorkspaceDir: workspaceDir,
containerWorkdir: "/sandbox",
},
});
const { createOpenShellFsBridge } = await import("./fs-bridge.js");
const bridge = createOpenShellFsBridge({ sandbox, backend });
const readlinkSpy = vi.spyOn(fs, "readlink").mockRejectedValue(new Error("fd path unavailable"));
const originalStat = fs.stat.bind(fs);
const statSpy = vi.spyOn(fs, "stat").mockImplementation(async (...args) => {
const stat = await originalStat(...args);
if (args[0] === targetPath) {
return cloneStatWithDev(stat, 0);
const { createOpenShellFsBridge } = await import("./fs-bridge.js");
const bridge = createOpenShellFsBridge({ sandbox, backend });
const readlinkSpy = vi
.spyOn(fs, "readlink")
.mockRejectedValue(new Error("fd path unavailable"));
const originalStat = fs.stat.bind(fs);
const statSpy = vi.spyOn(fs, "stat").mockImplementation(async (...args) => {
const stat = await originalStat(...args);
if (args[0] === targetPath) {
return cloneStatWithDev(stat, 0);
}
return stat;
});
try {
await expect(bridge.readFile({ filePath: "subdir/secret.txt" })).rejects.toThrow(
"Sandbox boundary checks failed",
);
expect(readlinkSpy).toHaveBeenCalled();
expect(statSpy).toHaveBeenCalledWith(targetPath);
} finally {
statSpy.mockRestore();
readlinkSpy.mockRestore();
}
return stat;
});
try {
await expect(bridge.readFile({ filePath: "subdir/secret.txt" })).rejects.toThrow(
"Sandbox boundary checks failed",
);
expect(readlinkSpy).toHaveBeenCalled();
expect(statSpy).toHaveBeenCalledWith(targetPath);
} finally {
statSpy.mockRestore();
readlinkSpy.mockRestore();
}
},
);
@@ -474,7 +478,9 @@ describe("openshell fs bridges", () => {
}) as unknown as typeof fs.open);
// Force the fallback verification path even on Linux so the ancestor-walk
// guard is exercised directly.
const readlinkSpy = vi.spyOn(fs, "readlink").mockRejectedValue(new Error("fd path unavailable"));
const readlinkSpy = vi
.spyOn(fs, "readlink")
.mockRejectedValue(new Error("fd path unavailable"));
try {
await expect(bridge.readFile({ filePath: "subdir/secret.txt" })).rejects.toThrow(
@@ -512,12 +518,13 @@ describe("openshell fs bridges", () => {
},
});
const { createOpenShellFsBridge, setReadOpenFlagsResolverForTest } = await import(
"./fs-bridge.js"
);
const { createOpenShellFsBridge, setReadOpenFlagsResolverForTest } =
await import("./fs-bridge.js");
const bridge = createOpenShellFsBridge({ sandbox, backend });
// Force the fallback path so the leaf-lstat guard is exercised.
const readlinkSpy = vi.spyOn(fs, "readlink").mockRejectedValue(new Error("fd path unavailable"));
const readlinkSpy = vi
.spyOn(fs, "readlink")
.mockRejectedValue(new Error("fd path unavailable"));
// Simulate a host that lacks `O_NOFOLLOW` (e.g. Windows) without touching
// the non-configurable native `fs.constants` data property. The bridge
// exposes a test-only seam for exactly this case.

View File

@@ -89,12 +89,8 @@ export function resolveAnthropicCacheRetentionFamily(params: {
// cacheRetention, honor it — the extension's GetInferenceProfile resolution
// handles the actual model detection at runtime.
if (
BEDROCK_APP_INFERENCE_PROFILE_ARN_RE.test(
normalizeLowercaseStringOrEmpty(params.modelId),
) &&
normalizeLowercaseStringOrEmpty(params.modelId).includes(
":application-inference-profile/",
)
BEDROCK_APP_INFERENCE_PROFILE_ARN_RE.test(normalizeLowercaseStringOrEmpty(params.modelId)) &&
normalizeLowercaseStringOrEmpty(params.modelId).includes(":application-inference-profile/")
) {
return "anthropic-bedrock";
}

View File

@@ -1,6 +1,7 @@
import { complete, type Api, type Model } from "@mariozechner/pi-ai";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { formatErrorMessage } from "../infra/errors.js";
import { prepareProviderRuntimeAuth } from "../plugins/provider-runtime.runtime.js";
import { resolveAgentDir, resolveAgentEffectiveModelPrimary } from "./agent-scope.js";
import { DEFAULT_PROVIDER } from "./defaults.js";
import {
@@ -15,7 +16,6 @@ import {
resolveModelRefFromString,
} from "./model-selection.js";
import { resolveModel } from "./pi-embedded-runner/model.js";
import { prepareProviderRuntimeAuth } from "../plugins/provider-runtime.runtime.js";
type SimpleCompletionAuthStorage = {
setRuntimeApiKey: (provider: string, apiKey: string) => void;