summarizeToolResult function

List<String> summarizeToolResult(
  1. String name,
  2. String output, {
  3. required bool isError,
})

Short result lines shown under a finished tool call, unstyled except for errors.

Implementation

List<String> summarizeToolResult(String name, String output, {required bool isError}) {
  final text = output.trim();
  if (isError) {
    final message = text.startsWith('Error: ') ? text.substring(7) : text;
    if (message.startsWith('The user declined')) {
      return <String>[Style.red('User declined')];
    }
    return _fold(_nonEmptyLines(message)).map(Style.red).toList();
  }
  if (text.isEmpty) {
    return const <String>['(No content)'];
  }
  switch (name) {
    case 'read':
      final count = RegExp(r'^\s*\d+\t', multiLine: true).allMatches(text).length;
      return count == 0 ? <String>[_firstLine(text)] : <String>['Read ${_plural(count, 'line')}'];
    case 'write':
      final match = RegExp(r'^(Created|Overwrote) .* \((\d+) lines\)\.$').firstMatch(text);
      if (match != null) {
        return <String>['Wrote ${_plural(int.parse(match[2]!), 'line')}'];
      }
    case 'edit':
      final snippet = text.indexOf('\n');
      if (snippet >= 0) {
        final lines = text.substring(snippet + 1).split('\n').map((line) => line.replaceFirst('\t', '  '));
        return _fold(lines.toList()).map(Style.dim).toList();
      }
      if (text.startsWith('Replaced ')) {
        return <String>[text.substring(0, text.indexOf(' in ')).replaceFirst('Replaced', 'Updated')];
      }
    case 'bash' || 'powershell':
      return _summarizeCommand(text);
    case 'glob':
      if (text != 'No files found.') {
        return <String>['Found ${_plural(_listedLines(text), 'file')}'];
      }
    case 'grep':
      if (text != 'No matches found.') {
        return <String>['Found ${_plural(_listedLines(text), 'line')}'];
      }
  }
  return <String>[_firstLine(text)];
}