@@ -263,7 +263,7 @@ private function registerAbilities(): void {
263263 'description ' => 'Explicitly allow reading from a stale, diverged, detached, or otherwise unsafe primary checkout. Worktree reads are unaffected. ' ,
264264 ),
265265 ),
266- 'required ' => array ( 'path ' ),
266+ 'required ' => array ( 'repo ' , ' path ' ),
267267 ),
268268 'output_schema ' => array (
269269 'type ' => 'object ' ,
@@ -304,7 +304,7 @@ private function registerAbilities(): void {
304304 'description ' => 'Explicitly allow listing a stale, diverged, detached, or otherwise unsafe primary checkout. Worktree reads are unaffected. ' ,
305305 ),
306306 ),
307- 'required ' => array (),
307+ 'required ' => array ( ' repo ' ),
308308 ),
309309 'output_schema ' => array (
310310 'type ' => 'object ' ,
@@ -369,7 +369,7 @@ private function registerAbilities(): void {
369369 'description ' => 'Explicitly allow grepping a stale, diverged, detached, or otherwise unsafe primary checkout. Worktree reads are unaffected. ' ,
370370 ),
371371 ),
372- 'required ' => array ( 'pattern ' ),
372+ 'required ' => array ( 'repo ' , ' pattern ' ),
373373 ),
374374 'output_schema ' => array (
375375 'type ' => 'object ' ,
@@ -575,8 +575,12 @@ private function registerAbilities(): void {
575575 'type ' => 'string ' ,
576576 'description ' => 'File content to write. ' ,
577577 ),
578+ 'allow_primary_mutation ' => array (
579+ 'type ' => 'boolean ' ,
580+ 'description ' => 'Permit mutation on the primary checkout (default false). Worktrees are always allowed. ' ,
581+ ),
578582 ),
579- 'required ' => array ( 'path ' , 'content ' ),
583+ 'required ' => array ( 'repo ' , ' path ' , 'content ' ),
580584 ),
581585 'output_schema ' => array (
582586 'type ' => 'object ' ,
@@ -638,8 +642,12 @@ private function registerAbilities(): void {
638642 'type ' => 'boolean ' ,
639643 'description ' => 'Replace all occurrences (default false). ' ,
640644 ),
645+ 'allow_primary_mutation ' => array (
646+ 'type ' => 'boolean ' ,
647+ 'description ' => 'Permit mutation on the primary checkout (default false). Worktrees are always allowed. ' ,
648+ ),
641649 ),
642- 'required ' => array ( 'path ' ),
650+ 'required ' => array ( 'repo ' , ' path ' ),
643651 ),
644652 'output_schema ' => array (
645653 'type ' => 'object ' ,
@@ -951,7 +959,7 @@ private function registerAbilities(): void {
951959 'description ' => 'Permit mutation on the primary checkout (default false). Worktrees are always allowed. ' ,
952960 ),
953961 ),
954- 'required ' => array ( 'path ' ),
962+ 'required ' => array ( 'repo ' , ' path ' ),
955963 ),
956964 'output_schema ' => array (
957965 'type ' => 'object ' ,
@@ -2587,9 +2595,13 @@ public static function showRepo( array $input ): array|\WP_Error {
25872595 * @return array Result.
25882596 */
25892597 public static function readFile ( array $ input ): array |\WP_Error {
2590- $ input = self ::normalize_mounted_workspace_path_input ($ input , array ( 'repo ' ));
2591- $ workspace = new Workspace ();
2592- $ reader = new WorkspaceReader ($ workspace );
2598+ $ input = self ::normalize_mounted_workspace_path_input ($ input , array ( 'repo ' ));
2599+ $ workspace = new Workspace ();
2600+ $ handle_check = $ workspace ->require_explicit_workspace_handle ($ input ['repo ' ] ?? '' );
2601+ if ( is_wp_error ($ handle_check ) ) {
2602+ return $ handle_check ;
2603+ }
2604+ $ reader = new WorkspaceReader ($ workspace );
25932605 if ( RemoteWorkspaceBackend::should_handle () && null !== self ::showLocalWorkspaceHandleIfPresent ($ workspace , (string ) ( $ input ['repo ' ] ?? '' )) ) {
25942606 return $ reader ->read_file (
25952607 $ input ['repo ' ] ?? '' ,
@@ -2631,9 +2643,13 @@ public static function readFile( array $input ): array|\WP_Error {
26312643 * @return array Result.
26322644 */
26332645 public static function listDirectory ( array $ input ): array |\WP_Error {
2634- $ input = self ::normalize_mounted_workspace_path_input ($ input , array ( 'repo ' ));
2635- $ workspace = new Workspace ();
2636- $ reader = new WorkspaceReader ($ workspace );
2646+ $ input = self ::normalize_mounted_workspace_path_input ($ input , array ( 'repo ' ));
2647+ $ workspace = new Workspace ();
2648+ $ handle_check = $ workspace ->require_explicit_workspace_handle ($ input ['repo ' ] ?? '' );
2649+ if ( is_wp_error ($ handle_check ) ) {
2650+ return $ handle_check ;
2651+ }
2652+ $ reader = new WorkspaceReader ($ workspace );
26372653 if ( RemoteWorkspaceBackend::should_handle () && null !== self ::showLocalWorkspaceHandleIfPresent ($ workspace , (string ) ( $ input ['repo ' ] ?? '' )) ) {
26382654 return $ reader ->list_directory (
26392655 $ input ['repo ' ] ?? '' ,
@@ -2666,9 +2682,13 @@ public static function listDirectory( array $input ): array|\WP_Error {
26662682 * @return array Result.
26672683 */
26682684 public static function grepFiles ( array $ input ): array |\WP_Error {
2669- $ input = self ::normalize_mounted_workspace_path_input ($ input , array ( 'repo ' ));
2670- $ workspace = new Workspace ();
2671- $ reader = new WorkspaceReader ($ workspace );
2685+ $ input = self ::normalize_mounted_workspace_path_input ($ input , array ( 'repo ' ));
2686+ $ workspace = new Workspace ();
2687+ $ handle_check = $ workspace ->require_explicit_workspace_handle ($ input ['repo ' ] ?? '' );
2688+ if ( is_wp_error ($ handle_check ) ) {
2689+ return $ handle_check ;
2690+ }
2691+ $ reader = new WorkspaceReader ($ workspace );
26722692 if ( RemoteWorkspaceBackend::should_handle () && null !== self ::showLocalWorkspaceHandleIfPresent ($ workspace , (string ) ( $ input ['repo ' ] ?? '' )) ) {
26732693 return $ reader ->grep (
26742694 $ input ['repo ' ] ?? '' ,
@@ -2958,7 +2978,13 @@ public static function removeRepo( array $input ): array|\WP_Error {
29582978 * @return array Result.
29592979 */
29602980 public static function writeFile ( array $ input ): array |\WP_Error {
2961- $ input = self ::normalize_mounted_workspace_path_input ($ input , array ( 'repo ' ));
2981+ $ input = self ::normalize_mounted_workspace_path_input ($ input , array ( 'repo ' ));
2982+ $ workspace = new Workspace ();
2983+ $ handle_check = $ workspace ->ensure_workspace_mutation_allowed ($ input ['repo ' ] ?? '' , ! empty ($ input ['allow_primary_mutation ' ]));
2984+ if ( is_wp_error ($ handle_check ) ) {
2985+ return $ handle_check ;
2986+ }
2987+
29622988 if ( RemoteWorkspaceBackend::should_handle () ) {
29632989 $ result = ( new RemoteWorkspaceBackend () )->write_file (
29642990 $ input ['repo ' ] ?? '' ,
@@ -2968,13 +2994,13 @@ public static function writeFile( array $input ): array|\WP_Error {
29682994 return self ::decorate_remote_workspace_result ('write_file ' , $ result );
29692995 }
29702996
2971- $ workspace = new Workspace ();
2972- $ writer = new WorkspaceWriter ($ workspace );
2997+ $ writer = new WorkspaceWriter ($ workspace );
29732998
29742999 return $ writer ->write_file (
29753000 $ input ['repo ' ] ?? '' ,
29763001 $ input ['path ' ] ?? '' ,
2977- $ input ['content ' ] ?? ''
3002+ $ input ['content ' ] ?? '' ,
3003+ ! empty ($ input ['allow_primary_mutation ' ])
29783004 );
29793005 }
29803006
@@ -2985,7 +3011,12 @@ public static function writeFile( array $input ): array|\WP_Error {
29853011 * @return array Result.
29863012 */
29873013 public static function editFile ( array $ input ): array |\WP_Error {
2988- $ input = self ::normalize_mounted_workspace_path_input ($ input , array ( 'repo ' ));
3014+ $ input = self ::normalize_mounted_workspace_path_input ($ input , array ( 'repo ' ));
3015+ $ workspace = new Workspace ();
3016+ $ handle_check = $ workspace ->ensure_workspace_mutation_allowed ($ input ['repo ' ] ?? '' , ! empty ($ input ['allow_primary_mutation ' ]));
3017+ if ( is_wp_error ($ handle_check ) ) {
3018+ return $ handle_check ;
3019+ }
29893020 $ old_string = (string ) ( $ input ['old_string ' ] ?? $ input ['search ' ] ?? $ input ['old ' ] ?? '' );
29903021 $ new_string = (string ) ( $ input ['new_string ' ] ?? $ input ['replace ' ] ?? $ input ['new ' ] ?? '' );
29913022
@@ -3008,15 +3039,15 @@ public static function editFile( array $input ): array|\WP_Error {
30083039 return self ::decorate_remote_workspace_result ('edit_file ' , $ result );
30093040 }
30103041
3011- $ workspace = new Workspace ();
3012- $ writer = new WorkspaceWriter ($ workspace );
3042+ $ writer = new WorkspaceWriter ($ workspace );
30133043
30143044 return $ writer ->edit_file (
30153045 $ input ['repo ' ] ?? '' ,
30163046 $ input ['path ' ] ?? '' ,
30173047 $ old_string ,
30183048 $ new_string ,
3019- ! empty ($ input ['replace_all ' ])
3049+ ! empty ($ input ['replace_all ' ]),
3050+ ! empty ($ input ['allow_primary_mutation ' ])
30203051 );
30213052 }
30223053
0 commit comments