@ai2070/l0
Version:
L0: The Missing Reliability Substrate for AI
267 lines • 6.94 kB
JavaScript
export function repairJson(json) {
if (!json || json.trim().length === 0) {
return json;
}
let repaired = json.trim();
repaired = balanceBraces(repaired);
repaired = balanceBrackets(repaired);
repaired = removeTrailingCommas(repaired);
repaired = fixUnclosedStrings(repaired);
return repaired;
}
export function balanceBraces(json) {
if (!json)
return json;
let openCount = 0;
let closeCount = 0;
let inString = false;
let escapeNext = false;
for (let i = 0; i < json.length; i++) {
const char = json[i];
if (escapeNext) {
escapeNext = false;
continue;
}
if (char === "\\") {
escapeNext = true;
continue;
}
if (char === '"') {
inString = !inString;
continue;
}
if (!inString) {
if (char === "{")
openCount++;
if (char === "}")
closeCount++;
}
}
if (openCount > closeCount) {
return json + "}".repeat(openCount - closeCount);
}
if (closeCount > openCount) {
let result = json;
let toRemove = closeCount - openCount;
for (let i = result.length - 1; i >= 0 && toRemove > 0; i--) {
if (result[i] === "}") {
result = result.slice(0, i) + result.slice(i + 1);
toRemove--;
}
}
return result;
}
return json;
}
export function balanceBrackets(json) {
if (!json)
return json;
let openCount = 0;
let closeCount = 0;
let inString = false;
let escapeNext = false;
for (let i = 0; i < json.length; i++) {
const char = json[i];
if (escapeNext) {
escapeNext = false;
continue;
}
if (char === "\\") {
escapeNext = true;
continue;
}
if (char === '"') {
inString = !inString;
continue;
}
if (!inString) {
if (char === "[")
openCount++;
if (char === "]")
closeCount++;
}
}
if (openCount > closeCount) {
return json + "]".repeat(openCount - closeCount);
}
if (closeCount > openCount) {
let result = json;
let toRemove = closeCount - openCount;
for (let i = result.length - 1; i >= 0 && toRemove > 0; i--) {
if (result[i] === "]") {
result = result.slice(0, i) + result.slice(i + 1);
toRemove--;
}
}
return result;
}
return json;
}
export function removeTrailingCommas(json) {
if (!json)
return json;
return json.replace(/,(\s*})/g, "$1").replace(/,(\s*])/g, "$1");
}
export function fixUnclosedStrings(json) {
if (!json)
return json;
let quoteCount = 0;
let escapeNext = false;
for (let i = 0; i < json.length; i++) {
const char = json[i];
if (escapeNext) {
escapeNext = false;
continue;
}
if (char === "\\") {
escapeNext = true;
continue;
}
if (char === '"') {
quoteCount++;
}
}
if (quoteCount % 2 !== 0) {
return json + '"';
}
return json;
}
export function repairMarkdownFences(markdown) {
if (!markdown)
return markdown;
const fencePattern = /```/g;
const matches = markdown.match(fencePattern);
if (!matches)
return markdown;
if (matches.length % 2 !== 0) {
return markdown + "\n```";
}
return markdown;
}
export function repairLatexEnvironments(latex) {
if (!latex)
return latex;
const beginPattern = /\\begin\{(\w+)\}/g;
const endPattern = /\\end\{(\w+)\}/g;
const begins = Array.from(latex.matchAll(beginPattern));
const ends = Array.from(latex.matchAll(endPattern));
const stack = [];
for (const begin of begins) {
stack.push(begin[1]);
}
for (const end of ends) {
const env = end[1];
const lastIndex = stack.lastIndexOf(env);
if (lastIndex !== -1) {
stack.splice(lastIndex, 1);
}
}
let result = latex;
for (const env of stack.reverse()) {
result += `\n\\end{${env}}`;
}
return result;
}
export function repairToolCallArguments(args) {
if (!args)
return args;
let repaired = args.trim();
if (!repaired.startsWith("{") && !repaired.startsWith("[")) {
repaired = "{" + repaired;
}
repaired = repairJson(repaired);
return repaired;
}
export function isValidJson(json) {
if (!json || json.trim().length === 0) {
return false;
}
try {
JSON.parse(json);
return true;
}
catch {
return false;
}
}
export function parseOrRepairJson(json) {
if (!json)
return null;
try {
return JSON.parse(json);
}
catch {
const repaired = repairJson(json);
try {
return JSON.parse(repaired);
}
catch {
return null;
}
}
}
export function extractJson(text) {
if (!text)
return null;
const startBrace = text.indexOf("{");
const startBracket = text.indexOf("[");
let start = -1;
if (startBrace !== -1 && startBracket !== -1) {
start = Math.min(startBrace, startBracket);
}
else if (startBrace !== -1) {
start = startBrace;
}
else if (startBracket !== -1) {
start = startBracket;
}
if (start === -1)
return null;
const startChar = text[start];
const endChar = startChar === "{" ? "}" : "]";
let depth = 0;
let inString = false;
let escapeNext = false;
for (let i = start; i < text.length; i++) {
const char = text[i];
if (escapeNext) {
escapeNext = false;
continue;
}
if (char === "\\") {
escapeNext = true;
continue;
}
if (char === '"') {
inString = !inString;
continue;
}
if (!inString) {
if (char === startChar)
depth++;
if (char === endChar) {
depth--;
if (depth === 0) {
return text.slice(start, i + 1);
}
}
}
}
return repairJson(text.slice(start));
}
export function wrapInJson(key, content) {
return JSON.stringify({ [key]: content });
}
export function ensureJson(content, wrapKey = "content") {
if (!content)
return "{}";
if (isValidJson(content)) {
return content;
}
const repaired = repairJson(content);
if (isValidJson(repaired)) {
return repaired;
}
return wrapInJson(wrapKey, content);
}
//# sourceMappingURL=repair.js.map