微信扫码
添加专属顾问
我要投稿
Gemini CLI 作为首个开源通用命令行智能体工具,其高效的Agent设计与上下文管理机制值得深入探讨。 核心内容: 1. 主控Agent循环的四大核心组件解析 2. 双重循环检测机制的实现原理 3. 会话轮次限制与历史压缩处理策略
gemini-cli
从开源至今仅一个多月,已经收获接近65K Star,作为第一个开源的通用命令行智能体工具,在开源社区贡献者的参与下,现如今功能已经非常完善。本文将对源码进行解析,学习其中优秀Agent的设计思路,将重点关注主控Agent以及上下文管理的实现,对于其他部分不在本文的讨论范围之内。
gemini-cli
的 Agent 循环主要由以下几个核心组件构成:
client.ts
) - 主控制器turn.ts
) - 单轮对话管理coreToolScheduler.ts
) - 工具调用调度loopDetectionService.ts
) - 循环检测// 主要入口点在 GeminiClient.sendMessageStream
asyncsendMessageStream(prompt:string, prompt_id?:string):Promise<AsyncGenerator<ServerGeminiStreamEvent>>{
// 1. 会话轮次限制检查
if(this.turnCount>=this.MAX_TURNS){
thrownewError(`Maximum turns (${this.MAX_TURNS}) reached`);
}
// 2. 聊天历史压缩
const compressed =awaitthis.tryCompressChat(prompt_id);
// 3. 循环检测
const loopDetected =awaitthis.loopDetectionService.checkForLoop(...);
// 4. 创建 Turn 实例并执行
const turn =newTurn(this.chat,this.coreToolScheduler,...);
return turn.run();
}
在主循环过程中,系统实现了双重循环检测机制,确保系统不会陷入无限的工具调用或内容生成循环:
prompt_id
开始时重置一个基本的内容检测方法,用于快速检测内容块是否存在重复。基本原理如下:
CONTENT_CHUNK_SIZE = 100
字符的固定大小块CONTENT_LOOP_THRESHOLD = 10
次时,计算平均距离1.5 × 块大小
,则判定为循环class LoopDetectionService{
privatestaticreadonlyCHUNK_SIZE=100;// 固定块大小
privatestaticreadonlyMIN_REPETITIONS=3;// 最小重复次数
privatecontentHashes:Map<string,number[]>=newMap();
analyzeContentChunksForLoop(content:string):boolean{
const chunks =this.createFixedSizeChunks(content,this.CHUNK_SIZE);
for(let i =0; i < chunks.length; i++){
const hash =this.hashContent(chunks[i]);
if(!this.contentHashes.has(hash)){
this.contentHashes.set(hash,[]);
}
const positions =this.contentHashes.get(hash)!;
positions.push(i);
// 检查是否有足够的重复
if(positions.length>=this.MIN_REPETITIONS){
const intervals =this.calculateIntervals(positions);
if(this.hasConsistentPattern(intervals)){
returntrue;// 检测到循环
}
}
}
returnfalse;
}
privatecreateFixedSizeChunks(content:string,size:number):string[]{
constchunks:string[]=[];
for(let i =0; i <= content.length- size; i += size){
chunks.push(content.substring(i, i + size));
}
return chunks;
}
privatehashContent(content:string):string{
// 使用简单的哈希算法
let hash =0;
for(let i =0; i < content.length; i++){
constchar= content.charCodeAt(i);
hash =((hash <<5)- hash)+char;
hash = hash & hash;// 转换为32位整数
}
return hash.toString();
}
}
试用LLM结合上下文判断是否出现内容循环,设置条件如下:
class LoopDetectionService{
privatestaticreadonlyDEFAULT_CHECK_INTERVAL=5;// 默认检查间隔
privatestaticreadonlyHIGH_CONFIDENCE_THRESHOLD=0.8;
privatestaticreadonlyMEDIUM_CONFIDENCE_THRESHOLD=0.6;
asynccheckForLoopWithLLM(history:ChatMessage[]):Promise<LoopCheckResult>{
const recentHistory = history.slice(-10);// 取最近10条消息
const prompt =this.buildLoopDetectionPrompt(recentHistory);
const response =awaitthis.llmClient.generateContent(prompt);
const result =this.parseLoopDetectionResponse(response);
// 根据置信度调整下次检查间隔
if(result.confidence>=this.HIGH_CONFIDENCE_THRESHOLD){
this.nextCheckInterval=2;// 高置信度,更频繁检查
}elseif(result.confidence>=this.MEDIUM_CONFIDENCE_THRESHOLD){
this.nextCheckInterval=3;// 中等置信度
}else{
this.nextCheckInterval=this.DEFAULT_CHECK_INTERVAL;// 低置信度,正常间隔
}
return result;
}
privatebuildLoopDetectionPrompt(history:ChatMessage[]):string{
return`
分析以下对话历史,判断AI助手是否陷入了非生产性的循环状态:
${history.map(msg => `${msg.role}: ${msg.content}`).join('\n')}
请评估:
1. 是否存在重复的响应模式
2. 是否在执行相同的无效操作
3. 是否缺乏实质性进展
返回JSON格式:{"isLoop": boolean, "confidence": number, "reason": string}
`;
}
}
Turn
类是单轮对话的核心管理器,负责处理流式响应和工具调用:
class Turn{
privatependingToolCalls:ToolCall[]=[];
async*run():AsyncGenerator<ServerGeminiStreamEvent>{
// 处理响应流
forawait(const response ofthis.chat.sendMessageStream(this.prompt)){
// 处理 thought 部分
if(response.thought){
yield{type:GeminiEventType.Thought,content: response.thought};
}
// 处理文本内容
if(response.text){
yield{type:GeminiEventType.Content,content: response.text};
}
// 处理函数调用
if(response.functionCalls){
for(const call of response.functionCalls){
this.handlePendingFunctionCall(call);
}
}
}
// 处理待处理的工具调用
if(this.pendingToolCalls.length>0){
yield*this.handleToolCalls();
}
}
privatehandlePendingFunctionCall(call:FunctionCall):void{
this.pendingToolCalls.push({
id:generateId(),
name: call.name,
params: call.args
});
}
}
gemini-cli
采用 纯内存 + 文件系统的混合存储方案, 不依赖数据库 :
// 压缩触发条件和参数
staticreadonlyCOMPRESSION_TOKEN_THRESHOLD=0.7;// 70% token 使用率触发压缩
staticreadonlyCOMPRESSION_PRESERVE_THRESHOLD=0.3;// 保留 30% 最新历史
staticreadonlyMAX_TURNS=100;// 最大会话轮次
asynctryCompressChat(prompt_id?:string):Promise<boolean>{
const history =this.getChat().getHistory(true);
const originalTokenCount =countTokens(history,this.model);
const limit =tokenLimit(this.model);
// 检查是否需要压缩
if(originalTokenCount >this.COMPRESSION_TOKEN_THRESHOLD* limit){
// 计算保留的历史记录数量
const preserveIndex =this.findIndexAfterFraction(
history,
this.COMPRESSION_PRESERVE_THRESHOLD
);
// 生成摘要并更新历史
const summary =awaitthis.sendMessage(getCompressionPrompt(),...);
this.getChat().updateHistory(newHistory);
returntrue;
}
returnfalse;
}
与Claude code
类似,也是提供把需要压缩的内容提炼为几个部分,进而减少token的使用量,避免超出上下文限制:
完整的prompt如下:
You are the component that summarizes internal chat history into a given structure.
When the conversation history grows too large, you will be invoked to distill the entire history into a concise, structured XML snapshot.This snapshot is CRITICAL,as it will become the agent's *only* memory of the past. The agent will resume its work based solely on this snapshot. All crucial details, plans, errors, and user directives MUST be preserved.
First, you will think through the entire history in a private <scratchpad>. Review the user's overall goal, the agent's actions, tool outputs, file modifications, and any unresolved questions. Identify every piece of information that is essential for future actions.
After your reasoning is complete, generate the final <state_snapshot> XML object. Be incredibly dense with information. Omit any irrelevant conversational filler.
The structure MUST be as follows:
<state_snapshot>
<overall_goal>
<!-- A single, concise sentence describing the user's high-level objective.-->
<!--Example:"Refactor the authentication service to use a new JWT library."-->
</overall_goal>
<key_knowledge>
<!--Crucial facts, conventions,and constraints the agent must remember based on the conversation history and interaction with the user.Use bullet points.-->
<!--Example:
-BuildCommand: \`npm run build\`
-Testing:Tests are run with \`npm test\`.Test files must endin \`.test.ts\`.
- API Endpoint:The primary API endpoint is \`https://api.example.com/v2\`.
-->
</key_knowledge>
<file_system_state>
<!--List files that have been created, read, modified,or deleted.Note their status and critical learnings.-->
<!--Example:
- CWD: \`/home/user/project/src\`
- READ: \`package.json\` -Confirmed'axios'is a dependency.
- MODIFIED: \`services/auth.ts\` -Replaced'jsonwebtoken'with'jose'.
- CREATED: \`tests/new-feature.test.ts\` -Initial test structure for the new feature.
-->
</file_system_state>
<recent_actions>
<!-- A summary of the last few significant agent actions and their outcomes.Focus on facts.-->
<!--Example:
-Ran \`grep 'old_function'\` which returned 3 results in2 files.
-Ran \`npm run test\`, which failed due to a snapshot mismatch in \`UserProfile.test.ts\`.
-Ran \`ls -F static/\` and discovered image assets are stored as \`.webp\`.
-->
</recent_actions>
<current_plan>
<!--The agent's step-by-step plan. Mark completed steps. -->
<!-- Example:
1. [DONE] Identify all files using the deprecated 'UserAPI'.
2. [IN PROGRESS] Refactor \`src/components/UserProfile.tsx\` to use the new 'ProfileAPI'.
3. [TODO] Refactor the remaining files.
4. [TODO] Update tests to reflect the API change.
-->
</current_plan>
</state_snapshot>
gemini-cli
的设计思路不乏以下亮点:
与Manus
类似,gemini-cli
使用文件系统持久化长期记忆,因为文件系统就是天然的数据库,这种设计既保证了系统的可靠性和性能,又提供了良好的用户体验和扩展性。
不过,略显遗憾的是目前gemini-cli
使用的仍然是单一主控Agent来控制所有交互,响应速度上会比较差;而Claude code
则是多Agent架构,同时异步设计实现了高效的响应速度,并且还允许用户根据不同任务定义不同的子Agent,在性能和效率上都是断档的存在。期待后续gemini-cli
和其他开源的Agent也能够实现类似的架构。
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业
2025-08-11
刚刚,智谱开源了他们的最强多模态模型,GLM-4.5V。
2025-08-11
谷歌开源 LangExtract,用 LLM 精准提取万物信息
2025-08-11
谷歌开源结构化信息提取神器!4K+ Star,精准定位+交互式可视化!
2025-08-11
如何编写一个MCP服务并在大模型中调用?试试这个go语言框架
2025-08-11
3.6K Star 开箱即用!开源Agentic浏览器,Perplexity Comet最强平替!
2025-08-11
一文了解专为处理复杂结构文档的知识库:腾讯开源的WeKnora
2025-08-11
AI快讯:AI安全漏洞揭秘:副业者如何利用漏洞检测赚钱?
2025-08-11
Coze、Dify、n8n:三国争霸哪家强?
2025-07-23
2025-06-17
2025-06-17
2025-07-23
2025-08-05
2025-07-14
2025-07-12
2025-07-27
2025-07-29
2025-07-29