feat: 升级至 v0.3.16 — 工单修复 51 项 + 审查修复 30 项(安全加固/适配器/工具系统/数据层/前端)
This commit is contained in:
@@ -95,20 +95,39 @@ export class ToolRegistry {
|
||||
}
|
||||
|
||||
const startTs = Date.now();
|
||||
const timeoutMs = tool.definition.timeoutMs;
|
||||
|
||||
// #12 修复: timeoutMs 为 undefined 时使用默认值,并校验有效性
|
||||
// 防止 setTimeout(fn, undefined) 被解释为 setTimeout(fn, 0) 立即触发超时
|
||||
// 类型定义中 timeoutMs 是必填 number,但 MCP/外部工具运行时可能缺失,需防御
|
||||
const DEFAULT_TIMEOUT_MS = 120_000;
|
||||
const rawTimeout = tool.definition.timeoutMs;
|
||||
const timeoutMs =
|
||||
typeof rawTimeout === 'number' && rawTimeout > 0
|
||||
? rawTimeout
|
||||
: DEFAULT_TIMEOUT_MS;
|
||||
|
||||
// #11 修复: 使用 AbortController 在超时后通知工具中止,防止 Promise 未取消导致资源泄漏
|
||||
// 原实现 Promise.race 超时后 tool.execute() 仍在后台运行,持续消耗资源
|
||||
// 现通过 signal 传给 context,工具可在耗时操作前检查 signal.aborted 自行中止
|
||||
const controller = new AbortController();
|
||||
const enhancedContext: ToolExecutionContext = {
|
||||
...context,
|
||||
signal: controller.signal,
|
||||
};
|
||||
|
||||
// M-15 修复: 使用 try/finally 清理 setTimeout,防止事件循环 timer 堆积
|
||||
// 工具正常完成时未触发的 timer 会持续占用事件循环 timeoutMs 毫秒
|
||||
let timer: ReturnType<typeof setTimeout> | undefined;
|
||||
try {
|
||||
// 带超时执行 — 使用 Promise.race 防止工具卡死阻塞 Agent Loop
|
||||
// #11: 超时触发 controller.abort(),支持 signal 的工具可据此中止后台操作
|
||||
const result = await Promise.race([
|
||||
tool.execute(toolCall.args, context),
|
||||
tool.execute(toolCall.args, enhancedContext),
|
||||
new Promise<never>((_, reject) => {
|
||||
timer = setTimeout(
|
||||
() => reject(new Error(`Tool execution timed out after ${timeoutMs}ms`)),
|
||||
timeoutMs,
|
||||
);
|
||||
timer = setTimeout(() => {
|
||||
controller.abort();
|
||||
reject(new Error(`Tool execution timed out after ${timeoutMs}ms`));
|
||||
}, timeoutMs);
|
||||
}),
|
||||
]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user