crewlayer 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.
- crewlayer/__init__.py +54 -0
- crewlayer/_actions.py +153 -0
- crewlayer/_client.py +87 -0
- crewlayer/_context.py +107 -0
- crewlayer/_exceptions.py +71 -0
- crewlayer/_http.py +101 -0
- crewlayer/_memory.py +192 -0
- crewlayer/_types.py +242 -0
- crewlayer/integrations/__init__.py +6 -0
- crewlayer/integrations/autogen.py +538 -0
- crewlayer/integrations/crewai.py +215 -0
- crewlayer/integrations/langchain.py +404 -0
- crewlayer/integrations/llamaindex.py +527 -0
- crewlayer/py.typed +0 -0
- crewlayer-0.1.0.dist-info/METADATA +232 -0
- crewlayer-0.1.0.dist-info/RECORD +17 -0
- crewlayer-0.1.0.dist-info/WHEEL +4 -0
crewlayer/_memory.py
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"""Memory resource clients — sync and async."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from crewlayer._http import AsyncTransport, SyncTransport
|
|
7
|
+
from crewlayer._types import (
|
|
8
|
+
ExtractResult,
|
|
9
|
+
MemoryPage,
|
|
10
|
+
RecallResult,
|
|
11
|
+
ShortMemory,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class MemoryClient:
|
|
16
|
+
"""Synchronous memory operations."""
|
|
17
|
+
|
|
18
|
+
def __init__(self, http: SyncTransport) -> None:
|
|
19
|
+
self._http = http
|
|
20
|
+
|
|
21
|
+
def append(
|
|
22
|
+
self,
|
|
23
|
+
agent_id: str,
|
|
24
|
+
role: str,
|
|
25
|
+
content: str,
|
|
26
|
+
*,
|
|
27
|
+
session_id: str = "default",
|
|
28
|
+
metadata: dict[str, Any] | None = None,
|
|
29
|
+
) -> ShortMemory:
|
|
30
|
+
"""Append a message to the agent's short-term session memory."""
|
|
31
|
+
data = self._http.request(
|
|
32
|
+
"POST",
|
|
33
|
+
f"/v1/agents/{agent_id}/memory/messages",
|
|
34
|
+
params={"session_id": session_id},
|
|
35
|
+
json={"role": role, "content": content, "metadata": metadata or {}},
|
|
36
|
+
)
|
|
37
|
+
return ShortMemory._from(data)
|
|
38
|
+
|
|
39
|
+
def messages(
|
|
40
|
+
self,
|
|
41
|
+
agent_id: str,
|
|
42
|
+
*,
|
|
43
|
+
session_id: str = "default",
|
|
44
|
+
limit: int = 50,
|
|
45
|
+
) -> ShortMemory:
|
|
46
|
+
"""Retrieve recent messages from the agent's session memory."""
|
|
47
|
+
data = self._http.request(
|
|
48
|
+
"GET",
|
|
49
|
+
f"/v1/agents/{agent_id}/memory/messages",
|
|
50
|
+
params={"session_id": session_id, "limit": limit},
|
|
51
|
+
)
|
|
52
|
+
return ShortMemory._from(data)
|
|
53
|
+
|
|
54
|
+
def recall(
|
|
55
|
+
self,
|
|
56
|
+
agent_id: str,
|
|
57
|
+
query: str,
|
|
58
|
+
*,
|
|
59
|
+
limit: int = 10,
|
|
60
|
+
min_similarity: float = 0.0,
|
|
61
|
+
) -> RecallResult:
|
|
62
|
+
"""Semantic search over long-term memories using the query text."""
|
|
63
|
+
data = self._http.request(
|
|
64
|
+
"POST",
|
|
65
|
+
f"/v1/agents/{agent_id}/memory/recall",
|
|
66
|
+
json={"query": query, "limit": limit, "min_similarity": min_similarity},
|
|
67
|
+
)
|
|
68
|
+
return RecallResult._from(data)
|
|
69
|
+
|
|
70
|
+
def extract(
|
|
71
|
+
self,
|
|
72
|
+
agent_id: str,
|
|
73
|
+
conversation: str,
|
|
74
|
+
*,
|
|
75
|
+
session_id: str | None = None,
|
|
76
|
+
) -> ExtractResult:
|
|
77
|
+
"""Extract facts from a conversation with Claude and persist as long-term memories."""
|
|
78
|
+
data = self._http.request(
|
|
79
|
+
"POST",
|
|
80
|
+
f"/v1/agents/{agent_id}/memory/extract",
|
|
81
|
+
json={"conversation": conversation, "session_id": session_id},
|
|
82
|
+
)
|
|
83
|
+
return ExtractResult._from(data)
|
|
84
|
+
|
|
85
|
+
def list(
|
|
86
|
+
self,
|
|
87
|
+
agent_id: str,
|
|
88
|
+
*,
|
|
89
|
+
page: int = 1,
|
|
90
|
+
page_size: int = 20,
|
|
91
|
+
) -> MemoryPage:
|
|
92
|
+
"""List all long-term memories for an agent, paginated."""
|
|
93
|
+
data = self._http.request(
|
|
94
|
+
"GET",
|
|
95
|
+
f"/v1/agents/{agent_id}/memory",
|
|
96
|
+
params={"page": page, "page_size": page_size},
|
|
97
|
+
)
|
|
98
|
+
return MemoryPage._from(data)
|
|
99
|
+
|
|
100
|
+
def delete(self, agent_id: str, memory_id: str) -> None:
|
|
101
|
+
"""Soft-delete a long-term memory record."""
|
|
102
|
+
self._http.request("DELETE", f"/v1/agents/{agent_id}/memory/{memory_id}")
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class AsyncMemoryClient:
|
|
106
|
+
"""Asynchronous memory operations."""
|
|
107
|
+
|
|
108
|
+
def __init__(self, http: AsyncTransport) -> None:
|
|
109
|
+
self._http = http
|
|
110
|
+
|
|
111
|
+
async def append(
|
|
112
|
+
self,
|
|
113
|
+
agent_id: str,
|
|
114
|
+
role: str,
|
|
115
|
+
content: str,
|
|
116
|
+
*,
|
|
117
|
+
session_id: str = "default",
|
|
118
|
+
metadata: dict[str, Any] | None = None,
|
|
119
|
+
) -> ShortMemory:
|
|
120
|
+
"""Append a message to the agent's short-term session memory."""
|
|
121
|
+
data = await self._http.request(
|
|
122
|
+
"POST",
|
|
123
|
+
f"/v1/agents/{agent_id}/memory/messages",
|
|
124
|
+
params={"session_id": session_id},
|
|
125
|
+
json={"role": role, "content": content, "metadata": metadata or {}},
|
|
126
|
+
)
|
|
127
|
+
return ShortMemory._from(data)
|
|
128
|
+
|
|
129
|
+
async def messages(
|
|
130
|
+
self,
|
|
131
|
+
agent_id: str,
|
|
132
|
+
*,
|
|
133
|
+
session_id: str = "default",
|
|
134
|
+
limit: int = 50,
|
|
135
|
+
) -> ShortMemory:
|
|
136
|
+
"""Retrieve recent messages from the agent's session memory."""
|
|
137
|
+
data = await self._http.request(
|
|
138
|
+
"GET",
|
|
139
|
+
f"/v1/agents/{agent_id}/memory/messages",
|
|
140
|
+
params={"session_id": session_id, "limit": limit},
|
|
141
|
+
)
|
|
142
|
+
return ShortMemory._from(data)
|
|
143
|
+
|
|
144
|
+
async def recall(
|
|
145
|
+
self,
|
|
146
|
+
agent_id: str,
|
|
147
|
+
query: str,
|
|
148
|
+
*,
|
|
149
|
+
limit: int = 10,
|
|
150
|
+
min_similarity: float = 0.0,
|
|
151
|
+
) -> RecallResult:
|
|
152
|
+
"""Semantic search over long-term memories using the query text."""
|
|
153
|
+
data = await self._http.request(
|
|
154
|
+
"POST",
|
|
155
|
+
f"/v1/agents/{agent_id}/memory/recall",
|
|
156
|
+
json={"query": query, "limit": limit, "min_similarity": min_similarity},
|
|
157
|
+
)
|
|
158
|
+
return RecallResult._from(data)
|
|
159
|
+
|
|
160
|
+
async def extract(
|
|
161
|
+
self,
|
|
162
|
+
agent_id: str,
|
|
163
|
+
conversation: str,
|
|
164
|
+
*,
|
|
165
|
+
session_id: str | None = None,
|
|
166
|
+
) -> ExtractResult:
|
|
167
|
+
"""Extract facts from a conversation with Claude and persist as long-term memories."""
|
|
168
|
+
data = await self._http.request(
|
|
169
|
+
"POST",
|
|
170
|
+
f"/v1/agents/{agent_id}/memory/extract",
|
|
171
|
+
json={"conversation": conversation, "session_id": session_id},
|
|
172
|
+
)
|
|
173
|
+
return ExtractResult._from(data)
|
|
174
|
+
|
|
175
|
+
async def list(
|
|
176
|
+
self,
|
|
177
|
+
agent_id: str,
|
|
178
|
+
*,
|
|
179
|
+
page: int = 1,
|
|
180
|
+
page_size: int = 20,
|
|
181
|
+
) -> MemoryPage:
|
|
182
|
+
"""List all long-term memories for an agent, paginated."""
|
|
183
|
+
data = await self._http.request(
|
|
184
|
+
"GET",
|
|
185
|
+
f"/v1/agents/{agent_id}/memory",
|
|
186
|
+
params={"page": page, "page_size": page_size},
|
|
187
|
+
)
|
|
188
|
+
return MemoryPage._from(data)
|
|
189
|
+
|
|
190
|
+
async def delete(self, agent_id: str, memory_id: str) -> None:
|
|
191
|
+
"""Soft-delete a long-term memory record."""
|
|
192
|
+
await self._http.request("DELETE", f"/v1/agents/{agent_id}/memory/{memory_id}")
|
crewlayer/_types.py
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
"""Response dataclasses returned by the CrewLayer SDK."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
# ---------------------------------------------------------------------------
|
|
8
|
+
# Memory
|
|
9
|
+
# ---------------------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class Message:
|
|
13
|
+
"""A single message in short-term (session) memory."""
|
|
14
|
+
role: str
|
|
15
|
+
content: str
|
|
16
|
+
metadata: dict[str, Any] = field(default_factory=dict)
|
|
17
|
+
|
|
18
|
+
@classmethod
|
|
19
|
+
def _from(cls, d: dict[str, Any]) -> Message:
|
|
20
|
+
return cls(role=d["role"], content=d["content"], metadata=d.get("metadata", {}))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass
|
|
24
|
+
class ShortMemory:
|
|
25
|
+
"""Short-term memory for a session — a list of recent messages."""
|
|
26
|
+
session_id: str
|
|
27
|
+
messages: list[Message]
|
|
28
|
+
count: int
|
|
29
|
+
|
|
30
|
+
@classmethod
|
|
31
|
+
def _from(cls, d: dict[str, Any]) -> ShortMemory:
|
|
32
|
+
return cls(
|
|
33
|
+
session_id=d["session_id"],
|
|
34
|
+
messages=[Message._from(m) for m in d["messages"]],
|
|
35
|
+
count=d["count"],
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass
|
|
40
|
+
class MemoryItem:
|
|
41
|
+
"""A single long-term memory record."""
|
|
42
|
+
id: str
|
|
43
|
+
agent_id: str
|
|
44
|
+
content: str
|
|
45
|
+
importance: float
|
|
46
|
+
tags: list[str]
|
|
47
|
+
created_at: str
|
|
48
|
+
summary: str | None = None
|
|
49
|
+
similarity: float | None = None
|
|
50
|
+
|
|
51
|
+
@classmethod
|
|
52
|
+
def _from(cls, d: dict[str, Any]) -> MemoryItem:
|
|
53
|
+
return cls(
|
|
54
|
+
id=d["id"],
|
|
55
|
+
agent_id=d["agent_id"],
|
|
56
|
+
content=d["content"],
|
|
57
|
+
importance=d["importance"],
|
|
58
|
+
tags=d["tags"],
|
|
59
|
+
created_at=d["created_at"],
|
|
60
|
+
summary=d.get("summary"),
|
|
61
|
+
similarity=d.get("similarity"),
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@dataclass
|
|
66
|
+
class RecallResult:
|
|
67
|
+
"""Semantic recall results ranked by similarity to the query."""
|
|
68
|
+
query: str
|
|
69
|
+
results: list[MemoryItem]
|
|
70
|
+
|
|
71
|
+
@classmethod
|
|
72
|
+
def _from(cls, d: dict[str, Any]) -> RecallResult:
|
|
73
|
+
return cls(query=d["query"], results=[MemoryItem._from(r) for r in d["results"]])
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@dataclass
|
|
77
|
+
class ExtractResult:
|
|
78
|
+
"""Result of extracting facts from a conversation."""
|
|
79
|
+
extracted_count: int
|
|
80
|
+
memory_ids: list[str]
|
|
81
|
+
|
|
82
|
+
@classmethod
|
|
83
|
+
def _from(cls, d: dict[str, Any]) -> ExtractResult:
|
|
84
|
+
return cls(extracted_count=d["extracted_count"], memory_ids=d["memory_ids"])
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@dataclass
|
|
88
|
+
class MemoryPage:
|
|
89
|
+
"""Paginated list of long-term memory records."""
|
|
90
|
+
items: list[MemoryItem]
|
|
91
|
+
total: int
|
|
92
|
+
page: int
|
|
93
|
+
page_size: int
|
|
94
|
+
|
|
95
|
+
@classmethod
|
|
96
|
+
def _from(cls, d: dict[str, Any]) -> MemoryPage:
|
|
97
|
+
return cls(
|
|
98
|
+
items=[MemoryItem._from(i) for i in d["items"]],
|
|
99
|
+
total=d["total"],
|
|
100
|
+
page=d["page"],
|
|
101
|
+
page_size=d["page_size"],
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
# ---------------------------------------------------------------------------
|
|
106
|
+
# Actions
|
|
107
|
+
# ---------------------------------------------------------------------------
|
|
108
|
+
|
|
109
|
+
@dataclass
|
|
110
|
+
class ActionRecord:
|
|
111
|
+
"""An immutable action log entry."""
|
|
112
|
+
id: str
|
|
113
|
+
tenant_id: str
|
|
114
|
+
agent_id: str
|
|
115
|
+
tool_name: str
|
|
116
|
+
input_params: dict[str, Any]
|
|
117
|
+
output_result: dict[str, Any]
|
|
118
|
+
status: str
|
|
119
|
+
timestamp: str
|
|
120
|
+
session_id: str | None = None
|
|
121
|
+
duration_ms: int | None = None
|
|
122
|
+
error_msg: str | None = None
|
|
123
|
+
metadata: dict[str, Any] = field(default_factory=dict)
|
|
124
|
+
|
|
125
|
+
@classmethod
|
|
126
|
+
def _from(cls, d: dict[str, Any]) -> ActionRecord:
|
|
127
|
+
return cls(
|
|
128
|
+
id=d["id"],
|
|
129
|
+
tenant_id=d["tenant_id"],
|
|
130
|
+
agent_id=d["agent_id"],
|
|
131
|
+
tool_name=d["tool_name"],
|
|
132
|
+
input_params=d["input_params"],
|
|
133
|
+
output_result=d["output_result"],
|
|
134
|
+
status=d["status"],
|
|
135
|
+
timestamp=d["timestamp"],
|
|
136
|
+
session_id=d.get("session_id"),
|
|
137
|
+
duration_ms=d.get("duration_ms"),
|
|
138
|
+
error_msg=d.get("error_msg"),
|
|
139
|
+
metadata=d.get("metadata", {}),
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
@dataclass
|
|
144
|
+
class ActionPage:
|
|
145
|
+
"""Cursor-paginated list of action records."""
|
|
146
|
+
items: list[ActionRecord]
|
|
147
|
+
count: int
|
|
148
|
+
next_cursor: str | None
|
|
149
|
+
|
|
150
|
+
@classmethod
|
|
151
|
+
def _from(cls, d: dict[str, Any]) -> ActionPage:
|
|
152
|
+
return cls(
|
|
153
|
+
items=[ActionRecord._from(i) for i in d["items"]],
|
|
154
|
+
count=d["count"],
|
|
155
|
+
next_cursor=d.get("next_cursor"),
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@dataclass
|
|
160
|
+
class ToolStat:
|
|
161
|
+
"""Aggregate statistics for a single tool."""
|
|
162
|
+
tool_name: str
|
|
163
|
+
count: int
|
|
164
|
+
error_rate: float
|
|
165
|
+
avg_duration_ms: float | None = None
|
|
166
|
+
|
|
167
|
+
@classmethod
|
|
168
|
+
def _from(cls, d: dict[str, Any]) -> ToolStat:
|
|
169
|
+
return cls(
|
|
170
|
+
tool_name=d["tool_name"],
|
|
171
|
+
count=d["count"],
|
|
172
|
+
error_rate=d["error_rate"],
|
|
173
|
+
avg_duration_ms=d.get("avg_duration_ms"),
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
@dataclass
|
|
178
|
+
class ActionStats:
|
|
179
|
+
"""Aggregate action statistics for an agent."""
|
|
180
|
+
total_actions: int
|
|
181
|
+
error_rate: float
|
|
182
|
+
by_tool: list[ToolStat]
|
|
183
|
+
avg_duration_ms: float | None = None
|
|
184
|
+
|
|
185
|
+
@classmethod
|
|
186
|
+
def _from(cls, d: dict[str, Any]) -> ActionStats:
|
|
187
|
+
return cls(
|
|
188
|
+
total_actions=d["total_actions"],
|
|
189
|
+
error_rate=d["error_rate"],
|
|
190
|
+
avg_duration_ms=d.get("avg_duration_ms"),
|
|
191
|
+
by_tool=[ToolStat._from(t) for t in d["by_tool"]],
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
# ---------------------------------------------------------------------------
|
|
196
|
+
# Context
|
|
197
|
+
# ---------------------------------------------------------------------------
|
|
198
|
+
|
|
199
|
+
@dataclass
|
|
200
|
+
class ContextEntry:
|
|
201
|
+
"""A single blackboard context entry."""
|
|
202
|
+
id: str
|
|
203
|
+
tenant_id: str
|
|
204
|
+
namespace: str
|
|
205
|
+
key: str
|
|
206
|
+
value: dict[str, Any]
|
|
207
|
+
version: int
|
|
208
|
+
created_at: str
|
|
209
|
+
updated_at: str
|
|
210
|
+
written_by: str | None = None
|
|
211
|
+
expires_at: str | None = None
|
|
212
|
+
|
|
213
|
+
@classmethod
|
|
214
|
+
def _from(cls, d: dict[str, Any]) -> ContextEntry:
|
|
215
|
+
return cls(
|
|
216
|
+
id=d["id"],
|
|
217
|
+
tenant_id=d["tenant_id"],
|
|
218
|
+
namespace=d["namespace"],
|
|
219
|
+
key=d["key"],
|
|
220
|
+
value=d["value"],
|
|
221
|
+
version=d["version"],
|
|
222
|
+
created_at=d["created_at"],
|
|
223
|
+
updated_at=d["updated_at"],
|
|
224
|
+
written_by=d.get("written_by"),
|
|
225
|
+
expires_at=d.get("expires_at"),
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
@dataclass
|
|
230
|
+
class ContextNamespace:
|
|
231
|
+
"""All non-expired entries in a namespace."""
|
|
232
|
+
namespace: str
|
|
233
|
+
entries: list[ContextEntry]
|
|
234
|
+
count: int
|
|
235
|
+
|
|
236
|
+
@classmethod
|
|
237
|
+
def _from(cls, d: dict[str, Any]) -> ContextNamespace:
|
|
238
|
+
return cls(
|
|
239
|
+
namespace=d["namespace"],
|
|
240
|
+
entries=[ContextEntry._from(e) for e in d["entries"]],
|
|
241
|
+
count=d["count"],
|
|
242
|
+
)
|