fix(plugin-sdk): guard provider stream error formatting

This commit is contained in:
Vincent Koc
2026-06-05 11:28:52 +02:00
parent a3f029f385
commit 9db5912e8a
2 changed files with 49 additions and 1 deletions

View File

@@ -199,6 +199,43 @@ describe("createPayloadPatchStreamWrapper", () => {
});
describe("createPlainTextToolCallCompatWrapper", () => {
it("emits sanitized errors when stream normalization sees hostile failures", async () => {
const hostileError = new Error("stream failed");
Object.defineProperty(hostileError, "message", {
get() {
throw new Error("message denied");
},
});
const baseStreamFn: StreamFn = () =>
(async function* () {
yield* [];
throw hostileError;
})() as never;
const wrapped = createPlainTextToolCallCompatWrapper(baseStreamFn);
const events: unknown[] = [];
for await (const event of wrapped(
{} as never,
{ tools: [{ name: "read" }] } as never,
{},
) as AsyncIterable<unknown>) {
events.push(event);
}
expect(events).toEqual([
{
type: "error",
reason: "error",
error: {
role: "assistant",
content: [],
stopReason: "error",
errorMessage: "Unknown provider stream error",
},
},
]);
});
it("promotes standalone text tool calls into tool-call stream events", async () => {
const baseStreamFn: StreamFn = () =>
createEventStream([

View File

@@ -173,6 +173,17 @@ function normalizeProviderDoneMessage(
return promotedMessage ? { kind: "promoted", message: promotedMessage } : undefined;
}
function describeProviderStreamError(error: unknown): string {
try {
if (error instanceof Error) {
return error.message || error.name || "Unknown provider stream error";
}
return String(error);
} catch {
return "Unknown provider stream error";
}
}
function wrapPlainTextToolCallStream(
source: ReturnType<StreamFn>,
context: Parameters<StreamFn>[1],
@@ -220,7 +231,7 @@ function wrapPlainTextToolCallStream(
role: "assistant",
content: [],
stopReason: "error",
errorMessage: error instanceof Error ? error.message : String(error),
errorMessage: describeProviderStreamError(error),
},
});
} finally {