acra-cli 0.1.1__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.
- acra/__init__.py +7 -0
- acra/__main__.py +4 -0
- acra/agents/__init__.py +0 -0
- acra/agents/__pycache__/__init__.cpython-312.pyc +0 -0
- acra/agents/__pycache__/llm.cpython-312.pyc +0 -0
- acra/agents/__pycache__/llm_utils.cpython-312.pyc +0 -0
- acra/agents/coder/__init__.py +0 -0
- acra/agents/coder/__pycache__/__init__.cpython-312.pyc +0 -0
- acra/agents/coder/__pycache__/coder_agent.cpython-312.pyc +0 -0
- acra/agents/coder/__pycache__/coder_chain.cpython-312.pyc +0 -0
- acra/agents/coder/coder_agent.py +235 -0
- acra/agents/coder/coder_chain.py +204 -0
- acra/agents/critic/__init__.py +0 -0
- acra/agents/critic/__pycache__/__init__.cpython-312.pyc +0 -0
- acra/agents/critic/__pycache__/critic_agent.cpython-312.pyc +0 -0
- acra/agents/critic/__pycache__/critic_chain.cpython-312.pyc +0 -0
- acra/agents/critic/critic_agent.py +199 -0
- acra/agents/critic/critic_chain.py +268 -0
- acra/agents/executor/__init__.py +0 -0
- acra/agents/executor/__pycache__/__init__.cpython-312.pyc +0 -0
- acra/agents/executor/__pycache__/docker_runner.cpython-312.pyc +0 -0
- acra/agents/executor/__pycache__/executor_agent.cpython-312.pyc +0 -0
- acra/agents/executor/__pycache__/sandbox_runner.cpython-312.pyc +0 -0
- acra/agents/executor/docker_runner.py +114 -0
- acra/agents/executor/executor_agent.py +142 -0
- acra/agents/executor/sandbox_runner.py +144 -0
- acra/agents/human/__init__.py +0 -0
- acra/agents/human/__pycache__/__init__.cpython-312.pyc +0 -0
- acra/agents/human/__pycache__/human_node.cpython-312.pyc +0 -0
- acra/agents/human/human_node.py +37 -0
- acra/agents/llm.py +263 -0
- acra/agents/llm_utils.py +161 -0
- acra/agents/memory/__init__.py +0 -0
- acra/agents/memory/__pycache__/__init__.cpython-312.pyc +0 -0
- acra/agents/memory/__pycache__/memory_agent.cpython-312.pyc +0 -0
- acra/agents/memory/__pycache__/memory_manager.cpython-312.pyc +0 -0
- acra/agents/memory/__pycache__/retrieval.cpython-312.pyc +0 -0
- acra/agents/memory/memory_agent.py +239 -0
- acra/agents/memory/memory_manager.py +273 -0
- acra/agents/memory/retrieval.py +355 -0
- acra/agents/planner/__init__.py +0 -0
- acra/agents/planner/__pycache__/__init__.cpython-312.pyc +0 -0
- acra/agents/planner/__pycache__/planner_agent.cpython-312.pyc +0 -0
- acra/agents/planner/__pycache__/planner_chain.cpython-312.pyc +0 -0
- acra/agents/planner/planner_agent.py +97 -0
- acra/agents/planner/planner_chain.py +160 -0
- acra/agents/researcher/__init__.py +1 -0
- acra/agents/researcher/__pycache__/__init__.cpython-312.pyc +0 -0
- acra/agents/researcher/__pycache__/researcher_agent.cpython-312.pyc +0 -0
- acra/agents/researcher/__pycache__/researcher_chain.cpython-312.pyc +0 -0
- acra/agents/researcher/researcher_agent.py +231 -0
- acra/agents/researcher/researcher_chain.py +193 -0
- acra/brain/__init__.py +6 -0
- acra/brain/model_registry.py +19 -0
- acra/brain/provider_manager.py +21 -0
- acra/cli.py +52 -0
- acra/commands/__init__.py +29 -0
- acra/commands/ask.py +49 -0
- acra/commands/brain.py +58 -0
- acra/commands/config.py +25 -0
- acra/commands/context.py +30 -0
- acra/commands/graph.py +18 -0
- acra/commands/keys.py +40 -0
- acra/commands/logs.py +13 -0
- acra/commands/memory.py +27 -0
- acra/commands/plugin.py +18 -0
- acra/commands/research.py +65 -0
- acra/commands/serve.py +13 -0
- acra/commands/session.py +20 -0
- acra/commands/utils.py +12 -0
- acra/config/__init__.py +36 -0
- acra/config/__pycache__/__init__.cpython-312.pyc +0 -0
- acra/config/__pycache__/defaults.cpython-312.pyc +0 -0
- acra/config/__pycache__/profile_manager.cpython-312.pyc +0 -0
- acra/config/defaults.py +88 -0
- acra/config/profile_manager.py +87 -0
- acra/execution/__init__.py +1 -0
- acra/execution/logs/__init__.py +1 -0
- acra/execution/logs/error_logs/__init__.py +1 -0
- acra/execution/logs/execution_logs/__init__.py +1 -0
- acra/execution/sandbox/__init__.py +1 -0
- acra/execution/sandbox/docker_executor.py +209 -0
- acra/execution/sandbox/isolated_runner.py +148 -0
- acra/execution/sandbox/sandbox_manager.py +178 -0
- acra/graph/__init__.py +0 -0
- acra/graph/checkpoint.py +85 -0
- acra/graph/conditional_edges.py +103 -0
- acra/graph/edges.py +85 -0
- acra/graph/graph_visualizer.py +175 -0
- acra/graph/nodes.py +68 -0
- acra/graph/router.py +69 -0
- acra/graph/state.py +93 -0
- acra/graph/workflow.py +117 -0
- acra/memory/__init__.py +1 -0
- acra/memory/checkpoints/__init__.py +1 -0
- acra/memory/checkpoints/data/__init__.py +1 -0
- acra/memory/checkpoints/postgres_checkpoint.py +247 -0
- acra/memory/checkpoints/sqlite_checkpoint.py +309 -0
- acra/memory/chroma_db/__init__.py +1 -0
- acra/memory/conversation_memory/__init__.py +1 -0
- acra/memory/conversation_memory/long_term.py +229 -0
- acra/memory/conversation_memory/short_term.py +158 -0
- acra/memory/storage/__init__.py +1 -0
- acra/memory/vector_store/__init__.py +0 -0
- acra/memory/vector_store/chroma_store.py +260 -0
- acra/memory/vector_store/embeddings.py +43 -0
- acra/observability/__init__.py +1 -0
- acra/observability/langsmith_tracing.py +91 -0
- acra/observability/metrics.py +189 -0
- acra/observability/monitoring.py +162 -0
- acra/observability/token_tracking.py +131 -0
- acra/prompts/__init__.py +1 -0
- acra/schemas/__init__.py +0 -0
- acra/schemas/__pycache__/__init__.cpython-312.pyc +0 -0
- acra/schemas/__pycache__/coder_schema.cpython-312.pyc +0 -0
- acra/schemas/__pycache__/critic_schema.cpython-312.pyc +0 -0
- acra/schemas/__pycache__/execution_schema.cpython-312.pyc +0 -0
- acra/schemas/__pycache__/planner_schema.cpython-312.pyc +0 -0
- acra/schemas/__pycache__/researcher_schema.cpython-312.pyc +0 -0
- acra/schemas/__pycache__/shared_schema.cpython-312.pyc +0 -0
- acra/schemas/coder_schema.py +257 -0
- acra/schemas/critic_schema.py +177 -0
- acra/schemas/execution_schema.py +74 -0
- acra/schemas/planner_schema.py +129 -0
- acra/schemas/researcher_schema.py +220 -0
- acra/schemas/shared_schema.py +329 -0
- acra/tools/__init__.py +1 -0
- acra/tools/code_tools/__init__.py +1 -0
- acra/tools/code_tools/file_reader.py +156 -0
- acra/tools/code_tools/file_writer.py +108 -0
- acra/tools/code_tools/python_repl.py +72 -0
- acra/tools/code_tools/terminal_runner.py +98 -0
- acra/tools/github_tools/__init__.py +1 -0
- acra/tools/github_tools/commit_generator.py +91 -0
- acra/tools/github_tools/github_search.py +113 -0
- acra/tools/github_tools/repo_analyzer.py +138 -0
- acra/tools/integration_test_helper.py +370 -0
- acra/tools/validation_tools/__init__.py +1 -0
- acra/tools/validation_tools/dependency_checker.py +101 -0
- acra/tools/validation_tools/environment_config_validator.py +353 -0
- acra/tools/validation_tools/http_validator.py +336 -0
- acra/tools/validation_tools/response_validator.py +407 -0
- acra/tools/validation_tools/security_checker.py +93 -0
- acra/tools/validation_tools/syntax_checker.py +75 -0
- acra/tools/validation_tools/web_framework_validator.py +382 -0
- acra/tools/web_tools/__init__.py +1 -0
- acra/tools/web_tools/arxiv_search.py +110 -0
- acra/tools/web_tools/serpapi_search.py +106 -0
- acra/tools/web_tools/tavily_search.py +96 -0
- acra/ui/__init__.py +8 -0
- acra/ui/__pycache__/__init__.cpython-312.pyc +0 -0
- acra/ui/__pycache__/banner.cpython-312.pyc +0 -0
- acra/ui/__pycache__/components.cpython-312.pyc +0 -0
- acra/ui/__pycache__/shell.cpython-312.pyc +0 -0
- acra/ui/__pycache__/theme.cpython-312.pyc +0 -0
- acra/ui/banner.py +40 -0
- acra/ui/components.py +32 -0
- acra/ui/shell.py +91 -0
- acra/ui/theme.py +28 -0
- acra/utils/__init__.py +21 -0
- acra/utils/context_manager.py +20 -0
- acra/utils/keyring_manager.py +83 -0
- acra/utils/output_formatter.py +18 -0
- acra/utils/session_manager.py +59 -0
- acra_cli-0.1.1.dist-info/METADATA +616 -0
- acra_cli-0.1.1.dist-info/RECORD +169 -0
- acra_cli-0.1.1.dist-info/WHEEL +5 -0
- acra_cli-0.1.1.dist-info/licenses/LICENSE +661 -0
- acra_cli-0.1.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import logging
|
|
4
|
+
import threading
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from typing import Any, Dict, List, Optional
|
|
7
|
+
from acra.config import MEMORY_STORAGE_DIR
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# memory manager class
|
|
11
|
+
|
|
12
|
+
class MemoryManager:
|
|
13
|
+
"""
|
|
14
|
+
Centralized memory management system.
|
|
15
|
+
|
|
16
|
+
Responsibilities:
|
|
17
|
+
- Store workflow memories
|
|
18
|
+
- Retrieve historical context
|
|
19
|
+
- Persist execution history
|
|
20
|
+
- Manage long-term memory
|
|
21
|
+
- Support autonomous learning
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
session_id: str = "default_session"
|
|
27
|
+
):
|
|
28
|
+
|
|
29
|
+
self.session_id = session_id
|
|
30
|
+
self._lock = threading.Lock()
|
|
31
|
+
self._max_entries = 500
|
|
32
|
+
|
|
33
|
+
self.memory_file = os.path.join(
|
|
34
|
+
str(MEMORY_STORAGE_DIR),
|
|
35
|
+
f"{session_id}.json"
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
self.memories = self._load_memories()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# load memories
|
|
42
|
+
|
|
43
|
+
def _load_memories(self) -> List[Dict[str, Any]]:
|
|
44
|
+
"""
|
|
45
|
+
Load memories from storage.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
if not os.path.exists(self.memory_file):
|
|
49
|
+
return []
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
|
|
53
|
+
with open(
|
|
54
|
+
self.memory_file,
|
|
55
|
+
"r",
|
|
56
|
+
encoding="utf-8"
|
|
57
|
+
) as f:
|
|
58
|
+
|
|
59
|
+
return json.load(f)
|
|
60
|
+
|
|
61
|
+
except Exception as e:
|
|
62
|
+
logging.getLogger(__name__).error("MemoryManager._load_memories failed: %s", e, exc_info=True)
|
|
63
|
+
|
|
64
|
+
return []
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# save memories
|
|
68
|
+
|
|
69
|
+
def _save_memories(self) -> None:
|
|
70
|
+
"""
|
|
71
|
+
Persist memories to disk.
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
with open(
|
|
76
|
+
self.memory_file,
|
|
77
|
+
"w",
|
|
78
|
+
encoding="utf-8"
|
|
79
|
+
) as f:
|
|
80
|
+
|
|
81
|
+
json.dump(
|
|
82
|
+
self.memories,
|
|
83
|
+
f,
|
|
84
|
+
indent=2,
|
|
85
|
+
ensure_ascii=False
|
|
86
|
+
)
|
|
87
|
+
except Exception as e:
|
|
88
|
+
logging.getLogger(__name__).error("MemoryManager._save_memories failed: %s", e, exc_info=True)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
# add memory
|
|
92
|
+
|
|
93
|
+
def add_memory(
|
|
94
|
+
self,
|
|
95
|
+
memory_type: str,
|
|
96
|
+
content: Dict[str, Any]
|
|
97
|
+
) -> None:
|
|
98
|
+
"""
|
|
99
|
+
Add new memory entry with thread safety and size limits.
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
memory_entry = {
|
|
103
|
+
|
|
104
|
+
"timestamp": (
|
|
105
|
+
datetime.utcnow().isoformat()
|
|
106
|
+
),
|
|
107
|
+
|
|
108
|
+
"memory_type": memory_type,
|
|
109
|
+
|
|
110
|
+
"content": content
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
with self._lock:
|
|
114
|
+
self.memories.append(memory_entry)
|
|
115
|
+
if len(self.memories) > self._max_entries:
|
|
116
|
+
self.memories = self.memories[-self._max_entries:]
|
|
117
|
+
self._save_memories()
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
# get all memories
|
|
121
|
+
|
|
122
|
+
def get_all_memories(
|
|
123
|
+
self
|
|
124
|
+
) -> List[Dict[str, Any]]:
|
|
125
|
+
"""
|
|
126
|
+
Return all stored memories.
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
return self.memories
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
# get memories by type
|
|
133
|
+
|
|
134
|
+
def get_memories_by_type(
|
|
135
|
+
self,
|
|
136
|
+
memory_type: str
|
|
137
|
+
) -> List[Dict[str, Any]]:
|
|
138
|
+
"""
|
|
139
|
+
Retrieve memories matching type.
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
return [
|
|
143
|
+
|
|
144
|
+
memory
|
|
145
|
+
|
|
146
|
+
for memory in self.memories
|
|
147
|
+
|
|
148
|
+
if memory.get("memory_type")
|
|
149
|
+
== memory_type
|
|
150
|
+
]
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
# search memories
|
|
154
|
+
|
|
155
|
+
def search_memories(
|
|
156
|
+
self,
|
|
157
|
+
keyword: str
|
|
158
|
+
) -> List[Dict[str, Any]]:
|
|
159
|
+
"""
|
|
160
|
+
Keyword-based memory search.
|
|
161
|
+
"""
|
|
162
|
+
|
|
163
|
+
keyword = keyword.lower()
|
|
164
|
+
|
|
165
|
+
results = []
|
|
166
|
+
|
|
167
|
+
for memory in self.memories:
|
|
168
|
+
|
|
169
|
+
memory_str = json.dumps(
|
|
170
|
+
memory
|
|
171
|
+
).lower()
|
|
172
|
+
|
|
173
|
+
if keyword in memory_str:
|
|
174
|
+
|
|
175
|
+
results.append(memory)
|
|
176
|
+
|
|
177
|
+
return results
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
# get recent memories
|
|
181
|
+
|
|
182
|
+
def get_recent_memories(
|
|
183
|
+
self,
|
|
184
|
+
limit: int = 5
|
|
185
|
+
) -> List[Dict[str, Any]]:
|
|
186
|
+
"""
|
|
187
|
+
Retrieve most recent memories.
|
|
188
|
+
"""
|
|
189
|
+
|
|
190
|
+
return self.memories[-limit:]
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
# delete memory
|
|
194
|
+
|
|
195
|
+
def delete_memory(
|
|
196
|
+
self,
|
|
197
|
+
index: int
|
|
198
|
+
) -> bool:
|
|
199
|
+
"""
|
|
200
|
+
Delete memory by index.
|
|
201
|
+
"""
|
|
202
|
+
|
|
203
|
+
try:
|
|
204
|
+
|
|
205
|
+
del self.memories[index]
|
|
206
|
+
|
|
207
|
+
self._save_memories()
|
|
208
|
+
|
|
209
|
+
return True
|
|
210
|
+
|
|
211
|
+
except Exception:
|
|
212
|
+
|
|
213
|
+
return False
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
# clear memory
|
|
217
|
+
|
|
218
|
+
def clear_memory(self) -> None:
|
|
219
|
+
"""
|
|
220
|
+
Remove all stored memories.
|
|
221
|
+
"""
|
|
222
|
+
|
|
223
|
+
self.memories = []
|
|
224
|
+
|
|
225
|
+
self._save_memories()
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
# memory statistics
|
|
229
|
+
|
|
230
|
+
def get_memory_stats(self) -> Dict[str, Any]:
|
|
231
|
+
"""
|
|
232
|
+
Return memory statistics.
|
|
233
|
+
"""
|
|
234
|
+
|
|
235
|
+
memory_types = {}
|
|
236
|
+
|
|
237
|
+
for memory in self.memories:
|
|
238
|
+
|
|
239
|
+
mem_type = memory.get(
|
|
240
|
+
"memory_type",
|
|
241
|
+
"unknown"
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
memory_types[mem_type] = (
|
|
245
|
+
memory_types.get(mem_type, 0)
|
|
246
|
+
+ 1
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
return {
|
|
250
|
+
|
|
251
|
+
"session_id": self.session_id,
|
|
252
|
+
|
|
253
|
+
"total_memories": len(
|
|
254
|
+
self.memories
|
|
255
|
+
),
|
|
256
|
+
|
|
257
|
+
"memory_types": memory_types,
|
|
258
|
+
|
|
259
|
+
"memory_file": self.memory_file
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
# global memory helper
|
|
263
|
+
|
|
264
|
+
def get_memory_manager(
|
|
265
|
+
session_id: str = "default_session"
|
|
266
|
+
) -> MemoryManager:
|
|
267
|
+
"""
|
|
268
|
+
Returns memory manager instance.
|
|
269
|
+
"""
|
|
270
|
+
|
|
271
|
+
return MemoryManager(
|
|
272
|
+
session_id=session_id
|
|
273
|
+
)
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
from typing import Any, Dict, List, Optional
|
|
2
|
+
|
|
3
|
+
from acra.agents.memory.memory_manager import (
|
|
4
|
+
get_memory_manager
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# memory retrieval and context management system
|
|
9
|
+
|
|
10
|
+
class MemoryRetrieval:
|
|
11
|
+
"""
|
|
12
|
+
Memory retrieval and context management system.
|
|
13
|
+
|
|
14
|
+
Responsibilities:
|
|
15
|
+
- Retrieve relevant workflow memories
|
|
16
|
+
- Search historical execution patterns
|
|
17
|
+
- Support autonomous reasoning
|
|
18
|
+
- Provide contextual memory to agents
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(
|
|
22
|
+
self,
|
|
23
|
+
session_id: str = "default_session"
|
|
24
|
+
):
|
|
25
|
+
|
|
26
|
+
self.memory_manager = (
|
|
27
|
+
get_memory_manager(session_id)
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# get relevant memories
|
|
32
|
+
|
|
33
|
+
def get_relevant_memories(
|
|
34
|
+
self,
|
|
35
|
+
query: str,
|
|
36
|
+
limit: int = 5
|
|
37
|
+
) -> List[Dict[str, Any]]:
|
|
38
|
+
"""
|
|
39
|
+
Retrieve memories relevant to query.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
matching_memories = (
|
|
43
|
+
self.memory_manager.search_memories(
|
|
44
|
+
query
|
|
45
|
+
)
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
return matching_memories[:limit]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# get failure memories
|
|
52
|
+
|
|
53
|
+
def get_failure_memories(
|
|
54
|
+
self,
|
|
55
|
+
limit: int = 5
|
|
56
|
+
) -> List[Dict[str, Any]]:
|
|
57
|
+
"""
|
|
58
|
+
Retrieve previous failure memories.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
failure_memories = []
|
|
62
|
+
|
|
63
|
+
all_memories = (
|
|
64
|
+
self.memory_manager.get_all_memories()
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
for memory in all_memories:
|
|
68
|
+
|
|
69
|
+
content = memory.get(
|
|
70
|
+
"content",
|
|
71
|
+
{}
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
if (
|
|
75
|
+
content.get("execution_success")
|
|
76
|
+
is False
|
|
77
|
+
):
|
|
78
|
+
|
|
79
|
+
failure_memories.append(memory)
|
|
80
|
+
|
|
81
|
+
return failure_memories[-limit:]
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
# get successful patterns
|
|
85
|
+
|
|
86
|
+
def get_successful_patterns(
|
|
87
|
+
self,
|
|
88
|
+
limit: int = 5
|
|
89
|
+
) -> List[Dict[str, Any]]:
|
|
90
|
+
"""
|
|
91
|
+
Retrieve successful execution memories.
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
successful_memories = []
|
|
95
|
+
|
|
96
|
+
all_memories = (
|
|
97
|
+
self.memory_manager.get_all_memories()
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
for memory in all_memories:
|
|
101
|
+
|
|
102
|
+
content = memory.get(
|
|
103
|
+
"content",
|
|
104
|
+
{}
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
quality_score = content.get(
|
|
108
|
+
"quality_score",
|
|
109
|
+
0
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
if (
|
|
113
|
+
content.get("execution_success")
|
|
114
|
+
is True
|
|
115
|
+
and quality_score >= 8
|
|
116
|
+
):
|
|
117
|
+
|
|
118
|
+
successful_memories.append(memory)
|
|
119
|
+
|
|
120
|
+
return successful_memories[-limit:]
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
# get error solutions
|
|
124
|
+
|
|
125
|
+
def get_error_solutions(
|
|
126
|
+
self,
|
|
127
|
+
error_message: str,
|
|
128
|
+
limit: int = 3
|
|
129
|
+
) -> List[Dict[str, Any]]:
|
|
130
|
+
"""
|
|
131
|
+
Retrieve previous fixes for similar errors.
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
matching_solutions = []
|
|
135
|
+
|
|
136
|
+
all_memories = (
|
|
137
|
+
self.memory_manager.get_all_memories()
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
for memory in all_memories:
|
|
141
|
+
|
|
142
|
+
content = memory.get(
|
|
143
|
+
"content",
|
|
144
|
+
{}
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
previous_error = str(
|
|
148
|
+
content.get(
|
|
149
|
+
"error_message",
|
|
150
|
+
""
|
|
151
|
+
)
|
|
152
|
+
).lower()
|
|
153
|
+
|
|
154
|
+
if (
|
|
155
|
+
error_message.lower()
|
|
156
|
+
in previous_error
|
|
157
|
+
):
|
|
158
|
+
|
|
159
|
+
matching_solutions.append(memory)
|
|
160
|
+
|
|
161
|
+
return matching_solutions[:limit]
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
# build context for agent
|
|
165
|
+
|
|
166
|
+
def build_context_for_agent(
|
|
167
|
+
self,
|
|
168
|
+
agent_name: str,
|
|
169
|
+
query: Optional[str] = None
|
|
170
|
+
) -> Dict[str, Any]:
|
|
171
|
+
"""
|
|
172
|
+
Build contextual memory package
|
|
173
|
+
for workflow agents.
|
|
174
|
+
"""
|
|
175
|
+
|
|
176
|
+
context = {
|
|
177
|
+
|
|
178
|
+
"agent_name": agent_name,
|
|
179
|
+
|
|
180
|
+
"recent_memories": (
|
|
181
|
+
self.memory_manager
|
|
182
|
+
.get_recent_memories(limit=5)
|
|
183
|
+
),
|
|
184
|
+
|
|
185
|
+
"successful_patterns": (
|
|
186
|
+
self.get_successful_patterns()
|
|
187
|
+
),
|
|
188
|
+
|
|
189
|
+
"failure_patterns": (
|
|
190
|
+
self.get_failure_memories()
|
|
191
|
+
)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
# Query-specific memory retrieval
|
|
195
|
+
if query:
|
|
196
|
+
|
|
197
|
+
context["relevant_memories"] = (
|
|
198
|
+
self.get_relevant_memories(
|
|
199
|
+
query=query
|
|
200
|
+
)
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
return context
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
# get execution history
|
|
207
|
+
|
|
208
|
+
def get_execution_history(
|
|
209
|
+
self,
|
|
210
|
+
limit: int = 10
|
|
211
|
+
) -> List[Dict[str, Any]]:
|
|
212
|
+
"""
|
|
213
|
+
Retrieve workflow execution history.
|
|
214
|
+
"""
|
|
215
|
+
|
|
216
|
+
all_memories = (
|
|
217
|
+
self.memory_manager.get_all_memories()
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
execution_history = []
|
|
221
|
+
|
|
222
|
+
for memory in all_memories:
|
|
223
|
+
|
|
224
|
+
content = memory.get(
|
|
225
|
+
"content",
|
|
226
|
+
{}
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
execution_history.append({
|
|
230
|
+
|
|
231
|
+
"timestamp": memory.get(
|
|
232
|
+
"timestamp"
|
|
233
|
+
),
|
|
234
|
+
|
|
235
|
+
"workflow_status": content.get(
|
|
236
|
+
"workflow_status"
|
|
237
|
+
),
|
|
238
|
+
|
|
239
|
+
"execution_success": content.get(
|
|
240
|
+
"execution_success"
|
|
241
|
+
),
|
|
242
|
+
|
|
243
|
+
"quality_score": content.get(
|
|
244
|
+
"quality_score"
|
|
245
|
+
),
|
|
246
|
+
|
|
247
|
+
"retry_count": content.get(
|
|
248
|
+
"retry_count"
|
|
249
|
+
)
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
return execution_history[-limit:]
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
# get memory insights
|
|
256
|
+
|
|
257
|
+
def get_memory_insights(
|
|
258
|
+
self
|
|
259
|
+
) -> Dict[str, Any]:
|
|
260
|
+
"""
|
|
261
|
+
Analyze workflow memory trends.
|
|
262
|
+
"""
|
|
263
|
+
|
|
264
|
+
all_memories = (
|
|
265
|
+
self.memory_manager.get_all_memories()
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
total_memories = len(all_memories)
|
|
269
|
+
|
|
270
|
+
successful_runs = 0
|
|
271
|
+
|
|
272
|
+
failed_runs = 0
|
|
273
|
+
|
|
274
|
+
avg_quality = 0
|
|
275
|
+
|
|
276
|
+
quality_scores = []
|
|
277
|
+
|
|
278
|
+
for memory in all_memories:
|
|
279
|
+
|
|
280
|
+
content = memory.get(
|
|
281
|
+
"content",
|
|
282
|
+
{}
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
if content.get(
|
|
286
|
+
"execution_success"
|
|
287
|
+
) is True:
|
|
288
|
+
|
|
289
|
+
successful_runs += 1
|
|
290
|
+
|
|
291
|
+
elif content.get(
|
|
292
|
+
"execution_success"
|
|
293
|
+
) is False:
|
|
294
|
+
|
|
295
|
+
failed_runs += 1
|
|
296
|
+
|
|
297
|
+
score = content.get(
|
|
298
|
+
"quality_score"
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
if score is not None:
|
|
302
|
+
|
|
303
|
+
quality_scores.append(score)
|
|
304
|
+
|
|
305
|
+
if quality_scores:
|
|
306
|
+
|
|
307
|
+
avg_quality = (
|
|
308
|
+
sum(quality_scores)
|
|
309
|
+
/ len(quality_scores)
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
success_rate = 0
|
|
313
|
+
|
|
314
|
+
total_runs = (
|
|
315
|
+
successful_runs + failed_runs
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
if total_runs > 0:
|
|
319
|
+
|
|
320
|
+
success_rate = (
|
|
321
|
+
successful_runs / total_runs
|
|
322
|
+
) * 100
|
|
323
|
+
|
|
324
|
+
return {
|
|
325
|
+
|
|
326
|
+
"total_memories": total_memories,
|
|
327
|
+
|
|
328
|
+
"successful_runs": successful_runs,
|
|
329
|
+
|
|
330
|
+
"failed_runs": failed_runs,
|
|
331
|
+
|
|
332
|
+
"success_rate": round(
|
|
333
|
+
success_rate,
|
|
334
|
+
2
|
|
335
|
+
),
|
|
336
|
+
|
|
337
|
+
"average_quality_score": round(
|
|
338
|
+
avg_quality,
|
|
339
|
+
2
|
|
340
|
+
)
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
#global retrieval helper
|
|
345
|
+
|
|
346
|
+
def get_memory_retrieval(
|
|
347
|
+
session_id: str = "default_session"
|
|
348
|
+
) -> MemoryRetrieval:
|
|
349
|
+
"""
|
|
350
|
+
Returns memory retrieval system.
|
|
351
|
+
"""
|
|
352
|
+
|
|
353
|
+
return MemoryRetrieval(
|
|
354
|
+
session_id=session_id
|
|
355
|
+
)
|
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
Binary file
|