@saber2pr/ai-agent 0.0.20 → 0.0.21

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.
@@ -152,9 +152,21 @@ class McpGraphAgent {
152
152
  : (this.options.extraSystemPrompt || "");
153
153
  // 使用变量占位符 {extraPrompt} 避免内容中的 {} 引发模板解析错误
154
154
  const prompt = prompts_1.ChatPromptTemplate.fromMessages([
155
- ["system", `你是一个代码审计专家。工作目录:${this.targetDir}。
156
- 当前模式:{mode}。
157
- KPI进度:{doneCount}/{targetCount}。已审计文件:{auditedList}
155
+ ["system", `你是一个代码专家。工作目录:${this.targetDir}。
156
+
157
+ # 当前进度状态
158
+ - 审计模式: {mode}
159
+ - 目标任务数: {targetCount}
160
+ - 已完成数量: {doneCount}
161
+ - 已审计文件列表: {auditedList}
162
+
163
+ # 核心任务准则
164
+ 1. 目标导向:如果 {doneCount} >= {targetCount},说明任务已达标。请直接输出总结,不要再调用任何工具。
165
+ 2. 避免死循环:不要反复尝试审计同一个文件或调用同样的工具。如果你发现某个文件修复失败,请尝试审计其他文件。
166
+ 3. 严格格式:
167
+ - 必须先在 <think> 标签内进行推理。
168
+ - 工具调用必须严格按照 Action: 名称 和 Arguments: {{JSON}} 的格式。
169
+ - 【重要】Arguments 中的 JSON 字符串,所有的换行符必须转义为 \\n,严禁出现物理换行符。
158
170
 
159
171
  # 附加指令
160
172
  {extraPrompt}`],
@@ -180,20 +192,23 @@ KPI进度:{doneCount}/{targetCount}。已审计文件:{auditedList}
180
192
  throw error;
181
193
  }
182
194
  }
195
+ // agent-graph.ts 中的 trackProgress 节点
183
196
  async trackProgress(state) {
197
+ var _a;
198
+ // 获取最后一条 AI 消息(即发起工具调用的那条)
184
199
  const lastAiMsg = state.messages[state.messages.length - 1];
185
200
  const newFiles = [];
186
- if (lastAiMsg === null || lastAiMsg === void 0 ? void 0 : lastAiMsg.tool_calls) {
201
+ if ((_a = lastAiMsg === null || lastAiMsg === void 0 ? void 0 : lastAiMsg.tool_calls) === null || _a === void 0 ? void 0 : _a.length) {
187
202
  for (const tc of lastAiMsg.tool_calls) {
188
- // 追踪涉及写、修复、生成审计报告的文件
189
- const toolsToTrack = ["write_text_file", "apply_fix", "generate_review"];
190
- if (toolsToTrack.includes(tc.name)) {
191
- const file = tc.args.path || tc.args.filePath || tc.args.file;
192
- if (file && typeof file === 'string')
193
- newFiles.push(file);
203
+ // 这里的逻辑要宽容:只要 AI 尝试处理了这些文件,就计入进度
204
+ const file = tc.args.path || tc.args.filePath || tc.args.file;
205
+ if (file && typeof file === 'string') {
206
+ newFiles.push(file);
194
207
  }
195
208
  }
196
209
  }
210
+ // 如果这一轮没有任何新文件被处理,且 AI 也没给最终回复,
211
+ // 我们需要防止它在下一轮条件判断中陷入死循环
197
212
  return { auditedFiles: newFiles };
198
213
  }
199
214
  async createGraph() {
@@ -205,12 +220,22 @@ KPI进度:{doneCount}/{targetCount}。已审计文件:{auditedList}
205
220
  .addConditionalEdges("agent", (state) => {
206
221
  var _a;
207
222
  const lastMsg = state.messages[state.messages.length - 1];
223
+ // 1. 如果 AI 想要调用工具,去 tools 节点
208
224
  if ((_a = lastMsg.tool_calls) === null || _a === void 0 ? void 0 : _a.length)
209
225
  return "tools";
210
- // 自动模式下且未达标时继续
211
- if (state.mode === "auto" && state.auditedFiles.length < state.targetCount)
212
- return "agent";
226
+ // 2. 如果是自动模式且未达标
227
+ if (state.mode === "auto") {
228
+ const isDone = state.auditedFiles.length >= state.targetCount;
229
+ // 如果还没达标,继续让 agent 思考下一步
230
+ if (!isDone)
231
+ return "agent";
232
+ }
233
+ // 3. 其他情况(达标了,或者对话模式 AI 给出了回复)一律结束
213
234
  return langgraph_1.END;
235
+ }, {
236
+ tools: "tools",
237
+ agent: "agent",
238
+ [langgraph_1.END]: langgraph_1.END,
214
239
  })
215
240
  .addEdge("tools", "progress")
216
241
  .addEdge("progress", "agent");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saber2pr/ai-agent",
3
- "version": "0.0.20",
3
+ "version": "0.0.21",
4
4
  "description": "AI Assistant CLI.",
5
5
  "author": "saber2pr",
6
6
  "license": "ISC",