@@ -38,6 +38,8 @@ interface SettingsState {
3838 cloudProvider : string ;
3939 cloudApiKey : string ;
4040 cloudModel : string ;
41+ // Tools
42+ disabledTools : string [ ] ;
4143}
4244
4345const DEFAULTS : SettingsState = {
@@ -72,6 +74,26 @@ const DEFAULTS: SettingsState = {
7274 cloudProvider : 'none' ,
7375 cloudApiKey : '' ,
7476 cloudModel : '' ,
77+ disabledTools : [
78+ 'delete_file' , 'rename_file' , 'copy_file' , 'create_directory' , 'get_file_info' ,
79+ 'open_file_in_editor' , 'diff_files' ,
80+ 'search_in_file' , 'replace_in_files' ,
81+ 'check_port' , 'install_packages' ,
82+ 'http_request' ,
83+ 'browser_fill_form' , 'browser_select_option' , 'browser_evaluate' ,
84+ 'browser_scroll' , 'browser_back' , 'browser_press_key' , 'browser_hover' ,
85+ 'browser_drag' , 'browser_screenshot' , 'browser_get_content' ,
86+ 'browser_get_url' , 'browser_get_links' , 'browser_tabs' ,
87+ 'browser_handle_dialog' , 'browser_console_messages' , 'browser_file_upload' ,
88+ 'browser_resize' , 'browser_wait' , 'browser_wait_for' , 'browser_close' ,
89+ 'git_status' , 'git_commit' , 'git_diff' , 'git_log' , 'git_branch' ,
90+ 'git_stash' , 'git_reset' ,
91+ 'analyze_error' ,
92+ 'undo_edit' , 'list_undoable' ,
93+ 'list_memories' ,
94+ 'write_scratchpad' , 'read_scratchpad' ,
95+ 'generate_image' ,
96+ ] ,
7597} ;
7698
7799const CLOUD_PROVIDERS = [
@@ -604,6 +626,96 @@ export const AdvancedSettingsPanel: React.FC = () => {
604626 < ToggleField label = "Format on Type" value = { settings . formatOnType } onChange = { v => update ( 'formatOnType' , v ) } />
605627 </ Section >
606628
629+ { /* ── Tools ───────────────────────────── */ }
630+ < Section title = "Tools" defaultOpen = { false } >
631+ < p className = "text-[10px] mb-2" style = { { color : 'var(--theme-foreground-muted)' } } >
632+ Toggle which tools the AI can use. Disabled tools are hidden from the model. { 66 - settings . disabledTools . length } /66 enabled.
633+ </ p >
634+ { ( ( ) => {
635+ const toolCategories : Record < string , string [ ] > = {
636+ 'File Operations' : [ 'read_file' , 'write_file' , 'edit_file' , 'append_to_file' , 'delete_file' , 'rename_file' , 'copy_file' , 'list_directory' , 'find_files' , 'create_directory' , 'get_project_structure' , 'get_file_info' , 'open_file_in_editor' , 'diff_files' ] ,
637+ 'Search' : [ 'grep_search' , 'search_in_file' , 'search_codebase' , 'replace_in_files' ] ,
638+ 'Terminal' : [ 'run_command' , 'check_port' , 'install_packages' ] ,
639+ 'Web' : [ 'web_search' , 'fetch_webpage' , 'http_request' ] ,
640+ 'Browser' : [ 'browser_navigate' , 'browser_snapshot' , 'browser_click' , 'browser_type' , 'browser_fill_form' , 'browser_select_option' , 'browser_evaluate' , 'browser_scroll' , 'browser_back' , 'browser_press_key' , 'browser_hover' , 'browser_drag' , 'browser_screenshot' , 'browser_get_content' , 'browser_get_url' , 'browser_get_links' , 'browser_tabs' , 'browser_handle_dialog' , 'browser_console_messages' , 'browser_file_upload' , 'browser_resize' , 'browser_wait' , 'browser_wait_for' , 'browser_close' ] ,
641+ 'Git' : [ 'git_status' , 'git_commit' , 'git_diff' , 'git_log' , 'git_branch' , 'git_stash' , 'git_reset' ] ,
642+ 'Code Analysis' : [ 'analyze_error' ] ,
643+ 'Undo' : [ 'undo_edit' , 'list_undoable' ] ,
644+ 'Memory' : [ 'save_memory' , 'get_memory' , 'list_memories' ] ,
645+ 'Planning' : [ 'write_todos' , 'update_todo' ] ,
646+ 'Scratchpad' : [ 'write_scratchpad' , 'read_scratchpad' ] ,
647+ 'Image Generation' : [ 'generate_image' ] ,
648+ } ;
649+ return (
650+ < div className = "space-y-0.5 max-h-[300px] overflow-auto" >
651+ { Object . entries ( toolCategories ) . map ( ( [ category , tools ] ) => {
652+ const enabledInCat = tools . filter ( t => ! settings . disabledTools . includes ( t ) ) . length ;
653+ const allEnabled = enabledInCat === tools . length ;
654+ return (
655+ < details key = { category } className = "group" >
656+ < summary className = "flex items-center gap-1.5 py-0.5 cursor-pointer select-none text-[10px] list-none" style = { { color : 'var(--theme-foreground)' } } >
657+ < span style = { { transition : 'transform 0.15s' , display : 'inline-block' , transform : 'rotate(-90deg)' } } className = "group-open:!rotate-0" >
658+ < ChevronDown size = { 10 } />
659+ </ span >
660+ < span className = "flex-1" > { category } < span style = { { color : 'var(--theme-foreground-muted)' } } > ({ enabledInCat } /{ tools . length } )</ span > </ span >
661+ < button
662+ onClick = { ( e ) => {
663+ e . preventDefault ( ) ;
664+ e . stopPropagation ( ) ;
665+ if ( allEnabled ) {
666+ update ( 'disabledTools' , [ ...new Set ( [ ...settings . disabledTools , ...tools ] ) ] ) ;
667+ } else {
668+ update ( 'disabledTools' , settings . disabledTools . filter ( t => ! tools . includes ( t ) ) ) ;
669+ }
670+ } }
671+ className = "text-[9px] px-1.5 py-0 rounded transition-colors"
672+ style = { { color : allEnabled ? 'var(--theme-foreground-muted)' : 'var(--theme-accent)' , backgroundColor : 'transparent' } }
673+ >
674+ { allEnabled ? 'Disable all' : 'Enable all' }
675+ </ button >
676+ </ summary >
677+ < div className = "pl-4 pb-1 space-y-0" >
678+ { tools . map ( toolName => {
679+ const isEnabled = ! settings . disabledTools . includes ( toolName ) ;
680+ return (
681+ < label key = { toolName } className = "flex items-center gap-1.5 py-[1px] cursor-pointer text-[10px] rounded px-1 -mx-1" style = { { color : isEnabled ? 'var(--theme-foreground)' : 'var(--theme-foreground-muted)' } } >
682+ < div
683+ onClick = { ( ) => {
684+ const newDisabled = isEnabled
685+ ? [ ...settings . disabledTools , toolName ]
686+ : settings . disabledTools . filter ( t => t !== toolName ) ;
687+ update ( 'disabledTools' , newDisabled ) ;
688+ } }
689+ className = "w-[26px] h-[13px] rounded-full relative transition-colors flex-shrink-0 cursor-pointer"
690+ style = { { backgroundColor : isEnabled ? 'var(--theme-accent)' : 'var(--theme-bg-tertiary, #3c3c3c)' } }
691+ >
692+ < div
693+ className = "w-[9px] h-[9px] rounded-full bg-white absolute top-[2px] transition-all"
694+ style = { { left : isEnabled ? '15px' : '2px' } }
695+ />
696+ </ div >
697+ < span > { toolName } </ span >
698+ </ label >
699+ ) ;
700+ } ) }
701+ </ div >
702+ </ details >
703+ ) ;
704+ } ) }
705+ { settings . disabledTools . length > 0 && (
706+ < button
707+ onClick = { ( ) => update ( 'disabledTools' , [ ] ) }
708+ className = "text-[9px] hover:underline mt-1 cursor-pointer"
709+ style = { { color : 'var(--theme-accent)' } }
710+ >
711+ Enable all tools
712+ </ button >
713+ ) }
714+ </ div >
715+ ) ;
716+ } ) ( ) }
717+ </ Section >
718+
607719 { /* Footer spacer */ }
608720 < div className = "h-4" />
609721 </ div >
0 commit comments