@@ -9,6 +9,7 @@ import { telemetryMock } from '@sim/testing/mocks/telemetry.mock'
99import { workflowsOrchestrationMock } from '@sim/testing/mocks/workflows-orchestration.mock'
1010import { getErrorMessage } from '@sim/utils/errors'
1111import { beforeEach , describe , expect , it , vi } from 'vitest'
12+ import { MAX_INLINE_MATERIALIZATION_BYTES } from '@/lib/execution/payloads/limits'
1213import { inspectToolResultForCopilot } from '@/lib/mothership/request/tools/resolved-secret-result'
1314import type { ExecutionContext } from '@/lib/mothership/request/types'
1415import { ResolvedSecretTraceRegistry } from '@/executor/utils/resolved-secret-trace-registry'
@@ -503,31 +504,53 @@ describe('run_workflow model-facing result budget', () => {
503504
504505 /**
505506 * The bound only handles size. An output JSON cannot encode cannot be checked, so the run is still
506- * refused rather than the value being hidden behind a pointer.
507+ * refused rather than the value being hidden behind a pointer, even while a bulky log beside it
508+ * is replaced. The bulky log comes first, so the whole-result walk passes the cap before it ever
509+ * reaches the unencodable one.
507510 */
508511 it ( 'still refuses a run with an unencodable block output while bounding bulky ones' , async ( ) => {
512+ const narrow = Array . from ( { length : 25_000 } , ( _ , index ) => ( {
513+ id : `r${ index } ` ,
514+ data : { a : 'x' } ,
515+ } ) )
509516 mocks . executeWorkflowUseCase . mockResolvedValue ( {
510517 success : true ,
511- output : { } ,
518+ output : { done : true } ,
512519 logs : [
513- {
514- blockId : 'big' ,
515- blockName : 'Big' ,
516- success : true ,
517- output : { rows : tableRows ( 4_800 , 3_200_000 ) } ,
518- } ,
520+ { blockId : 'big' , blockName : 'Big' , success : true , output : { rows : narrow } } ,
519521 { blockId : 'odd' , blockName : 'Odd' , success : true , output : { count : 1n } } ,
520522 ] ,
521523 metadata : { executionId : EXECUTION_ID } ,
522524 } )
523525
524- const settled = await executeRunWorkflowUntilBlock (
525- { workflowId : 'wf-1' , stopAfterBlockId : 'odd' } ,
526- context
526+ const settled = await executeRunWorkflow ( { workflowId : 'wf-1' } , context )
527+ const presented = settled . output as { logs : Array < { output : unknown } > }
528+ expect ( presented . logs [ 0 ] ?. output ) . toEqual (
529+ expect . stringContaining ( `logs get ${ EXECUTION_ID } --trace` )
527530 )
528- const presented = settled . output as { output : unknown ; logs : Array < { output : unknown } > }
529- expect ( presented . output ) . toEqual ( { count : 1n } )
530531 expect ( presented . logs [ 1 ] ?. output ) . toEqual ( { count : 1n } )
531532 expect ( inspectToolResultForCopilot ( settled , registry , 'run_workflow' ) . safe ) . toBe ( false )
532533 } )
534+
535+ /** The projection checks the error with the output, so the whole-result measure includes it. */
536+ it ( 'counts the error toward the caps a run result is bounded against' , async ( ) => {
537+ const text = { text : 'y' . repeat ( Math . floor ( MAX_INLINE_MATERIALIZATION_BYTES * 0.6 ) ) }
538+ const error = `Report failed: ${ 'e' . repeat ( Math . floor ( MAX_INLINE_MATERIALIZATION_BYTES * 0.5 ) ) } `
539+ mocks . executeWorkflowUseCase . mockResolvedValue ( {
540+ success : false ,
541+ error,
542+ output : { done : false } ,
543+ logs : [ { blockId : 'big' , blockName : 'Big' , success : true , output : text } ] ,
544+ metadata : { executionId : EXECUTION_ID } ,
545+ } )
546+
547+ const settled = await executeRunWorkflow ( { workflowId : 'wf-1' } , context )
548+ const projection = inspectToolResultForCopilot ( settled , registry , 'run_workflow' )
549+
550+ expect ( projection . safe ) . toBe ( true )
551+ expect ( projection . result . error ) . toBe ( error )
552+ expect (
553+ ( projection . result . output as { logs : Array < { output : unknown } > } ) . logs [ 0 ] ?. output
554+ ) . toEqual ( expect . stringContaining ( `logs get ${ EXECUTION_ID } --trace` ) )
555+ } )
533556} )
0 commit comments