Files
dev/third_party/pi/packages/ai/test/json-parse.test.ts
alexion 6081e3e325 chore(vendor): import pi 1.3.0
Imported as a linear vendor commit so forge rebases do not replay the upstream root tree.

git-subtree-dir: third_party/pi

git-subtree-split: 71023aec1546d6d677a65669c5665c0927ce0dd0
2026-10-15 17:58:48 -04:00

58 lines
2.0 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { parseStreamingJson, parseToolCallArguments } from "../src/utils/json-parse.ts";
describe("parseStreamingJson", () => {
// #10868
it("keeps invalid \\u escapes as literal text without dropping fields", () => {
expect(parseStreamingJson(String.raw`{"text":"\url{x}"}`)).toEqual({ text: "\\url{x}" });
expect(parseStreamingJson(String.raw`{"path":"a.tex","content":"\usepackage{x}","mode":"w"}`)).toEqual({
path: "a.tex",
content: "\\usepackage{x}",
mode: "w",
});
});
it("decodes valid \\u escapes", () => {
expect(parseStreamingJson(String.raw`{"text":"caf\u00e9 \url"}`)).toEqual({ text: "café \\url" });
});
it("omits a \\u escape that is cut off mid-stream", () => {
expect(parseStreamingJson(String.raw`{"text":"ab\u00`)).toEqual({ text: "ab" });
});
});
// #10897
describe("parseToolCallArguments", () => {
it("parses complete JSON and repairs invalid escapes", () => {
expect(parseToolCallArguments(String.raw`{"kind":"seek","note":"\url"}`)).toEqual({
arguments: { kind: "seek", note: "\\url" },
});
});
it("uses empty arguments for empty text", () => {
expect(parseToolCallArguments("")).toEqual({ arguments: {} });
});
it("does not keep the valid prefix of malformed JSON", () => {
const raw = '{"action":"apply","actions":[{"kind":"seek","time":.5}]}';
const result = parseToolCallArguments(raw);
expect(result.arguments).toEqual({});
expect(result.argumentsError).toMatch(/\n\nReceived arguments:\n/);
expect(result.argumentsError?.endsWith(raw)).toBe(true);
});
it("does not complete cut-off JSON", () => {
const raw = '{"kind":"seek","clipId":"clip-fl';
const result = parseToolCallArguments(raw);
expect(result.arguments).toEqual({});
expect(result.argumentsError?.endsWith(raw)).toBe(true);
});
it("rejects JSON that is not an object", () => {
expect(parseToolCallArguments("[1,2]")).toEqual({
arguments: {},
argumentsError: "Tool arguments must be a JSON object\n\nReceived arguments:\n[1,2]",
});
});
});