OpenHands Agent Canvas 的 npm 发布与库构建:从 CHANGELOG 看 `@openhands/agent-canvas` 的分发全貌
本文以仓库根目录的 CHANGELOG.md 为主线,逐条解读 @openhands/agent-canvas 首个 npm 发布版本(1.0.0-alpha.2)所声明的五项能力——npm 包发布、CLI 入口、库构建模式、子路径导出与类型声明——并对照仓库中的 package.json、bin/agent-canvas.mjs、vite.config.ts 与 .github/workflows/npm-publish.yml 等文件,说明这些能力在当前代码库中的真实实现与自动化发布流程。读完后你将掌握该 npm 包的用法、库导入方式,以及其基于 OIDC Trusted Publishing 与 release-please 的端到端发布机制。
一、CHANGELOG.md 的格式约定与版本骨架
CHANGELOG.md 全文遵循两个业界标准:
- 变更日志格式基于 Keep a Changelog 1.1.0;
- 版本号遵循 Semantic Versioning(SemVer 2.0.0)。
文件结构上,[Unreleased] 段用于积累未发布的变更,已发布版本以 ## [x.y.z] - 日期 标题分节,并用 ### Added 等小节归类变更类型。文档底部以 Markdown 链接定义方式维护版本锚点,例如 [1.0.0-alpha.2] 指向对应 release tag,[Unreleased] 指向与上一个 tag 的 compare 视图。
截至目前,仓库中记录的已发布条目只有一条:
## [1.0.0-alpha.2] - 2025-05-11—— Initial npm package release of@openhands/agent-canvas
需要指出的是,该包当前版本已远超 alpha.2:package.json 中 "version" 为 1.16.0,.release-please-manifest.json 也记录当前发布版本为 1.16.0。结合 release-please-config.json 中 "skip-changelog": true 的配置可以推断:alpha.2 之后的版本变更说明改由 release-please 在 release PR 与 GitHub Release 中自动生成,不再手工维护 CHANGELOG.md,因此该文件停留在首个 alpha 版本记录是符合仓库现状的。
二、1.0.0-alpha.2 的 Added 清单:逐项解读
CHANGELOG 中 1.0.0-alpha.2 的 ### Added 段落列出了六项能力。下面按原文顺序,结合仓库源码逐项展开。
1. 首个 npm 包发布:@openhands/agent-canvas
package.json 确认包名与基本定位:
"name": "@openhands/agent-canvas",描述为 “Agent Canvas UI for OpenHands - run AI coding agents with a visual interface”;"license": "MIT"、"private": false(已对外发布);"engines": { "node": ">=22.12.0" },且volta字段固定node: 22.12.0;"files"字段限定发布内容:dist、bin、build、config、scripts、tools——即 npm 包同时携带库产物、CLI 入口、预构建静态前端、默认配置与启动脚本。
2. CLI 入口:npx @openhands/agent-canvas 本地运行全栈
package.json 的 bin 字段将命令名 agent-canvas 映射到 bin/agent-canvas.mjs。该脚本文件头注释说明其定位:
Runs the full Agent Canvas stack locally by default: Agent-server via uvx, Automation backend via uvx, Pre-built static frontend. This is the production equivalent of
npm run dev.
即 CLI 通过 uvx 拉起 agent-server 与 automation 两个 Python 后端,再经 ingress 代理服务预构建的静态前端,是生产等价于 npm run dev 的单机全栈方案。
从源码看,该 CLI 支持以下参数与环境变量(以 bin/agent-canvas.mjs 中 --help 文案为准):
| 选项 / 环境变量 | 作用 |
|---|---|
-p, --port <port> |
ingress 端口,默认 8000 |
--public |
公共模式:必须提供 LOCAL_BACKEND_API_KEY,该 key 不注入前端,用户需在浏览器中手动粘贴 |
--frontend-only |
只启动静态前端(位于 ingress 之后),与 --backend-only 互斥 |
--backend-only |
只启动 agent-server + automation 后端 |
-v, --version |
打印版本号 |
--info |
打印默认栈版本与端口 |
LOCAL_BACKEND_API_KEY |
服务器 API key;非 --public 模式下省略则自动生成并跨重启持久化 |
OH_SECRET_KEY |
用于加密配置的密钥 |
OH_AGENT_SERVER_GIT_REF / OH_AGENT_SERVER_LOCAL_PATH / OH_AGENT_SERVER_VERSION |
指定 agent-server 的 Git ref、本地 SDK 检出路径或 PyPI 版本 |
默认端口等数值集中在 config/defaults.json:ingress(proxy)8000、agent-server 18000、automation 18001、容器内编辑器端口 8001;版本固定为 agentServer: 1.44.0、automation: 1.9.0,兼容下限 minimumAgentServer: 1.28.0。该文件注释自称“npm 与 Docker 两条安装路径共享的版本/端口/路径唯一事实源”,被 scripts/dev-safe.mjs、scripts/dev-with-automation.mjs、docker/entrypoint.sh 与 Docker 发布工作流共同读取。
脚本在启动前还会校验前端产物存在(检查包内 build/ 目录,见 bin/agent-canvas.mjs 中 existsSync(BUILD_DIR) 分支),缺失时提示先执行 npm install && npm run build,并明确这是针对源码运行场景的检查——从 npm 安装却缺失则属于打包错误。
3. 库构建模式与组件 barrel exports
CHANGELOG 声称的 “Library build mode with component barrel exports” 对应 package.json 中的:
"build:lib": "npm run make-i18n && react-router typegen && cross-env BUILD_LIB=true vite build && tsc -p tsconfig.lib.json"
其实现位于 vite.config.ts:当环境变量 BUILD_LIB=true 时,构建切换到库模式——
- 入口为
src/index.ts(源码中LIB_ENTRY常量),格式仅es; outDir: "dist"、sourcemap: true;rollupOptions.external排除react、react-dom、react/jsx-runtime、react/jsx-dev-runtime、react-router,即这些依赖不打包进产物,由消费方提供;- 输出
preserveModules的 ES 与 CJS 双格式([name].js/[name].cjs),preserveModulesRoot: "src"保持目录结构,使每个源码模块对应一个产物文件,从而支持子路径导入。
另外,库构建下 __EXTENSIONS_SKILLS_DIR__ 被注入为空字符串(vite.config.ts 中 define 配置),使消费方不被绑定到打包机器的 node_modules 路径——这是一个与库模式直接相关的细节:同一份代码在应用构建时注入本机 extensions skills 绝对路径,在库构建时改为由运行时回退到 "public"。
Barrel export 的入口链是 src/index.ts(仅一行 export * from "./lib")→ src/lib/index.ts,后者再依次 re-export 六个组件目录、providers(AgentServerUIProviders、AgentServerUIRoot 等)、query client 工厂、i18n(createAgentServerI18n、translationResources 等)、样式作用域常量(AGENT_SERVER_UI_SCOPE_SELECTOR 等)与遥测 API(configureTelemetry、trackEvent 等)。
4. 子路径导出(Subpath Exports)模块化导入
CHANGELOG 列出的七个子路径在 package.json 的 exports 字段中一一对应,全部指向 dist 下同名模块的 .js / .cjs / .d.ts:
| 子路径 | 指向产物 | 对应源目录 |
|---|---|---|
@openhands/agent-canvas(.) |
dist/index.{js,cjs,d.ts} |
src/index.ts → src/lib/index.ts |
@openhands/agent-canvas/browser |
dist/components/browser/index.* |
src/components/browser |
@openhands/agent-canvas/conversation |
dist/components/conversation/index.* |
src/components/conversation |
@openhands/agent-canvas/files |
dist/components/files/index.* |
src/components/files |
@openhands/agent-canvas/settings |
dist/components/settings/index.* |
src/components/settings |
@openhands/agent-canvas/sidebar |
dist/components/sidebar/index.* |
src/components/sidebar |
@openhands/agent-canvas/terminal |
dist/components/terminal/index.* |
src/components/terminal |
@openhands/agent-canvas/i18n |
dist/i18n/index.* |
src/i18n |
每个子路径均声明 types / import / require 三种条件,兼容 ESM 与 CJS 消费方;exports 同时保留 "./package.json" 供工具链读取元数据。库构建的 preserveModules 输出正是保证“源目录结构 == 产物目录结构”的前提,使这些子路径在打包后依然成立。
需要说明的配套约束:package.json 的 peerDependencies 将 react、react-dom 固定为 19.2.8、react-router 固定为 7.18.2,嵌入方需保证版本一致(或至少兼容),这与 vite.config.ts 库构建 external 列表相呼应。
5. TypeScript 类型声明
package.json 顶层 "types": "./dist/index.d.ts",子路径则各自携带 types 条件。声明文件由 tsconfig.lib.json 驱动生成:"emitDeclarationOnly": true、"declaration": true、"outDir": "dist"、"rootDir": "src",且 include 精确圈定了入口、src/lib、src/components、src/query-client-config.ts、src/i18n 及若干 settings/conversation 路由文件,exclude 掉全部测试文件。build:lib 脚本末尾的 tsc -p tsconfig.lib.json 即此步骤,与 vite build 的 JS 产物并行落在 dist/ 下。
6. GitHub Actions 自动化 npm 发布(OIDC Trusted Publishing)
对应的发布流水线是 .github/workflows/npm-publish.yml,关键设计如下:
- 触发条件:
v*tag 推送,或workflow_dispatch手动指定 release tag; - 权限:
contents: read+id-token: write——OIDC 可信发布所必需,全程无NPM_TOKEN凭据; - 环境要求:Node 24(注释注明可信发布要求 Node ≥ 22.14.0、npm ≥ 11.5.1),并有一步显式校验 npm 版本;
- 发布前步骤:
npm ci→npm test→npm run build(应用)→npm run build:lib(库)→ 将生产 PostHog 公钥烘焙进 config/defaults.json 的telemetry.posthogApiKey→npm pack --dry-run校验包内容 → 校验package.json版本与 release tag 一致; - dist-tag 策略:脚本查询 npm 上是否已存在稳定版(无预发布后缀)。在首个稳定版发布前,所有版本打
latest,保证npm install @openhands/agent-canvas始终解析到最新构建;出现稳定版后,-alpha/-beta/-rc版本分别回落各自的 dist-tag,仅稳定版保留latest。注释还解释了为何将 dist-tag 直接拼进npm publish --tag:OIDC token 只覆盖npm publish调用本身,单独执行npm dist-tag add会失败; - 发布命令:
npm publish --access public --provenance --tag <resolved>,--provenance附带构建溯源证明。
与发布衔接的上游是 release-please 驱动的打 tag 流程。.github/workflows/release.yml 在 main 或 release/** 分支推送时:先判断本次提交是否为 release-PR 合并产生的 chore(<scope>): release X.Y.Z squash 提交;若是,则轮询等待 test-and-build (ubuntu) 检查通过(最长 40 分钟),因为仓库的 “Release Tag” ruleset 要求 tag 提交上该检查必须为绿,否则 tag 推送会被 pre-receive 规则拒绝;随后调用 release-please 复用工作流创建 tag 与 Release。release-please-config.json 定义了 tag 前缀 v(include-v-in-tag: true)、release-type: node、draft-pull-request: true,并通过 extra-files 在发版时同步更新 config/defaults.json 的 $.versions.agentCanvas、helm/agent-canvas/Chart.yaml 以及两份 README 中的版本字符串——这也解释了为何 defaults.json 中 agentCanvas 与 package.json 同为 1.16.0。
三、版本对照:从 alpha.2 到当前仓库状态
将 CHANGELOG 声明与当前仓库证据放在一起,可以得到一张对照表:
| CHANGELOG(1.0.0-alpha.2)声明 | 当前仓库中的对应证据 |
|---|---|
npm 包 @openhands/agent-canvas |
package.json name / private: false,版本 1.16.0 |
CLI 入口 npx @openhands/agent-canvas |
bin/agent-canvas.mjs + bin 字段 |
| 库构建模式(barrel exports) | build:lib 脚本 + vite.config.ts 的 BUILD_LIB 分支 |
| 七个子路径导出 | package.json exports 字段逐条对应 |
| TypeScript 类型声明 | tsconfig.lib.json emitDeclarationOnly + types 字段 |
| OIDC 可信发布的 GitHub Actions | .github/workflows/npm-publish.yml |
四、小结
CHANGELOG.md 虽然只完整记录了 1.0.0-alpha.2 这一个版本,但它勾勒出的六项能力在此后的版本中全部保留并在仓库中留下了可验证的实现:以 uvx 拉起双后端 + 静态前端的 CLI(bin/agent-canvas.mjs、config/defaults.json),以 preserveModules 双格式产物支撑的子路径库导入(vite.config.ts、tsconfig.lib.json、src/lib/index.ts),以及由 release-please 打 tag、OIDC 可信发布加 provenance 推送 npm 的无凭据发布链(.github/workflows/release.yml、.github/workflows/npm-publish.yml、release-please-config.json)。对于希望把 Agent Canvas 以 npm 包形式嵌入自有系统、或需要理解其发版机制的开发者,以上文件路径即是最直接的事实依据与延伸阅读入口。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00