claude-mpm 4.1.4__py3-none-any.whl → 4.1.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/templates/research.json +39 -13
- claude_mpm/cli/__init__.py +2 -0
- claude_mpm/cli/commands/__init__.py +2 -0
- claude_mpm/cli/commands/configure.py +1221 -0
- claude_mpm/cli/commands/configure_tui.py +1921 -0
- claude_mpm/cli/commands/tickets.py +365 -784
- claude_mpm/cli/parsers/base_parser.py +7 -0
- claude_mpm/cli/parsers/configure_parser.py +119 -0
- claude_mpm/cli/startup_logging.py +39 -12
- claude_mpm/constants.py +1 -0
- claude_mpm/core/output_style_manager.py +24 -0
- claude_mpm/core/socketio_pool.py +35 -3
- claude_mpm/core/unified_agent_registry.py +46 -15
- claude_mpm/dashboard/static/css/connection-status.css +370 -0
- claude_mpm/dashboard/static/js/components/connection-debug.js +654 -0
- claude_mpm/dashboard/static/js/connection-manager.js +536 -0
- claude_mpm/dashboard/templates/index.html +11 -0
- claude_mpm/hooks/claude_hooks/services/__init__.py +3 -1
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +190 -0
- claude_mpm/services/agents/deployment/agent_discovery_service.py +12 -3
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +172 -233
- claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +575 -0
- claude_mpm/services/agents/deployment/agent_operation_service.py +573 -0
- claude_mpm/services/agents/deployment/agent_record_service.py +419 -0
- claude_mpm/services/agents/deployment/agent_state_service.py +381 -0
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +4 -2
- claude_mpm/services/diagnostics/checks/__init__.py +2 -0
- claude_mpm/services/diagnostics/checks/instructions_check.py +418 -0
- claude_mpm/services/diagnostics/diagnostic_runner.py +15 -2
- claude_mpm/services/event_bus/direct_relay.py +173 -0
- claude_mpm/services/infrastructure/__init__.py +31 -5
- claude_mpm/services/infrastructure/monitoring/__init__.py +43 -0
- claude_mpm/services/infrastructure/monitoring/aggregator.py +437 -0
- claude_mpm/services/infrastructure/monitoring/base.py +130 -0
- claude_mpm/services/infrastructure/monitoring/legacy.py +203 -0
- claude_mpm/services/infrastructure/monitoring/network.py +218 -0
- claude_mpm/services/infrastructure/monitoring/process.py +342 -0
- claude_mpm/services/infrastructure/monitoring/resources.py +243 -0
- claude_mpm/services/infrastructure/monitoring/service.py +367 -0
- claude_mpm/services/infrastructure/monitoring.py +67 -1030
- claude_mpm/services/project/analyzer.py +13 -4
- claude_mpm/services/project/analyzer_refactored.py +450 -0
- claude_mpm/services/project/analyzer_v2.py +566 -0
- claude_mpm/services/project/architecture_analyzer.py +461 -0
- claude_mpm/services/project/dependency_analyzer.py +462 -0
- claude_mpm/services/project/language_analyzer.py +265 -0
- claude_mpm/services/project/metrics_collector.py +410 -0
- claude_mpm/services/socketio/handlers/connection_handler.py +345 -0
- claude_mpm/services/socketio/server/broadcaster.py +32 -1
- claude_mpm/services/socketio/server/connection_manager.py +516 -0
- claude_mpm/services/socketio/server/core.py +63 -0
- claude_mpm/services/socketio/server/eventbus_integration.py +20 -9
- claude_mpm/services/socketio/server/main.py +27 -1
- claude_mpm/services/ticket_manager.py +5 -1
- claude_mpm/services/ticket_services/__init__.py +26 -0
- claude_mpm/services/ticket_services/crud_service.py +328 -0
- claude_mpm/services/ticket_services/formatter_service.py +290 -0
- claude_mpm/services/ticket_services/search_service.py +324 -0
- claude_mpm/services/ticket_services/validation_service.py +303 -0
- claude_mpm/services/ticket_services/workflow_service.py +244 -0
- {claude_mpm-4.1.4.dist-info → claude_mpm-4.1.6.dist-info}/METADATA +3 -1
- {claude_mpm-4.1.4.dist-info → claude_mpm-4.1.6.dist-info}/RECORD +67 -46
- claude_mpm/agents/OUTPUT_STYLE.md +0 -73
- claude_mpm/agents/backups/INSTRUCTIONS.md +0 -352
- claude_mpm/agents/templates/OPTIMIZATION_REPORT.md +0 -156
- claude_mpm/agents/templates/backup/data_engineer_agent_20250726_234551.json +0 -79
- claude_mpm/agents/templates/backup/documentation_agent_20250726_234551.json +0 -68
- claude_mpm/agents/templates/backup/engineer_agent_20250726_234551.json +0 -77
- claude_mpm/agents/templates/backup/ops_agent_20250726_234551.json +0 -78
- claude_mpm/agents/templates/backup/qa_agent_20250726_234551.json +0 -67
- claude_mpm/agents/templates/backup/research_agent_2025011_234551.json +0 -88
- claude_mpm/agents/templates/backup/research_agent_20250726_234551.json +0 -72
- claude_mpm/agents/templates/backup/research_memory_efficient.json +0 -88
- claude_mpm/agents/templates/backup/security_agent_20250726_234551.json +0 -78
- claude_mpm/agents/templates/backup/version_control_agent_20250726_234551.json +0 -62
- claude_mpm/agents/templates/vercel_ops_instructions.md +0 -582
- {claude_mpm-4.1.4.dist-info → claude_mpm-4.1.6.dist-info}/WHEEL +0 -0
- {claude_mpm-4.1.4.dist-info → claude_mpm-4.1.6.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.1.4.dist-info → claude_mpm-4.1.6.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.1.4.dist-info → claude_mpm-4.1.6.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Agent State Service - State Management for Agent Lifecycle
|
|
4
|
+
===========================================================
|
|
5
|
+
|
|
6
|
+
Handles agent state tracking and transitions for the lifecycle manager.
|
|
7
|
+
Extracted from AgentLifecycleManager to follow Single Responsibility Principle.
|
|
8
|
+
|
|
9
|
+
Key Responsibilities:
|
|
10
|
+
- Track agent states (ACTIVE, MODIFIED, DELETED, etc.)
|
|
11
|
+
- Manage state transitions
|
|
12
|
+
- Validate state changes
|
|
13
|
+
- Maintain state history
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import time
|
|
17
|
+
from dataclasses import dataclass, field
|
|
18
|
+
from enum import Enum
|
|
19
|
+
from typing import Dict, List, Optional
|
|
20
|
+
|
|
21
|
+
from claude_mpm.core.base_service import BaseService
|
|
22
|
+
from claude_mpm.services.agents.registry.modification_tracker import ModificationTier
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class LifecycleState(Enum):
|
|
26
|
+
"""Agent lifecycle states."""
|
|
27
|
+
|
|
28
|
+
ACTIVE = "active"
|
|
29
|
+
MODIFIED = "modified"
|
|
30
|
+
DELETED = "deleted"
|
|
31
|
+
CONFLICTED = "conflicted"
|
|
32
|
+
MIGRATING = "migrating"
|
|
33
|
+
VALIDATING = "validating"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclass
|
|
37
|
+
class AgentLifecycleRecord:
|
|
38
|
+
"""Complete lifecycle record for an agent."""
|
|
39
|
+
|
|
40
|
+
agent_name: str
|
|
41
|
+
current_state: LifecycleState
|
|
42
|
+
tier: ModificationTier
|
|
43
|
+
file_path: str
|
|
44
|
+
created_at: float
|
|
45
|
+
last_modified: float
|
|
46
|
+
version: str
|
|
47
|
+
modifications: List[str] = field(default_factory=list) # Modification IDs
|
|
48
|
+
persistence_operations: List[str] = field(default_factory=list) # Operation IDs
|
|
49
|
+
backup_paths: List[str] = field(default_factory=list)
|
|
50
|
+
validation_status: str = "valid"
|
|
51
|
+
validation_errors: List[str] = field(default_factory=list)
|
|
52
|
+
metadata: Dict[str, any] = field(default_factory=dict)
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def age_days(self) -> float:
|
|
56
|
+
"""Get age in days."""
|
|
57
|
+
return (time.time() - self.created_at) / (24 * 3600)
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def last_modified_datetime(self):
|
|
61
|
+
"""Get last modified as datetime."""
|
|
62
|
+
from datetime import datetime
|
|
63
|
+
|
|
64
|
+
return datetime.fromtimestamp(self.last_modified)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@dataclass
|
|
68
|
+
class StateTransition:
|
|
69
|
+
"""Record of a state transition."""
|
|
70
|
+
|
|
71
|
+
agent_name: str
|
|
72
|
+
from_state: LifecycleState
|
|
73
|
+
to_state: LifecycleState
|
|
74
|
+
timestamp: float
|
|
75
|
+
reason: str
|
|
76
|
+
metadata: Dict[str, any] = field(default_factory=dict)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class AgentStateService(BaseService):
|
|
80
|
+
"""
|
|
81
|
+
Service for managing agent lifecycle states.
|
|
82
|
+
|
|
83
|
+
Responsibilities:
|
|
84
|
+
- Track current state of all agents
|
|
85
|
+
- Validate and execute state transitions
|
|
86
|
+
- Maintain state history
|
|
87
|
+
- Query agents by state
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
def __init__(self):
|
|
91
|
+
"""Initialize the agent state service."""
|
|
92
|
+
super().__init__("agent_state_service")
|
|
93
|
+
|
|
94
|
+
# Agent records storage
|
|
95
|
+
self.agent_records: Dict[str, AgentLifecycleRecord] = {}
|
|
96
|
+
|
|
97
|
+
# State transition history
|
|
98
|
+
self.transition_history: List[StateTransition] = []
|
|
99
|
+
|
|
100
|
+
# Valid state transitions
|
|
101
|
+
self.valid_transitions = {
|
|
102
|
+
LifecycleState.ACTIVE: [
|
|
103
|
+
LifecycleState.MODIFIED,
|
|
104
|
+
LifecycleState.DELETED,
|
|
105
|
+
LifecycleState.CONFLICTED,
|
|
106
|
+
LifecycleState.MIGRATING,
|
|
107
|
+
LifecycleState.VALIDATING,
|
|
108
|
+
],
|
|
109
|
+
LifecycleState.MODIFIED: [
|
|
110
|
+
LifecycleState.ACTIVE,
|
|
111
|
+
LifecycleState.DELETED,
|
|
112
|
+
LifecycleState.CONFLICTED,
|
|
113
|
+
LifecycleState.VALIDATING,
|
|
114
|
+
],
|
|
115
|
+
LifecycleState.DELETED: [
|
|
116
|
+
LifecycleState.ACTIVE, # For restoration
|
|
117
|
+
],
|
|
118
|
+
LifecycleState.CONFLICTED: [
|
|
119
|
+
LifecycleState.ACTIVE,
|
|
120
|
+
LifecycleState.MODIFIED,
|
|
121
|
+
LifecycleState.DELETED,
|
|
122
|
+
],
|
|
123
|
+
LifecycleState.MIGRATING: [
|
|
124
|
+
LifecycleState.ACTIVE,
|
|
125
|
+
LifecycleState.MODIFIED,
|
|
126
|
+
LifecycleState.CONFLICTED,
|
|
127
|
+
],
|
|
128
|
+
LifecycleState.VALIDATING: [
|
|
129
|
+
LifecycleState.ACTIVE,
|
|
130
|
+
LifecycleState.MODIFIED,
|
|
131
|
+
LifecycleState.CONFLICTED,
|
|
132
|
+
],
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
self.logger.info("AgentStateService initialized")
|
|
136
|
+
|
|
137
|
+
def create_record(
|
|
138
|
+
self,
|
|
139
|
+
agent_name: str,
|
|
140
|
+
tier: ModificationTier,
|
|
141
|
+
file_path: str,
|
|
142
|
+
initial_state: LifecycleState = LifecycleState.ACTIVE,
|
|
143
|
+
version: str = "1.0.0",
|
|
144
|
+
**metadata,
|
|
145
|
+
) -> AgentLifecycleRecord:
|
|
146
|
+
"""
|
|
147
|
+
Create a new agent lifecycle record.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
agent_name: Name of the agent
|
|
151
|
+
tier: Agent tier (USER, PROJECT, SYSTEM)
|
|
152
|
+
file_path: Path to agent file
|
|
153
|
+
initial_state: Initial state (default: ACTIVE)
|
|
154
|
+
version: Initial version
|
|
155
|
+
**metadata: Additional metadata
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
Created AgentLifecycleRecord
|
|
159
|
+
"""
|
|
160
|
+
record = AgentLifecycleRecord(
|
|
161
|
+
agent_name=agent_name,
|
|
162
|
+
current_state=initial_state,
|
|
163
|
+
tier=tier,
|
|
164
|
+
file_path=file_path,
|
|
165
|
+
created_at=time.time(),
|
|
166
|
+
last_modified=time.time(),
|
|
167
|
+
version=version,
|
|
168
|
+
metadata=metadata,
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
self.agent_records[agent_name] = record
|
|
172
|
+
self.logger.debug(f"Created lifecycle record for agent '{agent_name}'")
|
|
173
|
+
|
|
174
|
+
return record
|
|
175
|
+
|
|
176
|
+
def get_record(self, agent_name: str) -> Optional[AgentLifecycleRecord]:
|
|
177
|
+
"""Get lifecycle record for an agent."""
|
|
178
|
+
return self.agent_records.get(agent_name)
|
|
179
|
+
|
|
180
|
+
def update_state(
|
|
181
|
+
self, agent_name: str, new_state: LifecycleState, reason: str = "", **metadata
|
|
182
|
+
) -> bool:
|
|
183
|
+
"""
|
|
184
|
+
Update agent state with validation.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
agent_name: Name of the agent
|
|
188
|
+
new_state: Target state
|
|
189
|
+
reason: Reason for transition
|
|
190
|
+
**metadata: Additional metadata
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
True if transition successful, False otherwise
|
|
194
|
+
"""
|
|
195
|
+
record = self.agent_records.get(agent_name)
|
|
196
|
+
if not record:
|
|
197
|
+
self.logger.warning(f"Agent '{agent_name}' not found for state update")
|
|
198
|
+
return False
|
|
199
|
+
|
|
200
|
+
# Check if transition is valid
|
|
201
|
+
if not self._is_valid_transition(record.current_state, new_state):
|
|
202
|
+
self.logger.warning(
|
|
203
|
+
f"Invalid state transition for '{agent_name}': "
|
|
204
|
+
f"{record.current_state.value} -> {new_state.value}"
|
|
205
|
+
)
|
|
206
|
+
return False
|
|
207
|
+
|
|
208
|
+
# Record transition
|
|
209
|
+
transition = StateTransition(
|
|
210
|
+
agent_name=agent_name,
|
|
211
|
+
from_state=record.current_state,
|
|
212
|
+
to_state=new_state,
|
|
213
|
+
timestamp=time.time(),
|
|
214
|
+
reason=reason,
|
|
215
|
+
metadata=metadata,
|
|
216
|
+
)
|
|
217
|
+
self.transition_history.append(transition)
|
|
218
|
+
|
|
219
|
+
# Update state
|
|
220
|
+
old_state = record.current_state
|
|
221
|
+
record.current_state = new_state
|
|
222
|
+
record.last_modified = time.time()
|
|
223
|
+
|
|
224
|
+
self.logger.info(
|
|
225
|
+
f"Agent '{agent_name}' state changed: "
|
|
226
|
+
f"{old_state.value} -> {new_state.value}"
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
return True
|
|
230
|
+
|
|
231
|
+
def _is_valid_transition(
|
|
232
|
+
self, from_state: LifecycleState, to_state: LifecycleState
|
|
233
|
+
) -> bool:
|
|
234
|
+
"""Check if a state transition is valid."""
|
|
235
|
+
if from_state == to_state:
|
|
236
|
+
return True # Allow same state (no-op)
|
|
237
|
+
|
|
238
|
+
valid_targets = self.valid_transitions.get(from_state, [])
|
|
239
|
+
return to_state in valid_targets
|
|
240
|
+
|
|
241
|
+
def list_agents_by_state(
|
|
242
|
+
self, state: Optional[LifecycleState] = None
|
|
243
|
+
) -> List[AgentLifecycleRecord]:
|
|
244
|
+
"""
|
|
245
|
+
List agents filtered by state.
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
state: State to filter by (None for all)
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
List of matching agent records
|
|
252
|
+
"""
|
|
253
|
+
agents = list(self.agent_records.values())
|
|
254
|
+
|
|
255
|
+
if state:
|
|
256
|
+
agents = [a for a in agents if a.current_state == state]
|
|
257
|
+
|
|
258
|
+
return sorted(agents, key=lambda x: x.last_modified, reverse=True)
|
|
259
|
+
|
|
260
|
+
def get_state_statistics(self) -> Dict[str, int]:
|
|
261
|
+
"""Get count of agents in each state."""
|
|
262
|
+
stats = {}
|
|
263
|
+
for record in self.agent_records.values():
|
|
264
|
+
state_name = record.current_state.value
|
|
265
|
+
stats[state_name] = stats.get(state_name, 0) + 1
|
|
266
|
+
return stats
|
|
267
|
+
|
|
268
|
+
def get_transition_history(
|
|
269
|
+
self, agent_name: Optional[str] = None, limit: int = 100
|
|
270
|
+
) -> List[StateTransition]:
|
|
271
|
+
"""
|
|
272
|
+
Get state transition history.
|
|
273
|
+
|
|
274
|
+
Args:
|
|
275
|
+
agent_name: Filter by agent name (None for all)
|
|
276
|
+
limit: Maximum number of transitions to return
|
|
277
|
+
|
|
278
|
+
Returns:
|
|
279
|
+
List of state transitions
|
|
280
|
+
"""
|
|
281
|
+
history = self.transition_history
|
|
282
|
+
|
|
283
|
+
if agent_name:
|
|
284
|
+
history = [t for t in history if t.agent_name == agent_name]
|
|
285
|
+
|
|
286
|
+
# Return most recent first
|
|
287
|
+
return sorted(history, key=lambda x: x.timestamp, reverse=True)[:limit]
|
|
288
|
+
|
|
289
|
+
def update_record_metadata(self, agent_name: str, **metadata) -> bool:
|
|
290
|
+
"""
|
|
291
|
+
Update metadata for an agent record.
|
|
292
|
+
|
|
293
|
+
Args:
|
|
294
|
+
agent_name: Name of the agent
|
|
295
|
+
**metadata: Metadata to update
|
|
296
|
+
|
|
297
|
+
Returns:
|
|
298
|
+
True if successful, False if agent not found
|
|
299
|
+
"""
|
|
300
|
+
record = self.agent_records.get(agent_name)
|
|
301
|
+
if not record:
|
|
302
|
+
return False
|
|
303
|
+
|
|
304
|
+
record.metadata.update(metadata)
|
|
305
|
+
record.last_modified = time.time()
|
|
306
|
+
return True
|
|
307
|
+
|
|
308
|
+
def increment_version(self, agent_name: str) -> Optional[str]:
|
|
309
|
+
"""
|
|
310
|
+
Increment the patch version of an agent.
|
|
311
|
+
|
|
312
|
+
Args:
|
|
313
|
+
agent_name: Name of the agent
|
|
314
|
+
|
|
315
|
+
Returns:
|
|
316
|
+
New version string or None if agent not found
|
|
317
|
+
"""
|
|
318
|
+
record = self.agent_records.get(agent_name)
|
|
319
|
+
if not record:
|
|
320
|
+
return None
|
|
321
|
+
|
|
322
|
+
# Parse and increment version
|
|
323
|
+
parts = record.version.split(".")
|
|
324
|
+
parts[-1] = str(int(parts[-1]) + 1)
|
|
325
|
+
record.version = ".".join(parts)
|
|
326
|
+
record.last_modified = time.time()
|
|
327
|
+
|
|
328
|
+
return record.version
|
|
329
|
+
|
|
330
|
+
def add_modification(self, agent_name: str, modification_id: str) -> bool:
|
|
331
|
+
"""Add a modification ID to agent's history."""
|
|
332
|
+
record = self.agent_records.get(agent_name)
|
|
333
|
+
if not record:
|
|
334
|
+
return False
|
|
335
|
+
|
|
336
|
+
record.modifications.append(modification_id)
|
|
337
|
+
record.last_modified = time.time()
|
|
338
|
+
return True
|
|
339
|
+
|
|
340
|
+
def add_persistence_operation(self, agent_name: str, operation_id: str) -> bool:
|
|
341
|
+
"""Add a persistence operation ID to agent's history."""
|
|
342
|
+
record = self.agent_records.get(agent_name)
|
|
343
|
+
if not record:
|
|
344
|
+
return False
|
|
345
|
+
|
|
346
|
+
record.persistence_operations.append(operation_id)
|
|
347
|
+
record.last_modified = time.time()
|
|
348
|
+
return True
|
|
349
|
+
|
|
350
|
+
def add_backup_path(self, agent_name: str, backup_path: str) -> bool:
|
|
351
|
+
"""Add a backup path to agent's record."""
|
|
352
|
+
record = self.agent_records.get(agent_name)
|
|
353
|
+
if not record:
|
|
354
|
+
return False
|
|
355
|
+
|
|
356
|
+
record.backup_paths.append(backup_path)
|
|
357
|
+
record.last_modified = time.time()
|
|
358
|
+
return True
|
|
359
|
+
|
|
360
|
+
def get_tier_statistics(self) -> Dict[str, int]:
|
|
361
|
+
"""Get count of agents in each tier."""
|
|
362
|
+
stats = {}
|
|
363
|
+
for record in self.agent_records.values():
|
|
364
|
+
tier_name = record.tier.value
|
|
365
|
+
stats[tier_name] = stats.get(tier_name, 0) + 1
|
|
366
|
+
return stats
|
|
367
|
+
|
|
368
|
+
async def _initialize(self) -> None:
|
|
369
|
+
"""Initialize the state service."""
|
|
370
|
+
self.logger.info("AgentStateService initialized")
|
|
371
|
+
|
|
372
|
+
async def _cleanup(self) -> None:
|
|
373
|
+
"""Cleanup the state service."""
|
|
374
|
+
self.logger.info("AgentStateService cleaned up")
|
|
375
|
+
|
|
376
|
+
async def _health_check(self) -> Dict[str, bool]:
|
|
377
|
+
"""Perform health check."""
|
|
378
|
+
return {
|
|
379
|
+
"records_loaded": len(self.agent_records) > 0,
|
|
380
|
+
"transitions_valid": True,
|
|
381
|
+
}
|
|
@@ -93,7 +93,8 @@ class MultiSourceAgentDeploymentService:
|
|
|
93
93
|
f"Discovering agents from {source_name} source: {source_dir}"
|
|
94
94
|
)
|
|
95
95
|
discovery_service = AgentDiscoveryService(source_dir)
|
|
96
|
-
|
|
96
|
+
# Pass log_discovery=False to avoid duplicate logging
|
|
97
|
+
agents = discovery_service.list_available_agents(log_discovery=False)
|
|
97
98
|
|
|
98
99
|
for agent_info in agents:
|
|
99
100
|
agent_name = agent_info.get("name")
|
|
@@ -110,8 +111,9 @@ class MultiSourceAgentDeploymentService:
|
|
|
110
111
|
|
|
111
112
|
agents_by_name[agent_name].append(agent_info)
|
|
112
113
|
|
|
114
|
+
# Use more specific log message
|
|
113
115
|
self.logger.info(
|
|
114
|
-
f"Discovered {len(agents)}
|
|
116
|
+
f"Discovered {len(agents)} {source_name} agent templates from {source_dir.name}"
|
|
115
117
|
)
|
|
116
118
|
|
|
117
119
|
return agents_by_name
|
|
@@ -12,6 +12,7 @@ from .common_issues_check import CommonIssuesCheck
|
|
|
12
12
|
from .configuration_check import ConfigurationCheck
|
|
13
13
|
from .filesystem_check import FilesystemCheck
|
|
14
14
|
from .installation_check import InstallationCheck
|
|
15
|
+
from .instructions_check import InstructionsCheck
|
|
15
16
|
from .mcp_check import MCPCheck
|
|
16
17
|
from .monitor_check import MonitorCheck
|
|
17
18
|
from .startup_log_check import StartupLogCheck
|
|
@@ -24,6 +25,7 @@ __all__ = [
|
|
|
24
25
|
"ConfigurationCheck",
|
|
25
26
|
"FilesystemCheck",
|
|
26
27
|
"InstallationCheck",
|
|
28
|
+
"InstructionsCheck",
|
|
27
29
|
"MCPCheck",
|
|
28
30
|
"MonitorCheck",
|
|
29
31
|
"StartupLogCheck",
|