Skip to content

Commit 3468f76

Browse files
committed
Version 1.0.0-preview.260115.1
1 parent 3537bcb commit 3468f76

File tree

11 files changed

+303
-93
lines changed

11 files changed

+303
-93
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Changelog - Agent Framework Toolkit
22

3-
## Unreleased
3+
## Version 1.0.0-preview.260115.1
4+
- Google: [BREAKING] Switched to the official Google NuGet Package (only breaking in Connection part if Google Vertex is used)
5+
- Google: Added GoogleEmbeddingFactory
6+
- Google: Added`ThinkingLevel` and `IncludeThoughts` in options
47
- `.RunAsync<T>(...)` in AIAgentExtensions now used provided serializationOptions (if given); only creating it's own if null.
58
- `.RunAsync<T>(...)` now support List/Array as T (using similar object wrapping technique as Microsoft.Extensions.AI)
69
- AzureOpenAI: Added Auto-correction of the Endpoint if you by mistake give the entire foundry url 'https://[name].services.ai.azure.com/api/projects/[project]' by on the fly correcting it to 'https://[name].services.ai.azure.com'. This is on by default, but can be turned off by setting property `AutoCorrectFoundryEndpoint` to false

Directory.Packages.props

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,35 @@
11
<Project>
2-
<!-- Enable Central Package Management for all src projects -->
3-
<PropertyGroup>
4-
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
5-
</PropertyGroup>
6-
<ItemGroup>
7-
<!-- Microsoft Agents AI Framework -->
8-
<PackageVersion Include="Microsoft.Agents.AI" Version="1.0.0-preview.260108.1" />
9-
<PackageVersion Include="Microsoft.Agents.AI.OpenAI" Version="1.0.0-preview.260108.1" />
10-
<PackageVersion Include="Microsoft.Agents.AI.Anthropic" Version="1.0.0-preview.260108.1" />
11-
<!-- Azure -->
12-
<PackageVersion Include="Azure.Identity" Version="1.17.1" />
13-
<PackageVersion Include="Azure.AI.OpenAI" Version="2.8.0-beta.1" />
14-
<PackageVersion Include="Azure.AI.Inference" Version="1.0.0-beta.5" />
15-
<PackageVersion Include="Microsoft.Extensions.AI.Abstractions" Version="10.1.1" />
16-
<PackageVersion Include="Microsoft.Extensions.AI.AzureAIInference" Version="10.0.0-preview.1.25559.3" />
17-
<!-- Third-party AI SDKs -->
18-
<PackageVersion Include="Google_GenerativeAI.Microsoft" Version="3.6.1" />
19-
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.1" />
20-
<PackageVersion Include="Mistral.SDK" Version="2.3.1" />
21-
<PackageVersion Include="ModelContextProtocol" Version="0.5.0-preview.1" />
22-
<!-- Code analysis -->
23-
<PackageVersion Include="JetBrains.Annotations" Version="2025.2.4" />
24-
<!-- Testing -->
25-
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
26-
<PackageVersion Include="xunit.v3" Version="3.2.1" />
27-
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
28-
<PackageVersion Include="OpenTelemetry" Version="1.14.0" />
29-
<PackageVersion Include="OpenTelemetry.Exporter.Console" Version="1.14.0" />
30-
<!-- Secrets -->
31-
<PackageVersion Include="Microsoft.Extensions.Configuration.UserSecrets" Version="10.0.1" />
32-
<!-- SourceLink for symbol packages -->
33-
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
34-
</ItemGroup>
35-
</Project>
2+
<!-- Enable Central Package Management for all src projects -->
3+
<PropertyGroup>
4+
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
5+
</PropertyGroup>
6+
<ItemGroup>
7+
<!-- Microsoft Agents AI Framework -->
8+
<PackageVersion Include="Microsoft.Agents.AI" Version="1.0.0-preview.260108.1" />
9+
<PackageVersion Include="Microsoft.Agents.AI.OpenAI" Version="1.0.0-preview.260108.1" />
10+
<PackageVersion Include="Microsoft.Agents.AI.Anthropic" Version="1.0.0-preview.260108.1" />
11+
<!-- Azure -->
12+
<PackageVersion Include="Azure.Identity" Version="1.17.1" />
13+
<PackageVersion Include="Azure.AI.OpenAI" Version="2.8.0-beta.1" />
14+
<PackageVersion Include="Azure.AI.Inference" Version="1.0.0-beta.5" />
15+
<PackageVersion Include="Microsoft.Extensions.AI.Abstractions" Version="10.2.0" />
16+
<PackageVersion Include="Microsoft.Extensions.AI.AzureAIInference" Version="10.0.0-preview.1.25559.3" />
17+
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.2" />
18+
<!-- Third-party AI SDKs -->
19+
<PackageVersion Include="Google.GenAI" Version="0.11.0" />
20+
<PackageVersion Include="Mistral.SDK" Version="2.3.1" />
21+
<PackageVersion Include="ModelContextProtocol" Version="0.6.0-preview.1" />
22+
<!-- Code analysis -->
23+
<PackageVersion Include="JetBrains.Annotations" Version="2025.2.4" />
24+
<!-- Testing -->
25+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
26+
<PackageVersion Include="xunit.v3" Version="3.2.2" />
27+
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
28+
<PackageVersion Include="OpenTelemetry" Version="1.14.0" />
29+
<PackageVersion Include="OpenTelemetry.Exporter.Console" Version="1.14.0" />
30+
<!-- Secrets -->
31+
<PackageVersion Include="Microsoft.Extensions.Configuration.UserSecrets" Version="10.0.2" />
32+
<!-- SourceLink for symbol packages -->
33+
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="10.0.102" />
34+
</ItemGroup>
35+
</Project>

development/Tests/GoogleTests.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using AgentFrameworkToolkit.Google;
2+
using AgentFrameworkToolkit.OpenAI;
3+
using Microsoft.Extensions.AI;
24
using Microsoft.Extensions.DependencyInjection;
35
using Secrets;
46

@@ -18,6 +20,9 @@ public sealed class GoogleTests : TestsBase
1820
[Fact]
1921
public Task AgentFactory_ToolCall() => ToolCallAgentTestsAsync(AgentProvider.Google);
2022

23+
[Fact]
24+
public Task AgentFactory_McpToolCall() => McpToolCallAgentTestsAsync(AgentProvider.Google);
25+
2126
[Fact]
2227
public Task AgentFactory_StructuredOutput() => StructuredOutputAgentTestsAsync(AgentProvider.Google);
2328

@@ -55,4 +60,30 @@ public async Task AgentFactory_DependencyInjection_Connection()
5560
.RunAsync("Hello", cancellationToken: cancellationToken)).Text;
5661
Assert.NotEmpty(text);
5762
}
63+
64+
[Fact]
65+
public async Task EmbeddingFactory()
66+
{
67+
Secrets.Secrets secrets = SecretsManager.GetSecrets();
68+
GoogleEmbeddingFactory factory = new(secrets.GoogleGeminiApiKey);
69+
IEmbeddingGenerator<string, Embedding<float>> generator = factory.GetEmbeddingGenerator(GoogleEmbeddingModels.GoogleEmbedding001);
70+
Embedding<float> embedding = await generator.GenerateAsync("Hello", cancellationToken: TestContext.Current.CancellationToken);
71+
Assert.Equal(3072, embedding.Dimensions);
72+
}
73+
74+
[Fact]
75+
public async Task EmbeddingFactory_DependencyInjection()
76+
{
77+
var secrets = SecretsManager.GetSecrets();
78+
ServiceCollection services = new();
79+
services.AddGoogleEmbeddingFactory(secrets.GoogleGeminiApiKey);
80+
81+
ServiceProvider provider = services.BuildServiceProvider();
82+
83+
GoogleEmbeddingFactory embeddingFactory = provider.GetRequiredService<GoogleEmbeddingFactory>();
84+
var cancellationToken = TestContext.Current.CancellationToken;
85+
Embedding<float> embedding = await embeddingFactory.GetEmbeddingGenerator(GoogleEmbeddingModels.GoogleEmbedding001)
86+
.GenerateAsync("Hello", cancellationToken: cancellationToken);
87+
Assert.Equal(3072, embedding.Dimensions);
88+
}
5889
}

development/Tests/TestBase.cs

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -124,16 +124,8 @@ protected async Task ToolCallAgentTestsAsync(AgentProvider provider)
124124
ToolCallingMiddlewareCity = null;
125125
AIAgent agent = await GetAgentForScenarioAsync(provider, AgentScenario.ToolCall, testLogger);
126126
AgentRunResponse response = await agent.RunAsync("What is the weather like in Paris", cancellationToken: TestContext.Current.CancellationToken);
127-
switch (provider)
128-
{
129-
case AgentProvider.Google:
130-
Assert.Single(response.Messages); //Do not give tool call details back
131-
break;
132-
default:
133-
Assert.Single(response.Messages.Where(x => x.Role == ChatRole.Tool).ToList());
134-
Assert.Equal(3, response.Messages.Count);
135-
break;
136-
}
127+
Assert.Single(response.Messages.Where(x => x.Role == ChatRole.Tool).ToList());
128+
Assert.Equal(3, response.Messages.Count);
137129

138130
Assert.Contains("SUNNY", response.Text.ToUpperInvariant());
139131
Assert.Contains("19", response.Text);
@@ -145,16 +137,7 @@ protected async Task McpToolCallAgentTestsAsync(AgentProvider provider)
145137
TestLoggerFactory testLogger = new();
146138
AIAgent agent = await GetAgentForScenarioAsync(provider, AgentScenario.McpToolCall, testLogger);
147139
AgentRunResponse response = await agent.RunAsync("Call the 'getting_started' tool to find what URL the nuget is on", cancellationToken: TestContext.Current.CancellationToken);
148-
switch (provider)
149-
{
150-
case AgentProvider.Google:
151-
Assert.Single(response.Messages); //Do not give tool call details back
152-
break;
153-
default:
154-
Assert.True(response.Messages.Count(x => x.Role == ChatRole.Tool) > 0);
155-
break;
156-
}
157-
140+
Assert.True(response.Messages.Count(x => x.Role == ChatRole.Tool) > 0);
158141
Assert.Contains("www.nuget.org/packages/TrelloDotNet".ToUpperInvariant(), response.Text.ToUpperInvariant());
159142
}
160143

@@ -552,6 +535,7 @@ Task<GoogleAgentOptions> GetGoogleAgentOptions(string model)
552535
Tools = tools,
553536
LoggerFactory = testLogger,
554537
Instructions = TestInstructions,
538+
Services = serviceProvider,
555539
ToolCallingMiddleware = async (_, context, next, token) =>
556540
{
557541
if (scenario is AgentScenario.ToolCall)
@@ -615,7 +599,6 @@ private async Task<IList<AITool>> GetToolsForScenarioAsync(AgentProvider provide
615599
case AgentScenario.ToolCall:
616600
switch (provider)
617601
{
618-
case AgentProvider.Google:
619602
case AgentProvider.CohereChatClient:
620603
tools = [AIFunctionFactory.Create(GetWeather, "get_weather")];
621604
break;

src/AgentFrameworkToolkit.Google/AgentFrameworkToolkit.Google.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<Import Project="..\..\nuget-package.props" />
99

1010
<ItemGroup>
11-
<PackageReference Include="Google_GenerativeAI.Microsoft" />
11+
<PackageReference Include="Google.GenAI" />
1212
<PackageReference Include="Microsoft.Agents.AI" />
1313
</ItemGroup>
1414
<ItemGroup>

src/AgentFrameworkToolkit.Google/GoogleAgentFactory.cs

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using GenerativeAI.Microsoft;
1+
using Google.GenAI;
2+
using Google.GenAI.Types;
23
using JetBrains.Annotations;
34
using Microsoft.Agents.AI;
45
using Microsoft.Extensions.AI;
@@ -63,7 +64,7 @@ public GoogleAgent CreateAgent(string model, string? instructions = null, string
6364
/// <returns>The Agent</returns>
6465
public GoogleAgent CreateAgent(GoogleAgentOptions options)
6566
{
66-
IChatClient client = GetClient(options.Model);
67+
IChatClient client = Connection.GetClient().AsIChatClient(options.Model);
6768

6869
AIAgent innerAgent = new ChatClientAgent(client, CreateChatClientAgentOptions(options), options.LoggerFactory, options.Services);
6970

@@ -98,16 +99,33 @@ private static ChatClientAgentOptions CreateChatClientAgentOptions(GoogleAgentOp
9899
chatOptions.MaxOutputTokens = options.MaxOutputTokens.Value;
99100
}
100101

101-
if (options.ThinkingBudget > 0)
102+
if (options.ThinkingBudget.HasValue || options.ThinkingLevel.HasValue)
102103
{
103104
anyOptionsSet = true;
104-
chatOptions.AdditionalProperties = new AdditionalPropertiesDictionary
105+
if (options.ThinkingLevel.HasValue)
105106
{
106-
["ThinkingBudget"] = options.ThinkingBudget,
107-
};
107+
chatOptions.RawRepresentationFactory = _ => new GenerateContentConfig
108+
{
109+
ThinkingConfig = new ThinkingConfig
110+
{
111+
ThinkingLevel = options.ThinkingLevel,
112+
IncludeThoughts = options.IncludeThoughts
113+
}
114+
};
115+
}
116+
else if (options.ThinkingBudget.HasValue)
117+
{
118+
chatOptions.RawRepresentationFactory = _ => new GenerateContentConfig
119+
{
120+
ThinkingConfig = new ThinkingConfig
121+
{
122+
ThinkingBudget = options.ThinkingBudget.Value,
123+
IncludeThoughts = options.IncludeThoughts
124+
}
125+
};
126+
}
108127
}
109128

110-
111129
if (options.Temperature != null)
112130
{
113131
anyOptionsSet = true;
@@ -138,24 +156,4 @@ private static ChatClientAgentOptions CreateChatClientAgentOptions(GoogleAgentOp
138156

139157
return chatClientAgentOptions;
140158
}
141-
142-
143-
private IChatClient GetClient(string model)
144-
{
145-
IChatClient client;
146-
if (Connection.Adapter != null)
147-
{
148-
client = new GenerativeAIChatClient(Connection.Adapter, model);
149-
}
150-
else if (Connection.ApiKey != null)
151-
{
152-
client = new GenerativeAIChatClient(Connection.ApiKey, model);
153-
}
154-
else
155-
{
156-
throw new AgentFrameworkToolkitException("You need to provide either an APIKey or Adapter to make a Google Connection");
157-
}
158-
159-
return client;
160-
}
161159
}

src/AgentFrameworkToolkit.Google/GoogleAgentOptions.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using Google.GenAI.Types;
12
using Microsoft.Agents.AI;
23
using Microsoft.Extensions.AI;
34
using Microsoft.Extensions.Logging;
@@ -62,9 +63,21 @@ public class GoogleAgentOptions
6263
public float? Temperature { get; set; }
6364

6465
/// <summary>
65-
/// How many tokens are allowed for thinking/reasoning
66+
/// Only models lower than Gemini 3: Indicates the thinking budget in tokens. 0 is DISABLED. -1 is AUTOMATIC. The default values
67+
/// and allowed ranges are model dependent.
6668
/// </summary>
67-
public int ThinkingBudget { get; set; }
69+
public int? ThinkingBudget { get; set; }
70+
71+
/// <summary>
72+
/// Only Gemini 3 and Higher: How much Thinking is allowed (Pro support HIGH and LOW, Flash support HIGH, MEDIUM, LOW and MINIMAL)
73+
/// </summary>
74+
public ThinkingLevel? ThinkingLevel { get; set; }
75+
76+
/// <summary>
77+
/// Indicates whether to include thoughts in the response. If true, thoughts are returned only
78+
/// if the model supports thought and thoughts are available.
79+
/// </summary>
80+
public bool IncludeThoughts { get; set; }
6881

6982
/// <summary>
7083
/// An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.
Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
using GenerativeAI.Core;
1+
using Google.Apis.Auth.OAuth2;
2+
using Google.GenAI;
3+
using Google.GenAI.Types;
4+
using Microsoft.Extensions.AI;
25

36
namespace AgentFrameworkToolkit.Google;
47

@@ -8,12 +11,49 @@ namespace AgentFrameworkToolkit.Google;
811
public class GoogleConnection
912
{
1013
/// <summary>
11-
/// API Key to use
14+
/// Optional String for the <a href="https://ai.google.dev/gemini-api/docs/api-key">API key</a>. Gemini API only.
1215
/// </summary>
1316
public string? ApiKey { get; set; }
1417

1518
/// <summary>
16-
/// Interface for platform-specific operations required to integrate with external APIs.
19+
/// Vertex Only: Optional Boolean for whether to use Vertex AI APIs. If not specified here nor in the environment variable, defaults to false.
1720
/// </summary>
18-
public IPlatformAdapter? Adapter { get; set; }
19-
}
21+
public bool? VertexAI { get; set; }
22+
23+
/// <summary>
24+
/// Vertex Only: Optional - see:Google.Apis.Auth.OAuth2.GoogleCredential.
25+
/// </summary>
26+
public ICredential? Credential { get; set; }
27+
28+
/// <summary>
29+
/// Vertex Only: Optional String for the project ID. Find it here: https://cloud.google.com/resource-manager/docs/creating-managing-projects#identifying_projects
30+
/// </summary>
31+
public string? Project { get; set; }
32+
33+
/// <summary>
34+
/// Vertex Only: Optional String for the location. See: https://cloud.google.com/vertex-ai/generative-ai/docs/learn/locations
35+
/// </summary>
36+
public string? Location { get; set; }
37+
38+
/// <summary>
39+
/// Options for the HTTP Request
40+
/// </summary>
41+
public HttpOptions? HttpOptions { get; set; }
42+
43+
/// <summary>
44+
/// Get a Raw Client
45+
/// </summary>
46+
/// <returns></returns>
47+
public Client GetClient()
48+
{
49+
Client client = new(
50+
vertexAI: VertexAI,
51+
apiKey: ApiKey,
52+
credential: Credential,
53+
project: Project,
54+
location: Location,
55+
httpOptions: HttpOptions);
56+
57+
return client;
58+
}
59+
}

0 commit comments

Comments
 (0)