2025-08-14 08:56:04 +05:30
|
|
|
"""
|
|
|
|
|
SuperClaude Update Operation Module
|
|
|
|
|
Refactored from update.py for unified CLI hub
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
import sys
|
|
|
|
|
import time
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
from typing import List, Optional, Dict, Any
|
|
|
|
|
import argparse
|
|
|
|
|
|
2025-08-14 22:03:34 +02:00
|
|
|
from ...core.installer import Installer
|
|
|
|
|
from ...core.registry import ComponentRegistry
|
|
|
|
|
from ...services.settings import SettingsService
|
|
|
|
|
from ...core.validator import Validator
|
|
|
|
|
from ...utils.ui import (
|
2025-08-14 08:56:04 +05:30
|
|
|
display_header, display_info, display_success, display_error,
|
2025-08-15 14:39:27 +02:00
|
|
|
display_warning, Menu, confirm, ProgressBar, Colors, format_size, prompt_api_key
|
2025-08-14 08:56:04 +05:30
|
|
|
)
|
2025-08-15 14:39:27 +02:00
|
|
|
from ...utils.environment import setup_environment_variables
|
2025-08-14 22:03:34 +02:00
|
|
|
from ...utils.logger import get_logger
|
2025-09-05 15:59:09 +00:00
|
|
|
from ... import DEFAULT_INSTALL_DIR, PROJECT_ROOT, DATA_DIR
|
2025-08-14 08:56:04 +05:30
|
|
|
from . import OperationBase
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class UpdateOperation(OperationBase):
|
|
|
|
|
"""Update operation implementation"""
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
super().__init__("update")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def register_parser(subparsers, global_parser=None) -> argparse.ArgumentParser:
|
|
|
|
|
"""Register update CLI arguments"""
|
|
|
|
|
parents = [global_parser] if global_parser else []
|
|
|
|
|
|
|
|
|
|
parser = subparsers.add_parser(
|
|
|
|
|
"update",
|
|
|
|
|
help="Update existing SuperClaude installation",
|
|
|
|
|
description="Update SuperClaude Framework components to latest versions",
|
|
|
|
|
epilog="""
|
|
|
|
|
Examples:
|
|
|
|
|
SuperClaude update # Interactive update
|
|
|
|
|
SuperClaude update --check --verbose # Check for updates (verbose)
|
|
|
|
|
SuperClaude update --components core mcp # Update specific components
|
|
|
|
|
SuperClaude update --backup --force # Create backup before update (forced)
|
|
|
|
|
""",
|
|
|
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
|
|
|
parents=parents
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Update mode options
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"--check",
|
|
|
|
|
action="store_true",
|
|
|
|
|
help="Check for available updates without installing"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"--components",
|
|
|
|
|
type=str,
|
|
|
|
|
nargs="+",
|
|
|
|
|
help="Specific components to update"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Backup options
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"--backup",
|
|
|
|
|
action="store_true",
|
|
|
|
|
help="Create backup before update"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"--no-backup",
|
|
|
|
|
action="store_true",
|
|
|
|
|
help="Skip backup creation"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Update options
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"--reinstall",
|
|
|
|
|
action="store_true",
|
|
|
|
|
help="Reinstall components even if versions match"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return parser
|
|
|
|
|
|
|
|
|
|
def check_installation_exists(install_dir: Path) -> bool:
|
|
|
|
|
"""Check if SuperClaude installation exists"""
|
2025-08-14 22:03:34 +02:00
|
|
|
settings_manager = SettingsService(install_dir)
|
2025-08-14 08:56:04 +05:30
|
|
|
|
|
|
|
|
return settings_manager.check_installation_exists()
|
|
|
|
|
|
|
|
|
|
def get_installed_components(install_dir: Path) -> Dict[str, Dict[str, Any]]:
|
|
|
|
|
"""Get currently installed components and their versions"""
|
|
|
|
|
try:
|
2025-08-14 22:03:34 +02:00
|
|
|
settings_manager = SettingsService(install_dir)
|
2025-08-14 08:56:04 +05:30
|
|
|
return settings_manager.get_installed_components()
|
|
|
|
|
except Exception:
|
|
|
|
|
return {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_available_updates(installed_components: Dict[str, str], registry: ComponentRegistry) -> Dict[str, Dict[str, str]]:
|
|
|
|
|
"""Check for available updates"""
|
|
|
|
|
updates = {}
|
|
|
|
|
|
|
|
|
|
for component_name, current_version in installed_components.items():
|
|
|
|
|
try:
|
|
|
|
|
metadata = registry.get_component_metadata(component_name)
|
|
|
|
|
if metadata:
|
|
|
|
|
available_version = metadata.get("version", "unknown")
|
|
|
|
|
if available_version != current_version:
|
|
|
|
|
updates[component_name] = {
|
|
|
|
|
"current": current_version,
|
|
|
|
|
"available": available_version,
|
|
|
|
|
"description": metadata.get("description", "No description")
|
|
|
|
|
}
|
|
|
|
|
except Exception:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
return updates
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def display_update_check(installed_components: Dict[str, str], available_updates: Dict[str, Dict[str, str]]) -> None:
|
|
|
|
|
"""Display update check results"""
|
|
|
|
|
print(f"\n{Colors.CYAN}{Colors.BRIGHT}Update Check Results{Colors.RESET}")
|
|
|
|
|
print("=" * 50)
|
|
|
|
|
|
|
|
|
|
if not installed_components:
|
|
|
|
|
print(f"{Colors.YELLOW}No SuperClaude installation found{Colors.RESET}")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
print(f"{Colors.BLUE}Currently installed components:{Colors.RESET}")
|
|
|
|
|
for component, version in installed_components.items():
|
|
|
|
|
print(f" {component}: v{version}")
|
|
|
|
|
|
|
|
|
|
if available_updates:
|
|
|
|
|
print(f"\n{Colors.GREEN}Available updates:{Colors.RESET}")
|
|
|
|
|
for component, info in available_updates.items():
|
|
|
|
|
print(f" {component}: v{info['current']} → v{info['available']}")
|
|
|
|
|
print(f" {info['description']}")
|
|
|
|
|
else:
|
|
|
|
|
print(f"\n{Colors.GREEN}All components are up to date{Colors.RESET}")
|
|
|
|
|
|
|
|
|
|
print()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_components_to_update(args: argparse.Namespace, installed_components: Dict[str, str],
|
|
|
|
|
available_updates: Dict[str, Dict[str, str]]) -> Optional[List[str]]:
|
|
|
|
|
"""Determine which components to update"""
|
|
|
|
|
logger = get_logger()
|
|
|
|
|
|
|
|
|
|
# Explicit components specified
|
|
|
|
|
if args.components:
|
|
|
|
|
# Validate that specified components are installed
|
|
|
|
|
invalid_components = [c for c in args.components if c not in installed_components]
|
|
|
|
|
if invalid_components:
|
|
|
|
|
logger.error(f"Components not installed: {invalid_components}")
|
|
|
|
|
return None
|
|
|
|
|
return args.components
|
|
|
|
|
|
|
|
|
|
# If no updates available and not forcing reinstall
|
|
|
|
|
if not available_updates and not args.reinstall:
|
|
|
|
|
logger.info("No updates available")
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
|
|
# Interactive selection
|
|
|
|
|
if available_updates:
|
|
|
|
|
return interactive_update_selection(available_updates, installed_components)
|
|
|
|
|
elif args.reinstall:
|
|
|
|
|
# Reinstall all components
|
|
|
|
|
return list(installed_components.keys())
|
|
|
|
|
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
|
|
|
2025-08-15 14:39:27 +02:00
|
|
|
def collect_api_keys_for_servers(selected_servers: List[str], mcp_instance) -> Dict[str, str]:
|
|
|
|
|
"""
|
|
|
|
|
Collect API keys for servers that require them during update
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
selected_servers: List of selected server keys
|
|
|
|
|
mcp_instance: MCP component instance
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
Dictionary of environment variable names to API key values
|
|
|
|
|
"""
|
|
|
|
|
# Filter servers needing keys
|
|
|
|
|
servers_needing_keys = [
|
|
|
|
|
(server_key, mcp_instance.mcp_servers[server_key])
|
|
|
|
|
for server_key in selected_servers
|
|
|
|
|
if server_key in mcp_instance.mcp_servers and
|
|
|
|
|
mcp_instance.mcp_servers[server_key].get("requires_api_key", False)
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
if not servers_needing_keys:
|
|
|
|
|
return {}
|
|
|
|
|
|
|
|
|
|
# Display API key configuration header
|
Some fixes (#372)
* Fix: Install only selected MCP servers and ensure valid empty backups
This commit addresses two separate issues:
1. **MCP Installation:** The `install` command was installing all MCP servers instead of only the ones selected by the user. The `_install` method in `setup/components/mcp.py` was iterating through all available servers, not the user's selection. This has been fixed to respect the `selected_mcp_servers` configuration. A new test has been added to verify this fix.
2. **Backup Creation:** The `create_backup` method in `setup/core/installer.py` created an invalid `.tar.gz` file when the backup source was empty. This has been fixed to ensure that a valid, empty tar archive is always created. A test was added for this as well.
Co-authored-by: Mithun Gowda B <mithungowda.b7411@gmail.com>
Co-authored-by: Jules <jules-ai-assistant@users.noreply.github.com>
* Fix: Correct installer validation for MCP and MCP Docs components
This commit fixes a validation issue in the installer where it would incorrectly fail after a partial installation of MCP servers.
The `MCPComponent` validation logic was checking for all "required" servers, regardless of whether they were selected by the user. This has been corrected to only validate the servers that were actually installed, by checking against the list of installed servers stored in the metadata. The metadata storage has also been fixed to only record the installed servers.
The `MCPDocsComponent` was failing validation because it was not being registered in the metadata if no documentation files were installed. This has been fixed by ensuring the post-installation hook runs even when no files are copied.
New tests have been added for both components to verify the corrected logic.
Co-authored-by: Mithun Gowda B <mithungowda.b7411@gmail.com>
Co-authored-by: Jules <jules-ai-assistant@users.noreply.github.com>
* Fix: Allow re-installation of components and correct validation logic
This commit fixes a bug that prevented new MCP servers from being installed on subsequent runs of the installer. It also fixes the validation logic that was causing failures after a partial installation.
The key changes are:
1. A new `is_reinstallable` method has been added to the base `Component` class. This allows certain components (like the `mcp` component) to be re-run even if they are already marked as installed.
2. The installer logic has been updated to respect this new method.
3. The `MCPComponent` now correctly stores only the installed servers in the metadata.
4. The validation logic for `MCPComponent` and `MCPDocsComponent` has been corrected to prevent incorrect failures.
New tests have been added to verify all aspects of the new logic.
Co-authored-by: Mithun Gowda B <mithungowda.b7411@gmail.com>
Co-authored-by: Jules <jules-ai-assistant@users.noreply.github.com>
* feat: Display authors in UI header and update author info
This commit implements the user's request to display author names and emails in the UI header of the installer.
The key changes are:
1. The `__email__` field in `SuperClaude/__init__.py` has been updated to include both authors' emails.
2. The `display_header` function in `setup/utils/ui.py` has been modified to read the author and email information and display it.
3. A new test has been added to `tests/test_ui.py` to verify the new UI output.
Co-authored-by: Mithun Gowda B <mithungowda.b7411@gmail.com>
Co-authored-by: Jules <jules-ai-assistant@users.noreply.github.com>
* feat: Version bump to 4.1.0 and various fixes
This commit prepares the project for the v4.1.0 release. It includes a version bump across all relevant files and incorporates several bug fixes and feature enhancements from recent tasks.
Key changes in this release:
- **Version Bump**: The project version has been updated from 4.0.9 to 4.1.0 in all configuration files, documentation, and source code.
- **Installer Fixes**:
- Components can now be marked as `reinstallable`, allowing them to be re-run on subsequent installations. This fixes a bug where new MCP servers could not be added.
- The validation logic for `mcp` and `mcp_docs` components has been corrected to avoid incorrect failures.
- A bug in the backup creation process that created invalid empty archives has been fixed.
- **UI Enhancements**:
- Author names and emails are now displayed in the installer UI header.
- **Metadata Updates**:
- Mithun Gowda B has been added as an author.
- **New Tests**:
- Comprehensive tests have been added for the installer logic, MCP components, and UI changes to ensure correctness and prevent regressions.
Co-authored-by: Mithun Gowda B <mithungowda.b7411@gmail.com>
Co-authored-by: Jules <jules-ai-assistant@users.noreply.github.com>
* fix: Resolve dependencies for partial installs and other fixes
This commit addresses several issues, the main one being a dependency resolution failure during partial installations.
Key changes:
- **Dependency Resolution**: The installer now correctly resolves the full dependency tree when a user requests to install a subset of components. This fixes the "Unknown component: core" error.
- **Component Re-installation**: A new `is_reinstallable` flag allows components like `mcp` to be re-run on subsequent installs, enabling the addition of new servers.
- **Validation Logic**: The validation for `mcp` and `mcp_docs` has been corrected to avoid spurious failures.
- **UI and Metadata**: Author information has been added to the UI header and source files.
- **Version Bump**: The project version has been updated to 4.1.0.
- **Tests**: New tests have been added to cover all the above changes.
Co-authored-by: Mithun Gowda B <mithungowda.b7411@gmail.com>
Co-authored-by: Jules <jules-ai-assistant@users.noreply.github.com>
* fix: Installer fixes and version bump to 4.1.0
This commit includes a collection of fixes for the installer logic, UI enhancements, and a version bump to 4.1.0.
Key changes:
- **Dependency Resolution**: The installer now correctly resolves the full dependency tree for partial installations, fixing the "Unknown component: core" error.
- **Component Re-installation**: A new `is_reinstallable` flag allows components like `mcp` to be re-run to add new servers.
- **MCP Installation**: The non-interactive installation of the `mcp` component now correctly prompts the user to select servers.
- **Validation Logic**: The post-installation validation logic has been corrected to only validate components from the current session and to use the correct list of installed servers.
- **UI & Metadata**: Author information has been added to the UI and source files.
- **Version Bump**: The project version has been updated from 4.0.9 to 4.1.0 across all files.
- **Tests**: New tests have been added to cover all the bug fixes.
* feat: Add --authors flag and multiple installer fixes
This commit introduces the `--authors` flag to display author information and includes a collection of fixes for the installer logic.
Key changes:
- **New Feature**: Added an `--authors` flag that displays the names, emails, and GitHub usernames of the project authors.
- **Dependency Resolution**: Fixed a critical bug where partial installations would fail due to unresolved dependencies.
- **Component Re-installation**: Added a mechanism to allow components to be "reinstallable", fixing an issue that prevented adding new MCP servers on subsequent runs.
- **MCP Installation**: The non-interactive installation of the `mcp` component now correctly prompts for server selection.
- **Validation Logic**: Corrected the post-installation validation to prevent spurious errors.
- **Version Bump**: The project version has been updated to 4.1.0.
- **Metadata**: Author and GitHub information has been added to the source files.
- **UI**: The installer header now displays author information.
- **Tests**: Added new tests for all new features and bug fixes.
* Add Docker support and framework enhancements
- Add serena-docker.json MCP configuration
- Update MCP configs and installer components
- Enhance CLI commands with new functionality
- Add symbols utility for framework operations
- Improve UI and logging components
---------
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: Jules <jules-ai-assistant@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Mithun Gowda B <mithungowda.b7411@gmail.com>
2025-09-19 19:03:50 +05:30
|
|
|
print(f"\n{Colors.CYAN}{Colors.BRIGHT}=== API Key Configuration ==={Colors.RESET}")
|
2025-08-15 14:39:27 +02:00
|
|
|
print(f"{Colors.YELLOW}New MCP servers require API keys for full functionality:{Colors.RESET}\n")
|
|
|
|
|
|
|
|
|
|
collected_keys = {}
|
|
|
|
|
for server_key, server_info in servers_needing_keys:
|
|
|
|
|
api_key_env = server_info.get("api_key_env")
|
|
|
|
|
service_name = server_info["name"]
|
|
|
|
|
|
|
|
|
|
if api_key_env:
|
|
|
|
|
key = prompt_api_key(service_name, api_key_env)
|
|
|
|
|
if key:
|
|
|
|
|
collected_keys[api_key_env] = key
|
|
|
|
|
|
|
|
|
|
return collected_keys
|
|
|
|
|
|
|
|
|
|
|
2025-08-14 08:56:04 +05:30
|
|
|
def interactive_update_selection(available_updates: Dict[str, Dict[str, str]],
|
|
|
|
|
installed_components: Dict[str, str]) -> Optional[List[str]]:
|
|
|
|
|
"""Interactive update selection"""
|
|
|
|
|
if not available_updates:
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
|
|
print(f"\n{Colors.CYAN}Available Updates:{Colors.RESET}")
|
|
|
|
|
|
|
|
|
|
# Create menu options
|
|
|
|
|
update_options = []
|
|
|
|
|
component_names = []
|
|
|
|
|
|
|
|
|
|
for component, info in available_updates.items():
|
|
|
|
|
update_options.append(f"{component}: v{info['current']} → v{info['available']}")
|
|
|
|
|
component_names.append(component)
|
|
|
|
|
|
|
|
|
|
# Add bulk options
|
|
|
|
|
preset_options = [
|
|
|
|
|
"Update All Components",
|
|
|
|
|
"Select Individual Components",
|
|
|
|
|
"Cancel Update"
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
menu = Menu("Select update option:", preset_options)
|
|
|
|
|
choice = menu.display()
|
|
|
|
|
|
|
|
|
|
if choice == -1 or choice == 2: # Cancelled
|
|
|
|
|
return None
|
|
|
|
|
elif choice == 0: # Update all
|
|
|
|
|
return component_names
|
|
|
|
|
elif choice == 1: # Select individual
|
|
|
|
|
component_menu = Menu("Select components to update:", update_options, multi_select=True)
|
|
|
|
|
selections = component_menu.display()
|
|
|
|
|
|
|
|
|
|
if not selections:
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
return [component_names[i] for i in selections]
|
|
|
|
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def display_update_plan(components: List[str], available_updates: Dict[str, Dict[str, str]],
|
|
|
|
|
installed_components: Dict[str, str], install_dir: Path) -> None:
|
|
|
|
|
"""Display update plan"""
|
|
|
|
|
print(f"\n{Colors.CYAN}{Colors.BRIGHT}Update Plan{Colors.RESET}")
|
|
|
|
|
print("=" * 50)
|
|
|
|
|
|
|
|
|
|
print(f"{Colors.BLUE}Installation Directory:{Colors.RESET} {install_dir}")
|
|
|
|
|
print(f"{Colors.BLUE}Components to update:{Colors.RESET}")
|
|
|
|
|
|
|
|
|
|
for i, component_name in enumerate(components, 1):
|
|
|
|
|
if component_name in available_updates:
|
|
|
|
|
info = available_updates[component_name]
|
|
|
|
|
print(f" {i}. {component_name}: v{info['current']} → v{info['available']}")
|
|
|
|
|
else:
|
|
|
|
|
current_version = installed_components.get(component_name, "unknown")
|
|
|
|
|
print(f" {i}. {component_name}: v{current_version} (reinstall)")
|
|
|
|
|
|
|
|
|
|
print()
|
|
|
|
|
|
|
|
|
|
|
2025-09-05 15:59:09 +00:00
|
|
|
def perform_update(components: List[str], args: argparse.Namespace, registry: ComponentRegistry) -> bool:
|
2025-08-14 08:56:04 +05:30
|
|
|
"""Perform the actual update"""
|
|
|
|
|
logger = get_logger()
|
|
|
|
|
start_time = time.time()
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# Create installer
|
|
|
|
|
installer = Installer(args.install_dir, dry_run=args.dry_run)
|
|
|
|
|
|
|
|
|
|
# Create component instances
|
|
|
|
|
component_instances = registry.create_component_instances(components, args.install_dir)
|
|
|
|
|
|
|
|
|
|
if not component_instances:
|
|
|
|
|
logger.error("No valid component instances created")
|
|
|
|
|
return False
|
|
|
|
|
|
2025-08-15 14:39:27 +02:00
|
|
|
# Handle MCP component specially - collect API keys for new servers
|
|
|
|
|
collected_api_keys = {}
|
|
|
|
|
if "mcp" in components and "mcp" in component_instances:
|
|
|
|
|
mcp_instance = component_instances["mcp"]
|
|
|
|
|
if hasattr(mcp_instance, 'mcp_servers'):
|
|
|
|
|
# Get all available MCP servers
|
|
|
|
|
all_server_keys = list(mcp_instance.mcp_servers.keys())
|
|
|
|
|
|
|
|
|
|
# Collect API keys for any servers that require them
|
|
|
|
|
collected_api_keys = collect_api_keys_for_servers(all_server_keys, mcp_instance)
|
|
|
|
|
|
|
|
|
|
# Set up environment variables if any keys were collected
|
|
|
|
|
if collected_api_keys:
|
|
|
|
|
setup_environment_variables(collected_api_keys)
|
|
|
|
|
|
|
|
|
|
# Store keys for MCP component to use during update
|
|
|
|
|
mcp_instance.collected_api_keys = collected_api_keys
|
|
|
|
|
|
|
|
|
|
logger.info(f"Collected {len(collected_api_keys)} API keys for MCP server update")
|
|
|
|
|
|
2025-08-14 08:56:04 +05:30
|
|
|
# Register components with installer
|
|
|
|
|
installer.register_components(list(component_instances.values()))
|
|
|
|
|
|
|
|
|
|
# Setup progress tracking
|
|
|
|
|
progress = ProgressBar(
|
|
|
|
|
total=len(components),
|
|
|
|
|
prefix="Updating: ",
|
|
|
|
|
suffix=""
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Update components
|
|
|
|
|
logger.info(f"Updating {len(components)} components...")
|
|
|
|
|
|
|
|
|
|
# Determine backup strategy
|
|
|
|
|
backup = args.backup or (not args.no_backup and not args.dry_run)
|
|
|
|
|
|
|
|
|
|
config = {
|
|
|
|
|
"force": args.force,
|
|
|
|
|
"backup": backup,
|
|
|
|
|
"dry_run": args.dry_run,
|
2025-08-15 14:39:27 +02:00
|
|
|
"update_mode": True,
|
|
|
|
|
"selected_mcp_servers": list(mcp_instance.mcp_servers.keys()) if "mcp" in component_instances else []
|
2025-08-14 08:56:04 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
success = installer.update_components(components, config)
|
|
|
|
|
|
|
|
|
|
# Update progress
|
|
|
|
|
for i, component_name in enumerate(components):
|
|
|
|
|
if component_name in installer.updated_components:
|
|
|
|
|
progress.update(i + 1, f"Updated {component_name}")
|
|
|
|
|
else:
|
|
|
|
|
progress.update(i + 1, f"Failed {component_name}")
|
|
|
|
|
time.sleep(0.1) # Brief pause for visual effect
|
|
|
|
|
|
|
|
|
|
progress.finish("Update complete")
|
|
|
|
|
|
|
|
|
|
# Show results
|
|
|
|
|
duration = time.time() - start_time
|
|
|
|
|
|
|
|
|
|
if success:
|
|
|
|
|
logger.success(f"Update completed successfully in {duration:.1f} seconds")
|
|
|
|
|
|
|
|
|
|
# Show summary
|
|
|
|
|
summary = installer.get_update_summary()
|
|
|
|
|
if summary.get('updated'):
|
|
|
|
|
logger.info(f"Updated components: {', '.join(summary['updated'])}")
|
|
|
|
|
|
|
|
|
|
if summary.get('backup_path'):
|
|
|
|
|
logger.info(f"Backup created: {summary['backup_path']}")
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
logger.error(f"Update completed with errors in {duration:.1f} seconds")
|
|
|
|
|
|
|
|
|
|
summary = installer.get_update_summary()
|
|
|
|
|
if summary.get('failed'):
|
|
|
|
|
logger.error(f"Failed components: {', '.join(summary['failed'])}")
|
|
|
|
|
|
|
|
|
|
return success
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.exception(f"Unexpected error during update: {e}")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def run(args: argparse.Namespace) -> int:
|
|
|
|
|
"""Execute update operation with parsed arguments"""
|
|
|
|
|
operation = UpdateOperation()
|
|
|
|
|
operation.setup_operation_logging(args)
|
|
|
|
|
logger = get_logger()
|
2025-09-05 15:59:09 +00:00
|
|
|
|
|
|
|
|
from setup.cli.base import __version__
|
|
|
|
|
|
2025-08-14 08:56:04 +05:30
|
|
|
# ✅ Inserted validation code
|
|
|
|
|
expected_home = Path.home().resolve()
|
|
|
|
|
actual_dir = args.install_dir.resolve()
|
|
|
|
|
|
|
|
|
|
if not str(actual_dir).startswith(str(expected_home)):
|
Some fixes (#372)
* Fix: Install only selected MCP servers and ensure valid empty backups
This commit addresses two separate issues:
1. **MCP Installation:** The `install` command was installing all MCP servers instead of only the ones selected by the user. The `_install` method in `setup/components/mcp.py` was iterating through all available servers, not the user's selection. This has been fixed to respect the `selected_mcp_servers` configuration. A new test has been added to verify this fix.
2. **Backup Creation:** The `create_backup` method in `setup/core/installer.py` created an invalid `.tar.gz` file when the backup source was empty. This has been fixed to ensure that a valid, empty tar archive is always created. A test was added for this as well.
Co-authored-by: Mithun Gowda B <mithungowda.b7411@gmail.com>
Co-authored-by: Jules <jules-ai-assistant@users.noreply.github.com>
* Fix: Correct installer validation for MCP and MCP Docs components
This commit fixes a validation issue in the installer where it would incorrectly fail after a partial installation of MCP servers.
The `MCPComponent` validation logic was checking for all "required" servers, regardless of whether they were selected by the user. This has been corrected to only validate the servers that were actually installed, by checking against the list of installed servers stored in the metadata. The metadata storage has also been fixed to only record the installed servers.
The `MCPDocsComponent` was failing validation because it was not being registered in the metadata if no documentation files were installed. This has been fixed by ensuring the post-installation hook runs even when no files are copied.
New tests have been added for both components to verify the corrected logic.
Co-authored-by: Mithun Gowda B <mithungowda.b7411@gmail.com>
Co-authored-by: Jules <jules-ai-assistant@users.noreply.github.com>
* Fix: Allow re-installation of components and correct validation logic
This commit fixes a bug that prevented new MCP servers from being installed on subsequent runs of the installer. It also fixes the validation logic that was causing failures after a partial installation.
The key changes are:
1. A new `is_reinstallable` method has been added to the base `Component` class. This allows certain components (like the `mcp` component) to be re-run even if they are already marked as installed.
2. The installer logic has been updated to respect this new method.
3. The `MCPComponent` now correctly stores only the installed servers in the metadata.
4. The validation logic for `MCPComponent` and `MCPDocsComponent` has been corrected to prevent incorrect failures.
New tests have been added to verify all aspects of the new logic.
Co-authored-by: Mithun Gowda B <mithungowda.b7411@gmail.com>
Co-authored-by: Jules <jules-ai-assistant@users.noreply.github.com>
* feat: Display authors in UI header and update author info
This commit implements the user's request to display author names and emails in the UI header of the installer.
The key changes are:
1. The `__email__` field in `SuperClaude/__init__.py` has been updated to include both authors' emails.
2. The `display_header` function in `setup/utils/ui.py` has been modified to read the author and email information and display it.
3. A new test has been added to `tests/test_ui.py` to verify the new UI output.
Co-authored-by: Mithun Gowda B <mithungowda.b7411@gmail.com>
Co-authored-by: Jules <jules-ai-assistant@users.noreply.github.com>
* feat: Version bump to 4.1.0 and various fixes
This commit prepares the project for the v4.1.0 release. It includes a version bump across all relevant files and incorporates several bug fixes and feature enhancements from recent tasks.
Key changes in this release:
- **Version Bump**: The project version has been updated from 4.0.9 to 4.1.0 in all configuration files, documentation, and source code.
- **Installer Fixes**:
- Components can now be marked as `reinstallable`, allowing them to be re-run on subsequent installations. This fixes a bug where new MCP servers could not be added.
- The validation logic for `mcp` and `mcp_docs` components has been corrected to avoid incorrect failures.
- A bug in the backup creation process that created invalid empty archives has been fixed.
- **UI Enhancements**:
- Author names and emails are now displayed in the installer UI header.
- **Metadata Updates**:
- Mithun Gowda B has been added as an author.
- **New Tests**:
- Comprehensive tests have been added for the installer logic, MCP components, and UI changes to ensure correctness and prevent regressions.
Co-authored-by: Mithun Gowda B <mithungowda.b7411@gmail.com>
Co-authored-by: Jules <jules-ai-assistant@users.noreply.github.com>
* fix: Resolve dependencies for partial installs and other fixes
This commit addresses several issues, the main one being a dependency resolution failure during partial installations.
Key changes:
- **Dependency Resolution**: The installer now correctly resolves the full dependency tree when a user requests to install a subset of components. This fixes the "Unknown component: core" error.
- **Component Re-installation**: A new `is_reinstallable` flag allows components like `mcp` to be re-run on subsequent installs, enabling the addition of new servers.
- **Validation Logic**: The validation for `mcp` and `mcp_docs` has been corrected to avoid spurious failures.
- **UI and Metadata**: Author information has been added to the UI header and source files.
- **Version Bump**: The project version has been updated to 4.1.0.
- **Tests**: New tests have been added to cover all the above changes.
Co-authored-by: Mithun Gowda B <mithungowda.b7411@gmail.com>
Co-authored-by: Jules <jules-ai-assistant@users.noreply.github.com>
* fix: Installer fixes and version bump to 4.1.0
This commit includes a collection of fixes for the installer logic, UI enhancements, and a version bump to 4.1.0.
Key changes:
- **Dependency Resolution**: The installer now correctly resolves the full dependency tree for partial installations, fixing the "Unknown component: core" error.
- **Component Re-installation**: A new `is_reinstallable` flag allows components like `mcp` to be re-run to add new servers.
- **MCP Installation**: The non-interactive installation of the `mcp` component now correctly prompts the user to select servers.
- **Validation Logic**: The post-installation validation logic has been corrected to only validate components from the current session and to use the correct list of installed servers.
- **UI & Metadata**: Author information has been added to the UI and source files.
- **Version Bump**: The project version has been updated from 4.0.9 to 4.1.0 across all files.
- **Tests**: New tests have been added to cover all the bug fixes.
* feat: Add --authors flag and multiple installer fixes
This commit introduces the `--authors` flag to display author information and includes a collection of fixes for the installer logic.
Key changes:
- **New Feature**: Added an `--authors` flag that displays the names, emails, and GitHub usernames of the project authors.
- **Dependency Resolution**: Fixed a critical bug where partial installations would fail due to unresolved dependencies.
- **Component Re-installation**: Added a mechanism to allow components to be "reinstallable", fixing an issue that prevented adding new MCP servers on subsequent runs.
- **MCP Installation**: The non-interactive installation of the `mcp` component now correctly prompts for server selection.
- **Validation Logic**: Corrected the post-installation validation to prevent spurious errors.
- **Version Bump**: The project version has been updated to 4.1.0.
- **Metadata**: Author and GitHub information has been added to the source files.
- **UI**: The installer header now displays author information.
- **Tests**: Added new tests for all new features and bug fixes.
* Add Docker support and framework enhancements
- Add serena-docker.json MCP configuration
- Update MCP configs and installer components
- Enhance CLI commands with new functionality
- Add symbols utility for framework operations
- Improve UI and logging components
---------
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: Jules <jules-ai-assistant@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Mithun Gowda B <mithungowda.b7411@gmail.com>
2025-09-19 19:03:50 +05:30
|
|
|
print(f"\n[x] Installation must be inside your user profile directory.")
|
2025-08-14 08:56:04 +05:30
|
|
|
print(f" Expected prefix: {expected_home}")
|
|
|
|
|
print(f" Provided path: {actual_dir}")
|
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# Validate global arguments
|
|
|
|
|
success, errors = operation.validate_global_args(args)
|
|
|
|
|
if not success:
|
|
|
|
|
for error in errors:
|
|
|
|
|
logger.error(error)
|
|
|
|
|
return 1
|
|
|
|
|
|
|
|
|
|
# Display header
|
|
|
|
|
if not args.quiet:
|
|
|
|
|
display_header(
|
2025-08-23 14:10:11 +02:00
|
|
|
f"SuperClaude Update v{__version__}",
|
2025-08-14 08:56:04 +05:30
|
|
|
"Updating SuperClaude framework components"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Check if SuperClaude is installed
|
|
|
|
|
if not check_installation_exists(args.install_dir):
|
|
|
|
|
logger.error(f"SuperClaude installation not found in {args.install_dir}")
|
|
|
|
|
logger.info("Use 'SuperClaude install' to install SuperClaude first")
|
|
|
|
|
return 1
|
|
|
|
|
|
|
|
|
|
# Create component registry
|
|
|
|
|
logger.info("Checking for available updates...")
|
|
|
|
|
|
|
|
|
|
registry = ComponentRegistry(PROJECT_ROOT / "setup" / "components")
|
|
|
|
|
registry.discover_components()
|
|
|
|
|
|
|
|
|
|
# Get installed components
|
|
|
|
|
installed_components = get_installed_components(args.install_dir)
|
|
|
|
|
if not installed_components:
|
|
|
|
|
logger.error("Could not determine installed components")
|
|
|
|
|
return 1
|
|
|
|
|
|
|
|
|
|
# Check for available updates
|
|
|
|
|
available_updates = get_available_updates(installed_components, registry)
|
|
|
|
|
|
|
|
|
|
# Display update check results
|
|
|
|
|
if not args.quiet:
|
|
|
|
|
display_update_check(installed_components, available_updates)
|
|
|
|
|
|
|
|
|
|
# If only checking for updates, exit here
|
|
|
|
|
if args.check:
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
# Get components to update
|
|
|
|
|
components = get_components_to_update(args, installed_components, available_updates)
|
|
|
|
|
if components is None:
|
|
|
|
|
logger.info("Update cancelled by user")
|
|
|
|
|
return 0
|
|
|
|
|
elif not components:
|
|
|
|
|
logger.info("No components selected for update")
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
# Display update plan
|
|
|
|
|
if not args.quiet:
|
|
|
|
|
display_update_plan(components, available_updates, installed_components, args.install_dir)
|
|
|
|
|
|
|
|
|
|
if not args.dry_run:
|
|
|
|
|
if not args.yes and not confirm("Proceed with update?", default=True):
|
|
|
|
|
logger.info("Update cancelled by user")
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
# Perform update
|
2025-09-05 15:59:09 +00:00
|
|
|
success = perform_update(components, args, registry)
|
2025-08-14 08:56:04 +05:30
|
|
|
|
|
|
|
|
if success:
|
|
|
|
|
if not args.quiet:
|
|
|
|
|
display_success("SuperClaude update completed successfully!")
|
|
|
|
|
|
|
|
|
|
if not args.dry_run:
|
|
|
|
|
print(f"\n{Colors.CYAN}Next steps:{Colors.RESET}")
|
|
|
|
|
print(f"1. Restart your Claude Code session")
|
|
|
|
|
print(f"2. Updated components are now available")
|
|
|
|
|
print(f"3. Check for any breaking changes in documentation")
|
|
|
|
|
|
|
|
|
|
return 0
|
|
|
|
|
else:
|
|
|
|
|
display_error("Update failed. Check logs for details.")
|
|
|
|
|
return 1
|
|
|
|
|
|
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
|
print(f"\n{Colors.YELLOW}Update cancelled by user{Colors.RESET}")
|
|
|
|
|
return 130
|
|
|
|
|
except Exception as e:
|
|
|
|
|
return operation.handle_operation_error("update", e)
|