Files
langflow/.github/workflows
Jordan Frazier 1ab6251164 feat: sync langflow and lfx versions (#13176)
* feat(lfx): synchronize LFX onto Langflow major.minor version line (Phase 1)

- Bump src/lfx/pyproject.toml from 0.5.0 to 1.10.0
- Tighten langflow-base lfx pin: ~=0.5.0 → ~=1.10.0
- Fix release.yml pre-release boundary from next-major to next-minor (<X.(Y+1).dev0)
- Add minor-parity soft check to scripts/release-lfx.sh
- Extend make patch to sync lfx version alongside langflow/base/frontend
- Document LFX compatibility contract in RELEASE.md

Contract: LFX X.Y.N is compatible with any Flow from Langflow X.Y.M.

* feat(lfx/upgrade): add compatibility checker (Phase 2)

* fix(lfx/upgrade): fix registry_code guard and types order-sensitivity in checker

* feat(lfx/upgrade): implement safe-upgrade applier (Phase 2)

* feat(lfx): add lfx upgrade command (Phase 2)

* feat(lfx/run): add --upgrade-flow option (Phase 2)

* feat(lfx/serve): add --upgrade-flow option (Phase 2)

* update lfx pyproject version

* [autofix.ci] apply automated fixes

* test(lfx/upgrade): add v1.9.0 starter flow fixtures for upgrade integration tests

* test(lfx/upgrade): add v1.9.0 starter flow fixtures and real-flow integration tests

* [autofix.ci] apply automated fixes

* fix(lfx/upgrade): use alias-aware registry lookup so renamed components are not falsely blocked

* fix(lfx/upgrade): handle outer flow envelope and file-path inputs in upgrade checks

* fix(lfx/upgrade): fail-fast on upgrade_flow errors; add regression tests for Bugs 1-3

* chore(tests): remove bug-number labels from test comments

* [autofix.ci] apply automated fixes

* fix(lfx/upgrade): address PR review comments

- Reject .py files early in serve --upgrade-flow with a clear error message
- Preserve outer flow envelope metadata (name, description, etc.) when lfx upgrade --write rewrites a file
- Move Mapping import under TYPE_CHECKING to satisfy Ruff TC003
- Assert fixture flows and registry are non-empty so parametrized tests cannot pass vacuously
- Remove unused capsys arg and replace print with sys.stderr.write (Ruff T201/ARG001)
- Add upgrade_flow param to run command docstring

* fix(lfx/upgrade): preserve envelope on run, apply nested upgrades (#13200)

* fix(lfx/upgrade): preserve envelope on run, apply nested upgrades

Three follow-ups on top of the upgrade tooling:

- run --upgrade-flow: re-attach the inner graph to the outer envelope before handing the flow to aload_flow_from_json. Previously the upgrade path unwrapped {"data": ...} and passed the inner dict to the loader, which raised KeyError: 'data'. Adds happy-path tests for envelope and flat file inputs.
- applier: recurse into one level of nested flow nodes (node.data.node.flow.data.nodes), matching the checker. Without this, outdated_safe nodes inside grouped components were reported but never written. Adds a regression test.
- upgrade --write test: assert the envelope is preserved (name, description, endpoint_name, etc.) instead of the previous unwrapped-output expectation, so the test matches the actual fix in this PR.
- Drive-by ruff cleanup: D417 docstring, SIM103, SIM108, E501, RUF059.

* [autofix.ci] apply automated fixes

---------

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

* fix(lfx/upgrade): fix loader KeyError, outer-envelope checker gap, and nested-node applier

Three bugs from ogabrielluiz's PR review:

1. run/base.py loader KeyError: file-path branch unwrapped the outer envelope
   for the checker but passed the inner dict to aload_flow_from_json, which does
   flow_graph["data"] unconditionally. Re-wrap as {"data": flow_dict} before the
   loader call. Applied consistently to all three input paths (--flow-json,
   --stdin, file-path).

2. run/base.py zero-node checker for --flow-json/--stdin: those paths stored the
   raw parsed JSON without unwrapping, so a caller passing an exported flow
   {"name":..., "data":{...}} caused the checker to see zero nodes and silently
   pass. Now unwrap with raw.get("data", raw) matching the file-path branch.

3. applier.py nested flows never upgraded: the early `continue` on top-level
   nodes not in safe_ids prevented the nested-node loop from running. Restructured
   so the nested check fires unconditionally for every top-level node, mirroring
   checker.py:160-165.

* fix(lfx/run): unify outer-envelope unwrap across all --upgrade-flow input paths

File-path reads now call raw.get("data", raw) matching --flow-json and
--stdin, so the upgrade checker always sees the inner graph. This also
removes the has_envelope/re-wrap machinery that was double-wrapping
outer-envelope files when passing to aload_flow_from_json.

Fix two test assertions that described the old double-wrapped shape.

* fix(lfx/upgrade): inject registry into upgrade_command; fix Makefile lfx pin regex

- upgrade_command now accepts an optional registry parameter so tests
  can pass the dict directly instead of mocking load_registry_from_index
- Makefile sed regex broadened from \"lfx~=.*\" to match both ~= and >=
  forms so make patch works after release.yml rewrites the pin
- Echo label changed to LFX (synced) to clarify the variable is the
  shared Langflow version, not a separate LFX-specific value

* fix(make/patch): fix langflow-base sed regex and validation grep

The dependency in pyproject.toml is "langflow-base[complete]>=X.Y.Z",
not the "langflow-base==X" form the original regex expected, so make
patch silently left the pin unchanged and the validation step always
failed. The sed pattern now matches any extras/operator combination and
rewrites to the canonical [complete]>= form; the grep uses -F so the
[complete] brackets are treated literally.

* test(lfx): add patch regex tests and symmetric safe-mode envelope tests

test_patch_regexes.py — 15 tests covering the Python regexes embedded in
the Makefile patch target. Exercises all three substitutions (langflow-base
pin, lfx pin, version field) against every realistic pin format including
the >=X.Y.Z,<dev0 form that release.yml writes. Would have caught the
langflow-base==.* vs [complete]>= mismatch before manual testing.

test_base.py — two new TestUpgradeFlowOption tests:
  test_upgrade_flow_safe_envelope_inline_json_loads_successfully
  test_upgrade_flow_safe_envelope_stdin_loads_successfully
Symmetric to the existing file-path envelope test; verifies that --flow-json
and --stdin with an outer-envelope flow also pass {"data": inner} to the
loader after safe upgrades, not a double-wrapped {"data": outer_envelope}.

* fix(lfx/upgrade): address review: compat checker, shared gate, fail-fast registry

Checker correctness:
- _outputs_are_compatible: drop cosmetic display_name from the breaking check;
  treat widened output types as safe (flow types must be a subset of registry
  types), only narrowing breaks downstream edges.
- _input_types_contained: stop flagging widened input_types as breaking; keep
  narrowing as the only breaking case; fix misleading comments.
- check_flow_compatibility now recurses fully into nested grouped components
  (symmetric with the applier) and accepts a pre-built registry lookup.

CLI/run/serve:
- New lfx.upgrade.cli_gate (UpgradeFlowMode enum, UpgradeFlowError,
  apply_upgrade_gate) shared by run_flow and serve_command so the two
  --upgrade-flow paths can't diverge.
- run_flow: extract _materialize_flow_dict and route gating through the shared
  helper.
- run/serve --upgrade-flow options typed as UpgradeFlowMode (check|safe choices).
- lfx upgrade: load_registry_from_index fails fast when the bundled registry is
  empty/missing instead of silently marking every node blocked; ASCII-only report
  output; new --strict flag; build the registry lookup once and reuse it.

Docs/tests:
- RELEASE.md: migration note for the lfx 0.5.0 -> 1.10.0 version jump.
- Regression tests for the checker fixes, the shared gate, fail-fast registry,
  --strict, and serve --upgrade-flow parity.

* [autofix.ci] apply automated fixes

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

* fix(lfx): consolidate flow-envelope handling and fix version-ceiling regex

Extract the outer-envelope unwrap/rewrap logic (previously hand-rolled as
raw.get("data", raw) with subtly different rules across serve, run, and
upgrade) into a single lfx.utils.flow_envelope module with split/merge
helpers. This fixes a serve bug where an enveloped flow had its inner graph
written bare to the temp file, making the loader's flow_graph["data"] raise
KeyError.

Also fix release.yml's major.minor extraction: the greedy sed grabbed the
upper bound from a range pin (>=1.10.0,<1.11.dev0), drifting the version
ceiling up one minor each release cycle. Anchor to the first version instead.

* fix(lfx): upgrade-flow gate reads bundled component index, not empty cache

The --upgrade-flow=check|safe gate on lfx run and lfx serve rejected every
flow as 'blocked'. Both call sites passed component_cache.all_types_dict to
apply_upgrade_gate, but that cache is populated lazily after services start,
so at gate time it is empty -- an empty registry classifies every node as
blocked. The standalone lfx upgrade command was unaffected because it reads
the bundled _assets/component_index.json instead.

Make the gate own registry loading: apply_upgrade_gate now defaults
all_types_dict to None and loads the bundled index (the same source lfx
upgrade uses) via a new _load_bundled_registry helper, raising
UpgradeFlowError on a missing/empty index so a broken install fails loudly
instead of silently blocking every component. Both call sites pass mode=
and let the gate load the registry.

Existing gate tests mocked component_cache with a populated registry, which
is exactly what hid the bug; repoint them at the new _load_bundled_registry
seam and add regression tests that do not mock the registry, including an
end-to-end run_flow check against a real clean v1.9.0 starter flow.

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@logspace.ai>
2026-06-05 01:30:59 +00:00
..
2026-04-21 16:18:16 -04:00