langgraph-velesdb 4.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- langgraph_velesdb/__init__.py +21 -0
- langgraph_velesdb/py.typed +0 -0
- langgraph_velesdb/tools.py +245 -0
- langgraph_velesdb-4.2.0.dist-info/METADATA +147 -0
- langgraph_velesdb-4.2.0.dist-info/RECORD +8 -0
- langgraph_velesdb-4.2.0.dist-info/WHEEL +5 -0
- langgraph_velesdb-4.2.0.dist-info/licenses/LICENSE +27 -0
- langgraph_velesdb-4.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""LangGraph memory tools for VelesDB — the ``why()`` knowledge-graph wedge.
|
|
2
|
+
|
|
3
|
+
Drop VelesDB's local-first agent memory into any LangGraph agent:
|
|
4
|
+
|
|
5
|
+
>>> from langgraph.prebuilt import create_react_agent
|
|
6
|
+
>>> from langgraph_velesdb import make_memory_tools
|
|
7
|
+
>>>
|
|
8
|
+
>>> agent = create_react_agent(llm, make_memory_tools("./agent_memory"))
|
|
9
|
+
|
|
10
|
+
``make_memory_tools`` returns the full VelesDB memory tool set: ``remember``,
|
|
11
|
+
``recall``, ``recall_where``, ``recall_fused``, ``relate``, ``forget``,
|
|
12
|
+
``feedback``, and the differentiator ``why`` — which answers with the
|
|
13
|
+
best-matching memory *plus* the connected subgraph a vector recall is blind
|
|
14
|
+
to — plus ``save_working_context``/``load_working_context`` for cross-run
|
|
15
|
+
resumption. The store is on disk, so memory persists across agent runs.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from langgraph_velesdb.tools import make_memory_tools
|
|
19
|
+
|
|
20
|
+
__all__ = ["make_memory_tools"]
|
|
21
|
+
__version__ = "4.2.0"
|
|
File without changes
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"""LangGraph / LangChain tools backed by VelesDB's high-level ``MemoryService``.
|
|
2
|
+
|
|
3
|
+
A thin adapter: each tool is a small method on ``_MemoryToolkit``, bound to one
|
|
4
|
+
``MemoryService`` (the core). No state or logic lives here beyond shaping
|
|
5
|
+
inputs/outputs for the tool layer — the engine does the work. Methods live on
|
|
6
|
+
a class (rather than as closures inside ``make_memory_tools``) so each tool's
|
|
7
|
+
own cyclomatic complexity is what a linter measures, instead of all ten
|
|
8
|
+
rolling up into one function.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from typing import Any, Optional
|
|
14
|
+
|
|
15
|
+
from langchain_core.tools import BaseTool, StructuredTool # nosemgrep: ai.python.detect-langchain.detect-langchain # this package IS the LangChain connector
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
from velesdb import MemoryService
|
|
19
|
+
except ImportError as exc: # pragma: no cover - import guard
|
|
20
|
+
raise ImportError(
|
|
21
|
+
"velesdb is required for langgraph-velesdb. Install with: pip install velesdb"
|
|
22
|
+
) from exc
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def make_memory_tools(
|
|
26
|
+
path: Optional[str] = None,
|
|
27
|
+
*,
|
|
28
|
+
service: Optional["MemoryService"] = None,
|
|
29
|
+
) -> list[BaseTool]:
|
|
30
|
+
"""Build the full VelesDB memory tool set for a LangGraph agent.
|
|
31
|
+
|
|
32
|
+
Returns ``remember`` / ``recall`` / ``recall_where`` / ``recall_fused`` /
|
|
33
|
+
``relate`` / ``forget`` / ``feedback`` / ``why`` / ``save_working_context``
|
|
34
|
+
/ ``load_working_context``.
|
|
35
|
+
|
|
36
|
+
Pass a ``path`` to open a local on-disk store (offline hash embedder), or a
|
|
37
|
+
pre-configured ``service`` (e.g. an Ollama-backed ``MemoryService``) to reuse
|
|
38
|
+
it. The store is on disk, so memory persists across agent runs.
|
|
39
|
+
"""
|
|
40
|
+
toolkit = _MemoryToolkit(_resolve_service(path, service))
|
|
41
|
+
return [
|
|
42
|
+
StructuredTool.from_function(fn)
|
|
43
|
+
for fn in (
|
|
44
|
+
toolkit.remember,
|
|
45
|
+
toolkit.recall,
|
|
46
|
+
toolkit.recall_where,
|
|
47
|
+
toolkit.recall_fused,
|
|
48
|
+
toolkit.relate,
|
|
49
|
+
toolkit.forget,
|
|
50
|
+
toolkit.feedback,
|
|
51
|
+
toolkit.why,
|
|
52
|
+
toolkit.save_working_context,
|
|
53
|
+
toolkit.load_working_context,
|
|
54
|
+
)
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class _MemoryToolkit:
|
|
59
|
+
"""Binds one ``MemoryService`` to the ten tool methods ``make_memory_tools``
|
|
60
|
+
wraps into ``StructuredTool``\\ s. Not part of the public API."""
|
|
61
|
+
|
|
62
|
+
def __init__(self, mem: "MemoryService") -> None:
|
|
63
|
+
self._mem = mem
|
|
64
|
+
|
|
65
|
+
def remember(
|
|
66
|
+
self,
|
|
67
|
+
fact: str,
|
|
68
|
+
links: Optional[list[list[Any]]] = None,
|
|
69
|
+
metadata: Optional[dict[str, Any]] = None,
|
|
70
|
+
ttl_seconds: Optional[int] = None,
|
|
71
|
+
) -> int:
|
|
72
|
+
"""Store a fact in long-term memory and return its id.
|
|
73
|
+
|
|
74
|
+
``links`` optionally wires typed outgoing edges to existing memory ids
|
|
75
|
+
at write time — each item is ``[target_id, relation]`` (equivalent to
|
|
76
|
+
calling ``relate`` right after). ``metadata`` attaches key/value pairs
|
|
77
|
+
``recall_where``/``recall_fused`` can later filter on (every fact also
|
|
78
|
+
gets an automatic ``_veles_date`` stamp — today's date as a
|
|
79
|
+
``YYYYMMDD`` int — unless you set that key yourself). ``ttl_seconds``
|
|
80
|
+
makes the fact expire, and stop being recalled, after that many
|
|
81
|
+
seconds. All three are optional; a bare ``remember(fact)`` behaves
|
|
82
|
+
exactly as before.
|
|
83
|
+
"""
|
|
84
|
+
return self._mem.remember(
|
|
85
|
+
fact,
|
|
86
|
+
links=_as_tuples(links),
|
|
87
|
+
metadata=metadata,
|
|
88
|
+
ttl_seconds=ttl_seconds,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
def recall(self, query: str, k: int = 5) -> list[dict[str, Any]]:
|
|
92
|
+
"""Recall memories semantically similar to the query (vector search).
|
|
93
|
+
|
|
94
|
+
Each hit's ``metadata`` is always ``None`` on this path — use
|
|
95
|
+
``recall_where`` (or ``recall_fused``) when you need each memory's
|
|
96
|
+
metadata, including the automatic ``_veles_date`` stamp.
|
|
97
|
+
"""
|
|
98
|
+
return self._mem.recall(query, k)
|
|
99
|
+
|
|
100
|
+
def recall_where(
|
|
101
|
+
self,
|
|
102
|
+
query: str,
|
|
103
|
+
filters: Optional[list[list[Any]]] = None,
|
|
104
|
+
k: int = 5,
|
|
105
|
+
) -> list[dict[str, Any]]:
|
|
106
|
+
"""Recall memories similar to the query, filtered by metadata, with
|
|
107
|
+
each hit's metadata attached.
|
|
108
|
+
|
|
109
|
+
``filters`` is a list of ``[field, op, value]`` triples, ``op`` one of
|
|
110
|
+
``"eq"``/``"ne"``/``"lt"``/``"le"``/``"gt"``/``"ge"`` — e.g.
|
|
111
|
+
``[["_veles_date", "ge", 20260101]]`` keeps only facts stamped on or
|
|
112
|
+
after that date. Pass an empty list (the default) for no filtering.
|
|
113
|
+
Unlike plain ``recall``, every hit's ``metadata`` dict is returned,
|
|
114
|
+
including the automatic ``_veles_date`` stamp every fact gets at
|
|
115
|
+
write time.
|
|
116
|
+
"""
|
|
117
|
+
return self._mem.recall_where(query, _as_tuples(filters) or [], k)
|
|
118
|
+
|
|
119
|
+
def recall_fused(
|
|
120
|
+
self,
|
|
121
|
+
query: str,
|
|
122
|
+
k: int = 5,
|
|
123
|
+
metadata_filter: Optional[dict[str, Any]] = None,
|
|
124
|
+
date_field: Optional[str] = None,
|
|
125
|
+
) -> Any:
|
|
126
|
+
"""Fused vector + graph recall: walks the graph from the top hit and
|
|
127
|
+
folds in any connected fact a plain ``recall`` would miss.
|
|
128
|
+
|
|
129
|
+
``metadata_filter`` is an optional exact-match metadata filter. Pass
|
|
130
|
+
``date_field="_veles_date"`` (the automatic stamp every fact gets) to
|
|
131
|
+
get back a dict with a chronological, date-prefixed timeline
|
|
132
|
+
(``dated_context``) instead of a plain list — useful for "what
|
|
133
|
+
happened, in order" questions. Omit ``date_field`` for the plain-list
|
|
134
|
+
form.
|
|
135
|
+
"""
|
|
136
|
+
return self._mem.recall_fused(query, k, metadata_filter, date_field=date_field)
|
|
137
|
+
|
|
138
|
+
def relate(self, from_id: int, to_id: int, relation: str) -> int:
|
|
139
|
+
"""Link two memories with a typed edge (``from_id`` -> ``to_id``)."""
|
|
140
|
+
return self._mem.relate(from_id, to_id, relation)
|
|
141
|
+
|
|
142
|
+
def forget(self, memory_id: int) -> bool:
|
|
143
|
+
"""Delete a memory by id.
|
|
144
|
+
|
|
145
|
+
Returns ``True`` if a memory actually existed under ``memory_id`` and
|
|
146
|
+
was removed, ``False`` if there was nothing stored there (a stale id
|
|
147
|
+
or a typo) — a no-op, not an error.
|
|
148
|
+
"""
|
|
149
|
+
return self._mem.forget(memory_id)
|
|
150
|
+
|
|
151
|
+
def feedback(self, memory_id: int, success: bool) -> Any:
|
|
152
|
+
"""Reinforce or weaken a memory after using it, and return its
|
|
153
|
+
updated confidence in ``[0.0, 1.0]``.
|
|
154
|
+
|
|
155
|
+
Call this once you know whether a memory you recalled actually helped
|
|
156
|
+
answer the question (``success=True``) or was misleading/irrelevant
|
|
157
|
+
(``success=False``). This closes the self-improving loop: future
|
|
158
|
+
``recall``/``recall_where``/``recall_fused`` calls rank
|
|
159
|
+
higher-confidence memories higher.
|
|
160
|
+
|
|
161
|
+
If the installed ``velesdb`` predates this method, returns
|
|
162
|
+
``{"error": "..."}`` instead of raising, telling you to upgrade.
|
|
163
|
+
"""
|
|
164
|
+
if not hasattr(self._mem, "feedback"):
|
|
165
|
+
return _unsupported("feedback")
|
|
166
|
+
return self._mem.feedback(memory_id, success)
|
|
167
|
+
|
|
168
|
+
def why(self, question: str, max_hops: int = 2) -> dict[str, Any]:
|
|
169
|
+
"""Explain something: the best-matching memory plus the connected
|
|
170
|
+
subgraph reachable through typed links — context a plain recall misses."""
|
|
171
|
+
return self._mem.why(question, max_hops)
|
|
172
|
+
|
|
173
|
+
def save_working_context(
|
|
174
|
+
self,
|
|
175
|
+
project: str,
|
|
176
|
+
session: str,
|
|
177
|
+
working: dict[str, Any],
|
|
178
|
+
) -> Any:
|
|
179
|
+
"""Persist the current working state under ``project`` + ``session``
|
|
180
|
+
so a later run can resume exactly where this one left off.
|
|
181
|
+
|
|
182
|
+
``working`` is free-form but conventionally shaped like
|
|
183
|
+
``{"goal": str, "active_constraints": [...], "verified_facts": [...],
|
|
184
|
+
"open_hypotheses": [...], "decisions": [...], "exact_evidence": [...],
|
|
185
|
+
"pending_actions": [...]}`` — call this near the end of a session, or
|
|
186
|
+
whenever the plan materially changes. Saving again under the same
|
|
187
|
+
``project`` + ``session`` replaces the previous state (not a merge).
|
|
188
|
+
|
|
189
|
+
If the installed ``velesdb`` predates this method, returns
|
|
190
|
+
``{"error": "..."}`` instead of raising, telling you to upgrade.
|
|
191
|
+
"""
|
|
192
|
+
if not hasattr(self._mem, "save_working_context"):
|
|
193
|
+
return _unsupported("save_working_context")
|
|
194
|
+
return self._mem.save_working_context(project, session, working)
|
|
195
|
+
|
|
196
|
+
def load_working_context(self, project: str, session: str) -> Any:
|
|
197
|
+
"""Load the working context previously saved under ``project`` +
|
|
198
|
+
``session`` by ``save_working_context``.
|
|
199
|
+
|
|
200
|
+
Call this at the very start of a new run, before doing anything else,
|
|
201
|
+
to resume a prior session instead of restarting from scratch. Returns
|
|
202
|
+
``None`` when nothing was ever saved under that exact
|
|
203
|
+
``project``/``session`` pair — not an error, just a fresh start.
|
|
204
|
+
|
|
205
|
+
If the installed ``velesdb`` predates this method, returns
|
|
206
|
+
``{"error": "..."}`` instead of raising, telling you to upgrade.
|
|
207
|
+
"""
|
|
208
|
+
if not hasattr(self._mem, "load_working_context"):
|
|
209
|
+
return _unsupported("load_working_context")
|
|
210
|
+
return self._mem.load_working_context(project, session)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def _resolve_service(
|
|
214
|
+
path: Optional[str], service: Optional["MemoryService"]
|
|
215
|
+
) -> "MemoryService":
|
|
216
|
+
if service is not None:
|
|
217
|
+
return service
|
|
218
|
+
if path is None:
|
|
219
|
+
raise ValueError("make_memory_tools requires either `path` or `service`")
|
|
220
|
+
return MemoryService(path)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def _as_tuples(pairs: Optional[list[list[Any]]]) -> Optional[list[tuple[Any, ...]]]:
|
|
224
|
+
"""``[[a, b, ...], ...]`` -> ``[(a, b, ...), ...]``, or ``None`` if falsy.
|
|
225
|
+
|
|
226
|
+
Shared by ``remember``'s ``links`` and ``recall_where``'s ``filters``: both
|
|
227
|
+
accept plain JSON-friendly lists of lists from the LLM and forward tuples
|
|
228
|
+
to the binding, which expects ``List[Tuple[...]]``.
|
|
229
|
+
"""
|
|
230
|
+
if not pairs:
|
|
231
|
+
return None
|
|
232
|
+
return [tuple(p) for p in pairs]
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def _unsupported(method: str) -> dict[str, str]:
|
|
236
|
+
"""Actionable tool-error payload for a ``MemoryService`` method missing on
|
|
237
|
+
the installed ``velesdb`` (older than this package expects).
|
|
238
|
+
|
|
239
|
+
Returned as a normal tool result rather than raised, so a missing method
|
|
240
|
+
surfaces to the LLM as a tool error it can react to instead of an
|
|
241
|
+
uncaught ``AttributeError`` that would kill the whole LangGraph run.
|
|
242
|
+
"""
|
|
243
|
+
return {
|
|
244
|
+
"error": f"{method} requires velesdb > 3.12.0 — upgrade with `pip install -U velesdb`"
|
|
245
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: langgraph-velesdb
|
|
3
|
+
Version: 4.2.0
|
|
4
|
+
Summary: LangGraph memory tools for VelesDB: drop the why() knowledge-graph memory wedge into any LangGraph agent.
|
|
5
|
+
Author-email: VelesDB Team <contact@wiscale.fr>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://velesdb.com
|
|
8
|
+
Project-URL: Repository, https://github.com/cyberlife-coder/VelesDB
|
|
9
|
+
Keywords: langgraph,langchain,velesdb,agent-memory,knowledge-graph,local-first,why,llm
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: langchain-core<2.0.0,>=0.3.0
|
|
22
|
+
Requires-Dist: velesdb>=3.12.0
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: pytest<9.0,>=7.0; extra == "dev"
|
|
25
|
+
Requires-Dist: langgraph>=0.2.0; extra == "dev"
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
# langgraph-velesdb
|
|
29
|
+
|
|
30
|
+
Drop VelesDB's local-first agent memory — the **`why()` knowledge-graph wedge** —
|
|
31
|
+
into any [LangGraph](https://github.com/langchain-ai/langgraph) agent in three lines.
|
|
32
|
+
|
|
33
|
+
Most agent memory is vector recall: it finds text that *looks like* the query.
|
|
34
|
+
VelesDB **connects** memories with typed links, so `why()` answers with the
|
|
35
|
+
best-matching memory **plus the connected subgraph** — context that shares no
|
|
36
|
+
words with the question, which a plain vector recall is blind to. The store is on
|
|
37
|
+
disk, so memory persists across agent runs.
|
|
38
|
+
|
|
39
|
+

|
|
40
|
+
|
|
41
|
+
## Install
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pip install langgraph-velesdb # pulls langchain-core + velesdb
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Use
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from langgraph.prebuilt import create_react_agent
|
|
51
|
+
from langgraph_velesdb import make_memory_tools
|
|
52
|
+
|
|
53
|
+
# Offline by default (hash embedder); pass a configured MemoryService for Ollama.
|
|
54
|
+
agent = create_react_agent(llm, make_memory_tools("./agent_memory"))
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`make_memory_tools` returns ten tools the agent can call:
|
|
58
|
+
|
|
59
|
+
| Tool | What it does |
|
|
60
|
+
|------------------------|--------------|
|
|
61
|
+
| `remember` | store a fact (optionally with `links`, `metadata`, `ttl_seconds`), return its id |
|
|
62
|
+
| `recall` | semantic (vector) recall — no metadata |
|
|
63
|
+
| `recall_where` | filtered recall (metadata `[field, op, value]` triples) **with metadata attached**, e.g. the auto `_veles_date` stamp |
|
|
64
|
+
| `recall_fused` | fused vector + graph recall; pass `date_field="_veles_date"` for a dated timeline |
|
|
65
|
+
| `relate` | link two memories with a typed edge |
|
|
66
|
+
| `forget` | delete a memory by id (`True` if it existed, `False` if it was already gone) |
|
|
67
|
+
| `feedback` | reinforce or weaken a memory after using it, closing the self-improving recall loop |
|
|
68
|
+
| `why` | best-matching memory **+ its connected subgraph** (the wedge) |
|
|
69
|
+
| `save_working_context` | persist the current goal/constraints/decisions/pending actions under a project + session |
|
|
70
|
+
| `load_working_context` | resume a prior run's working context — call at the start of a session |
|
|
71
|
+
|
|
72
|
+
For a pre-configured backend (e.g. Ollama embeddings), build the service yourself
|
|
73
|
+
and pass it through:
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
from velesdb import MemoryService
|
|
77
|
+
tools = make_memory_tools(service=MemoryService("./agent_memory"))
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Cross-run resumption
|
|
81
|
+
|
|
82
|
+
`save_working_context` / `load_working_context` let an agent pick up a task
|
|
83
|
+
across separate runs instead of restarting from scratch:
|
|
84
|
+
|
|
85
|
+
`make_memory_tools` returns a *list* of tools, so index them by name first
|
|
86
|
+
(the same pattern LangGraph's `ToolNode`/`create_react_agent` use internally):
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
tools = {t.name: t for t in make_memory_tools("./agent_memory")}
|
|
90
|
+
|
|
91
|
+
tools["save_working_context"].invoke({
|
|
92
|
+
"project": "veles",
|
|
93
|
+
"session": "issue-1546",
|
|
94
|
+
"working": {
|
|
95
|
+
"goal": "ship the langgraph tool set",
|
|
96
|
+
"pending_actions": ["open the PR"],
|
|
97
|
+
},
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
# ... next run, same project + session:
|
|
101
|
+
tools["load_working_context"].invoke({"project": "veles", "session": "issue-1546"})
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Dated recall
|
|
105
|
+
|
|
106
|
+
Every `remember`-ed fact is auto-stamped with `_veles_date` (today, as a
|
|
107
|
+
`YYYYMMDD` int) unless you set that metadata key yourself. Point
|
|
108
|
+
`recall_fused` at it to get a chronological timeline instead of a ranked list:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
tools = {t.name: t for t in make_memory_tools("./agent_memory")}
|
|
112
|
+
|
|
113
|
+
tools["recall_fused"].invoke({"query": "what changed this week", "date_field": "_veles_date"})
|
|
114
|
+
# -> {"memories": [...], "dated_context": "...", "now": "..."}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Compatibility
|
|
118
|
+
|
|
119
|
+
This package requires `velesdb>=3.12.0`, the highest version published to
|
|
120
|
+
PyPI at the time of writing. `feedback`, `save_working_context`,
|
|
121
|
+
`load_working_context`, and the automatic `_veles_date` metadata stamp landed
|
|
122
|
+
in `velesdb`/`velesdb-memory` *after* the 3.12.0 release cut and are not yet
|
|
123
|
+
in a published wheel. On a plain 3.12.0 install those three tools detect the
|
|
124
|
+
missing binding method at call time and return an error payload instead of
|
|
125
|
+
raising, e.g.:
|
|
126
|
+
|
|
127
|
+
```json
|
|
128
|
+
{"error": "feedback requires velesdb > 3.12.0 — upgrade with `pip install -U velesdb`"}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
so a single unsupported call surfaces to the agent as a normal tool result it
|
|
132
|
+
can react to, instead of an uncaught `AttributeError` killing the whole graph
|
|
133
|
+
run. `recall_where`/`recall_fused` still work, but their `metadata` stays
|
|
134
|
+
empty for auto-dating until you upgrade. `forget` works on 3.12.0 too, but
|
|
135
|
+
returns `None` instead of a `True`/`False` existed-or-not signal. The floor
|
|
136
|
+
will be bumped again once a `velesdb` release past 3.12.0 ships.
|
|
137
|
+
|
|
138
|
+
`list_working_contexts` (browse saved sessions for a project) is not exposed
|
|
139
|
+
here: it exists on the WASM and MCP surfaces but not yet on the `velesdb`
|
|
140
|
+
Python binding (`MemoryService`), and this package only ever calls the
|
|
141
|
+
binding — no memory logic is reimplemented in this MIT-licensed integration.
|
|
142
|
+
It will be added once the Python binding grows the method.
|
|
143
|
+
|
|
144
|
+
## License
|
|
145
|
+
|
|
146
|
+
MIT — see [LICENSE](./LICENSE). Wraps [`velesdb`](https://pypi.org/project/velesdb/),
|
|
147
|
+
which is under the VelesDB Core License 1.0.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
langgraph_velesdb/__init__.py,sha256=7kTqsXM0iReyVMAZ1aK2iFdffEaPxqzyJrq3_p_0jYU,907
|
|
2
|
+
langgraph_velesdb/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
langgraph_velesdb/tools.py,sha256=6R9WBKE-L0b41gE2aC-a0aZFT5pwuZktiKSIsNAsLck,10314
|
|
4
|
+
langgraph_velesdb-4.2.0.dist-info/licenses/LICENSE,sha256=hu80gXApIu5PnZ5cS0G4aLlhs-SqMhOT4OsqHr8Z5Is,1298
|
|
5
|
+
langgraph_velesdb-4.2.0.dist-info/METADATA,sha256=oSGR3U_IQq2tOjuKi7gXf83GSeFE41tKHpYjD-36ReA,6437
|
|
6
|
+
langgraph_velesdb-4.2.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
7
|
+
langgraph_velesdb-4.2.0.dist-info/top_level.txt,sha256=Vhmq6JWJ2ybjnubG6qMA3sxvF_v4FvpjNPL1dEIQkdA,18
|
|
8
|
+
langgraph_velesdb-4.2.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2026 Wiscale France
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
Note: This MIT license applies to the LangChain integration code only.
|
|
26
|
+
VelesDB Core itself is licensed under the Elastic License 2.0 (ELv2).
|
|
27
|
+
See https://github.com/cyberlife-coder/VelesDB for VelesDB Core licensing.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
langgraph_velesdb
|