@bolloon/bolloon-agent 0.3.29 → 0.3.30
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.
- package/dist/llm/pi-ai.js +28 -9
- package/dist/security/tool-gate.js +2 -18
- package/package.json +1 -1
package/dist/llm/pi-ai.js
CHANGED
|
@@ -282,15 +282,34 @@ export class PiAIModel {
|
|
|
282
282
|
const _t0 = Date.now();
|
|
283
283
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
284
284
|
const _tFetch = Date.now();
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
285
|
+
let response;
|
|
286
|
+
try {
|
|
287
|
+
response = await fetch(`${this.getBaseUrl()}/chat/completions`, {
|
|
288
|
+
method: 'POST',
|
|
289
|
+
headers: {
|
|
290
|
+
'Content-Type': 'application/json',
|
|
291
|
+
'Authorization': `Bearer ${apiKey}`
|
|
292
|
+
},
|
|
293
|
+
body: JSON.stringify(requestBody),
|
|
294
|
+
signal: this.combinedSignal(signal),
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
catch (err) {
|
|
298
|
+
// 2026-08-04: 网络层瞬时错误 (undici "terminated" / ECONNRESET / socket hang up / fetch failed 等)
|
|
299
|
+
// 退避重试最多 2 次 — 之前直接抛给 chat() 变成 "[AI 服务调用失败] terminated" 打断 agent 流程.
|
|
300
|
+
// abort (用户主动 / 120s 超时) 不重试, 原样抛出.
|
|
301
|
+
if (err?.name === 'AbortError' || signal?.aborted)
|
|
302
|
+
throw err;
|
|
303
|
+
const netMsg = String(err?.message || err?.cause?.message || '');
|
|
304
|
+
const isNetworkErr = /terminated|ECONNRESET|socket hang up|fetch failed|network|ETIMEDOUT|ECONNREFUSED|UND_ERR/i.test(netMsg);
|
|
305
|
+
if (attempt < 2 && isNetworkErr) {
|
|
306
|
+
const backoff = 1500 * (attempt + 1);
|
|
307
|
+
console.warn(`[pi-ai] 网络错误 attempt ${attempt + 1}/3: ${netMsg.slice(0, 120)}, 退避 ${backoff}ms 重试`);
|
|
308
|
+
await new Promise(resolve => setTimeout(resolve, backoff));
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
throw err;
|
|
312
|
+
}
|
|
294
313
|
const _tResp = Date.now();
|
|
295
314
|
if (!response.ok) {
|
|
296
315
|
const errBody = await response.text().catch(() => '(no body)');
|
|
@@ -202,23 +202,7 @@ export function checkOutput(output) {
|
|
|
202
202
|
};
|
|
203
203
|
}
|
|
204
204
|
// ============================================================
|
|
205
|
-
// Gate 7:
|
|
206
|
-
// ============================================================
|
|
207
|
-
const MAX_TOOL_CALLS_PER_TURN = 5;
|
|
208
|
-
export function checkChain(ctx) {
|
|
209
|
-
const count = ctx.toolCallCountInTurn ?? 0;
|
|
210
|
-
if (count >= MAX_TOOL_CALLS_PER_TURN) {
|
|
211
|
-
return {
|
|
212
|
-
gate: 'chain',
|
|
213
|
-
allowed: false,
|
|
214
|
-
reason: `单轮已调 ${count} 个 tool (上限 ${MAX_TOOL_CALLS_PER_TURN})`,
|
|
215
|
-
evidence: `当前轮 tool 调用次数: ${count}`,
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
return { gate: 'chain', allowed: true };
|
|
219
|
-
}
|
|
220
|
-
// ============================================================
|
|
221
|
-
// Gate 8: 黑名单 (复用 PreToolUse hook 已有 6 条规则, 重新实现于此)
|
|
205
|
+
// Gate 7: 黑名单 (复用 PreToolUse hook 已有 6 条规则, 重新实现于此)
|
|
222
206
|
// ============================================================
|
|
223
207
|
const DANGEROUS_CMD_PATTERNS = [
|
|
224
208
|
{ re: /\brm\s+(-[a-z]*f[a-z]*\s+)?-[a-z]*r[a-z]*\s+\//, reason: '禁止递归删除根目录' },
|
|
@@ -245,7 +229,7 @@ const TOOL_GATES = [
|
|
|
245
229
|
checkChannel,
|
|
246
230
|
checkRate,
|
|
247
231
|
checkInject,
|
|
248
|
-
checkChain
|
|
232
|
+
// 2026-08-04: 移除 checkChain — 单轮 5 工具上限会打断 agent 长流程 (MCP 多步测试被反复拦), 用户要求去掉
|
|
249
233
|
checkBlacklist,
|
|
250
234
|
// checkOutput 不在 tool.execute 前
|
|
251
235
|
];
|