Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
45 changes: 29 additions & 16 deletions src/bundles/lfx-bundles/src/lfx_bundles/zep/zep.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,37 @@
"""Non-functional compatibility stub for the legacy Zep Chat Memory component.

The original implementation targeted the zep-python v1 SDK (``ZepClient`` plus
``zep_python.langchain.ZepChatMessageHistory``). zep-python 2.x removed both
symbols, and the bundle's ``zep`` extra pins ``zep-python==2.0.2``, so
``build_message_history`` could never succeed on a supported install -- it
always hit its ImportError guard, which misleadingly told users to
``pip install zep-python`` (already installed, just incompatible).

The component is deprecated (``legacy=True``, replaced by the Message History
component, ``helpers.Memory``). Rather than delete it outright -- which would
break saved flows that still reference it -- it is kept as a stub: existing
flows continue to load, and building the node now raises a clear error
pointing at the replacement instead of the misleading install hint.
"""

from lfx.base.memory.model import LCChatMemoryComponent
from lfx.field_typing.constants import Memory
from lfx.inputs.inputs import DropdownInput, MessageTextInput, SecretStrInput

DISABLED_MESSAGE = (
"The legacy 'Zep Chat Memory' component no longer functions: it was built on the "
"zep-python v1 API, which no longer exists in the zep-python 2.x release that "
"Langflow installs. Replace this node with the 'Message History' component (its "
"designated replacement) or another memory integration."
)


class ZepChatMemory(LCChatMemoryComponent):
display_name = "Zep Chat Memory"
# NOTE: display_name/description/input strings are intentionally kept identical to the
# pre-stub component so flow identity and the i18n locale keys (locales/*.json) do not
# change. The deprecation is signalled via legacy=True, the replacement below, and the
# runtime error raised by build_message_history.
description = "Retrieves and store chat messages from Zep."
name = "ZepChatMemory"
icon = "ZepMemory"
Expand All @@ -27,19 +54,5 @@ class ZepChatMemory(LCChatMemoryComponent):
]

def build_message_history(self) -> Memory:
try:
# Monkeypatch API_BASE_PATH to
# avoid 404
# This is a workaround for the local Zep instance
# cloud Zep works with v2
import zep_python.zep_client
from zep_python import ZepClient
from zep_python.langchain import ZepChatMessageHistory

zep_python.zep_client.API_BASE_PATH = self.api_base_path
except ImportError as e:
msg = "Could not import zep-python package. Please install it with `pip install zep-python`."
raise ImportError(msg) from e

zep_client = ZepClient(api_url=self.url, api_key=self.api_key)
return ZepChatMessageHistory(session_id=self.session_id, zep_client=zep_client)
"""Always raise: the zep-python v1 API this component was built on is gone."""
raise RuntimeError(DISABLED_MESSAGE)
76 changes: 76 additions & 0 deletions src/bundles/lfx-bundles/tests/test_zep_component.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"""Unit tests for the tombstoned Zep Chat Memory component (``lfx-bundles``).

``ZepChatMemory`` is legacy (replaced by the Message History component) and its
implementation targeted the zep-python v1 SDK; the pinned ``zep-python==2.0.2``
removed that API, so ``build_message_history`` could never succeed. The
component is now a non-functional stub. These tests pin the stub contract:

* flow identity (component name, display_name, inputs, output wiring) is
unchanged, so saved flows keep loading and i18n locale keys are unaffected;
* ``build_message_history`` fails with a clear, actionable error -- not the old
misleading ``pip install zep-python`` ImportError hint;
* the stub never imports ``zep_python``, so the failure mode does not depend on
which zep-python version happens to be installed.
"""

import ast
import inspect

import pytest
from lfx_bundles.zep import ZepChatMemory
from lfx_bundles.zep import zep as zep_module


@pytest.fixture
def component():
return ZepChatMemory(
url="http://localhost:8000",
api_key="test-api-key", # pragma: allowlist secret
api_base_path="api/v1",
session_id="test-session",
_session_id="test-run-session",
)


def test_flow_identity_is_preserved(component):
# The component name is a flow-identity contract: saved flows reference it and
# migration_table.json maps it. The deprecation metadata must survive the stub.
assert ZepChatMemory.name == "ZepChatMemory"
assert ZepChatMemory.legacy is True
assert ZepChatMemory.replacement == ["helpers.Memory"]
assert ZepChatMemory.display_name == "Zep Chat Memory"

frontend_node = component.to_frontend_node()
template = frontend_node["data"]["node"]["template"]
for field in ("url", "api_key", "api_base_path", "session_id"):
assert field in template
assert template["url"]["value"] == "http://localhost:8000"

# Same single Memory output, wired to the same method name.
assert [(output.name, output.method) for output in component.outputs] == [
("memory", "build_message_history"),
]


def test_build_raises_actionable_error_not_install_hint(component):
with pytest.raises(RuntimeError, match="no longer functions") as exc_info:
component.build_message_history()

error_text = str(exc_info.value)
# Points at the designated replacement...
assert "Message History" in error_text
# ...and is not the old misleading missing-dependency path.
assert not isinstance(exc_info.value, ImportError)
assert "pip install" not in error_text


def test_stub_does_not_import_zep_python():
tree = ast.parse(inspect.getsource(zep_module))
imported = set()
for node in ast.walk(tree):
if isinstance(node, ast.Import):
imported.update(alias.name for alias in node.names)
elif isinstance(node, ast.ImportFrom) and node.module:
imported.add(node.module)
zep_imports = {name for name in imported if name == "zep_python" or name.startswith("zep_python.")}
assert not zep_imports
Loading