feat: merge Release v1.8.0 into main#11827
Conversation
feat(auth): Pluggable AuthService with abstract base class (#10702) * feat: Introduce service registration decorator and enhance ServiceManager for pluggable service discovery - Added `register_service` decorator to allow services to self-register with the ServiceManager. - Enhanced `ServiceManager` to support multiple service discovery mechanisms, including decorator-based registration, config files, and entry points. - Implemented methods for direct service class registration and plugin discovery from various sources, improving flexibility and extensibility of service management. * feat: Implement VariableService for managing environment variables - Introduced VariableService class to handle environment variables with in-memory caching. - Added methods for getting, setting, deleting, and listing variables. - Included logging for service initialization and variable operations. - Created an __init__.py file to expose VariableService in the package namespace. * feat: Enhance LocalStorageService with Service integration and async teardown - Updated LocalStorageService to inherit from both StorageService and Service for improved functionality. - Added a name attribute for service identification. - Implemented an async teardown method for future extensibility, even though no cleanup is currently needed. - Refactored the constructor to ensure proper initialization of both parent classes. * feat: Implement telemetry service with abstract base class and minimal logging functionality - Added `BaseTelemetryService` as an abstract base class defining the interface for telemetry services. - Introduced `TelemetryService`, a lightweight implementation that logs telemetry events without sending data. - Created `__init__.py` to expose the telemetry service in the package namespace. - Ensured robust async methods for logging various telemetry events and handling exceptions. * feat: Introduce BaseTracingService and implement minimal TracingService - Added `BaseTracingService` as an abstract base class defining the interface for tracing services. - Implemented `TracingService`, a lightweight version that logs trace events without external integrations. - Included async methods for starting and ending traces, tracing components, and managing logs and outputs. - Enhanced documentation for clarity on method usage and parameters. * feat: Add unit tests for service registration decorators - Introduced a new test suite for validating the functionality of the @register_service decorator. - Implemented tests for various service types including LocalStorageService, TelemetryService, and TracingService. - Verified behavior for service registration with and without overrides, ensuring correct service management. - Included tests for custom service implementations and preservation of class functionality. - Enhanced overall test coverage for the service registration mechanism. * feat: Add comprehensive unit and integration tests for ServiceManager - Introduced a suite of unit tests covering edge cases for service registration, lifecycle management, and dependency resolution. - Implemented integration tests to validate service loading from configuration files and environment variables. - Enhanced test coverage for various service types including LocalStorageService, TelemetryService, and VariableService. - Verified behavior for service registration with and without overrides, ensuring correct service management. - Ensured robust handling of error conditions and edge cases in service creation and configuration parsing. * feat: Add unit and integration tests for minimal service implementations - Introduced comprehensive unit tests for LocalStorageService, TelemetryService, TracingService, and VariableService. - Implemented integration tests to validate the interaction between minimal services. - Ensured robust coverage for file operations, service readiness, and exception handling. - Enhanced documentation within tests for clarity on functionality and expected behavior. * docs: Add detailed documentation for pluggable services architecture and usage * feat: Add example configuration file for Langflow services * docs: Update PLUGGABLE_SERVICES.md to enhance architecture benefits section - Revised the documentation to highlight the advantages of the pluggable service system. - Replaced the migration guide with a detailed overview of features such as automatic discovery, lazy instantiation, dependency injection, and lifecycle management. - Clarified examples of service registration and improved overall documentation for better understanding. * [autofix.ci] apply automated fixes * test(services): improve variable service teardown test with public API assertions * docs(pluggable-service-layer): add docstrings for service manager and implementations * fix: remove duplicate teardown method from LocalStorageService During rebase, the teardown method was added in two locations (lines 57 and 220). Removed the duplicate at line 57, keeping the one at the end of the class (line 220) which is the more appropriate location for cleanup methods. * fix(tests): update service tests for LocalStorageService constructor changes - Add MockSessionService fixtures to test files that use ServiceManager - Update LocalStorageService test instantiation to use mock session and settings services - Fix service count assertions to account for MockSessionService in fixtures - Remove duplicate class-level clean_manager fixtures in test_edge_cases.py These changes fix test failures caused by LocalStorageService requiring session_service and settings_service parameters instead of just data_dir. * fix(services): Harden service lifecycle methods - Fixed Diamond Inheritance in LocalStorageService - Added Circular Dependency Detection in _create_service_from_class - Fixed StorageService.teardown to Have Default Implementation * docs: Update discovery order for pluggable services * fix(lfx): replace aiofile with aiofiles for CI compatibility - The aiofile library uses native async I/O (libaio) which fails with EAGAIN (SystemError: 11, 'Resource temporarily unavailable') in containerized environments like GitHub Actions runners. - Switch to aiofiles which uses thread pool executors, providing reliable async file I/O across all environments including containers. * [autofix.ci] apply automated fixes * fix(lfx): prevent race condition in plugin discovery The discover_plugins() method had a TOCTOU (time-of-check to time-of-use) race condition. Since get() uses a keyed lock (per service name), multiple threads requesting different services could concurrently see _plugins_discovered=False and trigger duplicate plugin discovery. Wrap discover_plugins() with self._lock to ensure thread-safe access to the _plugins_discovered flag and prevent concurrent discovery execution. * [autofix.ci] apply automated fixes * feat: Introduce service registration decorator and enhance ServiceManager for pluggable service discovery - Added `register_service` decorator to allow services to self-register with the ServiceManager. - Enhanced `ServiceManager` to support multiple service discovery mechanisms, including decorator-based registration, config files, and entry points. - Implemented methods for direct service class registration and plugin discovery from various sources, improving flexibility and extensibility of service management. * feat: Enhance LocalStorageService with Service integration and async teardown - Updated LocalStorageService to inherit from both StorageService and Service for improved functionality. - Added a name attribute for service identification. - Implemented an async teardown method for future extensibility, even though no cleanup is currently needed. - Refactored the constructor to ensure proper initialization of both parent classes. * docs(pluggable-service-layer): add docstrings for service manager and implementations * feat(auth): implement abstract base class for authentication services and add auth service retrieval function * refactor(auth): move authentication logic from utils to AuthService Consolidate all authentication methods into the AuthService class to enable pluggable authentication implementations. The utils module now contains thin wrappers that delegate to the registered auth service. This allows alternative auth implementations (e.g., OIDC) to be registered via the pluggable services system while maintaining backward compatibility with existing code that imports from utils. Changes: - Move all auth logic (token creation, user validation, API key security, password hashing, encryption) to AuthService - Refactor utils.py to delegate to get_auth_service() - Update function signatures to remove settings_service parameter (now obtained from the service internally) * refactor(auth): update authentication methods and remove settings_service parameter - Changed function to retrieve current user from access token instead of JWT. - Updated AuthServiceFactory to specify SettingsService type in create method. - Removed settings_service dependency from encryption and decryption functions, simplifying the code. This refactor enhances the clarity and maintainability of the authentication logic. * test(auth): add unit tests for AuthService and pluggable authentication - Introduced comprehensive unit tests for AuthService, covering token creation, user validation, and authentication methods. - Added tests for pluggable authentication, ensuring correct delegation to registered services. - Enhanced test coverage for user authentication scenarios, including active/inactive user checks and token validation. These additions improve the reliability and maintainability of the authentication system. * fix(tests): update test cases to use AuthService and correct user retrieval method - Replaced the mock for retrieving the current user from JWT to access token in the TestSuperuserCommand. - Refactored unit tests for MCP encryption to utilize AuthService instead of a mock settings service, enhancing test reliability. - Updated patch decorators in tests to reflect the new method of obtaining the AuthService, ensuring consistency across test cases. These changes improve the accuracy and maintainability of the authentication tests. * docs(pluggable-services): add auth_service to ServiceType enum documentation * fix(auth): Add missing type hints and abstract methods to AuthServiceBase (#10710) * [autofix.ci] apply automated fixes * fix(auth): refactor api_key_security method to accept optional database session and improve error handling * feat(auth): enhance AuthServiceBase with detailed design principles and JIT provisioning methods * fix(auth): remove settings_service from encrypt/decrypt_api_key calls After the pluggable auth refactor, encrypt_api_key and decrypt_api_key no longer take a settings_service argument - they get it internally. - Update check_key import path in __main__.py (moved to crud module) - Remove settings_service argument from calls in: - api/v1/api_key.py - api/v1/store.py - services/variable/service.py - services/variable/kubernetes.py - Fix auth service to use session_scope() instead of non-existent get_db_service().with_session() * fix(auth): resolve type errors and duplicate definitions in pluggable auth branch - Add missing imports in auth/utils.py (Final, HTTPException, status, logger, SettingsService) that prevented application startup - Remove duplicate NoServiceRegisteredError class in lfx/services/manager.py - Remove duplicate teardown method in lfx/services/storage/local.py - Fix invalid settings_service parameter in encrypt_api_key calls in variable/service.py and variable/kubernetes.py - Add proper type guards for check_key calls to satisfy mypy - Add null checks for password fields in users.py endpoints * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * [autofix.ci] apply automated fixes * replace jose with pyjwt * [autofix.ci] apply automated fixes * starter projects * fix BE mcp tests * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * remive legacy usage of session * fix user tests * [autofix.ci] apply automated fixes * fix lfx tests * starter project update * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * fix mypy errors * fix mypy errors on tests * fix tests for decrypt_api_key * resolve conflicts in auth utils * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * Add pluggable authentication factory with provider enum * Add SSO feature flags to AuthSettings * Add SSO fields to User model * Add SSO configuration loader with YAML support * Add unit tests for SSO configuration loader * Add SSO configuration database model and CRUD operations * Add CRUD operations for SSO configuration management * Add SSO configuration service supporting both file and database configs * Add example SSO configuration file with W3ID and other providers * Implement OIDC authentication service with discovery and JIT provisioning * Update AuthServiceFactory to instantiate OIDC service when SSO enabled * Improve JWT token validation and API key decryption error handling * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes * fix: resolve ruff linting errors in auth services and add sso-config.yaml to gitignore * [autofix.ci] apply automated fixes * fix: use correct function name get_current_user_from_access_token in login endpoint * fix: remove incorrect settings_service parameter from decrypt_api_key call * fix: correct encryption logic to properly detect plaintext vs encrypted values * [autofix.ci] apply automated fixes * fix tests * [autofix.ci] apply automated fixes * fix mypy errors * fix tests * [autofix.ci] apply automated fixes * fix ruff errors * fix tests in service * [autofix.ci] apply automated fixes * fix test security cors * [autofix.ci] apply automated fixes * fix webhook issues * modify component index * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * fix webhook tests * [autofix.ci] apply automated fixes * build component index * remove SSO functionality * [autofix.ci] apply automated fixes * fix variable creation * [autofix.ci] apply automated fixes * refactor: move MCPServerConfig schema to a separate file and update model_dump usage * refactor: streamline AuthServiceFactory to use service_class for instance creation * handle access token type * [autofix.ci] apply automated fixes * remove SSO fields from user model * [autofix.ci] apply automated fixes * replace is_encrypted back * fix mypy errors * remove sso config example * feat: Refactor framework agnostic auth service (#11565) * modify auth service layer * [autofix.ci] apply automated fixes * fix ruff errorrs * [autofix.ci] apply automated fixes * Update src/backend/base/langflow/services/deps.py * address review comments * [autofix.ci] apply automated fixes * fix ruff errors * remove cache --------- * move base to lfx * [autofix.ci] apply automated fixes * resolve review comments * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * add auth protocol * [autofix.ci] apply automated fixes * revert models.py execption handling * revert wrappers to ensure backwards compatibility * fix http error code * fix FE tests * fix test_variables.py * [autofix.ci] apply automated fixes * fix ruff errors * fix tests * add wrappers for create token methods * fix ruff errors * [autofix.ci] apply automated fixes * update error message * modify status code for inactive user * fix ruff errors * fix patch for webhook tests * fix error message when getting active users --------- Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@logspace.ai> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Mike Pawlowski <mike.pawlowski@datastax.com> Co-authored-by: Mike Pawlowski <mpawlow@ca.ibm.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: ogabrielluiz <24829397+ogabrielluiz@users.noreply.github.com> Co-authored-by: Deon Sanchez <69873175+deon-sanchez@users.noreply.github.com> Co-authored-by: codeflash-ai[bot] <148906541+codeflash-ai[bot]@users.noreply.github.com>
* revert textarea to old classes * fixed text-area-wrapper to handle initial height when value is calculated * fixed playground padding * fixed no input text size * [autofix.ci] apply automated fixes * fixed flaky test --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
* Create guardrails.py * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * Update guardrails.py * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * tests: add unit tests for GuardrailsComponent functionality * [autofix.ci] apply automated fixes * fix: resolve linting errors in GuardrailsComponent and tests - Fix line length issues (E501) by breaking long strings - Fix docstring formatting (D205, D415) in _check_guardrail - Use ternary operator for response content extraction (SIM108) - Replace magic value with named constant (PLR2004) - Move return to else block per try/except best practices (TRY300) - Catch specific exceptions instead of blind Exception (BLE001) - Use list comprehension for checks_to_run (PERF401) - Mark unused variables with underscore prefix (RUF059, F841) - Add noqa comment for intentionally unused mock argument (ARG002) * [autofix.ci] apply automated fixes * refactor: address pr comments * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes * feat: enhance heuristic detection with configurable threshold and scoring system * refactor: simplify heuristic test assertions by removing unused variable * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * feat: enhance guardrail validation logic and input handling * refactor: streamline import statements and clean up whitespace in guardrails component * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * Fix: update empty input handling tests to raise ValueError and refactor related assertions * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes * feat: add Guardrails component with unit tests Add LLM-based guardrails component for detecting PII, tokens/passwords, jailbreak attempts, and custom guardrail rules, along with comprehensive unit tests. * [autofix.ci] apply automated fixes * fix: try removing logs * [autofix.ci] apply automated fixes --------- Co-authored-by: Lucas Democh <ldgoularte@gmail.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
* Implemented dismiss file functionality on input file component * fixed hover behavior * added test for removing file from input * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
* fixed react flow utils to clean advanced edges * Make connected handles not be able to be hidden * Added test for hiding connected handles * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
fix tooltip showing up when closing select
* fix(frontend): prevent crash when renaming empty sessions * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
…#11722) The regex in langflow_pre_release_tag.py expected a dot before `rc` (e.g. `1.8.0.rc0`), but PyPI returns PEP 440-normalized versions without the dot (e.g. `1.8.0rc0`). This caused the script to recompute the same version instead of incrementing, and `uv publish` silently skipped the duplicate upload. Update the regex to accept both formats with `\.?rc`.
…11725) * fix: align chat history with input field in fullscreen playground * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
* fix singleton webhook on flow * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
…Variable button (#11723) * fix: generate unique variable names in Prompt Template Add Variable button Previously, clicking the Add Variable button always inserted {variable_name}, causing duplicate text without creating new input fields. Now the button generates incremental names (variable_name, variable_name_1, variable_name_2) by checking existing variables in the template. * refactor: extract generateUniqueVariableName and import in tests Extract the variable name generation logic into an exported function so tests can import and validate the actual production code instead of testing a duplicated copy of the logic.
…11709) add edge between components Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>
) * Update state when exiting modal on accordion prompt component * Added isDoubleBrackets and show correct modal and use correct brackets when mustache is enabled * [autofix.ci] apply automated fixes * added test to see if state is synchronized and mustache is enabled * [autofix.ci] apply automated fixes * updated mustache id and removed extra prompt call * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Carlos Coelho <80289056+carlosrcoelho@users.noreply.github.com>
…es (#11720) * fix(frontend): add Safari-specific padding for playground chat messages * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
* Correctly parse dicts from tweaks * Add test * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
fix: sessions overflow issue
…tion (#11751) * merge fix * code improvements * [autofix.ci] apply automated fixes * add stop button and fix scroll on message * [autofix.ci] apply automated fixes * add new message content for sharable pg * fix tests until shard 43 * [autofix.ci] apply automated fixes * fix(frontend): clean up MemoizedSidebarTrigger imports and transition classes Sort imports, add type modifier to AllNodeType import, and split long transition class string for readability. * fix tests * [autofix.ci] apply automated fixes * fix mr test * fix jest tests * fix sidebar jest tes * [autofix.ci] apply automated fixes * fix sharable playground * [autofix.ci] apply automated fixes * remove rename from sharable pg * [autofix.ci] apply automated fixes * add new message content for sharable pg * fix: synchronize prompt state, add new mustache prompt component (#11702) * Update state when exiting modal on accordion prompt component * Added isDoubleBrackets and show correct modal and use correct brackets when mustache is enabled * [autofix.ci] apply automated fixes * added test to see if state is synchronized and mustache is enabled * [autofix.ci] apply automated fixes * updated mustache id and removed extra prompt call * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Carlos Coelho <80289056+carlosrcoelho@users.noreply.github.com> * fix(frontend): add Safari-specific padding for playground chat messages (#11720) * fix(frontend): add Safari-specific padding for playground chat messages * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: correctly pass headers in mcp stdio connections (#11746) * fix sharable playground * [autofix.ci] apply automated fixes * remove rename from sharable pg * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes * fix sharable playground * fix mcp server to use shell lexer * [autofix.ci] apply automated fixes * fix tests * fix outaded component tests --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Viktor Avelino <viktor.avelino@gmail.com> Co-authored-by: Lucas Oliveira <62335616+lucaseduoli@users.noreply.github.com> Co-authored-by: Carlos Coelho <80289056+carlosrcoelho@users.noreply.github.com> Co-authored-by: keval shah <kevalvirat@gmail.com> Co-authored-by: Jordan Frazier <122494242+jordanrfrazier@users.noreply.github.com>
* fix: correct field_order in all starter project JSON templates The field_order arrays in starter project nodes were out of sync with the actual input definitions in the Python component source files, causing parameters to display in the wrong order in the UI. Fixed 136 nodes across 32 starter project files including Chat Input, Chat Output, Language Model, Agent, Prompt Template, Text Input, Tavily AI Search, Read File, Embedding Model, and others. * test: add field_order validation test for starter projects Verifies that field_order arrays in starter project JSONs match the actual component input order by importing each component and comparing the relative ordering of fields. * fix mcp server to use shell lexer * [autofix.ci] apply automated fixes * fix: enforce full field_order in starter projects and add node overlap test Update all starter project JSONs to include the complete component field_order instead of a subset, preventing layout inconsistency between template and sidebar. Strengthen the field_order test to require an exact match and add a new test that verifies no two generic nodes overlap on the canvas. --------- Co-authored-by: cristhianzl <cristhian.lousa@gmail.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
* Fix dict handling of different formats * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * cmp index * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
improve styling of templete input Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* move chat input arround for travel json starter template * improve the layout of the component * fix layout --------- Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>
* fix: Filter out MCP and models_and_agents categories and MCPTools component from sidebar (#11513) * fix: hide MCP tool from model & agent * fix: removing mcp searching * fix testcases * fix testcases --------- Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local> Co-authored-by: Carlos Coelho <80289056+carlosrcoelho@users.noreply.github.com> Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com> * fix: Fix flaky Market Research test timeout on CI (#11665) * add wait for statement to prevent race condition * fix flaky global variable * add input selection * [autofix.ci] apply automated fixes * add disable inspect panel util * [autofix.ci] apply automated fixes * fix vector store test * [autofix.ci] apply automated fixes * use disable inspect pannel utils --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * ci: make docs deployment manual-only (#11602) feat: update GitHub Actions workflow to allow manual branch selection for docs deployment * fix: handle missing capabilities in Ollama API response (#11603) * fix: handle missing capabilities in Ollama API response Older Ollama versions don't return the `capabilities` field from `/api/show`. The previous code defaulted to an empty list and required "completion" capability, filtering out all models. Now we treat missing capabilities as backwards-compatible: assume the model supports completion unless tool_model_enabled is True (where we can't verify tool support without the capabilities field). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * [autofix.ci] apply automated fixes * test: add test cases for Ollama backwards compatibility fix Add tests for get_models handling of missing capabilities field: - test_get_models_missing_capabilities_without_tool_model - test_get_models_missing_capabilities_with_tool_model - test_get_models_mixed_capabilities_response Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * [autofix.ci] apply automated fixes * fix: wrap long docstring line to satisfy ruff E501 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * docs: draft hide internal endpoints in spec (#11469) * test-hide-internal-endpoints * hide-more-endpoints * display-mcp-endpoints * display-mcp-projects * add-back-health-check --------- Co-authored-by: Hamza Rashid <74062092+HzaRashid@users.noreply.github.com> * feat: update opensearch component with raw search component (#11491) * Update opensearch_multimodal.py * [autofix.ci] apply automated fixes * Update opensearch_multimodal.py * Skip existing knn_vector mapping & handle errors Before adding a knn_vector field mapping, check the index properties and skip updating if the field already exists (and warn if dimensions differ). Attempt to add the mapping only when missing, and catch failures from the OpenSearch k-NN plugin (e.g. NullPointerException); in that known case log a warning and skip the mapping update instead of failing hard. After adding, verify the field is mapped as knn_vector and raise an error if it is not. Also adjusts logging messages to be clearer. --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix(test): Skip Tavily API key fill when global variable is loaded (#11733) * update Google models * [autofix.ci] apply automated fixes * update tests * mark deprecated * build component index * [autofix.ci] apply automated fixes --------- Co-authored-by: olayinkaadelakun <olayinka.adelakun@ibm.com> Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local> Co-authored-by: Carlos Coelho <80289056+carlosrcoelho@users.noreply.github.com> Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com> Co-authored-by: Cristhian Zanforlin Lousa <cristhian.lousa@gmail.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@logspace.ai> Co-authored-by: Ram Gopal Srikar Katakam <44802869+RamGopalSrikar@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Mendon Kissling <59585235+mendonk@users.noreply.github.com> Co-authored-by: Hamza Rashid <74062092+HzaRashid@users.noreply.github.com> Co-authored-by: Edwin Jose <edwin.jose@datastax.com>
* fix: mock clearSessionMessages to prevent flowStore.getState error in test Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * [autofix.ci] apply automated fixes --------- Co-authored-by: Viktor Avelino <viktor.avelino@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
* fix: Misleading Empty State when no Folders now once all folders are deleted we show the default create first flow state * [autofix.ci] apply automated fixes * fix(api): prevent users from deactivating their own account (#11736) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * Fix: UI Overlay: Chat Input Component Overlapping README Note (#11710) * move chat input arround for travel json starter template * improve the layout of the component * fix layout --------- Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local> --------- Co-authored-by: Carlos Coelho <80289056+carlosrcoelho@users.noreply.github.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Ram Gopal Srikar Katakam <44802869+RamGopalSrikar@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: olayinkaadelakun <olayinka.adelakun@ibm.com> Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>
* fix windows integrations with postgres * add documentation * cross platform validation * [autofix.ci] apply automated fixes * ruff style and checker * fix import ruff --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
Codecov Report❌ Patch coverage is ❌ Your patch status has failed because the patch coverage (20.39%) is below the target coverage (40.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #11827 +/- ##
==========================================
+ Coverage 35.27% 35.34% +0.06%
==========================================
Files 1521 1525 +4
Lines 73008 73292 +284
Branches 10951 11021 +70
==========================================
+ Hits 25755 25904 +149
- Misses 45858 45974 +116
- Partials 1395 1414 +19
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
This comment has been minimized.
This comment has been minimized.
| "types-cachetools>=5.5.0.20240820", | ||
| "pyyaml>=6.0.2", | ||
| "pyleak>=0.1.14", | ||
| "mcp-server-fetch>=2025.1.17", |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Check whether uv.lock includes the new dependency
lockfile=$(fd -t f '^uv\.lock$' -a . | head -n1 || true)
if [ -n "${lockfile}" ]; then
rg -n "mcp-server-fetch" "${lockfile}" || echo "mcp-server-fetch not found in ${lockfile}"
else
echo "uv.lock not found"
fi
# Fetch PyPI metadata for version & python compatibility
python - <<'PY'
import json, urllib.request
try:
url = "https://pypi.org/pypi/mcp-server-fetch/json"
data = json.load(urllib.request.urlopen(url))
print("latest_version:", data["info"]["version"])
print("requires_python:", data["info"].get("requires_python"))
except Exception as e:
print(f"Error fetching PyPI data: {e}")
PYRepository: langflow-ai/langflow
Length of output: 291
🏁 Script executed:
#!/bin/bash
# Check pyproject.toml around line 73 for context
sed -n '60,85p' pyproject.tomlRepository: langflow-ai/langflow
Length of output: 698
Regenerate uv.lock to include the new dev dependency.
The mcp-server-fetch>=2025.1.17 dependency was added to pyproject.toml but is missing from uv.lock. Since the project uses uv for dependency management, the lockfile must be kept in sync. Run uv lock to update uv.lock with the new dependency.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pyproject.toml` at line 73, pyproject.toml added the new dev dependency
"mcp-server-fetch>=2025.1.17" but uv.lock wasn't updated; run the UV lock
command to regenerate the lockfile and commit the updated uv.lock so it includes
"mcp-server-fetch>=2025.1.17" (run `uv lock` in the project root, verify uv.lock
contains the mcp-server-fetch entry, then add/commit the updated uv.lock).
| "temperature", | ||
| "max_tokens" | ||
| ], |
There was a problem hiding this comment.
max_tokens is listed in field_order but absent from the template snapshot — field won't render in the starter project.
The field_order array references max_tokens, but the template object for LanguageModelComponent-htMuI (lines 976–1243) contains no max_tokens entry. When Langflow loads this starter project the UI renderer skips fields that exist in field_order but not in template, so users cannot configure max_tokens without first refreshing the component. Runtime is unaffected (build_model guards with getattr(self, "max_tokens", None)), but the intent of exposing the field is defeated.
The serialized max_tokens block should be added to the template section alongside the existing temperature entry, e.g.:
🛠 Proposed addition to the template section (after line 1242, before the closing brace)
+ "max_tokens": {
+ "_input_type": "IntInput",
+ "advanced": true,
+ "display_name": "Max Tokens",
+ "dynamic": false,
+ "info": "Maximum number of tokens to generate. Field name varies by provider.",
+ "list": false,
+ "list_add_label": "Add More",
+ "name": "max_tokens",
+ "placeholder": "",
+ "range_spec": {
+ "max": 128000,
+ "min": 1,
+ "step": 1,
+ "step_type": "int"
+ },
+ "required": false,
+ "show": true,
+ "title_case": false,
+ "tool_mode": false,
+ "trace_as_metadata": true,
+ "type": "int",
+ "value": ""
+ }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/backend/base/langflow/initial_setup/starter_projects/Document` Q&A.json
around lines 909 - 911, The starter project's LanguageModelComponent-htMuI lists
"max_tokens" in field_order but the template lacks a corresponding serialized
field, so add a max_tokens entry into the component's template object (next to
the existing temperature entry) so the UI can render it; locate
LanguageModelComponent-htMuI in the JSON, update its "template" section to
include a serialized max_tokens block (same structure as temperature: keys like
"name":"max_tokens", "value":<default>, "type":"int" or matching existing field
schema, and any metadata such as "label" and "required") and keep "max_tokens"
in field_order unchanged.
| { | ||
| "category": "Google Generative AI", | ||
| "icon": "GoogleGenerativeAI", | ||
| "metadata": { | ||
| "api_key_param": "google_api_key", | ||
| "context_length": 128000, | ||
| "model_class": "ChatGoogleGenerativeAIFixed", | ||
| "model_name_param": "model" | ||
| }, | ||
| "name": "gemini-1.5-pro", | ||
| "provider": "Google Generative AI" | ||
| }, | ||
| { | ||
| "category": "Google Generative AI", | ||
| "icon": "GoogleGenerativeAI", | ||
| "metadata": { | ||
| "api_key_param": "google_api_key", | ||
| "context_length": 128000, | ||
| "model_class": "ChatGoogleGenerativeAIFixed", | ||
| "model_name_param": "model" | ||
| }, | ||
| "name": "gemini-1.5-flash", | ||
| "provider": "Google Generative AI" | ||
| }, | ||
| { | ||
| "category": "Google Generative AI", | ||
| "icon": "GoogleGenerativeAI", | ||
| "metadata": { | ||
| "api_key_param": "google_api_key", | ||
| "context_length": 128000, | ||
| "model_class": "ChatGoogleGenerativeAIFixed", | ||
| "model_name_param": "model" | ||
| }, | ||
| "name": "gemini-1.5-flash-8b", | ||
| "provider": "Google Generative AI" | ||
| }, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for deprecated Gemini 1.5 model references across all starter project JSON files
rg -l 'gemini-1\.5' --glob '*.json' src/backend/base/langflow/initial_setup/starter_projects/Repository: langflow-ai/langflow
Length of output: 483
🌐 Web query:
Are Google Gemini 1.5 pro and flash models still available for inference API in February 2026?
💡 Result:
No.
- Gemini API (Google AI for Developers / AI Studio): Google shut down the Gemini 1.5 models (
gemini-1.5-pro,gemini-1.5-flash, andgemini-1.5-flash-8b) on September 29, 2025, so they are not available for inference in February 2026. [1] - Vertex AI (Gemini on Vertex): The specific Gemini 1.5 Pro/Flash model versions (e.g.,
gemini-1.5-pro-002,gemini-1.5-flash-002) have retirement dates in 2025 and are listed as retired models, so they are not available for inference in February 2026. [2] (Vertex had also already blocked access for new/no-prior-usage projects as of April 29, 2025.) [3]
Sources: [1] Gemini API release notes, [2] Vertex AI “Model versions and lifecycle”, [3] Vertex AI Generative AI release notes.
Remove or replace completely unavailable Gemini 1.5 models.
Google shut down Gemini 1.5 models (gemini-1.5-pro, gemini-1.5-flash, gemini-1.5-flash-8b) on September 29, 2025. These three entries at lines 1028, 1040, and 1052 are completely non-functional in February 2026. Users selecting these options will encounter failures. Replace them with current models like gemini-2.0-flash or gemini-3-pro-preview, or remove them entirely. This issue also appears in at least 4 other starter projects (Text Sentiment Analysis, Simple Agent, Portfolio Website Code Generator, Basic Prompting).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/backend/base/langflow/initial_setup/starter_projects/Financial` Report
Parser.json around lines 1019 - 1054, Remove the three deprecated Gemini 1.5
entries ("gemini-1.5-pro", "gemini-1.5-flash", "gemini-1.5-flash-8b") from the
Financial Report Parser starter JSON and replace them with supported model
entries (for example "gemini-2.0-flash" or "gemini-3-pro-preview"), preserving
the existing metadata structure (metadata.model_class:
"ChatGoogleGenerativeAIFixed", metadata.api_key_param, metadata.context_length,
metadata.model_name_param) and the provider/icon/category fields; also apply the
same replacement or removal to the other affected starter projects (Text
Sentiment Analysis, Simple Agent, Portfolio Website Code Generator, Basic
Prompting) so users do not see nonfunctional model options.
| @media not all and (min-resolution: 0.001dpcm) { | ||
| @supports (-webkit-appearance: none) { | ||
| .playground-messages-wrapper { | ||
| padding-left: 1rem; | ||
| padding-right: 1rem; | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Dead CSS rule: .playground-messages-wrapper nested inside .label will never match
CSS nesting inside a style rule creates a descendant selector. This block compiles to:
`@media` not all and (min-resolution: 0.001dpcm) {
`@supports` (-webkit-appearance: none) {
.label .playground-messages-wrapper { /* ← descendant selector */
padding-left: 1rem;
padding-right: 1rem;
}
}
}In the actual DOM, .playground-messages-wrapper (the <div> at line 199 of flow-page-sliding-container.tsx) is never a child of .label (a user-select utility), so this Safari padding fix is entirely unreachable — it will never be applied.
Move the block to the top level outside .label:
🐛 Proposed fix
.label {
user-select: none;
-webkit-user-select: none; /* Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none;
-
- /* Safari-only fix for playground padding */
- `@media` not all and (min-resolution: 0.001dpcm) {
- `@supports` (-webkit-appearance: none) {
- .playground-messages-wrapper {
- padding-left: 1rem;
- padding-right: 1rem;
- }
- }
- }
}
+/* Safari-only fix for playground padding */
+@media not all and (min-resolution: 0.001dpcm) {
+ `@supports` (-webkit-appearance: none) {
+ .playground-messages-wrapper {
+ padding-left: 1rem;
+ padding-right: 1rem;
+ }
+ }
+}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/frontend/src/App.css` around lines 22 - 29, The nested CSS rule places
.playground-messages-wrapper inside .label so it compiles to a descendant
selector that never matches; move the Safari-specific padding block out of the
.label nesting so the selector targets .playground-messages-wrapper at the top
level inside the `@media/`@supports wrapper. Locate the nested block in App.css
where .label contains the `@media/`@supports rule and extract or duplicate the
.playground-messages-wrapper rule so it exists directly under `@media` not all and
(min-resolution: 0.001dpcm) { `@supports` (-webkit-appearance: none) { ... } },
ensuring the selector is simply .playground-messages-wrapper and not .label
.playground-messages-wrapper.
| const queryClient = useQueryClient(); | ||
|
|
||
| if (!flowId) { | ||
| return false; | ||
| } | ||
|
|
||
| const sessionCacheKey = [ | ||
| "useGetMessagesQuery", | ||
| { id: flowId, session_id: sessionId }, | ||
| ]; | ||
|
|
||
| const { data: sessionMessages = [] } = useQuery<Message[]>({ | ||
| queryKey: sessionCacheKey, | ||
| queryFn: () => { | ||
| const cachedData = | ||
| queryClient.getQueryData<Message[]>(sessionCacheKey) || []; | ||
| return cachedData; | ||
| }, | ||
| staleTime: Infinity, | ||
| gcTime: 5 * 60 * 1000, | ||
| structuralSharing: false, | ||
| refetchOnMount: false, | ||
| refetchOnWindowFocus: false, | ||
| enabled: !!flowId, | ||
| }); |
There was a problem hiding this comment.
🚨 Rules of Hooks violation: useQuery is called conditionally after an early return.
useQueryClient() is always called (Hook #1), but the return false at Line 19 causes useQuery (Hook #2) to be skipped whenever flowId is falsy. React tracks hooks by call order; when flowId transitions between defined and undefined, the hook count changes and React throws a "Rendered fewer/more hooks than during the previous render" error at runtime.
The enabled: !!flowId option already exists — that is the correct React Query mechanism to conditionally disable the query while keeping the hook call unconditional. Move the guard after all hook calls:
🐛 Proposed fix
export const useSessionHasMessages = ({
sessionId,
flowId,
}: UseSessionHasMessagesParams): boolean => {
const queryClient = useQueryClient();
- if (!flowId) {
- return false;
- }
-
const sessionCacheKey = [
"useGetMessagesQuery",
{ id: flowId, session_id: sessionId },
];
const { data: sessionMessages = [] } = useQuery<Message[]>({
queryKey: sessionCacheKey,
queryFn: () => {
const cachedData =
queryClient.getQueryData<Message[]>(sessionCacheKey) || [];
return cachedData;
},
staleTime: Infinity,
gcTime: 5 * 60 * 1000,
structuralSharing: false,
refetchOnMount: false,
refetchOnWindowFocus: false,
enabled: !!flowId,
});
+ if (!flowId) return false;
+
const hasMessages = sessionMessages.some((message: Message) => {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/frontend/src/components/core/playgroundComponent/chat-view/chat-header/hooks/use-session-has-messages.ts`
around lines 17 - 41, Remove the early return that conditionally skips the
useQuery hook to fix the Rules of Hooks violation: always call useQuery (keep
the existing useQueryClient(), sessionCacheKey, and the useQuery call with
enabled: !!flowId) and then after the hooks complete, check flowId and return
false when appropriate (e.g., if !flowId return false using the already-fetched
sessionMessages). In short, delete the "if (!flowId) return false" before
useQuery, rely on enabled: !!flowId to disable the query, and perform the
flowId-based return after the hooks so hook call order stays stable.
| state.edges.some( | ||
| (edge) => | ||
| edge.target === data.id && | ||
| edge.targetHandle && | ||
| scapeJSONParse(edge.targetHandle)?.fieldName === name, |
There was a problem hiding this comment.
scapeJSONParse can throw and crash the component if any edge has a malformed targetHandle.
scapeJSONParse wraps JSON.parse, which throws a SyntaxError on invalid input. Because this runs inside a Zustand selector that fires on every edges update, a single bad targetHandle value in the store will bubble up as an uncaught exception, crashing the component tree.
🛡️ Proposed fix — guard with try/catch
const isConnected = useFlowStore(
useCallback(
(state) =>
state.edges.some(
(edge) =>
edge.target === data.id &&
edge.targetHandle &&
- scapeJSONParse(edge.targetHandle)?.fieldName === name,
+ (() => {
+ try {
+ return scapeJSONParse(edge.targetHandle!)?.fieldName === name;
+ } catch {
+ return false;
+ }
+ })(),
),
[data.id, name],
),
);📝 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.
| state.edges.some( | |
| (edge) => | |
| edge.target === data.id && | |
| edge.targetHandle && | |
| scapeJSONParse(edge.targetHandle)?.fieldName === name, | |
| state.edges.some( | |
| (edge) => | |
| edge.target === data.id && | |
| edge.targetHandle && | |
| (() => { | |
| try { | |
| return scapeJSONParse(edge.targetHandle!)?.fieldName === name; | |
| } catch { | |
| return false; | |
| } | |
| })(), |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelEditField.tsx`
around lines 34 - 38, The selector in InspectionPanelEditField uses
scapeJSONParse inside state.edges.some which can throw on malformed
targetHandle; wrap the JSON parse call in a safe parsing guard (either update
scapeJSONParse to catch and return undefined/null on parse errors or replace the
inline call with a try/catch around scapeJSONParse) so malformed
edge.targetHandle values don't throw; ensure the some predicate treats parse
failures as non-matching (e.g., treat undefined result as no fieldName match) so
the selector never throws during edges updates.
| <ShadTooltip | ||
| content={ | ||
| isConnected | ||
| ? "Cannot change visibility of connected handles" | ||
| : isOnCanvas | ||
| ? "Hide" | ||
| : "Show" | ||
| } | ||
| avoidCollisions | ||
| > | ||
| <IconComponent | ||
| name={isOnCanvas ? "Minus" : "Plus"} | ||
| className="h-3.5 w-3.5" | ||
| /> | ||
| </button> | ||
| <button | ||
| onClick={handleToggleVisibility} | ||
| disabled={isConnected} | ||
| className={cn( | ||
| "flex h-6 w-6 shrink-0 items-center justify-center rounded-full transition-colors", | ||
| isOnCanvas | ||
| ? "bg-primary/10 text-primary hover:bg-primary/20" | ||
| : "bg-muted text-muted-foreground hover:bg-muted-foreground/20 hover:text-foreground", | ||
| isConnected | ||
| ? "cursor-not-allowed opacity-50 hover:bg-primary/10" | ||
| : "", | ||
| )} | ||
| data-testid={`show${name}`} | ||
| id={`show${name}`} | ||
| aria-checked={isOnCanvas} | ||
| role="checkbox" | ||
| > | ||
| <IconComponent | ||
| name={isOnCanvas ? "Minus" : "Plus"} | ||
| className="h-3.5 w-3.5" | ||
| /> | ||
| </button> | ||
| </ShadTooltip> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Find ShadTooltip definition
find . -type f \( -name "*.ts" -o -name "*.tsx" \) | xargs grep -l "ShadTooltip" | head -20Repository: langflow-ai/langflow
Length of output: 2143
🏁 Script executed:
# Search for tooltip component definition in common locations
fd -type f -name "*tooltip*" -o -name "*Tooltip*"Repository: langflow-ai/langflow
Length of output: 234
🏁 Script executed:
# Look at the specific file under review
cat -n src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelEditField.tsx | head -100Repository: langflow-ai/langflow
Length of output: 3570
🏁 Script executed:
# Read ShadTooltip component implementation
cat -n src/frontend/src/components/common/shadTooltipComponent/index.tsxRepository: langflow-ai/langflow
Length of output: 3183
Tooltip will not appear when the button is disabled, leaving users without explanation for why the control is unresponsive.
The ShadTooltip component uses Radix UI's Tooltip with asChild={true} (default), which makes the button the direct trigger element. Disabled buttons don't fire pointer events, so the Radix trigger won't activate. Critically, the "Cannot change visibility of connected handles" message is the one users need to see precisely when isConnected=true—the state that disables the button. Without it, they receive no feedback about why the control is unresponsive.
🛠️ Proposed fix — wrap disabled button in a span
<ShadTooltip
content={
isConnected
? "Cannot change visibility of connected handles"
: isOnCanvas
? "Hide"
: "Show"
}
avoidCollisions
>
+ <span
+ tabIndex={isConnected ? 0 : undefined}
+ className={isConnected ? "cursor-not-allowed" : undefined}
+ >
<button
onClick={handleToggleVisibility}
disabled={isConnected}
className={cn(
"flex h-6 w-6 shrink-0 items-center justify-center rounded-full transition-colors",
isOnCanvas
? "bg-primary/10 text-primary hover:bg-primary/20"
: "bg-muted text-muted-foreground hover:bg-muted-foreground/20 hover:text-foreground",
isConnected
- ? "cursor-not-allowed opacity-50 hover:bg-primary/10"
+ ? "pointer-events-none opacity-50"
: "",
)}
data-testid={`show${name}`}
id={`show${name}`}
aria-checked={isOnCanvas}
role="checkbox"
>
<IconComponent
name={isOnCanvas ? "Minus" : "Plus"}
className="h-3.5 w-3.5"
/>
</button>
+ </span>
</ShadTooltip>📝 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.
| <ShadTooltip | |
| content={ | |
| isConnected | |
| ? "Cannot change visibility of connected handles" | |
| : isOnCanvas | |
| ? "Hide" | |
| : "Show" | |
| } | |
| avoidCollisions | |
| > | |
| <IconComponent | |
| name={isOnCanvas ? "Minus" : "Plus"} | |
| className="h-3.5 w-3.5" | |
| /> | |
| </button> | |
| <button | |
| onClick={handleToggleVisibility} | |
| disabled={isConnected} | |
| className={cn( | |
| "flex h-6 w-6 shrink-0 items-center justify-center rounded-full transition-colors", | |
| isOnCanvas | |
| ? "bg-primary/10 text-primary hover:bg-primary/20" | |
| : "bg-muted text-muted-foreground hover:bg-muted-foreground/20 hover:text-foreground", | |
| isConnected | |
| ? "cursor-not-allowed opacity-50 hover:bg-primary/10" | |
| : "", | |
| )} | |
| data-testid={`show${name}`} | |
| id={`show${name}`} | |
| aria-checked={isOnCanvas} | |
| role="checkbox" | |
| > | |
| <IconComponent | |
| name={isOnCanvas ? "Minus" : "Plus"} | |
| className="h-3.5 w-3.5" | |
| /> | |
| </button> | |
| </ShadTooltip> | |
| <ShadTooltip | |
| content={ | |
| isConnected | |
| ? "Cannot change visibility of connected handles" | |
| : isOnCanvas | |
| ? "Hide" | |
| : "Show" | |
| } | |
| avoidCollisions | |
| > | |
| <span | |
| tabIndex={isConnected ? 0 : undefined} | |
| className={isConnected ? "cursor-not-allowed" : undefined} | |
| > | |
| <button | |
| onClick={handleToggleVisibility} | |
| disabled={isConnected} | |
| className={cn( | |
| "flex h-6 w-6 shrink-0 items-center justify-center rounded-full transition-colors", | |
| isOnCanvas | |
| ? "bg-primary/10 text-primary hover:bg-primary/20" | |
| : "bg-muted text-muted-foreground hover:bg-muted-foreground/20 hover:text-foreground", | |
| isConnected | |
| ? "pointer-events-none opacity-50" | |
| : "", | |
| )} | |
| data-testid={`show${name}`} | |
| id={`show${name}`} | |
| aria-checked={isOnCanvas} | |
| role="checkbox" | |
| > | |
| <IconComponent | |
| name={isOnCanvas ? "Minus" : "Plus"} | |
| className="h-3.5 w-3.5" | |
| /> | |
| </button> | |
| </span> | |
| </ShadTooltip> |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/frontend/src/pages/FlowPage/components/InspectionPanel/components/InspectionPanelEditField.tsx`
around lines 63 - 95, The tooltip won't show when the button is disabled because
Radix's Tooltip (ShadTooltip) uses the button as the trigger and disabled
buttons don't fire pointer events; update the JSX so that when isConnected is
true the button is wrapped in a non-disabled inline wrapper (e.g., a <span
className="inline-block">) and pass the tooltip trigger to that wrapper instead
of the disabled button; keep the existing button props
(onClick={handleToggleVisibility}, disabled, aria-checked, role, data-testid/id)
and the IconComponent inside, and ensure the wrapper preserves layout
(inline-block) and any cursor/opacity styles so the UI remains identical while
allowing ShadTooltip to show the "Cannot change visibility of connected handles"
message.
| useEffect(() => { | ||
| const isEmpty = | ||
| flows?.find( | ||
| (flow) => | ||
| flow.folder_id === (folderId ?? myCollectionId) && | ||
| (ENABLE_MCP ? flow.is_component === false : true), | ||
| ) === undefined; | ||
| setIsEmptyFolder(isEmpty); | ||
| }, [flows, folderId, myCollectionId]); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# First, let's read the actual file to see the complete context around lines 97-129
cd src/frontend/src/pages/MainPage/pages/homePage
cat -n index.tsx | sed -n '90,135p'Repository: langflow-ai/langflow
Length of output: 1694
🏁 Script executed:
#!/bin/bash
# Check if ENABLE_MCP flag exists and its value
fd feature-flags.ts -x cat -n {} | head -50Repository: langflow-ai/langflow
Length of output: 1240
🏁 Script executed:
#!/bin/bash
# Search for usages of isEmptyFolder and EmptyFolder to understand the impact
rg "isEmptyFolder|EmptyFolder" -n -B2 -A2 \
src/frontend/src/pages/MainPage/pages/homePage/Repository: langflow-ai/langflow
Length of output: 4537
🏁 Script executed:
#!/bin/bash
# Check what flows are and understand the is_component property
rg "is_component|flows\?" -n -B2 -A2 \
src/frontend/src/pages/MainPage/pages/homePage/ | head -60Repository: langflow-ai/langflow
Length of output: 4260
isEmptyFolder incorrectly treats a components-only folder as empty when ENABLE_MCP is enabled
With ENABLE_MCP = true, the guard flow.is_component === false only counts flows — components are excluded from the emptiness check. Since the flows array is pre-filtered by the API based on the current tab (lines 60–68, 70), when you navigate to the components tab, the array contains only components. The check then searches for flows within a components-only array, finds nothing, and sets isEmpty = true. The folder displays the EmptyFolder view instead of the components list.
The tab-switching effect (lines 109–129) cannot recover because it guards with !isEmptyFolder (line 111) and thus never runs for this case.
If the intent is to show "empty only when there are genuinely no items in this folder," the condition should check for items regardless of type:
🐛 Proposed fix
useEffect(() => {
const isEmpty =
flows?.find(
(flow) =>
flow.folder_id === (folderId ?? myCollectionId) &&
- (ENABLE_MCP ? flow.is_component === false : true),
+ true,
) === undefined;
setIsEmptyFolder(isEmpty);
}, [flows, folderId, myCollectionId]);Alternatively, if the intent is to exclude components from the "empty" check (treating them as a separate category), rename isEmptyFolder to hasNoFlows and add a corresponding hasNoComponents check to avoid conflating an empty-of-flows folder with an empty folder.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/frontend/src/pages/MainPage/pages/homePage/index.tsx` around lines 97 -
105, The isEmptyFolder computation in the useEffect incorrectly ignores
components when ENABLE_MCP is true; update the logic in the effect that reads
flows to treat any item in the folder as non-empty (i.e., remove the
flow.is_component === false filter) so the existence check uses flows.find(flow
=> flow.folder_id === (folderId ?? myCollectionId)) and then calls
setIsEmptyFolder accordingly; alternatively, if you want to keep flows vs
components distinct, rename isEmptyFolder to hasNoFlows and add a separate
hasNoComponents flag and corresponding checks/setters so components-only folders
are not treated as empty by setIsEmptyFolder.
| : rawInputTypes; | ||
| const hasProxy = targetNode.data.node!.template[field]?.proxy; | ||
| const isToolMode = targetNode.data.node!.template[field]?.tool_mode; | ||
| const isAdvanced = targetNode.data.node!.template[field]?.advanced; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find all call-sites of cleanEdges and clearHandlesFromAdvancedFields
echo "=== cleanEdges call sites ==="
rg -n --type=ts --type=tsx -P '\bcleanEdges\s*\(' -A2 -B2
echo ""
echo "=== clearHandlesFromAdvancedFields call sites ==="
rg -n --type=ts --type=tsx -P '\bclearHandlesFromAdvancedFields\s*\(' -A2 -B2Repository: langflow-ai/langflow
Length of output: 217
🏁 Script executed:
# Read the relevant sections from reactflowUtils.ts to verify the logic
echo "=== Reading lines 150-210 (isAdvanced and cleanEdges logic) ==="
sed -n '150,210p' src/frontend/src/utils/reactflowUtils.ts | cat -n
echo ""
echo "=== Reading lines 250-295 (clearHandlesFromAdvancedFields) ==="
sed -n '250,295p' src/frontend/src/utils/reactflowUtils.ts | cat -n
echo ""
echo "=== Reading lines 2018-2030 (createNewFlow, locked property) ==="
sed -n '2018,2030p' src/frontend/src/utils/reactflowUtils.ts | cat -nRepository: langflow-ai/langflow
Length of output: 4765
🏁 Script executed:
# Check the FlowType definition to understand locked property expectations
echo "=== Searching for FlowType definition ==="
rg -n -B3 -A10 'type\s+FlowType|interface\s+FlowType' --type=ts --type=tsxRepository: langflow-ai/langflow
Length of output: 150
🏁 Script executed:
#!/bin/bash
# Search for cleanEdges and clearHandlesFromAdvancedFields call sites without file type restriction
echo "=== cleanEdges call sites ==="
rg -n 'cleanEdges\s*\(' -A2 -B2 2>/dev/null
echo ""
echo "=== clearHandlesFromAdvancedFields call sites ==="
rg -n 'clearHandlesFromAdvancedFields\s*\(' -A2 -B2 2>/dev/nullRepository: langflow-ai/langflow
Length of output: 6137
🏁 Script executed:
# Search for FlowType definition without file type restriction
echo "=== FlowType definition ==="
rg -n 'type FlowType|interface FlowType' -A15 2>/dev/null
echo ""
echo "=== Flow type with locked property ==="
rg -n 'locked\s*[:?]' -B5 -A2 2>/dev/null | head -80Repository: langflow-ai/langflow
Length of output: 9842
🏁 Script executed:
# Check where cleanEdges is invoked - search in the file itself for calls
echo "=== Checking invocations in reactflowUtils.ts ==="
grep -n 'cleanEdges(' src/frontend/src/utils/reactflowUtils.ts
echo ""
echo "=== Checking imports/usage of clearHandlesFromAdvancedFields ==="
grep -rn 'clearHandlesFromAdvancedFields' src/frontend/src/ --include="*.ts" 2>/dev/null | head -20Repository: langflow-ai/langflow
Length of output: 345
🏁 Script executed:
# Check the test file for cleanEdges to see if isAdvanced behavior is tested
echo "=== Checking cleanEdges test for isAdvanced ==="
grep -n "isAdvanced\|advanced" src/frontend/src/utils/__tests__/cleanEdges.test.ts -B2 -A2
echo ""
echo "=== Check what createNewFlow.test.ts says about locked ==="
grep -n "locked" src/frontend/src/utils/__tests__/createNewFlow.test.ts -B2 -A2Repository: langflow-ai/langflow
Length of output: 171
🏁 Script executed:
# Check flowStore to understand the complete flow of cleanEdges invocations
echo "=== View context around cleanEdges calls in flowStore.ts ==="
sed -n '215,225p' src/frontend/src/stores/flowStore.ts | cat -n
sed -n '295,305p' src/frontend/src/stores/flowStore.ts | cat -n
sed -n '350,365p' src/frontend/src/stores/flowStore.ts | cat -n
sed -n '658,668p' src/frontend/src/stores/flowStore.ts | cat -nRepository: langflow-ai/langflow
Length of output: 1860
🏁 Script executed:
# Check if there's a difference between "advanced" and "show" properties
echo "=== Searching for show property handling in cleanEdges or related ==="
grep -n "show\|advanced" src/frontend/src/utils/reactflowUtils.ts | head -30Repository: langflow-ai/langflow
Length of output: 1316
isAdvanced ORed unconditionally removes all edges to advanced fields on every cleanEdges call, causing silent data loss
The code at line 158 computes isAdvanced and ORs it into the removal predicate at lines 201-202:
if (
(scapedJSONStringfy(id) !== targetHandle ||
(targetNode.data.node?.tool_mode && isToolMode) ||
isAdvanced) &&
!isLoopInput
)
This removes ANY edge whose target field has advanced: true, even when scapedJSONStringfy(id) === targetHandle (the handle is still perfectly valid). Since cleanEdges is called on every flow state update (in resetFlow, setNodes, paste operations, and unselectAll in flowStore.ts), edges to advanced fields are silently removed on load and paste cycles. This makes it impossible for users to maintain persistent connections to advanced fields.
This contradicts the existing clearHandlesFromAdvancedFields function (lines 257–289), which is explicitly event-driven—it removes edges only when code in the modal changes—and is now rendered redundant. The filterHiddenFieldsEdges function already handles the distinct show === false case; conflating that with advanced: true here is incorrect.
The condition should not OR isAdvanced at the top level. Consider removing it entirely and relying on the event-driven cleanup, or intersecting it with a handle mismatch to avoid unconditional removal.
locked property lacks explicit fallback, unlike other optional fields
At line 2024, locked: flow?.locked returns undefined when flow is undefined, but the type expects boolean | null. Other fields in the same object use explicit fallbacks (icon: flow?.icon ?? undefined, is_component: flow?.is_component ?? false). For consistency, use locked: flow?.locked ?? false or ?? undefined.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/frontend/src/utils/reactflowUtils.ts` at line 158, The cleanEdges removal
predicate is incorrectly OR-ing isAdvanced (computed from
targetNode.data.node!.template[field]?.advanced) which causes all edges to
advanced fields to be removed unconditionally; update the predicate inside
cleanEdges (the block using scapedJSONStringfy(id) !== targetHandle,
targetNode.data.node?.tool_mode, isToolMode, isLoopInput) to remove isAdvanced
from the top-level OR and either delete it entirely or only apply it when the
handle mismatches (e.g., combine with scapedJSONStringfy(id) !== targetHandle)
so advanced-field edges are not dropped on every flow update; also keep the
event-driven cleanup in clearHandlesFromAdvancedFields and rely on
filterHiddenFieldsEdges for show===false cases. Separately, make the returned
locked property explicit by changing locked: flow?.locked to locked:
flow?.locked ?? false (or ?? undefined) so it never returns undefined
unexpectedly.
| GOOGLE_GENERATIVE_AI_MODELS_DETAILED = [ | ||
| # GEMINI 1.5 (stable) | ||
| create_model_metadata( | ||
| provider="Google Generative AI", | ||
| name="gemini-1.5-pro", | ||
| icon="GoogleGenerativeAI", | ||
| tool_calling=True, | ||
| ), | ||
| # GEMINI 2.5 (stable - recommended) | ||
| create_model_metadata( | ||
| provider="Google Generative AI", | ||
| name="gemini-1.5-flash", | ||
| name="gemini-2.5-flash", | ||
| icon="GoogleGenerativeAI", | ||
| tool_calling=True, | ||
| default=True, | ||
| ), | ||
| create_model_metadata( | ||
| provider="Google Generative AI", name="gemini-1.5-flash-8b", icon="GoogleGenerativeAI", tool_calling=True | ||
| ), | ||
| # GEMINI 2.0 (stable) | ||
| create_model_metadata( | ||
| provider="Google Generative AI", | ||
| name="gemini-2.0-flash-lite", | ||
| name="gemini-2.5-pro", | ||
| icon="GoogleGenerativeAI", | ||
| tool_calling=True, | ||
| ), | ||
| # GEMINI 2.5 (future/not yet released) | ||
| create_model_metadata( | ||
| provider="Google Generative AI", | ||
| name="gemini-2.5-pro", | ||
| name="gemini-2.5-flash-lite", | ||
| icon="GoogleGenerativeAI", | ||
| tool_calling=True, | ||
| preview=True, | ||
| not_supported=True, | ||
| ), | ||
| create_model_metadata( | ||
| provider="Google Generative AI", | ||
| name="gemini-2.5-flash", | ||
| name="gemini-2.5-flash-preview-09-2025", | ||
| icon="GoogleGenerativeAI", | ||
| tool_calling=True, | ||
| preview=True, | ||
| not_supported=True, | ||
| ), | ||
| create_model_metadata( | ||
| provider="Google Generative AI", | ||
| name="gemini-2.5-flash-lite", | ||
| name="gemini-2.5-flash-lite-preview-09-2025", | ||
| icon="GoogleGenerativeAI", | ||
| tool_calling=True, | ||
| preview=True, | ||
| not_supported=True, | ||
| ), | ||
| # GEMINI 3.0 (preview) | ||
| create_model_metadata( | ||
| provider="Google Generative AI", | ||
| name="gemini-3-pro-preview", | ||
| name="gemini-2.5-flash-image", | ||
| icon="GoogleGenerativeAI", | ||
| tool_calling=True, | ||
| preview=True, | ||
| ), | ||
| # GEMINI 2.0 (legacy - scheduled deprecation) | ||
| create_model_metadata( | ||
| provider="Google Generative AI", | ||
| name="gemini-3-flash-preview", | ||
| name="gemini-2.0-flash", | ||
| icon="GoogleGenerativeAI", | ||
| tool_calling=True, | ||
| preview=True, | ||
| deprecated=True, | ||
| ), | ||
| create_model_metadata( | ||
| provider="Google Generative AI", | ||
| name="gemini-3-pro-image-preview", | ||
| name="gemini-2.0-flash-lite", | ||
| icon="GoogleGenerativeAI", | ||
| tool_calling=True, | ||
| preview=True, | ||
| deprecated=True, | ||
| ), | ||
| # PREVIEW | ||
| create_model_metadata( | ||
| provider="Google Generative AI", | ||
| name="gemini-2.0-flash", | ||
| name="gemini-2.0-flash-preview-image-generation", | ||
| icon="GoogleGenerativeAI", | ||
| tool_calling=True, | ||
| preview=True, | ||
| deprecated=True, | ||
| ), | ||
| # GEMINI 3.0 (preview) | ||
| create_model_metadata( | ||
| provider="Google Generative AI", | ||
| name="gemini-exp-1206", | ||
| name="gemini-3-pro-preview", | ||
| icon="GoogleGenerativeAI", | ||
| tool_calling=True, | ||
| preview=True, | ||
| ), | ||
| create_model_metadata( | ||
| provider="Google Generative AI", | ||
| name="gemini-2.0-flash-thinking-exp-01-21", | ||
| name="gemini-3-flash-preview", | ||
| icon="GoogleGenerativeAI", | ||
| tool_calling=True, | ||
| preview=True, | ||
| ), | ||
| create_model_metadata( | ||
| provider="Google Generative AI", | ||
| name="learnlm-1.5-pro-experimental", | ||
| name="gemini-3-pro-image-preview", | ||
| icon="GoogleGenerativeAI", | ||
| tool_calling=True, | ||
| preview=True, | ||
| ), |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Google Gemini API available models 2025 2026 gemini-2.5-flash gemini-3-pro
💡 Result:
As of Feb 19, 2026, the official Gemini API model codes (Google AI for Developers) include:
- Gemini 2.5 Flash (stable):
gemini-2.5-flash(latest update: June 2025) [1][2] - Gemini 3 Pro (preview):
gemini-3-pro-preview(latest update: Nov 2025) [1][3] - Gemini 3.1 Pro (preview):
gemini-3.1-pro-previewandgemini-3.1-pro-preview-customtools(latest update: Feb 2026) [1][4] - Gemini 3 Flash (preview):
gemini-3-flash-preview(latest update: Dec 2025) [1][5]
So, gemini-2.5-flash is available (stable), while “Gemini 3 Pro” is exposed in the API as gemini-3-pro-preview (preview)—not gemini-3-pro (without -preview) per the current model list. [1][3]
Sources
[1] https://ai.google.dev/gemini-api/docs/models
[2] https://ai.google.dev/gemini-api/docs/models/gemini-2.5-flash
[3] https://ai.google.dev/gemini-api/docs/models/gemini-3-pro-preview
[4] https://ai.google.dev/gemini-api/docs/models/gemini-3.1-pro-preview
[5] https://ai.google.dev/gemini-api/docs/models/gemini-3-flash-preview
Several model names lack verification in official Google API documentation, and latest Gemini 3.1 models are missing.
Confirmed via Google's official API (Feb 19, 2026):
gemini-2.5-flash(stable) ✓gemini-3-pro-preview(preview) ✓gemini-3-flash-preview(preview) ✓
Cannot be verified in official Google API docs:
gemini-2.5-pro,gemini-2.5-flash-lite,gemini-2.5-flash-preview-09-2025,gemini-2.5-flash-lite-preview-09-2025,gemini-2.5-flash-image,gemini-3-pro-image-preview
Missing from code (available since Feb 2026):
gemini-3.1-pro-previewandgemini-3.1-pro-preview-customtoolsshould be added as the latest preview models.
Clarify whether unverified model names are internal/region-specific variants or if they should be removed. Update preview model names to remove outdated September 2025 suffixes if they no longer reflect the actual release status.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/lfx/src/lfx/base/models/google_generative_ai_constants.py` around lines 5
- 89, The list GOOGLE_GENERATIVE_AI_MODELS_DETAILED contains model entries
(created via create_model_metadata) that are either unverified against Google's
API (e.g., "gemini-2.5-pro", "gemini-2.5-flash-lite",
"gemini-2.5-flash-preview-09-2025", "gemini-2.5-flash-lite-preview-09-2025",
"gemini-2.5-flash-image", "gemini-3-pro-image-preview") and should be validated
or removed, and it is missing current Gemini 3.1 preview names; update the
constant by removing or flagging unverified/region-specific variants and add
entries for "gemini-3.1-pro-preview" and "gemini-3.1-pro-preview-customtools"
using create_model_metadata (mark preview=True), and rename/remove any outdated
"-09-2025" preview suffixes to match official model names.
This comment has been minimized.
This comment has been minimized.
|
Build successful! ✅ |
Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Tests