- 首頁
- Documentation
- 工作階段
- 壓縮與分支摘要
壓縮與分支摘要
壓縮與分支摘要是兩種機制,用於在不遺失先前工作上下文的情況下保持長期會話的可用性。
- 壓縮將當前分支上的舊歷史記錄重寫為摘要。
- 分支摘要在
/tree導航期間捕獲被放棄的分支上下文。
兩者都以會話條目的形式持久化,並在重建 LLM 輸入時轉換回使用者上下文訊息。
關鍵實作檔案
Section titled “關鍵實作檔案”src/session/compaction/compaction.tssrc/session/compaction/branch-summarization.tssrc/session/compaction/pruning.tssrc/session/compaction/utils.tssrc/session/session-manager.tssrc/session/agent-session.tssrc/session/messages.tssrc/extensibility/hooks/types.tssrc/config/settings-schema.ts
會話條目模型
Section titled “會話條目模型”壓縮與分支摘要是一等會話條目,而非普通的助理/使用者訊息。
CompactionEntrytype: "compaction"summary,可選shortSummaryfirstKeptEntryId(壓縮邊界)tokensBefore- 可選
details、preserveData、fromExtension
BranchSummaryEntrytype: "branch_summary"fromId、summary- 可選
details、fromExtension
當重建上下文(buildSessionContext)時:
- 活動路徑上最新的壓縮被轉換為一個
compactionSummary訊息。 - 從
firstKeptEntryId到壓縮點的保留條目會被重新包含。 - 路徑上後續的條目會被附加。
branch_summary條目被轉換為branchSummary訊息。custom_message條目被轉換為custom訊息。
這些自訂角色隨後在 convertToLlm() 中使用靜態範本轉換為面向 LLM 的使用者訊息:
prompts/compaction/compaction-summary-context.mdprompts/compaction/branch-summary-context.md
壓縮可以透過三種方式執行:
- 手動:
/compact [instructions]呼叫AgentSession.compact(...)。 - 自動溢出恢復:在助理錯誤符合上下文溢出條件後觸發。
- 自動閾值壓縮:在成功回合後,當上下文超過閾值時觸發。
壓縮結構(視覺化)
Section titled “壓縮結構(視覺化)”Before compaction:
entry: 0 1 2 3 4 5 6 7 8 9 ┌─────┬─────┬─────┬──────┬─────┬─────┬──────┬──────┬─────┬──────┐ │ hdr │ usr │ ass │ tool │ usr │ ass │ tool │ tool │ ass │ tool │ └─────┴─────┴─────┴──────┴─────┴─────┴──────┴──────┴─────┴──────┘ └────────┬───────┘ └──────────────┬──────────────┘ messagesToSummarize kept messages ↑ firstKeptEntryId (entry 4)
After compaction (new entry appended):
entry: 0 1 2 3 4 5 6 7 8 9 10 ┌─────┬─────┬─────┬──────┬─────┬─────┬──────┬──────┬─────┬──────┬─────┐ │ hdr │ usr │ ass │ tool │ usr │ ass │ tool │ tool │ ass │ tool │ cmp │ └─────┴─────┴─────┴──────┴─────┴─────┴──────┴──────┴─────┴──────┴─────┘ └──────────┬──────┘ └──────────────────────┬───────────────────┘ not sent to LLM sent to LLM ↑ starts from firstKeptEntryId
What the LLM sees:
┌────────┬─────────┬─────┬─────┬──────┬──────┬─────┬──────┐ │ system │ summary │ usr │ ass │ tool │ tool │ ass │ tool │ └────────┴─────────┴─────┴─────┴──────┴──────┴─────┴──────┘ ↑ ↑ └─────────────────┬────────────────┘ prompt from cmp messages from firstKeptEntryId溢出重試 vs 閾值壓縮
Section titled “溢出重試 vs 閾值壓縮”兩種自動路徑有意設計為不同:
-
溢出重試壓縮
- 觸發條件:當前模型的助理錯誤被偵測為上下文溢出。
- 失敗的助理錯誤訊息在重試前從活動代理狀態中移除。
- 自動壓縮以
reason: "overflow"和willRetry: true執行。 - 成功後,代理自動繼續(
agent.continue()),在壓縮之後執行。
-
閾值壓縮
- 觸發條件:
contextTokens > contextWindow - compaction.reserveTokens。 - 以
reason: "threshold"和willRetry: false執行。 - 成功後,若
compaction.autoContinue !== false,注入合成提示:"Continue if you have next steps."
- 觸發條件:
在壓縮檢查之前,可能會執行工具結果剪枝(pruneToolOutputs)。
預設剪枝策略:
- 保護最新的
40_000個工具輸出 token。 - 要求至少
20_000個總估計節省量。 - 永遠不剪枝來自
skill或read的工具結果。
被剪枝的工具結果會被替換為:
[Output truncated - N tokens]
如果剪枝更改了條目,會話儲存會被重寫,且代理訊息狀態會在壓縮決策之前重新整理。
邊界與切割點邏輯
Section titled “邊界與切割點邏輯”prepareCompaction() 僅考慮自上次壓縮條目(如果有的話)以來的條目。
- 找到上一個壓縮索引。
- 計算
boundaryStart = prevCompactionIndex + 1。 - 在有可用的測量使用率時,使用其調整
keepRecentTokens。 - 在邊界視窗上執行
findCutPoint()。
有效的切割點包括:
- 角色為以下的訊息條目:
user、assistant、bashExecution、hookMessage、branchSummary、compactionSummary custom_message條目branch_summary條目
硬性規則:永遠不在 toolResult 處切割。
如果切割點之前緊鄰非訊息的中繼資料條目(model_change、thinking_level_change、標籤等),則透過將切割索引向後移動直到遇到訊息或壓縮邊界,將它們拉入保留區域。
分割回合處理
Section titled “分割回合處理”如果切割點不在使用者回合起始處,壓縮將其視為分割回合。
回合起始偵測將以下視為使用者回合邊界:
message.role === "user"message.role === "bashExecution"custom_message條目branch_summary條目
分割回合壓縮生成兩個摘要:
- 歷史摘要(
messagesToSummarize) - 回合前綴摘要(
turnPrefixMessages)
最終儲存的摘要合併為:
<history summary>
---
**Turn Context (split turn):**
<turn prefix summary>compact(...) 從序列化的對話文字建構摘要:
- 透過
convertToLlm()轉換訊息。 - 使用
serializeConversation()序列化。 - 包裝在
<conversation>...</conversation>中。 - 可選地包含
<previous-summary>...</previous-summary>。 - 可選地將鉤子上下文注入為
<additional-context>列表。 - 使用
SUMMARIZATION_SYSTEM_PROMPT執行摘要提示。
提示選擇:
- 首次壓縮:
compaction-summary.md - 有先前摘要的迭代壓縮:
compaction-update-summary.md - 分割回合第二輪:
compaction-turn-prefix.md - 簡短 UI 摘要:
compaction-short-summary.md
遠端摘要模式:
- 若設定了
compaction.remoteEndpoint,壓縮會 POST:{ systemPrompt, prompt }
- 預期返回至少包含
{ summary }的 JSON。
摘要中的檔案操作上下文
Section titled “摘要中的檔案操作上下文”壓縮使用助理工具呼叫追蹤累計檔案活動:
read(path)→ 讀取集合write(path)→ 修改集合edit(path)→ 修改集合
累計行為:
- 僅當先前條目是由 pi 生成(
fromExtension !== true)時,才包含先前壓縮的詳細資訊。 - 在分割回合中,也包含回合前綴的檔案操作。
readFiles排除同時被修改的檔案。
摘要文字透過提示範本附加檔案標籤:
<read-files>...</read-files><modified-files>...</modified-files>持久化與重新載入
Section titled “持久化與重新載入”在摘要生成(或鉤子提供的摘要)之後,代理會話:
- 使用
appendCompaction(...)附加CompactionEntry。 - 透過
buildSessionContext()重建上下文。 - 以重建的上下文替換即時代理訊息。
- 發出
session_compact鉤子事件。
分支摘要管線
Section titled “分支摘要管線”分支摘要與樹狀導航相關,而非 token 溢出。
在 navigateTree(...) 期間:
- 使用
collectEntriesForBranchSummary(...)計算從舊葉節點到共同祖先的被放棄條目。 - 若呼叫者請求摘要(
options.summarize),在切換葉節點之前生成摘要。 - 若摘要存在,使用
branchWithSummary(...)將其附加到導航目標。
在操作上,這通常由 /tree 流程在 branchSummary.enabled 啟用時驅動。
分支切換結構(視覺化)
Section titled “分支切換結構(視覺化)”Tree before navigation:
┌─ B ─ C ─ D (old leaf, being abandoned) A ───┤ └─ E ─ F (target)
Common ancestor: AEntries to summarize: B, C, D
After navigation with summary:
┌─ B ─ C ─ D ─ [summary of B,C,D] A ───┤ └─ E ─ F (new leaf)準備與 token 預算
Section titled “準備與 token 預算”generateBranchSummary(...) 計算預算為:
tokenBudget = model.contextWindow - branchSummary.reserveTokens
prepareBranchEntries(...) 接著:
- 第一輪:從所有摘要條目中收集累計檔案操作,包含先前由 pi 生成的
branch_summary詳細資訊。 - 第二輪:從最新到最舊遍歷,添加訊息直到達到 token 預算。
- 優先保留最近的上下文。
- 為了連續性,可能仍然在預算邊緣包含大型摘要條目。
壓縮條目在分支摘要輸入期間作為訊息(compactionSummary)包含。
摘要生成與持久化
Section titled “摘要生成與持久化”分支摘要:
- 轉換並序列化選定的訊息。
- 包裝在
<conversation>中。 - 若有提供則使用自訂指令,否則使用
branch-summary.md。 - 使用
SUMMARIZATION_SYSTEM_PROMPT呼叫摘要模型。 - 前置
branch-summary-preamble.md。 - 附加檔案操作標籤。
結果以 BranchSummaryEntry 儲存,附帶可選的詳細資訊(readFiles、modifiedFiles)。
擴充功能與鉤子接觸點
Section titled “擴充功能與鉤子接觸點”session_before_compact
Section titled “session_before_compact”壓縮前鉤子。
可以:
- 取消壓縮(
{ cancel: true }) - 提供完整的自訂壓縮酬載(
{ compaction: CompactionResult })
session.compacting
Section titled “session.compacting”預設壓縮的提示/上下文自訂鉤子。
可以返回:
prompt(覆蓋基礎摘要提示)context(注入<additional-context>的額外上下文行)preserveData(儲存在壓縮條目上)
session_compact
Section titled “session_compact”壓縮後通知,包含已儲存的 compactionEntry 和 fromExtension 旗標。
session_before_tree
Section titled “session_before_tree”在預設分支摘要生成之前的樹狀導航時執行。
可以:
- 取消導航
- 提供自訂的
{ summary: { summary, details } },在使用者請求摘要時使用
session_tree
Section titled “session_tree”導航後事件,公開新/舊葉節點和可選的摘要條目。
執行時行為與失敗語義
Section titled “執行時行為與失敗語義”- 手動壓縮會先中止當前代理操作。
abortCompaction()取消手動和自動壓縮控制器。- 自動壓縮為 UI/狀態更新發出開始/結束會話事件。
- 自動壓縮可以嘗試多個候選模型並重試暫時性失敗。
- 溢出錯誤被排除在通用重試路徑之外,因為它們由壓縮處理。
- 若自動壓縮失敗:
- 溢出路徑發出
Context overflow recovery failed: ... - 閾值路徑發出
Auto-compaction failed: ...
- 溢出路徑發出
- 分支摘要可以透過中止信號(例如 Escape)取消,返回已取消/已中止的導航結果。
設定與預設值
Section titled “設定與預設值”來自 settings-schema.ts:
compaction.enabled=truecompaction.reserveTokens=16384compaction.keepRecentTokens=20000compaction.autoContinue=truecompaction.remoteEndpoint=undefinedbranchSummary.enabled=falsebranchSummary.reserveTokens=16384
這些值在執行時由 AgentSession 和壓縮/分支摘要模組使用。