@@ -355,6 +355,48 @@ export function processGeminiStreamChunk(data: any): {
355355 return result
356356}
357357
358+ /**
359+ * Safely parse JSON with fallback handling for common malformed JSON issues
360+ * Used specifically for SAP AI Core streaming responses
361+ */
362+ export function parseJsonSafely ( str : string ) : any {
363+ if ( ! str || typeof str !== "string" || str . trim ( ) === "" ) {
364+ console . error ( "Failed to parse JSON safely:" , str , new Error ( "Input must be a non-empty string" ) )
365+ throw new Error ( "Input must be a non-empty string" )
366+ }
367+
368+ try {
369+ // First try standard JSON parsing
370+ return JSON . parse ( str )
371+ } catch ( error ) {
372+ // If that fails, try to fix common JSON issues safely
373+ try {
374+ let cleaned = str . trim ( )
375+ cleaned = cleaned . replace ( / , ( \s * [ } \] ] ) / g, "$1" )
376+ cleaned = cleaned . replace ( / ( [ { , ] \s * ) ( [ a - z A - Z _ $ ] [ a - z A - Z 0 - 9 _ $ ] * ) \s * : / g, '$1"$2":' )
377+ cleaned = cleaned . replace ( / ' ( [ ^ ' ] * ?) ' / g, '"$1"' )
378+
379+ // Remove any trailing commas at the end
380+ cleaned = cleaned . replace ( / , \s * $ / , "" )
381+ return JSON . parse ( cleaned )
382+ } catch ( secondError ) {
383+ // If regex approach fails, try the toStrictJson approach as fallback
384+ // but only for trusted SAP AI Core responses
385+ try {
386+ const obj = new Function ( "return " + str ) ( )
387+ return JSON . stringify ( obj )
388+ } catch ( thirdError ) {
389+ console . error (
390+ "Failed to parse JSON safely:" ,
391+ str ,
392+ error instanceof Error ? error : new Error ( "Unknown error" ) ,
393+ )
394+ throw new Error ( `Invalid JSON format: ${ error instanceof Error ? error . message : "Unknown error" } ` )
395+ }
396+ }
397+ }
398+ }
399+
358400function convertAnthropicMessageToGemini ( message : Anthropic . Messages . MessageParam ) {
359401 const role = message . role === "assistant" ? "model" : "user"
360402 const parts = [ ]
@@ -420,29 +462,6 @@ export function prepareGeminiRequestPayload(
420462 return payload
421463}
422464
423- /**
424- * Safely parse JSON with fallback handling for common malformed JSON issues
425- * Used specifically for SAP AI Core streaming responses
426- */
427- export function parseJsonSafely ( str : string ) : any {
428- try {
429- // First try standard JSON parsing
430- return JSON . parse ( str )
431- } catch ( error ) {
432- // If that fails, try to fix common JSON issues safely
433- try {
434- // Remove trailing commas and fix other common issues
435- const cleaned = str
436- . replace ( / , ( \s * [ } \] ] ) / g, "$1" ) // Remove trailing commas
437- . replace ( / ( [ { , ] \s * ) ( [ a - z A - Z _ $ ] [ a - z A - Z 0 - 9 _ $ ] * ) \s * : / g, '$1"$2":' ) // Quote unquoted keys
438- return JSON . parse ( cleaned )
439- } catch ( secondError ) {
440- console . error ( "Failed to parse JSON safely:" , str , secondError )
441- throw secondError
442- }
443- }
444- }
445-
446465export class SapAiCoreHandler extends BaseProvider implements SingleCompletionHandler {
447466 private options : SapAiCoreHandlerOptions
448467 private token ?: Token
0 commit comments