Commit Graph

96 Commits

Author SHA1 Message Date
5a8c17b22d ci: backport bundle/nightly CI fixes from main (#13206, #13207, #13208) (#13210)
* ci: stop publishing -nightly bundle variants; release bundles on demand (#13206)

Bundles (lfx-arxiv, lfx-duckduckgo) change infrequently enough that a
nightly cadence is overkill. Drop the rename-to-`-nightly` and bundle
publish lanes from the nightly pipeline and add a dedicated
workflow_dispatch-only release_bundles.yml for purposeful releases.

- nightly_build.yml: drop update_bundle_versions.py invocation and the
  src/bundles/*/pyproject.toml git-add guard.
- release_nightly.yml: remove build-nightly-bundles and
  publish-nightly-bundles jobs; untether test-cross-platform and
  publish-nightly-main from them.
- release_bundles.yml (new): build all src/bundles/* wheels, run a
  cross-OS install smoke test, then publish to PyPI under their stable
  names. Tolerates already-published versions so re-runs without a
  version bump are no-ops.

release.yml still owns bundle publishing as part of main releases.

Manual follow-up (PyPI admin): delete the lfx-arxiv-nightly and
lfx-duckduckgo-nightly projects from PyPI.

* ci(release_bundles): build lfx wheel locally for smoke test (#13207)

The release_bundles.yml smoke test installs bundle wheels into a fresh
venv, which makes uv resolve their `lfx>=X.Y,<Z` pin against PyPI. When
bundles are released ahead of a matching lfx (typical case — bundles
ship more often than lfx bumps land on PyPI), the resolve fails:

  Because only lfx<=0.4.3 is available and lfx-arxiv==0.1.0 depends on
  lfx>=0.5.0,<0.6.0, we can conclude that lfx-arxiv==0.1.0 cannot be
  used.

Build the lfx wheel from the current ref in the build-bundles job and
install it alongside the bundle wheels in the smoke test. The lfx
wheel ships as a separate `dist-lfx-smoketest` artifact and is NOT
included in the publish-bundles step — only the `dist-bundles`
artifact gets pushed to PyPI.

* ci(nightly): re-pin bundle lfx deps to lfx-nightly during nightly build (#13208)

The nightly pipeline renames the workspace `lfx` package to `lfx-nightly`
in `src/lfx/pyproject.toml` and the root workspace dep, but leaves each
`src/bundles/*/pyproject.toml`'s `"lfx>=X.Y,<Z"` pin unchanged. With the
workspace `lfx` gone and PyPI still on lfx 0.4.3, the create-nightly-tag
job's `uv lock` fails:

  × No solution found when resolving dependencies for split [...]
  ╰─▶ Because only lfx<=0.4.3 is available and lfx-arxiv depends on
      lfx>=0.5.0,<0.6.0, we can conclude that lfx-arxiv's requirements
      are unsatisfiable.

`update_lfx_version.py` now also rewrites the `lfx` (or already-rewritten
`lfx-nightly`) specifier in every `src/bundles/*/pyproject.toml` to
`lfx-nightly==<dev version>`, mirroring how `update_lf_base_dependency`
re-pins the lfx dep inside `langflow-base`. The lookahead in the regex
prevents matching sibling packages like `lfx-arxiv` / `lfx-duckduckgo`.

No-op when no bundle pyprojects exist (e.g. on main today), so this is
safe to merge ahead of the bundle extraction landing on main. Restored
the guarded `git add src/bundles/*/pyproject.toml` step so the modified
bundle pyprojects ride the same commit/tag as the rest of the nightly
version bumps.

Cherry-pick to release-1.10.0 to unblock nightlies cut from that branch.
2026-05-19 10:12:54 -07:00
487a2402ba fix: Model handling for tool calling in agents and update IBM models (#13201)
fix: Model handling for tool calling in agents and update IBM models (#13191)

* Model handling for tool calling in agents and update IBM models

* [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-19 08:02:35 -07:00
2be85b167e feat: promote OpenRouter to a first-class unified model provider (#13185)
* feat: promote OpenRouter to a first-class unified model provider

Adds OpenRouter to the unified Model Providers system so users can
configure it once in Settings rather than per-flow. Reuses ChatOpenAI
with base_url=https://openrouter.ai/api/v1, supports a live model
catalog (fetched from /api/v1/models with the user's bearer key), and
forwards the optional HTTP-Referer / X-Title attribution headers when
the user provides a site URL or app name.

Validation is a cheap GET against /api/v1/models that raises
ValueError("Invalid OpenRouter API key") on a 401. The existing
flow-level OpenRouterComponent is left untouched for backward
compatibility.

Implements the opinionated direction proposed in #12839 (single
curated provider instead of a generic OpenAI-compatible field).

* Update Structured Data Analysis Agent.json

* [autofix.ci] apply automated fixes

* fix(openrouter): address review feedback

- Per-model tool_calling derived from OpenRouter's `supported_parameters`,
  not blanket-True. The Agent component calls
  `get_language_model_options(tool_calling=True)` so this fixes a real bug
  where non-tool-calling models (e.g. perceptron/perceptron-mk1) would have
  appeared in agent flows and failed at runtime.
- Default-model picks intersect with the curated seed list instead of
  taking the first 5 alphabetical ids (which were ai21/jamba-large-1.7,
  aion-labs/aion-1.0, etc.). Falls back to first MIN_DEFAULT_MODELS when
  the seed list shares nothing with the live catalog (stale-seed safety).
- Broadened the live-fetch except to include ValueError/TypeError (covers
  malformed JSON, non-list `data`, non-dict entries) and added defensive
  isinstance checks so a 200 with a bad payload degrades to `[]` instead
  of crashing on AttributeError.
- Bumped the live-fetch failure log from `debug` to `warning` with URL +
  status code, so an empty live catalog leaves a server-side breadcrumb.
- Wrapped the credentials probe in try/except → ValueError so a 5xx /
  timeout during `POST /validate-provider` surfaces as a user-facing 400
  via api/v1/variable.py (which only catches ValueError), not an
  unhandled 500.
- Tightened `os.environ.get(var["variable_key"])` (was
  `var.get("variable_key", "")` → `os.environ.get("")` masking misconfig).
- Documented `is_header` / `header_name` and the settings-only
  (no-`component_metadata`) pattern in the MODEL_PROVIDER_METADATA header
  comment.
- Updated seed slugs against the current OpenRouter catalog
  (anthropic/claude-3.7-sonnet was missing); curated list is now
  Claude Opus/Sonnet/Haiku 4.x + GPT-4o pair + Gemini 2.5 Pro + Llama 3.3.
- Added OPENROUTER_API_KEY / OPENROUTER_SITE_URL / OPENROUTER_APP_NAME to
  VARIABLES_TO_GET_FROM_ENVIRONMENT so users with env vars set see the
  provider as configured in Settings → Model Providers (parity with the
  other providers, and makes the "Falls back to env" copy honest).
- Tests: pinned `MIN_DEFAULT_MODELS` instead of magic 3; added cases for
  per-model tool_calling derivation, seed-intersection defaults,
  stale-seed fallback, httpx.HTTPStatusError, malformed payload, transient
  network → ValueError validation, env-var attribution headers, and env
  auto-import list. Replaced `patch.dict("sys.modules", ...)` with
  `patch.object(requests, "get", ...)` so the test stays correct if the
  lazy import is hoisted.

* Update Structured Data Analysis Agent.json

* feat(model-providers): search bar, models.dev metadata override, capability tags

Three follow-ups to the OpenRouter PR, requested by @ogabrielluiz in Slack:

1. **Search bars in the model providers modal.** ProviderList accepts a
   `query` prop and filters case-insensitively on the provider name; an
   `<Input icon="Search">` in ModelProvidersContent drives it. Inside the
   per-provider panel, ModelSelection grows its own search input that
   filters both LLM and embedding lists and resets when the selected
   provider changes (so OpenRouter → Anthropic doesn't carry stale text).
   Empty-state copy in both lanes; new i18n keys.

2. **models.dev metadata override (source of truth for covered providers).**
   New `lfx.base.models.models_dev_catalog` module:
     * `fetch_models_dev_snapshot()` — httpx GET against
       https://models.dev/api.json, returns None on transport / status /
       payload errors with a warning log.
     * `load_models_dev_snapshot()` / `save_models_dev_snapshot()` — disk
       cache at `<user_cache_dir>/langflow/models_dev/snapshot.json` with
       atomic temp-file write.
     * `apply_models_dev_overrides()` — translates each covered provider's
       models.dev entries into `ModelMetadata` (tool_call → tool_calling,
       reasoning passthrough, modalities.input has "image" → vision,
       limit.context → context_window, cost.input/output →
       cost_per_million_in/out). Providers not covered (IBM WatsonX, Azure
       OpenAI, Groq) pass through unchanged. Live-fetched providers
       (Ollama, IBM WatsonX, OpenRouter) keep their behavior because
       `replace_with_live_models` runs downstream at read time.
   `provider_queries.get_models_detailed()` now consults the in-memory
   snapshot via `get_active_snapshot()` and is `cache_clear()`-friendly so
   snapshot installs are picked up on the next call. The non-blocking
   refresh task in `get_lifespan` hydrates from disk first, then attempts a
   live fetch on a 24h interval; startup never blocks on models.dev.

3. **Capability tags next to the model name.** ModelRow renders small
   Badge pills (tool / reasoning / vision / embedding / search / preview)
   driven by metadata flags, in a stable left-to-right order, with the
   existing Deprecated badge kept at the end. The embedding tag only
   surfaces in the `all` view because the dedicated embeddings section
   header already conveys the same info.

Tests:
  - 14 new backend cases in `test_models_dev_catalog.py` (fetch / load /
    save / override / cache invalidation paths).
  - Search + capability-tag cases added to ProviderList and ModelSelection
    Jest suites (44 total, all green).
  - lfx tests/unit/base/models + tests/unit/inputs: 114 pass, no
    regressions.
  - ruff check clean on all touched files.

Out of scope: manual UI refresh button, surfacing pricing in the UI,
auto-adding providers from models.dev without a LangChain client.

* fix(openrouter): derive reasoning from supported_parameters

OpenRouter exposes "reasoning" in each model's supported_parameters array
exactly like it does "tools" (verified against /api/v1/models — Claude
Opus 4.x, o1/o3, DeepSeek R1 all carry it). The live fetcher was only
deriving tool_calling; reasoning was left at the create_model_metadata
default of False, so the new reasoning badge never lit up for OpenRouter
models even though the rest of the wiring was in place.

Now derives both flags from the same array. Test renamed to
…_derives_tool_calling_and_reasoning_per_model and pins all four
combinations (tools+reasoning, tools only, reasoning only, neither, plus
the missing-supported_parameters case).

* feat(model-providers): sort by recency, hide deprecated by default

OpenAI's list looked jumbled because the catalog rendered in raw
constants-file order — reasoning models interleaved with chat models,
deprecated and preview rows scattered throughout. Three changes:

1. **Thread `created` (Unix epoch) through ModelMetadata.** New optional
   field; populated by:
     - OpenRouter live fetch (existing `created` field on every model;
       defensive int-coercion handles bad payload values).
     - models.dev override (parses `release_date` YYYY-MM-DD → UTC
       midnight epoch; invalid / missing → 0).
   Static `*_constants.py` lists leave it at 0 → "unknown" tier.

2. **Sort each provider's group in `get_unified_models_detailed`.**
   Stable sort by `(is_deprecated, -created_epoch)`:
     - Non-deprecated dated rows: newest first.
     - Untimed rows (current static fallback): stable sort keeps their
       hand-curated constants-file order intact within the same tier.
     - Deprecated rows: bottom.
   The "first 5 = default" stamping now runs AFTER the sort so the
   highlighted defaults reflect the new ordering. For OpenAI's static
   list this changes nothing today (constants are already newest-first);
   once models.dev hydrates it picks up genuinely-recent dates from
   `release_date`.

3. **Collapse deprecated into a `<details>` disclosure.** Each section
   renders active rows normally, then a `Show N deprecated model(s)`
   summary that's closed by default. Resets on provider change. The rows
   stay in the DOM so existing flows referencing deprecated models still
   resolve; they're just out of the way.

`not_supported` is already filtered at the API layer (the modal doesn't
pass `includeUnsupported`), so those rows remain hidden as before.

Tests:
  - Backend: `created` propagation from `release_date` (+ malformed/empty
    cases), OpenRouter `created` passthrough (+ invalid-value
    degradation), and a full sort-order assertion covering
    [newest, mid, undated-a, undated-b, deprecated] ordering.
  - Frontend: deprecated disclosure default-closed, singular pluralization,
    no-disclosure-when-nothing-deprecated, reset on provider change via
    real user click → onToggle (the right pattern; the prior draft of
    this test mutated `details.open` directly and missed React's prop
    reconciliation).
  - 117 lfx tests + 48 frontend tests pass; ruff clean.

* [autofix.ci] apply automated fixes

* fix(models.dev override): preserve static deprecated flag + auto-deprecate dated snapshots

Two issues surfaced in the OpenAI/Anthropic screenshots:

1. **gpt-3.5-turbo wasn't in the deprecated disclosure** even though
   openai_constants.py has it flagged ``deprecated=True``. models.dev
   exposes no deprecated/lifecycle field (verified: only
   ``release_date`` and ``last_updated``), so the override threw away
   our static curation. ``apply_models_dev_overrides`` now builds a
   provider→{deprecated model names} lookup from the static lists and
   forwards the flag through ``_translate_model_entry`` for any name
   that matched a static deprecated row. ``gpt-4.5-preview`` and
   ``gpt-4-turbo-preview`` ride the same path.

2. **Anthropic dated-snapshot ids** (``claude-opus-4-5-20251101``,
   ``claude-haiku-4-5-20251001``, etc.) crowded the picker alongside
   their moving aliases. These are pinned-date snapshots of the
   alias — useful for production pins, noisy as defaults. Same
   pattern exists for OpenAI (``gpt-4o-2024-05-13``).
   ``_translate_model_entry`` now matches ``-YYYYMMDD$`` (Anthropic)
   and ``-YYYY-MM-DD$`` (OpenAI) and auto-flags those rows deprecated
   so they collapse into the disclosure tier rather than dominating
   the list. The 4-digit-only ``-0314``-style suffixes
   (``gpt-4-0314``, ``gpt-4-0613``) are deliberately *not* matched —
   those are pre-dated-naming snapshots that need static curation if
   we want to mark them.

Tests:
  - test_apply_overrides_marks_dated_snapshot_ids_deprecated pins:
      * alias rows stay active (claude-opus-4-5, gpt-4o)
      * Anthropic 8-digit and OpenAI hyphenated suffixes flip to
        deprecated
      * 4-digit-only suffixes don't false-positive
  - test_apply_overrides_preserves_static_deprecated_flag pins:
      * gpt-3.5-turbo / gpt-4.5-preview keep their static deprecation
      * a new model not in the static list (gpt-6) stays active

* fix(models.dev override): classify embeddings + age-based auto-deprecation

Two follow-ups from screenshot review on the OpenAI provider list.

**Bug 1 — embedding models showed in the Language Models section.**
models.dev mixes embeddings into a provider's ``models`` dict (e.g.
``text-embedding-3-large`` lives in the OpenAI block). The translator
was defaulting every entry to ``model_type="llm"``, so embeddings
polluted the LLM lane in the modal. The clean discriminator is the
``family`` field (``"text-embedding"`` for OpenAI's current embeddings,
verified for ada-002 / 3-small / 3-large); a name-substring check
("embedding") covers providers that fill ``family`` inconsistently.

**Bug 2 — old OpenAI models (gpt-4, gpt-4-turbo, text-embedding-ada-002)
stayed active even though they're functionally legacy.** models.dev has
no deprecation field, and OpenAI doesn't formally deprecate gpt-4 /
gpt-4-turbo in their catalog, but at ~924 days from release they're
clearly out of rotation. New ``_is_aged_out`` helper auto-deprecates
models older than ~30 months (900 days), preferring ``release_date``
over ``last_updated`` (the latter tracks catalog-curator edits like
typo fixes, not new model versions — gpt-4 has last_updated=2024-04
which would falsely keep it active).

Threshold tuned conservatively against today's catalog:
  - 1250d ada-002 → deprecated
  - 924d gpt-4, gpt-4-turbo → deprecated
  - 844d text-embedding-3-large/small → ACTIVE (still OpenAI's current
    embeddings; threshold deliberately above this point)
  - 735d gpt-4o → active
  - 261d Claude 4.x → active

``now`` is injected through ``_translate_model_entry`` and
``apply_models_dev_overrides`` for testability so the unit tests don't
depend on wall-clock time.

Tests:
  - test_apply_overrides_marks_embedding_family_as_embeddings_model_type
    pins ``family="text-embedding"`` → embeddings, generic LLMs stay
    llm, and a name-substring case (``voyage-3-embedding``) still
    classifies correctly when family is missing.
  - test_apply_overrides_auto_deprecates_stale_models pins both sides
    of the 900-day line and the no-date case (insufficient signal →
    stays active).

* fix(models.dev override): drop duplicate static groups + Google dated-preview + gemini-1.5

Three issues from screenshot review.

**1. Duplicate embedding rows in the OpenAI section.** The override
iterates ``static_lists`` and replaces the first OpenAI group
(``OPENAI_MODELS_DETAILED``, LLMs) with the combined override (which
holds both LLMs and embeddings from the single models.dev block). The
second OpenAI group (``OPENAI_EMBEDDING_MODELS_DETAILED``) then fell
through to the else branch and got appended unchanged, so every
embedding row rendered twice. Fix: when a provider's override has
already been applied, drop any subsequent static groups for the same
provider — they would only re-introduce duplicates.

**2. Google's dated-preview suffix wasn't auto-deprecated.** Each
vendor uses a different shape for snapshot ids:

| Vendor    | Shape                | Example                                   |
| --------- | -------------------- | ----------------------------------------- |
| Anthropic | ``-YYYYMMDD``        | ``claude-opus-4-5-20251101``              |
| OpenAI    | ``-YYYY-MM-DD``      | ``gpt-4o-2024-05-13``                     |
| Google    | ``-preview-MM-DD``   | ``gemini-2.5-pro-preview-05-06``          |
| Google    | ``-preview-MM-YYYY`` | ``gemini-2.5-flash-preview-09-2025``      |

``_DATED_SNAPSHOT_RE`` extended to match the Google variants. The
non-dated ``-preview-tts``-style suffix stays active (tts is a real
variant, not a snapshot).

**3. gemini-1.5-* stayed active despite being long out of rotation.**
At ~600-820 days these names sit under the 900-day age threshold, so
the heuristic alone wouldn't catch them. Added explicit
``deprecated=True`` entries for ``gemini-1.5-pro`` /
``gemini-1.5-flash`` / ``gemini-1.5-flash-8b`` to
``google_generative_ai_constants``; the override's static-deprecation
preservation flows them through.

Tests:
  - test_apply_overrides_drops_subsequent_static_groups_for_overridden_provider
    pins the no-duplicates invariant.
  - test_apply_overrides_marks_dated_snapshot_ids_deprecated grows to
    cover the Google preview-MM-DD / preview-MM-YYYY patterns and the
    non-dated -preview-tts negative case.
  - test_apply_overrides_preserves_gemini_1_5_static_deprecation pins
    that the static curation actually reaches the override output
    (and includes a sanity assert on the static list itself, so we
    don't drift the test off of the constants file by accident).

57 lfx model tests pass; ruff clean.

* [autofix.ci] apply automated fixes

* fix(ollama): stop 10s frontend poll + parallelize /api/show + cache

Closes #13137.

Two layered fixes for the runaway Ollama model fetch:

**Frontend — drop the 10-second refetchInterval.** The previous code
polled ``/api/v1/models`` every 10s as long as the Ollama provider card
was selected. Each backend call fanned out to ``GET /api/tags`` + ``POST
/api/show`` per model serially, so with many local models the request
overran the 10s interval and requests accumulated. The catalog already
refreshes on credential save / disconnect via
``invalidateProviderQueries`` and the backend cache (below) keeps a
on-demand window-focus refresh cheap; the timer was unnecessary.

**Backend — parallelize ``/api/show`` and cache.**

* ``get_ollama_models`` now fans out per-model capability probes via
  ``asyncio.gather``, so total latency is bounded by the slowest single
  request rather than ``N * avg``. Per-model failures are absorbed at
  debug-level — one broken model no longer poisons the whole catalog
  response.
* In-process TTL cache keyed by ``(base_url, capability)`` with a 30s
  window in front of the fan-out. Overlapping ``/api/v1/models``
  requests (which happen on every modal interaction, agent picker,
  embed picker, etc.) now share one upstream round-trip. Test-only
  ``_ollama_cache_clear`` helper for isolation.

Tests:
  - test_get_ollama_models_returns_only_matching_capability — capability
    filter still works.
  - test_get_ollama_models_runs_show_requests_in_parallel — pins
    parallelism via an asyncio.Event that would deadlock under serial.
  - test_get_ollama_models_tolerates_single_show_failure — one bad model
    doesn't drop the whole list.
  - test_get_ollama_models_caches_result_for_ttl_window — second call
    within the TTL hits the cache (zero upstream calls).
  - test_get_ollama_models_cache_keyed_by_base_url_and_capability —
    different base URLs and capability filters stay isolated.
  - test_get_ollama_models_refetches_after_ttl_expires — TTL expiry
    triggers a fresh fetch.

* Update Structured Data Analysis Agent.json

* [autofix.ci] apply automated fixes

* feat(model-input): declarative filters propagate to picker + sticky-default

Agent's Language Model dropdown was still showing tool-incompatible
models like ``gemini-3.1-flash-image-preview`` (``tool_call=false``
per models.dev). Root cause: the tool-calling constraint lived as a
hardcoded lambda at the Agent component's call site, but
``update_model_options_in_build_config``'s sticky-default
re-injection path didn't know about it — so a previously-saved
selection that no longer passed the filter got re-injected with
``not_enabled_locally=True`` and kept appearing in the picker.

Make the filter declarative so the helper, the cache key, and the
sticky-default path all read it from the same source.

* ``ModelInputMixin`` gains a ``filters: dict[str, Any] | None`` field.
  Any keys/values forward to ``get_unified_models_detailed`` and are
  matched against each model's metadata. Example: the Agent declares
  ``ModelInput(name="model", filters={"tool_calling": True})``
  instead of passing a lambda at the call site.

* ``get_language_model_options`` accepts ``filters: dict | None``;
  the legacy ``tool_calling`` kwarg is preserved and merged into the
  filter dict for backward compatibility.

* ``handle_model_input_update`` reads ``filters`` from the
  build_config and, when no explicit ``get_options_func`` is supplied,
  builds one that applies them. The options-cache key prefix is
  namespaced by sorted filter pairs so different constraint sets
  don't share cached options.

* The sticky-default block in ``update_model_options_in_build_config``
  validates the saved selection against the same filters dict via
  ``_saved_model_passes_filters``. When the saved row doesn't satisfy
  every constraint, the row is dropped and the value cleared so the
  downstream auto-default picks a compatible model. Conservative
  fallback: an unknown model (not in the catalog) still passes the
  filter so today's "inject and let the user configure" UX is
  unchanged for genuinely-unknown selections.

* Agent component: drop the inline lambda in ``update_build_config``;
  the filter now lives on the ModelInput declaration.

* Replaces the ``cache_key_prefix`` sniff for tool-calling intent —
  prefix is now derived from filters, not pattern-matched.

Tests cover the helpers, both sticky-default branches (drop vs
inject), and the conservative fallback for unknown saved models.

* [autofix.ci] apply automated fixes

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

* fix(google): tool_calling=False on image-output Gemini models

Even after the declarative filters={"tool_calling": True} shipped on
the Agent component's ModelInput, the picker still showed
gemini-3.1-flash-image-preview and friends. Root cause: the static
google_generative_ai_constants.py catalog defaulted every Gemini
model to tool_calling=True. Image-generation models can't actually
run with tools (verified in models.dev — these rows have
tool_call: false and modalities.output includes image), so the
static-only fallback (before the models.dev refresh hydrates) was
wrong upstream of the filter and leaked them through.

Four image-output models flipped to tool_calling=False in the static
catalog:
  * gemini-2.5-flash-image
  * gemini-2.0-flash-preview-image-generation
  * gemini-3-pro-image-preview
  * gemini-3.1-flash-image-preview

Models.dev's correct flag still wins via the override path once the
snapshot hydrates; this fix matters most for cold starts and
air-gapped deployments where only the bundled static lists are in
play.

Tests (test_static_catalog_tool_calling.py):
  - Parametrized over the four known image models; each must declare
    tool_calling=False in the static catalog (and remain listed — we
    need the static curation so the override preserves the flag by
    name match).
  - Heuristic regression guard: any Google model with "image" in its
    name that defaults to tool_calling=True will fail this test.
    Future image variants are caught before they reach the picker;
    legitimate exceptions opt in via an allowlist literal in the test.

* [autofix.ci] apply automated fixes

* fix(model-input): source filters from class declaration, not round-tripped build_config

The Agent picker was STILL showing gemini-3.1-flash-image-preview even
after the static catalog flag flip and the declarative filters work.
Reproduced and traced to a saved-flow round-trip: flows persisted
before the filters field shipped don't carry it in their stored
template. The frontend POSTs that stale template back, my helper read
build_config["model"]["filters"] (None), and the filter path
short-circuited to the unfiltered branch.

Fix: source filters from the ModelInput's class-level declaration
(canonical, always current with the server build), falling back to
build_config only when the component happens to expose no inputs
attribute. The build_config is also patched in place when the
declaration overrides it, so the next round-trip carries the active
filter back to the frontend.

* New helper ``_filters_from_component_inputs`` walks the component's
  inputs list and returns the matching ModelInput's filters dict (with
  None values dropped, same hygiene as the build_config path).
* New ``_resolve_filters`` orchestrates: class declaration > build_config,
  with an in-place write back to build_config when the class wins.
* Both call sites in ``handle_model_input_update`` and
  ``update_model_options_in_build_config`` now call ``_resolve_filters``;
  the old direct call to ``_filters_from_build_config`` is gone from the
  hot paths (kept exported because it's still useful as a defensive
  fallback when no component is available).

Tests (4 new in test_build_config_sticky_default.py):
  - _filters_from_component_inputs reads class declaration / returns
    empty when no matching input.
  - _resolve_filters prefers class over build_config and patches
    build_config in place.
  - _resolve_filters falls back to build_config when component has no
    inputs attribute (defensive fallback for non-standard callers).

* fix(frontend): honor ModelInput.filters in dropdown augment loop

The Agent picker kept showing tool-incompatible models like
gemini-3.1-flash-image-preview even after every backend filter and
static-catalog fix landed. Root cause was on the frontend, in the
ModelInputComponent's groupedOptions memo:

  - The first loop iterates over the backend-supplied options (which
    are filtered).
  - The augment loop then iterates over every enabled model in
    useGetModelProviders × useGetEnabledModels — both of which
    are filter-unaware — and pushes the union into the dropdown.

So even though the backend correctly excluded
gemini-3.1-flash-image-preview from options, the augment loop happily
re-added it because providersData listed it and enabledModelsData
flagged it as enabled.

Fix: read filters off nodeClass.template.model.filters (the same
declaration that drives the backend filter) and apply the same metadata
match to every option that flows through groupedOptions. Two
checkpoints:

  1. Defensive pass in the existing-options loop. The backend should
     have filtered already, but stale saved flows could surface a
     build_config that hasn't been corrected yet — same self-healing
     story as the backend _resolve_filters helper.
  2. New pass in the augment loop, after the model_type check.
     Every enabled-model candidate must satisfy the filter or it's
     skipped.

Conservative behavior matches the backend: when a filter key (e.g.
tool_calling) is declared but the candidate's metadata doesn't
carry that key at all, the candidate fails the check — better drop an
undeclared row than surface one that crashes at run time.

Tests (4 new): hides tool-incompatible augmented models, drops
saved options that fail the filter, conservative drop on missing
metadata key (with a known-good sibling so the assertion isn't
paper-thin), no-op when no filters are declared. Suite-local
beforeEach restores the default hook mocks since jest.clearAllMocks
only resets call history, not implementations.

* Fix tests

* Update .secrets.baseline

* Fix starter projects

* Update .secrets.baseline

* [autofix.ci] apply automated fixes

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

* Update component_index.json

* Update Structured Data Analysis Agent.json

* [autofix.ci] apply automated fixes

* fix frontend tests

* fix remaining CI errors

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-05-18 21:39:06 -07:00
c901602bc2 fix(ci): rename bundles to -nightly during nightly build (#13193)
fix: rename bundles for nightly build
2026-05-18 18:32:44 -07:00
23f2edf327 chore: Clean up the startup warnings for Python 3.14 (#13156)
* fix: backport policies ToolGuard lazy imports (#13144)

fix: backport policies toolguard lazy imports

* chore: Clean up the startup warnings for Python 3.14

* Update base.py

* Update component_index.json

* [autofix.ci] apply automated fixes

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

* Update component_index.json

* [autofix.ci] apply automated fixes

* Update Structured Data Analysis Agent.json

* [autofix.ci] apply automated fixes

* Update component_index.json

* [autofix.ci] apply automated fixes

* Update component_index.json

* Update starter projects

* Update .secrets.baseline

* [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-18 16:52:13 -07:00
d1da768192 feat(knowledge): merge ingestion + retrieval into mode-driven Knowledge component (#13120)
* feat(knowledge): merge ingestion + retrieval into mode-driven Knowledge component

Merge KnowledgeIngestionComponent and KnowledgeBaseComponent into a single
KnowledgeComponent driven by a TabInput mode selector ("Ingest" / "Retrieve"),
mirroring the PoliciesComponent pattern.

- New: src/lfx/src/lfx/components/files_and_knowledge/knowledge.py holds the
  full merged component. update_build_config and update_outputs hide the
  inputs and the output that do not apply to the current mode.
- Legacy KnowledgeIngestionComponent / KnowledgeBaseComponent become thin
  subclasses pinned to their respective modes with class-level inputs and
  outputs aligned to the legacy shape, so saved flows continue to load.
- Output names ("dataframe_output", "retrieve_data") preserved for back-compat.
- New tests cover mode-switch input/output visibility and subclass pinning;
  existing test_ingestion / test_retrieval suites rerouted to patch the new
  knowledge module path and continue to pass.

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

* chore(knowledge): drop emoji from mode labels, mark legacy subclasses

- Mode tab labels: "📥 Ingest" / "🔍 Retrieve" → "Ingest" / "Retrieve" so the
  selector blends with the rest of Langflow's TabInput palette (see MemoryComponent
  for the same convention).
- Set `legacy = True` on KnowledgeIngestionComponent and KnowledgeBaseComponent
  so the back-compat shims stay loadable by saved flows but no longer clutter
  the new-component palette — users should reach for the merged Knowledge
  component instead.

* [autofix.ci] apply automated fixes

* fix(knowledge): declare both outputs at class level so retrieve mode dispatches correctly

Saved flows in retrieve mode were hitting
``'NoneType' object has no attribute 'to_dataframe'`` because the merged
``KnowledgeComponent`` only declared ``dataframe_output`` (build_kb_info)
at the class level. The runtime resolves outputs from the class-level
``outputs`` list at __init__ time, so ``retrieve_data`` was never in
``_outputs_map``; the runtime fell back to ``build_kb_info``, which ran
``convert_to_dataframe(self.input_df)`` against a hidden, None-valued
input.

Fix: declare both outputs at the class level (TypeConverterComponent +
MemoryComponent already use this pattern). ``update_outputs`` keeps
filtering the canvas-visible output by mode, but the runtime can now
dispatch to either method based on which one the saved flow has wired up.
Also wire ``update_frontend_node`` to re-run the mode-driven output
filter on canvas load so saved flows render the correct output even
before the user clicks the tab.

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

* fix(knowledge): dispatch by mode in output methods to survive stale edges and legacy labels

Two failure modes were still triggering the
``'NoneType' object has no attribute 'to_dataframe'`` crash even with both
outputs declared at the class level:

1. User drops the Knowledge component (default INGEST), wires the
   ``dataframe_output`` edge, then switches to Retrieve. The saved edge
   still points at ``build_kb_info``; the runtime calls it against a
   None ``input_df`` and crashes inside ``convert_to_dataframe``.
2. Flows saved with the original emoji mode labels ("📥 Ingest" /
   "🔍 Retrieve") carry those strings on disk. The post-emoji-removal
   equality checks (``mode == MODE_RETRIEVE``) failed, so even though
   the user was conceptually in retrieve mode, the component fell
   through the ingest path.

Both methods now check the mode at entry and delegate to the other one
when the wired output doesn't match. Mode matching is lenient
(substring-based) so the legacy emoji labels still resolve.

``update_build_config`` and ``update_outputs`` also normalize legacy
labels onto the current canonical values so visibility toggles correctly
for flows pulled from old saves.

* [autofix.ci] apply automated fixes

* feat(knowledge): point legacy shims at the merged component and migrate starters

- Add ``replacement = ["files_and_knowledge.Knowledge"]`` to both
  ``KnowledgeIngestionComponent`` and ``KnowledgeBaseComponent`` so the
  canvas legacy-component banner offers the merged component as the
  one-click upgrade target.
- Rewrite the ``KnowledgeBase`` nodes in the two starter projects that
  shipped them (``Knowledge Retrieval`` and ``Vector Store RAG``) to use
  the new ``Knowledge`` component with mode pre-set to ``Retrieve``. All
  edges are re-pointed at the new node id, the embedded module path is
  updated to ``lfx.components.files_and_knowledge.knowledge.KnowledgeComponent``,
  and the mode value is normalised away from the old emoji label.

* [autofix.ci] apply automated fixes

* Update knowledge.py

* 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)

* Update component_index.json

* [autofix.ci] apply automated fixes

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

* Update src/lfx/src/lfx/components/files_and_knowledge/knowledge.py

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

* [autofix.ci] apply automated fixes

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

* fix: Restore knowledge creation functionality

* Template update

* Update component_index.json

* 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)

* fix: Linting errors

* Update knowledge.py

* [autofix.ci] apply automated fixes

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

* [autofix.ci] apply automated fixes

* fix: Address @rafaelgiln comments

* Update test_knowledge.py

* Update component_index.json

* Template updates

* Update .secrets.baseline

* [autofix.ci] apply automated fixes

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

* Update Structured Data Analysis Agent.json

* Update component_index.json

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* Fix edge connection with parser

* Update Structured Data Analysis Agent.json

---------

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>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-05-18 20:05:01 +00:00
cc009c9133 feat(lfx): Bundle Separation and LFX Extension Framework (#13043)
* feat(lfx): installed-package + seed-directory discovery for production install (LE-1022)

Adds the read-only production install path for Modes A, B, and C of the
Bundle Separation iteration. Manifest-shipping pip-installed
distributions and seed-directory subdirectories are discovered at server
startup and registered as Extensions at @official.

* discovery.py: walks importlib.metadata.distributions() + the
  $LANGFLOW_SEED_DIR / /opt/langflow/bundles seed root; produces
  DiscoveredExtension records and typed errors for malformed manifests
  / configured-but-missing seed dirs.
* registry.py: ExtensionRegistry service with the immutability
  invariant for installed and seed entries. Mutation verbs (uninstall,
  disable, enable, install, update_entry) all raise
  ExtensionImmutableError carrying the typed
  installed-extension-immutable / seed-directory-immutable code so the
  invariant is testable today; the CLI uninstall surface ships in B4.
* lfx extension list: read-only inspector with text and JSON output
  for operators inspecting Mode B/C images.
* Errors: four new typed codes
  (installed-extension-immutable, seed-directory-immutable,
  seed-directory-not-found, duplicate-extension-id) plus snapshot
  coverage in tests/unit/extension/test_errors.py.
* Tests: 165 extension tests pass, including the LE-1022 acceptance
  cases -- three pip-installed wheels visible at @official, three seed
  bundles visible at @official, and the parametrized service-layer
  immutability check across every mutation verb.
* Docs: docs/Deployment/deployment-extensions-production.mdx covers
  the Dockerfile template, k8s deployment notes, the bundle packaging
  convention (extension.json shipped via package-data), and
  troubleshooting for the typed error codes.

* feat(lfx): add single-Bundle loader and LANGFLOW_COMPONENTS_PATH discovery (#12967)

* feat(lfx): add extension manifest schema, validate CLI, and error formatter (LE-1014)

Foundation for the Bundle Separation iteration. Defines what a valid
extension.json looks like (Pydantic models + Draft 2020-12 JSON Schema),
ships the offline `lfx extension validate` command, and ships the single
`format_extension_error` function that every other extension-system module
will use to render structured errors.

What's in lfx.extension:

- `ExtensionManifest` / `BundleRef` / `LangflowCompat` Pydantic models with
  `extra="forbid"` so unknown fields fail loudly. Deferred fields (`services`,
  `routes`, `hooks`, `starter_projects`, `userConfig`) are reserved as
  None-only so non-null values produce a dedicated
  `field-deferred-in-this-milestone` error instead of a generic schema wall.
  `bundles` accepts a list but rejects length > 1 with
  `multi-bundle-deferred-in-this-milestone` (validator-enforced; the loader
  re-checks at install time in LE-1015).
- `schema.build_schema()` + `build_schema_json()` produce the publishable
  artifact at schemas.langflow.org/extension/v1.json.
- `ExtensionError` typed envelope and `format_extension_error` -- one branch
  per discriminant. Codes are registered in `ERROR_CODES`; an
  `ExtensionError` constructed with an unknown code raises at construction
  time, preventing producers from shipping without a matching renderer.
- `validate_extension` runs four passes: manifest discovery + schema,
  path-safety (no `..`, no absolute paths, no symlink escape), AST
  inspection of every `.py` (syntax, Component subclass present, build()
  declared, top-level `import *`, top-level I/O primitives), and an opt-in
  `--execute-imports` that runs each module in a subprocess with a
  temporary HOME / TMPDIR / LANGFLOW_CONFIG_DIR and LANGFLOW_*/LFX_* env
  vars stripped.
- `lfx extension validate` and `lfx extension schema` typer subcommands.

Acceptance-criteria coverage in tests/unit/extension/:

- Round-trips every v0 manifest field; deferred fields rejected; multi-bundle
  rejected with the dedicated discriminant.
- JSON Schema validates the v0 example and rejects 12 malformed manifests
  with distinct error paths (>= 10 required by the ticket).
- Median default-validate runtime < 100ms on the basic template.
- Crafted side-effect bundle: default validate does NOT execute it (canary
  file is never written); `--execute-imports` DOES execute it and the canary
  appears, while LANGFLOW_* env vars are NOT inherited by the subprocess.
- Snapshot tests for every code in ERROR_CODES; a guard test verifies
  ERROR_CODES and the snapshot table are in lockstep so future additions
  cannot ship without a format branch and a snapshot.

Wiring: `lfx extension` is a sub-app under the Authoring help panel so
future tickets (LE-1016 init/dev, LE-1018 reload) can attach without
colliding with the existing `lfx validate` (which validates flow JSON, not
extensions).

* fix(lfx): fall back to tomli on Python 3.10 in extension manifest loader

tomllib is stdlib only on 3.11+, but lfx supports 3.10-3.13. Use the
existing tomli runtime dependency as the 3.10 fallback (same API, so the
import alias keeps the rest of the module unchanged).

Fixes ModuleNotFoundError seen in CI on the 3.10 job.

* Update src/lfx/tests/unit/extension/test_schema.py

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

* Update src/lfx/src/lfx/extension/schema.py

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

* Update src/lfx/src/lfx/cli/_extension_commands.py

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

* feat(lfx): add single-Bundle loader and LANGFLOW_COMPONENTS_PATH discovery (LE-1015)

Introduces lfx.extension.loader: the runtime that turns an Extension on disk
into LoadedComponent records keyed by ext:<bundle>:<Class>@<slot>. Two paths in:

  - load_extension(root): one manifest, one Bundle, registered at @official.
    Re-checks multi-bundle at runtime (defense-in-depth vs. the schema).
  - discover_inline_bundles(paths): each subfolder of LANGFLOW_COMPONENTS_PATH
    is a Bundle at @extra. Walk order is platform-independent (sorted dirs,
    user-declared path order). First-wins on duplicate names; second emits
    duplicate-inline-bundle warning that names both paths.

Manifest-first precedence helpers (installed_extension_roots,
manifest_owning_distributions, filter_plugin_entry_points) let callers of
the legacy langflow.plugins entry-point loader skip distributions that ship
a manifest, so component entry-points are not double-registered.

New typed error codes: module-import-failed, duplicate-component-name,
duplicate-distribution, duplicate-inline-bundle, inline-bundle-name-invalid.
Each ships with a format branch and a snapshot test.

Tests cover the AC: single-bundle happy path, multi-bundle rejection,
missing/empty/no-Component bundle, duplicate class names, deterministic
walk order, recursive discovery, inline-bundle first-wins + dot-dir skip
+ bundle.json metadata, manifest-first precedence partition, PEP-503
distribution-name canonicalization.

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

* fix(lfx): address LE-1015 review feedback

- Drop the unproduced duplicate-distribution error code; LE-1022 will add
  it once startup-time discovery has a place to surface it.  Restores the
  invariant that every code in ERROR_CODES has a producer.
- Clarify that intra-bundle relative imports are NOT supported in v0; only
  absolute references between bundle modules work in this milestone.
- Use strict=False when re-resolving bundle_root in the walker; the path
  was already existence-checked, and a concurrent removal in the narrow
  window should not raise across the loader's public boundary.
- Hoist the json import out of _read_inline_bundle_json's body.

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

* refactor(lfx): split extension loader into a small subpackage (LE-1015)

Addresses the file-size feedback from the LE-1015 review.  The single
870-line loader.py becomes a flat package keyed off the four section
banners that already existed inline:

    loader/
      __init__.py     # re-exports the public surface
      _types.py       # SLOT constants, LoadedComponent, LoadResult
      _discovery.py   # filesystem walk + importlib.util orchestration
      _detection.py   # Component subclass identification (MRO heuristic)
      _orchestrator.py # load_extension, discover_inline_bundles
      _plugins.py     # manifest-first precedence over langflow.plugins

Largest file is now _orchestrator.py at 440 LOC (was 870); every file is
well under the 800-LOC project guideline.  No behavior change: the public
import paths from lfx.extension are unchanged, all 38 loader tests still
pass.  ``_canonicalize_distribution`` is now exported as
``canonicalize_distribution`` from ``loader._plugins`` (it's a stable
PEP-503 helper that downstream modules will reach for, so it loses the
private underscore).

The test suite is split to mirror the package:

    tests/unit/extension/loader/
      conftest.py             # shared fixtures, FakeDist, autouse scrub
      test_load_extension.py  # @official slot, identity, failure modes
      test_inline_bundles.py  # LANGFLOW_COMPONENTS_PATH, @extra slot
      test_plugins.py         # manifest-first precedence helpers
      test_types.py           # LoadedComponent, LoadResult, code parity

Each test file imports its own slice of the public API and pulls fixtures
from conftest, so a reader looking at one banner can read it in isolation.

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

* fix: LangflowCompat -> LfxCompat

* fix: Remove references to ticket

* fix: encode maxItems constraint in schema

* fix: deferred fields and schema version

* Fix ruff errors

* fix: align loader tests with renamed manifest API and strip ticket refs

The merge of feat/extension-validate brought in the LfxCompat / compat
rename, but the loader test fixtures still used LangflowCompat / bundle_api
and failed at the manifest layer. Update conftest.py + test_load_extension.py
to the post-rename API.

Strip 17 LE-XXXX ticket references from loader source files, errors.py
loader-specific comments, and the four loader test docstrings, matching the
convention applied to LE-1014. Descriptive prose preserved.

Promote _BUNDLE_NAME_RE to BUNDLE_NAME_RE on the manifest module so the
loader's orchestrator no longer reaches across modules into a private name.

* refactor(lfx): clarify broad except, log malformed bundle.json, expand test docstring

- Document why _discovery.import_bundle_module catches BaseException (startup-time loader, must surface bad bundles as typed errors rather than abort).
- Add debug-level logging when bundle.json is malformed or non-object so a stale-cache footgun is at least observable.
- Expand test_skips_re_imported_class docstring so future maintainers don't accidentally weaken the __module__-equality guard if package-style relative imports get added later.

Also drops the stale duplicate-distribution claim from the PR description; that code is correctly deferred to LE-1022 along with /all integration.

* feat(lfx): wire Extension System into /all, pathsep-split LANGFLOW_COMPONENTS_PATH, emit duplicate-distribution

Closes the four AC gaps the previous reviewer flagged on PR #12967:

1. /all integration: get_and_cache_all_types_dict now also calls a new
   import_extension_components() that loads installed Extensions via
   load_installed_extensions, loads inline bundles via discover_inline_bundles,
   and builds frontend-node templates with extension/bundle/extension_version
   fields stamped on. Failures are logged and skipped per bundle.

2. LANGFLOW_COMPONENTS_PATH is now split on os.pathsep so multi-entry env vars
   (e.g. /a:/b on POSIX) produce multiple components-path entries instead of
   one literal non-existent path. Empty segments and missing paths are skipped.

3. duplicate-distribution is a real producer: load_installed_extensions
   surfaces a typed warning on the winner LoadResult when two distributions
   share a canonical name, naming every involved manifest path.

4. Manifest-first precedence runtime wiring: new filter_component_entry_points
   loads each entry-point and only skips ones that resolve to a Component
   subclass on a manifest-shipping distribution. plugin_routes.load_plugin_routes
   now applies it so non-component entry-points (route registrars) keep
   loading per the AC's 'unaffected' promise. Added the previously-missing
   AC test for same-distribution component+non-component partition.

Also makes _distribution_canonical_name defensive against MagicMock test seams.

* fix(lfx): register extension components under namespaced ID; promote duplicate-distribution to error

Addresses the latest review of PR #12967:

P1: /all integration now keys the cache inner dict by LoadedComponent.namespaced_id
(ext:<bundle>:<Class>@<slot>) rather than the bare class name. Templates also carry
the namespaced_id as an explicit field so consumers that look at the value (not the
key) still see the canonical address. This is the form the LE-1020 migration table
will rewrite legacy class-name references to.

P2: load_installed_extensions now appends duplicate-distribution to result.errors
instead of result.warnings, so LoadResult.ok=False when two distributions share a
canonical name. The winner's components still appear in result.components so flows
already pinned to them keep working; only the conflict status changes. Updated test
to assert errors + ok=False; added explicit assertion that the winner's components
are still present.

* fix(lfx): installed-distribution discovery accepts pyproject.toml manifest form

Closes the latest review finding on PR #12967: the installed-distribution
scan only looked for extension.json, ignoring distributions whose manifest
lives in [tool.langflow.extension] inside pyproject.toml. The AC explicitly
treats both as valid manifest forms.

_distribution_manifest_path now:
- Returns extension.json immediately when present (preserves precedence
  matching load_manifest's discovery order).
- Falls back to pyproject.toml only when extension.json is absent AND the
  pyproject's [tool.langflow.extension] section is parseable.

Validation reuses load_manifest itself so the rule lives in exactly one
place; a stray pyproject.toml without the section is correctly ignored.

Tests cover: pyproject-only discovery, pyproject-without-section ignored,
extension.json wins on collision, end-to-end pyproject load at @official,
and pyproject-form manifest-first entry-point suppression.

* refactor(lfx): tighten loader invariants, surface silent skips, harden tests

Addresses the latest review feedback on PR #12967:

Type-level invariants (_types.py):
- LoadedComponent.__post_init__ enforces that @extra components must NOT
  carry a distribution. The reverse (@official without distribution) is
  permitted because load_extension is also used for dev-mode loads
  against a working tree before pip install.
- LoadResult docstring documents the partial-success contract: components
  may be non-empty when errors is non-empty (some files imported, others
  failed). Callers branching on ok get strict success.

Silent-failure fixes (_orchestrator.py + settings/base.py):
- inline-path-missing: a non-existent / non-dir LANGFLOW_COMPONENTS_PATH
  entry now produces a typed warning per skipped path so a typo no
  longer yields zero diagnostics. Settings-layer skip bumped from debug
  to warning for the same reason.
- bundle-json-invalid: a malformed or non-object bundle.json now surfaces
  a typed warning instead of silently rewriting the user-declared
  id/version to derived values under the same bundle name.
- no-component-subclass gating uses a call-local counter instead of
  result.errors so the diagnostic stays accurate when a future caller
  reuses a LoadResult (multi-bundle / batch wrapper scenarios).

Test hardening:
- test_re_imported_class_is_skipped_via_module_filter rewritten to
  actually exercise the __module__-equality check via sys.modules
  injection; previously passed via module-import-failed (relative-import
  failure), which would silently weaken if package registration changes.
- test_user_declared_path_order_is_preserved: AC #8's multi-path order
  case (distinct bundles in [path_b, path_a]) was unasserted; added.
- test_inline_module_import_failure_attributes_identity: AC #10's
  identity-on-partial-failure was covered for @official but not @extra;
  added.
- test_uses_real_distributions_by_default tightened to assert ep
  placement (in kept, not in skipped) instead of exact-list equality, so
  a future Langflow-shipped manifest doesn't silently flip the assertion.

bumped 64 -> 175 passing extension tests; 20 backend integration tests
still pass.

* fix(lfx): malformed pyproject manifests surface manifest-invalid instead of disappearing

Closes the latest review finding on PR #12967: a pyproject.toml with a
[tool.langflow.extension] section that has missing/invalid required
fields was silently dropped because _pyproject_has_extension_section
ran full schema validation via load_manifest and returned False on
ValueError/TypeError. That conflated 'no section' with 'section
malformed'.

Fix: detect section presence only. _pyproject_has_extension_section now
calls _read_pyproject_extension (TOML parse + key lookup, no schema
check). Behavior:
- Section absent or pyproject TOML unparseable -> False (treat as
  regular non-manifest package).
- Section present and is a table (valid OR schema-invalid) -> True.
- Section present but is not a table -> True; the author intended to
  declare an extension and load_extension will surface the typed error.

This way a typo'd pyproject Extension produces a typed manifest-invalid
LoadResult with extension_id attribution, and manifest-first precedence
still suppresses its legacy component entry-points -- matching the
'typed load results on success/failure' contract for the supported
pyproject manifest form.

Tests: two new cases pin the behavior. test_malformed_pyproject_section_
surfaces_manifest_invalid asserts a typed load-failure result with
distribution attribution; the second test pins manifest-first
suppression for malformed pyproject distributions.

* refactor(lfx): emit inline-path-unreadable, document reload contract, trim rot

Closes the remaining nits on PR #12967:

- inline-path-unreadable (new typed error code): a configured
  LANGFLOW_COMPONENTS_PATH entry that raises OSError on iterdir
  (typically permission-denied) now produces a typed LoadResult error
  carrying str(exc) instead of silently swallowing the message.
- duplicate-inline-bundle hint trimmed: removed forward promise about
  hard-error-in-a-later-release; same actionability, no expiration.
- discover_inline_bundles docstring trimmed from three paragraphs to
  two sentences (per CLAUDE.md anti-multi-paragraph rule).
- _distribution_manifest_path docstring trimmed to one-liner.
- installed_extension_roots dropped Used-by caller-narration list;
  manifest_owning_distributions docstring rewritten to call out the
  shadow-load risk for direct callers and point to load_installed_
  extensions for the typed warning surface.
- _discovery.import_bundle_module: replaced 'until that lands in a
  later milestone' rot with a single line ('Absolute imports only
  between bundle modules; relative imports unsupported.') AND added
  the single-load-per-process contract note documenting why LE-1018
  reload must scrub registry/sys.modules before re-invoking the loader.
- load_extension docstring grew a 'Single-load-per-process contract'
  block telling direct callers not to rely on this function for refresh.

Tests: new test_unreadable_path_emits_inline_path_unreadable pins the
OSError -> typed-error path.

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(lfx): atomic-swap Bundle reload pipeline + endpoint + CLI (LE-1018) (#12979)

* feat(lfx): add single-Bundle loader and LANGFLOW_COMPONENTS_PATH discovery (LE-1015)

Introduces lfx.extension.loader: the runtime that turns an Extension on disk
into LoadedComponent records keyed by ext:<bundle>:<Class>@<slot>. Two paths in:

  - load_extension(root): one manifest, one Bundle, registered at @official.
    Re-checks multi-bundle at runtime (defense-in-depth vs. the schema).
  - discover_inline_bundles(paths): each subfolder of LANGFLOW_COMPONENTS_PATH
    is a Bundle at @extra. Walk order is platform-independent (sorted dirs,
    user-declared path order). First-wins on duplicate names; second emits
    duplicate-inline-bundle warning that names both paths.

Manifest-first precedence helpers (installed_extension_roots,
manifest_owning_distributions, filter_plugin_entry_points) let callers of
the legacy langflow.plugins entry-point loader skip distributions that ship
a manifest, so component entry-points are not double-registered.

New typed error codes: module-import-failed, duplicate-component-name,
duplicate-distribution, duplicate-inline-bundle, inline-bundle-name-invalid.
Each ships with a format branch and a snapshot test.

Tests cover the AC: single-bundle happy path, multi-bundle rejection,
missing/empty/no-Component bundle, duplicate class names, deterministic
walk order, recursive discovery, inline-bundle first-wins + dot-dir skip
+ bundle.json metadata, manifest-first precedence partition, PEP-503
distribution-name canonicalization.

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

* fix(lfx): address LE-1015 review feedback

- Drop the unproduced duplicate-distribution error code; LE-1022 will add
  it once startup-time discovery has a place to surface it.  Restores the
  invariant that every code in ERROR_CODES has a producer.
- Clarify that intra-bundle relative imports are NOT supported in v0; only
  absolute references between bundle modules work in this milestone.
- Use strict=False when re-resolving bundle_root in the walker; the path
  was already existence-checked, and a concurrent removal in the narrow
  window should not raise across the loader's public boundary.
- Hoist the json import out of _read_inline_bundle_json's body.

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

* refactor(lfx): split extension loader into a small subpackage (LE-1015)

Addresses the file-size feedback from the LE-1015 review.  The single
870-line loader.py becomes a flat package keyed off the four section
banners that already existed inline:

    loader/
      __init__.py     # re-exports the public surface
      _types.py       # SLOT constants, LoadedComponent, LoadResult
      _discovery.py   # filesystem walk + importlib.util orchestration
      _detection.py   # Component subclass identification (MRO heuristic)
      _orchestrator.py # load_extension, discover_inline_bundles
      _plugins.py     # manifest-first precedence over langflow.plugins

Largest file is now _orchestrator.py at 440 LOC (was 870); every file is
well under the 800-LOC project guideline.  No behavior change: the public
import paths from lfx.extension are unchanged, all 38 loader tests still
pass.  ``_canonicalize_distribution`` is now exported as
``canonicalize_distribution`` from ``loader._plugins`` (it's a stable
PEP-503 helper that downstream modules will reach for, so it loses the
private underscore).

The test suite is split to mirror the package:

    tests/unit/extension/loader/
      conftest.py             # shared fixtures, FakeDist, autouse scrub
      test_load_extension.py  # @official slot, identity, failure modes
      test_inline_bundles.py  # LANGFLOW_COMPONENTS_PATH, @extra slot
      test_plugins.py         # manifest-first precedence helpers
      test_types.py           # LoadedComponent, LoadResult, code parity

Each test file imports its own slice of the public API and pulls fixtures
from conftest, so a reader looking at one banner can read it in isolation.

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

* feat(lfx): atomic-swap Bundle reload pipeline + endpoint + CLI (LE-1018)

Five-stage reload (parallel staging load -> validate -> swap under write
lock -> cleanup -> emit) for installed Bundles in Mode A.  In-flight
flows keep the pre-swap class via existing references; new flows pick up
the post-swap class atomically; concurrent reloads on the same Bundle
are rejected with reload-in-progress.

Adds:

* lfx/extension/registry.py -- BundleRegistry with per-bundle
  reload-in-progress guard and components_index.json writer
* lfx/extension/reload.py -- the five-stage pipeline; events emission
  is stubbed (TODO LE-1017) so the swap mechanics can ship before the
  events service lands
* loader: optional module_namespace param so Stage 1 lands in
  __reload_staging__.<id> instead of the live _lfx_ext.* namespace
* errors: four new typed reload codes (reload-in-progress,
  reload-bundle-not-installed, reload-bundle-name-mismatch,
  reload-source-missing) with branch templates and snapshot tests
* HTTP: POST /api/v1/extensions/{id}/bundles/{name}/reload, gated by
  the existing get_current_active_user dependency, returns 409 with a
  typed body for the in-progress collision case
* CLI: lfx extension reload <id> [--bundle <name>] -- HTTP client
  against the dev server with text/json output and proper exit codes
  (--all is gated until LE-1019 lands the list endpoint)
* tests: 16 reload-pipeline tests covering the AC matrix (rename
  round-trip, broken-bundle isolation, concurrent readers, in-flight
  flow, double-reload guard, bundle-name mismatch) plus 9 CLI client
  tests

Mode A only.  In Mode B/C bundle changes require a Docker image rebuild
and the reload path is not exercised.

The events emission in Stage 5 is intentionally stubbed -- the LE-1017
ticket will swap the body of _emit_bundle_reload_event in one place
without touching the pipeline core.

---------

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

* [autofix.ci] apply automated fixes

* feat(lfx): add `extension init` and `extension dev` CLIs (LE-1016) (#12968)

* feat(lfx): add extension manifest schema, validate CLI, and error formatter (LE-1014)

Foundation for the Bundle Separation iteration. Defines what a valid
extension.json looks like (Pydantic models + Draft 2020-12 JSON Schema),
ships the offline `lfx extension validate` command, and ships the single
`format_extension_error` function that every other extension-system module
will use to render structured errors.

What's in lfx.extension:

- `ExtensionManifest` / `BundleRef` / `LangflowCompat` Pydantic models with
  `extra="forbid"` so unknown fields fail loudly. Deferred fields (`services`,
  `routes`, `hooks`, `starter_projects`, `userConfig`) are reserved as
  None-only so non-null values produce a dedicated
  `field-deferred-in-this-milestone` error instead of a generic schema wall.
  `bundles` accepts a list but rejects length > 1 with
  `multi-bundle-deferred-in-this-milestone` (validator-enforced; the loader
  re-checks at install time in LE-1015).
- `schema.build_schema()` + `build_schema_json()` produce the publishable
  artifact at schemas.langflow.org/extension/v1.json.
- `ExtensionError` typed envelope and `format_extension_error` -- one branch
  per discriminant. Codes are registered in `ERROR_CODES`; an
  `ExtensionError` constructed with an unknown code raises at construction
  time, preventing producers from shipping without a matching renderer.
- `validate_extension` runs four passes: manifest discovery + schema,
  path-safety (no `..`, no absolute paths, no symlink escape), AST
  inspection of every `.py` (syntax, Component subclass present, build()
  declared, top-level `import *`, top-level I/O primitives), and an opt-in
  `--execute-imports` that runs each module in a subprocess with a
  temporary HOME / TMPDIR / LANGFLOW_CONFIG_DIR and LANGFLOW_*/LFX_* env
  vars stripped.
- `lfx extension validate` and `lfx extension schema` typer subcommands.

Acceptance-criteria coverage in tests/unit/extension/:

- Round-trips every v0 manifest field; deferred fields rejected; multi-bundle
  rejected with the dedicated discriminant.
- JSON Schema validates the v0 example and rejects 12 malformed manifests
  with distinct error paths (>= 10 required by the ticket).
- Median default-validate runtime < 100ms on the basic template.
- Crafted side-effect bundle: default validate does NOT execute it (canary
  file is never written); `--execute-imports` DOES execute it and the canary
  appears, while LANGFLOW_* env vars are NOT inherited by the subprocess.
- Snapshot tests for every code in ERROR_CODES; a guard test verifies
  ERROR_CODES and the snapshot table are in lockstep so future additions
  cannot ship without a format branch and a snapshot.

Wiring: `lfx extension` is a sub-app under the Authoring help panel so
future tickets (LE-1016 init/dev, LE-1018 reload) can attach without
colliding with the existing `lfx validate` (which validates flow JSON, not
extensions).

* fix(lfx): fall back to tomli on Python 3.10 in extension manifest loader

tomllib is stdlib only on 3.11+, but lfx supports 3.10-3.13. Use the
existing tomli runtime dependency as the 3.10 fallback (same API, so the
import alias keeps the rest of the module unchanged).

Fixes ModuleNotFoundError seen in CI on the 3.10 job.

* Update src/lfx/tests/unit/extension/test_schema.py

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

* Update src/lfx/src/lfx/extension/schema.py

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

* Update src/lfx/src/lfx/cli/_extension_commands.py

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

* feat(lfx): add single-Bundle loader and LANGFLOW_COMPONENTS_PATH discovery (LE-1015)

Introduces lfx.extension.loader: the runtime that turns an Extension on disk
into LoadedComponent records keyed by ext:<bundle>:<Class>@<slot>. Two paths in:

  - load_extension(root): one manifest, one Bundle, registered at @official.
    Re-checks multi-bundle at runtime (defense-in-depth vs. the schema).
  - discover_inline_bundles(paths): each subfolder of LANGFLOW_COMPONENTS_PATH
    is a Bundle at @extra. Walk order is platform-independent (sorted dirs,
    user-declared path order). First-wins on duplicate names; second emits
    duplicate-inline-bundle warning that names both paths.

Manifest-first precedence helpers (installed_extension_roots,
manifest_owning_distributions, filter_plugin_entry_points) let callers of
the legacy langflow.plugins entry-point loader skip distributions that ship
a manifest, so component entry-points are not double-registered.

New typed error codes: module-import-failed, duplicate-component-name,
duplicate-distribution, duplicate-inline-bundle, inline-bundle-name-invalid.
Each ships with a format branch and a snapshot test.

Tests cover the AC: single-bundle happy path, multi-bundle rejection,
missing/empty/no-Component bundle, duplicate class names, deterministic
walk order, recursive discovery, inline-bundle first-wins + dot-dir skip
+ bundle.json metadata, manifest-first precedence partition, PEP-503
distribution-name canonicalization.

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

* fix(lfx): address LE-1015 review feedback

- Drop the unproduced duplicate-distribution error code; LE-1022 will add
  it once startup-time discovery has a place to surface it.  Restores the
  invariant that every code in ERROR_CODES has a producer.
- Clarify that intra-bundle relative imports are NOT supported in v0; only
  absolute references between bundle modules work in this milestone.
- Use strict=False when re-resolving bundle_root in the walker; the path
  was already existence-checked, and a concurrent removal in the narrow
  window should not raise across the loader's public boundary.
- Hoist the json import out of _read_inline_bundle_json's body.

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

* refactor(lfx): split extension loader into a small subpackage (LE-1015)

Addresses the file-size feedback from the LE-1015 review.  The single
870-line loader.py becomes a flat package keyed off the four section
banners that already existed inline:

    loader/
      __init__.py     # re-exports the public surface
      _types.py       # SLOT constants, LoadedComponent, LoadResult
      _discovery.py   # filesystem walk + importlib.util orchestration
      _detection.py   # Component subclass identification (MRO heuristic)
      _orchestrator.py # load_extension, discover_inline_bundles
      _plugins.py     # manifest-first precedence over langflow.plugins

Largest file is now _orchestrator.py at 440 LOC (was 870); every file is
well under the 800-LOC project guideline.  No behavior change: the public
import paths from lfx.extension are unchanged, all 38 loader tests still
pass.  ``_canonicalize_distribution`` is now exported as
``canonicalize_distribution`` from ``loader._plugins`` (it's a stable
PEP-503 helper that downstream modules will reach for, so it loses the
private underscore).

The test suite is split to mirror the package:

    tests/unit/extension/loader/
      conftest.py             # shared fixtures, FakeDist, autouse scrub
      test_load_extension.py  # @official slot, identity, failure modes
      test_inline_bundles.py  # LANGFLOW_COMPONENTS_PATH, @extra slot
      test_plugins.py         # manifest-first precedence helpers
      test_types.py           # LoadedComponent, LoadResult, code parity

Each test file imports its own slice of the public API and pulls fixtures
from conftest, so a reader looking at one banner can read it in isolation.

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

* feat(lfx): add `extension init` and `extension dev` CLIs (LE-1016)

The two scaffolding CLIs an Extension author types:

  - `lfx extension init <target>` writes the basic single-Bundle
    template (manifest with $schema, README, .gitignore, one Component
    subclass + a pytest smoke test).  AC #1: the generated extension
    validates clean against LE-1014.  AC #2: the generated test file is
    a valid pytest module that exercises the component's build() method.
    AC #3: any --template other than 'basic' fails with a typed
    template-deferred-in-this-milestone error and a non-zero exit.
    Refuses to scaffold over a non-empty target dir.

  - `lfx extension dev <target>` validates the local extension, records
    its absolute path in <config_dir>/extensions/dev_extensions.json,
    prints reload instructions, and execs `langflow run` (or
    `python -m langflow` when langflow isn't on PATH).  --skip-launch
    registers without launching (used by tests + external dev-server
    scripts); --skip-validate lets authors register a known-broken
    manifest to debug it under the loader.

Stack:
  - Wave 0: error codes (extension-target-exists,
    extension-target-invalid, local-extension-missing) with format
    branches and snapshot tests.
  - Wave 1: lfx.extension.init_template -- pure-data scaffolder, no
    Typer dependency so the CLI is a thin shell over it.
  - Wave 1: lfx.extension.dev_registry -- atomic JSON state file under
    the langflow user-cache dir; helpers for register / list /
    unregister / load_dev_extensions / dev_extension_component_paths.
  - Wave 2: lfx.cli._extension_commands gains init/dev subcommands.
  - Wave 2: langflow.main lifespan hook reads the dev registry after
    bundle loading and extends components_path with each registered
    bundle dir, so the existing palette discovery picks up dev
    extensions.  Missing paths surface as local-extension-missing
    warnings (AC #5) without aborting startup.

Tests (84 new, 197 total in tests/unit/extension/):
  - test_init_template.py: AC scenarios + identifier derivation +
    deterministic file shape.
  - test_dev_registry.py: register/list/unregister round-trip,
    idempotent re-register refreshes timestamp, malformed state file
    treated as empty, missing-path warning, recovery when path
    reappears, env-var override precedence.
  - test_cli.py: AC #1 init->validate, AC #3 deferred templates,
    --skip-launch registers without launching, --skip-validate
    short-circuits the pre-flight pass.
  - test_errors.py: snapshot rows for all three new codes; the
    every-known-code-has-a-snapshot test enforces parity.

LE-1018 (reload) reuses load_dev_extensions; LE-1022 (installed-pkg
discovery) shares the components_path extension pattern.  AC #4 ("boots
Langflow with the extension visible in the palette within 5s") is
delivered jointly by `extension dev` (registers + execs) and the
lifespan hook (loads on startup).

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

* fix(lfx): address LE-1016 review feedback

Fixes the four HIGH issues + the elevated LOW from the review pass:

1. dev_extension_component_paths now forwards EVERY warning, not just
   local-extension-missing.  Previously a duplicate-component-name (or
   any future warning code) was silently dropped, hiding real signal
   from the lifespan hook's logs.

2. Defensive emit when a LoadResult has components but source_path is
   None.  The current loader always sets source_path, but a future
   hand-built LoadResult could violate that contract; we now surface a
   typed local-extension-missing error rather than dropping the
   extension silently.

3. Replaced the fragile ``min(len(parts))`` bundle-root selection with
   a relative-to-source-path measurement.  Handles deep-vs-shallow
   sibling extensions correctly without depending on absolute path
   depth.

4. Generated README now documents the langflow/lfx prerequisite under
   the Develop section so authors know `pytest` requires the lfx
   environment, not just Python.

5. Forced LANGFLOW_LAZY_LOAD_COMPONENTS=false unconditionally in the
   `extension dev` exec env (was setdefault, which let a developer's
   global lazy-loading export silently hide their dev components from
   the palette and miss AC #4's 5s budget).

Plus three MEDIUMs:

  - sys.modules cleanup in test_generated_test_file_runs_against_generated_component
    so a later test importing the same dotted path doesn't pick up a
    stale module from a deleted tmp_path.  Component instantiation
    moved inside the try block because Component.__init__ uses
    inspect.getsourcefile against self.__class__'s still-live module.
  - Added regex-drift test that pins the init_template patterns to
    match manifest.py's so a schema regex change can't quietly produce
    invalid scaffolded manifests.
  - Added two new dev_registry tests covering the forward-all-warnings
    contract and the source_path=None defense.

Tests: 201 passing (4 new); ruff check + format clean.

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

* fix: LangflowCompat -> LfxCompat

* fix: Remove references to ticket

* fix: encode maxItems constraint in schema

* fix: deferred fields and schema version

* Fix ruff errors

* fix: align loader tests with renamed manifest API and strip ticket refs

The merge of feat/extension-validate brought in the LfxCompat / compat
rename, but the loader test fixtures still used LangflowCompat / bundle_api
and failed at the manifest layer. Update conftest.py + test_load_extension.py
to the post-rename API.

Strip 17 LE-XXXX ticket references from loader source files, errors.py
loader-specific comments, and the four loader test docstrings, matching the
convention applied to LE-1014. Descriptive prose preserved.

Promote _BUNDLE_NAME_RE to BUNDLE_NAME_RE on the manifest module so the
loader's orchestrator no longer reaches across modules into a private name.

* fix(lfx): align init template with renamed manifest API

After merging feat/extension-loader into this branch, two surfaces
fell out of sync with the renamed manifest schema:

- init_template generates extension.json with `lfx: {bundle_api: [1]}`,
  but the validator now requires `lfx: {compat: ["1"]}` per LfxCompat.
  This made `test_basic_template_validates_clean` fail with
  manifest-invalid (`lfx.compat: Field required; lfx.bundle_api: Extra
  inputs are not permitted`).
- test_init_template_regexes_match_manifest_schema reads
  `manifest_mod._BUNDLE_NAME_RE`, but that symbol was promoted to public
  `BUNDLE_NAME_RE` in c63f84a591. Update the test to reference the
  public name; init_template's local copy is still private since it
  also covers `_EXTENSION_ID_RE`, which remains private upstream.

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(lfx): append-only migration table + flow deserializer rewrite hook (#13024)

* feat(lfx): add extension manifest schema, validate CLI, and error formatter (LE-1014)

Foundation for the Bundle Separation iteration. Defines what a valid
extension.json looks like (Pydantic models + Draft 2020-12 JSON Schema),
ships the offline `lfx extension validate` command, and ships the single
`format_extension_error` function that every other extension-system module
will use to render structured errors.

What's in lfx.extension:

- `ExtensionManifest` / `BundleRef` / `LangflowCompat` Pydantic models with
  `extra="forbid"` so unknown fields fail loudly. Deferred fields (`services`,
  `routes`, `hooks`, `starter_projects`, `userConfig`) are reserved as
  None-only so non-null values produce a dedicated
  `field-deferred-in-this-milestone` error instead of a generic schema wall.
  `bundles` accepts a list but rejects length > 1 with
  `multi-bundle-deferred-in-this-milestone` (validator-enforced; the loader
  re-checks at install time in LE-1015).
- `schema.build_schema()` + `build_schema_json()` produce the publishable
  artifact at schemas.langflow.org/extension/v1.json.
- `ExtensionError` typed envelope and `format_extension_error` -- one branch
  per discriminant. Codes are registered in `ERROR_CODES`; an
  `ExtensionError` constructed with an unknown code raises at construction
  time, preventing producers from shipping without a matching renderer.
- `validate_extension` runs four passes: manifest discovery + schema,
  path-safety (no `..`, no absolute paths, no symlink escape), AST
  inspection of every `.py` (syntax, Component subclass present, build()
  declared, top-level `import *`, top-level I/O primitives), and an opt-in
  `--execute-imports` that runs each module in a subprocess with a
  temporary HOME / TMPDIR / LANGFLOW_CONFIG_DIR and LANGFLOW_*/LFX_* env
  vars stripped.
- `lfx extension validate` and `lfx extension schema` typer subcommands.

Acceptance-criteria coverage in tests/unit/extension/:

- Round-trips every v0 manifest field; deferred fields rejected; multi-bundle
  rejected with the dedicated discriminant.
- JSON Schema validates the v0 example and rejects 12 malformed manifests
  with distinct error paths (>= 10 required by the ticket).
- Median default-validate runtime < 100ms on the basic template.
- Crafted side-effect bundle: default validate does NOT execute it (canary
  file is never written); `--execute-imports` DOES execute it and the canary
  appears, while LANGFLOW_* env vars are NOT inherited by the subprocess.
- Snapshot tests for every code in ERROR_CODES; a guard test verifies
  ERROR_CODES and the snapshot table are in lockstep so future additions
  cannot ship without a format branch and a snapshot.

Wiring: `lfx extension` is a sub-app under the Authoring help panel so
future tickets (LE-1016 init/dev, LE-1018 reload) can attach without
colliding with the existing `lfx validate` (which validates flow JSON, not
extensions).

* fix(lfx): fall back to tomli on Python 3.10 in extension manifest loader

tomllib is stdlib only on 3.11+, but lfx supports 3.10-3.13. Use the
existing tomli runtime dependency as the 3.10 fallback (same API, so the
import alias keeps the rest of the module unchanged).

Fixes ModuleNotFoundError seen in CI on the 3.10 job.

* Update src/lfx/tests/unit/extension/test_schema.py

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

* Update src/lfx/src/lfx/extension/schema.py

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

* Update src/lfx/src/lfx/cli/_extension_commands.py

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

* feat(lfx): add single-Bundle loader and LANGFLOW_COMPONENTS_PATH discovery (LE-1015)

Introduces lfx.extension.loader: the runtime that turns an Extension on disk
into LoadedComponent records keyed by ext:<bundle>:<Class>@<slot>. Two paths in:

  - load_extension(root): one manifest, one Bundle, registered at @official.
    Re-checks multi-bundle at runtime (defense-in-depth vs. the schema).
  - discover_inline_bundles(paths): each subfolder of LANGFLOW_COMPONENTS_PATH
    is a Bundle at @extra. Walk order is platform-independent (sorted dirs,
    user-declared path order). First-wins on duplicate names; second emits
    duplicate-inline-bundle warning that names both paths.

Manifest-first precedence helpers (installed_extension_roots,
manifest_owning_distributions, filter_plugin_entry_points) let callers of
the legacy langflow.plugins entry-point loader skip distributions that ship
a manifest, so component entry-points are not double-registered.

New typed error codes: module-import-failed, duplicate-component-name,
duplicate-distribution, duplicate-inline-bundle, inline-bundle-name-invalid.
Each ships with a format branch and a snapshot test.

Tests cover the AC: single-bundle happy path, multi-bundle rejection,
missing/empty/no-Component bundle, duplicate class names, deterministic
walk order, recursive discovery, inline-bundle first-wins + dot-dir skip
+ bundle.json metadata, manifest-first precedence partition, PEP-503
distribution-name canonicalization.

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

* fix(lfx): address LE-1015 review feedback

- Drop the unproduced duplicate-distribution error code; LE-1022 will add
  it once startup-time discovery has a place to surface it.  Restores the
  invariant that every code in ERROR_CODES has a producer.
- Clarify that intra-bundle relative imports are NOT supported in v0; only
  absolute references between bundle modules work in this milestone.
- Use strict=False when re-resolving bundle_root in the walker; the path
  was already existence-checked, and a concurrent removal in the narrow
  window should not raise across the loader's public boundary.
- Hoist the json import out of _read_inline_bundle_json's body.

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

* refactor(lfx): split extension loader into a small subpackage (LE-1015)

Addresses the file-size feedback from the LE-1015 review.  The single
870-line loader.py becomes a flat package keyed off the four section
banners that already existed inline:

    loader/
      __init__.py     # re-exports the public surface
      _types.py       # SLOT constants, LoadedComponent, LoadResult
      _discovery.py   # filesystem walk + importlib.util orchestration
      _detection.py   # Component subclass identification (MRO heuristic)
      _orchestrator.py # load_extension, discover_inline_bundles
      _plugins.py     # manifest-first precedence over langflow.plugins

Largest file is now _orchestrator.py at 440 LOC (was 870); every file is
well under the 800-LOC project guideline.  No behavior change: the public
import paths from lfx.extension are unchanged, all 38 loader tests still
pass.  ``_canonicalize_distribution`` is now exported as
``canonicalize_distribution`` from ``loader._plugins`` (it's a stable
PEP-503 helper that downstream modules will reach for, so it loses the
private underscore).

The test suite is split to mirror the package:

    tests/unit/extension/loader/
      conftest.py             # shared fixtures, FakeDist, autouse scrub
      test_load_extension.py  # @official slot, identity, failure modes
      test_inline_bundles.py  # LANGFLOW_COMPONENTS_PATH, @extra slot
      test_plugins.py         # manifest-first precedence helpers
      test_types.py           # LoadedComponent, LoadResult, code parity

Each test file imports its own slice of the public API and pulls fixtures
from conftest, so a reader looking at one banner can read it in isolation.

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

* fix: LangflowCompat -> LfxCompat

* fix: Remove references to ticket

* fix: encode maxItems constraint in schema

* fix: deferred fields and schema version

* Fix ruff errors

* fix: align loader tests with renamed manifest API and strip ticket refs

The merge of feat/extension-validate brought in the LfxCompat / compat
rename, but the loader test fixtures still used LangflowCompat / bundle_api
and failed at the manifest layer. Update conftest.py + test_load_extension.py
to the post-rename API.

Strip 17 LE-XXXX ticket references from loader source files, errors.py
loader-specific comments, and the four loader test docstrings, matching the
convention applied to LE-1014. Descriptive prose preserved.

Promote _BUNDLE_NAME_RE to BUNDLE_NAME_RE on the manifest module so the
loader's orchestrator no longer reaches across modules into a private name.

* feat(lfx): append-only migration table + flow deserializer rewrite hook

Adds the migration layer of the Extension System: an append-only JSON table
that maps three legacy component reference shapes (bare class name, old
import path, pre-Phase-A namespaced slot) to the post-Phase-A canonical
ext:<bundle>:<Class>@<slot> identifier, plus a deserializer hook that
rewrites a saved-flow payload in place against that table on load.

What landed:

  * lfx.extension.migration.schema -- Pydantic models for MigrationEntry +
    MigrationTable with per-entry validators (exactly one of bare/import/slot
    populated; canonical target shape) and table-level uniqueness check.
  * lfx.extension.migration.loader -- canonical in-repo path, threadsafe
    process-lifetime cache, typed errors on every failure mode.
  * lfx.extension.migration.rewrite -- node-by-node rewrite, idempotent on
    canonical refs, difflib-backed closest-match suggestion for unmapped
    references, cross-bucket ambiguity surfaces component-name-ambiguous
    instead of silently loading into the wrong bundle.
  * Wired into Graph.from_payload before validate_flow_for_current_settings
    so every saved-flow load goes through migration first.
  * scripts/migrate/check_migration_append_only.py -- CI guard that diffs
    the working-tree table against origin/main and rejects removals or
    target mutations; reordering and additions are allowed.
  * 34 new unit tests covering rewrite paths, loader failure modes, schema
    invariants, and the CI script behavior.

What is deliberately deferred:

  * flow-migrated event emission. The events pipeline is unavailable in this
    iteration; the wiring point in Graph.from_payload is marked TODO and the
    MigrationReport already carries every field a future emitter needs.

The shipped migration_table.json starts empty; entries land alongside the
pilot bundle extraction in a follow-up.

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

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(frontend): palette Bundle reload action + loading + toasts (#13025)

* feat(lfx): add extension manifest schema, validate CLI, and error formatter (LE-1014)

Foundation for the Bundle Separation iteration. Defines what a valid
extension.json looks like (Pydantic models + Draft 2020-12 JSON Schema),
ships the offline `lfx extension validate` command, and ships the single
`format_extension_error` function that every other extension-system module
will use to render structured errors.

What's in lfx.extension:

- `ExtensionManifest` / `BundleRef` / `LangflowCompat` Pydantic models with
  `extra="forbid"` so unknown fields fail loudly. Deferred fields (`services`,
  `routes`, `hooks`, `starter_projects`, `userConfig`) are reserved as
  None-only so non-null values produce a dedicated
  `field-deferred-in-this-milestone` error instead of a generic schema wall.
  `bundles` accepts a list but rejects length > 1 with
  `multi-bundle-deferred-in-this-milestone` (validator-enforced; the loader
  re-checks at install time in LE-1015).
- `schema.build_schema()` + `build_schema_json()` produce the publishable
  artifact at schemas.langflow.org/extension/v1.json.
- `ExtensionError` typed envelope and `format_extension_error` -- one branch
  per discriminant. Codes are registered in `ERROR_CODES`; an
  `ExtensionError` constructed with an unknown code raises at construction
  time, preventing producers from shipping without a matching renderer.
- `validate_extension` runs four passes: manifest discovery + schema,
  path-safety (no `..`, no absolute paths, no symlink escape), AST
  inspection of every `.py` (syntax, Component subclass present, build()
  declared, top-level `import *`, top-level I/O primitives), and an opt-in
  `--execute-imports` that runs each module in a subprocess with a
  temporary HOME / TMPDIR / LANGFLOW_CONFIG_DIR and LANGFLOW_*/LFX_* env
  vars stripped.
- `lfx extension validate` and `lfx extension schema` typer subcommands.

Acceptance-criteria coverage in tests/unit/extension/:

- Round-trips every v0 manifest field; deferred fields rejected; multi-bundle
  rejected with the dedicated discriminant.
- JSON Schema validates the v0 example and rejects 12 malformed manifests
  with distinct error paths (>= 10 required by the ticket).
- Median default-validate runtime < 100ms on the basic template.
- Crafted side-effect bundle: default validate does NOT execute it (canary
  file is never written); `--execute-imports` DOES execute it and the canary
  appears, while LANGFLOW_* env vars are NOT inherited by the subprocess.
- Snapshot tests for every code in ERROR_CODES; a guard test verifies
  ERROR_CODES and the snapshot table are in lockstep so future additions
  cannot ship without a format branch and a snapshot.

Wiring: `lfx extension` is a sub-app under the Authoring help panel so
future tickets (LE-1016 init/dev, LE-1018 reload) can attach without
colliding with the existing `lfx validate` (which validates flow JSON, not
extensions).

* fix(lfx): fall back to tomli on Python 3.10 in extension manifest loader

tomllib is stdlib only on 3.11+, but lfx supports 3.10-3.13. Use the
existing tomli runtime dependency as the 3.10 fallback (same API, so the
import alias keeps the rest of the module unchanged).

Fixes ModuleNotFoundError seen in CI on the 3.10 job.

* Update src/lfx/tests/unit/extension/test_schema.py

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

* Update src/lfx/src/lfx/extension/schema.py

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

* Update src/lfx/src/lfx/cli/_extension_commands.py

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

* feat(lfx): add single-Bundle loader and LANGFLOW_COMPONENTS_PATH discovery (LE-1015)

Introduces lfx.extension.loader: the runtime that turns an Extension on disk
into LoadedComponent records keyed by ext:<bundle>:<Class>@<slot>. Two paths in:

  - load_extension(root): one manifest, one Bundle, registered at @official.
    Re-checks multi-bundle at runtime (defense-in-depth vs. the schema).
  - discover_inline_bundles(paths): each subfolder of LANGFLOW_COMPONENTS_PATH
    is a Bundle at @extra. Walk order is platform-independent (sorted dirs,
    user-declared path order). First-wins on duplicate names; second emits
    duplicate-inline-bundle warning that names both paths.

Manifest-first precedence helpers (installed_extension_roots,
manifest_owning_distributions, filter_plugin_entry_points) let callers of
the legacy langflow.plugins entry-point loader skip distributions that ship
a manifest, so component entry-points are not double-registered.

New typed error codes: module-import-failed, duplicate-component-name,
duplicate-distribution, duplicate-inline-bundle, inline-bundle-name-invalid.
Each ships with a format branch and a snapshot test.

Tests cover the AC: single-bundle happy path, multi-bundle rejection,
missing/empty/no-Component bundle, duplicate class names, deterministic
walk order, recursive discovery, inline-bundle first-wins + dot-dir skip
+ bundle.json metadata, manifest-first precedence partition, PEP-503
distribution-name canonicalization.

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

* fix(lfx): address LE-1015 review feedback

- Drop the unproduced duplicate-distribution error code; LE-1022 will add
  it once startup-time discovery has a place to surface it.  Restores the
  invariant that every code in ERROR_CODES has a producer.
- Clarify that intra-bundle relative imports are NOT supported in v0; only
  absolute references between bundle modules work in this milestone.
- Use strict=False when re-resolving bundle_root in the walker; the path
  was already existence-checked, and a concurrent removal in the narrow
  window should not raise across the loader's public boundary.
- Hoist the json import out of _read_inline_bundle_json's body.

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

* refactor(lfx): split extension loader into a small subpackage (LE-1015)

Addresses the file-size feedback from the LE-1015 review.  The single
870-line loader.py becomes a flat package keyed off the four section
banners that already existed inline:

    loader/
      __init__.py     # re-exports the public surface
      _types.py       # SLOT constants, LoadedComponent, LoadResult
      _discovery.py   # filesystem walk + importlib.util orchestration
      _detection.py   # Component subclass identification (MRO heuristic)
      _orchestrator.py # load_extension, discover_inline_bundles
      _plugins.py     # manifest-first precedence over langflow.plugins

Largest file is now _orchestrator.py at 440 LOC (was 870); every file is
well under the 800-LOC project guideline.  No behavior change: the public
import paths from lfx.extension are unchanged, all 38 loader tests still
pass.  ``_canonicalize_distribution`` is now exported as
``canonicalize_distribution`` from ``loader._plugins`` (it's a stable
PEP-503 helper that downstream modules will reach for, so it loses the
private underscore).

The test suite is split to mirror the package:

    tests/unit/extension/loader/
      conftest.py             # shared fixtures, FakeDist, autouse scrub
      test_load_extension.py  # @official slot, identity, failure modes
      test_inline_bundles.py  # LANGFLOW_COMPONENTS_PATH, @extra slot
      test_plugins.py         # manifest-first precedence helpers
      test_types.py           # LoadedComponent, LoadResult, code parity

Each test file imports its own slice of the public API and pulls fixtures
from conftest, so a reader looking at one banner can read it in isolation.

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

* feat(lfx): atomic-swap Bundle reload pipeline + endpoint + CLI (LE-1018)

Five-stage reload (parallel staging load -> validate -> swap under write
lock -> cleanup -> emit) for installed Bundles in Mode A.  In-flight
flows keep the pre-swap class via existing references; new flows pick up
the post-swap class atomically; concurrent reloads on the same Bundle
are rejected with reload-in-progress.

Adds:

* lfx/extension/registry.py -- BundleRegistry with per-bundle
  reload-in-progress guard and components_index.json writer
* lfx/extension/reload.py -- the five-stage pipeline; events emission
  is stubbed (TODO LE-1017) so the swap mechanics can ship before the
  events service lands
* loader: optional module_namespace param so Stage 1 lands in
  __reload_staging__.<id> instead of the live _lfx_ext.* namespace
* errors: four new typed reload codes (reload-in-progress,
  reload-bundle-not-installed, reload-bundle-name-mismatch,
  reload-source-missing) with branch templates and snapshot tests
* HTTP: POST /api/v1/extensions/{id}/bundles/{name}/reload, gated by
  the existing get_current_active_user dependency, returns 409 with a
  typed body for the in-progress collision case
* CLI: lfx extension reload <id> [--bundle <name>] -- HTTP client
  against the dev server with text/json output and proper exit codes
  (--all is gated until LE-1019 lands the list endpoint)
* tests: 16 reload-pipeline tests covering the AC matrix (rename
  round-trip, broken-bundle isolation, concurrent readers, in-flight
  flow, double-reload guard, bundle-name mismatch) plus 9 CLI client
  tests

Mode A only.  In Mode B/C bundle changes require a Docker image rebuild
and the reload path is not exercised.

The events emission in Stage 5 is intentionally stubbed -- the LE-1017
ticket will swap the body of _emit_bundle_reload_event in one place
without touching the pipeline core.

* feat(frontend): palette Bundle reload action + loading + toasts

Adds the frontend half of the bundle reload flow.  When the Bundle
header is right-clicked or its overflow ("⋮") icon clicked, a Reload
action fires POST /api/v1/extensions/{id}/bundles/{name}/reload and
surfaces the result via the existing alert-store toast system.

What landed (frontend only):

  * src/controllers/API/queries/extensions/ -- typed wire-format models
    (ReloadBundleResponse, ExtensionErrorPayload, ReloadInProgressDetail)
    and the useReloadBundle mutation hook.  The hook unwraps the 409
    `reload-in-progress` detail into a stable, parseable Error message so
    the UI can branch without reading status codes.
  * components/bundleHeaderActions.tsx -- new Select-based overflow menu
    next to the Bundle header chevron.  Three toast paths: success
    (green, with components +/- delta), structural failure (red, with
    typed errors and inline hints), reload-in-progress (notice).
    Loading state swaps the kebab icon for a spinning Loader2 while
    the request is in flight.  Renders nothing when no extension_id is
    on the bundle, so the static SIDEBAR_BUNDLES list is unaffected.
  * components/bundleItems.tsx -- wires the new actions in next to the
    chevron, plus a context-menu (right-click) capture that opens the
    same overflow trigger so keyboard / mouse / right-click all share
    one source of truth.
  * types/index.ts -- BundleItemProps.item gains an optional
    extension_id; took the opportunity to extract the SidebarBundle
    interface and tighten three pre-existing `any` types.
  * customization/feature-flags.ts -- ENABLE_EXTENSION_RELOAD gate, off
    by default until the bundle-list endpoint that populates extension_id
    per bundle ships.
  * controllers/API/helpers/constants.ts -- EXTENSIONS URL constant.
  * Tests: 7 component tests + 3 mutation-hook tests, all green.  Total
    sidebar + extensions test count: 479 passing.

Deferred:

  * Event-pipeline subscription is left as an inline TODO.  The mutation
    response carries enough information to drive the toasts on its own
    today; once the events service lands the toast wiring will move to
    a `bundle_reloaded` / `bundle_reload_failed` listener so multi-tab
    and multi-worker swaps surface exactly once.

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

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat: End to end bundle installation

* fix: Review comments addressed

* Update component_index.json

* Update component_index.json

* Update router.py

* fix(docker): copy src/bundles before uv sync so workspace bundles resolve

Each directory under ``src/bundles`` is a uv workspace member referenced by
``langflow-base`` (and the root project) as a path dependency.  The Docker
builders ran ``uv sync --no-install-project`` after copying only the
top-level pyproject.toml files, so resolution failed with
``Distribution not found at: file:///app/src/bundles/<name>``.

Copying the whole ``src/bundles`` tree (rather than enumerating each
bundle) means a new bundle dropped under that dir does not require a
Dockerfile edit.  The full ``./src`` copy a few lines later produces the
same final layer either way; this earlier copy just unblocks the
dependency-resolution sync.

Touched all builders that run a workspace-resolving uv sync:

  * docker/build_and_push.Dockerfile
  * docker/build_and_push_base.Dockerfile
  * docker/build_and_push_ep.Dockerfile
  * docker/build_and_push_with_extras.Dockerfile
  * docker/dev.Dockerfile (bind-mount instead of COPY)

* Revert "fix(docker): copy src/bundles before uv sync so workspace bundles resolve"

This reverts commit 5aa008a3cd.

* feat: DuckDuckGo as Extension in new Bundle System (#13044)

* feat: DuckDuckGo Extension for bundles

* fix ruff errors

* Update test_pilot_duckduckgo_upgrade.py

* test(lfx): handle non-empty canonical migration table + editable installs

- test_path_override_bypasses_cache: mirror the cached canonical table
  into the temp file instead of asserting it's empty.  Drift in
  migration_table.json (the duckduckgo entries shipped with the B1
  pilot) no longer breaks the cache-bypass invariant.

- test_lfx_duckduckgo_ships_manifest: editable installs (pip install -e)
  surface only dist-info entries in dist.files, so we cannot use that
  path to find extension.json in the workspace venv.  Detect editable
  mode via direct_url.json's PEP 660 marker and fall through to walking
  the source tree; non-editable wheel installs still exercise the
  dist.files path the loader uses at runtime.

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

* fix(docker): copy src/bundles before uv sync so workspace bundles resolve

Each directory under ``src/bundles`` is a uv workspace member referenced by
``langflow-base`` (and the root project) as a path dependency.  The Docker
builders ran ``uv sync --no-install-project`` after copying only the
top-level pyproject.toml files, so resolution failed with
``Distribution not found at: file:///app/src/bundles/<name>``.

Copying the whole ``src/bundles`` tree (rather than enumerating each
bundle) means a new bundle dropped under that dir does not require a
Dockerfile edit.  The full ``./src`` copy a few lines later produces the
same final layer either way; this earlier copy just unblocks the
dependency-resolution sync.

Touched all builders that run a workspace-resolving uv sync:

  * docker/build_and_push.Dockerfile
  * docker/build_and_push_base.Dockerfile
  * docker/build_and_push_ep.Dockerfile
  * docker/build_and_push_with_extras.Dockerfile
  * docker/dev.Dockerfile (bind-mount instead of COPY)

---------

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

* fix: Review sweep

* fix: More review comments addressed

* Ruff check

* docs: add bundle porting guide

Step-by-step recipe for extracting a provider package from the in-tree
``src/lfx/src/lfx/components/<provider>/`` directory into a standalone
Extension Bundle distribution under ``src/bundles/<provider>/``.

The DuckDuckGo bundle is the reference; every section maps to a single
copy-pasteable change and a verification command.

Doc surfaces a forthcoming ``scripts/migrate/port_bundle.py`` automation
helper for the mechanical bits; that script lands on the next branch
together with the second-pilot port that validates the recipe end-to-end.

* fix(extension): accept Output(method=...) in build-method validator

The validator's static AST check looked for a literal ``build`` method
on every Component subclass and emitted ``build-method-missing`` when
absent.  Real Langflow components -- including the production
``DuckDuckGoSearchComponent`` and the in-tree ``ArXivComponent`` -- do
not declare a literal ``build``; they declare entry-points
declaratively via ``outputs = [Output(name=..., method=<name>)]`` and
the named method is what gets called.  Result: every clean port hit a
spurious ``build-method-missing`` error from ``lfx extension validate``.

Fix: extend ``_has_build_method`` to also accept any class that names a
method via ``Output(method="X")`` AND defines that method in the class
body.  The negative case ("Output(method=...) without a matching def")
still fires -- a typo'd method name would crash at runtime, so the
static check should keep flagging it.

Two new tests in ``test_validate.py`` lock the contract: positive case
mirroring duckduckgo / arxiv, negative case for typo'd method names.
All 26 validator tests pass.

PORTING.md updates fall out of running the recipe live against the
duckduckgo bundle on this branch:

  * Validate path is ``src/bundles/<bundle>/src/lfx_<bundle>``, not the
    bundle root (the manifest lives next to ``__init__.py``).
  * Index regen needs ``LFX_DEV=1`` to skip the prebuilt-index fast path
    and uses ``scripts/build_component_index.py``.
  * Drop the migration-table JSON from the ruff invocation (ruff treats
    it as Python and complains about the top-level expression).

* fix: Delete outdated components

* fix(palette): wire reload kebab via DropdownMenu, not Select

The reload kebab on the palette Bundle header was using Radix ``Select``
to back its overflow menu.  ``Select`` is for picking a value, not for
firing an action: ``onValueChange`` is gated by value-equality (so a
re-click of the only item is a no-op), and the popover-portal click
semantics interact poorly with the parent disclosure-trigger button.
The combined effect: clicking ⋮ → Reload opened the popover and closed
it, but never fired the network request, with no console error to point
at.

Switch to ``DropdownMenu`` (purpose-built action menu).
``DropdownMenuItem`` exposes ``onSelect`` which fires on every
activation -- the same callback path keyboard navigation uses -- so
clicking Reload reliably invokes the mutation.

Test mocks updated to drive the DropdownMenu primitives instead of
Select; all 8 bundleHeaderActions tests + the broader 437-test sidebar
suite still pass.

* fix(extension): route ddgs through the lockfile + drop bogus list endpoint hint

Two reviewer findings, both about reproducibility / correctness of
operator-facing surfaces.

[P2] ``docker/build_and_push_base.Dockerfile`` previously installed
``ddgs`` via an unpinned ``uv pip install ddgs`` after the workspace
sync.  That made the base image non-reproducible: a future ``ddgs``
release would silently drift from the tested lock state on every
rebuild.

Fix: route ddgs through the locked sync.

  * Restore the ``duckduckgo`` extra in ``src/backend/base/pyproject.toml``
    (``ddgs>=9.0.0``) as an internal "image-build sidecar".  Public
    consumers still install ``lfx-duckduckgo`` directly; the extra
    exists only to keep ``ddgs`` resolved in the lockfile.
  * The Dockerfile now passes ``--extra duckduckgo`` to ``uv sync
    --frozen``, picking up the locked ``ddgs==9.14.1``.
  * The follow-on bundle install keeps ``--no-deps`` so it does not
    duplicate the now-locked ``ddgs`` / ``lfx`` / ``langchain-community``.

[P3] ``langflow/api/v1/extensions.py`` returned a fix hint that pointed
operators at ``GET /api/v1/extensions`` -- a route that does not exist
in this PR (it lands with the LE-1019 list endpoint).  Replaced with a
reference to ``lfx extension list``, which is shipped here.

* fix(compat): bridge langflow.components.* dynamically via meta path finder

Commit 45552cd1df ("fix: Delete outdated components") removed the
physical shim files under ``src/backend/base/langflow/components/``
that forwarded saved-flow imports like
``from langflow.components.processing.converter import convert_to_dataframe``
or ``import langflow.components.knowledge_bases.retrieval`` to their
new ``lfx.components.*`` homes.  Without those shims, dotted imports
into ``langflow.components.<sub>.<leaf>`` failed at flow-load time --
the existing ``LangflowCompatibilityModule`` registers ``langflow.components``
itself in ``sys.modules`` but does not bridge submodules, so Python's
import machinery falls through to the now-empty langflow.components
directory and raises ``ModuleNotFoundError``.

Replace the deleted physical-shim stack with a single ``MetaPathFinder``
in ``langflow/__init__.py`` that dynamically resolves every
``langflow.components.<rest>`` import to ``lfx.components.<rest>`` and
registers the loaded lfx module in ``sys.modules`` under both names.
The langflow- and lfx-prefixed imports share a single underlying module
object, so class identity is preserved across the bridge -- ``isinstance``
checks against types resolved through either path keep working.

The finder also carries a small first-segment override map for the few
subpackages whose name diverged during the move; the only entry today is
``knowledge_bases`` -> ``files_and_knowledge``, matching the deleted
shim's intent.

Why a meta finder instead of restoring the physical shim files (option
1 from the scope analysis): the meta finder scales without per-bundle
maintenance.  Every future bundle extraction landed under ``lfx.components``
becomes reachable via the legacy ``langflow.components.<bundle>`` path
immediately; nobody has to remember to add a parallel langflow shim.

Six new unit tests in ``test_langflow_components_compat_shim.py`` lock
the contract: dotted submodule resolution, helpers re-export, the
``knowledge_bases`` override, class identity preservation, top-level
aliasing, and the "arbitrary extracted bundle" case that prevents
regression for future ports.

Verified pre-existing tests:
  * 17 dynamic-import integration tests pass.
  * The reload-route-guard suite still passes.
  * The Research Translation Loop starter-project test (which loads
    ArXivComponent) passes.

* Update index.tsx

* fix: Review pass on delivery

* fix: Second review sweep, bare names

* fix: Third review sweep

* Resolve dotted imports and attribute chains

Record import shape and flatten attribute chains so router references can be resolved across dotted imports and re-exports. Added ImportTarget dataclass, _attribute_chain helper, and switched IncludeCall/DecoratorRef to store attribute tuples. parse_file now records ImportTarget entries for imports and captures dotted parent/child chains for include_router and decorators. Replaced _resolve_var with _resolve_chain which handles "from" vs "module" imports, various import shapes (including import x.y and aliased imports), and prevents infinite recursion on re-export cycles.

* One more sweep

* Add seed-directory extension loading and docs

Introduce filesystem "seed directory" extension support and authoring docs. Adds three documentation pages (quickstart, manifest reference, author guide) and wires them into the docs sidebar. Implement load_seed_extensions to discover/load bundles from $LANGFLOW_SEED_DIR (default /opt/langflow/bundles), export it from loader/__init__ and extension package, and integrate it into the components import pipeline. Handle installed-vs-seed shadowing by preferring installed distributions and appending a typed seed-bundle-shadowed ExtensionError; add the corresponding error code and message. Update schema doc link and add unit/integration tests to cover seed loading, determinism, shadowing behavior, and migration-target resolution.

* Fix claims

* Fix docasaurus build

* Clean up the manual checklist

* Update test_pilot_duckduckgo_upgrade.py

* fix: Some wording issues with dogfooding

* fix: Comments addressed

* Update port_bundle.py

* Update component_index.json

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

* fix: pytest testpaths glob and accurate scaffold output in port_bundle

testpaths now uses ``src/bundles/*/tests`` so future bundle tests are
picked up automatically without hardcoding each bundle at the root.
pytest expands the glob via ``glob.iglob(..., recursive=True)``.

Rewrote port_bundle.py's ``_render_migration_entries`` and
``_render_test_scaffold`` to match the actual conventions:

* Migration entries now use ``bare_class_name``/``import_path``/
  ``legacy_slot`` + ``target`` + ``added_in`` (the keys
  ``lfx.extension.migration.loader`` actually reads) instead of the
  invented ``from``/``to``/``release`` shape.
* Test scaffold now imports ``load_migration_table`` and
  ``migrate_flow_payload`` -- the APIs the real tests use -- instead of
  a fictitious ``resolve_legacy_id``.  Includes the ``migration_table``
  fixture, ``_saved_flow``/``_saved_flow_node`` helpers, and the
  distribution-importable + manifest-shipped checks that mirror
  ``test_pilot_duckduckgo_upgrade.py``.

Verified by rendering the scaffold for duckduckgo with synthetic plan
data, dropping it into ``src/lfx/tests/integration/extension/``, and
running pytest -- ``3 passed, 2 skipped`` (skips are the wheel-only
checks, by design when run inside the lfx isolation venv).

* [autofix.ci] apply automated fixes

* fix: Review comments

* Update test_discovery.py

* feat: Port Arxiv to the Extension Framework (#13047)

* feat(bundles): port arxiv as the second-pilot Bundle + porting helper

Validates ``src/bundles/PORTING.md`` end-to-end by following its recipe
against a clean candidate (``ArXivComponent``: no third-party runtime
deps, no langflow-base extra, no deactivated duplicate).  Touchpoints
exercised:

  * Bundle skeleton at ``src/bundles/arxiv/`` mirroring duckduckgo.
  * In-tree provider directory removed from ``src/lfx/src/lfx/components/``
    along with its three references in ``components/__init__.py``.
  * Workspace wiring: dep, ``[tool.uv.sources]``, ``[tool.uv.workspace]``
    members, lockfile.
  * Migration table: bare-name + two import-path forms + legacy_slot
    entry.
  * Component index regenerated via ``LFX_DEV=1`` (forces dynamic
    discovery; without it the script reproduces stale entries).
  * Integration test ``test_pilot_arxiv_upgrade.py`` mirroring the
    duckduckgo pilot suite; 5 tests pass against the workspace install.

PORTING.md updates fall out of running the recipe live:
  * Validate path is ``src/bundles/<bundle>/src/lfx_<bundle>``, not the
    bundle root (the manifest lives next to ``__init__.py``).
  * Index regen needs ``LFX_DEV=1`` to skip the prebuilt-index fast path.
  * Drop the migration-table JSON from the ruff invocation (ruff treats
    it as Python and complains about the top-level expression).

``scripts/migrate/port_bundle.py`` is the mechanical helper referenced
from § Automation: stdlib-only, dry-run by default, refuses on invalid
input, and intentionally leaves migration-table edits + integration-test
authoring to a human (release version + bare-name uniqueness require
judgement).  Three guard rails verified: invalid bundle name,
existing-target-bundle, missing in-tree provider.

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

* Update Research Translation Loop.json

* Update .secrets.baseline

* fix: Move bundle test for arxiv

* Update PORTING.md

* Update component_index.json

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

* Update component_index.json

* [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>

* [autofix.ci] apply automated fixes

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

* Update component_index.json

* Update component_index.json

* Update component_index.json

* fix: empty cache dict on reload

* Lint fixes

* Update test_components_cache_integration.py

* Update test_reload.py

* Hardening pass

* Update test_init_template.py

* fix: resolve cross-source bundle-name shadowing before registry population

The reload pipeline reads ``live.source_path`` from the registry on every
call.  Previously, the registry-population loop in
``import_extension_components`` only special-cased installed-shadows-seed;
for every other pair (seed/dev, seed/inline, dev/inline,
installed/dev, installed/inline) it silently overwrote earlier records
via last-wins iteration order.  A stale dev registration whose
``source_path`` pointed at a different filesystem location could clobber
the seed record's ``source_path``; reload would then walk the dev path
while the operator edited the seed copy on disk -- producing 200 OK with
empty deltas on every reload, including for syntactically broken edits.

Generalize the dedup pass to every (earlier, later) pair using the
explicit precedence ``installed > seed > dev > inline``, applied before
both registry population AND palette template construction so the two
read from the same winning source.  Add a new generic ``bundle-shadowed``
typed error code for the pairs the existing ``seed-bundle-shadowed`` did
not cover; keep ``seed-bundle-shadowed`` for the documented installed-
over-seed pair so existing CLI exit-code logic and snapshot tests stay
intact.  Both codes are warn-only in ``lfx extension list``.

Also add an INFO log line in reload Stage 1 with the resolved
``source_path`` so the next "200 OK with empty deltas" repro can be
triaged from the server log alone -- if the path logged is not the path
the operator was editing, this dedup is what to look at.

Includes a regression test
(``test_seed_bundle_shadows_dev_emits_generic_bundle_shadowed``) that
asserts both halves: seed wins in the BundleRegistry AND the registry's
``source_path`` is the seed path, not the stale dev path.

* Update component_index.json

* fix: widen lfx-* bundles' requires-python to <3.15 to match langflow root

The two pilot bundles (``lfx-arxiv``, ``lfx-duckduckgo``) were scaffolded
by ``scripts/migrate/port_bundle.py`` whose template hard-coded
``requires-python = ">=3.10,<3.14"``.  Because both bundles are uv
workspace members of the langflow root, that cap leaked into every
workspace-level resolve: ``cd src/lfx && uv sync`` (the path
``make lfx_tests`` takes) refuses to pick a Python 3.14 interpreter even
though lfx itself, langflow, and langflow-base all advertise
``>=3.10,<3.15``.  Hosts with 3.14 installed see:

    error: The requested interpreter resolved to Python 3.14.5, which
    is incompatible with the project's Python requirement: `>=3.10, <3.14`.

Fix at the source so future ``port_bundle.py`` runs do not regress this:
template emits ``<3.15``, and the two existing emitted pyprojects are
bumped in lockstep.  ``uv.lock`` regenerates with the wider range.

Verified ``make lfx_tests`` resolves cleanly on a host with both 3.13.12
and 3.14.5 installed; the focused extension slice runs to completion.

* Update __init__.py

* Update src/lfx/tests/unit/extension/migration/test_rewrite.py

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

* Update src/lfx/src/lfx/extension/loader/_plugins.py

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

* Update docs/docs/Deployment/deployment-extensions-production.mdx

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

* Update src/lfx/src/lfx/extension/loader/_orchestrator.py

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

* Update docs/docs/Develop/extensions-author-guide.mdx

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

* Update docs/docs/Develop/extensions-manifest.mdx

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

* fix: Coderabbit review suggestions

* Template updates

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* Tweaks to bundle hot reload

* [autofix.ci] apply automated fixes

* chore: Address review comments by @Cristhianzl

* [autofix.ci] apply automated fixes

* Update BUNDLE_API.md

* Update component_index.json

* Update component_index.json

* Update Structured Data Analysis Agent.json

* fix: Next round of review comments

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.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>
2026-05-18 17:36:56 +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
cf488e545c fix: Gate more tests on package presence 2026-05-14 17:15:37 -07: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
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
da798a525d feat(components): Add Code Agents (CodeAct agent and OpenDsStar agent) and file ingestion components with supporting fixes (#12713)
* initial draft

* update DS Star agent

* chore(deps): use OpenDsStar 1.0.1 from PyPI

* refactor: move OpenDsStar to namespace, update imports, remove agents shim

* update open ds star version

* improved logging

* improved logging

* fix: propagate source file path for DataFrame inputs in ingestion components

DataFrame from CSV/Excel reads now carries the source file path via
pandas attrs, so IngestionDescriber and FileContentRetriever can
resolve the original file instead of searching per-row data keys.

* feat: add files_ingestion component bundle and bump OpenDsStar to 1.0.8

Register files_ingestion as a sidebar bundle in the frontend and
component registry. Update OpenDsStar dependency from 1.0.6 to 1.0.8.

* Add file content retriever component and tests

* Fix: Add tool_mode=True to FileContentRetriever outputs to prevent execution during build phase

* Fix: Return empty DataFrame instead of raising error when file_path not provided during build

* Update file content retriever component

* refactor: rename IngestionDescriberComponent to FileDescriptionGeneratorComponent

- Renamed class from IngestionDescriberComponent to FileDescriptionGeneratorComponent
- Updated component name attribute and display name
- Renamed files: ingestion_describer.py -> file_description_generator.py
- Renamed test file: test_ingestion_describer.py -> test_file_description_generator.py
- Updated all imports and references
- Rebuilt component index

BREAKING CHANGE: Component class name changed. Existing flows using IngestionDescriberComponent will need to be updated.

* fix: improve FileContentRetriever tool descriptions for CodeAct agent

- Add explicit warnings that tools expect string file paths only
- Clarify that search results/Data objects should not be passed
- Change error handling to raise ValueError (agents can handle exceptions)
- Add build-phase safety (return empty results when no path provided)
- Update tests to expect exceptions instead of error messages

This fixes CodeAct agent failures where it was trying to pass search
results (list of Data objects) to retrieve_content_as_dataframe()
instead of extracting the file path string first.

* fix: File Content Retriever now finds DataFrames with file_path in columns

- Added caching for file maps to avoid rebuilding on each method call
- Enhanced _get_file_maps() to check both attrs['source_file_path'] and 'file_path' column
- Fixes agent issue where DataFrame from Read File component couldn't be found
- Added test for DataFrame with file_path in columns scenario
- All 30 tests pass (26 passed, 4 skipped)

* fix: use to_csv() instead of to_string() for DataFrame text representation

Fixes agent hanging issue when retrieving file content as DataFrame.

The problem was that to_string() creates a formatted table representation
that cannot be parsed as CSV. When agents called retrieve_content_as_dataframe(),
it would try to parse this formatted text with pd.read_csv(), causing a
ParserError and infinite retry loop.

Changed to use to_csv(index=False) which produces valid CSV format that can
be parsed back into a DataFrame when needed.

- Maintains optimal performance by returning original DataFrame from dataframe_map
- Only uses CSV text representation as fallback
- All 26 tests pass
- Works correctly for both text and tabular files

* add agent template

* improve agent template

* bump OpenDsStar to 1.0.10 and update ingestion components

Upgrade OpenDsStar dependency from 1.0.8 to 1.0.10 in both langflow-base
and lfx pyproject.toml. Update file content retriever, file description
generator, component tool, and custom component with related improvements.
Expand test coverage for file content retriever.

* fix FileContentRetriever multi-file data retrieval and add code_timeout

The FileContentRetriever was broken for the multi-file case (when Read File
outputs a DataFrame with file_path + text columns). Three bugs were fixed:

1. Multi-file DataFrame mapped to wrong data: When Read File produced a
   summary DataFrame (one row per file, columns = [file_path, text]), the
   retriever mapped each file_path to the entire 2-row summary DataFrame
   instead of extracting per-file content. The agent would get 2 rows
   instead of thousands of actual data rows. Fixed by iterating rows and
   extracting each file's text into text_map.

2. CSV text now eagerly parsed into DataFrames: For .csv/.tsv files in
   text_map that lack a pre-built DataFrame, _get_file_maps() now parses
   the text into a DataFrame eagerly during initialization. This makes
   retrieve_content_as_dataframe work for the multi-file case without
   needing upstream structured DataFrames.

3. Maps built once, not per tool call: The file maps were rebuilt on every
   tool call because component_tool.py deepcopy's the component, and the
   maps were only built lazily during retrieval. Now the early-return paths
   (empty file_path) eagerly call _get_file_maps() during component build
   time, so the cached maps survive deepcopy. This is critical for
   scalability with hundreds of large files.

Additional changes:
- Removed _is_likely_file_content heuristic that was incorrectly filtering
  out valid file content
- Removed "Message" from input_types (was never handled)
- Removed redundant inner import of DataFrame
- Shortened error messages (cap available files to 5)
- Added warning log for unsupported input types
- Lazy CSV conversion: no longer eagerly converts structured DataFrames to
  CSV text in _get_file_maps, only converts on demand in retrieve_content
- Added code_timeout input to OpenDsStarAgentComponent (default 60s, was
  hardcoded 30s) to prevent timeouts with large datasets
- Added 19 unit tests covering all retrieval paths, caching, and the
  multi-file bug reproduction

* disable as_dataframe tool from vector store to fix agent confusion

The Chroma vector store's as_dataframe output was exposed as an agent tool,
returning a 2-row file index DataFrame (file_path + text columns). The agent
mistook this for actual data and tried to query 'price' on it, causing every
query to fail with KeyError.

Set tool_mode=False on the as_dataframe output so only search_documents is
exposed as a tool from the vector store. The agent now follows the correct
workflow: search_documents → get file path → retrieve_content_as_dataframe.

* Revert "disable as_dataframe tool from vector store to fix agent confusion"

This reverts commit e21c5dc649.

* bump OpenDsStar to 1.0.15, improve ingestion component tool descriptions and caching

- Upgrade OpenDsStar dependency from 1.0.10 to 1.0.15
- Add __deepcopy__ to FileContentRetriever to preserve cached maps across tool invocations
- Add JSON format support for eager DataFrame parsing
- Improve tool docstrings on FileContentRetriever and VectorStore for better agent usage
- Enable tool_mode on VectorStore search and table outputs

* support Message input in FileContentRetriever and FileDescriptionGenerator

- Add file_path to Message metadata in base_file._extract_file_metadata
- Accept Message type in FileContentRetriever.file_data input and handle
  it in _build_file_maps to extract file_path and text content
- Handle Message input in FileDescriptionGenerator to extract file_path
- Add tests for Message input: basic, missing file_path, and mixed types

* fix FileContentRetriever not appearing in component sidebar

- Remove forward reference to FileContentRetrieverComponent in __deepcopy__
  that broke the exec-based template builder, silently preventing registration
- Remove unnecessary cast() call in __deepcopy__
- Regenerate component_index.json (362 -> 363 components)
- Update template JSON edge handles to include Message in input_types

* add persistent directory, real-time logs, tool descriptions, and Merge Flows component

FileContentRetriever:
- Add persistent directory support for saving/loading text and DataFrame maps to disk
- Split text storage into individual files (texts/) instead of single JSON
- Guard against None file_data during tool deepcopy calls
- Warn when maps are empty after building
- Make Persistent Directory a visible (non-advanced) input

FileDescriptionGenerator:
- Switch from subprocess.run to Popen with real-time stderr streaming
- Add configurable timeout input (default 1800s, was hardcoded 600s)
- Stream subprocess progress to UI via self.log()

Tool descriptions:
- Add info field to Output model (excluded from serialization to avoid template pollution)
- Fix stale tool metadata overwriting fresh descriptions in component.py
- Each tool output now gets its own description instead of generic component description

New components:
- Add Merge Flows component to trigger multiple upstream flows from a single node

Tests:
- Add persistence tests (round-trip, skip duplicates, add new files, corrupted JSON, regression)
- Update FileDescriptionGenerator tests for Popen-based subprocess

* update Structured Data Agent template from UI re-export

* update Structured Data Agent template

* update Structured Data Agent template

* update Structured Data Agent template

* update Structured Data Agent template

* update Structured Data Agent template

* fix chardet perf, pipe deadlock, auto-sync, Chroma errors, and ingestion failure detection

Performance:
- Fix chardet.detect() scanning entire files (800s for 1.5GB) — sample first 100KB only
- Default ascii detection to utf-8 (superset) to handle non-ASCII chars beyond sample
- Fix subprocess stdout pipe deadlock — drain both stdout and stderr concurrently via select

FileContentRetriever:
- Add auto-sync: remove persisted entries for files no longer in file_data input
- Clean up orphaned files from persistent directory on save

FileDescriptionGenerator:
- Fail with clear error when descriptions are not generated (grouped by error reason)
- Increase default timeout from 1800s to 3600s via _DEFAULT_TIMEOUT_SECONDS constant
- Remove fast-path code (moved to OpenDsStar)

Chroma:
- Add clear error messages for missing persist directory, corrupted DB, and initialization failures
- Recreate persist directory if deleted between runs

Other:
- Add opendsstar_cache to .gitignore

* Chore(release): merge release 1.9.0 into main (#12710)

* test: add upgrade migration check to ci (#12061)

* Add upgrade migration check to ci

* [autofix.ci] apply automated fixes

* Add fetch step

* ruff

* Add merge migration

* Revert "Add merge migration"

This reverts commit fd32424739.

backups

* coderabbit suggestions

  1. Shell hardening in workflow - set -euo pipefail, full path grep, quoted variables
  2. _WORKSPACE_ROOT extracted as module constant (also addresses Cristhianzl's review comment about parents[5] duplication)
  3. git missing returns None instead of raising FileNotFoundError
  4. # noqa: S603 added to subprocess.run (fixes the Ruff CI failure)
  5. FK noise filtering now also compares target table/column, not just ondelete/onupdate
  6. Removed redundant git fetch origin main step (fetch-depth: 0 already fetches all branches)
  7. Deduplicated Alembic config creation in _get_main_branch_head (moved before the if branch)
  8. Simplified dict type hints (removed unnecessary dict[tuple, object])

* test: improve migration tests from PR review feedback

- Narrow broad except clause to only wrap subprocess.run call
- Add specific error messages for multi-head and unresolvable revisions
- Remove redundant hardcoded schema test (covered by compare_metadata)
- Fix SQLite FK noise filter to skip ondelete/onupdate comparison
- Add downgrade verification to test_upgrade_from_main_branch
- Add test file and workflow to CI trigger paths
- Add prompt for follow-up PostgreSQL migration test PR

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

* add engine check on downgrade

* [autofix.ci] apply automated fixes

* fix: harden CI error handling and test robustness

- Set validationPassed=false when validator crashes so CI fails instead of passing silently
- Wrap GitHub API calls in try-catch so comment-posting failures don't mask validation results
- Preserve git stderr in warnings for better CI debugging
- Add defensive handling for unexpected FK constraint shapes in SQLite noise filter
- Clean up SQLite WAL/SHM/journal companion files in test teardown

* Add explicit fetch to main

* ruff

* [autofix.ci] apply automated fixes

* Add sqlite filter tests and remove redundant fetch

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(deployments): unify payload passthrough from api to adapter (#12190)

* feat(deployments): unify dynamic payload passthrough across api and adapter

* use datatime.timezone for python3.10 compatibility

* use appropriate type vars in slots and sanitize error message

* tweaks to schemas

* use policy to avoid dump churn

* fix: allow clearing Max Tokens field with Backspace/Delete (#12198)

* fix: allow clearing Max Tokens field with Backspace/Delete

Empty string input was being converted to 0 via Number(""), which
triggered the min-value guard and snapped the field back to 1 before
onChange could propagate. Adding an early return for empty input lets
the field clear correctly, propagating null (no limit) downstream.

* test: add IntComponent tests for handleInputChange clearing behavior

Covers the regression where Backspace/Delete was blocked by the
min-value guard, and verifies that below-min values still clamp
correctly.

* fix: Resolve CodeQL false positives for path injection and URL substring sanitization (#12201)

* fix: Add explicit left/right DataFrame inputs for merge operations (#12177)

* add explicit left/right DataFrame inputs for merge operations

* [autofix.ci] apply automated fixes

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

* [autofix.ci] apply automated fixes

* ruff style and checker fixes

---------

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

* fix: add dict to allowlist preventing TableInput data loss (#12074)

* fix: add dict to allowlist preventing TableInput data loss

Co-Authored-By: DeyLak <DeyLak@users.noreply.github.com>

* test: add regression test for TableInput list[dict] preservation

Regression test for: https://github.com/langflow-ai/langflow/issues/12062

Co-Authored-By: DeyLak <DeyLak@users.noreply.github.com>

---------

Co-authored-by: DeyLak <DeyLak@users.noreply.github.com>
Co-authored-by: Cristhian Zanforlin Lousa <cristhian.lousa@gmail.com>

* chore: update pyproject versions 1.9.0

update pyproject versions 1.9.0

* fix: 1.9.0 nightly

1.9.0 nightly fix

* feat: add wxO deployment adapter (#12079)

* checkout wxo deployment adapter implementation

* checkout wxo deps and flow reqs impl

* clean up / minor refactor with updated tests

* major refactor: split up the implementation into folders and files

* clean up logic

* refactor and clean up of execution logic, improve type safety of "retry_create" helper, and remove dead code

* remove unused wxo service file

* remove "provider_name" arg and references

* fix: harden watsonx orchestrate deployment adapter for PR readiness

- Fix rollback AttributeError when agent_create_response is None
- Fix NoneType access on params in list() when called without params
- Fix inconsistent error types: use DeploymentNotFoundError in get/update
- Fix typo "occured" -> "occurred" in all error prefix messages
- Fix variable shadowing of fastapi.status in get_status()
- Fix pre-existing test bugs (wrong exception types, stale method refs)
- Fix e2e monkey-patching of non-existent service methods
- Add structured logging to create, delete, retry, and rollback flows
- Add jitter to retry backoff to avoid thundering herd
- Add __repr__ to WxOCredentials that fully masks the API key
- Extract hard-coded LLM model string to DEFAULT_WXO_AGENT_LLM constant
- Remove commented-out snapshot update code
- Expand test coverage from 24 to 75 tests covering retry logic,
  service methods, client auth, utilities, execution/status helpers,
  and artifact roundtrip

* fix(deployment): fix bugs and harden watsonx orchestrate adapter

- Fix update method silently discarding changes instead of sending them
  to the WXO API
- Wrap all synchronous SDK calls in asyncio.to_thread to avoid blocking
  the event loop
- Add error handling to get_status (was propagating raw exceptions)
- Use DeploymentType enum values instead of raw strings for
  SUPPORTED_ADAPTER_DEPLOYMENT_TYPES
- Fix type annotations in list method (list -> set)
- Fix typo in comment (reccomend -> recommend)
- Remove dead code: extract_agent_connection_ids,
  require_exclusive_resource, require_non_empty_string,
  resolve_health_environment_id, fetch_agent_release_status,
  normalize_release_status, resolve_lfx_runner_requirement,
  _pin_requirement_name, sync_langflow_tool_connections,
  create_langflow_flow_tool, resolve_snapshot_connections, and unused constants
- Make assert_create_resources_available and validate_connection async
- Make create_agent_run and get_agent_run async
- Add tests for list_types, get_status error handling, and update
  side-effects
- Update existing tests for async function signatures

* actually remove the dead code from tools.py

* properly await "validate_connection"

* update e2e test file

* add more scenarios to e2e test runner

* refactor(watsonx-orchestrate): improve WxOClient encapsulation and error messages
Encapsulate SDK private method access and endpoint paths inside
WxOClient wrappers so callers never handle raw paths or touch internal
_get/_post methods. Route all private HTTP calls through a single
_base client auto-created in __post_init__, removing the externally
constructed `base` field.
Additionally fix double-period and redundant text in error messages
produced by the ErrorPrefix + handler pattern, and update E2E/unit
assertions to match the sanitised error output.
Changes:
- types.py: bake endpoint paths into wrapper signatures (post_run,
  get_run, upload_tool_artifact, get_agents_raw); auto-create _base
  via __post_init__; remove base from constructor
- client.py: drop BaseWXOClient import and base= constructor arg
- core/execution.py: pass run_id / query_suffix instead of raw paths
- core/tools.py: pass tool_id instead of raw path
- service.py: fix double-period in ErrorPrefix interpolation; remove
  redundant restatements in generic except handlers
- tests: update _with_wxo_wrappers helper and test doubles to use
  _base; update FakeBaseClient._get to accept params
- e2e: update rollback scenario detail_contains to match sanitised msg

* skip import and tests of wxo adapter if current env is running python 3.10

* clarify random prefix / retry  behavior

* implement comments

* fix: align watsonx adapter with updated deployment schema
- Add `deployment_type` parameter to `get`, `update`, `redeploy`,
  `duplicate`, `delete`, `get_status`, and `undeploy_deployment` in
  WatsonxOrchestrateDeploymentService to match the updated
  BaseDeploymentService ABC
- Update e2e script to use renamed `add_ids` field on
  SnapshotDeploymentBindingUpdate

* remove non-interface method undeploy_deployment

* implement listing configs and snapshots

* add update implementation and improve http->deployment error translation and add tests

* improve exception handling

* checkout payload slot work

* custom payload schema for update

* new update implementation

* stop passing client cache to helpers

* add docs for ordereduniquests

* improve import patterns and document future risks for wxo dependencies

* remove global-variable prefixing of flows

* ref: harden typing, DRY helpers, and correctness fixes
- Replace `db: Any` with `db: AsyncSession` across client, config, and
  update_helpers modules
- Extract `_ensure_dict` / `ensure_langflow_connections_binding` helpers
  to eliminate repeated nested-dict safety logic in tools.py and
  update_helpers.py, with documentation explaining why malformed API
  payloads are silently corrected rather than rejected
- Use `PayloadSlot.parse()` for update payload validation instead of
  standalone helper; remove `parse_provider_update_payload`
- Fix lambda late-binding with default-argument captures in service.py
- Use `zip(strict=True)` in update_helpers for defensive mismatch
  detection
- Replace O(n²) duplicate detection with `collections.Counter` in
  payloads.py
- Simplify `dedupe_list` to `list(dict.fromkeys(...))`
- Move type-annotation-only imports into TYPE_CHECKING blocks in
  types.py and config.py
- Introduce `UPDATE_MAX_RETRIES` as a distinct constant from
  `CREATE_MAX_RETRIES`
- Fix "watsonX" → "watsonx" casing in error messages
- Clarify `get_status` docstring and `validate_connection` error message
- Add TODO(deployments-cache) for client cache invalidation on
  credential updates

* ref: drop client cache and adopt typed deployment context across the wxo adapter path, add request-context memoization with strict mixed-context guards, and lazily initialize wxo SDK clients. Add safer credential handling by storing only authenticators in WxOCredentials. Also improve provider error-detail extraction/messages and make the direct wxo E2E conflict scenario diagnostics and expectations more resilient.

* use explicit naming for context class; providerId

* fix error handling, retry safety, and exception diagnostics in wxo adapter

- Raise DeploymentError on empty API responses instead of fabricating
  fake success in create_agent_run_result and get_agent_run
- Elevate rollback failure logging from WARNING to ERROR for alerting
- Apply retryable filter to retry_rollback to skip 401/403/409/422
- Preserve exception chains (from exc) instead of suppressing (from None)
  across service.py, utils.py, execution.py, and update_helpers.py
- Broaden credential resolution catch to handle arbitrary DB exceptions
- Separate status code dispatch from string heuristics in
  raise_for_status_and_detail to prevent misclassification
- Add tests for all behavioral changes

* [autofix.ci] apply automated fixes

* fix: harden wxO adapter safety, immutability, and error diagnostics

- Make WxOClient and WxOCredentials frozen dataclasses with eager SDK
  client initialization to eliminate thread-safety races from
  asyncio.to_thread workers and prevent post-construction mutation
- Move instance_url validation and normalization into type __post_init__
- Raise DeploymentError on missing run_id instead of returning partial
  success with execution_id=None
- Preserve exception chains (from exc) instead of suppressing (from None)
  across create, update, and delete service methods
- Add warning logs when _ensure_dict replaces non-dict binding values
  and when _resolve_lfx_requirement falls back to minimum version
- Initialize derived_spec before try block to prevent potential NameError
- Log all ToolUploadBatchError errors before re-raising the first
- Change SUPPORTED_ADAPTER_DEPLOYMENT_TYPES from mutable set to frozenset
- Add tests for 409/422 error mapping in create, unsupported deployment
  type rejection, empty update rejection, zip artifact extraction paths,
  validate_connection negative paths, missing run_id, multiple deployment
  ID rejection, exception chain preservation, and _ensure_dict warning

* [autofix.ci] apply automated fixes

* fix ruff errors and and todo for status method

* fix mypy errors

* [autofix.ci] apply automated fixes

---------

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

* fix: 1.9.0 nightly (#12210)

fix 1.9.0 nightly

* fix(mcp): Add schema-driven type conversion (#11796)

* fix: nightly now properly gets 1.9.0 branch (#12215)

before it was attempting to pull release-notes as letters are alphanumerically after numbers when we sort -V then grab tail
now we only look at branch names that follow the pattern '^release-[0-9]+\.[0-9]+\.[0-9]+$'

* fix(mcp): Add schema-driven type conversion

- Add schema-driven type conversion (str→dict, str→int, etc.)
- normalize and unflatten tool arguments for MCP servers
- Unflatten flattened keys (e.g. params.search) into nested objects

* fix(mcp): handle dict type and array type in JSON schema for MCP tools

- Support "type": ["string", "null"] (JSON Schema array type)
- Normalize required to hashable elements (filter non-string entries)
- Add unit tests for create_input_schema_from_json_schema

* fix(mcp): map generic object type to dict for free-form params

When JSON schema has {"type": "object"} with no properties, treat it as
a free-form dict instead of building a nested Pydantic model. This allows
MCP servers expecting arbitrary key-value params to receive proper dicts,
and enables str→dict conversion via _normalize_arguments_for_mcp.

- Add conditional in parse_type: empty properties → dict, else nested model
- Add test_create_input_schema_generic_object_maps_to_dict

* fix(mcp): exclude None from tool arguments sent to MCP servers

* test_mcp: add more tests for datatypes

* fix(mcp): parse JSON strings for nested model params (e.g. foreman-mcp)

* fix(mcp): refactor _try_convert_value reducing repetition

* fix(mcp): add missing tests for remaining use cases

* fix(mcp): Fix mapping of None if expected is list, dict or str

* Update nightly_build.yml

---------

Co-authored-by: Adam-Aghili <149833988+Adam-Aghili@users.noreply.github.com>
Co-authored-by: Eric Hare <ericrhare@gmail.com>

* fix: prevent overwriting user-selected global variables in provider c… (#12217)

* fix: nightly now properly gets 1.9.0 branch (#12215)

before it was attempting to pull release-notes as letters are alphanumerically after numbers when we sort -V then grab tail
now we only look at branch names that follow the pattern '^release-[0-9]+\.[0-9]+\.[0-9]+$'

* docs: add search icon (#12216)

add-back-svg

* fix: prevent overwriting user-selected global variables in provider config

Previously, the apply_provider_variable_config_to_build_config function would
automatically overwrite field values with environment variable keys whenever
an env var was present, even if the user had already selected a different
global variable.

This fix adds a check to only auto-set the environment variable if:
- The field is currently empty, OR
- The field is not already configured to load from the database

This preserves user selections while still providing automatic configuration
for new/empty fields.

Added comprehensive unit tests to verify:
- Auto-setting env vars for empty fields
- Preserving user-selected global variables
- Overwriting hardcoded values (expected behavior)
- Skipping when env var is not set
- Applying component metadata correctly

* [autofix.ci] apply automated fixes

* style: use dictionary comprehension instead of for-loop

Fixed PERF403 Ruff style warning by replacing for-loop with dictionary
comprehension in update_projects_components_with_latest_component_versions

* chore: retrigger CI build

* test: improve test coverage and clarity for provider config

- Renamed test_apply_provider_config_overwrites_hardcoded_value to
  test_apply_provider_config_replaces_hardcoded_with_env_var for clarity
- Added test_apply_provider_config_idempotent_when_already_set to document
  idempotent behavior when value already matches env var key
- Removed sensitive value from debug log message to prevent potential
  exposure of API keys or credentials

These changes improve test coverage by documenting the no-op scenario
and enhance security by avoiding logging of potentially sensitive data.

* chore: retrigger CI build

---------

Co-authored-by: Adam-Aghili <149833988+Adam-Aghili@users.noreply.github.com>
Co-authored-by: Mendon Kissling <59585235+mendonk@users.noreply.github.com>
Co-authored-by: Steve Haertel <shaertel@ca.ibm.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Eric Hare <ericrhare@gmail.com>

* fix: Fixed CodeQL security scan about Incomplete URL substring sanitization on watsonx test suite (#12212)

* fix: Fixed CodeQL security scan about Incomplete URL substring sanitization

* fix coderabbitai comments

* fix: nightly now properly gets 1.9.0 branch (#12215)

before it was attempting to pull release-notes as letters are alphanumerically after numbers when we sort -V then grab tail
now we only look at branch names that follow the pattern '^release-[0-9]+\.[0-9]+\.[0-9]+$'

* fix failing action

* docs: add search icon (#12216)

add-back-svg

* Revert "Merge branch 'main' into dev-fix-security-code-scan-watsonx"

This reverts commit 41eb034e11, reversing
changes made to 4e51f4d836.

* Revert "Merge branch 'main' into dev-fix-security-code-scan-watsonx"

This reverts commit 4e51f4d836, reversing
changes made to 530bddd0a4.

---------

Co-authored-by: Adam-Aghili <149833988+Adam-Aghili@users.noreply.github.com>
Co-authored-by: Mendon Kissling <59585235+mendonk@users.noreply.github.com>

* fix: remove ibm-watsonx extra from complete installation (#12230)

* docs: lfx readme content (#11870)

* docs-add-lfx-content-to-readme

* github-link-syntax

* allowlist-blocklist

* docs: add a copy to markdown button to docusaurus theme (#12189)

* copy-page-component

* copy-theme-and-add-button

* docs: add versioning  (#12218)

* fix: nightly now properly gets 1.9.0 branch (#12215)

before it was attempting to pull release-notes as letters are alphanumerically after numbers when we sort -V then grab tail
now we only look at branch names that follow the pattern '^release-[0-9]+\.[0-9]+\.[0-9]+$'

* docs: add search icon (#12216)

add-back-svg

* initial-content

* cut-1.8-release-and-include-next-version

* stage-1.8.0-and-next

---------

Co-authored-by: Adam-Aghili <149833988+Adam-Aghili@users.noreply.github.com>

* docs: replace api build automation (#12214)

* remove-workflows-file-and-script

* tag-hidden-endpoints

* update-scripts-and-specs

* fix: nightly now properly gets 1.9.0 branch (#12215)

before it was attempting to pull release-notes as letters are alphanumerically after numbers when we sort -V then grab tail
now we only look at branch names that follow the pattern '^release-[0-9]+\.[0-9]+\.[0-9]+$'

* docs: add search icon (#12216)

add-back-svg

---------

Co-authored-by: Adam-Aghili <149833988+Adam-Aghili@users.noreply.github.com>
Co-authored-by: Debojit Kaushik <Kaushik.debojit@gmail.com>

* fix: prevent arbitrary file write via path traversal in files endpoint (#12227)

* fix(security): prevent arbitrary file write via path traversal in file uploads

* [autofix.ci] apply automated fixes

---------

Co-authored-by: Janardan S Kavia <janardanskavia@Janardans-MacBook-Pro.local>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* docs: Add AI coding agent skills for code review, testing, and refactoring (#12241)

Add AI coding agent skills for code review, testing, and refactoring

* feat: Add Windows Playwright testing to nightly builds (#12221)

* feat: add Windows support for Playwright tests in nightly builds

- Add windows-latest as runner option in typescript_test.yml
- Update Playwright browser installation to be OS-aware (Windows doesn't support --with-deps)
- Add matrix strategy to nightly_build.yml to run tests on both Linux and Windows
- Update Slack notifications to indicate multi-platform testing
- Tests now run in parallel on ubuntu-latest and windows-latest

This enables catching Windows-specific regressions early in the nightly build process.

* fix: add shell: bash to all script steps for Windows compatibility

Windows runners default to PowerShell which doesn't understand bash syntax.
All steps with bash scripts now explicitly specify shell: bash to ensure
cross-platform compatibility.

* feat: make Windows Playwright tests non-blocking initially

Add continue-on-error for Windows tests to allow nightly builds to succeed
even if Windows-specific issues are found. This gives us visibility into
Windows bugs without blocking releases.

Windows tests will still run every night and report failures, but won't
block the build. Once Windows tests are stable, we can remove this flag.

* chore: fix white space

chore: fix white space

* fix: replace matrix strategy with separate jobs for Windows Playwright tests

- GitHub Actions reusable workflows don't support matrix strategy
- Split frontend-tests into frontend-tests-linux and frontend-tests-windows
- Windows tests are non-blocking (continue-on-error: true)
- Updated all job dependencies and Slack notification logic
- Addresses PR review comment about matrix limitation

* chore: trigger workflow validation refresh

---------

Co-authored-by: Adam Aghili <Adam.Aghili@ibm.com>

* fix: Avoid foreign key violation on span table with topological sort (#12232)

* fix: Foreign key violation on span table

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* address review comments

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix: use deepcopy to prevent shared reference mutation in component updates (#12252)

* fix: use deepcopy to prevent shared reference mutation in component updates

Copies template data via deepcopy when updating project components to
prevent mutations from leaking between projects through all_types_dict.
Also fixes edge updates to use the copied project data and adds
cloneDeep in the frontend templatesGenerator.

* fix: deepcopy mutable FIELD_FORMAT_ATTRIBUTES and add coverage test

- Add deepcopy on field_dict[attr] assignment (line 192) to prevent
  shared references for mutable attributes like input_types, options,
  and fileTypes leaking back into all_types_dict
- Add test_update_components_does_not_mutate_field_format_attributes
  to verify the fix covers the FIELD_FORMAT_ATTRIBUTES update path

* feat: add support for Langchain 1.0 (#11114)

* feat: upgrade to LangChain 1.0

- langchain ~=1.2.0
- langchain-core ~=1.2.3
- langchain-community ~=0.4.1

Updated all langchain-* integration packages to versions compatible with langchain-core 1.0+.

* feat(lfx): add langchain-classic dependency for legacy agent classes

LangChain 1.0 removed AgentExecutor and related classes to langchain-classic.
This adds the dependency to maintain backward compatibility.

* refactor(lfx): update imports for LangChain 1.0 compatibility

- Move AgentExecutor, agent creators from langchain to langchain_classic
- Move AsyncCallbackHandler from langchain.callbacks to langchain_core.callbacks
- Move Chain, BaseChatMemory from langchain to langchain_classic
- Update LANGCHAIN_IMPORT_STRING for code generation

* fix(lfx): make sqlalchemy import lazy in session_scope

LangChain 1.0 no longer includes sqlalchemy as a transitive dependency.
Move the import inside the function where it's used to avoid import errors
when sqlalchemy is not installed.

* chore: update uv.lock for langchain-classic

* feat: enable nv-ingest optional dependencies for langchain 1.0

- Uncomment nv-ingest-api and nv-ingest-client, update to >=26.1.0
  (no longer has openai version conflict)
- Bump datasets from <4.0.0 to <5.0.0 to allow fsspec>=2025.5.1
  required by nv-ingest
- Update mlx-vlm TODO comment with accurate blocking reason

* chore: update nv-ingest to 26.1.1

nv-ingest 26.1.1 removes the openai dependency, resolving the
conflict with langchain-openai>=1.0.0 (which requires openai>=1.109.1).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: enable mlx and mlx-vlm dependencies for langchain 1.0

opencv-python 4.13+ now supports numpy>=2, resolving the conflict
with langchain-aws>=1.0.0 (which requires numpy>=2.2 on Python 3.12+).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* style: fix import order in callback.py

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: update imports to use langchain_classic for agent modules

* [autofix.ci] apply automated fixes

* fix: remove .item() calls in knowledge_bases.py

* fix(lfx): import BaseMemory from langchain_classic for langchain 1.0

* [autofix.ci] apply automated fixes

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

* refactor: update deprecated langchain imports for langchain 1.0

- langchain.callbacks.base -> langchain_core.callbacks.base
- langchain.tools -> langchain_core.tools
- langchain.schema -> langchain_core.messages/documents
- langchain.chains -> langchain_classic.chains
- langchain.retrievers -> langchain_classic.retrievers
- langchain.memory -> langchain_classic.memory
- langchain.globals -> langchain_core.globals
- langchain.docstore -> langchain_core.documents
- langchain.prompts -> langchain_core.prompts

Also simplified GoogleGenerativeAIEmbeddingsComponent to use native
langchain-google-genai 4.x which now supports output_dimensionality.

* [autofix.ci] apply automated fixes

* fix: add _to_int helper for pandas sum() compatibility across Python versions

* fix: update langfuse>=3.8.0 and fix cuga_agent.py (#11519)

* fix: update langfuse>=3.8.0 and fix cuga_agent.py

* [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>

* feat: implement LangFuseTracer for langfuse v3 API compatibility and add unit tests

* fix: upgrade cuga to 0.2.9 for langchain 1.0 compatibility

* fix: improve error handling and return value in get_langchain_callback method

* fix: update package versions for compatibility and improvements

* [autofix.ci] apply automated fixes

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

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

* fix: update langwatch dependency to version 0.10.0 for compatibility

* fix: update environment variable for Langfuse host to LANGFUSE_BASE_URL

* Update dependency versions in Youtube Analysis project

- Downgraded googleapiclient from 2.188.0 to 2.154.0
- Updated langchain_core from 1.2.7 to 1.2.9
- Updated fastapi from 0.128.1 to 0.128.5
- Downgraded youtube_transcript_api from 1.2.4 to 1.2.3
- Changed langchain_core version from 1.2.7 to 0.3.81
- Cleared input_types in model selection

# Conflicts:
#	src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json
#	src/backend/base/langflow/initial_setup/starter_projects/Basic Prompting.json
#	src/backend/base/langflow/initial_setup/starter_projects/Blog Writer.json
#	src/backend/base/langflow/initial_setup/starter_projects/Custom Component Generator.json
#	src/backend/base/langflow/initial_setup/starter_projects/Document Q&A.json
#	src/backend/base/langflow/initial_setup/starter_projects/Financial Report Parser.json
#	src/backend/base/langflow/initial_setup/starter_projects/Hybrid Search RAG.json
#	src/backend/base/langflow/initial_setup/starter_projects/Image Sentiment Analysis.json
#	src/backend/base/langflow/initial_setup/starter_projects/Instagram Copywriter.json
#	src/backend/base/langflow/initial_setup/starter_projects/Invoice Summarizer.json
#	src/backend/base/langflow/initial_setup/starter_projects/Knowledge Retrieval.json
#	src/backend/base/langflow/initial_setup/starter_projects/Market Research.json
#	src/backend/base/langflow/initial_setup/starter_projects/Meeting Summary.json
#	src/backend/base/langflow/initial_setup/starter_projects/Memory Chatbot.json
#	src/backend/base/langflow/initial_setup/starter_projects/News Aggregator.json
#	src/backend/base/langflow/initial_setup/starter_projects/Nvidia Remix.json
#	src/backend/base/langflow/initial_setup/starter_projects/Pokédex Agent.json
#	src/backend/base/langflow/initial_setup/starter_projects/Portfolio Website Code Generator.json
#	src/backend/base/langflow/initial_setup/starter_projects/Price Deal Finder.json
#	src/backend/base/langflow/initial_setup/starter_projects/Research Agent.json
#	src/backend/base/langflow/initial_setup/starter_projects/Research Translation Loop.json
#	src/backend/base/langflow/initial_setup/starter_projects/SEO Keyword Generator.json
#	src/backend/base/langflow/initial_setup/starter_projects/SaaS Pricing.json
#	src/backend/base/langflow/initial_setup/starter_projects/Search agent.json
#	src/backend/base/langflow/initial_setup/starter_projects/Sequential Tasks Agents.json
#	src/backend/base/langflow/initial_setup/starter_projects/Simple Agent.json
#	src/backend/base/langflow/initial_setup/starter_projects/Social Media Agent.json
#	src/backend/base/langflow/initial_setup/starter_projects/Text Sentiment Analysis.json
#	src/backend/base/langflow/initial_setup/starter_projects/Travel Planning Agents.json
#	src/backend/base/langflow/initial_setup/starter_projects/Twitter Thread Generator.json
#	src/backend/base/langflow/initial_setup/starter_projects/Vector Store RAG.json
#	src/backend/base/langflow/initial_setup/starter_projects/Youtube Analysis.json

* fix: handle InvalidRequestError during session rollback

* update projects

* ️ Speed up method `LangFuseTracer.end` by 141% in PR #11114 (`feat/langchain-1.0`) (#11682)

Optimize LangFuseTracer.end 


The optimized code achieves a **140% speedup** (8.23ms → 3.42ms) through two complementary optimizations:

## 1. Fast-path for Common Primitives in `serialize()`

**What changed:** Added an early-exit check that returns immutable primitives (`str`, `int`, `float`, `bool`) directly when no truncation or special handling is needed:

```python
if max_length is None and max_items is None and not to_str:
    if isinstance(obj, (str, int, float, bool)):
        return obj
```

**Why it's faster:** 
- The profiler shows `_serialize_dispatcher()` consumed **81.5% of runtime** in the original code (40.4ms out of 49.6ms)
- This optimization reduced dispatcher calls from **8,040 to 1,013** (~87% reduction), as primitives now bypass the expensive pattern-matching dispatcher entirely
- The fast-path check itself is extremely cheap: just two quick conditionals and an `isinstance()` check against a tuple of built-in types

**When it helps:** This optimization is particularly effective for workloads with many primitive values in dictionaries and lists—which is exactly what the tracing use case provides (metadata dicts with strings, numbers, booleans).

## 2. Eliminate Redundant Serialization in `LangFuseTracer.end()`

**What changed:** Serialize `inputs`, `outputs`, and `metadata` once each, then reuse the results:

```python
inputs_ser = serialize(inputs)
outputs_ser = serialize(outputs)
metadata_ser = serialize(metadata) if metadata else None
```

**Why it's faster:**
- The original code called `serialize()` **6 times total** (3 for `.update()` + 3 for `.update_trace()`)
- The optimized version calls it **3 times**, then passes the cached results
- Profiler shows the time spent in `serialize()` calls dropped from **72.2ms to 31.2ms** (~57% reduction)
- This is pure elimination of redundant work—the same dictionaries were being serialized twice with identical results

**Impact on workloads:** The `test_end_multiple_iterations_calls_end_each_time` test (500 iterations) demonstrates this matters in hot paths. If `LangFuseTracer.end()` is called frequently during flow execution, avoiding duplicate serialization provides compounding benefits.

## Combined Effect

Both optimizations target the serialization bottleneck from different angles:
- The fast-path reduces the cost of *each* serialize call by ~75% for primitive-heavy data
- The caching reduces the *number* of serialize calls by 50%

Together, they deliver the observed 140% speedup, with the optimization being especially effective for the common case of metadata dictionaries containing mostly primitive types.

Co-authored-by: codeflash-ai[bot] <148906541+codeflash-ai[bot]@users.noreply.github.com>

* refactor: reorder imports and simplify serialization logic for primitives

* [autofix.ci] apply automated fixes

* fix: update google dependency version to 0.4.0 in component_index.json

* [autofix.ci] apply automated fixes

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

* fix: pin z3-solver<4.15.7 to restore Linux wheels for Docker build

z3-solver 4.15.7 dropped manylinux wheels, causing the Docker build to
fail when trying to compile from source. Temporary pin until codeflash
is removed.

* [autofix.ci] apply automated fixes

* fix: update google dependency version to 0.4.0

* [autofix.ci] apply automated fixes

* fix: update langchain_core version to 1.2.17 in multiple starter project JSON files

* [autofix.ci] apply automated fixes

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

* fix: update deprecated langchain imports to langchain_classic for 1.0 compatibility

* fix: align langchain-chroma version in optional chroma dependency group

* fix: nightly now properly gets 1.9.0 branch (#12215)

before it was attempting to pull release-notes as letters are alphanumerically after numbers when we sort -V then grab tail
now we only look at branch names that follow the pattern '^release-[0-9]+\.[0-9]+\.[0-9]+$'

* docs: add search icon (#12216)

add-back-svg

* [autofix.ci] apply automated fixes

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

* feat: fall back to langchain_classic for pre-1.0 imports in user components

Old flows using removed langchain imports (e.g. langchain.memory,
langchain.schema, langchain.chains) now resolve via langchain_classic
at two levels: module-level for entirely removed modules, and
attribute-level for removed attributes in modules that still exist
in langchain 1.0. New langchain 1.0 imports are never affected since
fallbacks only trigger on import failure.

* urllib parse module import bug

* Update component_index.json

* [autofix.ci] apply automated fixes

* chore: rebuild component index

* [autofix.ci] apply automated fixes

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Harold Ship <harold.ship@gmail.com>
Co-authored-by: codeflash-ai[bot] <148906541+codeflash-ai[bot]@users.noreply.github.com>
Co-authored-by: Adam-Aghili <149833988+Adam-Aghili@users.noreply.github.com>
Co-authored-by: Mendon Kissling <59585235+mendonk@users.noreply.github.com>
Co-authored-by: Eric Hare <ericrhare@gmail.com>

* fix: prevent CI injection via unsanitized GitHub context interpolation (#12224)

Pass github.event.pull_request.head.ref through env: instead of
interpolating it directly into run: shell steps. This prevents bash
from evaluating command substitutions embedded in malicious branch names
before input validation runs.

Co-authored-by: Janardan Singh Kavia <janardankavia@ibm.com>

* feat: Refactor and Unify the ModelInput Selector Across Components (#12025)

* fix: Fixes Kubernetes deployment crash on runtime_port parsing (#11968) (#11975)

* feat: add runtime port validation for Kubernetes service discovery

* test: add unit tests for runtime port validation in Settings

* fix: improve runtime port validation to handle exceptions and edge cases

Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@logspace.ai>

* fix(frontend):  show delete option for default session when it has messages (#11969)

* feat: add documentation link to Guardrails component (#11978)

* feat: add documentation link to Guardrails component

* [autofix.ci] apply automated fixes

---------

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

* feat: traces v0 (#11689) (#11983)

* feat: traces v0

v0 for traces includes:
- filters: status, token usage range and datatime
- accordian rows per trace

Could add:
- more filter options. Ecamples: session_id, trace_id and latency range

* fix: token range

* feat: create sidebar buttons for logs and trace

add sidebar buttons for logs and trace
remove lods canvas control

* fix: fix duplicate trace ID insertion

hopefully fix duplicate trace ID insertion on windows

* fix: update tests and alembic tables for uts

update tests and alembic tables for uts

* chore: add session_id

* chore: allo grouping by session_id and flow_id

* chore: update race input output

* chore: change run name to flow_name - flow_id
was flow_name - trace_id
now flow_name - flow_id

* facelift

* clean up and add testcases

* clean up and add testcases

* merge Alembic detected multiple heads

* [autofix.ci] apply automated fixes

* improve testcases

* remodel files

* chore: address gabriel simple changes

address gabriel simple changes in traces.py and native.py

* clean up and testcases

* chore: address OTel and PG status comments

https://github.com/langflow-ai/langflow/pull/11689#discussion_r2854630438
https://github.com/langflow-ai/langflow/pull/11689#discussion_r2854630446

* chore: OTel span naming convention

model name is now set using name = f"{operation} {model_name}" if model_name else operation

* add traces

* feat: use uv sources for CPU-only PyTorch (#11884)

* feat: use uv sources for CPU-only PyTorch

Configure [tool.uv.sources] with pytorch-cpu index to avoid ~6GB CUDA
dependencies in Docker images. This replaces hardcoded wheel URLs with
a cleaner index-based approach.

- Add pytorch-cpu index with explicit = true
- Add torch/torchvision to [tool.uv.sources]
- Add explicit torch/torchvision deps to trigger source override
- Regenerate lockfile without nvidia/cuda/triton packages
- Add required-environments for multi-platform support



* fix: update regex to only replace name in [project] section

The previous regex matched all lines starting with `name = "..."`,
which incorrectly renamed the UV index `pytorch-cpu` to `langflow-nightly`
during nightly builds. This caused `uv lock` to fail with:
"Package torch references an undeclared index: pytorch-cpu"

The new regex specifically targets the name field within the [project]
section only, avoiding unintended replacements in other sections like
[[tool.uv.index]].

* style: fix ruff quote style

* fix: remove required-environments to fix Python 3.13 macOS x86_64 CI

The required-environments setting was causing hard failures when packages
like torch didn't have wheels for specific platform/Python combinations.
Without this setting, uv resolves optimistically and handles missing wheels
gracefully at runtime instead of failing during resolution.



---------



* LE-270: Hydration and Console Log error (#11628)

* LE-270: add fix hydration issues

* LE-270: fix disable field on max token on language model

---------



* test: add wait for selector in mcp server tests (#11883)

* Add wait for selector in mcp server tests

* [autofix.ci] apply automated fixes

* Add more awit for selectors

* [autofix.ci] apply automated fixes

---------



* fix: reduce visual lag in frontend  (#11686)

* Reduce lag in frontend by batching react events and reducing minimval visual build time

* Cleanup

* [autofix.ci] apply automated fixes

* add tests and improve code read

* [autofix.ci] apply automated fixes

* Remove debug log

---------




* feat: lazy load imports for language model component (#11737)

* Lazy load imports for language model component

Ensures that only the necessary dependencies are required.
For example, if OpenAI provider is used, it will now only
import langchain_openai, rather than requiring langchain_anthropic,
langchain_ibm, etc.

* Add backwards-compat functions

* [autofix.ci] apply automated fixes

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

* Add exception handling

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

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

* comp index

* docs: azure default temperature (#11829)

* change-azure-openai-default-temperature-to-1.0

* [autofix.ci] apply automated fixes

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

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

* [autofix.ci] apply automated fixes

---------



* [autofix.ci] apply automated fixes

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

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

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

* fix unit test?

* add no-group dev to docker builds

* [autofix.ci] apply automated fixes

---------





* feat: generate requirements.txt from dependencies  (#11810)

* Base script to generate requirements

Dymanically picks dependency for LanguageM Comp.
Requires separate change to remove eager loading.

* Lazy load imports for language model component

Ensures that only the necessary dependencies are required.
For example, if OpenAI provider is used, it will now only
import langchain_openai, rather than requiring langchain_anthropic,
langchain_ibm, etc.

* Add backwards-compat functions

* [autofix.ci] apply automated fixes

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

* Add exception handling

* Add CLI command to create reqs

* correctly exclude langchain imports

* Add versions to reqs

* dynamically resolve provider imports for language model comp

* Lazy load imports for reqs, some ruff fixes

* Add dynamic resolves for embedding model comp

* Add install hints

* Add missing provider tests; add warnings in reqs script

* Add a few warnings and fix install hint

* update comments add logging

* Package hints, warnings, comments, tests

* [autofix.ci] apply automated fixes

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

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

* Add alias for watsonx

* Fix anthropic for basic prompt, azure mapping

* [autofix.ci] apply automated fixes

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

* ruff

* [autofix.ci] apply automated fixes

* test formatting

* ruff

* [autofix.ci] apply automated fixes

---------



* fix: add handle to file input to be able to receive text (#11825)

* changed base file and file components to support muitiple files and files from messages

* update component index

* update input file component to clear value and show placeholder

* updated starter projects

* [autofix.ci] apply automated fixes

* updated base file, file and video file to share robust file verification method

* updated component index

* updated templates

* fix whitespaces

* [autofix.ci] apply automated fixes

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

* add file upload test for files fed through the handle

* [autofix.ci] apply automated fixes

* added tests and fixed things pointed out by revies

* update component index

* fixed test

* ruff fixes

* Update component_index.json

* [autofix.ci] apply automated fixes

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

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

* updated component index

* updated component index

* removed handle from file input

* Added functionality to use multiple files on the File Path, and to allow files on the langflow file system.

* [autofix.ci] apply automated fixes

* fixed lfx test

* build component index

---------





* docs: Add AGENTS.md development guide (#11922)

* add AGENTS.md rule to project

* change to agents-example

* remove agents.md

* add example description

* chore: address cris I1 comment

address cris I1 comment

* chore: address cris I5

address cris I5

* chore: address cris I6

address cris I6

* chore: address cris R7

address cris R7

* fix testcase

* chore: address cris R2

address cris R2

* restructure insight page into sidenav

* added header and total run node

* restructing branch

* chore: address gab otel model changes

address gab otel model changes will need no migration tables

* chore: update alembic migration tables

update alembic migration tables after model changes

* add empty state for gropu sessions

* remove invalid mock

* test: update and add backend tests

update and add backend tests

* chore: address backend code rabbit comments

address backend code rabbit comments

* chore: address code rabbit frontend comments

address code rabbit frontend comments

* chore: test_native_tracer minor fix address c1

test_native_tracer minor fix address c1

* chore: address C2 + C3

address C2 + C3

* chore: address H1-H5

address H1-H5

* test: update test_native_tracer

update test_native_tracer

* fixes

* chore: address M2

address m2

* chore: address M1

address M1

* dry changes, factorization

* chore: fix 422 spam and clean comments

fix 422 spam and clean comments

* chore: address M12

address M12

* chore: address M3
 address M3

* chore: address M4

address M4

* chore: address M5

address M5

* chore: clean up for M7, M9, M11

clean up for M7, M9, M11

* chore: address L2,L4,L5,L6 + any test

address L2,L4,L5 and L6 + any test

* chore: alembic + comment clean up

alembic + comment clean up

* chore: remove depricated test_traces file

remove depricated test_traces file. test have all been moved to test_traces_api.py

* fix datetime

* chore: fix test_trace_api ge=0 is allowed now

fix test_trace_api ge=0 is allowed now

* chore: remove unused traces cost flow

remove unused traces cost flow

* fix traces test

* fix traces test

* fix traces test

* fix traces test

* fix traces test

* chore: address gabriels otel coment

address gabriels otel coment latest

---------

Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>
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: Ram Gopal Srikar Katakam <44802869+RamGopalSrikar@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: olayinkaadelakun <olayinka.adelakun@ibm.com>
Co-authored-by: Jordan Frazier <122494242+jordanrfrazier@users.noreply.github.com>
Co-authored-by: cristhianzl <cristhian.lousa@gmail.com>
Co-authored-by: Hamza Rashid <74062092+HzaRashid@users.noreply.github.com>
Co-authored-by: Mendon Kissling <59585235+mendonk@users.noreply.github.com>
Co-authored-by: Lucas Oliveira <62335616+lucaseduoli@users.noreply.github.com>
Co-authored-by: Edwin Jose <edwin.jose@datastax.com>
Co-authored-by: Himavarsha <40851462+HimavarshaVS@users.noreply.github.com>

* fix(test): Fix superuser timeout test errors by replacing heavy clien… (#11982)

fix(test): Fix superuser timeout test errors by replacing heavy client fixture                                                    (#11972)

* fix super user timeout test error

* fix fixture db test

* remove canary test

* [autofix.ci] apply automated fixes

* flaky test

---------

Co-authored-by: Cristhian Zanforlin Lousa <cristhian.lousa@gmail.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* refactor(components): Replace eager import with lazy loading in agentics module  (#11974)

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

* fix: add ondelete=CASCADE to TraceBase.flow_id to match migration (#12002)

* fix: add ondelete=CASCADE to TraceBase.flow_id to match migration

The migration file creates the trace table's flow_id foreign key with
ondelete="CASCADE", but the model was missing this parameter. This
mismatch caused the migration validator to block startup.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: add defensive migration to ensure trace.flow_id has CASCADE

Adds a migration that ensures the trace.flow_id foreign key has
ondelete=CASCADE. While the original migration already creates it
with CASCADE, this provides a safety net for any databases that may
have gotten into an inconsistent state.

* fix: dynamically find FK constraint name in migration

The original migration did not name the FK constraint, so it gets an
auto-generated name that varies by database. This fix queries the
database to find the actual constraint name before dropping it.

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* fix: LE-456 - Update ButtonSendWrapper to handle building state and improve button functionality (#12000)

* fix: Update ButtonSendWrapper to handle building state and improve button functionality

* fix(frontend): rename stop button title to avoid Playwright selector conflict

The "Stop building" title caused getByRole('button', { name: 'Stop' })
to match two elements, breaking Playwright tests in shards 19, 20, 22, 25.

Renamed to "Cancel" to avoid the collision with the no-input stop button.

* Fix: pydantic fail because output is list, instead of a dict (#11987)

pydantic fail because output is list, instead of a dict

Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>

* refactor: Update guardrails icons (#12016)

* Update guardrails.py

Changing the heuristic threshold icons.

The field was using the default icons. I added icons related to the security theme.

* [autofix.ci] apply automated fixes

---------

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

* feat: Clean up the modelinput unification

* [autofix.ci] apply automated fixes

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

* Update test_embedding_model_component.py

* [autofix.ci] apply automated fixes

* Revert to main for other files

* More reversions

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

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

* [autofix.ci] apply automated fixes

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

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

* [autofix.ci] apply automated fixes

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

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

* Handle first run more elegantly in astra

* [autofix.ci] apply automated fixes

* Fix knowledge embedding dialog (#12071)

* fix: Handle message inputs when ingesting knowledge

* [autofix.ci] apply automated fixes

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

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

* Update test_ingestion.py

* [autofix.ci] apply automated fixes

* fix: Unify the knowledge creation model selector

* Revert tracing

* Update ingestion.py

* Rebuild comp index

* [autofix.ci] apply automated fixes

* Update test_ingestion.py

* [autofix.ci] apply automated fixes

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

* Update test_ingestion.py

* Update component_index.json

* [autofix.ci] apply automated fixes

---------

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

* [autofix.ci] apply automated fixes

* Update comp index

* Update test_astradb_base_component.py

* Update Knowledge Ingestion.json

* [autofix.ci] apply automated fixes

* Fix broken tests

* Cleanup from claude

* [autofix.ci] apply automated fixes

* Fix failing tests

* Update test_unified_models.py

* [autofix.ci] apply automated fixes

* Update Nvidia Remix.json

* Refactor ingest

* Rebuild templates and component index

* Fix test

* [autofix.ci] apply automated fixes

* Update component_index.json

* [autofix.ci] apply automated fixes

* test: add update_build_config visibility tests and PR review fixes (#12114)

- Add update_build_config field-visibility tests to LanguageModelComponent,
  ToolCallingAgentComponent, and BatchRunComponent covering Ollama, WatsonX,
  OpenAI, and no-model-selected cases
- Remove 16 stale @pytest.mark.skip tests from test_agent_component.py
- Wire up validate_model_selection in agent.py for early input validation
- Document AstraDB intentional use of lower-level update_model_options_in_build_config
- Clarify model_kwargs info text to note provider-specific support

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* Update embedding_model.py

* fix: address PR review recommendations for feat-unify-models++ (#12116)

- Fix 9 skipped tests in test_batch_run_component.py by replacing model
  list with _MockLLM instances, following the existing pattern used by
  test_with_config_failure_handling
- Fix test_agent_component.py: set component.model to a valid list before
  calling get_agent_requirements() in the three max_tokens tests, since
  validate_model_selection now requires a list-format model
- Replace os.environ direct reads in apply_provider_variable_config_to_build_config
  with get_all_variables_for_provider() (DB-first, env fallback), and pass
  user_id through from handle_model_input_update
- Add deprecated stubs for update_provider_fields_visibility, _update_watsonx_fields,
  and _update_ollama_fields in model_config.py with DeprecationWarning pointing
  to handle_model_input_update
- Fix typo: "deault" -> "default" in structured_output.py TODO comment
- Add 4 new KnowledgeIngestionComponent tests: new-format model_selection
  metadata path, allow_duplicates=True, missing metadata file error, and
  _build_embedding_metadata without API key

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* Ruff errors

* Update test_ingestion.py

* Update component index

* Test updates

* Update component_index.json

* Update stable_hash_history.json

* Template updates

* Update batch_run.py

* [autofix.ci] apply automated fixes

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

* Update Youtube Analysis.json

* Fix tests

* [autofix.ci] apply automated fixes

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

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

* Some cleanup and refactoring

* [autofix.ci] apply automated fixes

* Update Nvidia Remix.json

* Update Nvidia Remix.json

* Update unified_models.py

* Coderabbit AI review comments

* Component index update

* [autofix.ci] apply automated fixes

* Template updates

* [autofix.ci] apply automated fixes

* Template update

* [autofix.ci] apply automated fixes

* Review comments addressed

* [autofix.ci] apply automated fixes

* Update component_index.json

* Update stable_hash_history.json

* [autofix.ci] apply automated fixes

* Test updates

* Update test_ingestion.py

* Update test_ingestion.py

* Update test_ingestion.py

* [autofix.ci] apply automated fixes

* More clear tooltip text

* [autofix.ci] apply automated fixes

* Template updates

* Index and templates

* [autofix.ci] apply automated fixes

* Fix lambda build

* Template updates

* Rebuild comp index

* [autofix.ci] apply automated fixes

* Fix templates

* Fix failing test

* Update templates

* Update comp index

* [autofix.ci] apply automated fixes

* API key field in astra db

* Update starter

* Update comp index

* Starter proj update

* Add api key to field order

* Update test_unified_models.py

* Update test_unified_models.py

* [autofix.ci] apply automated fixes

* Update setup.py

* Update setup.py

* Update component_index.json

* [autofix.ci] apply automated fixes

* Return embedding models directly in KB

* [autofix.ci] apply automated fixes

* Update component_index.json

* fix: Refactor the unified models code

* Ruff checks

* Update flow_preparation.py

* [autofix.ci] apply automated fixes

* Update test_language_model_component.py

* fix: prevent overwriting user-selected global variables in provider c… (#12217)

* fix: nightly now properly gets 1.9.0 branch (#12215)

before it was attempting to pull release-notes as letters are alphanumerically after numbers when we sort -V then grab tail
now we only look at branch names that follow the pattern '^release-[0-9]+\.[0-9]+\.[0-9]+$'

* docs: add search icon (#12216)

add-back-svg

* fix: prevent overwriting user-selected global variables in provider config

Previously, the apply_provider_variable_config_to_build_config function would
automatically overwrite field values with environment variable keys whenever
an env var was present, even if the user had already selected a different
global variable.

This fix adds a check to only auto-set the environment variable if:
- The field is currently empty, OR
- The field is not already configured to load from the database

This preserves user selections while still providing automatic configuration
for new/empty fields.

Added comprehensive unit tests to verify:
- Auto-setting env vars for empty fields
- Preserving user-selected global variables
- Overwriting hardcoded values (expected behavior)
- Skipping when env var is not set
- Applying component metadata correctly

* [autofix.ci] apply automated fixes

* style: use dictionary comprehension instead of for-loop

Fixed PERF403 Ruff style warning by replacing for-loop with dictionary
comprehension in update_projects_components_with_latest_component_versions

* chore: retrigger CI build

* test: improve test coverage and clarity for provider config

- Renamed test_apply_provider_config_overwrites_hardcoded_value to
  test_apply_provider_config_replaces_hardcoded_with_env_var for clarity
- Added test_apply_provider_config_idempotent_when_already_set to document
  idempotent behavior when value already matches env var key
- Removed sensitive value from debug log message to prevent potential
  exposure of API keys or credentials

These changes improve test coverage by documenting the no-op scenario
and enhance security by avoiding logging of potentially sensitive data.

* chore: retrigger CI build

---------

Co-authored-by: Adam-Aghili <149833988+Adam-Aghili@users.noreply.github.com>
Co-authored-by: Mendon Kissling <59585235+mendonk@users.noreply.github.com>
Co-authored-by: Steve Haertel <shaertel@ca.ibm.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Eric Hare <ericrhare@gmail.com>

* Update build_config.py

* [autofix.ci] apply automated fixes

* Update build_config.py

* Fix tests

* fix: Dropdown issue with field population

* Update test_unified_models.py

* Clean up key config

* [autofix.ci] apply automated fixes

* fix tests

* Fix tests

* fix: Update tests

* Update tests

* Update test_tool_calling_agent.py

* Update test_unified_models.py

* Update test_tool_calling_agent.py

* Update tests

* Google AI generative embeddings fixes

* [autofix.ci] apply automated fixes

* Merge release branch

* Template update

* Merge release branch

* [autofix.ci] apply automated fixes

* Update openai_constants.py

* Update openai_constants.py

---------

Co-authored-by: Adam-Aghili <149833988+Adam-Aghili@users.noreply.github.com>
Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@logspace.ai>
Co-authored-by: keval shah <kevalvirat@gmail.com>
Co-authored-by: Antônio Alexandre Borges Lima <104531655+AntonioABLima@users.noreply.github.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: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com>
Co-authored-by: Ram Gopal Srikar Katakam <44802869+RamGopalSrikar@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: olayinkaadelakun <olayinka.adelakun@ibm.com>
Co-authored-by: Jordan Frazier <122494242+jordanrfrazier@users.noreply.github.com>
Co-authored-by: cristhianzl <cristhian.lousa@gmail.com>
Co-authored-by: Hamza Rashid <74062092+HzaRashid@users.noreply.github.com>
Co-authored-by: Mendon Kissling <59585235+mendonk@users.noreply.github.com>
Co-authored-by: Lucas Oliveira <62335616+lucaseduoli@users.noreply.github.com>
Co-authored-by: Edwin Jose <edwin.jose@datastax.com>
Co-authored-by: Himavarsha <40851462+HimavarshaVS@users.noreply.github.com>
Co-authored-by: Viktor Avelino <64113566+viktoravelino@users.noreply.github.com>
Co-authored-by: Lucas Democh <ldgoularte@gmail.com>
Co-authored-by: Steve Haertel <stevehaertel@users.noreply.github.com>
Co-authored-by: Steve Haertel <shaertel@ca.ibm.com>

* fix: Wait for dynamic model fetch in Nvidia (#12229)

* fix: Wait for dynamic model fetch in Nvidia

* [autofix.ci] apply automated fixes

* Create test_nvidia_component.py

* Update test_nvidia_component.py

* [autofix.ci] apply automated fixes

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* [autofix.ci] apply automated fixes

* Update test_nvidia_component.py

* Update component_index.json

* [autofix.ci] apply automated fixes

---------

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

* fix: protect image downloads by flow ownership (#12234)

* fix: protect image downloads by flow ownership

* test: add clarifying comments for image access review

---------

Co-authored-by: Janardan Singh Kavia <janardankavia@ibm.com>

* feat: Add Windows Playwright test fixes to RC (#12265)

* feat: Add Windows Playwright tests to nightly builds

- Add windows-latest to typescript_test.yml runner options
- Add shell: bash to all script steps for cross-platform compatibility
- Split Playwright installation into OS-aware steps (Linux uses --with-deps, Windows/macOS/self-hosted don't)
- Fix artifact naming with OS prefix to prevent conflicts: blob-report-${{ runner.os }}-${{ matrix.shardIndex }}
- Split frontend-tests into separate Linux and Windows jobs in nightly_build.yml
- Add ref parameter to all test jobs to checkout code from release branch
- Add resolve-release-branch to needs dependencies
- Update Slack notifications to handle both Linux and Windows test results
- Windows tests are non-blocking (not checked in release-nightly-build condition)
- Update .secrets.baseline with new line number (263 -> 347) for LANGFLOW_ENG_SLACK_WEBHOOK_URL

Fixes LE-566

* fix: Use contains() for self-hosted runner detection

- Replace exact string equality (==, !=) with contains() for substring matching
- Fixes issue when inputs.runs-on is array format: '["self-hosted", "linux", "ARM64", ...]'
- Ensures self-hosted Linux runners correctly skip --with-deps flag

Addresses CodeRabbit feedback on PR #12264

* fix: Sanitize folder names for CodeQL (#12263)

* fix(deps): pin tar-fs to >=2.1.4 to fix symlink following vulnerability (#12078)

Adds override for tar-fs in package.json to ensure versions prior to
2.1.4 are never resolved. Addresses CVE in tar-fs <2.1.4 (PVR0686558)
where symlink validation bypass was possible with a crafted tarball.

* fix: Rebuild the embedding model in the nv template (#12275)

* fix: support ZIP file upload for flows and projects endpoints (#12253)

* feat: support ZIP file upload for flows and projects endpoints

Add ZIP upload support to both /flows/upload/ and /projects/upload/
endpoints, enabling round-trip download-then-upload workflows. Extract
shared ZIP parsing logic into a dedicated utility with zip bomb
protections (entry count and file size limits). Fix batch flow name
deduplication to avoid infinite loops and DB collisions. Add tests for
ZIP upload, empty ZIP rejection, and download-upload round-trip.

* fix: add type annotation to satisfy mypy union narrowing

* fix: address PR review for ZIP upload (#12253)

- Add BadZipFile handling in extract_flows_from_zip for defense-in-depth
- Wrap blocking Z…

* add OpenDsStar 1.0.20 dependency and update uv.lock

Add OpenDsStar==1.0.20 to both backend and lfx pyproject.toml.
Regenerate uv.lock to include OpenDsStar and its transitive deps.

* [autofix.ci] apply automated fixes

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

* fix ruff lint errors in codeagents, file ingestion tests, and inspect script

* fix lfx tests: mock subprocess.Popen instead of subprocess.run

The FileDescriptionGenerator uses subprocess.Popen, not subprocess.run.
Tests were mocking the wrong function, causing real subprocess execution
that failed with ModuleNotFoundError for OpenDsStar in isolated lfx env.

* [autofix.ci] apply automated fixes

* fix lfx test mock data to match expected subprocess output format

Subprocess returns {"results": [...], "failed": [], "total": N},
not a bare list. Tests now use _wrap_results() helper.

* bump OpenDsStar to 1.0.21 to fix litellm dependency conflict

* fix tools metadata merge to preserve user-edited descriptions, remove orphan submodule

- Preserve user-edited description and display_description in tools
  metadata merge (fixes edit-tools Playwright test)
- Remove orphaned OpenDsStar-fork submodule entry that caused CI
  post-cleanup warnings

* smart tools description merge: update from code unless user customized

Compare old description to display_description — if they match, the user
never edited it and we update from code (picking up new Output.info
descriptions). If they differ, the user customized it and we preserve
their edit.

* [autofix.ci] apply automated fixes

* address CodeRabbit review: fix 4 major and 9 minor issues

Major fixes:
- Chroma: only suggest persist_directory when not in server mode
- FileContentRetriever: new input overwrites stale persisted data
- FileContentRetriever: preserve file_path on returned Message
- FileDescriptionGenerator: drain pipes in non-select fallback to prevent deadlock

Minor fixes:
- inspect_chroma_db: align docstring with actual 2000-char truncation
- test_file_content_retriever: fix empty/misplaced test functions
- test_file_description_generator: align duplicate paths test with actual behavior
- format.ts: fix NODE prefix regex pattern
- open_ds_star_agent: use get_running_loop(), remove duplicate cast import
- codeact_agent_smolagents: document timeout behavior, simplify import fallback

* bump OpenDsStar to 1.0.22

* Write File: make agent-friendly with tool_mode inputs, format control, and flexible input types

- Add tool_mode to input field (DataFrameInput) so agents can pass content directly
- Add file_format tool_mode input so agents can choose output format (csv, json, etc.)
- Handle raw pandas DataFrames from code agents (auto-wrap to Langflow DataFrame)
- Handle string inputs from chat agents (JSON → DataFrame, plain text → Message)
- Improve descriptions for agent discoverability
- Bump OpenDsStar to 1.0.24 (async tool invocation fix)
- Add 9 new tests covering all new features

* Write File: hide format dropdowns in tool mode, improve descriptions

- Hide local_format/aws_format/gdrive_format when tool_mode is active
- Agent uses unified file_format input instead
- Shorten field descriptions to pass ruff line length checks

* fix: add file_format field to News Aggregator starter project

The SaveToFile component now has a file_format input — update the
starter project template so field_order matches the component definition.
Update secrets baseline hash for shifted line.

* [autofix.ci] apply automated fixes

* rename Structured Data Agent starter project to Structured Data Analysis Agent

* fix: regenerate starter projects to include file_format field in SaveToFile node

The SaveToFileComponent added a new file_format input but the starter
project JSONs were not regenerated, causing field_order mismatches in
both Structured Data Analysis Agent and News Aggregator starter projects.

* feat: add html as a supported file format in SaveToFileComponent

Add html to LOCAL_MESSAGE_FORMAT_CHOICES, GDRIVE_FORMAT_CHOICES, and
the _save_message handler (reuses the txt write path). AWS already
supported html. Update the file_format tool-mode description to
include html.

* test: add test for saving Message as html format

* fix: regenerate starter projects after adding html format to SaveToFileComponent

* [autofix.ci] apply automated fixes

* fix(tests): skip assistant panel e2e test when OPENAI_API_KEY is missing

Without a configured model provider the assistant panel renders a
"no models" state instead of the input textarea and model selector,
causing the test to fail in CI environments without API keys.

* fix: add file_format field to SaveToFile in starter projects

The autofix bot incorrectly removed the file_format entry. Re-add it
to both field_order and template in News Aggregator and Structured
Data Analysis Agent starter projects. Update secrets baseline.

* fix: rebuild component index to include file_format in SaveToFile

The CI autofix kept removing file_format from starter projects because
the prebuilt component_index.json lacked the field. The update script
loads components from this index in production mode, so it regenerated
starter projects without file_format. Rebuild the index so it includes
the file_format input, which makes the autofix a no-op.

* fix: hide format dropdowns in SaveToFile when used as tool

The storage_location handler in update_build_config was showing format
dropdowns regardless of tool mode. Now it checks tools_metadata to
detect tool mode and keeps format dropdowns hidden, since the agent
uses the unified file_format string input instead.

* fix: remove debug script and replace stderr debug logging with proper logger

Remove scripts/inspect_chroma_db.py (debugging script). Replace all
_dbg() stderr writes in FileDescriptionGeneratorComponent with
standard logger calls at appropriate levels (debug/warning/info).

* fix: avoid double agent execution in OpenDsStarAgentRunnable.astream

astream was calling ainvoke after fully consuming the stream, which
re-executed the entire graph. Use the last streamed chunk as the final
result instead.

* fix: address PR review feedback from ogabrielluiz

- Mirror positional-to-kwargs mapping in async tool path (component_tool.py)
- Add final_answer guard to timeout suppression (codeact_agent_smolagents.py)
- Extract _build_graph_input() helper to deduplicate state dict x4 (open_ds_star_agent.py)
- Split ImportError from other exceptions in set_main_event_loop (open_ds_star_agent.py)
- Add sys.platform != 'win32' guard for select() on pipes (file_description_generator.py)
- Move ChromaError import before try block (chroma.py)
- Add logger.warning to __deepcopy__ fallback paths (component.py)
- Change accumulate_usage from additive to max-based merge (token_usage.py)
- Add async positional-arg test and update token usage tests

* increase opendsstar to 1.0.25 to fix pydantic dependency conflict

* vector stores: remove tool_mode=True for as_dataframe output

* increase OpenDsStar to 1.0.26

---------

Co-authored-by: Gal-Bloch <gal.bloch@ibm.com>
Co-authored-by: Eric Hare <ericrhare@gmail.com>
Co-authored-by: Jordan Frazier <122494242+jordanrfrazier@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Hamza Rashid <74062092+HzaRashid@users.noreply.github.com>
Co-authored-by: Viktor Avelino <64113566+viktoravelino@users.noreply.github.com>
Co-authored-by: Cristhian Zanforlin Lousa <cristhian.lousa@gmail.com>
Co-authored-by: Antônio Alexandre Borges Lima <104531655+AntonioABLima@users.noreply.github.com>
Co-authored-by: DeyLak <DeyLak@users.noreply.github.com>
Co-authored-by: Adam Aghili <Adam.Aghili@ibm.com>
Co-authored-by: Jordan Frazier <jordan.frazier@datastax.com>
Co-authored-by: Adam-Aghili <149833988+Adam-Aghili@users.noreply.github.com>
Co-authored-by: Florian Schüller <schuellerf@users.noreply.github.com>
Co-authored-by: Steve Haertel <stevehaertel@users.noreply.github.com>
Co-authored-by: Mendon Kissling <59585235+mendonk@users.noreply.github.com>
Co-authored-by: Steve Haertel <shaertel@ca.ibm.com>
Co-authored-by: Mateusz Szewczyk <139469471+MateuszOssGit@users.noreply.github.com>
Co-authored-by: Debojit Kaushik <Kaushik.debojit@gmail.com>
Co-authored-by: Janardan Singh Kavia <janardankavia@ibm.com>
Co-authored-by: Janardan S Kavia <janardanskavia@Janardans-MacBook-Pro.local>
Co-authored-by: vjgit96 <vijay.katuri@ibm.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@logspace.ai>
Co-authored-by: Harold Ship <harold.ship@gmail.com>
Co-authored-by: codeflash-ai[bot] <148906541+codeflash-ai[bot]@users.noreply.github.com>
Co-authored-by: keval shah <kevalvirat@gmail.com>
Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>
Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com>
Co-authored-by: Ram Gopal Srikar Katakam <44802869+RamGopalSrikar@users.noreply.github.com>
Co-authored-by: olayinkaadelakun <olayinka.adelakun@ibm.com>
Co-authored-by: Lucas Oliveira <62335616+lucaseduoli@users.noreply.github.com>
Co-authored-by: Edwin Jose <edwin.jose@datastax.com>
Co-authored-by: Himavarsha <40851462+HimavarshaVS@users.noreply.github.com>
Co-authored-by: Lucas Democh <ldgoularte@gmail.com>
Co-authored-by: Anderson Filho <115162146+andifilhohub@users.noreply.github.com>
Co-authored-by: April I. Murphy <36110273+aimurphy@users.noreply.github.com>
Co-authored-by: himavarshagoutham <himavarshajan17@gmail.com>
Co-authored-by: Viktor Avelino <viktor.avelino@gmail.com>
Co-authored-by: Hamza Rashid <hzarashid@gmail.com>
Co-authored-by: Rodrigo Nader <rodrigonader@MacBook-Pro-de-Rodrigo.local>
Co-authored-by: ogabrielluiz <gabriel@langflow.org>
Co-authored-by: Tarcio <rodriguestarcio.adv@gmail.com>
Co-authored-by: Carlos Coelho <80289056+carlosrcoelho@users.noreply.github.com>
Co-authored-by: Alfio Gliozzo <54385608+gliozzo@users.noreply.github.com>
Co-authored-by: Alfio Gliozzo <gliozzo@us.ibm.com>
Co-authored-by: OpenAI Codex <noreply@openai.com>
Co-authored-by: manav2000 <manav2000@users.noreply.github.com>
Co-authored-by: Deon Sanchez <69873175+deon-sanchez@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: DAVID BOAZ <DAVIDBO@il.ibm.com>
Co-authored-by: Arek Mateusiak <severfire@users.noreply.github.com>
Co-authored-by: DevByteAI <abud6673@gmail.com>
Co-authored-by: Alice Reis <alicemarianareis@gmail.com>
Co-authored-by: Alex Kuligowski <alekuligowski@gmail.com>
Co-authored-by: a-effort <35465683+a-effort@users.noreply.github.com>
2026-05-10 13:54:13 +00:00
eb5f83f950 fix: pin postgres image to bookworm in docker_example (#13027)
* fix: pin postgres image to bookworm in docker_example to prevent collation mismatch

The postgres:16 tag silently moved its base from Debian Bookworm
(glibc 2.36) to Trixie (glibc 2.41), causing a recurring collation
version mismatch warning on existing langflow-postgres volumes.

Pin to postgres:16-bookworm in both docker-compose files and update
the README so existing data volumes keep matching the OS locale data.

Refs: https://github.com/langflow-ai/langflow/issues/9608

* docs: pin postgres image to bookworm in current docs compose snippets

Mirror the docker_example pin in the four current docs that publish
copyable Compose snippets pairing postgres:16 with a persistent
langflow-postgres volume. Prevents the same Bookworm-to-Trixie
collation version mismatch warning when users follow docs instead
of docker_example.

Versioned historical docs are left as-is.

Refs: https://github.com/langflow-ai/langflow/issues/9608

* fix: switch postgres pin from bookworm to trixie for OS consistency

Aligns the pinned postgres base with the langflow runtime image, which
moved to Debian Trixie in #12990. Keeping postgres on bookworm would
have diverged the stack and locked the database to an aging glibc that
will receive fewer security backports as bookworm ages into oldstable.

The pin itself still solves the original bug — postgres:16 cannot
silently roll its OS underneath an existing volume.

Document the one-time REFRESH COLLATION VERSION step for users
upgrading from a bookworm-initialized volume in docker_example/README.md.

Refs: https://github.com/langflow-ai/langflow/issues/9608
(cherry picked from commit 7504eb4c72)
2026-05-07 19:39:49 +00:00
7504eb4c72 fix: pin postgres image to bookworm in docker_example (#13027)
* fix: pin postgres image to bookworm in docker_example to prevent collation mismatch

The postgres:16 tag silently moved its base from Debian Bookworm
(glibc 2.36) to Trixie (glibc 2.41), causing a recurring collation
version mismatch warning on existing langflow-postgres volumes.

Pin to postgres:16-bookworm in both docker-compose files and update
the README so existing data volumes keep matching the OS locale data.

Refs: https://github.com/langflow-ai/langflow/issues/9608

* docs: pin postgres image to bookworm in current docs compose snippets

Mirror the docker_example pin in the four current docs that publish
copyable Compose snippets pairing postgres:16 with a persistent
langflow-postgres volume. Prevents the same Bookworm-to-Trixie
collation version mismatch warning when users follow docs instead
of docker_example.

Versioned historical docs are left as-is.

Refs: https://github.com/langflow-ai/langflow/issues/9608

* fix: switch postgres pin from bookworm to trixie for OS consistency

Aligns the pinned postgres base with the langflow runtime image, which
moved to Debian Trixie in #12990. Keeping postgres on bookworm would
have diverged the stack and locked the database to an aging glibc that
will receive fewer security backports as bookworm ages into oldstable.

The pin itself still solves the original bug — postgres:16 cannot
silently roll its OS underneath an existing volume.

Document the one-time REFRESH COLLATION VERSION step for users
upgrading from a bookworm-initialized volume in docker_example/README.md.

Refs: https://github.com/langflow-ai/langflow/issues/9608
2026-05-07 19:39:49 +00:00
78f82cae32 perf: Enhance Gunicorn preload functionality for Langflow (#12778)
* perf: Enhance Gunicorn preload functionality for Langflow

- Introduced a new preload module to optimize memory usage by running fork-safe initialization in the Gunicorn master process.
- Updated the lifespan management in `main.py` to check if the master has preloaded resources, allowing workers to inherit state and skip redundant setup.
- Adjusted the server loading process to accommodate the new preload logic, ensuring efficient resource management across worker processes.

* feat(cache): Implement teardown method for RedisCache to prevent socket leaks

- Added a `teardown` method to the `RedisCache` class to close the Redis connection, addressing potential socket leaks during process forking.
- Introduced unit tests to verify the functionality of the `teardown` method, ensuring it handles client closure and errors gracefully.
- Tests cover scenarios including normal closure, error handling during closure, and teardown with URL-based connections.

* feat(cache): Implement teardown method in RedisCache to prevent socket leaks

- Added a `teardown` method to the `RedisCache` class, ensuring proper closure of the Redis client connection before forking to avoid socket leaks.
- Created comprehensive unit tests to validate the functionality of the `teardown` method, covering various scenarios including normal operation and error handling.
- Updated existing tests to reflect the new teardown functionality and ensure RedisCache is recognized as an instance of `ExternalAsyncBaseCacheService`.

* refactor(preload): Simplify DB engine disposal logic in master preload

- Removed exception handling around the DB engine disposal to streamline the process, ensuring that the engine is disposed of without unnecessary error logging. This change enhances code clarity and maintains the intended functionality of resource management during the preload phase.

* refactor(preload): Streamline cache service teardown logic

- Simplified the cache service socket closure process in the master preload function to prevent sharing across forks. This change enhances code clarity by removing unnecessary exception handling while maintaining the intended functionality of resource management during the preload phase.

* feat(preload): Introduce per-step completion flags for improved state management

- Added completion flags in the preload state to track the status of various initialization steps, including profile picture copying, starter project creation, agentic global variable initialization, MCP server configuration, and flow loading.
- Updated the lifespan management in `main.py` to utilize these flags, allowing the system to skip redundant setup tasks if they have already been completed during the preload phase.
- This enhancement improves resource management and ensures that the application behaves correctly in a multi-worker environment.

* refactor(lifespan): Replace temp dir management with get_owned_temp_dirs function

- Updated the lifespan management in `main.py` to utilize the new `get_owned_temp_dirs` function, which encapsulates the logic for determining temp directory ownership based on the process type (master or worker).
- Removed the `is_master` check from the lifespan function, simplifying the code and enhancing clarity regarding temp directory cleanup responsibilities.
- Added the `get_owned_temp_dirs` function in `preload.py` to centralize temp directory ownership logic, ensuring that workers do not attempt to clean up directories owned by the master process.

* refactor(lifespan): Enhance initialization flow with conditional gates

- Introduced conditional gates in the `get_lifespan` function to manage the initialization of profile pictures, super users, bundles, component types, and starter projects based on their completion status.
- Improved logging to provide clearer insights into which steps are being skipped or executed, enhancing the overall clarity of the initialization process.
- Updated the preload logic in `preload.py` to ensure that agentic global variables and MCP server configuration are only initialized when necessary, maintaining efficient resource management in a multi-worker environment.

* fix: resolve double-call of initialize_auto_login_default_superuser and add preload tests

- Fix double-call issue: setup_superuser() now handles AUTO_LOGIN completely with file lock
- Add comprehensive unit tests for preload.py covering failure-fallback contract
- Simplify code by doing superuser initialization in initialize_services() (called early in both preload and worker startup)
- File lock protects multi-worker race conditions when preload is disabled
- Tests verify critical step failures propagate, best-effort steps continue on failure

Made-with: Cursor

* fix(preload): resolve missing import and agentic initialization conflicts

Fixed critical bugs introduced in c0e81a5401 that caused preload failures:

1. Missing import: Added DEFAULT_SUPERUSER_PASSWORD to module-level imports
   - Was only imported inside AUTO_LOGIN block but used when AUTO_LOGIN=false
   - Caused NameError that crashed preload with "session scope error"

2. Removed agentic variable initialization from setup_superuser()
   - Prevents double-initialization conflict with preload's dedicated step
   - initialize_agentic_global_variables() in preload handles all users

3. Made teardown_superuser() more robust
   - Now skips deletion instead of raising errors on FK constraints
   - Prevents startup failures when default superuser has associated flows

Resolves: "An error occurred during the session scope" preload error
Resolves: Ghost thread warnings from incomplete initialization
Made-with: Cursor

* refactor(preload): Enhance state management and initialization logic

- Updated the `_PreloadState` class to include `bundles_loaded` and `types_cached` flags for better tracking of initialization steps.
- Modified the `get_lifespan` function to utilize the new state flags, improving the conditional logic for loading bundles and caching component types.
- Implemented a `reset` method in `_PreloadState` to ensure consistent state restoration after preload failures, enhancing reliability in multi-worker environments.
- Simplified the teardown process in `ExternalAsyncBaseCacheService` by making `teardown` an abstract method, allowing direct calls without fallback checks.

This refactor improves clarity and efficiency in the preload and lifespan management processes.

* refactor(lifespan): Improve component types caching and starter project creation logic

- Enhanced the `get_lifespan` function to utilize a local handle for component types when the cache is inherited, ensuring consistency in multi-worker environments.
- Added logging for scenarios where the component types cache is empty, allowing for cache rebuilding instead of skipping starter project creation.
- Streamlined the starter project creation process with improved error handling and logging, ensuring clarity on failures and skipped operations.

This refactor enhances the reliability and clarity of the initialization process in the application.

* fix(tests): Update teardown_superuser test to preserve default superuser if never logged

- Renamed the test function to clarify its purpose.
- Modified the test logic to ensure that the default superuser is not removed during teardown if it has never been logged in, preventing foreign key errors.
- Added assertions to verify that the superuser remains intact and its properties are correctly set after teardown.

This change enhances the reliability of the superuser management in the test suite.

* feat: Implement orphaned MCP server config migration and add unit tests

- Introduced `migrate_orphaned_mcp_servers_config` function to recover MCP server config files that become orphaned after a database reset while preserving the config directory.
- Added logic to handle scenarios with multiple orphaned files, ensuring safe migration and logging for manual recovery.
- Created comprehensive unit tests to validate the migration functionality, covering cases for single orphan recovery, multiple orphans, and scenarios with no orphans.
- Enhanced the setup of the superuser to include the migration process, improving the robustness of user configuration management.

This update enhances the application's ability to recover user configurations in containerized environments.

* fix(teardown): Improve superuser removal logic and error handling

- Updated the `teardown_superuser` function to remove the default superuser when AUTO_LOGIN is disabled and the user has never logged in, enhancing user management.
- Improved error handling to raise a `RuntimeError` if the removal fails, ensuring that issues are logged and not silently ignored.
- Adjusted the `DatabaseService` teardown process to reflect the updated superuser removal logic and ensure proper resource disposal.

This change enhances the reliability of the superuser management during application shutdown.

* fix(setup_superuser): Enhance error handling for AUTO_LOGIN timeout scenario

- Updated the `setup_superuser` function to provide clearer logging and error messages when the AUTO_LOGIN lock times out and no default superuser exists.
- Introduced a check to verify the existence of the default superuser in the database, raising a `RuntimeError` with a descriptive message if it is not found.
- Added unit tests to validate the behavior of the setup process under timeout conditions, ensuring that the application fails gracefully when required superuser credentials are missing.

This change improves the robustness of the superuser initialization process and enhances error visibility during startup.

* fix(preload): Update error handling to log exceptions with traceback for best-effort steps

- Modified the error handling in the `_run_master_preload` function to log exceptions with traceback instead of warnings for best-effort steps, ensuring better visibility into failures.
- Updated unit tests to reflect the change in logging behavior, verifying that exceptions are correctly logged during preload operations.

This change enhances the clarity of error reporting during the preload process, aiding in debugging and monitoring.

* fix(preload): Ensure cleanup of temporary directories during reset

- Updated the `reset` method in the `_PreloadState` class to call `cleanup()` on each `TemporaryDirectory` before clearing the `temp_dirs` list, preventing on-disk directory leaks during failed preloads.
- Added a unit test to verify that `cleanup()` is called for all temporary directories during the reset process, ensuring proper resource management.

This change enhances the reliability of the preload process by ensuring that temporary resources are properly cleaned up.

* refactor(preload): Introduce PreloadStep enumeration and streamline step completion logic

- Added a `PreloadStep` enumeration to define ordered preload phases, enhancing clarity and maintainability of the preload process.
- Replaced direct state attribute checks with the `is_step_complete` function to improve readability and encapsulate step completion logic.
- Updated the `_run_master_preload` function to utilize `mark_step_complete` for recording successful completion of preload steps, enforcing prerequisite ordering.
- Enhanced unit tests to validate the new step completion logic and ensure proper functionality of the preload process.

This refactor improves the structure and reliability of the preload mechanism, making it easier to manage and understand the initialization flow.

* refactor(superuser): Remove redundant checks for superuser credentials in setup functions

- Eliminated unnecessary validation for `DEFAULT_SUPERUSER` and `DEFAULT_SUPERUSER_PASSWORD` in both `initialize_auto_login_default_superuser` and `setup_superuser` functions, simplifying the initialization logic.
- This change streamlines the superuser setup process, assuming that the necessary credentials are managed externally, thus enhancing code clarity and maintainability.

* refactor(preload): Streamline error handling and step completion in preload process

- Introduced a `_best_effort` function to encapsulate error handling for preload steps, improving code readability and maintainability.
- Updated the `_run_master_preload` function to utilize the new error handling mechanism for various steps, ensuring consistent logging and state management.
- Enhanced the documentation in the preload module to clarify the handling of fork-unsafe resources and the overall preload process.

This refactor enhances the robustness and clarity of the preload mechanism, making it easier to manage and understand the initialization flow.

* refactor(preload): Enhance error handling and resource cleanup in preload process

- Wrapped post-initialization work in a try/finally block to ensure the DB engine and cache service are always disposed of, preventing resource leaks in forked workers.
- Updated logging to provide clearer visibility into the preload steps, including error handling for best-effort operations.
- Improved the structure of the `_run_master_preload` function by consolidating related operations and ensuring consistent cleanup.

This refactor enhances the robustness and clarity of the preload mechanism, ensuring safe resource management during initialization.

* [autofix.ci] apply automated fixes

* test(setup_superuser): remove default superuser before lock-timeout no-superuser case

The `initialized_services` fixture starts with `AUTO_LOGIN=false`, which
runs `setup_superuser` through the credentials-fallback path and creates
the default superuser. The "raises_when_no_superuser" test then mocked
the lock to time out, but the existence check found that pre-created
user and returned `AUTO_LOGIN_LOCK_TIMEOUT_SUPERUSER_PRESENT` instead of
raising `RuntimeError`. Delete the default superuser before mocking the
lock so the no-superuser branch is actually exercised.

---------

Co-authored-by: Jordan Frazier <jordan.frazier@datastax.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-05 21:49:11 +00:00
596e98b9b7 fix: Respect proxy environment variables in URL Component (#12989)
* fix: URLComponent ignores proxy in async mode (#12285)

The URLComponent fails to connect for users behind corporate proxies
because its asynchronous mode does not recognize standard system proxy
environment variables. The component defaults to use_async=True, which
initializes the RecursiveUrlLoader; the underlying async loader does
not natively respect system proxy environment variables, so the
component attempts a direct connection and fails in restricted network
environments.

Detect standard proxy environment variables (http_proxy, HTTP_PROXY,
https_proxy, HTTPS_PROXY) in URLComponent._create_loader. If a proxy
is detected and use_async is enabled, override use_async to False so
the loader uses its synchronous implementation, which natively
respects system proxies. Empty and whitespace-only values are
correctly evaluated as no-proxy and do not trigger the fallback.

Closes #10297

* fix(URLComponent): broaden proxy detection and harden tests

Address review findings on the proxy fix:

- Add ALL_PROXY and all_proxy to the detected env vars. ALL_PROXY is
  commonly set in corporate and container environments (curl, git,
  many Unix tools honour it), and is sometimes the only proxy var
  configured.
- Replace the unused proxy_url string with a single boolean any() over
  the env var keys, since only the presence of a proxy is consulted.
- Reorganize the proxy tests under TestURLComponentProxyHandling with
  a shared default-attributes helper, parametrize over all six env var
  spellings, and add coverage for multiple-simultaneous-proxies and
  the use_async=False path (which should not log a warning).

* [autofix.ci] apply automated fixes

* fix: remove no_proxy="*" macOS startup hack so corporate proxies work

Two startup paths set `os.environ["no_proxy"] = "*"` on macOS, which
disables proxy use for every HTTP client in the process and every child
gunicorn worker (httpx, requests, urllib3 — and therefore the OpenAI,
Anthropic, Groq, etc. SDKs that wrap them). For users behind corporate
proxies on macOS this made every external LLM call unroutable, even with
HTTPS_PROXY properly set.

The override traces to commit history with no concrete justification —
the only artifact is a Stack Overflow link about a uWSGI segfault, but
Langflow uses gunicorn, not uWSGI. Bench-verified that gunicorn boots
cleanly and serves requests on macOS without it (1 worker via
LangflowApplication, OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES retained,
HTTPS_PROXY survives intact in parent and child).

Verification:
  - gunicorn worker spawns and serves /health (200 OK), exits cleanly
  - httpx, urllib, requests all resolve HTTPS_PROXY after the macOS init
    (previously: all three returned empty proxy maps because of no_proxy=*)
  - OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES still set — the actual
    fork-safety fix is preserved

Closes the macOS half of #10297. Companion fix for the async URLComponent
half is in #12285 / branch pr-12285-rebased.

* [autofix.ci] apply automated fixes

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

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

* Orjson update

---------

Co-authored-by: Diogo Veiga <diogo.veiga@tecnico.ulisboa.pt>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-05-05 13:55:39 -07:00
6d2e255f5d Merge remote-tracking branch 'origin/release-1.9.2' into release-1.10.0
# Conflicts:
#	.secrets.baseline
#	pyproject.toml
#	src/backend/base/langflow/initial_setup/starter_projects/Knowledge Retrieval.json
#	src/backend/base/langflow/initial_setup/starter_projects/Vector Store RAG.json
#	src/backend/base/pyproject.toml
#	src/frontend/package-lock.json
#	src/frontend/package.json
#	src/lfx/pyproject.toml
#	src/lfx/src/lfx/_assets/component_index.json
#	src/sdk/pyproject.toml
#	uv.lock
2026-05-01 14:22:58 -07:00
af8cd0219e fix: pass Google embedding dimensions (#12876)
fix: pass google embedding dimensions
2026-04-28 23:02:33 +00:00
7a84f8b254 fix(mcp): enforce auth on /streamable for auth_type=oauth projects (#12756)
* fix(mcp): enforce authentication on /streamable for auth_type=oauth projects

Previously, projects configured with auth_type=oauth did not enforce
authentication on the /streamable (and /sse) endpoints when MCP Composer
was enabled. verify_project_auth only enforced API key authentication for
auth_type=apikey; for oauth it fell through to the superuser fallback,
returning HTTP 200 with full initialize/tools/list payloads to
unauthenticated requests.

This treats auth_type=oauth the same as auth_type=apikey on the direct
langflow MCP transport endpoints: requests must present a valid API key
or they are rejected with HTTP 401. End users of OAuth-configured
projects should continue to connect via the configured MCP Composer
OAuth endpoint (which proxies to these endpoints with backend
credentials).

* fix(mcp): preserve composer loopback forwarding on OAuth auth enforcement

Address review feedback on PR #12756. Requiring an API key for every OAuth
request would have broken the intended MCP Composer proxy path: the composer
subprocess is started with only the Langflow endpoint URL and OAuth env vars
and does not currently inject a backend x-api-key when it forwards
authenticated OAuth traffic, so hardening /streamable and /sse would turn
every legitimate composer-forwarded request into a 401.

Keep the enforcement against direct unauthenticated external access, but
trust requests whose direct TCP peer is a loopback address (the on-host
MCP Composer subprocess). Remote callers still need a valid x-api-key to
hit the project transport endpoints when auth_type=oauth.

Add coverage for the loopback passthrough and the _is_loopback_client
helper, and gate the rejection tests on a patched non-loopback client so
they exercise the remote path even though httpx AsyncClient reports
127.0.0.1 by default.

* fix(mcp): drop loopback trust shortcut; always require API key for OAuth transport

Follow-up to PR #12756. The loopback-based passthrough from the prior
commit is unsafe in deployments where Langflow sits behind a same-host
reverse proxy or sidecar: the proxy becomes the direct TCP peer, so
external unauthenticated traffic satisfies the loopback check and falls
through to the superuser, reopening the original bypass.

There is no composer-specific identity on the wire today — mcp-composer
forwards without any Langflow credential — so loopback address cannot
distinguish the trusted subprocess from another loopback peer. Require
a valid x-api-key on /streamable and /sse for every OAuth project
regardless of source. Until mcp-composer can forward a project-scoped
backend credential, the composer proxy path will return 401; this is
the intended secure behavior.

Remove the _is_loopback_client helper, the client_host plumbing into
verify_project_auth, and the associated tests. Drop the
force_non_loopback_client fixture; the rejection tests now exercise the
real code path directly.

* fix(mcp): clarify OAuth 401 detail about the current API-key requirement

The previous message asked callers to connect through MCP Composer, but
the composer proxy path currently returns 401 itself (see PR #12756
discussion) because mcp-composer cannot forward a backend credential
yet. Describe the actual working path — use an x-api-key — and note
that composer-based access is pending credential forwarding support.

* fix: No timeout when connect to oauth project

* Secrets baseline update

* fix: Standardize paths on Windows
2026-04-27 17:29:58 -07:00
fc7f6c4c6c fix: Handle videos with no comments in YouTube Comments component (#10633)
* fix: Handle videos with no comments in YouTube Comments component

- Define column order once to avoid code duplication
- Create empty DataFrame with proper schema when no comments exist
- Prevents KeyError when trying to reorder columns on empty DataFrame
- Returns consistent DataFrame structure regardless of comment count

* [autofix.ci] apply automated fixes

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

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

* [autofix.ci] apply automated fixes

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

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

* [autofix.ci] apply automated fixes

* Update component_index.json

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Eric Hare <ericrhare@gmail.com>
2026-04-24 03:56:09 +00:00
b9e81f6edd Merge remote-tracking branch 'origin/main' into release-1.10.0 2026-04-23 19:21:59 -07:00
0732423f27 chore: security patch (#12725)
* chore: security patch

security patch

* chore: upgrade package-lock.json

* chore: smolagents and transformer update

* chore: redis upgrade

* chore: litellm upgrade

* fix: Pin click to avoid lower versions

## Root cause

**litellm 1.83.5+** introduced an exact pin `click==8.1.8` in its `requires_dist` (upstream bug [BerriAI/litellm#26154](https://github.com/BerriAI/litellm/issues/26154) — "Pinning exact dependency versions breaks downstream consumers"). When this branch bumped litellm to 1.83.11, uv was forced to downgrade click from 8.3.2 → 8.1.8. Click 8.2+ captures stderr separately by default; 8.1 merges it — hence `ValueError: stderr not separately captured`.

## Fix

- [pyproject.toml:155](pyproject.toml:155) — added `"click>=8.3.0"` to `[tool.uv] override-dependencies` with comment linking the upstream issue.
- [src/backend/base/pyproject.toml:112](src/backend/base/pyproject.toml:112) — same override so `langflow-base` Docker builds pick it up too.
- Regenerated `uv.lock` (click: 8.1.8 → 8.3.3).
- Patched the `click` entry in `src/backend/base/uv.lock` to 8.3.3 (that lockfile is used by `docker/build_and_push_base.Dockerfile` via `uv sync --frozen`; uv treats backend/base as a workspace member so I updated its click block directly — no other references to 8.1.8 remain).
- Reverted [src/lfx/tests/unit/cli/test_run_real_flows.py](src/lfx/tests/unit/cli/test_run_real_flows.py) back to its original `result.stderr` usage — now passes cleanly with click 8.3.3.

All 19 tests in the file pass.

* Update build_and_push_backend.Dockerfile

The `uv pip install` command doesn't read `[tool.uv] override-dependencies` from the target packages' pyproject.toml — those overrides only apply during `uv lock`/`uv sync`. The fix is to pass the overrides explicitly via `--overrides`.

Now let me verify it works by running the same install locally.

Resolution succeeded — click==8.3.3, aiohttp==3.13.5, litellm==1.83.11 all coexist. Let me also test without `--overrides` to confirm I reproduce the original failure.

Reproduced the Docker failure locally. Now test with the overrides file:

Fix verified — resolution succeeds with the overrides file, failing without. Let me clean up and show the final Dockerfile change.

## Summary

**Root cause:** The Dockerfile uses `uv pip install ./src/...` which **does not read** `[tool.uv] override-dependencies` from the target packages' `pyproject.toml` — those overrides only apply during `uv lock`/`uv sync`. On Linux, `cuga>=0.2.20` requires `aiohttp>=3.13.5`, but `litellm==1.83.11` exact-pins `aiohttp==3.13.3` (same upstream bug as the click pin, [BerriAI/litellm#26154](https://github.com/BerriAI/litellm/issues/26154)). Without an active override, resolution fails.

**Fix:** Write a `/tmp/uv-overrides.txt` file mirroring the workspace's `override-dependencies` (litellm, python-dotenv, openai, aiohttp, click) and pass `--overrides /tmp/uv-overrides.txt` to `uv pip install`.

Verified locally by reproducing the exact failure in an isolated tmp directory (to escape the workspace's pyproject.toml auto-apply), then confirming the overrides file resolves it:
- aiohttp==3.13.5 ✓
- click==8.3.3 ✓
- litellm==1.83.11 ✓
- cuga==0.2.22 ✓

* Templates version update

* Update .secrets.baseline

* chore: update overrides

* chore: bump version

* chore: bump main version

* chore: bump SDK version to 0.1.1

* chore: run uv lock and uv sync after SDK version bump

* chore: read the overrides from a single source

security patch

* chore: add pip check toggle

add pip check toggle

* chore: litellm base uv.lock update

* fix(chore): Pin litellm back to last working release

* fix(chore): Pin to 1.83 and higher litellm

* Update build_and_push_backend.Dockerfile

* chore: update base uv.lock

* fix: lazyload toolguard since its an optional extra

* Update .secrets.baseline

* Update component_index.json

* Rebuild component index

* Update component_index.json

---------

Co-authored-by: Eric Hare <ericrhare@gmail.com>
Co-authored-by: vijay kumar katuri <vijay.katuri@ibm.com>
(cherry picked from commit 60a8f76c3fde17124057626c671ea8162872837a)
2026-04-23 17:49:53 -07:00
dbc87e7704 fix: db guards for deployments (#12339)
* checkout api handlers

* add missing table

* update to use "version" terminology for flows instead of outdated "history" verbage

* Fix provider account id mapping

* recover a little todo comment

* Add flow version migration and minor exception handling, etc

  1. deployments.py — Added AuthenticationError import + handling (401) in all 9 error handler blocks. Added update_deployment_db import + call to persist name changes to local DB after adapter update succeeds.
  2. flow_version/exceptions.py — Added FlowVersionDeployedError for blocking deletion of deployed versions.
  3. flow_version/crud.py —
    - Added has_deployment_attachments() helper that checks if a flow version has any deployment attachments
    - delete_flow_version_entry() now raises FlowVersionDeployedError if the version is attached to deployments
    - Pruning now excludes deployed versions via a NOT IN subquery on FlowVersionDeplottachment, preventing provider-side snapshot orphaning
  4. flow_version/__init__.py — Exports FlowVersionDeployedError
  5. flow_version.py (API route) — Imported FlowVersionDeployedError, added it to _translate_version_error as 409 Conflict
  6. models/__init__.py — Registered FlowVersionDeploymentAttachment for alembic/SQLModel metadata detection
  7. Migration c0d2ce43b315 — Creates flow_version_deployment_attachment table with all columns, FKs (CASCADE), and indexes. Single head, chains off fc7f696a57bf.

* [autofix.ci] apply automated fixes

* address bugs and inconsistencies

* rename column to "provider_snapshot_id"

* harden deployment API: fail loudly on invalid state instead of silently passing

Replace silent fallbacks, warning logs, and dropped values with hard
failures (422/500/502) across the deployment orchestration layer. Adds
logging to bare exception handlers and wraps materialize_snapshots in
the adapter error handler.

* [autofix.ci] apply automated fixes

* add materialize_snapshots to deployment service protocol

Promotes materialize_snapshots from duck-typed getattr usage to a
first-class method on DeploymentServiceProtocol, BaseDeploymentService,
and the no-op DeploymentService stub. Introduces MaterializeSnapshotsResult
schema for typed return values.

Updates deployments.py to call the method through the protocol instead of
getattr, giving static analysis coverage over the contract.

Documents the snapshot abstraction across BaseFlowArtifact, SnapshotItem,
MaterializeSnapshotsResult, and FlowVersionDeploymentAttachment.provider_snapshot_id
— explaining that snapshots are immutable, provider-owned copies of flow data
with opaque provider-assigned identifiers (e.g. wxO tool ID, K8s ConfigMap
name, S3 key).

* deployment sync: extract helpers, server-side type filter, orphan detection

- Extract _fetch_provider_resource_keys helper for provider validation
- Rename _sync_page_with_provider → _list_deployments_synced
- Match resource keys by provider ID only (not name)
- Restore server-side deployment_type filter with guard against
  false deletions (skip rows whose type doesn't match the filter
  instead of deleting them)
- Add orphan/divergence logging for post-create, post-update,
  post-duplicate DB write failures
- Return 422 on invalid UUID in update remove list (was silently ignored)
- Handle NotImplementedError → 501 from provider adapters
- Convert attachment IntegrityError to ValueError with descriptive message
- Add tests for sync helpers (15 cases)

* rebase on release-1.9.0 and align with lfx/services

* refactor(deployments): align provider mapper routing and WXO update payload mapping

Align deployment mapper resolution with adapter-type/provider-key routing and
refactor PATCH update handling to use mapper resolve/shape contracts end-to-end.
Map Langflow flow_version_id references at the API boundary into provider update
operations for Watsonx bind/unbind/remove paths, with expanded mapper tests.

* patch down-revision

* first pass with formalized boundary rules

* fix(deployments): harden watsonx payload boundary contracts

Enforce fail-fast payload slot parsing for required adapter results, split execution create/status slot contracts, and route execution-create mapping through deployment mappers.
Require watsonx flow artifact source_ref and move update reconciliation output to provider_result to keep mapper/adapter boundaries explicit and typed.

* refactor(deployments): modularize watsonx orchestrate create/update flow

Extract create/update logic into dedicated core modules with shared helpers to tighten deployment boundary contracts.
Align backend/lfx payload schema mapping and expand e2e/unit coverage for response mapping and update schema behavior.

* api impl for wxo-specific create payload

* further refactoring. add rollback of existing tools (undo new app bindings) in the create path

* add todo in execution.py

* refactor(deployments): replace snapshot_id/reference_id with source_ref-correlated tool refs
Introduce WatsonxToolRefBinding to correlate source_ref (flow version id)
with provider tool_id across all operation types. This replaces the prior
reference_id and snapshot_id fields with a unified structure that carries
provenance through create, bind, unbind, and remove_tool operations.
Key changes:
- Flatten API operation payloads: hoist flow_version_id onto operations,
  remove nested WatsonxApiUpdateToolReference wrapper
- Replace tools.existing_ids with inline tool_id_with_ref on bind operations
- Rename WatsonxCreateSnapshotBinding to WatsonxToolRefBinding (input) and
  WatsonxResultToolRefBinding (output, with created flag)
- Add created_app_ids to update results for connection tracking
- Raise HTTPException on contract violations in _to_api_tool_app_bindings
  instead of silently dropping unmappable bindings
- Add schema-level validation for conflicting source_ref on same tool_id
- E2E: cache tool_id→source_ref from create results, use helpers to build
  refs with distinct source_ref vs tool_id values

* Enforce DeploymentType enum and add description column

Make deployment_type a required column backed by a SQLAlchemy
TypeDecorator that validates on write (rejects None and invalid strings)
and coerces to DeploymentType on read. Add nullable description column
to the deployment model and surface it through the API.

Key changes:
- Add _DeploymentTypeColumn TypeDecorator for enum round-trip fidelity
- Make deployment_type non-optional in Deployment model, DeploymentRead,
  CRUD functions, and API layer
- Add description (Text, nullable) to Deployment model and fold its
  migration into the existing c0d2ce43b315 revision
- Remove _resolve_deployment_type helper — TypeDecorator handles coercion
- Remove DeploymentType fallbacks and backward-compat shims from API
  endpoints, base mapper, and watsonx orchestrate mapper
- Document cross-package coupling: DeploymentType is owned by lfx but
  persisted by langflow; member values must never be removed
- Fix pre-existing bug: provider_account_id → deployment_provider_account_id
  in get_deployment_status endpoint

Note: deployment_type is nullable=True at the DB level to satisfy the
EXPAND-phase migration validator; NOT NULL is enforced at the application
layer by the _DeploymentTypeColumn TypeDecorator.

* refactor(deployments): extract route helpers, harden sync and error handling
Move bulk of deployment route logic into mappers/helpers layer to slim
down deployments.py and enforce clearer boundary between routes, mappers,
and adapters (documented in DEPLOYMENT_BOUNDARY_RULES.md).
Key changes:
- Extract ~700 lines from deployments.py into helpers.py (pagination,
  adapter/mapper resolution, attachment management, snapshot sync,
  rollback, response shaping)
- Add read-path snapshot-level sync: get_deployment and
  list_deployments_synced verify provider_snapshot_ids against the
  provider and prune stale attachments, with graceful fallback on error
- Add compensating rollback for create (rollback_provider_create) and
  update (rollback_provider_update) when DB commit fails after provider
  mutation, using mapper-driven payload reconstruction
- Introduce handle_adapter_errors() context manager centralising
  DeploymentServiceError → HTTP status mapping via
  http_status_for_deployment_error; sanitise 500 detail to avoid
  leaking internals
- Add DeploymentNotConfiguredError → 503 mapping
- Add util_snapshot_ids_to_verify and resolve_rollback_update to base
  mapper with WxO overrides for provider-specific snapshot ID extraction
  and put_tools-based rollback payloads
- Add put_tools field to WatsonxDeploymentUpdatePayload for full tool
  list replacement; early-return in build_provider_update_plan and
  validate_operation_references when put_tools is set
- Extract verify_tools_by_ids into core/tools.py helper
- Harden resource_name_prefix with strip_whitespace + min_length=1
- Deduplicate snapshot_ids before provider calls
- Add deterministic order_by(created_at) to attachment CRUD queries
- Add exc_info=True to all best-effort rollback/compensate error logs
- Add session.rollback() in get_deployment snapshot sync error path
- Warn when list_snapshots receives both deployment_ids and snapshot_ids
- Add E2E scenarios for empty snapshot list, mixed snapshot IDs, tools
  endpoint, and deployment re-list after update
Tests:
- Add test_deployment_route_handlers.py covering stale-row delete +
  commit, non-404 adapter errors, handle_adapter_errors wiring,
  snapshot sync (happy path, skip, error fallback), project-scoped
  flow version validation for create and update
- Expand test_deployment_sync.py with snapshot-phase tests, rollback
  tests, pagination guard, and project-scoped validation
- Add deployment_type assertion to response mapping test
- Add DeploymentNotConfiguredError and bare DeploymentServiceError cases
  to exception mapping tests
- Add put_tools schema and update plan tests

* remove pompous performance commentary

* fix(deployments): remove upsert behavior and fail fast on duplicate name

The create_deployment endpoint previously performed a
get_deployment_by_resource_key lookup before inserting the DB row,
silently tolerating duplicates. Since the provider adapter returns a
fresh resource ID on every create, this lookup could never legitimately
match — and if it did, it would mask a data inconsistency bug.

Changes:
- Remove the get-or-create (upsert) pattern; go straight to
  create_deployment_db and let the unique constraint surface conflicts.
- Add deployment_name_exists CRUD function and an early 409 guard so
  duplicate names are rejected before any provider call, avoiding
  costly provider-side rollback for a locally-checkable condition.
- Update existing route-handler tests to reflect the removed lookup.
- Add tests for deployment_name_exists and the 409 duplicate-name path.

* feat: convert provider_key and deployment_type columns to DB-level enums
Replace plain string columns with SQLAlchemy Enum types backed by
Postgres/SQLite enum constraints, enforcing valid values at the DB
layer rather than only in application code.
Migration follows expand-contract pattern (add enum column, backfill,
drop old string column, rename) with index ops outside batch context
to avoid SQLite column-lookup issues. Upgrade and downgrade are fully
atomic.
- Add DeploymentProviderKey enum as single source of truth for
  provider identifiers; remove magic strings and _DeploymentTypeColumn
  TypeDecorator
- Make provider_key immutable after creation (remove from update
  request schema and API handler)
- Fix pre-existing test gap: add missing deployment_type argument to
  all TestDeploymentCRUD create_deployment() calls

* feat(flow-versions): add deployment awareness and sync-on-read

Add is_deployed field to flow version responses and provider-verified
sync to the list/get read paths, matching the existing deployment
endpoint sync pattern.

API changes:
- list_flow_versions returns is_deployed per entry and accepts optional
  deployment_ids filter to scope by specific deployments
- get_single_flow_version returns is_deployed on the full response
- Both endpoints now use write sessions and run best-effort
  snapshot-level sync before returning results

Sync-on-read (helpers.sync_flow_version_attachments):
- Queries all attachments for a flow's versions joined with deployment
  and provider account info in a single query
- Groups by provider, resolves adapter/mapper per group, verifies
  provider_snapshot_ids via list_snapshots, and prunes stale attachment
  rows through the existing sync_attachment_snapshot_ids helper
- Per-provider error handling so one provider outage doesn't block the
  response

New CRUD: list_attachments_for_flow_with_provider_info joins
FlowVersionDeploymentAttachment -> Deployment -> DeploymentProviderAccount
to avoid N+1 queries during sync grouping.

Tests: 50 passing (11 new) covering is_deployed indicator, deployment_ids
filtering, stale attachment pruning on list/get, and sync failure
resilience.

* Add user id authentication to a few missing endpoints

* [autofix.ci] apply automated fixes

* Update tests

Removes some mock tests that did nothing
Adds sqlite for true testing of db accessors
Reduces Mock objects usage

* refactor(deployments): enforce ownership boundaries on execution responses
Move provider-owned execution identifiers (execution_id, agent_id,
status, timestamps, errors) out of the top-level API response and into
provider_data, keeping only Langflow-owned fields (deployment_id) at the
top level.  This prevents future collisions if Langflow introduces its
own execution tracking.
Key changes:
- Remove execution_id from _ExecutionResponseBase; provider's opaque
  run identifier now lives exclusively inside provider_data
- Rename WatsonxExecutionResultData → WatsonxAgentExecutionResultData
  (adapter layer) and split the API-layer class into a private base
  (_WatsonxApiAgentExecutionResultBase) with dedicated
  WatsonxApiAgentExecutionCreateResultData and
  WatsonxApiAgentExecutionStatusResultData subclasses
- Translate WXO run_id → execution_id at the adapter boundary
  (create_agent_run_result / get_agent_run).
- Collapse util_execution_id + util_execution_deployment_resource_key
  into a single util_resource_key_from_execution that trusts the
  adapter-provided result.deployment_id directly
- Remove build_orchestrate_runs_query and extra payload fields
  (thread_id, llm_params, guardrails, etc.) unused in MVP
- Simplify WxOClient.post_run signature (drop query_suffix)
- Exclude provider_data from flow tool artifact to avoid unexpected
  top-level keys in the WxO tool runtime
- Document ownership boundary rules in DEPLOYMENT_BOUNDARY_RULES.md §14
- Add E2E polling for terminal execution status, input format variants,
  and missing-deployment negative test
- Expand unit tests for renamed schemas, field mapping, passthrough
  validation, and simplified payload builder

* feat: add name column to deployment_provider_account
Add a required, user-chosen display name to provider accounts
(e.g. "staging", "prod") that is unique within a given provider_key.
Includes model, CRUD, API schema/route, mapper, migration with
backfill, and tests.

* fix: replace hand-written migration with Alembic-generated revision
Replace the manually authored migration (b4e6f8a2c1d3) with an
Alembic-generated one (8255e9fc18d9) for the deployment_provider_account
name column.
Fix SQLite compatibility: sa.func.concat() generates a concat() function
call which does not exist in SQLite. Use sa.literal().concat() instead,
which produces the || operator and works on both PostgreSQL and SQLite.

* remove bogus unverified math from migration file

* feat: verify provider credentials before account creation
Add a verify_credentials step to the provider account creation flow
that validates API keys against the provider before persisting them.
This prevents storing invalid or revoked credentials and gives users
immediate feedback.
Key changes:
- Add verify_credentials to the deployment adapter interface (base,
  service, protocol) with WXO implementation that obtains a token
  via the IBM authenticator
- Add SSRF-hardened URL validation for provider_url (HTTPS-only,
  private IP blocklist, localhost rejection, normalization)
- Introduce ValidatedUrl/ValidatedUrlOptional annotated types in
  the API schema layer
- Refactor raise_for_status_and_detail to accept an optional cause
  parameter for explicit exception chain control
- Use ResourceNotFoundError (parent) instead of DeploymentNotFoundError
  in raise_for_status_and_detail for provider-agnostic 404 mapping
- Narrow get_authenticator return type to concrete union

* use whitelist only for valid urls

* feat: BREAKING: move credentials into provider_data and centralize update logic in mapper
- Replace top-level `api_key: SecretStr` with opaque `provider_data: dict` in API schemas;
  mapper extracts credentials via `resolve_credential_fields` for DB storage
- Add `resolve_provider_account_update` to base mapper so routes delegate
  full update-kwargs assembly (including cross-field logic) to the mapper
- WXO mapper override re-derives `provider_tenant_id` when `provider_url` changes
- Add tenant extraction utilities and `validate_tenant_url_consistency` in
  `deployment_provider_account/utils.py` as single source of truth
- Add `model_validator` on `DeploymentProviderAccount` for defense-in-depth
  tenant/URL consistency checks
- Rename `DEPLOYMENT_BOUNDARY_RULES.md` → `RULES.md`; document DB-direction
  mapper contract, credential flow, and update assembly
- Update all tests for new `provider_data` shape, mapper update methods,
  tenant extraction, and model-level consistency validation

* [autofix.ci] apply automated fixes

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

* fix(deployments): Harden provider account validation and WXO rollback

Use provider_url when resolving WXO credentials and scope provider account names per user within each provider. Re-verify provider account updates before persisting them and return 4xx responses for account conflicts instead of surfacing 500s.

Block deleting provider accounts that still own deployments and extend create rollback so failed WXO writes clean up provider-side resources. Add route, schema, mapper, sync, CRUD, and WXO tests to cover the new behavior.

* [autofix.ci] apply automated fixes

* update url validator docs; remove outdated reference to private url blacklist logic

* fix(deployments): Isolate snapshot sync writes

Use nested transactions around best-effort snapshot cleanup so provider sync failures cannot leak partial attachment deletes into the outer request transaction.

Persist explicit description clears during deployment PATCH requests, and add regression tests for both deployment sync paths and the route handler update flow.

* fix(deployments): Harden delete cleanup and wxO create tests

Treat missing provider agents as stale local cleanup so delete can
finish instead of leaving orphaned deployment rows behind.

Commit local delete operations eagerly, retry once on commit failure,
and move wxO create-path tests toward fake client objects so the real
service logic is exercised without external calls.

* new head

* fix(deployments): stop prefixing wxo raw connection app_ids
Preserve caller app_ids for newly created wxo connections while keeping lf_ prefixing for tool/deployment naming, centralize resource_name_prefix validation, and update mapper/service schema tests and docs to reflect the new behavior.

* fix(deployments): Harden provider account cleanup

Reconcile stale deployment rows before provider-account deletion so
out-of-band provider removals do not leave account cleanup blocked.

* fix: restore py310 compatibility and align payload slot tests
Import Self from typing_extensions in the deployment provider account model to keep backend imports working on Python 3.10, and update payload formalization tests to assert strict rejection of cross-model BaseModel inputs.

* fix(deployments): resolve mypy typing regressions across deployment flows
Normalize SQLModel query expressions for typed SQL operators, make deployment-related model IDs non-nullable where appropriate, and tighten provider mapper/update typing guards. Update deployment tests to align with stricter type contracts.

* fix(deployments): restore py310 test compatibility and migration idempotency
Replace Python 3.11-only UTC imports with timezone.utc in deployment-related tests and the watsonx e2e helper, and make the provider-account name migration safe to re-run when the column and unique constraint are created in separate steps.

* fix(deployments): restore provider account route ownership helpers
Reuse the shared provider-account lookup in update/delete routes so route tests keep the expected ownership path, and use the explicit-field helper when deciding whether to reverify credentials.

* [autofix.ci] apply automated fixes

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

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

* fix(deployments): enforce deployment guard constraints with clean API errors
Add DB trigger guards to block deleting deployed flow versions, deleting projects with deployments, and moving deployed flows across projects. Translate trigger violations to HTTP 409 with sanitized details, add best-effort pre-operation deployment/snapshot sync to reduce stale-state false positives, and cover guard parsing/delete flush behavior with tests.

* checkout latest crud and helpers files

* make helper for try catch sync logic

* add gaurd to prevent moving deployments across projects

* prevent moving deployments across provider accounts

* add live sqlite tests

* recover lost changes

* recover feature flag setup from release-1.9.0

* fix: address review findings for deployment guard branch
- Add comment in delete_user explaining why best-effort provider sync
  is intentionally skipped (too expensive; DB trigger is authoritative)
- Add docstring to _clean_guard_detail for maintainability
- Add happy-path trigger tests verifying operations succeed when no
  deployment conflicts exist (flow version delete, project delete,
  flow move, deployment rename)
- Fix list_attachments_for_flow_with_provider_info callers still using
  the old flow_id= parameter (now flow_ids=)
- Fix pre-existing broken test fixture (missing name in
  DeploymentProviderAccount)

* feat: add cross-project attachment guard and harden test suite
Add a new DB trigger (prevent_cross_project_attachment) that blocks
attaching a flow version to a deployment in a different project, for
both PostgreSQL and SQLite.
Refactor trigger tests into a unified dual-dialect test file
(test_deployment_guard_triggers.py) that runs against both SQLite
(always) and PostgreSQL (when TEST_DEPLOYMENT_GUARD_PG_URL is set).
Validated with both asyncpg and psycopg drivers.
Additional improvements:
- test_downgrade_removes_triggers now asserts the guard is active
  before downgrade, preventing false-positive passes
- Endpoint test uses statement inspection instead of fragile
  call-count gating
- Add exception parser coverage for CROSS_PROJECT_ATTACHMENT,
  implicit __context__ chains, and cyclic exception chains
- Add endpoint tests for cascade_delete_flow, update_flow,
  delete_multiple_flows, and global exception handler

* fix(deployments): make provider account identity immutable
Add DB deployment guard triggers to prevent updating provider account identity fields
(provider_key, provider_tenant_id, provider_url) once created, and preserve guard
error translation in the provider-account PATCH route. Extend trigger and route
tests to cover blocked updates and same-value no-op updates.

* refactor: extract sync logic into dedicated module and fix sync correctness issues
- Move deployment/attachment sync functions from helpers.py to new sync.py
  module, reducing helpers.py size and improving separation of concerns
- Fix fetch_provider_resource_keys to use deployment_ids instead of
  provider_params (pre-existing bug: wrong adapter parameter)
- Add empty-list guard to fetch_provider_resource_keys to avoid
  unnecessary provider calls
- Wrap snapshot sync in savepoint for proper fault isolation
- Update imports across flows.py, projects.py, flow_version.py,
  deployments.py to reference new sync module
- Update unit tests to target refactored module paths and add coverage
  for bug fixes

* refactor: implement binding-aware deployment sync and optimistic guard retries
Add provider binding contract and mapper extraction path:
- add ProviderSnapshotBinding in deployments/contracts.py
- add BaseDeploymentMapper.extract_snapshot_bindings() default no-op
- implement Watsonx mapper extract_snapshot_bindings() with strict provider_data parsing via PayloadSlot (snapshot_ids required)
Replace attachment snapshot verification loop with binding-aware set-based cleanup:
- add delete_unbound_attachments(user_id, deployment_ids, bindings) in flow_version_deployment_attachment/crud.py
  - uses CTE/anti-join to delete local attachments not present in provider bindings
  - when bindings are empty, delete all attachments for provided deployment_ids
- add count_attachments_by_deployment_ids() grouped recount helper
- update list_deployments_synced() in deployments/helpers.py to:
  - collect bindings from fetch_provider_resource_keys() provider_view during batch sync
  - run one savepoint-wrapped delete_unbound_attachments() for accepted deployments
  - run one grouped recount and patch attached_count from DB
  - remove list_attachments_by_deployment_ids + snapshot-provider phase
  - enforce two sync rounds max (initial pass + one refill)
Consolidate provider-side sync plumbing:
- change fetch_provider_resource_keys() in deployments/sync.py to return (known_resource_keys, provider_view)
- document tuple contents in function docstring
- remove now-unused sync_provider_attachment_snapshots() helper
- keep fetch_provider_snapshot_keys()/sync_attachment_snapshot_ids() for single-deployment read path
Scope read sync by provider account and conditionally expose deployment status:
- update deployment CRUD listing helpers to accept provider_account_id filter
- in flow_version API, add deployment_provider_account_id query param
- only perform deployment sync/is_deployed calculation when provider id is explicitly passed
- make FlowVersion.is_deployed optional (default None) so field can be omitted when not requested
Switch mutating APIs to optimistic catch-sync-retry pattern:
- add _retry_on_deployment_guard() in flows.py and projects.py
- replace pre-sync mutation flow with guarded retry on DeploymentGuardError
- for project create/update, retry only guarded flow-move DB operations
- preserve side-effect safety and improve stale-state recovery behavior
Tests:
- add unit tests for deployment guard retry helper (test_deployment_guard_retry.py)
- add unit tests for delete_unbound_attachments behavior, including empty bindings delete-all case (test_flow_version_deployment_attachment_crud.py)
- update deployment sync tests for tuple return, binding extraction, consolidated phase-2 cleanup/recount, and two-round refill behavior
- update flow_version tests for provider-scoped sync and conditional is_deployed field presence

* fix: extract tool_ids from provider data

* dont use stale rolled-back OORM Flow instance

* refactor(deployment): demote delete triggers and standardize guard handling
- Edit the existing deployment guard migration to remove DB delete triggers for flow version and project deletion in both PostgreSQL and SQLite.
- Keep core DB invariants (flow move, deployment project move, deployment provider account move, provider account identity immutability, and cross-project attachment).
- Add a new DB invariant trigger to enforce deployment.resource_key immutability.
- Rewrite trigger error text to technical/operator-focused language and remove ambiguous “detach” wording.
- Add migration comments documenting the current global provider identity guard and the future provider-specific migration path.
- Add app-level guard helpers in deployment/guards.py:
  - check_flow_has_deployed_versions
  - check_project_has_deployments
- Wire check_flow_has_deployed_versions into cascade_delete_flow before destructive deletes.
- Wire check_project_has_deployments into delete_project before deleting the folder row.
- Keep explicit DeploymentGuardError passthrough in cascade_delete_flow and retain parse fallback for non-guard exceptions.
- Refactor DeploymentGuardError to carry:
  - code
  - technical_detail
  - detail (API-friendly message)
- Add friendly guard-detail mapping by guard code.
- Update parse_deployment_guard_error to parse DEPLOYMENT_GUARD:<CODE>:<DETAIL> and preserve raw technical detail from chained exceptions.
- Simplify delete_user to DB-cascade delete + flush only.
- Remove deployment guard translation/parsing logic from delete_user.
- Keep an explicit endpoint comment documenting the intentional no-provider-teardown trade-off.
- Update flow_version deletion message to: “Remove its deployment attachment rows first.”
- Update tests to match the new guard contract and behavior:
  - Remove stale delete_user guard-translation endpoint test.
  - Update delete endpoint tests to assert app-level guard behavior and new friendly details.
  - Update trigger tests to reflect removed delete triggers and added resource_key trigger coverage.
  - Update trigger downgrade assertions for the revised trigger set.
  - Expand exception tests for code mapping, technical-detail preservation, unknown-code fallback, and new guard codes.
  - Add unit tests for deployment guard helper functions.

* surface better msg when project deletion attempted

* refactor(deployment): rename flow guard code and align guard messages
Rename FLOW_VERSION_DEPLOYED to FLOW_HAS_DEPLOYED_VERSIONS across deployment guard checks, project-level remapping, and tests.
Update friendly guard wording for flow/project/move/cross-project cases, and convert pytest match patterns to raw escaped regex strings to satisfy Ruff.

* add docs to migration file

* update docs in migration

* update docs

* refactor(flow-version): scope deployment status to list endpoint
Keep deployment status provider-scoped on version listing only, remove single-version sync/status behavior, and omit is_deployed from snapshot creation responses while aligning docs and tests.

* refactor(deployment): centralize guard retry helpers and align sync error handling
Move flow/project deployment-guard retry wrappers into deployment sync helpers while preserving upstream route logic, and align provider sync error mapping with deployment domain exceptions. Tighten wxo snapshot binding validation and update docs/tests for guard messaging and sync behavior.

* refactor(deployment): enforce snapshot ID invariants and improve delete error UX
- add shared non-empty string guard (`require_non_empty`) in database utils and use it in deployment attachment CRUD write paths
- enforce required `provider_snapshot_id` on attachment model and add Pydantic + SQLAlchemy validators as safety nets for non-CRUD writes
- introduce deployment attachment key schemas (`DeploymentAttachmentKey`, `DeploymentAttachmentKeyBatch`) with deduplication support
- add batch stale-row cleanup (`delete_deployment_attachments_by_keys`) using a VALUES CTE to delete exact deployment/flow-version pairs
- remove mapper-level `util_snapshot_ids_to_verify` hook from base + watsonx mapper and replace with sync utilities:
  - `extract_verified_snapshot_ids`
  - `extract_verified_provider_snapshot_ids`
- update sync and helper flows to use verified snapshot IDs, stricter provider ID validation, and safer corrected-count handling
- align provider ID handling so both deployment and snapshot sync paths reject blank provider IDs consistently
- tighten adapter/provider-key validation and enforce required snapshot binding during attach flow-version operations
- update deployment routes/helpers to new sync signatures and behavior
- remove legacy null/blank snapshot safety-net filters from attachment queries/delete-unbound reconciliation (intentional invariant enforcement)
- add broad backend test coverage for:
  - rejecting empty/blank snapshot IDs on create/update
  - exact-key batch deletion behavior
  - cartesian cross-delete regression prevention
  - updated route/sync expectations after helper refactor
- improve flow delete UX in the frontend list view by surfacing backend `detail` via `getAxiosErrorMessage` instead of a generic "Please try again"

* update logic and remove stale comment

* fix(deployment): handle orphaned deployment attachments and enforce SQLite FK constraints
Enable PRAGMA foreign_keys=ON for SQLite to enforce referential integrity
that was previously silently ignored, and add application-level cleanup for
orphaned FlowVersionDeploymentAttachment rows left behind by environments
where cascades never fired.
- Enable foreign_keys pragma in lfx SQLite settings
- Update deployment guards to detect and prune orphan attachments (missing
  deployment parent) before blocking on live ones, with structured logging
- Update flow_version and deployment CRUD queries to join on Deployment so
  is_deployed status and attachment counts reflect only live attachments
- Document has_deployment_attachments write side-effect (orphan pruning)
- Wrap pre-sync orphan cleanup in try/except so failures don't abort the
  sync process
- Explicitly delete spans and traces in cascade_delete_flow to avoid FK
  violations from the span.trace_id constraint (which lacks ON DELETE
  CASCADE in the DDL)
- Add in-memory SQLite integration tests covering guard pruning, orphan
  cleanup, version pruning, deployment counts, and is_deployed status
- Add unit tests for sync exception-handling paths

* refactor(deployment): replace DB trigger guards with ORM-layer preflight checks
Remove the unshipped trigger migration (97c9a98c9c01) and enforce
deployment invariants at the ORM/service layer instead:
- Add orm_guards.py with preflight checks for all six guard codes
  (FLOW_DEPLOYED_IN_PROJECT, DEPLOYMENT_PROJECT_MOVE, DEPLOYMENT_TYPE_UPDATE,
  DEPLOYMENT_RESOURCE_KEY_UPDATE, DEPLOYMENT_PROVIDER_ACCOUNT_MOVE,
  DEPLOYMENT_PROVIDER_ACCOUNT_IDENTITY_UPDATE, CROSS_PROJECT_ATTACHMENT)
- Wire guards as pure prefix blocks into deployment, provider-account,
  and attachment CRUD functions — existing write logic unchanged
- Add preflight validation before bulk update(Flow) statements in
  projects.py and folder/utils.py — existing statements unchanged
- Add ensure_flow_move_allowed to flows_helpers.py for ORM-instance
  update paths (_patch_flow, _update_existing_flow, _validate_and_assign_folder)
- Optimize batch flow-move guard to one query per source folder
- Simplify parse_deployment_guard_error to isinstance-only chain walk
  now that guards are raised explicitly as DeploymentGuardError
- Document retry helper contract: operations must enforce guards internally
- Replace trigger-centric tests with ORM/service-level guard tests
- Add project API guard integration tests for flow-move blocking

* fix(deployment): prune attachment rows before deployment deletes
Explicitly delete flow-version deployment attachments before deployment row deletes
to prevent orphaned attachments when FK cascades are disabled (e.g. SQLite
foreign_keys=OFF). Keep delete-by-resource-key and delete-by-id behavior intact
while documenting guard None-scope behavior and adding coverage for missing-row
and FK-disabled cleanup paths.

* recover lost tests

* misc

* remove deployment guard error extraction from lfx session scope

* extract re-raise logic into a helper

* fix: stabilize deployment guard retries and guard diagnostics
- scope WxO provider-client ContextVar state to each deployment provider scope via provider_clients_memoization_scope
- compose WxO scope lifecycle into deployment_provider_scope and document forward multi-adapter dispatch options
- add successful provider resource-key sync debug logging and remove stray print-based sync error debug
- log DeploymentGuardError details during flow cascade delete and in deployment guard exception re-raise helper
- fix folder defaulting guard precheck query to use Flow.folder_id.is_(None) so NULL-folder flows are included
- deduplicate require_non_empty by importing from langflow.services.database.utils in deployment mappers
- remove deprecated duplicate helper module at api/v1/mappers/deployments/util.py and keep package export wired to canonical helper
- add regression test for default-folder guard precheck covering NULL-folder flow handling

* add tests for provider scope context

* fix: improve deployment guard logging and async guard handling
Log DeploymentGuardError directly in flow/project endpoint guard catch blocks with operation context, and use the async guard helper for generic exception paths that need guard parsing. Add tests for async guard helper logging and raise behavior.

* less verbose name for scope

* harden delete_unbound_attachments by passing provider account id to it to scope deletion

* fix: return dense deployment attachment counts and simplify snapshot sync
Make `count_attachments_by_deployment_ids` return a dense mapping for all
requested deployment ids, including zero for ids with no countable attachments.
Update deployment listing code to rely on direct key access for corrected counts,
remove redundant `verified_snapshot_ids` plumbing from snapshot sync call sites,
keep local snapshot id integrity checks in sync logic, and align backend tests
plus log messaging with the new count contract.

* guard context scope

* test: expand deployment guard and sync regression coverage
Add comprehensive regression coverage for deployment guard and deployment-sync behavior across database and API test suites.
- verify deployment deletes remove linked attachment rows
- cover batched move guards and immutable deployment/provider fields
- validate cascade flow deletion and user-scoped orphan cleanup behavior
- exercise retry helper edge cases for flow/project guard retries
- align sync helper tests with stricter provider-id/error handling and dedupe/early-return paths
- add API 409 guard-path tests for deployed flow/project delete and move scenarios

* fix: align flow-version list semantics with provider-scoped deployment status
- remove `deployment_ids` handling from `GET /flows/{flow_id}/versions/` and keep plain list mode as versions-only
- enforce provider-account ownership for `deployment_provider_id` via `get_owned_provider_account_or_404` (404 on unknown/foreign ids)
- add explicit feature-flag guard for provider-scoped mode:
  `Cannot use deployment_provider_id: the wxo_deployments feature flag is disabled`
- remove `has_providers` / `count_provider_accounts` branching and drive behavior directly from request params
- replace `get_flow_version_list` with `get_flow_versions_with_provider_status` and scope `is_deployed` by:
  `Deployment.deployment_provider_account_id == provider_account_id`
- keep best-effort `sync_flow_version_attachments` before provider-scoped reads
- update API tests:
  - delete deployment_ids endpoint tests
  - add provider-scoped status regression coverage (true under provider A, false under provider B)
  - add provider-id feature-flag rejection test (400)
  - add unknown and foreign provider-id ownership tests (404)
  - simplify feature-disabled plain-list test to assert `is_deployed` remains omitted
- migrate CRUD/in-memory tests off removed `get_flow_version_list` to `get_flow_versions_with_provider_status`
- update stale flow export TODO comments referencing the removed function

* fix: batch stale deployment cleanup per provider sync group
Replace per-deployment stale deletes in deployment sync with a single batched delete per provider group.
Add a bulk deployment-delete CRUD helper and regression coverage for grouped stale-delete behavior plus multi-deployment attachment cleanup.

* test: expand deployment guard and provider account update coverage
Add direct ORM guard coverage for noop immutable updates and attachment project matching. Update in-memory deployment tests to cover provider account API key rotation and align stale fixtures with current model constraints.

* fix: make deployment GET sync binding-aware and harden guard/prune behavior
- Align SQLite defaults in `lfx/services/settings/base.py`:
  - remove forced `foreign_keys=ON` pragma from default sqlite pragmas
- Replace deployment GET snapshot-id verification with binding-aware reconciliation in `api/v1/deployments.py`:
  - resolve and use the concrete deployment mapper in GET
  - call mapper-provided `extract_snapshot_bindings_for_get(...)`
  - prune detached links via `delete_unbound_attachments(...)` inside `session.begin_nested()`
  - fall back safely to unverified attachment counts when sync is unsupported or fails
  - change provider_data response shaping to `mapper.shape_deployment_get_data(...)` to hide internal fields
- Extend mapper contracts in `api/v1/mappers/deployments/base.py`:
  - add `extract_snapshot_bindings_for_get(...)` (explicitly raises `NotImplementedError` by default)
  - add `shape_deployment_get_data(...)` (explicitly raises `NotImplementedError` by default)
  - make GET sync/shaping behavior explicit per provider instead of accidental passthrough
- Implement wxO-specific GET sync/shaping in `watsonx_orchestrate/mapper.py`:
  - parse/validate `provider_data.tool_ids` for binding extraction
  - emit `ProviderSnapshotBinding(resource_key, snapshot_id)` for each tool id
  - validate/shape GET `provider_data` to expose only `{"llm": ...}` to API clients
  - raise clear 500/value errors for malformed adapter payload contracts
- Update wxO adapter GET payload in `watsonx_orchestrate/service.py`:
  - always include `tool_ids` and derived `environment`
  - include `llm` when available
  - remove `or None` fallback so mapper receives consistent structure
- Harden flow-version pruning in `services/database/models/flow_version/crud.py`:
  - resolve concrete version IDs to prune first
  - delete `FlowVersionDeploymentAttachment` children before deleting `FlowVersion` rows
  - prevent stale doubly-orphan attachment rows when SQLite runs with foreign keys disabled
- Simplify guard exception semantics in `deployment/exceptions.py`:
  - stop walking chained exceptions; only treat explicit `DeploymentGuardError` instances as guard failures
  - add optional remap hook to `araise_if_deployment_guard_error_or_skip(...)`
  - add `remap_flow_guard_for_project_delete(...)` to convert flow guard code to project guard code where needed
- Remove duplicated per-route guard catch blocks and centralize behavior:
  - `api/utils/flow_utils.py`, `api/v1/flows.py`, and `api/v1/projects.py` now rely on shared async guard helper
  - project delete path now remaps `FLOW_HAS_DEPLOYED_VERSIONS` into `PROJECT_HAS_DEPLOYMENTS` via shared remap function
- Keep multi-delete flow route behavior consistent in `api/v1/flows.py`:
  - run guard remap/log helper in broad exception path before generic logging and 500 handling
- Update deployment exception tests in `test_exceptions.py`:
  - remove chain-parsing expectations
  - validate direct guard-raise semantics
  - add remap function coverage
- Expand flow version pruning tests:
  - `test_crud.py`: verify delete ordering (attachments first, versions second) and no-op behavior when nothing is pruned
  - `test_in_memory.py`: add broad regression class proving orphan attachment cleanup, live deployment preservation, cross-flow/user isolation, and repeated-cycle convergence
- Expand deployment API/mapper/sync test coverage:
  - `test_deployment_mapper_base.py`: assert new base mapper GET shaper raises until implemented
  - `test_deployment_route_handlers.py`: migrate assertions to binding-aware sync behavior, unsupported-provider fallback, sync-failure fallback, and provider_data sanitization
  - `test_deployment_sync.py`: add wxO mapper tests for `extract_snapshot_bindings_for_get(...)` and GET data shaping requirements
  - `test_watsonx_orchestrate.py`: validate wxO GET provider_data now includes `tool_ids`/`environment` defaults and feature-flag-scoped provider context behavior

* remove redunant description

* remove agent environment from payload for get()

* fix(deployment): prune orphan attachments before reading in flow guard

The cascade flow delete path called `check_flow_has_deployed_versions`,
which issued a SELECT before any write. On SQLite that left the
connection holding only a SHARED lock; the subsequent cascade DELETEs
then had to upgrade SHARED -> RESERVED, which doesn't busy-wait when
another connection already holds RESERVED, surfacing intermittently
in CI as `OperationalError: database is locked`.

Reorder the guard to issue a single DELETE-with-scalar-subquery for
orphan attachments first, so the connection acquires the writer lock
up front. The live-attachment SELECT runs afterwards on the same
session. As a side benefit, orphan pruning now also runs when live
attachments coexist (previously the early raise short-circuited it,
though SAVEPOINT rollback in the retry wrapper still discards the
prune in that failure path).

Log the raw driver-reported `rowcount` verbatim on every prune for
debuggability, and update guard tests for the new DELETE-then-SELECT
ordering.

* add log that pruning might be rolled back

* fix(deployment): set provider scope when reconciling before provider-account delete
The DELETE /api/v1/deployments/providers/{id} handler called
list_deployments_synced without entering deployment_provider_scope, so the
WxO adapter raised CredentialResolutionError ("Deployment account context is
not available for adapter resolution"). Reconciliation was silently dropped
and the stale local count blocked every delete with a 409.
Wrap the reconciliation call in deployment_provider_scope(provider_account.id)
to match every other adapter call site in this module, so stale local
deployment rows can actually be pruned and the provider account can be
removed when the provider no longer owns any resources.
Add three regression tests in TestProviderAccountRoutes:
- assert deployment_provider_scope is active (with the right provider id)
  during reconciliation, and that the context does not leak afterwards
- assert that a CredentialResolutionError from reconciliation falls back to
  the local count and returns 409 without deleting the provider row
- assert that reconciliation is skipped entirely when no local deployments
  exist for the provider

---------

Co-authored-by: Jordan Frazier <jordan.frazier@datastax.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
(cherry picked from commit 60bb53b44c)
2026-04-23 17:49:52 -07:00
242c6c70b5 fix: MCP Tools component now works in LFX standalone mode (#12760)
* fix: MCP Tools component now works in LFX standalone mode

When serving a flow via `lfx` (the standalone flow server) without the
full Langflow package installed, `MCPToolsComponent.update_tool_list()`
unconditionally tried to import `langflow.api.v2.mcp.get_server` and
open a DB session, raising `ImportError` before the existing fallback
to `server_config_from_value` in `resolve_mcp_config()` could run.

Treat the ImportError as the expected signal of standalone mode: skip
the DB lookup and use the server config embedded in the flow JSON.
The DB path is unchanged when Langflow is available.

* [autofix.ci] apply automated fixes

* fix: narrow LFX standalone fallback to missing Langflow modules only

Previously the fallback to the flow-embedded MCP server config triggered
on any ImportError from the Langflow imports, which would silently swallow
transitive dependency failures (e.g. sqlmodel failing to import inside
langflow.services.database.models.user.crud). That is a real bug in the
full Langflow stack — not LFX standalone mode — and silently using the
stale flow-embedded config would hide it while also bypassing the DB
config that is supposed to take precedence when Langflow is available.

Narrow the fallback to ModuleNotFoundError whose .name is one of the
Langflow modules we are trying to import; re-raise everything else so it
surfaces normally.

* Update component_index.json

* [autofix.ci] apply automated fixes

* fix: address review feedback on LFX standalone fallback

- Expand comment on `except ModuleNotFoundError` narrowing to explicitly
  document the ImportError-vs-ModuleNotFoundError distinction.
- Bump fallback log from adebug to ainfo (mode switch is material).
- Simplify `getattr(e, "name", None) or ""` to `e.name or ""`.
- Add TODO(legacy-cleanup) marker flagging 800-line file debt.
- Rename fallback tests to `should_[expected]_when_[condition]` convention.
- Add regression tests: plain ImportError surfaces; lfx.services.deps
  missing surfaces (locks in prefix-check precedence).
- Document why `patch("builtins.__import__")` is necessary in tests.

* [autofix.ci] apply automated fixes

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

* [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-04-23 21:42:42 +00:00
3ea28ed902 fix: propagate x-api-key and authorization headers to nested MCP calls (#12541)
* fix: propagate x-api-key and authorization headers to nested MCP calls (fixes #12529)

When Langflow is used as an MCP server containing flows with nested MCP
components, authentication headers like x-api-key were silently dropped
because extract_global_variables_from_headers() only captured headers
with the X-LANGFLOW-GLOBAL-VAR-* prefix.

Add _AUTH_HEADERS_TO_PROPAGATE to also capture x-api-key and authorization
under their lowercase header names. These values are stored in the
request_variables context, making them available for resolution in nested
MCP server configs. Users can now reference them in their server headers
config as {x-api-key: x-api-key} to propagate the incoming key.

* fix: remove duplicate verify_public_flow_and_get_user from core.py

The duplicate function in core.py referenced undefined names (uuid, session_scope)
and shadowed the canonical implementation in flow_utils.py, which is the one
re-exported from __init__.py and has the fuller signature including
authenticated_user_id. Removing the dead copy resolves the F821 ruff errors.

* Tighten scope of fix

* Update .secrets.baseline

* Clean up test locations

* Update .secrets.baseline

---------

Co-authored-by: Eric Hare <ericrhare@gmail.com>
2026-04-21 23:53:43 +00:00
f748738c74 fix: MCP Auth Error on restart / swapping auth (#12715)
* fix: MCP Auth Error on restart / swapping auth

* [autofix.ci] apply automated fixes

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

* Make this more robust

* fix: Propagate the api key in PATCH

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-04-17 04:07:24 +00:00
da516b7045 Merge release branch 2026-04-14 16:44:45 -07:00
38d142a723 fix: Upgrade cuga to 0.2.20 to resolve playwright dependency conflict (#12703)
* fix: upgrade playwright to 1.58.0 to address Chromium CVEs

- Add playwright>=1.58.0 to override-dependencies in pyproject.toml
- Update uv.lock: playwright 1.49.0 -> 1.58.0, pyee 12.0.0 -> 13.0.1
- Fixes CVE-2026-2313, CVE-2026-2314, CVE-2026-2315, CVE-2026-2319,
  CVE-2026-2321, CVE-2026-2441, CVE-2026-2648, CVE-2026-2649
- Ensures Docker builds download updated Chromium with security patches

* fix: update npm to latest version to address brace-expansion CVE-2026-33750

- Add npm update after Node.js installation in Dockerfile
- Fixes CVE-2026-33750 in system npm's brace-expansion dependency
- System npm had brace-expansion 2.0.2, update gets 5.0.5+
- Low risk change: npm is backward compatible, only affects CLI tool

* revert: remove npm update from Dockerfile

- npm update attempts were causing CI build failures
- Bundled npm has issues but updating it is proving problematic
- Focus on playwright CVE fix which is the primary concern
- brace-expansion CVE-2026-33750 is lower priority (DoS only)

* chore: sync uv.lock files

sync uv.lock files

* fix(mcp): dedupe edges in connect_components (#12701)

* fix(mcp): make add_connection idempotent to avoid duplicate edges

connect_components used to append a new edge unconditionally. Because
the edge id is deterministic from source/target/handles, calling it for
a pair the flow already had wired up (UI-then-MCP, batch retry, or just
a repeat call) produced a second edge with the same id, double-wiring
the flow at runtime.

Before appending, scan the existing edges for one with the same id and
return that instead. Different outputs/inputs between the same pair
still produce distinct ids and remain supported.

* test(mcp): cover dedupe against UI-saved edges, broaden match key

Older Langflow UIs saved edges with an `xy-edge__` id prefix instead of
the current `reactflow__edge-`, so an id-based dedup would miss the
UI-then-MCP case for any flow that came from an older version. Switch
the existence check to a structural one (source, target, sourceHandle
name, targetHandle fieldName) so the same logical connection dedupes
regardless of id format.

Add a fixture-driven test that loads MemoryChatbotNoLLM.json (an
xy-edge-prefixed flow) and replays each connection through
add_connection, asserting the edge count does not grow.

* fix(mcp): validate_flow fast-fails and reports partial errors (#12697)

* fix(mcp): validate_flow fast-fails and reports partial errors

validate_flow polled /monitor/builds for up to 30 seconds waiting for
every component to finish before reporting errors. When a component
fails early (for example a missing required field), downstream
components never run, so the loop waited out the full window and
returned just "Build timed out: N/M components completed" with no
actionable context.

- Short-circuit as soon as any completed build reports valid: false;
  return those errors immediately instead of polling on.
- On timeout, include the errors from the builds that did complete
  plus a component_count so the caller can see progress.
- Extract _collect_build_errors so the poll loop and timeout branch
  share the same error shape.

* fix(mcp): stream validate_flow build inline instead of polling

The previous implementation triggered an async build and polled
/monitor/builds, which depended on FastAPI BackgroundTasks firing the
log_vertex_build calls after the trigger request had returned. Under
ASGI test transport these tasks never run, so /monitor/builds stayed
empty and validate_flow timed out with component_count=0.

Switch to event_delivery=direct so the build streams its events back
inside the same request:

- Drive the build via client.stream_post and aggregate per-vertex
  results from end_vertex events.
- Fast-fail on the first vertex with valid=false, since downstream
  vertices depend on it and would not produce useful information.
- Surface top-level error events as a single flow-level error.
- Replace _collect_build_errors with _extract_vertex_error, which
  reads the structured error payload from the end_vertex outputs.

Update the lfx unit tests to use the streaming shape and tighten the
backend integration test to assert real success now that the build
actually runs end to end under ASGI.

* fix(graph): make end_all_traces_in_context Python 3.10 compatible

The implementation called asyncio.create_task(coro, context=context),
but the context= keyword was added to create_task in Python 3.11. On
3.10 it raised TypeError. The bug was latent because nothing in the
test suite previously consumed a streaming build response far enough
for Starlette to dispatch the post-response BackgroundTasks where this
code lives. The validate_flow streaming change exposes it.

On 3.10, route the create_task call through context.run so the new
Task copies the captured context as its current context, matching the
isolation the 3.11 path provides via the context= kwarg.

Add a regression test that asserts end_all_traces sees the value of a
contextvar set before the context was captured, even after the caller
mutates that var.

* fix: failing wxo list llm test (#12700)

patch service layer and update failing test

* [autofix.ci] apply automated fixes

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

* Try to fix the missing typer import

---------

Co-authored-by: Janardan S Kavia <janardanskavia@Janardans-MacBook-Pro.local>
Co-authored-by: Adam Aghili <Adam.Aghili@ibm.com>
Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@logspace.ai>
Co-authored-by: Hamza Rashid <74062092+HzaRashid@users.noreply.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-04-14 21:23:12 +00:00
7b856e7d22 fix(loop): iterate when only item is connected and render item as a table (#12669)
* fix(loop): drive iteration from item_output when done is not connected

Extract the loop body execution into an idempotent `_iterate` helper
that both `item_output` and `done_output` invoke. On release-1.9.0,
`_should_process_output` only runs outputs whose name is in the
vertex's outgoing edge source names, so `done_output` never ran when
nothing was connected to `done` and the subgraph iteration never
happened.

`_iterate` caches aggregated results and cached exceptions in ctx so
repeat calls (when both outputs are wired) run the subgraph exactly
once and surface the same failure on re-entry. `item_output` is now
async, calls `_iterate` before stopping the item branch, and returns
a Data payload listing the dispatched items so the inspector shows
real content instead of an empty string.

Add regression tests covering the item-only topology, the classic
both-outputs-connected topology, empty input, cached error re-raise,
and per-run ctx isolation.

* [autofix.ci] apply automated fixes

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

* fix(loop): emit item output as DataFrame so UI renders it as a table

Wrapping the iterated rows in a `Data` payload with `count` / `items`
keys caused the Item inspector to render as JSON instead of as a
tabular view. Return the rows as a DataFrame, mirroring the Mock Data
component pattern, so the inspector uses its table renderer.

* feat(loop): emit summary logs for each run

Add start, complete, skipped, and error log entries from `_iterate` so
the component's Logs tab shows a per-run summary with row counts and
total elapsed time. Failures include the elapsed duration and the
error message.

* [autofix.ci] apply automated fixes

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

* fix(loop): address review comments

- Refresh Research Translation Loop starter flow's saved item-output
  schema (JSON -> Table) to match item_output now returning a DataFrame.
- Clarify the test_ctx_isolation_across_runs docstring: production
  rebuilds the graph per request, so ctx is effectively per-run; reusing
  a single Graph instance across runs is intentionally not exercised.
- Update _iterate's docstring to describe the actual ctx scope rather
  than claiming graph-instance-level reset semantics that the framework
  does not provide.

* [autofix.ci] apply automated fixes

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

* fix(loop): stabilize chat output inspection test

* fix(loop): align starter project with item output contract

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-04-14 15:35:38 +00:00
9029c4b61e fix: Updates the CI workflow to handle known dependency conflicts. (#12691)
* fix: upgrade playwright to 1.58.0 to address Chromium CVEs

- Add playwright>=1.58.0 to override-dependencies in pyproject.toml
- Update uv.lock: playwright 1.49.0 -> 1.58.0, pyee 12.0.0 -> 13.0.1
- Fixes CVE-2026-2313, CVE-2026-2314, CVE-2026-2315, CVE-2026-2319,
  CVE-2026-2321, CVE-2026-2441, CVE-2026-2648, CVE-2026-2649
- Ensures Docker builds download updated Chromium with security patches

* fix: update npm to latest version to address brace-expansion CVE-2026-33750

- Add npm update after Node.js installation in Dockerfile
- Fixes CVE-2026-33750 in system npm's brace-expansion dependency
- System npm had brace-expansion 2.0.2, update gets 5.0.5+
- Low risk change: npm is backward compatible, only affects CLI tool

* revert: remove npm update from Dockerfile

- npm update attempts were causing CI build failures
- Bundled npm has issues but updating it is proving problematic
- Focus on playwright CVE fix which is the primary concern
- brace-expansion CVE-2026-33750 is lower priority (DoS only)

* CI: Filter cuga/playwright dependency conflict in release workflow

- Filter cuga/playwright conflict (we override playwright>=1.58.0 for CVE fixes)
- Still fails CI if other genuine dependency issues are detected
- Applied to both base and main package build steps

---------

Co-authored-by: Janardan S Kavia <janardanskavia@Janardans-MacBook-Pro.local>
2026-04-14 15:29:28 +00:00
2fa3d1c759 feat: add langflow-sdk support to release workflow (#12679)
* feat: add langflow-sdk build and publish support to release workflow

Add support for building and publishing the langflow-sdk package in the
release workflow, mirroring the nightly build support added in #12491.

Changes:
- Add `release_sdk` workflow input for controlling SDK release
- Add `determine-sdk-version` job with first-release PyPI handling
- Add `build-sdk` job with version verification and import testing
- Add `publish-sdk` job that publishes SDK to PyPI before LFX
- Update `build-lfx` to download SDK artifact and test both wheels together
- Update `build-base` and `build-main` to use SDK wheel as find-links
- Pass SDK artifact to cross-platform tests
- Add validation: releasing LFX requires releasing SDK
- Add pre-release version handling for SDK and LFX's SDK dependency

* Update release.yml

* Update release.yml

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-04-14 01:43:25 +00:00
26c415056c feat: add SHA-256 hash-based API key lookup (#12597)
* feat: add SHA-256 hash-based API key lookup

Replace the O(n) full table scan in check_key with an indexed
SHA-256 hash column for O(1) lookup. Legacy keys without a hash
fall back to decrypt-and-compare and get their hash backfilled
on first successful match.

- Add api_key_hash column to ApiKey model (nullable, indexed)
- Hash stored at key creation time
- Migration adds column and backfills hashes for existing keys
- Fail closed when multiple keys share the same hash
- Remove unused fernet_obj parameter from decrypt_api_key

* fix(migration): skip hashing duplicate-plaintext API keys

Two-pass backfill: decrypt all rows, group by plaintext, then hash only
unique-plaintext rows. Duplicate-plaintext groups are left with NULL
hash so the runtime fast-path lookup cannot return multiple matches and
fail closed. The runtime slow-path matches and backfills exactly one
row per group on first use; remaining NULL rows become harmless
orphans.

Logs counts only (no key IDs or plaintexts) to avoid leaking
operational info via deployment logs.

Extracts _backfill_hashes helper for testing; adds 9 unit tests.

---------

Co-authored-by: Eric Hare <ericrhare@gmail.com>
2026-04-13 23:06:44 +00:00
cfaba3ede7 fix: Remove redundant api key field in KB Ingest (#12624)
* fix: Remove redundant api key field in KB Ingest

* Update component_index.json
2026-04-11 21:19:17 +00:00
499815a630 feat: add policies component for tool protection via ToolGuard (#12592)
* feat: add policies component for tool protection via ToolGuard

Reintroduce the policies component from #12564 (originally by @boazdavid).
Adds policy-based tool protection system with business policy enforcement
using ToolGuard, including guard code generation from policy definitions,
support for multiple language models, and enhanced tool metadata.

Adds toolguard>=0.2.4 dependency and click>=8.3.2 override.

* [autofix.ci] apply automated fixes

* Update dependencies for new toolguard

* Update component_index.json

* Update uv.lock

---------

Co-authored-by: DAVID BOAZ <DAVIDBO@il.ibm.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-04-09 15:13:20 +00:00
cde9f23001 feat: deployment page and stepper UI with watsonx Orchestrate integration (#12303)
* feat: deployment page list

* feat: add deployment stepper modal with context-based state management

Implement a multi-step deployment creation flow with 4 steps (Provider,
Type, Attach Flows, Review). State is centralized in a scoped
DeploymentStepperContext to avoid prop-drilling across step components.
Includes bug fixes for version re-selection and connection pre-selection.

* feat: replace mock flows and versions with real API data in deployment stepper

Fetch real flows from the API (scoped to current folder) and versions
per-flow lazily when selected. Enrich selectedVersionByFlow context to
store versionTag alongside versionId so the review step can display it
without re-fetching. Remove MOCK_FLOWS_WITH_VERSIONS from mock-data.

* refactor: improve deployment stepper code quality and conventions

Rename all new deployment files to kebab-case per project conventions,
fix context re-render issues with useMemo/useCallback, replace raw
Tailwind colors with design tokens, add missing data-testid and ARIA
attributes, fix Deploy button disabled on review step, and move shared
FlowTabType to a dedicated types file.

* refactor: align deployment provider types and UI to backend contracts

- Rename ProviderInstance -> ProviderAccount to match backend naming
- Update ProviderAccount fields to match DeploymentProviderAccountGetResponse (provider_key, provider_url, provider_tenant_id, created_at, updated_at)
- Update ProviderCredentials fields to match DeploymentProviderAccountCreateRequest (provider_key, provider_url, api_key)
- Rename all "instance" UI terminology to "environment" (tabs, labels, components)
- Auto-select watsonx Orchestrate on mount as the only supported provider
- Remove Kubernetes from mock providers; update mock data to use watsonx_orchestrate only

* feat: add react-query hooks for deployments and provider accounts with mock data

- Add useGetProviderAccounts hook (GET /deployments/providers) replacing direct MOCK_PROVIDER_INSTANCES import in step-provider.tsx
- Add useGetDeployments hook (GET /deployments) replacing direct MOCK_DEPLOYMENTS import in deployments-page.tsx
- Replace fake setTimeout loading state with hook isLoading state
- Register DEPLOYMENTS and DEPLOYMENT_PROVIDER_ACCOUNTS URL constants
- Real API calls are commented out with TODO markers for easy swap when backend is ready

* chore: remove stale biome-ignore suppression in step-attach-flows

* fix: replace button role=radio with semantic input type=radio in ProviderCard

* fix: replace button role=radio with semantic radio inputs across deployment stepper

- Extract RadioSelectItem component (label + sr-only input + checkbox indicator)
  used by version, connection, and environment selectors
- Fix step-type.tsx type cards with label/input pattern (matching ProviderCard)
- Add role="radiogroup" wrapper to EnvironmentList
- Fix envVars key: use stable crypto.randomUUID() id instead of array index

* feat: add name field to provider accounts, multi-select connections, and real API call

- Add `name` field to ProviderAccount, ProviderCredentials, and mock data
- Switch connection selection from single to multi-select (CheckboxSelectItem)
- Allow creating new connections inline from the attach flows step
- Lift connections state up to DeploymentStepperContext
- Move ConnectionItem type from step-attach-flows to shared types.ts
- Wire up real API call in useGetProviderAccounts (remove mock)

* feat: wire deploy button and populate deployments page with real API data

- Add usePostDeployment and usePostProviderAccount mutation hooks
- Wire Deploy button in stepper modal: creates provider account if needed,
  then POSTs to /api/v1/deployments with WXO provider_data shape
- Fix environment_variables payload: wrap values as { value, source: "raw" }
  to satisfy EnvVarValueSpec schema
- Fix connection app_id: prefix with conn_ so WXO name validation passes
  (names must start with a letter)
- Multi-select connections with checkbox UI; persist connections in context
  so they survive back/forward navigation
- Update Deployment type to match API response shape; remove mock fields
  (url, status, health, lastModifiedBy)
- Wire useGetDeployments to real API; load provider ID from useGetProviderAccounts
- Update deployments table to display real fields: name, type, attached_count,
  provider name, updated_at

* refactor: extract DeploymentsContent component to eliminate nested ternary

* feat: add Test Deployment chat modal for deployed agents

Implements a chat interface to test deployments directly from the UI.
Wires up two entry points: the stepper modal "Test" button (inline
transition) and the deployments table play button (standalone dialog).

- Add usePostDeploymentExecution and useGetDeploymentExecution hooks
  hitting POST/GET /api/v1/deployments/executions
- Build test-deployment-modal: ChatHeader, ChatMessages, ChatInput,
  ChatMessageBubble with user/bot avatars, loading dots, tool traces
- useDeploymentChat hook: recursive setTimeout polling (max 30 × 1.5s),
  thread_id persistence for multi-turn, watsonx response parsing
  (response_type/type text, wxo_thread_id extraction)
- Stepper modal transitions inline to TestDeploymentContent on Test click
- Deployments table play button opens standalone TestDeploymentModal

* feat: add syntax highlighting to chat code blocks using SimplifiedCodeTabComponent

* feat: add action menu and icon-based type badge to deployments table

- Add dropdown action menu (Duplicate, Update, Delete) to each row
- Replace left-border type badge with icon-based badge (Bot for Agent, Plug for MCP)

* refactor: remove connected status from provider card in stepper

* feat: auto-detect flow env vars in deployment connection form

- Add POST /deployments/variables/detections backend endpoint that scans
  flow version data for credential fields (load_from_db=True globals and
  password=True fallbacks) and returns detected variable names
- Derive meaningful env var names from the model field's category when no
  global variable is linked (e.g. OPENAI_API_KEY from category "OpenAI")
- Add DetectEnvVarsRequest/DetectedEnvVar/DetectEnvVarsResponse schemas
- Add usePostDetectDeploymentEnvVars frontend mutation hook
- Pre-populate Create Connection env var rows with detected keys/values
  when attaching a flow version; global variable selections render as tags
  via InputComponent with global variable picker support

* feat: add empty state and smart default tab for available connections

- Default to "Create Connection" tab when no connections exist
- Show empty state with icon, description, and shortcut link when
  the Available Connections tab has no items

* feat: redesign review step with two-column layout and env vars section

Match new design reference with Deployment/Attached Flows columns
and a masked Configuration section showing env variable keys.

* feat: integrate delete deployment with loading state and fix test modal flow

- Add useDeleteDeployment hook (DELETE /deployments/{id}, refetches list)
- Show spinner + faded row while deletion is in progress; fix race where
  deleteTarget was cleared before isPending resolved by using separate deletingId state
- Redesign StepDeployStatus with animated spinner, ping ring, and success checkmark
- After deploy, "Test" closes the stepper and opens the standalone TestDeploymentModal
  (consistent UI, correct providerId, chat reset on close)
- Prevent closing the stepper modal while deployment is in progress

* refactor: address PR review concerns for deployment UI

- Split step-attach-flows.tsx (656→274 lines) into FlowListPanel,
  VersionPanel, and ConnectionPanel sub-components
- Extract Watsonx parser utilities into watsonx-result-parsers.ts,
  reducing use-deployment-chat.ts from 384 to 277 lines
- Surface detectEnvVars errors via setErrorData instead of silently
  resetting state
- Add EnvVarEntry named type to types.ts, replacing inline shape
  repeated across two files
- Move import json to module level in deployments.py (PEP 8)
- Fix URL construction in useGetDeploymentExecution to use axios
  params option, consistent with other hooks
- Remove commented-out MOCK_CONNECTIONS dead code
- Add TODO comment to hardcoded "watsonx-orchestrate" provider key

* refactor: apply React best practices and remove mock data from deployment UI

- Fix barrel imports: import directly from source files in deployments-page,
  step-provider, and step-attach-flows
- Replace useEffect auto-select with derived effectiveFlowId in step-attach-flows
- Fix async state init bug for environmentTab using useRef guard pattern
- Fix stale closure in handleAddEnvVar with functional setState
- Wrap useState initial value in lazy initializer for envVars
- Wrap all 8 handlers in useCallback; wrap panel components in memo()
- Remove mock-data.ts; move PROVIDERS constant inline to step-provider
- Drop MOCK_CONNECTIONS (was empty array) from context
- Simplify step-provider UI: remove provider selection radio group since
  only one provider exists; show watsonx Orchestrate as a static display

* feat: add Deploy button to canvas toolbar

Adds a primary-colored Deploy button at the far right of the canvas toolbar.
Clicking it saves the flow, creates a version snapshot, and opens the
deployment stepper modal with the current flow and version pre-selected in
the Attach Flows step, including auto-detection of environment variable keys.

* chore: disable ENABLE_DEPLOYMENTS feature flag

* fix: forward LANGFLOW_FEATURE_WXO_DEPLOYMENTS env var to frontend

The feature flag was reading from import.meta.env but the variable
was never injected by Vite's define config, so the deployments
feature was always disabled regardless of the .env value.

* feat: implement providers tab with environment list

Replace the "coming soon" placeholder in the Providers sub-tab with a
real table showing existing provider accounts (name, URL, provider key,
created date) fetched from the API, including loading skeleton and
empty state.

* feat: add provider creation modal with tab-aware action button

Create AddProviderModal with name, API key, and URL fields matching
the deploy modal. The top-right button now switches between
"New Deployment" and "New Environment" based on the active sub-tab.

* feat: implement provider account deletion with confirmation modal

Add useDeleteProviderAccount hook, wire it through ProvidersContent
and ProvidersTable with loading/disabled row state on delete, and
reuse DeleteConfirmationModal for the confirmation flow.

* fix: correct provider_key to watsonx-orchestrate and add API key visibility toggle

Fix the provider_key value sent to the API. Add eye/eye-off toggle
to the API Key input in both the add provider modal and the deploy
stepper's provider step.

* feat: navigate to deployments tab and open test modal after canvas deploy

After a successful deployment from the canvas deploy button, clicking
"Test" navigates to the deployments tab and auto-opens the test modal.
Also adds eye toggle to the deploy stepper's API Key field.

* Add llm config to deployment creation workflow

* [autofix.ci] apply automated fixes

* feat: add useGetDeploymentLlms query hook

Add missing query hook for the GET /deployments/llms endpoint,
resolving the broken import in step-type.tsx.

* Create provider env inline of step

Ensures the list llm call has an authed provider account to use

* feat: add extensibility for wxo tools in deployments api (#12425)

* feat(deployments): surface tool_ids in WXO API for explicit tool control
- Fix bind to reuse existing WXO tools via attachment lookup instead of
  always creating new ones
- Add tool_id-based operations (bind_tool, unbind_tool, remove_tool_by_id)
  alongside existing flow_version_id operations
- Add PATCH /deployments/snapshots/{provider_snapshot_id} endpoint to
  update snapshot content with a new flow version (blast-radius bounded
  to Langflow-tracked tools only)
- Add update_snapshot method to WXO adapter
- Enrich flow version list with deployment info (tool_id, tool_name,
  app_ids) via FlowVersionReadWithDeployments API schema
- Surface tool_id in WatsonxApiToolAppBinding responses; flow_version_id
  becomes optional for tool-id-based operations

* Revert "feat: Add Langflow Assistant chat panel for component generation (#11636)"

This reverts commit 61fac94139.

* Add some comments

* Reapply "feat: Add Langflow Assistant chat panel for component generation (#11636)"

This reverts commit d7f08791f0.

* fix(deployments): review fixes for wxo tools extensibility PR

- Add best-effort compensating rollback to update_snapshot endpoint
- Add N+1 TODO for provider account batch-fetch in build_deployment_info_map
- Remove unpopulated app_ids field from FlowVersionDeploymentInfo
- Use elif chains in validate_operation_references for tool-id ops
- Strip provider_snapshot_id once at function entry
- Add note about WXO-only update_snapshot adapter method
- Replace call-count-based _MultiQueryFakeDb with table-name dispatch
- Fix SnapshotUpdateRequest docstring route path

* fix doc

---------

Co-authored-by: Jordan Frazier <jordan.frazier@datastax.com>

* feat: allow attaching flows without connections in deployment stepper

Connections are now optional when attaching flows in step 3. Users can
skip the connection panel and proceed with just a version selected.
The deploy payload iterates selectedVersionByFlow so flows without
connections are included with an empty app_ids array.

* feat: show attached connections per flow in deployment stepper

Display connection names under each flow in the flow list panel so
users can see what's attached at a glance. Refactor the review step
to show configuration scoped per flow instead of a flat list.

* remove unused enriched flow version data. to be replaced by a new endpoint in /deployments

* Allow nonraw env vars wxo (#12435)

Allow vars to be interpreted through global vars

* feat: add update existing deployment from canvas deploy button (#12440)

* feat: add update existing deployment from canvas deploy button

When clicking Deploy on the canvas, if the flow already has existing
deployments, a choice dialog is shown allowing the user to either
update an existing deployment or create a new one. Updating calls
PATCH /deployments/snapshots/{provider_snapshot_id} with the new
flow version.

Backend changes:
- New GET /deployments/flow-attachments/{flow_id} endpoint to discover
  existing deployments for a flow
- New CRUD function list_attachments_for_flow_with_deployment_info
- New schemas FlowDeploymentAttachmentItem/FlowDeploymentAttachmentsResponse
- Fix update_snapshot to properly construct flow_definition with nested
  data structure, name, description, and last_tested_version
- Fix rollback path to cache ORM values before session.rollback()

Frontend changes:
- New useGetFlowDeploymentAttachments and usePatchSnapshot hooks
- New DeployChoiceDialog component with radio selection
- Modified deploy button to check for existing deployments on click

* feat: add flow_ids filter to deployments endpoint and fix snapshot update
Add a `flow_ids` query parameter to GET /deployments so the frontend can
discover which deployments a flow is part of. The response includes a new
`matched_attachments` field with per-attachment `flow_version_id` and
`provider_snapshot_id`, replacing the non-existent flow-attachments endpoint.
Refactor PATCH /snapshots to accept BaseFlowArtifact (via the mapper's new
resolve_snapshot_update_artifact method) instead of a raw dict, fixing the
misleading "Deployment name must include at least one alphanumeric character"
error that occurred because flow_version.data lacks a name field.
Frontend: rewrite useGetFlowDeploymentAttachments to query the real
GET /deployments endpoint per provider account.

* feat: refactor deploy dialog with update-snapshot flow and phased UI

Restructure deploy-choice-dialog into modular phases (provider, review,
deployment, update) to support both new deployments and snapshot updates.
Add use-get-deployments-by-providers query replacing the removed
flow-attachments endpoint, extract provider-credentials-form component,
and add error/navigation helpers. Backend: validate flow_id as string
in WatsonX Orchestrate service before deployment.

* [autofix.ci] apply automated fixes

* ruff

---------

Co-authored-by: Hamza Rashid <hzarashid@gmail.com>
Co-authored-by: Hamza Rashid <74062092+HzaRashid@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* feat: reorder model field and add scrollable dropdown in deploy wizard type step

Move Model select to appear after Agent Name (before Description) and
constrain the dropdown with max-height + scroll. A bouncing chevron
indicator fades in/out to signal more items below.

* feat(deployments): add paginated deployment flow-version listing (#12453)

* feat(deployments): add paginated deployment flow-version listing with snapshot sync
Add a new read path for listing flow versions attached to a deployment:
- introduces GET /deployments/{deployment_id}/flows with page/size pagination
- returns attachment-scoped metadata (flow_version id, flow_id, version_number, attached_at, provider_snapshot_id)
- keeps provider-owned fields under provider_data on each item
Implement snapshot-aware synchronization behavior for this list endpoint:
- loads deployment attachments from DB, extracts provider_snapshot_id values, and verifies them via adapter list_snapshots(snapshot_ids=...)
- removes stale attachment rows when snapshot IDs no longer exist on the provider
- falls back to DB-only response without enrichment on any sync failure (including partial failures after list_snapshots)
Refactor mapper boundaries to follow shape_* contract conventions:
- helper now passes through SnapshotListResult | None instead of pre-building enrichment maps
- route delegates full response shaping to mapper.shape_flow_version_list_result(...)
- base mapper performs direct DB->API mapping for flow-version list items
- WXO mapper overrides list shaping to enrich provider_data with connection_app_ids from snapshot binding.langflow.connections
Normalize WXO connection extraction into a shared read-path helper:
- add extract_langflow_connections_binding(...) in core/tools.py
- reuse it in verify_tools_by_ids and service config listing to avoid duplicated nested payload parsing
Add/adjust persistence and tests:
- add CRUD helpers for paginated attachment+flow_version join and attachment counting
- extend schema and route tests for new response models/endpoint behavior
- add mapper tests for base direct mapping and WXO-specific enrichment
- add sync tests for snapshot-id verification, stale-row cleanup, and fallback semantics

* fix(deployments): normalize wxo snapshot provider_data contracts
Validate and normalize snapshot connection payloads across mapper/service flows, and align flow-version item provider_data to use app_ids.
Add typed snapshot-item schema support in lfx and expand tests for missing/malformed snapshot provider_data behavior.

* add flow name

* return empty app_ids list instead of null

---------

Co-authored-by: Jordan Frazier <jordan.frazier@datastax.com>

* ref: remove resource name prefix (#12459)

* refactor: remove resource_name_prefix from all naming paths

Remove the resource_name_prefix concept entirely. Tool names now use the
exact flow name (or user-provided name in the future). Agent names use the
deployment name directly with no prefix.

BE:
- Delete resource_name_prefix.py
- Remove field + validators from API schemas (create + update)
- Remove field + validators from adapter schemas (create + update)
- Remove from mapper _build_provider_payload_body
- Remove resource_prefix from ProviderCreatePlan and ProviderUpdatePlan
- Remove tool_name_prefix from all tool creation functions
- Remove resolve_resource_name_prefix from utils
- Remove prefix constants from constants.py
- Remove prefixed_deployment_name from config.py
- Clean 5 test files (remove prefix-only tests, update payloads)

FE:
- Remove toResourceNamePrefix function from types.ts
- Remove resource_name_prefix from DeploymentCreateRequest type
- Remove usage from deployment-stepper-context.tsx payload builder

* [autofix.ci] apply automated fixes

* refactor: remove resource_name_prefix from all naming paths

Remove the resource_name_prefix concept entirely. Tool names now use the
exact flow name (or user-provided name in the future). Agent names use the
deployment name directly with no prefix.

BE:
- Delete resource_name_prefix.py
- Remove field + validators from API schemas (create + update)
- Remove field + validators from adapter schemas (create + update)
- Remove from mapper _build_provider_payload_body
- Remove resource_prefix from ProviderCreatePlan and ProviderUpdatePlan
- Remove tool_name_prefix from all tool creation functions
- Remove resolve_resource_name_prefix from utils
- Remove prefix constants from constants.py
- Remove prefixed_deployment_name from config.py
- Clean 5 test files (remove prefix-only tests, update payloads)

FE:
- Remove toResourceNamePrefix function from types.ts
- Remove resource_name_prefix from DeploymentCreateRequest type
- Remove usage from deployment-stepper-context.tsx payload builder

---------

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

* feat: wxo custom tool naming (#12460)

feat: custom tool naming when attaching flows to deployments

Users can now name tools when attaching flows in the deployment stepper.
If left blank, the flow name is used as the tool name.

BE:
- Add optional tool_name field to WatsonxApiBindOperation
- Mapper overrides raw_name_by_flow_version_id with user-provided tool_name
- Apply custom name to both raw payloads and provider bind operations

FE:
- Add toolNameByFlow state + setToolNameByFlow to stepper context
- Include tool_name in bind operations when set (trimmed, omitted if empty)
- Tool Name input in version panel (shown when a version is selected)
- Review step shows tool name (custom or flow name) in config cards
  with flow name + version underneath

* feat(deployments): derive connection ID from user-provided name

Replace random UUID generation with a sanitized version of the
connection name. Input is restricted to alphanumeric, underscore,
and space characters; spaces are converted to underscores in the ID.

* feat(deployments): prevent duplicate connection names

Disable the Create Connection button and show a validation error
when a connection with the same name (case-insensitive) already exists.

* refactor(deployments): extract page logic into custom hooks and self-contained tab components

Extract state management from the monolithic DeploymentsPage into focused
custom hooks (useDeleteWithConfirmation, useProviderFilter, useTestDeploymentModal)
and consolidate each tab's modals into its own content component, reducing the
page from 270 to 62 lines.

* fix(deployments): forward thread_id through WxO execution lifecycle

* fix(deployments): extract WxO tool call traces from actual step_history format

The parser expected tool_use/tool_result fields but WxO returns
type: "tool_calls" with tool_calls[] and type: "tool_response" —
traces were never being extracted. Rewrites extractToolTraces to
correlate calls with responses via tool_call_id, captures
agent_display_name, and makes each trace individually expandable.

* feat(deployments): refactor WXO deployment schemas and create response mapping (#12454)

* feat(deployments): add paginated deployment flow-version listing with snapshot sync
Add a new read path for listing flow versions attached to a deployment:
- introduces GET /deployments/{deployment_id}/flows with page/size pagination
- returns attachment-scoped metadata (flow_version id, flow_id, version_number, attached_at, provider_snapshot_id)
- keeps provider-owned fields under provider_data on each item
Implement snapshot-aware synchronization behavior for this list endpoint:
- loads deployment attachments from DB, extracts provider_snapshot_id values, and verifies them via adapter list_snapshots(snapshot_ids=...)
- removes stale attachment rows when snapshot IDs no longer exist on the provider
- falls back to DB-only response without enrichment on any sync failure (including partial failures after list_snapshots)
Refactor mapper boundaries to follow shape_* contract conventions:
- helper now passes through SnapshotListResult | None instead of pre-building enrichment maps
- route delegates full response shaping to mapper.shape_flow_version_list_result(...)
- base mapper performs direct DB->API mapping for flow-version list items
- WXO mapper overrides list shaping to enrich provider_data with connection_app_ids from snapshot binding.langflow.connections
Normalize WXO connection extraction into a shared read-path helper:
- add extract_langflow_connections_binding(...) in core/tools.py
- reuse it in verify_tools_by_ids and service config listing to avoid duplicated nested payload parsing
Add/adjust persistence and tests:
- add CRUD helpers for paginated attachment+flow_version join and attachment counting
- extend schema and route tests for new response models/endpoint behavior
- add mapper tests for base direct mapping and WXO-specific enrichment
- add sync tests for snapshot-id verification, stale-row cleanup, and fallback semantics

* fix(deployments): normalize wxo snapshot provider_data contracts
Validate and normalize snapshot connection payloads across mapper/service flows, and align flow-version item provider_data to use app_ids.
Add typed snapshot-item schema support in lfx and expand tests for missing/malformed snapshot provider_data behavior.

* add flow name

* return empty app_ids list instead of null

* feat(deployments): refactor WXO deployment schemas and create response mapping
Restructure the Watsonx Orchestrate deployment contracts to remove redundant connection declaration and make create responses explicit and typed.
- Remove `existing_app_ids` from API and adapter `connections` payload schemas.
- Replace shared API payload base with separate create/update models and focused validators.
- Keep validation strict (no legacy/backward-compat handling for removed fields).
- Derive provider-side `existing_app_ids` in plan builders from:
  operation app_ids - connections.raw_payloads[*].app_id
- Stop passing `existing_app_ids` through mapper payload translation.
- Add explicit create response shaping via mapper (`shape_deployment_create_result`) and route integration.
- Introduce typed create provider_data structure with `created_app_ids` and `tool_app_bindings`.
- Document and enforce `source_ref` normalization semantics:
  UUID refs map to `flow_version_id`; non-UUID refs map to `None`; empty refs error.
- Remove obsolete create-response helper path and align mapper interface signatures.
- Update unit tests and assertions to reflect the new contract and validation wording.

* improve api error logs (remove internal details and surface more informative message when an invalid field is provided

* feat(deployments): API contract updates, bug fixes, and observability improvements
BREAKING CHANGES (API):
- Move variable detection endpoint from POST /deployments/variables/detections
  to POST /variables/detections (variables router)
- Rename `reference_ids` to `flow_version_ids` in DetectVarsRequest schema
- Remove `existing_app_ids` from WXO create/update connection payloads
- Remove `resource_name_prefix` from WXO create/update payloads
- Add optional `tool_name` field to WXO bind operations
Backend:
- Rename DetectEnvVarsRequest/Response to DetectVarsRequest/Response (internal)
- Fix tool name mismatch (`name_of_raw not found in tools.raw_payloads`) during
  deployment updates by applying tool_name override and aligning
  filtered_raw_payloads with name-updated artifacts in the WXO mapper
- Fix "Missing snapshot bindings for added flow versions on update" by filtering
  out already-attached flow version IDs in the route handler before calling
  resolve_added_snapshot_bindings_for_update (stateless, DB-backed filtering)
- Switch WXO adapter core modules (retry, update, shared, create, tools) from
  stdlib logging to lfx.log.logger (structlog) for consistent log output
- Upgrade rollback log calls from info to warning level for visibility
- Add logger.exception() calls in handle_adapter_errors() for
  DeploymentServiceError, NotImplementedError, and ValueError to surface
  provider errors (e.g. validation failures) in backend logs with tracebacks
Frontend:
- Remove existingAppIds from deployment stepper context and create payload
- Move detect-env-vars hook from deployments/ to variables/ query directory
- Update step-attach-flows import path and payload field (flow_version_ids)
Tests:
- Add 15 unit tests for detect_env_vars endpoint and _derive_env_var_name helper
- Add 3 route-handler tests for already-attached flow version filtering on update
- Update WXO adapter tests: drop existing_app_ids, fix agent name assertions,
  fix mock signatures, adapt logging test for structlog

* fix: harden detect_env_vars endpoint against abuse
- Add max_length=50 on flow_version_ids to prevent resource exhaustion
- Hide /detections from OpenAPI schema (consistent with other variable routes)
- Return unresolved_ids in response so callers know which version IDs were skipped

* feat: add update agent impl (#12475)

* Allow updating an agent

ONLY allows attaching and detaching Flows.
Does NOT allow attaching / detaching connections, or editing attached
tool names.

* [autofix.ci] apply automated fixes

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

* remove print

* add missing files

* mypy

* Add edit flow tests

* [autofix.ci] apply automated fixes

---------

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

* feat: add list all conns impl for wxo create deploy workflow (#12476)

* feat(deployments): list all WXO tenant connections in create workflow

- Fix backend list_configs to handle SDK Pydantic model objects (not just dicts)
- Add useGetDeploymentConfigs hook to fetch tenant connections by provider
- Seed existing connections into the attach-flows step on mount
- Add search/filter input for the available connections list
- Raise configs endpoint page size cap to 10k for large tenants

* test(deployments): add list_configs tests for Pydantic model handling

Cover the fix where SDK ConnectionsClient.list() returns Pydantic
model objects instead of dicts: pure models, mixed dicts+models,
deduplication, and non-dict/non-model skip behavior.

* add todo

* [autofix.ci] apply automated fixes

* fix(tests): update imports for removed to_deployment_create_response helper

The helper was replaced by BaseDeploymentMapper.shape_deployment_create_result
in the schema refactor (#12454). Update both test files to use the new method.

* fix(tests): remove shape_deployment_create_result from passthrough test

Method signature changed from single-arg passthrough to (result, deployment_row)
in the schema refactor (#12454). It's now tested in test_deployment_description_and_type.py.

* tests

---------

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

* feat(deployments): improve attach flow step UX in deploy modal (#12482)

- Add detach flow button in both create and edit modes
- Defer version attachment until connection step is completed (skip/attach)
- Replace radio indicators with clickable version items that auto-advance to connections
- Move tool name editing to review page with inline edit/confirm pattern
- Sort newly created connections to top of list and remove variable count display
- Add visual distinction (blue border/bg) for attached versions
- Split review page connections into "Existing" and "New" sections

* feat(deployments): add expandable rows to show attached flows (#12483)

Allow users to click the "Attached" count in the deployments table to
expand a row showing the flow names and versions. Flows are fetched
lazily via GET /deployments/{id}/flows only when the row is expanded.

* feat(deployments): replace Duplicate with Details modal (#12492)

feat(deployments): replace Duplicate action with Details modal

Replace the unused "Duplicate" action menu item with a "Details" option
that opens a read-only modal showing deployment info, attached flows,
and their connections. Data is fetched via useGetDeployment,
useGetDeploymentAttachments, and useGetDeploymentConfigs.

* Add wxo lfx req override

* feat(wxo): tool name handling, rename support, and ownership safety (#12502)

* feat(wxo): tool name handling, rename support, and ownership safety

- Fix update_snapshot to preserve existing wxO tool name instead of
  deriving from flow name (prevents overwriting custom tool names)
- Add _validate_tool_name at API boundary with deferred validation so
  user-provided tool_name overrides aren't blocked by invalid flow names
- Add rename_tool operation (API + provider + plan + apply) with safety
  checks: tool must be on agent, must exist, must have binding.langflow
- Add verify_langflow_owned guard to all tool mutation paths (create,
  update, rename) to prevent modifying non-Langflow-managed tools
- Add WXO_LFX_REQUIREMENT_OVERRIDE env var for lfx version pinning
- Pre-seed resolved_connections from existing agent tools during update
- Surface tool_name in /flows endpoint response from wxO snapshot data
- Pre-populate tool names and connections in edit mode stepper (FE)
- Emit rename_tool operations from FE when pre-existing tool name changes
- Sort attached flows to top of flow list in edit mode (FE)
- Fix FE sending unsupported existing_app_ids field in update payload
- Add 24 backend + 6 frontend tests covering ownership checks, rename
  safety, name validation, plan building, env var override, and payloads

* [autofix.ci] apply automated fixes

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

* chore(wxo): trim verbose pre-seeding logs, add plan entry/exit logging

- Condense per-tool pre-seeding debug logs into a single summary line
- Add plan summary log at entry of apply_provider_create_plan_with_rollback
- Add plan summary log at entry of apply_provider_update_plan_with_rollback
- Add agent creation result log in create path

* fix(wxo): resolve mypy, ruff, and lint errors

- Fix dict[str, str] → dict[UUID, str] type annotation for
  raw_name_by_flow_version_id in mapper create/update paths (mypy)
- Move logger assignment after imports in config.py (ruff E402)
- Remove unnecessary result variable in shared.py (ruff TRY300/RET504)
- Add raise-from chain in tools.py _resolve_lfx_requirement (ruff B904)
- Hoist class aliases to module level in tests (ruff N806)

* fix(wxo): resolve mypy, ruff, and lint errors

- Fix dict[str, str] → dict[UUID, str] type annotation for
  raw_name_by_flow_version_id in mapper create/update paths (mypy)
- Use .items() for dict iteration instead of key-only loop (ruff PLC0206)
- Move logger assignment after imports in config.py (ruff E402)
- Remove unnecessary result variable in shared.py (ruff TRY300/RET504)
- Add raise-from chain in tools.py _resolve_lfx_requirement (ruff B904)
- Split long log format string in create.py (ruff E501)
- Hoist class aliases to module level in tests (ruff N806)

---------

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

* refactor(deployments): Revise v1 deployments API (#12478)

* refactor(deployments): trim top-level deployment API surface for WXO-first flow
- Remove unused deployment stub routes and schemas:
  - drop POST /deployments/{deployment_id}/redeploy and /duplicate handlers
  - remove DeploymentRedeployResponse and DeploymentDuplicateResponse usage
  - remove corresponding route-handler unit tests
- Simplify deployment list response contract:
  - remove deployment_type from DeploymentListResponse
  - update deployments route and base/WXO mapper list shapers to stop passing deployment_type
- Make deployment request schemas API-owned and stricter:
  - replace shared-kernel strict wrappers with DeploymentSpec / DeploymentSpecUpdate
  - remove create/update top-level config and flow-version mutation fields
    (flow_version_ids, add_flow_version_ids, remove_flow_version_ids, config)
  - tighten update validation to only accept spec and/or provider_data
- Align mapper behavior with trimmed API contracts:
  - base mapper create/update now maps spec explicitly to BaseDeploymentData/BaseDeploymentDataUpdate
  - remove base create/update handling for top-level snapshot/config/flow-version passthrough
  - make base util_create_flow_version_ids and util_flow_version_patch return empty results by default
  - update WXO mapper to use explicit spec mapping and provider_data-only operation reconciliation
  - remove WXO 422 guards tied to removed top-level config/flow-version request fields
- Remove obsolete provider_spec plumbing in adapter schema/utilities:
  - drop ProviderSpecModel and T_DeploymentSpec usage from lfx deployment schema
  - make BaseDeploymentData inherit directly from BaseModel
  - remove unused build_agent_payload helper that depended on provider_spec from WXO utils
- Update tests to reflect the trimmed contracts and current behavior:
  - remove schema tests for removed config/flow-version helper models
  - update schema compatibility tests to reject provider_spec in API deployment spec
  - update base mapper tests for new create-result shaping and provider payload validation expectations
  - remove WXO mapper tests asserting rejected top-level config/flow-version inputs
  - adjust WXO mapper naming assertions to current flow/tool naming behavior
  - update sync/service/payload formalization tests for provider_data-driven operations and provider_spec removal

* refactor(deployments): normalize deployment metadata and list payload contracts
- Source `get_deployment` name/description/type/timestamps from DB deployment rows and stop injecting `resource_key` into provider payloads.
- Clarify schema docs that `resource_key` is provider-originated but Langflow-owned once persisted.
- Replace `DeploymentConfigListItem`/`DeploymentSnapshotListItem` response envelopes with paginated `provider_data` payloads in API schemas.
- Update base deployment mapper to serialize config/snapshot items directly into paginated `provider_data.configs` and `provider_data.snapshots`.
- Add WXO API payload models and validation slots for config-list and snapshot-list provider result metadata.
- Add WXO adapter payload result contracts (`WatsonxConfigListResultData`, `WatsonxSnapshotListResultData`) and register them in deployment payload schemas.
- Update WXO service list-config/list-snapshot flows to parse and emit normalized provider result metadata (tenant scope now `{}`, deployment scope includes `deployment_id` and optional `tool_ids`).
- Remove `provider_data` from `lfx` `ConfigListItem` to align with the new list response contract.
- Update mapper registration tests to assert config/snapshot payload slots are wired.
- Update route-handler tests for new provider-result expectations and add regression coverage that `resource_key` is not injected into `provider_data`.
- Rewrite deployment schema tests around provider-data-only config/snapshot list responses and field-surface checks.
- Update WXO service tests for tenant-scope provider-result normalization.
- Update `lfx` schema tests to remove obsolete config-item `provider_data` assertions.

* feat(deployments): add WXO mapper shaping for config-list and snapshot-list responses
- Add `shape_config_list_result` and `shape_snapshot_list_result` to WXO
  deployment mapper with pagination, slot validation, and HTTP 500 on
  malformed payloads.
- Add `WatsonxApiConfigListItem` and `WatsonxApiSnapshotListItem` strict
  payload models with string normalization validators.
- Wire `configs` and `snapshots` item lists into the existing
  `WatsonxApiConfigListProviderData` and `WatsonxApiSnapshotListProviderData`
  provider-data envelopes.
- Add mapper unit tests for config-list slot validation, snapshot-list
  connections extraction, and malformed-payload rejection.
- Remove obsolete `resource_name_prefix` and `connections` from
  deployment-sync update test fixture.

* feat(deployments): add provider identity to responses, nest execution endpoints under deployments
Surface provider_id and provider_key on all deployment responses so
clients can identify which provider owns a deployment without a side
lookup. Nest execution endpoints under their parent deployment path
and drop redundant deployment_id / provider_id parameters that clients
previously had to supply.
Deployment responses:
- Add provider_id (UUID) and provider_key (str) to _DeploymentResponseBase,
  propagating to DeploymentGetResponse, DeploymentCreateResponse,
  DeploymentUpdateResponse, DeploymentStatusResponse, and DeploymentListItem.
- Add provider_key parameter to BaseDeploymentMapper.shape_deployment_create_result,
  shape_deployment_update_result, and shape_deployment_list_items.
- Update WatsonxOrchestrateDeploymentMapper overrides to match.
- Update resolve_adapter_from_deployment to return (row, adapter, provider_key)
  and resolve_adapter_mapper_from_deployment to return
  (row, adapter, mapper, provider_key).
- All route handlers pass provider_key through to shape methods and
  response constructors.
Execution endpoints:
- POST /executions → POST /deployments/{deployment_id}/executions.
  deployment_id moves from the request body to the URL path.
- GET /executions/{execution_id}?deployment_id=...
  → GET /deployments/{deployment_id}/executions/{execution_id}.
  deployment_id moves from a query param to the URL path.
- Remove deployment_id from ExecutionCreateRequest schema.
- Remove unused resolve_adapter_mapper_from_provider_id import.
Tests:
- Update all mapper tests to pass provider_key and assert provider_id /
  provider_key on shaped responses.
- Update route handler mocks for new helper return tuple sizes.
- Remove deployment_id from ExecutionCreateRequest test constructions.
- Fix pre-existing broken test_deployments_response_mapping.py (was
  importing removed to_deployment_create_response helper; now uses
  BaseDeploymentMapper.shape_deployment_create_result).

* refactor(deployments): delegate conflict error messaging to provider mappers
Move provider-specific conflict formatting out of shared helpers by adding a base mapper hook and a Watsonx override, thread mapper-aware conflict formatting through adapter error handling, and add tests for mapper delegation and fallback behavior.

* refactor(deployments): rename provider-account API fields and make update identifiers immutable
- rename provider-account API fields for cleaner contracts:
  - create/get: provider_tenant_id -> tenant_id
  - create/get: provider_url -> url
  - keep provider_key and provider_data unchanged
- enforce immutable provider-account identifiers on PATCH:
  - remove tenant_id and url from DeploymentProviderAccountUpdateRequest
  - remove update-path URL allowlist validation
  - trigger update credential verification only when provider_data changes
  - limit provider-account updates to name and provider_data
- simplify mapper update behavior:
  - resolve_provider_tenant_id now uses tenant_id parameter naming
  - remove no-op WXO resolve_provider_account_update override
  - remove dead auth_utils/decrypt path in WXO update verification
- align frontend deployment-provider-account usage with new API fields:
  - POST payload now sends url
  - ProviderAccount/ProviderCredentials now use tenant_id/url
  - deployment provider UI components now read/write url consistently
- update deployment mapper rules and backend tests for new contract
- verify with targeted backend tests: 245 passed

* fix(deployments): flatten API payloads, normalize execution routes, and trim null response fields
- flatten v1 deployment API request contracts by removing nested `spec` from create/update payloads
  - create now uses top-level `name`, `description`, `type`
  - update now uses top-level `name`, `description`, `provider_data`
- update backend handlers and mapper wiring to consume top-level deployment fields end-to-end
- fix execution route paths to avoid duplicated segment:
  - `/api/v1/deployments/{deployment_id}/executions`
  - `/api/v1/deployments/{deployment_id}/executions/{execution_id}`
- align frontend execution query hooks/chat flow with deployment-id path params and remove provider-id execution params
- add response null-trimming tweaks in deployment read/list endpoints:
  - set `response_model_exclude_none=True` on deployment list route
  - set `response_model_exclude_none=True` on deployment get route
  - normalize empty/non-dict `provider_data` to `None` before shaping detail response
- tighten watsonx API mapper payload contract:
  - type `connections.raw_payloads[*].environment_variables` as `dict[EnvVarKey, EnvVarValueSpec]`
  - remove unused API-level `provider_config` field from update raw connection payload
- refresh backend/frontend tests and deployment endpoint docs to match current API shapes and routes

* feat(deployments): redesign list contracts and normalize WXO payloads
Rework deployment list and flow attachment contracts to support flow-filtered list responses and lazy flow-version lookup in the frontend deploy dialog. Normalize WXO provider payload shapes by flattening provider entries, renaming identifier fields, and tightening adapter/API validation.
- replace deployment list-item matched_attachments with conditional flow_version_ids (omitted when no flow filter is provided)
- add flow_ids support to GET /api/v1/deployments/{id}/flows and propagate it through deployment sync helpers and flow_version_deployment_attachment CRUD filters
- flatten load_from_provider deployment entries, rename provider resource_key to id, and validate WXO entries with explicit fields
- rename WXO provider_data snapshot_ids to tool_ids for provider list/config metadata payloads
- inline WXO provider list entry model_validate payload construction for cleaner mapper logic
- add deployment description max-length contract in adapter/API schemas and enforce it in deployment CRUD create/update paths
- update frontend deploy-choice dialog to a two-request flow (list deployments first, fetch /flows on selection) and align FE deployment types/query hook params
- refresh mapper/route/schema/sync/frontend tests and add dedicated CRUD tests for deployment description length validation

* feat(deployments): align WXO provider_data list and connection payload contracts
- make provider-only deployment list responses use provider_data.deployments and omit top-level deployments/pagination fields
- rename config/snapshot provider_data list keys to connections and tools, and move page/size/total into provider_data
- remove provider_data.deployment_id from config/snapshot list payload shaping
- rename API connection input fields from raw_payloads to key_value and environment_variables to credentials
- add explicit credential item model (key/value/source) with duplicate-key validation
- map API credentials list back to adapter environment_variables dict in mapper for adapter compatibility
- make shared pagination fields optional in deployment response schemas and update config-list provider_data description to "connections"
- set response_model_exclude_none on /configs and /snapshots list routes to suppress unused top-level null pagination fields
- apply formatter quote normalization in WXO config validation debug log

* feat(deployments): add connection type to config listings, enforce security_scheme, and trim leaked adapter fields
- Config list items now expose a `type` field derived from the provider's
  `security_scheme`, enabling callers to distinguish connection types
  (e.g. `key_value_creds`) without a separate lookup
- Requests that return provider_data without a valid `security_scheme`
  now fail fast with HTTP 500 instead of silently omitting the type
- Config list responses no longer leak `tool_ids` or `deployment_id` —
  these were adapter-internal fields with no frontend or API consumers
- Snapshot list responses no longer leak `deployment_id`

* feat(deployments): flatten WXO API operations into per-entity keyed fields
Replace the discriminated `operations` array with explicit per-entity
fields for better type safety and developer experience:
- Create: `add_flows` + `upsert_tools` (create-only item, no remove_app_ids)
- Update: `upsert_flows` + `upsert_tools` + `remove_flows` + `remove_tools`
Each item carries its own add/remove app-id deltas instead of relying on
op-tag dispatch. The mapper consumes the new shapes directly and produces
unchanged adapter-layer operations, eliminating all isinstance dispatch.
Also corrects FlowVersionPatch semantics: upsert_flows.remove_app_ids
now only unbinds connections without detaching the flow from the agent;
detachment is exclusively driven by remove_flows.

* feat(deployments): align watsonx create/update payloads and created-tools responses
- Add `resource_key` to deployment create/update API responses and mapper output.
- Replace API-facing `tool_app_bindings` with `created_tools` in watsonx mapper responses.
- Shape `created_tools` from created snapshot/tool refs only (not all referenced tools).
- Flatten request `provider_data.connections` from nested `connections.key_value` to a direct list.
- Add duplicate `connections.app_id` validation using Counter and update related validation messages.
- Document connection typing strategy: implicit key_value today, future type field with default.
- Add strict `flow_version_id` validation on `WatsonxApiCreatedTool`
  (accept UUID or UUID string; reject other types/invalid UUIDs).
- Update mapper/unit tests for new response contract, flattened connections, and non-UUID rejection.

* fix(deployments): allow watsonx updates without llm
Make PATCH provider_data.llm optional in the Watsonx deployment flow while preserving create-time llm requirements.
- allow missing llm in the API update payload model
- only include llm in mapper-built provider payloads when explicitly provided
- remove adapter update-schema validation that required llm for update operations
- clarify validator docs for empty/no-op provider_data handling
- update mapper/service/schema tests to accept update payloads without llm

* fix(deployments): normalize wxo config list to connection_id/app_id and fix provider_accounts naming
Align the config-list contract end-to-end so that items are keyed by
connection_id + app_id (matching the upstream SDK model) instead of
opaque id/name pairs derived from dict introspection.
Backend:
- Reshape mapper/payloads to emit connection_id/app_id/type.
- Replace loose dict/model_dump parsing with strict ListConfigsResponse
  type checks; add _build_config_list_item factory and
  _normalize_optional_text with documented SDK quirk guards.
- Enrich deployment-scope configs with security_scheme type via
  get_drafts_by_ids.
- Rename DeploymentProviderAccountListResponse.providers to
  provider_accounts for consistency with the entity name.
- Remove leftover debug print/hardcoded requirements in core/tools.
Frontend:
- Migrate DeploymentConfigItem to connection_id/app_id/type and
  unwrap provider_data.connections in the query hook.
- Access provider_accounts instead of providers on the list response.
- Add onBlur confirm for editable tool names; fix overflow/truncation
  in the connection panel.
Tests:
- Use real ListConfigsResponse SDK model in service tests.
- Add scope-shape consistency, type preservation, dict-filtering, and
  mapper contract tests.

* fix(deployments): remove stale-tool fallback in list_snapshots and log unresolved IDs
Replace the phantom-stub fallback that synthesized SnapshotItems for
agent-referenced tool IDs when get_drafts_by_ids returned no results.
Those tools were likely deleted on the provider, and returning stubs
with the ID as the name and empty connections masked stale references
and risked corrupting downstream attachment sync.
Now returns only snapshots that actually resolve from the provider and
logs a warning with the stale tool IDs for observability. Also handles
partial resolution (some tools found, some not).
Update existing test to provide real tool data and add coverage for
all-stale and partial-resolution scenarios.

* fix(deployments): fail fast on invalid wxo config entries and trust provider identifiers
Fail fast when wxO returns unexpected config-list entry types, and preserve provider-provided connection/app identifiers without local normalization or deduplication. Also narrow conflict-detail mapping for connection errors to real conflict messages and update tests to match the new behavior.

* refactor: move tenant_id from top-level into provider_data for provider accounts
tenant_id is a provider-specific concept (e.g., WXO tenant vs Azure AD
tenant vs AWS account_id) and does not have universal semantics across
deployment providers. Moving it into provider_data keeps the top-level
API surface limited to Langflow-universal fields (id, name, provider_key,
url, timestamps) and lets each provider define its own metadata shape.
API schema changes:
- DeploymentProviderAccountCreateRequest: remove top-level tenant_id
  field; tenant_id now arrives inside provider_data alongside api_key
- DeploymentProviderAccountGetResponse: remove top-level tenant_id;
  add provider_data field for non-sensitive provider metadata (e.g.
  {"tenant_id": "..."} for WXO); credentials are excluded
- DeploymentProviderAccountUpdateRequest: unchanged (already uses
  provider_data for credential rotation)
Base mapper (base.py):
- resolve_provider_tenant_id: signature changed from (provider_url,
  tenant_id) to (provider_url, provider_data); delegates to new
  resolve_provider_tenant_id_from_data() for extraction/validation
- shape_provider_account_response: now includes provider_data via new
  shape_provider_account_provider_data() method that returns non-sensitive
  metadata (tenant_id when present)
WXO mapper (watsonx_orchestrate/mapper.py):
- resolve_provider_tenant_id: updated signature; extracts tenant_id
  from provider_data first, falls back to URL extraction
- _validate_provider_data: strips mapper-owned metadata keys (tenant_id)
  before passing to WatsonxVerifyCredentialsPayload slot (extra=forbid)
- New _credential_provider_data() helper for metadata/credential separation
Route + helpers:
- deployments.py create_provider_account: passes payload.provider_data
  (not payload.tenant_id) to resolve_provider_tenant_id
- helpers.py resolve_provider_tenant_id: updated parameter from
  tenant_id to provider_data
Frontend:
- ProviderAccount type: replaced tenant_id with optional provider_data
RULES.md: updated credential flow and defense-in-depth sections to
reflect provider_data as the source for provider metadata.
Tests: updated schema, base mapper, WXO mapper, and route handler tests
to use provider_data for tenant_id. Added tests for tenant metadata
passthrough, credential field filtering, and top-level tenant_id
rejection. Fixed two pre-existing test stubs missing resource_key.
No DB model or migration changes -- provider_tenant_id column remains;
the mapper extracts it from provider_data and stores it as before.

* fix: follow deployment boundary rules and fail fast (wxo) (#12539)

* feat(wxo): filter configs to key_value_creds, surface type and environment, harden mapper contract
Service layer (service.py):
- Filter list_configs to only return connections with security_scheme == "key_value_creds" in both tenant and deployment scopes
- Surface `environment` field alongside `type` in provider_data for config list items
- Normalize security_scheme via _normalize_optional_text to handle SDK enum/tuple quirks
- Extract _warn_if_expected_ids_missing helper to deduplicate staleness warnings
- Remove defensive isinstance checks on provider responses (trust the provider)
- Replace conflicting-binding error with last-write-wins (app_to_connection_id.update)
- Deduplicate connection IDs before calling get_drafts_by_ids
Mapper layer (mapper.py):
- Fail fast with HTTP 500 if config list item is missing a truthy `type`
- Conditionally include `environment` in shaped config list payload
Payloads (payloads.py):
- Add `environment: str | None` field to WatsonxApiConfigListItem with normalizing validator
Tests:
- Add test for deployment-scope key_value_creds filtering (mixed security schemes)
- Add test for tenant-scope key_value_creds filtering (oauth2 excluded)
- Add test for environment metadata passthrough in mapper and service
- Add tests for provider failure paths (tenant list failure, None response, tool fetch failure)
- Add tests for edge cases (latest-binding-wins, skip enrichment with no connections, malformed detailed connection)
- Update mapper tests to assert fail-fast on missing type
- Update existing fixtures to include security_scheme where required by new filtering

* refactor(deployments): move flow-version tool_name into provider_data
Move provider tool_name from a top-level flow-version response field into
provider_data, aligning API ownership boundaries for provider-originated
non-persisted fields.
- Remove top-level tool_name from DeploymentFlowVersionListItem
- Add tool_name to WatsonxApiDeploymentFlowVersionItemData with normalization
- Update WXO mapper to shape tool_name under provider_data
- Update frontend attachments type and consumer to read provider_data.tool_name
- Update backend tests for new response contract location
- Add explicit RULES.md requirement for non-persisted provider data placement

* make environment required

* refactor list configs method and fix broken tests

* feat(deployments): type-to-confirm dialog for deployment deletion (#12546)

* feat(deployments): replace simple delete confirm with type-to-confirm dialog

Deleting a deployment is irreversible — it removes the agent from both
Langflow and Watsonx Orchestrate permanently. Require the user to type
the deployment name before the Delete button activates, matching
industry-standard patterns (GitHub, AWS).

- Add `TypeToConfirmDeleteDialog` component (deployment-specific, not shared)
- Input resets on close; label + placeholder for accessibility
- Replace `DeleteConfirmationModal` in `deployments-content.tsx`
- 6 unit tests covering all confirmation behaviours

* fix(deployments): address PR review findings on type-to-confirm dialog

- Fix icon spacing: replace pr-1 with mr-2 on AlertTriangle (padding
  was compressing the SVG viewport instead of creating sibling spacing)
- Fix label copy: "agent name" → "deployment name" to cover both agent
  and MCP deployment types
- Remove unused cancelDelete from useDeleteWithConfirmation — callers
  close the dialog via setModalOpen; the export was dead code
- Add case-sensitivity test to type-to-confirm-delete-dialog tests
- Add unit tests for useDeleteWithConfirmation hook (8 tests covering
  requestDelete, confirmDelete, onSettled, onError, and setModalOpen)

* test(deployments): add comprehensive frontend test suite for WXO deployments (#12535)

* test(deployments): add unit tests for all deployment API query and mutation hooks

16 test files covering deployment queries, mutations, provider accounts,
execution hooks, and env var detection (59 tests total).

* test(deployments): add stepper context create-mode tests and expand edit-mode/tool-naming coverage

Step 2 of the frontend deployment test plan — 63 new tests (93 total)
covering create-mode payload builders, step validation, provider
selection, multi-flow scenarios, partial update payloads, detach/re-attach
flows, and tool naming edge cases.

* test(deployments): add component rendering tests for Step 3 (163 tests, 10 files)

Covers tables, stepper steps, connection panel, and modals with data-testid additions to source components for reliable targeting.

* test(deployments): add custom hook unit tests for Step 4 (121 tests, 7 files)

Covers useErrorAlert, useProviderFilter, useNavigateToTest, useDeleteWithConfirmation,
useTestDeploymentModal, useDeploymentChat (polling, thread_id, timeouts, tool traces),
and watsonx-result-parsers (extractText, extractToolTraces, extractThreadId).

* test(deployments): add deploy button and choice dialog unit tests for Step 5 (76 tests, 3 files)

- deploy-button.test.tsx (12 tests): feature-flag rendering, disabled states
  (no flow/preparing/dialog open), handleDeploy click, animate-pulse on icon
- deploy-choice-dialog/index.test.tsx (30 tests): phase transitions
  (provider → deployments → review → update), auto-select single attachment,
  provider key mapping, patchSnapshot args, update/error flows, onUpdateComplete
- deploy-choice-dialog/hooks/use-prepare-deploy.test.ts (34 tests): handleDeploy
  save/snapshot/provider fetch, no-flow bail-out, deployModal vs choiceDialog
  branching, error handling, handleChooseNew, handleUpdateComplete, resetChoiceState

* test(deployments): add E2E Playwright tests for Step 6 (28 tests, 5 files)

- deployments-page.spec.ts: page nav, empty/loaded states (5 tests)
- deployment-create.spec.ts: full create wizard, POST, deploy status (6 tests)
- deployment-edit.spec.ts: edit mode, PATCH, cancel (5 tests)
- deployment-providers.spec.ts: add/delete providers, confirmation (6 tests)
- deployment-test-modal.spec.ts: chat, polling, multi-turn, reset (6 tests)

Add shared deployment-mocks.ts for mock data reuse across all specs.

Add data-testid to stepper modal title, add-provider modal title, and
test-deployment modal title to avoid strict-mode selector violations.

Add data-testid to provider radio items in step-provider.tsx.

Set LANGFLOW_FEATURE_WXO_DEPLOYMENTS=true in CI workflow env.

* fix(tests): update deployment E2E mocks for wxo-fe API changes

- provider_accounts field rename: { providers } → { provider_accounts }
- ProviderAccount.provider_url → ProviderAccount.url
- Execution endpoints moved to deployment-scoped URLs:
  POST /deployments/executions → /deployments/{id}/executions
  GET /deployments/executions/{exec_id} → /deployments/{id}/executions/{exec_id}
- Remove deployment_id from POST execution request body (now in URL path)

* fix(tests): update unit tests for wxo-fe API shape changes

- ProviderAccount: provider_url → url, removed provider_tenant_id
- Provider list response: { providers } → { provider_accounts }
- ProviderCredentials: provider_url → url
- Deployment payload: spec.{name,description,type} → top-level fields
- Provider data: operations → add_flows/upsert_flows/remove_flows
- Connections: raw_payloads[].environment_variables → connections[].credentials
- DeploymentConfigItem: { id, name } → { app_id, connection_id }

* fix(tests): align frontend tests with revised deployments API shape

Update unit tests, E2E mocks, and the ProviderAccountListResponse type
to match the API changes from the v1 deployments revision (#12478):
- execution endpoints now use deployment_id in URL path
- getExecution uses deployment_id + execution_id (no provider_id)
- provider accounts response key changed to provider_accounts
- deployment configs response wrapped in provider_data
- deploy-choice-dialog now uses useGetDeploymentAttachments

* fix(ci): read LANGFLOW_FEATURE_WXO_DEPLOYMENTS from process.env fallback

Vite config only read feature flags from the .env file via dotenv,
ignoring CI workflow environment variables. This caused all 28
deployment E2E tests to fail because the flag was never enabled.

* fix(tests): add missing resource_key to deployment mapper test mocks

The SimpleNamespace mocks in TestCreateResponse and TestMapperUpdateResult
were missing the resource_key attribute now required by the mapper.

* test(deployments): add E2E tests for type-to-confirm deployment deletion

Adds testid to the delete dropdown item and four Playwright tests covering:
- dialog opens on delete action
- confirm button disabled until name matches exactly
- confirming with correct name calls DELETE /api/v1/deployments/{id}
- cancel dismisses without calling DELETE

* chore: trigger CI

* fix(deployments): remove unused description field from connection panel (#12549)

The Description input in the Create Connection tab was never persisted —
ConnectionItem has no description field and the value was not sent to any API.

* fix(deployments): enforce single-environment filter on deployments page (#12551)

fix(deployments): enforce single-environment filter and reorder provider form fields

Remove the "All environments" global listing mode from the deployments
page. Deployments are now always fetched for a single selected
environment, avoiding N parallel API calls that each trigger a backend
sync. Also differentiates empty states (no providers vs no deployments)
and reorders the provider credentials form to show URL before API key.

* be test

* be test

---------

Co-authored-by: Jordan Frazier <jordan.frazier@datastax.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Hamza Rashid <74062092+HzaRashid@users.noreply.github.com>
Co-authored-by: Hamza Rashid <hzarashid@gmail.com>
Co-authored-by: Jordan Frazier <122494242+jordanrfrazier@users.noreply.github.com>
2026-04-08 10:00:41 +00:00
abd772f780 fix: Build and install the langflow-sdk for lfx (fixes nightly) (#12481)
* fix: Build and install the langflow-sdk for lfx

* Publish sdk as a nightly

* Update ci.yml

* Update python_test.yml

* Update ci.yml
2026-04-03 05:59:09 +00:00
4bdc87dcc1 fix: Import and Statistics fixes for Knowledge Bases (#12446)
* fix: Access the appropriate attribute for chroma

* Fix display of chunk metadata

* [autofix.ci] apply automated fixes

* Add some unit tests

* Update ingestion.py

* [autofix.ci] apply automated fixes

* Review updates

* Update component_index.json

* Fix bug with ingestion

* [autofix.ci] apply automated fixes

* Update test_ingestion.py

* Update test_ingestion.py

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Carlos Coelho <80289056+carlosrcoelho@users.noreply.github.com>
2026-04-02 19:34:06 +00:00
45325f6376 feat: Langflow SDK and Flow DevOps API Toolkit (#12245)
* feat(sdk): add langflow-sdk Python client package

* feat(lfx): add Flow DevOps CLI toolkit

* feat(api): add flow upsert, export normalization, ZIP upload

* chore: CI coverage merge, Docker fixes, dependency updates

* Address CQ5 review / import bug

* Update test_status_command.py

* Update test_status_command.py

* Fix more tests

* Review edits

* Review edits

* Fix tests

* Follow up review updates

* Refactor common client code

* Update templates and comp index

* [autofix.ci] apply automated fixes

* Update test_database.py

* Updates from review comments

* Fix push interface to match the rest

* Update push.py

* Update push.py

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-04-02 16:13:13 +00:00
c43fbc95ce feat: LE-374 token usage tracking for LLM and Agent components (#11891)
* feat: add token usage tracking for LLM and Agent components

Track input/output/total tokens across LLM providers (OpenAI, Anthropic,
Ollama) and display them on both node badges and chat messages.

Backend: thread-safe callback handler for agent token accumulation,
usage_metadata extraction for Ollama/LangChain standard, pipeline
integration from component through vertex to API response.

Frontend: token count formatting utility, Coins icon badge on nodes
with tooltip breakdown, chat message status with token display.

* feat: accumulate token usage across serial LLMs on chat messages

Add upstream token usage accumulation so chat messages display the
total tokens from all LLMs in the pipeline, not just the last one.
Output vertex node badges hide token counts since the accumulated
total is shown on the chat message instead.

* chore: add CLAUDE.local.md to .gitignore

* chore: update starter project templates for token usage tracking

* fix: enable token usage tracking for streaming LLM responses

Enable stream_usage=True on OpenAI and Anthropic model constructors so
the API includes token counts in streaming chunks.

Fix _handle_stream to propagate the AIMessage back to _get_chat_result
when not connected to a chat output, so usage can be extracted from the
invoke fallback path.

Accumulate usage across multiple streaming chunks instead of overwriting,
since Anthropic splits input/output tokens across separate events.

* [autofix.ci] apply automated fixes

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

* refactor: centralize token usage extraction into shared module

Extract duplicated token usage logic from Component, LCModelComponent,
TokenUsageCallbackHandler, and Vertex into a shared lfx.schema.token_usage
module. Replace loose dict typing with the existing Usage Pydantic model
throughout the token tracking pipeline. Declare _token_usage on Component
__init__ instead of dynamically injecting it.

* [autofix.ci] apply automated fixes

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

* [autofix.ci] apply automated fixes

* feat: add validation for token_usage field in ResultDataResponse

* feat: enable stream_usage in OpenAI model tests

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* refactor: consolidate token usage extraction into single source of truth

Eliminate ~75 lines of duplicated LLMResult token extraction logic between
the token usage feature (TokenUsageCallbackHandler) and the traces feature
(NativeCallbackHandler) by adding a shared extract_usage_from_llm_result()
function. Also fix missing usage property mapping in chat history hook so
token counts display correctly in playground messages.

* feat: add token usage tracking to all LLM components

Add token usage extraction to the 7 remaining components that make LLM
calls but weren't tracking token consumption:

- Smart Router: direct extract_usage_from_message after invoke
- Guardrails: accumulate_usage across multiple guardrail checks
- Batch Run: accumulate_usage across batch responses
- Smart Transform: extract after ainvoke (already done in prior commit)
- Structured Output: via token_usage_callback on get_chat_result
- LLM Selector: direct extract for judge + callback for selected model
- NotDiamond: via token_usage_callback on get_chat_result

Also adds a backward-compatible token_usage_callback parameter to
get_chat_result() so components using that shared helper can capture
the AIMessage before it's reduced to .content.

* [autofix.ci] apply automated fixes

* fix: update mock_get_chat_result signatures to accept token_usage_callback

The structured output test mocks define explicit parameter lists for
get_chat_result but were missing the new token_usage_callback kwarg,
causing CI failure. Add **kwargs to all mock definitions.

* fix: address PR review findings for token usage UI and data flow

- Remove bare "bg" Tailwind class and replace hard-coded bg-neutral-700
  with semantic bg-success-background on success tooltip (C2/C3)
- Propagate usage properties regardless of source.id presence so agent
  inner messages still show token counts (H9)
- Make PropertiesType.source optional to match the new data flow
- Restore "in" preposition in "Finished in X.Xs" chat message (M10)
- Fix misleading "optional dependency" comment in native_callback.py (C1)

* fix: structured output token usage not captured due to config key mismatch

get_chat_result() reads "get_langchain_callbacks" as a callable, but
structured output was passing "callbacks" as a list — the token handler
was silently dropped. Fix by matching the expected key names and
injecting TokenUsageCallbackHandler via the LangChain callback chain
instead of the token_usage_callback parameter (which doesn't fire for
structured output chains that return Pydantic models, not AIMessages).

* [autofix.ci] apply automated fixes

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

* chore: update component index

* test: add E2E tests for token usage tracking

* [autofix.ci] apply automated fixes

* test: add missing unit tests from PR review

Adds the 4 recommended test scenarios identified in Cristhianzl's review
of PR #11891 (token usage tracking):

- TestStreamingTokenAccumulation: verifies extract_usage_from_chunk() +
  accumulate_usage() correctly accumulates across multiple streaming chunks
  (OpenAI, Anthropic, and usage_metadata formats)
- TestChatOutputTokenUsageAccumulation: verifies message_response() sets
  upstream token usage on the message and updates the stored message when
  applicable
- TestAgentTokenCallbackWiring: verifies TokenUsageCallbackHandler is wired
  into run_agent() callbacks and its result is stored on _token_usage
- TestResultDataResponseTokenUsageValidator: verifies the field_validator
  converts Usage Pydantic models to dicts and passes through None/dict values

* [autofix.ci] apply automated fixes

* Revert "[autofix.ci] apply automated fixes"

This reverts commit c618b12498.

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* fix: move hover action bar above message to prevent overlap with header row

Position the EditMessageButton toolbar using \`bottom-full\` instead of \`-top-4\` so it always sits fully above the message container. This prevents the button bar from overlapping the 'Finished in' usage/time row in bot messages.

* [autofix.ci] apply automated fixes

* feat: add token usage tooltip to bot message and fix node status background

- Wrap "Finished in" stat in a ShadTooltip showing last run time, duration, input/output token breakdown
- Fix node status success background color from bg-success-background to bg-zinc-700

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-04-01 17:36:35 +00:00
ccc7ffa714 fix: Improve the sub-process handling of the Docling Worker (#12296)
* fix: Don't reprocess files in Advanced Mode

* Preserve metadata in docling processing

* [autofix.ci] apply automated fixes

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

* Preserve metadata in docling processing

* Preserve metadata in docling processing

* Update docling_inline.py

* [autofix.ci] apply automated fixes

* Preserve metadata in docling processing

* Emit log while worker is active

* [autofix.ci] apply automated fixes

* Update test_file_component_image_processing.py

* Update test_file_component_image_processing.py

* Update component_index.json

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* Update component_index.json

* [autofix.ci] apply automated fixes

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

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

* Merge release branch

* Secrets baseline update

* [autofix.ci] apply automated fixes

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

* fix: Handle markdowns with large buffer output

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-03-31 18:39:55 +00:00
86dd7dfc31 fix: resolve code scanning alerts for URL sanitization and insecure randomness (#12362)
Use urlparse for proper hostname validation instead of substring check (LE-719).
Replace Math.random() with crypto.randomUUID() in test fixtures (LE-718).

Co-authored-by: Janardan Singh Kavia <janardankavia@ibm.com>
2026-03-31 17:39:55 +00:00
42832d07a5 feat: add core deployment implementation (#12108)
* checkout api handlers

* add missing table

* update to use "version" terminology for flows instead of outdated "history" verbage

* Fix provider account id mapping

* recover a little todo comment

* Add flow version migration and minor exception handling, etc

  1. deployments.py — Added AuthenticationError import + handling (401) in all 9 error handler blocks. Added update_deployment_db import + call to persist name changes to local DB after adapter update succeeds.
  2. flow_version/exceptions.py — Added FlowVersionDeployedError for blocking deletion of deployed versions.
  3. flow_version/crud.py —
    - Added has_deployment_attachments() helper that checks if a flow version has any deployment attachments
    - delete_flow_version_entry() now raises FlowVersionDeployedError if the version is attached to deployments
    - Pruning now excludes deployed versions via a NOT IN subquery on FlowVersionDeplottachment, preventing provider-side snapshot orphaning
  4. flow_version/__init__.py — Exports FlowVersionDeployedError
  5. flow_version.py (API route) — Imported FlowVersionDeployedError, added it to _translate_version_error as 409 Conflict
  6. models/__init__.py — Registered FlowVersionDeploymentAttachment for alembic/SQLModel metadata detection
  7. Migration c0d2ce43b315 — Creates flow_version_deployment_attachment table with all columns, FKs (CASCADE), and indexes. Single head, chains off fc7f696a57bf.

* [autofix.ci] apply automated fixes

* address bugs and inconsistencies

* rename column to "provider_snapshot_id"

* harden deployment API: fail loudly on invalid state instead of silently passing

Replace silent fallbacks, warning logs, and dropped values with hard
failures (422/500/502) across the deployment orchestration layer. Adds
logging to bare exception handlers and wraps materialize_snapshots in
the adapter error handler.

* [autofix.ci] apply automated fixes

* add materialize_snapshots to deployment service protocol

Promotes materialize_snapshots from duck-typed getattr usage to a
first-class method on DeploymentServiceProtocol, BaseDeploymentService,
and the no-op DeploymentService stub. Introduces MaterializeSnapshotsResult
schema for typed return values.

Updates deployments.py to call the method through the protocol instead of
getattr, giving static analysis coverage over the contract.

Documents the snapshot abstraction across BaseFlowArtifact, SnapshotItem,
MaterializeSnapshotsResult, and FlowVersionDeploymentAttachment.provider_snapshot_id
— explaining that snapshots are immutable, provider-owned copies of flow data
with opaque provider-assigned identifiers (e.g. wxO tool ID, K8s ConfigMap
name, S3 key).

* deployment sync: extract helpers, server-side type filter, orphan detection

- Extract _fetch_provider_resource_keys helper for provider validation
- Rename _sync_page_with_provider → _list_deployments_synced
- Match resource keys by provider ID only (not name)
- Restore server-side deployment_type filter with guard against
  false deletions (skip rows whose type doesn't match the filter
  instead of deleting them)
- Add orphan/divergence logging for post-create, post-update,
  post-duplicate DB write failures
- Return 422 on invalid UUID in update remove list (was silently ignored)
- Handle NotImplementedError → 501 from provider adapters
- Convert attachment IntegrityError to ValueError with descriptive message
- Add tests for sync helpers (15 cases)

* rebase on release-1.9.0 and align with lfx/services

* refactor(deployments): align provider mapper routing and WXO update payload mapping

Align deployment mapper resolution with adapter-type/provider-key routing and
refactor PATCH update handling to use mapper resolve/shape contracts end-to-end.
Map Langflow flow_version_id references at the API boundary into provider update
operations for Watsonx bind/unbind/remove paths, with expanded mapper tests.

* patch down-revision

* first pass with formalized boundary rules

* fix(deployments): harden watsonx payload boundary contracts

Enforce fail-fast payload slot parsing for required adapter results, split execution create/status slot contracts, and route execution-create mapping through deployment mappers.
Require watsonx flow artifact source_ref and move update reconciliation output to provider_result to keep mapper/adapter boundaries explicit and typed.

* refactor(deployments): modularize watsonx orchestrate create/update flow

Extract create/update logic into dedicated core modules with shared helpers to tighten deployment boundary contracts.
Align backend/lfx payload schema mapping and expand e2e/unit coverage for response mapping and update schema behavior.

* api impl for wxo-specific create payload

* further refactoring. add rollback of existing tools (undo new app bindings) in the create path

* add todo in execution.py

* refactor(deployments): replace snapshot_id/reference_id with source_ref-correlated tool refs
Introduce WatsonxToolRefBinding to correlate source_ref (flow version id)
with provider tool_id across all operation types. This replaces the prior
reference_id and snapshot_id fields with a unified structure that carries
provenance through create, bind, unbind, and remove_tool operations.
Key changes:
- Flatten API operation payloads: hoist flow_version_id onto operations,
  remove nested WatsonxApiUpdateToolReference wrapper
- Replace tools.existing_ids with inline tool_id_with_ref on bind operations
- Rename WatsonxCreateSnapshotBinding to WatsonxToolRefBinding (input) and
  WatsonxResultToolRefBinding (output, with created flag)
- Add created_app_ids to update results for connection tracking
- Raise HTTPException on contract violations in _to_api_tool_app_bindings
  instead of silently dropping unmappable bindings
- Add schema-level validation for conflicting source_ref on same tool_id
- E2E: cache tool_id→source_ref from create results, use helpers to build
  refs with distinct source_ref vs tool_id values

* Enforce DeploymentType enum and add description column

Make deployment_type a required column backed by a SQLAlchemy
TypeDecorator that validates on write (rejects None and invalid strings)
and coerces to DeploymentType on read. Add nullable description column
to the deployment model and surface it through the API.

Key changes:
- Add _DeploymentTypeColumn TypeDecorator for enum round-trip fidelity
- Make deployment_type non-optional in Deployment model, DeploymentRead,
  CRUD functions, and API layer
- Add description (Text, nullable) to Deployment model and fold its
  migration into the existing c0d2ce43b315 revision
- Remove _resolve_deployment_type helper — TypeDecorator handles coercion
- Remove DeploymentType fallbacks and backward-compat shims from API
  endpoints, base mapper, and watsonx orchestrate mapper
- Document cross-package coupling: DeploymentType is owned by lfx but
  persisted by langflow; member values must never be removed
- Fix pre-existing bug: provider_account_id → deployment_provider_account_id
  in get_deployment_status endpoint

Note: deployment_type is nullable=True at the DB level to satisfy the
EXPAND-phase migration validator; NOT NULL is enforced at the application
layer by the _DeploymentTypeColumn TypeDecorator.

* refactor(deployments): extract route helpers, harden sync and error handling
Move bulk of deployment route logic into mappers/helpers layer to slim
down deployments.py and enforce clearer boundary between routes, mappers,
and adapters (documented in DEPLOYMENT_BOUNDARY_RULES.md).
Key changes:
- Extract ~700 lines from deployments.py into helpers.py (pagination,
  adapter/mapper resolution, attachment management, snapshot sync,
  rollback, response shaping)
- Add read-path snapshot-level sync: get_deployment and
  list_deployments_synced verify provider_snapshot_ids against the
  provider and prune stale attachments, with graceful fallback on error
- Add compensating rollback for create (rollback_provider_create) and
  update (rollback_provider_update) when DB commit fails after provider
  mutation, using mapper-driven payload reconstruction
- Introduce handle_adapter_errors() context manager centralising
  DeploymentServiceError → HTTP status mapping via
  http_status_for_deployment_error; sanitise 500 detail to avoid
  leaking internals
- Add DeploymentNotConfiguredError → 503 mapping
- Add util_snapshot_ids_to_verify and resolve_rollback_update to base
  mapper with WxO overrides for provider-specific snapshot ID extraction
  and put_tools-based rollback payloads
- Add put_tools field to WatsonxDeploymentUpdatePayload for full tool
  list replacement; early-return in build_provider_update_plan and
  validate_operation_references when put_tools is set
- Extract verify_tools_by_ids into core/tools.py helper
- Harden resource_name_prefix with strip_whitespace + min_length=1
- Deduplicate snapshot_ids before provider calls
- Add deterministic order_by(created_at) to attachment CRUD queries
- Add exc_info=True to all best-effort rollback/compensate error logs
- Add session.rollback() in get_deployment snapshot sync error path
- Warn when list_snapshots receives both deployment_ids and snapshot_ids
- Add E2E scenarios for empty snapshot list, mixed snapshot IDs, tools
  endpoint, and deployment re-list after update
Tests:
- Add test_deployment_route_handlers.py covering stale-row delete +
  commit, non-404 adapter errors, handle_adapter_errors wiring,
  snapshot sync (happy path, skip, error fallback), project-scoped
  flow version validation for create and update
- Expand test_deployment_sync.py with snapshot-phase tests, rollback
  tests, pagination guard, and project-scoped validation
- Add deployment_type assertion to response mapping test
- Add DeploymentNotConfiguredError and bare DeploymentServiceError cases
  to exception mapping tests
- Add put_tools schema and update plan tests

* remove pompous performance commentary

* fix(deployments): remove upsert behavior and fail fast on duplicate name

The create_deployment endpoint previously performed a
get_deployment_by_resource_key lookup before inserting the DB row,
silently tolerating duplicates. Since the provider adapter returns a
fresh resource ID on every create, this lookup could never legitimately
match — and if it did, it would mask a data inconsistency bug.

Changes:
- Remove the get-or-create (upsert) pattern; go straight to
  create_deployment_db and let the unique constraint surface conflicts.
- Add deployment_name_exists CRUD function and an early 409 guard so
  duplicate names are rejected before any provider call, avoiding
  costly provider-side rollback for a locally-checkable condition.
- Update existing route-handler tests to reflect the removed lookup.
- Add tests for deployment_name_exists and the 409 duplicate-name path.

* feat: convert provider_key and deployment_type columns to DB-level enums
Replace plain string columns with SQLAlchemy Enum types backed by
Postgres/SQLite enum constraints, enforcing valid values at the DB
layer rather than only in application code.
Migration follows expand-contract pattern (add enum column, backfill,
drop old string column, rename) with index ops outside batch context
to avoid SQLite column-lookup issues. Upgrade and downgrade are fully
atomic.
- Add DeploymentProviderKey enum as single source of truth for
  provider identifiers; remove magic strings and _DeploymentTypeColumn
  TypeDecorator
- Make provider_key immutable after creation (remove from update
  request schema and API handler)
- Fix pre-existing test gap: add missing deployment_type argument to
  all TestDeploymentCRUD create_deployment() calls

* feat(flow-versions): add deployment awareness and sync-on-read

Add is_deployed field to flow version responses and provider-verified
sync to the list/get read paths, matching the existing deployment
endpoint sync pattern.

API changes:
- list_flow_versions returns is_deployed per entry and accepts optional
  deployment_ids filter to scope by specific deployments
- get_single_flow_version returns is_deployed on the full response
- Both endpoints now use write sessions and run best-effort
  snapshot-level sync before returning results

Sync-on-read (helpers.sync_flow_version_attachments):
- Queries all attachments for a flow's versions joined with deployment
  and provider account info in a single query
- Groups by provider, resolves adapter/mapper per group, verifies
  provider_snapshot_ids via list_snapshots, and prunes stale attachment
  rows through the existing sync_attachment_snapshot_ids helper
- Per-provider error handling so one provider outage doesn't block the
  response

New CRUD: list_attachments_for_flow_with_provider_info joins
FlowVersionDeploymentAttachment -> Deployment -> DeploymentProviderAccount
to avoid N+1 queries during sync grouping.

Tests: 50 passing (11 new) covering is_deployed indicator, deployment_ids
filtering, stale attachment pruning on list/get, and sync failure
resilience.

* Add user id authentication to a few missing endpoints

* [autofix.ci] apply automated fixes

* Update tests

Removes some mock tests that did nothing
Adds sqlite for true testing of db accessors
Reduces Mock objects usage

* refactor(deployments): enforce ownership boundaries on execution responses
Move provider-owned execution identifiers (execution_id, agent_id,
status, timestamps, errors) out of the top-level API response and into
provider_data, keeping only Langflow-owned fields (deployment_id) at the
top level.  This prevents future collisions if Langflow introduces its
own execution tracking.
Key changes:
- Remove execution_id from _ExecutionResponseBase; provider's opaque
  run identifier now lives exclusively inside provider_data
- Rename WatsonxExecutionResultData → WatsonxAgentExecutionResultData
  (adapter layer) and split the API-layer class into a private base
  (_WatsonxApiAgentExecutionResultBase) with dedicated
  WatsonxApiAgentExecutionCreateResultData and
  WatsonxApiAgentExecutionStatusResultData subclasses
- Translate WXO run_id → execution_id at the adapter boundary
  (create_agent_run_result / get_agent_run).
- Collapse util_execution_id + util_execution_deployment_resource_key
  into a single util_resource_key_from_execution that trusts the
  adapter-provided result.deployment_id directly
- Remove build_orchestrate_runs_query and extra payload fields
  (thread_id, llm_params, guardrails, etc.) unused in MVP
- Simplify WxOClient.post_run signature (drop query_suffix)
- Exclude provider_data from flow tool artifact to avoid unexpected
  top-level keys in the WxO tool runtime
- Document ownership boundary rules in DEPLOYMENT_BOUNDARY_RULES.md §14
- Add E2E polling for terminal execution status, input format variants,
  and missing-deployment negative test
- Expand unit tests for renamed schemas, field mapping, passthrough
  validation, and simplified payload builder

* feat: add name column to deployment_provider_account
Add a required, user-chosen display name to provider accounts
(e.g. "staging", "prod") that is unique within a given provider_key.
Includes model, CRUD, API schema/route, mapper, migration with
backfill, and tests.

* fix: replace hand-written migration with Alembic-generated revision
Replace the manually authored migration (b4e6f8a2c1d3) with an
Alembic-generated one (8255e9fc18d9) for the deployment_provider_account
name column.
Fix SQLite compatibility: sa.func.concat() generates a concat() function
call which does not exist in SQLite. Use sa.literal().concat() instead,
which produces the || operator and works on both PostgreSQL and SQLite.

* remove bogus unverified math from migration file

* feat: verify provider credentials before account creation
Add a verify_credentials step to the provider account creation flow
that validates API keys against the provider before persisting them.
This prevents storing invalid or revoked credentials and gives users
immediate feedback.
Key changes:
- Add verify_credentials to the deployment adapter interface (base,
  service, protocol) with WXO implementation that obtains a token
  via the IBM authenticator
- Add SSRF-hardened URL validation for provider_url (HTTPS-only,
  private IP blocklist, localhost rejection, normalization)
- Introduce ValidatedUrl/ValidatedUrlOptional annotated types in
  the API schema layer
- Refactor raise_for_status_and_detail to accept an optional cause
  parameter for explicit exception chain control
- Use ResourceNotFoundError (parent) instead of DeploymentNotFoundError
  in raise_for_status_and_detail for provider-agnostic 404 mapping
- Narrow get_authenticator return type to concrete union

* use whitelist only for valid urls

* feat: BREAKING: move credentials into provider_data and centralize update logic in mapper
- Replace top-level `api_key: SecretStr` with opaque `provider_data: dict` in API schemas;
  mapper extracts credentials via `resolve_credential_fields` for DB storage
- Add `resolve_provider_account_update` to base mapper so routes delegate
  full update-kwargs assembly (including cross-field logic) to the mapper
- WXO mapper override re-derives `provider_tenant_id` when `provider_url` changes
- Add tenant extraction utilities and `validate_tenant_url_consistency` in
  `deployment_provider_account/utils.py` as single source of truth
- Add `model_validator` on `DeploymentProviderAccount` for defense-in-depth
  tenant/URL consistency checks
- Rename `DEPLOYMENT_BOUNDARY_RULES.md` → `RULES.md`; document DB-direction
  mapper contract, credential flow, and update assembly
- Update all tests for new `provider_data` shape, mapper update methods,
  tenant extraction, and model-level consistency validation

* [autofix.ci] apply automated fixes

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

* fix(deployments): Harden provider account validation and WXO rollback

Use provider_url when resolving WXO credentials and scope provider account names per user within each provider. Re-verify provider account updates before persisting them and return 4xx responses for account conflicts instead of surfacing 500s.

Block deleting provider accounts that still own deployments and extend create rollback so failed WXO writes clean up provider-side resources. Add route, schema, mapper, sync, CRUD, and WXO tests to cover the new behavior.

* [autofix.ci] apply automated fixes

* update url validator docs; remove outdated reference to private url blacklist logic

* fix(deployments): Isolate snapshot sync writes

Use nested transactions around best-effort snapshot cleanup so provider sync failures cannot leak partial attachment deletes into the outer request transaction.

Persist explicit description clears during deployment PATCH requests, and add regression tests for both deployment sync paths and the route handler update flow.

* fix(deployments): Harden delete cleanup and wxO create tests

Treat missing provider agents as stale local cleanup so delete can
finish instead of leaving orphaned deployment rows behind.

Commit local delete operations eagerly, retry once on commit failure,
and move wxO create-path tests toward fake client objects so the real
service logic is exercised without external calls.

* new head

* fix(deployments): stop prefixing wxo raw connection app_ids
Preserve caller app_ids for newly created wxo connections while keeping lf_ prefixing for tool/deployment naming, centralize resource_name_prefix validation, and update mapper/service schema tests and docs to reflect the new behavior.

* fix(deployments): Harden provider account cleanup

Reconcile stale deployment rows before provider-account deletion so
out-of-band provider removals do not leave account cleanup blocked.

* fix: restore py310 compatibility and align payload slot tests
Import Self from typing_extensions in the deployment provider account model to keep backend imports working on Python 3.10, and update payload formalization tests to assert strict rejection of cross-model BaseModel inputs.

* fix(deployments): resolve mypy typing regressions across deployment flows
Normalize SQLModel query expressions for typed SQL operators, make deployment-related model IDs non-nullable where appropriate, and tighten provider mapper/update typing guards. Update deployment tests to align with stricter type contracts.

* fix(deployments): restore py310 test compatibility and migration idempotency
Replace Python 3.11-only UTC imports with timezone.utc in deployment-related tests and the watsonx e2e helper, and make the provider-account name migration safe to re-run when the column and unique constraint are created in separate steps.

* fix(deployments): restore provider account route ownership helpers
Reuse the shared provider-account lookup in update/delete routes so route tests keep the expected ownership path, and use the explicit-field helper when deciding whether to reverify credentials.

* pass name to create_provider_account helper in tests

* [autofix.ci] apply automated fixes

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

---------

Co-authored-by: Jordan Frazier <jordan.frazier@datastax.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-03-26 21:54:30 +00:00
ae02b4b691 fix: prevent overwriting user-selected global variables in provider c… (#12329)
* fix: prevent overwriting user-selected global variables in provider c… (#12217)

* fix: nightly now properly gets 1.9.0 branch (#12215)

before it was attempting to pull release-notes as letters are alphanumerically after numbers when we sort -V then grab tail
now we only look at branch names that follow the pattern '^release-[0-9]+\.[0-9]+\.[0-9]+$'

* docs: add search icon (#12216)

add-back-svg

* fix: prevent overwriting user-selected global variables in provider config

Previously, the apply_provider_variable_config_to_build_config function would
automatically overwrite field values with environment variable keys whenever
an env var was present, even if the user had already selected a different
global variable.

This fix adds a check to only auto-set the environment variable if:
- The field is currently empty, OR
- The field is not already configured to load from the database

This preserves user selections while still providing automatic configuration
for new/empty fields.

Added comprehensive unit tests to verify:
- Auto-setting env vars for empty fields
- Preserving user-selected global variables
- Overwriting hardcoded values (expected behavior)
- Skipping when env var is not set
- Applying component metadata correctly

* [autofix.ci] apply automated fixes

* style: use dictionary comprehension instead of for-loop

Fixed PERF403 Ruff style warning by replacing for-loop with dictionary
comprehension in update_projects_components_with_latest_component_versions

* chore: retrigger CI build

* test: improve test coverage and clarity for provider config

- Renamed test_apply_provider_config_overwrites_hardcoded_value to
  test_apply_provider_config_replaces_hardcoded_with_env_var for clarity
- Added test_apply_provider_config_idempotent_when_already_set to document
  idempotent behavior when value already matches env var key
- Removed sensitive value from debug log message to prevent potential
  exposure of API keys or credentials

These changes improve test coverage by documenting the no-op scenario
and enhance security by avoiding logging of potentially sensitive data.

* chore: retrigger CI build

---------

Co-Authored-By: Adam-Aghili <149833988+Adam-Aghili@users.noreply.github.com>
Co-Authored-By: Mendon Kissling <59585235+mendonk@users.noreply.github.com>
Co-Authored-By: Steve Haertel <shaertel@ca.ibm.com>
Co-Authored-By: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-Authored-By: Eric Hare <ericrhare@gmail.com>

* [autofix.ci] apply automated fixes

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

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

* Update test_unified_models.py

---------

Co-authored-by: Adam-Aghili <149833988+Adam-Aghili@users.noreply.github.com>
Co-authored-by: Mendon Kissling <59585235+mendonk@users.noreply.github.com>
Co-authored-by: Steve Haertel <shaertel@ca.ibm.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-03-25 13:53:37 -07:00
15c803a7bc fix: Sanitize folder names for CodeQL (#12263) 2026-03-20 21:37:10 +00:00
198fab1dc7 feat: Add Windows Playwright test fixes to RC (#12265)
* feat: Add Windows Playwright tests to nightly builds

- Add windows-latest to typescript_test.yml runner options
- Add shell: bash to all script steps for cross-platform compatibility
- Split Playwright installation into OS-aware steps (Linux uses --with-deps, Windows/macOS/self-hosted don't)
- Fix artifact naming with OS prefix to prevent conflicts: blob-report-${{ runner.os }}-${{ matrix.shardIndex }}
- Split frontend-tests into separate Linux and Windows jobs in nightly_build.yml
- Add ref parameter to all test jobs to checkout code from release branch
- Add resolve-release-branch to needs dependencies
- Update Slack notifications to handle both Linux and Windows test results
- Windows tests are non-blocking (not checked in release-nightly-build condition)
- Update .secrets.baseline with new line number (263 -> 347) for LANGFLOW_ENG_SLACK_WEBHOOK_URL

Fixes LE-566

* fix: Use contains() for self-hosted runner detection

- Replace exact string equality (==, !=) with contains() for substring matching
- Fixes issue when inputs.runs-on is array format: '["self-hosted", "linux", "ARM64", ...]'
- Ensures self-hosted Linux runners correctly skip --with-deps flag

Addresses CodeRabbit feedback on PR #12264
2026-03-20 19:22:09 +00:00
69da593d56 feat: Refactor and Unify the ModelInput Selector Across Components (#12025)
* fix: Fixes Kubernetes deployment crash on runtime_port parsing (#11968) (#11975)

* feat: add runtime port validation for Kubernetes service discovery

* test: add unit tests for runtime port validation in Settings

* fix: improve runtime port validation to handle exceptions and edge cases

Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@logspace.ai>

* fix(frontend):  show delete option for default session when it has messages (#11969)

* feat: add documentation link to Guardrails component (#11978)

* feat: add documentation link to Guardrails component

* [autofix.ci] apply automated fixes

---------

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

* feat: traces v0 (#11689) (#11983)

* feat: traces v0

v0 for traces includes:
- filters: status, token usage range and datatime
- accordian rows per trace

Could add:
- more filter options. Ecamples: session_id, trace_id and latency range

* fix: token range

* feat: create sidebar buttons for logs and trace

add sidebar buttons for logs and trace
remove lods canvas control

* fix: fix duplicate trace ID insertion

hopefully fix duplicate trace ID insertion on windows

* fix: update tests and alembic tables for uts

update tests and alembic tables for uts

* chore: add session_id

* chore: allo grouping by session_id and flow_id

* chore: update race input output

* chore: change run name to flow_name - flow_id
was flow_name - trace_id
now flow_name - flow_id

* facelift

* clean up and add testcases

* clean up and add testcases

* merge Alembic detected multiple heads

* [autofix.ci] apply automated fixes

* improve testcases

* remodel files

* chore: address gabriel simple changes

address gabriel simple changes in traces.py and native.py

* clean up and testcases

* chore: address OTel and PG status comments

https://github.com/langflow-ai/langflow/pull/11689#discussion_r2854630438
https://github.com/langflow-ai/langflow/pull/11689#discussion_r2854630446

* chore: OTel span naming convention

model name is now set using name = f"{operation} {model_name}" if model_name else operation

* add traces

* feat: use uv sources for CPU-only PyTorch (#11884)

* feat: use uv sources for CPU-only PyTorch

Configure [tool.uv.sources] with pytorch-cpu index to avoid ~6GB CUDA
dependencies in Docker images. This replaces hardcoded wheel URLs with
a cleaner index-based approach.

- Add pytorch-cpu index with explicit = true
- Add torch/torchvision to [tool.uv.sources]
- Add explicit torch/torchvision deps to trigger source override
- Regenerate lockfile without nvidia/cuda/triton packages
- Add required-environments for multi-platform support



* fix: update regex to only replace name in [project] section

The previous regex matched all lines starting with `name = "..."`,
which incorrectly renamed the UV index `pytorch-cpu` to `langflow-nightly`
during nightly builds. This caused `uv lock` to fail with:
"Package torch references an undeclared index: pytorch-cpu"

The new regex specifically targets the name field within the [project]
section only, avoiding unintended replacements in other sections like
[[tool.uv.index]].

* style: fix ruff quote style

* fix: remove required-environments to fix Python 3.13 macOS x86_64 CI

The required-environments setting was causing hard failures when packages
like torch didn't have wheels for specific platform/Python combinations.
Without this setting, uv resolves optimistically and handles missing wheels
gracefully at runtime instead of failing during resolution.



---------



* LE-270: Hydration and Console Log error (#11628)

* LE-270: add fix hydration issues

* LE-270: fix disable field on max token on language model

---------



* test: add wait for selector in mcp server tests (#11883)

* Add wait for selector in mcp server tests

* [autofix.ci] apply automated fixes

* Add more awit for selectors

* [autofix.ci] apply automated fixes

---------



* fix: reduce visual lag in frontend  (#11686)

* Reduce lag in frontend by batching react events and reducing minimval visual build time

* Cleanup

* [autofix.ci] apply automated fixes

* add tests and improve code read

* [autofix.ci] apply automated fixes

* Remove debug log

---------




* feat: lazy load imports for language model component (#11737)

* Lazy load imports for language model component

Ensures that only the necessary dependencies are required.
For example, if OpenAI provider is used, it will now only
import langchain_openai, rather than requiring langchain_anthropic,
langchain_ibm, etc.

* Add backwards-compat functions

* [autofix.ci] apply automated fixes

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

* Add exception handling

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

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

* comp index

* docs: azure default temperature (#11829)

* change-azure-openai-default-temperature-to-1.0

* [autofix.ci] apply automated fixes

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

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

* [autofix.ci] apply automated fixes

---------



* [autofix.ci] apply automated fixes

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

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

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

* fix unit test?

* add no-group dev to docker builds

* [autofix.ci] apply automated fixes

---------





* feat: generate requirements.txt from dependencies  (#11810)

* Base script to generate requirements

Dymanically picks dependency for LanguageM Comp.
Requires separate change to remove eager loading.

* Lazy load imports for language model component

Ensures that only the necessary dependencies are required.
For example, if OpenAI provider is used, it will now only
import langchain_openai, rather than requiring langchain_anthropic,
langchain_ibm, etc.

* Add backwards-compat functions

* [autofix.ci] apply automated fixes

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

* Add exception handling

* Add CLI command to create reqs

* correctly exclude langchain imports

* Add versions to reqs

* dynamically resolve provider imports for language model comp

* Lazy load imports for reqs, some ruff fixes

* Add dynamic resolves for embedding model comp

* Add install hints

* Add missing provider tests; add warnings in reqs script

* Add a few warnings and fix install hint

* update comments add logging

* Package hints, warnings, comments, tests

* [autofix.ci] apply automated fixes

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

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

* Add alias for watsonx

* Fix anthropic for basic prompt, azure mapping

* [autofix.ci] apply automated fixes

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

* ruff

* [autofix.ci] apply automated fixes

* test formatting

* ruff

* [autofix.ci] apply automated fixes

---------



* fix: add handle to file input to be able to receive text (#11825)

* changed base file and file components to support muitiple files and files from messages

* update component index

* update input file component to clear value and show placeholder

* updated starter projects

* [autofix.ci] apply automated fixes

* updated base file, file and video file to share robust file verification method

* updated component index

* updated templates

* fix whitespaces

* [autofix.ci] apply automated fixes

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

* add file upload test for files fed through the handle

* [autofix.ci] apply automated fixes

* added tests and fixed things pointed out by revies

* update component index

* fixed test

* ruff fixes

* Update component_index.json

* [autofix.ci] apply automated fixes

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

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

* updated component index

* updated component index

* removed handle from file input

* Added functionality to use multiple files on the File Path, and to allow files on the langflow file system.

* [autofix.ci] apply automated fixes

* fixed lfx test

* build component index

---------





* docs: Add AGENTS.md development guide (#11922)

* add AGENTS.md rule to project

* change to agents-example

* remove agents.md

* add example description

* chore: address cris I1 comment

address cris I1 comment

* chore: address cris I5

address cris I5

* chore: address cris I6

address cris I6

* chore: address cris R7

address cris R7

* fix testcase

* chore: address cris R2

address cris R2

* restructure insight page into sidenav

* added header and total run node

* restructing branch

* chore: address gab otel model changes

address gab otel model changes will need no migration tables

* chore: update alembic migration tables

update alembic migration tables after model changes

* add empty state for gropu sessions

* remove invalid mock

* test: update and add backend tests

update and add backend tests

* chore: address backend code rabbit comments

address backend code rabbit comments

* chore: address code rabbit frontend comments

address code rabbit frontend comments

* chore: test_native_tracer minor fix address c1

test_native_tracer minor fix address c1

* chore: address C2 + C3

address C2 + C3

* chore: address H1-H5

address H1-H5

* test: update test_native_tracer

update test_native_tracer

* fixes

* chore: address M2

address m2

* chore: address M1

address M1

* dry changes, factorization

* chore: fix 422 spam and clean comments

fix 422 spam and clean comments

* chore: address M12

address M12

* chore: address M3
 address M3

* chore: address M4

address M4

* chore: address M5

address M5

* chore: clean up for M7, M9, M11

clean up for M7, M9, M11

* chore: address L2,L4,L5,L6 + any test

address L2,L4,L5 and L6 + any test

* chore: alembic + comment clean up

alembic + comment clean up

* chore: remove depricated test_traces file

remove depricated test_traces file. test have all been moved to test_traces_api.py

* fix datetime

* chore: fix test_trace_api ge=0 is allowed now

fix test_trace_api ge=0 is allowed now

* chore: remove unused traces cost flow

remove unused traces cost flow

* fix traces test

* fix traces test

* fix traces test

* fix traces test

* fix traces test

* chore: address gabriels otel coment

address gabriels otel coment latest

---------

Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>
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: Ram Gopal Srikar Katakam <44802869+RamGopalSrikar@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: olayinkaadelakun <olayinka.adelakun@ibm.com>
Co-authored-by: Jordan Frazier <122494242+jordanrfrazier@users.noreply.github.com>
Co-authored-by: cristhianzl <cristhian.lousa@gmail.com>
Co-authored-by: Hamza Rashid <74062092+HzaRashid@users.noreply.github.com>
Co-authored-by: Mendon Kissling <59585235+mendonk@users.noreply.github.com>
Co-authored-by: Lucas Oliveira <62335616+lucaseduoli@users.noreply.github.com>
Co-authored-by: Edwin Jose <edwin.jose@datastax.com>
Co-authored-by: Himavarsha <40851462+HimavarshaVS@users.noreply.github.com>

* fix(test): Fix superuser timeout test errors by replacing heavy clien… (#11982)

fix(test): Fix superuser timeout test errors by replacing heavy client fixture                                                    (#11972)

* fix super user timeout test error

* fix fixture db test

* remove canary test

* [autofix.ci] apply automated fixes

* flaky test

---------

Co-authored-by: Cristhian Zanforlin Lousa <cristhian.lousa@gmail.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* refactor(components): Replace eager import with lazy loading in agentics module  (#11974)

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

* fix: add ondelete=CASCADE to TraceBase.flow_id to match migration (#12002)

* fix: add ondelete=CASCADE to TraceBase.flow_id to match migration

The migration file creates the trace table's flow_id foreign key with
ondelete="CASCADE", but the model was missing this parameter. This
mismatch caused the migration validator to block startup.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: add defensive migration to ensure trace.flow_id has CASCADE

Adds a migration that ensures the trace.flow_id foreign key has
ondelete=CASCADE. While the original migration already creates it
with CASCADE, this provides a safety net for any databases that may
have gotten into an inconsistent state.

* fix: dynamically find FK constraint name in migration

The original migration did not name the FK constraint, so it gets an
auto-generated name that varies by database. This fix queries the
database to find the actual constraint name before dropping it.

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* fix: LE-456 - Update ButtonSendWrapper to handle building state and improve button functionality (#12000)

* fix: Update ButtonSendWrapper to handle building state and improve button functionality

* fix(frontend): rename stop button title to avoid Playwright selector conflict

The "Stop building" title caused getByRole('button', { name: 'Stop' })
to match two elements, breaking Playwright tests in shards 19, 20, 22, 25.

Renamed to "Cancel" to avoid the collision with the no-input stop button.

* Fix: pydantic fail because output is list, instead of a dict (#11987)

pydantic fail because output is list, instead of a dict

Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>

* refactor: Update guardrails icons (#12016)

* Update guardrails.py

Changing the heuristic threshold icons.

The field was using the default icons. I added icons related to the security theme.

* [autofix.ci] apply automated fixes

---------

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

* feat: Clean up the modelinput unification

* [autofix.ci] apply automated fixes

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

* Update test_embedding_model_component.py

* [autofix.ci] apply automated fixes

* Revert to main for other files

* More reversions

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

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

* [autofix.ci] apply automated fixes

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

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

* [autofix.ci] apply automated fixes

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

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

* Handle first run more elegantly in astra

* [autofix.ci] apply automated fixes

* Fix knowledge embedding dialog (#12071)

* fix: Handle message inputs when ingesting knowledge

* [autofix.ci] apply automated fixes

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

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

* Update test_ingestion.py

* [autofix.ci] apply automated fixes

* fix: Unify the knowledge creation model selector

* Revert tracing

* Update ingestion.py

* Rebuild comp index

* [autofix.ci] apply automated fixes

* Update test_ingestion.py

* [autofix.ci] apply automated fixes

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

* Update test_ingestion.py

* Update component_index.json

* [autofix.ci] apply automated fixes

---------

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

* [autofix.ci] apply automated fixes

* Update comp index

* Update test_astradb_base_component.py

* Update Knowledge Ingestion.json

* [autofix.ci] apply automated fixes

* Fix broken tests

* Cleanup from claude

* [autofix.ci] apply automated fixes

* Fix failing tests

* Update test_unified_models.py

* [autofix.ci] apply automated fixes

* Update Nvidia Remix.json

* Refactor ingest

* Rebuild templates and component index

* Fix test

* [autofix.ci] apply automated fixes

* Update component_index.json

* [autofix.ci] apply automated fixes

* test: add update_build_config visibility tests and PR review fixes (#12114)

- Add update_build_config field-visibility tests to LanguageModelComponent,
  ToolCallingAgentComponent, and BatchRunComponent covering Ollama, WatsonX,
  OpenAI, and no-model-selected cases
- Remove 16 stale @pytest.mark.skip tests from test_agent_component.py
- Wire up validate_model_selection in agent.py for early input validation
- Document AstraDB intentional use of lower-level update_model_options_in_build_config
- Clarify model_kwargs info text to note provider-specific support

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* Update embedding_model.py

* fix: address PR review recommendations for feat-unify-models++ (#12116)

- Fix 9 skipped tests in test_batch_run_component.py by replacing model
  list with _MockLLM instances, following the existing pattern used by
  test_with_config_failure_handling
- Fix test_agent_component.py: set component.model to a valid list before
  calling get_agent_requirements() in the three max_tokens tests, since
  validate_model_selection now requires a list-format model
- Replace os.environ direct reads in apply_provider_variable_config_to_build_config
  with get_all_variables_for_provider() (DB-first, env fallback), and pass
  user_id through from handle_model_input_update
- Add deprecated stubs for update_provider_fields_visibility, _update_watsonx_fields,
  and _update_ollama_fields in model_config.py with DeprecationWarning pointing
  to handle_model_input_update
- Fix typo: "deault" -> "default" in structured_output.py TODO comment
- Add 4 new KnowledgeIngestionComponent tests: new-format model_selection
  metadata path, allow_duplicates=True, missing metadata file error, and
  _build_embedding_metadata without API key

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* Ruff errors

* Update test_ingestion.py

* Update component index

* Test updates

* Update component_index.json

* Update stable_hash_history.json

* Template updates

* Update batch_run.py

* [autofix.ci] apply automated fixes

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

* Update Youtube Analysis.json

* Fix tests

* [autofix.ci] apply automated fixes

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

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

* Some cleanup and refactoring

* [autofix.ci] apply automated fixes

* Update Nvidia Remix.json

* Update Nvidia Remix.json

* Update unified_models.py

* Coderabbit AI review comments

* Component index update

* [autofix.ci] apply automated fixes

* Template updates

* [autofix.ci] apply automated fixes

* Template update

* [autofix.ci] apply automated fixes

* Review comments addressed

* [autofix.ci] apply automated fixes

* Update component_index.json

* Update stable_hash_history.json

* [autofix.ci] apply automated fixes

* Test updates

* Update test_ingestion.py

* Update test_ingestion.py

* Update test_ingestion.py

* [autofix.ci] apply automated fixes

* More clear tooltip text

* [autofix.ci] apply automated fixes

* Template updates

* Index and templates

* [autofix.ci] apply automated fixes

* Fix lambda build

* Template updates

* Rebuild comp index

* [autofix.ci] apply automated fixes

* Fix templates

* Fix failing test

* Update templates

* Update comp index

* [autofix.ci] apply automated fixes

* API key field in astra db

* Update starter

* Update comp index

* Starter proj update

* Add api key to field order

* Update test_unified_models.py

* Update test_unified_models.py

* [autofix.ci] apply automated fixes

* Update setup.py

* Update setup.py

* Update component_index.json

* [autofix.ci] apply automated fixes

* Return embedding models directly in KB

* [autofix.ci] apply automated fixes

* Update component_index.json

* fix: Refactor the unified models code

* Ruff checks

* Update flow_preparation.py

* [autofix.ci] apply automated fixes

* Update test_language_model_component.py

* fix: prevent overwriting user-selected global variables in provider c… (#12217)

* fix: nightly now properly gets 1.9.0 branch (#12215)

before it was attempting to pull release-notes as letters are alphanumerically after numbers when we sort -V then grab tail
now we only look at branch names that follow the pattern '^release-[0-9]+\.[0-9]+\.[0-9]+$'

* docs: add search icon (#12216)

add-back-svg

* fix: prevent overwriting user-selected global variables in provider config

Previously, the apply_provider_variable_config_to_build_config function would
automatically overwrite field values with environment variable keys whenever
an env var was present, even if the user had already selected a different
global variable.

This fix adds a check to only auto-set the environment variable if:
- The field is currently empty, OR
- The field is not already configured to load from the database

This preserves user selections while still providing automatic configuration
for new/empty fields.

Added comprehensive unit tests to verify:
- Auto-setting env vars for empty fields
- Preserving user-selected global variables
- Overwriting hardcoded values (expected behavior)
- Skipping when env var is not set
- Applying component metadata correctly

* [autofix.ci] apply automated fixes

* style: use dictionary comprehension instead of for-loop

Fixed PERF403 Ruff style warning by replacing for-loop with dictionary
comprehension in update_projects_components_with_latest_component_versions

* chore: retrigger CI build

* test: improve test coverage and clarity for provider config

- Renamed test_apply_provider_config_overwrites_hardcoded_value to
  test_apply_provider_config_replaces_hardcoded_with_env_var for clarity
- Added test_apply_provider_config_idempotent_when_already_set to document
  idempotent behavior when value already matches env var key
- Removed sensitive value from debug log message to prevent potential
  exposure of API keys or credentials

These changes improve test coverage by documenting the no-op scenario
and enhance security by avoiding logging of potentially sensitive data.

* chore: retrigger CI build

---------

Co-authored-by: Adam-Aghili <149833988+Adam-Aghili@users.noreply.github.com>
Co-authored-by: Mendon Kissling <59585235+mendonk@users.noreply.github.com>
Co-authored-by: Steve Haertel <shaertel@ca.ibm.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Eric Hare <ericrhare@gmail.com>

* Update build_config.py

* [autofix.ci] apply automated fixes

* Update build_config.py

* Fix tests

* fix: Dropdown issue with field population

* Update test_unified_models.py

* Clean up key config

* [autofix.ci] apply automated fixes

* fix tests

* Fix tests

* fix: Update tests

* Update tests

* Update test_tool_calling_agent.py

* Update test_unified_models.py

* Update test_tool_calling_agent.py

* Update tests

* Google AI generative embeddings fixes

* [autofix.ci] apply automated fixes

* Merge release branch

* Template update

* Merge release branch

* [autofix.ci] apply automated fixes

* Update openai_constants.py

* Update openai_constants.py

---------

Co-authored-by: Adam-Aghili <149833988+Adam-Aghili@users.noreply.github.com>
Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@logspace.ai>
Co-authored-by: keval shah <kevalvirat@gmail.com>
Co-authored-by: Antônio Alexandre Borges Lima <104531655+AntonioABLima@users.noreply.github.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: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com>
Co-authored-by: Ram Gopal Srikar Katakam <44802869+RamGopalSrikar@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: olayinkaadelakun <olayinka.adelakun@ibm.com>
Co-authored-by: Jordan Frazier <122494242+jordanrfrazier@users.noreply.github.com>
Co-authored-by: cristhianzl <cristhian.lousa@gmail.com>
Co-authored-by: Hamza Rashid <74062092+HzaRashid@users.noreply.github.com>
Co-authored-by: Mendon Kissling <59585235+mendonk@users.noreply.github.com>
Co-authored-by: Lucas Oliveira <62335616+lucaseduoli@users.noreply.github.com>
Co-authored-by: Edwin Jose <edwin.jose@datastax.com>
Co-authored-by: Himavarsha <40851462+HimavarshaVS@users.noreply.github.com>
Co-authored-by: Viktor Avelino <64113566+viktoravelino@users.noreply.github.com>
Co-authored-by: Lucas Democh <ldgoularte@gmail.com>
Co-authored-by: Steve Haertel <stevehaertel@users.noreply.github.com>
Co-authored-by: Steve Haertel <shaertel@ca.ibm.com>
2026-03-19 19:48:47 +00:00
7d4ffbcbf5 feat: add support for Langchain 1.0 (#11114)
* feat: upgrade to LangChain 1.0

- langchain ~=1.2.0
- langchain-core ~=1.2.3
- langchain-community ~=0.4.1

Updated all langchain-* integration packages to versions compatible with langchain-core 1.0+.

* feat(lfx): add langchain-classic dependency for legacy agent classes

LangChain 1.0 removed AgentExecutor and related classes to langchain-classic.
This adds the dependency to maintain backward compatibility.

* refactor(lfx): update imports for LangChain 1.0 compatibility

- Move AgentExecutor, agent creators from langchain to langchain_classic
- Move AsyncCallbackHandler from langchain.callbacks to langchain_core.callbacks
- Move Chain, BaseChatMemory from langchain to langchain_classic
- Update LANGCHAIN_IMPORT_STRING for code generation

* fix(lfx): make sqlalchemy import lazy in session_scope

LangChain 1.0 no longer includes sqlalchemy as a transitive dependency.
Move the import inside the function where it's used to avoid import errors
when sqlalchemy is not installed.

* chore: update uv.lock for langchain-classic

* feat: enable nv-ingest optional dependencies for langchain 1.0

- Uncomment nv-ingest-api and nv-ingest-client, update to >=26.1.0
  (no longer has openai version conflict)
- Bump datasets from <4.0.0 to <5.0.0 to allow fsspec>=2025.5.1
  required by nv-ingest
- Update mlx-vlm TODO comment with accurate blocking reason

* chore: update nv-ingest to 26.1.1

nv-ingest 26.1.1 removes the openai dependency, resolving the
conflict with langchain-openai>=1.0.0 (which requires openai>=1.109.1).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: enable mlx and mlx-vlm dependencies for langchain 1.0

opencv-python 4.13+ now supports numpy>=2, resolving the conflict
with langchain-aws>=1.0.0 (which requires numpy>=2.2 on Python 3.12+).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* style: fix import order in callback.py

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: update imports to use langchain_classic for agent modules

* [autofix.ci] apply automated fixes

* fix: remove .item() calls in knowledge_bases.py

* fix(lfx): import BaseMemory from langchain_classic for langchain 1.0

* [autofix.ci] apply automated fixes

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

* refactor: update deprecated langchain imports for langchain 1.0

- langchain.callbacks.base -> langchain_core.callbacks.base
- langchain.tools -> langchain_core.tools
- langchain.schema -> langchain_core.messages/documents
- langchain.chains -> langchain_classic.chains
- langchain.retrievers -> langchain_classic.retrievers
- langchain.memory -> langchain_classic.memory
- langchain.globals -> langchain_core.globals
- langchain.docstore -> langchain_core.documents
- langchain.prompts -> langchain_core.prompts

Also simplified GoogleGenerativeAIEmbeddingsComponent to use native
langchain-google-genai 4.x which now supports output_dimensionality.

* [autofix.ci] apply automated fixes

* fix: add _to_int helper for pandas sum() compatibility across Python versions

* fix: update langfuse>=3.8.0 and fix cuga_agent.py (#11519)

* fix: update langfuse>=3.8.0 and fix cuga_agent.py

* [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>

* feat: implement LangFuseTracer for langfuse v3 API compatibility and add unit tests

* fix: upgrade cuga to 0.2.9 for langchain 1.0 compatibility

* fix: improve error handling and return value in get_langchain_callback method

* fix: update package versions for compatibility and improvements

* [autofix.ci] apply automated fixes

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

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

* fix: update langwatch dependency to version 0.10.0 for compatibility

* fix: update environment variable for Langfuse host to LANGFUSE_BASE_URL

* Update dependency versions in Youtube Analysis project

- Downgraded googleapiclient from 2.188.0 to 2.154.0
- Updated langchain_core from 1.2.7 to 1.2.9
- Updated fastapi from 0.128.1 to 0.128.5
- Downgraded youtube_transcript_api from 1.2.4 to 1.2.3
- Changed langchain_core version from 1.2.7 to 0.3.81
- Cleared input_types in model selection

# Conflicts:
#	src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json
#	src/backend/base/langflow/initial_setup/starter_projects/Basic Prompting.json
#	src/backend/base/langflow/initial_setup/starter_projects/Blog Writer.json
#	src/backend/base/langflow/initial_setup/starter_projects/Custom Component Generator.json
#	src/backend/base/langflow/initial_setup/starter_projects/Document Q&A.json
#	src/backend/base/langflow/initial_setup/starter_projects/Financial Report Parser.json
#	src/backend/base/langflow/initial_setup/starter_projects/Hybrid Search RAG.json
#	src/backend/base/langflow/initial_setup/starter_projects/Image Sentiment Analysis.json
#	src/backend/base/langflow/initial_setup/starter_projects/Instagram Copywriter.json
#	src/backend/base/langflow/initial_setup/starter_projects/Invoice Summarizer.json
#	src/backend/base/langflow/initial_setup/starter_projects/Knowledge Retrieval.json
#	src/backend/base/langflow/initial_setup/starter_projects/Market Research.json
#	src/backend/base/langflow/initial_setup/starter_projects/Meeting Summary.json
#	src/backend/base/langflow/initial_setup/starter_projects/Memory Chatbot.json
#	src/backend/base/langflow/initial_setup/starter_projects/News Aggregator.json
#	src/backend/base/langflow/initial_setup/starter_projects/Nvidia Remix.json
#	src/backend/base/langflow/initial_setup/starter_projects/Pokédex Agent.json
#	src/backend/base/langflow/initial_setup/starter_projects/Portfolio Website Code Generator.json
#	src/backend/base/langflow/initial_setup/starter_projects/Price Deal Finder.json
#	src/backend/base/langflow/initial_setup/starter_projects/Research Agent.json
#	src/backend/base/langflow/initial_setup/starter_projects/Research Translation Loop.json
#	src/backend/base/langflow/initial_setup/starter_projects/SEO Keyword Generator.json
#	src/backend/base/langflow/initial_setup/starter_projects/SaaS Pricing.json
#	src/backend/base/langflow/initial_setup/starter_projects/Search agent.json
#	src/backend/base/langflow/initial_setup/starter_projects/Sequential Tasks Agents.json
#	src/backend/base/langflow/initial_setup/starter_projects/Simple Agent.json
#	src/backend/base/langflow/initial_setup/starter_projects/Social Media Agent.json
#	src/backend/base/langflow/initial_setup/starter_projects/Text Sentiment Analysis.json
#	src/backend/base/langflow/initial_setup/starter_projects/Travel Planning Agents.json
#	src/backend/base/langflow/initial_setup/starter_projects/Twitter Thread Generator.json
#	src/backend/base/langflow/initial_setup/starter_projects/Vector Store RAG.json
#	src/backend/base/langflow/initial_setup/starter_projects/Youtube Analysis.json

* fix: handle InvalidRequestError during session rollback

* update projects

* ️ Speed up method `LangFuseTracer.end` by 141% in PR #11114 (`feat/langchain-1.0`) (#11682)

Optimize LangFuseTracer.end 


The optimized code achieves a **140% speedup** (8.23ms → 3.42ms) through two complementary optimizations:

## 1. Fast-path for Common Primitives in `serialize()`

**What changed:** Added an early-exit check that returns immutable primitives (`str`, `int`, `float`, `bool`) directly when no truncation or special handling is needed:

```python
if max_length is None and max_items is None and not to_str:
    if isinstance(obj, (str, int, float, bool)):
        return obj
```

**Why it's faster:** 
- The profiler shows `_serialize_dispatcher()` consumed **81.5% of runtime** in the original code (40.4ms out of 49.6ms)
- This optimization reduced dispatcher calls from **8,040 to 1,013** (~87% reduction), as primitives now bypass the expensive pattern-matching dispatcher entirely
- The fast-path check itself is extremely cheap: just two quick conditionals and an `isinstance()` check against a tuple of built-in types

**When it helps:** This optimization is particularly effective for workloads with many primitive values in dictionaries and lists—which is exactly what the tracing use case provides (metadata dicts with strings, numbers, booleans).

## 2. Eliminate Redundant Serialization in `LangFuseTracer.end()`

**What changed:** Serialize `inputs`, `outputs`, and `metadata` once each, then reuse the results:

```python
inputs_ser = serialize(inputs)
outputs_ser = serialize(outputs)
metadata_ser = serialize(metadata) if metadata else None
```

**Why it's faster:**
- The original code called `serialize()` **6 times total** (3 for `.update()` + 3 for `.update_trace()`)
- The optimized version calls it **3 times**, then passes the cached results
- Profiler shows the time spent in `serialize()` calls dropped from **72.2ms to 31.2ms** (~57% reduction)
- This is pure elimination of redundant work—the same dictionaries were being serialized twice with identical results

**Impact on workloads:** The `test_end_multiple_iterations_calls_end_each_time` test (500 iterations) demonstrates this matters in hot paths. If `LangFuseTracer.end()` is called frequently during flow execution, avoiding duplicate serialization provides compounding benefits.

## Combined Effect

Both optimizations target the serialization bottleneck from different angles:
- The fast-path reduces the cost of *each* serialize call by ~75% for primitive-heavy data
- The caching reduces the *number* of serialize calls by 50%

Together, they deliver the observed 140% speedup, with the optimization being especially effective for the common case of metadata dictionaries containing mostly primitive types.

Co-authored-by: codeflash-ai[bot] <148906541+codeflash-ai[bot]@users.noreply.github.com>

* refactor: reorder imports and simplify serialization logic for primitives

* [autofix.ci] apply automated fixes

* fix: update google dependency version to 0.4.0 in component_index.json

* [autofix.ci] apply automated fixes

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

* fix: pin z3-solver<4.15.7 to restore Linux wheels for Docker build

z3-solver 4.15.7 dropped manylinux wheels, causing the Docker build to
fail when trying to compile from source. Temporary pin until codeflash
is removed.

* [autofix.ci] apply automated fixes

* fix: update google dependency version to 0.4.0

* [autofix.ci] apply automated fixes

* fix: update langchain_core version to 1.2.17 in multiple starter project JSON files

* [autofix.ci] apply automated fixes

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

* fix: update deprecated langchain imports to langchain_classic for 1.0 compatibility

* fix: align langchain-chroma version in optional chroma dependency group

* fix: nightly now properly gets 1.9.0 branch (#12215)

before it was attempting to pull release-notes as letters are alphanumerically after numbers when we sort -V then grab tail
now we only look at branch names that follow the pattern '^release-[0-9]+\.[0-9]+\.[0-9]+$'

* docs: add search icon (#12216)

add-back-svg

* [autofix.ci] apply automated fixes

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

* feat: fall back to langchain_classic for pre-1.0 imports in user components

Old flows using removed langchain imports (e.g. langchain.memory,
langchain.schema, langchain.chains) now resolve via langchain_classic
at two levels: module-level for entirely removed modules, and
attribute-level for removed attributes in modules that still exist
in langchain 1.0. New langchain 1.0 imports are never affected since
fallbacks only trigger on import failure.

* urllib parse module import bug

* Update component_index.json

* [autofix.ci] apply automated fixes

* chore: rebuild component index

* [autofix.ci] apply automated fixes

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Harold Ship <harold.ship@gmail.com>
Co-authored-by: codeflash-ai[bot] <148906541+codeflash-ai[bot]@users.noreply.github.com>
Co-authored-by: Adam-Aghili <149833988+Adam-Aghili@users.noreply.github.com>
Co-authored-by: Mendon Kissling <59585235+mendonk@users.noreply.github.com>
Co-authored-by: Eric Hare <ericrhare@gmail.com>
2026-03-19 18:56:10 +00:00
f46ff2ab72 feat: Add Windows Playwright testing to nightly builds (#12221)
* feat: add Windows support for Playwright tests in nightly builds

- Add windows-latest as runner option in typescript_test.yml
- Update Playwright browser installation to be OS-aware (Windows doesn't support --with-deps)
- Add matrix strategy to nightly_build.yml to run tests on both Linux and Windows
- Update Slack notifications to indicate multi-platform testing
- Tests now run in parallel on ubuntu-latest and windows-latest

This enables catching Windows-specific regressions early in the nightly build process.

* fix: add shell: bash to all script steps for Windows compatibility

Windows runners default to PowerShell which doesn't understand bash syntax.
All steps with bash scripts now explicitly specify shell: bash to ensure
cross-platform compatibility.

* feat: make Windows Playwright tests non-blocking initially

Add continue-on-error for Windows tests to allow nightly builds to succeed
even if Windows-specific issues are found. This gives us visibility into
Windows bugs without blocking releases.

Windows tests will still run every night and report failures, but won't
block the build. Once Windows tests are stable, we can remove this flag.

* chore: fix white space

chore: fix white space

* fix: replace matrix strategy with separate jobs for Windows Playwright tests

- GitHub Actions reusable workflows don't support matrix strategy
- Split frontend-tests into frontend-tests-linux and frontend-tests-windows
- Windows tests are non-blocking (continue-on-error: true)
- Updated all job dependencies and Slack notification logic
- Addresses PR review comment about matrix limitation

* chore: trigger workflow validation refresh

---------

Co-authored-by: Adam Aghili <Adam.Aghili@ibm.com>
2026-03-19 15:08:54 +00:00
288719d4ff fix: prevent overwriting user-selected global variables in provider c… (#12217)
* fix: nightly now properly gets 1.9.0 branch (#12215)

before it was attempting to pull release-notes as letters are alphanumerically after numbers when we sort -V then grab tail
now we only look at branch names that follow the pattern '^release-[0-9]+\.[0-9]+\.[0-9]+$'

* docs: add search icon (#12216)

add-back-svg

* fix: prevent overwriting user-selected global variables in provider config

Previously, the apply_provider_variable_config_to_build_config function would
automatically overwrite field values with environment variable keys whenever
an env var was present, even if the user had already selected a different
global variable.

This fix adds a check to only auto-set the environment variable if:
- The field is currently empty, OR
- The field is not already configured to load from the database

This preserves user selections while still providing automatic configuration
for new/empty fields.

Added comprehensive unit tests to verify:
- Auto-setting env vars for empty fields
- Preserving user-selected global variables
- Overwriting hardcoded values (expected behavior)
- Skipping when env var is not set
- Applying component metadata correctly

* [autofix.ci] apply automated fixes

* style: use dictionary comprehension instead of for-loop

Fixed PERF403 Ruff style warning by replacing for-loop with dictionary
comprehension in update_projects_components_with_latest_component_versions

* chore: retrigger CI build

* test: improve test coverage and clarity for provider config

- Renamed test_apply_provider_config_overwrites_hardcoded_value to
  test_apply_provider_config_replaces_hardcoded_with_env_var for clarity
- Added test_apply_provider_config_idempotent_when_already_set to document
  idempotent behavior when value already matches env var key
- Removed sensitive value from debug log message to prevent potential
  exposure of API keys or credentials

These changes improve test coverage by documenting the no-op scenario
and enhance security by avoiding logging of potentially sensitive data.

* chore: retrigger CI build

---------

Co-authored-by: Adam-Aghili <149833988+Adam-Aghili@users.noreply.github.com>
Co-authored-by: Mendon Kissling <59585235+mendonk@users.noreply.github.com>
Co-authored-by: Steve Haertel <shaertel@ca.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-03-17 15:19:33 -07:00