v0.1.2: 全项目代码审查修复 + 子代理编排器 + 上下文压缩 + 并行工具执行
后端修复: Ollama adapter 移除死代码/修复超时硬编码/iteration硬编码/pullModel无超时/流异常断开补发DONE; SSE解析器支持非字符串arguments; Sandbox fail-closed安全加固; IPC移除未使用变量 新增功能: TaskOrchestrator子任务编排器; DelegateTaskTool委派工具; Agent Loop并行工具执行; 上下文自动压缩; 记忆检索注入System Prompt 前端修复: useAgentStream text_delta thought累积bug; 工具调用状态正确流转; 修复重复stateChange事件; TraceStep.thought正确填充
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
* Tool Registry — 工具注册表
|
||||
*
|
||||
* 管理所有可用工具(内置 + MCP),提供查找、注册、注销功能。
|
||||
* 提供 per-tool 超时强制和结果大小限制,防止卡死和上下文溢出。
|
||||
*/
|
||||
|
||||
import type {
|
||||
@@ -11,6 +12,9 @@ import type {
|
||||
} from '../types';
|
||||
import type { IMetonaTool, ToolRegistryEntry, ToolExecutionContext } from '../types/metona-tool';
|
||||
|
||||
/** 工具返回值最大字符数(约 50KB),超过则截断 */
|
||||
const MAX_RESULT_CHARS = 50_000;
|
||||
|
||||
export class ToolRegistry {
|
||||
private tools = new Map<string, ToolRegistryEntry>();
|
||||
private disabledTools = new Set<string>();
|
||||
@@ -75,7 +79,7 @@ export class ToolRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
/** 执行工具 */
|
||||
/** 执行工具(带超时强制和结果大小限制) */
|
||||
async execute(
|
||||
toolCall: MetonaToolCall,
|
||||
context: ToolExecutionContext,
|
||||
@@ -94,12 +98,27 @@ export class ToolRegistry {
|
||||
}
|
||||
|
||||
const startTs = Date.now();
|
||||
const timeoutMs = tool.definition.timeoutMs;
|
||||
|
||||
try {
|
||||
const result = await tool.execute(toolCall.args, context);
|
||||
// 带超时执行 — 使用 Promise.race 防止工具卡死阻塞 Agent Loop
|
||||
const result = await Promise.race([
|
||||
tool.execute(toolCall.args, context),
|
||||
new Promise<never>((_, reject) => {
|
||||
setTimeout(
|
||||
() => reject(new Error(`Tool execution timed out after ${timeoutMs}ms`)),
|
||||
timeoutMs,
|
||||
);
|
||||
}),
|
||||
]);
|
||||
|
||||
// 结果大小限制 — 防止过大返回值耗尽 LLM 上下文窗口
|
||||
const safeResult = this.truncateResult(result);
|
||||
|
||||
return {
|
||||
toolCallId: toolCall.id,
|
||||
toolName: toolCall.name,
|
||||
result,
|
||||
result: safeResult,
|
||||
success: true,
|
||||
durationMs: Date.now() - startTs,
|
||||
timestamp: Date.now(),
|
||||
@@ -117,6 +136,19 @@ export class ToolRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
/** 截断过大的工具返回值,防止 LLM 上下文溢出 */
|
||||
private truncateResult(result: unknown): unknown {
|
||||
const str = typeof result === 'string' ? result : JSON.stringify(result);
|
||||
if (str.length <= MAX_RESULT_CHARS) return result;
|
||||
|
||||
return {
|
||||
_truncated: true,
|
||||
_original_size: str.length,
|
||||
_preview: str.slice(0, MAX_RESULT_CHARS),
|
||||
_message: `Result truncated: original ${str.length} chars exceeds limit ${MAX_RESULT_CHARS}`,
|
||||
};
|
||||
}
|
||||
|
||||
/** 获取工具数量 */
|
||||
get size(): number {
|
||||
return Array.from(this.tools.values()).filter((e) => e.enabled && !this.disabledTools.has(e.tool.definition.name)).length;
|
||||
|
||||
Reference in New Issue
Block a user