@@ -209,7 +209,7 @@ exports.checkAvailability = async function () {
209209 * aiProgress, aiTextStream, aiToolEdit, aiError, aiComplete
210210 */
211211exports . sendPrompt = async function ( params ) {
212- const { prompt, projectPath, sessionAction, model, locale, selectionContext, images, envOverrides } = params ;
212+ const { prompt, projectPath, sessionAction, model, locale, selectionContext, images, envOverrides, permissionMode } = params ;
213213 const requestId = Date . now ( ) . toString ( 36 ) + Math . random ( ) . toString ( 36 ) . slice ( 2 , 7 ) ;
214214
215215 // Handle session
@@ -252,7 +252,7 @@ exports.sendPrompt = async function (params) {
252252 }
253253
254254 // Run the query asynchronously — don't await here so we return requestId immediately
255- _runQuery ( requestId , enrichedPrompt , projectPath , model , currentAbortController . signal , locale , images , envOverrides )
255+ _runQuery ( requestId , enrichedPrompt , projectPath , model , currentAbortController . signal , locale , images , envOverrides , permissionMode )
256256 . catch ( err => {
257257 console . error ( "[Phoenix AI] Query error:" , err ) ;
258258 } ) ;
@@ -370,7 +370,7 @@ exports.clearClarification = async function () {
370370/**
371371 * Internal: run a Claude SDK query and stream results back to the browser.
372372 */
373- async function _runQuery ( requestId , prompt , projectPath , model , signal , locale , images , envOverrides ) {
373+ async function _runQuery ( requestId , prompt , projectPath , model , signal , locale , images , envOverrides , permissionMode ) {
374374 let editCount = 0 ;
375375 let toolCounter = 0 ;
376376 let queryFn ;
@@ -455,7 +455,7 @@ async function _runQuery(requestId, prompt, projectPath, model, signal, locale,
455455 }
456456 } ,
457457 mcpServers : { "phoenix-editor" : editorMcpServer } ,
458- permissionMode : "acceptEdits" ,
458+ permissionMode : permissionMode || "acceptEdits" ,
459459 appendSystemPrompt :
460460 "When modifying an existing file, always prefer the Edit tool " +
461461 "(find-and-replace) instead of the Write tool. The Write tool should ONLY be used " +
@@ -496,6 +496,39 @@ async function _runQuery(requestId, prompt, projectPath, model, signal, locale,
496496 hooks : [
497497 async ( input ) => {
498498 console . log ( "[Phoenix AI] Intercepted Edit tool" ) ;
499+ // Plan file edits: capture content, write to disk, skip editor
500+ const editPath = ( input . tool_input . file_path || "" ) . replace ( / \\ / g, "/" ) ;
501+ if ( editPath . includes ( "/.claude/plans/" ) ) {
502+ try {
503+ let content = "" ;
504+ if ( fs . existsSync ( input . tool_input . file_path ) ) {
505+ content = fs . readFileSync ( input . tool_input . file_path , "utf8" ) ;
506+ }
507+ if ( input . tool_input . old_string && input . tool_input . new_string ) {
508+ content = content . replace ( input . tool_input . old_string , input . tool_input . new_string ) ;
509+ }
510+ const dir = path . dirname ( input . tool_input . file_path ) ;
511+ if ( ! fs . existsSync ( dir ) ) {
512+ fs . mkdirSync ( dir , { recursive : true } ) ;
513+ }
514+ fs . writeFileSync ( input . tool_input . file_path , content , "utf8" ) ;
515+ _lastPlanContent = content ;
516+ console . log ( "[Phoenix AI] Captured plan edit content:" , content . length + "ch" ) ;
517+ } catch ( err ) {
518+ console . warn ( "[Phoenix AI] Failed to edit plan file:" , err . message ) ;
519+ }
520+ let planReason = "Plan file updated." ;
521+ if ( _queuedClarification ) {
522+ planReason += CLARIFICATION_HINT ;
523+ }
524+ return {
525+ hookSpecificOutput : {
526+ hookEventName : "PreToolUse" ,
527+ permissionDecision : "deny" ,
528+ permissionDecisionReason : planReason
529+ }
530+ } ;
531+ }
499532 const myToolId = toolCounter ; // capture before any await
500533 const edit = {
501534 file : input . tool_input . file_path ,
0 commit comments