"""Configuration commands.""" import socket import sys import time from ..config import load_config, save_config, set_registry_token, get_registry_url def cmd_config(args): """Manage CmdForge configuration.""" if args.config_cmd == "show": return _cmd_config_show(args) elif args.config_cmd == "set-token": return _cmd_config_set_token(args) elif args.config_cmd == "set": return _cmd_config_set(args) elif args.config_cmd == "connect": return _cmd_config_connect(args) elif args.config_cmd == "disconnect": return _cmd_config_disconnect(args) else: print("Config commands:") print(" show Show current configuration") print(" connect Connect this app to your CmdForge account") print(" disconnect Disconnect from registry (clear token)") print(" set-token Set registry authentication token") print(" set Set a configuration value") return 0 def _cmd_config_show(args): """Show current configuration.""" config = load_config() print("CmdForge Configuration:") print(f" Registry URL: {config.registry.url}") print(f" Token: {'***' if config.registry.token else '(not set)'}") print(f" Client ID: {config.client_id}") print(f" Auto-fetch: {config.auto_fetch_from_registry}") if config.default_provider: print(f" Default provider: {config.default_provider}") return 0 def _cmd_config_set_token(args): """Set registry authentication token.""" token = args.token set_registry_token(token) print("Registry token saved.") return 0 def _cmd_config_set(args): """Set a configuration value.""" config = load_config() key = args.key value = args.value if key == "auto_fetch": config.auto_fetch_from_registry = value.lower() in ("true", "1", "yes") elif key == "default_provider": config.default_provider = value if value else None elif key == "registry_url": config.registry.url = value else: print(f"Unknown config key: {key}") print("Available keys: auto_fetch, default_provider, registry_url") return 1 save_config(config) print(f"Set {key} = {value}") return 0 def _cmd_config_connect(args): """Connect this app to a CmdForge account via web pairing.""" try: import requests except ImportError: print("Error: requests library required. Install with: pip install requests") return 1 username = args.username hostname = socket.gethostname() registry_url = get_registry_url() # Remove trailing /api/v1 if present to get base URL base_url = registry_url.rstrip("/") if base_url.endswith("/api/v1"): base_url = base_url[:-7] pairing_url = f"{base_url}/api/v1/pairing/check/{username}" print(f"Connecting to CmdForge as @{username}...") print(f"Device: {hostname}") print() print("Waiting for approval from the web interface...") print("Go to https://cmdforge.brrd.tech/dashboard/connected-apps") print("and click 'Connect New App', then 'I've Run the Command'") print() print("Press Ctrl+C to cancel") print() # Poll for pairing status max_attempts = 150 # 5 minutes at 2-second intervals attempt = 0 try: while attempt < max_attempts: attempt += 1 try: response = requests.get( pairing_url, params={"hostname": hostname}, timeout=10 ) if response.status_code == 200: data = response.json() status = data.get("data", {}).get("status") if status == "connected": token = data.get("data", {}).get("token") if token: set_registry_token(token) print("\nConnected successfully!") print(f"Your device '{hostname}' is now linked to @{username}") print("\nYou can now publish tools with: cmdforge registry publish") return 0 else: print("\nError: Pairing completed but no token received") return 1 elif status == "pending": # Still waiting, continue polling pass elif status == "expired": print("\nPairing request expired. Please try again.") return 1 elif status == "not_found": # No pending pairing yet, continue waiting pass else: # Unknown status, keep waiting pass elif response.status_code == 404: # No pairing found yet, keep waiting pass else: # Server error, but keep trying pass except requests.exceptions.RequestException: # Network error, keep trying pass # Show progress indicator dots = "." * ((attempt % 3) + 1) sys.stdout.write(f"\rWaiting{dots} ") sys.stdout.flush() time.sleep(2) print("\n\nTimed out waiting for approval.") print("Please initiate the connection from the web interface first.") return 1 except KeyboardInterrupt: print("\n\nConnection cancelled.") return 1 def _cmd_config_disconnect(args): """Disconnect from registry by clearing the token.""" config = load_config() if not config.registry.token: print("Not connected to registry (no token set).") return 0 # Clear the token set_registry_token(None) print("Disconnected from registry.") print("Token has been cleared from local configuration.") return 0