Skip to content

fix: Add dynamic tool mode descriptions for agent integration#10743

Merged
Cristhianzl merged 4 commits into
mainfrom
cz/fix-file-as-tool-generic-prompt
Nov 28, 2025
Merged

fix: Add dynamic tool mode descriptions for agent integration#10743
Cristhianzl merged 4 commits into
mainfrom
cz/fix-file-as-tool-generic-prompt

Conversation

@Cristhianzl
Copy link
Copy Markdown
Member

@Cristhianzl Cristhianzl commented Nov 26, 2025

This pull request adds comprehensive tests and refactors the FileComponent to improve its support for "tool mode," making it easier for agents to interact with uploaded files. The main changes include dynamic descriptions that reflect available files, robust handling of edge cases for file names, and a redesigned tool interface that does not require parameters. These updates enhance reliability and usability when integrating file reading capabilities into agent workflows.

Tool mode and dynamic description improvements:

  • Added a dynamic get_tool_description() method and property to FileComponent, which generates descriptions including the names of uploaded files, supporting better agent understanding and context.
  • Changed the description attribute to be a dynamic property, and added add_tool_output = True to enable tool mode toggling without requiring tool_mode inputs.

Tool interface and error handling:

  • Refactored the _get_tools() method to create a tool that reads files directly from those uploaded via the UI, without requiring parameters; includes robust error handling for missing or invalid files.

Testing enhancements:

  • Added a new TestFileComponentToolMode test class with extensive unit and integration tests for tool mode, dynamic descriptions, edge cases in file names (spaces, special characters, unicode, long names), error handling, and tool execution.
  • Added pytest import to support asynchronous and advanced testing features.

UI and input/output configuration:

  • Updated input and output configuration to ensure that tool_mode=True is set for relevant fields and outputs, supporting the toolset toggle and correct UI behavior.

Summary by CodeRabbit

  • New Features

    • File descriptions now dynamically display the names of uploaded files for better visibility and clarity.
    • File component now supports tool mode, enabling seamless file access and processing as tools within your workflows.
  • Tests

    • Expanded comprehensive test coverage for file component tool mode, validating behavior across various filename formats, special characters, and multiple edge case scenarios.

✏️ Tip: You can customize this high-level summary in your review settings.

image image

@Cristhianzl Cristhianzl requested a review from erichare November 26, 2025 20:18
@Cristhianzl Cristhianzl self-assigned this Nov 26, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Nov 26, 2025

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

The PR enhances FileComponent to support tool mode by introducing dynamic tool descriptions that reflect uploaded files and adding a _get_tools() method to expose file reading as a callable tool, alongside comprehensive test coverage for edge cases.

Changes

Cohort / File(s) Summary
FileComponent Tool Mode Implementation
src/lfx/src/lfx/components/files_and_knowledge/file.py
Adds dynamic tool description via get_tool_description() property, introduces _get_tools() to create StructuredTool for file reading, sets add_tool_output = True for tool mode enablement, and refactors description from static string to computed property.
FileComponent Tool Mode Tests
src/backend/tests/unit/components/files_and_knowledge/test_file_component.py
Introduces TestFileComponentToolMode class with comprehensive tests for tool descriptions (zero/single/multiple/empty file lists), dynamic property behavior, filename handling (spaces, special characters, unicode, long names), empty path filtering, _get_tools() scenarios (no parameters, metadata, error handling, empty lists), and tool_mode flag assertions.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant FileComponent
    participant ToolRegistry
    participant StructuredTool

    User->>FileComponent: Initialize with files in tool mode
    FileComponent->>FileComponent: get_tool_description()
    FileComponent-->>User: Dynamic description with file names
    
    User->>FileComponent: Request tools via _get_tools()
    FileComponent->>StructuredTool: Create load_files_message tool
    Note over StructuredTool: Empty args schema<br/>Display name & description metadata
    StructuredTool->>FileComponent: Tool instance
    FileComponent-->>ToolRegistry: Return list with file reading tool
    
    User->>StructuredTool: Execute tool
    StructuredTool->>FileComponent: load_files_message()
    FileComponent-->>StructuredTool: File content
    StructuredTool-->>User: Result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Areas requiring attention:
    • Dynamic property implementation for description and interaction with get_tool_description()
    • _get_tools() method logic for StructuredTool construction and metadata handling
    • Edge cases in test coverage for filename parsing and tool description generation
    • Verification that add_tool_output = True flag is properly propagated and recognized by the framework

Possibly related PRs

Suggested labels

python, lgtm

Suggested reviewers

  • edwinjosechittilappilly

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Test Quality And Coverage ⚠️ Warning Tests use private _attributes dictionary manipulation instead of public API in 20+ methods, creating brittle and unmaintainable test code despite comprehensive coverage and edge cases. Refactor tests to use component.path = value instead of _attributes manipulation, fix import ordering per Ruff I001 standards, and fix E501 line length violation in file.py line 216.
✅ Passed checks (6 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: adding dynamic tool mode descriptions for agent integration in FileComponent.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Test Coverage For New Implementations ✅ Passed The PR includes comprehensive test coverage with a new TestFileComponentToolMode class containing 26+ test methods covering all new implementations including get_tool_description(), async _get_tools(), description property, add_tool_output attribute, and _base_description, with proper edge case and error handling tests.
Test File Naming And Structure ✅ Passed The test file test_file_component.py fully adheres to all specified test naming and structure requirements with proper pytest structure and 24 comprehensively named test methods.
Excessive Mock Usage Warning ✅ Passed TestFileComponentToolMode demonstrates minimal mock usage with zero @patch decorators and zero MagicMock instantiations, focusing on real FileComponent object behavior and properties.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added the bug Something isn't working label Nov 26, 2025
@codecov
Copy link
Copy Markdown

codecov Bot commented Nov 26, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 32.45%. Comparing base (f2fb7b3) to head (4057783).
⚠️ Report is 5 commits behind head on main.

❌ Your project status has failed because the head coverage (40.04%) is below the target coverage (60.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main   #10743      +/-   ##
==========================================
+ Coverage   32.43%   32.45%   +0.02%     
==========================================
  Files        1367     1367              
  Lines       63315    63315              
  Branches     9357     9357              
==========================================
+ Hits        20537    20552      +15     
+ Misses      41745    41731      -14     
+ Partials     1033     1032       -1     
Flag Coverage Δ
backend 51.31% <ø> (+0.08%) ⬆️
lfx 40.04% <ø> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.
see 5 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Nov 26, 2025
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/lfx/src/lfx/components/files_and_knowledge/file.py (1)

234-237: Remove unnecessary pass statement.

The pass statement in the empty Pydantic model is unnecessary in Python 3 and triggers PIE790.

Apply this diff:

         # Empty schema - no parameters needed
         class EmptySchema(BaseModel):
             """No parameters required - uses pre-uploaded files."""
-
-            pass
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5226daa and bfd3980.

📒 Files selected for processing (2)
  • src/backend/tests/unit/components/files_and_knowledge/test_file_component.py (2 hunks)
  • src/lfx/src/lfx/components/files_and_knowledge/file.py (3 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
src/backend/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)

src/backend/**/*.py: Use FastAPI async patterns with await for async operations in component execution methods
Use asyncio.create_task() for background tasks and implement proper cleanup with try/except for asyncio.CancelledError
Use queue.put_nowait() for non-blocking queue operations and asyncio.wait_for() with timeouts for controlled get operations

Files:

  • src/backend/tests/unit/components/files_and_knowledge/test_file_component.py
src/backend/**/*component*.py

📄 CodeRabbit inference engine (.cursor/rules/icons.mdc)

In Python component classes, set the icon attribute to a string matching the desired icon name (e.g., icon = "AstraDB"). The string must match the frontend icon mapping exactly (case-sensitive).

Files:

  • src/backend/tests/unit/components/files_and_knowledge/test_file_component.py
src/backend/tests/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/testing.mdc)

src/backend/tests/**/*.py: Place backend unit tests in src/backend/tests/ directory, component tests in src/backend/tests/unit/components/ organized by component subdirectory, and integration tests accessible via make integration_tests
Use same filename as component with appropriate test prefix/suffix (e.g., my_component.pytest_my_component.py)
Use the client fixture (FastAPI Test Client) defined in src/backend/tests/conftest.py for API tests; it provides an async httpx.AsyncClient with automatic in-memory SQLite database and mocked environment variables. Skip client creation by marking test with @pytest.mark.noclient
Inherit from the correct ComponentTestBase family class located in src/backend/tests/base.py based on API access needs: ComponentTestBase (no API), ComponentTestBaseWithClient (needs API), or ComponentTestBaseWithoutClient (pure logic). Provide three required fixtures: component_class, default_kwargs, and file_names_mapping
Create comprehensive unit tests for all new backend components. If unit tests are incomplete, create a corresponding Markdown file documenting manual testing steps and expected outcomes
Test both sync and async code paths, mock external dependencies appropriately, test error handling and edge cases, validate input/output behavior, and test component initialization and configuration
Use @pytest.mark.asyncio decorator for async component tests and ensure async methods are properly awaited
Test background tasks using asyncio.create_task() and verify completion with asyncio.wait_for() with appropriate timeout constraints
Test queue operations using non-blocking queue.put_nowait() and asyncio.wait_for(queue.get(), timeout=...) to verify queue processing without blocking
Use @pytest.mark.no_blockbuster marker to skip the blockbuster plugin in specific tests
For database tests that may fail in batch runs, run them sequentially using uv run pytest src/backend/tests/unit/test_database.py r...

Files:

  • src/backend/tests/unit/components/files_and_knowledge/test_file_component.py
**/{test_*.py,*.test.ts,*.test.tsx}

📄 CodeRabbit inference engine (coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt)

Check that test files follow the project's naming conventions (test_*.py for backend, *.test.ts for frontend)

Files:

  • src/backend/tests/unit/components/files_and_knowledge/test_file_component.py
**/test_*.py

📄 CodeRabbit inference engine (coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt)

**/test_*.py: Backend tests should follow pytest structure with proper test_*.py naming
For async functions, ensure proper async testing patterns are used with pytest for backend

Files:

  • src/backend/tests/unit/components/files_and_knowledge/test_file_component.py
🧠 Learnings (12)
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: Applies to src/backend/tests/**/*.py : Test component versioning and backward compatibility using `file_names_mapping` fixture with `VersionComponentMapping` objects mapping component files across Langflow versions

Applied to files:

  • src/backend/tests/unit/components/files_and_knowledge/test_file_component.py
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: Applies to src/backend/tests/**/*.py : Use same filename as component with appropriate test prefix/suffix (e.g., `my_component.py` → `test_my_component.py`)

Applied to files:

  • src/backend/tests/unit/components/files_and_knowledge/test_file_component.py
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: Applies to src/backend/tests/**/*.py : Inherit from the correct `ComponentTestBase` family class located in `src/backend/tests/base.py` based on API access needs: `ComponentTestBase` (no API), `ComponentTestBaseWithClient` (needs API), or `ComponentTestBaseWithoutClient` (pure logic). Provide three required fixtures: `component_class`, `default_kwargs`, and `file_names_mapping`

Applied to files:

  • src/backend/tests/unit/components/files_and_knowledge/test_file_component.py
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: Applies to src/backend/tests/**/*.py : Create comprehensive unit tests for all new backend components. If unit tests are incomplete, create a corresponding Markdown file documenting manual testing steps and expected outcomes

Applied to files:

  • src/backend/tests/unit/components/files_and_knowledge/test_file_component.py
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: Applies to src/backend/tests/**/*.py : Use `aiofiles` and `anyio.Path` for async file operations in tests; create temporary test files using `tmp_path` fixture and verify file existence and content

Applied to files:

  • src/backend/tests/unit/components/files_and_knowledge/test_file_component.py
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: Applies to src/backend/tests/**/*.py : Test both sync and async code paths, mock external dependencies appropriately, test error handling and edge cases, validate input/output behavior, and test component initialization and configuration

Applied to files:

  • src/backend/tests/unit/components/files_and_knowledge/test_file_component.py
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: When adding a new component test, inherit from the correct `ComponentTestBase` class and provide the three required fixtures (`component_class`, `default_kwargs`, `file_names_mapping`) to greatly reduce boilerplate and enforce version compatibility

Applied to files:

  • src/backend/tests/unit/components/files_and_knowledge/test_file_component.py
📚 Learning: 2025-11-24T19:46:09.104Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/backend_development.mdc:0-0
Timestamp: 2025-11-24T19:46:09.104Z
Learning: Applies to tests/unit/components/**/*.py : Provide `file_names_mapping` for backward compatibility in component version testing

Applied to files:

  • src/backend/tests/unit/components/files_and_knowledge/test_file_component.py
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: Applies to src/backend/tests/**/*.py : Test component build config updates by calling `to_frontend_node()` to get the node template, then calling `update_build_config()` to apply configuration changes

Applied to files:

  • src/backend/tests/unit/components/files_and_knowledge/test_file_component.py
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: Applies to src/backend/tests/**/*.py : Use `pytest.mark.api_key_required` and `pytest.mark.no_blockbuster` markers for components that need external APIs; use `MockLanguageModel` from `tests.unit.mock_language_model` for testing without external API keys

Applied to files:

  • src/backend/tests/unit/components/files_and_knowledge/test_file_component.py
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: Applies to src/backend/tests/**/*.py : Use predefined JSON flows and utility functions from `tests.unit.build_utils` (create_flow, build_flow, get_build_events, consume_and_assert_stream) for flow execution testing

Applied to files:

  • src/backend/tests/unit/components/files_and_knowledge/test_file_component.py
📚 Learning: 2025-08-05T22:51:27.961Z
Learnt from: edwinjosechittilappilly
Repo: langflow-ai/langflow PR: 0
File: :0-0
Timestamp: 2025-08-05T22:51:27.961Z
Learning: The TestComposioComponentAuth test in src/backend/tests/unit/components/bundles/composio/test_base_composio.py demonstrates proper integration testing patterns for external API components, including real API calls with mocking for OAuth completion, comprehensive resource cleanup, and proper environment variable handling with pytest.skip() fallbacks.

Applied to files:

  • src/backend/tests/unit/components/files_and_knowledge/test_file_component.py
🧬 Code graph analysis (2)
src/lfx/src/lfx/components/files_and_knowledge/file.py (1)
src/lfx/src/lfx/base/data/base_file.py (1)
  • load_files_message (303-336)
src/backend/tests/unit/components/files_and_knowledge/test_file_component.py (1)
src/lfx/src/lfx/components/files_and_knowledge/file.py (3)
  • description (220-222)
  • get_tool_description (190-217)
  • _get_tools (224-266)
🪛 GitHub Actions: Ruff Style Check
src/backend/tests/unit/components/files_and_knowledge/test_file_component.py

[error] 1-1: Ruff check failed: Import block is un-sorted or un-formatted. I001

🪛 GitHub Check: Ruff Style Check (3.13)
src/lfx/src/lfx/components/files_and_knowledge/file.py

[failure] 248-248: Ruff (BLE001)
src/lfx/src/lfx/components/files_and_knowledge/file.py:248:20: BLE001 Do not catch blind exception: Exception


[failure] 237-237: Ruff (PIE790)
src/lfx/src/lfx/components/files_and_knowledge/file.py:237:13: PIE790 Unnecessary pass statement


[failure] 215-215: Ruff (E501)
src/lfx/src/lfx/components/files_and_knowledge/file.py:215:121: E501 Line too long (121 > 120)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (15)
  • GitHub Check: Lint Backend / Run Mypy (3.12)
  • GitHub Check: Lint Backend / Run Mypy (3.11)
  • GitHub Check: Lint Backend / Run Mypy (3.13)
  • GitHub Check: Lint Backend / Run Mypy (3.10)
  • GitHub Check: Test Docker Images / Test docker images
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 5
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 2
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 3
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 4
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 1
  • GitHub Check: Run Backend Tests / Integration Tests - Python 3.10
  • GitHub Check: Run Backend Tests / LFX Tests - Python 3.10
  • GitHub Check: Test Starter Templates
  • GitHub Check: Update Component Index
  • GitHub Check: Update Starter Projects
🔇 Additional comments (6)
src/backend/tests/unit/components/files_and_knowledge/test_file_component.py (2)

430-502: LGTM - Excellent async test coverage.

The async tests properly use @pytest.mark.asyncio decorator, correctly await async operations, and thoroughly test the _get_tools() functionality including:

  • Tool creation without parameters
  • Dynamic description with filenames
  • Tool metadata validation
  • Actual tool execution with file reading

The use of tmp_path fixture for file operations follows the project guidelines.


506-535: Strong error handling test coverage.

These tests properly validate that the tool handles error scenarios gracefully (missing files, empty file lists) without crashing, which is essential for reliability in agent integrations.

src/lfx/src/lfx/components/files_and_knowledge/file.py (4)

39-44: LGTM - Well-designed dynamic description approach.

Converting the description to a dynamic property that includes uploaded file names provides valuable context for agent integrations. The add_tool_output = True flag correctly enables tool mode toggling without requiring explicit tool_mode inputs.


219-222: LGTM - Clean property implementation.

The description property correctly delegates to get_tool_description() to provide dynamic descriptions based on the current state of uploaded files.


239-249: Exception handling is appropriate for tool error recovery.

While the static analyzer flags the broad Exception catch (BLE001), this pattern is correct for a tool that must return a string error message rather than crash. The tool is also configured with handle_tool_error=True for additional resilience. This defensive approach is essential for agent reliability.

Note: The async function calling the synchronous load_files_message() method is acceptable here, as the method performs file I/O that is expected to complete quickly in typical use cases.


253-266: LGTM - Robust tool implementation with excellent metadata.

The tool creation includes:

  • Proper use of StructuredTool with empty schema (no parameters needed)
  • Dynamic description from get_tool_description()
  • Async coroutine for tool execution
  • Comprehensive metadata for UI display
  • Error handling configured with handle_tool_error=True

This implementation aligns perfectly with the PR objectives to enable agent integration using pre-uploaded files without requiring file paths as parameters.

Comment on lines 1 to 8
import json
from unittest.mock import MagicMock, patch

import pytest

from langflow.io import Output
from lfx.components.files_and_knowledge.file import FileComponent

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix import ordering per Ruff standards.

The import block needs to be properly sorted to resolve the Ruff I001 error flagged by the pipeline.

Based on standard Python import conventions and Ruff's expectations, ensure imports are grouped and sorted as follows:

  1. Standard library imports (sorted alphabetically)
  2. Third-party imports (sorted alphabetically)
  3. First-party imports (sorted alphabetically)

Apply this diff to fix the import order:

 import json
 from unittest.mock import MagicMock, patch
 
 import pytest
-
 from langflow.io import Output
 from lfx.components.files_and_knowledge.file import FileComponent
🧰 Tools
🪛 GitHub Actions: Ruff Style Check

[error] 1-1: Ruff check failed: Import block is un-sorted or un-formatted. I001

🪛 GitHub Check: Ruff Style Check (3.13)

[failure] 1-7: Ruff (I001)
src/backend/tests/unit/components/files_and_knowledge/test_file_component.py:1:1: I001 Import block is un-sorted or un-formatted

🤖 Prompt for AI Agents
In src/backend/tests/unit/components/files_and_knowledge/test_file_component.py
lines 1-8, the import block is not ordered per Ruff/I001; reorder imports into
three groups: (1) standard library imports sorted alphabetically (e.g., json),
(2) third-party imports sorted alphabetically (e.g., pytest), and (3)
first-party/project imports sorted alphabetically (e.g., from langflow.io import
Output and from lfx.components.files_and_knowledge.file import FileComponent),
each group separated by a single blank line.

Comment on lines +283 to +428
component = FileComponent()
component._attributes["path"] = None

description = component.get_tool_description()

assert description == "Loads and returns the content from uploaded files."

def test_get_tool_description_with_single_file(self):
"""Test tool description includes single file name."""
component = FileComponent()
component._attributes["path"] = ["flow123/document.pdf"]

description = component.get_tool_description()

assert "document.pdf" in description
assert "Available files:" in description

def test_get_tool_description_with_multiple_files(self):
"""Test tool description includes all file names."""
component = FileComponent()
component._attributes["path"] = [
"flow123/report.pdf",
"flow123/data.csv",
"flow123/notes.txt",
]

description = component.get_tool_description()

assert "report.pdf" in description
assert "data.csv" in description
assert "notes.txt" in description
assert "Available files:" in description

def test_get_tool_description_with_empty_list(self):
"""Test tool description with empty file list."""
component = FileComponent()
component._attributes["path"] = []

description = component.get_tool_description()

assert description == "Loads and returns the content from uploaded files."

def test_description_property_returns_dynamic_description(self):
"""Test that description property returns dynamic description."""
component = FileComponent()
component._attributes["path"] = ["flow123/test.pdf"]

# Access via property
description = component.description

assert "test.pdf" in description

# ==================== Edge Cases: File Names ====================

def test_get_tool_description_filename_with_spaces(self):
"""Test handling of filenames with spaces."""
component = FileComponent()
component._attributes["path"] = ["flow123/my document with spaces.pdf"]

description = component.get_tool_description()

assert "my document with spaces.pdf" in description

def test_get_tool_description_filename_with_comma(self):
"""Test handling of filenames with commas."""
component = FileComponent()
component._attributes["path"] = ["flow123/file,with,commas.txt"]

description = component.get_tool_description()

assert "file,with,commas.txt" in description

def test_get_tool_description_filename_with_multiple_dots(self):
"""Test handling of filenames with multiple dots."""
component = FileComponent()
component._attributes["path"] = ["flow123/file.name.with.dots.pdf"]

description = component.get_tool_description()

assert "file.name.with.dots.pdf" in description

def test_get_tool_description_filename_with_special_characters(self):
"""Test handling of filenames with special characters."""
component = FileComponent()
component._attributes["path"] = [
"flow123/file-with-dashes.pdf",
"flow123/file_with_underscores.txt",
"flow123/file (with) parentheses.doc",
]

description = component.get_tool_description()

assert "file-with-dashes.pdf" in description
assert "file_with_underscores.txt" in description
assert "file (with) parentheses.doc" in description

def test_get_tool_description_filename_with_unicode(self):
"""Test handling of filenames with unicode characters."""
component = FileComponent()
component._attributes["path"] = [
"flow123/文档.pdf",
"flow123/документ.txt",
"flow123/arquivo_português.pdf",
]

description = component.get_tool_description()

assert "文档.pdf" in description
assert "документ.txt" in description
assert "arquivo_português.pdf" in description

def test_get_tool_description_filename_with_numbers(self):
"""Test handling of filenames with numbers."""
component = FileComponent()
component._attributes["path"] = [
"flow123/report_2024_01_15.pdf",
"flow123/v1.2.3_release_notes.txt",
]

description = component.get_tool_description()

assert "report_2024_01_15.pdf" in description
assert "v1.2.3_release_notes.txt" in description

def test_get_tool_description_very_long_filename(self):
"""Test handling of very long filenames."""
component = FileComponent()
long_name = "a" * 200 + ".pdf"
component._attributes["path"] = [f"flow123/{long_name}"]

description = component.get_tool_description()

assert long_name in description

def test_get_tool_description_filters_empty_paths(self):
"""Test that empty paths are filtered out."""
component = FileComponent()
component._attributes["path"] = ["flow123/valid.pdf", "", None, "flow123/another.txt"]

description = component.get_tool_description()

assert "valid.pdf" in description
assert "another.txt" in description
# Should not crash or include empty entries

# ==================== _get_tools() Tests ====================
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Avoid direct manipulation of private _attributes dictionary.

Throughout this test class, file paths are set by directly accessing component._attributes["path"]. This bypasses the public API and creates fragile tests that may break if the internal implementation changes.

Use the public path attribute instead:

     def test_get_tool_description_without_files(self):
         """Test tool description when no files are uploaded."""
         component = FileComponent()
-        component._attributes["path"] = None
+        component.path = None
 
         description = component.get_tool_description()

Apply this pattern consistently to all tests in this class that currently set component._attributes["path"] (lines 284, 293, 303, 319, 328, 340, 349, 358, 367, 382, 397, 411, 420, 434, 451, 463, 476, 493, 510, 525).

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/backend/tests/unit/components/files_and_knowledge/test_file_component.py
around lines 281 to 426 (and the other line locations called out in the review:
284, 293, 303, 319, 328, 340, 349, 358, 367, 382, 397, 411, 420, 434, 451, 463,
476, 493, 510, 525), replace all direct assignments to the private dictionary
component._attributes["path"] with the public API by setting component.path
(e.g., component.path = None or component.path = ["flow123/..."]). Ensure you
apply this consistently across every test in the file, and if the path property
expects a specific type, supply that type (None, empty list, or list of paths)
so tests continue to exercise the same behavior without touching internals.


if file_names:
files_str = ", ".join(file_names)
return f"{base_description} Available files: {files_str}. Call this tool to read the content of these files."
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Break long line to fix E501 style violation.

Line 215 exceeds the 120-character limit.

Apply this diff:

         if file_names:
             files_str = ", ".join(file_names)
-            return f"{base_description} Available files: {files_str}. Call this tool to read the content of these files."
+            return (
+                f"{base_description} Available files: {files_str}. "
+                f"Call this tool to read the content of these files."
+            )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return f"{base_description} Available files: {files_str}. Call this tool to read the content of these files."
if file_names:
files_str = ", ".join(file_names)
return (
f"{base_description} Available files: {files_str}. "
f"Call this tool to read the content of these files."
)
🧰 Tools
🪛 GitHub Check: Ruff Style Check (3.13)

[failure] 215-215: Ruff (E501)
src/lfx/src/lfx/components/files_and_knowledge/file.py:215:121: E501 Line too long (121 > 120)

🤖 Prompt for AI Agents
In src/lfx/src/lfx/components/files_and_knowledge/file.py around line 215, the
return statement exceeds the 120-character limit; break the long f-string into
multiple shorter string literals by wrapping the return expression in
parentheses and splitting the f-string across two lines (or concatenate two
f-strings) so the resulting line lengths are under 120 characters while
preserving the same output: first part with base_description, second part with "
Available files: {files_str}. Call this tool to read the content of these
files.".

@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Nov 26, 2025
@github-actions github-actions Bot added the lgtm This PR has been approved by a maintainer label Nov 26, 2025
@Cristhianzl Cristhianzl added this pull request to the merge queue Nov 27, 2025
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Nov 27, 2025
@Cristhianzl Cristhianzl added this pull request to the merge queue Nov 28, 2025
Merged via the queue into main with commit 0a16803 Nov 28, 2025
59 of 61 checks passed
@Cristhianzl Cristhianzl deleted the cz/fix-file-as-tool-generic-prompt branch November 28, 2025 12:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working lgtm This PR has been approved by a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants