21/Documentation
语音输入与 Web Push
输入框中的麦克风,以及 agent 等待你操作时的通知
这两项功能默认均已禁用。您可以在编辑器中启用麦克风按钮,并启用在 agent 等待输入时触发的浏览器通知。
语音输入(可选)
一个 输入框中的麦克风按钮,以及 Settings → Voice 中的一个 免提开关。点击按钮并说话,转录文本就会填入输入框,供你查看并发送。开启免提时会自动替你发送,走的是与手动输入文本相同的受保护回复路径,绝不绕过。只要输入框为空,麦克风就会就是整行末尾的圆形按钮;一旦输入第一个字符,它就会变回发送按钮。要么听写,要么打字,以此保持单一主操作,避免两个按钮争抢输入框的宽度。
说话时,录音界面会完全覆盖编辑区、功能栏和输入框,且不增加高度,因此上方的屏幕内容完全不会位移。OK 出现在原本麦克风的位置,点击可结束录音。最远端的 废弃 会废弃录音,在音频转录过程中点击仍可取消。说话停止后,保持安静两秒会自动结束录音;OK 周围会闭合一圈动画作为提示,再次开口会重新计时。在说出第一个字之前,录音绝不会自行结束。
在配置提供方之前,该功能并不存在。 运行 collie stt setup,或者配置 Whistle(见下文)。未配置时不渲染按钮、不从手机传出音频、不保存凭据、不运行子进程。是直接不存在,而非仅禁用。共有四个提供方:
| 提供商 | 具体含义 |
|---|---|
openai-compatible | 任何支持 POST /audio/transcriptions 的端点:公共 OpenAI API、云端 Whisper 克隆版或 同一台机器上的本地引擎,这是零出站流量的选择(下方)。 |
codex | 借用你已经信任的 codex 二进制文件获取临时令牌。无需新账号,也无需新密钥,但该 私有、不受支持 端点包含一步授权:在终端输入 yes,或在 Settings 中点击 我接受(下方)。 |
local-cli | 每次录音运行一次宿主机上已有的转录命令(例如 whisper-cli 或 muesli-cli),并从其标准输出读取转录结果。无需 HTTP 服务器(下方)。 |
whistle | Collie 自带的引擎,Whistle。无需配置密钥或命令。最长 4 分钟的录音会以 WAV 文件形式发送给它,音频保留在宿主机上。手机也可以在本地运行 Whistle,无需上传。 |
配置必须通过 CLI 操作,原因与 配对 相同:该界面接收凭据,因此必须在宿主机的键盘上完成。没有任何用于填写密钥、端点或命令的 Web 表单。两个不需要这些信息的例外。 Whistle 不保存凭据、不运行自定义命令,也不将音频传出宿主机,因此拥有写入权限的设备可以在 Settings 中进行配置(原因)。在 Settings → Voice → Host speech 中,拥有写入权限的设备可以让宿主机在 Whistle、ChatGPT 订阅(即 codex 提供方)和关闭之间切换。启用 ChatGPT 前,必须完成终端输出的同等授权并点击 我接受(下方)。在终端中通过密钥、命令配置的提供方,或由环境变量指定的提供方,会在该页面显示且绝不能在应用内修改。针对这两种情况,页面仅展示需要在宿主机上运行的命令,附带 复制 和 再次检查,不提供表单。
$ bin/collie stt setup
Which speech-to-text provider?
openai-compatible any endpoint that speaks POST /audio/transcriptions —
the public OpenAI API, or a local whisper.cpp / parakeet.cpp
server, which is the zero-egress choice and the one to prefer.
codex borrow your own `codex` sign-in. No new key, no new account —
and a private endpoint that may break without notice.
local-cli run a transcription command already on this machine, such as
whisper-cli or muesli-cli. Its stdout is the transcript.
provider [openai-compatible]:
The API base, INCLUDING its version prefix — the provider appends /audio/transcriptions.
local http://127.0.0.1:8080/v1 (whisper.cpp / parakeet.cpp — nothing leaves the host)
cloud https://api.openai.com/v1 (room audio leaves this machine)
base URL: http://127.0.0.1:8080/v1
The model the endpoint understands. Empty takes Collie's default, gpt-transcribe.
model [gpt-transcribe]: whisper-1
API key [none]:
The language you speak, as a two-letter ISO-639-1 code — en, de, tr, ja.
LEAVE IT EMPTY to let the model detect it, which is what you want if you mix languages in one
sentence. Name one only if short clips keep coming back in a language you did not speak: a few
seconds of accented audio is too little for the model to detect from, and it guesses.
spoken language [auto-detect]: en
✓ speech-to-text configured — /home/you/.local/state/collie/stt.json (owner-only)
Live immediately — no restart needed. The bridge re-reads this file per request.
Check it end to end with `collie stt test`.上述每个问题都有对应的 flag(--provider · --url · --model · --key · --lang),因此配置运行不需要终端。将密钥留空是一种受支持的模式:调用无密钥端点时完全不带 Authorization 请求头,而不是带一个空请求头。
仅在出现一种失败情况时才值得设置口述语言。 留空(默认值)时,模型会自行检测语言,这正是在一句话中混合两种语言的人所需要的。如果 短 片段总是以你未说过的语言返回,请设置此项:几秒钟带口音的音频不足以完成检测,模型会进行猜测。可以使用双字母代码,或由 Collie 为你缩减范围的地区标签(en-GB → en)。它仅适用于 openai-compatible 提供商;codex 端点不接受语言参数,collie stt status 会明确指出这一点,而不是让你误以为支持。
较长的录音会获得较长的超时限制。 浏览器对单个片段的时间预算是该片段大小的函数,而非固定数值:它假定上行速率持续为 256 kb/s,并在此基础上加上桥接器自身的提供商超时上限,因此 8 MiB 的最大值允许略低于六分钟的时间。Collie 愿意录制的片段就是它愿意等待的片段。上传进行期间,Collie 会停止轮询并停止升级连接横幅的提示状态:手机上行被你自己的音频占满不是停机故障,绝不能被报告为故障。
录音最长持续 5 分钟。运行 Whistle 的宿主机限制为 4 分钟,因为手机发送的是 WAV 文件,体积约为压缩音频的 4 倍。录音界面会显示适用的时长上限。
是否生效? stt test 会通过真实服务商发送 0.2 秒生成的静音音频,手机能录制的每种容器格式各发送一次:
$ bin/collie stt test
provider: openai-compatible (http://127.0.0.1:8080/v1, model whisper-1, language en)
sending: 0.2 s of generated silence as audio/wav (the setup probe) … ✓ 214 ms
transcript: (empty) — expected from silence, and the empty answer still proves the pipeline.
sending: 0.2 s of generated silence as audio/webm;codecs=opus (Chrome, Android, Firefox) … ✓ 198 ms
sending: 0.2 s of generated silence as audio/mp4 (Safari, iOS) … ✓ 190 ms在宿主机运行 Whistle 时,stt test 会发送一段 16 kHz WAV 音频,并提示跳过 webm 和 mp4,因为手机在将录音发送给该提供方之前已将其转换为 16 kHz WAV。
空转录结果即为通过:静音转录结果为空,而我们要验证的正是这个往返过程。如果失败,错误信息会指明其类型(身份验证、端点、响应格式)。然后在手机上重新加载 Collie:消息框旁会出现一个麦克风。collie stt status 会说明已配置的内容以及各项设置的来源(文件,或优先级更高的环境变量);collie stt off 会移除 stt.json,按钮随即消失,无论哪种操作都无需重启。
Whistle:在手机或宿主机上运行的语音转文本
Whistle 是 Cactus Compute 开发的小型语音模型。文件大小为 16.9 MB,采用 Apache-2.0 许可证。它支持英语、德语、法语、西班牙语、意大利语、荷兰语和波兰语,并能自动识别语言。无需账号、密钥或额外程序。Collie 内置了运行该模型的引擎,支持在 Linux、macOS、Windows 和 NixOS 上运行。
Whistle 可以在两处运行。你可以针对每台手机分别选择。
| 引擎 | 文字生成位置 | 适用场景 |
|---|---|---|
| 宿主机 | 在运行 Collie 的计算机上,作为 Collie 自身二进制文件的短期子进程运行。 | 手机性能较弱或较旧。录音作为 WAV 文件上传,一段语音处理需要一两秒。 |
| 此手机 | 在手机浏览器中,运行于 worker 内。 | 手机性能较新。无需上传,音频从不离开手机;模型下载到手机后即可离线运行。 |
两个引擎读取同一个模型。主机保留一份副本。希望自行运行 Whistle 的手机会直接从主机复制模型,绝不会从互联网下载。在较新的手机上,一段语音处理大约需要一秒。
从“设置”中进行设置。 您需要一台具备写入权限的设备(拥有 已配对 的设备)。只读设备会看到“拥有写入权限的设备可进行设置。”且无法开始下载。
Settings → Voice 包含一个主页面及下辖的两个子页面:
- 语音 会优先展示正在使用的配置。顶部卡片的标题显示已配置的内容:主机运行的命令,例如
whisper-cli下带 模型 ggml-base.bin 和 您主机上的自定义命令;语音服务的模型,例如whisper-large-v3带 api.groq.com 的语音服务;Cactus Compute 出品的 Whistle 带 模型 ca52876 以及 在此手机上 或 在您的主机上;或者 ChatGPT 订阅 (OpenAI) 带 通过主机上的 Codex。如果该命令是旧版whistle-stt封装器,卡片会作出说明并提供 切换至内置 Whistle,点击可打开“主机语音”。接下来是状态,显示其依赖项,例如“就绪。Whistle ca52876 已在此手机上。”或“未就绪。Codex 在您的主机上处于退出登录状态。”,还有 音频 发往的位置,以及它是如何被 设置 的(由哪台设备在何时从“设置”配置,或在主机的终端中配置)。卡片下方是免提开关。其余所有内容均收纳在单行 修改语音工作方式 中。在语音功能正常工作时,每次访问该行均保持折叠状态。当功能异常时(未设置任何内容、手机已暂停、主机选项未响应),该行会展开,且顶部卡片显示对应操作:在此手机上设置语音、恢复 或 修复。展开后,它会显示该手机自己的选项:在此手机上(带有 推荐 标记)或 在您的主机上(运行代理的计算机),此项按设备单独保存。正在使用的选项带有加粗边框、底色浅调和 使用中 徽标,在两者之间切换不会移动页面上的任何内容。随后是一行主机使用的配置(点击可展开全部五个选项),以及一行模型信息。每个选项都有一个信息按钮,列出关于该选项的五项事实:音频发往何处、是否支持离线工作、费用、所需的配置步骤以及速度。点击信息按钮不会选中任何选项。 - 宿主机语音 列出了主机的五个选项。Whistle 和自定义命令会将音频保留在您的机器上。语音服务和 ChatGPT 订阅则会将音频发送至主机外部。关闭选项单独位于它们下方。此处的更改适用于与该主机配对的每台设备。如果新选择的方案比被替换的方案传输音频范围更广,系统会先进行确认;点击即可回退。每个选项都包含 设置方法:编号步骤、供复制的命令,以及应用可执行操作的自带按钮。下一步要执行的操作标有 下一步。仅当正在使用的选项无法工作时,它才会单独展开。正在使用的选项还会显示已配置的内容,例如“已配置:whisper-cli,模型 ggml-base.bin”。
- Whistle 模型 说明了制作方 Cactus Compute、许可证,并提供了指向 Hugging Face 上模型页面的链接。它展示了主机上的副本与此手机上的副本,二者各自显示独立状态。
配置 Whistle:
- 在语音功能尚无法使用的手机上,轻触 语音 顶部卡片中的 在此手机上设置语音。点击一次即可完成全部流程:如果主机缺少该模型,则先下载;本手机随后从主机复制该模型,并选中 在此手机上。进度条会显示进度及当前执行的步骤(“正在下载到主机…”或“正在复制到此手机…”)。如果某一步失败,流程将停止,说明原因并提供 重试。只读设备可以复制,因为复制属于读取操作,但它不能要求主机执行下载。相同的两个步骤也位于 修改语音工作方式 下:在没有副本的手机上显示为 配置 (16.9 MB),在主机已拥有模型时显示为 复制到此手机。
- 或者打开 Whistle 模型 并轻触 下载到主机 (16.9 MB)。进度条会显示进度。如果失败,页面会说明原因。轻触 重试。当模型就绪后,页面会列出其版本(Hugging Face 修订版本的前七个字符以及指向该修订版本的链接)及其大小。详细信息 显示简短的校验和以及主机下载该模型的时间。
- 若要通过主机进行听写,请打开 宿主机语音 并依次选择 主机上的 Whistle 和 针对所有设备更改。或者打开其下方的 设置方法 并轻触 在主机上使用。如果您在终端中配置了带有密钥或命令的其他提供方,页面会显示该提供方且不提供选择项。Whistle 的步骤随后会在主机上以
collie stt off开始,然后执行collie stt whistle --host。 - 针对此手机上的副本,Whistle 模型 会标明版本并提供 从此手机中移除。它还会说明浏览器是同意保留该副本(“已保留”),还是可能在空间不足时将其清除。如果主机稍后获取了更新的模型,该副本会给出提示并提供 更新。
- 在 语音 上,打开 修改语音工作方式 并选择 在此手机上 或 在您的主机上。在手机获取副本之前,在此手机上 处于停用状态。在主机没有可用语音选项时,在您的主机上 处于停用状态。所选项目下方的文本行会标明主机使用的配置。
- 若要从主机中移除模型,请轻触 Whistle 模型 上的 从主机中移除 并确认。如果 Whistle 是主机引擎,则在您重新下载之前,主机上的语音功能将停止使用。
更改者。 当配对的设备从“设置”更改主机的选项时,主机将记录该设备的名称及时间。语音 和 宿主机语音 随后会显示“最后由 Pixel 8 更改”及时间。在终端中进行的更改会清除该记录。
或者在终端中进行配置。
$ bin/collie stt whistle # fetch the model once
$ bin/collie stt whistle --host # also make Whistle this host's engine
$ bin/collie stt whistle --from <path> # use a copy you already have, same hash check
$ bin/collie stt whistle --remove # remove the model, and the host engine if it is Whistle
$ bin/collie stt status # shows the model line在替换您特意配置的提供方之前,--host 会先进行询问。--yes 可以在没有终端的运行环境中应答此提问。提问出现在下载之前,因此被拒绝的运行不会拉取任何内容。--remove 会保留其他类型的提供方。collie stt off 会移除提供方,并提示模型仍会保留。当主机上的模型不是本版本所接受的模型时,collie doctor 会发出警告。该引擎立即可用,无需重启。使用 collie stt test 检查状态。
下载的内容及下载来源。 主机从一个固定的 Hugging Face 地址拉取 whistle.cact,跟随重定向至其 CDN(最多五次,仅限 HTTPS,且绝不重定向至本地或私有地址),并且仅在其 sha256 与本版本携带的哈希值一致时才保留该文件。哈希值不匹配会删除该文件并报告这两个哈希值。下载上限为 32 MiB,超时时间为 10 分钟。该文件保存在状态目录的 whistle 文件夹中。引擎代码(约 1 MB)包含在每个 Collie 发行版中,来自 Collie 自身的文件。
不会自行下载任何内容。 不会在安装时下载,不会在更新时下载,也不会在您选择引擎时下载。仅当用户轻触 下载到宿主机、设置 或运行 collie stt whistle 时,模型才会下载。当手机所有者轻触 设置、复制到此手机 或 恢复 时,手机会从主机复制该模型,且不会从其他任何位置复制。主机最多同时向两台手机发送模型。第三台手机会收到“请稍后重试”的提示。
限制。 主机引擎可处理长达 4 分钟的录音,因为 WAV 大小约为压缩音频的四倍,且上传上限保持为 8 MiB。录音器会显示该上限。手机引擎最多可处理 5 分钟。主机子进程的超时时间为音频长度的一半,最少 60 秒,最多 3 分钟,且主机上最多同时处理两段音频。手机需要有容纳模型的空闲空间(会申请两倍于文件大小的空间)以及安全连接(HTTPS,如 tailscale serve 所提供)。
当手机无法处理时。 如果某段音频在 在此手机上 上处理失败,语音界面会说明原因并提供 发送到主机,前提是主机具有可用的语音提供方。该音频将保留在内存中,处于失败状态,直到您轻触“发送到主机”或将其舍弃。Collie 绝不会自动发送它,因为您选择该引擎的目的正是让音频保留在本地。同一会话中引擎崩溃两次将停用 在此手机上,直到您重新加载应用。
手机上的副本被清除时。 浏览器可能会清除该副本以释放空间。此选项仍保留在此手机上,且听写已暂停:语音 显示“Dictation is paused”并提供 恢复,以再次从主机复制模型。麦克风仍会录音,音频片段保留在手机上,处理方式与上述 发送到主机 相同。Collie 不会自动切换到主机。若要使用主机,请选择 在您的主机上。
浏览器。 此手机 需要浏览器为语音 worker 提供独立的安全性策略。已在 Android 上的 Chrome 中测试。WebKit 已在 WebKit 构建版本中测试。iPhone 上的 Safari 尚未在真机上验证。无法运行该功能的浏览器会将 在此手机上 显示为关闭并注明原因,在您的主机上 仍可使用。
如果你使用了旧包装层。 此页面的早期版本展示过包裹原生运行器的 local-cli 包装层(ffmpeg 和 jq)。该配置已弃用,但现有的配置不会受到任何影响并继续工作。若要改用内置引擎,请运行 bin/collie stt whistle --host --yes,或者先运行 collie stt off 然后运行 bin/collie stt whistle --host。你也可以保留该包装层。其模型文件不会被自动复用。使用 --from <path> 传入该文件可跳过下载。
该引擎的安全细节以及允许从 Settings 进行配置的原因,请参阅 安全性 和 ADR 0096。
容器支持取决于具体服务商
手机从不录制 WAV。它在 Chrome、Android 和 Firefox 上录制 WebM 容器的 Opus,在 Safari 和 iOS 上录制 MP4 容器的 AAC,并直接按原样发送这些字节。能转录 WAV 的服务商仍可能对这两种格式返回 400,导致每次听写都因“refused”而失败,而 stt test 看起来却正常。这就是 stt test 发送全部三个音频片段的原因:在配置阶段而非手机端发现拒绝情况。
一个于 2026-09-01 在 OpenRouter 的 POST /v1/audio/transcriptions 上验证的案例:
| 格式 | mistralai/voxtral-small-24b-2507-stt | openai/whisper-large-v3-turbo |
|---|---|---|
| wav | 是 | 是 |
| ogg/opus | 是 | 是 |
| webm/opus | 否,400 | 是 |
| mp4/m4a AAC | 否,400 | 是 |
解决方法在于模型,而非密钥:将同一个 OpenRouter 密钥指向支持全部四种格式的 openai/whisper-large-v3-turbo。
bin/collie stt setup --provider openai-compatible \
--url https://openrouter.ai/api/v1 --model openai/whisper-large-v3-turbo --key <key>被拒绝的转录现在会指明上游状态码及发送时使用的容器格式,因此手机上的错误信息会显示服务商拒绝了哪种格式。(#148,感谢 @drewbitt)
零出站流量:将其指向你自己的引擎
选择 openai-compatible 提供商的原因是:为其提供本地基础 URL,房间内的音频绝不会离开主机。有两个引擎提供与 OpenAI 兼容的转录端点:whisper.cpp 自带的 server,以及 mudler/parakeet.cpp(MIT)。按照各自的说明构建或安装其中一个,在回环地址上运行它,然后将 --url 指向它:
bin/collie stt setup --provider openai-compatible --url http://127.0.0.1:8080/v1这就是全部的集成逻辑:Collie 不关心由哪个引擎响应。
Mistral 的 Voxtral 无需专门支持,遵循此约定的其他任何组件也一样,这就是抽象接口的意义。vLLM 在 /v1/audio/transcriptions 上提供开放权重的 Voxtral 模型,因此本地模型与任何其他引擎使用相同的 --url。托管模型则是发送给 Mistral 自身基地址的相同请求:
bin/collie stt setup --provider openai-compatible \
--url https://api.mistral.ai/v1 --model voxtral-mini-latest --key <key> --lang enVoxtral Mini Transcribe 支持 13 种语言,并接受 Collie 已在发送的相同 ISO-639-1 language 字段。在信任它之前先用 collie stt test 验证:"兼容 OpenAI" 是每个端点自身的声明,该指令正是用于检查此项。
codex 提供方:你所接受的内容
collie stt setup --provider codex 会输出同意声明块并暂停,直到你输入 yes。直白地说:录音会发送到通过 你的 登录授权的 未记录且不受支持的 ChatGPT 端点,因此你的 ChatGPT 账号将承担速率限制和封禁风险,并且它可能在没有任何通知的情况下失效。
Collie 优先使用自身名称请求该端点。仅当该真实身份被拒绝时,它才会回退到 Codex CLI 的请求头,且该回退逻辑会写入配置,以 collie stt status 能够回读的形式保存。Collie 绝不会读取或存储 ~/.codex/auth.json;你已信任的二进制文件仍然是唯一接触它的组件。
你也可以在 Settings 中进行选择。 在具有写入权限的设备上打开 Settings → Voice → Host speech。该页面会显示主机当前使用的配置。对于 ChatGPT subscription,它还会显示记录的身份:honest,或在需要回退时显示 codex-cli。仅当主机上安装了 codex 且已登录 ChatGPT 时,ChatGPT subscription 行才处于开启状态。Collie 会向 codex login status 查询以确认。否则该行会用一句话说明原因,其 设置方法 会标明下一步操作:在主机上安装 Codex,使用 codex login 登录,然后点击 Use ChatGPT subscription。点击该行,弹出的面板会逐字显示相同的许可协议,其上一行注明此更改适用于与该主机配对的每台设备。在点击 我接受 之前,不会向主机发送任何内容。随后主机将运行与 collie stt setup 相同的探测(先验证真实身份),并写入相同的配置。若探测失败,则不会写入任何内容,且面板会说明原因。同一页面上的 关闭 可移除该 provider。终端仍按相同方式工作。
运行自定义命令:local-cli 提供程序
local-cli 每次录音运行一次你已有的转录命令,中间无 HTTP 服务器:
bin/collie stt setup --provider local-cli \
--command /Applications/Muesli.app/Contents/MacOS/muesli-cli --args transcribe
bin/collie stt testCollie 将录音写入私有临时文件并运行 <command> [args…] <file>。该文件的路径始终为最后一个参数。命令的标准输出去除首尾空白后即为转录结果。
| 设置 | 标志 | 环境变量 | 具体含义 |
|---|---|---|---|
command | --command | COLLIE_STT_COMMAND | 绝对路径,或 PATH 中的名称。 |
args | --args | 无 | 文件路径之前的参数。 |
运行 setup 时会查找裸名称并保存完整路径。该服务运行时采用较短的 PATH,因此你 shell 能找到的名称在其中可能无法解析。像 ./whisper-cli 这样的相对路径会被拒绝。
--args 接受以空格分隔的词。没有 shell 会读取它们,因此引号会原样保留。包含空格的参数则需要改用 JSON 形式:
bin/collie stt setup --provider local-cli --command whisper-cli \
--args '["-m", "/srv/my models/ggml-base.bin", "-nt"]'该命令必须满足的条件:
- 必须是当前用户可执行的常规文件。指向常规文件的符号链接亦可,因为 Collie 会跟踪符号链接。
collie stt setup会拒绝其他任何内容,且collie stt status会说明错误原因。 - 以状态码 0 退出,并将转录结果输出到标准输出。其他任何情况均视为听写失败。
- 在 60 秒内完成。超时后 Collie 会使用 SIGKILL 终止该命令及其启动的每个进程。
- 输出到标准输出的内容最多为 256 KiB。一旦输出超过此限制,Collie 会立即将其终止。
- 不残留任何运行中的进程。命令退出时,Collie 会终止由其启动且仍在运行的任何进程。必须保持运行的辅助程序必须启动自己的会话,例如使用
setsid。
在 Windows 上,Collie 会在相同时机终止命令的整个进程树,且在正常退出后会终止该命令启动且仍在运行的任何进程。还剩一种情况:由已退出的辅助程序所启动的进程,其存活时间可能超过该命令。
最多同时有两个听写运行该命令。第三个会收到手机端已知的相同“忙”响应,Collie 不会为其启动任何操作。
空标准输出在手机端视为失败,因为输入框中没有可填入的内容。collie stt test 将其算作成功,因为它的音频片段是静音。
注意。 该命令以 bridge 自身的身份和权限运行,每次听写运行一次。它没有 shell,没有标准输入,也没有 COLLIE_* 环境变量。其标准错误绝不会被读取,手机端也绝不会看到命令行或路径,只能看到命令失败及其退出状态码。临时文件存放在仅当前用户可打开的文件夹中,Collie 会在每次运行后将其删除。如果 bridge 本身在运行中途被终止,下次 bridge 启动时会清理存放已满一小时的此类文件夹。音频接下来发送到何处由命令决定:本地引擎会将其保留在宿主机上。
上述所有内容的推理依据(为何被拒绝两次、发生了什么变化以及接口为何设计成这样)见 ADR 0029。
Web Push(可选)
默认禁用。设置需要三个步骤。发送端库(web-push)在构建期间作为可选依赖项引入:
collie push-keys # 1. generate + write the VAPID keys
collie restart # 2. Collie reads them at start
# 3. on your phone: Settings → Alertspush-keys 命令生成密钥对,并将文件权限模式为 600 的 COLLIE_VAPID_PUBLIC 和 COLLIE_VAPID_PRIVATE 写入活动的 .env,在二进制安装中为 ~/.config/collie/.env,在 Herdr 安装中为 Herdr 插件配置目录中的相应文件。
传入联系 URI 作为参数以设置 RFC 8292 subject 声明:
collie push-keys mailto:you@example.com在由 Herdr 管理的安装中,这两个步骤均以 action 形式提供(herdr plugin action invoke push-keys --plugin herdr.collie 和 restart)。Herdr action 不接受位置参数,因此设置 subject 需要在 shell 中直接运行命令。
密钥处理细节:
除非传入 --force,否则该命令拒绝覆盖现有密钥。更换密钥会使所有当前订阅失效,要求每台设备重新订阅后才能再次接收通知。在现有配置上提供 subject 参数仅更新联系地址,并保留当前密钥。
注意。 在 0.8.0 之前的 Herdr 版本中,操作固定为初始插件安装期间缓存的集合(ADR 0006)。在运行herdr plugin install之前,push-keys和push-test操作不会出现。请改用直接运行bash scripts/collie-ctl.sh push-keys。包装脚本会将命令直接传递给二进制文件。
测试所有已订阅设备的推送路径:
collie push-test # or: push-test "Title" "Body"推送需要一到两秒。如果命令报告推送已禁用,请重启服务以便加载生成的密钥。如果报告没有已订阅的设备,请在手机浏览器中完成步骤 3。
Web Push 需要安全上下文(HTTPS)。这由 tailscale serve(MagicDNS 证书)或终止 TLS 的外部反向代理(变体 C)提供。纯 HTTP 配置(COLLIE_SERVE_MODE=http)缺少安全上下文,浏览器会禁用“设置”中的订阅控件。
当 agent 进入 blocked 或 done 状态时,Collie 会发送通知,并将 agent 消息放入正文中。点击通知会直接在 Web UI 中跳转到该 agent。
Collie 发送哪些警报
共五类,在 Settings → Alerts → Notify when 下各自带有独立开关。
| 警报 | 触发条件 | 默认值 |
|---|---|---|
| 需要输入 | agent 正在等待你的输入 | 开 |
| 已完成 | agent 完成其任务 | 关 |
| 应用更新 | 有更新的 Collie 版本可用 | 开 |
| 机器负载持续偏高 | 机器的 CPU、内存或使用率最高的磁盘持续超出为其设定的规则 | 开 |
| 缓存即将变冷 | 窗格的提示词缓存将在约 5 分钟内过期 | 关 |
当 agent 从运行状态变为闲置状态时会触发 Finished,因此被你中断的 agent 也会算作已完成。
在机器页面设置规则之前,机器负载不会发送任何内容。该开关可一次性关闭所有规则。数值每次攀升并居高不下时都会发送一次警报,点击即可打开该机器的状态视图。参见 机器。
每台设备均以其自身的 语言 显示通知标题,更新后尚未打开过 Collie 的设备则显示为英文。正文保持网桥写入的内容不变。
每个开关都在 bridge 范围内生效。推送会扩散到每个已订阅的设备,因此无需按设备单独设置。
也可以通过窗格自身的设置,为单个窗格开启缓存预警:打开该窗格,点击 ⋮,然后点击窗格设置。这些窗格会列在“设置”中的全局开关下方,各自带有一个“移除”按钮。
这两种状态为叠加关系,而非覆盖关系。当全局开关开启或窗格在列表中时,窗格就会收到预警,因此关闭全局开关不会让手动关注的窗格静音。
受监控的窗格会收到警告:每个保活周期。agent 的下一次请求会推迟截止时间,只有在此之后,同一窗格才能再次发出警告。静音时段同样适用:处于休眠状态的 bridge 不会发送任何内容,在窗口期内结束的休眠仍会发出警告。已经处于冷状态的窗格绝不会收到警告,包括因 /model 切换而在时间尚未耗尽时变冷的窗格。
COLLIE_CACHE_WARN_SECONDS可调整窗口时间,默认 300 秒(configure.md)。
注意。此告警需要读取提示词缓存,因此它仅覆盖显示缓存倒计时的窗格,不包含其他窗格:harness 必须保留 Collie 可读取的副本,且 agent 必须已执行过至少一轮。窗格实际发出预警的时间窗口为配置的秒数,或该窗格自身缓存寿命的一半,以较短者为准。Claude 的 1 小时缓存会保留完整的 300 秒窗口。Codex、OpenCode、pi 和 omp 的 5 分钟缓存则会在变冷前约 2.5 分钟发出预警。
由于主屏幕重新安装和 service-worker 重置会创建新端点且不一定会返回 HTTP 410,失效订阅可能会随时间累积。当设备重新注册时,Collie 会更新记录。你可以直接查看和删除已存储的端点:
# one line per device: service, since, user agent, endpoint tail
bin/collie push list
bin/collie push forget <substring> # or: push forget --all来自 durable agent 的推送
durable agent 的问题卡片可以向手机发送推送通知,Collie 会限制单个 durable agent 的推送次数上限。
推送内容显示 "Permission needed in" 以及该窗格的名称。它绝不会携带 durable agent 自己针对该问题设置的标题。durable agent 可以自定义文字:其标题(最多 60 个字符)会在冒号后紧随窗格名称显示,其单行描述(最多 120 个字符)作为正文。自定义文字仅改变推送显示的内容,绝不会影响推送频率。
| 上限规则 | 限制指标 | 超出后行为 |
|---|---|---|
| 单个窗格 | 每分钟 3 次推送 | 问题会显示在手机上,但不发送推送 |
| 单台机器上的单个 durable agent | 每分钟 10 次推送 | 同上 |
| 单台机器上的单个 durable agent | 每小时 30 次推送 | 发送一条汇总推送,然后该 durable agent 在一小时内不再发送推送 |
汇总内容显示 "A durable agent on {host} is raising many asks",其中 host 为机器名。在 crew 中它会显示 member 的名称。Needs input 开关和静音功能也会拦截该汇总。上限绝不会隐藏问题:每个未完结的问题都会保留在手机上。
Collie 对每个问题只推送一次。它按机器、durable agent 和工具调用记录每个问题,因此重启后再次提出相同问题的 durable agent 会在手机上显示该问题,但不会发送第二次推送。问题关闭一小时后记录会被清除。该记录保存在状态目录中的 durable-asks.json。在 crew 中,由 lead 执行这些规则并保留该文件,member 不会为自己的问题发送推送(ADR 0100)。