using System.IO; using System.Linq; using System.Text.Json; namespace AxCopilot.Services.Agent; public sealed class TaskStopTool : IAgentTool { public string Name => "task_stop"; public string Description => "Stop a task (marks status=stopped) on the workspace task board."; public ToolParameterSchema Parameters => new() { Properties = new() { ["id"] = new() { Type = "integer", Description = "Task id" }, ["reason"] = new() { Type = "string", Description = "Stop reason (optional)." } }, Required = ["id"] }; public Task ExecuteAsync(JsonElement args, AgentContext context, CancellationToken ct = default) { if (!args.SafeTryGetProperty("id", out var idEl)) return Task.FromResult(ToolResult.Fail("id is required.")); if (string.IsNullOrWhiteSpace(context.WorkFolder) || !Directory.Exists(context.WorkFolder)) return Task.FromResult(ToolResult.Fail("valid WorkFolder is required.")); var id = idEl.GetInt32(); var reason = args.SafeTryGetProperty("reason", out var reasonEl) ? (reasonEl.SafeGetString() ?? "").Trim() : ""; var tasks = TaskBoardStore.Load(context.WorkFolder); var task = tasks.FirstOrDefault(t => t.Id == id); if (task == null) return Task.FromResult(ToolResult.Fail($"Task #{id} not found.")); task.Status = "stopped"; if (!string.IsNullOrWhiteSpace(reason)) task.Output = string.IsNullOrWhiteSpace(task.Output) ? $"stop reason: {reason}" : $"{task.Output}\nstop reason: {reason}"; task.UpdatedAt = DateTime.Now; TaskBoardStore.Save(context.WorkFolder, tasks); return Task.FromResult(ToolResult.Ok($"Stopped task #{task.Id}: {task.Title}")); } }