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.
Files changed (87) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_AGENT_TEMPLATE.md +16 -19
  3. claude_mpm/agents/MEMORY.md +21 -49
  4. claude_mpm/agents/templates/OPTIMIZATION_REPORT.md +156 -0
  5. claude_mpm/agents/templates/api_qa.json +36 -116
  6. claude_mpm/agents/templates/backup/data_engineer_agent_20250726_234551.json +42 -9
  7. claude_mpm/agents/templates/backup/documentation_agent_20250726_234551.json +29 -6
  8. claude_mpm/agents/templates/backup/engineer_agent_20250726_234551.json +34 -6
  9. claude_mpm/agents/templates/backup/ops_agent_20250726_234551.json +41 -9
  10. claude_mpm/agents/templates/backup/qa_agent_20250726_234551.json +30 -8
  11. claude_mpm/agents/templates/backup/research_agent_2025011_234551.json +2 -2
  12. claude_mpm/agents/templates/backup/research_agent_20250726_234551.json +29 -6
  13. claude_mpm/agents/templates/backup/research_memory_efficient.json +2 -2
  14. claude_mpm/agents/templates/backup/security_agent_20250726_234551.json +41 -9
  15. claude_mpm/agents/templates/backup/version_control_agent_20250726_234551.json +23 -7
  16. claude_mpm/agents/templates/code_analyzer.json +18 -36
  17. claude_mpm/agents/templates/data_engineer.json +43 -14
  18. claude_mpm/agents/templates/documentation.json +55 -74
  19. claude_mpm/agents/templates/engineer.json +57 -40
  20. claude_mpm/agents/templates/imagemagick.json +7 -2
  21. claude_mpm/agents/templates/memory_manager.json +1 -1
  22. claude_mpm/agents/templates/ops.json +36 -4
  23. claude_mpm/agents/templates/project_organizer.json +23 -71
  24. claude_mpm/agents/templates/qa.json +34 -2
  25. claude_mpm/agents/templates/refactoring_engineer.json +9 -5
  26. claude_mpm/agents/templates/research.json +36 -4
  27. claude_mpm/agents/templates/security.json +29 -2
  28. claude_mpm/agents/templates/ticketing.json +3 -3
  29. claude_mpm/agents/templates/vercel_ops_agent.json +2 -2
  30. claude_mpm/agents/templates/version_control.json +28 -2
  31. claude_mpm/agents/templates/web_qa.json +38 -151
  32. claude_mpm/agents/templates/web_ui.json +2 -2
  33. claude_mpm/cli/commands/agent_manager.py +221 -1
  34. claude_mpm/cli/commands/agents.py +556 -1009
  35. claude_mpm/cli/commands/memory.py +248 -927
  36. claude_mpm/cli/commands/run.py +139 -484
  37. claude_mpm/cli/parsers/agent_manager_parser.py +34 -0
  38. claude_mpm/cli/startup_logging.py +76 -0
  39. claude_mpm/core/agent_registry.py +6 -10
  40. claude_mpm/core/framework_loader.py +205 -595
  41. claude_mpm/core/log_manager.py +49 -1
  42. claude_mpm/core/logging_config.py +2 -4
  43. claude_mpm/hooks/claude_hooks/event_handlers.py +7 -117
  44. claude_mpm/hooks/claude_hooks/hook_handler.py +91 -755
  45. claude_mpm/hooks/claude_hooks/hook_handler_original.py +1040 -0
  46. claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +347 -0
  47. claude_mpm/hooks/claude_hooks/services/__init__.py +13 -0
  48. claude_mpm/hooks/claude_hooks/services/connection_manager.py +190 -0
  49. claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
  50. claude_mpm/hooks/claude_hooks/services/state_manager.py +282 -0
  51. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
  52. claude_mpm/services/agents/deployment/agent_deployment.py +42 -454
  53. claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
  54. claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
  55. claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
  56. claude_mpm/services/agents/memory/agent_memory_manager.py +42 -508
  57. claude_mpm/services/agents/memory/memory_categorization_service.py +165 -0
  58. claude_mpm/services/agents/memory/memory_file_service.py +103 -0
  59. claude_mpm/services/agents/memory/memory_format_service.py +201 -0
  60. claude_mpm/services/agents/memory/memory_limits_service.py +99 -0
  61. claude_mpm/services/agents/registry/__init__.py +1 -1
  62. claude_mpm/services/cli/__init__.py +18 -0
  63. claude_mpm/services/cli/agent_cleanup_service.py +407 -0
  64. claude_mpm/services/cli/agent_dependency_service.py +395 -0
  65. claude_mpm/services/cli/agent_listing_service.py +463 -0
  66. claude_mpm/services/cli/agent_output_formatter.py +605 -0
  67. claude_mpm/services/cli/agent_validation_service.py +589 -0
  68. claude_mpm/services/cli/dashboard_launcher.py +424 -0
  69. claude_mpm/services/cli/memory_crud_service.py +617 -0
  70. claude_mpm/services/cli/memory_output_formatter.py +604 -0
  71. claude_mpm/services/cli/session_manager.py +513 -0
  72. claude_mpm/services/cli/socketio_manager.py +498 -0
  73. claude_mpm/services/cli/startup_checker.py +370 -0
  74. claude_mpm/services/core/cache_manager.py +311 -0
  75. claude_mpm/services/core/memory_manager.py +637 -0
  76. claude_mpm/services/core/path_resolver.py +498 -0
  77. claude_mpm/services/core/service_container.py +520 -0
  78. claude_mpm/services/core/service_interfaces.py +436 -0
  79. claude_mpm/services/diagnostics/checks/agent_check.py +65 -19
  80. claude_mpm/services/memory/router.py +116 -10
  81. {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.4.dist-info}/METADATA +1 -1
  82. {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.4.dist-info}/RECORD +86 -55
  83. claude_mpm/cli/commands/run_config_checker.py +0 -159
  84. {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.4.dist-info}/WHEEL +0 -0
  85. {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.4.dist-info}/entry_points.txt +0 -0
  86. {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.4.dist-info}/licenses/LICENSE +0 -0
  87. {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 existing function
114
- _show_status(self.memory_manager)
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
- memory_dir = self.memory_manager.memories_dir
143
+ # Use CRUD service to list memories with stats
144
+ result = self.crud_service.list_memories(include_stats=True)
124
145
 
125
- if not memory_dir.exists():
146
+ if not result.get("success"):
126
147
  return {
127
- "memory_directory": str(memory_dir),
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
- agents = []
135
- total_size = 0
136
-
137
- for memory_file in memory_dir.glob("*.md"):
138
- if memory_file.is_file():
139
- size = memory_file.stat().st_size
140
- total_size += size
141
-
142
- agents.append(
143
- {
144
- "agent_id": memory_file.stem,
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": str(memory_dir),
153
- "exists": True,
168
+ "memory_directory": result.get("memory_directory", ""),
169
+ "exists": result.get("exists", False),
154
170
  "agents": agents,
155
- "total_size_kb": total_size / 1024,
156
- "total_files": len(agents),
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
- def _get_memories_data(self, args) -> Dict[str, Any]:
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
- # For structured output, return the initialization task
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
- # Text output using existing function
228
- _init_memory(args, self.memory_manager)
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
- # For structured output, we'd need to implement the actual learning addition
242
- # For now, delegate to existing function and return success
243
- _add_learning(args, self.memory_manager)
244
- return CommandResult.success_result("Learning added to agent memory")
245
- # Text output using existing function
246
- _add_learning(args, self.memory_manager)
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
- # For structured output, return cleanup results
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=cleanup_data
349
+ result.get("message", "Memory cleanup completed"), data=result
267
350
  )
268
- # Text output using existing function
269
- _clean_memory(args, self.memory_manager)
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, return optimization results
283
- optimization_data = {
284
- "optimized_agents": [],
285
- "size_reduction": 0,
286
- "summary": "Memory optimization completed",
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=optimization_data
397
+ "Memory optimization completed", data=result
290
398
  )
291
- # Text output using existing function
292
- _optimize_memory(args, self.memory_manager)
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
- def _init_memory(args, memory_manager):
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
- Args:
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
- Args:
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
- if not status.get("success", True):
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
- # Show per-agent details
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
- except Exception as e:
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
- def _show_basic_status(memory_manager):
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
- if result.get("success"):
803
- print(" Successfully processed documentation")
804
- print(f" Files processed: {result.get('files_processed', 0)}")
805
- print(f" Memories created: {result.get('memories_created', 0)}")
806
- print(f" Memories updated: {result.get('memories_updated', 0)}")
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
- if result.get("success") is False:
861
- print(f"❌ Analysis failed: {result.get('error', 'Unknown error')}")
862
- return
863
-
864
- # Display common patterns
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
- def _show_memories(args, memory_manager):
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
- agent_id = result.get("agent_id", "unknown")
1208
- original_size = result.get("original_size", 0)
1209
- optimized_size = result.get("optimized_size", 0)
1210
- size_reduction = result.get("size_reduction", 0)
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
- summary = result.get("summary", {})
1237
-
1238
- print("✅ Bulk optimization completed")
1239
- print(f" Agents processed: {summary.get('agents_processed', 0)}")
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
- WHY: Provides programmatic access to a specific agent's memory for
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