mnemo-agent 0.1.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.
mnemo/__init__.py ADDED
@@ -0,0 +1,4 @@
1
+ """mnemo — local-first agent memory CLI."""
2
+
3
+ __version__ = "0.1.0"
4
+ __author__ = "Joshua Ndala"
File without changes
@@ -0,0 +1,81 @@
1
+ """Letta adapter — calls real API when letta-client is installed, stubs otherwise."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from mnemo.models import AgentDump, Fact
8
+
9
+
10
+ def _require_letta() -> Any:
11
+ try:
12
+ from letta_client import Letta # type: ignore
13
+ return Letta
14
+ except ImportError:
15
+ raise ImportError(
16
+ "letta adapter requires: pip install letta-client\n"
17
+ "Or: pip install 'mnemo[letta]'"
18
+ )
19
+
20
+
21
+ def dump_from_letta(base_url: str, agent_id: str, agent_name: str) -> AgentDump:
22
+ """Fetch memories from a Letta agent and return a normalized AgentDump."""
23
+ Letta = _require_letta()
24
+ client = Letta(base_url=base_url)
25
+
26
+ # Letta: GET /v1/agents/{agent_id}/memory/messages or /core_memory
27
+ try:
28
+ memory_blocks = client.agents.memory.retrieve(agent_id=agent_id)
29
+ except Exception as exc:
30
+ raise RuntimeError(f"Letta API error: {exc}") from exc
31
+
32
+ facts: list[Fact] = []
33
+
34
+ # Letta returns human/persona/custom memory blocks
35
+ for block in getattr(memory_blocks, "blocks", []):
36
+ label = getattr(block, "label", "memory")
37
+ value = getattr(block, "value", "")
38
+ block_id = str(getattr(block, "id", ""))
39
+
40
+ if not value:
41
+ continue
42
+
43
+ # Treat each newline-separated line as a separate fact
44
+ for line in str(value).splitlines():
45
+ line = line.strip()
46
+ if not line:
47
+ continue
48
+ facts.append(
49
+ Fact(
50
+ entity=agent_id,
51
+ attribute=label,
52
+ value=line,
53
+ source="letta",
54
+ confidence=1.0,
55
+ metadata={"block_id": block_id, "agent_id": agent_id},
56
+ )
57
+ )
58
+
59
+ return AgentDump(agent=agent_name, source="letta", facts=facts)
60
+
61
+
62
+ def load_to_letta(dump: AgentDump, base_url: str, agent_id: str) -> int:
63
+ """Append facts to a Letta agent's core memory. Returns count pushed."""
64
+ Letta = _require_letta()
65
+ client = Letta(base_url=base_url)
66
+
67
+ pushed = 0
68
+ for fact in dump.facts:
69
+ try:
70
+ client.agents.core_memory.modify(
71
+ agent_id=agent_id,
72
+ label="human",
73
+ value=fact.to_text(),
74
+ append=True,
75
+ )
76
+ pushed += 1
77
+ except Exception as exc: # noqa: BLE001
78
+ import click
79
+ click.echo(f" ⚠ Failed to push fact {fact.id}: {exc}", err=True)
80
+
81
+ return pushed
@@ -0,0 +1,69 @@
1
+ """Mem0 adapter — calls real API when mem0ai is installed, stubs otherwise."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from mnemo.models import AgentDump, Fact
8
+
9
+
10
+ def _require_mem0() -> Any:
11
+ try:
12
+ import mem0ai # type: ignore
13
+ return mem0ai
14
+ except ImportError:
15
+ raise ImportError(
16
+ "mem0 adapter requires: pip install mem0ai\n"
17
+ "Or: pip install 'mnemo[mem0]'"
18
+ )
19
+
20
+
21
+ def dump_from_mem0(api_key: str, user_id: str, agent: str) -> AgentDump:
22
+ """Fetch all memories from Mem0 and return a normalized AgentDump."""
23
+ mem0 = _require_mem0()
24
+ client = mem0.MemoryClient(api_key=api_key)
25
+
26
+ raw_memories: list[dict] = client.get_all(user_id=user_id)
27
+
28
+ facts: list[Fact] = []
29
+ for mem in raw_memories:
30
+ # Mem0 returns: {id, memory, user_id, metadata, created_at, ...}
31
+ # We normalize to entity=user_id, attribute="memory", value=text
32
+ facts.append(
33
+ Fact(
34
+ id=str(mem.get("id", "")),
35
+ entity=user_id,
36
+ attribute="memory",
37
+ value=str(mem.get("memory", "")),
38
+ source="mem0",
39
+ confidence=float(mem.get("score", 1.0)),
40
+ metadata={
41
+ k: v
42
+ for k, v in mem.items()
43
+ if k not in ("id", "memory", "user_id", "score")
44
+ },
45
+ )
46
+ )
47
+
48
+ return AgentDump(agent=agent, source="mem0", facts=facts)
49
+
50
+
51
+ def load_to_mem0(dump: AgentDump, api_key: str, user_id: str) -> int:
52
+ """Push facts from a dump into Mem0. Returns count of facts pushed."""
53
+ mem0 = _require_mem0()
54
+ client = mem0.MemoryClient(api_key=api_key)
55
+
56
+ pushed = 0
57
+ for fact in dump.facts:
58
+ try:
59
+ client.add(
60
+ messages=[{"role": "user", "content": fact.to_text()}],
61
+ user_id=user_id,
62
+ metadata={"mnemo_id": fact.id, **fact.metadata},
63
+ )
64
+ pushed += 1
65
+ except Exception as exc: # noqa: BLE001
66
+ import click
67
+ click.echo(f" ⚠ Failed to push fact {fact.id}: {exc}", err=True)
68
+
69
+ return pushed