add File-history snapshot ids and replay summaries for file edits
This commit is contained in:
+81
-2
@@ -1159,14 +1159,35 @@ class LocalCodingAgent:
|
||||
and tool_result.metadata.get('action') != 'delegate_agent'
|
||||
):
|
||||
return None
|
||||
return {
|
||||
metadata = dict(tool_result.metadata)
|
||||
entry: dict[str, object] = {
|
||||
'timestamp': datetime.now(timezone.utc).isoformat(),
|
||||
'turn_index': turn_index,
|
||||
'tool_call_id': tool_call.id,
|
||||
'tool_name': tool_call.name,
|
||||
'ok': tool_result.ok,
|
||||
**dict(tool_result.metadata),
|
||||
'history_entry_id': f'{turn_index}:{tool_call.id}:{tool_call.name}',
|
||||
'result_preview': self._preview_text(tool_result.content, 220),
|
||||
**metadata,
|
||||
}
|
||||
action = metadata.get('action')
|
||||
path = metadata.get('path')
|
||||
if isinstance(path, str) and path:
|
||||
entry['history_kind'] = 'file_change'
|
||||
entry['changed_paths'] = [path]
|
||||
before_sha256 = metadata.get('before_sha256')
|
||||
if isinstance(before_sha256, str) and before_sha256:
|
||||
entry['before_snapshot_id'] = f'{path}:{before_sha256[:12]}'
|
||||
after_sha256 = metadata.get('after_sha256')
|
||||
if isinstance(after_sha256, str) and after_sha256:
|
||||
entry['after_snapshot_id'] = f'{path}:{after_sha256[:12]}'
|
||||
elif isinstance(metadata.get('command'), str):
|
||||
entry['history_kind'] = 'shell'
|
||||
elif action == 'delegate_agent':
|
||||
entry['history_kind'] = 'delegation'
|
||||
else:
|
||||
entry['history_kind'] = 'tool'
|
||||
return entry
|
||||
|
||||
def _compact_prefix_count(self, session: AgentSessionState) -> int:
|
||||
prefix_count = 0
|
||||
@@ -1711,6 +1732,24 @@ class LocalCodingAgent:
|
||||
if not file_history:
|
||||
return
|
||||
replay_count = len(file_history)
|
||||
unique_paths = sorted(
|
||||
{
|
||||
path
|
||||
for entry in file_history
|
||||
for path in (
|
||||
entry.get('changed_paths')
|
||||
if isinstance(entry.get('changed_paths'), list)
|
||||
else ([entry.get('path')] if isinstance(entry.get('path'), str) else [])
|
||||
)
|
||||
if isinstance(path, str) and path
|
||||
}
|
||||
)
|
||||
snapshot_count = sum(
|
||||
1
|
||||
for entry in file_history
|
||||
for key in ('before_snapshot_id', 'after_snapshot_id')
|
||||
if isinstance(entry.get(key), str) and entry.get(key)
|
||||
)
|
||||
for message in reversed(session.messages):
|
||||
if message.metadata.get('kind') != 'file_history_replay':
|
||||
continue
|
||||
@@ -1722,6 +1761,8 @@ class LocalCodingAgent:
|
||||
metadata={
|
||||
'kind': 'file_history_replay',
|
||||
'file_history_count': replay_count,
|
||||
'file_history_unique_paths': len(unique_paths),
|
||||
'file_history_snapshot_count': snapshot_count,
|
||||
},
|
||||
message_id=f'file_history_replay_{replay_count}',
|
||||
)
|
||||
@@ -1730,16 +1771,45 @@ class LocalCodingAgent:
|
||||
self,
|
||||
file_history: tuple[dict[str, object], ...],
|
||||
) -> str:
|
||||
unique_paths = sorted(
|
||||
{
|
||||
path
|
||||
for entry in file_history
|
||||
for path in (
|
||||
entry.get('changed_paths')
|
||||
if isinstance(entry.get('changed_paths'), list)
|
||||
else ([entry.get('path')] if isinstance(entry.get('path'), str) else [])
|
||||
)
|
||||
if isinstance(path, str) and path
|
||||
}
|
||||
)
|
||||
snapshot_count = sum(
|
||||
1
|
||||
for entry in file_history
|
||||
for key in ('before_snapshot_id', 'after_snapshot_id')
|
||||
if isinstance(entry.get(key), str) and entry.get(key)
|
||||
)
|
||||
lines = [
|
||||
'<system-reminder>',
|
||||
'Recent file history from this saved session:',
|
||||
f'- History entries: {len(file_history)}',
|
||||
f'- Unique changed paths: {len(unique_paths)}',
|
||||
f'- Snapshot ids: {snapshot_count}',
|
||||
]
|
||||
if unique_paths:
|
||||
preview_paths = ', '.join(unique_paths[:4])
|
||||
if len(unique_paths) > 4:
|
||||
preview_paths += f', ... (+{len(unique_paths) - 4} more)'
|
||||
lines.append(f'- Changed path preview: {preview_paths}')
|
||||
for entry in file_history[-10:]:
|
||||
action = str(entry.get('action', entry.get('tool_name', 'tool')))
|
||||
turn = entry.get('turn_index')
|
||||
path = entry.get('path')
|
||||
command = entry.get('command')
|
||||
details = [f'action={action}']
|
||||
history_entry_id = entry.get('history_entry_id')
|
||||
if isinstance(history_entry_id, str) and history_entry_id:
|
||||
details.append(f'entry_id={history_entry_id}')
|
||||
if turn is not None:
|
||||
details.append(f'turn={turn}')
|
||||
if path:
|
||||
@@ -1750,12 +1820,21 @@ class LocalCodingAgent:
|
||||
if isinstance(child_session_ids, list) and child_session_ids:
|
||||
details.append(f'child_sessions={len(child_session_ids)}')
|
||||
lines.append(f"- {'; '.join(details)}")
|
||||
before_snapshot_id = entry.get('before_snapshot_id')
|
||||
if isinstance(before_snapshot_id, str) and before_snapshot_id:
|
||||
lines.append(f' before_snapshot: {before_snapshot_id}')
|
||||
after_snapshot_id = entry.get('after_snapshot_id')
|
||||
if isinstance(after_snapshot_id, str) and after_snapshot_id:
|
||||
lines.append(f' after_snapshot: {after_snapshot_id}')
|
||||
before_preview = entry.get('before_preview')
|
||||
if isinstance(before_preview, str) and before_preview:
|
||||
lines.append(f' before: {before_preview}')
|
||||
after_preview = entry.get('after_preview')
|
||||
if isinstance(after_preview, str) and after_preview:
|
||||
lines.append(f' after: {after_preview}')
|
||||
result_preview = entry.get('result_preview')
|
||||
if isinstance(result_preview, str) and result_preview:
|
||||
lines.append(f' result: {result_preview}')
|
||||
if len(file_history) > 10:
|
||||
lines.append(f'- ... plus {len(file_history) - 10} older file-history entries')
|
||||
lines.extend(
|
||||
|
||||
+9
-1
@@ -121,7 +121,7 @@ def execute_tool_streaming(
|
||||
return
|
||||
|
||||
result = tool.execute(arguments, context)
|
||||
if name in {'list_dir', 'read_file', 'glob_search', 'grep_search'} and result.ok:
|
||||
if result.ok and result.content and name != 'delegate_agent':
|
||||
yield from _stream_static_text_result(result)
|
||||
return
|
||||
yield ToolStreamUpdate(kind='result', result=result)
|
||||
@@ -541,6 +541,9 @@ def _run_bash(arguments: dict[str, Any], context: ToolExecutionContext) -> str:
|
||||
'action': 'bash',
|
||||
'command': command,
|
||||
'exit_code': completed.returncode,
|
||||
'stdout_preview': _snapshot_text(stdout),
|
||||
'stderr_preview': _snapshot_text(stderr),
|
||||
'output_preview': _snapshot_text('\n'.join(payload).strip()),
|
||||
},
|
||||
)
|
||||
|
||||
@@ -634,6 +637,8 @@ def _stream_bash(
|
||||
'command': command,
|
||||
'exit_code': exit_code,
|
||||
'timed_out': True,
|
||||
'stdout_preview': _snapshot_text(''.join(stdout_chunks)),
|
||||
'stderr_preview': _snapshot_text(''.join(stderr_chunks)),
|
||||
},
|
||||
),
|
||||
)
|
||||
@@ -659,6 +664,9 @@ def _stream_bash(
|
||||
'command': command,
|
||||
'exit_code': exit_code,
|
||||
'streamed': True,
|
||||
'stdout_preview': _snapshot_text(stdout),
|
||||
'stderr_preview': _snapshot_text(stderr),
|
||||
'output_preview': _snapshot_text('\n'.join(payload).strip()),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user