claude-mpm 3.4.26__py3-none-any.whl → 3.5.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 (123) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/INSTRUCTIONS.md +182 -299
  3. claude_mpm/agents/agent_loader.py +283 -57
  4. claude_mpm/agents/agent_loader_integration.py +6 -9
  5. claude_mpm/agents/base_agent.json +2 -1
  6. claude_mpm/agents/base_agent_loader.py +1 -1
  7. claude_mpm/cli/__init__.py +6 -10
  8. claude_mpm/cli/commands/__init__.py +0 -2
  9. claude_mpm/cli/commands/agents.py +1 -1
  10. claude_mpm/cli/commands/memory.py +1 -1
  11. claude_mpm/cli/commands/run.py +12 -0
  12. claude_mpm/cli/parser.py +0 -13
  13. claude_mpm/cli/utils.py +1 -1
  14. claude_mpm/config/__init__.py +44 -2
  15. claude_mpm/config/agent_config.py +348 -0
  16. claude_mpm/config/paths.py +322 -0
  17. claude_mpm/constants.py +0 -1
  18. claude_mpm/core/__init__.py +2 -5
  19. claude_mpm/core/agent_registry.py +63 -17
  20. claude_mpm/core/claude_runner.py +354 -43
  21. claude_mpm/core/config.py +7 -1
  22. claude_mpm/core/config_aliases.py +4 -3
  23. claude_mpm/core/config_paths.py +151 -0
  24. claude_mpm/core/factories.py +4 -50
  25. claude_mpm/core/logger.py +11 -13
  26. claude_mpm/core/service_registry.py +2 -2
  27. claude_mpm/dashboard/static/js/components/agent-inference.js +101 -25
  28. claude_mpm/dashboard/static/js/components/event-processor.js +3 -2
  29. claude_mpm/hooks/claude_hooks/hook_handler.py +343 -83
  30. claude_mpm/hooks/memory_integration_hook.py +1 -1
  31. claude_mpm/init.py +37 -6
  32. claude_mpm/scripts/socketio_daemon.py +6 -2
  33. claude_mpm/services/__init__.py +71 -3
  34. claude_mpm/services/agents/__init__.py +85 -0
  35. claude_mpm/services/agents/deployment/__init__.py +21 -0
  36. claude_mpm/services/{agent_deployment.py → agents/deployment/agent_deployment.py} +192 -41
  37. claude_mpm/services/{agent_lifecycle_manager.py → agents/deployment/agent_lifecycle_manager.py} +11 -10
  38. claude_mpm/services/agents/loading/__init__.py +11 -0
  39. claude_mpm/services/{agent_profile_loader.py → agents/loading/agent_profile_loader.py} +9 -8
  40. claude_mpm/services/{base_agent_manager.py → agents/loading/base_agent_manager.py} +2 -2
  41. claude_mpm/services/{framework_agent_loader.py → agents/loading/framework_agent_loader.py} +116 -40
  42. claude_mpm/services/agents/management/__init__.py +9 -0
  43. claude_mpm/services/{agent_management_service.py → agents/management/agent_management_service.py} +6 -5
  44. claude_mpm/services/agents/memory/__init__.py +21 -0
  45. claude_mpm/services/{agent_memory_manager.py → agents/memory/agent_memory_manager.py} +3 -3
  46. claude_mpm/services/agents/registry/__init__.py +29 -0
  47. claude_mpm/services/{agent_registry.py → agents/registry/agent_registry.py} +101 -16
  48. claude_mpm/services/{deployed_agent_discovery.py → agents/registry/deployed_agent_discovery.py} +12 -2
  49. claude_mpm/services/{agent_modification_tracker.py → agents/registry/modification_tracker.py} +6 -5
  50. claude_mpm/services/async_session_logger.py +584 -0
  51. claude_mpm/services/claude_session_logger.py +299 -0
  52. claude_mpm/services/framework_claude_md_generator/content_assembler.py +2 -2
  53. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +17 -17
  54. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +3 -3
  55. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +1 -1
  56. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +1 -1
  57. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +19 -24
  58. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +1 -1
  59. claude_mpm/services/framework_claude_md_generator.py +4 -2
  60. claude_mpm/services/memory/__init__.py +17 -0
  61. claude_mpm/services/{memory_builder.py → memory/builder.py} +3 -3
  62. claude_mpm/services/memory/cache/__init__.py +14 -0
  63. claude_mpm/services/{shared_prompt_cache.py → memory/cache/shared_prompt_cache.py} +1 -1
  64. claude_mpm/services/memory/cache/simple_cache.py +317 -0
  65. claude_mpm/services/{memory_optimizer.py → memory/optimizer.py} +1 -1
  66. claude_mpm/services/{memory_router.py → memory/router.py} +1 -1
  67. claude_mpm/services/optimized_hook_service.py +542 -0
  68. claude_mpm/services/project_registry.py +14 -8
  69. claude_mpm/services/response_tracker.py +237 -0
  70. claude_mpm/services/ticketing_service_original.py +4 -2
  71. claude_mpm/services/version_control/branch_strategy.py +3 -1
  72. claude_mpm/utils/paths.py +12 -10
  73. claude_mpm/utils/session_logging.py +114 -0
  74. claude_mpm/validation/agent_validator.py +2 -1
  75. {claude_mpm-3.4.26.dist-info → claude_mpm-3.5.0.dist-info}/METADATA +26 -20
  76. {claude_mpm-3.4.26.dist-info → claude_mpm-3.5.0.dist-info}/RECORD +83 -106
  77. claude_mpm/cli/commands/ui.py +0 -57
  78. claude_mpm/core/simple_runner.py +0 -1046
  79. claude_mpm/hooks/builtin/__init__.py +0 -1
  80. claude_mpm/hooks/builtin/logging_hook_example.py +0 -165
  81. claude_mpm/hooks/builtin/memory_hooks_example.py +0 -67
  82. claude_mpm/hooks/builtin/mpm_command_hook.py +0 -125
  83. claude_mpm/hooks/builtin/post_delegation_hook_example.py +0 -124
  84. claude_mpm/hooks/builtin/pre_delegation_hook_example.py +0 -125
  85. claude_mpm/hooks/builtin/submit_hook_example.py +0 -100
  86. claude_mpm/hooks/builtin/ticket_extraction_hook_example.py +0 -237
  87. claude_mpm/hooks/builtin/todo_agent_prefix_hook.py +0 -240
  88. claude_mpm/hooks/builtin/workflow_start_hook.py +0 -181
  89. claude_mpm/orchestration/__init__.py +0 -6
  90. claude_mpm/orchestration/archive/direct_orchestrator.py +0 -195
  91. claude_mpm/orchestration/archive/factory.py +0 -215
  92. claude_mpm/orchestration/archive/hook_enabled_orchestrator.py +0 -188
  93. claude_mpm/orchestration/archive/hook_integration_example.py +0 -178
  94. claude_mpm/orchestration/archive/interactive_subprocess_orchestrator.py +0 -826
  95. claude_mpm/orchestration/archive/orchestrator.py +0 -501
  96. claude_mpm/orchestration/archive/pexpect_orchestrator.py +0 -252
  97. claude_mpm/orchestration/archive/pty_orchestrator.py +0 -270
  98. claude_mpm/orchestration/archive/simple_orchestrator.py +0 -82
  99. claude_mpm/orchestration/archive/subprocess_orchestrator.py +0 -801
  100. claude_mpm/orchestration/archive/system_prompt_orchestrator.py +0 -278
  101. claude_mpm/orchestration/archive/wrapper_orchestrator.py +0 -187
  102. claude_mpm/schemas/workflow_validator.py +0 -411
  103. claude_mpm/services/parent_directory_manager/__init__.py +0 -577
  104. claude_mpm/services/parent_directory_manager/backup_manager.py +0 -258
  105. claude_mpm/services/parent_directory_manager/config_manager.py +0 -210
  106. claude_mpm/services/parent_directory_manager/deduplication_manager.py +0 -279
  107. claude_mpm/services/parent_directory_manager/framework_protector.py +0 -143
  108. claude_mpm/services/parent_directory_manager/operations.py +0 -186
  109. claude_mpm/services/parent_directory_manager/state_manager.py +0 -624
  110. claude_mpm/services/parent_directory_manager/template_deployer.py +0 -579
  111. claude_mpm/services/parent_directory_manager/validation_manager.py +0 -378
  112. claude_mpm/services/parent_directory_manager/version_control_helper.py +0 -339
  113. claude_mpm/services/parent_directory_manager/version_manager.py +0 -222
  114. claude_mpm/ui/__init__.py +0 -1
  115. claude_mpm/ui/rich_terminal_ui.py +0 -295
  116. claude_mpm/ui/terminal_ui.py +0 -328
  117. /claude_mpm/services/{agent_versioning.py → agents/deployment/agent_versioning.py} +0 -0
  118. /claude_mpm/services/{agent_capabilities_generator.py → agents/management/agent_capabilities_generator.py} +0 -0
  119. /claude_mpm/services/{agent_persistence_service.py → agents/memory/agent_persistence_service.py} +0 -0
  120. {claude_mpm-3.4.26.dist-info → claude_mpm-3.5.0.dist-info}/WHEEL +0 -0
  121. {claude_mpm-3.4.26.dist-info → claude_mpm-3.5.0.dist-info}/entry_points.txt +0 -0
  122. {claude_mpm-3.4.26.dist-info → claude_mpm-3.5.0.dist-info}/licenses/LICENSE +0 -0
  123. {claude_mpm-3.4.26.dist-info → claude_mpm-3.5.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,322 @@
1
+ """
2
+ Centralized path management for claude-mpm.
3
+
4
+ This module provides a consistent, reliable way to access project paths
5
+ without fragile parent.parent.parent patterns.
6
+ """
7
+
8
+ import os
9
+ import sys
10
+ from pathlib import Path
11
+ from typing import Optional, Union
12
+ from functools import cached_property
13
+ import logging
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+
18
+ class ClaudeMPMPaths:
19
+ """
20
+ Centralized path management for the claude-mpm project.
21
+
22
+ This class provides a singleton instance with properties for all common paths
23
+ in the project, eliminating the need for fragile Path(__file__).parent.parent patterns.
24
+
25
+ Usage:
26
+ from claude_mpm.config.paths import paths
27
+
28
+ # Access common paths
29
+ project_root = paths.project_root
30
+ agents_dir = paths.agents_dir
31
+ config_file = paths.config_dir / "some_config.yaml"
32
+ """
33
+
34
+ _instance: Optional['ClaudeMPMPaths'] = None
35
+ _project_root: Optional[Path] = None
36
+
37
+ def __new__(cls) -> 'ClaudeMPMPaths':
38
+ """Singleton pattern to ensure single instance."""
39
+ if cls._instance is None:
40
+ cls._instance = super().__new__(cls)
41
+ return cls._instance
42
+
43
+ def __init__(self):
44
+ """Initialize paths if not already done."""
45
+ if self._project_root is None:
46
+ self._detect_project_root()
47
+
48
+ def _detect_project_root(self) -> None:
49
+ """
50
+ Detect the project root directory.
51
+
52
+ Strategy:
53
+ 1. Look for definitive project markers (pyproject.toml, setup.py)
54
+ 2. Look for combination of markers to ensure we're at the right level
55
+ 3. Walk up from current file location
56
+ """
57
+ # Start from this file's location
58
+ current = Path(__file__).resolve()
59
+
60
+ # Walk up the directory tree
61
+ for parent in current.parents:
62
+ # Check for definitive project root indicators
63
+ # Prioritize pyproject.toml and setup.py as they're only at root
64
+ if (parent / 'pyproject.toml').exists() or (parent / 'setup.py').exists():
65
+ self._project_root = parent
66
+ logger.debug(f"Project root detected at: {parent} (found pyproject.toml or setup.py)")
67
+ return
68
+
69
+ # Secondary check: .git directory + VERSION file together
70
+ # This combination is more likely to be the real project root
71
+ if (parent / '.git').exists() and (parent / 'VERSION').exists():
72
+ self._project_root = parent
73
+ logger.debug(f"Project root detected at: {parent} (found .git and VERSION)")
74
+ return
75
+
76
+ # Fallback: walk up to find claude-mpm directory name
77
+ for parent in current.parents:
78
+ if parent.name == 'claude-mpm':
79
+ self._project_root = parent
80
+ logger.debug(f"Project root detected at: {parent} (by directory name)")
81
+ return
82
+
83
+ # Last resort fallback: 3 levels up from this file
84
+ # paths.py is in src/claude_mpm/config/
85
+ self._project_root = current.parent.parent.parent
86
+ logger.warning(f"Project root fallback to: {self._project_root}")
87
+
88
+ @property
89
+ def project_root(self) -> Path:
90
+ """Get the project root directory."""
91
+ if self._project_root is None:
92
+ self._detect_project_root()
93
+ return self._project_root
94
+
95
+ @property
96
+ def src_dir(self) -> Path:
97
+ """Get the src directory."""
98
+ return self.project_root / "src"
99
+
100
+ @property
101
+ def claude_mpm_dir(self) -> Path:
102
+ """Get the main claude_mpm package directory."""
103
+ return self.src_dir / "claude_mpm"
104
+
105
+ @property
106
+ def agents_dir(self) -> Path:
107
+ """Get the agents directory."""
108
+ return self.claude_mpm_dir / "agents"
109
+
110
+ @property
111
+ def services_dir(self) -> Path:
112
+ """Get the services directory."""
113
+ return self.claude_mpm_dir / "services"
114
+
115
+ @property
116
+ def hooks_dir(self) -> Path:
117
+ """Get the hooks directory."""
118
+ return self.claude_mpm_dir / "hooks"
119
+
120
+ @property
121
+ def config_dir(self) -> Path:
122
+ """Get the config directory."""
123
+ return self.claude_mpm_dir / "config"
124
+
125
+ @property
126
+ def cli_dir(self) -> Path:
127
+ """Get the CLI directory."""
128
+ return self.claude_mpm_dir / "cli"
129
+
130
+ @property
131
+ def core_dir(self) -> Path:
132
+ """Get the core directory."""
133
+ return self.claude_mpm_dir / "core"
134
+
135
+ @property
136
+ def schemas_dir(self) -> Path:
137
+ """Get the schemas directory."""
138
+ return self.claude_mpm_dir / "schemas"
139
+
140
+ @property
141
+ def scripts_dir(self) -> Path:
142
+ """Get the scripts directory."""
143
+ return self.project_root / "scripts"
144
+
145
+ @property
146
+ def tests_dir(self) -> Path:
147
+ """Get the tests directory."""
148
+ return self.project_root / "tests"
149
+
150
+ @property
151
+ def docs_dir(self) -> Path:
152
+ """Get the documentation directory."""
153
+ return self.project_root / "docs"
154
+
155
+ @property
156
+ def logs_dir(self) -> Path:
157
+ """Get the logs directory (creates if doesn't exist)."""
158
+ logs = self.project_root / "logs"
159
+ logs.mkdir(exist_ok=True)
160
+ return logs
161
+
162
+ @property
163
+ def temp_dir(self) -> Path:
164
+ """Get the temporary files directory (creates if doesn't exist)."""
165
+ temp = self.project_root / ".tmp"
166
+ temp.mkdir(exist_ok=True)
167
+ return temp
168
+
169
+ @property
170
+ def claude_mpm_dir_hidden(self) -> Path:
171
+ """Get the hidden .claude-mpm directory (creates if doesn't exist)."""
172
+ hidden = self.project_root / ".claude-mpm"
173
+ hidden.mkdir(exist_ok=True)
174
+ return hidden
175
+
176
+ @cached_property
177
+ def version_file(self) -> Path:
178
+ """Get the VERSION file path."""
179
+ return self.project_root / "VERSION"
180
+
181
+ @cached_property
182
+ def pyproject_file(self) -> Path:
183
+ """Get the pyproject.toml file path."""
184
+ return self.project_root / "pyproject.toml"
185
+
186
+ @cached_property
187
+ def package_json_file(self) -> Path:
188
+ """Get the package.json file path."""
189
+ return self.project_root / "package.json"
190
+
191
+ @cached_property
192
+ def claude_md_file(self) -> Path:
193
+ """Get the CLAUDE.md file path."""
194
+ return self.project_root / "CLAUDE.md"
195
+
196
+ def get_version(self) -> str:
197
+ """
198
+ Get the project version from various sources.
199
+
200
+ Returns:
201
+ Version string or 'unknown' if not found.
202
+ """
203
+ # Try VERSION file first
204
+ if self.version_file.exists():
205
+ return self.version_file.read_text().strip()
206
+
207
+ # Try package metadata
208
+ try:
209
+ from importlib.metadata import version
210
+ return version('claude-mpm')
211
+ except Exception:
212
+ pass
213
+
214
+ return 'unknown'
215
+
216
+ def ensure_in_path(self) -> None:
217
+ """Ensure src directory is in Python path."""
218
+ src_str = str(self.src_dir)
219
+ if src_str not in sys.path:
220
+ sys.path.insert(0, src_str)
221
+
222
+ def relative_to_project(self, path: Union[str, Path]) -> Path:
223
+ """
224
+ Get a path relative to the project root.
225
+
226
+ Args:
227
+ path: Path to make relative
228
+
229
+ Returns:
230
+ Path relative to project root
231
+ """
232
+ abs_path = Path(path).resolve()
233
+ try:
234
+ return abs_path.relative_to(self.project_root)
235
+ except ValueError:
236
+ return abs_path
237
+
238
+ def resolve_config_path(self, config_name: str) -> Path:
239
+ """
240
+ Resolve a configuration file path.
241
+
242
+ Args:
243
+ config_name: Name of the config file
244
+
245
+ Returns:
246
+ Full path to the config file
247
+ """
248
+ # Check in config directory first
249
+ config_path = self.config_dir / config_name
250
+ if config_path.exists():
251
+ return config_path
252
+
253
+ # Check in project root
254
+ root_path = self.project_root / config_name
255
+ if root_path.exists():
256
+ return root_path
257
+
258
+ # Return config dir path as default
259
+ return config_path
260
+
261
+ def __str__(self) -> str:
262
+ """String representation."""
263
+ return f"ClaudeMPMPaths(root={self.project_root})"
264
+
265
+ def __repr__(self) -> str:
266
+ """Developer representation."""
267
+ return (
268
+ f"ClaudeMPMPaths(\n"
269
+ f" project_root={self.project_root},\n"
270
+ f" src_dir={self.src_dir},\n"
271
+ f" claude_mpm_dir={self.claude_mpm_dir}\n"
272
+ f")"
273
+ )
274
+
275
+
276
+ # Singleton instance for import
277
+ paths = ClaudeMPMPaths()
278
+
279
+
280
+ # Convenience functions
281
+ def get_project_root() -> Path:
282
+ """Get the project root directory."""
283
+ return paths.project_root
284
+
285
+
286
+ def get_src_dir() -> Path:
287
+ """Get the src directory."""
288
+ return paths.src_dir
289
+
290
+
291
+ def get_claude_mpm_dir() -> Path:
292
+ """Get the main claude_mpm package directory."""
293
+ return paths.claude_mpm_dir
294
+
295
+
296
+ def get_agents_dir() -> Path:
297
+ """Get the agents directory."""
298
+ return paths.agents_dir
299
+
300
+
301
+ def get_services_dir() -> Path:
302
+ """Get the services directory."""
303
+ return paths.services_dir
304
+
305
+
306
+ def get_config_dir() -> Path:
307
+ """Get the config directory."""
308
+ return paths.config_dir
309
+
310
+
311
+ def get_version() -> str:
312
+ """Get the project version."""
313
+ return paths.get_version()
314
+
315
+
316
+ def ensure_src_in_path() -> None:
317
+ """Ensure src directory is in Python path."""
318
+ paths.ensure_in_path()
319
+
320
+
321
+ # Auto-ensure src is in path when module is imported
322
+ ensure_src_in_path()
claude_mpm/constants.py CHANGED
@@ -26,7 +26,6 @@ class CLICommands(str, Enum):
26
26
  TICKETS = "tickets"
27
27
  INFO = "info"
28
28
  AGENTS = "agents"
29
- UI = "ui"
30
29
  MEMORY = "memory"
31
30
  MONITOR = "monitor"
32
31
 
@@ -16,9 +16,8 @@ try:
16
16
  from .service_registry import ServiceRegistry, get_service_registry, initialize_services
17
17
  from .injectable_service import InjectableService
18
18
  from .factories import (
19
- ServiceFactory, HookManagerFactory, OrchestratorFactoryWrapper,
20
- AgentServiceFactory, SessionManagerFactory, ConfigurationFactory,
21
- get_factory_registry
19
+ ServiceFactory, AgentServiceFactory, SessionManagerFactory,
20
+ ConfigurationFactory, get_factory_registry
22
21
  )
23
22
  except ImportError:
24
23
  pass
@@ -36,8 +35,6 @@ __all__ = [
36
35
  "initialize_services",
37
36
  "InjectableService",
38
37
  "ServiceFactory",
39
- "HookManagerFactory",
40
- "OrchestratorFactoryWrapper",
41
38
  "AgentServiceFactory",
42
39
  "SessionManagerFactory",
43
40
  "ConfigurationFactory",
@@ -51,29 +51,49 @@ class SimpleAgentRegistry:
51
51
  self._discover_agents()
52
52
 
53
53
  def _discover_agents(self):
54
- """Discover agents from the framework."""
55
- # Check multiple possible locations
54
+ """Discover agents from the framework and project."""
55
+ # Check multiple possible locations, including project-level
56
56
  agent_locations = [
57
+ # Project-level agents (highest priority)
58
+ Path.cwd() / ".claude-mpm" / "agents",
59
+ # Framework/system agents
57
60
  self.framework_path / "src" / "claude_mpm" / "agents" / "templates",
58
61
  self.framework_path / "src" / "claude_mpm" / "agents",
59
62
  self.framework_path / "agents",
60
63
  ]
61
64
 
65
+ # Track discovered agents to handle precedence
66
+ discovered_agents = {}
67
+
62
68
  for agents_dir in agent_locations:
63
69
  if agents_dir.exists():
64
70
  # Look for both .md and .json files
65
71
  for pattern in ["*.md", "*.json"]:
66
72
  for agent_file in agents_dir.glob(pattern):
67
73
  agent_id = agent_file.stem
68
- self.agents[agent_id] = {
74
+ tier = self._determine_tier(agent_file)
75
+
76
+ # Check if we already have this agent
77
+ if agent_id in discovered_agents:
78
+ existing_tier = discovered_agents[agent_id]['tier']
79
+ # Skip if existing has higher precedence
80
+ # Precedence: project > user > system
81
+ tier_precedence = {'project': 3, 'user': 2, 'system': 1}
82
+ if tier_precedence.get(existing_tier, 0) >= tier_precedence.get(tier, 0):
83
+ continue
84
+
85
+ discovered_agents[agent_id] = {
69
86
  'name': agent_id,
70
87
  'type': agent_id,
71
88
  'path': str(agent_file),
72
89
  'last_modified': agent_file.stat().st_mtime,
73
- 'tier': self._determine_tier(agent_file),
90
+ 'tier': tier,
74
91
  'specializations': self._extract_specializations(agent_id),
75
92
  'description': self._extract_description(agent_id)
76
93
  }
94
+
95
+ # Store the final agents
96
+ self.agents = discovered_agents
77
97
 
78
98
  def _determine_tier(self, agent_path: Path) -> str:
79
99
  """Determine agent tier based on path."""
@@ -113,11 +133,21 @@ class SimpleAgentRegistry:
113
133
  }
114
134
  return descriptions.get(agent_id, f'{agent_id.title()} agent')
115
135
 
116
- def listAgents(self, **kwargs) -> Dict[str, Any]:
117
- """List all agents (camelCase for compatibility)."""
136
+ def list_agents(self, **kwargs) -> Dict[str, Any]:
137
+ """List all agents."""
118
138
  return self.agents
119
139
 
120
- def list_agents(self, agent_type: Optional[str] = None, tier: Optional[str] = None) -> List[AgentMetadata]:
140
+ def listAgents(self, **kwargs) -> Dict[str, Any]:
141
+ """DEPRECATED: Use list_agents() instead. Kept for backward compatibility."""
142
+ import warnings
143
+ warnings.warn(
144
+ "listAgents() is deprecated, use list_agents() instead",
145
+ DeprecationWarning,
146
+ stacklevel=2
147
+ )
148
+ return self.list_agents(**kwargs)
149
+
150
+ def list_agents_filtered(self, agent_type: Optional[str] = None, tier: Optional[str] = None) -> List[AgentMetadata]:
121
151
  """List agents with optional filtering."""
122
152
  results = []
123
153
  for agent_id, metadata in self.agents.items():
@@ -294,7 +324,7 @@ class AgentRegistryAdapter:
294
324
  return {}
295
325
 
296
326
  try:
297
- return self.registry.listAgents(**kwargs)
327
+ return self.registry.list_agents(**kwargs)
298
328
  except Exception as e:
299
329
  self.logger.error(f"Error listing agents: {e}")
300
330
  return {}
@@ -314,7 +344,7 @@ class AgentRegistryAdapter:
314
344
 
315
345
  try:
316
346
  # Try to load agent definition
317
- agents = self.registry.listAgents()
347
+ agents = self.registry.list_agents()
318
348
  for agent_id, metadata in agents.items():
319
349
  if agent_name in agent_id or agent_name == metadata.get('type'):
320
350
  # Load the agent file
@@ -344,7 +374,7 @@ class AgentRegistryAdapter:
344
374
 
345
375
  try:
346
376
  # Get agents with required specializations
347
- agents = self.registry.listAgents()
377
+ agents = self.registry.list_agents()
348
378
 
349
379
  if required_specializations:
350
380
  # Filter by specializations
@@ -386,7 +416,7 @@ class AgentRegistryAdapter:
386
416
 
387
417
  try:
388
418
  # Get all agents
389
- all_agents = self.registry.listAgents()
419
+ all_agents = self.registry.list_agents()
390
420
 
391
421
  hierarchy = {
392
422
  'project': [],
@@ -526,18 +556,33 @@ def get_specialized_agent_types() -> Set[str]:
526
556
  return adapter.registry.specialized_agent_types
527
557
  return set()
528
558
 
529
- def listAgents() -> Dict[str, Dict[str, Any]]:
559
+ def list_agents_all() -> Dict[str, Dict[str, Any]]:
530
560
  """
531
- Synchronous function for listing all agents (camelCase compatibility)
561
+ Synchronous function for listing all agents
532
562
 
533
563
  Returns:
534
564
  Dictionary of agent name -> agent metadata
535
565
  """
536
566
  adapter = AgentRegistryAdapter()
537
567
  if adapter.registry:
538
- return adapter.registry.listAgents()
568
+ return adapter.registry.list_agents()
539
569
  return {}
540
570
 
571
+ def listAgents() -> Dict[str, Dict[str, Any]]:
572
+ """
573
+ DEPRECATED: Use list_agents_all() instead. Kept for backward compatibility.
574
+
575
+ Returns:
576
+ Dictionary of agent name -> agent metadata
577
+ """
578
+ import warnings
579
+ warnings.warn(
580
+ "listAgents() is deprecated, use list_agents_all() instead",
581
+ DeprecationWarning,
582
+ stacklevel=2
583
+ )
584
+ return list_agents_all()
585
+
541
586
  def list_agents(agent_type: Optional[str] = None, tier: Optional[str] = None) -> List[AgentMetadata]:
542
587
  """
543
588
  Synchronous function to list agents with optional filtering
@@ -551,7 +596,7 @@ def list_agents(agent_type: Optional[str] = None, tier: Optional[str] = None) ->
551
596
  """
552
597
  adapter = AgentRegistryAdapter()
553
598
  if adapter.registry:
554
- return adapter.registry.list_agents(agent_type=agent_type, tier=tier)
599
+ return adapter.registry.list_agents_filtered(agent_type=agent_type, tier=tier)
555
600
  return []
556
601
 
557
602
  def discover_agents_sync(force_refresh: bool = False) -> Dict[str, AgentMetadata]:
@@ -600,7 +645,7 @@ def get_registry_stats() -> Dict[str, Any]:
600
645
  """
601
646
  adapter = AgentRegistryAdapter()
602
647
  if adapter.registry:
603
- agents = adapter.registry.list_agents()
648
+ agents = adapter.registry.list_agents_filtered()
604
649
  return {
605
650
  'total_agents': len(agents),
606
651
  'agent_types': len(set(a.type for a in agents)),
@@ -619,8 +664,9 @@ __all__ = [
619
664
  'discover_agents',
620
665
  'get_core_agent_types',
621
666
  'get_specialized_agent_types',
622
- 'listAgents',
667
+ 'list_agents_all',
623
668
  'list_agents',
669
+ 'listAgents', # Deprecated
624
670
  'discover_agents_sync',
625
671
  'get_agent',
626
672
  'get_registry_stats'