mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-07 11:20:42 +00:00
* fix(agents): prevent Bedrock replay death loop on empty assistant content Fixes #71572 * docs: document Bedrock replay repair (#71627) (thanks @openperf) * fix(diagnostics): share diagnostic event state across sdk graphs --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
45 lines
1.8 KiB
TypeScript
45 lines
1.8 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
STREAM_ERROR_FALLBACK_TEXT,
|
|
buildStreamErrorAssistantMessage,
|
|
} from "./stream-message-shared.js";
|
|
|
|
const model = {
|
|
api: "bedrock-converse-stream",
|
|
provider: "amazon-bedrock",
|
|
id: "anthropic.claude-3-haiku-20240307-v1:0",
|
|
};
|
|
|
|
describe("buildStreamErrorAssistantMessage", () => {
|
|
it("never returns an empty content array", () => {
|
|
const message = buildStreamErrorAssistantMessage({
|
|
model,
|
|
errorMessage: "stream aborted by upstream host=internal.example.com",
|
|
});
|
|
expect(Array.isArray(message.content)).toBe(true);
|
|
expect(message.content.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it("places only the sentinel in content and never echoes the raw error text", () => {
|
|
const message = buildStreamErrorAssistantMessage({
|
|
model,
|
|
errorMessage: "stream aborted by upstream host=internal.example.com",
|
|
});
|
|
// Replay-visible content must be the canonical sentinel — replaying raw
|
|
// provider error strings could leak hostnames/metadata to the model and
|
|
// turn them into a prompt-injection surface.
|
|
expect(message.content).toEqual([{ type: "text", text: STREAM_ERROR_FALLBACK_TEXT }]);
|
|
expect(JSON.stringify(message.content)).not.toContain("internal.example.com");
|
|
// The detailed error remains available in the peer field for clients/UIs.
|
|
expect(message.errorMessage).toBe("stream aborted by upstream host=internal.example.com");
|
|
expect(message.stopReason).toBe("error");
|
|
});
|
|
|
|
it("uses the same sentinel when errorMessage is blank", () => {
|
|
const message = buildStreamErrorAssistantMessage({ model, errorMessage: " " });
|
|
expect(message.content).toEqual([{ type: "text", text: STREAM_ERROR_FALLBACK_TEXT }]);
|
|
// Original errorMessage is preserved verbatim for clients that surface it.
|
|
expect(message.errorMessage).toBe(" ");
|
|
});
|
|
});
|