fix(agentic): guard component code search column input#13620
fix(agentic): guard component code search column input#13620kiranmagic7 wants to merge 1 commit into
Conversation
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughThis PR fixes silent failures in the Langflow Assistant's ChangesComponent Code Search Tool Hardening
🎯 2 (Simple) | ⏱️ ~12 minutes 🚥 Pre-merge checks | ✅ 7 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (7 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/backend/base/langflow/agentic/flows/LangflowAssistant.json`:
- Line 2764: The embedded component DataFrameKeywordSearch uses IntInput (for
number_candidates) but IntInput is not imported from langflow.io, causing a
NameError when the component loads; update the import statement that currently
lists DataFrameInput, MessageTextInput, DropdownInput, BoolInput, Output to also
include IntInput so the class DataFrameKeywordSearch can reference IntInput
without error.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: b9dbcc83-e233-4f7c-bada-9d8715e9d14f
📒 Files selected for processing (2)
src/backend/base/langflow/agentic/flows/LangflowAssistant.jsonsrc/backend/tests/unit/agentic/flows/test_langflow_assistant_component_code_search.py
| "title_case": false, | ||
| "type": "code", | ||
| "value": "from langflow.custom import Component\nfrom langflow.io import DataFrameInput, MessageTextInput, DropdownInput, BoolInput, Output\nfrom langflow.schema import DataFrame\nimport pandas as pd\n\n\nclass DataFrameKeywordSearch(Component):\n display_name = \"Keyword Search\"\n description = \"Search for keywords in a DataFrame column using any/all/coverage matching\"\n icon = \"Search\"\n\n inputs = [\n DataFrameInput(\n name=\"dataframe\",\n display_name=\"DataFrame\",\n info=\"Input DataFrame to search\",\n ),\n MessageTextInput(\n name=\"column\",\n display_name=\"Column\",\n info=\"Column name to search in\",\n tool_mode=True,\n ),\n MessageTextInput(\n name=\"keywords\",\n display_name=\"Keywords\",\n info=\"Keywords to search for\",\n is_list=True,\n tool_mode=True,\n ),\n DropdownInput(\n name=\"match_type\",\n display_name=\"Match Type\",\n options=[\"any\", \"all\", \"coverage\"],\n value=\"any\",\n info=\"'any' = OR logic, 'all' = AND logic, 'coverage' = keyword coverage ranking\",\n ),\n BoolInput(\n name=\"case_sensitive\",\n display_name=\"Case Sensitive\",\n value=False,\n advanced=True,\n info=\"Whether search is case-sensitive\",\n ),\n IntInput(\n name=\"number_candidates\",\n display_name=\"Number of Candidates\",\n value=5,\n info=\"The number of candidates to filter and return in the dataframe output\")\n ]\n\n outputs = [\n Output(name=\"result\", display_name=\"Filtered DataFrame\", method=\"search\"),\n ]\n\n def search(self) -> DataFrame:\n df = self.dataframe\n column = self.column\n keywords = self.keywords if isinstance(self.keywords, list) else []\n match_type = self.match_type\n case_sensitive = self.case_sensitive\n\n if df is None or len(df) == 0:\n return DataFrame(pd.DataFrame())\n\n if column not in df.columns:\n return DataFrame(pd.DataFrame())\n\n keywords = [str(k).strip() for k in keywords if k]\n if not keywords:\n return DataFrame(df)\n\n text_series = df[column].fillna(\"\").astype(str)\n\n if not case_sensitive:\n text_series = text_series.str.lower()\n keywords = [k.lower() for k in keywords]\n\n if match_type == \"any\":\n mask = pd.Series([False] * len(df), index=df.index)\n for keyword in keywords:\n mask = mask | text_series.str.contains(keyword, regex=False)\n result = df[mask]\n\n elif match_type == \"all\":\n mask = pd.Series([True] * len(df), index=df.index)\n for keyword in keywords:\n mask = mask & text_series.str.contains(keyword, regex=False)\n result = df[mask]\n\n elif match_type == \"coverage\":\n scores = []\n total_keywords = len(keywords)\n\n for text in text_series:\n keywords_found = sum(1 for keyword in keywords if keyword in text)\n score = keywords_found / total_keywords\n scores.append(score)\n\n result = df.copy()\n result[\"_score\"] = scores\n result = result[result[\"_score\"] > 0].sort_values(\"_score\", ascending=False)\n\n return DataFrame(result.reset_index(drop=True)).head(self.number_candidates)" | ||
| "value": "from langflow.custom import Component\nfrom langflow.io import DataFrameInput, MessageTextInput, DropdownInput, BoolInput, Output\nfrom langflow.schema import DataFrame\nimport pandas as pd\n\n\nclass DataFrameKeywordSearch(Component):\n display_name = \"Keyword Search\"\n description = \"Search for keywords in a DataFrame column using any/all/coverage matching\"\n icon = \"Search\"\n\n inputs = [\n DataFrameInput(\n name=\"dataframe\",\n display_name=\"DataFrame\",\n info=\"Input DataFrame to search\",\n ),\n MessageTextInput(\n name=\"column\",\n display_name=\"Column\",\n info=\"Column name to search in\",\n value=\"text\",\n ),\n MessageTextInput(\n name=\"keywords\",\n display_name=\"Keywords\",\n info=\"Keywords to search for\",\n is_list=True,\n tool_mode=True,\n ),\n DropdownInput(\n name=\"match_type\",\n display_name=\"Match Type\",\n options=[\"any\", \"all\", \"coverage\"],\n value=\"any\",\n info=\"'any' = OR logic, 'all' = AND logic, 'coverage' = keyword coverage ranking\",\n ),\n BoolInput(\n name=\"case_sensitive\",\n display_name=\"Case Sensitive\",\n value=False,\n advanced=True,\n info=\"Whether search is case-sensitive\",\n ),\n IntInput(\n name=\"number_candidates\",\n display_name=\"Number of Candidates\",\n value=5,\n info=\"The number of candidates to filter and return in the dataframe output\")\n ]\n\n outputs = [\n Output(name=\"result\", display_name=\"Filtered DataFrame\", method=\"search\"),\n ]\n\n def search(self) -> DataFrame:\n df = self.dataframe\n column = self.column\n keywords = self.keywords if isinstance(self.keywords, list) else []\n match_type = self.match_type\n case_sensitive = self.case_sensitive\n\n if df is None or len(df) == 0:\n return DataFrame(pd.DataFrame())\n\n if column not in df.columns:\n valid_columns = \", \".join(map(str, df.columns))\n raise ValueError(f\"Unknown column {column!r}. Valid columns: {valid_columns}\")\n\n keywords = [str(k).strip() for k in keywords if k]\n if not keywords:\n return DataFrame(df)\n\n text_series = df[column].fillna(\"\").astype(str)\n\n if not case_sensitive:\n text_series = text_series.str.lower()\n keywords = [k.lower() for k in keywords]\n\n if match_type == \"any\":\n mask = pd.Series([False] * len(df), index=df.index)\n for keyword in keywords:\n mask = mask | text_series.str.contains(keyword, regex=False)\n result = df[mask]\n\n elif match_type == \"all\":\n mask = pd.Series([True] * len(df), index=df.index)\n for keyword in keywords:\n mask = mask & text_series.str.contains(keyword, regex=False)\n result = df[mask]\n\n elif match_type == \"coverage\":\n scores = []\n total_keywords = len(keywords)\n\n for text in text_series:\n keywords_found = sum(1 for keyword in keywords if keyword in text)\n score = keywords_found / total_keywords\n scores.append(score)\n\n result = df.copy()\n result[\"_score\"] = scores\n result = result[result[\"_score\"] > 0].sort_values(\"_score\", ascending=False)\n\n return DataFrame(result.reset_index(drop=True)).head(self.number_candidates)" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
uv run python - <<'PY'
import json
from pathlib import Path
path = Path("src/backend/base/langflow/agentic/flows/LangflowAssistant.json")
flow = json.loads(path.read_text(encoding="utf-8"))
template = None
for node in flow["data"]["nodes"]:
data = node.get("data", {})
if data.get("type") == "DataFrameKeywordSearch":
template = data["node"]["template"]
break
assert template is not None, "DataFrameKeywordSearch template not found"
code = template["code"]["value"]
import_lines = [ln for ln in code.splitlines() if ln.startswith("from langflow.io import")]
uses_intinput = "IntInput(" in code
imports_intinput = any("IntInput" in ln for ln in import_lines)
print("uses_intinput =", uses_intinput)
print("imports_intinput =", imports_intinput)
if uses_intinput and not imports_intinput:
raise SystemExit("Mismatch confirmed: IntInput is used but not imported.")
PYRepository: langflow-ai/langflow
Length of output: 107
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import json
from pathlib import Path
path = Path("src/backend/base/langflow/agentic/flows/LangflowAssistant.json")
flow = json.loads(path.read_text(encoding="utf-8"))
template = None
for node in flow["data"]["nodes"]:
data = node.get("data", {})
if data.get("type") == "DataFrameKeywordSearch":
template = data["node"]["template"]
break
assert template is not None, "DataFrameKeywordSearch template not found"
code = template["code"]["value"]
import_lines = [ln for ln in code.splitlines() if ln.startswith("from langflow.io import")]
uses_intinput = "IntInput(" in code
imports_intinput = any("IntInput" in ln for ln in import_lines)
print("uses_intinput =", uses_intinput)
print("imports_intinput =", imports_intinput)
if uses_intinput and not imports_intinput:
raise SystemExit("IntInput is used but not imported in embedded component code.")
PYRepository: langflow-ai/langflow
Length of output: 190
Fix embedded component: import IntInput in DataFrameKeywordSearch
The embedded Python code uses IntInput(...) but the from langflow.io import ... line omits IntInput, which will raise a NameError when the component is loaded (around line 2764).
Suggested fix
-from langflow.io import DataFrameInput, MessageTextInput, DropdownInput, BoolInput, Output
+from langflow.io import DataFrameInput, MessageTextInput, DropdownInput, BoolInput, IntInput, Output🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/backend/base/langflow/agentic/flows/LangflowAssistant.json` at line 2764,
The embedded component DataFrameKeywordSearch uses IntInput (for
number_candidates) but IntInput is not imported from langflow.io, causing a
NameError when the component loads; update the import statement that currently
lists DataFrameInput, MessageTextInput, DropdownInput, BoolInput, Output to also
include IntInput so the class DataFrameKeywordSearch can reference IntInput
without error.
|
Pushed Validation after the update: |
|
CI follow-up for current head |
|
Status check on current head When a reviewer has bandwidth, the fix is narrowly scoped to guarding the |
|
Refreshed this branch against current Conflict resolution was limited to
Local proof on The PR may still be subject to the repo's aggregate/nightly CI gate, but the branch conflict is cleared and the focused regression is green. |
|
Status check after the June 24 rebase: current head Review focus remains the narrow |
|
Friendly follow-up after the latest live check: current head Review focus: the narrow |
|
Friendly follow-up after the latest live check: current head Review focus is the same narrow guard: keep the bundled |
951b8f9 to
bf82246
Compare
|
Rebased this branch onto current Conflict resolution was limited to
Local proof on the refreshed head: GitHub now reports the PR mergeable again; hosted checks have restarted on the refreshed head. |
Summary
component_code_searchsilently returns empty results for invalid column names, making the agent report the component library as empty #13618 by preventing the bundledcomponent_code_searchtool from exposingcolumnas an LLM-supplied argumenttextfield, which matches the tool's purpose of searching component source codeValueError, so misconfiguration is recoverable instead of looking like "no components exist"LangflowAssistant.jsonflowNotes
CONTRIBUTING.mdsays to target the active release branch, but the latest release is1.10.0and there is norelease-1.10.1branch currently published. This PR targetsmain, matching the current bug report surface.Validation
python3 -m json.tool src/backend/base/langflow/agentic/flows/LangflowAssistant.json >/dev/nulluv run pytest src/backend/tests/unit/agentic/flows/test_langflow_assistant_component_code_search.py -q— 2 passeduv run ruff check src/backend/tests/unit/agentic/flows/test_langflow_assistant_component_code_search.pygit diff --checkSummary by CodeRabbit
Release Notes
Bug Fixes
Tests