claude-mpm 5.0.2__py3-none-any.whl → 5.1.9__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.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +2002 -0
- claude_mpm/agents/PM_INSTRUCTIONS.md +1176 -909
- claude_mpm/agents/base_agent_loader.py +10 -35
- claude_mpm/agents/frontmatter_validator.py +68 -0
- claude_mpm/agents/templates/circuit-breakers.md +293 -44
- claude_mpm/cli/__init__.py +0 -1
- claude_mpm/cli/commands/__init__.py +2 -0
- claude_mpm/cli/commands/agent_state_manager.py +64 -11
- claude_mpm/cli/commands/agents.py +446 -25
- claude_mpm/cli/commands/auto_configure.py +535 -233
- claude_mpm/cli/commands/configure.py +545 -89
- claude_mpm/cli/commands/postmortem.py +401 -0
- claude_mpm/cli/commands/run.py +1 -39
- claude_mpm/cli/commands/skills.py +322 -19
- claude_mpm/cli/interactive/agent_wizard.py +302 -195
- claude_mpm/cli/parsers/agents_parser.py +137 -0
- claude_mpm/cli/parsers/auto_configure_parser.py +13 -0
- claude_mpm/cli/parsers/base_parser.py +4 -0
- claude_mpm/cli/parsers/skills_parser.py +7 -0
- claude_mpm/cli/startup.py +73 -32
- claude_mpm/commands/mpm-agents-auto-configure.md +2 -2
- claude_mpm/commands/mpm-agents-list.md +2 -2
- claude_mpm/commands/mpm-config-view.md +2 -2
- claude_mpm/commands/mpm-help.md +3 -0
- claude_mpm/commands/mpm-postmortem.md +123 -0
- claude_mpm/commands/mpm-session-resume.md +2 -2
- claude_mpm/commands/mpm-ticket-organize.md +2 -2
- claude_mpm/commands/mpm-ticket-view.md +2 -2
- claude_mpm/config/agent_presets.py +312 -82
- claude_mpm/config/skill_presets.py +392 -0
- claude_mpm/constants.py +1 -0
- claude_mpm/core/claude_runner.py +2 -25
- claude_mpm/core/framework/loaders/file_loader.py +54 -101
- claude_mpm/core/interactive_session.py +19 -5
- claude_mpm/core/oneshot_session.py +16 -4
- claude_mpm/core/output_style_manager.py +173 -43
- claude_mpm/core/protocols/__init__.py +23 -0
- claude_mpm/core/protocols/runner_protocol.py +103 -0
- claude_mpm/core/protocols/session_protocol.py +131 -0
- claude_mpm/core/shared/singleton_manager.py +11 -4
- claude_mpm/core/system_context.py +38 -0
- claude_mpm/core/unified_agent_registry.py +129 -1
- claude_mpm/core/unified_config.py +22 -0
- claude_mpm/hooks/claude_hooks/memory_integration.py +12 -1
- claude_mpm/models/agent_definition.py +7 -0
- claude_mpm/services/agents/cache_git_manager.py +621 -0
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +110 -3
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +195 -1
- claude_mpm/services/agents/sources/git_source_sync_service.py +37 -5
- claude_mpm/services/analysis/__init__.py +25 -0
- claude_mpm/services/analysis/postmortem_reporter.py +474 -0
- claude_mpm/services/analysis/postmortem_service.py +765 -0
- claude_mpm/services/command_deployment_service.py +108 -5
- claude_mpm/services/core/base.py +7 -2
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +7 -15
- claude_mpm/services/git/git_operations_service.py +8 -8
- claude_mpm/services/mcp_config_manager.py +75 -145
- claude_mpm/services/mcp_gateway/core/process_pool.py +22 -16
- claude_mpm/services/mcp_service_verifier.py +6 -3
- claude_mpm/services/monitor/daemon.py +28 -8
- claude_mpm/services/monitor/daemon_manager.py +96 -19
- claude_mpm/services/project/project_organizer.py +4 -0
- claude_mpm/services/runner_configuration_service.py +16 -3
- claude_mpm/services/session_management_service.py +16 -4
- claude_mpm/utils/agent_filters.py +288 -0
- claude_mpm/utils/gitignore.py +3 -0
- claude_mpm/utils/migration.py +372 -0
- claude_mpm/utils/progress.py +5 -1
- {claude_mpm-5.0.2.dist-info → claude_mpm-5.1.9.dist-info}/METADATA +69 -8
- {claude_mpm-5.0.2.dist-info → claude_mpm-5.1.9.dist-info}/RECORD +76 -62
- /claude_mpm/agents/{OUTPUT_STYLE.md → CLAUDE_MPM_OUTPUT_STYLE.md} +0 -0
- {claude_mpm-5.0.2.dist-info → claude_mpm-5.1.9.dist-info}/WHEEL +0 -0
- {claude_mpm-5.0.2.dist-info → claude_mpm-5.1.9.dist-info}/entry_points.txt +0 -0
- {claude_mpm-5.0.2.dist-info → claude_mpm-5.1.9.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.0.2.dist-info → claude_mpm-5.1.9.dist-info}/top_level.txt +0 -0
|
@@ -167,6 +167,16 @@ class AgentsCommand(AgentCommand):
|
|
|
167
167
|
"available": self._list_available_from_sources,
|
|
168
168
|
# Agent discovery with rich filtering (Phase 1: Discovery & Browsing)
|
|
169
169
|
"discover": self._discover_agents,
|
|
170
|
+
# NEW: Collection-based agent management
|
|
171
|
+
"list-collections": self._list_collections,
|
|
172
|
+
"deploy-collection": self._deploy_collection,
|
|
173
|
+
"list-by-collection": self._list_by_collection,
|
|
174
|
+
# Cache git management commands
|
|
175
|
+
"cache-status": self._cache_status,
|
|
176
|
+
"cache-pull": self._cache_pull,
|
|
177
|
+
"cache-push": self._cache_push,
|
|
178
|
+
"cache-sync": self._cache_sync,
|
|
179
|
+
"cache-commit": self._cache_commit,
|
|
170
180
|
}
|
|
171
181
|
|
|
172
182
|
if args.agents_command in command_map:
|
|
@@ -551,34 +561,63 @@ class AgentsCommand(AgentCommand):
|
|
|
551
561
|
return CommandResult.error_result(f"Error discovering agents: {e}")
|
|
552
562
|
|
|
553
563
|
def _deploy_agents(self, args, force=False) -> CommandResult:
|
|
554
|
-
"""Deploy
|
|
564
|
+
"""Deploy agents using two-phase sync: cache → deploy.
|
|
565
|
+
|
|
566
|
+
Phase 3 Integration (1M-486): Uses Git sync service for deployment.
|
|
567
|
+
- Phase 1: Sync agents to ~/.claude-mpm/cache/remote-agents/ (if needed)
|
|
568
|
+
- Phase 2: Deploy from cache to project .claude-mpm/agents/
|
|
569
|
+
|
|
570
|
+
This replaces the old single-tier deployment with a multi-project
|
|
571
|
+
architecture where one cache serves multiple project deployments.
|
|
572
|
+
"""
|
|
555
573
|
try:
|
|
556
|
-
# Handle preset deployment
|
|
574
|
+
# Handle preset deployment (uses different path)
|
|
557
575
|
if hasattr(args, "preset") and args.preset:
|
|
558
576
|
return self._deploy_preset(args)
|
|
559
577
|
|
|
560
|
-
|
|
561
|
-
|
|
578
|
+
from ...services.agents.sources.git_source_sync_service import (
|
|
579
|
+
GitSourceSyncService,
|
|
580
|
+
)
|
|
581
|
+
|
|
582
|
+
# Initialize git sync service
|
|
583
|
+
git_sync = GitSourceSyncService()
|
|
584
|
+
project_dir = Path.cwd()
|
|
585
|
+
|
|
586
|
+
self.logger.info("Phase 1: Syncing agents to cache...")
|
|
587
|
+
|
|
588
|
+
# Sync to cache (downloads from GitHub if needed)
|
|
589
|
+
sync_result = git_sync.sync_repository(force=force)
|
|
590
|
+
|
|
591
|
+
if not sync_result.get("synced"):
|
|
592
|
+
error_msg = sync_result.get("error", "Unknown sync error")
|
|
593
|
+
self.logger.error(f"Sync failed: {error_msg}")
|
|
594
|
+
return CommandResult.error_result(f"Sync failed: {error_msg}")
|
|
595
|
+
|
|
596
|
+
self.logger.info(
|
|
597
|
+
f"Phase 1 complete: {sync_result.get('agent_count', 0)} agents in cache"
|
|
598
|
+
)
|
|
599
|
+
self.logger.info(f"Phase 2: Deploying agents to {project_dir}...")
|
|
562
600
|
|
|
563
|
-
# Deploy
|
|
564
|
-
|
|
601
|
+
# Deploy from cache to project directory
|
|
602
|
+
deploy_result = git_sync.deploy_agents_to_project(
|
|
603
|
+
project_dir=project_dir,
|
|
604
|
+
agent_list=None, # Deploy all cached agents
|
|
605
|
+
force=force,
|
|
606
|
+
)
|
|
565
607
|
|
|
566
|
-
#
|
|
608
|
+
# Format combined results for output
|
|
567
609
|
combined_result = {
|
|
568
|
-
"deployed_count":
|
|
569
|
-
+
|
|
570
|
-
"deployed":
|
|
571
|
-
|
|
572
|
-
"
|
|
573
|
-
|
|
574
|
-
"
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
+ project_result.get("errors", []),
|
|
580
|
-
"target_dir": system_result.get("target_dir")
|
|
581
|
-
or project_result.get("target_dir"),
|
|
610
|
+
"deployed_count": len(deploy_result.get("deployed", []))
|
|
611
|
+
+ len(deploy_result.get("updated", [])),
|
|
612
|
+
"deployed": deploy_result.get("deployed", []),
|
|
613
|
+
"updated": deploy_result.get("updated", []),
|
|
614
|
+
"skipped": deploy_result.get("skipped", []),
|
|
615
|
+
"errors": deploy_result.get("failed", []),
|
|
616
|
+
"target_dir": deploy_result.get("deployment_dir", ""),
|
|
617
|
+
"sync_info": {
|
|
618
|
+
"cached_agents": sync_result.get("agent_count", 0),
|
|
619
|
+
"cache_dir": sync_result.get("cache_dir", ""),
|
|
620
|
+
},
|
|
582
621
|
}
|
|
583
622
|
|
|
584
623
|
output_format = self._get_output_format(args)
|
|
@@ -589,12 +628,15 @@ class AgentsCommand(AgentCommand):
|
|
|
589
628
|
)
|
|
590
629
|
print(formatted)
|
|
591
630
|
|
|
631
|
+
success_count = len(deploy_result["deployed"]) + len(
|
|
632
|
+
deploy_result["updated"]
|
|
633
|
+
)
|
|
592
634
|
return CommandResult.success_result(
|
|
593
|
-
f"Deployed {
|
|
635
|
+
f"Deployed {success_count} agents from cache",
|
|
594
636
|
data={
|
|
595
|
-
"
|
|
596
|
-
"
|
|
597
|
-
"total_deployed":
|
|
637
|
+
"sync_result": sync_result,
|
|
638
|
+
"deploy_result": deploy_result,
|
|
639
|
+
"total_deployed": success_count,
|
|
598
640
|
},
|
|
599
641
|
)
|
|
600
642
|
|
|
@@ -2119,6 +2161,385 @@ class AgentsCommand(AgentCommand):
|
|
|
2119
2161
|
self.logger.error(f"Error in auto-configure: {e}", exc_info=True)
|
|
2120
2162
|
return CommandResult.error_result(f"Error in auto-configure: {e}")
|
|
2121
2163
|
|
|
2164
|
+
def _list_collections(self, args) -> CommandResult:
|
|
2165
|
+
"""List all available agent collections.
|
|
2166
|
+
|
|
2167
|
+
NEW: Shows all collections with agent counts and metadata.
|
|
2168
|
+
Enables discovery of available agent collections before deployment.
|
|
2169
|
+
"""
|
|
2170
|
+
try:
|
|
2171
|
+
from pathlib import Path
|
|
2172
|
+
|
|
2173
|
+
from ...services.agents.deployment.remote_agent_discovery_service import (
|
|
2174
|
+
RemoteAgentDiscoveryService,
|
|
2175
|
+
)
|
|
2176
|
+
|
|
2177
|
+
# Get remote agents cache directory
|
|
2178
|
+
cache_dir = Path.home() / ".claude-mpm" / "cache" / "remote-agents"
|
|
2179
|
+
|
|
2180
|
+
if not cache_dir.exists():
|
|
2181
|
+
return CommandResult.error_result(
|
|
2182
|
+
"No remote agent collections found. Run 'claude-mpm agents deploy' first."
|
|
2183
|
+
)
|
|
2184
|
+
|
|
2185
|
+
# Use RemoteAgentDiscoveryService to list collections
|
|
2186
|
+
remote_service = RemoteAgentDiscoveryService(cache_dir)
|
|
2187
|
+
collections = remote_service.list_collections()
|
|
2188
|
+
|
|
2189
|
+
if not collections:
|
|
2190
|
+
return CommandResult.success_result(
|
|
2191
|
+
"No agent collections found in cache.", data={"collections": []}
|
|
2192
|
+
)
|
|
2193
|
+
|
|
2194
|
+
# Format output
|
|
2195
|
+
output_lines = ["Available Agent Collections:\n"]
|
|
2196
|
+
for collection in collections:
|
|
2197
|
+
output_lines.append(
|
|
2198
|
+
f" • {collection['collection_id']} ({collection['agent_count']} agents)"
|
|
2199
|
+
)
|
|
2200
|
+
|
|
2201
|
+
return CommandResult.success_result(
|
|
2202
|
+
"\n".join(output_lines), data={"collections": collections}
|
|
2203
|
+
)
|
|
2204
|
+
|
|
2205
|
+
except Exception as e:
|
|
2206
|
+
self.logger.error(f"Error listing collections: {e}", exc_info=True)
|
|
2207
|
+
return CommandResult.error_result(f"Error listing collections: {e}")
|
|
2208
|
+
|
|
2209
|
+
def _deploy_collection(self, args) -> CommandResult:
|
|
2210
|
+
"""Deploy all agents from a specific collection.
|
|
2211
|
+
|
|
2212
|
+
NEW: Enables bulk deployment of all agents from a named collection.
|
|
2213
|
+
Useful for deploying entire agent sets at once.
|
|
2214
|
+
"""
|
|
2215
|
+
try:
|
|
2216
|
+
from pathlib import Path
|
|
2217
|
+
|
|
2218
|
+
from ...services.agents.deployment.multi_source_deployment_service import (
|
|
2219
|
+
MultiSourceAgentDeploymentService,
|
|
2220
|
+
)
|
|
2221
|
+
|
|
2222
|
+
collection_id = args.collection_id
|
|
2223
|
+
|
|
2224
|
+
# Get agents from collection
|
|
2225
|
+
service = MultiSourceAgentDeploymentService()
|
|
2226
|
+
cache_dir = Path.home() / ".claude-mpm" / "cache" / "remote-agents"
|
|
2227
|
+
agents = service.get_agents_by_collection(collection_id, cache_dir)
|
|
2228
|
+
|
|
2229
|
+
if not agents:
|
|
2230
|
+
return CommandResult.error_result(
|
|
2231
|
+
f"No agents found in collection '{collection_id}'"
|
|
2232
|
+
)
|
|
2233
|
+
|
|
2234
|
+
# Dry run mode
|
|
2235
|
+
if getattr(args, "dry_run", False):
|
|
2236
|
+
agent_names = [
|
|
2237
|
+
agent.get("metadata", {}).get("name", "Unknown") for agent in agents
|
|
2238
|
+
]
|
|
2239
|
+
output = f"Would deploy {len(agents)} agents from collection '{collection_id}':\n"
|
|
2240
|
+
for name in agent_names:
|
|
2241
|
+
output += f" • {name}\n"
|
|
2242
|
+
return CommandResult.success_result(
|
|
2243
|
+
output,
|
|
2244
|
+
data={"collection_id": collection_id, "agent_count": len(agents)},
|
|
2245
|
+
)
|
|
2246
|
+
|
|
2247
|
+
# Deploy agents
|
|
2248
|
+
# TODO: Implement actual deployment logic using deployment service
|
|
2249
|
+
# For now, show what would be deployed
|
|
2250
|
+
return CommandResult.success_result(
|
|
2251
|
+
f"Deployment of collection '{collection_id}' would deploy {len(agents)} agents.\n"
|
|
2252
|
+
f"(Full deployment implementation pending)",
|
|
2253
|
+
data={
|
|
2254
|
+
"collection_id": collection_id,
|
|
2255
|
+
"agent_count": len(agents),
|
|
2256
|
+
"status": "pending_implementation",
|
|
2257
|
+
},
|
|
2258
|
+
)
|
|
2259
|
+
|
|
2260
|
+
except Exception as e:
|
|
2261
|
+
self.logger.error(f"Error deploying collection: {e}", exc_info=True)
|
|
2262
|
+
return CommandResult.error_result(f"Error deploying collection: {e}")
|
|
2263
|
+
|
|
2264
|
+
def _list_by_collection(self, args) -> CommandResult:
|
|
2265
|
+
"""List agents from a specific collection.
|
|
2266
|
+
|
|
2267
|
+
NEW: Shows detailed information about agents in a collection.
|
|
2268
|
+
Supports multiple output formats (table, json, yaml).
|
|
2269
|
+
"""
|
|
2270
|
+
try:
|
|
2271
|
+
import json as json_lib
|
|
2272
|
+
from pathlib import Path
|
|
2273
|
+
|
|
2274
|
+
from ...services.agents.deployment.multi_source_deployment_service import (
|
|
2275
|
+
MultiSourceAgentDeploymentService,
|
|
2276
|
+
)
|
|
2277
|
+
|
|
2278
|
+
collection_id = args.collection_id
|
|
2279
|
+
output_format = getattr(args, "format", "table")
|
|
2280
|
+
|
|
2281
|
+
# Get agents from collection
|
|
2282
|
+
service = MultiSourceAgentDeploymentService()
|
|
2283
|
+
cache_dir = Path.home() / ".claude-mpm" / "cache" / "remote-agents"
|
|
2284
|
+
agents = service.get_agents_by_collection(collection_id, cache_dir)
|
|
2285
|
+
|
|
2286
|
+
if not agents:
|
|
2287
|
+
return CommandResult.error_result(
|
|
2288
|
+
f"No agents found in collection '{collection_id}'"
|
|
2289
|
+
)
|
|
2290
|
+
|
|
2291
|
+
# Format output based on requested format
|
|
2292
|
+
if output_format == "json":
|
|
2293
|
+
return CommandResult.success_result(
|
|
2294
|
+
json_lib.dumps(agents, indent=2),
|
|
2295
|
+
data={"collection_id": collection_id, "agents": agents},
|
|
2296
|
+
)
|
|
2297
|
+
if output_format == "yaml":
|
|
2298
|
+
try:
|
|
2299
|
+
import yaml
|
|
2300
|
+
|
|
2301
|
+
return CommandResult.success_result(
|
|
2302
|
+
yaml.dump(agents, default_flow_style=False),
|
|
2303
|
+
data={"collection_id": collection_id, "agents": agents},
|
|
2304
|
+
)
|
|
2305
|
+
except ImportError:
|
|
2306
|
+
return CommandResult.error_result(
|
|
2307
|
+
"YAML support not available (install PyYAML)"
|
|
2308
|
+
)
|
|
2309
|
+
|
|
2310
|
+
# Table format (default)
|
|
2311
|
+
output_lines = [f"Agents in collection '{collection_id}':\n"]
|
|
2312
|
+
for agent in agents:
|
|
2313
|
+
metadata = agent.get("metadata", {})
|
|
2314
|
+
name = metadata.get("name", "Unknown")
|
|
2315
|
+
description = metadata.get("description", "No description")
|
|
2316
|
+
version = agent.get("version", "unknown")
|
|
2317
|
+
output_lines.append(f" • {name} (v{version})")
|
|
2318
|
+
output_lines.append(f" {description}\n")
|
|
2319
|
+
|
|
2320
|
+
return CommandResult.success_result(
|
|
2321
|
+
"\n".join(output_lines),
|
|
2322
|
+
data={"collection_id": collection_id, "agent_count": len(agents)},
|
|
2323
|
+
)
|
|
2324
|
+
|
|
2325
|
+
except Exception as e:
|
|
2326
|
+
self.logger.error(f"Error listing collection agents: {e}", exc_info=True)
|
|
2327
|
+
return CommandResult.error_result(f"Error listing collection agents: {e}")
|
|
2328
|
+
|
|
2329
|
+
def _cache_status(self, args) -> CommandResult:
|
|
2330
|
+
"""Show git status of agent cache.
|
|
2331
|
+
|
|
2332
|
+
Displays current branch, uncommitted changes, unpushed commits, and
|
|
2333
|
+
remote URL for the agent cache repository.
|
|
2334
|
+
"""
|
|
2335
|
+
try:
|
|
2336
|
+
from ...services.agents.cache_git_manager import CacheGitManager
|
|
2337
|
+
|
|
2338
|
+
cache_dir = Path.home() / ".claude-mpm" / "cache" / "remote-agents"
|
|
2339
|
+
manager = CacheGitManager(cache_dir)
|
|
2340
|
+
|
|
2341
|
+
if not manager.is_git_repo():
|
|
2342
|
+
print("❌ Cache is not a git repository")
|
|
2343
|
+
print(f"\nCache location: {cache_dir}")
|
|
2344
|
+
print(
|
|
2345
|
+
"\n💡 This is expected if you haven't cloned the agents repository."
|
|
2346
|
+
)
|
|
2347
|
+
print(" The cache will be managed via HTTP sync instead.")
|
|
2348
|
+
return CommandResult.error_result("Cache is not a git repository")
|
|
2349
|
+
|
|
2350
|
+
status = manager.get_status()
|
|
2351
|
+
output_format = self._get_output_format(args)
|
|
2352
|
+
|
|
2353
|
+
if self._is_structured_format(output_format):
|
|
2354
|
+
formatted = (
|
|
2355
|
+
self._formatter.format_as_json(status)
|
|
2356
|
+
if str(output_format).lower() == OutputFormat.JSON
|
|
2357
|
+
else self._formatter.format_as_yaml(status)
|
|
2358
|
+
)
|
|
2359
|
+
print(formatted)
|
|
2360
|
+
return CommandResult.success_result(
|
|
2361
|
+
"Cache status retrieved", data=status
|
|
2362
|
+
)
|
|
2363
|
+
|
|
2364
|
+
# Text output
|
|
2365
|
+
print(f"\n📁 Cache: {manager.repo_path}")
|
|
2366
|
+
print(f"🌿 Branch: {status.get('branch', 'unknown')}")
|
|
2367
|
+
|
|
2368
|
+
if status.get("remote_url"):
|
|
2369
|
+
print(f"🔗 Remote: {status['remote_url']}")
|
|
2370
|
+
|
|
2371
|
+
# Show sync status
|
|
2372
|
+
ahead = status.get("ahead", 0)
|
|
2373
|
+
behind = status.get("behind", 0)
|
|
2374
|
+
|
|
2375
|
+
if ahead > 0:
|
|
2376
|
+
print(f"📤 Ahead of remote: {ahead} commit(s)")
|
|
2377
|
+
if behind > 0:
|
|
2378
|
+
print(f"📥 Behind remote: {behind} commit(s)")
|
|
2379
|
+
|
|
2380
|
+
if ahead == 0 and behind == 0:
|
|
2381
|
+
print("✅ In sync with remote")
|
|
2382
|
+
|
|
2383
|
+
# Show uncommitted changes
|
|
2384
|
+
uncommitted = status.get("uncommitted", [])
|
|
2385
|
+
if uncommitted:
|
|
2386
|
+
print(f"\n⚠️ Uncommitted changes: {len(uncommitted)}")
|
|
2387
|
+
for file in uncommitted[:10]: # Show max 10 files
|
|
2388
|
+
print(f" - {file}")
|
|
2389
|
+
if len(uncommitted) > 10:
|
|
2390
|
+
print(f" ... and {len(uncommitted) - 10} more")
|
|
2391
|
+
else:
|
|
2392
|
+
print("\n✅ No uncommitted changes")
|
|
2393
|
+
|
|
2394
|
+
# Overall status
|
|
2395
|
+
if status.get("is_clean"):
|
|
2396
|
+
print("\n✨ Cache is clean and up-to-date")
|
|
2397
|
+
else:
|
|
2398
|
+
print("\n💡 Run 'claude-mpm agents cache-sync' to sync with remote")
|
|
2399
|
+
|
|
2400
|
+
return CommandResult.success_result("Cache status displayed", data=status)
|
|
2401
|
+
|
|
2402
|
+
except Exception as e:
|
|
2403
|
+
self.logger.error(f"Error getting cache status: {e}", exc_info=True)
|
|
2404
|
+
return CommandResult.error_result(f"Error getting cache status: {e}")
|
|
2405
|
+
|
|
2406
|
+
def _cache_pull(self, args) -> CommandResult:
|
|
2407
|
+
"""Pull latest agents from remote repository."""
|
|
2408
|
+
try:
|
|
2409
|
+
from ...services.agents.cache_git_manager import CacheGitManager
|
|
2410
|
+
|
|
2411
|
+
cache_dir = Path.home() / ".claude-mpm" / "cache" / "remote-agents"
|
|
2412
|
+
manager = CacheGitManager(cache_dir)
|
|
2413
|
+
|
|
2414
|
+
if not manager.is_git_repo():
|
|
2415
|
+
print("❌ Cache is not a git repository")
|
|
2416
|
+
return CommandResult.error_result("Cache is not a git repository")
|
|
2417
|
+
|
|
2418
|
+
branch = getattr(args, "branch", "main")
|
|
2419
|
+
print(f"🔄 Pulling latest changes from {branch}...")
|
|
2420
|
+
|
|
2421
|
+
success, msg = manager.pull_latest(branch)
|
|
2422
|
+
|
|
2423
|
+
if success:
|
|
2424
|
+
print(f"✅ {msg}")
|
|
2425
|
+
return CommandResult.success_result(msg)
|
|
2426
|
+
print(f"❌ {msg}")
|
|
2427
|
+
return CommandResult.error_result(msg)
|
|
2428
|
+
|
|
2429
|
+
except Exception as e:
|
|
2430
|
+
self.logger.error(f"Error pulling cache: {e}", exc_info=True)
|
|
2431
|
+
return CommandResult.error_result(f"Error pulling cache: {e}")
|
|
2432
|
+
|
|
2433
|
+
def _cache_commit(self, args) -> CommandResult:
|
|
2434
|
+
"""Commit changes to cache repository."""
|
|
2435
|
+
try:
|
|
2436
|
+
from ...services.agents.cache_git_manager import CacheGitManager
|
|
2437
|
+
|
|
2438
|
+
cache_dir = Path.home() / ".claude-mpm" / "cache" / "remote-agents"
|
|
2439
|
+
manager = CacheGitManager(cache_dir)
|
|
2440
|
+
|
|
2441
|
+
if not manager.is_git_repo():
|
|
2442
|
+
print("❌ Cache is not a git repository")
|
|
2443
|
+
return CommandResult.error_result("Cache is not a git repository")
|
|
2444
|
+
|
|
2445
|
+
# Get commit message from args
|
|
2446
|
+
message = getattr(args, "message", None)
|
|
2447
|
+
if not message:
|
|
2448
|
+
# Default message
|
|
2449
|
+
message = "feat: update agents from local development"
|
|
2450
|
+
|
|
2451
|
+
print("💾 Committing changes...")
|
|
2452
|
+
success, msg = manager.commit_changes(message)
|
|
2453
|
+
|
|
2454
|
+
if success:
|
|
2455
|
+
print(f"✅ {msg}")
|
|
2456
|
+
print(f"\n💡 Commit message: {message}")
|
|
2457
|
+
return CommandResult.success_result(msg)
|
|
2458
|
+
print(f"❌ {msg}")
|
|
2459
|
+
return CommandResult.error_result(msg)
|
|
2460
|
+
|
|
2461
|
+
except Exception as e:
|
|
2462
|
+
self.logger.error(f"Error committing cache changes: {e}", exc_info=True)
|
|
2463
|
+
return CommandResult.error_result(f"Error committing cache changes: {e}")
|
|
2464
|
+
|
|
2465
|
+
def _cache_push(self, args) -> CommandResult:
|
|
2466
|
+
"""Push local agent changes to remote."""
|
|
2467
|
+
try:
|
|
2468
|
+
from ...services.agents.cache_git_manager import CacheGitManager
|
|
2469
|
+
|
|
2470
|
+
cache_dir = Path.home() / ".claude-mpm" / "cache" / "remote-agents"
|
|
2471
|
+
manager = CacheGitManager(cache_dir)
|
|
2472
|
+
|
|
2473
|
+
if not manager.is_git_repo():
|
|
2474
|
+
print("❌ Cache is not a git repository")
|
|
2475
|
+
return CommandResult.error_result("Cache is not a git repository")
|
|
2476
|
+
|
|
2477
|
+
# Check for uncommitted changes
|
|
2478
|
+
if manager.has_uncommitted_changes():
|
|
2479
|
+
print("⚠️ You have uncommitted changes.")
|
|
2480
|
+
print("\n💡 Commit changes first with:")
|
|
2481
|
+
print(" claude-mpm agents cache-commit --message 'your message'")
|
|
2482
|
+
|
|
2483
|
+
# Ask if user wants to commit first
|
|
2484
|
+
auto_commit = getattr(args, "auto_commit", False)
|
|
2485
|
+
if auto_commit:
|
|
2486
|
+
print("\n📝 Auto-committing changes...")
|
|
2487
|
+
success, msg = manager.commit_changes("feat: update agents")
|
|
2488
|
+
if not success:
|
|
2489
|
+
print(f"❌ Commit failed: {msg}")
|
|
2490
|
+
return CommandResult.error_result(f"Commit failed: {msg}")
|
|
2491
|
+
print(f"✅ {msg}")
|
|
2492
|
+
else:
|
|
2493
|
+
return CommandResult.error_result(
|
|
2494
|
+
"Uncommitted changes detected. Commit first or use --auto-commit"
|
|
2495
|
+
)
|
|
2496
|
+
|
|
2497
|
+
# Push changes
|
|
2498
|
+
branch = getattr(args, "branch", "main")
|
|
2499
|
+
print(f"📤 Pushing changes to {branch}...")
|
|
2500
|
+
|
|
2501
|
+
success, msg = manager.push_changes(branch)
|
|
2502
|
+
|
|
2503
|
+
if success:
|
|
2504
|
+
print(f"✅ {msg}")
|
|
2505
|
+
return CommandResult.success_result(msg)
|
|
2506
|
+
print(f"❌ {msg}")
|
|
2507
|
+
return CommandResult.error_result(msg)
|
|
2508
|
+
|
|
2509
|
+
except Exception as e:
|
|
2510
|
+
self.logger.error(f"Error pushing cache: {e}", exc_info=True)
|
|
2511
|
+
return CommandResult.error_result(f"Error pushing cache: {e}")
|
|
2512
|
+
|
|
2513
|
+
def _cache_sync(self, args) -> CommandResult:
|
|
2514
|
+
"""Full cache sync: pull, commit (if needed), push."""
|
|
2515
|
+
try:
|
|
2516
|
+
from ...services.agents.cache_git_manager import CacheGitManager
|
|
2517
|
+
|
|
2518
|
+
cache_dir = Path.home() / ".claude-mpm" / "cache" / "remote-agents"
|
|
2519
|
+
manager = CacheGitManager(cache_dir)
|
|
2520
|
+
|
|
2521
|
+
if not manager.is_git_repo():
|
|
2522
|
+
print("❌ Cache is not a git repository")
|
|
2523
|
+
return CommandResult.error_result("Cache is not a git repository")
|
|
2524
|
+
|
|
2525
|
+
print("🔄 Syncing cache with remote...\n")
|
|
2526
|
+
|
|
2527
|
+
success, msg = manager.sync_with_remote()
|
|
2528
|
+
|
|
2529
|
+
# Print detailed sync message
|
|
2530
|
+
print(msg)
|
|
2531
|
+
|
|
2532
|
+
if success:
|
|
2533
|
+
print("\n✨ Cache sync complete!")
|
|
2534
|
+
return CommandResult.success_result("Cache synced successfully")
|
|
2535
|
+
|
|
2536
|
+
print("\n❌ Cache sync failed. See details above.")
|
|
2537
|
+
return CommandResult.error_result("Cache sync failed")
|
|
2538
|
+
|
|
2539
|
+
except Exception as e:
|
|
2540
|
+
self.logger.error(f"Error syncing cache: {e}", exc_info=True)
|
|
2541
|
+
return CommandResult.error_result(f"Error syncing cache: {e}")
|
|
2542
|
+
|
|
2122
2543
|
|
|
2123
2544
|
def manage_agents(args):
|
|
2124
2545
|
"""
|