Commit Graph

18137 Commits

Author SHA1 Message Date
a0a08cc398 fix(api): resolve global-variable default_fields on API runs (#11781) (#13129)
When a flow is uploaded via API and run via API, global variables with
"Apply to Fields" (default_fields) were silently ignored. The component
received an empty value and failed with errors like
"OpenAI API key is required". Opening the flow once in the Playground
worked around it because the frontend writes load_from_db: true back to
the stored template.

Root cause: variable resolution at vertex build time
(update_params_with_load_from_db_fields) only fires for fields whose
stored template already has load_from_db: true. That flag is set
exclusively by the frontend's inputGlobalComponent hook, which
API-only workflows never trigger.

Fix: mirror the frontend's behaviour in-memory inside simple_run_flow,
just before Graph.from_payload. A new helper module
langflow.api.v1.global_variable_defaults builds the same
{display_name: variable_name} map as getUnavailableFields and applies
it to empty, eligible (str-type, visible, not already load_from_db)
template fields. The mutation is local to the request; the stored
flow is unchanged. Variable-service errors are logged and swallowed so
a lookup failure cannot block flow execution.

Tests: 27 unit tests cover map construction, the pure graph
transformer (matching rules, skip rules, immutability, malformed
input tolerance), and the async wrapper (success and failure paths).

Fixes #11781
2026-05-15 21:17:08 +00:00
f1e9181887 fix: reuse single Langfuse client across flow runs to stop thread leak (#13107)
* fix: reuse single Langfuse client across flow runs to stop thread leak

The Langfuse v3 SDK spawns background threads per client instantiation
(task_manager, prompt_cache, OTel exporters) and never joins them.
LangFuseTracer was constructing a new Langfuse() per flow run, so under
load the process accumulated threads indefinitely.

Cache the client at module level keyed by (secret_key, public_key, host),
route both LangFuseTracer._setup_langfuse and the feedback-helper
_get_langfuse_client through it, and call client.flush() in end() so
buffered events are delivered before the trace completes.

Fixes #9066

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-05-15 20:38:07 +00:00
545d8598b7 fix: added per-user endpoint for flows (#13072)
* added per-user endpoint

* fixed webhook test

* added test

* added cross user security

* fixed nit

* added depends wrapper

* fix: update webhook_run_flow docstring to match new auth dependency signature

* [autofix.ci] apply automated fixes

* fixed flow 404 when running from second user

* regenerated component index

---------

Co-authored-by: ogabrielluiz <gabriel@langflow.org>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-05-15 19:01:03 +00:00
ea559d7971 fix: validate review tool names inline (#13040) 2026-05-15 18:29:41 +00:00
bd35587957 chore: Add non-blocking test coverage advisor for PRs (#13148)
add checker to verify tests non blocker
2026-05-15 17:36:17 +00:00
a003bd6ca6 fix: Memory Base Table output causes JSON serialization error when saving Agent message (#13136)
* test

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* fix: Coercion of Numpy scalar values

* Update src/backend/tests/unit/test_messages.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-05-15 17:33:04 +00:00
66912d4a53 Merge main source updates into release-1.10.0
# Conflicts:
#	docker/build_and_push.Dockerfile
#	docker/build_and_push_backend.Dockerfile
#	docker/build_and_push_base.Dockerfile
#	docker/build_and_push_ep.Dockerfile
#	docker/build_and_push_with_extras.Dockerfile
2026-05-15 09:47:56 -07:00
c556b7ea97 Merge release-1.9.3 into main 1.9.3 2026-05-15 09:41:17 -07:00
322e4908b9 fix: backport policies ToolGuard lazy imports (#13144)
fix: backport policies toolguard lazy imports
2026-05-15 09:24:55 -07:00
1e6f0f95aa fix: Remove redundant Components entry from the left sidebar (#13090)
remove search Icon

Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>
2026-05-15 13:53:43 +00:00
53c62bceb0 chore: Block hardcoded Tailwind palette via Biome lint (#13125)
* add biome checker for hardcoded pallete

* add biome checker on ci

* [autofix.ci] apply automated fixes

* lint-js fix

* improve CI job

* biome fixes

* unblock CI on biome job

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-05-15 12:08:51 +00:00
ac308a09f6 fix(frontend): stop empty-state splash from flashing after login (#12966)
* fix(frontend): stop empty-state splash from flashing after login

Two bugs caused EmptyPageCommunity and EmptyFolder to render for one
frame between login success and the flows query resolving.

1. flowsManagerStore.resetStore() set flows: [] on logout. After
   logout/login the truthy gate in main-page.tsx (flows && examples &&
   folders) passed immediately with stale empty values, and
   shouldShowMainContent returned false, so EmptyPageCommunity rendered
   until the new flows query resolved. Reset to undefined instead so the
   gate correctly waits for the next fetch.

2. homePage initialized isEmptyFolder = true and only flipped it inside
   a useEffect, so the first render of HomePage always rendered
   EmptyFolder regardless of state. Use null as the resolving sentinel,
   skip the effect until both the global flows store and the folder
   query are populated, and render the existing list skeleton while
   resolving.

Verified with a MutationObserver in the post-login transition: prior to
this change three empty-state components were inserted into the DOM in
the same paint window; after the change none are.

* fix(frontend): resolve isEmptyFolder when folder query errors

The post-login flash guard waited for folderData to be defined, but
folderData stays undefined when the folder query errors out (e.g. when
myCollectionId is undefined after the user deletes all folders).
isEmptyFolder then stuck at null and the page rendered ListSkeleton
forever instead of EmptyFolder.

Gate on isLoading from useGetFolderQuery instead. isLoading is true
only on the first fetch with no data and flips to false on success
or error, so the effect still waits past the post-login stale-store
window but resolves correctly when the query settles either way.
2026-05-15 10:55:45 +00:00
5e9f0c37bc Merge branch 'release-1.9.3' into release-1.10.0
# Conflicts:
#	.secrets.baseline
#	docs/package.json
#	pyproject.toml
#	src/backend/base/langflow/initial_setup/starter_projects/Vector Store RAG.json
#	src/backend/base/pyproject.toml
#	src/backend/tests/unit/components/files_and_knowledge/test_retrieval.py
#	src/frontend/package-lock.json
#	src/frontend/package.json
#	src/frontend/src/components/core/parameterRenderComponent/components/modelInputComponent/__tests__/ModelInputComponent.test.tsx
#	src/frontend/src/components/core/parameterRenderComponent/components/modelInputComponent/index.tsx
#	src/frontend/src/modals/modelProviderModal/hooks/useProviderConfiguration.ts
#	src/lfx/pyproject.toml
#	src/lfx/src/lfx/_assets/component_index.json
#	src/sdk/pyproject.toml
#	uv.lock
2026-05-14 21:20:42 -07:00
3e99bbcee8 Merge branch 'release-1.9.3'
# Conflicts:
#	docker/build_and_push.Dockerfile
#	docker/build_and_push_backend.Dockerfile
#	docker/build_and_push_base.Dockerfile
#	docker/build_and_push_ep.Dockerfile
#	docker/build_and_push_with_extras.Dockerfile
2026-05-14 21:01:03 -07:00
b695f97cd3 fix: More python 3.14 compatibility cleanup 2026-05-14 17:49:56 -07:00
cf488e545c fix: Gate more tests on package presence 2026-05-14 17:15:37 -07:00
5fec0a1a42 fix: Skip Python 3.14 incompatible watsonX imports 2026-05-14 16:50:30 -07:00
ecadc106d0 fix: Python 3.14 fallback for baidu 2026-05-14 16:19:03 -07:00
f2b028f28b fix: update gunicorn constraint to allow version 26.x
- Update gunicorn constraint from <26.0.0 to <27.0.0
- Resolves dependency check failure with gunicorn 26.0.0
- Regenerate uv.lock with updated constraint
2026-05-14 18:01:34 -04:00
883872f95f Update release.yml 2026-05-14 14:39:20 -07:00
22e9003bec fix: correct version numbers for 1.9.3 patch release
- langflow-base: 0.10.0 -> 0.9.3
- lfx: 0.5.0 -> 0.4.3 (and dependency reference)
- sdk: 0.2.0 -> 0.1.3
2026-05-14 16:56:00 -04:00
e16c99d031 fix: upgrade langchain-classic to 1.0.7 (#13130)
chore: upgrade langchain-classic to 1.0.7

- Update version constraint from ~=1.0.0 to ~=1.0.7
- Fixes issues present in version 1.0.4
- Update uv.lock with new dependency resolution

Co-authored-by: Janardan S Kavia <janardanskavia@Janardans-MacBook-Pro.local>
2026-05-14 16:51:35 -04:00
d5ef588e42 chore: bump versions to 1.9.3 2026-05-14 15:41:43 -04:00
e067f18720 feat: add UTM tracking to outbound watsonx Orchestrate links (#12888)
* Add UTM tracking to outbound watsonx Orchestrate links

Introduces a decorateWxoUrl utility that appends utm_source, utm_medium,
utm_campaign, and a per-link utm_content to IBM-hosted URLs using the URL
API. The utm_source is configurable via LANGFLOW_WXO_UTM_SOURCE with a
"langflow" default. Applied to the Sign-up and Find-your-credentials links
in step-provider and add-provider-modal.

* update tsts

* update tsts
2026-05-14 19:31:54 +00:00
3da78df85c feat(mcp): pass session_id through MCP tool calls (#13124)
Adds optional session_id support to flows exposed via the MCP
interface so MCP clients (Claude Desktop, Cursor, etc.) can persist
conversation history across tool calls.

- json_schema_from_flow now advertises session_id as an optional
  string property on every generated tool schema, unless the flow
  already defines its own session_id input.
- handle_call_tool reads session_id from the incoming arguments and
  forwards it to simple_run_flow. When absent or blank, it falls
  back to a generated UUID, preserving the prior per-call behavior.

Reported by Alejandro: MCP clients had no way to maintain chat
history because the server unconditionally generated a fresh
conversation id per call.
2026-05-14 11:34:36 -07:00
e21f5882a9 Fix: preprocessing related fields removed from PATCH endpoint (#13112)
Fix: preprocessing related fields removed form PATCH endpoint as they are immutable.
2026-05-14 16:48:52 +00:00
5f1463fb12 docs: mcp tool call configurable timeouts (#13051)
* docs-configure-mcp-tool-timeouts

* Apply suggestions from code review

Co-authored-by: April I. Murphy <36110273+aimurphy@users.noreply.github.com>

* docs-peer-review

---------

Co-authored-by: April I. Murphy <36110273+aimurphy@users.noreply.github.com>
2026-05-14 15:21:31 +00:00
a80cf1c649 chore: support Python 3.14 (#13085)
* feat: upgrade Docker images to Python 3.14 (experimental)

- Update pyproject.toml: requires-python from <3.14 to <3.15
- Update all 5 Dockerfiles to use Python 3.14:
  - Builder stage: python3.12-trixie-slim → python3.14-trixie-slim
  - Runtime stage: python:3.12-slim-trixie → python:3.14-slim-trixie

- src/backend/base/pyproject.toml
- docker/build_and_push_base.Dockerfile
- docker/build_and_push.Dockerfile
- docker/build_and_push_backend.Dockerfile
- docker/build_and_push_with_extras.Dockerfile
- docker/build_and_push_ep.Dockerfile

Python 3.14.5 was released on May 10, 2026. Upgrading to the latest
Python version should help reduce CVE vulnerabilities in Docker images.

This is an experimental change to test Python 3.14 compatibility:
- Docker images will use Python 3.14
- CI/CD workflows still test on Python 3.10-3.13
- Nightly build will validate if dependencies work with 3.14
- Can be reverted quickly if issues are found

- Monitor nightly build for failures
- If successful, update CI/CD workflows to add Python 3.14 to test matrix
- If failures occur, revert and investigate compatibility issues

* chore: support Python 3.14

Bump requires-python upper bound to <3.15 across langflow, langflow-base,
lfx, and langflow-sdk, and add 3.14 to CI test matrices so PRs are gated
on 3.14 compatibility.

Conditional pins for transitive deps without 3.14 wheels at the existing
caps:
- onnxruntime: >=1.26 on 3.14 (existing <1.24 cap retained for 3.10)
- faiss-cpu: >=1.13.2 on 3.14 (existing ==1.9.0.post1 retained for <3.14)

* chore: marker-gate IBM watsonx packages for Python 3.14

ibm-watsonx-ai 1.3.x cannot import on Python 3.14: its StrEnum subclasses
override __init__ in a way that conflicts with 3.14's reworked enum
__set_name__ path (TypeError on KnowledgeBaseFieldRole class creation).

Cap ibm-watsonx-ai, langchain-ibm, and the ibm-watsonx-orchestrate-*
extras at python_version<'3.14' until upstream adapts. Watsonx component
imports are already lazy, so this surfaces only at component-access time
on 3.14, where the existing ImportError handler in
lfx.components.ibm.__init__ degrades it gracefully.

test_model_utils.py imports ChatWatsonx at module top to verify
get_model_name resolves model_id; guard that import so the test
module skips on 3.14 instead of breaking collection.

* [autofix.ci] apply automated fixes

* chore: upgrade remaining Docker images to Python 3.14

build_and_push*.Dockerfile already moved to 3.14 in the merge from
feat/upgrade-python-3.14-docker-images. Apply the same bump to the
dev, devcontainer, and lfx Docker images so all in-repo Dockerfiles
share one Python version.

* [autofix.ci] apply automated fixes

* chore: gate 3.14-broken extras to python_version<'3.14'

cuga (and its transitive fastembed -> py-rust-stemmers source build),
altk/agent-lifecycle-toolkit (re-pulls ibm-watsonx-ai which was already
gated), langchain-pinecone, langwatch, ragstack-ai-knowledge-store, and
OpenDsStar all pin themselves below 3.14 upstream. Without a marker
guard, the workspace lock still tries to install them and a Docker
`uv sync` then attempts source builds that require Rust (CI Docker
test failure with py-rust-stemmers 0.1.5).

Add python_version<'3.14' (or <'3.13' for ragstack) to each pin so
those packages are simply omitted from the 3.14 install set until
upstream catches up. uv pip check is now clean on 3.14.2.

* test: skip test_altk_agent on Python 3.14

altk (agent-lifecycle-toolkit) is gated to python_version<'3.14'
upstream and now via the langflow-base [altk] extra marker. The test
imports altk at module top to exercise ALTKAgentComponent; guard the
import so collection skips on 3.14 instead of failing.

* test: skip remaining altk tests on Python 3.14

Three more test modules import lfx.base.agents.altk_* at module top,
which transitively imports altk. Add the same module-level skip guard
as test_altk_agent.py:
- test_altk_agent_logic.py
- test_altk_agent_tool_conversion.py
- test_conversation_context_ordering.py

* fix(calculator): replace removed ast.Num with ast.Constant for Python 3.14

ast.Num was deprecated in Python 3.8 in favor of ast.Constant and
removed entirely in 3.14. The calculator tool and its core walker
crashed on 3.14 with 'module ast has no attribute Num'.

Switch the isinstance checks to ast.Constant + isinstance(node.value,
(int, float)), and drop the now-dead ast.Num backwards-compat branch
in calculator_core.py (the ast.Constant branch already handles every
input it would have matched). Update the parser unit-test fixtures
to construct ast.Constant nodes.

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* test: skip LangWatch HTTP instrumentation tests on Python 3.14

langwatch is gated to python_version<'3.14' upstream. The
TestLangWatchHttpInstrumentation class patches langwatch.setup and
langwatch.trace inside a fixture, which requires langwatch to be
importable; on 3.14 the test errors with ModuleNotFoundError.

Guard the class with a skipif on langwatch availability.

* test: allow IBM and altk components to be missing on Python 3.14

test_all_modules_importable enforces that every component in __all__
imports cleanly. On 3.14 the ibm-watsonx-ai, langchain-ibm, and altk
packages are gated upstream and intentionally not installed, so the
WatsonxAI, WatsonxEmbeddings, and ALTKAgent components fail to import
as designed.

- test_all_components_in_categories_importable: accept a known-gated
  deny-list on 3.14 instead of failing.
- test_all_lfx_component_modules_directly_importable: extend the
  existing 'missing optional dependency' allowlist with altk,
  langchain_ibm, and ibm_watsonx_ai.

* fix(lfx): pass ensure_exists to user_cache_dir for Python 3.14

Python 3.14 tightened PurePath.__init__ to reject unknown keyword
arguments. The KeyedWorkerLockManager constructor was passing
ensure_exists=True to Path() instead of user_cache_dir(), which
silently worked on 3.10-3.13 but raises TypeError on 3.14 and also
meant the cache directory was never actually being created.

Move the kwarg to user_cache_dir() where it belongs and update the
two unit tests that asserted the buggy call shape.

* [autofix.ci] apply automated fixes

* test: accept either ZIP or JSON error path on Python 3.14

Python 3.14's zipfile.is_zipfile() now validates the central-directory
signature in addition to EOCD, so the garbage+EOCD payload no longer
passes the is_zipfile() dispatch in the /flows/upload/ route. The
endpoint still returns 400 with a descriptive detail (now from the JSON
branch); only the message wording differs, which the test was asserting
verbatim.

* fix(lfx): normalize cors_origins ['*'] back to '*' on Python 3.14

Pydantic-settings on Python 3.14 parses the env var '*' into ['*']
before the cors_origins field validator runs (the list[str] | str union
resolves differently than on 3.10-3.13). Collapse that back to the
bare-string wildcard so downstream consumers — including
warn_about_future_cors_changes and the test suite — see the same shape
on every supported Python version.

---------

Co-authored-by: vijay kumar katuri <vijay.katuri@ibm.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
(cherry picked from commit 1955f8fae5)
2026-05-13 22:23:39 +00:00
1955f8fae5 chore: support Python 3.14 (#13085)
* feat: upgrade Docker images to Python 3.14 (experimental)

## Changes
- Update pyproject.toml: requires-python from <3.14 to <3.15
- Update all 5 Dockerfiles to use Python 3.14:
  - Builder stage: python3.12-trixie-slim → python3.14-trixie-slim
  - Runtime stage: python:3.12-slim-trixie → python:3.14-slim-trixie

## Files Updated
- src/backend/base/pyproject.toml
- docker/build_and_push_base.Dockerfile
- docker/build_and_push.Dockerfile
- docker/build_and_push_backend.Dockerfile
- docker/build_and_push_with_extras.Dockerfile
- docker/build_and_push_ep.Dockerfile

## Rationale
Python 3.14.5 was released on May 10, 2026. Upgrading to the latest
Python version should help reduce CVE vulnerabilities in Docker images.

## Testing Strategy
This is an experimental change to test Python 3.14 compatibility:
- Docker images will use Python 3.14
- CI/CD workflows still test on Python 3.10-3.13
- Nightly build will validate if dependencies work with 3.14
- Can be reverted quickly if issues are found

## Next Steps
- Monitor nightly build for failures
- If successful, update CI/CD workflows to add Python 3.14 to test matrix
- If failures occur, revert and investigate compatibility issues

* chore: support Python 3.14

Bump requires-python upper bound to <3.15 across langflow, langflow-base,
lfx, and langflow-sdk, and add 3.14 to CI test matrices so PRs are gated
on 3.14 compatibility.

Conditional pins for transitive deps without 3.14 wheels at the existing
caps:
- onnxruntime: >=1.26 on 3.14 (existing <1.24 cap retained for 3.10)
- faiss-cpu: >=1.13.2 on 3.14 (existing ==1.9.0.post1 retained for <3.14)

* chore: marker-gate IBM watsonx packages for Python 3.14

ibm-watsonx-ai 1.3.x cannot import on Python 3.14: its StrEnum subclasses
override __init__ in a way that conflicts with 3.14's reworked enum
__set_name__ path (TypeError on KnowledgeBaseFieldRole class creation).

Cap ibm-watsonx-ai, langchain-ibm, and the ibm-watsonx-orchestrate-*
extras at python_version<'3.14' until upstream adapts. Watsonx component
imports are already lazy, so this surfaces only at component-access time
on 3.14, where the existing ImportError handler in
lfx.components.ibm.__init__ degrades it gracefully.

test_model_utils.py imports ChatWatsonx at module top to verify
get_model_name resolves model_id; guard that import so the test
module skips on 3.14 instead of breaking collection.

* [autofix.ci] apply automated fixes

* chore: upgrade remaining Docker images to Python 3.14

build_and_push*.Dockerfile already moved to 3.14 in the merge from
feat/upgrade-python-3.14-docker-images. Apply the same bump to the
dev, devcontainer, and lfx Docker images so all in-repo Dockerfiles
share one Python version.

* [autofix.ci] apply automated fixes

* chore: gate 3.14-broken extras to python_version<'3.14'

cuga (and its transitive fastembed -> py-rust-stemmers source build),
altk/agent-lifecycle-toolkit (re-pulls ibm-watsonx-ai which was already
gated), langchain-pinecone, langwatch, ragstack-ai-knowledge-store, and
OpenDsStar all pin themselves below 3.14 upstream. Without a marker
guard, the workspace lock still tries to install them and a Docker
`uv sync` then attempts source builds that require Rust (CI Docker
test failure with py-rust-stemmers 0.1.5).

Add python_version<'3.14' (or <'3.13' for ragstack) to each pin so
those packages are simply omitted from the 3.14 install set until
upstream catches up. uv pip check is now clean on 3.14.2.

* test: skip test_altk_agent on Python 3.14

altk (agent-lifecycle-toolkit) is gated to python_version<'3.14'
upstream and now via the langflow-base [altk] extra marker. The test
imports altk at module top to exercise ALTKAgentComponent; guard the
import so collection skips on 3.14 instead of failing.

* test: skip remaining altk tests on Python 3.14

Three more test modules import lfx.base.agents.altk_* at module top,
which transitively imports altk. Add the same module-level skip guard
as test_altk_agent.py:
- test_altk_agent_logic.py
- test_altk_agent_tool_conversion.py
- test_conversation_context_ordering.py

* fix(calculator): replace removed ast.Num with ast.Constant for Python 3.14

ast.Num was deprecated in Python 3.8 in favor of ast.Constant and
removed entirely in 3.14. The calculator tool and its core walker
crashed on 3.14 with 'module ast has no attribute Num'.

Switch the isinstance checks to ast.Constant + isinstance(node.value,
(int, float)), and drop the now-dead ast.Num backwards-compat branch
in calculator_core.py (the ast.Constant branch already handles every
input it would have matched). Update the parser unit-test fixtures
to construct ast.Constant nodes.

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* test: skip LangWatch HTTP instrumentation tests on Python 3.14

langwatch is gated to python_version<'3.14' upstream. The
TestLangWatchHttpInstrumentation class patches langwatch.setup and
langwatch.trace inside a fixture, which requires langwatch to be
importable; on 3.14 the test errors with ModuleNotFoundError.

Guard the class with a skipif on langwatch availability.

* test: allow IBM and altk components to be missing on Python 3.14

test_all_modules_importable enforces that every component in __all__
imports cleanly. On 3.14 the ibm-watsonx-ai, langchain-ibm, and altk
packages are gated upstream and intentionally not installed, so the
WatsonxAI, WatsonxEmbeddings, and ALTKAgent components fail to import
as designed.

- test_all_components_in_categories_importable: accept a known-gated
  deny-list on 3.14 instead of failing.
- test_all_lfx_component_modules_directly_importable: extend the
  existing 'missing optional dependency' allowlist with altk,
  langchain_ibm, and ibm_watsonx_ai.

* fix(lfx): pass ensure_exists to user_cache_dir for Python 3.14

Python 3.14 tightened PurePath.__init__ to reject unknown keyword
arguments. The KeyedWorkerLockManager constructor was passing
ensure_exists=True to Path() instead of user_cache_dir(), which
silently worked on 3.10-3.13 but raises TypeError on 3.14 and also
meant the cache directory was never actually being created.

Move the kwarg to user_cache_dir() where it belongs and update the
two unit tests that asserted the buggy call shape.

* [autofix.ci] apply automated fixes

* test: accept either ZIP or JSON error path on Python 3.14

Python 3.14's zipfile.is_zipfile() now validates the central-directory
signature in addition to EOCD, so the garbage+EOCD payload no longer
passes the is_zipfile() dispatch in the /flows/upload/ route. The
endpoint still returns 400 with a descriptive detail (now from the JSON
branch); only the message wording differs, which the test was asserting
verbatim.

* fix(lfx): normalize cors_origins ['*'] back to '*' on Python 3.14

Pydantic-settings on Python 3.14 parses the env var '*' into ['*']
before the cors_origins field validator runs (the list[str] | str union
resolves differently than on 3.10-3.13). Collapse that back to the
bare-string wildcard so downstream consumers — including
warn_about_future_cors_changes and the test suite — see the same shape
on every supported Python version.

---------

Co-authored-by: vijay kumar katuri <vijay.katuri@ibm.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-05-13 22:23:39 +00:00
0d80a36008 fix(knowledge-base): align Filter by metadata pickers with app dropdowns (#13117)
* fix(knowledge-base): align Filter by metadata pickers with app dropdowns

The "+ Filter by metadata" popover used plain <Input> fields backed by a
native HTML <datalist> for key/value suggestions. The browser-native
dropdown looked nothing like the shadcn `Select` used right next to it
(e.g. "All sources") — QA flagged the inconsistency.

Replace each free-text input with a shadcn-style combobox built on
Popover + Command (cmdk):
  - Outline button trigger with chevron, matching SelectTrigger.
  - Suggestion list rendered as CommandItem rows with a check on the
    current selection.
  - When the typed query is not in the suggestions, a "Use \"foo\"" item
    appears so users can still commit a custom key/value.
  - Closing the picker clears the search query; selecting an item
    commits and closes.

Validation, refetch-on-open, error messaging, and submit flow are
unchanged. Tests rewritten against the new combobox testids and a
jsdom shim for Element.prototype.scrollIntoView (cmdk calls it).

* refactor(knowledge-base): split ChunksMetadataFilter into focused modules

ChunksMetadataFilter was holding data fetching, derived option lists,
validation rules, popover orchestration, and the combobox UI all in one
file. Split along single-responsibility lines so each piece changes for
its own reason:

  - MetadataCombobox.tsx — presentational Popover+Command combobox with
    custom-entry fallback. Generic over options/testId; reusable.
  - hooks/useChunksMetadataFilter.ts — wraps useGetKbMetadataKeys and
    derives availableKeys / valueSuggestions / flags / refetch.
  - metadataFilterValidation.ts — pure KEY_PATTERN + validateMetadataFilter
    returning { ok, key, value } | { ok: false, error }. Testable in
    isolation; no DOM.
  - ChunksMetadataFilter.tsx — orchestration only: outer popover, form
    state, submit. Composes the three above.

Adds focused unit tests for the validator (regex + happy path + empty
+ uppercase). Existing integration test for the filter itself is left
untouched.

* fix(knowledge-base): gate Next Step on metadata-pair validity

Custom Fields validation only fired on blur and lived in MetadataEditor's
local state, so an invalid key like "Year" still let the user advance to
Review & Build. StepReview rendered the raw pairs (showing "Year: 2020"
in the summary) but ``metadataPairsToFormValue`` silently filtered the
invalid row out at submit — the backend never received that metadata.
The UI was effectively lying.

Single source of truth in metadataValidation.ts:

  - validateMetadataPair (per-row: empty, regex, value length)
  - validateMetadataPairs (cross-row: duplicates, max count)
  - filterValidMetadataPairs (clean trimmed set for display/submit)

Wired through:

  - MetadataEditor derives errors from the prop list via the shared
    validator, dropping the blur-only local state. Errors always
    reflect the current input.
  - useKnowledgeBaseForm.getValidationErrors now checks run-level and
    per-file metadata. handleNext blocks while any row is invalid and
    surfaces a single error key under validationErrors.metadata.
  - StepConfiguration renders that error next to the Custom Fields
    block.
  - StepReview filters the summary through filterValidMetadataPairs so
    it only shows pairs the backend will actually persist.

Adds focused unit tests for the new validator (per-row rules, dupes,
max-count, filter behavior).
2026-05-13 22:08:30 +00:00
5d3e0f18f1 fix: normalise legacy uppercase SpanStatus/SpanType values on DB read (#13000)
* fix: normalise legacy uppercase SpanStatus/SpanType values on DB read

* [autofix.ci] apply automated fixes

* Update model.py

* [autofix.ci] apply automated fixes

* fix ruff testcases

---------

Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Eric Hare <ericrhare@gmail.com>
2026-05-13 21:57:02 +00:00
191aaba05d fix: prevent canvas text-selection highlight on shift+drag in Tauri (#12995)
* fix: prevent canvas text-selection highlight on shift+drag in Tauri WebView

* ensure macos fuctionality is identical to chromium

* [autofix.ci] apply automated fixes

---------

Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-05-13 21:34:25 +00:00
ea29bcc6b9 feat: Redis-backed job queue for multi-worker deployments (#12588)
* feat: implement Redis job queue and fakeredis support
- Refactored the job queue service to support Redis-backed management for cross-worker scaling.
- Added environment variables for configuration:
    - `LANGFLOW_JOB_QUEUE_TYPE=redis`
    - `LANGFLOW_REDIS_QUEUE_DB=1`
- Updated job ownership methods to be asynchronous for improved concurrency handling.
- Enhanced Redis cache service with namespacing via key prefixes.
- Introduced `fakeredis` for in-memory Redis simulation in testin>
- Added comprehensive unit tests for Redis job queue components.

* fix: run  experimental warning for RedisCache usage only once

- Introduced a mechanism to emit a one-time warning for the RedisCache experimental feature during server runtime.
- The warning is logged only if no other worker has already emitted it, ensuring clarity for users regarding the experimental status of RedisCache.
- The implementation includes a temporary file check to prevent multiple warnings across different processes.

* docs: document environment variables for worker management
- Added documentation for LANGFLOW_GUNICORN_PRELOAD to explain preloading for better performance.
- Detailed the use of LANGFLOW_JOB_QUEUE_TYPE for specifying backends (e.g., Redis).
- Included LANGFLOW_REDIS_QUEUE_DB to define the database index for job queues.
- Updated the "High-Load Environments" guide with these optimal configurations.

* docs: updated 'High-load and multi-worker environments' section

* feat: enhance RedisJobQueueService with consumer wrapper management
- Introduced a caching mechanism for Redis stream consumers to optimize job data retrieval.
- Added methods to manage consumer wrappers, ensuring they are reused across sequential polls.
- Implemented cleanup logic to cancel and clear consumer wrappers during job cleanup and service stop.
- Expanded unit tests to verify consumer wrapper reuse and cleanup behavior.

* fix: ensure Redis keys are deleted during job cleanup even on cancellation

- Updated the cleanup_job method in RedisJobQueueService to guarantee Redis keys are removed even if the job cleanup is interrupted by a CancelledError.
- Added a new unit test to verify that Redis keys are deleted correctly when cleanup is called during task cancellation.

* fix: manage connection check task in RedisJobQueueService

- Added handling for the connection check task in the stop method to ensure it is properly cancelled and awaited if still running.
- This change improves resource management and prevents potential issues during service shutdown.

* fix: handle unpublished sentinel requeue on cancellation in RedisJobQueueService

- Updated the job processing logic to ensure that if a job is cancelled during the xadd operation, the unpublished sentinel is requeued instead of being dropped.
- Introduced a new unit test to verify this behavior, ensuring robustness in job handling during cancellations.

* fix: improve Redis job queue service with enhanced configuration and cleanup

- Added atexit cleanup to remove stale temporary files for RedisCache.
- Refactored Redis job queue service to use shared constants for stream prefixes, improving maintainability.
- Updated type hints for better clarity and consistency in RedisQueueWrapper and RedisJobQueueService.
- Enhanced error handling with configurable backoff for transient read failures.

* fix: enhance Redis job queue service with maxlen configuration for xadd

- Updated the xadd method in RedisJobQueueService to include maxlen and approximate parameters, improving stream management and preventing excessive memory usage.

* fix: enhance job ownership retrieval in RedisJobQueueService

- Updated the get_job_owner method to refresh the Redis key TTL on successful lookups, ensuring long-running jobs maintain their ownership anchor.
- Improved code clarity by extracting the owner key into a variable and adding detailed docstring explanations for better understanding of the TTL management.

* fix: improve job ownership handling in cleanup_job method

- Enhanced the cleanup_job method in RedisJobQueueService to accurately capture job ownership before deleting Redis keys, preventing potential data corruption in multi-worker scenarios.
- Added comments for clarity on ownership logic and its implications during job cleanup.

* fix: optimize TTL management in RedisJobQueueService

- Introduced periodic TTL refresh logic in the _bridge_to_redis method to enhance Redis stream management, reducing round-trips and improving throughput.
- Added constants for TTL refresh events and seconds to maintain clarity and configurability.
- Updated event handling to ensure TTL is refreshed appropriately based on event count and time elapsed.

* fix: improve event handling in flow response management

- Removed unnecessary error handling for missing event tasks in get_flow_events_response, allowing for smoother operation when no task exists.
- Updated create_flow_response to handle optional event_task parameter, ensuring proper cleanup during disconnections.
- Added unit tests to verify behavior when event tasks are missing, enhancing robustness in streaming scenarios.

* fix: enhance RedisQueueWrapper with startup grace period and stream observation

- Added a startup grace period to prevent premature end-of-stream signals when the producer has not yet issued its first XADD.
- Introduced a flag to track whether the stream has been observed, improving the handling of early polling scenarios.
- Updated logic to ensure proper handling of stream existence checks and logging for better debugging during job processing.

* fix: implement cleanup for old cross-worker job queues in RedisJobQueueService

- Added a new method to clean up done cross-worker consumer wrappers that are not owned by the current worker, ensuring proper resource management.
- Enhanced the existing cleanup logic to prevent memory leaks by explicitly pruning stale entries from the consumer wrappers dictionary.
- Improved logging to provide better visibility into the cleanup process for cross-worker jobs.

* fix: enhance job handling in JobQueueService with guarded task execution

- Updated the start_job method to accept a Coroutine type for task_coro, ensuring type safety.
- Introduced a new _guarded_task method to wrap job coroutines, guaranteeing that unhandled exceptions emit an error event and write a sentinel to the Redis Stream, improving reliability in job processing.
- Enhanced documentation to clarify the behavior of the new task handling mechanism and its implications for cross-worker consumers.

* fix: improve client disconnection handling in create_flow_response

- Added logging for scenarios where a client disconnects without an associated event_task, clarifying that the producer will continue running until the build completes.
- Documented the limitation regarding cross-worker passive disconnects and the need for a Redis side-channel for proper cancellation, enhancing observability in the logs.

* fix: enhance RedisQueueWrapper to manage initial read state and buffer behavior

- Introduced a flag to track the completion of the first XREAD call, ensuring proper buffer management during the initial read phase.
- Updated the empty method to reflect the state of the buffer accurately, preventing premature exits from the drain loop until the first read is complete.
- Improved documentation to clarify the behavior of the new flag and its impact on job processing.

* fix: clarify RedisQueueWrapper behavior in tests for buffer state and no-op operations

- Updated test documentation to explain the behavior of the empty() method in relation to the first XREAD completion, ensuring accurate understanding of buffer state during job processing.
- Adjusted assertions in tests to reflect the intended behavior of the RedisQueueWrapper, specifically regarding the no-op nature of put_nowait and its impact on the internal buffer.

* fix: update dependencies in pyproject.toml and uv.lock

- Added fakeredis dependency with a minimum version of 2.0.0 to both pyproject.toml and uv.lock files.
- Ensured proper formatting and comments in pyproject.toml for clarity on onnxruntime version constraints.

* fix: enhance RedisQueueWrapper and job queue handling for improved cancellation and buffer management

- Introduced a structural protocol `_CancellableQueue` to ensure queues can handle cancellation properly during client disconnects.
- Updated `RedisQueueWrapper` to implement this protocol, allowing for graceful cancellation of background tasks.
- Added a maximum size limit to the internal buffer to prevent unbounded memory usage and ensure backpressure on slow consumers.
- Implemented a done callback to handle unexpected fill task crashes, ensuring consumers are not left hanging indefinitely.
- Enhanced unit tests to verify compliance with the new protocol and the behavior of the buffer under various conditions.

* fix: RedisQueueWrapper sentinel delivery, error time-bound, and cancel response

- Deliver end-of-stream sentinel on fill-task cancellation (_on_fill_done now
  handles both cancelled and exception paths so consumers are never left hanging)
- Add _error_start time-bound to xread and exists() error loops: after
  _STARTUP_GRACE_S seconds of continuous Redis errors the sentinel is delivered
  instead of retrying forever
- Advance _last_id cursor only after buffer.put() succeeds so cancellation mid-put
  does not silently skip that message in the Redis cursor
- Return False from cancel_flow_build when event_task is None (cross-worker path)
  so the HTTP response correctly reports success=False instead of false success

* [autofix.ci] apply automated fixes

---------

Co-authored-by: ogabrielluiz <gabriel@langflow.org>
Co-authored-by: Jordan Frazier <jordan.frazier@datastax.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-05-13 21:09:51 +00:00
3cbd07b68d fix(ui): distinguish Memory and Model icons (BrainCog / BrainCircuit) (#13111)
Memory base and Model Providers both rendered the plain "Brain" Lucide
icon, which QA flagged as confusing — the two sections felt
interchangeable at a glance.

Repoint each surface to its own variant per product/manager direction:

  Model Providers / model trigger / settings nav: Brain → BrainCircuit
  Memory base (sidebar nav, modal, details header, empty states):
    Brain → BrainCog

BrainCircuit was already in use for Language Models / LLM Operations in
the component library, so the Model Providers surface now lines up with
that family. Memory keeps its own distinct glyph (cog) to read as
"managed knowledge" rather than "a model".

Test fixture in sidebarSegmentedNav.test.tsx updated. Provider-list
fixtures that happened to default to "Brain" for unrelated test data are
left as-is.
2026-05-13 19:30:07 +00:00
fb0587c23a fix: ValidationError reduction on OSS and Desktop (#12920)
* Unserializable Object string support

* FlowCreate causing unhandled error fix

* [autofix.ci] apply automated fixes

* added typeerror to thecatch and improved testcases

* fix: added testcase

* fix: widen TraceRead I/O types and validate flows list items before import

TraceRead.input/output were typed as dict|None, causing a 500 when a
stored span contained the '[Unserializable Object]' sentinel string.
Widen to dict|str|None to match TraceSummaryRead.

The flows upload endpoint assumed data["flows"] was a list of dicts;
payloads like {"flows": "oops"} or {"flows": [1]} reached
normalize_code_for_import and raised AttributeError before the 422
handler ran. Add explicit isinstance checks for both the list container
and each item, returning 422 with a clear message on failure.

Regression tests added for both fixes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Viktor Avelino <64113566+viktoravelino@users.noreply.github.com>
2026-05-13 17:39:47 +00:00
bbe2ccdc91 docs: fix sidebar and TOC styles for Redocusaurus (#12748)
* docs: improve sidebar and TOC readability + scroll progress

- Fix left nav sidebar hugging the left edge (remove margin-left)
- Increase sidebar font sizes and lift muted colors for legibility
- TOC right-side: white inactive items, pink active, gray for passed sections
- Add clientModule (tocProgress.js) to track scroll progress in TOC
- Add Redocusaurus API page styles to match site theme

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: fix sidebar/TOC height stability and active item reflow

- Force sidebarViewport to 100vh to prevent shrinking during scroll
- Replace font-weight on active TOC item with text-shadow to avoid reflow

* docs: left-anchor sidebar and increase fonts on large screens

* docs: constrain prev/next nav to match content max-width

* docs: fix sidebar jump on scroll by moving padding-top inside menu

* docs: fix sidebar-ad spacing with transparent padding on li

* docs: fix sidebarViewport height and MutationObserver leak

* docs: constrain doc content to 75vw and remove dead CSS comments

- Cap docMainContainer at 75vw
- Set pagination-nav to 100% width to match content column
- Remove commented-out .markdown and .ch-scrollycoding blocks

* docs: set docMainContainer max-width to 75% for better reading width

* docs: center main-wrapper on large screens and center docItemWrapper

* fix: revert lodash override to stable 4.17.21

lodash 4.18.0 is a broken release — template.js uses assignWith and
arrayEach without importing them, crashing npm start. Pin to 4.17.21
across all nested overrides.

* fix: prevent horizontal scroll on mobile docs pages

docsWrapper has flex:1 0 auto (flex-shrink:0), so it never shrinks below
the natural content width (~570px on iPhone). Cap it to 100vw and add
min-width:0 down the flex chain (docRoot, docMainContainer) so the
layout stays within viewport on narrow screens.

Also remove the overflow:visible override from ch-code-wrapper, which
was defeating the code block's own horizontal containment.

* feat: responsive navbar search and hide social icons on mobile

Shrink search bar as viewport narrows (160px at 1100px, 100px at 996px),
collapse to icon-only at 960px. Hide GitHub, X, and Discord icons below
996px where the hamburger menu takes over navigation.

* fix: images always respect container width above 996px

Use min(100%, 600px) so images are capped at 600px but never overflow
their container when the content area is narrower (e.g. sidebar open).

* fix: improve TOC progress scroll tracking and bottom-of-page detection

Adds scroll handler with RAF throttle, pauses/resumes MutationObserver
to avoid loops, and forces last TOC link active when scrolled to page bottom.

* fix: translate Portuguese comments to English in custom.css

* fix: sidebar viewport fills full screen height

* feat: sidebar section icon turns pink with ease transition when active

* fix: reduce TOC font size to 0.8rem

* fix: remove docMainContainer right padding and add 48px gap to content col

* fix: card header responsive alignment and title margin reset

* fix: darken card background and active sidebar item bg on light theme

* fix: revert TOC colors and add inline code border radius tweak

* fix: minimal scrollbar for sidebar and TOC — thumb only on hover

* fix: scrollbar fade-in/out transition at 0.25s ease

* feat: add rehype plugin for table column wrapping and centering

Inserts zero-width space after underscores in inline code cells so long
env-var names wrap at underscore boundaries. Also centers Format/Default
columns via a col-center class applied at build time.

* fix: use --ifm-heading-color for sidebar group labels in both themes

* refactor: split docs custom.css into themed partials

Breaks the 1,658-line monolithic custom.css into 8 focused files
(tokens, layout, navbar, sidebar, typography, components, code,
redocusaurus). custom.css is now a thin entry point with @imports.

* fix: align sidebar and navbar with shared --docs-gutter token

Introduces --docs-gutter: 1rem in tokens.css and applies it to both
navbar__inner horizontal padding and sidebar nav.menu padding-left,
keeping the Langflow logo and sidebar items visually aligned.

* fix: match sidebar ad background to page background color

Dark mode uses #111 (same as sidebar bg); light mode uses --ifm-background-color.

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 22:11:36 +00:00
0b93705a8d fix: restore Langfuse feedback trace linking (#13081)
* fix: restore langfuse feedback trace linking

* [autofix.ci] apply automated fixes

* fix: add run id to placeholder graph

* fix: gate langfuse feedback sync and surface failures

Gate the background task on tracing being enabled and Langfuse being
configured so we don't enqueue work that silently no-ops. Raise instead
of swallowing missing-credentials and import errors so background-task
failures hit logs. Add delete_feedback_score for the clear-feedback
(True/False -> None) transition that previously fell through.

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-05-12 20:52:28 +00:00
4f9e0da208 feat: regression bucket (#12948)
* initial-plan

* create-initial-yaml-files

* add-info-to-bug-report

* add-regression-stub-workflow

* use-create-comment-instead-of-github-script
2026-05-12 14:13:46 +00:00
6691ac7ff3 fix: Skip built-in tool when external tool has same name (#13036)
* fix duplicate tool call

* chore: auto-bake note keys and regenerate backend locales/en.json [skip ci]

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* chore: auto-bake note keys and regenerate backend locales/en.json [skip ci]

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* [autofix.ci] apply automated fixes (attempt 3/3)

* chore: auto-bake note keys and regenerate backend locales/en.json [skip ci]

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-05-12 09:13:17 -03:00
b90433a9ae fix: Lazy loading of policies deps 2026-05-11 18:58:01 -07:00
5c823f69d8 feat: Add agent preprocessing to perform compaction/gating for MemoryBases (#12975)
* MB enhancement: Added agent pre-processing features to ingestion, can act as an LLM judge to gate ingestion based on system prompt.

* Update mb01b2c3d4e5_add_preprocessing_output.py

---------

Co-authored-by: Eric Hare <ericrhare@gmail.com>
2026-05-11 22:52:08 +00:00
7f181e9f16 feat(kb): Knowledge Bases — Infrastructure Overhaul (#12802)
* Add Memory Base API: models, migrations, service, endpoints, and tests

Introduces Memory Base (MB) — a per-flow knowledge base that auto-captures
conversation history and ingests it into a Chroma vector store on configurable
thresholds.

Backend changes:
- MemoryBase + MemoryBaseSession DB models with full CRUD
- Three Alembic migrations: base tables, merge head, phase-2 fields
  (embedding_model, preprocessing, preproc_model, preproc_instructions)
- MemoryBaseService: create/list/get/update/delete, session tracking,
  pending-message cursor logic, mismatch detection, regenerate
- ingest_memory_task: async Chroma ingestion with cursor advance on success
- REST API (/api/v1/memories): CRUD, flush, sessions, mismatch, regenerate
- Flow output hook: on_flow_output() triggers auto-capture after each run
- Plumbing in build.py, endpoints.py, workflow.py to call on_flow_output
- deps.py: expose get_memory_base_service()
- kb_helpers.py: FS/metadata helpers used by MB service

Authored-By: Debojit Kaushik <kaushik.debojit@gmail.com>

Add dedupe_key idempotency enforcement for MB ingestion jobs

Centralizes idempotency into JobService.create_job() with a null-safe check,
removing the redundant pre-flight logic from MemoryBaseService.

Key changes:
- services/jobs/exceptions.py: new DuplicateJobError(RuntimeError) —
  raised when a QUEUED/IN_PROGRESS/COMPLETED job with the same dedupe_key
  exists; FAILED/CANCELLED are retryable and are excluded
- services/jobs/__init__.py: exports DuplicateJobError
- services/jobs/service.py: null-guarded dedup query inside create_job()
  within the same session_scope as the insert (minimizes TOCTOU window)
- services/database/models/jobs/model.py: dedupe_key field -> index=True
- alembic/versions/36aa87831162: adds dedupe_key column + ix_job_dedupe_key
  index to job table with checkfirst guards
- services/memory_base/service.py: updated key format to
  "ingestion:{mb_id}:{session_id}:{first_msg_id}" for namespace isolation;
  removed _has_non_retryable_job_for_dedupe_key and _has_active_job methods
  and all call sites; DuplicateJobError catch in _maybe_trigger() for
  silent skip on auto-capture; split regenerate() catch clauses
- api/v1/memories.py: explicit DuplicateJobError catch before RuntimeError
  in flush_memory_base() for semantic clarity (both return 409)

Co-Authored-By: Debojit Kaushik <kaushik.debojit@gmail.com>

Checkpointing working version of MBs. TODO: User separation, Get messages endpoint, MB resumption midway through a chat for a session, tests.

Added messages endpoint for Memory Bases. Added pagination to sessions endpoint. Modifed messages model to include ingestion related attributes.

Added unit tests, fixed linting issues and formatting issues.

Aligned Workflows API, /run endpoint, playground to all work with Memory Bases. Created DB models asociated with tracking memory base state with sessions and jobs. Added tests, created unit tests for service and task files related to MemoryBases.

Improved concurrency of jobs, added (memory_base_id, session_id) locking to serialize jobs in case the job creation cadence moves ahead of ingestion jobs. Improved concurrency handling and moved the pending check to be live inside the ingestion job rather than a snapshot before triggering the job.

Consolidated all migrations related to memory_bases into one idempotent version and serialized all migrations form release along with memory_bases for cleanliness and maintainability.

Introduced advisory locking to address multi worker environment, added unique constraint to MB creation, added sanitization check to KB pathnames to avoid illegal directory creation.

Added partial write rollback for ChromaDB, aligned same session is  used for each job to avoid dangling advisory locks.

* feat(kb): Knowledge Bases Infrastructure Overhaul

* refactor(kb): reuse Memory Base helpers to reduce duplication (#12878)

* refactor(kb): reuse Memory Base helpers to reduce duplication

Stacked on top of #12802 — consolidates the overlap between this KB
infra PR and the Memory Base work in #12417 so the two PRs land
cleanly together.

1. Chain migrations linearly
   ``72df732be86b_add_ingestion_run_table`` now points at
   ``mb00a1b2c3d4`` (the Memory Base head) instead of
   ``d306e5c17c41``. Both PRs had branched from the same release
   ancestor, which would have required an Alembic merge migration at
   integration time; with the stack in place, a single linear history
   lands: ``d306e5c17c41 ← mb00a1b2c3d4 ← 72df732be86b ←
   15fe9304bca7 ← e728126476a8``.

2. Delegate the path-traversal guard to the shared helper
   ``_validate_kb_path_containment`` now wraps
   ``kb_path_helpers.validate_kb_path`` instead of duplicating its
   ``is_relative_to`` check — the HTTPException translation and
   structured log line stay here because they're route-specific, but
   the traversal rule itself is defined once.

3. Reuse ``infer_embedding_provider`` during KB backfill
   ``knowledge_base_service.backfill_from_disk`` now falls back to
   the pure-string inference helper when legacy metadata has
   ``embedding_model`` set but ``embedding_provider`` is
   ``"Unknown"``. Matches the inference the Memory Base service uses
   and avoids shipping backfilled rows with
   ``embedding_provider="Unknown"`` when the model name is
   recognizable.

4. Use ``dedupe_key`` for connector ingestions
   ``POST /knowledge_bases/{kb_name}/ingest/connector`` now builds a
   stable SHA-256 key over (user, kb, source_type,
   canonicalized-source-config) and passes it to
   ``JobService.create_job``. A double-click on "Ingest" or a retry
   racing with an in-flight job now returns HTTP 409 instead of
   spawning a duplicate run. Only the hash lands on the job row, so
   credentials in ``source_config`` don't leak through ``dedupe_key``.

5. Extract ``KBIngestionHelper.write_documents_to_backend``
   Backend-agnostic counterpart to
   ``write_documents_to_chroma`` (which is Chroma-only and used by
   Memory Base). The inline retry/cancellation loop inside
   ``perform_ingestion`` collapses into a single helper call so
   Mongo/Astra/Postgres/OpenSearch paths share identical batching,
   cancellation, and exponential-backoff behaviour with the
   file-upload/folder paths.

* Update templates

* Update .secrets.baseline

* Update component_index.json

* Update starter projects

* Update .secrets.baseline

* refactor(kb): migrate ingestion-source registry to AdapterRegistry (#12879)

Port the hand-rolled ``ingestion_sources/registry.py`` onto the
existing ``lfx.services.adapters.registry.AdapterRegistry`` so
third parties can publish ingestion sources as
pip-installable plugins without modifying core.

Plugin authors can now register sources two new ways in addition to
the in-tree ``register_source(SourceType.X, Y)`` call:

* Entry point group ``lfx.ingestion_source.adapters``
* ``[ingestion_source.adapters]`` in ``lfx.toml`` (or
  ``[tool.lfx.ingestion_source.adapters]`` in ``pyproject.toml``)

What stays the same:

* ``SourceType`` enum remains the source of truth for built-in
  identifiers; API boundaries (``ConnectorIngestRequest``) still
  validate against it.
* Every existing caller (``register_source`` / ``get_source_class``
  / ``create_source`` / ``registered_sources``) keeps its contract
  — the six built-ins continue to self-register at import time via
  ``ingestion_sources/__init__``.
* ``create_source`` still returns a fresh instance per call. Sources
  carry request-scoped ``user_id``/``source_config`` so
  ``AdapterRegistry.get_instance`` (which caches singletons) is
  bypassed in favour of ``get_class``.
* Collision semantics preserved: re-registering a different class
  under an existing key raises ``ValueError`` at import time.
* Error-message split preserved: unknown strings (call-site typo) →
  ``"Unknown ingestion source"``; known-but-unregistered →
  ``"not registered"``. API routes key HTTP 400 vs 500 off this.

New public helper: ``registered_source_keys()`` returns the full
set of registered keys (including third-party plugins) for callers
that want to surface plugins in a picker; ``registered_sources()``
still returns only the built-in ``SourceType`` enum members for
backward compatibility.

Tests:
  * Existing 49 ingestion-source tests pass unmodified (behavior
    parity with the old registry).
  * 4 new tests cover the plugin surface: entry-point registration,
    TOML registration, built-ins not shadowed by entry points, and
    the Unknown-vs-not-registered error-message split.

* fix(kb): unstick remote-backend deletes + hydrate stale embedding metadata (#12880)

* Update component_index.json

* Template update

* fix(kb): delete opensearch metadata matches (#12873)

* scope: Chroma and OpenSearch backends

* Ruff cleanup

* format

* [autofix.ci] apply automated fixes

* test(kb): cover backend registry ingestion routing (#12870)

* [codex] Add Knowledge Backends settings (#12909)

feat: add knowledge backend settings

* feat(kb): New KB backend settings

* [autofix.ci] apply automated fixes

* Update component_index.json

* chore(logs): Improve the logging display in KB

* feat(kb): Full support for OpenSearch backend

* Update index.tsx

* test(kb): tighten ingestion run auth assertion (#12872)

* test(kb): tighten ingestion run auth assertion

* [autofix.ci] apply automated fixes

* fix(kb): surface job_id in run detail modal and report skipped runs accurately

Addresses two QA findings on PR #12872:

- BUG-1: the Ingestion Run Detail modal hid the run's job_id even
  though the API returned it. Add a Run ID + Job ID block to the
  modal so operators can correlate runs with the underlying job
  service entry.
- BUG-2: a run that produced 0 successes but >=1 skipped item (e.g.
  empty file / no extractable text) was finalized as SUCCEEDED and
  surfaced via the cumulative-KB-chunks toast as "ingestion complete
  - N chunks ready". Treat any run with skipped or failed items
  (without a clean full success) as PARTIAL, and replace the toast
  with a per-run breakdown (succeeded/skipped/failed + chunks
  ingested by THIS run) shown as a notice instead of success.

Also adds a regression test for the skipped-only -> PARTIAL path in
KBIngestionHelper.perform_ingestion, and tightens types in the
existing KnowledgeBasesTab test (removes pre-existing any usage so
the staged biome no-any hook stays green).

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* test(kb): cover folder ingest allow-list wiring (#12869)

* test(kb): cover folder ingest allow-list wiring

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* fix(kb): allow clearing persisted separator (#12871)

* fix(kb): allow clearing persisted separator

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* Update component_index.json

* Update test_cometapi_component.py

* Revert "Update test_cometapi_component.py"

This reverts commit e789ef6bed.

* chore: auto-bake note keys and regenerate backend locales/en.json [skip ci]

* feat: Add test connection option for backends

* Biome check

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* chore: rebake starter projects after release-1.10.0 merge

The Validate Starter Project Templates hook regenerated the embedded
component source in Knowledge Retrieval.json and Vector Store RAG.json
to match the merged retrieval.py (now imports path/metadata helpers
from _kb_paths).

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* feat(jobs): add job_metadata mirror for KB ingestion runs

Step 1 of unifying KB ingestion tracking onto the canonical 'job'
table per @dkaushik94's review feedback on PR 12935.

Adds a nullable 'job_metadata' JSON column on the 'job' table and
mirrors the 'ingestion_run' lifecycle data onto it: create_run,
mark_running and finalize_run all dual-write the same counters,
items list, status, and source config. The 'ingestion_run' table
remains the canonical source of truth for read paths in this PR;
that's deferred to the contract phase once the API/UI migrate.

Component-path ingestions (no parent Job row) skip the mirror
without raising. JobService gains an 'update_job_metadata' helper
for shallow-merge / replace semantics.

Tests: 9 new tests cover create/mark/finalize dual-write,
component-path no-op, ghost-job tolerance, and the JobService
helper's merge/replace/missing-row branches. Existing 10
ingestion-run endpoint tests still pass.

Migration: da7f6b9b638a (EXPAND, nullable column, fully reversible)

* chore: rebake starter projects after retrieval.py TYPE_CHECKING change

* feat(jobs): unify KB ingestion tracking onto job table; drop ingestion_run

Switches both reads and writes off the legacy 'ingestion_run' table
and onto 'Job.job_metadata'. The full sequence in this PR:

  da7f6b9b638a (prev commit) — add Job.job_metadata column (EXPAND)
  927dd37c3ea0 — backfill existing ingestion_run rows (MIGRATE)
  fc7393328808 — drop the ingestion_run table (CONTRACT, reversible)

Reads/writes now go through 'Job.job_metadata'; the response shape
(IngestionRunInfo / IngestionRunDetail) is unchanged so no frontend
changes are needed. 76 tests pass.

* chore(jobs): collapse ingestion_run lifecycle migrations

The ingestion_run table never shipped to any tagged release —
verified by checking every tag from v1.9.x through v1.10.0.dev9. The
table only existed on feature branches (this one and
feat/kb-ingest-metadata). So the 'create table → backfill → drop
table' migration dance was theatre for a table no production user
ever had.

Collapses 5 migrations to 1 by deleting:
  72df732be86b — add ingestion_run table
  e728126476a8 — add kb_id FK to ingestion_run
  927dd37c3ea0 — backfill ingestion_run → job.job_metadata
  fc7393328808 — drop ingestion_run table

Repoints the chain so 15fe9304bca7 (knowledge_base) attaches directly
to mb00a1b2c3d4, and da7f6b9b638a (Job.job_metadata) attaches after
15fe9304bca7. Net schema change for production users: a single
nullable JSON column added to the job table.

Devs running this feature branch locally and carrying an
ingestion_run table in their dev DB will need to drop it manually or
nuke + re-migrate. There are no production users of this branch by
construction.

Tests: all 22 KB-related tests still pass.

* refactor(kb): drop unused VectorStoreBackend Protocol

The Protocol was exported as part of the public surface but nothing
in the codebase actually used it as a type annotation, isinstance
narrowing target, or registry constraint:

  - Every concrete backend (Chroma/OpenSearch/Mongo/Astra/Postgres)
    inherits from the BaseVectorStoreBackend ABC
  - The registry signature requires type[BaseVectorStoreBackend]
  - No call site used '\: VectorStoreBackend' or
    'isinstance(x, VectorStoreBackend)'
  - The only test reference (a runtime-check assertion) duplicated
    the ABC isinstance check on the line above

Per @dkaushik94's review feedback: the Protocol was dead weight.
Folded its contract-level guidance ('lightweight to construct, heavy
resources released in teardown') into the ABC docstring so the
documentation isn't lost, then deleted the Protocol class and
trimmed exports.

Test surface: replaced the Protocol runtime-check assertion in
test_backends_registry.py with a BaseVectorStoreBackend isinstance
check (same intent, no Protocol needed). 9 registry tests pass.

* refactor(kb): standardize Job.asset_id on KnowledgeBaseRecord.id

Per @dkaushik94's review on list_runs_for_kb: switches the read-side
filter from a JSON-extract on Job.job_metadata.kb_name to an indexed
btree lookup on Job.asset_id. Required standardizing what asset_id
means for KB ingestion jobs.

Before — Job.asset_id was set to metadata['id'] (a UUID stored in
embedding_metadata.json), independent of the knowledge_base table's
primary key. Two id-spaces in flight, with legacy generation logic
inlined at three create_job sites.

After — Job.asset_id is set to KnowledgeBaseRecord.id everywhere.
When the KB has a DB record (the common case post-startup-backfill),
the row's primary key flows directly onto Job.asset_id. Legacy KBs
on disk only fall back to metadata['id'] (or a generated UUID) so
backwards-compat survives.

* New _resolve_kb_asset_id helper centralizes the resolution logic.
  Three ingest endpoints (file upload / folder / connector) and the
  cancel endpoint now go through it instead of inlining metadata['id']
  reads with their own fallback dance.
* list_runs_for_kb resolves the kb_record up front and filters by
  Job.user_id + asset_type='knowledge_base' + asset_id=kb_record.id
  when present. Falls back to JSON-extract on kb_name only for KBs
  without a DB record.
* Tests: _insert_run helper auto-provisions a KnowledgeBaseRecord so
  the indexed path is exercised by default. New unit test pins the
  indexed-path behavior: two Jobs with the same kb_name in metadata
  but different asset_ids must not cross-contaminate the result set.

23 KB tests pass (13 service + 10 endpoint).

* refactor(kb): drop embedding_provider/model columns; model_selection is the single source

Per @dkaushik94's review: the flat embedding_provider /
embedding_model columns on KnowledgeBaseRecord were redundant
with model_selection, which already carried the same data inside
its dict. Drops the columns and routes everything through two new
helpers.

* New helpers get_embedding_provider(model_selection) and
  get_embedding_model(model_selection) in
  langflow.api.utils.knowledge_base_service. Both extract the
  field from a model_selection payload (single-dict or list-wrapped),
  with sensible fallbacks ("Unknown" / empty string).
* record_to_metadata_dict continues to emit the flat keys in the
  legacy JSON shape (the API response and on-disk metadata.json
  consumers still want them) — but they're now derived views over
  model_selection via the helpers, not separate columns.
* KnowledgeBaseRecord model: removed the two columns. Migration
  15fe9304bca7_add_knowledge_base_table.py edited to not create
  them in the first place (branch has no users — same approach as the
  ingestion_run lifecycle collapse).
* create_record signature drops embedding_provider /
  embedding_model params. Three callers updated:
  - knowledge_bases.py:create_knowledge_base folds the request's
    flat fields into model_selection when the request didn't
    carry one of its own.
  - lfx/components/files_and_knowledge/ingestion.py:_persist_kb_record
    passes model_selection directly.
  - backfill_from_disk synthesizes model_selection from the
    legacy on-disk flat fields (preserving the
    infer_embedding_provider fallback for KBs that only have a
    model name).
* On-disk embedding_metadata.json writes (in
  lfx/components/files_and_knowledge/ingestion.py) and
  KBAnalysisHelper.get_metadata reads of those flat keys are
  unchanged — the file format keeps the flat fields for back-compat
  with retrieval / memory_retrieval readers.
* Tests: ~10 sites updated to pass model_selection={...} instead
  of the two flat params. test_backfill_inserts_missing_rows now
  asserts on record.model_selection.get('provider').

API surface: CreateKnowledgeBaseRequest and KnowledgeBaseInfo
keep the flat fields (frontend back-compat is preserved). The
columns are gone, the helpers are the single source of truth.

31 tests pass (21 service + 10 endpoint).

* [autofix.ci] apply automated fixes

* fix(kb): standardize perform_ingestion on model_selection

CI surfaced a TypeError after the previous commit's global rename
swept up a perform_ingestion() test call too — that function still
took flat embedding_provider / embedding_model args while the test
was now passing model_selection.

Aligned the helper with the rest of the standardization: drops the
two flat params, accepts model_selection (dict | list) and derives
provider / model internally via the existing
get_embedding_provider / get_embedding_model helpers when calling
build_embeddings.

Updated all three call sites in knowledge_bases.py
(file-upload / folder / connector ingest paths) to pass
model_selection — synthesized from the legacy flat metadata fields
when the on-disk metadata predates model_selection. Reverted the one
test that the original sweep missed (test_perform_ingestion_rollback)
to the new shape.

4/4 TestPerformIngestionTask tests pass.

* Update Vector Store RAG.json

* feat(kb): user metadata on ingestion + retrieval (#12921)

* fix(frontend): rename KB upload labels and open ingest section by default

Rename "Configure Sources" heading to "Ingest Content" and the dropdown
trigger from "Add Sources" to "Add Files". Drop the "Hide Configuration"
footer toggle so the ingest section is always visible. Chunk size,
overlap, and separator inputs render disabled until at least one source
is added. Match the Add Files focus-visible ring to border-input so the
Radix-managed focus return no longer flashes a black outline.

* fix(models): mark Google + IBM embedding models deprecated

Flag the Google Generative AI and IBM WatsonX embedding model entries in
the unified model catalog as deprecated. They are not natively supported
by Knowledge Base ingestion, so users were attempting invalid
configurations. The KB upload picker and Model Providers modal now fetch
with include_deprecated=true and render a "Deprecated" badge so the
models stay visible but are clearly flagged as unsupported.

* fix(models): keep gemini-embedding-001 active

Only mark text-embedding-004 and embedding-001 as deprecated; the
gemini-embedding-001 model is still served by the Google Generative AI
v1beta endpoint, so leave it visible without the badge.

* feat(kb): user metadata on ingestion + retrieval

Surface the per-chunk user-metadata pipeline that already lives on the KB
infra branch. Adds the API + UI to collect tags at ingest time, persist
them on the ingestion_run row, filter the chunks browser by them, and
narrow KnowledgeBaseComponent retrieval through them.

Backend
- POST /{kb}/ingest gains optional metadata + per_file_metadata multipart
  fields. POST /{kb}/ingest/folder gains the same fields on its JSON body.
- New parse_user_metadata / parse_per_file_metadata helpers enforce ≤16
  keys, lowercase ^[a-z0-9_]{1,32}$ keys, ≤256-char values, ≤16-item
  string arrays, and reject the reserved chunk-internal keys.
- FileUploadSource and FolderSource merge per-file overrides into each
  IngestionItem.source_metadata; perform_ingestion now lets per-item
  values win over run-level on key collision.
- ingestion_run grows a user_metadata JSON column (alembic
  16a290ab1332, EXPAND, server_default '{}').
- GET /{kb}/chunks accepts repeating meta_<key>=<value> params; values
  AND across keys, OR within each key. Sidesteps the global comma-split
  query middleware that breaks JSON-blob query params.
- KnowledgeBaseComponent gains a metadata_filter input that post-filters
  the similarity_search results client-side until per-backend
  translators land.

Frontend
- New MetadataEditor renders inside the KB upload modal under Chunking
  Settings for run-level tags, and inside FilesPanel as an expandable
  per-file override.
- Chunks browser gets ChunksMetadataFilter (popover + chips) wired into
  useGetKnowledgeBaseChunks via the new metadata_filter param map.

Tests
- 29 validator tests for the rule set, 4 ingestion-source tests for
  per-file propagation + describe counts, integration tests for the
  chunks endpoint AND/OR filter, 9 retrieval-side helper tests for
  parse + match, 8 frontend MetadataEditor tests.

* [autofix.ci] apply automated fixes

* feat(kb): show metadata tags in upload review summary

Surface run-level tags + per-file override count in the Step 2 Review
summary so users can confirm what is about to ship onto each chunk
before clicking Create. Empty metadata stays invisible to keep the
summary tight on the common no-tag path.

* [autofix.ci] apply automated fixes

* chore: auto-bake note keys and regenerate backend locales/en.json [skip ci]

* fix(kb): restore IngestionRun model after merge wipe

The merge from fix/kb-ingest-content-naming (based off release-1.10.0)
silently dropped the IngestionRun SQLModel + its registration in the
models package __init__. Without the model, alembic's autogenerate
guard saw the live DB column-set drift from the empty target_metadata
and raised AutogenerateDiffsDetected at startup, blocking the backend
from booting.

Restore the model files and re-add the import + __all__ entry so the
table is visible to SQLModel's MetaData on boot.

* [autofix.ci] apply automated fixes

* fix(kb): restore ingestion_run migrations after merge wipe

Same root cause as the previous fix: the merge from
fix/kb-ingest-content-naming dropped not just the IngestionRun model
but the three migrations that build the ingestion_run schema:

- 72df732be86b — create ingestion_run table
- e728126476a8 — add kb_id FK column
- 16a290ab1332 — add user_metadata JSON column

Without these, the model says the table exists while no migration
creates it, so test_no_phantom_migrations flags a phantom add_table
diff and the model/migration consistency CI step fails.

Restore the migration files from the original feature commit. Schema
is unchanged from that commit so this is byte-for-byte the state CI
last saw green on this branch.

* fix(alembic): collapse ingestion_run + job_metadata heads to a single tip

Two issues blocked test_no_phantom_migrations after the previous
restoration:

1. e728126476a8 (add kb_id to ingestion_run) chained off
   15fe9304bca7 (creates knowledge_base) which left the
   ingestion_run-creation migration 72df732be86b dangling as its own
   head. Re-chain e728126476a8 onto 72df732be86b so the ingestion_run
   chain is linear; the FK target dependency on knowledge_base is
   declared via depends_on instead of down_revision.

2. After step 1 the graph still had two independent tips —
   16a290ab1332 (ingestion_run.user_metadata) and da7f6b9b638a
   (job.job_metadata) — neither referencing the other. Add an empty
   merge migration 5238aab36810 unifying both so 'alembic upgrade
   head' resolves to a single revision.

`alembic heads` now reports ['5238aab36810'] and
test_migration_execution passes locally (8 passed, 2 sqlite-only
skips).

* [autofix.ci] apply automated fixes

* fix(alembic): mark merge migration with EXPAND phase

The migration validator only accepts EXPAND / MIGRATE / CONTRACT.
Empty merge migrations are pure graph nodes (no DDL) so they belong
in EXPAND — they never drop or rewrite data.

* Update component_index.json

* fix(frontend): align KB upload modal test text with i18n strings

CI surfaced a TestingLibraryElementError — the test was looking for
'Ingest Content' / 'Add Files', but the merge from
feat/kb-v1-db-connectors switched those to i18n strings
('Configure Sources' / 'Add Sources' via t('knowledge.configureSources')
etc.).

Updates the two assertions and the surrounding test names to match
the current rendered copy. 71/71 KnowledgeBaseUploadModal tests pass.

* feat(kb): metadata input on flow KnowledgeIngestionComponent

Adds a Metadata advanced input accepting a JSON object. The decoded
dict is JSON-encoded once per run and stamped onto every chunk's
source_metadata key — same shape the API path writes — so the chunks
browser metadata filter and KnowledgeBaseComponent.metadata_filter
work uniformly across upload, folder, and flow-driven ingestion.

Malformed JSON or non-object payloads log a warning and skip the
metadata stamp rather than failing the run.

* chore: auto-bake note keys and regenerate backend locales/en.json [skip ci]

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Eric Hare <ericrhare@gmail.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* chore: rename knowledge backends to db providers

* Linting cleanup

* Update dbProviderConstants.ts

* fix: icon assets

* Update index.tsx

* fix: Ensure selection of default provider

* Update indices

* chore: Consolidate database migrations

* Update kb1a2b3c4d5e_add_knowledge_base_schema.py

* fix: Ingestions from component behave same

* Ruff fixes

* More ruff fixes

* Update Vector Store RAG.json

* [autofix.ci] apply automated fixes

* Starter project update

* fix: Address two P1s for folder access

* Regen other deps

* fix(knowledge-base): pin review modal height, poll active ingestion runs, rename labels (#12977)

* fix(knowledge-base): pin review modal height and poll active ingestion runs

- Lock the upload modal to a fixed `h-[690px]` on the Review step so the
  envelope no longer resizes as users page through chunk previews of
  varying length. Step 1 keeps its `min-h-*` flex behavior.
- Add drawer-scoped polling to the Ingestion Runs section: refetch every
  5s while any run is non-terminal (`pending`/`running`), refetch on
  drawer open, and stop entirely once all rows are terminal or the
  drawer closes. Background tabs are skipped via
  `refetchIntervalInBackground: false`.

* fix(knowledge-base): rename Configure Sources to Ingest Content and Add Sources to Add Files

Update the English locale to align the upload modal labels with the
agreed wording:

- `knowledge.configureSources` / `knowledge.helpConfigureSources`:
  "Configure Sources" -> "Ingest Content"
- `knowledge.addSources` / `knowledge.addSourcesTitle` /
  `knowledge.submitAddSources`: "Add Sources" -> "Add Files"

`knowledge.sourcesLabel` ("Sources") is intentionally left as-is. Other
locales remain untouched and will be picked up via the existing
translation flow.

* Update component_index.json

* Update KnowledgeBaseUploadModal.test.tsx

* Update component_index.json

* fix(knowledge-base): surface metadata on chunk cards and make filter self-documenting (#12993)

Closes the QA-flagged UX gap where the chunks-browser metadata feature
was effectively only usable by API users. Two fixes bundled:

- Chunk cards now render the source file name + user-supplied tags as
  chips, so the metadata applied at ingestion time is visible without
  hitting the API. Reserved ingestion-internal keys (chunk_index,
  job_id, etc.) stay hidden via a frontend mirror of
  KB_METADATA_RESERVED_KEYS.

- The "Filter by metadata" popover no longer asks the user to type
  blind. A new GET /knowledge_bases/{kb}/metadata/keys endpoint scans
  chunks server-side and returns distinct user keys + a sample of
  values (capped at 50/key with a truncated flag). The popover binds
  both inputs to a <datalist>, so users get native suggestions on
  click while keeping free-text typing for keys not yet ingested.
  Refetches on every popover open so freshly-ingested metadata shows
  up without a hard page refresh.

Test coverage: 41 backend tests in TestKnowledgeBaseAPI (3 new for
the keys endpoint), 30 frontend tests in sourceChunksPage (file_name
rendering, user-tag chips, reserved-key hiding, array-valued tags,
malformed JSON, datalist population, validation, refetch-on-open).

* feat(knowledge-base): KB row settings shortcut + ingestion history in Update modal (#13012)

Two QA-flagged UX gaps on the Knowledge Bases tab:

- "Update Knowledge" was buried inside the row's overflow menu — promoted
  to a one-click settings icon directly on the row, with the dropdown
  retained for the rest of the row actions. Disabled while ingesting,
  matching the dropdown rule.

- The "Update Knowledge" modal gave no visibility into what a KB
  already contained, so users couldn't tell if a file had been ingested
  before. New collapsible "Previously ingested" panel above the upload
  fields shows each prior run with its user-typed source name, type,
  date, status, and counts. Empty/loading/error states covered.

Backend additions
- IngestionRunInfo gains a ``source_name`` field, populated in
  ``_run_row_to_info`` from ``RunRow.source_config["source_name"]``.
  Whitespace-only values collapse to ``None`` so the frontend renders
  the type label as a clean fallback.

Frontend
- IngestionHistoryPanel uses ``useGetIngestionRuns`` with
  ``staleTime: 0`` + ``refetchOnMount: "always"`` so the list is fresh
  immediately after an ingest, mirroring the cache fix from #12993.
- StepConfiguration receives ``kbName`` and renders the panel only when
  ``isAddSourcesMode && kbName``.
- Run row prefers ``source_name`` (e.g. "Test6") with the type label
  ("File Upload") as a small subtitle when both are present.

Tests
- Backend: new ``test_exposes_source_name_from_source_config`` covers
  populated, missing, and whitespace-only cases.
- Frontend: 6 IngestionHistoryPanel tests (empty/loading/error/render
  states, source_name preference, whitespace handling, collapse,
  hook args). 3 new column tests for the row settings icon. Existing
  column tests migrated to the new ``kb-row-actions-trigger`` testid.

* Update Vector Store RAG.json

* chore: auto-bake note keys and regenerate backend locales/en.json [skip ci]

* Update IngestionHistoryPanel.tsx

* fix(memory-base): resolve embeddings from static registry, fix Google Gemini provider inference (#13023)

Memory Base retrieval failed with "Embedding model X for provider Y not
found." for every supported embedding model. Two interacting bugs:

1. KBIngestionHelper.build_embeddings looked the model up in the
   user-filtered catalog returned by get_embedding_model_options. That
   catalog is empty whenever the per-user credential lookup silently
   returns an empty enabled-providers set — which happens when the call
   bridges from an async event loop into a worker thread. Fall back to
   the static EMBEDDING_PROVIDER_CLASS_MAPPING / EMBEDDING_PARAM_MAPPINGS
   registry instead: the metadata persisted in embedding_metadata.json
   is the source of truth, and the runtime API key is still resolved by
   get_embeddings.

2. infer_embedding_provider mis-classified models/gemini-embedding-001
   as "OpenAI" (no Google pattern matched the gemini-embedding name) and
   the Google patterns returned "Google" instead of the canonical
   "Google Generative AI" registered in EMBEDDING_PROVIDER_CLASS_MAPPING.
   Look the model up in the unified catalog first, and update the
   pattern table to use the canonical provider name plus the
   "models/..." prefix Google uses.

Adds regression tests covering OpenAI text-embedding-3-*, Google
gemini-embedding-001, and the previously-empty user-filtered catalog
path.

* feat: Adding Chroma Cloud as Vector DB provider (#13030)

* Adding Chroma Cloud support for Knowledge Bases.

Added Chroma cloud support. Users can configure Chroma Cloud and switch between providers especially between ChromaDB local and Cloud.

* [autofix.ci] apply automated fixes

* Update Vector Store RAG.json

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Eric Hare <ericrhare@gmail.com>

* fix(kb): align OpenSearch KB default vector field with canvas component (#13009)

* fix(kb): align OpenSearch KB default vector field with canvas component

The KB OpenSearch backend defaulted to 'vector_field' while the
canvas OpenSearch component defaults to 'chunk_embedding'.
Combining KB ingestion with the canvas component on the same index
failed with "Field 'chunk_embedding' is not knn_vector type".

Switch the KB backend (and the corresponding frontend defaults /
fallbacks in the DB Providers settings page) to 'chunk_embedding'
so both layers agree out of the box. Operators who already
ingested into 'vector_field' can still override via backend_config
or the global variable.

* test(kb): pin OpenSearch backend default vector_field to 'chunk_embedding'

Adds unit coverage for ``OpenSearchBackend`` so the canvas / KB
field-name alignment can't silently regress:

* asserts ``DEFAULT_VECTOR_FIELD == 'chunk_embedding'``,
* asserts ``_build_vector_store`` passes ``vector_field='chunk_embedding'``
  to the LangChain wrapper when no override is provided,
* asserts an explicit ``backend_config['vector_field']`` still wins,
* parametrized table for None / empty / truthy resolution.

* fix(kb): cancel in-flight ingestion jobs on KB delete (#13003)

* fix(kb): cancel in-flight ingestion jobs on KB delete

Without this, deleting a KB while an ingestion job is running would
leave the deleted KB reappearing in the list a few seconds later. The
background job kept polling `is_job_cancelled` (it never tripped) and
its open backend client would auto-recreate the KB directory on the
next chunk write — Chroma's PersistentClient creates its sqlite parent
on demand. The ingestion then rewrote `embedding_metadata.json` into
the recreated dir, and the list endpoint's disk-fallback path
re-discovered it as a valid KB.

Add `JobService.cancel_in_flight_jobs_by_asset` and call it from the
single + bulk KB delete endpoints before storage teardown. The
ingestion's existing cancelled-handler then runs cleanup, so no
further chunks are written.

* fix(kb): DB-first delete + .kb_deleted sentinel hides locked-disk dirs

Two related bugs around KB delete on Windows when Chroma still holds an
exclusive SQLite lock:

  1. delete_storage() ran before the DB row delete, so a locked rmtree
     turned into HTTP 500 and left the row dangling.  The dir was
     partially cleaned (non-locked files removed) but the row plus the
     SQLite stub kept the KB visible to listings.
  2. The disk-scan fallback in get_knowledge_bases() and the API list
     endpoint had no way to tell a "really still here" dir from a
     "we tried to delete this and rmtree was blocked" dir, so a deleted
     KB kept reappearing in the canvas component dropdown.

Fix:

  * KBStorageHelper.delete_storage() now drops a .kb_deleted sentinel
    file inside any directory it could not physically remove.  Replaces
    the previous .deleted_<name>_<timestamp> rename fallback (which
    failed under the same Windows lock conditions on the rename itself).
  * delete_knowledge_base() and delete_knowledge_bases_bulk() reorder
    to DB-first (Option A).  When the DB delete succeeds and storage
    cleanup fails, the endpoint returns 200 with a warning instead of
    500: the user no longer sees the KB, and the operator gets a clear
    follow-up message.
  * lfx.base.knowledge_bases.knowledge_base_utils.get_knowledge_bases()
    skips dirs carrying the sentinel.  The API-side list endpoint's
    disk-scan fallback does the same via KBStorageHelper.is_kb_dir_deleted.
  * create_knowledge_base() detects sentinel-marked dirs and surfaces a
    clearer 409 ("previously deleted; awaiting restart cleanup") instead
    of the bare "already exists", and clears any stale sentinel after a
    successful mkdir as a defensive no-op.
  * Cross-package contract: the lfx layer cannot import from the langflow
    API package, so it inlines the sentinel filename string.  A unit
    test in test_kb_storage_deletion.py asserts the inlined value matches
    KB_DELETED_SENTINEL.

Tests: 88 KB-related tests pass (test_kb_storage_deletion.py +
test_knowledge_bases_api.py).  Two existing tests updated to assert the
new 200-with-warning shape; the previous 500-on-storage-failure shape
was the buggy behavior.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: Stay deleted when sentinel shows up

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: enforce session isolation in MemoryBase retrieval and purge chunks on session delete (#13037)

* fix: enforce session isolation in MemoryBase retrieval and purge chunks on session delete

Two related bugs in the MemoryBase feature (#12903):

1. Filter by Session: switch the Chroma where-clause to the canonical
   `{"session_id": {"$eq": ...}}` form and force-coerce the toggle to
   a real bool. Both shapes are accepted by chromadb today, but the
   explicit form removes any ambiguity if a non-bool slips into the
   attribute and would otherwise be truthy (e.g. the literal string
   "false").

2. Ghost chunks on session delete: the message-session delete
   endpoints only wiped MessageTable rows, leaving every embedded
   chunk behind in Chroma. New sessions then pulled the deleted
   data back through the retrieval component. Wire the delete
   endpoints to a new `MemoryBaseService.purge_session_data` that
   walks the user's Memory Bases, deletes chunks where
   `session_id == X`, and clears the corresponding tracking rows
   (MemoryBaseSession + MemoryBaseWorkflowRun). Chunk-delete
   failures are logged but never abort the user-visible message
   delete.

* Update ingestion.py

* fix: exclude component error messages from MemoryBase ingestion (#13039)

Component errors (e.g. an embedding API failure) were persisted to the
message table with `error=True` / `category='error'` and the MemoryBase
ingestion task pulled them in like any other message, embedding the error
text into Chroma. Retrieval then surfaced these chunks as context.

Filter both signals at the SQL fetch boundary so errors never enter the
document-build / Chroma write path. The cursor still advances past any
later non-error message, so skipped error rows are not reconsidered.

Includes regression tests covering the error flag, the error category,
and cross-session/cross-flow isolation.

* fix(kb): require OpenSearch username/password in DB Provider settings (#13005)

The DB Providers settings panel marked Username and Password as
optional, but the OpenSearch runtime components (canvas vector-store +
KB backend) default to basic auth and raise "Auth Mode is 'basic' but
username/password are missing" when the corresponding global variables
aren't set. Operators who filled in only the cluster URL hit a
confusing error far downstream from the settings screen.

Mark the credential fields required so the existing canSave / save
validation in DBProvidersPage forces them up-front. Operators with
auth-less clusters (sigv4 / upstream proxy) can still satisfy the
form with a placeholder value — OpenSearch ignores credentials when
auth is not enforced.

Also assert the asymmetric (one-field-only) case in tests, since the
backend's tuple-based http_auth silently treats partial creds as
no-auth.

* Update component_index.json

* Update component_index.json

* chore: auto-bake note keys and regenerate backend locales/en.json [skip ci]

* Update kb1a2b3c4d5e_add_knowledge_base_schema.py

* [autofix.ci] apply automated fixes

* fix: templates

* fix: Session filtering for memory bases

* chore: auto-bake note keys and regenerate backend locales/en.json [skip ci]

* Update component_index.json

* chore: auto-bake note keys and regenerate backend locales/en.json [skip ci]

* Update test_memory_retrieval.py

* test: pin OpenSearch backend filter=None drop behavior

The OpenSearch backend's similarity_search override drops `filter` when
None/empty so LangChain's OpenSearchVectorSearch wrapper never injects
`"filter": null` into the k-NN query body. If that regresses, every KB
retrieval against OpenSearch fails with x_content_parse_exception and the
upstream flow loses both KB and any downstream context — which is the most
likely OpenSearch-only symptom shape behind Rafael's report.

These tests pin:
- filter=None: kwarg is dropped from both asimilarity_search and
  asimilarity_search_with_score
- filter={}: also dropped (k-NN parser rejects empty objects)
- filter={truthy}: forwarded unchanged

* fix(knowledge-base): KB UI polish — drawer + row dropdown (#13069)

* fix(knowledge-base): keep drawer open when interacting with row dropdown

The KnowledgePage outside-click handler treats clicks on Radix portal
content (dropdown menus, popovers, dialogs, tooltips) as outside the
drawer and closes it. Because dropdown content lives on document.body,
clicking a menu item triggered closeDrawer, the layout reflowed (mr-80
toggled off), AG-Grid resized, and the row re-rendered—tearing down the
open dropdown before the click event reached the menu item. Result:
"View Chunks" and other row actions required two clicks.

Skip the dismissal when the mousedown target is inside any Radix popper
portal, menu, dialog, or tooltip.

* refactor(knowledge-base): rename row action to "Ingest Files" with FileUp icon

The row shortcut and dropdown item previously used a gear icon and the
label "Update Knowledge". The gear implies settings, but the only action
behind it is adding/ingesting files. Switch both the icon (Settings →
FileUp, RefreshCw → FileUp) and the label ("Update Knowledge" → "Ingest
Files") so the affordance matches the action.

Tooltip, aria-label, and dropdown item label updated. Tests adjusted
accordingly.

* fix(knowledge-base): stop clipping stacked Layers icon in Name column

The Name cell renderer applied "-mx-[3px]" to the row icon, pulling it
3px outside its layout box. For KBs with multiple source types the icon
becomes "Layers" (stacked), which has visible content right up to its
bounding box. With the negative margin, the icon's left edge crossed
AG-Grid's cell overflow boundary and got clipped.

Drop the negative margin, give the cell wrapper a 4px left padding for
breathing room, and tighten the icon→text gap from 4 to 3 so total
horizontal layout stays close to the original.

* fix(knowledge-base): give ingestion history rows room to breathe

Rows in the Previously Ingested panel packed the status badge, source
name, type label, and time onto a single line. Long source names + long
type labels (e.g. "Chroma Cloud Collection") clipped against the time
stamp and made the row hard to scan.

Restructure each row into three stacked sections:
  1. status badge (left) · relative time (right)
  2. source name (sm/medium) with the type label as a quiet subtitle
  3. succeeded / failed / skipped counts · chunks

Row padding bumped from p-2 to p-3 and inter-section gap from gap-1 to
gap-2 to match the new hierarchy.

* refactor(knowledge-base): drop Source Files / Linked Flows placeholders

Both sections in the KB inspection drawer always rendered the same empty
state ("No source files available." / "No linked flows available.")
because neither field is wired up on the backend yet. Showing empty
placeholders adds noise without giving the user information.

Remove the two sections from the drawer. Update the mock + assertions
in KnowledgeBaseDrawer.test.tsx so the test stops claiming the removed
strings should render.

* fix(knowledge-base): give drawer ingestion runs the same room to breathe

The drawer's Ingestion Runs rows had the same cramped single-line layout
the modal panel had before the previous commit: status badge + source
type + time crammed onto one row, counts beneath. Match the new pattern
so the two surfaces feel consistent.

Each row now stacks:
  1. status badge (left) · relative time (right)
  2. source type label (sm/medium)
  3. succeeded / failed / skipped counts · chunks · bytes

Row padding bumped p-2 → p-3 and inter-section gap gap-1 → gap-2.

---------

Co-authored-by: Eric Hare <ericrhare@gmail.com>

---------

Co-authored-by: Debojit Kaushik <kaushik.debojit@gmail.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: keval shah <kevalvirat@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 21:21:07 +00:00
540ae9fea2 chore: remove internal ticket references from code (#13073) 2026-05-11 19:25:27 +00:00
81913eb668 fix: add [proxy] extra to litellm dependency for langflow-ide (#12235)
* fix: add apscheduler and cryptography for litellm proxy_server imports

When langflow-ide logs through litellm (e.g. to langfuse), litellm imports
its proxy server module, which requires `apscheduler` and `cryptography` at
runtime. The natural fix would be `litellm[proxy]`, but that extra pins
boto3>=1.40.76, which collides with our `aioboto3` transitives on
release-1.10.0. Adding the two missing modules directly keeps the install
working without taking on the rest of the proxy server runtime.

Fixes #12228

* test: guard apscheduler and cryptography in litellm extra

Asserts the `litellm` optional-dependency group keeps the runtime modules
needed for langfuse logging via litellm.proxy.proxy_server (#12228).

---------

Co-authored-by: Jah-yee Agent <agent@openclaw.ai>
Co-authored-by: Eric Hare <ericrhare@gmail.com>
2026-05-11 12:17:16 -07:00
994a2e8b94 feat: Isolate FileSystem tool sandbox per authenticated user (#13031)
* add user id scope to file sys actions

* add security sandbox

* fs user isolation doc

* chore: auto-bake note keys and regenerate backend locales/en.json [skip ci]

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* [autofix.ci] apply automated fixes (attempt 3/3)

* fix be tests

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* [autofix.ci] apply automated fixes (attempt 3/3)

* ruff style and checker

* ruff style and checker

* ruff style and checker

* chore: auto-bake note keys and regenerate backend locales/en.json [skip ci]

* [autofix.ci] apply automated fixes

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-05-11 15:41:55 -03:00
ec66e55a73 fix: gracefully handle pyperclip failure in headless/remote environments (#12614)
* fix: gracefully handle pyperclip failure in headless/remote environments (fixes #12341)

The langflow api-key command failed in Docker/SSH environments because pyperclip
could not find a clipboard mechanism. Wrap the clipboard copy in a try/except so
the API key is still displayed when clipboard access is unavailable.

* [autofix.ci] apply automated fixes

* test: cover pyperclip failure path in api_key_banner (#12341)

Regression guard ensuring the API key is still displayed when the
clipboard mechanism is unavailable (Docker/SSH/headless), plus a
drift guard for the happy-path clipboard hint.

* fix: log clipboard failure instead of silent pass (ruff S110)

Replaces the bare `except: pass` with a debug log so the failure is
diagnosable in headless environments without spamming users with
warnings about an expected condition.

---------

Co-authored-by: octo-patch <octo-patch@github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Eric Hare <ericrhare@gmail.com>
2026-05-11 18:10:51 +00:00
fb460a9c30 test: Skip user-flow-state-cleanup e2e on Windows CI (#13070)
* remove flow state test from windows arch

* skip shard starter projects on windows
2026-05-11 15:08:58 -03:00
5c111a19ab fix: strip reserved 'code' param before build() in component reuse path (#12712)
* fix: strip reserved 'code' param before build() in component reuse path (#8610)

Root cause: When a custom component is reused (self.custom_component already exists),
get_params() returns params that still include the reserved 'code' field. Unlike the
instantiate_class path which pops 'code' before use, the reuse path passes it through
to build_custom_component, which calls build(**params) — causing TypeError for
components whose build() method does not accept **kwargs.

Made-with: Cursor

* test: add regression tests for custom component code parameter reuse

Verifies that TypeError no longer occurs when reusing custom components
with the code parameter in both instantiate and reuse paths.

Per CodeRabbit review on PR #12712.

Made-with: Cursor

* [autofix.ci] apply automated fixes

* fix: also strip 'code' from build params in langflow loading duplicate

Mirror the lfx fix in the parallel src/backend/base/langflow/interface/
initialize/loading.py copy. In production this build_custom_component is
dead code (only update_params_with_load_from_db_fields is imported from
this module), but keeping the duplicate in sync avoids future drift and
the same TypeError if any caller starts using it.

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Eric Hare <ericrhare@gmail.com>
2026-05-11 17:01:18 +00:00
89d5475b43 fix: use stable UUIDs for Qdrant document IDs to prevent duplicate ingestion (#12642)
* fix: use stable UUIDs for Qdrant document IDs to prevent duplicate ingestion (fixes #12641)

* fix: deterministically serialize Qdrant doc metadata for stable IDs

Use json.dumps with sort_keys=True and the project's custom_serializer
instead of str(sorted(metadata.items())). The previous form relied on
Python's repr for nested dicts/sets/datetimes/Decimals, which is unstable
across processes (PYTHONHASHSEED for sets) and does not recurse into
nested dict ordering.

* test: add unit tests for Qdrant stable-ID generation

Cover the four invariants of the deterministic UUID5 derivation:
  - same content + metadata yields the same UUID across runs (uuid5)
  - metadata insertion order is irrelevant (sort_keys=True)
  - different content yields different UUIDs
  - non-primitive metadata (datetime, Decimal) serializes via custom_serializer

---------

Co-authored-by: octo-patch <octo-patch@github.com>
Co-authored-by: Eric Hare <ericrhare@gmail.com>
2026-05-11 16:34:17 +00:00
88f38f1b58 fix: update isinstance(value, Data) logic (#12769)
* update `isinstance(value, Data)` logic

* fix bug and add tests

* [autofix.ci] apply automated fixes

* fixing bug that outside of my implementation in Phoenix

* fix: disable pytest plugin autoload in unit tests

* fix ruff

* fix: preserve structured Data payload instead of recursive conversion

* fix: harden arize phoenix data conversion

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Eric Hare <ericrhare@gmail.com>
2026-05-11 09:00:52 -07:00