




























@@ -1,12 +1,14 @@
11import type { AssistantMessage } from "@mariozechner/pi-ai";
22import { describe, expect, it } from "vitest";
3+import { MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE } from "../shared/assistant-error-format.js";
34import {
45BILLING_ERROR_USER_MESSAGE,
56formatBillingErrorMessage,
67formatAssistantErrorText,
78getApiErrorPayloadFingerprint,
89formatRawAssistantErrorForUi,
910isRawApiErrorPayload,
11+sanitizeUserFacingText,
1012} from "./pi-embedded-helpers.js";
1113import { makeAssistantMessageFixture } from "./test-helpers/assistant-message-fixtures.js";
1214@@ -349,6 +351,34 @@ describe("formatAssistantErrorText", () => {
349351"LLM request failed: provider returned an invalid streaming response. Please try again.",
350352);
351353});
354+355+it("sanitizes transport-classified malformed streaming fragments (#59076)", () => {
356+const msg = makeAssistantError(MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE);
357+expect(formatAssistantErrorText(msg)).toBe(
358+"LLM streaming response contained a malformed fragment. Please try again.",
359+);
360+});
361+362+it("does not broadly rewrite non-streaming 'Unexpected token' JSON parse errors", () => {
363+const msg = makeAssistantError("Unexpected token < in JSON at position 0");
364+expect(formatAssistantErrorText(msg)).toBe("Unexpected token < in JSON at position 0");
365+});
366+367+it("does not rewrite non-streaming provider JSON request-validation diagnostics", () => {
368+const msg = makeAssistantError("Expected value in JSON at position 12 for messages.0.content");
369+expect(formatAssistantErrorText(msg)).toBe(
370+"Expected value in JSON at position 12 for messages.0.content",
371+);
372+});
373+374+it("keeps provider request-validation JSON diagnostics actionable", () => {
375+const msg = makeAssistantError(
376+'{"type":"error","error":{"type":"invalid_request_error","message":"Expected value in JSON at position 12 for messages.0.content"}}',
377+);
378+expect(formatAssistantErrorText(msg)).toBe(
379+"LLM request rejected: Expected value in JSON at position 12 for messages.0.content",
380+);
381+});
352382});
353383354384describe("formatRawAssistantErrorForUi", () => {
@@ -424,3 +454,21 @@ describe("raw API error payload helpers", () => {
424454);
425455});
426456});
457+458+describe("sanitizeUserFacingText — streaming JSON parse error (#59076)", () => {
459+it("rewrites transport-classified malformed streaming fragments in error context", () => {
460+const result = sanitizeUserFacingText(MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE, {
461+errorContext: true,
462+});
463+expect(result).toBe("LLM streaming response contained a malformed fragment. Please try again.");
464+});
465+466+it("does not rewrite JSON parse error when not in error context", () => {
467+// When not in error context, the text could be legitimate assistant content
468+// mentioning JSON errors. Don't rewrite.
469+const text =
470+"Expected ',' or '}' after property value in JSON at position 334 (line 1 column 335)";
471+const result = sanitizeUserFacingText(text, { errorContext: false });
472+expect(result).toBe(text);
473+});
474+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。