@@ -6,18 +6,24 @@ import { randomUUID } from 'node:crypto';
66
77import path from 'path' ;
88import * as os from 'os' ;
9+ // eslint-disable-next-line no-restricted-imports -- resolves the SDK's bundled CLI path where ESM has no bare require
910import { createRequire } from 'node:module' ;
1011import type {
1112 ProgressEmitter ,
1213 SpinnerHandle ,
1314 TokenUsageDelta ,
1415} from './progress' ;
15- import { debug , logToFile , initLogFile , getLogFilePath } from '@utils/debug' ;
16+ import {
17+ formatLogLine ,
18+ logToFile ,
19+ initLogFile ,
20+ getLogFilePath ,
21+ } from '@utils/debug' ;
1622import type { WizardRunOptions } from '@utils/types' ;
1723import { analytics } from '@utils/analytics' ;
1824import { isTemplateEnvFileName } from '@utils/env-scan' ;
1925import { runtimeEnv } from '@env' ;
20- import type { AioCapture } from '@agent /aio-capture' ;
26+ import type { AioCapture } from '. /aio-capture' ;
2127import {
2228 Harness ,
2329 CallType ,
@@ -36,14 +42,14 @@ import {
3642 gatewayAuth ,
3743 isPastRefresh ,
3844 type GatewayAuth ,
39- } from '@agent /gateway-session' ;
45+ } from '. /gateway-session' ;
4046import { evaluateBashCommand } from './bash-fence' ;
41- import { createWizardToolsServer , WIZARD_TOOL_NAMES } from '@agent /tools' ;
47+ import { createWizardToolsServer , WIZARD_TOOL_NAMES } from '. /tools' ;
4248import {
4349 createPreToolUseYaraHooks ,
4450 createPostToolUseYaraHooks ,
4551 prewarmYaraScanner ,
46- } from '@agent /yara-hooks' ;
52+ } from '. /yara-hooks' ;
4753import { createTriageLLMProvider } from './triage-provider' ;
4854import type { LLMProvider } from '@posthog/warlock' ;
4955import { assembleCommandments } from './runner/switchboard/commandments' ;
@@ -91,11 +97,8 @@ async function getSDKModule(): Promise<any> {
9197 * This ensures we use the SDK's bundled version rather than the user's installed Claude Code.
9298 */
9399function getClaudeCodeExecutablePath ( ) : string {
94- // Bare `require` is undefined in ESM (tsx dev runs) — fall back to createRequire.
95- const resolver =
96- typeof require !== 'undefined'
97- ? require
98- : createRequire ( process . argv [ 1 ] ?? `${ process . cwd ( ) } /` ) ;
100+ // ESM has no bare `require`: resolve from the entry script.
101+ const resolver = createRequire ( process . argv [ 1 ] ?? `${ process . cwd ( ) } /` ) ;
99102 // resolve finds the package's main entry, then we get cli.js from same dir
100103 const sdkPackagePath = resolver . resolve ( '@anthropic-ai/claude-agent-sdk' ) ;
101104 return path . join ( path . dirname ( sdkPackagePath ) , 'cli.js' ) ;
@@ -221,7 +224,7 @@ export type AgentConfig = {
221224 /** Schema for callers that consume a structured SDK result. */
222225 outputFormat ?: import ( '@anthropic-ai/claude-agent-sdk' ) . Options [ 'outputFormat' ] ;
223226 /** Bridge that drives the `wizard_ask` overlay. Omit in non-interactive hosts. */
224- askBridge ?: import ( '@agent /wizard-ask-bridge' ) . WizardAskBridge ;
227+ askBridge ?: import ( '. /wizard-ask-bridge' ) . WizardAskBridge ;
225228 /** Per-run cap on `wizard_ask` invocations. Defaults to 10. */
226229 askMaxQuestions ?: number ;
227230 /** Extra tools added on top of BASE_ALLOWED_TOOLS for this run. */
@@ -239,7 +242,7 @@ export type AgentConfig = {
239242 * flag routes the run here; threaded into wizard-tools so the orchestrator
240243 * tools register.
241244 */
242- orchestrator ?: import ( '@agent /runner/sequence/orchestrator/queue-tools' ) . OrchestratorToolsContext ;
245+ orchestrator ?: import ( '. /runner/sequence/orchestrator/queue-tools' ) . OrchestratorToolsContext ;
243246 /**
244247 * Optional AIO capture — mirrors each assistant SDK message into the
245248 * authenticated project as `$ai_generation`. No-op instance when
@@ -417,6 +420,16 @@ export function buildAgentEnv(
417420// Re-export for backwards compatibility — canonical source is skill-install.ts
418421export { isSkillInstallCommand } from '@shared/skill-install' ;
419422
423+ /** A debug run's diagnostic line, as info log progress; a run without `debug` emits nothing. */
424+ function debugLine (
425+ emit : ProgressEmitter ,
426+ options : Pick < WizardRunOptions , 'debug' > ,
427+ ...args : unknown [ ]
428+ ) : void {
429+ if ( ! options . debug ) return ;
430+ emit ( { kind : 'log' , level : 'info' , message : formatLogLine ( ...args ) } ) ;
431+ }
432+
420433/**
421434 * Permission hook that allows only safe commands. Bash commands are gated by
422435 * the exact per-manager fence in bash-fence.ts (install/build/typecheck/lint
@@ -435,6 +448,8 @@ export function wizardCanUseTool(
435448 readOnly ?: boolean ;
436449 wizardAskPending ?: boolean ;
437450 disallowedTools ?: readonly string [ ] ;
451+ /** A debug run's line for each Bash decision. */
452+ onDebug ?: ( line : string ) => void ;
438453 } = { } ,
439454) :
440455 | { behavior : 'allow' ; updatedInput : Record < string , unknown > }
@@ -516,12 +531,14 @@ export function wizardCanUseTool(
516531 const decision = evaluateBashCommand ( command ) ;
517532 if ( decision . allowed ) {
518533 logToFile ( `Allowing bash command: ${ command } ` ) ;
519- debug ( `Allowing bash command: ${ command } ` ) ;
534+ context . onDebug ?. ( `Allowing bash command: ${ command } ` ) ;
520535 return { behavior : 'allow' , updatedInput : input } ;
521536 }
522537
523538 logToFile ( `Denying bash command (${ decision . analyticsReason } ): ${ command } ` ) ;
524- debug ( `Denying bash command (${ decision . analyticsReason } ): ${ command } ` ) ;
539+ context . onDebug ?.(
540+ `Denying bash command (${ decision . analyticsReason } ): ${ command } ` ,
541+ ) ;
525542 analytics . wizardCapture ( 'bash denied' , {
526543 reason : decision . analyticsReason ,
527544 command,
@@ -689,14 +706,12 @@ export async function initializeAgent(
689706 apiKeyPresent : ! ! config . posthogApiKey ,
690707 } ) ;
691708
692- if ( options . debug ) {
693- debug ( 'Agent config:' , {
694- workingDirectory : agentRunConfig . workingDirectory ,
695- posthogMcpUrl : config . posthogMcpUrl ,
696- gatewayUrl,
697- apiKeyPresent : ! ! config . posthogApiKey ,
698- } ) ;
699- }
709+ debugLine ( emit , options , 'Agent config:' , {
710+ workingDirectory : agentRunConfig . workingDirectory ,
711+ posthogMcpUrl : config . posthogMcpUrl ,
712+ gatewayUrl,
713+ apiKeyPresent : ! ! config . posthogApiKey ,
714+ } ) ;
700715
701716 // Pre-warm the warlock scanner (WASM init + rule compile) off the hook path
702717 // so the first tool-call scan doesn't pay cold-start under a hook timeout.
@@ -714,7 +729,7 @@ export async function initializeAgent(
714729 message : `Failed to initialize agent: ${ ( error as Error ) . message } ` ,
715730 } ) ;
716731 logToFile ( 'Agent initialization error:' , error ) ;
717- debug ( 'Agent initialization error:' , error ) ;
732+ debugLine ( emit , options , 'Agent initialization error:' , error ) ;
718733 throw error ;
719734 }
720735}
@@ -1181,6 +1196,7 @@ export async function runAgent(
11811196 readOnly : agentConfig . readOnly ,
11821197 wizardAskPending : agentConfig . getPendingQuestion ?.( ) != null ,
11831198 disallowedTools : agentConfig . disallowedTools ,
1199+ onDebug : ( line ) => debugLine ( emit , options , line ) ,
11841200 } ,
11851201 ) ;
11861202 logToFile ( 'canUseTool result:' , result ) ;
@@ -1204,9 +1220,7 @@ export async function runAgent(
12041220 // Capture stderr from CLI subprocess for debugging
12051221 stderr : ( data : string ) => {
12061222 logToFile ( 'CLI stderr:' , data ) ;
1207- if ( options . debug ) {
1208- debug ( 'CLI stderr:' , data ) ;
1209- }
1223+ debugLine ( emit , options , 'CLI stderr:' , data ) ;
12101224 } ,
12111225 // Stop hook: collect remark, then allow stop
12121226 hooks : {
@@ -1672,7 +1686,7 @@ export async function runAgent(
16721686 message : `Error: ${ ( error as Error ) . message } ` ,
16731687 } ) ;
16741688 logToFile ( 'Agent run failed:' , error ) ;
1675- debug ( 'Full error:' , error ) ;
1689+ debugLine ( emit , options , 'Full error:' , error ) ;
16761690 throw error ;
16771691 } finally {
16781692 agentConfig . signal ?. removeEventListener ( 'abort' , onExternalAbort ) ;
@@ -2042,9 +2056,7 @@ function handleSDKMessage(
20422056 } ;
20432057 logToFile ( `SDK Message: ${ message . type } ` , JSON . stringify ( message , null , 2 ) ) ;
20442058
2045- if ( options . debug ) {
2046- debug ( `SDK Message type: ${ message . type } ` ) ;
2047- }
2059+ debugLine ( emit , options , `SDK Message type: ${ message . type } ` ) ;
20482060
20492061 switch ( message . type ) {
20502062 case 'assistant' : {
@@ -2227,9 +2239,7 @@ function handleSDKMessage(
22272239
22282240 default :
22292241 // Log other message types for debugging
2230- if ( options . debug ) {
2231- debug ( `Unhandled message type: ${ message . type } ` ) ;
2232- }
2242+ debugLine ( emit , options , `Unhandled message type: ${ message . type } ` ) ;
22332243 break ;
22342244 }
22352245}
0 commit comments