hipcortex 0.2.0__tar.gz
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.
- hipcortex-0.2.0/PKG-INFO +108 -0
- hipcortex-0.2.0/README.md +67 -0
- hipcortex-0.2.0/hipcortex/__init__.py +15 -0
- hipcortex-0.2.0/hipcortex/adapters/__init__.py +1 -0
- hipcortex-0.2.0/hipcortex/adapters/autogen.py +156 -0
- hipcortex-0.2.0/hipcortex/adapters/crewai.py +153 -0
- hipcortex-0.2.0/hipcortex/async_client.py +255 -0
- hipcortex-0.2.0/hipcortex/cli.py +480 -0
- hipcortex-0.2.0/hipcortex/client.py +223 -0
- hipcortex-0.2.0/hipcortex/install/SKILL.md +114 -0
- hipcortex-0.2.0/hipcortex/install/__init__.py +1 -0
- hipcortex-0.2.0/hipcortex/langchain_memory.py +238 -0
- hipcortex-0.2.0/hipcortex/llamaindex_storage.py +107 -0
- hipcortex-0.2.0/hipcortex.egg-info/PKG-INFO +108 -0
- hipcortex-0.2.0/hipcortex.egg-info/SOURCES.txt +23 -0
- hipcortex-0.2.0/hipcortex.egg-info/dependency_links.txt +1 -0
- hipcortex-0.2.0/hipcortex.egg-info/entry_points.txt +2 -0
- hipcortex-0.2.0/hipcortex.egg-info/requires.txt +28 -0
- hipcortex-0.2.0/hipcortex.egg-info/top_level.txt +1 -0
- hipcortex-0.2.0/pyproject.toml +49 -0
- hipcortex-0.2.0/setup.cfg +4 -0
- hipcortex-0.2.0/setup.py +35 -0
- hipcortex-0.2.0/tests/test_async_client.py +60 -0
- hipcortex-0.2.0/tests/test_async_langchain.py +61 -0
- hipcortex-0.2.0/tests/test_cli_install.py +137 -0
hipcortex-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hipcortex
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Persistent causal memory for AI agents — LangChain, LlamaIndex, AutoGen, CrewAI
|
|
5
|
+
Author: HipCortex Contributors
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/farmountain/HipCortex
|
|
8
|
+
Project-URL: Repository, https://github.com/farmountain/HipCortex
|
|
9
|
+
Project-URL: Issues, https://github.com/farmountain/HipCortex/issues
|
|
10
|
+
Project-URL: Benchmark, https://github.com/farmountain/HipCortex/blob/main/BENCHMARK.md
|
|
11
|
+
Keywords: ai,memory,langchain,autogen,crewai,llm,agents,rag
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Requires-Python: >=3.9
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
Requires-Dist: requests>=2.28
|
|
19
|
+
Requires-Dist: httpx>=0.27
|
|
20
|
+
Provides-Extra: langchain
|
|
21
|
+
Requires-Dist: langchain-core>=0.1; extra == "langchain"
|
|
22
|
+
Provides-Extra: llamaindex
|
|
23
|
+
Requires-Dist: llama-index-core>=0.10; extra == "llamaindex"
|
|
24
|
+
Provides-Extra: crewai
|
|
25
|
+
Requires-Dist: crewai>=0.28; extra == "crewai"
|
|
26
|
+
Requires-Dist: crewai-tools>=0.1; extra == "crewai"
|
|
27
|
+
Provides-Extra: autogen
|
|
28
|
+
Requires-Dist: pyautogen>=0.2; extra == "autogen"
|
|
29
|
+
Provides-Extra: benchmark
|
|
30
|
+
Requires-Dist: mem0ai>=0.1; extra == "benchmark"
|
|
31
|
+
Requires-Dist: tabulate>=0.9; extra == "benchmark"
|
|
32
|
+
Provides-Extra: all
|
|
33
|
+
Requires-Dist: langchain-core>=0.1; extra == "all"
|
|
34
|
+
Requires-Dist: llama-index-core>=0.10; extra == "all"
|
|
35
|
+
Requires-Dist: crewai>=0.28; extra == "all"
|
|
36
|
+
Requires-Dist: crewai-tools>=0.1; extra == "all"
|
|
37
|
+
Requires-Dist: pyautogen>=0.2; extra == "all"
|
|
38
|
+
Requires-Dist: mem0ai>=0.1; extra == "all"
|
|
39
|
+
Requires-Dist: tabulate>=0.9; extra == "all"
|
|
40
|
+
Dynamic: requires-python
|
|
41
|
+
|
|
42
|
+
# hipcortex
|
|
43
|
+
|
|
44
|
+
**Persistent causal memory for AI agents — LangChain, LlamaIndex, AutoGen, CrewAI.**
|
|
45
|
+
|
|
46
|
+
1.74ms p50 write latency. Temporal decay. Causal world model. Merkle-chained audit log. GDPR right-to-forget.
|
|
47
|
+
|
|
48
|
+
## Install
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install hipcortex
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Quick start
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
from hipcortex import HipCortexClient
|
|
58
|
+
|
|
59
|
+
client = HipCortexClient("http://localhost:3030")
|
|
60
|
+
|
|
61
|
+
# Store memory
|
|
62
|
+
client.add_memory(actor="alice", action="said", target="The meeting is at 3pm")
|
|
63
|
+
|
|
64
|
+
# Search (keyword or cosine similarity)
|
|
65
|
+
results = client.search("meeting time", limit=5)
|
|
66
|
+
|
|
67
|
+
# Stats
|
|
68
|
+
print(client.stats())
|
|
69
|
+
|
|
70
|
+
# GDPR forget
|
|
71
|
+
client.forget("alice")
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Framework integrations
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
# LangChain — drop-in for ConversationBufferMemory
|
|
78
|
+
from hipcortex.langchain_memory import HipCortexMemory
|
|
79
|
+
memory = HipCortexMemory(session_id="user-42", url="http://localhost:3030")
|
|
80
|
+
|
|
81
|
+
# LlamaIndex
|
|
82
|
+
from hipcortex.llamaindex_storage import HipCortexChatStore
|
|
83
|
+
store = HipCortexChatStore(client=client)
|
|
84
|
+
|
|
85
|
+
# AutoGen
|
|
86
|
+
from hipcortex.adapters.autogen import HipCortexAutoGenMemory
|
|
87
|
+
mem = HipCortexAutoGenMemory(client=client, agent_id="researcher")
|
|
88
|
+
agent.register_hook("process_message_before_send", mem.on_message_sent)
|
|
89
|
+
|
|
90
|
+
# CrewAI
|
|
91
|
+
from hipcortex.adapters.crewai import HipCortexRememberTool, HipCortexRecallTool
|
|
92
|
+
tools = [HipCortexRememberTool(client=client), HipCortexRecallTool(client=client)]
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Start the server
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# Self-hosted (single binary, zero deps)
|
|
99
|
+
cargo run --bin webserver --no-default-features --features "web-server,petgraph_backend"
|
|
100
|
+
|
|
101
|
+
# Fly.io
|
|
102
|
+
fly deploy
|
|
103
|
+
|
|
104
|
+
# Live demo
|
|
105
|
+
https://hipcortex.fly.dev
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Full docs:** https://github.com/farmountain/HipCortex
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# hipcortex
|
|
2
|
+
|
|
3
|
+
**Persistent causal memory for AI agents — LangChain, LlamaIndex, AutoGen, CrewAI.**
|
|
4
|
+
|
|
5
|
+
1.74ms p50 write latency. Temporal decay. Causal world model. Merkle-chained audit log. GDPR right-to-forget.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install hipcortex
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick start
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from hipcortex import HipCortexClient
|
|
17
|
+
|
|
18
|
+
client = HipCortexClient("http://localhost:3030")
|
|
19
|
+
|
|
20
|
+
# Store memory
|
|
21
|
+
client.add_memory(actor="alice", action="said", target="The meeting is at 3pm")
|
|
22
|
+
|
|
23
|
+
# Search (keyword or cosine similarity)
|
|
24
|
+
results = client.search("meeting time", limit=5)
|
|
25
|
+
|
|
26
|
+
# Stats
|
|
27
|
+
print(client.stats())
|
|
28
|
+
|
|
29
|
+
# GDPR forget
|
|
30
|
+
client.forget("alice")
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Framework integrations
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
# LangChain — drop-in for ConversationBufferMemory
|
|
37
|
+
from hipcortex.langchain_memory import HipCortexMemory
|
|
38
|
+
memory = HipCortexMemory(session_id="user-42", url="http://localhost:3030")
|
|
39
|
+
|
|
40
|
+
# LlamaIndex
|
|
41
|
+
from hipcortex.llamaindex_storage import HipCortexChatStore
|
|
42
|
+
store = HipCortexChatStore(client=client)
|
|
43
|
+
|
|
44
|
+
# AutoGen
|
|
45
|
+
from hipcortex.adapters.autogen import HipCortexAutoGenMemory
|
|
46
|
+
mem = HipCortexAutoGenMemory(client=client, agent_id="researcher")
|
|
47
|
+
agent.register_hook("process_message_before_send", mem.on_message_sent)
|
|
48
|
+
|
|
49
|
+
# CrewAI
|
|
50
|
+
from hipcortex.adapters.crewai import HipCortexRememberTool, HipCortexRecallTool
|
|
51
|
+
tools = [HipCortexRememberTool(client=client), HipCortexRecallTool(client=client)]
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Start the server
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Self-hosted (single binary, zero deps)
|
|
58
|
+
cargo run --bin webserver --no-default-features --features "web-server,petgraph_backend"
|
|
59
|
+
|
|
60
|
+
# Fly.io
|
|
61
|
+
fly deploy
|
|
62
|
+
|
|
63
|
+
# Live demo
|
|
64
|
+
https://hipcortex.fly.dev
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Full docs:** https://github.com/farmountain/HipCortex
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""HipCortex Python SDK — AI memory engine client."""
|
|
2
|
+
|
|
3
|
+
from .client import HipCortexClient
|
|
4
|
+
from .async_client import AsyncHipCortexClient
|
|
5
|
+
from .langchain_memory import HipCortexMemory, AsyncHipCortexMemory
|
|
6
|
+
from .llamaindex_storage import HipCortexStorageContext
|
|
7
|
+
|
|
8
|
+
__version__ = "0.2.0"
|
|
9
|
+
__all__ = [
|
|
10
|
+
"HipCortexClient",
|
|
11
|
+
"AsyncHipCortexClient",
|
|
12
|
+
"HipCortexMemory",
|
|
13
|
+
"AsyncHipCortexMemory",
|
|
14
|
+
"HipCortexStorageContext",
|
|
15
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Framework adapters for HipCortex — AutoGen and CrewAI."""
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"""HipCortex AutoGen adapter — targets AutoGen 0.4+ (autogen-agentchat >= 0.4).
|
|
2
|
+
|
|
3
|
+
AutoGen 0.4 changed from register_hook() to the Memory protocol.
|
|
4
|
+
|
|
5
|
+
Usage (AutoGen 0.4+):
|
|
6
|
+
from autogen_agentchat.agents import AssistantAgent
|
|
7
|
+
from hipcortex import HipCortexClient
|
|
8
|
+
from hipcortex.adapters.autogen import HipCortexAutoGenMemory
|
|
9
|
+
|
|
10
|
+
client = HipCortexClient(base_url="http://localhost:3030")
|
|
11
|
+
memory = HipCortexAutoGenMemory(client=client, agent_id="researcher")
|
|
12
|
+
agent = AssistantAgent(name="researcher", model_client=..., memory=[memory])
|
|
13
|
+
|
|
14
|
+
Usage (AutoGen 0.3 — legacy):
|
|
15
|
+
agent.register_hook("process_message_before_send", memory.on_message_sent_v03)
|
|
16
|
+
agent.register_hook("process_all_messages_before_reply", memory.on_messages_received_v03)
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
from typing import Any, Dict, List, Optional
|
|
22
|
+
|
|
23
|
+
from ..client import HipCortexClient
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
from autogen_core.memory import Memory, MemoryContent, MemoryMimeType, MemoryQueryResult
|
|
27
|
+
from autogen_core import CancellationToken
|
|
28
|
+
_AUTOGEN4_AVAILABLE = True
|
|
29
|
+
except ImportError:
|
|
30
|
+
_AUTOGEN4_AVAILABLE = False
|
|
31
|
+
class Memory: # type: ignore[no-redef]
|
|
32
|
+
pass
|
|
33
|
+
class CancellationToken: # type: ignore[no-redef]
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class HipCortexAutoGenMemory(Memory): # type: ignore[misc]
|
|
38
|
+
"""AutoGen 0.4 Memory protocol backed by HipCortex."""
|
|
39
|
+
|
|
40
|
+
def __init__(
|
|
41
|
+
self,
|
|
42
|
+
client: HipCortexClient,
|
|
43
|
+
agent_id: str = "autogen-agent",
|
|
44
|
+
top_k: int = 10,
|
|
45
|
+
) -> None:
|
|
46
|
+
self._client = client
|
|
47
|
+
self._agent_id = agent_id
|
|
48
|
+
self._top_k = top_k
|
|
49
|
+
|
|
50
|
+
# AutoGen 0.4 Memory protocol -------------------------------------------
|
|
51
|
+
|
|
52
|
+
async def add(
|
|
53
|
+
self,
|
|
54
|
+
content: Any,
|
|
55
|
+
cancellation_token: Optional[CancellationToken] = None,
|
|
56
|
+
) -> None:
|
|
57
|
+
if _AUTOGEN4_AVAILABLE and hasattr(content, "content"):
|
|
58
|
+
text = str(content.content)
|
|
59
|
+
role = getattr(content, "role", None)
|
|
60
|
+
mime = getattr(content, "mime_type", None)
|
|
61
|
+
action = "ai_message" if (
|
|
62
|
+
(role and role in ("assistant", "ai")) or
|
|
63
|
+
(mime and "assistant" in str(mime).lower())
|
|
64
|
+
) else "observation"
|
|
65
|
+
else:
|
|
66
|
+
text = str(content)
|
|
67
|
+
action = "observation"
|
|
68
|
+
self._client.add_memory(
|
|
69
|
+
actor=self._agent_id, action=action,
|
|
70
|
+
target=text, record_type="Temporal",
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
async def query(
|
|
74
|
+
self,
|
|
75
|
+
query: Any,
|
|
76
|
+
cancellation_token: Optional[CancellationToken] = None,
|
|
77
|
+
) -> Any:
|
|
78
|
+
query_text = str(getattr(query, "content", query))
|
|
79
|
+
try:
|
|
80
|
+
search_results = self._client.search(query=query_text, limit=self._top_k)
|
|
81
|
+
except Exception:
|
|
82
|
+
search_results = [
|
|
83
|
+
{"record": r, "score": 1.0}
|
|
84
|
+
for r in self._client.get_conversation_history(self._agent_id, limit=self._top_k)
|
|
85
|
+
]
|
|
86
|
+
if not _AUTOGEN4_AVAILABLE:
|
|
87
|
+
return search_results
|
|
88
|
+
memories = []
|
|
89
|
+
for item in search_results:
|
|
90
|
+
rec = item.get("record", item)
|
|
91
|
+
memories.append(MemoryContent(
|
|
92
|
+
content=rec.get("target", ""),
|
|
93
|
+
mime_type=MemoryMimeType.TEXT,
|
|
94
|
+
metadata={"score": item.get("score", 1.0), "actor": rec.get("actor", ""),
|
|
95
|
+
"action": rec.get("action", ""), "timestamp": rec.get("timestamp", "")},
|
|
96
|
+
))
|
|
97
|
+
return MemoryQueryResult(results=memories)
|
|
98
|
+
|
|
99
|
+
async def update_context(
|
|
100
|
+
self,
|
|
101
|
+
model_context: Any,
|
|
102
|
+
cancellation_token: Optional[CancellationToken] = None,
|
|
103
|
+
) -> Any:
|
|
104
|
+
records = self._client.get_conversation_history(self._agent_id, limit=self._top_k)
|
|
105
|
+
records.sort(key=lambda r: r.get("timestamp", ""))
|
|
106
|
+
if not records:
|
|
107
|
+
return {"memories_added": 0}
|
|
108
|
+
lines = [f"[{r.get('action','memory')}] {r.get('target','')}" for r in records]
|
|
109
|
+
system_msg = {"role": "system", "content": "[HipCortex memory]\n" + "\n".join(lines)}
|
|
110
|
+
if hasattr(model_context, "add_message"):
|
|
111
|
+
await model_context.add_message(system_msg)
|
|
112
|
+
elif hasattr(model_context, "messages"):
|
|
113
|
+
model_context.messages.insert(0, system_msg)
|
|
114
|
+
return {"memories_added": len(records)}
|
|
115
|
+
|
|
116
|
+
async def clear(self) -> None:
|
|
117
|
+
self._client.forget(self._agent_id)
|
|
118
|
+
|
|
119
|
+
# AutoGen 0.3 legacy hooks -----------------------------------------------
|
|
120
|
+
|
|
121
|
+
def on_message_sent_v03(self, message: Dict[str, Any], **kwargs: Any) -> Dict[str, Any]:
|
|
122
|
+
"""AutoGen 0.3 hook: process_message_before_send."""
|
|
123
|
+
content = message.get("content", "")
|
|
124
|
+
role = message.get("role", "assistant")
|
|
125
|
+
action = "ai_message" if role == "assistant" else "human_message"
|
|
126
|
+
self._client.add_memory(actor=self._agent_id, action=action, target=str(content),
|
|
127
|
+
record_type="Reflexion" if role == "assistant" else "Temporal")
|
|
128
|
+
return message
|
|
129
|
+
|
|
130
|
+
def on_messages_received_v03(
|
|
131
|
+
self, messages: List[Dict[str, Any]], **kwargs: Any
|
|
132
|
+
) -> List[Dict[str, Any]]:
|
|
133
|
+
"""AutoGen 0.3 hook: process_all_messages_before_reply."""
|
|
134
|
+
history = self._client.get_conversation_history(self._agent_id, limit=20)
|
|
135
|
+
if not history:
|
|
136
|
+
return messages
|
|
137
|
+
history.sort(key=lambda r: r.get("timestamp", ""))
|
|
138
|
+
lines = [
|
|
139
|
+
f"{'AI' if r.get('action') == 'ai_message' else 'Human'}: {r.get('target','')}"
|
|
140
|
+
for r in history
|
|
141
|
+
]
|
|
142
|
+
return [{"role": "system", "content": "[HipCortex memory]\n" + "\n".join(lines)}] + list(messages)
|
|
143
|
+
|
|
144
|
+
# Sync helpers (no AutoGen needed) ---------------------------------------
|
|
145
|
+
|
|
146
|
+
def store(self, content: str, action: str = "observation") -> Dict[str, Any]:
|
|
147
|
+
return self._client.add_memory(actor=self._agent_id, action=action,
|
|
148
|
+
target=content, record_type="Temporal")
|
|
149
|
+
|
|
150
|
+
def recall(self, limit: int = 20) -> str:
|
|
151
|
+
records = self._client.get_conversation_history(self._agent_id, limit=limit)
|
|
152
|
+
records.sort(key=lambda r: r.get("timestamp", ""))
|
|
153
|
+
return "\n".join(f"[{r.get('action','?')}] {r.get('target','')}" for r in records)
|
|
154
|
+
|
|
155
|
+
def forget_all(self) -> Dict[str, Any]:
|
|
156
|
+
return self._client.forget(self._agent_id)
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"""CrewAI tool adapter for HipCortex.
|
|
2
|
+
|
|
3
|
+
Exposes HipCortex memory operations as CrewAI ``BaseTool`` subclasses
|
|
4
|
+
so agents can store and retrieve memories as tool calls during task execution.
|
|
5
|
+
|
|
6
|
+
Usage::
|
|
7
|
+
|
|
8
|
+
from crewai import Agent, Task, Crew
|
|
9
|
+
from hipcortex import HipCortexClient
|
|
10
|
+
from hipcortex.adapters.crewai import (
|
|
11
|
+
HipCortexRememberTool,
|
|
12
|
+
HipCortexRecallTool,
|
|
13
|
+
HipCortexForgetTool,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
client = HipCortexClient(base_url="http://localhost:3000")
|
|
17
|
+
tools = [
|
|
18
|
+
HipCortexRememberTool(client=client, agent_id="researcher"),
|
|
19
|
+
HipCortexRecallTool(client=client, agent_id="researcher"),
|
|
20
|
+
HipCortexForgetTool(client=client, agent_id="researcher"),
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
researcher = Agent(
|
|
24
|
+
role="Senior Researcher",
|
|
25
|
+
goal="Research and remember findings",
|
|
26
|
+
tools=tools,
|
|
27
|
+
...
|
|
28
|
+
)
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from __future__ import annotations
|
|
32
|
+
|
|
33
|
+
from typing import Any, Optional, Type
|
|
34
|
+
|
|
35
|
+
from ..client import HipCortexClient
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
from crewai_tools import BaseTool
|
|
39
|
+
from pydantic import BaseModel, Field
|
|
40
|
+
_CREWAI_AVAILABLE = True
|
|
41
|
+
except ImportError:
|
|
42
|
+
_CREWAI_AVAILABLE = False
|
|
43
|
+
|
|
44
|
+
class BaseModel: # type: ignore[no-redef]
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
class Field: # type: ignore[no-redef]
|
|
48
|
+
def __init__(self, *a: Any, **kw: Any) -> None: ...
|
|
49
|
+
|
|
50
|
+
class BaseTool: # type: ignore[no-redef]
|
|
51
|
+
name: str = ""
|
|
52
|
+
description: str = ""
|
|
53
|
+
args_schema: Any = None
|
|
54
|
+
def _run(self, *a: Any, **kw: Any) -> str: ...
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
# ---------------------------------------------------------------------------
|
|
58
|
+
# Input schemas
|
|
59
|
+
# ---------------------------------------------------------------------------
|
|
60
|
+
|
|
61
|
+
if _CREWAI_AVAILABLE:
|
|
62
|
+
class RememberInput(BaseModel):
|
|
63
|
+
content: str = Field(..., description="Observation or fact to remember.")
|
|
64
|
+
action: str = Field(default="observation", description="Action tag (e.g. 'finding', 'decision').")
|
|
65
|
+
|
|
66
|
+
class RecallInput(BaseModel):
|
|
67
|
+
limit: int = Field(default=20, description="Max number of memories to return.")
|
|
68
|
+
|
|
69
|
+
class ForgetInput(BaseModel):
|
|
70
|
+
confirm: bool = Field(default=False, description="Set to True to confirm deletion.")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
# ---------------------------------------------------------------------------
|
|
74
|
+
# Tools
|
|
75
|
+
# ---------------------------------------------------------------------------
|
|
76
|
+
|
|
77
|
+
class HipCortexRememberTool(BaseTool): # type: ignore[misc]
|
|
78
|
+
"""CrewAI tool: store an observation in HipCortex memory."""
|
|
79
|
+
|
|
80
|
+
name: str = "hipcortex_remember"
|
|
81
|
+
description: str = (
|
|
82
|
+
"Store an important observation, finding, or decision in persistent memory. "
|
|
83
|
+
"Use this whenever you discover information worth remembering for future tasks."
|
|
84
|
+
)
|
|
85
|
+
if _CREWAI_AVAILABLE:
|
|
86
|
+
args_schema: Type[BaseModel] = RememberInput
|
|
87
|
+
|
|
88
|
+
def __init__(self, client: HipCortexClient, agent_id: str = "crewai-agent") -> None:
|
|
89
|
+
super().__init__()
|
|
90
|
+
self._client = client
|
|
91
|
+
self._agent_id = agent_id
|
|
92
|
+
|
|
93
|
+
def _run(self, content: str, action: str = "observation") -> str:
|
|
94
|
+
result = self._client.add_memory(
|
|
95
|
+
actor=self._agent_id,
|
|
96
|
+
action=action,
|
|
97
|
+
target=content,
|
|
98
|
+
record_type="Temporal",
|
|
99
|
+
)
|
|
100
|
+
if result.get("success"):
|
|
101
|
+
return f"Stored memory with id={result.get('record_id', '?')}"
|
|
102
|
+
return f"Failed to store memory: {result.get('error', 'unknown error')}"
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class HipCortexRecallTool(BaseTool): # type: ignore[misc]
|
|
106
|
+
"""CrewAI tool: retrieve recent memories from HipCortex."""
|
|
107
|
+
|
|
108
|
+
name: str = "hipcortex_recall"
|
|
109
|
+
description: str = (
|
|
110
|
+
"Retrieve recent memories and observations stored in HipCortex. "
|
|
111
|
+
"Use this to recall past findings before starting a new research task."
|
|
112
|
+
)
|
|
113
|
+
if _CREWAI_AVAILABLE:
|
|
114
|
+
args_schema: Type[BaseModel] = RecallInput
|
|
115
|
+
|
|
116
|
+
def __init__(self, client: HipCortexClient, agent_id: str = "crewai-agent") -> None:
|
|
117
|
+
super().__init__()
|
|
118
|
+
self._client = client
|
|
119
|
+
self._agent_id = agent_id
|
|
120
|
+
|
|
121
|
+
def _run(self, limit: int = 20) -> str:
|
|
122
|
+
records = self._client.get_conversation_history(self._agent_id, limit=limit)
|
|
123
|
+
if not records:
|
|
124
|
+
return "No memories found."
|
|
125
|
+
records.sort(key=lambda r: r.get("timestamp", ""))
|
|
126
|
+
lines = []
|
|
127
|
+
for i, rec in enumerate(records, 1):
|
|
128
|
+
lines.append(f"{i}. [{rec.get('action', '?')}] {rec.get('target', '')}")
|
|
129
|
+
return "\n".join(lines)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
class HipCortexForgetTool(BaseTool): # type: ignore[misc]
|
|
133
|
+
"""CrewAI tool: delete all memories for this agent (GDPR / session reset)."""
|
|
134
|
+
|
|
135
|
+
name: str = "hipcortex_forget"
|
|
136
|
+
description: str = (
|
|
137
|
+
"Delete all memories stored for this agent. "
|
|
138
|
+
"Only use this when explicitly asked to clear memory or start fresh."
|
|
139
|
+
)
|
|
140
|
+
if _CREWAI_AVAILABLE:
|
|
141
|
+
args_schema: Type[BaseModel] = ForgetInput
|
|
142
|
+
|
|
143
|
+
def __init__(self, client: HipCortexClient, agent_id: str = "crewai-agent") -> None:
|
|
144
|
+
super().__init__()
|
|
145
|
+
self._client = client
|
|
146
|
+
self._agent_id = agent_id
|
|
147
|
+
|
|
148
|
+
def _run(self, confirm: bool = False) -> str:
|
|
149
|
+
if not confirm:
|
|
150
|
+
return "Deletion not confirmed. Pass confirm=True to proceed."
|
|
151
|
+
result = self._client.forget(self._agent_id)
|
|
152
|
+
deleted = result.get("records_deleted", 0)
|
|
153
|
+
return f"Deleted {deleted} memory records for agent '{self._agent_id}'."
|