Контекст
Провайдеру уезжает не журнал сессии, а редактируемая проекция журнала: журнал append-only и нужен для аудита, уборка его не переписывает.
Что где лежит
| путь | что |
|---|---|
sessions/<id>.jsonl | журнал: сообщения, вызовы, результаты, ревизии |
sessions/<id>.out/LIVE_CONTEXT.json | зеркало рабочего контекста, его правит модель |
sessions/<id>.out/<hash>.txt | полный вывод команды, обрезанный в контексте |
sessions/<id>.out/cwd | рабочий каталог сессии |
Обрезка не теряет данные: большой или бинарный вывод ядро кладёт файлом в <id>.out/ и дописывает в результат [полный вывод: …] — читай кусок через grep/read.
Бюджет и окно
Физическое окно модели и экономический бюджет — разные ограничения: модель с окном в миллион токенов не обязана получать весь контекст на каждом ходу.
ctx_window = 1000000 # физическое окно модели
context_budget = 0 # 0 = auto: 100k при окне ≤300k, иначе 200k
context_reserve = 8192 # запас до предела для следующего хода
context_target = 0 # 0 = auto: 70% бюджета
keep_results = 5 # сколько последних результатов не трогает автоэлизия
[models."vendor/model"]
context_budget = 500000
context_target = 350000
Побеждает самый длинный совпавший префикс slug; явный context_budget сильнее профиля; смена модели в рантайме меняет профиль на следующем ходу. Порог считается по токенам провайдера: к своей оценке применяется откалиброванный множитель — отношение usage.prompt_tokens к ней же, со свежими ходами в большем весе.
Два слоя уборки
Автоэлизия — пред-шаг без участия модели. При переходе через context_budget ядро само схлопывает самые старые результаты инструментов в пометку (имя тула, размер, хвост команды), не трогая последние keep_results, пока оценка не опустится до context_target. Решение живёт записью в журнале и накладывается проекцией; уборка переживает resume и не срабатывает повторно.
Правка зеркала моделью — только если после элизии всё ещё выше цели. Тогда в ход приезжает абзац «управляешь своим контекстом», модель правит LIVE_CONTEXT.json обычными read/edit/write и зовёт ctx:
{"action": "commit"}
{"action": "status"}
Правка файла сама ревизию не применяет; пустой объект тоже означает commit. status печатает путь к зеркалу, бюджет, цель и последнюю принятую ревизию. Подтверждение применения — следующее системное сообщение, а не отчёт модели: повторять commit ради подтверждения не надо. restore() отвергает черновик, где удалён или изменён user-блок или текст ассистента: снимать можно результаты инструментов и аргументы вызовов. Вызов и его результат — атомарный блок.
ctx clear
Правка зеркала блоками слишком груба: она теряет уже принятые решения. Для точечной уборки есть clear — он трогает только результаты инструментов.
{"action": "clear", "call_ids": ["call_7", "call_9"]}
{"action": "clear", "before": "call_12"}
{"action": "clear", "keep_last": 3, "tool": "read"}
| ключ | что делает |
|---|---|
call_ids | вырезать перечисленные результаты |
before | всё строго до указанного call_id |
keep_last | всё старше N последних результатов |
tool | маска: только результаты этого инструмента |
min_bytes | маска: только результаты не меньше N байт |
Маски сужают уже выбранное (keep_last + tool), а не выбирают сами. Повторный вызов на вырезанном отвечает «нечего вырезать».
/compact и /compact <инструкция> в TUI просят ту же уборку тем же агентом; отдельного summarizer'а нет.
Границы
- Ходы диалога неприкосновенны; снимаются результаты тулов и аргументы вызовов.
- Перед уборкой выпиши принятые решения пометкой РЕШЕНО: запрет спасает диалог, но не заменяет записку.
- Служебные пары
read/edit/writeзеркала иctx commitпосле успешного применения из проекции исчезают, в журнале остаются; shell-правки того же файла черезrunобслуживанием зеркала не считаются. - Большую вставку человека правкой зеркала ужать нельзя: крупное вложение уезжает файлом и отваливается вместе с тулами.