claude-mpm 5.6.10__py3-none-any.whl → 5.6.33__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.

Potentially problematic release.


This version of claude-mpm might be problematic. Click here for more details.

Files changed (117) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/cli/commands/commander.py +174 -4
  3. claude_mpm/cli/parsers/commander_parser.py +43 -10
  4. claude_mpm/cli/startup.py +140 -20
  5. claude_mpm/cli/startup_display.py +2 -1
  6. claude_mpm/commander/__init__.py +6 -0
  7. claude_mpm/commander/adapters/__init__.py +32 -3
  8. claude_mpm/commander/adapters/auggie.py +260 -0
  9. claude_mpm/commander/adapters/base.py +98 -1
  10. claude_mpm/commander/adapters/claude_code.py +32 -1
  11. claude_mpm/commander/adapters/codex.py +237 -0
  12. claude_mpm/commander/adapters/example_usage.py +310 -0
  13. claude_mpm/commander/adapters/mpm.py +389 -0
  14. claude_mpm/commander/adapters/registry.py +204 -0
  15. claude_mpm/commander/api/app.py +32 -16
  16. claude_mpm/commander/api/routes/messages.py +11 -11
  17. claude_mpm/commander/api/routes/projects.py +20 -20
  18. claude_mpm/commander/api/routes/sessions.py +19 -21
  19. claude_mpm/commander/api/routes/work.py +86 -50
  20. claude_mpm/commander/api/schemas.py +4 -0
  21. claude_mpm/commander/chat/cli.py +42 -3
  22. claude_mpm/commander/config.py +5 -3
  23. claude_mpm/commander/core/__init__.py +10 -0
  24. claude_mpm/commander/core/block_manager.py +325 -0
  25. claude_mpm/commander/core/response_manager.py +323 -0
  26. claude_mpm/commander/daemon.py +215 -10
  27. claude_mpm/commander/env_loader.py +59 -0
  28. claude_mpm/commander/frameworks/base.py +4 -1
  29. claude_mpm/commander/instance_manager.py +124 -11
  30. claude_mpm/commander/memory/__init__.py +45 -0
  31. claude_mpm/commander/memory/compression.py +347 -0
  32. claude_mpm/commander/memory/embeddings.py +230 -0
  33. claude_mpm/commander/memory/entities.py +310 -0
  34. claude_mpm/commander/memory/example_usage.py +290 -0
  35. claude_mpm/commander/memory/integration.py +325 -0
  36. claude_mpm/commander/memory/search.py +381 -0
  37. claude_mpm/commander/memory/store.py +657 -0
  38. claude_mpm/commander/registry.py +10 -4
  39. claude_mpm/commander/runtime/monitor.py +32 -2
  40. claude_mpm/commander/work/executor.py +38 -20
  41. claude_mpm/commander/workflow/event_handler.py +25 -3
  42. claude_mpm/core/claude_runner.py +152 -0
  43. claude_mpm/core/config.py +3 -3
  44. claude_mpm/core/config_constants.py +74 -9
  45. claude_mpm/core/constants.py +56 -12
  46. claude_mpm/core/interactive_session.py +5 -4
  47. claude_mpm/core/logging_utils.py +4 -2
  48. claude_mpm/core/network_config.py +148 -0
  49. claude_mpm/core/oneshot_session.py +7 -6
  50. claude_mpm/core/output_style_manager.py +37 -7
  51. claude_mpm/core/socketio_pool.py +13 -5
  52. claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
  53. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  54. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  55. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  56. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  57. claude_mpm/hooks/claude_hooks/auto_pause_handler.py +1 -1
  58. claude_mpm/hooks/claude_hooks/event_handlers.py +284 -89
  59. claude_mpm/hooks/claude_hooks/hook_handler.py +81 -32
  60. claude_mpm/hooks/claude_hooks/installer.py +90 -28
  61. claude_mpm/hooks/claude_hooks/memory_integration.py +1 -1
  62. claude_mpm/hooks/claude_hooks/response_tracking.py +1 -1
  63. claude_mpm/hooks/claude_hooks/services/__init__.py +21 -0
  64. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
  65. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  66. claude_mpm/hooks/claude_hooks/services/__pycache__/container.cpython-311.pyc +0 -0
  67. claude_mpm/hooks/claude_hooks/services/__pycache__/protocols.cpython-311.pyc +0 -0
  68. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  69. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  70. claude_mpm/hooks/claude_hooks/services/connection_manager.py +2 -2
  71. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +2 -2
  72. claude_mpm/hooks/claude_hooks/services/container.py +310 -0
  73. claude_mpm/hooks/claude_hooks/services/protocols.py +328 -0
  74. claude_mpm/hooks/claude_hooks/services/state_manager.py +2 -2
  75. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +2 -2
  76. claude_mpm/hooks/templates/pre_tool_use_simple.py +6 -6
  77. claude_mpm/hooks/templates/pre_tool_use_template.py +6 -6
  78. claude_mpm/scripts/claude-hook-handler.sh +3 -3
  79. claude_mpm/services/command_deployment_service.py +44 -26
  80. claude_mpm/services/hook_installer_service.py +77 -8
  81. claude_mpm/services/pm_skills_deployer.py +3 -2
  82. claude_mpm/skills/__init__.py +2 -1
  83. claude_mpm/skills/bundled/pm/mpm-session-pause/SKILL.md +170 -0
  84. claude_mpm/skills/registry.py +295 -90
  85. {claude_mpm-5.6.10.dist-info → claude_mpm-5.6.33.dist-info}/METADATA +5 -3
  86. {claude_mpm-5.6.10.dist-info → claude_mpm-5.6.33.dist-info}/RECORD +91 -94
  87. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-312.pyc +0 -0
  88. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-314.pyc +0 -0
  89. claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-312.pyc +0 -0
  90. claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-314.pyc +0 -0
  91. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-312.pyc +0 -0
  92. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-314.pyc +0 -0
  93. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-312.pyc +0 -0
  94. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-314.pyc +0 -0
  95. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
  96. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-314.pyc +0 -0
  97. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-312.pyc +0 -0
  98. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-314.pyc +0 -0
  99. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-312.pyc +0 -0
  100. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-314.pyc +0 -0
  101. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-312.pyc +0 -0
  102. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-314.pyc +0 -0
  103. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-312.pyc +0 -0
  104. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-314.pyc +0 -0
  105. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-312.pyc +0 -0
  106. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-314.pyc +0 -0
  107. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-312.pyc +0 -0
  108. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-314.pyc +0 -0
  109. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-312.pyc +0 -0
  110. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-314.pyc +0 -0
  111. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-312.pyc +0 -0
  112. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-314.pyc +0 -0
  113. {claude_mpm-5.6.10.dist-info → claude_mpm-5.6.33.dist-info}/WHEEL +0 -0
  114. {claude_mpm-5.6.10.dist-info → claude_mpm-5.6.33.dist-info}/entry_points.txt +0 -0
  115. {claude_mpm-5.6.10.dist-info → claude_mpm-5.6.33.dist-info}/licenses/LICENSE +0 -0
  116. {claude_mpm-5.6.10.dist-info → claude_mpm-5.6.33.dist-info}/licenses/LICENSE-FAQ.md +0 -0
  117. {claude_mpm-5.6.10.dist-info → claude_mpm-5.6.33.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,310 @@
1
+ """Entity extraction from conversation messages.
2
+
3
+ Extracts structured entities like files, functions, errors, and commands
4
+ from conversation content for enhanced search and filtering.
5
+ """
6
+
7
+ import logging
8
+ import re
9
+ from dataclasses import dataclass
10
+ from enum import Enum
11
+ from typing import Any, Dict, List
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class EntityType(Enum):
17
+ """Types of entities that can be extracted.
18
+
19
+ Attributes:
20
+ FILE: File path (e.g., "src/auth.py")
21
+ FUNCTION: Function or method name (e.g., "login()")
22
+ CLASS: Class name (e.g., "UserService")
23
+ ERROR: Error type or message (e.g., "ValueError")
24
+ COMMAND: Shell command (e.g., "pytest tests/")
25
+ URL: Web URL (e.g., "https://example.com")
26
+ PACKAGE: Package or module name (e.g., "requests")
27
+ """
28
+
29
+ FILE = "file"
30
+ FUNCTION = "function"
31
+ CLASS = "class"
32
+ ERROR = "error"
33
+ COMMAND = "command"
34
+ URL = "url"
35
+ PACKAGE = "package"
36
+
37
+
38
+ @dataclass
39
+ class Entity:
40
+ """Extracted entity from conversation.
41
+
42
+ Attributes:
43
+ type: Entity type
44
+ value: Entity value (file path, function name, etc.)
45
+ context: Surrounding context (optional)
46
+ metadata: Additional metadata
47
+
48
+ Example:
49
+ >>> entity = Entity(
50
+ ... type=EntityType.FILE,
51
+ ... value="src/auth.py",
52
+ ... context="Fix the login bug in auth.py"
53
+ ... )
54
+ """
55
+
56
+ type: EntityType
57
+ value: str
58
+ context: str = ""
59
+ metadata: Dict[str, Any] = None
60
+
61
+ def __post_init__(self) -> None:
62
+ """Initialize metadata if not provided."""
63
+ if self.metadata is None:
64
+ self.metadata = {}
65
+
66
+ def to_dict(self) -> Dict[str, Any]:
67
+ """Convert to dictionary for JSON serialization."""
68
+ return {
69
+ "type": self.type.value,
70
+ "value": self.value,
71
+ "context": self.context,
72
+ "metadata": self.metadata,
73
+ }
74
+
75
+ @classmethod
76
+ def from_dict(cls, data: Dict[str, Any]) -> "Entity":
77
+ """Create Entity from dictionary."""
78
+ return cls(
79
+ type=EntityType(data["type"]),
80
+ value=data["value"],
81
+ context=data.get("context", ""),
82
+ metadata=data.get("metadata", {}),
83
+ )
84
+
85
+
86
+ class EntityExtractor:
87
+ """Extracts entities from conversation messages.
88
+
89
+ Uses regex patterns to identify files, functions, errors, commands, etc.
90
+
91
+ Example:
92
+ >>> extractor = EntityExtractor()
93
+ >>> entities = extractor.extract("Fix the login bug in src/auth.py")
94
+ >>> entities[0].type
95
+ <EntityType.FILE: 'file'>
96
+ >>> entities[0].value
97
+ 'src/auth.py'
98
+ """
99
+
100
+ # File patterns (common extensions and paths)
101
+ FILE_PATTERNS = [
102
+ r"\b[\w/\-\.]+\.(?:py|js|ts|tsx|jsx|java|cpp|c|h|go|rs|rb|php|cs|swift|kt|md|txt|json|yaml|yml|toml|xml|html|css|scss|sh|bash)\b",
103
+ r"\b(?:src|lib|tests?|scripts?|docs?|config)/[\w/\-\.]+\b",
104
+ ]
105
+
106
+ # Function patterns (with parens or common prefixes)
107
+ FUNCTION_PATTERNS = [
108
+ r"\b[a-z_][a-z0-9_]*\(\)",
109
+ r"\bdef\s+([a-z_][a-z0-9_]*)",
110
+ r"\bfunction\s+([a-z_][a-z0-9_]*)",
111
+ r"\basync\s+(?:def|function)\s+([a-z_][a-z0-9_]*)",
112
+ ]
113
+
114
+ # Class patterns (PascalCase)
115
+ CLASS_PATTERNS = [
116
+ r"\bclass\s+([A-Z][a-zA-Z0-9_]*)",
117
+ r"\b([A-Z][a-zA-Z0-9_]+(?:Service|Controller|Manager|Handler|Repository|Model|View))\b",
118
+ ]
119
+
120
+ # Error patterns
121
+ ERROR_PATTERNS = [
122
+ r"\b([A-Z][a-zA-Z]*Error)\b",
123
+ r"\b([A-Z][a-zA-Z]*Exception)\b",
124
+ r"error:\s+(.+?)(?:\n|$)",
125
+ ]
126
+
127
+ # Command patterns (common CLI tools)
128
+ COMMAND_PATTERNS = [
129
+ r"\b(?:npm|yarn|pnpm|pip|poetry|cargo|go|make|docker|kubectl|git)\s+[\w\-]+",
130
+ r"\bpytest\s+[\w/\-\.]+",
131
+ r"\bpython\s+[\w/\-\.]+",
132
+ ]
133
+
134
+ # URL patterns
135
+ URL_PATTERN = r"https?://[\w\.\-/\?=&#%]+"
136
+
137
+ # Package patterns
138
+ PACKAGE_PATTERNS = [
139
+ r"\bimport\s+([\w\.]+)",
140
+ r"\bfrom\s+([\w\.]+)\s+import",
141
+ r"\brequire\(['\"]([\w\-@/]+)['\"]",
142
+ r"\buse\s+([\w:]+)",
143
+ ]
144
+
145
+ def extract(self, text: str) -> List[Entity]:
146
+ """Extract all entities from text.
147
+
148
+ Args:
149
+ text: Text to extract entities from
150
+
151
+ Returns:
152
+ List of extracted entities
153
+
154
+ Example:
155
+ >>> entities = extractor.extract("Fix the login bug in src/auth.py")
156
+ """
157
+ entities: List[Entity] = []
158
+
159
+ # Extract files
160
+ for pattern in self.FILE_PATTERNS:
161
+ for match in re.finditer(pattern, text):
162
+ entities.append(
163
+ Entity(
164
+ type=EntityType.FILE,
165
+ value=match.group(0),
166
+ context=self._get_context(text, match.start(), match.end()),
167
+ )
168
+ )
169
+
170
+ # Extract functions
171
+ for pattern in self.FUNCTION_PATTERNS:
172
+ for match in re.finditer(pattern, text):
173
+ # Use group 1 if capturing group exists, else group 0
174
+ value = match.group(1) if match.lastindex else match.group(0)
175
+ entities.append(
176
+ Entity(
177
+ type=EntityType.FUNCTION,
178
+ value=value.rstrip("()"), # Remove parens
179
+ context=self._get_context(text, match.start(), match.end()),
180
+ )
181
+ )
182
+
183
+ # Extract classes
184
+ for pattern in self.CLASS_PATTERNS:
185
+ for match in re.finditer(pattern, text):
186
+ value = match.group(1) if match.lastindex else match.group(0)
187
+ entities.append(
188
+ Entity(
189
+ type=EntityType.CLASS,
190
+ value=value,
191
+ context=self._get_context(text, match.start(), match.end()),
192
+ )
193
+ )
194
+
195
+ # Extract errors
196
+ for pattern in self.ERROR_PATTERNS:
197
+ for match in re.finditer(pattern, text):
198
+ value = match.group(1) if match.lastindex else match.group(0)
199
+ entities.append(
200
+ Entity(
201
+ type=EntityType.ERROR,
202
+ value=value.strip(),
203
+ context=self._get_context(text, match.start(), match.end()),
204
+ )
205
+ )
206
+
207
+ # Extract commands
208
+ for pattern in self.COMMAND_PATTERNS:
209
+ for match in re.finditer(pattern, text):
210
+ entities.append(
211
+ Entity(
212
+ type=EntityType.COMMAND,
213
+ value=match.group(0),
214
+ context=self._get_context(text, match.start(), match.end()),
215
+ )
216
+ )
217
+
218
+ # Extract URLs
219
+ for match in re.finditer(self.URL_PATTERN, text):
220
+ entities.append(
221
+ Entity(
222
+ type=EntityType.URL,
223
+ value=match.group(0),
224
+ context=self._get_context(text, match.start(), match.end()),
225
+ )
226
+ )
227
+
228
+ # Extract packages
229
+ for pattern in self.PACKAGE_PATTERNS:
230
+ for match in re.finditer(pattern, text):
231
+ value = match.group(1) if match.lastindex else match.group(0)
232
+ entities.append(
233
+ Entity(
234
+ type=EntityType.PACKAGE,
235
+ value=value,
236
+ context=self._get_context(text, match.start(), match.end()),
237
+ )
238
+ )
239
+
240
+ # Deduplicate entities (same type + value)
241
+ seen = set()
242
+ unique_entities = []
243
+ for entity in entities:
244
+ key = (entity.type, entity.value)
245
+ if key not in seen:
246
+ seen.add(key)
247
+ unique_entities.append(entity)
248
+
249
+ logger.debug("Extracted %d unique entities from text", len(unique_entities))
250
+ return unique_entities
251
+
252
+ def _get_context(self, text: str, start: int, end: int, window: int = 50) -> str:
253
+ """Get surrounding context for entity.
254
+
255
+ Args:
256
+ text: Full text
257
+ start: Entity start position
258
+ end: Entity end position
259
+ window: Characters to include before/after
260
+
261
+ Returns:
262
+ Context string with entity highlighted
263
+ """
264
+ context_start = max(0, start - window)
265
+ context_end = min(len(text), end + window)
266
+
267
+ context = text[context_start:context_end]
268
+
269
+ # Truncate at sentence boundaries if possible
270
+ if context_start > 0 and ". " in context[:window]:
271
+ context = context.split(". ", 1)[1]
272
+ if context_end < len(text) and ". " in context[-window:]:
273
+ context = context.rsplit(". ", 1)[0] + "."
274
+
275
+ return context.strip()
276
+
277
+ def filter_by_type(
278
+ self, entities: List[Entity], entity_type: EntityType
279
+ ) -> List[Entity]:
280
+ """Filter entities by type.
281
+
282
+ Args:
283
+ entities: List of entities to filter
284
+ entity_type: Type to filter for
285
+
286
+ Returns:
287
+ Filtered list of entities
288
+
289
+ Example:
290
+ >>> files = extractor.filter_by_type(entities, EntityType.FILE)
291
+ """
292
+ return [e for e in entities if e.type == entity_type]
293
+
294
+ def get_unique_values(
295
+ self, entities: List[Entity], entity_type: EntityType
296
+ ) -> List[str]:
297
+ """Get unique entity values for a type.
298
+
299
+ Args:
300
+ entities: List of entities
301
+ entity_type: Type to extract values for
302
+
303
+ Returns:
304
+ List of unique values
305
+
306
+ Example:
307
+ >>> files = extractor.get_unique_values(entities, EntityType.FILE)
308
+ ['src/auth.py', 'tests/test_auth.py']
309
+ """
310
+ return list({e.value for e in entities if e.type == entity_type})
@@ -0,0 +1,290 @@
1
+ """Example usage of Commander memory system.
2
+
3
+ Demonstrates:
4
+ 1. Capturing conversations from Project
5
+ 2. Searching conversations semantically
6
+ 3. Loading context for session resumption
7
+ 4. Entity extraction and filtering
8
+ """
9
+
10
+ import asyncio
11
+
12
+ from ..models.project import Project, ProjectState, ThreadMessage
13
+ from .entities import EntityType
14
+ from .integration import MemoryIntegration
15
+
16
+
17
+ async def example_basic_usage():
18
+ """Example 1: Basic conversation capture and search."""
19
+ print("\n=== Example 1: Basic Usage ===\n")
20
+
21
+ # Initialize memory integration
22
+ memory = MemoryIntegration.create()
23
+
24
+ # Create sample project with conversation
25
+ project = Project(
26
+ id="proj-example-123",
27
+ path="/Users/masa/Projects/example-app",
28
+ name="example-app",
29
+ state=ProjectState.IDLE,
30
+ )
31
+
32
+ # Add sample conversation to project
33
+ project.thread = [
34
+ ThreadMessage(
35
+ id="msg-1",
36
+ role="user",
37
+ content="Fix the login authentication bug in src/auth.py",
38
+ ),
39
+ ThreadMessage(
40
+ id="msg-2",
41
+ role="assistant",
42
+ content="I'll investigate the authentication bug. Let me read the auth.py file.",
43
+ ),
44
+ ThreadMessage(
45
+ id="msg-3",
46
+ role="assistant",
47
+ content="Found the issue in UserService.authenticate() - the token validation was missing expiry check. Fixed it.",
48
+ ),
49
+ ThreadMessage(
50
+ id="msg-4",
51
+ role="user",
52
+ content="Great! Can you also add tests for this fix?",
53
+ ),
54
+ ThreadMessage(
55
+ id="msg-5",
56
+ role="assistant",
57
+ content="Added test_token_expiry_validation() in tests/test_auth.py. All tests passing.",
58
+ ),
59
+ ]
60
+
61
+ # Capture conversation
62
+ conversation = await memory.capture_project_conversation(
63
+ project, instance_name="claude-code-1", session_id="sess-abc123"
64
+ )
65
+
66
+ print(f"✅ Captured conversation: {conversation.id}")
67
+ print(f" Messages: {len(conversation.messages)}")
68
+ print(f" Summary: {conversation.summary}")
69
+ print(
70
+ f" Entities extracted: {len([e for msg in conversation.messages for e in msg.entities])}"
71
+ )
72
+
73
+ # Search conversations
74
+ print("\n🔍 Searching for 'authentication bug'...")
75
+ results = await memory.search_conversations(
76
+ "authentication bug fix", project_id=project.id, limit=3
77
+ )
78
+
79
+ for i, result in enumerate(results, 1):
80
+ print(f"\n{i}. Score: {result.score:.3f}")
81
+ print(f" Conversation: {result.conversation.id}")
82
+ print(f" Snippet: {result.snippet[:100]}...")
83
+
84
+
85
+ async def example_entity_search():
86
+ """Example 2: Entity-based search and filtering."""
87
+ print("\n=== Example 2: Entity Search ===\n")
88
+
89
+ memory = MemoryIntegration.create()
90
+
91
+ # Create project with file references
92
+ project = Project(
93
+ id="proj-example-456",
94
+ path="/Users/masa/Projects/example-app",
95
+ name="example-app",
96
+ )
97
+
98
+ project.thread = [
99
+ ThreadMessage(
100
+ id="msg-1",
101
+ role="user",
102
+ content="Update the UserService class in src/services/user_service.py",
103
+ ),
104
+ ThreadMessage(
105
+ id="msg-2",
106
+ role="assistant",
107
+ content="I'll update UserService.create_user() to include email validation. Also updating tests/test_user_service.py.",
108
+ ),
109
+ ]
110
+
111
+ # Capture
112
+ conversation = await memory.capture_project_conversation(
113
+ project, instance_name="claude-code-2"
114
+ )
115
+
116
+ # Extract entities
117
+ entities = []
118
+ for msg in conversation.messages:
119
+ entities.extend(msg.entities)
120
+
121
+ # Filter by type
122
+ files = memory.extractor.get_unique_values(
123
+ [memory.extractor.Entity.from_dict(e) for e in entities], EntityType.FILE
124
+ )
125
+ print(f"📁 Files mentioned: {files}")
126
+
127
+ classes = memory.extractor.get_unique_values(
128
+ [memory.extractor.Entity.from_dict(e) for e in entities], EntityType.CLASS
129
+ )
130
+ print(f"🏗️ Classes mentioned: {classes}")
131
+
132
+ # Search by entity
133
+ print("\n🔍 Finding conversations that mention 'src/services/user_service.py'...")
134
+ results = await memory.search.search_by_entities(
135
+ EntityType.FILE,
136
+ "src/services/user_service.py",
137
+ project_id=project.id,
138
+ )
139
+
140
+ print(f"Found {len(results)} conversations mentioning this file")
141
+
142
+
143
+ async def example_context_loading():
144
+ """Example 3: Load context for session resumption."""
145
+ print("\n=== Example 3: Context Loading for Session Resumption ===\n")
146
+
147
+ memory = MemoryIntegration.create()
148
+
149
+ # Create multiple conversations (simulating historical work)
150
+ project = Project(
151
+ id="proj-example-789",
152
+ path="/Users/masa/Projects/example-app",
153
+ name="example-app",
154
+ )
155
+
156
+ # Conversation 1: Week ago
157
+ project.thread = [
158
+ ThreadMessage(
159
+ id="msg-1",
160
+ role="user",
161
+ content="Implement user registration with email verification",
162
+ ),
163
+ ThreadMessage(
164
+ id="msg-2",
165
+ role="assistant",
166
+ content="Implemented registration in src/auth.py with email service integration",
167
+ ),
168
+ ]
169
+ await memory.capture_project_conversation(project, instance_name="claude-code-1")
170
+
171
+ # Conversation 2: Yesterday
172
+ project.thread = [
173
+ ThreadMessage(
174
+ id="msg-3",
175
+ role="user",
176
+ content="Fix the email verification bug - tokens not expiring",
177
+ ),
178
+ ThreadMessage(
179
+ id="msg-4",
180
+ role="assistant",
181
+ content="Fixed token expiry check in src/auth.py and added tests",
182
+ ),
183
+ ]
184
+ await memory.capture_project_conversation(project, instance_name="claude-code-1")
185
+
186
+ # Load context for resumption
187
+ print("📖 Loading context for session resumption...")
188
+ context = await memory.load_context_for_session(
189
+ project.id, max_tokens=4000, limit_conversations=10
190
+ )
191
+
192
+ print(f"✅ Loaded context ({len(context)} chars):\n")
193
+ print(context[:500] + "...\n")
194
+
195
+ print(
196
+ "This context would be injected into the new session to provide historical awareness."
197
+ )
198
+
199
+
200
+ async def example_similarity_search():
201
+ """Example 4: Find similar conversations."""
202
+ print("\n=== Example 4: Similarity Search ===\n")
203
+
204
+ memory = MemoryIntegration.create()
205
+
206
+ # Create project with multiple conversations
207
+ project = Project(
208
+ id="proj-example-999",
209
+ path="/Users/masa/Projects/example-app",
210
+ name="example-app",
211
+ )
212
+
213
+ # Reference conversation
214
+ project.thread = [
215
+ ThreadMessage(
216
+ id="msg-1",
217
+ role="user",
218
+ content="Fix the authentication bug in login flow",
219
+ ),
220
+ ThreadMessage(
221
+ id="msg-2",
222
+ role="assistant",
223
+ content="Fixed token validation in src/auth.py",
224
+ ),
225
+ ]
226
+ ref_conv = await memory.capture_project_conversation(project)
227
+
228
+ # Similar conversation
229
+ project.thread = [
230
+ ThreadMessage(
231
+ id="msg-3",
232
+ role="user",
233
+ content="Update the login authentication to use OAuth",
234
+ ),
235
+ ThreadMessage(
236
+ id="msg-4",
237
+ role="assistant",
238
+ content="Implemented OAuth in src/auth.py",
239
+ ),
240
+ ]
241
+ await memory.capture_project_conversation(project)
242
+
243
+ # Different conversation
244
+ project.thread = [
245
+ ThreadMessage(
246
+ id="msg-5",
247
+ role="user",
248
+ content="Add dark mode toggle to the UI",
249
+ ),
250
+ ThreadMessage(
251
+ id="msg-6",
252
+ role="assistant",
253
+ content="Added dark mode CSS in styles/theme.css",
254
+ ),
255
+ ]
256
+ await memory.capture_project_conversation(project)
257
+
258
+ # Find similar
259
+ print(f"🔍 Finding conversations similar to: {ref_conv.id}")
260
+ similar = await memory.search.find_similar(ref_conv.id, limit=3)
261
+
262
+ for i, result in enumerate(similar, 1):
263
+ print(f"\n{i}. Similarity: {result.score:.3f}")
264
+ print(f" Conversation: {result.conversation.id}")
265
+ print(f" Summary: {result.conversation.summary}")
266
+
267
+
268
+ async def main():
269
+ """Run all examples."""
270
+ print("\n" + "=" * 60)
271
+ print("Commander Memory System - Example Usage")
272
+ print("=" * 60)
273
+
274
+ # Run examples
275
+ await example_basic_usage()
276
+ await example_entity_search()
277
+ await example_context_loading()
278
+ await example_similarity_search()
279
+
280
+ print("\n" + "=" * 60)
281
+ print("✅ All examples completed!")
282
+ print("=" * 60 + "\n")
283
+
284
+ print("📚 For more information, see:")
285
+ print(" - src/claude_mpm/commander/memory/README.md")
286
+ print(" - API documentation in each module")
287
+
288
+
289
+ if __name__ == "__main__":
290
+ asyncio.run(main())