Core 包解析
概述
packages/core 是 gemini-cli 的核心,包含 Agent 的所有逻辑。
目录结构
packages/core/src/
├── core/ # 核心类
├── tools/ # 工具实现
├── services/ # 服务层
├── agents/ # Agent 系统
├── mcp/ # MCP 集成
├── hooks/ # 扩展钩子
├── policy/ # 策略引擎
├── telemetry/ # 遥测
└── utils/ # 工具函数核心类
GeminiClient
Agent 的主控制器,负责运行 Agent 循环。
文件:core/client.ts
关键职责:
- 管理对话状态
- 执行 Agent 循环
- 调度工具执行
- 处理用户确认
typescript
// 简化的 GeminiClient 结构
class GeminiClient {
private chat: GeminiChat
private tools: ServerTool[]
private conversation: Message[]
// 运行 Agent 循环
async run(userMessage: string): AsyncGenerator<GeminiEvent> {
this.conversation.push({ role: 'user', content: userMessage })
while (true) {
const response = await this.chat.send(this.conversation)
for (const event of this.processResponse(response)) {
yield event
if (event.type === 'ToolCallRequest') {
const result = await this.executeToolCall(event)
this.conversation.push(/* result */)
}
}
if (/* 完成 */) break
}
}
}GeminiChat
封装 Gemini API 调用。
文件:core/geminiChat.ts
关键职责:
- 管理 API 连接
- 处理流式响应
- Token 计数
typescript
// 简化的 GeminiChat 结构
class GeminiChat {
private model: GenerativeModel
private chat: Chat
async send(contents: Content[]): AsyncGenerator<Chunk> {
const result = await this.chat.sendMessageStream(contents)
for await (const chunk of result.stream) {
yield this.processChunk(chunk)
}
}
}Turn 和事件系统
定义 Agent 运行中的各种事件。
文件:core/turn.ts
typescript
// 事件类型
type GeminiEventType =
| 'Content' // 文本输出
| 'ToolCallRequest' // 工具调用请求
| 'ToolCallResponse' // 工具执行结果
| 'Thought' // 思考过程
| 'Error' // 错误
| 'ChatCompressed' // 对话压缩
| 'LoopDetected' // 循环检测
// 事件基础结构
interface GeminiEvent {
type: GeminiEventType
timestamp: number
data: unknown
}工具系统
工具接口
文件:tools/tool.ts
typescript
interface ServerTool {
name: string
schema: FunctionDeclaration
execute(params: unknown, signal?: AbortSignal): Promise<ToolResult>
shouldConfirmExecute?(params: unknown): Promise<ConfirmDetails | false>
}工具实现
以 read-file.ts 为例:
typescript
// tools/read-file.ts (简化)
export const readFileTool: ServerTool = {
name: 'read_file',
schema: {
name: 'read_file',
description: '读取文件内容',
parameters: {
type: 'object',
properties: {
file_path: { type: 'string' },
offset: { type: 'number' },
limit: { type: 'number' }
},
required: ['file_path']
}
},
async execute({ file_path, offset, limit }) {
const content = await fs.readFile(file_path, 'utf-8')
// 处理分页、截断等
return { content }
}
}工具注册
所有工具在启动时注册:
typescript
// 工具列表
const tools: ServerTool[] = [
readFileTool,
writeFileTool,
editFileTool,
shellTool,
grepTool,
globTool,
webFetchTool,
// ...
]服务层
LoopDetectionService
检测 Agent 是否陷入循环。
文件:services/loopDetection.ts
typescript
class LoopDetectionService {
private recentActions: Action[] = []
onAction(action: Action) {
this.recentActions.push(action)
// 保持滑动窗口
}
detect(): LoopResult {
// 检查重复模式
// 检查最大轮次
// 检查连续错误
}
}ChatCompressionService
当对话过长时压缩历史。
文件:services/chatCompression.ts
typescript
class ChatCompressionService {
async compress(messages: Message[]): Promise<Message[]> {
const tokenCount = await this.countTokens(messages)
if (tokenCount < threshold) {
return messages
}
// 找到分割点
// 总结早期消息
// 返回压缩后的消息
}
}ChatRecordingService
保存和恢复会话。
文件:services/chatRecording.ts
typescript
class ChatRecordingService {
saveCheckpoint(conversation: Conversation) {
// 保存到文件
}
loadCheckpoint(id: string): Conversation {
// 从文件恢复
}
}代码流程
用户输入 "读取 package.json" 的完整流程:
1. CLI 接收输入
↓
2. GeminiClient.run("读取 package.json")
↓
3. 添加到 conversation
↓
4. GeminiChat.send(conversation)
↓
5. Gemini API 返回 ToolCallRequest(read_file)
↓
6. GeminiClient 找到 readFileTool
↓
7. readFileTool.execute({ file_path: "package.json" })
↓
8. 返回文件内容
↓
9. 添加结果到 conversation
↓
10. GeminiChat.send(conversation)
↓
11. Gemini API 返回文本响应
↓
12. 输出给用户关键设计模式
1. 事件驱动
使用 Generator 函数产生事件流:
typescript
async *run(): AsyncGenerator<GeminiEvent> {
// 产生事件而不是直接处理
yield { type: 'Content', data: '...' }
yield { type: 'ToolCallRequest', data: {...} }
}2. 依赖注入
服务通过构造函数注入:
typescript
class GeminiClient {
constructor(
private chat: GeminiChat,
private loopDetector: LoopDetectionService,
private compression: ChatCompressionService
) {}
}3. 接口抽象
工具通过统一接口定义:
typescript
// 所有工具实现相同接口
interface ServerTool {
name: string
execute(params: unknown): Promise<ToolResult>
}学习建议
- 从类型开始:先读
turn.ts理解数据结构 - 看简单工具:
read-file.ts是最简单的工具 - 理解主循环:
client.ts的 run 方法是核心 - 调试运行:用 console.log 跟踪执行流程
小结
- Core 包实现了完整的 Agent 逻辑
- GeminiClient 是主控制器
- 工具系统设计简洁统一
- 服务层处理各种辅助功能
下一步
源码走读完成,接下来动手实践:构建迷你 Agent →