diff options
Diffstat (limited to 'tests/Agent.Core.Tests/PromptAndRuntimeTests.cs')
| -rw-r--r-- | tests/Agent.Core.Tests/PromptAndRuntimeTests.cs | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/tests/Agent.Core.Tests/PromptAndRuntimeTests.cs b/tests/Agent.Core.Tests/PromptAndRuntimeTests.cs index 23ad2d2..c3c634d 100644 --- a/tests/Agent.Core.Tests/PromptAndRuntimeTests.cs +++ b/tests/Agent.Core.Tests/PromptAndRuntimeTests.cs @@ -144,6 +144,29 @@ public sealed class PromptAndRuntimeTests Assert.Contains("iteration limit", failed.Result, StringComparison.OrdinalIgnoreCase); } + [Fact] + public async Task Runtime_does_not_retry_a_sandbox_policy_denial() + { + TaskRegistry registry = new(); + var backend = new UnauthorizedBackend(); + var dispatcher = new InternalToolDispatcher( + new DenyByDefaultPolicy(new HashSet<string>(["file_search"], StringComparer.Ordinal)), backend); + var ollama = new FileSearchOllamaClient(); + var runtime = new AgentRuntime(registry, ollama, new AgentRuntimeSettings("", "en", [], "sandbox"), dispatcher); + TaskSnapshot task = registry.Enqueue("research regional curry", null, null); + registry.Transition(task.TaskId, AgentTaskState.Planning); + registry.Transition(task.TaskId, AgentTaskState.Running); + + await runtime.ExecuteAsync(task.TaskId, TestContext.Current.CancellationToken); + + Assert.True(registry.TryGet(task.TaskId, null, out TaskSnapshot? failed)); + Assert.Equal(AgentTaskState.Failed, failed!.State); + Assert.Contains("denied by sandbox policy", failed.Result, StringComparison.OrdinalIgnoreCase); + Assert.Contains("not approved for Read", failed.Result, StringComparison.OrdinalIgnoreCase); + Assert.Equal(1, ollama.CallCount); + Assert.Equal(1, backend.CallCount); + } + private sealed class RecordingOllamaClient : IOllamaClient { public List<IReadOnlyList<OllamaMessage>> Calls { get; } = []; @@ -217,4 +240,30 @@ public sealed class PromptAndRuntimeTests return Task.FromResult(new OllamaResult("", 1, 1, [new OllamaToolCall(new OllamaFunctionCall("process_run", arguments.RootElement.Clone()))])); } } + + private sealed class UnauthorizedBackend : IInternalToolBackend + { + public int CallCount { get; private set; } + + public Task<ToolExecutionResult> ExecuteAsync(Guid taskId, string toolName, JsonElement arguments, CancellationToken cancellationToken) + { + CallCount++; + throw new UnauthorizedAccessException("'C:\\Users' is not approved for Read."); + } + } + + private sealed class FileSearchOllamaClient : IOllamaClient + { + public int CallCount { get; private set; } + + public Task<OllamaResult> ChatAsync(IReadOnlyList<OllamaMessage> messages, double? temperatureOverride, CancellationToken cancellationToken) => + Task.FromResult(new OllamaResult("unexpected", 1, 1)); + + public Task<OllamaResult> ChatWithToolsAsync(IReadOnlyList<OllamaMessage> messages, double? temperatureOverride, IReadOnlyList<InternalToolDefinition> tools, CancellationToken cancellationToken) + { + CallCount++; + using JsonDocument arguments = JsonDocument.Parse("""{"root":"C:\\Users","mode":"name","query":"*.txt"}"""); + return Task.FromResult(new OllamaResult("", 1, 1, [new OllamaToolCall(new OllamaFunctionCall("file_search", arguments.RootElement.Clone()))])); + } + } } |
