-
Notifications
You must be signed in to change notification settings - Fork 10.4k
feat: Granular Extension Hook Control #15620
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat: Granular Extension Hook Control #15620
Conversation
Summary of ChangesHello @AbdulTawabJuly, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a significant enhancement to the hook system, providing granular control over extension-contributed hooks. Users can now disable all hooks from a specific extension via a new configuration setting or an updated CLI command, without affecting other functionalities of that extension. This change improves user control and transparency by clearly labeling extension hooks in the UI and preventing 'Invalid hook event name' warnings by filtering configuration properties. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces granular control over extension hooks, allowing users to disable all hooks from a specific extension. The changes include a new setting, updates to the /hooks command to support extension-based enable/disable actions, and UI improvements to show hook sources. The implementation is solid and includes good test coverage. However, I've found a high-severity issue where enabling an extension's hooks can lead to an inconsistent state for individually disabled hooks, which I've detailed in a comment.
| let count = 0; | ||
| for (const entry of this.entries) { | ||
| if (entry.extensionName === extensionName) { | ||
| entry.enabled = enabled; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current implementation of setExtensionHooksEnabled can lead to an inconsistent state between the in-memory representation of enabled hooks and the state that would be loaded from settings on a restart.
When enabling all hooks for an extension (enabled: true), this function sets entry.enabled = true for all hooks from that extension. This overrides any individual hooks that are explicitly disabled in the hooks.disabled setting.
However, upon application restart, HookRegistry.initialize() will re-process the settings. processHookDefinition correctly considers both disabledHooks and extensionHooksDisabled. A hook that is in disabledHooks will be correctly marked as enabled: false, even if its extension is not in extensionHooksDisabled.
This means a hook that was individually disabled, then enabled as part of its extension, will be enabled for the current session but disabled again after a restart. This is unpredictable behavior for the user.
To fix this, setExtensionHooksEnabled should respect the disabledHooks setting when enabling hooks.
A similar issue exists in the setHookEnabled method, which is not part of this pull request but should be updated to respect extensionHooksDisabled for consistency.
| entry.enabled = enabled; | |
| entry.enabled = enabled && !(this.config.getDisabledHooks() || []).includes(this.getHookName(entry)); |
Summary
Implements granular extension hook control, allowing users to disable all hooks from specific extensions while keeping other extension features (like MCP tools) operational.
Details
What's New
hooks.extensionHooksDisabled: ["extension-name"]or via the/hookscommand with wildcard syntaxextension/*.Changes Made
extensionNametracking to hook entries andsetExtensionHooksEnabled()method for runtime control.setExtensionHooksEnabled()for public use.getExtensionHooksDisabled()method andextensionHooksDisabledfield.getHooks()andgetProjectHooks()to filter out config properties (disabled,extensionHooksDisabled) so only validHookEventNameenum values are processed.Related Issues
Fixes #15263
How to Validate
I created demo extensions with hooks and MCP tools since no existing extensions combine all three features.
To validate:
/hooksto view all registered hooks with their source extension labeled.demo-extensionhooks via/hooks disable extension/demo-extension./hooksagain to confirm the hooks are marked as disabled and produce no output.Pre-Merge Checklist