From b34965b936e3cde81cca1bdace961b1834509b26 Mon Sep 17 00:00:00 2001 From: Huang richao Date: Fri, 24 Apr 2026 17:52:47 +0800 Subject: [PATCH] fix: narrow macOS app installer per review --- README.md | 44 +++++--- assets/install-macos-app.sh | 179 ++++++++++++++++++++++++++++++++ scripts/install-macos-app.sh | 195 ----------------------------------- 3 files changed, 209 insertions(+), 209 deletions(-) create mode 100755 assets/install-macos-app.sh delete mode 100755 scripts/install-macos-app.sh diff --git a/README.md b/README.md index e78484f..c3c1751 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,20 @@ cp mykey_template.py mykey.py python launch.pyw ``` +#### Method 2: uv (for experienced Python users) + +If you prefer a modern Python workflow, GenericAgent also provides a minimal `pyproject.toml`: + +```bash +git clone https://github.com/lsdefine/GenericAgent.git +cd GenericAgent +uv pip install -e ".[ui]" # Core + GUI dependencies +cp mykey_template.py mykey.py +python launch.pyw +``` + +> GenericAgent is meant to grow its environment through the Agent itself, not by pre-installing every possible package. + Full guide: [GETTING_STARTED.md](GETTING_STARTED.md) --- @@ -191,10 +205,9 @@ You're also welcome to join our **GenericAgent Community Group** for discussion,
- - +
WeChat Group 6
WeChat Group 6 QR Code
WeChat Group 8
WeChat Group 8 QR Code
WeChat Group 9
WeChat Group 9 QR Code
WeChat Group 10
WeChat Group 10 QR Code
WeChat Group 11
WeChat Group 11 QR Code
@@ -293,6 +306,20 @@ cp mykey_template.py mykey.py python launch.pyw ``` +#### 方法二:uv 快速安装(熟悉 Python 的用户) + +如果你习惯现代 Python 工作流,GenericAgent 也提供了一个最小化的 `pyproject.toml`: + +```bash +git clone https://github.com/lsdefine/GenericAgent.git +cd GenericAgent +uv pip install -e ".[ui]" # 核心 + GUI 依赖 +cp mykey_template.py mykey.py +python launch.pyw +``` + +> GenericAgent 更推荐由 Agent 在使用中自举环境,而不是预先手动装完整依赖。 + 完整引导流程见 [GETTING_STARTED.md](GETTING_STARTED.md)。 📖 新手使用指南(图文版):[飞书文档](https://my.feishu.cn/wiki/CGrDw0T76iNFuskmwxdcWrpinPb) @@ -400,16 +427,6 @@ 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 项目文件夹。 - ## 📊 与同类产品对比 @@ -475,10 +492,9 @@ GenericAgent 通过**分层记忆 × 最小工具集 × 自主执行循环**完
- - +
微信群 6
微信群 6 二维码
微信群 8
微信群 8 二维码
微信群 9
微信群 9 二维码
微信群 10
微信群 10 二维码
微信群 11
微信群 11 二维码
diff --git a/assets/install-macos-app.sh b/assets/install-macos-app.sh new file mode 100755 index 0000000..e438af5 --- /dev/null +++ b/assets/install-macos-app.sh @@ -0,0 +1,179 @@ +#!/bin/bash + +# GenericAgent macOS Desktop App Installation Script +# +# Usage: +# bash assets/install-macos-app.sh [--auto] +# +# This installer creates a small .app bundle that opens Terminal and runs +# `python3 launch.pyw` from the current GenericAgent checkout. + +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 -euo pipefail + +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}"; } + +AUTO_MODE=false +for arg in "$@"; do + case "$arg" in + --auto) AUTO_MODE=true ;; + esac +done + +APP_NAME="GenericAgent" +PRIMARY_INSTALL_DIR="/Applications" +FALLBACK_INSTALL_DIR="${HOME}/Applications" + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" +ICON_PATH="${PROJECT_ROOT}/assets/images/logo.jpg" +LAUNCH_SCRIPT="${PROJECT_ROOT}/launch.pyw" + +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 + +if ! command -v python3 >/dev/null 2>&1; then + log_error "python3 is not installed." + exit 1 +fi + +if [ ! -f "${LAUNCH_SCRIPT}" ]; then + log_error "launch.pyw not found at ${LAUNCH_SCRIPT}" + exit 1 +fi + +project_path_for_applescript="${PROJECT_ROOT}/" +project_path_for_applescript="${project_path_for_applescript//\\/\\\\}" +project_path_for_applescript="${project_path_for_applescript//\"/\\\"}" + +detect_existing_app() { + if [ -d "${PRIMARY_INSTALL_DIR}/${APP_NAME}.app" ]; then + echo "${PRIMARY_INSTALL_DIR}/${APP_NAME}.app" + return + fi + if [ -d "${FALLBACK_INSTALL_DIR}/${APP_NAME}.app" ]; then + echo "${FALLBACK_INSTALL_DIR}/${APP_NAME}.app" + return + fi +} + +existing_app_path="$(detect_existing_app || true)" +if [ -n "${existing_app_path}" ]; then + log_warning "${APP_NAME}.app already exists at ${existing_app_path}" +fi + +if [ "${AUTO_MODE}" = false ]; then + echo "" + echo "This will install a desktop app that launches GenericAgent" + echo "from Spotlight, Launchpad, or the Applications folder." + echo "" + if [ -n "${existing_app_path}" ]; then + read -p "Reinstall ${APP_NAME}.app? (y/N) " -n 1 -r + else + read -p "Continue? (Y/n) " -n 1 -r + fi + echo + if [ -n "${existing_app_path}" ]; then + [[ ! ${REPLY:-} =~ ^[Yy]$ ]] && { echo "Aborted."; exit 0; } + else + [[ ${REPLY:-} =~ ^[Nn]$ ]] && { echo "Aborted."; exit 0; } + fi +fi + +TMP_DIR="$(mktemp -d)" +trap 'rm -rf "${TMP_DIR}"' EXIT + +log_info "Building ${APP_NAME}.app..." + +cat > "${TMP_DIR}/${APP_NAME}.applescript" </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" + 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 icon." +fi + +install_bundle() { + local install_dir="$1" + local destination="${install_dir}/${APP_NAME}.app" + mkdir -p "${install_dir}" + rm -rf "${destination}" + cp -R "${TMP_DIR}/${APP_NAME}.app" "${destination}" +} + +install_path="" +if install_bundle "${PRIMARY_INSTALL_DIR}" 2>/dev/null; then + install_path="${PRIMARY_INSTALL_DIR}/${APP_NAME}.app" +else + log_warning "Could not write to ${PRIMARY_INSTALL_DIR}; falling back to ${FALLBACK_INSTALL_DIR}" + install_bundle "${FALLBACK_INSTALL_DIR}" + install_path="${FALLBACK_INSTALL_DIR}/${APP_NAME}.app" +fi + +log_success "Installed to: ${install_path}" + +echo "" +echo -e "${CYAN}╔═══════════════════════════════════════════════════════════╗${NC}" +echo -e "${CYAN}║${NC} ✨ ${APP_NAME} Desktop App installed successfully! ${CYAN}║${NC}" +echo -e "${CYAN}╚═══════════════════════════════════════════════════════════╝${NC}" +echo "" +echo -e "${BLUE}Launch methods:${NC}" +echo " • Spotlight: Cmd + Space → type '${APP_NAME}' → Enter" +echo " • Launchpad: Find the '${APP_NAME}' icon" +echo " • Finder: Open ${install_path}" +echo "" +echo -e "${BLUE}Runtime behavior:${NC}" +echo " The app uses the current checkout path embedded at install time:" +echo " ${PROJECT_ROOT}" +echo " If you move the repo later, re-run this installer." +echo "" +echo -e "${BLUE}Uninstall:${NC}" +echo " rm -rf '${install_path}'" +echo "" diff --git a/scripts/install-macos-app.sh b/scripts/install-macos-app.sh deleted file mode 100755 index a40535e..0000000 --- a/scripts/install-macos-app.sh +++ /dev/null @@ -1,195 +0,0 @@ -#!/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 ""