@zhin.js/ai 0.0.2 → 1.0.1

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.
Files changed (94) hide show
  1. package/CHANGELOG.md +2 -7
  2. package/lib/agent.d.ts +54 -6
  3. package/lib/agent.d.ts.map +1 -1
  4. package/lib/agent.js +468 -116
  5. package/lib/agent.js.map +1 -1
  6. package/lib/compaction.d.ts +132 -0
  7. package/lib/compaction.d.ts.map +1 -0
  8. package/lib/compaction.js +370 -0
  9. package/lib/compaction.js.map +1 -0
  10. package/lib/context-manager.d.ts.map +1 -1
  11. package/lib/context-manager.js +10 -3
  12. package/lib/context-manager.js.map +1 -1
  13. package/lib/conversation-memory.d.ts +192 -0
  14. package/lib/conversation-memory.d.ts.map +1 -0
  15. package/lib/conversation-memory.js +619 -0
  16. package/lib/conversation-memory.js.map +1 -0
  17. package/lib/index.d.ts +25 -163
  18. package/lib/index.d.ts.map +1 -1
  19. package/lib/index.js +24 -1122
  20. package/lib/index.js.map +1 -1
  21. package/lib/output.d.ts +93 -0
  22. package/lib/output.d.ts.map +1 -0
  23. package/lib/output.js +176 -0
  24. package/lib/output.js.map +1 -0
  25. package/lib/providers/anthropic.d.ts +7 -0
  26. package/lib/providers/anthropic.d.ts.map +1 -1
  27. package/lib/providers/anthropic.js +5 -0
  28. package/lib/providers/anthropic.js.map +1 -1
  29. package/lib/providers/ollama.d.ts +10 -0
  30. package/lib/providers/ollama.d.ts.map +1 -1
  31. package/lib/providers/ollama.js +19 -4
  32. package/lib/providers/ollama.js.map +1 -1
  33. package/lib/providers/openai.d.ts +7 -0
  34. package/lib/providers/openai.d.ts.map +1 -1
  35. package/lib/providers/openai.js +11 -0
  36. package/lib/providers/openai.js.map +1 -1
  37. package/lib/rate-limiter.d.ts +38 -0
  38. package/lib/rate-limiter.d.ts.map +1 -0
  39. package/lib/rate-limiter.js +86 -0
  40. package/lib/rate-limiter.js.map +1 -0
  41. package/lib/session.d.ts +7 -0
  42. package/lib/session.d.ts.map +1 -1
  43. package/lib/session.js +47 -18
  44. package/lib/session.js.map +1 -1
  45. package/lib/storage.d.ts +68 -0
  46. package/lib/storage.d.ts.map +1 -0
  47. package/lib/storage.js +105 -0
  48. package/lib/storage.js.map +1 -0
  49. package/lib/tone-detector.d.ts +19 -0
  50. package/lib/tone-detector.d.ts.map +1 -0
  51. package/lib/tone-detector.js +72 -0
  52. package/lib/tone-detector.js.map +1 -0
  53. package/lib/types.d.ts +84 -8
  54. package/lib/types.d.ts.map +1 -1
  55. package/package.json +13 -42
  56. package/src/agent.ts +518 -135
  57. package/src/compaction.ts +529 -0
  58. package/src/context-manager.ts +10 -9
  59. package/src/conversation-memory.ts +816 -0
  60. package/src/index.ts +121 -1406
  61. package/src/output.ts +261 -0
  62. package/src/providers/anthropic.ts +4 -0
  63. package/src/providers/ollama.ts +23 -4
  64. package/src/providers/openai.ts +8 -1
  65. package/src/rate-limiter.ts +129 -0
  66. package/src/session.ts +47 -18
  67. package/src/storage.ts +135 -0
  68. package/src/tone-detector.ts +89 -0
  69. package/src/types.ts +95 -6
  70. package/tests/agent.test.ts +123 -70
  71. package/tests/compaction.test.ts +310 -0
  72. package/tests/context-manager.test.ts +73 -47
  73. package/tests/conversation-memory.test.ts +128 -0
  74. package/tests/output.test.ts +128 -0
  75. package/tests/providers.test.ts +574 -0
  76. package/tests/rate-limiter.test.ts +108 -0
  77. package/tests/session.test.ts +139 -48
  78. package/tests/setup.ts +82 -240
  79. package/tests/storage.test.ts +224 -0
  80. package/tests/tone-detector.test.ts +80 -0
  81. package/tsconfig.json +4 -5
  82. package/vitest.setup.ts +1 -0
  83. package/README.md +0 -564
  84. package/TOOLS.md +0 -294
  85. package/lib/tools.d.ts +0 -45
  86. package/lib/tools.d.ts.map +0 -1
  87. package/lib/tools.js +0 -194
  88. package/lib/tools.js.map +0 -1
  89. package/src/tools.ts +0 -205
  90. package/tests/ai-trigger.test.ts +0 -369
  91. package/tests/integration.test.ts +0 -596
  92. package/tests/providers.integration.test.ts +0 -227
  93. package/tests/tool.test.ts +0 -800
  94. package/tests/tools-builtin.test.ts +0 -346
@@ -0,0 +1,619 @@
1
+ /**
2
+ * ConversationMemory — 基于数据库的会话记忆(话题感知 + 链式摘要)
3
+ *
4
+ * 两张表分离存储:
5
+ *
6
+ * ai_messages 表(逐条记录):
7
+ * ┌──────────────────────────────────────────────────────────┐
8
+ * │ session_id | role | content | round | time │
9
+ * │ s1 | user | 你好 | 1 | ... │
10
+ * │ s1 | assistant | 你好呀! | 1 | ... │
11
+ * │ ... | ... | ... | ... | ... │
12
+ * └──────────────────────────────────────────────────────────┘
13
+ *
14
+ * ai_summaries 表(链式摘要):
15
+ * ┌────────────────────────────────────────────────────────────────────┐
16
+ * │ id | session_id | parent_id | from_round | to_round | summary │
17
+ * │ 1 | s1 | null | 1 | 7 | 用户讨论了… │
18
+ * │ 2 | s1 | 1 | 8 | 15 | 之前...又… │
19
+ * └────────────────────────────────────────────────────────────────────┘
20
+ *
21
+ * 摘要触发规则:
22
+ * 1. 检测到话题切换(当前消息与最近消息的关键词重合度低)
23
+ * 2. 且上一个话题持续 ≥ minTopicRounds 轮
24
+ * → 异步生成摘要,覆盖上一话题的全部消息
25
+ *
26
+ * 上下文构建规则:
27
+ * 1. 取最新 summary + 最近 slidingWindowSize 轮消息(滑动窗口)
28
+ * 2. 检查连续性:summary.to_round === window第一条round - 1
29
+ * → 连续:[summary] + [window]
30
+ * → 不连续:丢弃 summary,仅用 [window]
31
+ */
32
+ import { Logger } from '@zhin.js/logger';
33
+ const logger = new Logger(null, 'ConvMemory');
34
+ // ============================================================================
35
+ // 数据库模型定义
36
+ // ============================================================================
37
+ /** ai_messages 表结构 */
38
+ export const AI_MESSAGE_MODEL = {
39
+ session_id: { type: 'text', nullable: false },
40
+ role: { type: 'text', nullable: false },
41
+ content: { type: 'text', nullable: false },
42
+ round: { type: 'integer', nullable: false },
43
+ created_at: { type: 'integer', default: 0 },
44
+ };
45
+ /** ai_summaries 表结构(链式) */
46
+ export const AI_SUMMARY_MODEL = {
47
+ session_id: { type: 'text', nullable: false },
48
+ parent_id: { type: 'integer', nullable: true },
49
+ from_round: { type: 'integer', nullable: false },
50
+ to_round: { type: 'integer', nullable: false },
51
+ summary: { type: 'text', nullable: false },
52
+ created_at: { type: 'integer', default: 0 },
53
+ };
54
+ const DEFAULT_CONFIG = {
55
+ minTopicRounds: 5,
56
+ slidingWindowSize: 5,
57
+ topicChangeThreshold: 0.15,
58
+ };
59
+ // ============================================================================
60
+ // 内存实现
61
+ // ============================================================================
62
+ class MemoryStore {
63
+ messages = new Map();
64
+ summaries = new Map();
65
+ nextSummaryId = 1;
66
+ async getMessages(sessionId) {
67
+ return this.messages.get(sessionId) || [];
68
+ }
69
+ async addMessage(record) {
70
+ const list = this.messages.get(record.session_id) || [];
71
+ list.push(record);
72
+ this.messages.set(record.session_id, list);
73
+ }
74
+ async getMaxRound(sessionId) {
75
+ const msgs = this.messages.get(sessionId) || [];
76
+ if (msgs.length === 0)
77
+ return 0;
78
+ return Math.max(...msgs.map(m => m.round));
79
+ }
80
+ async getMessagesAfterRound(sessionId, afterRound) {
81
+ const msgs = this.messages.get(sessionId) || [];
82
+ return msgs.filter(m => m.round > afterRound);
83
+ }
84
+ async getMessagesByRoundRange(sessionId, fromRound, toRound) {
85
+ const msgs = this.messages.get(sessionId) || [];
86
+ return msgs.filter(m => m.round >= fromRound && m.round <= toRound);
87
+ }
88
+ async searchMessages(sessionId, keyword) {
89
+ const msgs = this.messages.get(sessionId) || [];
90
+ const kw = keyword.toLowerCase();
91
+ return msgs.filter(m => m.content.toLowerCase().includes(kw));
92
+ }
93
+ async getLatestSummary(sessionId) {
94
+ const list = this.summaries.get(sessionId) || [];
95
+ if (list.length === 0)
96
+ return null;
97
+ return list.reduce((a, b) => a.to_round > b.to_round ? a : b);
98
+ }
99
+ async getSummaryById(sessionId, summaryId) {
100
+ const list = this.summaries.get(sessionId) || [];
101
+ return list.find(s => s.id === summaryId) ?? null;
102
+ }
103
+ async addSummary(record) {
104
+ const full = { ...record, id: this.nextSummaryId++ };
105
+ const list = this.summaries.get(record.session_id) || [];
106
+ list.push(full);
107
+ this.summaries.set(record.session_id, list);
108
+ return full;
109
+ }
110
+ dispose() {
111
+ this.messages.clear();
112
+ this.summaries.clear();
113
+ }
114
+ }
115
+ // ============================================================================
116
+ // 数据库实现
117
+ // ============================================================================
118
+ class DatabaseStore {
119
+ msgModel;
120
+ sumModel;
121
+ constructor(msgModel, sumModel) {
122
+ this.msgModel = msgModel;
123
+ this.sumModel = sumModel;
124
+ }
125
+ async getMessages(sessionId) {
126
+ return (await this.msgModel.select().where({ session_id: sessionId }));
127
+ }
128
+ async addMessage(record) {
129
+ await this.msgModel.create(record);
130
+ }
131
+ async getMaxRound(sessionId) {
132
+ const msgs = await this.getMessages(sessionId);
133
+ if (msgs.length === 0)
134
+ return 0;
135
+ return Math.max(...msgs.map(m => m.round));
136
+ }
137
+ async getMessagesAfterRound(sessionId, afterRound) {
138
+ const msgs = await this.getMessages(sessionId);
139
+ return msgs.filter(m => m.round > afterRound);
140
+ }
141
+ async getMessagesByRoundRange(sessionId, fromRound, toRound) {
142
+ const msgs = await this.getMessages(sessionId);
143
+ return msgs.filter(m => m.round >= fromRound && m.round <= toRound);
144
+ }
145
+ async searchMessages(sessionId, keyword) {
146
+ const msgs = await this.getMessages(sessionId);
147
+ const kw = keyword.toLowerCase();
148
+ return msgs.filter(m => m.content.toLowerCase().includes(kw));
149
+ }
150
+ async getLatestSummary(sessionId) {
151
+ const records = (await this.sumModel.select().where({ session_id: sessionId }));
152
+ if (records.length === 0)
153
+ return null;
154
+ return records.reduce((a, b) => a.to_round > b.to_round ? a : b);
155
+ }
156
+ async getSummaryById(sessionId, summaryId) {
157
+ const records = (await this.sumModel.select().where({ session_id: sessionId }));
158
+ return records.find(s => s.id === summaryId) ?? null;
159
+ }
160
+ async addSummary(record) {
161
+ const created = await this.sumModel.create(record);
162
+ return { ...record, id: created?.id ?? created?.lastID ?? 0 };
163
+ }
164
+ dispose() { }
165
+ }
166
+ // ============================================================================
167
+ // 话题检测工具
168
+ // ============================================================================
169
+ /**
170
+ * 提取文本中的关键词集合(中文按字/词,英文按空格分词)
171
+ *
172
+ * 简单但高效:不依赖分词库,用字符 bigram + 英文单词作为特征
173
+ */
174
+ function extractTokens(text) {
175
+ const tokens = new Set();
176
+ const cleaned = text.toLowerCase().replace(/[^\u4e00-\u9fff\w]/g, ' ');
177
+ // 中文字符 bigram
178
+ const chars = cleaned.replace(/[^\u4e00-\u9fff]/g, '');
179
+ for (let i = 0; i < chars.length - 1; i++) {
180
+ tokens.add(chars.slice(i, i + 2));
181
+ }
182
+ // 单个中文字也加入(短消息可能只有单字关键词)
183
+ for (const ch of chars) {
184
+ tokens.add(ch);
185
+ }
186
+ // 英文单词(≥2字符)
187
+ const words = cleaned.match(/[a-z]{2,}/g);
188
+ if (words) {
189
+ for (const w of words)
190
+ tokens.add(w);
191
+ }
192
+ return tokens;
193
+ }
194
+ /**
195
+ * 计算两个 token 集合的 Jaccard 相似度
196
+ */
197
+ function jaccardSimilarity(a, b) {
198
+ if (a.size === 0 && b.size === 0)
199
+ return 1;
200
+ if (a.size === 0 || b.size === 0)
201
+ return 0;
202
+ let intersection = 0;
203
+ for (const token of a) {
204
+ if (b.has(token))
205
+ intersection++;
206
+ }
207
+ const union = a.size + b.size - intersection;
208
+ return union === 0 ? 0 : intersection / union;
209
+ }
210
+ export class ConversationMemory {
211
+ store;
212
+ provider = null;
213
+ config;
214
+ summarizing = new Set();
215
+ /** per-session 话题跟踪 */
216
+ topicStates = new Map();
217
+ /** per-session 轮次缓存(避免每次查数据库) */
218
+ roundCache = new Map();
219
+ /** 各 session 最后活跃时间(用于淘汰) */
220
+ lastAccess = new Map();
221
+ /** 内存缓存上限:超过此数量时淘汰过期条目 */
222
+ static MAX_TRACKED_SESSIONS = 5000;
223
+ /** 缓存过期时间:24 小时未访问即淘汰 */
224
+ static SESSION_CACHE_TTL = 24 * 60 * 60 * 1000;
225
+ constructor(config) {
226
+ this.store = new MemoryStore();
227
+ this.config = { ...DEFAULT_CONFIG, ...config };
228
+ }
229
+ // ── 依赖注入 ──
230
+ setProvider(provider) {
231
+ this.provider = provider;
232
+ }
233
+ upgradeToDatabase(msgModel, sumModel) {
234
+ const old = this.store;
235
+ this.store = new DatabaseStore(msgModel, sumModel);
236
+ old.dispose();
237
+ logger.debug('ConversationMemory: upgraded to database storage');
238
+ }
239
+ // ── 写入 ──
240
+ /**
241
+ * 保存一轮对话,并检测话题切换来触发摘要
242
+ */
243
+ async saveRound(sessionId, userContent, assistantContent) {
244
+ this.lastAccess.set(sessionId, Date.now());
245
+ this.pruneStaleSessionCaches();
246
+ // 优先用缓存,首次才查数据库
247
+ const cached = this.roundCache.get(sessionId);
248
+ let currentRound = cached != null ? cached + 1 : (await this.store.getMaxRound(sessionId)) + 1;
249
+ // 防御性检查:确保 round 始终是有效正整数
250
+ if (!Number.isFinite(currentRound) || currentRound < 1) {
251
+ logger.warn(`[saveRound] round 异常 (${currentRound}), 重置为 1`);
252
+ currentRound = 1;
253
+ }
254
+ this.roundCache.set(sessionId, currentRound);
255
+ const ts = Date.now();
256
+ await this.store.addMessage({
257
+ session_id: sessionId,
258
+ role: 'user',
259
+ content: userContent,
260
+ round: currentRound,
261
+ created_at: ts,
262
+ });
263
+ await this.store.addMessage({
264
+ session_id: sessionId,
265
+ role: 'assistant',
266
+ content: assistantContent,
267
+ round: currentRound,
268
+ created_at: ts,
269
+ });
270
+ // 话题切换检测 + 异步摘要
271
+ this.handleTopicAndSummary(sessionId, userContent, currentRound);
272
+ }
273
+ // ── 话题检测 + 摘要触发 ──
274
+ /**
275
+ * 话题检测流程(全程异步,不阻塞对话):
276
+ *
277
+ * 1. 短消息(token ≤ 3)→ 跳过检测,视为延续话题
278
+ * 2. Jaccard 快检 → 高相似(≥ 0.5) → 肯定同话题,跳过 LLM
279
+ * 3. Jaccard 不确定(< 0.5) → 调 LLM 裁决
280
+ * 4. LLM 判定切换 + 旧话题 ≥ minTopicRounds → 触发摘要
281
+ */
282
+ handleTopicAndSummary(sessionId, userContent, currentRound) {
283
+ let state = this.topicStates.get(sessionId);
284
+ // 首次对话 → 初始化
285
+ if (!state) {
286
+ state = {
287
+ topicStartRound: currentRound,
288
+ recentTokens: extractTokens(userContent),
289
+ recentUserMessages: [userContent],
290
+ };
291
+ this.topicStates.set(sessionId, state);
292
+ return;
293
+ }
294
+ const currentTokens = extractTokens(userContent);
295
+ // 短消息跳过检测
296
+ if (currentTokens.size <= 3) {
297
+ for (const t of currentTokens)
298
+ state.recentTokens.add(t);
299
+ state.recentUserMessages.push(userContent);
300
+ if (state.recentUserMessages.length > 3)
301
+ state.recentUserMessages.shift();
302
+ return;
303
+ }
304
+ // Jaccard 快检
305
+ const similarity = jaccardSimilarity(currentTokens, state.recentTokens);
306
+ if (similarity >= 0.5) {
307
+ // 高相似 → 肯定同话题,无需 LLM
308
+ this.updateTopicState(state, currentTokens, userContent);
309
+ return;
310
+ }
311
+ // 不确定 → 异步调 LLM 裁决
312
+ logger.debug(`[话题检测] Jaccard=${similarity.toFixed(2)} < 0.5, 交由 LLM 判断`);
313
+ const recentMsgs = [...state.recentUserMessages];
314
+ const topicStart = state.topicStartRound;
315
+ // 先乐观更新(假设同话题),LLM 判定后可能回滚
316
+ this.updateTopicState(state, currentTokens, userContent);
317
+ // 异步 LLM 判断
318
+ this.detectTopicChangeByLLM(recentMsgs, userContent).then((isChange) => {
319
+ if (!isChange) {
320
+ logger.debug(`[话题检测] LLM 判定: 同话题`);
321
+ return;
322
+ }
323
+ // LLM 确认话题切换
324
+ const topicDuration = currentRound - topicStart;
325
+ logger.debug(`[话题检测] LLM 判定: 切换! ` +
326
+ `旧话题: 第${topicStart}-${currentRound - 1}轮 (${topicDuration}轮)`);
327
+ // 回滚话题状态 → 重置为新话题
328
+ const currentState = this.topicStates.get(sessionId);
329
+ if (currentState) {
330
+ currentState.topicStartRound = currentRound;
331
+ currentState.recentTokens = currentTokens;
332
+ currentState.recentUserMessages = [userContent];
333
+ }
334
+ // 旧话题够长 → 生成摘要
335
+ if (topicDuration >= this.config.minTopicRounds) {
336
+ this.generateSummaryAsync(sessionId, topicStart, currentRound - 1);
337
+ }
338
+ }).catch((err) => {
339
+ logger.warn('[话题检测] LLM 调用失败,保持当前话题', err);
340
+ });
341
+ }
342
+ /** 更新话题状态(同话题情况) */
343
+ updateTopicState(state, tokens, message) {
344
+ for (const t of tokens)
345
+ state.recentTokens.add(t);
346
+ if (state.recentTokens.size > 500)
347
+ state.recentTokens = tokens;
348
+ state.recentUserMessages.push(message);
349
+ if (state.recentUserMessages.length > 3)
350
+ state.recentUserMessages.shift();
351
+ }
352
+ /**
353
+ * 调用 LLM 判断话题是否切换
354
+ *
355
+ * 输入: 最近几条用户消息 + 当前用户消息
356
+ * 输出: true = 话题切换, false = 同话题
357
+ */
358
+ async detectTopicChangeByLLM(recentMessages, currentMessage) {
359
+ if (!this.provider)
360
+ return false;
361
+ const recentText = recentMessages.map((m, i) => `${i + 1}. ${m}`).join('\n');
362
+ const model = this.provider.models[0];
363
+ const response = await this.provider.chat({
364
+ model,
365
+ messages: [
366
+ {
367
+ role: 'system',
368
+ content: '你是一个话题分析助手。判断用户最新发送的消息相比之前的消息,是否切换到了一个全新的话题。只回答一个字:是 或 否。',
369
+ },
370
+ {
371
+ role: 'user',
372
+ content: `之前的消息:\n${recentText}\n\n最新消息:\n${currentMessage}`,
373
+ },
374
+ ],
375
+ temperature: 0.1,
376
+ });
377
+ const raw = response.choices[0]?.message?.content;
378
+ const content = (typeof raw === 'string' ? raw : '').trim();
379
+ // 解析回答:包含"是"→ 切换,包含"否"或其他 → 未切换
380
+ return content.includes('是') && !content.includes('否');
381
+ }
382
+ /**
383
+ * 异步生成链式摘要(不阻塞对话)
384
+ */
385
+ generateSummaryAsync(sessionId, fromRound, toRound) {
386
+ if (!this.provider)
387
+ return;
388
+ if (this.summarizing.has(sessionId))
389
+ return;
390
+ this.summarizing.add(sessionId);
391
+ this.store.getLatestSummary(sessionId).then(async (parentSummary) => {
392
+ try {
393
+ const messages = await this.store.getMessagesByRoundRange(sessionId, fromRound, toRound);
394
+ if (messages.length === 0) {
395
+ this.summarizing.delete(sessionId);
396
+ return;
397
+ }
398
+ logger.debug(`[摘要] 开始: session=${sessionId}, 轮次 ${fromRound}-${toRound}, ` +
399
+ `parent=${parentSummary?.id ?? 'null'}, ${messages.length}条消息`);
400
+ const summaryText = await this.callLLMSummarize(parentSummary?.summary ?? null, messages);
401
+ // 质量兜底:字数异常的摘要丢弃
402
+ if (summaryText && summaryText.length >= 20 && summaryText.length <= 1000) {
403
+ const created = await this.store.addSummary({
404
+ session_id: sessionId,
405
+ parent_id: parentSummary?.id ?? null,
406
+ from_round: fromRound,
407
+ to_round: toRound,
408
+ summary: summaryText,
409
+ created_at: Date.now(),
410
+ });
411
+ logger.info(`[摘要] 完成: id=${created.id}, session=${sessionId}, ` +
412
+ `轮次 ${fromRound}-${toRound}, parent=${parentSummary?.id ?? 'null'}, ` +
413
+ `${summaryText.length}字`);
414
+ }
415
+ else {
416
+ logger.warn(`[摘要] 质量异常,丢弃: session=${sessionId}, ` +
417
+ `长度=${summaryText?.length ?? 0}`);
418
+ }
419
+ }
420
+ catch (err) {
421
+ logger.warn(`[摘要] 失败: session=${sessionId}`, err);
422
+ }
423
+ finally {
424
+ this.summarizing.delete(sessionId);
425
+ }
426
+ });
427
+ }
428
+ // ── 读取(构建上下文) ──
429
+ /**
430
+ * 构建 LLM 上下文消息列表
431
+ *
432
+ * 规则:
433
+ * 1. 取滑动窗口(最近 slidingWindowSize 轮)
434
+ * 2. 取最新 summary
435
+ * 3. 检查连续性:summary.to_round === window第一轮 - 1
436
+ * → 连续:[summary] + [window 消息]
437
+ * → 不连续:仅 [window 消息]
438
+ */
439
+ async buildContext(sessionId) {
440
+ const currentRound = this.roundCache.get(sessionId) ?? await this.store.getMaxRound(sessionId);
441
+ if (currentRound === 0)
442
+ return [];
443
+ // 1. 滑动窗口
444
+ const windowStart = Math.max(1, currentRound - this.config.slidingWindowSize + 1);
445
+ const windowMessages = await this.store.getMessagesByRoundRange(sessionId, windowStart, currentRound);
446
+ windowMessages.sort((a, b) => a.round - b.round || a.created_at - b.created_at);
447
+ if (windowMessages.length === 0)
448
+ return [];
449
+ const firstWindowRound = windowMessages[0].round;
450
+ // 2. 取最新 summary
451
+ const latest = await this.store.getLatestSummary(sessionId);
452
+ const result = [];
453
+ // 3. 连续性校验
454
+ // 连续: summary.to_round >= firstWindowRound - 1
455
+ // → 紧挨(to_round === first-1)或重叠(to_round >= first)都算连续
456
+ // 不连续: summary.to_round < firstWindowRound - 1
457
+ // → 中间有间隔,summary 与当前话题无关,丢弃
458
+ if (latest && latest.to_round >= firstWindowRound - 1) {
459
+ result.push({
460
+ role: 'system',
461
+ content: `[对话记忆] 之前的对话摘要(覆盖第${latest.from_round}-${latest.to_round}轮):\n${latest.summary}`,
462
+ });
463
+ // 重叠时去重:只注入 summary 未覆盖的窗口消息
464
+ const dedupStart = latest.to_round + 1;
465
+ const dedupMessages = windowMessages.filter(m => m.round >= dedupStart);
466
+ for (const msg of dedupMessages) {
467
+ result.push({ role: msg.role, content: msg.content });
468
+ }
469
+ logger.debug(`[上下文] summary(${latest.from_round}-${latest.to_round}) + ` +
470
+ `window(${dedupStart}-${currentRound}), 去重后${dedupMessages.length}条`);
471
+ }
472
+ else {
473
+ if (latest) {
474
+ logger.debug(`[上下文] summary 不连续 (to_round=${latest.to_round}, window_start=${firstWindowRound}), 仅用窗口`);
475
+ }
476
+ // 无 summary 或不连续 → 仅窗口
477
+ for (const msg of windowMessages) {
478
+ result.push({ role: msg.role, content: msg.content });
479
+ }
480
+ }
481
+ return result;
482
+ }
483
+ // ── LLM 摘要 ──
484
+ async callLLMSummarize(parentSummary, messages) {
485
+ if (!this.provider || messages.length === 0)
486
+ return null;
487
+ const transcript = messages
488
+ .sort((a, b) => a.round - b.round || a.created_at - b.created_at)
489
+ .map(m => {
490
+ const role = m.role === 'user' ? '用户' : '助手';
491
+ return `${role}: ${m.content}`;
492
+ })
493
+ .join('\n');
494
+ const maxChars = 3000;
495
+ const trimmedTranscript = transcript.length > maxChars
496
+ ? '...\n' + transcript.slice(-maxChars)
497
+ : transcript;
498
+ let userContent;
499
+ if (parentSummary) {
500
+ userContent =
501
+ `## 之前的对话摘要\n${parentSummary}\n\n` +
502
+ `## 最近的对话记录\n${trimmedTranscript}`;
503
+ }
504
+ else {
505
+ userContent = trimmedTranscript;
506
+ }
507
+ const model = this.provider.models[0];
508
+ const response = await this.provider.chat({
509
+ model,
510
+ messages: [
511
+ {
512
+ role: 'system',
513
+ content: parentSummary
514
+ ? '你是一个对话摘要助手。请将「之前的摘要」和「最近的对话记录」合并为一段新的综合摘要(150-300字)。保留关键信息、用户偏好和重要结论,让新摘要完整覆盖所有历史。只输出摘要内容,不要添加任何前缀。'
515
+ : '你是一个对话摘要助手。请将以下对话压缩为一段简洁的中文摘要(100-200字),保留关键信息、用户偏好和重要结论。只输出摘要内容,不要添加任何前缀。',
516
+ },
517
+ { role: 'user', content: userContent },
518
+ ],
519
+ temperature: 0.3,
520
+ });
521
+ const content = response.choices[0]?.message?.content;
522
+ return typeof content === 'string' ? content.trim() : null;
523
+ }
524
+ // ── 查询 API(供 AI 工具调用) ──
525
+ async searchMessages(sessionId, keyword, limit = 20) {
526
+ const results = await this.store.searchMessages(sessionId, keyword);
527
+ return results
528
+ .sort((a, b) => b.round - a.round || b.created_at - a.created_at)
529
+ .slice(0, limit)
530
+ .map(m => ({ round: m.round, role: m.role, content: m.content, time: m.created_at }));
531
+ }
532
+ async getMessagesByRound(sessionId, fromRound, toRound) {
533
+ const results = await this.store.getMessagesByRoundRange(sessionId, fromRound, toRound);
534
+ return results
535
+ .sort((a, b) => a.round - b.round || a.created_at - b.created_at)
536
+ .map(m => ({ round: m.round, role: m.role, content: m.content, time: m.created_at }));
537
+ }
538
+ async getCurrentRound(sessionId) {
539
+ return this.roundCache.get(sessionId) ?? this.store.getMaxRound(sessionId);
540
+ }
541
+ async traceByKeyword(sessionId, keyword, limit = 30) {
542
+ const kw = keyword.toLowerCase();
543
+ let current = await this.store.getLatestSummary(sessionId);
544
+ let matchedSummary = null;
545
+ while (current) {
546
+ if (current.summary.toLowerCase().includes(kw)) {
547
+ matchedSummary = current;
548
+ break;
549
+ }
550
+ if (current.parent_id != null) {
551
+ current = await this.store.getSummaryById(sessionId, current.parent_id);
552
+ }
553
+ else {
554
+ break;
555
+ }
556
+ }
557
+ if (matchedSummary) {
558
+ const messages = await this.store.getMessagesByRoundRange(sessionId, matchedSummary.from_round, matchedSummary.to_round);
559
+ return {
560
+ summary: {
561
+ id: matchedSummary.id,
562
+ fromRound: matchedSummary.from_round,
563
+ toRound: matchedSummary.to_round,
564
+ summary: matchedSummary.summary,
565
+ },
566
+ messages: messages
567
+ .sort((a, b) => a.round - b.round || a.created_at - b.created_at)
568
+ .slice(0, limit)
569
+ .map(m => ({ round: m.round, role: m.role, content: m.content, time: m.created_at })),
570
+ };
571
+ }
572
+ const directResults = await this.store.searchMessages(sessionId, keyword);
573
+ return {
574
+ summary: null,
575
+ messages: directResults
576
+ .sort((a, b) => b.round - a.round)
577
+ .slice(0, limit)
578
+ .map(m => ({ round: m.round, role: m.role, content: m.content, time: m.created_at })),
579
+ };
580
+ }
581
+ // ── 生命周期 ──
582
+ /**
583
+ * 淘汰长时间未访问的 session 缓存,防止 topicStates/roundCache 无限增长。
584
+ * 触发条件:Map size 超过 MAX_TRACKED_SESSIONS。
585
+ */
586
+ pruneStaleSessionCaches() {
587
+ if (this.lastAccess.size <= ConversationMemory.MAX_TRACKED_SESSIONS)
588
+ return;
589
+ const now = Date.now();
590
+ const ttl = ConversationMemory.SESSION_CACHE_TTL;
591
+ for (const [sid, ts] of this.lastAccess) {
592
+ if (now - ts > ttl) {
593
+ this.topicStates.delete(sid);
594
+ this.roundCache.delete(sid);
595
+ this.lastAccess.delete(sid);
596
+ this.summarizing.delete(sid);
597
+ }
598
+ }
599
+ // 如果 TTL 淘汰后仍超限,按 LRU 删除最旧的
600
+ if (this.lastAccess.size > ConversationMemory.MAX_TRACKED_SESSIONS) {
601
+ const entries = [...this.lastAccess.entries()].sort((a, b) => a[1] - b[1]);
602
+ const toRemove = entries.slice(0, entries.length - ConversationMemory.MAX_TRACKED_SESSIONS);
603
+ for (const [sid] of toRemove) {
604
+ this.topicStates.delete(sid);
605
+ this.roundCache.delete(sid);
606
+ this.lastAccess.delete(sid);
607
+ this.summarizing.delete(sid);
608
+ }
609
+ }
610
+ }
611
+ dispose() {
612
+ this.store.dispose();
613
+ this.summarizing.clear();
614
+ this.topicStates.clear();
615
+ this.roundCache.clear();
616
+ this.lastAccess.clear();
617
+ }
618
+ }
619
+ //# sourceMappingURL=conversation-memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-memory.js","sourceRoot":"","sources":["../src/conversation-memory.ts"],"names":[],"mappings":"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"}