Commit Graph

17889 Commits

Author SHA1 Message Date
dce21ff925 ref: flip wxo ff (#12924)
* revert wxo deploy ffj

* skip deployments telemetry test when flag is off
2026-04-30 16:08:28 +00:00
9c6839c0f0 fix(tests): Stabilize Windows-only Playwright e2e failures (#12942) 2026-04-30 11:55:41 -03:00
bc16a400d6 docs: add telemetry for deployments endpoints (#12922)
* docs-add-telemetry-for-deployments-endpoints

* peer-review
2026-04-30 13:47:32 +00:00
fab079c400 [backend] fix: add cache_dir setting to avoid multi-instance conflicts (#12940)
* [backend] fix: add cache_dir setting to avoid multi-instance conflicts

Fixes #12299

## Problem
- Cache factory always used config_dir for disk cache
- Multi-instance clusters shared the same cache directory
- Caused sqlite3.DatabaseError: database disk image is malformed

## Solution
1. Added cache_dir setting (defaults to config_dir for backward compatibility)
2. Updated cache factory to use cache_dir when set, fallback to config_dir

## Impact
- Multi-instance deployments can now set LANGFLOW_CACHE_DIR independently
- Prevents concurrent access issues on shared storage (NFS, etc.)
- Backward compatible: existing deployments unaffected

## Configuration
Set via environment variable:
  LANGFLOW_CACHE_DIR=/path/to/cache

Or in settings:
  cache_dir: /path/to/cache

(cherry picked from commit 38bf3ec6e2)
Cherry-picked-from-PR: https://github.com/langflow-ai/langflow/pull/12315

* fix: Fix Ruff PERF403 and add cache_dir validator

- Convert dictionary comprehension in setup.py to fix PERF403
- Add cache_dir validator to normalize paths like config_dir
- Follows CodeRabbit review feedback

(cherry picked from commit c8610fb4ce)
Cherry-picked-from-PR: https://github.com/langflow-ai/langflow/pull/12315

* [autofix.ci] apply automated fixes

(cherry picked from commit 508e864858)
Cherry-picked-from-PR: https://github.com/langflow-ai/langflow/pull/12315

* Create test_cache_factory.py

* [autofix.ci] apply automated fixes

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

* Update component_index.json

---------

Co-authored-by: 阳虎 <yanghu@yanghudeMacBook-Pro.local>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-04-29 16:29:38 -07:00
9df2a22876 feat: MemoryBases GUI Component (#12903)
* Memory Base component for LF GUI.

Added option session_id filtration to MemoryBase component. The component filters on all chat history for a particular flow, and keeps it session scoped based on the session_id filtration toggle.

fix: Add kb_path validation before metadata load

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

* chore: trigger CI checks

* [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>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: vijay kumar katuri <vijay.katuri@ibm.com>
2026-04-29 15:43:10 -07:00
79872f1c9d fix: Don't show empty category for MCP search in sidebar (#12930)
fix: Don't show empty category for MCP search
2026-04-29 21:08:29 +00:00
2652d7a52e fix(LE-602): Update Pydantic to >=2.13.0 for fastapi-pagination v0.16.0 compatibility (#12938)
fix(LE-602): update pydantic to >=2.13.0 for fastapi-pagination v0.16.0 compatibility

- Updated pydantic from ~=2.12.5 to >=2.13.0,<3.0.0 in langflow-base
- Updated uv.lock with pydantic 2.13.3 and pydantic-core 2.46.3
- Kept SDK and lfx packages with flexible >=2.0.0 constraint (no fastapi-pagination dependency)
- Verified compatibility with existing tests
2026-04-29 21:00:56 +00:00
d965a3ae6c docs: wxo deployment is behind feature flag (#12937)
* docs-add-release-note-and-tip-for-wxo-feature-flag

* remove-unnecessary-information-from-1.10

* Apply suggestions from code review

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

---------

Co-authored-by: April I. Murphy <36110273+aimurphy@users.noreply.github.com>
2026-04-29 20:52:40 +00:00
8735f065d7 fix: namespace inputs.session on build_public_tmp (#12934)
* fix: namespace inputs.session on build_public_tmp

The unauthenticated POST /api/v1/build_public_tmp/{flow_id}/flow endpoint
accepted a caller-supplied inputs.session that was forwarded to the build's
Memory component verbatim, letting an attacker read chat history stored
under any session id, including the predictable session_id == flow_id that
/api/v1/run hands out by default.

This is a follow-up to the prior CVE-2026-33017 fix (#12160), which removed
the attacker-controlled data parameter but left inputs.session accepted.

Wrap any non-None inputs.session under the per-(client_id, flow_id) virtual
flow ID via a new scope_session_to_namespace helper. Empty strings,
in-namespace values, and pre-prefixed values are handled idempotently. None
passes through unchanged; downstream falls back to the virtual flow ID.

Adds @pytest.mark.security regression tests including an end-to-end memory
query collision check.

* chore: wrap over-length --session-id help string

Fixes pre-existing E501 in _running_commands.py:67 introduced by #12906.
Splits the help string across two lines to fit the 120-column limit.
2026-04-29 19:22:16 +00:00
2c021ac0c7 chore: enable CodeRabbit auto-review on release-* branches (#12936)
Adds release-.* to reviews.auto_review.base_branches so PRs targeting
release branches (e.g. release-1.9.2) receive the same auto-review as
PRs targeting main.
2026-04-29 19:20:57 +00:00
6b7703c067 feat(i18n): translate default node titles on language change, preserve user-customized names (#12928)
* feat(i18n): translate default node display_name/description on language change, preserve user-customized names

Builds a `component_display_names` map (all locale translations per
component type) in `/api/v1/all`. `syncNodeTranslations` checks whether
a node's current display_name/description appears in that set before
overwriting — values in the set are defaults (safe to translate), values
not in the set are user-customized (left alone).

- Backend: add `build_component_display_names()` to i18n.py; append
  result to `/api/v1/all` response
- Frontend: store map in typesStore; extract from API response before
  setTypes; apply set-membership check in syncNodeTranslations for
  display_name and description

* [autofix.ci] apply automated fixes

* fix(ruff): apply ternary operator and use dict.values() in i18n helpers

* fix(ruff): collapse dict comprehension to single line

* fix(tests): exclude component_display_names from component count in test_get_all

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-04-29 18:51:55 +00:00
784169cee7 fix: fallback to sync call in lfx run when stream=true (#12906)
* fix(lfx): unblock streaming flows in lfx run

LCModelComponent._handle_stream tried to persist a partial Message via
send_message whenever the LM was wired to ChatOutput, but the message-
store path requires session_id and the chunk-consumption path requires
an EventManager. lfx run had neither, so flows with stream=True crashed
in astore_message ("session_id, sender, sender_name must be provided").

- run_flow now auto-generates a session_id when none is supplied so the
  message-store validator passes; an explicit value still wins.
- lfx run gains a --session-id flag for memory continuity across runs
  (Memory / MessageHistory components keyed on session_id).
- _handle_stream now also requires an EventManager before taking the
  streaming branch — without one, the chunk iterator would be stored
  but never drained, surfacing as an empty result downstream. Falls
  back to ainvoke and returns the full text instead.

Tests cover the autogen, caller-precedence, and uniqueness cases on
run_flow plus the four _handle_stream branches (no session_id, no
event_manager, both present, not connected to chat output).

* fix(lfx): autogen session_id in CUGA agent when graph has none

Matches the pattern already used by base/agents/agent.py and
base/agents/altk_base_agent.py. Without this, calling the CUGA agent
outside run_flow (which now autogens a session_id) would still fail
astore_message validation.

* [autofix.ci] apply automated fixes

* fix(lfx): plumb session_id through serve /run and /stream

StreamRequest already declared a session_id field but it was never
applied to the graph; RunRequest didn't have the field at all. Both
endpoints called execute_graph_with_capture, which executed against
an empty graph.session_id, so message-store paths skipped storage
silently and Memory components could not maintain continuity.

- Add session_id to RunRequest.
- Have execute_graph_with_capture accept session_id, autogen if empty
  (matches run_flow), and apply it to graph.session_id before
  execution.
- Forward session_id from both /run and /stream handlers.

* fix(lfx): propagate session_id and user_id so memory works on lfx run

The lfx run path uses graph.async_start instead of graph.arun, bypassing
the has_session_id_vertices propagation loop in Graph._run that the
playground hits via build_graph_from_data. Memory/MessageHistory
components reading session_id from their input field would see "" even
when --session-id was passed. Replicate the loop in run_flow and
execute_graph_with_capture, with the same precedence as the playground:
hardcoded values on the component win.

AgentComponent's variable lookup precheck blocks any flow that resolves
variables (e.g. api_key) when graph.user_id is empty. Auto-generate a
ceremonial UUID; lfx's env-fallback variable service ignores user_id, so
this only satisfies the precheck — env vars remain process-global with
no per-user scoping.

Make VariableService.get_variable async to match the langflow call site
(`await variable_service.get_variable(...)` in custom_component.get_variable).
The signature accepts and ignores user_id/field/session kwargs so flows
behave identically under either backend.

Tests cover propagation precedence (empty input filled, hardcoded value
preserved, missing vertex skipped), user_id auto-gen and caller-takes-
precedence, and the async signature with kwarg absorption.

* [autofix.ci] apply automated fixes

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

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

* fix(lfx): plumb fallback_to_env_vars so DatabaseVariableService works in lfx run

The lfx run path uses graph.async_start, which never propagated
fallback_to_env_vars to vertex builds — the flag defaulted to False all
the way down to update_params_with_load_from_db_fields. Result: if a user
swapped lfx's env-fallback VariableService for langflow's
DatabaseVariableService (via lfx.toml), every load_from_db variable
(e.g. api_key=OPENAI_API_KEY) would raise "variable not found" because
the random ceremonial user_id has no DB rows, with no env fallback.

Add fallback_to_env_vars kwarg to async_start and astep (default False,
non-breaking for existing callers). run_flow and execute_graph_with_capture
read settings.fallback_to_env_var (defaults True, settable via
LANGFLOW_FALLBACK_TO_ENV_VAR=false) and pass it through. Mirrors what
processing.process.run_graph_internal does for the langflow API path.

Make memory.stubs.astore_message tolerant of non-UUID flow_ids: the stub
is the no-op fallback when no real database is registered, so it should
not crash on synthetic identifiers (e.g. test fixtures, lfx callers
passing string flow ids). UUID parsing only normalizes format; an
invalid string is preserved verbatim.

Tests:
- TestRunFlowFallbackToEnvVars: confirms run_flow forwards
  fallback_to_env_vars from settings (default and disabled).
- TestGraphExecution: same for execute_graph_with_capture.
- Existing mock_async_start signatures updated to accept **kwargs.
- Test fixtures using flow_id="test-flow-id" replaced with a real UUID
  so the now-active ChatInput storage path doesn't trip stubs.py's
  UUID parse — aligning fixtures with production semantics.

* test(lfx): pass session_id=None when invoking the typer run() directly

The lfx test suite calls ``run(...)`` (the typer command) without going through
typer's CLI parser. Any parameter with a ``typer.Option(...)`` default in the
signature (e.g. ``session_id``) evaluates to a ``typer.models.OptionInfo``
sentinel under that invocation pattern, not None. The session_id propagation
loop then writes that sentinel into ``vertex.raw_params["session_id"]``, which
fails ``MessageTextInput`` validation with
``Invalid value type <class 'typer.models.OptionInfo'>``.

Fix at the call site: pass ``session_id=None`` explicitly. Mirrors how typer
would resolve the option after parsing CLI args. Two tests affected;
test_run_command.py now reflects the constraint that calls bypassing typer
must pass all option-shaped args.

* fix(lfx): harden session_id/user_id handling on lfx run path

Addresses review findings on the streaming-fix PR:

- Reject empty/whitespace --session-id and --user-id up-front so a shell
  quirk or empty env var surfaces a clear error instead of silently
  auto-generating a fresh session and breaking Memory continuity.
- Extract a shared helper (lfx/run/_defaults.py) for session_id/user_id
  auto-gen, vertex propagation, and fallback_to_env_vars resolution; both
  run_flow and execute_graph_with_capture now delegate to it.
- Warn when settings_service is None (silently flipped fallback_to_env_vars
  to False before).
- CUGA agent: wrap uuid.uuid4() with str() to match the rest of the file
  and the codebase's expectation that Message.session_id renders as a hex
  string. Add focused tests with module-level skip when the cuga import
  side-effect (MODELS_METADATA["OpenAI"]) isn't satisfiable.
- Streaming-fallback warning now names the component (display_name + _id)
  so users can identify which model fell back to ainvoke.
- memory/stubs.py: replace contextlib.suppress(ValueError) with explicit
  try/except + warning so malformed flow_ids leave a breadcrumb.
- Improve --session-id help text to explain WHEN to set it.
- Tune session_id auto-gen log level from warning to info (less noisy on
  default CLI runs; visible at -v).
- Add tests: --session-id CLI plumbing, multi-call continuity, empty/
  whitespace rejection, and isinstance(str) on the streaming fallback path.

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-04-29 15:22:24 +00:00
9b11f5a383 feat: backend i18n — serve translated component metadata via Accept-Language (#12517)
* feat: add IBM Globalization Pipeline integration and i18n setup

- Add GP REST API client with GP-HMAC authentication (scripts/gp/gp_client.py)
- Add upload/download scripts for syncing strings with GP
- Set up i18next + react-i18next with 7 language support (en, fr, ja, es, de, pt, zh-Hans)
- Add 48 UI strings in flat dot notation to en.json (from alerts_constants)
- Add GitHub Actions for automated upload on en.json changes and daily translation download

* [autofix.ci] apply automated fixes

* fix: resolve ruff linting issues in GP scripts

- Fix quote style, import ordering, docstring format
- Use Path instead of os.makedirs/open/os.path.join
- Add missing timeouts to requests calls
- Move noqa comments to correct lines for S501

* feat: migrate all frontend UI strings to i18n for GP localization

- Replace all hardcoded user-facing strings with t() calls across 80+ components, pages, modals, and utilities
- Add 326 translation keys to en.json covering errors, alerts, dialogs, chat, flow, settings, store, table, output, nav, auth, and more
- Add translated locale files for fr, es, de, pt, ja, zh-Hans (downloaded from Globalization Pipeline)
- Migrate alerts_constants.tsx and constants.ts string usages to react-i18next
- Support non-React files (stores, utils) via i18n.t() direct calls

* feat: migrate sidebar strings to i18n (Phase 4)

- Add 56 new translation keys for sidebar categories, nav items, labels, buttons, and empty states
- Convert SIDEBAR_CATEGORIES display_names to i18n key references in styleUtils.ts
- Update 13 sidebar components to use t() for all user-facing strings
- Refresh all 6 locale files from GP (382 total keys)
- Add BACKEND_STRINGS_STRATEGY.md documenting plan for component display_name i18n

* [autofix.ci] apply automated fixes

* fix: add react-i18next mock and fix sidebar nav tests for i18n migration

- Add global react-i18next mock in jest.setup.js using en.json lookups so
  t(key) returns English strings instead of raw keys in test environment
- Fix sidebarSegmentedNav tests: update NAV_ITEMS expectations to use i18n
  keys, and use en.json lookups for tooltip/accessibility label assertions

* feat: add LanguageSelector dropdown to globalization pipeline

Cherry-picked frontend-only changes from feat/gp-backend-i18n (6ab21559db, 3e274a84e3):
- Add LanguageSelector component with dropdown to switch UI language
- Wire LanguageSelector into AccountMenu header
- Persist language preference to localStorage in i18n.ts
- Send Accept-Language header via useCustomApiHeaders (reactive via useTranslation)

No backend files included.

* [autofix.ci] apply automated fixes

* ci: add GP_TEST environment to gp-download and gp-upload workflows

* temp: add feature branch push trigger for workflow testing

* temp: trigger gp-upload workflow test

* fix: use correct GP_test environment name in workflows

* fix: use vars for GP_INSTANCE and GP_BUNDLE

* [autofix.ci] apply automated fixes

* fix: correct environment name to GP-test (hyphen not underscore)

* chore: update translations from Globalization Pipeline [skip ci]

* [autofix.ci] apply automated fixes

* chore: update translations from Globalization Pipeline [skip ci]

* temp: trigger gp-upload workflow test

* ci: add download-gp-bundle job to nightly build pipeline

Downloads frontend translations from Globalization Pipeline after
create-nightly-tag and before frontend tests run, ensuring tests
always validate the latest translated locale files.

- Frontend tests (Linux/Windows) now depend on download-gp-bundle
- Backend unit tests are unaffected (no frontend locale dependency)
- GP failure blocks release-nightly-build (same severity as linux tests)

* chore: remove temporary dev files from gp scripts directory

Remove BACKEND_STRINGS_STRATEGY.md (internal planning doc), test_auth.py
(GP auth debugging script), and en.json (dev-time string snapshot).
Also add venv/ to .gitignore to prevent accidental commits of the local virtualenv.

* [autofix.ci] apply automated fixes

* chore: update translations from Globalization Pipeline [skip ci]

* [autofix.ci] apply automated fixes

* chore: update translations from Globalization Pipeline [skip ci]

* feat(i18n): move language selector from account menu to Settings > General

- Add LanguageForm card component in GeneralPage following the existing
  Card pattern (ProfilePictureForm), with immediate language switching
- English marked as "(Recommended)" via i18n key
- Remove Language row from AccountMenu dropdown
- Add settings.languageTitle/Description/Recommended keys to en.json
  for upload to Globalization Pipeline

* feat(i18n): refactor language constants and improve GP pipeline

- Extract SUPPORTED_LANGUAGES into src/frontend/src/constants/languages.ts
- Update LanguageForm to import from shared constants, add aria-label
- Add settings.languageSelectAriaLabel key to en.json
- Update LanguageSelector component to use shared SUPPORTED_LANGUAGES
- Fix gp_client and download_translations scripts
- Update GP upload/download/nightly GitHub Actions workflows
- Add GP script tests

* [autofix.ci] apply automated fixes

* ci(gp): trigger upload on release branches, download via dispatch only

- Upload now triggers on push to release-* branches (instead of main)
  so translators get strings once they're finalized on the release branch
- Download removes the daily cron schedule; workflow_dispatch only
  since the nightly build already handles scheduled runs

* chore: update translations from Globalization Pipeline

* fix(i18n): address PR review comments — tests, nightly build decoupling, GP test workflow

- Add pytest tests for gp_client.py (HMAC auth, HTTP errors, timeout)
- Add pytest tests for upload_strings.py and download_translations.py
- Add conftest.py to set sys.path so GP scripts can be imported from repo root
- Add scripts/gp/__init__.py to make gp a proper package for test imports
- Add gp-test.yml workflow to run GP script tests on PRs touching scripts/gp/**
- Decouple download-gp-bundle from nightly build chain:
  - Add continue-on-error: true so GP failure never blocks the build
  - Remove download-gp-bundle from needs/if of frontend-tests-linux,
    frontend-tests-windows, and release-nightly-build
  - Add warning annotation step that fires on GP download failure

* feat(i18n): lazy-load non-English locale files via Vite dynamic imports

- Remove 6 static locale imports from i18n.ts; only en.json is bundled
- Export loadLanguage() which dynamically imports a locale chunk on demand
  and caches it via i18n.hasResourceBundle (no-op on repeat calls)
- Update index.tsx to await loadLanguage(detectedLang) before rendering,
  preventing an English flash for non-English users
- Make handleChange async in LanguageForm and LanguageSelector to await
  loadLanguage before calling i18n.changeLanguage
- Add i18n.test.ts covering loadLanguage: en no-op, new language load,
  cache hit, and multiple independent languages
- Update LanguageForm.test.tsx to mock @/i18n and assert loadLanguage
  is called before changeLanguage on language switch

* [autofix.ci] apply automated fixes

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

* fix: add ruff ignores for scripts/gp/tests

- Add per-file ignores for scripts/gp/tests/* to fix CI failures
- Ignore S101 (assert usage), TRY003, EM101 for test files
- Follows existing pattern for other test directories

* [autofix.ci] apply automated fixes

* fix(ci): run GP translation download before nightly tag creation

Previously download-gp-bundle ran after create-nightly-tag, so fresh
translations were committed to the branch after the tag was already
created. The nightly Docker image builds from the tag, meaning it never
included the day's translations.

Fix: move download-gp-bundle to run before create-nightly-tag so the
tag is created on a commit that already includes the latest translations.

* fix(ui): replace native select with Radix UI Select in LanguageForm

Swaps the native <select> element for the existing Radix UI Select
component to get consistent padding on both sides of the chevron,
removing reliance on browser-rendered chevron positioning.

* feat: backend i18n — serve translated component metadata via Accept-Language

- Add locale middleware (set_locale) in main.py to parse Accept-Language header
- Add translate_component_dict() in utils/i18n.py to substitute display_names
- Add backend locale files (en/fr/es/de/pt/ja/zh-Hans) with 4,748 keys
- Add GP scripts: extract_backend_strings.py, upload_backend_strings.py, download_backend_translations.py
- Add CI workflows: gp-backend-check.yml (PR validation + auto-commit), gp-backend-upload.yml (release branch upload)
- /api/v1/all returns translated component metadata for non-English locales

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

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

* refactor: simplify GP backend workflows to remove duplication

- gp-backend-check: drop redundant --check job, keep only auto-commit
- gp-backend-upload: remove extraction/commit steps, trigger on en.json
  path change, and add latest-release-branch guard (mirrors gp-upload.yml)

* feat: add nightly backend translation download job to gp-download workflow

Mirrors the existing frontend download job — resolves latest release branch,
runs download_backend_translations.py, and opens an auto-merge PR.

* [autofix.ci] apply automated fixes

* fix: skip backend translation download on nightly schedule

Backend download only runs on workflow_dispatch — the nightly cron is
for the frontend build pipeline only.

* fix: remove backend GP download from nightly build workflow

Backend translations are now downloaded via workflow_dispatch in
gp-download.yml, not as part of the nightly build pipeline.

* fix: remove frontend GP download from nightly build workflow

Frontend translations are now downloaded via nightly cron in
gp-download.yml, not as part of the nightly build pipeline.

* fix: remove en.json from check workflow trigger paths

The extraction script only reads from lfx.components — en.json is never
edited directly, so triggering on it was redundant and would silently
overwrite any intentional manual edits.

* fix: mock lfx.components in sys.modules for collect_strings test

The test was failing because collect_strings() imports lfx.components
before reaching the pkgutil/importlib mocks. Injecting fake modules into
sys.modules lets the import succeed so the mocks can take over.

* fix: resolve ruff violations in GP scripts and main.py

- Use .values() instead of .items() when attr_name is unused (B007/PERF102)
- Split long print f-string to stay under 120 chars (E501)
- Add blank line in docstring between summary and description (D205)
- Use ternary operator for locale assignment in main.py (SIM108)

* feat(i18n): sync canvas node translations on language change

Add syncNodeTranslations() to flowStore that patches translatable
metadata (display_name, description, template field display_names,
output display_names) on all canvas nodes when the types catalog is
refreshed with a new language. Field values are never touched. Nodes
whose type is absent from the catalog (custom-code, group nodes) are
skipped.

Called from two places to handle the race between flow loading and
types fetching:
- use-get-types.ts after setTypes(data) — covers the case where nodes
  are already on canvas when translations arrive
- resetFlow — covers the case where translations are already loaded
  when the flow mounts

* feat(i18n): translate Templates modal and starter flow metadata

## Backend

- Extend extraction script (`scripts/gp/extract_backend_strings.py`) to
  auto-discover all `initial_setup/starter_projects/*.json` files and emit
  `starter_flows.{safe_key}.name` / `starter_flows.{safe_key}.description`
  keys — no manual work needed when new starter flows are added.

- Add `translate_starter_flows()` to `utils/i18n.py`, mirroring the
  existing `translate_component_dict()` pattern. Derives a stable
  `name_key` (slug) from the English name and attaches it to each
  `FlowRead` so the frontend can match flows by identity regardless of
  locale.

- Update `FlowRead` model to expose `name_key: str | None`.

- Refactor `read_basic_examples()` endpoint (`api/v1/flows.py`):
  - Accept `Request` parameter to read `request.state.locale` (set by
    existing `set_locale` middleware).
  - Cache the raw `flow_reads` list instead of the compressed response so
    the same DB result can be translated per-request (cheap: ~33 dict
    lookups, no additional DB hit).
  - Call `translate_starter_flows()` on every request so `name_key` is
    always populated.

- Update all 7 backend locale files (en, fr, de, es, ja, pt, zh-Hans)
  with new `starter_flows.*` keys from GP.

## Frontend

- Templates modal (`modals/templatesModal/`):
  - Translate sidebar title, category group labels ("Use Cases",
    "Methodology"), and all nav item labels.
  - Translate "Get started" header and description.
  - Translate card category badges (PROMPTING, RAG, AGENTS).
  - Translate search placeholder and "No templates found" empty state.
  - Translate "Start from scratch" footer and "Blank Flow" button.
  - Use `flow.name_key` (stable slug) for example lookup in
    `GetStartedComponent` so matching is locale-independent.

- Refetch examples on language change: add `i18n.language` to the
  `useGetBasicExamplesQuery` cache key so React Query re-fetches
  translated flow data whenever the UI language switches.

- Add `name_key?: string | null` to `FlowType`.

- Empty state pages (`emptyPage`, `emptyFolder`): translate "Empty
  project", "Start building", description, and "New Flow" button.

- Update all 7 frontend locale files with new `templatesModal.*` and
  `emptyPage.*` keys from GP.

* [autofix.ci] apply automated fixes

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

* feat(i18n): translate MCP Server tab and fix sidebar category truncation

- Translate all strings in McpServerTab, McpFlowsSection, McpAuthSection:
  title, description, guide link, Flows/Tools label + tooltip, Edit Tools
  button, Auth label, None (public), Edit/Add Auth, Auto install tab,
  Loading state, config error messages
- Use stable id/label split for Auto install / JSON tabs so mode
  comparison is locale-independent
- Add truncate to sidebar category label span to prevent long translated
  names (e.g. French "Mannequins et agents") from wrapping to two lines
- Update all 7 frontend locale files with new mcp.* keys from GP

* feat(i18n): translate Knowledge, Files pages and fix sidebar overflow

- Translate Knowledge page (empty state, search, loading, alerts, chunks page)
- Translate My Files page (title, empty state, table columns, upload/delete)
- Fix sidebar category label overflow with min-w-0 truncate on flex spans
- Fix "Discover more components" button text truncation
- Fix empty page CTA button max-width for longer translations
- Remove duplicate language selector from account menu (browser auto-detection already in i18n.ts)
- Upload 471 strings to GP and download translations for fr/ja/es/de/pt/zh-Hans

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

* [autofix.ci] apply automated fixes

* feat(i18n): translate delete confirmation modal and fix CTA button overflow

- Translate DeleteConfirmationModal (title, body, buttons, "can't be undone")
- Translate flow/folder/component description labels via use-description-modal
- Translate "and its message history" and folder delete note at call sites
- Fix empty page CTA button overflow with whitespace-normal w-auto

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

* feat(i18n): translate Create Knowledge Base modal and flow dropdown menu

* [autofix.ci] apply automated fixes

* fix(i18n): use min-height for Knowledge Base modal to prevent scroll on translated text

* [autofix.ci] apply automated fixes

* feat(i18n): translate StepperModal footer buttons (Next Step, Back, Need Help?)

* feat(i18n): translate model input dropdown (No Models Enabled, Refresh List, Manage Model Providers)

* feat(i18n): translate Model Providers modal (config form, model selection, disconnect warning, multiselect placeholder)

* feat(i18n): translate starter template note/README nodes at serve-time

- Extend extract_backend_strings.py to extract noteNode descriptions as
  template_notes.{flow_key}.{index} keys (64 notes across 32 templates)
- Add translate_flow_notes() to i18n.py to substitute translated markdown
  per-request without mutating the cached template data
- Wire translate_flow_notes() into the /starter-projects/ endpoint using
  the same request.state.locale pattern as the flows endpoint
- Update all 6 backend locale files via GP pipeline (4858 keys total)

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

* feat(i18n): translate canvas note nodes on language change via dedicated endpoint

- Add stamp_note_keys() to i18n.py: stamps i18n_key onto noteNodes of
  starter templates when a user copy is created, enabling stable lookup
- Call stamp_note_keys() in _new_flow() (flows_helpers.py) so keys are
  persisted to DB at copy-creation time
- Add GET /flows/{flow_id}/note_translations endpoint returning
  { node_id: translated_text } for the request locale; falls back to
  positional recompute for flows without stamped keys
- Add useGetNoteTranslationsQuery (React Query) keyed on [flowId, language]
  so it auto-refetches on language change without explicit invalidation
- Apply translations in NoteNode via useEffect on query data
- Rewrite syncNoteTranslations to accept Record<string, string> (node_id map)
- Remove old syncNoteTranslations(FlowType[]) approach and all debug
  console.warn/console.error [i18n-debug] statements
- Suppress i18next Locize promotional console.info by temporarily replacing
  console.info around the synchronous init() call
- Add i18n_key?: string to noteClassType frontend type

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

* feat(i18n): fix Playground/Share button overlap and translate Share button

- Remove fixed w-[7.2rem] from SimpleSidebarTrigger and DisabledButton so
  the Playground button grows to fit translated text in any language
- Add misc.share i18n key and replace hardcoded "Share" string in
  deploy-dropdown with t("misc.share")
- Download GP translations for de/pt/zh-Hans

* feat(i18n): translate input placeholder and info fields for backend components

Extend the backend i18n pipeline to cover placeholder and info (tooltip)
text in addition to display_name and description:

- extract_backend_strings.py: extract placeholder from input fields
- i18n.py (translate_component_dict): translate placeholder and info at
  request time alongside display_name
- Regenerate en.json (6700 keys, +179 placeholders, +info keys)
- Download translated locale files for de, es, fr, ja, pt, zh-Hans

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

* feat(i18n): translate Share dropdown items (API access, Export, MCP Server, Embed, Shareable Playground)

* fix(i18n): stamp i18n_key in translate_flow_notes and remove dead stamp_note_keys

- Stamp i18n_key onto noteNodes inside translate_flow_notes() using the
  original English name_key so the key travels with the node when a user
  copies a template — fixes translation failure for duplicate copies like
  "Simple Agent (2)" where the frontend sends the translated name
- Remove stamp_note_keys() and its call in _new_flow(): now a no-op since
  i18n_key is always stamped by translate_flow_notes at /basic_examples/
- Remove positional fallback from get_note_translations: only use stamped
  i18n_key; drop unused _safe_flow_key import and note_index counter
- Fix read_basic_examples to pass name_key (original English) instead of
  the already-translated flow.name to translate_flow_notes

* refactor(i18n): bake i18n_key into template noteNodes, remove runtime stamping

Replaces fragile positional indexing with keys baked directly into the source
JSON files, so keys are stable regardless of node order changes.

- scripts/gp/bake_note_keys.py: new script that stamps template_notes.{flow}.{n}
  onto each noteNode missing an i18n_key; idempotent and --dry-run safe
- scripts/gp/extract_backend_strings.py: Tier 4 reads i18n_key from node data
  instead of positional index; warns if any noteNode is missing a key
- utils/i18n.py: translate_flow_notes() simplified — reads baked key, translates,
  no more flow_name param or index counter or stamping logic
- api/v1/flows.py, starter_projects.py: drop flow_name arg from call sites
- test_i18n_note_translation.py: tests updated for key-read behavior
- starter_projects/*.json: 64 noteNodes across 32 templates stamped with i18n_key

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

* ci(i18n): auto-bake note keys on template JSON changes in CI

Extends gp-backend-check.yml to trigger on starter_projects/** changes
and runs bake_note_keys.py before extract_backend_strings.py so any new
noteNodes get i18n_key stamped automatically on PR branches.

* refactor(i18n): replace index-based note keys with content-hash keys

bake_note_keys.py now derives i18n_key from sha256[:8] of the
noteNode description instead of a positional counter. Keys are
stable on reorder, auto-rotate when content changes, and never
silently reuse an old index after a note is deleted.

All 64 note keys across 32 starter templates restamped to the
new template_notes.{flow_key}.{hash8} format. Script is idempotent —
running twice on unchanged content produces no changes.

* fix(i18n): thread-safe translation loading and correct falsy key check

- _load_translations(): add double-checked locking with threading.Lock to
  prevent race condition under concurrent requests at cold start
- translate(): use `is not None` instead of truthiness check so empty-string
  translations are not silently dropped in favour of the fallback chain

* feat(i18n): translate Settings page UI strings across multiple sections

- Profile picture chooser: translate People/Space category labels
- MCP Servers page: translate title, description, button, status labels, dropdown items, and all Add MCP Server modal strings
- API Keys page: translate column headers (Name, Key, Created, Last Used, Total Uses) and Create API Key dialog (title, description, labels, buttons, generated key message)
- Shortcuts page: translate all 27 shortcut display names via valueFormatter
- Messages page: translate title and description
- Base modal: translate shared Cancel button

* fix(i18n): replace fixed card heights with min-h to prevent layout issues with longer translations

Cards with h-[84px] would overflow/misalign when translated text wrapped to
multiple lines. Using min-h-[84px] keeps the minimum size while allowing
cards to grow naturally for longer translations.

* feat(i18n): translate SaveChangesModal (unsaved changes popup)

Translates all strings in the unsaved-changes dialog shown when
navigating away from a flow with pending changes:
- title, saving spinner, last saved, exit/save buttons
- unsaved changes warning and auto-saving help link

* chore(i18n): download updated frontend and backend translations from GP

Frontend: 704 strings across fr, ja, es, de, pt, zh-Hans
Backend: updated note keys (hash-based) across fr, ja, es, de, pt, zh-Hans

* feat(i18n): translate ToolsModal (URL/tools selection popup)

Translates all strings in the tools modal including:
- search placeholder, column headers (Name, Description, Slug/Tool)
- sidebar labels, input placeholders, hint text
- Parameters section title and subtitle
- Close button

* chore(i18n): download updated frontend translations from GP

724 strings across fr, ja, es, de, pt, zh-Hans including new
toolsModal and saveChangesModal keys.

* feat(i18n): translate MCP Client settings page, shareable playground label, and Global Variable modal

- McpClientPage: add useTranslation, move all hardcoded strings (title,
  description, steps, config file label, API key notice) to
  settings.mcpClient.* keys
- deploy-dropdown: fix unpublished "Shareable Playground" label that was
  missed when the published branch already used t()
- GlobalVariableModal: add useTranslation, translate all UI strings
  (title, description, type/name/value/fields labels & placeholders,
  save/update button, success and error toasts)
- en.json: add 13 settings.mcpClient.* keys and 23 globalVars.modal.* keys
- All locale files (de, es, fr, ja, pt, zh-Hans) updated from GP

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

* feat(i18n): translate MCP Server Auth modal (authModal)

- Add useTranslation to authModal/index.tsx
- Translate all hardcoded strings: title, auth type label, radio labels
  (None/API Key/OAuth), no-auth warning, API Key description, OAuth
  field labels/placeholders, Save button, reinstall warning (with and
  without installed clients interpolation)
- Add 30 authModal.* keys to en.json
- Update all locale files (de, es, fr, ja, pt, zh-Hans) from GP (776 strings)

* feat: add translation keys for MCP JSON configuration

* feat(i18n): translate project delete notification, MCP install notification, and McpJsonContent

- main-page.tsx: translate "Project deleted successfully" and "Error
  deleting project" success/error toasts
- useMcpServer.ts: translate "MCP Server installed successfully on
  {{client}}..." success toast using i18n.t()
- McpJsonContent.tsx: translate "Add this config..." hint, Transport
  label, and Generate/API key generated button labels
- Add 3 new keys (mcp.installedSuccessfully, project.deletedSuccessfully,
  project.errorDeleting) + 5 mcpJson.* keys to en.json
- Update locale files from GP

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

* feat(i18n): translate default flow/project names and delete notifications

- reactflowUtils.ts: use i18n.t("flow.defaultName") for new flow default name
- use-add-flow.ts: use t() for "Starter Project" and "New Project" names at creation time
- sideBarFolderButtons: use t("project.newName") when creating a new project
- main-page.tsx: translate project deleted success/error toasts
- useMcpServer.ts: translate MCP install success toast
- list/index.tsx: translate flow deleted success/error toasts
- Add keys: flow.defaultName, project.newName, project.starterName,
  project.deletedSuccessfully, project.errorDeleting,
  flow.deletedSuccessfully, flow.errorDeleting, flow.errorDeletingRetry,
  mcp.installedSuccessfully
- Update all locale files from GP (790 strings)

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

* refactor(i18n): content-hash component keys and normalize frontend lookup

Backend locale keys for components now use a hybrid format:
  components.{norm_name}.{field_path}.{sha256[:8]}
e.g. components.prompttemplate.display_name.8cd80ebe

The 8-char hash suffix is derived from the English source value, so any
change to a component string produces a new key, forcing GP to issue a
fresh translation. The human-readable prefix keeps keys debuggable.

Component names are normalized (spaces removed, lowercased) in both the
key prefix and the runtime hash computation, so renames like
"PromptTemplate" → "Prompt Template" don't break existing translations.

Frontend syncNodeTranslations() now builds a normalized lookup map so
that nodes stored with old-style type names (e.g. "PromptTemplate") are
correctly resolved against the live registry key ("Prompt Template"),
fixing untranslated Prompt Template nodes in starter template flows.

Also adds chunked uploading to upload_backend_strings.py to avoid
read timeouts when pushing large payloads to GP.

* feat(i18n): fix legacy component alias translation and translate file manager UI

Frontend:
- syncNodeTranslations() now falls back to templates store to resolve legacy
  node.data.type aliases (e.g. "Prompt" → Prompt Template, "parser" →
  ParserComponent), fixing untranslated nodes in starter templates like
  Vector Store RAG
- Translate "Flow saved successfully!" toast in FlowPage
- Translate file manager modal: "Select files" button, error/success toasts,
  drag-and-drop zone labels, folder selection strings (13 new keys)

Backend:
- check_backend_status.py: new script to check GP translation progress
- upload_backend_strings.py: single PUT with 5min timeout, bundle name logged
- download_backend_translations.py: bundle name logged on start
- All locale files updated with latest GP translations (langflow-ui-backend-v2)

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

* feat(i18n): translate canvas controls and Model Providers page strings

- Add useTranslation to MemoizedCanvasControls for Flow Locked, Agent Working, Saving, Lock/Unlock flow labels
- Add useTranslation to CanvasControlsDropdown for Zoom In/Out/To 100%/To Fit and tooltips
- Add useTranslation to ModelProvidersPage for page title and description
- Add canvas.* and modelProviders.page* keys to en.json
- Sync all locale files (fr, ja, es, de, pt, zh-Hans) via GP pipeline

* feat(i18n): translate upload folder button and model trigger strings

- UploadFolderButton: replace hardcoded "Upload a flow" tooltip with t("folder.uploadFlow")
- ModelTrigger: replace hardcoded "No models enabled" and "Select a model" with t() calls

* feat(i18n): cache /basic_examples/ translations per locale

Add _starter_flows_translated_cache keyed by locale so translate_starter_flows
and translate_flow_notes run at most once per locale per 5 minutes instead of
on every request.

* feat(i18n): translate NoteNode empty placeholder text

* feat(i18n): translate slider labels, model trigger, dropdown loading, and loading component

- Translate Precise/Balanced/Creative/Wild slider labels and min/max labels
- Translate "Setup Provider" placeholder in ModelTrigger
- Translate "Loading options" in dropdownComponent (both occurrences)
- Translate "Loading..." in loadingComponent (used by LoadingPage)
- Add syncNodeTranslations() call after model refresh to re-apply translations
- Add 8 new keys to en.json and download translated locale files

* feat(i18n): translate model provider toast notifications

Replace hardcoded English strings in useProviderConfiguration with t()
calls: configuration saved, activated, disconnected success toasts, and
all error titles/messages for save, activate, disconnect, and model
toggle operations.

* fix(i18n): address PR review — DRY key functions, locale allow-list, dead code, silent failures

- Extract safe_flow_key/normalize_component_key/content_hash/component_field_key into
  langflow/utils/i18n_keys.py so runtime translator and extract script share one
  source of truth (C1)
- Validate Accept-Language against supported locales in set_locale middleware;
  unknown values fall back to "en" to prevent cache pollution (C2)
- Delete dead `remaining = ...` block in check_backend_status.py that made a
  redundant network call and never used the result (I2)
- Log logger.warning instead of silently swallowing OSError/JSONDecodeError in
  _load_translations (I3)
- Rename test_strips_dedup_suffix → test_parentheses_in_name_become_underscores
  with corrected comment (I5)
- Remove redundant `import copy as _copy` inside translate_flow_notes (R2)
- Move translate_flow_notes/translate_starter_flows import to flows.py module top (R1)
- Add # Why: comments on max_size=16, uncompressed cache, and verify=False (R5/I8/M3)
- Wrap loadLanguage dynamic import in try/catch so unknown locales don't crash
  React with an unhandled rejection; add i18n.test.ts to cover the fallback

* refactor(gp): consolidate upload/download scripts with --target flag

Replaces four separate scripts (upload_strings, upload_backend_strings,
download_translations, download_backend_translations) with two unified
entry points: upload.py and download.py, each taking --target frontend|backend.

Updates gp-upload.yml to a single workflow with two jobs, updates
gp-download.yml run lines, and removes the now-redundant
gp-backend-upload.yml workflow.

* [autofix.ci] apply automated fixes

* chore(starter-projects): sync starter project snapshots with release-1.10.0

Updates dependency versions (langchain_core 1.2.29 → 1.2.27) and minor
JSON formatting differences across 21 starter project files following
merge from release-1.10.0.

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

* feat(i18n): restore LanguageForm component in Settings > General page

* [autofix.ci] apply automated fixes

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

* fix(projects): always use English for new project names

Translated project names (e.g. Japanese '新規プロジェクト') caused MCP
server name collisions because sanitize_mcp_name() strips non-ASCII
chars and all names fell back to 'lf-unnamed'. Hardcode 'New Project'
and 'Starter Project' instead of passing them through t() so the
names sent to the backend are always ASCII.

* chore(i18n): download missing Vector Store RAG note translations

README and Load Data Flow note keys were missing from all non-English
locales. Uploaded to GP and downloaded translations for fr, ja, es,
de, pt, zh-Hans.

* [autofix.ci] apply automated fixes

* fix(canvas): fix zoom dropdown shortcut layout on Windows

The shortcut container had a fixed w-[25px] which fits the single-char
Mac modifier key (⌘) but clips the 4-char Windows modifier key (Ctrl).
Remove the fixed width and use gap-0.5 so the container sizes to its
content on all platforms.

* fix(i18n): sync tooltip info and placeholder fields for existing canvas nodes

syncNodeTranslations() was only updating display_name from fresh component
definitions, leaving baked-in English info (tooltip) and placeholder strings
on nodes loaded from saved flows and starter templates. Extend the merge to
also overlay info and placeholder for template fields, and info for output
fields. Also adds info?: string to OutputFieldType to match what the backend
already sends.

* fix(i18n): persist language selection across page refreshes

loadLanguage() was only adding the resource bundle but never calling
i18n.changeLanguage(), so the active language stayed "en" on every page
load even when a preference was saved in localStorage. Move the
changeLanguage() call into loadLanguage() so both startup (index.tsx)
and runtime language switches activate the language after loading the bundle.

* fix(sidebar): add tooltip to truncated category header labels

Category headers use truncate but had no tooltip, making long translated
names (e.g. French) unreadable. Wrap the label span with ShadTooltip
matching the pattern used by sidebar draggable items.

* fix(sidebar): add tooltip to truncated discover more components button

* fix(sidebar): add tooltips to footer buttons (new custom component, MCP)

* fix(login): center-align title to handle wrapped translations gracefully

* fix(signup): center-align title to handle wrapped translations gracefully

* fix: remove tooltips from form field labels and add tooltip to sign-in button for consistency

* [autofix.ci] apply automated fixes

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

* [autofix.ci] apply automated fixes

* fix: resolve ruff violations in gp scripts and i18n util

- FBT001: make dry_run keyword-only in bake_note_keys._bake_file
- S112: add S112 to noqa comments in extract_backend_strings.py
- PLW2901: rename shadowed loop variable in i18n.translate_note_nodes

* [autofix.ci] apply automated fixes

* fix: lazy-import langflow in extract_backend_strings to fix GP test collection

The top-level `from langflow.utils.i18n_keys import ...` caused an
ImportError in CI where the GP test job runs without langflow installed.
Move the imports inside collect_strings() so the module is importable
without langflow — all tests mock collect_strings anyway.

* fix(tests): mock langflow.utils.i18n_keys in test_collect_strings_skips_deactivated_modules

The test calls collect_strings() directly, which now lazy-imports
langflow.utils.i18n_keys. Patch a minimal fake module into sys.modules
so the test runs without langflow installed. Also fix the key assertion
to match the lowercased output of normalize_component_key.

* fix(frontend): restore missing modal height constant imports in KnowledgeBaseUploadModal

The i18n commit (bd070cab63) accidentally dropped MODAL_HEIGHT_DEFAULT,
MODAL_HEIGHT_WITH_ADVANCED, and VALIDATION_ERROR_LINE_HEIGHT from the
constants import when refactoring STEP_TITLES/STEP_DESCRIPTIONS, causing
a ReferenceError at runtime and failing all 39 Jest tests.

* [autofix.ci] apply automated fixes

* fix(tests): add global mocks for ShadTooltip and useGetNoteTranslationsQuery

- Mock shadTooltipComponent to render children only — avoids needing
  TooltipProvider in sidebar unit tests
- Mock useGetNoteTranslationsQuery to return empty data — avoids needing
  QueryClientProvider in NoteNode unit tests
- Fix t() interpolation mock to resolve {{count}} in KnowledgeBasesTab tests

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

* fix(tests): add syncNodeTranslations no-op mock to flowStore in affected tests

* [autofix.ci] apply automated fixes

* fix(tests): use stable testId selector instead of node title text in Blog Writer spec

* fix(i18n): preserve instance-level node display_name and description in syncNodeTranslations

Only sync field-level translations (template inputs and outputs).
Node titles and descriptions are instance-level identity — user and
template renames must not be overwritten by canonical registry values.

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

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 13:43:21 +00:00
760da3889b feat: Clear all traces for flow (#12354)
feat: add useDeleteTracesMutation for deleting traces and integrate into FlowInsightsContent
- Introduced a new mutation hook `useDeleteTracesMutation` for deleting traces via API.
- Updated `FlowInsightsContent` to include a button for clearing all records with confirmation dialog.
- Integrated success and error alerts for delete operations.
2026-04-29 13:27:05 +00:00
af8cd0219e fix: pass Google embedding dimensions (#12876)
fix: pass google embedding dimensions
2026-04-28 23:02:33 +00:00
9514c9dc06 feat(deployments): add agent name validation during deployment creation (#12858)
* feat(deployments): add agent name validation during deployment creation

This commit introduces a new `names` query parameter to the `GET /deployments` endpoint to filter deployments by name, and leverages it in the frontend to enforce agent name uniqueness before creation.

Backend:
- **API**: Added `names` list query parameter to `GET /deployments`.
- **CRUD**: Updated `list_deployments_page` and `count_deployments_by_provider` to support `names` SQL `IN` filtering.
- **Mappers & Services**: Plumbed the `names` filter through the deployment mappers to `DeploymentListParams` (as `deployment_names`) and forwarded it to the Watsonx Orchestrate adapter `list` API.
- **LFX Schema**: Introduced `NormalizedStr` type and added `deployment_names` to `DeploymentListParams` with empty-string rejection.
- **Tests**: Added comprehensive unit and integration tests across CRUD, route handlers, mappers, and the Watsonx Orchestrate service to ensure the name filter behaves correctly in both DB mode and provider mode.

Frontend:
- **API Hooks**: Created the `useCheckAgentNames` hook which concurrently queries the deployments endpoint (with both `load_from_provider=false` and `load_from_provider=true`) and gracefully combines the results from both the DB and the provider.
- **UI**: Integrated a 500ms debounced agent name validation into the `StepType` component inside the deployment stepper context. It now displays a loading spinner during checks, renders an error message if the name is taken, and blocks the user from proceeding.
- **Tests**: Updated `step-type.test.tsx` for the new validation logic and added an E2E Playwright test in `deployments-page.spec.ts` to verify that the `names` query parameter is correctly constructed and passed.

* remove reference to dead unreference DeploymentListParams

* remove filter params dead code for slots/validation

* add some tests for config/snapshot list params

* fix(deployments): fail fast on invalid wxO list-filter names
resolve_deployment_list_adapter_params and resolve_snapshot_list_adapter_params
in the wxO mapper used to normalize input names and silently drop entries that
sanitised to empty (e.g. "!!!"). When every entry reduced this way, the base
resolver treated `names or None` as no filter at all and returned every
deployment/snapshot — the opposite of what the caller asked for.
Replace that silent path with a small `_validate_name_filter` helper that
delegates to validate_wxo_name (re-using the existing rules instead of
duplicating them) and re-raises its InvalidContentError as HTTPException(422)
with the resource label ("deployment"/"snapshot") and the offending value,
mirroring `_validate_tool_name` already in the same file. Valid-but-unsanitised
inputs ("My Agent" -> "My_Agent") still normalise correctly for matching;
names=None still short-circuits to no filter.
Add focused tests for both resolvers: normalization, None passthrough, 422
on invalid names with the resource label and offending value in the detail,
and fail-fast on the first invalid in a mixed list.
Also fix test_list_deployments_with_names_filter, whose fake agent fixture
was missing the "environments" key that wxO always returns for agents.
The adapter's get_agent_environments is intentionally strict per its
docstring, and adjacent tests already use the canonical shape.

* fix(deployments): validate agent names

* test(deployments): fix create-mode fixtures

* remove unused db from mapper signature

* more explicit docs

* test(deployments): fix names filter request check

* fix tests

* fix test signatures for list_deployments_synced

* fix test for notimplementederror

---------

Co-authored-by: Viktor Avelino <viktor.avelino@gmail.com>
2026-04-28 22:00:54 +00:00
d1b73e9f18 fix(mcp): render connection handles for non-string MCP tool inputs (#12782)
* fix(mcp): render connection handles for non-string MCP tool inputs

MCP Tool components only exposed connectable input ports for string fields.
Number (int/float), boolean, and data/JSON fields rendered as UI-only widgets
with no handle, so upstream components could not be wired in.

The frontend's computeDisplayHandle hides the port for types in
LANGFLOW_SUPPORTED_TYPES unless input_types is non-empty, but
schema_to_langflow_inputs created IntInput/FloatInput/BoolInput/DictInput
without setting input_types. Add a class -> input_types map
(Message for numerics/bool, Data for dicts) and apply it in the schema
conversion.

To make the newly-connectable handles work at runtime, extend BoolInput and
DictInput with validators that coerce incoming Message/Data payloads
(IntInput, FloatInput and NestedDictInput already did this).

Fixes #9424

* fix: Expected input types for Dict and NestedDict
2026-04-28 22:00:53 +00:00
f7d63d081d fix: Add microseconds support for PostgreSQL data store (#9941)
* Add microseconds support for PostgreSQL data store

* Fix UT + Pydantic model

* Extract TZ's as contants

* Return TS in str from serialize_timestamp, because microseconds may be lost on Pydantic conversion (str type)

* Fix inconsistent err message

* Fix UT test_timestamp_serialization

* Reuse timestamp_to_str method

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* Code review fixes

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

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

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

* fix: address CR feedback on timestamp microsecond support

Fix all critical and minor issues raised in code review:

- timestamp_to_str in lfx: datetime path was missing .%f, dropping
  microseconds entirely (two messages per second got identical timestamps)
- str_to_timestamp in both modules: replace single strptime with a loop
  over all TIMESTAMP_FORMATS restoring backward compat with old strings
  without microseconds ("2024-06-15 10:30:00 UTC")
- .replace(tzinfo=utc) → .astimezone(utc) for formats with numeric tz
  offsets, fixing silent time corruption for non-UTC users
- TF_WITH_TZ_AND_MICROSECONDS_ISO: was a duplicate of
  TF_WITH_TZ_AND_MICROSECONDS; changed to "%Y-%m-%dT%H:%M:%S.%f%z"
- encoders.py encode_datetime: add .%f so output is parseable by
  the validator chain
- playground_events.py PlaygroundEvent and TokenEvent default_factory:
  add .%f to timestamp format strings
- model.py: fix comment .FFFF → .ffffff; use astimezone in fromisoformat
  fallback when parsed datetime carries a tz offset
- Add 35 unit tests covering microsecond preservation, correct UTC
  conversion for non-UTC offsets, roundtrip losslessness, sub-second
  ordering, backward compat and encoder output parseability

* Add `order` parameter to `get_messages` and `aget_messages` tests

* Refactor: use `str_to_timestamp` and `timestamp_to_str` for timestamp parsing in message endpoint tests

* [autofix.ci] apply automated fixes

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

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

* Fix encode_datetime precision

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: ogabrielluiz <gabriel@langflow.org>
Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@logspace.ai>
2026-04-28 21:01:41 +00:00
9dcdc704ec docs: change upgrade reinstall order (#12911)
* docs-change-upgrade-reinstall-order

* docs-make-langflow-oss-version-section
2026-04-28 20:23:02 +00:00
c8abc0ed7f fix(composio): prevent KeyError('type') on Gmail/Calendar tool execution (#12905)
* fix(composio): prevent KeyError('type') on Gmail/Calendar tool execution

Composio==0.9.2 raw-subscripts properties[name]["type"] inside its file
substitution helpers (composio.core.models._files lines 235/308) and its
Pydantic schema builder (composio.utils.shared.pydantic_model_from_param_schema
line 232). When a tool's input_parameters schema has any property without an
explicit JSON Schema "type" key — common for Gmail/Calendar actions whose
properties only specify anyOf/$ref/additionalProperties — the call raises
KeyError('type').

Reproduction: drag the Gmail (or Google Calendar) component, paste a Composio
API key, "Check all" actions, wire to Agent, then ask a question in Playground.
The agent invokes a tool such as GMAIL_FETCH_EMAILS, Composio fails inside
substitute_file_uploads/substitute_file_downloads, and the chat surfaces
"KeyError Details: type".

Fix lives entirely on the Langflow side (no upstream wait):
- New SafeLangchainProvider subclass of composio_langchain.LangchainProvider
  whose wrap_tool sanitizes tool.input_parameters before delegating, so
  composio's downstream raw subscripts always succeed.
- Module-level monkey-patch on FileHelper._substitute_file_{uploads,downloads}
  _recursively that calls _sanitize_schema first, covering the direct
  execute_action path (which bypasses wrap_tool) as well as the agent path.
- ComposioBaseComponent.configure_tools also sanitizes the deep-copied schemas
  cached in composio.tools._tool_schemas, since that cache is taken before
  process_schema_recursively rewrites tool.input_parameters.
- _sanitize_schema infers "object" when properties exist, "array" when items
  exist, and otherwise defaults to "string" — guaranteed never to overwrite an
  existing type. Conservative defaults keep the file-substitution branch a
  no-op for non-object schemas.

Tests: 12 new unit tests in
src/backend/tests/unit/components/bundles/composio/test_safe_provider.py
covering every sanitize branch (object/array/anyOf/$ref/$defs/non-dict),
provider instantiation, the FileHelper monkey-patch flag, and an end-to-end
guard that drives composio's actual upload walker against a typeless schema.
Verified live in Playground: GMAIL_FETCH_EMAILS, GOOGLECALENDAR_EVENTS_LIST,
GOOGLECALENDAR_CREATE_EVENT and friends now execute end-to-end and return data
instead of raising.

Fixes #12894
Fixes #12895

* [autofix.ci] apply automated fixes

* fix(composio): harden safe_provider against missing extra and sig drift

- Wrap composio imports in try/except so bare langflow installs without the
  composio extra don't crash at module load time.
- Make safe_uploads/safe_downloads kw-only so future positional reorder in
  composio.core.models._files fails loud instead of silently swapping args.
- Document global side effect of FileHelper monkey-patch in docstring.

* fix(composio): patch pydantic builder + widen monkey-patch sigs

Adds _patch_pydantic_builder_once wrapping
composio.utils.shared.pydantic_model_from_param_schema, the third
KeyError('type') site reachable from the legacy tools.get path that
bypasses configure_tools' cached-schema sanitizer.

Widens safe_uploads/safe_downloads wrappers to *args/**kwargs via a
shared _extract_schema_arg helper so the patch survives an upstream
switch from keyword to positional invocation.

Adds 5 tests: positional-arg forward-compat, pydantic builder patched
+ no-KeyError, and two no-op regression-preservation guards asserting
fully-typed schemas round-trip unchanged.

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-04-28 19:56:13 +00:00
4dfe24ab20 ci: unblock community PRs from spurious CI failures (#12916)
Three failures consistently flip community/fork PRs red even when every
substantive check passes (observed on PR #9941):

- Update Component Index: actions/checkout was given only the head ref,
  defaulting the repository to the upstream where the fork branch does
  not exist. Pass head.repo.full_name + head.ref so the head can be
  checked out from the fork. Continue using the pull_request trigger so
  fork code never runs in a privileged context.

- Merge Frontend Jest + Playwright Coverage Reports: codecov-action ran
  with fail_ci_if_error: true and an empty token (forks can't read repo
  secrets), turning a reporting step into a hard merge blocker. Skip the
  upload when CODECOV_TOKEN is unavailable and match the python coverage
  job's fail_ci_if_error: false.

- CI Success: roll-up gate cascading from the two above; clears
  automatically once they pass.
2026-04-28 19:53:42 +00:00
3aaee0f8a6 feat: add envs to deployment list response for wxo agents (#12881)
* feat: and envs to deployment list response for wxo agents

* remove redunant normalization

* add blank lines for readability

* tighten up schema and mapper base class and tests

* fix tests
2026-04-28 19:26:38 +00:00
3f2d2fc399 fix: lfx env var resolution when value is empty (#12907)
* fix(lfx): allow env-var fallback when user_id is None

get_api_key_for_provider short-circuited to None whenever user_id was
None, making the os.getenv(variable_name) fallback at the bottom of the
function unreachable. lfx run has no concept of user_id, so any flow
exported with an empty credential field (the typical case after a
re-export) failed with 'API key is required' even when the canonical
env var was set in the shell.

Restructured to: try the database-backed variable service only when a
user_id is available, then always fall through to os.getenv. The
shell-exported credential is now picked up regardless of whether a
user is present.

* ruff
:
g
2026-04-28 14:57:05 +00:00
7d4d3e13a3 chore: bump versions to 1.9.2 (#12898) 2026-04-28 14:53:35 +00:00
a46ae46f9f feat: Add an Astra DB Data API Component (#12766)
* feat: Add an Astra DB Data API Component

* Run pre-commit hooks to format

* Update astradb_data_api.py

* Update component index

* Merge branch 'release-1.10.0' into feat/astra-db-data-api-component

* Updates

* Update component_index.json

* Update component_index.json
2026-04-27 19:02:40 -07: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
2860e0e591 fix(frontend): validate deployment agent name (#12896) 2026-04-27 19:19:14 +00:00
276d16b2be chore(frontend): remove stale Dockerfile and start-nginx script (#12795)
These files were superseded by docker/frontend/ in Dec 2024 but left in
place. They still use the pre-openshift sed -i entrypoint that breaks
under readOnlyRootFilesystem, so any local build from this Dockerfile
produces a broken image. Nothing in CI, Makefile, or build tooling
references them.
2026-04-27 19:07:16 +00:00
5d947b11c7 feat: Add Memory Base APIs models migrations service endpoints and tests (#12417)
* Add Memory Base API: models, migrations, service, endpoints, and tests

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

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

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

Add dedupe_key idempotency enforcement for MB ingestion jobs

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

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

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

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

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

Added unit tests, fixed linting issues and formatting issues.

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

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

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

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

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

* [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>
Co-authored-by: Eric Hare <ericrhare@gmail.com>
2026-04-27 11:30:18 -07:00
2f51b7eccd fix(tests): Restore Windows-compatible slider Playwright test (#12904)
* fix slider test on windows

* add fallback slider test

* fix e2e slider test

* fix query input on windows

* fix win aces event

* fix slider test playwright

* change input read approach
2026-04-27 17:58:10 +00:00
1e9a96f5b9 docs: include host field for external db in Helm chart (#12899)
docs-include-host-value-for-external-db
2026-04-27 17:16:56 +00:00
e277b4b1cb fix: migrate orphaned MCP servers config across DB resets (#12762)
* fix: migrate orphaned MCP servers config across DB resets

When Langflow restarts with a fresh database but the same LANGFLOW_CONFIG_DIR
(common in containerized deployments without a persisted DB volume), the
default superuser is recreated with a new UUID and the previously saved
_mcp_servers_{old_uuid}.json files become unreachable.

On default-superuser creation in AUTO_LOGIN mode, scan the config directory
for orphaned _mcp_servers_*.json files under prior UUID folders and migrate
the most recently modified one to the new user (copy contents + register a
UserFile row). Never overwrites an existing file and is a no-op when no
orphan is found; failures are swallowed so migration cannot block startup.

Fixes langflow-ai/langflow#9524

* fix: address review feedback on MCP orphan migration

- Refuse to migrate when multiple orphan candidates are present. MCP server
  entries can contain env/headers auth material, so silently picking the
  newest orphan could import an unrelated user's config. Operators get a
  warning with candidate paths for manual recovery.
- Self-heal missing DB rows when the current user's MCP config file already
  exists on disk (e.g. from a previous migration that crashed before commit)
  instead of returning early and leaving the config invisible.
- Add regression tests for the multi-orphan skip path, self-heal path, and
  "DB row already present" short-circuit.
2026-04-27 16:35:58 +00:00
d8bad2c1db fix(chroma): replace deprecated Client(settings=) with HttpClient for chromadb >=1.0 (#12900)
* fix(chroma): replace deprecated Client(settings=) with HttpClient for chromadb >=1.0

On chromadb 1.0+, `chromadb.Client(settings=Settings(chroma_server_host=...))`
silently creates a local in-memory ephemeral database instead of connecting to
the configured remote server. This caused the Chroma DB component to always
return empty results (`dataframe: []`) when pointing at a remote ChromaDB server.

Replace the deprecated `Client(settings=...)` call with `chromadb.HttpClient()`
which is the correct API for connecting to a remote ChromaDB HTTP server.

Also update component_index.json with the fixed component code and recomputed sha256.

Fixes #12665

Co-Authored-By: Octopus <liyuan851277048@icloud.com>

* Update component_index.json

* Update test_chroma_vector_store_component.py

* [autofix.ci] apply automated fixes

---------

Co-authored-by: octo-patch <octo-patch@github.com>
Co-authored-by: Octopus <liyuan851277048@icloud.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-04-27 09:29:22 -07:00
7860e2a1d8 feat: refresh deployed success step (#12853)
* feat(deploy): refresh deployed success step

* refactor(deploy): split modal sections

* test(deploy): cover success step

* fix(deploy): rename flows step copy

* fix(tests): update deployment test selectors for renamed step heading

Tests were failing because the UI step heading changed from "Attach Flows"
to "Flows". Updated three test files to use the new selector text.

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

* test(deployments): fix stepper e2e selectors

---------

Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-04-27 14:45:57 +00:00
8b83cf686c feat: disable frontend retries for client errors (#12890)
* checkout fe disable retries files from fe-retries branch

* refactor(frontend): tighten retry helpers and broaden their tests
Address review feedback on the retry rework in UseRequestProcessor:
- Use axios.isAxiosError as a type guard instead of an `as AxiosError`
  cast, so non-axios errors (TypeErrors thrown by queryFn, etc.) are
  classified by structure rather than by an unsafe shape assertion.
- Hoist makeRetry(5) / makeRetry(3) to module scope as queryRetry /
  mutationRetry. They're pure factories and don't need to be rebuilt on
  every render of the hook; matches how retryDelay was already scoped.
- Honor a caller-provided options.retryDelay on the mutate path
  (`options.retryDelay ?? retryDelay`). Previously the explicit
  retryDelay was set after `...options`, silently clobbering any
  override — inconsistent with the query path where `...options` wins.
Tests:
- Rename capture vars to mockCapturedQueryOptions /
  mockCapturedMutationOptions so they comply with jest's mock-prefix
  hoisting rule for variables referenced from a jest.mock factory.
- Have setup() throw a clear error if the wrapped hook was never called,
  instead of NPE-ing on `const { retry } = null`.
- Mark axios fixtures with `isAxiosError: true` so they actually pass
  the new type guard. Add an explicit axiosNetworkError() helper and a
  nonAxiosError() case to lock in the "non-axios = transient = retry"
  branch.
- Add coverage for caller-provided options.retryDelay on both query and
  mutate paths to prevent the previous regression from coming back.
2026-04-27 14:33:44 +00:00
e77b48a9ef feat: add telemetry to deployments APIs (#12874)
* feat: Add telemetry to deployments API

Instruments 8 CUD-shaped deployment routes to emit telemetry events for tracking usage, duration, and error rates.

Changes:
- `schema.py`: Added `DeploymentPayload` Pydantic model to define the structure of telemetry data for deployment events (action, provider, seconds, success, error_type).
- `service.py`: Added three async methods (`log_package_deployment`, `log_package_deployment_provider`, `log_package_deployment_run`) to enqueue deployment events to the telemetry queue.
- `deployments.py`:
  - Created `DeploymentTelemetryCtx` dataclass and a non-invasive yield-based FastAPI dependency (`_make_telemetry_dep`) to handle timing, success/failure detection, and event emission.
  - Instrumented 8 routes (create/update/delete for deployments and providers, create run, update snapshot) by injecting the telemetry dependency and setting the provider context.
- `test_telemetry_schema.py`: Added unit tests for `DeploymentPayload` initialization, defaults, serialization, and roundtrip.
- `test_telemetry.py`: Added unit tests for the new `log_package_deployment*` service methods, including a check for the `do_not_track` setting.
- `test_deployments_telemetry.py`: Created a new integration test file with 10 tests covering happy paths, error paths (e.g., `HTTPException` mapping), and cross-route smoke tests for all instrumented endpoints.

* get rid of dup noqas

* update deprecated status http

* update unit tests

* feat: capture wxo_tenant_id in deployments telemetry

Adds `wxo_tenant_id` to DeploymentPayload (alias `wxoTenantId`) and
`DeploymentTelemetryCtx` so provider-account tenant identity is recorded
alongside provider/action/duration. Threads `provider_tenant_id` through
`resolve_adapter_from_deployment` and `resolve_adapter_mapper_from_deployment`
return tuples so all 8 instrumented routes populate the field, not just the
5 that already had `provider_account` in scope.

* Change exception type to error message to match existing patterns

---------

Co-authored-by: Hamza Rashid <hzarashid@gmail.com>
2026-04-27 14:00:15 +00:00
1629a45bd5 fix(frontend): align shareable playground input style with in-IDE playground (#12862)
* fix UI on shareable playground

* fix dialog not closing after confirm active change user
2026-04-27 13:27:49 +00:00
6934ac5a29 feat: Ship Calculator default tool + dynamic system prompt injection (#12864)
* add better tool call on agent

* ruff style and checker

* [autofix.ci] apply automated fixes

* gh suggestions

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-04-27 13:05:49 +00:00
50e594eb1e fix: guard output logs against non-dict artifacts (#12877)
* fix: guard against non-dict artifacts in output log building

When a component like Chroma (using chromadb internally) stores a
threading.Lock object as an artifact value, the code in
ResultData.validate_model() and build_output_logs() would crash with
TypeError because it tried to use the 'in' operator on a non-dict object.

- ResultData.validate_model(): skip artifacts that are not dicts before
  checking for 'stream_url' and 'type' keys
- build_output_logs(): guard STREAM case with isinstance(message, dict)
  check, and guard ARRAY case against None message

Fixes #12591

(cherry picked from commit 4e0b4e8191)

* test: cover non-dict result artifacts

---------

Co-authored-by: octo-patch <octo-patch@github.com>
2026-04-24 13:04:27 -07:00
99fc770206 docs: document tag format requirements and release artifacts in RELEASE.md (#12867)
- Add requirement that all tags MUST start with 'v' prefix
- Explain duplicate tag issue that caused v1.9.0 release notes to miss commits
- Document automatic tag format validation in release workflow
- Add new section documenting all release artifacts (PyPI packages and Docker images)
- Note that backend/frontend/EP images are published independently

Related to:
- #12847 (prevent duplicate tags and validate tag format)
- #12854 (allow backend/frontend Docker builds when main version exists)

These changes ensure future releases follow proper tagging conventions
and document what artifacts are published during a release.
2026-04-24 17:37:15 +00:00
1a9ffa05c0 fix(custom): include __future__ imports in component sandbox compilation (#12865)
* fix(custom): include __future__ imports in component sandbox compilation

When compiling custom component code, `from __future__ import annotations`
was classified as a regular ImportFrom node and excluded from the
definitions module. Because it is a compiler directive (PEP 563), it must
be present at compile() time to enable lazy annotation evaluation.

Without this fix, any custom component using the standard
`TYPE_CHECKING` + `from __future__ import annotations` pattern raised a
NameError at class-definition time because the type-only imports were
not available at runtime.

Changes:
- Separate __future__ imports from regular ImportFrom nodes in
  prepare_global_scope so they are NOT processed as runtime imports
- Prepend the collected __future__ imports to the definitions module
  before compile(), restoring PEP 563 semantics for helper
  classes/functions
- Thread the __future__ imports into compile_class_code() via a new
  optional parameter so the main component class also gets PEP 563
- Add a regression test reproducing the exact pattern described in #12776

Fixes #12776

* [autofix.ci] apply automated fixes

* Update test_validate.py

---------

Co-authored-by: octo-patch <octo-patch@github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-04-24 08:39:00 -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
dc26d19c1e fix: Update signature for WXO tests
(cherry picked from commit 981fe5f25e0ee87760b46d4eff1a5e28e8069e1b)
2026-04-23 17:49:53 -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
0659105762 fix: allow backend/frontend Docker builds when main version exists (#12854)
Backend and frontend images (langflowai/langflow-backend and
langflowai/langflow-frontend) are separate from the main image
(langflowai/langflow), so they should not be skipped when the
main version already exists on Docker Hub.

This fixes the issue where backend/frontend builds for 1.9.0
were skipped because the main 1.9.0 image was already published,
preventing these critical images from being available on Docker Hub.

Fixes: Backend and frontend Docker images not published in 1.9.0 release
(cherry picked from commit 595587027d)
2026-04-23 17:49:53 -07:00
cc50cae6b4 fix: route memory ops to stubs when DB service is noop (#12808)
fix(lfx): route memory ops to stubs when DB service is noop

lfx.memory bound to langflow.memory at import time whenever the langflow
package was importable, even when the registered DB service was
NoopDatabaseService. langflow.memory.aupdate_messages then called
session.get() on a NoopSession (which unconditionally returns None) and
raised spurious "Message with id X not found" errors mid-stream from the
Agent component.

Dispatch now happens at call time via has_langflow_db_backend(), which
requires both langflow to be importable AND a non-noop DB service to be
registered. Call-time evaluation is required because the DB service is
typically registered after lfx.memory is first imported during component
class loading.

(cherry picked from commit 6453d66de6)
2026-04-23 17:49:53 -07:00
0e6d284bc4 fix(security): default WEBHOOK_AUTH_ENABLE to True (#12845)
* fix(security): default WEBHOOK_AUTH_ENABLE to True (unauth webhook execution)

POST /api/v1/webhook/{flow_id} previously executed any user's flow
without authentication because WEBHOOK_AUTH_ENABLE defaulted to False.
Change the default to True so webhook endpoints require an API key and
validate that the caller owns the flow being executed. Operators who
need the prior behavior can explicitly opt in with
LANGFLOW_WEBHOOK_AUTH_ENABLE=False.

Docs updated to reflect the new secure-by-default behavior.

* test(security): add regression tests for WEBHOOK_AUTH_ENABLE default

Guard against a regression of the unauthenticated webhook execution fix:
one test pins the class-level default to True, the other confirms the
runtime config rejects an unauthenticated POST with 403 under defaults.

(cherry picked from commit cb6f7508dd)
2026-04-23 17:49:53 -07:00
b2d4539590 fix(ci): prevent duplicate tags and validate tag format in release workflow (#12847)
- Add tag format validation (must start with 'v')
- Check for duplicate tags without 'v' prefix
- Prevent release notes from using wrong base comparison
- Add validate-tag-format job dependency to create_release

Fixes tag duplication issue that caused v1.9.0 release notes to miss 58 commits.

Root cause: Duplicate tags (1.8.3 vs v1.8.3) caused GitHub's generateReleaseNotes
to pick the wrong base tag due to alphabetical sorting.

This ensures future releases will:
1. Only accept tags with 'v' prefix (v1.2.3 format)
2. Detect and reject releases if duplicate tags exist
3. Generate correct release notes with proper commit history

(cherry picked from commit a754961428)
2026-04-23 17:49:53 -07:00
849158ed51 docs: tip for running local ollama models (#12840)
add-tip-about-running-large-models-locally

(cherry picked from commit bc2bd31c05)
2026-04-23 17:49:52 -07:00