@@ -540,8 +540,8 @@ export function activate(context: vscode.ExtensionContext): void {
540540 try {
541541 const r = trimSession ( picked . value , Number ( keepInput ) ) ;
542542 vscode . window . showInformationMessage (
543- `✓ 裁剪完成 / Trimmed : ${ r . originalLines } → ${ r . keptLines } 行 (${ r . sizeMb . toFixed ( 1 ) } MB → ${ r . trimmedSizeMb . toFixed ( 1 ) } MB)\n\n` +
544- `备份位置 / Backup: ${ r . backupPath } \n\n关闭并重新打开 CC 对话面板以生效 / Close and reopen CC chat to reload .` ,
543+ `✓ 裁剪副本已创建 / Trim copy created : ${ r . originalLines } → ${ r . keptLines } 行 (${ r . sizeMb . toFixed ( 1 ) } MB → ${ r . trimmedSizeMb . toFixed ( 1 ) } MB)\n\n` +
544+ `原对话不变,裁剪版标题为 "...(trim)",刷新列表即可看到 / Original unchanged. Trimmed copy titled "...(trim)" — refresh to see it .` ,
545545 { modal : true }
546546 ) ;
547547 } catch ( err ) {
@@ -611,8 +611,8 @@ export function activate(context: vscode.ExtensionContext): void {
611611 try {
612612 const r = trimSession ( jsonlPath , Number ( keepInput ) ) ;
613613 vscode . window . showInformationMessage (
614- `✓ 裁剪完成 / Trimmed : ${ r . originalLines } → ${ r . keptLines } 行 / lines (${ r . sizeMb . toFixed ( 1 ) } MB → ${ r . trimmedSizeMb . toFixed ( 1 ) } MB)\n\n` +
615- `备份位置 / Backup: ${ r . backupPath } \n\n关闭并重新打开 CC 对话面板以生效 / Close and reopen CC chat panel to reload .` ,
614+ `✓ 裁剪副本已创建 / Trim copy created : ${ r . originalLines } → ${ r . keptLines } 行 / lines (${ r . sizeMb . toFixed ( 1 ) } MB → ${ r . trimmedSizeMb . toFixed ( 1 ) } MB)\n\n` +
615+ `原对话不变,裁剪版标题为 "...(trim)",刷新列表即可看到 / Original unchanged. Trimmed copy titled "...(trim)" — refresh to see it .` ,
616616 { modal : true }
617617 ) ;
618618 } catch ( err ) {
@@ -1334,7 +1334,7 @@ function getSessionDisplayTitle(jsonlPath: string): string {
13341334function trimSession (
13351335 jsonlPath : string ,
13361336 keepRecentMessages : number = 400
1337- ) : { keptLines : number ; originalLines : number ; sizeMb : number ; trimmedSizeMb : number ; backupPath : string } {
1337+ ) : { keptLines : number ; originalLines : number ; sizeMb : number ; trimmedSizeMb : number ; newFilePath : string ; newSessionId : string } {
13381338 const raw = fs . readFileSync ( jsonlPath , 'utf8' ) ;
13391339 const lines = raw . split ( '\n' ) ;
13401340 const originalLines = lines . filter ( ( l ) => l . trim ( ) ) . length ;
@@ -1346,8 +1346,8 @@ function trimSession(
13461346 } ) ;
13471347
13481348 // Classify each non-empty line
1349- const msgLines : number [ ] = [ ] ; // indices of user/assistant message lines
1350- const initLines : number [ ] = [ ] ; // everything else (system, summaries, etc.)
1349+ const msgLines : number [ ] = [ ] ;
1350+ const initLines : number [ ] = [ ] ;
13511351
13521352 for ( let i = 0 ; i < parsed . length ; i ++ ) {
13531353 const obj = parsed [ i ] . obj ;
@@ -1360,7 +1360,7 @@ function trimSession(
13601360 }
13611361 }
13621362
1363- // Keep last keepRecentMessages message lines, ensuring we don't start with assistant
1363+ // Keep last keepRecentMessages message lines, start from a user turn
13641364 let recent = msgLines . slice ( - keepRecentMessages ) ;
13651365 while ( recent . length > 0 ) {
13661366 const firstObj = parsed [ recent [ 0 ] ] . obj ;
@@ -1369,23 +1369,55 @@ function trimSession(
13691369 recent = recent . slice ( 1 ) ;
13701370 }
13711371
1372- // Build output: init lines + recent message lines, preserving original order
1372+ // Build selected lines preserving original order
13731373 const keepSet = new Set ( [ ...initLines , ...recent ] ) ;
1374- const outLines : string [ ] = [ ] ;
1374+ const selectedLines : Record < string , unknown > [ ] = [ ] ;
13751375 for ( let i = 0 ; i < parsed . length ; i ++ ) {
1376- if ( ! parsed [ i ] . raw . trim ( ) ) continue ; // skip blank
1377- if ( keepSet . has ( i ) ) outLines . push ( parsed [ i ] . raw ) ;
1376+ if ( ! parsed [ i ] . raw . trim ( ) ) continue ;
1377+ if ( keepSet . has ( i ) && parsed [ i ] . obj ) selectedLines . push ( parsed [ i ] . obj ! ) ;
13781378 }
13791379
1380- // Backup original
1381- const ts = new Date ( ) . toISOString ( ) . replace ( / [: .] / g, '-' ) . slice ( 0 , 19 ) ;
1382- const backupPath = `${ jsonlPath } .bak-${ ts } ` ;
1383- fs . copyFileSync ( jsonlPath , backupPath ) ;
1380+ // Generate new session ID and remap all UUIDs (same approach as injectSession)
1381+ const crypto = require ( 'crypto' ) as typeof import ( 'crypto' ) ;
1382+ const newSessionId : string = crypto . randomUUID ( ) ;
1383+ const uuidMap = new Map < string , string > ( ) ;
1384+
1385+ const outLines : string [ ] = [ ] ;
1386+ let titleSet = false ;
1387+
1388+ for ( const obj of selectedLines ) {
1389+ const cloned = { ...obj } as Record < string , unknown > ;
1390+
1391+ // Remap uuid
1392+ const oldUuid = cloned . uuid as string | undefined ;
1393+ const newUuid : string = crypto . randomUUID ( ) ;
1394+ if ( oldUuid ) uuidMap . set ( oldUuid , newUuid ) ;
1395+ cloned . uuid = newUuid ;
1396+
1397+ // Remap parentUuid
1398+ const oldParent = cloned . parentUuid as string | null | undefined ;
1399+ if ( typeof oldParent === 'string' && uuidMap . has ( oldParent ) ) {
1400+ cloned . parentUuid = uuidMap . get ( oldParent ) ! ;
1401+ }
1402+
1403+ // Stamp new sessionId
1404+ cloned . sessionId = newSessionId ;
1405+
1406+ // Set customTitle on first line that has one (or first line overall)
1407+ if ( ! titleSet ) {
1408+ const originalTitle = ( cloned . customTitle as string | undefined ) || getSessionDisplayTitle ( jsonlPath ) ;
1409+ cloned . customTitle = `${ originalTitle } (trim)` ;
1410+ titleSet = true ;
1411+ }
1412+
1413+ outLines . push ( JSON . stringify ( cloned ) ) ;
1414+ }
13841415
1385- // Overwrite in-place
1386- fs . writeFileSync ( jsonlPath , outLines . join ( '\n' ) + '\n' , 'utf8' ) ;
1387- const trimmedSizeMb = fs . statSync ( jsonlPath ) . size / 1024 / 1024 ;
1416+ // Write new file alongside original (same project dir, new UUID filename)
1417+ const newFilePath = path . join ( path . dirname ( jsonlPath ) , `${ newSessionId } .jsonl` ) ;
1418+ fs . writeFileSync ( newFilePath , outLines . join ( '\n' ) + '\n' , 'utf8' ) ;
1419+ const trimmedSizeMb = fs . statSync ( newFilePath ) . size / 1024 / 1024 ;
13881420
1389- return { keptLines : outLines . length , originalLines, sizeMb, trimmedSizeMb, backupPath } ;
1421+ return { keptLines : outLines . length , originalLines, sizeMb, trimmedSizeMb, newFilePath , newSessionId } ;
13901422}
13911423
0 commit comments