From 72555156079beee1e0d4a070cf4b7e47eec501c8 Mon Sep 17 00:00:00 2001 From: Huang richao Date: Thu, 23 Apr 2026 23:19:24 +0800 Subject: [PATCH] feat: add macOS Desktop App installation script - Add scripts/install-macos-app.sh for one-click macOS app installation - Uses bundled assets/images/logo.jpg as app icon - AppleScript prompts for project folder on first run - Updates README with macOS Desktop App installation option - Supports both interactive and --auto non-interactive modes Co-authored-by: Qwen-Coder --- README.md | 10 ++ scripts/install-macos-app.sh | 195 +++++++++++++++++++++++++++++++++++ 2 files changed, 205 insertions(+) create mode 100755 scripts/install-macos-app.sh diff --git a/README.md b/README.md index d9e5149..e78484f 100644 --- a/README.md +++ b/README.md @@ -400,6 +400,16 @@ streamlit run frontends/stapp2.py # 另一种 Streamlit 风格 UI - `/continue` - 列出可恢复会话快照 - `/continue N` - 恢复第 `N` 个可恢复会话 +### macOS Desktop App (Optional) + +将 GenericAgent 安装为 macOS 原生桌面应用,支持通过 Spotlight、Launchpad 或应用程序文件夹一键启动: + +```bash +bash scripts/install-macos-app.sh +``` + +安装后按 `Cmd + Space` → 输入 "GenericAgent" 即可启动。首次运行会提示选择 GenericAgent 项目文件夹。 + ## 📊 与同类产品对比 diff --git a/scripts/install-macos-app.sh b/scripts/install-macos-app.sh new file mode 100755 index 0000000..a40535e --- /dev/null +++ b/scripts/install-macos-app.sh @@ -0,0 +1,195 @@ +#!/bin/bash + +# GenericAgent macOS Desktop App Installation Script +# Installs GenericAgent as a native macOS desktop application +# +# Usage: bash scripts/install-macos-app.sh [--auto] +# +# Options: +# --auto Non-interactive mode, skip prompts and install directly + +if [ -z "${BASH_VERSION}" ]; then + if command -v bash >/dev/null 2>&1; then + exec bash -- "${0}" "$@" + else + echo "Error: This script requires bash." + exit 1 + fi +fi + +set -eo pipefail + +# ============================================ +# Colors +# ============================================ +RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; CYAN='\033[0;36m'; NC='\033[0m' +log_info() { echo -e "${BLUE}ℹ️ $1${NC}"; } +log_success() { echo -e "${GREEN}✅ $1${NC}"; } +log_warning() { echo -e "${YELLOW}⚠️ $1${NC}"; } +log_error() { echo -e "${RED}❌ $1${NC}"; } + +# ============================================ +# Parse arguments +# ============================================ +AUTO_MODE=false +for arg in "$@"; do + case "$arg" in --auto) AUTO_MODE=true ;; esac +done + +# ============================================ +# Configuration +# ============================================ +APP_NAME="GenericAgent" +APP_PATH="/Applications/${APP_NAME}.app" + +# Icon: bundled alongside this script +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" +ICON_PATH="${PROJECT_ROOT}/assets/images/logo.jpg" + +# ============================================ +# Pre-flight checks +# ============================================ +echo -e "${CYAN}" +echo "╔═══════════════════════════════════════════════════════════╗" +echo "║ GenericAgent — macOS Desktop App Installer ║" +echo "╚═══════════════════════════════════════════════════════════╝" +echo -e "${NC}" + +if [[ "$(uname)" != "Darwin" ]]; then + log_error "This script only supports macOS." + exit 1 +fi + +# Check Python and pip +if ! command -v python3 &>/dev/null; then + log_error "python3 is not installed." + exit 1 +fi + +# Check if already installed +APP_ALREADY_INSTALLED=false +if [ -d "$APP_PATH" ]; then + APP_ALREADY_INSTALLED=true + log_warning "GenericAgent.app already exists in /Applications." +fi + +# Interactive prompt +if [ "$AUTO_MODE" = false ]; then + echo "" + echo "This will install a desktop app that launches GenericAgent" + echo "from Spotlight (Cmd+Space), Launchpad, or the Applications folder." + echo "" + if [ "$APP_ALREADY_INSTALLED" = true ]; then + read -p "Reinstall GenericAgent.app? (y/N) " -n 1 -r + else + read -p "Continue? (Y/n) " -n 1 -r + fi + echo + if [ "$APP_ALREADY_INSTALLED" = true ]; then + [[ ! $REPLY =~ ^[Yy]$ ]] && { echo "Aborted."; exit 0; } + else + [[ $REPLY =~ ^[Nn]$ ]] && { echo "Aborted."; exit 0; } + fi +fi + +# Remove existing app +[ -d "$APP_PATH" ] && rm -rf "$APP_PATH" + +# ============================================ +# Build the app +# ============================================ +TMP_DIR=$(mktemp -d) +trap 'rm -rf "$TMP_DIR"' EXIT + +log_info "Building GenericAgent.app..." + +# Create AppleScript — launches launch.pyw in project directory +# The script prompts for project path on first run, or uses a default +cat > "${TMP_DIR}/GenericAgent.applescript" << 'APPLESCRIPT' +property defaultPath : "" + +on run + set projectPath to defaultPath + + if projectPath is "" then + -- Ask user for GenericAgent project folder + set projectPath to choose folder with prompt "Select your GenericAgent project folder:" + end if + + set projectPathStr to POSIX path of projectPath + set launchScript to projectPathStr & "launch.pyw" + + tell application "Terminal" + activate + do script "cd " & quoted form of projectPathStr & " && python3 launch.pyw" + end tell +end run +APPLESCRIPT + +# Compile to .app +osacompile -o "${TMP_DIR}/${APP_NAME}.app" "${TMP_DIR}/GenericAgent.applescript" 2>/dev/null + +# ============================================ +# Install icon +# ============================================ +log_info "Applying GenericAgent icon..." + +if [ -f "$ICON_PATH" ]; then + ICONSET_DIR="${TMP_DIR}/ga-icon.iconset" + mkdir -p "$ICONSET_DIR" + + sips -z 16 16 "$ICON_PATH" --out "${ICONSET_DIR}/icon_16x16.png" >/dev/null 2>&1 + sips -z 32 32 "$ICON_PATH" --out "${ICONSET_DIR}/icon_16x16@2x.png" >/dev/null 2>&1 + sips -z 32 32 "$ICON_PATH" --out "${ICONSET_DIR}/icon_32x32.png" >/dev/null 2>&1 + sips -z 64 64 "$ICON_PATH" --out "${ICONSET_DIR}/icon_32x32@2x.png" >/dev/null 2>&1 + sips -z 128 128 "$ICON_PATH" --out "${ICONSET_DIR}/icon_128x128.png" >/dev/null 2>&1 + sips -z 256 256 "$ICON_PATH" --out "${ICONSET_DIR}/icon_128x128@2x.png" >/dev/null 2>&1 + sips -z 256 256 "$ICON_PATH" --out "${ICONSET_DIR}/icon_256x256.png" >/dev/null 2>&1 + sips -z 512 512 "$ICON_PATH" --out "${ICONSET_DIR}/icon_256x256@2x.png" >/dev/null 2>&1 + sips -z 512 512 "$ICON_PATH" --out "${ICONSET_DIR}/icon_512x512.png" >/dev/null 2>&1 + cp "$ICON_PATH" "${ICONSET_DIR}/icon_512x512@2x.png" + + iconutil -c icns "$ICONSET_DIR" -o "${TMP_DIR}/ga-icon.icns" 2>/dev/null + cp "${TMP_DIR}/ga-icon.icns" "${TMP_DIR}/${APP_NAME}.app/Contents/Resources/applet.icns" + log_success "Icon applied from assets/images/logo.jpg" +else + log_warning "Logo not found at ${ICON_PATH}, using default" +fi + +# ============================================ +# Install to /Applications +# ============================================ +cp -R "${TMP_DIR}/${APP_NAME}.app" "/Applications/" +log_success "Installed to: ${APP_PATH}" + +# ============================================ +# Post-install: refresh icon cache +# ============================================ +rm ~/Library/Application\ Support/Dock/*.db 2>/dev/null || true +killall Dock 2>/dev/null || true + +# ============================================ +# Summary +# ============================================ +echo "" +echo -e "${CYAN}╔═══════════════════════════════════════════════════════════╗${NC}" +echo -e "${CYAN}║${NC} ✨ GenericAgent Desktop App installed successfully! ${CYAN}║${NC}" +echo -e "${CYAN}╚═══════════════════════════════════════════════════════════╝${NC}" +echo "" +echo -e "${BLUE}Launch methods:${NC}" +echo " • Spotlight: Cmd + Space → type 'GenericAgent' → Enter" +echo " • Launchpad: Find the 'GenericAgent' icon" +echo " • Finder: Open /Applications/GenericAgent.app" +echo "" +echo -e "${BLUE}First run:${NC}" +echo " The app will ask you to select your GenericAgent project folder." +echo " It then runs 'python3 launch.pyw' from that directory." +echo "" +echo -e "${BLUE}Set default project folder:${NC}" +echo " Edit /Applications/GenericAgent.app and change the defaultPath property" +echo " in Contents/Resources/Scripts/main.scpt (or re-run this installer)." +echo "" +echo -e "${BLUE}Uninstall:${NC}" +echo " rm -rf '/Applications/GenericAgent.app'" +echo ""