feat: add JSON detection utility for various formats

- Implemented a utility function `detectJsonInLine` to identify and parse JSON data from different formats including direct JSON, tool calls, tool results, embedded JSON, and code blocks.
- Introduced `JsonDetectionResult` interface to standardize the detection results.
- Added a new test results file to track the status of tests.
This commit is contained in:
catlog22
2026-02-01 15:17:03 +08:00
parent f196b76064
commit 0342976c51
4 changed files with 1237 additions and 1417 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,102 @@
/**
* JSON Detection Result
*/
export interface JsonDetectionResult {
isJson: boolean;
parsed?: Record<string, unknown>;
error?: string;
}
/**
* Detect if a line contains JSON data
* Supports multiple formats:
* - Direct JSON: {...} or [...]
* - Tool Call: [Tool] toolName({...})
* - Tool Result: [Tool Result] status: {...}
* - Embedded JSON: trailing JSON object
* - Code block JSON: ```json ... ```
*
* @param content - The content line to detect JSON in
* @returns Detection result with parsed data if valid JSON found
*/
export function detectJsonInLine(content: string): JsonDetectionResult {
const trimmed = content.trim();
// 1. Direct JSON object or array
if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
try {
const parsed = JSON.parse(trimmed);
return { isJson: true, parsed: parsed as Record<string, unknown> };
} catch {
// Continue to other patterns
}
}
// 2. Tool Call format: [Tool] toolName({...})
const toolCallMatch = trimmed.match(/^\[Tool\]\s+(\w+)\((.*)\)$/);
if (toolCallMatch) {
const [, toolName, paramsStr] = toolCallMatch;
let parameters: unknown;
try {
parameters = paramsStr ? JSON.parse(paramsStr) : {};
} catch {
parameters = paramsStr || null;
}
return {
isJson: true,
parsed: {
action: 'invoke',
toolName,
parameters,
} as Record<string, unknown>,
};
}
// 3. Tool Result format: [Tool Result] status: output
const toolResultMatch = trimmed.match(/^\[Tool Result\]\s+(.+?)\s*:\s*(.+)$/);
if (toolResultMatch) {
const [, status, outputStr] = toolResultMatch;
let output: unknown;
try {
output = outputStr.startsWith('{') ? JSON.parse(outputStr) : outputStr;
} catch {
output = outputStr;
}
return {
isJson: true,
parsed: {
action: 'result',
status,
output,
} as Record<string, unknown>,
};
}
// 4. Embedded JSON at end of line
const embeddedJsonMatch = trimmed.match(/\{.*\}$/);
if (embeddedJsonMatch) {
try {
const parsed = JSON.parse(embeddedJsonMatch[0]);
return { isJson: true, parsed: parsed as Record<string, unknown> };
} catch {
// Not valid JSON
}
}
// 5. Code block JSON
const codeBlockMatch = trimmed.match(/```(?:json)?\s*\n([\s\S]*?)\n```/);
if (codeBlockMatch) {
try {
const parsed = JSON.parse(codeBlockMatch[1]);
return { isJson: true, parsed: parsed as Record<string, unknown> };
} catch {
return { isJson: false, error: 'Invalid JSON in code block' };
}
}
return { isJson: false };
}

View File

@@ -0,0 +1,4 @@
{
"status": "failed",
"failedTests": []
}