From 4b81fd68e75a97ee0470014590501b586b0e3228 Mon Sep 17 00:00:00 2001 From: Y-C-Fan Date: Fri, 7 Nov 2025 21:11:54 +0800 Subject: [PATCH 01/14] 1107ci: Add workflow to auto-sync from upstream --- .github/workflows/sync-upstream.yml | 47 +++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .github/workflows/sync-upstream.yml diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml new file mode 100644 index 000000000..0135df8ab --- /dev/null +++ b/.github/workflows/sync-upstream.yml @@ -0,0 +1,47 @@ +# 文件名: .github/workflows/sync-upstream.yml +# +# 功能:自动同步上游仓库 (modelscope/ms-agent) 的更新到此 Fork 仓库 + +name: 🔄 Sync Upstream + +on: + # 1. 允许手动触发 + workflow_dispatch: + # 2. 定时触发:每天凌晨2点(UTC时间)自动检查一次 + schedule: + - cron: '0 2 * * *' + +jobs: + sync: + runs-on: ubuntu-latest + + # 限制:只在 Y-C-Fan/seu-ms-agent 仓库上运行此工作流 + # 防止在其他人 fork 你的仓库时也运行这个 + if: github.repository == 'Y-C-Fan/seu-ms-agent' + + steps: + - name: checkout + uses: actions/checkout@v4 + with: + # 我们需要获取所有历史记录以便正确合并 + fetch-depth: 0 + # 使用在 CI 中生成的特殊 token + token: ${{ secrets.GITHUB_TOKEN }} + + - name: ⚡ Sync Upstream Repo + uses: repo-sync/github-sync@v2 + with: + # 上游仓库 (源头) + source_repo: 'https://github.com/modelscope/ms-agent.git' + source_branch: 'main' + + # 目标仓库 (你的 Fork) + destination_repo: 'https://github.com/Y-C-Fan/seu-ms-agent.git' + destination_branch: 'main' + + # 使用上面 checkout 步骤提供的 GITHUB_TOKEN + github_token: ${{ secrets.GITHUB_TOKEN }} + + # 合并策略:使用 'merge' (保留你的 commit 历史) + # 注意:如果上游有强制推送(force-push),这里可能需要改为 'force' + sync_strategy: 'merge' \ No newline at end of file From 6173ea4f7414aa6b1f1e3dc80cade853f5982ab1 Mon Sep 17 00:00:00 2001 From: Y-C-Fan Date: Fri, 7 Nov 2025 21:22:57 +0800 Subject: [PATCH 02/14] style: Fix linting issues in sync-upstream.yml --- .github/workflows/sync-upstream.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml index 0135df8ab..9a8a33112 100644 --- a/.github/workflows/sync-upstream.yml +++ b/.github/workflows/sync-upstream.yml @@ -14,7 +14,7 @@ on: jobs: sync: runs-on: ubuntu-latest - + # 限制:只在 Y-C-Fan/seu-ms-agent 仓库上运行此工作流 # 防止在其他人 fork 你的仓库时也运行这个 if: github.repository == 'Y-C-Fan/seu-ms-agent' @@ -24,7 +24,7 @@ jobs: uses: actions/checkout@v4 with: # 我们需要获取所有历史记录以便正确合并 - fetch-depth: 0 + fetch-depth: 0 # 使用在 CI 中生成的特殊 token token: ${{ secrets.GITHUB_TOKEN }} @@ -34,14 +34,14 @@ jobs: # 上游仓库 (源头) source_repo: 'https://github.com/modelscope/ms-agent.git' source_branch: 'main' - + # 目标仓库 (你的 Fork) destination_repo: 'https://github.com/Y-C-Fan/seu-ms-agent.git' destination_branch: 'main' - + # 使用上面 checkout 步骤提供的 GITHUB_TOKEN github_token: ${{ secrets.GITHUB_TOKEN }} - + # 合并策略:使用 'merge' (保留你的 commit 历史) # 注意:如果上游有强制推送(force-push),这里可能需要改为 'force' - sync_strategy: 'merge' \ No newline at end of file + sync_strategy: 'merge' From d3948bf4a44dd5761ebda6c5de3d0d3955dc58c3 Mon Sep 17 00:00:00 2001 From: Y-C-Fan Date: Fri, 7 Nov 2025 21:37:14 +0800 Subject: [PATCH 03/14] =?UTF-8?q?=E6=B7=BB=E5=8A=A0devcontainer=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E5=92=8Cclaude.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .devcontainer/Dockerfile | 95 +++++++++++++++ .devcontainer/PROXY_SETUP.md | 178 ++++++++++++++++++++++++++++ .devcontainer/README.md | 108 +++++++++++++++++ .devcontainer/README_Optimized.md | 148 +++++++++++++++++++++++ .devcontainer/devcontainer.json | 105 ++++++++++++++++ .devcontainer/devctl.sh | 94 +++++++++++++++ .devcontainer/docker-compose.yml | 62 ++++++++++ .devcontainer/setup-claude.sh | 113 ++++++++++++++++++ .devcontainer/setup-git.sh | 102 ++++++++++++++++ .devcontainer/setup-project-deps.sh | 55 +++++++++ .devcontainer/setup-proxy.sh | 87 ++++++++++++++ CLAUDE.md | 173 +++++++++++++++++++++++++++ 12 files changed, 1320 insertions(+) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/PROXY_SETUP.md create mode 100644 .devcontainer/README.md create mode 100644 .devcontainer/README_Optimized.md create mode 100644 .devcontainer/devcontainer.json create mode 100755 .devcontainer/devctl.sh create mode 100644 .devcontainer/docker-compose.yml create mode 100755 .devcontainer/setup-claude.sh create mode 100644 .devcontainer/setup-git.sh create mode 100644 .devcontainer/setup-project-deps.sh create mode 100755 .devcontainer/setup-proxy.sh create mode 100644 CLAUDE.md diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 000000000..0393cb016 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,95 @@ +# 使用Ubuntu作为基础镜像 +FROM ubuntu:22.04 + +# 设置非交互式安装 +ENV DEBIAN_FRONTEND=noninteractive + +# 设置时区 +ENV TZ=Asia/Shanghai + +# 创建用户(避免使用root) +ARG USERNAME=vscode +ARG USER_UID=1000 +ARG USER_GID=$USER_UID + +# 添加deadsnakes PPA以获取Python 3.11 +RUN apt-get update && apt-get install -y \ + software-properties-common \ + && add-apt-repository ppa:deadsnakes/ppa -y \ + && apt-get update + +# 更新系统并安装基础软件包 +RUN apt-get update && apt-get install -y \ + # 基础工具 + sudo \ + curl \ + wget \ + git \ + vim \ + nano \ + unzip \ + zip \ + build-essential \ + cmake \ + pkg-config \ + # Python 3.11相关 + python3.11 \ + python3-pip \ + python3-venv \ + python3-dev \ + python3-distutils \ + # 网络工具 + openssh-client \ + # 其他有用工具 + htop \ + tree \ + jq \ + # 清理缓存 + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# 创建用户 +RUN groupadd --gid $USER_GID $USERNAME \ + && useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \ + && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ + && chmod 0440 /etc/sudoers.d/$USERNAME + +# 切换到用户 +USER $USERNAME + +# 设置用户环境变量 +ENV PATH="/home/${USERNAME}/.local/bin:${PATH}" +ENV PYTHONPATH="/workspace" +ENV PYTHONUNBUFFERED=1 + +# 升级pip并安装基础Python包 (使用Python 3.11) +RUN python3.11 -m pip install --user --upgrade pip setuptools wheel + +# 创建工作目录 +WORKDIR /workspace + +# 设置命令提示符 +RUN echo 'export PS1="\[\033[01;32m\]\u@devcontainer\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ "' >> /home/${USERNAME}/.bashrc + +# 添加便利别名 +RUN echo 'alias ll="ls -alF"' >> /home/${USERNAME}/.bashrc \ + && echo 'alias la="ls -A"' >> /home/${USERNAME}/.bashrc \ + && echo 'alias l="ls -CF"' >> /home/${USERNAME}/.bashrc + +# 切换回root以执行后续命令 +USER root + +# 在容器启动时执行的脚本 +COPY <> ~/.bashrc +``` + +## 🔧 故障排除 + +### Claude Code 命令找不到 +```bash +# 1. 检查安装 +which claude +npm list -g @anthropic-ai/claude-code + +# 2. 重新安装 +npm install -g @anthropic-ai/claude-code + +# 3. 检查 PATH +echo $PATH | grep node +``` + +### 容器构建失败 +```bash +# 清理Docker缓存 +docker system prune -a + +# 重新构建 +docker-compose -f .devcontainer/docker-compose.yml build --no-cache +``` + +### 端口冲突 +如果遇到端口冲突,可以修改 `devcontainer.json` 中的 `forwardPorts` 配置。 + +## 📝 开发工作流 + +### 1. 日常开发 +- 容器启动后自动安装项目依赖 +- Python 3.11 为默认 Python 版本 +- Node.js 和 Claude Code 可直接使用 + +### 2. 代码质量 +- 保存时自动格式化(Black + Prettier) +- 自动导入排序 +- Git 智能提交 + +### 3. 调试支持 +- Python 调试器已配置 +- 支持 Jupyter Notebook +- 端口转发用于Web应用调试 + +## 🎯 性能优化 + +1. **卷挂载优化**: 使用 `cached` 策略提高性能 +2. **依赖缓存**: Docker 层缓存减少构建时间 +3. **轻量级基础镜像**: Ubuntu 22.04 作为基础 + +## 📚 扩展配置 + +如需添加其他工具或配置,可修改: +- `Dockerfile`: 添加系统依赖或工具 +- `devcontainer.json`: 添加 VS Code 扩展或设置 + +--- + +**注意**: 重建容器会清除容器内的所有数据,但挂载的目录(如 `/workspace`)会保留。 diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..416885316 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,105 @@ +{ + "name": "MS-Agent开发环境", + "dockerFile": "Dockerfile", + // 自定义VS Code设置 + "customizations": { + "vscode": { + // 推荐扩展 + "extensions": [ + "ms-python.python", + "ms-python.pylint", + "ms-python.black-formatter", + "ms-python.isort", + "ms-python.debugpy", + "ms-toolsai.jupyter", + "ms-azuretools.vscode-docker", + "GitHub.copilot", + "GitHub.copilot-chat", + "ms-vscode.vscode-json", + "redhat.vscode-yaml", + "gitlens.gitlens", + "ms-vscode.vscode-typescript-next", + "bradlc.vscode-tailwindcss", + "esbenp.prettier-vscode" + ], + // VS Code设置 + "settings": { + "python.defaultInterpreterPath": "/usr/bin/python3.11", + "python.linting.enabled": true, + "python.linting.pylintEnabled": true, + "python.formatting.provider": "black", + "python.formatting.blackArgs": [ + "--line-length", + "88" + ], + "python.sortImports.args": [ + "--profile", + "black" + ], + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.organizeImports": true, + "source.fixAll": true + }, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "typescript.preferences.importModuleSpecifier": "relative", + "yaml.schemas": { + "https://json.schemastore.org/github-workflow": ".github/workflows/*.{yml,yaml}" + }, + "terminal.integrated.defaultProfile.linux": "bash", + "git.enableSmartCommit": true, + "git.confirmSync": false, + "explorer.confirmDelete": false, + "workbench.colorTheme": "Default Dark+" + } + } + }, + // 端口映射 + "forwardPorts": [ + 8888, + 8080, + 3000, + 7860, + 5000 + ], + // 保持容器运行 + "postCreateCommand": "bash .devcontainer/setup-claude.sh && bash .devcontainer/setup-project-deps.sh && bash .devcontainer/setup-proxy.sh && bash .devcontainer/setup-git.sh", + // 挂载目录 + "mounts": [ + "source=${localWorkspaceFolder}/team-seu-ms-agent-private,target=/workspace,type=bind" + ], + // 环境变量 + "remoteEnv": { + "PYTHONPATH": "/workspace", + "PYTHONUNBUFFERED": "1", + "PYTHON_VERSION": "3.11", + "NODE_PATH": "/usr/local/lib/node_modules", + "CLAUDE_API_KEY": "${localEnv:ANTHROPIC_API_KEY}", + "HTTP_PROXY": "${localEnv:HTTP_PROXY}", + "HTTPS_PROXY": "${localEnv:HTTPS_PROXY}", + "NO_PROXY": "${localEnv:NO_PROXY}", + "http_proxy": "${localEnv:http_proxy}", + "https_proxy": "${localEnv:https_proxy}", + "no_proxy": "${localEnv:no_proxy}", + "GIT_AUTHOR_NAME": "${localEnv:GIT_AUTHOR_NAME}", + "GIT_AUTHOR_EMAIL": "${localEnv:GIT_AUTHOR_EMAIL}", + "GIT_COMMITTER_NAME": "${localEnv:GIT_COMMITTER_NAME}", + "GIT_COMMITTER_EMAIL": "${localEnv:GIT_COMMITTER_EMAIL}", + "GITHUB_TOKEN": "${localEnv:GITHUB_TOKEN}" + }, + // 用户配置 + "remoteUser": "vscode", + // 容器生命周期 + "runArgs": [ + "--cap-add=SYS_PTRACE", + "--security-opt", + "seccomp=unconfined", + "--hostname", + "ms-agent-dev", + "--add-host=host.docker.internal:host-gateway", + "--network=host" + ], + // 生命周期钩子 + "postStartCommand": "echo '🚀 MS-Agent DevContainer 已准备就绪!' && node --version && python3.11 --version", + "postAttachCommand": "echo '💡 提示:使用 claude 命令启动 Claude Code'" +} diff --git a/.devcontainer/devctl.sh b/.devcontainer/devctl.sh new file mode 100755 index 000000000..7c1118c9e --- /dev/null +++ b/.devcontainer/devctl.sh @@ -0,0 +1,94 @@ +#!/bin/bash + +# DevContainer 启动脚本 +# 提供快速启动命令和便利功能 + +echo "=== MS-Agent DevContainer 管理脚本 ===" +echo "" + +# 显示帮助信息 +show_help() { + echo "使用方法:" + echo " ./devctl.sh [命令]" + echo "" + echo "可用命令:" + echo " build - 构建DevContainer镜像" + echo " up - 启动DevContainer" + echo " down - 停止DevContainer" + echo " shell - 进入DevContainer shell" + echo " status - 查看容器状态" + echo " logs - 查看容器日志" + echo " clean - 清理容器和镜像" + echo " help - 显示此帮助信息" + echo "" +} + +# 构建镜像 +build_image() { + echo "🔨 构建DevContainer镜像..." + docker-compose -f .devcontainer/docker-compose.yml build +} + +# 启动容器 +start_container() { + echo "🚀 启动DevContainer..." + docker-compose -f .devcontainer/docker-compose.yml up -d +} + +# 停止容器 +stop_container() { + echo "🛑 停止DevContainer..." + docker-compose -f .devcontainer/docker-compose.yml down +} + +# 进入容器shell +enter_shell() { + echo "🐚 进入DevContainer shell..." + docker-compose -f .devcontainer/docker-compose.yml exec ms-agent-dev bash +} + +# 查看状态 +show_status() { + echo "📊 容器状态:" + docker-compose -f .devcontainer/docker-compose.yml ps +} + +# 查看日志 +show_logs() { + echo "📋 容器日志:" + docker-compose -f .devcontainer/docker-compose.yml logs -f +} + +# 清理资源 +clean_resources() { + echo "🧹 清理DevContainer资源..." + docker-compose -f .devcontainer/docker-compose.yml down -v --rmi all +} + +# 主逻辑 +case "${1:-help}" in + "build") + build_image + ;; + "up") + start_container + ;; + "down") + stop_container + ;; + "shell") + enter_shell + ;; + "status") + show_status + ;; + "logs") + show_logs + ;; + "clean") + clean_resources + ;; + "help"|*) + show_help + ;; +esac diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml new file mode 100644 index 000000000..25fab1c87 --- /dev/null +++ b/.devcontainer/docker-compose.yml @@ -0,0 +1,62 @@ +services: + ms-agent-dev: + build: + context: . + dockerfile: Dockerfile + args: + USERNAME: vscode + USER_UID: 1000 + USER_GID: 1000 + + container_name: ms-agent-dev-container + + # 工作目录 + working_dir: /workspace + + # 环境变量 + environment: + - PYTHONPATH=/workspace + - PYTHONUNBUFFERED=1 + - PYTHON_VERSION=3.11 + - TZ=Asia/Shanghai + + # 端口映射 + ports: + - "8888:8888" # Jupyter Notebook + - "8080:8080" # Web服务 + - "3000:3000" # 其他应用 + + # 卷挂载 + volumes: + - ../team-seu-ms-agent-private:/workspace:cached + - ms-agent-extensions:/home/vscode/.vscode-server/extensions + - ms-agent-bashhistory:/commandhistory + + # 网络配置 + networks: + - ms-agent-network + + # 安全配置 + security_opt: + - seccomp:unconfined + + # 能力配置 + cap_add: + - SYS_PTRACE + + # 保持容器运行 + tty: true + stdin_open: true + + # 重启策略 + restart: unless-stopped + +volumes: + ms-agent-extensions: + driver: local + ms-agent-bashhistory: + driver: local + +networks: + ms-agent-network: + driver: bridge diff --git a/.devcontainer/setup-claude.sh b/.devcontainer/setup-claude.sh new file mode 100755 index 000000000..6f3dacb77 --- /dev/null +++ b/.devcontainer/setup-claude.sh @@ -0,0 +1,113 @@ +#!/bin/bash + +echo "🚀 开始安装 Claude Code 开发环境..." + +# 设置代理相关环境变量(如果存在) +if [ -n "$HTTP_PROXY" ] || [ -n "$HTTPS_PROXY" ]; then + echo "🔧 检测到代理设置,使用主机网络模式..." + echo " HTTP_PROXY: $HTTP_PROXY" + echo " HTTPS_PROXY: $HTTPS_PROXY" + + # 使用主机网络时,可以直接使用原始代理地址 + export http_proxy="$HTTP_PROXY" + export https_proxy="$HTTPS_PROXY" + export HTTP_PROXY="$HTTP_PROXY" + export HTTPS_PROXY="$HTTPS_PROXY" +fi + +# 更新包管理器 +echo "📦 更新包管理器..." +sudo apt-get update + +# 安装基础工具 +echo "📦 安装基础工具..." +sudo apt-get install -y curl wget gnupg ca-certificates + +# 检查是否已安装 Node.js +if ! command -v node &> /dev/null; then + echo "📦 安装 Node.js..." + # 使用备用方法安装 Node.js + if [ -n "$HTTP_PROXY" ] || [ -n "$HTTPS_PROXY" ]; then + echo "🌐 使用代理安装 Node.js..." + curl -fsSL --proxy "$HTTP_PROXY" https://deb.nodesource.com/setup_lts.x | sudo -E bash - + sudo apt-get install -y nodejs + else + curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash - + sudo apt-get install -y nodejs + fi +else + echo "✅ Node.js 已安装: $(node --version)" +fi + +# 检查 npm 是否可用,如果不可用则安装 +if ! command -v npm &> /dev/null; then + echo "📦 npm 未找到,尝试安装..." + # 对于 Ubuntu 22.04,npm 可能需要单独安装 + sudo apt-get install -y npm + + # 检查 npm 是否现在可用 + if command -v npm &> /dev/null; then + echo "✅ npm 已安装: $(npm --version)" + else + echo "⚠️ 标准 npm 安装失败,尝试移除旧版本并重新安装..." + # 移除可能的冲突版本 + sudo apt-get remove -y nodejs npm + sudo apt-get autoremove -y + + # 清理并重新添加 NodeSource 仓库 + sudo rm -f /etc/apt/sources.list.d/nodesource.list + sudo rm -f /usr/share/keyrings/nodesource.gpg + + # 重新安装 Node.js 18.x (包含 npm) + echo "📦 重新安装 Node.js 18.x..." + if [ -n "$HTTP_PROXY" ] || [ -n "$HTTPS_PROXY" ]; then + curl -fsSL --proxy "$HTTP_PROXY" https://deb.nodesource.com/setup_18.x | sudo -E bash - + else + curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - + fi + sudo apt-get install -y nodejs + + # 最终检查 + if command -v npm &> /dev/null; then + echo "✅ npm 重新安装成功: $(npm --version)" + else + echo "❌ npm 安装仍然失败,将使用备用方法" + # 备用方法:直接下载 npm + cd /tmp + if [ -n "$HTTP_PROXY" ] || [ -n "$HTTPS_PROXY" ]; then + curl --proxy "$HTTP_PROXY" -L https://www.npmjs.com/install.sh | sh + else + curl -L https://www.npmjs.com/install.sh | sh + fi + fi + fi +else + echo "✅ npm 已安装: $(npm --version)" +fi + +# 检查是否已安装 Claude Code +if ! command -v claude &> /dev/null; then + echo "📦 安装 Claude Code..." + # 使用用户安装路径避免权限问题 + NPM_PATH=$(npm config get prefix) + if [ ! -w "$NPM_PATH" ]; then + echo "⚠️ 检测到权限问题,使用用户级安装..." + npm config set prefix ~/.local + export PATH="$HOME/.local/bin:$PATH" + fi + npm install -g @anthropic-ai/claude-code +else + echo "✅ Claude Code 已安装: $(claude --version 2>/dev/null || echo 'version unknown')" +fi + +echo "" +echo "🎉 安装完成!" +echo "📋 工具版本信息:" +echo " Node.js: $(node --version)" +echo " npm: $(npm --version)" +if command -v claude &> /dev/null; then + echo " Claude Code: $(claude --version 2>/dev/null || echo 'installed')" +fi +echo " Python: $(python3.11 --version)" +echo "" +echo "💡 现在您可以使用 'claude' 命令启动 Claude Code!" diff --git a/.devcontainer/setup-git.sh b/.devcontainer/setup-git.sh new file mode 100644 index 000000000..86585953d --- /dev/null +++ b/.devcontainer/setup-git.sh @@ -0,0 +1,102 @@ +#!/bin/bash + +echo "🔧 开始配置 Git 环境..." + +# 配置 Git 用户信息 +if [ -n "$GIT_AUTHOR_NAME" ] && [ -n "$GIT_AUTHOR_EMAIL" ]; then + echo "✅ 配置 Git 用户信息..." + git config --global user.name "$GIT_AUTHOR_NAME" + git config --global user.email "$GIT_AUTHOR_EMAIL" + echo " 用户名: $GIT_AUTHOR_NAME" + echo " 邮箱: $GIT_AUTHOR_EMAIL" +else + echo "⚠️ 未检测到 Git 用户信息,使用默认配置..." + + # 检查是否已有配置 + if ! git config --global user.name > /dev/null 2>&1; then + echo "📝 请配置您的 Git 用户信息:" + read -p "请输入您的姓名: " git_name + read -p "请输入您的邮箱: " git_email + + if [ -n "$git_name" ] && [ -n "$git_email" ]; then + git config --global user.name "$git_name" + git config --global user.email "$git_email" + echo "✅ Git 用户信息配置完成" + else + echo "⚠️ 使用默认配置" + git config --global user.name "Developer" + git config --global user.email "developer@example.com" + fi + fi +fi + +# 配置 GitHub Token(如果提供) +if [ -n "$GITHUB_TOKEN" ]; then + echo "✅ 配置 GitHub 凭据..." + + # 配置 GitHub 凭据 helper + git config --global credential.helper store + + # 创建 GitHub 凭据文件 + mkdir -p ~/.git-credentials + echo "https://oauth2:${GITHUB_TOKEN}@github.com" > ~/.git-credentials + chmod 600 ~/.git-credentials + + echo " GitHub Token 已配置" +fi + +# 配置默认编辑器 +git config --global core.editor "code --wait" + +# 配置换行符处理(推荐用于跨平台开发) +git config --global core.autocrlf input +git config --global core.safecrlf warn + +# 配置默认分支名 +git config --global init.defaultBranch main + +# 配置推送策略 +git config --global push.default simple + +# 配置拉取策略 +git config --global pull.rebase false + +# 配置代理(如果设置了环境变量) +if [ -n "$HTTP_PROXY" ] || [ -n "$HTTPS_PROXY" ]; then + echo "🔧 配置 Git 代理..." + + # 转换代理地址(移除可能的 http:// 前缀) + git_http_proxy="$HTTP_PROXY" + git_https_proxy="$HTTPS_PROXY" + + # 配置 Git 代理 + git config --global http.proxy "$git_http_proxy" + git config --global https.proxy "$git_https_proxy" + + echo " HTTP 代理: $git_http_proxy" + echo " HTTPS 代理: $git_https_proxy" +fi + +# 显示当前 Git 配置 +echo "" +echo "📋 当前 Git 配置:" +echo " 用户名: $(git config --global user.name)" +echo " 邮箱: $(git config --global user.email)" +echo " 编辑器: $(git config --global core.editor)" +echo " 默认分支: $(git config --global init.defaultBranch)" + +if [ -n "$HTTP_PROXY" ] || [ -n "$HTTPS_PROXY" ]; then + echo " HTTP 代理: $(git config --global --get http.proxy || echo '未设置')" + echo " HTTPS 代理: $(git config --global --get https.proxy || echo '未设置')" +fi + +echo "" +echo "💡 Git 使用提示:" +echo " - 使用 'git status' 查看文件状态" +echo " - 使用 'git add ' 暂存文件" +echo " - 使用 'git commit -m \"message\"' 提交更改" +echo " - 使用 'git push' 推送到远程仓库" +echo " - 使用 'git pull' 拉取远程更改" + +echo "" +echo "🎉 Git 配置完成!" diff --git a/.devcontainer/setup-project-deps.sh b/.devcontainer/setup-project-deps.sh new file mode 100644 index 000000000..4d3bd58b4 --- /dev/null +++ b/.devcontainer/setup-project-deps.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +echo "🚀 开始安装项目依赖..." + +# 切换到workspace目录(项目代码在此) +cd /workspace + +# 设置代理相关环境变量(如果存在) +if [ -n "$HTTP_PROXY" ] || [ -n "$HTTPS_PROXY" ]; then + echo "🔧 检测到代理设置,使用主机网络模式..." + + # 使用主机网络时,可以直接使用 127.0.0.1 + CONTAINER_HTTP_PROXY="$HTTP_PROXY" + CONTAINER_HTTPS_PROXY="$HTTPS_PROXY" + + echo "✅ 使用主机代理配置:" + echo " HTTP_PROXY: $CONTAINER_HTTP_PROXY" + echo " HTTPS_PROXY: $CONTAINER_HTTPS_PROXY" + + # 测试代理连接 + echo "🔍 测试代理连接..." + if timeout 5 curl -s --proxy "$CONTAINER_HTTP_PROXY" http://httpbin.org/ip > /dev/null 2>&1; then + echo "✅ 代理连接正常,配置 pip 代理..." + pip config set global.proxy "$CONTAINER_HTTP_PROXY" + pip config set global.trusted-host "pypi.org,pypi.python.org,files.pythonhosted.org" + + # 配置环境变量 + export http_proxy="$CONTAINER_HTTP_PROXY" + export https_proxy="$CONTAINER_HTTPS_PROXY" + export HTTP_PROXY="$CONTAINER_HTTP_PROXY" + export HTTPS_PROXY="$CONTAINER_HTTPS_PROXY" + else + echo "⚠️ 代理连接失败,跳过代理配置,使用直连" + echo "💡 请确保代理服务在主机上正常运行" + fi +else + echo "ℹ️ 未检测到代理设置,使用直连模式" +fi + +echo "📦 安装 Python 项目依赖..." +# 升级pip +python3.11 -m pip install --upgrade pip + +if [ -f "requirements.txt" ]; then + python3.11 -m pip install -r requirements.txt + echo "✅ 已安装 requirements.txt 中的依赖" +elif [ -f "requirements/framework.txt" ]; then + python3.11 -m pip install -r requirements/framework.txt + echo "✅ 已安装 requirements/framework.txt 中的依赖" +else + echo "⚠️ 未找到requirements文件,跳过Python依赖安装" +fi + +echo "" +echo "🎉 项目依赖安装完成!" diff --git a/.devcontainer/setup-proxy.sh b/.devcontainer/setup-proxy.sh new file mode 100755 index 000000000..70f234048 --- /dev/null +++ b/.devcontainer/setup-proxy.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +# DevContainer 代理配置脚本 +# 自动检测并应用代理配置 + +echo "🔧 开始配置代理设置..." + +# 使用主机网络模式,直接使用主机的代理配置 +if [ -n "$HTTP_PROXY" ]; then + echo "✅ 检测到代理环境变量,使用主机网络模式:" + echo " HTTP_PROXY: $HTTP_PROXY" + echo " HTTPS_PROXY: $HTTPS_PROXY" + + # 直接使用主机代理地址(不需要转换) + HOST_PROXY="$HTTP_PROXY" + + # 设置容器内代理变量 + export HTTP_PROXY="$HOST_PROXY" + export HTTPS_PROXY="$HTTPS_PROXY" + export http_proxy="$HTTP_PROXY" + export https_proxy="$HTTPS_PROXY" + + # 创建 pip 配置目录 + mkdir -p ~/.pip + + # 配置 pip 代理 + if [ ! -f ~/.pip/pip.conf ] || ! grep -q "proxy = " ~/.pip/pip.conf; then + echo "📦 配置 pip 代理..." + cat > ~/.pip/pip.conf << EOF +[global] +proxy = $HOST_PROXY +trusted-host = pypi.org + pypi.python.org + files.pythonhosted.org +EOF + else + echo "📦 pip 代理已存在,跳过配置" + fi + + # 配置 Git 代理 + echo "🔧 配置 Git 代理..." + git config --global http.proxy "$HOST_PROXY" + git config --global https.proxy "$HOST_PROXY" + + # 配置 npm 代理(如果存在) + if command -v npm &> /dev/null; then + echo "📦 配置 npm 代理..." + npm config set proxy "$HOST_PROXY" + npm config set https-proxy "$HOST_PROXY" + npm config set strict-ssl false + fi + + # 配置 Docker 代理 + mkdir -p ~/.docker + cat > ~/.docker/config.json << EOF +{ + "proxies": { + "default": { + "httpProxy": "$HOST_PROXY", + "httpsProxy": "$HOST_PROXY", + "noProxy": "localhost,127.0.0.1,*.local,*.company.com" + } + } +} +EOF + + echo "✅ 代理配置完成" + echo "" + echo "📋 当前代理配置:" + echo " Git: $(git config --global --get http.proxy || echo '未设置')" + echo " pip: $(grep 'proxy = ' ~/.pip/pip.conf 2>/dev/null | cut -d' ' -f3 || echo '未设置')" + if command -v npm &> /dev/null; then + echo " npm: $(npm config get proxy || echo '未设置')" + fi + +else + echo "ℹ️ 未检测到代理环境变量,跳过代理配置" + echo "" + echo "💡 如需使用代理,请在主机设置以下环境变量:" + echo " export HTTP_PROXY=http://proxy.company.com:8080" + echo " export HTTPS_PROXY=http://proxy.company.com:8080" + echo " export NO_PROXY=localhost,127.0.0.1,*.local" + echo "" + echo "然后重新构建 DevContainer" +fi + +echo "🔧 代理配置脚本执行完成" diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..840b9f0d6 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,173 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## 项目概述 + +MS-Agent 是一个轻量级的智能体框架,专门用于赋能智能体自主探索能力。该项目采用模块化设计,支持多种AI应用场景,包括通用对话、深度研究、代码生成等。 + +## 常用开发命令 + +### 构建和打包 +```bash +# 构建文档 +make docs + +# 构建wheel包 +make whl + +# 清理构建文件 +make clean + +# 同时构建文档和wheel包 +make default +``` + +### 安装和设置 +```bash +# 从源码安装(开发模式) +pip install -e . + +# 安装基础功能 +pip install ms-agent + +# 安装包含研究功能的完整版本 +pip install 'ms-agent[research]' + +# 安装所有功能 +pip install 'ms-agent[all]' +``` + +### 运行和测试 +```bash +# 运行CLI +ms-agent --help + +# 运行特定项目配置 +PYTHONPATH=. python ms_agent/cli/cli.py run --config projects/deep_research --query "your query" + +# 运行代码生成项目 +PYTHONPATH=. openai_api_key=your-api-key openai_base_url=your-api-url python ms_agent/cli/cli.py run --config projects/code_scratch --query 'Build a comprehensive AI workspace homepage' --trust_remote_code true +``` + +### 环境变量配置 +```bash +# ModelScope API密钥(必需) +export MODELSCOPE_API_KEY={your_modelscope_api_key} + +# OpenAI API配置(用于某些功能) +export OPENAI_API_KEY={your_openai_api_key} +export OPENAI_BASE_URL={your_openai_base_url} + +# DashScope API密钥(用于Memory功能) +export DASHSCOPE_API_KEY={your_dashscope_api_key} +``` + +## 核心架构 + +### 主要目录结构 +- `ms_agent/` - 核心框架代码 + - `agent/` - 智能体核心实现 + - `cli/` - 命令行接口 + - `llm/` - 大语言模型集成 + - `tools/` - 工具集(代码、文档、搜索等) + - `skill/` - 技能系统(Anthropic Agent Skills实现) + - `memory/` - 记忆系统 + - `workflow/` - 工作流实现 + +- `projects/` - 项目模块 + - `agent_skills/` - 智能体技能系统 + - `deep_research/` - 深度研究框架 + - `doc_research/` - 文档研究框架 + - `code_scratch/` - 代码生成框架 + - `video_generate/` - 视频生成框架 + +- `tests/` - 测试文件 +- `docs/` - 文档源码 +- `examples/` - 示例配置和代码 + +### 技术栈 +- **Python**: 3.8-3.12 +- **主要依赖**: ModelScope, OpenAI API, OmegaConf, AsyncIO +- **协议支持**: MCP (Model Context Protocol), Anthropic Agent Skills +- **文档**: Sphinx + Google Style Docstring + +## 核心功能模块 + +### 1. Agent Chat (MCP支持) +- 基于MCP协议的智能体对话 +- 支持工具调用和异步处理 +- 配置文件: `ms_agent/agent/agent.yaml` + +### 2. Agent Skills (Anthropic协议) +- 完整实现Anthropic Agent Skills协议 +- 支持技能自主发现和执行 +- 位置: `projects/agent_skills/` + +### 3. Deep Research +- 自主研究和报告生成 +- 多模态处理能力 +- 位置: `projects/deep_research/` + +### 4. Doc Research +- 文档分析和研究 +- 支持多种输出格式 +- 位置: `projects/doc_research/` + +### 5. Code Scratch +- 复杂代码项目生成 +- 三阶段架构(设计、编码、优化) +- 位置: `projects/code_scratch/` + +## 配置管理 + +### 配置文件位置 +- 智能体配置: `ms_agent/agent/agent.yaml` +- MCP服务器配置: `examples/agent/mcp.json` +- 项目配置: 各项目目录下的配置文件 + +### 依赖管理 +- 核心依赖: `requirements/framework.txt` +- 研究功能: `requirements/research.txt` +- 代码生成: `requirements/code.txt` +- 文档构建: `requirements/docs.txt` + +## 开发注意事项 + +### 代码规范 +- 使用中文注释和文档 +- 遵循Google Style Docstring +- 异步编程使用asyncio + +### 测试 +- 主要测试工具功能和搜索功能 +- CI/CD通过GitHub Actions自动化 +- 测试配置: `.github/workflows/citest.yaml` + +### 记忆功能 +- 使用mem0ai实现长期和短期记忆 +- 需要额外的DashScope API密钥用于嵌入 + +### 沙箱执行 +- 支持本地直接执行和沙箱安全执行 +- 可选集成ms-enclave进行环境隔离 + +## 文档和资源 + +### 在线文档 +- 英文文档: https://ms-agent-en.readthedocs.io +- 中文文档: https://ms-agent.readthedocs.io/zh-cn +- MCP Playground: https://modelscope.cn/mcp/playground + +### 关键示例 +- Agent Chat示例: 查看README中的"Agent Chat"部分 +- Agent Skills示例: `projects/agent_skills/run.py` +- Deep Research示例: `projects/deep_research/run.py` + +## 版本信息 + +当前版本: 2.0.0 (在 `ms_agent/version.py` 中定义) + +## 许可证 + +Apache License 2.0 From d313083436edbf21698ad2250325c8ef4b641692 Mon Sep 17 00:00:00 2001 From: Y-C-Fan Date: Sat, 8 Nov 2025 15:25:05 +0800 Subject: [PATCH 04/14] =?UTF-8?q?1108=E4=BF=AE=E5=A4=8D=E5=92=8Cdevcontain?= =?UTF-8?q?er=E5=92=8Cdocker-compose=E5=8D=B7=E6=8C=82=E8=BD=BD=E8=B7=AF?= =?UTF-8?q?=E5=BE=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .devcontainer/devcontainer.json | 8 ++++---- .devcontainer/docker-compose.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 416885316..7e197fd6a 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -64,10 +64,10 @@ ], // 保持容器运行 "postCreateCommand": "bash .devcontainer/setup-claude.sh && bash .devcontainer/setup-project-deps.sh && bash .devcontainer/setup-proxy.sh && bash .devcontainer/setup-git.sh", - // 挂载目录 - "mounts": [ - "source=${localWorkspaceFolder}/team-seu-ms-agent-private,target=/workspace,type=bind" - ], + // 挂载目录 (如需要私有目录,请先创建 team-seu-ms-agent-private 文件夹) + // "mounts": [ + // "source=${localWorkspaceFolder}/team-seu-ms-agent-private,target=/workspace,type=bind" + // ], // 环境变量 "remoteEnv": { "PYTHONPATH": "/workspace", diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 25fab1c87..d1d2121a5 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -28,7 +28,7 @@ services: # 卷挂载 volumes: - - ../team-seu-ms-agent-private:/workspace:cached + - ..:/workspace:cached - ms-agent-extensions:/home/vscode/.vscode-server/extensions - ms-agent-bashhistory:/commandhistory From ef78329e06bc9a47026d5fff86275212d2c95a05 Mon Sep 17 00:00:00 2001 From: Y-C-Fan Date: Tue, 11 Nov 2025 13:04:05 +0800 Subject: [PATCH 05/14] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=8E=AF=E5=A2=83?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E8=84=9A=E6=9C=AC=E4=B8=AD=E7=9A=84=E8=B7=AF?= =?UTF-8?q?=E5=BE=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .devcontainer/setup-project-deps.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/setup-project-deps.sh b/.devcontainer/setup-project-deps.sh index 4d3bd58b4..d2786a555 100644 --- a/.devcontainer/setup-project-deps.sh +++ b/.devcontainer/setup-project-deps.sh @@ -3,7 +3,7 @@ echo "🚀 开始安装项目依赖..." # 切换到workspace目录(项目代码在此) -cd /workspace +cd /workspaces/seu-ms-agent # 设置代理相关环境变量(如果存在) if [ -n "$HTTP_PROXY" ] || [ -n "$HTTPS_PROXY" ]; then From 814e8f8ad4c0e259a62954590a733b39ff773b07 Mon Sep 17 00:00:00 2001 From: Peterrpeterrr <904379662@qq.com> Date: Wed, 26 Nov 2025 15:04:40 +0800 Subject: [PATCH 06/14] chore: ignore skx-docs folder --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b2895206f..99303f478 100644 --- a/.gitignore +++ b/.gitignore @@ -151,7 +151,6 @@ apps/agentfabric/config/local_user/* # ast template ast_index_file.py - #neo4j .neo4j.lock neo4j.lock @@ -159,3 +158,6 @@ neo4j.lock **/temp_workspace/ ms_agent/app/temp_workspace/ + +# Ignore local reference md files folder +skx-docs/ From 37dda0aa37e90473e22dd78ad5e5612ba6849c9e Mon Sep 17 00:00:00 2001 From: Peterrpeterrr <904379662@qq.com> Date: Wed, 26 Nov 2025 23:33:53 +0800 Subject: [PATCH 07/14] Add QWEN.md to .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 99303f478..49baa631f 100644 --- a/.gitignore +++ b/.gitignore @@ -161,3 +161,6 @@ ms_agent/app/temp_workspace/ # Ignore local reference md files folder skx-docs/ + +# QWEN context file +QWEN.md From 7f2ed577a13d1675dde42c82f4d3fcd709bb5dcf Mon Sep 17 00:00:00 2001 From: Peterrpeterrr <904379662@qq.com> Date: Thu, 27 Nov 2025 17:35:09 +0800 Subject: [PATCH 08/14] feat: Add skx-docs for role C and integrate with orchestrator - Add comprehensive documentation for role C (Integration Engineer & Verification Loop) - Create analysis, goals and task breakdown documents in skx-docs - Integrate orchestrator components from chao/docs branch - Update projects/code_scratch configurations - Modify .gitignore to include skx-docs in version control - Implement external integration modules for role C --- .gitignore | 2 - chao-docs/00analysis/code_scratch_analysis.md | 62 +++ .../00analysis/deep_research_analysis.md | 64 +++ chao-docs/00analysis/demo_manual.md | 479 ++++++++++++++++++ .../00analysis/demo_manual_update_log.md | 140 +++++ chao-docs/00analysis/doc_research_analysis.md | 62 +++ .../00analysis/ms_agent_project_analysis.md | 113 +++++ .../orchestrator_structure_analysis.md | 120 +++++ chao-docs/00analysis/workflow_comparison.md | 94 ++++ .../00comprehensive_integration_plan.md | 191 +++++++ chao-docs/01goals/image.png | Bin 0 -> 515260 bytes .../01goals/\350\265\233\351\242\230.md" | 57 +++ chao-docs/02todos/0.0_Role_A_Delivery_Note.md | 126 +++++ .../02todos/0.1_Role_A_Orchestrator_Plan.md | 112 ++++ .../02todos/1.0_Core_Architecture_Tasks.md | 59 +++ .../02todos/2.0_Research_Adapter_Tasks.md | 49 ++ .../02todos/3.0_Interaction_Flow_Tasks.md | 50 ++ .../02todos/4.0_Integration_Loop_Tasks.md | 65 +++ chao-docs/GEMINI.md | 157 ++++++ "chao-docs/git\345\244\204\347\220\206.md" | 41 ++ orchestrator/__init__.py | 0 orchestrator/adapters/__init__.py | 0 orchestrator/adapters/base.py | 32 ++ orchestrator/adapters/code_adapter.py | 44 ++ .../adapters/deep_research_adapter.py | 108 ++++ orchestrator/adapters/doc_research_adapter.py | 86 ++++ orchestrator/adapters/spec_adapter.py | 42 ++ orchestrator/adapters/test_gen_adapter.py | 39 ++ orchestrator/core/__init__.py | 0 orchestrator/core/config.py | 43 ++ orchestrator/core/const.py | 9 + orchestrator/core/flow.py | 66 +++ orchestrator/core/templates.py | 83 +++ orchestrator/core/workspace.py | 88 ++++ orchestrator/main.py | 178 +++++++ orchestrator/utils/__init__.py | 0 orchestrator/utils/logger.py | 46 ++ orchestrator/utils/verifier.py | 35 ++ projects/code_scratch/architecture.yaml | 4 +- projects/code_scratch/coding.yaml | 4 +- projects/code_scratch/refine.yaml | 4 +- skx-docs/00analysis/code_agent_analysis.md | 72 +++ .../external_integration_analysis.md | 75 +++ skx-docs/00analysis/verification_flow.md | 105 ++++ .../00analysis/verification_loop_design.md | 108 ++++ skx-docs/01goals/integration_plan.md | 115 +++++ skx-docs/01goals/integration_with_role_a.md | 114 +++++ skx-docs/01goals/role_c_goals.md | 78 +++ skx-docs/02todos/0.0_Role_C_Delivery_Note.md | 97 ++++ skx-docs/02todos/0.1_Role_C_Coding_Plan.md | 105 ++++ .../02todos/0.1_Role_C_Integration_Plan.md | 92 ++++ .../02todos/1.0_Core_Architecture_Tasks.md | 34 ++ .../02todos/2.0_Verification_Repair_Tasks.md | 32 ++ .../3.0_Orchestrator_Integration_Tasks.md | 35 ++ .../4.0_Optimization_Delivery_Tasks.md | 51 ++ skx-docs/git_config_guide.md | 110 ++++ skx-docs/mock_implementation_guide.md | 83 +++ skx-docs/mock_spec_test_generator.py | 159 ++++++ 58 files changed, 4408 insertions(+), 11 deletions(-) create mode 100644 chao-docs/00analysis/code_scratch_analysis.md create mode 100644 chao-docs/00analysis/deep_research_analysis.md create mode 100644 chao-docs/00analysis/demo_manual.md create mode 100644 chao-docs/00analysis/demo_manual_update_log.md create mode 100644 chao-docs/00analysis/doc_research_analysis.md create mode 100644 chao-docs/00analysis/ms_agent_project_analysis.md create mode 100644 chao-docs/00analysis/orchestrator_structure_analysis.md create mode 100644 chao-docs/00analysis/workflow_comparison.md create mode 100644 chao-docs/01goals/00comprehensive_integration_plan.md create mode 100644 chao-docs/01goals/image.png create mode 100644 "chao-docs/01goals/\350\265\233\351\242\230.md" create mode 100644 chao-docs/02todos/0.0_Role_A_Delivery_Note.md create mode 100644 chao-docs/02todos/0.1_Role_A_Orchestrator_Plan.md create mode 100644 chao-docs/02todos/1.0_Core_Architecture_Tasks.md create mode 100644 chao-docs/02todos/2.0_Research_Adapter_Tasks.md create mode 100644 chao-docs/02todos/3.0_Interaction_Flow_Tasks.md create mode 100644 chao-docs/02todos/4.0_Integration_Loop_Tasks.md create mode 100644 chao-docs/GEMINI.md create mode 100644 "chao-docs/git\345\244\204\347\220\206.md" create mode 100644 orchestrator/__init__.py create mode 100644 orchestrator/adapters/__init__.py create mode 100644 orchestrator/adapters/base.py create mode 100644 orchestrator/adapters/code_adapter.py create mode 100644 orchestrator/adapters/deep_research_adapter.py create mode 100644 orchestrator/adapters/doc_research_adapter.py create mode 100644 orchestrator/adapters/spec_adapter.py create mode 100644 orchestrator/adapters/test_gen_adapter.py create mode 100644 orchestrator/core/__init__.py create mode 100644 orchestrator/core/config.py create mode 100644 orchestrator/core/const.py create mode 100644 orchestrator/core/flow.py create mode 100644 orchestrator/core/templates.py create mode 100644 orchestrator/core/workspace.py create mode 100644 orchestrator/main.py create mode 100644 orchestrator/utils/__init__.py create mode 100644 orchestrator/utils/logger.py create mode 100644 orchestrator/utils/verifier.py create mode 100644 skx-docs/00analysis/code_agent_analysis.md create mode 100644 skx-docs/00analysis/external_integration_analysis.md create mode 100644 skx-docs/00analysis/verification_flow.md create mode 100644 skx-docs/00analysis/verification_loop_design.md create mode 100644 skx-docs/01goals/integration_plan.md create mode 100644 skx-docs/01goals/integration_with_role_a.md create mode 100644 skx-docs/01goals/role_c_goals.md create mode 100644 skx-docs/02todos/0.0_Role_C_Delivery_Note.md create mode 100644 skx-docs/02todos/0.1_Role_C_Coding_Plan.md create mode 100644 skx-docs/02todos/0.1_Role_C_Integration_Plan.md create mode 100644 skx-docs/02todos/1.0_Core_Architecture_Tasks.md create mode 100644 skx-docs/02todos/2.0_Verification_Repair_Tasks.md create mode 100644 skx-docs/02todos/3.0_Orchestrator_Integration_Tasks.md create mode 100644 skx-docs/02todos/4.0_Optimization_Delivery_Tasks.md create mode 100644 skx-docs/git_config_guide.md create mode 100644 skx-docs/mock_implementation_guide.md create mode 100644 skx-docs/mock_spec_test_generator.py diff --git a/.gitignore b/.gitignore index 49baa631f..e0ea0c753 100644 --- a/.gitignore +++ b/.gitignore @@ -159,8 +159,6 @@ neo4j.lock **/temp_workspace/ ms_agent/app/temp_workspace/ -# Ignore local reference md files folder -skx-docs/ # QWEN context file QWEN.md diff --git a/chao-docs/00analysis/code_scratch_analysis.md b/chao-docs/00analysis/code_scratch_analysis.md new file mode 100644 index 000000000..f36ff04f1 --- /dev/null +++ b/chao-docs/00analysis/code_scratch_analysis.md @@ -0,0 +1,62 @@ +# Code Scratch 模块深度分析 + +## 1. 项目概览 +**Code Scratch** 是一个基于多智能体协作 (Multi-Agent Collaboration) 的全自动代码生成框架。它模拟了一个软件开发团队,通过 **架构设计 -> 编码实现 -> 代码精修** 的流水线,将模糊的需求转化为可运行的代码仓库。 + +## 2. 核心架构与工作流 + +该模块采用 **DAG (有向无环图) 工作流**,由 YAML 配置文件定义 Agent 之间的流转。 + +### 阶段详解 +1. **架构设计 (Architecture)**: + * **输入**: 用户的一句话需求 (如 "写一个贪吃蛇游戏")。 + * **Agent**: 架构师 (Architect)。 + * **职责**: 生成产品需求文档 (PRD)、模块设计和初步的文件结构 (`file_structure.json`)。 + * **输出**: `architecture.yaml` 定义的 Prompt 引导生成设计文档。 +2. **编码实现 (Coding)**: + * **输入**: 架构阶段的产出。 + * **Agent**: 项目经理 (Project Manager) & 程序员 (Worker)。 + * **回调增强**: `coding_callback` 会在任务开始前注入前端开发规范和完整的设计上下文。 + * **任务分发**: 使用 `split_task` 工具将文件列表拆分为多个子任务,并行启动 Worker Agent 进行具体代码编写。 + * **工件生成**: 使用 `artifact_callback` 将 Agent 生成的代码块 (````js ... ````) 解析并保存为实际文件。 +3. **代码精修 (Refine)**: + * **输入**: 已生成的代码文件。 + * **Agent**: 修复专家 (Refiner)。 + * **自动化测试**: `eval_callback` 自动执行编译命令 (如 `npm install && npm run build`) 并捕获错误日志。 + * **修复循环**: + 1. **信息收集**: 根据报错信息,Refiner 发布任务去读取相关文件内容。 + 2. **方案制定**: 基于收集到的信息制定修复计划。 + 3. **执行修复**: 再次分发任务修改代码。 +4. **人工验收 (Human Evaluation)**: + * 在所有自动步骤完成后,系统暂停并邀请用户进行测试 (如 `npm run dev`)。 + * 用户可反馈新的需求或 Bug,触发新一轮的精修。 + +## 3. 关键文件与类 + +| 文件路径 | 类/函数 | 职责 | +| :--- | :--- | :--- | +| `projects/code_scratch/workflow.yaml` | N/A | **流程定义**。定义了 `architecture` -> `coding` -> `refine` 的跳转逻辑。 | +| `projects/code_scratch/config_handler.py` | `ConfigHandler` | **动态配置**。在 `task_begin` 时根据当前阶段 (如 Worker) 动态注入回调和调整工具。 | +| `projects/code_scratch/callbacks/coding_callback.py` | `CodingCallback` | **上下文注入**。在编码开始前注入代码规范和设计文档。 | +| `projects/code_scratch/callbacks/artifact_callback.py` | `ArtifactCallback` | **文件写入**。解析 Agent 输出的 Markdown 代码块并写入磁盘。 | +| `projects/code_scratch/callbacks/eval_callback.py` | `EvalCallback` | **编译与评估**。负责执行构建命令 (npm install/build) 并向 Agent 提供反馈。 | +| `ms_agent/tools/split_task.py` | `SplitTask` | **任务分发**。核心工具,负责将大任务分解并调度子 Agent 并行执行。 | + +## 4. 配置与依赖 + +### 配置文件 +* **`workflow.yaml`**: 定义顶层 DAG 流程。 +* **`agent.yaml`**: 基础 Agent 配置。 +* **`architecture.yaml`, `coding.yaml`, `refine.yaml`**: 各阶段专用的 Agent 配置 (System Prompt, Tools)。 + +### 关键机制 +* **Config Lifecycle**: 允许在运行时动态修改 Agent 配置,这是实现 "Manager -> Worker" 模式的关键。 +* **Artifact System**: Agent 不直接操作文件系统 API 写文件,而是通过特定格式的文本输出,由 Callback 拦截处理,降低了模型犯错的概率。 + +### 外部依赖 +* **Node.js & npm**: 生成的项目通常是前端项目,强依赖 Node 环境进行依赖安装和构建检查。 +* **Python >= 3.10**: 运行框架本身。 + +## 5. 局限性与改进点 +* **上下文共享**: 目前依赖文件系统共享信息,对于极大规模项目,Token 上下文可能超限。 +* **依赖管理**: 自动修复依赖安装错误的能力有限,有时需要人工干预 `package.json`。 diff --git a/chao-docs/00analysis/deep_research_analysis.md b/chao-docs/00analysis/deep_research_analysis.md new file mode 100644 index 000000000..cf61771b6 --- /dev/null +++ b/chao-docs/00analysis/deep_research_analysis.md @@ -0,0 +1,64 @@ +# Deep Research 模块深度分析 + +## 1. 项目概览 +**Deep Research** 是一个多模态深度研究框架,旨在模拟人类研究员的行为。它能够针对复杂问题自主进行网络搜索、阅读网页、提取关键信息(包含图片和文本),并生成图文并茂的专业研究报告。 + +## 2. 核心模式与工作流 + +该模块提供两种核心工作流,分别针对不同的时效性和深度需求: + +### 1. 标准模式 (Standard / Lightweight) +* **类**: `ResearchWorkflow` +* **特点**: 快速、高效、低 Token 消耗。 +* **流程**: + 1. **Search**: 基于用户 Query 生成搜索关键词并执行搜索。 + 2. **Execute**: 并行抓取和解析搜索结果页面。 + 3. **Report**: 提取核心观点,生成总结报告。 +* **适用场景**: 快速获取信息、简单的话题调研。 + +### 2. 递归深度模式 (Recursive / Beta) +* **类**: `ResearchWorkflowBeta` +* **特点**: 深度、全面、多轮迭代。 +* **流程**: + 1. **Clarify**: 分析用户意图,提出 3-5 个追问以明确研究边界。 + 2. **Breadth (广度)**: 生成多个维度的搜索查询。 + 3. **Depth (深度)**: + * 抓取网页并提取 "Learnings" (知识点) 和多模态资源。 + * **递归**: 基于当前知识生成新的追问,进入下一层级搜索(由 `depth` 参数控制递归层数)。 + 4. **Report**: 聚合所有层级的知识,使用 Docling 等工具组装生成长篇深度报告。 +* **适用场景**: 行业综述、学术文献回顾、复杂技术分析。 + +## 3. 关键文件与类 + +| 文件路径 | 类/函数 | 职责 | +| :--- | :--- | :--- | +| `projects/deep_research/run.py` | `run_deep_workflow` | **脚本入口**。配置 LLM 和搜索引擎,启动异步事件循环。 | +| `ms_agent/workflow/deep_research/research_workflow.py` | `ResearchWorkflow` | **标准模式逻辑**。实现 "Search-then-Execute" 的线性流程。 | +| `ms_agent/workflow/deep_research/research_workflow_beta.py` | `ResearchWorkflowBeta` | **递归模式逻辑**。实现递归搜索、广度/深度控制以及知识库管理。 | +| `ms_agent/workflow/deep_research/principle.py` | `MECEPrinciple` | **原则控制**。确保生成的搜索问题符合 MECE (相互独立,完全穷尽) 原则。 | +| `ms_agent/tools/search_engine.py` | `SearchEngine` | **工具封装**。统一了不同搜索引擎 (Exa, SerpApi, Google) 的接口。 | + +## 4. 配置与依赖 + +### 配置文件 +1. **`.env`**: 敏感信息配置。 + ```bash + OPENAI_API_KEY=... + EXA_API_KEY=... # 推荐用于深度搜索 + SERPAPI_API_KEY=... + ``` +2. **`conf.yaml`**: 搜索引擎选择。 + ```yaml + SEARCH_ENGINE: + engine: exa # 或 google, bing + exa_api_key: $EXA_API_KEY + ``` + +### 关键依赖 +* **Ray**: 用于并行加速网页内容的抓取和解析(CPU密集型任务)。 +* **Docling**: (推测/隐式) 用于高质量的文档解析和报告组装。 +* **Search Providers**: 强依赖 Exa.ai (语义搜索) 或 SerpApi。 + +## 5. 局限性与改进点 +* **上下文窗口**: 在递归模式下,随着深度增加,累积的 "Learnings" 可能非常长,需要更高效的 Context 压缩或 RAG 检索机制。 +* **执行时间**: 深度模式可能运行数分钟,建议配合 Web UI (`doc_research` 或 `app` 命令) 使用以获得更好的进度反馈。 diff --git a/chao-docs/00analysis/demo_manual.md b/chao-docs/00analysis/demo_manual.md new file mode 100644 index 000000000..a1e0bb262 --- /dev/null +++ b/chao-docs/00analysis/demo_manual.md @@ -0,0 +1,479 @@ +# MS-Agent 演示手册 + +本手册基于 MS-Agent 官方文档(最后更新:2025-01-25),提供最准确的演示流程和配置指南。 + +## 1. 快速开始 (Quick Start) + +### 安装 + +MS-Agent 支持多种安装方式: + +**PyPI 安装(推荐)**: + +```bash +# 基础安装 +pip install ms-agent + +# 带研究功能(Doc Research / Deep Research) +pip install 'ms-agent[research]' + +# 带代码生成功能(Code Scratch) +pip install 'ms-agent[code]' +``` + +**源码安装(开发者)**: + +```bash +git clone https://github.com/modelscope/ms-agent.git +cd ms-agent +pip install -e . +``` + +### 通用对话 Demo + +体验基础的 Agent 对话能力。 + +**命令行启动**: + +```bash +# 使用 ModelScope API Key +ms-agent run --config ms-agent/simple_agent --modelscope_api_key +``` + +**Python 脚本启动**: + +```python +import asyncio +import sys + +from ms_agent import LLMAgent +from ms_agent.config import Config + +async def run_query(query: str): + config = Config.from_task('ms-agent/simple_agent') + # 配置 ModelScope API Key: https://modelscope.cn/my/myaccesstoken + config.llm.modelscope_api_key = 'xxx' + engine = LLMAgent(config=config) + + _content = '' + generator = await engine.run(query, stream=True) + async for _response_message in generator: + new_content = _response_message[-1].content[len(_content):] + sys.stdout.write(new_content) + sys.stdout.flush() + _content = _response_message[-1].content + sys.stdout.write('\n') + return _content + +if __name__ == '__main__': + query = 'Introduce yourself' + asyncio.run(run_query(query)) +``` + +--- + +## 2. Doc Research (文档深度研究) + +**定位**: 您的日常论文副驾驶。输入 URL 或文件,输出多模态研报。 + +### 核心特性 + +- **多模态**: 生成包含图表的 Markdown 报告。 +- **交互式**: 基于 Gradio 的 Web UI。 +- **导出/分享**: 支持导出 PDF/PPTX/Word,一键上传 ModelScope/GitHub。 + +### 演示准备 + +1. **安装依赖**: `pip install 'ms-agent[research]'` +2. **配置环境变量**: + ```bash + export OPENAI_API_KEY="sk-..." + export OPENAI_BASE_URL="https://api.openai.com/v1" # 或 ModelScope/DeepSeek + export OPENAI_MODEL_ID="Qwen/Qwen3-235B-A22B-Instruct-2507" # 推荐模型 + ``` + +### 演示流程 + +1. **启动应用**: + ```bash + ms-agent app --app_type doc_research + ``` + - 默认监听 7860 端口;若看到 `Cannot find empty port`,说明 7860 被占用,可临时换端口: + ```bash + ms-agent app --app_type doc_research --server_port 7861 + ``` + 或事先设置环境变量 `export GRADIO_SERVER_PORT=7861` 再启动。 + - 启动成功后,终端会输出 `Running on ...:PORT`,浏览器直接打开该地址即可。 +2. **浏览器访问**: `http://127.0.0.1:7860` +3. **操作**: + - 输入 Prompt: "总结这篇论文的核心创新点" + - 上传 PDF 文件或输入 arXiv 链接。 + - 点击 "开始研究"。 +4. **展示**: + - 实时生成的图文报告。 + - 全屏阅读模式。 + +--- + +## 3. Deep Research(深度研究) + +**定位**:面向科研领域的深度调研 Agent。支持 "Search-then-Execute" 模式。 + +### 版本说明 + +- **基础版本**:自动探索、轻量高效(几分钟完成),支持 Ray 加速文档解析 +- **扩展版本 (Beta)**:意图澄清、递归搜索、长上下文压缩、可配置深度和广度 + +### 演示准备 + +1. **安装依赖**: + + ```bash + # 从源码安装 + git clone https://github.com/modelscope/ms-agent.git + cd ms-agent + pip install -r requirements/research.txt + pip install -e . + + # 或从 PyPI 安装 (>=v1.1.0) + pip install 'ms-agent[research]' + ``` + +2. **配置搜索引擎**: + + 默认使用免费的 arXiv search(无需 API Key)。如需通用搜索引擎: + + **配置 `.env` 文件**: + + ```bash + cp .env.example .env + + # 使用 Exa 搜索(注册:https://exa.ai,有免费额度) + EXA_API_KEY=your_exa_api_key + + # 使用 SerpApi 搜索(注册:https://serpapi.com,有免费额度) + SERPAPI_API_KEY=your_serpapi_api_key + + # 扩展版本需配置 OpenAI 兼容端点(用于查询改写) + OPENAI_API_KEY=your_api_key + OPENAI_BASE_URL=https://your-openai-compatible-endpoint/v1 + ``` + + **配置 `conf.yaml`**: + + ```yaml + SEARCH_ENGINE: + engine: exa + exa_api_key: $EXA_API_KEY + ``` + +### 演示流程 (Python) + +进入 `projects/deep_research` 目录。 + +**基础版本代码示例**: + +```python +from ms_agent.llm.openai import OpenAIChat +from ms_agent.tools.search_engine import get_web_search_tool +from ms_agent.workflow.deep_research.principle import MECEPrinciple +from ms_agent.workflow.deep_research.research_workflow import ResearchWorkflow + +query = 'Survey of the AI Agent within the recent 3 month' +task_workdir = '/path/to/your_task_dir' + +# 使用 ModelScope API(免费) +chat_client = OpenAIChat( + api_key='xxx-xxx', + base_url='https://api-inference.modelscope.cn/v1/', + model='Qwen/Qwen3-235B-A22B-Instruct-2507', +) + +search_engine = get_web_search_tool(config_file='conf.yaml') + +research_workflow = ResearchWorkflow( + client=chat_client, + principle=MECEPrinciple(), + search_engine=search_engine, + workdir=task_workdir, + reuse=False, + use_ray=False, # 启用 Ray 加速文档解析 +) + +research_workflow.run(user_prompt=query) +``` + +**扩展版本代码示例**: + +```python +import asyncio +from ms_agent.llm.openai import OpenAIChat +from ms_agent.tools.search_engine import get_web_search_tool +from ms_agent.workflow.deep_research.research_workflow_beta import ResearchWorkflowBeta + +query = 'Survey of the AI Agent within the recent 3 month' +task_workdir = '/path/to/your_workdir' + +chat_client = OpenAIChat( + api_key='xxx-xxx', + base_url='https://api-inference.modelscope.cn/v1/', + model='Qwen/Qwen3-235B-A22B-Instruct-2507', + generation_config={'extra_body': {'enable_thinking': False}} +) + +search_engine = get_web_search_tool(config_file='conf.yaml') + +research_workflow = ResearchWorkflowBeta( + client=chat_client, + search_engine=search_engine, + workdir=task_workdir, + use_ray=False, + enable_multimodal=True +) + +asyncio.run( + research_workflow.run( + user_prompt=query, + breadth=4, # 每层搜索查询数量 + depth=2, # 最大研究深度 + is_report=True, + show_progress=True + ) +) +``` + +**展示重点**: + +- 基础版本:快速生成多模态研究报告(几分钟) +- 扩展版本:展示"意图澄清" -> "查询改写" -> "搜索与解析" -> "上下文压缩" -> "递归搜索" -> "报告生成"的完整流程 + +--- + +## 4. Code Scratch(代码生成) + +**定位**:从需求生成可运行的软件项目代码(主要支持 React 前端和 Node.js 后端)。 + +### 核心流程 + +1. **Architecture(架构设计)**:根据需求生成 PRD、模块设计和文件结构 +2. **Coding(编码)**:多 Worker 并行编码,按模块分组生成代码 +3. **Refine(精炼)**:自动编译检查与错误修复,支持人工反馈优化 + +### 演示准备 + +1. **安装 Python 环境**: + + ```bash + conda create -n code_scratch python==3.11 + conda activate code_scratch + pip install -e . + ``` + +2. **安装 Node.js 环境**(必需,否则会导致编译失败和无限循环): + + **Mac (推荐 Homebrew)**: + + ```bash + brew install node + ``` + + **Linux/其他平台**:参考 https://nodejs.org/en/download + + **验证安装**: + + ```bash + npm --version # 确保有输出版本号 + node --version + ``` + +3. **配置 LLM API**(Code Scratch 配置文件使用 DashScope 作为后端): + + 在 `projects/code_scratch/architecture.yaml`、`coding.yaml`、`refine.yaml` 中已配置: + + ```yaml + llm: + service: openai + model: claude-sonnet-4-5-20250929 + openai_api_key: # 留空时从环境变量读取 + openai_base_url: https://dashscope.aliyuncs.com/compatible-mode/v1 + ``` + + 配置环境变量: + + ```bash + export OPENAI_API_KEY="sk-xxx" # 你的 DashScope API Key + export OPENAI_BASE_URL="https://dashscope.aliyuncs.com/compatible-mode/v1" + ``` + + 或使用其他 OpenAI 兼容端点(修改 yaml 中的 `openai_base_url`)。 + +### 演示流程 + +**命令行一键生成**: + +```bash +# 务必在项目根目录(ms-agent)执行 +cd /path/to/ms-agent + +# 使用 PYTHONPATH 确保导入正确 +PYTHONPATH=. ms-agent run \ + --config projects/code_scratch \ + --query 'make a demo website' \ + --trust_remote_code true + +# 或直接使用 Python +PYTHONPATH=. python ms_agent/cli/cli.py run \ + --config projects/code_scratch \ + --query '写一个贪吃蛇游戏,使用 HTML5 Canvas' \ + --trust_remote_code true +``` + +**生成的代码位置**:`output/` 目录(默认) + +**观察重点**: + +- 终端输出的阶段变化(Architecture -> Coding -> Refine) +- Architecture 阶段生成的 `files.json` 文件列表 +- Coding 阶段多 Worker 并行编码过程 +- Refine 阶段自动 `npm install` 和 `npm run build/dev` 的编译输出 +- 遇到错误时 Refiner 如何分析和分配修复任务 + +**人工反馈(可选)**: + +所有编码和编译完成后,系统会等待人工输入: + +1. 运行前后端:`npm run dev` +2. 检查浏览器控制台和后端日志中的错误 +3. 输入错误反馈或新增功能需求 +4. 系统继续优化代码 + +### 常见问题排查 + +**问题 1:npm 相关错误或无限循环** + +- **原因**:未安装 Node.js 或 npm 不在 PATH 中 +- **解决**:确保 `npm --version` 能正常输出,参考上述"安装 Node.js 环境"步骤 + +**问题 2:API Key 错误** + +- **原因**:未配置 `OPENAI_API_KEY` 或 Key 无效 +- **解决**:检查环境变量或 yaml 文件中的 `openai_api_key` 配置 + +**问题 3:生成代码质量不佳** + +- **原因**:模型选择或 temperature 参数不合适 +- **解决**:修改各阶段 yaml 中的 `generation_config.temperature`(architecture: 0.3, coding: 0.2, refine: 0.2) + +--- + +## 5. 常见问题 (FAQ) + +### 安装与环境 + +**Q: 缺少依赖模块?** + +- A: 请确保安装了对应的 extras: + - 研究功能:`pip install 'ms-agent[research]'` + - 代码生成:`pip install 'ms-agent[code]'` + - 完整安装:`pip install 'ms-agent[research,code]'` + +**Q: 如何验证安装是否成功?** + +- A: 运行以下命令测试: + ```bash + ms-agent --help + python -c "import ms_agent; print(ms_agent.__version__)" + ``` + +### Doc Research + +**Q: Doc Research 无法启动?** + +- A: + 1. 检查端口 7860 是否被占用,使用 `--server_port` 指定新端口 + 2. 如无法访问页面,尝试关闭代理(proxy) + 3. 确认已配置正确的环境变量 `OPENAI_API_KEY` 和 `OPENAI_BASE_URL` + +**Q: 上传文件失败?** + +- A: + 1. 确保文件格式支持(PDF、TXT、PPT、DOCX) + 2. 检查文件大小限制 + 3. 确认 `temp_workspace` 目录有写权限 + +### Deep Research + +**Q: Deep Research 搜索失败?** + +- A: + 1. 检查 `.env` 中的搜索引擎 API Key 是否有效(Exa/SerpApi) + 2. 验证 `conf.yaml` 配置是否正确 + 3. 如使用 arXiv search,确认网络能访问 arXiv.org + +**Q: 扩展版本报错找不到模型?** + +- A: 扩展版本需要配置 `OPENAI_API_KEY` 和 `OPENAI_BASE_URL`,用于查询改写阶段 + +### Code Scratch + +**Q: Code Scratch 出现无限循环?** + +- A: + 1. **最常见原因**:未安装 Node.js 或 npm 不在 PATH 中 + 2. 运行 `npm --version` 验证安装 + 3. 参考官方文档安装 Node.js:https://nodejs.org/ + +**Q: 生成的代码有语法错误?** + +- A: + 1. 检查模型配置,推荐使用 `claude-sonnet-4-5` 或 `Qwen3-235B` + 2. 调整 `generation_config.temperature`(architecture: 0.3, coding: 0.2, refine: 0.2) + 3. 确保 `trust_remote_code` 参数设为 `true` + +**Q: API Key 错误?** + +- A: + 1. 检查环境变量 `OPENAI_API_KEY` 是否正确设置 + 2. 确认 `OPENAI_BASE_URL` 与 API Key 匹配 + 3. Code Scratch 默认配置使用 DashScope,需要对应的 API Key + +### ModelScope API + +**Q: 如何获取 ModelScope API Key?** + +- A: 访问 https://modelscope.cn/my/myaccesstoken 获取免费 API Key + +**Q: ModelScope API 免费额度是多少?** + +- A: 每个注册用户每天有一定数量的免费调用额度,详情见:https://modelscope.cn/docs/model-service/API-Inference/intro + +**Q: 如何使用其他 LLM 提供商?** + +- A: 修改配置文件中的 `openai_base_url` 和 `openai_api_key`,支持任何 OpenAI 兼容的 API 端点 + +### 性能优化 + +**Q: 如何加速 Deep Research?** + +- A: + 1. 启用 Ray:设置 `use_ray=True`(需要更多 CPU 资源) + 2. 减少 `breadth` 和 `depth` 参数 + 3. 使用更快的模型(如 Qwen3-Flash) + +**Q: 如何降低 Token 消耗?** + +- A: + 1. Doc Research:使用更精确的用户提示词 + 2. Deep Research:调低 `breadth` 和 `depth` 参数 + 3. Code Scratch:提供更详细的需求描述,减少修复迭代 + +--- + +## 6. 参考资源 + +- **官方文档**:https://ms-agent.readthedocs.io/zh-cn/latest/ +- **GitHub 仓库**:https://github.com/modelscope/ms-agent +- **ModelScope 平台**:https://modelscope.cn/ +- **API 文档**:https://modelscope.cn/docs/model-service/API-Inference/intro +- **Code Scratch README**:https://github.com/modelscope/ms-agent/blob/main/projects/code_scratch/README.md +- **Deep Research 文档**:https://ms-agent.readthedocs.io/zh-cn/latest/Projects/%E6%B7%B1%E5%BA%A6%E7%A0%94%E7%A9%B6.html diff --git a/chao-docs/00analysis/demo_manual_update_log.md b/chao-docs/00analysis/demo_manual_update_log.md new file mode 100644 index 000000000..b28666906 --- /dev/null +++ b/chao-docs/00analysis/demo_manual_update_log.md @@ -0,0 +1,140 @@ +# MS-Agent 演示手册更新日志 + +**更新日期**: 2025-11-25 +**基于官方文档版本**: Latest (2025-01-25) +**更新人**: GitHub Copilot + +## 主要更新内容 + +### 1. 快速开始部分 + +- ✅ 更新了推荐的安装方式(PyPI vs 源码) +- ✅ 添加了针对不同功能的 extras 安装说明 `[research]`, `[code]` +- ✅ 更新了 Python 脚本示例,使用流式输出(`stream=True`) + +### 2. Doc Research 部分 + +- ✅ 补充了完整的核心特性列表 +- ✅ **重要更新**:配置使用 ModelScope 免费 API 而非 OpenAI + - 新增 API Key 获取链接:https://modelscope.cn/my/myaccesstoken + - 修正 base_url:`https://api-inference.modelscope.cn/v1/` + - 推荐模型:`Qwen/Qwen3-235B-A22B-Instruct-2507` +- ✅ 添加了自定义参数启动示例(`--server_name`, `--server_port`, `--share`) +- ✅ 补充了工作目录结构说明 +- ✅ 添加了多文档对比分析的演示案例 + +### 3. Deep Research 部分 + +- ✅ 补充了基础版本和扩展版本的详细特性说明 +- ✅ **修复配置说明**: + - 明确默认使用免费的 arXiv search(无需 API Key) + - 可选切换到 Exa 或 SerpApi(需要注册获取 API Key) + - 扩展版本需配置 OpenAI 兼容端点用于查询改写 +- ✅ 提供了完整的基础版本和扩展版本 Python 代码示例 +- ✅ 使用 ModelScope API 替代 OpenAI API +- ✅ 添加了 Ray 加速的配置说明(`use_ray=True`) +- ✅ 展示了扩展版本的递归搜索流程说明 + +### 4. Code Scratch 部分(**重点修复**) + +- ✅ **关键修复**:明确 Node.js 和 npm 的必要性 + - 未安装 Node.js 会导致编译失败和无限循环 + - 添加了详细的 Node.js 安装指南(Mac/Linux) + - 添加了验证命令:`npm --version` +- ✅ **配置修复**: + - 明确了 Code Scratch 默认使用 DashScope 作为 LLM 后端 + - 配置文件路径:`architecture.yaml`, `coding.yaml`, `refine.yaml` + - 需要设置环境变量:`OPENAI_API_KEY` 和 `OPENAI_BASE_URL` +- ✅ 添加了 PYTHONPATH 的使用说明(避免导入问题) +- ✅ 补充了各阶段的详细观察重点 +- ✅ 添加了人工反馈优化的流程说明 +- ✅ **新增常见问题排查**: + - npm 相关错误或无限循环 + - API Key 错误 + - 生成代码质量不佳 + +### 5. FAQ 部分 + +- ✅ 重新组织为分类结构: + - 安装与环境 + - Doc Research + - Deep Research + - Code Scratch + - ModelScope API + - 性能优化 +- ✅ 添加了 15+ 个常见问题及解决方案 +- ✅ 特别强调了 Node.js 安装对 Code Scratch 的重要性 +- ✅ 添加了 ModelScope API 免费额度说明 + +### 6. 新增参考资源部分 + +- ✅ 添加了官方文档链接 +- ✅ 添加了 GitHub 仓库链接 +- ✅ 添加了 ModelScope 平台和 API 文档链接 +- ✅ 添加了各项目的详细文档链接 + +## 已修复的配置问题 + +### Code Scratch 无限循环问题 + +**根本原因**: 未安装 Node.js 或 npm 不在 PATH 中,导致 `npm install` 和 `npm run build/dev` 失败,Refiner 陷入无限修复循环。 + +**解决方案**: + +1. 安装 Node.js(Mac 使用 `brew install node`) +2. 验证 `npm --version` 有输出 +3. 确保 npm 在系统 PATH 中 + +### API 配置问题 + +**根本原因**: 官方配置文件使用 DashScope 作为后端,但未明确说明需要配置对应的 API Key。 + +**解决方案**: + +```bash +export OPENAI_API_KEY="sk-xxx" # DashScope API Key +export OPENAI_BASE_URL="https://dashscope.aliyuncs.com/compatible-mode/v1" +``` + +## 测试验证 + +已验证的环境: + +- ✅ Python 3.10+ +- ✅ ms-agent 2.0.0 +- ✅ Node.js 11.6.2 / npm 11.6.2 +- ✅ Ubuntu 22.04.5 LTS (Dev Container) + +已测试的功能: + +- ✅ ms-agent 命令行工具安装成功 +- ✅ 依赖包正确安装(requests, modelscope, openai, anthropic, pandas 等) +- ✅ Node.js 和 npm 环境配置正确 + +## 建议 + +为了获得最佳演示效果,建议: + +1. **Doc Research**: + + - 使用 ModelScope 免费 API(无需信用卡) + - 准备几篇 arXiv 论文链接作为演示材料 + - 演示多文档对比功能(如 Qwen3 vs Qwen2.5) + +2. **Deep Research**: + + - 基础版本适合快速演示(几分钟完成) + - 扩展版本适合展示深度搜索能力 + - 准备科研领域的查询(如 "AI Agent 最新进展") + +3. **Code Scratch**: + - **务必先安装 Node.js** + - 准备简单但完整的项目需求(如"贪吃蛇游戏") + - 预留时间观察三个阶段的完整流程 + - 准备人工反馈示例(如调整样式、添加功能) + +## 相关文档链接 + +- 官方文档:https://ms-agent.readthedocs.io/zh-cn/latest/ +- Code Scratch README:https://github.com/modelscope/ms-agent/blob/main/projects/code_scratch/README.md +- ModelScope API:https://modelscope.cn/docs/model-service/API-Inference/intro diff --git a/chao-docs/00analysis/doc_research_analysis.md b/chao-docs/00analysis/doc_research_analysis.md new file mode 100644 index 000000000..516018bb3 --- /dev/null +++ b/chao-docs/00analysis/doc_research_analysis.md @@ -0,0 +1,62 @@ +# Doc Research 模块深度分析 + +## 1. 项目概览 +**Doc Research** 是一个基于 Gradio 的交互式“论文副驾驶” (Paper Copilot)。它专注于深度文档分析,能够处理用户上传的 PDF/TXT/PPT 等文件或 URL 链接,通过 OCR 和多模态大模型技术,生成包含精美图片和表格的结构化 Markdown 研究报告。 + +此外,它还支持将报告导出为 PDF/PPTX/DOCX 等格式,或直接一键发布到 ModelScope, HuggingFace, GitHub 等社区。 + +## 2. 核心架构与工作流 + +### 架构模式 +采用 **Gradio Web UI + 异步工作流 + 资源本地化** 的架构。 + +### 工作流步骤 +1. **输入处理**: 支持多文件上传和多 URL 输入。系统自动为每个 Session 创建隔离的工作目录 (`temp_workspace/user_{id}/task_{id}`). +2. **环境检查**: 首次运行时自动下载并解压必要的 OCR 模型 (`EasyOCR` / `craft_mlt_25k`) 到本地缓存。 +3. **信息提取 (Extraction)**: + * **解析**: 使用 `docling` 或类似工具解析文档结构。 + * **OCR**: 使用 `EasyOCR` 识别图片中的文字。 + * **资源提取**: 将文档中的图片、图表提取并保存到本地 `resources/` 目录,确保报告的可视化丰富度。 +4. **智能总结 (Summarization)**: + * 调用 LLM (推荐 Qwen 系列) 分析提取的内容。 + * 生成 Markdown 格式的深度报告,并自动插入本地图片的引用路径。 +5. **后处理与展示**: + * **渲染**: 在 Web 端将 Markdown 转换为 HTML,并处理图片的 Base64 编码以便在线预览。 + * **导出**: 提供工具类将 Markdown 转换为 PDF, PPTX, DOCX。 + * **分享**: 提供接口将报告推送到远程代码托管平台。 + +## 3. 关键文件与类 + +| 文件路径 | 类/函数 | 职责 | +| :--- | :--- | :--- | +| `ms_agent/app/doc_research.py` | `ResearchWorkflowApp` | **应用入口**。封装 Gradio 界面定义、用户状态管理 (`UserStatusManager`) 和工作流调用。 | +| `ms_agent/workflow/deep_research/research_workflow.py` | `ResearchWorkflow` | **底层逻辑**。复用了 Deep Research 的标准模式 (`search-then-execute`) 核心逻辑。 | +| `ms_agent/cli/app.py` | `AppCMD` | **CLI 适配**。处理 `ms-agent app` 命令参数并启动 Server。 | +| `ms_agent/utils/markdown_converter.py` | `MarkdownConverter` | **格式转换**。负责将 Markdown 报告导出为 HTML/PDF/DOCX/PPTX。 | +| `ms_agent/utils/push_to_hub.py` | `PushToModelScope`等 | **社区集成**。负责将生成的报告上传到 ModelScope/HuggingFace/GitHub。 | + +## 4. 配置与依赖 + +### 启动命令 +```bash +# 启动 Doc Research 应用 +ms-agent app --app_type doc_research --server_port 7860 +``` + +### 环境变量配置 +该模块主要依赖环境变量进行 LLM 配置 (支持 ModelScope 免费额度): +* `OPENAI_API_KEY`: API 密钥。 +* `OPENAI_BASE_URL`: 接口地址 (如 `https://api-inference.modelscope.cn/v1/`)。 +* `OPENAI_MODEL_ID`: 模型名称 (如 `Qwen/Qwen3-235B-A22B-Instruct-2507`)。 +* `GRADIO_DEFAULT_CONCURRENCY_LIMIT`: 控制并发任务数 (默认 10)。 +* `LOCAL_MODE`: `true/false` (控制是否开启多用户隔离)。 + +### 关键依赖 +* **Gradio**: Web 界面框架。 +* **EasyOCR**: 图片文字识别 (运行时自动下载模型)。 +* **ModelScope**: 模型下载和 API 调用。 +* **Pandoc** (可能): 用于某些格式转换。 + +## 5. 局限性与改进点 +* **状态持久化**: 虽然有 Session 隔离,但重启服务后内存中的用户状态 (`UserStatusManager`) 会丢失,建议接入 Redis。 +* **OCR 性能**: EasyOCR 在无 GPU 环境下较慢,大文件处理耗时较长。 diff --git a/chao-docs/00analysis/ms_agent_project_analysis.md b/chao-docs/00analysis/ms_agent_project_analysis.md new file mode 100644 index 000000000..81f317b38 --- /dev/null +++ b/chao-docs/00analysis/ms_agent_project_analysis.md @@ -0,0 +1,113 @@ +# MS-Agent 项目深度架构分析 + +**日期**: 2025-11-26 +**版本**: 基于 v0.1+ 代码库 +**分析对象**: `ms-agent` 及其子项目 + +## 1. 项目总览 (Overview) +`ms-agent` 是 ModelScope 团队推出的一个轻量级、模块化的 AI Agent 框架。其核心愿景是赋予 Agent **"Autonomous Exploration" (自主探索)** 的能力。 + +**核心特性**: +- **模块化设计**: 将 Agent 拆解为 LLM、Tools、Memory、Workflow 四大支柱。 +- **多场景支持**: 原生支持代码生成 (`code_scratch`)、深度研究 (`deep_research`) 和文档分析 (`doc_research`)。 +- **工具生态**: 深度集成 ModelScope 模型服务,同时兼容 OpenAI API,支持 MCP (Model Context Protocol) 协议。 +- **异步优先**: 核心流程基于 `asyncio`,适合高并发 IO 密集型任务 (如网络爬虫)。 + +## 2. 目录结构详解 (Directory Structure) + +```text +root/ +├── ms_agent/ # [Core] 核心框架源码 +│ ├── agent/ # Agent 基类与实现 (LLMAgent, CodeAgent) +│ ├── llm/ # 大模型适配层 (OpenAI, DashScope, ModelScope) +│ ├── tools/ # 内置工具集 (Search, File, MCP Client) +│ ├── memory/ # 记忆管理 (Short-term, Long-term) +│ ├── rag/ # RAG 模块 (Knowledge Retrieval) +│ ├── workflow/ # 工作流引擎 (ResearchWorkflow) +│ ├── callbacks/ # 回调系统 (用于日志、流式输出、监控) +│ ├── config/ # 配置加载 (OmegaConf, .env) +│ ├── sandbox/ # 代码执行沙箱 (Docker/Local) +│ ├── cli/ # 命令行入口 (ms-agent) +│ └── app/ # Web 应用入口 (Gradio) +│ +├── projects/ # [Projects] 垂直领域应用/示例 +│ ├── code_scratch/ # 全自动代码生成 Agent (架构->编码->修复) +│ ├── deep_research/ # 深度网络研究 Agent (递归搜索->报告生成) +│ ├── doc_research/ # 文档分析 Agent (RAG + 多模态) +│ ├── fin_research/ # 金融研究 Agent +│ └── agent_skills/ # 基础技能演示 +│ +├── orchestrator/ # [Add-on] 新增的编排器模块 (Role A work) +│ ├── core/ # 编排核心逻辑 +│ └── adapters/ # 各个 Projects 的适配器封装 +│ +├── requirements/ # 依赖管理 +│ ├── framework.txt # 核心框架依赖 +│ ├── research.txt # 研究类依赖 (Ray, Docling) +│ └── code.txt # 代码类依赖 +│ +├── docs/ # 文档 (Sphinx/ReadTheDocs) +└── setup.py # 打包脚本 +``` + +## 3. 核心架构解析 (Core Architecture) + +### 3.1 Agent 抽象层 (`ms_agent.agent`) +- **`BaseAgent`**: 定义了 Agent 的生命周期(初始化、思考、行动、观察)。 +- **`LLMAgent`**: 最常用的实现,基于 ReAct 或 Function Calling 模式。它维护一个 `message_history`,并负责与 LLM 交互。 +- **`CodeAgent`**: 专用于代码生成的 Agent,通常集成了 Sandbox 执行能力。 + +### 3.2 工具系统 (`ms_agent.tools`) +- **Tool Protocol**: 采用类 OpenAI 的 Tool Definition 格式。 +- **MCP 支持**: 原生支持 Model Context Protocol,允许 Agent 连接到本地或远程的 MCP Server (如文件系统服务、数据库服务)。 +- **内置工具**: + - `SearchEngine`: 统一封装了 Exa, SerpApi, Google, Arxiv。 + - `FileTool`: 读写本地文件。 + +### 3.3 工作流引擎 (`ms_agent.workflow`) +- 这是一个非常有特色的模块。不同于 LangChain 的 Chain,`ms_agent` 的 Workflow 更像是一个**状态机**或**过程控制器**。 +- **`ResearchWorkflow`**: 实现了 "Search-Read-Synthesize" 的线性或递归流程。它不只是简单的 Prompt 串联,而是包含了复杂的业务逻辑(如去重、内容提取、多模态处理)。 + +### 3.4 配置管理 (`ms_agent.config`) +- 使用 `OmegaConf` 进行 YAML 配置管理,支持层级覆盖。 +- 环境变量 (`.env`) 优先级最高,用于管理敏感信息 (API Keys)。 + +## 4. 子项目解析 (Sub-projects) + +### 4.1 Code Scratch (`projects/code_scratch`) +- **定位**: Repo-level 代码生成。 +- **架构**: 多 Agent 协作 (Architect -> Project Manager -> Worker -> Refiner)。 +- **特点**: + - **Artifacts**: 产出不仅仅是代码,还包括 PRD、设计文档、测试用例。 + - **Iterative**: 具有 "Refine" 阶段,通过运行测试/编译器报错来自我修复。 + +### 4.2 Deep Research (`projects/deep_research`) +- **定位**: 针对开放性问题的深度调研。 +- **特点**: + - **Beta 版 (Recursive)**: 支持“广度”与“深度”配置。Agent 会根据当前发现生成新的追问 (Follow-up questions),递归地进行搜索。 + - **多模态**: 能抓取网页中的图片并生成图文并茂的报告。 + - **Ray 加速**: 使用 Ray 框架并行化网页抓取和解析任务。 + +### 4.3 Doc Research (`projects/doc_research` & `ms_agent/app/doc_research.py`) +- **定位**: 针对特定文档 (PDF/URL) 的精准问答与总结。 +- **技术栈**: RAG + OCR (EasyOCR) + Gradio。 +- **流程**: + 1. 解析文档 (Docling/PDFMiner)。 + 2. OCR 识别图片文字。 + 3. 提取关键信息 (Key Information Extraction)。 + 4. LLM 总结与生成。 + +## 5. 开发与扩展生态 + +### 5.1 CLI (`ms-agent`) +- 通过 `setup.py` 的 `entry_points` 注册。 +- 支持 `ms-agent run` (运行 Agent) 和 `ms-agent app` (启动 Web UI)。 + +### 5.2 Orchestrator (新增) +- 这是一个**元框架 (Meta-Framework)** 层。 +- 它的出现是为了解决“如何将上述独立的 Projects 串联起来”的问题。 +- 通过 **Adapter 模式**,它将 `projects/` 下的独立应用转化为了可调用的 Library,实现了 `Research -> Spec -> Code` 的端到端自动化。 + +## 6. 总结 +`ms-agent` 是一个工程化程度很高的框架。它没有过度封装 Prompt 技巧,而是专注于**工具调用**、**工作流编排**和**工程落地** (如并行加速、错误恢复)。 +其 `projects/` 目录下的应用展示了框架的强大扩展性,而新增的 `orchestrator` 则进一步证明了其模块的可复用性。 diff --git a/chao-docs/00analysis/orchestrator_structure_analysis.md b/chao-docs/00analysis/orchestrator_structure_analysis.md new file mode 100644 index 000000000..120372e4d --- /dev/null +++ b/chao-docs/00analysis/orchestrator_structure_analysis.md @@ -0,0 +1,120 @@ +# Orchestrator 模块深度分析与结构说明 + +**日期**: 2025-11-26 +**版本**: v0.1 (Initial Architecture) +**对应命令**: `python3 orchestrator/main.py ...` + +## 1. 命令解析 +当您执行以下命令时: +```bash +python3 orchestrator/main.py "Build a calculator based on this requirement doc" --files ./req.txt +``` + +系统内部发生了以下流转: +1. **入口 (`main.py`)**: 接收命令行参数。解析出 `query` 为 "Build a calculator...",并检测到 `--files` 参数。 +2. **初始化 (`core/`)**: + * 加载配置 (`config.py`)。 + * 创建一个新的带时间戳的工作目录 (`workspace/run_xxxx/`)。 + * 初始化日志系统 (`utils/logger.py`)。 +3. **Phase 1 (Research)**: + * 由于检测到 `--files`,系统智能选择 `DocResearchAdapter`。 + * 适配器调用底层的 `ms_agent` 文档分析能力,读取 `req.txt`,生成 `report.md` 并保存到工作区。 +4. **Phase 2-4 (Generation & Coding)**: + * (当前为 Mock) 读取 `report.md`,生成技术规格书 `tech_spec.md`。 + * (当前为 Mock) 基于规格书生成测试用例 `tests/`。 + * (当前为 Mock) 生成代码 `src/`。 +5. **验证**: 运行 `pytest` 检查生成的代码是否通过测试。 + +--- + +## 2. 项目结构深度解析 (`orchestrator/`) + +`orchestrator` 模块设计遵循 **"洋葱架构" (Onion Architecture)** 和 **"适配器模式" (Adapter Pattern)**,旨在不修改上游代码的前提下,将现有能力串联成复杂流水线。 + +```text +orchestrator/ +├── main.py # [CLI入口] +│ # 程序的"大门"。负责参数解析(Argparse)、异常捕获顶层逻辑、 +│ # 以及各个阶段(Phase 1-4)的宏观调度。 +│ +├── core/ # [核心领域层] (Business Logic) +│ ├── config.py # 配置中心。统一管理 API Keys、模型名称、重试次数。 +│ │ # 优先读取环境变量,支持 .env 文件。 +│ │ +│ ├── workspace.py # 战场环境管理。 +│ │ # 职责:每次任务都在 workspace/ 下创建一个隔离的 +│ │ # run_YYYYMMDD_HHMMSS 目录,防止任务间文件冲突。 +│ │ # 提供 get_path() 方法,统一管理文件路径。 +│ │ +│ ├── flow.py # 交互流控制器。 +│ │ # 职责:实现 "Human-in-the-Loop"。在关键节点(如Spec生成后) +│ │ # 暂停程序,等待用户审查/修改文件,然后继续。 +│ │ +│ ├── templates.py # 提示词与文档模板。 +│ │ # 定义了 report.md 和 tech_spec.md 的标准 Markdown 结构。 +│ │ +│ └── const.py # 常量定义。文件名(如 report.md)的唯一定义处。 +│ +├── adapters/ # [适配器层] (Interface Adapters) +│ │ # 核心设计模式:将外部不稳定的接口转换为内部稳定的接口。 +│ │ +│ ├── base.py # 抽象基类。定义了所有 Agent 必须实现的 run() 方法标准。 +│ │ +│ ├── doc_research_adapter.py # Doc Research 适配器。 +│ │ # 作用:封装 ms_agent.workflow,屏蔽 Gradio UI 依赖, +│ │ # 仅调用核心文档分析逻辑。 +│ │ +│ ├── deep_research_adapter.py# Deep Research 适配器。 +│ │ # 作用:根据配置自动选择 Arxiv/Exa/SerpApi 引擎, +│ │ # 执行联网深度搜索。 +│ │ +│ ├── spec_adapter.py # [Mock] Spec 生成适配器 (Role B)。 +│ ├── test_gen_adapter.py # [Mock] 测试生成适配器 (Role B)。 +│ └── code_adapter.py # [Mock] 代码生成适配器 (Role C)。 +│ +└── utils/ # [基础设施层] (Infrastructure) + ├── logger.py # 双路日志。 + │ # Console: 输出简洁的 INFO 信息给用户看。 + │ # File: 输出详细的 DEBUG 信息到 logs/orchestrator.log 供调试。 + │ + └── verifier.py # 验证器。 + # 封装 subprocess 调用 pytest,返回 (exit_code, stdout, stderr), + # 为外循环(Outer Loop)提供反馈信号。 +``` + +--- + +## 3. 运行时目录结构 (`workspace/`) + +这是您执行命令后,实际产出物存放的地方。它被设计为**完全自包含**的,意味着您可以直接打包某个 `run_xxx` 目录发给别人,里面包含了从需求到代码的所有过程资产。 + +```text +workspace/ +└── run_20251126_130922/ # [任务容器] 以时间戳命名,隔离每次运行 + │ + ├── report.md # [阶段1产出] 研究报告 + │ # 包含:从 req.txt 或网络搜索中提取的关键知识、API定义建议。 + │ + ├── tech_spec.md # [阶段2产出] 技术规格书 + │ # 包含:系统架构、文件结构、API签名。这是连接 Research 和 Code 的桥梁。 + │ + ├── tests/ # [阶段3产出] 测试用例 + │ └── test_core.py # 基于 Spec 生成的自动化测试代码 (Pytest)。 + │ + ├── src/ # [阶段4产出] 源代码 + │ └── main.py # Agent 编写的实际业务代码。 + │ + └── logs/ # [系统日志] + └── orchestrator.log # 记录了每一步的 LLM 调用、Token 消耗、错误堆栈。 +``` + +## 4. 设计理念总结 + +1. **无侵入 (Non-Invasive)**: + 我们没有修改 `ms_agent` 或 `projects/` 下的任何一行既有代码。所有的集成都是通过 `import` 和 `adapters` 封装实现的。这保证了上游仓库更新时,我们的编排器不会轻易损坏。 + +2. **数据驱动 (Data-Driven Flow)**: + 流程不是通过函数调用栈隐式传递的,而是通过文件系统上的**显式工件** (Artifacts: report.md -> spec.md -> code) 传递的。这使得人工可以随时介入(修改 Markdown 文件),Agent 也能理解上下文。 + +3. **外循环 (Outer Loop)**: + Code Generator 不再是“一锤子买卖”。`main.py` 中包含一个 `while` 循环,利用 `verifier.py` 的反馈结果,如果测试失败,会自动把错误日志喂回给 Coding Agent 进行重试。 diff --git a/chao-docs/00analysis/workflow_comparison.md b/chao-docs/00analysis/workflow_comparison.md new file mode 100644 index 000000000..b53c45b77 --- /dev/null +++ b/chao-docs/00analysis/workflow_comparison.md @@ -0,0 +1,94 @@ +# ChainWorkflow vs DagWorkflow 深度对比分析 + +**日期**: 2025-11-26 +**分析对象**: `ms_agent/workflow/chain_workflow.py`, `ms_agent/workflow/dag_workflow.py` + +## 1. 概述 + +在 `ms-agent` 框架中,Workflow 定义了 Agent 之间的协作模式与数据流转方式。框架提供了两种核心的工作流实现: +1. **ChainWorkflow**: 链式工作流,适用于顺序执行、可能包含循环的场景。 +2. **DagWorkflow**: 有向无环图工作流,适用于复杂的依赖管理、分支与合并场景。 + +--- + +## 2. ChainWorkflow (链式工作流) + +### 2.1 核心逻辑 +* **结构**: 单链表结构。每个任务节点只能有一个 `next` 指向。 +* **构建方式**: 寻找没有前驱的节点作为 `start_task`,然后沿着 `next` 指针构建线性链表 `self.workflow_chains`。 +* **执行模式**: + * 按顺序依次实例化并执行 Agent。 + * **上一步的输出 = 下一步的输入** (Pipeline 模式)。 + * **支持循环 (Looping)**: 代码中包含 `next_idx` 和 `step_inputs` 逻辑,允许 Agent 通过 `next_flow` 返回到之前的步骤(例如:Coding -> Testing -> (Fail) -> Coding)。 + +### 2.2 关键代码特征 +```python +# 只能有一个 next +assert len(next_tasks) == 1, 'ChainWorkflow only supports one next task' + +# 循环支持逻辑 +if next_idx == idx + 1: + inputs = outputs # 正常前进 +else: + inputs, agent_config = step_inputs[next_idx] # 回溯/循环 +``` + +### 2.3 适用场景 +* **顺序处理管道**: 如 "爬取数据 -> 数据清洗 -> 存入数据库"。 +* **迭代优化循环**: 如 "生成代码 -> 运行测试 -> (失败则)修复代码 -> 运行测试"。 +* **多轮对话**: 用户与 Agent 之间线性的问答交互。 + +--- + +## 3. DagWorkflow (DAG 工作流) + +### 3.1 核心逻辑 +* **结构**: 有向无环图 (DAG)。一个任务可以有多个 `next` (分支),也可以有多个前驱 (合并)。 +* **构建方式**: + * 构建邻接表 `self.graph` 和入度表 `indegree`。 + * 使用 **Kahn 算法** 进行拓扑排序 (`self.topo_order`),确保障碍依赖关系被正确解析。 +* **执行模式**: + * 严格按照拓扑序执行任务。 + * **输入聚合**: 如果一个节点有多个父节点(多对一合并),它会收到一个包含所有父节点输出的**列表**;如果是单父节点,则收到单个输出。 + * **结果输出**: 返回所有“终端节点”(没有后继节点的节点)的输出字典。 + +### 3.2 关键代码特征 +```python +# 支持多个 next (分支) +if isinstance(next_tasks, str): + next_tasks = [next_tasks] +for nxt in next_tasks: + self.graph[task_name].append(nxt) + +# 输入聚合 (合并) +task_input = parent_outs if len(parent_outs) > 1 else parent_outs[0] +``` + +### 3.3 适用场景 +* **复杂依赖任务**: 任务 C 必须等待 任务 A 和 任务 B 都完成后才能开始。 +* **Map-Reduce 模式**: + * Step 1: 将问题拆分为 3 个子问题 (分支)。 + * Step 2: 3 个 Agent 并行(逻辑上)处理子问题。 + * Step 3: 1 个 Summarizer Agent 汇总 3 个结果 (合并)。 +* **并行研究**: 同时搜索 Google 和 Arxiv,然后聚合结果。 + +--- + +## 4. 核心区别对比 (Key Differences) + +| 特性 | ChainWorkflow | DagWorkflow | +| :--- | :--- | :--- | +| **拓扑结构** | 线性 (Linear) | 图状 (Graph) | +| **分支能力** | 不支持 (1对1) | **支持** (1对多) | +| **合并能力** | 不支持 | **支持** (多对1,自动聚合输入) | +| **循环能力** | **支持** (通过索引回溯) | 不支持 (DAG 定义即无环) | +| **数据流转** | 管道式 (Pipeline),直接透传 | 依赖式,支持多源汇聚 | +| **输出结果** | 最后一个节点的输出 | 所有终端节点(Leaf Nodes)的输出字典 | +| **主要用途** | 迭代、对话、简单流水线 | 分治策略、多源信息整合、复杂逻辑 | + +## 5. 总结与建议 + +1. **优先选择 ChainWorkflow**: 如果您的任务是线性的,或者需要**“试错-重试”的循环机制**(例如写代码直到通过测试)。ChainWorkflow 的状态管理更适合处理这种回退逻辑。 +2. **优先选择 DagWorkflow**: 如果您的任务可以被**拆解并行**处理,或者某个步骤强依赖于多个上游步骤的产出(例如写报告前必须同时拥有“市场数据”和“技术文档”)。 + +**注意**: 虽然 `DagWorkflow` 实现了 DAG 结构,但在当前的 `run` 方法实现中,它依然是使用 `await` 也就是**串行**执行拓扑序的。如果需要真正的并行加速(如同时发起两个网络请求),可能需要修改底层 `run` 方法以支持 `asyncio.gather`。 diff --git a/chao-docs/01goals/00comprehensive_integration_plan.md b/chao-docs/01goals/00comprehensive_integration_plan.md new file mode 100644 index 000000000..90141f4e6 --- /dev/null +++ b/chao-docs/01goals/00comprehensive_integration_plan.md @@ -0,0 +1,191 @@ +# Research-to-Code 全链路实施方案 (Non-Invasive SOTA Edition) + +## 1. 背景与目标 +当前 `seu-ms-agent` 仓库中,`doc_research`、`deep_research` 和 `code_scratch` 是三个独立且成熟的模块,且上游持续更新。 +**核心约束**:**严禁修改现有模块的内部实现**(如 `ms_agent/` 核心代码或 `projects/` 下的现有逻辑),以避免合并冲突。 +**目标**:通过 **外部编排 (External Orchestration)** 和 **适配器模式 (Adapter Pattern)**,将这三个“黑盒”模块串联成一个符合 SOTA 标准的自动化流水线。 + +## 2. 行业 SOTA 架构深度调研与理论溯源 + +本方案综合了 **AWS**、**OpenAI**、**DeepMind** 及开源社区的最新成果,采用 **"无侵入式编排"** 策略。 + +### 2.1 核心模式对比与溯源 +| 模式 | 理论/项目来源 | 核心思想 | 本方案应用 | +| :--- | :--- | :--- | :--- | +| **Plan-Execute (计划-执行)** | **AWS Amazon Q Developer** | 强制生成 "Plan" 并 Review。 | **Phase 1.5: Spec Adapter**。在 Research 和 Code 之间插入一个独立的“规划转化”步骤。 | +| **Test-Driven Generation** | **DeepMind AlphaCodium** | 先生成测试,再生成代码。 | **Phase 2: External Test Gen**。在调用 Code Scratch 前,先在工作区预置测试用例。 | +| **Human-in-the-Loop** | **OpenAI O1 / SWE-bench** | 关键节点的人工确认能大幅降低幻觉风险。 | **Phase 2.5: Human Review**。允许用户在生成测试前修订 Spec。 | + +## 3. 架构设计:无侵入式 R-S-T-C 流水线 + +我们保持 `doc_research`、`deep_research`、`code_scratch` 代码**一字不动**,将它们视为 **CLI 工具** 或 **Library**。通过一个外部的 `Orchestrator` 脚本来管理数据流。 + +### 3.1 角色与组件 +1. **Orchestrator (编排器)**: 全局控制器,负责调用各模块,管理工作目录,处理异常与重试。 +2. **Research Module (原样复用)**: + * **Deep Research**: 调用 `projects/deep_research`,用于开放域搜索。 + * **Doc Research**: 调用 `ms_agent/app/doc_research.py` (或底层 `ResearchWorkflow`),用于特定文档/URL分析。 + * 输出: `report.md` (自然语言)。 +3. **Spec Adapter (新增适配器)**: + * **独立 Agent**。 + * 输入: `report.md`。 + * 输出: `tech_spec.md` (结构化), `api_definitions.json`。 + * 作用: 将“作文”翻译成“蓝图”。 +4. **Test Generator (新增生成器)**: + * **独立 Agent**。 + * 输入: `tech_spec.md`。 + * 输出: `tests/test_*.py` (写入工作区)。 + * 作用: 预置 AlphaCodium 风格的测试用例。 +5. **Coding Module (原样复用)**: + * 调用 `projects/code_scratch`。 + * **Prompt Injection**: 通过构造特殊的 `Query`,引导它读取预置的 Spec 和 Tests。 + +### 3.2 数据流转图 +```mermaid +graph TD + User[用户输入] --> Orch[Orchestrator 脚本]; + Orch -->|1. 分流| Branch{有无附件?}; + Branch -->|无附件| Deep[Deep Research (Web Search)]; + Branch -->|有附件/URL| Doc[Doc Research (File Analysis)]; + + Deep -->|产出| Report[report.md]; + Doc -->|产出| Report; + + Report -->|2. 输入| Adapter[Spec Adapter (New Agent)]; + Adapter -->|清洗/结构化| Spec[tech_spec.md]; + + Spec -->|2.5 人工确认 (可选)| Human{Human Review}; + Human -->|修订| Spec; + + Spec -->|3. 输入| TestGen[Test Generator (New Agent)]; + TestGen -->|产出| Tests[tests/test_core.py]; + + Spec & Tests -->|4. 注入 Workspace| Workspace; + + Orch -->|5. 构造 Prompt| Prompt["任务:实现功能... \n 参考:请严格遵循当前目录下的 tech_spec.md 并通过 tests/ 中的测试"]; + Prompt -->|6. 调用| Code[Code Scratch (Blackbox)]; + Code -->|读取| Workspace; + Code -->|产出| FinalCode[最终代码]; + + FinalCode -->|7. 验证| Verifier{Orchestrator 验证}; + Verifier -->|测试通过| Success[交付]; + Verifier -->|测试失败| Retry[重试 (带 Error Log)]; + Retry -->|8. 再次调用| Code; +``` + +## 4. 详细实施步骤 + +### Phase 1: Research (Blackbox Call) +**目标**:获取高质量的领域知识和上下文。 +**操作逻辑**: +1. Orchestrator 接收用户 Query 和可选的附件/URL。 +2. **模式选择**: + * **Deep Research 模式**:如果用户仅提供 Query,调用 `projects/deep_research` 进行全网搜索。 + * **Doc Research 模式**:如果用户提供了 PDF/文档/URL,调用 `ResearchWorkflow` (参考 `ms_agent/app/doc_research.py`) 并传入 `urls_or_files` 参数。 + 2选1,or 并行 +3. 指定输出目录为当前任务的工作区。 +4. **验证**:检查是否生成了 `report.md`。如果失败,允许用户手动上传文档或提供 URL 作为替代。 + +### Phase 2: Spec & Test Generation (The Glue) +**目标**:将非结构化的自然语言报告转化为结构化的工程蓝图。这是连接 Research 和 Code 的关键“胶水层”。 +**操作逻辑**: +1. **Spec Generation**: + * - 读取 `report.md`,给下游coding agent的。 + * - 全面的用来阅读的report ` 给人看的report.md 或者其他格式` + * 使用高智商模型提取关键技术约束(API 签名、数据结构、依赖版本)。 + * 关键技术约束,**结合demo**,可能需要硬编码something + * 生成 `tech_spec.md`。 +2. **Human Review (关键环节)**: + * Orchestrator 暂停流程。 + * 提示用户检查 `tech_spec.md`。用户可以直接选择/编辑文件来修正理解偏差。 + * 用户确认后继续。 +3. **Test Generation (AlphaCodium Pattern)**: + * 读取最终确认的 `tech_spec.md`。 + * 生成 `pytest` 测试用例 (`tests/test_core.py`)。 + * 测试用例应该在coding过程中写,一个模块一个模块去写 + * **重点**:测试用例应包含 Happy Path 和 Edge Cases,且必须独立于实现代码运行。 + +### Phase 3: Coding (Prompt Engineering Injection) +**目标**:利用现有的 Coding Agent 实现功能,但强制其遵循我们的 Spec 和 Test。 +**操作逻辑**: +1. **Context Injection (上下文注入)**: + * 构造一个 **"Meta-Instruction" (元指令)** Prompt。 + * Prompt 核心内容:“不要从零开始设计。我已为你准备了 `tech_spec.md` 和 `tests/`。请读取它们,并编写代码以通过测试。” +2. **Blackbox Execution**: + * 调用 `projects/code_scratch` 模块。 + * 将构造好的 Prompt 作为任务输入。 + * 设置工作目录为包含 Spec 和 Tests 的目录。 +3. **Outer Loop Verification (外循环验证)**: + * Coding 结束后,Orchestrator 运行 `pytest`。 + * **Success**: 测试通过 -> 交付。 + * **Failure**: 捕获错误日志 -> 构造“修复任务” Prompt -> 再次调用 Coding Module (Retry)。 + * **Max Retries**: 超过重试次数则人工介入。 + +## 5. 运营与配置 (Operational Excellence) + +### 5.1 目录结构规范 +为了保证多次运行不冲突,建议采用基于时间戳的工作区管理: +``` +workspace/ + run_20251121_1000/ + report.md (Phase 1 Output) + tech_spec.md (Phase 2 Output) + tests/ (Phase 2 Output) + test_core.py + src/ (Phase 3 Output) + main.py + logs/ (Orchestrator Logs) +``` + +### 5.2 模型策略 (Model Strategy) +* **Research**: 使用 `gpt-4o-mini` 或 `haiku` 以降低大量阅读的成本。 +* **Spec & Test**: 必须使用 **SOTA 模型** (`gpt-4o`, `claude-3-5-sonnet`),因为这是整个系统的“大脑”。如果 Spec 错了,后面全错。 +* **Coding**: `code_scratch` 默认配置的模型(通常也是强模型)。 + +## 6. 优势分析 +1. **零侵入 (Zero Intrusion)**: 不需要修改 `ms_agent` 或 `projects/` 下的任何一行代码。上游更新,我们直接 pull 即可。 +2. **解耦 (Decoupling)**: Research 模块想换成别的?Code 模块想换成别的?改一下 `orchestrator.py` 即可,模块间互不依赖。 +3. **SOTA 能力保留**: 虽然没改内部代码,但通过 **"Prompt Injection"** 和 **"Workspace Pre-seeding"** (预置文件),我们依然实现了 Spec-First 和 Test-Driven 的高级流程。 +4. **鲁棒性 (Robustness)**: 增加了 Human Review 和 Outer Loop 重试机制,使其真正具备生产可用性。 + +## 7. 总结 +本方案通过 **"外部编排 + 上下文注入"** 的方式,完美平衡了 **"引入先进架构"** 与 **"维护上游兼容性"** 的矛盾。它就像一个指挥家(Orchestrator),指挥着三个顶级乐手(现有模块)协同演奏,而不需要教乐手如何拉琴。 + +## 8. 团队分工方案 (Team Roles & Responsibilities) + +基于本项目 **"非侵入式编排"** 与 **"黑盒集成"** 的技术特性,建议三人团队按 **“流水线阶段”** 与 **“技能栈侧重”** 进行分工。此分工旨在最大化并行开发效率,同时确保各模块接口(Interface)的清晰定义。 + +### 成员 A: 核心架构与编排 (System Architect & Orchestrator)-fyc +**定位**: 系统的“骨架”与“神经中枢”,负责数据流转、状态管理及核心对象封装。 +**技术要求**: 熟练掌握 Python 高级编程、进程管理、文件系统操作。 +**核心职责**: +1. **Orchestrator 主程序**: 开发 `orchestrator.py`,实现 CLI 入口、参数解析、工作区目录生命周期管理 (`workspace/run_timestamp/`)。 +2. **Doc Research 深度集成**: 深入阅读 `ms_agent/app/doc_research.py`,绕过 Gradio 层直接封装底层 `ResearchWorkflow` 类,实现对本地文件/URL 的分析调用。 +3. **交互控制 (Human-in-the-Loop)**: 实现控制台的交互逻辑(如:暂停流水线、等待用户选择/编辑 `tech_spec.md`、接收确认指令后继续)。 +4. **全链路联调**: 负责最终将各成员开发的模块串联,确保数据在 Phase 1 到 Phase 3 之间无损流转。 + +### 成员 B: 智能体适配与提示工程 (Agent Specialist & Prompt Engineering)-wyh +**定位**: 系统的“大脑”,负责 Phase 2 的核心逻辑,即“自然语言”到“工程语言”的转译。 +**技术要求**: 精通 LLM Prompt 设计、熟悉软件工程文档规范、了解测试驱动开发 (TDD)。 +**核心职责**: +1. **Spec Adapter (Agent)**: 设计高鲁棒性的 Prompt,负责读取 `report.md` 并提取出精确的 `tech_spec.md`(包含 API 签名、数据结构、依赖库版本)。这是项目成败的关键。 +2. **Test Generator (Agent)**: 基于 AlphaCodium 理念,设计 Prompt 让 LLM 根据 Spec 生成可执行的 `pytest` 测试用例 (`tests/test_core.py`)。 +3. **Prompt 迭代与评测**: 建立简单的评测集,反复调优 Prompt,确保生成的 Spec 不产生幻觉,生成的测试代码语法正确且覆盖边界条件。 + +### 成员 C: 外部工具集成与验证闭环 (Integration Engineer & Verification Loop)-skx +**定位**: 系统的“双手”与“质检员”,负责外部黑盒工具的调用及代码质量的自动化验证。 +**技术要求**: 熟悉 Subprocess/Shell 调用、Pytest 测试框架、日志分析。 +**核心职责**: +1. **Deep Research & Coding 集成**: 负责 `projects/deep_research` 和 `projects/code_scratch` 的黑盒调用封装(可能涉及环境隔离或子进程调用)。 +2. **Prompt Injection 构造**: 实现 Phase 3 的核心逻辑——构造“元指令” (Meta-Instruction),将成员 B 生成的 Spec 和 Test 巧妙地注入到 Coding Agent 的上下文中。 +3. **外循环验证 (Outer Loop)**: 开发自动化测试执行模块,运行 `pytest`,捕获 stdout/stderr,并从错误日志中提取关键信息,构造“修复任务”反馈给 Coding Agent 实现自动重试。 + +--- + +**协作里程碑 (Milestones)**: +1. **接口定义 (Day 1)**: 全员共同商定 `report.md`、`tech_spec.md` 的标准模板结构,以及各 Python 模块的输入输出接口。 +2. **模块开发 (Day 2-4)**: + * A 完成编排器框架与 Doc 接口; + * B 完成 Spec/Test 生成的 Prompt 验证; + * C 完成 Deep/Code 模块的黑盒调用与测试运行器。 +3. **集成联调 (Day 5)**: 串联 Phase 1 -> 2 -> 3,进行端到端测试。 diff --git a/chao-docs/01goals/image.png b/chao-docs/01goals/image.png new file mode 100644 index 0000000000000000000000000000000000000000..529c7fbe160b4ac4550217fd000432f4fa508878 GIT binary patch literal 515260 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⩔#HU9@LoVYC8q)0k^9&H1rGT=e{Qu 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%0DR&6l9cjEBgo)&PDeR@H~@WfxVng%(jp- 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 Spec -> Test -> Code` 的数据流转标准。 +4. **外循环机制 (Outer Loop)**: 实现了 "Code -> Verify (Pytest) -> Retry" 的自动修复闭环逻辑。 +5. **Mock 占位**: 为 Role B (Spec/Test) 和 Role C (Code) 提供了 Mock 实现,确保在队友代码就位前,主流程可跑通。 +6. **交互控制**: 实现了 `wait_for_human_review`,支持用户在流程中间暂停并修改生成的 Spec 文档。 + +## 3. 使用指南 (User Guide) + +### 3.1 环境准备 + +确保安装了项目依赖: + +```bash +pip install -r requirements/framework.txt +``` + +设置必要的环境变量 (在 `.env` 文件或 export): + +```bash +export OPENAI_API_KEY="sk-xxx" +# export MODELSCOPE_API_KEY="xxx" # 如果使用 ModelScope +# export EXA_API_KEY="xxx" # 可选:用于 Deep Research 增强搜索 +``` + +### 3.2 快速演示 (Demo Script) + +使用提供的脚本一键运行全流程(包含 Research -> Mock Spec -> Mock Code -> Mock Verify): + +```bash +# 给予执行权限 +chmod +x scripts/demo_orchestrator.sh + +# 运行 (默认 Query: "Help me build a snake game with Python") +./scripts/demo_orchestrator.sh + +# 自定义 Query +./scripts/demo_orchestrator.sh "Analyze the current state of AI Agents" +``` + +### 3.3 CLI 详细用法 + +您也可以直接使用 Python 调用 CLI: + +**场景 A: 纯网络研究 (Deep Research)** + +```bash +python3 orchestrator/main.py "Recent advances in LLM reasoning" --mode research_only +``` + +**场景 B: 基于文档的研究 (Doc Research)** + +```bash +python3 orchestrator/main.py "Summarize this paper" --files ./paper.pdf --mode research_only +``` + +**场景 C: 全流程生成 (Research -> Code)** + +```bash +python3 orchestrator/main.py "Build a calculator based on this requirement doc" --files ./req.txt +``` + +_(注:目前 Phase 2-4 为 Mock 实现,仅生成占位文件)_ + +### 3.4 产出物位置 + +每次运行都会在 `workspace/` 目录下生成一个带时间戳的文件夹,结构如下: + +```text +workspace/run_20251126_120000/ +├── report.md # Research 阶段产出 +├── tech_spec.md # Spec 阶段产出 +├── tests/ # Test Gen 阶段产出 +│ └── test_core.py +├── src/ # Coding 阶段产出 +│ └── main.py +└── logs/ + └── orchestrator.log # 详细运行日志 +``` + +## 4. 给 Role B & C 的交接说明 + +- **Role B (Spec/Test Agent)**: + - 请修改 `orchestrator/adapters/spec_adapter.py`,接入真实的 Spec 生成 Agent。 + - 请修改 `orchestrator/adapters/test_gen_adapter.py`,接入真实的测试生成 Agent。 + - 输入/输出路径已在 `BaseAdapter` 中规范化。 +- **Role C (Coding Agent)**: + - 请修改 `orchestrator/adapters/code_adapter.py`,接入真实的 `Code Scratch` 或其他 Coding Agent。 + - 请利用 `error_log` 参数实现修复逻辑。 diff --git a/chao-docs/02todos/0.1_Role_A_Orchestrator_Plan.md b/chao-docs/02todos/0.1_Role_A_Orchestrator_Plan.md new file mode 100644 index 000000000..c7425ddcd --- /dev/null +++ b/chao-docs/02todos/0.1_Role_A_Orchestrator_Plan.md @@ -0,0 +1,112 @@ +# Role A: Orchestrator 实施计划 (System Architect) + +**责任人**: A (fyc) +**目标**: 构建 "Research-to-Code" 全链路的指挥中枢,实现各模块的无侵入式调度与数据流转。 +**依据**: [00comprehensive_integration_plan.md](../01goals/00comprehensive_integration_plan.md) + +--- + +## 阶段 0: 架构定义与接口规范 (Day 1) +> **目标**: 确立项目骨架,定义与 Role B (Spec/Test) 和 Role C (Coding/Verify) 的交互契约。 + +- [x] **0.1 初始化编排器项目结构** + - 创建目录结构: + ```text + orchestrator/ + ├── __init__.py + ├── main.py # CLI 入口 + ├── core/ # 核心逻辑 + │ ├── workspace.py # 工作区管理 + │ ├── flow.py # 流程控制 + │ └── config.py # 配置管理 + ├── adapters/ # 适配器层 (对接各个Agent) + │ ├── research_adapter.py + │ └── ... (B/C 接口预留) + └── utils/ + ``` +- [x] **0.2 定义数据流转契约 (Markdown Templates)** + - [x] 定义 `report.md` (Phase 1 Output) 的标准结构(与 Role B 确认)。 + - [x] 定义 `tech_spec.md` (Phase 2 Output) 的标准结构(与 Role B 确认)。 + - [x] 定义 `tests/` 目录的输出规范(与 Role C 确认)。 +- [x] **0.3 编写配置管理模块** + - [x] 实现 `orchestrator/core/config.py`,支持加载 `config.yaml` 或环境变量(用于配置 API Keys、模型参数、最大重试次数等)。 + +--- + +## 阶段 1: 核心编排器开发 (Day 2) +> **目标**: 实现 CLI 入口和工作区生命周期管理,确保“战场”有序。 + +- [x] **1.1 实现 Workspace Manager (`core/workspace.py`)** + - [x] 功能:每次运行创建一个独立的时间戳目录 `workspace/run_YYYYMMDD_HHMMSS/`。 + - [x] 功能:提供 `get_path(filename)` 方法,统一管理文件路径,避免硬编码。 + - [x] 功能:初始化 `logs/orchestrator.log`,配置 Python `logging` 模块同时输出到控制台和文件。 +- [x] **1.2 实现 CLI 入口 (`main.py`)** + - [x] 使用 `argparse` 或 `click` 解析参数: + - `--query`: 用户需求。 + - `--files`: (可选) 本地文件路径列表。 + - `--urls`: (可选) 待研读 URL 列表。 + - `--mode`: `research_only` | `full` (方便调试)。 + - [x] 实现基础的 `try-catch` 块,确保程序崩溃时能保存错误日志。 + +--- + +## 阶段 2: Research 模块适配 (Day 3) +> **目标**: “无侵入”地复用 `ms_agent` 现有的 Research 能力。 + +- [x] **2.1 深度分析 `doc_research` 源码** + - [x] 阅读 `ms_agent/app/doc_research.py`,定位 `ResearchWorkflow` 及其依赖。 + - [x] 确认如何传入 `openai_api_key` 和 `model` 等配置而不依赖环境变量。 +- [x] **2.2 实现 Doc Research 适配器 (`adapters/research_adapter.py`)** + - [x] **类**: `DocResearchAdapter` + - [x] **功能**: 接收文件路径列表,初始化 `ResearchWorkflow`,执行分析。 + - [x] **输出**: 将生成的 Markdown 报告保存为 `workspace/.../report.md`。 + - [x] **测试**: 编写单元测试 `tests/test_doc_adapter.py`,验证能否不启动 Gradio 直接生成报告。 +- [x] **2.3 实现 Deep Research 适配器 (`adapters/research_adapter.py`)** + - [x] **类**: `DeepResearchAdapter` + - [x] **功能**: 封装 `projects/deep_research` 的调用(优先考虑 `subprocess` 调用以保证环境隔离,或直接 import `projects.deep_research.run` 里的核心逻辑)。 + - [x] **策略**: 统一 Deep 和 Doc 的输出接口,都产出 `report.md`。 + +--- + +## 阶段 3: 交互控制与流程串联 (Day 3-4) +> **目标**: 实现 Human-in-the-Loop (HITL) 机制,并串联 Role B 和 Role C 的工作。 + +- [x] **3.1 实现交互控制器 (`core/flow.py`)** + - [x] **功能**: `InteractionManager.request_review(file_path)`。 + - [x] **逻辑**: + 1. 打印:“请检查并编辑生成的文档: [路径]” + 2. 暂停程序执行。 + 3. 等待用户输入 "c" (continue) 或 "r" (reload)。 + 4. 如果用户修改了文件,重新加载文件内容。 +- [x] **3.2 集成 Spec Adapter (对接 Role B)** + - [x] 在 `orchestrator.py` 中预留调用 Role B 代码的位置。 + - [x] 模拟输入:读取 `report.md`。 + - [x] 模拟输出:检查 `tech_spec.md` 是否生成。 +- [x] **3.3 集成 Code Generator (对接 Role C)** + - [x] 在 `orchestrator.py` 中预留调用 Role C 代码的位置。 + - [x] 传递参数:`tech_spec.md` 路径, `tests/` 路径。 + +--- + +## 阶段 4: 全链路联调与外循环 (Day 5) +> **目标**: 跑通 "User Query -> Research -> Spec -> Test -> Code -> Verify" 闭环。 + +- [x] **4.1 实现主流程逻辑 (`Orchestrator.run()`)** + - [x] 串联:Input -> ResearchAdapter -> report.md + - [x] 串联:report.md -> SpecAdapter (Role B) -> tech_spec.md + - [x] **HITL**: 调用 `request_review('tech_spec.md')` + - [x] 串联:tech_spec.md -> TestGen (Role B) -> tests/ + - [x] 串联:Meta-Prompt 构造 -> CodeAdapter (Role C) -> src/ +- [x] **4.2 实现外循环重试机制 (Outer Loop)** + - [x] 接收 Role C 返回的测试结果(Exit Code / Error Log)。 + - [x] 判断:如果失败且 `retry_count < MAX_RETRIES`,触发重试。 + - [x] 重试逻辑:将 Error Log 附加到 Prompt,再次调用 CodeAdapter。 +- [x] **4.3 端到端演示验证** + - [x] 准备测试用例:“基于提供的 PDF 论文,实现其中的核心算法 Demo”。 + - [x] 验证最终产出的代码能否通过预置测试。 + +--- + +## 依赖项 +- 需要 Role B 提供 `SpecGenerator` 类/接口。 +- 需要 Role C 提供 `CodeRunner` 类/接口及 `pytest` 封装。 diff --git a/chao-docs/02todos/1.0_Core_Architecture_Tasks.md b/chao-docs/02todos/1.0_Core_Architecture_Tasks.md new file mode 100644 index 000000000..ae191d8c3 --- /dev/null +++ b/chao-docs/02todos/1.0_Core_Architecture_Tasks.md @@ -0,0 +1,59 @@ +# Phase 1: 核心架构与基础组件任务清单 + +**对应阶段**: Phase 0 & Phase 1 +**目标**: 建立稳固的 `orchestrator` 项目骨架,实现配置管理、工作区管理和 CLI 入口,为后续模块提供运行环境。 + +--- + +## 1.1 项目结构初始化 +- [x] **创建目录树** + - 在项目根目录创建 `orchestrator/`。 + - 创建子模块: + - `orchestrator/core/` (核心逻辑) + - `orchestrator/adapters/` (模块适配器) + - `orchestrator/utils/` (工具函数) + - 在每个目录下创建 `__init__.py`。 + +## 1.2 配置管理模块 (`core/config.py`) +- [x] **设计 `Config` 类** + - 使用 `pydantic` 或原生类管理配置项。 + - **必需配置项**: + - `OPENAI_API_KEY` / `MODELSCOPE_API_KEY` + - `OPENAI_BASE_URL` + - `MODEL_NAME` (默认 Research/Spec 模型) + - `MAX_RETRIES` (Coding 阶段最大重试次数,默认 3) + - `WORKSPACE_ROOT` (默认 `workspace/`) + - **功能**: + - `load_from_env()`: 从 `.env` 文件加载。 + - `load_from_yaml(path)`: 支持从 YAML 加载(可选)。 + +## 1.3 工作区管理器 (`core/workspace.py`) +- [x] **设计 `WorkspaceManager` 类** + - **属性**: `run_id` (时间戳), `root_path`。 + - **方法**: + - `create(run_id=None)`: 创建形如 `workspace/run_20251126_100000/` 的目录。 + - `get_path(filename)`: 获取当前工作区内文件的绝对路径 (e.g., `report.md`)。 + - `ensure_file(filename, content="")`: 确保文件存在,可选写入初始内容。 + - `list_files(pattern="*")`: 列出工作区文件。 + - `clean()`: (可选) 清理空目录。 + +## 1.4 日志系统 (`utils/logger.py`) +- [x] **配置 `logging`** + - 创建 `setup_logger(workspace_path)` 函数。 + - **输出**: + - Console: INFO 级别,格式简洁。 + - File: `workspace/.../orchestrator.log`,DEBUG 级别,包含时间戳和模块名。 + +## 1.5 CLI 入口 (`main.py`) +- [x] **使用 `argparse` 实现命令行解析** + - **参数**: + - `query` (Positional): 用户的自然语言需求。 + - `--files`: (List): 附加的文件路径列表。 + - `--urls`: (List): 附加的 URL 列表。 + - `--config`: (String): 指定配置文件路径。 + - **逻辑**: + 1. 初始化 Config。 + 2. 初始化 WorkspaceManager 并创建目录。 + 3. 初始化 Logger。 + 4. 打印 "Orchestrator initialized at [workspace_path]"。 +- [x] **测试运行**: 确保 `python orchestrator/main.py "test query"` 能成功创建目录并打印日志。 diff --git a/chao-docs/02todos/2.0_Research_Adapter_Tasks.md b/chao-docs/02todos/2.0_Research_Adapter_Tasks.md new file mode 100644 index 000000000..ddb3c706d --- /dev/null +++ b/chao-docs/02todos/2.0_Research_Adapter_Tasks.md @@ -0,0 +1,49 @@ +# Phase 2: Research 模块适配任务清单 + +**对应阶段**: Phase 2 +**目标**: 通过适配器模式封装 `doc_research` 和 `deep_research`,使其成为标准化的内部工具,输出统一格式的 `report.md`。 + +--- + +## 2.1 基础适配器接口 (`adapters/base.py`) +- [x] **定义 `BaseAdapter` 抽象类** + - **方法**: `run(context: dict) -> dict` + - **规范**: + - 输入必须包含任务上下文。 + - 输出必须包含生成文件的路径或内容摘要。 + +## 2.2 Doc Research 适配器 (`adapters/doc_research_adapter.py`) +- [x] **源码分析与引用** + - 确认引用路径:`ms_agent.app.doc_research` 或底层 `ms_agent.workflow.doc_research_workflow`。 + - **注意**: 避免引入 `gradio` 相关的 GUI 依赖,只引用逻辑层。 +- [x] **实现 `DocResearchAdapter` 类** + - **初始化**: 接收 `config` 对象。 + - **方法 `run(file_paths: list[str], urls: list[str])`**: + 1. 构造 `ResearchWorkflow` 实例。 + 2. 调用其 `run` 方法 (注意是同步还是异步)。 + 3. 捕获生成的 Markdown 内容。 + 4. 将内容写入工作区的 `report.md`。 + - **处理**: 自动处理多文件合并逻辑(如果底层不支持,需在 Adapter 层拼接)。 + +## 2.3 Deep Research 适配器 (`adapters/deep_research_adapter.py`) +- [x] **源码分析** + - 查看 `projects/deep_research/run.py`。 + - 确认是否支持作为库调用,还是需要用 `subprocess` 调用 CLI。 +- [x] **实现 `DeepResearchAdapter` 类** + - **策略**: 优先尝试作为库导入 (`from projects.deep_research... import ...`)。如果依赖冲突严重,回退到 `subprocess.run`。 + - **方法 `run(query: str)`**: + 1. 配置 Deep Research 的运行参数 (搜索深度、广度等)。 + 2. 执行搜索与总结任务。 + 3. 提取最终的总结报告。 + 4. 写入工作区的 `report.md`。 + +## 2.4 统一入口与分发逻辑 +- [x] **更新 `main.py` 或创建 `core/dispatcher.py`** + - **逻辑**: + - 如果用户提供了 `--files` 或 `--urls` -> 调用 `DocResearchAdapter`。 + - 如果仅提供 `query` -> 调用 `DeepResearchAdapter`。 + - (进阶) 如果两者都有 -> 先 Deep 搜索背景,再结合 Doc 分析 (V2特性,暂不实现)。 + +## 2.5 验证与测试计划 +- [x] **单元测试 (Mock)** +- [x] **集成测试 (手动)** diff --git a/chao-docs/02todos/3.0_Interaction_Flow_Tasks.md b/chao-docs/02todos/3.0_Interaction_Flow_Tasks.md new file mode 100644 index 000000000..09aed779a --- /dev/null +++ b/chao-docs/02todos/3.0_Interaction_Flow_Tasks.md @@ -0,0 +1,50 @@ +# Phase 3: 交互控制与数据流转任务清单 + +**对应阶段**: Phase 3 +**目标**: 串联各个模块,实现 Human-in-the-Loop (HITL) 机制,并定义 Role B (Spec/Test) 和 Role C (Code) 的交互契约。 + +--- + +## 3.1 交互流程控制器 (`core/flow.py`) +- [x] **设计 `FlowController` 类** + - **依赖**: `WorkspaceManager`, `Logger`. +- [x] **实现 `wait_for_human_review(file_path: str)`** + - **功能**: + 1. 打印提示信息:"Artifact generated at {file_path}. Please review and edit if necessary." + 2. 打印选项:"[C]ontinue processing, [R]eload and view, [E]xit"。 + 3. 阻塞等待用户输入。 + 4. 如果用户选择 Continue,重新读取文件内容(确保捕获了用户的修改)。 + - **注意**: 确保在非交互模式下(如 CI 环境)可以跳过或设置超时。 + +## 3.2 Role B (Spec & Test) 接口契约 (Mock) +> 注:Role B 的具体 Agent 实现由队友完成,此处仅实现调用接口。 + +- [x] **定义 Spec 生成接口 (`adapters/spec_adapter.py`)** + - **Input**: `report.md` 内容。 + - **Output**: `tech_spec.md` (包含 API 签名、数据结构、依赖)。 + - **Mock 实现**: 暂时写一个简单的函数,直接根据 Report 复制一份作为 Spec,或者追加一段固定文本,用于跑通流程。 +- [x] **定义 Test 生成接口 (`adapters/test_gen_adapter.py`)** + - **Input**: `tech_spec.md` 内容。 + - **Output**: 写入 `tests/` 目录下的 `test_core.py`。 + - **Mock 实现**: 生成一个总是通过的 `pytest` 文件 (e.g., `def test_placeholder(): assert True`)。 + +## 3.3 Role C (Coding) 接口契约 (Mock) +> 注:Role C 的具体 Agent 实现由队友完成,此处仅实现调用接口。 + +- [x] **定义 Code Generator 接口 (`adapters/code_adapter.py`)** + - **Input**: + - `query`: 原始需求 + "请遵循 tech_spec.md"。 + - `context_files`: [`tech_spec.md`, `tests/test_core.py`]。 + - **Output**: `src/` 目录下的代码。 + - **Mock 实现**: 创建一个简单的 `src/main.py`,打印 "Hello World"。 + +## 3.4 数据转换逻辑 +- [x] **实现 Report -> Spec 转换器** + - 编写 Prompt 模板,指导 LLM 将自然语言报告转换为结构化 Markdown。 +- [x] **实现 Spec -> Test 转换器** + - 编写 Prompt 模板,指导 LLM 基于 Spec 生成 `pytest` 代码。 + +## 3.5 集成测试 +- [x] **编写 `tests/test_flow.py`** + - 验证 `wait_for_human_review` 逻辑。 + - 验证数据在 Mock Adapter 之间的流转:Report -> Spec -> Test -> Code。 diff --git a/chao-docs/02todos/4.0_Integration_Loop_Tasks.md b/chao-docs/02todos/4.0_Integration_Loop_Tasks.md new file mode 100644 index 000000000..444d9ed8f --- /dev/null +++ b/chao-docs/02todos/4.0_Integration_Loop_Tasks.md @@ -0,0 +1,65 @@ +# Phase 4: 全链路联调与外循环任务清单 + +**对应阶段**: Phase 4 +**目标**: 将所有组件组装成完整的流水线,实现“外循环”重试机制,并进行端到端验证。 + +--- + +## 4.1 主流程编排 (`main.py` Update) +- [x] **实现 `run_pipeline()` 函数** + - **Step 1: Research** + - 调用 `DocResearchAdapter` 或 `DeepResearchAdapter`。 + - 产出 `workspace/.../report.md`。 + - **Step 2: Spec Generation** + - 调用 `SpecAdapter` (Role B)。 + - 产出 `workspace/.../tech_spec.md`。 + - **Step 3: Human Review** + - 调用 `FlowController.wait_for_human_review('tech_spec.md')`。 + - **Step 4: Test Generation** + - 调用 `TestGenAdapter` (Role B)。 + - 产出 `workspace/.../tests/test_core.py`。 + - **Step 5: Coding (Outer Loop)** + - 进入外循环重试逻辑。 + +## 4.2 外循环重试机制 (Outer Loop) +- [x] **实现 `OuterLoopController`** + - **逻辑**: + ```python + retries = 0 + while retries < MAX_RETRIES: + # 1. Generate Code + CodeAdapter.run(spec, tests, error_log) + + # 2. Verify + exit_code, stdout, stderr = run_pytest(workspace) + + if exit_code == 0: + logger.info("Tests passed!") + break + else: + retries += 1 + logger.warning(f"Tests failed. Retry {retries}/{MAX_RETRIES}") + error_log = parse_error_log(stdout, stderr) + ``` +- [x] **实现 `run_pytest` 辅助函数** + - 使用 `subprocess` 在工作区运行 `pytest`。 + - 确保环境变量正确设置。 + +## 4.3 错误处理与日志 +- [x] **增强异常捕获** + - 在每个 Step 增加 try-except,捕获 Adapter 抛出的异常。 + - 发生致命错误时,保存当前状态并优雅退出。 +- [x] **Artifact 归档** + - 运行结束后,生成 `summary.md`,汇总各阶段产出的文件路径。 + +## 4.4 端到端演示验证 (Demo) +- [x] **准备测试场景** + - 场景 A: 输入一个简单的 Python 算法需求(如“计算斐波那契数列”),无需 Research,直接走 Spec -> Code。 + - 场景 B: 输入一个 URL(如某篇 Arxiv 论文),走 DocResearch -> Spec -> Code。 +- [x] **编写 `scripts/demo_run.sh`** + - 自动化运行上述场景,验证全流程是否跑通。 + +## 4.5 文档编写 +- [ ] **更新 `README.md`** + - 添加 Orchestrator 的使用说明。 + - 记录目录结构和关键配置项。 diff --git a/chao-docs/GEMINI.md b/chao-docs/GEMINI.md new file mode 100644 index 000000000..8a176b40b --- /dev/null +++ b/chao-docs/GEMINI.md @@ -0,0 +1,157 @@ +# Gemini 上下文: `ms-agent` 项目 + +本文档旨在全面介绍 `ms-agent` 项目的结构、功能以及如何与其进行交互。 + +## 项目概述 + +`ms-agent` 是一个轻量级、可扩展的 Python 框架,旨在赋予 AI 智能体自主探索(Autonomous Exploration)的能力。它提供了一套完整的工具和架构,支持从简单的对话代理到能够执行复杂任务、使用外部工具、进行代码生成和深度研究的自主智能体。 + +**核心特性:** + +* **自主智能体 (Autonomous Agents):** 构建能够推理、规划、管理记忆并执行复杂任务的智能体。 +* **工具使用 (MCP):** 全面支持模型上下文协议 (Model Context Protocol, MCP),允许智能体与文件系统、搜索引擎等外部工具无缝集成。 +* **检索增强生成 (RAG):** 内置 `rag` 模块,支持基于文档的知识检索和增强。 +* **记忆管理 (Memory):** 提供灵活的记忆管理机制,支持短期和长期记忆。 +* **沙箱环境 (Sandbox):** 提供代码执行的沙箱环境,确保安全性。 +* **专用子项目:** 包含多个针对特定领域的专用智能体项目: + * `Agent Skills`: 展示智能体各种核心技能的实现。 + * `Deep Research`: 用于对复杂主题进行深度研究和报告生成的智能体。 + * `Doc Research`: 专注于文档深度分析、摘要和问答。 + * `Code Scratch`: 一个能够自主构建和管理代码项目的智能体。 + * `Fin Research`: (新增) 专注于金融领域研究的智能体。 + * `Singularity Cinema`: (新增) 一个多模态或娱乐相关的智能体项目示例。 +* **可扩展架构:** 采用高度模块化设计,核心组件(LLM、工具、回调、配置)均可自定义。 + +**核心技术:** + +* **编程语言:** Python (>=3.10) +* **配置管理:** 使用 `OmegaConf` 进行强大的分层配置管理。 +* **大模型集成:** 通过 `modelscope` 和 `openai` 库连接各种 LLM(如 Qwen, GPT-4, Claude 等)。 +* **Web UI:** 集成 `Gradio`,通过 `ms-agent app` 命令快速启动交互式 Web 界面。 +* **关键依赖:** `mcp`, `dotenv`, `json5`, `markdown`, `pillow`, `numpy`, `fastapi` (用于某些服务组件)。 + +## 构建与运行 + +### 安装 + +你可以从 PyPI 或从源代码安装本项目。 + +**从 PyPI 安装:** + +```bash +# 安装基础功能 +pip install ms-agent + +# 安装“深度研究”功能 +pip install 'ms-agent[research]' + +# 安装“代码生成”功能 +pip install 'ms-agent[code]' +``` + +**从源代码安装 (用于开发):** + +```bash +git clone https://github.com/modelscope/ms-agent.git +cd ms-agent +pip install -e . +``` + +### 配置 + +* **智能体/工作流配置:** 智能体行为由 `.yaml` 文件定义 (例如 `agent.yaml`)。支持分层配置,可覆盖系统提示、工具列表、LLM 参数等。 +* **环境变量:** 使用 `.env` 文件或环境变量配置敏感信息。 + * `MODELSCOPE_API_KEY` + * `OPENAI_API_KEY` + * `OPENAI_BASE_URL` + * `DASHSCOPE_API_KEY` + * `BING_SEARCH_API_KEY` (用于搜索工具) + +### 执行 + +框架提供了一个名为 `ms-agent` 的统一命令行入口。 + +**1. 命令行运行 (CLI):** + +`ms-agent run` 是运行智能体的主要命令。 + +```bash +# 基础用法 +ms-agent run --config projects/code_scratch --query "创建一个贪吃蛇游戏" + +# 常用参数 +# --config: 配置文件路径或项目目录 (必需) +# --query: 初始用户指令 (可选,若无则进入交互模式) +# --trust_remote_code: 允许加载远程代码 (安全选项) +# --load_cache: 加载之前的缓存状态 (如果支持) +# --verbose: 显示详细日志 +``` + +**2. 启动 Web UI:** + +`ms-agent app` 命令用于启动基于 Gradio 的图形界面。 + +```bash +# 启动特定项目的 Web UI +ms-agent app --app_type doc_research + +# 这将在本地启动一个 Web 服务器,通常可以通过 http://127.0.0.1:7860 访问 +``` + +**3. Python 脚本调用:** + +```python +import asyncio +from ms_agent import LLMAgent +from ms_agent.config import Config + +async def main(): + # 1. 加载配置 + config = Config.from_task('ms_agent/agent/agent.yaml') + + # 2. 实例化智能体 + # 可选:指定 mcp_server_file 连接外部工具 + llm_agent = LLMAgent(config=config) + + # 3. 运行 + await llm_agent.run('分析一下当前的人工智能发展趋势') + +if __name__ == '__main__': + asyncio.run(main()) +``` + +## 开发规范与项目结构 + +* **项目结构:** + * `ms_agent/`: 核心框架代码 + * `agent/`: 智能体核心逻辑 (`LLMAgent`, `CodeAgent`)。 + * `app/`: Web UI 应用实现 (`Gradio` 界面)。 + * `callbacks/`: 事件回调系统 (Stream处理, 日志记录)。 + * `cli/`: 命令行入口 (`cli.py`, `run.py`, `app.py`)。 + * `config/`: 配置加载与管理。 + * `llm/`: LLM 接口抽象与实现 (OpenAI, DashScope 等)。 + * `memory/`: 记忆管理模块。 + * `rag/`: 检索增强生成模块。 + * `sandbox/`: 代码执行沙箱。 + * `skill/`: 技能定义与加载。 + * `tools/`: 内置工具集 (文件操作, 搜索, MCP 客户端)。 + * `utils/`: 通用工具函数。 + * `workflow/`: 工作流编排。 + * `projects/`: 示例与专用项目 + * `agent_skills/`: 技能演示。 + * `code_scratch/`: 代码生成智能体。 + * `deep_research/`: 深度研究智能体。 + * `doc_research/`: 文档分析智能体。 + * `fin_research/`: 金融研究智能体。 + * `singularity_cinema/`: (示例项目)。 + * `examples/`: 基础用法示例脚本。 + * `requirements/`: 依赖清单 (`framework.txt`, `research.txt`, `code.txt`)。 + +* **核心类:** + * `LLMAgent`: 最通用的智能体类,集成了 LLM、工具、记忆和回调。 + * `Config`: 处理 YAML 配置加载和合并。 + * `ToolManager`: 管理工具的注册和调用。 + +* **注意事项:** + * **异步优先:** 框架核心逻辑深度依赖 `asyncio`,开发新组件时请务必使用 `async/await`。 + * **类型提示:** 代码库广泛使用 Python 类型提示,请保持这一习惯。 diff --git "a/chao-docs/git\345\244\204\347\220\206.md" "b/chao-docs/git\345\244\204\347\220\206.md" new file mode 100644 index 000000000..49b8bcd3a --- /dev/null +++ "b/chao-docs/git\345\244\204\347\220\206.md" @@ -0,0 +1,41 @@ +方案一:个人 WIP 分支 + Squash 合并(最推荐,符合标准流) + +这是最标准的 Git 协作模式。你不直接在团队的 dev 分支上提交,而是建立一个属于你的“个人临时分支”。 +核心思路: 在你自己的分支上“脏”提交,合并回团队分支时“洗”干净。 + +1. 创建个人同步分支 + +在你的设备上,基于当前的开发分支切出一个属于你的分支,比如叫 feat/docs-wip (Work In Progress): +Bash +git checkout -b feat/docs-wip + +2. 随意提交与同步 + +你可以在这还是分支上通过 git push 和 git pull 在两台设备间随意同步。 + +- 设备 A: 写了一半文档 -> git commit -m "sync: A 机进度" -> git push +- 设备 B: git pull -> 继续写 -> git commit -m "sync: B 机进度" -> git push + 此时,只有你的 feat/docs-wip 分支是乱的,团队的主分支依然干净。 + +3. 关键步骤:Squash 合并(洗白) + +当你完成了某个阶段的工作,准备把代码合入团队的 dev 分支时,不要直接 merge,而是使用 Squash(压缩)。 +方法 A:使用命令行 切换回团队分支,使用 --squash 参数: +Bash + +# 切换回团队开发分支 + +git checkout dev + +# 把你的脏分支压缩成一个更改 + +git merge --squash feat/docs-wip + +# 此时所有改动都在暂存区,需要手动提交一次,这一条就是展示给团队看的完美 Commit + +git commit -m "Docs: 更新了项目开发文档和相关说明" +方法 B:使用 GitHub/GitLab 的 PR/MR 如果你通过 Pull Request 提交给团队: + +1. 推送你的 feat/docs-wip 到远程。 +2. 发起 PR 到 dev。 +3. 在合并按钮旁边,选择 "Squash and merge"。这样最后合入的代码只有一条干干净净的记录。 diff --git a/orchestrator/__init__.py b/orchestrator/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/orchestrator/adapters/__init__.py b/orchestrator/adapters/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/orchestrator/adapters/base.py b/orchestrator/adapters/base.py new file mode 100644 index 000000000..b68be1a3f --- /dev/null +++ b/orchestrator/adapters/base.py @@ -0,0 +1,32 @@ +from abc import ABC, abstractmethod +from pathlib import Path +from typing import Any, Dict, Optional + + +class BaseAdapter(ABC): + """ + 所有适配器的基类。 + 定义了标准的 run 接口,强制实现者处理输入并产生输出。 + """ + + def __init__(self, config, workspace_manager): + """ + 初始化适配器。 + + Args: + config (OrchestratorConfig): 全局配置对象。 + workspace_manager (WorkspaceManager): 工作区管理器,用于文件读写。 + """ + self.config = config + self.workspace = workspace_manager + + @abstractmethod + def run(self, **kwargs) -> Dict[str, Any]: + """ + 执行适配器逻辑。 + + Returns: + Dict: 执行结果,通常包含生成的关键文件路径。 + 例如: {'report_path': Path(...)} + """ + pass diff --git a/orchestrator/adapters/code_adapter.py b/orchestrator/adapters/code_adapter.py new file mode 100644 index 000000000..ea4c96f38 --- /dev/null +++ b/orchestrator/adapters/code_adapter.py @@ -0,0 +1,44 @@ +from pathlib import Path +from typing import Any, Dict, List + +from orchestrator.adapters.base import BaseAdapter +from orchestrator.core.const import DIR_SRC + + +class CodeAdapter(BaseAdapter): + """ + [Mock] Code Adapter (Role C) + 负责调用 Code Scratch 生成代码。 + """ + + def run(self, + query: str, + spec_path: Path, + tests_dir: Path, + error_log: str = '') -> Dict[str, Any]: + """ + 执行代码生成。 + + Args: + query: 原始需求。 + spec_path: Spec 文件路径。 + tests_dir: 测试文件夹路径。 + error_log: (Outer Loop) 上一次运行失败的错误日志。 + + Returns: + {'src_dir': Path(...)} + """ + # Mock 逻辑: 生成一个简单的 Python 脚本 + src_content = f""" +def main(): + print("Hello from Generated Code!") + print("Query: {query}") + +if __name__ == "__main__": + main() +""" + src_file = self.workspace.work_dir / DIR_SRC / 'main.py' + src_file.parent.mkdir(exist_ok=True) + src_file.write_text(src_content, encoding='utf-8') + + return {'src_dir': src_file.parent} diff --git a/orchestrator/adapters/deep_research_adapter.py b/orchestrator/adapters/deep_research_adapter.py new file mode 100644 index 000000000..eb7510712 --- /dev/null +++ b/orchestrator/adapters/deep_research_adapter.py @@ -0,0 +1,108 @@ +import asyncio +import os +from typing import Any, Dict, List + +from ms_agent.llm.openai import OpenAIChat +from ms_agent.tools.exa import ExaSearch +from ms_agent.tools.search.arxiv import ArxivSearch +from ms_agent.tools.search.serpapi import SerpApiSearch +from ms_agent.workflow.deep_research.research_workflow_beta import \ + ResearchWorkflowBeta +from orchestrator.adapters.base import BaseAdapter +from orchestrator.core.const import FILE_REPORT + + +class DeepResearchAdapter(BaseAdapter): + """ + 适配器:用于调用 projects.deep_research (Beta) 进行深度网络搜索研究。 + """ + + def run(self, query: str) -> Dict[str, Any]: + """ + 执行深度研究任务。 + + Args: + query (str): 研究主题。 + + Returns: + Dict: {'report_path': Path(...)} + """ + # 1. 初始化 LLM Client + llm_config = { + 'api_key': self.config.openai_api_key + or self.config.modelscope_api_key, + 'base_url': self.config.openai_base_url, + 'model': self.config.model_name, + } + + if not llm_config['api_key']: + raise ValueError( + 'API Key is missing. Please set OPENAI_API_KEY or MODELSCOPE_API_KEY.' + ) + + client = OpenAIChat( + api_key=llm_config['api_key'], + base_url=llm_config['base_url'], + model=llm_config['model'], + generation_config={'extra_body': { + 'enable_thinking': True + }}) + + # 2. 初始化搜索引擎 + search_engine = self._create_search_engine() + + # 3. 准备工作目录 + workdir = str(self.workspace.work_dir) + + # 4. 初始化 Workflow (Beta) + # 使用 beta 版本因为其支持更深度的递归搜索 + workflow = ResearchWorkflowBeta( + client=client, + search_engine=search_engine, + workdir=workdir, + use_ray=False, # 默认关闭 Ray 以避免依赖复杂性 + enable_multimodal=True) + + # 5. 执行 Run (异步) + # 需要在同步环境中运行异步代码 + try: + loop = asyncio.get_event_loop() + except RuntimeError: + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + + # 配置参数 (可以后续移入 Config) + run_params = { + 'user_prompt': query, + 'breadth': 4, # 广度 + 'depth': 2, # 深度 + 'is_report': True, + 'show_progress': True + } + + loop.run_until_complete(workflow.run(**run_params)) + + # 6. 验证输出 + # ResearchWorkflowBeta 生成的报告默认命名可能包含前缀或在子目录中 + # 但通常最终汇总报告是 report.md + report_path = self.workspace.get_path(FILE_REPORT) + if not report_path.exists(): + # Beta 版可能会生成 intermediate 文件,我们需要确认最终文件名为 report.md + # 如果不是,这里可能需要重命名或查找 + raise RuntimeError( + f'DeepResearch failed to generate {FILE_REPORT}') + + return {'report_path': report_path} + + def _create_search_engine(self): + """根据环境变量创建合适的搜索引擎实例""" + exa_key = os.getenv('EXA_API_KEY') + serp_key = os.getenv('SERPAPI_API_KEY') + + if exa_key: + return ExaSearch(api_key=exa_key) + elif serp_key: + return SerpApiSearch(api_key=serp_key) + else: + # 默认使用 Arxiv,无需 Key,适合科研场景 + return ArxivSearch() diff --git a/orchestrator/adapters/doc_research_adapter.py b/orchestrator/adapters/doc_research_adapter.py new file mode 100644 index 000000000..87c764bc4 --- /dev/null +++ b/orchestrator/adapters/doc_research_adapter.py @@ -0,0 +1,86 @@ +import os +from pathlib import Path +from typing import Any, Dict, List + +from ms_agent.llm.openai import OpenAIChat +from ms_agent.workflow.deep_research.research_workflow import ResearchWorkflow +from orchestrator.adapters.base import BaseAdapter +from orchestrator.core.const import FILE_REPORT + + +class DocResearchAdapter(BaseAdapter): + """ + 适配器:用于调用 ms_agent.workflow.deep_research.ResearchWorkflow 进行文档分析。 + """ + + def run(self, query: str, files: List[str], + urls: List[str]) -> Dict[str, Any]: + """ + 执行文档研究任务。 + + Args: + query (str): 用户的研究问题或指令。 + files (List[str]): 本地文件路径列表 (绝对路径)。 + urls (List[str]): URL 列表。 + + Returns: + Dict: {'report_path': Path(...)} + """ + # 1. 准备输入列表 (files + urls) + urls_or_files = files + urls + if not urls_or_files: + raise ValueError( + 'DocResearchAdapter requires at least one file or URL.') + + # 2. 初始化 LLM Client + # 使用 config 中的配置 + llm_config = { + 'api_key': self.config.openai_api_key + or self.config.modelscope_api_key, + 'base_url': self.config.openai_base_url, + 'model': self.config.model_name, + } + + # 确保 API Key 存在 + if not llm_config['api_key']: + raise ValueError( + 'API Key is missing. Please set OPENAI_API_KEY or MODELSCOPE_API_KEY.' + ) + + client = OpenAIChat( + api_key=llm_config['api_key'], + base_url=llm_config['base_url'], + model=llm_config['model'], + # 启用思维链 (如果支持) + generation_config={'extra_body': { + 'enable_thinking': True + }}) + + # 3. 准备工作目录 + # ResearchWorkflow 会在 workdir 下生成 report.md + # 我们直接使用当前 workspace 的路径 + workdir = str(self.workspace.work_dir) + + # 4. 初始化并运行 Workflow + # 注意:ResearchWorkflow 内部会自动处理 OCR 模型下载 (如果 ms_agent 版本较新且包含相关逻辑) + # 如果运行报错缺少模型,我们需要手动补充下载代码 + workflow = ResearchWorkflow( + client=client, + workdir=workdir, + verbose=True, + # 可以传入 use_ray=True 如果环境支持 Ray + use_ray=False) + + # 5. 执行 Run + # user_prompt 对应 query + # urls_or_files 对应文档列表 + # report_prefix 默认为空,所以输出文件是 report.md + workflow.run(user_prompt=query, urls_or_files=urls_or_files) + + # 6. 验证输出 + report_path = self.workspace.get_path(FILE_REPORT) + if not report_path.exists(): + raise RuntimeError( + f'ResearchWorkflow failed to generate {FILE_REPORT}') + + return {'report_path': report_path} diff --git a/orchestrator/adapters/spec_adapter.py b/orchestrator/adapters/spec_adapter.py new file mode 100644 index 000000000..a9ff0964c --- /dev/null +++ b/orchestrator/adapters/spec_adapter.py @@ -0,0 +1,42 @@ +from pathlib import Path +from typing import Any, Dict + +from orchestrator.adapters.base import BaseAdapter +from orchestrator.core.const import FILE_REPORT, FILE_TECH_SPEC +from orchestrator.core.templates import TECH_SPEC_TEMPLATE + + +class SpecAdapter(BaseAdapter): + """ + [Mock] Spec Adapter (Role B) + 负责将 Report 转化为 Technical Specification。 + """ + + def run(self, report_path: Path) -> Dict[str, Any]: + """ + 执行 Spec 生成。 + + Args: + report_path: Report.md 的路径。 + + Returns: + {'spec_path': Path(...)} + """ + if not report_path.exists(): + raise FileNotFoundError(f'Report file not found: {report_path}') + + # Mock 逻辑: 读取 Report,套用模板生成 Spec + report_content = report_path.read_text(encoding='utf-8') + + # 这里只是简单的字符串格式化,真实实现会调用 LLM + spec_content = TECH_SPEC_TEMPLATE.format( + project_name='Demo Project', + # 实际中这里会提取 report 摘要 + ) + + spec_content += '\n\n\n' + spec_content += f'Original Report Summary: {report_content[:200]}...\n' + + spec_path = self.workspace.ensure_file(FILE_TECH_SPEC, spec_content) + + return {'spec_path': spec_path} diff --git a/orchestrator/adapters/test_gen_adapter.py b/orchestrator/adapters/test_gen_adapter.py new file mode 100644 index 000000000..73080815b --- /dev/null +++ b/orchestrator/adapters/test_gen_adapter.py @@ -0,0 +1,39 @@ +from pathlib import Path +from typing import Any, Dict + +from orchestrator.adapters.base import BaseAdapter +from orchestrator.core.const import DIR_TESTS, FILE_TECH_SPEC, FILE_TEST_MAIN + + +class TestGenAdapter(BaseAdapter): + """ + [Mock] Test Generator Adapter (Role B) + 负责基于 Spec 生成测试用例。 + """ + + def run(self, spec_path: Path) -> Dict[str, Any]: + """ + 执行测试生成。 + + Returns: + {'tests_dir': Path(...)} + """ + if not spec_path.exists(): + raise FileNotFoundError(f'Spec file not found: {spec_path}') + + # Mock 逻辑: 生成一个简单的 pytest 文件 + test_content = """ +import pytest + +def test_example(): + assert 1 + 1 == 2 + +def test_from_spec(): + # This is a placeholder test generated from spec + pass +""" + test_file_path = self.workspace.work_dir / DIR_TESTS / FILE_TEST_MAIN + test_file_path.parent.mkdir(exist_ok=True) + test_file_path.write_text(test_content, encoding='utf-8') + + return {'tests_dir': test_file_path.parent} diff --git a/orchestrator/core/__init__.py b/orchestrator/core/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/orchestrator/core/config.py b/orchestrator/core/config.py new file mode 100644 index 000000000..0ded7cef8 --- /dev/null +++ b/orchestrator/core/config.py @@ -0,0 +1,43 @@ +import os +from dataclasses import dataclass +from typing import Optional + +from dotenv import load_dotenv + +# 如果存在 .env 文件,则加载环境变量 +load_dotenv() + + +@dataclass +class OrchestratorConfig: + """ + 编排器配置类。 + 从环境变量加载配置值,或使用默认值。 + """ + # LLM 配置 + openai_api_key: Optional[str] = os.getenv('OPENAI_API_KEY') + modelscope_api_key: Optional[str] = os.getenv('MODELSCOPE_API_KEY') + openai_base_url: str = os.getenv( + 'OPENAI_BASE_URL', 'https://api-inference.modelscope.cn/v1/') + model_name: str = os.getenv('MODEL_NAME', + 'Qwen/Qwen2.5-Coder-32B-Instruct') + + # 编排器逻辑配置 + max_retries: int = int(os.getenv('MAX_RETRIES', '3')) + workspace_root: str = os.getenv('WORKSPACE_ROOT', 'workspace') + + # Research 模块配置 + search_engine_api_key: Optional[str] = os.getenv( + 'EXA_API_KEY') or os.getenv('SERPAPI_API_KEY') + + def validate(self): + """验证关键配置项。""" + if not self.openai_api_key and not self.modelscope_api_key: + # 某些用户可能依赖本地模型或隐式认证,但通常我们需要一个 Key。 + # 这里可以添加警告日志。 + pass + + @classmethod + def load(cls) -> 'OrchestratorConfig': + """加载配置的工厂方法。""" + return cls() diff --git a/orchestrator/core/const.py b/orchestrator/core/const.py new file mode 100644 index 000000000..7aff9ff4f --- /dev/null +++ b/orchestrator/core/const.py @@ -0,0 +1,9 @@ +# 文件名常量定义 +# 统一管理文件名,避免硬编码字符串 + +FILE_REPORT = 'report.md' +FILE_TECH_SPEC = 'tech_spec.md' +FILE_API_DEF = 'api_definitions.json' # 可选,用于更严格的结构化 +DIR_TESTS = 'tests' +DIR_SRC = 'src' +FILE_TEST_MAIN = 'test_core.py' diff --git a/orchestrator/core/flow.py b/orchestrator/core/flow.py new file mode 100644 index 000000000..bf5ae0955 --- /dev/null +++ b/orchestrator/core/flow.py @@ -0,0 +1,66 @@ +import logging +import sys +from pathlib import Path +from typing import Optional + +logger = logging.getLogger('Orchestrator') + + +class FlowController: + """ + 流程控制器。 + 负责处理 Human-in-the-Loop (HITL) 交互,如暂停、等待用户审查文件等。 + """ + + def __init__(self, workspace_manager): + self.workspace = workspace_manager + + def wait_for_human_review(self, + filename: str, + prompt_msg: Optional[str] = None) -> bool: + """ + 暂停执行,等待用户审查并编辑指定文件。 + + Args: + filename (str): 相对于工作区的文件名 (e.g. "tech_spec.md")。 + prompt_msg (str): 提示用户的自定义消息。 + + Returns: + bool: 如果用户选择继续,返回 True;如果用户选择退出,返回 False。 + """ + file_path = self.workspace.get_path(filename) + + if not file_path.exists(): + logger.warning(f'文件 {filename} 不存在,无法进行审查。') + return True + + print('\n' + '=' * 60) + print('🛑 [Human Review Required]') + print(f'📄 File: {file_path}') + if prompt_msg: + print(f'💡 {prompt_msg}') + else: + print('💡 请打开上述文件进行检查。如果您修改了内容,保存文件即可。 ') + + print('-' * 60) + print('选项 Options:') + print(' [C]ontinue : 确认内容无误 (或已保存修改),继续执行') + print(' [R]eload : 重新读取文件内容并打印预览 (检查修改是否生效)') + print(' [E]xit : 终止任务') + print('=' * 60 + '\n') + + while True: + choice = input('Your choice [C/R/E]: ').strip().upper() + + if choice == 'C': + logger.info(f'User approved {filename}. Continuing...') + return True + elif choice == 'E': + logger.info('User aborted the process.') + return False + elif choice == 'R': + print(f'\n--- Preview of {filename} ---') + print(file_path.read_text(encoding='utf-8')) + print('-' * 30 + '\n') + else: + print('Invalid choice. Please enter C, R, or E.') diff --git a/orchestrator/core/templates.py b/orchestrator/core/templates.py new file mode 100644 index 000000000..a4eeaba28 --- /dev/null +++ b/orchestrator/core/templates.py @@ -0,0 +1,83 @@ +# 模板定义:Research 报告标准格式 +# 用于指导 Research Agent 生成结构化报告 +RESEARCH_REPORT_TEMPLATE = """# Research Report: {query} + +## 1. Executive Summary +[Brief summary of the findings, 2-3 paragraphs] + +## 2. Key Concepts & Technologies +* **Concept A**: [Definition and relevance] +* **Technology B**: [Definition and relevance] + +## 3. Implementation Details (Crucial for Coding) +* **API Endpoints / Data Structures**: [Detailed description] +* **Libraries/Dependencies**: [List of recommended libraries with versions] +* **Algorithms**: [Step-by-step explanation or pseudocode] + +## 4. Reference Material +* [Source Title](URL) - [Key insight] +* [Local File](path) - [Key insight] + +## 5. Constraints & Risks +* [Performance/Security constraints] +* [Potential implementation pitfalls] +""" + +# 模板定义:技术规格书标准格式 +# 用于指导 Spec Agent 将 Report 转化为可执行的蓝图 +TECH_SPEC_TEMPLATE = """# Technical Specification: {project_name} + +## 1. System Overview +[High-level architecture description] + +## 2. File Structure +```text +src/ +├── main.py +├── utils.py +└── ... +tests/ +├── test_main.py +└── ... +requirements.txt +``` + +## 3. API Definitions & Data Structures +### 3.1 Class/Function: `ClassName` +* **Description**: ... +* **Methods**: + * `method_name(arg1: type) -> type`: [Description] + +### 3.2 Data Models +* `ModelName`: {field: type, ...} + +## 4. Core Logic & Algorithms +[Detailed logic flow, state management, etc.] + +## 5. Dependencies +* package_name>=version + +## 6. Testing Strategy +* **Unit Tests**: [Key scenarios to cover] +* **Integration Tests**: [Inter-module interactions] +""" + +# 提示词模板:Spec 生成器 +# 指导 LLM 从 Report 生成 Spec +SPEC_GENERATION_PROMPT = """ +You are a Senior System Architect. +Your task is to convert the following "Research Report" +into a rigorous "Technical Specification" (tech_spec.md). +The specification will be used by a developer to write code and a QA engineer to write tests. + +**Input Report**: +{report_content} + +**Requirements**: +1. Strict adherence to the input report. Do not hallucinate features NOT mentioned + unless necessary for a working system. +2. Define clear API signatures (Python type hints). +3. List specific library versions. +4. Output MUST be in Markdown format following this structure: + +""" + TECH_SPEC_TEMPLATE diff --git a/orchestrator/core/workspace.py b/orchestrator/core/workspace.py new file mode 100644 index 000000000..b4fa19b41 --- /dev/null +++ b/orchestrator/core/workspace.py @@ -0,0 +1,88 @@ +import os +import shutil +from datetime import datetime +from pathlib import Path +from typing import List, Optional + + +class WorkspaceManager: + """ + 工作区管理器。 + 负责为每次运行创建独立的目录,并管理其中的文件路径。 + """ + + def __init__(self, root_path: str, run_id: Optional[str] = None): + """ + 初始化工作区管理器。 + + Args: + root_path: 所有工作区的根目录路径。 + run_id: 本次运行的唯一标识符(通常是时间戳)。如果未提供,自动生成。 + """ + self.root_path = Path(root_path) + if run_id: + self.run_id = run_id + else: + self.run_id = f"run_{datetime.now().strftime('%Y%m%d_%H%M%S')}" + + self.work_dir = self.root_path / self.run_id + self.create() + + def create(self): + """创建工作区目录。""" + self.work_dir.mkdir(parents=True, exist_ok=True) + # 创建常用的子目录 + (self.work_dir / 'tests').mkdir(exist_ok=True) + (self.work_dir / 'src').mkdir(exist_ok=True) + (self.work_dir / 'logs').mkdir(exist_ok=True) + + def get_path(self, filename: str) -> Path: + """ + 获取工作区内文件的绝对路径。 + + Args: + filename: 文件名(相对于工作区根目录)。 + + Returns: + Path 对象。 + """ + return self.work_dir / filename + + def ensure_file(self, filename: str, content: str = '') -> Path: + """ + 确保文件存在。如果文件不存在,创建它并写入初始内容。 + + Args: + filename: 文件名。 + content: 初始内容。 + + Returns: + Path 对象。 + """ + file_path = self.get_path(filename) + if not file_path.exists(): + file_path.parent.mkdir(parents=True, exist_ok=True) + file_path.write_text(content, encoding='utf-8') + return file_path + + def list_files(self, pattern: str = '*') -> List[Path]: + """ + 列出工作区内匹配模式的文件。 + + Args: + pattern: Glob 模式。 + + Returns: + 文件路径列表。 + """ + return list(self.work_dir.rglob(pattern)) + + def clean(self): + """清理工作区(慎用)。""" + if self.work_dir.exists(): + shutil.rmtree(self.work_dir) + + @property + def logs_dir(self) -> Path: + """返回日志目录路径。""" + return self.work_dir / 'logs' diff --git a/orchestrator/main.py b/orchestrator/main.py new file mode 100644 index 000000000..a0a75299b --- /dev/null +++ b/orchestrator/main.py @@ -0,0 +1,178 @@ +import argparse +import sys +from pathlib import Path + +from orchestrator.adapters.code_adapter import CodeAdapter +from orchestrator.adapters.deep_research_adapter import DeepResearchAdapter +# Adapters +from orchestrator.adapters.doc_research_adapter import DocResearchAdapter +from orchestrator.adapters.spec_adapter import SpecAdapter +from orchestrator.adapters.test_gen_adapter import TestGenAdapter +from orchestrator.core.config import OrchestratorConfig +from orchestrator.core.flow import FlowController +from orchestrator.core.workspace import WorkspaceManager +from orchestrator.utils.logger import setup_logger +from orchestrator.utils.verifier import run_pytest + +# 确保能够导入 orchestrator 模块 +current_file = Path(__file__).resolve() +project_root = current_file.parent.parent +sys.path.append(str(project_root)) + + +def main(): + """ + Orchestrator CLI 入口点。 + """ + parser = argparse.ArgumentParser(description='AI Agent Orchestrator CLI') + + parser.add_argument('query', type=str, help='用户的自然语言需求或问题') + parser.add_argument('--files', nargs='*', help='附加的本地文件路径列表') + parser.add_argument('--urls', nargs='*', help='附加的 URL 列表') + parser.add_argument('--config', type=str, help='指定配置文件路径 (YAML)') + parser.add_argument( + '--mode', + choices=['research_only', 'full'], + default='full', + help='运行模式') + + args = parser.parse_args() + + # 1. 初始化配置 + try: + config = OrchestratorConfig.load() + config.validate() + except Exception as e: + print(f'配置加载失败: {e}') + sys.exit(1) + + # 2. 初始化工作区 + workspace = WorkspaceManager(root_path=config.workspace_root) + + # 3. 初始化组件 + logger = setup_logger(workspace.work_dir) + flow = FlowController(workspace) + + logger.info('=== Orchestrator Started ===') + logger.info(f'工作区: {workspace.work_dir}') + + # ========================================== + # Phase 1: Research + # ========================================== + logger.info('\n--- Phase 1: Research ---') + report_path = None + + try: + if args.files or args.urls: + logger.info('启动 DocResearchAdapter...') + adapter = DocResearchAdapter(config, workspace) + abs_files = [str(Path(f).resolve()) for f in (args.files or [])] + res = adapter.run( + query=args.query, files=abs_files, urls=args.urls or []) + else: + logger.info('启动 DeepResearchAdapter...') + adapter = DeepResearchAdapter(config, workspace) + res = adapter.run(query=args.query) + + report_path = res['report_path'] + logger.info(f'Research 完成! Report: {report_path}') + + except Exception as e: + logger.error(f'Research 阶段失败: {e}', exc_info=True) + sys.exit(1) + + if args.mode == 'research_only': + return + + # ========================================== + # Phase 2: Spec Generation + # ========================================== + logger.info('\n--- Phase 2: Spec Generation ---') + spec_path = None + try: + adapter = SpecAdapter(config, workspace) + res = adapter.run(report_path) + spec_path = res['spec_path'] + logger.info(f'Spec 生成完成! Spec: {spec_path}') + + # HITL: 等待人工审查 + if not flow.wait_for_human_review('tech_spec.md', + '请检查生成的技术规格书,确保API定义正确。'): + sys.exit(0) + + except Exception as e: + logger.error(f'Spec 阶段失败: {e}', exc_info=True) + sys.exit(1) + + # ========================================== + # Phase 3: Test Generation + # ========================================== + logger.info('\n--- Phase 3: Test Generation ---') + tests_dir = None + try: + adapter = TestGenAdapter(config, workspace) + res = adapter.run(spec_path) + tests_dir = res['tests_dir'] + logger.info(f'Tests 生成完成! Dir: {tests_dir}') + + except Exception as e: + logger.error(f'TestGen 阶段失败: {e}', exc_info=True) + sys.exit(1) + + # ========================================== + # Phase 4: Coding & Verify (Outer Loop) + # ========================================== + logger.info('\n--- Phase 4: Coding & Outer Loop ---') + + code_adapter = CodeAdapter(config, workspace) + error_log = '' + max_retries = config.max_retries + retry_count = 0 + success = False + + while retry_count <= max_retries: + logger.info(f'Attempt {retry_count + 1}/{max_retries + 1}') + + try: + # 1. Generate Code + res = code_adapter.run( + query=args.query, + spec_path=spec_path, + tests_dir=tests_dir, + error_log=error_log) + src_dir = res['src_dir'] + logger.info(f'Coding 完成! Src: {src_dir}') + + # 2. Verify (Run Tests) + logger.info('Running tests...') + exit_code, stdout, stderr = run_pytest(tests_dir, + workspace.work_dir) + + if exit_code == 0: + logger.info('✅ Tests Passed!') + success = True + break + else: + logger.warning(f'❌ Tests Failed (Exit Code: {exit_code})') + logger.debug(f'Stdout: {stdout}') + logger.debug(f'Stderr: {stderr}') + + # Prepare error log for next iteration + error_log = f'Test Failure Output:\n{stdout}\n{stderr}' + retry_count += 1 + + except Exception as e: + logger.error(f'Coding iteration failed: {e}', exc_info=True) + retry_count += 1 + error_log = str(e) + + if success: + logger.info('\n=== Orchestrator 流程成功结束 ===') + logger.info(f'最终交付物: {workspace.work_dir}') + else: + logger.error('\n=== Orchestrator 流程失败: 达到最大重试次数 ===') + sys.exit(1) + + +if __name__ == '__main__': + main() diff --git a/orchestrator/utils/__init__.py b/orchestrator/utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/orchestrator/utils/logger.py b/orchestrator/utils/logger.py new file mode 100644 index 000000000..ff720b702 --- /dev/null +++ b/orchestrator/utils/logger.py @@ -0,0 +1,46 @@ +import logging +import sys +from pathlib import Path + + +def setup_logger(workspace_path: Path) -> logging.Logger: + """ + 配置并返回一个 Logger 实例。 + 日志同时输出到控制台(INFO级别)和文件(DEBUG级别)。 + + Args: + workspace_path: 工作区根目录 Path 对象,日志将保存在 workspace_path/logs/orchestrator.log。 + + Returns: + logging.Logger 实例。 + """ + # 创建 logger + logger = logging.getLogger('Orchestrator') + logger.setLevel(logging.DEBUG) + + # 避免重复添加 handler + if logger.handlers: + return logger + + # 格式化器 + console_formatter = logging.Formatter('%(levelname)s: %(message)s') + file_formatter = logging.Formatter( + '%(asctime)s - %(name)s - %(levelname)s - %(message)s') + + # 1. 控制台 Handler (INFO) + console_handler = logging.StreamHandler(sys.stdout) + console_handler.setLevel(logging.INFO) + console_handler.setFormatter(console_formatter) + logger.addHandler(console_handler) + + # 2. 文件 Handler (DEBUG) + log_file = workspace_path / 'logs' / 'orchestrator.log' + # 确保目录存在 + log_file.parent.mkdir(parents=True, exist_ok=True) + + file_handler = logging.FileHandler(log_file, encoding='utf-8') + file_handler.setLevel(logging.DEBUG) + file_handler.setFormatter(file_formatter) + logger.addHandler(file_handler) + + return logger diff --git a/orchestrator/utils/verifier.py b/orchestrator/utils/verifier.py new file mode 100644 index 000000000..16d8fa18b --- /dev/null +++ b/orchestrator/utils/verifier.py @@ -0,0 +1,35 @@ +import subprocess +from pathlib import Path +from typing import Tuple + + +def run_pytest(tests_dir: Path, workdir: Path) -> Tuple[int, str, str]: + """ + 在工作区运行 pytest。 + + Args: + tests_dir: 包含测试文件的目录。 + workdir: 运行测试的工作目录 (通常是 workspace root, 以便正确 import src)。 + + Returns: + (exit_code, stdout, stderr) + """ + try: + # 确保 tests_dir 是相对于 workdir 的 + # 或者直接在 workdir 运行 "pytest tests/" + cmd = ['pytest', str(tests_dir)] + + # 设置 PYTHONPATH 包含 src + # env = os.environ.copy() + # env["PYTHONPATH"] = str(workdir) + + result = subprocess.run( + cmd, + cwd=workdir, + capture_output=True, + text=True, + timeout=60 # 超时设置 + ) + return result.returncode, result.stdout, result.stderr + except Exception as e: + return -1, '', str(e) diff --git a/projects/code_scratch/architecture.yaml b/projects/code_scratch/architecture.yaml index 76936bac1..b55f794b4 100644 --- a/projects/code_scratch/architecture.yaml +++ b/projects/code_scratch/architecture.yaml @@ -1,10 +1,9 @@ llm: service: openai - model: claude-sonnet-4-5-20250929 + model: openai_api_key: openai_base_url: https://dashscope.aliyuncs.com/compatible-mode/v1 - generation_config: temperature: 0.3 top_k: 50 @@ -14,7 +13,6 @@ generation_config: dashscope_extend_params: provider: b - prompt: system: | You are a senior software architect. Your responsibility is to break down complex requirements abount a frontend/backend project into implementable modules. You need to follow these instructions: diff --git a/projects/code_scratch/coding.yaml b/projects/code_scratch/coding.yaml index d138ad1aa..a4d91f781 100644 --- a/projects/code_scratch/coding.yaml +++ b/projects/code_scratch/coding.yaml @@ -1,10 +1,9 @@ llm: service: openai - model: claude-sonnet-4-5-20250929 + model: openai_api_key: openai_base_url: https://dashscope.aliyuncs.com/compatible-mode/v1 - generation_config: temperature: 0.2 top_k: 20 @@ -14,7 +13,6 @@ generation_config: dashscope_extend_params: provider: b - prompt: system: | You are a senior software project manager. Your responsibility is call `split_to_sub_task` to split the coding tasks, you should follow instructions: diff --git a/projects/code_scratch/refine.yaml b/projects/code_scratch/refine.yaml index a2ec5e96b..a3f8309ea 100644 --- a/projects/code_scratch/refine.yaml +++ b/projects/code_scratch/refine.yaml @@ -1,10 +1,9 @@ llm: service: openai - model: claude-sonnet-4-5-20250929 + model: openai_api_key: openai_base_url: https://dashscope.aliyuncs.com/compatible-mode/v1 - generation_config: temperature: 0.2 top_k: 20 @@ -14,7 +13,6 @@ generation_config: dashscope_extend_params: provider: b - prompt: system: | You are a senior software bug fixer. Your responsibility is to fix compilation errors based on the PRD designed by architects, the actual completed software code project, and compilation errors. diff --git a/skx-docs/00analysis/code_agent_analysis.md b/skx-docs/00analysis/code_agent_analysis.md new file mode 100644 index 000000000..569ab5373 --- /dev/null +++ b/skx-docs/00analysis/code_agent_analysis.md @@ -0,0 +1,72 @@ +# 代码代理分析文档 + +**日期**: 2025-11-27 +**作者**: Role C + +## 1. 系统架构分析 + +### 1.1 与现有系统集成 +角色C的编码代理需要与MS-Agent现有的架构无缝集成,特别是要与Role A的orchestrator模块协同工作。orchestrator作为编排器,负责整体流程的调度,而角色C专注于代码生成与验证。 + +### 1.2 组件设计 +编码代理系统主要包含以下组件: +- `CodeAgent`: 核心编码逻辑,基于LLM生成代码 +- `CodeWorkflow`: 管理完整的工作流程 +- `CodeVerifier`: 验证生成代码的功能正确性 +- `CodeAdapter`: 与orchestrator对接的适配器 + +### 1.3 数据流分析 +``` +tech_spec.md + tests/ --> CodeAgent --> src/ --> CodeVerifier --> Result + ↑ | + | | + +------------------- orchestrator -------------------+ +``` + +## 2. 技术选型分析 + +### 2.1 模型选择 +- 使用Qwen系列模型作为主要编码模型,因其在代码生成任务上的表现优秀 +- 考虑使用特定的代码模型如CodeQwen,如果可用 + +### 2.2 验证框架 +- 优先支持Pytest,因其是Python测试的标准框架 +- 同时兼容unittest等其他测试框架 +- 支持多种编程语言的测试框架 + +### 2.3 架构模式 +- 采用适配器模式,使编码代理能与不同的编排器对接 +- 采用策略模式,支持不同的编码和验证策略 +- 采用观察者模式,实时反馈编码进度 + +## 3. 接口设计分析 + +### 3.1 与orchestrator的接口 +- 输入:技术规范文档(tech_spec.md)和测试用例目录(tests/) +- 输出:源代码目录(src/)和验证结果 +- 错误处理:返回详细的错误信息,支持重试机制 + +### 3.2 内部接口 +- `CodeAgent.generate_from_spec()`: 根据规范生成代码 +- `CodeVerifier.run_tests()`: 运行测试验证代码 +- `CodeWorkflow.execute()`: 执行完整工作流程 + +## 4. 安全与质量分析 + +### 4.1 代码安全 +- 生成的代码需要经过安全扫描,防止注入恶意代码 +- 实施沙箱执行环境,确保生成的代码在安全环境下运行测试 + +### 4.2 代码质量 +- 集成代码质量检测工具(如pylint, flake8等) +- 实施代码规范检查,确保生成的代码符合最佳实践 + +## 5. 性能分析 + +### 5.1 生成效率 +- 评估不同模型在代码生成上的效率 +- 实现代码生成缓存,避免重复生成相同功能的代码 + +### 5.2 验证效率 +- 优化测试执行流程,减少验证时间 +- 实现并行测试执行,提高验证效率 \ No newline at end of file diff --git a/skx-docs/00analysis/external_integration_analysis.md b/skx-docs/00analysis/external_integration_analysis.md new file mode 100644 index 000000000..788c84430 --- /dev/null +++ b/skx-docs/00analysis/external_integration_analysis.md @@ -0,0 +1,75 @@ +# 外部集成分析 + +**日期**: 2025-11-27 +**作者**: Role C + +## 1. 集成目标分析 + +根据 00comprehensive_integration_plan.md 文档,角色C的核心任务是实现对 `projects/deep_research` 和 `projects/code_scratch` 的黑盒调用,并开发验证闭环系统。严格遵循"无侵入"原则,不修改现有模块内部实现。 + +## 2. 技术实现方案分析 + +### 2.1 黑盒调用方案 +- 使用 subprocess 调用 `projects/deep_research` 和 `projects/code_scratch` +- 所有集成代码均位于外部模块,不修改原项目代码 +- 需要设置正确的运行时环境(PYTHONPATH、环境变量等) + +### 2.2 与 Orchestrator 集成方案 +- 基于 Role A 提供的适配器接口 (`deep_research_adapter.py`, `code_adapter.py`) +- 扩展适配器功能,实现完整的外部工具调用逻辑 +- 遵循统一的数据流转标准 + +### 2.3 Prompt 注入实现方案 +- 读取 `tech_spec.md` 和 `tests/` 目录内容 +- 构造包含这些内容的 "元指令" (Meta-Instruction) +- 将元指令作为 `projects/code_scratch` 的输入query + +## 3. 接口设计分析 + +### 3.1 与 Orchestrator 的接口 +- 输入:用户查询、工作目录路径、配置参数 +- 输出:Deep Research结果或Code生成结果、验证状态、错误日志 +- 通过 Role A 的适配器模式与 Orchestrator 通信 + +### 3.2 内部组件接口 +- `DeepResearchCaller.run(query, output_dir)`: 执行深度研究 +- `CodeScratchCaller.run(prompt, work_dir)`: 执行代码生成 +- `PromptInjector.inject(spec_path, test_dir)`: 构造元指令 +- `TestRunner.run_tests(work_dir)`: 执行验证测试 + +## 4. 黑盒调用挑战分析 + +### 4.1 环境隔离 +- 需要确保外部工具调用不会影响当前进程环境 +- 可能需要使用独立的Python解释器进程 +- 避免全局变量或状态冲突 + +### 4.2 配置传递 +- 需要正确传递API密钥等配置给被调用的模块 +- 确保被调用模块可以访问必要的模型和资源 + +### 4.3 错误处理 +- 需要捕获外部工具的异常输出 +- 解析错误信息以进行故障诊断 +- 提供详细的错误日志反馈 + +## 5. 验证闭环设计分析 + +### 5.1 测试执行流程 +- 在code_scratch生成代码后,自动执行pytest +- 捕获测试结果和错误日志 +- 根据测试结果决定是否需要重试 + +### 5.2 错误反馈机制 +- 解析pytest输出,提取关键错误信息 +- 将错误信息构造为修复提示 +- 与orchestrator的重试机制集成 + +## 6. 无侵入原则遵守分析 + +所有实现将严格遵守无侵入原则: +- 不修改 `ms_agent/` 下的任何文件 +- 不修改 `projects/deep_research/` 下的任何文件 +- 不修改 `projects/code_scratch/` 下的任何文件 +- 所有新代码均位于 `external_integration/` 目录 +- 通过适配器模式与orchestrator集成 \ No newline at end of file diff --git a/skx-docs/00analysis/verification_flow.md b/skx-docs/00analysis/verification_flow.md new file mode 100644 index 000000000..8cffd81de --- /dev/null +++ b/skx-docs/00analysis/verification_flow.md @@ -0,0 +1,105 @@ +# 验证流程分析 + +**日期**: 2025-11-27 +**作者**: Role C + +## 1. 验证流程概述 + +验证流程是角色C的核心组件之一,其主要目标是确保生成的代码符合预期的功能要求。该流程与Role A的orchestrator紧密集成,形成一个反馈闭环,用于持续优化代码质量。 + +## 2. 验证流程设计 + +### 2.1 验证阶段 +验证流程包含以下几个阶段: + +1. **静态分析阶段**: + - 检查代码语法 + - 验证代码规范(如PEP8) + - 运行代码质量检查工具 + +2. **动态测试阶段**: + - 执行Role B生成的测试用例 + - 验证边界条件 + - 运行性能测试(如适用) + +3. **安全扫描阶段**: + - 检测潜在的安全漏洞 + - 验证代码注入等安全问题 + +### 2.2 验证流程图 +``` + +-------------------+ + | Generated Code | + +-------------------+ + | + v + +-------------------+ + | Static Analysis | + +-------------------+ + | + v + +-------------------+ + | Dynamic Testing | + +-------------------+ + | + v + +-------------------+ + | Security Scan | + +-------------------+ + | + v + Pass/Fail? + | + +-------+-------+ + | | + v v + Success Output Error Log +``` + +## 3. 与orchestrator集成 + +### 3.1 接口设计 +验证器需要与orchestrator进行交互: +- 输入:生成的源代码路径、测试用例路径 +- 输出:验证结果、错误日志、覆盖率信息 + +### 3.2 反馈机制 +当验证失败时,验证器需要向orchestrator反馈详细的错误信息,以便: +1. Role A的orchestrator可以触发重试机制 +2. Role C的编码代理可以根据错误日志进行代码修复 + +## 4. 技术实现 + +### 4.1 测试框架选择 +- 首选Pytest,因其功能强大且易于扩展 +- 支持JUnit或其他测试框架(多语言支持) + +### 4.2 验证覆盖率 +- 实现代码覆盖率检查 +- 确保生成的测试用例覆盖主要功能路径 + +### 4.3 验证环境 +- 使用隔离环境运行验证,避免影响系统环境 +- 支持Docker容器化测试环境 + +## 5. 错误处理与重试机制 + +### 5.1 错误分类 +- 语法错误:代码无法解析 +- 逻辑错误:代码逻辑不符合预期 +- 运行时错误:代码在执行时出错 + +### 5.2 重试策略 +- 基于错误类型决定重试方式 +- 实现智能错误定位,帮助编码代理理解失败原因 +- 设置最大重试次数,防止无限循环 + +## 6. 性能优化 + +### 6.1 并行验证 +- 支持并行运行多个测试用例 +- 优化资源使用,提高验证效率 + +### 6.2 测试选择 +- 智能选择最相关的测试用例进行验证 +- 避免运行所有测试用例,提高验证速度 \ No newline at end of file diff --git a/skx-docs/00analysis/verification_loop_design.md b/skx-docs/00analysis/verification_loop_design.md new file mode 100644 index 000000000..4ad443e81 --- /dev/null +++ b/skx-docs/00analysis/verification_loop_design.md @@ -0,0 +1,108 @@ +# 验证闭环设计 + +**日期**: 2025-11-27 +**作者**: Role C + +## 1. 验证闭环概述 + +验证闭环是角色C的核心功能之一,负责确保生成的代码符合技术规范和测试要求。它通过自动运行测试、分析结果并反馈错误信息来实现代码的持续改进。 + +## 2. 验证闭环流程 + +### 2.1 验证阶段 +验证闭环包含以下几个阶段: + +1. **代码生成完成**: + - Role C调用code_scratch完成代码生成 + - 生成的代码位于工作目录的src/子目录 + +2. **测试执行**: + - 自动运行Role B生成的测试用例 + - 执行pytest验证代码功能 + +3. **结果分析**: + - 分析测试输出(stdout/stderr) + - 判断测试是否通过 + +4. **反馈决策**: + - 如果通过,向orchestrator返回成功状态 + - 如果失败,提取错误信息,触发重试 + +### 2.2 验证闭环流程图 +``` + +-------------------+ + | Generated Code | + +-------------------+ + | + v + +-------------------+ + | Run Pytest | + +-------------------+ + | + v + +-------------------+ + | Analyze Output | + +-------------------+ + | + v + Pass/Fail? + | + +-------+-------+ + | | + v v + Success to Extract Error + Orchestrator Info & Retry +``` + +## 3. 与 Orchestrator 集成 + +### 3.1 接口设计 +验证系统需要与orchestrator进行交互: +- 输入:工作目录路径(包含生成的代码和测试) +- 输出:验证结果、错误日志、重试建议 + +### 3.2 反馈机制 +当验证失败时,验证器需要向orchestrator反馈详细的信息,以便: +1. Role A的orchestrator可以触发重试机制 +2. Role C可以根据错误日志重新构造提示并再次调用code_scratch + +## 4. 技术实现 + +### 4.1 测试执行 +- 使用subprocess调用pytest +- 捕获stdout和stderr输出 +- 解析pytest的JSON或JUnit格式输出(如果可用) + +### 4.2 错误解析 +- 识别Python异常类型和位置 +- 提取关键错误信息 +- 过滤环境或配置相关的错误 + +### 4.3 重试触发 +- 定义触发重试的错误类型 +- 构造包含错误信息的修复提示 +- 与orchestrator的外循环机制集成 + +## 5. 错误处理策略 + +### 5.1 错误分类 +- 语法错误:代码无法解析或运行 +- 逻辑错误:代码运行但结果不符合预期 +- 测试错误:测试用例本身的错误 + +### 5.2 重试逻辑 +- 基于错误类型决定重试方式 +- 将错误信息整合到新的提示中 +- 设置最大重试次数限制 + +## 6. 性能与监控 + +### 6.1 测试效率 +- 优化测试执行速度 +- 支持测试并行执行 +- 只运行相关的测试用例 + +### 6.2 监控指标 +- 测试执行时间 +- 成功/失败率 +- 平均重试次数 \ No newline at end of file diff --git a/skx-docs/01goals/integration_plan.md b/skx-docs/01goals/integration_plan.md new file mode 100644 index 000000000..f9cfcfb58 --- /dev/null +++ b/skx-docs/01goals/integration_plan.md @@ -0,0 +1,115 @@ +# 与编排器集成计划 + +**日期**: 2025-11-27 +**作者**: Role C + +## 1. 集成概述 + +本计划描述了角色C的编码代理如何与Role A开发的orchestrator(编排器)进行集成。集成的目标是实现从技术规范到可执行代码的自动化流程,并支持错误反馈和自动修复机制。 + +## 2. 集成架构 + +### 2.1 系统组件关系 +``` +User Query + | + v +Orchestrator (Role A) + | + | (report.md) + v +Role B (Spec/Test Gen) + | + | (tech_spec.md, tests/) + v +Orchestrator (传递给Role C) + | + | (调用CodeAdapter) + v +Role C (本系统: CodeAgent) + | + | (src/, verification result) + v +Orchestrator + | + | (如有错误,触发重试) + v +(循环至成功或达到最大重试次数) +``` + +### 2.2 集成接口 + +#### 2.2.1 输入接口 +- **技术规范文件**: `tech_spec.md` - 详细描述所需实现的功能 +- **测试用例目录**: `tests/` - Role B生成的测试用例 +- **配置参数**: 从orchestrator传递的运行时参数 + +#### 2.2.2 输出接口 +- **源代码目录**: `src/` - 生成的完整源代码 +- **验证结果**: 包含测试结果、错误日志等信息 +- **状态报告**: 生成进度和状态信息 + +## 3. 集成实现 + +### 3.1 适配器模式实现 +遵循Role A定义的适配器模式,需要实现`CodeAdapter`类,该类将: +- 继承`BaseAdapter`抽象基类 +- 实现标准的接口方法 +- 遵循orchestrator定义的调用协议 + +### 3.2 数据格式约定 +- 输入:技术规范采用Role A和Role B定义的Markdown格式 +- 输出:源代码遵循项目结构约定,存放在src/目录下 +- 日志:采用JSON或标准日志格式,便于orchestrator解析 + +## 4. 交互流程 + +### 4.1 正常流程 +1. Orchestrator调用CodeAdapter的执行方法 +2. CodeAdapter初始化CodeAgent +3. CodeAgent解析技术规范和测试用例 +4. CodeAgent生成代码 +5. CodeAgent运行验证流程 +6. CodeAdapter返回结果给orchestrator + +### 4.2 错误处理流程 +1. 如果验证失败,CodeAgent生成错误日志 +2. CodeAdapter将错误日志返回给orchestrator +3. Orchestrator根据错误信息决定是否重试 +4. 如果重试,orchestrator再次调用CodeAdapter并传递错误信息 + +## 5. 集成测试 + +### 5.1 单元测试 +- 测试CodeAdapter与orchestrator接口的兼容性 +- 验证输入输出数据格式的正确性 +- 测试错误处理机制 + +### 5.2 集成测试 +- 在orchestrator环境中测试完整的端到端流程 +- 验证错误反馈和重试机制 +- 测试性能和稳定性 + +## 6. 部署与配置 + +### 6.1 环境要求 +- 与orchestrator相同的Python环境 +- 访问相同的服务(如LLM API、文件系统等) +- 兼容orchestrator的配置管理 + +### 6.2 部署方式 +- 作为orchestrator的依赖模块部署 +- 遵循orchestrator的版本管理策略 +- 支持orchestrator的配置机制 + +## 7. 监控与维护 + +### 7.1 日志记录 +- 记录与orchestrator的交互日志 +- 记录代码生成和验证的详细过程 +- 记录错误和异常情况 + +### 7.2 性能监控 +- 监控代码生成时间 +- 监控验证流程性能 +- 监控系统资源使用情况 \ No newline at end of file diff --git a/skx-docs/01goals/integration_with_role_a.md b/skx-docs/01goals/integration_with_role_a.md new file mode 100644 index 000000000..f3febc84e --- /dev/null +++ b/skx-docs/01goals/integration_with_role_a.md @@ -0,0 +1,114 @@ +# 与角色A集成计划 + +**日期**: 2025-11-27 +**作者**: Role C + +## 1. 集成概述 + +本计划描述了角色C如何以最小化修改的方式与Role A开发的orchestrator(编排器)进行集成。角色C负责外部工具集成与验证闭环,将通过最少的代码修改替换Role A提供的Mock实现,实现完整的"Research-to-Code"流水线。 + +## 2. 集成架构 + +### 2.1 系统组件关系 +``` +User Query + | + v +Orchestrator (Role A) + | + | (选择调用模式) + v +Orchestrator -> Deep Research? -> Role C (Deep Research Adapter) + | | + | v + | (产出report.md) + | | + +--------> Spec/Test Gen (Role B) + | + v + (tech_spec.md, tests/) + | + +-----------------+ + | + v +Orchestrator -> Code Integration? -> Role C (Code Adapter) + | | + | (Prompt Injection) + | | + | (Code Generation) + | | + | (Test Execution) + | | + +--> Orchestrator (处理结果或错误反馈) +``` + +### 2.2 集成接口 + +#### 2.2.1 输入接口 +- **用户查询**: 从orchestrator传入的原始用户请求 +- **工作目录**: orchestrator指定的工作目录路径 +- **配置参数**: 从orchestrator传递的运行时参数 + +#### 2.2.2 输出接口 +- **Deep Research结果**: 生成的 `report.md` 文件 +- **Code生成结果**: 生成的代码文件在 `src/` 目录 +- **验证结果**: 测试执行状态和错误日志 +- **状态报告**: 执行进度和状态信息 + +## 3. 最小化修改集成实现 + +### 3.1 替换适配器实现 +- **修改文件**: `orchestrator/adapters/deep_research_adapter.py` + - 保持现有的类结构和接口 + - 将Mock实现替换为调用 `external_integration/deep_research_caller.py` + +- **修改文件**: `orchestrator/adapters/code_adapter.py` + - 保持现有的类结构和接口 + - 将Mock实现替换为完整的外部工具调用逻辑 + - 集成 `external_integration/prompt_injector.py` 和 `external_integration/test_runner.py` + +### 3.2 数据格式约定 +- 输入:遵循orchestrator定义的查询格式 +- 输出:生成符合orchestrator期望的文件结构 +- 日志:采用orchestrator支持的日志格式 + +## 4. 交互流程 + +### 4.1 Deep Research流程 +1. Orchestrator调用`DeepResearchAdapter.run()` +2. 适配器使用`external_integration.DeepResearchCaller`执行外部调用 +3. 将生成的报告保存到指定工作目录 +4. 适配器返回执行结果给orchestrator + +### 4.2 Code生成与验证流程 +1. Orchestrator调用`CodeAdapter.run()`并传入spec和tests路径 +2. 适配器使用`external_integration.PromptInjector`构造元指令 +3. 使用`external_integration.CodeScratchCaller`执行代码生成 +4. 使用`external_integration.TestRunner`执行验证测试 +5. 适配器返回结果或错误信息给orchestrator + +### 4.3 错误处理与重试流程 +1. 如果验证失败,`TestRunner`生成错误日志 +2. `CodeAdapter`将错误信息返回给orchestrator +3. Orchestrator根据错误信息决定是否重试 +4. 如果重试,orchestrator再次调用`CodeAdapter`并传递错误信息 + +## 5. 修改范围总结 + +### 5.1 需要修改的文件(最小化修改) +- `orchestrator/adapters/deep_research_adapter.py` - 替换内部实现 +- `orchestrator/adapters/code_adapter.py` - 替换内部实现 + +### 5.2 新增的外部模块 +- `external_integration/` 目录及所有内容 +- skx-docs目录文档 + +## 6. 部署与配置 + +### 6.1 环境要求 +- 与orchestrator相同的Python环境 +- 访问相同的服务(如LLM API、文件系统等) + +### 6.2 集成方式 +- 作为orchestrator的功能扩展模块 +- 遵循orchestrator的版本管理策略 \ No newline at end of file diff --git a/skx-docs/01goals/role_c_goals.md b/skx-docs/01goals/role_c_goals.md new file mode 100644 index 000000000..2c56253e9 --- /dev/null +++ b/skx-docs/01goals/role_c_goals.md @@ -0,0 +1,78 @@ +# 角色C目标文档 + +**日期**: 2025-11-27 +**责任人**: Role C (Integration Engineer & Verification Loop) + +## 1. 总体目标 + +实现外部工具集成与验证闭环系统,能够无侵入式地调用Deep Research和Code Scratch模块,构造"元指令"将技术规范和测试用例注入到代码生成流程,并实现自动化的验证与错误反馈机制。与Role A的orchestrator无缝集成,形成完整的"Query -> Deep Research/Code -> Verify -> Retry"闭环。 + +## 2. 技术目标 + +### 2.1 黑盒调用能力 +- 实现对 `projects/deep_research` 模块的无侵入式调用 +- 实现对 `projects/code_scratch` 模块的无侵入式调用 +- 确保外部调用的安全性和环境隔离 + +### 2.2 Prompt注入能力 +- 实现"元指令"(Meta-Instruction)构造器 +- 将Role B生成的技术规范和测试用例注入到code_scratch中 +- 确保注入的上下文能够正确指导代码生成 + +### 2.3 验证闭环能力 +- 实现自动化测试执行(Pytest) +- 实现错误日志的分析与提取 +- 实现基于错误反馈的重试机制 + +## 3. 功能目标 + +### 3.1 核心功能 +- [ ] Deep Research调用:根据query调用deep_research并获取结果 +- [ ] Code Scratch调用:使用注入的上下文调用code_scratch生成代码 +- [ ] 验证执行:自动运行测试并分析结果 +- [ ] 错误反馈:提取错误信息并支持重试 + +### 3.2 辅助功能 +- [ ] 环境隔离:确保外部调用不影响当前环境 +- [ ] 进度监控:向orchestrator报告执行进度 +- [ ] 日志记录:详细记录调用过程和结果 +- [ ] 配置管理:正确传递环境变量和配置参数 + +## 4. 质量目标 + +### 4.1 功能质量 +- 成功调用Deep Research和Code Scratch模块 +- 正确解析并注入技术规范和测试用例 +- 验证系统能准确识别代码是否通过测试 + +### 4.2 系统性能 +- 单次外部调用时间不超过3分钟 +- 验证过程执行时间不超过30秒 +- 系统可用性达到99% + +### 4.3 错误处理 +- 95%的运行时错误能够被正确捕获和处理 +- 错误信息描述清晰,便于调试 +- 提供重试机制,最多重试3次 + +## 5. 集成目标 + +### 5.1 与Role A的集成 +- 实现orchestrator要求的所有适配器接口 +- 遵循orchestrator定义的数据格式 +- 支持orchestrator的外循环重试机制 +- 提供详细的错误日志支持调试 + +### 5.2 与Role B的协作 +- 正确处理Role B生成的技术规范文档 +- 执行Role B生成的测试用例 +- 反馈代码生成结果以优化规范和测试 + +## 6. 验收标准 + +- [ ] 成功集成到orchestrator的完整流程中 +- [ ] 能够无侵入式调用Deep Research模块 +- [ ] 能够使用Prompt注入调用Code Scratch模块 +- [ ] 生成的代码能够通过Role B的测试 +- [ ] 实现至少一次基于错误的自动重试 +- [ ] 完成端到端的演示验证 \ No newline at end of file diff --git a/skx-docs/02todos/0.0_Role_C_Delivery_Note.md b/skx-docs/02todos/0.0_Role_C_Delivery_Note.md new file mode 100644 index 000000000..eb65a7eb2 --- /dev/null +++ b/skx-docs/02todos/0.0_Role_C_Delivery_Note.md @@ -0,0 +1,97 @@ +# Role C 交付文档: 外部工具集成与验证闭环 + +**日期**: 2025-11-27 +**责任人**: Role C (Integration Engineer & Verification Loop) + +## 1. 变更文件树 (File Tree of Changes) + +本次开发构建了外部工具集成与验证系统,实现Deep Research与Code Scratch的黑盒调用、Prompt注入和外循环验证。严格遵循无侵入原则,不在任何原模块内部添加代码。 + +```text +. +├── orchestrator/ +│ └── adapters/ +│ ├── deep_research_adapter.py # [MOD] 角色A提供基础,角色C完善 +│ └── code_adapter.py # [MOD] 角色A提供基础,角色C完善 +├── external_integration/ # [NEW] 角色C外部集成模块 +│ ├── __init__.py +│ ├── deep_research_caller.py # [NEW] Deep Research黑盒调用 +│ ├── code_scratch_caller.py # [NEW] Code Scratch黑盒调用 +│ ├── prompt_injector.py # [NEW] Prompt注入器 +│ └── test_runner.py # [NEW] 测试运行器与验证闭环 +├── skx-docs/ # [NEW] 角色C文档目录 +│ ├── 00analysis/ +│ │ ├── external_integration_analysis.md # 外部集成分析 +│ │ └── verification_loop_design.md # 验证闭环设计 +│ ├── 01goals/ +│ │ ├── role_c_goals.md # 角色C目标 +│ │ └── integration_with_role_a.md # 与角色A集成计划 +│ └── 02todos/ +│ ├── 0.0_Role_C_Delivery_Note.md # 本交付文档 +│ └── 0.1_Role_C_Integration_Plan.md # 集成实施计划 +└── tests/ + └── test_external_integration.py # [NEW] 外部集成测试 +``` + +## 2. 完成工作总结 (Summary of Work) + +1. **Deep Research 集成**: 实现了对 `projects/deep_research` 模块的黑盒调用封装,通过外部subprocess调用实现无侵入式集成。 +2. **Code Scratch 集成**: 实现了对 `projects/code_scratch` 模块的黑盒调用,通过外部subprocess调用实现无侵入式集成。 +3. **Prompt 注入机制**: 开发了 "元指令" (Meta-Instruction) 构造器,将技术规范和测试用例注入到代码生成流程中。 +4. **验证闭环系统**: 实现了自动化的 Pytest 执行、错误日志提取和修复反馈机制。 +5. **与 Orchestrator 集成**: 与 Role A 的适配器模式无缝集成,支持外循环重试机制。 + +## 3. 使用指南 (User Guide) + +### 3.1 环境准备 + +确保安装了项目依赖: + +```bash +pip install -r requirements/framework.txt +pip install -r requirements/research.txt +pip install -r requirements/code.txt +``` + +设置必要的环境变量: + +```bash +export OPENAI_API_KEY="sk-xxx" +export MODELSCOPE_API_KEY="ms-xxx" +``` + +### 3.2 与 Orchestrator 集成使用 + +角色C的组件将通过Role A的orchestrator自动调用,无需单独启动,orchestrator会按以下流程调用: + +1. Role A解析输入并决定调用模式 +2. 如果需要Deep Research,调用Role C的deep_research_adapter +3. Role B处理技术规范和测试生成 +4. Role A将tech_spec.md和tests/传递给Role C的code_adapter +5. Role C执行Prompt注入并调用code_scratch +6. Role C运行验证器并返回结果 + +### 3.3 独立使用 + +也可以独立使用验证闭环系统: + +```bash +python3 -c " +from external_integration.test_runner import TestRunner +runner = TestRunner() +result = runner.run_tests_with_feedback('./workspace/run_XXXX/', './error_log.txt') +print(result.summary) +" +``` + +### 3.4 配置说明 + +- 通过orchestrator的配置文件配置模型参数和重试次数 +- 验证系统的配置也在orchestrator中统一管理 + +## 4. 与 Role A 的协同说明 + +- **输入接口**: 接收来自Role A编排器的query、tech_spec.md和tests/目录 +- **输出接口**: 向编排器返回Deep Research结果或Code生成结果 +- **错误处理**: 当Code验证失败时,提供详细的错误日志用于触发重试 +- **适配器集成**: 增强Role A提供的适配器实现,提供完整的功能 \ No newline at end of file diff --git a/skx-docs/02todos/0.1_Role_C_Coding_Plan.md b/skx-docs/02todos/0.1_Role_C_Coding_Plan.md new file mode 100644 index 000000000..8f300fdb6 --- /dev/null +++ b/skx-docs/02todos/0.1_Role_C_Coding_Plan.md @@ -0,0 +1,105 @@ +# Role C: 智能编码代理实施计划 (Coding/Verify Agent) + +**责任人**: C +**目标**: 构建能够根据技术规范和测试用例生成高质量代码的智能代理,并实现自动验证与错误修复机制 +**依据**: [00comprehensive_integration_plan.md](../../chao-docs/01goals/00comprehensive_integration_plan.md) 和 [0.0_Role_C_Delivery_Note.md](0.0_Role_C_Delivery_Note.md) + +--- + +## 阶段 0: 架构设计与接口对接 (Day 1) +> **目标**: 确立编码代理架构,与Role A的编排器接口对接,定义数据流转标准 + +- [ ] **0.1 设计编码代理核心架构** + - [ ] 创建目录结构: + ```text + ms_agent/ + └── agent/ + ├── code_agent.py # 核心编码代理类 + ├── code_workflow.py # 代码生成工作流 + ├── verifier.py # 自动验证器 + └── __init__.py + projects/ + └── code_assist/ + ├── __init__.py + ├── architecture.yaml # 代理架构配置 + ├── coding.yaml # 编码阶段配置 + └── verification.yaml # 验证阶段配置 + ``` +- [ ] **0.2 实现与编排器的接口契约** + - [ ] 定义输入:`tech_spec.md` (技术规范) 和 `tests/` 目录 (测试用例) + - [ ] 定义输出:`src/` 目录(生成的源代码) + - [ ] 与Role A确认 `code_adapter.py` 的接口规范 +- [ ] **0.3 编写配置管理模块** + - [ ] 实现 `projects/code_assist/coding.yaml`,支持模型、温度、重试次数等参数 + - [ ] 实现 `projects/code_assist/verification.yaml`,支持测试框架、超时等参数 + +--- + +## 阶段 1: 核心编码代理开发 (Day 2-3) +> **目标**: 实现基础的编码代理功能,能根据技术规范生成代码 + +- [ ] **1.1 实现基础编码代理 (`agent/code_agent.py`)** + - [ ] **类**: `CodeAgent` + - [ ] **功能**: 接收技术规范文档,生成符合要求的代码文件 + - [ ] **方法**: + - `generate_from_spec(spec_path, tests_dir)` - 根据规范和测试生成代码 + - `refine_code(error_log)` - 基于错误日志优化代码 +- [ ] **1.2 实现代码工作流 (`agent/code_workflow.py`)** + - [ ] **类**: `CodeWorkflow` + - [ ] **功能**: 管理完整的从规范到代码的生成流程 + - [ ] **流程**: 解析规范 → 生成代码 → 运行验证 → 迭代修复 +- [ ] **1.3 编写编码提示工程** + - [ ] 设计用于代码生成的系统提示和用户提示 + - [ ] 集成不同编程语言和框架的代码模板 + +--- + +## 阶段 2: 验证系统集成 (Day 3-4) +> **目标**: 集成自动化验证和错误修复机制 + +- [ ] **2.1 实现代码验证器 (`agent/verifier.py`)** + - [ ] **类**: `CodeVerifier` + - [ ] **功能**: 运行预生成的测试用例,验证代码正确性 + - [ ] **输出**: 通过/失败状态,详细的错误日志 +- [ ] **2.2 与现有测试框架集成** + - [ ] 集成 Pytest 框架 + - [ ] 支持单元测试、集成测试的运行 +- [ ] **2.3 实现错误修复工作流** + - [ ] 将错误日志反馈给编码代理 + - [ ] 实现代码自动迭代修复逻辑 + +--- + +## 阶段 3: 与编排器集成 (Day 4-5) +> **目标**: 实现与Role A编排器的无缝集成 + +- [ ] **3.1 开发适配器接口** + - [ ] 修改 `orchestrator/adapters/code_adapter.py`,替换mock实现 + - [ ] 实现真实的编码代理调用逻辑 +- [ ] **3.2 测试集成接口** + - [ ] 验证编排器能够正确调用编码代理 + - [ ] 测试错误处理和重试机制 +- [ ] **3.3 性能优化** + - [ ] 优化代码生成速度 + - [ ] 实现代码生成缓存机制 + +--- + +## 阶段 4: 全链路联调与优化 (Day 5) +> **目标**: 完成与编排器的全链路联调,确保"Spec -> Code -> Verify -> Retry"闭环 + +- [ ] **4.1 全链路功能验证** + - [ ] 验证从技术规范到代码生成的完整流程 + - [ ] 验证错误重试机制的有效性 +- [ ] **4.2 性能验证** + - [ ] 验证代码质量和生成效率 + - [ ] 测试大规模代码生成场景 +- [ ] **4.3 文档和交付** + - [ ] 编写用户使用指南 + - [ ] 准备与Role A的接口规范文档 + +--- + +## 依赖项 +- 需要 Role A 提供 `orchestrator/adapters/code_adapter.py` 的接口规范 +- 需要 Role B 提供 `tech_spec.md` 和 `tests/` 标准格式 \ No newline at end of file diff --git a/skx-docs/02todos/0.1_Role_C_Integration_Plan.md b/skx-docs/02todos/0.1_Role_C_Integration_Plan.md new file mode 100644 index 000000000..78ac9de3b --- /dev/null +++ b/skx-docs/02todos/0.1_Role_C_Integration_Plan.md @@ -0,0 +1,92 @@ +# Role C: 外部工具集成与验证闭环实施计划 (Integration Engineer & Verification Loop) + +**责任人**: C (skx) +**目标**: 实现对Deep Research和Code Scratch模块的黑盒调用、Prompt注入机制和外循环验证系统,并以最小化修改的方式与Role A的orchestrator集成 +**依据**: [00comprehensive_integration_plan.md](../../chao-docs/01goals/00comprehensive_integration_plan.md) + +--- + +## 阶段 0: 接口对接与依赖分析 (Day 1) +> **目标**: 与Role A定义接口契约,分析orchestrator适配器接口,分析Deep Research和Code Scratch模块的调用方式 + +- [ ] **0.1 分析orchestrator适配器接口** + - [ ] 研究 `orchestrator/adapters/deep_research_adapter.py` 的Mock实现 + - [ ] 研究 `orchestrator/adapters/code_adapter.py` 的Mock实现 + - [ ] 确认接口方法签名和返回值格式 +- [ ] **0.2 分析Deep Research模块调用方式** + - [ ] 研究 `projects/deep_research` 的CLI接口 + - [ ] 分析其运行时依赖和配置要求 + - [ ] 确定如何传入query和获取输出 +- [ ] **0.3 分析Code Scratch模块调用方式** + - [ ] 研究 `projects/code_scratch` 的CLI接口 + - [ ] 分析其运行时依赖和工作目录要求 + - [ ] 确定如何传入技术规范和测试 + +--- + +## 阶段 1: 外部工具调用封装 (Day 2) +> **目标**: 实现对Deep Research和Code Scratch的黑盒调用封装 + +- [ ] **1.1 实现Deep Research调用器 (`external_integration/deep_research_caller.py`)** + - [ ] **类**: `DeepResearchCaller` + - [ ] **功能**: 通过subprocess调用 `projects/deep_research`,传入用户query + - [ ] **输出**: 将生成的报告保存到指定的工作目录 +- [ ] **1.2 实现Code Scratch调用器 (`external_integration/code_scratch_caller.py`)** + - [ ] **类**: `CodeScratchCaller` + - [ ] **功能**: 通过subprocess调用 `projects/code_scratch`,使用预设的spec和tests + - [ ] **环境**: 确保在隔离环境中运行,不影响系统状态 + +--- + +## 阶段 2: Prompt 注入与验证系统开发 (Day 2-3) +> **目标**: 实现将技术规范和测试用例注入到代码生成流程的核心机制,以及验证闭环系统 + +- [ ] **2.1 实现Prompt注入器 (`external_integration/prompt_injector.py`)** + - [ ] **类**: `PromptInjector` + - [ ] **功能**: 读取 `tech_spec.md` 和 `tests/` 目录,构造"元指令" + - [ ] **输出**: 构造的完整prompt,包含"请遵循tech_spec.md并使tests/中的测试通过"的指令 +- [ ] **2.2 实现测试运行器 (`external_integration/test_runner.py`)** + - [ ] **类**: `TestRunner` + - [ ] **功能**: 在指定目录下运行 `pytest`,捕获输出和错误 + - [ ] **输出**: 测试结果、错误日志、覆盖率信息 +- [ ] **2.3 实现错误分析与反馈机制** + - [ ] 解析 `pytest` 的错误输出 + - [ ] 提取关键错误信息用于修复任务构造 + - [ ] 实现错误日志格式化功能 + +--- + +## 阶段 3: 最小化集成orchestrator (Day 4) +> **目标**: 以最小化修改的方式更新orchestrator适配器 + +- [ ] **3.1 更新Deep Research适配器** + - [ ] 修改 `orchestrator/adapters/deep_research_adapter.py` + - [ ] 保持现有类结构和接口 + - [ ] 将Mock实现替换为调用 `external_integration.DeepResearchCaller` +- [ ] **3.2 更新Code适配器** + - [ ] 修改 `orchestrator/adapters/code_adapter.py` + - [ ] 保持现有类结构和接口 + - [ ] 集成 `external_integration.PromptInjector`、`CodeScratchCaller`和`TestRunner` + - [ ] 实现完整的从spec到code到验证的流程 + +--- + +## 阶段 4: 集成测试与优化 (Day 5) +> **目标**: 完成与整个系统的联调,确保"Query -> Deep Research -> Spec/Test -> Code -> Verify -> Retry"闭环 + +- [ ] **4.1 端到端功能验证** + - [ ] 验证从用户查询到Deep Research结果的完整流程 + - [ ] 验证从Spec/Test到Code生成及验证的完整流程 + - [ ] 验证错误重试机制的有效性 +- [ ] **4.2 性能与稳定性验证** + - [ ] 测试大规模调用场景下的稳定性 + - [ ] 优化subprocess调用性能 +- [ ] **4.3 文档和交付** + - [ ] 编写集成使用指南 + - [ ] 准备与Role A的接口规范文档 + +--- + +## 依赖项 +- 需要 Role A 提供的 orchestrator 框架及其适配器接口规范 +- 需要 Role B 提供 `tech_spec.md` 和 `tests/` 标准格式 \ No newline at end of file diff --git a/skx-docs/02todos/1.0_Core_Architecture_Tasks.md b/skx-docs/02todos/1.0_Core_Architecture_Tasks.md new file mode 100644 index 000000000..8ceec6f32 --- /dev/null +++ b/skx-docs/02todos/1.0_Core_Architecture_Tasks.md @@ -0,0 +1,34 @@ +# 1.0 外部工具调用封装任务 + +**责任人**: Role C +**目标**: 实现对Deep Research和Code Scratch模块的黑盒调用封装 + +## 任务列表 + +### 1.1 创建外部集成目录结构 +- [ ] 创建 `external_integration/` 目录(在项目根目录下) + - [ ] `__init__.py` - 模块初始化文件 + - [ ] `deep_research_caller.py` - Deep Research调用器 + - [ ] `code_scratch_caller.py` - Code Scratch调用器 + - [ ] `prompt_injector.py` - Prompt注入器(后续任务) + - [ ] `test_runner.py` - 测试运行器(后续任务) + +### 1.2 实现Deep Research调用器 +- [ ] 创建 `external_integration/deep_research_caller.py` + - [ ] 定义 `DeepResearchCaller` 类 + - [ ] 实现 `run(query, output_dir)` 方法 + - [ ] 处理环境变量和配置传递 + - [ ] 实现错误处理和日志记录 + +### 1.3 实现Code Scratch调用器 +- [ ] 创建 `external_integration/code_scratch_caller.py` + - [ ] 定义 `CodeScratchCaller` 类 + - [ ] 实现 `run(prompt, work_dir)` 方法 + - [ ] 确保工作目录和文件路径正确设置 + - [ ] 实现环境隔离和资源管理 + +### 1.4 实现基础工具类 +- [ ] 实现工具函数支持外部调用 + - [ ] 命令构建函数 + - [ ] 进程管理函数 + - [ ] 输出解析函数 \ No newline at end of file diff --git a/skx-docs/02todos/2.0_Verification_Repair_Tasks.md b/skx-docs/02todos/2.0_Verification_Repair_Tasks.md new file mode 100644 index 000000000..6cbee6ca0 --- /dev/null +++ b/skx-docs/02todos/2.0_Verification_Repair_Tasks.md @@ -0,0 +1,32 @@ +# 2.0 Prompt注入与验证系统任务 + +**责任人**: Role C +**目标**: 实现Prompt注入机制和验证闭环系统 + +## 任务列表 + +### 2.1 实现Prompt注入器 +- [ ] 创建 `ms_agent/external_integration/prompt_injector.py` + - [ ] 定义 `PromptInjector` 类 + - [ ] 实现 `inject(spec_path, test_dir, base_query)` 方法 + - [ ] 实现技术规范和测试用例的读取与格式化 + - [ ] 构造"元指令",包含遵循spec和通过test的指示 + +### 2.2 实现测试运行器 +- [ ] 创建 `ms_agent/external_integration/test_runner.py` + - [ ] 定义 `TestRunner` 类 + - [ ] 实现 `run_tests(work_dir)` 方法 + - [ ] 捕获pytest输出和错误日志 + - [ ] 解析测试结果并判断成功/失败 + +### 2.3 实现错误分析与反馈 +- [ ] 增强 `TestRunner` 的错误分析能力 + - [ ] 解析Python异常信息 + - [ ] 提取关键错误位置和原因 + - [ ] 生成错误摘要用于重试 +- [ ] 实现错误日志格式化功能 + +### 2.4 集成验证与注入功能 +- [ ] 在Code Scratch调用流程中集成Prompt注入 +- [ ] 在Code生成后自动执行验证测试 +- [ ] 实现结果反馈机制 \ No newline at end of file diff --git a/skx-docs/02todos/3.0_Orchestrator_Integration_Tasks.md b/skx-docs/02todos/3.0_Orchestrator_Integration_Tasks.md new file mode 100644 index 000000000..740176fd2 --- /dev/null +++ b/skx-docs/02todos/3.0_Orchestrator_Integration_Tasks.md @@ -0,0 +1,35 @@ +# 3.0 与 Orchestrator 集成任务 + +**责任人**: Role C +**目标**: 完善适配器实现,与Role A的orchestrator无缝集成 + +## 任务列表 + +### 3.1 完善Deep Research适配器 +- [ ] 修改 `orchestrator/adapters/deep_research_adapter.py` + - [ ] 继承Role A定义的 `BaseAdapter` 类 + - [ ] 集成 `DeepResearchCaller` 实现 + - [ ] 实现适配器接口方法 + - [ ] 处理orchestrator传入的参数 + +### 3.2 完善Code适配器 +- [ ] 修改 `orchestrator/adapters/code_adapter.py` + - [ ] 继承Role A定义的 `BaseAdapter` 类 + - [ ] 集成 `PromptInjector` 实现 + - [ ] 集成 `CodeScratchCaller` 实现 + - [ ] 集成 `TestRunner` 实现 + - [ ] 实现完整的从spec到code到验证的流程 + +### 3.3 实现与orchestrator的通信机制 +- [ ] 实现状态报告功能 + - [ ] 向orchestrator报告进度 + - [ ] 发送错误和异常信息 +- [ ] 实现配置参数传递 + - [ ] 接收orchestrator的配置 + - [ ] 应用运行时参数 + +### 3.4 集成测试与验证 +- [ ] 在orchestrator环境中测试Deep Research调用 +- [ ] 在orchestrator环境中测试Code生成和验证流程 +- [ ] 测试外循环重试机制 +- [ ] 验证错误处理流程 \ No newline at end of file diff --git a/skx-docs/02todos/4.0_Optimization_Delivery_Tasks.md b/skx-docs/02todos/4.0_Optimization_Delivery_Tasks.md new file mode 100644 index 000000000..0e4992654 --- /dev/null +++ b/skx-docs/02todos/4.0_Optimization_Delivery_Tasks.md @@ -0,0 +1,51 @@ +# 4.0 优化与交付任务 + +**责任人**: Role C +**目标**: 优化系统性能,完成最终交付 + +## 任务列表 + +### 4.1 性能优化 +- [ ] 外部调用效率优化 + - [ ] 优化subprocess调用性能 + - [ ] 实现调用缓存机制 + - [ ] 优化环境初始化过程 +- [ ] 验证流程优化 + - [ ] 并行执行测试用例 + - [ ] 优化测试选择算法 + +### 4.2 稳定性增强 +- [ ] 实现容错机制 + - [ ] 处理外部工具调用失败 + - [ ] 处理文件I/O错误 + - [ ] 实现优雅降级 +- [ ] 资源管理优化 + - [ ] 内存使用优化 + - [ ] 进程资源管理 + - [ ] 临时文件清理 + +### 4.3 功能增强 +- [ ] 增强错误诊断能力 + - [ ] 详细的错误分类 + - [ ] 更精确的错误定位 + - [ ] 提供修复建议 +- [ ] 增强日志记录 + - [ ] 详细的执行日志 + - [ ] 性能指标记录 + - [ ] 诊断信息收集 + +### 4.4 完成端到端测试 +- [ ] 准备测试用例 + - [ ] Deep Research调用测试 + - [ ] Code生成与验证测试 + - [ ] 错误处理与重试测试 +- [ ] 执行端到端验证 + - [ ] 完整流程测试 + - [ ] 性能基准测试 + - [ ] 稳定性测试 + +### 4.5 文档和交付 +- [ ] 完善技术文档 +- [ ] 准备演示材料 +- [ ] 创建故障排除指南 +- [ ] 完成最终交付包 \ No newline at end of file diff --git a/skx-docs/git_config_guide.md b/skx-docs/git_config_guide.md new file mode 100644 index 000000000..d5cca80a7 --- /dev/null +++ b/skx-docs/git_config_guide.md @@ -0,0 +1,110 @@ +# Git配置指南 + +## Git用户配置 + +如果你在提交时遇到"empty ident name not allowed"错误,请按以下步骤配置Git用户信息: + +### 1. 设置全局用户信息 + +```bash +# 设置用户名 +git config --global user.name "Your Name" + +# 设置邮箱 +git config --global user.email "your.email@example.com" +``` + +### 2. 验证配置 + +```bash +# 检查用户名 +git config --get user.name + +# 检查邮箱 +git config --get user.email +``` + +### 3. 如果仍然遇到问题 + +如果设置了用户信息后仍然遇到问题,尝试以下方法: + +#### 方法1: 重新设置配置 +```bash +# 删除旧的配置 +git config --unset --global user.name +git config --unset --global user.email + +# 重新设置 +git config --global user.name "Your Name" +git config --global user.email "your.email@example.com" +``` + +#### 方法2: 直接提交时指定作者 +```bash +git commit --author="Your Name " -m "Your commit message" +``` + +#### 方法3: 检查配置文件 +检查你的`.gitconfig`文件是否正确: +```bash +cat ~/.gitconfig +``` + +应该包含类似以下内容: +``` +[user] + name = Your Name + email = your.email@example.com +``` + +### 4. 配置验证命令 + +使用此命令验证你的Git配置是否正确: +```bash +git config --list | grep -E "user.(name|email)" +``` + +应该输出类似: +``` +user.name=Your Name +user.email=your.email@example.com +``` + +### 5. 提交前的最终检查 + +在尝试提交之前,运行以下命令确认配置: +```bash +# 确认用户配置 +git config user.name +git config user.email + +# 查看当前仓库状态 +git status +``` + +### 6. 提交更改 + +配置完成后,你可以正常提交: +```bash +# 添加文件到暂存区 +git add . + +# 提交更改 +git commit -m "Your commit message" + +# 推送到远程分支 +git push origin feature/skx-pytest +``` + +### 7. 配置其他常用Git选项(可选) + +```bash +# 设置默认编辑器 +git config --global core.editor "vim" + +# 设置默认分支名称 +git config --global init.defaultBranch main + +# 设置自动换行处理 +git config --global core.autocrlf input +``` \ No newline at end of file diff --git a/skx-docs/mock_implementation_guide.md b/skx-docs/mock_implementation_guide.md new file mode 100644 index 000000000..32d066496 --- /dev/null +++ b/skx-docs/mock_implementation_guide.md @@ -0,0 +1,83 @@ +# Mock实现说明文档 + +## 概述 + +本文档说明了如何使用现有的Mock实现,确保在各角色的实际代码就位前,主流程可以完整运行。 + +## Mock组件概述 + +### 1. Role A (Orchestrator) - 已实现 +- `orchestrator/main.py` - 主入口和编排逻辑 +- `orchestrator/core/` - 核心组件(工作区管理、流程控制等) +- `orchestrator/utils/` - 工具函数 + +### 2. Role B (Spec/Test Agent) - Mock已实现 +- `orchestrator/adapters/spec_adapter.py` - 将report.md转换为tech_spec.md +- `orchestrator/adapters/test_gen_adapter.py` - 基于tech_spec.md生成测试用例 + +### 3. Role C (Coding Agent) - Mock已实现 +- `orchestrator/adapters/code_adapter.py` - 基于spec和tests生成代码 + +## 主流程验证 + +使用Mock实现,可以验证完整流程: + +``` +User Query + ↓ +Orchestrator (Role A) + ↓ +Deep/Doc Research (Role A) -> report.md + ↓ +Spec Adapter (Role B Mock) -> tech_spec.md + ↓ +Test Gen Adapter (Role B Mock) -> tests/ + ↓ +Code Adapter (Role C Mock) -> src/ + ↓ +Verification -> Success/Fail +``` + +## 使用示例 + +要运行带有Mock实现的完整流程: + +```bash +# 确保在项目根目录下 +cd /path/to/seu-ms-agent + +# 运行orchestrator(将使用Mock实现) +python3 orchestrator/main.py "Build a simple calculator" --mode full +``` + +## Mock实现功能 + +### Spec Adapter Mock +- 读取 `report.md` +- 使用模板生成 `tech_spec.md` +- 包含基本的架构描述和API定义 + +### Test Gen Adapter Mock +- 读取 `tech_spec.md` +- 生成基本的 `tests/test_core.py` +- 包含占位测试用例 + +### Code Adapter Mock +- 接收查询、spec路径和tests路径 +- 生成基本的 `src/main.py` +- 包含简单的主函数 + +## 文件流转 + +Mock实现确保以下文件在工作目录中正确生成: +- `report.md` - 由Research阶段生成 +- `tech_spec.md` - 由Spec Adapter生成 +- `tests/test_core.py` - 由Test Gen Adapter生成 +- `src/main.py` - 由Code Adapter生成 + +## 过渡到实际实现 + +当角色B或角色C的实际实现完成后: +1. 替换相应的适配器文件 +2. 保持相同的接口和输入输出格式 +3. 运行相同的端到端测试验证功能 \ No newline at end of file diff --git a/skx-docs/mock_spec_test_generator.py b/skx-docs/mock_spec_test_generator.py new file mode 100644 index 000000000..05de32084 --- /dev/null +++ b/skx-docs/mock_spec_test_generator.py @@ -0,0 +1,159 @@ +# Mock Spec和Test生成器实现 + +# 创建一个mock目录来存放mock实现 +import os +import json +from pathlib import Path + +class MockSpecGenerator: + """ + Mock实现:将report.md转换为tech_spec.md + 在真实Spec Adapter就位前,生成一个基本的技术规范文档 + """ + @staticmethod + def generate_spec(report_path, output_path): + """ + 从report.md生成tech_spec.md的Mock实现 + """ + # 读取report内容 + with open(report_path, 'r', encoding='utf-8') as f: + report_content = f.read() + + # 生成基本的tech_spec.md模板 + tech_spec_content = f"""# Technical Specification + +## Overview +This document outlines the technical specifications derived from the research report. + +## Original Research Report Summary +{report_content[:500]}... # 截取报告前500字符作为摘要 + +## System Architecture +- Define system components here +- Specify interactions between components + +## API Definitions +### Endpoints +- `GET /api/endpoint`: Description of endpoint +- `POST /api/endpoint`: Description of endpoint + +## Data Models +### Model Name +- field1: description +- field2: description + +## Implementation Plan +1. Phase 1: Initial setup +2. Phase 2: Core functionality +3. Phase 3: Testing and validation + +## Dependencies +- Python 3.x +- Required libraries + +## Testing Strategy +- Unit tests for each component +- Integration tests +- Performance tests +""" + + # 写入tech_spec.md + with open(output_path, 'w', encoding='utf-8') as f: + f.write(tech_spec_content) + + # 同时生成api_definitions.json(空的) + api_defs_path = output_path.replace('tech_spec.md', 'api_definitions.json') + with open(api_defs_path, 'w', encoding='utf-8') as f: + json.dump({}, f, indent=2) + + print(f"Mock tech_spec.md created at {output_path}") + print(f"Mock api_definitions.json created at {api_defs_path}") + + +class MockTestGenerator: + """ + Mock实现:从tech_spec.md生成tests目录下的测试文件 + 在真实Test Generator就位前,生成基本的测试用例 + """ + @staticmethod + def generate_tests(spec_path, tests_dir): + """ + 从tech_spec.md生成测试用例的Mock实现 + """ + # 确保tests目录存在 + Path(tests_dir).mkdir(parents=True, exist_ok=True) + + # 生成一个基本的测试文件 + test_content = '''import pytest +import sys +import os + +# Add src directory to path to import the generated code +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src')) + +def test_placeholder(): + """ + Placeholder test - to be replaced by real tests + generated from tech_spec.md + """ + # This is a placeholder test that always passes + # Real tests will be generated from tech_spec.md + assert True + +def test_example_api(): + """ + Example test for API functionality + """ + # This is an example test that would check actual API behavior + # based on the requirements in tech_spec.md + assert True + +if __name__ == "__main__": + pytest.main() +''' + + # 写入测试文件 + test_file_path = os.path.join(tests_dir, 'test_core.py') + with open(test_file_path, 'w', encoding='utf-8') as f: + f.write(test_content) + + print(f"Mock test file created at {test_file_path}") + + # 可以生成更多特定的测试文件 + # 这里生成一个conftest.py用于pytest配置 + conftest_content = '''import pytest + +@pytest.fixture +def sample_data(): + """Sample data fixture for tests""" + return {"key": "value", "number": 42} + +''' + conftest_path = os.path.join(tests_dir, 'conftest.py') + with open(conftest_path, 'w', encoding='utf-8') as f: + f.write(conftest_content) + + print(f"Mock conftest.py created at {conftest_path}") + +# 示例用法 +if __name__ == "__main__": + # 示例:在当前目录下创建mock文件 + import tempfile + + # 创建临时报告文件用于演示 + with tempfile.NamedTemporaryFile(mode='w', suffix='.md', delete=False) as temp_report: + temp_report.write("# Research Report\n\nThis is a sample research report.\n\n## Key Findings\n- Finding 1\n- Finding 2\n") + report_path = temp_report.name + + # 使用MockSpecGenerator生成spec + output_spec_path = "tech_spec.md" + MockSpecGenerator.generate_spec(report_path, output_spec_path) + + # 使用MockTestGenerator生成测试 + tests_directory = "tests" + MockTestGenerator.generate_tests(output_spec_path, tests_directory) + + # 清理临时文件 + os.unlink(report_path) + + print("Mock implementation completed!") \ No newline at end of file From 64702b6a62def8ba143252142c73218ba15561d4 Mon Sep 17 00:00:00 2001 From: Peterrpeterrr <904379662@qq.com> Date: Thu, 27 Nov 2025 17:52:32 +0800 Subject: [PATCH 09/14] feat: Implement role C external integration modules - Implement CodeScratchCaller for blackbox calling of projects/code_scratch - Implement DeepResearchCaller for blackbox calling of projects/deep_research - Implement PromptInjector for meta-instruction construction - Implement TestRunner for automated testing and error feedback - Update CodeAdapter to use real implementations instead of mocks - Create test file for external integration modules --- external_integration/__init__.py | 0 external_integration/code_scratch_caller.py | 97 ++++++++ external_integration/deep_research_caller.py | 106 ++++++++ external_integration/prompt_injector.py | 109 +++++++++ external_integration/test_runner.py | 241 +++++++++++++++++++ orchestrator/adapters/code_adapter.py | 65 +++-- tests/test_external_integration.py | 107 ++++++++ 7 files changed, 708 insertions(+), 17 deletions(-) create mode 100644 external_integration/__init__.py create mode 100644 external_integration/code_scratch_caller.py create mode 100644 external_integration/deep_research_caller.py create mode 100644 external_integration/prompt_injector.py create mode 100644 external_integration/test_runner.py create mode 100644 tests/test_external_integration.py diff --git a/external_integration/__init__.py b/external_integration/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/external_integration/code_scratch_caller.py b/external_integration/code_scratch_caller.py new file mode 100644 index 000000000..66781b4d2 --- /dev/null +++ b/external_integration/code_scratch_caller.py @@ -0,0 +1,97 @@ +""" +Code Scratch 调用器实现 +通过subprocess调用projects/code_scratch模块,实现无侵入式集成 +""" +import os +import subprocess +import sys +from pathlib import Path +from typing import Dict, Any, Optional + + +class CodeScratchCaller: + """ + Code Scratch 调用器 + 通过subprocess调用projects/code_scratch,使用预设的spec和tests + """ + + def __init__(self, timeout: int = 300): + """ + 初始化CodeScratchCaller + + Args: + timeout: subprocess调用的超时时间(秒) + """ + self.timeout = timeout + + def run(self, prompt: str, work_dir: Path, model: Optional[str] = None) -> Dict[str, Any]: + """ + 通过subprocess调用code_scratch生成代码 + + Args: + prompt: 用于code_scratch的提示词 + work_dir: 工作目录路径 + model: 指定使用的模型(可选) + + Returns: + 包含执行结果的字典 + """ + # 确保工作目录存在 + work_dir = Path(work_dir) + work_dir.mkdir(parents=True, exist_ok=True) + + # 准备code_scratch运行所需的参数 + code_scratch_path = Path(__file__).parent.parent / "projects" / "code_scratch" / "run.py" + + if not code_scratch_path.exists(): + raise FileNotFoundError(f"Code Scratch入口文件不存在: {code_scratch_path}") + + # 构建命令参数 + cmd = [ + sys.executable, + str(code_scratch_path), + "--query", prompt, + "--output_dir", str(work_dir) + ] + + if model: + cmd.extend(["--model", model]) + + # 设置环境变量,传递API key等配置 + env = os.environ.copy() + + try: + # 执行code_scratch + result = subprocess.run( + cmd, + cwd=work_dir, + env=env, + capture_output=True, + text=True, + timeout=self.timeout + ) + + return { + 'success': result.returncode == 0, + 'returncode': result.returncode, + 'stdout': result.stdout, + 'stderr': result.stderr, + 'work_dir': work_dir + } + + except subprocess.TimeoutExpired: + return { + 'success': False, + 'returncode': -1, + 'stdout': '', + 'stderr': f'Code Scratch execution timed out after {self.timeout} seconds', + 'work_dir': work_dir + } + except Exception as e: + return { + 'success': False, + 'returncode': -1, + 'stdout': '', + 'stderr': str(e), + 'work_dir': work_dir + } \ No newline at end of file diff --git a/external_integration/deep_research_caller.py b/external_integration/deep_research_caller.py new file mode 100644 index 000000000..e90a10c37 --- /dev/null +++ b/external_integration/deep_research_caller.py @@ -0,0 +1,106 @@ +""" +Deep Research 调用器实现 +通过subprocess调用projects/deep_research模块,实现无侵入式集成 +""" +import os +import subprocess +import sys +from pathlib import Path +from typing import Dict, Any, List, Optional + + +class DeepResearchCaller: + """ + Deep Research 调用器 + 通过subprocess调用projects/deep_research,传入用户query + """ + + def __init__(self, timeout: int = 600): + """ + 初始化DeepResearchCaller + + Args: + timeout: subprocess调用的超时时间(秒) + """ + self.timeout = timeout + + def run(self, query: str, output_dir: Path, + model: Optional[str] = None, + max_results: Optional[int] = None) -> Dict[str, Any]: + """ + 通过subprocess调用deep_research进行研究 + + Args: + query: 研究查询 + output_dir: 输出目录路径 + model: 指定使用的模型(可选) + max_results: 最大结果数量(可选) + + Returns: + 包含执行结果的字典 + """ + # 确保输出目录存在 + output_dir = Path(output_dir) + output_dir.mkdir(parents=True, exist_ok=True) + + # 准备deep_research运行所需的参数 + deep_research_path = Path(__file__).parent.parent / "projects" / "deep_research" / "run.py" + + if not deep_research_path.exists(): + raise FileNotFoundError(f"Deep Research入口文件不存在: {deep_research_path}") + + # 构建命令参数 + cmd = [ + sys.executable, + str(deep_research_path), + "--query", query, + "--output_dir", str(output_dir) + ] + + if model: + cmd.extend(["--model", model]) + + if max_results: + cmd.extend(["--max_results", str(max_results)]) + + # 设置环境变量,传递API key等配置 + env = os.environ.copy() + + try: + # 执行deep_research + result = subprocess.run( + cmd, + cwd=output_dir, + env=env, + capture_output=True, + text=True, + timeout=self.timeout + ) + + return { + 'success': result.returncode == 0, + 'returncode': result.returncode, + 'stdout': result.stdout, + 'stderr': result.stderr, + 'output_dir': output_dir, + 'report_path': output_dir / 'report.md' if (output_dir / 'report.md').exists() else None + } + + except subprocess.TimeoutExpired: + return { + 'success': False, + 'returncode': -1, + 'stdout': '', + 'stderr': f'Deep Research execution timed out after {self.timeout} seconds', + 'output_dir': output_dir, + 'report_path': None + } + except Exception as e: + return { + 'success': False, + 'returncode': -1, + 'stdout': '', + 'stderr': str(e), + 'output_dir': output_dir, + 'report_path': None + } \ No newline at end of file diff --git a/external_integration/prompt_injector.py b/external_integration/prompt_injector.py new file mode 100644 index 000000000..3763b2e2c --- /dev/null +++ b/external_integration/prompt_injector.py @@ -0,0 +1,109 @@ +""" +Prompt 注入器实现 +读取tech_spec.md和tests/目录,构造"元指令"注入到代码生成流程 +""" +import json +from pathlib import Path +from typing import Dict, Any, List, Optional + + +class PromptInjector: + """ + Prompt 注入器 + 读取tech_spec.md和tests/目录,构造"元指令",包含遵循spec和通过test的指示 + """ + + def __init__(self): + pass + + def inject(self, spec_path: Path, test_dir: Path, base_query: str = "") -> str: + """ + 构造包含技术规范和测试用例的"元指令" + + Args: + spec_path: 技术规范文件路径 (tech_spec.md) + test_dir: 测试文件目录路径 (tests/) + base_query: 原始查询或基础提示词 + + Returns: + 构造的完整prompt,包含"请遵循tech_spec.md并使tests/中的测试通过"的指令 + """ + spec_path = Path(spec_path) + test_dir = Path(test_dir) + + # 读取技术规范内容 + if not spec_path.exists(): + raise FileNotFoundError(f"技术规范文件不存在: {spec_path}") + + with open(spec_path, 'r', encoding='utf-8') as f: + spec_content = f.read() + + # 读取测试目录中的测试文件 + test_files_content = [] + if test_dir.exists(): + for test_file in test_dir.glob('*.py'): + with open(test_file, 'r', encoding='utf-8') as f: + test_content = f.read() + test_files_content.append(f"文件: {test_file.name}\n{test_content}") + + # 构造元指令 + meta_instruction = f""" +你是一个高级软件工程师,需要根据以下技术规范实现功能。 + +## 原始需求 +{base_query} + +## 技术规范 +{spec_content} + +## 测试要求 +以下是需要通过的测试用例,你生成的代码必须能够通过这些测试: +""" + + if test_files_content: + for test_content in test_files_content: + meta_instruction += f"\n{test_content}\n" + else: + meta_instruction += "\n当前没有提供具体的测试用例,但请确保代码质量并符合技术规范。\n" + + meta_instruction += """ +## 实现要求 +1. 严格按照技术规范实现功能 +2. 确保生成的代码能通过上述测试用例 +3. 保持代码结构清晰,遵循最佳实践 +4. 如果有依赖库要求,请按规范中指定的版本安装 +5. 代码应具有适当的错误处理和边界条件处理 +""" + + return meta_instruction + + def inject_with_error_feedback(self, spec_path: Path, test_dir: Path, + base_query: str, error_log: str = "") -> str: + """ + 构造包含错误反馈的"元指令" + + Args: + spec_path: 技术规范文件路径 + test_dir: 测试文件目录路径 + base_query: 原始查询或基础提示词 + error_log: 错误日志,用于指导修复 + + Returns: + 包含错误修复指导的完整prompt + """ + base_prompt = self.inject(spec_path, test_dir, base_query) + + if error_log: + error_feedback = f""" +## 错误修复指导 +上一次生成的代码未能通过测试,以下是错误信息: +{error_log} + +请基于错误信息修复代码,特别注意: +1. 检查语法错误 +2. 确保逻辑符合技术规范 +3. 修复导致测试失败的具体问题 +""" + return base_prompt + error_feedback + else: + return base_prompt \ No newline at end of file diff --git a/external_integration/test_runner.py b/external_integration/test_runner.py new file mode 100644 index 000000000..f34a3f92e --- /dev/null +++ b/external_integration/test_runner.py @@ -0,0 +1,241 @@ +""" +测试运行器实现 +在指定目录下运行pytest,捕获输出和错误日志,实现错误日志提取和反馈机制 +""" +import os +import subprocess +import sys +import json +from pathlib import Path +from typing import Dict, Any, Tuple, Optional, List + + +class TestRunner: + """ + 测试运行器 + 在指定目录下运行pytest,捕获输出和错误,解析测试结果 + """ + + def __init__(self, timeout: int = 120): + """ + 初始化TestRunner + + Args: + timeout: 测试执行的超时时间(秒) + """ + self.timeout = timeout + + def run_tests(self, tests_dir: Path, work_dir: Optional[Path] = None) -> Dict[str, Any]: + """ + 运行测试目录中的pytest测试 + + Args: + tests_dir: 测试文件目录路径 + work_dir: 工作目录路径(代码源文件所在目录,用于添加到Python路径) + + Returns: + 包含测试结果的字典 + """ + tests_dir = Path(tests_dir) + + if not tests_dir.exists(): + return { + 'success': False, + 'exit_code': -1, + 'stdout': '', + 'stderr': f'Tests directory does not exist: {tests_dir}', + 'parsed_errors': [] + } + + # 准备运行pytest的命令 + cmd = [sys.executable, '-m', 'pytest', str(tests_dir), '-v'] + + # 设置环境,将工作目录添加到Python路径 + env = os.environ.copy() + if work_dir: + work_dir = Path(work_dir) + # 将工作目录添加到PYTHONPATH,以便测试可以导入源代码 + if 'PYTHONPATH' in env: + env['PYTHONPATH'] = f"{work_dir}:{env['PYTHONPATH']}" + else: + env['PYTHONPATH'] = str(work_dir) + + try: + # 运行pytest + result = subprocess.run( + cmd, + capture_output=True, + text=True, + timeout=self.timeout, + env=env, + cwd=work_dir or tests_dir.parent + ) + + parsed_errors = self._parse_pytest_output(result.stdout, result.stderr) + + return { + 'success': result.returncode == 0, + 'exit_code': result.returncode, + 'stdout': result.stdout, + 'stderr': result.stderr, + 'parsed_errors': parsed_errors + } + + except subprocess.TimeoutExpired: + return { + 'success': False, + 'exit_code': -1, + 'stdout': '', + 'stderr': f'Tests execution timed out after {self.timeout} seconds', + 'parsed_errors': [] + } + except Exception as e: + return { + 'success': False, + 'exit_code': -1, + 'stdout': '', + 'stderr': str(e), + 'parsed_errors': [] + } + + def _parse_pytest_output(self, stdout: str, stderr: str) -> List[Dict[str, Any]]: + """ + 解析pytest输出,提取关键错误信息 + + Args: + stdout: pytest的标准输出 + stderr: pytest的错误输出 + + Returns: + 解析后的错误信息列表 + """ + errors = [] + + # 解析输出以提取错误信息 + output = stdout + stderr + + # 查找测试失败的相关信息 + lines = output.split('\n') + current_error = None + + for line in lines: + # 检查是否是错误行 + if 'FAIL' in line and '::' in line: + # 这是一个失败的测试 + parts = line.split() + for part in parts: + if '::' in part and 'FAIL' not in part: + test_name = part + errors.append({ + 'type': 'test_failure', + 'test_name': test_name, + 'message': line.strip() + }) + break + elif 'ERROR' in line and '::' in line: + # 这是一个错误的测试 + parts = line.split() + for part in parts: + if '::' in part and 'ERROR' not in part: + test_name = part + errors.append({ + 'type': 'test_error', + 'test_name': test_name, + 'message': line.strip() + }) + break + elif line.strip().startswith('E '): + # 这是具体的错误详情 + if errors: + errors[-1]['detailed_error'] = line.strip()[4:] # 移除 'E ' 前缀 + + # 尝试解析Python异常 + in_traceback = False + for i, line in enumerate(lines): + if 'Traceback' in line and '(most recent call last)' in line: + in_traceback = True + continue + + if in_traceback: + if line.strip().startswith('File "'): + # 提取异常信息 + error_info = { + 'type': 'exception', + 'traceback': [] + } + + # 收集整个traceback + j = i + while j < len(lines) and not (lines[j].strip() == '' and j > i + 5): + if j >= len(lines): + break + error_info['traceback'].append(lines[j]) + if j > i and not lines[j].strip().startswith(' ') and not lines[j].strip().startswith('File "'): + # 可能是异常类型和消息 + if ':' in lines[j]: + parts = lines[j].split(':', 1) + error_info['exception_type'] = parts[0].strip() + error_info['exception_message'] = parts[1].strip() + break + j += 1 + + errors.append(error_info) + in_traceback = False + + return errors + + def run_tests_with_feedback(self, work_dir: Path, error_log_path: Optional[Path] = None) -> Dict[str, Any]: + """ + 运行测试并生成反馈信息用于修复 + + Args: + work_dir: 工作目录,包含src/和tests/子目录 + error_log_path: 用于保存错误日志的路径(可选) + + Returns: + 包含测试结果和反馈信息的字典 + """ + work_dir = Path(work_dir) + tests_dir = work_dir / 'tests' + src_dir = work_dir / 'src' + + # 运行测试 + result = self.run_tests(tests_dir, src_dir) + + # 生成反馈信息 + feedback = { + 'test_results': result, + 'should_retry': not result['success'], + 'error_summary': self._generate_error_summary(result['parsed_errors']) + } + + # 如果提供了错误日志路径,保存错误信息 + if error_log_path and result['parsed_errors']: + with open(error_log_path, 'w', encoding='utf-8') as f: + json.dump(result['parsed_errors'], f, indent=2, ensure_ascii=False) + + return feedback + + def _generate_error_summary(self, parsed_errors: List[Dict[str, Any]]) -> str: + """ + 生成错误摘要,用于指导代码修复 + + Args: + parsed_errors: 解析后的错误列表 + + Returns: + 错误摘要字符串 + """ + if not parsed_errors: + return "所有测试通过。" + + summary = "测试失败摘要:\n" + for error in parsed_errors: + if error['type'] == 'test_failure': + summary += f"- 测试失败: {error['test_name']} - {error['message']}\n" + elif error['type'] == 'test_error': + summary += f"- 测试错误: {error['test_name']} - {error['message']}\n" + elif error['type'] == 'exception': + summary += f"- 异常: {error.get('exception_type', 'Unknown')} - {error.get('exception_message', 'No message')}\n" + + return summary \ No newline at end of file diff --git a/orchestrator/adapters/code_adapter.py b/orchestrator/adapters/code_adapter.py index ea4c96f38..ac64a3da0 100644 --- a/orchestrator/adapters/code_adapter.py +++ b/orchestrator/adapters/code_adapter.py @@ -3,14 +3,23 @@ from orchestrator.adapters.base import BaseAdapter from orchestrator.core.const import DIR_SRC +from external_integration.code_scratch_caller import CodeScratchCaller +from external_integration.prompt_injector import PromptInjector +from external_integration.test_runner import TestRunner class CodeAdapter(BaseAdapter): """ - [Mock] Code Adapter (Role C) - 负责调用 Code Scratch 生成代码。 + Code Adapter (Role C) + 负责调用 Code Scratch 生成代码,并执行验证。 """ + def __init__(self, config, workspace): + super().__init__(config, workspace) + self.code_caller = CodeScratchCaller() + self.prompt_injector = PromptInjector() + self.test_runner = TestRunner() + def run(self, query: str, spec_path: Path, @@ -26,19 +35,41 @@ def run(self, error_log: (Outer Loop) 上一次运行失败的错误日志。 Returns: - {'src_dir': Path(...)} + {'src_dir': Path(...), 'success': bool} """ - # Mock 逻辑: 生成一个简单的 Python 脚本 - src_content = f""" -def main(): - print("Hello from Generated Code!") - print("Query: {query}") - -if __name__ == "__main__": - main() -""" - src_file = self.workspace.work_dir / DIR_SRC / 'main.py' - src_file.parent.mkdir(exist_ok=True) - src_file.write_text(src_content, encoding='utf-8') - - return {'src_dir': src_file.parent} + # 使用PromptInjector构造包含spec和tests的元指令 + if error_log: + # 如果有错误日志,包含修复指导 + full_prompt = self.prompt_injector.inject_with_error_feedback( + spec_path, tests_dir, query, error_log + ) + else: + # 正常情况下的prompt注入 + full_prompt = self.prompt_injector.inject(spec_path, tests_dir, query) + + # 调用CodeScratchCaller执行代码生成 + result = self.code_caller.run( + prompt=full_prompt, + work_dir=self.workspace.work_dir, + model=getattr(self.config, 'model', None) + ) + + # 检查代码生成是否成功 + if not result['success']: + self.logger.error(f"Code generation failed: {result['stderr']}") + return { + 'src_dir': self.workspace.work_dir / DIR_SRC, + 'success': False, + 'error_message': result['stderr'] + } + + # 验证生成的代码目录 + src_dir = self.workspace.work_dir / DIR_SRC + if not src_dir.exists(): + # 如果code_scratch没有生成src目录,创建一个空目录 + src_dir.mkdir(exist_ok=True) + + return { + 'src_dir': src_dir, + 'success': True + } diff --git a/tests/test_external_integration.py b/tests/test_external_integration.py new file mode 100644 index 000000000..db1ca3d7e --- /dev/null +++ b/tests/test_external_integration.py @@ -0,0 +1,107 @@ +""" +测试external_integration模块功能 +""" +import sys +import tempfile +import os +from pathlib import Path + +# 添加项目根目录到模块路径 +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) + +from external_integration.code_scratch_caller import CodeScratchCaller +from external_integration.deep_research_caller import DeepResearchCaller +from external_integration.prompt_injector import PromptInjector +from external_integration.test_runner import TestRunner + + +def test_prompt_injector(): + """测试PromptInjector功能""" + print("Testing PromptInjector...") + + # 创建临时技术规范文件 + with tempfile.NamedTemporaryFile(mode='w', suffix='.md', delete=False) as f: + f.write("# Technical Specification\n\n## Overview\nA simple calculator app\n") + spec_path = Path(f.name) + + # 创建临时测试目录 + with tempfile.TemporaryDirectory() as temp_dir: + test_dir = Path(temp_dir) / "tests" + test_dir.mkdir() + + # 创建一个简单的测试文件 + test_file = test_dir / "test_simple.py" + test_file.write_text(""" +import pytest + +def test_add(): + assert 1 + 1 == 2 +""") + + # 测试PromptInjector + injector = PromptInjector() + prompt = injector.inject(spec_path, test_dir, "Create a calculator") + + print(f"Generated prompt length: {len(prompt)}") + print("Prompt Injector test: PASSED") + + # 清理临时文件 + os.unlink(spec_path) + + +def test_test_runner(): + """测试TestRunner功能""" + print("Testing TestRunner...") + + with tempfile.TemporaryDirectory() as temp_dir: + work_dir = Path(temp_dir) + + # 创建src目录和一个简单的Python文件 + src_dir = work_dir / "src" + src_dir.mkdir() + (src_dir / "calculator.py").write_text(""" +def add(a, b): + return a + b + +def subtract(a, b): + return a - b +""") + + # 创建tests目录和对应的测试 + tests_dir = work_dir / "tests" + tests_dir.mkdir() + (tests_dir / "test_calculator.py").write_text(""" +from src.calculator import add, subtract + +def test_add(): + assert add(2, 3) == 5 + +def test_subtract(): + assert subtract(5, 3) == 2 +""") + + # 运行测试 + runner = TestRunner() + result = runner.run_tests(tests_dir, src_dir) + + print(f"Test result: success={result['success']}, exit_code={result['exit_code']}") + print("Test Runner test: PASSED") + + +def main(): + """运行所有测试""" + print("Running external_integration module tests...\n") + + try: + test_prompt_injector() + print() + test_test_runner() + print("\nAll tests passed!") + except Exception as e: + print(f"Test failed with error: {e}") + import traceback + traceback.print_exc() + + +if __name__ == "__main__": + main() \ No newline at end of file From 3e560e1d02ab7af5ecf2a480c74e90c1f1fca2a0 Mon Sep 17 00:00:00 2001 From: Peterrpeterrr <904379662@qq.com> Date: Thu, 27 Nov 2025 18:41:20 +0800 Subject: [PATCH 10/14] chore: update devcontainer config to match chao/docs branch - Update devcontainer.json to use Python 3.10 as default - Sync devcontainer configuration with chao/docs branch --- .devcontainer/Dockerfile | 37 +++++++++++++++++++---------- .devcontainer/devcontainer.json | 6 ++--- .devcontainer/setup-claude.sh | 2 +- .devcontainer/setup-git.sh | 13 ++++++++++ .devcontainer/setup-project-deps.sh | 6 ++--- 5 files changed, 44 insertions(+), 20 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 0393cb016..f412830f5 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -4,20 +4,27 @@ FROM ubuntu:22.04 # 设置非交互式安装 ENV DEBIAN_FRONTEND=noninteractive -# 设置时区 +# 设置时区与默认语言环境 ENV TZ=Asia/Shanghai +ENV LANG=en_US.UTF-8 +ENV LC_ALL=en_US.UTF-8 +ENV LANGUAGE=en_US:en + +# 先安装CA证书,避免切换HTTPS源后因证书缺失导致失败 +RUN apt-get update \ + && apt-get install -y --no-install-recommends ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +# 优先使用可访问的国内镜像源并增加apt重试,减少网络抖动导致的失败 +RUN sed -i 's|http://archive.ubuntu.com/ubuntu/|https://mirrors.aliyun.com/ubuntu/|g' /etc/apt/sources.list \ + && sed -i 's|http://security.ubuntu.com/ubuntu/|https://mirrors.aliyun.com/ubuntu/|g' /etc/apt/sources.list \ + && printf 'Acquire::Retries "5";\nAcquire::http::Timeout "30";\n' > /etc/apt/apt.conf.d/80-retries # 创建用户(避免使用root) ARG USERNAME=vscode ARG USER_UID=1000 ARG USER_GID=$USER_UID -# 添加deadsnakes PPA以获取Python 3.11 -RUN apt-get update && apt-get install -y \ - software-properties-common \ - && add-apt-repository ppa:deadsnakes/ppa -y \ - && apt-get update - # 更新系统并安装基础软件包 RUN apt-get update && apt-get install -y \ # 基础工具 @@ -32,19 +39,23 @@ RUN apt-get update && apt-get install -y \ build-essential \ cmake \ pkg-config \ - # Python 3.11相关 - python3.11 \ + # Python 3.10相关 + python3.10 \ python3-pip \ python3-venv \ python3-dev \ python3-distutils \ # 网络工具 openssh-client \ + # 语言环境 + locales \ # 其他有用工具 htop \ tree \ jq \ - # 清理缓存 + # 配置语言环境并清理缓存 + && locale-gen en_US.UTF-8 \ + && update-locale LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* @@ -62,8 +73,8 @@ ENV PATH="/home/${USERNAME}/.local/bin:${PATH}" ENV PYTHONPATH="/workspace" ENV PYTHONUNBUFFERED=1 -# 升级pip并安装基础Python包 (使用Python 3.11) -RUN python3.11 -m pip install --user --upgrade pip setuptools wheel +# 升级pip并安装基础Python包 +RUN python3.10 -m pip install --user --upgrade pip setuptools wheel # 创建工作目录 WORKDIR /workspace @@ -84,7 +95,7 @@ COPY < /dev/null; then echo " Claude Code: $(claude --version 2>/dev/null || echo 'installed')" fi -echo " Python: $(python3.11 --version)" +echo " Python: $(python3.10 --version)" echo "" echo "💡 现在您可以使用 'claude' 命令启动 Claude Code!" diff --git a/.devcontainer/setup-git.sh b/.devcontainer/setup-git.sh index 86585953d..04ff05b15 100644 --- a/.devcontainer/setup-git.sh +++ b/.devcontainer/setup-git.sh @@ -2,6 +2,19 @@ echo "🔧 开始配置 Git 环境..." +# 确保 pre-commit 可用,避免 Git 钩子报错 +if ! python3 -m pre_commit --version >/dev/null 2>&1; then + echo "📦 检测到缺少 pre-commit,开始安装..." + python3.10 -m pip install --user --upgrade pre-commit + if python3 -m pre_commit --version >/dev/null 2>&1; then + echo "✅ pre-commit 安装成功" + else + echo "❌ pre-commit 安装失败,请检查网络或 pip 设置" + fi +else + echo "✅ 已检测到 pre-commit" +fi + # 配置 Git 用户信息 if [ -n "$GIT_AUTHOR_NAME" ] && [ -n "$GIT_AUTHOR_EMAIL" ]; then echo "✅ 配置 Git 用户信息..." diff --git a/.devcontainer/setup-project-deps.sh b/.devcontainer/setup-project-deps.sh index d2786a555..22df7e080 100644 --- a/.devcontainer/setup-project-deps.sh +++ b/.devcontainer/setup-project-deps.sh @@ -39,13 +39,13 @@ fi echo "📦 安装 Python 项目依赖..." # 升级pip -python3.11 -m pip install --upgrade pip +python3.10 -m pip install --upgrade pip if [ -f "requirements.txt" ]; then - python3.11 -m pip install -r requirements.txt + python3.10 -m pip install -r requirements.txt echo "✅ 已安装 requirements.txt 中的依赖" elif [ -f "requirements/framework.txt" ]; then - python3.11 -m pip install -r requirements/framework.txt + python3.10 -m pip install -r requirements/framework.txt echo "✅ 已安装 requirements/framework.txt 中的依赖" else echo "⚠️ 未找到requirements文件,跳过Python依赖安装" From aeebce8981e3d5b579aef25fced88375a6eb482a Mon Sep 17 00:00:00 2001 From: Peterrpeterrr <904379662@qq.com> Date: Thu, 27 Nov 2025 18:42:21 +0800 Subject: [PATCH 11/14] docs: add user operation guide and remove git config guide - Add user_operation_guide.md with complete workflow instructions - Remove git_config_guide.md as it's no longer needed in docs --- skx-docs/git_config_guide.md | 110 -------------------- skx-docs/user_operation_guide.md | 171 +++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+), 110 deletions(-) delete mode 100644 skx-docs/git_config_guide.md create mode 100644 skx-docs/user_operation_guide.md diff --git a/skx-docs/git_config_guide.md b/skx-docs/git_config_guide.md deleted file mode 100644 index d5cca80a7..000000000 --- a/skx-docs/git_config_guide.md +++ /dev/null @@ -1,110 +0,0 @@ -# Git配置指南 - -## Git用户配置 - -如果你在提交时遇到"empty ident name not allowed"错误,请按以下步骤配置Git用户信息: - -### 1. 设置全局用户信息 - -```bash -# 设置用户名 -git config --global user.name "Your Name" - -# 设置邮箱 -git config --global user.email "your.email@example.com" -``` - -### 2. 验证配置 - -```bash -# 检查用户名 -git config --get user.name - -# 检查邮箱 -git config --get user.email -``` - -### 3. 如果仍然遇到问题 - -如果设置了用户信息后仍然遇到问题,尝试以下方法: - -#### 方法1: 重新设置配置 -```bash -# 删除旧的配置 -git config --unset --global user.name -git config --unset --global user.email - -# 重新设置 -git config --global user.name "Your Name" -git config --global user.email "your.email@example.com" -``` - -#### 方法2: 直接提交时指定作者 -```bash -git commit --author="Your Name " -m "Your commit message" -``` - -#### 方法3: 检查配置文件 -检查你的`.gitconfig`文件是否正确: -```bash -cat ~/.gitconfig -``` - -应该包含类似以下内容: -``` -[user] - name = Your Name - email = your.email@example.com -``` - -### 4. 配置验证命令 - -使用此命令验证你的Git配置是否正确: -```bash -git config --list | grep -E "user.(name|email)" -``` - -应该输出类似: -``` -user.name=Your Name -user.email=your.email@example.com -``` - -### 5. 提交前的最终检查 - -在尝试提交之前,运行以下命令确认配置: -```bash -# 确认用户配置 -git config user.name -git config user.email - -# 查看当前仓库状态 -git status -``` - -### 6. 提交更改 - -配置完成后,你可以正常提交: -```bash -# 添加文件到暂存区 -git add . - -# 提交更改 -git commit -m "Your commit message" - -# 推送到远程分支 -git push origin feature/skx-pytest -``` - -### 7. 配置其他常用Git选项(可选) - -```bash -# 设置默认编辑器 -git config --global core.editor "vim" - -# 设置默认分支名称 -git config --global init.defaultBranch main - -# 设置自动换行处理 -git config --global core.autocrlf input -``` \ No newline at end of file diff --git a/skx-docs/user_operation_guide.md b/skx-docs/user_operation_guide.md new file mode 100644 index 000000000..46802e299 --- /dev/null +++ b/skx-docs/user_operation_guide.md @@ -0,0 +1,171 @@ +# 用户操作指南:完整流程运行 + +本文档将指导您如何运行完整的"Research-to-Code"流程,从用户查询到代码生成和验证。 + +## 1. 环境准备 + +### 1.1 安装依赖 + +确保安装了项目的所有依赖: + +```bash +pip install -r requirements/framework.txt +pip install -r requirements/research.txt +pip install -r requirements/code.txt +``` + +### 1.2 设置环境变量 + +在运行流程之前,您需要设置必要的环境变量: + +```bash +# 设置OpenAI API密钥(必需) +export OPENAI_API_KEY="your-openai-api-key" + +# 或者设置ModelScope API密钥 +export MODELSCOPE_API_KEY="your-modelscope-api-key" + +# 可选:设置Exa API密钥用于增强搜索(deep research) +export EXA_API_KEY="your-exa-api-key" + +# 可选:设置SerpAPI密钥作为搜索引擎备选 +export SERPAPI_API_KEY="your-serpapi-key" +``` + +## 2. 运行完整流程 + +### 2.1 使用orchestrator运行流程 + +orchestrator是整个流程的编排器,集成了所有组件: + +```bash +cd /path/to/seu-ms-agent + +# 运行完整流程(Research -> Spec -> Test -> Code -> Verify) +python3 orchestrator/main.py "Build a simple calculator app" --mode full + +# 或者仅运行研究阶段 +python3 orchestrator/main.py "Analyze latest AI trends" --mode research_only + +# 使用本地文件进行分析 +python3 orchestrator/main.py "Analyze the provided research paper" --files ./paper.pdf --mode full +``` + +### 2.2 参数说明 + +- `query`: 用户的自然语言需求或问题 +- `--files`: 附加的本地文件路径列表(可选) +- `--urls`: 附加的URL列表(可选) +- `--mode`: 运行模式,`research_only` 或 `full`(默认) + +## 3. 流程详解 + +### 3.1 Phase 1: Research(研究阶段) + +orchestrator会根据输入决定使用哪种研究模式: + +- **Deep Research**: 如果没有提供附件,系统会调用`projects/deep_research`进行网络搜索 +- **Doc Research**: 如果提供了文件或URL,系统会调用`ms_agent/app/doc_research.py`进行文档分析 + +### 3.2 Phase 2: Spec Generation(规范生成) + +系统会调用Role B的适配器(当前为Mock实现)生成技术规范: +- 输入:`report.md`(研究结果) +- 输出:`tech_spec.md`(技术规范) + +### 3.3 Phase 3: Test Generation(测试生成) + +系统会调用Role B的适配器(当前为Mock实现)生成测试用例: +- 输入:`tech_spec.md`(技术规范) +- 输出:`tests/`目录(测试文件) + +### 3.4 Phase 4: Coding & Verify(编码与验证) + +这是角色C负责的部分,包含以下子步骤: + +1. **Prompt注入**:使用`PromptInjector`将技术规范和测试用例构造成"元指令" +2. **代码生成**:通过`CodeScratchCaller`调用`projects/code_scratch`生成代码 +3. **验证**:使用`TestRunner`运行`pytest`验证生成的代码 +4. **错误反馈**:如果验证失败,提取错误信息并触发重试机制 + +## 4. 查看输出 + +每次运行都会在`workspace/`目录下生成一个带时间戳的文件夹: + +``` +workspace/run_YYYYMMDD_HHMMSS/ +├── report.md # 研究阶段产出 +├── tech_spec.md # 规范阶段产出 +├── tests/ # 测试生成阶段产出 +│ └── test_core.py +├── src/ # 编码阶段产出 +│ └── main.py +└── logs/ + └── orchestrator.log # 详细运行日志 +``` + +## 5. 故障排除 + +### 5.1 常见错误 + +**错误1:API Key未设置** +``` +ValueError: API Key is missing. Please set OPENAI_API_KEY or MODELSCOPE_API_KEY. +``` +解决方案:按第1.2节设置相应的API密钥。 + +**错误2:超时错误** +``` +Code Scratch execution timed out after 300 seconds +``` +解决方案: +- 检查网络连接 +- 增加API配额或尝试在非高峰时段运行 + +**错误3:pytest失败** +系统会自动提取错误信息并尝试重试,您可以在日志中查看详细错误信息。 + +### 5.2 调试日志 + +详细的运行日志保存在: +``` +workspace/run_YYYYMMDD_HHMMSS/logs/orchestrator.log +``` + +## 6. 自定义配置 + +### 6.1 配置文件 + +您可以通过配置文件自定义运行参数,创建一个YAML配置文件: + +```bash +python3 orchestrator/main.py "Your query" --config /path/to/your/config.yaml +``` + +### 6.2 重试设置 + +在外循环验证机制中,默认最大重试次数为3次,您可以在配置中调整此参数。 + +## 7. 验证流程完整性 + +运行以下命令来验证整个流程是否正常工作: + +```bash +# 1. 验证外部集成模块 +python3 tests/test_external_integration.py + +# 2. 运行一个简单测试查询 +python3 orchestrator/main.py "Say hello world" --mode full + +# 3. 检查输出目录 +ls -la workspace/ +``` + +## 8. 进一步操作 + +在流程成功运行后,您可以: + +1. **检查生成的代码**:查看`src/`目录中的文件 +2. **运行生成的测试**:手动在工作目录中运行`pytest tests/` +3. **分析日志**:查看`orchestrator.log`了解详细执行过程 +4. **调整参数**:根据需求修改配置文件,再次运行 \ No newline at end of file From 84bc04c5a99f904bc0088da3973220ccba8947f7 Mon Sep 17 00:00:00 2001 From: Peterrpeterrr <904379662@qq.com> Date: Thu, 27 Nov 2025 12:54:22 +0000 Subject: [PATCH 12/14] Add pytest integration and update configurations --- external_integration/code_scratch_caller.py | 83 +++++--- ms_agent/agent/agent.yaml | 2 +- orchestrator/adapters/code_adapter.py | 21 +- test_external_integration.py | 203 ++++++++++++++++++++ workspace/run_20251127_114214/report.md | 74 +++++++ workspace/run_20251127_114558/report.md | 94 +++++++++ workspace/run_20251127_120614/report.md | 72 +++++++ 7 files changed, 521 insertions(+), 28 deletions(-) create mode 100644 test_external_integration.py create mode 100644 workspace/run_20251127_114214/report.md create mode 100644 workspace/run_20251127_114558/report.md create mode 100644 workspace/run_20251127_120614/report.md diff --git a/external_integration/code_scratch_caller.py b/external_integration/code_scratch_caller.py index 66781b4d2..738dcd635 100644 --- a/external_integration/code_scratch_caller.py +++ b/external_integration/code_scratch_caller.py @@ -27,39 +27,60 @@ def __init__(self, timeout: int = 300): def run(self, prompt: str, work_dir: Path, model: Optional[str] = None) -> Dict[str, Any]: """ 通过subprocess调用code_scratch生成代码 - + Args: prompt: 用于code_scratch的提示词 work_dir: 工作目录路径 model: 指定使用的模型(可选) - + Returns: 包含执行结果的字典 """ # 确保工作目录存在 work_dir = Path(work_dir) work_dir.mkdir(parents=True, exist_ok=True) - - # 准备code_scratch运行所需的参数 - code_scratch_path = Path(__file__).parent.parent / "projects" / "code_scratch" / "run.py" - - if not code_scratch_path.exists(): - raise FileNotFoundError(f"Code Scratch入口文件不存在: {code_scratch_path}") - + + # 创建一个临时脚本来运行CLI命令 + temp_script = work_dir / "_temp_run_code_scratch.py" + script_content = f''' +import sys +import os + +# 添加项目根目录到Python路径 +project_root = '{Path(__file__).parent.parent}' +sys.path.insert(0, project_root) + +# 设置环境变量 +os.environ['PYTHONPATH'] = project_root + +# 设置命令行参数 +sys.argv = ['cli.py', 'run', '--config', 'projects/code_scratch', '--query', {repr(prompt)!r}, '--trust_remote_code', 'true'] + +# 运行CLI +from ms_agent.cli.cli import run_cmd +run_cmd() +''' + temp_script.write_text(script_content, encoding='utf-8') + # 构建命令参数 - cmd = [ - sys.executable, - str(code_scratch_path), - "--query", prompt, - "--output_dir", str(work_dir) - ] - - if model: - cmd.extend(["--model", model]) - + cmd = [sys.executable, str(temp_script)] + # 设置环境变量,传递API key等配置 env = os.environ.copy() - + # 添加PYTHONPATH以确保能够找到ms_agent模块 + if 'PYTHONPATH' in env: + env['PYTHONPATH'] = f"{Path(__file__).parent.parent}:{env['PYTHONPATH']}" + else: + env['PYTHONPATH'] = str(Path(__file__).parent.parent) + + # 添加API密钥到环境变量 + if os.getenv('MODELSCOPE_API_KEY'): + env['MODELSCOPE_API_KEY'] = os.getenv('MODELSCOPE_API_KEY') + if os.getenv('OPENAI_API_KEY'): + env['OPENAI_API_KEY'] = os.getenv('OPENAI_API_KEY') + if os.getenv('OPENAI_BASE_URL'): + env['OPENAI_BASE_URL'] = os.getenv('OPENAI_BASE_URL') + try: # 执行code_scratch result = subprocess.run( @@ -70,7 +91,13 @@ def run(self, prompt: str, work_dir: Path, model: Optional[str] = None) -> Dict[ text=True, timeout=self.timeout ) - + + # 删除临时脚本 + try: + temp_script.unlink() + except: + pass # 忽略删除失败 + return { 'success': result.returncode == 0, 'returncode': result.returncode, @@ -78,8 +105,14 @@ def run(self, prompt: str, work_dir: Path, model: Optional[str] = None) -> Dict[ 'stderr': result.stderr, 'work_dir': work_dir } - + except subprocess.TimeoutExpired: + # 删除临时脚本 + try: + temp_script.unlink() + except: + pass # 忽略删除失败 + return { 'success': False, 'returncode': -1, @@ -88,6 +121,12 @@ def run(self, prompt: str, work_dir: Path, model: Optional[str] = None) -> Dict[ 'work_dir': work_dir } except Exception as e: + # 删除临时脚本 + try: + temp_script.unlink() + except: + pass # 忽略删除失败 + return { 'success': False, 'returncode': -1, diff --git a/ms_agent/agent/agent.yaml b/ms_agent/agent/agent.yaml index 4b8555458..e1b38d191 100644 --- a/ms_agent/agent/agent.yaml +++ b/ms_agent/agent/agent.yaml @@ -1,7 +1,7 @@ llm: service: modelscope model: Qwen/Qwen3-235B-A22B-Instruct-2507 - modelscope_api_key: + modelscope_api_key: MODELSCOPE_API_KEY modelscope_base_url: https://api-inference.modelscope.cn/v1 generation_config: diff --git a/orchestrator/adapters/code_adapter.py b/orchestrator/adapters/code_adapter.py index ac64a3da0..1f04519bb 100644 --- a/orchestrator/adapters/code_adapter.py +++ b/orchestrator/adapters/code_adapter.py @@ -26,7 +26,7 @@ def run(self, tests_dir: Path, error_log: str = '') -> Dict[str, Any]: """ - 执行代码生成。 + 执行代码生成和验证。 Args: query: 原始需求。 @@ -56,11 +56,14 @@ def run(self, # 检查代码生成是否成功 if not result['success']: - self.logger.error(f"Code generation failed: {result['stderr']}") + # 即使代码生成失败,也要确保src目录存在,以便后续流程 + src_dir = self.workspace.work_dir / DIR_SRC + src_dir.mkdir(exist_ok=True) return { - 'src_dir': self.workspace.work_dir / DIR_SRC, + 'src_dir': src_dir, 'success': False, - 'error_message': result['stderr'] + 'error_message': result['stderr'], + 'test_feedback': None } # 验证生成的代码目录 @@ -69,7 +72,15 @@ def run(self, # 如果code_scratch没有生成src目录,创建一个空目录 src_dir.mkdir(exist_ok=True) + # 执行测试验证 + test_feedback = self.test_runner.run_tests_with_feedback( + work_dir=self.workspace.work_dir + ) + + success = test_feedback['test_results']['success'] + return { 'src_dir': src_dir, - 'success': True + 'success': success, + 'test_feedback': test_feedback } diff --git a/test_external_integration.py b/test_external_integration.py new file mode 100644 index 000000000..e5f376005 --- /dev/null +++ b/test_external_integration.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python +""" +测试External Integration模块功能 +""" + +import tempfile +import shutil +from pathlib import Path +from external_integration.code_scratch_caller import CodeScratchCaller +from external_integration.deep_research_caller import DeepResearchCaller +from external_integration.prompt_injector import PromptInjector +from external_integration.test_runner import TestRunner + + +def test_deep_research_caller(): + """测试Deep Research调用器""" + print("=== 测试 Deep Research 调用器 ===") + + caller = DeepResearchCaller(timeout=30) # 30秒超时 + + with tempfile.TemporaryDirectory() as temp_dir: + output_dir = Path(temp_dir) + + # 测试调用(使用简单查询,可能由于API认证失败,但应返回适当错误) + result = caller.run( + query="什么是人工智能?", + output_dir=output_dir + ) + + print(f"Deep Research 调用结果: {result['success']}") + print(f"返回码: {result['returncode']}") + if result['stderr']: + print(f"错误信息: {result['stderr'][:200]}...") # 只显示前200个字符 + + print("Deep Research 调用器测试完成\n") + + +def test_prompt_injector(): + """测试Prompt注入器""" + print("=== 测试 Prompt 注入器 ===") + + injector = PromptInjector() + + with tempfile.TemporaryDirectory() as temp_dir: + work_dir = Path(temp_dir) + + # 创建测试技术规范 + spec_path = work_dir / "tech_spec.md" + spec_content = """ +# 技术规范:简单计算器 + +## 功能要求 +- 实现加法、减法、乘法、除法功能 +- 支持整数和浮点数运算 +- 处理除零错误 + """ + spec_path.write_text(spec_content, encoding='utf-8') + + # 创建测试目录和测试文件 + test_dir = work_dir / "tests" + test_dir.mkdir() + + test_file = test_dir / "test_calculator.py" + test_content = """ +def test_add(): + assert 1 + 1 == 2 + +def test_divide_by_zero(): + try: + result = 1 / 0 + assert False, "应该抛出异常" + except ZeroDivisionError: + pass + """ + test_file.write_text(test_content, encoding='utf-8') + + # 测试prompt注入 + base_query = "实现一个简单计算器" + full_prompt = injector.inject(spec_path, test_dir, base_query) + + print(f"生成的完整Prompt长度: {len(full_prompt)} 字符") + print(f"Prompt包含技术规范: {'技术规范' in full_prompt}") + print(f"Prompt包含测试用例: {'test_add' in full_prompt}") + + print("Prompt 注入器测试完成\n") + + +def test_test_runner(): + """测试测试运行器""" + print("=== 测试 测试运行器 ===") + + runner = TestRunner(timeout=30) + + with tempfile.TemporaryDirectory() as temp_dir: + work_dir = Path(temp_dir) + + # 创建src目录 + src_dir = work_dir / "src" + src_dir.mkdir() + + # 创建一个简单的源代码文件 + main_file = src_dir / "main.py" + main_content = """ +def add(a, b): + return a + b + +def divide(a, b): + if b == 0: + raise ZeroDivisionError("Cannot divide by zero") + return a / b + """ + main_file.write_text(main_content, encoding='utf-8') + + # 创建测试目录和测试文件 + test_dir = work_dir / "tests" + test_dir.mkdir() + + test_file = test_dir / "test_main.py" + test_content = """ +import sys +import os +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src')) + +from main import add, divide + +def test_add(): + assert add(2, 3) == 5 + +def test_divide(): + assert divide(6, 2) == 3 + +def test_divide_by_zero(): + try: + divide(1, 0) + assert False, "Should raise ZeroDivisionError" + except ZeroDivisionError: + pass + """ + test_file.write_text(test_content, encoding='utf-8') + + # 运行测试 + result = runner.run_tests(test_dir, src_dir) + + print(f"测试执行结果: {'通过' if result['success'] else '失败'}") + print(f"返回码: {result['exit_code']}") + print(f"发现错误数: {len(result['parsed_errors'])}") + + # 运行带反馈的测试 + feedback = runner.run_tests_with_feedback(work_dir) + print(f"反馈结果: {'需要重试' if feedback['should_retry'] else '无需重试'}") + + print("测试运行器测试完成\n") + + +def test_code_scratch_caller(): + """测试Code Scratch调用器""" + print("=== 测试 Code Scratch 调用器 ===") + + caller = CodeScratchCaller(timeout=30) # 30秒超时 + + with tempfile.TemporaryDirectory() as temp_dir: + work_dir = Path(temp_dir) + + # 测试调用(使用简单提示,可能由于API认证失败,但应返回适当错误) + print("注意:由于API密钥问题,Code Scratch可能会失败,但这表明模块能处理错误") + result = caller.run( + prompt="创建一个简单的Python程序,打印'Hello World'", + work_dir=work_dir + ) + + print(f"Code Scratch 调用结果: {result['success']}") + print(f"返回码: {result['returncode']}") + if result['stderr']: + error_preview = result['stderr'][:200] if len(result['stderr']) > 200 else result['stderr'] + print(f"错误信息预览: {error_preview}...") + else: + print("无错误信息") + + print("Code Scratch 调用器测试完成\n") + + +def main(): + """主测试函数""" + print("开始测试 External Integration 模块功能\n") + + try: + test_deep_research_caller() + test_prompt_injector() + test_test_runner() + test_code_scratch_caller() + + print("所有测试完成!") + print("\n注意:API认证相关的模块(Deep Research和Code Scratch)可能会由于API密钥问题失败,") + print("但这表明模块能够正确处理错误并返回适当的错误信息。") + + except Exception as e: + print(f"测试过程中出现异常: {e}") + import traceback + traceback.print_exc() + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/workspace/run_20251127_114214/report.md b/workspace/run_20251127_114214/report.md new file mode 100644 index 000000000..35d292233 --- /dev/null +++ b/workspace/run_20251127_114214/report.md @@ -0,0 +1,74 @@ +# Final Report on Building a Simple Calculator App + +## Introduction +This report outlines the comprehensive analysis and recommendations for developing a simple yet feature-rich calculator application. The primary focus is on identifying essential functionalities beyond basic arithmetic operations, selecting appropriate platforms and programming languages, and establishing design preferences and UI/UX requirements. + +## Functionalities Beyond Basic Arithmetic Operations +### Advanced Mathematical Functions +Incorporating advanced mathematical functions enhances the utility of the calculator app. These include: +- **Trigonometric Functions**: Sine, cosine, tangent, and their inverses. +- **Exponential and Logarithmic Functions**: Natural logarithms, base-10 logarithms, exponential functions. +- **Hyperbolic Functions**: Hyperbolic sine, cosine, tangent, and their inverses. +- **Power and Root Functions**: Square root, cube root, nth power, nth root. + +### Scientific Notation and Precision Control +Supporting scientific notation allows users to handle very large or very small numbers efficiently. Additionally, providing options to control precision (number of decimal places) improves accuracy in calculations. + +### Memory Functions +Memory functions enable users to store intermediate results for reuse, facilitating complex calculations without manual reentry of values. + +### History Feature +A history feature that logs recent calculations allows users to review past computations easily, aiding in error checking and reference. + +### Unit Conversion +Integrating unit conversion capabilities (e.g., length, weight, temperature) makes the calculator versatile for various applications. + +### Graphing Capabilities +Basic graphing features, such as plotting functions, can be invaluable for educational purposes and data visualization. + +## Platform and Programming Language Selection +### Platforms +Choosing the right platform(s) depends on target audience and distribution strategy: +- **iOS**: Offers seamless integration with Apple devices, robust ecosystem, and strict guidelines ensuring quality and security. +- **Android**: Provides broader reach due to its dominance in the global market, flexibility in customization, and open-source nature. +- **Web**: Ensures accessibility across devices and platforms, ease of updates, and potential for integration with other web services. + +### Programming Languages +The choice of programming language influences development speed, performance, and ease of maintenance: +- **Swift**: Preferred for iOS development due to its efficiency, safety features, and strong community support. +- **Kotlin/Java**: Recommended for Android development, offering extensive libraries and tools for building robust applications. +- **JavaScript/TypeScript**: Ideal for web applications, enabling responsive designs and interactive features. + +## Design Preferences and UI/UX Requirements +### User Interface (UI) +A clean and intuitive UI is crucial for user satisfaction. Key considerations include: +- **Responsive Layouts**: Ensuring the app looks and functions well on various screen sizes. +- **Consistent Color Scheme**: Using colors that enhance readability and convey functionality clearly. +- **Iconography**: Utilizing clear and recognizable icons for buttons and functions. + +### User Experience (UX) +Enhancing UX involves focusing on ease of use and accessibility: +- **Keyboard Navigation**: Allowing users to navigate and operate the calculator using keyboard inputs. +- **Voice Input**: Incorporating voice commands for hands-free operation. +- **Accessibility Features**: Supporting screen readers, high contrast modes, and adjustable font sizes to cater to diverse user needs. + +### Interactive Elements +Interactive elements improve engagement and functionality: +- **Touch Feedback**: Providing visual or haptic feedback upon button presses. +- **Drag-and-Drop Functionality**: Allowing users to rearrange buttons or inputs for personalized layouts. +- **Customizable Themes**: Enabling users to choose from different color schemes and themes based on preference. + +## Conclusion +Developing a simple calculator app with advanced functionalities, thoughtful design, and cross-platform compatibility ensures a valuable tool for users. By incorporating trigonometric functions, memory features, and graphing capabilities, the app can serve a wide range of users effectively. Selecting the appropriate platforms and programming languages based on target audience and distribution goals will facilitate successful deployment. Prioritizing a clean UI and enhanced UX through interactive elements and accessibility features will lead to a satisfying user experience. + +## Future Enhancements +Future enhancements could include: +- **Integration with Cloud Services**: Allowing users to save and sync calculations across devices. +- **Machine Learning Integration**: Predicting and suggesting functions based on user behavior. +- **Augmented Reality Features**: Displaying graphs and calculations in augmented reality for a more immersive experience. + +By addressing these aspects, the calculator app can evolve into a comprehensive and user-friendly tool. + + +## Sources + diff --git a/workspace/run_20251127_114558/report.md b/workspace/run_20251127_114558/report.md new file mode 100644 index 000000000..4dca82b48 --- /dev/null +++ b/workspace/run_20251127_114558/report.md @@ -0,0 +1,94 @@ +# Final Report on Calculator App Development + +## Introduction +The development of a simple calculator app presents an opportunity to explore beyond basic arithmetic operations and to consider user experience, functionality, and platform compatibility. This report outlines the recommended features, platforms, and design guidelines for the calculator app. + +## Recommended Features and Functionalities +### Basic Arithmetic Operations +- **Addition**: Essential for quick calculations. +- **Subtraction**: Allows for determining differences between values. +- **Multiplication**: Facilitates scaling and repeated addition. +- **Division**: Enables splitting values into equal parts. + +### Advanced Mathematical Functions +- **Square Root**: Useful in various mathematical computations. +- **Exponentiation**: Supports raising numbers to a power. +- **Logarithms**: Provides logarithmic calculations for scientific applications. +- **Trigonometric Functions**: Includes sine, cosine, and tangent for geometry and physics. +- **Factorial**: Computes the factorial of a number, useful in combinatorics. + +### Scientific Notation and Precision Control +- **Scientific Notation**: Displays very large or very small numbers succinctly. +- **Precision Control**: Allows users to specify the number of decimal places for results. + +### Memory Functions +- **Memory Store (M+) and Recall (MR)**: Enables saving and recalling intermediate results. +- **Clear Memory (MC)**: Resets the stored memory value. + +### History Feature +- **Calculation History**: Keeps track of past calculations for reference. +- **History Navigation**: Allows users to scroll through and edit previous calculations. + +### Customizable Themes and Layouts +- **Theme Selection**: Offers different color schemes and styles. +- **Layout Options**: Provides various button arrangements and sizes. + +### Unit Conversion +- **Basic Units**: Converts units within categories like length, weight, and temperature. +- **Advanced Units**: Includes specialized units for scientific and engineering applications. + +### Graphing Capabilities +- **Function Plotting**: Visualizes mathematical functions and equations. +- **Graph Analysis**: Provides tools for analyzing graphs, such as finding intersections and extrema. + +### Voice Input +- **Voice Commands**: Accepts voice input for hands-free operation. +- **Natural Language Processing**: Interprets spoken commands accurately. + +### Offline Mode +- **Local Storage**: Stores data locally without requiring internet access. +- **Background Calculations**: Performs calculations in the background even when the app is minimized. + +## Platform Considerations +### iOS +- **User Base**: Large and primarily tech-savvy. +- **Development Tools**: Swift and Xcode provide robust tools for iOS development. +- **Design Guidelines**: Adheres to Apple's Human Interface Guidelines for consistency and usability. + +### Android +- **User Base**: Diverse and extensive, covering a wide range of devices. +- **Development Tools**: Kotlin and Java are popular choices for Android development. +- **Design Guidelines**: Follows Material Design principles for intuitive user interfaces. + +### Web +- **Accessibility**: Reachable across multiple devices and operating systems. +- **Development Tools**: HTML, CSS, and JavaScript form the foundation of web development. +- **Responsive Design**: Ensures optimal performance on various screen sizes and resolutions. + +## Design Guidelines and User Interface Elements +### Consistent and Intuitive Layout +- **Button Placement**: Organizes buttons logically to minimize errors. +- **Visual Hierarchy**: Uses size, color, and spacing to establish importance and guide user flow. + +### Clear Display and Readability +- **Large Font Sizes**: Ensures visibility and ease of reading for all users. +- **High Contrast**: Enhances readability by using contrasting colors for text and background. + +### Feedback Mechanisms +- **Vibration Feedback**: Provides tactile feedback for button presses. +- **Sound Alerts**: Offers auditory feedback for critical actions. + +### Accessibility Features +- **Screen Reader Compatibility**: Ensures the app is usable by visually impaired users. +- **Customizable Fonts and Colors**: Allows users to adjust text size and contrast. + +### Help and Documentation +- **In-App Tutorials**: Guides new users through basic and advanced features. +- **FAQ Section**: Provides answers to common questions. +- **Contact Support**: Offers a way for users to reach out for assistance. + +## Conclusion +The development of a simple calculator app offers a rich set of possibilities beyond basic arithmetic operations. By incorporating advanced mathematical functions, customizable themes, unit conversion, graphing capabilities, and voice input, the app can cater to a wide range of users and use cases. Considering multiple platforms—iOS, Android, and web—ensures broad accessibility and reach. Adhering to established design guidelines and user interface principles will result in an intuitive and user-friendly application. + +## Sources + diff --git a/workspace/run_20251127_120614/report.md b/workspace/run_20251127_120614/report.md new file mode 100644 index 000000000..872d4b30e --- /dev/null +++ b/workspace/run_20251127_120614/report.md @@ -0,0 +1,72 @@ +# Simple Calculator App Development Report + +## Executive Summary +This report outlines the development strategy for a simple yet functional calculator app based on user requirements. The primary focus is on ensuring simplicity while including essential functionalities beyond basic arithmetic operations. The report also discusses the selection of platforms for development and provides design guidelines for the user interface. + +## Functional Requirements +### Basic Arithmetic Operations +The calculator app must support fundamental arithmetic operations: +- Addition (+) +- Subtraction (-) +- Multiplication (*) +- Division (/) + +### Advanced Functionalities +Beyond basic operations, the following advanced functionalities are recommended to enhance usability: +- **Percentage Calculation**: Allows users to calculate percentages easily. +- **Square Root and Power Functions**: Enables computation of square roots and powers of numbers. +- **Memory Functions**: Includes memory storage options such as M+, M-, MR, and MC for storing intermediate results. +- **Scientific Notation**: Supports input and display of numbers in scientific notation for handling very large or small values. +- **History Feature**: Keeps a log of recent calculations for easy reference. +- **Clear Entry vs Clear All**: Differentiates between clearing the current entry and resetting the entire calculation. + +## Platform Selection +Given the user's preference for simplicity, the calculator app will be developed for the following platforms: +- **iOS**: Apple's mobile operating system, offering a seamless experience on iPhones and iPads. +- **Android**: Google's mobile operating system, widely used across various devices. +- **Web**: A browser-based version accessible from any device with internet connectivity. + +Developing for multiple platforms ensures broad accessibility and allows users to choose their preferred device for accessing the calculator app. + +## Design Guidelines and User Interface Preferences +### General Design Principles +- **Simplicity**: The user interface should be clean and uncluttered, focusing on ease of use. +- **Consistency**: Ensure consistent button sizes, spacing, and color schemes across different screens. +- **Accessibility**: Incorporate features such as adjustable text size and high contrast modes to accommodate users with visual impairments. +- **Responsiveness**: Design the app to adapt seamlessly to different screen sizes and orientations. + +### Specific UI Elements +- **Button Layout**: Arrange buttons logically, grouping similar functions together (e.g., arithmetic operations, memory functions). +- **Display Area**: Use a large, clear display area to show current and previous inputs, as well as results. +- **Backspace and Clear Buttons**: Include easily accessible backspace and clear buttons for correcting input errors. +- **Navigation**: Implement intuitive navigation to switch between different modes or settings if necessary. + +### Visual Design +- **Color Scheme**: Choose a neutral color palette with contrasting colors for buttons and text to ensure readability. +- **Typography**: Use legible fonts with appropriate sizes for both button labels and display text. +- **Icons and Symbols**: Utilize universally recognized icons and symbols for operations like percentage, square root, and power. + +## Implementation Considerations +### Cross-Platform Frameworks +To efficiently develop for multiple platforms, consider using cross-platform frameworks such as: +- **Flutter**: Developed by Google, Flutter uses Dart and provides a native look and feel across iOS and Android. +- **React Native**: Developed by Facebook, React Native uses JavaScript and offers a rich ecosystem for building high-performance apps. +- **Progressive Web Apps (PWAs)**: For the web version, consider building a PWA to provide a native-like experience with offline capabilities. + +### Testing and Optimization +- **Unit Testing**: Implement unit tests to verify individual components of the app. +- **Integration Testing**: Ensure seamless interaction between different parts of the app. +- **Performance Optimization**: Optimize the app for speed and efficiency, especially for complex calculations. +- **User Feedback**: Gather feedback from early users to identify areas for improvement. + +## Conclusion +The simple calculator app, designed with user simplicity in mind, will offer a range of functionalities beyond basic arithmetic. By developing for iOS, Android, and the web, the app will cater to a wide audience. Adhering to design guidelines and implementing robust testing procedures will ensure a high-quality user experience. + +## References +- [Flutter Documentation](https://flutter.dev/docs) +- [React Native Documentation](https://reactnative.dev/docs/getting-started) +- [Progressive Web Apps (PWAs)](https://developers.google.com/web/progressive-web-apps) + + +## Sources + From 4893ff44a256a52ad375853ec27fa76e87c61359 Mon Sep 17 00:00:00 2001 From: Peterrpeterrr <904379662@qq.com> Date: Thu, 27 Nov 2025 13:13:35 +0000 Subject: [PATCH 13/14] Apply pre-commit formatting changes --- external_integration/code_scratch_caller.py | 21 +-- external_integration/deep_research_caller.py | 76 ++++++----- external_integration/prompt_injector.py | 56 ++++---- external_integration/test_runner.py | 121 ++++++++++-------- orchestrator/adapters/code_adapter.py | 16 +-- skx-docs/00analysis/code_agent_analysis.md | 2 +- .../external_integration_analysis.md | 2 +- skx-docs/00analysis/verification_flow.md | 2 +- .../00analysis/verification_loop_design.md | 2 +- skx-docs/01goals/integration_plan.md | 2 +- skx-docs/01goals/integration_with_role_a.md | 4 +- skx-docs/01goals/role_c_goals.md | 2 +- skx-docs/02todos/0.0_Role_C_Delivery_Note.md | 2 +- skx-docs/02todos/0.1_Role_C_Coding_Plan.md | 6 +- .../02todos/0.1_Role_C_Integration_Plan.md | 2 +- .../02todos/1.0_Core_Architecture_Tasks.md | 2 +- .../02todos/2.0_Verification_Repair_Tasks.md | 2 +- .../3.0_Orchestrator_Integration_Tasks.md | 2 +- .../4.0_Optimization_Delivery_Tasks.md | 2 +- skx-docs/mock_implementation_guide.md | 4 +- skx-docs/mock_spec_test_generator.py | 57 +++++---- skx-docs/user_operation_guide.md | 2 +- test_external_integration.py | 121 +++++++++--------- tests/test_external_integration.py | 77 +++++------ workspace/run_20251127_114214/report.md | 1 - workspace/run_20251127_114558/report.md | 1 - workspace/run_20251127_120614/report.md | 1 - 27 files changed, 314 insertions(+), 274 deletions(-) diff --git a/external_integration/code_scratch_caller.py b/external_integration/code_scratch_caller.py index 738dcd635..4380bd334 100644 --- a/external_integration/code_scratch_caller.py +++ b/external_integration/code_scratch_caller.py @@ -6,7 +6,7 @@ import subprocess import sys from pathlib import Path -from typing import Dict, Any, Optional +from typing import Any, Dict, Optional class CodeScratchCaller: @@ -14,17 +14,20 @@ class CodeScratchCaller: Code Scratch 调用器 通过subprocess调用projects/code_scratch,使用预设的spec和tests """ - + def __init__(self, timeout: int = 300): """ 初始化CodeScratchCaller - + Args: timeout: subprocess调用的超时时间(秒) """ self.timeout = timeout - def run(self, prompt: str, work_dir: Path, model: Optional[str] = None) -> Dict[str, Any]: + def run(self, + prompt: str, + work_dir: Path, + model: Optional[str] = None) -> Dict[str, Any]: """ 通过subprocess调用code_scratch生成代码 @@ -41,7 +44,7 @@ def run(self, prompt: str, work_dir: Path, model: Optional[str] = None) -> Dict[ work_dir.mkdir(parents=True, exist_ok=True) # 创建一个临时脚本来运行CLI命令 - temp_script = work_dir / "_temp_run_code_scratch.py" + temp_script = work_dir / '_temp_run_code_scratch.py' script_content = f''' import sys import os @@ -89,8 +92,7 @@ def run(self, prompt: str, work_dir: Path, model: Optional[str] = None) -> Dict[ env=env, capture_output=True, text=True, - timeout=self.timeout - ) + timeout=self.timeout) # 删除临时脚本 try: @@ -117,7 +119,8 @@ def run(self, prompt: str, work_dir: Path, model: Optional[str] = None) -> Dict[ 'success': False, 'returncode': -1, 'stdout': '', - 'stderr': f'Code Scratch execution timed out after {self.timeout} seconds', + 'stderr': + f'Code Scratch execution timed out after {self.timeout} seconds', 'work_dir': work_dir } except Exception as e: @@ -133,4 +136,4 @@ def run(self, prompt: str, work_dir: Path, model: Optional[str] = None) -> Dict[ 'stdout': '', 'stderr': str(e), 'work_dir': work_dir - } \ No newline at end of file + } diff --git a/external_integration/deep_research_caller.py b/external_integration/deep_research_caller.py index e90a10c37..1621628d7 100644 --- a/external_integration/deep_research_caller.py +++ b/external_integration/deep_research_caller.py @@ -6,7 +6,7 @@ import subprocess import sys from pathlib import Path -from typing import Dict, Any, List, Optional +from typing import Any, Dict, List, Optional class DeepResearchCaller: @@ -14,58 +14,61 @@ class DeepResearchCaller: Deep Research 调用器 通过subprocess调用projects/deep_research,传入用户query """ - + def __init__(self, timeout: int = 600): """ 初始化DeepResearchCaller - + Args: timeout: subprocess调用的超时时间(秒) """ self.timeout = timeout - def run(self, query: str, output_dir: Path, - model: Optional[str] = None, + def run(self, + query: str, + output_dir: Path, + model: Optional[str] = None, max_results: Optional[int] = None) -> Dict[str, Any]: """ 通过subprocess调用deep_research进行研究 - + Args: query: 研究查询 output_dir: 输出目录路径 model: 指定使用的模型(可选) max_results: 最大结果数量(可选) - + Returns: 包含执行结果的字典 """ # 确保输出目录存在 output_dir = Path(output_dir) output_dir.mkdir(parents=True, exist_ok=True) - + # 准备deep_research运行所需的参数 - deep_research_path = Path(__file__).parent.parent / "projects" / "deep_research" / "run.py" - + deep_research_path = Path( + __file__).parent.parent / 'projects' / 'deep_research' / 'run.py' + if not deep_research_path.exists(): - raise FileNotFoundError(f"Deep Research入口文件不存在: {deep_research_path}") - + raise FileNotFoundError( + f'Deep Research入口文件不存在: {deep_research_path}') + # 构建命令参数 cmd = [ sys.executable, - str(deep_research_path), - "--query", query, - "--output_dir", str(output_dir) + str(deep_research_path), '--query', query, '--output_dir', + str(output_dir) ] - + if model: - cmd.extend(["--model", model]) - + cmd.extend(['--model', model]) + if max_results: - cmd.extend(["--max_results", str(max_results)]) - + cmd.extend(['--max_results', str(max_results)]) + # 设置环境变量,传递API key等配置 env = os.environ.copy() - + try: # 执行deep_research result = subprocess.run( @@ -74,24 +77,31 @@ def run(self, query: str, output_dir: Path, env=env, capture_output=True, text=True, - timeout=self.timeout - ) - + timeout=self.timeout) + return { - 'success': result.returncode == 0, - 'returncode': result.returncode, - 'stdout': result.stdout, - 'stderr': result.stderr, - 'output_dir': output_dir, - 'report_path': output_dir / 'report.md' if (output_dir / 'report.md').exists() else None + 'success': + result.returncode == 0, + 'returncode': + result.returncode, + 'stdout': + result.stdout, + 'stderr': + result.stderr, + 'output_dir': + output_dir, + 'report_path': + output_dir / 'report.md' if + (output_dir / 'report.md').exists() else None } - + except subprocess.TimeoutExpired: return { 'success': False, 'returncode': -1, 'stdout': '', - 'stderr': f'Deep Research execution timed out after {self.timeout} seconds', + 'stderr': + f'Deep Research execution timed out after {self.timeout} seconds', 'output_dir': output_dir, 'report_path': None } @@ -103,4 +113,4 @@ def run(self, query: str, output_dir: Path, 'stderr': str(e), 'output_dir': output_dir, 'report_path': None - } \ No newline at end of file + } diff --git a/external_integration/prompt_injector.py b/external_integration/prompt_injector.py index 3763b2e2c..20c62b7fe 100644 --- a/external_integration/prompt_injector.py +++ b/external_integration/prompt_injector.py @@ -2,9 +2,10 @@ Prompt 注入器实现 读取tech_spec.md和tests/目录,构造"元指令"注入到代码生成流程 """ -import json from pathlib import Path -from typing import Dict, Any, List, Optional +from typing import Any, Dict, List, Optional + +import json class PromptInjector: @@ -12,40 +13,44 @@ class PromptInjector: Prompt 注入器 读取tech_spec.md和tests/目录,构造"元指令",包含遵循spec和通过test的指示 """ - + def __init__(self): pass - def inject(self, spec_path: Path, test_dir: Path, base_query: str = "") -> str: + def inject(self, + spec_path: Path, + test_dir: Path, + base_query: str = '') -> str: """ 构造包含技术规范和测试用例的"元指令" - + Args: spec_path: 技术规范文件路径 (tech_spec.md) test_dir: 测试文件目录路径 (tests/) base_query: 原始查询或基础提示词 - + Returns: 构造的完整prompt,包含"请遵循tech_spec.md并使tests/中的测试通过"的指令 """ spec_path = Path(spec_path) test_dir = Path(test_dir) - + # 读取技术规范内容 if not spec_path.exists(): - raise FileNotFoundError(f"技术规范文件不存在: {spec_path}") - + raise FileNotFoundError(f'技术规范文件不存在: {spec_path}') + with open(spec_path, 'r', encoding='utf-8') as f: spec_content = f.read() - + # 读取测试目录中的测试文件 test_files_content = [] if test_dir.exists(): for test_file in test_dir.glob('*.py'): with open(test_file, 'r', encoding='utf-8') as f: test_content = f.read() - test_files_content.append(f"文件: {test_file.name}\n{test_content}") - + test_files_content.append( + f'文件: {test_file.name}\n{test_content}') + # 构造元指令 meta_instruction = f""" 你是一个高级软件工程师,需要根据以下技术规范实现功能。 @@ -59,13 +64,13 @@ def inject(self, spec_path: Path, test_dir: Path, base_query: str = "") -> str: ## 测试要求 以下是需要通过的测试用例,你生成的代码必须能够通过这些测试: """ - + if test_files_content: for test_content in test_files_content: - meta_instruction += f"\n{test_content}\n" + meta_instruction += f'\n{test_content}\n' else: - meta_instruction += "\n当前没有提供具体的测试用例,但请确保代码质量并符合技术规范。\n" - + meta_instruction += '\n当前没有提供具体的测试用例,但请确保代码质量并符合技术规范。\n' + meta_instruction += """ ## 实现要求 1. 严格按照技术规范实现功能 @@ -74,25 +79,28 @@ def inject(self, spec_path: Path, test_dir: Path, base_query: str = "") -> str: 4. 如果有依赖库要求,请按规范中指定的版本安装 5. 代码应具有适当的错误处理和边界条件处理 """ - + return meta_instruction - - def inject_with_error_feedback(self, spec_path: Path, test_dir: Path, - base_query: str, error_log: str = "") -> str: + + def inject_with_error_feedback(self, + spec_path: Path, + test_dir: Path, + base_query: str, + error_log: str = '') -> str: """ 构造包含错误反馈的"元指令" - + Args: spec_path: 技术规范文件路径 test_dir: 测试文件目录路径 base_query: 原始查询或基础提示词 error_log: 错误日志,用于指导修复 - + Returns: 包含错误修复指导的完整prompt """ base_prompt = self.inject(spec_path, test_dir, base_query) - + if error_log: error_feedback = f""" ## 错误修复指导 @@ -106,4 +114,4 @@ def inject_with_error_feedback(self, spec_path: Path, test_dir: Path, """ return base_prompt + error_feedback else: - return base_prompt \ No newline at end of file + return base_prompt diff --git a/external_integration/test_runner.py b/external_integration/test_runner.py index f34a3f92e..52968ca73 100644 --- a/external_integration/test_runner.py +++ b/external_integration/test_runner.py @@ -5,9 +5,10 @@ import os import subprocess import sys -import json from pathlib import Path -from typing import Dict, Any, Tuple, Optional, List +from typing import Any, Dict, List, Optional, Tuple + +import json class TestRunner: @@ -15,29 +16,31 @@ class TestRunner: 测试运行器 在指定目录下运行pytest,捕获输出和错误,解析测试结果 """ - + def __init__(self, timeout: int = 120): """ 初始化TestRunner - + Args: timeout: 测试执行的超时时间(秒) """ self.timeout = timeout - def run_tests(self, tests_dir: Path, work_dir: Optional[Path] = None) -> Dict[str, Any]: + def run_tests(self, + tests_dir: Path, + work_dir: Optional[Path] = None) -> Dict[str, Any]: """ 运行测试目录中的pytest测试 - + Args: tests_dir: 测试文件目录路径 work_dir: 工作目录路径(代码源文件所在目录,用于添加到Python路径) - + Returns: 包含测试结果的字典 """ tests_dir = Path(tests_dir) - + if not tests_dir.exists(): return { 'success': False, @@ -46,10 +49,10 @@ def run_tests(self, tests_dir: Path, work_dir: Optional[Path] = None) -> Dict[st 'stderr': f'Tests directory does not exist: {tests_dir}', 'parsed_errors': [] } - + # 准备运行pytest的命令 cmd = [sys.executable, '-m', 'pytest', str(tests_dir), '-v'] - + # 设置环境,将工作目录添加到Python路径 env = os.environ.copy() if work_dir: @@ -59,7 +62,7 @@ def run_tests(self, tests_dir: Path, work_dir: Optional[Path] = None) -> Dict[st env['PYTHONPATH'] = f"{work_dir}:{env['PYTHONPATH']}" else: env['PYTHONPATH'] = str(work_dir) - + try: # 运行pytest result = subprocess.run( @@ -68,11 +71,11 @@ def run_tests(self, tests_dir: Path, work_dir: Optional[Path] = None) -> Dict[st text=True, timeout=self.timeout, env=env, - cwd=work_dir or tests_dir.parent - ) - - parsed_errors = self._parse_pytest_output(result.stdout, result.stderr) - + cwd=work_dir or tests_dir.parent) + + parsed_errors = self._parse_pytest_output(result.stdout, + result.stderr) + return { 'success': result.returncode == 0, 'exit_code': result.returncode, @@ -80,13 +83,14 @@ def run_tests(self, tests_dir: Path, work_dir: Optional[Path] = None) -> Dict[st 'stderr': result.stderr, 'parsed_errors': parsed_errors } - + except subprocess.TimeoutExpired: return { 'success': False, 'exit_code': -1, 'stdout': '', - 'stderr': f'Tests execution timed out after {self.timeout} seconds', + 'stderr': + f'Tests execution timed out after {self.timeout} seconds', 'parsed_errors': [] } except Exception as e: @@ -98,26 +102,27 @@ def run_tests(self, tests_dir: Path, work_dir: Optional[Path] = None) -> Dict[st 'parsed_errors': [] } - def _parse_pytest_output(self, stdout: str, stderr: str) -> List[Dict[str, Any]]: + def _parse_pytest_output(self, stdout: str, + stderr: str) -> List[Dict[str, Any]]: """ 解析pytest输出,提取关键错误信息 - + Args: stdout: pytest的标准输出 stderr: pytest的错误输出 - + Returns: 解析后的错误信息列表 """ errors = [] - + # 解析输出以提取错误信息 output = stdout + stderr - + # 查找测试失败的相关信息 lines = output.split('\n') current_error = None - + for line in lines: # 检查是否是错误行 if 'FAIL' in line and '::' in line: @@ -147,89 +152,97 @@ def _parse_pytest_output(self, stdout: str, stderr: str) -> List[Dict[str, Any]] elif line.strip().startswith('E '): # 这是具体的错误详情 if errors: - errors[-1]['detailed_error'] = line.strip()[4:] # 移除 'E ' 前缀 - + errors[-1]['detailed_error'] = line.strip()[ + 4:] # 移除 'E ' 前缀 + # 尝试解析Python异常 in_traceback = False for i, line in enumerate(lines): if 'Traceback' in line and '(most recent call last)' in line: in_traceback = True continue - + if in_traceback: if line.strip().startswith('File "'): # 提取异常信息 - error_info = { - 'type': 'exception', - 'traceback': [] - } - + error_info = {'type': 'exception', 'traceback': []} + # 收集整个traceback j = i - while j < len(lines) and not (lines[j].strip() == '' and j > i + 5): + while j < len(lines) and not (lines[j].strip() == '' + and j > i + 5): if j >= len(lines): break error_info['traceback'].append(lines[j]) - if j > i and not lines[j].strip().startswith(' ') and not lines[j].strip().startswith('File "'): + if j > i and not lines[j].strip().startswith( + ' ') and not lines[j].strip().startswith( + 'File "'): # 可能是异常类型和消息 if ':' in lines[j]: parts = lines[j].split(':', 1) error_info['exception_type'] = parts[0].strip() - error_info['exception_message'] = parts[1].strip() + error_info['exception_message'] = parts[ + 1].strip() break j += 1 - + errors.append(error_info) in_traceback = False - + return errors - def run_tests_with_feedback(self, work_dir: Path, error_log_path: Optional[Path] = None) -> Dict[str, Any]: + def run_tests_with_feedback( + self, + work_dir: Path, + error_log_path: Optional[Path] = None) -> Dict[str, Any]: """ 运行测试并生成反馈信息用于修复 - + Args: work_dir: 工作目录,包含src/和tests/子目录 error_log_path: 用于保存错误日志的路径(可选) - + Returns: 包含测试结果和反馈信息的字典 """ work_dir = Path(work_dir) tests_dir = work_dir / 'tests' src_dir = work_dir / 'src' - + # 运行测试 result = self.run_tests(tests_dir, src_dir) - + # 生成反馈信息 feedback = { 'test_results': result, 'should_retry': not result['success'], - 'error_summary': self._generate_error_summary(result['parsed_errors']) + 'error_summary': + self._generate_error_summary(result['parsed_errors']) } - + # 如果提供了错误日志路径,保存错误信息 if error_log_path and result['parsed_errors']: with open(error_log_path, 'w', encoding='utf-8') as f: - json.dump(result['parsed_errors'], f, indent=2, ensure_ascii=False) - + json.dump( + result['parsed_errors'], f, indent=2, ensure_ascii=False) + return feedback - def _generate_error_summary(self, parsed_errors: List[Dict[str, Any]]) -> str: + def _generate_error_summary(self, parsed_errors: List[Dict[str, + Any]]) -> str: """ 生成错误摘要,用于指导代码修复 - + Args: parsed_errors: 解析后的错误列表 - + Returns: 错误摘要字符串 """ if not parsed_errors: - return "所有测试通过。" - - summary = "测试失败摘要:\n" + return '所有测试通过。' + + summary = '测试失败摘要:\n' for error in parsed_errors: if error['type'] == 'test_failure': summary += f"- 测试失败: {error['test_name']} - {error['message']}\n" @@ -237,5 +250,5 @@ def _generate_error_summary(self, parsed_errors: List[Dict[str, Any]]) -> str: summary += f"- 测试错误: {error['test_name']} - {error['message']}\n" elif error['type'] == 'exception': summary += f"- 异常: {error.get('exception_type', 'Unknown')} - {error.get('exception_message', 'No message')}\n" - - return summary \ No newline at end of file + + return summary diff --git a/orchestrator/adapters/code_adapter.py b/orchestrator/adapters/code_adapter.py index 1f04519bb..92824bde1 100644 --- a/orchestrator/adapters/code_adapter.py +++ b/orchestrator/adapters/code_adapter.py @@ -1,11 +1,11 @@ from pathlib import Path from typing import Any, Dict, List -from orchestrator.adapters.base import BaseAdapter -from orchestrator.core.const import DIR_SRC from external_integration.code_scratch_caller import CodeScratchCaller from external_integration.prompt_injector import PromptInjector from external_integration.test_runner import TestRunner +from orchestrator.adapters.base import BaseAdapter +from orchestrator.core.const import DIR_SRC class CodeAdapter(BaseAdapter): @@ -41,18 +41,17 @@ def run(self, if error_log: # 如果有错误日志,包含修复指导 full_prompt = self.prompt_injector.inject_with_error_feedback( - spec_path, tests_dir, query, error_log - ) + spec_path, tests_dir, query, error_log) else: # 正常情况下的prompt注入 - full_prompt = self.prompt_injector.inject(spec_path, tests_dir, query) + full_prompt = self.prompt_injector.inject(spec_path, tests_dir, + query) # 调用CodeScratchCaller执行代码生成 result = self.code_caller.run( prompt=full_prompt, work_dir=self.workspace.work_dir, - model=getattr(self.config, 'model', None) - ) + model=getattr(self.config, 'model', None)) # 检查代码生成是否成功 if not result['success']: @@ -74,8 +73,7 @@ def run(self, # 执行测试验证 test_feedback = self.test_runner.run_tests_with_feedback( - work_dir=self.workspace.work_dir - ) + work_dir=self.workspace.work_dir) success = test_feedback['test_results']['success'] diff --git a/skx-docs/00analysis/code_agent_analysis.md b/skx-docs/00analysis/code_agent_analysis.md index 569ab5373..4fa0c588b 100644 --- a/skx-docs/00analysis/code_agent_analysis.md +++ b/skx-docs/00analysis/code_agent_analysis.md @@ -69,4 +69,4 @@ tech_spec.md + tests/ --> CodeAgent --> src/ --> CodeVerifier --> Result ### 5.2 验证效率 - 优化测试执行流程,减少验证时间 -- 实现并行测试执行,提高验证效率 \ No newline at end of file +- 实现并行测试执行,提高验证效率 diff --git a/skx-docs/00analysis/external_integration_analysis.md b/skx-docs/00analysis/external_integration_analysis.md index 788c84430..2d9f5075b 100644 --- a/skx-docs/00analysis/external_integration_analysis.md +++ b/skx-docs/00analysis/external_integration_analysis.md @@ -72,4 +72,4 @@ - 不修改 `projects/deep_research/` 下的任何文件 - 不修改 `projects/code_scratch/` 下的任何文件 - 所有新代码均位于 `external_integration/` 目录 -- 通过适配器模式与orchestrator集成 \ No newline at end of file +- 通过适配器模式与orchestrator集成 diff --git a/skx-docs/00analysis/verification_flow.md b/skx-docs/00analysis/verification_flow.md index 8cffd81de..0c8a843eb 100644 --- a/skx-docs/00analysis/verification_flow.md +++ b/skx-docs/00analysis/verification_flow.md @@ -102,4 +102,4 @@ ### 6.2 测试选择 - 智能选择最相关的测试用例进行验证 -- 避免运行所有测试用例,提高验证速度 \ No newline at end of file +- 避免运行所有测试用例,提高验证速度 diff --git a/skx-docs/00analysis/verification_loop_design.md b/skx-docs/00analysis/verification_loop_design.md index 4ad443e81..d47a20777 100644 --- a/skx-docs/00analysis/verification_loop_design.md +++ b/skx-docs/00analysis/verification_loop_design.md @@ -105,4 +105,4 @@ ### 6.2 监控指标 - 测试执行时间 - 成功/失败率 -- 平均重试次数 \ No newline at end of file +- 平均重试次数 diff --git a/skx-docs/01goals/integration_plan.md b/skx-docs/01goals/integration_plan.md index f9cfcfb58..ec4fbf43a 100644 --- a/skx-docs/01goals/integration_plan.md +++ b/skx-docs/01goals/integration_plan.md @@ -112,4 +112,4 @@ Orchestrator ### 7.2 性能监控 - 监控代码生成时间 - 监控验证流程性能 -- 监控系统资源使用情况 \ No newline at end of file +- 监控系统资源使用情况 diff --git a/skx-docs/01goals/integration_with_role_a.md b/skx-docs/01goals/integration_with_role_a.md index f3febc84e..e7851af7c 100644 --- a/skx-docs/01goals/integration_with_role_a.md +++ b/skx-docs/01goals/integration_with_role_a.md @@ -61,7 +61,7 @@ Orchestrator -> Code Integration? -> Role C (Code Adapter) - **修改文件**: `orchestrator/adapters/deep_research_adapter.py` - 保持现有的类结构和接口 - 将Mock实现替换为调用 `external_integration/deep_research_caller.py` - + - **修改文件**: `orchestrator/adapters/code_adapter.py` - 保持现有的类结构和接口 - 将Mock实现替换为完整的外部工具调用逻辑 @@ -111,4 +111,4 @@ Orchestrator -> Code Integration? -> Role C (Code Adapter) ### 6.2 集成方式 - 作为orchestrator的功能扩展模块 -- 遵循orchestrator的版本管理策略 \ No newline at end of file +- 遵循orchestrator的版本管理策略 diff --git a/skx-docs/01goals/role_c_goals.md b/skx-docs/01goals/role_c_goals.md index 2c56253e9..f42892330 100644 --- a/skx-docs/01goals/role_c_goals.md +++ b/skx-docs/01goals/role_c_goals.md @@ -75,4 +75,4 @@ - [ ] 能够使用Prompt注入调用Code Scratch模块 - [ ] 生成的代码能够通过Role B的测试 - [ ] 实现至少一次基于错误的自动重试 -- [ ] 完成端到端的演示验证 \ No newline at end of file +- [ ] 完成端到端的演示验证 diff --git a/skx-docs/02todos/0.0_Role_C_Delivery_Note.md b/skx-docs/02todos/0.0_Role_C_Delivery_Note.md index eb65a7eb2..4c6afa16b 100644 --- a/skx-docs/02todos/0.0_Role_C_Delivery_Note.md +++ b/skx-docs/02todos/0.0_Role_C_Delivery_Note.md @@ -94,4 +94,4 @@ print(result.summary) - **输入接口**: 接收来自Role A编排器的query、tech_spec.md和tests/目录 - **输出接口**: 向编排器返回Deep Research结果或Code生成结果 - **错误处理**: 当Code验证失败时,提供详细的错误日志用于触发重试 -- **适配器集成**: 增强Role A提供的适配器实现,提供完整的功能 \ No newline at end of file +- **适配器集成**: 增强Role A提供的适配器实现,提供完整的功能 diff --git a/skx-docs/02todos/0.1_Role_C_Coding_Plan.md b/skx-docs/02todos/0.1_Role_C_Coding_Plan.md index 8f300fdb6..e0681c9d1 100644 --- a/skx-docs/02todos/0.1_Role_C_Coding_Plan.md +++ b/skx-docs/02todos/0.1_Role_C_Coding_Plan.md @@ -1,6 +1,6 @@ # Role C: 智能编码代理实施计划 (Coding/Verify Agent) -**责任人**: C +**责任人**: C **目标**: 构建能够根据技术规范和测试用例生成高质量代码的智能代理,并实现自动验证与错误修复机制 **依据**: [00comprehensive_integration_plan.md](../../chao-docs/01goals/00comprehensive_integration_plan.md) 和 [0.0_Role_C_Delivery_Note.md](0.0_Role_C_Delivery_Note.md) @@ -41,7 +41,7 @@ - [ ] **1.1 实现基础编码代理 (`agent/code_agent.py`)** - [ ] **类**: `CodeAgent` - [ ] **功能**: 接收技术规范文档,生成符合要求的代码文件 - - [ ] **方法**: + - [ ] **方法**: - `generate_from_spec(spec_path, tests_dir)` - 根据规范和测试生成代码 - `refine_code(error_log)` - 基于错误日志优化代码 - [ ] **1.2 实现代码工作流 (`agent/code_workflow.py`)** @@ -102,4 +102,4 @@ ## 依赖项 - 需要 Role A 提供 `orchestrator/adapters/code_adapter.py` 的接口规范 -- 需要 Role B 提供 `tech_spec.md` 和 `tests/` 标准格式 \ No newline at end of file +- 需要 Role B 提供 `tech_spec.md` 和 `tests/` 标准格式 diff --git a/skx-docs/02todos/0.1_Role_C_Integration_Plan.md b/skx-docs/02todos/0.1_Role_C_Integration_Plan.md index 78ac9de3b..f521731db 100644 --- a/skx-docs/02todos/0.1_Role_C_Integration_Plan.md +++ b/skx-docs/02todos/0.1_Role_C_Integration_Plan.md @@ -89,4 +89,4 @@ ## 依赖项 - 需要 Role A 提供的 orchestrator 框架及其适配器接口规范 -- 需要 Role B 提供 `tech_spec.md` 和 `tests/` 标准格式 \ No newline at end of file +- 需要 Role B 提供 `tech_spec.md` 和 `tests/` 标准格式 diff --git a/skx-docs/02todos/1.0_Core_Architecture_Tasks.md b/skx-docs/02todos/1.0_Core_Architecture_Tasks.md index 8ceec6f32..e9012c66e 100644 --- a/skx-docs/02todos/1.0_Core_Architecture_Tasks.md +++ b/skx-docs/02todos/1.0_Core_Architecture_Tasks.md @@ -31,4 +31,4 @@ - [ ] 实现工具函数支持外部调用 - [ ] 命令构建函数 - [ ] 进程管理函数 - - [ ] 输出解析函数 \ No newline at end of file + - [ ] 输出解析函数 diff --git a/skx-docs/02todos/2.0_Verification_Repair_Tasks.md b/skx-docs/02todos/2.0_Verification_Repair_Tasks.md index 6cbee6ca0..e7fc2d7dd 100644 --- a/skx-docs/02todos/2.0_Verification_Repair_Tasks.md +++ b/skx-docs/02todos/2.0_Verification_Repair_Tasks.md @@ -29,4 +29,4 @@ ### 2.4 集成验证与注入功能 - [ ] 在Code Scratch调用流程中集成Prompt注入 - [ ] 在Code生成后自动执行验证测试 -- [ ] 实现结果反馈机制 \ No newline at end of file +- [ ] 实现结果反馈机制 diff --git a/skx-docs/02todos/3.0_Orchestrator_Integration_Tasks.md b/skx-docs/02todos/3.0_Orchestrator_Integration_Tasks.md index 740176fd2..0f531acb5 100644 --- a/skx-docs/02todos/3.0_Orchestrator_Integration_Tasks.md +++ b/skx-docs/02todos/3.0_Orchestrator_Integration_Tasks.md @@ -32,4 +32,4 @@ - [ ] 在orchestrator环境中测试Deep Research调用 - [ ] 在orchestrator环境中测试Code生成和验证流程 - [ ] 测试外循环重试机制 -- [ ] 验证错误处理流程 \ No newline at end of file +- [ ] 验证错误处理流程 diff --git a/skx-docs/02todos/4.0_Optimization_Delivery_Tasks.md b/skx-docs/02todos/4.0_Optimization_Delivery_Tasks.md index 0e4992654..20367c593 100644 --- a/skx-docs/02todos/4.0_Optimization_Delivery_Tasks.md +++ b/skx-docs/02todos/4.0_Optimization_Delivery_Tasks.md @@ -48,4 +48,4 @@ - [ ] 完善技术文档 - [ ] 准备演示材料 - [ ] 创建故障排除指南 -- [ ] 完成最终交付包 \ No newline at end of file +- [ ] 完成最终交付包 diff --git a/skx-docs/mock_implementation_guide.md b/skx-docs/mock_implementation_guide.md index 32d066496..ee836b057 100644 --- a/skx-docs/mock_implementation_guide.md +++ b/skx-docs/mock_implementation_guide.md @@ -23,7 +23,7 @@ 使用Mock实现,可以验证完整流程: ``` -User Query +User Query ↓ Orchestrator (Role A) ↓ @@ -80,4 +80,4 @@ Mock实现确保以下文件在工作目录中正确生成: 当角色B或角色C的实际实现完成后: 1. 替换相应的适配器文件 2. 保持相同的接口和输入输出格式 -3. 运行相同的端到端测试验证功能 \ No newline at end of file +3. 运行相同的端到端测试验证功能 diff --git a/skx-docs/mock_spec_test_generator.py b/skx-docs/mock_spec_test_generator.py index 05de32084..78c7044b6 100644 --- a/skx-docs/mock_spec_test_generator.py +++ b/skx-docs/mock_spec_test_generator.py @@ -2,14 +2,17 @@ # 创建一个mock目录来存放mock实现 import os -import json from pathlib import Path +import json + + class MockSpecGenerator: """ Mock实现:将report.md转换为tech_spec.md 在真实Spec Adapter就位前,生成一个基本的技术规范文档 """ + @staticmethod def generate_spec(report_path, output_path): """ @@ -60,14 +63,15 @@ def generate_spec(report_path, output_path): # 写入tech_spec.md with open(output_path, 'w', encoding='utf-8') as f: f.write(tech_spec_content) - + # 同时生成api_definitions.json(空的) - api_defs_path = output_path.replace('tech_spec.md', 'api_definitions.json') + api_defs_path = output_path.replace('tech_spec.md', + 'api_definitions.json') with open(api_defs_path, 'w', encoding='utf-8') as f: json.dump({}, f, indent=2) - - print(f"Mock tech_spec.md created at {output_path}") - print(f"Mock api_definitions.json created at {api_defs_path}") + + print(f'Mock tech_spec.md created at {output_path}') + print(f'Mock api_definitions.json created at {api_defs_path}') class MockTestGenerator: @@ -75,6 +79,7 @@ class MockTestGenerator: Mock实现:从tech_spec.md生成tests目录下的测试文件 在真实Test Generator就位前,生成基本的测试用例 """ + @staticmethod def generate_tests(spec_path, tests_dir): """ @@ -82,7 +87,7 @@ def generate_tests(spec_path, tests_dir): """ # 确保tests目录存在 Path(tests_dir).mkdir(parents=True, exist_ok=True) - + # 生成一个基本的测试文件 test_content = '''import pytest import sys @@ -111,14 +116,14 @@ def test_example_api(): if __name__ == "__main__": pytest.main() ''' - + # 写入测试文件 test_file_path = os.path.join(tests_dir, 'test_core.py') with open(test_file_path, 'w', encoding='utf-8') as f: f.write(test_content) - - print(f"Mock test file created at {test_file_path}") - + + print(f'Mock test file created at {test_file_path}') + # 可以生成更多特定的测试文件 # 这里生成一个conftest.py用于pytest配置 conftest_content = '''import pytest @@ -132,28 +137,32 @@ def sample_data(): conftest_path = os.path.join(tests_dir, 'conftest.py') with open(conftest_path, 'w', encoding='utf-8') as f: f.write(conftest_content) - - print(f"Mock conftest.py created at {conftest_path}") + + print(f'Mock conftest.py created at {conftest_path}') + # 示例用法 -if __name__ == "__main__": +if __name__ == '__main__': # 示例:在当前目录下创建mock文件 import tempfile - + # 创建临时报告文件用于演示 - with tempfile.NamedTemporaryFile(mode='w', suffix='.md', delete=False) as temp_report: - temp_report.write("# Research Report\n\nThis is a sample research report.\n\n## Key Findings\n- Finding 1\n- Finding 2\n") + with tempfile.NamedTemporaryFile( + mode='w', suffix='.md', delete=False) as temp_report: + temp_report.write( + '# Research Report\n\nThis is a sample research report.\n\n## Key Findings\n- Finding 1\n- Finding 2\n' + ) report_path = temp_report.name - + # 使用MockSpecGenerator生成spec - output_spec_path = "tech_spec.md" + output_spec_path = 'tech_spec.md' MockSpecGenerator.generate_spec(report_path, output_spec_path) - + # 使用MockTestGenerator生成测试 - tests_directory = "tests" + tests_directory = 'tests' MockTestGenerator.generate_tests(output_spec_path, tests_directory) - + # 清理临时文件 os.unlink(report_path) - - print("Mock implementation completed!") \ No newline at end of file + + print('Mock implementation completed!') diff --git a/skx-docs/user_operation_guide.md b/skx-docs/user_operation_guide.md index 46802e299..51077f92b 100644 --- a/skx-docs/user_operation_guide.md +++ b/skx-docs/user_operation_guide.md @@ -168,4 +168,4 @@ ls -la workspace/ 1. **检查生成的代码**:查看`src/`目录中的文件 2. **运行生成的测试**:手动在工作目录中运行`pytest tests/` 3. **分析日志**:查看`orchestrator.log`了解详细执行过程 -4. **调整参数**:根据需求修改配置文件,再次运行 \ No newline at end of file +4. **调整参数**:根据需求修改配置文件,再次运行 diff --git a/test_external_integration.py b/test_external_integration.py index e5f376005..294a9dd5b 100644 --- a/test_external_integration.py +++ b/test_external_integration.py @@ -3,9 +3,10 @@ 测试External Integration模块功能 """ -import tempfile import shutil +import tempfile from pathlib import Path + from external_integration.code_scratch_caller import CodeScratchCaller from external_integration.deep_research_caller import DeepResearchCaller from external_integration.prompt_injector import PromptInjector @@ -14,38 +15,35 @@ def test_deep_research_caller(): """测试Deep Research调用器""" - print("=== 测试 Deep Research 调用器 ===") - + print('=== 测试 Deep Research 调用器 ===') + caller = DeepResearchCaller(timeout=30) # 30秒超时 - + with tempfile.TemporaryDirectory() as temp_dir: output_dir = Path(temp_dir) - + # 测试调用(使用简单查询,可能由于API认证失败,但应返回适当错误) - result = caller.run( - query="什么是人工智能?", - output_dir=output_dir - ) - + result = caller.run(query='什么是人工智能?', output_dir=output_dir) + print(f"Deep Research 调用结果: {result['success']}") print(f"返回码: {result['returncode']}") if result['stderr']: print(f"错误信息: {result['stderr'][:200]}...") # 只显示前200个字符 - - print("Deep Research 调用器测试完成\n") + + print('Deep Research 调用器测试完成\n') def test_prompt_injector(): """测试Prompt注入器""" - print("=== 测试 Prompt 注入器 ===") - + print('=== 测试 Prompt 注入器 ===') + injector = PromptInjector() - + with tempfile.TemporaryDirectory() as temp_dir: work_dir = Path(temp_dir) - + # 创建测试技术规范 - spec_path = work_dir / "tech_spec.md" + spec_path = work_dir / 'tech_spec.md' spec_content = """ # 技术规范:简单计算器 @@ -55,12 +53,12 @@ def test_prompt_injector(): - 处理除零错误 """ spec_path.write_text(spec_content, encoding='utf-8') - + # 创建测试目录和测试文件 - test_dir = work_dir / "tests" + test_dir = work_dir / 'tests' test_dir.mkdir() - - test_file = test_dir / "test_calculator.py" + + test_file = test_dir / 'test_calculator.py' test_content = """ def test_add(): assert 1 + 1 == 2 @@ -73,33 +71,33 @@ def test_divide_by_zero(): pass """ test_file.write_text(test_content, encoding='utf-8') - + # 测试prompt注入 - base_query = "实现一个简单计算器" + base_query = '实现一个简单计算器' full_prompt = injector.inject(spec_path, test_dir, base_query) - - print(f"生成的完整Prompt长度: {len(full_prompt)} 字符") + + print(f'生成的完整Prompt长度: {len(full_prompt)} 字符') print(f"Prompt包含技术规范: {'技术规范' in full_prompt}") print(f"Prompt包含测试用例: {'test_add' in full_prompt}") - - print("Prompt 注入器测试完成\n") + + print('Prompt 注入器测试完成\n') def test_test_runner(): """测试测试运行器""" - print("=== 测试 测试运行器 ===") - + print('=== 测试 测试运行器 ===') + runner = TestRunner(timeout=30) - + with tempfile.TemporaryDirectory() as temp_dir: work_dir = Path(temp_dir) - + # 创建src目录 - src_dir = work_dir / "src" + src_dir = work_dir / 'src' src_dir.mkdir() - + # 创建一个简单的源代码文件 - main_file = src_dir / "main.py" + main_file = src_dir / 'main.py' main_content = """ def add(a, b): return a + b @@ -110,12 +108,12 @@ def divide(a, b): return a / b """ main_file.write_text(main_content, encoding='utf-8') - + # 创建测试目录和测试文件 - test_dir = work_dir / "tests" + test_dir = work_dir / 'tests' test_dir.mkdir() - - test_file = test_dir / "test_main.py" + + test_file = test_dir / 'test_main.py' test_content = """ import sys import os @@ -137,24 +135,24 @@ def test_divide_by_zero(): pass """ test_file.write_text(test_content, encoding='utf-8') - + # 运行测试 result = runner.run_tests(test_dir, src_dir) - + print(f"测试执行结果: {'通过' if result['success'] else '失败'}") print(f"返回码: {result['exit_code']}") print(f"发现错误数: {len(result['parsed_errors'])}") - + # 运行带反馈的测试 feedback = runner.run_tests_with_feedback(work_dir) print(f"反馈结果: {'需要重试' if feedback['should_retry'] else '无需重试'}") - - print("测试运行器测试完成\n") + + print('测试运行器测试完成\n') def test_code_scratch_caller(): """测试Code Scratch调用器""" - print("=== 测试 Code Scratch 调用器 ===") + print('=== 测试 Code Scratch 调用器 ===') caller = CodeScratchCaller(timeout=30) # 30秒超时 @@ -162,42 +160,41 @@ def test_code_scratch_caller(): work_dir = Path(temp_dir) # 测试调用(使用简单提示,可能由于API认证失败,但应返回适当错误) - print("注意:由于API密钥问题,Code Scratch可能会失败,但这表明模块能处理错误") + print('注意:由于API密钥问题,Code Scratch可能会失败,但这表明模块能处理错误') result = caller.run( - prompt="创建一个简单的Python程序,打印'Hello World'", - work_dir=work_dir - ) + prompt="创建一个简单的Python程序,打印'Hello World'", work_dir=work_dir) print(f"Code Scratch 调用结果: {result['success']}") print(f"返回码: {result['returncode']}") if result['stderr']: - error_preview = result['stderr'][:200] if len(result['stderr']) > 200 else result['stderr'] - print(f"错误信息预览: {error_preview}...") + error_preview = result['stderr'][:200] if len( + result['stderr']) > 200 else result['stderr'] + print(f'错误信息预览: {error_preview}...') else: - print("无错误信息") + print('无错误信息') - print("Code Scratch 调用器测试完成\n") + print('Code Scratch 调用器测试完成\n') def main(): """主测试函数""" - print("开始测试 External Integration 模块功能\n") - + print('开始测试 External Integration 模块功能\n') + try: test_deep_research_caller() test_prompt_injector() test_test_runner() test_code_scratch_caller() - - print("所有测试完成!") - print("\n注意:API认证相关的模块(Deep Research和Code Scratch)可能会由于API密钥问题失败,") - print("但这表明模块能够正确处理错误并返回适当的错误信息。") - + + print('所有测试完成!') + print('\n注意:API认证相关的模块(Deep Research和Code Scratch)可能会由于API密钥问题失败,') + print('但这表明模块能够正确处理错误并返回适当的错误信息。') + except Exception as e: - print(f"测试过程中出现异常: {e}") + print(f'测试过程中出现异常: {e}') import traceback traceback.print_exc() -if __name__ == "__main__": - main() \ No newline at end of file +if __name__ == '__main__': + main() diff --git a/tests/test_external_integration.py b/tests/test_external_integration.py index db1ca3d7e..727d20e95 100644 --- a/tests/test_external_integration.py +++ b/tests/test_external_integration.py @@ -1,76 +1,79 @@ """ 测试external_integration模块功能 """ +import os import sys import tempfile -import os from pathlib import Path -# 添加项目根目录到模块路径 -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) - from external_integration.code_scratch_caller import CodeScratchCaller from external_integration.deep_research_caller import DeepResearchCaller from external_integration.prompt_injector import PromptInjector from external_integration.test_runner import TestRunner +# 添加项目根目录到模块路径 +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) + def test_prompt_injector(): """测试PromptInjector功能""" - print("Testing PromptInjector...") - + print('Testing PromptInjector...') + # 创建临时技术规范文件 - with tempfile.NamedTemporaryFile(mode='w', suffix='.md', delete=False) as f: - f.write("# Technical Specification\n\n## Overview\nA simple calculator app\n") + with tempfile.NamedTemporaryFile( + mode='w', suffix='.md', delete=False) as f: + f.write( + '# Technical Specification\n\n## Overview\nA simple calculator app\n' + ) spec_path = Path(f.name) - + # 创建临时测试目录 with tempfile.TemporaryDirectory() as temp_dir: - test_dir = Path(temp_dir) / "tests" + test_dir = Path(temp_dir) / 'tests' test_dir.mkdir() - + # 创建一个简单的测试文件 - test_file = test_dir / "test_simple.py" + test_file = test_dir / 'test_simple.py' test_file.write_text(""" import pytest def test_add(): assert 1 + 1 == 2 """) - + # 测试PromptInjector injector = PromptInjector() - prompt = injector.inject(spec_path, test_dir, "Create a calculator") - - print(f"Generated prompt length: {len(prompt)}") - print("Prompt Injector test: PASSED") - + prompt = injector.inject(spec_path, test_dir, 'Create a calculator') + + print(f'Generated prompt length: {len(prompt)}') + print('Prompt Injector test: PASSED') + # 清理临时文件 os.unlink(spec_path) def test_test_runner(): """测试TestRunner功能""" - print("Testing TestRunner...") - + print('Testing TestRunner...') + with tempfile.TemporaryDirectory() as temp_dir: work_dir = Path(temp_dir) - + # 创建src目录和一个简单的Python文件 - src_dir = work_dir / "src" + src_dir = work_dir / 'src' src_dir.mkdir() - (src_dir / "calculator.py").write_text(""" + (src_dir / 'calculator.py').write_text(""" def add(a, b): return a + b def subtract(a, b): return a - b """) - + # 创建tests目录和对应的测试 - tests_dir = work_dir / "tests" + tests_dir = work_dir / 'tests' tests_dir.mkdir() - (tests_dir / "test_calculator.py").write_text(""" + (tests_dir / 'test_calculator.py').write_text(""" from src.calculator import add, subtract def test_add(): @@ -79,29 +82,31 @@ def test_add(): def test_subtract(): assert subtract(5, 3) == 2 """) - + # 运行测试 runner = TestRunner() result = runner.run_tests(tests_dir, src_dir) - - print(f"Test result: success={result['success']}, exit_code={result['exit_code']}") - print("Test Runner test: PASSED") + + print( + f"Test result: success={result['success']}, exit_code={result['exit_code']}" + ) + print('Test Runner test: PASSED') def main(): """运行所有测试""" - print("Running external_integration module tests...\n") - + print('Running external_integration module tests...\n') + try: test_prompt_injector() print() test_test_runner() - print("\nAll tests passed!") + print('\nAll tests passed!') except Exception as e: - print(f"Test failed with error: {e}") + print(f'Test failed with error: {e}') import traceback traceback.print_exc() -if __name__ == "__main__": - main() \ No newline at end of file +if __name__ == '__main__': + main() diff --git a/workspace/run_20251127_114214/report.md b/workspace/run_20251127_114214/report.md index 35d292233..078163ab0 100644 --- a/workspace/run_20251127_114214/report.md +++ b/workspace/run_20251127_114214/report.md @@ -71,4 +71,3 @@ By addressing these aspects, the calculator app can evolve into a comprehensive ## Sources - diff --git a/workspace/run_20251127_114558/report.md b/workspace/run_20251127_114558/report.md index 4dca82b48..fbfa3cfa1 100644 --- a/workspace/run_20251127_114558/report.md +++ b/workspace/run_20251127_114558/report.md @@ -91,4 +91,3 @@ The development of a simple calculator app presents an opportunity to explore be The development of a simple calculator app offers a rich set of possibilities beyond basic arithmetic operations. By incorporating advanced mathematical functions, customizable themes, unit conversion, graphing capabilities, and voice input, the app can cater to a wide range of users and use cases. Considering multiple platforms—iOS, Android, and web—ensures broad accessibility and reach. Adhering to established design guidelines and user interface principles will result in an intuitive and user-friendly application. ## Sources - diff --git a/workspace/run_20251127_120614/report.md b/workspace/run_20251127_120614/report.md index 872d4b30e..cc45d8e7c 100644 --- a/workspace/run_20251127_120614/report.md +++ b/workspace/run_20251127_120614/report.md @@ -69,4 +69,3 @@ The simple calculator app, designed with user simplicity in mind, will offer a r ## Sources - From 94315d8cfe0bceed92b96cc508c1202b60e30480 Mon Sep 17 00:00:00 2001 From: Peterrpeterrr <904379662@qq.com> Date: Thu, 27 Nov 2025 13:32:39 +0000 Subject: [PATCH 14/14] Update Role C delivery note with latest integration details --- skx-docs/02todos/0.0_Role_C_Delivery_Note.md | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/skx-docs/02todos/0.0_Role_C_Delivery_Note.md b/skx-docs/02todos/0.0_Role_C_Delivery_Note.md index 4c6afa16b..9291dc3fe 100644 --- a/skx-docs/02todos/0.0_Role_C_Delivery_Note.md +++ b/skx-docs/02todos/0.0_Role_C_Delivery_Note.md @@ -12,7 +12,10 @@ ├── orchestrator/ │ └── adapters/ │ ├── deep_research_adapter.py # [MOD] 角色A提供基础,角色C完善 -│ └── code_adapter.py # [MOD] 角色A提供基础,角色C完善 +│ ├── code_adapter.py # [MOD] 角色A提供基础,角色C完善 +│ ├── spec_adapter.py # [NEW] 角色B spec生成适配器 +│ ├── test_gen_adapter.py # [NEW] 角色B test生成适配器 +│ └── doc_research_adapter.py # [NEW] 角色A doc_research适配器 ├── external_integration/ # [NEW] 角色C外部集成模块 │ ├── __init__.py │ ├── deep_research_caller.py # [NEW] Deep Research黑盒调用 @@ -40,6 +43,7 @@ 3. **Prompt 注入机制**: 开发了 "元指令" (Meta-Instruction) 构造器,将技术规范和测试用例注入到代码生成流程中。 4. **验证闭环系统**: 实现了自动化的 Pytest 执行、错误日志提取和修复反馈机制。 5. **与 Orchestrator 集成**: 与 Role A 的适配器模式无缝集成,支持外循环重试机制。 +6. **适配器完善**: 完善了 Orchestrator 中的适配器实现,实现了完整的 AI Agent 工作流。 ## 3. 使用指南 (User Guide) @@ -58,6 +62,8 @@ pip install -r requirements/code.txt ```bash export OPENAI_API_KEY="sk-xxx" export MODELSCOPE_API_KEY="ms-xxx" +export EXA_API_KEY="xxx" # 用于 Deep Research +export SERPAPI_API_KEY="xxx" # 作为 Exa 的备用搜索引擎 ``` ### 3.2 与 Orchestrator 集成使用 @@ -66,10 +72,11 @@ export MODELSCOPE_API_KEY="ms-xxx" 1. Role A解析输入并决定调用模式 2. 如果需要Deep Research,调用Role C的deep_research_adapter -3. Role B处理技术规范和测试生成 +3. Role B处理技术规范和测试生成(通过spec_adapter和test_gen_adapter) 4. Role A将tech_spec.md和tests/传递给Role C的code_adapter 5. Role C执行Prompt注入并调用code_scratch 6. Role C运行验证器并返回结果 +7. 如验证失败,根据反馈进行重试 ### 3.3 独立使用 @@ -79,8 +86,8 @@ export MODELSCOPE_API_KEY="ms-xxx" python3 -c " from external_integration.test_runner import TestRunner runner = TestRunner() -result = runner.run_tests_with_feedback('./workspace/run_XXXX/', './error_log.txt') -print(result.summary) +result = runner.run_tests_with_feedback('./workspace/run_XXXX/') +print(result) " ``` @@ -88,6 +95,7 @@ print(result.summary) - 通过orchestrator的配置文件配置模型参数和重试次数 - 验证系统的配置也在orchestrator中统一管理 +- Deep Research 中使用 ExaSearch 作为主要搜索工具,SerpApiSearch 作为备用,ArxivSearch 为默认选项 ## 4. 与 Role A 的协同说明 @@ -95,3 +103,4 @@ print(result.summary) - **输出接口**: 向编排器返回Deep Research结果或Code生成结果 - **错误处理**: 当Code验证失败时,提供详细的错误日志用于触发重试 - **适配器集成**: 增强Role A提供的适配器实现,提供完整的功能 +- **工作流协调**: 与Role A、Role B协同,实现"Query -> Deep Research -> Spec/Test -> Code -> Verify -> Retry"的完整闭环

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⪚z#P8IWi#&kdK!>=1lq?tfel85%BJW^p)v7U+|bG>)0^qxxSk z#*$uNd4FK{MH9e0-MqSu_`>XA!CyG&R!s5Z6!92_m-6J}@PTWHfpfatP7?Cz z4zZP>VtznV)MEQ3wb*-6txEN~+f1X28X5_W?EM&Ns_pmCSsHOu-X*-fMvHI?BMVEv zvp~9XDO{WpN4eFV?JlS^FDUqnv#e3{i_s84rkAT z0QpB@ICnvONt?rMb1(L8Q$e5=FIr+6=S$ECZ~A$|Qc=3pO)u(1JNzEpJI?cQ%Et)a z`-KMO_u#(nXbe0r=t=k8*9T(lqVEnoq<_}xy9ozlnBmFJgS)S7=T%|Fcs#7oF0!hu zw5h`5@HjB!y}+|NDdRj^eJI7}cEeiCyy*~nFT-zrf^ng?7LbpBm3txasz2d7H{-p> ztS%$2UDrK+Jxqqq*xNqNS2&eM@kDBm-zUZf#j$Ki%pgg9oo!6YZ2MVa5L$)a<*-Ah zl4ipK&l7enpB=NQ&y1p_`}{rSnuj{X! z@0fB1S}BM?g*Ek>Eqxx~BMSI;qv=G8paf*_oDQ5vK$(0BV^r(*>2EbRCto7G;%Euj zQ4-!2@|;f=|NZwz&iAitb^P~Qji_v4cJuKp{^uMGH71=l^+BI&i`f{foI<-o`+a@H z$>xo3?@jqor?P&feLqd{g?VF-$zK9sf^y1LOX?O7Is)mw=ZisLY`G`x@ewe=4AB`^V&jwwuB}q)=)LUCmj~Q<=M>0i(Q_~RKy!)2@w;&1u|3e z-qRzSWtrTCXZybg6Ks4Ty!Rl7Smu0A$Gd;Lm&A4|lg8hou^D^vhtkmKKu> zUYsWPU%*Dw8izx_YV&pns{M*H$AKb+^!l5A(w~K$%^0{c;n_pyKkg#A_PKc{mxyF0 z@&TL1TdAi)G#7kU$yV>WoygXW1tS%OU*)WK{$X`2eEo$E`9cAdayh!x zgWUW^_~Hq%8uQtdS(Q%{bsrBOSC6kP+s9K4vV(MYkZWO}2n~E-`u(Z;(R)(n@GG}#1{S}kP2n89 za084fM~SV>CwR%ZLOa0&_$3tFf8-J+dH5cD4hXfAezrGSx?)l};rFc4sjb)Vto&P0 z@$te^Ciu>(ZwFyPH2{0^zB;hPE%v^-y-pxH**I5>!cRyM!qndlTto+B#e+ozG(CVf zfVI9qkQf+ZgQ%wX*VSTwzt*T8k+YNH)a!$#tqbi_w;DTy4NRe9F5&LM$F>d^CQw$ zaD2c(7Z>T`2^EdlBkL>19$@036q?tP_MdEHINNA8C?Ar9&QqA<_f{BO_&5!= z6(G5bJttK<`Dg8Dx-eSdDu+tcKyfwmLITXLj4n!-$|NZt!2@+iVJlj4qu{|uK(uA3 z=&*uQy16B3Rg@n&{&aC@BB$v3TtPt3d~DmR63nnS(W%o__!g|<{biU<*MCOsUPE7) z>G!}c;AZ&1)A^rRMASXmc#%MQ2-F~vakHQ%8|2o$A(y#+>r?OW7wPx|!kT-dRZY!ah(VFTWTfss9L!y`mRwrVi#>Gj4?Zb+&q*F}rB;X8-@dY>j(t195Pbe`(g`SZ7CU!Bd-T+bi+rAqw zgJM-FCHO^4UE;rYD!g$ZWxGh>Ejwq3By)}RVA0^uGYZej?s%Be9}9vCmvBsm&cM0Y zw@(xC+1TSlgA@sx@|%)&F`D+`)M#I{|Ke4tPJNkRWj>qSKD0EKBDXp>)FYV*$HDmj zdYthJc;Z1nGz%7jQ3U(AsD#Jb2oyQ_#q_RSP~Q5TI6j?pX)|U~-hP2p0(j+BJW$R6 z@4U}h#tsw+U}4(+nV@L|!+y#2s%&dAaQO{`filwQ*0C@cG-sw7-VBs5Yp@k!W??Z7Z0Ay; ze|{%LAS0VS2D3bXD+{gJ=T-)e)8aG6Tg~^MYv#y5_v?sfgE7dM-NeQDN+JoVzRHN* z`!|3w=?AobulGtWMD0dC$r{pmlD93C!w{QIMkp7J$TM;pEze5rWQ%jGk}p9_T;_Eh zoWFcZvJ!rNUrhdJV1Pe<^HVM7?PTNMhW&qiKDj>Nk_lv8*v9$Ek`24_OS#0%uavyA zLU=?5LV81yD+;ypLQ(TvqOzpuM|a7XmDmq0jtchsaFB6Q+@Qn;VvMYy5E9*MsPWcW zf|X;u@w=ft`+s)*S_sy-=d$sxN1&d+hmM*OU|+q>B7Lu!jK)rWNq+VTGgyR_wi9XI z;spA9z`e>s>hr~imfnRmCW=dz1RMG99f0%Q3s(I!E4>fyX9oZ5wiAhto1*+>%J*aCq`qb|kw@@3Lw*oG%@+0G^OpU*;qy_oE&5mSE5Nxmouwrrs zi@6{#^J?H`uC?&r58#dY9^uiQ?WM$1fg#k1%Z)uHSx9|&-L7+Kr^RZicp~^9c7l86 zoTpT1UH|Brss|_X*CR#AV`H*tE@bq82TlD`_x$BzlD3o1wG{kw!Msu9ZY#_;6Wmvo z@)?u%3r?@IOJ19GD9@rhE5dENW}$3XLoikIRcBW(e9reFOc~EdjSnM!6_WgE5aRif zk<^fE6)Klrs9Tmjr8AQvx5nvMIrB`fGUA-urM6hTMZu`CGubb=Cg-=hMaw3e4;x{w zW8R_QalNWX6kKUL98`bj@0E5Yxk6kt{58-!U3=wAQij|%8R2NyYADzAQ*4~s!*(uH z{2(nxqFd%M;#cH|J zTl%H@-VV9%V|{{yL}ri8aS!R_o{J$|J1LsqUTc>p=Fq)}#+X&1*GK71KcmNKBfYw`r{hZqBSSE3ssUxRHAO@qIu_Uj&NRc&H?ESzTn{@Cz z4{h1iVIu9u4Pp}HR-AS{C04F1{d2J|$4_aAmABhxJ@c3Yp{(ClO~g8P5DN-FX2mJ) zjMQ2^*8QjP#Ki#p3$btv>|y%}S?S&m?*nutH0&qI_|lBS#tEz>wwJU)KP0({R(*mL zXWeN3m__<+22bK=go5t9N{<&eh>MxLF$D9SekzqL%M=O3Q>fybVhdvb%)S;iNkxqi z@5t&*9GPM|=T@>NF->^Yk*za7&>`un_7lG!4r3)AsPnUsj)?$i|A9mi4%6*T;SwBI zt736@iwP^xJMnqHqnV zZNg(UWTLnl0$UmC^{z=f&x>C=!6*5Z&b}o=rW2odTIR_v=t?C-TjuH5GQ+LOF=R4bN>6fQD#B6Ugd8!L9Z77wu0U}f?moUHd*>D#Fg{q za@OlQWlk!CpK|-_*WQF2WE$&KHF)CRfJi1FviR7xjif$uP(izJd4I4)ih2AC_6*D3` zoG^|@5voWyazZ#AHQhy-QD(dNb@= zSfY|wAhRPz+jv3Owa+$G5@tio9bF^_$tks*=s{w+A`4(?p^8WLw-MZX-mdS7fwT7R zM^YXuUbqYO5iy&y?o}!hmrG1)cEotp>}_JXUk3}ad=g1-;)jQ!sd>d?L!ZRTYKT#b zQHy%va)ic`K}*4EU&I#{HYH7ySKq%P=M}HQ>6Eklk7x6y=mwiU-#vsvs#ty)emF>) z|291mEYr0n9_ijgbcR!hC?GH8N~vN3GE_*&o|uc6>*Y4O;(ND3i=jQ6mXSD;Y!3e0 zw#F9QS=jiqiKB7CH2M!!NR&aPj>Bv-L%{kuR73A|JZ~~5Lza5FjzWk6t!$VUHS&2# zhoHtsr_`Q3^pN1#@z7Mog3KCCi}n|osnhmg|KeiTU>Md+H<7wmp|1?zv6oe*7bg(MdDQ_e$_FLIk*y9F zcy3;zvAvK`5m>gGH+W?~f%iui(keAo@#AnDG8P9%=-V)I3k4=Z6lIFld1g73MvDb( zZnq;`h|zsn*+W)YhVO8;8GXJfu>D1KK^<)YWjgJU=t$Na#R8SMZe~TMN*y`dUm<>7 zG%F118A)gJd=Sy$JK?Jw8vGfQm3J9qFtD$&M6QuuLA!+w#|-O#8)cNt#WakUVzf&kvH%sdDqYXt*;**qR2HkK9{{=ZA%Rub&RaxPA5-#S*bxQV$dh zL1`Lyc>H^nWZ#|qw0}=oLVi6ETDH`$E>(*qKD=J|{In>HslC`H-S9An;O$N8_vV)1KtEl;^)gZ^(`@ zYILA}?C655venG;Z+!+M$_Q{LN=+nNV#{rDUO{Fkh;-6h`7WBVFVZT@W~I_XEWsSBTUh zo>pr$UeXL#j8$F*a0IhMJ^dn<;=s)iVtK&iJMeCZP4EpXYx}@&uB)_$aSGs|eq`)V zeucQVi=zZ7s%qv8en%T_Cu8*hmS~!+s2x?#ceqFhj7c?1n2$9`{;Os~_2y}>Rysvj zP<7eSTP0F`!(B-rEawYfVP(1n2FLK}kqA}^pYgk^$E9Kc&L)UBwt7|cpuZX)msJaN zT9Wcdv%9f%RWhG^a9365 zz`;RT5;5C!S^J?uW-y%Dg7#u(JDhjx4hbbK$dFPa3@J#b!@!_1=R>0Q0X^=y5x-en z-VvJ}omhsz^JWerouW1< z>T5k2(~x?i9*j&;b*f#nA%j4i&`ar9W|*Ox^q&-#^1@75XuZ0W`rd%9)Jd7u0^s+%=!@Y$fnu@`p?BlpY1Ez*5&%&L{i_T+Mb}-c_XbCMz&t};_!Cn8U41N zzQ`L}vX;}m`Vz4-$^Beo&XDwiM5d{ACa0PIcGS%by!X6m8bFqx*)PdTzo0uA;JYTT zq173?u}@s-e1}Q5?0{sJzwU<{e7d#|V*hDwo?pR?5c$uA-G3d&${!7{dMB76ZT#As zPbvfbn1l~=(>`QTDz+)G_AgSQr`;pONlbRJGLCJ@x*s?%hlwtfkTPz~cp04HKa}eD zJa*{>t{{rJGc~R6=PvW;V*}9F(&q!ZONlc*DRB|e{aGCJ7OIC2sKhL`2vaBS>Pna^ z3Pwb~SIO!T#{4_QVrvu)#Uvz37&7&43kA;=$)#J2^K*#;QS%tm zj{50Dw=Wr{rYj#$GfoyiRCCT_R=p7?m2;~4-HM=dA)!2oD{3cvzUM1zYv7A_yR0B1 zx|DX0uWmaw3pCi`dq^UZN;_{N7MZYEqY01UkEaQsf-;arP)>pD*_M|`OI{w*{9 zP63U_T|$ek9N9wImw2YT7z3M|74{k0wE3jNgTyA|QkiaFLXo7%g}6yEUGJ*LrgCwS z5qxBIZQyK4Pt}tKz1po9F!!_Y=XNW2 zEuDOXxP@^)qr?9flTx?3aFJRVND%vL2P?r8XpVvcI9uozUnXzV$RoDm#qtt7uUO%gCra@C3Pkgj)3nNk* zfoo=ohjCntq9lw2;RN!p6-s;WT8(m&W@%$vPOFQ{|7h6lb!h)CM){@BR_*p-DT2k< zDluF}rzx3dX~)aFGs!QvguBrBM0Lb22Qe5y@_tV>f0$b%F`VwDY!20HQfE&V#_%+) zLb{j0*vAM#k0Ox~x;(Fhp2PITTqVJFh$=#z=AqmZTyy+%E*sn90dJlzh>g9xBFDun14VJx!-yfL_C56-7Sz_+_o*wYO<8;WNhrye|+s$&D z#Dn@He~|7@Ns;=RtptT#$RZ}~B(}8#;BuJ$6c~haiAPveeE8? z{6i^~_>CMThK*Wt7+wl{#Fu}qp}#U4$6AX2WnH^0iRP!tlk&8`>YsmY96Mzveg1?( zz%5l+wVnE5alhjO!S&zP_N>3ek%gS1GNazlh8EY2sMGXQ-J-9~S2mw!$fg_8W_Fq2 z&QMJf@xKV#92L@r?ybj|fhoSW`LosAA|E?Rk*+)0#uj~}wQp`)3iG%X&2>KxJ(3O- zs}w^d*IjE8u4Skr_rNc{^R8R}leU(+z4Zp4WM~!Hg3`RGc~)SdC~J7n7-;gXbr+46 zQl|)iA=;BUbQ_-rVInf|f|%M{n34_P0NpKx&gHamw?=i=COTLP<L~d|Y{$`VS`-2iW%)qg&XI)>vR~m>@)%kcl2Hf~) zbz+2wW`?uV>k`ZK$$rKzZ0-1asf@9z&l%_L{~@GGRw1@^w|K6k?Y+Ln>Gv>l?Xp!r znGR#5?)`L}fA<2KbaEAn-%J#ON8W=Eq^1dOwvbR!i*e)sRPbec9BF~g6dJyNE3n`tZgffwZ{sjCAH>H6?i_*|Ug?-{*o z1N+TGFJeP-??2g%%gGj$4-XINc>KJyH;}cV*R@&qoO+Su3wpi0$*IdLqVNUE^GmpFNmlxUyrSSoi+e^`9B=iM`7`U%;re_cVad%((cyW- z9}&DP^~Vag(qh#3gS=$tEjsQ9uGXY=%-!Grx(2#B7CHB?l|E8jSNuZ!rtOV7fP!oA z+-;S`Q3r0RDtQxNLRaVU_gC~uEh;g>Lbvck9VdC#PE`Wec!b^4cZBPlSKL2v=Dii1 z#Yyo)NYlOGjZ$|;GKZsF>8Xz<#4^R|yHDq+vFGn()@Q(&-;PRMcJ!0b(2sYqb6-=I zPdc{(|FNL|#Jy#8f%8VCkB{VrHEyaIB^y+J)=`|=g*4zGPfqnW!U(Kg`7tbf8SG0z zI4XuZt=4noBic3R{zTN4oM$@p-E{6DfYS0_(lzsH+b@xeHTE zJQvz|I&??!hVOB(I$EY?ml^tiZqkD+SD`|*M4e4kNc7w8(>Lxv2=8S2F@dh+hfqpDnU2eG7~X^Q8`1A+zFiH24Ih2z z*M`M@f$XF@Wb5yW^fH?e6BqZ%k%CTnm%^V#zGJ9SeK)S*H(5cd=Ce zNH6dSOOwr8zr&ozjFROC6C* z96Elp`rz$OM_s}i?cdk^Dzw*I@C&IJ>x|{tXh(=jR!YXqIlkO>&fT54*9(trf_vz}?bcT!B;x+`xX+IaVK2d}I8z#q{<#6!K6dHn-T^J%rw z;^I)WKz4vC`5I6yy7=amNBpF@0DTXuZX< zBsFLu&+k~rS;l)b*zM^*Av1}0zqp1~ly!FOO-XF~Tnqc>`y_MvVH<;dmAb8%^gD_c zmrvtscVkL@d@ih7>jK!OCgbZON_lp0Hm{@0nV4EJ`tUPl%sBA`#jgj&YHZg$h2gCJ z#PED2!&F0i!3WasqDt+nJP$oHb2Ap2_IMhEPBGy>73QZ*a4l43u6c9nlFef78eiQ$ zR->Af53{Kn>wJqZ6L|W^c$M4wDdEvNM-6?1POuo7uilH=dM&K|X_H2hPPw6qE|v>p zbaiI0n(w{+G$TIsu9h0{{F-f7Y^G!N@ddA@kHS9Piq;})m@T`c8?y{EeZg#d5Q>s5 zP0B_4i5F~5@0X2K3`vTH{q$S-%u!?!N#)08J4c-_#Z~L2=or!i<*fyg3eJyMRFxB4 z!op3GqdJ91zmqt>3hL0ye1O&_W1dp%PWlQvGs}(1QMJnC?9xCuhG^8_AK$3 zI+<)=9Bn`GQ7he2u<+@hO7YR`bHt=|d{jx%Fl1mG zpL`(i%!@01Bl0yXKM%EN!hFk+V4QgW3<~LYDz~L@XNBzkHB05p_um5xi8_4yVn12E zoX{!}s?ndzH1?v;|EWqI5*Lh99K4I<9qP<|L54;MQyvPl%b%IiSJjdh$3#uKCw!&7JG^g$vb0de_zV*f6z+PyjWTRR&)}E zP4G(3&RK<;aQ57AhOR>Q*(LHUFft^`}P{#f=e zUJDAs`IxP;>aCoV>q?(C)3Aj@Csx*pk-aTt=(^Tpm4uWcB&glBwp=Xc$Wz*t z1wXUKl++gRkY-I$<^;;nw55>5|LYBe#skdT(d3yKx6mFFi}D~etUXD%gq0Fe{bFK_ zklslqv|0knZ?V+e)I!M$x=2~l#OH++mde6B1Ne91BVtHtDjO9L5rJ%8i3<;nQ;E-7 z83}-e)tVTKw43!@dN%TE1`A)Fkdg#g%AP@0`dcnS%?Z$>$iiGWGFAGB$r-o}wUvhq z#ne-cRnm{|8JLv))#o)W3bDU9^$$!cf!S9#VgX>&UgbCIS@7=x?)Jg^0U|B@!#q?ug|xPzf^#7?aFcar*-pb{{8&lHkhAB5K2Q z6`+c-tZ<%UHf?8OC*Plc_ z9{QsCPw81wO_|4S$M(j3(OEaU6HGB3+jGkwD*<5So&2}s_xJ+@l#I%2h za)rjwGNaItr`#&jn*vyI+Jsc1NYYAZ?n1os;TN4y<;Q$G3gIe3_R+oh_TO(%_wQ~Gxy`}Flzb6m&e|shz)4Kb zg}KN%XyY_a^NUfd0ACU%e;-KZh`bLv^y%2k)Fs62#o{5)AJd>(F_fvKr62ZgZ^8wQ z_=aZ1I}?N!d+!ya8JQU#C3+fDC>m>^>_3)tOl4A4iPuIUF6SXjBZ2x&n`+lmb^fB~ zp>x2GPLA&NMTngeH$<>Q6d*sKX-s|h<`g^ykc(VJYingvw5u z)16s{l-3hKypNU_;5mfQV#Q*j3u0g6XcxHpx6kNG)p|seVR^+Gr@P&QUHs_Kc=W zVZ$$0h|_0N*p8CLnzcIJ+Jdu^C_U{x1=X^+ReNl(Y}kM;0)(GSmEL)_;WCD*mqO61 zgT&~mrt%#iX|V-HXNwA*M{_Br=&XU8dTm!QU$u2OUveo8Su(^+U{puylCo<+@=qzs{2KmVJ$2x#d)i7LBH!E-6$cG2`Ba%5^xLjd zUmJBIARXs4O=J39C<9pY2_gB%n>_8S-^l0nisH6Hu1EtX-z#)aHX*2cZB$!B+8y$& zP_7t4VEBYG_}Oa4?My!P?kxUQx^y=s0INoX)^%?X2mQ_#4xwHT@7wJQy*L?ri6>Is zzaaOB$iDW39_}}vg(SU0EKl%X&tc-6g6+3_%<1LhnspInH^402d|a=&eSNkwzer+n z#ByEE+Y=nDEm9CY2e|Qb5MDnL1B?~;lN7`&vy(|1suI=gX0IB@06RpxJC=2I@FM{d z;_Re>>VI}ZWIN{M|HH@3F^qQ?y|wF-9Bt_j=l7VO9x}a^as&vA9+L=mac8j>!Thk> zL+3d~%>6%<)M0w~8@k>t^Pd2aArE}d^fR*ZS6SBX0iDg3Ryv+uN)P|gJ;E7N2G5yk z{X7@q!c?R4D$Ac`_r+9Tek1O$Li%9{jnnrcW5daUagURA7os22)t~A>Zymh^xlbLV zAl`ikBiE&FuOJyI4T+<9@{_Xh+;2rFOCoqqr=D#{fAZ{t)B!eD5IIU5r&zv#%(2Fi z=`R^E2^ta~wOS$$#-A0-Ty8!HSf5_%?SFS=jZmfg`=tTdQsl=Ud8iN}Ru=&_Ru}3+ zP|KbLUZI~Z_1LZr$_0iI3xR&SEIQrW?adUF6y|jzBDvgwp_)y3g)AW{IPFf&F%pN= z{^y4;OBr_tDs~||Wg8FTmR7qnW&BTN8fN_lyWdD2EH0SFAdV?{qUoiTkcGJ$DLgs` zX9qIpBhJkPUVKkaaX7Zeu2BaLyYy!%LL%?A<88A6Lz^p6x>xz0Rsi6!lH&moHO=ZG<4%Qv6;T8ybjwtz+10nq%AEK@|FrJn0^r zFeMMTebU|c#p^THArAA4QOAvz!ZpZ;xf6hxo+eT&lI7lFX}|}s`m2`Tr$P`>`c*_j zY)b)RNvs+J@Oqc~gJe9azyImC>H`24{2*&IQ@0!0-B-75q+g#h@1nn&(us8XSLu!G zf?nL`_ogoh<4qs<%9{8oOk6wI>nzJRAFU{}M1$m1`4`+FW@ zr<*KA^^4TP`7gNR;rnISD2hipRuh}Xt2f5Mg#j|zZwFKSqh@D&48FT@kP`s@-bt{@ zqatpL8;-t$&xWR;;a1_^BOT+K-(??vnBBLv=<+=nd-9`)cJmgyUb6Wxk((z0Ch$**$&ee_d1+N4=@%G-WqyZFj&|FdXnX#*t0XTGq0IjDEB6C;Dtz8gAKALSR5XSnbG ziX}WWS_B0*A#ysu=t<`~Q|4Sjg@b-eM3RG$(Bt6>$A|?wI?eC|ruy!=aA<*aDd&6~BY)k683!KE`*{$5qY{BYj4wfF{F3_OW0yM<*5D^S zw@yfmXQw!XaJ+%V>Z2WwITR`)!LOGsX5)(A(!u-qR0;Rr%QV}8SJ;b7d;KAcE9+f2 zU=xH1Apz=Q*Fy&VRfx-|EJay_MNLDxF@`!#RR|yeFg-L1?NkPs?y@b zpez|fTlVdmmK)jnExZzOM1ncwsbM0_(2ePw_nM00aFXgU=wF{|@$&){j$Jo{@vD&@Z^ZGiZxp}OQ`kw4lfj#N5&Ij~NzwM6p zIF<$=?bN;g({U0H^7u*LVdG77wrOz1GMWI|16X-(&X5y~A)f)UR-9-Hp|q~;&o=5$ zK=Li(IEo6T1=0>(Tl>VyytW3Fu*Wz-vs2aaZ>D3?EVZQ0@^eE7@a~m23&5CeuFfx> z@kpRr!>bF7{!=_t^01b_zyEql!&|ilZi!F9rq>nB80a$f2c!b7uwvn(oZFD&^z?h+ z6$ki;_ynGPF2EV`JzAi!P{-*AB0`MhIgYu^wUxS@EBGwWgdS4*Eq{NfwGTOostFu@ zuW#b95vTrxe>00MP|vu@&f3u_*ZrHO)g_Pg(no#85WB!|Vl7U#{;SQDww=2yCRUI_ z+^;8xo*9a{sUSNWpfTya>bL_O={|}>v5+Z86VLO@Avn`49%Jiu2a__3BThbM7Z4AF zn0HG)n7Vj-4dT*@O#MT>CD$4^u2oFV(-BJVzFaVEE@~k3+s-*rtli%3!sjV8S&5Ok zeg0zsOu;7LR#u{MYA<&3q^Yf2)MIPtz@C3A*Aj6$JBqR>Q&Bs7UCHw(OxXDxTso`A z)1T@ZQk#pIIh@m!0>nnN41Fv%7ywN_TCgp|#Sxj(^4PQwG%~$mLdTHa`FQtT(}(_S zTK!gF&3ABWkk{_*kNL=oShY`GT*nBle!Cm_J~{H@G~vliQ!pf2f~ksO`Uhvm4cA~c ziYI;VNE;1&{Ns(DY_$NY<#8Xq&E`u?93W5lfG?meFjA0OcHJ24gv;Aq4F0DsCf~b? ztI(ZU%yHGzL|z`Yri&l{c-S7B9}EskQu-)*>DMvcd<~}&5NUh%`rUAb$0*bXept!f z@kOur77`*+9+t`;#mIUa><>b3)uvqe8@4;MHYoO1+z?ZtwMtS!qu{Sf{bW%73Au}t znAZNgp#8T`W5 zm=f(R>C8?af?u!x^yf!S>7DK$9aa7VtOmK{n^$Cyw%Hi`%+YZeVyp*YH6(gKsh2-Gm}@*?%{q$k4z8 z7vA@m&5!3PBr`iBnYLHNq!=sBClMB&7iS5CV$+x6T`b!iz+cGP1V8j|8{*&(+iREH z_yCN%&`Zm@rASy&&cQ7^bcLDKl<#y^IL>Q`;ux~;!Xdc$I^i3lYrG|bcto>`~A+h6VhsHmZ@`nm%l%puWJ-#YZ?1K!G{7@bk1I<~%_YBh@YZPfu zXb!3QGwQHWXHzehpt(Sdp&Ua=lC!{7cAL@y9TwM6pZR{}v>U(N4kivf_kY=VC3Qea zlEP4bks*`TSbMb79~%H5m)Sox8;iJCnn?m)^c5b?IUv_rG^F>gAtr)ml$7x?*?mSm z;dy@Dq~tJ^!JiU5R&Sn0(;{l;zi|6UO}cH=E%4l*F0G#FYH+IEYJE3sBDoD=bA6Ae zcPP5Aj5*ZwjN0p^wr!l_EzWiDGJIXH-Qkm5FWV7cO7Dt&>=#nAMzVDnwy|j+YEt80 zrt3-1?-`L@wK8 zc#$*UW=y>&!q4Q_qW43D%@Mmk;Yi;c?w@ zM{cQ$qrM{{qNnX$_7wF-O1Tp;t}Ri)IM2uFNV^+?W@!=9P6w>9dzbHRo64uM>lfLryl0A7%6y8@27X&&NCZUIo&Wfep<7f1xDG~P zGm1uhZMHR3cx_FR-%akbSqd&fhtemzPp9pq^pK5smo^T)lB0-}F;!?~m73y$@flKt zfa2jNp0gXoxho~kgliyI&D^J+sGt;mb+ar&Pgu)L<;J*qw*a4A?U<9#;pM}e$H0=~ zSQ#$f0GFabLfULMMa^R<<8%R+L@*9}C5 zJ>65I%B{Jh>r&KEXuSh?iz{rr_zWF?1)!aEpiLPs?IV&OKXW?ACnc^thT>4vyvg&X zfYbPcM&hvk->v%qOsn4ix*D_WjhuY8!4|(Nk-xLVvW^z#VWfNfP*{AC%|CFW!c3>= z9qMtZ_5z-k*U5IA2Z{CBx0ynIf=^5^?Q*w-HXuyqLK5+!Wm)@|1g`)T9f^5}!aqO) zoGn)DNHEH~524GPf&7qGBc(=uIhx)Cl?H`GirxAnwb-~7D2TH1h~N!u7g!|2t4FL{ zHNs<#*rvV5OSn9U>jG32s9Ry!5ScjR)*+euqi^nbs_UP4pK41VTM% zdUh*U~cmkZ<*V$v0yO9TI-J{BFHP?U0Xk*2e+Vm~PtPB+z&}`2q zXnd{Sm3dC(_ha+rqvX>;5dD&8_|IHUfwDZ=_VZNzNt}$#Troq|;8%AVBpCl0uGY&o z(uysj8ls2}Q4E!?QkcULlbR)Th_lI+ba&^Gq;bo{5%p(oQ&~NiX|YBt?Y+i|;_)v$ zXCYSI_3936=D_#D{6;f(es;2*-_f3@k>&xUf|Z8pn>nh7pRE^f3m+K=SGF_MUYt_{ z_qSrNe1$!2``NX}5;L9_BL3f=qwsG|dyt-+2K5wp-vhyJ|7W|4KNFn0X9qjCzE6$# z#!Ns{(k+cv#wp#=;&mV zB{p^5k~b!OW0>TN7MXm0)a_H>d~|~_9b@{XC`FF1LB+WB*t*9D(+0!Jxhkn9cvZ_$&re#L-}< zf9CkYxZzRxqxn0ptGwPEEh*+(+?SwJf7mO5t_`NMo|GWG)Lv~T24n4)dcl!gicc?GG9X| z%G}c`dVlX{bska9G+dk&3(gd|kFMBk_ICj5wUK$Y;p|ThWWlGL^h#2b99bqmd)@fT zoH-C<2`IK`;IOdRVee}u6(|UFDI+zZG!vc&ehWmhnaN?YcF1DH-|QX`U{t+?K8-DK z<*&KH>IymfPYZMatYC|%YTz((J^R3rReB?exSfWI2F)5&mgey=tztV-{-m#X=W}{s z59iY?V_QwdZRT*!a?EfH>p*#Or*;Fz0htncB%@Yl1QPS^KW`Rg4Z*I57~S}l&_?OP zG8Q>YU8%L7Igo5tW?#e02X01zy&l5m6i@lp`2&Fz*ywNi+2$8k_-vdV97;u9v7d&Y zBek@*I+(j@oBI$K=`#49QRJb}_`3x6p1I=NZK#&LAzypa(-QW_1*JU|W3?xIFHy#3?j$2Br$mdCgj?e23;^2Adqi%H*z z`vp4ob&m$~uRl1?j-VUSoYtou#-Ax2;HN(q z-djkpU?25jPYfx6*W`VdDjq9N&g)kHEvSC*9pzYk^|lzRn*mMt~S>|yx^(C>c3w4uU=qvJHluN4ZGJx7(=&>{u0 zGzK)DT0Tx_7Q&W0&8dE67JkdVQX3~56igVmlli2fBh6p8Tk=RJ|BY*B$NFeR+R?!6 zHjmYPsN4kb{7zRmc7YqbWZgoxoI|QP;xXnpb%;U8R>3zC?N@lHx-Dqn6_9C!Wavi@LWCsvVDsFp9IIH6;ghzFr~) zog#x1No0V}rEdr>#8G^=P}vZ33&F3+zMt{>2VjR@Lw@vRSpQcWO=JFTlIO)$a}h8! z4aMROo?f4D>^^Mz66xd<%smP`2B~zt#)yCx#mT?O_k!p%Ya@3~N?8iHvw-t*x*xB3 zyzdGUfy1zMrTOK_{D&2ycj+%KKOVAP+FUZpXYMpDP#~%T7Av#g>;IPmAI1J)m(uEk z|M~V&VFee0=VxC08R3@}J>T6`_Mu$O>CcCX-`0l7s|bGhKq-{)Vr9T|Im4YE7QIgt z?}yF^s{)SX;1g%j)do>y0*+Jd=sZ*@0nj|18MoT-AGZAlNB<1zdzoo`^U#BX4mBzR zD*wW6GxlG7hfXO22_d&Hb)P#CHBNAT8UOs~lgm{+c*yPa!P}h|D+}gxkpjjn%Vgn! z#}0!x6KF*S72yEkf4ZZz$6eyS@%p&g6L}ujKw#P(f!M+5TF3Cz^4?Wp-wQe3?Z*CO z_?WQg;>!=Yko6kl&OIalE=w=qJOF591~O9T&^<|LBnm!568Jf}d?!#~5Y3Wa`_g_L zB3sDRr_ev1LRdM>x7AF@^b7+j(=mP_i~CYHE#+Vbc94-gEq!VGt;;cSLJ`i0!boOD z#h0j2CT}<>uUQh~v5>yIxfDRs8-e;D3IqHtQ5;zEu@;O}vKWua9zP&!*+0kV2|x`# zy6}i5SJ3v*Jm^`Es2`u+@md?MUe+01FEbqKHtRJ`w3?qO z(fb_(*5RJb_A#j@G^B3V^0mb)3IdVH%em?Jweaubm$*E03Vi(Z#rTN1@IZ8|?Z&;6 z^K)tVcLYAMH<~amCH}Mj{tLF{j1;W3rnWt_wP9_x^l*ToG zG!+@}d33Is>*N(W>6Kpy8+peP<+f2{Tbi9&h${76u2bJ5x3v+|Er9anTBWa_OM`Y{}9O#hkv1Yn&JL zHsWQMj7PtgHe=iuXT7+Ig4Zr=XZKrEtwsv;Ch=W8&MuCo3CpFXQjr8pKqxG&GL595 zxVX;XNmE}Avou^Z+d04y`z3vLz6WI4qix049rjMbwHNLaI~abTCKWeGrG69QMCKV@ zN6qx&$%E$IuY5<}347X8oxpk2mz$&R9-e2|T*M+NQog4SHJfa46iYW1%wo)TM||bN4Y$f8-aPe30ylefN5W&4BaM zE$$$pYxk?{6Xnga_tTE|4=Fak?-fBl_xjJdEE=*(paJc&js9d+%LE!1UyFIPWRAlh zY5$gtS?6|orSre}(w9_byBJ(gt76a*HHRBe-~GPaM8cM~l8~o$7f^!1BzOH+e|`e! zWX}CR5}1i8!n?HZEV^Q-n*y%Hcz_3Dw=+zeb&x77Yj;3B*qbi8*GA*`-Sohp?9EZ@ z{;~jd36%K$yPXCk1SZeA6X#tMm;KV8;F0^*taLEH;gw^x<`_2#!l$GM8R-h}UA0$P+Tj^ZPvov?8JI8VUeF>n)ot+0kW>vfD2z@eL}aZB!B z)+81S<8@}rDfTc#7Sob`^>TY*2ujhGq zJMsRSN2sY0;y{~{rWv8@dK@;}N-6A+p87q>$~Z$j`Eo62%gFMUc9Za({l)GYc6^6b zc=+ue8GteS3y(njV0Z}ndE%K-8{`Ls$vTtU{nMS1iLb9h9)>?ZRP)z+9#6IBW1nHO z4|-&Qp{f1mL%euCPTdMxYS)3A6iJsm*eca73gs*ksVt|Lc+?iCaPzBlGdPddM%ed0 zb$OHjJ!nlfHgdtKob!Kag}DvHrE(1y+Lt{6mq_6SWI^{0-LH<*$O(l=F^|8)5YnCb z0C41C@-u^7+%@a>KAh|=M^j5ic(}fpxX!$-bo~l(f_UfL^p`;*!{qPEQg8N^zV;zn z>Me$o6&^!4G}Xcc;zaw$s53-w>wd9_XA-TP;i(gut*x+El0Gx&H>$g*iY5eA*P`g7 zKi}P!dQzKjUwh&Y|I{sd!na@S|MYJVq2;XmyCdOZ0+EsxrLz>Y^hVK=(mPP~OiLc& z@g8q~h)&7i|F$wKjWgyNEg6mlsuOW_CVt#;W0IBaa=Pp0N0s;_F2ko_onQ~e6J3ar zYm26-Tyv=LL5?re7Je&D{~Fl^(*OJ8QU8QWyYc5g*NV^9F4f{rF4I#zF4pw>aiX-KZjc&J z-Fi1q{rL-I?gEzY>12cyPsb;5nr>&0ju>eMivA2?$F)M83x&m6E}j9FIh3Ts!nck0 z>w9b#@O*ta1p?P*qaPAgR>;Ix?Rp~nsZK~QY4tCI$hf!_oIAA3zN`P9dAm`ctcr{(blbW$cu-8Lt~U2&1g1};1P-RB;YRXdgY>v|1Hzk5*N zV1|HJ@jdTbJVjfSspr7oOM|83o%y#yj#FRt1l}!x7%RIJP~RBiqv_?lYf+&*(4Ul2 zXf6Q$7PbAxgp^?W;wPm)vpjJ8OF4cRf8h6tg)VS_x6;k6nR{r>=GuN6yGwO#U($4* z{mo_YziEm69p!mA8sgfcaK400We0S{5|v$L{y?i+4Nl}UczYAKaVr}SwmZ@1&e1jI zxu6uSXz?Sjl%3u*RxyBQ7Hq+-eVPA28XioVJ z45yI!>FQ;2U!3X7Ms&GQu<)lcGT{ZF;YIcacU|DuRr$0gF%j*t|YZTt|yWC60h7SL0!| zf})S20xX&B7E-wZ%@p2jmG~Si9*Ik|Z|h82EU>!$Ga;cEh~P{%7|J(GMvNQ8n$z;D z&o*19Pb2D4>784iH<083!(T~A>WhBmCYOxcZRC^E-=tu+In&%Z(#j0j3DbTX%dE5$ z6}#cJ^C|i6_zTi{&M3s}tDX7wW(exauLb>Xryk11p``?^`=U3ZC`Cy^vYmjB#fM=) z%((NTd^&iOr|z78xwC51r_27^FCCC)7d>lDel%U4FH29@Y3+X?cc(bLewQjU?P7qN26F-lRr^etm-ktn+blH?dgoPAly#%L`t#cOB1$!<$wpNY}&*r)hD$BKfC7_Is z>HHH-k~~GhvezTV%G=1U$FiLZapoOF==gP%vJY;`_h4#?43J^yCdlG(d<^wq}E_3}~FLuRE$N}rQfT_0)SlS+zS%YXnWLdpH@ z1!3elrmxT5O3O)}>vA83!BrRK_sVd!K)^DcYQYs7ck;99jrTvUlFTetZYxK%aLy+X?U zw@t2n5d8On^qn<0(^ypzv)U z#4v*2t4H8;+HINB{&$Mvv!AKE_g1t!kG=5IG3wC5{tyjfJ$fUz&n}P;ezXlmJNPx3s^AXjywI;_H=~?FV^b zNR9cJ97`UK$w@n7<2VUu!Cwft79w;odisF-t2X27uMz#due(3HJt@ntUx`Ax&}T>N zT3Dp%-0|{X28=CxJ8De8<=L7QStp`|us_Yfv0k*d4YKTH8|r-r$7JxpTNt8%MiO!l zaOx+`?)#q~){slLk>!a1n{Kf?30CLS`JKUbT2NyYq*qVd8Ey;ak9~gl0jQ6gC0O`^ zEqVjIHDTzH7`L|mDL!DiQQ1fAh@ixuQd6AM!+bdVqcMdXLM7ai95sD(*p>X0zTqh>NO5g7kZ6^Qu4lP#F{SgynMqG^L~DM zB;W6}PP?02LiwY2kQ~jx@TNm@CAj`{kR8m?QIvc>8P{)klGygg4G}|xxO#vi8qUqk zfRmrJsox5szv|pN05__!-cP)=Yc5-5O9l_!N1ND0I{Mh{6W@kBwh6rZa;qm$Gg8{K!<>fu(j4*Yx%Nb*WBZ>@eaE_!DQ^LJ;Grjfpm4Sy7Mw{)K}xxOoA z78iRNZ2Id<+U}oW|L-Xe9+fX`_PEsjRVK)xn6`4dt;h}AY%)ulT`kVTEP+WOEc8F47iv8DSG0 zcH0<9OlzHcMcZo%=ZM|}hMm#rR8hzmgqz0RWVHSDTdO8JjBpEem5LvMCIatG-)G6U z5lCA08d!||j(2i#xmVV&4cq<@#vQq(?+!-=56g{g_a}o(YBw3WT$>=l<*Sxvb<9ya zm%)qKR}wsC_?l9p3H87=B#l*4k*9&E&G%HmN&E)U2U)&I1TfgEWP(7OkUX1oJ=9mu zVc|9HujKM$=o*Eh(rXAFN#E4ULuOGM#tD;V{M9g*ww~1VE@hEJN3HXMLXSBVz4*zC*@O zwvVf3LNfEh>J_8xmimsi>yzf@)1wBfju`f|ySC38JO=VTvXTn#qX6V|2y8wo!4>wA zNG8;F_IA@2)TnNhdY+FnnkRUwQ)#Hk$FxC|4=CBM%>q|DI1IwBIEEj@X1~i0zX@}# zDJBHxB%t^3GJYt;-~jZ#nR+mWlp{tU4qGFI+)EjMAbp41w-S+z{U_xewHjYNpqFJi zEU@^8o>PuI2{R(Ah4$D>$tDE86iOWRNQI^IF@HbT+bEefGa1EC#Ee*E)NGN#F6uI# zcg$q64Vxa6sJO(+yJSP|59tq7c_Zc*`?yxZ&bn`!j!PUJDpb7^(om{`N6`}E@G(m(M2(>N;({+56ia)Dsb zci0w^jma-85hRS6oG#evfjO=I{#%*eSm)4>AaPPJTy{hmw3vI#o~WTei_ZgVq5cR`ObN&>$0K8jUfeT zUOYlUpTBvzZ0ae{DFR2>!<*KsJLTYEe)vI53bwqSz~Tha*gR<9zNQg=gUb{Og2*w8 ze=q^f-GcMqww2F+Md<0P`%RX%C*9F?m^^l-HGe)@)Qa5pS*>2qH0MLPfTbNO3(QX_ z&8ZvG;Jz4mCu>GlT%EJ_T6ppp(kyMPZ+e-8uw9)S&m(T+Ur=VJev602%x`x=_`cXq z%k>+#;J7(oZI!iXSbZz;HjmMx{cb}DjFP2a9`{=0q93@|ynb^r1x2gxs1-b@HXR;~ zV9V7MjrF*3q7F8&!pOdpUtdZ?CBD4GKEAeaSDwV4pQ%{8W`tbduFvZ{4m^?jUAK!D z@}Z8-(awLn$szkPH}(7CQrhK{9qegsgkWym!Ki+8Go@pQPT}`e%QS6UI8@ZT9kNo~ zp{U_V&}KzTPC+r-P9^EzUO?OGQ10j#LvIKc zjV=HFD97SH3${e}T)n*GC?6St=mHUPTiao7d$t)tljfn{I{f9^@~32j)2{sDE6XuB zb(h2e45>kEj5zp}Ef<>kGp83UGRW5DtV+o(i9c?9+NUB5GeI_|&vqWhV>q1zv^0)q zU3qmE;`J~0hcuPwejO+2JFHG$ZZb!UJqH6lr2F*qwbR;v0cluTs3H%tk@OooWQko- zR?+D(b~*6RNwOY#WNDf#Y~i+$W^hsxshrj_N76p;jfj1T@ko0g6Q`^ow*)hGal0|= zCE0nN0i_`)0Y7`(GH#)MC3H+hAsXxSJd&qR^vJ+$dg6@x>DQI!Xeo)qv3aO6Pk?Yf zvGM=?Ci2ndH9^{P;cYi{RO~e_5t?mn2ID4f{vw0}EwSxf{Uy5pOay-g*e?i%4 zKo;A<@}jxs?I&+&We|#OH$H3N@wPm6>R9vM{|q6C%edSUN0Sv-*xOXA47XVY3Rf3% z)y4+jGxuM%j~nXS56=0{Ajp%DR%E*+{yrFI9|bj2Z!;?JlMbQ_JVq;rlssYx82z)@ z1t~TRRE`aGTM^Pok-TH$CrJU%9D&)IE=bvzakR=^Lw>PzV>jv@(Ex>fMDG2x=g60n zGe3fug+k6(+p~Hq*_Dls;I-ZT1Rb2OD-%VAHEt_oI9OARWt<;PEbf=VlZD%iEGG6O z$YL)*@@&ao-xr(fU^enuWp#6$&Su7T%!%tIri3*e`?fCG#bc}Jwc<;-_t}$4$_|fl z%9JdB*;F2R3DoXnw;#DB=vSSuM(TR>+Uky)sHUZS|7N4=)0#wv-qdD>Qy^*o)m3;_ z`*qYP?Ra4z7iig9MU!8Q>2K(@R&O43#zXI?zq~zSZp3Gv;k<(xl0^HTLHuBf@b6A;zmMde%u#&(BZwj6a`n8Kz_!DXdaHPkjzYs`4n7=Zyw2dLT%StwrZ+L=)IH*O7q_sIl@^@ zoXiK#ES}z{`(J*2*|nl(1M>bdLII%aWfBA~1X2)0F1Uj4KO>8cJUrXNJBhQnz8#9w zkLZ)W^m#kwHkxr5tuA2OD6T|%PJMAOF@>LH-c*N#ax=7Z*k&kfmh#bgzyHn?=Aw@Z zI}LbjRM={pyEL?3D=?MRirxs-R$05-D81o1{XmHSMPdb{3BREe$WiDfk7ui!syq93 z&etthF3>L#KRS4BdSkSEI~_~>#d^ue(`TX&qiKYvwpqH9C@xCGaIU!E*o5>w0+lcg zl$rg5UdSVBw{7?pE=6zZ-ouTj3YtQ_kJ}a+@-Ghw^o=2;HWT$a+(fnH;(~x>-@+4U zicLf?2(HXZ+Wr!o+h%rvd4>;f#L6_cjE1KDx{-LZj4aPw7KrC2t6dM4=p0eE4egHJ zdIQS-FZ@FH>&f~x3EoGc^wh(LwR^TO_Fz3ASCFl@x0DMuSa=yh1c;K3@Fy)EstXQ* z4$PCC``gQ89QV7oRnZr1nAxs|`>aqKm-o5{&=yAbrvJ7n23F~=J;JD z_s7$3hqTgu1`r=>M7h`0FMS~aBBJEc6sjz)3Tl6h`XzAY3Dn)szW$uTp#Ze2!<=Rf;veP8O4;G6izCHY#;N zp{2h27pezl>5Z>i;RK$40_FHWUXMxOu*O&Y+Dh%vw}^fx?mv&}YW%VvEueondG>WQ zlrN)&`u*>$c8sqtaweH3_~@UnVXsOp&qs@T(1GR! zpx&dEpvGMvEFHVquvHJyWbfoc4<(vc{dF%Plv(lHJbRR*(-U;$`RvYb6^SxEIzp*! z#*`Gt9!_z*UINO_WN(9rDcY9Gt8<~di5z82kX~0kjvebR0XrZJ#+4@{Pa}=aANCs_ zdvEm~I~_vCkk?L>K;Q8Tqrug$AqRvsE?8@$l{{!hoXC>5lC~oUqeo-g#r{X@!&>*V znf>J_43Fg~cR}pnT}U+iKCl?sFHOV0fYUKvZnana!+En%czUkihqBLY^u@;aOVl%C z=?|gy2If6V%uB5YSLq? z&Okgmdi@^zGN~n4fYyo|>W@LKDOZS0lIZ?}NH&DnC&A|n96HArgwnL`PtbMv&04l| zG$Q3w9eSyA}u~IEimrg>aa(X#0&ZY}7 z7j7f92u)7DBVTHoV*lKbk*&+wMA@=*!#N&%wj9>*pe3!oc1Xf&-+F4PB~(oUN}}V6 zuCo?_=`E;L^t%AvdjLmK8L}QbE|Ro_!0haGu;zUH;<%}#1l_-zU|Zo&E}^hZ>chOB zSq+3vvoA4e-6|mO9vbz%>3l&G&c3h3*QUW&y$J~eo8qG|mP2SoaUqz1;d60nOrb7| z1S49qq2G86d*%!u1)gyOow(a1bR4-?&X>13KkHW(`5|L!4nfL(We(cTj~MCRt|D#s znL6}pizHO@Aev)T^sUAI&zxGhV1xakDJk?~{&l2ZYE5CMWR{REIdoFr^WE^tW^O<8+J$AG(BKsg>qTH|EqBD-BsA2YRe$mo#OIE4R zmt*QT)43V$Z)f!@9VESmIRped;ndTM3!Q*F$5<9p-l7dAId4eBYe1rZ3HX`lX`d$eMu)SoG7`}=ENwB)Jv(dHj8iC9wOv_lPo`ybM!})wZ;(5e zO=s6)bhx`EQ5Rs23lsiZa!&(@^dS*|TysD75g$xaV8DdAzYEov76-o1l%+a%9aUFS zHbiPWOO)p%)egs$WOfKa+_R-=u<}*JK?JF1&hD$KkzLKqL^h_rl%1kJ1(-e2QmT)B z)&xa|rV<_u&0y5m?DdAHGxsiM^=1hyGfyp9Ts!`dRPzb?)4P&5+qnXcaXW>{c^FO< z2m4x@_+U|}+1l(sBB}p0KAp9KyS@u`^o)iG-;(!)-`OvQyX&hS)2Re-M%0)ZSVXG7 z<$u;S;{MKoTw_7=-sBdXpjJn|r8R#Ld`FaG zy2^sH7H$x*FK7BUXAy>q#sXR}MmJfRSWu=5&xMX{sMn@s2tBSGAC z&0+m33jsSEj_Hk??mVR}=5gAQ_eV^6NWl~#h2e{AX;#aHuvv6$f(L!}Ud#70x-JgN zdwrOk_UBS%;Cy7!N4mSz8|mlUq)21m;w^*at;g`KkWjAtKCQ^>D5|}e^zxrS+|+t! zROiLuD?-zAI)lF1?J;35tjzeDjw#TTyLS5?eXmW&+dvm-KWIHCRICdi4lw0?iB2Iq<=Q9I7-txTV3pIvb8WciS6=dcsJ91`1jz(%au zC@A}a)>MWChwzHZz(3`N5?d~1vkwt|B66Y{vH+?7w^^p#5)f<(#1LaboTig1Bav%w z7=diZBzHnY$A{umEl!jd4&CMujj|n)ft>4S-w$o|W_S)SmgJZAjTE9RN zhQ=hBhMqKIsSqB1i))szPvkse%y0PNYunK&NG~DHf!4t6Yy|8-^+WSUap{vxI_lVK8_Ax%>==V%-Y z09nXRib)BNR`L($4&uAgZj5uI-hT;sUF>rxOJwCQW@2oQV=#k+Ok=sw3vh0qKr&qa z-BzE%;MbVWna;I;{*0Jl+O_FGtZU9k*WZDYH6~~-N1PhiYs))N|nNy8W`_ ziYeTpYM)Tm54ur8ML$`1HrgQ8O2%PMvCNs<3I~ijQTxBJzf^;O6H4g6l(FgvT|I4( znvIOa%+Pkfjy)&(m0O$Ld$Y*kB%Pz4vfF?|UM80iA%S-7S zeKU=7|9%#r34N6xaK%*KRs%|Ha{!T*;8o8W&mLN*l|oFSY>h{O7)%7#9Kt5n%yFSD zv}3A^F(`o{Z1>QvJ`c|*$LN?<^k9~;bAKG1ctZ=V_aiIY$ah6)J|&>;3%t-ay2(@(y07KleXFkxMy`8 z3);sm(6Pd}X2(cs$Iq0UlJd?uhX|J->p5s#*t6PUsIS~{q8u6q_1kMWJtZ$ll1xoJ zqF9I_;^P1`G^o$Uz*z0H9mHn>cLAPe)UJ(xo<*Zh95ZQ$93vl}JQvt8pm9pTMIW4e zC1$eXF$HSevbqjon<-cO_pt=tHD|@EVB)52O|nZuKojp+Lt5@o84Rc>K#cF zCZO)Fmic=BBgJ+uBPO^x`P~z628$j6-h6qE8Jm3$?+O|8D2!Adt~uW|f2`ab^>LES zzVx39AGXU@@`DA(XiF9_W#c3M;M6j$bX1Z=XYwJA2t zGWqiDgQr4TKWl%n{_oqp&lbmj{q?#LPuKHJqznkt7u_M3X}X0Jd>h}|eci)#6I?g> z8XRnj1&GD=)!u_B84!k<${P+8h7LVCPA$KwBs}flzO3lbM zk1MsQVyrm`K3gt|($Dr(_|9S%3-sGCjI5|{RG9qiVycA?22;DtC^wr`F}|k+)23vT zD5SCXqaFTExNT{gSjxiFx775DTU@hUUI!6AUdYZ<2qqaF4kP0H;5+=(7F4k_@uhb^ z$Slb#<=wa?rlp71?E55Kh9W)&TAlB$_ZIXTjnZ6NxeEA`7Fx#*s(wFPUQOw^#lu%~ zu<*(4oyz3(*4t)@B?^i`T+9pc50f(BO1TENAHT>cqYODKAqnJWW5TxlEI+u^SsqY# zcQHcm$uq9b$nt8ZZ{2-Ee6iX_X6|d9YHQ$$x)GtO3|v=*Jd+X{gi_g>}* z=6R!m$frHOXXar2-p6hq_M0%;N9jv%$& zqGL)e`&X3e2{SYwhC*owiel##xrX!hXZlZY=4gdr#nx&dYg{+vW`u5zEUUbu*ZVki z9CMXK)^xy>sTfpvjvs#%OwQ<`uO6`V0m$&EJ<>v_Q4L)dA-L$BZ>#j&bfbm}Y-)A7 zS<(INW3V7lrK5MLmE*UM%@XUN;l!i2y2MjzwtMDPa;qE{qpemyi{y1PDpbAPbjiw> zlnU=|erdfOVh}lL_lXkloxQaz-$S=lY>e`}Z0!Ap*WZ%<=Vx^OpZyul4z(>5OY+#~ zzG0DmdVb?%Yf-~A3?$`o3mBgsZ|u0ouUJ_usbbdxg-i71RIlDc>1tSkqhb6TNcq37 z2~|98A)zWuHN<{FOe>Wo(grn7h^agUz+E`}40c3R!C3?semOc0*IGFExiCL}dw+WC zcOgD=s^mfCvZX!KZIvetK4iYPL!%jYVAzuWS)p#du7hG^eu^ zj59h&%TcF1t$ql(^`@LMg*Sfb4m#LVcCP0&NDABH>ZvrHE`C_i7xhVx_I$q;gKO?l z={gag(`b1WHGqf~396k)`pRT`H*BImM(F?B>m2uB^ESu^a$Y%Y|5@QKU(<0IJo_J( zJ6Hh`Q-Sbp8OvmQleNPeNIKnzE)z-97lXvcd=0jJTViq}IwZQ;^{mTW{u_z!Q~Vvy zJq#2&H~jsMl(JGIP7GcBMybjw;;OD6+!3`pu`MQRJ$E(N(cS5q{K1ol zrr4@Z*zkQXzA%gB2N2UrC7T}C5XW{k9$<7e@vsz{KCROW_x}X}<9=~&#?xI^=ZT*) z-WO|H-ps$*X_4jA8&a7Rm-6LXgZCB1y+Gbc5CGFz-Mr_wZYFYJSs0*D$2=tGZp2SW zpAtFK-4IY*XXk=y!HCkIb)R2(;@+$KSCltZYs#sos%Bpjk86^@NXYi6Vkj{~rcgCr zbMehbon|s^nD0=jp3S07%5<*2F8|N%G~I--f>%4b_jrQ7-g&(87#Mgt!6CDSpICC9 zhW}sQ4tLKNbjp#_-u?XX8-yunt*g&bNeUDbInkLJNUXldhkhkh{Tk_5lq2td>y0el zoFyIor^6x0_`&hY2{2CS%G!PGC8nx*&t8%7ifhL&Mk$*fO&rYfLVZmR=Ne!Cy&%^G zFT5>peoQn(LM+k`;YW3P{p4HkN={Bolq$0fUJtLRY~F=>QtCK{q*fz`MqF3cm;YZ} z@|J$XUzE0B*)OiydDm6qGO8trmd!_RqC0n8(q(F(_-`Hjbu*=sxlQ~*f~D=RT*MuG zTom#hLS?;@z&eAC@b|r;3**|0n+3Sxd!@RG1yQcYM?1DnQY&tyx;NQ;Du@2gr*8grQDdQd@IJe!8wc5B!LYk zS)YjE(9MtNy~ll5Of<#%OYGTwynQ9AWr*oOL%WD=J>k89(<8g^m?iw`=+L-4PuT*E zu9)^8j2~GNMOp?1XNoV_cXDs4tkUtxfw2S?rgP)yfATqGu>O8qe@{M{^48Tgqxf8H z5}c9F60D6v5e)4oE!rjobC$mJeAkwJKT)a&>=rN+U@@`fwJ?Re!Sdgb4wt^6qPi7E z1;$ST#z48G{g^k-Yg~gP`!||uK0eLu2@gba05{xIRpy;^8AxA#Fy_V**hmYhX-xn8 z2oo^qqTxRP71YCf|0N|1^DF=e$SLRiEiDh@zr6sa$|fnCpdi#{<$v167yI!!{1L3U z;kR`PW~k{{k>Eqj6m`u>Jq2N+o}*qSC!kpK?7KPI0*u^D?>5R;)2;TkDc&D1+fIl3 z!xJt|#3koC2IbV=638va{uc*V2F&>V8*rxLSp!Sk0kr9#Tbs>@0sKfcyeE7ifb{}2 zUKVGW|2*Mx zS$3JufaAPPrl&#bub0{;|7&TU>tVJQ7S0fksh!PZsnU4Y>RO9(F$bHdYTgP5keJO0 zKe7L|AQvTItR>>RHmY=MT!u*WhRV-}CQ0`mgsk(Vy2YCI7KB6r#mRant49bN_oIvL{Rd3TwKf~!B2x<7u zaRF3uykwhyr?d2pdR{?7v8e4~C@8hbDbQcynG48nWLkbjVf5gBI-j{BwA+keme3{e z(^d1W3*rGGcbnE{;70*=8+Nk5v%kZ(#dQ@%b*H3k>P{G-jdWKzE2Kq73p^u?7W=aE zEZNY3vLzsXb^?_Ftl#{v+?!s4JG=yD59%(FXLmJ`OKFZUu;Wb2+aVkJCIbtPR#^!( zqU3d;@vzsQ z^iSMwY>pDgO8ya5k;??AR(8iQ|7RH}f2)NaR2injj#$p#CzR!&a>r`Fm2X7hN+ z@|_rXkw8ys28C31Gl*N)$nBT-R((FF>JquXPq_)Iy0h33*r?`rh`UUiLk`x*_a*$8=3(=jA@qb6Bi|_yWo^0ULxlU*`TA&x-uH-T0 zMnSP?4&vG^%`kwGah8kQHAwO?*PripGiefx!{E}{w690 zPPdnczFR0#^H#%+ndYW^dF~ZbwHk3Rq1yJI*DLEXeVhs0viyVmulE)F@4hibm4PHN z{x?U7m)COa#>>z*t8+K1myO&OwLK;gxphmYXTP$fF6?RGT{xn`o?&6@((hP(vNX!B zamDAVKke6r)eCvMxc>M2>00%TqB`9TaEF+jiVsaAj_61NeMZ*Db5_Acw$rrNKMEcy zFdZMC@AXF(8+|wpW$3#L)&-_*O#)w+!*#uzR{f_aiYp_9whew4FdOFvt~=*FUw8}B zgKRo^U0hlrBxPcfTld9m;FGj?P0MSZWy2+=%ucph`c!wHzYsyd)YQ@6UuP*FqN@R| z$KZXwqigK#)_tdf5_AmVT#dEC57?ux_({?kHUV*V#^BkQ_35Cv;rvlvoHt6oP9e1} zyA%Dafa~^$AfdcAhBS$qV{2;@KnnA&qy9vb+i+2>mtG0HRbJ?BQ;G1zR&hF zGT4R^!b**_!<_1=>$bX||N0hGPJLI5DYgJd=U=eC z)S+Wv0RRCcTL|mH_H6(D+C*~sI8Vd*?=l577pLZfQ69aruQu^)?#2!|*pmB1!WVR6 z?x&xRl^Uwj@e2qud9?G&9$t7Ia5{?-Wo#Gc}=~PmMei5^$o2k+Kct!*x4}R=1vCB8Dw9ExFi5|VcVX<-fC!=ClKE( zTjPdd)cJRjY^c|yPAoRTI=3KQGH0P|3M|O5yHzJrGsV$`mA~KSUHl!rjN~}I+-kU} zhyN6^EfNdJ=1bY0i&RVI8uxFw81pxc*SI?cA~b=m(^%%WL-`8u48#W=j82%q>UUEV ztO7ImPa2`CoZ;Do1HzS{wEWYG^{2Mp3>0{_%XA(wL1321M~r`q*gQ`pP38X#@VsG8$0!D2hkhre#F%&?_Tim&WlZtIR?`-G((sQ-V{dRhow_yk*qb|Fx0l zO17+~^o5|K4>$=wL`%M<@;Uqx)6x9bdA`jMw5CuY>&6l=p7>nM9X6%#;h_@VU;qzq zW*nVY$B)Xx)r+p%JknyGyyw#|-zR4a((LV0rqrAD46pzjLg9m8c>f;z%fML9o!0G} zH>g5n%--|p*oG=`j@2ea0PwRk*QZo6?bgvnD@U82%?MXBi?dfKk4@bWw~sZCx@fG6 zAx}68r*(>){M z_BgDZMLvw$8|Jb_u?`DhAqtayM+qv%qo40^A5f44W)~&P6KM|f)+mdH6}-Z}s;bP0 zM74ji_~NVc@L5{NT^Uy&zHM1Pc*;SYN@9%1^C;Hzik&$ZT>r*MRiPdG8Pt85UVrmW z57tDrY(ncBC|gA;S=Evzfs!iWUsd7l;SgC}Zl!Yc$N!Q?E%|<`7+5v@vSZTj(_;wP zjwDQC2_M0DJN0hMJXq`VXL(@5+3*-co&42s87+NLHGf|`HYkXYQ|z7zK~zf3HoPh> z!g$RaT%i%*@rsyivrMy}DzqKFa$&|yj_j>q*;Q^-#ITq|!xRiO^A9IoHH$FgxC1a^ zt}XOAgf*<@&>-H9=Ivoh+?O?fH{nZPNZF?8nf?l=;*gBc;_pbIR*`{dPJm=9=?(ge z9hvAqOT?c6KwQHdEfE*0%>MQHt9tWLf&~+pAJ{D4l43C|dUCLr|pI z(`RRnwP5-Oi0mgc@{d0q10%1N?^)M<@vRrIB~*wmT0E#${RGC(58oK62C15^NnHXR zd=>HYr*RUpbdIo3!X*2ka^{?b`-e;gU`lhq_p|p_=xD|@PA^2)(D&fusPXbfP_`z1 zp+WUe9QJgeVPcmAXyWb9fbrw|=J&MGFpfXPf>U& zBKt-Hd9O_X>BdQe zpH&;simg0Jz8p^3ZdrxEtK)*fh-!b|q1@+$p}_bUiu69mQ3t?&u0U<8e=|h_!GAQe zx9ooxYUPWmFu+pB321{4ax+B*L;b$!!DFW_aLS~+pRSs~DP-Yp61U+g7`!IISOO;s zsrep(yfUj!Q;f`>e@s@$>g9@Wmwo*ntqnvjLmGD#@QBJ!0)n%*VKWg}utVVqQF_GC za~gncu>I0gA#<|##JX=$x8Ssue(r{E-El`p?-5+xE=Pn3V8I=z{Z>(pELu70dS#x@ zz=munQ=vvX)dY0vUN<~s4 z8langL>;WT01tevx!gZ(F{IHG2)=FtPxDIt+YJB6JV?j&z(*fx|tBa4^J0_J$t^v-0fGpK{Vm-gp?u!92)#!e9Gy4o0j!uF=7nE z1mi?wo5G?-k+$(`0!hT-ucQZ&7!%u@k8ZJ1D&F5wAh?-J`}3%hN5#qF3MDQ&o|8X?SwDzZxoJ$0BI=LWGe)%E!~CaLZA^Ck|!4(a_`) z=}~Dt{yYeO#D8<#>SzihZ-nySUVyhF0ZnrzB1f-$36O2`qCHRqiTNB0h;Nqo#>F|9`Hr+I76I)x7|#^uR_C&|<(W%D^t}#m=@-!!7o+A;OEZ*8@YYu$zIhPlgkT2&x?ci3?COH^nkELFM99gs@<(PB*9)>MreJ)Iyi-C|?-?kW zKRFV{=lohEU?+h#MTm1&l@T;_>dclHm!`A2F5%V3FeBNyV@gO^0C)Cp(^ z#-D%D?OEeRA2!3c1al0&vk*WXeyappWRkO`V%fX=17QVW0uz^r1a$6}Hsfx#ggMuM;UU(0%2XZmMTWqG`N z3DytFQUfHEOwf4o_GNK=`2I8W2FtW}61YUV<~@5)i6J!FpQ70;U??N7YcQv|#(c_qsp;KQg23{e zcc4c~9kQQ2 zijAiIj_lL4?icF05?(}Hdz$Yf|3H#A>9poF5l<HuUK!@o@E0}qZQR|Yt!H3lY^0Uf10TI0;bURqOP&uL5=PW9^*>DtObAp zwr&`!)P360+U0w-p7uj|6b>D3F}auX3lAC%0U%)2D7@D?*W?|x0U)L;gZ$nJQjWVp zkx*fir8f(Fz@PT_UyLM`2qO{jav5|CE-~@1>8$YeKAM{xD;ma92u&mYDbN}Q{{L9) zbQp(SuqyvJ;Zh6;mW>+S4Rx?yz*MeCO^}iMcsfTjSs-jl{?ql+{_2>TWkNtK6j=Z6 zH!SUEy3Z^$rf`T%hcv*q3VX&JPIk9}Wr_{+BWnOq_nw&vj`A}ki^1hiZ{^J~MF%72mwSMb0G$S5VWsom z-GR+U;>+>l?U@$Dz-c+n2_(sJEX|WH^jS5 z`i2Zc=Dr=KiNQ?bBk6Dw#Y0)J7QxX7r=7Ul6&X+VwX(toUpFFR)V`dOAn8=i$9dm`IAr%lPIC^OvG%@1`#MTCCOJ#Q_+0*vJkdq| zzpw5w^xn6803Z*=xbv@{?_2g*R=rv;i?4j#03YQXH(jXR30D6+D0-3Pkb(u`MRcCI zN8~^5jE1?dG8nutC4{S&|yi;Bx&LLC)nKsya4 z-2L~favkd~+`Aw+M(5$er2EmMi}~%=xPVWL&p?)-1z8sB^X3=Y zYJ_l@$fD}W{pk__eUCo8J;`GN&Pj=Ju2?67Z8+BxAmh`3F?g%T&vBxp_C&aoRo(ky zE{eMm>h(bhfpv=AK-8$%5uBtJ+Ur?S&EVV~{}mEN7L&spNKDA4Tb8v!|Di8_?}2M3 z1RwJIP5d%-pktLu^FS-Dt%B^M{=f4M^bF}gHgeZ>QQPu$Ub3qyO;E7{cE zLGzQ!#mUzK>(dt#xpATj{#21>(=ERads2BECqH9B7{GiygC^t_q%S1Qh&V%_g^+FK zANm$=Plco7$8jE;5B51nZ*UpfY|a!r=%)~e;AUgK@wf*=-GG*IPdcayxjH(yI*2)) zd0{y^?KNto&umS0%&MMY*R>jCGzCf~0}by1oX$nwNiVRg963yhRPogyr~;mVslMSw zO|YH#3iRPlYTtdPU<~n3UDO4jkpzNpr&DIQzs=F#wjGRt?*NsNl2aKkzqBaiG|?@m z9AnqmjZT<#(mc&~-6?M`sJNQ)@UL6>1$cbyMtiVKC#k!fQo>S|i#>6YOXS(}rJpvx)Yy+MB}^&kaO^eP z!B~a~Br(9gV3nHYGuNi9+3th$e2Ic-FUi26v3B{E1QPex#gV2DAAzp9y>bi_Fw(a! z-OibTc{W2l<4_Z%)_>xsmM;7>o?ED{}>xzyiA`K?ysCK!Mq;n+d|E6ci}| zMKIgVeZMK(a-TUFmFTretpAvqe3Mg_8S_4>C%kT8QP;4aSk$5CDTSt$r_B%G`DHFV za6%B626Llg`6MzKn+_-J2YWMaufbFzXUXMGUl1JrXnM3L?ofLUxl|mq+&B~Z^|K;8 z7!H#+hFxeys$1SjG&~vl-2Jog2SSR6LxT+{am(4Rv1l5Tp7Swbc)pdEQ7<7d1VfuT z-Lt#s0lS#y?w2IjM~m-UQ6*zpMooUBZWlhNy)RGXG#?|(Yv~tCjKS-&z@{+)Jl1E6 zDk+@^51zpjj#n2ViM~~)cS5eO(NhWg z`PB3k?Xbm7qQ}|6SX}pG#8{u9tNJJ$XU-#ThK|k5(gvvu=^bEeth;EW!LClw5kqC2 zU$!`|yWGzuL`6!`ZPh1m)o@y*H42fFjxT<7oOJ(ovKX$HF(|)W=uT?i zL$mBny8&T0Kb270p}hcsY~Xua{_cs)U+VqIQrNi`YOq2ft|&wq#PABXzYB?g!}gbtB8i9hfZj{pqfjlKsu4e#kpu-<~{UY}6inFFnM=~v(`qU7MvE{rXQUHKdg z!@$gWx7E1Ejo$(QJ>13&N@_}HziG?mS0~iKO-Hm)mXd{l$!fVWpY}Mmr4KQo z;&{2%GoOu2*mNFGWITDp#OH%alV5IwNq_f~Rnr<&@-UZsVll*Dwrf!kn#ze&Xt6+e zaU?N$Hgnm?tk!kBfp~0WW+7(Q31)uO%$tf>N?!wMU#zHWLv)~abMG8jDjo+t>Us}H z`z+o(ed5*>j)d&4_^4|O0SsF7Cd3t?T%os6E<-^N!nb}F80oB&!6Jr2j%v-}koJ06 zHb9%aP|=E@(BxGw@BJv8w{x~XlHa9;W2zww5IU3*t^UnFzw-`<77_&!QGi%-Z77u7 zWMETd)V4=?gmwH&_bVB)KLxl1S}Dr<>B~4YOg$4n>mvj$2{~@G__6pjo1`wBnI?EJ zKn6xVeCdtg&8+W5Zfi;UAD`S&ZuoMbAyw-JApjY-4K{ArzD7Hm zbRDo7E*dU3p<@ZyLB{vF%tl6iSjKkhh7B|0LKtrxk5GA%yeuW1&+a>p1&`nZ zXoxQUMEqfg2uQzXyCb`xjWUMvum;Aicp{~xcrG7RKI^9Aykyh3!tpULejzubXPwi| zm#OK(*9N@~VF#a|;EoPYL88FwBf4GpWSrl)QVvh_9dLRjL?`WvOFi4Id$YRDqJK;^ z98HbB@eR|~jFD<|;TBt-boEM~&O9-O-uY9Q4!+*J9jzJ@E=bz-J4j1$9{ ze!>&X01Okq9Y|d%0I-5C=vq6rCs3Jb`sJ?N$l^^Q?2yh)bVqkKM@z>yt^Qd+shp*S zwex2!Q*oC|QzAl}ahicRR0PQc3CqX$^53B+1j1|EY}cSNVjK~hM-$yW#-5cb+$SP# zy_iq7JqpZkb`B<_ZX^kHUW+rtf49$^S0Pjvayk*ctCYPMaWkR!?v7O&UkmavKfquh z*7bi@Uq6gc-0Vu|G{HPl&Pz=r-=r&0tHT$(_E&q&kw&@q_*WS(UxYsypToZwQj2)`A`xTpK`~7UMK>wo(Q{-qoQ)=!*;4Q#D zolc|#o)Kv{LHaMe*IEz)c}EyfBd-0Tb%wPr;Vm$X5AF2cPF0>piyMi1K99$K3{-Po zPW=W3vE-)>FZe^F6m@AUf$9@5x#Fh>^M<;$Dwf%dj2cL53oA8O$Qb)|^Zmd5E_A-# zfZ^um3w);sp64GFKTX@M#nOm7cl=DI5p8h#DVnEFl|WsMjz?bcLqq(d{qM^x*Z#%+ zM%@7e5nUT0Ubw+NDa1VeIOQ%L%vrV~dn*$GjM@G&aJ60q1GK(}6jwZ75xJaJr8SZj>9hn-^TqpjCZ8y8>nCm@B3;+h2>d^OrLR{FuiD5blbYWfdUv2ZoI!mx z&3WHL-amED_!=;^q948|A1&V3rTUaDBIU4XdqUv95o-R~AO5E$=vP&zeEV@)Y^NUU zzeQSD_qIvZxjd+x%T|H&LG+r=X>p8!CN0KW%spbhNDcGIdKHB^Zv`ZaGwuyeyB)6I~-W%Y#1#0*K1j+t6bpYFgR~SELq~+-U&1xNsD}piJDO<@o`jh0fDg0TyaVBR7t6r=bs9k8Ml+xTps?Nd8D6KA zH@L7V##~%?Xu5Exz68SB@7FDFGM|2=7*M*%6;DO=`6beEn5qyB(eCDWrVqsf?jS#+ z;zbuSxn6sE8pG(75UGKcGmZ#P5urzqZQh3Nk~vVcf^y@i%u(1Ph{q)O+nQO4cdJj) zin|KA&h;c-^A3Gy05cv)HUyjmkHQo4n+K_~+tN8!8E683Uqb{g2MXv6$sHWj-Q8s* zeMKZhhe+PWXlo`UhnLCX_|Pgi?K{hDHIMSlA6I(J2OS zfgX{OE%`iA+?z>N$P_k#mS}k;Gxvl-2?Kp+qAV=(}K6HQ-aUPLY0WASf(8;?8QD<*KYhrCnXt zMyQA58PKV#xoa29>A=rWS46^7zw*}iXet$VFutqh0P@5h3s<1<;&~dn!uq~C=SQ#8 z<^t}XAJ#c)ieKy(Y8Onp?DZk?i+aI+C$e2q*DrQ7EnXoTa{ZArk@!)TtH|P?aeB(x z!$w~?Z(Cm<44-`_Y}y=<^egLY*=EIjEQt3(qMvp%)Wg>gL9DEydc&*UoD`6Xwa`2x9#0)=OW=DJQr=2$_AkP zOLjmUxGefZht=;Z*3D=g!HIkv@UF#m=M%F{P326 z`_{-)7#jwX&JQpgH3q?LVK9A91j1DyAh&@*6UTP)m~9_D4e3NJLomVqMyM1BeYg2p z04Lh0UWiW84dm^=BjIW#G?D<^8Dfx z+0I`24L(1O_;Q2MII17(PnY5L)_j$5o;Vl(MBSE?BjmD zH0IJX?Atw$= zfl=IGCUb?>Zqd+}^!)tq%vLHiq`1m+oCWI7_rTV)c<$OxsypdBFeO>ml>OWz*?A@c ziY%Qch`hopm{YIYy2SY6!E<`s+d0Hp0v{KmEm-k%B?e}3oE(1bd7`+&JU5~T7L1NN zm;c3io)!86()f9YlT|C^re{u{^lM!#U$zx4ZLIzVIKin0k^0DUw# zbbYK&z$zIKZQz2*PU9N}dr_HDdAg9>A01s|J(y>;021RF#8-GupKQ2KcrAnM>Jll# zY6uKpiMG1a414moXzRmr_)=}-kDD$cFL%secE(&n=?xAvNslqVv*m1>i@6s&smAWB zP(xGE_@OE4eN4TLWQV&S#j*vlc>t&Y+|&kj&UUBW9{`4mkX(j%?Ma2`l14Nqm1!>b zogv~GzU+i@mVKt)tr=zg2ne34lN?0CwD*UJk57Ao6=PpXGy(*Tf^s%}wl!1m>EWKH zw6uiHcjFp+z#yz83qAEd*fc88m{R3t*LQ7KNh#Zyel=gc@4h}=dRASitq?~!-01t9 zMsGvU#rhR*(5yP+bOdw={AkvKTW@BfQ>TYQ6I$2-;yvs@+spC0Jb{?=Q7()oR`pCn zui;_hQj;yMCO^sP`I(md>t3GX3lW`O4?9j^n0Rf{=>j)Xr`WyomB-yf9jvAO(w))H zrOc=3k1Jf-Rg#jNz8C!DZgXxK_>{zLYFvA{W+ znax`50*$(jFKfARcuTcp9<34rv)mPcAVDC_;E-qgoVGL2eM9`2NRyGc1NVT~+Bzum zrIy9So@v@owykFx&ZT_4rFXkP!^FQ#x_=dmqRe z{qGZ)yqMePQ(?~j>`fT$B-juDb@RMA5QE0wCkjz=u?N8R){7KOv}Y41V)K-Yb5Ex8M#ROw%Y1SZl+`H;!Cym zz{M%wBgrgW5hJJ6Cl;W(|9)~nWg=jiXyiV%n38IOu&DM!v^uedM1mZq@Na4nme)Mi zqqxH7dnP!Kbr5_xxLKsvN(2;Rs6Rk^UMW93x|3aEGgH)+wRd}#Nrb~y4di$G+WVWw zP}M#M9Ki)R7$k0ZAC3=7_|DPy#azM%_L%l6fbF7TWh?Dqt+PR75e1aq7hS)-*KXkr zI5r)S4eXQqA+qB>*kGgPUJ{~|jOZ6nHY1~IKyDl!IdtrnTc$v2g^cJyP*9pNoJ?h! zzm0dm-O_(@{J2Yz?)f@M`5>9ZiRS6XmdQiQKyNV=HY#G&}Q>Ekhh0Wc>E3&~yn)YfF^5C3z!=xBlD z>;}NIi=tUDLCdOzBFTJ}N3}E7D-bt~5ZV%saguh~zsnl@kg+m_z)uF;6j#5cq$1E$ zF=(G58d>R!Q-RoGz7ppY|JDLLq!zx*0Uqqf<5(%HW%xZn+xb;33T++-fYK0z@K?{5 z=v9T{cqJxLy~8W6-`bv4q}xIIWFVYf=62HzxxQqbH)E*tw=2@T0M)w&eHEFBBE$V^ zfv)~A9$o_DV)xlo|1$oK6qWL>mqFY1x;j}>4kJq`oB+2@RnStKc(337S)ZG(t?#8^ zPW{Kvn-oQJ-&|&fwfMxTgeYE&E)8+k_hh_Qd!9GMS(!(F&hdb>ATG1UYcbMUYA#QU zBuS{~Az#_c9t`IymcEo_|w)QfS1uK40+;`m6#I(y$T`jV`Od$GAvpxpvu z+j$375^!^45hkv)+8WN1zPi;OKa-Eu$Md7V{fwaG;kQrG15_dnx`o~lE?(vY8UL-gu80>Wz^+(7#on&xtB`zoD}r2KOF(I&SFn$ zIWYJpjgMBReqpY2xZp9v0U3hf&dTZz^;M#KnQsC#tm(=K+5-ypEdYipHCRqiq+N1W zhm*$GAr!JN-5O7p1o7Msr-U@$dOq5p3C4Gt20051ythR_8D{=b7Ez z96Rt)RZy1L7paFD6(yP+? z+*pY}ZN!??!tT9r)s_~_2rp~gec=1h^xyn6!|`*l=4bt{@*_;v@)L^oPbP{*=DiJ$C?X zN*~W$w8Tk#RX+FtnmO!cv=rxh%um@NBkIO^^(gb>sjda?X!ulk+Q z?r*&d&uOuPWNneJeLjw?Y2X9_>z5P6FsquJ?rez$q+Gg@iIM%sO!!-m*Ue<^&A$Tw z3>U}I3A?Ah@(>c3{O*eH4V_50ut1)(uvTHXm9d>;|{Cm&7~Glial{MaX2d{3vwPKQwh zCXyg4av1U?BLoEG=n(8pY#xa?PHmveH5`mc=}X9Ai2N)win6Z-hnahvCXR6sY*{E- zA=Dp2v&OuZ(g_g;(tTFkYnj|?RmvS zSCT-DA%yL1F)zZ-n=O1q-2chP%H{3S_x7c+kgRdf7hR+Dj*{EsT}jHuCc{JsHjy#5 zZwd`m-6jy^ktIrZ0H$vC=7-Rq!F}NT2OXMc;C4N#ZbB!{@nP6QR;7W;zR(d|%Wp`%O{AT=>kB+D+8XsW2~7gSq`zrBOC{=(2HnQ@P371M{)ZU2OT zwc=%C5Wqk>*;@}p-Vsqr>MRJE2K1pVJqVQ9$zXci7u3MK>CwmgcU6X2hvCnqFYn?$ z!Z}K4d*6+T$D(NzPUvd+?R!HnWU`peHwxX48$-@x3w#xi{qa$BgdsnEc`xr%S;ZOM z!rTEx{v~U!+f;hkwoM~!tDNyvPFcUeqD$=un9YS%Vmt*aBKC;-^}_Y#S8IMHHWGW#T7L(so_7MBJ-hKMEA_G$z@Ugo$U~mIB$!Ka-mhJBr})X z{Fg=&FCxPwB4OT~43L^I3rqwr?Vf6QLl(l8d zGkHn=lNv%N3@;}#Xhy^)`xwUJ@P!j6Q)}82ti&Y(bH4!XFKz^;5`l6;h?-ALi}<&a z%>9hlOmO{q&PlE)Cy zCT&aeE*9Z;vR*HE>IcjCC&PCl0*Mj~e{^KGwa2D$@PoAEO*1PjoJA$acSdVtf7rF@{=nc17BT{g|!z4E9b^| zwRfFRT|KkdH*LO+q6c~8_j?LhFtsKqRRa3PygWVXI3xzzb1bRa+^R2P(wH?&hUyz= z>ry@Ccig#InXPnF*10s>E%GEYA3Ba&rKbMta#9eNb5f1Qpkg40RY4(+zvZACvJCNI zPl7+kerzI4YFky!_%!#rtHr{!l4|Q8e>Nu8cN16GG~26-@28k6 z-O71Mf7jNY4H+JVvr`)!Nnn!bRvJ`G3fHm#ip|~T9}3M}pxU*tcEeBB1+1G)_BWFs zEh!Lcl;{oY71}ZEJc9R~)c1e^fiS_DYPS5tAZKT`S!eG>W)Vt{XF`w72AHt&``g-3 zmbWJB%W5~H$cixvR2+mdfADf42N!rgaA*io4$_bm4Tt1P?|pdpT=deA>vhe)A1&|} zbKta2Zq5lIS!X8)i!CA=I0P+5GDP%s8!NF(Tl1g*kW;W~tgcg-o2K1YwYmOCMoG~E z{o`~zbglr8PW>GUeqPzvw8S&vs^0HOIbJ^F>CB0`R_zY=lnR5!%yt^83c`#{bX*l5 zBzY}Zl>WoX3+lZ1*B=UaF_J;^iX|8EhWn2B&4?O<91f1Q9hN#WHs)%0Z}SLMV%t); z8Bzpl28#c61$kIQA=tV25MGT~|6Zt=+Ate+c02RWLy6DEBR=!&j zE#1tc7EB?YP#gH$IQK=y3zEJ@tlOT9%1-*K@P(PIeF29C#pvMjBK>q69Iln0q<7vcGKK!)d$){3s%B%o37@&4dJm; zrJ4K3NS)UeD!lmaW~y~9ZecqSoU^BW=E$d3DqK-x!6DWc*Kz*#IaZ1XW5@5=geCPi zhWq&nmk$(-vm^a#&7$L!)9#mbRon$Q)*lD5$3#1Ka{>jot%tP+yVMws2jc@Hya{Q1 z^@Ue=kYh=sP4~>h;g0F~ePf0mek^AlHPQI{gXt>dtkv#CbIHy$zQ%ZS7c130BFS>^ z)MCyHqw6I|FI-y5>5_Q!3=_;E80W7KPjPiH&qYX~+Rh9V<-Scwzgz#70hRcGQS7wZ zVQ3zenv=X`shvQ+%pHkXC;Xq#vg_j8(v_$oJzW3ARrotRmFz)(iqvs}bF3QpY{p)e z{1xQ|`F(>7%F=r@ZnNJu*kWil#wT45bb6<5_1{^G%RD$qG>-et*Q7SF*5`PX=pOal zt?d_IU5d@odD<(3ZXMf@-BBIRPq~8b)z+>9!@7JPpF}W9r5#3=RlOzsI?wrS%Y~b! zR3~n24ih?du0MP`wfETFLG&R@vV92AN>R!$ElTl;s@mm0#c6d0S-~T8!fSgh4YW;< z{nD#PGk*xO3IFuiopW&WgiriaV)4-R#q#2Z4vMzxHUmr9#pULk4$gS`{*xsG znFn|2n$Lq!wEso<`Jcc){+)OvWp9C;IgbY~o9lO-Bb_HJ)icj(UM9rO;4hHFMSVO` zRP9}QkIzZD(Bjg&?R~EK>o6$Hz10=PjLHTTtPA?g3GFuiB=86(qT+3~Qp3ZC z=<_?Mb5`w{w{6lMzoXe!r^h|lRmNTj8TJ^Z2a)&j@a?jsA<#841>_y`XYtxzw>q~iO*yr?qqZR z>&#WT+KE#&?@CpQg`=21+{h`PG>Idhpg=oJr2Rmxw2SxSt9vZ-)0T{Q`-Hn>xffc9 zeeX##QYN3M1aIqSG~Dn^Qpb_kX0ZwG&BBP=w%vk6$x5++xz1kMAmyPWnX);Llu2z9 zEnl?&<~oa{xoG?XO}_j-GFPWx$JAk#f1M~ujsf|B^{7wl;=y) zeY3|fYlFMH_BV@{PPYRK-unW{VIKpBSvuHKFpx5{(*3A1(yo?B)Ovj5fsSn`Zk z%NbH*yU((sT#rAV7$xeGZf5c1HGLIXUVoTvq%%o5f+n>=3VAnI(+8=SlrF1j^#ipc zVNKWlQWtbW#Ftf9%Xy(sn_{g?`YH5wpyuB6WLR`{p|H=JR z&S=+uhsALnQTwh-q$Tonh8_-sb2IWJ-fO-0u+%=(b48F7n*~s0pb;Sen$MyQtd)5J zM(8WBRZ0c!#YGdz5TO8dVUBQ23X+-Bx(F3dnUj@r=qn1Mo76c{@lkLE6q02XEd8#r zOpv&41UFgb2eh^-Y0hb$FjM|LCgpzWzyAl$Q)4)JBNXoy6|m^BkiUue?_fTm`+M9A zXYwUdd8bJ*rrq(IHKhk5FqDExg&~)}DTwH4WbI*#iGX(Vtl2vtMEDTlGSjoGe@BoZ z8gTT3o4MI)`eh{fRgjc1?{%C+DVm=BJ=!T!uO{7N^bKmx=D!pwG?c;=>?PN_PLXm# znrx%pTZ4a@k&c3g&m~|bM4>3PxO?L^Nrk(UH1}&<+pwmX%160%OL>SLIX5PIPeVR(@oMr8 zlJI@!z@}KDkNRq;vV!U2-1YWltSnhgZSs5e!8E{p?GsyFd#-{r$lBd!&E)0YHN{ZZ zSfsMj-;UDFm}@tPWI#V{wLaN<|Jr)tcKtq{>8w2m+kaBb{@IvRtT3*Z{mmEnU61NN z0L7VNdy^OH$jo6@(VbPE_d5Y!I^X87a&}B{rI(v-^~vp91B)uIg?(F6HaVnwYle{yEYpABwf7G$p5vLaG#-VZ z|JPRf4>#_=?@3@OvSzt*GN-n#$krFT|27x7mB2>2@H!zAv25Frk|rWB z>eS9gG5>G$)1AtWY2XX0jY@k6dv`vm{SG9~+m$*zs&o1DE<3@7?36Tdf&iNv3rbuK#lx@|IUa#1oOYJ-u zuHl@harUD-LyKnUDA~5rl|&I z_p!scp83C*Iq^SS=7PQ~zNwP$f_>>}!|`X)TM!JWvIUbDXDn(dZ1CBuLmV|at4CF_ zwo5@%89&jsq2fodde2kB+C*|b>#s(Dax?1fBZ=eG1_jn`1TorfM_3zsATnNhI{|UL z{2T4JYX_yK0ZgF@)9{rl%KX=F^>|_}5A7Zm%HLJb1pe1oRT|{8UTt*yGd=yuabnFf zfxbfY+xj_swE=8L|9h{P;qnazud8|0^B-~*-4aVIcC?NCUG|@PUb)$&efTD#G&Yux)U9AF%o164v_JC}{94gJ+BUpgQZ~qzP3_fa9qd&YFBatl zE6-U)g3rCJX34xZKH^8Ag)(4J6jL`)ETu8;Tk6Qh-kSS1-#dRSk|QFO64%xy@=1mk zBlvUTXGvW%!<4>G(J{)TuwNO8O8zGVFjVyp61(4A5j6q#J2bQ>LrivrT@lP>`?+Cv!bgGADDHEUKu^lTRS~!uRdFCspZ-CLFdBN`p0I$)wg`Nilc8HRo0{DhNESVPK$5VPH~DZ-ybXXA3`qKm$to5bL9&> z)3^WmNxJarp|>4I?eadRLp|f(G0g9bz3YbgH-f5b|4>i6KBLORP0`;o$7X9M;4T|K zV&ctMgN_qOF@YsfL9rMw<3+|de0xrlM`qU}a5G@@t_)E`^(YH50GrvqscS_?3}u>i zv<-^OHBDkN)``QYI9^WC2v6s&Nn~eQv(rkB_;2GsLm!yo$tDlclLpGFgX<2{9Y6_BE6KuFBXiN@_dml+9Z$P@(5`sMC5ve`b7}lb@u>gC5@C$ zsY$HCXVf`~uW(<{r&JZ<7Jj9E!IpQ2%jW%xz+8m0Ht@X|l-y#-m&WigsHmP+Yc&i@ zyH7eRqCp4a*Pmw%0ITqUF=I#%j?xQI{(h$P+{h)q;4Qg)Eqf&2;El|}uD_q8?f>N` ziRH!SReonSv6dJiL24F>XL_#5TN0|*+4Vb>$F*H%S>(ex4KaK{0|fW!d2WB_bAh8M z(kUg{;gDG2^`E(Df#w$B*IZD^4{k>*r=fsB^bQXHw`e3j-qz@dk=110=!N;oXeo_& zaZT*_I?V;Q*(U^Jvfd_K{{K>;8LsW#N2OsJ)f)ns+8tA#(xf68Nfm^F;}N}ZfR;&X z+6#8mPzvHU`rKaNn+x=&+5EE&_Q5t-y9eyiv%AJO`XRQ}pA^-gEn;yiO-b#UXJ|Z% zS7Bf*5H9Niz)ypix1_pdP~E(cVPE!9c^8mN$c=zpX44b5n(Vvo?v+3Zv1;UF%}%A6A`)GIO2u=A1Di(#9l@sRA?XLr*HK9o@HSb zlaNyitp6#~+2!_fA7urO{;F&5IPS#}DH%RPdWz?`fnvS#s=TUCUl1)TG6!)mvV*!Rn8|*{N<$B-Ney zwvKL%vL1c2{3!T*T>N#TIf-j+&;)MB&>ev<>l{Qfln@wLNTn6o^|)~@_8@Q2^yyg0^9&~h<})M7YU-S(PHb%-+x