第12章:Services 服务层
本章介绍 Claude Code 的 Services 服务层设计,包括 API 客户端、MCP 协议实现、OAuth 认证等核心服务。
12.1 Services 目录结构
服务层位于 src/services/ 目录,包含多个子模块:
src/services/
├── api/ # API 客户端
│ ├── client.ts # Anthropic API 客户端
│ ├── claude.ts # Claude API 封装
│ ├── errors.ts # 错误处理
│ ├── errorUtils.ts # 错误工具
│ ├── withRetry.ts # 重试机制
│ ├── usage.ts # 使用量追踪
│ └── filesApi.ts # Files API
│
├── mcp/ # MCP 协议实现
│ ├── client.ts # MCP 客户端
│ ├── config.ts # MCP 配置解析
│ ├── auth.ts # MCP OAuth
│ ├── types.ts # MCP 类型定义
│ ├── utils.ts # MCP 工具函数
│ └ normalization.ts # 数据规范化
│
├── oauth/ # OAuth 认证
│ ├── client.ts # OAuth 客户端
│ └ auth-code-listener.ts # Auth Code 监听
│
├── analytics/ # 分析服务
│ ├── index.ts # 分析入口
│ ├── growthbook.ts # GrowthBook 集成
│ ├── sink.ts # 数据收集
│ └ datadog.ts # DataDog 集成
│
├── compact/ # 上下文压缩
│ ├── compact.ts # 压缩实现
│ ├── autoCompact.ts # 自动压缩
│ └ microCompact.ts # 微压缩
│
├── lsp/ # LSP 服务
│ ├── LSPClient.ts # LSP 客户端
│ ├── LSPServerManager.ts # LSP 服务器管理
│ └ config.ts # LSP 配置
│
├── voice/ # 语音服务
│ ├── voice.ts # 语音处理
│ ├── voiceStreamSTT.ts # 语音转文字
│
└── SessionMemory/ # 会话记忆
├── sessionMemory.ts # 记忆实现
└ prompts.ts # 记忆提示词
12.2 API 客户端配置
12.2.1 多云服务商支持
Claude Code 支持多种 API 服务商:
graph TD
A[API Client] --> B{Provider Detection}
B --> C[Anthropic Direct]
B --> D[AWS Bedrock]
B --> D2[Azure Foundry]
B --> E[Google Vertex AI]
C --> F[ANTHROPIC_API_KEY]
D --> G[AWS Credentials]
D2 --> H[ANTHROPIC_FOUNDRY_API_KEY]
E --> I[GCP Credentials]
12.2.2 环境变量配置
/**
* 各服务商的环境变量配置:
*
* Direct API:
* - ANTHROPIC_API_KEY: 直接 API 访问密钥
*
* AWS Bedrock:
* - AWS credentials: 通过 aws-sdk 默认配置
* - AWS_REGION / AWS_DEFAULT_REGION: 区域设置(默认 us-east-1)
*
* Azure Foundry:
* - ANTHROPIC_FOUNDRY_RESOURCE: Azure 资源名称
* - ANTHROPIC_FOUNDRY_API_KEY: Microsoft Foundry API Key
* - 或使用 Azure AD DefaultAzureCredential
*
* Vertex AI:
* - ANTHROPIC_VERTEX_PROJECT_ID: GCP 项目 ID
* - CLOUD_ML_REGION: GCP 区域
* - 标准 GCP credentials 配置
*/
12.2.3 客户端创建逻辑
function createAnthropicClient(): Anthropic {
const provider = getAPIProvider()
switch (provider) {
case 'anthropic':
return new Anthropic({
apiKey: getAnthropicApiKey(),
baseURL: process.env.ANTHROPIC_BASE_URL,
})
case 'bedrock':
return createBedrockClient()
case 'foundry':
return createFoundryClient()
case 'vertex':
return createVertexClient()
}
}
12.3 错误处理机制
12.3.1 错误类型定义
Claude Code 使用 Anthropic SDK 提供的错误类型:
// 从 SDK 导入的错误类型
import {
APIConnectionError, // 连接错误
APIConnectionTimeoutError, // 连接超时
APIError, // 通用 API 错误
APIUserAbortError, // 用户中止
} from '@anthropic-ai/sdk'
// 错误消息前缀
export const API_ERROR_MESSAGE_PREFIX = 'API Error'
export const PROMPT_TOO_LONG_ERROR_MESSAGE = 'Prompt is too long'
12.3.2 重试机制
withRetry.ts 实现智能重试策略,使用 AsyncGenerator 模式:
flowchart TD
A[API Call] --> B{Success?}
B -->|Yes| C[Yield Result]
B -->|No| D{529 Error?}
D -->|Yes| E{Foreground Source?}
E -->|Yes| F[Retry with Backoff]
E -->|No| G[Bail Out]
D -->|No| H{Other Retryable?}
H -->|Yes| I[Retry]
H -->|No| G
F --> A
I --> A
// 重试配置常量
const DEFAULT_MAX_RETRIES = 10
const BASE_DELAY_MS = 500
// 前台查询源(用户正在等待结果,会重试 529)
const FOREGROUND_529_RETRY_SOURCES = new Set([
'repl_main_thread',
'sdk',
'agent:custom',
'compact',
// ... 更多前台源
])
// AsyncGenerator 模式支持流式错误消息
export async function* withRetry<T>(
getClient: () => Promise<Anthropic>,
operation: (client, attempt, context) => Promise<T>,
options: RetryOptions,
): AsyncGenerator<SystemAPIErrorMessage, T>
12.4 MCP 协议实现
12.4.1 MCP 配置解析
mcp/config.ts 解析 MCP 服务器配置:
// MCP 服务器配置格式
export type McpServerConfig = {
command?: string // Stdio 启动命令
args?: string[] // 命令参数
url?: string // HTTP/SSE URL
transport?: 'stdio' | 'sse' | 'http'
env?: Record<string, string>
capabilities?: {
tools?: boolean
resources?: boolean
prompts?: boolean
}
}
12.4.2 MCP 客户端初始化
sequenceDiagram
participant Claude as Claude Code
participant Client as MCP Client
participant Server as MCP Server
Claude->>Client: createMcpClient(config)
Client->>Server: connect (stdio/sse/http)
Server-->>Client: connected
Client->>Server: initialize
Server-->>Client: capabilities
Client->>Server: listTools
Server-->>Client: tools list
Client->>Claude: register tools
export async function initializeMcpClient(
config: McpServerConfig
): Promise<Client> {
const client = new Client(
{ name: 'claude-code', version: '1.0.0' },
{ capabilities: { tools: {}, resources: {}, prompts: {} } }
)
// 创建传输层
let transport: Transport
if (config.transport === 'stdio') {
transport = new StdioClientTransport({
command: config.command!,
args: config.args ?? [],
env: config.env,
})
} else if (config.transport === 'sse') {
transport = new SSEClientTransport(new URL(config.url!))
} else {
transport = new StreamableHTTPClientTransport(new URL(config.url!))
}
await client.connect(transport)
return client
}
12.4.3 MCP Tool 调用
export async function callMcpTool(
client: Client,
toolName: string,
args: Record<string, unknown>
): Promise<CallToolResult> {
const result = await client.request(
{ method: 'tools/call', params: { name: toolName, arguments: args } },
CallToolResultSchema
)
return result
}
12.4.4 MCP OAuth 认证
mcp/auth.ts 处理 MCP 服务器的 OAuth 认证流程:
sequenceDiagram
participant Claude as Claude Code
participant MCP as MCP Client
participant Auth as Auth Server
participant User as 用户
MCP->>Claude: 需要认证
Claude->>Auth: 获取 OAuth URL
Auth-->>Claude: auth_url
Claude->>User: 打开浏览器
User->>Auth: 授权
Auth-->>Claude: callback (auth_code)
Claude->>Auth: exchange code for token
Auth-->>Claude: access_token
Claude->>MCP: 提供 token
MCP->>MCP Server: 认证完成
12.5 OAuth 认证服务
12.5.1 OAuth 客户端
oauth/client.ts 实现 OAuth 2.0 流程,配置来自 constants/oauth.ts:
// Claude.ai OAuth scopes - 用于 Claude.ai 订阅用户
export const CLAUDE_AI_OAUTH_SCOPES = [
'user:profile', // 用户基本信息
'user:inference', // API 调用权限
'user:sessions:claude_code', // Claude Code 会话
'user:mcp_servers', // MCP 服务器管理
'user:file_upload', // 文件上传
]
// OAuth 配置结构
type OauthConfig = {
BASE_API_URL: string
CONSOLE_AUTHORIZE_URL: string
CLAUDE_AI_AUTHORIZE_URL: string
TOKEN_URL: string
CLIENT_ID: string
// ...更多配置
}
生产环境配置:
const PROD_OAUTH_CONFIG = {
BASE_API_URL: 'https://api.anthropic.com',
CONSOLE_AUTHORIZE_URL: 'https://platform.claude.com/oauth/authorize',
CLAUDE_AI_AUTHORIZE_URL: 'https://claude.com/cai/oauth/authorize',
TOKEN_URL: 'https://platform.claude.com/v1/oauth/token',
CLIENT_ID: '9d1c250a-e61b-44d9-88ed-5944d1962f5e',
}
获取组织 UUID:
export async function getOrganizationUUID(): Promise<string | null> {
const tokens = getClaudeAIOAuthTokens()
if (!tokens) return null
const response = await fetch(`${OAUTH_API_URL}/organizations`, {
headers: { Authorization: `Bearer ${tokens.accessToken}` },
})
if (!response.ok) return null
const data = await response.json()
return data.id
}
12.5.2 Token 管理
export async function checkAndRefreshOAuthTokenIfNeeded(): Promise<boolean> {
const tokens = getClaudeAIOAuthTokens()
if (!tokens) return false
// 检查是否即将过期
const expiry = decodeJwtExpiry(tokens.accessToken)
if (!expiry) return false
const now = Math.floor(Date.now() / 1000)
const buffer = 5 * 60 // 5 分钟缓冲
if (expiry - now < buffer) {
// 需要刷新
return await refreshAccessToken(tokens.refreshToken)
}
return true
}
12.6 上下文压缩服务
12.6.1 Compact 机制
当对话历史过长时,Claude Code 会自动压缩上下文:
flowchart TD
A[对话历史增长] --> B{超过阈值?}
B -->|No| C[继续对话]
B -->|Yes| D[触发 Compact]
D --> E[提取关键信息]
E --> F[生成摘要]
F --> G[替换历史]
G --> H[继续对话]
export async function compactConversation(
messages: MessageParam[]
): Promise<MessageParam[]> {
// 1. 分析消息结构
const groups = groupMessagesByTopic(messages)
// 2. 提取关键信息
const keyPoints = extractKeyPoints(groups)
// 3. 生成压缩摘要
const summary = await generateCompactSummary(keyPoints)
// 4. 构建新的消息列表
return [
{ role: 'user', content: `[Context Summary]\n${summary}` },
{ role: 'assistant', content: 'I understand the context. Let\'s continue.' },
...messages.slice(-10) // 保留最近的 10 条消息
]
}
12.6.2 Micro Compact
微压缩用于快速清理低价值内容:
export function microCompact(messages: MessageParam[]): MessageParam[] {
return messages.map(msg => {
if (msg.role === 'assistant') {
// 移除冗长的确认回复
if (isVerboseConfirmation(msg.content)) {
return { ...msg, content: 'Done.' }
}
}
return msg
})
}
12.7 辅助服务
12.7.1 Analytics 服务
// 分析事件类型
export type AnalyticsEvent =
| 'session_start'
| 'session_end'
| 'tool_call'
| 'api_request'
| 'error_occurred'
// 发送分析数据
export function logEvent(event: AnalyticsEvent, data: Record<string, unknown>) {
sink.send({
event,
timestamp: Date.now(),
sessionId: getSessionId(),
...data,
})
}
12.7.2 LSP 服务
// LSP 客户端管理
export class LSPServerManager {
private servers: Map<string, LSPServerInstance> = new Map()
async startServer(languageId: string, config: LSPConfig): Promise<void> {
const instance = new LSPServerInstance(languageId, config)
await instance.start()
this.servers.set(languageId, instance)
}
async getDiagnostics(filePath: string): Promise<Diagnostic[]> {
const languageId = detectLanguage(filePath)
const server = this.servers.get(languageId)
if (!server) return []
return server.getDiagnostics(filePath)
}
}
本章小结
Services 服务层是 Claude Code 的后端支撑系统,主要特点:
- 多云服务商支持:Anthropic、AWS Bedrock、Azure Foundry、Vertex AI
- MCP 协议完整实现:支持 Stdio、SSE、HTTP 三种传输
- 智能错误处理:指数退避重试、错误分类处理
- 上下文管理:自动压缩、微压缩、会话记忆
通过本章的学习,读者可以深入了解 Claude Code 如何与各种后端服务集成,以及如何实现稳定的 API 调用和智能的上下文管理。