第15章 · Bridge系统
第15章 · Bridge系统
15.1 三代架构演进
Bridge是Claude Code的远程控制骨架,负责让CLI实例能被外部系统(桌面应用、Web界面、CI/CD流水线、Agent SDK)远程操控。从源码中可以清晰地看到Bridge经历了三代架构演进:
第一代:HTTP轮询 最原始的远程控制方式——客户端定期向服务端发起HTTP请求,检查是否有新的工作指令。简单可靠但延迟高。
第二代:WebSocket REPL Bridge
bridge/replBridge.ts(100KB)实现了WebSocket双向通信,支持实时消息传递和控制请求。这是当前的主力方案。
第三代:Direct Connect
server/directConnectManager.ts实现了直接的WebSocket连接,使用NDJSON(换行分隔的JSON)协议。适用于本地客户端直连场景(如桌面应用)。
15.2 bridgeMain.ts核心流程
bridge/bridgeMain.ts(115KB)是Bridge的神经中枢,实现了完整的远程控制循环。
Bridge Loop入口:
export async function runBridgeLoop(
config: BridgeConfig,
environmentId: string,
environmentSecret: string,
api: BridgeApiClient,
spawner: SessionSpawner,
logger: BridgeLogger,
signal: AbortSignal,
backoffConfig: BackoffConfig = DEFAULT_BACKOFF,
initialSessionId?: string,
getAccessToken?: () => string | undefined | Promise<string | undefined>,
): Promise<void>退避配置反映了对网络不稳定性的成熟处理:
DEFAULT_BACKOFF = {
connInitialMs: 2_000, // 初始连接重试延迟
connCapMs: 120_000, // 最大连接退避(2分钟)
connGiveUpMs: 600_000, // 连接放弃阈值(10分钟)
generalInitialMs: 500, // 一般重试初始延迟
generalCapMs: 30_000, // 一般退避上限
generalGiveUpMs: 600_000, // 一般放弃阈值
}会话追踪使用了丰富的数据结构:
const activeSessions = new Map<string, SessionHandle>()
const sessionStartTimes = new Map<string, number>()
const sessionWorkIds = new Map<string, string>()
const sessionCompatIds = new Map<string, string>()
const sessionIngressTokens = new Map<string, string>()
const sessionTimers = new Map<string, ReturnType<typeof setTimeout>>()
const completedWorkIds = new Set<string>()
const sessionWorktrees = new Map<string, WorktreeInfo>()
const timedOutSessions = new Set<string>()
const titledSessions = new Set<string>()这些Map的数量(10+)说明Bridge需要管理每个会话的多个维度:时间追踪、工作ID映射、JWT令牌、超时状态、Worktree信息等。
Spawn模式:
export type SpawnMode = 'single-session' | 'worktree' | 'same-dir'single-session:在当前目录启动单个会话,结束后Bridge也关闭worktree:持久化服务器,每个会话使用隔离的Git worktreesame-dir:持久化服务器,所有会话共享工作目录(可能产生冲突)
多会话Spawn通过GrowthBook特性门tengu_ccr_bridge_multi_session控制,需要--spawn / --capacity / --create-session-in-dir参数。
容量管理:capacityWake机制允许在容量释放时提前唤醒轮询循环,避免不必要的等待。
15.3 REPL Bridge协议
bridge/replBridge.ts实现了Bridge的WebSocket层协议。
核心参数类型:
export type BridgeCoreParams = {
dir: string // 工作目录
machineName: string // 主机名
branch: string // Git分支
gitRepoUrl: string | null // Git远程URL
title: string // 会话标题
baseUrl: string // API基础URL
sessionIngressUrl: string // WebSocket URL
workerType: string // Worker类型
getAccessToken: () => string | undefined
createSession: (opts) => Promise<string | null>
archiveSession: (sessionId: string) => Promise<void>
onAuth401?: (staleToken: string) => Promise<boolean>
getPollIntervalConfig?: () => PollIntervalConfig
initialHistoryCap?: number // 默认200(来自标志)
// ... 更多回调
}Bridge状态机:
export type BridgeState = 'ready' | 'connected' | 'reconnecting' | 'failed'Handle接口——Bridge会话的远程控制面板:
export type ReplBridgeHandle = {
bridgeSessionId: string
environmentId: string
sessionIngressUrl: string
writeMessages(messages: Message[]): void
writeSdkMessages(messages: SDKMessage[]): void
sendControlRequest(request: SDKControlRequest): void
sendControlResponse(response: SDKControlResponse): void
sendControlCancelRequest(requestId: string): void
sendResult(): void
teardown(): Promise<void>
}15.4 JWT认证与Work Secret
Work Secret是Bridge会话的认证凭证包:
export type WorkSecret = {
version: number
session_ingress_token: string // WebSocket认证JWT
api_base_url: string
sources: Array<{ type: string; git_info?: GitInfo }>
auth: Array<{ type: string; token: string }>
claude_code_args?: Record<string, string> | null
mcp_config?: unknown | null
environment_variables?: Record<string, string> | null
use_code_sessions?: boolean // CCR v2选择器
}Work Secret不仅包含认证令牌,还包含了完整的会话配置——MCP配置、环境变量、代码参数等。这使得Bridge能在收到工作指令的同时获得执行该工作所需的全部上下文。
JWT的自动刷新策略为:在令牌过期前5分钟开始刷新,最多重试3次。这种提前刷新避免了令牌过期导致的连接中断。
15.5 Bridge的容错设计
Bridge的容错设计体现在多个层面:
连接级别:指数退避重连(2s → 4s → 8s → ... → 120s)
会话级别:超时看门狗(timedOutSessions追踪被杀死的会话)
工作级别:stopWorkWithRetry使用递增延迟(1s → 2s → 4s)
系统级别:SIGTERM → 30秒优雅关闭 → SIGKILL
bridge-kick命令是一个内部调试工具,允许开发者注入各种故障场景来测试恢复路径:
/bridge-kick close 1002 — 触发WebSocket关闭
/bridge-kick poll 404 — 下次轮询返回404
/bridge-kick register fail — 下次注册瞬态失败
/bridge-kick reconnect — 直接调用doReconnect
/bridge-kick status — 打印Bridge状态