diff --git a/assistant-connector/dotnet/README.md b/assistant-connector/dotnet/README.md index ed8b2fb3..d4aaa1d1 100644 --- a/assistant-connector/dotnet/README.md +++ b/assistant-connector/dotnet/README.md @@ -1,3 +1,37 @@ -This project contains a .NET connector allowing to connect .NET agents and assistants to Semantic Workbench. +# Semantic Workbench -The repository contains some [examples](../../examples/) using this connector. +Semantic Workbench is a versatile tool designed for quickly prototyping intelligent assistants. +Whether you're building new assistants or integrating existing ones, the workbench offers a unified +interface for managing conversations, configuring settings, and customizing behavior. + +# Connector + +The Connector allows to seamlessly integrate .NET agents, built with any framework, into Semantic +Workbench. By using HTTP for communication, the connector enables your agent to handle instructions +and exchange data with both the frontend and backend of Semantic Workbench. + +# Setup Guide + +To integrate your agent: + +1. Add the `Microsoft.SemanticWorkbench.Connector` nuget to the .NET project containing your agent. + +2. **Define an agent configuration**: Create a configuration class for your agent. This can be empty + if no configuration is needed from the workbench UI. + +3. **Extend Agent Functionality**: Inherit from `Microsoft.SemanticWorkbench.Connector.AgentBase` + and implement the `GetDefaultConfig` and `ParseConfig` methods in your agent class. Examples + are available in the repository. + +4. **Create a Connector**: Implement `Microsoft.SemanticWorkbench.Connector.WorkbenchConnector` and + its `CreateAgentAsync` method to allow the workbench to create multiple agent instances. + +5. Start a `Microsoft.SemanticWorkbench.Connector.WorkbenchConnector` calling the `ConnectAsync` + method. + +6. Start a Web service using the endpoints defined in `Microsoft.SemanticWorkbench.Connector.Webservice`. + +# Examples + +Find sample .NET agents and assistants using this connector in the +[official repository](https://github.com/microsoft/semanticworkbench/tree/main/examples). diff --git a/assistant-connector/dotnet/WorkbenchConnector/AgentBase.cs b/assistant-connector/dotnet/WorkbenchConnector/AgentBase.cs index 8249a2d8..e0b90fe1 100644 --- a/assistant-connector/dotnet/WorkbenchConnector/AgentBase.cs +++ b/assistant-connector/dotnet/WorkbenchConnector/AgentBase.cs @@ -1,5 +1,9 @@ // Copyright (c) Microsoft. All rights reserved. +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; using Microsoft.Extensions.Logging; namespace Microsoft.SemanticWorkbench.Connector; @@ -16,13 +20,13 @@ public abstract class AgentBase public IAgentConfig RawConfig { get; protected set; } // Simple storage layer to persist agents data - protected readonly IAgentServiceStorage Storage; + protected IAgentServiceStorage Storage { get; private set; } // Reference to agent service - protected readonly WorkbenchConnector WorkbenchConnector; + protected WorkbenchConnector WorkbenchConnector { get; private set; } // Agent logger - protected readonly ILogger Log; + protected ILogger Log { get; private set; } /// /// Agent instantiation @@ -30,7 +34,7 @@ public abstract class AgentBase /// Semantic Workbench connector /// Agent data storage /// Agent logger - public AgentBase( + protected AgentBase( WorkbenchConnector workbenchConnector, IAgentServiceStorage storage, ILogger log) @@ -68,6 +72,7 @@ public virtual AgentInfo ToDataModel() /// /// Start the agent /// + /// Async task cancellation token public virtual Task StartAsync( CancellationToken cancellationToken = default) { @@ -77,6 +82,7 @@ public virtual Task StartAsync( /// /// Stop the agent /// + /// Async task cancellation token public virtual Task StopAsync( CancellationToken cancellationToken = default) { @@ -158,7 +164,6 @@ await Task.WhenAll([ /// /// Delete a conversation /// - /// Agent instance ID /// Conversation ID /// Async task cancellation token public virtual Task DeleteConversationAsync( @@ -211,11 +216,11 @@ public virtual async Task AddParticipantAsync( /// Remove a participant from a conversation /// /// Conversation ID - /// Participant information + /// Participant information /// Async task cancellation token public virtual async Task RemoveParticipantAsync( string conversationId, - Participant participantUpdatedEvent, + Participant participant, CancellationToken cancellationToken = default) { this.Log.LogDebug("Removing participant from conversation '{0}' on agent '{1}'", @@ -224,7 +229,7 @@ public virtual async Task RemoveParticipantAsync( Conversation? conversation = await this.Storage.GetConversationAsync(conversationId, this.Id, cancellationToken).ConfigureAwait(false); if (conversation == null) { return; } - conversation.RemoveParticipant(participantUpdatedEvent); + conversation.RemoveParticipant(participant); await this.Storage.SaveConversationAsync(conversation, cancellationToken).ConfigureAwait(false); } @@ -287,7 +292,7 @@ public virtual Task ReceiveNoteAsync( /// Receive a command, a special type of message /// /// Conversation ID - /// Message information + /// Command information /// Async task cancellation token public virtual Task ReceiveCommandAsync( string conversationId, @@ -321,7 +326,7 @@ public virtual Task ReceiveCommandResponseAsync( /// Remove a message from a conversation /// /// Conversation ID - /// Message information + /// Message information /// Async task cancellation token public virtual async Task DeleteMessageAsync( string conversationId, diff --git a/assistant-connector/dotnet/WorkbenchConnector/ConfigUtils.cs b/assistant-connector/dotnet/WorkbenchConnector/ConfigUtils.cs index 0ebcb9e6..7c4f7c42 100644 --- a/assistant-connector/dotnet/WorkbenchConnector/ConfigUtils.cs +++ b/assistant-connector/dotnet/WorkbenchConnector/ConfigUtils.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. +using System.Collections.Generic; + namespace Microsoft.SemanticWorkbench.Connector; public static class ConfigUtils diff --git a/assistant-connector/dotnet/WorkbenchConnector/Constants.cs b/assistant-connector/dotnet/WorkbenchConnector/Constants.cs index b771d868..fbb233b9 100644 --- a/assistant-connector/dotnet/WorkbenchConnector/Constants.cs +++ b/assistant-connector/dotnet/WorkbenchConnector/Constants.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. +using System.Net.Http; + namespace Microsoft.SemanticWorkbench.Connector; public static class Constants diff --git a/assistant-connector/dotnet/WorkbenchConnector/Models/Command.cs b/assistant-connector/dotnet/WorkbenchConnector/Models/Command.cs index 3abc36cb..35885410 100644 --- a/assistant-connector/dotnet/WorkbenchConnector/Models/Command.cs +++ b/assistant-connector/dotnet/WorkbenchConnector/Models/Command.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. +using System; + // ReSharper disable once CheckNamespace namespace Microsoft.SemanticWorkbench.Connector; diff --git a/assistant-connector/dotnet/WorkbenchConnector/Models/Conversation.cs b/assistant-connector/dotnet/WorkbenchConnector/Models/Conversation.cs index 34f24439..eb99e4e0 100644 --- a/assistant-connector/dotnet/WorkbenchConnector/Models/Conversation.cs +++ b/assistant-connector/dotnet/WorkbenchConnector/Models/Conversation.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. +using System.Collections.Generic; +using System.Linq; using System.Text; using System.Text.Json.Serialization; using Microsoft.SemanticKernel.ChatCompletion; diff --git a/assistant-connector/dotnet/WorkbenchConnector/Models/ConversationEvent.cs b/assistant-connector/dotnet/WorkbenchConnector/Models/ConversationEvent.cs index 06de4707..daeaff65 100644 --- a/assistant-connector/dotnet/WorkbenchConnector/Models/ConversationEvent.cs +++ b/assistant-connector/dotnet/WorkbenchConnector/Models/ConversationEvent.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. +using System; using System.Text.Json.Serialization; // ReSharper disable once CheckNamespace diff --git a/assistant-connector/dotnet/WorkbenchConnector/Models/DebugInfo.cs b/assistant-connector/dotnet/WorkbenchConnector/Models/DebugInfo.cs index 2c549402..91446119 100644 --- a/assistant-connector/dotnet/WorkbenchConnector/Models/DebugInfo.cs +++ b/assistant-connector/dotnet/WorkbenchConnector/Models/DebugInfo.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. +using System.Collections.Generic; + // ReSharper disable once CheckNamespace namespace Microsoft.SemanticWorkbench.Connector; diff --git a/assistant-connector/dotnet/WorkbenchConnector/Models/Message.cs b/assistant-connector/dotnet/WorkbenchConnector/Models/Message.cs index a11ff1b6..7b4ffba1 100644 --- a/assistant-connector/dotnet/WorkbenchConnector/Models/Message.cs +++ b/assistant-connector/dotnet/WorkbenchConnector/Models/Message.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. +using System; using System.Text.Json.Serialization; // ReSharper disable once CheckNamespace @@ -30,12 +31,19 @@ public class Message [JsonPropertyName("metadata")] public MessageMetadata Metadata { get; set; } = new(); + /// + /// Prepare a chat message instance /// /// Content types: /// - text/plain /// - text/html /// - application/json (requires "json_schema" metadata) /// + /// + /// Agent ID + /// Chat content + /// Optional debugging data + /// Message content type public static Message CreateChatMessage( string agentId, string content, diff --git a/assistant-connector/dotnet/WorkbenchConnector/Storage/AgentServiceStorage.cs b/assistant-connector/dotnet/WorkbenchConnector/Storage/AgentServiceStorage.cs index ba996e18..0d0fb2a4 100644 --- a/assistant-connector/dotnet/WorkbenchConnector/Storage/AgentServiceStorage.cs +++ b/assistant-connector/dotnet/WorkbenchConnector/Storage/AgentServiceStorage.cs @@ -1,7 +1,12 @@ // Copyright (c) Microsoft. All rights reserved. +using System; +using System.Collections.Generic; +using System.IO; using System.Runtime.InteropServices; using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; @@ -39,9 +44,9 @@ public AgentServiceStorage( : "StoragePathLinux") ?? string.Empty; this._path = Path.Join(tmpPath, connectorId); - if (this._path.Contains("$tmp")) + if (this._path.Contains("$tmp", StringComparison.OrdinalIgnoreCase)) { - this._path = this._path.Replace("$tmp", Path.GetTempPath()); + this._path = this._path.Replace("$tmp", Path.GetTempPath(), StringComparison.OrdinalIgnoreCase); } this._path = Path.Join(this._path, "agents"); diff --git a/assistant-connector/dotnet/WorkbenchConnector/Storage/IAgentServiceStorage.cs b/assistant-connector/dotnet/WorkbenchConnector/Storage/IAgentServiceStorage.cs index 6a81cbdf..e43b7d5f 100644 --- a/assistant-connector/dotnet/WorkbenchConnector/Storage/IAgentServiceStorage.cs +++ b/assistant-connector/dotnet/WorkbenchConnector/Storage/IAgentServiceStorage.cs @@ -1,5 +1,9 @@ // Copyright (c) Microsoft. All rights reserved. +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + // ReSharper disable once CheckNamespace namespace Microsoft.SemanticWorkbench.Connector; diff --git a/assistant-connector/dotnet/WorkbenchConnector/Webservice.cs b/assistant-connector/dotnet/WorkbenchConnector/Webservice.cs index c990da59..4fc59aa3 100644 --- a/assistant-connector/dotnet/WorkbenchConnector/Webservice.cs +++ b/assistant-connector/dotnet/WorkbenchConnector/Webservice.cs @@ -1,7 +1,13 @@ // Copyright (c) Microsoft. All rights reserved. +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; using System.Text; using System.Text.Json; +using System.Threading; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -295,22 +301,20 @@ public static IEndpointRouteBuilder UseFetchConversationInsightEndpoint( return Results.NotFound($"State '{insightId}' Not Found"); } - else + + // TODO: support schemas + var result = new { - // TODO: support schemas - var result = new + id = insightId, + data = new { - id = insightId, - data = new - { - content = insight.Content - }, - json_schema = (object)null!, - ui_schema = (object)null! - }; + content = insight.Content + }, + json_schema = (object)null!, + ui_schema = (object)null! + }; - return Results.Json(result); - } + return Results.Json(result); }); return builder; @@ -546,7 +550,7 @@ private static IEndpointRouteBuilder UseCatchAllEndpoint( StringBuilder headersStringBuilder = new(); foreach (KeyValuePair header in context.Request.Headers) { - headersStringBuilder.AppendLine($"{header.Key}: {header.Value}"); + headersStringBuilder.AppendLine(CultureInfo.InvariantCulture, $"{header.Key}: {header.Value}"); } // Read body diff --git a/assistant-connector/dotnet/WorkbenchConnector/WorkbenchConfig.cs b/assistant-connector/dotnet/WorkbenchConnector/WorkbenchConfig.cs index a1cc706a..dbc14c6d 100644 --- a/assistant-connector/dotnet/WorkbenchConnector/WorkbenchConfig.cs +++ b/assistant-connector/dotnet/WorkbenchConnector/WorkbenchConfig.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. +using System; + namespace Microsoft.SemanticWorkbench.Connector; public class WorkbenchConfig diff --git a/assistant-connector/dotnet/WorkbenchConnector/WorkbenchConnector.cs b/assistant-connector/dotnet/WorkbenchConnector/WorkbenchConnector.cs index 75238d90..83ffa0f3 100644 --- a/assistant-connector/dotnet/WorkbenchConnector/WorkbenchConnector.cs +++ b/assistant-connector/dotnet/WorkbenchConnector/WorkbenchConnector.cs @@ -1,7 +1,13 @@ // Copyright (c) Microsoft. All rights reserved. +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; using System.Text; using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; @@ -9,15 +15,15 @@ namespace Microsoft.SemanticWorkbench.Connector; public abstract class WorkbenchConnector : IDisposable { - protected readonly IAgentServiceStorage Storage; - protected readonly WorkbenchConfig Config = new(); - protected readonly HttpClient HttpClient; - protected readonly ILogger Log; - protected readonly Dictionary Agents; + protected IAgentServiceStorage Storage { get; private set; } + protected WorkbenchConfig Config { get; private set; } = new(); + protected HttpClient HttpClient { get; private set; } + protected ILogger Log { get; private set; } + protected Dictionary Agents { get; private set; } private Timer? _pingTimer; - public WorkbenchConnector( + protected WorkbenchConnector( IConfiguration appConfig, IAgentServiceStorage storage, ILogger logger) @@ -40,9 +46,9 @@ public WorkbenchConnector( public virtual async Task ConnectAsync(CancellationToken cancellationToken = default) { this.Log.LogInformation("Connecting {1} {2} {3}...", this.Config.ConnectorName, this.Config.ConnectorId, this.Config.ConnectorEndpoint); - #pragma warning disable CS4014 // ping runs in the background without blocking +#pragma warning disable CS4014 // ping runs in the background without blocking this._pingTimer ??= new Timer(_ => this.PingSemanticWorkbenchBackendAsync(cancellationToken), null, 0, 10000); - #pragma warning restore CS4014 +#pragma warning restore CS4014 List agents = await this.Storage.GetAllAgentsAsync(cancellationToken).ConfigureAwait(false); this.Log.LogInformation("Starting {0} agents", agents.Count); @@ -56,12 +62,15 @@ public virtual async Task ConnectAsync(CancellationToken cancellationToken = def /// Disconnect the agent service from the workbench backend /// /// Async task cancellation token - public virtual Task DisconnectAsync(CancellationToken cancellationToken = default) + public virtual async Task DisconnectAsync(CancellationToken cancellationToken = default) { this.Log.LogInformation("Disconnecting {1} {2} ...", this.Config.ConnectorName, this.Config.ConnectorId); - this._pingTimer?.Dispose(); + if (this._pingTimer != null) + { + await this._pingTimer.DisposeAsync().ConfigureAwait(false); + } + this._pingTimer = null; - return Task.CompletedTask; } /// @@ -69,6 +78,7 @@ public virtual Task DisconnectAsync(CancellationToken cancellationToken = defaul /// /// Agent instance ID /// Agent name + /// Configuration content /// Async task cancellation token public abstract Task CreateAgentAsync( string agentId, @@ -110,7 +120,7 @@ public virtual async Task DeleteAgentAsync( /// /// Agent instance ID /// Conversation ID - /// Content. Markdown and HTML are supported. + /// Insight content. Markdown and HTML are supported. /// Async task cancellation token public virtual async Task UpdateAgentConversationInsightAsync( string agentId, @@ -137,8 +147,8 @@ public virtual async Task UpdateAgentConversationInsightAsync( }; string url = Constants.SendAgentConversationInsightsEvent.Path - .Replace(Constants.SendAgentConversationInsightsEvent.AgentPlaceholder, agentId) - .Replace(Constants.SendAgentConversationInsightsEvent.ConversationPlaceholder, conversationId); + .Replace(Constants.SendAgentConversationInsightsEvent.AgentPlaceholder, agentId, StringComparison.OrdinalIgnoreCase) + .Replace(Constants.SendAgentConversationInsightsEvent.ConversationPlaceholder, conversationId, StringComparison.OrdinalIgnoreCase); await this.SendAsync(HttpMethod.Post, url, data, agentId, "UpdateAgentConversationInsight", cancellationToken).ConfigureAwait(false); } @@ -167,18 +177,17 @@ public virtual async Task SetAgentStatusAsync( }; string url = Constants.SendAgentStatusMessage.Path - .Replace(Constants.SendAgentStatusMessage.ConversationPlaceholder, conversationId) - .Replace(Constants.SendAgentStatusMessage.AgentPlaceholder, agentId); + .Replace(Constants.SendAgentStatusMessage.ConversationPlaceholder, conversationId, StringComparison.OrdinalIgnoreCase) + .Replace(Constants.SendAgentStatusMessage.AgentPlaceholder, agentId, StringComparison.OrdinalIgnoreCase); await this.SendAsync(HttpMethod.Put, url, data, agentId, $"SetAgentStatus[{status}]", cancellationToken).ConfigureAwait(false); } /// - /// Set a temporary agent status within a conversation + /// Reset the temporary agent status within a conversation /// /// Agent instance ID /// Conversation ID - /// Short status description /// Async task cancellation token public virtual async Task ResetAgentStatusAsync( string agentId, @@ -188,18 +197,18 @@ public virtual async Task ResetAgentStatusAsync( this.Log.LogDebug("Setting agent status in conversation '{0}' with agent '{1}'", conversationId.HtmlEncode(), agentId.HtmlEncode()); - string payload = """ - { - "status": null, - "active_participant": true - } - """; + const string Payload = """ + { + "status": null, + "active_participant": true + } + """; - var data = JsonSerializer.Deserialize(payload); + var data = JsonSerializer.Deserialize(Payload); string url = Constants.SendAgentStatusMessage.Path - .Replace(Constants.SendAgentStatusMessage.ConversationPlaceholder, conversationId) - .Replace(Constants.SendAgentStatusMessage.AgentPlaceholder, agentId); + .Replace(Constants.SendAgentStatusMessage.ConversationPlaceholder, conversationId, StringComparison.OrdinalIgnoreCase) + .Replace(Constants.SendAgentStatusMessage.AgentPlaceholder, agentId, StringComparison.OrdinalIgnoreCase); await this.SendAsync(HttpMethod.Put, url, data!, agentId, "ResetAgentStatus", cancellationToken).ConfigureAwait(false); } @@ -221,7 +230,7 @@ public virtual async Task SendMessageAsync( conversationId.HtmlEncode(), agentId.HtmlEncode()); string url = Constants.SendAgentMessage.Path - .Replace(Constants.SendAgentMessage.ConversationPlaceholder, conversationId); + .Replace(Constants.SendAgentMessage.ConversationPlaceholder, conversationId, StringComparison.OrdinalIgnoreCase); await this.SendAsync(HttpMethod.Post, url, message, agentId, "SendMessage", cancellationToken).ConfigureAwait(false); } @@ -240,7 +249,7 @@ public virtual async Task GetFilesAsync( this.Log.LogDebug("Fetching list of files in conversation '{0}'", conversationId.HtmlEncode()); string url = Constants.GetConversationFiles.Path - .Replace(Constants.GetConversationFiles.ConversationPlaceholder, conversationId); + .Replace(Constants.GetConversationFiles.ConversationPlaceholder, conversationId, StringComparison.OrdinalIgnoreCase); HttpResponseMessage result = await this.SendAsync(HttpMethod.Get, url, null, agentId, "GetFiles", cancellationToken).ConfigureAwait(false); @@ -282,8 +291,8 @@ public virtual async Task DownloadFileAsync( this.Log.LogDebug("Downloading file from conversation '{0}'", conversationId.HtmlEncode()); string url = Constants.ConversationFile.Path - .Replace(Constants.ConversationFile.ConversationPlaceholder, conversationId) - .Replace(Constants.ConversationFile.FileNamePlaceholder, fileName); + .Replace(Constants.ConversationFile.ConversationPlaceholder, conversationId, StringComparison.OrdinalIgnoreCase) + .Replace(Constants.ConversationFile.FileNamePlaceholder, fileName, StringComparison.OrdinalIgnoreCase); HttpResponseMessage result = await this.SendAsync(HttpMethod.Get, url, null, agentId, "DownloadFile", cancellationToken).ConfigureAwait(false); @@ -316,7 +325,7 @@ public virtual async Task UploadFileAsync( this.Log.LogDebug("Deleting file {0} from a conversation '{1}'", fileName.HtmlEncode(), conversationId.HtmlEncode()); string url = Constants.UploadConversationFile.Path - .Replace(Constants.UploadConversationFile.ConversationPlaceholder, conversationId); + .Replace(Constants.UploadConversationFile.ConversationPlaceholder, conversationId, StringComparison.OrdinalIgnoreCase); // TODO: include file using multipart/form-data @@ -339,8 +348,8 @@ public virtual async Task DeleteFileAsync( this.Log.LogDebug("Deleting file {0} from a conversation '{1}'", fileName.HtmlEncode(), conversationId.HtmlEncode()); string url = Constants.ConversationFile.Path - .Replace(Constants.ConversationFile.ConversationPlaceholder, conversationId) - .Replace(Constants.ConversationFile.FileNamePlaceholder, fileName); + .Replace(Constants.ConversationFile.ConversationPlaceholder, conversationId, StringComparison.OrdinalIgnoreCase) + .Replace(Constants.ConversationFile.FileNamePlaceholder, fileName, StringComparison.OrdinalIgnoreCase); await this.SendAsync(HttpMethod.Delete, url, null, agentId, "DeleteFile", cancellationToken).ConfigureAwait(false); } @@ -349,7 +358,7 @@ public virtual async Task PingSemanticWorkbenchBackendAsync(CancellationToken ca { this.Log.LogTrace("Pinging workbench backend"); string path = Constants.AgentServiceRegistration.Path - .Replace(Constants.AgentServiceRegistration.Placeholder, this.Config.ConnectorId); + .Replace(Constants.AgentServiceRegistration.Placeholder, this.Config.ConnectorId, StringComparison.OrdinalIgnoreCase); var data = new { @@ -359,10 +368,10 @@ public virtual async Task PingSemanticWorkbenchBackendAsync(CancellationToken ca online_expires_in_seconds = 20 }; - await this.SendAsync(HttpMethod.Put, path, data, null, "PingSWBackend",cancellationToken).ConfigureAwait(false); + await this.SendAsync(HttpMethod.Put, path, data, null, "PingSWBackend", cancellationToken).ConfigureAwait(false); } -#region internals =========================================================================== + #region internals =========================================================================== public void Dispose() { @@ -432,5 +441,5 @@ protected virtual HttpRequestMessage PrepareRequest( return request; } -#endregion + #endregion } diff --git a/assistant-connector/dotnet/WorkbenchConnector/WorkbenchConnector.csproj b/assistant-connector/dotnet/WorkbenchConnector/WorkbenchConnector.csproj index 81089fdb..e640174c 100644 --- a/assistant-connector/dotnet/WorkbenchConnector/WorkbenchConnector.csproj +++ b/assistant-connector/dotnet/WorkbenchConnector/WorkbenchConnector.csproj @@ -1,11 +1,14 @@  - net8.0 - enable - enable Microsoft.SemanticWorkbench.Connector Microsoft.SemanticWorkbench.Connector + net8.0 + disable + enable + 12 + LatestMajor + $(NoWarn);IDE0130;CA2254;CA1812; @@ -16,4 +19,92 @@ - + + true + true + All + latest + + true + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + false + false + + + + true + true + + + + 0.1.0 + Microsoft.SemanticWorkbench.Connector + Connector for Agents and Assistants developed with Semantic Workbench + The connector allow Agents and Assistants to be used within Semantic Workbench. + Copilot, Agent, Agentic AI, Assistant, AI, Artificial Intelligence + bin/$(Configuration)/$(TargetFramework)/$(AssemblyName).xml + Microsoft + Microsoft + MIT + © Microsoft Corporation. All rights reserved. + https://github.com/microsoft/semanticworkbench + https://github.com/microsoft/semanticworkbench + true + icon.png + icon.png + README.md + true + true + full + true + snupkg + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assistant-connector/dotnet/WorkbenchConnector/icon.png b/assistant-connector/dotnet/WorkbenchConnector/icon.png new file mode 100644 index 00000000..3862f148 Binary files /dev/null and b/assistant-connector/dotnet/WorkbenchConnector/icon.png differ diff --git a/assistant-connector/dotnet/pack.sh b/assistant-connector/dotnet/pack.sh new file mode 100755 index 00000000..da5ea3c6 --- /dev/null +++ b/assistant-connector/dotnet/pack.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e +HERE="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)" +cd $HERE + +cd WorkbenchConnector +dotnet build -c Release --nologo diff --git a/examples/dotnet-03-simple-chatbot/MyAgent.cs b/examples/dotnet-03-simple-chatbot/MyAgent.cs index 642240d6..268830b2 100644 --- a/examples/dotnet-03-simple-chatbot/MyAgent.cs +++ b/examples/dotnet-03-simple-chatbot/MyAgent.cs @@ -88,7 +88,7 @@ public override async Task ReceiveCommandAsync( if (!this.Config.ReplyToAgents && command.Sender.Role == "assistant") { return; } // Support only the "say" command - if (command.CommandName.ToLowerInvariant() != "say") { return; } + if (!command.CommandName.Equals("say", StringComparison.OrdinalIgnoreCase)) { return; } // Update the chat history to include the message received await base.AddMessageToHistoryAsync(conversationId, command, cancellationToken).ConfigureAwait(false); @@ -345,7 +345,7 @@ private Task LogChatHistoryAsInsight( Conversation conversation, CancellationToken cancellationToken) { - Insight insight = new Insight("history", "Chat History", conversation.ToHtmlString(this.Id)); + Insight insight = new("history", "Chat History", conversation.ToHtmlString(this.Id)); return this.SetConversationInsightAsync(conversation.Id, insight, cancellationToken); } } diff --git a/examples/dotnet-03-simple-chatbot/dotnet-03-simple-chatbot.csproj b/examples/dotnet-03-simple-chatbot/dotnet-03-simple-chatbot.csproj index a5c0e262..2a17a9c2 100644 --- a/examples/dotnet-03-simple-chatbot/dotnet-03-simple-chatbot.csproj +++ b/examples/dotnet-03-simple-chatbot/dotnet-03-simple-chatbot.csproj @@ -6,7 +6,7 @@ enable AgentExample AgentExample - $(NoWarn);SKEXP0010; + $(NoWarn);SKEXP0010;CA1861; @@ -17,11 +17,35 @@ + + + + true + true + All + latest + + true + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + all runtime; build; native; contentfiles; analyzers; buildtransitive - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + all runtime; build; native; contentfiles; analyzers; buildtransitive