Skip to content

Commit 96a6dc0

Browse files
javiercnCopilot
andcommitted
refactor(dotnet): simplify mixed approval handling
Keep the existing approval flow unchanged and use RequiresConfirmation only to unwrap collateral server calls. Co-authored-by: Copilot App <[email protected]>
1 parent 938c1e9 commit 96a6dc0

13 files changed

Lines changed: 148 additions & 814 deletions

‎sdks/dotnet/src/AGUI.Abstractions/Extensions/AGUIToolExtensions.cs‎

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
using System.Collections.Generic;
22
using System.Linq;
3-
using System.Threading;
4-
using System.Threading.Tasks;
53
using Microsoft.Extensions.AI;
64

75
namespace AGUI.Abstractions;
@@ -40,9 +38,8 @@ public static IEnumerable<AGUITool> AsAGUITools(this IEnumerable<AITool> tools)
4038
}
4139

4240
/// <summary>
43-
/// Converts a sequence of <see cref="AGUITool"/> instances to invocable <see cref="AIFunction"/> proxies.
44-
/// The actual implementation remains on the client side; the proxies are intended to be wrapped with
45-
/// <see cref="ApprovalRequiredAIFunction"/> before they are supplied to a function-invoking chat client.
41+
/// Converts a sequence of <see cref="AGUITool"/> instances to <see cref="AITool"/> declarations.
42+
/// These are declaration-only and cannot be invoked, as the actual implementation exists on the client side.
4643
/// </summary>
4744
/// <param name="tools">The AG-UI tool definitions.</param>
4845
/// <returns>A sequence of <see cref="AITool"/> declarations.</returns>
@@ -60,31 +57,10 @@ private static IEnumerable<AITool> ConvertTools(IList<AGUITool> tools)
6057
{
6158
foreach (var tool in tools)
6259
{
63-
yield return new ClientToolAIFunction(tool);
64-
}
65-
}
66-
67-
private sealed class ClientToolAIFunction : AIFunction
68-
{
69-
private readonly AGUITool _tool;
70-
71-
internal ClientToolAIFunction(AGUITool tool)
72-
{
73-
_tool = tool;
74-
}
75-
76-
public override string Name => _tool.Name;
77-
78-
public override string Description => _tool.Description ?? string.Empty;
79-
80-
public override System.Text.Json.JsonElement JsonSchema => _tool.Parameters;
81-
82-
protected override ValueTask<object?> InvokeCoreAsync(
83-
AIFunctionArguments arguments,
84-
CancellationToken cancellationToken)
85-
{
86-
return new ValueTask<object?>(Task.FromException<object?>(
87-
new InvalidOperationException($"Client tool '{Name}' cannot be invoked on the server without a client-produced result.")));
60+
yield return AIFunctionFactory.CreateDeclaration(
61+
name: tool.Name,
62+
description: tool.Description,
63+
jsonSchema: tool.Parameters);
8864
}
8965
}
9066
}

‎sdks/dotnet/src/AGUI.Server/AGUI.Server.csproj‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
</ItemGroup>
1818

1919
<ItemGroup>
20-
<PackageReference Include="Microsoft.Extensions.AI" />
20+
<PackageReference Include="Microsoft.Extensions.AI.Abstractions" />
2121
</ItemGroup>
2222

2323
</Project>

‎sdks/dotnet/src/AGUI.Server/ChatResponseUpdateAGUIExtensions.cs‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -464,16 +464,17 @@ private static async IAsyncEnumerable<BaseEvent> CoreAsync(
464464

465465
yield return ToolCallEndEvent.Create(toolCall.CallId, raw);
466466

467-
// Client tools are always represented to FICC as approval-required proxies,
468-
// so unwrap their approval requests back into ordinary AG-UI tool calls.
467+
// A client tool is owned and gated by the client, never the server. Always
468+
// surface its call as a plain TOOL_CALL (the run finishes with success) so
469+
// the client executes it — including when the model re-invokes it on a
470+
// continuation (where it arrives wrapped as an approval request).
469471
if (clientToolNames.Contains(toolCall.Name))
470472
{
471473
break;
472474
}
473475

474-
// FICC wraps every peer in a mixed batch when one function requires approval.
475-
// A false value identifies a collateral server call: unwrap it so clients can
476-
// preserve the call as informational history without prompting for approval.
476+
// FICC also wraps server calls when a peer requires approval. Those collateral
477+
// calls don't require confirmation, so unwrap them without prompting.
477478
#pragma warning disable MEAI001
478479
if (!ar.RequiresConfirmation)
479480
#pragma warning restore MEAI001

‎sdks/dotnet/src/AGUI.Server/Internal/ClientResultAIFunction.cs‎

Lines changed: 0 additions & 42 deletions
This file was deleted.

0 commit comments

Comments
 (0)