@@ -18,6 +18,7 @@ import * as https from 'https';
1818import * as http from 'http' ;
1919import { URL } from 'url' ;
2020import { TraceSink } from './sink' ;
21+ import { ScreenshotMetadata } from '../types' ;
2122
2223/**
2324 * Optional logger interface for SDK users
@@ -75,10 +76,19 @@ export class CloudTraceSink extends TraceSink {
7576 private apiUrl : string ;
7677 private logger ?: SentienceLogger ;
7778
78- // File size tracking (NEW)
79+ // File size tracking
7980 private traceFileSizeBytes : number = 0 ;
8081 private screenshotTotalSizeBytes : number = 0 ;
8182
83+ // Screenshot storage directory
84+ private screenshotDir : string ;
85+
86+ // Screenshot metadata tracking (sequence -> ScreenshotMetadata)
87+ private screenshotMetadata : Map < number , ScreenshotMetadata > = new Map ( ) ;
88+
89+ // Upload success flag
90+ private uploadSuccessful : boolean = false ;
91+
8292 /**
8393 * Create a new CloudTraceSink
8494 *
@@ -107,6 +117,12 @@ export class CloudTraceSink extends TraceSink {
107117 const cacheDir = getPersistentCacheDir ( ) ;
108118 this . tempFilePath = path . join ( cacheDir , `${ this . runId } .jsonl` ) ;
109119
120+ // Screenshot storage directory
121+ this . screenshotDir = path . join ( cacheDir , `${ this . runId } _screenshots` ) ;
122+ if ( ! fs . existsSync ( this . screenshotDir ) ) {
123+ fs . mkdirSync ( this . screenshotDir , { recursive : true } ) ;
124+ }
125+
110126 try {
111127 // Open file in append mode
112128 this . writeStream = fs . createWriteStream ( this . tempFilePath , {
@@ -282,17 +298,25 @@ export class CloudTraceSink extends TraceSink {
282298 const statusCode = await this . _uploadToCloud ( compressedData ) ;
283299
284300 if ( statusCode === 200 ) {
301+ this . uploadSuccessful = true ;
285302 console . log ( '✅ [Sentience] Trace uploaded successfully' ) ;
286303
304+ // Upload screenshots after trace upload succeeds
305+ if ( this . screenshotMetadata . size > 0 ) {
306+ console . log ( `📸 [Sentience] Uploading ${ this . screenshotMetadata . size } screenshots...` ) ;
307+ await this . _uploadScreenshots ( ) ;
308+ }
309+
287310 // Upload trace index file
288311 await this . _uploadIndex ( ) ;
289312
290313 // Call /v1/traces/complete to report file sizes
291314 await this . _completeTrace ( ) ;
292315
293- // 4. Delete temp file on success
294- await fsPromises . unlink ( this . tempFilePath ) ;
316+ // 4. Delete files on success
317+ await this . _cleanupFiles ( ) ;
295318 } else {
319+ this . uploadSuccessful = false ;
296320 console . error ( `❌ [Sentience] Upload failed: HTTP ${ statusCode } ` ) ;
297321 console . error ( ` Local trace preserved at: ${ this . tempFilePath } ` ) ;
298322 }
@@ -323,6 +347,7 @@ export class CloudTraceSink extends TraceSink {
323347 stats : {
324348 trace_file_size_bytes : this . traceFileSizeBytes ,
325349 screenshot_total_size_bytes : this . screenshotTotalSizeBytes ,
350+ screenshot_count : this . screenshotMetadata . size ,
326351 } ,
327352 } ) ;
328353
0 commit comments