using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; namespace StellaOps.Interop; public sealed partial class ToolManager { private readonly string _workDir; private readonly IToolPathResolver _pathResolver; private readonly IToolProcessRunner _processRunner; public ToolManager( string workDir, IReadOnlyDictionary? toolPaths = null, IToolPathResolver? pathResolver = null, IToolProcessRunner? processRunner = null) { _workDir = workDir; var resolvedPaths = toolPaths ?? new Dictionary(StringComparer.OrdinalIgnoreCase); _pathResolver = pathResolver ?? new ToolPathResolver(resolvedPaths); _processRunner = processRunner ?? new ToolProcessRunner(); } public async Task VerifyToolAsync(string tool, string args, CancellationToken ct = default) { var result = await RunAsync(tool, args, ct).ConfigureAwait(false); if (!result.Success) { throw new ToolExecutionException( $"Tool '{tool}' not available or failed to run.", result); } } public async Task RunAsync(string tool, string args, CancellationToken ct = default) { var toolPath = _pathResolver.ResolveToolPath(tool); if (toolPath is null) { return ToolResult.Failed($"Tool not found: {tool}"); } return await _processRunner.RunAsync(tool, toolPath, args, _workDir, ct).ConfigureAwait(false); } public bool IsToolAvailable(string tool) => _pathResolver.ResolveToolPath(tool) is not null; public string? ResolveToolPath(string tool) => _pathResolver.ResolveToolPath(tool); }