first commit

This commit is contained in:
H
2026-04-03 13:01:19 +08:00
commit 538eced414
2575 changed files with 645911 additions and 0 deletions

View File

@@ -0,0 +1,772 @@
# 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` |