deeper-cli 1.2.4 → 1.3.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/cli/index.js +231 -44
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/chat-repl.ts +1 -1
- package/src/memory/xmemory.ts +254 -48
- package/src/model/DeepSeekClient.ts +5 -0
package/dist/cli/index.js
CHANGED
|
@@ -1131,44 +1131,100 @@ function uid() {
|
|
|
1131
1131
|
function ensureDir() {
|
|
1132
1132
|
if (!existsSync5(MEM_DIR)) mkdirSync4(MEM_DIR, { recursive: true });
|
|
1133
1133
|
if (!existsSync5(STATS_FILE)) {
|
|
1134
|
-
writeFileSync3(STATS_FILE, JSON.stringify({ totalEntries: 0, byType: {}, totalTokens: 0, lastCleanup: Date.now() }), "utf-8");
|
|
1134
|
+
writeFileSync3(STATS_FILE, JSON.stringify({ totalEntries: 0, byType: {}, totalTokens: 0, lastCleanup: Date.now(), lastConsolidate: Date.now() }, null, 2), "utf-8");
|
|
1135
1135
|
}
|
|
1136
1136
|
}
|
|
1137
1137
|
function loadStats() {
|
|
1138
1138
|
try {
|
|
1139
1139
|
return JSON.parse(readFileSync4(STATS_FILE, "utf-8"));
|
|
1140
1140
|
} catch {
|
|
1141
|
-
return { totalEntries: 0, byType: {}, totalTokens: 0, lastCleanup: 0 };
|
|
1141
|
+
return { totalEntries: 0, byType: {}, totalTokens: 0, lastCleanup: 0, lastConsolidate: 0 };
|
|
1142
1142
|
}
|
|
1143
1143
|
}
|
|
1144
1144
|
function saveStats(s) {
|
|
1145
1145
|
writeFileSync3(STATS_FILE, JSON.stringify(s, null, 2), "utf-8");
|
|
1146
1146
|
}
|
|
1147
|
-
|
|
1147
|
+
function tokenize(text) {
|
|
1148
|
+
const lower = text.toLowerCase();
|
|
1149
|
+
const words = lower.split(/[\s\p{P}\p{S}]+/).filter((w) => w.length >= 2);
|
|
1150
|
+
const bigrams = [];
|
|
1151
|
+
for (let i = 0; i < words.length - 1; i++) bigrams.push(words[i] + "_" + words[i + 1]);
|
|
1152
|
+
return [.../* @__PURE__ */ new Set([...words, ...bigrams])];
|
|
1153
|
+
}
|
|
1154
|
+
function similarity(a, b2) {
|
|
1155
|
+
if (a === b2) return 1;
|
|
1156
|
+
if (!a || !b2) return 0;
|
|
1157
|
+
const ta = tokenize(a);
|
|
1158
|
+
const tb = tokenize(b2);
|
|
1159
|
+
if (ta.length === 0 || tb.length === 0) return 0;
|
|
1160
|
+
const sa = new Set(ta);
|
|
1161
|
+
const sb = new Set(tb);
|
|
1162
|
+
let intersection = 0;
|
|
1163
|
+
for (const t of sa) if (sb.has(t)) intersection++;
|
|
1164
|
+
const union = Math.max(sa.size, sb.size);
|
|
1165
|
+
return union > 0 ? intersection / union : 0;
|
|
1166
|
+
}
|
|
1167
|
+
var MEM_DIR, STATS_FILE, MAX_WORKING_MEM, MAX_TOTAL_MEM, CLEANUP_THRESHOLD, DEDUP_SIMILARITY_THRESHOLD, CONSOLIDATE_THRESHOLD, SAVE_DEBOUNCE_MS, currentSessionId, TFIDFIndexer, XMemory, xmemory;
|
|
1148
1168
|
var init_xmemory = __esm({
|
|
1149
1169
|
"src/memory/xmemory.ts"() {
|
|
1150
1170
|
"use strict";
|
|
1151
1171
|
init_constants();
|
|
1152
1172
|
MEM_DIR = join4(DEEPER_HOME, "xmemory");
|
|
1153
1173
|
STATS_FILE = join4(MEM_DIR, "stats.json");
|
|
1154
|
-
MAX_WORKING_MEM =
|
|
1155
|
-
MAX_TOTAL_MEM =
|
|
1156
|
-
CLEANUP_THRESHOLD =
|
|
1174
|
+
MAX_WORKING_MEM = 100;
|
|
1175
|
+
MAX_TOTAL_MEM = 3e3;
|
|
1176
|
+
CLEANUP_THRESHOLD = 2e3;
|
|
1177
|
+
DEDUP_SIMILARITY_THRESHOLD = 0.85;
|
|
1178
|
+
CONSOLIDATE_THRESHOLD = 5;
|
|
1179
|
+
SAVE_DEBOUNCE_MS = 3e3;
|
|
1157
1180
|
currentSessionId = "";
|
|
1181
|
+
TFIDFIndexer = class {
|
|
1182
|
+
docFreq = /* @__PURE__ */ new Map();
|
|
1183
|
+
numDocs = 0;
|
|
1184
|
+
build(entries) {
|
|
1185
|
+
this.docFreq.clear();
|
|
1186
|
+
this.numDocs = 0;
|
|
1187
|
+
for (const entry of entries) {
|
|
1188
|
+
this.numDocs++;
|
|
1189
|
+
const tokens = new Set(tokenize(entry.content));
|
|
1190
|
+
for (const t of tokens) this.docFreq.set(t, (this.docFreq.get(t) || 0) + 1);
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
idf(term) {
|
|
1194
|
+
const df = this.docFreq.get(term) || 0;
|
|
1195
|
+
if (df === 0 || df >= this.numDocs) return 0;
|
|
1196
|
+
return Math.log((this.numDocs + 0.5) / (df + 0.5)) + 1;
|
|
1197
|
+
}
|
|
1198
|
+
tfidfScore(content, queryTerms) {
|
|
1199
|
+
const tokens = tokenize(content);
|
|
1200
|
+
const tfMap = /* @__PURE__ */ new Map();
|
|
1201
|
+
for (const t of tokens) tfMap.set(t, (tfMap.get(t) || 0) + 1);
|
|
1202
|
+
const maxTf = Math.max(...tfMap.values(), 1);
|
|
1203
|
+
let score = 0;
|
|
1204
|
+
for (const qt of queryTerms) {
|
|
1205
|
+
const tf = (tfMap.get(qt) || 0) / maxTf * (1 + Math.log(tokens.length));
|
|
1206
|
+
score += tf * this.idf(qt);
|
|
1207
|
+
}
|
|
1208
|
+
return score;
|
|
1209
|
+
}
|
|
1210
|
+
};
|
|
1158
1211
|
XMemory = class {
|
|
1159
1212
|
working = [];
|
|
1160
1213
|
index = /* @__PURE__ */ new Map();
|
|
1161
1214
|
dirty = false;
|
|
1215
|
+
saveTimer = null;
|
|
1216
|
+
tfidf = new TFIDFIndexer();
|
|
1162
1217
|
constructor() {
|
|
1163
1218
|
ensureDir();
|
|
1164
1219
|
}
|
|
1165
|
-
// ============ 写入 ============
|
|
1166
1220
|
store(type, content, tags = [], importance = 5, accuracy = 7, source = "agent", references = []) {
|
|
1221
|
+
const deduped = this.deduplicate(type, content, importance);
|
|
1222
|
+
if (deduped !== null) return deduped;
|
|
1167
1223
|
const id = uid();
|
|
1168
1224
|
const entry = {
|
|
1169
1225
|
id,
|
|
1170
1226
|
type,
|
|
1171
|
-
content: content.slice(0,
|
|
1227
|
+
content: content.slice(0, 4e3),
|
|
1172
1228
|
tags,
|
|
1173
1229
|
importance: Math.min(10, Math.max(0, importance)),
|
|
1174
1230
|
accuracy: Math.min(10, Math.max(0, accuracy)),
|
|
@@ -1181,12 +1237,11 @@ var init_xmemory = __esm({
|
|
|
1181
1237
|
};
|
|
1182
1238
|
if (type === "working") {
|
|
1183
1239
|
this.working.push(entry);
|
|
1184
|
-
|
|
1185
|
-
this.working.shift();
|
|
1186
|
-
}
|
|
1240
|
+
this.evictWorking();
|
|
1187
1241
|
}
|
|
1188
1242
|
this.index.set(id, entry);
|
|
1189
1243
|
this.dirty = true;
|
|
1244
|
+
this.scheduleSave();
|
|
1190
1245
|
if (this.index.size > CLEANUP_THRESHOLD) {
|
|
1191
1246
|
this.autoCleanup();
|
|
1192
1247
|
}
|
|
@@ -1204,31 +1259,41 @@ var init_xmemory = __esm({
|
|
|
1204
1259
|
storeWorking(content, tags = []) {
|
|
1205
1260
|
return this.store("working", content, tags, 3, 5, "agent");
|
|
1206
1261
|
}
|
|
1207
|
-
// ============ 检索 ============
|
|
1208
1262
|
recall(query, limit = 5, minImportance = 0) {
|
|
1209
|
-
const keywords = query
|
|
1263
|
+
const keywords = tokenize(query).filter((w) => w.length >= 2);
|
|
1210
1264
|
if (keywords.length === 0) return [];
|
|
1211
|
-
|
|
1265
|
+
this.tfidf.build(this.index.values());
|
|
1212
1266
|
const now = Date.now();
|
|
1267
|
+
const scored = [];
|
|
1213
1268
|
for (const entry of this.index.values()) {
|
|
1214
1269
|
if (entry.importance < minImportance) continue;
|
|
1215
|
-
|
|
1216
|
-
const c2 = (entry.content || "").toLowerCase();
|
|
1270
|
+
const c2 = entry.content.toLowerCase();
|
|
1217
1271
|
const t = entry.tags.join(" ").toLowerCase();
|
|
1272
|
+
let keywordScore = 0;
|
|
1273
|
+
let exactMatchBonus = 0;
|
|
1218
1274
|
for (const kw of keywords) {
|
|
1219
|
-
if (c2.includes(kw))
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1275
|
+
if (c2.includes(kw)) {
|
|
1276
|
+
keywordScore += 3;
|
|
1277
|
+
exactMatchBonus += 1;
|
|
1278
|
+
}
|
|
1279
|
+
if (t.includes(kw)) keywordScore += 2;
|
|
1280
|
+
if (entry.type === "procedural" && c2.includes(kw)) keywordScore += 1;
|
|
1281
|
+
if (entry.type === "semantic" && c2.includes(kw)) keywordScore += 1.5;
|
|
1282
|
+
}
|
|
1283
|
+
const tfidfScore = this.tfidf.tfidfScore(entry.content, keywords);
|
|
1284
|
+
const recencyBoost = Math.max(0, 3 - (now - entry.accessedAt) / (1e3 * 60 * 30));
|
|
1285
|
+
const frequencyBoost = Math.min(entry.accessCount * 0.3, 4);
|
|
1286
|
+
const importanceWeight = entry.importance * 0.6;
|
|
1287
|
+
const ageHours = (now - entry.createdAt) / (1e3 * 60 * 60);
|
|
1288
|
+
const ageDecay = Math.min(ageHours / 48, 6);
|
|
1289
|
+
const totalScore = keywordScore * 1 + tfidfScore * 2 + importanceWeight + recencyBoost + frequencyBoost - ageDecay + (exactMatchBonus >= 3 ? 3 : 0);
|
|
1290
|
+
if (totalScore > 0) scored.push({ entry, score: totalScore });
|
|
1227
1291
|
}
|
|
1228
1292
|
scored.sort((a, b2) => b2.score - a.score);
|
|
1229
1293
|
return scored.slice(0, limit).map((s) => {
|
|
1230
1294
|
s.entry.accessedAt = now;
|
|
1231
1295
|
s.entry.accessCount++;
|
|
1296
|
+
s.entry.importance = Math.min(10, s.entry.importance + 0.1);
|
|
1232
1297
|
return s.entry;
|
|
1233
1298
|
});
|
|
1234
1299
|
}
|
|
@@ -1237,18 +1302,21 @@ var init_xmemory = __esm({
|
|
|
1237
1302
|
for (const entry of this.index.values()) {
|
|
1238
1303
|
if (entry.type === type) res.push(entry);
|
|
1239
1304
|
}
|
|
1240
|
-
res.sort((a, b2) => b2.
|
|
1305
|
+
res.sort((a, b2) => b2.importance * 2 + b2.accessCount - (a.importance * 2 + a.accessCount));
|
|
1241
1306
|
return res.slice(0, limit);
|
|
1242
1307
|
}
|
|
1243
1308
|
getWorking() {
|
|
1244
|
-
return this.working
|
|
1309
|
+
return this.working.sort(
|
|
1310
|
+
(a, b2) => b2.importance * 2 + b2.accessCount - (a.importance * 2 + a.accessCount)
|
|
1311
|
+
);
|
|
1245
1312
|
}
|
|
1246
|
-
getWorkingContext(maxTokens =
|
|
1313
|
+
getWorkingContext(maxTokens = 4e3) {
|
|
1247
1314
|
if (this.working.length === 0) return "";
|
|
1248
|
-
const
|
|
1315
|
+
const sorted = this.getWorking();
|
|
1316
|
+
const lines = sorted.map((e) => `[${e.source}] ${e.content.slice(0, 500)}`);
|
|
1249
1317
|
let result = "";
|
|
1250
1318
|
for (const line of lines) {
|
|
1251
|
-
if ((result + line).length > maxTokens *
|
|
1319
|
+
if ((result + line).length > maxTokens * 3) break;
|
|
1252
1320
|
result += line + "\n";
|
|
1253
1321
|
}
|
|
1254
1322
|
return result;
|
|
@@ -1257,19 +1325,34 @@ var init_xmemory = __esm({
|
|
|
1257
1325
|
const recalled = this.recall(task, limit, 3);
|
|
1258
1326
|
const proc = recalled.filter((r2) => r2.type === "procedural" || r2.type === "semantic");
|
|
1259
1327
|
if (proc.length === 0) return "";
|
|
1260
|
-
return "[\u8BB0\u5FC6\u63D0\u793A]\n" + proc.map((p) => `- ${p.content.slice(0,
|
|
1328
|
+
return "[\u8BB0\u5FC6\u63D0\u793A]\n" + proc.map((p) => `- [${p.type === "procedural" ? "\u6280\u80FD" : "\u77E5\u8BC6"}] ${p.content.slice(0, 350)}`).join("\n");
|
|
1261
1329
|
}
|
|
1262
1330
|
getSessionSummary() {
|
|
1263
1331
|
const entries = [...this.index.values()].filter((e) => e.sessionId === currentSessionId);
|
|
1264
1332
|
if (entries.length === 0) return "";
|
|
1265
|
-
const
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1333
|
+
const byType = { semantic: [], procedural: [], episodic: [], working: [] };
|
|
1334
|
+
for (const e of entries) {
|
|
1335
|
+
if (byType[e.type]) byType[e.type].push(e);
|
|
1336
|
+
}
|
|
1337
|
+
const parts = [];
|
|
1338
|
+
const keySemantic = byType.semantic.sort((a, b2) => b2.importance - a.importance).slice(0, 5);
|
|
1339
|
+
if (keySemantic.length > 0) {
|
|
1340
|
+
parts.push(`[\u77E5\u8BC6\u8BB0\u5FC6\xB7${keySemantic.length}\u6761]
|
|
1341
|
+
` + keySemantic.map((e) => `\u2022 ${e.content.slice(0, 250)}`).join("\n"));
|
|
1342
|
+
}
|
|
1343
|
+
const keyProcedural = byType.procedural.sort((a, b2) => b2.importance - a.importance).slice(0, 5);
|
|
1344
|
+
if (keyProcedural.length > 0) {
|
|
1345
|
+
parts.push(`[\u6280\u80FD\u8BB0\u5FC6\xB7${keyProcedural.length}\u6761]
|
|
1346
|
+
` + keyProcedural.map((e) => `\u2022 ${e.content.slice(0, 250)}`).join("\n"));
|
|
1347
|
+
}
|
|
1348
|
+
const keyEpisodic = byType.episodic.sort((a, b2) => b2.importance - a.importance).slice(0, 3);
|
|
1349
|
+
if (keyEpisodic.length > 0) {
|
|
1350
|
+
parts.push(`[\u7ECF\u5386\u8BB0\u5FC6\xB7${keyEpisodic.length}\u6761]
|
|
1351
|
+
` + keyEpisodic.map((e) => `\u2192 ${e.content.slice(0, 150)}`).join("\n"));
|
|
1352
|
+
}
|
|
1353
|
+
return `[XMemory\xB7\u672C\u4F1A\u8BDD ${entries.length}\u6761]
|
|
1354
|
+
${parts.join("\n")}`;
|
|
1355
|
+
}
|
|
1273
1356
|
async save() {
|
|
1274
1357
|
if (!this.dirty) return;
|
|
1275
1358
|
ensureDir();
|
|
@@ -1280,7 +1363,7 @@ var init_xmemory = __esm({
|
|
|
1280
1363
|
}
|
|
1281
1364
|
for (const [type, entries] of Object.entries(byType)) {
|
|
1282
1365
|
const file = join4(MEM_DIR, `${type}.json`);
|
|
1283
|
-
writeFileSync3(file, JSON.stringify(entries.slice(-
|
|
1366
|
+
writeFileSync3(file, JSON.stringify(entries.slice(-800)), "utf-8");
|
|
1284
1367
|
}
|
|
1285
1368
|
const stats = loadStats();
|
|
1286
1369
|
stats.totalEntries = this.index.size;
|
|
@@ -1312,16 +1395,112 @@ var init_xmemory = __esm({
|
|
|
1312
1395
|
if (this.working.length > MAX_WORKING_MEM) {
|
|
1313
1396
|
this.working = this.working.slice(-MAX_WORKING_MEM);
|
|
1314
1397
|
}
|
|
1398
|
+
this.consolidateIfNeeded();
|
|
1399
|
+
}
|
|
1400
|
+
scheduleSave() {
|
|
1401
|
+
if (this.saveTimer) return;
|
|
1402
|
+
this.saveTimer = setTimeout(() => {
|
|
1403
|
+
this.saveTimer = null;
|
|
1404
|
+
this.save().catch(() => {
|
|
1405
|
+
});
|
|
1406
|
+
}, SAVE_DEBOUNCE_MS);
|
|
1407
|
+
}
|
|
1408
|
+
deduplicate(type, content, importance) {
|
|
1409
|
+
const threshold = type === "working" ? 0.95 : type === "episodic" ? 0.85 : DEDUP_SIMILARITY_THRESHOLD;
|
|
1410
|
+
const shortContent = content.slice(0, 500);
|
|
1411
|
+
for (const entry of this.index.values()) {
|
|
1412
|
+
if (entry.type !== type) continue;
|
|
1413
|
+
const sim = similarity(shortContent, entry.content.slice(0, 500));
|
|
1414
|
+
if (sim >= threshold) {
|
|
1415
|
+
entry.accessedAt = Date.now();
|
|
1416
|
+
entry.accessCount++;
|
|
1417
|
+
entry.importance = Math.min(10, Math.max(entry.importance, importance));
|
|
1418
|
+
if (content.length > entry.content.length && content.length <= 4e3) {
|
|
1419
|
+
entry.content = content;
|
|
1420
|
+
this.dirty = true;
|
|
1421
|
+
}
|
|
1422
|
+
return entry.id;
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
return null;
|
|
1426
|
+
}
|
|
1427
|
+
evictWorking() {
|
|
1428
|
+
while (this.working.length > MAX_WORKING_MEM) {
|
|
1429
|
+
let worstIdx = 0;
|
|
1430
|
+
let worstScore = Infinity;
|
|
1431
|
+
for (let i = 0; i < this.working.length; i++) {
|
|
1432
|
+
const e = this.working[i];
|
|
1433
|
+
const score = e.importance + e.accessCount * 0.3 - (Date.now() - e.accessedAt) / (1e3 * 60 * 15);
|
|
1434
|
+
if (score < worstScore) {
|
|
1435
|
+
worstScore = score;
|
|
1436
|
+
worstIdx = i;
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
this.working.splice(worstIdx, 1);
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
consolidateIfNeeded() {
|
|
1443
|
+
const stats = loadStats();
|
|
1444
|
+
const now = Date.now();
|
|
1445
|
+
if (now - stats.lastConsolidate < 24 * 60 * 60 * 1e3) return;
|
|
1446
|
+
const candidates = /* @__PURE__ */ new Map();
|
|
1447
|
+
for (const entry of this.index.values()) {
|
|
1448
|
+
if (entry.type === "episodic" && entry.accessCount >= CONSOLIDATE_THRESHOLD) {
|
|
1449
|
+
const key = entry.tags.slice(0, 3).sort().join("|") || "_default_";
|
|
1450
|
+
if (!candidates.has(key)) candidates.set(key, []);
|
|
1451
|
+
candidates.get(key).push(entry);
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
let consolidated = 0;
|
|
1455
|
+
for (const [, group] of candidates) {
|
|
1456
|
+
if (group.length < 2) continue;
|
|
1457
|
+
group.sort((a, b2) => b2.accessCount - a.accessCount);
|
|
1458
|
+
const best = group[0];
|
|
1459
|
+
const allContent = group.map((g2) => g2.content).join("\n");
|
|
1460
|
+
const summary = `[ consolidated from ${group.length} memories ]
|
|
1461
|
+
${allContent.slice(0, 2e3)}`;
|
|
1462
|
+
const newType = best.accessCount >= 10 ? "procedural" : "semantic";
|
|
1463
|
+
const existing = this.findSimilar(newType, best.content);
|
|
1464
|
+
if (existing) {
|
|
1465
|
+
existing.content = summary.slice(0, 4e3);
|
|
1466
|
+
existing.accessCount += Math.floor(group.reduce((s, g2) => s + g2.accessCount, 0) / group.length);
|
|
1467
|
+
existing.importance = Math.min(10, existing.importance + 1);
|
|
1468
|
+
} else {
|
|
1469
|
+
this.store(newType, summary, best.tags, Math.min(10, best.importance + 2), 9, "system");
|
|
1470
|
+
consolidated++;
|
|
1471
|
+
}
|
|
1472
|
+
for (const old of group) {
|
|
1473
|
+
if (old.id !== best.id) this.index.delete(old.id);
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
if (consolidated > 0 || candidates.size > 0) {
|
|
1477
|
+
stats.lastConsolidate = now;
|
|
1478
|
+
saveStats(stats);
|
|
1479
|
+
this.dirty = true;
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
findSimilar(type, content) {
|
|
1483
|
+
const threshold = 0.75;
|
|
1484
|
+
let best = null;
|
|
1485
|
+
let bestSim = 0;
|
|
1486
|
+
for (const entry of this.index.values()) {
|
|
1487
|
+
if (entry.type !== type) continue;
|
|
1488
|
+
const sim = similarity(content.slice(0, 300), entry.content.slice(0, 300));
|
|
1489
|
+
if (sim > bestSim) {
|
|
1490
|
+
bestSim = sim;
|
|
1491
|
+
best = entry;
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
return bestSim >= threshold ? best : null;
|
|
1315
1495
|
}
|
|
1316
|
-
// ============ 维护 ============
|
|
1317
1496
|
autoCleanup() {
|
|
1318
1497
|
const entries = [...this.index.values()];
|
|
1319
1498
|
entries.sort((a, b2) => {
|
|
1320
|
-
const scoreA = a.importance * 2 + a.accessCount - (Date.now() - a.accessedAt) / (1e3 * 60 * 60 * 24);
|
|
1321
|
-
const scoreB = b2.importance * 2 + b2.accessCount - (Date.now() - b2.accessedAt) / (1e3 * 60 * 60 * 24);
|
|
1499
|
+
const scoreA = a.importance * 2 + a.accessCount + (a.type === "semantic" ? 3 : a.type === "procedural" ? 2 : 0) - (Date.now() - a.accessedAt) / (1e3 * 60 * 60 * 24);
|
|
1500
|
+
const scoreB = b2.importance * 2 + b2.accessCount + (b2.type === "semantic" ? 3 : b2.type === "procedural" ? 2 : 0) - (Date.now() - b2.accessedAt) / (1e3 * 60 * 60 * 24);
|
|
1322
1501
|
return scoreA - scoreB;
|
|
1323
1502
|
});
|
|
1324
|
-
const toKeep = entries.slice(-
|
|
1503
|
+
const toKeep = entries.slice(-800);
|
|
1325
1504
|
this.index.clear();
|
|
1326
1505
|
this.working = [];
|
|
1327
1506
|
for (const entry of toKeep) {
|
|
@@ -3843,6 +4022,11 @@ var init_DeepSeekClient = __esm({
|
|
|
3843
4022
|
const rc = m.reasoning_content || m.thinking;
|
|
3844
4023
|
if (rc) msg.reasoning_content = rc;
|
|
3845
4024
|
return msg;
|
|
4025
|
+
}).map((msg) => {
|
|
4026
|
+
if (msg.role === "tool" && !msg.name) {
|
|
4027
|
+
msg.name = "tool";
|
|
4028
|
+
}
|
|
4029
|
+
return msg;
|
|
3846
4030
|
}),
|
|
3847
4031
|
temperature: config.temperature,
|
|
3848
4032
|
max_tokens: config.maxTokens,
|
|
@@ -12450,7 +12634,10 @@ ${globalRules}` });
|
|
|
12450
12634
|
}
|
|
12451
12635
|
r2.push(e);
|
|
12452
12636
|
}
|
|
12453
|
-
return r2
|
|
12637
|
+
return r2.map((m) => {
|
|
12638
|
+
if (m.role === "tool" && !m.name) m.name = "tool";
|
|
12639
|
+
return m;
|
|
12640
|
+
});
|
|
12454
12641
|
}
|
|
12455
12642
|
function trimHistory(h, max) {
|
|
12456
12643
|
while (h.length > max) h.shift();
|