autosnippet
Version:
Extract code patterns into a knowledge base for AI coding assistants
121 lines (120 loc) • 4.05 kB
JavaScript
/**
* LoopContext — reactLoop 单次执行的完整状态
*
* 封装原 reactLoop 内散落的 10+ 局部变量:
* - 注入依赖 (messages, tracker, trace, memoryCoordinator, sharedState)
* - 循环状态 (iteration, lastReply, toolCalls, tokenUsage)
* - 错误恢复 (consecutiveAiErrors, consecutiveEmptyResponses)
* - 配置 (source, budget, capabilities, baseSystemPrompt, toolSchemas, prompt)
*
* 使 reactLoop 的提取方法只需接收一个 ctx 参数。
*
* @module core/LoopContext
*/
export class LoopContext {
// ─── 注入依赖 ───
/** 统一消息适配器 */
messages;
/** ExplorationTracker 实例 */
tracker;
/** ActiveContext 实例 */
trace;
/** MemoryCoordinator 实例 */
memoryCoordinator;
/** 共享状态 */
sharedState;
// ─── 循环状态 ───
/** 当前迭代次数 */
iteration = 0;
/** 最终回复文本 */
lastReply = '';
/** 本轮工具调用记录 */
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- tool call entries have varying shapes (ToolCallEntry, ToolCallRecord, etc.) across callers; no common structural type satisfies all consumers
toolCalls = [];
/** } 本轮 token 用量 */
tokenUsage = { input: 0, output: 0 };
/** 循环开始时间戳 */
loopStartTime = 0;
// ─── 错误恢复 ───
/** 连续 AI 错误计数 (2-strike 策略) */
consecutiveAiErrors = 0;
/** 连续空响应计数 */
consecutiveEmptyResponses = 0;
// ─── 配置 (只读) ───
/** 来源 'user' | 'system' */
source;
/** 预算配置 */
budget;
capabilities;
/** 基础系统提示词 */
baseSystemPrompt;
/** 工具 schemas */
toolSchemas;
/** 原始用户提示 */
prompt;
/** 工具调用钩子 */
onToolCall;
/** 额外上下文 */
context;
/** 原始 ContextWindow 引用 */
contextWindow;
/** 首轮 toolChoice 覆盖 ('required'/'auto'/'none') */
toolChoiceOverride;
/** 外部中止信号 — hard timeout 时取消进行中的 LLM 调用 */
abortSignal;
constructor(config) {
this.messages = config.messages;
this.tracker = (config.tracker || null);
this.trace = (config.trace || null);
this.memoryCoordinator = (config.memoryCoordinator || null);
this.sharedState = (config.sharedState || null);
this.source = config.source || 'user';
this.budget = config.budget;
this.capabilities = config.capabilities;
this.baseSystemPrompt = config.baseSystemPrompt;
this.toolSchemas = config.toolSchemas;
this.prompt = config.prompt;
this.onToolCall = (config.onToolCall || null);
this.context = config.context || {};
this.contextWindow = config.contextWindow || null;
this.toolChoiceOverride = config.toolChoiceOverride || null;
this.abortSignal = (config.abortSignal || null);
this.loopStartTime = Date.now();
}
// ─── 计算属性 ───
/** 是否为 system 场景 */
get isSystem() {
return this.source === 'system';
}
/** 最大迭代数 */
get maxIterations() {
return this.budget.maxIterations || 20;
}
// ─── Token 累计辅助 ───
/**
* 累加 token 用量到循环级统计
* @param usage { inputTokens, outputTokens }
*/
addTokenUsage(usage) {
if (!usage) {
return;
}
const inTok = usage.inputTokens || 0;
const outTok = usage.outputTokens || 0;
this.tokenUsage.input += inTok;
this.tokenUsage.output += outTok;
}
// ─── 结果构建 ───
/**
* 构建循环返回值
* @returns }
*/
buildResult() {
return {
reply: this.lastReply,
toolCalls: [...this.toolCalls],
tokenUsage: { ...this.tokenUsage },
iterations: this.iteration,
};
}
}