singularity-forge/packages/pi-ai/src/utils/json-parse.ts
ace-pm f92ee8d64c
Rename @sf-run/* → @singularity-forge/* package scope
- All 373 source files updated
- Package.json scopes in all workspace packages
- Loader workspace symlink dir updated
- RpcClient import unified from pi-coding-agent (fixes type mismatch)
- Scripts, configs, flake.nix updated
- Workspace symlinks rebuilt
2026-04-15 22:56:33 +02:00

51 lines
1.7 KiB
TypeScript

import { parseStreamingJson as nativeParseStreamingJson } from "@singularity-forge/native";
import { hasXmlParameterTags, hasYamlBulletLists, repairToolJson } from "./repair-tool-json.js";
/**
* Attempts to parse potentially incomplete JSON during streaming.
* Always returns a valid object, even if the JSON is incomplete.
*
* Uses the native Rust streaming JSON parser for performance.
* Falls back to YAML bullet-list repair when the native parser
* returns an empty object from input that contains YAML-style
* bullet lists copied from template formatting (#2660).
*
* @param partialJson The partial JSON string from streaming
* @returns Parsed object or empty object if parsing fails
*/
export function parseStreamingJson<T = any>(partialJson: string | undefined): T {
if (!partialJson || partialJson.trim() === "") {
return {} as T;
}
// Fast path: try native streaming parser first
const result = nativeParseStreamingJson<T>(partialJson);
// XML parameter tags can be trapped inside otherwise valid JSON strings,
// so run repair before trusting the native parse result.
if (hasXmlParameterTags(partialJson)) {
try {
return JSON.parse(repairToolJson(partialJson)) as T;
} catch {
// Fall through to the native parser result on incomplete partials
}
}
// If the native parser returned a non-empty result, use it.
// Only attempt repair when the result is empty AND the input
// contains YAML bullet patterns (avoids unnecessary work).
if (
result &&
typeof result === "object" &&
Object.keys(result as object).length === 0 &&
hasYamlBulletLists(partialJson)
) {
try {
return JSON.parse(repairToolJson(partialJson)) as T;
} catch {
// Repair failed — return the empty object from native parser
}
}
return result;
}