Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d1a3b71
feat(bundles): port arxiv as the second-pilot Bundle + porting helper
erichare May 9, 2026
0f43ab3
chore: auto-bake note keys and regenerate backend locales/en.json [sk…
github-actions[bot] May 9, 2026
5af4c21
Merge branch 'feat/extension-production-install' into feat/extension-…
erichare May 9, 2026
107676c
Merge branch 'feat/extension-production-install' into feat/extension-…
erichare May 9, 2026
550c121
Merge branch 'feat/extension-production-install' into feat/extension-…
erichare May 9, 2026
48f497f
Update Research Translation Loop.json
erichare May 9, 2026
87f7c08
Update .secrets.baseline
erichare May 9, 2026
f1b943c
Merge branch 'feat/extension-production-install' into feat/extension-…
erichare May 9, 2026
7319691
fix: Move bundle test for arxiv
erichare May 9, 2026
535f7c5
Merge branch 'feat/extension-production-install' into feat/extension-…
erichare May 9, 2026
f7fd89f
Merge branch 'feat/extension-production-install' into feat/extension-…
erichare May 9, 2026
52a1a97
Merge branch 'feat/extension-production-install' into feat/extension-…
erichare May 9, 2026
101bb17
Merge branch 'feat/extension-production-install' into feat/extension-…
erichare May 9, 2026
bfae8e0
Merge branch 'feat/extension-production-install' into feat/extension-…
erichare May 10, 2026
24f95b5
Merge branch 'feat/extension-production-install' into feat/extension-…
erichare May 10, 2026
1d1f32e
Merge branch 'feat/extension-production-install' into feat/extension-…
erichare May 10, 2026
a0c294c
Update PORTING.md
erichare May 10, 2026
e64aed7
Merge remote-tracking branch 'origin/feat/extension-production-instal…
erichare May 10, 2026
329b1f2
Merge branch 'release-1.10.0' into feat/extension-pilot-arxiv
erichare May 10, 2026
996bf4b
Update component_index.json
erichare May 10, 2026
5e4e668
chore: auto-bake note keys and regenerate backend locales/en.json [sk…
github-actions[bot] May 10, 2026
ed7a756
Merge branch 'feat/extension-production-install' into feat/extension-…
erichare May 10, 2026
3e123fe
Update component_index.json
erichare May 10, 2026
2522488
Merge branch 'feat/extension-pilot-arxiv' of https://github.com/langf…
erichare May 10, 2026
ab7bb22
Merge branch 'feat/extension-production-install' into feat/extension-…
erichare May 10, 2026
f871f9f
[autofix.ci] apply automated fixes
autofix-ci[bot] May 10, 2026
cee261e
Merge branch 'feat/extension-production-install' into feat/extension-…
erichare May 10, 2026
051e1e0
Merge branch 'feat/extension-production-install' into feat/extension-…
erichare May 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ dependencies = [
# ``pip install langflow`` still pulls the component in -- the AC for B1
# is "no user-visible change at install time".
"lfx-duckduckgo>=0.1.0",
# Second pilot port (validates src/bundles/PORTING.md): lfx-arxiv ships
# ArXivComponent as a standalone Bundle. Same regular-dep rationale --
# ``pip install langflow`` keeps shipping the arxiv component as before.
"lfx-arxiv>=0.1.0",
# langflow-extensions:bundle-deps-end
]

Expand Down Expand Up @@ -80,6 +84,7 @@ lfx = { workspace = true }
langflow-sdk = { workspace = true }
# langflow-extensions:bundle-sources-start
lfx-duckduckgo = { workspace = true }
lfx-arxiv = { workspace = true }
# langflow-extensions:bundle-sources-end
torch = { index = "pytorch-cpu" }
torchvision = { index = "pytorch-cpu" }
Expand All @@ -92,6 +97,7 @@ members = [
"src/sdk",
# langflow-extensions:bundle-members-start
"src/bundles/duckduckgo",
"src/bundles/arxiv",
# langflow-extensions:bundle-members-end
]

Expand Down Expand Up @@ -425,6 +431,16 @@ external = ["RUF027"]
"S104", # Binding to all interfaces (test servers)
"S108", # Insecure temp file usage (safe in tests)
]
"src/bundles/*/tests/*" = [
"D1",
"PLR2004",
"S101",
"SLF001",
"BLE001", # allow broad-exception catching in tests
"S104", # Binding to all interfaces (test servers)
"S108", # Insecure temp file usage (safe in tests)
"INP001", # Bundle test dirs are not import packages
]
"src/backend/tests/locust/*" = [
"D1", # Missing docstrings (CLI tools don't need full docstrings)
"T201", # Print statements (needed for CLI output)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@
],
"total_dependencies": 2
},
"module": "lfx.components.arxiv.arxiv.ArXivComponent"
"module": "lfx_arxiv.components.arxiv.arxiv.ArXivComponent"
},
"minimized": false,
"output_types": [],
Expand Down
9 changes: 0 additions & 9 deletions src/backend/base/langflow/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -363,15 +363,6 @@
"components.areducecomponent.inputs.source.info.21c26f21": "Input DataFrame to aggregate. The schema is automatically inferred from column names and types.",
"components.areducecomponent.outputs.states.display_name.1bf5fc7c": "Output Table",
"components.areducecomponent.outputs.states.info.9e0bb12a": "Aggregated DataFrame generated by the LLM following the specified output schema.",
"components.arxivcomponent.description.6fcfc4fe": "Search and retrieve papers from arXiv.org",
"components.arxivcomponent.display_name.2d546634": "arXiv",
"components.arxivcomponent.inputs.max_results.display_name.32040fb9": "Max Results",
"components.arxivcomponent.inputs.max_results.info.b0446804": "Maximum number of results to return",
"components.arxivcomponent.inputs.search_query.display_name.3ad6e0f4": "Search Query",
"components.arxivcomponent.inputs.search_query.info.dd5e9aa2": "The search query for arXiv papers (e.g., 'quantum computing')",
"components.arxivcomponent.inputs.search_type.display_name.6413a1ee": "Search Field",
"components.arxivcomponent.inputs.search_type.info.55d35699": "The field to search in",
"components.arxivcomponent.outputs.dataframe.display_name.16d1c905": "Table",
"components.assemblyaigetsubtitles.description.1c28e36e": "Export your transcript in SRT or VTT format for subtitles and closed captions",
"components.assemblyaigetsubtitles.display_name.3743bb02": "AssemblyAI Get Subtitles",
"components.assemblyaigetsubtitles.inputs.api_key.display_name.5ec16b95": "Assembly API Key",
Expand Down
124 changes: 0 additions & 124 deletions src/backend/tests/unit/components/search/test_arxiv_component.py

This file was deleted.

5 changes: 4 additions & 1 deletion src/bundles/PORTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,10 @@ wrong:
# 1. The bundle's manifest is structurally valid. Point ``validate`` at
# the package directory (where extension.json lives), not the bundle
# root -- the manifest is nested inside ``src/lfx_<bundle>/`` so the
# wheel ships it.
# wheel ships it. The validator accepts both ``def build(self): ...``
# and ``outputs = [Output(method="...")]`` shapes; a component that
# uses neither will fail with ``build-method-missing`` -- add an
# ``outputs`` declaration in that case.
uv run lfx extension validate src/bundles/<bundle>/src/lfx_<bundle>

# 2. Workspace resolves and the bundle is importable.
Expand Down
43 changes: 43 additions & 0 deletions src/bundles/arxiv/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# lfx-arxiv

arXiv search component as a standalone Langflow Extension Bundle.

This is the second-pilot port that validates
[`src/bundles/PORTING.md`](../PORTING.md) — the documented recipe for
extracting an in-tree provider into a standalone Bundle distribution.
The bundle ships a single component, `ArXivComponent`, which queries
arXiv's public Atom API for paper metadata.

## Install

```bash
pip install lfx-arxiv
```

The bundle is registered automatically via the `langflow.extensions`
entry-point. After install, restart your Langflow server; the
`ArXivComponent` will appear in the palette under the `arxiv` bundle
group.

## Develop

```bash
cd src/bundles/arxiv
pip install -e .
lfx extension validate .
```

## Manifest

The extension manifest is shipped at
`src/lfx_arxiv/extension.json` and points at the bundle at
`components/arxiv`. Components register under the canonical
namespaced ID `ext:arxiv:ArXivComponent@official`.

## Migration

Saved flows referencing the legacy class name `ArXivComponent` or the
old import paths `lfx.components.arxiv.arxiv.ArXivComponent` /
`lfx.components.arxiv.ArXivComponent` are rewritten to the new
namespaced ID by the migration table in
`src/lfx/src/lfx/extension/migration/migration_table.json`.
53 changes: 53 additions & 0 deletions src/bundles/arxiv/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
[project]
name = "lfx-arxiv"
version = "0.1.0"
description = "arXiv search component as a standalone Langflow Extension Bundle."
readme = "README.md"
requires-python = ">=3.10,<3.14"
license = { text = "MIT" }
authors = [
{ name = "Langflow", email = "contact@langflow.org" },
]
keywords = ["langflow", "lfx", "extension", "bundle", "arxiv", "search"]

# Runtime deps: lfx (the BUNDLE_API surface) plus defusedxml for safe XML
# parsing (the arxiv API returns Atom). defusedxml is already an lfx dep
# but we list it here as a direct runtime dep so the bundle keeps building
# even if lfx drops it later.
dependencies = [
"lfx>=0.5.0,<0.6.0",
"defusedxml>=0.7.1,<1.0.0",
]

[project.urls]
Homepage = "https://github.com/langflow-ai/langflow"
Documentation = "https://docs.langflow.org/extensions"
Repository = "https://github.com/langflow-ai/langflow"

# Manifest-shipping distributions are discovered via the
# ``langflow.extensions`` entry-point. The value is the dotted path to
# the package containing ``extension.json`` -- the loader walks
# ``importlib.metadata.files()`` from there to find the manifest, and
# falls back to this entry-point for editable installs whose dist.files
# only surfaces dist-info entries.
[project.entry-points."langflow.extensions"]
lfx-arxiv = "lfx_arxiv"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
# extension.json + components live inside the lfx_arxiv package so
# ``importlib.metadata.files(dist)`` finds them and the loader resolves
# bundles[].path relative to the manifest's directory.
packages = ["src/lfx_arxiv"]
include = ["src/lfx_arxiv/extension.json", "src/lfx_arxiv/components/**/*.py"]

[tool.hatch.build.targets.sdist]
include = [
"src/lfx_arxiv",
"extension.json",
"README.md",
"pyproject.toml",
]
15 changes: 15 additions & 0 deletions src/bundles/arxiv/src/lfx_arxiv/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"""lfx-arxiv: arXiv Search bundle.

This package is the distribution unit ``lfx-arxiv``. At runtime
Langflow's loader discovers ``extension.json`` shipped alongside this
``__init__.py`` and registers ``ArXivComponent`` under the namespaced
ID ``ext:arxiv:ArXivComponent@official``.

Second pilot port (after lfx-duckduckgo) -- exercises the same
extraction recipe documented in ``src/bundles/PORTING.md`` against a
component with no third-party runtime deps.
"""

from lfx_arxiv.components.arxiv.arxiv import ArXivComponent

__all__ = ["ArXivComponent"]
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from xml.etree.ElementTree import Element

from defusedxml.ElementTree import fromstring

from lfx.custom.custom_component.component import Component
from lfx.io import DropdownInput, IntInput, MessageTextInput, Output
from lfx.schema.data import Data
Expand Down
16 changes: 16 additions & 0 deletions src/bundles/arxiv/src/lfx_arxiv/extension.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"$schema": "https://schemas.langflow.org/extension/v1.json",
"id": "lfx-arxiv",
"version": "0.1.0",
"name": "arXiv Search",
"description": "arXiv search component as a standalone Langflow Extension Bundle.",
"lfx": {
"compat": ["1"]
},
"bundles": [
{
"name": "arxiv",
"path": "components/arxiv"
}
]
}
Loading
Loading