package com.github.sormuras.bach;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.util.List;
import java.util.stream.Stream;

/** A command consisting of a tool name and a list of arguments. */
public record ToolCall(String name, List<String> arguments) {
  public static ToolCall of(String name, Object... arguments) {
    if (arguments.length == 0) return new ToolCall(name, List.of());
    if (arguments.length == 1) return new ToolCall(name, List.of(arguments[0].toString()));
    return new ToolCall(name, List.of()).with(Stream.of(arguments));
  }

  public static ToolCall of(List<String> command) {
    var size = command.size();
    if (size == 0) throw new IllegalArgumentException("Empty command");
    var name = command.get(0);
    if (size == 1) return new ToolCall(name, List.of());
    if (size == 2) return new ToolCall(name, List.of(command.get(1).trim()));
    return new ToolCall(name, List.of()).with(command.stream().skip(1).map(String::trim));
  }

  public ToolCall with(Stream<?> objects) {
    var strings = objects.map(Object::toString);
    return new ToolCall(name, Stream.concat(arguments.stream(), strings).toList());
  }

  public ToolCall with(Object argument) {
    return with(Stream.of(argument));
  }

  public ToolCall with(String key, Object value, Object... values) {
    var call = with(Stream.of(key, value));
    return values.length == 0 ? call : call.with(Stream.of(values));
  }

  public ToolCall withFindFiles(String glob) {
    return withFindFiles(Path.of(""), glob);
  }

  public ToolCall withFindFiles(Path start, String glob) {
    return withFindFiles(start, "glob", glob);
  }

  public ToolCall withFindFiles(Path start, String syntax, String pattern) {
    var syntaxAndPattern = syntax + ':' + pattern;
    var matcher = start.getFileSystem().getPathMatcher(syntaxAndPattern);
    return withFindFiles(start, Integer.MAX_VALUE, matcher);
  }

  public ToolCall withFindFiles(Path start, int maxDepth, PathMatcher matcher) {
    try (var files = Files.find(start, maxDepth, (p, a) -> matcher.matches(p))) {
      return with(files);
    } catch (Exception exception) {
      throw new RuntimeException("Find files failed in: " + start, exception);
    }
  }
}

@@ -418,38 +418,27 @@
 oolCall(name
-, List.of()
 );%0A
+
     if (argu
@@ -541,35 +541,24 @@
 oolCall(name
-, List.of()
 ).with(Strea
@@ -809,27 +809,16 @@
 all(name
-, List.of()
 );%0A    i
@@ -922,19 +922,8 @@
 name
-, List.of()
 ).wi
@@ -967,32 +967,97 @@
 g::trim));%0A  %7D%0A%0A
+  public ToolCall(String name) %7B%0A    this(name, List.of());%0A  %7D%0A%0A
   public ToolCal

Introduce zero-arguments constructor