|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import fs from 'node:fs/promises'; |
|
|
import os from 'node:os'; |
|
|
import path from 'node:path'; |
|
|
import { Content } from '@google/genai'; |
|
|
|
|
|
interface ErrorReportData { |
|
|
error: { message: string; stack?: string } | { message: string }; |
|
|
context?: unknown; |
|
|
additionalInfo?: Record<string, unknown>; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export async function reportError( |
|
|
error: Error | unknown, |
|
|
baseMessage: string, |
|
|
context?: Content[] | Record<string, unknown> | unknown[], |
|
|
type = 'general', |
|
|
): Promise<void> { |
|
|
const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); |
|
|
const reportFileName = `gemini-client-error-${type}-${timestamp}.json`; |
|
|
const reportPath = path.join(os.tmpdir(), reportFileName); |
|
|
|
|
|
let errorToReport: { message: string; stack?: string }; |
|
|
if (error instanceof Error) { |
|
|
errorToReport = { message: error.message, stack: error.stack }; |
|
|
} else if ( |
|
|
typeof error === 'object' && |
|
|
error !== null && |
|
|
'message' in error |
|
|
) { |
|
|
errorToReport = { |
|
|
message: String((error as { message: unknown }).message), |
|
|
}; |
|
|
} else { |
|
|
errorToReport = { message: String(error) }; |
|
|
} |
|
|
|
|
|
const reportContent: ErrorReportData = { error: errorToReport }; |
|
|
|
|
|
if (context) { |
|
|
reportContent.context = context; |
|
|
} |
|
|
|
|
|
let stringifiedReportContent: string; |
|
|
try { |
|
|
stringifiedReportContent = JSON.stringify(reportContent, null, 2); |
|
|
} catch (stringifyError) { |
|
|
|
|
|
console.error( |
|
|
`${baseMessage} Could not stringify report content (likely due to context):`, |
|
|
stringifyError, |
|
|
); |
|
|
console.error('Original error that triggered report generation:', error); |
|
|
if (context) { |
|
|
console.error( |
|
|
'Original context could not be stringified or included in report.', |
|
|
); |
|
|
} |
|
|
|
|
|
try { |
|
|
const minimalReportContent = { error: errorToReport }; |
|
|
stringifiedReportContent = JSON.stringify(minimalReportContent, null, 2); |
|
|
|
|
|
await fs.writeFile(reportPath, stringifiedReportContent); |
|
|
console.error( |
|
|
`${baseMessage} Partial report (excluding context) available at: ${reportPath}`, |
|
|
); |
|
|
} catch (minimalWriteError) { |
|
|
console.error( |
|
|
`${baseMessage} Failed to write even a minimal error report:`, |
|
|
minimalWriteError, |
|
|
); |
|
|
} |
|
|
return; |
|
|
} |
|
|
|
|
|
try { |
|
|
await fs.writeFile(reportPath, stringifiedReportContent); |
|
|
console.error(`${baseMessage} Full report available at: ${reportPath}`); |
|
|
} catch (writeError) { |
|
|
console.error( |
|
|
`${baseMessage} Additionally, failed to write detailed error report:`, |
|
|
writeError, |
|
|
); |
|
|
|
|
|
console.error('Original error that triggered report generation:', error); |
|
|
if (context) { |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
console.error('Original context:', context); |
|
|
} catch { |
|
|
try { |
|
|
console.error( |
|
|
'Original context (stringified, truncated):', |
|
|
JSON.stringify(context).substring(0, 1000), |
|
|
); |
|
|
} catch { |
|
|
console.error('Original context could not be logged or stringified.'); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|