@@ -3185,6 +3185,65 @@ class CopilotTokenTracker implements vscode.Disposable {
31853185 } ) ;
31863186 }
31873187
3188+ /**
3189+ * Opens a JSONL file in a formatted view with array brackets and commas.
3190+ * Does not modify the original file.
3191+ */
3192+ public async showFormattedJsonlFile ( sessionFilePath : string ) : Promise < void > {
3193+ try {
3194+ // Read the file content
3195+ const fileContent = await fs . promises . readFile ( sessionFilePath , 'utf-8' ) ;
3196+
3197+ // Parse JSONL into array of objects
3198+ const lines = fileContent . trim ( ) . split ( '\n' ) . filter ( line => line . trim ( ) . length > 0 ) ;
3199+ const jsonObjects : unknown [ ] = [ ] ;
3200+
3201+ for ( let i = 0 ; i < lines . length ; i ++ ) {
3202+ try {
3203+ const obj = JSON . parse ( lines [ i ] ) ;
3204+ jsonObjects . push ( obj ) ;
3205+ } catch ( e ) {
3206+ // Skip malformed lines with detailed warning
3207+ this . warn ( `Skipping malformed line ${ i + 1 } in ${ sessionFilePath } : ${ e } ` ) ;
3208+ }
3209+ }
3210+
3211+ // Format as JSON array
3212+ const formattedJson = JSON . stringify ( jsonObjects , null , 2 ) ;
3213+
3214+ // Create an untitled document with the formatted content
3215+ const fileName = path . basename ( sessionFilePath , path . extname ( sessionFilePath ) ) ;
3216+ const prettyUri = vscode . Uri . parse ( `untitled:${ fileName } -formatted.json` ) ;
3217+
3218+ // Check if this document is already open and close it to refresh
3219+ const openDoc = vscode . workspace . textDocuments . find ( d => d . uri . toString ( ) === prettyUri . toString ( ) ) ;
3220+ if ( openDoc ) {
3221+ // Close the existing document so we can create a fresh one with updated content
3222+ const editor = vscode . window . visibleTextEditors . find ( e => e . document === openDoc ) ;
3223+ if ( editor ) {
3224+ await vscode . window . showTextDocument ( openDoc , editor . viewColumn ) ;
3225+ await vscode . commands . executeCommand ( 'workbench.action.closeActiveEditor' ) ;
3226+ }
3227+ }
3228+
3229+ // Create and open the document
3230+ const doc = await vscode . workspace . openTextDocument ( prettyUri ) ;
3231+ const editor = await vscode . window . showTextDocument ( doc , { preview : true } ) ;
3232+
3233+ // Insert the formatted JSON
3234+ await editor . edit ( ( editBuilder ) => {
3235+ editBuilder . insert ( new vscode . Position ( 0 , 0 ) , formattedJson ) ;
3236+ } ) ;
3237+
3238+ // Set language mode to JSON for syntax highlighting
3239+ await vscode . languages . setTextDocumentLanguage ( doc , 'json' ) ;
3240+
3241+ } catch ( error ) {
3242+ this . error ( `Error formatting JSONL file ${ sessionFilePath } :` , error ) ;
3243+ throw error ;
3244+ }
3245+ }
3246+
31883247 private getLogViewerHtml ( webview : vscode . Webview , logData : SessionLogData ) : string {
31893248 const nonce = this . getNonce ( ) ;
31903249 const scriptUri = webview . asWebviewUri ( vscode . Uri . joinPath ( this . extensionUri , 'dist' , 'webview' , 'logviewer.js' ) ) ;
@@ -3577,6 +3636,17 @@ class CopilotTokenTracker implements vscode.Disposable {
35773636 }
35783637 break ;
35793638
3639+ case 'openFormattedJsonlFile' :
3640+ if ( message . file ) {
3641+ try {
3642+ await this . showFormattedJsonlFile ( message . file ) ;
3643+ } catch ( err ) {
3644+ const errorMsg = err instanceof Error ? err . message : String ( err ) ;
3645+ vscode . window . showErrorMessage ( 'Could not open formatted file: ' + message . file + ' (' + errorMsg + ')' ) ;
3646+ }
3647+ }
3648+ break ;
3649+
35803650 case 'revealPath' :
35813651 if ( message . path ) {
35823652 try {
0 commit comments