Add structured memory system for persistent agent context
Implements `StructuredMemoryManager` to track conversation summaries, user preferences, and learned facts across sessions. Includes: - Configurable storage limits with automatic enforcement - Heuristic extraction of preferences and facts from messages - Memory context injection into system prompts - Full test coverage for all manager operations
This commit is contained in:
+57
-5
@@ -25,6 +25,7 @@ import {
|
||||
} from './types';
|
||||
import { ConversationStateManager } from './conversation-state';
|
||||
import { ErrorHandler } from './error-handler';
|
||||
import { StructuredMemoryManager } from './structured-memory';
|
||||
|
||||
export const VIEW_TYPE_OLLAMA_CHAT = 'ollama-chat-view';
|
||||
|
||||
@@ -42,7 +43,12 @@ export class ChatView extends ItemView {
|
||||
return this.newChatButtonClickHandler;
|
||||
}
|
||||
|
||||
constructor(leaf: WorkspaceLeaf, settings: PluginSettings, vectorStore?: VaultVectorStore) {
|
||||
constructor(
|
||||
leaf: WorkspaceLeaf,
|
||||
settings: PluginSettings,
|
||||
vectorStore?: VaultVectorStore,
|
||||
structuredMemoryManager?: StructuredMemoryManager
|
||||
) {
|
||||
super(leaf);
|
||||
this.messages = [];
|
||||
this.lastMessageEl = null;
|
||||
@@ -70,6 +76,7 @@ export class ChatView extends ItemView {
|
||||
this.actionPreviewBuilder = new ActionPreviewBuilder(this.app.vault, this.app);
|
||||
this.noteContextBuilder = new NoteContextBuilder(this.app.vault, this.app, this.vaultIndexer);
|
||||
this.conversationStateManager = new ConversationStateManager();
|
||||
this.structuredMemoryManager = structuredMemoryManager;
|
||||
this.workflowEngine = new WorkflowEngine(
|
||||
this.app.vault,
|
||||
this.app,
|
||||
@@ -380,7 +387,6 @@ export class ChatView extends ItemView {
|
||||
|
||||
getTools(): OllamaTool[] {
|
||||
const allTools: OllamaTool[] = [
|
||||
|
||||
{
|
||||
type: 'function',
|
||||
function: {
|
||||
@@ -600,17 +606,30 @@ export class ChatView extends ItemView {
|
||||
|
||||
buildMessages(userMessageContent: string, tools?: OllamaTool[]): OllamaMessage[] {
|
||||
const systemContent = getSystemPromptForMode(this.currentAgentMode);
|
||||
const systemMessage: OllamaMessage = {
|
||||
const messages: OllamaMessage[] = [];
|
||||
|
||||
// Inject structured memory as a preceding system message if available
|
||||
if (this.structuredMemoryManager) {
|
||||
const memoryContext = this.structuredMemoryManager.buildMemoryContext();
|
||||
if (memoryContext) {
|
||||
messages.push({
|
||||
role: 'system',
|
||||
content: memoryContext,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
messages.push({
|
||||
role: 'system',
|
||||
content: systemContent,
|
||||
};
|
||||
});
|
||||
|
||||
const userMessage: OllamaMessage = {
|
||||
role: 'user',
|
||||
content: userMessageContent,
|
||||
};
|
||||
|
||||
const messages: OllamaMessage[] = [systemMessage, userMessage];
|
||||
messages.push(userMessage);
|
||||
|
||||
if (tools && tools.length > 0) {
|
||||
messages.push({
|
||||
@@ -1059,6 +1078,38 @@ export class ChatView extends ItemView {
|
||||
content: fullResponse,
|
||||
});
|
||||
|
||||
// Update structured memory with preferences, facts, and a conversation summary
|
||||
if (this.structuredMemoryManager) {
|
||||
const prefs = this.structuredMemoryManager.extractPreferencesFromMessage(userMessage);
|
||||
for (const pref of prefs) {
|
||||
this.structuredMemoryManager.addUserPreference(pref);
|
||||
}
|
||||
|
||||
const facts = this.structuredMemoryManager.extractFactsFromMessage(userMessage);
|
||||
for (const fact of facts) {
|
||||
this.structuredMemoryManager.addLearnedFact(fact);
|
||||
}
|
||||
|
||||
// Also extract from assistant response
|
||||
const assistantFacts = this.structuredMemoryManager.extractFactsFromMessage(fullResponse);
|
||||
for (const fact of assistantFacts) {
|
||||
this.structuredMemoryManager.addLearnedFact(fact);
|
||||
}
|
||||
|
||||
const { topic, keyPoints } = this.structuredMemoryManager.summarizeConversation(
|
||||
this.conversationStateManager.getShortTermContext()
|
||||
);
|
||||
if (keyPoints.length > 0) {
|
||||
this.structuredMemoryManager.addConversationSummary({
|
||||
id: crypto.randomUUID?.() ?? `summary-${Date.now()}-${Math.random()}`,
|
||||
timestamp: Date.now(),
|
||||
topic,
|
||||
summary: keyPoints.join('; ').slice(0, 300),
|
||||
keyPoints,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Limit conversation history to prevent memory issues
|
||||
if (this.messages.length > this.settings.maxMessageHistory) {
|
||||
this.messages = this.messages.slice(-this.settings.maxMessageHistory);
|
||||
@@ -1100,6 +1151,7 @@ export class ChatView extends ItemView {
|
||||
private noteContextBuilder: NoteContextBuilder;
|
||||
private workflowEngine: WorkflowEngine;
|
||||
private conversationStateManager: ConversationStateManager;
|
||||
private structuredMemoryManager?: StructuredMemoryManager;
|
||||
private vectorStore?: VaultVectorStore;
|
||||
|
||||
private modeSelectorEl: HTMLSelectElement | null = null;
|
||||
|
||||
Reference in New Issue
Block a user