昨天我們快速看過 ~/.gemini/antigravity-cli/ 目錄時,有提到了每次開啟新 Session,系統都會在 brain/ 與 conversations/ 底下各建立專屬的資料。昨天我想說 brain/ 不過就是放 Log 的地方,但實際進去看才發現裡面比我想得豐富很多。今天我們來深入看一下 brain/ 底下的到底有什麼,以及可以怎麼解讀。
brain/ 裡面裝了什麼?進到 ~/.gemini/antigravity-cli/brain/<Session-UUID>/,整個目錄其實是 Antigravity CLI 一段 Session 中的 Session Workspace,裡面的結構可能會有這些東西:
~/.gemini/antigravity-cli/brain/<Session-UUID>/
├── xxxx.jpg # 生成的圖片、圖表或獨立報告
├── yyyy_plan.md # Plan Mode 生成的計畫
├── scratch/ # Agent 運作時手刻的暫存 Script(例如:測試或資料轉換 Script)
├── .user_uploaded/ # 使用者上傳過的圖片或附件
├── .tempmediaStorage/ # Agent 讀過的檔案暫存區(例如:PDF、圖片等)
└── .system_generated/ # Agent 系統底層運行的各項軌跡
├── steps/ # 工具呼叫的原始輸出(可能累積上千個資料夾)
│ └── <step_index>/output.txt
├── tasks/ # 背景非同步任務日誌(如 task-<id>.log)
├── messages/ # 內部事件與非同步通知(如 <uuid>.json)
└── logs/ # 對話主線日誌
├── transcript.jsonl # 步驟摘要日誌(長文字會被截斷)
└── transcript_full.jsonl # 包含完整思考對話與工具參數的全文日誌
這裡要先講一下,對於 Antigravity CLI 而言,ReAct 的每一步都是一個 Step,例如:User Input 或是 Tool Call 等等。這裡挑幾個比較有趣的看一下:
scratch/(腳本暫存區):*.js 或 *.py 之類的檔案。.system_generated/steps/<step_index>/output.txt:100/、1012/ ...),每個目錄代表 Agent 在第幾個 Step 呼叫工具(比如改檔、讀檔或下指令)時,產生的原始終端輸出(raw stdout/stderr),這些輸出都會被獨立存成一份 output.txt。.system_generated/tasks/:內容雖然很雜,但如果要看整場對話的「主線」,主要還是 logs/ 底下的 transcript.jsonl 與 transcript_full.jsonl。
快速聊一下 json 跟 jsonl(JSON Lines)的差別,一般常見的 JSON 通常是一個單一且完整的結構。如果要往裡面增加一筆資料,不能直接在檔案尾端隨意加一行,而是必須把整份內容讀出來、解析成記憶體物件、修改完再整個重新序列化覆寫回磁碟,而且只要結尾少了一個括號,整份 JSON 就會直接 Parse Failed。而 JSONL(JSON Lines)的規則相對簡單:每行都是獨立、合法的 JSON 物件,行與行之間只用換行符號隔開,最外層不需要任何 Array 符號包覆。
在 Agent 記錄運行 Log 的場景下,把對話存成 JSONL 的好處有幾個:
我們可以用下方指令看看檔案內容(這裡我們取 10 筆):
head -n 10 ~/.gemini/antigravity-cli/brain/*/.system_generated/logs/transcript_full.jsonl | jq .
結果會類似這樣,在 transcript.jsonl 裡,每一行都是一個獨立的事件(Step)。根據不同的執行階段,主要有幾種常見的 type:
// 1. type: "USER_INPUT"(使用者在終端機輸入 Prompt 的事件)
{
"step_index": 0,
"source": "USER_EXPLICIT",
"type": "USER_INPUT",
"status": "DONE",
"created_at": "2026-09-28T10:00:00Z",
"content": "幫我看一下 README.md 的內容"
}
// 2. type: "PLANNER_RESPONSE"(模型思考過程與預計工具呼叫,不一定每次都有工具呼叫)
{
"step_index": 1,
"source": "MODEL",
"type": "PLANNER_RESPONSE",
"status": "DONE",
"created_at": "2026-09-28T10:00:02Z",
"thinking": "使用者想要查看 README.md,我應該呼叫 view_file 工具來讀取檔案內容...",
"tool_calls": [
{
"name": "view_file",
"args": {
"AbsolutePath": "/path/to/project/README.md",
"StartLine": 1,
"EndLine": 30
}
}
],
"content": "我現在幫您查看 README.md 的內容。"
}
// 3. type: "GENERIC"(工具執行後的回傳結果,即 Observation)
{
"step_index": 2,
"source": "MODEL",
"type": "GENERIC",
"status": "DONE",
"created_at": "2026-09-28T10:00:03Z",
"content": "# My Project\n\nThis is a sample project for demonstration."
}
把這幾種 type 串在一起,就是我們在 Day 16 提到的 ReAct 循環:
1. USER_INPUT (輸入) : 你在終端機輸入「幫我看一下 README.md」
↓
2. PLANNER_RESPONSE (思考 or 執行): 模型經過思考,決定呼叫 view_file (tool_calls)
↓
3. GENERIC (執行結果): 本地讀取檔案後回傳的內容 (content)
↓
4. PLANNER_RESPONSE (最終解答): 模型消化完檔案內容,輸出最終答案 (content)
這包 JSON 資料中,主要資訊集中在這三個欄位:
thinking(模型思考鏈):tool_calls(工具呼叫):name)與傳入的參數(args)。例如它呼叫了 run_command 或 view_file,參數是什麼都能清楚看到。content(模型回覆文字):酷吧!明天我們繼續來看另外一個重要目錄 conversations/ 底下的結構化 SQLite 資料庫吧。明天見~