Bridge 如何“偷听”AI 但不偷走隐私:VibeStick 的观察器、协议与安全边界
摘要:Codex 和 Claude 并没有为这块小屏幕提供统一状态 API。VibeStick Bridge 如何从本地进程、JSONL 会话和限额事件中构造可靠状态?本文分析 provider 抽象、状态推断、HTTP 协议与安全设计。
先纠正标题:Bridge 没有窃听提示词,也不需要把聊天内容上传到某个神秘中转站。它做的是“观察”本机 Agent 留下的运行痕迹,然后把少量状态翻译成 StickS3 看得懂的 JSON。
这件事听起来像侦探工作,实际更像看办公室门口的灯:进程在不在、最近有没有活动、最后一条事件是什么、配额数据是否过期。看得到有人加班,不代表要趴门缝里听会议内容。
一、统一 provider 层:先把方言翻成普通话
bridge/src/vibe_stick/providers/base.py 定义了 ProviderObservation。Codex 和 Claude 的观察器最终都要交出同一份答卷:
@dataclass
class ProviderObservation:
provider_id: str
display_name: str
online: bool
status: AgentStatus
project: str
quota_5h_remaining: int | None
quota_7d_remaining: int | None
quota_updated_at: str
quota_stale: bool
alert_type: str
alert_message: str
alert_event_id: str
latest_event_timestamp: datetime | None = None
Bridge 的 BridgeStateStore 同时刷新两个 provider,再根据 VIBE_STICK_PROVIDER=auto|codex|claude 选择活动对象。自动模式还保留上一次选择,避免两个 Agent 状态接近时屏幕左右横跳,像一个同时追两场球赛但遥控器接触不良的人。
下面是 Bridge 从两个 Provider 获取观察结果,经过状态推断和选择逻辑,最终生成统一状态输出的完整流程:
所以屏幕展示的是本地会话中最近一次可见的限额快照,不是 OpenAI 官方 quota API。快照会落盘;新值暂时取不到时,旧值继续展示并标为 stale。工程上,带时间戳的旧数据通常比突然“失忆”(无数据)更有用,前提是老老实实告诉用户它旧了。
三、Claude:tool_use 不一定等于等待审批
Claude 观察器同样读取项目 JSONL,但状态推断更细。它记录最新普通事件、错误、完成事件、tool use,以及每个 session 的 permissionMode。
关键判断是:只有 tool use 是最新事件、处于时间窗口内,并且该 session 为 default 权限模式时,才认为 APPROVAL。在 acceptEdits、auto 或 bypass 模式下,工具调用会自动继续,不能见到 tool_use 三个字就替用户拉响审批警报。
Claude 5H/7D 用量是 opt-in。启用后 Bridge 会尝试使用本机 Claude Code 登录凭据访问非公开 endpoint,并设置最短轮询间隔。失败后保留旧快照并标 stale;从未成功时显示 --%。因为接口未公开,这项能力随上游变化而失效的风险必须写进产品说明,而不是藏进脚注的脚注。
四、状态存储:线程安全比“反正请求不多”可靠
Bridge 基于标准库 ThreadingHTTPServer。多个请求可能同时触发状态刷新、录音和配额更新,因此 BridgeStateStore 使用 threading.RLock 保护内存状态与落盘。
主要接口包括:
| 方法 | 路径 | 用途 |
|---|---|---|
| GET | /state |
获取 provider、quota、alert 与 Bridge 元数据 |
| GET | /health |
获取版本、Python 路径和 QR 支持状态 |
| GET | /setup |
本机管理页,仅 loopback 可访问 |
| POST | /event |
按键事件和手工状态 |
| POST | /quota/refresh |
强制刷新活动 provider 配额 |
| POST | /recording/start |
创建录音 session |
| POST | /recording/audio |
上传 PCM 二进制 |
| POST | /recording/stop |
转写、粘贴或重试 |
Bridge 在 /state 响应中附加名称、版本等元数据,日志也记录固件名称、版本和 transport header。这为未来的协议兼容检查打了基础,虽然当前还没有完整的版本协商机制。
五、安全:Token 是门锁,不是防空洞
当 Bridge 绑定 0.0.0.0 等非 loopback 地址时,启动逻辑会拒绝空 Token 和常见占位值。设备通过 X-Vibe-Stick-Token 认证,服务端使用常量时间比较。UDP 发现请求也必须带相同 Token,否则 Bridge 保持沉默。
其他防线包括:
- 管理页只允许 loopback 客户端;
- 录音请求有默认 2 MB 大小限制;
/state、录音和事件接口都在受保护路径集合中;- 管理页响应禁用缓存;
- HTTP API 不返回 ASR key、agent token 或原始 Claude usage 响应。
但局域网音频仍使用明文 HTTP,共享 Token 也还没有设备级轮换和撤销。当前方案是在受信任 LAN 上为原型提供基础保护,不等价于端到端加密。未来需要安全配对、单设备凭据、NVS encryption,必要时再评估 TLS 或应用层加密。
六、这个观察器架构的脆弱点
本地观察是一种聪明但现实的折中,也有三个天然风险。
第一,上游 JSONL schema 可能变化。解析必须对缺字段、坏行和新事件类型保持宽容,并用 fixture 测试固定已知样本。
第二,状态是推断而非真相。四分钟活动窗口只是经验值;长时间运行的工具可能让 Agent 实际在忙但日志暂时安静。
第三,轮询成本会随会话增多上升。当前通过限制文件数和 tail bytes 控制成本;更大规模时可引入文件游标、增量索引或事件订阅。
好架构不是假装这些问题不存在,而是把不确定性关进 adapter,让设备协议保持稳定。上游方言变了,改观察器;小屏幕不必跟着重刷人生观。
下一篇进入跨平台现场:VibeStick 如何从 macOS 走向 Windows,以及为什么“能启动”离“能交付”中间还隔着防火墙、安装器和一只托盘图标。
本文分析的是本地兼容与实验性观察机制,不代表 OpenAI 或 Anthropic 提供、认可上述状态与 quota API。
葡萄城是专业的软件开发技术和低代码平台提供商,聚焦软件开发技术,以“赋能开发者”为使命,致力于通过表格控件、低代码和BI等各类软件开发工具和服务,一站式满足开发者需求,帮助企业提升开发效率并创新开发模式。
更多推荐



所有评论(0)