claude-mpm 3.3.0__py3-none-any.whl → 3.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. claude_mpm/agents/templates/data_engineer.json +1 -1
  2. claude_mpm/agents/templates/documentation.json +1 -1
  3. claude_mpm/agents/templates/engineer.json +1 -1
  4. claude_mpm/agents/templates/ops.json +1 -1
  5. claude_mpm/agents/templates/pm.json +1 -1
  6. claude_mpm/agents/templates/qa.json +1 -1
  7. claude_mpm/agents/templates/research.json +1 -1
  8. claude_mpm/agents/templates/security.json +1 -1
  9. claude_mpm/agents/templates/test_integration.json +112 -0
  10. claude_mpm/agents/templates/version_control.json +1 -1
  11. claude_mpm/cli/commands/memory.py +749 -26
  12. claude_mpm/cli/commands/run.py +115 -14
  13. claude_mpm/cli/parser.py +89 -1
  14. claude_mpm/constants.py +6 -0
  15. claude_mpm/core/claude_runner.py +74 -11
  16. claude_mpm/core/config.py +1 -1
  17. claude_mpm/core/session_manager.py +46 -0
  18. claude_mpm/core/simple_runner.py +74 -11
  19. claude_mpm/hooks/builtin/mpm_command_hook.py +5 -5
  20. claude_mpm/hooks/claude_hooks/hook_handler.py +213 -30
  21. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +9 -2
  22. claude_mpm/hooks/memory_integration_hook.py +51 -5
  23. claude_mpm/services/__init__.py +23 -5
  24. claude_mpm/services/agent_memory_manager.py +800 -71
  25. claude_mpm/services/memory_builder.py +823 -0
  26. claude_mpm/services/memory_optimizer.py +619 -0
  27. claude_mpm/services/memory_router.py +445 -0
  28. claude_mpm/services/project_analyzer.py +771 -0
  29. claude_mpm/services/socketio_server.py +649 -45
  30. claude_mpm/services/version_control/git_operations.py +26 -0
  31. claude_mpm-3.4.0.dist-info/METADATA +183 -0
  32. {claude_mpm-3.3.0.dist-info → claude_mpm-3.4.0.dist-info}/RECORD +36 -52
  33. claude_mpm/agents/agent-template.yaml +0 -83
  34. claude_mpm/agents/templates/test-integration-agent.md +0 -34
  35. claude_mpm/agents/test_fix_deployment/.claude-pm/config/project.json +0 -6
  36. claude_mpm/cli/README.md +0 -109
  37. claude_mpm/cli_module/refactoring_guide.md +0 -253
  38. claude_mpm/core/agent_registry.py.bak +0 -312
  39. claude_mpm/core/base_service.py.bak +0 -406
  40. claude_mpm/core/websocket_handler.py +0 -233
  41. claude_mpm/hooks/README.md +0 -97
  42. claude_mpm/orchestration/SUBPROCESS_DESIGN.md +0 -66
  43. claude_mpm/schemas/README_SECURITY.md +0 -92
  44. claude_mpm/schemas/agent_schema.json +0 -395
  45. claude_mpm/schemas/agent_schema_documentation.md +0 -181
  46. claude_mpm/schemas/agent_schema_security_notes.md +0 -165
  47. claude_mpm/schemas/examples/standard_workflow.json +0 -505
  48. claude_mpm/schemas/ticket_workflow_documentation.md +0 -482
  49. claude_mpm/schemas/ticket_workflow_schema.json +0 -590
  50. claude_mpm/services/framework_claude_md_generator/README.md +0 -92
  51. claude_mpm/services/parent_directory_manager/README.md +0 -83
  52. claude_mpm/services/version_control/VERSION +0 -1
  53. claude_mpm/services/websocket_server.py +0 -376
  54. claude_mpm-3.3.0.dist-info/METADATA +0 -432
  55. {claude_mpm-3.3.0.dist-info → claude_mpm-3.4.0.dist-info}/WHEEL +0 -0
  56. {claude_mpm-3.3.0.dist-info → claude_mpm-3.4.0.dist-info}/entry_points.txt +0 -0
  57. {claude_mpm-3.3.0.dist-info → claude_mpm-3.4.0.dist-info}/licenses/LICENSE +0 -0
  58. {claude_mpm-3.3.0.dist-info → claude_mpm-3.4.0.dist-info}/top_level.txt +0 -0
@@ -49,7 +49,7 @@ def manage_memory(args):
49
49
  _show_status(memory_manager)
50
50
 
51
51
  elif args.memory_command == "view":
52
- _view_memory(args, memory_manager)
52
+ _show_memories(args, memory_manager)
53
53
 
54
54
  elif args.memory_command == "add":
55
55
  _add_learning(args, memory_manager)
@@ -57,6 +57,30 @@ def manage_memory(args):
57
57
  elif args.memory_command == "clean":
58
58
  _clean_memory(args, memory_manager)
59
59
 
60
+ elif args.memory_command == "optimize":
61
+ _optimize_memory(args, memory_manager)
62
+
63
+ elif args.memory_command == "build":
64
+ _build_memory(args, memory_manager)
65
+
66
+ elif args.memory_command == "cross-ref":
67
+ _cross_reference_memory(args, memory_manager)
68
+
69
+ elif args.memory_command == "route":
70
+ _route_memory_command(args, memory_manager)
71
+
72
+ elif args.memory_command == "show":
73
+ _show_memories(args, memory_manager)
74
+
75
+ elif args.memory_command == "init":
76
+ _init_memory(args, memory_manager)
77
+
78
+ else:
79
+ logger.error(f"Unknown memory command: {args.memory_command}")
80
+ print(f"Unknown memory command: {args.memory_command}")
81
+ print("Available commands: init, status, view, add, clean, optimize, build, cross-ref, route, show")
82
+ return 1
83
+
60
84
  except Exception as e:
61
85
  logger.error(f"Error managing memory: {e}")
62
86
  print(f"❌ Error: {e}")
@@ -65,19 +89,170 @@ def manage_memory(args):
65
89
  return 0
66
90
 
67
91
 
92
+ def _init_memory(args, memory_manager):
93
+ """
94
+ Initialize project-specific memories via agent delegation.
95
+
96
+ WHY: When starting with a new project, agents need project-specific knowledge
97
+ beyond what automatic analysis provides. This command triggers an agent task
98
+ to comprehensively scan the project and create custom memories.
99
+
100
+ Args:
101
+ args: Command line arguments (unused but kept for consistency)
102
+ memory_manager: AgentMemoryManager instance
103
+ """
104
+ logger = get_logger("cli")
105
+
106
+ print("🚀 Initializing project-specific memories...")
107
+ print("=" * 80)
108
+ print()
109
+ print("This will analyze the project to:")
110
+ print(" 1. Scan project structure and documentation")
111
+ print(" 2. Analyze source code for patterns and conventions")
112
+ print(" 3. Create targeted memories for each agent type")
113
+ print(" 4. Add insights using 'claude-mpm memory add' commands")
114
+ print()
115
+ print("The analysis will cover:")
116
+ print(" • Project architecture and design patterns")
117
+ print(" • Coding conventions and standards")
118
+ print(" • Key modules and integration points")
119
+ print(" • Testing patterns and quality standards")
120
+ print(" • Performance considerations")
121
+ print(" • Domain-specific terminology")
122
+ print()
123
+ print("=" * 80)
124
+ print()
125
+ print("[Agent Task: Initialize Project-Specific Memories]")
126
+ print()
127
+ print("Please analyze this project and create custom memories for all agents.")
128
+ print()
129
+ print("Instructions:")
130
+ print("1. Scan the project structure, documentation, and source code")
131
+ print("2. Identify key patterns, conventions, and project-specific knowledge")
132
+ print("3. Create targeted memories for each agent type")
133
+ print("4. Use 'claude-mpm memory add <agent> <type> \"<content>\"' commands")
134
+ print()
135
+ print("Focus areas:")
136
+ print(" • Architectural patterns and design decisions")
137
+ print(" • Coding conventions from actual source code")
138
+ print(" • Key modules, APIs, and integration points")
139
+ print(" • Testing patterns and quality standards")
140
+ print(" • Performance considerations specific to this project")
141
+ print(" • Common pitfalls based on the codebase")
142
+ print(" • Domain-specific terminology and concepts")
143
+ print()
144
+ print("Example commands to use:")
145
+ print(' claude-mpm memory add engineer pattern "Use dependency injection with @inject"')
146
+ print(' claude-mpm memory add qa pattern "Test files follow test_<module>_<feature>.py"')
147
+ print(' claude-mpm memory add research context "Project uses microservices architecture"')
148
+ print()
149
+ print("Begin by examining the project structure and key files.")
150
+ print()
151
+ print("=" * 80)
152
+ print()
153
+ print("📝 Note: Copy the task above to execute the memory initialization process.")
154
+ print(" Use 'claude-mpm memory add' commands to add discovered insights.")
155
+
156
+
68
157
  def _show_status(memory_manager):
69
158
  """
70
- Show memory file status.
159
+ Show comprehensive memory system status.
71
160
 
72
- WHY: Users need to see what memory files exist, their sizes, and
73
- when they were last updated to understand the memory system state.
161
+ WHY: Users need to see memory system health, file sizes, optimization
162
+ opportunities, and agent-specific statistics to understand the system state.
74
163
 
75
164
  Args:
76
165
  memory_manager: AgentMemoryManager instance
77
166
  """
78
- print("Agent Memory Status")
167
+ print("Agent Memory System Status")
79
168
  print("-" * 80)
80
169
 
170
+ try:
171
+ # Get comprehensive status from memory manager
172
+ status = memory_manager.get_memory_status()
173
+
174
+ if not status.get("success", True):
175
+ print(f"❌ Error getting status: {status.get('error', 'Unknown error')}")
176
+ return
177
+
178
+ # Show system overview
179
+ system_health = status.get("system_health", "unknown")
180
+ health_emoji = {
181
+ "healthy": "✅",
182
+ "needs_optimization": "⚠️",
183
+ "high_usage": "📊",
184
+ "no_memory_dir": "📁"
185
+ }.get(system_health, "❓")
186
+
187
+ print(f"🧠 Memory System Health: {health_emoji} {system_health}")
188
+ print(f"📁 Memory Directory: {status.get('memory_directory', 'Unknown')}")
189
+ print(f"🔧 System Enabled: {'Yes' if status.get('system_enabled', True) else 'No'}")
190
+ print(f"📚 Auto Learning: {'Yes' if status.get('auto_learning', True) else 'No'}")
191
+ print(f"📊 Total Agents: {status.get('total_agents', 0)}")
192
+ print(f"💾 Total Size: {status.get('total_size_kb', 0):.1f} KB")
193
+ print()
194
+
195
+ # Show optimization opportunities
196
+ opportunities = status.get("optimization_opportunities", [])
197
+ if opportunities:
198
+ print(f"⚠️ Optimization Opportunities ({len(opportunities)}):")
199
+ for opportunity in opportunities[:5]: # Show top 5
200
+ print(f" • {opportunity}")
201
+ if len(opportunities) > 5:
202
+ print(f" ... and {len(opportunities) - 5} more")
203
+ print()
204
+
205
+ # Show per-agent details
206
+ agents = status.get("agents", {})
207
+ if agents:
208
+ print(f"📋 Agent Memory Details:")
209
+ for agent_id, agent_info in sorted(agents.items()):
210
+ if "error" in agent_info:
211
+ print(f" ❌ {agent_id}: Error - {agent_info['error']}")
212
+ continue
213
+
214
+ size_kb = agent_info.get("size_kb", 0)
215
+ size_limit = agent_info.get("size_limit_kb", 8)
216
+ utilization = agent_info.get("size_utilization", 0)
217
+ sections = agent_info.get("sections", 0)
218
+ items = agent_info.get("items", 0)
219
+ last_modified = agent_info.get("last_modified", "Unknown")
220
+ auto_learning = agent_info.get("auto_learning", True)
221
+
222
+ # Format last modified time
223
+ try:
224
+ from datetime import datetime
225
+ dt = datetime.fromisoformat(last_modified.replace('Z', '+00:00'))
226
+ last_modified_str = dt.strftime('%Y-%m-%d %H:%M:%S')
227
+ except:
228
+ last_modified_str = last_modified
229
+
230
+ # Status indicator based on usage
231
+ if utilization > 90:
232
+ status_emoji = "🔴" # High usage
233
+ elif utilization > 70:
234
+ status_emoji = "🟡" # Medium usage
235
+ else:
236
+ status_emoji = "🟢" # Low usage
237
+
238
+ print(f" {status_emoji} {agent_id}")
239
+ print(f" Size: {size_kb:.1f} KB / {size_limit} KB ({utilization:.1f}%)")
240
+ print(f" Content: {sections} sections, {items} items")
241
+ print(f" Auto-learning: {'On' if auto_learning else 'Off'}")
242
+ print(f" Last modified: {last_modified_str}")
243
+ else:
244
+ print("📭 No agent memories found")
245
+
246
+ except Exception as e:
247
+ print(f"❌ Error showing status: {e}")
248
+ # Fallback to basic status display
249
+ _show_basic_status(memory_manager)
250
+
251
+
252
+ def _show_basic_status(memory_manager):
253
+ """Fallback basic status display if comprehensive status fails."""
254
+ print("\n--- Basic Status (Fallback) ---")
255
+
81
256
  memory_dir = memory_manager.memories_dir
82
257
  if not memory_dir.exists():
83
258
  print("📁 Memory directory not found - no agent memories stored yet")
@@ -93,7 +268,6 @@ def _show_status(memory_manager):
93
268
 
94
269
  print(f"📁 Memory directory: {memory_dir}")
95
270
  print(f"📊 Total memory files: {len(memory_files)}")
96
- print()
97
271
 
98
272
  total_size = 0
99
273
  for file_path in sorted(memory_files):
@@ -101,26 +275,8 @@ def _show_status(memory_manager):
101
275
  size_kb = stat.st_size / 1024
102
276
  total_size += stat.st_size
103
277
 
104
- # Extract agent ID from filename (remove '_agent' suffix)
105
278
  agent_id = file_path.stem.replace('_agent', '')
106
-
107
- # Try to count sections in markdown file
108
- try:
109
- content = file_path.read_text()
110
- # Count level 2 headers (sections)
111
- section_count = len([line for line in content.splitlines() if line.startswith('## ')])
112
- # Count bullet points (learnings)
113
- learning_count = len([line for line in content.splitlines() if line.strip().startswith('- ')])
114
- except:
115
- section_count = "?"
116
- learning_count = "?"
117
-
118
- print(f"🧠 {agent_id}")
119
- print(f" Size: {size_kb:.1f} KB")
120
- print(f" Sections: {section_count}")
121
- print(f" Items: {learning_count}")
122
- print(f" Last modified: {datetime.fromtimestamp(stat.st_mtime).strftime('%Y-%m-%d %H:%M:%S')}")
123
- print()
279
+ print(f" {agent_id}: {size_kb:.1f} KB")
124
280
 
125
281
  print(f"💾 Total size: {total_size / 1024:.1f} KB")
126
282
 
@@ -229,4 +385,571 @@ def _clean_memory(args, memory_manager):
229
385
  print(" Future cleanup will remove:")
230
386
  print(" - Memory files older than 30 days with no recent access")
231
387
  print(" - Corrupted memory files")
232
- print(" - Memory files for non-existent agents")
388
+ print(" - Memory files for non-existent agents")
389
+
390
+
391
+ def _optimize_memory(args, memory_manager):
392
+ """
393
+ Optimize memory files by removing duplicates and consolidating similar items.
394
+
395
+ WHY: Memory files can become cluttered over time with duplicate or redundant
396
+ information. This command provides automated cleanup while preserving
397
+ important learnings.
398
+
399
+ Args:
400
+ args: Command arguments with optional agent_id
401
+ memory_manager: AgentMemoryManager instance
402
+ """
403
+ print("🔧 Memory Optimization")
404
+ print("-" * 80)
405
+
406
+ agent_id = getattr(args, 'agent_id', None)
407
+
408
+ try:
409
+ if agent_id:
410
+ print(f"📊 Optimizing memory for agent: {agent_id}")
411
+ result = memory_manager.optimize_memory(agent_id)
412
+ else:
413
+ print("📊 Optimizing all agent memories...")
414
+ result = memory_manager.optimize_memory()
415
+
416
+ if result.get("success"):
417
+ if agent_id:
418
+ # Single agent results
419
+ _display_single_optimization_result(result)
420
+ else:
421
+ # All agents results
422
+ _display_bulk_optimization_results(result)
423
+ else:
424
+ print(f"❌ Optimization failed: {result.get('error', 'Unknown error')}")
425
+
426
+ except Exception as e:
427
+ print(f"❌ Error during optimization: {e}")
428
+
429
+
430
+ def _build_memory(args, memory_manager):
431
+ """
432
+ Build agent memories from project documentation.
433
+
434
+ WHY: Project documentation contains valuable patterns and guidelines that
435
+ agents should be aware of. This command automatically extracts and assigns
436
+ relevant information to appropriate agents.
437
+
438
+ Args:
439
+ args: Command arguments with optional force_rebuild flag
440
+ memory_manager: AgentMemoryManager instance
441
+ """
442
+ print("📚 Memory Building from Documentation")
443
+ print("-" * 80)
444
+
445
+ force_rebuild = getattr(args, 'force_rebuild', False)
446
+
447
+ try:
448
+ print("🔍 Analyzing project documentation...")
449
+ result = memory_manager.build_memories_from_docs(force_rebuild)
450
+
451
+ if result.get("success"):
452
+ print(f"✅ Successfully processed documentation")
453
+ print(f" Files processed: {result.get('files_processed', 0)}")
454
+ print(f" Memories created: {result.get('memories_created', 0)}")
455
+ print(f" Memories updated: {result.get('memories_updated', 0)}")
456
+ print(f" Agents affected: {result.get('total_agents_affected', 0)}")
457
+
458
+ if result.get('agents_affected'):
459
+ print(f" Affected agents: {', '.join(result['agents_affected'])}")
460
+
461
+ # Show file-specific results
462
+ files_results = result.get('files', {})
463
+ if files_results:
464
+ print("\n📄 File processing details:")
465
+ for file_path, file_result in files_results.items():
466
+ if file_result.get('success'):
467
+ extracted = file_result.get('items_extracted', 0)
468
+ created = file_result.get('memories_created', 0)
469
+ print(f" {file_path}: {extracted} items extracted, {created} memories created")
470
+
471
+ if result.get('errors'):
472
+ print("\n⚠️ Errors encountered:")
473
+ for error in result['errors']:
474
+ print(f" {error}")
475
+
476
+ else:
477
+ print(f"❌ Build failed: {result.get('error', 'Unknown error')}")
478
+
479
+ except Exception as e:
480
+ print(f"❌ Error building memories: {e}")
481
+
482
+
483
+ def _cross_reference_memory(args, memory_manager):
484
+ """
485
+ Find cross-references and common patterns across agent memories.
486
+
487
+ WHY: Different agents may have learned similar information or there may be
488
+ knowledge gaps that can be identified through cross-referencing.
489
+
490
+ Args:
491
+ args: Command arguments with optional query
492
+ memory_manager: AgentMemoryManager instance
493
+ """
494
+ print("🔗 Memory Cross-Reference Analysis")
495
+ print("-" * 80)
496
+
497
+ query = getattr(args, 'query', None)
498
+
499
+ try:
500
+ if query:
501
+ print(f"🔍 Searching for: '{query}'")
502
+ else:
503
+ print("🔍 Analyzing all agent memories for patterns...")
504
+
505
+ result = memory_manager.cross_reference_memories(query)
506
+
507
+ if result.get("success") is False:
508
+ print(f"❌ Analysis failed: {result.get('error', 'Unknown error')}")
509
+ return
510
+
511
+ # Display common patterns
512
+ common_patterns = result.get("common_patterns", [])
513
+ if common_patterns:
514
+ print(f"\n🔄 Common patterns found ({len(common_patterns)}):")
515
+ for pattern in common_patterns[:10]: # Show top 10
516
+ agents = ', '.join(pattern['agents'])
517
+ print(f" • {pattern['pattern']}")
518
+ print(f" Found in: {agents} ({pattern['count']} instances)")
519
+ else:
520
+ print("\n🔄 No common patterns found")
521
+
522
+ # Display query matches if query was provided
523
+ if query and result.get("query_matches"):
524
+ print(f"\n🎯 Query matches for '{query}':")
525
+ for match in result["query_matches"]:
526
+ print(f" 📋 {match['agent']}:")
527
+ for line in match['matches'][:3]: # Show first 3 matches
528
+ print(f" • {line}")
529
+
530
+ # Display agent correlations
531
+ correlations = result.get("agent_correlations", {})
532
+ if correlations:
533
+ print(f"\n🤝 Agent knowledge correlations:")
534
+ sorted_correlations = sorted(correlations.items(), key=lambda x: x[1], reverse=True)
535
+ for agents, count in sorted_correlations[:5]: # Show top 5
536
+ print(f" {agents}: {count} common items")
537
+ else:
538
+ print("\n🤝 No significant correlations found")
539
+
540
+ except Exception as e:
541
+ print(f"❌ Error during cross-reference analysis: {e}")
542
+
543
+
544
+ def _show_memories(args, memory_manager):
545
+ """
546
+ Show agent memories in a user-friendly format with cross-references and patterns.
547
+
548
+ WHY: Users need to see agent memories in a readable format to understand
549
+ what agents have learned and identify common patterns across agents.
550
+
551
+ DESIGN DECISION: Added --raw flag to output structured JSON data for
552
+ programmatic processing, enabling external tools and scripts to access
553
+ all agent memories in a structured format.
554
+
555
+ Args:
556
+ args: Command arguments with optional agent_id, format, and raw flag
557
+ memory_manager: AgentMemoryManager instance
558
+ """
559
+ agent_id = getattr(args, 'agent_id', None)
560
+ format_type = getattr(args, 'format', 'detailed')
561
+ raw_output = getattr(args, 'raw', False)
562
+
563
+ try:
564
+ if raw_output:
565
+ # Output structured JSON data
566
+ if agent_id:
567
+ # Get single agent memory in raw format
568
+ _output_single_agent_raw(agent_id, memory_manager)
569
+ else:
570
+ # Get all agent memories in raw format
571
+ _output_all_memories_raw(memory_manager)
572
+ else:
573
+ # Normal user-friendly display
574
+ print("🧠 Agent Memories Display")
575
+ print("-" * 80)
576
+
577
+ if agent_id:
578
+ _show_single_agent_memory(agent_id, format_type, memory_manager)
579
+ else:
580
+ _show_all_agent_memories(format_type, memory_manager)
581
+
582
+ except Exception as e:
583
+ if raw_output:
584
+ # Output error in JSON format for consistency
585
+ error_output = {
586
+ "success": False,
587
+ "error": str(e),
588
+ "timestamp": datetime.now().isoformat()
589
+ }
590
+ print(json.dumps(error_output, indent=2))
591
+ else:
592
+ print(f"❌ Error showing memories: {e}")
593
+
594
+
595
+ def _show_single_agent_memory(agent_id, format_type, memory_manager):
596
+ """Show memory for a single agent in the specified format."""
597
+ memory_content = memory_manager.load_agent_memory(agent_id)
598
+
599
+ if not memory_content:
600
+ print(f"📭 No memory found for agent: {agent_id}")
601
+ return
602
+
603
+ print(f"🤖 Agent: {agent_id}")
604
+ print("-" * 40)
605
+
606
+ if format_type == 'full':
607
+ print(memory_content)
608
+ else:
609
+ # Parse and display memory sections
610
+ sections = _parse_memory_content(memory_content)
611
+
612
+ for section_name, items in sections.items():
613
+ if items:
614
+ print(f"\n📚 {section_name} ({len(items)} items):")
615
+ for i, item in enumerate(items[:5], 1): # Show first 5 items
616
+ print(f" {i}. {item}")
617
+ if len(items) > 5:
618
+ print(f" ... and {len(items) - 5} more")
619
+
620
+
621
+ def _show_all_agent_memories(format_type, memory_manager):
622
+ """Show memories for all agents with cross-references."""
623
+ # Get all available agent memory files
624
+ memory_dir = memory_manager.memories_dir
625
+ if not memory_dir.exists():
626
+ print("📁 No memory directory found")
627
+ return
628
+
629
+ memory_files = list(memory_dir.glob("*_agent.md"))
630
+ if not memory_files:
631
+ print("📭 No agent memories found")
632
+ return
633
+
634
+ print(f"📊 Found memories for {len(memory_files)} agents")
635
+ print()
636
+
637
+ agent_memories = {}
638
+ total_items = 0
639
+
640
+ # Load all agent memories
641
+ for file_path in sorted(memory_files):
642
+ agent_id = file_path.stem.replace('_agent', '')
643
+ try:
644
+ memory_content = memory_manager.load_agent_memory(agent_id)
645
+ if memory_content:
646
+ sections = _parse_memory_content(memory_content)
647
+ agent_memories[agent_id] = sections
648
+
649
+ # Count items
650
+ item_count = sum(len(items) for items in sections.values())
651
+ total_items += item_count
652
+
653
+ if format_type == 'summary':
654
+ print(f"🤖 {agent_id}")
655
+ print(f" 📚 {len(sections)} sections, {item_count} total items")
656
+
657
+ # Show section summary
658
+ for section_name, items in sections.items():
659
+ if items:
660
+ print(f" • {section_name}: {len(items)} items")
661
+ print()
662
+ elif format_type == 'detailed':
663
+ print(f"🤖 {agent_id}")
664
+ print(f" 📚 {len(sections)} sections, {item_count} total items")
665
+
666
+ for section_name, items in sections.items():
667
+ if items:
668
+ print(f"\n 📖 {section_name}:")
669
+ for item in items[:3]: # Show first 3 items
670
+ print(f" • {item}")
671
+ if len(items) > 3:
672
+ print(f" ... and {len(items) - 3} more")
673
+ print()
674
+ except Exception as e:
675
+ print(f"❌ Error loading memory for {agent_id}: {e}")
676
+
677
+ print(f"📊 Total: {total_items} memory items across {len(agent_memories)} agents")
678
+
679
+ # Show cross-references if we have multiple agents
680
+ if len(agent_memories) > 1:
681
+ print("\n🔗 Cross-References and Common Patterns:")
682
+ _find_common_patterns(agent_memories)
683
+
684
+
685
+ def _parse_memory_content(content):
686
+ """Parse memory content into sections and items."""
687
+ sections = {}
688
+ current_section = None
689
+ current_items = []
690
+
691
+ for line in content.split('\n'):
692
+ line = line.strip()
693
+
694
+ if line.startswith('## ') and not line.startswith('## Memory Usage'):
695
+ # New section
696
+ if current_section and current_items:
697
+ sections[current_section] = current_items.copy()
698
+
699
+ current_section = line[3:].strip()
700
+ current_items = []
701
+ elif line.startswith('- ') and current_section:
702
+ # Item in current section
703
+ item = line[2:].strip()
704
+ if item and len(item) > 5: # Filter out very short items
705
+ current_items.append(item)
706
+
707
+ # Add final section
708
+ if current_section and current_items:
709
+ sections[current_section] = current_items
710
+
711
+ return sections
712
+
713
+
714
+ def _find_common_patterns(agent_memories):
715
+ """Find common patterns across agent memories."""
716
+ pattern_count = {}
717
+ agent_patterns = {}
718
+
719
+ # Collect all patterns and which agents have them
720
+ for agent_id, sections in agent_memories.items():
721
+ agent_patterns[agent_id] = set()
722
+
723
+ for section_name, items in sections.items():
724
+ for item in items:
725
+ # Normalize item for comparison (lowercase, basic cleanup)
726
+ normalized = item.lower().strip()
727
+ if len(normalized) > 10: # Skip very short items
728
+ pattern_count[normalized] = pattern_count.get(normalized, 0) + 1
729
+ agent_patterns[agent_id].add(normalized)
730
+
731
+ # Find patterns that appear in multiple agents
732
+ common_patterns = [(pattern, count) for pattern, count in pattern_count.items() if count > 1]
733
+ common_patterns.sort(key=lambda x: x[1], reverse=True)
734
+
735
+ if common_patterns:
736
+ print("\n🔄 Most Common Patterns:")
737
+ for pattern, count in common_patterns[:5]:
738
+ # Find which agents have this pattern
739
+ agents_with_pattern = [agent for agent, patterns in agent_patterns.items()
740
+ if pattern in patterns]
741
+ print(f" • {pattern[:80]}{'...' if len(pattern) > 80 else ''}")
742
+ print(f" Found in: {', '.join(agents_with_pattern)} ({count} agents)")
743
+ print()
744
+ else:
745
+ print(" No common patterns found across agents")
746
+
747
+ # Show agent similarities
748
+ print("\n🤝 Agent Knowledge Similarity:")
749
+ agents = list(agent_memories.keys())
750
+ for i, agent1 in enumerate(agents):
751
+ for agent2 in agents[i+1:]:
752
+ common_items = len(agent_patterns[agent1] & agent_patterns[agent2])
753
+ if common_items > 0:
754
+ total_items = len(agent_patterns[agent1] | agent_patterns[agent2])
755
+ similarity = (common_items / total_items) * 100 if total_items > 0 else 0
756
+ print(f" {agent1} ↔ {agent2}: {common_items} common items ({similarity:.1f}% similarity)")
757
+
758
+
759
+ def _route_memory_command(args, memory_manager):
760
+ """
761
+ Test memory command routing logic.
762
+
763
+ WHY: Users and developers need to understand how memory commands are routed
764
+ to appropriate agents for debugging and customization purposes.
765
+
766
+ Args:
767
+ args: Command arguments with content to route
768
+ memory_manager: AgentMemoryManager instance
769
+ """
770
+ print("🎯 Memory Command Routing Test")
771
+ print("-" * 80)
772
+
773
+ content = getattr(args, 'content', None)
774
+ if not content:
775
+ print("❌ No content provided for routing analysis")
776
+ print(" Usage: memory route --content 'your content here'")
777
+ return
778
+
779
+ try:
780
+ print(f"📝 Analyzing content: '{content[:100]}{'...' if len(content) > 100 else ''}'")
781
+
782
+ result = memory_manager.route_memory_command(content)
783
+
784
+ if result.get("success") is False:
785
+ print(f"❌ Routing failed: {result.get('error', 'Unknown error')}")
786
+ return
787
+
788
+ target_agent = result.get("target_agent", "unknown")
789
+ section = result.get("section", "unknown")
790
+ confidence = result.get("confidence", 0.0)
791
+ reasoning = result.get("reasoning", "No reasoning provided")
792
+
793
+ print(f"\n🎯 Routing Decision:")
794
+ print(f" Target Agent: {target_agent}")
795
+ print(f" Section: {section}")
796
+ print(f" Confidence: {confidence:.2f}")
797
+ print(f" Reasoning: {reasoning}")
798
+
799
+ # Show agent scores if available
800
+ agent_scores = result.get("agent_scores", {})
801
+ if agent_scores:
802
+ print(f"\n📊 Agent Relevance Scores:")
803
+ sorted_scores = sorted(
804
+ [(agent, data['score']) for agent, data in agent_scores.items()],
805
+ key=lambda x: x[1], reverse=True
806
+ )
807
+ for agent, score in sorted_scores[:5]: # Show top 5
808
+ print(f" {agent}: {score:.3f}")
809
+ # Show matched keywords if available
810
+ if agent in agent_scores and agent_scores[agent].get('matched_keywords'):
811
+ keywords = ', '.join(agent_scores[agent]['matched_keywords'][:3])
812
+ print(f" Keywords: {keywords}")
813
+
814
+ except Exception as e:
815
+ print(f"❌ Error routing memory command: {e}")
816
+
817
+
818
+ def _display_single_optimization_result(result):
819
+ """Display optimization results for a single agent."""
820
+ agent_id = result.get("agent_id", "unknown")
821
+ original_size = result.get("original_size", 0)
822
+ optimized_size = result.get("optimized_size", 0)
823
+ size_reduction = result.get("size_reduction", 0)
824
+ size_reduction_percent = result.get("size_reduction_percent", 0)
825
+
826
+ print(f"✅ Optimization completed for {agent_id}")
827
+ print(f" Original size: {original_size:,} bytes")
828
+ print(f" Optimized size: {optimized_size:,} bytes")
829
+ print(f" Size reduction: {size_reduction:,} bytes ({size_reduction_percent}%)")
830
+
831
+ duplicates = result.get("duplicates_removed", 0)
832
+ consolidated = result.get("items_consolidated", 0)
833
+ reordered = result.get("items_reordered", 0)
834
+
835
+ if duplicates > 0:
836
+ print(f" Duplicates removed: {duplicates}")
837
+ if consolidated > 0:
838
+ print(f" Items consolidated: {consolidated}")
839
+ if reordered > 0:
840
+ print(f" Sections reordered: {reordered}")
841
+
842
+ backup_path = result.get("backup_created")
843
+ if backup_path:
844
+ print(f" Backup created: {backup_path}")
845
+
846
+
847
+ def _display_bulk_optimization_results(result):
848
+ """Display optimization results for all agents."""
849
+ summary = result.get("summary", {})
850
+
851
+ print(f"✅ Bulk optimization completed")
852
+ print(f" Agents processed: {summary.get('agents_processed', 0)}")
853
+ print(f" Agents optimized: {summary.get('agents_optimized', 0)}")
854
+ print(f" Total size before: {summary.get('total_size_before', 0):,} bytes")
855
+ print(f" Total size after: {summary.get('total_size_after', 0):,} bytes")
856
+ print(f" Total reduction: {summary.get('total_size_reduction', 0):,} bytes ({summary.get('total_size_reduction_percent', 0)}%)")
857
+ print(f" Total duplicates removed: {summary.get('total_duplicates_removed', 0)}")
858
+ print(f" Total items consolidated: {summary.get('total_items_consolidated', 0)}")
859
+
860
+ # Show per-agent summary
861
+ agents_results = result.get("agents", {})
862
+ if agents_results:
863
+ print(f"\n📊 Per-agent results:")
864
+ for agent_id, agent_result in agents_results.items():
865
+ if agent_result.get("success"):
866
+ reduction = agent_result.get("size_reduction_percent", 0)
867
+ duplicates = agent_result.get("duplicates_removed", 0)
868
+ consolidated = agent_result.get("items_consolidated", 0)
869
+
870
+ status_parts = []
871
+ if duplicates > 0:
872
+ status_parts.append(f"{duplicates} dupes")
873
+ if consolidated > 0:
874
+ status_parts.append(f"{consolidated} consolidated")
875
+
876
+ status = f" ({', '.join(status_parts)})" if status_parts else ""
877
+ print(f" {agent_id}: {reduction}% reduction{status}")
878
+ else:
879
+ error = agent_result.get("error", "Unknown error")
880
+ print(f" {agent_id}: ❌ {error}")
881
+
882
+
883
+ def _output_all_memories_raw(memory_manager):
884
+ """
885
+ Output all agent memories in raw JSON format.
886
+
887
+ WHY: Provides programmatic access to all agent memories for external tools,
888
+ scripts, or APIs that need to process or analyze the complete memory state.
889
+
890
+ Args:
891
+ memory_manager: AgentMemoryManager instance
892
+ """
893
+ try:
894
+ raw_data = memory_manager.get_all_memories_raw()
895
+ print(json.dumps(raw_data, indent=2, ensure_ascii=False))
896
+ except Exception as e:
897
+ error_output = {
898
+ "success": False,
899
+ "error": f"Failed to retrieve all memories: {str(e)}",
900
+ "timestamp": datetime.now().isoformat()
901
+ }
902
+ print(json.dumps(error_output, indent=2))
903
+
904
+
905
+ def _output_single_agent_raw(agent_id, memory_manager):
906
+ """
907
+ Output single agent memory in raw JSON format.
908
+
909
+ WHY: Provides programmatic access to a specific agent's memory for
910
+ targeted analysis or processing by external tools.
911
+
912
+ Args:
913
+ agent_id: ID of the agent to retrieve memory for
914
+ memory_manager: AgentMemoryManager instance
915
+ """
916
+ try:
917
+ # Get all memories and extract the specific agent
918
+ all_memories = memory_manager.get_all_memories_raw()
919
+
920
+ if not all_memories.get("success", False):
921
+ error_output = {
922
+ "success": False,
923
+ "error": all_memories.get("error", "Failed to retrieve memories"),
924
+ "timestamp": datetime.now().isoformat()
925
+ }
926
+ print(json.dumps(error_output, indent=2))
927
+ return
928
+
929
+ agents = all_memories.get("agents", {})
930
+ if agent_id not in agents:
931
+ error_output = {
932
+ "success": False,
933
+ "error": f"No memory found for agent: {agent_id}",
934
+ "available_agents": list(agents.keys()),
935
+ "timestamp": datetime.now().isoformat()
936
+ }
937
+ print(json.dumps(error_output, indent=2))
938
+ return
939
+
940
+ # Return single agent data with metadata
941
+ single_agent_output = {
942
+ "success": True,
943
+ "timestamp": all_memories["timestamp"],
944
+ "agent": agents[agent_id]
945
+ }
946
+
947
+ print(json.dumps(single_agent_output, indent=2, ensure_ascii=False))
948
+
949
+ except Exception as e:
950
+ error_output = {
951
+ "success": False,
952
+ "error": f"Failed to retrieve memory for agent {agent_id}: {str(e)}",
953
+ "timestamp": datetime.now().isoformat()
954
+ }
955
+ print(json.dumps(error_output, indent=2))