mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-23 12:30:43 -07:00
feat(hooks): Add a hooks.enabled setting. (#15933)
This commit is contained in:
@@ -512,7 +512,7 @@ describe('migrate command', () => {
|
||||
'\nMigration complete! Please review the migrated hooks in .gemini/settings.json',
|
||||
);
|
||||
expect(debugLoggerLogSpy).toHaveBeenCalledWith(
|
||||
'Note: Set tools.enableHooks to true in your settings to enable the hook system.',
|
||||
'Note: Set hooks.enabled to true in your settings to enable the hook system.',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -243,7 +243,7 @@ export async function handleMigrateFromClaude() {
|
||||
'\nMigration complete! Please review the migrated hooks in .gemini/settings.json',
|
||||
);
|
||||
debugLogger.log(
|
||||
'Note: Set tools.enableHooks to true in your settings to enable the hook system.',
|
||||
'Note: Set hooks.enabled to true in your settings to enable the hook system.',
|
||||
);
|
||||
} catch (error) {
|
||||
debugLogger.error(`Error saving migrated hooks: ${getErrorMessage(error)}`);
|
||||
|
||||
@@ -53,6 +53,7 @@ import { requestConsentNonInteractive } from './extensions/consent.js';
|
||||
import { promptForSetting } from './extensions/extensionSettings.js';
|
||||
import type { EventEmitter } from 'node:stream';
|
||||
import { runExitCleanup } from '../utils/cleanup.js';
|
||||
import { getEnableHooks } from './settingsSchema.js';
|
||||
|
||||
export interface CliArgs {
|
||||
query: string | undefined;
|
||||
@@ -291,7 +292,7 @@ export async function parseArguments(settings: Settings): Promise<CliArgs> {
|
||||
}
|
||||
|
||||
// Register hooks command if hooks are enabled
|
||||
if (settings?.tools?.enableHooks) {
|
||||
if (getEnableHooks(settings)) {
|
||||
yargsInstance.command(hooksCommand);
|
||||
}
|
||||
|
||||
@@ -722,7 +723,7 @@ export async function loadCliConfig(
|
||||
ptyInfo: ptyInfo?.name,
|
||||
modelConfigServiceConfig: settings.modelConfigs,
|
||||
// TODO: loading of hooks based on workspace trust
|
||||
enableHooks: settings.tools?.enableHooks,
|
||||
enableHooks: getEnableHooks(settings),
|
||||
hooks: settings.hooks || {},
|
||||
projectHooks: projectHooks || {},
|
||||
onModelChange: (model: string) => saveModelChange(loadedSettings, model),
|
||||
|
||||
@@ -64,6 +64,7 @@ import {
|
||||
type ExtensionSetting,
|
||||
} from './extensions/extensionSettings.js';
|
||||
import type { EventEmitter } from 'node:stream';
|
||||
import { getEnableHooks } from './settingsSchema.js';
|
||||
|
||||
interface ExtensionManagerParams {
|
||||
enabledExtensionOverrides?: string[];
|
||||
@@ -551,7 +552,7 @@ Would you like to attempt to install via "git clone" instead?`,
|
||||
.filter((contextFilePath) => fs.existsSync(contextFilePath));
|
||||
|
||||
let hooks: { [K in HookEventName]?: HookDefinition[] } | undefined;
|
||||
if (this.settings.tools?.enableHooks) {
|
||||
if (getEnableHooks(this.settings)) {
|
||||
hooks = await this.loadExtensionHooks(effectiveExtensionPath, {
|
||||
extensionPath: effectiveExtensionPath,
|
||||
workspacePath: this.workspaceDir,
|
||||
|
||||
@@ -750,8 +750,8 @@ describe('extension tests', () => {
|
||||
);
|
||||
|
||||
const settings = loadSettings(tempWorkspaceDir).merged;
|
||||
if (!settings.tools) settings.tools = {};
|
||||
settings.tools.enableHooks = true;
|
||||
if (!settings.hooks) settings.hooks = {};
|
||||
settings.hooks.enabled = true;
|
||||
|
||||
extensionManager = new ExtensionManager({
|
||||
workspaceDir: tempWorkspaceDir,
|
||||
@@ -771,7 +771,7 @@ describe('extension tests', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should not load hooks if enableHooks is false', async () => {
|
||||
it('should not load hooks if hooks.enabled is false', async () => {
|
||||
const extDir = createExtension({
|
||||
extensionsDir: userExtensionsDir,
|
||||
name: 'hook-extension-disabled',
|
||||
@@ -786,8 +786,8 @@ describe('extension tests', () => {
|
||||
);
|
||||
|
||||
const settings = loadSettings(tempWorkspaceDir).merged;
|
||||
if (!settings.tools) settings.tools = {};
|
||||
settings.tools.enableHooks = false;
|
||||
if (!settings.hooks) settings.hooks = {};
|
||||
settings.hooks.enabled = false;
|
||||
|
||||
extensionManager = new ExtensionManager({
|
||||
workspaceDir: tempWorkspaceDir,
|
||||
|
||||
@@ -1075,12 +1075,12 @@ const SETTINGS_SCHEMA = {
|
||||
},
|
||||
enableHooks: {
|
||||
type: 'boolean',
|
||||
label: 'Enable Hooks System',
|
||||
label: 'Enable Hooks System (Experimental)',
|
||||
category: 'Advanced',
|
||||
requiresRestart: true,
|
||||
default: false,
|
||||
default: true,
|
||||
description:
|
||||
'Enable the hooks system for intercepting and customizing Gemini CLI behavior. When enabled, hooks configured in settings will execute at appropriate lifecycle events (BeforeTool, AfterTool, BeforeModel, etc.). Requires MessageBus integration.',
|
||||
'Enables the hooks system experiment. When disabled, the hooks system is completely deactivated regardless of other settings.',
|
||||
showInDialog: false,
|
||||
},
|
||||
},
|
||||
@@ -1544,6 +1544,16 @@ const SETTINGS_SCHEMA = {
|
||||
'Hook configurations for intercepting and customizing agent behavior.',
|
||||
showInDialog: false,
|
||||
properties: {
|
||||
enabled: {
|
||||
type: 'boolean',
|
||||
label: 'Enable Hooks',
|
||||
category: 'Advanced',
|
||||
requiresRestart: false,
|
||||
default: false,
|
||||
description:
|
||||
'Canonical toggle for the hooks system. When disabled, no hooks will be executed.',
|
||||
showInDialog: false,
|
||||
},
|
||||
disabled: {
|
||||
type: 'array',
|
||||
label: 'Disabled Hooks',
|
||||
@@ -2057,3 +2067,9 @@ type InferSettings<T extends SettingsSchema> = {
|
||||
};
|
||||
|
||||
export type Settings = InferSettings<SettingsSchemaType>;
|
||||
|
||||
export function getEnableHooks(settings: Settings): boolean {
|
||||
return (
|
||||
(settings.tools?.enableHooks ?? true) && (settings.hooks?.enabled ?? false)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ describe('hooksCommand', () => {
|
||||
type: 'message',
|
||||
messageType: 'info',
|
||||
content:
|
||||
'Hook system is not enabled. Enable it in settings with tools.enableHooks',
|
||||
'Hook system is not enabled. Enable it in settings with hooks.enabled.',
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ async function panelAction(
|
||||
type: 'message',
|
||||
messageType: 'info',
|
||||
content:
|
||||
'Hook system is not enabled. Enable it in settings with tools.enableHooks',
|
||||
'Hook system is not enabled. Enable it in settings with hooks.enabled.',
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user