feat: Agent 记忆系统替代预设功能,全功能协调运作

核心改造:
- 取消 Agent 预设(保留兼容),新增 AI Agent 记忆系统
- 自动提取 → 存储 → 检索 → 注入上下文的完整记忆闭环
- 记忆类型:事实/偏好/规则/事件,支持重要性评分和标签

新增文件:
- services/memory-manager.ts: 记忆管理核心
  - 关键词+标签+重要性加权检索
  - 会话结束自动提取(LLM 驱动)
  - 去重检测、使用频率追踪
- components/memory-panel.ts: 记忆管理面板 UI

修改文件:
- types.d.ts: 新增 MemoryEntry/MemorySearchResult 类型
- db/chat-db.ts: 升级 v2,新增 memories 存储
- input-area.ts: 对话流集成记忆检索+自动提取
- agent-engine.ts: Agent Loop 注入记忆上下文
- settings-modal.ts: 记忆开关设置
- main.ts: 记忆系统初始化
- index.html: 记忆设置面板 HTML
- style.css: 记忆面板完整样式

功能协调:
- 对话流: 记忆检索 → RAG 检索 → 系统提示词组合 → 流式对话
- Agent Loop: 记忆检索 → 系统提示词注入 → 工具调用循环
- 会话结束: 自动提取关键信息 → 存入记忆库
- 跨会话: 记忆持久化 IndexedDB,新对话自动召回相关记忆
This commit is contained in:
thzxx
2026-04-06 13:44:45 +08:00
parent 37e11502b8
commit dc43db7d9c
10 changed files with 1057 additions and 7 deletions
+67 -2
View File
@@ -1,15 +1,16 @@
/**
* ChatDB - IndexedDB 封装层
* v2: 新增 memories 存储(Agent 记忆系统)
*/
import type { ChatSession } from '../types.js';
import type { ChatSession, MemoryEntry } from '../types.js';
export class ChatDB {
private dbName: string;
private version: number;
private db: IDBDatabase | null = null;
constructor(dbName = 'metona-ollama', version = 1) {
constructor(dbName = 'metona-ollama', version = 2) {
this.dbName = dbName;
this.version = version;
}
@@ -36,6 +37,13 @@ export class ChatDB {
if (!db.objectStoreNames.contains('settings')) {
db.createObjectStore('settings', { keyPath: 'key' });
}
if (!db.objectStoreNames.contains('memories')) {
const memoryStore = db.createObjectStore('memories', { keyPath: 'id' });
memoryStore.createIndex('type', 'type', { unique: false });
memoryStore.createIndex('importance', 'importance', { unique: false });
memoryStore.createIndex('updatedAt', 'updatedAt', { unique: false });
memoryStore.createIndex('lastUsedAt', 'lastUsedAt', { unique: false });
}
};
});
}
@@ -151,4 +159,61 @@ export class ChatDB {
request.onerror = () => reject(request.error);
});
}
// ── Agent 记忆系统 CRUD ──
async saveMemory(entry: MemoryEntry): Promise<string> {
return new Promise((resolve, reject) => {
const store = this._tx('memories', 'readwrite');
const request = store.put(entry);
request.onsuccess = () => resolve(entry.id);
request.onerror = () => reject(request.error);
});
}
async getMemory(id: string): Promise<MemoryEntry | null> {
return new Promise((resolve, reject) => {
const store = this._tx('memories');
const request = store.get(id);
request.onsuccess = () => resolve(request.result || null);
request.onerror = () => reject(request.error);
});
}
async getAllMemories(): Promise<MemoryEntry[]> {
return new Promise((resolve, reject) => {
const store = this._tx('memories');
const request = store.getAll();
request.onsuccess = () => resolve(request.result || []);
request.onerror = () => reject(request.error);
});
}
async getMemoriesByType(type: string): Promise<MemoryEntry[]> {
return new Promise((resolve, reject) => {
const store = this._tx('memories');
const index = store.index('type');
const request = index.getAll(type);
request.onsuccess = () => resolve(request.result || []);
request.onerror = () => reject(request.error);
});
}
async deleteMemory(id: string): Promise<void> {
return new Promise((resolve, reject) => {
const store = this._tx('memories', 'readwrite');
const request = store.delete(id);
request.onsuccess = () => resolve();
request.onerror = () => reject(request.error);
});
}
async clearAllMemories(): Promise<void> {
return new Promise((resolve, reject) => {
const store = this._tx('memories', 'readwrite');
const request = store.clear();
request.onsuccess = () => resolve();
request.onerror = () => reject(request.error);
});
}
}