Add more thorough check for JSON in providers/

This commit is contained in:
Waleed Latif
2025-02-13 18:14:58 -08:00
parent 071e370de8
commit d99bd1e0a9
2 changed files with 42 additions and 4 deletions
+5 -4
View File
@@ -1,6 +1,7 @@
import { executeTool, getTool } from '@/tools'
import { getProvider } from './registry'
import { ProviderRequest, ProviderResponse, TokenInfo } from './types'
import { extractAndParseJSON } from './utils'
// Helper function to generate provider-specific structured output instructions
function generateStructuredOutputInstructions(responseFormat: any): string {
@@ -101,8 +102,8 @@ export async function executeProviderRequest(
// If responseFormat is specified and we have content (not a function call), validate and parse the response
if (request.responseFormat && content && !provider.hasFunctionCall(currentResponse)) {
try {
// Try to parse the content as JSON
const parsedContent = JSON.parse(content)
// Extract and parse the JSON content
const parsedContent = extractAndParseJSON(content)
// Validate that all required fields are present and have correct types
const validationErrors = request.responseFormat.fields
@@ -138,8 +139,8 @@ export async function executeProviderRequest(
// Store the validated JSON response
content = JSON.stringify(parsedContent)
} catch (error: any) {
console.error('Error parsing structured response:', error)
throw new Error(`Failed to parse response as structured output: ${error.message}`)
console.error('Raw content:', content)
throw new Error(`Failed to parse structured response: ${error.message}`)
}
}
+37
View File
@@ -38,3 +38,40 @@ export function getProviderFromModel(model: string): ProviderId {
// Default to deepseek for any other models
return 'deepseek'
}
export function extractAndParseJSON(content: string): any {
// First clean up the string
const trimmed = content.trim()
// Find the first '{' and last '}'
const firstBrace = trimmed.indexOf('{')
const lastBrace = trimmed.lastIndexOf('}')
if (firstBrace === -1 || lastBrace === -1) {
throw new Error('No JSON object found in content')
}
// Extract just the JSON part
const jsonStr = trimmed.slice(firstBrace, lastBrace + 1)
try {
return JSON.parse(jsonStr)
} catch (error) {
// If parsing fails, try to clean up common issues
const cleaned = jsonStr
.replace(/\n/g, ' ') // Remove newlines
.replace(/\s+/g, ' ') // Normalize whitespace
.replace(/,\s*([}\]])/g, '$1') // Remove trailing commas
try {
return JSON.parse(cleaned)
} catch (innerError) {
console.error('Original content:', content)
console.error('Extracted JSON:', jsonStr)
console.error('Cleaned JSON:', cleaned)
throw new Error(
`Failed to parse JSON after cleanup: ${innerError instanceof Error ? innerError.message : 'Unknown error'}`
)
}
}
}