From 50d9b82f6cac8eaa9010bd9877ce2169b62c0a9b Mon Sep 17 00:00:00 2001 From: bit-cook Date: Mon, 31 Aug 2026 11:30:55 +0000 Subject: [PATCH 01/21] feat: redesign and unify AgentBoot web surfaces --- .github/workflows/deploy-pages.yml | 2 + .github/workflows/release.yml | 1 + DESIGN.md | 98 ++ DESIGN_NOTES.md | 23 + cloudflare/DEPLOY.md | 4 + cloudflare/deploy.sh | 1 + cloudflare/web-assets.js | 2 + cloudflare/worker.js | 386 +------- pages/404.html | 25 + pages/assets/favicon.svg | 4 + pages/assets/site.css | 1487 ++++++++++++++++++++++++++++ pages/assets/site.js | 49 + pages/en/index.html | 405 +++++--- pages/index.html | 405 +++++--- scripts/sync-web-assets.py | 80 ++ tests/test_docs_consistency.py | 34 +- tests/test_release_workflow.py | 1 + 17 files changed, 2333 insertions(+), 674 deletions(-) create mode 100644 DESIGN.md create mode 100644 DESIGN_NOTES.md create mode 100644 cloudflare/web-assets.js create mode 100644 pages/404.html create mode 100644 pages/assets/favicon.svg create mode 100644 pages/assets/site.css create mode 100644 pages/assets/site.js create mode 100644 scripts/sync-web-assets.py diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml index fdeb84f..0500107 100644 --- a/.github/workflows/deploy-pages.yml +++ b/.github/workflows/deploy-pages.yml @@ -41,6 +41,8 @@ jobs: 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: Verify generated web assets + run: python3 scripts/sync-web-assets.py --check - name: Build online packages run: python3 scripts/build-online.py - name: Verify package payload diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7a73b70..d90379d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -24,6 +24,7 @@ jobs: 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 + python3 scripts/sync-web-assets.py --check node --check cloudflare/worker.js online: diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 0000000..a7152a4 --- /dev/null +++ b/DESIGN.md @@ -0,0 +1,98 @@ +# DESIGN.md — AgentBoot + +## 1. Objective + +AgentBoot 的每个界面都应让人感到“工具已经准备好,下一步可以轻松开始”:明亮、可靠、有行动感,但不幼稚或喧闹。页面必须像一个经过认真编辑的开源工具,而不是套了营销模板的下载页;质量标准是可长期复用、可直接发布的产品级界面。 + +## 2. Product Context + +- **What the product does:** AgentBoot 用一套可验证的安装流程,在 Linux、macOS 与 Windows 上按需安装、配置和卸载主流 AI Agent。 +- **Who it's for:** 同时尝试多个命令行 AI Agent 的开发者与技术爱好者;他们会核对命令、来源和兼容性,希望快速开始,也在意安全边界与离线可用性。 +- **Adjacent brands (feel like these):** Linear 的信息纪律、Vercel 文档的技术清晰度、Duolingo 的积极能量。 +- **Distant brand (do not feel like this):** 远离典型 Web3 落地页;不使用霓虹渐变、漂浮光球和夸张承诺制造技术感。 +- **Cultural register:** 技术可信为底,乐观亲切为表。像一个熟悉终端、愿意把复杂步骤收拾干净的朋友。 + +## 3. Visual Foundations + +### 3a. Color + +- **Neutral scale:** `--ink-950: #12251D`, `--ink-800: #294238`, `--ink-600: #5B7067`, `--ink-400: #91A198`, `--paper: #FFFDF5`, `--surface: #FFFFFF`, `--line: #DCE7DF`, `--soft: #F2F7F2`。 +- **Accents:** `--green: #137A52` 为主要行动色,`--green-dark: #0D5E3E` 为悬停与高对比状态,`--sun: #FFD84D` 为乐观点睛色,`--coral: #FF7A59` 与 `--sky: #DFF3FF` 只用于结构提示。 +- **Semantic:** `--success: #137A52`, `--warning: #A65E00`, `--error: #B42318`, `--info: #176B87`。 +- **Usage rules:** 每个视口最多一个实心绿色主按钮;太阳黄承担品牌识别和视觉锚点,不承载小号正文;珊瑚色和天蓝色不得同时铺满大面积背景;正文永远使用中性色。 + +### 3b. Typography + +- **Display face:** `ui-rounded, "Avenir Next Rounded", "SF Pro Rounded", "Segoe UI", sans-serif`,只使用 700 与 800,标题字距 `-0.035em`。 +- **Body face:** `Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif`,使用 400、600、700。 +- **Monospace:** `"SFMono-Regular", Consolas, "Liberation Mono", monospace`。 +- **Type scale:** `12 / 14 / 16 / 18 / 24 / 32 / 48 / 72`,关键尺寸通过 `clamp()` 在相邻级别间平滑缩放。 +- **Weight discipline:** 800 只用于 H1 和关键数字,700 用于 H2/H3,600 用于标签与按钮,正文保持 400;不得把整段说明设为半粗体。 + +### 3c. Spacing & rhythm + +- **Base unit:** `4px`。 +- **Spacing scale:** `4 / 8 / 12 / 16 / 24 / 32 / 48 / 64 / 96 / 128px`。 +- **Generous whitespace:** 桌面端主章节垂直内边距为 `96–128px`,平板为 `72–96px`,手机为 `56–72px`;正文行宽不超过 `68ch`,全站容器不超过 `1180px`。 + +### 3d. Component seeds + +- **Button:** 仅三类:绿色实心主操作、白底描边次操作、带方向箭头的文本链接。最小触控高度 `44px`,圆角 `12px`,不使用胶囊按钮。 +- **Card / container:** 只在命令、安全说明和深度信息确实需要成组时使用;圆角 `18–24px`、1px 实线边框、无通用阴影。功能列表使用开放式分隔线,不做 3×2 卡片阵列。 +- **Iconography:** 使用同一套 1.8px 圆角线性 SVG;图标只辅助动作或状态,不替代文字,不用 Emoji 作为装饰。 +- **Brand mark:** 由太阳黄圆点和深绿色终端折线组成,表达“启动”和“向前”,可纯 CSS/SVG 重建。 + +## 4. Accessibility + +- **Text contrast:** 正文至少 4.5:1,大字和 UI 至少 3:1;黄色不直接承载低字号文字。 +- **Motion:** 动画只包含 160–420ms 的淡入、位移和状态反馈;`prefers-reduced-motion: reduce` 时关闭非必要动画与平滑滚动。 +- **Focus indicators:** 所有可交互元素使用 `3px` 太阳黄外环加 `2px` 纸白间隔,不依赖颜色变化单独表达焦点。 +- **Alt text policy:** 装饰性几何图形 `aria-hidden="true"`;信息图形必须用可见文本或准确的 `aria-label` 说明其状态和意义。 +- **Interaction floor:** 触控目标至少 `44×44px`;命令行可键盘滚动,复制结果通过礼貌型 live region 通知;页面提供跳到主要内容的链接。 + +## 5. Voice & Tone + +- **Register:** 对话式技术表达,明确但不生硬,积极但不喊口号。 +- **Sentence rhythm:** 标题短而有动词;说明句长短混合,一段只传递一个判断。 +- **Words this brand uses:** “装好”、“验证”、“按需”、“开始创造”。 +- **Words this brand refuses:** “赋能”、“颠覆”、“无缝”、“革命性”、“解锁潜能”。 +- **Address:** 中文优先使用省略主语的直接表达,必要时称“你”;英文使用 “you”,不称 “users”。 + +## 6. Implementation Practices + +- **Token format:** 原生 CSS 自定义属性;静态页与 Worker 使用同一份 `pages/assets/site.css` 源文件。 +- **Component convention:** 无框架、无运行时依赖的语义 HTML + 原生 CSS/JavaScript;任何浏览器脚本失效时,安装命令、链接和主要信息仍可使用。 +- **Image treatment rules:** 不加载图库照片或 AI 位图;品牌表达来自排版、纯色几何和终端界面的代码原生图形。 +- **Grid system:** 最大 12 列的流式 CSS Grid;主要采用不对称 `7:5` 首屏、`5:7` 安装区和内容重要性驱动的分栏,而不是等宽卡片矩阵。 +- **Motion rules:** `cubic-bezier(.2,.8,.2,1)`,160–420ms;允许轻微上移、颜色和边框转换,禁止弹跳、无限漂浮和视差滚动。 +- **Synchronization:** `pages/` 是中英文 HTML、CSS 与 JavaScript 的唯一视觉源;生成脚本把其内容嵌入 Worker,并以检查模式阻止多个线上入口漂移。 + +## 7. Anti-Patterns + +- **No gradient hero backgrounds.** AgentBoot 的乐观感来自高明度纯色和清晰动作,不借用 SaaS 默认霓虹氛围。 +- **No Emoji section headings.** 技术可信度由语言、排版和一致线性图形建立,不用聊天式符号凑气氛。 +- **No 3×2 feature-card grid.** 功能按重要性分级,用开放式行列与一个重点模块表达,而不是把七项能力压成同样重量。 +- **No primary button everywhere.** 首屏和当前安装动作各自只有一个主要视觉重心,其余操作使用描边或文本链接。 +- **No empty superlatives.** 不写“强大、无缝、革命性”;每句价值陈述必须能由具体功能或发布验证支持。 +- **No forced dark mode.** 用户明确要求亮色,视觉在不同系统主题下保持统一;高对比与夜间阅读通过色值质量解决,不自动翻转品牌。 +- **No desktop shrink-down.** 手机布局重新排序、隐藏低价值表格列并扩大触控区,不只是把桌面内容缩小。 + +## 8. Decision-Making + +1. **Accessibility is the floor.** 品牌色、布局或动效与可访问性冲突时,先改设计选择。 +2. **Install clarity over visual novelty.** 安装命令、平台区别与安全说明不得为了构图被折叠或隐藏。 +3. **One source over local perfection.** Worker、Pages 与镜像必须共享视觉源;不接受某个入口单独手工美化。 +4. **Content hierarchy over completeness.** 核心价值先出现,深度能力后展开;同级信息过多时先合并语义,而不是再加卡片。 +5. **Optimism over spectacle.** 色彩与微动效鼓励行动,但不抢占命令和文档的阅读注意力。 +6. **Distinctive over generic.** 在不损害前五项的前提下,优先采用有 AgentBoot 识别度的结构,而非模板默认组件。 + +## 9. Workflow + +1. 先写清每个页面唯一要完成的用户动作,并确认中英文信息对齐。 +2. 用语义 HTML 排出阅读顺序,确保无 CSS/JavaScript 也能完成主要任务。 +3. 应用颜色、字阶、空间与组件规则,保持每屏只有一个主要动作。 +4. 从 `320px` 手机宽度开始布置,再扩展到平板、桌面和超宽屏。 +5. 运行生成/同步检查,保证 Worker、Pages 与站点镜像没有内容漂移。 +6. 用键盘、减少动态效果模式和高缩放检查交互与可读性。 +7. 在真实浏览器中对中英文页面执行桌面、平板、手机截图和溢出检查。 +8. 运行完整自动化测试与线上冒烟,确认安装分发端点未被视觉改动影响。 diff --git a/DESIGN_NOTES.md b/DESIGN_NOTES.md new file mode 100644 index 0000000..d04499b --- /dev/null +++ b/DESIGN_NOTES.md @@ -0,0 +1,23 @@ +# AgentBoot design notes + +## Current direction + +- Bright “launch day” visual language: paper white, action green, sun yellow, small coral/sky accents. +- Editorial landing-page hierarchy with product-UI precision around installation commands. +- Signature element: a code-native terminal inside an orbital launch motif; no external image or font requests. +- `pages/` is the authored source. Cloudflare Worker pages are generated by `scripts/sync-web-assets.py`. + +## Validated behavior + +- Desktop viewport: 1440×1100, no horizontal overflow. +- Chinese and English mobile viewports: 375×812, no horizontal overflow. +- Brand links and action controls meet the 44px touch target floor. +- Copy buttons use Clipboard API with a legacy fallback and visible success/error states. +- Reduced-motion, visible focus, table overflow, deep-path 404 assets, and light-only color scheme are explicit. + +## Avoid next time + +- Do not reintroduce gradient heroes, emoji headings, equal-weight feature-card grids, or external font/image dependencies. +- Keep decorative pseudo-elements inside their component bounds; an earlier `right: -13px` spotlight label caused mobile document overflow. +- Do not hand-edit `cloudflare/web-assets.js`; regenerate it from `pages/`. +- Do not publish the osome.work mirror without replacing its historical installer/package copies with the current verified Pages set. diff --git a/cloudflare/DEPLOY.md b/cloudflare/DEPLOY.md index 543693b..e2b83c0 100644 --- a/cloudflare/DEPLOY.md +++ b/cloudflare/DEPLOY.md @@ -3,6 +3,7 @@ `cloudflare/worker.js` 为 `https://boot.ide.pub` 提供: - `/`、`/en`:中英文产品页; +- `/assets/*`:与 Pages 共用的样式、交互与图标,按版本长期缓存; - `/install.sh`、`/install.ps1`:当前 Release 安装器; - `/rel/`:Release 资产代理,支持 `Range` / `If-Range`; - `/health`:实际探测当前版本安装器、在线包与 SHA-256 旁车。 @@ -30,10 +31,13 @@ sh deploy.sh `deploy.sh` 会执行: ```sh +python3 ../scripts/sync-web-assets.py --check npx wrangler deploy --config wrangler.jsonc python3 ../scripts/verify-live-release.py ``` +网页以 `pages/` 为唯一源。修改主页、404、CSS、JavaScript 或图标后,先在仓库根目录运行 `python3 scripts/sync-web-assets.py`。CI 与部署脚本会用 `--check` 阻止 Worker 和 Pages 内容漂移。 + 只有以下条件全部满足才算发布成功: - `/health` 返回当前 tag 且 `ok=true`; diff --git a/cloudflare/deploy.sh b/cloudflare/deploy.sh index dd25e18..c1be0dc 100755 --- a/cloudflare/deploy.sh +++ b/cloudflare/deploy.sh @@ -4,6 +4,7 @@ set -eu cd "$(dirname "$0")" command -v npx >/dev/null 2>&1 || { echo "需要 Node.js/npm 提供 npx" >&2; exit 1; } +python3 ../scripts/sync-web-assets.py --check echo "==> 使用 Wrangler 部署 Worker boot …" npx --yes wrangler deploy --config wrangler.jsonc echo "==> 验证主入口与镜像 …" diff --git a/cloudflare/web-assets.js b/cloudflare/web-assets.js new file mode 100644 index 0000000..895d992 --- /dev/null +++ b/cloudflare/web-assets.js @@ -0,0 +1,2 @@ +// Generated by scripts/sync-web-assets.py; do not edit by hand. +export const WEB_ASSETS = Object.freeze({"/index.html":{"body":"\n\n\n \n \n \n \n AgentBoot · 一条命令,启动你的 AI Agent\n \n \n \n \n \n \n \n\n\n 跳到主要内容\n\n \n\n
\n
\n

v1.1.0 · 免费开源 · 三平台可用

\n

一条命令,
Agent 就位

\n

把安装、模型、镜像、离线包和安全卸载收进一个清楚的菜单。你选择要用的 AI Agent,AgentBoot 负责把它可靠地装好。

\n \n
    \n
  • 14 个 Agent 按需选择
  • \n
  • Linux · macOS · Windows
  • \n
  • 离线安装
  • \n
  • MIT License
  • \n
\n
\n\n
\n \n \n \n
\n
\n \n agentboot\n
\n
\n

$ agentboot

\n

检查系统环境与网络…

\n

选择你想安装的 Agent

\n

校验来源与 SHA-256

\n

安装完成,开始创造。

\n
\n
\n
\n
\n\n
\n
\n
\n
\n
\n

从这里开始

\n

复制一行,马上启动

\n

安装完成后输入 agentboot 打开控制台菜单,或输入 ab 直接与内置 Agent 对话。

\n
\n
\n \n \n \n

安装器仅使用项目控制的 Worker、GitHub Pages 与 GitHub Release,并对安装包执行同源 SHA-256 校验。

\n
\n
\n\n
\n
\n
\n Linux / macOS\n \n
\n curl -fsSL https://boot.ide.pub/install.sh | sh\n
\n\n
\n
\n Windows PowerShell\n \n
\n powershell -NoProfile -ExecutionPolicy Bypass -Command \"iex ((New-Object Net.WebClient).DownloadString('https://boot.ide.pub/install.ps1'))\"\n
\n
\n
\n\n
    \n
  1. 安装 AgentBoot

    上面一条命令约 10 秒完成,只安装 AgentBoot 本体与内置 Agent。

  2. \n
  3. 选择需要的 Agent

    运行 agentboot,在菜单中安装、卸载和配置。

  4. \n
  5. 开始工作

    运行选好的 Agent;也可以直接输入 ab 零配置对话。

  6. \n
\n
\n\n
\n
\n

不仅是安装脚本

复杂留在里面,选择留给你

\n

不塞给你一个全家桶,也不把失败留给你排查。AgentBoot 把最容易出错的环境、网络、来源与卸载边界统一处理。

\n
\n\n
\n
\n

始终可用的起点

\n

即使其他 Agent 装不上,ab 也能马上工作

\n

零第三方依赖 Python 核心,默认接入 Agnes 免费模型,并内置离线 Linux 知识库、会话持久化和高危命令拦截。

\n
\n\n
    \n
  1. 01

    按需安装,不装全家桶

    14 个主流 Agent 自由选择:Claude Code、Codex、Qwen Code、OpenCode、MiMo、Cline、Pi、CoCo 等。

  2. \n
  3. 02

    模型提供商统一管理

    Agnes 零配置可用,也支持命名管理任意 OpenAI 兼容接口、Ollama、LM Studio 与故障切换顺序。

  4. \n
  5. 03

    中国网络自动适配

    自动选择 npm、Node、PyPI 镜像,Worker、Pages、Release 三源容错,并提供一键代理配置。

  6. \n
  7. 04

    离线包经过真实验证

    发布包完成安装、启动、卸载冒烟;菜单 [7] 还能在目标平台按需构建自定义包。

  8. \n
  9. 05

    卸载知道自己该删什么

    菜单 [9]uninstall 只清理由 AgentBoot 管理的程序,默认保留配置、认证和会话。

  10. \n
  11. 06

    性能可以现场测量

    TLS 连接复用、知识库预建索引、上下文自动瘦身和流式中断保护;/bench 基于当前网络与模型实测。

  12. \n
\n
\n
\n\n
\n
\n
\n

你的工具箱

14 个 Agent,一个入口

\n

在线安装按需选择;标记为离线可用的 Agent 可连同依赖与运行时一起打包。

\n
\n\n
\n
\n
14个内置选项
\n 绿点表示支持离线安装\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
#Agent命令厂商离线
01CoCo AgentcocoBitCookLinux/macOS
02OpenCodeopencodeopencode.ai仅在线
03Hermes AgenthermesHermes需 Git
04Cline CLIclineCline支持
05CodeBuddy CLIcodebuddyTencent支持
06Pi Coding AgentpiEarendil Works支持
07Claude CodeclaudeAnthropic支持
08OpenAI Codex CLIcodexOpenAIAgnes 预置
09Qwen CodeqwenAlibabaAgnes 预置
10MiMo CodemimoXiaomi支持
11OpenClawopenclawOpenClaw支持
12Gemini CLIgeminiGoogle支持
13iFlow CLIiflowiFlow 心流支持
14AideraiderAider AI仅在线
\n
\n

Codex 与 Qwen 安装后自动预置 Agnes 免费模型;也可通过菜单 +add-agent 添加自己的 Agent。

\n
\n
\n
\n\n
\n
\n
\n

没有网络,也能安装

\n

可验证离线包,把完整运行环境一起带走

\n

v1.1.0 首批提供 Linux x64 与 Windows x64 Codex 精简包,CI 实际执行安装、版本启动与卸载。

\n
    \n
  • 已验证精简包:从 Releases 下载后直接带到目标机。
  • \n
  • 自建离线包:用菜单 [7]build-offline 在目标平台按需构建。
  • \n
  • 无需额外解压软件:运行包内 install-offline.ps1sh install-offline.sh
  • \n
\n
\n\n
\n

模型由你决定

\n

开箱即用,也完全允许自定义

\n
    \n
  • Agnes 免费模型:ab 零配置直接用,Codex 与 Qwen 自动接线。
  • \n
  • 自定义提供商:任意 OpenAI 兼容接口,命名管理、随时切换。
  • \n
  • 本地模型:内置 Ollama 与 LM Studio 预设,也可添加 vLLM。
  • \n
  • 故障切换:设置备用顺序,主模型失败后自动降级。
  • \n
\n
\n
\n
\n\n
\n
\n
\n

需要更多细节

文档直接说人话

\n

从安装、离线部署到自定义 Agent,按你当前要解决的问题继续阅读。

\n
\n \n
\n
\n\n
\n
\n

少折腾环境,早点开始创造

\n

AgentBoot 是 MIT 许可的开源项目。先用一条命令开始,所有选择依然掌握在你手里。

\n \n
\n
\n
\n\n \n\n\n","type":"text/html; charset=utf-8","etag":"\"86a52ca150f60bc2\""},"/en/index.html":{"body":"\n\n\n \n \n \n \n AgentBoot · Launch your AI agents with one command\n \n \n \n \n \n \n \n\n\n Skip to main content\n\n \n\n
\n
\n

v1.1.0 · Free and open source · Three platforms

\n

One command.
Agents ready.

\n

Bring installation, models, mirrors, offline packs, and safe uninstall into one clear menu. You choose the AI agents you need; AgentBoot installs them reliably.

\n \n
    \n
  • Choose from 14 agents
  • \n
  • Linux · macOS · Windows
  • \n
  • Offline installation
  • \n
  • MIT License
  • \n
\n
\n\n
\n \n \n \n
\n
\n \n agentboot\n
\n
\n

$ agentboot

\n

Checking system and network…

\n

Choose the agents you want to install

\n

Verify source and SHA-256

\n

Ready. Start building.

\n
\n
\n
\n
\n\n
\n
\n
\n
\n
\n

Start here

\n

Copy one line. Start right away.

\n

After installation, run agentboot to open the console menu, or ab to chat directly with the built-in agent.

\n
\n
\n \n \n \n

The installer uses only project-controlled Worker, GitHub Pages, and GitHub Release sources, then verifies each installation package against a same-origin SHA-256 checksum.

\n
\n
\n\n
\n
\n
\n Linux / macOS\n \n
\n curl -fsSL https://boot.ide.pub/install.sh | sh\n
\n\n
\n
\n Windows PowerShell\n \n
\n powershell -NoProfile -ExecutionPolicy Bypass -Command \"iex ((New-Object Net.WebClient).DownloadString('https://boot.ide.pub/install.ps1'))\"\n
\n
\n
\n\n
    \n
  1. Install AgentBoot

    The command above takes about 10 seconds and installs only AgentBoot itself and the built-in agent.

  2. \n
  3. Choose the agents you need

    Run agentboot to install, uninstall, and configure agents from the menu.

  4. \n
  5. Get to work

    Launch your chosen agent, or run ab for a zero-configuration chat.

  6. \n
\n
\n\n
\n
\n

More than an install script

AgentBoot handles the complexity. You make the choices.

\n

No all-in-one bundle, and no failed setup left for you to debug. AgentBoot handles the parts most likely to break: environments, networks, sources, and uninstall boundaries.

\n
\n\n
\n
\n

A starting point that's always ready

\n

Even if other agents won't install, ab works right away

\n

The built-in agent uses a Python core with no third-party dependencies, the free Agnes model by default, an offline Linux knowledge base, persistent sessions, and safeguards against high-risk commands.

\n
\n\n
    \n
  1. 01

    Install on demand, not as a bundle

    Choose from 14 mainstream agents, including Claude Code, Codex, Qwen Code, OpenCode, MiMo, Cline, Pi, and CoCo.

  2. \n
  3. 02

    Manage model providers in one place

    Agnes works with zero configuration. You can also name and manage any OpenAI-compatible endpoint, Ollama, or LM Studio, and set a failover order.

  4. \n
  5. 03

    Automatically adapt to networks in China

    AgentBoot selects npm, Node, and PyPI mirrors automatically, fails over across Worker, Pages, and Release sources, and configures a proxy in one step.

  6. \n
  7. 04

    Offline packs are tested end to end

    Release packs pass install, launch, and uninstall smoke tests; menu [7] can also build a custom pack on demand on the target platform.

  8. \n
  9. 05

    Uninstall only what AgentBoot owns

    Menu [9] or uninstall removes AgentBoot-managed programs while keeping configuration, credentials, and sessions by default.

  10. \n
  11. 06

    Measure performance where it matters

    AgentBoot reuses TLS connections, prebuilds knowledge-base indexes, trims context automatically, and protects interrupted streams. /bench measures your current network and model.

  12. \n
\n
\n
\n\n
\n
\n
\n

Your toolbox

14 agents. One front door.

\n

Choose agents as needed for online installation. Agents marked as offline-ready can be packaged with their dependencies and runtimes.

\n
\n\n
\n
\n
14built-in choices
\n A green dot indicates support for offline installation\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
#AgentCommandVendorOffline
01CoCo AgentcocoBitCookLinux/macOS
02OpenCodeopencodeopencode.aiOnline only
03Hermes AgenthermesHermesRequires Git
04Cline CLIclineClineSupported
05CodeBuddy CLIcodebuddyTencentSupported
06Pi Coding AgentpiEarendil WorksSupported
07Claude CodeclaudeAnthropicSupported
08OpenAI Codex CLIcodexOpenAIAgnes preset
09Qwen CodeqwenAlibabaAgnes preset
10MiMo CodemimoXiaomiSupported
11OpenClawopenclawOpenClawSupported
12Gemini CLIgeminiGoogleSupported
13iFlow CLIiflowiFlowSupported
14AideraiderAider AIOnline only
\n
\n

Codex and Qwen are automatically configured with the free Agnes model after installation. Add your own agent with menu + or the add-agent command.

\n
\n
\n
\n\n
\n
\n
\n

Install without internet access

\n

Verified offline packs bring the complete runtime with you

\n

v1.1.0 initially provides slim Codex packs for Linux x64 and Windows x64. CI installs each pack, runs its version command, and uninstalls it.

\n
    \n
  • Verified slim packs: download from Releases and carry them to the target machine.
  • \n
  • Custom offline packs: use menu [7] or build-offline on the target platform.
  • \n
  • No extra extraction software: run install-offline.ps1 or sh install-offline.sh inside the pack.
  • \n
\n
\n\n
\n

Your models, your choice

\n

Ready out of the box and fully customizable

\n
    \n
  • Agnes free model: use ab with zero setup; Codex and Qwen are configured automatically.
  • \n
  • Custom providers: name, manage, and switch any OpenAI-compatible endpoint.
  • \n
  • Local models: Ollama and LM Studio presets, with vLLM available as a custom provider.
  • \n
  • Failover: set a fallback order and switch automatically when the primary fails.
  • \n
\n
\n
\n
\n\n
\n
\n
\n

More detail when you need it

Documentation that speaks plainly

\n

Start with the problem in front of you, from installation and offline deployment to custom agents.

\n
\n \n
\n
\n\n
\n
\n

Spend less time wrestling with setup. Start building sooner.

\n

AgentBoot is open source under the MIT License. Start with one command; every choice stays in your hands.

\n \n
\n
\n
\n\n \n\n\n","type":"text/html; charset=utf-8","etag":"\"eb766b947b8368b7\""},"/404.html":{"body":"\n\n\n \n \n \n \n 页面未找到 · AgentBoot\n \n \n\n\n
\n
\n

404

\n

这条路径没有 Agent,回到启动台吧

\n

地址可能已变更,或只是多输入了一个字符。项目主页、安装命令和文档都还在。

\n \n
\n
\n\n\n","type":"text/html; charset=utf-8","etag":"\"92d469229bf5cde6\""},"/assets/site.css":{"body":":root {\n color-scheme: light;\n --ink-950: #12251d;\n --ink-800: #294238;\n --ink-600: #5b7067;\n --ink-400: #91a198;\n --paper: #fffdf5;\n --surface: #ffffff;\n --soft: #f2f7f2;\n --line: #dce7df;\n --green: #137a52;\n --green-dark: #0d5e3e;\n --green-soft: #e3f5eb;\n --sun: #ffd84d;\n --sun-soft: #fff3b9;\n --coral: #ff7a59;\n --sky: #dff3ff;\n --success: #137a52;\n --warning: #a65e00;\n --error: #b42318;\n --info: #176b87;\n --code: #10251d;\n --code-text: #ecfff4;\n --display: ui-rounded, \"Avenir Next Rounded\", \"SF Pro Rounded\", \"Segoe UI\", sans-serif;\n --body: Inter, ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif;\n --mono: \"SFMono-Regular\", Consolas, \"Liberation Mono\", monospace;\n --ease: cubic-bezier(.2, .8, .2, 1);\n}\n\n* {\n box-sizing: border-box;\n}\n\nhtml {\n overflow-x: clip;\n scroll-behavior: smooth;\n scroll-padding-top: 88px;\n}\n\nbody {\n margin: 0;\n background: var(--paper);\n color: var(--ink-950);\n font-family: var(--body);\n font-size: 16px;\n line-height: 1.68;\n text-rendering: optimizeLegibility;\n -webkit-font-smoothing: antialiased;\n}\n\nbutton,\na {\n -webkit-tap-highlight-color: transparent;\n}\n\na {\n color: var(--green-dark);\n text-decoration-thickness: 1.5px;\n text-underline-offset: .2em;\n}\n\na:hover {\n color: var(--green);\n}\n\n:focus-visible {\n outline: 3px solid var(--sun);\n outline-offset: 3px;\n}\n\n.skip-link {\n position: fixed;\n z-index: 100;\n top: 12px;\n left: 12px;\n translate: 0 -150%;\n border: 1px solid var(--ink-950);\n border-radius: 10px;\n background: var(--surface);\n color: var(--ink-950);\n padding: 10px 14px;\n font-weight: 700;\n}\n\n.skip-link:focus {\n translate: 0;\n}\n\n.shell {\n width: min(1180px, calc(100% - 48px));\n margin-inline: auto;\n}\n\n.site-nav {\n position: relative;\n z-index: 10;\n display: flex;\n min-height: 76px;\n align-items: center;\n justify-content: space-between;\n gap: 24px;\n}\n\n.brand {\n display: inline-flex;\n min-height: 44px;\n align-items: center;\n gap: 11px;\n color: var(--ink-950);\n font-family: var(--display);\n font-size: 18px;\n font-weight: 800;\n letter-spacing: -.025em;\n text-decoration: none;\n}\n\n.brand-mark {\n position: relative;\n display: inline-grid;\n width: 34px;\n height: 34px;\n place-items: center;\n overflow: hidden;\n border: 2px solid var(--ink-950);\n border-radius: 11px;\n background: var(--sun);\n}\n\n.brand-mark::before,\n.brand-mark::after {\n content: \"\";\n position: absolute;\n height: 2px;\n border-radius: 999px;\n background: var(--ink-950);\n transform-origin: left center;\n}\n\n.brand-mark::before {\n width: 12px;\n translate: -1px -3px;\n rotate: 38deg;\n}\n\n.brand-mark::after {\n width: 10px;\n translate: 2px 5px;\n}\n\n.nav-links {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.nav-link,\n.language-link {\n display: inline-flex;\n min-height: 44px;\n align-items: center;\n justify-content: center;\n border-radius: 10px;\n color: var(--ink-800);\n padding: 8px 11px;\n font-size: 14px;\n font-weight: 650;\n text-decoration: none;\n}\n\n.nav-link:hover,\n.language-link:hover {\n background: var(--green-soft);\n color: var(--green-dark);\n}\n\n.language-link {\n border: 1px solid var(--line);\n background: rgba(255, 255, 255, .72);\n}\n\n.hero {\n position: relative;\n display: grid;\n min-height: 660px;\n align-items: center;\n grid-template-columns: minmax(0, 7fr) minmax(340px, 5fr);\n gap: clamp(32px, 6vw, 86px);\n padding-block: 72px 112px;\n}\n\n.hero::before {\n content: \"\";\n position: absolute;\n z-index: -2;\n top: 2%;\n right: 0;\n width: min(48vw, 620px);\n aspect-ratio: 1;\n border-radius: 50%;\n background: var(--sun-soft);\n}\n\n.hero::after {\n content: \"\";\n position: absolute;\n z-index: -1;\n bottom: 9%;\n left: 0;\n width: min(30vw, 380px);\n aspect-ratio: 1;\n border-radius: 50%;\n background: var(--sky);\n opacity: .7;\n}\n\n.eyebrow {\n display: inline-flex;\n align-items: center;\n gap: 9px;\n margin: 0 0 22px;\n color: var(--green-dark);\n font-size: 13px;\n font-weight: 750;\n letter-spacing: .08em;\n text-transform: uppercase;\n}\n\n.eyebrow::before {\n content: \"\";\n width: 9px;\n height: 9px;\n border-radius: 50%;\n background: var(--coral);\n box-shadow: 0 0 0 5px rgba(255, 122, 89, .14);\n}\n\nh1,\nh2,\nh3 {\n font-family: var(--display);\n text-wrap: balance;\n}\n\nh1 {\n max-width: 800px;\n margin: 0;\n font-size: clamp(48px, 7.1vw, 88px);\n font-weight: 800;\n letter-spacing: -.06em;\n line-height: .98;\n}\n\n.hero-highlight {\n position: relative;\n display: inline-block;\n white-space: nowrap;\n}\n\n.hero-highlight::after {\n content: \"\";\n position: absolute;\n z-index: -1;\n right: -.08em;\n bottom: .04em;\n left: -.02em;\n height: .24em;\n border-radius: 99px;\n background: var(--sun);\n rotate: -1.5deg;\n}\n\n.hero-copy {\n max-width: 650px;\n margin: 28px 0 0;\n color: var(--ink-600);\n font-size: clamp(17px, 2vw, 21px);\n line-height: 1.62;\n}\n\n.hero-actions {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n margin-top: 34px;\n}\n\n.button {\n display: inline-flex;\n min-height: 48px;\n align-items: center;\n justify-content: center;\n gap: 9px;\n border: 1px solid var(--ink-950);\n border-radius: 12px;\n padding: 11px 17px;\n font-size: 15px;\n font-weight: 750;\n line-height: 1;\n text-decoration: none;\n transition: translate 160ms var(--ease), background-color 160ms var(--ease), color 160ms var(--ease);\n}\n\n.button-primary {\n background: var(--green);\n color: #fff;\n border-color: var(--green);\n}\n\n.button-primary:hover {\n background: var(--green-dark);\n color: #fff;\n translate: 0 -2px;\n}\n\n.button-secondary {\n background: var(--surface);\n color: var(--ink-950);\n}\n\n.button-secondary:hover {\n background: var(--sun-soft);\n color: var(--ink-950);\n translate: 0 -2px;\n}\n\n.button svg,\n.text-link svg {\n width: 18px;\n height: 18px;\n flex: 0 0 auto;\n fill: none;\n stroke: currentColor;\n stroke-linecap: round;\n stroke-linejoin: round;\n stroke-width: 1.8;\n}\n\n.hero-proof {\n display: flex;\n flex-wrap: wrap;\n gap: 10px 18px;\n margin: 26px 0 0;\n padding: 0;\n color: var(--ink-600);\n font-size: 13px;\n font-weight: 650;\n list-style: none;\n}\n\n.hero-proof li {\n display: flex;\n align-items: center;\n gap: 7px;\n}\n\n.hero-proof li::before {\n content: \"\";\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--green);\n}\n\n.launch-visual {\n position: relative;\n min-height: 450px;\n}\n\n.orbit {\n position: absolute;\n inset: 0;\n margin: auto;\n border: 1px solid rgba(18, 37, 29, .18);\n border-radius: 50%;\n}\n\n.orbit-one {\n width: min(100%, 430px);\n aspect-ratio: 1;\n}\n\n.orbit-two {\n width: min(76%, 330px);\n aspect-ratio: 1;\n border-style: dashed;\n}\n\n.orbit-dot {\n position: absolute;\n top: 10%;\n right: 14%;\n width: 18px;\n height: 18px;\n border: 3px solid var(--paper);\n border-radius: 50%;\n background: var(--coral);\n box-shadow: 0 0 0 1px var(--ink-950);\n}\n\n.terminal {\n position: absolute;\n inset: 50% auto auto 50%;\n width: min(94%, 390px);\n overflow: hidden;\n border: 2px solid var(--ink-950);\n border-radius: 22px;\n background: var(--code);\n box-shadow: 18px 18px 0 var(--sun);\n color: var(--code-text);\n translate: -50% -50%;\n}\n\n.terminal-bar {\n display: flex;\n min-height: 48px;\n align-items: center;\n justify-content: space-between;\n border-bottom: 1px solid rgba(255, 255, 255, .13);\n padding: 0 17px;\n color: #b9d3c4;\n font-family: var(--mono);\n font-size: 12px;\n}\n\n.terminal-dots {\n display: flex;\n gap: 6px;\n}\n\n.terminal-dots i {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--coral);\n}\n\n.terminal-dots i:nth-child(2) {\n background: var(--sun);\n}\n\n.terminal-dots i:nth-child(3) {\n background: #57d49b;\n}\n\n.terminal-body {\n min-height: 238px;\n padding: 26px 22px;\n font-family: var(--mono);\n font-size: clamp(12px, 1.35vw, 14px);\n line-height: 1.8;\n}\n\n.terminal-body p {\n margin: 0 0 12px;\n}\n\n.prompt {\n color: #69e4a7;\n}\n\n.terminal-muted {\n color: #9bb7a8;\n}\n\n.terminal-check {\n color: var(--sun);\n}\n\n.section {\n padding-block: clamp(72px, 10vw, 120px);\n}\n\n.section-soft {\n position: relative;\n background: var(--soft);\n}\n\n.section-soft::before,\n.section-soft::after {\n content: \"\";\n position: absolute;\n right: 0;\n left: 0;\n height: 1px;\n background: var(--line);\n}\n\n.section-soft::before {\n top: 0;\n}\n\n.section-soft::after {\n bottom: 0;\n}\n\n.section-heading {\n display: grid;\n align-items: end;\n grid-template-columns: minmax(0, 4fr) minmax(280px, 3fr);\n gap: 32px;\n margin-bottom: 54px;\n}\n\n.kicker {\n margin: 0 0 12px;\n color: var(--green);\n font-size: 13px;\n font-weight: 750;\n letter-spacing: .08em;\n text-transform: uppercase;\n}\n\nh2 {\n max-width: 700px;\n margin: 0;\n font-size: clamp(34px, 4.8vw, 56px);\n font-weight: 800;\n letter-spacing: -.045em;\n line-height: 1.06;\n}\n\n.section-lede {\n max-width: 56ch;\n margin: 0;\n color: var(--ink-600);\n font-size: 17px;\n}\n\n.install-layout {\n display: grid;\n align-items: start;\n grid-template-columns: minmax(240px, 4fr) minmax(0, 8fr);\n gap: clamp(34px, 7vw, 88px);\n}\n\n.install-intro {\n position: sticky;\n top: 104px;\n}\n\n.install-intro h2 {\n font-size: clamp(34px, 4vw, 48px);\n}\n\n.install-intro p {\n color: var(--ink-600);\n}\n\n.security-note {\n display: grid;\n grid-template-columns: 38px 1fr;\n gap: 13px;\n margin-top: 28px;\n padding-top: 22px;\n border-top: 1px solid var(--line);\n color: var(--ink-600);\n font-size: 14px;\n}\n\n.security-icon {\n display: grid;\n width: 38px;\n height: 38px;\n place-items: center;\n border-radius: 12px;\n background: var(--green-soft);\n color: var(--green-dark);\n}\n\n.security-icon svg {\n width: 21px;\n height: 21px;\n fill: none;\n stroke: currentColor;\n stroke-linecap: round;\n stroke-linejoin: round;\n stroke-width: 1.8;\n}\n\n.security-note p {\n margin: 0;\n}\n\n.command-stack {\n display: grid;\n gap: 16px;\n}\n\n.command-card {\n overflow: hidden;\n border: 1px solid var(--ink-950);\n border-radius: 20px;\n background: var(--surface);\n}\n\n.command-head {\n display: flex;\n min-height: 56px;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n border-bottom: 1px solid var(--line);\n padding: 10px 12px 10px 20px;\n}\n\n.command-platform {\n display: flex;\n align-items: center;\n gap: 11px;\n font-weight: 750;\n}\n\n.platform-dot {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: var(--coral);\n}\n\n.command-card:nth-child(2) .platform-dot {\n background: #2f80ed;\n}\n\n.copy-button {\n display: inline-flex;\n min-width: 90px;\n min-height: 44px;\n align-items: center;\n justify-content: center;\n gap: 7px;\n border: 1px solid var(--line);\n border-radius: 10px;\n background: var(--soft);\n color: var(--ink-950);\n padding: 8px 12px;\n font: 700 13px/1 var(--body);\n cursor: pointer;\n transition: background-color 160ms var(--ease), border-color 160ms var(--ease);\n}\n\n.copy-button:hover {\n border-color: var(--green);\n background: var(--green-soft);\n}\n\n.copy-button[data-state=\"success\"] {\n border-color: var(--green);\n background: var(--green-soft);\n color: var(--green-dark);\n}\n\n.copy-button[data-state=\"error\"] {\n border-color: var(--error);\n background: #fff0ed;\n color: var(--error);\n}\n\n.copy-button svg {\n width: 16px;\n height: 16px;\n fill: none;\n stroke: currentColor;\n stroke-linecap: round;\n stroke-linejoin: round;\n stroke-width: 1.8;\n}\n\n.command-code {\n display: block;\n margin: 0;\n overflow-x: auto;\n background: var(--code);\n color: var(--code-text);\n padding: 24px 20px;\n font-family: var(--mono);\n font-size: 13px;\n line-height: 1.75;\n white-space: pre;\n scrollbar-color: #557266 var(--code);\n}\n\n.command-code::selection,\n.terminal ::selection {\n background: var(--sun);\n color: var(--ink-950);\n}\n\n.steps {\n display: grid;\n margin: 48px 0 0;\n padding: 0;\n counter-reset: step;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n list-style: none;\n}\n\n.step {\n position: relative;\n min-height: 180px;\n padding: 30px clamp(20px, 3vw, 34px);\n counter-increment: step;\n border-top: 1px solid var(--line);\n border-bottom: 1px solid var(--line);\n}\n\n.step + .step {\n border-left: 1px solid var(--line);\n}\n\n.step::before {\n content: \"0\" counter(step);\n display: block;\n margin-bottom: 30px;\n color: var(--coral);\n font: 750 13px/1 var(--mono);\n}\n\n.step h3 {\n margin: 0 0 8px;\n font-size: 19px;\n font-weight: 750;\n letter-spacing: -.02em;\n}\n\n.step p {\n margin: 0;\n color: var(--ink-600);\n font-size: 14px;\n}\n\n.inline-code,\n.rich-text code,\n.agent-table code,\n.feature-row code {\n border: 1px solid var(--line);\n border-radius: 6px;\n background: var(--surface);\n color: var(--green-dark);\n padding: .12em .42em;\n font-family: var(--mono);\n font-size: .88em;\n}\n\n.feature-layout {\n display: grid;\n align-items: start;\n grid-template-columns: minmax(280px, 5fr) minmax(0, 7fr);\n gap: clamp(40px, 8vw, 100px);\n}\n\n.feature-spotlight {\n position: sticky;\n top: 104px;\n overflow: hidden;\n border: 1px solid var(--ink-950);\n border-radius: 24px;\n background: var(--sun);\n padding: clamp(28px, 4vw, 44px);\n}\n\n.feature-spotlight::after {\n content: \"ab\";\n position: absolute;\n right: 0;\n bottom: -58px;\n color: rgba(18, 37, 29, .09);\n font: 800 clamp(120px, 18vw, 220px)/1 var(--display);\n letter-spacing: -.08em;\n}\n\n.feature-spotlight .kicker {\n color: var(--ink-800);\n}\n\n.feature-spotlight h3 {\n max-width: 470px;\n margin: 0;\n font-size: clamp(30px, 4vw, 48px);\n font-weight: 800;\n letter-spacing: -.045em;\n line-height: 1.08;\n}\n\n.feature-spotlight p {\n position: relative;\n z-index: 1;\n max-width: 48ch;\n margin: 24px 0 0;\n color: var(--ink-800);\n}\n\n.feature-list {\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.feature-row {\n display: grid;\n padding: 25px 0 28px;\n border-top: 1px solid var(--line);\n grid-template-columns: 44px 1fr;\n gap: 18px;\n}\n\n.feature-row:last-child {\n border-bottom: 1px solid var(--line);\n}\n\n.feature-index {\n color: var(--green);\n font: 750 12px/1.5 var(--mono);\n}\n\n.feature-row h3 {\n margin: -4px 0 7px;\n font-size: 20px;\n font-weight: 750;\n letter-spacing: -.025em;\n}\n\n.feature-row p {\n max-width: 60ch;\n margin: 0;\n color: var(--ink-600);\n font-size: 14px;\n}\n\n.agent-panel {\n overflow: hidden;\n border: 1px solid var(--ink-950);\n border-radius: 24px;\n background: var(--surface);\n}\n\n.agent-panel-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 20px;\n border-bottom: 1px solid var(--line);\n padding: 20px 24px;\n}\n\n.agent-count {\n display: flex;\n align-items: baseline;\n gap: 9px;\n}\n\n.agent-count strong {\n font: 800 38px/1 var(--display);\n letter-spacing: -.04em;\n}\n\n.agent-count span,\n.agent-legend {\n color: var(--ink-600);\n font-size: 13px;\n}\n\n.table-scroll {\n max-width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.agent-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 14px;\n}\n\n.agent-table th,\n.agent-table td {\n min-height: 52px;\n padding: 14px 20px;\n border-bottom: 1px solid var(--line);\n text-align: left;\n vertical-align: middle;\n}\n\n.agent-table th {\n background: var(--soft);\n color: var(--ink-600);\n font-size: 12px;\n font-weight: 750;\n letter-spacing: .04em;\n text-transform: uppercase;\n}\n\n.agent-table tr:last-child td {\n border-bottom: 0;\n}\n\n.agent-table tbody tr:hover {\n background: #fffdf3;\n}\n\n.agent-name {\n font-weight: 750;\n}\n\n.status {\n display: inline-flex;\n align-items: center;\n gap: 7px;\n white-space: nowrap;\n}\n\n.status::before {\n content: \"\";\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--ink-400);\n}\n\n.status-ready {\n color: var(--success);\n font-weight: 650;\n}\n\n.status-ready::before {\n background: var(--success);\n}\n\n.agent-footnote {\n margin: 0;\n border-top: 1px solid var(--line);\n background: var(--sun-soft);\n color: var(--ink-800);\n padding: 16px 22px;\n font-size: 13px;\n}\n\n.detail-grid {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 1px;\n border: 1px solid var(--line);\n background: var(--line);\n}\n\n.detail-block {\n min-height: 320px;\n background: var(--paper);\n padding: clamp(30px, 5vw, 58px);\n}\n\n.detail-block:nth-child(2) {\n background: var(--sky);\n}\n\n.detail-block h3 {\n max-width: 470px;\n margin: 0 0 20px;\n font-size: clamp(27px, 3vw, 38px);\n font-weight: 800;\n letter-spacing: -.04em;\n line-height: 1.1;\n}\n\n.rich-text {\n color: var(--ink-800);\n}\n\n.rich-text p {\n margin: 0 0 16px;\n}\n\n.rich-text ul {\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.rich-text li {\n position: relative;\n padding: 11px 0 11px 24px;\n border-top: 1px solid rgba(18, 37, 29, .15);\n}\n\n.rich-text li::before {\n content: \"\";\n position: absolute;\n top: 20px;\n left: 2px;\n width: 8px;\n height: 8px;\n border-radius: 2px;\n background: var(--green);\n rotate: 45deg;\n}\n\n.docs-list {\n display: grid;\n margin: 0;\n padding: 0;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 12px;\n list-style: none;\n}\n\n.docs-link {\n display: flex;\n min-height: 128px;\n flex-direction: column;\n justify-content: space-between;\n gap: 24px;\n border: 1px solid var(--line);\n border-radius: 18px;\n background: var(--surface);\n color: var(--ink-950);\n padding: 22px;\n text-decoration: none;\n transition: border-color 160ms var(--ease), translate 160ms var(--ease);\n}\n\n.docs-link:hover {\n border-color: var(--green);\n color: var(--green-dark);\n translate: 0 -3px;\n}\n\n.docs-link strong {\n font-size: 16px;\n}\n\n.docs-link span {\n color: var(--ink-600);\n font-size: 13px;\n}\n\n.text-link {\n display: inline-flex;\n align-items: center;\n gap: 7px;\n font-weight: 750;\n}\n\n.final-call {\n position: relative;\n overflow: hidden;\n contain: paint;\n border: 1px solid var(--ink-950);\n border-radius: 28px;\n background: var(--green);\n color: #fff;\n padding: clamp(36px, 7vw, 76px);\n}\n\n.final-call::after {\n content: \"\";\n position: absolute;\n right: -80px;\n bottom: -120px;\n width: 320px;\n height: 320px;\n border: 58px solid var(--sun);\n border-radius: 50%;\n opacity: .98;\n}\n\n.final-call h2 {\n position: relative;\n z-index: 1;\n max-width: 700px;\n font-size: clamp(36px, 6vw, 66px);\n}\n\n.final-call p {\n position: relative;\n z-index: 1;\n max-width: 55ch;\n margin: 22px 0 0;\n color: #dff8e9;\n font-size: 17px;\n}\n\n.final-call .hero-actions {\n position: relative;\n z-index: 1;\n}\n\n.final-call .button-primary {\n border-color: var(--sun);\n background: var(--sun);\n color: var(--ink-950);\n}\n\n.final-call .button-primary:hover {\n border-color: #ffe277;\n background: #ffe277;\n color: var(--ink-950);\n}\n\n.final-call .button-secondary {\n border-color: rgba(255, 255, 255, .5);\n background: transparent;\n color: #fff;\n}\n\n.final-call .button-secondary:hover {\n border-color: #fff;\n background: rgba(255, 255, 255, .1);\n color: #fff;\n}\n\n.site-footer {\n padding-block: 34px 44px;\n}\n\n.footer-row {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 30px;\n}\n\n.footer-note {\n max-width: 680px;\n margin: 13px 0 0;\n color: var(--ink-600);\n font-size: 13px;\n}\n\n.footer-links {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-end;\n gap: 6px 18px;\n font-size: 13px;\n font-weight: 650;\n}\n\n.footer-links a {\n min-height: 44px;\n display: inline-flex;\n align-items: center;\n}\n\n.not-found {\n display: grid;\n min-height: 100svh;\n place-items: center;\n padding: 40px 24px;\n}\n\n.not-found-card {\n position: relative;\n width: min(720px, 100%);\n overflow: hidden;\n border: 1px solid var(--ink-950);\n border-radius: 28px;\n background: var(--surface);\n padding: clamp(32px, 8vw, 72px);\n box-shadow: 18px 18px 0 var(--sun);\n}\n\n.not-found-code {\n margin: 0 0 28px;\n color: var(--coral);\n font: 800 clamp(60px, 15vw, 132px)/.8 var(--display);\n letter-spacing: -.07em;\n}\n\n.not-found h1 {\n max-width: 620px;\n font-size: clamp(34px, 7vw, 58px);\n line-height: 1.06;\n}\n\n.not-found p {\n max-width: 50ch;\n margin: 22px 0 0;\n color: var(--ink-600);\n}\n\n@media (prefers-reduced-motion: no-preference) {\n .hero-copy,\n .hero-actions,\n .hero-proof {\n animation: rise-in 620ms var(--ease) both;\n }\n\n .hero-actions {\n animation-delay: 100ms;\n }\n\n .hero-proof {\n animation-delay: 180ms;\n }\n\n .terminal {\n animation: terminal-in 720ms 80ms var(--ease) both;\n }\n\n .orbit-dot {\n animation: pulse 2.8s var(--ease) infinite;\n }\n\n @keyframes rise-in {\n from { opacity: 0; translate: 0 16px; }\n to { opacity: 1; translate: 0; }\n }\n\n @keyframes terminal-in {\n from { opacity: 0; translate: -46% -46%; }\n to { opacity: 1; translate: -50% -50%; }\n }\n\n @keyframes pulse {\n 50% { scale: 1.14; }\n }\n}\n\n@media (max-width: 900px) {\n .hero {\n min-height: auto;\n grid-template-columns: 1fr;\n padding-block: 54px 90px;\n }\n\n .launch-visual {\n min-height: 410px;\n }\n\n .section-heading,\n .install-layout,\n .feature-layout {\n grid-template-columns: 1fr;\n }\n\n .install-intro,\n .feature-spotlight {\n position: static;\n }\n\n .install-intro {\n display: grid;\n align-items: end;\n grid-template-columns: 1fr 1fr;\n gap: 30px;\n }\n\n .security-note {\n margin: 0;\n }\n\n .feature-spotlight {\n min-height: 310px;\n }\n}\n\n@media (max-width: 720px) {\n .shell {\n width: min(100% - 32px, 1180px);\n }\n\n .site-nav {\n min-height: 68px;\n }\n\n .nav-link {\n display: none;\n }\n\n .hero {\n gap: 42px;\n padding-top: 46px;\n }\n\n h1 {\n font-size: clamp(44px, 14vw, 68px);\n }\n\n .hero-copy {\n font-size: 17px;\n }\n\n .launch-visual {\n min-height: 350px;\n }\n\n .orbit-one {\n width: min(94%, 350px);\n }\n\n .orbit-two {\n width: min(72%, 270px);\n }\n\n .terminal {\n box-shadow: 11px 11px 0 var(--sun);\n }\n\n .terminal-body {\n min-height: 210px;\n padding: 22px 18px;\n }\n\n .section-heading {\n align-items: start;\n gap: 18px;\n margin-bottom: 38px;\n }\n\n .install-intro {\n display: block;\n }\n\n .security-note {\n margin-top: 24px;\n }\n\n .steps,\n .detail-grid,\n .docs-list {\n grid-template-columns: 1fr;\n }\n\n .step {\n min-height: auto;\n border-bottom: 0;\n padding: 24px 4px;\n }\n\n .step + .step {\n border-left: 0;\n }\n\n .step:last-child {\n border-bottom: 1px solid var(--line);\n }\n\n .step::before {\n margin-bottom: 16px;\n }\n\n .agent-panel-head,\n .footer-row {\n align-items: flex-start;\n flex-direction: column;\n }\n\n .agent-table th,\n .agent-table td {\n padding-inline: 14px;\n }\n\n .agent-table th:nth-child(4),\n .agent-table td:nth-child(4) {\n display: none;\n }\n\n .footer-links {\n justify-content: flex-start;\n }\n\n .final-call::after {\n right: -140px;\n bottom: -180px;\n }\n}\n\n@media (max-width: 480px) {\n .brand {\n font-size: 16px;\n }\n\n .brand-mark {\n width: 32px;\n height: 32px;\n }\n\n .language-link {\n padding-inline: 10px;\n }\n\n .hero-actions,\n .hero-actions .button {\n width: 100%;\n }\n\n .hero-proof {\n display: grid;\n grid-template-columns: 1fr 1fr;\n }\n\n .launch-visual {\n min-height: 320px;\n }\n\n .terminal {\n border-radius: 17px;\n }\n\n .terminal-bar {\n min-height: 42px;\n }\n\n .terminal-body {\n min-height: 190px;\n font-size: 11px;\n }\n\n .command-head {\n padding-left: 14px;\n }\n\n .copy-button {\n min-width: 82px;\n }\n\n .command-code {\n padding: 19px 14px;\n font-size: 11px;\n }\n\n .feature-spotlight {\n min-height: 330px;\n }\n\n .feature-row {\n grid-template-columns: 34px 1fr;\n gap: 10px;\n }\n\n .agent-table th:first-child,\n .agent-table td:first-child,\n .agent-table th:nth-child(4),\n .agent-table td:nth-child(4) {\n display: none;\n }\n\n .agent-table {\n font-size: 12px;\n }\n\n .agent-table th,\n .agent-table td {\n padding-inline: 10px;\n }\n\n .agent-legend {\n display: none;\n }\n\n .not-found-card {\n box-shadow: 10px 10px 0 var(--sun);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n html {\n scroll-behavior: auto;\n }\n\n *,\n *::before,\n *::after {\n animation-duration: .01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: .01ms !important;\n }\n}\n\n@media print {\n .site-nav,\n .hero-actions,\n .copy-button,\n .final-call,\n .site-footer {\n display: none;\n }\n\n body {\n background: #fff;\n }\n\n .section,\n .hero {\n min-height: auto;\n padding-block: 28px;\n }\n}\n","type":"text/css; charset=utf-8","etag":"\"93e52ab55ce71853\""},"/assets/site.js":{"body":"(function () {\n \"use strict\";\n\n var copyButtons = document.querySelectorAll(\"[data-copy]\");\n\n function legacyCopy(text) {\n var input = document.createElement(\"textarea\");\n input.value = text;\n input.setAttribute(\"readonly\", \"\");\n input.style.position = \"fixed\";\n input.style.opacity = \"0\";\n document.body.appendChild(input);\n input.select();\n var copied = document.execCommand(\"copy\");\n input.remove();\n return copied ? Promise.resolve() : Promise.reject(new Error(\"copy failed\"));\n }\n\n function copyText(text) {\n if (navigator.clipboard && window.isSecureContext) {\n return navigator.clipboard.writeText(text);\n }\n return legacyCopy(text);\n }\n\n copyButtons.forEach(function (button) {\n var idleLabel = button.getAttribute(\"data-label-idle\") || \"Copy\";\n var successLabel = button.getAttribute(\"data-label-success\") || \"Copied\";\n var errorLabel = button.getAttribute(\"data-label-error\") || \"Select command\";\n var label = button.querySelector(\"[data-copy-label]\");\n var timer;\n\n button.addEventListener(\"click\", function () {\n window.clearTimeout(timer);\n copyText(button.getAttribute(\"data-copy\") || \"\").then(function () {\n button.setAttribute(\"data-state\", \"success\");\n label.textContent = successLabel;\n }).catch(function () {\n button.setAttribute(\"data-state\", \"error\");\n label.textContent = errorLabel;\n }).finally(function () {\n timer = window.setTimeout(function () {\n button.removeAttribute(\"data-state\");\n label.textContent = idleLabel;\n }, 1800);\n });\n });\n });\n}());\n","type":"text/javascript; charset=utf-8","etag":"\"e32ad7eff5bfef9a\""},"/assets/favicon.svg":{"body":"\n \n \n\n","type":"image/svg+xml; charset=utf-8","etag":"\"97f7d8aaef171778\""}}); diff --git a/cloudflare/worker.js b/cloudflare/worker.js index a66de95..bd1e53a 100644 --- a/cloudflare/worker.js +++ b/cloudflare/worker.js @@ -1,21 +1,15 @@ /** - * AgentBoot 分发 Worker(Cloudflare Workers 免费版) - * ================================================= - * 绑定:Workers 名称为 boot;自定义域 boot.ide.pub(路由 boot.ide.pub/*) - * 端点: - * GET / 中文说明页 - * GET /install.sh → 转发 GitHub Release 的 install.sh(curl|sh 入口) - * GET /install.ps1 → 转发 GitHub Release 的 install.ps1 - * GET /rel/<文件名> → 转发 GitHub Release 资产(在线/离线安装包) - * GET /gh/main.tar.gz → 转发 codeload 主分支源码包 - * GET /health → 健康检查 - * 说明:*.workers.dev 在中国大陆通常不可直接访问,生产入口请使用 - * 绑定的自定义域 boot.ide.pub(Cloudflare 任播网络)。 + * AgentBoot distribution Worker. + * Pages are generated from pages/ by scripts/sync-web-assets.py. */ +import { WEB_ASSETS } from "./web-assets.js"; + const REPO = "bit-cook/AgentBoot"; const TAG = "v1.1.0"; const GH_REL = `https://github.com/${REPO}/releases/download/${TAG}`; +const ASSET_CACHE = "public, max-age=86400, stale-while-revalidate=604800"; +const PAGE_CACHE = "public, max-age=300, stale-while-revalidate=3600"; export default { async fetch(request) { @@ -57,10 +51,12 @@ export default { : `https://codeload.github.com/${REPO}/tar.gz/refs/heads/main`; return proxy(target, ext === "zip" ? "application/zip" : "application/x-gzip", 300); } - if (path === "/") return page("zh"); - if (path === "/en") return page("en"); - - return text("AgentBoot Worker · 404 Not Found\n试:/install.sh 或 /rel/\n", 404); + if (path === "/") return webResponse(request, "/index.html", PAGE_CACHE); + if (path === "/en") return webResponse(request, "/en/index.html", PAGE_CACHE); + if (path === "/assets/site.css" || path === "/assets/site.js" || path === "/assets/favicon.svg") { + return webResponse(request, path, ASSET_CACHE); + } + return webResponse(request, "/404.html", "no-store", 404); }, }; @@ -86,6 +82,28 @@ async function proxy(target, contentType, cacheTtl, incoming = null) { return new Response(resp.body, { status: resp.status, headers }); } +function webResponse(request, route, cacheControl, status = 200) { + const asset = WEB_ASSETS[route]; + if (request.headers.get("If-None-Match") === asset.etag) { + return new Response(null, { status: 304, headers: webHeaders(asset, cacheControl) }); + } + return new Response(request.method === "HEAD" ? null : asset.body, { + status, + headers: webHeaders(asset, cacheControl), + }); +} + +function webHeaders(asset, cacheControl) { + return { + "Cache-Control": cacheControl, + "Content-Type": asset.type, + "ETag": asset.etag, + "Referrer-Policy": "strict-origin-when-cross-origin", + "X-Content-Type-Options": "nosniff", + "X-Frame-Options": "DENY", + }; +} + function text(body, status = 200) { return new Response(body, { status, @@ -99,339 +117,3 @@ function json(obj, status = 200) { headers: { "Content-Type": "application/json; charset=utf-8", "Access-Control-Allow-Origin": "*" }, }); } - -const PAGE_ZH = ` - - - - -AgentBoot · 一键安装 AI Agent 启动器 - - - - -
- -
-

AgentBoot

-

极简 · 极速 · 开箱即用的 AI Agent 启动器 —— 一条命令装好,主流 Agent 菜单自选

-
- v1.1.0Linux · macOS · Windows界面中文 - 14 个 Agent 自选离线安装中国镜像自适应MIT -
-

中文 | English

-
- -

⚡ 一键安装

-

Linux / macOS

-
curl -fsSL https://boot.ide.pub/install.sh | sh -
-

Windows(PowerShell)

-
powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((New-Object Net.WebClient).DownloadString('https://boot.ide.pub/install.ps1'))" -
-
安装器只使用项目控制的 Worker / GitHub Pages / GitHub Release 三源,并对包与同源 SHA-256 一起校验。
- -

🚀 三步上手

-
    -
  1. 安装 AgentBoot
    上面一条命令,10 秒完成;只会装 AgentBoot 本体与内置 Agent。
  2. -
  3. 打开控制台菜单
    agentboot —— 环境体检 / 安装与卸载 Agent / 模型配置 / 镜像代理 / 自定义离线包。
  4. -
  5. 或直接对话
    ab —— 内置保底 Agent,默认 Agnes 免费模型,零配置开箱即用。
  6. -
- -

✨ 特性

-
-
📦 菜单自选安装(不是全家桶)

14 个主流 Agent 按需勾选:Claude Code、Codex、Qwen Code、OpenCode、CodeBuddy、MiMo、Cline、Pi、CoCo…

-
🛟 内置保底 Agent(ab)

其他都装不上时它一定能用:零第三方依赖 Python 核心、Agnes 免费模型、离线 Linux 知识库、会话持久化。

-
🧠 模型提供商管理器

Agnes 零配置开箱;自定义提供商命名管理;Ollama / LM Studio 本地模型;故障切换顺序。

-
🇨🇳 中国网络自适应

自动切换 npm / Node / PyPI 镜像;Worker / Pages / Release 三源容错;代理一键配置。

-
📴 已验证离线 & 按需构建

Release 精简包通过真实安装、启动与卸载冒烟;菜单 [7] 可在目标平台自选 Agent 构建。

-
🧹 可追溯安全卸载

菜单 [9] 或 uninstall 命令批量卸载;只清理由 AgentBoot 管理的程序,默认保留配置、认证与会话。

-
⚡ 可测性能

TLS 连接复用、知识库预建索引、上下文自动瘦身与流式中断保护;/bench 按当前网络与模型现场测量。

-
- -

🤖 支持的 Agent(14 个)

-
- - - - - - - - - - - - - - - -
#Agent命令厂商离线
1CoCo AgentcocoBitCookLinux/macOS
2OpenCodeopencodeopencode.ai仅在线
3Hermes AgenthermesHermes✓(需 Git)
4Cline CLIclineCline
5CodeBuddy CLIcodebuddyTencent
6Pi Coding AgentpiEarendil Works
7Claude CodeclaudeAnthropic
8OpenAI Codex CLIcodexOpenAI✓(Agnes 预置)
9Qwen CodeqwenAlibaba✓(Agnes 预置)
10MiMo CodemimoXiaomi
11OpenClawopenclawOpenClaw
12Gemini CLIgeminiGoogle
13iFlow CLIiflowiFlow 心流
14AideraiderAider AI仅在线(pip)
-
✓ = 支持离线安装(离线包内置完整依赖与运行时)。Codex / Qwen 安装后自动预置 Agnes 免费模型;自定义 Agent 可通过菜单 +add-agent 命令添加。
- -

📴 离线安装

-

无网机器?两条路:

-
    -
  • 已验证精简包:v1.1.0 首批提供 Linux x64 / Windows x64 的 Codex 包,CI 实际执行安装、版本启动与卸载;
  • -
  • 自建离线包:菜单 [7]build-offline 在目标平台自选 Agent;Hermes 必须在对应平台构建。
  • -
-

目标机无需联网、无需解压软件(Windows 资源管理器 / 系统自带 tar / 自解压脚本三选一),运行包内 install-offline.ps1sh install-offline.sh 即可。

- -

🧠 模型:开箱即用 + 完全自定义

-
    -
  • Agnes 免费模型(官方预设):ab 零配置直接用;Codex / Qwen 安装后自动接线;
  • -
  • 自定义提供商:任意 OpenAI 兼容接口,命名管理、随时增删切换;
  • -
  • 本地模型:内置 Ollama / LM Studio 预设,也可把 vLLM 添加为自定义 OpenAI 兼容提供商;
  • -
  • 故障切换:设置备用顺序,主模型失败自动降级。
  • -
- -

📚 文档

- - - - - - -`; - -const PAGE_EN = ` - - - - -AgentBoot · One-command AI Agent Launcher - - - - -
- -
-

English | 中文

-

AgentBoot

-

Minimal, fast, ready-to-run AI Agent launcher — one command to install, mainstream agents to choose from.

-
- v1.1.0Linux · macOS · WindowsChinese UI default - 14 agentsOffline installChina-network adaptiveMIT -
-
- -

⚡ One-command install

-

Linux / macOS

-
curl -fsSL https://boot.ide.pub/install.sh | sh -
-

Windows (PowerShell)

-
powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((New-Object Net.WebClient).DownloadString('https://boot.ide.pub/install.ps1'))" -
-
The installer uses project-controlled Worker / GitHub Pages / GitHub Release origins and verifies each archive against its same-origin SHA-256.
- -

🚀 Three steps

-
    -
  1. Install AgentBoot
    One command, ~10 seconds; only AgentBoot itself and the built-in agent are installed.
  2. -
  3. Open the console menu
    agentboot — environment check / install or uninstall agents / model providers / mirrors & proxy / custom offline builds.
  4. -
  5. Or just chat
    ab — the built-in fallback agent with the free Agnes model, zero config.
  6. -
- -

✨ Features

-
-
📦 Choose what to install (no bundle bloat)

14 mainstream agents to pick from: Claude Code, Codex, Qwen Code, OpenCode, CodeBuddy, MiMo, Cline, Pi, CoCo…

-
🛟 Built-in fallback agent (ab)

A zero-third-party-dependency Python core with Agnes, an offline Linux knowledge base, and session persistence.

-
🧠 Model provider manager

Agnes out of the box; named custom providers; Ollama / LM Studio local models; failover order.

-
🇨🇳 China network adaptive

npm / Node / PyPI mirrors, Worker/Pages/Release fallback, and one-click proxy configuration.

-
📴 Verified offline & custom builds

Release packs pass real install/run/uninstall smoke tests; menu [7] builds selected Agents on their target platform.

-
🧹 Ownership-aware uninstall

Menu [9] or the uninstall command removes AgentBoot-managed programs in batches while preserving config, credentials, and sessions by default.

-
⚡ Measurable performance

TLS reuse, pre-indexed KB, context trimming, and stream protection; /bench measures the current network and provider.

-
- -

🤖 Supported agents (14)

-
- - - - - - - - - - - - - - - -
#AgentCommandVendorOffline
1CoCo AgentcocoBitCookLinux/macOS
2OpenCodeopencodeopencode.aionline only
3Hermes AgenthermesHermes✓ (needs Git)
4Cline CLIclineCline
5CodeBuddy CLIcodebuddyTencent
6Pi Coding AgentpiEarendil Works
7Claude CodeclaudeAnthropic
8OpenAI Codex CLIcodexOpenAI✓ (Agnes preset)
9Qwen CodeqwenAlibaba✓ (Agnes preset)
10MiMo CodemimoXiaomi
11OpenClawopenclawOpenClaw
12Gemini CLIgeminiGoogle
13iFlow CLIiflowiFlow
14AideraiderAider AIonline only (pip)
-
✓ = offline install supported (dependencies and runtimes bundled). Codex / Qwen are auto-wired to the free Agnes model after install. Add your own agents via menu + or the add-agent command.
- -

📴 Offline install

-

No internet on the target machine? Two options:

-
    -
  • Verified slim packs: v1.1.0 initially provides Linux x64 / Windows x64 Codex packs after CI installs, starts, and uninstalls them;
  • -
  • Custom packs: menu [7] or build-offline on the target platform; Hermes must be built natively.
  • -
-

No unzip software needed (Windows Explorer / system tar / self-extracting script), then run install-offline.ps1 or sh install-offline.sh.

- -

🧠 Models: works out of the box + fully customizable

-
    -
  • Agnes free model (official preset): ab uses it with zero config; Codex / Qwen are auto-wired;
  • -
  • Custom providers: any OpenAI-compatible endpoint, named and managed;
  • -
  • Local models: Ollama / LM Studio presets; add vLLM as a custom OpenAI-compatible provider;
  • -
  • Failover: set a fallback order and the primary failure switches automatically.
  • -
- -

📚 Docs

- - - - - - -`; - -function page(lang) { - const html = lang === "en" ? PAGE_EN : PAGE_ZH; - return new Response(html, { headers: { "Content-Type": "text/html; charset=utf-8" } }); -} diff --git a/pages/404.html b/pages/404.html new file mode 100644 index 0000000..874843f --- /dev/null +++ b/pages/404.html @@ -0,0 +1,25 @@ + + + + + + + + 页面未找到 · AgentBoot + + + + +
+
+ +

这条路径没有 Agent,回到启动台吧

+

地址可能已变更,或只是多输入了一个字符。项目主页、安装命令和文档都还在。

+ +
+
+ + diff --git a/pages/assets/favicon.svg b/pages/assets/favicon.svg new file mode 100644 index 0000000..4919996 --- /dev/null +++ b/pages/assets/favicon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/pages/assets/site.css b/pages/assets/site.css new file mode 100644 index 0000000..e76326e --- /dev/null +++ b/pages/assets/site.css @@ -0,0 +1,1487 @@ +:root { + color-scheme: light; + --ink-950: #12251d; + --ink-800: #294238; + --ink-600: #5b7067; + --ink-400: #91a198; + --paper: #fffdf5; + --surface: #ffffff; + --soft: #f2f7f2; + --line: #dce7df; + --green: #137a52; + --green-dark: #0d5e3e; + --green-soft: #e3f5eb; + --sun: #ffd84d; + --sun-soft: #fff3b9; + --coral: #ff7a59; + --sky: #dff3ff; + --success: #137a52; + --warning: #a65e00; + --error: #b42318; + --info: #176b87; + --code: #10251d; + --code-text: #ecfff4; + --display: ui-rounded, "Avenir Next Rounded", "SF Pro Rounded", "Segoe UI", sans-serif; + --body: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; + --mono: "SFMono-Regular", Consolas, "Liberation Mono", monospace; + --ease: cubic-bezier(.2, .8, .2, 1); +} + +* { + box-sizing: border-box; +} + +html { + overflow-x: clip; + scroll-behavior: smooth; + scroll-padding-top: 88px; +} + +body { + margin: 0; + background: var(--paper); + color: var(--ink-950); + font-family: var(--body); + font-size: 16px; + line-height: 1.68; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; +} + +button, +a { + -webkit-tap-highlight-color: transparent; +} + +a { + color: var(--green-dark); + text-decoration-thickness: 1.5px; + text-underline-offset: .2em; +} + +a:hover { + color: var(--green); +} + +:focus-visible { + outline: 3px solid var(--sun); + outline-offset: 3px; +} + +.skip-link { + position: fixed; + z-index: 100; + top: 12px; + left: 12px; + translate: 0 -150%; + border: 1px solid var(--ink-950); + border-radius: 10px; + background: var(--surface); + color: var(--ink-950); + padding: 10px 14px; + font-weight: 700; +} + +.skip-link:focus { + translate: 0; +} + +.shell { + width: min(1180px, calc(100% - 48px)); + margin-inline: auto; +} + +.site-nav { + position: relative; + z-index: 10; + display: flex; + min-height: 76px; + align-items: center; + justify-content: space-between; + gap: 24px; +} + +.brand { + display: inline-flex; + min-height: 44px; + align-items: center; + gap: 11px; + color: var(--ink-950); + font-family: var(--display); + font-size: 18px; + font-weight: 800; + letter-spacing: -.025em; + text-decoration: none; +} + +.brand-mark { + position: relative; + display: inline-grid; + width: 34px; + height: 34px; + place-items: center; + overflow: hidden; + border: 2px solid var(--ink-950); + border-radius: 11px; + background: var(--sun); +} + +.brand-mark::before, +.brand-mark::after { + content: ""; + position: absolute; + height: 2px; + border-radius: 999px; + background: var(--ink-950); + transform-origin: left center; +} + +.brand-mark::before { + width: 12px; + translate: -1px -3px; + rotate: 38deg; +} + +.brand-mark::after { + width: 10px; + translate: 2px 5px; +} + +.nav-links { + display: flex; + align-items: center; + gap: 6px; +} + +.nav-link, +.language-link { + display: inline-flex; + min-height: 44px; + align-items: center; + justify-content: center; + border-radius: 10px; + color: var(--ink-800); + padding: 8px 11px; + font-size: 14px; + font-weight: 650; + text-decoration: none; +} + +.nav-link:hover, +.language-link:hover { + background: var(--green-soft); + color: var(--green-dark); +} + +.language-link { + border: 1px solid var(--line); + background: rgba(255, 255, 255, .72); +} + +.hero { + position: relative; + display: grid; + min-height: 660px; + align-items: center; + grid-template-columns: minmax(0, 7fr) minmax(340px, 5fr); + gap: clamp(32px, 6vw, 86px); + padding-block: 72px 112px; +} + +.hero::before { + content: ""; + position: absolute; + z-index: -2; + top: 2%; + right: 0; + width: min(48vw, 620px); + aspect-ratio: 1; + border-radius: 50%; + background: var(--sun-soft); +} + +.hero::after { + content: ""; + position: absolute; + z-index: -1; + bottom: 9%; + left: 0; + width: min(30vw, 380px); + aspect-ratio: 1; + border-radius: 50%; + background: var(--sky); + opacity: .7; +} + +.eyebrow { + display: inline-flex; + align-items: center; + gap: 9px; + margin: 0 0 22px; + color: var(--green-dark); + font-size: 13px; + font-weight: 750; + letter-spacing: .08em; + text-transform: uppercase; +} + +.eyebrow::before { + content: ""; + width: 9px; + height: 9px; + border-radius: 50%; + background: var(--coral); + box-shadow: 0 0 0 5px rgba(255, 122, 89, .14); +} + +h1, +h2, +h3 { + font-family: var(--display); + text-wrap: balance; +} + +h1 { + max-width: 800px; + margin: 0; + font-size: clamp(48px, 7.1vw, 88px); + font-weight: 800; + letter-spacing: -.06em; + line-height: .98; +} + +.hero-highlight { + position: relative; + display: inline-block; + white-space: nowrap; +} + +.hero-highlight::after { + content: ""; + position: absolute; + z-index: -1; + right: -.08em; + bottom: .04em; + left: -.02em; + height: .24em; + border-radius: 99px; + background: var(--sun); + rotate: -1.5deg; +} + +.hero-copy { + max-width: 650px; + margin: 28px 0 0; + color: var(--ink-600); + font-size: clamp(17px, 2vw, 21px); + line-height: 1.62; +} + +.hero-actions { + display: flex; + flex-wrap: wrap; + gap: 12px; + margin-top: 34px; +} + +.button { + display: inline-flex; + min-height: 48px; + align-items: center; + justify-content: center; + gap: 9px; + border: 1px solid var(--ink-950); + border-radius: 12px; + padding: 11px 17px; + font-size: 15px; + font-weight: 750; + line-height: 1; + text-decoration: none; + transition: translate 160ms var(--ease), background-color 160ms var(--ease), color 160ms var(--ease); +} + +.button-primary { + background: var(--green); + color: #fff; + border-color: var(--green); +} + +.button-primary:hover { + background: var(--green-dark); + color: #fff; + translate: 0 -2px; +} + +.button-secondary { + background: var(--surface); + color: var(--ink-950); +} + +.button-secondary:hover { + background: var(--sun-soft); + color: var(--ink-950); + translate: 0 -2px; +} + +.button svg, +.text-link svg { + width: 18px; + height: 18px; + flex: 0 0 auto; + fill: none; + stroke: currentColor; + stroke-linecap: round; + stroke-linejoin: round; + stroke-width: 1.8; +} + +.hero-proof { + display: flex; + flex-wrap: wrap; + gap: 10px 18px; + margin: 26px 0 0; + padding: 0; + color: var(--ink-600); + font-size: 13px; + font-weight: 650; + list-style: none; +} + +.hero-proof li { + display: flex; + align-items: center; + gap: 7px; +} + +.hero-proof li::before { + content: ""; + width: 7px; + height: 7px; + border-radius: 50%; + background: var(--green); +} + +.launch-visual { + position: relative; + min-height: 450px; +} + +.orbit { + position: absolute; + inset: 0; + margin: auto; + border: 1px solid rgba(18, 37, 29, .18); + border-radius: 50%; +} + +.orbit-one { + width: min(100%, 430px); + aspect-ratio: 1; +} + +.orbit-two { + width: min(76%, 330px); + aspect-ratio: 1; + border-style: dashed; +} + +.orbit-dot { + position: absolute; + top: 10%; + right: 14%; + width: 18px; + height: 18px; + border: 3px solid var(--paper); + border-radius: 50%; + background: var(--coral); + box-shadow: 0 0 0 1px var(--ink-950); +} + +.terminal { + position: absolute; + inset: 50% auto auto 50%; + width: min(94%, 390px); + overflow: hidden; + border: 2px solid var(--ink-950); + border-radius: 22px; + background: var(--code); + box-shadow: 18px 18px 0 var(--sun); + color: var(--code-text); + translate: -50% -50%; +} + +.terminal-bar { + display: flex; + min-height: 48px; + align-items: center; + justify-content: space-between; + border-bottom: 1px solid rgba(255, 255, 255, .13); + padding: 0 17px; + color: #b9d3c4; + font-family: var(--mono); + font-size: 12px; +} + +.terminal-dots { + display: flex; + gap: 6px; +} + +.terminal-dots i { + width: 8px; + height: 8px; + border-radius: 50%; + background: var(--coral); +} + +.terminal-dots i:nth-child(2) { + background: var(--sun); +} + +.terminal-dots i:nth-child(3) { + background: #57d49b; +} + +.terminal-body { + min-height: 238px; + padding: 26px 22px; + font-family: var(--mono); + font-size: clamp(12px, 1.35vw, 14px); + line-height: 1.8; +} + +.terminal-body p { + margin: 0 0 12px; +} + +.prompt { + color: #69e4a7; +} + +.terminal-muted { + color: #9bb7a8; +} + +.terminal-check { + color: var(--sun); +} + +.section { + padding-block: clamp(72px, 10vw, 120px); +} + +.section-soft { + position: relative; + background: var(--soft); +} + +.section-soft::before, +.section-soft::after { + content: ""; + position: absolute; + right: 0; + left: 0; + height: 1px; + background: var(--line); +} + +.section-soft::before { + top: 0; +} + +.section-soft::after { + bottom: 0; +} + +.section-heading { + display: grid; + align-items: end; + grid-template-columns: minmax(0, 4fr) minmax(280px, 3fr); + gap: 32px; + margin-bottom: 54px; +} + +.kicker { + margin: 0 0 12px; + color: var(--green); + font-size: 13px; + font-weight: 750; + letter-spacing: .08em; + text-transform: uppercase; +} + +h2 { + max-width: 700px; + margin: 0; + font-size: clamp(34px, 4.8vw, 56px); + font-weight: 800; + letter-spacing: -.045em; + line-height: 1.06; +} + +.section-lede { + max-width: 56ch; + margin: 0; + color: var(--ink-600); + font-size: 17px; +} + +.install-layout { + display: grid; + align-items: start; + grid-template-columns: minmax(240px, 4fr) minmax(0, 8fr); + gap: clamp(34px, 7vw, 88px); +} + +.install-intro { + position: sticky; + top: 104px; +} + +.install-intro h2 { + font-size: clamp(34px, 4vw, 48px); +} + +.install-intro p { + color: var(--ink-600); +} + +.security-note { + display: grid; + grid-template-columns: 38px 1fr; + gap: 13px; + margin-top: 28px; + padding-top: 22px; + border-top: 1px solid var(--line); + color: var(--ink-600); + font-size: 14px; +} + +.security-icon { + display: grid; + width: 38px; + height: 38px; + place-items: center; + border-radius: 12px; + background: var(--green-soft); + color: var(--green-dark); +} + +.security-icon svg { + width: 21px; + height: 21px; + fill: none; + stroke: currentColor; + stroke-linecap: round; + stroke-linejoin: round; + stroke-width: 1.8; +} + +.security-note p { + margin: 0; +} + +.command-stack { + display: grid; + gap: 16px; +} + +.command-card { + overflow: hidden; + border: 1px solid var(--ink-950); + border-radius: 20px; + background: var(--surface); +} + +.command-head { + display: flex; + min-height: 56px; + align-items: center; + justify-content: space-between; + gap: 12px; + border-bottom: 1px solid var(--line); + padding: 10px 12px 10px 20px; +} + +.command-platform { + display: flex; + align-items: center; + gap: 11px; + font-weight: 750; +} + +.platform-dot { + width: 10px; + height: 10px; + border-radius: 50%; + background: var(--coral); +} + +.command-card:nth-child(2) .platform-dot { + background: #2f80ed; +} + +.copy-button { + display: inline-flex; + min-width: 90px; + min-height: 44px; + align-items: center; + justify-content: center; + gap: 7px; + border: 1px solid var(--line); + border-radius: 10px; + background: var(--soft); + color: var(--ink-950); + padding: 8px 12px; + font: 700 13px/1 var(--body); + cursor: pointer; + transition: background-color 160ms var(--ease), border-color 160ms var(--ease); +} + +.copy-button:hover { + border-color: var(--green); + background: var(--green-soft); +} + +.copy-button[data-state="success"] { + border-color: var(--green); + background: var(--green-soft); + color: var(--green-dark); +} + +.copy-button[data-state="error"] { + border-color: var(--error); + background: #fff0ed; + color: var(--error); +} + +.copy-button svg { + width: 16px; + height: 16px; + fill: none; + stroke: currentColor; + stroke-linecap: round; + stroke-linejoin: round; + stroke-width: 1.8; +} + +.command-code { + display: block; + margin: 0; + overflow-x: auto; + background: var(--code); + color: var(--code-text); + padding: 24px 20px; + font-family: var(--mono); + font-size: 13px; + line-height: 1.75; + white-space: pre; + scrollbar-color: #557266 var(--code); +} + +.command-code::selection, +.terminal ::selection { + background: var(--sun); + color: var(--ink-950); +} + +.steps { + display: grid; + margin: 48px 0 0; + padding: 0; + counter-reset: step; + grid-template-columns: repeat(3, minmax(0, 1fr)); + list-style: none; +} + +.step { + position: relative; + min-height: 180px; + padding: 30px clamp(20px, 3vw, 34px); + counter-increment: step; + border-top: 1px solid var(--line); + border-bottom: 1px solid var(--line); +} + +.step + .step { + border-left: 1px solid var(--line); +} + +.step::before { + content: "0" counter(step); + display: block; + margin-bottom: 30px; + color: var(--coral); + font: 750 13px/1 var(--mono); +} + +.step h3 { + margin: 0 0 8px; + font-size: 19px; + font-weight: 750; + letter-spacing: -.02em; +} + +.step p { + margin: 0; + color: var(--ink-600); + font-size: 14px; +} + +.inline-code, +.rich-text code, +.agent-table code, +.feature-row code { + border: 1px solid var(--line); + border-radius: 6px; + background: var(--surface); + color: var(--green-dark); + padding: .12em .42em; + font-family: var(--mono); + font-size: .88em; +} + +.feature-layout { + display: grid; + align-items: start; + grid-template-columns: minmax(280px, 5fr) minmax(0, 7fr); + gap: clamp(40px, 8vw, 100px); +} + +.feature-spotlight { + position: sticky; + top: 104px; + overflow: hidden; + border: 1px solid var(--ink-950); + border-radius: 24px; + background: var(--sun); + padding: clamp(28px, 4vw, 44px); +} + +.feature-spotlight::after { + content: "ab"; + position: absolute; + right: 0; + bottom: -58px; + color: rgba(18, 37, 29, .09); + font: 800 clamp(120px, 18vw, 220px)/1 var(--display); + letter-spacing: -.08em; +} + +.feature-spotlight .kicker { + color: var(--ink-800); +} + +.feature-spotlight h3 { + max-width: 470px; + margin: 0; + font-size: clamp(30px, 4vw, 48px); + font-weight: 800; + letter-spacing: -.045em; + line-height: 1.08; +} + +.feature-spotlight p { + position: relative; + z-index: 1; + max-width: 48ch; + margin: 24px 0 0; + color: var(--ink-800); +} + +.feature-list { + margin: 0; + padding: 0; + list-style: none; +} + +.feature-row { + display: grid; + padding: 25px 0 28px; + border-top: 1px solid var(--line); + grid-template-columns: 44px 1fr; + gap: 18px; +} + +.feature-row:last-child { + border-bottom: 1px solid var(--line); +} + +.feature-index { + color: var(--green); + font: 750 12px/1.5 var(--mono); +} + +.feature-row h3 { + margin: -4px 0 7px; + font-size: 20px; + font-weight: 750; + letter-spacing: -.025em; +} + +.feature-row p { + max-width: 60ch; + margin: 0; + color: var(--ink-600); + font-size: 14px; +} + +.agent-panel { + overflow: hidden; + border: 1px solid var(--ink-950); + border-radius: 24px; + background: var(--surface); +} + +.agent-panel-head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 20px; + border-bottom: 1px solid var(--line); + padding: 20px 24px; +} + +.agent-count { + display: flex; + align-items: baseline; + gap: 9px; +} + +.agent-count strong { + font: 800 38px/1 var(--display); + letter-spacing: -.04em; +} + +.agent-count span, +.agent-legend { + color: var(--ink-600); + font-size: 13px; +} + +.table-scroll { + max-width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; +} + +.agent-table { + width: 100%; + border-collapse: collapse; + font-size: 14px; +} + +.agent-table th, +.agent-table td { + min-height: 52px; + padding: 14px 20px; + border-bottom: 1px solid var(--line); + text-align: left; + vertical-align: middle; +} + +.agent-table th { + background: var(--soft); + color: var(--ink-600); + font-size: 12px; + font-weight: 750; + letter-spacing: .04em; + text-transform: uppercase; +} + +.agent-table tr:last-child td { + border-bottom: 0; +} + +.agent-table tbody tr:hover { + background: #fffdf3; +} + +.agent-name { + font-weight: 750; +} + +.status { + display: inline-flex; + align-items: center; + gap: 7px; + white-space: nowrap; +} + +.status::before { + content: ""; + width: 7px; + height: 7px; + border-radius: 50%; + background: var(--ink-400); +} + +.status-ready { + color: var(--success); + font-weight: 650; +} + +.status-ready::before { + background: var(--success); +} + +.agent-footnote { + margin: 0; + border-top: 1px solid var(--line); + background: var(--sun-soft); + color: var(--ink-800); + padding: 16px 22px; + font-size: 13px; +} + +.detail-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 1px; + border: 1px solid var(--line); + background: var(--line); +} + +.detail-block { + min-height: 320px; + background: var(--paper); + padding: clamp(30px, 5vw, 58px); +} + +.detail-block:nth-child(2) { + background: var(--sky); +} + +.detail-block h3 { + max-width: 470px; + margin: 0 0 20px; + font-size: clamp(27px, 3vw, 38px); + font-weight: 800; + letter-spacing: -.04em; + line-height: 1.1; +} + +.rich-text { + color: var(--ink-800); +} + +.rich-text p { + margin: 0 0 16px; +} + +.rich-text ul { + margin: 0; + padding: 0; + list-style: none; +} + +.rich-text li { + position: relative; + padding: 11px 0 11px 24px; + border-top: 1px solid rgba(18, 37, 29, .15); +} + +.rich-text li::before { + content: ""; + position: absolute; + top: 20px; + left: 2px; + width: 8px; + height: 8px; + border-radius: 2px; + background: var(--green); + rotate: 45deg; +} + +.docs-list { + display: grid; + margin: 0; + padding: 0; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 12px; + list-style: none; +} + +.docs-link { + display: flex; + min-height: 128px; + flex-direction: column; + justify-content: space-between; + gap: 24px; + border: 1px solid var(--line); + border-radius: 18px; + background: var(--surface); + color: var(--ink-950); + padding: 22px; + text-decoration: none; + transition: border-color 160ms var(--ease), translate 160ms var(--ease); +} + +.docs-link:hover { + border-color: var(--green); + color: var(--green-dark); + translate: 0 -3px; +} + +.docs-link strong { + font-size: 16px; +} + +.docs-link span { + color: var(--ink-600); + font-size: 13px; +} + +.text-link { + display: inline-flex; + align-items: center; + gap: 7px; + font-weight: 750; +} + +.final-call { + position: relative; + overflow: hidden; + contain: paint; + border: 1px solid var(--ink-950); + border-radius: 28px; + background: var(--green); + color: #fff; + padding: clamp(36px, 7vw, 76px); +} + +.final-call::after { + content: ""; + position: absolute; + right: -80px; + bottom: -120px; + width: 320px; + height: 320px; + border: 58px solid var(--sun); + border-radius: 50%; + opacity: .98; +} + +.final-call h2 { + position: relative; + z-index: 1; + max-width: 700px; + font-size: clamp(36px, 6vw, 66px); +} + +.final-call p { + position: relative; + z-index: 1; + max-width: 55ch; + margin: 22px 0 0; + color: #dff8e9; + font-size: 17px; +} + +.final-call .hero-actions { + position: relative; + z-index: 1; +} + +.final-call .button-primary { + border-color: var(--sun); + background: var(--sun); + color: var(--ink-950); +} + +.final-call .button-primary:hover { + border-color: #ffe277; + background: #ffe277; + color: var(--ink-950); +} + +.final-call .button-secondary { + border-color: rgba(255, 255, 255, .5); + background: transparent; + color: #fff; +} + +.final-call .button-secondary:hover { + border-color: #fff; + background: rgba(255, 255, 255, .1); + color: #fff; +} + +.site-footer { + padding-block: 34px 44px; +} + +.footer-row { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 30px; +} + +.footer-note { + max-width: 680px; + margin: 13px 0 0; + color: var(--ink-600); + font-size: 13px; +} + +.footer-links { + display: flex; + flex-wrap: wrap; + justify-content: flex-end; + gap: 6px 18px; + font-size: 13px; + font-weight: 650; +} + +.footer-links a { + min-height: 44px; + display: inline-flex; + align-items: center; +} + +.not-found { + display: grid; + min-height: 100svh; + place-items: center; + padding: 40px 24px; +} + +.not-found-card { + position: relative; + width: min(720px, 100%); + overflow: hidden; + border: 1px solid var(--ink-950); + border-radius: 28px; + background: var(--surface); + padding: clamp(32px, 8vw, 72px); + box-shadow: 18px 18px 0 var(--sun); +} + +.not-found-code { + margin: 0 0 28px; + color: var(--coral); + font: 800 clamp(60px, 15vw, 132px)/.8 var(--display); + letter-spacing: -.07em; +} + +.not-found h1 { + max-width: 620px; + font-size: clamp(34px, 7vw, 58px); + line-height: 1.06; +} + +.not-found p { + max-width: 50ch; + margin: 22px 0 0; + color: var(--ink-600); +} + +@media (prefers-reduced-motion: no-preference) { + .hero-copy, + .hero-actions, + .hero-proof { + animation: rise-in 620ms var(--ease) both; + } + + .hero-actions { + animation-delay: 100ms; + } + + .hero-proof { + animation-delay: 180ms; + } + + .terminal { + animation: terminal-in 720ms 80ms var(--ease) both; + } + + .orbit-dot { + animation: pulse 2.8s var(--ease) infinite; + } + + @keyframes rise-in { + from { opacity: 0; translate: 0 16px; } + to { opacity: 1; translate: 0; } + } + + @keyframes terminal-in { + from { opacity: 0; translate: -46% -46%; } + to { opacity: 1; translate: -50% -50%; } + } + + @keyframes pulse { + 50% { scale: 1.14; } + } +} + +@media (max-width: 900px) { + .hero { + min-height: auto; + grid-template-columns: 1fr; + padding-block: 54px 90px; + } + + .launch-visual { + min-height: 410px; + } + + .section-heading, + .install-layout, + .feature-layout { + grid-template-columns: 1fr; + } + + .install-intro, + .feature-spotlight { + position: static; + } + + .install-intro { + display: grid; + align-items: end; + grid-template-columns: 1fr 1fr; + gap: 30px; + } + + .security-note { + margin: 0; + } + + .feature-spotlight { + min-height: 310px; + } +} + +@media (max-width: 720px) { + .shell { + width: min(100% - 32px, 1180px); + } + + .site-nav { + min-height: 68px; + } + + .nav-link { + display: none; + } + + .hero { + gap: 42px; + padding-top: 46px; + } + + h1 { + font-size: clamp(44px, 14vw, 68px); + } + + .hero-copy { + font-size: 17px; + } + + .launch-visual { + min-height: 350px; + } + + .orbit-one { + width: min(94%, 350px); + } + + .orbit-two { + width: min(72%, 270px); + } + + .terminal { + box-shadow: 11px 11px 0 var(--sun); + } + + .terminal-body { + min-height: 210px; + padding: 22px 18px; + } + + .section-heading { + align-items: start; + gap: 18px; + margin-bottom: 38px; + } + + .install-intro { + display: block; + } + + .security-note { + margin-top: 24px; + } + + .steps, + .detail-grid, + .docs-list { + grid-template-columns: 1fr; + } + + .step { + min-height: auto; + border-bottom: 0; + padding: 24px 4px; + } + + .step + .step { + border-left: 0; + } + + .step:last-child { + border-bottom: 1px solid var(--line); + } + + .step::before { + margin-bottom: 16px; + } + + .agent-panel-head, + .footer-row { + align-items: flex-start; + flex-direction: column; + } + + .agent-table th, + .agent-table td { + padding-inline: 14px; + } + + .agent-table th:nth-child(4), + .agent-table td:nth-child(4) { + display: none; + } + + .footer-links { + justify-content: flex-start; + } + + .final-call::after { + right: -140px; + bottom: -180px; + } +} + +@media (max-width: 480px) { + .brand { + font-size: 16px; + } + + .brand-mark { + width: 32px; + height: 32px; + } + + .language-link { + padding-inline: 10px; + } + + .hero-actions, + .hero-actions .button { + width: 100%; + } + + .hero-proof { + display: grid; + grid-template-columns: 1fr 1fr; + } + + .launch-visual { + min-height: 320px; + } + + .terminal { + border-radius: 17px; + } + + .terminal-bar { + min-height: 42px; + } + + .terminal-body { + min-height: 190px; + font-size: 11px; + } + + .command-head { + padding-left: 14px; + } + + .copy-button { + min-width: 82px; + } + + .command-code { + padding: 19px 14px; + font-size: 11px; + } + + .feature-spotlight { + min-height: 330px; + } + + .feature-row { + grid-template-columns: 34px 1fr; + gap: 10px; + } + + .agent-table th:first-child, + .agent-table td:first-child, + .agent-table th:nth-child(4), + .agent-table td:nth-child(4) { + display: none; + } + + .agent-table { + font-size: 12px; + } + + .agent-table th, + .agent-table td { + padding-inline: 10px; + } + + .agent-legend { + display: none; + } + + .not-found-card { + box-shadow: 10px 10px 0 var(--sun); + } +} + +@media (prefers-reduced-motion: reduce) { + html { + scroll-behavior: auto; + } + + *, + *::before, + *::after { + animation-duration: .01ms !important; + animation-iteration-count: 1 !important; + transition-duration: .01ms !important; + } +} + +@media print { + .site-nav, + .hero-actions, + .copy-button, + .final-call, + .site-footer { + display: none; + } + + body { + background: #fff; + } + + .section, + .hero { + min-height: auto; + padding-block: 28px; + } +} diff --git a/pages/assets/site.js b/pages/assets/site.js new file mode 100644 index 0000000..6072760 --- /dev/null +++ b/pages/assets/site.js @@ -0,0 +1,49 @@ +(function () { + "use strict"; + + var copyButtons = document.querySelectorAll("[data-copy]"); + + function legacyCopy(text) { + var input = document.createElement("textarea"); + input.value = text; + input.setAttribute("readonly", ""); + input.style.position = "fixed"; + input.style.opacity = "0"; + document.body.appendChild(input); + input.select(); + var copied = document.execCommand("copy"); + input.remove(); + return copied ? Promise.resolve() : Promise.reject(new Error("copy failed")); + } + + function copyText(text) { + if (navigator.clipboard && window.isSecureContext) { + return navigator.clipboard.writeText(text); + } + return legacyCopy(text); + } + + copyButtons.forEach(function (button) { + var idleLabel = button.getAttribute("data-label-idle") || "Copy"; + var successLabel = button.getAttribute("data-label-success") || "Copied"; + var errorLabel = button.getAttribute("data-label-error") || "Select command"; + var label = button.querySelector("[data-copy-label]"); + var timer; + + button.addEventListener("click", function () { + window.clearTimeout(timer); + copyText(button.getAttribute("data-copy") || "").then(function () { + button.setAttribute("data-state", "success"); + label.textContent = successLabel; + }).catch(function () { + button.setAttribute("data-state", "error"); + label.textContent = errorLabel; + }).finally(function () { + timer = window.setTimeout(function () { + button.removeAttribute("data-state"); + label.textContent = idleLabel; + }, 1800); + }); + }); + }); +}()); diff --git a/pages/en/index.html b/pages/en/index.html index 9bb8216..bd63708 100644 --- a/pages/en/index.html +++ b/pages/en/index.html @@ -1,164 +1,255 @@ - - -AgentBoot · One-command AI Agent Launcher - - + + + + + AgentBoot · Launch your AI agents with one command + + + + + + + -
- -
-

English | 中文

-

AgentBoot

-

Minimal, fast, ready-to-run AI Agent launcher — one command to install, mainstream agents to choose from.

-
- v1.1.0Linux · macOS · WindowsChinese UI default - 14 agentsOffline installChina-network adaptiveMIT -
-
- -

⚡ One-command install

-

Linux / macOS

-
curl -fsSL https://boot.ide.pub/install.sh | sh -
-

Windows (PowerShell)

-
powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((New-Object Net.WebClient).DownloadString('https://boot.ide.pub/install.ps1'))" -
-
The installer uses project-controlled Worker / GitHub Pages / GitHub Release origins and verifies each archive against its same-origin SHA-256.
- -

🚀 Three steps

-
    -
  1. Install AgentBoot
    One command, ~10 seconds; only AgentBoot itself and the built-in agent are installed.
  2. -
  3. Open the console menu
    agentboot — environment check / install or uninstall agents / model providers / mirrors & proxy / custom offline builds.
  4. -
  5. Or just chat
    ab — the built-in fallback agent with the free Agnes model, zero config.
  6. -
- -

✨ Features

-
-
📦 Choose what to install (no bundle bloat)

14 mainstream agents to pick from: Claude Code, Codex, Qwen Code, OpenCode, CodeBuddy, MiMo, Cline, Pi, CoCo…

-
🛟 Built-in fallback agent (ab)

A zero-third-party-dependency Python core with Agnes, an offline Linux knowledge base, and session persistence.

-
🧠 Model provider manager

Agnes out of the box; named custom providers; Ollama / LM Studio local models; failover order.

-
🇨🇳 China network adaptive

npm / Node / PyPI mirrors, Worker/Pages/Release fallback, and one-click proxy configuration.

-
📴 Verified offline & custom builds

Release packs pass real install/run/uninstall smoke tests; menu [7] builds selected Agents on their target platform.

-
🧹 Ownership-aware uninstall

Menu [9] or the uninstall command removes AgentBoot-managed programs in batches while preserving config, credentials, and sessions by default.

-
⚡ Measurable performance

TLS reuse, pre-indexed KB, context trimming, and stream protection; /bench measures the current network and provider.

-
- -

🤖 Supported agents (14)

-
- - - - - - - - - - - - - - - -
#AgentCommandVendorOffline
1CoCo AgentcocoBitCookLinux/macOS
2OpenCodeopencodeopencode.aionline only
3Hermes AgenthermesHermes✓ (needs Git)
4Cline CLIclineCline
5CodeBuddy CLIcodebuddyTencent
6Pi Coding AgentpiEarendil Works
7Claude CodeclaudeAnthropic
8OpenAI Codex CLIcodexOpenAI✓ (Agnes preset)
9Qwen CodeqwenAlibaba✓ (Agnes preset)
10MiMo CodemimoXiaomi
11OpenClawopenclawOpenClaw
12Gemini CLIgeminiGoogle
13iFlow CLIiflowiFlow
14AideraiderAider AIonline only (pip)
-
✓ = offline install supported (dependencies and runtimes bundled). Codex / Qwen are auto-wired to the free Agnes model after install. Add your own agents via menu + or the add-agent command.
- -

📴 Offline install

-

No internet on the target machine? Two options:

-
    -
  • Verified slim packs: v1.1.0 initially provides Linux x64 / Windows x64 Codex packs after CI installs, starts, and uninstalls them;
  • -
  • Custom packs: menu [7] or build-offline on the target platform; Hermes must be built natively.
  • -
-

No unzip software needed (Windows Explorer / system tar / self-extracting script), then run install-offline.ps1 or sh install-offline.sh.

- -

🧠 Models: works out of the box + fully customizable

-
    -
  • Agnes free model (official preset): ab uses it with zero config; Codex / Qwen are auto-wired;
  • -
  • Custom providers: any OpenAI-compatible endpoint, named and managed;
  • -
  • Local models: Ollama / LM Studio presets; add vLLM as a custom OpenAI-compatible provider;
  • -
  • Failover: set a fallback order and the primary failure switches automatically.
  • -
- -

📚 Docs

- - - - - + + + + +
+
+

v1.1.0 · Free and open source · Three platforms

+

One command.
Agents ready.

+

Bring installation, models, mirrors, offline packs, and safe uninstall into one clear menu. You choose the AI agents you need; AgentBoot installs them reliably.

+ +
    +
  • Choose from 14 agents
  • +
  • Linux · macOS · Windows
  • +
  • Offline installation
  • +
  • MIT License
  • +
+
+ +
+ + + +
+
+ + agentboot +
+
+

$ agentboot

+

Checking system and network…

+

Choose the agents you want to install

+

Verify source and SHA-256

+

Ready. Start building.

+
+
+
+
+ +
+
+
+
+
+

Start here

+

Copy one line. Start right away.

+

After installation, run agentboot to open the console menu, or ab to chat directly with the built-in agent.

+
+
+ +

The installer uses only project-controlled Worker, GitHub Pages, and GitHub Release sources, then verifies each installation package against a same-origin SHA-256 checksum.

+
+
+ +
+
+
+ Linux / macOS + +
+ curl -fsSL https://boot.ide.pub/install.sh | sh +
+ +
+
+ Windows PowerShell + +
+ powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((New-Object Net.WebClient).DownloadString('https://boot.ide.pub/install.ps1'))" +
+
+
+ +
    +
  1. Install AgentBoot

    The command above takes about 10 seconds and installs only AgentBoot itself and the built-in agent.

  2. +
  3. Choose the agents you need

    Run agentboot to install, uninstall, and configure agents from the menu.

  4. +
  5. Get to work

    Launch your chosen agent, or run ab for a zero-configuration chat.

  6. +
+
+ +
+
+

More than an install script

AgentBoot handles the complexity. You make the choices.

+

No all-in-one bundle, and no failed setup left for you to debug. AgentBoot handles the parts most likely to break: environments, networks, sources, and uninstall boundaries.

+
+ +
+
+

A starting point that's always ready

+

Even if other agents won't install, ab works right away

+

The built-in agent uses a Python core with no third-party dependencies, the free Agnes model by default, an offline Linux knowledge base, persistent sessions, and safeguards against high-risk commands.

+
+ +
    +
  1. 01

    Install on demand, not as a bundle

    Choose from 14 mainstream agents, including Claude Code, Codex, Qwen Code, OpenCode, MiMo, Cline, Pi, and CoCo.

  2. +
  3. 02

    Manage model providers in one place

    Agnes works with zero configuration. You can also name and manage any OpenAI-compatible endpoint, Ollama, or LM Studio, and set a failover order.

  4. +
  5. 03

    Automatically adapt to networks in China

    AgentBoot selects npm, Node, and PyPI mirrors automatically, fails over across Worker, Pages, and Release sources, and configures a proxy in one step.

  6. +
  7. 04

    Offline packs are tested end to end

    Release packs pass install, launch, and uninstall smoke tests; menu [7] can also build a custom pack on demand on the target platform.

  8. +
  9. 05

    Uninstall only what AgentBoot owns

    Menu [9] or uninstall removes AgentBoot-managed programs while keeping configuration, credentials, and sessions by default.

  10. +
  11. 06

    Measure performance where it matters

    AgentBoot reuses TLS connections, prebuilds knowledge-base indexes, trims context automatically, and protects interrupted streams. /bench measures your current network and model.

  12. +
+
+
+ +
+
+
+

Your toolbox

14 agents. One front door.

+

Choose agents as needed for online installation. Agents marked as offline-ready can be packaged with their dependencies and runtimes.

+
+ +
+
+
14built-in choices
+ A green dot indicates support for offline installation +
+
+ + + + + + + + + + + + + + + + + + +
#AgentCommandVendorOffline
01CoCo AgentcocoBitCookLinux/macOS
02OpenCodeopencodeopencode.aiOnline only
03Hermes AgenthermesHermesRequires Git
04Cline CLIclineClineSupported
05CodeBuddy CLIcodebuddyTencentSupported
06Pi Coding AgentpiEarendil WorksSupported
07Claude CodeclaudeAnthropicSupported
08OpenAI Codex CLIcodexOpenAIAgnes preset
09Qwen CodeqwenAlibabaAgnes preset
10MiMo CodemimoXiaomiSupported
11OpenClawopenclawOpenClawSupported
12Gemini CLIgeminiGoogleSupported
13iFlow CLIiflowiFlowSupported
14AideraiderAider AIOnline only
+
+

Codex and Qwen are automatically configured with the free Agnes model after installation. Add your own agent with menu + or the add-agent command.

+
+
+
+ +
+
+
+

Install without internet access

+

Verified offline packs bring the complete runtime with you

+

v1.1.0 initially provides slim Codex packs for Linux x64 and Windows x64. CI installs each pack, runs its version command, and uninstalls it.

+
    +
  • Verified slim packs: download from Releases and carry them to the target machine.
  • +
  • Custom offline packs: use menu [7] or build-offline on the target platform.
  • +
  • No extra extraction software: run install-offline.ps1 or sh install-offline.sh inside the pack.
  • +
+
+ +
+

Your models, your choice

+

Ready out of the box and fully customizable

+
    +
  • Agnes free model: use ab with zero setup; Codex and Qwen are configured automatically.
  • +
  • Custom providers: name, manage, and switch any OpenAI-compatible endpoint.
  • +
  • Local models: Ollama and LM Studio presets, with vLLM available as a custom provider.
  • +
  • Failover: set a fallback order and switch automatically when the primary fails.
  • +
+
+
+
+ +
+
+
+

More detail when you need it

Documentation that speaks plainly

+

Start with the problem in front of you, from installation and offline deployment to custom agents.

+
+ +
+
+ +
+
+

Spend less time wrestling with setup. Start building sooner.

+

AgentBoot is open source under the MIT License. Start with one command; every choice stays in your hands.

+ +
+
+
+ + diff --git a/pages/index.html b/pages/index.html index bcf0cd0..67bde04 100644 --- a/pages/index.html +++ b/pages/index.html @@ -1,164 +1,255 @@ - - -AgentBoot · 一键安装 AI Agent 启动器 - - + + + + + AgentBoot · 一条命令,启动你的 AI Agent + + + + + + + -
- -
-

AgentBoot

-

极简 · 极速 · 开箱即用的 AI Agent 启动器 —— 一条命令装好,主流 Agent 菜单自选

-
- v1.1.0Linux · macOS · Windows界面中文 - 14 个 Agent 自选离线安装中国镜像自适应MIT -
-

中文 | English

-
- -

⚡ 一键安装

-

Linux / macOS

-
curl -fsSL https://boot.ide.pub/install.sh | sh -
-

Windows(PowerShell)

-
powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((New-Object Net.WebClient).DownloadString('https://boot.ide.pub/install.ps1'))" -
-
安装器只使用项目控制的 Worker / GitHub Pages / GitHub Release 三源,并对包与同源 SHA-256 一起校验。
- -

🚀 三步上手

-
    -
  1. 安装 AgentBoot
    上面一条命令,10 秒完成;只会装 AgentBoot 本体与内置 Agent。
  2. -
  3. 打开控制台菜单
    agentboot —— 环境体检 / 安装与卸载 Agent / 模型配置 / 镜像代理 / 自定义离线包。
  4. -
  5. 或直接对话
    ab —— 内置保底 Agent,默认 Agnes 免费模型,零配置开箱即用。
  6. -
- -

✨ 特性

-
-
📦 菜单自选安装(不是全家桶)

14 个主流 Agent 按需勾选:Claude Code、Codex、Qwen Code、OpenCode、CodeBuddy、MiMo、Cline、Pi、CoCo…

-
🛟 内置保底 Agent(ab)

其他都装不上时它一定能用:零第三方依赖 Python 核心、Agnes 免费模型、离线 Linux 知识库、会话持久化。

-
🧠 模型提供商管理器

Agnes 零配置开箱;自定义提供商命名管理;Ollama / LM Studio 本地模型;故障切换顺序。

-
🇨🇳 中国网络自适应

自动切换 npm / Node / PyPI 镜像;Worker / Pages / Release 三源容错;代理一键配置。

-
📴 已验证离线 & 按需构建

Release 精简包通过真实安装、启动与卸载冒烟;菜单 [7] 可在目标平台自选 Agent 构建。

-
🧹 可追溯安全卸载

菜单 [9] 或 uninstall 命令批量卸载;只清理由 AgentBoot 管理的程序,默认保留配置、认证与会话。

-
⚡ 可测性能

TLS 连接复用、知识库预建索引、上下文自动瘦身与流式中断保护;/bench 按当前网络与模型现场测量。

-
- -

🤖 支持的 Agent(14 个)

-
- - - - - - - - - - - - - - - -
#Agent命令厂商离线
1CoCo AgentcocoBitCookLinux/macOS
2OpenCodeopencodeopencode.ai仅在线
3Hermes AgenthermesHermes✓(需 Git)
4Cline CLIclineCline
5CodeBuddy CLIcodebuddyTencent
6Pi Coding AgentpiEarendil Works
7Claude CodeclaudeAnthropic
8OpenAI Codex CLIcodexOpenAI✓(Agnes 预置)
9Qwen CodeqwenAlibaba✓(Agnes 预置)
10MiMo CodemimoXiaomi
11OpenClawopenclawOpenClaw
12Gemini CLIgeminiGoogle
13iFlow CLIiflowiFlow 心流
14AideraiderAider AI仅在线(pip)
-
✓ = 支持离线安装(离线包内置完整依赖与运行时)。Codex / Qwen 安装后自动预置 Agnes 免费模型;自定义 Agent 可通过菜单 +add-agent 命令添加。
- -

📴 离线安装

-

无网机器?两条路:

-
    -
  • 已验证精简包:v1.1.0 首批提供 Linux x64 / Windows x64 的 Codex 包,CI 实际执行安装、版本启动与卸载;
  • -
  • 自建离线包:菜单 [7]build-offline 在目标平台自选 Agent;Hermes 必须在对应平台构建。
  • -
-

目标机无需联网、无需解压软件(Windows 资源管理器 / 系统自带 tar / 自解压脚本三选一),运行包内 install-offline.ps1sh install-offline.sh 即可。

- -

🧠 模型:开箱即用 + 完全自定义

-
    -
  • Agnes 免费模型(官方预设):ab 零配置直接用;Codex / Qwen 安装后自动接线;
  • -
  • 自定义提供商:任意 OpenAI 兼容接口,命名管理、随时增删切换;
  • -
  • 本地模型:内置 Ollama / LM Studio 预设,也可把 vLLM 添加为自定义 OpenAI 兼容提供商;
  • -
  • 故障切换:设置备用顺序,主模型失败自动降级。
  • -
- -

📚 文档

- - -
- MIT License · github.com/bit-cook/AgentBoot - · 主入口 boot.ide.pub(Cloudflare) - · 本页为 GitHub Pages 镜像入口 -
ab 内置 Agent 默认使用 Agnes 免费模型;执行命令类操作默认拦截高危行为。 -
- - + + + + +
+
+

v1.1.0 · 免费开源 · 三平台可用

+

一条命令,
Agent 就位

+

把安装、模型、镜像、离线包和安全卸载收进一个清楚的菜单。你选择要用的 AI Agent,AgentBoot 负责把它可靠地装好。

+ +
    +
  • 14 个 Agent 按需选择
  • +
  • Linux · macOS · Windows
  • +
  • 离线安装
  • +
  • MIT License
  • +
+
+ +
+ + + +
+
+ + agentboot +
+
+

$ agentboot

+

检查系统环境与网络…

+

选择你想安装的 Agent

+

校验来源与 SHA-256

+

安装完成,开始创造。

+
+
+
+
+ +
+
+
+
+
+

从这里开始

+

复制一行,马上启动

+

安装完成后输入 agentboot 打开控制台菜单,或输入 ab 直接与内置 Agent 对话。

+
+
+ +

安装器仅使用项目控制的 Worker、GitHub Pages 与 GitHub Release,并对安装包执行同源 SHA-256 校验。

+
+
+ +
+
+
+ Linux / macOS + +
+ curl -fsSL https://boot.ide.pub/install.sh | sh +
+ +
+
+ Windows PowerShell + +
+ powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((New-Object Net.WebClient).DownloadString('https://boot.ide.pub/install.ps1'))" +
+
+
+ +
    +
  1. 安装 AgentBoot

    上面一条命令约 10 秒完成,只安装 AgentBoot 本体与内置 Agent。

  2. +
  3. 选择需要的 Agent

    运行 agentboot,在菜单中安装、卸载和配置。

  4. +
  5. 开始工作

    运行选好的 Agent;也可以直接输入 ab 零配置对话。

  6. +
+
+ +
+
+

不仅是安装脚本

复杂留在里面,选择留给你

+

不塞给你一个全家桶,也不把失败留给你排查。AgentBoot 把最容易出错的环境、网络、来源与卸载边界统一处理。

+
+ +
+
+

始终可用的起点

+

即使其他 Agent 装不上,ab 也能马上工作

+

零第三方依赖 Python 核心,默认接入 Agnes 免费模型,并内置离线 Linux 知识库、会话持久化和高危命令拦截。

+
+ +
    +
  1. 01

    按需安装,不装全家桶

    14 个主流 Agent 自由选择:Claude Code、Codex、Qwen Code、OpenCode、MiMo、Cline、Pi、CoCo 等。

  2. +
  3. 02

    模型提供商统一管理

    Agnes 零配置可用,也支持命名管理任意 OpenAI 兼容接口、Ollama、LM Studio 与故障切换顺序。

  4. +
  5. 03

    中国网络自动适配

    自动选择 npm、Node、PyPI 镜像,Worker、Pages、Release 三源容错,并提供一键代理配置。

  6. +
  7. 04

    离线包经过真实验证

    发布包完成安装、启动、卸载冒烟;菜单 [7] 还能在目标平台按需构建自定义包。

  8. +
  9. 05

    卸载知道自己该删什么

    菜单 [9]uninstall 只清理由 AgentBoot 管理的程序,默认保留配置、认证和会话。

  10. +
  11. 06

    性能可以现场测量

    TLS 连接复用、知识库预建索引、上下文自动瘦身和流式中断保护;/bench 基于当前网络与模型实测。

  12. +
+
+
+ +
+
+
+

你的工具箱

14 个 Agent,一个入口

+

在线安装按需选择;标记为离线可用的 Agent 可连同依赖与运行时一起打包。

+
+ +
+
+
14个内置选项
+ 绿点表示支持离线安装 +
+
+ + + + + + + + + + + + + + + + + + +
#Agent命令厂商离线
01CoCo AgentcocoBitCookLinux/macOS
02OpenCodeopencodeopencode.ai仅在线
03Hermes AgenthermesHermes需 Git
04Cline CLIclineCline支持
05CodeBuddy CLIcodebuddyTencent支持
06Pi Coding AgentpiEarendil Works支持
07Claude CodeclaudeAnthropic支持
08OpenAI Codex CLIcodexOpenAIAgnes 预置
09Qwen CodeqwenAlibabaAgnes 预置
10MiMo CodemimoXiaomi支持
11OpenClawopenclawOpenClaw支持
12Gemini CLIgeminiGoogle支持
13iFlow CLIiflowiFlow 心流支持
14AideraiderAider AI仅在线
+
+

Codex 与 Qwen 安装后自动预置 Agnes 免费模型;也可通过菜单 +add-agent 添加自己的 Agent。

+
+
+
+ +
+
+
+

没有网络,也能安装

+

可验证离线包,把完整运行环境一起带走

+

v1.1.0 首批提供 Linux x64 与 Windows x64 Codex 精简包,CI 实际执行安装、版本启动与卸载。

+
    +
  • 已验证精简包:从 Releases 下载后直接带到目标机。
  • +
  • 自建离线包:用菜单 [7]build-offline 在目标平台按需构建。
  • +
  • 无需额外解压软件:运行包内 install-offline.ps1sh install-offline.sh
  • +
+
+ +
+

模型由你决定

+

开箱即用,也完全允许自定义

+
    +
  • Agnes 免费模型:ab 零配置直接用,Codex 与 Qwen 自动接线。
  • +
  • 自定义提供商:任意 OpenAI 兼容接口,命名管理、随时切换。
  • +
  • 本地模型:内置 Ollama 与 LM Studio 预设,也可添加 vLLM。
  • +
  • 故障切换:设置备用顺序,主模型失败后自动降级。
  • +
+
+
+
+ +
+
+
+

需要更多细节

文档直接说人话

+

从安装、离线部署到自定义 Agent,按你当前要解决的问题继续阅读。

+
+ +
+
+ +
+
+

少折腾环境,早点开始创造

+

AgentBoot 是 MIT 许可的开源项目。先用一条命令开始,所有选择依然掌握在你手里。

+ +
+
+
+ + diff --git a/scripts/sync-web-assets.py b/scripts/sync-web-assets.py new file mode 100644 index 0000000..83b1110 --- /dev/null +++ b/scripts/sync-web-assets.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +"""Generate the Cloudflare Worker web bundle from the canonical Pages sources.""" + +from __future__ import annotations + +import argparse +import hashlib +import json +from pathlib import Path +import shutil +import sys + + +ROOT = Path(__file__).resolve().parents[1] +OUTPUT = ROOT / "cloudflare" / "web-assets.js" +SOURCES = { + "/index.html": (ROOT / "pages" / "index.html", "text/html; charset=utf-8"), + "/en/index.html": (ROOT / "pages" / "en" / "index.html", "text/html; charset=utf-8"), + "/404.html": (ROOT / "pages" / "404.html", "text/html; charset=utf-8"), + "/assets/site.css": (ROOT / "pages" / "assets" / "site.css", "text/css; charset=utf-8"), + "/assets/site.js": (ROOT / "pages" / "assets" / "site.js", "text/javascript; charset=utf-8"), + "/assets/favicon.svg": (ROOT / "pages" / "assets" / "favicon.svg", "image/svg+xml; charset=utf-8"), +} + +MIRROR_PATHS = ( + "index.html", + "en/index.html", + "404.html", + "assets/site.css", + "assets/site.js", + "assets/favicon.svg", +) + + +def render() -> str: + records = {} + for route, (path, content_type) in SOURCES.items(): + body = path.read_text(encoding="utf-8") + digest = hashlib.sha256(body.encode()).hexdigest()[:16] + records[route] = {"body": body, "type": content_type, "etag": '"%s"' % digest} + payload = json.dumps(records, ensure_ascii=False, separators=(",", ":")) + return ( + "// Generated by scripts/sync-web-assets.py; do not edit by hand.\n" + f"export const WEB_ASSETS = Object.freeze({payload});\n" + ) + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--check", action="store_true", help="fail if the generated file is stale") + parser.add_argument("--mirror-root", type=Path, help="sync pages into /AgentBoot") + args = parser.parse_args() + expected = render() + ok = True + if args.check: + if not OUTPUT.exists() or OUTPUT.read_text(encoding="utf-8") != expected: + print("cloudflare/web-assets.js is stale; run scripts/sync-web-assets.py", file=sys.stderr) + ok = False + else: + OUTPUT.write_text(expected, encoding="utf-8") + + if args.mirror_root: + mirror = args.mirror_root.resolve() / "AgentBoot" + for relative in MIRROR_PATHS: + source = ROOT / "pages" / relative + target = mirror / relative + if target.is_file() and target.read_bytes() == source.read_bytes(): + continue + if args.check: + print(f"mirror is stale: {target}", file=sys.stderr) + ok = False + else: + target.parent.mkdir(parents=True, exist_ok=True) + shutil.copy2(source, target) + print(f"updated {target}") + return 0 if ok else 1 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tests/test_docs_consistency.py b/tests/test_docs_consistency.py index 3a3bdf6..df6affd 100644 --- a/tests/test_docs_consistency.py +++ b/tests/test_docs_consistency.py @@ -22,21 +22,39 @@ def test_chinese_guides_share_release_critical_facts(self): def test_web_surfaces_share_release_critical_facts(self): surfaces = [(ROOT / "pages/index.html").read_text(encoding="utf-8"), (ROOT / "pages/en/index.html").read_text(encoding="utf-8"), - (ROOT / "cloudflare/worker.js").read_text(encoding="utf-8")] + (ROOT / "cloudflare/web-assets.js").read_text(encoding="utf-8")] for fact in ("v1.1.0", "Codex", "uninstall"): for surface in surfaces: self.assertIn(fact, surface, fact) - def test_web_surfaces_include_mobile_overflow_and_touch_fixes(self): - surfaces = [(ROOT / "pages/index.html").read_text(encoding="utf-8"), - (ROOT / "pages/en/index.html").read_text(encoding="utf-8"), - (ROOT / "cloudflare/worker.js").read_text(encoding="utf-8")] - for surface in surfaces: + def test_pages_include_accessible_responsive_interactions(self): + pages = [(ROOT / "pages/index.html").read_text(encoding="utf-8"), + (ROOT / "pages/en/index.html").read_text(encoding="utf-8")] + css = (ROOT / "pages/assets/site.css").read_text(encoding="utf-8") + script = (ROOT / "pages/assets/site.js").read_text(encoding="utf-8") + for surface in pages: self.assertIn("table-scroll", surface) - self.assertIn("minmax(min(100%,280px),1fr)", surface) - self.assertIn("min-height:44px", surface) self.assertIn("aria-live", surface) self.assertIn(" Date: Mon, 31 Aug 2026 11:47:34 +0000 Subject: [PATCH 02/21] test: add deterministic performance benchmark --- .gitignore | 4 + performance-baseline.json | 16 +++ scripts/benchmark-performance.py | 219 +++++++++++++++++++++++++++++++ 3 files changed, 239 insertions(+) create mode 100644 performance-baseline.json create mode 100644 scripts/benchmark-performance.py diff --git a/.gitignore b/.gitignore index 49f94c3..228f62d 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,7 @@ __pycache__/ node_modules/ .DS_Store Thumbs.db + +# 本地性能实验输出(固定基线 performance-baseline.json 需要提交) +performance-run.log +performance-round-*.json diff --git a/performance-baseline.json b/performance-baseline.json new file mode 100644 index 0000000..a544498 --- /dev/null +++ b/performance-baseline.json @@ -0,0 +1,16 @@ +{ + "metrics": { + "startup_ms": 182.878, + "ab_version_ms": 119.849, + "menu_version_ms": 216.862, + "menu_ready_ms": 215.563, + "agent_run_ms": 167.357, + "install_ms": 218.45, + "homepage_gzip_bytes": 11026.0 + }, + "score": 100.0, + "sampling": { + "rounds": 3, + "runs_per_round": 15 + } +} diff --git a/scripts/benchmark-performance.py b/scripts/benchmark-performance.py new file mode 100644 index 0000000..7a25837 --- /dev/null +++ b/scripts/benchmark-performance.py @@ -0,0 +1,219 @@ +#!/usr/bin/env python3 +"""Deterministic AgentBoot performance benchmark (stdlib only). + +This benchmark intentionally excludes public-network latency. It measures the +fixed cost AgentBoot controls: process startup, menu readiness, local model +request handling, install orchestration, and critical-page transfer size. +""" + +from __future__ import annotations + +import argparse +from contextlib import contextmanager +import gzip +from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer +import json +import os +from pathlib import Path +import shutil +import statistics +import subprocess +import sys +import tempfile +import threading +import time + + +ROOT = Path(__file__).resolve().parents[1] +PYTHON = sys.executable + + +class ModelHandler(BaseHTTPRequestHandler): + protocol_version = "HTTP/1.1" + + def do_POST(self): + length = int(self.headers.get("Content-Length", "0")) + self.rfile.read(length) + body = json.dumps({ + "choices": [{"message": {"content": "ok", "tool_calls": []}}] + }, separators=(",", ":")).encode() + self.send_response(200) + self.send_header("Content-Type", "application/json") + self.send_header("Content-Length", str(len(body))) + self.end_headers() + self.wfile.write(body) + + def log_message(self, _format, *_args): + pass + + +@contextmanager +def model_server(): + server = ThreadingHTTPServer(("127.0.0.1", 0), ModelHandler) + thread = threading.Thread(target=server.serve_forever, daemon=True) + thread.start() + try: + yield server.server_address[1] + finally: + server.shutdown() + server.server_close() + thread.join(timeout=2) + + +def write_config(home: Path, port: int | None = None) -> None: + home.mkdir(parents=True, exist_ok=True) + config = { + "active": "bench" if port else "agnes", + "providers": ({ + "bench": { + "base_url": "http://127.0.0.1:%d/v1" % port, + "api_key": "", + "model": "bench", + } + } if port else {}), + "confirm": "safe", + "max_steps": 1, + "lang": "zh", + } + (home / "config.json").write_text(json.dumps(config), encoding="utf-8") + + +def elapsed_ms(command: list[str], env: dict[str, str], stdin: bytes | None = None) -> float: + start = time.perf_counter() + subprocess.run( + command, + cwd=ROOT, + env=env, + input=stdin, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + check=True, + timeout=15, + ) + return (time.perf_counter() - start) * 1000.0 + + +def median_command(command, env, runs, stdin=None) -> float: + elapsed_ms(command, env, stdin) + values = [elapsed_ms(command, env, stdin) for _ in range(runs)] + return statistics.median(values) + + +def fake_toolchain(root: Path) -> Path: + binary = root / "fake-bin" + binary.mkdir() + node = binary / "node" + npm = binary / "npm" + node.write_text("#!/bin/sh\nprintf 'v22.23.2\\n'\n", encoding="utf-8") + npm.write_text( + "#!/bin/sh\n" + "prefix=''\n" + "while [ $# -gt 0 ]; do\n" + " if [ \"$1\" = --prefix ]; then shift; prefix=$1; fi\n" + " shift\n" + "done\n" + "[ -n \"$prefix\" ] || exit 2\n" + "mkdir -p \"$prefix/bin\"\n" + "printf '#!/bin/sh\\nexit 0\\n' > \"$prefix/bin/codex\"\n" + "chmod +x \"$prefix/bin/codex\"\n", + encoding="utf-8", + ) + node.chmod(0o755) + npm.chmod(0o755) + return binary + + +def clean_install_home(root: Path) -> None: + for name in ("agentboot-home", "home"): + shutil.rmtree(root / name, ignore_errors=True) + (root / name).mkdir() + write_config(root / "agentboot-home") + + +def install_metric(root: Path, runs: int) -> float: + binary = fake_toolchain(root) + env = dict(os.environ) + env.update({ + "AGENTBOOT_HOME": str(root / "agentboot-home"), + "AGENTBOOT_MIRROR": "off", + "HOME": str(root / "home"), + "PATH": str(binary) + os.pathsep + env.get("PATH", ""), + }) + command = [PYTHON, "core/menu.py", "install", "codex"] + values = [] + for index in range(runs + 1): + clean_install_home(root) + value = elapsed_ms(command, env) + if index: + values.append(value) + return statistics.median(values) + + +def homepage_bytes() -> int: + paths = ( + ROOT / "pages" / "index.html", + ROOT / "pages" / "assets" / "site.css", + ROOT / "pages" / "assets" / "site.js", + ) + return sum(len(gzip.compress(path.read_bytes(), compresslevel=9)) for path in paths) + + +def measure(runs: int) -> dict[str, float]: + with tempfile.TemporaryDirectory(prefix="agentboot-perf-") as tmp: + root = Path(tmp) + home = root / "agentboot-home" + write_config(home) + env = dict(os.environ) + env.update({"AGENTBOOT_HOME": str(home), "AGENTBOOT_MIRROR": "off"}) + + ab_version = median_command([PYTHON, "core/agent.py", "version"], env, runs) + menu_version = median_command([PYTHON, "core/menu.py", "version"], env, runs) + menu_ready = median_command([PYTHON, "core/menu.py"], env, runs, b"0\n") + + with model_server() as port: + write_config(home, port) + agent_run = median_command( + [PYTHON, "core/agent.py", "run", "ping"], env, runs) + + install = install_metric(root, max(3, runs // 2)) + + return { + "startup_ms": round(statistics.fmean((ab_version, menu_version, menu_ready)), 3), + "ab_version_ms": round(ab_version, 3), + "menu_version_ms": round(menu_version, 3), + "menu_ready_ms": round(menu_ready, 3), + "agent_run_ms": round(agent_run, 3), + "install_ms": round(install, 3), + "homepage_gzip_bytes": float(homepage_bytes()), + } + + +def score(metrics: dict[str, float], baseline: dict[str, float]) -> float: + keys = ("startup_ms", "agent_run_ms", "install_ms", "homepage_gzip_bytes") + return round(100.0 * statistics.fmean(metrics[key] / baseline[key] for key in keys), 4) + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--runs", type=int, default=9) + parser.add_argument("--baseline", type=Path) + parser.add_argument("--write-baseline", type=Path) + args = parser.parse_args() + if args.runs < 3: + parser.error("--runs must be at least 3") + + metrics = measure(args.runs) + output = {"metrics": metrics} + if args.baseline: + baseline = json.loads(args.baseline.read_text(encoding="utf-8"))["metrics"] + output["score"] = score(metrics, baseline) + else: + output["score"] = 100.0 + if args.write_baseline: + args.write_baseline.write_text(json.dumps(output, indent=2) + "\n", encoding="utf-8") + print(json.dumps(output, indent=2)) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) From 63939b937e177d69dbda6f0458d4b19ef1d648be Mon Sep 17 00:00:00 2001 From: bit-cook Date: Mon, 31 Aug 2026 11:49:00 +0000 Subject: [PATCH 03/21] perf: defer optional agent imports --- core/agent.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/core/agent.py b/core/agent.py index bc68f99..e78b38b 100644 --- a/core/agent.py +++ b/core/agent.py @@ -11,13 +11,9 @@ * 工具:run_cmd / read_file / write_file / edit_file / list_dir / linux_help / http_get """ import json -import ipaddress import os import re -import shlex -import socket import sys -import tempfile import time sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) @@ -129,6 +125,7 @@ def save_config(cfg): def _atomic_private_json(path, data): + import tempfile directory = os.path.dirname(path) or "." os.makedirs(directory, mode=0o700, exist_ok=True) fd, tmp = tempfile.mkstemp(prefix=os.path.basename(path) + ".", suffix=".tmp", dir=directory) @@ -196,6 +193,7 @@ def _split_base(base_url): def _is_literal_loopback(host): + import ipaddress if str(host or "").lower() == "localhost": return True try: @@ -666,6 +664,7 @@ def linux_help(query): def _simple_command_level(segment): """Conservatively classify one shell pipeline segment.""" + import shlex try: words = shlex.split(segment, posix=os.name != "nt") except ValueError: @@ -728,6 +727,7 @@ def _trusted_executable(name): def safe_command_argv(cmd): + import shlex if classify_cmd(cmd) != "safe": return None try: @@ -758,6 +758,7 @@ def run_safe_cmd(cmd, timeout=60): def run_cmd(cmd, timeout=60): import subprocess # 惰性导入:保持启动极速 + import tempfile timeout = min(max(int(timeout or 60), 5), 300) shell = ["cmd", "/c", cmd] if os.name == "nt" else ["/bin/sh", "-c", cmd] out_file = tempfile.TemporaryFile(mode="w+b") @@ -923,6 +924,8 @@ def search_files(pattern, path=".", regex=False, max_results=40): def _validate_public_http_url(url): + import ipaddress + import socket from urllib.parse import urlsplit parsed = urlsplit(url or "") if parsed.scheme not in ("http", "https") or not parsed.hostname or parsed.username or parsed.password: @@ -1322,6 +1325,7 @@ def repl(cfg, resume=False): def doctor(cfg): + import socket print("AgentBoot 环境体检 v%s" % VERSION) print("-" * 46) print("Python : %s.%s.%s %s" % (*sys.version_info[:3], sys.executable)) From 167e3847c7ae8d7d50de3ce27542c2392ec060fe Mon Sep 17 00:00:00 2001 From: bit-cook Date: Mon, 31 Aug 2026 11:50:40 +0000 Subject: [PATCH 04/21] fix: preserve socket test seam --- core/agent.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/agent.py b/core/agent.py index e78b38b..0b598ff 100644 --- a/core/agent.py +++ b/core/agent.py @@ -13,6 +13,7 @@ import json import os import re +import socket import sys import time @@ -925,7 +926,6 @@ def search_files(pattern, path=".", regex=False, max_results=40): def _validate_public_http_url(url): import ipaddress - import socket from urllib.parse import urlsplit parsed = urlsplit(url or "") if parsed.scheme not in ("http", "https") or not parsed.hostname or parsed.username or parsed.password: From e9cd78ec011ee03143b02082d1d2045982c52746 Mon Sep 17 00:00:00 2001 From: bit-cook Date: Mon, 31 Aug 2026 11:51:03 +0000 Subject: [PATCH 05/21] fix: preserve socket compatibility seam --- core/agent.py | 1 - 1 file changed, 1 deletion(-) diff --git a/core/agent.py b/core/agent.py index 0b598ff..3c17cd8 100644 --- a/core/agent.py +++ b/core/agent.py @@ -1325,7 +1325,6 @@ def repl(cfg, resume=False): def doctor(cfg): - import socket print("AgentBoot 环境体检 v%s" % VERSION) print("-" * 46) print("Python : %s.%s.%s %s" % (*sys.version_info[:3], sys.executable)) From 5a201477b117dd9ab91c98d954627e9b1870e196 Mon Sep 17 00:00:00 2001 From: bit-cook Date: Mon, 31 Aug 2026 11:56:20 +0000 Subject: [PATCH 06/21] revert: restore eager agent imports --- core/agent.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/core/agent.py b/core/agent.py index 3c17cd8..bc68f99 100644 --- a/core/agent.py +++ b/core/agent.py @@ -11,10 +11,13 @@ * 工具:run_cmd / read_file / write_file / edit_file / list_dir / linux_help / http_get """ import json +import ipaddress import os import re +import shlex import socket import sys +import tempfile import time sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) @@ -126,7 +129,6 @@ def save_config(cfg): def _atomic_private_json(path, data): - import tempfile directory = os.path.dirname(path) or "." os.makedirs(directory, mode=0o700, exist_ok=True) fd, tmp = tempfile.mkstemp(prefix=os.path.basename(path) + ".", suffix=".tmp", dir=directory) @@ -194,7 +196,6 @@ def _split_base(base_url): def _is_literal_loopback(host): - import ipaddress if str(host or "").lower() == "localhost": return True try: @@ -665,7 +666,6 @@ def linux_help(query): def _simple_command_level(segment): """Conservatively classify one shell pipeline segment.""" - import shlex try: words = shlex.split(segment, posix=os.name != "nt") except ValueError: @@ -728,7 +728,6 @@ def _trusted_executable(name): def safe_command_argv(cmd): - import shlex if classify_cmd(cmd) != "safe": return None try: @@ -759,7 +758,6 @@ def run_safe_cmd(cmd, timeout=60): def run_cmd(cmd, timeout=60): import subprocess # 惰性导入:保持启动极速 - import tempfile timeout = min(max(int(timeout or 60), 5), 300) shell = ["cmd", "/c", cmd] if os.name == "nt" else ["/bin/sh", "-c", cmd] out_file = tempfile.TemporaryFile(mode="w+b") @@ -925,7 +923,6 @@ def search_files(pattern, path=".", regex=False, max_results=40): def _validate_public_http_url(url): - import ipaddress from urllib.parse import urlsplit parsed = urlsplit(url or "") if parsed.scheme not in ("http", "https") or not parsed.hostname or parsed.username or parsed.password: From 14ec8ce4a2eeda7ae4424987ac15332ea3f195c5 Mon Sep 17 00:00:00 2001 From: bit-cook Date: Mon, 31 Aug 2026 11:58:14 +0000 Subject: [PATCH 07/21] perf: defer menu HTTP client imports --- core/menu.py | 15 ++++++++------- tests/test_script_install.py | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/core/menu.py b/core/menu.py index f267d82..94ddbd5 100644 --- a/core/menu.py +++ b/core/menu.py @@ -29,7 +29,6 @@ import tempfile import time import urllib.parse -import urllib.request sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import agent # noqa: E402 复用配置与模型能力 @@ -391,6 +390,7 @@ def node_ok(path=None, minimum=None): def ensure_node(minimum=None): """确保 Node 满足 Agent 最低版本;不足时部署便携运行时。""" + from urllib import request as urllib_request sysnode = shutil.which("node") if sysnode and node_ok(sysnode, minimum): return sysnode @@ -421,8 +421,8 @@ def ensure_node(minimum=None): for u in urls: try: log_info("下载 Node 运行时:%s" % u) - req = urllib.request.Request(u, headers={"User-Agent": "AgentBoot/1.0"}) - with urllib.request.urlopen(req, timeout=60) as r, open(archive, "wb") as f: + req = urllib_request.Request(u, headers={"User-Agent": "AgentBoot/1.0"}) + with urllib_request.urlopen(req, timeout=60) as r, open(archive, "wb") as f: while True: chunk = r.read(1 << 20) if not chunk: @@ -437,8 +437,8 @@ def ensure_node(minimum=None): try: if not os.path.exists(sums_path): sums_url = "%s/%s/SHASUMS256.txt" % (NODE_MIRROR_GLOBAL, NODE_VERSION) - req = urllib.request.Request(sums_url, headers={"User-Agent": "AgentBoot/1.0"}) - with urllib.request.urlopen(req, timeout=60) as response, open(sums_path, "wb") as output: + req = urllib_request.Request(sums_url, headers={"User-Agent": "AgentBoot/1.0"}) + with urllib_request.urlopen(req, timeout=60) as response, open(sums_path, "wb") as output: shutil.copyfileobj(response, output) expected = None with open(sums_path, "r", encoding="ascii") as sums: @@ -880,11 +880,12 @@ def install_via_script(a): def _download_script(url, suffix): - request = urllib.request.Request(url, headers={"User-Agent": "AgentBoot/1.0"}) + from urllib import request as urllib_request + request = urllib_request.Request(url, headers={"User-Agent": "AgentBoot/1.0"}) fd, path = tempfile.mkstemp(prefix="agentboot-script-", suffix=suffix) try: total = 0 - with os.fdopen(fd, "wb") as output, urllib.request.urlopen(request, timeout=60) as response: + with os.fdopen(fd, "wb") as output, urllib_request.urlopen(request, timeout=60) as response: final_url = urllib.parse.urlsplit(response.geturl()) if final_url.scheme.lower() != "https": raise ValueError("安装脚本重定向到了非 HTTPS 地址") diff --git a/tests/test_script_install.py b/tests/test_script_install.py index 090dfb8..259b67d 100644 --- a/tests/test_script_install.py +++ b/tests/test_script_install.py @@ -71,7 +71,7 @@ def geturl(self): def read(self, _size): return b"echo unsafe" - with mock.patch.object(menu.urllib.request, "urlopen", return_value=Response()), \ + with mock.patch("urllib.request.urlopen", return_value=Response()), \ self.assertRaisesRegex(ValueError, "非 HTTPS"): menu._download_script("https://example.test/install.sh", ".sh") From 72b78df65df0965745a2b6a061d85e445fb981ae Mon Sep 17 00:00:00 2001 From: bit-cook Date: Mon, 31 Aug 2026 12:05:19 +0000 Subject: [PATCH 08/21] perf: remove duplicate installer health check --- install.sh | 1 - pages/install.sh | 1 - tests/test_installer_transactions.py | 4 ++++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/install.sh b/install.sh index 5727b0f..6bed4eb 100755 --- a/install.sh +++ b/install.sh @@ -223,7 +223,6 @@ esac # ---------- 6. 体检 ---------- step "环境体检" -"$PY" "${APP_DIR}/core/agent.py" doctor >/dev/null 2>&1 || true "$PY" "${APP_DIR}/core/agent.py" doctor 2>/dev/null || true # ---------- 7. 完成 ---------- diff --git a/pages/install.sh b/pages/install.sh index 5727b0f..6bed4eb 100755 --- a/pages/install.sh +++ b/pages/install.sh @@ -223,7 +223,6 @@ esac # ---------- 6. 体检 ---------- step "环境体检" -"$PY" "${APP_DIR}/core/agent.py" doctor >/dev/null 2>&1 || true "$PY" "${APP_DIR}/core/agent.py" doctor 2>/dev/null || true # ---------- 7. 完成 ---------- diff --git a/tests/test_installer_transactions.py b/tests/test_installer_transactions.py index 54b92b2..465202e 100644 --- a/tests/test_installer_transactions.py +++ b/tests/test_installer_transactions.py @@ -9,6 +9,10 @@ class InstallerTransactionTests(unittest.TestCase): + def test_posix_online_installer_runs_one_visible_doctor_pass(self): + shell = (ROOT / "install.sh").read_text(encoding="utf-8") + self.assertEqual(shell.count('"${APP_DIR}/core/agent.py" doctor'), 1) + def test_posix_installers_use_atomic_app_switch(self): for relative in ("install.sh", "scripts/install-offline.sh"): text = (ROOT / relative).read_text(encoding="utf-8") From 926397e74b4d959490b6cf428e35a8bebe87c546 Mon Sep 17 00:00:00 2001 From: bit-cook Date: Mon, 31 Aug 2026 12:08:05 +0000 Subject: [PATCH 09/21] perf: reuse npm batch environment probes --- core/menu.py | 41 ++++++++++++++++++--------- tests/test_agent_lifecycle_methods.py | 13 +++++++++ tests/test_runtime_platforms.py | 8 ++++++ 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/core/menu.py b/core/menu.py index 94ddbd5..ecf89da 100644 --- a/core/menu.py +++ b/core/menu.py @@ -323,15 +323,15 @@ def node_exe(): return os.path.join(d, "node.exe") if not POSIX else os.path.join(d, "bin", "node") -def npm_cmd(minimum=None): +def npm_cmd(minimum=None, version_cache=None): """优先系统 npm,其次运行时自带 npm。""" n = shutil.which("npm") system_node = shutil.which("node") - if n and node_ok(system_node, minimum): + if n and node_ok(system_node, minimum, version_cache): return n d = runtime_node_dir() cand = os.path.join(d, "npm.cmd") if not POSIX else os.path.join(d, "bin", "npm") - return cand if os.path.exists(cand) and node_ok(node_exe(), minimum) else None + return cand if os.path.exists(cand) and node_ok(node_exe(), minimum, version_cache) else None def child_env(): @@ -375,14 +375,19 @@ def _version_satisfies(current, requirement): return False -def node_ok(path=None, minimum=None): +def node_ok(path=None, minimum=None, version_cache=None): try: executable = path or shutil.which("node") or node_exe() - out = subprocess.run([executable, "--version"], - capture_output=True, text=True, timeout=10) - if out.returncode == 0: + current = version_cache.get(executable) if version_cache is not None else None + if current is None: + out = subprocess.run([executable, "--version"], + capture_output=True, text=True, timeout=10) + if out.returncode != 0: + return False current = _version_tuple(out.stdout.strip()) - return bool(current and _version_satisfies(current, minimum or ">=18")) + if current and version_cache is not None: + version_cache[executable] = current + return bool(current and _version_satisfies(current, minimum or ">=18")) except Exception: pass return False @@ -757,24 +762,31 @@ def uninstall_agents(ids, purge=False): # ---------------------------------------------------------------- 在线安装 -def npm_install(pkg, minimum=None): - npm = npm_cmd(minimum) +def npm_install(pkg, minimum=None, context=None): + context = context if context is not None else {} + versions = context.setdefault("node_versions", {}) + npm = npm_cmd(minimum, versions) if not npm: got = ensure_node(minimum) if not got: log_err("需要 Node.js %s(无法自动部署,请检查网络)" % (minimum or ">=18")) return False - npm = npm_cmd(minimum) + versions.clear() + npm = npm_cmd(minimum, versions) if not npm: log_err("Node 已就绪但未找到匹配的 npm") return False ensure_npm_prefix() cmd = [npm, "install", "-g", pkg, "--prefix", NPM_PREFIX, "--no-audit", "--no-fund"] - if cn_mode(): + if "cn" not in context: + context["cn"] = cn_mode() + if context["cn"]: cmd += ["--registry", NPM_MIRROR] log_info("$ %s" % " ".join(cmd)) - r = subprocess.run(cmd, env=child_env()) + if "env" not in context: + context["env"] = child_env() + r = subprocess.run(cmd, env=context["env"]) return r.returncode == 0 @@ -782,6 +794,7 @@ def install_online(ids): agents = load_registry() by_id = {a["id"]: a for a in agents} ok_list, fail_list = [], [] + npm_context = {} for aid in ids: a = by_id.get(aid) if not a: @@ -808,7 +821,7 @@ def install_online(ids): if not ok: log_err("专用流程失败:可检查 Git 是否安装、或配置代理后重试") elif method == "npm": - ok = npm_install(a["npm"], a.get("node")) + ok = npm_install(a["npm"], a.get("node"), npm_context) elif method == "script": ok = install_via_script(a) elif method == "pip": diff --git a/tests/test_agent_lifecycle_methods.py b/tests/test_agent_lifecycle_methods.py index 7918a71..0acc799 100644 --- a/tests/test_agent_lifecycle_methods.py +++ b/tests/test_agent_lifecycle_methods.py @@ -17,6 +17,19 @@ class AgentLifecycleTests(unittest.TestCase): + def test_npm_batch_reuses_mirror_and_environment_detection(self): + context = {} + completed = subprocess.CompletedProcess([], 0) + with mock.patch.object(menu, "npm_cmd", return_value="npm"), \ + mock.patch.object(menu, "ensure_npm_prefix"), \ + mock.patch.object(menu, "cn_mode", return_value=False) as mirror, \ + mock.patch.object(menu, "child_env", return_value={}) as child_env, \ + mock.patch.object(menu.subprocess, "run", return_value=completed): + self.assertTrue(menu.npm_install("one", ">=18", context)) + self.assertTrue(menu.npm_install("two", ">=20", context)) + mirror.assert_called_once_with() + child_env.assert_called_once_with() + def test_opencode_not_advertised_offline_until_postinstall_is_supported(self): registry = json.loads((ROOT / "agents/registry.json").read_text(encoding="utf-8")) opencode = next(agent for agent in registry["agents"] if agent["id"] == "opencode") diff --git a/tests/test_runtime_platforms.py b/tests/test_runtime_platforms.py index 93a99d3..4e09b66 100644 --- a/tests/test_runtime_platforms.py +++ b/tests/test_runtime_platforms.py @@ -15,6 +15,14 @@ class NodeVersionTests(unittest.TestCase): + def test_batch_cache_reuses_one_node_version_probe(self): + cache = {} + completed = subprocess.CompletedProcess([], 0, stdout="v22.23.2\n", stderr="") + with mock.patch.object(menu.subprocess, "run", return_value=completed) as run: + self.assertTrue(menu.node_ok("/managed/node", ">=18", cache)) + self.assertTrue(menu.node_ok("/managed/node", ">=22", cache)) + self.assertEqual(run.call_count, 1) + def result(self, version, code=0): return subprocess.CompletedProcess([], code, stdout=version, stderr="") From 9fd0bbbc9e53f00a3671b36e3b2198791ed781ca Mon Sep 17 00:00:00 2001 From: bit-cook Date: Mon, 31 Aug 2026 12:09:07 +0000 Subject: [PATCH 10/21] test: cover npm batch context --- tests/test_runtime_platforms.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_runtime_platforms.py b/tests/test_runtime_platforms.py index 4e09b66..b1d446a 100644 --- a/tests/test_runtime_platforms.py +++ b/tests/test_runtime_platforms.py @@ -44,7 +44,9 @@ def test_npm_install_requests_agent_minimum(self): mock.patch.object(menu, "npm_install", return_value=False) as install, \ mock.patch.object(menu, "ensure_path_registered"): menu.install_online(["openclaw"]) - install.assert_called_once_with("openclaw", ">=22.22.0") + install.assert_called_once() + self.assertEqual(install.call_args.args[:2], ("openclaw", ">=22.22.0")) + self.assertIsInstance(install.call_args.args[2], dict) def test_portable_runtime_satisfies_strictest_registry_requirement(self): self.assertEqual(menu.NODE_VERSION, "v22.23.2") From 30416a515edb68c8304240e94dad7410d5557327 Mon Sep 17 00:00:00 2001 From: bit-cook Date: Mon, 31 Aug 2026 12:10:54 +0000 Subject: [PATCH 11/21] perf: compact model request payloads --- core/agent.py | 4 ++-- tests/test_regressions.py | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/core/agent.py b/core/agent.py index bc68f99..0defef1 100644 --- a/core/agent.py +++ b/core/agent.py @@ -295,7 +295,7 @@ def chat(cfg, messages, stream_cb=None, tools=None, max_tokens=None, temperature if p.get("api_key"): headers["Authorization"] = "Bearer " + p["api_key"] - payload = json.dumps(body, ensure_ascii=False).encode("utf-8") + payload = json.dumps(body, ensure_ascii=False, separators=(",", ":")).encode("utf-8") last_err = None for attempt in range(3): @@ -455,7 +455,7 @@ def _ttfb(cfg, prompt="回复:1"): headers = {"Content-Type": "application/json", "Connection": "keep-alive"} if p.get("api_key"): headers["Authorization"] = "Bearer " + p["api_key"] - payload = json.dumps(body, ensure_ascii=False).encode("utf-8") + payload = json.dumps(body, ensure_ascii=False, separators=(",", ":")).encode("utf-8") t0 = time.perf_counter() try: conn = _connect(scheme, host, port) diff --git a/tests/test_regressions.py b/tests/test_regressions.py index ae27d2c..088f55b 100644 --- a/tests/test_regressions.py +++ b/tests/test_regressions.py @@ -15,6 +15,10 @@ class HighImpactRegressionTests(unittest.TestCase): + def test_model_request_uses_compact_json(self): + source = (ROOT / "core" / "agent.py").read_text(encoding="utf-8") + self.assertGreaterEqual(source.count('separators=(",", ":")'), 2) + def test_installed_ab_wrappers_forward_subcommands(self): files = ("install.sh", "scripts/install-offline.sh", "scripts/install.ps1", "scripts/install-offline.ps1") From aa8402d8e84a45d33ab0c26ac5a4119abfb4e1d8 Mon Sep 17 00:00:00 2001 From: bit-cook Date: Mon, 31 Aug 2026 12:13:02 +0000 Subject: [PATCH 12/21] perf: defer installer-only utility imports --- core/menu.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/menu.py b/core/menu.py index ecf89da..d6cb6e5 100644 --- a/core/menu.py +++ b/core/menu.py @@ -17,7 +17,6 @@ python menu.py mirror auto|off|cn|proxy http://127.0.0.1:7890 """ import json -import hashlib from contextlib import contextmanager import os import re @@ -26,7 +25,6 @@ import subprocess import sys import platform -import tempfile import time import urllib.parse @@ -395,6 +393,7 @@ def node_ok(path=None, minimum=None, version_cache=None): def ensure_node(minimum=None): """确保 Node 满足 Agent 最低版本;不足时部署便携运行时。""" + import hashlib from urllib import request as urllib_request sysnode = shutil.which("node") if sysnode and node_ok(sysnode, minimum): @@ -893,6 +892,7 @@ def install_via_script(a): def _download_script(url, suffix): + import tempfile from urllib import request as urllib_request request = urllib_request.Request(url, headers={"User-Agent": "AgentBoot/1.0"}) fd, path = tempfile.mkstemp(prefix="agentboot-script-", suffix=suffix) @@ -1034,6 +1034,7 @@ def _download_mirror(urls, dest): def _seed_uv(pkg_root): """预置 uv 二进制到 /.uv_bin 并写入 marker,绕过 postinstall 的 GitHub 直连下载。""" + import hashlib import tarfile import zipfile version, asset_info, sha = _hermes_uv_meta(pkg_root) From 0fa419213ea798d0801bf55c1b8a16bf6888184b Mon Sep 17 00:00:00 2001 From: bit-cook Date: Mon, 31 Aug 2026 12:17:13 +0000 Subject: [PATCH 13/21] perf: favor cached quiet npm installs --- core/menu.py | 6 ++++-- tests/test_regressions.py | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/core/menu.py b/core/menu.py index d6cb6e5..1e32459 100644 --- a/core/menu.py +++ b/core/menu.py @@ -777,7 +777,8 @@ def npm_install(pkg, minimum=None, context=None): return False ensure_npm_prefix() cmd = [npm, "install", "-g", pkg, "--prefix", NPM_PREFIX, - "--no-audit", "--no-fund"] + "--no-audit", "--no-fund", "--prefer-offline", + "--progress=false", "--loglevel=error"] if "cn" not in context: context["cn"] = cn_mode() if context["cn"]: @@ -1113,7 +1114,8 @@ def install_hermes_special(a): return False ensure_npm_prefix() cmd = [npm, "install", "--ignore-scripts", "-g", a["npm"], - "--prefix", NPM_PREFIX, "--no-audit", "--no-fund"] + "--prefix", NPM_PREFIX, "--no-audit", "--no-fund", "--prefer-offline", + "--progress=false", "--loglevel=error"] if cn_mode(): cmd += ["--registry", NPM_MIRROR] log_info("$ %s" % " ".join(cmd)) diff --git a/tests/test_regressions.py b/tests/test_regressions.py index 088f55b..1bb8326 100644 --- a/tests/test_regressions.py +++ b/tests/test_regressions.py @@ -57,6 +57,8 @@ def test_npm_install_is_scoped_to_agentboot_prefix(self): command = run.call_args.args[0] self.assertIn("--prefix", command) self.assertEqual(command[command.index("--prefix") + 1], "/managed/agentboot/npm-prefix") + for option in ("--no-audit", "--no-fund", "--prefer-offline", "--progress=false", "--loglevel=error"): + self.assertIn(option, command) def test_ttfb_does_not_wait_for_remaining_response_body(self): class Response: From 1ae956719b9d7e4b382255a2e7e3935495494567 Mon Sep 17 00:00:00 2001 From: bit-cook Date: Mon, 31 Aug 2026 12:24:10 +0000 Subject: [PATCH 14/21] perf: launch commands through cached modules --- core/launch.py | 21 +++++++++++++++++++++ install.sh | 4 ++-- pages/install.sh | 4 ++-- scripts/install-offline.ps1 | 4 ++-- scripts/install-offline.sh | 4 ++-- scripts/install.ps1 | 4 ++-- tests/test_installer_transactions.py | 1 + tests/test_regressions.py | 7 +++++++ 8 files changed, 39 insertions(+), 10 deletions(-) create mode 100644 core/launch.py diff --git a/core/launch.py b/core/launch.py new file mode 100644 index 0000000..3006c81 --- /dev/null +++ b/core/launch.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +"""Tiny installed-command dispatcher; importing enables Python bytecode caching.""" + +import sys + + +def main(): + target = sys.argv[1] if len(sys.argv) > 1 else "menu" + sys.argv = [sys.argv[0]] + sys.argv[2:] + if target == "agent": + import agent + agent.main() + elif target == "menu": + import menu + menu.main() + else: + raise SystemExit("unknown AgentBoot launcher target: %s" % target) + + +if __name__ == "__main__": + main() diff --git a/install.sh b/install.sh index 6bed4eb..0740f02 100755 --- a/install.sh +++ b/install.sh @@ -182,13 +182,13 @@ cat > "$agentboot_tmp" < "$ab_tmp" < "$agentboot_tmp" < "$ab_tmp" < "$agentboot_tmp" < "$ab_tmp" < Date: Mon, 31 Aug 2026 12:26:30 +0000 Subject: [PATCH 15/21] perf: load menu configuration once --- core/menu.py | 15 ++++++++------- tests/test_language_persistence.py | 6 ++++++ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/core/menu.py b/core/menu.py index 1e32459..2ec5d7c 100644 --- a/core/menu.py +++ b/core/menu.py @@ -2061,8 +2061,10 @@ def menu_mirror(): def resolve_lang(): """语言解析:环境变量 AGENTBOOT_LANG 优先,其次配置文件,默认中文。""" - lang = os.environ.get("AGENTBOOT_LANG") or agent.load_config().get("lang") or "zh" + cfg = agent.load_config() + lang = os.environ.get("AGENTBOOT_LANG") or cfg.get("lang") or "zh" i18n.set_lang(lang) + return cfg def set_lang_persist(lang, cfg=None): @@ -2096,9 +2098,8 @@ def banner(): print(i18n.t("menu.tagline") + "\n") -def main_menu(): - resolve_lang() - cfg = agent.load_config() +def main_menu(cfg=None): + cfg = cfg if isinstance(cfg, dict) else resolve_lang() agents = load_registry() while True: banner() @@ -2149,11 +2150,11 @@ def main_menu(): def main(): - resolve_lang() + cfg = resolve_lang() agent._utf8_console() argv = sys.argv[1:] if not argv: - main_menu() + main_menu(cfg) return cmd = argv[0] if cmd == "lang": @@ -2261,7 +2262,7 @@ def main(): elif cmd in ("version", "--version"): print("AgentBoot 控制台 v%s" % VERSION) elif cmd == "menu": - main_menu() + main_menu(cfg) else: print(__doc__) diff --git a/tests/test_language_persistence.py b/tests/test_language_persistence.py index d13ffb0..dc93718 100644 --- a/tests/test_language_persistence.py +++ b/tests/test_language_persistence.py @@ -15,6 +15,12 @@ class LanguagePersistenceTests(unittest.TestCase): + def test_resolve_language_returns_the_loaded_config(self): + cfg = {"lang": "en"} + with mock.patch.object(menu.agent, "load_config", return_value=cfg) as load: + self.assertIs(menu.resolve_lang(), cfg) + load.assert_called_once_with() + def test_language_switch_mutates_live_config(self): cfg = agent.default_config() with mock.patch.object(menu.agent, "save_config"): From 7ecbe6b84c856101ad80576d9c4b6f5902de699e Mon Sep 17 00:00:00 2001 From: bit-cook Date: Mon, 31 Aug 2026 12:29:13 +0000 Subject: [PATCH 16/21] perf: batch compatible npm agent installs --- core/menu.py | 28 ++++++++++++++++++++++++--- tests/test_agent_lifecycle_methods.py | 18 +++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/core/menu.py b/core/menu.py index 2ec5d7c..026a0b0 100644 --- a/core/menu.py +++ b/core/menu.py @@ -762,6 +762,9 @@ def uninstall_agents(ids, purge=False): # ---------------------------------------------------------------- 在线安装 def npm_install(pkg, minimum=None, context=None): + packages = [pkg] if isinstance(pkg, str) else list(pkg) + if not packages: + return True context = context if context is not None else {} versions = context.setdefault("node_versions", {}) npm = npm_cmd(minimum, versions) @@ -776,7 +779,7 @@ def npm_install(pkg, minimum=None, context=None): log_err("Node 已就绪但未找到匹配的 npm") return False ensure_npm_prefix() - cmd = [npm, "install", "-g", pkg, "--prefix", NPM_PREFIX, + cmd = [npm, "install", "-g"] + packages + ["--prefix", NPM_PREFIX, "--no-audit", "--no-fund", "--prefer-offline", "--progress=false", "--loglevel=error"] if "cn" not in context: @@ -794,7 +797,7 @@ def install_online(ids): agents = load_registry() by_id = {a["id"]: a for a in agents} ok_list, fail_list = [], [] - npm_context = {} + npm_context, ready = {}, [] for aid in ids: a = by_id.get(aid) if not a: @@ -813,6 +816,25 @@ def install_online(ids): log_err(t("menu.install_os_limit") % (a["name"], "/".join(os_limits), plat_id())) fail_list.append(aid) continue + ready.append(a) + + npm_groups = {} + for a in ready: + if a.get("method", "npm") == "npm" and not a.get("special_install"): + npm_groups.setdefault(a.get("node") or ">=18", []).append(a) + batched = set() + for minimum, group in npm_groups.items(): + if len(group) < 2: + continue + packages = [a["npm"] for a in group] + log_info("批量安装 %d 个 npm Agent(共用依赖解析与连接)" % len(group)) + if npm_install(packages, minimum, npm_context): + batched.update(a["id"] for a in group) + else: + log_info("批量安装失败,回退逐个安装以定位问题") + + for a in ready: + aid = a["id"] method = a.get("method", "npm") ok = False if a.get("special_install") == "hermes": @@ -821,7 +843,7 @@ def install_online(ids): if not ok: log_err("专用流程失败:可检查 Git 是否安装、或配置代理后重试") elif method == "npm": - ok = npm_install(a["npm"], a.get("node"), npm_context) + ok = aid in batched or npm_install(a["npm"], a.get("node"), npm_context) elif method == "script": ok = install_via_script(a) elif method == "pip": diff --git a/tests/test_agent_lifecycle_methods.py b/tests/test_agent_lifecycle_methods.py index 0acc799..d12179e 100644 --- a/tests/test_agent_lifecycle_methods.py +++ b/tests/test_agent_lifecycle_methods.py @@ -17,6 +17,24 @@ class AgentLifecycleTests(unittest.TestCase): + def test_matching_node_requirements_share_one_npm_install(self): + agents = [ + {"id": "one", "name": "One", "vendor": "T", "desc": "", "bin": "one", + "method": "npm", "npm": "pkg-one", "node": ">=18"}, + {"id": "two", "name": "Two", "vendor": "T", "desc": "", "bin": "two", + "method": "npm", "npm": "pkg-two", "node": ">=18"}, + ] + with mock.patch.object(menu, "load_registry", return_value=agents), \ + mock.patch.object(menu, "npm_install", return_value=True) as install, \ + mock.patch.object(menu, "find_bin", side_effect=lambda name: "/managed/" + name), \ + mock.patch.object(menu, "wire_agnes", return_value=({}, [])), \ + mock.patch.object(menu, "record_install"), \ + mock.patch.object(menu, "ensure_path_registered"): + self.assertEqual(menu.install_online(["one", "two"]), []) + install.assert_called_once() + self.assertEqual(install.call_args.args[0], ["pkg-one", "pkg-two"]) + self.assertEqual(install.call_args.args[1], ">=18") + def test_npm_batch_reuses_mirror_and_environment_detection(self): context = {} completed = subprocess.CompletedProcess([], 0) From 8e8f5bc1d9b64f4e61d1278cb7dbc8bf52507387 Mon Sep 17 00:00:00 2001 From: bit-cook Date: Mon, 31 Aug 2026 12:31:08 +0000 Subject: [PATCH 17/21] perf: reuse TLS contexts across reconnects --- core/agent.py | 16 ++++++++++++---- tests/test_proxy_behavior.py | 8 ++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/core/agent.py b/core/agent.py index 0defef1..52f8109 100644 --- a/core/agent.py +++ b/core/agent.py @@ -214,11 +214,21 @@ def _validate_model_transport(scheme, host, api_key): # 连接池:复用 TLS 连接,砍掉每轮对话的握手开销(极限性能核心) _POOL = {} +_SSL_CONTEXTS = {} + + +def _ssl_context(): + import ssl + insecure = os.environ.get("AGENTBOOT_INSECURE") == "1" + context = _SSL_CONTEXTS.get(insecure) + if context is None: + context = ssl._create_unverified_context() if insecure else ssl.create_default_context() + _SSL_CONTEXTS[insecure] = context + return context def _connect(scheme, host, port, timeout=180): import http.client - import ssl from urllib.parse import urlsplit proxy_url = os.environ.get("HTTPS_PROXY") or os.environ.get("https_proxy") if not proxy_url: @@ -236,9 +246,7 @@ def _connect(scheme, host, port, timeout=180): if conn is not None: return conn if scheme == "https": - ctx = ssl.create_default_context() - if os.environ.get("AGENTBOOT_INSECURE") == "1": - ctx = ssl._create_unverified_context() + ctx = _ssl_context() if proxy: conn = http.client.HTTPSConnection(proxy.hostname, proxy.port or (443 if proxy.scheme == "https" else 80), timeout=timeout, context=ctx) diff --git a/tests/test_proxy_behavior.py b/tests/test_proxy_behavior.py index 638a984..0065325 100644 --- a/tests/test_proxy_behavior.py +++ b/tests/test_proxy_behavior.py @@ -17,6 +17,14 @@ class ProxyBehaviorTests(unittest.TestCase): + def test_ssl_context_is_reused_per_verification_mode(self): + agent._SSL_CONTEXTS.clear() + marker = object() + with mock.patch("ssl.create_default_context", return_value=marker) as create: + self.assertIs(agent._ssl_context(), marker) + self.assertIs(agent._ssl_context(), marker) + create.assert_called_once_with() + def test_invalid_proxy_is_rejected(self): with mock.patch.object(menu, "load_env_json", return_value={}), \ mock.patch.object(menu, "save_env_json") as save: From 96e7e4e2b2db6650d5edba310daa16e3dd1cfa22 Mon Sep 17 00:00:00 2001 From: bit-cook Date: Mon, 31 Aug 2026 12:56:59 +0000 Subject: [PATCH 18/21] perf: slim online runtime packages --- scripts/build-online.py | 10 ++++++++-- tests/test_release_staging.py | 6 ++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/scripts/build-online.py b/scripts/build-online.py index b303287..aec1a83 100644 --- a/scripts/build-online.py +++ b/scripts/build-online.py @@ -21,8 +21,13 @@ ".gitattributes", ".gitignore", "CHANGELOG.md", "LICENSE", "VERSION", "README.md", "README.en.md", "install.bat", "install.sh", "安装指南.md", ) -DIRECTORIES = ("agents", "cloudflare", "core", "docs", "scripts", "tools") +DIRECTORIES = ("agents", "core", "docs", "scripts", "tools") SKIP_PARTS = {"__pycache__", "node_modules", "payloads", "dist"} +SKIP_FILES = { + "scripts/benchmark-performance.py", + "scripts/sync-web-assets.py", + "scripts/verify-live-release.py", +} def package_files(): @@ -34,7 +39,8 @@ def package_files(): for dirname in DIRECTORIES: for path in (ROOT / dirname).rglob("*"): rel = path.relative_to(ROOT) - if path.is_file() and not (set(rel.parts) & SKIP_PARTS) and path.suffix != ".pyc": + if path.is_file() and not (set(rel.parts) & SKIP_PARTS) and \ + rel.as_posix() not in SKIP_FILES and path.suffix != ".pyc": files.append(path) return sorted(files, key=lambda path: path.relative_to(ROOT).as_posix()) diff --git a/tests/test_release_staging.py b/tests/test_release_staging.py index 11bca5f..78239c6 100644 --- a/tests/test_release_staging.py +++ b/tests/test_release_staging.py @@ -13,6 +13,12 @@ class ReleaseStagingTests(unittest.TestCase): + def test_online_package_excludes_deploy_and_benchmark_sources(self): + source = (ROOT / "scripts" / "build-online.py").read_text(encoding="utf-8") + self.assertNotIn('"cloudflare", "core"', source) + self.assertIn('"scripts/benchmark-performance.py"', source) + self.assertIn('"scripts/sync-web-assets.py"', source) + def test_explicit_stage_excludes_workspace_artifacts(self): with tempfile.TemporaryDirectory() as tmp: stage = Path(tmp) / "stage" From 3531bfe8881f7846530db9e289f2282eec299ab8 Mon Sep 17 00:00:00 2001 From: bit-cook Date: Mon, 31 Aug 2026 13:11:14 +0000 Subject: [PATCH 19/21] release: prepare AgentBoot v1.2.0 --- pages/agentboot-online-v1.1.0.tar.gz | Bin 119951 -> 0 bytes pages/agentboot-online-v1.1.0.tar.gz.sha256 | 1 - pages/agentboot-online-v1.1.0.zip | Bin 143942 -> 0 bytes pages/agentboot-online-v1.1.0.zip.sha256 | 1 - pages/agentboot-online-v1.2.0.tar.gz.sha256 | 1 + pages/agentboot-online-v1.2.0.zip.sha256 | 1 + scripts/install-offline.ps1 | 4 +++- scripts/install-offline.sh | 2 +- scripts/install.ps1 | 5 +++-- scripts/tools/stage_application.py | 2 +- tests/test_docs_consistency.py | 8 ++++---- tests/test_installer_transactions.py | 1 + tests/test_release_staging.py | 1 + tests/test_version_consistency.py | 6 ++++++ ...211\350\243\205\346\214\207\345\215\227.md" | 14 +++++++------- 15 files changed, 29 insertions(+), 18 deletions(-) delete mode 100644 pages/agentboot-online-v1.1.0.tar.gz delete mode 100644 pages/agentboot-online-v1.1.0.tar.gz.sha256 delete mode 100644 pages/agentboot-online-v1.1.0.zip delete mode 100644 pages/agentboot-online-v1.1.0.zip.sha256 create mode 100644 pages/agentboot-online-v1.2.0.tar.gz.sha256 create mode 100644 pages/agentboot-online-v1.2.0.zip.sha256 diff --git a/pages/agentboot-online-v1.1.0.tar.gz b/pages/agentboot-online-v1.1.0.tar.gz deleted file mode 100644 index 27a2f93586205bdf518ec3cb8cfcd73b2a3d60c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 119951 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

I!vbDpb$XG>r#~(zpebGbzk0s_{W= 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 z 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 Suj=)SuKx!YB5*|jxCQ_dXmpDJ diff --git a/pages/agentboot-online-v1.1.0.tar.gz.sha256 b/pages/agentboot-online-v1.1.0.tar.gz.sha256 deleted file mode 100644 index af8f13b..0000000 --- a/pages/agentboot-online-v1.1.0.tar.gz.sha256 +++ /dev/null @@ -1 +0,0 @@ -a597f71008061bfb8c71ceae1934e08e1dac638f02219c19eb0822950db1320e agentboot-online-v1.1.0.tar.gz diff --git a/pages/agentboot-online-v1.1.0.zip b/pages/agentboot-online-v1.1.0.zip deleted file mode 100644 index f656f162e452eefc4d4465e35917b5abd8534e88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 143942 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 **版本 v1.1.0** · 支持 Linux / macOS / Windows · 界面默认中文(切换:`agentboot lang en`) +> **版本 v1.2.0** · 支持 Linux / macOS / Windows · 界面默认中文(切换:`agentboot lang en`) > 语言 / Language: 中文(本页) | [English](docs/en/install-guide.md) | 中文副本:[docs/zh/安装指南.md](docs/zh/安装指南.md) > AgentBoot 是一个极简、极速、开箱即用的 AI Agent 启动器:内置一个保底最小 Agent(默认 Agnes 免费模型),其余 Agent(CoCo Agent、OpenCode、Hermes Agent、Cline、CodeBuddy、Pi、Claude Code、Codex、Qwen Code、MiMo Code、OpenClaw、Gemini CLI、iFlow CLI、Aider)通过**菜单自选安装**。除 Aider(pip 生态)外,**全部 Agent 支持离线安装**(离线包内置完整运行时,含 Hermes 的 Python venv 与 CoCo 的私有 Node)。 @@ -61,9 +61,9 @@ curl -fsSL https://bit-cook.github.io/AgentBoot/install.sh | sh - **方式 A(推荐)**:到 GitHub Releases 下载现成的离线包 `https://github.com/bit-cook/AgentBoot/releases` → 选择 - - `AgentBoot-offline-v1.1.0-win-x64-codex.zip`(Windows x64) - - `AgentBoot-offline-v1.1.0-linux-x64-codex.tar.gz`(Linux x64) - - `AgentBoot-offline-v1.1.0-linux-x64-codex-sfx.sh`(Linux x64 自解压单文件) + - `AgentBoot-offline-v1.2.0-win-x64-codex.zip`(Windows x64) + - `AgentBoot-offline-v1.2.0-linux-x64-codex.tar.gz`(Linux x64) + - `AgentBoot-offline-v1.2.0-linux-x64-codex-sfx.sh`(Linux x64 自解压单文件) - **方式 B(自建)**:在有网的 Linux/macOS 或 Windows 机器上运行项目自带的构建脚本, 自动从 npmmirror 镜像拉取全部 Agent 离线载荷并打包: @@ -83,9 +83,9 @@ curl -fsSL https://bit-cook.github.io/AgentBoot/install.sh | sh | 目标机器情况 | 解压方法 | |---|---| | **Windows(任意版本)** | 直接**右键 ZIP → 全部解压缩**。Windows 资源管理器自带 ZIP 支持,无需安装任何软件 | -| **Windows 10/11(命令行党)** | 系统自带 `tar`:`tar -xf AgentBoot-offline-v1.1.0-win-x64-codex.zip` | -| **Linux x64** | 系统自带 `tar`:`tar -xzf AgentBoot-offline-v1.1.0-linux-x64-codex.tar.gz -C ~` | -| **Linux x64 极简环境** | 用自解压单文件:`sh AgentBoot-offline-v1.1.0-linux-x64-codex-sfx.sh` | +| **Windows 10/11(命令行党)** | 系统自带 `tar`:`tar -xf AgentBoot-offline-v1.2.0-win-x64-codex.zip` | +| **Linux x64** | 系统自带 `tar`:`tar -xzf AgentBoot-offline-v1.2.0-linux-x64-codex.tar.gz -C ~` | +| **Linux x64 极简环境** | 用自解压单文件:`sh AgentBoot-offline-v1.2.0-linux-x64-codex-sfx.sh` | > 自解压包 `*-sfx.sh` 本身就是一个 shell 脚本 + 内嵌 base64 数据,`sh xxx-sfx.sh` 即自动解压并直接进入安装流程,非常适合只有最小化系统的服务器。 From a991f79e2d09ccab58e896b6cb1434168cdd0892 Mon Sep 17 00:00:00 2001 From: bit-cook Date: Mon, 31 Aug 2026 13:11:35 +0000 Subject: [PATCH 20/21] docs: finalize v1.2.0 version surfaces --- CHANGELOG.md | 11 +++++++++++ README.en.md | 2 +- README.md | 2 +- VERSION | 2 +- cloudflare/web-assets.js | 2 +- cloudflare/worker.js | 8 ++++---- core/agent.py | 2 +- docs/en/install-guide.md | 14 +++++++------- ...256\211\350\243\205\346\214\207\345\215\227.md" | 14 +++++++------- install.sh | 4 ++-- pages/en/index.html | 4 ++-- pages/index.html | 4 ++-- pages/install.ps1 | 9 +++++---- pages/install.sh | 4 ++-- 14 files changed, 47 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a179219..5c65225 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # 更新日志 +## v1.2.0 (2026-08-31) + +- 全面重构中英文主页:亮色乐观视觉、桌面/手机自适应、可访问性、品牌 404 与单一 canonical。 +- Pages 成为唯一网页源,Worker 自动生成同源资源;HTML 短缓存、版本化静态资源 immutable 缓存与 ETag 304。 +- `agentboot` 延迟加载 HTTP/SSL 网络栈与安装专用模块,控制台冷启动显著缩短。 +- 新增轻量 `launch.py`,让命令入口复用 Python 字节码缓存;频繁启动菜单实测降低约 34.6%。 +- 多 Agent 安装按相同 Node 约束合并 npm 解析与连接,失败自动回退逐个安装;批次内复用 Node、镜像和环境探测。 +- npm 安装优先本地缓存并关闭进度与冗余日志;在线安装器移除重复体检,POSIX 安装约减少一次 2 秒级网络检查。 +- 内置 Agent 使用紧凑请求 JSON,并在断线重连时复用 TLSContext;保持 TLS 校验、代理与流式安全边界。 +- 新增确定性性能基准,覆盖启动、内置 Agent 本地请求、安装调度与主页关键资源,所有实验保留/回退可审计。 + ## v1.1.0 (2026-08-30) - 新增 Agent 安全卸载:菜单 `[9]`、`agentboot uninstall `、批量卸载与 CoCo `--purge`。 diff --git a/README.en.md b/README.en.md index 2bf69b2..64d8647 100644 --- a/README.en.md +++ b/README.en.md @@ -98,7 +98,7 @@ ab model # provider manager ## Offline packages -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: +Download a platform-and-Agent-specific verified pack from [Releases](https://github.com/bit-cook/AgentBoot/releases). v1.2.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 diff --git a/README.md b/README.md index f04f1c3..e95508b 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ ab bench # 性能基准 ## 离线安装与瘦身定制 -到 [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` 和卸载后才上传。 +到 [Releases](https://github.com/bit-cook/AgentBoot/releases) 下载带平台与 Agent 名称的已验证精简包,拷到目标机解压后运行包内 `install-offline.ps1` / `sh install-offline.sh`。v1.2.0 首批发布 Linux x64 / Windows x64 的 Codex 包,发布流水线会实际执行安装、`codex --version` 和卸载后才上传。 其他 Agent 使用菜单 `[7]` 或 `build-offline win-x64 claude-code,pi` 在目标平台按需构建。Hermes 含平台相关 Python venv,必须在对应平台构建;Aider 暂不支持离线。 diff --git a/VERSION b/VERSION index 9084fa2..26aaba0 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.0 +1.2.0 diff --git a/cloudflare/web-assets.js b/cloudflare/web-assets.js index 895d992..4e75f05 100644 --- a/cloudflare/web-assets.js +++ b/cloudflare/web-assets.js @@ -1,2 +1,2 @@ // Generated by scripts/sync-web-assets.py; do not edit by hand. -export const WEB_ASSETS = Object.freeze({"/index.html":{"body":"\n\n\n \n \n \n \n AgentBoot · 一条命令,启动你的 AI Agent\n \n \n \n \n \n \n \n\n\n 跳到主要内容\n\n

\n\n
\n
\n

v1.1.0 · 免费开源 · 三平台可用

\n

一条命令,
Agent 就位

\n

把安装、模型、镜像、离线包和安全卸载收进一个清楚的菜单。你选择要用的 AI Agent,AgentBoot 负责把它可靠地装好。

\n \n
    \n
  • 14 个 Agent 按需选择
  • \n
  • Linux · macOS · Windows
  • \n
  • 离线安装
  • \n
  • MIT License
  • \n
\n
\n\n
\n \n \n \n
\n
\n \n agentboot\n
\n
\n

$ agentboot

\n

检查系统环境与网络…

\n

选择你想安装的 Agent

\n

校验来源与 SHA-256

\n

安装完成,开始创造。

\n
\n
\n
\n
\n\n
\n
\n
\n
\n
\n

从这里开始

\n

复制一行,马上启动

\n

安装完成后输入 agentboot 打开控制台菜单,或输入 ab 直接与内置 Agent 对话。

\n
\n
\n \n \n \n

安装器仅使用项目控制的 Worker、GitHub Pages 与 GitHub Release,并对安装包执行同源 SHA-256 校验。

\n
\n
\n\n
\n
\n
\n Linux / macOS\n \n
\n curl -fsSL https://boot.ide.pub/install.sh | sh\n
\n\n
\n
\n Windows PowerShell\n \n
\n powershell -NoProfile -ExecutionPolicy Bypass -Command \"iex ((New-Object Net.WebClient).DownloadString('https://boot.ide.pub/install.ps1'))\"\n
\n
\n
\n\n
    \n
  1. 安装 AgentBoot

    上面一条命令约 10 秒完成,只安装 AgentBoot 本体与内置 Agent。

  2. \n
  3. 选择需要的 Agent

    运行 agentboot,在菜单中安装、卸载和配置。

  4. \n
  5. 开始工作

    运行选好的 Agent;也可以直接输入 ab 零配置对话。

  6. \n
\n
\n\n
\n
\n

不仅是安装脚本

复杂留在里面,选择留给你

\n

不塞给你一个全家桶,也不把失败留给你排查。AgentBoot 把最容易出错的环境、网络、来源与卸载边界统一处理。

\n
\n\n
\n
\n

始终可用的起点

\n

即使其他 Agent 装不上,ab 也能马上工作

\n

零第三方依赖 Python 核心,默认接入 Agnes 免费模型,并内置离线 Linux 知识库、会话持久化和高危命令拦截。

\n
\n\n
    \n
  1. 01

    按需安装,不装全家桶

    14 个主流 Agent 自由选择:Claude Code、Codex、Qwen Code、OpenCode、MiMo、Cline、Pi、CoCo 等。

  2. \n
  3. 02

    模型提供商统一管理

    Agnes 零配置可用,也支持命名管理任意 OpenAI 兼容接口、Ollama、LM Studio 与故障切换顺序。

  4. \n
  5. 03

    中国网络自动适配

    自动选择 npm、Node、PyPI 镜像,Worker、Pages、Release 三源容错,并提供一键代理配置。

  6. \n
  7. 04

    离线包经过真实验证

    发布包完成安装、启动、卸载冒烟;菜单 [7] 还能在目标平台按需构建自定义包。

  8. \n
  9. 05

    卸载知道自己该删什么

    菜单 [9]uninstall 只清理由 AgentBoot 管理的程序,默认保留配置、认证和会话。

  10. \n
  11. 06

    性能可以现场测量

    TLS 连接复用、知识库预建索引、上下文自动瘦身和流式中断保护;/bench 基于当前网络与模型实测。

  12. \n
\n
\n
\n\n
\n
\n
\n

你的工具箱

14 个 Agent,一个入口

\n

在线安装按需选择;标记为离线可用的 Agent 可连同依赖与运行时一起打包。

\n
\n\n
\n
\n
14个内置选项
\n 绿点表示支持离线安装\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
#Agent命令厂商离线
01CoCo AgentcocoBitCookLinux/macOS
02OpenCodeopencodeopencode.ai仅在线
03Hermes AgenthermesHermes需 Git
04Cline CLIclineCline支持
05CodeBuddy CLIcodebuddyTencent支持
06Pi Coding AgentpiEarendil Works支持
07Claude CodeclaudeAnthropic支持
08OpenAI Codex CLIcodexOpenAIAgnes 预置
09Qwen CodeqwenAlibabaAgnes 预置
10MiMo CodemimoXiaomi支持
11OpenClawopenclawOpenClaw支持
12Gemini CLIgeminiGoogle支持
13iFlow CLIiflowiFlow 心流支持
14AideraiderAider AI仅在线
\n
\n

Codex 与 Qwen 安装后自动预置 Agnes 免费模型;也可通过菜单 +add-agent 添加自己的 Agent。

\n
\n
\n
\n\n
\n
\n
\n

没有网络,也能安装

\n

可验证离线包,把完整运行环境一起带走

\n

v1.1.0 首批提供 Linux x64 与 Windows x64 Codex 精简包,CI 实际执行安装、版本启动与卸载。

\n
    \n
  • 已验证精简包:从 Releases 下载后直接带到目标机。
  • \n
  • 自建离线包:用菜单 [7]build-offline 在目标平台按需构建。
  • \n
  • 无需额外解压软件:运行包内 install-offline.ps1sh install-offline.sh
  • \n
\n
\n\n
\n

模型由你决定

\n

开箱即用,也完全允许自定义

\n
    \n
  • Agnes 免费模型:ab 零配置直接用,Codex 与 Qwen 自动接线。
  • \n
  • 自定义提供商:任意 OpenAI 兼容接口,命名管理、随时切换。
  • \n
  • 本地模型:内置 Ollama 与 LM Studio 预设,也可添加 vLLM。
  • \n
  • 故障切换:设置备用顺序,主模型失败后自动降级。
  • \n
\n
\n
\n
\n\n
\n
\n
\n

需要更多细节

文档直接说人话

\n

从安装、离线部署到自定义 Agent,按你当前要解决的问题继续阅读。

\n
\n \n
\n
\n\n
\n
\n

少折腾环境,早点开始创造

\n

AgentBoot 是 MIT 许可的开源项目。先用一条命令开始,所有选择依然掌握在你手里。

\n \n
\n
\n
\n\n \n\n\n","type":"text/html; charset=utf-8","etag":"\"86a52ca150f60bc2\""},"/en/index.html":{"body":"\n\n\n \n \n \n \n AgentBoot · Launch your AI agents with one command\n \n \n \n \n \n \n \n\n\n Skip to main content\n\n \n\n
\n
\n

v1.1.0 · Free and open source · Three platforms

\n

One command.
Agents ready.

\n

Bring installation, models, mirrors, offline packs, and safe uninstall into one clear menu. You choose the AI agents you need; AgentBoot installs them reliably.

\n \n
    \n
  • Choose from 14 agents
  • \n
  • Linux · macOS · Windows
  • \n
  • Offline installation
  • \n
  • MIT License
  • \n
\n
\n\n
\n \n \n \n
\n
\n \n agentboot\n
\n
\n

$ agentboot

\n

Checking system and network…

\n

Choose the agents you want to install

\n

Verify source and SHA-256

\n

Ready. Start building.

\n
\n
\n
\n
\n\n
\n
\n
\n
\n
\n

Start here

\n

Copy one line. Start right away.

\n

After installation, run agentboot to open the console menu, or ab to chat directly with the built-in agent.

\n
\n
\n \n \n \n

The installer uses only project-controlled Worker, GitHub Pages, and GitHub Release sources, then verifies each installation package against a same-origin SHA-256 checksum.

\n
\n
\n\n
\n
\n
\n Linux / macOS\n \n
\n curl -fsSL https://boot.ide.pub/install.sh | sh\n
\n\n
\n
\n Windows PowerShell\n \n
\n powershell -NoProfile -ExecutionPolicy Bypass -Command \"iex ((New-Object Net.WebClient).DownloadString('https://boot.ide.pub/install.ps1'))\"\n
\n
\n
\n\n
    \n
  1. Install AgentBoot

    The command above takes about 10 seconds and installs only AgentBoot itself and the built-in agent.

  2. \n
  3. Choose the agents you need

    Run agentboot to install, uninstall, and configure agents from the menu.

  4. \n
  5. Get to work

    Launch your chosen agent, or run ab for a zero-configuration chat.

  6. \n
\n
\n\n
\n
\n

More than an install script

AgentBoot handles the complexity. You make the choices.

\n

No all-in-one bundle, and no failed setup left for you to debug. AgentBoot handles the parts most likely to break: environments, networks, sources, and uninstall boundaries.

\n
\n\n
\n
\n

A starting point that's always ready

\n

Even if other agents won't install, ab works right away

\n

The built-in agent uses a Python core with no third-party dependencies, the free Agnes model by default, an offline Linux knowledge base, persistent sessions, and safeguards against high-risk commands.

\n
\n\n
    \n
  1. 01

    Install on demand, not as a bundle

    Choose from 14 mainstream agents, including Claude Code, Codex, Qwen Code, OpenCode, MiMo, Cline, Pi, and CoCo.

  2. \n
  3. 02

    Manage model providers in one place

    Agnes works with zero configuration. You can also name and manage any OpenAI-compatible endpoint, Ollama, or LM Studio, and set a failover order.

  4. \n
  5. 03

    Automatically adapt to networks in China

    AgentBoot selects npm, Node, and PyPI mirrors automatically, fails over across Worker, Pages, and Release sources, and configures a proxy in one step.

  6. \n
  7. 04

    Offline packs are tested end to end

    Release packs pass install, launch, and uninstall smoke tests; menu [7] can also build a custom pack on demand on the target platform.

  8. \n
  9. 05

    Uninstall only what AgentBoot owns

    Menu [9] or uninstall removes AgentBoot-managed programs while keeping configuration, credentials, and sessions by default.

  10. \n
  11. 06

    Measure performance where it matters

    AgentBoot reuses TLS connections, prebuilds knowledge-base indexes, trims context automatically, and protects interrupted streams. /bench measures your current network and model.

  12. \n
\n
\n
\n\n
\n
\n
\n

Your toolbox

14 agents. One front door.

\n

Choose agents as needed for online installation. Agents marked as offline-ready can be packaged with their dependencies and runtimes.

\n
\n\n
\n
\n
14built-in choices
\n A green dot indicates support for offline installation\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
#AgentCommandVendorOffline
01CoCo AgentcocoBitCookLinux/macOS
02OpenCodeopencodeopencode.aiOnline only
03Hermes AgenthermesHermesRequires Git
04Cline CLIclineClineSupported
05CodeBuddy CLIcodebuddyTencentSupported
06Pi Coding AgentpiEarendil WorksSupported
07Claude CodeclaudeAnthropicSupported
08OpenAI Codex CLIcodexOpenAIAgnes preset
09Qwen CodeqwenAlibabaAgnes preset
10MiMo CodemimoXiaomiSupported
11OpenClawopenclawOpenClawSupported
12Gemini CLIgeminiGoogleSupported
13iFlow CLIiflowiFlowSupported
14AideraiderAider AIOnline only
\n
\n

Codex and Qwen are automatically configured with the free Agnes model after installation. Add your own agent with menu + or the add-agent command.

\n
\n
\n
\n\n
\n
\n
\n

Install without internet access

\n

Verified offline packs bring the complete runtime with you

\n

v1.1.0 initially provides slim Codex packs for Linux x64 and Windows x64. CI installs each pack, runs its version command, and uninstalls it.

\n
    \n
  • Verified slim packs: download from Releases and carry them to the target machine.
  • \n
  • Custom offline packs: use menu [7] or build-offline on the target platform.
  • \n
  • No extra extraction software: run install-offline.ps1 or sh install-offline.sh inside the pack.
  • \n
\n
\n\n
\n

Your models, your choice

\n

Ready out of the box and fully customizable

\n
    \n
  • Agnes free model: use ab with zero setup; Codex and Qwen are configured automatically.
  • \n
  • Custom providers: name, manage, and switch any OpenAI-compatible endpoint.
  • \n
  • Local models: Ollama and LM Studio presets, with vLLM available as a custom provider.
  • \n
  • Failover: set a fallback order and switch automatically when the primary fails.
  • \n
\n
\n
\n
\n\n
\n
\n
\n

More detail when you need it

Documentation that speaks plainly

\n

Start with the problem in front of you, from installation and offline deployment to custom agents.

\n
\n \n
\n
\n\n
\n
\n

Spend less time wrestling with setup. Start building sooner.

\n

AgentBoot is open source under the MIT License. Start with one command; every choice stays in your hands.

\n \n
\n
\n
\n\n \n\n\n","type":"text/html; charset=utf-8","etag":"\"eb766b947b8368b7\""},"/404.html":{"body":"\n\n\n \n \n \n \n 页面未找到 · AgentBoot\n \n \n\n\n
\n
\n

404

\n

这条路径没有 Agent,回到启动台吧

\n

地址可能已变更,或只是多输入了一个字符。项目主页、安装命令和文档都还在。

\n \n
\n
\n\n\n","type":"text/html; charset=utf-8","etag":"\"92d469229bf5cde6\""},"/assets/site.css":{"body":":root {\n color-scheme: light;\n --ink-950: #12251d;\n --ink-800: #294238;\n --ink-600: #5b7067;\n --ink-400: #91a198;\n --paper: #fffdf5;\n --surface: #ffffff;\n --soft: #f2f7f2;\n --line: #dce7df;\n --green: #137a52;\n --green-dark: #0d5e3e;\n --green-soft: #e3f5eb;\n --sun: #ffd84d;\n --sun-soft: #fff3b9;\n --coral: #ff7a59;\n --sky: #dff3ff;\n --success: #137a52;\n --warning: #a65e00;\n --error: #b42318;\n --info: #176b87;\n --code: #10251d;\n --code-text: #ecfff4;\n --display: ui-rounded, \"Avenir Next Rounded\", \"SF Pro Rounded\", \"Segoe UI\", sans-serif;\n --body: Inter, ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif;\n --mono: \"SFMono-Regular\", Consolas, \"Liberation Mono\", monospace;\n --ease: cubic-bezier(.2, .8, .2, 1);\n}\n\n* {\n box-sizing: border-box;\n}\n\nhtml {\n overflow-x: clip;\n scroll-behavior: smooth;\n scroll-padding-top: 88px;\n}\n\nbody {\n margin: 0;\n background: var(--paper);\n color: var(--ink-950);\n font-family: var(--body);\n font-size: 16px;\n line-height: 1.68;\n text-rendering: optimizeLegibility;\n -webkit-font-smoothing: antialiased;\n}\n\nbutton,\na {\n -webkit-tap-highlight-color: transparent;\n}\n\na {\n color: var(--green-dark);\n text-decoration-thickness: 1.5px;\n text-underline-offset: .2em;\n}\n\na:hover {\n color: var(--green);\n}\n\n:focus-visible {\n outline: 3px solid var(--sun);\n outline-offset: 3px;\n}\n\n.skip-link {\n position: fixed;\n z-index: 100;\n top: 12px;\n left: 12px;\n translate: 0 -150%;\n border: 1px solid var(--ink-950);\n border-radius: 10px;\n background: var(--surface);\n color: var(--ink-950);\n padding: 10px 14px;\n font-weight: 700;\n}\n\n.skip-link:focus {\n translate: 0;\n}\n\n.shell {\n width: min(1180px, calc(100% - 48px));\n margin-inline: auto;\n}\n\n.site-nav {\n position: relative;\n z-index: 10;\n display: flex;\n min-height: 76px;\n align-items: center;\n justify-content: space-between;\n gap: 24px;\n}\n\n.brand {\n display: inline-flex;\n min-height: 44px;\n align-items: center;\n gap: 11px;\n color: var(--ink-950);\n font-family: var(--display);\n font-size: 18px;\n font-weight: 800;\n letter-spacing: -.025em;\n text-decoration: none;\n}\n\n.brand-mark {\n position: relative;\n display: inline-grid;\n width: 34px;\n height: 34px;\n place-items: center;\n overflow: hidden;\n border: 2px solid var(--ink-950);\n border-radius: 11px;\n background: var(--sun);\n}\n\n.brand-mark::before,\n.brand-mark::after {\n content: \"\";\n position: absolute;\n height: 2px;\n border-radius: 999px;\n background: var(--ink-950);\n transform-origin: left center;\n}\n\n.brand-mark::before {\n width: 12px;\n translate: -1px -3px;\n rotate: 38deg;\n}\n\n.brand-mark::after {\n width: 10px;\n translate: 2px 5px;\n}\n\n.nav-links {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.nav-link,\n.language-link {\n display: inline-flex;\n min-height: 44px;\n align-items: center;\n justify-content: center;\n border-radius: 10px;\n color: var(--ink-800);\n padding: 8px 11px;\n font-size: 14px;\n font-weight: 650;\n text-decoration: none;\n}\n\n.nav-link:hover,\n.language-link:hover {\n background: var(--green-soft);\n color: var(--green-dark);\n}\n\n.language-link {\n border: 1px solid var(--line);\n background: rgba(255, 255, 255, .72);\n}\n\n.hero {\n position: relative;\n display: grid;\n min-height: 660px;\n align-items: center;\n grid-template-columns: minmax(0, 7fr) minmax(340px, 5fr);\n gap: clamp(32px, 6vw, 86px);\n padding-block: 72px 112px;\n}\n\n.hero::before {\n content: \"\";\n position: absolute;\n z-index: -2;\n top: 2%;\n right: 0;\n width: min(48vw, 620px);\n aspect-ratio: 1;\n border-radius: 50%;\n background: var(--sun-soft);\n}\n\n.hero::after {\n content: \"\";\n position: absolute;\n z-index: -1;\n bottom: 9%;\n left: 0;\n width: min(30vw, 380px);\n aspect-ratio: 1;\n border-radius: 50%;\n background: var(--sky);\n opacity: .7;\n}\n\n.eyebrow {\n display: inline-flex;\n align-items: center;\n gap: 9px;\n margin: 0 0 22px;\n color: var(--green-dark);\n font-size: 13px;\n font-weight: 750;\n letter-spacing: .08em;\n text-transform: uppercase;\n}\n\n.eyebrow::before {\n content: \"\";\n width: 9px;\n height: 9px;\n border-radius: 50%;\n background: var(--coral);\n box-shadow: 0 0 0 5px rgba(255, 122, 89, .14);\n}\n\nh1,\nh2,\nh3 {\n font-family: var(--display);\n text-wrap: balance;\n}\n\nh1 {\n max-width: 800px;\n margin: 0;\n font-size: clamp(48px, 7.1vw, 88px);\n font-weight: 800;\n letter-spacing: -.06em;\n line-height: .98;\n}\n\n.hero-highlight {\n position: relative;\n display: inline-block;\n white-space: nowrap;\n}\n\n.hero-highlight::after {\n content: \"\";\n position: absolute;\n z-index: -1;\n right: -.08em;\n bottom: .04em;\n left: -.02em;\n height: .24em;\n border-radius: 99px;\n background: var(--sun);\n rotate: -1.5deg;\n}\n\n.hero-copy {\n max-width: 650px;\n margin: 28px 0 0;\n color: var(--ink-600);\n font-size: clamp(17px, 2vw, 21px);\n line-height: 1.62;\n}\n\n.hero-actions {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n margin-top: 34px;\n}\n\n.button {\n display: inline-flex;\n min-height: 48px;\n align-items: center;\n justify-content: center;\n gap: 9px;\n border: 1px solid var(--ink-950);\n border-radius: 12px;\n padding: 11px 17px;\n font-size: 15px;\n font-weight: 750;\n line-height: 1;\n text-decoration: none;\n transition: translate 160ms var(--ease), background-color 160ms var(--ease), color 160ms var(--ease);\n}\n\n.button-primary {\n background: var(--green);\n color: #fff;\n border-color: var(--green);\n}\n\n.button-primary:hover {\n background: var(--green-dark);\n color: #fff;\n translate: 0 -2px;\n}\n\n.button-secondary {\n background: var(--surface);\n color: var(--ink-950);\n}\n\n.button-secondary:hover {\n background: var(--sun-soft);\n color: var(--ink-950);\n translate: 0 -2px;\n}\n\n.button svg,\n.text-link svg {\n width: 18px;\n height: 18px;\n flex: 0 0 auto;\n fill: none;\n stroke: currentColor;\n stroke-linecap: round;\n stroke-linejoin: round;\n stroke-width: 1.8;\n}\n\n.hero-proof {\n display: flex;\n flex-wrap: wrap;\n gap: 10px 18px;\n margin: 26px 0 0;\n padding: 0;\n color: var(--ink-600);\n font-size: 13px;\n font-weight: 650;\n list-style: none;\n}\n\n.hero-proof li {\n display: flex;\n align-items: center;\n gap: 7px;\n}\n\n.hero-proof li::before {\n content: \"\";\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--green);\n}\n\n.launch-visual {\n position: relative;\n min-height: 450px;\n}\n\n.orbit {\n position: absolute;\n inset: 0;\n margin: auto;\n border: 1px solid rgba(18, 37, 29, .18);\n border-radius: 50%;\n}\n\n.orbit-one {\n width: min(100%, 430px);\n aspect-ratio: 1;\n}\n\n.orbit-two {\n width: min(76%, 330px);\n aspect-ratio: 1;\n border-style: dashed;\n}\n\n.orbit-dot {\n position: absolute;\n top: 10%;\n right: 14%;\n width: 18px;\n height: 18px;\n border: 3px solid var(--paper);\n border-radius: 50%;\n background: var(--coral);\n box-shadow: 0 0 0 1px var(--ink-950);\n}\n\n.terminal {\n position: absolute;\n inset: 50% auto auto 50%;\n width: min(94%, 390px);\n overflow: hidden;\n border: 2px solid var(--ink-950);\n border-radius: 22px;\n background: var(--code);\n box-shadow: 18px 18px 0 var(--sun);\n color: var(--code-text);\n translate: -50% -50%;\n}\n\n.terminal-bar {\n display: flex;\n min-height: 48px;\n align-items: center;\n justify-content: space-between;\n border-bottom: 1px solid rgba(255, 255, 255, .13);\n padding: 0 17px;\n color: #b9d3c4;\n font-family: var(--mono);\n font-size: 12px;\n}\n\n.terminal-dots {\n display: flex;\n gap: 6px;\n}\n\n.terminal-dots i {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--coral);\n}\n\n.terminal-dots i:nth-child(2) {\n background: var(--sun);\n}\n\n.terminal-dots i:nth-child(3) {\n background: #57d49b;\n}\n\n.terminal-body {\n min-height: 238px;\n padding: 26px 22px;\n font-family: var(--mono);\n font-size: clamp(12px, 1.35vw, 14px);\n line-height: 1.8;\n}\n\n.terminal-body p {\n margin: 0 0 12px;\n}\n\n.prompt {\n color: #69e4a7;\n}\n\n.terminal-muted {\n color: #9bb7a8;\n}\n\n.terminal-check {\n color: var(--sun);\n}\n\n.section {\n padding-block: clamp(72px, 10vw, 120px);\n}\n\n.section-soft {\n position: relative;\n background: var(--soft);\n}\n\n.section-soft::before,\n.section-soft::after {\n content: \"\";\n position: absolute;\n right: 0;\n left: 0;\n height: 1px;\n background: var(--line);\n}\n\n.section-soft::before {\n top: 0;\n}\n\n.section-soft::after {\n bottom: 0;\n}\n\n.section-heading {\n display: grid;\n align-items: end;\n grid-template-columns: minmax(0, 4fr) minmax(280px, 3fr);\n gap: 32px;\n margin-bottom: 54px;\n}\n\n.kicker {\n margin: 0 0 12px;\n color: var(--green);\n font-size: 13px;\n font-weight: 750;\n letter-spacing: .08em;\n text-transform: uppercase;\n}\n\nh2 {\n max-width: 700px;\n margin: 0;\n font-size: clamp(34px, 4.8vw, 56px);\n font-weight: 800;\n letter-spacing: -.045em;\n line-height: 1.06;\n}\n\n.section-lede {\n max-width: 56ch;\n margin: 0;\n color: var(--ink-600);\n font-size: 17px;\n}\n\n.install-layout {\n display: grid;\n align-items: start;\n grid-template-columns: minmax(240px, 4fr) minmax(0, 8fr);\n gap: clamp(34px, 7vw, 88px);\n}\n\n.install-intro {\n position: sticky;\n top: 104px;\n}\n\n.install-intro h2 {\n font-size: clamp(34px, 4vw, 48px);\n}\n\n.install-intro p {\n color: var(--ink-600);\n}\n\n.security-note {\n display: grid;\n grid-template-columns: 38px 1fr;\n gap: 13px;\n margin-top: 28px;\n padding-top: 22px;\n border-top: 1px solid var(--line);\n color: var(--ink-600);\n font-size: 14px;\n}\n\n.security-icon {\n display: grid;\n width: 38px;\n height: 38px;\n place-items: center;\n border-radius: 12px;\n background: var(--green-soft);\n color: var(--green-dark);\n}\n\n.security-icon svg {\n width: 21px;\n height: 21px;\n fill: none;\n stroke: currentColor;\n stroke-linecap: round;\n stroke-linejoin: round;\n stroke-width: 1.8;\n}\n\n.security-note p {\n margin: 0;\n}\n\n.command-stack {\n display: grid;\n gap: 16px;\n}\n\n.command-card {\n overflow: hidden;\n border: 1px solid var(--ink-950);\n border-radius: 20px;\n background: var(--surface);\n}\n\n.command-head {\n display: flex;\n min-height: 56px;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n border-bottom: 1px solid var(--line);\n padding: 10px 12px 10px 20px;\n}\n\n.command-platform {\n display: flex;\n align-items: center;\n gap: 11px;\n font-weight: 750;\n}\n\n.platform-dot {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: var(--coral);\n}\n\n.command-card:nth-child(2) .platform-dot {\n background: #2f80ed;\n}\n\n.copy-button {\n display: inline-flex;\n min-width: 90px;\n min-height: 44px;\n align-items: center;\n justify-content: center;\n gap: 7px;\n border: 1px solid var(--line);\n border-radius: 10px;\n background: var(--soft);\n color: var(--ink-950);\n padding: 8px 12px;\n font: 700 13px/1 var(--body);\n cursor: pointer;\n transition: background-color 160ms var(--ease), border-color 160ms var(--ease);\n}\n\n.copy-button:hover {\n border-color: var(--green);\n background: var(--green-soft);\n}\n\n.copy-button[data-state=\"success\"] {\n border-color: var(--green);\n background: var(--green-soft);\n color: var(--green-dark);\n}\n\n.copy-button[data-state=\"error\"] {\n border-color: var(--error);\n background: #fff0ed;\n color: var(--error);\n}\n\n.copy-button svg {\n width: 16px;\n height: 16px;\n fill: none;\n stroke: currentColor;\n stroke-linecap: round;\n stroke-linejoin: round;\n stroke-width: 1.8;\n}\n\n.command-code {\n display: block;\n margin: 0;\n overflow-x: auto;\n background: var(--code);\n color: var(--code-text);\n padding: 24px 20px;\n font-family: var(--mono);\n font-size: 13px;\n line-height: 1.75;\n white-space: pre;\n scrollbar-color: #557266 var(--code);\n}\n\n.command-code::selection,\n.terminal ::selection {\n background: var(--sun);\n color: var(--ink-950);\n}\n\n.steps {\n display: grid;\n margin: 48px 0 0;\n padding: 0;\n counter-reset: step;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n list-style: none;\n}\n\n.step {\n position: relative;\n min-height: 180px;\n padding: 30px clamp(20px, 3vw, 34px);\n counter-increment: step;\n border-top: 1px solid var(--line);\n border-bottom: 1px solid var(--line);\n}\n\n.step + .step {\n border-left: 1px solid var(--line);\n}\n\n.step::before {\n content: \"0\" counter(step);\n display: block;\n margin-bottom: 30px;\n color: var(--coral);\n font: 750 13px/1 var(--mono);\n}\n\n.step h3 {\n margin: 0 0 8px;\n font-size: 19px;\n font-weight: 750;\n letter-spacing: -.02em;\n}\n\n.step p {\n margin: 0;\n color: var(--ink-600);\n font-size: 14px;\n}\n\n.inline-code,\n.rich-text code,\n.agent-table code,\n.feature-row code {\n border: 1px solid var(--line);\n border-radius: 6px;\n background: var(--surface);\n color: var(--green-dark);\n padding: .12em .42em;\n font-family: var(--mono);\n font-size: .88em;\n}\n\n.feature-layout {\n display: grid;\n align-items: start;\n grid-template-columns: minmax(280px, 5fr) minmax(0, 7fr);\n gap: clamp(40px, 8vw, 100px);\n}\n\n.feature-spotlight {\n position: sticky;\n top: 104px;\n overflow: hidden;\n border: 1px solid var(--ink-950);\n border-radius: 24px;\n background: var(--sun);\n padding: clamp(28px, 4vw, 44px);\n}\n\n.feature-spotlight::after {\n content: \"ab\";\n position: absolute;\n right: 0;\n bottom: -58px;\n color: rgba(18, 37, 29, .09);\n font: 800 clamp(120px, 18vw, 220px)/1 var(--display);\n letter-spacing: -.08em;\n}\n\n.feature-spotlight .kicker {\n color: var(--ink-800);\n}\n\n.feature-spotlight h3 {\n max-width: 470px;\n margin: 0;\n font-size: clamp(30px, 4vw, 48px);\n font-weight: 800;\n letter-spacing: -.045em;\n line-height: 1.08;\n}\n\n.feature-spotlight p {\n position: relative;\n z-index: 1;\n max-width: 48ch;\n margin: 24px 0 0;\n color: var(--ink-800);\n}\n\n.feature-list {\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.feature-row {\n display: grid;\n padding: 25px 0 28px;\n border-top: 1px solid var(--line);\n grid-template-columns: 44px 1fr;\n gap: 18px;\n}\n\n.feature-row:last-child {\n border-bottom: 1px solid var(--line);\n}\n\n.feature-index {\n color: var(--green);\n font: 750 12px/1.5 var(--mono);\n}\n\n.feature-row h3 {\n margin: -4px 0 7px;\n font-size: 20px;\n font-weight: 750;\n letter-spacing: -.025em;\n}\n\n.feature-row p {\n max-width: 60ch;\n margin: 0;\n color: var(--ink-600);\n font-size: 14px;\n}\n\n.agent-panel {\n overflow: hidden;\n border: 1px solid var(--ink-950);\n border-radius: 24px;\n background: var(--surface);\n}\n\n.agent-panel-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 20px;\n border-bottom: 1px solid var(--line);\n padding: 20px 24px;\n}\n\n.agent-count {\n display: flex;\n align-items: baseline;\n gap: 9px;\n}\n\n.agent-count strong {\n font: 800 38px/1 var(--display);\n letter-spacing: -.04em;\n}\n\n.agent-count span,\n.agent-legend {\n color: var(--ink-600);\n font-size: 13px;\n}\n\n.table-scroll {\n max-width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.agent-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 14px;\n}\n\n.agent-table th,\n.agent-table td {\n min-height: 52px;\n padding: 14px 20px;\n border-bottom: 1px solid var(--line);\n text-align: left;\n vertical-align: middle;\n}\n\n.agent-table th {\n background: var(--soft);\n color: var(--ink-600);\n font-size: 12px;\n font-weight: 750;\n letter-spacing: .04em;\n text-transform: uppercase;\n}\n\n.agent-table tr:last-child td {\n border-bottom: 0;\n}\n\n.agent-table tbody tr:hover {\n background: #fffdf3;\n}\n\n.agent-name {\n font-weight: 750;\n}\n\n.status {\n display: inline-flex;\n align-items: center;\n gap: 7px;\n white-space: nowrap;\n}\n\n.status::before {\n content: \"\";\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--ink-400);\n}\n\n.status-ready {\n color: var(--success);\n font-weight: 650;\n}\n\n.status-ready::before {\n background: var(--success);\n}\n\n.agent-footnote {\n margin: 0;\n border-top: 1px solid var(--line);\n background: var(--sun-soft);\n color: var(--ink-800);\n padding: 16px 22px;\n font-size: 13px;\n}\n\n.detail-grid {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 1px;\n border: 1px solid var(--line);\n background: var(--line);\n}\n\n.detail-block {\n min-height: 320px;\n background: var(--paper);\n padding: clamp(30px, 5vw, 58px);\n}\n\n.detail-block:nth-child(2) {\n background: var(--sky);\n}\n\n.detail-block h3 {\n max-width: 470px;\n margin: 0 0 20px;\n font-size: clamp(27px, 3vw, 38px);\n font-weight: 800;\n letter-spacing: -.04em;\n line-height: 1.1;\n}\n\n.rich-text {\n color: var(--ink-800);\n}\n\n.rich-text p {\n margin: 0 0 16px;\n}\n\n.rich-text ul {\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.rich-text li {\n position: relative;\n padding: 11px 0 11px 24px;\n border-top: 1px solid rgba(18, 37, 29, .15);\n}\n\n.rich-text li::before {\n content: \"\";\n position: absolute;\n top: 20px;\n left: 2px;\n width: 8px;\n height: 8px;\n border-radius: 2px;\n background: var(--green);\n rotate: 45deg;\n}\n\n.docs-list {\n display: grid;\n margin: 0;\n padding: 0;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 12px;\n list-style: none;\n}\n\n.docs-link {\n display: flex;\n min-height: 128px;\n flex-direction: column;\n justify-content: space-between;\n gap: 24px;\n border: 1px solid var(--line);\n border-radius: 18px;\n background: var(--surface);\n color: var(--ink-950);\n padding: 22px;\n text-decoration: none;\n transition: border-color 160ms var(--ease), translate 160ms var(--ease);\n}\n\n.docs-link:hover {\n border-color: var(--green);\n color: var(--green-dark);\n translate: 0 -3px;\n}\n\n.docs-link strong {\n font-size: 16px;\n}\n\n.docs-link span {\n color: var(--ink-600);\n font-size: 13px;\n}\n\n.text-link {\n display: inline-flex;\n align-items: center;\n gap: 7px;\n font-weight: 750;\n}\n\n.final-call {\n position: relative;\n overflow: hidden;\n contain: paint;\n border: 1px solid var(--ink-950);\n border-radius: 28px;\n background: var(--green);\n color: #fff;\n padding: clamp(36px, 7vw, 76px);\n}\n\n.final-call::after {\n content: \"\";\n position: absolute;\n right: -80px;\n bottom: -120px;\n width: 320px;\n height: 320px;\n border: 58px solid var(--sun);\n border-radius: 50%;\n opacity: .98;\n}\n\n.final-call h2 {\n position: relative;\n z-index: 1;\n max-width: 700px;\n font-size: clamp(36px, 6vw, 66px);\n}\n\n.final-call p {\n position: relative;\n z-index: 1;\n max-width: 55ch;\n margin: 22px 0 0;\n color: #dff8e9;\n font-size: 17px;\n}\n\n.final-call .hero-actions {\n position: relative;\n z-index: 1;\n}\n\n.final-call .button-primary {\n border-color: var(--sun);\n background: var(--sun);\n color: var(--ink-950);\n}\n\n.final-call .button-primary:hover {\n border-color: #ffe277;\n background: #ffe277;\n color: var(--ink-950);\n}\n\n.final-call .button-secondary {\n border-color: rgba(255, 255, 255, .5);\n background: transparent;\n color: #fff;\n}\n\n.final-call .button-secondary:hover {\n border-color: #fff;\n background: rgba(255, 255, 255, .1);\n color: #fff;\n}\n\n.site-footer {\n padding-block: 34px 44px;\n}\n\n.footer-row {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 30px;\n}\n\n.footer-note {\n max-width: 680px;\n margin: 13px 0 0;\n color: var(--ink-600);\n font-size: 13px;\n}\n\n.footer-links {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-end;\n gap: 6px 18px;\n font-size: 13px;\n font-weight: 650;\n}\n\n.footer-links a {\n min-height: 44px;\n display: inline-flex;\n align-items: center;\n}\n\n.not-found {\n display: grid;\n min-height: 100svh;\n place-items: center;\n padding: 40px 24px;\n}\n\n.not-found-card {\n position: relative;\n width: min(720px, 100%);\n overflow: hidden;\n border: 1px solid var(--ink-950);\n border-radius: 28px;\n background: var(--surface);\n padding: clamp(32px, 8vw, 72px);\n box-shadow: 18px 18px 0 var(--sun);\n}\n\n.not-found-code {\n margin: 0 0 28px;\n color: var(--coral);\n font: 800 clamp(60px, 15vw, 132px)/.8 var(--display);\n letter-spacing: -.07em;\n}\n\n.not-found h1 {\n max-width: 620px;\n font-size: clamp(34px, 7vw, 58px);\n line-height: 1.06;\n}\n\n.not-found p {\n max-width: 50ch;\n margin: 22px 0 0;\n color: var(--ink-600);\n}\n\n@media (prefers-reduced-motion: no-preference) {\n .hero-copy,\n .hero-actions,\n .hero-proof {\n animation: rise-in 620ms var(--ease) both;\n }\n\n .hero-actions {\n animation-delay: 100ms;\n }\n\n .hero-proof {\n animation-delay: 180ms;\n }\n\n .terminal {\n animation: terminal-in 720ms 80ms var(--ease) both;\n }\n\n .orbit-dot {\n animation: pulse 2.8s var(--ease) infinite;\n }\n\n @keyframes rise-in {\n from { opacity: 0; translate: 0 16px; }\n to { opacity: 1; translate: 0; }\n }\n\n @keyframes terminal-in {\n from { opacity: 0; translate: -46% -46%; }\n to { opacity: 1; translate: -50% -50%; }\n }\n\n @keyframes pulse {\n 50% { scale: 1.14; }\n }\n}\n\n@media (max-width: 900px) {\n .hero {\n min-height: auto;\n grid-template-columns: 1fr;\n padding-block: 54px 90px;\n }\n\n .launch-visual {\n min-height: 410px;\n }\n\n .section-heading,\n .install-layout,\n .feature-layout {\n grid-template-columns: 1fr;\n }\n\n .install-intro,\n .feature-spotlight {\n position: static;\n }\n\n .install-intro {\n display: grid;\n align-items: end;\n grid-template-columns: 1fr 1fr;\n gap: 30px;\n }\n\n .security-note {\n margin: 0;\n }\n\n .feature-spotlight {\n min-height: 310px;\n }\n}\n\n@media (max-width: 720px) {\n .shell {\n width: min(100% - 32px, 1180px);\n }\n\n .site-nav {\n min-height: 68px;\n }\n\n .nav-link {\n display: none;\n }\n\n .hero {\n gap: 42px;\n padding-top: 46px;\n }\n\n h1 {\n font-size: clamp(44px, 14vw, 68px);\n }\n\n .hero-copy {\n font-size: 17px;\n }\n\n .launch-visual {\n min-height: 350px;\n }\n\n .orbit-one {\n width: min(94%, 350px);\n }\n\n .orbit-two {\n width: min(72%, 270px);\n }\n\n .terminal {\n box-shadow: 11px 11px 0 var(--sun);\n }\n\n .terminal-body {\n min-height: 210px;\n padding: 22px 18px;\n }\n\n .section-heading {\n align-items: start;\n gap: 18px;\n margin-bottom: 38px;\n }\n\n .install-intro {\n display: block;\n }\n\n .security-note {\n margin-top: 24px;\n }\n\n .steps,\n .detail-grid,\n .docs-list {\n grid-template-columns: 1fr;\n }\n\n .step {\n min-height: auto;\n border-bottom: 0;\n padding: 24px 4px;\n }\n\n .step + .step {\n border-left: 0;\n }\n\n .step:last-child {\n border-bottom: 1px solid var(--line);\n }\n\n .step::before {\n margin-bottom: 16px;\n }\n\n .agent-panel-head,\n .footer-row {\n align-items: flex-start;\n flex-direction: column;\n }\n\n .agent-table th,\n .agent-table td {\n padding-inline: 14px;\n }\n\n .agent-table th:nth-child(4),\n .agent-table td:nth-child(4) {\n display: none;\n }\n\n .footer-links {\n justify-content: flex-start;\n }\n\n .final-call::after {\n right: -140px;\n bottom: -180px;\n }\n}\n\n@media (max-width: 480px) {\n .brand {\n font-size: 16px;\n }\n\n .brand-mark {\n width: 32px;\n height: 32px;\n }\n\n .language-link {\n padding-inline: 10px;\n }\n\n .hero-actions,\n .hero-actions .button {\n width: 100%;\n }\n\n .hero-proof {\n display: grid;\n grid-template-columns: 1fr 1fr;\n }\n\n .launch-visual {\n min-height: 320px;\n }\n\n .terminal {\n border-radius: 17px;\n }\n\n .terminal-bar {\n min-height: 42px;\n }\n\n .terminal-body {\n min-height: 190px;\n font-size: 11px;\n }\n\n .command-head {\n padding-left: 14px;\n }\n\n .copy-button {\n min-width: 82px;\n }\n\n .command-code {\n padding: 19px 14px;\n font-size: 11px;\n }\n\n .feature-spotlight {\n min-height: 330px;\n }\n\n .feature-row {\n grid-template-columns: 34px 1fr;\n gap: 10px;\n }\n\n .agent-table th:first-child,\n .agent-table td:first-child,\n .agent-table th:nth-child(4),\n .agent-table td:nth-child(4) {\n display: none;\n }\n\n .agent-table {\n font-size: 12px;\n }\n\n .agent-table th,\n .agent-table td {\n padding-inline: 10px;\n }\n\n .agent-legend {\n display: none;\n }\n\n .not-found-card {\n box-shadow: 10px 10px 0 var(--sun);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n html {\n scroll-behavior: auto;\n }\n\n *,\n *::before,\n *::after {\n animation-duration: .01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: .01ms !important;\n }\n}\n\n@media print {\n .site-nav,\n .hero-actions,\n .copy-button,\n .final-call,\n .site-footer {\n display: none;\n }\n\n body {\n background: #fff;\n }\n\n .section,\n .hero {\n min-height: auto;\n padding-block: 28px;\n }\n}\n","type":"text/css; charset=utf-8","etag":"\"93e52ab55ce71853\""},"/assets/site.js":{"body":"(function () {\n \"use strict\";\n\n var copyButtons = document.querySelectorAll(\"[data-copy]\");\n\n function legacyCopy(text) {\n var input = document.createElement(\"textarea\");\n input.value = text;\n input.setAttribute(\"readonly\", \"\");\n input.style.position = \"fixed\";\n input.style.opacity = \"0\";\n document.body.appendChild(input);\n input.select();\n var copied = document.execCommand(\"copy\");\n input.remove();\n return copied ? Promise.resolve() : Promise.reject(new Error(\"copy failed\"));\n }\n\n function copyText(text) {\n if (navigator.clipboard && window.isSecureContext) {\n return navigator.clipboard.writeText(text);\n }\n return legacyCopy(text);\n }\n\n copyButtons.forEach(function (button) {\n var idleLabel = button.getAttribute(\"data-label-idle\") || \"Copy\";\n var successLabel = button.getAttribute(\"data-label-success\") || \"Copied\";\n var errorLabel = button.getAttribute(\"data-label-error\") || \"Select command\";\n var label = button.querySelector(\"[data-copy-label]\");\n var timer;\n\n button.addEventListener(\"click\", function () {\n window.clearTimeout(timer);\n copyText(button.getAttribute(\"data-copy\") || \"\").then(function () {\n button.setAttribute(\"data-state\", \"success\");\n label.textContent = successLabel;\n }).catch(function () {\n button.setAttribute(\"data-state\", \"error\");\n label.textContent = errorLabel;\n }).finally(function () {\n timer = window.setTimeout(function () {\n button.removeAttribute(\"data-state\");\n label.textContent = idleLabel;\n }, 1800);\n });\n });\n });\n}());\n","type":"text/javascript; charset=utf-8","etag":"\"e32ad7eff5bfef9a\""},"/assets/favicon.svg":{"body":"\n \n \n\n","type":"image/svg+xml; charset=utf-8","etag":"\"97f7d8aaef171778\""}}); +export const WEB_ASSETS = Object.freeze({"/index.html":{"body":"\n\n\n \n \n \n \n AgentBoot · 一条命令,启动你的 AI Agent\n \n \n \n \n \n \n \n\n\n 跳到主要内容\n\n \n\n
\n
\n

v1.2.0 · 免费开源 · 三平台可用

\n

一条命令,
Agent 就位

\n

把安装、模型、镜像、离线包和安全卸载收进一个清楚的菜单。你选择要用的 AI Agent,AgentBoot 负责把它可靠地装好。

\n \n
    \n
  • 14 个 Agent 按需选择
  • \n
  • Linux · macOS · Windows
  • \n
  • 离线安装
  • \n
  • MIT License
  • \n
\n
\n\n
\n \n \n \n
\n
\n \n agentboot\n
\n
\n

$ agentboot

\n

检查系统环境与网络…

\n

选择你想安装的 Agent

\n

校验来源与 SHA-256

\n

安装完成,开始创造。

\n
\n
\n
\n
\n\n
\n
\n
\n
\n
\n

从这里开始

\n

复制一行,马上启动

\n

安装完成后输入 agentboot 打开控制台菜单,或输入 ab 直接与内置 Agent 对话。

\n
\n
\n \n \n \n

安装器仅使用项目控制的 Worker、GitHub Pages 与 GitHub Release,并对安装包执行同源 SHA-256 校验。

\n
\n
\n\n
\n
\n
\n Linux / macOS\n \n
\n curl -fsSL https://boot.ide.pub/install.sh | sh\n
\n\n
\n
\n Windows PowerShell\n \n
\n powershell -NoProfile -ExecutionPolicy Bypass -Command \"iex ((New-Object Net.WebClient).DownloadString('https://boot.ide.pub/install.ps1'))\"\n
\n
\n
\n\n
    \n
  1. 安装 AgentBoot

    上面一条命令约 10 秒完成,只安装 AgentBoot 本体与内置 Agent。

  2. \n
  3. 选择需要的 Agent

    运行 agentboot,在菜单中安装、卸载和配置。

  4. \n
  5. 开始工作

    运行选好的 Agent;也可以直接输入 ab 零配置对话。

  6. \n
\n
\n\n
\n
\n

不仅是安装脚本

复杂留在里面,选择留给你

\n

不塞给你一个全家桶,也不把失败留给你排查。AgentBoot 把最容易出错的环境、网络、来源与卸载边界统一处理。

\n
\n\n
\n
\n

始终可用的起点

\n

即使其他 Agent 装不上,ab 也能马上工作

\n

零第三方依赖 Python 核心,默认接入 Agnes 免费模型,并内置离线 Linux 知识库、会话持久化和高危命令拦截。

\n
\n\n
    \n
  1. 01

    按需安装,不装全家桶

    14 个主流 Agent 自由选择:Claude Code、Codex、Qwen Code、OpenCode、MiMo、Cline、Pi、CoCo 等。

  2. \n
  3. 02

    模型提供商统一管理

    Agnes 零配置可用,也支持命名管理任意 OpenAI 兼容接口、Ollama、LM Studio 与故障切换顺序。

  4. \n
  5. 03

    中国网络自动适配

    自动选择 npm、Node、PyPI 镜像,Worker、Pages、Release 三源容错,并提供一键代理配置。

  6. \n
  7. 04

    离线包经过真实验证

    发布包完成安装、启动、卸载冒烟;菜单 [7] 还能在目标平台按需构建自定义包。

  8. \n
  9. 05

    卸载知道自己该删什么

    菜单 [9]uninstall 只清理由 AgentBoot 管理的程序,默认保留配置、认证和会话。

  10. \n
  11. 06

    性能可以现场测量

    TLS 连接复用、知识库预建索引、上下文自动瘦身和流式中断保护;/bench 基于当前网络与模型实测。

  12. \n
\n
\n
\n\n
\n
\n
\n

你的工具箱

14 个 Agent,一个入口

\n

在线安装按需选择;标记为离线可用的 Agent 可连同依赖与运行时一起打包。

\n
\n\n
\n
\n
14个内置选项
\n 绿点表示支持离线安装\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
#Agent命令厂商离线
01CoCo AgentcocoBitCookLinux/macOS
02OpenCodeopencodeopencode.ai仅在线
03Hermes AgenthermesHermes需 Git
04Cline CLIclineCline支持
05CodeBuddy CLIcodebuddyTencent支持
06Pi Coding AgentpiEarendil Works支持
07Claude CodeclaudeAnthropic支持
08OpenAI Codex CLIcodexOpenAIAgnes 预置
09Qwen CodeqwenAlibabaAgnes 预置
10MiMo CodemimoXiaomi支持
11OpenClawopenclawOpenClaw支持
12Gemini CLIgeminiGoogle支持
13iFlow CLIiflowiFlow 心流支持
14AideraiderAider AI仅在线
\n
\n

Codex 与 Qwen 安装后自动预置 Agnes 免费模型;也可通过菜单 +add-agent 添加自己的 Agent。

\n
\n
\n
\n\n
\n
\n
\n

没有网络,也能安装

\n

可验证离线包,把完整运行环境一起带走

\n

v1.2.0 首批提供 Linux x64 与 Windows x64 Codex 精简包,CI 实际执行安装、版本启动与卸载。

\n
    \n
  • 已验证精简包:从 Releases 下载后直接带到目标机。
  • \n
  • 自建离线包:用菜单 [7]build-offline 在目标平台按需构建。
  • \n
  • 无需额外解压软件:运行包内 install-offline.ps1sh install-offline.sh
  • \n
\n
\n\n
\n

模型由你决定

\n

开箱即用,也完全允许自定义

\n
    \n
  • Agnes 免费模型:ab 零配置直接用,Codex 与 Qwen 自动接线。
  • \n
  • 自定义提供商:任意 OpenAI 兼容接口,命名管理、随时切换。
  • \n
  • 本地模型:内置 Ollama 与 LM Studio 预设,也可添加 vLLM。
  • \n
  • 故障切换:设置备用顺序,主模型失败后自动降级。
  • \n
\n
\n
\n
\n\n
\n
\n
\n

需要更多细节

文档直接说人话

\n

从安装、离线部署到自定义 Agent,按你当前要解决的问题继续阅读。

\n
\n \n
\n
\n\n
\n
\n

少折腾环境,早点开始创造

\n

AgentBoot 是 MIT 许可的开源项目。先用一条命令开始,所有选择依然掌握在你手里。

\n \n
\n
\n
\n\n \n\n\n","type":"text/html; charset=utf-8","etag":"\"91786b20ada44a56\""},"/en/index.html":{"body":"\n\n\n \n \n \n \n AgentBoot · Launch your AI agents with one command\n \n \n \n \n \n \n \n\n\n Skip to main content\n\n \n\n
\n
\n

v1.2.0 · Free and open source · Three platforms

\n

One command.
Agents ready.

\n

Bring installation, models, mirrors, offline packs, and safe uninstall into one clear menu. You choose the AI agents you need; AgentBoot installs them reliably.

\n \n
    \n
  • Choose from 14 agents
  • \n
  • Linux · macOS · Windows
  • \n
  • Offline installation
  • \n
  • MIT License
  • \n
\n
\n\n
\n \n \n \n
\n
\n \n agentboot\n
\n
\n

$ agentboot

\n

Checking system and network…

\n

Choose the agents you want to install

\n

Verify source and SHA-256

\n

Ready. Start building.

\n
\n
\n
\n
\n\n
\n
\n
\n
\n
\n

Start here

\n

Copy one line. Start right away.

\n

After installation, run agentboot to open the console menu, or ab to chat directly with the built-in agent.

\n
\n
\n \n \n \n

The installer uses only project-controlled Worker, GitHub Pages, and GitHub Release sources, then verifies each installation package against a same-origin SHA-256 checksum.

\n
\n
\n\n
\n
\n
\n Linux / macOS\n \n
\n curl -fsSL https://boot.ide.pub/install.sh | sh\n
\n\n
\n
\n Windows PowerShell\n \n
\n powershell -NoProfile -ExecutionPolicy Bypass -Command \"iex ((New-Object Net.WebClient).DownloadString('https://boot.ide.pub/install.ps1'))\"\n
\n
\n
\n\n
    \n
  1. Install AgentBoot

    The command above takes about 10 seconds and installs only AgentBoot itself and the built-in agent.

  2. \n
  3. Choose the agents you need

    Run agentboot to install, uninstall, and configure agents from the menu.

  4. \n
  5. Get to work

    Launch your chosen agent, or run ab for a zero-configuration chat.

  6. \n
\n
\n\n
\n
\n

More than an install script

AgentBoot handles the complexity. You make the choices.

\n

No all-in-one bundle, and no failed setup left for you to debug. AgentBoot handles the parts most likely to break: environments, networks, sources, and uninstall boundaries.

\n
\n\n
\n
\n

A starting point that's always ready

\n

Even if other agents won't install, ab works right away

\n

The built-in agent uses a Python core with no third-party dependencies, the free Agnes model by default, an offline Linux knowledge base, persistent sessions, and safeguards against high-risk commands.

\n
\n\n
    \n
  1. 01

    Install on demand, not as a bundle

    Choose from 14 mainstream agents, including Claude Code, Codex, Qwen Code, OpenCode, MiMo, Cline, Pi, and CoCo.

  2. \n
  3. 02

    Manage model providers in one place

    Agnes works with zero configuration. You can also name and manage any OpenAI-compatible endpoint, Ollama, or LM Studio, and set a failover order.

  4. \n
  5. 03

    Automatically adapt to networks in China

    AgentBoot selects npm, Node, and PyPI mirrors automatically, fails over across Worker, Pages, and Release sources, and configures a proxy in one step.

  6. \n
  7. 04

    Offline packs are tested end to end

    Release packs pass install, launch, and uninstall smoke tests; menu [7] can also build a custom pack on demand on the target platform.

  8. \n
  9. 05

    Uninstall only what AgentBoot owns

    Menu [9] or uninstall removes AgentBoot-managed programs while keeping configuration, credentials, and sessions by default.

  10. \n
  11. 06

    Measure performance where it matters

    AgentBoot reuses TLS connections, prebuilds knowledge-base indexes, trims context automatically, and protects interrupted streams. /bench measures your current network and model.

  12. \n
\n
\n
\n\n
\n
\n
\n

Your toolbox

14 agents. One front door.

\n

Choose agents as needed for online installation. Agents marked as offline-ready can be packaged with their dependencies and runtimes.

\n
\n\n
\n
\n
14built-in choices
\n A green dot indicates support for offline installation\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
#AgentCommandVendorOffline
01CoCo AgentcocoBitCookLinux/macOS
02OpenCodeopencodeopencode.aiOnline only
03Hermes AgenthermesHermesRequires Git
04Cline CLIclineClineSupported
05CodeBuddy CLIcodebuddyTencentSupported
06Pi Coding AgentpiEarendil WorksSupported
07Claude CodeclaudeAnthropicSupported
08OpenAI Codex CLIcodexOpenAIAgnes preset
09Qwen CodeqwenAlibabaAgnes preset
10MiMo CodemimoXiaomiSupported
11OpenClawopenclawOpenClawSupported
12Gemini CLIgeminiGoogleSupported
13iFlow CLIiflowiFlowSupported
14AideraiderAider AIOnline only
\n
\n

Codex and Qwen are automatically configured with the free Agnes model after installation. Add your own agent with menu + or the add-agent command.

\n
\n
\n
\n\n
\n
\n
\n

Install without internet access

\n

Verified offline packs bring the complete runtime with you

\n

v1.2.0 initially provides slim Codex packs for Linux x64 and Windows x64. CI installs each pack, runs its version command, and uninstalls it.

\n
    \n
  • Verified slim packs: download from Releases and carry them to the target machine.
  • \n
  • Custom offline packs: use menu [7] or build-offline on the target platform.
  • \n
  • No extra extraction software: run install-offline.ps1 or sh install-offline.sh inside the pack.
  • \n
\n
\n\n
\n

Your models, your choice

\n

Ready out of the box and fully customizable

\n
    \n
  • Agnes free model: use ab with zero setup; Codex and Qwen are configured automatically.
  • \n
  • Custom providers: name, manage, and switch any OpenAI-compatible endpoint.
  • \n
  • Local models: Ollama and LM Studio presets, with vLLM available as a custom provider.
  • \n
  • Failover: set a fallback order and switch automatically when the primary fails.
  • \n
\n
\n
\n
\n\n
\n
\n
\n

More detail when you need it

Documentation that speaks plainly

\n

Start with the problem in front of you, from installation and offline deployment to custom agents.

\n
\n \n
\n
\n\n
\n
\n

Spend less time wrestling with setup. Start building sooner.

\n

AgentBoot is open source under the MIT License. Start with one command; every choice stays in your hands.

\n \n
\n
\n
\n\n \n\n\n","type":"text/html; charset=utf-8","etag":"\"e308bf93b5165b3d\""},"/404.html":{"body":"\n\n\n \n \n \n \n 页面未找到 · AgentBoot\n \n \n\n\n
\n
\n

404

\n

这条路径没有 Agent,回到启动台吧

\n

地址可能已变更,或只是多输入了一个字符。项目主页、安装命令和文档都还在。

\n \n
\n
\n\n\n","type":"text/html; charset=utf-8","etag":"\"92d469229bf5cde6\""},"/assets/site.css":{"body":":root {\n color-scheme: light;\n --ink-950: #12251d;\n --ink-800: #294238;\n --ink-600: #5b7067;\n --ink-400: #91a198;\n --paper: #fffdf5;\n --surface: #ffffff;\n --soft: #f2f7f2;\n --line: #dce7df;\n --green: #137a52;\n --green-dark: #0d5e3e;\n --green-soft: #e3f5eb;\n --sun: #ffd84d;\n --sun-soft: #fff3b9;\n --coral: #ff7a59;\n --sky: #dff3ff;\n --success: #137a52;\n --warning: #a65e00;\n --error: #b42318;\n --info: #176b87;\n --code: #10251d;\n --code-text: #ecfff4;\n --display: ui-rounded, \"Avenir Next Rounded\", \"SF Pro Rounded\", \"Segoe UI\", sans-serif;\n --body: Inter, ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif;\n --mono: \"SFMono-Regular\", Consolas, \"Liberation Mono\", monospace;\n --ease: cubic-bezier(.2, .8, .2, 1);\n}\n\n* {\n box-sizing: border-box;\n}\n\nhtml {\n overflow-x: clip;\n scroll-behavior: smooth;\n scroll-padding-top: 88px;\n}\n\nbody {\n margin: 0;\n background: var(--paper);\n color: var(--ink-950);\n font-family: var(--body);\n font-size: 16px;\n line-height: 1.68;\n text-rendering: optimizeLegibility;\n -webkit-font-smoothing: antialiased;\n}\n\nbutton,\na {\n -webkit-tap-highlight-color: transparent;\n}\n\na {\n color: var(--green-dark);\n text-decoration-thickness: 1.5px;\n text-underline-offset: .2em;\n}\n\na:hover {\n color: var(--green);\n}\n\n:focus-visible {\n outline: 3px solid var(--sun);\n outline-offset: 3px;\n}\n\n.skip-link {\n position: fixed;\n z-index: 100;\n top: 12px;\n left: 12px;\n translate: 0 -150%;\n border: 1px solid var(--ink-950);\n border-radius: 10px;\n background: var(--surface);\n color: var(--ink-950);\n padding: 10px 14px;\n font-weight: 700;\n}\n\n.skip-link:focus {\n translate: 0;\n}\n\n.shell {\n width: min(1180px, calc(100% - 48px));\n margin-inline: auto;\n}\n\n.site-nav {\n position: relative;\n z-index: 10;\n display: flex;\n min-height: 76px;\n align-items: center;\n justify-content: space-between;\n gap: 24px;\n}\n\n.brand {\n display: inline-flex;\n min-height: 44px;\n align-items: center;\n gap: 11px;\n color: var(--ink-950);\n font-family: var(--display);\n font-size: 18px;\n font-weight: 800;\n letter-spacing: -.025em;\n text-decoration: none;\n}\n\n.brand-mark {\n position: relative;\n display: inline-grid;\n width: 34px;\n height: 34px;\n place-items: center;\n overflow: hidden;\n border: 2px solid var(--ink-950);\n border-radius: 11px;\n background: var(--sun);\n}\n\n.brand-mark::before,\n.brand-mark::after {\n content: \"\";\n position: absolute;\n height: 2px;\n border-radius: 999px;\n background: var(--ink-950);\n transform-origin: left center;\n}\n\n.brand-mark::before {\n width: 12px;\n translate: -1px -3px;\n rotate: 38deg;\n}\n\n.brand-mark::after {\n width: 10px;\n translate: 2px 5px;\n}\n\n.nav-links {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.nav-link,\n.language-link {\n display: inline-flex;\n min-height: 44px;\n align-items: center;\n justify-content: center;\n border-radius: 10px;\n color: var(--ink-800);\n padding: 8px 11px;\n font-size: 14px;\n font-weight: 650;\n text-decoration: none;\n}\n\n.nav-link:hover,\n.language-link:hover {\n background: var(--green-soft);\n color: var(--green-dark);\n}\n\n.language-link {\n border: 1px solid var(--line);\n background: rgba(255, 255, 255, .72);\n}\n\n.hero {\n position: relative;\n display: grid;\n min-height: 660px;\n align-items: center;\n grid-template-columns: minmax(0, 7fr) minmax(340px, 5fr);\n gap: clamp(32px, 6vw, 86px);\n padding-block: 72px 112px;\n}\n\n.hero::before {\n content: \"\";\n position: absolute;\n z-index: -2;\n top: 2%;\n right: 0;\n width: min(48vw, 620px);\n aspect-ratio: 1;\n border-radius: 50%;\n background: var(--sun-soft);\n}\n\n.hero::after {\n content: \"\";\n position: absolute;\n z-index: -1;\n bottom: 9%;\n left: 0;\n width: min(30vw, 380px);\n aspect-ratio: 1;\n border-radius: 50%;\n background: var(--sky);\n opacity: .7;\n}\n\n.eyebrow {\n display: inline-flex;\n align-items: center;\n gap: 9px;\n margin: 0 0 22px;\n color: var(--green-dark);\n font-size: 13px;\n font-weight: 750;\n letter-spacing: .08em;\n text-transform: uppercase;\n}\n\n.eyebrow::before {\n content: \"\";\n width: 9px;\n height: 9px;\n border-radius: 50%;\n background: var(--coral);\n box-shadow: 0 0 0 5px rgba(255, 122, 89, .14);\n}\n\nh1,\nh2,\nh3 {\n font-family: var(--display);\n text-wrap: balance;\n}\n\nh1 {\n max-width: 800px;\n margin: 0;\n font-size: clamp(48px, 7.1vw, 88px);\n font-weight: 800;\n letter-spacing: -.06em;\n line-height: .98;\n}\n\n.hero-highlight {\n position: relative;\n display: inline-block;\n white-space: nowrap;\n}\n\n.hero-highlight::after {\n content: \"\";\n position: absolute;\n z-index: -1;\n right: -.08em;\n bottom: .04em;\n left: -.02em;\n height: .24em;\n border-radius: 99px;\n background: var(--sun);\n rotate: -1.5deg;\n}\n\n.hero-copy {\n max-width: 650px;\n margin: 28px 0 0;\n color: var(--ink-600);\n font-size: clamp(17px, 2vw, 21px);\n line-height: 1.62;\n}\n\n.hero-actions {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n margin-top: 34px;\n}\n\n.button {\n display: inline-flex;\n min-height: 48px;\n align-items: center;\n justify-content: center;\n gap: 9px;\n border: 1px solid var(--ink-950);\n border-radius: 12px;\n padding: 11px 17px;\n font-size: 15px;\n font-weight: 750;\n line-height: 1;\n text-decoration: none;\n transition: translate 160ms var(--ease), background-color 160ms var(--ease), color 160ms var(--ease);\n}\n\n.button-primary {\n background: var(--green);\n color: #fff;\n border-color: var(--green);\n}\n\n.button-primary:hover {\n background: var(--green-dark);\n color: #fff;\n translate: 0 -2px;\n}\n\n.button-secondary {\n background: var(--surface);\n color: var(--ink-950);\n}\n\n.button-secondary:hover {\n background: var(--sun-soft);\n color: var(--ink-950);\n translate: 0 -2px;\n}\n\n.button svg,\n.text-link svg {\n width: 18px;\n height: 18px;\n flex: 0 0 auto;\n fill: none;\n stroke: currentColor;\n stroke-linecap: round;\n stroke-linejoin: round;\n stroke-width: 1.8;\n}\n\n.hero-proof {\n display: flex;\n flex-wrap: wrap;\n gap: 10px 18px;\n margin: 26px 0 0;\n padding: 0;\n color: var(--ink-600);\n font-size: 13px;\n font-weight: 650;\n list-style: none;\n}\n\n.hero-proof li {\n display: flex;\n align-items: center;\n gap: 7px;\n}\n\n.hero-proof li::before {\n content: \"\";\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--green);\n}\n\n.launch-visual {\n position: relative;\n min-height: 450px;\n}\n\n.orbit {\n position: absolute;\n inset: 0;\n margin: auto;\n border: 1px solid rgba(18, 37, 29, .18);\n border-radius: 50%;\n}\n\n.orbit-one {\n width: min(100%, 430px);\n aspect-ratio: 1;\n}\n\n.orbit-two {\n width: min(76%, 330px);\n aspect-ratio: 1;\n border-style: dashed;\n}\n\n.orbit-dot {\n position: absolute;\n top: 10%;\n right: 14%;\n width: 18px;\n height: 18px;\n border: 3px solid var(--paper);\n border-radius: 50%;\n background: var(--coral);\n box-shadow: 0 0 0 1px var(--ink-950);\n}\n\n.terminal {\n position: absolute;\n inset: 50% auto auto 50%;\n width: min(94%, 390px);\n overflow: hidden;\n border: 2px solid var(--ink-950);\n border-radius: 22px;\n background: var(--code);\n box-shadow: 18px 18px 0 var(--sun);\n color: var(--code-text);\n translate: -50% -50%;\n}\n\n.terminal-bar {\n display: flex;\n min-height: 48px;\n align-items: center;\n justify-content: space-between;\n border-bottom: 1px solid rgba(255, 255, 255, .13);\n padding: 0 17px;\n color: #b9d3c4;\n font-family: var(--mono);\n font-size: 12px;\n}\n\n.terminal-dots {\n display: flex;\n gap: 6px;\n}\n\n.terminal-dots i {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--coral);\n}\n\n.terminal-dots i:nth-child(2) {\n background: var(--sun);\n}\n\n.terminal-dots i:nth-child(3) {\n background: #57d49b;\n}\n\n.terminal-body {\n min-height: 238px;\n padding: 26px 22px;\n font-family: var(--mono);\n font-size: clamp(12px, 1.35vw, 14px);\n line-height: 1.8;\n}\n\n.terminal-body p {\n margin: 0 0 12px;\n}\n\n.prompt {\n color: #69e4a7;\n}\n\n.terminal-muted {\n color: #9bb7a8;\n}\n\n.terminal-check {\n color: var(--sun);\n}\n\n.section {\n padding-block: clamp(72px, 10vw, 120px);\n}\n\n.section-soft {\n position: relative;\n background: var(--soft);\n}\n\n.section-soft::before,\n.section-soft::after {\n content: \"\";\n position: absolute;\n right: 0;\n left: 0;\n height: 1px;\n background: var(--line);\n}\n\n.section-soft::before {\n top: 0;\n}\n\n.section-soft::after {\n bottom: 0;\n}\n\n.section-heading {\n display: grid;\n align-items: end;\n grid-template-columns: minmax(0, 4fr) minmax(280px, 3fr);\n gap: 32px;\n margin-bottom: 54px;\n}\n\n.kicker {\n margin: 0 0 12px;\n color: var(--green);\n font-size: 13px;\n font-weight: 750;\n letter-spacing: .08em;\n text-transform: uppercase;\n}\n\nh2 {\n max-width: 700px;\n margin: 0;\n font-size: clamp(34px, 4.8vw, 56px);\n font-weight: 800;\n letter-spacing: -.045em;\n line-height: 1.06;\n}\n\n.section-lede {\n max-width: 56ch;\n margin: 0;\n color: var(--ink-600);\n font-size: 17px;\n}\n\n.install-layout {\n display: grid;\n align-items: start;\n grid-template-columns: minmax(240px, 4fr) minmax(0, 8fr);\n gap: clamp(34px, 7vw, 88px);\n}\n\n.install-intro {\n position: sticky;\n top: 104px;\n}\n\n.install-intro h2 {\n font-size: clamp(34px, 4vw, 48px);\n}\n\n.install-intro p {\n color: var(--ink-600);\n}\n\n.security-note {\n display: grid;\n grid-template-columns: 38px 1fr;\n gap: 13px;\n margin-top: 28px;\n padding-top: 22px;\n border-top: 1px solid var(--line);\n color: var(--ink-600);\n font-size: 14px;\n}\n\n.security-icon {\n display: grid;\n width: 38px;\n height: 38px;\n place-items: center;\n border-radius: 12px;\n background: var(--green-soft);\n color: var(--green-dark);\n}\n\n.security-icon svg {\n width: 21px;\n height: 21px;\n fill: none;\n stroke: currentColor;\n stroke-linecap: round;\n stroke-linejoin: round;\n stroke-width: 1.8;\n}\n\n.security-note p {\n margin: 0;\n}\n\n.command-stack {\n display: grid;\n gap: 16px;\n}\n\n.command-card {\n overflow: hidden;\n border: 1px solid var(--ink-950);\n border-radius: 20px;\n background: var(--surface);\n}\n\n.command-head {\n display: flex;\n min-height: 56px;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n border-bottom: 1px solid var(--line);\n padding: 10px 12px 10px 20px;\n}\n\n.command-platform {\n display: flex;\n align-items: center;\n gap: 11px;\n font-weight: 750;\n}\n\n.platform-dot {\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: var(--coral);\n}\n\n.command-card:nth-child(2) .platform-dot {\n background: #2f80ed;\n}\n\n.copy-button {\n display: inline-flex;\n min-width: 90px;\n min-height: 44px;\n align-items: center;\n justify-content: center;\n gap: 7px;\n border: 1px solid var(--line);\n border-radius: 10px;\n background: var(--soft);\n color: var(--ink-950);\n padding: 8px 12px;\n font: 700 13px/1 var(--body);\n cursor: pointer;\n transition: background-color 160ms var(--ease), border-color 160ms var(--ease);\n}\n\n.copy-button:hover {\n border-color: var(--green);\n background: var(--green-soft);\n}\n\n.copy-button[data-state=\"success\"] {\n border-color: var(--green);\n background: var(--green-soft);\n color: var(--green-dark);\n}\n\n.copy-button[data-state=\"error\"] {\n border-color: var(--error);\n background: #fff0ed;\n color: var(--error);\n}\n\n.copy-button svg {\n width: 16px;\n height: 16px;\n fill: none;\n stroke: currentColor;\n stroke-linecap: round;\n stroke-linejoin: round;\n stroke-width: 1.8;\n}\n\n.command-code {\n display: block;\n margin: 0;\n overflow-x: auto;\n background: var(--code);\n color: var(--code-text);\n padding: 24px 20px;\n font-family: var(--mono);\n font-size: 13px;\n line-height: 1.75;\n white-space: pre;\n scrollbar-color: #557266 var(--code);\n}\n\n.command-code::selection,\n.terminal ::selection {\n background: var(--sun);\n color: var(--ink-950);\n}\n\n.steps {\n display: grid;\n margin: 48px 0 0;\n padding: 0;\n counter-reset: step;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n list-style: none;\n}\n\n.step {\n position: relative;\n min-height: 180px;\n padding: 30px clamp(20px, 3vw, 34px);\n counter-increment: step;\n border-top: 1px solid var(--line);\n border-bottom: 1px solid var(--line);\n}\n\n.step + .step {\n border-left: 1px solid var(--line);\n}\n\n.step::before {\n content: \"0\" counter(step);\n display: block;\n margin-bottom: 30px;\n color: var(--coral);\n font: 750 13px/1 var(--mono);\n}\n\n.step h3 {\n margin: 0 0 8px;\n font-size: 19px;\n font-weight: 750;\n letter-spacing: -.02em;\n}\n\n.step p {\n margin: 0;\n color: var(--ink-600);\n font-size: 14px;\n}\n\n.inline-code,\n.rich-text code,\n.agent-table code,\n.feature-row code {\n border: 1px solid var(--line);\n border-radius: 6px;\n background: var(--surface);\n color: var(--green-dark);\n padding: .12em .42em;\n font-family: var(--mono);\n font-size: .88em;\n}\n\n.feature-layout {\n display: grid;\n align-items: start;\n grid-template-columns: minmax(280px, 5fr) minmax(0, 7fr);\n gap: clamp(40px, 8vw, 100px);\n}\n\n.feature-spotlight {\n position: sticky;\n top: 104px;\n overflow: hidden;\n border: 1px solid var(--ink-950);\n border-radius: 24px;\n background: var(--sun);\n padding: clamp(28px, 4vw, 44px);\n}\n\n.feature-spotlight::after {\n content: \"ab\";\n position: absolute;\n right: 0;\n bottom: -58px;\n color: rgba(18, 37, 29, .09);\n font: 800 clamp(120px, 18vw, 220px)/1 var(--display);\n letter-spacing: -.08em;\n}\n\n.feature-spotlight .kicker {\n color: var(--ink-800);\n}\n\n.feature-spotlight h3 {\n max-width: 470px;\n margin: 0;\n font-size: clamp(30px, 4vw, 48px);\n font-weight: 800;\n letter-spacing: -.045em;\n line-height: 1.08;\n}\n\n.feature-spotlight p {\n position: relative;\n z-index: 1;\n max-width: 48ch;\n margin: 24px 0 0;\n color: var(--ink-800);\n}\n\n.feature-list {\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.feature-row {\n display: grid;\n padding: 25px 0 28px;\n border-top: 1px solid var(--line);\n grid-template-columns: 44px 1fr;\n gap: 18px;\n}\n\n.feature-row:last-child {\n border-bottom: 1px solid var(--line);\n}\n\n.feature-index {\n color: var(--green);\n font: 750 12px/1.5 var(--mono);\n}\n\n.feature-row h3 {\n margin: -4px 0 7px;\n font-size: 20px;\n font-weight: 750;\n letter-spacing: -.025em;\n}\n\n.feature-row p {\n max-width: 60ch;\n margin: 0;\n color: var(--ink-600);\n font-size: 14px;\n}\n\n.agent-panel {\n overflow: hidden;\n border: 1px solid var(--ink-950);\n border-radius: 24px;\n background: var(--surface);\n}\n\n.agent-panel-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 20px;\n border-bottom: 1px solid var(--line);\n padding: 20px 24px;\n}\n\n.agent-count {\n display: flex;\n align-items: baseline;\n gap: 9px;\n}\n\n.agent-count strong {\n font: 800 38px/1 var(--display);\n letter-spacing: -.04em;\n}\n\n.agent-count span,\n.agent-legend {\n color: var(--ink-600);\n font-size: 13px;\n}\n\n.table-scroll {\n max-width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.agent-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 14px;\n}\n\n.agent-table th,\n.agent-table td {\n min-height: 52px;\n padding: 14px 20px;\n border-bottom: 1px solid var(--line);\n text-align: left;\n vertical-align: middle;\n}\n\n.agent-table th {\n background: var(--soft);\n color: var(--ink-600);\n font-size: 12px;\n font-weight: 750;\n letter-spacing: .04em;\n text-transform: uppercase;\n}\n\n.agent-table tr:last-child td {\n border-bottom: 0;\n}\n\n.agent-table tbody tr:hover {\n background: #fffdf3;\n}\n\n.agent-name {\n font-weight: 750;\n}\n\n.status {\n display: inline-flex;\n align-items: center;\n gap: 7px;\n white-space: nowrap;\n}\n\n.status::before {\n content: \"\";\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--ink-400);\n}\n\n.status-ready {\n color: var(--success);\n font-weight: 650;\n}\n\n.status-ready::before {\n background: var(--success);\n}\n\n.agent-footnote {\n margin: 0;\n border-top: 1px solid var(--line);\n background: var(--sun-soft);\n color: var(--ink-800);\n padding: 16px 22px;\n font-size: 13px;\n}\n\n.detail-grid {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 1px;\n border: 1px solid var(--line);\n background: var(--line);\n}\n\n.detail-block {\n min-height: 320px;\n background: var(--paper);\n padding: clamp(30px, 5vw, 58px);\n}\n\n.detail-block:nth-child(2) {\n background: var(--sky);\n}\n\n.detail-block h3 {\n max-width: 470px;\n margin: 0 0 20px;\n font-size: clamp(27px, 3vw, 38px);\n font-weight: 800;\n letter-spacing: -.04em;\n line-height: 1.1;\n}\n\n.rich-text {\n color: var(--ink-800);\n}\n\n.rich-text p {\n margin: 0 0 16px;\n}\n\n.rich-text ul {\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.rich-text li {\n position: relative;\n padding: 11px 0 11px 24px;\n border-top: 1px solid rgba(18, 37, 29, .15);\n}\n\n.rich-text li::before {\n content: \"\";\n position: absolute;\n top: 20px;\n left: 2px;\n width: 8px;\n height: 8px;\n border-radius: 2px;\n background: var(--green);\n rotate: 45deg;\n}\n\n.docs-list {\n display: grid;\n margin: 0;\n padding: 0;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 12px;\n list-style: none;\n}\n\n.docs-link {\n display: flex;\n min-height: 128px;\n flex-direction: column;\n justify-content: space-between;\n gap: 24px;\n border: 1px solid var(--line);\n border-radius: 18px;\n background: var(--surface);\n color: var(--ink-950);\n padding: 22px;\n text-decoration: none;\n transition: border-color 160ms var(--ease), translate 160ms var(--ease);\n}\n\n.docs-link:hover {\n border-color: var(--green);\n color: var(--green-dark);\n translate: 0 -3px;\n}\n\n.docs-link strong {\n font-size: 16px;\n}\n\n.docs-link span {\n color: var(--ink-600);\n font-size: 13px;\n}\n\n.text-link {\n display: inline-flex;\n align-items: center;\n gap: 7px;\n font-weight: 750;\n}\n\n.final-call {\n position: relative;\n overflow: hidden;\n contain: paint;\n border: 1px solid var(--ink-950);\n border-radius: 28px;\n background: var(--green);\n color: #fff;\n padding: clamp(36px, 7vw, 76px);\n}\n\n.final-call::after {\n content: \"\";\n position: absolute;\n right: -80px;\n bottom: -120px;\n width: 320px;\n height: 320px;\n border: 58px solid var(--sun);\n border-radius: 50%;\n opacity: .98;\n}\n\n.final-call h2 {\n position: relative;\n z-index: 1;\n max-width: 700px;\n font-size: clamp(36px, 6vw, 66px);\n}\n\n.final-call p {\n position: relative;\n z-index: 1;\n max-width: 55ch;\n margin: 22px 0 0;\n color: #dff8e9;\n font-size: 17px;\n}\n\n.final-call .hero-actions {\n position: relative;\n z-index: 1;\n}\n\n.final-call .button-primary {\n border-color: var(--sun);\n background: var(--sun);\n color: var(--ink-950);\n}\n\n.final-call .button-primary:hover {\n border-color: #ffe277;\n background: #ffe277;\n color: var(--ink-950);\n}\n\n.final-call .button-secondary {\n border-color: rgba(255, 255, 255, .5);\n background: transparent;\n color: #fff;\n}\n\n.final-call .button-secondary:hover {\n border-color: #fff;\n background: rgba(255, 255, 255, .1);\n color: #fff;\n}\n\n.site-footer {\n padding-block: 34px 44px;\n}\n\n.footer-row {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 30px;\n}\n\n.footer-note {\n max-width: 680px;\n margin: 13px 0 0;\n color: var(--ink-600);\n font-size: 13px;\n}\n\n.footer-links {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-end;\n gap: 6px 18px;\n font-size: 13px;\n font-weight: 650;\n}\n\n.footer-links a {\n min-height: 44px;\n display: inline-flex;\n align-items: center;\n}\n\n.not-found {\n display: grid;\n min-height: 100svh;\n place-items: center;\n padding: 40px 24px;\n}\n\n.not-found-card {\n position: relative;\n width: min(720px, 100%);\n overflow: hidden;\n border: 1px solid var(--ink-950);\n border-radius: 28px;\n background: var(--surface);\n padding: clamp(32px, 8vw, 72px);\n box-shadow: 18px 18px 0 var(--sun);\n}\n\n.not-found-code {\n margin: 0 0 28px;\n color: var(--coral);\n font: 800 clamp(60px, 15vw, 132px)/.8 var(--display);\n letter-spacing: -.07em;\n}\n\n.not-found h1 {\n max-width: 620px;\n font-size: clamp(34px, 7vw, 58px);\n line-height: 1.06;\n}\n\n.not-found p {\n max-width: 50ch;\n margin: 22px 0 0;\n color: var(--ink-600);\n}\n\n@media (prefers-reduced-motion: no-preference) {\n .hero-copy,\n .hero-actions,\n .hero-proof {\n animation: rise-in 620ms var(--ease) both;\n }\n\n .hero-actions {\n animation-delay: 100ms;\n }\n\n .hero-proof {\n animation-delay: 180ms;\n }\n\n .terminal {\n animation: terminal-in 720ms 80ms var(--ease) both;\n }\n\n .orbit-dot {\n animation: pulse 2.8s var(--ease) infinite;\n }\n\n @keyframes rise-in {\n from { opacity: 0; translate: 0 16px; }\n to { opacity: 1; translate: 0; }\n }\n\n @keyframes terminal-in {\n from { opacity: 0; translate: -46% -46%; }\n to { opacity: 1; translate: -50% -50%; }\n }\n\n @keyframes pulse {\n 50% { scale: 1.14; }\n }\n}\n\n@media (max-width: 900px) {\n .hero {\n min-height: auto;\n grid-template-columns: 1fr;\n padding-block: 54px 90px;\n }\n\n .launch-visual {\n min-height: 410px;\n }\n\n .section-heading,\n .install-layout,\n .feature-layout {\n grid-template-columns: 1fr;\n }\n\n .install-intro,\n .feature-spotlight {\n position: static;\n }\n\n .install-intro {\n display: grid;\n align-items: end;\n grid-template-columns: 1fr 1fr;\n gap: 30px;\n }\n\n .security-note {\n margin: 0;\n }\n\n .feature-spotlight {\n min-height: 310px;\n }\n}\n\n@media (max-width: 720px) {\n .shell {\n width: min(100% - 32px, 1180px);\n }\n\n .site-nav {\n min-height: 68px;\n }\n\n .nav-link {\n display: none;\n }\n\n .hero {\n gap: 42px;\n padding-top: 46px;\n }\n\n h1 {\n font-size: clamp(44px, 14vw, 68px);\n }\n\n .hero-copy {\n font-size: 17px;\n }\n\n .launch-visual {\n min-height: 350px;\n }\n\n .orbit-one {\n width: min(94%, 350px);\n }\n\n .orbit-two {\n width: min(72%, 270px);\n }\n\n .terminal {\n box-shadow: 11px 11px 0 var(--sun);\n }\n\n .terminal-body {\n min-height: 210px;\n padding: 22px 18px;\n }\n\n .section-heading {\n align-items: start;\n gap: 18px;\n margin-bottom: 38px;\n }\n\n .install-intro {\n display: block;\n }\n\n .security-note {\n margin-top: 24px;\n }\n\n .steps,\n .detail-grid,\n .docs-list {\n grid-template-columns: 1fr;\n }\n\n .step {\n min-height: auto;\n border-bottom: 0;\n padding: 24px 4px;\n }\n\n .step + .step {\n border-left: 0;\n }\n\n .step:last-child {\n border-bottom: 1px solid var(--line);\n }\n\n .step::before {\n margin-bottom: 16px;\n }\n\n .agent-panel-head,\n .footer-row {\n align-items: flex-start;\n flex-direction: column;\n }\n\n .agent-table th,\n .agent-table td {\n padding-inline: 14px;\n }\n\n .agent-table th:nth-child(4),\n .agent-table td:nth-child(4) {\n display: none;\n }\n\n .footer-links {\n justify-content: flex-start;\n }\n\n .final-call::after {\n right: -140px;\n bottom: -180px;\n }\n}\n\n@media (max-width: 480px) {\n .brand {\n font-size: 16px;\n }\n\n .brand-mark {\n width: 32px;\n height: 32px;\n }\n\n .language-link {\n padding-inline: 10px;\n }\n\n .hero-actions,\n .hero-actions .button {\n width: 100%;\n }\n\n .hero-proof {\n display: grid;\n grid-template-columns: 1fr 1fr;\n }\n\n .launch-visual {\n min-height: 320px;\n }\n\n .terminal {\n border-radius: 17px;\n }\n\n .terminal-bar {\n min-height: 42px;\n }\n\n .terminal-body {\n min-height: 190px;\n font-size: 11px;\n }\n\n .command-head {\n padding-left: 14px;\n }\n\n .copy-button {\n min-width: 82px;\n }\n\n .command-code {\n padding: 19px 14px;\n font-size: 11px;\n }\n\n .feature-spotlight {\n min-height: 330px;\n }\n\n .feature-row {\n grid-template-columns: 34px 1fr;\n gap: 10px;\n }\n\n .agent-table th:first-child,\n .agent-table td:first-child,\n .agent-table th:nth-child(4),\n .agent-table td:nth-child(4) {\n display: none;\n }\n\n .agent-table {\n font-size: 12px;\n }\n\n .agent-table th,\n .agent-table td {\n padding-inline: 10px;\n }\n\n .agent-legend {\n display: none;\n }\n\n .not-found-card {\n box-shadow: 10px 10px 0 var(--sun);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n html {\n scroll-behavior: auto;\n }\n\n *,\n *::before,\n *::after {\n animation-duration: .01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: .01ms !important;\n }\n}\n\n@media print {\n .site-nav,\n .hero-actions,\n .copy-button,\n .final-call,\n .site-footer {\n display: none;\n }\n\n body {\n background: #fff;\n }\n\n .section,\n .hero {\n min-height: auto;\n padding-block: 28px;\n }\n}\n","type":"text/css; charset=utf-8","etag":"\"93e52ab55ce71853\""},"/assets/site.js":{"body":"(function () {\n \"use strict\";\n\n var copyButtons = document.querySelectorAll(\"[data-copy]\");\n\n function legacyCopy(text) {\n var input = document.createElement(\"textarea\");\n input.value = text;\n input.setAttribute(\"readonly\", \"\");\n input.style.position = \"fixed\";\n input.style.opacity = \"0\";\n document.body.appendChild(input);\n input.select();\n var copied = document.execCommand(\"copy\");\n input.remove();\n return copied ? Promise.resolve() : Promise.reject(new Error(\"copy failed\"));\n }\n\n function copyText(text) {\n if (navigator.clipboard && window.isSecureContext) {\n return navigator.clipboard.writeText(text);\n }\n return legacyCopy(text);\n }\n\n copyButtons.forEach(function (button) {\n var idleLabel = button.getAttribute(\"data-label-idle\") || \"Copy\";\n var successLabel = button.getAttribute(\"data-label-success\") || \"Copied\";\n var errorLabel = button.getAttribute(\"data-label-error\") || \"Select command\";\n var label = button.querySelector(\"[data-copy-label]\");\n var timer;\n\n button.addEventListener(\"click\", function () {\n window.clearTimeout(timer);\n copyText(button.getAttribute(\"data-copy\") || \"\").then(function () {\n button.setAttribute(\"data-state\", \"success\");\n label.textContent = successLabel;\n }).catch(function () {\n button.setAttribute(\"data-state\", \"error\");\n label.textContent = errorLabel;\n }).finally(function () {\n timer = window.setTimeout(function () {\n button.removeAttribute(\"data-state\");\n label.textContent = idleLabel;\n }, 1800);\n });\n });\n });\n}());\n","type":"text/javascript; charset=utf-8","etag":"\"e32ad7eff5bfef9a\""},"/assets/favicon.svg":{"body":"\n \n \n\n","type":"image/svg+xml; charset=utf-8","etag":"\"97f7d8aaef171778\""}}); diff --git a/cloudflare/worker.js b/cloudflare/worker.js index bd1e53a..e514c85 100644 --- a/cloudflare/worker.js +++ b/cloudflare/worker.js @@ -6,9 +6,9 @@ import { WEB_ASSETS } from "./web-assets.js"; const REPO = "bit-cook/AgentBoot"; -const TAG = "v1.1.0"; +const TAG = "v1.2.0"; const GH_REL = `https://github.com/${REPO}/releases/download/${TAG}`; -const ASSET_CACHE = "public, max-age=86400, stale-while-revalidate=604800"; +const ASSET_CACHE = "public, max-age=31536000, immutable"; const PAGE_CACHE = "public, max-age=300, stale-while-revalidate=3600"; export default { @@ -24,7 +24,7 @@ export default { await Promise.all(required.map(async (name) => { try { const response = await fetch(`${GH_REL}/${name}`, { - method: "HEAD", headers: { "User-Agent": "AgentBoot-Worker/1.1" }, + method: "HEAD", headers: { "User-Agent": "AgentBoot-Worker/1.2" }, cf: { cacheEverything: false }, }); assets[name] = response.status; @@ -61,7 +61,7 @@ export default { }; async function proxy(target, contentType, cacheTtl, incoming = null) { - const requestHeaders = new Headers({ "User-Agent": "AgentBoot-Worker/1.1" }); + const requestHeaders = new Headers({ "User-Agent": "AgentBoot-Worker/1.2" }); if (incoming) { for (const name of ["Range", "If-Range", "If-None-Match", "If-Modified-Since"]) { const value = incoming.headers.get(name); diff --git a/core/agent.py b/core/agent.py index 52f8109..9b88a7e 100644 --- a/core/agent.py +++ b/core/agent.py @@ -27,7 +27,7 @@ try: VERSION = open(os.path.join(APP_DIR, "VERSION"), "r", encoding="ascii").read().strip() except OSError: - VERSION = "1.1.0" + VERSION = "1.2.0" AB_HOME = os.environ.get("AGENTBOOT_HOME") or os.path.join(os.path.expanduser("~"), ".agentboot") CONFIG_PATH = os.path.join(AB_HOME, "config.json") KB_DIR = os.path.join(APP_DIR, "tools", "linux-kb") diff --git a/docs/en/install-guide.md b/docs/en/install-guide.md index 62263bc..1ebb748 100644 --- a/docs/en/install-guide.md +++ b/docs/en/install-guide.md @@ -1,6 +1,6 @@ # AgentBoot Installation Guide -> **v1.1.0** · Linux / macOS / Windows · CLI UI in Chinese by default (switchable to English: `agentboot lang en`) +> **v1.2.0** · Linux / macOS / Windows · CLI UI in Chinese by default (switchable to English: `agentboot lang en`) > AgentBoot is a minimal, fast, ready-to-run AI Agent launcher: it ships a built-in fallback agent (free **Agnes** model by default), while the other agents (Claude Code, Codex, Qwen Code, OpenCode, CodeBuddy, MiMo Code, Cline, Pi, CoCo, …) are installed **from a menu of your choice**. **目录 / Table of contents**: [One-command online install](#one-command-online-install) · [One-command offline install](#one-command-offline-install) · [Custom agents](#custom-agents-beyond-the-registry) · [Custom offline packages](#custom-offline-packages-slim) · [China network](#china-network-adaptive) · [Model providers](#model-providers) · [Built-in agent](#built-in-agent-ab) · [Upgrade & uninstall](#upgrade--uninstall) · [Troubleshooting](#online-install-troubleshooting) · [FAQ](#faq) @@ -43,9 +43,9 @@ Three steps: **① get an offline package → ② copy & extract → ③ run the ### Step 1 — Get an offline package - **Option A**: download from [Releases](https://github.com/bit-cook/AgentBoot/releases) - - `AgentBoot-offline-v1.1.0-win-x64-codex.zip` (Windows x64) - - `AgentBoot-offline-v1.1.0-linux-x64-codex.tar.gz` (Linux x64) - - `AgentBoot-offline-v1.1.0-linux-x64-codex-sfx.sh` (Linux x64 self-extracting file) + - `AgentBoot-offline-v1.2.0-win-x64-codex.zip` (Windows x64) + - `AgentBoot-offline-v1.2.0-linux-x64-codex.tar.gz` (Linux x64) + - `AgentBoot-offline-v1.2.0-linux-x64-codex-sfx.sh` (Linux x64 self-extracting file) - **Option B — build your own slim package** (recommended; see [Custom offline packages](#custom-offline-packages-slim)): pick platforms and agents, output goes to `dist/`. @@ -54,9 +54,9 @@ Three steps: **① get an offline package → ② copy & extract → ③ run the | Target machine | How | |---|---| | Windows (any) | Right-click the ZIP → Extract All (built into Explorer) | -| Windows 10/11 (CLI) | `tar -xf AgentBoot-offline-v1.1.0-win-x64-codex.zip` | -| Linux x64 | `tar -xzf AgentBoot-offline-v1.1.0-linux-x64-codex.tar.gz -C ~` | -| Minimal Linux x64 | `sh AgentBoot-offline-v1.1.0-linux-x64-codex-sfx.sh` | +| Windows 10/11 (CLI) | `tar -xf AgentBoot-offline-v1.2.0-win-x64-codex.zip` | +| Linux x64 | `tar -xzf AgentBoot-offline-v1.2.0-linux-x64-codex.tar.gz -C ~` | +| Minimal Linux x64 | `sh AgentBoot-offline-v1.2.0-linux-x64-codex-sfx.sh` | ### Step 3 — Run the offline installer diff --git "a/docs/zh/\345\256\211\350\243\205\346\214\207\345\215\227.md" "b/docs/zh/\345\256\211\350\243\205\346\214\207\345\215\227.md" index 2a2fbf5..9f9537f 100644 --- "a/docs/zh/\345\256\211\350\243\205\346\214\207\345\215\227.md" +++ "b/docs/zh/\345\256\211\350\243\205\346\214\207\345\215\227.md" @@ -1,6 +1,6 @@ # AgentBoot 安装指南 -> **版本 v1.1.0** · 支持 Linux / macOS / Windows · 界面默认中文(切换:`agentboot lang en`) +> **版本 v1.2.0** · 支持 Linux / macOS / Windows · 界面默认中文(切换:`agentboot lang en`) > 语言 / Language: 中文(本页) | [English](../en/install-guide.md) | [根目录中文指南](../../安装指南.md) > AgentBoot 是一个极简、极速、开箱即用的 AI Agent 启动器:内置保底 Agent,其余 Agent 通过菜单自选安装。离线能力以注册表和目标平台构建验证为准;Aider 与 OpenCode 当前仅在线安装,Hermes 必须在目标平台原生构建。 @@ -61,9 +61,9 @@ curl -fsSL https://bit-cook.github.io/AgentBoot/install.sh | sh - **方式 A(推荐)**:到 GitHub Releases 下载现成的离线包 `https://github.com/bit-cook/AgentBoot/releases` → 选择 - - `AgentBoot-offline-v1.1.0-win-x64-codex.zip`(Windows x64) - - `AgentBoot-offline-v1.1.0-linux-x64-codex.tar.gz`(Linux x64) - - `AgentBoot-offline-v1.1.0-linux-x64-codex-sfx.sh`(Linux x64 自解压单文件) + - `AgentBoot-offline-v1.2.0-win-x64-codex.zip`(Windows x64) + - `AgentBoot-offline-v1.2.0-linux-x64-codex.tar.gz`(Linux x64) + - `AgentBoot-offline-v1.2.0-linux-x64-codex-sfx.sh`(Linux x64 自解压单文件) - **方式 B(自建)**:在有网的 Linux/macOS 或 Windows 机器上运行项目自带的构建脚本, 自动从 npmmirror 镜像拉取全部 Agent 离线载荷并打包: @@ -83,9 +83,9 @@ curl -fsSL https://bit-cook.github.io/AgentBoot/install.sh | sh | 目标机器情况 | 解压方法 | |---|---| | **Windows(任意版本)** | 直接**右键 ZIP → 全部解压缩**。Windows 资源管理器自带 ZIP 支持,无需安装任何软件 | -| **Windows 10/11(命令行党)** | 系统自带 `tar`:`tar -xf AgentBoot-offline-v1.1.0-win-x64-codex.zip` | -| **Linux x64** | 系统自带 `tar`:`tar -xzf AgentBoot-offline-v1.1.0-linux-x64-codex.tar.gz -C ~` | -| **Linux x64 极简环境** | 用自解压单文件:`sh AgentBoot-offline-v1.1.0-linux-x64-codex-sfx.sh` | +| **Windows 10/11(命令行党)** | 系统自带 `tar`:`tar -xf AgentBoot-offline-v1.2.0-win-x64-codex.zip` | +| **Linux x64** | 系统自带 `tar`:`tar -xzf AgentBoot-offline-v1.2.0-linux-x64-codex.tar.gz -C ~` | +| **Linux x64 极简环境** | 用自解压单文件:`sh AgentBoot-offline-v1.2.0-linux-x64-codex-sfx.sh` | > 自解压包 `*-sfx.sh` 本身就是一个 shell 脚本 + 内嵌 base64 数据,`sh xxx-sfx.sh` 即自动解压并直接进入安装流程,非常适合只有最小化系统的服务器。 diff --git a/install.sh b/install.sh index 0740f02..1c86fbe 100755 --- a/install.sh +++ b/install.sh @@ -9,7 +9,7 @@ set -eu REPO="bit-cook/AgentBoot" -TAG="v1.1.0" +TAG="v1.2.0" TARBALL="agentboot-online-${TAG}.tar.gz" BOOT_BASE="https://boot.ide.pub" GH="https://github.com/${REPO}/releases/download/${TAG}" @@ -156,7 +156,7 @@ OLD_APP="${AB_ROOT}/app.old.$$" rm -rf "$NEW_APP" "$OLD_APP" mkdir -p "$NEW_APP" cp -R "${SRC_DIR}/." "$NEW_APP/" -if [ ! -f "$NEW_APP/core/menu.py" ] || [ ! -f "$NEW_APP/core/agent.py" ]; then +if [ ! -f "$NEW_APP/core/menu.py" ] || [ ! -f "$NEW_APP/core/agent.py" ] || [ ! -f "$NEW_APP/core/launch.py" ]; then err "安装包结构无效,保留现有版本" rm -rf "$NEW_APP" exit 1 diff --git a/pages/en/index.html b/pages/en/index.html index bd63708..e906cee 100644 --- a/pages/en/index.html +++ b/pages/en/index.html @@ -33,7 +33,7 @@
-

v1.1.0 · Free and open source · Three platforms

+

v1.2.0 · Free and open source · Three platforms

One command.
Agents ready.

Bring installation, models, mirrors, offline packs, and safe uninstall into one clear menu. You choose the AI agents you need; AgentBoot installs them reliably.

@@ -190,7 +190,7 @@

Even if other agents won't install, ab works right away

Install without internet access

Verified offline packs bring the complete runtime with you

-

v1.1.0 initially provides slim Codex packs for Linux x64 and Windows x64. CI installs each pack, runs its version command, and uninstalls it.

+

v1.2.0 initially provides slim Codex packs for Linux x64 and Windows x64. CI installs each pack, runs its version command, and uninstalls it.

  • Verified slim packs: download from Releases and carry them to the target machine.
  • Custom offline packs: use menu [7] or build-offline on the target platform.
  • diff --git a/pages/index.html b/pages/index.html index 67bde04..2e01173 100644 --- a/pages/index.html +++ b/pages/index.html @@ -33,7 +33,7 @@
    -

    v1.1.0 · 免费开源 · 三平台可用

    +

    v1.2.0 · 免费开源 · 三平台可用

    一条命令,
    Agent 就位

    把安装、模型、镜像、离线包和安全卸载收进一个清楚的菜单。你选择要用的 AI Agent,AgentBoot 负责把它可靠地装好。

    @@ -190,7 +190,7 @@

    即使其他 Agent 装不上,ab 也能马上工作

    没有网络,也能安装

    可验证离线包,把完整运行环境一起带走

    -

    v1.1.0 首批提供 Linux x64 与 Windows x64 Codex 精简包,CI 实际执行安装、版本启动与卸载。

    +

    v1.2.0 首批提供 Linux x64 与 Windows x64 Codex 精简包,CI 实际执行安装、版本启动与卸载。

    • 已验证精简包:从 Releases 下载后直接带到目标机。
    • 自建离线包:用菜单 [7]build-offline 在目标平台按需构建。
    • diff --git a/pages/install.ps1 b/pages/install.ps1 index 6509068..d403b90 100644 --- a/pages/install.ps1 +++ b/pages/install.ps1 @@ -9,7 +9,7 @@ $ProgressPreference = 'SilentlyContinue' try { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 } catch {} $Repo = 'bit-cook/AgentBoot' -$Tag = 'v1.1.0' +$Tag = 'v1.2.0' $ZipName = "agentboot-online-$Tag.zip" $BootBase = 'https://boot.ide.pub' $GH = "https://github.com/$Repo/releases/download/$Tag" @@ -58,7 +58,8 @@ function Install-AppAtomic([string]$source, [string]$destination) { New-Item -ItemType Directory -Path $newApp -Force | Out-Null Copy-Item -Path (Join-Path $source '*') -Destination $newApp -Recurse -Force if (-not (Test-Path (Join-Path $newApp 'core\menu.py')) -or - -not (Test-Path (Join-Path $newApp 'core\agent.py'))) { + -not (Test-Path (Join-Path $newApp 'core\agent.py')) -or + -not (Test-Path (Join-Path $newApp 'core\launch.py'))) { throw '安装包结构无效' } if (Test-Path $destination) { Move-Item $destination $oldApp } @@ -240,7 +241,7 @@ rem AgentBoot 控制台 set "AB_INSTALL=%~dp0.." set "PYTHON=$pyCommand" if exist "%AB_INSTALL%\runtime\python\python.exe" set "PYTHON=%AB_INSTALL%\runtime\python\python.exe" -"%PYTHON%" "%AB_INSTALL%\app\core\menu.py" %* +"%PYTHON%" "%AB_INSTALL%\app\core\launch.py" menu %* "@ $abLauncher = @" @@ -249,7 +250,7 @@ rem AgentBoot 内置最小 Agent set "AB_INSTALL=%~dp0.." set "PYTHON=$pyCommand" if exist "%AB_INSTALL%\runtime\python\python.exe" set "PYTHON=%AB_INSTALL%\runtime\python\python.exe" -"%PYTHON%" "%AB_INSTALL%\app\core\agent.py" %* +"%PYTHON%" "%AB_INSTALL%\app\core\launch.py" agent %* "@ Set-LauncherAtomic (Join-Path $BinDir 'agentboot.cmd') $agentbootLauncher Set-LauncherAtomic (Join-Path $BinDir 'ab.cmd') $abLauncher diff --git a/pages/install.sh b/pages/install.sh index 0740f02..1c86fbe 100755 --- a/pages/install.sh +++ b/pages/install.sh @@ -9,7 +9,7 @@ set -eu REPO="bit-cook/AgentBoot" -TAG="v1.1.0" +TAG="v1.2.0" TARBALL="agentboot-online-${TAG}.tar.gz" BOOT_BASE="https://boot.ide.pub" GH="https://github.com/${REPO}/releases/download/${TAG}" @@ -156,7 +156,7 @@ OLD_APP="${AB_ROOT}/app.old.$$" rm -rf "$NEW_APP" "$OLD_APP" mkdir -p "$NEW_APP" cp -R "${SRC_DIR}/." "$NEW_APP/" -if [ ! -f "$NEW_APP/core/menu.py" ] || [ ! -f "$NEW_APP/core/agent.py" ]; then +if [ ! -f "$NEW_APP/core/menu.py" ] || [ ! -f "$NEW_APP/core/agent.py" ] || [ ! -f "$NEW_APP/core/launch.py" ]; then err "安装包结构无效,保留现有版本" rm -rf "$NEW_APP" exit 1 From 2f812c753508cfef80012784125e8085dcca6059 Mon Sep 17 00:00:00 2001 From: bit-cook Date: Mon, 31 Aug 2026 13:40:10 +0000 Subject: [PATCH 21/21] ci: allow temporary Linux runner override --- .github/workflows/release.yml | 8 ++++---- tests/test_release_workflow.py | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d90379d..d6eb3d2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ permissions: jobs: validate: - runs-on: ubuntu-latest + runs-on: ${{ vars.AGENTBOOT_LINUX_RUNNER || 'ubuntu-latest' }} steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: @@ -28,7 +28,7 @@ jobs: node --check cloudflare/worker.js online: - runs-on: ubuntu-latest + runs-on: ${{ vars.AGENTBOOT_LINUX_RUNNER || 'ubuntu-latest' }} steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: @@ -49,7 +49,7 @@ jobs: pages/VERSION offline-linux: - runs-on: ubuntu-latest + runs-on: ${{ vars.AGENTBOOT_LINUX_RUNNER || 'ubuntu-latest' }} steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: @@ -129,7 +129,7 @@ jobs: publish: needs: [validate, online, offline-linux, offline-windows, macos-smoke] if: github.ref_type == 'tag' - runs-on: ubuntu-latest + runs-on: ${{ vars.AGENTBOOT_LINUX_RUNNER || 'ubuntu-latest' }} environment: release-production permissions: contents: write diff --git a/tests/test_release_workflow.py b/tests/test_release_workflow.py index 0a49f81..113ad04 100644 --- a/tests/test_release_workflow.py +++ b/tests/test_release_workflow.py @@ -33,6 +33,7 @@ def test_release_supports_prerelease_dry_run_and_tag_only_publish(self): self.assertIn("install-offline.ps1\" -Agents codex", text) self.assertIn("runs-on: macos-15-intel", text) self.assertIn("PLATFORMS=darwin-x64", text) + self.assertIn("vars.AGENTBOOT_LINUX_RUNNER || 'ubuntu-latest'", text) def test_live_verifier_covers_primary_and_mirror(self): text = (ROOT / "scripts/verify-live-release.py").read_text(encoding="utf-8")