mirror of
https://github.com/davidkaya/aryx.git
synced 2026-08-07 04:08:45 +02:00
feat: enable 'always approve for session' for runtime tools
Runtime tool permission requests (read, write, shell, store_memory) now resolve stable approval names via fallback in the sidecar approval coordinator, enabling the 'Always approve' button and session-level auto-approval for built-in tools. Backend: - Add fallback tool names for PermissionRequestRead (read), PermissionRequestWrite (write), PermissionRequestShell (shell), and PermissionRequestMemory (store_memory) - Add autoApprovedToolName parameter to RequiresToolCallApproval for permission-kind-based session approval matching - Track tool.execution_start events in ToolNamesByCallId for supplementary exact-name resolution Frontend: - Use approval.toolName ?? approval.permissionKind as fallback key in resolveSessionApproval and ApprovalBanner - Add shell, read, write permission-kind entries to builtin approval tool definitions so pruning preserves session overrides Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -58,6 +58,31 @@ public sealed class CopilotTurnExecutionStateTests
|
||||
Assert.Equal("agent-1", observedAgent.AgentId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ObserveSessionEvent_ToolExecutionStart_TracksToolNameByCallId()
|
||||
{
|
||||
RunTurnCommandDto command = CreateCommand();
|
||||
CopilotTurnExecutionState state = new(command);
|
||||
|
||||
state.ObserveSessionEvent(
|
||||
command.Pattern.Agents[0],
|
||||
SessionEvent.FromJson(
|
||||
"""
|
||||
{
|
||||
"type": "tool.execution_start",
|
||||
"data": {
|
||||
"toolCallId": "tool-call-1",
|
||||
"toolName": "view"
|
||||
},
|
||||
"id": "33333333-3333-3333-3333-333333333333",
|
||||
"timestamp": "2026-03-27T00:00:00Z"
|
||||
}
|
||||
"""));
|
||||
|
||||
Assert.True(state.ToolNamesByCallId.TryGetValue("tool-call-1", out string? toolName));
|
||||
Assert.Equal("view", toolName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EmitThinkingIfNeeded_DoesNotDuplicateQueuedThinkingActivity()
|
||||
{
|
||||
|
||||
@@ -766,7 +766,29 @@ public sealed class CopilotWorkflowRunnerTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TryGetApprovalToolName_ReadsMcpCustomAndHookRequests()
|
||||
public void RequiresToolCallApproval_HonorsRuntimeApprovalAliases()
|
||||
{
|
||||
ApprovalPolicyDto policy = new()
|
||||
{
|
||||
Rules =
|
||||
[
|
||||
new ApprovalCheckpointRuleDto
|
||||
{
|
||||
Kind = "tool-call",
|
||||
AgentIds = ["agent-1"],
|
||||
},
|
||||
],
|
||||
AutoApprovedToolNames = ["read", "store_memory"],
|
||||
};
|
||||
|
||||
Assert.False(CopilotApprovalCoordinator.RequiresToolCallApproval(policy, "agent-1", "view", "read"));
|
||||
Assert.False(CopilotApprovalCoordinator.RequiresToolCallApproval(policy, "agent-1", "remember_fact", "store_memory"));
|
||||
Assert.True(CopilotApprovalCoordinator.RequiresToolCallApproval(policy, "agent-1", "write_file", "write"));
|
||||
Assert.True(CopilotApprovalCoordinator.RequiresToolCallApproval(policy, "agent-1", "git.status"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TryGetApprovalToolName_ResolvesDirectNamesAndRuntimeFallbacks()
|
||||
{
|
||||
Assert.True(
|
||||
CopilotApprovalCoordinator.TryGetApprovalToolName(
|
||||
@@ -804,7 +826,7 @@ public sealed class CopilotWorkflowRunnerTests
|
||||
out string? hookToolName));
|
||||
Assert.Equal("web_fetch", hookToolName);
|
||||
|
||||
Assert.False(
|
||||
Assert.True(
|
||||
CopilotApprovalCoordinator.TryGetApprovalToolName(
|
||||
new PermissionRequestShell
|
||||
{
|
||||
@@ -818,7 +840,49 @@ public sealed class CopilotWorkflowRunnerTests
|
||||
CanOfferSessionApproval = false,
|
||||
},
|
||||
out string? shellToolName));
|
||||
Assert.Null(shellToolName);
|
||||
Assert.Equal("shell", shellToolName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TryGetApprovalToolName_FallsBackToRuntimeApprovalAliasesWhenLookupMissing()
|
||||
{
|
||||
Assert.True(
|
||||
CopilotApprovalCoordinator.TryGetApprovalToolName(
|
||||
new PermissionRequestRead
|
||||
{
|
||||
Kind = "read",
|
||||
ToolCallId = "tool-call-read",
|
||||
Intention = "Inspect a file",
|
||||
Path = "README.md",
|
||||
},
|
||||
out string? readToolName));
|
||||
Assert.Equal("read", readToolName);
|
||||
|
||||
Assert.True(
|
||||
CopilotApprovalCoordinator.TryGetApprovalToolName(
|
||||
new PermissionRequestWrite
|
||||
{
|
||||
Kind = "write",
|
||||
ToolCallId = "tool-call-write",
|
||||
Intention = "Update a file",
|
||||
FileName = "README.md",
|
||||
Diff = "@@ -1 +1 @@",
|
||||
},
|
||||
out string? writeToolName));
|
||||
Assert.Equal("write", writeToolName);
|
||||
|
||||
Assert.True(
|
||||
CopilotApprovalCoordinator.TryGetApprovalToolName(
|
||||
new PermissionRequestMemory
|
||||
{
|
||||
Kind = "memory",
|
||||
ToolCallId = "tool-call-memory",
|
||||
Subject = "repo conventions",
|
||||
Fact = "Use Bun for script execution.",
|
||||
Citations = "package.json",
|
||||
},
|
||||
out string? memoryToolName));
|
||||
Assert.Equal("store_memory", memoryToolName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user