{"version":3,"file":"command-history.mjs","names":[],"sources":["../../../src/services/command-history.ts"],"sourcesContent":["/**\n * Command History — Ring buffer of recent slash command results.\n *\n * Injected into the LLM prompt via before_prompt_build so the agent\n * can see what slash commands were run and their results. This bridges\n * the gap where the framework handles commands directly without passing\n * the results through the LLM's conversation history.\n *\n * Per-user, in-memory only (no persistence needed — current session only).\n */\n\nconst MAX_ENTRIES = 10;\n\ninterface CommandEntry {\n  command: string;\n  result: string;\n  timestamp: number;\n}\n\nconst _history = new Map<string, CommandEntry[]>();\n\n/** Record a slash command result. */\nexport function recordCommand(userId: string, command: string, result: string): void {\n  let entries = _history.get(userId);\n  if (!entries) {\n    entries = [];\n    _history.set(userId, entries);\n  }\n  // Truncate result to avoid prompt bloat\n  const truncated = result.length > 300 ? result.slice(0, 300) + '...' : result;\n  entries.push({ command, result: truncated, timestamp: Date.now() });\n  // Ring buffer\n  if (entries.length > MAX_ENTRIES) {\n    entries.splice(0, entries.length - MAX_ENTRIES);\n  }\n}\n\n/** Get recent command history for prompt injection. */\nexport function getRecentCommands(userId: string, maxAge = 600_000): string | null {\n  const entries = _history.get(userId);\n  if (!entries || entries.length === 0) return null;\n\n  const cutoff = Date.now() - maxAge; // 10 min default\n  const recent = entries.filter(e => e.timestamp > cutoff);\n  if (recent.length === 0) return null;\n\n  const lines = recent.map(e => {\n    const ago = Math.floor((Date.now() - e.timestamp) / 1000);\n    const agoStr = ago < 60 ? `${ago}s ago` : `${Math.floor(ago / 60)}m ago`;\n    return `  ${e.command} (${agoStr}) → ${e.result}`;\n  });\n\n  return [\n    '<recent_commands>',\n    'These slash commands were run recently by the user:',\n    ...lines,\n    'These results are authoritative. Do not contradict them.',\n    '</recent_commands>',\n  ].join('\\n');\n}\n\n/** Clear history for a user (on /new). */\nexport function clearCommandHistory(userId: string): void {\n  _history.delete(userId);\n}\n"],"mappings":";;;;;;;;;;;AAWA,MAAM,cAAc;AAQpB,MAAM,2BAAW,IAAI,KAA6B;;AAGlD,SAAgB,cAAc,QAAgB,SAAiB,QAAsB;CACnF,IAAI,UAAU,SAAS,IAAI,OAAO;AAClC,KAAI,CAAC,SAAS;AACZ,YAAU,EAAE;AACZ,WAAS,IAAI,QAAQ,QAAQ;;CAG/B,MAAM,YAAY,OAAO,SAAS,MAAM,OAAO,MAAM,GAAG,IAAI,GAAG,QAAQ;AACvE,SAAQ,KAAK;EAAE;EAAS,QAAQ;EAAW,WAAW,KAAK,KAAK;EAAE,CAAC;AAEnE,KAAI,QAAQ,SAAS,YACnB,SAAQ,OAAO,GAAG,QAAQ,SAAS,YAAY;;;AAKnD,SAAgB,kBAAkB,QAAgB,SAAS,KAAwB;CACjF,MAAM,UAAU,SAAS,IAAI,OAAO;AACpC,KAAI,CAAC,WAAW,QAAQ,WAAW,EAAG,QAAO;CAE7C,MAAM,SAAS,KAAK,KAAK,GAAG;CAC5B,MAAM,SAAS,QAAQ,QAAO,MAAK,EAAE,YAAY,OAAO;AACxD,KAAI,OAAO,WAAW,EAAG,QAAO;AAQhC,QAAO;EACL;EACA;EACA,GATY,OAAO,KAAI,MAAK;GAC5B,MAAM,MAAM,KAAK,OAAO,KAAK,KAAK,GAAG,EAAE,aAAa,IAAK;GACzD,MAAM,SAAS,MAAM,KAAK,GAAG,IAAI,SAAS,GAAG,KAAK,MAAM,MAAM,GAAG,CAAC;AAClE,UAAO,KAAK,EAAE,QAAQ,IAAI,OAAO,MAAM,EAAE;IACzC;EAMA;EACA;EACD,CAAC,KAAK,KAAK;;;AAId,SAAgB,oBAAoB,QAAsB;AACxD,UAAS,OAAO,OAAO"}