@@ -54,6 +54,42 @@ function redactPreview(s) {
5454 . slice ( 0 , 240 ) ;
5555}
5656
57+ function looksPathLike ( s ) {
58+ const value = String ( s || '' ) . trim ( ) ;
59+ if ( ! value || value . length > 1024 || / [ \r \n < > ] / . test ( value ) ) return false ;
60+ if ( / ^ f i l e : \/ \/ \/ ? (?: [ A - Z a - z ] : [ \\ / ] | \/ | ~ [ \\ / ] ) / . test ( value ) ) return true ;
61+ if ( / ^ (?: [ A - Z a - z ] : [ \\ / ] | \/ | ~ [ \\ / ] | \. { 1 , 2 } [ \\ / ] ) \S + / . test ( value ) ) return true ;
62+ return / ^ [ A - Z a - z 0 - 9 . _ - ] + (?: [ \\ / ] [ A - Z a - z 0 - 9 . _ - ] + ) * \. [ A - Z a - z 0 - 9 ] { 1 , 12 } $ / . test ( value ) ;
63+ }
64+
65+ function looksPromptLike ( s ) {
66+ const value = String ( s || '' ) ;
67+ if ( ! value ) return false ;
68+ if ( value . includes ( 'Working directory:' ) || value . includes ( 'Use the Read tool' ) ) return true ;
69+ if ( value . includes ( '<env>' ) || value . includes ( '</env>' ) || value . includes ( '<system-reminder>' ) ) return true ;
70+ return value . length > 512 && / (?: t o o l | p r o m p t | e n v i r o n m e n t | p l a t f o r m | w o r k s p a c e ) / i. test ( value ) ;
71+ }
72+
73+ function basenameOfPath ( s ) {
74+ const value = String ( s || '' ) . trim ( ) . replace ( / ^ f i l e : \/ + / , '' ) ;
75+ const parts = value . split ( / [ \\ / ] + / ) . filter ( Boolean ) ;
76+ return parts . length ? parts [ parts . length - 1 ] . slice ( 0 , 120 ) : '' ;
77+ }
78+
79+ function looksLikeMessage ( buf ) {
80+ if ( ! buf ?. length ) return false ;
81+ const key = buf [ 0 ] ;
82+ const wireType = key & 7 ;
83+ const field = key >> 3 ;
84+ if ( ! field || ! [ 0 , 1 , 2 , 5 ] . includes ( wireType ) ) return false ;
85+ try {
86+ const parsed = parseFields ( buf ) ;
87+ return parsed . length > 0 && parsed . every ( f => f . field > 0 ) ;
88+ } catch {
89+ return false ;
90+ }
91+ }
92+
5793function stringField ( fields , num ) {
5894 const f = getField ( fields , num , 2 ) ;
5995 return f ? f . value . toString ( 'utf8' ) : '' ;
@@ -343,6 +379,50 @@ function summarizeNativeStepBody(kind, bodyBuf) {
343379 return { fieldCount : f . length } ;
344380}
345381
382+ function summarizeReadWrapperField19 ( wrapperBuf ) {
383+ const fields = parseFields ( wrapperBuf ) ;
384+ return {
385+ bytes : wrapperBuf . length ,
386+ fieldNumbers : fields . map ( f => f . field ) ,
387+ children : fields . slice ( 0 , positiveIntEnv ( 'WINDSURFAPI_PROTO_TRACE_READ_WRAPPER_CHILD_LIMIT' , 24 ) )
388+ . map ( ( f ) => {
389+ const out = {
390+ field : f . field ,
391+ wireType : f . wireType ,
392+ } ;
393+ if ( f . wireType === 0 ) {
394+ out . type = 'varint' ;
395+ out . value = typeof f . value === 'bigint' ? f . value . toString ( ) : f . value ;
396+ return out ;
397+ }
398+ if ( ! Buffer . isBuffer ( f . value ) ) return out ;
399+ out . bytes = f . value . length ;
400+ out . sha256 = shortHash ( f . value ) ;
401+ if ( looksLikeMessage ( f . value ) ) {
402+ out . type = 'message_or_bytes' ;
403+ out . summary = summarizeMessageChildren ( f . value , 8 ) ;
404+ return out ;
405+ }
406+ if ( mostlyText ( f . value ) ) {
407+ const text = f . value . toString ( 'utf8' ) ;
408+ out . type = 'string' ;
409+ out . hasNewline = / [ \r \n ] / . test ( text ) ;
410+ out . hasAngleBracket = / [ < > ] / . test ( text ) ;
411+ out . looksPathLike = looksPathLike ( text ) ;
412+ out . looksPromptLike = looksPromptLike ( text ) ;
413+ out . basename = out . looksPathLike ? basenameOfPath ( text ) : '' ;
414+ if ( process . env . WINDSURFAPI_PROTO_TRACE_READ_WRAPPER_STRINGS === '1' ) {
415+ out . preview = redactPreview ( text ) ;
416+ }
417+ return out ;
418+ }
419+ out . type = 'message_or_bytes' ;
420+ out . summary = summarizeMessageChildren ( f . value , 8 ) ;
421+ return out ;
422+ } ) ,
423+ } ;
424+ }
425+
346426function summarizeTrajectoryStep ( stepBuf , index ) {
347427 const fields = parseFields ( stepBuf ) ;
348428 const oneofFields = [ ] ;
@@ -363,13 +443,16 @@ function summarizeTrajectoryStep(stepBuf, index) {
363443 field : f . field ,
364444 ...summarizeMessageChildren ( f . value , 8 ) ,
365445 } ) ) ;
446+ const type = numberField ( fields , 1 ) ;
447+ const wrapper19 = type === 14 ? getField ( fields , 19 , 2 ) : null ;
366448 return {
367449 index,
368- type : numberField ( fields , 1 ) ,
450+ type,
369451 status : numberField ( fields , 4 ) ,
370452 fieldNumbers : fields . map ( f => f . field ) ,
371453 nativeOneofs : oneofFields ,
372454 messageFields : interestingFields ,
455+ ...( wrapper19 ? { readWrapperField19 : summarizeReadWrapperField19 ( wrapper19 . value ) } : { } ) ,
373456 } ;
374457}
375458
0 commit comments