| |
| |
| |
| |
| |
|
|
| import { |
| SettingScope, |
| isLoadableSettingScope, |
| type LoadedSettings, |
| } from '../config/settings.js'; |
| import { getErrorMessage } from '@google/gemini-cli-core'; |
| import type { ModifiedScope } from './skillSettings.js'; |
|
|
| export type HookActionStatus = 'success' | 'no-op' | 'error'; |
|
|
| |
| |
| |
| export interface HookActionResult { |
| status: HookActionStatus; |
| hookName: string; |
| action: 'enable' | 'disable'; |
| |
| modifiedScopes: ModifiedScope[]; |
| |
| alreadyInStateScopes: ModifiedScope[]; |
| |
| error?: string; |
| } |
|
|
| |
| |
| |
| export function enableHook( |
| settings: LoadedSettings, |
| hookName: string, |
| ): HookActionResult { |
| const writableScopes = [SettingScope.Workspace, SettingScope.User]; |
| const foundInDisabledScopes: ModifiedScope[] = []; |
| const alreadyEnabledScopes: ModifiedScope[] = []; |
|
|
| for (const scope of writableScopes) { |
| if (isLoadableSettingScope(scope)) { |
| const scopePath = settings.forScope(scope).path; |
| const scopeDisabled = |
| settings.forScope(scope).settings.hooksConfig?.disabled; |
| if (scopeDisabled?.includes(hookName)) { |
| foundInDisabledScopes.push({ scope, path: scopePath }); |
| } else { |
| alreadyEnabledScopes.push({ scope, path: scopePath }); |
| } |
| } |
| } |
|
|
| if (foundInDisabledScopes.length === 0) { |
| return { |
| status: 'no-op', |
| hookName, |
| action: 'enable', |
| modifiedScopes: [], |
| alreadyInStateScopes: alreadyEnabledScopes, |
| }; |
| } |
|
|
| const modifiedScopes: ModifiedScope[] = []; |
| try { |
| for (const { scope, path } of foundInDisabledScopes) { |
| if (isLoadableSettingScope(scope)) { |
| const currentScopeDisabled = |
| settings.forScope(scope).settings.hooksConfig?.disabled ?? []; |
| const newDisabled = currentScopeDisabled.filter( |
| (name) => name !== hookName, |
| ); |
| settings.setValue(scope, 'hooksConfig.disabled', newDisabled); |
| modifiedScopes.push({ scope, path }); |
| } |
| } |
| } catch (error) { |
| return { |
| status: 'error', |
| hookName, |
| action: 'enable', |
| modifiedScopes, |
| alreadyInStateScopes: alreadyEnabledScopes, |
| error: `Failed to enable hook: ${getErrorMessage(error)}`, |
| }; |
| } |
|
|
| return { |
| status: 'success', |
| hookName, |
| action: 'enable', |
| modifiedScopes, |
| alreadyInStateScopes: alreadyEnabledScopes, |
| }; |
| } |
|
|
| |
| |
| |
| export function disableHook( |
| settings: LoadedSettings, |
| hookName: string, |
| scope: SettingScope, |
| ): HookActionResult { |
| if (!isLoadableSettingScope(scope)) { |
| return { |
| status: 'error', |
| hookName, |
| action: 'disable', |
| modifiedScopes: [], |
| alreadyInStateScopes: [], |
| error: `Invalid settings scope: ${scope}`, |
| }; |
| } |
|
|
| const scopePath = settings.forScope(scope).path; |
| const currentScopeDisabled = |
| settings.forScope(scope).settings.hooksConfig?.disabled ?? []; |
|
|
| if (currentScopeDisabled.includes(hookName)) { |
| return { |
| status: 'no-op', |
| hookName, |
| action: 'disable', |
| modifiedScopes: [], |
| alreadyInStateScopes: [{ scope, path: scopePath }], |
| }; |
| } |
|
|
| |
| const otherScope = |
| scope === SettingScope.Workspace |
| ? SettingScope.User |
| : SettingScope.Workspace; |
| const alreadyDisabledInOther: ModifiedScope[] = []; |
|
|
| if (isLoadableSettingScope(otherScope)) { |
| const otherScopeDisabled = |
| settings.forScope(otherScope).settings.hooksConfig?.disabled; |
| if (otherScopeDisabled?.includes(hookName)) { |
| alreadyDisabledInOther.push({ |
| scope: otherScope, |
| path: settings.forScope(otherScope).path, |
| }); |
| } |
| } |
|
|
| const newDisabled = [...currentScopeDisabled, hookName]; |
| settings.setValue(scope, 'hooksConfig.disabled', newDisabled); |
|
|
| return { |
| status: 'success', |
| hookName, |
| action: 'disable', |
| modifiedScopes: [{ scope, path: scopePath }], |
| alreadyInStateScopes: alreadyDisabledInOther, |
| }; |
| } |
|
|