



















@@ -209,6 +209,55 @@ function runtimePluginConfig(config?: Record<string, unknown>): OpenClawConfig {
209209} as OpenClawConfig;
210210}
211211212+function requireRecord(value: unknown, label: string): Record<string, unknown> {
213+if (!value || typeof value !== "object" || Array.isArray(value)) {
214+throw new Error(`expected ${label} to be a record`);
215+}
216+return value as Record<string, unknown>;
217+}
218+219+function requireArray(value: unknown, label: string): unknown[] {
220+if (!Array.isArray(value)) {
221+throw new Error(`expected ${label} to be an array`);
222+}
223+return value;
224+}
225+226+function expectRecordFields(record: Record<string, unknown>, fields: Record<string, unknown>) {
227+for (const [key, value] of Object.entries(fields)) {
228+expect(record[key]).toEqual(value);
229+}
230+}
231+232+function expectWrappedResultFields(result: unknown, fields: Record<string, unknown>) {
233+expectRecordFields(requireRecord(result, "wrapped stream result"), fields);
234+}
235+236+function expectPayloadServiceTier(result: Record<string, unknown>, type: string) {
237+expectRecordFields(requireRecord(result._capturedPayload, "captured payload"), {
238+serviceTier: { type },
239+});
240+}
241+242+function expectThinkingProfile(
243+profile: unknown,
244+fields: { defaultLevel?: string; levelIds?: string[]; includesAdaptive?: boolean },
245+) {
246+const record = requireRecord(profile, "thinking profile");
247+if (fields.defaultLevel !== undefined) {
248+expect(record.defaultLevel).toBe(fields.defaultLevel);
249+}
250+const levelIds = requireArray(record.levels, "thinking levels").map((level) =>
251+String(requireRecord(level, "thinking level").id),
252+);
253+if (fields.levelIds) {
254+expect(levelIds).toEqual(fields.levelIds);
255+}
256+if (fields.includesAdaptive !== undefined) {
257+expect(levelIds.includes("adaptive")).toBe(fields.includesAdaptive);
258+}
259+}
260+212261describe("amazon-bedrock provider plugin", () => {
213262beforeEach(() => {
214263foundationModelResults.length = 0;
@@ -246,23 +295,20 @@ describe("amazon-bedrock provider plugin", () => {
246295it("marks Claude 4.6 Bedrock models as adaptive by default", async () => {
247296const provider = await registerSingleProviderPlugin(amazonBedrockPlugin);
248297249-expect(
298+expectThinkingProfile(
250299provider.resolveThinkingProfile?.({
251300provider: "amazon-bedrock",
252301modelId: "us.anthropic.claude-opus-4-6-v1",
253302} as never),
254-).toMatchObject({
255-levels: expect.arrayContaining([{ id: "adaptive" }]),
256-defaultLevel: "adaptive",
257-});
258-expect(
303+{ includesAdaptive: true, defaultLevel: "adaptive" },
304+);
305+expectThinkingProfile(
259306provider.resolveThinkingProfile?.({
260307provider: "amazon-bedrock",
261308modelId: "amazon.nova-micro-v1:0",
262309} as never),
263-).toMatchObject({
264-levels: expect.not.arrayContaining([{ id: "adaptive" }]),
265-});
310+{ includesAdaptive: false },
311+);
266312});
267313268314it("mirrors Claude Opus 4.7 thinking levels for Bedrock model refs", async () => {
@@ -274,24 +320,16 @@ describe("amazon-bedrock provider plugin", () => {
274320"eu.anthropic.claude-opus-4-7",
275321"arn:aws:bedrock:us-west-2:123456789012:inference-profile/us.anthropic.claude-opus-4-7",
276322]) {
277-expect(
323+expectThinkingProfile(
278324provider.resolveThinkingProfile?.({
279325provider: "amazon-bedrock",
280326 modelId,
281327} as never),
282-).toMatchObject({
283-levels: [
284-{ id: "off" },
285-{ id: "minimal" },
286-{ id: "low" },
287-{ id: "medium" },
288-{ id: "high" },
289-{ id: "xhigh" },
290-{ id: "adaptive" },
291-{ id: "max" },
292-],
293-defaultLevel: "off",
294-});
328+{
329+levelIds: ["off", "minimal", "low", "medium", "high", "xhigh", "adaptive", "max"],
330+defaultLevel: "off",
331+},
332+);
295333}
296334});
297335@@ -323,7 +361,7 @@ describe("amazon-bedrock provider plugin", () => {
323361streamFn: (_model: unknown, _context: unknown, options: Record<string, unknown>) => options,
324362} as never);
325363326-expect(
364+expectWrappedResultFields(
327365wrapped?.(
328366{
329367api: "openai-completions",
@@ -333,9 +371,8 @@ describe("amazon-bedrock provider plugin", () => {
333371{ messages: [] } as never,
334372{},
335373),
336-).toMatchObject({
337-cacheRetention: "none",
338-});
374+{ cacheRetention: "none" },
375+);
339376});
340377341378it("refreshes AWS shared config cache before Bedrock sends", async () => {
@@ -391,7 +428,7 @@ describe("amazon-bedrock provider plugin", () => {
391428{ temperature: 0.2, maxTokens: 10 },
392429) as Record<string, unknown> | undefined;
393430394-expect(result).toMatchObject({ maxTokens: 10 });
431+expectWrappedResultFields(result, { maxTokens: 10 });
395432expect(result).not.toHaveProperty("temperature");
396433});
397434@@ -413,7 +450,7 @@ describe("amazon-bedrock provider plugin", () => {
413450{ temperature: 0.2, maxTokens: 10 },
414451) as Record<string, unknown> | undefined;
415452416-expect(result).toMatchObject({ maxTokens: 10 });
453+expectWrappedResultFields(result, { maxTokens: 10 });
417454expect(result).not.toHaveProperty("temperature");
418455});
419456@@ -437,7 +474,7 @@ describe("amazon-bedrock provider plugin", () => {
437474{ temperature: 0, region: "us-west-2" } as never,
438475) as Record<string, unknown> | undefined;
439476440-expect(result).toMatchObject({ region: "us-west-2" });
477+expectWrappedResultFields(result, { region: "us-west-2" });
441478expect(result).not.toHaveProperty("temperature");
442479});
443480@@ -459,7 +496,7 @@ describe("amazon-bedrock provider plugin", () => {
459496{ temperature: 0.4, maxTokens: 12 },
460497) as Record<string, unknown> | undefined;
461498462-expect(result).toMatchObject({ maxTokens: 12 });
499+expectWrappedResultFields(result, { maxTokens: 12 });
463500expect(result).not.toHaveProperty("temperature");
464501});
465502@@ -544,7 +581,7 @@ describe("amazon-bedrock provider plugin", () => {
544581const discovery = pluginJson.configSchema?.properties?.discovery;
545582const guardrail = pluginJson.configSchema?.properties?.guardrail;
546583547-expect(discovery).toMatchObject({
584+expectRecordFields(requireRecord(discovery, "discovery schema"), {
548585type: "object",
549586additionalProperties: false,
550587});
@@ -567,7 +604,7 @@ describe("amazon-bedrock provider plugin", () => {
567604minimum: 1,
568605});
569606570-expect(guardrail).toMatchObject({
607+expectRecordFields(requireRecord(guardrail, "guardrail schema"), {
571608type: "object",
572609additionalProperties: false,
573610});
@@ -598,7 +635,7 @@ describe("amazon-bedrock provider plugin", () => {
598635599636expect(result).not.toHaveProperty("_capturedPayload");
600637// The onPayload hook should not exist when no guardrail is configured
601-expect(result).toMatchObject({ cacheRetention: "none" });
638+expectWrappedResultFields(result, { cacheRetention: "none" });
602639});
603640604641it("injects all four fields when guardrail config includes optional fields", async () => {
@@ -680,7 +717,7 @@ describe("amazon-bedrock provider plugin", () => {
680717},
681718});
682719// Non-Anthropic models should also get cacheRetention: "none"
683-expect(result).toMatchObject({ cacheRetention: "none" });
720+expectWrappedResultFields(result, { cacheRetention: "none" });
684721});
685722686723it("uses live plugin config to inject guardrailConfig after startup disable", async () => {
@@ -720,7 +757,7 @@ describe("amazon-bedrock provider plugin", () => {
720757);
721758722759expect(result).not.toHaveProperty("_capturedPayload");
723-expect(result).toMatchObject({ cacheRetention: "none" });
760+expectWrappedResultFields(result, { cacheRetention: "none" });
724761});
725762});
726763@@ -740,7 +777,7 @@ describe("amazon-bedrock provider plugin", () => {
740777runtimePluginConfig(undefined),
741778{ serviceTier: "flex" },
742779);
743-expect(result._capturedPayload).toMatchObject({ serviceTier: { type: "flex" } });
780+expectPayloadServiceTier(result, "flex");
744781});
745782746783it("injects serviceTier for valid snake_case value ('priority')", async () => {
@@ -752,7 +789,7 @@ describe("amazon-bedrock provider plugin", () => {
752789runtimePluginConfig(undefined),
753790{ service_tier: "priority" },
754791);
755-expect(result._capturedPayload).toMatchObject({ serviceTier: { type: "priority" } });
792+expectPayloadServiceTier(result, "priority");
756793});
757794758795it("injects serviceTier for all valid tier names", async () => {
@@ -765,7 +802,7 @@ describe("amazon-bedrock provider plugin", () => {
765802runtimePluginConfig(undefined),
766803{ serviceTier: tier },
767804);
768-expect(result._capturedPayload).toMatchObject({ serviceTier: { type: tier } });
805+expectPayloadServiceTier(result, tier);
769806}
770807});
771808@@ -791,7 +828,7 @@ describe("amazon-bedrock provider plugin", () => {
791828{ serviceTier: "flex" },
792829{ serviceTier: { type: "priority" } },
793830);
794-expect(result._capturedPayload).toMatchObject({ serviceTier: { type: "priority" } });
831+expectPayloadServiceTier(result, "priority");
795832});
796833797834it("skips injection for non-converse API models", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。