Skip to content

Chat History

The ChatHistoryManager persists conversations, prunes old messages on every read/write, and formats output for the active provider’s role convention.

Enabled by default. Runs transparently on every history operation. Permanently deletes — not just hides.

Rules in priority order:

RuleDefaultBehavior
Age30 days (720 h)Messages older than maxAgeHours removed first
Count50 messagesIf over maxMessages, oldest go first
Tokens32 000If over maxTokens, oldest go first

System messages are always preserved when preserveSystemMessages is true (default).

Token estimation: 4 chars ≈ 1 token — conservative enough to prevent overflow, generous enough not to strip useful context.

sequenceDiagram participant UI participant CHM as ChatHistoryManager participant DB as AgentService (SQLite) participant Cache as In-memory cache UI->>CHM: Send message CHM->>DB: Read existing history CHM->>CHM: Add timestamp, merge Note over CHM: Prune (age → count → tokens)<br/>system messages kept CHM->>DB: Save pruned history CHM->>Cache: Sync fast-path cache CHM->>CHM: Format per provider (role mapping) CHM-->>UI: Formatted history

Each provider has its own role names + message shape. LLM_CONFIGS holds the mapping; formatChatHistory(role, message, model, key) produces the correct output for the active model.

Flow per call:

  1. Raw history from SQLite (or in-memory fast-path).
  2. Append new message with timestamp.
  3. Prune combined result.
  4. Save pruned back to SQLite.
  5. Format each entry via model’s role mapping (user / assistant / system).
  6. Return formatted array to the LLM caller.

For long conversations you want to keep a synopsis of instead of the full transcript:

await chatHistory.saveSummary(key, "Auth setup covered...");
const summary = await chatHistory.getSummary(key);

Summaries live alongside the full history in SQLite. Useful for injection when the full history is too large to fit.

  • Primary: SQLite via AgentService. Keyed by workspace identity + conversation ID.
  • Fast-path: in-memory cache (Memory class in src/memory/base.ts) kept in sync for repeated reads within a session.
  • clearHistory() purges both.
SettingDefaultPurpose
chatHistory.enableAutoPruningtrueEnable pruning
chatHistory.maxMessages50Message cap
chatHistory.maxTokens32000Token cap
chatHistory.maxAgeHours720Age cap (30 days)

These keys are read from settings.json directly and aren’t surfaced in the Settings UI — add them by hand if you want to tune pruning.

  • Memory — old history doesn’t accumulate.
  • Privacy — code snippets, keys, and secrets in old messages don’t linger.
  • Perf — smaller history = faster queries + less formatting work.
  • Quality — LLMs perform better with focused, recent context.
  • Context system — how history fits into the per-turn context budget
  • Memory — persistent facts (survives conversation clears)
  • Self-healing §Layer 4 — window-based summarization for long single conversations