Fix/prevent duplicate flow creation#11016
Conversation
WalkthroughThis PR introduces comprehensive authentication hardening across multiple API endpoints, adds Streamable HTTP transport support for MCP alongside SSE, refactors file access patterns with centralized authorization and path safety, updates CI/CD workflows for dependency and wheel handling, and modernizes starter project templates with enhanced component logic, improved session handling, and expanded provider support. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant MCP Endpoint
participant StreamableHTTP Manager
participant MCP Server
participant Context
Client->>MCP Endpoint: Request to /mcp/streamable
MCP Endpoint->>Context: Get current user context
MCP Endpoint->>StreamableHTTP Manager: get_streamable_http_manager()
StreamableHTTP Manager-->>MCP Endpoint: Return active session manager
MCP Endpoint->>MCP Server: Delegate request handling
MCP Server-->>MCP Endpoint: Process request
MCP Endpoint->>Context: Reset user context token
MCP Endpoint->>Client: ResponseNoOp (no duplicate response)
Note over MCP Endpoint,MCP Server: New Streamable HTTP transport<br/>alongside existing SSE transport
sequenceDiagram
participant User
participant API Endpoint
participant Dependency Injection
participant Auth Service
participant Handler
User->>API Endpoint: Request to protected endpoint
API Endpoint->>Dependency Injection: Resolve Depends(get_current_active_user)
Dependency Injection->>Auth Service: get_current_active_user()
Alt User authenticated
Auth Service-->>Dependency Injection: Return User object
Dependency Injection-->>API Endpoint: Inject user parameter
API Endpoint->>Handler: Process request with current_user
Handler-->>User: Return response
Else User not authenticated
Auth Service-->>API Endpoint: Raise authentication error
API Endpoint-->>User: 401 Unauthorized
End
Note over API Endpoint,Auth Service: Authentication hardening<br/>across multiple endpoints
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Areas requiring extra attention:
Possibly related PRs
Suggested labels
Suggested reviewers
Pre-merge checks and finishing touchesImportant Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 error, 3 warnings)
✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
src/backend/base/langflow/initial_setup/starter_projects/Document Q&A.json (2)
472-488: Fixisinstancecalls using union types inChatOutput._validate_input.
_validate_inputcurrently usesisinstance(item, Message | Data | DataFrame | str)andisinstance(self.input_value, Message | Data | DataFrame | str | list | Generator | type(None)). The second argument toisinstancemust be a type or tuple of types; passing a PEP 604 union can raiseTypeErrorat runtime.You can keep the same semantics with tuples:
- if isinstance(self.input_value, list) and not all( - isinstance(item, Message | Data | DataFrame | str) for item in self.input_value - ): + if isinstance(self.input_value, list) and not all( + isinstance(item, (Message, Data, DataFrame, str)) for item in self.input_value + ): @@ - if not isinstance( - self.input_value, - Message | Data | DataFrame | str | list | Generator | type(None), - ): + if not isinstance( + self.input_value, + (Message, Data, DataFrame, str, list, Generator, type(None)), + ):
1190-1287: Align Docling advanced processing with per-file rollup inFileComponent.process_files.In the advanced Docling branch,
process_filesloops over eachfilebut callsself.rollup_data(file_list, rows)(and similarly with[advanced_data]). This mixes a single file’s rows with the fullfile_list, which is likely to mis-associate rows and files when more than one file is processed.To keep the mapping correct, use the current
fileinstead of the wholefile_list:- final_return: list[BaseFileComponent.BaseFile] = [] + final_return: list[BaseFileComponent.BaseFile] = [] for file in file_list: file_path = str(file.path) advanced_data: Data | None = self._process_docling_in_subprocess(file_path) @@ - final_return.extend(self.rollup_data(file_list, rows)) + final_return.extend(self.rollup_data([file], rows)) @@ - final_return.extend(self.rollup_data([file], [empty_data])) + final_return.extend(self.rollup_data([file], [empty_data])) else: # If not structured, keep as-is (e.g., markdown export or error dict) - final_return.extend(self.rollup_data(file_list, [advanced_data])) + final_return.extend(self.rollup_data([file], [advanced_data]))This keeps each Docling result correctly bound to its originating file while preserving the unnesting behavior.
src/backend/base/langflow/api/v1/mcp_projects.py (1)
688-688:generated_api_keyis alwaysNone.The variable
generated_api_keyis initialized toNoneat line 688 but never assigned a value. The conditional at line 860 will always beFalse, making the associated message unreachable.Either assign
generated_api_keywhen an API key is created (around line 776), or remove the dead code:if should_generate_api_key: async with session_scope() as api_key_session: api_key_create = ApiKeyCreate(name=f"MCP Server {project.name}") api_key_response = await create_api_key(api_key_session, api_key_create, current_user.id) langflow_api_key = api_key_response.api_key + generated_api_key = langflow_api_key args.extend(["--headers", "x-api-key", langflow_api_key])Also applies to: 860-862
♻️ Duplicate comments (2)
src/backend/base/langflow/initial_setup/starter_projects/Knowledge Retrieval.json (1)
235-311: ChatOutput here matches the validated implementation; no additional issues.This
ChatOutputinstance embeds the same implementation and FastAPI/orjson dependency versions as in the Meeting Summary starter. The earlier review of that code/deps applies here as well; behavior and types are consistent.As with the other starters, ensure the pinned
fastapiandorjsonversions are present and compatible in your runtime.src/backend/base/langflow/initial_setup/starter_projects/Price Deal Finder.json (1)
479-496: Apply the sameChatOutput._validate_inputfix here as in “Document Q&A”.This file embeds the same
ChatOutputimplementation, including theisinstance(..., Message | Data | DataFrame | str)andisinstance(..., Message | Data | DataFrame | str | list | Generator | type(None))patterns. Please update them to use tuples of types as shown in the earlier comment onDocument Q&A.jsonso both starter projects share the corrected implementation.
🧹 Nitpick comments (21)
src/backend/base/langflow/api/v1/users.py (1)
25-48: LGTM! Security hardening correctly implemented.The addition of superuser authentication to the user creation endpoint is an important security improvement that prevents unauthorized account creation. The implementation correctly uses
Depends(get_current_active_superuser)and the docstring accurately documents the requirement.Optional: Consider using the
dependenciespattern for consistency.Since
current_useris not used in the function body (hence the# noqa: ARG001), consider using thedependenciespattern in the decorator for consistency with theread_all_usersendpoint on line 59:-@router.post("/", response_model=UserRead, status_code=201) +@router.post("/", response_model=UserRead, status_code=201, dependencies=[Depends(get_current_active_superuser)]) async def add_user( user: UserCreate, session: DbSession, - current_user: Annotated[User, Depends(get_current_active_superuser)], # noqa: ARG001 ) -> User:This makes it more explicit that the dependency is purely for authentication and avoids the need for the
noqacomment. Both approaches are functionally equivalent, but thedependenciespattern is generally preferred when the injected value isn't used.src/backend/base/langflow/initial_setup/starter_projects/Invoice Summarizer.json (1)
1241-1299: Add missing display_name to agent_llm dropdown.The
agent_llmdropdown input (lines 1241-1299) is missing adisplay_namefield in the nested component definition. While it has a default label "Model Provider", ensure the field structure is complete and consistent with other input fields in the template.src/backend/base/langflow/api/v1/mcp_utils.py (2)
96-101: Overly broad exception catch may hide bugs.Catching
Exceptionwith# noqa: BLE001suppresses linting but may hide unexpected errors beyond typicalLookupErrorfromContextVar.get(). Consider catchingLookupErrorspecifically, which is whatContextVar.get()raises when no value is set.- try: - current_user = current_user_ctx.get() - except Exception as e: # noqa: BLE001 - msg = f"Error getting current user: {e!s}" - await logger.aexception(msg) - current_user = None + try: + current_user = current_user_ctx.get() + except LookupError: + await logger.adebug("No current user context set, skipping user files listing") + current_user = None
139-140: Potential issue:stored_filenamemay be empty if bothpathandnameare empty.If
stored_pathis empty anduser_file.nameis also empty/None,stored_filenamecould be empty, leading to invalid resource URIs.+ if not stored_filename: + await logger.adebug(f"Skipping user file with empty filename: {user_file.id}") + continue safe_filename = quote(stored_filename)src/backend/base/langflow/helpers/flow.py (4)
52-57: Mutable default argument is a known anti-pattern.While
# noqa: B006suppresses the linter, using a mutable default (dict) can lead to unexpected behavior if the dict is ever mutated. Consider usingNoneas default with initialization inside the function, similar tolist_flows_by_folder_id.async def list_flows_by_flow_folder( *, user_id: str | None = None, flow_id: str | None = None, - order_params: dict | None = {"column": "updated_at", "direction": "desc"}, # noqa: B006 + order_params: dict | None = None, ) -> list[Data]: + if order_params is None: + order_params = {"column": "updated_at", "direction": "desc"}
86-86: Accessing private_mappingattribute is fragile.Using
flow._mapping(noqa: SLF001) relies on SQLAlchemy's internal Row representation. This could break with SQLAlchemy version updates. Consider using a more explicit conversion.- return [Data(data=dict(flow._mapping)) for flow in flows] # noqa: SLF001 + return [Data(data={"id": flow.id, "name": flow.name, "updated_at": flow.updated_at}) for flow in flows]
141-150: Redundant validation after initial check.Lines 148-150 check
if not (attr and val)but this condition is impossible to reach given the preceding logic. Ifflow_nameis truthy,attrandvalare set. Ifflow_idis truthy, they're overwritten. The initial check at line 135 ensures at least one is truthy.- if not (attr and val): - msg = "Flow id or Name is required" - raise ValueError(msg)
114-117: Redundantorder_params is not Nonecheck.At line 102-103,
order_paramsis guaranteed to be non-None after the initialization. The check at line 114 is always true.- if order_params is not None: - sort_col = getattr(Flow, order_params.get("column", "updated_at"), Flow.updated_at) - sort_dir = SORT_DISPATCHER.get(order_params.get("direction", "desc"), desc) - stmt = stmt.order_by(sort_dir(sort_col)) + sort_col = getattr(Flow, order_params.get("column", "updated_at"), Flow.updated_at) + sort_dir = SORT_DISPATCHER.get(order_params.get("direction", "desc"), desc) + stmt = stmt.order_by(sort_dir(sort_col))src/backend/base/langflow/api/v1/schemas.py (1)
473-475: Consider documenting the transport field options.Adding a
Fielddescription would improve API documentation clarity for consumers.class MCPInstallRequest(BaseModel): client: str - transport: Literal["sse", "streamablehttp"] | None = None + transport: Literal["sse", "streamablehttp"] | None = Field( + default=None, + description="Transport protocol: 'sse' for Server-Sent Events or 'streamablehttp' for Streamable HTTP" + )src/backend/base/langflow/api/v2/files.py (1)
229-230: Generic error message hides debugging information.While returning 500 for server config issues is correct, the generic "Error accessing storage" message may make troubleshooting difficult. Consider logging the actual error while returning the generic message.
except PermissionError as e: # Access denied or invalid credentials - return 500 as this is a server config issue + await logger.aerror(f"Storage permission error for user {current_user.id}: {e}") raise HTTPException(status_code=500, detail="Error accessing storage") from esrc/backend/base/langflow/initial_setup/starter_projects/Meeting Summary.json (1)
1656-1720: MemoryComponent logic looks consistent with existing patterns.
MemoryComponent’s store/retrieve paths, telemetry, and type usage (Data/DataFrame/Message) are coherent and match typical Langflow memory patterns; no correctness or safety issues stand out here in this starter snapshot.You may eventually want to tighten the return typing of
retrieve_messages(it returns a list but is cast toData) for better static checking, but this is non‑blocking for the starter.src/backend/base/langflow/api/v1/chat.py (3)
58-131:retrieve_vertices_orderendpoint logic is reasonable; consider minor robustness tweaks.The new
/build/{flow_id}/verticesendpoint correctly:
- Reuses
build_graph_from_db/build_and_cache_graph_from_data,- Sets a fresh
run_idand caches the graph for later use, and- Logs playground telemetry in both success and error paths.
Two small refinements you might consider (non‑blocking):
- Use
if data is None:instead ofif not data:to avoid depending on the truthiness ofFlowDataRequest.vertices_to_runis built viaset.union(...), which makes ordering implementation‑defined; if the client relies on a stable order, returning a sorted list (or preserving the original sequence) would be safer.
201-216: Auth‑gatingGET /build/{job_id}/eventsmay block public flows; verify call paths.Requiring
get_current_active_userfor the events endpoint is appropriate for authenticated builds, but note that:
build_public_tmpexplicitly supports unauthenticated “public” flows and still returnsjob_idwhenevent_delivery != EventDeliveryType.DIRECT.- There is no separate unauthenticated events route for public jobs; clients would need to call this same
/build/{job_id}/events, which now requires auth.If any callers rely on polling/streaming events for public flows without authentication, those flows will now fail with 401. Either:
- Ensure public flows always use
event_delivery=EventDeliveryType.DIRECTso they never hit this route, or- Introduce a dedicated events endpoint (or conditional auth) for public jobs.
219-255:cancel_buildnow returns a structured response and has clearer error handling.The updated
cancel_buildendpoint:
- Enforces authentication,
- Returns a typed
CancelFlowResponsewith a clearsuccessflag and message, and- Distinguishes between normal failures, job‑not‑found (
ValueError/JobQueueNotFoundError→ 404), and unexpected errors (500).Behaviorally this is much easier for clients to reason about. One thing to keep in mind is that generic exceptions are surfaced via
str(exc)in the HTTP 500, which may leak internal details; if that’s a concern, you might want to replace it with a generic message and keep details in logs only.src/backend/base/langflow/api/v1/files.py (3)
179-207: Comprehensive path traversal protection.The multi-layered defense is well implemented:
- Reject
..patterns explicitly- Validate against allowed folder whitelist
- Reject path separators in filename
- Use
resolve()+startswith()for symlink-aware containment checkHowever, the
startswith()check on string paths can have edge cases (e.g.,/allowed_basevs/allowed_base_other).Consider using
Path.is_relative_to()(Python 3.9+) for more robust containment:- if not str(file_path).startswith(str(allowed_base)): + try: + file_path.relative_to(allowed_base) + except ValueError: # Return 404 to prevent path traversal attempts from revealing system structure raise HTTPException(status_code=404, detail="Profile picture not found")
216-220: Apply consistent path containment check for package fallback.The same
startswith()consideration applies to the package path validation. For consistency, apply the same improvement here.- if not str(package_path).startswith(str(allowed_package_base)): + try: + package_path.relative_to(allowed_package_base) + except ValueError: # Return 404 to prevent path traversal attempts from revealing system structure raise HTTPException(status_code=404, detail="Profile picture not found")
49-53: Consider more specific exception handling.The bare
except Exceptioncatches all exceptions includingKeyboardInterruptandSystemExit(though those derive fromBaseException). The logging is good, but consider catching more specific exceptions.- except Exception as _: - import logging - - logger = logging.getLogger(__name__) - logger.exception("Exception occurred while getting allowed profile picture folders") + except OSError: + # File system errors when enumerating directories + import logging + logger = logging.getLogger(__name__) + logger.exception("Exception occurred while getting allowed profile picture folders")src/backend/base/langflow/initial_setup/starter_projects/Research Agent.json (1)
2780-2780: Review extensive Agent component code changes for correctness.The Agent component's embedded code (line 2780 onwards) underwent a major refactoring introducing:
- Dynamic provider switching with MODEL_PROVIDERS_DICT
- Structured output support with schema validation
- Multiple new async methods (get_agent_requirements, get_llm, json_response, get_memory_data)
- Complex field visibility and configuration logic in update_build_config
Risks to assess:
- The code is deeply embedded in a JSON configuration file, making maintenance and testing difficult
- Multiple levels of indirection in provider handling (MODEL_PROVIDERS_DICT → component_class → _build_llm_model)
- Exception handling catches broad Exception types that could mask unexpected errors
- Memory data retrieval logic filters messages by ID comparison but doesn't validate message object structure
Consider refactoring this embedded code into separate, testable Python modules.
src/backend/base/langflow/api/v1/mcp_projects.py (3)
427-433: Use%-style formatting for logger calls.Using f-strings in logger calls evaluates the string even when the log level is disabled. Prefer
%-style formatting for better performance.try: await project_server.session_manager.handle_request(request.scope, request.receive, request._send) # noqa: SLF001 except HTTPException: raise except Exception as exc: - await logger.aexception(f"Error handling Streamable HTTP request for project {project_id}: {exc!s}") + await logger.aexception("Error handling Streamable HTTP request for project %s: %s", project_id, exc) raise HTTPException(status_code=500, detail="Internal server error in project MCP transport") from exc
1251-1265: Use%-style formatting for logger calls in_run_session_manager.Multiple f-strings are used in logger calls within this method. Prefer
%-style formatting for consistency and performance.async def _run_session_manager(self, *, task_status: TaskStatus[None] = anyio.TASK_STATUS_IGNORED): """Own the lifecycle of the project's Streamable HTTP session manager.""" try: async with self.session_manager.run(): self._manager_started = True # set flag before unblocking task (ensures waiting requests proceed) task_status.started() # unblock await anyio.sleep_forever() except anyio.get_cancelled_exc_class(): - await logger.adebug(f"Streamable HTTP manager cancelled for project {self.project_id}") + await logger.adebug("Streamable HTTP manager cancelled for project %s", self.project_id) except Exception as e: - await logger.aexception(f"Error in session manager for project {self.project_id}: {e}") + await logger.aexception("Error in session manager for project %s: %s", self.project_id, e) raise finally: self._manager_started = False - await logger.adebug(f"Streamable HTTP manager stopped for project {self.project_id}") + await logger.adebug("Streamable HTTP manager stopped for project %s", self.project_id)
1319-1326: Use%-style formatting for logger call.try: # https://anyio.readthedocs.io/en/stable/cancellation.html, https://docs.python.org/3/library/asyncio-task.html#asyncio.Task.cancel self._task_group.cancel_scope.cancel() # type: ignore[union-attr] await self._tg_task # type: ignore[misc] except Exception as e: # noqa: BLE001 - await logger.aexception(f"Failed to stop project task group: {e}") + await logger.aexception("Failed to stop project task group: %s", e) finally: self._cleanup() await logger.adebug("Project MCP task group stopped")
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
src/frontend/package-lock.jsonis excluded by!**/package-lock.jsonuv.lockis excluded by!**/*.lock
📒 Files selected for processing (41)
.env.example(1 hunks).github/workflows/cross-platform-test.yml(5 hunks).github/workflows/nightly_build.yml(0 hunks).github/workflows/release.yml(1 hunks).github/workflows/release_nightly.yml(1 hunks).secrets.baseline(3 hunks)pyproject.toml(1 hunks)src/backend/base/langflow/__main__.py(0 hunks)src/backend/base/langflow/api/log_router.py(3 hunks)src/backend/base/langflow/api/utils/core.py(1 hunks)src/backend/base/langflow/api/utils/mcp/__init__.py(1 hunks)src/backend/base/langflow/api/utils/mcp/config_utils.py(6 hunks)src/backend/base/langflow/api/v1/chat.py(4 hunks)src/backend/base/langflow/api/v1/endpoints.py(2 hunks)src/backend/base/langflow/api/v1/files.py(7 hunks)src/backend/base/langflow/api/v1/mcp.py(4 hunks)src/backend/base/langflow/api/v1/mcp_projects.py(28 hunks)src/backend/base/langflow/api/v1/mcp_utils.py(6 hunks)src/backend/base/langflow/api/v1/monitor.py(6 hunks)src/backend/base/langflow/api/v1/projects.py(4 hunks)src/backend/base/langflow/api/v1/schemas.py(1 hunks)src/backend/base/langflow/api/v1/users.py(1 hunks)src/backend/base/langflow/api/v1/validate.py(2 hunks)src/backend/base/langflow/api/v2/files.py(3 hunks)src/backend/base/langflow/api/v2/registration.py(2 hunks)src/backend/base/langflow/helpers/flow.py(3 hunks)src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json(5 hunks)src/backend/base/langflow/initial_setup/starter_projects/Basic Prompting.json(5 hunks)src/backend/base/langflow/initial_setup/starter_projects/Blog Writer.json(9 hunks)src/backend/base/langflow/initial_setup/starter_projects/Custom Component Generator.json(7 hunks)src/backend/base/langflow/initial_setup/starter_projects/Document Q&A.json(9 hunks)src/backend/base/langflow/initial_setup/starter_projects/Financial Report Parser.json(10 hunks)src/backend/base/langflow/initial_setup/starter_projects/Image Sentiment Analysis.json(8 hunks)src/backend/base/langflow/initial_setup/starter_projects/Instagram Copywriter.json(25 hunks)src/backend/base/langflow/initial_setup/starter_projects/Invoice Summarizer.json(23 hunks)src/backend/base/langflow/initial_setup/starter_projects/Knowledge Ingestion.json(5 hunks)src/backend/base/langflow/initial_setup/starter_projects/Knowledge Retrieval.json(6 hunks)src/backend/base/langflow/initial_setup/starter_projects/Meeting Summary.json(13 hunks)src/backend/base/langflow/initial_setup/starter_projects/Memory Chatbot.json(7 hunks)src/backend/base/langflow/initial_setup/starter_projects/Price Deal Finder.json(23 hunks)src/backend/base/langflow/initial_setup/starter_projects/Research Agent.json(23 hunks)
💤 Files with no reviewable changes (2)
- .github/workflows/nightly_build.yml
- src/backend/base/langflow/main.py
🧰 Additional context used
📓 Path-based instructions (3)
src/backend/**/*.py
📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)
src/backend/**/*.py: Use FastAPI async patterns withawaitfor async operations in component execution methods
Useasyncio.create_task()for background tasks and implement proper cleanup with try/except forasyncio.CancelledError
Usequeue.put_nowait()for non-blocking queue operations andasyncio.wait_for()with timeouts for controlled get operations
Files:
src/backend/base/langflow/api/log_router.pysrc/backend/base/langflow/api/v1/schemas.pysrc/backend/base/langflow/api/utils/mcp/__init__.pysrc/backend/base/langflow/api/v1/validate.pysrc/backend/base/langflow/api/v1/users.pysrc/backend/base/langflow/api/v1/files.pysrc/backend/base/langflow/api/v1/monitor.pysrc/backend/base/langflow/api/utils/mcp/config_utils.pysrc/backend/base/langflow/helpers/flow.pysrc/backend/base/langflow/api/v2/registration.pysrc/backend/base/langflow/api/v1/projects.pysrc/backend/base/langflow/api/v1/mcp.pysrc/backend/base/langflow/api/v1/mcp_utils.pysrc/backend/base/langflow/api/v1/endpoints.pysrc/backend/base/langflow/api/utils/core.pysrc/backend/base/langflow/api/v2/files.pysrc/backend/base/langflow/api/v1/chat.pysrc/backend/base/langflow/api/v1/mcp_projects.py
src/backend/base/langflow/api/**/*.py
📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)
Backend API endpoints should be organized by version (v1/, v2/) under
src/backend/base/langflow/api/with specific modules for features (chat.py, flows.py, users.py, etc.)
Files:
src/backend/base/langflow/api/log_router.pysrc/backend/base/langflow/api/v1/schemas.pysrc/backend/base/langflow/api/utils/mcp/__init__.pysrc/backend/base/langflow/api/v1/validate.pysrc/backend/base/langflow/api/v1/users.pysrc/backend/base/langflow/api/v1/files.pysrc/backend/base/langflow/api/v1/monitor.pysrc/backend/base/langflow/api/utils/mcp/config_utils.pysrc/backend/base/langflow/api/v2/registration.pysrc/backend/base/langflow/api/v1/projects.pysrc/backend/base/langflow/api/v1/mcp.pysrc/backend/base/langflow/api/v1/mcp_utils.pysrc/backend/base/langflow/api/v1/endpoints.pysrc/backend/base/langflow/api/utils/core.pysrc/backend/base/langflow/api/v2/files.pysrc/backend/base/langflow/api/v1/chat.pysrc/backend/base/langflow/api/v1/mcp_projects.py
{pyproject.toml,uv.lock}
📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)
Use
uv(>=0.4) for Python dependency management in backend development
Files:
pyproject.toml
🧠 Learnings (14)
📚 Learning: 2025-09-21T09:46:44.276Z
Learnt from: iann0036
Repo: langflow-ai/langflow PR: 9935
File: src/lfx/src/lfx/components/amazon/aws_api_call.py:35-48
Timestamp: 2025-09-21T09:46:44.276Z
Learning: Amazon components in the Langflow bundle consistently require explicit AWS credentials (aws_access_key_id and aws_secret_access_key with required=True) rather than falling back to environment/machine credentials for security reasons in hosted environments.
Applied to files:
.env.example
📚 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 src/backend/base/langflow/components/**/__init__.py : Update `__init__.py` with alphabetically sorted imports when adding new components
Applied to files:
src/backend/base/langflow/api/utils/mcp/__init__.pysrc/backend/base/langflow/helpers/flow.pysrc/backend/base/langflow/initial_setup/starter_projects/Custom Component Generator.json
📚 Learning: 2025-07-23T21:19:22.567Z
Learnt from: deon-sanchez
Repo: langflow-ai/langflow PR: 9158
File: src/backend/base/langflow/api/v1/mcp_projects.py:404-404
Timestamp: 2025-07-23T21:19:22.567Z
Learning: In langflow MCP projects configuration, prefer using dynamically computed URLs (like the `sse_url` variable) over hardcoded localhost URLs to ensure compatibility across different deployment environments.
Applied to files:
src/backend/base/langflow/api/utils/mcp/__init__.pysrc/backend/base/langflow/api/utils/mcp/config_utils.pysrc/backend/base/langflow/api/v1/projects.pysrc/backend/base/langflow/api/v1/mcp_projects.py
📚 Learning: 2025-10-29T03:59:53.796Z
Learnt from: ricofurtado
Repo: langflow-ai/langflow PR: 10430
File: src/backend/base/langflow/api/v2/registration.py:0-0
Timestamp: 2025-10-29T03:59:53.796Z
Learning: The user registration functionality in `src/backend/base/langflow/api/v2/registration.py` is temporary and will be deprecated when single-user registration is confirmed as a requirement for the langflow project.
Applied to files:
src/backend/base/langflow/api/v1/users.pysrc/backend/base/langflow/api/v2/registration.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 Langflow's `Message` objects using `langflow.schema.message.Message` and validate text, sender, sender_name, session_id, files, and properties attributes
Applied to files:
src/backend/base/langflow/api/v1/monitor.pysrc/backend/base/langflow/api/v1/mcp_utils.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 Langflow REST API endpoints using the `client` fixture with appropriate HTTP methods (GET, POST, etc.), headers (logged_in_headers), and payload validation
Applied to files:
.github/workflows/release_nightly.ymlsrc/backend/base/langflow/api/v1/endpoints.py
📚 Learning: 2025-10-29T04:04:47.426Z
Learnt from: ricofurtado
Repo: langflow-ai/langflow PR: 10430
File: src/backend/base/langflow/api/v2/registration.py:25-26
Timestamp: 2025-10-29T04:04:47.426Z
Learning: The user registration endpoints in `src/backend/base/langflow/api/v2/registration.py` are specifically designed for Desktop environment deployment only, not for server or containerized deployments.
Applied to files:
src/backend/base/langflow/api/v2/registration.pysrc/backend/base/langflow/api/v1/endpoints.py
📚 Learning: 2025-10-29T03:55:50.216Z
Learnt from: ricofurtado
Repo: langflow-ai/langflow PR: 10430
File: src/backend/base/langflow/api/v2/registration.py:0-0
Timestamp: 2025-10-29T03:55:50.216Z
Learning: In the langflow project, user registration endpoints in API v2 (`src/backend/base/langflow/api/v2/registration.py`) are intentionally designed to be unauthenticated to support Desktop application initialization and onboarding flows.
Applied to files:
src/backend/base/langflow/api/v2/registration.pysrc/backend/base/langflow/api/v1/endpoints.py
📚 Learning: 2025-06-26T19:43:18.260Z
Learnt from: ogabrielluiz
Repo: langflow-ai/langflow PR: 0
File: :0-0
Timestamp: 2025-06-26T19:43:18.260Z
Learning: In langflow custom components, the `module_name` parameter is now propagated through template building functions to add module metadata and code hashes to frontend nodes for better component tracking and debugging.
Applied to files:
src/backend/base/langflow/initial_setup/starter_projects/Custom Component Generator.json
📚 Learning: 2025-08-07T20:23:23.569Z
Learnt from: edwinjosechittilappilly
Repo: langflow-ai/langflow PR: 0
File: :0-0
Timestamp: 2025-08-07T20:23:23.569Z
Learning: Some Langflow starter project files and components still use `from loguru import logger` instead of the centralized structlog logger from `langflow.logging.logger`. These should be updated to ensure consistent structured logging across the entire codebase.
Applied to files:
src/backend/base/langflow/initial_setup/starter_projects/Custom Component Generator.json
📚 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 src/backend/base/langflow/components/**/*.py : Add new components to the appropriate subdirectory under `src/backend/base/langflow/components/` (agents/, data/, embeddings/, input_output/, models/, processing/, prompts/, tools/, or vectorstores/)
Applied to files:
src/backend/base/langflow/initial_setup/starter_projects/Custom Component Generator.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Instagram Copywriter.json
📚 Learning: 2025-08-07T20:23:23.569Z
Learnt from: edwinjosechittilappilly
Repo: langflow-ai/langflow PR: 0
File: :0-0
Timestamp: 2025-08-07T20:23:23.569Z
Learning: The Langflow codebase has an excellent structlog implementation that follows best practices, with proper global configuration, environment-based output formatting, and widespread adoption across components. The main cleanup needed is updating starter project templates and documentation examples that still contain legacy `from loguru import logger` imports.
Applied to files:
src/backend/base/langflow/initial_setup/starter_projects/Custom Component Generator.json
📚 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 {pyproject.toml,uv.lock} : Use `uv` (>=0.4) for Python dependency management in backend development
Applied to files:
.github/workflows/cross-platform-test.yml
📚 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 src/backend/base/langflow/api/**/*.py : Backend API endpoints should be organized by version (v1/, v2/) under `src/backend/base/langflow/api/` with specific modules for features (chat.py, flows.py, users.py, etc.)
Applied to files:
src/backend/base/langflow/api/v1/endpoints.pysrc/backend/base/langflow/api/v1/chat.py
🧬 Code graph analysis (11)
src/backend/base/langflow/api/log_router.py (1)
src/backend/base/langflow/services/auth/utils.py (1)
get_current_active_user(261-264)
src/backend/base/langflow/api/utils/mcp/__init__.py (1)
src/backend/base/langflow/api/utils/mcp/config_utils.py (4)
get_composer_streamable_http_url(256-265)get_project_sse_url(233-238)get_project_streamable_http_url(225-230)get_url_by_os(181-204)
src/backend/base/langflow/api/v1/validate.py (1)
src/backend/base/langflow/services/auth/utils.py (1)
get_current_active_user(261-264)
src/backend/base/langflow/api/v1/users.py (2)
src/backend/tests/unit/api/v2/test_mcp_servers_file.py (1)
current_user(87-91)src/backend/base/langflow/services/auth/utils.py (1)
get_current_active_superuser(267-272)
src/backend/base/langflow/api/v1/monitor.py (4)
src/backend/base/langflow/services/database/models/flow/model.py (1)
Flow(186-213)src/backend/base/langflow/services/database/models/message/model.py (1)
MessageTable(126-171)src/backend/base/langflow/services/database/models/transactions/crud.py (1)
transform_transaction_table(77-82)src/backend/base/langflow/services/auth/utils.py (1)
get_current_active_user(261-264)
src/backend/base/langflow/helpers/flow.py (1)
src/backend/base/langflow/services/database/models/flow/model.py (2)
Flow(186-213)to_data(198-208)
src/backend/base/langflow/api/v2/registration.py (1)
src/backend/base/langflow/services/auth/utils.py (1)
get_current_active_user(261-264)
src/backend/base/langflow/api/v1/projects.py (2)
src/backend/base/langflow/api/utils/mcp/config_utils.py (2)
get_project_sse_url(233-238)get_project_streamable_http_url(225-230)src/backend/base/langflow/api/v1/mcp_projects.py (1)
register_project_with_composer(1378-1410)
src/backend/base/langflow/api/v1/endpoints.py (3)
src/backend/base/langflow/services/deps.py (1)
get_settings_service(125-138)src/backend/base/langflow/services/auth/utils.py (1)
get_current_active_user(261-264)src/backend/base/langflow/api/v1/schemas.py (1)
ConfigResponse(362-412)
src/backend/base/langflow/api/v2/files.py (3)
src/backend/base/langflow/services/storage/service.py (2)
get_file_size(82-83)get_file_stream(61-75)src/lfx/src/lfx/services/storage/local.py (1)
get_file_size(188-213)src/lfx/src/lfx/base/data/storage_utils.py (1)
get_file_size(139-174)
src/backend/base/langflow/api/v1/chat.py (5)
src/backend/base/langflow/services/auth/utils.py (1)
get_current_active_user(261-264)src/backend/base/langflow/services/deps.py (1)
get_queue_service(242-246)src/backend/base/langflow/api/utils/core.py (1)
EventDeliveryType(44-47)src/backend/base/langflow/api/build.py (1)
get_flow_events_response(101-164)src/backend/base/langflow/api/v1/schemas.py (1)
CancelFlowResponse(415-419)
🪛 Gitleaks (8.30.0)
.secrets.baseline
[high] 762-762: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
[high] 770-770: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
[high] 780-780: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
[high] 788-788: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
[high] 798-798: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
[high] 806-806: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
[high] 816-816: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
[high] 824-824: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
[high] 834-834: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
[high] 844-844: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
[high] 852-852: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
[high] 860-860: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
[high] 868-868: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
| "cuga~=0.1.11", | ||
| "agent-lifecycle-toolkit~=0.4.4", |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
cuga 0.1.11 PyPI package
💡 Result:
There is no cuga 0.1.11 on PyPI. The latest published release on PyPI is 0.1.7 (uploaded Nov 14, 2025). See the package page for release history. [1]
If you need me to check a different index or the project’s GitHub for unreleased tags, I can do that. [1]
🌐 Web query:
agent-lifecycle-toolkit 0.4.4 PyPI package
💡 Result:
I couldn't find a PyPI release for agent-lifecycle-toolkit version 0.4.4. The project's PyPI release history shows 0.4.0, 0.4.1 and 0.4.2 (and later 0.5.0+), but no 0.4.4 entry. [1][2]
Sources:
- agent-lifecycle-toolkit PyPI project page (release history). [1]
- agent-lifecycle-toolkit PyPI specific release page (0.4.1 / 0.4.2 shown). [2]
Dependency versions do not exist on PyPI and will cause installation failures.
The specified versions cannot be installed:
cuga 0.1.11does not exist on PyPI (latest available is 0.1.7)agent-lifecycle-toolkit 0.4.4does not exist on PyPI (available versions: 0.4.0, 0.4.1, 0.4.2, then 0.5.0+)
Update these to existing versions available on PyPI, or if these versions are intentionally unpublished, clarify the dependency source.
🤖 Prompt for AI Agents
In pyproject.toml around lines 138-139, the pinned versions "cuga~=0.1.11" and
"agent-lifecycle-toolkit~=0.4.4" do not exist on PyPI and will break installs;
change them to valid published releases (e.g., "cuga~=0.1.7" and
"agent-lifecycle-toolkit~=0.4.2" or to "agent-lifecycle-toolkit~=0.5.0" if you
need the newer series), or if those exact unpublished versions are required,
replace the entries with a valid VCS or private index source (add the repository
URL or --extra-index-url) and update the project documentation to explain the
non-PyPI source.
| async def _get_mcp_composer_auth_config(project: Folder) -> dict: | ||
| """Decrypt and return MCP Composer auth configuration for a project.""" | ||
| auth_config = None | ||
| if project.auth_settings: | ||
| decrypted_settings = decrypt_auth_settings(project.auth_settings) | ||
| if decrypted_settings: | ||
| auth_config = decrypted_settings | ||
|
|
||
| if not auth_config: | ||
| error_message = "Auth config is missing. Please check your settings and try again." | ||
| raise ValueError(error_message) | ||
|
|
||
| return auth_config | ||
|
|
||
|
|
||
| async def get_composer_streamable_http_url(project: Folder) -> str: | ||
| """Generate Streamable HTTP URL for the MCP Composer instance.""" | ||
| auth_config = await _get_mcp_composer_auth_config(project) | ||
| composer_host = auth_config.get("oauth_host") | ||
| composer_port = auth_config.get("oauth_port") | ||
| if not composer_host or not composer_port: | ||
| error_msg = "OAuth host and port are required to get the MCP Composer URL" | ||
| raise ValueError(error_msg) | ||
| composer_url = f"http://{composer_host}:{composer_port}" | ||
| return await get_url_by_os(composer_host, int(composer_port), composer_url) # type: ignore[arg-type] |
There was a problem hiding this comment.
Add error handling for invalid port values.
The get_composer_streamable_http_url function converts composer_port to int at line 265, but if the decrypted config contains an invalid value (e.g., non-numeric string), this will raise a ValueError that propagates as a 500 error.
Consider adding validation:
composer_host = auth_config.get("oauth_host")
composer_port = auth_config.get("oauth_port")
if not composer_host or not composer_port:
error_msg = "OAuth host and port are required to get the MCP Composer URL"
raise ValueError(error_msg)
+ try:
+ port = int(composer_port)
+ except (ValueError, TypeError) as e:
+ raise ValueError(f"Invalid oauth_port value: {composer_port}") from e
composer_url = f"http://{composer_host}:{composer_port}"
- return await get_url_by_os(composer_host, int(composer_port), composer_url)
+ return await get_url_by_os(composer_host, port, composer_url)| # Provide direct connection URLs since we're no longer using composer | ||
| streamable_http_url = await get_project_streamable_http_url(project_id) | ||
| legacy_sse_url = await get_project_sse_url(project_id) | ||
| if not streamable_http_url: | ||
| raise HTTPException(status_code=500, detail="Failed to get direct Streamable HTTP URL") | ||
|
|
||
| response["result"] = { | ||
| "project_id": str(project_id), | ||
| "sse_url": sse_url, | ||
| "streamable_http_url": streamable_http_url, | ||
| "legacy_sse_url": legacy_sse_url, | ||
| "sse_url": legacy_sse_url, | ||
| "uses_composer": False, | ||
| } |
There was a problem hiding this comment.
Inconsistent null check for URLs.
streamable_http_url is validated but legacy_sse_url is not. If both URLs are required for the response, validate both consistently.
# Provide direct connection URLs since we're no longer using composer
streamable_http_url = await get_project_streamable_http_url(project_id)
legacy_sse_url = await get_project_sse_url(project_id)
- if not streamable_http_url:
- raise HTTPException(status_code=500, detail="Failed to get direct Streamable HTTP URL")
+ if not streamable_http_url or not legacy_sse_url:
+ raise HTTPException(status_code=500, detail="Failed to get direct connection URLs")🤖 Prompt for AI Agents
In src/backend/base/langflow/api/v1/mcp_projects.py around lines 593 to 605, the
code validates streamable_http_url but not legacy_sse_url leading to
inconsistent null handling; add a check for legacy_sse_url similar to
streamable_http_url (e.g., if not legacy_sse_url: raise
HTTPException(status_code=500, detail="Failed to get legacy SSE URL")), or
adjust logic to allow one missing URL by documenting and setting the response
field to None accordingly, then ensure response["result"] includes the validated
values.
| if current_user: | ||
| user_files_stmt = select(UserFile).where(UserFile.user_id == current_user.id) | ||
| user_files = (await session.exec(user_files_stmt)).all() | ||
| for user_file in user_files: | ||
| stored_path = getattr(user_file, "path", "") or "" | ||
| stored_filename = Path(stored_path).name if stored_path else user_file.name | ||
| safe_filename = quote(stored_filename) | ||
| if stored_filename.startswith(f"{MCP_SERVERS_FILE}_{current_user.id}"): | ||
| # reserved file name for langflow MCP server config file(s) | ||
| continue | ||
| description = getattr(user_file, "provider", None) or "User file uploaded via File Manager" | ||
| resource = types.Resource( | ||
| uri=f"{base_url}/api/v1/files/download/{current_user.id}/{safe_filename}", | ||
| name=stored_filename, | ||
| description=description, | ||
| mimeType=build_content_type_from_extension(stored_filename), | ||
| ) | ||
| resources.append(resource) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find the UserFile model definition
find . -name "*.py" -type f -exec grep -l "class UserFile" {} \;Repository: langflow-ai/langflow
Length of output: 46
🏁 Script executed:
#!/bin/bash
# Search for UserFile class definition
rg "class UserFile" -A 50 --type pyRepository: langflow-ai/langflow
Length of output: 46
🏁 Script executed:
#!/bin/bash
# Search for UserFile in the entire codebase
rg "UserFile" --type py | head -30Repository: langflow-ai/langflow
Length of output: 3036
🏁 Script executed:
#!/bin/bash
# Search for imports of UserFile
rg "from.*import.*UserFile|import.*UserFile" --type pyRepository: langflow-ai/langflow
Length of output: 1314
🏁 Script executed:
#!/bin/bash
# Find and read the File model
find . -path "*/langflow/services/database/models/file/model.py" -type fRepository: langflow-ai/langflow
Length of output: 130
🏁 Script executed:
#!/bin/bash
# Read the File model
cat src/backend/base/langflow/services/database/models/file/model.pyRepository: langflow-ai/langflow
Length of output: 803
Remove unnecessary getattr() for path—it's a required field in the File model.
The path field is defined as path: str = Field(nullable=False) (required), so the getattr(user_file, "path", "") pattern is unnecessary and suggests false uncertainty about the model schema. Access it directly as user_file.path. The getattr(user_file, "provider", None) is appropriate since provider is optional (str | None), and user_file.name is correctly accessed directly since name is also required.
🤖 Prompt for AI Agents
In src/backend/base/langflow/api/v1/mcp_utils.py around lines 135 to 152, remove
the unnecessary use of getattr(user_file, "path", "") since path is a required
non-nullable field on the File model; access user_file.path directly and compute
stored_filename from Path(user_file.path).name (falling back to user_file.name
only if needed), keep getattr(user_file, "provider", None) for the optional
provider field, and ensure safe_filename, URI construction, and mimeType logic
remain unchanged.
|
|
||
|
|
||
| @router.get("/builds") | ||
| @router.get("/builds", dependencies=[Depends(get_current_active_user)]) |
There was a problem hiding this comment.
Good security improvement: Authentication added to /builds endpoints.
These endpoints were previously unprotected and now require an authenticated user. However, the authentication dependency only verifies the user is logged in but doesn't filter the results by user ownership. The flow_id parameter comes from the client, so a user could potentially access or delete vertex builds for flows they don't own.
Consider adding user-scoped filtering similar to get_messages and get_message_sessions:
@router.get("/builds", dependencies=[Depends(get_current_active_user)])
-async def get_vertex_builds(flow_id: Annotated[UUID, Query()], session: DbSession) -> VertexBuildMapModel:
+async def get_vertex_builds(
+ flow_id: Annotated[UUID, Query()],
+ session: DbSession,
+ current_user: Annotated[User, Depends(get_current_active_user)],
+) -> VertexBuildMapModel:
try:
+ # Verify flow belongs to current user
+ flow = await session.get(Flow, flow_id)
+ if not flow or flow.user_id != current_user.id:
+ raise HTTPException(status_code=404, detail="Flow not found")
vertex_builds = await get_vertex_builds_by_flow_id(session, flow_id)Also applies to: 36-36
🤖 Prompt for AI Agents
In src/backend/base/langflow/api/v1/monitor.py around lines 27 and 36, the
endpoints were changed to require authentication but still accept a
client-provided flow_id without verifying ownership; update both endpoints to
take the current user (via Depends(get_current_active_user)), check that the
provided flow_id belongs to that user (e.g., query the Flow/Project by id and
compare owner_id/user_id to current_user.id), restrict the builds query to that
owner's flows (or filter by owner_id) and return a 403/raise HTTPException if
the flow is not found or not owned by the user before proceeding with get/delete
logic.
|
|
||
|
|
||
| @router.get("/") | ||
| @router.get("/", dependencies=[Depends(get_current_active_user)]) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n src/backend/base/langflow/api/v2/registration.pyRepository: langflow-ai/langflow
Length of output: 5758
🏁 Script executed:
rg -i "desktop" src/backend/base/langflow/ -A 2 -B 2 --max-count 20Repository: langflow-ai/langflow
Length of output: 9134
🏁 Script executed:
rg "get_current_active_user" src/backend/base/langflow/services/auth/ -A 10Repository: langflow-ai/langflow
Length of output: 2025
🏁 Script executed:
rg "def get_current_user" src/backend/base/langflow/services/auth/ -A 15 -B 2Repository: langflow-ai/langflow
Length of output: 6186
🏁 Script executed:
rg "skip_auth" src/backend/base/langflow/services/auth/ -A 5 -B 2Repository: langflow-ai/langflow
Length of output: 3179
🏁 Script executed:
rg "skip_auth_auto_login|AUTO_LOGIN" src/backend/base/langflow/ -B 2 -A 2 --max-count 15Repository: langflow-ai/langflow
Length of output: 23975
🏁 Script executed:
rg "registration" src/backend/base/langflow/api/v2/ -B 3 -A 3Repository: langflow-ai/langflow
Length of output: 9132
Confirm Desktop application compatibility with authenticated GET endpoint.
Adding authentication to the GET endpoint creates an asymmetry: POST (register) remains unauthenticated while GET (retrieve registration) now requires authentication. This conflicts with the original design where both endpoints were intentionally unauthenticated for Desktop application initialization.
Before this change, Desktop apps could register without credentials (POST) and check registration status (GET). Now they cannot check status without JWT or API key. Verify this doesn't break Desktop initialization flows or ensure Desktop apps have a documented way to obtain credentials during setup.
🤖 Prompt for AI Agents
In src/backend/base/langflow/api/v2/registration.py around line 139, the GET
endpoint was changed to require authentication which breaks the Desktop app flow
because POST remains unauthenticated; to fix, revert the change so the GET route
is unauthenticated (remove the dependencies=[Depends(get_current_active_user)]
from the @router.get decorator) so GET and POST remain symmetric for Desktop
initialization, add a short code comment noting the Desktop initialization
requirement, and update any docs/tests that assumed the GET endpoint requires
auth.
| "lf_version": "1.5.0.post1", | ||
| "metadata": { | ||
| "code_hash": "f2867efda61f", | ||
| "code_hash": "b9d63ae59e8a", |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Is https://docs.langflow.org/split-text a valid accessible documentation URL?
💡 Result:
No. The URL https://docs.langflow.org/split-text returns a 404 (not found) and is not accessible. [1] The Split Text documentation exists on the Langflow docs site under a different path (see "Split Text" on the components/processing page). [2]
Sources:
- Failed fetch / 404 for https://docs.langflow.org/split-text. [1]
- "Split Text" documentation on Langflow docs (Processing components / Split Text). [2]
🌐 Web query:
Is langchain_cohere version 0.3.5 available and what are its changes from 0.3.3?
💡 Result:
Yes — langchain_cohere version 0.3.5 is available. Source: PyPI listing and the repo releases. [2][1]
Main changes in 0.3.5 vs 0.3.3 (from the GitHub release notes):
- Deprecate create_csv_agent. [1]
- Add JSON mode with_structured_output (new json mode). [1]
Sources:
[1] langchain-ai/langchain-cohere — Releases (0.3.5).
[2] langchain-cohere on PyPI.
Fix broken documentation URL for SplitTextComponent.
The documentation URL https://docs.langflow.org/split-text returns a 404 error and is inaccessible. Update it to point to the correct documentation path on the Langflow docs site (components/processing page). The langchain_cohere version bump to 0.3.5 is valid.
🤖 Prompt for AI Agents
In src/backend/base/langflow/initial_setup/starter_projects/Knowledge
Ingestion.json around line 92, the documentation URL for SplitTextComponent is
incorrect (https://docs.langflow.org/split-text returns 404); update that value
to the correct docs path under the components processing section (e.g.,
https://docs.langflow.org/components/processing or the specific anchor for
SplitText on that page) so the link resolves, and leave the langchain_cohere
version bump to 0.3.5 as-is.
c10d986 to
909bdb1
Compare
Description
This PR addresses an issue where users in high-latency environments could unintentionally create duplicate flows.
Problem:
Previously, when a user clicked on a template card, the request to create the flow was initiated, but the UI remained interactive. If the internet connection was slow, the user could click the card multiple times while the first request was still pending, resulting in multiple identical flows being created.
Solution:
I updated the
TemplateGetStartedCardComponentto include a localloadingstate.loadingistrue.wait, and the arrow icon is replaced by a spinner to indicate activity..finally()to ensure the loading state is reset properly even if the request fails.Type of Change
How Has This Been Tested?
Summary by CodeRabbit
New Features
Bug Fixes
Security
Chores
✏️ Tip: You can customize this high-level summary in your review settings.