From ffbe0971329916e2be1e52a23b2c6857c51fe00e Mon Sep 17 00:00:00 2001 From: Dave Page Date: Tue, 10 Mar 2026 14:33:04 +0000 Subject: [PATCH] Fixed an issue where AI features are visible in the UI even when LLM_ENABLED is set to False --- docs/en_US/release_notes_9_14.rst | 1 + web/pgadmin/browser/__init__.py | 1 + .../browser/templates/browser/js/utils.js | 3 +++ web/pgadmin/llm/__init__.py | 4 ++++ web/pgadmin/llm/static/js/ai_tools.js | 18 ++++++++++++++---- .../js/components/QueryToolComponent.jsx | 8 ++++---- 6 files changed, 27 insertions(+), 8 deletions(-) diff --git a/docs/en_US/release_notes_9_14.rst b/docs/en_US/release_notes_9_14.rst index f841dcd5cd5..8ef4835233e 100644 --- a/docs/en_US/release_notes_9_14.rst +++ b/docs/en_US/release_notes_9_14.rst @@ -30,4 +30,5 @@ Bug fixes | `Issue #9279 `_ - Fixed an issue where OAuth2 authentication fails with 'object has no attribute' if OAUTH2_AUTO_CREATE_USER is False. | `Issue #9392 `_ - Ensure that the Geometry Viewer refreshes when re-running queries or switching geometry columns, preventing stale data from being displayed. + | `Issue #9709 `_ - Fixed an issue where AI features (AI Assistant tab, AI Reports menus, and AI Preferences) were visible in the UI even when LLM_ENABLED is set to False. | `Issue #9721 `_ - Fixed an issue where permissions page is not completely accessible on full scroll. diff --git a/web/pgadmin/browser/__init__.py b/web/pgadmin/browser/__init__.py index 01cf716555c..1ef3f537d5d 100644 --- a/web/pgadmin/browser/__init__.py +++ b/web/pgadmin/browser/__init__.py @@ -538,6 +538,7 @@ def utils(): "Administrator") else restricted_shared_storage_list, enable_server_passexec_cmd=config.ENABLE_SERVER_PASS_EXEC_CMD, max_server_tags_allowed=config.MAX_SERVER_TAGS_ALLOWED, + llm_enabled=config.LLM_ENABLED, ), 200) response.headers['Content-Type'] = MIMETYPE_APP_JS response.headers['Cache-Control'] = NO_CACHE_CONTROL diff --git a/web/pgadmin/browser/templates/browser/js/utils.js b/web/pgadmin/browser/templates/browser/js/utils.js index 363759f34e0..d8996f0dafa 100644 --- a/web/pgadmin/browser/templates/browser/js/utils.js +++ b/web/pgadmin/browser/templates/browser/js/utils.js @@ -72,6 +72,9 @@ define('pgadmin.browser.utils', /* Enable server password exec command */ pgAdmin['enable_server_passexec_cmd'] = '{{enable_server_passexec_cmd}}'; + /* LLM/AI features enabled */ + pgAdmin['llm_enabled'] = '{{llm_enabled}}' == 'True'; + // Define list of nodes on which Query tool option doesn't appears let unsupported_nodes = pgAdmin.unsupported_nodes = [ 'server_group', 'server', 'coll-tablespace', 'tablespace', diff --git a/web/pgadmin/llm/__init__.py b/web/pgadmin/llm/__init__.py index 6bc2549750a..d983d68fd68 100644 --- a/web/pgadmin/llm/__init__.py +++ b/web/pgadmin/llm/__init__.py @@ -45,6 +45,10 @@ def register_preferences(self): """ Register preferences for LLM providers. """ + # Don't register AI preferences if LLM is disabled at system level + if not getattr(config, 'LLM_ENABLED', False): + return + self.preference = Preferences('ai', gettext('AI')) # Default Provider Setting diff --git a/web/pgadmin/llm/static/js/ai_tools.js b/web/pgadmin/llm/static/js/ai_tools.js index 2fdb79b2fed..b259fb5b202 100644 --- a/web/pgadmin/llm/static/js/ai_tools.js +++ b/web/pgadmin/llm/static/js/ai_tools.js @@ -10,6 +10,7 @@ import AIReport from './AIReport'; import { AllPermissionTypes, BROWSER_PANELS } from '../../../browser/static/js/constants'; import getApiInstance from '../../../static/js/api_instance'; +import MainMenuFactory from '../../../browser/static/js/MainMenuFactory'; import url_for from 'sources/url_for'; // AI Reports Module @@ -36,9 +37,14 @@ define([ this.initialized = true; - // Check LLM status + // Check LLM status and only register menus if enabled this.checkLLMStatus(); + return this; + }, + + // Register AI Reports menus + registerMenus: function() { // Register AI Reports menu category pgBrowser.add_menu_category({ name: 'ai_tools', @@ -158,11 +164,9 @@ define([ } pgBrowser.add_menus(menus); - - return this; }, - // Check if LLM is configured + // Check if LLM is configured, register menus only if system-enabled checkLLMStatus: function() { const api = getApiInstance(); api.get(url_for('llm.status')) @@ -172,6 +176,12 @@ define([ this.llmSystemEnabled = res.data.data?.system_enabled || false; } this.llmStatusChecked = true; + + // Only register menus if LLM is enabled at system level + if (this.llmSystemEnabled) { + this.registerMenus(); + MainMenuFactory.createMainMenus(); + } }) .catch(() => { this.llmEnabled = false; diff --git a/web/pgadmin/tools/sqleditor/static/js/components/QueryToolComponent.jsx b/web/pgadmin/tools/sqleditor/static/js/components/QueryToolComponent.jsx index 0468825e4ea..f19eb97f09d 100644 --- a/web/pgadmin/tools/sqleditor/static/js/components/QueryToolComponent.jsx +++ b/web/pgadmin/tools/sqleditor/static/js/components/QueryToolComponent.jsx @@ -233,7 +233,7 @@ export default function QueryToolComponent({params, pgWindow, pgAdmin, selectedN tabs: [ LayoutDocker.getPanel({id: PANELS.QUERY, title: gettext('Query'), content: setSelectedText(text)} setQtStatePartial={setQtStatePartial}/>}), LayoutDocker.getPanel({id: PANELS.HISTORY, title: gettext('Query History'), content: }), - LayoutDocker.getPanel({id: PANELS.AI_ASSISTANT, title: gettext('AI Assistant'), content: }), + ...(pgAdmin.llm_enabled ? [LayoutDocker.getPanel({id: PANELS.AI_ASSISTANT, title: gettext('AI Assistant'), content: })] : []), ], }, { @@ -442,7 +442,7 @@ export default function QueryToolComponent({params, pgWindow, pgAdmin, selectedN eventBus.current.registerListener(QUERY_TOOL_EVENTS.REINIT_QT_CONNECTION, initializeQueryTool); eventBus.current.registerListener(QUERY_TOOL_EVENTS.FOCUS_PANEL, (qtPanelId)=>{ - docker.current.focus(qtPanelId); + docker.current?.focus(qtPanelId); }); eventBus.current.registerListener(QUERY_TOOL_EVENTS.SET_CONNECTION_STATUS, (status)=>{ @@ -464,9 +464,9 @@ export default function QueryToolComponent({params, pgWindow, pgAdmin, selectedN if(qtPanelId == currentTabId) { setQtStatePartial({is_visible: true}); - if(docker.current.isTabVisible(PANELS.QUERY)) { + if(docker.current?.isTabVisible(PANELS.QUERY)) { docker.current.focus(PANELS.QUERY); - } else if(docker.current.isTabVisible(PANELS.HISTORY)) { + } else if(docker.current?.isTabVisible(PANELS.HISTORY)) { docker.current.focus(PANELS.HISTORY); }