@@ -8,7 +8,10 @@ import clack from '../utils/clack';
88import { debug , logToFile , initLogFile , LOG_FILE_PATH } from '../utils/debug' ;
99import type { WizardOptions } from '../utils/types' ;
1010import { analytics } from '../utils/analytics' ;
11- import { WIZARD_INTERACTION_EVENT_NAME } from './constants' ;
11+ import {
12+ WIZARD_INTERACTION_EVENT_NAME ,
13+ WIZARD_REMARK_EVENT_NAME ,
14+ } from './constants' ;
1215import { getLlmGatewayUrlFromHost } from '../utils/urls' ;
1316import { LINTING_TOOLS } from './safe-tools' ;
1417
@@ -43,6 +46,8 @@ export const AgentSignals = {
4346 ERROR_MCP_MISSING : '[ERROR-MCP-MISSING]' ,
4447 /** Signal emitted when the agent cannot access the setup resource */
4548 ERROR_RESOURCE_MISSING : '[ERROR-RESOURCE-MISSING]' ,
49+ /** Signal emitted when the agent provides a remark about its run */
50+ WIZARD_REMARK : '[WIZARD-REMARK]' ,
4651} as const ;
4752
4853export type AgentSignal = ( typeof AgentSignals ) [ keyof typeof AgentSignals ] ;
@@ -431,6 +436,23 @@ export async function runAgent(
431436 logToFile ( `Agent run completed in ${ durationSeconds } s` ) ;
432437 }
433438
439+ // Extract and capture the agent's reflection on the run
440+ const outputText = collectedText . join ( '\n' ) ;
441+ const remarkRegex = new RegExp (
442+ `${ AgentSignals . WIZARD_REMARK . replace (
443+ / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g,
444+ '\\$&' ,
445+ ) } \\s*(.+?)(?:\\n|$)`,
446+ 's' ,
447+ ) ;
448+ const remarkMatch = outputText . match ( remarkRegex ) ;
449+ if ( remarkMatch && remarkMatch [ 1 ] ) {
450+ const remark = remarkMatch [ 1 ] . trim ( ) ;
451+ if ( remark ) {
452+ analytics . capture ( WIZARD_REMARK_EVENT_NAME , { remark } ) ;
453+ }
454+ }
455+
434456 analytics . capture ( WIZARD_INTERACTION_EVENT_NAME , {
435457 action : 'agent integration completed' ,
436458 duration_ms : durationMs ,
@@ -492,6 +514,33 @@ export async function runAgent(
492514 debug ( 'CLI stderr:' , data ) ;
493515 }
494516 } ,
517+ // Stop hook to have the agent reflect on its run
518+ hooks : {
519+ Stop : [
520+ {
521+ hooks : [
522+ ( input : { stop_hook_active : boolean } ) => {
523+ logToFile ( 'Stop hook triggered' , {
524+ stop_hook_active : input . stop_hook_active ,
525+ } ) ;
526+
527+ // Only ask for reflection on first stop (not after reflection is provided)
528+ if ( input . stop_hook_active ) {
529+ logToFile ( 'Stop hook: allowing stop (already reflected)' ) ;
530+ return { } ; // Allow stopping
531+ }
532+
533+ logToFile ( 'Stop hook: requesting reflection' ) ;
534+ return {
535+ decision : 'block' ,
536+ reason : `Before concluding, provide a brief remark about what information or guidance would have been useful to have in the integration prompt or documentation for this run. Specifically cite anything that would have prevented tool failures, erroneous edits, or other wasted turns. Format your response exactly as: ${ AgentSignals . WIZARD_REMARK } Your remark here` ,
537+ } ;
538+ } ,
539+ ] ,
540+ timeout : 30 ,
541+ } ,
542+ ] ,
543+ } ,
495544 } ,
496545 } ) ;
497546
0 commit comments