@@ -61,26 +61,44 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
6161 archive . on ( "error" , reject )
6262 } )
6363
64- // Add each failed task's log file to the archive
64+ // Add each failed task's log file and history files to the archive
6565 const logDir = path . join ( LOG_BASE_PATH , String ( runId ) )
6666 let filesAdded = 0
6767
6868 for ( const task of failedTasks ) {
6969 // Sanitize language and exercise to prevent path traversal
7070 const safeLanguage = sanitizePathComponent ( task . language )
7171 const safeExercise = sanitizePathComponent ( task . exercise )
72+ const expectedBase = path . resolve ( LOG_BASE_PATH )
73+
74+ // Add the log file
7275 const logFileName = `${ safeLanguage } -${ safeExercise } .log`
7376 const logFilePath = path . join ( logDir , logFileName )
7477
7578 // Verify the resolved path is within the expected directory (defense in depth)
76- const resolvedPath = path . resolve ( logFilePath )
77- const expectedBase = path . resolve ( LOG_BASE_PATH )
78- if ( ! resolvedPath . startsWith ( expectedBase ) ) {
79- continue // Skip files with suspicious paths
79+ const resolvedLogPath = path . resolve ( logFilePath )
80+ if ( resolvedLogPath . startsWith ( expectedBase ) && fs . existsSync ( logFilePath ) ) {
81+ archive . file ( logFilePath , { name : logFileName } )
82+ filesAdded ++
8083 }
8184
82- if ( fs . existsSync ( logFilePath ) ) {
83- archive . file ( logFilePath , { name : logFileName } )
85+ // Add the API conversation history file
86+ // Format: {language}-{exercise}.{iteration}_api_conversation_history.json
87+ const apiHistoryFileName = `${ safeLanguage } -${ safeExercise } .${ task . iteration } _api_conversation_history.json`
88+ const apiHistoryFilePath = path . join ( logDir , apiHistoryFileName )
89+ const resolvedApiHistoryPath = path . resolve ( apiHistoryFilePath )
90+ if ( resolvedApiHistoryPath . startsWith ( expectedBase ) && fs . existsSync ( apiHistoryFilePath ) ) {
91+ archive . file ( apiHistoryFilePath , { name : apiHistoryFileName } )
92+ filesAdded ++
93+ }
94+
95+ // Add the UI messages file
96+ // Format: {language}-{exercise}.{iteration}_ui_messages.json
97+ const uiMessagesFileName = `${ safeLanguage } -${ safeExercise } .${ task . iteration } _ui_messages.json`
98+ const uiMessagesFilePath = path . join ( logDir , uiMessagesFileName )
99+ const resolvedUiMessagesPath = path . resolve ( uiMessagesFilePath )
100+ if ( resolvedUiMessagesPath . startsWith ( expectedBase ) && fs . existsSync ( uiMessagesFilePath ) ) {
101+ archive . file ( uiMessagesFilePath , { name : uiMessagesFileName } )
84102 filesAdded ++
85103 }
86104 }
0 commit comments