yuangs 5.59.0 → 5.63.0
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/agent/DualAgentRuntime.d.ts +15 -1
- package/dist/agent/DualAgentRuntime.js +62 -37
- package/dist/agent/DualAgentRuntime.js.map +1 -1
- package/dist/agent/PlanCache.d.ts +207 -0
- package/dist/agent/PlanCache.js +468 -0
- package/dist/agent/PlanCache.js.map +1 -0
- package/dist/agent/executor.d.ts +4 -0
- package/dist/agent/executor.js +48 -2
- package/dist/agent/executor.js.map +1 -1
- package/dist/agent/governance/riskScoring.d.ts +118 -0
- package/dist/agent/governance/riskScoring.js +422 -0
- package/dist/agent/governance/riskScoring.js.map +1 -0
- package/dist/agent/governance.d.ts +26 -0
- package/dist/agent/governance.js +86 -5
- package/dist/agent/governance.js.map +1 -1
- package/dist/agent/protocolV2_2.js +31 -10
- package/dist/agent/protocolV2_2.js.map +1 -1
- package/dist/agent/relevance.d.ts +93 -0
- package/dist/agent/relevance.js +345 -1
- package/dist/agent/relevance.js.map +1 -1
- package/dist/agent/smartContextManager.d.ts +22 -1
- package/dist/agent/smartContextManager.js +108 -4
- package/dist/agent/smartContextManager.js.map +1 -1
- package/dist/agent/state.d.ts +3 -0
- package/dist/commands/contextStorage.d.ts +32 -0
- package/dist/commands/contextStorage.js +81 -0
- package/dist/commands/contextStorage.js.map +1 -1
- package/dist/core/modelRouter/AdaptiveWeights.d.ts +134 -0
- package/dist/core/modelRouter/AdaptiveWeights.js +300 -0
- package/dist/core/modelRouter/AdaptiveWeights.js.map +1 -0
- package/dist/core/modelRouter/ModelRouter.d.ts +45 -3
- package/dist/core/modelRouter/ModelRouter.js +138 -6
- package/dist/core/modelRouter/ModelRouter.js.map +1 -1
- package/dist/core/modelRouter/MultiMetricSupervisor.d.ts +99 -0
- package/dist/core/modelRouter/MultiMetricSupervisor.js +267 -0
- package/dist/core/modelRouter/MultiMetricSupervisor.js.map +1 -0
- package/dist/core/modelRouter/policies/DslPolicy.d.ts +16 -1
- package/dist/core/modelRouter/policies/DslPolicy.js +22 -1
- package/dist/core/modelRouter/policies/DslPolicy.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.defaultPlanCache = exports.PlanCache = void 0;
|
|
7
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
8
|
+
const DEFAULT_CACHE_CONFIG = {
|
|
9
|
+
maxEntries: 100,
|
|
10
|
+
ttl: 3600000, // 1 hour
|
|
11
|
+
enableComplexityAware: true,
|
|
12
|
+
similarityThreshold: 0.85
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* 计划缓存系统
|
|
16
|
+
*
|
|
17
|
+
* 功能:
|
|
18
|
+
* 1. 输入规范化 - 将可变参数替换为占位符
|
|
19
|
+
* 2. 相似度匹配 - 使用 TF-IDF 计算文本相似度
|
|
20
|
+
* 3. 复杂度感知 - 根据计划复杂度调整缓存策略
|
|
21
|
+
* 4. LRU 淘汰 - 最近最少使用优先淘汰
|
|
22
|
+
* 5. TTL 过期 - 自动清理过期缓存
|
|
23
|
+
*
|
|
24
|
+
* 使用场景:
|
|
25
|
+
* - 用户重复请求相似任务
|
|
26
|
+
* - 批量操作中的重复计划
|
|
27
|
+
* - 测试和调试阶段的频繁调用
|
|
28
|
+
*/
|
|
29
|
+
class PlanCache {
|
|
30
|
+
cache = new Map();
|
|
31
|
+
config;
|
|
32
|
+
totalHits = 0;
|
|
33
|
+
totalMisses = 0;
|
|
34
|
+
// LRU 优化: 跟踪最旧的条目键,避免 O(N) 遍历
|
|
35
|
+
lruKeys = new Set();
|
|
36
|
+
oldestKey;
|
|
37
|
+
// 停用词列表(用于 TF-IDF)
|
|
38
|
+
STOP_WORDS = new Set([
|
|
39
|
+
'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'being',
|
|
40
|
+
'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could',
|
|
41
|
+
'should', 'may', 'might', 'must', 'shall', 'can', 'need', 'of', 'at',
|
|
42
|
+
'by', 'for', 'with', 'about', 'against', 'between', 'into', 'through',
|
|
43
|
+
'during', 'before', 'after', 'above', 'below', 'to', 'from', 'up', 'down',
|
|
44
|
+
'in', 'out', 'on', 'off', 'over', 'under', 'again', 'further', 'then',
|
|
45
|
+
'once', 'here', 'there', 'when', 'where', 'why', 'how', 'all', 'each',
|
|
46
|
+
'few', 'more', 'most', 'other', 'some', 'such', 'no', 'nor', 'not',
|
|
47
|
+
'only', 'own', 'same', 'so', 'than', 'too', 'very', 'just', 'and',
|
|
48
|
+
'but', 'if', 'or', 'because', 'as', 'until', 'while', '这', '那',
|
|
49
|
+
'是', '的', '了', '在', '有', '和', '与', '或', '如果', '那么',
|
|
50
|
+
'因为', '所以', '但是', '然后', '之后', '之前', '的时候'
|
|
51
|
+
]);
|
|
52
|
+
constructor(config = {}) {
|
|
53
|
+
this.config = { ...DEFAULT_CACHE_CONFIG, ...config };
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* 获取或生成计划
|
|
57
|
+
*/
|
|
58
|
+
async getOrGenerate(input, generator) {
|
|
59
|
+
const normalized = this.normalizeInput(input);
|
|
60
|
+
const hash = this.hashInput(normalized);
|
|
61
|
+
// 1. 尝试精确匹配
|
|
62
|
+
const exactEntry = this.cache.get(hash);
|
|
63
|
+
if (exactEntry && this.isValid(exactEntry)) {
|
|
64
|
+
exactEntry.accessCount++;
|
|
65
|
+
exactEntry.lastAccessed = Date.now();
|
|
66
|
+
exactEntry.hitCount++;
|
|
67
|
+
this.totalHits++;
|
|
68
|
+
// 更新 LRU 跟踪 (访问后可能改变 oldestKey)
|
|
69
|
+
this.updateLRUOnAccess(hash);
|
|
70
|
+
console.log(`[PlanCache] Exact cache hit for: ${input.substring(0, 50)}...`);
|
|
71
|
+
return { ...exactEntry.plan }; // 返回副本防止修改
|
|
72
|
+
}
|
|
73
|
+
// 2. 尝试相似度匹配
|
|
74
|
+
if (this.config.enableComplexityAware) {
|
|
75
|
+
const similarEntry = this.findSimilar(normalized);
|
|
76
|
+
if (similarEntry && this.isValid(similarEntry)) {
|
|
77
|
+
similarEntry.accessCount++;
|
|
78
|
+
similarEntry.lastAccessed = Date.now();
|
|
79
|
+
similarEntry.hitCount++;
|
|
80
|
+
this.totalHits++;
|
|
81
|
+
// 更新 LRU 跟踪 (访问后可能改变 oldestKey)
|
|
82
|
+
const accessedHash = this.getHashByEntry(similarEntry);
|
|
83
|
+
if (accessedHash) {
|
|
84
|
+
this.updateLRUOnAccess(accessedHash);
|
|
85
|
+
}
|
|
86
|
+
const similarity = this.calculateSimilarity(normalized, similarEntry.normalizedInput);
|
|
87
|
+
console.log(`[PlanCache] Similar cache hit (${similarity.toFixed(2)})`);
|
|
88
|
+
return { ...similarEntry.plan };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// 3. 缓存未命中,生成新计划
|
|
92
|
+
this.totalMisses++;
|
|
93
|
+
console.log(`[PlanCache] Cache miss, generating new plan...`);
|
|
94
|
+
const plan = await generator();
|
|
95
|
+
// 4. 缓存新生成的计划
|
|
96
|
+
this.set(hash, {
|
|
97
|
+
plan,
|
|
98
|
+
normalizedInput: normalized,
|
|
99
|
+
timestamp: Date.now(),
|
|
100
|
+
accessCount: 1,
|
|
101
|
+
lastAccessed: Date.now(),
|
|
102
|
+
hitCount: 0,
|
|
103
|
+
complexityScore: this.calculateComplexity(plan)
|
|
104
|
+
});
|
|
105
|
+
return plan;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* 保存计划到缓存
|
|
109
|
+
*/
|
|
110
|
+
set(hash, entry) {
|
|
111
|
+
// 如果是新条目且缓存已满,先淘汰
|
|
112
|
+
if (!this.cache.has(hash) && this.cache.size >= this.config.maxEntries) {
|
|
113
|
+
this.evictLRU();
|
|
114
|
+
}
|
|
115
|
+
this.cache.set(hash, entry);
|
|
116
|
+
// 更新 LRU 跟踪
|
|
117
|
+
this.lruKeys.add(hash);
|
|
118
|
+
// 使用 lastAccessed 而不是 timestamp 来跟踪 LRU
|
|
119
|
+
if (!this.oldestKey) {
|
|
120
|
+
this.oldestKey = hash;
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
const oldestEntry = this.cache.get(this.oldestKey);
|
|
124
|
+
// 如果当前条目的 lastAccessed 早于 oldestKey 的 lastAccessed,更新 oldestKey
|
|
125
|
+
if (oldestEntry && entry.lastAccessed < oldestEntry.lastAccessed) {
|
|
126
|
+
this.oldestKey = hash;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* 访问时更新 LRU 跟踪
|
|
132
|
+
*
|
|
133
|
+
* 当条目被访问时,它的 lastAccessed 会被更新,
|
|
134
|
+
* 如果之前是 oldestKey,需要重新计算。
|
|
135
|
+
*/
|
|
136
|
+
updateLRUOnAccess(accessedHash) {
|
|
137
|
+
// 如果访问的是当前的 oldestKey,需要重新计算
|
|
138
|
+
if (this.oldestKey === accessedHash) {
|
|
139
|
+
this.updateOldestKey();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* 根据缓存条目获取其哈希值
|
|
144
|
+
* 用于相似度匹配后更新 LRU
|
|
145
|
+
*/
|
|
146
|
+
getHashByEntry(targetEntry) {
|
|
147
|
+
for (const [hash, entry] of this.cache) {
|
|
148
|
+
if (entry === targetEntry) {
|
|
149
|
+
return hash;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* 检查缓存条目是否有效
|
|
156
|
+
*/
|
|
157
|
+
isValid(entry) {
|
|
158
|
+
const age = Date.now() - entry.timestamp;
|
|
159
|
+
return age < this.config.ttl;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* 查找相似的计划
|
|
163
|
+
*
|
|
164
|
+
* 性能说明: 当前使用 O(N) 遍历,对于默认 maxEntries=100 的情况下性能可接受。
|
|
165
|
+
* 如果未来需要支持更大的缓存,可以考虑使用局部敏感哈希 (LSH) 或近似最近邻搜索。
|
|
166
|
+
*/
|
|
167
|
+
findSimilar(normalizedInput) {
|
|
168
|
+
let bestMatch;
|
|
169
|
+
let bestSimilarity = 0;
|
|
170
|
+
for (const [hash, entry] of this.cache) {
|
|
171
|
+
if (!this.isValid(entry))
|
|
172
|
+
continue;
|
|
173
|
+
const similarity = this.calculateSimilarity(normalizedInput, entry.normalizedInput);
|
|
174
|
+
if (similarity > bestSimilarity && similarity >= this.config.similarityThreshold) {
|
|
175
|
+
bestSimilarity = similarity;
|
|
176
|
+
bestMatch = entry;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return bestMatch;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* 规范化输入
|
|
183
|
+
*
|
|
184
|
+
* 策略:
|
|
185
|
+
* 1. 转换为小写
|
|
186
|
+
* 2. 替换数字为 N
|
|
187
|
+
* 3. 替换引号内容为 ""
|
|
188
|
+
* 4. 移除多余空格
|
|
189
|
+
* 5. 移除停用词
|
|
190
|
+
*/
|
|
191
|
+
normalizeInput(input) {
|
|
192
|
+
return input
|
|
193
|
+
.toLowerCase()
|
|
194
|
+
// 替换数字
|
|
195
|
+
.replace(/\b\d+\b/g, 'N')
|
|
196
|
+
// 替换引号内容
|
|
197
|
+
.replace(/["'][^"']*["']/g, '""')
|
|
198
|
+
// 替换文件路径
|
|
199
|
+
.replace(/[\w\-./]+\.(ts|js|py|go|rs|java|json|yaml|yml|md)/g, 'FILE')
|
|
200
|
+
// 替换 URL
|
|
201
|
+
.replace(/https?:\/\/[^\s]+/g, 'URL')
|
|
202
|
+
// 标准化空白字符
|
|
203
|
+
.replace(/\s+/g, ' ')
|
|
204
|
+
.trim();
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* 计算输入哈希
|
|
208
|
+
*/
|
|
209
|
+
hashInput(input) {
|
|
210
|
+
return crypto_1.default
|
|
211
|
+
.createHash('sha256')
|
|
212
|
+
.update(input)
|
|
213
|
+
.digest('hex')
|
|
214
|
+
.substring(0, 16);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* 计算文本相似度 (TF 向量 + 余弦相似度)
|
|
218
|
+
*/
|
|
219
|
+
calculateSimilarity(input1, input2) {
|
|
220
|
+
const tf1 = this.calculateNormalizedTF(input1);
|
|
221
|
+
const tf2 = this.calculateNormalizedTF(input2);
|
|
222
|
+
return this.cosineSimilarity(tf1, tf2);
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* 计算归一化的词频向量
|
|
226
|
+
*
|
|
227
|
+
* 注意: 这个方法只计算 Term Frequency (TF) 并归一化,
|
|
228
|
+
* 不包含 Inverse Document Frequency (IDF)。
|
|
229
|
+
* 对于相似度匹配来说,单文档的 TF 已经足够。
|
|
230
|
+
*/
|
|
231
|
+
calculateNormalizedTF(text) {
|
|
232
|
+
const words = text.split(/\s+/).filter(w => w.length > 2 && !this.STOP_WORDS.has(w));
|
|
233
|
+
const tf = new Map();
|
|
234
|
+
// 计算词频 (TF)
|
|
235
|
+
for (const word of words) {
|
|
236
|
+
tf.set(word, (tf.get(word) || 0) + 1);
|
|
237
|
+
}
|
|
238
|
+
// 归一化
|
|
239
|
+
const maxFreq = Math.max(...tf.values());
|
|
240
|
+
const vector = new Map();
|
|
241
|
+
for (const [word, freq] of tf) {
|
|
242
|
+
vector.set(word, freq / maxFreq);
|
|
243
|
+
}
|
|
244
|
+
return vector;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* 余弦相似度
|
|
248
|
+
*/
|
|
249
|
+
cosineSimilarity(vec1, vec2) {
|
|
250
|
+
let dotProduct = 0;
|
|
251
|
+
let norm1 = 0;
|
|
252
|
+
let norm2 = 0;
|
|
253
|
+
const allWords = new Set([...vec1.keys(), ...vec2.keys()]);
|
|
254
|
+
for (const word of allWords) {
|
|
255
|
+
const v1 = vec1.get(word) || 0;
|
|
256
|
+
const v2 = vec2.get(word) || 0;
|
|
257
|
+
dotProduct += v1 * v2;
|
|
258
|
+
norm1 += v1 * v1;
|
|
259
|
+
norm2 += v2 * v2;
|
|
260
|
+
}
|
|
261
|
+
const denominator = Math.sqrt(norm1) * Math.sqrt(norm2);
|
|
262
|
+
return denominator > 0 ? dotProduct / denominator : 0;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* 计算计划复杂度
|
|
266
|
+
*/
|
|
267
|
+
calculateComplexity(plan) {
|
|
268
|
+
let complexity = 0;
|
|
269
|
+
// 步骤数量贡献
|
|
270
|
+
complexity += Math.min(plan.steps.length / 10, 0.4);
|
|
271
|
+
// 高风险步骤贡献
|
|
272
|
+
const highRiskCount = plan.steps.filter(s => s.risk_level === 'high').length;
|
|
273
|
+
complexity += (highRiskCount / plan.steps.length) * 0.3;
|
|
274
|
+
// 步骤类型多样性
|
|
275
|
+
const types = new Set(plan.steps.map(s => s.type));
|
|
276
|
+
complexity += (types.size / 5) * 0.2;
|
|
277
|
+
// 依赖关系复杂度
|
|
278
|
+
const totalDeps = plan.steps.reduce((sum, s) => sum + (s.dependencies?.length || 0), 0);
|
|
279
|
+
complexity += Math.min(totalDeps / plan.steps.length / 2, 0.1);
|
|
280
|
+
return Math.min(complexity, 1.0);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* LRU 淘汰策略 (优化版本)
|
|
284
|
+
*
|
|
285
|
+
* 使用 oldestKey 跟踪最近最少使用的条目,将最常见的情况优化为 O(1)。
|
|
286
|
+
* 仅在 oldestKey 无效时回退到 O(N) 遍历。
|
|
287
|
+
*
|
|
288
|
+
* 注意: 这不是标准的 LRU 实现(使用 Map + 双向链表),
|
|
289
|
+
* 但对于当前用例(maxEntries=100,低频淘汰)已足够高效。
|
|
290
|
+
*/
|
|
291
|
+
evictLRU() {
|
|
292
|
+
// 如果 oldestKey 无效,回退到遍历方式
|
|
293
|
+
if (!this.oldestKey || !this.cache.has(this.oldestKey)) {
|
|
294
|
+
this.evictLRUFallback();
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
const evicted = this.oldestKey;
|
|
298
|
+
this.cache.delete(evicted);
|
|
299
|
+
this.lruKeys.delete(evicted);
|
|
300
|
+
// 重新计算 oldestKey
|
|
301
|
+
this.updateOldestKey();
|
|
302
|
+
console.log(`[PlanCache] Evicted LRU entry: ${evicted.substring(0, 8)}...`);
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* 更新 oldestKey (在淘汰或删除后调用)
|
|
306
|
+
*
|
|
307
|
+
* 注意: 这是一个 O(N) 操作,因为需要遍历所有条目找到最少使用的。
|
|
308
|
+
* 但这只在淘汰/清理时调用,不是每次访问时调用,所以整体性能仍可接受。
|
|
309
|
+
*/
|
|
310
|
+
updateOldestKey() {
|
|
311
|
+
let oldestHash;
|
|
312
|
+
let oldestAccess = Infinity;
|
|
313
|
+
for (const [hash, entry] of this.cache) {
|
|
314
|
+
if (entry.lastAccessed < oldestAccess) {
|
|
315
|
+
oldestAccess = entry.lastAccessed;
|
|
316
|
+
oldestHash = hash;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
this.oldestKey = oldestHash;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* LRU 淘汰回退方法 (当 oldestKey 无效时使用)
|
|
323
|
+
*/
|
|
324
|
+
evictLRUFallback() {
|
|
325
|
+
let oldestHash;
|
|
326
|
+
let oldestTime = Infinity;
|
|
327
|
+
for (const [hash, entry] of this.cache) {
|
|
328
|
+
if (entry.lastAccessed < oldestTime) {
|
|
329
|
+
oldestTime = entry.lastAccessed;
|
|
330
|
+
oldestHash = hash;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
if (oldestHash) {
|
|
334
|
+
this.cache.delete(oldestHash);
|
|
335
|
+
this.lruKeys.delete(oldestHash);
|
|
336
|
+
this.oldestKey = undefined;
|
|
337
|
+
this.updateOldestKey();
|
|
338
|
+
console.log(`[PlanCache] Evicted LRU entry (fallback): ${oldestHash.substring(0, 8)}...`);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* 清理过期缓存
|
|
343
|
+
*/
|
|
344
|
+
cleanup() {
|
|
345
|
+
let cleaned = 0;
|
|
346
|
+
const now = Date.now();
|
|
347
|
+
for (const [hash, entry] of this.cache) {
|
|
348
|
+
if (now - entry.timestamp > this.config.ttl) {
|
|
349
|
+
this.cache.delete(hash);
|
|
350
|
+
this.lruKeys.delete(hash);
|
|
351
|
+
cleaned++;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
if (cleaned > 0) {
|
|
355
|
+
console.log(`[PlanCache] Cleaned up ${cleaned} expired entries`);
|
|
356
|
+
// 清理后更新 oldestKey
|
|
357
|
+
this.updateOldestKey();
|
|
358
|
+
}
|
|
359
|
+
return cleaned;
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* 清空缓存
|
|
363
|
+
*/
|
|
364
|
+
clear() {
|
|
365
|
+
this.cache.clear();
|
|
366
|
+
this.lruKeys.clear();
|
|
367
|
+
this.oldestKey = undefined;
|
|
368
|
+
this.totalHits = 0;
|
|
369
|
+
this.totalMisses = 0;
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* 获取缓存统计
|
|
373
|
+
*/
|
|
374
|
+
getStats() {
|
|
375
|
+
const entries = Array.from(this.cache.values());
|
|
376
|
+
const totalRequests = this.totalHits + this.totalMisses;
|
|
377
|
+
// 计算复杂度分布
|
|
378
|
+
let low = 0, medium = 0, high = 0;
|
|
379
|
+
for (const entry of entries) {
|
|
380
|
+
if (entry.complexityScore < 0.3)
|
|
381
|
+
low++;
|
|
382
|
+
else if (entry.complexityScore < 0.7)
|
|
383
|
+
medium++;
|
|
384
|
+
else
|
|
385
|
+
high++;
|
|
386
|
+
}
|
|
387
|
+
// 计算平均缓存大小: 通过序列化每个 plan 为 JSON 字符串来估算内存占用
|
|
388
|
+
// 注意: 这只是近似值,实际内存占用会更高(包括对象开销、Map 结构等)
|
|
389
|
+
const totalSize = entries.reduce((sum, e) => sum + JSON.stringify(e.plan).length, 0);
|
|
390
|
+
const avgSize = entries.length > 0 ? totalSize / entries.length : 0;
|
|
391
|
+
return {
|
|
392
|
+
totalEntries: this.cache.size,
|
|
393
|
+
totalHits: this.totalHits,
|
|
394
|
+
totalMisses: this.totalMisses,
|
|
395
|
+
hitRate: totalRequests > 0 ? this.totalHits / totalRequests : 0,
|
|
396
|
+
avgCacheSize: avgSize,
|
|
397
|
+
complexityDistribution: { low, medium, high }
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* 获取缓存条目详情
|
|
402
|
+
*/
|
|
403
|
+
getEntry(hash) {
|
|
404
|
+
const entry = this.cache.get(hash);
|
|
405
|
+
return entry && this.isValid(entry) ? entry : undefined;
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* 预热缓存(批量导入)
|
|
409
|
+
*
|
|
410
|
+
* 注意: 如果条目数超过 maxEntries,将使用 LRU 策略淘汰旧条目
|
|
411
|
+
*/
|
|
412
|
+
warmUp(entries) {
|
|
413
|
+
for (const { input, plan } of entries) {
|
|
414
|
+
const normalized = this.normalizeInput(input);
|
|
415
|
+
// 使用 set 方法以确保所有缓存管理逻辑正确应用
|
|
416
|
+
this.set(this.hashInput(normalized), {
|
|
417
|
+
plan: { ...plan }, // 返回副本防止修改原始计划
|
|
418
|
+
normalizedInput: normalized,
|
|
419
|
+
timestamp: Date.now(),
|
|
420
|
+
accessCount: 0,
|
|
421
|
+
lastAccessed: Date.now(),
|
|
422
|
+
hitCount: 0,
|
|
423
|
+
complexityScore: this.calculateComplexity(plan)
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
console.log(`[PlanCache] Warmed up with ${entries.length} entries`);
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* 导出缓存(用于持久化)
|
|
430
|
+
*/
|
|
431
|
+
export() {
|
|
432
|
+
const result = [];
|
|
433
|
+
for (const [hash, entry] of this.cache) {
|
|
434
|
+
if (this.isValid(entry)) {
|
|
435
|
+
result.push({ hash, entry });
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
return result;
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* 导入缓存(从持久化恢复)
|
|
442
|
+
*/
|
|
443
|
+
import(data) {
|
|
444
|
+
for (const { hash, entry } of data) {
|
|
445
|
+
if (this.isValid(entry)) {
|
|
446
|
+
this.cache.set(hash, entry);
|
|
447
|
+
this.lruKeys.add(hash);
|
|
448
|
+
// 更新 oldestKey (使用 lastAccessed)
|
|
449
|
+
if (!this.oldestKey) {
|
|
450
|
+
this.oldestKey = hash;
|
|
451
|
+
}
|
|
452
|
+
else {
|
|
453
|
+
const oldestEntry = this.cache.get(this.oldestKey);
|
|
454
|
+
if (oldestEntry && entry.lastAccessed < oldestEntry.lastAccessed) {
|
|
455
|
+
this.oldestKey = hash;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
console.log(`[PlanCache] Imported ${data.length} entries`);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
exports.PlanCache = PlanCache;
|
|
464
|
+
// 注意: 不再导出默认单例,以避免全局状态和测试隔离问题
|
|
465
|
+
// 每个需要 PlanCache 的实例应该创建自己的实例
|
|
466
|
+
// 如果需要共享缓存,请通过依赖注入的方式传递
|
|
467
|
+
exports.defaultPlanCache = new PlanCache();
|
|
468
|
+
//# sourceMappingURL=PlanCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PlanCache.js","sourceRoot":"","sources":["../../src/agent/PlanCache.ts"],"names":[],"mappings":"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"}
|
package/dist/agent/executor.d.ts
CHANGED
package/dist/agent/executor.js
CHANGED
|
@@ -254,10 +254,11 @@ class ToolExecutor {
|
|
|
254
254
|
};
|
|
255
255
|
}
|
|
256
256
|
catch (error) {
|
|
257
|
+
const friendly = this.getFriendlyError('read_file', error);
|
|
257
258
|
return {
|
|
258
259
|
success: false,
|
|
259
|
-
error:
|
|
260
|
-
output:
|
|
260
|
+
error: friendly.message,
|
|
261
|
+
output: friendly.suggestion
|
|
261
262
|
};
|
|
262
263
|
}
|
|
263
264
|
}
|
|
@@ -914,6 +915,51 @@ class ToolExecutor {
|
|
|
914
915
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
915
916
|
return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i];
|
|
916
917
|
}
|
|
918
|
+
/**
|
|
919
|
+
* 获取用户友好的错误消息和建议
|
|
920
|
+
*/
|
|
921
|
+
static getFriendlyError(toolName, error) {
|
|
922
|
+
const errorMsg = error?.message || String(error);
|
|
923
|
+
const lowerError = errorMsg.toLowerCase();
|
|
924
|
+
// 文件不存在
|
|
925
|
+
if (lowerError.includes('enoent') || lowerError.includes('no such file') || lowerError.includes('not found')) {
|
|
926
|
+
const match = errorMsg.match(/['"](.*?)['"]|['`](.*?)['`]/);
|
|
927
|
+
const fileName = match ? match[1] : '指定文件';
|
|
928
|
+
return {
|
|
929
|
+
message: `文件未找到: ${fileName}`,
|
|
930
|
+
suggestion: `💡 建议:使用 list_files 查看可用文件,或检查文件路径是否正确`
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
// 权限错误
|
|
934
|
+
if (lowerError.includes('eacces') || lowerError.includes('permission denied')) {
|
|
935
|
+
return {
|
|
936
|
+
message: `权限不足:无法访问该文件`,
|
|
937
|
+
suggestion: `💡 建议:检查文件权限,或使用 sudo(如果适用)`
|
|
938
|
+
};
|
|
939
|
+
}
|
|
940
|
+
// 语法错误
|
|
941
|
+
if (lowerError.includes('syntax') || lowerError.includes('parse')) {
|
|
942
|
+
return {
|
|
943
|
+
message: `命令语法错误`,
|
|
944
|
+
suggestion: `💡 建议:检查命令格式,参考工具文档`
|
|
945
|
+
};
|
|
946
|
+
}
|
|
947
|
+
// 根据工具名称提供特定建议
|
|
948
|
+
const suggestions = {
|
|
949
|
+
read_file_lines: '💡 建议:检查 start_line 是否在文件范围内,使用 file_info 查看文件总行数',
|
|
950
|
+
read_file_lines_from_end: '💡 建议:count 参数不要超过文件总行数',
|
|
951
|
+
search_in_files: '💡 建议:使用更具体的搜索词,或使用 file_pattern 限制搜索范围',
|
|
952
|
+
search_symbol: '💡 建议:检查符号名称是否正确,或尝试使用 search_in_files 搜索',
|
|
953
|
+
write_file: '💡 建议:确保目录存在,检查文件路径是否正确',
|
|
954
|
+
git_status: '💡 建议:确认当前在 Git 仓库中',
|
|
955
|
+
git_diff: '💡 建议:检查是否有未提交的更改',
|
|
956
|
+
git_log: '💡 建议:检查是否有提交历史'
|
|
957
|
+
};
|
|
958
|
+
return {
|
|
959
|
+
message: errorMsg,
|
|
960
|
+
suggestion: suggestions[toolName] || '💡 建议:检查参数是否正确,或尝试不同的工具'
|
|
961
|
+
};
|
|
962
|
+
}
|
|
917
963
|
}
|
|
918
964
|
exports.ToolExecutor = ToolExecutor;
|
|
919
965
|
//# sourceMappingURL=executor.js.map
|