reagentbuilder
Version:
An enterprise-grade AI agent framework based on LangChain and LangGraph, featuring dynamic tools, interceptors, breakpoints, and performance monitoring.
170 lines • 7.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BreakpointManager = void 0;
const index_js_1 = require("../core/index.js");
// ============ 断点管理类 ============
class BreakpointManager {
constructor(config, maxConcurrentBreakpoints = 5) {
this.executionQueue = new Map();
this.concurrentBreakpoints = new Set();
this.config = config;
this.maxConcurrentBreakpoints = maxConcurrentBreakpoints;
// 预计算配置状态
this.isEnabled = config.enabled;
this.hasCoreBeforeModel = !!(config.core?.beforeModelInvoke);
this.hasCoreAfterComplete = !!(config.core?.afterAgentComplete);
this.hasModelBefore = !!(config.model?.beforeCall);
this.hasModelAfter = !!(config.model?.afterCall);
this.hasGlobalBefore = !!(config.global?.beforeToolCall);
this.hasGlobalAfter = !!(config.global?.afterToolCall);
this.hasToolSpecific = !!(config.toolSpecific && config.toolSpecific.size > 0);
}
async enqueueBreakpoint(key, breakpointFn) {
if (this.concurrentBreakpoints.size >= this.maxConcurrentBreakpoints) {
index_js_1.logger.debug(`断点并发限制达到上限 (${this.maxConcurrentBreakpoints}),跳过断点: ${key}`);
return;
}
if (this.executionQueue.has(key)) {
index_js_1.logger.debug(`断点已在执行队列中,跳过重复断点: ${key}`);
return;
}
const breakpointPromise = this.executeBreakpoint(key, breakpointFn);
this.executionQueue.set(key, breakpointPromise.then(() => undefined));
try {
return await breakpointPromise;
}
finally {
this.executionQueue.delete(key);
}
}
async executeBreakpoint(key, breakpointFn) {
this.concurrentBreakpoints.add(key);
try {
const timeout = 2000;
let timeoutId;
const result = await Promise.race([
breakpointFn(),
new Promise((_, reject) => {
timeoutId = setTimeout(() => reject(new Error(`断点执行超时: ${key}`)), timeout);
})
]);
// 清理超时定时器
clearTimeout(timeoutId);
return result;
}
catch (error) {
index_js_1.logger.warn(`断点执行失败 [${key}]: ${error instanceof Error ? error.message : String(error)}`);
return;
}
finally {
this.concurrentBreakpoints.delete(key);
}
}
async breakBeforeModelInvoke(messages, state) {
if (!this.isEnabled || !this.hasCoreBeforeModel)
return;
const key = index_js_1.perfUtils.generateId('core-before-model');
await this.enqueueBreakpoint(key, async () => {
index_js_1.logger.debug('核心开始断点 - 观察大模型输入');
await this.config.core.beforeModelInvoke(messages, state);
});
}
async breakAfterAgentComplete(finalState) {
if (!this.isEnabled || !this.hasCoreAfterComplete)
return;
const key = index_js_1.perfUtils.generateId('core-after-complete');
await this.enqueueBreakpoint(key, async () => {
index_js_1.logger.debug('核心结束断点 - 观察最终状态');
await this.config.core.afterAgentComplete(finalState);
});
}
async breakBeforeModelCall(state) {
if (!this.isEnabled || !this.hasModelBefore)
return;
const key = index_js_1.perfUtils.generateId('model-before-call');
await this.enqueueBreakpoint(key, async () => {
index_js_1.logger.debug('模型调用前断点');
await this.config.model.beforeCall(state);
});
}
async breakAfterModelCall(response, state) {
if (!this.isEnabled || !this.hasModelAfter)
return;
const key = index_js_1.perfUtils.generateId('model-after-call');
await this.enqueueBreakpoint(key, async () => {
index_js_1.logger.debug('模型调用后断点');
await this.config.model.afterCall(response, state);
});
}
async breakBeforeToolCall(toolCall, state) {
if (!this.isEnabled || !this.hasGlobalBefore)
return;
const key = `global-before-tool-${toolCall.name}-${toolCall.id || index_js_1.perfUtils.generateId('tool')}`;
await this.enqueueBreakpoint(key, async () => {
index_js_1.logger.debug(`全局工具调用前断点: ${toolCall.name}`);
await this.config.global.beforeToolCall(toolCall, state);
});
}
async breakAfterToolCall(result, toolCall, state) {
if (!this.isEnabled || !this.hasGlobalAfter)
return;
const key = `global-after-tool-${toolCall.name}-${toolCall.id || index_js_1.perfUtils.generateId('tool')}`;
await this.enqueueBreakpoint(key, async () => {
index_js_1.logger.debug(`全局工具调用后断点: ${toolCall.name}`);
await this.config.global.afterToolCall(result, toolCall, state);
});
}
async breakBeforeSpecificToolCall(toolCall, state) {
if (!this.isEnabled || !this.hasToolSpecific)
return;
const toolName = String(toolCall.name || 'unknown');
const toolBreakpoint = this.config.toolSpecific?.get(toolName);
if (!toolBreakpoint?.beforeToolCall)
return;
const key = `specific-before-tool-${toolName}-${toolCall.id || index_js_1.perfUtils.generateId('tool')}`;
await this.enqueueBreakpoint(key, async () => {
index_js_1.logger.debug(`特定工具调用前断点: ${toolName}`);
await toolBreakpoint.beforeToolCall(toolCall, state);
});
}
async breakAfterSpecificToolCall(result, toolCall, state) {
if (!this.isEnabled || !this.hasToolSpecific)
return;
const toolName = String(toolCall.name || 'unknown');
const toolBreakpoint = this.config.toolSpecific?.get(toolName);
if (!toolBreakpoint?.afterToolCall)
return;
const key = `specific-after-tool-${toolName}-${toolCall.id || index_js_1.perfUtils.generateId('tool')}`;
await this.enqueueBreakpoint(key, async () => {
index_js_1.logger.debug(`特定工具调用后断点: ${toolName}`);
await toolBreakpoint.afterToolCall(result, toolCall, state);
});
}
getActiveBreakpointCount() {
return this.concurrentBreakpoints.size;
}
async cleanup() {
const activeBreakpointCount = this.concurrentBreakpoints.size;
if (activeBreakpointCount > 0) {
index_js_1.logger.warn(`清理断点管理器时仍有 ${activeBreakpointCount} 个活跃断点`);
}
const maxWaitTime = 2000;
let waitTime = 0;
while (this.concurrentBreakpoints.size > 0 && waitTime < maxWaitTime) {
await new Promise(resolve => setTimeout(resolve, 100));
waitTime += 100;
}
if (this.concurrentBreakpoints.size > 0) {
index_js_1.logger.warn(`断点管理器清理超时,强制清理 ${this.concurrentBreakpoints.size} 个断点`);
}
this.executionQueue.clear();
this.concurrentBreakpoints.clear();
// 清理配置对象中的Map引用
if (this.config.toolSpecific) {
this.config.toolSpecific.clear();
}
index_js_1.logger.debug('断点管理器资源清理完成');
}
}
exports.BreakpointManager = BreakpointManager;
//# sourceMappingURL=breakpoint-manager.js.map