Skip to content

Commit 41da783

Browse files
committed
feat: add persistent memory system for cross-session context
- Add data/memory.md for storing user profile, projects, and preferences - Create src/utils/memory.js with load/save/update helpers - Inject memory into system prompt on every session - Update bot instructions to maintain memory when user shares info - Gitignore data/ to protect personal data from cloud exposure
1 parent ec77ca7 commit 41da783

3 files changed

Lines changed: 48 additions & 2 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ opencode-data/
88
plans/
99
scratch/
1010
resources/
11+
data/

src/handlers/messageHandler.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { isValidMessage, splitMessage, cleanMarkdownForTelegram } from '../utils
55
import { getVerifierModel } from '../config/models.js';
66
import { logger } from '../services/logger.js';
77
import { hasPendingFreeformQuestion, submitTuiResponse } from '../services/tuiControl.js';
8+
import { loadMemory } from '../utils/memory.js';
89

910
export const DEFAULT_SYSTEM_PROMPT = `You are "El Coleto", a high-energy, vibrant, and brazenly honest personal assistant from the Colombian Caribbean coast. 🇨🇴🥥
1011
Your voice is informal but sharp, energetic, and completely "sin vergüenza" (shameless) when it comes to the truth.
@@ -42,6 +43,7 @@ Your primary goal is to be a **Direct Strategic Partner**. You don't just agree;
4243
5. **Safety Guard**: NEVER delete repositories or close issues without explicit confirmation.
4344
6. **File System**: "rm" is blocked. Use it to organize the project responsibly.
4445
7. **Accuracy**: If writing code, provide complete, working examples.
46+
8. **Memory**: When the user shares personal info, preferences, or context worth remembering, update \`data/memory.md\` using bash tools to persist it. Keep it light.
4547
4648
### 📚 Bot Command Dictionary
4749
- \`/precision\`: Toggles "Deep Verification Mode" (Double Check).
@@ -67,6 +69,9 @@ export async function handleMessage(ctx) {
6769
const chatId = ctx.chat.id;
6870
const userMessage = ctx.message.text;
6971

72+
const memory = loadMemory();
73+
const memoryContext = memory ? `\n\n## 📝 PERSISTENT MEMORY\nThe following is stored memory from previous sessions:\n${memory}\n\nUse this memory to maintain context across conversations. Update it when the user shares new information about themselves, their preferences, projects, or anything worth remembering long-term.` : '';
74+
7075
// Validate input
7176
if (!isValidMessage(userMessage)) return;
7277

@@ -139,8 +144,8 @@ export async function handleMessage(ctx) {
139144
}
140145

141146
const currentSystemPrompt = sessionData.developerMode
142-
? `${ DEFAULT_SYSTEM_PROMPT } \n\n⚠️ ** DEVELOPER MODE ACTIVE **: You have explicit permission to modify source code in \`src/\`. Use bash and file_edit tools responsibly.`
143-
: `${DEFAULT_SYSTEM_PROMPT}\n\n🔒 **DEVELOPER MODE DISABLED**: You are FORBIDDEN from modifying files in \`src/\`. If requested, explain that /dev mode must be enabled. You CAN still edit \`todos.md\`, \`output/\`, and \`notes/\`.`;
147+
? `${ DEFAULT_SYSTEM_PROMPT }${memoryContext} \n\n⚠️ ** DEVELOPER MODE ACTIVE **: You have explicit permission to modify source code in \`src/\`. Use bash and file_edit tools responsibly.`
148+
: `${DEFAULT_SYSTEM_PROMPT}${memoryContext}\n\n🔒 **DEVELOPER MODE DISABLED**: You are FORBIDDEN from modifying files in \`src/\`. If requested, explain that /dev mode must be enabled. You CAN still edit \`todos.md\`, \`output/\`, and \`notes/\`.`;
144149

145150
const promptBody = {
146151
parts: [{ type: 'text', text: userMessage }],

src/utils/memory.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { readFileSync, writeFileSync, existsSync } from 'fs';
2+
import { join } from 'path';
3+
import { fileURLToPath } from 'url';
4+
5+
const __dirname = fileURLToPath(new URL('.', import.meta.url));
6+
const MEMORY_PATH = join(__dirname, '../../data/memory.md');
7+
8+
export function loadMemory() {
9+
if (!existsSync(MEMORY_PATH)) return null;
10+
try {
11+
return readFileSync(MEMORY_PATH, 'utf-8');
12+
} catch {
13+
return null;
14+
}
15+
}
16+
17+
export function saveMemory(content) {
18+
try {
19+
writeFileSync(MEMORY_PATH, content, 'utf-8');
20+
return true;
21+
} catch {
22+
return false;
23+
}
24+
}
25+
26+
export function updateMemoryField(field, value) {
27+
let content = loadMemory() || '# Memory\n\n## Last Updated\n\n## User Profile\n\n## Current Projects\n\n## Recent Context\n\n## Preferences\n\n## Notes';
28+
29+
const date = new Date().toISOString().split('T')[0];
30+
content = content.replace(/## Last Updated[\s\S]*?(?=##|$)/, `## Last Updated\n${date}\n`);
31+
32+
const fieldPattern = new RegExp(`(## ${field}[\\s\\S]*?)(?=##|$)`, 'i');
33+
const fieldMatch = content.match(fieldPattern);
34+
35+
if (fieldMatch) {
36+
content = content.replace(fieldPattern, `$1${value}\n`);
37+
}
38+
39+
return saveMemory(content);
40+
}

0 commit comments

Comments
 (0)