akseljoonas HF Staff Claude Opus 4.6 (1M context) commited on
Commit
06d26aa
·
1 Parent(s): 950ca5c

Add deterministic pruning of old tool outputs before LLM compaction

Browse files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

agent/context_manager/manager.py CHANGED
@@ -221,10 +221,51 @@ class ContextManager:
221
 
222
  return False
223
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
  async def compact(
225
  self, model_name: str, tool_specs: list[dict] | None = None
226
  ) -> None:
227
  """Remove old messages to keep history under target size"""
 
 
228
  if (self.context_length <= self.max_context) or not self.items:
229
  return
230
 
 
221
 
222
  return False
223
 
224
+ def prune_old_tool_outputs(self) -> None:
225
+ """Stage 1 compaction: deterministically truncate old tool outputs.
226
+
227
+ For any tool message older than the last 6 messages, replace content
228
+ exceeding 500 chars with a short one-line summary preserving
229
+ tool_call_id and name.
230
+ """
231
+ if len(self.items) <= 6:
232
+ return
233
+
234
+ cutoff = len(self.items) - 6
235
+ for i in range(cutoff - 1, -1, -1):
236
+ msg = self.items[i]
237
+ if getattr(msg, "role", None) != "tool":
238
+ continue
239
+ content = getattr(msg, "content", None) or ""
240
+ if len(content) <= 500:
241
+ continue
242
+
243
+ tool_name = getattr(msg, "name", None) or "tool"
244
+ preview = content[:80]
245
+ total = len(content)
246
+
247
+ if tool_name == "hf_jobs":
248
+ summary = f"[hf_jobs: {preview}... ({total} chars)]"
249
+ elif tool_name == "bash":
250
+ # Try to extract exit_code from content
251
+ exit_code_part = ""
252
+ if "exit_code" in content[:200]:
253
+ for line in content[:200].splitlines():
254
+ if "exit_code" in line:
255
+ exit_code_part = f"exit_code visible if present, "
256
+ break
257
+ summary = f"[bash: {exit_code_part}{preview}... ({total} chars)]"
258
+ else:
259
+ summary = f"[{tool_name}: {preview}... ({total} chars)]"
260
+
261
+ msg.content = summary
262
+
263
  async def compact(
264
  self, model_name: str, tool_specs: list[dict] | None = None
265
  ) -> None:
266
  """Remove old messages to keep history under target size"""
267
+ self.prune_old_tool_outputs()
268
+
269
  if (self.context_length <= self.max_context) or not self.items:
270
  return
271
 
agent/core/agent_loop.py CHANGED
@@ -199,6 +199,7 @@ def _is_transient_error(error: Exception) -> bool:
199
 
200
  async def _compact_and_notify(session: Session) -> None:
201
  """Run compaction and send event if context was reduced."""
 
202
  old_length = session.context_manager.context_length
203
  tool_specs = session.tool_router.get_tool_specs_for_llm()
204
  await session.context_manager.compact(
 
199
 
200
  async def _compact_and_notify(session: Session) -> None:
201
  """Run compaction and send event if context was reduced."""
202
+ session.context_manager.prune_old_tool_outputs()
203
  old_length = session.context_manager.context_length
204
  tool_specs = session.tool_router.get_tool_specs_for_llm()
205
  await session.context_manager.compact(