feat: add /mc tags and /mc summary commands (v3.2)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-31 15:00:31 +10:00
co-authored by Claude Sonnet 4.6
parent 9c21baf461
commit 54c7ba65e7
+86
View File
@@ -526,12 +526,96 @@ function cmdSessions(args) {
return out.trimEnd(); return out.trimEnd();
} }
function cmdTags(args) {
const agent = args || "main";
const memDir = resolveMemDir(agent);
if (!memDir) return `Agent "${agent}" not found.`;
const tagsFile = path.join(memDir, "tags.md");
const content = readFile(tagsFile);
if (!content) return `No tags for "${agent}".`;
// Parse tags and their date counts
const tagSections = content.split(/^## /gm).filter(s => s.trim());
if (tagSections.length === 0) return `No tags for "${agent}".`;
let out = `Tags: ${agent} (${tagSections.length} tags)\n`;
out += "─────────────────────────────\n";
const tags = [];
for (const section of tagSections) {
const lines = section.trim().split("\n");
const tag = lines[0].trim();
if (!tag.startsWith("#")) continue;
const dates = lines.filter(l => l.startsWith("- "));
tags.push({ tag, count: dates.length, latest: dates[0]?.replace("- ", "") || "?" });
}
// Sort by count descending
tags.sort((a, b) => b.count - a.count);
for (const { tag, count, latest } of tags.slice(0, 30)) {
out += `${tag.padEnd(25)} ${String(count).padStart(3)} days latest: ${latest}\n`;
}
if (tags.length > 30) out += `\n ... and ${tags.length - 30} more tags`;
return out.trimEnd();
}
function cmdSummary(args) {
const parts = (args || "").trim().split(/\s+/);
const agent = parts.find(p => !p.startsWith("-") && !/^\d{4}/.test(p) && p !== "daily" && p !== "weekly") || "main";
const typeArg = parts.find(p => p === "daily" || p === "weekly");
const dateArg = parts.find(p => /^\d{4}/.test(p));
const memDir = resolveMemDir(agent);
if (!memDir) return `Agent "${agent}" not found.`;
// If specific date given, show that summary
if (dateArg) {
const type = typeArg || (dateArg.includes("W") ? "weekly" : "daily");
const sumFile = path.join(memDir, "summaries", type, `${dateArg}.md`);
const content = readFile(sumFile);
if (!content) return `No ${type} summary for ${dateArg}.`;
return content;
}
// List available summaries
const types = typeArg ? [typeArg] : ["daily", "weekly"];
let out = `Summaries: ${agent}\n`;
out += "─────────────────────────────\n";
for (const type of types) {
const sumDir = path.join(memDir, "summaries", type);
let files;
try { files = fs.readdirSync(sumDir).filter(f => f.endsWith(".md")).sort().reverse(); }
catch { continue; }
if (files.length === 0) continue;
out += `\n[${type.charAt(0).toUpperCase() + type.slice(1)}] (${files.length})\n`;
for (const f of files.slice(0, 10)) {
const name = f.replace(".md", "");
const content = readFile(path.join(sumDir, f));
const sessMatch = content?.match(/\*\*(?:Total s|S)essions:\*\*\s*(\d+)/);
const sessions = sessMatch ? sessMatch[1] : "?";
out += ` ${name} ${sessions} session(s)\n`;
}
if (files.length > 10) out += ` ... +${files.length - 10} more\n`;
}
out += `\nUse /mc summary <YYYY-MM-DD> or /mc summary <YYYY-Www> to view details.`;
return out.trimEnd();
}
function cmdHelp() { function cmdHelp() {
return `MC Commands (Memory Continuity) return `MC Commands (Memory Continuity)
───────────────────────────── ─────────────────────────────
/mc state [agent] View current state (default: main) /mc state [agent] View current state (default: main)
/mc state --all Overview of all agents /mc state --all Overview of all agents
/mc sessions [date] Session logs (daily activity) /mc sessions [date] Session logs (daily activity)
/mc summary [daily|weekly] List or view summaries
/mc tags [agent] View tag index
/mc history [agent] List archived sessions /mc history [agent] List archived sessions
/mc restore <N> [agent] Restore archive #N /mc restore <N> [agent] Restore archive #N
/mc clear [agent] Clear state (archives first) /mc clear [agent] Clear state (archives first)
@@ -571,6 +655,8 @@ export default function (api) {
case "settings": text = cmdSettings(subargs || null); break; case "settings": text = cmdSettings(subargs || null); break;
case "compact": text = cmdCompact(subargs || null); break; case "compact": text = cmdCompact(subargs || null); break;
case "export": text = cmdExport(subargs || null); break; case "export": text = cmdExport(subargs || null); break;
case "tags": text = cmdTags(subargs || null); break;
case "summary": text = cmdSummary(subargs || null); break;
case "help": case "--help": case "-h": case "": case "help": case "--help": case "-h": case "":
text = cmdHelp(); break; text = cmdHelp(); break;
default: default: