feat: auto-extract #tags from sessions to memory/tags.md (v3.2)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-31 14:57:49 +10:00
co-authored by Claude Sonnet 4.6
parent e859f3bb48
commit cad5e54aca
+39
View File
@@ -231,6 +231,9 @@ function writeSessionLog(workspaceDir, messages, config = {}) {
const isNew = !fs.existsSync(logFile); const isNew = !fs.existsSync(logFile);
const prefix = isNew ? `# Session Log — ${dateStr}\n\n` : ""; const prefix = isNew ? `# Session Log — ${dateStr}\n\n` : "";
fs.appendFileSync(logFile, prefix + entry, "utf8"); fs.appendFileSync(logFile, prefix + entry, "utf8");
// Extract and index #tags from the topic
updateTagIndex(workspaceDir, topic, dateStr);
} }
/** /**
@@ -464,6 +467,42 @@ function generateWeeklySummary(workspaceDir, config = {}) {
fs.writeFileSync(weeklyFile, summary, "utf8"); fs.writeFileSync(weeklyFile, summary, "utf8");
} }
/**
* Extract #tags from a session topic and update the tag index.
* Tags file: memory/tags.md — simple markdown index mapping tags to dates.
*/
function updateTagIndex(workspaceDir, topic, dateStr) {
if (!topic) return;
// Extract #tags (word chars + hyphens after #)
const tags = topic.match(/#[\w-]+/g);
if (!tags || tags.length === 0) return;
const tagsFile = path.join(workspaceDir, "memory", "tags.md");
let existing = readFile(tagsFile) || "# Tag Index\n\n";
for (const tag of tags) {
const normalizedTag = tag.toLowerCase();
// Check if this tag+date combo already exists
if (existing.includes(`${normalizedTag}`) && existing.includes(dateStr)) continue;
// Find or create tag section
const tagHeader = `## ${normalizedTag}`;
if (existing.includes(tagHeader)) {
// Append date to existing tag section
existing = existing.replace(
tagHeader,
`${tagHeader}\n- ${dateStr}`
);
} else {
// Add new tag section
existing += `${tagHeader}\n- ${dateStr}\n\n`;
}
}
writeFile(tagsFile, existing);
}
function extractStateFromMessages(messages) { function extractStateFromMessages(messages) {
if (!messages || messages.length === 0) return null; if (!messages || messages.length === 0) return null;