summaryrefslogtreecommitdiff
path: root/src/Agent.Windows
diff options
context:
space:
mode:
Diffstat (limited to 'src/Agent.Windows')
-rw-r--r--src/Agent.Windows/Tools/WindowsToolBackend.cs28
1 files changed, 22 insertions, 6 deletions
diff --git a/src/Agent.Windows/Tools/WindowsToolBackend.cs b/src/Agent.Windows/Tools/WindowsToolBackend.cs
index c432894..5cbf853 100644
--- a/src/Agent.Windows/Tools/WindowsToolBackend.cs
+++ b/src/Agent.Windows/Tools/WindowsToolBackend.cs
@@ -97,6 +97,13 @@ public sealed class WindowsToolBackend(WindowsSandboxSettings settings, ISecurit
ErrorCode: ex.Code, ErrorCategory: ex.Category, TargetPath: ex.TargetPath,
RequiredPermission: ex.RequiredPermission, Resolution: ex.Resolution));
}
+ catch (Exception ex) when (ex is ToolValidationException or JsonException or InvalidOperationException)
+ {
+ return Task.FromResult(new ToolExecutionResult(false, ex.Message, false,
+ $"{toolName}:tool.input_invalid:{ex.Message}", RetryAllowed: true,
+ ErrorCode: "tool.input_invalid", ErrorCategory: "tool",
+ Resolution: "Correct the Tool arguments using the published schema and retry."));
+ }
}
public async Task EndTaskAsync(Guid taskId, bool success, CancellationToken cancellationToken)
@@ -300,12 +307,21 @@ public sealed class WindowsToolBackend(WindowsSandboxSettings settings, ISecurit
private static string ApplyPatch(string path, string patch)
{
string current = File.Exists(path) ? File.ReadAllText(path) : string.Empty;
- using JsonDocument document = JsonDocument.Parse(patch);
- string oldText = document.RootElement.GetProperty("old_text").GetString()!;
- string newText = document.RootElement.GetProperty("new_text").GetString()!;
- int first = current.IndexOf(oldText, StringComparison.Ordinal);
- if (first < 0 || current.IndexOf(oldText, first + oldText.Length, StringComparison.Ordinal) >= 0) throw new InvalidOperationException("Patch old_text must match exactly once.");
- return current[..first] + newText + current[(first + oldText.Length)..];
+ JsonDocument document;
+ try { document = JsonDocument.Parse(patch); }
+ catch (JsonException) { throw new ToolValidationException("Patch must be a JSON object string containing old_text and new_text; unified diff is unsupported."); }
+ using (document)
+ {
+ if (document.RootElement.ValueKind != JsonValueKind.Object ||
+ !document.RootElement.TryGetProperty("old_text", out JsonElement oldElement) || oldElement.ValueKind != JsonValueKind.String ||
+ !document.RootElement.TryGetProperty("new_text", out JsonElement newElement) || newElement.ValueKind != JsonValueKind.String)
+ throw new ToolValidationException("Patch must be a JSON object string containing string old_text and new_text fields.");
+ string oldText = oldElement.GetString()!;
+ string newText = newElement.GetString()!;
+ int first = current.IndexOf(oldText, StringComparison.Ordinal);
+ if (first < 0 || current.IndexOf(oldText, first + oldText.Length, StringComparison.Ordinal) >= 0) throw new InvalidOperationException("Patch old_text must match exactly once.");
+ return current[..first] + newText + current[(first + oldText.Length)..];
+ }
}
private sealed class TaskContext(TaskResourceJournal journal, TaskAclManager acl, Guid sessionId)