claude-mpm 4.1.2__py3-none-any.whl → 4.1.4__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.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/BASE_AGENT_TEMPLATE.md +16 -19
- claude_mpm/agents/MEMORY.md +21 -49
- claude_mpm/agents/templates/OPTIMIZATION_REPORT.md +156 -0
- claude_mpm/agents/templates/api_qa.json +36 -116
- claude_mpm/agents/templates/backup/data_engineer_agent_20250726_234551.json +42 -9
- claude_mpm/agents/templates/backup/documentation_agent_20250726_234551.json +29 -6
- claude_mpm/agents/templates/backup/engineer_agent_20250726_234551.json +34 -6
- claude_mpm/agents/templates/backup/ops_agent_20250726_234551.json +41 -9
- claude_mpm/agents/templates/backup/qa_agent_20250726_234551.json +30 -8
- claude_mpm/agents/templates/backup/research_agent_2025011_234551.json +2 -2
- claude_mpm/agents/templates/backup/research_agent_20250726_234551.json +29 -6
- claude_mpm/agents/templates/backup/research_memory_efficient.json +2 -2
- claude_mpm/agents/templates/backup/security_agent_20250726_234551.json +41 -9
- claude_mpm/agents/templates/backup/version_control_agent_20250726_234551.json +23 -7
- claude_mpm/agents/templates/code_analyzer.json +18 -36
- claude_mpm/agents/templates/data_engineer.json +43 -14
- claude_mpm/agents/templates/documentation.json +55 -74
- claude_mpm/agents/templates/engineer.json +57 -40
- claude_mpm/agents/templates/imagemagick.json +7 -2
- claude_mpm/agents/templates/memory_manager.json +1 -1
- claude_mpm/agents/templates/ops.json +36 -4
- claude_mpm/agents/templates/project_organizer.json +23 -71
- claude_mpm/agents/templates/qa.json +34 -2
- claude_mpm/agents/templates/refactoring_engineer.json +9 -5
- claude_mpm/agents/templates/research.json +36 -4
- claude_mpm/agents/templates/security.json +29 -2
- claude_mpm/agents/templates/ticketing.json +3 -3
- claude_mpm/agents/templates/vercel_ops_agent.json +2 -2
- claude_mpm/agents/templates/version_control.json +28 -2
- claude_mpm/agents/templates/web_qa.json +38 -151
- claude_mpm/agents/templates/web_ui.json +2 -2
- claude_mpm/cli/commands/agent_manager.py +221 -1
- claude_mpm/cli/commands/agents.py +556 -1009
- claude_mpm/cli/commands/memory.py +248 -927
- claude_mpm/cli/commands/run.py +139 -484
- claude_mpm/cli/parsers/agent_manager_parser.py +34 -0
- claude_mpm/cli/startup_logging.py +76 -0
- claude_mpm/core/agent_registry.py +6 -10
- claude_mpm/core/framework_loader.py +205 -595
- claude_mpm/core/log_manager.py +49 -1
- claude_mpm/core/logging_config.py +2 -4
- claude_mpm/hooks/claude_hooks/event_handlers.py +7 -117
- claude_mpm/hooks/claude_hooks/hook_handler.py +91 -755
- claude_mpm/hooks/claude_hooks/hook_handler_original.py +1040 -0
- claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +347 -0
- claude_mpm/hooks/claude_hooks/services/__init__.py +13 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +190 -0
- claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
- claude_mpm/hooks/claude_hooks/services/state_manager.py +282 -0
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +42 -454
- claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
- claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
- claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
- claude_mpm/services/agents/memory/agent_memory_manager.py +42 -508
- claude_mpm/services/agents/memory/memory_categorization_service.py +165 -0
- claude_mpm/services/agents/memory/memory_file_service.py +103 -0
- claude_mpm/services/agents/memory/memory_format_service.py +201 -0
- claude_mpm/services/agents/memory/memory_limits_service.py +99 -0
- claude_mpm/services/agents/registry/__init__.py +1 -1
- claude_mpm/services/cli/__init__.py +18 -0
- claude_mpm/services/cli/agent_cleanup_service.py +407 -0
- claude_mpm/services/cli/agent_dependency_service.py +395 -0
- claude_mpm/services/cli/agent_listing_service.py +463 -0
- claude_mpm/services/cli/agent_output_formatter.py +605 -0
- claude_mpm/services/cli/agent_validation_service.py +589 -0
- claude_mpm/services/cli/dashboard_launcher.py +424 -0
- claude_mpm/services/cli/memory_crud_service.py +617 -0
- claude_mpm/services/cli/memory_output_formatter.py +604 -0
- claude_mpm/services/cli/session_manager.py +513 -0
- claude_mpm/services/cli/socketio_manager.py +498 -0
- claude_mpm/services/cli/startup_checker.py +370 -0
- claude_mpm/services/core/cache_manager.py +311 -0
- claude_mpm/services/core/memory_manager.py +637 -0
- claude_mpm/services/core/path_resolver.py +498 -0
- claude_mpm/services/core/service_container.py +520 -0
- claude_mpm/services/core/service_interfaces.py +436 -0
- claude_mpm/services/diagnostics/checks/agent_check.py +65 -19
- claude_mpm/services/memory/router.py +116 -10
- {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.4.dist-info}/METADATA +1 -1
- {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.4.dist-info}/RECORD +86 -55
- claude_mpm/cli/commands/run_config_checker.py +0 -159
- {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.4.dist-info}/WHEEL +0 -0
- {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.4.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.4.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.4.dist-info}/top_level.txt +0 -0
|
@@ -13,13 +13,13 @@ DESIGN DECISIONS:
|
|
|
13
13
|
|
|
14
14
|
import json
|
|
15
15
|
import os
|
|
16
|
-
from datetime import datetime
|
|
17
16
|
from pathlib import Path
|
|
18
17
|
from typing import Any, Dict
|
|
19
18
|
|
|
20
|
-
from ...core.logger import get_logger
|
|
21
19
|
from ...core.shared.config_loader import ConfigLoader
|
|
22
20
|
from ...services.agents.memory import AgentMemoryManager
|
|
21
|
+
from ...services.cli.memory_crud_service import MemoryCRUDService
|
|
22
|
+
from ...services.cli.memory_output_formatter import MemoryOutputFormatter
|
|
23
23
|
from ..shared.base_command import CommandResult, MemoryCommand
|
|
24
24
|
|
|
25
25
|
|
|
@@ -29,6 +29,8 @@ class MemoryManagementCommand(MemoryCommand):
|
|
|
29
29
|
def __init__(self):
|
|
30
30
|
super().__init__("memory")
|
|
31
31
|
self._memory_manager = None
|
|
32
|
+
self._formatter = None
|
|
33
|
+
self._crud_service = None
|
|
32
34
|
|
|
33
35
|
@property
|
|
34
36
|
def memory_manager(self):
|
|
@@ -42,6 +44,22 @@ class MemoryManagementCommand(MemoryCommand):
|
|
|
42
44
|
self._memory_manager = AgentMemoryManager(config, current_dir)
|
|
43
45
|
return self._memory_manager
|
|
44
46
|
|
|
47
|
+
@property
|
|
48
|
+
def formatter(self):
|
|
49
|
+
"""Get formatter instance (lazy loaded)."""
|
|
50
|
+
if self._formatter is None:
|
|
51
|
+
# Check if quiet mode is requested
|
|
52
|
+
quiet = os.environ.get("CLAUDE_MPM_QUIET", "false").lower() == "true"
|
|
53
|
+
self._formatter = MemoryOutputFormatter(quiet=quiet)
|
|
54
|
+
return self._formatter
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def crud_service(self):
|
|
58
|
+
"""Get CRUD service instance (lazy loaded)."""
|
|
59
|
+
if self._crud_service is None:
|
|
60
|
+
self._crud_service = MemoryCRUDService(memory_manager=self.memory_manager)
|
|
61
|
+
return self._crud_service
|
|
62
|
+
|
|
45
63
|
def validate_args(self, args) -> str:
|
|
46
64
|
"""Validate command arguments."""
|
|
47
65
|
# Check if memory command is valid
|
|
@@ -110,8 +128,10 @@ class MemoryManagementCommand(MemoryCommand):
|
|
|
110
128
|
return CommandResult.success_result(
|
|
111
129
|
"Memory status retrieved", data=status_data
|
|
112
130
|
)
|
|
113
|
-
# Text output using
|
|
114
|
-
|
|
131
|
+
# Text output using formatter
|
|
132
|
+
status = self.memory_manager.get_memory_status()
|
|
133
|
+
output = self.formatter.format_status(status)
|
|
134
|
+
print(output)
|
|
115
135
|
return CommandResult.success_result("Memory status displayed")
|
|
116
136
|
|
|
117
137
|
except Exception as e:
|
|
@@ -120,112 +140,150 @@ class MemoryManagementCommand(MemoryCommand):
|
|
|
120
140
|
|
|
121
141
|
def _get_status_data(self) -> Dict[str, Any]:
|
|
122
142
|
"""Get memory status as structured data."""
|
|
123
|
-
|
|
143
|
+
# Use CRUD service to list memories with stats
|
|
144
|
+
result = self.crud_service.list_memories(include_stats=True)
|
|
124
145
|
|
|
125
|
-
if not
|
|
146
|
+
if not result.get("success"):
|
|
126
147
|
return {
|
|
127
|
-
"
|
|
148
|
+
"error": result.get("error", "Failed to get status"),
|
|
128
149
|
"exists": False,
|
|
129
150
|
"agents": [],
|
|
130
151
|
"total_size_kb": 0,
|
|
131
152
|
"total_files": 0,
|
|
132
153
|
}
|
|
133
154
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
"file": memory_file.name,
|
|
146
|
-
"size_kb": size / 1024,
|
|
147
|
-
"path": str(memory_file),
|
|
148
|
-
}
|
|
149
|
-
)
|
|
155
|
+
# Transform CRUD service result to expected format
|
|
156
|
+
memories = result.get("memories", [])
|
|
157
|
+
agents = [
|
|
158
|
+
{
|
|
159
|
+
"agent_id": mem["agent_id"],
|
|
160
|
+
"file": mem["file"],
|
|
161
|
+
"size_kb": mem.get("size_kb", 0),
|
|
162
|
+
"path": mem["path"],
|
|
163
|
+
}
|
|
164
|
+
for mem in memories
|
|
165
|
+
]
|
|
150
166
|
|
|
151
167
|
return {
|
|
152
|
-
"memory_directory":
|
|
153
|
-
"exists":
|
|
168
|
+
"memory_directory": result.get("memory_directory", ""),
|
|
169
|
+
"exists": result.get("exists", False),
|
|
154
170
|
"agents": agents,
|
|
155
|
-
"total_size_kb":
|
|
156
|
-
"total_files":
|
|
171
|
+
"total_size_kb": result.get("total_size_kb", 0),
|
|
172
|
+
"total_files": result.get("total_files", 0),
|
|
157
173
|
}
|
|
158
174
|
|
|
159
175
|
def _show_memories(self, args) -> CommandResult:
|
|
160
176
|
"""Show agent memories."""
|
|
161
177
|
try:
|
|
162
178
|
output_format = getattr(args, "format", "text")
|
|
179
|
+
agent_id = getattr(args, "agent_id", None)
|
|
180
|
+
raw_output = getattr(args, "raw", False)
|
|
181
|
+
|
|
182
|
+
if output_format in ["json", "yaml"] or raw_output:
|
|
183
|
+
# Use CRUD service for structured output
|
|
184
|
+
result = self.crud_service.read_memory(agent_id)
|
|
185
|
+
|
|
186
|
+
if not result.get("success"):
|
|
187
|
+
return CommandResult.error_result(
|
|
188
|
+
result.get("error", "Failed to read memories")
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
if raw_output:
|
|
192
|
+
# Output raw JSON for external tools
|
|
193
|
+
print(json.dumps(result, indent=2, ensure_ascii=False))
|
|
194
|
+
return CommandResult.success_result("Raw memory data output")
|
|
195
|
+
|
|
196
|
+
return CommandResult.success_result("Memories retrieved", data=result)
|
|
197
|
+
|
|
198
|
+
# Text output
|
|
199
|
+
result = self.crud_service.read_memory(agent_id)
|
|
200
|
+
|
|
201
|
+
if not result.get("success"):
|
|
202
|
+
print(f"❌ {result.get('error', 'Failed to read memories')}")
|
|
203
|
+
return CommandResult.error_result(result.get("error"))
|
|
204
|
+
|
|
205
|
+
print("🧠 Agent Memories Display")
|
|
206
|
+
print("-" * 80)
|
|
207
|
+
|
|
208
|
+
if agent_id:
|
|
209
|
+
# Single agent memory
|
|
210
|
+
content = result.get("content", "")
|
|
211
|
+
if content:
|
|
212
|
+
output = self.formatter.format_memory_view(
|
|
213
|
+
agent_id, content, getattr(args, "format", "detailed")
|
|
214
|
+
)
|
|
215
|
+
print(output)
|
|
216
|
+
else:
|
|
217
|
+
print(f"📭 No memory found for agent: {agent_id}")
|
|
218
|
+
else:
|
|
219
|
+
# All agent memories
|
|
220
|
+
agents = result.get("agents", {})
|
|
221
|
+
if agents:
|
|
222
|
+
# Parse and format all memories
|
|
223
|
+
agent_memories = {}
|
|
224
|
+
for aid, data in agents.items():
|
|
225
|
+
sections = self.formatter._parse_memory_content(
|
|
226
|
+
data.get("content", "")
|
|
227
|
+
)
|
|
228
|
+
agent_memories[aid] = sections
|
|
229
|
+
|
|
230
|
+
output = self.formatter.format_agent_memories_summary(
|
|
231
|
+
agent_memories, getattr(args, "format", "detailed")
|
|
232
|
+
)
|
|
233
|
+
print(output)
|
|
234
|
+
else:
|
|
235
|
+
print("📭 No agent memories found")
|
|
163
236
|
|
|
164
|
-
if output_format in ["json", "yaml"]:
|
|
165
|
-
# Structured output
|
|
166
|
-
memories_data = self._get_memories_data(args)
|
|
167
|
-
return CommandResult.success_result(
|
|
168
|
-
"Memories retrieved", data=memories_data
|
|
169
|
-
)
|
|
170
|
-
# Text output using existing function
|
|
171
|
-
_show_memories(args, self.memory_manager)
|
|
172
237
|
return CommandResult.success_result("Memories displayed")
|
|
173
238
|
|
|
174
239
|
except Exception as e:
|
|
175
240
|
self.logger.error(f"Error showing memories: {e}", exc_info=True)
|
|
176
241
|
return CommandResult.error_result(f"Error showing memories: {e}")
|
|
177
242
|
|
|
178
|
-
|
|
179
|
-
"""Get memories as structured data."""
|
|
180
|
-
agent_id = getattr(args, "agent", None)
|
|
181
|
-
|
|
182
|
-
if agent_id:
|
|
183
|
-
# Single agent memory
|
|
184
|
-
memory_content = self.memory_manager.load_agent_memory(agent_id)
|
|
185
|
-
return {
|
|
186
|
-
"agent_id": agent_id,
|
|
187
|
-
"memory_content": memory_content,
|
|
188
|
-
"has_memory": bool(memory_content),
|
|
189
|
-
}
|
|
190
|
-
# All agent memories
|
|
191
|
-
memory_dir = self.memory_manager.memories_dir
|
|
192
|
-
if not memory_dir.exists():
|
|
193
|
-
return {"agents": [], "memory_directory": str(memory_dir), "exists": False}
|
|
194
|
-
|
|
195
|
-
agents = {}
|
|
196
|
-
for memory_file in memory_dir.glob("*.md"):
|
|
197
|
-
if memory_file.is_file():
|
|
198
|
-
agent_id = memory_file.stem
|
|
199
|
-
memory_content = self.memory_manager.load_agent_memory(agent_id)
|
|
200
|
-
agents[agent_id] = {
|
|
201
|
-
"memory_content": memory_content,
|
|
202
|
-
"file_path": str(memory_file),
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
return {
|
|
206
|
-
"agents": agents,
|
|
207
|
-
"memory_directory": str(memory_dir),
|
|
208
|
-
"exists": True,
|
|
209
|
-
"agent_count": len(agents),
|
|
210
|
-
}
|
|
243
|
+
# Removed _get_memories_data - now handled inline with CRUD service
|
|
211
244
|
|
|
212
245
|
def _init_memory(self, args) -> CommandResult:
|
|
213
246
|
"""Initialize project-specific memories."""
|
|
214
247
|
try:
|
|
215
248
|
output_format = getattr(args, "format", "text")
|
|
216
249
|
|
|
250
|
+
# Use CRUD service for initialization task
|
|
251
|
+
result = self.crud_service.init_project_memories()
|
|
252
|
+
|
|
253
|
+
if not result.get("success"):
|
|
254
|
+
return CommandResult.error_result(
|
|
255
|
+
result.get("error", "Failed to create initialization task")
|
|
256
|
+
)
|
|
257
|
+
|
|
217
258
|
if output_format in ["json", "yaml"]:
|
|
218
|
-
#
|
|
219
|
-
task_data = {
|
|
220
|
-
"task": "Initialize project-specific agent memories",
|
|
221
|
-
"description": "Analyze project structure and create targeted memories for agents",
|
|
222
|
-
"suggested_command": "claude-mpm memory add --agent <agent_name> --learning '<insight>'",
|
|
223
|
-
}
|
|
259
|
+
# Return structured task data
|
|
224
260
|
return CommandResult.success_result(
|
|
225
|
-
"Memory initialization task created", data=task_data
|
|
261
|
+
"Memory initialization task created", data=result.get("task_data")
|
|
226
262
|
)
|
|
227
|
-
|
|
228
|
-
|
|
263
|
+
|
|
264
|
+
# Text output - display the task
|
|
265
|
+
task = result.get("task_data", {})
|
|
266
|
+
print("🚀 Initializing project-specific memories...")
|
|
267
|
+
print("=" * 80)
|
|
268
|
+
print()
|
|
269
|
+
print("This will analyze the project to:")
|
|
270
|
+
for idx, instruction in enumerate(task.get("instructions", []), 1):
|
|
271
|
+
print(f" {idx}. {instruction}")
|
|
272
|
+
print()
|
|
273
|
+
print("The analysis will cover:")
|
|
274
|
+
for area in task.get("focus_areas", []):
|
|
275
|
+
print(f" • {area}")
|
|
276
|
+
print()
|
|
277
|
+
print("Example commands to use:")
|
|
278
|
+
for cmd in task.get("example_commands", []):
|
|
279
|
+
print(f" {cmd}")
|
|
280
|
+
print()
|
|
281
|
+
print("=" * 80)
|
|
282
|
+
print()
|
|
283
|
+
print(
|
|
284
|
+
"📝 Note: Copy the task above to execute the memory initialization process."
|
|
285
|
+
)
|
|
286
|
+
|
|
229
287
|
return CommandResult.success_result("Memory initialization task displayed")
|
|
230
288
|
|
|
231
289
|
except Exception as e:
|
|
@@ -237,13 +295,35 @@ class MemoryManagementCommand(MemoryCommand):
|
|
|
237
295
|
try:
|
|
238
296
|
output_format = getattr(args, "format", "text")
|
|
239
297
|
|
|
298
|
+
# Extract arguments
|
|
299
|
+
agent_id = getattr(args, "agent_id", None)
|
|
300
|
+
learning_type = getattr(args, "learning_type", "context")
|
|
301
|
+
content = getattr(args, "content", "")
|
|
302
|
+
|
|
303
|
+
if not agent_id or not content:
|
|
304
|
+
return CommandResult.error_result(
|
|
305
|
+
"Agent ID and content are required for adding learning"
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
# Use CRUD service to add learning
|
|
309
|
+
result = self.crud_service.update_memory(agent_id, learning_type, content)
|
|
310
|
+
|
|
311
|
+
if not result.get("success"):
|
|
312
|
+
return CommandResult.error_result(
|
|
313
|
+
result.get("error", "Failed to add learning")
|
|
314
|
+
)
|
|
315
|
+
|
|
240
316
|
if output_format in ["json", "yaml"]:
|
|
241
|
-
#
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
317
|
+
# Return structured result
|
|
318
|
+
return CommandResult.success_result(
|
|
319
|
+
"Learning added to agent memory", data=result
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
# Text output
|
|
323
|
+
print(f"✅ Added {learning_type} to {agent_id} memory")
|
|
324
|
+
print(f" Section: {result.get('section', 'Unknown')}")
|
|
325
|
+
print(f" Content: {result.get('content_preview', content[:100])}")
|
|
326
|
+
|
|
247
327
|
return CommandResult.success_result("Learning added")
|
|
248
328
|
|
|
249
329
|
except Exception as e:
|
|
@@ -254,19 +334,47 @@ class MemoryManagementCommand(MemoryCommand):
|
|
|
254
334
|
"""Clean up old/unused memory files."""
|
|
255
335
|
try:
|
|
256
336
|
output_format = getattr(args, "format", "text")
|
|
337
|
+
agent_id = getattr(args, "agent_id", None)
|
|
338
|
+
dry_run = getattr(args, "dry_run", True)
|
|
339
|
+
|
|
340
|
+
# Use CRUD service for cleanup
|
|
341
|
+
result = self.crud_service.clean_memory(agent_id=agent_id, dry_run=dry_run)
|
|
342
|
+
|
|
343
|
+
if not result.get("success"):
|
|
344
|
+
return CommandResult.error_result(result.get("error", "Cleanup failed"))
|
|
257
345
|
|
|
258
346
|
if output_format in ["json", "yaml"]:
|
|
259
|
-
#
|
|
260
|
-
cleanup_data = {
|
|
261
|
-
"cleaned_files": [],
|
|
262
|
-
"errors": [],
|
|
263
|
-
"summary": "Memory cleanup completed",
|
|
264
|
-
}
|
|
347
|
+
# Return structured cleanup results
|
|
265
348
|
return CommandResult.success_result(
|
|
266
|
-
"Memory cleanup completed", data=
|
|
349
|
+
result.get("message", "Memory cleanup completed"), data=result
|
|
267
350
|
)
|
|
268
|
-
|
|
269
|
-
|
|
351
|
+
|
|
352
|
+
# Text output
|
|
353
|
+
print("🧹 Memory cleanup")
|
|
354
|
+
print("-" * 80)
|
|
355
|
+
|
|
356
|
+
if dry_run:
|
|
357
|
+
print("📊 Cleanup preview (dry run)")
|
|
358
|
+
candidates = result.get("cleanup_candidates", [])
|
|
359
|
+
if candidates:
|
|
360
|
+
print(f"Found {len(candidates)} files eligible for cleanup:")
|
|
361
|
+
for candidate in candidates:
|
|
362
|
+
print(
|
|
363
|
+
f" • {candidate['agent_id']}: {candidate['size_kb']:.1f} KB, {candidate['age_days']} days old"
|
|
364
|
+
)
|
|
365
|
+
print(f" Reason: {candidate['reason']}")
|
|
366
|
+
else:
|
|
367
|
+
print("No files eligible for cleanup")
|
|
368
|
+
else:
|
|
369
|
+
cleaned = result.get("cleaned_files", [])
|
|
370
|
+
if cleaned:
|
|
371
|
+
print(f"Cleaned {len(cleaned)} files")
|
|
372
|
+
else:
|
|
373
|
+
print(result.get("message", "No files cleaned"))
|
|
374
|
+
|
|
375
|
+
if result.get("note"):
|
|
376
|
+
print(f"\n⚠️ {result['note']}")
|
|
377
|
+
|
|
270
378
|
return CommandResult.success_result("Memory cleanup completed")
|
|
271
379
|
|
|
272
380
|
except Exception as e:
|
|
@@ -277,19 +385,31 @@ class MemoryManagementCommand(MemoryCommand):
|
|
|
277
385
|
"""Optimize memory files."""
|
|
278
386
|
try:
|
|
279
387
|
output_format = getattr(args, "format", "text")
|
|
388
|
+
agent_id = getattr(args, "agent_id", None)
|
|
280
389
|
|
|
281
390
|
if output_format in ["json", "yaml"]:
|
|
282
|
-
# For structured output,
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
}
|
|
391
|
+
# For structured output, perform optimization and return results
|
|
392
|
+
if agent_id:
|
|
393
|
+
result = self.memory_manager.optimize_memory(agent_id)
|
|
394
|
+
else:
|
|
395
|
+
result = self.memory_manager.optimize_memory()
|
|
288
396
|
return CommandResult.success_result(
|
|
289
|
-
"Memory optimization completed", data=
|
|
397
|
+
"Memory optimization completed", data=result
|
|
290
398
|
)
|
|
291
|
-
# Text output using
|
|
292
|
-
|
|
399
|
+
# Text output using formatter
|
|
400
|
+
if agent_id:
|
|
401
|
+
print(f"📊 Optimizing memory for agent: {agent_id}")
|
|
402
|
+
result = self.memory_manager.optimize_memory(agent_id)
|
|
403
|
+
output = self.formatter.format_optimization_results(
|
|
404
|
+
result, is_single_agent=True
|
|
405
|
+
)
|
|
406
|
+
else:
|
|
407
|
+
print("📊 Optimizing all agent memories...")
|
|
408
|
+
result = self.memory_manager.optimize_memory()
|
|
409
|
+
output = self.formatter.format_optimization_results(
|
|
410
|
+
result, is_single_agent=False
|
|
411
|
+
)
|
|
412
|
+
print(output)
|
|
293
413
|
return CommandResult.success_result("Memory optimization completed")
|
|
294
414
|
|
|
295
415
|
except Exception as e:
|
|
@@ -366,22 +486,6 @@ class MemoryManagementCommand(MemoryCommand):
|
|
|
366
486
|
return CommandResult.error_result(f"Error routing memory command: {e}")
|
|
367
487
|
|
|
368
488
|
|
|
369
|
-
def manage_memory(args):
|
|
370
|
-
"""
|
|
371
|
-
Main entry point for memory management commands.
|
|
372
|
-
|
|
373
|
-
This function maintains backward compatibility while using the new MemoryCommand pattern.
|
|
374
|
-
"""
|
|
375
|
-
command = MemoryManagementCommand()
|
|
376
|
-
result = command.execute(args)
|
|
377
|
-
|
|
378
|
-
# Print result if structured output format is requested
|
|
379
|
-
if hasattr(args, "format") and args.format in ["json", "yaml"]:
|
|
380
|
-
command.print_result(result, args)
|
|
381
|
-
|
|
382
|
-
return result.exit_code
|
|
383
|
-
|
|
384
|
-
|
|
385
489
|
def manage_memory(args) -> int:
|
|
386
490
|
"""Main entry point for memory management commands.
|
|
387
491
|
|
|
@@ -397,385 +501,25 @@ def manage_memory(args) -> int:
|
|
|
397
501
|
return result.exit_code
|
|
398
502
|
|
|
399
503
|
|
|
400
|
-
|
|
401
|
-
"""
|
|
402
|
-
Initialize project-specific memories via agent delegation.
|
|
504
|
+
# Removed _init_memory - now handled by MemoryCRUDService.init_project_memories()
|
|
403
505
|
|
|
404
|
-
WHY: When starting with a new project, agents need project-specific knowledge
|
|
405
|
-
beyond what automatic analysis provides. This command triggers an agent task
|
|
406
|
-
to comprehensively scan the project and create custom memories.
|
|
407
506
|
|
|
408
|
-
|
|
409
|
-
args: Command line arguments (unused but kept for consistency)
|
|
410
|
-
memory_manager: AgentMemoryManager instance
|
|
411
|
-
"""
|
|
412
|
-
get_logger("cli")
|
|
413
|
-
|
|
414
|
-
print("🚀 Initializing project-specific memories...")
|
|
415
|
-
print("=" * 80)
|
|
416
|
-
print()
|
|
417
|
-
print("This will analyze the project to:")
|
|
418
|
-
print(" 1. Scan project structure and documentation")
|
|
419
|
-
print(" 2. Analyze source code for patterns and conventions")
|
|
420
|
-
print(" 3. Create targeted memories for each agent type")
|
|
421
|
-
print(" 4. Add insights using 'claude-mpm memory add' commands")
|
|
422
|
-
print()
|
|
423
|
-
print("The analysis will cover:")
|
|
424
|
-
print(" • Project architecture and design patterns")
|
|
425
|
-
print(" • Coding conventions and standards")
|
|
426
|
-
print(" • Key modules and integration points")
|
|
427
|
-
print(" • Testing patterns and quality standards")
|
|
428
|
-
print(" • Performance considerations")
|
|
429
|
-
print(" • Domain-specific terminology")
|
|
430
|
-
print()
|
|
431
|
-
print("=" * 80)
|
|
432
|
-
print()
|
|
433
|
-
print("[Agent Task: Initialize Project-Specific Memories]")
|
|
434
|
-
print()
|
|
435
|
-
print("Please analyze this project and create custom memories for all agents.")
|
|
436
|
-
print()
|
|
437
|
-
print("Instructions:")
|
|
438
|
-
print("1. Scan the project structure, documentation, and source code")
|
|
439
|
-
print("2. Identify key patterns, conventions, and project-specific knowledge")
|
|
440
|
-
print("3. Create targeted memories for each agent type")
|
|
441
|
-
print("4. Use 'claude-mpm memory add <agent> <type> \"<content>\"' commands")
|
|
442
|
-
print()
|
|
443
|
-
print("Focus areas:")
|
|
444
|
-
print(" • Architectural patterns and design decisions")
|
|
445
|
-
print(" • Coding conventions from actual source code")
|
|
446
|
-
print(" • Key modules, APIs, and integration points")
|
|
447
|
-
print(" • Testing patterns and quality standards")
|
|
448
|
-
print(" • Performance considerations specific to this project")
|
|
449
|
-
print(" • Common pitfalls based on the codebase")
|
|
450
|
-
print(" • Domain-specific terminology and concepts")
|
|
451
|
-
print()
|
|
452
|
-
print("Example commands to use:")
|
|
453
|
-
print(
|
|
454
|
-
' claude-mpm memory add engineer pattern "Use dependency injection with @inject"'
|
|
455
|
-
)
|
|
456
|
-
print(
|
|
457
|
-
' claude-mpm memory add qa pattern "Test files follow test_<module>_<feature>.py"'
|
|
458
|
-
)
|
|
459
|
-
print(
|
|
460
|
-
' claude-mpm memory add research context "Project uses microservices architecture"'
|
|
461
|
-
)
|
|
462
|
-
print()
|
|
463
|
-
print("Begin by examining the project structure and key files.")
|
|
464
|
-
print()
|
|
465
|
-
print("=" * 80)
|
|
466
|
-
print()
|
|
467
|
-
print("📝 Note: Copy the task above to execute the memory initialization process.")
|
|
468
|
-
print(" Use 'claude-mpm memory add' commands to add discovered insights.")
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
def _show_status(memory_manager):
|
|
472
|
-
"""
|
|
473
|
-
Show comprehensive memory system status.
|
|
507
|
+
# Removed _show_status - functionality moved to MemoryManagementCommand._show_status()
|
|
474
508
|
|
|
475
|
-
WHY: Users need to see memory system health, file sizes, optimization
|
|
476
|
-
opportunities, and agent-specific statistics to understand the system state.
|
|
477
509
|
|
|
478
|
-
|
|
479
|
-
memory_manager: AgentMemoryManager instance
|
|
480
|
-
"""
|
|
481
|
-
print("Agent Memory System Status")
|
|
482
|
-
print("-" * 80)
|
|
510
|
+
# Removed _show_basic_status - functionality integrated into MemoryManagementCommand
|
|
483
511
|
|
|
484
|
-
try:
|
|
485
|
-
# Get comprehensive status from memory manager
|
|
486
|
-
status = memory_manager.get_memory_status()
|
|
487
512
|
|
|
488
|
-
|
|
489
|
-
print(f"❌ Error getting status: {status.get('error', 'Unknown error')}")
|
|
490
|
-
return
|
|
513
|
+
# Removed _view_memory - functionality moved to MemoryCRUDService.read_memory()
|
|
491
514
|
|
|
492
|
-
# Show system overview
|
|
493
|
-
system_health = status.get("system_health", "unknown")
|
|
494
|
-
health_emoji = {
|
|
495
|
-
"healthy": "✅",
|
|
496
|
-
"needs_optimization": "⚠️",
|
|
497
|
-
"high_usage": "📊",
|
|
498
|
-
"no_memory_dir": "📁",
|
|
499
|
-
}.get(system_health, "❓")
|
|
500
|
-
|
|
501
|
-
print(f"🧠 Memory System Health: {health_emoji} {system_health}")
|
|
502
|
-
print(f"📁 Memory Directory: {status.get('memory_directory', 'Unknown')}")
|
|
503
|
-
print(
|
|
504
|
-
f"🔧 System Enabled: {'Yes' if status.get('system_enabled', True) else 'No'}"
|
|
505
|
-
)
|
|
506
|
-
print(
|
|
507
|
-
f"📚 Auto Learning: {'Yes' if status.get('auto_learning', True) else 'No'}"
|
|
508
|
-
)
|
|
509
|
-
print(f"📊 Total Agents: {status.get('total_agents', 0)}")
|
|
510
|
-
print(f"💾 Total Size: {status.get('total_size_kb', 0):.1f} KB")
|
|
511
|
-
print()
|
|
512
|
-
|
|
513
|
-
# Show optimization opportunities
|
|
514
|
-
opportunities = status.get("optimization_opportunities", [])
|
|
515
|
-
if opportunities:
|
|
516
|
-
print(f"⚠️ Optimization Opportunities ({len(opportunities)}):")
|
|
517
|
-
for opportunity in opportunities[:5]: # Show top 5
|
|
518
|
-
print(f" • {opportunity}")
|
|
519
|
-
if len(opportunities) > 5:
|
|
520
|
-
print(f" ... and {len(opportunities) - 5} more")
|
|
521
|
-
print()
|
|
522
515
|
|
|
523
|
-
|
|
524
|
-
agents = status.get("agents", {})
|
|
525
|
-
if agents:
|
|
526
|
-
print("📋 Agent Memory Details:")
|
|
527
|
-
for agent_id, agent_info in sorted(agents.items()):
|
|
528
|
-
if "error" in agent_info:
|
|
529
|
-
print(f" ❌ {agent_id}: Error - {agent_info['error']}")
|
|
530
|
-
continue
|
|
531
|
-
|
|
532
|
-
size_kb = agent_info.get("size_kb", 0)
|
|
533
|
-
size_limit = agent_info.get("size_limit_kb", 8)
|
|
534
|
-
utilization = agent_info.get("size_utilization", 0)
|
|
535
|
-
sections = agent_info.get("sections", 0)
|
|
536
|
-
items = agent_info.get("items", 0)
|
|
537
|
-
last_modified = agent_info.get("last_modified", "Unknown")
|
|
538
|
-
auto_learning = agent_info.get("auto_learning", True)
|
|
539
|
-
|
|
540
|
-
# Format last modified time
|
|
541
|
-
try:
|
|
542
|
-
from datetime import datetime
|
|
543
|
-
|
|
544
|
-
dt = datetime.fromisoformat(last_modified.replace("Z", "+00:00"))
|
|
545
|
-
last_modified_str = dt.strftime("%Y-%m-%d %H:%M:%S")
|
|
546
|
-
except:
|
|
547
|
-
last_modified_str = last_modified
|
|
548
|
-
|
|
549
|
-
# Status indicator based on usage
|
|
550
|
-
if utilization > 90:
|
|
551
|
-
status_emoji = "🔴" # High usage
|
|
552
|
-
elif utilization > 70:
|
|
553
|
-
status_emoji = "🟡" # Medium usage
|
|
554
|
-
else:
|
|
555
|
-
status_emoji = "🟢" # Low usage
|
|
516
|
+
# Removed _add_learning - now handled by MemoryCRUDService.update_memory()
|
|
556
517
|
|
|
557
|
-
print(f" {status_emoji} {agent_id}")
|
|
558
|
-
print(
|
|
559
|
-
f" Size: {size_kb:.1f} KB / {size_limit} KB ({utilization:.1f}%)"
|
|
560
|
-
)
|
|
561
|
-
print(f" Content: {sections} sections, {items} items")
|
|
562
|
-
print(f" Auto-learning: {'On' if auto_learning else 'Off'}")
|
|
563
|
-
print(f" Last modified: {last_modified_str}")
|
|
564
|
-
else:
|
|
565
|
-
print("📭 No agent memories found")
|
|
566
518
|
|
|
567
|
-
|
|
568
|
-
print(f"❌ Error showing status: {e}")
|
|
569
|
-
# Fallback to basic status display
|
|
570
|
-
_show_basic_status(memory_manager)
|
|
519
|
+
# Removed _clean_memory - now handled by MemoryCRUDService.clean_memory()
|
|
571
520
|
|
|
572
521
|
|
|
573
|
-
|
|
574
|
-
"""Fallback basic status display if comprehensive status fails."""
|
|
575
|
-
print("\n--- Basic Status (Fallback) ---")
|
|
576
|
-
|
|
577
|
-
memory_dir = memory_manager.memories_dir
|
|
578
|
-
if not memory_dir.exists():
|
|
579
|
-
print("📁 Memory directory not found - no agent memories stored yet")
|
|
580
|
-
print(f" Expected location: {memory_dir}")
|
|
581
|
-
return
|
|
582
|
-
|
|
583
|
-
# Support both old and new formats
|
|
584
|
-
memory_files = list(memory_dir.glob("*_memories.md"))
|
|
585
|
-
# Also check for old formats for backward compatibility
|
|
586
|
-
memory_files.extend(memory_dir.glob("*_agent.md"))
|
|
587
|
-
memory_files.extend(
|
|
588
|
-
[
|
|
589
|
-
f
|
|
590
|
-
for f in memory_dir.glob("*.md")
|
|
591
|
-
if f.name != "README.md"
|
|
592
|
-
and not f.name.endswith("_memories.md")
|
|
593
|
-
and not f.name.endswith("_agent.md")
|
|
594
|
-
]
|
|
595
|
-
)
|
|
596
|
-
|
|
597
|
-
if not memory_files:
|
|
598
|
-
print("📭 No memory files found")
|
|
599
|
-
print(f" Memory directory: {memory_dir}")
|
|
600
|
-
return
|
|
601
|
-
|
|
602
|
-
print(f"📁 Memory directory: {memory_dir}")
|
|
603
|
-
print(f"📊 Total memory files: {len(memory_files)}")
|
|
604
|
-
|
|
605
|
-
total_size = 0
|
|
606
|
-
for file_path in sorted(memory_files):
|
|
607
|
-
stat = file_path.stat()
|
|
608
|
-
size_kb = stat.st_size / 1024
|
|
609
|
-
total_size += stat.st_size
|
|
610
|
-
|
|
611
|
-
# Extract agent name from various formats
|
|
612
|
-
if file_path.name.endswith("_memories.md"):
|
|
613
|
-
agent_id = file_path.stem[:-9] # Remove "_memories"
|
|
614
|
-
elif file_path.name.endswith("_agent.md"):
|
|
615
|
-
agent_id = file_path.stem[:-6] # Remove "_agent"
|
|
616
|
-
else:
|
|
617
|
-
agent_id = file_path.stem
|
|
618
|
-
print(f" {agent_id}: {size_kb:.1f} KB")
|
|
619
|
-
|
|
620
|
-
print(f"💾 Total size: {total_size / 1024:.1f} KB")
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
def _view_memory(args, memory_manager):
|
|
624
|
-
"""
|
|
625
|
-
View agent memory file contents.
|
|
626
|
-
|
|
627
|
-
WHY: Users need to inspect what learnings an agent has accumulated
|
|
628
|
-
to understand its behavior and debug issues.
|
|
629
|
-
|
|
630
|
-
Args:
|
|
631
|
-
args: Command arguments with agent_id
|
|
632
|
-
memory_manager: AgentMemoryManager instance
|
|
633
|
-
"""
|
|
634
|
-
agent_id = args.agent_id
|
|
635
|
-
|
|
636
|
-
try:
|
|
637
|
-
memory_content = memory_manager.load_agent_memory(agent_id)
|
|
638
|
-
|
|
639
|
-
if not memory_content:
|
|
640
|
-
print(f"📭 No memory found for agent: {agent_id}")
|
|
641
|
-
return
|
|
642
|
-
|
|
643
|
-
print(f"🧠 Memory for agent: {agent_id}")
|
|
644
|
-
print("-" * 80)
|
|
645
|
-
print(memory_content)
|
|
646
|
-
|
|
647
|
-
except FileNotFoundError:
|
|
648
|
-
print(f"📭 No memory file found for agent: {agent_id}")
|
|
649
|
-
except Exception as e:
|
|
650
|
-
print(f"❌ Error viewing memory: {e}")
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
def _add_learning(args, memory_manager):
|
|
654
|
-
"""
|
|
655
|
-
Manually add learning to agent memory.
|
|
656
|
-
|
|
657
|
-
WHY: Allows manual injection of learnings for testing or correction
|
|
658
|
-
purposes, useful for debugging and development.
|
|
659
|
-
|
|
660
|
-
Args:
|
|
661
|
-
args: Command arguments with agent_id, learning_type, and content
|
|
662
|
-
memory_manager: AgentMemoryManager instance
|
|
663
|
-
"""
|
|
664
|
-
agent_id = args.agent_id
|
|
665
|
-
section = args.learning_type # Map learning_type to section name
|
|
666
|
-
content = args.content
|
|
667
|
-
|
|
668
|
-
# Map learning types to appropriate sections
|
|
669
|
-
section_map = {
|
|
670
|
-
"pattern": "Project Architecture",
|
|
671
|
-
"error": "Common Mistakes to Avoid",
|
|
672
|
-
"optimization": "Implementation Guidelines",
|
|
673
|
-
"preference": "Implementation Guidelines",
|
|
674
|
-
"context": "Current Technical Context",
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
section_name = section_map.get(section, "Current Technical Context")
|
|
678
|
-
|
|
679
|
-
try:
|
|
680
|
-
success = memory_manager.update_agent_memory(agent_id, section_name, content)
|
|
681
|
-
|
|
682
|
-
if success:
|
|
683
|
-
print(f"✅ Added {section} to {agent_id} memory in section: {section_name}")
|
|
684
|
-
print(f" Content: {content[:100]}{'...' if len(content) > 100 else ''}")
|
|
685
|
-
else:
|
|
686
|
-
print(f"❌ Failed to add learning to {agent_id} memory")
|
|
687
|
-
print(" Memory file may be at size limit or section may be full")
|
|
688
|
-
|
|
689
|
-
except Exception as e:
|
|
690
|
-
print(f"❌ Error adding learning: {e}")
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
def _clean_memory(args, memory_manager):
|
|
694
|
-
"""
|
|
695
|
-
Clean up old/unused memory files.
|
|
696
|
-
|
|
697
|
-
WHY: Memory files can accumulate over time. This provides a way to
|
|
698
|
-
clean up old or unused files to save disk space.
|
|
699
|
-
|
|
700
|
-
DESIGN DECISION: For Phase 1, this is a stub implementation.
|
|
701
|
-
Full cleanup logic will be implemented based on usage patterns.
|
|
702
|
-
|
|
703
|
-
Args:
|
|
704
|
-
args: Command arguments
|
|
705
|
-
memory_manager: AgentMemoryManager instance
|
|
706
|
-
"""
|
|
707
|
-
print("🧹 Memory cleanup")
|
|
708
|
-
print("-" * 80)
|
|
709
|
-
|
|
710
|
-
# For Phase 1, just show what would be cleaned
|
|
711
|
-
memory_dir = memory_manager.memories_dir
|
|
712
|
-
if not memory_dir.exists():
|
|
713
|
-
print("📁 No memory directory found - nothing to clean")
|
|
714
|
-
return
|
|
715
|
-
|
|
716
|
-
# Support both old and new formats
|
|
717
|
-
memory_files = list(memory_dir.glob("*_memories.md"))
|
|
718
|
-
# Also check for old formats for backward compatibility
|
|
719
|
-
memory_files.extend(memory_dir.glob("*_agent.md"))
|
|
720
|
-
memory_files.extend(
|
|
721
|
-
[
|
|
722
|
-
f
|
|
723
|
-
for f in memory_dir.glob("*.md")
|
|
724
|
-
if f.name != "README.md"
|
|
725
|
-
and not f.name.endswith("_memories.md")
|
|
726
|
-
and not f.name.endswith("_agent.md")
|
|
727
|
-
]
|
|
728
|
-
)
|
|
729
|
-
if not memory_files:
|
|
730
|
-
print("📭 No memory files found - nothing to clean")
|
|
731
|
-
return
|
|
732
|
-
|
|
733
|
-
print(f"📊 Found {len(memory_files)} memory files")
|
|
734
|
-
print()
|
|
735
|
-
print("⚠️ Cleanup not yet implemented in Phase 1")
|
|
736
|
-
print(" Future cleanup will remove:")
|
|
737
|
-
print(" - Memory files older than 30 days with no recent access")
|
|
738
|
-
print(" - Corrupted memory files")
|
|
739
|
-
print(" - Memory files for non-existent agents")
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
def _optimize_memory(args, memory_manager):
|
|
743
|
-
"""
|
|
744
|
-
Optimize memory files by removing duplicates and consolidating similar items.
|
|
745
|
-
|
|
746
|
-
WHY: Memory files can become cluttered over time with duplicate or redundant
|
|
747
|
-
information. This command provides automated cleanup while preserving
|
|
748
|
-
important learnings.
|
|
749
|
-
|
|
750
|
-
Args:
|
|
751
|
-
args: Command arguments with optional agent_id
|
|
752
|
-
memory_manager: AgentMemoryManager instance
|
|
753
|
-
"""
|
|
754
|
-
print("🔧 Memory Optimization")
|
|
755
|
-
print("-" * 80)
|
|
756
|
-
|
|
757
|
-
agent_id = getattr(args, "agent_id", None)
|
|
758
|
-
|
|
759
|
-
try:
|
|
760
|
-
if agent_id:
|
|
761
|
-
print(f"📊 Optimizing memory for agent: {agent_id}")
|
|
762
|
-
result = memory_manager.optimize_memory(agent_id)
|
|
763
|
-
else:
|
|
764
|
-
print("📊 Optimizing all agent memories...")
|
|
765
|
-
result = memory_manager.optimize_memory()
|
|
766
|
-
|
|
767
|
-
if result.get("success"):
|
|
768
|
-
if agent_id:
|
|
769
|
-
# Single agent results
|
|
770
|
-
_display_single_optimization_result(result)
|
|
771
|
-
else:
|
|
772
|
-
# All agents results
|
|
773
|
-
_display_bulk_optimization_results(result)
|
|
774
|
-
else:
|
|
775
|
-
print(f"❌ Optimization failed: {result.get('error', 'Unknown error')}")
|
|
776
|
-
|
|
777
|
-
except Exception as e:
|
|
778
|
-
print(f"❌ Error during optimization: {e}")
|
|
522
|
+
# Removed _optimize_memory - functionality moved to MemoryManagementCommand._optimize_memory()
|
|
779
523
|
|
|
780
524
|
|
|
781
525
|
def _build_memory(args, memory_manager):
|
|
@@ -799,35 +543,11 @@ def _build_memory(args, memory_manager):
|
|
|
799
543
|
print("🔍 Analyzing project documentation...")
|
|
800
544
|
result = memory_manager.build_memories_from_docs(force_rebuild)
|
|
801
545
|
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
print(f" Agents affected: {result.get('total_agents_affected', 0)}")
|
|
808
|
-
|
|
809
|
-
if result.get("agents_affected"):
|
|
810
|
-
print(f" Affected agents: {', '.join(result['agents_affected'])}")
|
|
811
|
-
|
|
812
|
-
# Show file-specific results
|
|
813
|
-
files_results = result.get("files", {})
|
|
814
|
-
if files_results:
|
|
815
|
-
print("\n📄 File processing details:")
|
|
816
|
-
for file_path, file_result in files_results.items():
|
|
817
|
-
if file_result.get("success"):
|
|
818
|
-
extracted = file_result.get("items_extracted", 0)
|
|
819
|
-
created = file_result.get("memories_created", 0)
|
|
820
|
-
print(
|
|
821
|
-
f" {file_path}: {extracted} items extracted, {created} memories created"
|
|
822
|
-
)
|
|
823
|
-
|
|
824
|
-
if result.get("errors"):
|
|
825
|
-
print("\n⚠️ Errors encountered:")
|
|
826
|
-
for error in result["errors"]:
|
|
827
|
-
print(f" {error}")
|
|
828
|
-
|
|
829
|
-
else:
|
|
830
|
-
print(f"❌ Build failed: {result.get('error', 'Unknown error')}")
|
|
546
|
+
# Use formatter to display build results
|
|
547
|
+
quiet = os.environ.get("CLAUDE_MPM_QUIET", "false").lower() == "true"
|
|
548
|
+
formatter = MemoryOutputFormatter(quiet=quiet)
|
|
549
|
+
output = formatter.format_build_results(result)
|
|
550
|
+
print(output)
|
|
831
551
|
|
|
832
552
|
except Exception as e:
|
|
833
553
|
print(f"❌ Error building memories: {e}")
|
|
@@ -844,298 +564,22 @@ def _cross_reference_memory(args, memory_manager):
|
|
|
844
564
|
args: Command arguments with optional query
|
|
845
565
|
memory_manager: AgentMemoryManager instance
|
|
846
566
|
"""
|
|
847
|
-
print("🔗 Memory Cross-Reference Analysis")
|
|
848
|
-
print("-" * 80)
|
|
849
|
-
|
|
850
567
|
query = getattr(args, "query", None)
|
|
851
568
|
|
|
852
569
|
try:
|
|
853
|
-
if query:
|
|
854
|
-
print(f"🔍 Searching for: '{query}'")
|
|
855
|
-
else:
|
|
856
|
-
print("🔍 Analyzing all agent memories for patterns...")
|
|
857
|
-
|
|
858
570
|
result = memory_manager.cross_reference_memories(query)
|
|
859
571
|
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
common_patterns = result.get("common_patterns", [])
|
|
866
|
-
if common_patterns:
|
|
867
|
-
print(f"\n🔄 Common patterns found ({len(common_patterns)}):")
|
|
868
|
-
for pattern in common_patterns[:10]: # Show top 10
|
|
869
|
-
agents = ", ".join(pattern["agents"])
|
|
870
|
-
print(f" • {pattern['pattern']}")
|
|
871
|
-
print(f" Found in: {agents} ({pattern['count']} instances)")
|
|
872
|
-
else:
|
|
873
|
-
print("\n🔄 No common patterns found")
|
|
874
|
-
|
|
875
|
-
# Display query matches if query was provided
|
|
876
|
-
if query and result.get("query_matches"):
|
|
877
|
-
print(f"\n🎯 Query matches for '{query}':")
|
|
878
|
-
for match in result["query_matches"]:
|
|
879
|
-
print(f" 📋 {match['agent']}:")
|
|
880
|
-
for line in match["matches"][:3]: # Show first 3 matches
|
|
881
|
-
print(f" • {line}")
|
|
882
|
-
|
|
883
|
-
# Display agent correlations
|
|
884
|
-
correlations = result.get("agent_correlations", {})
|
|
885
|
-
if correlations:
|
|
886
|
-
print("\n🤝 Agent knowledge correlations:")
|
|
887
|
-
sorted_correlations = sorted(
|
|
888
|
-
correlations.items(), key=lambda x: x[1], reverse=True
|
|
889
|
-
)
|
|
890
|
-
for agents, count in sorted_correlations[:5]: # Show top 5
|
|
891
|
-
print(f" {agents}: {count} common items")
|
|
892
|
-
else:
|
|
893
|
-
print("\n🤝 No significant correlations found")
|
|
572
|
+
# Use formatter to display cross-reference results
|
|
573
|
+
quiet = os.environ.get("CLAUDE_MPM_QUIET", "false").lower() == "true"
|
|
574
|
+
formatter = MemoryOutputFormatter(quiet=quiet)
|
|
575
|
+
output = formatter.format_cross_reference(result, query)
|
|
576
|
+
print(output)
|
|
894
577
|
|
|
895
578
|
except Exception as e:
|
|
896
579
|
print(f"❌ Error during cross-reference analysis: {e}")
|
|
897
580
|
|
|
898
581
|
|
|
899
|
-
|
|
900
|
-
"""
|
|
901
|
-
Show agent memories in a user-friendly format with cross-references and patterns.
|
|
902
|
-
|
|
903
|
-
WHY: Users need to see agent memories in a readable format to understand
|
|
904
|
-
what agents have learned and identify common patterns across agents.
|
|
905
|
-
|
|
906
|
-
DESIGN DECISION: Added --raw flag to output structured JSON data for
|
|
907
|
-
programmatic processing, enabling external tools and scripts to access
|
|
908
|
-
all agent memories in a structured format.
|
|
909
|
-
|
|
910
|
-
Args:
|
|
911
|
-
args: Command arguments with optional agent_id, format, and raw flag
|
|
912
|
-
memory_manager: AgentMemoryManager instance
|
|
913
|
-
"""
|
|
914
|
-
agent_id = getattr(args, "agent_id", None)
|
|
915
|
-
format_type = getattr(args, "format", "detailed")
|
|
916
|
-
raw_output = getattr(args, "raw", False)
|
|
917
|
-
|
|
918
|
-
try:
|
|
919
|
-
if raw_output:
|
|
920
|
-
# Output structured JSON data
|
|
921
|
-
if agent_id:
|
|
922
|
-
# Get single agent memory in raw format
|
|
923
|
-
_output_single_agent_raw(agent_id, memory_manager)
|
|
924
|
-
else:
|
|
925
|
-
# Get all agent memories in raw format
|
|
926
|
-
_output_all_memories_raw(memory_manager)
|
|
927
|
-
else:
|
|
928
|
-
# Normal user-friendly display
|
|
929
|
-
print("🧠 Agent Memories Display")
|
|
930
|
-
print("-" * 80)
|
|
931
|
-
|
|
932
|
-
if agent_id:
|
|
933
|
-
_show_single_agent_memory(agent_id, format_type, memory_manager)
|
|
934
|
-
else:
|
|
935
|
-
_show_all_agent_memories(format_type, memory_manager)
|
|
936
|
-
|
|
937
|
-
except Exception as e:
|
|
938
|
-
if raw_output:
|
|
939
|
-
# Output error in JSON format for consistency
|
|
940
|
-
error_output = {
|
|
941
|
-
"success": False,
|
|
942
|
-
"error": str(e),
|
|
943
|
-
"timestamp": datetime.now().isoformat(),
|
|
944
|
-
}
|
|
945
|
-
print(json.dumps(error_output, indent=2))
|
|
946
|
-
else:
|
|
947
|
-
print(f"❌ Error showing memories: {e}")
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
def _show_single_agent_memory(agent_id, format_type, memory_manager):
|
|
951
|
-
"""Show memory for a single agent in the specified format."""
|
|
952
|
-
memory_content = memory_manager.load_agent_memory(agent_id)
|
|
953
|
-
|
|
954
|
-
if not memory_content:
|
|
955
|
-
print(f"📭 No memory found for agent: {agent_id}")
|
|
956
|
-
return
|
|
957
|
-
|
|
958
|
-
print(f"🤖 Agent: {agent_id}")
|
|
959
|
-
print("-" * 40)
|
|
960
|
-
|
|
961
|
-
if format_type == "full":
|
|
962
|
-
print(memory_content)
|
|
963
|
-
else:
|
|
964
|
-
# Parse and display memory sections
|
|
965
|
-
sections = _parse_memory_content(memory_content)
|
|
966
|
-
|
|
967
|
-
for section_name, items in sections.items():
|
|
968
|
-
if items:
|
|
969
|
-
print(f"\n📚 {section_name} ({len(items)} items):")
|
|
970
|
-
for i, item in enumerate(items[:5], 1): # Show first 5 items
|
|
971
|
-
print(f" {i}. {item}")
|
|
972
|
-
if len(items) > 5:
|
|
973
|
-
print(f" ... and {len(items) - 5} more")
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
def _show_all_agent_memories(format_type, memory_manager):
|
|
977
|
-
"""Show memories for all agents with cross-references."""
|
|
978
|
-
# Get all available agent memory files
|
|
979
|
-
memory_dir = memory_manager.memories_dir
|
|
980
|
-
if not memory_dir.exists():
|
|
981
|
-
print("📁 No memory directory found")
|
|
982
|
-
return
|
|
983
|
-
|
|
984
|
-
# Support both old and new formats
|
|
985
|
-
memory_files = list(memory_dir.glob("*_memories.md"))
|
|
986
|
-
# Also check for old formats for backward compatibility
|
|
987
|
-
memory_files.extend(memory_dir.glob("*_agent.md"))
|
|
988
|
-
memory_files.extend(
|
|
989
|
-
[
|
|
990
|
-
f
|
|
991
|
-
for f in memory_dir.glob("*.md")
|
|
992
|
-
if f.name != "README.md"
|
|
993
|
-
and not f.name.endswith("_memories.md")
|
|
994
|
-
and not f.name.endswith("_agent.md")
|
|
995
|
-
]
|
|
996
|
-
)
|
|
997
|
-
if not memory_files:
|
|
998
|
-
print("📭 No agent memories found")
|
|
999
|
-
return
|
|
1000
|
-
|
|
1001
|
-
print(f"📊 Found memories for {len(memory_files)} agents")
|
|
1002
|
-
print()
|
|
1003
|
-
|
|
1004
|
-
agent_memories = {}
|
|
1005
|
-
total_items = 0
|
|
1006
|
-
|
|
1007
|
-
# Load all agent memories
|
|
1008
|
-
for file_path in sorted(memory_files):
|
|
1009
|
-
# Extract agent name from various formats
|
|
1010
|
-
if file_path.name.endswith("_memories.md"):
|
|
1011
|
-
agent_id = file_path.stem[:-9] # Remove "_memories"
|
|
1012
|
-
elif file_path.name.endswith("_agent.md"):
|
|
1013
|
-
agent_id = file_path.stem[:-6] # Remove "_agent"
|
|
1014
|
-
else:
|
|
1015
|
-
agent_id = file_path.stem
|
|
1016
|
-
try:
|
|
1017
|
-
memory_content = memory_manager.load_agent_memory(agent_id)
|
|
1018
|
-
if memory_content:
|
|
1019
|
-
sections = _parse_memory_content(memory_content)
|
|
1020
|
-
agent_memories[agent_id] = sections
|
|
1021
|
-
|
|
1022
|
-
# Count items
|
|
1023
|
-
item_count = sum(len(items) for items in sections.values())
|
|
1024
|
-
total_items += item_count
|
|
1025
|
-
|
|
1026
|
-
if format_type == "summary":
|
|
1027
|
-
print(f"🤖 {agent_id}")
|
|
1028
|
-
print(f" 📚 {len(sections)} sections, {item_count} total items")
|
|
1029
|
-
|
|
1030
|
-
# Show section summary
|
|
1031
|
-
for section_name, items in sections.items():
|
|
1032
|
-
if items:
|
|
1033
|
-
print(f" • {section_name}: {len(items)} items")
|
|
1034
|
-
print()
|
|
1035
|
-
elif format_type == "detailed":
|
|
1036
|
-
print(f"🤖 {agent_id}")
|
|
1037
|
-
print(f" 📚 {len(sections)} sections, {item_count} total items")
|
|
1038
|
-
|
|
1039
|
-
for section_name, items in sections.items():
|
|
1040
|
-
if items:
|
|
1041
|
-
print(f"\n 📖 {section_name}:")
|
|
1042
|
-
for item in items[:3]: # Show first 3 items
|
|
1043
|
-
print(f" • {item}")
|
|
1044
|
-
if len(items) > 3:
|
|
1045
|
-
print(f" ... and {len(items) - 3} more")
|
|
1046
|
-
print()
|
|
1047
|
-
except Exception as e:
|
|
1048
|
-
print(f"❌ Error loading memory for {agent_id}: {e}")
|
|
1049
|
-
|
|
1050
|
-
print(f"📊 Total: {total_items} memory items across {len(agent_memories)} agents")
|
|
1051
|
-
|
|
1052
|
-
# Show cross-references if we have multiple agents
|
|
1053
|
-
if len(agent_memories) > 1:
|
|
1054
|
-
print("\n🔗 Cross-References and Common Patterns:")
|
|
1055
|
-
_find_common_patterns(agent_memories)
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
def _parse_memory_content(content):
|
|
1059
|
-
"""Parse memory content into sections and items."""
|
|
1060
|
-
sections = {}
|
|
1061
|
-
current_section = None
|
|
1062
|
-
current_items = []
|
|
1063
|
-
|
|
1064
|
-
for line in content.split("\n"):
|
|
1065
|
-
line = line.strip()
|
|
1066
|
-
|
|
1067
|
-
if line.startswith("## ") and not line.startswith("## Memory Usage"):
|
|
1068
|
-
# New section
|
|
1069
|
-
if current_section and current_items:
|
|
1070
|
-
sections[current_section] = current_items.copy()
|
|
1071
|
-
|
|
1072
|
-
current_section = line[3:].strip()
|
|
1073
|
-
current_items = []
|
|
1074
|
-
elif line.startswith("- ") and current_section:
|
|
1075
|
-
# Item in current section
|
|
1076
|
-
item = line[2:].strip()
|
|
1077
|
-
if item and len(item) > 5: # Filter out very short items
|
|
1078
|
-
current_items.append(item)
|
|
1079
|
-
|
|
1080
|
-
# Add final section
|
|
1081
|
-
if current_section and current_items:
|
|
1082
|
-
sections[current_section] = current_items
|
|
1083
|
-
|
|
1084
|
-
return sections
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
def _find_common_patterns(agent_memories):
|
|
1088
|
-
"""Find common patterns across agent memories."""
|
|
1089
|
-
pattern_count = {}
|
|
1090
|
-
agent_patterns = {}
|
|
1091
|
-
|
|
1092
|
-
# Collect all patterns and which agents have them
|
|
1093
|
-
for agent_id, sections in agent_memories.items():
|
|
1094
|
-
agent_patterns[agent_id] = set()
|
|
1095
|
-
|
|
1096
|
-
for _section_name, items in sections.items():
|
|
1097
|
-
for item in items:
|
|
1098
|
-
# Normalize item for comparison (lowercase, basic cleanup)
|
|
1099
|
-
normalized = item.lower().strip()
|
|
1100
|
-
if len(normalized) > 10: # Skip very short items
|
|
1101
|
-
pattern_count[normalized] = pattern_count.get(normalized, 0) + 1
|
|
1102
|
-
agent_patterns[agent_id].add(normalized)
|
|
1103
|
-
|
|
1104
|
-
# Find patterns that appear in multiple agents
|
|
1105
|
-
common_patterns = [
|
|
1106
|
-
(pattern, count) for pattern, count in pattern_count.items() if count > 1
|
|
1107
|
-
]
|
|
1108
|
-
common_patterns.sort(key=lambda x: x[1], reverse=True)
|
|
1109
|
-
|
|
1110
|
-
if common_patterns:
|
|
1111
|
-
print("\n🔄 Most Common Patterns:")
|
|
1112
|
-
for pattern, count in common_patterns[:5]:
|
|
1113
|
-
# Find which agents have this pattern
|
|
1114
|
-
agents_with_pattern = [
|
|
1115
|
-
agent
|
|
1116
|
-
for agent, patterns in agent_patterns.items()
|
|
1117
|
-
if pattern in patterns
|
|
1118
|
-
]
|
|
1119
|
-
print(f" • {pattern[:80]}{'...' if len(pattern) > 80 else ''}")
|
|
1120
|
-
print(f" Found in: {', '.join(agents_with_pattern)} ({count} agents)")
|
|
1121
|
-
print()
|
|
1122
|
-
else:
|
|
1123
|
-
print(" No common patterns found across agents")
|
|
1124
|
-
|
|
1125
|
-
# Show agent similarities
|
|
1126
|
-
print("\n🤝 Agent Knowledge Similarity:")
|
|
1127
|
-
agents = list(agent_memories.keys())
|
|
1128
|
-
for i, agent1 in enumerate(agents):
|
|
1129
|
-
for agent2 in agents[i + 1 :]:
|
|
1130
|
-
common_items = len(agent_patterns[agent1] & agent_patterns[agent2])
|
|
1131
|
-
if common_items > 0:
|
|
1132
|
-
total_items = len(agent_patterns[agent1] | agent_patterns[agent2])
|
|
1133
|
-
similarity = (
|
|
1134
|
-
(common_items / total_items) * 100 if total_items > 0 else 0
|
|
1135
|
-
)
|
|
1136
|
-
print(
|
|
1137
|
-
f" {agent1} ↔ {agent2}: {common_items} common items ({similarity:.1f}% similarity)"
|
|
1138
|
-
)
|
|
582
|
+
# Note: Memory display functions have been moved to MemoryManagementCommand and MemoryCRUDService
|
|
1139
583
|
|
|
1140
584
|
|
|
1141
585
|
def _route_memory_command(args, memory_manager):
|
|
@@ -1204,141 +648,18 @@ def _route_memory_command(args, memory_manager):
|
|
|
1204
648
|
|
|
1205
649
|
def _display_single_optimization_result(result):
|
|
1206
650
|
"""Display optimization results for a single agent."""
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
size_reduction_percent = result.get("size_reduction_percent", 0)
|
|
1212
|
-
|
|
1213
|
-
print(f"✅ Optimization completed for {agent_id}")
|
|
1214
|
-
print(f" Original size: {original_size:,} bytes")
|
|
1215
|
-
print(f" Optimized size: {optimized_size:,} bytes")
|
|
1216
|
-
print(f" Size reduction: {size_reduction:,} bytes ({size_reduction_percent}%)")
|
|
1217
|
-
|
|
1218
|
-
duplicates = result.get("duplicates_removed", 0)
|
|
1219
|
-
consolidated = result.get("items_consolidated", 0)
|
|
1220
|
-
reordered = result.get("items_reordered", 0)
|
|
1221
|
-
|
|
1222
|
-
if duplicates > 0:
|
|
1223
|
-
print(f" Duplicates removed: {duplicates}")
|
|
1224
|
-
if consolidated > 0:
|
|
1225
|
-
print(f" Items consolidated: {consolidated}")
|
|
1226
|
-
if reordered > 0:
|
|
1227
|
-
print(f" Sections reordered: {reordered}")
|
|
1228
|
-
|
|
1229
|
-
backup_path = result.get("backup_created")
|
|
1230
|
-
if backup_path:
|
|
1231
|
-
print(f" Backup created: {backup_path}")
|
|
651
|
+
quiet = os.environ.get("CLAUDE_MPM_QUIET", "false").lower() == "true"
|
|
652
|
+
formatter = MemoryOutputFormatter(quiet=quiet)
|
|
653
|
+
output = formatter.format_optimization_results(result, is_single_agent=True)
|
|
654
|
+
print(output)
|
|
1232
655
|
|
|
1233
656
|
|
|
1234
657
|
def _display_bulk_optimization_results(result):
|
|
1235
658
|
"""Display optimization results for all agents."""
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
print(
|
|
1240
|
-
print(f" Agents optimized: {summary.get('agents_optimized', 0)}")
|
|
1241
|
-
print(f" Total size before: {summary.get('total_size_before', 0):,} bytes")
|
|
1242
|
-
print(f" Total size after: {summary.get('total_size_after', 0):,} bytes")
|
|
1243
|
-
print(
|
|
1244
|
-
f" Total reduction: {summary.get('total_size_reduction', 0):,} bytes ({summary.get('total_size_reduction_percent', 0)}%)"
|
|
1245
|
-
)
|
|
1246
|
-
print(f" Total duplicates removed: {summary.get('total_duplicates_removed', 0)}")
|
|
1247
|
-
print(f" Total items consolidated: {summary.get('total_items_consolidated', 0)}")
|
|
1248
|
-
|
|
1249
|
-
# Show per-agent summary
|
|
1250
|
-
agents_results = result.get("agents", {})
|
|
1251
|
-
if agents_results:
|
|
1252
|
-
print("\n📊 Per-agent results:")
|
|
1253
|
-
for agent_id, agent_result in agents_results.items():
|
|
1254
|
-
if agent_result.get("success"):
|
|
1255
|
-
reduction = agent_result.get("size_reduction_percent", 0)
|
|
1256
|
-
duplicates = agent_result.get("duplicates_removed", 0)
|
|
1257
|
-
consolidated = agent_result.get("items_consolidated", 0)
|
|
1258
|
-
|
|
1259
|
-
status_parts = []
|
|
1260
|
-
if duplicates > 0:
|
|
1261
|
-
status_parts.append(f"{duplicates} dupes")
|
|
1262
|
-
if consolidated > 0:
|
|
1263
|
-
status_parts.append(f"{consolidated} consolidated")
|
|
1264
|
-
|
|
1265
|
-
status = f" ({', '.join(status_parts)})" if status_parts else ""
|
|
1266
|
-
print(f" {agent_id}: {reduction}% reduction{status}")
|
|
1267
|
-
else:
|
|
1268
|
-
error = agent_result.get("error", "Unknown error")
|
|
1269
|
-
print(f" {agent_id}: ❌ {error}")
|
|
1270
|
-
|
|
659
|
+
quiet = os.environ.get("CLAUDE_MPM_QUIET", "false").lower() == "true"
|
|
660
|
+
formatter = MemoryOutputFormatter(quiet=quiet)
|
|
661
|
+
output = formatter.format_optimization_results(result, is_single_agent=False)
|
|
662
|
+
print(output)
|
|
1271
663
|
|
|
1272
|
-
def _output_all_memories_raw(memory_manager):
|
|
1273
|
-
"""
|
|
1274
|
-
Output all agent memories in raw JSON format.
|
|
1275
|
-
|
|
1276
|
-
WHY: Provides programmatic access to all agent memories for external tools,
|
|
1277
|
-
scripts, or APIs that need to process or analyze the complete memory state.
|
|
1278
|
-
|
|
1279
|
-
Args:
|
|
1280
|
-
memory_manager: AgentMemoryManager instance
|
|
1281
|
-
"""
|
|
1282
|
-
try:
|
|
1283
|
-
raw_data = memory_manager.get_all_memories_raw()
|
|
1284
|
-
print(json.dumps(raw_data, indent=2, ensure_ascii=False))
|
|
1285
|
-
except Exception as e:
|
|
1286
|
-
error_output = {
|
|
1287
|
-
"success": False,
|
|
1288
|
-
"error": f"Failed to retrieve all memories: {e!s}",
|
|
1289
|
-
"timestamp": datetime.now().isoformat(),
|
|
1290
|
-
}
|
|
1291
|
-
print(json.dumps(error_output, indent=2))
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
def _output_single_agent_raw(agent_id, memory_manager):
|
|
1295
|
-
"""
|
|
1296
|
-
Output single agent memory in raw JSON format.
|
|
1297
664
|
|
|
1298
|
-
|
|
1299
|
-
targeted analysis or processing by external tools.
|
|
1300
|
-
|
|
1301
|
-
Args:
|
|
1302
|
-
agent_id: ID of the agent to retrieve memory for
|
|
1303
|
-
memory_manager: AgentMemoryManager instance
|
|
1304
|
-
"""
|
|
1305
|
-
try:
|
|
1306
|
-
# Get all memories and extract the specific agent
|
|
1307
|
-
all_memories = memory_manager.get_all_memories_raw()
|
|
1308
|
-
|
|
1309
|
-
if not all_memories.get("success", False):
|
|
1310
|
-
error_output = {
|
|
1311
|
-
"success": False,
|
|
1312
|
-
"error": all_memories.get("error", "Failed to retrieve memories"),
|
|
1313
|
-
"timestamp": datetime.now().isoformat(),
|
|
1314
|
-
}
|
|
1315
|
-
print(json.dumps(error_output, indent=2))
|
|
1316
|
-
return
|
|
1317
|
-
|
|
1318
|
-
agents = all_memories.get("agents", {})
|
|
1319
|
-
if agent_id not in agents:
|
|
1320
|
-
error_output = {
|
|
1321
|
-
"success": False,
|
|
1322
|
-
"error": f"No memory found for agent: {agent_id}",
|
|
1323
|
-
"available_agents": list(agents.keys()),
|
|
1324
|
-
"timestamp": datetime.now().isoformat(),
|
|
1325
|
-
}
|
|
1326
|
-
print(json.dumps(error_output, indent=2))
|
|
1327
|
-
return
|
|
1328
|
-
|
|
1329
|
-
# Return single agent data with metadata
|
|
1330
|
-
single_agent_output = {
|
|
1331
|
-
"success": True,
|
|
1332
|
-
"timestamp": all_memories["timestamp"],
|
|
1333
|
-
"agent": agents[agent_id],
|
|
1334
|
-
}
|
|
1335
|
-
|
|
1336
|
-
print(json.dumps(single_agent_output, indent=2, ensure_ascii=False))
|
|
1337
|
-
|
|
1338
|
-
except Exception as e:
|
|
1339
|
-
error_output = {
|
|
1340
|
-
"success": False,
|
|
1341
|
-
"error": f"Failed to retrieve memory for agent {agent_id}: {e!s}",
|
|
1342
|
-
"timestamp": datetime.now().isoformat(),
|
|
1343
|
-
}
|
|
1344
|
-
print(json.dumps(error_output, indent=2))
|
|
665
|
+
# Note: Raw output functions have been moved to MemoryCRUDService
|