Skip to content

Latest commit

 

History

History
223 lines (154 loc) · 6.27 KB

File metadata and controls

223 lines (154 loc) · 6.27 KB

Bridge — 远程遥控终端

源码位置:src/bridge/(33 个文件) 编译开关:feature('BRIDGE_MODE')feature('DAEMON') 远程开关:GrowthBook tengu_ccr_bridge

从 claude.ai 或手机直接操控本地 CLI。


核心概念

Bridge(Remote Control)让用户从 claude.ai 网页端远程操控运行在本地终端的 Claude Code:

  • 网页输入 prompt → 传送到本地 CLI 执行
  • CLI 输出实时回传到网页
  • 支持远程权限审批
  • 支持中断、切换模型、设置思考 token 上限

两种运行模式

独立模式(claude remote-control

src/bridge/bridgeMain.ts 中实现,作为独立的长运行服务器:

注册环境 → 轮询工作 → 生成子进程处理会话

支持 3 种 session 分发模式(SpawnMode):

模式 说明
single-session 一个 session,结束后 bridge 关闭
worktree 持久服务器,每个 session 获得隔离的 git worktree
same-dir 持久服务器,所有 session 共享 cwd

REPL 内嵌模式(/remote-control

src/bridge/initReplBridge.ts + src/bridge/replBridge.ts 中实现:

  • 在交互式 REPL 会话中启动
  • 将当前对话镜像到 claude.ai
  • 支持双向:本地打字和网页打字都能驱动同一个会话

启用条件

src/bridge/bridgeEnabled.ts 定义了严格的检查链:

isBridgeEnabled() =
  feature('BRIDGE_MODE')             ← 编译时 flag
  && isClaudeAISubscriber()          ← 必须是付费订阅用户
  && GrowthBook('tengu_ccr_bridge')  ← 服务端 feature flag

不满足时的诊断信息:

  • 非订阅用户 → 提示需要订阅
  • 缺少 user:profile OAuth scope → 提示需要重新登录
  • 无法确定组织 UUID → 提示刷新账户信息
  • GrowthBook 未通过 → 提示功能未启用

两代传输协议

v1(环境层方案)

完整的环境生命周期:

注册环境 → 轮询工作 → 确认 → 心跳 → 注销
  • 传输层:HybridTransport(WebSocket 读 + HTTP POST 写)
  • API 路径:/v1/environments/bridge 注册,/v1/environments/{id}/work/poll 轮询

v2(无环境层方案)

跳过整个 Environments API,直接连接 session-ingress:

1. POST /v1/code/sessions            ← 创建 session
2. POST /v1/code/sessions/{id}/bridge ← 获取 worker_jwt + epoch
3. SSE (读) + CCRClient (写)          ← 建立双向通道
4. JWT 到期前 5 分钟主动刷新          ← 保持连接
  • 传输层:SSETransport(读)+ CCRClient(写到 CCR v2 /worker/* 端点)
  • 由 GrowthBook tengu_bridge_repl_v2 门控

消息处理

src/bridge/bridgeMessaging.ts 实现消息路由:

入站消息

类型 说明
control_response 权限回复
control_request 服务端控制请求
SDKMessage 标准消息(只转发 user 类型)

去重机制

  • 回声去重BoundedUUIDSet(环形缓冲区,默认 2000 条)过滤自己发出的消息
  • 重投递去重recentInboundUUIDs 过滤重复入站提示

服务端控制请求

请求 说明
initialize 返回能力声明
set_model 切换模型
set_max_thinking_tokens 设置思考 token 上限
set_permission_mode 设置权限模式
interrupt 中断当前操作

必须在 10-14 秒内响应,否则服务端关闭连接


独立 Bridge 服务器主循环

src/bridge/bridgeMain.tsrunBridgeLoop() 函数:

1. 注册环境 → POST /v1/environments/bridge
   (传递机器名、目录、分支、Git URL、最大 session 数)

2. 轮询工作 → GET /v1/environments/{id}/work/poll
   (指数退避)

3. 接收工作 → 解码 WorkSecret(base64url JSON)
   (提取 session_ingress_token 和 api_base_url)

4. 生成子进程 → claude --print --sdk-url ... --session-id ...
   (NDJSON stdin/stdout 通信)

5. 活动监控 → 解析 stdout NDJSON
   (提取工具使用和结果)

6. 心跳 → POST .../heartbeat

7. 清理 → stopWork + deregisterEnvironment

安全机制

机制 说明
OAuth 令牌 主身份凭证,从 keychain 读取,支持自动刷新
Worker JWT 每 session 的短期令牌(几小时过期)
Trusted Device Token 设备信任令牌
401 恢复 检测 401 → OAuth 刷新 → 重获凭证 → 重建传输层
主动刷新 JWT 到期前 5 分钟调度刷新

崩溃恢复

src/bridge/bridgePointer.ts 实现崩溃恢复指针:

  • 路径:{projectsDir}/{sanitized-cwd}/bridge-pointer.json
  • 内容:{ sessionId, environmentId, source }
  • 生命周期:session 创建后写入 → 运行中定期刷新 mtime → 干净退出时清除
  • TTL:4 小时
  • 下次启动检测到指针文件,提供 --session-id 恢复选项
  • 支持 git worktree 兄弟目录扫描

状态机

ready → connected → [reconnecting →] connected
                  → failed
状态 说明
ready 传输层创建成功
connected 连接建立 + 历史消息 flush 完成
reconnecting JWT 过期恢复中
failed 致命错误

CCR Mirror 模式

一个特殊的只写模式:

  • 只转发事件到远端,不接收入站提示
  • 本地 session 在 claude.ai 可见但不可被远程控制
  • CCR_MIRROR 编译 flag + tengu_ccr_mirror GrowthBook flag 门控

关键源码文件

文件 职责
src/bridge/bridgeMain.ts 独立 bridge 服务器主循环
src/bridge/bridgeEnabled.ts 功能门控检查
src/bridge/bridgeConfig.ts OAuth 令牌和 URL 解析
src/bridge/bridgeApi.ts REST API 客户端
src/bridge/replBridge.ts REPL 内嵌桥接核心
src/bridge/replBridgeTransport.ts 传输层抽象(v1/v2)
src/bridge/bridgeMessaging.ts 消息解析、路由、去重
src/bridge/initReplBridge.ts REPL 初始化包装器
src/bridge/sessionRunner.ts 子进程 session 生成器
src/bridge/bridgePointer.ts 崩溃恢复指针
src/bridge/workSecret.ts 工作密钥解码
src/bridge/jwtUtils.ts JWT 刷新调度
src/bridge/trustedDevice.ts 设备信任令牌