first commit

This commit is contained in:
2026-02-28 23:01:30 +08:00
commit 3956ee4806
415 changed files with 74538 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
---
read_when:
- 打包 OpenClaw.app
- 调试 macOS Gateway 网关 launchd 服务
- 为 macOS 安装 Gateway 网关 CLI
summary: macOS 上的 Gateway 网关运行时(外部 launchd 服务)
title: macOS 上的 Gateway 网关
x-i18n:
generated_at: "2026-02-03T07:52:30Z"
model: claude-opus-4-5
provider: pi
source_hash: 4a3e963d13060b123538005439213e786e76127b370a6c834d85a369e4626fe5
source_path: platforms/mac/bundled-gateway.md
workflow: 15
---
# macOS 上的 Gateway 网关(外部 launchd
OpenClaw.app 不再捆绑 Node/Bun 或 Gateway 网关运行时。macOS 应用期望有一个**外部**的 `openclaw` CLI 安装,不会将 Gateway 网关作为子进程启动,而是管理一个每用户的 launchd 服务来保持 Gateway 网关运行(或者如果已有本地 Gateway 网关正在运行,则连接到现有的)。
## 安装 CLI本地模式必需
你需要在 Mac 上安装 Node 22+,然后全局安装 `openclaw`
```bash
npm install -g openclaw@<version>
```
macOS 应用的**安装 CLI**按钮通过 npm/pnpm 运行相同的流程(不推荐使用 bun 作为 Gateway 网关运行时)。
## LaunchdGateway 网关作为 LaunchAgent
标签:
- `bot.molt.gateway`(或 `bot.molt.<profile>`;旧版 `com.openclaw.*` 可能仍然存在)
Plist 位置(每用户):
- `~/Library/LaunchAgents/bot.molt.gateway.plist`
(或 `~/Library/LaunchAgents/bot.molt.<profile>.plist`
管理者:
- macOS 应用在本地模式下拥有 LaunchAgent 的安装/更新权限。
- CLI 也可以安装它:`openclaw gateway install`
行为:
- "OpenClaw Active"启用/禁用 LaunchAgent。
- 应用退出**不会**停止 Gateway 网关launchd 保持其存活)。
- 如果 Gateway 网关已经在配置的端口上运行,应用会连接到它而不是启动新的。
日志:
- launchd stdout/err`/tmp/openclaw/openclaw-gateway.log`
## 版本兼容性
macOS 应用会检查 Gateway 网关版本与其自身版本是否匹配。如果不兼容,请更新全局 CLI 以匹配应用版本。
## 冒烟测试
```bash
openclaw --version
OPENCLAW_SKIP_CHANNELS=1 \
OPENCLAW_SKIP_CANVAS_HOST=1 \
openclaw gateway --port 18999 --bind loopback
```
然后:
```bash
openclaw gateway call health --url ws://127.0.0.1:18999 --timeout 3000
```

View File

@@ -0,0 +1,128 @@
---
read_when:
- 实现 macOS Canvas 面板
- 为可视化工作区添加智能体控制
- 调试 WKWebView canvas 加载
summary: 通过 WKWebView + 自定义 URL 方案嵌入的智能体控制 Canvas 面板
title: Canvas
x-i18n:
generated_at: "2026-02-03T07:52:39Z"
model: claude-opus-4-5
provider: pi
source_hash: e39caa21542e839d9f59ad0bf7ecefb379225ed7e8f00cd59131d188f193bec6
source_path: platforms/mac/canvas.md
workflow: 15
---
# CanvasmacOS 应用)
macOS 应用使用 `WKWebView` 嵌入一个智能体控制的 **Canvas 面板**。它是一个用于 HTML/CSS/JS、A2UI 和小型交互式界面的轻量级可视化工作区。
## Canvas 存储位置
Canvas 状态存储在 Application Support 下:
- `~/Library/Application Support/OpenClaw/canvas/<session>/...`
Canvas 面板通过**自定义 URL 方案**提供这些文件:
- `openclaw-canvas://<session>/<path>`
示例:
- `openclaw-canvas://main/``<canvasRoot>/main/index.html`
- `openclaw-canvas://main/assets/app.css``<canvasRoot>/main/assets/app.css`
- `openclaw-canvas://main/widgets/todo/``<canvasRoot>/main/widgets/todo/index.html`
如果根目录下没有 `index.html`,应用会显示一个**内置脚手架页面**。
## 面板行为
- 无边框、可调整大小的面板,锚定在菜单栏(或鼠标光标)附近。
- 记住每个会话的大小/位置。
- 当本地 canvas 文件更改时自动重新加载。
- 一次只显示一个 Canvas 面板(根据需要切换会话)。
可以从设置 → **允许 Canvas** 禁用 Canvas。禁用时canvas 节点命令返回 `CANVAS_DISABLED`
## 智能体 API 接口
Canvas 通过 **Gateway 网关 WebSocket** 暴露,因此智能体可以:
- 显示/隐藏面板
- 导航到路径或 URL
- 执行 JavaScript
- 捕获快照图像
CLI 示例:
```bash
openclaw nodes canvas present --node <id>
openclaw nodes canvas navigate --node <id> --url "/"
openclaw nodes canvas eval --node <id> --js "document.title"
openclaw nodes canvas snapshot --node <id>
```
注意事项:
- `canvas.navigate` 接受**本地 canvas 路径**、`http(s)` URL 和 `file://` URL。
- 如果传递 `"/"`Canvas 会显示本地脚手架或 `index.html`
## Canvas 中的 A2UI
A2UI 由 Gateway 网关 canvas 主机托管并在 Canvas 面板内渲染。
当 Gateway 网关广播 Canvas 主机时macOS 应用在首次打开时自动导航到 A2UI 主机页面。
默认 A2UI 主机 URL
```
http://<gateway-host>:18793/__openclaw__/a2ui/
```
### A2UI 命令v0.8
Canvas 目前接受 **A2UI v0.8** 服务器→客户端消息:
- `beginRendering`
- `surfaceUpdate`
- `dataModelUpdate`
- `deleteSurface`
`createSurface`v0.9)不受支持。
CLI 示例:
```bash
cat > /tmp/a2ui-v0.8.jsonl <<'EOFA2'
{"surfaceUpdate":{"surfaceId":"main","components":[{"id":"root","component":{"Column":{"children":{"explicitList":["title","content"]}}}},{"id":"title","component":{"Text":{"text":{"literalString":"Canvas (A2UI v0.8)"},"usageHint":"h1"}}},{"id":"content","component":{"Text":{"text":{"literalString":"If you can read this, A2UI push works."},"usageHint":"body"}}}]}}
{"beginRendering":{"surfaceId":"main","root":"root"}}
EOFA2
openclaw nodes canvas a2ui push --jsonl /tmp/a2ui-v0.8.jsonl --node <id>
```
快速测试:
```bash
openclaw nodes canvas a2ui push --node <id> --text "Hello from A2UI"
```
## 从 Canvas 触发智能体运行
Canvas 可以通过深层链接触发新的智能体运行:
- `openclaw://agent?...`
示例(在 JS 中):
```js
window.location.href = "openclaw://agent?message=Review%20this%20design";
```
除非提供有效密钥,否则应用会提示确认。
## 安全注意事项
- Canvas 方案阻止目录遍历;文件必须位于会话根目录下。
- 本地 Canvas 内容使用自定义方案(不需要 loopback 服务器)。
- 仅在显式导航时允许外部 `http(s)` URL。

View File

@@ -0,0 +1,73 @@
---
read_when:
- 将 mac 应用与 Gateway 网关生命周期集成时
summary: macOS 上的 Gateway 网关生命周期launchd
title: Gateway 网关生命周期
x-i18n:
generated_at: "2026-02-03T07:52:31Z"
model: claude-opus-4-5
provider: pi
source_hash: 9b910f574b723bc194ac663a5168e48d95f55cb468ce34c595d8ca60d3463c6a
source_path: platforms/mac/child-process.md
workflow: 15
---
# macOS 上的 Gateway 网关生命周期
macOS 应用**默认通过 launchd 管理 Gateway 网关**,不会将
Gateway 网关作为子进程生成。它首先尝试连接到配置端口上已运行的
Gateway 网关;如果无法访问,它会通过外部 `openclaw` CLI无嵌入式运行时启用 launchd
服务。这为你提供了可靠的登录时自动启动和崩溃后重启。
子进程模式(由应用直接生成 Gateway 网关)**目前未使用**。
如果你需要与 UI 更紧密的耦合,请在终端中手动运行 Gateway 网关。
## 默认行为launchd
- 应用安装标记为 `bot.molt.gateway` 的按用户 LaunchAgent
(使用 `--profile`/`OPENCLAW_PROFILE` 时为 `bot.molt.<profile>`;支持旧版 `com.openclaw.*`)。
- 当启用本地模式时,应用确保 LaunchAgent 已加载,并
在需要时启动 Gateway 网关。
- 日志写入 launchd Gateway 网关日志路径(在调试设置中可见)。
常用命令:
```bash
launchctl kickstart -k gui/$UID/bot.molt.gateway
launchctl bootout gui/$UID/bot.molt.gateway
```
运行命名配置文件时,将标签替换为 `bot.molt.<profile>`
## 未签名的开发构建
`scripts/restart-mac.sh --no-sign` 用于在没有签名密钥时的快速本地构建。为了防止 launchd 指向未签名的中继二进制文件,它:
- 写入 `~/.openclaw/disable-launchagent`
已签名运行的 `scripts/restart-mac.sh` 会在标记存在时清除此覆盖。要手动重置:
```bash
rm ~/.openclaw/disable-launchagent
```
## 仅连接模式
要强制 macOS 应用**永不安装或管理 launchd**,请使用
`--attach-only`(或 `--no-launchd`)启动它。这会设置 `~/.openclaw/disable-launchagent`
因此应用只会连接到已运行的 Gateway 网关。你可以在调试设置中切换相同的
行为。
## 远程模式
远程模式永远不会启动本地 Gateway 网关。应用使用到
远程主机的 SSH 隧道并通过该隧道连接。
## 为什么我们更喜欢 launchd
- 登录时自动启动。
- 内置的重启/KeepAlive 语义。
- 可预测的日志和监管。
如果将来再次需要真正的子进程模式,它应该被记录为
单独的、明确的仅开发模式。

View File

@@ -0,0 +1,109 @@
---
read_when:
- 设置 macOS 开发环境
summary: 为在 OpenClaw macOS 应用上工作的开发者提供的设置指南
title: macOS 开发设置
x-i18n:
generated_at: "2026-02-03T07:52:36Z"
model: claude-opus-4-5
provider: pi
source_hash: 4ea67701bd58b7512f945fce58d79e1b3d990fbf45183323a1e3ab9688827623
source_path: platforms/mac/dev-setup.md
workflow: 15
---
# macOS 开发者设置
本指南涵盖从源代码构建和运行 OpenClaw macOS 应用程序的必要步骤。
## 前置条件
在构建应用之前,确保你已安装以下内容:
1. **Xcode 26.2+**Swift 开发所需。
2. **Node.js 22+ & pnpm**Gateway 网关、CLI 和打包脚本所需。
## 1. 安装依赖
安装项目范围的依赖:
```bash
pnpm install
```
## 2. 构建和打包应用
要构建 macOS 应用并将其打包到 `dist/OpenClaw.app`,运行:
```bash
./scripts/package-mac-app.sh
```
如果你没有 Apple Developer ID 证书,脚本将自动使用 **ad-hoc 签名**`-`)。
有关开发运行模式、签名标志和 Team ID 故障排除,请参阅 macOS 应用 README
https://github.com/openclaw/openclaw/blob/main/apps/macos/README.md
> **注意**Ad-hoc 签名的应用可能会触发安全提示。如果应用立即崩溃并显示"Abort trap 6",请参阅[故障排除](#troubleshooting)部分。
## 3. 安装 CLI
macOS 应用期望全局安装 `openclaw` CLI 来管理后台任务。
**安装方法(推荐):**
1. 打开 OpenClaw 应用。
2. 转到 **General** 设置标签页。
3. 点击 **"Install CLI"**。
或者,手动安装:
```bash
npm install -g openclaw@<version>
```
## 故障排除
### 构建失败:工具链或 SDK 不匹配
macOS 应用构建期望最新的 macOS SDK 和 Swift 6.2 工具链。
**系统依赖(必需):**
- **软件更新中可用的最新 macOS 版本**Xcode 26.2 SDK 所需)
- **Xcode 26.2**Swift 6.2 工具链)
**检查:**
```bash
xcodebuild -version
xcrun swift --version
```
如果版本不匹配,更新 macOS/Xcode 并重新运行构建。
### 授予权限时应用崩溃
如果在尝试允许**语音识别**或**麦克风**访问时应用崩溃,可能是由于 TCC 缓存损坏或签名不匹配。
**修复:**
1. 重置 TCC 权限:
```bash
tccutil reset All bot.molt.mac.debug
```
2. 如果这不起作用,在 [`scripts/package-mac-app.sh`](https://github.com/openclaw/openclaw/blob/main/scripts/package-mac-app.sh) 中临时更改 `BUNDLE_ID` 以强制 macOS 从"全新状态"开始。
### Gateway 网关无限期"Starting..."
如果 Gateway 网关状态一直停留在"Starting...",检查是否有僵尸进程占用端口:
```bash
openclaw gateway status
openclaw gateway stop
# 如果你没有使用 LaunchAgent开发模式/手动运行),找到监听器:
lsof -nP -iTCP:18789 -sTCP:LISTEN
```
如果手动运行占用了端口停止该进程Ctrl+C。作为最后手段杀死你找到的 PID。

View File

@@ -0,0 +1,41 @@
---
read_when:
- 调试 Mac 应用健康指示器
summary: macOS 应用如何报告 Gateway 网关/Baileys 健康状态
title: 健康检查
x-i18n:
generated_at: "2026-02-03T07:52:40Z"
model: claude-opus-4-5
provider: pi
source_hash: 0560e96501ddf53a499f8960cfcf11c2622fcb9056bfd1bcc57876e955cab03d
source_path: platforms/mac/health.md
workflow: 15
---
# macOS 上的健康检查
如何从菜单栏应用查看关联渠道是否健康。
## 菜单栏
- 状态圆点现在反映 Baileys 健康状态:
- 绿色:已关联 + socket 最近已打开。
- 橙色:正在连接/重试。
- 红色:已登出或探测失败。
- 第二行显示"linked · auth 12m"或显示失败原因。
- "Run Health Check"菜单项触发按需探测。
## 设置
- 通用选项卡新增健康卡片,显示:关联认证时间、会话存储路径/数量、上次检查时间、上次错误/状态码,以及运行健康检查/显示日志按钮。
- 使用缓存快照,因此 UI 立即加载,离线时优雅降级。
- **渠道选项卡**显示渠道状态 + WhatsApp/Telegram 的控制(登录二维码、登出、探测、上次断开/错误)。
## 探测工作原理
- 应用每约 60 秒和按需时通过 `ShellExecutor` 运行 `openclaw health --json`。探测加载凭证并报告状态,不发送消息。
- 分别缓存上次成功的快照和上次错误以避免闪烁;显示每个的时间戳。
## 有疑问时
- 你仍然可以使用 [Gateway 网关健康](/gateway/health) 中的 CLI 流程(`openclaw status``openclaw status --deep``openclaw health --json`),并在 `/tmp/openclaw/openclaw-*.log` 中跟踪 `web-heartbeat` / `web-reconnect`

View File

@@ -0,0 +1,38 @@
---
read_when:
- 更改菜单栏图标行为
summary: macOS 上 OpenClaw 菜单栏图标的状态和动画
title: 菜单栏图标
x-i18n:
generated_at: "2026-02-01T21:32:49Z"
model: claude-opus-4-5
provider: pi
source_hash: a67a6e6bbdc2b611ba365d3be3dd83f9e24025d02366bc35ffcce9f0b121872b
source_path: platforms/mac/icon.md
workflow: 15
---
# 菜单栏图标状态
作者steipete · 更新时间2025-12-06 · 范围macOS 应用(`apps/macos`
- **空闲:** 正常图标动画(眨眼、偶尔摆动)。
- **暂停:** 状态项使用 `appearsDisabled`;无动画。
- **语音触发(大耳朵):** 语音唤醒检测器在听到唤醒词时调用 `AppState.triggerVoiceEars(ttl: nil)`,在捕获语音期间保持 `earBoostActive=true`。耳朵放大1.9 倍),显示圆形耳孔以提高可读性,然后在 1 秒静音后通过 `stopVoiceEars()` 恢复。仅由应用内语音管道触发。
- **工作中(智能体运行中):** `AppState.isWorking=true` 驱动"尾巴/腿部快速摆动"微动画:工作进行中腿部摆动加快并略有偏移。目前在 WebChat 智能体运行时切换;在接入其他长时间任务时请添加相同的切换逻辑。
接入点
- 语音唤醒:运行时/测试器在触发时调用 `AppState.triggerVoiceEars(ttl: nil)`,在 1 秒静音后调用 `stopVoiceEars()` 以匹配捕获窗口。
- 智能体活动:在工作区间前后设置 `AppStateStore.shared.setWorking(true/false)`(已在 WebChat 智能体调用中完成)。保持区间简短,并在 `defer` 块中重置以避免动画卡住。
形状与尺寸
- 基础图标在 `CritterIconRenderer.makeIcon(blink:legWiggle:earWiggle:earScale:earHoles:)` 中绘制。
- 耳朵缩放默认为 `1.0`;语音增强时设置 `earScale=1.9` 并切换 `earHoles=true`不改变整体框架18×18 pt 模板图像渲染到 36×36 px Retina 后备存储)。
- 快速摆动使用最高约 1.0 的腿部摆幅并带有轻微的水平抖动;它与现有的空闲摆动叠加。
行为说明
- 耳朵/工作状态没有外部 CLI/代理切换;保持仅由应用自身信号控制,以避免意外的状态抖动。
- 保持 TTL 较短(&lt;10 秒),以便在任务挂起时图标能快速恢复到基准状态。

View File

@@ -0,0 +1,64 @@
---
read_when:
- 捕获 macOS 日志或调查隐私数据日志记录
- 调试语音唤醒/会话生命周期问题
summary: OpenClaw 日志:滚动诊断文件日志 + 统一日志隐私标志
title: macOS 日志
x-i18n:
generated_at: "2026-02-01T21:32:54Z"
model: claude-opus-4-5
provider: pi
source_hash: c4c201d154915e0eb08bf5e32bac98fa93766f50f2a24bf56ab4424eb7781526
source_path: platforms/mac/logging.md
workflow: 15
---
# 日志macOS
## 滚动诊断文件日志Debug 面板)
OpenClaw 通过 swift-log默认使用统一日志路由 macOS 应用日志,并且在需要持久化捕获时可以将本地轮转文件日志写入磁盘。
- 详细级别:**Debug 面板 → Logs → App logging → Verbosity**
- 启用:**Debug 面板 → Logs → App logging → "Write rolling diagnostics log (JSONL)"**
- 位置:`~/Library/Logs/OpenClaw/diagnostics.jsonl`(自动轮转;旧文件以 `.1``.2`、… 为后缀)
- 清除:**Debug 面板 → Logs → App logging → "Clear"**
注意事项:
- 此功能**默认关闭**。仅在主动调试时启用。
- 该文件包含敏感信息;分享前请先审查内容。
## macOS 上统一日志的隐私数据
统一日志会屏蔽大部分负载内容,除非子系统选择启用 `privacy -off`。根据 Peter 关于 macOS [日志隐私机制](https://steipete.me/posts/2025/logging-privacy-shenanigans)2025的文章这通过 `/Library/Preferences/Logging/Subsystems/` 中以子系统名称为键的 plist 文件来控制。只有新的日志条目才会应用该标志,因此请在复现问题之前启用它。
## 为 OpenClaw 启用(`bot.molt`
- 先将 plist 写入临时文件,然后以 root 身份原子性地安装:
```bash
cat <<'EOF' >/tmp/bot.molt.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>DEFAULT-OPTIONS</key>
<dict>
<key>Enable-Private-Data</key>
<true/>
</dict>
</dict>
</plist>
EOF
sudo install -m 644 -o root -g wheel /tmp/bot.molt.plist /Library/Preferences/Logging/Subsystems/bot.molt.plist
```
- 无需重启logd 会很快检测到该文件,但只有新的日志行才会包含隐私负载。
- 使用现有的辅助脚本查看更丰富的输出,例如 `./scripts/clawlog.sh --category WebChat --last 5m`
## 调试后禁用
- 移除覆盖配置:`sudo rm /Library/Preferences/Logging/Subsystems/bot.molt.plist`
- 可选择运行 `sudo log config --reload` 强制 logd 立即丢弃覆盖配置。
- 请注意此数据可能包含电话号码和消息正文;仅在确实需要额外详细信息时才保留该 plist 文件。

View File

@@ -0,0 +1,88 @@
---
read_when:
- 调整 Mac 菜单 UI 或状态逻辑
summary: 菜单栏状态逻辑及向用户展示的内容
title: 菜单栏
x-i18n:
generated_at: "2026-02-01T21:33:00Z"
model: claude-opus-4-5
provider: pi
source_hash: 8eb73c0e671a76aae4ebb653c65147610bf3e6d3c9c0943d150e292e7761d16d
source_path: platforms/mac/menu-bar.md
workflow: 15
---
# 菜单栏状态逻辑
## 显示内容
- 我们在菜单栏图标和菜单的第一行状态行中展示当前智能体的工作状态。
- 工作活跃时隐藏健康状态;当所有会话空闲时恢复显示。
- 菜单中的"节点"区块仅列出**设备**(通过 `node.list` 配对的节点),不包括客户端/在线状态条目。
- 当提供商用量快照可用时,"用量"部分会显示在上下文下方。
## 状态模型
- 会话:事件携带 `runId`(每次运行)以及载荷中的 `sessionKey`。"main" 会话的键为 `main`;如果不存在,则回退到最近更新的会话。
- 优先级main 始终优先。如果 main 处于活跃状态,立即显示其状态。如果 main 空闲,则显示最近活跃的非 main 会话。活动进行中不会来回切换;仅在当前会话进入空闲或 main 变为活跃时才切换。
- 活动类型:
- `job`:高层命令执行(`state: started|streaming|done|error`)。
- `tool``phase: start|result`,包含 `toolName``meta/args`
## IconState 枚举Swift
- `idle`
- `workingMain(ActivityKind)`
- `workingOther(ActivityKind)`
- `overridden(ActivityKind)`(调试覆盖)
### ActivityKind → 图标符号
- `exec` → 💻
- `read` → 📄
- `write` → ✍️
- `edit` → 📝
- `attach` → 📎
- 默认 → 🛠️
### 视觉映射
- `idle`:正常小动物图标。
- `workingMain`:带图标符号的徽章,完整色调,腿部"工作"动画。
- `workingOther`:带图标符号的徽章,柔和色调,无快跑动画。
- `overridden`:无论活动状态如何,使用所选的图标符号/色调。
## 状态行文本(菜单)
- 工作活跃时:`<会话角色> · <活动标签>`
- 示例:`Main · exec: pnpm test``Other · read: apps/macos/Sources/OpenClaw/AppState.swift`
- 空闲时:回退显示健康摘要。
## 事件接收
- 来源:控制渠道 `agent` 事件(`ControlChannel.handleAgentEvent`)。
- 解析字段:
- `stream: "job"`,包含 `data.state` 用于启动/停止。
- `stream: "tool"`,包含 `data.phase``name`,可选 `meta`/`args`
- 标签:
- `exec``args.command` 的第一行。
- `read`/`write`:缩短的路径。
- `edit`:路径加上从 `meta`/diff 计数推断的变更类型。
- 回退:工具名称。
## 调试覆盖
- 设置 ▸ 调试 ▸ "图标覆盖" 选择器:
- `系统(自动)`(默认)
- `工作中main`(按工具类型)
- `工作中other`(按工具类型)
- `空闲`
- 通过 `@AppStorage("iconOverride")` 存储;映射到 `IconState.overridden`
## 测试清单
- 触发 main 会话任务:验证图标立即切换且状态行显示 main 标签。
- main 空闲时触发非 main 会话任务:图标/状态显示非 main保持稳定直到完成。
- 在 other 活跃时启动 main图标立即切换到 main。
- 快速连续工具调用:确保徽章不会闪烁(工具结果的 TTL 宽限期)。
- 所有会话空闲后健康行重新出现。

View File

@@ -0,0 +1,62 @@
---
read_when:
- 在 OpenClaw.app 中托管 PeekabooBridge
- 通过 Swift Package Manager 集成 Peekaboo
- 更改 PeekabooBridge 协议/路径
summary: 用于 macOS UI 自动化的 PeekabooBridge 集成
title: Peekaboo Bridge
x-i18n:
generated_at: "2026-02-01T21:32:57Z"
model: claude-opus-4-5
provider: pi
source_hash: b5b9ddb9a7c59e153a1d5d23c33616bb1542b5c7dadedc3af340aeee9ba03487
source_path: platforms/mac/peekaboo.md
workflow: 15
---
# Peekaboo BridgemacOS UI 自动化)
OpenClaw 可以将 **PeekabooBridge** 作为本地的、权限感知的 UI 自动化代理进行托管。这使得 `peekaboo` CLI 能够驱动 UI 自动化,同时复用 macOS 应用的 TCC 权限。
## 这是什么(以及不是什么)
- **宿主**OpenClaw.app 可以作为 PeekabooBridge 宿主。
- **客户端**:使用 `peekaboo` CLI无需单独的 `openclaw ui ...` 界面)。
- **界面**:视觉叠加层保留在 Peekaboo.app 中OpenClaw 只是一个轻量代理宿主。
## 启用桥接
在 macOS 应用中:
- 设置 → **启用 Peekaboo Bridge**
启用后OpenClaw 会启动一个本地 UNIX 套接字服务器。如果禁用,宿主会停止,`peekaboo` 将回退到其他可用宿主。
## 客户端发现顺序
Peekaboo 客户端通常按以下顺序尝试宿主:
1. Peekaboo.app完整用户体验
2. Claude.app如已安装
3. OpenClaw.app轻量代理
使用 `peekaboo bridge status --verbose` 查看当前活跃的宿主及使用的套接字路径。你可以通过以下方式覆盖:
```bash
export PEEKABOO_BRIDGE_SOCKET=/path/to/bridge.sock
```
## 安全与权限
- 桥接会验证**调用方的代码签名**;强制执行 TeamID 白名单Peekaboo 宿主 TeamID + OpenClaw 应用 TeamID
- 请求在约 10 秒后超时。
- 如果缺少所需权限,桥接会返回清晰的错误信息,而不是启动系统设置。
## 快照行为(自动化)
快照存储在内存中,并在短暂窗口期后自动过期。如果需要更长的保留时间,请从客户端重新捕获。
## 故障排除
- 如果 `peekaboo` 报告"bridge client is not authorized",请确保客户端已正确签名,或仅在**调试**模式下使用 `PEEKABOO_ALLOW_UNSIGNED_SOCKET_CLIENTS=1` 运行宿主。
- 如果未找到宿主请打开其中一个宿主应用Peekaboo.app 或 OpenClaw.app并确认已授予权限。

View File

@@ -0,0 +1,46 @@
---
read_when:
- 调试缺失或卡住的 macOS 权限提示
- 打包或签名 macOS 应用
- 更改 Bundle ID 或应用安装路径
summary: macOS 权限持久化TCC和签名要求
title: macOS 权限
x-i18n:
generated_at: "2026-02-01T21:32:58Z"
model: claude-opus-4-5
provider: pi
source_hash: d012589c0583dd0b3792d695f3f71a6ff265704cf02a3b79f8c4a5b14712e6aa
source_path: platforms/mac/permissions.md
workflow: 15
---
# macOS 权限TCC
macOS 权限授予是脆弱的。TCC 将权限授予与应用的代码签名、Bundle 标识符和磁盘路径关联。如果其中任何一项发生变化macOS 会将该应用视为新应用,可能会丢弃或隐藏权限提示。
## 稳定权限的要求
- 相同路径:从固定位置运行应用(对于 OpenClaw`dist/OpenClaw.app`)。
- 相同 Bundle 标识符:更改 Bundle ID 会创建新的权限身份。
- 已签名的应用:未签名或临时签名的构建不会持久化权限。
- 一致的签名:使用真实的 Apple Development 或 Developer ID 证书,以确保签名在多次构建之间保持稳定。
临时签名每次构建都会生成新的身份。macOS 会忘记之前的授权,提示可能完全消失,直到清除过期条目为止。
## 权限提示消失时的恢复清单
1. 退出应用。
2. 在系统设置 -> 隐私与安全性中移除该应用条目。
3. 从相同路径重新启动应用并重新授予权限。
4. 如果提示仍未出现,使用 `tccutil` 重置 TCC 条目后重试。
5. 某些权限仅在完全重启 macOS 后才会重新出现。
重置示例(根据需要替换 Bundle ID
```bash
sudo tccutil reset Accessibility bot.molt.mac
sudo tccutil reset ScreenCapture bot.molt.mac
sudo tccutil reset AppleEvents
```
如果你正在测试权限,请始终使用真实证书签名。临时签名的构建仅适用于不需要权限的快速本地运行。

View File

@@ -0,0 +1,92 @@
---
read_when:
- 制作或验证 OpenClaw macOS 发布版本
- 更新 Sparkle appcast 或订阅源资源
summary: OpenClaw macOS 发布清单Sparkle 订阅源、打包、签名)
title: macOS 发布
x-i18n:
generated_at: "2026-02-01T21:33:17Z"
model: claude-opus-4-5
provider: pi
source_hash: 703c08c13793cd8c96bd4c31fb4904cdf4ffff35576e7ea48a362560d371cb30
source_path: platforms/mac/release.md
workflow: 15
---
# OpenClaw macOS 发布Sparkle
本应用现已支持 Sparkle 自动更新。发布构建必须经过 Developer ID 签名、压缩,并发布包含签名的 appcast 条目。
## 前提条件
- 已安装 Developer ID Application 证书(示例:`Developer ID Application: <Developer Name> (<TEAMID>)`)。
- 环境变量 `SPARKLE_PRIVATE_KEY_FILE` 已设置为 Sparkle ed25519 私钥路径(公钥已嵌入 Info.plist。如果缺失请检查 `~/.profile`
- 用于 `xcrun notarytool` 的公证凭据(钥匙串配置文件或 API 密钥),以实现通过 Gatekeeper 安全分发的 DMG/zip。
- 我们使用名为 `openclaw-notary` 的钥匙串配置文件,由 shell 配置文件中的 App Store Connect API 密钥环境变量创建:
- `APP_STORE_CONNECT_API_KEY_P8``APP_STORE_CONNECT_KEY_ID``APP_STORE_CONNECT_ISSUER_ID`
- `echo "$APP_STORE_CONNECT_API_KEY_P8" | sed 's/\\n/\n/g' > /tmp/openclaw-notary.p8`
- `xcrun notarytool store-credentials "openclaw-notary" --key /tmp/openclaw-notary.p8 --key-id "$APP_STORE_CONNECT_KEY_ID" --issuer "$APP_STORE_CONNECT_ISSUER_ID"`
- 已安装 `pnpm` 依赖(`pnpm install --config.node-linker=hoisted`)。
- Sparkle 工具通过 SwiftPM 自动获取,位于 `apps/macos/.build/artifacts/sparkle/Sparkle/bin/``sign_update``generate_appcast` 等)。
## 构建与打包
注意事项:
- `APP_BUILD` 映射到 `CFBundleVersion`/`sparkle:version`;保持纯数字且单调递增(不含 `-beta`),否则 Sparkle 会将其视为相同版本。
- 默认为当前架构(`$(uname -m)`)。对于发布/通用构建,设置 `BUILD_ARCHS="arm64 x86_64"`(或 `BUILD_ARCHS=all`)。
- 使用 `scripts/package-mac-dist.sh` 生成发布产物zip + DMG + 公证)。使用 `scripts/package-mac-app.sh` 进行本地/开发打包。
```bash
# 从仓库根目录运行;设置发布 ID 以启用 Sparkle 订阅源。
# APP_BUILD 必须为纯数字且单调递增,以便 Sparkle 正确比较。
BUNDLE_ID=bot.molt.mac \
APP_VERSION=2026.1.27-beta.1 \
APP_BUILD="$(git rev-list --count HEAD)" \
BUILD_CONFIG=release \
SIGN_IDENTITY="Developer ID Application: <Developer Name> (<TEAMID>)" \
scripts/package-mac-app.sh
# 打包用于分发的 zip包含资源分支以支持 Sparkle 增量更新)
ditto -c -k --sequesterRsrc --keepParent dist/OpenClaw.app dist/OpenClaw-2026.1.27-beta.1.zip
# 可选:同时构建适合用户使用的样式化 DMG拖拽到 /Applications
scripts/create-dmg.sh dist/OpenClaw.app dist/OpenClaw-2026.1.27-beta.1.dmg
# 推荐:构建 + 公证/装订 zip + DMG
# 首先,创建一次钥匙串配置文件:
# xcrun notarytool store-credentials "openclaw-notary" \
# --apple-id "<apple-id>" --team-id "<team-id>" --password "<app-specific-password>"
NOTARIZE=1 NOTARYTOOL_PROFILE=openclaw-notary \
BUNDLE_ID=bot.molt.mac \
APP_VERSION=2026.1.27-beta.1 \
APP_BUILD="$(git rev-list --count HEAD)" \
BUILD_CONFIG=release \
SIGN_IDENTITY="Developer ID Application: <Developer Name> (<TEAMID>)" \
scripts/package-mac-dist.sh
# 可选:随发布一起提供 dSYM
ditto -c -k --keepParent apps/macos/.build/release/OpenClaw.app.dSYM dist/OpenClaw-2026.1.27-beta.1.dSYM.zip
```
## Appcast 条目
使用发布说明生成器,以便 Sparkle 渲染格式化的 HTML 说明:
```bash
SPARKLE_PRIVATE_KEY_FILE=/path/to/ed25519-private-key scripts/make_appcast.sh dist/OpenClaw-2026.1.27-beta.1.zip https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml
```
`CHANGELOG.md`(通过 [`scripts/changelog-to-html.sh`](https://github.com/openclaw/openclaw/blob/main/scripts/changelog-to-html.sh))生成 HTML 发布说明,并将其嵌入 appcast 条目。
发布时,将更新后的 `appcast.xml` 与发布资源zip + dSYM一起提交。
## 发布与验证
-`OpenClaw-2026.1.27-beta.1.zip`(和 `OpenClaw-2026.1.27-beta.1.dSYM.zip`)上传到标签 `v2026.1.27-beta.1` 对应的 GitHub 发布。
- 确保原始 appcast URL 与内置的订阅源匹配:`https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml`
- 完整性检查:
- `curl -I https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml` 返回 200。
- `curl -I <enclosure url>` 在资源上传后返回 200。
- 在之前的公开构建版本上,从 About 选项卡运行"Check for Updates…",验证 Sparkle 能正常安装新构建。
完成定义:已签名的应用 + appcast 已发布,从旧版本的更新流程正常工作,且发布资源已附加到 GitHub 发布。

View File

@@ -0,0 +1,90 @@
---
read_when:
- 设置或调试远程 mac 控制时
summary: macOS 应用通过 SSH 控制远程 OpenClaw Gateway 网关的流程
title: 远程控制
x-i18n:
generated_at: "2026-02-03T07:52:53Z"
model: claude-opus-4-5
provider: pi
source_hash: 61b43707250d5515fd0f85f092bdde24598f14904398ff3fca3736bcc48d72f8
source_path: platforms/mac/remote.md
workflow: 15
---
# 远程 OpenClawmacOS ⇄ 远程主机)
此流程让 macOS 应用作为运行在另一台主机(桌面/服务器)上的 OpenClaw Gateway 网关的完整远程控制。这是应用的 **Remote over SSH**(远程运行)功能。所有功能——健康检查、语音唤醒转发和 Web Chat——都重用来自 _Settings → General_ 的相同远程 SSH 配置。
## 模式
- **Local (this Mac)**:一切都在笔记本电脑上运行。不涉及 SSH。
- **Remote over SSH默认**OpenClaw 命令在远程主机上执行。mac 应用使用 `-o BatchMode` 加上你选择的身份/密钥打开 SSH 连接,并进行本地端口转发。
- **Remote direct (ws/wss)**:无 SSH 隧道。mac 应用直接连接到 Gateway 网关 URL例如通过 Tailscale Serve 或公共 HTTPS 反向代理)。
## 远程传输
远程模式支持两种传输方式:
- **SSH 隧道**(默认):使用 `ssh -N -L ...` 将 Gateway 网关端口转发到 localhost。Gateway 网关会将节点的 IP 视为 `127.0.0.1`,因为隧道是 loopback。
- **Direct (ws/wss)**:直接连接到 Gateway 网关 URL。Gateway 网关看到真实的客户端 IP。
## 远程主机上的先决条件
1. 安装 Node + pnpm 并构建/安装 OpenClaw CLI`pnpm install && pnpm build && pnpm link --global`)。
2. 确保 `openclaw` 在非交互式 shell 的 PATH 中(如需要,请符号链接到 `/usr/local/bin``/opt/homebrew/bin`)。
3. 使用密钥认证打开 SSH。我们推荐使用 **Tailscale** IP 以实现离开局域网时的稳定可达性。
## macOS 应用设置
1. 打开 _Settings → General_
2.**OpenClaw runs** 下,选择 **Remote over SSH** 并设置:
- **Transport****SSH tunnel** 或 **Direct (ws/wss)**
- **SSH target**`user@host`(可选 `:port`)。
- 如果 Gateway 网关在同一局域网上并广播 Bonjour从发现列表中选择它以自动填充此字段。
- **Gateway URL**(仅 Direct`wss://gateway.example.ts.net`(或本地/局域网使用 `ws://...`)。
- **Identity file**(高级):你的密钥路径。
- **Project root**(高级):用于命令的远程 checkout 路径。
- **CLI path**(高级):可运行的 `openclaw` 入口点/二进制文件的可选路径(广播时自动填充)。
3. 点击 **Test remote**。成功表示远程 `openclaw status --json` 正确运行。失败通常意味着 PATH/CLI 问题;退出码 127 表示远程找不到 CLI。
4. 健康检查和 Web Chat 现在将自动通过此 SSH 隧道运行。
## Web Chat
- **SSH 隧道**Web Chat 通过转发的 WebSocket 控制端口(默认 18789连接到 Gateway 网关。
- **Direct (ws/wss)**Web Chat 直接连接到配置的 Gateway 网关 URL。
- 不再有单独的 WebChat HTTP 服务器。
## 权限
- 远程主机需要与本地相同的 TCC 批准(自动化、辅助功能、屏幕录制、麦克风、语音识别、通知)。在该机器上运行新手引导以一次性授予它们。
- 节点通过 `node.list` / `node.describe` 广播其权限状态,以便智能体知道哪些可用。
## 安全注意事项
- 优先在远程主机上使用 loopback 绑定,并通过 SSH 或 Tailscale 连接。
- 如果你将 Gateway 网关绑定到非 loopback 接口,请要求令牌/密码认证。
- 参见[安全](/gateway/security)和 [Tailscale](/gateway/tailscale)。
## WhatsApp 登录流程(远程)
- **在远程主机上**运行 `openclaw channels login --verbose`。用手机上的 WhatsApp 扫描二维码。
- 如果认证过期,在该主机上重新运行登录。健康检查会显示关联问题。
## 故障排除
- **exit 127 / not found**`openclaw` 不在非登录 shell 的 PATH 中。将其添加到 `/etc/paths`、你的 shell rc或符号链接到 `/usr/local/bin`/`/opt/homebrew/bin`
- **Health probe failed**:检查 SSH 可达性、PATH以及 Baileys 是否已登录(`openclaw status --json`)。
- **Web Chat 卡住**:确认 Gateway 网关正在远程主机上运行,转发的端口与 Gateway 网关 WS 端口匹配UI 需要健康的 WS 连接。
- **节点 IP 显示 127.0.0.1**:使用 SSH 隧道时是预期的。如果你想让 Gateway 网关看到真实的客户端 IP请将 **Transport** 切换到 **Direct (ws/wss)**
- **Voice Wake**:触发短语在远程模式下自动转发;不需要单独的转发器。
## 通知声音
通过带有 `openclaw``node.invoke` 的脚本为每个通知选择声音,例如:
```bash
openclaw nodes notify --node <id> --title "Ping" --body "Remote gateway ready" --sound Glass
```
应用中不再有全局"默认声音"开关;调用者为每个请求选择声音(或无声音)。

View File

@@ -0,0 +1,54 @@
---
read_when:
- 构建或签名 Mac 调试构建
summary: 打包脚本生成的 macOS 调试构建的签名步骤
title: macOS 签名
x-i18n:
generated_at: "2026-02-01T21:33:15Z"
model: claude-opus-4-5
provider: pi
source_hash: 403b92f9a0ecdb7cb42ec097c684b7a696be3696d6eece747314a4dc90d8797e
source_path: platforms/mac/signing.md
workflow: 15
---
# Mac 签名(调试构建)
此应用通常从 [`scripts/package-mac-app.sh`](https://github.com/openclaw/openclaw/blob/main/scripts/package-mac-app.sh) 构建,该脚本目前会:
- 设置稳定的调试 Bundle 标识符:`ai.openclaw.mac.debug`
- 使用该 Bundle ID 写入 Info.plist可通过 `BUNDLE_ID=...` 覆盖)
- 调用 [`scripts/codesign-mac-app.sh`](https://github.com/openclaw/openclaw/blob/main/scripts/codesign-mac-app.sh) 对主二进制文件和应用包进行签名,使 macOS 将每次重新构建视为相同的已签名包,并保留 TCC 权限(通知、辅助功能、屏幕录制、麦克风、语音)。要获得稳定的权限,请使用真实签名身份;临时签名是可选的且不稳定(参阅 [macOS 权限](/platforms/mac/permissions))。
- 默认使用 `CODESIGN_TIMESTAMP=auto`;为 Developer ID 签名启用受信任的时间戳。设置 `CODESIGN_TIMESTAMP=off` 可跳过时间戳(离线调试构建)。
- 将构建元数据注入 Info.plist`OpenClawBuildTimestamp`UTC`OpenClawGitCommit`(短哈希),以便"关于"面板可以显示构建信息、git 信息和调试/发布渠道。
- **打包需要 Node 22+**:脚本会运行 TS 构建和 Control UI 构建。
- 从环境变量中读取 `SIGN_IDENTITY`。将 `export SIGN_IDENTITY="Apple Development: Your Name (TEAMID)"`(或你的 Developer ID Application 证书)添加到 shell 配置文件中,以始终使用你的证书签名。临时签名需要通过 `ALLOW_ADHOC_SIGNING=1``SIGN_IDENTITY="-"` 显式启用(不建议用于权限测试)。
- 签名后运行 Team ID 审计,如果应用包内的任何 Mach-O 文件由不同的 Team ID 签名则会失败。设置 `SKIP_TEAM_ID_CHECK=1` 可跳过此检查。
## 用法
```bash
# 从仓库根目录
scripts/package-mac-app.sh # 自动选择身份;未找到时报错
SIGN_IDENTITY="Developer ID Application: Your Name" scripts/package-mac-app.sh # 真实证书
ALLOW_ADHOC_SIGNING=1 scripts/package-mac-app.sh # 临时签名(权限不会持久化)
SIGN_IDENTITY="-" scripts/package-mac-app.sh # 显式临时签名(同样的限制)
DISABLE_LIBRARY_VALIDATION=1 scripts/package-mac-app.sh # 仅限开发的 Sparkle Team ID 不匹配解决方案
```
### 临时签名注意事项
使用 `SIGN_IDENTITY="-"`(临时签名)签名时,脚本会自动禁用**强化运行时**`--options runtime`)。这是为了防止应用在尝试加载不共享相同 Team ID 的嵌入式框架(如 Sparkle时崩溃。临时签名还会破坏 TCC 权限持久化;参阅 [macOS 权限](/platforms/mac/permissions) 了解恢复步骤。
## 关于面板的构建元数据
`package-mac-app.sh` 会在包中标记以下信息:
- `OpenClawBuildTimestamp`:打包时的 ISO8601 UTC 时间
- `OpenClawGitCommit`:短 git 哈希(不可用时为 `unknown`
"关于"选项卡读取这些键以显示版本、构建日期、git 提交以及是否为调试构建(通过 `#if DEBUG`)。代码更改后运行打包程序以刷新这些值。
## 原因
TCC 权限与 Bundle 标识符*和*代码签名绑定。使用不断变化的 UUID 的未签名调试构建会导致 macOS 在每次重新构建后忘记授权。对二进制文件进行签名(默认临时签名)并保持固定的 Bundle ID/路径(`dist/OpenClaw.app`)可以在构建之间保留授权,与 VibeTunnel 的方案一致。

View File

@@ -0,0 +1,40 @@
---
read_when:
- 更新 macOS Skills 设置 UI
- 更改 Skills 门控或安装行为
summary: macOS Skills 设置 UI 和基于 Gateway 网关的状态
title: Skills
x-i18n:
generated_at: "2026-02-03T10:08:09Z"
model: claude-opus-4-5
provider: pi
source_hash: ecd5286bbe49eed89319686c4f7d6da55ef7b0d3952656ba98ef5e769f3fbf79
source_path: platforms/mac/skills.md
workflow: 15
---
# SkillsmacOS
macOS 应用通过 Gateway 网关展示 OpenClaw Skills它不会在本地解析 Skills。
## 数据来源
- `skills.status`Gateway 网关)返回所有 Skills 以及资格和缺失的要求
(包括内置 Skills 的允许列表阻止情况)。
- 要求来源于每个 `SKILL.md` 中的 `metadata.openclaw.requires`
## 安装操作
- `metadata.openclaw.install` 定义安装选项brew/node/go/uv
- 应用调用 `skills.install` 在 Gateway 网关主机上运行安装器。
- 当提供多个安装器时Gateway 网关仅展示一个首选安装器
(如果可用则使用 brew否则使用来自 `skills.install` 的 node 管理器,默认 npm
## 环境变量/API 密钥
- 应用将密钥存储在 `~/.openclaw/openclaw.json``skills.entries.<skillKey>` 下。
- `skills.update` 更新 `enabled``apiKey``env`
## 远程模式
- 安装 + 配置更新发生在 Gateway 网关主机上(不是本地 Mac

View File

@@ -0,0 +1,67 @@
---
read_when:
- 调整语音浮层行为
summary: 唤醒词与按键说话重叠时的语音浮层生命周期
title: 语音浮层
x-i18n:
generated_at: "2026-02-01T21:33:26Z"
model: claude-opus-4-5
provider: pi
source_hash: 3be1a60aa7940b2368ff62cd49f04b2b8422876030e8ea206b467f66a5a6bd4d
source_path: platforms/mac/voice-overlay.md
workflow: 15
---
# 语音浮层生命周期macOS
受众macOS 应用贡献者。目标:在唤醒词与按键说话重叠时保持语音浮层行为可预测。
### 当前意图
- 如果浮层已因唤醒词显示,此时用户按下热键,热键会话会*接管*现有文本而非重置。浮层在热键按住期间保持显示。用户松开时:如果有去除空白后的文本则发送,否则关闭。
- 单独使用唤醒词时仍在静音后自动发送;按键说话在松开时立即发送。
### 已实现2025 年 12 月 9 日)
- 浮层会话现在为每次捕获(唤醒词或按键说话)携带一个令牌。当令牌不匹配时,部分/最终/发送/关闭/音量更新会被丢弃,避免过时回调。
- 按键说话会接管任何可见的浮层文本作为前缀(因此在唤醒浮层显示时按下热键会保留文本并追加新语音)。它最多等待 1.5 秒获取最终转录结果,然后回退到当前文本。
- 提示音/浮层日志以 `info` 级别输出,分类为 `voicewake.overlay``voicewake.ptt``voicewake.chime`(会话开始、部分、最终、发送、关闭、提示音原因)。
### 后续步骤
1. **VoiceSessionCoordinatoractor**
- 同一时间只拥有一个 `VoiceSession`
- API基于令牌`beginWakeCapture``beginPushToTalk``updatePartial``endCapture``cancel``applyCooldown`
- 丢弃携带过时令牌的回调(防止旧识别器重新打开浮层)。
2. **VoiceSession模型**
- 字段:`token``source`wakeWord|pushToTalk、已提交/临时文本、提示音标志、计时器(自动发送、空闲)、`overlayMode`display|editing|sending、冷却截止时间。
3. **浮层绑定**
- `VoiceSessionPublisher``ObservableObject`)将活跃会话镜像到 SwiftUI。
- `VoiceWakeOverlayView` 仅通过 publisher 渲染;绝不直接修改全局单例。
- 浮层用户操作(`sendNow``dismiss``edit`)携带会话令牌回调到 coordinator。
4. **统一发送路径**
- `endCapture` 时:如果去除空白后文本为空 → 关闭;否则 `performSend(session:)`(播放一次发送提示音、转发、关闭)。
- 按键说话:无延迟;唤醒词:可选自动发送延迟。
- 按键说话结束后对唤醒运行时施加短暂冷却,防止唤醒词立即重新触发。
5. **日志**
- Coordinator 在子系统 `bot.molt`、分类 `voicewake.overlay``voicewake.chime` 下输出 `.info` 级别日志。
- 关键事件:`session_started``adopted_by_push_to_talk``partial``finalized``send``dismiss``cancel``cooldown`
### 调试清单
- 复现浮层粘滞问题时流式查看日志:
```bash
sudo log stream --predicate 'subsystem == "bot.molt" AND category CONTAINS "voicewake"' --level info --style compact
```
- 验证只有一个活跃会话令牌;过时回调应被 coordinator 丢弃。
- 确保按键说话松开时始终使用活跃令牌调用 `endCapture`;如果文本为空,预期 `dismiss` 且不播放提示音或发送。
### 迁移步骤(建议)
1. 添加 `VoiceSessionCoordinator`、`VoiceSession` 和 `VoiceSessionPublisher`。
2. 重构 `VoiceWakeRuntime`,使其创建/更新/结束会话,而非直接操作 `VoiceWakeOverlayController`。
3. 重构 `VoicePushToTalk`,使其接管现有会话并在松开时调用 `endCapture`;施加运行时冷却。
4. 将 `VoiceWakeOverlayController` 连接到 publisher移除来自 runtime/PTT 的直接调用。
5. 添加会话接管、冷却和空文本关闭的集成测试。

View File

@@ -0,0 +1,74 @@
---
read_when:
- 开发语音唤醒或按键通话路径
summary: Mac 应用中的语音唤醒和按键通话模式及路由详情
title: 语音唤醒
x-i18n:
generated_at: "2026-02-03T10:08:23Z"
model: claude-opus-4-5
provider: pi
source_hash: f6440bb89f349ba5c1c9aacffe95e568681beb9899ca736dedfe2f4a366cb5e4
source_path: platforms/mac/voicewake.md
workflow: 15
---
# 语音唤醒与按键通话
## 模式
- **唤醒词模式**(默认):常驻语音识别器等待触发词(`swabbleTriggerWords`)。匹配时开始捕获,显示带有部分文本的悬浮窗,并在静默后自动发送。
- **按键通话(按住右 Option 键)**:按住右 Option 键立即开始捕获——无需触发词。按住时显示悬浮窗;松开后延迟片刻再最终转发,以便你可以调整文本。
## 运行时行为(唤醒词)
- 语音识别器位于 `VoiceWakeRuntime` 中。
- 仅当唤醒词和下一个词之间有**明显停顿**(约 0.55 秒间隔)时才触发。悬浮窗/提示音可以在命令开始前的停顿时就启动。
- 静默窗口:语音流畅时为 2.0 秒,如果只听到触发词则为 5.0 秒。
- 硬性停止120 秒,防止会话失控。
- 会话间去抖动350 毫秒。
- 悬浮窗通过 `VoiceWakeOverlayController` 驱动,带有已提交/临时状态的颜色区分。
- 发送后,识别器干净地重启以监听下一个触发词。
## 生命周期不变量
- 如果启用了语音唤醒且权限已授予,唤醒词识别器应该处于监听状态(除非正在进行显式的按键通话捕获)。
- 悬浮窗可见性(包括通过 X 按钮手动关闭)绝不能阻止识别器恢复。
## 悬浮窗卡住的故障模式(之前的问题)
之前,如果悬浮窗卡在可见状态且你手动关闭它,语音唤醒可能会显得"失效",因为运行时的重启尝试可能被悬浮窗可见性阻止,且没有安排后续重启。
加固措施:
- 唤醒运行时重启不再被悬浮窗可见性阻止。
- 悬浮窗关闭完成时通过 `VoiceSessionCoordinator` 触发 `VoiceWakeRuntime.refresh(...)`,因此手动点击 X 关闭总是会恢复监听。
## 按键通话细节
- 热键检测使用全局 `.flagsChanged` 监视器检测**右 Option 键**`keyCode 61` + `.option`)。我们只观察事件(不拦截)。
- 捕获管道位于 `VoicePushToTalk` 中:立即启动语音识别,将部分结果流式传输到悬浮窗,并在松开时调用 `VoiceWakeForwarder`
- 按键通话开始时,我们暂停唤醒词运行时以避免音频采集冲突;松开后自动重启。
- 权限:需要麦克风 + 语音识别权限;查看事件需要辅助功能/输入监控批准。
- 外接键盘:某些键盘可能无法按预期暴露右 Option 键——如果用户报告未响应,提供备用快捷键。
## 面向用户的设置
- **语音唤醒**开关:启用唤醒词运行时。
- **按住 Cmd+Fn 说话**:启用按键通话监视器。在 macOS < 26 上禁用
- 语言和麦克风选择器实时电平指示器触发词表测试器仅本地不转发)。
- 麦克风选择器在设备断开时保留上次选择显示断开提示并临时回退到系统默认设备直到设备恢复
- **声音**触发检测和发送时的提示音默认为 macOS"Glass"系统声音你可以为每个事件选择任何 `NSSound` 可加载的文件例如 MP3/WAV/AIFF或选择**无声音**。
## 转发行为
- 启用语音唤醒时转录文本被转发到活动的 Gateway 网关/智能体 Mac 应用其他部分使用相同的本地/远程模式)。
- 回复被投递到**上次使用的主提供商**WhatsApp/Telegram/Discord/WebChat)。如果投递失败错误会被记录运行记录仍可通过 WebChat/会话日志查看
## 转发负载
- `VoiceWakeForwarder.prefixedTranscript(_:)` 在发送前添加机器提示前缀唤醒词和按键通话路径共享此方法
## 快速验证
- 开启按键通话按住 Cmd+Fn说话松开悬浮窗应显示部分结果然后发送
- 按住时菜单栏耳朵图标应保持放大状态使用 `triggerVoiceEars(ttl:nil)`松开后恢复

View File

@@ -0,0 +1,43 @@
---
read_when:
- 调试 macOS WebChat 视图或 loopback 端口
summary: macOS 应用如何嵌入 Gateway 网关 WebChat 以及如何调试
title: WebChat
x-i18n:
generated_at: "2026-02-03T07:52:46Z"
model: claude-opus-4-5
provider: pi
source_hash: 04ff448758e530098e2004625f33e42fc3dbe31137cd3beec2d55590e507de08
source_path: platforms/mac/webchat.md
workflow: 15
---
# WebChatmacOS 应用)
macOS 菜单栏应用将 WebChat UI 嵌入为原生 SwiftUI 视图。它连接到 Gateway 网关,默认使用所选智能体的**主会话**(带有会话切换器用于其他会话)。
- **本地模式**:直接连接到本地 Gateway 网关 WebSocket。
- **远程模式**:通过 SSH 转发 Gateway 网关控制端口,并使用该隧道作为数据平面。
## 启动和调试
- 手动Lobster 菜单 → "Open Chat"。
- 测试时自动打开:
```bash
dist/OpenClaw.app/Contents/MacOS/OpenClaw --webchat
```
- 日志:`./scripts/clawlog.sh`(子系统 `bot.molt`,类别 `WebChatSwiftUI`)。
## 工作原理
- 数据平面Gateway 网关 WS 方法 `chat.history`、`chat.send`、`chat.abort`、`chat.inject` 和事件 `chat`、`agent`、`presence`、`tick`、`health`。
- 会话:默认为主会话(`main`,或当范围为全局时为 `global`。UI 可以在会话之间切换。
- 新手引导使用专用会话,以将首次运行设置分开。
## 安全面
- 远程模式仅通过 SSH 转发 Gateway 网关 WebSocket 控制端口。
## 已知限制
- UI 针对聊天会话优化(不是完整的浏览器沙箱)。

View File

@@ -0,0 +1,68 @@
---
read_when:
- 编辑 IPC 合约或菜单栏应用 IPC
summary: OpenClaw 应用的 macOS IPC 架构、Gateway 网关节点传输和 PeekabooBridge
title: macOS IPC
x-i18n:
generated_at: "2026-02-03T07:52:57Z"
model: claude-opus-4-5
provider: pi
source_hash: d0211c334a4a59b71afb29dd7b024778172e529fa618985632d3d11d795ced92
source_path: platforms/mac/xpc.md
workflow: 15
---
# OpenClaw macOS IPC 架构
**当前模型:** 一个本地 Unix 套接字将**节点主机服务**连接到 **macOS 应用**,用于 exec 审批 + `system.run`。存在一个 `openclaw-mac` 调试 CLI 用于发现/连接检查;智能体操作仍通过 Gateway 网关 WebSocket 和 `node.invoke` 流转。UI 自动化使用 PeekabooBridge。
## 目标
- 单个 GUI 应用实例拥有所有面向 TCC 的工作通知、屏幕录制、麦克风、语音、AppleScript
- 小型自动化接口Gateway 网关 + 节点命令,加上用于 UI 自动化的 PeekabooBridge。
- 可预测的权限:始终是同一个签名的 bundle ID由 launchd 启动,因此 TCC 授权保持有效。
## 工作原理
### Gateway 网关 + 节点传输
- 应用运行 Gateway 网关(本地模式)并作为节点连接到它。
- 智能体操作通过 `node.invoke` 执行(例如 `system.run``system.notify``canvas.*`)。
### 节点服务 + 应用 IPC
- 一个无头节点主机服务连接到 Gateway 网关 WebSocket。
- `system.run` 请求通过本地 Unix 套接字转发到 macOS 应用。
- 应用在 UI 上下文中执行 exec必要时提示并返回输出。
图示SCI
```
Agent -> Gateway -> Node Service (WS)
| IPC (UDS + token + HMAC + TTL)
v
Mac App (UI + TCC + system.run)
```
### PeekabooBridgeUI 自动化)
- UI 自动化使用名为 `bridge.sock` 的单独 UNIX 套接字和 PeekabooBridge JSON 协议。
- 主机优先顺序客户端侧Peekaboo.app → Claude.app → OpenClaw.app → 本地执行。
- 安全性:桥接主机需要允许的 TeamID仅 DEBUG 的同 UID 逃逸通道由 `PEEKABOO_ALLOW_UNSIGNED_SOCKET_CLIENTS=1` 保护Peekaboo 约定)。
- 参见:[PeekabooBridge 用法](/platforms/mac/peekaboo)了解详情。
## 操作流程
- 重启/重建:`SIGN_IDENTITY="Apple Development: <Developer Name> (<TEAMID>)" scripts/restart-mac.sh`
- 终止现有实例
- Swift 构建 + 打包
- 写入/引导/启动 LaunchAgent
- 单实例:如果具有相同 bundle ID 的另一个实例正在运行,应用会提前退出。
## 加固注意事项
- 优先要求所有特权接口的 TeamID 匹配。
- PeekabooBridge`PEEKABOO_ALLOW_UNSIGNED_SOCKET_CLIENTS=1`(仅 DEBUG可能允许同 UID 调用者用于本地开发。
- 所有通信仅保持本地;不暴露网络套接字。
- TCC 提示仅源自 GUI 应用包;在重建时保持签名的 bundle ID 稳定。
- IPC 加固:套接字模式 `0600`、令牌、对等 UID 检查、HMAC 质询/响应、短 TTL。