第11章:Bridge 桥接层
本章介绍 Claude Code 的 Bridge 桥接层实现,包括远程控制(Remote Control)功能的架构设计和通信机制。
11.1 Bridge 目录结构
Bridge 模块位于 src/bridge/ 目录,包含约 30 个 TypeScript 文件:
src/bridge/
├── types.ts # 类型定义和常量
├── bridgeApi.ts # Bridge API 客户端
├── bridgeConfig.ts # Bridge 配置解析
├── bridgeMain.ts # Bridge 主入口
├── bridgeMessaging.ts # 消息处理
├── createSession.ts # Session 创建
├── sessionRunner.ts # Session 运行器
├── replBridge.ts # REPL Bridge 实现
├── replBridgeTransport.ts # 传输层抽象
├── jwtUtils.ts # JWT 工具和 Token 刷新
├── bridgeEnabled.ts # Bridge 启用检测
├── bridgeDebug.ts # 调试工具
├── bridgeStatusUtil.ts # 状态管理
├── bridgeUI.ts # UI 层集成
├── initReplBridge.ts # Bridge 初始化
├── inboundMessages.ts # 入站消息处理
├── inboundAttachments.ts # 入站附件处理
├── flushGate.ts # 输出缓冲控制
├── capacityWake.ts # 能力唤醒
├── pollConfig.ts # 配置轮询
├── sessionIdCompat.ts # Session ID 兼容性
├── trustedDevice.ts # 可信设备管理
├── workSecret.ts # 工作密钥解析
└── ...
11.2 核心类型定义
11.2.1 Session 相关类型
// Session 超时常量(24小时)
export const DEFAULT_SESSION_TIMEOUT_MS = 24 * 60 * 60 * 1000
// Session 完成状态
export type SessionDoneStatus = 'completed' | 'failed' | 'interrupted'
// Session 活动类型
export type SessionActivityType = 'tool_start' | 'text' | 'result' | 'error'
// Session 活动记录
export type SessionActivity = {
type: SessionActivityType
summary: string // 如 "Editing src/foo.ts"
timestamp: number
}
11.2.2 工作密钥类型
// 工作密钥(Session 启动参数)
export type WorkSecret = {
version: number
session_ingress_token: string // Session 入口 Token
api_base_url: string // API 基础 URL
sources: Array<{
type: string
git_info?: { type: string; repo: string; ref?: string; token?: string }
}>
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 兼容标识
}
11.2.3 启动模式
// Bridge Session 工作目录选择模式
export type SpawnMode =
| 'single-session' // 单 Session,Session 结束后 Bridge 退出
| 'worktree' // 持久服务,每个 Session 独立 git worktree
| 'same-dir' // 持久服务,所有 Session 共享 cwd
11.3 Session 创建流程
Session 创建通过 createBridgeSession 函数实现,用于 claude remote-control 命令和 /remote-control 斜杠命令:
sequenceDiagram
participant User as 用户
participant Bridge as Bridge
participant OAuth as OAuth 服务
participant API as claude.ai API
User->>Bridge: 发起 remote-control
Bridge->>OAuth: 获取 Access Token
OAuth-->>Bridge: accessToken
Bridge->>OAuth: 获取 Organization UUID
OAuth-->>Bridge: orgUUID
Bridge->>API: POST /v1/sessions
API-->>Bridge: sessionId
Bridge->>Bridge: 启动 sessionRunner
Bridge-->>User: 返回 sessionId
11.3.1 createBridgeSession 函数
export async function createBridgeSession({
environmentId,
title,
events,
gitRepoUrl,
branch,
signal,
baseUrl,
getAccessToken,
permissionMode,
}): Promise<string | null> {
// 1. 获取 OAuth Token
const accessToken = getAccessToken?.() ?? getClaudeAIOAuthTokens()?.accessToken
if (!accessToken) return null
// 2. 获取 Organization UUID
const orgUUID = await getOrganizationUUID()
if (!orgUUID) return null
// 3. 构建 Git 源信息
let gitSource = null
let gitOutcome = null
if (gitRepoUrl) {
const parsed = parseGitRemote(gitRepoUrl)
if (parsed) {
gitSource = {
type: 'git_repository',
url: `https://${parsed.host}/${parsed.owner}/${parsed.name}`,
revision: branch,
}
gitOutcome = {
type: 'git_repository',
git_info: {
type: 'github',
repo: `${parsed.owner}/${parsed.name}`,
branches: [`claude/${branch || 'task'}`],
},
}
}
}
// 4. 发送创建请求
const response = await axios.post(`${baseUrl}/v1/sessions`, {
environment_id: environmentId,
title,
events,
source: gitSource,
expected_outcome: gitOutcome,
permission_mode: permissionMode,
})
return response.data.id
}
11.4 JWT 认证与 Token 刷新
11.4.1 JWT 解码
jwtUtils.ts 提供了 JWT Token 解码功能,无需验证签名:
// 解码 JWT payload(不验证签名)
export function decodeJwtPayload(token: string): unknown | null {
// 去除 sk-ant-si- 前缀
const jwt = token.startsWith('sk-ant-si-')
? token.slice('sk-ant-si-'.length)
: token
const parts = jwt.split('.')
if (parts.length !== 3 || !parts[1]) return null
return jsonParse(Buffer.from(parts[1], 'base64url').toString('utf8'))
}
// 解码 JWT expiry
export function decodeJwtExpiry(token: string): number | null {
const payload = decodeJwtPayload(token)
if (payload && typeof payload === 'object' && 'exp' in payload) {
return payload.exp
}
return null
}
11.4.2 Token 刷新调度器
flowchart TD
A[schedule] --> B[计算刷新时间]
B --> C[设置定时器]
C --> D{Token 即将过期?}
D -->|Yes| E[调用 onRefresh]
E --> F[获取新 Token]
F --> G{成功?}
G -->|Yes| H[重新 schedule]
G -->|No| I[失败计数 +1]
I --> J{超过 MAX_FAILURES?}
J -->|Yes| K[停止刷新]
J -->|No| L[延迟重试]
// 刷新缓冲时间:提前 5 分钟刷新
const TOKEN_REFRESH_BUFFER_MS = 5 * 60 * 1000
// 备用刷新间隔:30 分钟
const FALLBACK_REFRESH_INTERVAL_MS = 30 * 60 * 1000
// 最大连续失败次数
const MAX_REFRESH_FAILURES = 3
export function createTokenRefreshScheduler({
getAccessToken,
onRefresh,
label,
refreshBufferMs,
}): {
schedule: (sessionId: string, token: string) => void
scheduleFromExpiresIn: (sessionId: string, expiresInSeconds: number) => void
cancel: (sessionId: string) => void
cancelAll: () => void
} {
const timers = new Map<string, ReturnType<typeof setTimeout>>()
const failureCounts = new Map<string, number>()
const generations = new Map<string, number>()
// 调度刷新
function schedule(sessionId: string, token: string) {
const expiry = decodeJwtExpiry(token)
if (!expiry) {
// 无法解析过期时间,使用备用间隔
scheduleFromExpiresIn(sessionId, FALLBACK_REFRESH_INTERVAL_MS / 1000)
return
}
const nowMs = Date.now()
const expiryMs = expiry * 1000
const delayMs = expiryMs - nowMs - refreshBufferMs
if (delayMs <= 0) {
// 已过期或即将过期,立即刷新
doRefresh(sessionId)
} else {
setTimer(sessionId, delayMs)
}
}
return { schedule, scheduleFromExpiresIn, cancel, cancelAll }
}
11.5 传输层架构
Bridge 支持两种传输协议版本:
11.5.1 V1 协议(WebSocket)
graph LR
A[claude.ai] --> B[WebSocket]
B --> C[replBridgeTransport]
C --> D[Session Runner]
D --> E[Claude Code REPL]
11.5.2 V2 协议(CCR)
graph LR
A[claude.ai] --> B[CCR API]
B --> C[codeSessionApi]
C --> D[Session Runner]
D --> E[Claude Code REPL]
11.6 消息协议
11.6.1 入站消息类型
inboundMessages.ts 处理来自远程客户端的消息:
// 消息类型定义
type InboundMessage =
| { type: 'text'; content: string }
| { type: 'attachment'; data: Attachment }
| { type: 'permission_response'; decision: 'allow' | 'deny' }
| { type: 'interrupt' }
| { type: 'ping' }
11.6.2 消息处理流程
sequenceDiagram
participant Client as 远程客户端
participant Transport as 传输层
participant Messaging as bridgeMessaging
participant Runner as sessionRunner
participant REPL as Claude Code
Client->>Transport: 发送消息
Transport->>Messaging: 解析消息
Messaging->>Messaging: 验证权限
Messaging->>Runner: 分发消息
Runner->>REPL: 注入到对话
REPL-->>Runner: 处理结果
Runner-->>Messaging: 输出事件
Messaging-->>Transport: 编码响应
Transport-->>Client: 发送响应
11.7 认证配置参数
// Bridge 配置
export type BridgeConfig = {
dir: string // 工作目录
machineName: string // 机器名称
branch: string // Git 分支
gitRepoUrl: string | null
maxSessions: number // 最大 Session 数
spawnMode: SpawnMode // 启动模式
verbose: boolean // 详细日志
sandbox: boolean // 沙箱模式
bridgeId: string // Bridge 实例 UUID
workerType: string // 工作类型
environmentId: string // 环境注册 ID
}
本章小结
Bridge 模块是 Claude Code 远程控制功能的核心实现,主要特点:
- 双协议支持:V1 WebSocket 和 V2 CCR 兼容
- JWT Token 管理:自动刷新机制确保长连接稳定
- 多种启动模式:single-session、worktree、same-dir
- 完整消息协议:支持文本、附件、权限响应等多种消息类型
下一章将介绍 Services 服务层的详细设计。