Files
claude-code-mirror/claude-code-中文Wiki/05-服务层详解.md
2026-04-03 13:01:19 +08:00

773 lines
22 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Claude Code 服务层详解
## 概述
服务层services/)是 Claude Code 的核心业务逻辑层,提供 API 通信、协议管理、数据处理等功能。本文档详细介绍各服务的职责、实现和协作关系。
---
## 1. services/api/ - Anthropic API 客户端
### client.ts - API 客户端工厂
**文件位置**: `src/services/api/client.ts`
**核心功能**: 创建配置好的 Anthropic API 客户端实例。
**支持的认证方式**:
#### 1. 直接 API 访问
```typescript
// 环境变量: ANTHROPIC_API_KEY
```
#### 2. AWS Bedrock
```typescript
// 环境变量配置
AWS_REGION AWS_DEFAULT_REGION
ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION ( Haiku )
```
- 支持 `AWS_BEARER_TOKEN_BEDROCK` 进行 API Key 认证
- 支持自动凭证刷新
#### 3. Azure Foundry
```typescript
// 环境变量
ANTHROPIC_FOUNDRY_RESOURCE ANTHROPIC_FOUNDRY_BASE_URL
ANTHROPIC_FOUNDRY_API_KEY ()
```
- 支持 Azure AD 认证(`DefaultAzureCredential`
- 支持自定义回调端口
#### 4. Google Vertex AI
```typescript
// 环境变量
VERTEX_REGION_* ()
CLOUD_ML_REGION ()
ANTHROPIC_VERTEX_PROJECT_ID
```
- 支持 `google-auth-library` 凭证系统
- 防止元数据服务器超时
**关键函数**:
```typescript
export async function getAnthropicClient({
apiKey,
maxRetries,
model,
fetchOverride,
source,
}: {
apiKey?: string
maxRetries: number
model?: string
fetchOverride?: ClientOptions['fetch']
source?: string
}): Promise<Anthropic>
```
**请求拦截**:
- 注入自定义头:`x-app: cli`, `User-Agent`, `X-Claude-Code-Session-Id`
- 支持 `ANTHROPIC_CUSTOM_HEADERS` 环境变量自定义头
- 支持 `x-anthropic-additional-protection`
- 生成客户端请求 ID (`x-client-request-id`) 用于追踪
**代理支持**:
```typescript
fetchOptions: getProxyFetchOptions({ forAnthropicAPI: true })
```
### claude.ts - API 调用封装
**文件位置**: `src/services/api/claude.ts`
**核心功能**:
- `queryModelWithStreaming()` - 流式查询模型
- `getMaxOutputTokensForModel()` - 获取模型最大输出 token
- `getPromptTooLongTokenGap()` - 解析 prompt 太长错误
- `PROMPT_TOO_LONG_ERROR_MESSAGE` - 错误消息常量
### filesApi.ts - 文件 API
**功能**: 处理文件上传到 Claude API。
### errors.ts - 错误处理
**核心类型**:
```typescript
export const PROMPT_TOO_LONG_ERROR_MESSAGE =
'Conversation too long. Press esc twice to go up a few messages and try again.'
export function startsWithApiErrorPrefix(text: string | null): boolean
export function isPromptTooLongError(error: Error): boolean
```
### withRetry.ts - 重试逻辑
**功能**: 提供指数退避重试机制。
```typescript
export async function withRetry<T>(
fn: () => Promise<T>,
options: {
maxRetries?: number
initialDelayMs?: number
maxDelayMs?: number
}
): Promise<T>
```
### usage.ts - 使用量追踪
**功能**: 追踪 API 调用使用量(输入/输出 token
---
## 2. services/mcp/ - Model Context Protocol
### 类型系统 (types.ts)
**配置作用域** (`ConfigScope`):
```typescript
z.enum(['local', 'user', 'project', 'dynamic', 'enterprise', 'claudeai', 'managed'])
```
**传输类型** (`Transport`):
```typescript
z.enum(['stdio', 'sse', 'sse-ide', 'http', 'ws', 'sdk'])
```
**服务器配置**:
```typescript
// Stdio 配置
McpStdioServerConfigSchema = z.object({
type: z.literal('stdio'),
command: z.string(),
args: z.array(z.string()),
env: z.record(z.string()),
})
// SSE 配置
McpSSEServerConfigSchema = z.object({
type: z.literal('sse'),
url: z.string(),
headers: z.record(z.string()),
oauth: McpOAuthConfigSchema,
})
// WebSocket 配置
McpWebSocketServerConfigSchema = z.object({
type: z.literal('ws'),
url: z.string(),
headers: z.record(z.string()),
})
```
**连接状态类型**:
```typescript
ConnectedMCPServer = { client, name, type: 'connected', capabilities, serverInfo, cleanup }
FailedMCPServer = { name, type: 'failed', error }
NeedsAuthMCPServer = { name, type: 'needs-auth' }
PendingMCPServer = { name, type: 'pending', reconnectAttempt }
DisabledMCPServer = { name, type: 'disabled' }
```
### useManageMCPConnections.ts - 连接管理 Hook
**文件位置**: `src/services/mcp/useManageMCPConnections.ts`
**核心职责**:
1. 初始化 MCP 客户端连接
2. 设置连接生命周期处理器
3. 管理自动重连SSE 连接)
4. 同步 appState
**关键特性**:
#### 自动重连
- 最大重试次数: 5
- 初始退避: 1000ms
- 最大退避: 30000ms
- 指数退避策略
#### 通知处理器
```typescript
// 工具列表变更
client.client.setNotificationHandler(ToolListChangedNotificationSchema, ...)
// 提示列表变更
client.client.setNotificationHandler(PromptListChangedNotificationSchema, ...)
// 资源列表变更
client.client.setNotificationHandler(ResourceListChangedNotificationSchema, ...)
```
#### 通道推送 (KAIROS 特性)
```typescript
// 注册通道通知处理器
client.client.setNotificationHandler(ChannelMessageNotificationSchema, async notification => {
enqueue({
mode: 'prompt',
value: wrapChannelMessage(client.name, content, meta),
priority: 'next',
isMeta: true,
})
})
```
### channelNotification.ts - 通道通知
**功能**: 处理 MCP 服务器的通道消息通知。
### channelPermissions.ts - 通道权限
**功能**: 管理通道权限回调。
### auth.ts - MCP 认证
**功能**: 处理 MCP 服务器的 OAuth 认证流程。
### oauthPort.ts - OAuth 端口管理
**功能**: 管理 OAuth 回调端口。
### elicitationHandler.ts - 信息请求处理
**功能**: 处理 MCP 服务器的信息请求elicitation
### normalization.ts - 工具名称规范化
**功能**: 规范化 MCP 工具名称,避免命名冲突。
---
## 3. services/oauth/ - OAuth 2.0 认证
**文件位置**: `src/services/oauth/index.ts`
### OAuthService 类
**核心功能**: 实现 OAuth 2.0 授权码流程(支持 PKCE
```typescript
export class OAuthService {
async startOAuthFlow(
authURLHandler: (url: string, automaticUrl?: string) => Promise<void>,
options?: {
loginWithClaudeAi?: boolean
inferenceOnly?: boolean
expiresIn?: number
orgUUID?: string
loginHint?: string
loginMethod?: string
skipBrowserOpen?: boolean
}
): Promise<OAuthTokens>
}
```
**两种授权流程**:
#### 1. 自动流程
- 打开浏览器,跳转到授权页面
- 用户在浏览器中完成授权
- 回调到本地监听服务器
#### 2. 手动流程
- 显示手动授权 URL
- 用户复制 URL 到浏览器
- 用户复制授权码回来
**核心步骤**:
1. 创建本地授权码监听器 (`AuthCodeListener`)
2. 生成 PKCE 值(`code_verifier`, `code_challenge`
3. 构建授权 URL
4. 等待授权码
5. 交换令牌
### client.ts - OAuth 客户端
**功能**: 与 OAuth 服务器通信。
```typescript
export async function exchangeCodeForTokens(
code: string,
state: string,
codeVerifier: string,
port: number,
isManual: boolean,
expiresIn?: number
): Promise<OAuthTokenExchangeResponse>
export function buildAuthUrl(opts: {
codeChallenge: string
state: string
port: number
isManual: boolean
loginWithClaudeAi?: boolean
inferenceOnly?: boolean
orgUUID?: string
loginHint?: string
loginMethod?: string
}): string
```
### crypto.ts - 加密工具
**功能**: PKCE 加密操作。
```typescript
export function generateCodeVerifier(): string
export function generateCodeChallenge(verifier: string): string
export function generateState(): string
```
### auth-code-listener.ts - 授权码监听
**功能**: 启动本地 HTTP 服务器监听 OAuth 回调。
```typescript
export class AuthCodeListener {
async start(): Promise<number> // 返回监听端口
waitForAuthorization(state: string, onReady: () => Promise<void>): Promise<string>
handleSuccessRedirect(scopes: string[]): void
handleErrorRedirect(): void
close(): void
}
```
---
## 4. services/lsp/ - Language Server Protocol
### manager.ts - LSP 管理器
**文件位置**: `src/services/lsp/manager.ts`
**核心接口**:
```typescript
export interface LSPServerManager {
getAllServers(): Map<string, LSPServerInstance>
getServer(name: string): LSPServerInstance | undefined
getServerCapabilities(name: string): ServerCapabilities | undefined
initialize(): Promise<void>
shutdown(): Promise<void>
}
```
**初始化流程**:
1. `initializeLspServerManager()` - 初始化管理器单例
2. `createLSPServerManager()` - 创建管理器实例
3. `registerLSPNotificationHandlers()` - 注册通知处理器
**状态管理**:
```typescript
type InitializationState = 'not-started' | 'pending' | 'success' | 'failed'
```
**关键函数**:
```typescript
export function getLspServerManager(): LSPServerManager | undefined
export function isLspConnected(): boolean
export async function waitForInitialization(): Promise<void>
export function reinitializeLspServerManager(): void // 用于 /reload-plugins
export async function shutdownLspServerManager(): Promise<void>
```
### LSPServerInstance.ts - 服务器实例
**功能**: 管理单个 LSP 服务器实例。
### LSPClient.ts - LSP 客户端
**功能**: 实现 LSP 协议客户端逻辑。
### LSPDiagnosticRegistry.ts - 诊断注册
**功能**: 注册和管理 LSP 诊断信息。
### passiveFeedback.ts - 被动反馈
**功能**: 处理 LSP 的被动反馈(如悬停信息、定义跳转)。
---
## 5. services/analytics/ - 分析服务
### index.ts - 分析服务入口
**文件位置**: `src/services/analytics/index.ts`
**核心功能**:
- 事件日志记录
- GrowthBook 特性开关
- 事件队列管理
**事件日志**:
```typescript
export function logEvent(
eventName: string,
metadata: Record<string, boolean | number | undefined>
): void
export async function logEventAsync(
eventName: string,
metadata: Record<string, boolean | number | undefined>
): Promise<void>
```
**设计原则**:
- 无依赖设计,避免导入循环
- 事件在 sink 连接前进入队列
- 支持同步/异步事件记录
**GrowthBook 集成**:
```typescript
export function getFeatureValue_CACHED_MAY_BE_STALE(
featureName: string,
defaultValue: T
): T
```
---
## 6. services/plugins/ - 插件系统
### pluginOperations.ts - 插件操作
**文件位置**: `src/services/plugins/pluginOperations.ts`
**核心操作**:
```typescript
export async function installPluginOp(
plugin: string,
scope: InstallableScope = 'user'
): Promise<PluginOperationResult>
export async function uninstallPluginOp(
plugin: string,
scope: InstallableScope = 'user',
deleteDataDir = true
): Promise<PluginOperationResult>
export async function setPluginEnabledOp(
plugin: string,
enabled: boolean,
scope?: InstallableScope
): Promise<PluginOperationResult>
export async function updatePluginOp(
plugin: string,
scope: PluginScope
): Promise<PluginUpdateResult>
```
**安装作用域**:
```typescript
export const VALID_INSTALLABLE_SCOPES = ['user', 'project', 'local'] as const
```
**操作原则**:
1. 搜索市场获取插件信息
2. 写入设置(声明意图)
3. 缓存插件并记录版本
### PluginInstallationManager.ts - 安装管理
**功能**: 管理插件的下载、安装、更新。
---
## 7. services/compact/ - 对话压缩
### compact.ts - 核心压缩逻辑
**文件位置**: `src/services/compact/compact.ts`
**核心接口**:
```typescript
export interface CompactionResult {
boundaryMarker: SystemMessage
summaryMessages: UserMessage[]
attachments: AttachmentMessage[]
hookResults: HookResultMessage[]
messagesToKeep?: Message[]
userDisplayMessage?: string
preCompactTokenCount?: number
postCompactTokenCount?: number
truePostCompactTokenCount?: number
compactionUsage?: ReturnType<typeof getTokenUsage>
}
```
**压缩类型**:
#### 完整压缩 (`compactConversation`)
```typescript
export async function compactConversation(
messages: Message[],
context: ToolUseContext,
cacheSafeParams: CacheSafeParams,
suppressFollowUpQuestions: boolean,
customInstructions?: string,
isAutoCompact: boolean = false,
recompactionInfo?: RecompactionInfo
): Promise<CompactionResult>
```
#### 部分压缩 (`partialCompactConversation`)
```typescript
export async function partialCompactConversation(
allMessages: Message[],
pivotIndex: number,
context: ToolUseContext,
cacheSafeParams: CacheSafeParams,
userFeedback?: string,
direction: PartialCompactDirection = 'from'
): Promise<CompactionResult>
```
**核心流程**:
1. 执行 PreCompact hooks
2. 剥离图片/文档(节省 token
3. 调用 AI 生成摘要
4. 创建压缩边界标记
5. 执行 SessionStart hooks
6. 清理缓存
### microCompact.ts - 微压缩
**功能**: 在调用压缩 API 前减少消息 token 数量。
```typescript
export async function microcompactMessages(
messages: Message[],
context: ToolUseContext
): Promise<{ messages: Message[] }>
```
### sessionMemoryCompact.ts - 会话内存压缩
**功能**: 快速压缩,无需调用 AI。
### autoCompact.ts - 自动压缩
**功能**: 当上下文即将达到限制时自动触发压缩。
---
## 8. services/policyLimits/ - 组织策略限制
**文件位置**: `src/services/policyLimits/index.ts`
**功能**: 获取并应用组织级别的策略限制。
**资格条件**:
- Console 用户API Key: 全部符合
- OAuth 用户Claude.ai: 仅 Team 和 Enterprise 订阅
**核心函数**:
```typescript
export function isPolicyLimitsEligible(): boolean
export async function waitForPolicyLimitsToLoad(): Promise<void>
export function isPolicyAllowed(policy: string): boolean
export async function loadPolicyLimits(): Promise<void>
export async function refreshPolicyLimits(): Promise<void>
export async function clearPolicyLimitsCache(): Promise<void>
```
**缓存策略**:
- 文件缓存: `~/.claude/policy-limits.json`
- ETag 校验
- 后台轮询(每小时)
**失败处理**: 失败时继续运行fail open
---
## 9. services/remoteManagedSettings/ - 远程托管设置
**文件位置**: `src/services/remoteManagedSettings/index.ts`
**功能**: 为企业客户获取和管理远程托管设置。
**核心函数**:
```typescript
export function isEligibleForRemoteManagedSettings(): boolean
export async function waitForRemoteManagedSettingsToLoad(): Promise<void>
export async function loadRemoteManagedSettings(): Promise<void>
export async function refreshRemoteManagedSettings(): Promise<void>
export async function clearRemoteManagedSettingsCache(): Promise<void>
```
**安全检查**:
```typescript
export async function checkManagedSettingsSecurity(
cachedSettings: SettingsJson,
newSettings: SettingsJson
): Promise<SecurityCheckResult>
```
---
## 10. services/extractMemories/ - 自动记忆提取
**文件位置**: `src/services/extractMemories/extractMemories.ts`
**功能**: 从当前会话中提取持久记忆并写入自动记忆目录。
**触发时机**: 在查询循环结束时(模型生成最终响应后)
**核心接口**:
```typescript
export function initExtractMemories(): void
export async function executeExtractMemories(
context: REPLHookContext,
appendSystemMessage?: AppendSystemMessageFn
): Promise<void>
export async function drainPendingExtraction(timeoutMs?: number): Promise<void>
```
**工具权限**:
```typescript
export function createAutoMemCanUseTool(memoryDir: string): CanUseToolFn
// 允许: Read, Grep, Glob, 只读 Bash
// 允许: Edit, Write 仅限 auto-memory 路径
```
**特性开关**:
- `tengu_passport_quail` - 启用/禁用记忆提取
- `tengu_bramble_lintel` - 提取频率控制
- `TEAMMEM` - 团队记忆支持
---
## 11. services/tokenEstimation.ts - Token 估算
**文件位置**: `src/services/tokenEstimation.ts`
**核心功能**: 估算文本和消息的 token 数量。
**主要函数**:
```typescript
export async function countTokensWithAPI(content: string): Promise<number | null>
export async function countMessagesTokensWithAPI(
messages: Anthropic.Beta.Messages.BetaMessageParam[],
tools: Anthropic.Beta.Messages.BetaToolUnion[]
): Promise<number | null>
export function roughTokenCountEstimation(
content: string,
bytesPerToken: number = 4
): number
export async function countTokensViaHaikuFallback(
messages: Anthropic.Beta.Messages.BetaMessageParam[],
tools: Anthropic.Beta.Messages.BetaToolUnion[]
): Promise<number | null>
```
**文件类型估算**:
```typescript
export function bytesPerTokenForFileType(fileExtension: string): number {
switch (fileExtension) {
case 'json':
case 'jsonl':
case 'jsonc':
return 2 // JSON 更密集
default:
return 4
}
}
```
**图像 token 估算**:
```typescript
// tokens = (width px * height px) / 750
// 最大 2000x2000 (约 5333 tokens)
```
---
## 12. services/teamMemorySync/ - 团队记忆同步
(参见 `extractMemories/` 中的 `TEAMMEM` 特性)
**功能**: 在团队成员之间同步记忆文件。
---
## 服务层架构图
```
┌─────────────────────────────────────────────────────────────┐
│ CLI 入口 │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 命令层 (commands/) │
│ /commit /review /compact /mcp /config /doctor 等 │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 服务层 (services/) │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ api/ │ │ mcp/ │ │ lsp/ │ │
│ │ Anthropic │ │ Model Context│ │ Language │ │
│ │ API 客户端 │ │ Protocol │ │ Server │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ oauth/ │ │ analytics/ │ │ plugins/ │ │
│ │ OAuth 2.0 │ │ GrowthBook │ │ 插件系统 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ compact/ │ │policyLimits/│ │remoteManage │ │
│ │ 对话压缩 │ │ 策略限制 │ │ dSettings/ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │extractMemories│ │tokenEstim ation│ │
│ │ 自动记忆提取 │ │ Token 估算 │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 工具层 (tools/) │
│ Read / Write / Edit / Bash / Grep / Glob 等 │
└─────────────────────────────────────────────────────────────┘
```
---
## 相关源码文件索引
| 服务 | 主要文件 |
|------|---------|
| API Client | `src/services/api/client.ts`, `claude.ts` |
| MCP | `src/services/mcp/` |
| OAuth | `src/services/oauth/` |
| LSP | `src/services/lsp/` |
| Analytics | `src/services/analytics/` |
| Plugins | `src/services/plugins/` |
| Compact | `src/services/compact/` |
| Policy Limits | `src/services/policyLimits/` |
| Remote Settings | `src/services/remoteManagedSettings/` |
| Extract Memories | `src/services/extractMemories/` |
| Token Estimation | `src/services/tokenEstimation.ts` |