This is an automated email from the ASF dual-hosted git repository.

kaxil pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new b1ce1cac7f5 Fix Common AI Model tab not loading on Airflow 3.4 (#74898)
b1ce1cac7f5 is described below

commit b1ce1cac7f53aae9385637dad8e24ffa159876d4
Author: Kaxil Naik <[email protected]>
AuthorDate: Sat Oct 17 13:54:48 2026 +0100

    Fix Common AI Model tab not loading on Airflow 3.4 (#74898)
    
    The AI Model React app scoped itself with an 'operator_names' applies_to
    key, which names no TaskInstanceResponse field. Since core started
    rejecting such paths, the api-server withholds the app and the tab never
    appears. Use the 'operator_name' field instead.
---
 .../airflow/providers/common/ai/plugins/model_panel.py |  2 +-
 .../tests/unit/common/ai/plugins/test_model_panel.py   | 18 +++++++++++++++++-
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git 
a/providers/common/ai/src/airflow/providers/common/ai/plugins/model_panel.py 
b/providers/common/ai/src/airflow/providers/common/ai/plugins/model_panel.py
index 966cd3acc4f..f3a4295cbf7 100644
--- a/providers/common/ai/src/airflow/providers/common/ai/plugins/model_panel.py
+++ b/providers/common/ai/src/airflow/providers/common/ai/plugins/model_panel.py
@@ -86,7 +86,7 @@ class ModelPanelPlugin(AirflowPlugin):
                 # class name and the decorator's display name, since 
TaskInstance falls
                 # back to the class name when there's no custom_operator_name.
                 "applies_to": {
-                    "operator_names": [
+                    "operator_name": [
                         "LLMOperator",
                         "AgentOperator",
                         "@task.llm",
diff --git 
a/providers/common/ai/tests/unit/common/ai/plugins/test_model_panel.py 
b/providers/common/ai/tests/unit/common/ai/plugins/test_model_panel.py
index 8c27a43cd70..94c0363da14 100644
--- a/providers/common/ai/tests/unit/common/ai/plugins/test_model_panel.py
+++ b/providers/common/ai/tests/unit/common/ai/plugins/test_model_panel.py
@@ -16,13 +16,17 @@
 # under the License.
 from __future__ import annotations
 
+import copy
+
 import pytest
 
+from tests_common.test_utils.mock_plugins import mock_plugin_manager
 from tests_common.test_utils.version_compat import AIRFLOW_V_3_1_PLUS, 
AIRFLOW_V_3_4_PLUS
 
 if not AIRFLOW_V_3_1_PLUS:
     pytest.skip("The AI Model panel is only compatible with Airflow >= 3.1.0", 
allow_module_level=True)
 
+from airflow import plugins_manager
 from airflow.providers.common.ai.decorators.agent import 
_AgentDecoratedOperator
 from airflow.providers.common.ai.decorators.llm import _LLMDecoratedOperator
 from airflow.providers.common.ai.operators.agent import AgentOperator
@@ -63,10 +67,22 @@ class TestModelPanelPlugin:
         """Tied to the actual operator/decorator names a task instance would 
record,
         so a rename of either doesn't silently desync the tab's scoping from 
reality."""
         app = ModelPanelPlugin.react_apps[0]
-        operator_names = app["applies_to"]["operator_names"]
+        operator_names = app["applies_to"]["operator_name"]
         assert set(operator_names) == {
             LLMOperator.__name__,
             AgentOperator.__name__,
             _LLMDecoratedOperator.custom_operator_name,
             _AgentDecoratedOperator.custom_operator_name,
         }
+
+    @requires_3_4
+    def test_react_app_survives_core_applies_to_validation(self):
+        """Core withholds a React App whose applies_to path names no 
TaskInstanceResponse field."""
+        plugin = ModelPanelPlugin()
+        # Core rewrites each view's applies_to in place, so validate a copy, 
not the class-level list.
+        plugin.react_apps = copy.deepcopy(ModelPanelPlugin.react_apps)
+
+        with mock_plugin_manager(plugins=[plugin]):
+            _, react_apps = plugins_manager._get_ui_plugins()
+
+        assert [app["name"] for app in react_apps] == ["AI Model"]

Reply via email to