Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions dotnet/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
<!-- Default properties inherited by all projects. Projects can override. -->
<RunAnalyzersDuringBuild>true</RunAnalyzersDuringBuild>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
<AnalysisLevel>latest</AnalysisLevel>
<AnalysisLevel>10.0-all</AnalysisLevel>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
Expand Down
1 change: 1 addition & 0 deletions dotnet/samples/.editorconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Suppressing errors for Sample projects under dotnet/samples folder
[*.cs]
dotnet_diagnostic.CA1716.severity = none # Add summary to documentation comment.
dotnet_diagnostic.CA1873.severity = none # Evaluation of logging arguments may be expensive
dotnet_diagnostic.CA2000.severity = none # Call System.IDisposable.Dispose on object before all references to it are out of scope
dotnet_diagnostic.CA2007.severity = none # Do not directly await a Task

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public async Task<ChatResponse> GetResponseAsync(IEnumerable<ChatMessage> messag
GenerateContentResponse generateResult = await this._models.GenerateContentAsync(modelId!, contents, config).ConfigureAwait(false);

// Create the response.
ChatResponse chatResponse = new(new ChatMessage(ChatRole.Assistant, new List<AIContent>()))
ChatResponse chatResponse = new(new ChatMessage(ChatRole.Assistant, []))
{
CreatedAt = generateResult.CreateTime is { } dt ? new DateTimeOffset(dt) : null,
ModelId = !string.IsNullOrWhiteSpace(generateResult.ModelVersion) ? generateResult.ModelVersion : modelId,
Expand Down Expand Up @@ -82,7 +82,7 @@ public async IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseAsync(IEnu
await foreach (GenerateContentResponse generateResult in this._models.GenerateContentStreamAsync(modelId!, contents, config).WithCancellation(cancellationToken).ConfigureAwait(false))
{
// Create a response update for each result in the stream.
ChatResponseUpdate responseUpdate = new(ChatRole.Assistant, new List<AIContent>())
ChatResponseUpdate responseUpdate = new(ChatRole.Assistant, [])
{
CreatedAt = generateResult.CreateTime is { } dt ? new DateTimeOffset(dt) : null,
ModelId = !string.IsNullOrWhiteSpace(generateResult.ModelVersion) ? generateResult.ModelVersion : modelId,
Expand Down Expand Up @@ -148,7 +148,7 @@ void IDisposable.Dispose() { /* nop */ }
// create the request instance, allowing the caller to populate it with GenAI-specific options. Otherwise, create
// a new instance directly.
string? model = this._defaultModelId;
List<Content> contents = new();
List<Content> contents = [];
GenerateContentConfig config = options?.RawRepresentationFactory?.Invoke(this) as GenerateContentConfig ?? new();

if (options is not null)
Expand All @@ -160,7 +160,7 @@ void IDisposable.Dispose() { /* nop */ }

if (options.Instructions is { } instructions)
{
((config.SystemInstruction ??= new()).Parts ??= new()).Add(new() { Text = instructions });
((config.SystemInstruction ??= new()).Parts ??= []).Add(new() { Text = instructions });
}

if (options.MaxOutputTokens is { } maxOutputTokens)
Expand All @@ -185,7 +185,7 @@ void IDisposable.Dispose() { /* nop */ }

if (options.StopSequences is { } stopSequences)
{
(config.StopSequences ??= new()).AddRange(stopSequences);
(config.StopSequences ??= []).AddRange(stopSequences);
}

if (options.Temperature is { } temperature)
Expand Down Expand Up @@ -213,7 +213,7 @@ void IDisposable.Dispose() { /* nop */ }
switch (tool)
{
case AIFunctionDeclaration af:
functionDeclarations ??= new();
functionDeclarations ??= [];
functionDeclarations.Add(new()
{
Name = af.Name,
Expand All @@ -223,15 +223,15 @@ void IDisposable.Dispose() { /* nop */ }
break;

case HostedCodeInterpreterTool:
(config.Tools ??= new()).Add(new() { CodeExecution = new() });
(config.Tools ??= []).Add(new() { CodeExecution = new() });
break;

case HostedFileSearchTool:
(config.Tools ??= new()).Add(new() { Retrieval = new() });
(config.Tools ??= []).Add(new() { Retrieval = new() });
break;

case HostedWebSearchTool:
(config.Tools ??= new()).Add(new() { GoogleSearch = new() });
(config.Tools ??= []).Add(new() { GoogleSearch = new() });
break;
}
}
Expand All @@ -240,8 +240,8 @@ void IDisposable.Dispose() { /* nop */ }
if (functionDeclarations is { Count: > 0 })
{
Tool functionTools = new();
(functionTools.FunctionDeclarations ??= new()).AddRange(functionDeclarations);
(config.Tools ??= new()).Add(functionTools);
(functionTools.FunctionDeclarations ??= []).AddRange(functionDeclarations);
(config.Tools ??= []).Add(functionTools);
}

// Transfer over the tool mode if there are any tools.
Expand All @@ -261,7 +261,7 @@ void IDisposable.Dispose() { /* nop */ }
config.ToolConfig = new() { FunctionCallingConfig = new() { Mode = FunctionCallingConfigMode.ANY } };
if (required.RequiredFunctionName is not null)
{
((config.ToolConfig.FunctionCallingConfig ??= new()).AllowedFunctionNames ??= new()).Add(required.RequiredFunctionName);
((config.ToolConfig.FunctionCallingConfig ??= new()).AllowedFunctionNames ??= []).Add(required.RequiredFunctionName);
}
break;
}
Expand All @@ -287,14 +287,14 @@ void IDisposable.Dispose() { /* nop */ }
string instruction = message.Text;
if (!string.IsNullOrWhiteSpace(instruction))
{
((config.SystemInstruction ??= new()).Parts ??= new()).Add(new() { Text = instruction });
((config.SystemInstruction ??= new()).Parts ??= []).Add(new() { Text = instruction });
}

continue;
}

Content content = new() { Role = message.Role == ChatRole.Assistant ? "model" : "user" };
content.Parts ??= new();
content.Parts ??= [];
AddPartsForAIContents(ref callIdToFunctionNames, message.Contents, content.Parts);

contents.Add(content);
Expand Down Expand Up @@ -367,7 +367,7 @@ private static void AddPartsForAIContents(ref Dictionary<string, string>? callId
break;

case FunctionCallContent functionCallContent:
(callIdToFunctionNames ??= new())[functionCallContent.CallId] = functionCallContent.Name;
(callIdToFunctionNames ??= [])[functionCallContent.CallId] = functionCallContent.Name;
callIdToFunctionNames[""] = functionCallContent.Name; // track last function name in case calls don't have IDs

part = new()
Expand Down Expand Up @@ -480,22 +480,22 @@ private static void AddAIContentsForParts(List<Part> parts, IList<AIContent> con
{
foreach (var citation in citations)
{
textContent.Annotations = new List<AIAnnotation>()
{
new CitationAnnotation()
{
Title = citation.Title,
Url = Uri.TryCreate(citation.Uri, UriKind.Absolute, out Uri? uri) ? uri : null,
AnnotatedRegions = new List<AnnotatedRegion>()
{
new TextSpanAnnotatedRegion()
{
StartIndex = citation.StartIndex,
EndIndex = citation.EndIndex,
}
},
}
};
textContent.Annotations =
[
new CitationAnnotation()
{
Title = citation.Title,
Url = Uri.TryCreate(citation.Uri, UriKind.Absolute, out Uri? uri) ? uri : null,
AnnotatedRegions =
[
new TextSpanAnnotatedRegion()
{
StartIndex = citation.StartIndex,
EndIndex = citation.EndIndex,
}
],
}
];
}
}
}
Expand Down Expand Up @@ -551,7 +551,7 @@ void AddIfPresent(string key, int? value)
{
if (value is int i)
{
(details.AdditionalCounts ??= new())[key] = i;
(details.AdditionalCounts ??= [])[key] = i;
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion dotnet/src/Microsoft.Agents.AI.A2A/A2AAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ private static AgentMessage CreateA2AMessage(A2AAgentThread typedThread, IEnumer

private static A2AContinuationToken? CreateContinuationToken(string taskId, TaskState state)
{
if (state == TaskState.Submitted || state == TaskState.Working)
if (state is TaskState.Submitted or TaskState.Working)
{
return new A2AContinuationToken(taskId);
}
Expand Down
6 changes: 5 additions & 1 deletion dotnet/src/Microsoft.Agents.AI.AGUI/AGUIChatClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,11 @@ public async IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseAsync(
if (options?.Tools is { Count: > 0 })
{
input.Tools = options.Tools.AsAGUITools();
this._logger.LogDebug("[AGUIChatClient] Tool count: {ToolCount}", options.Tools.Count);

if (this._logger.IsEnabled(LogLevel.Debug))
{
this._logger.LogDebug("[AGUIChatClient] Tool count: {ToolCount}", options.Tools.Count);
}
}

var clientToolSet = new HashSet<string>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public static async IAsyncEnumerable<ChatMessage> ProcessActivityAsync(IAsyncEnu
{
yield return CreateChatMessageFromActivity(activity, [new TextContent(activity.Text)]);
}
else
else if (logger.IsEnabled(LogLevel.Warning))
{
logger.LogWarning("Unknown activity type '{ActivityType}' received.", activity.Type);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ public static CosmosChatMessageStore CreateFromSerializedState(CosmosClient cosm
throw new ArgumentException("Invalid serialized state", nameof(serializedStoreState));
}

var state = JsonSerializer.Deserialize<StoreState>(serializedStoreState, jsonSerializerOptions);
var state = serializedStoreState.Deserialize<StoreState>(jsonSerializerOptions);
if (state?.ConversationIdentifier is not { } conversationId)
{
throw new ArgumentException("Invalid serialized state", nameof(serializedStoreState));
Expand Down
31 changes: 26 additions & 5 deletions dotnet/src/Microsoft.Agents.AI.DevUI/DevUIMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,11 @@ public async Task HandleRequestAsync(HttpContext context)
context.Response.StatusCode = StatusCodes.Status301MovedPermanently;
context.Response.Headers.Location = redirectUrl;

this._logger.LogDebug("Redirecting {OriginalPath} to {RedirectUrl}", NewlineRegex().Replace(path, ""), NewlineRegex().Replace(redirectUrl, ""));
if (this._logger.IsEnabled(LogLevel.Debug))
{
this._logger.LogDebug("Redirecting {OriginalPath} to {RedirectUrl}", NewlineRegex().Replace(path, ""), NewlineRegex().Replace(redirectUrl, ""));
}

return;
}

Expand Down Expand Up @@ -123,7 +127,11 @@ private async Task<bool> TryServeResourceAsync(HttpContext context, string resou
{
if (!this._resourceCache.TryGetValue(resourcePath.Replace('.', '/'), out var cacheEntry))
{
this._logger.LogDebug("Embedded resource not found: {ResourcePath}", resourcePath);
if (this._logger.IsEnabled(LogLevel.Debug))
{
this._logger.LogDebug("Embedded resource not found: {ResourcePath}", resourcePath);
}

return false;
}

Expand All @@ -133,7 +141,12 @@ private async Task<bool> TryServeResourceAsync(HttpContext context, string resou
if (context.Request.Headers.IfNoneMatch == cacheEntry.ETag)
{
response.StatusCode = StatusCodes.Status304NotModified;
this._logger.LogDebug("Resource not modified (304): {ResourcePath}", resourcePath);

if (this._logger.IsEnabled(LogLevel.Debug))
{
this._logger.LogDebug("Resource not modified (304): {ResourcePath}", resourcePath);
}

return true;
}

Expand Down Expand Up @@ -161,12 +174,20 @@ private async Task<bool> TryServeResourceAsync(HttpContext context, string resou

await response.Body.WriteAsync(content, context.RequestAborted).ConfigureAwait(false);

this._logger.LogDebug("Served embedded resource: {ResourcePath} (compressed: {Compressed})", resourcePath, serveCompressed);
if (this._logger.IsEnabled(LogLevel.Debug))
{
this._logger.LogDebug("Served embedded resource: {ResourcePath} (compressed: {Compressed})", resourcePath, serveCompressed);
}

return true;
}
catch (Exception ex)
{
this._logger.LogError(ex, "Error serving embedded resource: {ResourcePath}", resourcePath);
if (this._logger.IsEnabled(LogLevel.Error))
{
this._logger.LogError(ex, "Error serving embedded resource: {ResourcePath}", resourcePath);
}

return false;
}
}
Expand Down
6 changes: 4 additions & 2 deletions dotnet/src/Microsoft.Agents.AI.DurableTask/DurableAIAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,10 @@ public override async Task<AgentRunResponse> RunAsync(
responseFormat = chatClientOptions.ChatOptions?.ResponseFormat;
}

RunRequest request = new([.. messages], responseFormat, enableToolCalls, enableToolNames);
request.OrchestrationId = this._context.InstanceId;
RunRequest request = new([.. messages], responseFormat, enableToolCalls, enableToolNames)
{
OrchestrationId = this._context.InstanceId
};

try
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public static DurableAgentStateFunctionCallContent FromFunctionCallContent(Funct
{
return new DurableAgentStateFunctionCallContent()
{
Arguments = content.Arguments?.ToImmutableDictionary() ?? ImmutableDictionary<string, object?>.Empty,
Arguments = content.Arguments?.ToDictionary() ?? [],
CallId = content.CallId,
Name = content.Name
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ internal sealed partial class AGUIServerSentEventsResult : IResult, IDisposable
private readonly ILogger<AGUIServerSentEventsResult> _logger;
private Utf8JsonWriter? _jsonWriter;

public int? StatusCode => StatusCodes.Status200OK;

internal AGUIServerSentEventsResult(IAsyncEnumerable<BaseEvent> events, ILogger<AGUIServerSentEventsResult> logger)
{
this._events = events;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ public HostedAgentResponseExecutor(
AIAgent? agent = this._serviceProvider.GetKeyedService<AIAgent>(agentName);
if (agent is null)
{
this._logger.LogWarning("Failed to resolve agent with name '{AgentName}'", agentName);
if (this._logger.IsEnabled(LogLevel.Warning))
{
this._logger.LogWarning("Failed to resolve agent with name '{AgentName}'", agentName);
}

return ValueTask.FromResult<ResponseError?>(new ResponseError
{
Code = "agent_not_found",
Expand Down
2 changes: 1 addition & 1 deletion dotnet/src/Microsoft.Agents.AI.Mem0/Mem0Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ internal sealed class CreateMemoryRequest
[JsonPropertyName("agent_id")] public string? AgentId { get; set; }
[JsonPropertyName("run_id")] public string? RunId { get; set; }
[JsonPropertyName("user_id")] public string? UserId { get; set; }
[JsonPropertyName("messages")] public CreateMemoryMessage[] Messages { get; set; } = Array.Empty<CreateMemoryMessage>();
[JsonPropertyName("messages")] public CreateMemoryMessage[] Messages { get; set; } = [];
}

internal sealed class CreateMemoryMessage
Expand Down
Loading
Loading