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,441 @@
# Claude Code 架构总览
本文件说明:介绍 Claude Code 的整体架构设计、技术栈、核心设计模式。
## 1. 项目背景
Claude Code 是 Anthropic 官方开发的 CLI命令行界面工具旨在为开发者提供一个在终端环境中与 Claude 交互的途径,完成各种软件工程任务。
### 核心定位
- **终端优先**:专为命令行环境设计,使用 InkReact for CLIs渲染 Terminal UI
- **软件工程助手**专注于代码编写、文件操作、Git 管理、任务执行等开发任务
- **安全可控**:提供细粒度的权限控制,用户可精确控制工具访问范围
### 源码泄露事件
2026 年 3 月 31 日,通过 npm source map 泄露了大量 Claude Code 源码,引起了安全研究社区的关注。这次泄露使外界得以深入了解 Claude Code 的内部实现机制。
## 2. 技术栈详解
### 2.1 运行时环境Bun
Claude Code 使用 [Bun](https://bun.sh/) 作为 JavaScript/TypeScript 运行时:
```typescript
// 使用 bun:bundle feature flag 进行条件编译
import { feature } from 'bun:bundle'
// Dead code elimination 示例
const REPLTool = feature('REPL_MODE')
? require('./tools/REPLTool/REPLTool.js').REPLTool
: null
```
**Bun 的优势**
- 启动速度快
- 内置 bundler 功能支持条件导入Dead code elimination
- 原生支持 TypeScript
- 高效的 I/O 操作
### 2.2 语言TypeScript
全项目使用 TypeScript 开发,具有:
- 完整的类型系统
- 严格的参数校验(基于 Zod v4
- 模块化的接口设计
### 2.3 终端 UIReact + Ink
Claude Code 使用 [Ink](https://github.com/vadimdemedes/ink) 库来实现 React 风格的终端界面:
```typescript
// Ink 组件示例
import { Box, Text } from 'ink'
const MyComponent = () => (
<Box>
<Text>Hello, Terminal!</Text>
</Box>
)
```
**UI 组件特点**
- 支持颜色、布局、边框等终端视觉效果
- 兼容 React 生态系统hooks、context
- 用于渲染消息、进度条、选择器等 UI 元素
### 2.4 CLI 框架Commander.js
使用 Commander.js 处理命令行参数和子命令:
```typescript
import { Command } from '@commander-js/extra-typings'
const program = new Command()
program
.name('claude')
.description('Anthropic 的 CLI 工具')
.version('1.0.0')
```
### 2.5 参数校验Zod v4
使用 Zod v4 进行运行时参数校验:
```typescript
import { z } from 'zod/v4'
const inputSchema = z.object({
file_path: z.string(),
offset: z.number().int().nonnegative().optional(),
limit: z.number().int().positive().optional(),
})
```
### 2.6 代码搜索ripgrep
内置集成了 ripgrep (`rg`) 用于高效的代码搜索:
```typescript
// 在 GrepTool 等工具中使用
import { execFile } from 'child_process'
execFile('rg', ['--json', pattern, directory], callback)
```
## 3. 核心架构设计
### 3.1 整体架构图
```
┌─────────────────────────────────────────────────────────────┐
│ main.tsx │
│ (CLI 入口点) │
└─────────────────────┬───────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ QueryEngine │
│ (查询引擎核心) │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ - submitMessage(): 处理用户输入 │ │
│ │ - query(): 执行 API 调用循环 │ │
│ │ - 流式响应处理 │ │
│ │ - 工具调用编排 │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────┬───────────────────────────────────────────┘
┌─────────────┼─────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Tools │ │ Commands │ │ Context │
│ (工具系统) │ │ (命令系统) │ │ (上下文系统) │
└─────────────┘ └─────────────┘ └─────────────┘
```
### 3.2 工具系统架构
工具系统是 Claude Code 最核心的扩展机制:
```
┌─────────────────────────────────────────────────────────────┐
│ Tool.ts │
│ (工具基类定义) │
│ - inputSchema: Zod 输入校验 │
│ - call(): 工具执行入口 │
│ - checkPermissions(): 权限检查 │
│ - render*: UI 渲染方法 │
└─────────────────────────────────────────────────────────────┘
┌────────────────────┼────────────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ BashTool │ │ FileReadTool │ │ AgentTool │
│ (Shell命令) │ │ (文件读取) │ │ (子Agent) │
└─────────────┘ └─────────────┘ └─────────────┘
│ │ │
└────────────────────┼────────────────────┘
┌───────────────────────────────────┐
│ ToolRegistry (tools.ts) │
│ - getAllBaseTools(): 获取所有工具 │
│ - getTools(): 按权限过滤工具 │
│ - assembleToolPool(): 合并 MCP │
└───────────────────────────────────┘
```
### 3.3 命令系统架构
命令系统支持三种类型的命令:
```typescript
type CommandType =
| 'prompt' // 展开为提示发送给模型
| 'local' // 本地执行,返回文本结果
| 'local-jsx' // 本地执行,渲染 Ink UI
```
**命令注册流程**
1.`commands.ts` 中定义命令
2. 使用条件编译控制命令可见性
3. 通过 `getCommands()` 获取可用命令列表
### 3.4 查询管道架构
```
用户输入 ──► processUserInput() ──► query() ──► API 调用
│ │
│ ▼
│ 工具执行循环
│ │
│ ┌─────────┼─────────┐
│ ▼ ▼ ▼
│ Tool 1 Tool 2 Tool N
│ │ │ │
│ └─────────┼─────────┘
│ ▼
│ 结果处理 ◄──────┐
│ │ │
│ ▼ │
└──────► 结果返回 ───────────┘
```
## 4. 关键设计模式
### 4.1 工厂模式 (Factory Pattern)
使用 `buildTool()` 工厂函数创建工具实例:
```typescript
export function buildTool<D extends AnyToolDef>(def: D): BuiltTool<D> {
return {
...TOOL_DEFAULTS, // 填充默认实现
userFacingName: () => def.name,
...def,
} as BuiltTool<D>
}
```
### 4.2 策略模式 (Strategy Pattern)
权限检查使用策略模式:
```typescript
async checkPermissions(
input: z.infer<Input>,
context: ToolUseContext,
): Promise<PermissionResult> {
// 根据权限模式选择不同的检查策略
switch (context.mode) {
case 'auto': return autoCheck(input, context)
case 'bypass': return allowAll(input)
case 'default': return defaultCheck(input, context)
}
}
```
### 4.3 装饰器模式 (Decorator Pattern)
`backfillObservableInput()` 允许在工具执行前修改输入:
```typescript
backfillObservableInput?(input: Record<string, unknown>): void {
// 在观察者看到输入之前修改它
// 必须幂等
}
```
### 4.4 生成器模式 (Generator Pattern)
查询管道使用 AsyncGenerator 实现流式处理:
```typescript
async *query(params: QueryParams): AsyncGenerator<
| StreamEvent
| RequestStartEvent
| Message
| TombstoneMessage
| ToolUseSummaryMessage,
Terminal
> {
// 流式 yield 消息
}
```
## 5. 状态管理
### 5.1 全局状态 (AppState)
```typescript
interface AppState {
toolPermissionContext: ToolPermissionContext
fastMode: boolean
fileHistory: FileHistoryState
mcp: MCPState
// ...其他状态
}
```
### 5.2 会话状态
- **Session ID**:唯一标识每次会话
- **Message 列表**:维护对话历史
- **Token 使用**:追踪 API 调用成本
- **文件缓存**readFileState 缓存已读文件内容
## 6. 安全机制
### 6.1 权限模式 (Permission Modes)
| 模式 | 描述 |
|------|------|
| `default` | 执行危险操作前询问用户 |
| `auto` | 基于规则自动允许/拒绝 |
| `bypass` | 允许所有操作(仅供可信环境) |
| `plan` | 计划模式,限制更严格 |
### 6.2 工具沙箱
BashTool 支持使用沙箱执行命令:
```typescript
const shouldUseSandbox = await shouldUseSandbox(command)
if (shouldUseSandbox) {
// 使用沙箱执行
} else {
// 直接执行
}
```
## 7. 扩展机制
### 7.1 MCP (Model Context Protocol)
支持通过 MCP 协议扩展工具:
```typescript
interface MCPServerConnection {
name: string
type: 'stdio' | 'http'
command?: string
args?: string[]
env?: Record<string, string>
}
```
### 7.2 插件系统
```typescript
// 插件加载
const plugins = await loadAllPluginsCacheOnly()
// 插件命令注册
export function getPluginCommands(): Promise<Command[]>
```
### 7.3 技能系统 (Skills)
技能是保存在本地目录中的可执行脚本:
```typescript
// 技能目录结构
~/.claude/skills/
skill-name/
skill.md #
script.sh #
```
## 8. 性能优化
### 8.1 记忆化 (Memoization)
使用 lodash 的 `memoize` 缓存昂贵计算:
```typescript
export const getGitStatus = memoize(async (): Promise<string | null> => {
// Git 状态获取(只计算一次)
})
```
### 8.2 条件编译 (Dead Code Elimination)
通过 Bun 的 `feature()` 实现条件编译:
```typescript
const SleepTool = feature('PROACTIVE') || feature('KAIROS')
? require('./tools/SleepTool/SleepTool.js').SleepTool
: null
```
### 8.3 自动压缩 (Auto-compact)
当上下文接近 Token 限制时自动压缩历史:
```typescript
const { compactionResult } = await deps.autocompact(
messagesForQuery,
toolUseContext,
{ systemPrompt, userContext, systemContext, toolUseContext },
querySource,
tracking,
snipTokensFreed,
)
```
## 9. 源码目录结构
```
claude-code/
├── src/
│ ├── main.tsx # CLI 入口
│ ├── QueryEngine.ts # 查询引擎
│ ├── Tool.ts # 工具基类
│ ├── tools.ts # 工具注册表
│ ├── commands.ts # 命令注册
│ ├── context.ts # 上下文收集
│ ├── cost-tracker.ts # 成本追踪
│ ├── query.ts # 查询管道
│ │
│ ├── tools/ # 工具实现
│ │ ├── BashTool/ # Shell 命令执行
│ │ ├── FileReadTool/ # 文件读取
│ │ ├── FileEditTool/ # 文件编辑
│ │ ├── FileWriteTool/ # 文件写入
│ │ ├── GlobTool/ # 文件模式匹配
│ │ ├── GrepTool/ # 代码搜索
│ │ ├── AgentTool/ # 子 Agent
│ │ ├── WebFetchTool/ # 网页获取
│ │ ├── WebSearchTool/ # 网络搜索
│ │ ├── Task*/ # 任务管理系列
│ │ └── ...
│ │
│ ├── services/ # 服务层
│ │ ├── api/ # API 调用
│ │ ├── mcp/ # MCP 协议
│ │ ├── compact/ # 上下文压缩
│ │ └── analytics/ # 分析服务
│ │
│ ├── state/ # 状态管理
│ │ ├── AppState.ts
│ │ └── store.ts
│ │
│ └── utils/ # 工具函数
│ ├── permissions/ # 权限系统
│ ├── model/ # 模型配置
│ └── ...
├── package.json
└── tsconfig.json
```
## 10. 总结
Claude Code 的架构设计体现了以下原则:
1. **模块化**:清晰的分层和模块划分
2. **可扩展性**:工具系统、命令系统、插件系统三位一体
3. **类型安全**TypeScript + Zod 双重保障
4. **性能优先**:记忆化、条件编译、流式处理
5. **安全可控**:细粒度的权限控制系统
这套架构使得 Claude Code 能够有效地在终端环境中执行复杂的软件工程任务,同时保持高度的可配置性和安全性。

View File

@@ -0,0 +1,813 @@
# 核心模块详解
本文件说明:详细分析 Claude Code 的核心源文件,理解其实现原理。
## 1. main.tsx - CLI 入口点
### 1.1 功能概述
`main.tsx` 是 Claude Code 应用程序的入口点,负责:
- CLI 参数解析
- 应用程序初始化
- REPLRead-Eval-Print Loop启动
- 各种启动前检查和配置
### 1.2 启动流程
```typescript
// 1. 启动性能分析
profileCheckpoint('main_tsx_entry')
// 2. MDM 设置预读取(并行)
startMdmRawRead()
// 3. Keychain 凭据预读取(并行)
startKeychainPrefetch()
// 4. 初始化遥测
initializeTelemetryAfterTrust()
// 5. 获取引导数据
const bootstrapData = await fetchBootstrapData()
// 6. 启动 REPL
launchRepl()
```
### 1.3 关键导入
```typescript
import { Command as CommanderCommand } from '@commander-js/extra-typings'
import React from 'react'
import chalk from 'chalk'
import { getTools } from './tools.js'
import { getCommands, filterCommandsForRemoteMode } from './commands.js'
import { getSystemContext, getUserContext } from './context.js'
```
### 1.4 核心配置初始化
```typescript
// 权限模式设置
const initialPermissionMode = await initialPermissionModeFromCLI()
// 工具权限上下文初始化
initializeToolPermissionContext({
mode: initialPermissionMode,
additionalWorkingDirectories: new Map(),
alwaysAllowRules: {},
alwaysDenyRules: {},
alwaysAskRules: {},
isBypassPermissionsModeAvailable: false,
})
// 获取工具列表
const tools = getTools(appState.toolPermissionContext)
// 获取命令列表
const commands = await getCommands(cwd)
```
## 2. QueryEngine.ts - LLM 查询引擎核心
### 2.1 功能概述
`QueryEngine` 是 Claude Code 的核心查询处理类,负责:
- 管理对话生命周期(每个对话一个 QueryEngine 实例)
- 处理用户消息提交
- 执行 API 调用循环
- 处理流式响应
- 编排工具执行
- 管理会话状态消息、Token 使用等)
### 2.2 类结构
```typescript
export class QueryEngine {
private config: QueryEngineConfig
private mutableMessages: Message[] // 对话消息列表
private abortController: AbortController // 中断控制器
private permissionDenials: SDKPermissionDenial[] // 权限拒绝记录
private totalUsage: NonNullableUsage // 累计 Token 使用
private hasHandledOrphanedPermission = false
private readFileState: FileStateCache // 文件读取缓存
private discoveredSkillNames = new Set<string>()
private loadedNestedMemoryPaths = new Set<string>()
}
```
### 2.3 核心方法submitMessage()
这是处理用户输入的主要方法:
```typescript
async *submitMessage(
prompt: string | ContentBlockParam[],
options?: { uuid?: string; isMeta?: boolean },
): AsyncGenerator<SDKMessage, void, unknown>
```
**执行流程**
1. **初始化阶段**
```typescript
this.discoveredSkillNames.clear()
setCwd(cwd)
// 获取系统提示词
const { defaultSystemPrompt, userContext, systemContext } =
await fetchSystemPromptParts({ tools, mainLoopModel, ... })
```
2. **处理用户输入**
```typescript
const { messages, shouldQuery, allowedTools, model, resultText } =
await processUserInput({
input: prompt,
mode: 'prompt',
context: processUserInputContext,
})
// 更新权限规则
setAppState(prev => ({
...prev,
toolPermissionContext: {
...prev.toolPermissionContext,
alwaysAllowRules: { command: allowedTools }
}
}))
```
3. **构建系统提示**
```typescript
const systemPrompt = asSystemPrompt([
...(customPrompt ?? defaultSystemPrompt),
...(memoryMechanicsPrompt ?? []), // 记忆机制提示
...(appendSystemPrompt ?? [])
])
```
4. **查询循环**
```typescript
for await (const message of query({
messages,
systemPrompt,
userContext,
systemContext,
canUseTool: wrappedCanUseTool,
})) {
// 处理各种消息类型
switch (message.type) {
case 'assistant': /* 记录助手消息 */ break
case 'progress': /* 进度更新 */ break
case 'user': /* 用户消息 */ break
case 'stream_event': /* 流式事件 */ break
case 'attachment': /* 附件处理 */ break
}
}
```
### 2.4 流式响应处理
QueryEngine 处理多种流式事件:
```typescript
if (message.type === 'stream_event') {
// message_start: 新消息开始
if (message.event.type === 'message_start') {
currentMessageUsage = EMPTY_USAGE
currentMessageUsage = updateUsage(currentMessageUsage, message.event.message.usage)
}
// message_delta: 消息增量更新
if (message.event.type === 'message_delta') {
currentMessageUsage = updateUsage(currentMessageUsage, message.event.usage)
if (message.event.delta.stop_reason != null) {
lastStopReason = message.event.delta.stop_reason
}
}
// message_stop: 消息结束
if (message.event.type === 'message_stop') {
this.totalUsage = accumulateUsage(this.totalUsage, currentMessageUsage)
}
}
```
### 2.5 思考模式 (Thinking Mode)
Claude Code 支持 Claude 的思考模式:
```typescript
const initialThinkingConfig: ThinkingConfig = thinkingConfig
? thinkingConfig
: shouldEnableThinkingByDefault() !== false
? { type: 'adaptive' } // 自适应思考
: { type: 'disabled' } // 禁用
```
思考规则(注释中的说明):
1. 包含思考或编辑块的消息必须在 `max_thinking_length > 0` 的查询中
2. 思考块不能是消息块中的最后一个
3. 思考块必须在整个助手轨迹中保留
### 2.6 错误恢复机制
```typescript
// USD 预算超限检查
if (maxBudgetUsd !== undefined && getTotalCost() >= maxBudgetUsd) {
yield {
type: 'result',
subtype: 'error_max_budget_usd',
...
}
return
}
// 最大轮次检查
if (maxTurns && nextTurnCount > maxTurns) {
yield { type: 'result', subtype: 'error_max_turns', ... }
return
}
// 结构化输出重试限制
if (callsThisQuery >= maxRetries) {
yield { type: 'result', subtype: 'error_max_structured_output_retries', ... }
return
}
```
## 3. Tool.ts - 工具基类和接口定义
### 3.1 工具接口定义
```typescript
export type Tool<
Input extends AnyObject = AnyObject,
Output = unknown,
P extends ToolProgressData = ToolProgressData,
> = {
// 工具名称
readonly name: string
// 可选别名(用于工具重命名后的向后兼容)
aliases?: string[]
// 工具搜索提示词
searchHint?: string
// 核心执行方法
call(
args: z.infer<Input>,
context: ToolUseContext,
canUseTool: CanUseToolFn,
parentMessage: AssistantMessage,
onProgress?: ToolCallProgress<P>,
): Promise<ToolResult<Output>>
// 获取工具描述
description(
input: z.infer<Input>,
options: {...}
): Promise<string>
// 输入 Schema
readonly inputSchema: Input
// 输入 JSON Schema用于 MCP 工具)
readonly inputJSONSchema?: ToolInputJSONSchema
// 输出 Schema
outputSchema?: z.ZodType<unknown>
}
```
### 3.2 工具权限方法
```typescript
// 验证输入是否有效
validateInput?(
input: z.infer<Input>,
context: ToolUseContext,
): Promise<ValidationResult>
// 检查权限
checkPermissions(
input: z.infer<Input>,
context: ToolUseContext,
): Promise<PermissionResult>
// 准备权限匹配器
preparePermissionMatcher?(
input: z.infer<Input>,
): Promise<(pattern: string) => boolean>
```
### 3.3 工具渲染方法
```typescript
// 渲染工具使用消息
renderToolUseMessage(
input: Partial<z.infer<Input>>,
options: { theme: ThemeName; verbose: boolean; commands?: Command[] }
): React.ReactNode
// 渲染工具结果消息
renderToolResultMessage?(
content: Output,
progressMessagesForMessage: ProgressMessage<P>[],
options: {...}
): React.ReactNode
// 渲染工具使用标签
renderToolUseTag?(input: Partial<z.infer<Input>>): React.ReactNode
// 渲染进度消息
renderToolUseProgressMessage?(
progressMessagesForMessage: ProgressMessage<P>[],
options: {...}
): React.ReactNode
```
### 3.4 buildTool 工厂函数
```typescript
const TOOL_DEFAULTS = {
isEnabled: () => true,
isConcurrencySafe: (_input?: unknown) => false,
isReadOnly: (_input?: unknown) => false,
isDestructive: (_input?: unknown) => false,
checkPermissions: async () => ({ behavior: 'allow', updatedInput: input }),
toAutoClassifierInput: (_input?: unknown) => '',
userFacingName: (_input?: unknown) => '',
}
export function buildTool<D extends AnyToolDef>(def: D): BuiltTool<D> {
return {
...TOOL_DEFAULTS,
userFacingName: () => def.name,
...def,
} as BuiltTool<D>
}
```
### 3.5 工具权限上下文
```typescript
export type ToolPermissionContext = {
mode: PermissionMode // 'default' | 'auto' | 'bypass' | 'plan'
additionalWorkingDirectories: Map<string, AdditionalWorkingDirectory>
alwaysAllowRules: ToolPermissionRulesBySource
alwaysDenyRules: ToolPermissionRulesBySource
alwaysAskRules: ToolPermissionRulesBySource
isBypassPermissionsModeAvailable: boolean
isAutoModeAvailable?: boolean
strippedDangerousRules?: ToolPermissionRulesBySource
shouldAvoidPermissionPrompts?: boolean
awaitAutomatedChecksBeforeDialog?: boolean
prePlanMode?: PermissionMode
}
```
## 4. commands.ts - 命令注册中心
### 4.1 功能概述
`commands.ts` 是 Claude Code 的命令注册中心,管理所有 slash commands以 `/` 开头的命令)。
### 4.2 命令类型
```typescript
type CommandType =
| 'prompt' // 展开为提示发送给模型
| 'local' // 本地执行,返回文本
| 'local-jsx' // 本地执行,渲染 Ink UI
```
### 4.3 命令定义结构
```typescript
interface Command {
type: CommandType
name: string
aliases?: string[]
description: string
contentLength: number
source: 'builtin' | 'plugin' | 'bundled' | 'mcp' | ...
availability?: ('claude-ai' | 'console')[]
// ...
}
```
### 4.4 命令加载流程
```typescript
// 1. 获取技能目录命令
const skillDirCommands = await getSkillDirCommands(cwd)
// 2. 获取插件命令
const pluginCommands = await getPluginCommands()
// 3. 获取内置命令
const builtinCommands = COMMANDS()
// 4. 合并并过滤
const allCommands = [
...bundledSkills,
...builtinPluginSkills,
...skillDirCommands,
...workflowCommands,
...pluginCommands,
...pluginSkills,
...COMMANDS(),
]
// 5. 检查可用性要求
const filteredCommands = allCommands.filter(cmd =>
meetsAvailabilityRequirement(cmd)
)
// 6. 检查是否启用
.filter(cmd => isCommandEnabled(cmd))
```
### 4.5 远程安全命令
```typescript
export const REMOTE_SAFE_COMMANDS: Set<Command> = new Set([
session, exit, clear, help, theme, color, vim,
cost, usage, copy, btw, feedback, plan,
keybindings, statusline, stickers, mobile,
])
```
### 4.6 命令查找
```typescript
export function findCommand(
commandName: string,
commands: Command[],
): Command | undefined {
return commands.find(
_ =>
_.name === commandName ||
getCommandName(_) === commandName ||
_.aliases?.includes(commandName)
)
}
```
## 5. context.ts - 系统/用户上下文收集
### 5.1 功能概述
`context.ts` 负责收集系统上下文和用户上下文,这些上下文会被预置到每个对话的开头。
### 5.2 Git 状态收集
```typescript
export const getGitStatus = memoize(async (): Promise<string | null> => {
// 检查是否是 Git 仓库
const isGit = await getIsGit()
if (!isGit) return null
// 并行获取多个 Git 信息
const [branch, mainBranch, status, log, userName] = await Promise.all([
getBranch(),
getDefaultBranch(),
execFileNoThrow(gitExe(), ['status', '--short'], ...),
execFileNoThrow(gitExe(), ['log', '--oneline', '-n', '5'], ...),
execFileNoThrow(gitExe(), ['config', 'user.name'], ...),
])
return [
`Current branch: ${branch}`,
`Main branch: ${mainBranch}`,
`Git user: ${userName}`,
`Status:\n${truncatedStatus}`,
`Recent commits:\n${log}`,
].join('\n\n')
})
```
### 5.3 系统上下文
```typescript
export const getSystemContext = memoize(async () => {
const gitStatus = await getGitStatus()
// 缓存破坏注入(仅用于调试)
const injection = feature('BREAK_CACHE_COMMAND')
? getSystemPromptInjection()
: null
return {
...(gitStatus && { gitStatus }),
...(injection && { cacheBreaker: `[CACHE_BREAKER: ${injection}]` }),
}
})
```
### 5.4 用户上下文
```typescript
export const getUserContext = memoize(async () => {
// 获取 CLAUDE.md 文件内容
const shouldDisableClaudeMd = isEnvTruthy(process.env.CLAUDE_CODE_DISABLE_CLAUDE_MDS)
|| (isBareMode() && getAdditionalDirectoriesForClaudeMd().length === 0)
const claudeMd = shouldDisableClaudeMd
? null
: getClaudeMds(filterInjectedMemoryFiles(await getMemoryFiles()))
// 缓存 CLAUDE.md 内容供自动模式分类器使用
setCachedClaudeMdContent(claudeMd || null)
return {
...(claudeMd && { claudeMd }),
currentDate: `Today's date is ${getLocalISODate()}.`,
}
})
```
### 5.5 上下文缓存
所有上下文函数都使用 `memoize` 进行缓存,确保在一次对话中只计算一次:
```typescript
export const getSystemContext = memoize(async () => {...})
export const getUserContext = memoize(async () => {...})
export const getGitStatus = memoize(async () => {...})
```
## 6. cost-tracker.ts - Token 成本追踪
### 6.1 功能概述
`cost-tracker.ts` 负责追踪和计算 API 调用的 Token 使用量和成本。
### 6.2 核心数据结构
```typescript
type StoredCostState = {
totalCostUSD: number
totalAPIDuration: number
totalAPIDurationWithoutRetries: number
totalToolDuration: number
totalLinesAdded: number
totalLinesRemoved: number
lastDuration: number | undefined
modelUsage: { [modelName: string]: ModelUsage }
}
type ModelUsage = {
inputTokens: number
outputTokens: number
cacheReadInputTokens: number
cacheCreationInputTokens: number
webSearchRequests: number
costUSD: number
contextWindow: number
maxOutputTokens: number
}
```
### 6.3 成本计算
```typescript
export function addToTotalSessionCost(
cost: number,
usage: Usage,
model: string,
): number {
const modelUsage = addToTotalModelUsage(cost, usage, model)
addToTotalCostState(cost, modelUsage, model)
// 发送到 Statsig 计数器
getCostCounter()?.add(cost, { model })
getTokenCounter()?.add(usage.input_tokens, { ...attrs, type: 'input' })
getTokenCounter()?.add(usage.output_tokens, { ...attrs, type: 'output' })
// 处理 Advisor 使用量
for (const advisorUsage of getAdvisorUsage(usage)) {
const advisorCost = calculateUSDCost(advisorUsage.model, advisorUsage)
totalCost += addToTotalSessionCost(advisorCost, advisorUsage, advisorUsage.model)
}
return totalCost
}
```
### 6.4 成本格式化
```typescript
export function formatTotalCost(): string {
const costDisplay = formatCost(getTotalCostUSD())
return chalk.dim(`
Total cost: ${costDisplay}
Total duration (API): ${formatDuration(getTotalAPIDuration())}
Total duration (wall): ${formatDuration(getTotalDuration())}
Total code changes: ${linesAdded} lines added, ${linesRemoved} lines removed
${formatModelUsage()}
`)
}
```
### 6.5 会话成本保存/恢复
```typescript
// 保存当前会话成本到项目配置
export function saveCurrentSessionCosts(fpsMetrics?: FpsMetrics): void {
saveCurrentProjectConfig(current => ({
...current,
lastCost: getTotalCostUSD(),
lastAPIDuration: getTotalAPIDuration(),
lastLinesAdded: getTotalLinesAdded(),
lastLinesRemoved: getTotalLinesRemoved(),
lastModelUsage: Object.fromEntries(...),
lastSessionId: getSessionId(),
}))
}
// 恢复会话成本
export function restoreCostStateForSession(sessionId: string): boolean {
const data = getStoredSessionCosts(sessionId)
if (!data) return false
setCostStateForRestore(data)
return true
}
```
## 7. query.ts - 查询管道
### 7.1 功能概述
`query.ts` 是核心的查询处理管道,负责:
- 消息流式 API 调用
- 工具调用编排
- 自动压缩
- 错误恢复
### 7.2 主查询循环
```typescript
export async function* query(
params: QueryParams,
): AsyncGenerator<...> {
const consumedCommandUuids: string[] = []
const terminal = yield* queryLoop(params, consumedCommandUuids)
return terminal
}
async function* queryLoop(
params: QueryParams,
consumedCommandUuids: string[],
): AsyncGenerator<...> {
let state: State = {
messages: params.messages,
toolUseContext: params.toolUseContext,
autoCompactTracking: undefined,
maxOutputTokensRecoveryCount: 0,
// ...
}
while (true) {
// 1. 上下文压缩
const { compactionResult } = await deps.autocompact(...)
// 2. API 调用循环
for await (const message of deps.callModel({...})) {
if (message.type === 'assistant') {
assistantMessages.push(message)
// 处理工具调用块
}
}
// 3. 工具执行
if (needsFollowUp) {
const toolUpdates = runTools(toolUseBlocks, ...)
for await (const update of toolUpdates) {
// 处理工具结果
}
}
// 4. 递归继续
state = { ...state, messages: [...messages, ...assistantMessages, ...toolResults] }
}
}
```
### 7.3 工具执行编排
```typescript
// 两种工具执行模式
if (streamingToolExecutor) {
// 流式工具执行:在模型流式输出的同时执行工具
logEvent('tengu_streaming_tool_execution_used', {...})
} else {
// 批量工具执行:等待模型完全响应后执行
logEvent('tengu_streaming_tool_execution_not_used', {...})
}
const toolUpdates = streamingToolExecutor
? streamingToolExecutor.getRemainingResults()
: runTools(toolUseBlocks, assistantMessages, canUseTool, toolUseContext)
```
### 7.4 错误恢复机制
```typescript
// 1. 模型回退
if (innerError instanceof FallbackTriggeredError && fallbackModel) {
currentModel = fallbackModel
attemptWithFallback = true
continue
}
// 2. Prompt Too Long 恢复
if (isWithheld413) {
// 尝试排空上下文折叠
const drained = contextCollapse.recoverFromOverflow(...)
if (drained.committed > 0) {
state = { ...state, messages: drained.messages }
continue
}
// 尝试响应式压缩
const compacted = await reactiveCompact.tryReactiveCompact(...)
if (compacted) {
// ...
}
}
// 3. Max Output Tokens 恢复
if (maxOutputTokensRecoveryCount < MAX_OUTPUT_TOKENS_RECOVERY_LIMIT) {
const recoveryMessage = createUserMessage({
content: `Output token limit hit. Resume directly...`
})
state = { ...state, messages: [...messages, recoveryMessage] }
continue
}
```
### 7.5 上下文压缩
```typescript
// Snip去除压缩
if (feature('HISTORY_SNIP')) {
const snipResult = snipModule!.snipCompactIfNeeded(messagesForQuery)
messagesForQuery = snipResult.messages
snipTokensFreed = snipResult.tokensFreed
}
// 微压缩
const microcompactResult = await deps.microcompact(messagesForQuery, ...)
messagesForQuery = microcompactResult.messages
// 自动压缩
const { compactionResult } = await deps.autocompact(
messagesForQuery,
toolUseContext,
{ systemPrompt, userContext, systemContext, toolUseContext },
querySource,
tracking,
snipTokensFreed,
)
```
### 7.6 工具使用摘要
```typescript
// 为耗时的 Haiku 调用生成工具使用摘要
if (config.gates.emitToolUseSummaries && toolUseBlocks.length > 0) {
const summary = await generateToolUseSummary({
tools: toolInfoForSummary,
signal: toolUseContext.abortController.signal,
lastAssistantText,
})
// 异步生成,不阻塞下一个 API 调用
nextPendingToolUseSummary = summary.then(s =>
s ? createToolUseSummaryMessage(summary, toolUseIds) : null
)
}
```
## 8. 总结
这七个核心文件共同构成了 Claude Code 的核心架构:
| 文件 | 职责 |
|------|------|
| `main.tsx` | CLI 入口,应用程序初始化 |
| `QueryEngine.ts` | 对话生命周期管理,消息处理 |
| `Tool.ts` | 工具基类和接口定义 |
| `commands.ts` | Slash 命令注册和管理 |
| `context.ts` | 系统/用户上下文收集 |
| `cost-tracker.ts` | Token 成本追踪 |
| `query.ts` | API 调用管道,工具编排 |
理解这些核心模块是深入研究 Claude Code 源码的基础。

View File

@@ -0,0 +1,949 @@
# 工具系统详解
本文件说明:详细介绍 Claude Code 的工具系统,包括所有内置工具的功能、输入 schema、权限模型和核心逻辑。
## 1. 工具系统架构
### 1.1 工具注册表
所有内置工具在 `tools.ts` 中注册:
```typescript
export function getAllBaseTools(): Tools {
return [
AgentTool,
TaskOutputTool,
BashTool,
GlobTool,
GrepTool,
ExitPlanModeV2Tool,
FileReadTool,
FileEditTool,
FileWriteTool,
NotebookEditTool,
WebFetchTool,
TodoWriteTool,
WebSearchTool,
TaskStopTool,
AskUserQuestionTool,
SkillTool,
EnterPlanModeTool,
// ... 更多工具
]
}
```
### 1.2 工具调用流程
```
用户输入/模型决策
checkPermissions() ────► 权限检查
validateInput() ────► 输入验证
call() ───────────► 工具执行
renderToolResultMessage() ────► 结果渲染
```
### 1.3 工具基类接口
所有工具都实现以下核心方法:
| 方法 | 描述 |
|------|------|
| `call(args, context, canUseTool, parentMessage)` | 工具执行入口 |
| `description(input, options)` | 获取工具描述 |
| `inputSchema` | 输入参数 Zod Schema |
| `checkPermissions(input, context)` | 权限检查 |
| `validateInput(input, context)` | 输入验证 |
| `renderToolUseMessage(input, options)` | 渲染工具调用消息 |
| `renderToolResultMessage(content, options)` | 渲染工具结果 |
## 2. BashTool - Shell 命令执行
### 2.1 功能描述
BashTool 是 Claude Code 最核心的工具之一,负责在用户授权下执行 Shell 命令。
### 2.2 输入 Schema
```typescript
const inputSchema = z.object({
command: z.string().describe('要执行的命令'),
cwd: z.string().optional().describe('工作目录'),
timeout: z.number().optional().describe('超时时间(毫秒)'),
})
```
### 2.3 权限模型
**权限检查规则**
1. 检查命令是否匹配 `alwaysAllowRules`
2. 检查命令是否匹配 `alwaysDenyRules`
3. 检查命令是否属于危险命令(如 `rm -rf`
4. 用户确认后执行
**危险命令警告**
- `rm -rf` 类删除命令
- 格式化命令(如 `mkfs`
- 覆盖系统文件
### 2.4 核心逻辑
```typescript
async call({ command, cwd, timeout }, context) {
// 1. 展开路径
const fullCommand = expandPath(command)
// 2. 权限检查
const decision = await checkBashPermission(fullCommand, context)
// 3. 决定是否使用沙箱
const shouldSandbox = await shouldUseSandbox(fullCommand)
// 4. 执行命令
if (shouldSandbox) {
return executeInSandbox(fullCommand, cwd, timeout)
} else {
return executeDirect(fullCommand, cwd, timeout)
}
// 5. 追踪文件变更
if (result.modifiedFiles) {
for (const file of result.modifiedFiles) {
updateFileHistory(file, 'modified')
}
}
}
```
### 2.5 沙箱执行
Claude Code 支持使用沙箱执行危险命令:
```typescript
async function shouldUseSandbox(command: string): Promise<boolean> {
// 检测命令是否危险
const isDangerous = detectDangerousCommand(command)
// 检查用户是否设置了沙箱偏好
const sandboxPreference = getSandboxPreference()
return isDangerous || sandboxPreference === 'always'
}
```
## 3. FileReadTool - 文件读取
### 3.1 功能描述
FileReadTool 用于读取文件内容,支持多种文件类型:
- 纯文本文件
- 图片文件PNG, JPG, GIF, WebP
- PDF 文档
- Jupyter Notebooks
### 3.2 输入 Schema
```typescript
const inputSchema = z.object({
file_path: z.string().describe('要读取的文件绝对路径'),
offset: z.number().int().nonnegative().optional().describe('起始行号'),
limit: z.number().int().positive().optional().describe('读取行数'),
pages: z.string().optional().describe('PDF 页码范围(如 "1-5"'),
})
```
### 3.3 权限模型
- 检查文件路径是否在允许目录下
- 检查是否匹配 deny rules
- 检查是否为会话相关文件(特殊处理)
### 3.4 核心逻辑
```typescript
async call({ file_path, offset = 1, limit, pages }, context) {
const ext = path.extname(file_path).toLowerCase()
// 根据文件类型处理
if (ext === '.ipynb') {
return readNotebook(file_path)
} else if (IMAGE_EXTENSIONS.has(ext)) {
return readImage(file_path)
} else if (ext === '.pdf') {
return readPDF(file_path, pages)
} else {
return readTextFile(file_path, offset, limit)
}
}
```
### 3.5 特殊处理
**Deduplication去重**
- 如果文件未修改且读取范围相同,返回 `file_unchanged` stub
- 避免重复发送相同内容浪费 Token
**内存新鲜度提示**
```typescript
function memoryFileFreshnessNote(mtimeMs: number): string {
const age = Date.now() - mtimeMs
if (age < 60000) return '(updated seconds ago)'
if (age < 3600000) return `(updated ${Math.floor(age/60000)}m ago)`
// ...
}
```
## 4. FileWriteTool - 文件写入
### 4.1 功能描述
FileWriteTool 用于创建或覆盖文件内容。
### 4.2 输入 Schema
```typescript
const inputSchema = z.object({
file_path: z.string().describe('文件路径'),
content: z.string().describe('文件内容'),
})
```
### 4.3 权限模型
- 写入权限检查
- 目录创建权限
- 危险路径保护(如 `/etc``/System`
### 4.4 核心逻辑
```typescript
async call({ file_path, content }, context) {
// 1. 验证路径
const fullPath = expandPath(file_path)
// 2. 安全检查
if (isDangerousPath(fullPath)) {
throw new Error('Cannot write to protected path')
}
// 3. 确保目录存在
const dir = path.dirname(fullPath)
await ensureDirExists(dir)
// 4. 写入文件
await writeFile(fullPath, content)
// 5. 更新文件状态缓存
context.readFileState.set(fullPath, {
content,
timestamp: Date.now(),
})
return { success: true, path: fullPath }
}
```
## 5. FileEditTool - 文件编辑
### 5.1 功能描述
FileEditTool 支持两种编辑模式:
1. **Search/Replace 模式**:通过 old_string 和 new_string 进行替换
2. **Edit 模式**:直接编辑文件内容
### 5.2 输入 Schema
```typescript
const inputSchema = z.object({
file_path: z.string().describe('文件路径'),
old_string: z.string().optional().describe('要替换的文本(精确匹配)'),
new_string: z.string().optional().describe('替换后的文本'),
// 或者使用 partial_diff
partial_diff: z.object({
replacements: z.array(z.object({
old_string: z.string(),
new_string: z.string(),
}))
}).optional()
})
```
### 5.3 权限模型
- 需要有效的 old_string防止意外覆盖
- 不能用于删除整个文件
- 禁止编辑二进制文件
### 5.4 核心逻辑
```typescript
async call({ file_path, old_string, new_string, partial_diff }, context) {
// 1. 读取当前文件内容
const content = await readFile(file_path)
// 2. 执行替换
let newContent: string
if (partial_diff) {
// 批量替换
newContent = content
for (const { old_string, new_string } of partial_diff.replacements) {
newContent = applyReplacement(newContent, old_string, new_string)
}
} else {
// 单次替换
newContent = applyReplacement(content, old_string, new_string)
}
// 3. 验证 old_string 存在且唯一
const occurrences = countOccurrences(content, old_string)
if (occurrences === 0) {
throw new Error('old_string not found in file')
}
if (occurrences > 1) {
throw new Error('old_string appears multiple times, be more specific')
}
// 4. 写入文件
await writeFile(file_path, newContent)
// 5. 更新缓存
context.readFileState.set(file_path, {
content: newContent,
timestamp: Date.now(),
})
}
```
## 6. GlobTool - 文件模式匹配
### 6.1 功能描述
使用 glob 模式查找文件。
### 6.2 输入 Schema
```typescript
const inputSchema = z.object({
pattern: z.string().describe('Glob 模式(如 "**/*.ts"'),
cwd: z.string().optional().describe('搜索根目录'),
})
```
### 6.3 核心逻辑
```typescript
async call({ pattern, cwd }, context) {
// 使用 ripgrep 的 glob 功能实现高性能搜索
const results = await execFile('rg', [
'--files-with-matches',
'--glob', pattern,
cwd || process.cwd()
])
return {
files: results.split('\n').filter(Boolean)
}
}
```
## 7. GrepTool - 代码搜索
### 7.1 功能描述
在代码库中搜索匹配文本。
### 7.2 输入 Schema
```typescript
const inputSchema = z.object({
pattern: z.string().describe('搜索模式(支持正则)'),
cwd: z.string().optional().describe('搜索目录'),
context: z.number().optional().describe('上下文行数'),
file_pattern: z.string().optional().describe('文件过滤模式'),
})
```
### 7.3 核心逻辑
```typescript
async call({ pattern, cwd, context = 3, file_pattern }, context) {
const args = [
'--json',
'-C', context.toString(),
pattern,
]
if (file_pattern) {
args.push('--glob', file_pattern)
}
args.push(cwd || '.')
const results = await execFile('rg', args)
// 解析 JSON 输出
const matches = JSON.parse(results)
return {
matches: matches.map(parseMatch),
count: matches.length
}
}
```
## 8. WebFetchTool - 网页获取
### 8.1 功能描述
获取网页内容。
### 8.2 输入 Schema
```typescript
const inputSchema = z.object({
url: z.string().url().describe('网页 URL'),
})
```
### 8.3 权限模型
**预批准域名列表**
- anthropic.com
- claude.ai
- github.com
- 主要新闻和文档站点
### 8.4 核心逻辑
```typescript
async call({ url }, context) {
// 1. URL 安全检查
if (!isPreapprovedUrl(url)) {
const decision = await context.requestPrompt('web_fetch', url)
if (!decision.approved) {
throw new Error('URL not approved')
}
}
// 2. 获取网页
const response = await fetch(url)
// 3. 解析 HTML
const text = await extractText(response)
// 4. 清理和格式化
return {
content: cleanHtml(text),
title: extractTitle(response),
url,
}
}
```
## 9. WebSearchTool - 网络搜索
### 9.1 功能描述
执行网络搜索。
### 9.2 输入 Schema
```typescript
const inputSchema = z.object({
query: z.string().describe('搜索查询'),
})
```
### 9.3 核心逻辑
```typescript
async call({ query }, context) {
// 使用搜索引擎 API
const results = await searchEngine.query(query)
return {
results: results.map(r => ({
title: r.title,
url: r.url,
snippet: r.snippet,
})),
total: results.length,
}
}
```
## 10. AgentTool - 子 Agent
### 10.1 功能描述
AgentTool 允许 Claude 创建和管理子 Agent 来并行执行任务。
### 10.2 输入 Schema
```typescript
const inputSchema = z.object({
agent: z.enum(['general', 'plan', 'explore', ...]).describe('Agent 类型'),
prompt: z.string().describe('给 Agent 的指令'),
agentId: z.string().optional().describe('现有 Agent ID用于恢复'),
maxTurns: z.number().optional().describe('最大轮次'),
})
```
### 10.3 Agent 类型
| 类型 | 描述 |
|------|------|
| `general` | 通用任务执行 |
| `plan` | 计划制定 |
| `explore` | 代码探索 |
| `verification` | 验证检查 |
### 10.4 核心逻辑
```typescript
async call({ agent, prompt, maxTurns }, context) {
// 1. 创建或恢复 Agent
const agentId = await createSubAgent({
type: agent,
prompt,
maxTurns,
})
// 2. 执行 Agent
const result = await runAgent(agentId, context)
// 3. 返回结果
return {
output: result.output,
agentId,
turns: result.turns,
}
}
```
## 11. SkillTool - 技能执行
### 11.1 功能描述
SkillTool 用于执行用户定义的技能Skills这些技能以 Markdown 文件形式保存在本地目录中。
### 11.2 输入 Schema
```typescript
const inputSchema = z.object({
name: z.string().describe('技能名称'),
args: z.string().optional().describe('传递给技能的参数'),
})
```
### 11.3 技能定义格式
技能目录结构:
```
~/.claude/skills/my-skill/
└── skill.md
```
skill.md 格式:
```markdown
---
name: my-skill
description: 这个技能做什么
---
# My Skill
这个技能用于执行特定任务...
## 使用方法
执行时会运行以下脚本...
```
### 11.4 核心逻辑
```typescript
async call({ name, args }, context) {
// 1. 查找技能定义
const skill = await findSkill(name)
if (!skill) {
throw new Error(`Skill not found: ${name}`)
}
// 2. 解析技能定义
const { prompt, script } = parseSkillDefinition(skill)
// 3. 执行脚本
const output = await executeScript(script, { args })
return {
output,
skillName: name,
}
}
```
## 12. MCPTool - Model Context Protocol
### 12.1 功能描述
MCPTool 是 MCPModel Context Protocol协议的工具包装器允许调用 MCP 服务器提供的工具。
### 12.2 输入 Schema
```typescript
const inputSchema = z.object({
server: z.string().describe('MCP 服务器名称'),
tool: z.string().describe('工具名称'),
arguments: z.record(z.string(), z.unknown()).optional().describe('工具参数'),
})
```
### 12.3 核心逻辑
```typescript
async call({ server, tool, arguments }, context) {
// 1. 获取 MCP 客户端
const client = context.mcpClients.find(c => c.name === server)
if (!client) {
throw new Error(`MCP server not found: ${server}`)
}
// 2. 发送工具调用请求
const result = await client.callTool(tool, arguments)
// 3. 返回结果
return result
}
```
## 13. LSPTool - 语言服务器协议
### 13.1 功能描述
LSPTool 提供对 Language Server Protocol 的访问,用于代码导航、诊断等。
### 13.2 核心功能
- 跳转到定义 (Go to Definition)
- 查找引用 (Find References)
- 代码补全 (Completions)
- 诊断信息 (Diagnostics)
## 14. NotebookEditTool - Jupyter Notebook 编辑
### 14.1 功能描述
NotebookEditTool 专门用于编辑 Jupyter Notebook 文件。
### 14.2 输入 Schema
```typescript
const inputSchema = z.object({
file_path: z.string().describe('Notebook 文件路径'),
cell_id: z.string().optional().describe('要编辑的单元格 ID'),
new_source: z.string().optional().describe('新单元格内容'),
action: z.enum(['insert', 'delete', 'move']).optional().describe('操作类型'),
})
```
## 15. Task 系列工具
### 15.1 概述
Task 系列工具提供完整的任务管理功能:
| 工具 | 描述 |
|------|------|
| `TaskCreateTool` | 创建新任务 |
| `TaskGetTool` | 获取任务详情 |
| `TaskUpdateTool` | 更新任务状态 |
| `TaskListTool` | 列出任务 |
| `TaskStopTool` | 停止任务 |
| `TaskOutputTool` | 获取任务输出 |
### 15.2 TaskCreateTool 输入 Schema
```typescript
const inputSchema = z.object({
description: z.string().describe('任务描述'),
status: z.enum(['pending', 'in_progress', 'completed']).optional(),
priority: z.enum(['low', 'medium', 'high']).optional(),
})
```
### 15.3 任务状态流转
```
pending ──► in_progress ──► completed
│ │
└──────► failed
```
## 16. SendMessageTool - 团队消息
### 16.1 功能描述
SendMessageTool 用于向团队成员发送消息。
### 16.2 输入 Schema
```typescript
const inputSchema = z.object({
recipient: z.string().describe('收件人标识'),
message: z.string().describe('消息内容'),
})
```
## 17. TeamCreateTool - 创建团队
### 17.1 功能描述
TeamCreateTool 创建一个 Agent 团队,团队成员可以协作完成任务。
### 17.2 输入 Schema
```typescript
const inputSchema = z.object({
name: z.string().describe('团队名称'),
members: z.array(z.object({
name: z.string(),
role: z.enum(['coordinator', 'worker', 'reviewer']),
agentType: z.string().optional(),
})).describe('团队成员'),
})
```
### 17.3 团队角色
| 角色 | 描述 |
|------|------|
| `coordinator` | 协调者,负责分配任务 |
| `worker` | 执行者,负责完成任务 |
| `reviewer` | 审核者,负责检查结果 |
## 18. EnterPlanModeTool / ExitPlanModeTool
### 18.1 功能描述
计划模式允许 Claude 在执行前先制定计划,用户确认后再执行。
### 18.2 输入 Schema
```typescript
// EnterPlanModeTool
const inputSchema = z.object({
prompt: z.string().optional().describe('计划提示'),
})
// ExitPlanModeTool
// 无需参数
```
## 19. EnterWorktreeTool / ExitWorktreeTool
### 19.1 功能描述
用于创建和切换 Git Worktree便于在多个分支上同时工作。
### 19.2 输入 Schema
```typescript
// EnterWorktreeTool
const inputSchema = z.object({
branch: z.string().describe('分支名'),
path: z.string().optional().describe('Worktree 路径'),
})
// ExitWorktreeTool
const inputSchema = z.object({
path: z.string().optional().describe('要删除的 Worktree 路径'),
})
```
## 20. ToolSearchTool - 工具搜索
### 20.1 功能描述
ToolSearchTool 允许模型在运行时搜索可用工具,当工具过多时会延迟加载。
### 20.2 输入 Schema
```typescript
const inputSchema = z.object({
query: z.string().describe('搜索查询'),
})
```
### 20.3 延迟加载机制
```typescript
// 当工具数量超过阈值时启用延迟加载
const TOOL_SEARCH_THRESHOLD = 50
if (totalTools > TOOL_SEARCH_THRESHOLD) {
// 工具标记为 shouldDefer: true
// 首次调用时需要通过 ToolSearchTool 激活
}
```
## 21. CronCreateTool - 定时任务
### 21.1 功能描述
CronCreateTool 创建定时执行的任务。
### 21.2 输入 Schema
```typescript
const inputSchema = z.object({
schedule: z.string().describe('Cron 表达式'),
command: z.string().describe('要执行的命令'),
name: z.string().optional().describe('任务名称'),
})
```
## 22. RemoteTriggerTool - 远程触发
### 22.1 功能描述
RemoteTriggerTool 允许从远程触发任务执行。
### 22.2 输入 Schema
```typescript
const inputSchema = z.object({
trigger_id: z.string().describe('触发器 ID'),
payload: z.record(z.string(), z.unknown()).optional().describe('传递的数据'),
})
```
## 23. SleepTool - 延迟执行
### 23.1 功能描述
SleepTool 用于在任务执行中引入延迟。
### 23.2 输入 Schema
```typescript
const inputSchema = z.object({
duration: z.number().describe('延迟时间(秒)'),
})
```
## 24. SyntheticOutputTool - 结构化输出
### 24.1 功能描述
SyntheticOutputTool 用于提供符合 JSON Schema 的结构化输出。
### 24.2 输入 Schema
```typescript
const inputSchema = z.object({
schema: z.record(z.string(), z.unknown()).describe('JSON Schema'),
data: z.record(z.string(), z.unknown()).describe('输出数据'),
})
```
### 24.3 验证机制
```typescript
async call({ schema, data }, context) {
// 使用 Zod 验证数据
const validator = z.object(schema)
const result = validator.safeParse(data)
if (!result.success) {
throw new Error(`Invalid output: ${result.error.message}`)
}
return { validated: result.data }
}
```
## 25. 工具权限系统总结
### 25.1 权限模式
| 模式 | 描述 | 行为 |
|------|------|------|
| `default` | 默认模式 | 询问危险操作 |
| `auto` | 自动模式 | 基于规则自动决定 |
| `bypass` | 绕过模式 | 允许所有操作 |
| `plan` | 计划模式 | 强制计划模式 |
### 25.2 权限检查流程
```
1. validateInput() - 验证输入有效性
2. checkPermissions() - 检查权限规则
├──► alwaysAllow → 返回允许
├──► alwaysDeny → 返回拒绝
└──► 需要询问 → 等待用户确认
```
### 25.3 权限规则匹配
```typescript
// 权限规则支持通配符模式
const rules = {
'Bash(rm *)': 'deny', // 拒绝所有 rm 命令
'Bash(git *)': 'allow', // 允许所有 git 命令
'Read(/home/user/src/*)': 'allow', // 允许读取特定目录
}
```
## 26. 工具渲染系统
### 26.1 渲染方法
| 方法 | 用途 |
|------|------|
| `renderToolUseMessage` | 渲染工具调用消息 |
| `renderToolUseTag` | 渲染工具标签(如超时标记) |
| `renderToolUseProgressMessage` | 渲染进度消息 |
| `renderToolResultMessage` | 渲染工具结果 |
| `renderToolUseErrorMessage` | 渲染错误消息 |
| `renderToolUseRejectedMessage` | 渲染拒绝消息 |
### 26.2 渲染选项
```typescript
interface RenderOptions {
style?: 'condensed' | 'full'
theme?: ThemeName
verbose?: boolean
isTranscriptMode?: boolean
terminalSize?: { columns: number; rows: number }
}
```
## 27. 总结
Claude Code 的工具系统设计遵循以下原则:
1. **一致性**:所有工具实现统一的 Tool 接口
2. **安全性**:细粒度的权限控制和验证
3. **可扩展性**:支持 MCP、插件、技能等多种扩展机制
4. **用户控制**:用户可精确控制每个工具的使用权限
5. **高性能**:支持流式执行、缓存、去重等优化

View File

@@ -0,0 +1,569 @@
# Claude Code 命令系统详解
## 概述
Claude Code 的命令系统是用户与 CLI 交互的核心方式。每个斜杠命令slash command都是一个独立的模块支持懒加载以提高启动性能。命令定义遵循统一的 `Command` 接口,包含元数据和执行逻辑。
## 命令类型
### 1. prompt 类型命令
生成提示词发送给 AI 模型处理。
```typescript
type Command = {
type: 'prompt'
name: string
description: string
contentLength: number
source: 'builtin'
async getPromptForCommand(args): Promise<ContentBlockParam[]>
}
```
### 2. local-jsx 类型命令
渲染本地 React 组件的交互式命令。
```typescript
type Command = {
type: 'local-jsx'
name: string
description: string
load: () => import('./xxx.js')
}
```
### 3. local 类型命令
执行本地逻辑的命令,不涉及 AI 模型。
```typescript
type Command = {
type: 'local'
name: string
description: string
supportsNonInteractive: boolean
load: () => import('./xxx.js')
}
```
---
## 命令详解
### /commit - 创建 Git 提交
**文件位置**: `src/commands/commit.ts`
**功能描述**: 分析当前 Git 状态,生成符合项目规范的提交信息,创建新的 Git 提交。
**触发条件**: 用户输入 `/commit`
**核心逻辑**:
1. 获取当前 Git 状态(`git status``git diff HEAD``git branch --show-current`
2. 获取最近 10 条提交记录以了解项目提交风格
3. 根据变更内容生成提交信息
4. 使用 HEREDOC 语法执行 `git commit`
**安全协议**:
- 禁止更新 git config
- 禁止跳过 hooks除非用户明确要求
- 必须创建新提交,禁止使用 `--amend`
- 禁止提交包含密钥的文件(.env 等)
- 禁止使用需要交互输入的 git 命令(如 `git rebase -i`
**相关文件**:
- `src/commands/commit.ts` - 命令入口
- `src/utils/attribution.js` - 获取归属文本
---
### /review - 代码审查
**文件位置**: `src/commands/review.ts`
**功能描述**: 审查 GitHub Pull Request 的代码变更。
**触发条件**: 用户输入 `/review [PR编号]`
**核心逻辑**:
1. 若未提供 PR 编号,执行 `gh pr list` 显示打开的 PR 列表
2. 若提供 PR 编号,执行 `gh pr view <number>` 获取详情
3. 执行 `gh pr diff <number>` 获取代码差异
4. 分析代码质量、风格、潜在问题、安全性等
5. 提供改进建议
**本地审查提示词** (`LOCAL_REVIEW_PROMPT`):
```
You are an expert code reviewer. Follow these steps:
1. If no PR number is provided, run `gh pr list`
2. Analyze the changes and provide a thorough code review
...
```
**ultrareview 命令**:
- 唯一入口:通过 `/ultrareview` 触发远程 Bug Hunter 路径
- 使用 `~10-20 min` 执行深度 bug 查找
- 需要在 Claude Code 网页版运行
**相关文件**:
- `src/commands/review.ts` - 包含本地 review 和 ultrareview 命令
- `src/commands/review/ultrareviewEnabled.ts` - ultrareview 功能开关
---
### /compact - 对话压缩
**文件位置**: `src/commands/compact/index.ts`, `src/commands/compact/compact.ts`
**功能描述**: 清除对话历史但保留摘要,保持在上下文中。
**触发条件**: 用户输入 `/compact [自定义摘要指令]`
**核心逻辑**:
1. 首先尝试会话内存压缩(无自定义指令时)
2. 若有自定义指令或会话内存压缩不适用,执行传统的压缩流程:
- 执行 PreCompact hooks
- 运行 microcompact 减少 token 数量
- 调用 `compactConversation` 生成摘要
- 执行 PostCompact hooks
3. 重置文件状态缓存
4. 生成压缩边界标记和摘要消息
**压缩类型**:
- **完整压缩**: 总结整个对话历史
- **部分压缩**: 围绕选定消息索引进行压缩
- `from`: 总结索引之后的消息,保留早期消息
- `up_to`: 总结索引之前的消息,保留后续消息
**相关服务**:
- `src/services/compact/compact.ts` - 核心压缩逻辑
- `src/services/compact/microCompact.ts` - 微压缩
- `src/services/compact/sessionMemoryCompact.ts` - 会话内存压缩
- `src/services/compact/postCompactCleanup.ts` - 压缩后清理
---
### /mcp - MCP 服务器管理
**文件位置**: `src/commands/mcp/index.ts`
**功能描述**: 管理 MCPModel Context Protocol服务器连接。
**触发条件**: 用户输入 `/mcp [enable|disable [服务器名称]]`
**核心逻辑**:
1. 懒加载 MCP 管理界面组件
2. 支持启用/禁用特定 MCP 服务器
3. 管理 MCP 服务器配置
**MCP 配置类型** (`Transport`):
- `stdio` - 标准 I/O 传输
- `sse` - Server-Sent Events
- `http` - HTTP 传输
- `ws` - WebSocket
- `sdk` - SDK 传输
**相关服务**:
- `src/services/mcp/useManageMCPConnections.ts` - MCP 连接管理 Hook
- `src/services/mcp/types.ts` - MCP 类型定义
- `src/services/mcp/client.ts` - MCP 客户端实现
---
### /config - 配置面板
**文件位置**: `src/commands/config/index.ts`
**功能描述**: 打开配置面板,管理 Claude Code 设置。
**别名**: `/settings`
**触发条件**: 用户输入 `/config`
**核心逻辑**:
- 懒加载配置面板 React 组件
- 支持用户偏好设置、项目设置等
---
### /doctor - 诊断检查
**文件位置**: `src/commands/doctor/index.ts`
**功能描述**: 诊断和验证 Claude Code 安装状态和设置。
**触发条件**: 用户输入 `/doctor`
**核心逻辑**:
1. 检查环境变量 `DISABLE_DOCTOR_COMMAND` 确认是否启用
2. 懒加载诊断组件
3. 执行多项检查:安装完整性、配置正确性、认证状态等
---
### /login - 登录
**文件位置**: `src/commands/login/index.ts`
**功能描述**: 使用 Anthropic 账户登录或切换账户。
**触发条件**: 用户输入 `/login`
**核心逻辑**:
1. 检测是否已有 API Key 认证(`hasAnthropicApiKeyAuth()`
2. 根据认证状态显示不同描述
3. 检查环境变量 `DISABLE_LOGIN_COMMAND`
4. 懒加载登录组件
---
### /logout - 登出
**文件位置**: `src/commands/logout/index.ts`
**功能描述**: 从 Anthropic 账户登出。
**触发条件**: 用户输入 `/logout`
**核心逻辑**:
1. 检查环境变量 `DISABLE_LOGOUT_COMMAND`
2. 执行登出逻辑,清除认证信息
---
### /memory - 记忆文件编辑
**文件位置**: `src/commands/memory/index.ts`
**功能描述**: 编辑 Claude 记忆文件。
**触发条件**: 用户输入 `/memory`
**核心逻辑**:
- 懒加载记忆编辑器组件
---
### /skills - 技能列表
**文件位置**: `src/commands/skills/index.ts`
**功能描述**: 列出可用的技能Skills
**触发条件**: 用户输入 `/skills`
**核心逻辑**:
- 懒加载技能列表组件
- 显示所有已安装和可用的技能
---
### /tasks - 后台任务管理
**文件位置**: `src/commands/tasks/index.ts`
**功能描述**: 列出和管理后台任务。
**别名**: `/bashes`
**触发条件**: 用户输入 `/tasks`
**核心逻辑**:
- 懒加载任务管理界面
- 显示正在运行、完成、失败的任务
---
### /vim - Vim 模式切换
**文件位置**: `src/commands/vim/index.ts`, `src/commands/vim/vim.ts`
**功能描述**: 在 Vim 和 Normal 编辑模式之间切换。
**触发条件**: 用户输入 `/vim`
**核心逻辑**:
- 切换 REPL 的编辑模式
- 仅在交互式会话中可用
---
### /diff - 变更查看
**文件位置**: `src/commands/diff/index.ts`
**功能描述**: 查看未提交的变更和每轮对话的差异。
**触发条件**: 用户输入 `/diff`
**核心逻辑**:
- 懒加载差异查看组件
- 显示工作区与上次提交的差异
---
### /cost - 成本显示
**文件位置**: `src/commands/cost/index.ts`, `src/commands/cost/cost.ts`
**功能描述**: 显示当前会话的总成本和持续时间。
**触发条件**: 用户输入 `/cost`
**隐藏条件**:
- Claude.ai 订阅用户Ants 除外)默认隐藏
- 订阅用户可看到成本明细
---
### /theme - 主题切换
**文件位置**: `src/commands/theme/index.ts`
**功能描述**: 更改终端主题。
**触发条件**: 用户输入 `/theme`
**核心逻辑**:
- 懒加载主题选择组件
---
### /context - 上下文可视化
**文件位置**: `src/commands/context/index.ts`
**功能描述**: 将当前上下文使用情况可视化为彩色网格。
**触发条件**: 用户输入 `/context`
**交互模式变体**:
- `context` - 交互式彩色网格(仅交互式会话)
- `context` (非交互式) - 纯文本上下文使用情况
---
### /pr_comments - PR 评论获取
**文件位置**: `src/commands/pr_comments/index.ts`
**功能描述**: 获取 GitHub Pull Request 的评论。
**触发条件**: 用户输入 `/pr-comments [参数]`
**核心逻辑**:
1. 使用 `gh pr view` 获取 PR 信息
2. 使用 `gh api` 获取 PR 级评论
3. 使用 `gh api` 获取代码审查评论
4. 格式化显示评论列表
**备用方案**: 若市场不可用,使用内置提示词直接调用 GitHub CLI
---
### /resume - 恢复对话
**文件位置**: `src/commands/resume/index.ts`
**功能描述**: 恢复之前的对话。
**别名**: `/continue`
**触发条件**: 用户输入 `/resume [对话ID或搜索词]`
**核心逻辑**:
- 懒加载恢复界面
- 支持按 ID 或关键词搜索历史对话
---
### /share - 分享会话
**文件位置**: `src/commands/share/index.ts`
**功能描述**: 分享当前会话。
**触发条件**: 用户输入 `/share`
**核心逻辑**:
- 生成分享链接或会话导出
---
### /desktop - 桌面客户端
**文件位置**: `src/commands/desktop/index.ts`
**功能描述**: 在 Claude Desktop 中继续当前会话。
**别名**: `/app`
**触发条件**: 用户输入 `/desktop`
**平台限制**:
- macOS: 完全支持
- Windows (x64): 支持
- 其他平台: 隐藏
---
### /mobile - 移动应用
**文件位置**: `src/commands/mobile/index.ts`
**功能描述**: 显示下载 Claude 移动应用的二维码。
**别名**: `/ios`, `/android`
**触发条件**: 用户输入 `/mobile`
**核心逻辑**:
- 懒加载移动应用下载界面组件
- 显示 iOS 和 Android 的下载选项
---
### /permissions - 权限管理
**文件位置**: `src/commands/permissions/index.ts`
**功能描述**: 管理允许和拒绝的工具权限规则。
**别名**: `/allowed-tools`
**触发条件**: 用户输入 `/permissions`
**核心逻辑**:
- 懒加载权限管理界面
- 配置 `alwaysAllowRules` 等权限规则
---
### /agents - Agent 配置管理
**文件位置**: `src/commands/agents/index.ts`
**功能描述**: 管理 Agent 配置。
**触发条件**: 用户输入 `/agents`
**核心逻辑**:
- 懒加载 Agent 管理界面
- 支持多 Agent 配置
---
### /exit - 退出 REPL
**文件位置**: `src/commands/exit/index.ts`
**功能描述**: 退出 REPL 会话。
**别名**: `/quit`
**触发条件**: 用户输入 `/exit`
**特性**:
- `immediate: true` - 立即执行,不等待 AI 响应
---
### /bridge - 远程控制
**文件位置**: `src/commands/bridge/index.ts`
**功能描述**: 连接此终端进行远程控制会话。
**别名**: `/rc`
**触发条件**: 用户输入 `/remote-control [名称]`
**条件限制**:
- 需要启用 `BRIDGE_MODE` 功能
- 需要 `isBridgeEnabled()` 返回 true
**核心逻辑**:
- 建立与 Claude Code 网页版的桥接连接
- 支持远程会话控制
---
## 命令注册机制
命令通过 `src/commands.js` 统一注册和管理:
```typescript
export interface Command {
type: 'prompt' | 'local-jsx' | 'local'
name: string
description: string
aliases?: string[]
load?: () => Promise<any>
getPromptForCommand?: (args: string, context: CommandContext) => Promise<ContentBlockParam[]>
allowedTools?: string[]
contentLength?: number
progressMessage?: string
source?: 'builtin'
isEnabled?: () => boolean
isHidden?: boolean
supportsNonInteractive?: boolean
argumentHint?: string
}
```
## 懒加载机制
大多数命令使用懒加载模式:
```typescript
const command = {
type: 'local-jsx',
name: 'example',
load: () => import('./example.js'),
}
```
这确保只有实际使用的命令才会加载其代码,优化启动性能。
## 权限控制
某些命令支持 `isEnabled()` 方法动态控制可用性:
```typescript
const command = {
type: 'local',
name: 'doctor',
isEnabled: () => !isEnvTruthy(process.env.DISABLE_DOCTOR_COMMAND),
load: () => import('./doctor.js'),
}
```
---
## 相关源码文件
| 命令 | 源码路径 |
|------|---------|
| commit | `src/commands/commit.ts` |
| review | `src/commands/review.ts` |
| compact | `src/commands/compact/` |
| mcp | `src/commands/mcp/` |
| config | `src/commands/config/` |
| doctor | `src/commands/doctor/` |
| login | `src/commands/login/` |
| logout | `src/commands/logout/` |
| memory | `src/commands/memory/` |
| skills | `src/commands/skills/` |
| tasks | `src/commands/tasks/` |
| vim | `src/commands/vim/` |
| diff | `src/commands/diff/` |
| cost | `src/commands/cost/` |
| theme | `src/commands/theme/` |
| context | `src/commands/context/` |
| resume | `src/commands/resume/` |
| share | `src/commands/share/` |
| desktop | `src/commands/desktop/` |
| mobile | `src/commands/mobile/` |
| permissions | `src/commands/permissions/` |
| agents | `src/commands/agents/` |
| exit | `src/commands/exit/` |
| bridge | `src/commands/bridge/` |

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` |

View File

@@ -0,0 +1,659 @@
# Claude Code 桥接系统详解
## 概述
桥接系统Bridge是 Claude Code CLI 与 IDE 扩展VS Code, JetBrains之间的双向通信层。它使 IDE 能够:
1. 在远程设备上启动 Claude Code 会话
2. 将用户输入转发到 Claude Code
3. 显示 Claude Code 的输出和工具执行结果
4. 处理权限请求和响应
---
## 核心架构
```
┌──────────────────────────────────────────────────────────────┐
│ IDE Extension (VS Code / JetBrains) │
│ - 用户界面 │
│ - 输入处理 │
│ - 输出展示 │
└──────────────────────────────────────────────────────────────┘
│ WebSocket / HTTP
┌──────────────────────────────────────────────────────────────┐
│ Bridge Layer │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ bridgeMain.ts │ │
│ │ 入口点,管理桥接生命周期 │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ bridgeMessaging.ts │ │
│ │ 消息处理、入口路由、流量控制 │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ replBridge.ts │ │
│ │ REPL 会话桥接 │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ sessionRunner.ts │ │
│ │ 会话执行管理 │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ jwtUtils.ts │ │
│ │ JWT 认证工具 │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ bridgePermissionCallbacks.ts │ │
│ │ 权限回调处理 │ │
│ └────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────┐
│ Claude Code CLI (子进程) │
│ - 命令处理 │
│ - 工具执行 │
│ - API 调用 │
└──────────────────────────────────────────────────────────────┘
```
---
## 1. bridgeMain.ts - 桥接主入口
**文件位置**: `src/bridge/bridgeMain.ts`
### 核心类型
```typescript
export type BridgeState = 'ready' | 'connected' | 'reconnecting' | 'failed'
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>
}
```
### 核心函数
```typescript
export async function initBridgeCore(
params: BridgeCoreParams
): Promise<BridgeCoreHandle | null>
```
**BridgeCoreParams 输入参数**:
```typescript
type BridgeCoreParams = {
dir: string // 工作目录
machineName: string // 机器名称
branch: string // Git 分支
gitRepoUrl: string | null // Git 仓库 URL
title: string // 会话标题
baseUrl: string // API 基础 URL
sessionIngressUrl: string // 会话入口 URL
workerType: string // 工作器类型
getAccessToken: () => string | undefined
createSession: (opts: {...}) => Promise<string | null>
archiveSession: (sessionId: string) => Promise<void>
toSDKMessages?: (messages: Message[]) => SDKMessage[]
onAuth401?: (staleAccessToken: string) => Promise<boolean>
getPollIntervalConfig?: () => PollIntervalConfig
initialMessages?: Message[]
previouslyFlushedUUIDs?: Set<string>
onInboundMessage?: (msg: SDKMessage) => void
onPermissionResponse?: (response: SDKControlResponse) => void
onInterrupt?: () => void
onSetModel?: (model: string | undefined) => void
onSetMaxThinkingTokens?: (maxTokens: number | null) => void
onSetPermissionMode?: (mode: PermissionMode) => {...}
onStateChange?: (state: BridgeState, detail?: string) => void
onUserMessage?: (text: string, sessionId: string) => boolean
perpetual?: boolean
initialSSESequenceNum?: number
}
```
### 桥接生命周期
1. **注册桥接环境**
```typescript
const reg = await api.registerBridgeEnvironment(bridgeConfig)
environmentId = reg.environment_id
environmentSecret = reg.environment_secret
```
2. **创建会话**
```typescript
const createdSessionId = await createSession({...})
currentSessionId = createdSessionId
```
3. **启动工作轮询循环**
```typescript
void startWorkPollLoop(pollOpts)
```
4. **处理入口消息**
```typescript
transport.onData(data => {
handleIngressMessage(data, recentPostedUUIDs, recentInboundUUIDs, ...)
})
```
5. **清理**
```typescript
await doTeardownImpl()
```
---
## 2. bridgeMessaging.ts - 消息处理
**文件位置**: `src/bridge/bridgeMessaging.ts`
### 消息入口处理
```typescript
export function handleIngressMessage(
data: string,
recentPostedUUIDs: BoundedUUIDSet,
recentInboundUUIDs: BoundedUUIDSet,
onInboundMessage: ((msg: SDKMessage) => void | Promise<void>) | undefined,
onPermissionResponse?: ((response: SDKControlResponse) => void) | undefined,
onControlRequest?: ((request: SDKControlRequest) => void) | undefined,
): void
```
**消息类型判断**:
```typescript
export function isSDKMessage(value: unknown): value is SDKMessage
export function isSDKControlResponse(value: unknown): value is SDKControlResponse
export function isSDKControlRequest(value: unknown): value is SDKControlRequest
```
### 可桥接消息过滤
```typescript
export function isEligibleBridgeMessage(m: Message): boolean {
// 排除虚拟消息
if ((m.type === 'user' || m.type === 'assistant') && m.isVirtual) {
return false
}
return (
m.type === 'user' ||
m.type === 'assistant' ||
(m.type === 'system' && m.subtype === 'local_command')
)
}
```
### 服务器控制请求处理
```typescript
export function handleServerControlRequest(
request: SDKControlRequest,
handlers: ServerControlRequestHandlers,
): void
```
**支持的请求类型**:
- `initialize` - 初始化
- `set_model` - 设置模型
- `set_max_thinking_tokens` - 设置最大思考 token
- `set_permission_mode` - 设置权限模式
- `interrupt` - 中断
### 标题文本提取
```typescript
export function extractTitleText(m: Message): string | undefined
// 从用户消息中提取标题
```
### BoundedUUIDSet - UUID 环形缓冲区
```typescript
export class BoundedUUIDSet {
constructor(capacity: number)
add(uuid: string): void
has(uuid: string): boolean
clear(): void
}
```
**用途**:
- 消息回音过滤
- 重复消息去重
---
## 3. replBridge.ts - REPL 会话桥接
**文件位置**: `src/bridge/replBridge.ts`
### 核心接口
```typescript
export type ReplBridgeTransport = {
setOnConnect(callback: () => void): void
setOnData(callback: (data: string) => void): void
setOnClose(callback: (code: number | undefined) => void): void
connect(): void
write(message: object): Promise<void>
writeBatch(messages: object[]): Promise<void>
close(): void
getStateLabel(): string
getLastSequenceNum(): number
isConnectedStatus(): boolean
}
```
### 传输类型
#### 1. HybridTransport (v1)
- WebSocket 读取
- HTTP POST 写入
- 目标: Session-Ingress
#### 2. SSETransport (v2)
- Server-Sent Events 读取
- HTTP POST 写入
- 目标: CCR (/worker/*)
### 初始化流程
```typescript
export async function initReplBridge(
params: InitBridgeOptions
): Promise<ReplBridgeHandle | null>
```
### 消息写入
```typescript
writeMessages(messages: Message[]) {
// 过滤可桥接消息
const filtered = messages.filter(m =>
isEligibleBridgeMessage(m) &&
!initialMessageUUIDs.has(m.uuid) &&
!recentPostedUUIDs.has(m.uuid)
)
// 转换并发送
const sdkMessages = toSDKMessages(filtered)
void transport.writeBatch(events)
}
```
---
## 4. jwtUtils.ts - JWT 认证
**文件位置**: `src/bridge/jwtUtils.ts`
### JWT 解析
```typescript
export function decodeJwtPayload(token: string): unknown | null {
// 剥离 sk-ant-si- 前缀
const jwt = token.startsWith('sk-ant-si-')
? token.slice('sk-ant-si-'.length)
: token
// 解析 payload (不验证签名)
const parts = jwt.split('.')
if (parts.length !== 3 || !parts[1]) return null
return jsonParse(Buffer.from(parts[1], 'base64url').toString('utf8'))
}
```
### Token 刷新调度器
```typescript
export function createTokenRefreshScheduler({
getAccessToken,
onRefresh,
label,
refreshBufferMs = 5 * 60 * 1000, // 5 分钟
}): {
schedule: (sessionId: string, token: string) => void
scheduleFromExpiresIn: (sessionId: string, expiresInSeconds: number) => void
cancel: (sessionId: string) => void
cancelAll: () => void
}
```
**刷新策略**:
- 过期前 5 分钟刷新(默认)
- 指数退避重试
- 最多 3 次连续失败
---
## 5. sessionRunner.ts - 会话执行管理
**文件位置**: `src/bridge/sessionRunner.ts`
### 核心类型
```typescript
type SessionSpawnerDeps = {
execPath: string
scriptArgs: string[]
env: NodeJS.ProcessEnv
verbose: boolean
sandbox: boolean
debugFile?: string
permissionMode?: string
onDebug: (msg: string) => void
onActivity?: (sessionId: string, activity: SessionActivity) => void
onPermissionRequest?: (sessionId: string, request: PermissionRequest, accessToken: string) => void
}
export function createSessionSpawner(deps: SessionSpawnerDeps): SessionSpawner
```
### 会话句柄
```typescript
export type SessionHandle = {
sessionId: string
done: Promise<SessionDoneStatus>
activities: SessionActivity[]
accessToken: string
lastStderr: string[]
currentActivity: SessionActivity | null
kill(): void
forceKill(): void
writeStdin(data: string): void
updateAccessToken(token: string): void
}
```
### 活动提取
```typescript
function extractActivities(
line: string,
sessionId: string,
onDebug: (msg: string) => void
): SessionActivity[]
```
**活动类型**:
```typescript
type SessionActivity =
| { type: 'tool_start'; summary: string; timestamp: number }
| { type: 'text'; summary: string; timestamp: number }
| { type: 'result'; summary: string; timestamp: number }
| { type: 'error'; summary: string; timestamp: number }
```
### 子进程管理
```typescript
const child: ChildProcess = spawn(deps.execPath, args, {
cwd: dir,
stdio: ['pipe', 'pipe', 'pipe'],
env,
windowsHide: true,
})
```
**环境变量设置**:
```typescript
const env: NodeJS.ProcessEnv = {
...deps.env,
CLAUDE_CODE_OAUTH_TOKEN: undefined,
CLAUDE_CODE_ENVIRONMENT_KIND: 'bridge',
CLAUDE_CODE_SESSION_ACCESS_TOKEN: opts.accessToken,
CLAUDE_CODE_USE_CCR_V2: opts.useCcrV2 ? '1' : undefined,
CLAUDE_CODE_WORKER_EPOCH: String(opts.workerEpoch),
}
```
---
## 6. bridgePermissionCallbacks.ts - 权限回调
**文件位置**: `src/bridge/bridgePermissionCallbacks.ts`
### 权限响应类型
```typescript
type BridgePermissionResponse = {
behavior: 'allow' | 'deny'
updatedInput?: Record<string, unknown>
updatedPermissions?: PermissionUpdate[]
message?: string
}
```
### 回调接口
```typescript
type BridgePermissionCallbacks = {
sendRequest(
requestId: string,
toolName: string,
input: Record<string, unknown>,
toolUseId: string,
description: string,
permissionSuggestions?: PermissionUpdate[],
blockedPath?: string
): void
sendResponse(requestId: string, response: BridgePermissionResponse): void
cancelRequest(requestId: string): void
onResponse(
requestId: string,
handler: (response: BridgePermissionResponse) => void
): () => void // 返回取消订阅函数
}
```
---
## 7. replBridgeHandle.ts - REPL 桥接句柄
**文件位置**: `src/bridge/replBridgeHandle.ts`
### 句柄类型
```typescript
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>
}
```
---
## 8. replBridgeTransport.ts - 传输层实现
**文件位置**: `src/bridge/replBridgeTransport.ts`
### 工厂函数
```typescript
export function createV1ReplTransport(
transport: HybridTransport
): ReplBridgeTransport
export function createV2ReplTransport(opts: {
sessionUrl: string
ingressToken: string
sessionId: string
initialSequenceNum: number
}): Promise<ReplBridgeTransport>
```
---
## 9. 入口消息处理流程
```
IDE Extension
│ 1. 用户输入
┌─────────────────┐
│ WS 连接 │
└─────────────────┘
┌─────────────────────────────────────────┐
│ handleIngressMessage() │
│ │
│ 1. 解析 JSON │
│ 2. 检查 UUID (回音/重复过滤) │
│ 3. 分发消息类型 │
│ - user → onInboundMessage │
│ - control_response → onPermission │
│ - control_request → onControlRequest │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ Claude Code CLI (子进程) │
│ │
│ - 执行工具 │
│ - AI 推理 │
│ - 返回结果 │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ writeMessages() / writeSdkMessages() │
│ │
│ 1. 过滤消息 │
│ 2. 转换为 SDK 格式 │
│ 3. 通过 transport.writeBatch() 发送 │
└─────────────────────────────────────────┘
IDE Extension (WebSocket 订阅)
显示输出
```
---
## 10. 权限请求流程
```
Claude Code CLI
▼ (can_use_tool 请求)
┌─────────────────────────────────────────┐
│ BridgePermissionCallbacks │
│ │
│ sendRequest(requestId, toolName, input) │
└─────────────────────────────────────────┘
│ WebSocket / HTTP
┌─────────────────────────────────────────┐
│ IDE Extension │
│ │
│ 显示权限对话框 │
│ 用户允许/拒绝 │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ sendResponse(requestId, response) │
│ │
│ response: { │
│ behavior: 'allow' | 'deny', │
│ updatedInput?, │
│ updatedPermissions? │
│ } │
└─────────────────────────────────────────┘
onResponse() 回调
CLI 继续执行或中止
```
---
## 11. 关键配置
### 轮询配置
```typescript
const DEFAULT_POLL_CONFIG = {
poll_interval_ms_not_at_capacity: 5000, // 5 秒
poll_interval_ms_at_capacity: 120000, // 2 分钟
reclaim_older_than_ms: 5 * 60 * 1000, // 5 分钟
non_exclusive_heartbeat_interval_ms: 30000, // 30 秒
session_keepalive_interval_v2_ms: 120000, // 2 分钟
}
```
### 重连策略
```typescript
const MAX_RECONNECT_ATTEMPTS = 5
const INITIAL_BACKOFF_MS = 1000
const MAX_BACKOFF_MS = 30000
```
### UUID 缓冲区容量
```typescript
const recentPostedUUIDs = new BoundedUUIDSet(2000)
const recentInboundUUIDs = new BoundedUUIDSet(2000)
```
---
## 相关源码文件
| 文件 | 功能 |
|------|------|
| `bridgeMain.ts` | 桥接主入口和生命周期管理 |
| `bridgeMessaging.ts` | 消息处理、路由、流量控制 |
| `replBridge.ts` | REPL 会话桥接 |
| `replBridgeTransport.ts` | 传输层实现 |
| `sessionRunner.ts` | 子进程会话管理 |
| `jwtUtils.ts` | JWT 解析和刷新调度 |
| `bridgePermissionCallbacks.ts` | 权限回调接口 |
| `replBridgeHandle.ts` | 句柄类型定义 |
| `bridgeApi.ts` | 桥接 API 客户端 |
| `pollConfig.ts` | 轮询配置 |
| `flushGate.ts` | 刷新门控 |
| `capacityWake.ts` | 容量唤醒机制 |

View File

@@ -0,0 +1,655 @@
# Claude Code 权限系统详解
## 概述
Claude Code 的权限系统管理工具调用的授权流程。当 Claude 尝试执行危险操作(如运行 Bash 命令、写入文件)时,系统会请求用户确认。权限系统支持多种授权模式和来源,确保用户对工具执行有完全控制。
---
## 核心架构
```
┌─────────────────────────────────────────────────────────────────┐
│ 权限请求入口 │
│ │
│ hasPermissionsToUseTool(tool, input, context, message, id) │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 权限模式检查 (PermissionMode) │
│ │
│ default | plan | bypassPermissions | auto | localAssistant │
└─────────────────────────────────────────────────────────────────┘
┌───────────────┼───────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Coordinator │ │ Interactive │ │ Swarm Worker │
│ Handler │ │ Handler │ │ Handler │
└──────────────┘ └──────────────┘ └──────────────┘
│ │ │
└───────────────┼───────────────┘
┌──────────────────────────────────────┐
│ 权限决策结果 │
│ │
│ allow | deny | ask | skip │
└──────────────────────────────────────┘
```
---
## 1. 权限模式 (PermissionMode)
**文件位置**: `src/utils/permissions/PermissionMode.ts`
### 模式类型
```typescript
type PermissionMode =
| 'default' // 标准交互式权限确认
| 'plan' // 计划模式,只读操作
| 'bypassPermissions' // 跳过所有权限检查
| 'auto' // 自动批准基于分类器
| 'localAssistant' // 本地助手模式
```
### 模式转换
```typescript
export function transitionPermissionMode(
from: PermissionMode,
to: PermissionMode,
options?: { skipAutoGate?: boolean }
): { ok: true } | { ok: false; error: string }
```
---
## 2. PermissionContext - 权限上下文
**文件位置**: `src/hooks/toolPermission/PermissionContext.ts`
### 创建权限上下文
```typescript
function createPermissionContext(
tool: ToolType,
input: Record<string, unknown>,
toolUseContext: ToolUseContext,
assistantMessage: AssistantMessage,
toolUseID: string,
setToolPermissionContext: (context: ToolPermissionContext) => void,
queueOps?: PermissionQueueOps,
)
```
### 上下文方法
```typescript
type PermissionContext = {
// 工具信息
tool: ToolType
input: Record<string, unknown>
toolUseContext: ToolUseContext
assistantMessage: AssistantMessage
messageId: string
toolUseID: string
// 日志记录
logDecision(args: PermissionDecisionArgs, opts?: {...}): void
logCancelled(): void
// 权限持久化
async persistPermissions(updates: PermissionUpdate[]): Promise<boolean>
// 决策构建
buildAllow(
updatedInput: Record<string, unknown>,
opts?: {...}
): PermissionAllowDecision
buildDeny(
message: string,
decisionReason: PermissionDecisionReason
): PermissionDenyDecision
// 用户处理
async handleUserAllow(
updatedInput: Record<string, unknown>,
permissionUpdates: PermissionUpdate[],
feedback?: string,
...
): Promise<PermissionAllowDecision>
// Hook 执行
async runHooks(
permissionMode: string | undefined,
suggestions: PermissionUpdate[] | undefined,
updatedInput?: Record<string, unknown>,
...
): Promise<PermissionDecision | null>
// 分类器尝试
async tryClassifier(
pendingClassifierCheck: PendingClassifierCheck | undefined,
updatedInput: Record<string, unknown> | undefined
): Promise<PermissionDecision | null>
// 队列操作
pushToQueue(item: ToolUseConfirm): void
removeFromQueue(): void
updateQueueItem(patch: Partial<ToolUseConfirm>): void
// 中止处理
resolveIfAbort(resolve: (decision: PermissionDecision) => void): boolean
cancelAndAbort(
feedback?: string,
isAbort?: boolean,
contentBlocks?: ContentBlockParam[]
): PermissionDecision
}
```
---
## 3. 权限决策类型
**文件位置**: `src/types/permissions.ts`
### 决策类型
```typescript
type PermissionDecision =
| { behavior: 'allow'; updatedInput?: Record<string, unknown>; ... }
| { behavior: 'deny'; message: string; ... }
| { behavior: 'ask' }
| { behavior: 'skip' }
```
### 决策来源
```typescript
type PermissionDecisionSource =
| { type: 'hook'; permanent?: boolean }
| { type: 'user'; permanent: boolean }
| { type: 'classifier' }
| 'config' // 配置自动允许
```
### 待处理分类器检查
```typescript
type PendingClassifierCheck = {
input: Record<string, unknown>
command: string
// ...
}
```
---
## 4. 权限处理器
### 4.1 Coordinator Handler
**文件位置**: `src/hooks/toolPermission/handlers/coordinatorHandler.ts`
用于协调者工作进程coordinator worker的权限处理流程。
```typescript
async function handleCoordinatorPermission(
params: CoordinatorPermissionParams
): Promise<PermissionDecision | null>
```
**处理流程**:
1. **尝试权限 Hooks**(快速,本地)
```typescript
const hookResult = await ctx.runHooks(
permissionMode,
suggestions,
updatedInput
)
if (hookResult) return hookResult
```
2. **尝试分类器**(慢速,推理)
```typescript
const classifierResult = feature('BASH_CLASSIFIER')
? await ctx.tryClassifier?.(pendingClassifierCheck, updatedInput)
: null
if (classifierResult) return classifierResult
```
3. **降级到交互式对话框**
```typescript
return null // 交给交互式处理
```
### 4.2 Interactive Handler
**文件位置**: `src/hooks/toolPermission/handlers/interactiveHandler.ts`
用于主代理的交互式权限处理。
```typescript
function handleInteractivePermission(
params: InteractivePermissionParams,
resolve: (decision: PermissionDecision) => void,
): void
```
**处理流程**:
1. **推送确认队列项**
```typescript
ctx.pushToQueue({
assistantMessage,
tool,
description,
input: displayInput,
toolUseID,
permissionResult: result,
permissionPromptStartTimeMs,
onUserInteraction: () => { ... },
onAbort: () => { ... },
onAllow: () => { ... },
onReject: () => { ... },
recheckPermission: () => { ... },
})
```
2. **桥接权限转发**(远程控制)
```typescript
if (bridgeCallbacks && bridgeRequestId) {
bridgeCallbacks.sendRequest(
bridgeRequestId,
ctx.tool.name,
displayInput,
ctx.toolUseID,
description,
result.suggestions,
result.blockedPath
)
}
```
3. **通道权限转发**KAIROS
```typescript
if (channelCallbacks && !ctx.tool.requiresUserInteraction?.()) {
// 发送到通道Telegram, iMessage 等)
client.notification({
method: CHANNEL_PERMISSION_REQUEST_METHOD,
params
})
}
```
4. **异步 Hook 执行**
```typescript
void (async () => {
const hookDecision = await ctx.runHooks(...)
if (hookDecision && claim()) {
resolveOnce(hookDecision)
}
})()
```
5. **异步分类器执行**
```typescript
if (feature('BASH_CLASSIFIER') && result.pendingClassifierCheck) {
setClassifierChecking(ctx.toolUseID)
void executeAsyncClassifierCheck(...)
}
```
### 4.3 Swarm Worker Handler
**文件位置**: `src/hooks/toolPermission/handlers/swarmWorkerHandler.ts`
用于 Swarm Worker 的权限处理(简化的仅拒绝处理)。
---
## 5. 权限回调 (Bridge Permission Callbacks)
**文件位置**: `src/bridge/bridgePermissionCallbacks.ts`
### 回调接口
```typescript
type BridgePermissionCallbacks = {
sendRequest(
requestId: string,
toolName: string,
input: Record<string, unknown>,
toolUseId: string,
description: string,
permissionSuggestions?: PermissionUpdate[],
blockedPath?: string,
): void
sendResponse(requestId: string, response: BridgePermissionResponse): void
cancelRequest(requestId: string): void
onResponse(
requestId: string,
handler: (response: BridgePermissionResponse) => void,
): () => void
}
```
### 权限响应
```typescript
type BridgePermissionResponse = {
behavior: 'allow' | 'deny'
updatedInput?: Record<string, unknown>
updatedPermissions?: PermissionUpdate[]
message?: string
}
```
---
## 6. 权限规则管理
### 6.1 PermissionUpdate
**文件位置**: `src/utils/permissions/PermissionUpdateSchema.ts`
```typescript
type PermissionUpdate = {
destination: 'alwaysAllowRules' | 'alwaysDenyRules' | 'command'
rule: {
tool: string
input?: Record<string, unknown>
matchers?: InputMatcher[]
}
Permanente: boolean
}
```
### 6.2 规则应用
```typescript
export function applyPermissionUpdates(
context: ToolPermissionContext,
updates: PermissionUpdate[]
): ToolPermissionContext
```
### 6.3 规则持久化
```typescript
export function persistPermissionUpdates(updates: PermissionUpdate[]): void
export function supportsPersistence(
destination: 'alwaysAllowRules' | 'alwaysDenyRules' | 'command'
): boolean
```
---
## 7. Bash 分类器
**文件位置**: `src/tools/BashTool/bashPermissions.ts`
### 分类器决策
```typescript
type ClassifierDecision =
| { type: 'classifier'; classifier: 'auto-mode'; reason: string }
| { type: 'classifier'; classifier: 'pattern-match'; reason: string }
| { type: 'user-defined'; reason: string }
| { type: 'deny'; reason: string }
```
### 分类器检查
```typescript
export async function awaitClassifierAutoApproval(
pendingClassifierCheck: PendingClassifierCheck,
signal: AbortSignal,
isNonInteractiveSession: boolean,
): Promise<ClassifierDecision | null>
```
---
## 8. 权限日志
**文件位置**: `src/hooks/toolPermission/permissionLogging.ts`
### 日志函数
```typescript
export function logPermissionDecision(
args: PermissionDecisionArgs,
decision: {
decision: 'accept' | 'reject'
source: PermissionApprovalSource | PermissionRejectionSource
},
permissionPromptStartTimeMs?: number
): void
```
### 事件类型
```typescript
// 接受
logEvent('tengu_tool_permission_accepted', {...})
logEvent('tengu_tool_permission_auto_approved', {...})
// 拒绝
logEvent('tengu_tool_permission_rejected', {...})
logEvent('tengu_tool_use_cancelled', {...})
```
---
## 9. 权限检查入口
**文件位置**: `src/utils/permissions/permissions.ts`
### 主检查函数
```typescript
export async function hasPermissionsToUseTool(
tool: Tool,
input: Record<string, unknown>,
toolUseContext: ToolUseContext,
assistantMessage: AssistantMessage,
toolUseID: string,
): Promise<PermissionDecision>
```
**决策流程**:
1. **模式检查**
- `bypassPermissions`: 直接允许
- `plan`: 计划模式规则
- `auto`: 分类器自动决策
2. **规则匹配**
- `alwaysAllowRules`: 匹配则允许
- `alwaysDenyRules`: 匹配则拒绝
3. **会话状态**
- 非交互式会话可能有不同行为
4. **分类器检查**
- 仅 Bash 工具支持
- 异步执行
5. **Hook 检查**
- 执行 PermissionRequest hooks
6. **降级到交互式**
- 返回 `{ behavior: 'ask' }`
---
## 10. 权限队列
### ToolUseConfirm
```typescript
type ToolUseConfirm = {
assistantMessage: AssistantMessage
tool: Tool
description: string
input: Record<string, unknown>
toolUseContext: ToolUseContext
toolUseID: string
permissionResult: PermissionDecision & { behavior: 'ask' }
permissionPromptStartTimeMs: number
classifierCheckInProgress?: boolean
classifierAutoApproved?: boolean
classifierMatchedRule?: string
onUserInteraction(): void
onDismissCheckmark(): void
onAbort(): void
onAllow(
updatedInput: Record<string, unknown>,
permissionUpdates: PermissionUpdate[],
feedback?: string,
contentBlocks?: ContentBlockParam[]
): Promise<void>
onReject(feedback?: string, contentBlocks?: ContentBlockParam[]): void
recheckPermission(): Promise<void>
}
```
---
## 11. 权限处理流程图
```
用户执行工具
hasPermissionsToUseTool()
┌─────────────────────┐
│ 权限模式检查 │
│ bypassPermissions? │ ───是──▶ 直接允许
└─────────────────────┘
│否
┌─────────────────────┐
│ 规则检查 │
│ alwaysAllowRules? │ ───是──▶ 直接允许
│ alwaysDenyRules? │ ───是──▶ 直接拒绝
└─────────────────────┘
┌─────────────────────┐
│ 分类器检查 │
│ BASH_CLASSIFIER? │ ───是──▶ 异步推理
└─────────────────────┘
┌─────────────────────┐
│ Hook 检查 │
│ executePermission │ ───允许──▶ 返回允许
│ RequestHooks │ ───拒绝──▶ 返回拒绝
└─────────────────────┘
交互式确认对话框
├─── 用户允许 ───▶ handleUserAllow()
│ │
│ ▼
│ persistPermissions()
│ │
│ ▼
│ logPermissionDecision()
│ │
│ ▼
│ 返回 PermissionAllowDecision
├─── 用户拒绝 ───▶ onReject()
│ │
│ ▼
│ cancelAndAbort()
│ │
│ ▼
│ 返回 PermissionDenyDecision
└─── 用户中断 ───▶ Esc 按键
abortController.abort()
返回 PermissionDenyDecision
```
---
## 12. 远程权限流程
```
CLI 端 (handleInteractivePermission)
bridgeCallbacks.sendRequest(bridgeRequestId, ...)
│ WebSocket / HTTP
IDE Extension / Web UI
显示权限对话框
用户允许/拒绝
bridgeCallbacks.sendResponse(bridgeRequestId, response)
│ WebSocket / HTTP
CLI 端 (onResponse 回调)
resolveOnce(decision)
```
---
## 13. 关键常量
```typescript
// 200ms 宽限期后用户交互取消分类器
const GRACE_PERIOD_MS = 200
// 分类器自动批准后显示 ✓ 的时间
const CHECKMARK_DISPLAY_MS = 3000 // 终端聚焦时
const CHECKMARK_DISPLAY_MS = 1000 // 终端未聚焦时
```
---
## 相关源码文件
| 文件 | 功能 |
|------|------|
| `PermissionContext.ts` | 权限上下文创建和管理 |
| `handlers/coordinatorHandler.ts` | 协调者处理器 |
| `handlers/interactiveHandler.ts` | 交互式处理器 |
| `handlers/swarmWorkerHandler.ts` | Swarm Worker 处理器 |
| `permissionLogging.ts` | 权限日志记录 |
| `src/utils/permissions/permissions.ts` | 权限检查入口 |
| `src/utils/permissions/PermissionUpdate.ts` | 权限更新管理 |
| `src/utils/permissions/PermissionMode.ts` | 权限模式定义 |
| `src/bridge/bridgePermissionCallbacks.ts` | 桥接权限回调 |
| `src/tools/BashTool/bashPermissions.ts` | Bash 分类器 |
| `src/types/permissions.ts` | 权限类型定义 |

View File

@@ -0,0 +1,279 @@
# 插件与技能系统
Claude Code 提供了强大的插件系统和技能系统来扩展功能。本文档详细介绍这两个系统的架构和实现。
## 1. 插件系统 (plugins/)
### 1.1 插件加载机制
Claude Code 的插件系统支持内置插件和第三方插件。
**关键文件:**
- `/src/plugins/builtinPlugins.ts` - 内置插件注册表
- `/src/utils/plugins/pluginLoader.ts` - 插件加载器
- `/src/utils/plugins/loadPluginHooks.ts` - 插件钩子加载
**插件结构:**
```typescript
interface LoadedPlugin {
name: string // 插件名称
manifest: { // 插件清单
name: string
description: string
version: string
}
path: string // 插件路径
source: string // 来源标识
repository: string // 仓库地址
enabled: boolean // 是否启用
isBuiltin: boolean // 是否为内置插件
hooksConfig?: HooksSettings // 钩子配置
mcpServers?: MCPServer[] // MCP 服务器配置
}
```
### 1.2 内置插件 (builtinPlugins.ts)
内置插件是与 Claude Code CLI 一起打包的插件,可以通过 `/plugin` UI 启用/禁用。
**与 Bundled Skills 的区别:**
| 特性 | 内置插件 | Bundled Skills |
|------|----------|----------------|
| 出现位置 | `/plugin` UI 的 "Built-in" 部分 | `/skills` 列表 |
| 用户控制 | 可启用/禁用(持久化到用户设置) | 始终可用 |
| 组件类型 | 可提供多种组件skills, hooks, MCP servers | 仅 skills |
**插件 ID 格式:**
- 内置插件:`{name}@builtin`
- 市场插件:`{name}@{marketplace}`
**核心函数:**
```typescript
// 注册内置插件
registerBuiltinPlugin(definition: BuiltinPluginDefinition): void
// 检查是否为内置插件
isBuiltinPluginId(pluginId: string): boolean
// 获取所有内置插件(分启用/禁用)
getBuiltinPlugins(): { enabled: LoadedPlugin[]; disabled: LoadedPlugin[] }
// 获取内置插件提供的技能命令
getBuiltinPluginSkillCommands(): Command[]
```
### 1.3 插件注册和执行流程
**注册流程:**
1. 在启动时调用 `initBuiltinPlugins()` 注册所有内置插件
2. 插件定义包含:`name`, `description`, `version`, `isAvailable()`, `defaultEnabled`, `skills`, `hooks`, `mcpServers`
**加载流程 (loadPluginHooks.ts)**
```typescript
export const loadPluginHooks = memoize(async (): Promise<void> => {
const { enabled } = await loadAllPluginsCacheOnly()
// 转换插件钩子配置为匹配器
const pluginMatchers = convertPluginHooksToMatchers(plugin)
// 清除旧钩子并注册新钩子(原子操作)
clearRegisteredPluginHooks()
registerHookCallbacks(allPluginHooks)
})
```
**钩子事件类型:**
- `PreToolUse` - 工具执行前
- `PostToolUse` - 工具执行后
- `PermissionDenied` - 权限被拒绝
- `SessionStart/SessionEnd` - 会话开始/结束
- `SubagentStart/SubagentStop` - 子智能体启动/停止
- `TaskCreated/TaskCompleted` - 任务创建/完成
### 1.4 第三方插件支持
第三方插件通过市场安装,支持以下功能:
- 自定义 skills
- 钩子系统
- MCP 服务器
## 2. 技能系统 (skills/)
### 2.1 技能定义和格式
**技能定义结构 (BundledSkillDefinition)**
```typescript
type BundledSkillDefinition = {
name: string // 技能名称
description: string // 技能描述
aliases?: string[] // 别名
whenToUse?: string // 使用建议
argumentHint?: string // 参数提示
allowedTools?: string[] // 允许的工具
model?: string // 模型覆盖
disableModelInvocation?: boolean // 禁用模型调用
userInvocable?: boolean // 用户可调用
isEnabled?: () => boolean // 启用检查函数
hooks?: HooksSettings // 钩子设置
context?: 'inline' | 'fork' // 执行上下文
agent?: string // 代理类型
files?: Record<string, string> // 参考文件
getPromptForCommand: (args: string, context: ToolUseContext) => Promise<ContentBlockParam[]>
}
```
### 2.2 技能执行机制 (SkillTool)
**关键文件:** `/src/tools/SkillTool/SkillTool.ts`
**执行模式:**
1. **Inline 模式(内联执行)**
- 技能内容直接注入对话
- 使用 `processPromptSlashCommand` 处理
- 支持 `!command``$ARGUMENTS` 扩展
2. **Fork 模式(分叉执行)**
- 在独立子智能体中运行技能
- 拥有独立 token 预算
- 通过 `executeForkedSkill` 实现
**SkillTool 输入/输出:**
```typescript
// 输入
input: {
skill: string // 技能名称,如 "commit", "review-pr"
args?: string // 可选参数
}
// 输出
output: {
success: boolean
commandName: string
status: 'inline' | 'forked'
agentId?: string // fork 模式下的子智能体 ID
result?: string // fork 模式下的执行结果
}
```
**权限检查:**
- 技能执行需要权限检查
- 支持规则匹配(前缀匹配如 `review:*`
- 自动允许安全属性的技能
### 2.3 内置技能
**位置:** `/src/skills/bundled/`
**内置技能列表:**
| 技能名 | 描述 |
|--------|------|
| `remember` | 记忆技能 |
| `loremIpsum` | 生成占位文本 |
| `verify` | 验证技能 |
| `loop` | 循环执行技能 |
| `claudeApi` | Claude API 相关 |
| `debug` | 调试技能 |
| `stuck` | 处理卡住情况 |
| `batch` | 批量处理 |
| `updateConfig` | 更新配置 |
| `keybindings` | 快捷键 |
| `simplify` | 简化代码 |
| `skillify` | 技能化 |
### 2.4 用户自定义技能
用户可以在 `~/.claude/skills/` 目录下创建自定义技能。
**技能文件结构:**
```
~/.claude/skills/
└── my-skill/
└── SKILL.md # 技能定义文件
```
**注册流程:**
```typescript
// 注册技能
registerBundledSkill(definition: BundledSkillDefinition): void
// 获取所有已注册技能
getBundledSkills(): Command[]
// 技能文件提取(用于有参考文件的技能)
async function extractBundledSkillFiles(
skillName: string,
files: Record<string, string>
): Promise<string | null>
```
### 2.5 技能与命令的转换
技能在内部被转换为 `Command` 对象:
```typescript
function skillDefinitionToCommand(definition: BundledSkillDefinition): Command {
return {
type: 'prompt',
name: definition.name,
description: definition.description,
source: 'bundled',
loadedFrom: 'bundled',
hooks: definition.hooks,
context: definition.context,
agent: definition.agent,
// ...
}
}
```
## 3. 插件与技能的协同
### 3.1 插件提供技能
插件可以通过内置技能机制提供技能:
```typescript
// 插件定义
const myPlugin: BuiltinPluginDefinition = {
name: 'my-plugin',
description: 'My custom plugin',
skills: [skill1, skill2],
// ...
}
```
### 3.2 钩子在技能执行中的应用
技能执行时会触发各种钩子:
- `PreToolUse` - 检查技能是否允许使用特定工具
- `PostToolUse` - 记录技能执行结果
- `Stop` - 技能执行完成
## 4. MCP 集成
技能系统支持 MCP (Model Context Protocol) 技能构建器:
```typescript
// 位置:/src/skills/mcpSkillBuilders.ts
export function createMcpSkill(
serverName: string,
toolName: string
): BundledSkillDefinition
```
## 5. 权限与安全
### 5.1 技能白名单
`SAFE_SKILL_PROPERTIES` 定义了安全属性列表,只包含以下属性的技能会自动获得权限:
- `type`, `progressMessage`, `contentLength`, `argNames`, `model`, `effort`
- `source`, `pluginInfo`, `disableNonInteractive`, `skillRoot`, `context`, `agent`
- `getPromptForCommand`, `frontmatterKeys`
- `name`, `description`, `hasUserSpecifiedDescription`, `isEnabled`, `isHidden`
- `aliases`, `isMcp`, `argumentHint`, `whenToUse`, `paths`, `version`
- `disableModelInvocation`, `userInvocable`, `loadedFrom`, `immediate`, `userFacingName`
### 5.2 远程技能 (实验性)
启用 `EXPERIMENTAL_SKILL_SEARCH` 后支持远程技能:
- 技能定义存储在远程服务器
- 通过 `_canonical_<slug>` 格式引用
- 支持 GCS、HTTP/HTTPS、S3 等协议

View File

@@ -0,0 +1,390 @@
# 状态与任务管理
Claude Code 提供了强大的状态管理和任务管理系统来协调复杂的操作流程。
## 1. 状态管理 (state/)
### 1.1 状态存储机制
**核心文件:**
- `/src/state/store.ts` - 状态存储基础实现
- `/src/state/AppStateStore.ts` - 应用状态存储
- `/src/state/onChangeAppState.ts` - 状态变更处理
- `/src/state/selectors.ts` - 状态选择器
**Store 模式实现:**
```typescript
// 位置:/src/state/store.ts
export type Store<T> = {
getState: () => T // 获取当前状态
setState: (updater: (prev: T) => T) => void // 更新状态
subscribe: (listener: Listener) => () => void // 订阅变更
}
export function createStore<T>(
initialState: T,
onChange?: OnChange<T>
): Store<T>
```
**特性:**
- 不可变性Immutability状态更新采用函数式风格
- 订阅机制:支持多个监听器,变更时自动通知
- 变更回调:`onChange` 回调在状态变更后执行
### 1.2 AppState 结构
**位置:** `/src/state/AppStateStore.ts`
`AppState` 是全局状态的核心结构,包含以下主要部分:
```typescript
export type AppState = {
// 设置与配置
settings: SettingsJson
verbose: boolean
mainLoopModel: ModelSetting
// 任务管理
tasks: { [taskId: string]: TaskState }
agentNameRegistry: Map<string, AgentId>
foregroundedTaskId?: string
viewingAgentTaskId?: string
// MCP 状态
mcp: {
clients: MCPServerConnection[]
tools: Tool[]
commands: Command[]
resources: Record<string, ServerResource[]>
pluginReconnectKey: number
}
// 插件状态
plugins: {
enabled: LoadedPlugin[]
disabled: LoadedPlugin[]
commands: Command[]
errors: PluginError[]
installationStatus: {...}
needsRefresh: boolean
}
// Agent 定义
agentDefinitions: AgentDefinitionsResult
// 团队上下文
teamContext?: {
teamName: string
teamFilePath: string
leadAgentId: string
selfAgentId?: string
selfAgentName?: string
isLeader?: boolean
selfAgentColor?: string
teammates: {...}
}
// 推理状态
speculation: SpeculationState
thinkingEnabled: boolean | undefined
}
```
### 1.3 状态持久化
**持久化策略:**
- 设置存储在 `~/.claude/settings.json`
- 任务状态存储在 `~/.claude/tasks/{taskListId}/`
- 团队配置存储在 `~/.claude/teams/{team-name}/`
**状态恢复:**
- 应用启动时从磁盘加载设置
- 团队成员重新连接时恢复上下文
- 任务队列在会话间持久化
### 1.4 状态变更处理
**onChangeAppState.ts**
```typescript
// 状态变更时的处理逻辑
-
-
- UI
```
## 2. 任务管理 (tasks/)
### 2.1 任务类型
**位置:** `/src/tasks/types.ts`
Claude Code 支持多种任务类型:
```typescript
export type TaskState =
| LocalShellTaskState // 本地 Shell 任务
| LocalAgentTaskState // 本地 Agent 任务
| RemoteAgentTaskState // 远程 Agent 任务
| InProcessTeammateTaskState // 进程中队友任务
| LocalWorkflowTaskState // 本地工作流任务
| MonitorMcpTaskState // MCP 监控任务
| DreamTaskState // 异步任务
```
### 2.2 任务状态机
**任务状态流转:**
```
pending → in_progress → completed
↓ ↓ ↓
blocked blocked blocked
↓ ↓
cancelled cancelled
```
**状态定义:**
```typescript
type TaskStatus = 'pending' | 'in_progress' | 'completed' | 'cancelled' | 'blocked'
interface TaskState {
id: string
status: TaskStatus
subject: string
description?: string
activeForm?: string // 进行中的操作描述
owner?: string // 任务负责人
blocks: string[] // 此任务阻止的任务
blockedBy: string[] // 阻止此任务的任务
metadata?: Record<string, unknown>
}
```
### 2.3 任务工具
Claude Code 提供四个主要任务工具:
#### TaskCreateTool
**位置:** `/src/tools/TaskCreateTool/TaskCreateTool.ts`
```typescript
input: {
subject: string // 任务标题
description: string // 任务描述
activeForm?: string // 进行中显示文本
metadata?: Record<string, unknown> // 元数据
}
output: {
task: {
id: string
subject: string
}
}
```
**特性:**
- 创建任务后自动展开任务列表
- 支持任务创建钩子 (`TaskCreated` hooks)
- 阻止错误的钩子可取消创建
#### TaskUpdateTool
**位置:** `/src/tools/TaskUpdateTool/TaskUpdateTool.ts`
```typescript
input: {
taskId: string
subject?: string
description?: string
activeForm?: string
status?: TaskStatus | 'deleted'
addBlocks?: string[] // 此任务阻止的任务
addBlockedBy?: string[] // 阻止此任务的任务
owner?: string
metadata?: Record<string, unknown>
}
output: {
success: boolean
taskId: string
updatedFields: string[]
statusChange?: { from: string; to: string }
verificationNudgeNeeded?: boolean
}
```
**特性:**
- 支持原子字段更新
- 任务完成时触发 `TaskCompleted` 钩子
- 所有权变更时通知新负责人
- 阻止依赖任务处理
#### TaskListTool
列出所有任务,支持过滤和排序。
#### TaskStopTool
停止正在运行的任务。
### 2.4 任务间依赖
**依赖管理:**
```typescript
// 阻止关系
task.blocks = ['task-id-1', 'task-id-2'] // 此任务阻止这些任务
task.blockedBy = ['task-id-3'] // 此任务被这些任务阻止
// 依赖检查
function canStartTask(task: TaskState): boolean {
return task.blockedBy.every(id => isTaskCompleted(id))
}
```
### 2.5 任务输出 (TaskOutputTool)
**位置:** `/src/tools/TaskOutputTool/`
用于检索任务的执行输出和结果。
## 3. 任务与状态的集成
### 3.1 AppState 中的任务管理
```typescript
// 任务存储在 AppState.tasks 中
tasks: { [taskId: string]: TaskState }
// 任务 ID 注册表(用于按名称查找)
agentNameRegistry: Map<string, AgentId>
// 前台任务 ID
foregroundedTaskId?: string
// 查看中的 Agent 任务 ID
viewingAgentTaskId?: string
```
### 3.2 任务状态变更与 UI 更新
```typescript
// TaskCreateTool 和 TaskUpdateTool 自动更新 expandedView
context.setAppState(prev => {
if (prev.expandedView === 'tasks') return prev
return { ...prev, expandedView: 'tasks' as const }
})
```
## 4. 后台任务管理
### 4.1 背景任务识别
```typescript
export function isBackgroundTask(task: TaskState): boolean {
if (task.status !== 'running' && task.status !== 'pending') {
return false
}
// 前台任务isBackgrounded === false不是后台任务
if ('isBackgrounded' in task && task.isBackgrounded === false) {
return false
}
return true
}
```
### 4.2 任务清理
**Shell 任务清理:**
```typescript
// 位置:/src/tasks/LocalShellTask/killShellTasks.ts
export function killShellTasksForAgent(
agentId: AgentId,
getAppState: () => AppState,
setAppState: (updater: (prev: AppState) => AppState) => void
): void
```
### 4.3 任务与 Hooks 的集成
```typescript
// 任务创建钩子
executeTaskCreatedHooks(
taskId: string,
subject: string,
description: string,
agentName: string | undefined,
teamName: string | undefined,
// ...
)
// 任务完成钩子
executeTaskCompletedHooks(
taskId: string,
subject: string,
description: string,
agentName: string | undefined,
teamName: string | undefined,
// ...
)
```
## 5. 工作流集成
### 5.1 DreamTask
用于异步长时间运行的任务:
```typescript
// 位置:/src/tasks/DreamTask/DreamTask.ts
export type DreamTaskState = {
// 异步任务状态
}
```
### 5.2 InProcessTeammateTask
用于进程中队友通信的任务类型:
```typescript
// 位置:/src/tasks/InProcessTeammateTask/types.ts
export type InProcessTeammateTaskState = {
identity: TeammateIdentity
abortController?: AbortController
shutdownRequested?: boolean
// ...
}
```
## 6. 任务列表管理
### 6.1 任务列表 ID
```typescript
function getTaskListId(): string {
// 基于团队名称或会话 ID
}
```
### 6.2 任务通知
```typescript
// 任务更新通知
notifyTasksUpdated()
// 任务目录
getTasksDir(taskListId: string): string
```
## 7. 验证与提醒
当完成任务列表时,系统会检查是否需要进行验证:
```typescript
// 在 TaskUpdateTool 中
if (allTasks.length >= 3 && !allTasks.some(t => /verif/i.test(t.subject))) {
verificationNudgeNeeded = true
}
```
这提醒主线程 Agent 在没有验证步骤的情况下关闭了 3+ 个任务列表。

View File

@@ -0,0 +1,437 @@
# 多智能体协作
Claude Code 的多智能体系统允许创建和协调多个 AI 代理协同工作。本文档详细介绍 AgentTool 和相关协作机制。
## 1. AgentTool 概述
### 1.1 核心文件
**位置:** `/src/tools/AgentTool/`
**主要文件:**
- `runAgent.ts` - Agent 运行核心逻辑
- `builtInAgents.ts` - 内置 Agent 定义
- `loadAgentsDir.ts` - Agent 目录加载
- `agentMemory.ts` - Agent 内存管理
- `built-in/` - 内置 Agent 实现
### 1.2 Agent 定义结构
```typescript
export type AgentDefinition = {
agentType: string // Agent 类型标识
whenToUse?: string // 使用建议
disallowedTools?: string[] // 禁用工具列表
tools?: string[] | '*' // 允许的工具
source?: string // 来源
baseDir?: string // 基础目录
model?: string // 模型设置
permissionMode?: PermissionMode // 权限模式
maxTurns?: number // 最大轮次
getSystemPrompt?: () => string // 系统提示
hooks?: HooksSettings // 钩子设置
skills?: string[] // 预加载技能
mcpServers?: MCPServerSpec[] // MCP 服务器
omitClaudeMd?: boolean // 是否省略 CLAUDE.md
effort?: EffortValue // 努力值
callback?: () => void // 完成回调
}
```
## 2. 子智能体生成
### 2.1 runAgent 函数
**位置:** `/src/tools/AgentTool/runAgent.ts`
`runAgent` 是创建和运行子智能体的核心函数:
```typescript
export async function* runAgent({
agentDefinition, // Agent 定义
promptMessages, // 提示消息
toolUseContext, // 工具使用上下文
canUseTool, // 工具使用权限检查
isAsync, // 是否异步执行
querySource, // 查询来源
model, // 模型覆盖
maxTurns, // 最大轮次
allowedTools, // 允许的工具列表
// ...
}): AsyncGenerator<Message, void>
```
### 2.2 消息过滤
```typescript
// 过滤不完整的工具调用
export function filterIncompleteToolCalls(messages: Message[]): Message[] {
// 移除有工具调用但没有结果的助手消息
}
```
### 2.3 上下文隔离
```typescript
// 为子智能体创建隔离的上下文
const agentToolUseContext = createSubagentContext(toolUseContext, {
options: agentOptions,
agentId,
agentType: agentDefinition.agentType,
messages: initialMessages,
readFileState: agentReadFileState,
abortController: agentAbortController,
getAppState: agentGetAppState,
shareSetAppState: !isAsync, // 同步 Agent 共享状态
})
```
## 3. 智能体生命周期管理
### 3.1 生命周期阶段
1. **初始化阶段**
- 创建 Agent ID
- 设置上下文
- 初始化 MCP 服务器
- 注册 Hooks
2. **执行阶段**
- 运行查询循环
- 处理工具调用
- 管理会话
3. **清理阶段**
- 清理 MCP 服务器
- 清除会话 Hooks
- 释放内存
- 杀死后台任务
### 3.2 生命周期钩子
```typescript
// SubagentStart 钩子
for await (const hookResult of executeSubagentStartHooks(
agentId,
agentDefinition.agentType,
agentAbortController.signal,
)) {
// 收集额外上下文
}
// SubagentStop 钩子
if (agentDefinition.hooks) {
clearSessionHooks(rootSetAppState, agentId)
}
```
## 4. 内置智能体 (built-in/)
### 4.1 generalPurposeAgent
**位置:** `/src/tools/AgentTool/built-in/generalPurposeAgent.ts`
通用目的 Agent适用于复杂研究和多步骤任务执行
```typescript
export const GENERAL_PURPOSE_AGENT: BuiltInAgentDefinition = {
agentType: 'general-purpose',
whenToUse: 'General-purpose agent for researching complex questions...',
tools: ['*'], // 允许所有工具
source: 'built-in',
getSystemPrompt: getGeneralPurposeSystemPrompt,
}
```
### 4.2 planAgent
**位置:** `/src/tools/AgentTool/built-in/planAgent.ts`
软件架构师 Agent用于设计实现计划
**关键特性:**
- **只读模式**:禁止任何文件修改操作
- 严格禁用工具:`Edit`, `Write`, `NotebookEdit`, `Agent`
- 允许工具:`Read`, `Glob`, `Grep`, `Bash`(仅限只读操作)
**系统提示片段:**
```
=== CRITICAL: READ-ONLY MODE - NO FILE MODIFICATIONS ===
This is a READ-ONLY planning task. You are STRICTLY PROHIBITED from:
- Creating new files (no Write, touch, or file creation of any kind)
- Modifying existing files (no Edit operations)
- Deleting files (no rm or deletion)
...
```
### 4.3 verificationAgent
验证 Agent用于验证任务完成情况
```typescript
// 在 TaskUpdateTool 中引用
const VERIFICATION_AGENT_TYPE = 'verification'
// 当满足条件时提示验证
if (allTasks.length >= 3 && !allTasks.some(t => /verif/i.test(t.subject))) {
verificationNudgeNeeded = true
}
```
### 4.4 exploreAgent
探索 Agent用于代码库探索和搜索
**特性:**
- 只读操作
- 使用 `find`/`grep``Glob`/`Grep` 进行搜索
- 不加载 CLAUDE.md节省 token
### 4.5 statuslineSetup
状态栏设置 Agent用于配置状态行显示。
### 4.6 claudeCodeGuideAgent
Claude Code 指南 Agent帮助用户学习使用 Claude Code。
## 5. Agent 内存管理
### 5.1 Agent 内存结构
**位置:** `/src/tools/AgentTool/agentMemory.ts`
```typescript
export type AgentMemory = {
sessionId: string
agentId: string
messages: Message[]
toolUseResults: Map<string, ToolResult>
fileState: FileStateCache
}
```
### 5.2 文件状态缓存
```typescript
// 克隆文件状态缓存
const agentReadFileState = forkContextMessages !== undefined
? cloneFileStateCache(toolUseContext.readFileState)
: createFileStateCacheWithSizeLimit(READ_FILE_STATE_CACHE_SIZE)
// 清理时释放
agentToolUseContext.readFileState.clear()
```
### 5.3 转录记录
```typescript
// 记录初始消息
await recordSidechainTranscript(initialMessages, agentId)
// 记录新消息
await recordSidechainTranscript([message], agentId, lastRecordedUuid)
```
## 6. 团队协调器 (coordinator/)
### 6.1 协调器模式
**位置:** `/src/coordinator/coordinatorMode.ts`
协调器模式允许多个 Agent 在团队中协作。
### 6.2 协调器 Agent
```typescript
// 获取协调器 Agent
function getCoordinatorAgents(): AgentDefinition[]
```
## 7. 团队管理工具
### 7.1 TeamCreateTool
**位置:** `/src/tools/TeamCreateTool/TeamCreateTool.ts`
创建团队,管理团队配置。
### 7.2 TeamDeleteTool
**位置:** `/src/tools/TeamDeleteTool/TeamDeleteTool.ts`
删除团队,清理团队资源。
### 7.3 团队文件结构
**位置:** `/src/utils/swarm/teamHelpers.ts`
```typescript
export type TeamFile = {
name: string
description?: string
createdAt: number
leadAgentId: string
leadSessionId?: string
hiddenPaneIds?: string[]
teamAllowedPaths?: TeamAllowedPath[]
members: Array<{
agentId: string
name: string
agentType?: string
model?: string
prompt?: string
color?: string
planModeRequired?: boolean
joinedAt: number
tmuxPaneId: string
cwd: string
worktreePath?: string
sessionId?: string
subscriptions: string[]
backendType?: BackendType
isActive?: boolean
mode?: PermissionMode
}>
}
```
## 8. Agent 与技能的集成
### 8.1 技能预加载
Agent 可以预加载技能:
```typescript
const skillsToPreload = agentDefinition.skills ?? []
if (skillsToPreload.length > 0) {
const allSkills = await getSkillToolCommands(getProjectRoot())
// 加载并注入技能内容
}
```
### 8.2 技能名称解析
```typescript
function resolveSkillName(
skillName: string,
allSkills: Command[],
agentDefinition: AgentDefinition
): string | null {
// 1. 精确匹配
if (hasCommand(skillName, allSkills)) return skillName
// 2. 前缀匹配 (e.g., "my-skill" → "my-plugin:my-skill")
const qualifiedName = `${pluginPrefix}:${skillName}`
if (hasCommand(qualifiedName, allSkills)) return qualifiedName
// 3. 后缀匹配 (e.g., ":my-skill")
// ...
}
```
## 9. MCP 服务器集成
### 9.1 Agent 专用 MCP 服务器
Agent 可以定义自己的 MCP 服务器:
```typescript
async function initializeAgentMcpServers(
agentDefinition: AgentDefinition,
parentClients: MCPServerConnection[]
): Promise<{
clients: MCPServerConnection[]
tools: Tools
cleanup: () => Promise<void>
}>
```
### 9.2 服务器合并
```typescript
// 合并父级和 Agent 专用的 MCP 客户端
const allTools = uniqBy([...resolvedTools, ...agentMcpTools], 'name')
```
## 10. 权限与隔离
### 10.1 权限模式
```typescript
const agentPermissionMode = agentDefinition.permissionMode
if (agentPermissionMode &&
state.toolPermissionContext.mode !== 'bypassPermissions' &&
state.toolPermissionContext.mode !== 'acceptEdits') {
toolPermissionContext = {
...toolPermissionContext,
mode: agentPermissionMode
}
}
```
### 10.2 工具过滤
```typescript
const resolvedTools = resolveAgentTools(
agentDefinition,
availableTools,
isAsync
).resolvedTools
```
## 11. 性能优化
### 11.1 CLAUDE.md 省略
```typescript
const shouldOmitClaudeMd = agentDefinition.omitClaudeMd &&
!override?.userContext &&
getFeatureValue_CACHED_MAY_BE_STALE('tengu_slim_subagent_claudemd', true)
```
### 11.2 Git 状态省略
```typescript
const resolvedSystemContext =
agentDefinition.agentType === 'Explore' ||
agentDefinition.agentType === 'Plan'
? systemContextNoGit // 省略 gitStatus
: baseSystemContext
```
### 11.3 推理配置
```typescript
thinkingConfig: useExactTools
? toolUseContext.options.thinkingConfig // 继承父级
: { type: 'disabled' as const } // 禁用
```
## 12. Telemetry 与追踪
### 12.1 Perfetto 追踪
```typescript
if (isPerfettoTracingEnabled()) {
registerPerfettoAgent(agentId, agentDefinition.agentType, parentId)
}
// 清理时注销
unregisterPerfettoAgent(agentId)
```
### 12.2 转录存储
```typescript
// 边链转录
await recordSidechainTranscript(initialMessages, agentId)
// Agent 元数据
await writeAgentMetadata(agentId, {
agentType: agentDefinition.agentType,
worktreePath,
description
})
```

View File

@@ -0,0 +1,691 @@
# Swarm 系统
Claude Code 的 Swarm 系统是一个多智能体协作框架,支持团队模式、进程内队友和多种终端后端实现。
## 1. Swarm 系统概述
### 1.1 核心目录结构
**位置:** `/src/utils/swarm/`
```
swarm/
├── backends/
│ ├── types.ts # 后端类型定义
│ ├── registry.ts # 后端注册表
│ ├── detection.ts # 环境检测
│ ├── TmuxBackend.ts # Tmux 后端
│ ├── ITermBackend.ts # iTerm2 后端
│ ├── InProcessBackend.ts # 进程内后端
│ ├── PaneBackendExecutor.ts # 面板执行器
│ └── teammateModeSnapshot.ts # 团队模式快照
├── teamHelpers.ts # 团队辅助函数
├── teammateInit.ts # 队友初始化
├── teammateLayoutManager.ts # 布局管理
├── teammateModel.ts # 队友模型
├── teammatePromptAddendum.ts # 提示补充
├── permissionSync.ts # 权限同步
├── reconnection.ts # 重连机制
├── spawnUtils.ts # 生成工具
├── spawnInProcess.ts # 进程内生成
├── inProcessRunner.ts # 进程内运行器
├── constants.ts # 常量定义
└── leaderPermissionBridge.ts # 权限桥接
```
## 2. 团队模式快照 (teammateModeSnapshot.ts)
### 2.1 快照机制
```typescript
// 位置:/src/utils/swarm/backends/teammateModeSnapshot.ts
export type TeammateMode = 'auto' | 'tmux' | 'in-process'
// CLI 覆盖
let cliTeammateModeOverride: TeammateMode | null = null
// 捕获启动时的团队模式
export function captureTeammateModeSnapshot(): void {
if (cliTeammateModeOverride) {
initialTeammateMode = cliTeammateModeOverride
} else {
const config = getGlobalConfig()
initialTeammateMode = config.teammateMode ?? 'auto'
}
}
// 获取快照模式
export function getTeammateModeFromSnapshot(): TeammateMode
```
### 2.2 模式类型
| 模式 | 描述 |
|------|------|
| `auto` | 自动检测可用后端 |
| `tmux` | 强制使用 Tmux 后端 |
| `in-process` | 使用进程内后端 |
## 3. 团队辅助函数 (teamHelpers.ts)
### 3.1 团队文件操作
```typescript
// 获取团队目录
export function getTeamDir(teamName: string): string
// 获取团队配置文件路径
export function getTeamFilePath(teamName: string): string
// 读取团队文件(同步)
export function readTeamFile(teamName: string): TeamFile | null
// 读取团队文件(异步)
export async function readTeamFileAsync(teamName: string): Promise<TeamFile | null>
// 写入团队文件(同步)
function writeTeamFile(teamName: string, teamFile: TeamFile): void
// 写入团队文件(异步)
export async function writeTeamFileAsync(teamName: string, teamFile: TeamFile): Promise<void>
```
### 3.2 团队成员管理
```typescript
// 从团队文件移除队友
export function removeTeammateFromTeamFile(
teamName: string,
identifier: { agentId?: string; name?: string }
): boolean
// 移除成员
export function removeMemberFromTeam(
teamName: string,
tmuxPaneId: string
): boolean
// 按 Agent ID 移除成员
export function removeMemberByAgentId(
teamName: string,
agentId: string
): boolean
// 设置成员权限模式
export function setMemberMode(
teamName: string,
memberName: string,
mode: PermissionMode
): boolean
// 同步队友模式
export function syncTeammateMode(mode: PermissionMode, teamNameOverride?: string): void
// 设置成员活跃状态
export async function setMemberActive(
teamName: string,
memberName: string,
isActive: boolean
): Promise<void>
```
### 3.3 团队清理
```typescript
// 清理会话团队
export async function cleanupSessionTeams(): Promise<void>
// 清理团队目录
export async function cleanupTeamDirectories(teamName: string): Promise<void>
// 注册团队会话清理
export function registerTeamForSessionCleanup(teamName: string): void
// 注销团队会话清理
export function unregisterTeamForSessionCleanup(teamName: string): void
```
## 4. 队友初始化 (teammateInit.ts)
### 4.1 初始化流程
```typescript
// 位置:/src/utils/swarm/teammateInit.ts
export function initializeTeammateHooks(
setAppState: (updater: (prev: AppState) => AppState) => void,
sessionId: string,
teamInfo: { teamName: string; agentId: string; agentName: string }
): void
```
### 4.2 团队权限应用
```typescript
// 应用团队范围的允许路径
if (teamFile.teamAllowedPaths && teamFile.teamAllowedPaths.length > 0) {
for (const allowedPath of teamFile.teamAllowedPaths) {
setAppState(prev => ({
...prev,
toolPermissionContext: applyPermissionUpdate(
prev.toolPermissionContext,
{
type: 'addRules',
rules: [{ toolName: allowedPath.toolName, ruleContent }],
behavior: 'allow',
destination: 'session'
}
)
}))
}
}
```
### 4.3 停止钩子注册
```typescript
// 注册停止钩子以通知团队领导
addFunctionHook(
setAppState,
sessionId,
'Stop',
'',
async (messages, _signal) => {
// 标记为空闲
void setMemberActive(teamName, agentName, false)
// 发送空闲通知
const notification = createIdleNotification(agentName, {...})
await writeToMailbox(leadAgentName, {...})
return true
}
)
```
## 5. 布局管理 (teammateLayoutManager.ts)
### 5.1 队友颜色分配
```typescript
// 分配队友颜色
export function assignTeammateColor(teammateId: string): AgentColorName
// 获取队友颜色
export function getTeammateColor(teammateId: string): AgentColorName | undefined
// 清除所有颜色分配
export function clearTeammateColors(): void
```
### 5.2 后端选择
```typescript
async function getBackend(): Promise<PaneBackend> {
return (await detectAndGetBackend()).backend
}
```
### 5.3 面板操作
```typescript
// 在 Swarm 视图中创建队友面板
export async function createTeammatePaneInSwarmView(
teammateName: string,
teammateColor: AgentColorName
): Promise<{ paneId: string; isFirstTeammate: boolean }>
// 启用面板边框状态
export async function enablePaneBorderStatus(
windowTarget?: string,
useSwarmSocket?: boolean
): Promise<void>
// 发送命令到面板
export async function sendCommandToPane(
paneId: string,
command: string,
useSwarmSocket?: boolean
): Promise<void>
```
## 6. 后端系统 (backends/)
### 6.1 后端类型
**位置:** `/src/utils/swarm/backends/types.ts`
```typescript
export type BackendType = 'tmux' | 'iterm2' | 'in-process'
export type PaneBackendType = 'tmux' | 'iterm2'
export type PaneId = string
export type CreatePaneResult = {
paneId: PaneId
isFirstTeammate: boolean
}
```
### 6.2 PaneBackend 接口
```typescript
export type PaneBackend = {
readonly type: BackendType
readonly displayName: string
readonly supportsHideShow: boolean
isAvailable(): Promise<boolean>
isRunningInside(): Promise<boolean>
createTeammatePaneInSwarmView(
name: string,
color: AgentColorName
): Promise<CreatePaneResult>
sendCommandToPane(
paneId: PaneId,
command: string,
useExternalSession?: boolean
): Promise<void>
setPaneBorderColor(
paneId: PaneId,
color: AgentColorName,
useExternalSession?: boolean
): Promise<void>
setPaneTitle(
paneId: PaneId,
name: string,
color: AgentColorName,
useExternalSession?: boolean
): Promise<void>
enablePaneBorderStatus(
windowTarget?: string,
useExternalSession?: boolean
): Promise<void>
rebalancePanes(windowTarget: string, hasLeader: boolean): Promise<void>
killPane(paneId: PaneId, useExternalSession?: boolean): Promise<boolean>
hidePane(paneId: PaneId, useExternalSession?: boolean): Promise<boolean>
showPane(
paneId: PaneId,
targetWindowOrPane: string,
useExternalSession?: boolean
): Promise<boolean>
}
```
### 6.3 TmuxBackend
**位置:** `/src/utils/swarm/backends/TmuxBackend.ts`
使用 tmux 进行面板管理的后端实现。
**功能:**
- 创建 tmux 窗口和面板
- 发送命令到指定面板
- 设置面板颜色和标题
- 管理面板布局
### 6.4 ITermBackend
**位置:** `/src/utils/swarm/backends/ITermBackend.ts`
使用 iTerm2 原生分割面板的后端实现。
**功能:**
- 通过 it2 CLI 与 iTerm2 通信
- 创建垂直/水平分割
- 设置 profile 和颜色
### 6.5 InProcessBackend
**位置:** `/src/utils/swarm/backends/InProcessBackend.ts`
在当前 Node.js 进程中运行队友的后端。
**特性:**
- 共享 API 客户端和 MCP 连接
- 通过文件邮箱通信
- 使用 AbortController 终止
- 始终可用(无外部依赖)
```typescript
export class InProcessBackend implements TeammateExecutor {
readonly type = 'in-process' as const
async spawn(config: TeammateSpawnConfig): Promise<TeammateSpawnResult>
async sendMessage(agentId: string, message: TeammateMessage): Promise<void>
async terminate(agentId: string, reason?: string): Promise<boolean>
async kill(agentId: string): Promise<boolean>
async isActive(agentId: string): Promise<boolean>
}
```
### 6.6 后端注册表
**位置:** `/src/utils/swarm/backends/registry.ts`
```typescript
// 检测并获取合适的后端
export async function detectAndGetBackend(): Promise<BackendDetectionResult>
// 注册所有后端
export async function ensureBackendsRegistered(): Promise<void>
// 按类型获取后端
export async function getBackendByType(type: BackendType): Promise<PaneBackend>
```
## 7. 权限同步 (permissionSync.ts)
### 7.1 权限请求流程
```
Worker Agent → 权限请求 → Leader Mailbox
Leader Agent ← 轮询 ← 权限队列
用户批准/拒绝
Leader → 权限响应 → Worker Mailbox
Worker ← 处理响应 ←
```
### 7.2 权限请求结构
```typescript
export type SwarmPermissionRequest = {
id: string
workerId: string
workerName: string
workerColor?: string
teamName: string
toolName: string
toolUseId: string
description: string
input: Record<string, unknown>
permissionSuggestions: unknown[]
status: 'pending' | 'approved' | 'rejected'
resolvedBy?: 'worker' | 'leader'
resolvedAt?: number
feedback?: string
updatedInput?: Record<string, unknown>
permissionUpdates?: PermissionUpdate[]
createdAt: number
}
```
### 7.3 权限操作
```typescript
// 创建权限请求
export function createPermissionRequest(params: {...}): SwarmPermissionRequest
// 写入待处理权限请求
export async function writePermissionRequest(
request: SwarmPermissionRequest
): Promise<SwarmPermissionRequest>
// 读取待处理权限
export async function readPendingPermissions(
teamName?: string
): Promise<SwarmPermissionRequest[]>
// 解决权限请求
export async function resolvePermission(
requestId: string,
resolution: PermissionResolution,
teamName?: string
): Promise<boolean>
// 通过邮箱发送权限请求
export async function sendPermissionRequestViaMailbox(
request: SwarmPermissionRequest
): Promise<boolean>
// 通过邮箱发送权限响应
export async function sendPermissionResponseViaMailbox(
workerName: string,
resolution: PermissionResolution,
requestId: string,
teamName?: string
): Promise<boolean>
```
### 7.4 沙箱权限
```typescript
// 发送沙箱权限请求
export async function sendSandboxPermissionRequestViaMailbox(
host: string,
requestId: string,
teamName?: string
): Promise<boolean>
// 发送沙箱权限响应
export async function sendSandboxPermissionResponseViaMailbox(
workerName: string,
requestId: string,
host: string,
allow: boolean,
teamName?: string
): Promise<boolean>
```
### 7.5 团队领导检查
```typescript
// 检查是否为团队领导
export function isTeamLeader(teamName?: string): boolean
// 检查是否为 Swarm Worker
export function isSwarmWorker(): boolean
```
## 8. 重连机制 (reconnection.ts)
### 8.1 初始团队上下文计算
```typescript
export function computeInitialTeamContext():
| AppState['teamContext']
| undefined {
// 从 CLI 参数获取动态团队上下文
const context = getDynamicTeamContext()
if (!context?.teamName || !context?.agentName) {
return undefined
}
// 读取团队文件获取领导 Agent ID
const teamFile = readTeamFile(teamName)
return {
teamName,
teamFilePath,
leadAgentId: teamFile.leadAgentId,
selfAgentId: agentId,
selfAgentName: agentName,
isLeader,
teammates: {}
}
}
```
### 8.2 从会话恢复团队上下文
```typescript
export function initializeTeammateContextFromSession(
setAppState: (updater: (prev: AppState) => AppState) => void,
teamName: string,
agentName: string
): void {
// 从团队文件读取成员信息
const teamFile = readTeamFile(teamName)
const member = teamFile.members.find(m => m.name === agentName)
const agentId = member?.agentId
// 设置 AppState 中的团队上下文
setAppState(prev => ({
...prev,
teamContext: {
teamName,
teamFilePath,
leadAgentId: teamFile.leadAgentId,
selfAgentId: agentId,
selfAgentName: agentName,
isLeader: false,
teammates: {}
}
}))
}
```
## 9. 队友生成 (spawnUtils.ts, spawnInProcess.ts)
### 9.1 进程内队友生成
```typescript
// 位置:/src/utils/swarm/spawnInProcess.ts
export async function spawnInProcessTeammate(
identity: TeammateIdentity,
context: ToolUseContext
): Promise<{
success: boolean
agentId: string
taskId?: string
teammateContext?: TeammateContext
abortController?: AbortController
error?: string
}>
export function killInProcessTeammate(
taskId: string,
setAppState: (updater: (prev: AppState) => AppState) => void
): boolean
```
### 9.2 进程内运行器
```typescript
// 位置:/src/utils/swarm/inProcessRunner.ts
export async function startInProcessTeammate(params: {
identity: TeammateIdentity
taskId: string
prompt: string
teammateContext: TeammateContext
toolUseContext: ToolUseContext
abortController: AbortController
model?: string
systemPrompt?: string
systemPromptMode?: 'default' | 'replace' | 'append'
allowedTools?: string[]
allowPermissionPrompts?: boolean
}): Promise<void>
```
## 10. TeammateExecutor 接口
### 10.1 接口定义
```typescript
export type TeammateExecutor = {
readonly type: BackendType
isAvailable(): Promise<boolean>
spawn(config: TeammateSpawnConfig): Promise<TeammateSpawnResult>
sendMessage(agentId: string, message: TeammateMessage): Promise<void>
terminate(agentId: string, reason?: string): Promise<boolean>
kill(agentId: string): Promise<boolean>
isActive(agentId: string): Promise<boolean>
}
```
### 10.2 TeammateSpawnConfig
```typescript
export type TeammateSpawnConfig = TeammateIdentity & {
prompt: string
cwd: string
model?: string
systemPrompt?: string
systemPromptMode?: 'default' | 'replace' | 'append'
worktreePath?: string
parentSessionId: string
permissions?: string[]
allowPermissionPrompts?: boolean
}
```
### 10.3 TeammateSpawnResult
```typescript
export type TeammateSpawnResult = {
success: boolean
agentId: string // 格式: agentName@teamName
error?: string
abortController?: AbortController // 进程内队友使用
taskId?: string // AppState.tasks 中的任务 ID
paneId?: PaneId // 基于面板的后端使用
}
```
## 11. 消息类型
### 11.1 TeammateMessage
```typescript
export type TeammateMessage = {
text: string
from: string
color?: string
timestamp?: string
summary?: string // 5-10 字预览
}
```
## 12. 类型守卫
### 12.1 面板后端检查
```typescript
export function isPaneBackend(type: BackendType): type is 'tmux' | 'iterm2' {
return type === 'tmux' || type === 'iterm2'
}
```
## 13. 环境检测
### 13.1 tmux 检测
```typescript
// 检测是否在 tmux 会话内运行
export async function isInsideTmux(): Promise<boolean>
```
### 13.2 iTerm2 检测
```typescript
// 检测 iTerm2 是否可用
export async function isITerm2Available(): Promise<boolean>
```
## 14. 团队常量
**位置:** `/src/utils/swarm/constants.ts`
```typescript
export const TEAM_LEAD_NAME = 'team-lead'
export const DEFAULT_TEAM_PANE_WIDTH = '30%'
export const DEFAULT_TEAM_PANE_HEIGHT = '50%'
```

View File

@@ -0,0 +1,317 @@
# UI 组件系统
Claude Code 的 UI 组件系统是一个复杂的多层架构,结合了 React 组件、Ink 渲染器和终端 UI 技术。本文档详细介绍各层组件的设计和实现。
## 目录结构
```
src/
├── components/ # React 业务组件 (~140个)
├── ink/ # Ink 渲染器封装
│ ├── ink.tsx # 主渲染器 (1722行)
│ ├── components/ # Ink 基础 UI 组件
│ ├── events/ # 事件系统
│ ├── hooks/ # React Hooks
│ ├── layout/ # Yoga 布局引擎封装
│ ├── termio/ # 终端 IO 处理
│ └── screen.ts # 屏幕缓冲区管理
├── screens/ # 全屏 UI 屏幕
│ ├── Doctor.tsx # 诊断屏幕
│ ├── REPL.tsx # REPL 屏幕
│ └── ResumeConversation.tsx # 恢复对话屏幕
└── outputStyles/ # 输出样式管理
```
## 1. Ink 渲染器 (ink/)
Ink 是一个用于构建终端 UI 的 React 渲染器。Claude Code 对其进行了深度定制。
### 1.1 主渲染器 (ink.tsx)
**文件路径**: `src/ink/ink.tsx` (1722行)
**核心类**: `Ink`
**主要职责**:
- 管理 React Fiber 树和渲染生命周期
- 处理终端输入/输出
- 管理帧缓冲区和屏幕更新
- 处理鼠标跟踪和焦点管理
**关键属性**:
```typescript
class Ink {
private readonly log: LogUpdate // 日志更新器
private readonly terminal: Terminal // 终端连接
private scheduleRender: () => void // 渲染调度
private container: FiberRoot // React 容器
private rootNode: dom.DOMElement // 根 DOM 节点
readonly focusManager: FocusManager // 焦点管理器
private renderer: Renderer // 渲染器
private stylePool: StylePool // 样式池
private charPool: CharPool // 字符池
private hyperlinkPool: HyperlinkPool // 超链接池
readonly selection: SelectionState // 文本选择状态
private searchHighlightQuery: string // 搜索高亮查询
}
```
**渲染流程**:
1. 接收 React 组件树
2. 通过 React Reconciler 计算布局 (使用 Yoga 引擎)
3. 将布局结果渲染到屏幕缓冲区
4. 通过终端 IO 输出到终端
### 1.2 Ink 组件 (ink/components/)
#### Box 组件
**文件**: `ink/components/Box.tsx`
Box 是 Ink 的核心布局组件,类似于 Web 的 `div` 和 Flexbox 的结合。
**主要属性**:
```typescript
type Props = {
flexDirection?: 'row' | 'column' // 布局方向
flexGrow?: number // 增长系数
flexShrink?: number // 收缩系数
flexWrap?: 'nowrap' | 'wrap' // 换行策略
gap?: number // 间距
overflowX?: 'visible' | 'hidden' | 'scroll' // 水平溢出
overflowY?: 'visible' | 'hidden' | 'scroll' // 垂直溢出
// 边距
margin?: number
marginX?: number
marginY?: number
padding?: number
// ... 边框、背景等样式
}
```
**使用示例**:
```tsx
<Box flexDirection="column" gap={1} padding={2}>
<Text>Hello</Text>
<Box flexGrow={1}>Content</Box>
</Box>
```
#### Button 组件
**文件**: `ink/components/Button.tsx`
Button 提供交互式按钮组件,支持焦点、悬停和激活状态。
**状态类型**:
```typescript
type ButtonState = {
focused: boolean // 是否获得焦点
hovered: boolean // 是否悬停
active: boolean // 是否激活
}
```
**主要属性**:
```typescript
type Props = {
onAction: () => void // 点击/回车/空格触发
tabIndex?: number // Tab 顺序
autoFocus?: boolean // 自动聚焦
children: ((state: ButtonState) => React.ReactNode) | React.ReactNode
}
```
#### ScrollBox 组件
**文件**: `ink/components/ScrollBox.tsx`
ScrollBox 是支持滚动的容器组件,提供虚拟滚动功能。
**句柄接口**:
```typescript
interface ScrollBoxHandle {
scrollTo(y: number): void // 滚动到指定位置
scrollBy(dy: number): void // 相对滚动
scrollToElement(el: DOMElement, offset?: number): void // 滚动到元素
scrollToBottom(): void // 滚动到底部
getScrollTop(): number // 获取滚动位置
getScrollHeight(): number // 获取内容高度
getViewportHeight(): number // 获取视口高度
isSticky(): boolean // 是否吸附底部
subscribe(listener: () => void): () => void // 订阅滚动变化
setClampBounds(min: number, max: number): void // 设置边界
}
```
**特性**:
- Viewport Culling: 只渲染可见区域内的子元素
- Sticky Scroll: 新内容自动滚动到底部
- 节流渲染: 滚动事件节流,避免过度渲染
#### TerminalFocusContext
**文件**: `ink/components/TerminalFocusContext.tsx`
提供终端焦点状态的 React Context。
#### Other Components
| 组件 | 文件 | 用途 |
|------|------|------|
| Text | Text.tsx | 文本显示,支持颜色、样式 |
| Link | Link.tsx | 超链接渲染 |
| Newline | Newline.tsx | 换行符 |
| Spacer | Spacer.tsx | 空白间距 |
| RawAnsi | RawAnsi.tsx | 原始 ANSI 转义序列 |
| NoSelect | NoSelect.tsx | 禁用选择 |
| ErrorOverview | ErrorOverview.tsx | 错误概览 |
| AlternateScreen | AlternateScreen.tsx | 替代屏幕 |
| App | App.tsx | 根应用组件 |
### 1.3 ANSI 处理 (Ansi.tsx)
**文件**: `src/ink/Ansi.tsx`
Ansi 组件解析并渲染包含 ANSI 转义序列的字符串。
**功能**:
- 解析 SGR (Select Graphic Rendition) 参数
- 支持颜色、背景色、粗体、斜体、下划线等样式
- 支持超链接
- Memoized 防止不必要的重渲染
**属性**:
```typescript
type Props = {
children: string // ANSI 字符串
dimColor?: boolean // 是否淡化颜色
}
```
### 1.4 事件系统 (ink/events/)
```
events/
├── click-event.ts # 点击事件
├── focus-event.ts # 焦点事件
├── keyboard-event.ts # 键盘事件
├── input-event.ts # 输入事件
├── terminal-focus-event.ts # 终端焦点事件
├── terminal-event.ts # 终端事件
├── emitter.ts # 事件发射器
├── dispatcher.ts # 事件分发器
└── event.ts # 事件基类
```
**键盘事件结构**:
```typescript
interface KeyboardEvent {
key: string // 按键名称
ctrl: boolean // Ctrl 修饰键
shift: boolean // Shift 修饰键
alt: boolean // Alt 修饰键
meta: boolean // Meta 修饰键
}
```
### 1.5 布局系统 (ink/layout/)
使用 Facebook Yoga 布局引擎进行 Flexbox 布局计算。
```
layout/
├── yoga.ts # Yoga 引擎封装
├── engine.ts # 布局引擎
├── node.ts # 布局节点
└── geometry.ts # 几何计算
```
### 1.6 终端 IO (ink/termio/)
```
termio/
├── ansi.ts # ANSI 转义序列解析
├── parser.ts # 终端输出解析
├── dec.ts # DEC 私有模式
├── osc.ts # Operating System Commands
├── types.ts # 类型定义
└── tokenize.ts # 标记化
```
## 2. React 业务组件 (components/)
components 目录包含约 140 个 React 组件,提供高级 UI 功能。
### 2.1 主要分类
| 类别 | 示例组件 | 用途 |
|------|----------|------|
| 消息 | Message.tsx, MessageRow.tsx, Messages.tsx | 消息显示 |
| 对话 | ChatInput.tsx, PromptInput/* | 用户输入 |
| 设置 | Settings/*, ThemePicker.tsx | 设置界面 |
| 诊断 | DiagnosticsDisplay.tsx, Doctor.tsx | 问题诊断 |
| 权限 | permissions/* | 权限管理 |
| MCP | MCPServerApprovalDialog.tsx, mcp/* | MCP 服务器 |
| 差分 | StructuredDiff.tsx, FileEditToolDiff.tsx | 差异显示 |
| 搜索 | GlobalSearchDialog.tsx, HistorySearchDialog.tsx | 搜索功能 |
| 任务 | TaskListV2.tsx, tasks/* | 任务管理 |
### 2.2 设计系统 (components/design-system/)
```
design-system/
├── ThemedBox.tsx # 主题化 Box
├── ThemedText.tsx # 主题化 Text
├── ThemeProvider.tsx # 主题提供者
└── color.ts # 颜色工具
```
### 2.3 核心组件示例
#### Message.tsx (~79KB)
消息行组件,处理 Assistant 和 User 消息的渲染。
#### Spinner.tsx (~88KB)
丰富的旋转指示器组件,支持多种变体。
#### Stats.tsx (~153KB)
统计信息显示面板。
## 3. 全屏屏幕 (screens/)
### 3.1 Doctor.tsx (73KB)
诊断屏幕,显示系统健康状态和问题检测。
### 3.2 REPL.tsx (896KB)
最大的组件REPL 交互界面,包含完整的命令行编辑功能。
### 3.3 ResumeConversation.tsx (60KB)
对话恢复屏幕,允许用户恢复之前的会话。
## 4. 输出样式 (outputStyles/)
```
outputStyles/
└── loadOutputStylesDir.ts
```
负责加载和管理输出样式目录。
## 5. 核心概念
### 5.1 帧缓冲区 (Frame)
每帧包含完整的屏幕内容,由 Ink 渲染器管理双缓冲:
- `frontFrame`: 当前显示帧
- `backFrame`: 下一帧(渲染中)
### 5.2 样式池 (StylePool)
重用样式对象,减少内存分配。
### 5.3 Yoga 布局
使用 Yoga 引擎计算 Flexbox 布局,支持:
- flexDirection, justifyContent, alignItems
- flexGrow, flexShrink
- margin, padding, gap
- overflow 处理
### 5.4 虚拟滚动
ScrollBox 通过只渲染可见内容实现虚拟滚动,提升大列表性能。
### 5.5 焦点管理
FocusManager 跟踪键盘焦点,支持 Tab/Shift+Tab 导航。

View File

@@ -0,0 +1,401 @@
# 配置与迁移系统
Claude Code 使用 Zod 进行配置模式验证,并通过迁移系统处理配置版本升级。
## 目录结构
```
src/
├── schemas/ # Zod 配置模式定义
├── migrations/ # 配置迁移脚本
└── utils/settings/ # 设置管理系统
├── settings.ts # 设置管理核心
├── validation.ts # 验证逻辑
├── changeDetector.ts # 变更检测
├── applySettingsChange.ts # 变更应用
├── permissionValidation.ts # 权限规则验证
├── toolValidationConfig.ts # 工具验证配置
├── types.ts # 类型定义
├── constants.ts # 常量
├── mdm/ # 移动设备管理
└── settingsCache.ts # 设置缓存
```
## 1. 配置模式 (schemas/)
### 1.1 主模式文件
**文件**: `src/schemas/hooks.ts` (7884行)
使用 Zod 定义所有配置项的验证模式。
### 1.2 核心模式示例
```typescript
// 基础设置模式
const baseSettingsSchema = z.object({
// 模型配置
model: z.string(),
maxTokens: z.number().optional(),
// UI 设置
theme: z.enum(['dark', 'light', 'system']),
fontSize: z.number().min(8).max(24),
// 权限设置
allowPermissions: z.boolean(),
permissionRules: z.array(permissionRuleSchema).optional(),
})
// MCP 服务器配置
const mcpServerSchema = z.object({
name: z.string(),
command: z.string(),
args: z.array(z.string()).optional(),
env: z.record(z.string()).optional(),
})
```
## 2. 设置管理 (utils/settings/)
### 2.1 设置核心 (settings.ts)
**文件**: `src/utils/settings/settings.ts` (~32KB)
**主要函数**:
| 函数 | 用途 |
|------|------|
| `getSettings()` | 获取当前设置 |
| `updateSettings(partial)` | 更新设置 |
| `resetSettings()` | 重置为默认值 |
| `loadManagedFileSettings()` | 加载托管配置文件 |
| `parseSettingsFile(path)` | 解析设置文件 |
**设置加载优先级** (从低到高):
1. 默认值
2. 托管设置文件 (`managed-settings.json`)
3. 托管设置 Drop-in 目录 (`managed-settings.d/*.json`)
4. 用户设置文件 (`~/.claude/settings.json`)
**托管设置系统**:
```typescript
// 加载托管文件设置
export function loadManagedFileSettings(): {
settings: SettingsJson | null
errors: ValidationError[]
} {
// 1. 加载 managed-settings.json (基础)
// 2. 按字母顺序加载 managed-settings.d/*.json (覆盖)
}
```
### 2.2 变更检测 (changeDetector.ts)
**文件**: `src/utils/settings/changeDetector.ts` (~16KB)
检测设置变更并触发相应的处理逻辑。
**主要功能**:
- 检测设置项的变化
- 生成变更事件
- 防止循环依赖
### 2.3 变更应用 (applySettingsChange.ts)
**文件**: `src/utils/settings/applySettingsChange.ts`
应用设置变更到运行时系统。
```typescript
// 示例:应用主题变更
async function applyThemeChange(theme: Theme): Promise<void> {
// 1. 更新渲染器主题
// 2. 通知所有订阅者
// 3. 持久化到磁盘
}
```
### 2.4 验证 (validation.ts)
**文件**: `src/utils/settings/validation.ts` (~8KB)
**主要函数**:
| 函数 | 用途 |
|------|------|
| `validateSettings(settings)` | 验证完整设置 |
| `validateSetting(key, value)` | 验证单个设置 |
| `formatZodError(error)` | 格式化 Zod 错误 |
| `filterInvalidPermissionRules(rules)` | 过滤无效权限规则 |
**验证流程**:
```typescript
export function validateSettings(
settings: unknown
): SettingsWithErrors {
const result = SettingsSchema.safeParse(settings)
if (result.success) {
return { settings: result.data, errors: [] }
}
// 转换 Zod 错误为友好格式
return {
settings: null,
errors: formatZodError(result.error)
}
}
```
### 2.5 权限验证 (permissionValidation.ts)
**文件**: `src/utils/settings/permissionValidation.ts` (~8.5KB)
验证权限规则的有效性。
**权限规则结构**:
```typescript
interface PermissionRule {
tool: string // 工具名称
path?: string // 路径模式
deny?: boolean // 拒绝还是允许
reason?: string // 原因说明
}
```
**验证规则**:
1. 工具名称必须有效
2. 路径模式必须是有效的 glob 或正则
3. 冲突规则被拒绝
### 2.6 工具验证配置 (toolValidationConfig.ts)
**文件**: `src/utils/settings/toolValidationConfig.ts`
配置哪些工具需要验证或可以直接执行。
```typescript
// 免验证工具
const bypassValidationTools = [
'Read',
'BackgroundRead',
'TodoWrite',
'NotebookEdit',
]
// 需要路径验证的工具
const pathValidationTools = [
'Bash',
'Write',
'Edit',
'Read',
]
```
### 2.7 MDM 配置 (mdm/)
**目录**: `src/utils/settings/mdm/`
支持移动设备管理 (Mobile Device Management) 配置。
```
mdm/
└── settings.ts # MDM 设置加载
```
### 2.8 类型定义 (types.ts)
**文件**: `src/utils/settings/types.ts` (~43KB)
定义所有设置相关的类型。
```typescript
// 设置 JSON 结构
type SettingsJson = {
// 基本设置
model?: string
theme?: 'dark' | 'light' | 'system'
// MCP
mcpServers?: Record<string, McpServerConfig>
// 权限
permissionRules?: PermissionRule[]
// 实验性功能
experimental?: Record<string, boolean>
}
// 设置来源
type SettingSource =
| 'default'
| 'managed'
| 'user'
// 可编辑的设置源
type EditableSettingSource = 'user'
```
## 3. 迁移系统 (migrations/)
### 3.1 迁移文件列表
| 文件 | 用途 |
|------|------|
| `migrateAutoUpdatesToSettings.ts` | 自动更新迁移 |
| `migrateBypassPermissionsAcceptedToSettings.ts` | 绕过权限迁移 |
| `migrateEnableAllProjectMcpServersToSettings.ts` | MCP 服务器迁移 |
| `migrateFennecToOpus.ts` | Fennec → Opus 模型迁移 |
| `migrateLegacyOpusToCurrent.ts` | Legacy Opus 迁移 |
| `migrateOpusToOpus1m.ts` | Opus → Opus 1M 迁移 |
| `migrateReplBridgeEnabledToRemoteControlAtStartup.ts` | REPL 桥接迁移 |
| `migrateSonnet1mToSonnet45.ts` | Sonnet 1M → 4.5 迁移 |
| `migrateSonnet45ToSonnet46.ts` | Sonnet 4.5 → 4.6 迁移 |
| `resetAutoModeOptInForDefaultOffer.ts` | 自动模式重置 |
| `resetProToOpusDefault.ts` | Pro → Opus 默认重置 |
### 3.2 迁移示例
**migrateOpusToOpus1m.ts**:
```typescript
export function migrateOpusToOpus1m(
oldSettings: LegacySettings
): NewSettings {
return {
...oldSettings,
model: oldSettings.model === 'opus' ? 'opus-3-5-20241120' : oldSettings.model,
}
}
```
### 3.3 迁移执行时机
迁移在以下时机执行:
1. 应用启动时
2. 设置加载前
3. 版本检测后
## 4. 常量 (constants.ts)
**文件**: `src/utils/settings/constants.ts` (~5.5KB)
```typescript
// 设置源优先级
const SETTING_SOURCE_PRIORITY: Record<SettingSource, number> = {
default: 0,
managed: 50,
user: 100,
}
// 设置路径
const SETTINGS_DIR = 'settings'
const SETTINGS_FILE = 'settings.json'
const MANAGED_SETTINGS_FILE = 'managed-settings.json'
const MANAGED_SETTINGS_DROPIN_DIR = 'managed-settings.d'
// 默认值
const DEFAULT_MODEL = 'claude-opus-4-5'
const DEFAULT_THEME = 'dark'
const DEFAULT_MAX_TOKENS = 8192
```
## 5. 缓存管理 (settingsCache.ts)
**文件**: `src/utils/settings/settingsCache.ts` (~2.4KB)
```typescript
// 缓存接口
interface SettingsCache {
get(key: string): SettingsJson | null
set(key: string, value: SettingsJson): void
invalidate(key: string): void
clear(): void
}
// 缓存策略
const CACHE_TTL = 5 * 60 * 1000 // 5 分钟
const MAX_CACHE_SIZE = 10
```
## 6. 托管设置系统详解
### 6.1 Drop-in 机制
托管设置支持 Drop-in 目录机制,允许多个配置文件按优先级合并:
```
~/.claude/settings.json # 用户设置
/etc/claude/managed-settings.json # 系统托管基础
/etc/claude/managed-settings.d/
├── 10-base.json # 优先级 10
├── 20-security.json # 优先级 20
└── 30-otel.json # 优先级 30
```
### 6.2 合并规则
1. 基础文件先加载
2. Drop-in 文件按文件名排序后加载
3. 后加载的文件优先级更高
4. 数组字段替换,非数组字段合并
## 7. 配置验证规则
### 7.1 路径验证
```typescript
function validatePath(path: string): boolean {
// 禁止危险路径
if (path.includes('..')) return false
if (path.startsWith('/etc/')) return false
if (path.startsWith('/sys/')) return false
// 检查权限
if (!canAccessPath(path)) return false
return true
}
```
### 7.2 命令验证
```typescript
function validateCommand(command: string): boolean {
// 白名单检查
const allowedCommands = ['read', 'edit', 'bash']
return allowedCommands.includes(command)
}
```
### 7.3 模型名称验证
```typescript
const VALID_MODELS = [
'claude-opus-4-5',
'claude-sonnet-4-6',
'claude-opus-3-5-20241120',
// ...
]
function validateModel(model: string): boolean {
return VALID_MODELS.includes(model)
}
```
## 8. 内部写入标识 (internalWrites.ts)
**文件**: `src/utils/settings/internalWrites.ts`
标识由系统内部触发的设置写入,防止来自用户配置文件的覆盖。
```typescript
// 标记内部写入
export function markInternalWrite(key: string): void {
internalWrites.add(key)
}
// 检查是否为内部写入
export function isInternalWrite(key: string): boolean {
return internalWrites.has(key)
}
```

View File

@@ -0,0 +1,387 @@
# 网络与代理
Claude Code 的网络系统处理代理配置、远程会话管理和服务器模式。
## 目录结构
```
src/
├── upstreamproxy/ # 上游代理配置
│ ├── upstreamproxy.ts # 代理核心
│ └── relay.ts # 代理中继
├── remote/ # 远程会话
│ ├── RemoteSessionManager.ts # 会话管理
│ ├── SessionsWebSocket.ts # WebSocket 会话
│ ├── remotePermissionBridge.ts # 权限桥接
│ └── sdkMessageAdapter.ts # SDK 消息适配
└── server/ # 服务器模式
├── createDirectConnectSession.ts # 直连会话
├── directConnectManager.ts # 直连管理
└── types.ts # 类型定义
```
## 1. 上游代理 (upstreamproxy/)
### 1.1 代理核心 (upstreamproxy.ts)
**文件**: `src/upstreamproxy/upstreamproxy.ts` (~10KB)
管理 Claude Code 与上游服务之间的 HTTP/SOCKS 代理连接。
**核心功能**:
- 代理协议支持 (HTTP, HTTPS, SOCKS4, SOCKS5)
- 代理认证 (Basic,NTLM, Negotiate)
- 连接池管理
- 自动重试和故障转移
**主要类**: `UpstreamProxy`
```typescript
class UpstreamProxy {
// 代理配置
readonly type: 'http' | 'https' | 'socks4' | 'socks5'
readonly host: string
readonly port: number
readonly auth?: ProxyAuth
// 连接池
private pool: ConnectionPool
// 方法
async getConnection(url: URL): Promise<Connection>
async request(req: Request): Promise<Response>
close(): void
}
```
**代理认证**:
```typescript
interface ProxyAuth {
type: 'basic' | 'ntlm' | 'negotiate'
username: string
password?: string
domain?: string // NTLM 专用
}
```
### 1.2 代理中继 (relay.ts)
**文件**: `src/upstreamproxy/relay.ts` (~15KB)
在代理链中转发请求,支持多层代理。
**功能**:
- 代理链构建
- 请求/响应转发
- 头部处理
- 连接复用
```typescript
class ProxyRelay {
// 上游代理链
private relays: UpstreamProxy[]
// 添加跳点
addHop(proxy: UpstreamProxy): void
// 转发请求
async relayRequest(req: Request): Promise<Response>
}
```
## 2. 远程会话 (remote/)
### 2.1 会话管理器 (RemoteSessionManager.ts)
**文件**: `src/remote/RemoteSessionManager.ts` (~9KB)
管理远程 Claude Code 实例的会话。
**核心功能**:
- 会话生命周期管理
- 连接状态监控
- 消息路由
- 断开重连
**主要接口**:
```typescript
interface RemoteSession {
id: string
remoteId: string
status: 'connecting' | 'connected' | 'disconnected'
createdAt: number
lastActivity: number
}
class RemoteSessionManager {
// 创建会话
async createSession(config: RemoteConfig): Promise<RemoteSession>
// 获取会话
getSession(id: string): RemoteSession | null
// 列出所有会话
listSessions(): RemoteSession[]
// 终止会话
async terminateSession(id: string): Promise<void>
// 事件
onSessionCreated: Event<RemoteSession>
onSessionClosed: Event<string>
onSessionError: Event<{ id: string; error: Error }>
}
```
### 2.2 WebSocket 会话 (SessionsWebSocket.ts)
**文件**: `src/remote/SessionsWebSocket.ts` (~12.5KB)
通过 WebSocket 管理远程会话的实时通信。
**功能**:
- WebSocket 连接建立
- 心跳检测
- 消息序列化/反序列化
- 重连逻辑
```typescript
class SessionsWebSocket {
// 连接 URL
readonly url: string
// WebSocket 实例
private ws: WebSocket
// 状态
get status(): 'connecting' | 'open' | 'closing' | 'closed'
// 发送消息
send(message: SessionMessage): void
// 接收消息
onMessage: (message: SessionMessage) => void
// 重连
async reconnect(): Promise<void>
}
```
### 2.3 权限桥接 (remotePermissionBridge.ts)
**文件**: `src/remote/remotePermissionBridge.ts` (~2.4KB)
在远程会话中桥接权限检查。
```typescript
// 本地权限检查
const localCheck = await checkPermission(tool, args)
// 远程权限请求
const remoteGrant = await remoteSession.requestPermission({
tool,
args,
reason: 'Remote session requested'
})
// 合并结果
return localCheck || remoteGrant
```
### 2.4 SDK 消息适配器 (sdkMessageAdapter.ts)
**文件**: `src/remote/sdkMessageAdapter.ts` (~9KB)
适配 Claude SDK 消息格式与内部消息格式。
```typescript
// SDK 消息 -> 内部消息
function adaptFromSDK(sdkMessage: SDKMessage): InternalMessage
// 内部消息 -> SDK 消息
function adaptToSDK(internalMessage: InternalMessage): SDKMessage
// 工具结果适配
function adaptToolResult(result: ToolResult): ToolResultBlockParam
```
## 3. 服务器模式 (server/)
### 3.1 直连会话 (createDirectConnectSession.ts)
**文件**: `src/server/createDirectConnectSession.ts` (~2.2KB)
创建直接的点对点连接会话。
```typescript
interface DirectConnectConfig {
remoteId: string
authToken: string
endpoint: URL
}
async function createDirectConnectSession(
config: DirectConnectConfig
): Promise<DirectSession> {
// 1. 验证配置
validateConfig(config)
// 2. 建立连接
const connection = await establishConnection(config)
// 3. 创建会话
return new DirectSession(connection)
}
```
### 3.2 直连管理器 (directConnectManager.ts)
**文件**: `src/server/directConnectManager.ts` (~6KB)
管理所有直连会话。
**功能**:
- 会话注册/注销
- 连接状态跟踪
- 资源清理
- 并发控制
```typescript
class DirectConnectManager {
// 注册新会话
register(session: DirectSession): void
// 注销会话
unregister(sessionId: string): void
// 获取活跃会话
getActiveSessions(): DirectSession[]
// 广播消息
broadcast(message: Message): void
// 清理闲置会话
cleanupIdleSessions(): void
}
```
### 3.3 类型定义 (types.ts)
**文件**: `src/server/types.ts`
```typescript
// 服务器模式配置
interface ServerConfig {
host: string
port: number
tls: boolean
cert?: string
key?: string
}
// 直连配置
interface DirectConnectConfig {
remoteId: string
authToken: string
endpoint: string
}
// 会话消息
interface SessionMessage {
type: 'query' | 'result' | 'error' | 'heartbeat'
sessionId: string
payload: unknown
timestamp: number
}
```
## 4. 连接流程
### 4.1 远程会话建立
```
Client Server
| |
|--- WebSocket Connect --------->|
| |
|<-- Handshake Challenge -------|
| |
|--- Handshake Response ------->|
| |
|<-- Session Created ----------|
| |
|<====== Session Active =======>|
| |
|<-- Session Terminated --------|
```
### 4.2 代理请求流程
```
Claude Code
|
v
UpstreamProxy
|
+---> HTTP Proxy
|
+---> SOCKS5 Proxy
|
v
Anthropic API
```
## 5. 安全考虑
### 5.1 TLS/SSL
- 服务器模式支持 TLS 终止
- 证书验证可选
- 支持自签名证书 (开发模式)
### 5.2 认证
- Token-based 认证
- 定期心跳检测
- 会话超时控制
### 5.3 网络隔离
- 敏感数据加密传输
- 代理链逐跳认证
- 审计日志记录
## 6. 配置示例
### 6.1 代理配置 (settings.json)
```json
{
"proxy": {
"type": "socks5",
"host": "proxy.example.com",
"port": 1080,
"auth": {
"type": "basic",
"username": "user",
"password": "pass"
}
}
}
```
### 6.2 服务器模式配置
```json
{
"server": {
"enabled": true,
"host": "0.0.0.0",
"port": 8080,
"tls": true,
"cert": "/path/to/cert.pem",
"key": "/path/to/key.pem"
}
}
```

View File

@@ -0,0 +1,496 @@
# 其他重要模块
本文档介绍 Claude Code 中不属于前几章的重要模块。
## 目录结构
```
src/
├── bootstrap/ # 启动引导
├── memdir/ # 持久化内存目录
├── native-ts/ # 原生 TypeScript 工具
│ ├── yoga-layout/ # Yoga 布局引擎
│ ├── file-index/ # 文件索引
│ └── color-diff/ # 颜色差异计算
├── voice/ # 语音输入
├── vim/ # Vim 模式
├── keybindings/ # 快捷键配置
├── moreright/ # 权限扩展 UI
├── outputStyles/ # 输出样式管理
└── query/ # 查询管道
├── tokenBudget.ts # Token 预算管理
├── stopHooks.ts # 停止钩子
└── config.ts # 查询配置
```
## 1. 启动引导 (bootstrap/)
### 1.1 引导状态 (state.ts)
**文件**: `src/bootstrap/state.ts` (~56KB)
管理应用启动状态和全局状态。
**主要功能**:
- 启动时间跟踪
- 交互时间统计
- 功能开关状态
- 工作目录管理
**关键函数**:
| 函数 | 用途 |
|------|------|
| `getOriginalCwd()` | 获取原始工作目录 |
| `getKairosActive()` | 获取 Kairos 状态 |
| `flushInteractionTime()` | 刷新交互时间 |
| `markScrollActivity()` | 标记滚动活动 |
## 2. 持久化内存 (memdir/)
### 2.1 内存目录核心 (memdir.ts)
**文件**: `src/memdir/memdir.ts` (~21KB)
管理 MEMORY.md 文件和自动记忆系统。
**主要功能**:
- 内存文件读写
- 记忆检索
- 入口点截断
- 团队记忆管理
**关键常量**:
```typescript
export const ENTRYPOINT_NAME = 'MEMORY.md'
export const MAX_ENTRYPOINT_LINES = 200
export const MAX_ENTRYPOINT_BYTES = 25_000
```
**截断函数**:
```typescript
export function truncateEntrypointContent(
raw: string
): EntrypointTruncation {
// 1. 按行截断 (最多200行)
// 2. 按字节截断 (最多25KB)
// 3. 返回截断结果和警告信息
}
```
### 2.2 记忆类型 (memoryTypes.ts)
**文件**: `src/memdir/memoryTypes.ts` (~23KB)
定义记忆相关的数据结构和常量。
```typescript
// 记忆入口
interface MemoryEntry {
id: string
type: 'individual' | 'team'
keywords: string[]
content: string
createdAt: number
accessedAt: number
}
// 记忆类型
const TYPES_SECTION_INDIVIDUAL = ...
const TRUSTING_RECALL_SECTION = ...
const WHAT_NOT_TO_SAVE_SECTION = ...
```
### 2.3 路径管理 (paths.ts)
**文件**: `src/memdir/paths.ts` (~11KB)
管理内存目录的路径计算。
```typescript
export function getMemoryDir(): string {
return join(getProjectDir(), '.claude', 'memory')
}
export function getAutoMemPath(): string {
return join(getMemoryDir(), 'auto', 'MEMORY.md')
}
```
### 2.4 相关文件
| 文件 | 用途 |
|------|------|
| `findRelevantMemories.ts` | 查找相关记忆 |
| `memoryAge.ts` | 记忆老化计算 |
| `memoryScan.ts` | 记忆扫描 |
| `teamMemPaths.ts` | 团队记忆路径 |
| `teamMemPrompts.ts` | 团队记忆提示词 |
## 3. 原生 TypeScript 工具 (native-ts/)
### 3.1 Yoga 布局引擎 (yoga-layout/)
封装 Facebook Yoga 布局引擎。
**注意**: Yoga 是用 C++ 编写的,通过原生绑定调用。
```typescript
// 获取 Yoga 计数器
export function getYogaCounters(): {
ms: number
visited: number
measured: number
cacheHits: number
live: number
}
```
### 3.2 文件索引 (file-index/)
文件内容的快速索引系统。
**用途**:
- 代码搜索加速
- 上下文构建
- 记忆检索
### 3.3 颜色差异 (color-diff/)
计算颜色之间的视觉差异。
```typescript
// Delta E (CIE2000) 计算
export function colorDistance(
color1: RGB,
color2: RGB
): number {
// 返回 Delta E 值
// < 1: 几乎不可察觉
// 1-2: 轻微差异
// 2-5: 有感差异
// > 5: 明显差异
}
```
## 4. 语音输入 (voice/)
### 4.1 语音模式启用 (voiceModeEnabled.ts)
**文件**: `src/voice/voiceModeEnabled.ts`
检查语音输入模式是否启用。
```typescript
export function isVoiceModeEnabled(): boolean {
return isEnvTruthy('VOICE_MODE_ENABLED')
}
```
## 5. Vim 模式 (vim/)
### 5.1 模块结构
```
vim/
├── motions.ts # 动作 (h/j/k/l/w/b/e/...)
├── operators.ts # 操作符 (d/y/c/s/r)
├── textObjects.ts # 文本对象 (iw/aW/is/as/...)
├── transitions.ts # 状态转换
└── types.ts # 类型定义
```
### 5.2 核心概念
**动作 (Motions)**:
```typescript
// 基础动作
type Motion =
| { type: 'char'; direction: 'left' | 'right' }
| { type: 'word'; direction: 'forward' | 'backward' }
| { type: 'line'; direction: 'up' | 'down' }
| { type: 'lineStart' }
| { type: 'lineEnd' }
```
**操作符 (Operators)**:
```typescript
type Operator =
| { type: 'delete' }
| { type: 'yank' }
| { type: 'change' }
| { type: 'replace' }
| { type: 'swapCase' }
```
**状态机**:
```typescript
type VimState =
| 'normal' // 普通模式
| 'insert' // 插入模式
| 'visual' // 可视模式
| 'operator' // 操作符等待
```
### 5.3 状态转换 (transitions.ts)
**文件**: `src/vim/transitions.ts` (~12KB)
管理 Vim 模式的状态转换。
```typescript
// 转换函数
function transition(
state: VimState,
input: VimInput
): VimState
// 示例: Normal -> Insert
// i -> Insert
// a -> Insert (after cursor)
// o -> Insert (new line below)
// 示例: Normal -> Visual
// v -> Visual (character-wise)
// V -> Visual (line-wise)
```
## 6. 快捷键配置 (keybindings/)
### 6.1 模块结构
```
keybindings/
├── defaultBindings.ts # 默认绑定
├── KeybindingContext.tsx # 快捷键上下文
├── KeybindingProviderSetup.tsx # 提供者设置
├── loadUserBindings.ts # 加载用户绑定
├── match.ts # 匹配逻辑
├── parser.ts # 解析器
├── resolver.ts # 解析器
├── schema.ts # 模式定义
├── useKeybinding.ts # Hook
├── validate.ts # 验证
└── template.ts # 模板
```
### 6.2 默认绑定 (defaultBindings.ts)
**文件**: `src/keybindings/defaultBindings.ts` (~12KB)
定义默认键盘快捷键。
```typescript
export const DEFAULT_BINDINGS: KeyBinding[] = [
// 编辑
{ key: 'ctrl+c', action: 'copy' },
{ key: 'ctrl+v', action: 'paste' },
{ key: 'ctrl+z', action: 'undo' },
// 导航
{ key: 'ctrl+p', action: 'previousItem' },
{ key: 'ctrl+n', action: 'nextItem' },
// 特定
{ key: 'ctrl+o', action: 'expand' },
{ key: 'escape', action: 'dismiss' },
]
```
### 6.3 快捷键解析 (parser.ts)
解析用户定义的快捷键字符串。
```typescript
// 解析 "ctrl+shift+k"
parseKeybinding("ctrl+shift+k")
// -> {
// ctrl: true,
// shift: true,
// key: 'k'
// }
```
### 6.4 快捷键验证 (validate.ts)
验证快捷键定义的有效性。
```typescript
export function validateBinding(
binding: KeyBinding
): ValidationResult {
// 1. 检查修饰键组合
// 2. 检查冲突
// 3. 检查保留键
}
```
### 6.5 使用 Hook (useKeybinding.ts)
React Hook 用于在组件中使用快捷键。
```typescript
function useKeybinding(
key: string,
handler: () => void,
options?: {
enabled?: boolean
scope?: 'global' | 'local'
}
): void
```
## 7. 权限扩展 UI (moreright/)
### 7.1 权限扩展组件 (useMoreRight.tsx)
**文件**: `src/moreright/useMoreRight.tsx`
提供额外的权限扩展 UI。
```typescript
function useMoreRight(): {
// 权限请求
requestPermission: (
tool: string,
args: unknown
) => Promise<boolean>
// 权限状态
hasPermission: (tool: string) => boolean
// 打开权限面板
openPermissionPanel: () => void
}
```
## 8. 输出样式管理 (outputStyles/)
### 8.1 样式加载 (loadOutputStylesDir.ts)
**文件**: `src/outputStyles/loadOutputStylesDir.ts`
加载输出样式目录中的自定义样式。
```typescript
export function loadOutputStylesDir(
dirPath: string
): OutputStyle[] {
// 1. 扫描目录
// 2. 解析样式文件
// 3. 验证样式
// 4. 返回样式列表
}
```
## 9. 查询管道 (query/)
### 9.1 Token 预算管理 (tokenBudget.ts)
**文件**: `src/query/tokenBudget.ts`
管理查询的 Token 预算。
```typescript
export interface TokenBudget {
total: number // 总预算
used: number // 已使用
reserved: number // 预留
remaining: number // 剩余
}
// 预算检查
export function checkBudget(budget: TokenBudget): boolean {
return budget.remaining > 0
}
// 预算分配
export function allocateBudget(
budget: TokenBudget,
amount: number
): TokenBudget {
return {
...budget,
used: budget.used + amount,
remaining: budget.total - budget.used - amount
}
}
```
### 9.2 停止钩子 (stopHooks.ts)
**文件**: `src/query/stopHooks.ts` (~17KB)
定义查询停止时的回调钩子。
```typescript
export type StopHook = {
id: string
name: string
priority: number
execute: (context: StopContext) => Promise<void>
}
export interface StopContext {
queryId: string
reason: 'complete' | 'error' | 'user_cancel'
tokensUsed: number
duration: number
}
// 注册钩子
export function registerStopHook(hook: StopHook): void
// 执行钩子
export async function executeStopHooks(
context: StopContext
): Promise<void> {
const hooks = getHooks()
.sort((a, b) => b.priority - a.priority)
for (const hook of hooks) {
await hook.execute(context)
}
}
```
### 9.3 查询配置 (config.ts)
**文件**: `src/query/config.ts`
```typescript
export interface QueryConfig {
// 模型
model: string
maxTokens: number
// 预算
tokenBudget: number
// 停止条件
stopHooks: string[]
// 工具配置
tools: ToolConfig[]
// 上下文
systemPrompt?: string
contextFiles?: string[]
}
```
## 10. 总结
这些模块提供了 Claude Code 的重要辅助功能:
| 模块 | 核心功能 |
|------|----------|
| bootstrap | 应用启动和状态管理 |
| memdir | 持久化记忆系统 |
| native-ts | 性能关键原生工具 |
| voice | 语音输入支持 |
| vim | Vim 模式编辑 |
| keybindings | 快捷键系统 |
| moreright | 权限扩展 |
| outputStyles | 输出样式 |
| query | 查询管道 |

View File

@@ -0,0 +1,171 @@
# Claude Code 源码中文 Wiki
本文件说明:总索引文档,介绍整个 Wiki 的结构和各部分内容。
## 概述
Claude Code 是 Anthropic 开发的 CLI 工具,用于在终端环境中与 Claude 交互完成软件工程任务。本 Wiki 基于 2026-03-31 通过 npm source map 泄露的源码进行详细分析。
## 项目规模
- **文件数量**:约 1900 个文件
- **代码规模**512K+ 行代码
- **源码泄露时间**2026-03-31通过 npm source map
## 技术栈
| 组件 | 技术 |
|------|------|
| 运行时 | Bun |
| 语言 | TypeScript |
| 终端 UI | React + Ink |
| CLI 框架 | Commander.js |
| 参数校验 | Zod v4 |
| 代码搜索 | ripgrep |
| 构建工具 | Bun bundle |
## Wiki 结构
### 1. 架构总览 (`01-架构总览.md`)
介绍 Claude Code 的整体架构设计,包括:
- 项目背景与定位
- 技术栈详解
- 核心架构设计
- 源码泄露事件
### 2. 核心模块详解 (`02-核心模块详解.md`)
详细分析以下核心文件的实现原理:
| 文件 | 功能 |
|------|------|
| `src/main.tsx` | CLI 入口点,应用程序初始化 |
| `src/QueryEngine.ts` | LLM 查询引擎核心处理流式响应、工具调用循环、思考模式、重试逻辑、token 计数 |
| `src/Tool.ts` | 工具基类和接口定义,工具注册表核心 |
| `src/commands.ts` | 命令注册中心,所有 slash command 的注册和管理 |
| `src/context.ts` | 系统/用户上下文收集Git 状态、CLAUDE.md 处理 |
| `src/cost-tracker.ts` | Token 成本追踪,费用计算 |
| `src/query.ts` | 查询管道,消息处理循环 |
### 3. 工具系统 (`03-工具系统.md`)
详细介绍所有内置工具的实现:
**文件操作工具**
- `BashTool` - 执行 Shell 命令
- `FileReadTool` - 读取文件支持文本、图片、PDF、Jupyter Notebook
- `FileWriteTool` - 写入文件
- `FileEditTool` - 编辑文件(支持 Search/Replace 模式)
- `GlobTool` - 文件模式匹配
- `GrepTool` - 代码搜索
- `NotebookEditTool` - Jupyter Notebook 编辑
**Web 工具**
- `WebFetchTool` - 获取网页内容
- `WebSearchTool` - 网络搜索
**Agent 与团队工具**
- `AgentTool` - 创建和管理子 Agent
- `TeamCreateTool` - 创建 Agent 团队
- `TeamDeleteTool` - 删除团队
- `SendMessageTool` - 向团队成员发送消息
**任务管理工具**
- `TaskCreateTool` - 创建任务
- `TaskGetTool` - 获取任务详情
- `TaskUpdateTool` - 更新任务状态
- `TaskListTool` - 列出任务
- `TaskStopTool` - 停止任务
- `TaskOutputTool` - 获取任务输出
- `TodoWriteTool` - 待办事项管理
**模式与工作流工具**
- `EnterPlanModeTool` - 进入计划模式
- `ExitPlanModeTool` - 退出计划模式
- `EnterWorktreeTool` - 进入 Git Worktree
- `ExitWorktreeTool` - 退出 Git Worktree
**搜索与技能工具**
- `ToolSearchTool` - 工具搜索
- `SkillTool` - 技能执行
- `MCPTool` - Model Context Protocol 工具
**其他工具**
- `LSPTool` - 语言服务器协议工具
- `CronCreateTool` - 创建定时任务
- `RemoteTriggerTool` - 远程触发器
- `SleepTool` - 延迟执行
- `SyntheticOutputTool` - 结构化输出
## 核心概念
### 1. 工具系统 (Tool System)
Claude Code 的工具系统基于 `Tool` 基类构建,每个工具实现:
- `call()` - 工具执行逻辑
- `description()` - 工具描述
- `inputSchema` - 输入参数校验
- `checkPermissions()` - 权限检查
- `renderToolUseMessage()` - 渲染工具使用消息
- `renderToolResultMessage()` - 渲染工具结果消息
### 2. 查询引擎 (Query Engine)
QueryEngine 是核心查询处理组件:
- 管理对话生命周期
- 处理流式 API 响应
- 执行工具调用循环
- 支持思考模式 (Thinking Mode)
- 实现自动压缩 (Auto-compact) 机制
### 3. 命令系统 (Command System)
命令系统支持多种命令类型:
- `prompt` - 展开为提示文本发送给模型
- `local` - 本地执行的命令
- `local-jsx` - 本地执行并渲染 Ink UI
### 4. 上下文管理 (Context Management)
上下文系统收集:
- Git 状态信息
- CLAUDE.md 文件内容
- 用户上下文
- 系统上下文
### 5. 成本追踪 (Cost Tracking)
成本追踪系统记录:
- 输入/输出 Token 数量
- 缓存读写 Token
- Web 搜索请求次数
- API 调用时长
## 目录结构
```
claude-code-源码/
├── src/
│ ├── main.tsx # CLI 入口
│ ├── QueryEngine.ts # 查询引擎
│ ├── Tool.ts # 工具基类
│ ├── commands.ts # 命令注册
│ ├── context.ts # 上下文收集
│ ├── cost-tracker.ts # 成本追踪
│ ├── query.ts # 查询管道
│ ├── tools/ # 工具实现
│ │ ├── BashTool/
│ │ ├── FileReadTool/
│ │ ├── FileEditTool/
│ │ ├── AgentTool/
│ │ └── ...(其他工具)
│ └── ...(其他模块)
└── package.json
```
## 扩展阅读
- 深入理解工具系统请阅读 `03-工具系统.md`
- 深入理解核心模块请阅读 `02-核心模块详解.md`
- 架构概览请阅读 `01-架构总览.md`