chore(i18n): refresh zh-CN translations

This commit is contained in:
openclaw-docs-i18n[bot] 2026-04-10 23:52:38 +00:00
parent d7cebbe43f
commit 827ad032e1
4 changed files with 940 additions and 975 deletions

View File

@ -1,56 +1,57 @@
---
read_when:
- 你需要了解某个 CI 作业为何运行或未运行
- 你需要了解为什么某个 CI 作业会运行或不会运行
- 你正在调试失败的 GitHub Actions 检查
summary: CI 作业图、作用域门控以及本地命令对应关系
summary: CI 作业图、作用域门禁,以及本地命令等效项
title: CI 流水线
x-i18n:
generated_at: "2026-04-09T02:58:23Z"
generated_at: "2026-04-10T23:44:34Z"
model: gpt-5.4
provider: openai
source_hash: d104f2510fadd674d7952aa08ad73e10f685afebea8d7f19adc1d428e2bdc908
source_hash: ca7e355b7f73bfe8ea8c6971e78164b8b2e68cbb27966964955e267fed89fce6
source_path: ci.md
workflow: 15
---
# CI 流水线
CI 会在每次推送到 `main` 以及每个拉取请求上运行。它使用智能作用域划分,仅在变更与相关区域有关时才运行高开销作业。
CI 会在每次推送到 `main` 以及每个拉取请求时运行。它使用智能作用域划分,在仅有不相关区域发生变更时跳过开销较大的作业。
## 作业概览
| 作业 | 用途 | 运行时机 |
| ------------------------ | ------------------------------------------------------------------------------------- | -------------------------------- |
| `preflight` | 检测仅文档变更、变更作用域、变更的扩展,并构建 CI 清单 | 所有非草稿的推送和 PR 都会运行 |
| `security-fast` | 私钥检测、通过 `zizmor` 进行工作流审计、生产依赖审计 | 所有非草稿的推送和 PR 都会运行 |
| `build-artifacts` | 构建 `dist/` 和 Control UI 一次,并上传供下游作业复用的制品 | 与 Node 相关的变更 |
| `checks-fast-core` | 快速 Linux 正确性通道,例如 bundled/plugin-contract/protocol 检查 | 与 Node 相关的变更 |
| `checks-fast-extensions` | 在 `checks-fast-extensions-shard` 完成后聚合扩展分片通道 | 与 Node 相关的变更 |
| `extension-fast` | 仅针对已变更的内置插件运行聚焦测试 | 检测到扩展变更时 |
| `check` | CI 中的主要本地门禁:`pnpm check` 加 `pnpm build:strict-smoke` | 与 Node 相关的变更 |
| `check-additional` | 架构、边界、导入循环防护,以及 Gateway 网关 watch 回归测试工具 | 与 Node 相关的变更 |
| `build-smoke` | 已构建 CLI 的 smoke 测试和启动内存 smoke 测试 | 与 Node 相关的变更 |
| `checks` | 更重的 Linux Node 通道:完整测试、渠道测试,以及仅在 push 时运行的 Node 22 兼容性测试 | 与 Node 相关的变更 |
| `check-docs` | 文档格式、lint 和失效链接检查 | 文档发生变更时 |
| `skills-python` | 面向 Python 支持的 Skills 的 Ruff + pytest | 与 Python Skills 相关的变更 |
| `checks-windows` | Windows 特定测试通道 | 与 Windows 相关的变更 |
| `macos-node` | 使用共享构建制品的 macOS TypeScript 测试通道 | 与 macOS 相关的变更 |
| `macos-swift` | macOS 应用的 Swift lint、构建和测试 | 与 macOS 相关的变更 |
| `android` | Android 构建和测试矩阵 | 与 Android 相关的变更 |
| 作业 | 目的 | 运行时机 |
| ------------------------ | ------------------------------------------------------------------------------------ | ----------------------------------- |
| `preflight` | 检测仅文档变更、变更作用域、变更的扩展,并构建 CI 清单 | 在所有非草稿推送和 PR 上始终运行 |
| `security-fast` | 私钥检测、通过 `zizmor` 进行工作流审计、生产依赖审计 | 在所有非草稿推送和 PR 上始终运行 |
| `build-artifacts` | 构建 `dist/` 和 Control UI 一次,并上传可供下游作业复用的制品 | 与 Node 相关的变更 |
| `checks-fast-core` | 快速 Linux 正确性通道,例如 bundled/plugin-contract/protocol 检查 | 与 Node 相关的变更 |
| `checks-node-extensions` | 跨整个扩展套件的完整 bundled-plugin 测试分片 | 与 Node 相关的变更 |
| `checks-node-core-test` | 核心 Node 测试分片不包括渠道、bundled、contract 和扩展通道 | 与 Node 相关的变更 |
| `extension-fast` | 仅针对已变更 bundled 插件的聚焦测试 | 检测到扩展变更时 |
| `check` | CI 中的主要本地门禁:`pnpm check` 加 `pnpm build:strict-smoke` | 与 Node 相关的变更 |
| `check-additional` | 架构、边界、导入循环防护,以及 Gateway 网关 watch 回归测试 harness | 与 Node 相关的变更 |
| `build-smoke` | 已构建 CLI 的冒烟测试和启动内存冒烟测试 | 与 Node 相关的变更 |
| `checks` | 剩余的 Linux Node 通道:渠道测试以及仅在推送时运行的 Node 22 兼容性检查 | 与 Node 相关的变更 |
| `check-docs` | 文档格式、lint 和损坏链接检查 | 文档发生变更时 |
| `skills-python` | 面向 Python 支持的 Skills 的 Ruff + pytest | 与 Python Skills 相关的变更 |
| `checks-windows` | Windows 特定测试通道 | 与 Windows 相关的变更 |
| `macos-node` | 使用共享构建制品的 macOS TypeScript 测试通道 | 与 macOS 相关的变更 |
| `macos-swift` | macOS 应用的 Swift lint、构建和测试 | 与 macOS 相关的变更 |
| `android` | Android 构建和测试矩阵 | 与 Android 相关的变更 |
## 快速失败顺序
作业的排序方式是让低成本检查先失败,避免高成本作业继续运行:
作业的排列顺序经过设计,以便让廉价检查先失败,避免昂贵作业过早运行:
1. `preflight` 决定哪些通道实际存在。`docs-scope` 和 `changed-scope` 逻辑是该作业中的步骤,而不是独立作业。
2. `security-fast`、`check`、`check-additional`、`check-docs` 和 `skills-python` 会快速失败,不必等待更重的制品和平台矩阵作业。
3. `build-artifacts` 会与快速 Linux 通道并行运行,这样下游使用方可以在共享构建准备好后立即启动
4. 然后更重的平台和运行时通道会展开:`checks-fast-core`、`checks-fast-extensions`、`extension-fast`、`checks`、`checks-windows`、`macos-node`、`macos-swift` 和 `android`
1. `preflight` 决定哪些通道实际存在。`docs-scope` 和 `changed-scope` 逻辑是这个作业内部的步骤,不是独立作业。
2. `security-fast`、`check`、`check-additional`、`check-docs` 和 `skills-python` 会快速失败,而不会等待更重的制品和平台矩阵作业。
3. `build-artifacts` 会与快速 Linux 通道并行运行,这样下游使用方一旦共享构建准备好就可以立即开始
4. 更重的平台和运行时通道会在此之后展开:`checks-fast-core`、`checks-node-extensions`、`checks-node-core-test`、`extension-fast`、`checks`、`checks-windows`、`macos-node`、`macos-swift` 和 `android`
作用域逻辑位于 `scripts/ci-changed-scope.mjs`其单元测试位于 `src/scripts/ci-changed-scope.test.ts`
`install-smoke` 工作流会通过它自己的 `preflight` 作业复用同一个作用域脚本。它会根据更窄的 changed-smoke 信号计算 `run_install_smoke`,因此 Docker/安装 smoke 只会在与安装、打包和容器相关的变更时运行。
作用域逻辑位于 `scripts/ci-changed-scope.mjs`并由 `src/scripts/ci-changed-scope.test.ts` 中的单元测试覆盖
独的 `install-smoke` 工作流会通过它自己的 `preflight` 作业复用同一个作用域脚本。它会基于更窄的 changed-smoke 信号计算 `run_install_smoke`,因此 Docker/安装冒烟测试只会在与安装、打包和容器相关的变更时运行。
push 上,`checks` 矩阵会增加仅限 push 的 `compat-node22` 通道。在拉取请求上,该通道会被跳过,矩阵将继续专注于常规测试/渠道通道。
推送时,`checks` 矩阵会增加仅推送时运行的 `compat-node22` 通道。在拉取请求中,该通道会被跳过,矩阵会继续聚焦于常规测试/渠道通道。
## 运行器
@ -60,7 +61,7 @@ CI 会在每次推送到 `main` 以及每个拉取请求上运行。它使用智
| `blacksmith-32vcpu-windows-2025` | `checks-windows` |
| `macos-latest` | `macos-node`、`macos-swift` |
## 本地对应命令
## 本地等效项
```bash
pnpm check # 类型检查 + lint + 格式检查
@ -69,6 +70,6 @@ pnpm check:import-cycles
pnpm test:gateway:watch-regression
pnpm test # vitest 测试
pnpm test:channels
pnpm check:docs # 文档格式 + lint + 失效链接检查
pnpm build # 当 CI 制品/build-smoke 通道相关时构建 dist
pnpm check:docs # 文档格式 + lint + 损坏链接检查
pnpm build # 当 CI 的 artifact/build-smoke 通道相关时,构建 dist
```

File diff suppressed because it is too large Load Diff

View File

@ -1,40 +1,40 @@
---
read_when:
- 调整心跳频率或消息传递方式
- 调整心跳频率或消息内容
- 决定在计划任务中使用心跳还是 cron
summary: 心跳轮询消息和通知规则
title: 心跳
x-i18n:
generated_at: "2026-04-07T23:54:15Z"
generated_at: "2026-04-10T23:44:34Z"
model: gpt-5.4
provider: openai
source_hash: a8021d747637060eacb91ec5f75904368a08790c19f4fca32acda8c8c0a25e41
source_hash: e4485072148753076d909867a623696829bf4a82dcd0479b95d5d0cae43100b0
source_path: gateway/heartbeat.md
workflow: 15
---
# 心跳 (Gateway 网关)
# 心跳Gateway 网关)
> **心跳 vs Cron** 参见 [Automation & Tasks](/zh-CN/automation),了解何时使用它们各自更合适
> **心跳还是 Cron** 关于何时使用两者,请参阅 [自动化与任务](/zh-CN/automation)
心跳会在主会话中运行**周期性的智能体轮次**让模型能够提示任何需要关注的事项,同时不会对你造成刷屏
心跳会在主会话中运行**周期性的智能体轮次**这样模型就能提示任何需要注意的事项,而不会不停打扰你
心跳是一计划执行的主会话轮次——它**不会**创建[后台任务](/zh-CN/automation/tasks)记录。
任务记录用于脱离工作ACP 运行、子智能体、隔离的 cron 作业)。
心跳是一计划执行的主会话轮次——它**不会**创建[后台任务](/zh-CN/automation/tasks)记录。
任务记录用于脱离主会话的工作ACP 运行、子智能体、隔离的 cron 作业)。
故障排除:[Scheduled Tasks](/zh-CN/automation/cron-jobs#troubleshooting)
故障排除:[计划任务](/zh-CN/automation/cron-jobs#troubleshooting)
## 快速开始(初学者)
## 快速开始(适合初学者)
1. 保持心跳启用状态(默认是 `30m`对于 Anthropic OAuth/token 认证,包括 Claude CLI 复用,则为 `1h`),或者设置你自己的频率。
2. 在智能体工作区中创建一个简短的 `HEARTBEAT.md` 清单或 `tasks:` 块(可选但推荐)。
3. 决定心跳消息应发送到哪里(默认是 `target: "none"`;设置 `target: "last"` 可路由到最近联系对象)。
4. 可选:启用心跳推理传递以提高透明度。
1. 保持心跳启用状态(默认是 `30m`如果使用 Anthropic OAuth/令牌凭证认证,包括复用 Claude CLI则默认是 `1h`),或者设置你自己的频率。
2. 在智能体工作区中创建一个很小的 `HEARTBEAT.md` 检查清单或 `tasks:` 块(可选但推荐)。
3. 决定心跳消息应发送到哪里(默认是 `target: "none"`;设置 `target: "last"` 可路由到最近一次联系对象)。
4. 可选:启用心跳推理内容投递,以提升透明度。
5. 可选:如果心跳运行只需要 `HEARTBEAT.md`,可使用轻量级引导上下文。
6. 可选:启用隔离会话,以避免每次心跳都发送完整的对话历史。
6. 可选:启用隔离会话,避免每次心跳都发送完整会话历史。
7. 可选:将心跳限制在活跃时段内(本地时间)。
示例配置
配置示例:
```json5
{
@ -42,12 +42,12 @@ x-i18n:
defaults: {
heartbeat: {
every: "30m",
target: "last", // 显式发送到最近联系对象(默认是 "none"
target: "last", // 显式投递到最近一次联系对象(默认是 "none"
directPolicy: "allow", // 默认:允许直接/私信目标;设为 "block" 可抑制发送
lightContext: true, // 可选:从引导文件中注入 HEARTBEAT.md
isolatedSession: true, // 可选:每次运行都使用全新会话(无对话历史)
lightContext: true, // 可选:从引导文件中注入 HEARTBEAT.md
isolatedSession: true, // 可选:每次运行都使用新会话(无会话历史)
// activeHours: { start: "08:00", end: "24:00" },
// includeReasoning: true, // 可选:同时发送单独的 `Reasoning:` 消息
// includeReasoning: true, // 可选:发送单独的 `Reasoning:` 消息
},
},
},
@ -56,33 +56,33 @@ x-i18n:
## 默认值
- 间隔:`30m`或者在检测到的认证模式为 Anthropic OAuth/token 认证时为 `1h`,包括 Claude CLI 复用)。设置 `agents.defaults.heartbeat.every` 或针对每个智能体设置 `agents.list[].heartbeat.every`;使用 `0m` 可禁用。
- 间隔:`30m`如果检测到的认证模式是 Anthropic OAuth/令牌凭证认证,包括复用 Claude CLI则为 `1h`)。设置 `agents.defaults.heartbeat.every` 或按智能体设置 `agents.list[].heartbeat.every`;使用 `0m` 可禁用。
- 提示词正文(可通过 `agents.defaults.heartbeat.prompt` 配置):
`Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.`
- 心跳提示词会**原样**作为用户消息发送。只有当默认智能体启用了心跳,并且该运行在内部被标记后,系统提示词才会包含一个“Heartbeat”部分。
- 当使用 `0m` 禁用心跳时,普通运行也会从引导上下文中省略 `HEARTBEAT.md`,这样模型就不会看到仅供心跳使用的说明
- 活跃时段(`heartbeat.activeHours`)会在配置的时区中进行检查。
该时间窗口之外,心跳会被跳过,直到窗口内的下一个 tick
- 心跳提示词会作为用户消息**原样**发送。系统提示词仅在默认智能体启用了心跳且本次运行在内部被标记为心跳时,才会包含一个“Heartbeat”部分。
- 当心跳通过 `0m` 禁用时,普通运行也会从引导上下文中省略 `HEARTBEAT.md`,这样模型就不会看到仅供心跳使用的指令
- 活跃时段(`heartbeat.activeHours`)会按照已配置的时区进行检查。
窗口之外,心跳会被跳过,直到下一个落在窗口内的时钟周期
## 心跳提示词的用途
默认提示词刻意保持宽泛
默认提示词是有意保持宽泛的
- **后台任务**“Consider outstanding tasks” 会推动智能体审查待跟进事项(收件箱、日历、提醒、排队工作),并提示任何紧急内容。
- **人工检查**“Checkup sometimes on your human during day time” 会推动偶尔发送轻量级的“你有什么需要吗?”消息,但会根据你配置的本地时区避免夜间刷屏(参见 [/concepts/timezone](/zh-CN/concepts/timezone))。
- **后台任务**“Consider outstanding tasks” 会推动智能体检查待处理事项(收件箱、日历、提醒、排队工作),并提示任何紧急内容。
- **人工检查**“Checkup sometimes on your human during day time” 会推动偶尔发送轻量级的“你需要什么帮助吗?”消息,但会通过你配置的本地时区避免夜间打扰(见 [/concepts/timezone](/zh-CN/concepts/timezone))。
心跳可以对已完成的[后台任务](/zh-CN/automation/tasks)作出反应,但心跳运行本身不会创建任务记录。
如果你希望心跳执行非常具体的事情(例如“检查 Gmail PubSub 统计信息”或“验证 Gateway 网关健康状态”),请将 `agents.defaults.heartbeat.prompt`(或 `agents.list[].heartbeat.prompt`)设置为自定义正文(原样发送)。
如果你希望心跳执行非常具体的事情(例如“检查 Gmail PubSub 统计”或“验证 Gateway 网关健康状态”),请将 `agents.defaults.heartbeat.prompt`(或 `agents.list[].heartbeat.prompt`)设置为自定义正文(原样发送)。
## 响应约定
- 如果没有任何事项需要关注,请回复 **`HEARTBEAT_OK`**。
- 在心跳运行期间,如果 `HEARTBEAT_OK` 出现在回复的**开头或结尾**OpenClaw 会将其视为确认。该标记会被移除;如果剩余内容**≤ `ackMaxChars`**默认300整条回复会被丢弃。
- 如果没有任何需要关注的内容,请回复 **`HEARTBEAT_OK`**。
- 在心跳运行期间,如果 `HEARTBEAT_OK` 出现在回复的**开头或结尾**OpenClaw 会将其视为确认信号。当剩余内容**≤ `ackMaxChars`**默认300该标记会被移除并且整条回复会被丢弃。
- 如果 `HEARTBEAT_OK` 出现在回复的**中间**,则不会被特殊处理。
- 对于提醒消息,**不要**包含 `HEARTBEAT_OK`;只返回提醒文本。
心跳之外,如果消息开头或结尾意外出现 `HEARTBEAT_OK`,它会被移除并记录日志;如果消息只有 `HEARTBEAT_OK`,则该消息会被丢弃。
非心跳场景下,如果消息开头或结尾意外出现 `HEARTBEAT_OK`,它会被移除并记录日志;如果整条消息只有 `HEARTBEAT_OK`,则会被丢弃。
## 配置
@ -91,35 +91,34 @@ x-i18n:
agents: {
defaults: {
heartbeat: {
every: "30m", // 默认30m0m 禁用)
every: "30m", // 默认30m0m 表示禁用)
model: "anthropic/claude-opus-4-6",
includeReasoning: false, // 默认false可用时发送单独的 Reasoning: 消息)
includeReasoning: false, // 默认false可用时投递单独的 Reasoning: 消息)
lightContext: false, // 默认falsetrue 时仅保留工作区引导文件中的 HEARTBEAT.md
isolatedSession: false, // 默认falsetrue 时每次心跳都在全新会话中运行(无对话历史)
target: "last", // 默认none | 可选last | none | <channel id>(核心或插件,例如 "bluebubbles"
to: "+15551234567", // 可选的特定渠道覆盖
accountId: "ops-bot", // 可选多账号渠道 id
isolatedSession: false, // 默认falsetrue 时每次心跳都在新会话中运行(无会话历史)
target: "last", // 默认none | 可选last | none | <channel id>(核心或插件,例如 "bluebubbles"
to: "+15551234567", // 可选:按渠道覆盖目标收件人
accountId: "ops-bot", // 可选多账号渠道 id
prompt: "Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.",
ackMaxChars: 300, // HEARTBEAT_OK 后允许的最大字符数
ackMaxChars: 300, // HEARTBEAT_OK 后允许的最大字符数
},
},
},
}
```
### 作用范围和优先级
### 范围与优先级
- `agents.defaults.heartbeat` 设置全局心跳行为。
- `agents.list[].heartbeat` 会在其之上合并;如果任何智能体`heartbeat` 块,则**只有这些智能体**会运行心跳。
- `agents.list[].heartbeat` 会在其基础上合并;如果任何智能体具`heartbeat` 块,则**只有这些智能体**会运行心跳。
- `channels.defaults.heartbeat` 设置所有渠道的可见性默认值。
- `channels.<channel>.heartbeat` 覆盖渠道默认值。
- `channels.<channel>.accounts.<id>.heartbeat`(多账号渠道)按渠道内账号进行覆盖
- `channels.<channel>.heartbeat` 覆盖渠道默认值。
- `channels.<channel>.accounts.<id>.heartbeat`(多账号渠道)会按渠道内账号进一步覆盖设置
### 每个智能体的心跳
### 按智能体设置心跳
如果任意 `agents.list[]` 条目包含 `heartbeat` 块,则**只有这些智能体**
会运行心跳。每个智能体的块会在 `agents.defaults.heartbeat`
之上合并(因此你可以先设置共享默认值,再按智能体覆盖)。
如果任何 `agents.list[]` 条目包含 `heartbeat` 块,则**只有这些智能体**会运行心跳。
按智能体的块会在 `agents.defaults.heartbeat` 之上合并(因此你可以先设置共享默认值,再按智能体覆盖)。
示例:两个智能体,只有第二个智能体运行心跳。
@ -129,7 +128,7 @@ x-i18n:
defaults: {
heartbeat: {
every: "30m",
target: "last", // 显式发送到最近联系对象(默认是 "none"
target: "last", // 显式投递到最近一次联系对象(默认是 "none"
},
},
list: [
@ -140,6 +139,7 @@ x-i18n:
every: "1h",
target: "whatsapp",
to: "+15551234567",
timeoutSeconds: 45,
prompt: "Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.",
},
},
@ -150,7 +150,7 @@ x-i18n:
### 活跃时段示例
将心跳限制在某个特定时区的工作时段内:
将心跳限制在特定时区的工作时间内:
```json5
{
@ -158,11 +158,11 @@ x-i18n:
defaults: {
heartbeat: {
every: "30m",
target: "last", // 显式发送到最近联系对象(默认是 "none"
target: "last", // 显式投递到最近一次联系对象(默认是 "none"
activeHours: {
start: "09:00",
end: "22:00",
timezone: "America/New_York", // 可选;如果已设置则使用你的 userTimezone,否则使用主机时区
timezone: "America/New_York", // 可选;如果设置了 userTimezone 则使用它,否则使用主机时区
},
},
},
@ -170,21 +170,21 @@ x-i18n:
}
```
在这个时间窗口之外(美东时间上午 9 点前或晚上 10 点后),心跳会被跳过。窗口内的下一次计划 tick 会正常运行。
在这个时间窗口之外(美时间上午 9 点前或晚上 10 点后),心跳会被跳过。下一个位于窗口内的计划周期将正常运行。
### 24/7 配置
如果你希望心跳全天运行,可使用以下模式之一
如果你希望心跳全天运行,可使用以下任一模式:
- 完全省略 `activeHours`无时间窗口限制;这是默认行为)。
- 完全省略 `activeHours`不限制时间窗口;这是默认行为)。
- 设置全天窗口:`activeHours: { start: "00:00", end: "24:00" }`。
不要将 `start``end` 设置为相同时间(例如 `08:00``08:00`)。
这会被视为零宽度窗口,因此心跳始终被跳过。
这会被视为零宽度窗口,因此心跳始终被跳过。
### 多账号示例
使用 `accountId` 将消息发送到 Telegram 等多账号渠道中的特定账号:
使用 `accountId` 将消息定向到 Telegram 等多账号渠道上的特定账号:
```json5
{
@ -195,7 +195,7 @@ x-i18n:
heartbeat: {
every: "1h",
target: "telegram",
to: "12345678:topic:42", // 可选:路由到特定 topic/thread
to: "12345678:topic:42", // 可选:路由到特定话题/线程
accountId: "ops-bot",
},
},
@ -213,56 +213,50 @@ x-i18n:
### 字段说明
- `every`:心跳间隔(时长字符串;默认单位 = 分钟)。
- `every`:心跳间隔(时长字符串;默认单位分钟)。
- `model`:心跳运行时可选的模型覆盖(`provider/model`)。
- `includeReasoning`:启用后,在可用时也会发送单独的 `Reasoning:` 消息(形式与 `/reasoning on` 相同)。
- `includeReasoning`:启用后,在可用时也会投递单独的 `Reasoning:` 消息(形式与 `/reasoning on` 相同)。
- `lightContext`:为 true 时,心跳运行会使用轻量级引导上下文,并且只保留工作区引导文件中的 `HEARTBEAT.md`
- `isolatedSession`:为 true 时,每次心跳都会在无先前对话历史的全新会话中运行。使用与 cron `sessionTarget: "isolated"` 相同的隔离模式。可显著降低每次心跳的 token 成本。与 `lightContext: true` 结合使用可获得最大节省。消息传递路由仍使用主会话上下文。
- `isolatedSession`:为 true 时,每次心跳都在没有先前会话历史的新会话中运行。使用与 cron `sessionTarget: "isolated"` 相同的隔离模式。可显著降低每次心跳的 token 成本。与 `lightContext: true` 组合可获得最大节省。投递路由仍使用主会话上下文。
- `session`:心跳运行的可选会话键。
- `main`(默认):智能体主会话。
- 显式会话键(从 `openclaw sessions --json` 或 [sessions CLI](/cli/sessions) 复制)。
- 会话键格式:参见 [Sessions](/zh-CN/concepts/session) 和 [Groups](/zh-CN/channels/groups)。
- 显式会话键(`openclaw sessions --json` 或 [sessions CLI](/cli/sessions) 复制)。
- 会话键格式:见 [会话](/zh-CN/concepts/session) 和 [群组](/zh-CN/channels/groups)。
- `target`
- `last`发送到最近使用的外部渠道。
- 显式渠道:任已配置的渠道或插件 id例如 `discord`、`matrix`、`telegram` 或 `whatsapp`
- `none`(默认):运行心跳,但**不向外部发送**
- `directPolicy`:控制直接/私信递行为:
- `allow`(默认):允许直接/私信心跳递。
- `block`:抑制直接/私信递(`reason=dm-blocked`)。
- `to`:可选的接收者覆盖(渠道特定 id例如 WhatsApp 的 E.164 或 Telegram chat id。对于 Telegram topic/thread,使用 `<chatId>:topic:<messageThreadId>`
- `accountId`:多账号渠道的可选账号 id。当 `target: "last"` 时,如果解析出的最近渠道支持账号,则该账号 id 会应用于该渠道;否则会被忽略。如果该账号 id 与解析出的渠道中已配置账号不匹配,则会跳过传递。
- `prompt`:覆盖默认提示词正文(不合并)。
- `ackMaxChars``HEARTBEAT_OK` 之后允许的最大字符数,超过则会发送
- `suppressToolErrorWarnings`:为 true 时,在心跳运行期间抑制工具错误警告载
- `activeHours`:将心跳运行限制在某个时间窗口内。对象包含 `start`HH:MM含边界天开始请使用 `00:00`)、`end`HH:MM不含边界一天结束可使`24:00`)以及可选的 `timezone`
- 省略或设为 `"user"`:如果已设置,则使用你的 `agents.defaults.userTimezone`,否则回退到主机系统时区。
- `last`投递到最近一次使用的外部渠道。
- 显式渠道:任已配置的渠道或插件 id例如 `discord`、`matrix`、`telegram` 或 `whatsapp`
- `none`(默认):运行心跳,但**不进行**外部投递
- `directPolicy`:控制直接/私信递行为:
- `allow`(默认):允许直接/私信心跳递。
- `block`:抑制直接/私信递(`reason=dm-blocked`)。
- `to`:可选的收件人覆盖(按渠道定义的 id例如 WhatsApp 的 E.164 或 Telegram chat id。对于 Telegram 话题/线程,使用 `<chatId>:topic:<messageThreadId>`
- `accountId`:多账号渠道的可选账号 id。当 `target: "last"` 时,如果解析出的最近渠道支持账号,则会应用该账号 id否则会被忽略。如果该账号 id 与解析出的渠道中已配置的账号不匹配,则会跳过投递。
- `prompt`:覆盖默认提示词正文(不合并)。
- `ackMaxChars``HEARTBEAT_OK` 后允许的最大字符数,超出则继续投递
- `suppressToolErrorWarnings`:为 true 时,在心跳运行期间抑制工具错误警告载。
- `activeHours`:将心跳运行限制在一个时间窗口内。该对象包含 `start`HH:MM含边界天开始请使用 `00:00`)、`end`HH:MM不含边界一天结束可用 `24:00`)以及可选的 `timezone`
- 省略或设为 `"user"`:如果设置了你的 `agents.defaults.userTimezone` 则使用它,否则回退到主机系统时区。
- `"local"`:始终使用主机系统时区。
- 任 IANA 标识符(例如 `America/New_York`):直接使用;如果无效,则回退到上面的 `"user"` 行为。
- 对于活跃窗口,`start` 和 `end` 不得相等;相等会被视为零宽度(始终在窗口外)。
- 在活跃窗口之外,心跳会被跳过,直到窗口内的下一个 tick
- 任 IANA 标识符(例如 `America/New_York`):直接使用;如果无效,则回退到上面的 `"user"` 行为。
- `start``end` 不能相等;相等会被视为零宽度窗口(始终处于窗口外)。
- 在活跃窗口之外,心跳会被跳过,直到下一个位于窗口内的计划周期
## 递行为
## 递行为
- 默认情况下,心跳在智能体的主会话中运行(`agent:<id>:<mainKey>`
或者当 `session.scope = "global"` 时使用 `global`。设置 `session` 可覆盖为某个
特定渠道会话Discord/WhatsApp 等)。
- `session` 只影响运行上下文;消息传递由 `target``to` 控制。
- 若要发送到特定渠道/接收者,请设置 `target` + `to`。当
`target: "last"` 时,传递会使用该会话最近的外部渠道。
- 默认情况下,心跳传递允许直接/私信目标。设置 `directPolicy: "block"` 可在仍然运行心跳轮次的同时抑制向直接目标发送。
- 如果主队列繁忙,心跳会被跳过,并在稍后重试。
- 如果 `target` 解析后没有外部目的地,运行仍会发生,但不会
发送外发消息。
- 如果 `showOk`、`showAlerts` 和 `useIndicator` 全部被禁用,则该运行会在前期被跳过,并标记为 `reason=alerts-disabled`
- 如果仅禁用了提醒传递OpenClaw 仍可运行心跳、更新时间已到任务的时间戳、恢复会话空闲时间戳,并抑制向外发送的提醒载荷。
- 仅心跳的回复**不会**保持会话活跃;最后的 `updatedAt`
会被恢复,因此空闲过期行为保持正常。
- 脱离式[后台任务](/zh-CN/automation/tasks)可以加入一个系统事件队列并唤醒心跳,以便主会话更快注意到某些事情。这种唤醒不会使心跳运行成为后台任务。
- 心跳默认在智能体的主会话中运行(`agent:<id>:<mainKey>`),当 `session.scope = "global"` 时则运行在 `global` 中。设置 `session` 可将其覆盖为特定的渠道会话Discord/WhatsApp 等)。
- `session` 只影响运行上下文;投递由 `target``to` 控制。
- 要投递到特定渠道/收件人,请设置 `target` + `to`。当使用 `target: "last"` 时,投递会使用该会话最近一次使用的外部渠道。
- 默认情况下,心跳投递允许直接/私信目标。设置 `directPolicy: "block"` 可在仍运行心跳轮次的同时抑制直接目标发送。
- 如果主队列繁忙,心跳会被跳过,并在之后重试。
- 如果 `target` 未解析到任何外部目标,运行仍会发生,但不会发送出站消息。
- 如果 `showOk`、`showAlerts` 和 `useIndicator` 全部被禁用,则该次运行会在开始前被跳过,并记为 `reason=alerts-disabled`
- 如果仅禁用了提醒投递OpenClaw 仍可以运行心跳、更新时间已到任务的时间戳、恢复会话空闲时间戳,并抑制对外提醒负载。
- 仅包含心跳内容的回复**不会**保持会话活跃;最后的 `updatedAt` 会被恢复,因此空闲过期仍按正常方式生效。
- 脱离主会话的[后台任务](/zh-CN/automation/tasks)可以将系统事件加入队列,并唤醒心跳,以便主会话尽快注意到某些事情。这种唤醒不会让心跳运行变成后台任务。
## 可见性控制
默认情况下,`HEARTBEAT_OK` 确认会被抑制,而提醒内容会
正常发送。你可以按渠道或按账号进行调整:
默认情况下,`HEARTBEAT_OK` 确认消息会被抑制,而提醒内容会正常投递。你可以按渠道或按账号进行调整:
```yaml
channels:
@ -278,20 +272,20 @@ channels:
accounts:
work:
heartbeat:
showAlerts: false # 为该账号抑制提醒发送
showAlerts: false # 为此账号抑制提醒投递
```
优先级:每账号 → 每渠道 → 渠道默认值 → 内置默认值。
优先级:按账号 → 按渠道 → 渠道默认值 → 内置默认值。
### 每个标志的作用
### 标志的作用
- `showOk`:当模型返回仅含 OK 的回复时,发送 `HEARTBEAT_OK` 确认。
- `showOk`:当模型返回仅含 OK 的回复时,发送 `HEARTBEAT_OK` 确认消息
- `showAlerts`:当模型返回非 OK 回复时,发送提醒内容。
- `useIndicator`:为 UI 状态界面发出指示器事件。
如果**三者都**为 falseOpenClaw 会完全跳过心跳运行(不调用模型)。
如果**这三项全部**为 falseOpenClaw 会完全跳过心跳运行(不调用模型)。
### 每渠道与每账号示例
### 按渠道与按账号示例
```yaml
channels:
@ -315,31 +309,26 @@ channels:
### 常见模式
| 目标 | 配置 |
| ---------------------------------------- | ---------------------------------------------------------------------------------------- |
| --- | --- |
| 默认行为(静默 OK提醒开启 | _(无需配置)_ |
| 完全静默(无消息无指示器) | `channels.defaults.heartbeat: { showOk: false, showAlerts: false, useIndicator: false }` |
| 仅指示器(无消息) | `channels.defaults.heartbeat: { showOk: false, showAlerts: false, useIndicator: true }` |
| 仅在一个渠道中显示 OK | `channels.telegram.heartbeat: { showOk: true }` |
| 完全静默(无消息无指示器) | `channels.defaults.heartbeat: { showOk: false, showAlerts: false, useIndicator: false }` |
| 仅指示器(无消息) | `channels.defaults.heartbeat: { showOk: false, showAlerts: false, useIndicator: true }` |
| 仅在一个渠道中显示 OK | `channels.telegram.heartbeat: { showOk: true }` |
## HEARTBEAT.md可选
## `HEARTBEAT.md`(可选)
如果工作区中存在 `HEARTBEAT.md` 文件,默认提示词会告诉
智能体读取它。你可以将其视为你的“心跳检查清单”:内容要小而稳定,
并且适合每 30 分钟都包含一次。
如果工作区中存在 `HEARTBEAT.md` 文件,默认提示词会告诉智能体去读取它。你可以把它看作你的“心跳检查清单”:小巧、稳定,并且适合每 30 分钟包含一次。
在普通运行中,只有当默认智能体启用了心跳指引时,
`HEARTBEAT.md` 才会被注入。如果使用 `0m` 禁用心跳频率,或
设置 `includeSystemPromptSection: false`,它就会从普通引导
上下文中省略。
在普通运行中,只有当默认智能体启用了心跳指引时,才会注入 `HEARTBEAT.md`
如果将心跳频率通过 `0m` 禁用,或设置 `includeSystemPromptSection: false`,则会在普通引导上下文中省略它。
如果 `HEARTBEAT.md` 存在但实际上为空(只有空行和 markdown
标题,例如 `# Heading`OpenClaw 会跳过心跳运行以节省 API 调用。
这种跳过会报告为 `reason=empty-heartbeat-file`
如果 `HEARTBEAT.md` 存在但实际上为空(只有空行和 Markdown 标题,例如 `# Heading`OpenClaw 会跳过该次心跳运行以节省 API 调用。
该跳过会记为 `reason=empty-heartbeat-file`
如果文件不存在,心跳仍会运行,并由模型决定该做什么。
请保持它很小(简短清单或提醒),以避免提示词膨胀。
请保持它足够小巧(简短的检查清单或提醒),以避免提示词膨胀。
示例 `HEARTBEAT.md`
`HEARTBEAT.md` 示例
```md
# Heartbeat checklist
@ -351,8 +340,7 @@ channels:
### `tasks:`
`HEARTBEAT.md` 还支持一个小型结构化 `tasks:` 块,
用于在心跳内部执行基于间隔的检查。
`HEARTBEAT.md` 还支持一个小型结构化 `tasks:` 块,用于在心跳内部执行基于间隔的检查。
示例:
@ -372,73 +360,66 @@ tasks:
- If nothing needs attention after all due tasks, reply HEARTBEAT_OK.
```
行为:
行为如下
- OpenClaw 会解析 `tasks:` 块,并根据各任务自己的 `interval` 检查每个任务
- 只有**到期**任务会被包含在该次 tick 的心跳提示词中。
- 如果没有任务到期,心跳会被完全跳过`reason=no-tasks-due`),以避免浪费一次模型调用。
- `HEARTBEAT.md` 中的非任务内容会被保留,并作为附加上下文追加在到期任务列表之后
- 任务上次运行时间戳存储在会话状态中(`heartbeatTaskState`),因此这些间隔在正常重启后仍会保留。
- 只有在心跳运行完成其正常回复路径后,任务时间戳才会推进。被跳过的 `empty-heartbeat-file` / `no-tasks-due` 运行不会将任务标记为已完成。
- OpenClaw 会解析 `tasks:` 块,并根据每个任务自己的 `interval` 进行检查
- 只有**到期**的任务才会被包含到该次时钟周期的心跳提示词中。
- 如果没有任务到期,则会完全跳过该次心跳`reason=no-tasks-due`),以避免浪费一次模型调用。
- `HEARTBEAT.md` 中的非任务内容会被保留,并在到期任务列表之后作为附加上下文追加。
- 任务的上次运行时间戳会存储在会话状态(`heartbeatTaskState`)中,因此这些间隔信息在正常重启后依然保留。
- 只有在一次心跳运行完成其正常回复路径之后,任务时间戳才会前进。被跳过的 `empty-heartbeat-file` / `no-tasks-due` 运行不会将任务标记为已完成。
当你希望一个心跳文件容纳多个周期性检查,同时又不想每次 tick 都为全部检查付费时,任务模式就很有用。
当你希望一个心跳文件容纳多个周期性检查,但又不想在每次时钟周期中都为所有检查付费时,任务模式会很有用。
### 智能体可以更新 HEARTBEAT.md 吗?
### 智能体可以更新 `HEARTBEAT.md` 吗?
可以——如果你要求它这做。
可以——如果你要求它这做。
`HEARTBEAT.md` 只是智能体工作区中的一个普通文件,因此你可以在
普通聊天中对智能体说:
`HEARTBEAT.md` 只是智能体工作区中的一个普通文件,因此你可以在普通聊天中告诉智能体类似这样的话:
- “更新 `HEARTBEAT.md`,加入每日检查。”
- “重写 `HEARTBEAT.md`,让它更短,并专注于收件箱跟进事项。”
- “更新 `HEARTBEAT.md`,加入每日检查日历的内容。”
- “重写 `HEARTBEAT.md`,让它更短,并聚焦于收件箱跟进事项。”
如果你希望它主动这样做,也可以在
心跳提示词中加入一行明确说明,例如:“如果清单已经过时,请更新 HEARTBEAT.md
并替换为更好的版本。”
如果你希望这件事主动发生,也可以在心跳提示词中加入一行明确说明,比如:“如果检查清单变陈旧了,就用更好的版本更新 HEARTBEAT.md。”
安全说明不要把密钥API keys、电话号码、私有 token放进
`HEARTBEAT.md`——它会成为提示词上下文的一部分。
安全提示不要把秘密信息API 密钥、电话号码、私有令牌)放进 `HEARTBEAT.md`——它会成为提示词上下文的一部分。
## 手动唤醒(按需)
你可以通过以下命令将系统事件加入队列并立即触发心跳:
你可以通过以下命令将系统事件加入队列并立即触发一次心跳:
```bash
openclaw system event --text "Check for urgent follow-ups" --mode now
```
如果多个智能体配置了 `heartbeat`,手动唤醒会立即运行其中每个
智能体的心跳。
如果多个智能体都配置了 `heartbeat`,手动唤醒会立即运行每一个此类智能体的心跳。
使用 `--mode next-heartbeat` 可等待下一次计划 tick
使用 `--mode next-heartbeat` 可等待下一个计划时钟周期
## 推理递(可选)
## 推理内容投递(可选)
默认情况下,心跳只传递最终的“answer”载荷
默认情况下,心跳只会投递最终的“answer”负载
如果你希望提高透明度,请启用:
- `agents.defaults.heartbeat.includeReasoning: true`
启用后,心跳还会传递一条单独的消息,前缀为
`Reasoning:`(形式与 `/reasoning on` 相同)。当智能体
正在管理多个会话/codexes而你希望看到它为何决定提醒
你时,这会很有帮助——但它也可能泄露比你想要的更多内部细节。建议在群聊中保持关闭。
启用后,心跳还会投递一条单独的消息,前缀为
`Reasoning:`(形式与 `/reasoning on` 相同)。当智能体正在管理多个会话 / codexes而你希望看到它为什么决定提醒你时这会很有帮助——但它也可能泄露比你想要更多的内部细节。建议在群聊中保持关闭。
## 成本意识
心跳会运行完整的智能体轮次。更短的间隔会消耗更多 token。降低成本:
心跳会运行完整的智能体轮次。更短的间隔会消耗更多 token。为了降低成本:
- 使用 `isolatedSession: true` 以避免发送完整对话历史(每次运行约从 ~100K tokens 降至 ~2-5K
- 使用 `lightContext: true` 将引导文件限制为只有 `HEARTBEAT.md`
- 使用 `isolatedSession: true` 来避免发送完整会话历史(每次运行大约可从 ~100K token 降到 ~2-5K
- 使用 `lightContext: true` 将引导文件限制为 `HEARTBEAT.md`
- 设置更便宜的 `model`(例如 `ollama/llama3.2:1b`)。
- 保持 `HEARTBEAT.md`
- 如果你只想要内部状态更新,请使用 `target: "none"`
- 保持 `HEARTBEAT.md` 足够小。
- 如果你只想更新内部状态,请使用 `target: "none"`
## 相关内容
- [Automation & Tasks](/zh-CN/automation) — 所有自动化机制概
- [Background Tasks](/zh-CN/automation/tasks) — 脱离式工作如何被跟踪
- [Timezone](/zh-CN/concepts/timezone) — 时区如何影响心跳调度
- [Troubleshooting](/zh-CN/automation/cron-jobs#troubleshooting) — 自动化问题调试
- [自动化与任务](/zh-CN/automation) —— 所有自动化机制一
- [后台任务](/zh-CN/automation/tasks) —— 脱离主会话的工作如何被跟踪
- [时区](/zh-CN/concepts/timezone) —— 时区如何影响心跳调度
- [故障排除](/zh-CN/automation/cron-jobs#troubleshooting) — 调试自动化问题

View File

@ -1,128 +1,107 @@
---
read_when:
- 查找公开发布通道定义
- 查找版本命名和发布节奏
summary: 公开发布道、版本命名和发布节奏
- 正在查找公开发布渠道的定义
- 正在查找版本命名和发布节奏
summary: 公开发布道、版本命名和发布节奏
title: 发布策略
x-i18n:
generated_at: "2026-04-05T10:07:37Z"
generated_at: "2026-04-10T23:44:34Z"
model: gpt-5.4
provider: openai
source_hash: bb52a13264c802395aa55404c6baeec5c7b2a6820562e7a684057e70cc85668f
source_hash: ca613d094c93670c012f0b79720fad0d5d85be802f54b0acb7a8f22aca5bde12
source_path: reference/RELEASING.md
workflow: 15
---
# 发布策略
OpenClaw 有三条公开发布道:
OpenClaw 有三条公开发布道:
- stable带标签的发布版本默认发布到 npm `beta`,或在显式指定时发布到 npm `latest`
- stable带标签的发布版本默认发布到 npm `beta`,或在明确要求时发布到 npm `latest`
- beta预发布标签发布到 npm `beta`
- dev`main` 的滚动最新头部版本
- dev`main` 的持续更新头部版本
## 版本命名
- 稳定版发布版本:`YYYY.M.D`
- Stable 发布版本:`YYYY.M.D`
- Git 标签:`vYYYY.M.D`
- 稳定版修正版发布版本:`YYYY.M.D-N`
- Stable 修正版发布版本:`YYYY.M.D-N`
- Git 标签:`vYYYY.M.D-N`
- Beta 预发布版本:`YYYY.M.D-beta.N`
- Git 标签:`vYYYY.M.D-beta.N`
- 月和日不要补零
- `latest` 表示当前已晋升的稳定 npm 发布版本
- 月和日不要补零
- `latest` 表示当前已提升为正式版的 stable npm 发布版本
- `beta` 表示当前 beta 安装目标
- 稳定版和稳定版修正版默认发布到 npm `beta`;发布操作员可以显式指定发布到 `latest`,或在之后将已验证的 beta 构建晋升
- 每个 OpenClaw 发布都会同时发布 npm 包和 macOS 应用
- Stable 和 stable 修正版发布默认发布到 npm `beta`;发布操作人员也可以显式指定发布到 `latest`,或者稍后再将已验证的 beta 构建提升过去
- 每个 OpenClaw 发布都会同时交付 npm 包和 macOS 应用
## 发布节奏
- 发布先走 beta
- 只有在最新 beta 验证通过后,才会进 stable
- 详细的发布流程、审批、凭证和恢复说明仅供维护者使用
- 只有在最新 beta 完成验证后,才会进 stable
- 详细的发布流程、审批、凭证和恢复说明仅限维护者查看
## 发布前检查
- 在运行 `pnpm release:check` 之前先运行 `pnpm build && pnpm ui:build`,以便打包验证步骤所需的 `dist/*` 发布产物和 Control UI bundle 已存在
- 在每次带标签发布前运行 `pnpm release:check`
- `main` 分支的 npm 发布前检查还会在打包 tarball 之前运行
`OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_CACHE_TEST=1 pnpm test:live:cache`
并使用工作流密钥 `OPENAI_API_KEY`
`ANTHROPIC_API_KEY`
- 在审批前运行 `RELEASE_TAG=vYYYY.M.D node --import tsx scripts/openclaw-npm-release-check.ts`
(或对应的 beta/修正版标签)
- npm 发布后,运行
`node --import tsx scripts/openclaw-npm-postpublish-verify.ts YYYY.M.D`
(或对应的 beta/修正版版本),在一个全新的临时前缀中验证已发布注册表的安装路径
- 维护者发布自动化现在使用“先预检再晋升”流程:
- 实际 npm 发布必须通过成功的 npm `preflight_run_id`
- 稳定 npm 发布默认使用 `beta`
- 稳定 npm 发布可通过工作流输入显式指定目标为 `latest`
- 稳定 npm 从 `beta` 晋升到 `latest` 仍然作为可信 `OpenClaw NPM Release` 工作流中的显式手动模式提供
- 该晋升模式仍需要 `npm-release` 环境中有效的 `NPM_TOKEN`,因为 npm `dist-tag` 管理独立于可信发布
- 在运行 `pnpm release:check` 之前,先运行 `pnpm build && pnpm ui:build`,这样 pack 校验步骤所需的 `dist/*` 发布产物和 Control UI bundle 才会存在
- 每次带标签发布前都要运行 `pnpm release:check`
- `main` 分支上的 npm 发布前检查还会在打包 tarball 之前运行 `OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_CACHE_TEST=1 pnpm test:live:cache`,并使用 `OPENAI_API_KEY``ANTHROPIC_API_KEY` 这两个工作流密钥
- 在批准前运行 `RELEASE_TAG=vYYYY.M.D node --import tsx scripts/openclaw-npm-release-check.ts`(或对应的 beta / 修正版标签)
- npm 发布后,运行 `node --import tsx scripts/openclaw-npm-postpublish-verify.ts YYYY.M.D`(或对应的 beta / 修正版版本),以在一个全新的临时前缀中验证已发布注册表安装路径
- 维护者发布自动化现在使用“先预检,再提升”的流程:
- 真正的 npm 发布必须依赖一次成功的 npm `preflight_run_id`
- stable npm 发布默认目标为 `beta`
- stable npm 发布可以通过工作流输入显式指定目标为 `latest`
- 也仍然支持在受信任的 `OpenClaw NPM Release` 工作流中,以显式手动模式将 stable 从 `beta` 提升到 `latest`
- 该提升模式仍然需要 `npm-release` 环境中存在有效的 `NPM_TOKEN`,因为 npm `dist-tag` 管理与受信任发布是分开的
- 公开的 `macOS Release` 仅用于验证
- 实际的私有 mac 发布必须通过成功的私有 mac
`preflight_run_id``validate_run_id`
- 实际发布路径会晋升已准备好的产物,而不是再次重新构建
- 对于像 `YYYY.M.D-N` 这样的稳定版修正版发布,发布后验证器还会检查从 `YYYY.M.D``YYYY.M.D-N` 的同一临时前缀升级路径,因此发布修正不能悄悄让旧的全局安装仍停留在基础稳定版负载上
- npm 发布前检查会以失败关闭,除非 tarball 同时包含
`dist/control-ui/index.html` 和非空的 `dist/control-ui/assets/` 负载,
以避免再次发布一个空的浏览器仪表板
- 如果发布工作涉及 CI 规划、扩展时序清单或快速测试矩阵,请在审批前从 `.github/workflows/ci.yml`
重新生成并审查由规划器负责的 `checks-fast-extensions`
工作流矩阵输出,以免发布说明描述过时的 CI 布局
- 稳定版 macOS 发布就绪还包括更新器相关接口:
- GitHub 发布最终必须包含打包后的 `.zip`、`.dmg` 和 `.dSYM.zip`
- 发布后,`main` 上的 `appcast.xml` 必须指向新的稳定版 zip
- 打包后的应用必须保持非调试 bundle id、非空的 Sparkle feed
URL以及不低于该发布版本规范 Sparkle 构建下限的 `CFBundleVersion`
- 真正的私有 mac 发布必须依赖成功的私有 mac `preflight_run_id``validate_run_id`
- 真正的发布路径会提升已准备好的产物,而不是再次重新构建它们
- 对于像 `YYYY.M.D-N` 这样的 stable 修正版发布,发布后验证器还会检查从 `YYYY.M.D` 升级到 `YYYY.M.D-N` 的同一临时前缀升级路径,这样修正版发布就不能在无声无息中让旧的全局安装仍停留在基础 stable 负载上
- npm 发布前检查默认采用失败即关闭的策略,除非 tarball 同时包含 `dist/control-ui/index.html` 和非空的 `dist/control-ui/assets/` 内容,否则检查不会通过,以避免再次发布一个空的浏览器仪表盘
- 如果发布工作涉及 CI 规划、扩展时序清单或扩展测试矩阵,请在批准前重新生成并审查来自 `.github/workflows/ci.yml` 的规划器维护的 `checks-node-extensions` 工作流矩阵输出,以免发布说明描述过时的 CI 布局
- Stable macOS 发布就绪检查还包括更新器相关表面:
- GitHub release 最终必须包含打包后的 `.zip`、`.dmg` 和 `.dSYM.zip`
- 发布后,`main` 上的 `appcast.xml` 必须指向新的 stable zip
- 打包后的应用必须保持非调试 bundle id、非空的 Sparkle feed URL以及不低于该发布版本规范 Sparkle 构建底线的 `CFBundleVersion`
## NPM 工作流输入
`OpenClaw NPM Release` 接受以下由操作员控制的输入:
`OpenClaw NPM Release` 接受以下由操作人员控制的输入:
- `tag`:必填发布标签,例如 `v2026.4.2`、`v2026.4.2-1` 或
`v2026.4.2-beta.1`
- `preflight_only`:若仅执行验证/构建/打包则为 `true`,若执行实际发布路径则为 `false`
- `preflight_run_id`:在实际发布路径中为必填,这样工作流会复用成功预检运行中准备好的 tarball
- `npm_dist_tag`:发布路径的 npm 目标标签;默认值为 `beta`
- `promote_beta_to_latest`:若为 `true`,则跳过发布,并将已发布的稳定版 `beta` 构建移动到 `latest`
- `tag`:必填发布标签,例如 `v2026.4.2`、`v2026.4.2-1` 或 `v2026.4.2-beta.1`
- `preflight_only``true` 表示仅执行验证 / 构建 / 打包,`false` 表示执行真实发布路径
- `preflight_run_id`:真实发布路径中必填,这样工作流可以复用成功预检运行中准备好的 tarball
- `npm_dist_tag`:发布路径的 npm 目标标签;默认是 `beta`
- `promote_beta_to_latest``true` 表示跳过发布,并将一个已经发布的 stable `beta` 构建移动到 `latest`
规则:
- 稳定版和修正版标签可以发布到 `beta``latest`
- beta 预发布标签只能发布到 `beta`
- 实际发布路径必须使用与预检时相同的 `npm_dist_tag`;工作流会在继续发布前验证该元数据
- 晋升模式必须使用稳定版或修正版标签、`preflight_only=false`、
空的 `preflight_run_id`,以及 `npm_dist_tag=beta`
- 晋升模式还要求 `npm-release`
环境中存在有效的 `NPM_TOKEN`,因为 `npm dist-tag add` 仍然需要常规 npm 认证
- Stable 和修正版标签可以发布到 `beta``latest`
- Beta 预发布标签只能发布到 `beta`
- 真实发布路径必须使用与预检时相同的 `npm_dist_tag`;工作流会在继续发布前校验该元数据
- 提升模式必须使用 stable 或修正版标签、`preflight_only=false`、空的 `preflight_run_id`,以及 `npm_dist_tag=beta`
- 提升模式还要求 `npm-release` 环境中存在有效的 `NPM_TOKEN`,因为 `npm dist-tag add` 仍然需要常规 npm 认证
## 稳定版 npm 发布顺序
## Stable npm 发布顺序
在发布稳定版 npm 时:
在发布 stable npm 版本时:
1. 使用 `preflight_only=true` 运行 `OpenClaw NPM Release`
2. 在常规的先 beta 流程中选择 `npm_dist_tag=beta`,或者仅当你有意直接发布稳定版时才选择 `latest`
1. `preflight_only=true` 运行 `OpenClaw NPM Release`
2. 正常的先 beta 后 stable 流程请选择 `npm_dist_tag=beta`;只有在你明确想直接发布 stable 时才选择 `latest`
3. 保存成功的 `preflight_run_id`
4. 再次运行 `OpenClaw NPM Release`,设置 `preflight_only=false`,并使用相同的
`tag`、相同的 `npm_dist_tag` 和保存的 `preflight_run_id`
5. 如果该发布已落到 `beta`,则在之后运行 `OpenClaw NPM Release`
使用相同的稳定版 `tag`、`promote_beta_to_latest=true`、`preflight_only=false`、
空的 `preflight_run_id``npm_dist_tag=beta`,以便在你想把该已发布构建移动到 `latest` 时执行晋升
4. 再次运行 `OpenClaw NPM Release`,这次使用 `preflight_only=false`,并传入相同的 `tag`、相同的 `npm_dist_tag`,以及上一步保存的 `preflight_run_id`
5. 如果该发布先落在 `beta`,之后当你想把该已发布构建移动到 `latest` 时,再用相同的 stable `tag`、`promote_beta_to_latest=true`、`preflight_only=false`、空的 `preflight_run_id``npm_dist_tag=beta` 运行 `OpenClaw NPM Release`
晋升模式仍然需要 `npm-release` 环境审批,以及该环境中有效的
`NPM_TOKEN`
提升模式仍然需要 `npm-release` 环境审批以及该环境中的有效 `NPM_TOKEN`
这样既保留了直接发布路径,也保留了先 beta 再晋升路径,并且二者都清晰记录、对操作员可见。
这样一来,直接发布路径和先 beta 后提升路径都会被记录下来,并且对操作人员清晰可见。
## 公开参考资料
## 公开参考
- [`.github/workflows/openclaw-npm-release.yml`](https://github.com/openclaw/openclaw/blob/main/.github/workflows/openclaw-npm-release.yml)
- [`scripts/openclaw-npm-release-check.ts`](https://github.com/openclaw/openclaw/blob/main/scripts/openclaw-npm-release-check.ts)
- [`scripts/package-mac-dist.sh`](https://github.com/openclaw/openclaw/blob/main/scripts/package-mac-dist.sh)
- [`scripts/make_appcast.sh`](https://github.com/openclaw/openclaw/blob/main/scripts/make_appcast.sh)
维护者在
[`openclaw/maintainers/release/README.md`](https://github.com/openclaw/maintainers/blob/main/release/README.md)
中使用私有发布文档作为实际操作手册。
维护者会使用私有发布文档 [`openclaw/maintainers/release/README.md`](https://github.com/openclaw/maintainers/blob/main/release/README.md) 作为实际操作手册。