@saber2pr/ai-agent 0.0.50 → 0.0.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,9 +6,6 @@ interface TokenUsage {
6
6
  }
7
7
  declare const AgentState: import("@langchain/langgraph").AnnotationRoot<{
8
8
  messages: import("@langchain/langgraph").BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
9
- auditedFiles: import("@langchain/langgraph").BinaryOperatorAggregate<string[], string[]>;
10
- targetCount: import("@langchain/langgraph").BinaryOperatorAggregate<number, number>;
11
- mode: import("@langchain/langgraph").BinaryOperatorAggregate<"chat" | "auto", "chat" | "auto">;
12
9
  tokenUsage: import("@langchain/langgraph").BinaryOperatorAggregate<TokenUsage, TokenUsage>;
13
10
  totalDuration: import("@langchain/langgraph").BinaryOperatorAggregate<number, number>;
14
11
  }>;
@@ -24,7 +21,6 @@ export default class McpGraphAgent<T extends AgentGraphModel = any> {
24
21
  private alwaysSystem;
25
22
  private recursionLimit;
26
23
  private apiConfig;
27
- private maxTargetCount;
28
24
  private maxTokens;
29
25
  private mcpClients;
30
26
  private streamEnabled;
@@ -66,36 +62,21 @@ export default class McpGraphAgent<T extends AgentGraphModel = any> {
66
62
  totalDuration: number;
67
63
  }>;
68
64
  private getRecentToolCalls;
69
- trackProgress(state: typeof AgentState.State): Promise<{
70
- auditedFiles: string[];
71
- }>;
72
65
  private printFinalSummary;
73
66
  createGraph(): Promise<import("@langchain/langgraph").CompiledStateGraph<import("@langchain/langgraph").StateType<{
74
67
  messages: import("@langchain/langgraph").BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
75
- auditedFiles: import("@langchain/langgraph").BinaryOperatorAggregate<string[], string[]>;
76
- targetCount: import("@langchain/langgraph").BinaryOperatorAggregate<number, number>;
77
- mode: import("@langchain/langgraph").BinaryOperatorAggregate<"chat" | "auto", "chat" | "auto">;
78
68
  tokenUsage: import("@langchain/langgraph").BinaryOperatorAggregate<TokenUsage, TokenUsage>;
79
69
  totalDuration: import("@langchain/langgraph").BinaryOperatorAggregate<number, number>;
80
70
  }>, import("@langchain/langgraph").UpdateType<{
81
71
  messages: import("@langchain/langgraph").BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
82
- auditedFiles: import("@langchain/langgraph").BinaryOperatorAggregate<string[], string[]>;
83
- targetCount: import("@langchain/langgraph").BinaryOperatorAggregate<number, number>;
84
- mode: import("@langchain/langgraph").BinaryOperatorAggregate<"chat" | "auto", "chat" | "auto">;
85
72
  tokenUsage: import("@langchain/langgraph").BinaryOperatorAggregate<TokenUsage, TokenUsage>;
86
73
  totalDuration: import("@langchain/langgraph").BinaryOperatorAggregate<number, number>;
87
- }>, "tools" | "__start__" | "agent" | "progress", {
74
+ }>, "tools" | "__start__" | "agent", {
88
75
  messages: import("@langchain/langgraph").BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
89
- auditedFiles: import("@langchain/langgraph").BinaryOperatorAggregate<string[], string[]>;
90
- targetCount: import("@langchain/langgraph").BinaryOperatorAggregate<number, number>;
91
- mode: import("@langchain/langgraph").BinaryOperatorAggregate<"chat" | "auto", "chat" | "auto">;
92
76
  tokenUsage: import("@langchain/langgraph").BinaryOperatorAggregate<TokenUsage, TokenUsage>;
93
77
  totalDuration: import("@langchain/langgraph").BinaryOperatorAggregate<number, number>;
94
78
  }, {
95
79
  messages: import("@langchain/langgraph").BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
96
- auditedFiles: import("@langchain/langgraph").BinaryOperatorAggregate<string[], string[]>;
97
- targetCount: import("@langchain/langgraph").BinaryOperatorAggregate<number, number>;
98
- mode: import("@langchain/langgraph").BinaryOperatorAggregate<"chat" | "auto", "chat" | "auto">;
99
80
  tokenUsage: import("@langchain/langgraph").BinaryOperatorAggregate<TokenUsage, TokenUsage>;
100
81
  totalDuration: import("@langchain/langgraph").BinaryOperatorAggregate<number, number>;
101
82
  }, import("@langchain/langgraph").StateDefinition>>;
@@ -29,18 +29,6 @@ const AgentState = langgraph_1.Annotation.Root({
29
29
  reducer: (x, y) => x.concat(y),
30
30
  default: () => [],
31
31
  }),
32
- auditedFiles: (0, langgraph_1.Annotation)({
33
- reducer: (x, y) => Array.from(new Set([...x, ...y])),
34
- default: () => [],
35
- }),
36
- targetCount: (0, langgraph_1.Annotation)({
37
- reducer: (x, y) => y !== null && y !== void 0 ? y : x,
38
- default: () => 4,
39
- }),
40
- mode: (0, langgraph_1.Annotation)({
41
- reducer: (x, y) => y !== null && y !== void 0 ? y : x,
42
- default: () => 'chat',
43
- }),
44
32
  // ✅ Token 累加器
45
33
  tokenUsage: (0, langgraph_1.Annotation)({
46
34
  reducer: (x, y) => ({
@@ -67,8 +55,7 @@ class McpGraphAgent {
67
55
  this.targetDir = options.targetDir || process.cwd();
68
56
  this.recursionLimit = options.recursionLimit || 80;
69
57
  this.apiConfig = options.apiConfig;
70
- this.maxTargetCount = options.maxTargetCount || 4;
71
- this.maxTokens = options.maxTokens || 8000;
58
+ this.maxTokens = options.maxTokens || 100000;
72
59
  this.streamEnabled = options.stream || false;
73
60
  process.setMaxListeners(100);
74
61
  // ✅ 修复 AbortSignal 监听器数量警告
@@ -283,8 +270,6 @@ class McpGraphAgent {
283
270
  const app = await this.createGraph();
284
271
  const graphStream = await app.stream({
285
272
  messages: [new messages_1.HumanMessage(query)],
286
- mode: 'auto',
287
- targetCount: this.maxTargetCount,
288
273
  }, {
289
274
  configurable: { thread_id: 'auto_worker' },
290
275
  recursionLimit: this.recursionLimit,
@@ -312,8 +297,6 @@ class McpGraphAgent {
312
297
  const app = await this.createGraph();
313
298
  const graphStream = await app.stream({
314
299
  messages: [new messages_1.HumanMessage(query)],
315
- mode: 'auto',
316
- targetCount: this.maxTargetCount,
317
300
  }, {
318
301
  configurable: { thread_id: 'stream_worker' },
319
302
  recursionLimit: this.recursionLimit,
@@ -346,7 +329,7 @@ class McpGraphAgent {
346
329
  rl.close();
347
330
  return;
348
331
  }
349
- const graphStream = await app.stream({ messages: [new messages_1.HumanMessage(input)], mode: 'chat' }, {
332
+ const graphStream = await app.stream({ messages: [new messages_1.HumanMessage(input)] }, {
350
333
  configurable: { thread_id: 'session' },
351
334
  recursionLimit: this.recursionLimit,
352
335
  debug: this.verbose,
@@ -416,7 +399,6 @@ class McpGraphAgent {
416
399
  }
417
400
  }
418
401
  async callModel(state) {
419
- const auditedListStr = state.auditedFiles.length > 0 ? state.auditedFiles.map(f => `\n - ${f}`).join('') : '暂无';
420
402
  const recentToolCalls = this.getRecentToolCalls(state.messages);
421
403
  const recentToolCallsStr = recentToolCalls.length > 0
422
404
  ? `\n\n⚠️ 最近调用的工具(避免重复调用相同工具和参数):\n${recentToolCalls
@@ -425,9 +407,14 @@ class McpGraphAgent {
425
407
  : '';
426
408
  // 1. 构建当前的系统提示词模板
427
409
  const systemPromptTemplate = `你是一个代码专家。工作目录:${this.targetDir}。
428
- 当前模式:{mode}
429
- 进度:{doneCount}/{targetCount}
430
- 已审计文件:{auditedList}
410
+
411
+ # 🧠 思考要求 (Mandatory Thinking Process)
412
+ 在进行任何输出或调用工具之前,你**必须**先进行深度的逻辑思考。请将你的思考过程包裹在 <think> 标签内。
413
+ 你的思考应包含:
414
+ 1. **当前状态分析**:目前任务进展到哪一步了?
415
+ 2. **逻辑推导**:基于已知信息,下一步应该做什么?为什么?
416
+ 3. **工具选择建议**:如果需要调用工具,预期通过该工具获得什么结果?
417
+ 4. **风险/边界评估**:有哪些潜在的代码缺陷或执行风险需要注意?
431
418
 
432
419
  # 🛠️ 工具调用规范
433
420
  1. Arguments 必须是纯粹的 JSON 对象,严禁将其作为字符串放入引号中。
@@ -458,10 +445,6 @@ class McpGraphAgent {
458
445
  try {
459
446
  const promptParams = {
460
447
  messages: inputMessages,
461
- mode: state.mode,
462
- targetCount: state.targetCount,
463
- doneCount: state.auditedFiles.length,
464
- auditedList: auditedListStr,
465
448
  recentToolCalls: recentToolCallsStr,
466
449
  extraPrompt: this.options.extraSystemPrompt || '',
467
450
  };
@@ -611,21 +594,6 @@ class McpGraphAgent {
611
594
  }
612
595
  return toolCalls;
613
596
  }
614
- async trackProgress(state) {
615
- var _a;
616
- const lastAiMsg = state.messages[state.messages.length - 1];
617
- const currentAudited = new Set(state.auditedFiles);
618
- if ((_a = lastAiMsg === null || lastAiMsg === void 0 ? void 0 : lastAiMsg.tool_calls) === null || _a === void 0 ? void 0 : _a.length) {
619
- for (const tc of lastAiMsg.tool_calls) {
620
- // 兼容所有可能的路径参数字段
621
- const file = tc.args.path || tc.args.filePath || tc.args.file || tc.args.file_path;
622
- if (file && typeof file === 'string') {
623
- currentAudited.add(file);
624
- }
625
- }
626
- }
627
- return { auditedFiles: Array.from(currentAudited) };
628
- }
629
597
  printFinalSummary(state) {
630
598
  var _a;
631
599
  const totalTokens = ((_a = state.tokenUsage) === null || _a === void 0 ? void 0 : _a.total) || 0;
@@ -635,7 +603,6 @@ class McpGraphAgent {
635
603
  console.log(`🏁 \x1b[32;1m[审计任务全量结算]\x1b[0m`);
636
604
  console.log(` - 累计消耗总额: \x1b[33m${totalTokens}\x1b[0m Tokens`);
637
605
  console.log(` - 累计执行耗时: \x1b[36m${(totalMs / 1000).toFixed(2)}\x1b[0m s`);
638
- console.log(` - 审计文件总数: ${state.auditedFiles.length} 个`);
639
606
  console.log('═'.repeat(50) + '\n');
640
607
  }
641
608
  }
@@ -643,7 +610,6 @@ class McpGraphAgent {
643
610
  const workflow = new langgraph_1.StateGraph(AgentState)
644
611
  .addNode('agent', state => this.callModel(state))
645
612
  .addNode('tools', this.toolNode)
646
- .addNode('progress', state => this.trackProgress(state))
647
613
  .addEdge(langgraph_1.START, 'agent')
648
614
  .addConditionalEdges('agent', state => {
649
615
  const { messages } = state;
@@ -653,6 +619,9 @@ class McpGraphAgent {
653
619
  // 如果已消耗 Token 超过了 options 中设置的 maxTokens (假设是总限额)
654
620
  if (this.options.maxTokens && state.tokenUsage.total >= this.options.maxTokens) {
655
621
  console.warn('⚠️ [警告] 已达到最大 Token 限制,强制结束任务。');
622
+ state.messages.push(new messages_1.AIMessage({
623
+ content: `⚠️ 抱歉,当前任务消耗的 Token 已达上限 ${this.options.maxTokens}。为了防止无限循环,我已停止执行。你可以尝试分步骤指令,继续发送指令,直到任务完成。`
624
+ }));
656
625
  this.printFinalSummary(state);
657
626
  return langgraph_1.END;
658
627
  }
@@ -660,22 +629,23 @@ class McpGraphAgent {
660
629
  if (lastMsg.tool_calls && lastMsg.tool_calls.length > 0) {
661
630
  return 'tools';
662
631
  }
663
- // 2. 判定结束的条件:
664
- // - 模式是 auto 且审计完成
665
- // - 或者 AI 明确输出了结束语
666
- // - 或者 AI 输出了普通内容且没有工具调用(针对问答模式)
667
- const isAutoFinished = state.mode === 'auto' && state.auditedFiles.length > state.targetCount;
668
632
  const isFinalAnswer = content.includes('Final Answer');
669
- // 修复核心:如果 AI 只是在聊天(没有工具调用),直接结束,不要跳回 agent
670
- if (isAutoFinished || isFinalAnswer || state.mode === 'chat') {
633
+ if (isFinalAnswer) {
671
634
  this.printFinalSummary(state);
672
635
  return langgraph_1.END;
673
636
  }
674
- // 兜底:如果是在 auto 模式且还没干完活,才跳回 agent(通常不会走到这里)
637
+ if (messages.length > 50) {
638
+ state.messages.push(new messages_1.AIMessage({
639
+ content: `💡 **嘿,我们已经聊了很多了!**
640
+
641
+ 为了保证服务质量,我通常会在 50 步操作后停下来和您确认一下。这样可以避免我产生“幻觉”或者做一些无用功。
642
+
643
+ **任务还没完成吗?** 没关系,只要您回复“继续”,我马上就回来接着干!或者您有什么新的想法要告诉我?`
644
+ }));
645
+ return langgraph_1.END;
646
+ }
675
647
  return langgraph_1.END;
676
- })
677
- .addEdge('tools', 'progress')
678
- .addEdge('progress', 'agent');
648
+ }).addEdge('tools', 'agent');
679
649
  return workflow.compile({ checkpointer: this.checkpointer });
680
650
  }
681
651
  }
@@ -7,7 +7,7 @@ export interface ApiConfig {
7
7
  model: string;
8
8
  }
9
9
  export interface ToolInfo {
10
- type: "function";
10
+ type: 'function';
11
11
  function: {
12
12
  name: string;
13
13
  description?: string;
@@ -38,7 +38,6 @@ export interface GraphAgentOptions<T extends AgentGraphModel = any> extends Agen
38
38
  apiModel?: T;
39
39
  alwaysSystem?: boolean;
40
40
  recursionLimit?: number;
41
- maxTargetCount?: number;
42
41
  /** 是否启用流式输出,默认 false */
43
42
  stream?: boolean;
44
43
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saber2pr/ai-agent",
3
- "version": "0.0.50",
3
+ "version": "0.0.52",
4
4
  "description": "AI Assistant CLI.",
5
5
  "author": "saber2pr",
6
6
  "license": "ISC",