Files
agent-aide/aide-program/docs/01-入口脚本设计.md
2025-12-13 04:37:41 +08:00

12 KiB
Raw Blame History

入口脚本设计

一、概述

1.1 设计目标

提供跨平台的统一命令行入口,使用户可以通过 aide <command> 的方式调用所有功能。

1.2 入口脚本清单

脚本 平台 说明
aide.sh Linux/macOS Shell 脚本入口
aide.bat Windows 批处理脚本入口
main.py 所有平台 Python 主程序

二、aide.sh 设计Linux/macOS

2.1 功能要求

  1. 定位 Python:查找可用的 Python 3.10+ 解释器
  2. 定位脚本目录:确定 main.py 的位置
  3. 传递参数:将所有命令行参数传递给 Python 程序
  4. 处理错误Python 未找到时给出明确提示

2.2 实现示例

#!/usr/bin/env bash
# Aide 命令行工具入口脚本Linux/macOS
# 版本: 1.0

set -e  # 遇到错误立即退出

# 获取脚本所在目录
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# Python 主程序路径
MAIN_PY="${SCRIPT_DIR}/main.py"

# 查找 Python 解释器
find_python() {
    # 尝试查找 Python 3.10+
    for cmd in python3.12 python3.11 python3.10 python3 python; do
        if command -v "$cmd" &> /dev/null; then
            # 检查版本
            version=$("$cmd" -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')
            major=$(echo "$version" | cut -d. -f1)
            minor=$(echo "$version" | cut -d. -f2)

            if [ "$major" -eq 3 ] && [ "$minor" -ge 10 ]; then
                echo "$cmd"
                return 0
            fi
        fi
    done

    return 1
}

# 查找 Python
PYTHON=$(find_python)

if [ -z "$PYTHON" ]; then
    echo "✗ Python 3.10+ 未找到" >&2
    echo "  建议: 安装 Python 3.10 或更高版本" >&2
    echo "  文档: https://www.python.org/downloads/" >&2
    exit 3
fi

# 检查 main.py 是否存在
if [ ! -f "$MAIN_PY" ]; then
    echo "✗ 找不到 main.py" >&2
    echo "  位置: $MAIN_PY" >&2
    exit 1
fi

# 执行 Python 程序
exec "$PYTHON" "$MAIN_PY" "$@"

2.3 安装方式

# 方式1添加到 PATH
export PATH="/path/to/aide:$PATH"

# 方式2创建符号链接
ln -s /path/to/aide/aide.sh /usr/local/bin/aide

# 方式3添加别名
alias aide='/path/to/aide/aide.sh'

三、aide.bat 设计Windows

3.1 功能要求

  1. 定位 Python:查找可用的 Python 3.10+ 解释器
  2. 定位脚本目录:确定 main.py 的位置
  3. 传递参数:将所有命令行参数传递给 Python 程序
  4. 处理错误Python 未找到时给出明确提示

3.2 实现示例

@echo off
REM Aide 命令行工具入口脚本Windows
REM 版本: 1.0

setlocal enabledelayedexpansion

REM 获取脚本所在目录
set "SCRIPT_DIR=%~dp0"

REM Python 主程序路径
set "MAIN_PY=%SCRIPT_DIR%main.py"

REM 查找 Python 解释器
set "PYTHON="
for %%p in (python3.12 python3.11 python3.10 python3 python py) do (
    where %%p >nul 2>&1
    if !errorlevel! equ 0 (
        REM 检查版本
        for /f "delims=" %%v in ('%%p -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"') do (
            set "version=%%v"
        )

        REM 解析版本号
        for /f "tokens=1,2 delims=." %%a in ("!version!") do (
            set "major=%%a"
            set "minor=%%b"
        )

        REM 检查是否满足要求3.10+
        if !major! equ 3 if !minor! geq 10 (
            set "PYTHON=%%p"
            goto :found
        )
    )
)

:found
if "%PYTHON%"=="" (
    echo ✗ Python 3.10+ 未找到 >&2
    echo   建议: 安装 Python 3.10 或更高版本 >&2
    echo   文档: https://www.python.org/downloads/ >&2
    exit /b 3
)

REM 检查 main.py 是否存在
if not exist "%MAIN_PY%" (
    echo ✗ 找不到 main.py >&2
    echo   位置: %MAIN_PY% >&2
    exit /b 1
)

REM 执行 Python 程序
"%PYTHON%" "%MAIN_PY%" %*
exit /b %errorlevel%

3.3 安装方式

REM 方式1添加到 PATH
set PATH=C:\path\to\aide;%PATH%

REM 方式2创建批处理文件到系统目录
copy aide.bat C:\Windows\System32\aide.bat

四、main.py 设计

4.1 功能要求

  1. 命令分发:根据第一个参数分发到对应的命令处理函数
  2. 参数解析:解析命令行参数
  3. 错误处理:统一的错误处理和退出码
  4. 帮助信息:提供 --help--version 支持

4.2 实现框架

#!/usr/bin/env python3
"""
Aide 命令行工具主程序
版本: 1.0
"""

import sys
from pathlib import Path

# 添加 src 目录到 Python 路径
SCRIPT_DIR = Path(__file__).parent
sys.path.insert(0, str(SCRIPT_DIR))

from core.output import ok, warn, err, info
from commands.init import cmd_init
from commands.env import cmd_env
from commands.config_cmd import cmd_config


VERSION = "1.0.0"


def show_help():
    """显示帮助信息"""
    help_text = """Aide - AI 辅助开发工作流工具

用法:
    aide <command> [options]

命令:
    init                初始化 .aide 目录和配置文件
    env ensure          检测并修复项目开发环境
    env ensure --runtime 检测 aide 运行时环境
    config get <key>    获取配置值
    config set <key> <value> 设置配置值

选项:
    -h, --help          显示帮助信息
    -v, --version       显示版本信息

示例:
    aide init
    aide env ensure
    aide config get task.source
    aide config set task.source "new-task.md"

文档: https://github.com/your-org/aide
"""
    print(help_text)


def show_version():
    """显示版本信息"""
    print(f"Aide v{VERSION}")


def main():
    """主函数"""
    # 解析参数
    args = sys.argv[1:]

    # 无参数或帮助
    if not args or args[0] in ["-h", "--help", "help"]:
        show_help()
        return 0

    # 版本信息
    if args[0] in ["-v", "--version", "version"]:
        show_version()
        return 0

    # 获取命令
    command = args[0]

    try:
        # 命令分发
        if command == "init":
            return cmd_init(args[1:])
        elif command == "env":
            return cmd_env(args[1:])
        elif command == "config":
            return cmd_config(args[1:])
        else:
            err(
                f"未知命令: {command}",
                [
                    "可用命令: init, env, config",
                    "使用 'aide --help' 查看帮助"
                ]
            )
            return 2

    except KeyboardInterrupt:
        print("\n")
        info("操作已取消")
        return 130  # 128 + SIGINT(2)

    except Exception as e:
        err(
            "命令执行失败",
            [
                f"原因: {str(e)}",
                "使用 'aide --help' 查看帮助"
            ]
        )
        return 1


if __name__ == "__main__":
    sys.exit(main())

4.3 命令处理函数接口

每个命令处理函数应该遵循以下接口:

def cmd_<command>(args: list[str]) -> int:
    """命令处理函数

    Args:
        args: 命令参数列表(不包含命令本身)

    Returns:
        退出码0 表示成功)
    """
    pass

五、参数解析

5.1 简单参数解析

对于简单的命令,可以手动解析参数:

def cmd_env(args: list[str]) -> int:
    """env 命令处理"""
    if not args:
        err("缺少子命令", ["使用 'aide env ensure' 检测环境"])
        return 2

    subcommand = args[0]

    if subcommand == "ensure":
        # 检查 --runtime 参数
        runtime_only = "--runtime" in args
        return env_ensure(runtime_only=runtime_only)
    else:
        err(f"未知子命令: {subcommand}", ["可用子命令: ensure"])
        return 2

5.2 使用 argparse可选

对于复杂的命令,可以使用 argparse

import argparse

def cmd_config(args: list[str]) -> int:
    """config 命令处理"""
    parser = argparse.ArgumentParser(
        prog="aide config",
        description="配置管理"
    )

    subparsers = parser.add_subparsers(dest="subcommand")

    # get 子命令
    parser_get = subparsers.add_parser("get", help="获取配置值")
    parser_get.add_argument("key", help="配置键")

    # set 子命令
    parser_set = subparsers.add_parser("set", help="设置配置值")
    parser_set.add_argument("key", help="配置键")
    parser_set.add_argument("value", help="配置值")

    try:
        parsed = parser.parse_args(args)
    except SystemExit:
        return 2

    if parsed.subcommand == "get":
        return config_get(parsed.key)
    elif parsed.subcommand == "set":
        return config_set(parsed.key, parsed.value)
    else:
        parser.print_help()
        return 2

六、错误处理

6.1 异常捕获

def main():
    """主函数"""
    try:
        # 命令执行
        return execute_command()

    except KeyboardInterrupt:
        # Ctrl+C 中断
        print("\n")
        info("操作已取消")
        return 130

    except FileNotFoundError as e:
        # 文件不存在
        err("文件不存在", [f"路径: {e.filename}"])
        return 5

    except PermissionError as e:
        # 权限错误
        err("权限不足", [f"路径: {e.filename}"])
        return 1

    except Exception as e:
        # 其他错误
        err("命令执行失败", [f"原因: {str(e)}"])
        return 1

6.2 退出码规范

退出码 含义
0 成功
1 一般错误
2 参数错误
3 环境错误
4 配置错误
5 文件错误
130 用户中断Ctrl+C

七、测试

7.1 入口脚本测试

# 测试 aide.sh
./aide.sh --version
./aide.sh --help
./aide.sh init
./aide.sh env ensure

# 测试 aide.batWindows
aide.bat --version
aide.bat --help
aide.bat init
aide.bat env ensure

7.2 main.py 测试

def test_main_help(capsys):
    """测试帮助信息"""
    sys.argv = ["aide", "--help"]
    result = main()

    assert result == 0
    captured = capsys.readouterr()
    assert "用法:" in captured.out

def test_main_version(capsys):
    """测试版本信息"""
    sys.argv = ["aide", "--version"]
    result = main()

    assert result == 0
    captured = capsys.readouterr()
    assert "Aide v" in captured.out

def test_main_unknown_command(capsys):
    """测试未知命令"""
    sys.argv = ["aide", "unknown"]
    result = main()

    assert result == 2
    captured = capsys.readouterr()
    assert "未知命令" in captured.out

八、安装和分发

8.1 目录结构

aide/
├── aide.sh          # Linux/macOS 入口
├── aide.bat         # Windows 入口
├── main.py          # Python 主程序
├── core/            # 核心模块
├── commands/        # 命令实现
└── utils/           # 工具函数

8.2 安装脚本(可选)

#!/usr/bin/env bash
# install.sh - Aide 安装脚本

set -e

INSTALL_DIR="${HOME}/.local/bin"

# 创建安装目录
mkdir -p "$INSTALL_DIR"

# 复制文件
cp -r aide "$INSTALL_DIR/"

# 创建符号链接
ln -sf "$INSTALL_DIR/aide/aide.sh" "$INSTALL_DIR/aide"

# 添加到 PATH
if ! echo "$PATH" | grep -q "$INSTALL_DIR"; then
    echo "export PATH=\"$INSTALL_DIR:\$PATH\"" >> ~/.bashrc
    echo "✓ 已添加到 PATH"
    echo "  请运行: source ~/.bashrc"
fi

echo "✓ Aide 安装完成"
echo "  使用 'aide --help' 查看帮助"

九、总结

9.1 核心要点

  1. 提供跨平台的统一入口
  2. 自动查找合适的 Python 解释器
  3. 统一的命令分发和错误处理
  4. 清晰的帮助和版本信息

9.2 实现检查清单

  • 实现 aide.shLinux/macOS
  • 实现 aide.batWindows
  • 实现 main.py 命令分发
  • 实现帮助和版本信息
  • 实现错误处理和退出码
  • 编写入口脚本测试
  • 验证跨平台兼容性
  • 编写安装脚本(可选)

版本v1.0 更新日期2025-12-13