@@ -10,7 +10,10 @@ import {
1010 createWriteStream ,
1111 existsSync ,
1212 mkdirSync ,
13+ closeSync ,
14+ openSync ,
1315 readFileSync ,
16+ readSync ,
1417 readdirSync ,
1518 realpathSync ,
1619 rmSync ,
@@ -53,6 +56,7 @@ export const CROSS_OS_AGENT_TURN_TIMEOUT_SECONDS = parsePositiveIntegerEnv(
5356 600 ,
5457) ;
5558export const CROSS_OS_COMMAND_CAPTURE_TAIL_BYTES = 16 * 1024 * 1024 ;
59+ const CROSS_OS_AGENT_LOG_FALLBACK_TAIL_BYTES = 2 * 1024 * 1024 ;
5660const CROSS_OS_PROCESS_TREE_KILL_AFTER_MS = parsePositiveIntegerEnv (
5761 "OPENCLAW_CROSS_OS_PROCESS_TREE_KILL_AFTER_MS" ,
5862 15_000 ,
@@ -3276,12 +3280,8 @@ export function shouldSkipOptionalCrossOsAgentTurnError(error, logPath) {
32763280 if ( ! / A g e n t o u t p u t d i d n o t c o n t a i n t h e e x p e c t e d O K m a r k e r / u. test ( message ) ) {
32773281 return false ;
32783282 }
3279- try {
3280- const log = readFileSync ( logPath , "utf8" ) ;
3281- return / " s t a t u s " \s * : \s * " t i m e o u t " | R e q u e s t t i m e d o u t b e f o r e a r e s p o n s e w a s g e n e r a t e d / u. test ( log ) ;
3282- } catch {
3283- return false ;
3284- }
3283+ const log = readLogTextTail ( logPath ) ;
3284+ return / " s t a t u s " \s * : \s * " t i m e o u t " | R e q u e s t t i m e d o u t b e f o r e a r e s p o n s e w a s g e n e r a t e d / u. test ( log ) ;
32853285}
32863286
32873287function buildReleaseAgentTurnArgs ( sessionId ) {
@@ -3313,7 +3313,7 @@ export function agentTurnUsedEmbeddedFallback(result, options = {}) {
33133313 typeof options . logText === "string"
33143314 ? options . logText
33153315 : typeof options . logPath === "string"
3316- ? safeReadTextFile ( options . logPath )
3316+ ? readLogTextTail ( options . logPath )
33173317 : "" ;
33183318 return / E M B E D D E D F A L L B A C K : / u. test ( `${ result . stdout ?? "" } \n${ result . stderr ?? "" } \n${ logText } ` ) ;
33193319}
@@ -3330,12 +3330,8 @@ export function agentOutputHasExpectedOkMarker(stdout, options = {}) {
33303330 if ( typeof options . logPath !== "string" ) {
33313331 return false ;
33323332 }
3333- try {
3334- const logTexts = parseAgentPayloadTexts ( readFileSync ( options . logPath , "utf8" ) ) ;
3335- return logTexts . some ( ( text ) => text . trim ( ) === "OK" ) ;
3336- } catch {
3337- return false ;
3338- }
3333+ const logTexts = parseAgentPayloadTexts ( readLogTextTail ( options . logPath ) ) ;
3334+ return logTexts . some ( ( text ) => text . trim ( ) === "OK" ) ;
33393335}
33403336
33413337function readLogFileSize ( logPath ) {
@@ -3347,19 +3343,52 @@ function readLogFileSize(logPath) {
33473343}
33483344
33493345function readLogTextSince ( logPath , offsetBytes ) {
3346+ return readLogTextWindow ( logPath , {
3347+ offsetBytes,
3348+ maxBytes : CROSS_OS_AGENT_LOG_FALLBACK_TAIL_BYTES ,
3349+ } ) ;
3350+ }
3351+
3352+ function readLogTextTail ( logPath ) {
3353+ return readLogTextWindow ( logPath , {
3354+ maxBytes : CROSS_OS_AGENT_LOG_FALLBACK_TAIL_BYTES ,
3355+ } ) ;
3356+ }
3357+
3358+ function readLogTextWindow ( logPath , options = { } ) {
3359+ const maxBytes = Math . max (
3360+ 1 ,
3361+ Math . floor ( options . maxBytes ?? CROSS_OS_AGENT_LOG_FALLBACK_TAIL_BYTES ) ,
3362+ ) ;
3363+ const offsetBytes =
3364+ typeof options . offsetBytes === "number" && Number . isFinite ( options . offsetBytes )
3365+ ? Math . max ( 0 , Math . floor ( options . offsetBytes ) )
3366+ : 0 ;
3367+ let stat ;
33503368 try {
3351- return readFileSync ( logPath ) . subarray ( offsetBytes ) . toString ( "utf8" ) ;
3369+ stat = statSync ( logPath ) ;
33523370 } catch {
33533371 return "" ;
33543372 }
3355- }
3373+ if ( ! stat . isFile ( ) || stat . size <= 0 ) {
3374+ return "" ;
3375+ }
33563376
3357- function safeReadTextFile ( logPath ) {
3358- try {
3359- return readFileSync ( logPath , "utf8" ) ;
3360- } catch {
3377+ const tailStart = Math . max ( 0 , stat . size - maxBytes ) ;
3378+ const start = Math . min ( stat . size , Math . max ( offsetBytes , tailStart ) ) ;
3379+ const length = stat . size - start ;
3380+ if ( length <= 0 ) {
33613381 return "" ;
33623382 }
3383+
3384+ const fd = openSync ( logPath , "r" ) ;
3385+ try {
3386+ const buffer = Buffer . alloc ( length ) ;
3387+ const bytesRead = readSync ( fd , buffer , 0 , length , start ) ;
3388+ return buffer . subarray ( 0 , bytesRead ) . toString ( "utf8" ) ;
3389+ } finally {
3390+ closeSync ( fd ) ;
3391+ }
33633392}
33643393
33653394function parseAgentPayloadTexts ( stdout ) {
0 commit comments