diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml index c920626..a0f9ec0 100644 --- a/.github/workflows/deploy-pages.yml +++ b/.github/workflows/deploy-pages.yml @@ -3,7 +3,21 @@ name: deploy-pages on: push: branches: [main] - paths: ["pages/**", ".github/workflows/deploy-pages.yml"] + paths: + - "agents/**" + - "cloudflare/**" + - "core/**" + - "docs/**" + - "scripts/**" + - "tools/**" + - "pages/**" + - "tests/**" + - "README*.md" + - "CHANGELOG.md" + - "VERSION" + - "install.*" + - "安装指南.md" + - ".github/workflows/deploy-pages.yml" workflow_dispatch: permissions: @@ -16,8 +30,28 @@ concurrency: cancel-in-progress: true jobs: + quality: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Run tests + run: python3 -m unittest discover -s tests -v + - name: Compile Python sources + run: python3 -m py_compile core/*.py scripts/tools/*.py scripts/build-online.py + - name: Build online packages + run: python3 scripts/build-online.py + - name: Verify package payload + shell: bash + run: | + tag="v$(cat VERSION)" + (cd pages && sha256sum -c "agentboot-online-${tag}.tar.gz.sha256" "agentboot-online-${tag}.zip.sha256") + tar -tzf "pages/agentboot-online-${tag}.tar.gz" | grep -F 'AgentBoot/core/menu.py' + python3 -m zipfile -l "pages/agentboot-online-${tag}.zip" | grep -F 'AgentBoot/core/menu.py' + deploy: - runs-on: [self-hosted, windows] + needs: quality + runs-on: ubuntu-latest environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} @@ -26,6 +60,11 @@ jobs: uses: actions/checkout@v4 - name: Configure Pages uses: actions/configure-pages@v5 + - name: Build online packages + run: | + cp install.sh pages/install.sh + cp scripts/install.ps1 pages/install.ps1 + python3 scripts/build-online.py - name: Upload site artifact uses: actions/upload-pages-artifact@v3 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..27be60f --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,146 @@ +name: release + +on: + push: + tags: ["v*"] + pull_request: + branches: [main] + workflow_dispatch: + +permissions: + contents: write + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Validate tag and version + shell: bash + run: | + if [ "$GITHUB_REF_TYPE" = "tag" ]; then test "$GITHUB_REF_NAME" = "v$(cat VERSION)"; fi + python3 -m unittest discover -s tests -v + python3 -m py_compile core/*.py scripts/*.py scripts/tools/*.py tests/*.py + sh -n install.sh scripts/*.sh pages/install.sh cloudflare/deploy.sh + node --check cloudflare/worker.js + + online: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Build online packages + run: | + cp install.sh pages/install.sh + cp scripts/install.ps1 pages/install.ps1 + python3 scripts/build-online.py + cp install.sh scripts/install.ps1 VERSION pages/ + - uses: actions/upload-artifact@v4 + with: + name: online + path: | + pages/agentboot-online-* + pages/install.sh + pages/install.ps1 + pages/VERSION + + offline-linux: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Build verified Codex offline package + run: AGENTS=codex PLATFORMS=linux-x64 TAG="v$(cat VERSION)" sh scripts/build-offline.sh + - name: Smoke install, execute, and uninstall + shell: bash + run: | + root="$(mktemp -d)" + mkdir -p "$root/extract" "$root/home" + tag="v$(cat VERSION)" + tar -xzf "dist/AgentBoot-offline-${tag}-linux-x64.tar.gz" -C "$root/extract" + app="$root/extract/AgentBoot" + HOME="$root/home" sh "$app/install-offline.sh" codex + AGENTBOOT_HOME="$root/home/.agentboot" HOME="$root/home" "$root/home/.agentboot/bin/codex" --version + AGENTBOOT_HOME="$root/home/.agentboot" HOME="$root/home" python3 "$root/home/.agentboot/app/core/menu.py" uninstall codex + test ! -e "$root/home/.agentboot/agents/codex" + mv "dist/AgentBoot-offline-${tag}-linux-x64.tar.gz" "dist/AgentBoot-offline-${tag}-linux-x64-codex.tar.gz" + mv "dist/AgentBoot-offline-${tag}-linux-x64-sfx.sh" "dist/AgentBoot-offline-${tag}-linux-x64-codex-sfx.sh" + - uses: actions/upload-artifact@v4 + with: + name: offline-linux + path: dist/AgentBoot-offline-*-linux-x64-codex* + + offline-windows: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + - name: Build verified Codex offline package + shell: powershell + run: .\scripts\build-offline.ps1 -Tag ('v' + (Get-Content VERSION -Raw).Trim()) -Platforms win-x64 -Agents codex + - name: Smoke install, execute, and uninstall + shell: powershell + run: | + $root = Join-Path $env:RUNNER_TEMP 'agentboot-smoke' + $extract = Join-Path $root 'extract' + $smokeHome = Join-Path $root 'home' + New-Item -ItemType Directory -Path $extract, $smokeHome -Force | Out-Null + $tag = 'v' + (Get-Content VERSION -Raw).Trim() + tar -xf "dist\AgentBoot-offline-$tag-win-x64.zip" -C $extract + $app = Join-Path $extract 'AgentBoot' + $env:AGENTBOOT_HOME = Join-Path $smokeHome '.agentboot' + $env:USERPROFILE = $smokeHome + $env:LOCALAPPDATA = Join-Path $smokeHome 'LocalAppData' + & "$app\install-offline.ps1" -Agents codex + & "$smokeHome\.agentboot\bin\codex.cmd" --version + python "$env:LOCALAPPDATA\AgentBoot\app\core\menu.py" uninstall codex + if (Test-Path "$smokeHome\.agentboot\agents\codex") { throw 'Codex payload not removed' } + Move-Item "dist\AgentBoot-offline-$tag-win-x64.zip" "dist\AgentBoot-offline-$tag-win-x64-codex.zip" + - uses: actions/upload-artifact@v4 + with: + name: offline-windows + path: dist/AgentBoot-offline-*-win-x64-codex.zip + + publish: + needs: [validate, online, offline-linux, offline-windows] + if: github.ref_type == 'tag' + runs-on: ubuntu-latest + steps: + - uses: actions/download-artifact@v4 + with: + path: release + merge-multiple: true + - name: Generate checksums + run: (cd release && find . -maxdepth 1 -type f ! -name SHA256SUMS.txt -print0 | sort -z | xargs -0 sha256sum > SHA256SUMS.txt) + - name: Publish GitHub Release + env: + GH_TOKEN: ${{ github.token }} + run: | + gh release create "$GITHUB_REF_NAME" release/* \ + --repo "$GITHUB_REPOSITORY" \ + --title "AgentBoot $GITHUB_REF_NAME" \ + --prerelease \ + --generate-notes \ + --verify-tag + - name: Wait for Pages deployment + env: + GH_TOKEN: ${{ github.token }} + run: | + for attempt in $(seq 1 30); do + row=$(gh run list --repo "$GITHUB_REPOSITORY" --workflow deploy-pages --branch main --limit 10 \ + --json headSha,conclusion,status -q ".[] | select(.headSha == \"$GITHUB_SHA\") | [.status,.conclusion] | @tsv" | head -n 1) + status=$(printf '%s' "$row" | cut -f1) + conclusion=$(printf '%s' "$row" | cut -f2) + [ "$status" = completed ] && [ "$conclusion" = success ] && exit 0 + [ "$status" = completed ] && [ "$conclusion" = failure ] && exit 1 + sleep 10 + done + exit 1 + - name: Wait for primary and mirror endpoints + run: | + for attempt in $(seq 1 60); do + python3 scripts/verify-live-release.py && exit 0 + sleep 10 + done + exit 1 + - name: Promote verified release + env: + GH_TOKEN: ${{ github.token }} + run: gh release edit "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" --prerelease=false --latest diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ee02f4..913432d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # 更新日志 +## v1.1.0 (2026-08-30) + +- 新增 Agent 安全卸载:菜单 `[9]`、`agentboot uninstall `、批量卸载与 CoCo `--purge`。 +- 新增原子安装归属清单,区分 AgentBoot 管理安装与系统同名命令;兼容可证明归属的 v1 遗留安装。 +- 在线、离线、CoCo 与自定义 Agent 安装成功后统一记录来源、包名、命令与安装前缀。 +- 新增固定卸载验收、安装追踪集成测试、Python 编译门禁和确定性在线包构建。 +- Pages 工作流在核心代码变化时自动测试并重建在线 tar/zip,避免源码与实际下载包脱节。 +- `ab` 命令链按每个子命令判定风险,`safe` 真正只读,非交互 `smart` 不再静默放行写操作。 +- Node 便携运行时升级到 22.23.2,按 Agent 精确校验最低版本;修复 Windows/ARM/macOS 离线平台映射。 +- 在线包新增 SHA-256 旁车校验和原子升级回滚;构建器以临时文件原子发布且结果可复现。 +- 自定义脚本仅允许 HTTPS,下载到临时文件后以固定参数执行,消除 URL shell 注入;脚本上限 4 MiB。 +- 修正 `ab bench` 首字延迟计时、全部 60 个 Linux 知识库段落索引、`ab` 子命令包装器和 CoCo 数据备份恢复。 +- 离线包新增目标机逐文件 SHA-256 校验,`--all` 仅安装包内 MANIFEST 实际列出的 Agent;构建缺载荷会硬失败。 +- 修复 Windows CMD shim 百分号格式、npm 真实入口解析和便携 Node 路径,Linux/Windows 均通过原生安装→启动→卸载矩阵。 +- Worker 支持 Range/If-Range 与真实资产健康探测;发布采用 prerelease→Pages/Worker live verify→Latest 的协调状态机。 +- 修正 Node engine 范围、离线资产名、相对链接、vLLM 文案、移动端表格溢出、触摸目标和旧性能固定数字。 + ## v1.0.0 (2026-08-29) 首发版本。 diff --git a/README.en.md b/README.en.md index 2ead555..ee50399 100644 --- a/README.en.md +++ b/README.en.md @@ -7,15 +7,15 @@ [![Platform](https://img.shields.io/badge/Platform-Linux%20%7C%20macOS%20%7C%20Windows-blue)](#one-command-install) [![Agents](https://img.shields.io/badge/Agents-14_indigo)](#supported-agents) [![Model](https://img.shields.io/badge/Default_model-Agnes_free-orange)](#models) -[![License](https://img.shields.io/badge/License-MIT-green)](../LICENSE) +[![License](https://img.shields.io/badge/License-MIT-green)](LICENSE) One command to install, mainstream agents to **choose from a menu** (not a bundle); -a **built-in fallback agent** that always works; **full offline** and **slim custom** packages; +a **built-in fallback agent** that always works; **verified slim offline** and **custom-built** packages; China-network adaptive out of the box. CLI UI in Chinese by default, English switchable. **Primary entry**: [boot.ide.pub](https://boot.ide.pub) · **Mirror**: [GitHub Pages](https://bit-cook.github.io/AgentBoot/) -**语言 / Language**: [中文 README](../README.md) | **English (this file)** +**语言 / Language**: [中文 README](README.md) | **English (this file)** @@ -39,7 +39,7 @@ Two commands after install: | Command | Purpose | |---|---| -| `agentboot` | Console menu (agents / models / mirrors / custom offline builds) — Chinese UI, English switchable via `agentboot lang en` | +| `agentboot` | Console menu (install/uninstall agents, models, mirrors, offline builds) — Chinese UI, English switchable via `agentboot lang en` | | `ab` | Built-in fallback agent — **free Agnes model, zero config** | > The one-liner installs AgentBoot itself only — which third-party agents to install is always your choice in the menu. @@ -49,12 +49,14 @@ Two commands after install: | | | |---|---| | 📦 **Choose what to install** | 14 mainstream agents, multi-select in the menu | -| 🛟 **Built-in fallback agent** | `ab`: single file, stdlib only, Agnes by default, offline Linux knowledge base, session persistence | +| 🛟 **Built-in fallback agent** | `ab`: zero third-party dependencies, Agnes by default, offline Linux knowledge base, session persistence | | 🧠 **Model provider manager** | Named custom providers, Ollama/LM Studio presets, failover order, connectivity test | | 🇨🇳 **China network adaptive** | npmmirror / Node mirrors / Tsinghua PyPI, four-source downloads, proxy support | -| 📴 **Two kinds of offline packages** | Full (0.8–1.6GB per platform) + slim custom builds (e.g. win-x64 + Pi ≈ 89MB) | +| 📴 **Verified offline packages** | Releases provide Codex slim packs tested through install/run/uninstall; menu `[7]` builds other Agents on their target platform | | ➕ **Custom agents** | Add anything beyond the registry (npm / pip / script), stored in your home dir | -| ⚡ **Extreme performance** | TLS connection reuse (~440ms off per turn), pre-indexed KB (<1ms warm), `/bench` | +| 🧹 **Safe uninstall** | Menu `[9]` or `agentboot uninstall `; removes owned program files and preserves user data by default | +| 🔐 **Verified install** | Enforced SHA-256, atomic app switching, rollback; custom scripts require HTTPS and avoid shell interpolation | +| ⚡ **Measured performance** | TLS connection reuse, pre-indexed KB, and an on-device `/bench` for current network/model conditions | ## Supported agents (14) @@ -79,7 +81,7 @@ Package names verified on the npm registry. `✓` = offline payload bundled. ## Built-in fallback agent (ab) -Works when everything else fails — the design baseline: +Works when everything else fails — a Python standard-library core shipped with i18n and knowledge-base resources: ```bash ab # interactive (Agnes free model by default) @@ -96,13 +98,13 @@ ab model # provider manager ## Offline packages -Download from [Releases](https://github.com/bit-cook/AgentBoot/releases), copy to the target machine — no internet, no unzip software needed. Or build your own **slim package** (pick platforms and agents): +Download a platform-and-Agent-specific verified pack from [Releases](https://github.com/bit-cook/AgentBoot/releases). v1.1.0 initially publishes Linux x64 and Windows x64 Codex packs only after CI installs them, runs `codex --version`, and uninstalls them. Build other Agents on their target platform with menu `[7]` or: ```bash python core/menu.py build-offline win-x64 claude-code,pi ``` -Details: [Installation Guide (EN)](docs/en/install-guide.md) · [安装指南 (中文)](../安装指南.md) +Details: [Installation Guide (EN)](docs/en/install-guide.md) · [安装指南 (中文)](安装指南.md) ## Models @@ -110,23 +112,33 @@ Details: [Installation Guide (EN)](docs/en/install-guide.md) · [安装指南 ( - Custom OpenAI-compatible providers (named), local models (Ollama / LM Studio), failover order; - Config: `~/.agentboot/config.json`; switch language: `agentboot lang en`. -## Performance (measured via `ab bench`) +## Uninstall Agents +Open `agentboot` and choose `[9] Uninstall Agents`, or use the CLI: + +```bash +agentboot uninstall codex +agentboot uninstall codex,qwen-code # batch uninstall +agentboot uninstall coco --purge # also remove CoCo user data ``` -KB query : cold 2.4 ms · warm 0.0 ms -Model TTFB : first (TLS handshake) 1016 ms · reused 579 ms -Reuse benefit : ~437 ms saved per turn -``` + +AgentBoot records install ownership and will not remove an unrelated command merely because it has the same name. Normal uninstall removes the program, offline payload, and AgentBoot-owned shim while keeping model config, credentials, and sessions. `--purge` currently applies to CoCo and removes its user data as well; AgentBoot does not guess at other projects' data directories. Legacy v1.0.0 installs are removed automatically only when their AgentBoot ownership can be proven. + +## Performance (measured via `ab bench`) + +`ab bench` measures KB cold/warm queries and first-token latency for a fresh TLS connection versus a reused connection on the current machine and provider. Results vary by network, model, and region and are not a fixed product guarantee. ## Links -- [Installation Guide (EN)](docs/en/install-guide.md) · [安装指南 (中文)](../安装指南.md) +- [Installation Guide (EN)](docs/en/install-guide.md) · [安装指南 (中文)](安装指南.md) - Primary entry: [boot.ide.pub](https://boot.ide.pub) · Mirror: [GitHub Pages](https://bit-cook.github.io/AgentBoot/) ## Security - The free Agnes model credentials are built in by design; remove `PRESETS["agnes"]["api_key"]` in `core/agent.py` if you fork; -- Command execution blocks dangerous operations by default (confirm in interactive mode). +- `smart` inspects every command-chain segment, blocks dangerous operations, and requires interactive confirmation for ordinary mutations; non-interactive runs never silently approve writes; +- `safe` permits read-only commands/tools only. Automation that intentionally mutates the machine must explicitly set `confirm=always`. +- Online tar/zip archives are fetched with same-origin `.sha256` sidecars and verified before an atomic app-directory switch; failed upgrades preserve or restore the previous version. ## License diff --git a/README.md b/README.md index fa9060d..477dd97 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ [![License](https://img.shields.io/badge/License-MIT-green)](LICENSE) 一条命令装好,主流 Agent **菜单自选**(不是全家桶);内置**保底 Agent** 永远可用; -**全量离线**与**瘦身定制**两种离线包;中国网络环境**开箱自适应**。界面默认中文。 +提供**已验证精简离线包**与**按需自建离线包**;中国网络环境**开箱自适应**。界面默认中文。 **主入口**:[https://boot.ide.pub](https://boot.ide.pub) · **镜像**:[GitHub Pages](https://bit-cook.github.io/AgentBoot/) @@ -38,7 +38,7 @@ powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((New-Object Net.Web | 命令 | 作用 | |---|---| -| `agentboot` | 中文控制台菜单:环境体检 / 自选安装 Agent / 离线安装 / 模型配置 / 镜像代理 / 自定义离线包 | +| `agentboot` | 中文控制台菜单:环境体检 / 安装与卸载 Agent / 模型配置 / 镜像代理 / 自定义离线包 | | `ab` | **内置保底 Agent** —— 默认 Agnes 免费模型,零配置开箱即用 | > 一键脚本**只装 AgentBoot 本体**,装哪些第三方 Agent 始终由你在菜单里自己决定。 @@ -48,11 +48,13 @@ powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((New-Object Net.Web | | | |---|---| | 📦 **菜单自选安装** | 14 个主流 Agent 按需勾选(见下表),支持命令行指定 | -| 🛟 **内置保底 Agent** | `ab` 单文件零依赖:Agnes 开箱即用、离线 Linux 知识库、工具调用、会话持久化 | +| 🛟 **内置保底 Agent** | `ab` 零第三方依赖 Python 核心:Agnes 开箱即用、离线 Linux 知识库、工具调用、会话持久化 | | 🧠 **提供商管理器** | Agnes 预设 + 自定义提供商命名管理 + Ollama/LM Studio 本地模型 + 故障切换顺序 | | 🇨🇳 **中国网络自适应** | npmmirror / Node 镜像 / 清华 PyPI 自动切换;四源下载容错;代理一键配置 | -| 📴 **两种离线包** | 全量(三平台 0.8–1.6GB)+ **瘦身定制**(自选平台与 Agent,如 win-x64 仅 Pi ≈ 89MB) | +| 📴 **可验证离线包** | Release 提供经安装/启动/卸载冒烟的 Codex 精简包;菜单 `[7]` 可按目标平台自建其他 Agent 包 | | ➕ **自定义 Agent** | 菜单向导或 `add-agent` 添加注册表之外的任意 Agent(npm / pip / 脚本),用户目录保存、升级不丢 | +| 🧹 **安全卸载** | 菜单 `[9]` 或 `agentboot uninstall `;精确清理程序,默认保留配置、认证与会话 | +| 🔐 **可验证安装** | 在线包强制 SHA-256 校验、原子切换与失败回滚;自定义脚本仅 HTTPS 且无 shell 拼接 | | ⚡ **极致性能** | TLS 连接复用、知识库预建索引(热查询 <1ms)、上下文自动瘦身、流式中断保护、`/bench` 基准 | | 🪟 **三平台一致体验** | 同一套菜单、命令与文档;Windows 长路径与商店存根等细节已处理 | @@ -81,7 +83,7 @@ powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((New-Object Net.Web 其他 Agent 都装不上时,`ab` 一定能用——这是 AgentBoot 的设计底线: -- **单文件、零第三方依赖**(仅 Python 标准库),任何有 Python 的机器直接跑; +- **零第三方依赖 Python 核心**(仅标准库;随附 i18n 与知识库资源),任何有 Python 的机器直接跑; - **Agnes 免费模型**默认即用;`/model` 管理器可切换自定义接口与本地模型; - **工具**:执行命令(高危拦截)、读写/精确编辑文件、目录列表、`search_files` 内容搜索、抓网页; - **离线 Linux 知识库**(9 大主题 60+ 段落):查用法、操作 Linux、修常见问题(磁盘满/端口占用/服务起不来…); @@ -97,9 +99,9 @@ ab bench # 性能基准 ## 离线安装与瘦身定制 -到 [Releases](https://github.com/bit-cook/AgentBoot/releases) 下载离线包(三平台 0.8–1.6GB,**除 Aider 外全部 Agent 离线可用**),拷到目标机解压后运行包内 `install-offline.ps1` / `sh install-offline.sh`。无解压软件也有三重保障(资源管理器自带 ZIP / 系统自带 tar / 自解压 sfx 脚本)。 +到 [Releases](https://github.com/bit-cook/AgentBoot/releases) 下载带平台与 Agent 名称的已验证精简包,拷到目标机解压后运行包内 `install-offline.ps1` / `sh install-offline.sh`。v1.1.0 首批发布 Linux x64 / Windows x64 的 Codex 包,发布流水线会实际执行安装、`codex --version` 和卸载后才上传。 -只要其中几个 Agent?菜单 `[7]` 或 `build-offline win-x64 claude-code,pi` 自选构建**瘦身包**(实测 win-x64 仅 Pi ≈ 89MB)。 +其他 Agent 使用菜单 `[7]` 或 `build-offline win-x64 claude-code,pi` 在目标平台按需构建。Hermes 含平台相关 Python venv,必须在对应平台构建;Aider 暂不支持离线。 **详细步骤、脚本参数与故障排查见 [《安装指南.md》](安装指南.md)。** @@ -109,12 +111,24 @@ ab bench # 性能基准 - `/model`(ab)或菜单 `[4]` 打开**提供商管理器**:自定义任意 OpenAI 兼容提供商(命名管理)、Ollama / LM Studio 本地模型、故障切换顺序、连通测试; - 配置存于 `~/.agentboot/config.json`。 +## 卸载 Agent + +运行 `agentboot` 选择 `[9] 卸载 Agent`,或直接使用: + +```bash +agentboot uninstall codex +agentboot uninstall codex,qwen-code # 批量卸载 +agentboot uninstall coco --purge # 同时删除 CoCo 用户数据 +``` + +AgentBoot 通过安装清单识别归属,不会因为系统中存在同名命令就误删外部安装。默认卸载只删除程序、离线载荷和 AgentBoot 启动 shim,保留模型配置、认证信息和会话。`--purge` 目前用于 CoCo,可同时清理其用户数据;其他 Agent 的数据目录由各项目定义,AgentBoot 不会猜测删除。旧版遗留安装仅在能证明由 AgentBoot 管理时才会自动卸载。 + ## 项目结构 ``` AgentBoot/ ├── install.sh / install.bat / scripts/install.ps1 在线一键安装 -├── core/agent.py 内置最小 Agent(单文件零依赖) +├── core/agent.py 内置最小 Agent(零第三方依赖 Python 核心) ├── core/menu.py 中文控制台菜单(安装/模型/镜像/离线/构建) ├── agents/registry.json Agent 注册表(v2,含平台与依赖声明) ├── tools/linux-kb/ 离线 Linux 知识库 @@ -127,11 +141,7 @@ AgentBoot/ ## 性能(`ab bench` 实测) -``` -知识库查询 : 冷 2.4 ms(含首载索引) · 热 0.0 ms -模型首字延迟 : 首次(含 TLS 握手)1016 ms · 复用连接 579 ms -连接复用收益 : 每轮省约 437 ms -``` +`ab bench` 会在当前机器和当前模型源现场测量知识库冷/热查询,以及首次 TLS 连接与复用连接的首字延迟;结果取决于网络、模型和地区,不写死为产品保证。 ## 文档与链接 @@ -142,7 +152,9 @@ AgentBoot/ ## 安全说明 - `core/agent.py` 内置 Agnes 免费模型的默认接入信息(本项目预设特性);fork 后可删除 `PRESETS["agnes"]` 中的 `api_key`; -- 执行命令类工具默认拦截高危操作(格式化、递归删除、重启等),交互模式下需确认。 +- `smart` 策略逐段检查命令链,高危操作(格式化、递归删除、重启等)默认拦截,普通写操作需交互确认;非交互任务不会静默放行写操作; +- `safe` 策略只允许只读命令与工具,自动化确需修改本机时必须显式配置 `confirm=always`。 +- 在线 tar/zip 与 `.sha256` 同源下载并强制校验,升级使用原子目录切换,失败自动保留/恢复旧版本。 ## License diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..9084fa2 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +1.1.0 diff --git a/agents/registry.json b/agents/registry.json index 74bbc4a..94b2598 100644 --- a/agents/registry.json +++ b/agents/registry.json @@ -75,7 +75,7 @@ "bin": "pi", "method": "npm", "npm": "@earendil-works/pi-coding-agent", - "node": ">=22", + "node": ">=22.19.0", "offline": true, "notes": ["与 pi.dev 官方安装器同源的 npm 包", "文档:https://pi.dev", "模型:pi 需按官方方式配置 provider(pi.dev 文档)"] }, @@ -135,7 +135,7 @@ "bin": "openclaw", "method": "npm", "npm": "openclaw", - "node": ">=22", + "node": ">=22.22.3 <23 || >=24.15.0 <25 || >=25.9.0", "offline": true, "notes": ["需要较新 Node(22.22+ 或 24+),旧版 Node 仅警告仍可尝试", "文档:https://docs.openclaw.ai"] }, diff --git a/cloudflare/DEPLOY.md b/cloudflare/DEPLOY.md index fb2abcc..543693b 100644 --- a/cloudflare/DEPLOY.md +++ b/cloudflare/DEPLOY.md @@ -1,69 +1,52 @@ -# Cloudflare 部署说明(AgentBoot 分发 Worker) +# Cloudflare Worker 部署 -本目录的 `worker.js` 承担 `https://boot.ide.pub` 的安装脚本分发: +`cloudflare/worker.js` 为 `https://boot.ide.pub` 提供: -``` -curl -fsSL https://boot.ide.pub/install.sh | sh -``` +- `/`、`/en`:中英文产品页; +- `/install.sh`、`/install.ps1`:当前 Release 安装器; +- `/rel/`:Release 资产代理,支持 `Range` / `If-Range`; +- `/health`:实际探测当前版本安装器、在线包与 SHA-256 旁车。 -Worker 名称固定为 **boot**(对应"域名前缀用 boot"的要求)。`*.workers.dev` -在中国大陆通常被阻断,因此同时把自定义域 `boot.ide.pub` 绑定到该 Worker。 +Worker 名称固定为 `boot`,配置见 `wrangler.jsonc`。部署只使用 Wrangler OAuth 或最小权限 API Token,不使用 Cloudflare Global API Key。 -## 手动部署(Cloudflare 控制台) +## 首次登录 + +```sh +npx wrangler login +npx wrangler whoami +``` -1. Workers & Pages → Create Worker → 名称填 `boot` → 粘贴 `worker.js` → Deploy。 -2. Worker 详情 → Settings → Domains & Routes → Add → Custom domain → `boot.ide.pub` - (Cloudflare 会自动创建 DNS 记录与路由)。 +浏览器授权应至少允许 Workers Scripts 与 Routes 写入,以及 Zone 读取。 -## 脚本部署(Cloudflare API,无需 wrangler) +## 发布 -先准备环境变量(全局 API Key 在 Cloudflare 控制台 My Profile → API Tokens 页获取): +先确保 GitHub Release 与 Pages 已发布当前 `VERSION`,再执行: ```sh -export CF_EMAIL="你的账号邮箱" -export CF_KEY="你的 Global API Key" -export CF_ACCOUNT_ID="账户 ID(域名为 ide.pub 的那个账户)" -export CF_ZONE_ID="ide.pub 这个 zone 的 ID" +cd cloudflare +sh deploy.sh ``` -然后: +`deploy.sh` 会执行: ```sh -# 1) 部署/更新 Worker(模块语法上传) -curl -X PUT \ - "https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/workers/scripts/boot" \ - -H "X-Auth-Email: $CF_EMAIL" -H "X-Auth-Key: $CF_KEY" \ - -F 'metadata={"main_module":"worker.js","compatibility_date":"2024-09-23"};type=application/json' \ - -F 'worker.js=@worker.js;type=application/javascript+module' - -# 2) 启用 workers.dev 预览地址(可选) -curl -X POST \ - "https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/workers/scripts/boot/subdomain" \ - -H "X-Auth-Email: $CF_EMAIL" -H "X-Auth-Key: $CF_KEY" \ - -H "Content-Type: application/json" -d '{"enabled":true}' - -# 3) DNS:创建 boot 子域(AAAA 100:: + 代理,把流量交给 Cloudflare) -curl -X POST \ - "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records" \ - -H "X-Auth-Email: $CF_EMAIL" -H "X-Auth-Key: $CF_KEY" \ - -H "Content-Type: application/json" \ - -d '{"type":"AAAA","name":"boot","content":"100::","proxied":true}' - -# 4) 路由:boot.ide.pub/* 全部交给 Worker boot 处理 -curl -X POST \ - "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/workers/routes" \ - -H "X-Auth-Email: $CF_EMAIL" -H "X-Auth-Key: $CF_KEY" \ - -H "Content-Type: application/json" \ - -d '{"pattern":"boot.ide.pub/*","script":"boot"}' +npx wrangler deploy --config wrangler.jsonc +python3 ../scripts/verify-live-release.py ``` -## 验证 +只有以下条件全部满足才算发布成功: + +- `/health` 返回当前 tag 且 `ok=true`; +- Worker 与 Pages 的 `install.sh` / `install.ps1` 都指向当前 tag; +- 两个来源的在线 tar/zip 与各自 `.sha256` 一致; +- Worker `/rel/` 正确返回 `206 Partial Content`。 + +## 回滚 ```sh -curl -fsSL https://boot.ide.pub/health -curl -fsSL https://boot.ide.pub/install.sh | head -n 5 +npx wrangler deployments list --name boot +npx wrangler rollback --name boot +python3 ../scripts/verify-live-release.py ``` -## 版本升级 - -`worker.js` 顶部的 `REPO` / `TAG` 与各安装脚本中的 `TAG` 保持一致;发新版本时同步修改。 +回滚 Worker 后,验证器会按仓库当前 `VERSION` 检查。如果同时回滚 GitHub Release,需要先切换到对应源码/tag再运行验证。 diff --git a/cloudflare/deploy.sh b/cloudflare/deploy.sh index 3121d28..dd25e18 100755 --- a/cloudflare/deploy.sh +++ b/cloudflare/deploy.sh @@ -1,41 +1,11 @@ #!/bin/sh -# AgentBoot Cloudflare Worker 一键部署脚本(API 方式) -# 用法: -# export CF_EMAIL=... CF_KEY=... CF_ACCOUNT_ID=... CF_ZONE_ID=... -# sh deploy.sh +# AgentBoot Cloudflare Worker 一键部署脚本(Wrangler OAuth) set -eu cd "$(dirname "$0")" -: "${CF_EMAIL:?请设置 CF_EMAIL}" -: "${CF_KEY:?请设置 CF_KEY(Global API Key)}" -: "${CF_ACCOUNT_ID:?请设置 CF_ACCOUNT_ID}" -: "${CF_ZONE_ID:?请设置 CF_ZONE_ID(ide.pub)}" - -API="https://api.cloudflare.com/client/v4" -H1="X-Auth-Email: $CF_EMAIL" -H2="X-Auth-Key: $CF_KEY" - -echo "==> 上传 Worker boot …" -curl -sS -X PUT "$API/accounts/$CF_ACCOUNT_ID/workers/scripts/boot" \ - -H "$H1" -H "$H2" \ - -F 'metadata={"main_module":"worker.js","compatibility_date":"2024-09-23"};type=application/json' \ - -F 'worker.js=@worker.js;type=application/javascript+module' | head -c 400; echo - -echo "==> 启用 workers.dev 预览 …" -curl -sS -X POST "$API/accounts/$CF_ACCOUNT_ID/workers/scripts/boot/subdomain" \ - -H "$H1" -H "$H2" -H "Content-Type: application/json" \ - -d '{"enabled":true}' | head -c 300; echo - -echo "==> 创建 DNS 记录 boot(若已存在会报 already exist,可忽略)…" -curl -sS -X POST "$API/zones/$CF_ZONE_ID/dns_records" \ - -H "$H1" -H "$H2" -H "Content-Type: application/json" \ - -d '{"type":"AAAA","name":"boot","content":"100::","proxied":true}' | head -c 300; echo - -echo "==> 创建路由 boot.ide.pub/* → boot …" -curl -sS -X POST "$API/zones/$CF_ZONE_ID/workers/routes" \ - -H "$H1" -H "$H2" -H "Content-Type: application/json" \ - -d '{"pattern":"boot.ide.pub/*","script":"boot"}' | head -c 300; echo - -echo "==> 验证 …" -curl -fsSL https://boot.ide.pub/health || echo "(DNS 生效可能需要 1-2 分钟)" -echo "部署脚本执行完毕。" +command -v npx >/dev/null 2>&1 || { echo "需要 Node.js/npm 提供 npx" >&2; exit 1; } +echo "==> 使用 Wrangler 部署 Worker boot …" +npx --yes wrangler deploy --config wrangler.jsonc +echo "==> 验证主入口与镜像 …" +python3 ../scripts/verify-live-release.py +echo "部署与线上验证完成。" diff --git a/cloudflare/worker.js b/cloudflare/worker.js index 8905983..092ef4d 100644 --- a/cloudflare/worker.js +++ b/cloudflare/worker.js @@ -14,7 +14,7 @@ */ const REPO = "bit-cook/AgentBoot"; -const TAG = "v1.0.0"; +const TAG = "v1.1.0"; const GH_REL = `https://github.com/${REPO}/releases/download/${TAG}`; export default { @@ -23,7 +23,21 @@ export default { const path = url.pathname.replace(/\/+$/, "") || "/"; if (path === "/health") { - return json({ ok: true, repo: REPO, tag: TAG, time: new Date().toISOString() }); + const required = ["install.sh", `agentboot-online-${TAG}.tar.gz`, + `agentboot-online-${TAG}.tar.gz.sha256`, `agentboot-online-${TAG}.zip`, + `agentboot-online-${TAG}.zip.sha256`]; + const assets = {}; + await Promise.all(required.map(async (name) => { + try { + const response = await fetch(`${GH_REL}/${name}`, { + method: "HEAD", headers: { "User-Agent": "AgentBoot-Worker/1.1" }, + cf: { cacheEverything: false }, + }); + assets[name] = response.status; + } catch (_) { assets[name] = 0; } + })); + const ok = required.every((name) => assets[name] >= 200 && assets[name] < 400); + return json({ ok, repo: REPO, tag: TAG, assets, time: new Date().toISOString() }, ok ? 200 : 503); } if (path === "/install.sh") { return proxy(`${GH_REL}/install.sh`, "text/x-shellscript; charset=utf-8", 300); @@ -34,7 +48,7 @@ export default { if (path.startsWith("/rel/")) { const name = decodeURIComponent(path.slice("/rel/".length)); if (!/^[\w.-]+$/.test(name)) return text("bad asset name", 400); - return proxy(`${GH_REL}/${name}`, null, 21600); + return proxy(`${GH_REL}/${name}`, null, 21600, request); } if (path === "/gh/main.tar.gz" || path === "/gh/main.zip") { const ext = path.endsWith(".zip") ? "zip" : "tar.gz"; @@ -50,10 +64,17 @@ export default { }, }; -async function proxy(target, contentType, cacheTtl) { +async function proxy(target, contentType, cacheTtl, incoming = null) { + const requestHeaders = new Headers({ "User-Agent": "AgentBoot-Worker/1.1" }); + if (incoming) { + for (const name of ["Range", "If-Range", "If-None-Match", "If-Modified-Since"]) { + const value = incoming.headers.get(name); + if (value) requestHeaders.set(name, value); + } + } const resp = await fetch(target, { - cf: { cacheEverything: true, cacheTtl }, - headers: { "User-Agent": "AgentBoot-Worker/1.0" }, + cf: { cacheEverything: !requestHeaders.has("Range"), cacheTtl }, + headers: requestHeaders, }); if (!resp.ok) { return text(`上游不可用(${resp.status}):${target}\n请稍后重试或使用 GitHub 直链。\n`, 502); @@ -85,7 +106,7 @@ const PAGE_ZH = ` AgentBoot · 一键安装 AI Agent 启动器 - +