from __future__ import annotations import argparse import ctypes import os import shutil import sys from pathlib import Path from PySide6.QtCore import QTimer from PySide6.QtGui import QIcon from PySide6.QtWidgets import QApplication from adam.app import build_application WINDOWS_APP_ID = "ADAM.Desktop.Orchestrator" def application_paths() -> tuple[Path, Path]: """Return the writable app folder and bundled read-only resource folder.""" source_root = Path(__file__).resolve().parent if getattr(sys, "frozen", False): return Path(sys.executable).resolve().parent, Path( getattr(sys, "_MEIPASS", source_root) ).resolve() return source_root, source_root def prepare_portable_config(app_root: Path, resource_root: Path) -> None: """Seed a packaged copy with its default registry without overwriting user edits.""" if app_root == resource_root: return config_dir = app_root / "config" config_dir.mkdir(parents=True, exist_ok=True) bundled_config = resource_root / "config" for name in ("tools.json", "settings.json", "external_tools.json"): source = bundled_config / name destination = config_dir / name if source.is_file() and not destination.exists(): shutil.copy2(source, destination) def set_windows_app_identity() -> None: """Give Windows a stable identity instead of grouping ADAM under Python.""" if sys.platform != "win32": return try: ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(WINDOWS_APP_ID) except (AttributeError, OSError): pass def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser(description="ADAM desktop orchestrator") parser.add_argument( "--screenshot", type=Path, help="Save a launch screenshot and exit (used for visual smoke tests).", ) return parser.parse_args() def main() -> int: args = parse_args() project_root, resource_root = application_paths() prepare_portable_config(project_root, resource_root) set_windows_app_identity() if args.screenshot and not os.environ.get("QT_QPA_PLATFORM"): os.environ["QT_QPA_PLATFORM"] = "offscreen" qt_app = QApplication(sys.argv) qt_app.setApplicationName("ADAM") qt_app.setOrganizationName("ADAM") qt_app.setStyle("Fusion") icon_path = resource_root / "assets" / "adam_atom.png" if icon_path.exists(): qt_app.setWindowIcon(QIcon(str(icon_path))) window, services = build_application(project_root) window.show() if args.screenshot: destination = args.screenshot.resolve() def capture() -> None: destination.parent.mkdir(parents=True, exist_ok=True) window.grab().save(str(destination)) services.shutdown() qt_app.quit() QTimer.singleShot(1200, capture) exit_code = qt_app.exec() services.shutdown() return exit_code if __name__ == "__main__": raise SystemExit(main())