codeant-ai-for-open-source[bot] commented on code in PR #40972:
URL: https://github.com/apache/superset/pull/40972#discussion_r3442765844


##########
superset/mcp_service/chart/schemas.py:
##########
@@ -1736,6 +1759,65 @@ def validate_unique_column_labels(self) -> 
"XYChartConfig":
 # giving LLMs enough context to construct valid configs.
 
 
+# Superset viz_type values that LLM clients routinely send where this API
+# expects its chart_type discriminator. Each maps to (chart_type, kind);
+# kind is only meaningful for the xy family.
+_VIZ_TYPE_TO_CHART_TYPE: dict[str, tuple[str, str | None]] = {
+    "bar": ("xy", "bar"),
+    "dist_bar": ("xy", "bar"),
+    "echarts_timeseries_bar": ("xy", "bar"),
+    "line": ("xy", "line"),
+    "echarts_timeseries_line": ("xy", "line"),
+    "echarts_timeseries_smooth": ("xy", "line"),
+    "area": ("xy", "area"),
+    "echarts_area": ("xy", "area"),
+    "scatter": ("xy", "scatter"),
+    "echarts_timeseries_scatter": ("xy", "scatter"),
+    "big_number_total": ("big_number", None),
+    "pivot_table_v2": ("pivot_table", None),
+}
+
+
+def _normalize_chart_request_input(data: Any) -> Any:
+    """Accept common Superset REST/form_data vocabulary in chart requests.
+
+    LLM clients reliably reach for Superset's public field names —
+    ``datasource_id``, ``viz_type``, and concrete viz plugin names such as
+    ``echarts_timeseries_bar`` — before consulting this API's schema. Each
+    rejection costs the client a model round trip, so the unambiguous
+    synonyms are translated instead of refused.
+    """
+    if not isinstance(data, dict):
+        return data
+    if "dataset_id" not in data and "datasource_id" in data:
+        data["dataset_id"] = data.pop("datasource_id")
+    config = data.get("config")
+    if isinstance(config, dict):
+        if "viz_type" in config:
+            viz_type = config["viz_type"]
+            if "chart_type" not in config:
+                config["chart_type"] = viz_type
+                config.pop("viz_type")
+            elif config.get("chart_type") != "table":

Review Comment:
   **Suggestion:** When only `viz_type` is provided, the normalizer blindly 
copies it into `chart_type` and removes `viz_type`. This breaks valid Superset 
table plugin requests like `viz_type="ag-grid-table"` because `chart_type` 
becomes an unsupported discriminator value instead of resolving to the table 
chart config. Map known table plugin viz types (for example `ag-grid-table`) to 
`chart_type="table"` before dropping `viz_type`. [incomplete implementation]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ AG Grid table chart requests rejected despite valid config.
   - ⚠️ LLM agents need extra retries, worsening latency.
   - ⚠️ Explore link generation fails for ag-grid-table configs.
   ```
   </details>
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Note the discriminated union `ChartConfig` in 
`superset/mcp_service/chart/schemas.py`
   (around PR lines 1749–1755) which uses `discriminator="chart_type"` and 
documents allowed
   values: `'xy'`, `'table'`, `'pie'`, `'pivot_table'`, `'mixed_timeseries'`, 
`'handlebars'`,
   `'big_number'`.
   
   2. Observe the new normalizer `_normalize_chart_request_input` in the same 
file (lines
   1782–1810). When `config` contains `"viz_type"` but no `"chart_type"`, it 
executes the
   block at lines 1799–1801: it sets `config["chart_type"] = viz_type` and then 
removes
   `"viz_type"` entirely.
   
   3. From `superset/mcp_service/app.py` lines 320–17, see that AG Grid tables 
are a
   supported Superset viz plugin: `chart_type="table", 
viz_type="ag-grid-table": Interactive
   AG Grid table`, meaning `viz_type="ag-grid-table"` is a legitimate request 
shape in
   Superset vocabulary.
   
   4. Call the MCP `generate_chart` tool
   (`superset/mcp_service/chart/tool/generate_chart.py:98`) or 
`generate_explore_link`
   (`superset/mcp_service/explore/tool/generate_explore_link.py:21`) with a 
request using
   only Superset-style plugin naming in the config, e.g. `{"dataset_id": 1, 
"config":
   {"viz_type": "ag-grid-table", "columns": [...]}}`. The 
`ChartRequestNormalizerMixin` model
   validator (schemas.py:113–119) invokes `_normalize_chart_request_input`, 
which converts
   `chart_type` to the raw string `"ag-grid-table"` and discards `viz_type`. 
Since
   `"ag-grid-table"` is not an accepted `chart_type` literal in `ChartConfig` 
and is also not
   mapped in `_VIZ_TYPE_TO_CHART_TYPE` (schemas.py:66–79 only covers 
`'pivot_table_v2'` for
   table family), Pydantic raises a validation error for an unknown 
discriminator value. A
   valid Superset table plugin request is thus rejected instead of being 
normalized to
   `chart_type="table"` and handled by `TableChartConfig`.
   ```
   </details>
   
   [![Fix in 
Cursor](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-cursor-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=780cfbc919344db498465b50a9fa68cf&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
 [![Fix in VSCode 
Claude](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-vscode-claude-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=780cfbc919344db498465b50a9fa68cf&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
   
   *(Use Cmd/Ctrl + Click for best experience)*
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset/mcp_service/chart/schemas.py
   **Line:** 1799:1801
   **Comment:**
        *Incomplete Implementation: When only `viz_type` is provided, the 
normalizer blindly copies it into `chart_type` and removes `viz_type`. This 
breaks valid Superset table plugin requests like `viz_type="ag-grid-table"` 
because `chart_type` becomes an unsupported discriminator value instead of 
resolving to the table chart config. Map known table plugin viz types (for 
example `ag-grid-table`) to `chart_type="table"` before dropping `viz_type`.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   Once fix is implemented, also check other comments on the same PR, and ask 
user if the user wants to fix the rest of the comments as well. if said yes, 
then fetch all the comments validate the correctness and implement a minimal fix
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40972&comment_hash=1f6ff65cb468073af15306cd3e48367cff0313bed6f7dd3a6efdaefc93050f03&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40972&comment_hash=1f6ff65cb468073af15306cd3e48367cff0313bed6f7dd3a6efdaefc93050f03&reaction=dislike'>👎</a>



##########
superset/mcp_service/chart/schemas.py:
##########
@@ -1736,6 +1759,65 @@ def validate_unique_column_labels(self) -> 
"XYChartConfig":
 # giving LLMs enough context to construct valid configs.
 
 
+# Superset viz_type values that LLM clients routinely send where this API
+# expects its chart_type discriminator. Each maps to (chart_type, kind);
+# kind is only meaningful for the xy family.
+_VIZ_TYPE_TO_CHART_TYPE: dict[str, tuple[str, str | None]] = {
+    "bar": ("xy", "bar"),
+    "dist_bar": ("xy", "bar"),
+    "echarts_timeseries_bar": ("xy", "bar"),
+    "line": ("xy", "line"),
+    "echarts_timeseries_line": ("xy", "line"),
+    "echarts_timeseries_smooth": ("xy", "line"),
+    "area": ("xy", "area"),
+    "echarts_area": ("xy", "area"),
+    "scatter": ("xy", "scatter"),
+    "echarts_timeseries_scatter": ("xy", "scatter"),
+    "big_number_total": ("big_number", None),
+    "pivot_table_v2": ("pivot_table", None),
+}
+
+
+def _normalize_chart_request_input(data: Any) -> Any:
+    """Accept common Superset REST/form_data vocabulary in chart requests.
+
+    LLM clients reliably reach for Superset's public field names —
+    ``datasource_id``, ``viz_type``, and concrete viz plugin names such as
+    ``echarts_timeseries_bar`` — before consulting this API's schema. Each
+    rejection costs the client a model round trip, so the unambiguous
+    synonyms are translated instead of refused.
+    """
+    if not isinstance(data, dict):
+        return data
+    if "dataset_id" not in data and "datasource_id" in data:
+        data["dataset_id"] = data.pop("datasource_id")
+    config = data.get("config")
+    if isinstance(config, dict):
+        if "viz_type" in config:
+            viz_type = config["viz_type"]
+            if "chart_type" not in config:
+                config["chart_type"] = viz_type
+                config.pop("viz_type")
+            elif config.get("chart_type") != "table":
+                config.pop("viz_type")
+        chart_type = config.get("chart_type")

Review Comment:
   **Suggestion:** This branch discards `viz_type` whenever `chart_type` is 
present and not `"table"`, even if the provided `chart_type` is invalid. That 
means a request with a typo in `chart_type` but a valid `viz_type` fallback is 
unrecoverably rejected. Keep `viz_type` as a fallback when `chart_type` is not 
recognized, and only drop it after successful chart-type normalization. [logic 
error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ⚠️ Requests with typoed chart_type fail despite valid viz_type.
   - ⚠️ LLM agents lose automatic recovery from minor mistakes.
   ```
   </details>
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. In `_VIZ_TYPE_TO_CHART_TYPE` at `superset/mcp_service/chart/schemas.py` 
lines 66–79,
   note that several Superset plugin `viz_type` values like 
`"echarts_timeseries_bar"` and
   `"pivot_table_v2"` are mapped to canonical `(chart_type, kind)` pairs (e.g.
   `"echarts_timeseries_bar" -> ("xy", "bar")`), i.e. they can serve as a 
fallback source of
   truth for `chart_type`.
   
   2. In `_normalize_chart_request_input` (schemas.py lines 1782–1810), when 
both
   `"viz_type"` and `"chart_type"` are present in `config`, the branch at lines 
1802–1803
   executes whenever `chart_type` is anything other than `"table"`: `elif
   config.get("chart_type") != "table": config.pop("viz_type")`. This happens 
before the
   subsequent normalization that consults `_VIZ_TYPE_TO_CHART_TYPE`.
   
   3. Invoke the MCP `generate_chart` tool
   (`superset/mcp_service/chart/tool/generate_chart.py:98`) with a mixed-input 
config that
   includes a typoed `chart_type` but a valid Superset plugin `viz_type`, for 
example:
   `{"dataset_id": 1, "config": {"chart_type": "xyy", "viz_type": 
"echarts_timeseries_bar",
   "x": {"name": "date"}, "y": [{"name": "sales", "aggregate": "SUM"}]}}`. The
   `ChartRequestNormalizerMixin` validator (schemas.py:113–119) calls
   `_normalize_chart_request_input`, which sees both keys and, because 
`"chart_type" !=
   "table"`, executes the branch at 1802–1803 and deletes `"viz_type"`.
   
   4. After `"viz_type"` has been discarded, `_normalize_chart_request_input` 
looks up
   `chart_type = config.get("chart_type")` and only normalizes values present in
   `_VIZ_TYPE_TO_CHART_TYPE` (schemas.py:104–109). The typoed `"xyy"` is not 
recognized or
   corrected, so `ChartConfig`'s discriminated union (schemas.py:39–56) is 
instantiated with
   an invalid `chart_type` and Pydantic raises a validation error. If 
`viz_type` had been
   preserved until after normalization, the valid `"echarts_timeseries_bar"` 
value could have
   been used as a fallback via `_VIZ_TYPE_TO_CHART_TYPE`, turning this into a 
recoverable
   request instead of a hard failure.
   ```
   </details>
   
   [![Fix in 
Cursor](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-cursor-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=953997f100b64cd9bbb2d8fb2aa26b24&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
 [![Fix in VSCode 
Claude](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-vscode-claude-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=953997f100b64cd9bbb2d8fb2aa26b24&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
   
   *(Use Cmd/Ctrl + Click for best experience)*
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset/mcp_service/chart/schemas.py
   **Line:** 1802:1803
   **Comment:**
        *Logic Error: This branch discards `viz_type` whenever `chart_type` is 
present and not `"table"`, even if the provided `chart_type` is invalid. That 
means a request with a typo in `chart_type` but a valid `viz_type` fallback is 
unrecoverably rejected. Keep `viz_type` as a fallback when `chart_type` is not 
recognized, and only drop it after successful chart-type normalization.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   Once fix is implemented, also check other comments on the same PR, and ask 
user if the user wants to fix the rest of the comments as well. if said yes, 
then fetch all the comments validate the correctness and implement a minimal fix
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40972&comment_hash=734bc122e1b76c9d5b59396e0ab361ac33dbb30d05cfa1f0d7df41be136d611d&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40972&comment_hash=734bc122e1b76c9d5b59396e0ab361ac33dbb30d05cfa1f0d7df41be136d611d&reaction=dislike'>👎</a>



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to