0.4.11
21 · Техническая документация

21. Формат rollout (JSONL)

Rollout — это полный лог одной сессии в формате JSONL. Каждая строка — один JSON-объект. Файл append-only: события дописываются по мере turn'а. Используется для:

  • /resume <id> — восстановление сессии.
  • Воспроизведения для отладки.
  • Источник для Phase 1 памяти (см. 07-memories.md).
  • Аудита.

Реализация — крейт rollout/. Расширенная версия — rollout-trace/.

1. Файл

Имя

text
rollout-YYYY-MM-DDThh-mm-ss-<uuid>.jsonl

Создаётся в rollout/src/recorder.rs:1370 (format!("rollout-{date_str}-{conversation_id}.jsonl")).

Путь

text
~/.astracode/sessions/YYYY/MM/DD/rollout-<timestamp>-<uuid>.jsonl

Архивированные через action в session picker переезжают в:

text
~/.astracode/archived_sessions/rollout-<timestamp>-<uuid>.jsonl

См. rollout/src/lib.rs (SESSIONS_SUBDIR, ARCHIVED_SESSIONS_SUBDIR).

Версионирование

Явного поля schema_version нет; SessionMeta.timestamp — время создания, а не версия схемы. Backwards compatibility обеспечивается через tolerant deserialization, serde(default) и aliases на новых/переименованных полях.

2. Структура

Первая строка — session_meta

jsonl
{
  "timestamp": "2026-06-01T10-23-45.123Z",
  "item": {
    "type": "session_meta",
    "meta": {
      "id": "9e3b4f12-...-abc",
      "forked_from_id": null,
      "timestamp": "2026-06-01T10:23:45.123Z",
      "cwd": "/home/user/work/myproject",
      "originator": "astracode-cli/X.Y.Z",
      "cli_version": "X.Y.Z",
      "agent_nickname": "cli",
      "agent_role": "assistant",
      "agent_path": null,
      "source": "cli",
      "model_provider": "openai",
      "base_instructions": null,
      "dynamic_tools": [...],
      "memory_mode": "enabled"
    },
    "git": {
      "commit_hash": "abc123def",
      "branch": "main",
      "repository_url": "https://github.com/..."
    }
  }
}

SessionMeta (protocol/src/protocol.rs) содержит id (ThreadId) и memory_mode (опц. строка). Полный набор полей — там же; SessionMetaLine оборачивает SessionMeta (#[serde(flatten)]) и добавляет опц. git.

Последующие строки — RolloutItem

rust
#[serde(tag = "type", content = "payload", rename_all = "snake_case")]
pub enum RolloutItem {
    SessionMeta(SessionMetaLine),   // только первая запись
    ResponseItem(ResponseItem),     // сообщение пользователя/ассистента или tool call
    Compacted(CompactedItem),       // итог compact'а
    TurnContext(TurnContextItem),   // snapshot контекста turn'а
    EventMsg(EventMsg),             // обёрнутое событие из протокола (turn start/end, tool begin/end, ...)
}

Каждая строка имеет timestamp и поле item.type:

jsonl
{"timestamp":"...", "item":{"type":"response_item", ...}}
{"timestamp":"...", "item":{"type":"event_msg", "payload":{"type":"user_message","message_id":"msg_123","text":"hello"}}}
{"timestamp":"...", "item":{"type":"turn_context", "payload":{...}}}
{"timestamp":"...", "item":{"type":"compacted", "payload":{...}}}

3. Типы событий

session_meta

Только в начале файла. Описана выше.

response_item

Один элемент истории — сообщение, reasoning, tool call, tool output.

json
{
  "type": "response_item",
  "payload": {
    "type": "message",          // message | reasoning | function_call | function_call_output | ...
    "id": "msg_abc",
    "role": "user",             // user | assistant | system | developer
    "content": [
      { "type": "input_text", "text": "Fix the failing test." }
    ]
  }
}

Полный набор типов в astracode_protocol::models::ResponseItem.

event_msg

Обёрнутые события протокола (EventMsg, protocol/src/protocol.rs; сериализуется через #[serde(tag = "type", rename_all = "snake_case")]). Стримятся в TUI и пишутся в rollout.

payload.type Когда
task_started Старт turn'а (alias: turn_started)
user_message User отправил сообщение
agent_message_delta Кусок текста ассистента (стрим)
agent_message Финальное сообщение ассистента
agent_reasoning / agent_reasoning_delta / agent_reasoning_raw_content Extended thinking блок и его дельты
item_started / item_completed Начало/завершение item'а (assistant message / tool call / reasoning)
exec_command_begin / exec_command_output_delta / exec_command_end Подробности shell exec
patch_apply_begin / patch_apply_updated / patch_apply_end Применение патчей
mcp_tool_call_begin / mcp_tool_call_end MCP-вызовы
exec_approval_request / apply_patch_approval_request / request_permissions Approval flow
model_reroute Смена модели / fallback
thread_goal_updated Изменение цели треда
context_compacted Произошёл compact
task_complete Turn закончен (alias: turn_complete)
turn_aborted Turn прерван (с reason)

tool_use_start / tool_use_end / reasoning_start / reasoning_end / assistant_message / assistant_message_delta в коде не существуют — это устаревшие имена. Жизненный цикл item'ов идёт через item_started/item_completed, а текст/_reasoning — через agent_message*/agent_reasoning*.

Полный список — astracode_protocol::protocol::EventMsg.

turn_context

Snapshot конфигурации turn'а (TurnContextItem): модель, reasoning_effort, permission_profile, environments, доступные tools. Пишется при старте каждого turn'а и после mid-turn compaction.

json
{
  "type": "turn_context",
  "payload": {
    "turn_id": "...",
    "trace_id": "...",
    "cwd": "/home/user/work/myproject",
    "current_date": "...",
    "timezone": "...",
    "approval_policy": "on-request",
    "sandbox_policy": {...},
    "permission_profile": {...},
    "network": {...},
    "model": "gpt-5",
    "personality": "default",
    "collaboration_mode": "default",
    "effort": {...},
    "summary": {...},
    "user_instructions": "...",
    "developer_instructions": "...",
    "final_output_json_schema": null,
    "truncation_policy": null
  }
}

compacted

Итог /compact (CompactedItem) — резюме, заменившее старую историю.

json
{
  "type": "compacted",
  "payload": {
    "message": "...",
    "replacement_history": [ ... ]
  }
}

message — текст резюме; replacement_history (опц.) — Vec<ResponseItem>, восстанавливающий контекст после compaction.

4. Запись на диск

Реализация: rollout/src/recorder.rs.

  • Асинхронно: команды отправляются в MPSC канал.
  • Buffered: AddItems накапливаются в pending_items, пишутся одним write_all() + flush() либо при explicit flush()/persist(), либо после каждого batch'а.
  • Recovery: при ошибке записи writer закрывает файл, переоткрывает и повторяет.

API: - record_items(items) — не ждёт результата. - flush() — ждёт окончания записи всех pending. - persist() — то же + sync to disk.

5. Чтение

Полная загрузка

rust
let items = RolloutRecorder::load_rollout_items(path).await?;

rollout/src/recorder.rs — построчно парсит JSON и собирает Vec<RolloutItem>.

Для resume

rust
let history = RolloutRecorder::get_rollout_history(path).await?;
// → InitialHistory::Resumed(ResumedHistory { conversation_id, history, rollout_path })

ResumedHistory (protocol/src/protocol.rs) содержит поле history: Vec<RolloutItem> (не items), conversation_id и опц. rollout_path.

Listing

  • Файловый scan: рекурсивно по ~/.astracode/sessions/.
  • Через state DB: list_threads_db() использует индекс из threads таблицы (быстрее для большого числа сессий). См. 23-state-db.md.

6. Расширенный трейсинг (rollout-trace)

Крейт rollout-trace/ — параллельная система, пишущая trace bundle (директория с дополнительным JSONL + сырыми payload-файлами):

  • Используется экспериментальным multi-agent v2, code-mode cells и remote compaction.
  • Детальный реплей с reduced state.
  • Тут — отдельные события (RolloutStarted, InferenceStarted, ToolCallStarted, CodeCellStarted, CompactionRequestStarted, AgentResultObserved и т.п.).

См. rollout-trace/src/raw_event.rs для полного списка:

text
RolloutStarted, RolloutEnded,
ThreadStarted, ThreadEnded,
AstraCodeTurnStarted, AstraCodeTurnEnded,
InferenceStarted, InferenceCompleted, InferenceFailed, InferenceCancelled,
ToolCallStarted, ToolCallRuntimeStarted/Ended, ToolCallEnded,
CodeCellStarted, CodeCellInitialResponse, CodeCellEnded,
CompactionRequestStarted/Completed/Failed,
CompactionInstalled,
AgentResultObserved,
ProtocolEventObserved (обёрнутые UI события),
Other (произвольный payload для расширений)

Включается через env-переменную ASTRACODE_ROLLOUT_TRACE_ROOT (указывает директорию для trace-бандлов). Если переменная не задана — трейсинг выключен. Это диагностический режим: ошибка инициализации трейса не ломает сессию. Полей rollout_trace_enabled в config.toml нет. Реплей бандла — astracode debug trace-reduce (других debug-rollout-подкоманд вроде astracode replay или astracode debug rollout нет).

7. Полезные команды

bash
# Найти rollout текущей сессии (debug-режим TUI)
/rollout

# Снаружи — список сессий за день
ls ~/.astracode/sessions/2026/06/01/

# Просмотреть JSONL
jq -c . ~/.astracode/sessions/2026/06/01/rollout-*.jsonl | head -20

# Поиск всех user-сообщений
jq -c 'select(.item.type=="event_msg" and .item.payload.type=="user_message") | .item.payload.text' \
   ~/.astracode/sessions/2026/06/01/rollout-*.jsonl

# Время длительности turn'ов
jq -c 'select(.item.type=="event_msg" and (.item.payload.type=="task_started" or .item.payload.type=="task_complete")) | [.timestamp, .item.payload.type]' \
   ~/.astracode/sessions/2026/06/01/rollout-*.jsonl

8. Размер и ротация

Rollouts могут быстро расти (особенно при extended thinking и подробных tool output'ах). Типично: - Короткая сессия (1-2 turn'а): 5-50 KB. - Средняя (10-30 turn'ов): 100-500 KB. - Длинная (с большим контекстом, многими tool calls): 5-50 MB.

Автоматической ротации rollout-файлов нет. Для штатной логической очистки используйте archive action в session picker: он перемещает файл в archived_sessions/, не уничтожая данные. Прямое массовое удаление файлов из sessions/ делает треды невосстановимыми и при следующем чтении списка приводит к удалению stale metadata rows; поддерживаемого массового physical purge API сейчас нет.

9. Безопасность

  • Содержимое rollout не шифруется.
  • Сюда попадают полные user prompts, code контент, command output (включая случайные секреты, если они проходили через terminal).
  • Сюда НЕ попадают: API-ключи (они никогда не отдаются модели), пароли из secrets/local.age.
  • При шаринге rollout кому-то — просматривайте на наличие чувствительной информации.

10. Совместимость

Версия AstraCode Rollout формат Чтение старых
0.5.x Текущий Да
0.3.x (codex upstream) Близкий, но без goal, dynamic_tools, memory_mode полей Да (через serde(default)/alias)
Старые codex pre-0.3 Возможны несовместимости Best effort

11. Файлы