mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-21 10:34:35 -07:00
feat(hooks): add support for friendly names and descriptions (#15174)
This commit is contained in:
@@ -356,6 +356,18 @@ describe('SettingsSchema', () => {
|
||||
'Enable local and remote subagents. Warning: Experimental feature, uses YOLO mode for subagents',
|
||||
);
|
||||
});
|
||||
|
||||
it('should have name and description in hook definitions', () => {
|
||||
const hookDef = SETTINGS_SCHEMA_DEFINITIONS['HookDefinitionArray'];
|
||||
expect(hookDef).toBeDefined();
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const hookItemProperties = (hookDef as any).items.properties.hooks.items
|
||||
.properties;
|
||||
expect(hookItemProperties.name).toBeDefined();
|
||||
expect(hookItemProperties.name.type).toBe('string');
|
||||
expect(hookItemProperties.description).toBeDefined();
|
||||
expect(hookItemProperties.description.type).toBe('string');
|
||||
});
|
||||
});
|
||||
|
||||
it('has JSON schema definitions for every referenced ref', () => {
|
||||
|
||||
@@ -1891,6 +1891,10 @@ export const SETTINGS_SCHEMA_DEFINITIONS: Record<
|
||||
type: 'object',
|
||||
description: 'Individual hook configuration.',
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'Unique identifier for the hook.',
|
||||
},
|
||||
type: {
|
||||
type: 'string',
|
||||
description:
|
||||
@@ -1901,6 +1905,10 @@ export const SETTINGS_SCHEMA_DEFINITIONS: Record<
|
||||
description:
|
||||
'Shell command to execute. Receives JSON input via stdin and returns JSON output via stdout.',
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
description: 'A description of the hook.',
|
||||
},
|
||||
timeout: {
|
||||
type: 'number',
|
||||
description: 'Timeout in milliseconds for hook execution.',
|
||||
|
||||
@@ -309,6 +309,24 @@ describe('hooksCommand', () => {
|
||||
content: 'Failed to enable hook: Failed to save settings',
|
||||
});
|
||||
});
|
||||
|
||||
it('should complete hook names using friendly names', () => {
|
||||
const enableCmd = hooksCommand.subCommands!.find(
|
||||
(cmd) => cmd.name === 'enable',
|
||||
)!;
|
||||
|
||||
const hookEntry = createMockHook(
|
||||
'./hooks/test.sh',
|
||||
HookEventName.BeforeTool,
|
||||
true,
|
||||
);
|
||||
hookEntry.config.name = 'friendly-name';
|
||||
|
||||
mockHookSystem.getAllHooks.mockReturnValue([hookEntry]);
|
||||
|
||||
const completions = enableCmd.completion!(mockContext, 'frie');
|
||||
expect(completions).toContain('friendly-name');
|
||||
});
|
||||
});
|
||||
|
||||
describe('disable subcommand', () => {
|
||||
|
||||
@@ -213,7 +213,7 @@ function completeHookNames(
|
||||
* Get a display name for a hook
|
||||
*/
|
||||
function getHookDisplayName(hook: HookRegistryEntry): string {
|
||||
return hook.config.command || 'unknown-hook';
|
||||
return hook.config.name || hook.config.command || 'unknown-hook';
|
||||
}
|
||||
|
||||
const panelCommand: SlashCommand = {
|
||||
|
||||
@@ -9,7 +9,13 @@ import { Box, Text } from 'ink';
|
||||
|
||||
interface HooksListProps {
|
||||
hooks: ReadonlyArray<{
|
||||
config: { command?: string; type: string; timeout?: number };
|
||||
config: {
|
||||
command?: string;
|
||||
type: string;
|
||||
name?: string;
|
||||
description?: string;
|
||||
timeout?: number;
|
||||
};
|
||||
source: string;
|
||||
eventName: string;
|
||||
matcher?: string;
|
||||
@@ -50,7 +56,8 @@ export const HooksList: React.FC<HooksListProps> = ({ hooks }) => {
|
||||
</Text>
|
||||
<Box flexDirection="column" paddingLeft={2}>
|
||||
{eventHooks.map((hook, index) => {
|
||||
const hookName = hook.config.command || 'unknown';
|
||||
const hookName =
|
||||
hook.config.name || hook.config.command || 'unknown';
|
||||
const statusColor = hook.enabled ? 'green' : 'gray';
|
||||
const statusText = hook.enabled ? 'enabled' : 'disabled';
|
||||
|
||||
@@ -63,8 +70,14 @@ export const HooksList: React.FC<HooksListProps> = ({ hooks }) => {
|
||||
</Text>
|
||||
</Box>
|
||||
<Box paddingLeft={2} flexDirection="column">
|
||||
{hook.config.description && (
|
||||
<Text italic>{hook.config.description}</Text>
|
||||
)}
|
||||
<Text dimColor>
|
||||
Source: {hook.source}
|
||||
{hook.config.name &&
|
||||
hook.config.command &&
|
||||
` | Command: ${hook.config.command}`}
|
||||
{hook.matcher && ` | Matcher: ${hook.matcher}`}
|
||||
{hook.sequential && ` | Sequential`}
|
||||
{hook.config.timeout &&
|
||||
|
||||
Reference in New Issue
Block a user