Add daily journal system (Milestone 5)

- Add journal service with date-based organization
- Add quick capture with timestamps and tags
- Add auto-linking for mentioned nodes and hashtags
- Add AI-powered daily summary generation
- Add journal search across all entries
- Add CLI commands: journal, j (alias), c (quick capture)
- Add MCP tools: memory_journal, memory_journal_list, memory_journal_summarize
This commit is contained in:
2026-02-03 10:57:23 +01:00
parent 056a02d936
commit 67b1e3b481
4 changed files with 446 additions and 0 deletions

View File

@@ -590,6 +590,66 @@ server.tool(
}
);
// --- memory_journal ---
import { getOrCreateJournal, appendToJournal, listJournals, generateJournalSummary, JournalMetadata } from '../core/journal';
server.tool(
'memory_journal',
'Get or create today\'s journal, or add an entry to it',
{
text: z.string().optional().describe('Text to add to journal (if omitted, returns current journal)'),
date: z.string().optional().describe('Specific date (YYYY-MM-DD)'),
tags: z.array(z.string()).optional().describe('Tags for the entry'),
},
async ({ text, date, tags }) => {
if (text) {
const { journal, entry } = await appendToJournal(text, { tags, date });
const meta = journal.metadata as JournalMetadata;
return { content: [{ type: 'text' as const, text: serialize({ added: true, date: meta.date, entry }) }] };
}
const journal = await getOrCreateJournal(date);
return { content: [{ type: 'text' as const, text: serialize(journal) }] };
}
);
server.tool(
'memory_journal_list',
'List recent journals',
{
limit: z.number().optional().describe('Max journals to return (default: 10)'),
month: z.string().optional().describe('Filter by month (YYYY-MM)'),
},
async ({ limit, month }) => {
const journals = listJournals({ limit: limit || 10, month });
return {
content: [{
type: 'text' as const,
text: serialize(journals.map(j => {
const meta = j.metadata as JournalMetadata;
return {
id: j.id,
date: meta.date,
entries: meta.entries?.length || 0,
hasSummary: !!meta.summary,
};
})),
}],
};
}
);
server.tool(
'memory_journal_summarize',
'Generate AI summary for a journal',
{
date: z.string().optional().describe('Date to summarize (default: today)'),
},
async ({ date }) => {
const summary = await generateJournalSummary(date);
return { content: [{ type: 'text' as const, text: serialize({ summary }) }] };
}
);
// --- memory_index ---
import { indexProject } from '../core/indexer';