Fix ACD turn summary loss and add /dump command

ACD (Aggressive Context Dehydration) fixes:
- Fixed dehydrate_context() to extract turn summary from context window
  instead of using the passed-in final_response (which contained only
  the timing footer, not the actual LLM response)
- Removed final_response parameter from dehydrate_context() since it
  now self-extracts the last assistant message as the summary
- This ensures the actual turn summary is preserved after dehydration,
  not just the timing footer

New /dump command:
- Added /dump command to dump entire context window to tmp/ for debugging
- Shows message index, role, kind, content length, and full content
- Available in both console and machine modes

UTF-8 safety:
- Fixed truncate_to_word_boundary() to use character indices instead of
  byte indices, preventing panics on multi-byte UTF-8 characters
- Added UTF-8 string slicing guidance to AGENTS.md

Agent: g3
This commit is contained in:
Dhanji R. Prasanna
2026-01-12 05:13:02 +05:30
parent ac17b95b24
commit f415dbb84b
14 changed files with 1771 additions and 27 deletions

View File

@@ -288,6 +288,22 @@ fn create_core_tools(exclude_research: bool) -> Vec<Tool> {
}),
});
// ACD rehydration tool
tools.push(Tool {
name: "rehydrate".to_string(),
description: "Restore dehydrated conversation history from a previous context segment. Use this when you see a DEHYDRATED CONTEXT stub and need to recall the full conversation details from that segment.".to_string(),
input_schema: json!({
"type": "object",
"properties": {
"fragment_id": {
"type": "string",
"description": "The fragment ID to restore (from a DEHYDRATED CONTEXT stub message)"
}
},
"required": ["fragment_id"]
}),
});
tools
}
@@ -495,7 +511,7 @@ mod tests {
// write_file, str_replace, take_screenshot,
// todo_read, todo_write, code_coverage, code_search, research, remember
// (13 total - memory is auto-loaded, only remember tool needed)
assert_eq!(tools.len(), 13);
assert_eq!(tools.len(), 14);
}
#[test]
@@ -509,7 +525,7 @@ mod tests {
fn test_create_tool_definitions_core_only() {
let config = ToolConfig::default();
let tools = create_tool_definitions(config);
assert_eq!(tools.len(), 13);
assert_eq!(tools.len(), 14);
}
#[test]
@@ -517,7 +533,7 @@ mod tests {
let config = ToolConfig::new(true, true);
let tools = create_tool_definitions(config);
// 13 core + 15 webdriver = 28
assert_eq!(tools.len(), 28);
assert_eq!(tools.len(), 29);
}
#[test]
@@ -535,8 +551,8 @@ mod tests {
let tools_with_research = create_core_tools(false);
let tools_without_research = create_core_tools(true);
assert_eq!(tools_with_research.len(), 13);
assert_eq!(tools_without_research.len(), 12);
assert_eq!(tools_with_research.len(), 14);
assert_eq!(tools_without_research.len(), 13);
assert!(tools_with_research.iter().any(|t| t.name == "research"));
assert!(!tools_without_research.iter().any(|t| t.name == "research"));