@bolloon/bolloon-agent 0.1.15 → 0.1.17

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.
@@ -861,7 +861,10 @@ ${this.getToolDefinitions()}
861
861
  let lastQualityScore = 0;
862
862
  let refineAttempts = 0;
863
863
  let consecutiveErrors = 0;
864
+ let lastFailedTool = ''; // 跟踪最近一次失败的 tool name
865
+ let lastFailedToolCount = 0; // 最近失败工具的连续失败次数
864
866
  const MAX_CONSECUTIVE_ERRORS = 3;
867
+ const MAX_SAME_TOOL_FAILURES = 3; // 同一工具连续失败 3 次, 强制让 LLM 给出最终答案
865
868
  // 发送循环开始的事件
866
869
  if (onStream) {
867
870
  onStream({ type: 'status', content: '🔄 开始 ReAct 循环...', tool: 'system' });
@@ -987,16 +990,35 @@ ${toolDefs}
987
990
  }
988
991
  else {
989
992
  consecutiveErrors++;
990
- console.warn(`[PiAgent] 工具执行失败 (${consecutiveErrors}/${MAX_CONSECUTIVE_ERRORS}): ${result.error}`);
991
- // 连续错误达到上限,尝试换一种方式
993
+ // 跟踪同一工具连续失败次数
994
+ if (toolCall.name === lastFailedTool) {
995
+ lastFailedToolCount++;
996
+ }
997
+ else {
998
+ lastFailedTool = toolCall.name;
999
+ lastFailedToolCount = 1;
1000
+ }
1001
+ console.warn(`[PiAgent] 工具 ${toolCall.name} 执行失败 (${lastFailedToolCount}/${MAX_SAME_TOOL_FAILURES}): ${result.error}`);
1002
+ // 同一工具连续失败达到上限, 不再重试, 强制 LLM 给出最终答案
1003
+ if (lastFailedToolCount >= MAX_SAME_TOOL_FAILURES) {
1004
+ console.log(`[PiAgent] 工具 ${toolCall.name} 连续 ${MAX_SAME_TOOL_FAILURES} 次失败, 放弃并要求直接回答`);
1005
+ this.messageHistory.push({
1006
+ role: 'system',
1007
+ content: `[注意] 工具 ${toolCall.name} 在这个上下文中不可用 (连续 ${MAX_SAME_TOOL_FAILURES} 次失败: ${result.error}). 请不要再次调用它, 直接用你已知的信息回答用户, 并在回答开头标记 <final gen>.`
1008
+ });
1009
+ lastFailedTool = '';
1010
+ lastFailedToolCount = 0;
1011
+ consecutiveErrors = 0;
1012
+ continue; // 让 LLM 看到系统提示后再决定
1013
+ }
1014
+ // 连续错误达到上限(混合不同工具), 尝试换一种方式
992
1015
  if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
993
1016
  console.log(`[PiAgent] 连续 ${MAX_CONSECUTIVE_ERRORS} 次错误,尝试换一种方式处理`);
994
- // 添加错误上下文,让 LLM 换一种方式
995
1017
  this.messageHistory.push({
996
1018
  role: 'system',
997
- content: `[注意] 前面的工具调用连续失败。请尝试其他工具或换一种方式完成用户请求。`
1019
+ content: `[注意] 前面的工具调用连续失败。请尝试其他工具或换一种方式完成用户请求, 或用 <final gen> 给出最终回答.`
998
1020
  });
999
- consecutiveErrors = 0; // 重置以继续尝试
1021
+ consecutiveErrors = 0;
1000
1022
  }
1001
1023
  }
1002
1024
  }
@@ -1045,9 +1067,14 @@ ${toolDefs}
1045
1067
  }
1046
1068
  }
1047
1069
  if (!finalResponse) {
1048
- finalResponse = '任务处理超时,请尝试更具体的请求。';
1070
+ // 走到这里通常是 LLM 一直在调同一个不存在的工具, 没输出 <final gen>
1071
+ // 把已知的失败信息也带回去, 让用户知道发生了什么
1072
+ const reason = lastFailedTool
1073
+ ? `(工具 ${lastFailedTool} 连续 ${MAX_SAME_TOOL_FAILURES} 次失败, 已放弃)`
1074
+ : `(共 ${iteration - 1} 轮无最终输出)`;
1075
+ finalResponse = `抱歉,任务未能完成 ${reason}。请换个方式提问,或明确告诉 agent 不要调用工具。`;
1049
1076
  if (onStream) {
1050
- onStream({ type: 'error', content: '⚠️ 任务处理超时', tool: 'system' });
1077
+ onStream({ type: 'error', content: `⚠️ 任务未完成: ${reason}`, tool: 'system' });
1051
1078
  }
1052
1079
  }
1053
1080
  // 通知前端循环完成
@@ -1357,9 +1384,21 @@ ${this.extractOperationsFromRef(operationsRef)}
1357
1384
  try {
1358
1385
  const response = await llm.chat(`根据以下对话内容,为这个对话生成一个简短的名称(不超过20个字):\n\n${conversation}\n\n直接输出名称,不要其他解释。`, '命名建议');
1359
1386
  const name = response.reply.trim();
1360
- if (name && name.length <= 20 && name !== '智能体') {
1361
- return `Agent | ${name}`;
1387
+ // 拒绝错误回退串 (LLM 不可用时返回的占位文本)
1388
+ if (!name)
1389
+ return null;
1390
+ if (/^(抱歉|对不起|sorry|error|错误|失败|暂不可用|服务不可用)/i.test(name)) {
1391
+ console.log(`[suggestRename] 拒绝错误回退: "${name}"`);
1392
+ return null;
1362
1393
  }
1394
+ if (name.length > 20)
1395
+ return null;
1396
+ if (name === '智能体')
1397
+ return null;
1398
+ // 拒绝纯符号/标点
1399
+ if (!/[一-鿿\w]/.test(name))
1400
+ return null;
1401
+ return `Agent | ${name}`;
1363
1402
  }
1364
1403
  catch {
1365
1404
  // ignore
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "Bolloon Agent",
3
+ "short_name": "Bolloon",
4
+ "description": "AI Agent with Claude API integration",
5
+ "start_url": "/",
6
+ "display": "standalone",
7
+ "background_color": "#1a1a2e",
8
+ "theme_color": "#1a1a2e",
9
+ "icons": [
10
+ {
11
+ "src": "/icons/favicon-192x192.png",
12
+ "sizes": "192x192",
13
+ "type": "image/png"
14
+ },
15
+ {
16
+ "src": "/icons/favicon-512x512.png",
17
+ "sizes": "512x512",
18
+ "type": "image/png"
19
+ }
20
+ ]
21
+ }