compact: compact worker をツール駆動マルチターンに再設計

段階 4〜9 を一括で実装:
- mark_read_required / add_reference / write_summary + read_file の 4 ツールで
  compact worker を駆動。結果は CompactWorkerContext に集約
- 新セッションの先頭を [summary, ...auto-read, references, ...retained] で構築
- デフォルトリファレンスは tracker.recent_files(5) から
- auto-read は compact_auto_read_budget で総量制限。超過は即エラー
- compact worker 自身は compact_worker_max_input_tokens で累計入力を制限
- 5 セクション要約フォーマットに system prompt を更新
- write_summary 未呼び出し / auto-read 空のときは 1 回追加プロンプトで促す
This commit is contained in:
2026-04-19 09:26:55 +09:00
parent 758ced5e7f
commit 34d1e78b40
7 changed files with 688 additions and 41 deletions
@@ -61,6 +61,19 @@ fn single_text_events(text: &str) -> Vec<LlmEvent> {
]
}
/// Emit a single `write_summary(text=...)` tool call as one LLM response.
fn write_summary_tool_use_events(call_id: &str, text: &str) -> Vec<LlmEvent> {
let input = serde_json::json!({ "text": text }).to_string();
vec![
LlmEvent::tool_use_start(0, call_id, "write_summary"),
LlmEvent::tool_input_delta(0, input),
LlmEvent::tool_use_stop(0),
LlmEvent::Status(StatusEvent {
status: ResponseStatus::Completed,
}),
]
}
const MINIMAL_MANIFEST_TOML: &str = r#"
[pod]
name = "test-pod"
@@ -233,10 +246,11 @@ async fn agents_md_absent_omits_trailing_section() {
#[tokio::test]
async fn agents_md_not_reread_after_compact() {
let client = MockClient::new(vec![
single_text_events("a"),
single_text_events("b"),
single_text_events("summary"),
single_text_events("c"),
single_text_events("a"), // pod.run("first")
single_text_events("b"), // pod.run("second")
write_summary_tool_use_events("call-1", "compacted summary"), // compact worker: tool_use
single_text_events("done"), // compact worker: close
single_text_events("c"), // pod.run("third")
]);
let (mut pod, pwd) = make_pod_with_body("BODY", client).await.unwrap();
let agents_path = pwd.join("AGENTS.md");
@@ -264,10 +278,11 @@ async fn agents_md_not_reread_after_compact() {
#[tokio::test]
async fn compact_preserves_system_prompt() {
let client = MockClient::new(vec![
single_text_events("a"),
single_text_events("b"),
single_text_events("summary"),
single_text_events("c"),
single_text_events("a"), // pod.run("first")
single_text_events("b"), // pod.run("second")
write_summary_tool_use_events("call-1", "compacted summary"), // compact worker: tool_use
single_text_events("done"), // compact worker: close
single_text_events("c"), // pod.run("third")
]);
let (mut pod, _pwd) = make_pod_with_body("SP cwd={{ cwd }}", client)
.await