The shipped default combined a sliding history window with no compaction, which is the worse of the two available trades in both directions it is measured on. `max_history_messages: 30` is a sliding tail window (`projection::window` — `drain(..len - max)`). Past 30 messages it drops from the head on *every* turn, so the prompt prefix changes on every single request and every provider that caches one (Anthropic breakpoints, OpenAI automatic prefix caching) misses every time. It also drops those messages with no summary standing in for them: silent amnesia, not just a cold cache. Compaction rewrites the prefix once per compaction and leaves a summary behind — yet it was the half that was commented out, while the window's own doc-comment already said the two were exclusive. Both are now `Option` and both ship unset, so nothing shrinks a conversation unless a human types `/compact`. Which surfaced the real bug: `/compact` did not work either. The compactor was `Option<Arc<ContextCompactor>>` keyed on the config section existing, so commenting out `compaction:` disabled the manual command too — `force_compact` returned `Ok(false)` and the chat answered "compaction disabled". Manual compaction is a command a user types; it cannot depend on an admin having filled in a token threshold. The compactor is now built unconditionally and `threshold_tokens: Option<u32>` arms only the automatic pass; `try_compact` early-returns without it, `force_compact` deliberately never consults it. The projection accordingly yields to the *automatic* pass rather than to the compactor's existence (`LoopConfig.auto_compaction_enabled`), so a configured message cap is not silently voided by `/compact` merely being available. `CompactionConfig::Default` is hand-written for the same reason `RoleAttrs`'s is: a derived one gives `keep_recent: 0`, which would compact away every recent message on any box omitting the section — now the default. Also fixes two documentation bugs in the same file: `event_triage` was documented nested under `llm:`, where it parses fine and is then silently ignored (it is a top-level field), and `datetime` was documented twice with conflicting examples. A new test asserts the shipped default actually deserializes and that both guards are off — a field the default omits must be genuinely optional, or a brand-new install fails to boot. Automatic compaction returns later, triggered off the resolved model's own context window instead of a hand-tuned token count that cannot know which model is answering.
2.1 KiB
Settings (Config page)
The Config page holds instance-wide settings. It is admin-only: what an admin changes here applies to every user of the instance.
Each setting is saved individually with its own Save button (a few, like the language, save as soon as they are changed).
Interface
- Language — the default interface language for the whole instance. Each user can override it on their own profile page.
Background agents — not here
The settings for the background agents (event triage, the two memory lints) are not on this page. Each one is configured on its own tab of the System agents page, next to that agent's run history — see system-agents.md.
They are still admin-only, and still instance-wide. They simply live where their run log is, because "why did this agent do nothing last night?" is usually answered half by the schedule and half by the log.
Compaction
Compaction summarises the older part of a conversation so the context stays within limits: the summary replaces those messages in future turns, while the most recent ones are kept verbatim.
It runs on request, not on its own. Type /compact in the chat whenever a conversation has grown long and you want it condensed. Nothing is summarised until you ask, so a conversation keeps its full history — which is also what lets the model provider reuse its cache of the conversation instead of re-reading it from scratch every message.
(An admin can arm an automatic pass by setting compaction.threshold_tokens in config.yml; it is off in the shipped configuration.)
- Compaction model — the model used to write those summaries, for the whole instance. Summarising is a simple writing task, so a cheap, fast model is usually the right choice — there is no reason to spend premium-model tokens on it. Leave it empty for automatic selection (by the
compaction.strengthvalue inconfig.yml, or the instance's default priority order). If the chosen model is later deleted, compaction silently falls back to automatic selection.
Developer
- Debug mode — shows extra technical diagnostics in the interface.