claude-mpm 4.7.6__py3-none-any.whl → 4.7.8__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/cli/commands/configure.py +360 -76
- {claude_mpm-4.7.6.dist-info → claude_mpm-4.7.8.dist-info}/METADATA +1 -1
- {claude_mpm-4.7.6.dist-info → claude_mpm-4.7.8.dist-info}/RECORD +8 -8
- {claude_mpm-4.7.6.dist-info → claude_mpm-4.7.8.dist-info}/WHEEL +0 -0
- {claude_mpm-4.7.6.dist-info → claude_mpm-4.7.8.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.7.6.dist-info → claude_mpm-4.7.8.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.7.6.dist-info → claude_mpm-4.7.8.dist-info}/top_level.txt +0 -0
claude_mpm/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
4.7.
|
1
|
+
4.7.8
|
@@ -60,6 +60,8 @@ class SimpleAgentManager:
|
|
60
60
|
import logging
|
61
61
|
|
62
62
|
self.logger = logging.getLogger(__name__)
|
63
|
+
# Track pending changes for batch operations
|
64
|
+
self.deferred_changes: Dict[str, bool] = {}
|
63
65
|
|
64
66
|
def _load_states(self):
|
65
67
|
"""Load agent states from file."""
|
@@ -85,6 +87,33 @@ class SimpleAgentManager:
|
|
85
87
|
self.states[agent_name]["enabled"] = enabled
|
86
88
|
self._save_states()
|
87
89
|
|
90
|
+
def set_agent_enabled_deferred(self, agent_name: str, enabled: bool) -> None:
|
91
|
+
"""Queue agent state change without saving."""
|
92
|
+
self.deferred_changes[agent_name] = enabled
|
93
|
+
|
94
|
+
def commit_deferred_changes(self) -> None:
|
95
|
+
"""Save all deferred changes at once."""
|
96
|
+
for agent_name, enabled in self.deferred_changes.items():
|
97
|
+
if agent_name not in self.states:
|
98
|
+
self.states[agent_name] = {}
|
99
|
+
self.states[agent_name]["enabled"] = enabled
|
100
|
+
self._save_states()
|
101
|
+
self.deferred_changes.clear()
|
102
|
+
|
103
|
+
def discard_deferred_changes(self) -> None:
|
104
|
+
"""Discard all pending changes."""
|
105
|
+
self.deferred_changes.clear()
|
106
|
+
|
107
|
+
def get_pending_state(self, agent_name: str) -> bool:
|
108
|
+
"""Get agent state including pending changes."""
|
109
|
+
if agent_name in self.deferred_changes:
|
110
|
+
return self.deferred_changes[agent_name]
|
111
|
+
return self.states.get(agent_name, {}).get("enabled", True)
|
112
|
+
|
113
|
+
def has_pending_changes(self) -> bool:
|
114
|
+
"""Check if there are unsaved changes."""
|
115
|
+
return len(self.deferred_changes) > 0
|
116
|
+
|
88
117
|
def discover_agents(self) -> List[AgentConfig]:
|
89
118
|
"""Discover available agents from template JSON files."""
|
90
119
|
agents = []
|
@@ -296,6 +325,33 @@ class ConfigureCommand(BaseCommand):
|
|
296
325
|
self._switch_scope()
|
297
326
|
elif choice == "6":
|
298
327
|
self._show_version_info_interactive()
|
328
|
+
elif choice == "l":
|
329
|
+
# Check for pending agent changes
|
330
|
+
if self.agent_manager and self.agent_manager.has_pending_changes():
|
331
|
+
should_save = Confirm.ask(
|
332
|
+
"[yellow]You have unsaved agent changes. Save them before launching?[/yellow]",
|
333
|
+
default=True,
|
334
|
+
)
|
335
|
+
if should_save:
|
336
|
+
self.agent_manager.commit_deferred_changes()
|
337
|
+
self.console.print("[green]✓ Agent changes saved[/green]")
|
338
|
+
else:
|
339
|
+
self.agent_manager.discard_deferred_changes()
|
340
|
+
self.console.print(
|
341
|
+
"[yellow]⚠ Agent changes discarded[/yellow]"
|
342
|
+
)
|
343
|
+
|
344
|
+
# Save all configuration
|
345
|
+
self.console.print("\n[cyan]Saving configuration...[/cyan]")
|
346
|
+
if self._save_all_configuration():
|
347
|
+
# Launch Claude MPM (this will replace the process if successful)
|
348
|
+
self._launch_claude_mpm()
|
349
|
+
# If execvp fails, we'll return here and break
|
350
|
+
break
|
351
|
+
self.console.print(
|
352
|
+
"[red]✗ Failed to save configuration. Not launching.[/red]"
|
353
|
+
)
|
354
|
+
Prompt.ask("\nPress Enter to continue")
|
299
355
|
elif choice == "q":
|
300
356
|
self.console.print(
|
301
357
|
"\n[green]Configuration complete. Goodbye![/green]"
|
@@ -356,16 +412,17 @@ class ConfigureCommand(BaseCommand):
|
|
356
412
|
),
|
357
413
|
("5", "Switch Scope", f"Current: {self.current_scope}"),
|
358
414
|
("6", "Version Info", "Display MPM and Claude versions"),
|
359
|
-
("
|
415
|
+
("l", "Save & Launch", "Save all changes and start Claude MPM"),
|
416
|
+
("q", "Quit", "Exit without launching"),
|
360
417
|
]
|
361
418
|
|
362
419
|
table = Table(show_header=False, box=None, padding=(0, 2))
|
363
|
-
table.add_column("Key", style="cyan", width=
|
364
|
-
table.add_column("Option", style="bold white", width=
|
365
|
-
table.add_column("Description", style="
|
420
|
+
table.add_column("Key", style="cyan bold", width=4) # Bolder shortcuts
|
421
|
+
table.add_column("Option", style="bold white", width=24) # Wider for titles
|
422
|
+
table.add_column("Description", style="white") # Better contrast
|
366
423
|
|
367
424
|
for key, option, desc in menu_items:
|
368
|
-
table.add_row(f"[{key}]", option, desc)
|
425
|
+
table.add_row(f"\\[{key}]", option, desc)
|
369
426
|
|
370
427
|
menu_panel = Panel(
|
371
428
|
table, title="[bold]Main Menu[/bold]", box=ROUNDED, style="green"
|
@@ -390,22 +447,41 @@ class ConfigureCommand(BaseCommand):
|
|
390
447
|
|
391
448
|
# Show agent menu
|
392
449
|
self.console.print("\n[bold]Agent Management Options:[/bold]")
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
self.console.print(
|
450
|
+
|
451
|
+
# Use Text objects to properly display shortcuts with styling
|
452
|
+
text_t = Text(" ")
|
453
|
+
text_t.append("[t]", style="cyan bold")
|
454
|
+
text_t.append(" Toggle agents (enable/disable multiple)")
|
455
|
+
self.console.print(text_t)
|
456
|
+
|
457
|
+
text_c = Text(" ")
|
458
|
+
text_c.append("[c]", style="cyan bold")
|
459
|
+
text_c.append(" Customize agent template")
|
460
|
+
self.console.print(text_c)
|
461
|
+
|
462
|
+
text_v = Text(" ")
|
463
|
+
text_v.append("[v]", style="cyan bold")
|
464
|
+
text_v.append(" View agent details")
|
465
|
+
self.console.print(text_v)
|
466
|
+
|
467
|
+
text_r = Text(" ")
|
468
|
+
text_r.append("[r]", style="cyan bold")
|
469
|
+
text_r.append(" Reset agent to defaults")
|
470
|
+
self.console.print(text_r)
|
471
|
+
|
472
|
+
text_b = Text(" ")
|
473
|
+
text_b.append("[b]", style="cyan bold")
|
474
|
+
text_b.append(" Back to main menu")
|
475
|
+
self.console.print(text_b)
|
476
|
+
|
399
477
|
self.console.print()
|
400
478
|
|
401
479
|
choice = Prompt.ask("[bold cyan]Select an option[/bold cyan]", default="b")
|
402
480
|
|
403
481
|
if choice == "b":
|
404
482
|
break
|
405
|
-
if choice == "
|
406
|
-
self.
|
407
|
-
elif choice == "d":
|
408
|
-
self._disable_agent_interactive(agents)
|
483
|
+
if choice == "t":
|
484
|
+
self._toggle_agents_interactive(agents)
|
409
485
|
elif choice == "c":
|
410
486
|
self._customize_agent_template(agents)
|
411
487
|
elif choice == "v":
|
@@ -468,55 +544,127 @@ class ConfigureCommand(BaseCommand):
|
|
468
544
|
|
469
545
|
self.console.print(table)
|
470
546
|
|
471
|
-
def
|
472
|
-
"""
|
473
|
-
|
547
|
+
def _display_agents_with_pending_states(self, agents: List[AgentConfig]) -> None:
|
548
|
+
"""Display agents table with pending state indicators."""
|
549
|
+
has_pending = self.agent_manager.has_pending_changes()
|
550
|
+
pending_count = len(self.agent_manager.deferred_changes) if has_pending else 0
|
474
551
|
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
self.agent_manager.set_agent_enabled(agent.name, True)
|
479
|
-
self.console.print("[green]All agents enabled successfully![/green]")
|
480
|
-
else:
|
481
|
-
try:
|
482
|
-
idx = int(agent_id) - 1
|
483
|
-
if 0 <= idx < len(agents):
|
484
|
-
agent = agents[idx]
|
485
|
-
self.agent_manager.set_agent_enabled(agent.name, True)
|
486
|
-
self.console.print(
|
487
|
-
f"[green]Agent '{agent.name}' enabled successfully![/green]"
|
488
|
-
)
|
489
|
-
else:
|
490
|
-
self.console.print("[red]Invalid agent ID.[/red]")
|
491
|
-
except ValueError:
|
492
|
-
self.console.print("[red]Invalid input. Please enter a number.[/red]")
|
552
|
+
title = f"Available Agents ({len(agents)} total)"
|
553
|
+
if has_pending:
|
554
|
+
title += f" [yellow]({pending_count} change{'s' if pending_count != 1 else ''} pending)[/yellow]"
|
493
555
|
|
494
|
-
|
556
|
+
table = Table(title=title, box=ROUNDED, show_lines=True, expand=True)
|
557
|
+
table.add_column("ID", justify="right", style="cyan", width=5)
|
558
|
+
table.add_column("Name", style="bold", width=22)
|
559
|
+
table.add_column("Status", width=20)
|
560
|
+
table.add_column("Description", style="bold cyan", width=45)
|
495
561
|
|
496
|
-
|
497
|
-
|
498
|
-
|
562
|
+
for idx, agent in enumerate(agents, 1):
|
563
|
+
current_state = self.agent_manager.is_agent_enabled(agent.name)
|
564
|
+
pending_state = self.agent_manager.get_pending_state(agent.name)
|
499
565
|
|
500
|
-
|
501
|
-
if
|
502
|
-
|
503
|
-
|
504
|
-
self.console.print("[green]All agents disabled successfully![/green]")
|
505
|
-
else:
|
506
|
-
try:
|
507
|
-
idx = int(agent_id) - 1
|
508
|
-
if 0 <= idx < len(agents):
|
509
|
-
agent = agents[idx]
|
510
|
-
self.agent_manager.set_agent_enabled(agent.name, False)
|
511
|
-
self.console.print(
|
512
|
-
f"[green]Agent '{agent.name}' disabled successfully![/green]"
|
513
|
-
)
|
566
|
+
# Show pending status with arrow
|
567
|
+
if current_state != pending_state:
|
568
|
+
if pending_state:
|
569
|
+
status = "[yellow]✗ Disabled → ✓ Enabled[/yellow]"
|
514
570
|
else:
|
515
|
-
|
516
|
-
|
517
|
-
|
571
|
+
status = "[yellow]✓ Enabled → ✗ Disabled[/yellow]"
|
572
|
+
else:
|
573
|
+
status = (
|
574
|
+
"[green]✓ Enabled[/green]"
|
575
|
+
if current_state
|
576
|
+
else "[dim]✗ Disabled[/dim]"
|
577
|
+
)
|
518
578
|
|
519
|
-
|
579
|
+
desc_display = Text()
|
580
|
+
desc_display.append(
|
581
|
+
(
|
582
|
+
agent.description[:42] + "..."
|
583
|
+
if len(agent.description) > 42
|
584
|
+
else agent.description
|
585
|
+
),
|
586
|
+
style="cyan",
|
587
|
+
)
|
588
|
+
|
589
|
+
table.add_row(str(idx), agent.name, status, desc_display)
|
590
|
+
|
591
|
+
self.console.print(table)
|
592
|
+
|
593
|
+
def _toggle_agents_interactive(self, agents: List[AgentConfig]) -> None:
|
594
|
+
"""Interactive multi-agent enable/disable with batch save."""
|
595
|
+
|
596
|
+
# Initialize pending states from current states
|
597
|
+
for agent in agents:
|
598
|
+
current_state = self.agent_manager.is_agent_enabled(agent.name)
|
599
|
+
self.agent_manager.set_agent_enabled_deferred(agent.name, current_state)
|
600
|
+
|
601
|
+
while True:
|
602
|
+
# Display table with pending states
|
603
|
+
self._display_agents_with_pending_states(agents)
|
604
|
+
|
605
|
+
# Show menu
|
606
|
+
self.console.print("\n[bold]Toggle Agent Status:[/bold]")
|
607
|
+
text_toggle = Text(" ")
|
608
|
+
text_toggle.append("[t]", style="cyan bold")
|
609
|
+
text_toggle.append(" Enter agent IDs to toggle (e.g., '1,3,5' or '1-4')")
|
610
|
+
self.console.print(text_toggle)
|
611
|
+
|
612
|
+
text_all = Text(" ")
|
613
|
+
text_all.append("[a]", style="cyan bold")
|
614
|
+
text_all.append(" Enable all agents")
|
615
|
+
self.console.print(text_all)
|
616
|
+
|
617
|
+
text_none = Text(" ")
|
618
|
+
text_none.append("[n]", style="cyan bold")
|
619
|
+
text_none.append(" Disable all agents")
|
620
|
+
self.console.print(text_none)
|
621
|
+
|
622
|
+
text_save = Text(" ")
|
623
|
+
text_save.append("[s]", style="green bold")
|
624
|
+
text_save.append(" Save changes and return")
|
625
|
+
self.console.print(text_save)
|
626
|
+
|
627
|
+
text_cancel = Text(" ")
|
628
|
+
text_cancel.append("[c]", style="yellow bold")
|
629
|
+
text_cancel.append(" Cancel (discard changes)")
|
630
|
+
self.console.print(text_cancel)
|
631
|
+
|
632
|
+
choice = (
|
633
|
+
Prompt.ask("[bold cyan]Select an option[/bold cyan]", default="s")
|
634
|
+
.strip()
|
635
|
+
.lower()
|
636
|
+
)
|
637
|
+
|
638
|
+
if choice == "s":
|
639
|
+
if self.agent_manager.has_pending_changes():
|
640
|
+
self.agent_manager.commit_deferred_changes()
|
641
|
+
self.console.print("[green]✓ Changes saved successfully![/green]")
|
642
|
+
else:
|
643
|
+
self.console.print("[yellow]No changes to save.[/yellow]")
|
644
|
+
Prompt.ask("Press Enter to continue")
|
645
|
+
break
|
646
|
+
if choice == "c":
|
647
|
+
self.agent_manager.discard_deferred_changes()
|
648
|
+
self.console.print("[yellow]Changes discarded.[/yellow]")
|
649
|
+
Prompt.ask("Press Enter to continue")
|
650
|
+
break
|
651
|
+
if choice == "a":
|
652
|
+
for agent in agents:
|
653
|
+
self.agent_manager.set_agent_enabled_deferred(agent.name, True)
|
654
|
+
elif choice == "n":
|
655
|
+
for agent in agents:
|
656
|
+
self.agent_manager.set_agent_enabled_deferred(agent.name, False)
|
657
|
+
elif choice == "t" or choice.replace(",", "").replace("-", "").isdigit():
|
658
|
+
selected_ids = self._parse_id_selection(
|
659
|
+
choice if choice != "t" else Prompt.ask("Enter IDs"), len(agents)
|
660
|
+
)
|
661
|
+
for idx in selected_ids:
|
662
|
+
if 1 <= idx <= len(agents):
|
663
|
+
agent = agents[idx - 1]
|
664
|
+
current = self.agent_manager.get_pending_state(agent.name)
|
665
|
+
self.agent_manager.set_agent_enabled_deferred(
|
666
|
+
agent.name, not current
|
667
|
+
)
|
520
668
|
|
521
669
|
def _customize_agent_template(self, agents: List[AgentConfig]) -> None:
|
522
670
|
"""Customize agent JSON template."""
|
@@ -613,14 +761,41 @@ class ConfigureCommand(BaseCommand):
|
|
613
761
|
# Editing options
|
614
762
|
self.console.print("[bold]Editing Options:[/bold]")
|
615
763
|
if not is_system:
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
self.console.print(
|
764
|
+
text_1 = Text(" ")
|
765
|
+
text_1.append("[1]", style="cyan bold")
|
766
|
+
text_1.append(" Edit in external editor")
|
767
|
+
self.console.print(text_1)
|
768
|
+
|
769
|
+
text_2 = Text(" ")
|
770
|
+
text_2.append("[2]", style="cyan bold")
|
771
|
+
text_2.append(" Add/modify a field")
|
772
|
+
self.console.print(text_2)
|
773
|
+
|
774
|
+
text_3 = Text(" ")
|
775
|
+
text_3.append("[3]", style="cyan bold")
|
776
|
+
text_3.append(" Remove a field")
|
777
|
+
self.console.print(text_3)
|
778
|
+
|
779
|
+
text_4 = Text(" ")
|
780
|
+
text_4.append("[4]", style="cyan bold")
|
781
|
+
text_4.append(" Reset to defaults")
|
782
|
+
self.console.print(text_4)
|
620
783
|
else:
|
621
|
-
|
622
|
-
|
623
|
-
|
784
|
+
text_1 = Text(" ")
|
785
|
+
text_1.append("[1]", style="cyan bold")
|
786
|
+
text_1.append(" Create customized copy")
|
787
|
+
self.console.print(text_1)
|
788
|
+
|
789
|
+
text_2 = Text(" ")
|
790
|
+
text_2.append("[2]", style="cyan bold")
|
791
|
+
text_2.append(" View full template")
|
792
|
+
self.console.print(text_2)
|
793
|
+
|
794
|
+
text_b = Text(" ")
|
795
|
+
text_b.append("[b]", style="cyan bold")
|
796
|
+
text_b.append(" Back")
|
797
|
+
self.console.print(text_b)
|
798
|
+
|
624
799
|
self.console.print()
|
625
800
|
|
626
801
|
choice = Prompt.ask("[bold cyan]Select an option[/bold cyan]", default="b")
|
@@ -973,11 +1148,32 @@ class ConfigureCommand(BaseCommand):
|
|
973
1148
|
|
974
1149
|
# Show behavior menu
|
975
1150
|
self.console.print("\n[bold]Options:[/bold]")
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
self.console.print(
|
1151
|
+
|
1152
|
+
text_1 = Text(" ")
|
1153
|
+
text_1.append("[1]", style="cyan bold")
|
1154
|
+
text_1.append(" Edit identity configuration")
|
1155
|
+
self.console.print(text_1)
|
1156
|
+
|
1157
|
+
text_2 = Text(" ")
|
1158
|
+
text_2.append("[2]", style="cyan bold")
|
1159
|
+
text_2.append(" Edit workflow configuration")
|
1160
|
+
self.console.print(text_2)
|
1161
|
+
|
1162
|
+
text_3 = Text(" ")
|
1163
|
+
text_3.append("[3]", style="cyan bold")
|
1164
|
+
text_3.append(" Import behavior file")
|
1165
|
+
self.console.print(text_3)
|
1166
|
+
|
1167
|
+
text_4 = Text(" ")
|
1168
|
+
text_4.append("[4]", style="cyan bold")
|
1169
|
+
text_4.append(" Export behavior file")
|
1170
|
+
self.console.print(text_4)
|
1171
|
+
|
1172
|
+
text_b = Text(" ")
|
1173
|
+
text_b.append("[b]", style="cyan bold")
|
1174
|
+
text_b.append(" Back to main menu")
|
1175
|
+
self.console.print(text_b)
|
1176
|
+
|
981
1177
|
self.console.print()
|
982
1178
|
|
983
1179
|
choice = Prompt.ask("[bold cyan]Select an option[/bold cyan]", default="b")
|
@@ -1264,9 +1460,22 @@ class ConfigureCommand(BaseCommand):
|
|
1264
1460
|
self.console.print(table)
|
1265
1461
|
self.console.print("\n[bold]Commands:[/bold]")
|
1266
1462
|
self.console.print(" Enter service IDs to toggle (e.g., '1,3' or '1-4')")
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1463
|
+
|
1464
|
+
text_a = Text(" ")
|
1465
|
+
text_a.append("[a]", style="cyan bold")
|
1466
|
+
text_a.append(" Enable all")
|
1467
|
+
self.console.print(text_a)
|
1468
|
+
|
1469
|
+
text_n = Text(" ")
|
1470
|
+
text_n.append("[n]", style="cyan bold")
|
1471
|
+
text_n.append(" Disable all")
|
1472
|
+
self.console.print(text_n)
|
1473
|
+
|
1474
|
+
text_b = Text(" ")
|
1475
|
+
text_b.append("[b]", style="cyan bold")
|
1476
|
+
text_b.append(" Back to previous menu")
|
1477
|
+
self.console.print(text_b)
|
1478
|
+
|
1270
1479
|
self.console.print()
|
1271
1480
|
|
1272
1481
|
choice = Prompt.ask("[bold cyan]Toggle services[/bold cyan]", default="b")
|
@@ -1331,9 +1540,22 @@ class ConfigureCommand(BaseCommand):
|
|
1331
1540
|
self.console.print(table)
|
1332
1541
|
self.console.print("\n[bold]Commands:[/bold]")
|
1333
1542
|
self.console.print(" Enter service IDs to toggle (e.g., '1,3' or '1-4')")
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1543
|
+
|
1544
|
+
text_a = Text(" ")
|
1545
|
+
text_a.append("[a]", style="cyan bold")
|
1546
|
+
text_a.append(" Enable all")
|
1547
|
+
self.console.print(text_a)
|
1548
|
+
|
1549
|
+
text_n = Text(" ")
|
1550
|
+
text_n.append("[n]", style="cyan bold")
|
1551
|
+
text_n.append(" Disable all")
|
1552
|
+
self.console.print(text_n)
|
1553
|
+
|
1554
|
+
text_b = Text(" ")
|
1555
|
+
text_b.append("[b]", style="cyan bold")
|
1556
|
+
text_b.append(" Back to previous menu")
|
1557
|
+
self.console.print(text_b)
|
1558
|
+
|
1337
1559
|
self.console.print()
|
1338
1560
|
|
1339
1561
|
choice = Prompt.ask("[bold cyan]Toggle services[/bold cyan]", default="b")
|
@@ -1607,6 +1829,68 @@ class ConfigureCommand(BaseCommand):
|
|
1607
1829
|
Prompt.ask("Press Enter to continue")
|
1608
1830
|
return False
|
1609
1831
|
|
1832
|
+
def _save_all_configuration(self) -> bool:
|
1833
|
+
"""Save all configuration changes across all contexts.
|
1834
|
+
|
1835
|
+
Returns:
|
1836
|
+
bool: True if all saves successful, False otherwise
|
1837
|
+
"""
|
1838
|
+
try:
|
1839
|
+
# 1. Save any pending agent changes
|
1840
|
+
if self.agent_manager and self.agent_manager.has_pending_changes():
|
1841
|
+
self.agent_manager.commit_deferred_changes()
|
1842
|
+
self.console.print("[green]✓ Agent changes saved[/green]")
|
1843
|
+
|
1844
|
+
# 2. Save configuration file
|
1845
|
+
config = Config()
|
1846
|
+
|
1847
|
+
# Determine config file path based on scope
|
1848
|
+
if self.current_scope == "project":
|
1849
|
+
config_file = self.project_dir / ".claude-mpm" / "configuration.yaml"
|
1850
|
+
else:
|
1851
|
+
config_file = Path.home() / ".claude-mpm" / "configuration.yaml"
|
1852
|
+
|
1853
|
+
config_file.parent.mkdir(parents=True, exist_ok=True)
|
1854
|
+
|
1855
|
+
# Save with suppressed logging to avoid duplicate messages
|
1856
|
+
import logging
|
1857
|
+
|
1858
|
+
root_logger = logging.getLogger("claude_mpm")
|
1859
|
+
original_level = root_logger.level
|
1860
|
+
root_logger.setLevel(logging.WARNING)
|
1861
|
+
|
1862
|
+
try:
|
1863
|
+
config.save(config_file, format="yaml")
|
1864
|
+
finally:
|
1865
|
+
root_logger.setLevel(original_level)
|
1866
|
+
|
1867
|
+
self.console.print(f"[green]✓ Configuration saved to {config_file}[/green]")
|
1868
|
+
return True
|
1869
|
+
|
1870
|
+
except Exception as e:
|
1871
|
+
self.console.print(f"[red]✗ Error saving configuration: {e}[/red]")
|
1872
|
+
import traceback
|
1873
|
+
|
1874
|
+
traceback.print_exc()
|
1875
|
+
return False
|
1876
|
+
|
1877
|
+
def _launch_claude_mpm(self) -> None:
|
1878
|
+
"""Launch Claude MPM run command, replacing current process."""
|
1879
|
+
self.console.print("\n[bold cyan]═══ Launching Claude MPM ═══[/bold cyan]\n")
|
1880
|
+
|
1881
|
+
try:
|
1882
|
+
# Use execvp to replace the current process with claude-mpm run
|
1883
|
+
# This ensures a clean transition from configurator to Claude MPM
|
1884
|
+
os.execvp("claude-mpm", ["claude-mpm", "run"])
|
1885
|
+
except Exception as e:
|
1886
|
+
self.console.print(
|
1887
|
+
f"[yellow]⚠ Could not launch Claude MPM automatically: {e}[/yellow]"
|
1888
|
+
)
|
1889
|
+
self.console.print(
|
1890
|
+
"[cyan]→ Please run 'claude-mpm run' manually to start.[/cyan]"
|
1891
|
+
)
|
1892
|
+
Prompt.ask("\nPress Enter to exit")
|
1893
|
+
|
1610
1894
|
def _switch_scope(self) -> None:
|
1611
1895
|
"""Switch between project and user scope."""
|
1612
1896
|
self.current_scope = "user" if self.current_scope == "project" else "project"
|
@@ -1,5 +1,5 @@
|
|
1
1
|
claude_mpm/BUILD_NUMBER,sha256=9JfxhnDtr-8l3kCP2U5TVXSErptHoga8m7XA8zqgGOc,4
|
2
|
-
claude_mpm/VERSION,sha256=
|
2
|
+
claude_mpm/VERSION,sha256=XWuLX-eNJrJGfyBd1GUrzseop7w6skHL0X8KHS__eFE,6
|
3
3
|
claude_mpm/__init__.py,sha256=UCw6j9e_tZQ3kJtTqmdfNv7MHyw9nD1jkj80WurwM2g,2064
|
4
4
|
claude_mpm/__main__.py,sha256=Ro5UBWBoQaSAIoSqWAr7zkbLyvi4sSy28WShqAhKJG0,723
|
5
5
|
claude_mpm/constants.py,sha256=cChN3myrAcF3jC-6DvHnBFTEnwlDk-TAsIXPvUZr_yw,5953
|
@@ -79,7 +79,7 @@ claude_mpm/cli/commands/analyze_code.py,sha256=yWZpG0aL4XlhcthtvbUqnFSlnvvseWO3V
|
|
79
79
|
claude_mpm/cli/commands/cleanup.py,sha256=TukZoPVfAFSF4ICfKCQUibczDE73EJP8nbEbfuT8GhE,19768
|
80
80
|
claude_mpm/cli/commands/cleanup_orphaned_agents.py,sha256=JR8crvgrz7Sa6d-SI-gKywok5S9rwc_DzDVk_h85sVs,4467
|
81
81
|
claude_mpm/cli/commands/config.py,sha256=Yfi8WO-10_MYz2QipFw-yEzVvHKNQ6iSQXeyW5J85Cg,18559
|
82
|
-
claude_mpm/cli/commands/configure.py,sha256=
|
82
|
+
claude_mpm/cli/commands/configure.py,sha256=rj8IEAyI-TgRAnTxtOJ8AL2xGhP33gOte8z8WzKhsG4,92942
|
83
83
|
claude_mpm/cli/commands/dashboard.py,sha256=4jPTmTl97DRNNJlYREWeE1iDdkct1uL-vv24MZn9fj4,11403
|
84
84
|
claude_mpm/cli/commands/debug.py,sha256=YCfJ3aYf6hOCvLW_grdfINdEqI4RXVS28VJ7tkZBFS8,47115
|
85
85
|
claude_mpm/cli/commands/doctor.py,sha256=nNKLZG3Qv_UsHNgrmetrWKgS7Pe2Jn5vq5aXyl60wKQ,7310
|
@@ -786,9 +786,9 @@ claude_mpm/utils/subprocess_utils.py,sha256=D0izRT8anjiUb_JG72zlJR_JAw1cDkb7kalN
|
|
786
786
|
claude_mpm/validation/__init__.py,sha256=YZhwE3mhit-lslvRLuwfX82xJ_k4haZeKmh4IWaVwtk,156
|
787
787
|
claude_mpm/validation/agent_validator.py,sha256=GprtAvu80VyMXcKGsK_VhYiXWA6BjKHv7O6HKx0AB9w,20917
|
788
788
|
claude_mpm/validation/frontmatter_validator.py,sha256=YpJlYNNYcV8u6hIOi3_jaRsDnzhbcQpjCBE6eyBKaFY,7076
|
789
|
-
claude_mpm-4.7.
|
790
|
-
claude_mpm-4.7.
|
791
|
-
claude_mpm-4.7.
|
792
|
-
claude_mpm-4.7.
|
793
|
-
claude_mpm-4.7.
|
794
|
-
claude_mpm-4.7.
|
789
|
+
claude_mpm-4.7.8.dist-info/licenses/LICENSE,sha256=lpaivOlPuBZW1ds05uQLJJswy8Rp_HMNieJEbFlqvLk,1072
|
790
|
+
claude_mpm-4.7.8.dist-info/METADATA,sha256=0zNQ_GqGZeqiE8cxEiJK7LQNZ6gfeuJyvsVrunOlrEE,17517
|
791
|
+
claude_mpm-4.7.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
792
|
+
claude_mpm-4.7.8.dist-info/entry_points.txt,sha256=Vlw3GNi-OtTpKSrez04iNrPmxNxYDpIWxmJCxiZ5Tx8,526
|
793
|
+
claude_mpm-4.7.8.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
|
794
|
+
claude_mpm-4.7.8.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|