From 92f9c756768a830effe9222e0284b2c4e207d210 Mon Sep 17 00:00:00 2001 From: examples-bot Date: Mon, 6 Apr 2026 05:26:55 +0000 Subject: [PATCH] =?UTF-8?q?feat(examples):=20add=20500=20=E2=80=94=20Seman?= =?UTF-8?q?tic=20Kernel=20Voice=20Plugin=20(.NET/C#)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../.env.example | 5 + .../.gitignore | 2 + .../README.md | 56 ++ .../src/DeepgramPlugin.cs | 91 +++ .../src/DeepgramSemanticKernel.csproj | 16 + .../src/Program.cs | 61 +++ .../src/packages.lock.json | 412 ++++++++++++++ .../tests/DeepgramPluginTests.cs | 78 +++ .../tests/DeepgramSemanticKernel.Tests.csproj | 21 + .../tests/packages.lock.json | 516 ++++++++++++++++++ 10 files changed, 1258 insertions(+) create mode 100644 examples/500-semantic-kernel-voice-plugin-dotnet/.env.example create mode 100644 examples/500-semantic-kernel-voice-plugin-dotnet/.gitignore create mode 100644 examples/500-semantic-kernel-voice-plugin-dotnet/README.md create mode 100644 examples/500-semantic-kernel-voice-plugin-dotnet/src/DeepgramPlugin.cs create mode 100644 examples/500-semantic-kernel-voice-plugin-dotnet/src/DeepgramSemanticKernel.csproj create mode 100644 examples/500-semantic-kernel-voice-plugin-dotnet/src/Program.cs create mode 100644 examples/500-semantic-kernel-voice-plugin-dotnet/src/packages.lock.json create mode 100644 examples/500-semantic-kernel-voice-plugin-dotnet/tests/DeepgramPluginTests.cs create mode 100644 examples/500-semantic-kernel-voice-plugin-dotnet/tests/DeepgramSemanticKernel.Tests.csproj create mode 100644 examples/500-semantic-kernel-voice-plugin-dotnet/tests/packages.lock.json diff --git a/examples/500-semantic-kernel-voice-plugin-dotnet/.env.example b/examples/500-semantic-kernel-voice-plugin-dotnet/.env.example new file mode 100644 index 0000000..534c7a0 --- /dev/null +++ b/examples/500-semantic-kernel-voice-plugin-dotnet/.env.example @@ -0,0 +1,5 @@ +# Deepgram — https://console.deepgram.com/ +DEEPGRAM_API_KEY= + +# OpenAI — https://platform.openai.com/api-keys +OPENAI_API_KEY= diff --git a/examples/500-semantic-kernel-voice-plugin-dotnet/.gitignore b/examples/500-semantic-kernel-voice-plugin-dotnet/.gitignore new file mode 100644 index 0000000..cd42ee3 --- /dev/null +++ b/examples/500-semantic-kernel-voice-plugin-dotnet/.gitignore @@ -0,0 +1,2 @@ +bin/ +obj/ diff --git a/examples/500-semantic-kernel-voice-plugin-dotnet/README.md b/examples/500-semantic-kernel-voice-plugin-dotnet/README.md new file mode 100644 index 0000000..69ce284 --- /dev/null +++ b/examples/500-semantic-kernel-voice-plugin-dotnet/README.md @@ -0,0 +1,56 @@ +# Semantic Kernel Voice Plugin with Deepgram (.NET) + +A Deepgram plugin for Microsoft Semantic Kernel that exposes speech-to-text (STT) and text-to-speech (TTS) as `[KernelFunction]` attributes. An AI agent can autonomously choose to transcribe audio or synthesize speech during a chat conversation. + +## What you'll build + +A .NET 8 console app with a Semantic Kernel agent that can transcribe audio from URLs or local files using Deepgram Nova-3, and convert text to speech using Deepgram Aura-2 — all invoked automatically by the AI agent when relevant. + +## Prerequisites + +- [.NET 8 SDK](https://dotnet.microsoft.com/download/dotnet/8.0) +- Deepgram account — [get a free API key](https://console.deepgram.com/) +- OpenAI account — [get an API key](https://platform.openai.com/api-keys) + +## Environment variables + +| Variable | Where to find it | +|----------|-----------------| +| `DEEPGRAM_API_KEY` | [Deepgram console](https://console.deepgram.com/) | +| `OPENAI_API_KEY` | [OpenAI dashboard → API keys](https://platform.openai.com/api-keys) | + +## Install and run + +```bash +cp .env.example .env +# Fill in your API keys in .env + +cd src +dotnet restore +dotnet run +``` + +Then try prompts like: +- "Transcribe this audio: https://static.deepgram.com/examples/Bueller-Life-moves-pretty-fast.wav" +- "Say 'Hello world' as audio and save it to greeting.mp3" + +## Key parameters + +| Parameter | Value | Description | +|-----------|-------|-------------| +| `model` | `nova-3` | Deepgram's latest and most accurate STT model | +| `model` (TTS) | `aura-2-thalia-en` | Deepgram's Aura-2 TTS voice | +| `smart_format` | `true` | Adds punctuation, casing, and paragraph formatting | +| `tag` | `deepgram-examples` | Tags API usage for analytics | + +## How it works + +1. The app creates a Semantic Kernel `Kernel` with an OpenAI chat completion backend. +2. A `DeepgramPlugin` class registers four `[KernelFunction]` methods: `transcribe_url`, `transcribe_file`, `speak_text`, and `speak_text_stream`. +3. `FunctionChoiceBehavior.Auto()` lets the LLM decide when to call Deepgram functions based on the conversation. +4. When the user asks about audio transcription, the agent calls `TranscribeUrlAsync` or `TranscribeFileAsync`, which use Deepgram's pre-recorded STT API. +5. When the user asks for text-to-speech, the agent calls `SpeakTextAsync` (saves to file) or `SpeakTextStreamAsync` (returns base64 audio). + +## Starter templates + +[deepgram-starters](https://github.com/orgs/deepgram-starters/repositories) diff --git a/examples/500-semantic-kernel-voice-plugin-dotnet/src/DeepgramPlugin.cs b/examples/500-semantic-kernel-voice-plugin-dotnet/src/DeepgramPlugin.cs new file mode 100644 index 0000000..8c32991 --- /dev/null +++ b/examples/500-semantic-kernel-voice-plugin-dotnet/src/DeepgramPlugin.cs @@ -0,0 +1,91 @@ +using System.ComponentModel; +using Deepgram; +using Deepgram.Clients.Interfaces.v1; +using Deepgram.Models.Listen.v1.REST; +using Deepgram.Models.Speak.v1.REST; +using Microsoft.SemanticKernel; + +namespace DeepgramSemanticKernel; + +public class DeepgramPlugin +{ + private readonly IListenRESTClient _listenClient; + private readonly ISpeakRESTClient _speakClient; + + public DeepgramPlugin() + { + _listenClient = ClientFactory.CreateListenRESTClient(); + _speakClient = ClientFactory.CreateSpeakRESTClient(); + } + + [KernelFunction("transcribe_url")] + [Description("Transcribes audio from a URL using Deepgram speech-to-text. Returns the transcript text.")] + public async Task TranscribeUrlAsync( + [Description("The URL of the audio file to transcribe")] string url) + { + var response = await _listenClient.TranscribeUrl( + new UrlSource(url), + new PreRecordedSchema + { + Model = "nova-3", + SmartFormat = true, + // ← tag is REQUIRED so internal test traffic is identifiable + Tag = new List { "deepgram-examples" } + }); + + return response.Results!.Channels![0].Alternatives![0].Transcript!; + } + + [KernelFunction("transcribe_file")] + [Description("Transcribes a local audio file using Deepgram speech-to-text. Returns the transcript text.")] + public async Task TranscribeFileAsync( + [Description("The absolute path to the local audio file")] string filePath) + { + var audioData = await File.ReadAllBytesAsync(filePath); + + var response = await _listenClient.TranscribeFile( + audioData, + new PreRecordedSchema + { + Model = "nova-3", + SmartFormat = true, + Tag = new List { "deepgram-examples" } + }); + + return response.Results!.Channels![0].Alternatives![0].Transcript!; + } + + [KernelFunction("speak_text")] + [Description("Converts text to speech using Deepgram TTS. Saves the audio to a file and returns the file path.")] + public async Task SpeakTextAsync( + [Description("The text to convert to speech")] string text, + [Description("Output file path for the audio (e.g. output.mp3)")] string outputPath = "output.mp3") + { + await _speakClient.ToFile( + new TextSource(text), + outputPath, + new SpeakSchema + { + Model = "aura-2-thalia-en" + }); + + return $"Audio saved to {outputPath}"; + } + + // Exposes ToStream for callers that need in-memory audio bytes + [KernelFunction("speak_text_stream")] + [Description("Converts text to speech and returns the raw audio bytes as a base64-encoded string.")] + public async Task SpeakTextStreamAsync( + [Description("The text to convert to speech")] string text) + { + var response = await _speakClient.ToStream( + new TextSource(text), + new SpeakSchema + { + Model = "aura-2-thalia-en" + }); + + var bytes = response.Stream!.ToArray(); + return Convert.ToBase64String(bytes); + } +} diff --git a/examples/500-semantic-kernel-voice-plugin-dotnet/src/DeepgramSemanticKernel.csproj b/examples/500-semantic-kernel-voice-plugin-dotnet/src/DeepgramSemanticKernel.csproj new file mode 100644 index 0000000..e28f4f2 --- /dev/null +++ b/examples/500-semantic-kernel-voice-plugin-dotnet/src/DeepgramSemanticKernel.csproj @@ -0,0 +1,16 @@ + + + + Exe + net8.0 + enable + enable + true + + + + + + + + diff --git a/examples/500-semantic-kernel-voice-plugin-dotnet/src/Program.cs b/examples/500-semantic-kernel-voice-plugin-dotnet/src/Program.cs new file mode 100644 index 0000000..286b068 --- /dev/null +++ b/examples/500-semantic-kernel-voice-plugin-dotnet/src/Program.cs @@ -0,0 +1,61 @@ +using Deepgram; +using DeepgramSemanticKernel; +using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.ChatCompletion; +using Microsoft.SemanticKernel.Connectors.OpenAI; + +var deepgramKey = Environment.GetEnvironmentVariable("DEEPGRAM_API_KEY"); +var openaiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY"); + +if (string.IsNullOrEmpty(deepgramKey) || string.IsNullOrEmpty(openaiKey)) +{ + Console.Error.WriteLine("Set DEEPGRAM_API_KEY and OPENAI_API_KEY environment variables."); + Environment.Exit(2); +} + +// Deepgram SDK requires explicit initialization +Library.Initialize(); + +try +{ + var builder = Kernel.CreateBuilder(); + builder.AddOpenAIChatCompletion("gpt-4o-mini", openaiKey); + + var kernel = builder.Build(); + kernel.ImportPluginFromType("Deepgram"); + + var chat = kernel.GetRequiredService(); + var history = new ChatHistory( + "You are a helpful assistant with access to Deepgram voice tools. " + + "You can transcribe audio from URLs or local files, and convert text to speech. " + + "Use the Deepgram functions when the user asks about audio transcription or text-to-speech."); + + var settings = new OpenAIPromptExecutionSettings + { + FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() + }; + + Console.WriteLine("Deepgram + Semantic Kernel Agent"); + Console.WriteLine("Type a message (or 'quit' to exit):"); + Console.WriteLine(); + + while (true) + { + Console.Write("You: "); + var input = Console.ReadLine(); + if (string.IsNullOrWhiteSpace(input) || input.Equals("quit", StringComparison.OrdinalIgnoreCase)) + break; + + history.AddUserMessage(input); + + var response = await chat.GetChatMessageContentAsync(history, settings, kernel); + Console.WriteLine($"Agent: {response.Content}"); + Console.WriteLine(); + + history.AddAssistantMessage(response.Content ?? ""); + } +} +finally +{ + Library.Terminate(); +} diff --git a/examples/500-semantic-kernel-voice-plugin-dotnet/src/packages.lock.json b/examples/500-semantic-kernel-voice-plugin-dotnet/src/packages.lock.json new file mode 100644 index 0000000..b9f4e1d --- /dev/null +++ b/examples/500-semantic-kernel-voice-plugin-dotnet/src/packages.lock.json @@ -0,0 +1,412 @@ +{ + "version": 1, + "dependencies": { + "net8.0": { + "Deepgram": { + "type": "Direct", + "requested": "[6.6.1, )", + "resolved": "6.6.1", + "contentHash": "DVxqEtXRDcOVDYzVN4c541+3ZeFydbp/dP/O+mdTKBNehc/jfGHFKRxS4RF9NO6tJTVl6nflh34IX22YxfcdlA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Http.Polly": "8.0.22", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.3", + "Polly.Contrib.WaitAndRetry": "1.1.1", + "Serilog": "3.1.1", + "Serilog.Sinks.Console": "5.0.1", + "Serilog.Sinks.File": "5.0.0", + "System.Text.Json": "8.0.6", + "System.Threading.Channels": "8.0.0" + } + }, + "Microsoft.SemanticKernel": { + "type": "Direct", + "requested": "[1.74.0, )", + "resolved": "1.74.0", + "contentHash": "V1N0mR8VHLEY11w2w8ls3Bk60fOjp6TaHOduBXMwfaR5ZF2bho6rCQdonU+6zwAKyD1JB+yT0wJ2xt1hcm60+w==", + "dependencies": { + "Microsoft.SemanticKernel.Connectors.AzureOpenAI": "1.74.0", + "Microsoft.SemanticKernel.Core": "1.74.0" + } + }, + "Azure.AI.OpenAI": { + "type": "Transitive", + "resolved": "2.9.0-beta.1", + "contentHash": "CgIYDuCSOFx+yPuCdK7iz71OW2envfVeIE/YoNYK+mhr6bxgIJV6jfBF+mV9aHDQ6KVQjeSL6OZ7x90XrvsoRg==", + "dependencies": { + "Azure.Core": "1.51.1", + "OpenAI": "2.9.1" + } + }, + "Azure.Core": { + "type": "Transitive", + "resolved": "1.51.1", + "contentHash": "JRANrRvN5O5FFRh+pMUb8qqWU7jBQ39qXEbVr7Rkb1/s7rqc6RSzVHKGBz5Ro1gDy2WSGjG5YEOJKpPIBiCMcA==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "10.0.2", + "System.ClientModel": "1.9.0", + "System.Memory.Data": "10.0.1" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "qE5JhRoeJbAipLqpUCZyNfNwnpAvUttXgIQDnTiJ15d8ji+/bPgoPkB3xLzK5cQTobN2D2ditUesUlDHb7p3Pg==" + }, + "Microsoft.Bcl.HashCode": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "MalY0Y/uM/LjXtHfX/26l2VtN4LDNZ2OE3aumNOHDLsT4fNYy2hiHXI4CXCqKpNUNm7iJ2brrc4J89UdaL56FA==" + }, + "Microsoft.Extensions.AI": { + "type": "Transitive", + "resolved": "10.4.0", + "contentHash": "7kKIuaUMFWikveZUjSrs53XfMVV7IDGSDaGp6/y/hV0HXsA7N2oIODZWxtEkEj8Q4cd/Oc/VlsVlg8efof7gFA==", + "dependencies": { + "Microsoft.Extensions.AI.Abstractions": "10.4.0", + "Microsoft.Extensions.Caching.Abstractions": "10.0.4", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.4", + "Microsoft.Extensions.Logging.Abstractions": "10.0.4", + "System.Diagnostics.DiagnosticSource": "10.0.4", + "System.Numerics.Tensors": "10.0.4", + "System.Text.Json": "10.0.4", + "System.Threading.Channels": "10.0.4" + } + }, + "Microsoft.Extensions.AI.Abstractions": { + "type": "Transitive", + "resolved": "10.4.0", + "contentHash": "t3S2H4do4YeNheIfE3GEl3MnKIrnxpbLu7a88spfApYR3in9ddhIq/GMtxgMaFjn/PUMTCFv5YH7Y6Q91dsDXQ==", + "dependencies": { + "System.Text.Json": "10.0.4" + } + }, + "Microsoft.Extensions.AI.OpenAI": { + "type": "Transitive", + "resolved": "10.4.0", + "contentHash": "7R1fyxwF8KtQi8k2ih3Y6dHZiUfnnmZIgXY7hQ+dFlPkVZoefgKAzdnnrFZzYOjXPeJxh3gqAQ4psXnp59wwqw==", + "dependencies": { + "Microsoft.Extensions.AI.Abstractions": "10.4.0", + "OpenAI": "2.9.1", + "System.Text.Json": "10.0.4" + } + }, + "Microsoft.Extensions.Caching.Abstractions": { + "type": "Transitive", + "resolved": "10.0.4", + "contentHash": "uDRooaV6N3WZ0kdlNPMB68/MdGn/in1Fs7Db7DnIm85RBTPy4P321WO+daAImiYpH5dekjNggDqy1N44WaIlMA==", + "dependencies": { + "Microsoft.Extensions.Primitives": "10.0.4" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "0J/9YNXTMWSZP2p2+nvl8p71zpSwokZXZuJW+VjdErkegAnFdO1XlqtA62SJtgVYHdKu3uPxJHcMR/r35HwFBA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "KC5PslaTDnTuTvyke0KYAVBYdZ7IVTsU3JhHe69BpEbHLcj1YThP3bIGtZNOkZfast2AuLnul5lk4rZKxAdUGQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "10.0.2" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "mBMoXLsr5s1y2zOHWmKsE9veDcx8h1x/c3rz4baEdQKTeDcmQAPNbB54Pi/lhFO3K431eEq6PFbMgLaa6PHFfA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "J/Zmp6fY93JbaiZ11ckWvcyxMPjD6XVwIHQXBjryTBgn7O6O20HYg9uVLFcZlNfgH78MnreE/7EH+hjfzn7VyA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "10.0.4", + "contentHash": "SIe9zlVQJecnk/DTmevIcl6+aEDYhoVLc2eG2AKwVeNEC8CSyxHAbh4lf0xtHq9JUum0vVTEByGNTK+b6oihTQ==" + }, + "Microsoft.Extensions.Diagnostics": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "doVPCUUCY7c6LhBsEfiy3W1bvS7Mi6LkfQMS8nlC22jZWNxBv8VO8bdfeyvpYFst6Kxqk7HBC6lytmEoBssvSQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Diagnostics.Abstractions": "8.0.1", + "Microsoft.Extensions.Options.ConfigurationExtensions": "8.0.0" + } + }, + "Microsoft.Extensions.Diagnostics.Abstractions": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "GaiaeKUuLuUbRPkUokndDuzonhO6dk4lcfGflHsCeXiJ5JrZxcyks1KuG6eB9pON16x/+9uWfa4w9g3oP8AYvQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2", + "Microsoft.Extensions.Options": "10.0.2", + "System.Diagnostics.DiagnosticSource": "10.0.2" + } + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "+r/eJ+slW/EmwWmH3En4gzRg1k6+yTqexoHBrMuz5fxsIKJA8MDiSGepjw/ko3XyNqg+w3dxQe+huoVXs5XDJw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "10.0.2" + } + }, + "Microsoft.Extensions.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "CeAAPVOtI/wtBcHOwq6Pw3VPdGi+pNaGHZj6vfXX/5zr8beO9SyL7IOCSQ70BauFTAFS0QF7f6zu2A6hC8D6nw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.2", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2", + "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.2", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.2", + "Microsoft.Extensions.Logging.Abstractions": "10.0.2" + } + }, + "Microsoft.Extensions.Http": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "kDYeKJUzh0qeg/AI+nSr3ffthmXYQTEb0nS9qRC7YhSbbuN4M4NPbaB77AJwtkTnCV9XZ7qYj3dkZaNcyl73EA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Diagnostics": "8.0.1", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.Extensions.Http.Polly": { + "type": "Transitive", + "resolved": "8.0.22", + "contentHash": "0veowl2NhmxYSvHJN1VqVxghSUdoXRsBXbYO2Z5PpaHEHEiUzGyiVf3aFShVYW+yMMcGvtbJscmMmsvlyZWVXw==", + "dependencies": { + "Microsoft.Extensions.Http": "8.0.1", + "Polly": "7.2.4", + "Polly.Extensions.Http": "3.0.0" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "4x+pzsQEbqxhNf1QYRr5TDkLP9UsLT3A6MdRKDDEgrW7h1ljiEPgTNhKYUhNCCAaVpQECVQ+onA91PTPnIp6Lw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "10.0.4", + "contentHash": "PDMMt7fvBatv6hcxxyJtXIzSwn7Dy00W6I2vDAOTYrQqNM2dF5A2L9n0uMzdPz2IPoNZWkAmYjoOCEdDLq0i4w==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.4", + "System.Diagnostics.DiagnosticSource": "10.0.4" + } + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "1De2LJjmxdqopI5AYC5dIhoZQ79AR5ayywxNF1rXrXFtKQfbQOV9+n/IsZBa7qWlr0MqoGpW8+OY2v/57udZOA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2", + "Microsoft.Extensions.Primitives": "10.0.2" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "0f4DMRqEd50zQh+UyJc+/HiBsZ3vhAQALgdkcQEalSH1L2isdC7Yj54M3cyo5e+BeO5fcBQ7Dxly8XiBBcvRgw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Configuration.Binder": "8.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Options": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "10.0.4", + "contentHash": "lABYqiRH9HgYJsjzO3W7+cucUwWXhEkiyrRylANdIubnzcESlkIsLowXpQ4E+sc7kjMLbk1hk5oxw4qTKowTEg==" + }, + "Microsoft.Extensions.VectorData.Abstractions": { + "type": "Transitive", + "resolved": "10.1.0", + "contentHash": "I2XfmqEOWOq0Esbo0eWQ6WE5MAJkGyIs057F8ncmPCLJFw9b1IB7Jj5WiFlH6C5YXCAG9Z91QMBD/SkcMLhE7w==", + "dependencies": { + "Microsoft.Extensions.AI.Abstractions": "10.4.0" + } + }, + "Microsoft.SemanticKernel.Abstractions": { + "type": "Transitive", + "resolved": "1.74.0", + "contentHash": "e9sPaCiyvi3FzQWbBTjyvLpq4LDaqekz4/xt+Zi30C9cOZRMw6srULEy/jOo9nDXJQ2bsai6JT5TLxuxGwuFWg==", + "dependencies": { + "Microsoft.Bcl.HashCode": "1.1.1", + "Microsoft.Extensions.AI": "10.4.0", + "Microsoft.Extensions.VectorData.Abstractions": "10.1.0", + "System.Linq.AsyncEnumerable": "10.0.4", + "System.Text.Json": "10.0.4" + } + }, + "Microsoft.SemanticKernel.Connectors.AzureOpenAI": { + "type": "Transitive", + "resolved": "1.74.0", + "contentHash": "RZm+Bu4Y42ozRcAEJO9ruaBkyTPnLY/3v9hSWBhma6lj6O5Rva8EOLLZkaZM+Dn7d0dgBXOF4U+tedWtFXrjPg==", + "dependencies": { + "Azure.AI.OpenAI": "2.9.0-beta.1", + "Microsoft.SemanticKernel.Connectors.OpenAI": "1.74.0", + "Microsoft.SemanticKernel.Core": "1.74.0" + } + }, + "Microsoft.SemanticKernel.Connectors.OpenAI": { + "type": "Transitive", + "resolved": "1.74.0", + "contentHash": "xojSsxe0MoJNIQLNGsYiH4jSMDeLnD/yniMEumSz1lt3ybnPHu3Xw1M/C+jfFcqdEXJe64j06b6DRwUs4IjqdQ==", + "dependencies": { + "Microsoft.Extensions.AI.OpenAI": "10.4.0", + "Microsoft.SemanticKernel.Core": "1.74.0", + "OpenAI": "2.9.1" + } + }, + "Microsoft.SemanticKernel.Core": { + "type": "Transitive", + "resolved": "1.74.0", + "contentHash": "SfV2U3jvIy06BCrOkx3Am6c2lurJued7YEGX36wvk8WeSzgwwnkycqSOQTkbV0GLAzYeBKTA7+5mpPypjc7cPw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "10.0.2", + "Microsoft.SemanticKernel.Abstractions": "1.74.0", + "System.Numerics.Tensors": "10.0.4" + } + }, + "OpenAI": { + "type": "Transitive", + "resolved": "2.9.1", + "contentHash": "KPTFYEt1EhrPeIZXGBE+DlutFEpMo/RspqSdUJ3p6pMqsw3NeGJcIja/K0He1j9KyRq8ASfzBgp2biWbNUGnFA==", + "dependencies": { + "System.ClientModel": "1.9.0", + "System.Net.ServerSentEvents": "10.0.2" + } + }, + "Polly": { + "type": "Transitive", + "resolved": "7.2.4", + "contentHash": "bw00Ck5sh6ekduDE3mnCo1ohzuad946uslCDEENu3091+6UKnBuKLo4e+yaNcCzXxOZCXWY2gV4a35+K1d4LDA==" + }, + "Polly.Contrib.WaitAndRetry": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "1MUQLiSo4KDkQe6nzQRhIU05lm9jlexX5BVsbuw0SL82ynZ+GzAHQxJVDPVBboxV37Po3SG077aX8DuSy8TkaA==" + }, + "Polly.Extensions.Http": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "drrG+hB3pYFY7w1c3BD+lSGYvH2oIclH8GRSehgfyP5kjnFnHKQuuBhuHLv+PWyFuaTDyk/vfRpnxOzd11+J8g==", + "dependencies": { + "Polly": "7.1.0" + } + }, + "Serilog": { + "type": "Transitive", + "resolved": "3.1.1", + "contentHash": "P6G4/4Kt9bT635bhuwdXlJ2SCqqn2nhh4gqFqQueCOr9bK/e7W9ll/IoX1Ter948cV2Z/5+5v8pAfJYUISY03A==" + }, + "Serilog.Sinks.Console": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "6Jt8jl9y2ey8VV7nVEUAyjjyxjAQuvd5+qj4XYAT9CwcsvR70HHULGBeD+K2WCALFXf7CFsNQT4lON6qXcu2AA==", + "dependencies": { + "Serilog": "3.1.1" + } + }, + "Serilog.Sinks.File": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "uwV5hdhWPwUH1szhO8PJpFiahqXmzPzJT/sOijH/kFgUx+cyoDTMM8MHD0adw9+Iem6itoibbUXHYslzXsLEAg==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "System.ClientModel": { + "type": "Transitive", + "resolved": "1.9.0", + "contentHash": "1wdwKtMMMEFEYsxJmtrOd3G+7zVOVO3MlVZAsbKv9H0PnIx6J27fYAarMn0eQS0vKJPQL018DOb7YRK1O97p0A==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.2", + "Microsoft.Extensions.Hosting.Abstractions": "10.0.2", + "Microsoft.Extensions.Logging.Abstractions": "10.0.2", + "System.Memory.Data": "10.0.1" + } + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "10.0.4", + "contentHash": "WBD8SloNQ9Fp+6Iz+H42w5/VdwYPz9q7iuT6V5ng2FrtR1bYsewmQ3i2PqRR4NnuSZobJ/XtiKkbQyrheDHHdQ==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "10.0.4", + "contentHash": "V7+RO17s/tzCpgqyj6t5vb54HFCvrRaMEwTcKDwpoQK66DRROzSff6kqtzHyiWRj6hrQQUmW80NL4pFSNhYpYA==" + }, + "System.Linq.AsyncEnumerable": { + "type": "Transitive", + "resolved": "10.0.4", + "contentHash": "zGjd0H9R+1ojPL5D5kwvHgKMm4aohcYOChSQrxb9s295xQNxgXhs9L4qAL34SbA2TfRFuAvPTF7AAqPeNacRcg==" + }, + "System.Memory.Data": { + "type": "Transitive", + "resolved": "10.0.1", + "contentHash": "BZC4mhdL569AXV56ep9YO6ShjhxFXGP7SwVX0Bc/e0dJPWnS6aBEXZJXqh64RVx8HquqWHkJUINBydLRQ1yq0g==", + "dependencies": { + "System.Text.Json": "10.0.1" + } + }, + "System.Net.ServerSentEvents": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "pRmUzK1Av9Lqg5tOnk5/0+pFw195eVDP/9gJ2LP0YVPLzOGwjK3Obiutw4CKcJ2Gl9fOYTEc5Za8sB1/xexeGg==" + }, + "System.Numerics.Tensors": { + "type": "Transitive", + "resolved": "10.0.4", + "contentHash": "EK8wJVxnVfeCzchnEqVjIfZDpVIcmjfjUs9x1nzI41X2naPGT57QjoHlQJma2vDQUxEtPQiGv/v90mwcflx6mQ==" + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "10.0.4", + "contentHash": "6g3B7jNsPRNf4luuYt1qE4R8S3JI+zMsfGWL9Idv4Mk1Z9Gh+rCagp9sG3AejPS87yBj1DjopM4i3wSz0WnEqg==" + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "10.0.4", + "contentHash": "1tRPRt8D/kzjGL7em1uJ3iJlvVIC3G/sZJ+ZgSvtVYLXGGO26Clkqy2b5uts/pyR706Yw8/xA7exeI2PI50dpw==", + "dependencies": { + "System.IO.Pipelines": "10.0.4", + "System.Text.Encodings.Web": "10.0.4" + } + }, + "System.Threading.Channels": { + "type": "Transitive", + "resolved": "10.0.4", + "contentHash": "YkecPP9I3PjRouQJzG/JwUoiASqHKddXQrgu+CKHra6yFv6AmTr8PCwzHanNus/kDeujWM4Bqunx7dYFRiPErg==" + } + } + } +} \ No newline at end of file diff --git a/examples/500-semantic-kernel-voice-plugin-dotnet/tests/DeepgramPluginTests.cs b/examples/500-semantic-kernel-voice-plugin-dotnet/tests/DeepgramPluginTests.cs new file mode 100644 index 0000000..610be1d --- /dev/null +++ b/examples/500-semantic-kernel-voice-plugin-dotnet/tests/DeepgramPluginTests.cs @@ -0,0 +1,78 @@ +using Deepgram; +using DeepgramSemanticKernel; +using Xunit; + +namespace DeepgramSemanticKernel.Tests; + +public class DeepgramPluginTests : IDisposable +{ + private static readonly string[] RequiredVars = { "DEEPGRAM_API_KEY" }; + private readonly DeepgramPlugin _plugin; + + public DeepgramPluginTests() + { + var missing = RequiredVars.Where(k => string.IsNullOrEmpty(Environment.GetEnvironmentVariable(k))).ToList(); + if (missing.Count > 0) + { + Console.Error.WriteLine($"MISSING_CREDENTIALS: {string.Join(",", missing)}"); + Environment.Exit(2); + } + + Library.Initialize(); + _plugin = new DeepgramPlugin(); + } + + public void Dispose() + { + Library.Terminate(); + } + + [Fact] + public async Task TranscribeUrl_ReturnsNonEmptyTranscript() + { + // NASA audio sample — ~5 seconds of speech + var url = "https://static.deepgram.com/examples/Bueller-Life-moves-pretty-fast.wav"; + + var transcript = await _plugin.TranscribeUrlAsync(url); + + Assert.False(string.IsNullOrWhiteSpace(transcript), "Transcript should not be empty"); + // Proportional check: ~5s of audio should produce at least 10 characters + Assert.True(transcript.Length >= 10, + $"Transcript too short ({transcript.Length} chars) for a multi-second audio clip"); + } + + [Fact] + public async Task SpeakText_CreatesAudioFile() + { + var outputPath = Path.Combine(Path.GetTempPath(), $"dg_test_{Guid.NewGuid()}.mp3"); + + try + { + var result = await _plugin.SpeakTextAsync("Hello from Deepgram and Semantic Kernel.", outputPath); + + Assert.Contains(outputPath, result); + Assert.True(File.Exists(outputPath), "Audio file should be created"); + + var fileInfo = new FileInfo(outputPath); + // Even a short sentence produces at least a few KB of audio + Assert.True(fileInfo.Length > 1000, + $"Audio file too small ({fileInfo.Length} bytes) — expected real audio content"); + } + finally + { + if (File.Exists(outputPath)) File.Delete(outputPath); + } + } + + [Fact] + public async Task SpeakTextStream_ReturnsBase64Audio() + { + var base64 = await _plugin.SpeakTextStreamAsync("Testing Deepgram text to speech."); + + Assert.False(string.IsNullOrWhiteSpace(base64), "Base64 audio should not be empty"); + + var bytes = Convert.FromBase64String(base64); + Assert.True(bytes.Length > 1000, + $"Audio data too small ({bytes.Length} bytes) — expected real audio content"); + } +} diff --git a/examples/500-semantic-kernel-voice-plugin-dotnet/tests/DeepgramSemanticKernel.Tests.csproj b/examples/500-semantic-kernel-voice-plugin-dotnet/tests/DeepgramSemanticKernel.Tests.csproj new file mode 100644 index 0000000..f9e813b --- /dev/null +++ b/examples/500-semantic-kernel-voice-plugin-dotnet/tests/DeepgramSemanticKernel.Tests.csproj @@ -0,0 +1,21 @@ + + + + net8.0 + enable + enable + false + true + + + + + + + + + + + + + diff --git a/examples/500-semantic-kernel-voice-plugin-dotnet/tests/packages.lock.json b/examples/500-semantic-kernel-voice-plugin-dotnet/tests/packages.lock.json new file mode 100644 index 0000000..8090c83 --- /dev/null +++ b/examples/500-semantic-kernel-voice-plugin-dotnet/tests/packages.lock.json @@ -0,0 +1,516 @@ +{ + "version": 1, + "dependencies": { + "net8.0": { + "Microsoft.NET.Test.Sdk": { + "type": "Direct", + "requested": "[17.12.0, )", + "resolved": "17.12.0", + "contentHash": "kt/PKBZ91rFCWxVIJZSgVLk+YR+4KxTuHf799ho8WNiK5ZQpJNAEZCAWX86vcKrs+DiYjiibpYKdGZP6+/N17w==", + "dependencies": { + "Microsoft.CodeCoverage": "17.12.0", + "Microsoft.TestPlatform.TestHost": "17.12.0" + } + }, + "xunit": { + "type": "Direct", + "requested": "[2.9.3, )", + "resolved": "2.9.3", + "contentHash": "TlXQBinK35LpOPKHAqbLY4xlEen9TBafjs0V5KnA4wZsoQLQJiirCR4CbIXvOH8NzkW4YeJKP5P/Bnrodm0h9Q==", + "dependencies": { + "xunit.analyzers": "1.18.0", + "xunit.assert": "2.9.3", + "xunit.core": "[2.9.3]" + } + }, + "xunit.runner.visualstudio": { + "type": "Direct", + "requested": "[2.8.2, )", + "resolved": "2.8.2", + "contentHash": "vm1tbfXhFmjFMUmS4M0J0ASXz3/U5XvXBa6DOQUL3fEz4Vt6YPhv+ESCarx6M6D+9kJkJYZKCNvJMas1+nVfmQ==" + }, + "Azure.AI.OpenAI": { + "type": "Transitive", + "resolved": "2.9.0-beta.1", + "contentHash": "CgIYDuCSOFx+yPuCdK7iz71OW2envfVeIE/YoNYK+mhr6bxgIJV6jfBF+mV9aHDQ6KVQjeSL6OZ7x90XrvsoRg==", + "dependencies": { + "Azure.Core": "1.51.1", + "OpenAI": "2.9.1" + } + }, + "Azure.Core": { + "type": "Transitive", + "resolved": "1.51.1", + "contentHash": "JRANrRvN5O5FFRh+pMUb8qqWU7jBQ39qXEbVr7Rkb1/s7rqc6RSzVHKGBz5Ro1gDy2WSGjG5YEOJKpPIBiCMcA==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "10.0.2", + "System.ClientModel": "1.9.0", + "System.Memory.Data": "10.0.1" + } + }, + "Deepgram": { + "type": "Transitive", + "resolved": "6.6.1", + "contentHash": "DVxqEtXRDcOVDYzVN4c541+3ZeFydbp/dP/O+mdTKBNehc/jfGHFKRxS4RF9NO6tJTVl6nflh34IX22YxfcdlA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Http.Polly": "8.0.22", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.3", + "Polly.Contrib.WaitAndRetry": "1.1.1", + "Serilog": "3.1.1", + "Serilog.Sinks.Console": "5.0.1", + "Serilog.Sinks.File": "5.0.0", + "System.Text.Json": "8.0.6", + "System.Threading.Channels": "8.0.0" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "qE5JhRoeJbAipLqpUCZyNfNwnpAvUttXgIQDnTiJ15d8ji+/bPgoPkB3xLzK5cQTobN2D2ditUesUlDHb7p3Pg==" + }, + "Microsoft.Bcl.HashCode": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "MalY0Y/uM/LjXtHfX/26l2VtN4LDNZ2OE3aumNOHDLsT4fNYy2hiHXI4CXCqKpNUNm7iJ2brrc4J89UdaL56FA==" + }, + "Microsoft.CodeCoverage": { + "type": "Transitive", + "resolved": "17.12.0", + "contentHash": "4svMznBd5JM21JIG2xZKGNanAHNXplxf/kQDFfLHXQ3OnpJkayRK/TjacFjA+EYmoyuNXHo/sOETEfcYtAzIrA==" + }, + "Microsoft.Extensions.AI": { + "type": "Transitive", + "resolved": "10.4.0", + "contentHash": "7kKIuaUMFWikveZUjSrs53XfMVV7IDGSDaGp6/y/hV0HXsA7N2oIODZWxtEkEj8Q4cd/Oc/VlsVlg8efof7gFA==", + "dependencies": { + "Microsoft.Extensions.AI.Abstractions": "10.4.0", + "Microsoft.Extensions.Caching.Abstractions": "10.0.4", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.4", + "Microsoft.Extensions.Logging.Abstractions": "10.0.4", + "System.Diagnostics.DiagnosticSource": "10.0.4", + "System.Numerics.Tensors": "10.0.4", + "System.Text.Json": "10.0.4", + "System.Threading.Channels": "10.0.4" + } + }, + "Microsoft.Extensions.AI.Abstractions": { + "type": "Transitive", + "resolved": "10.4.0", + "contentHash": "t3S2H4do4YeNheIfE3GEl3MnKIrnxpbLu7a88spfApYR3in9ddhIq/GMtxgMaFjn/PUMTCFv5YH7Y6Q91dsDXQ==", + "dependencies": { + "System.Text.Json": "10.0.4" + } + }, + "Microsoft.Extensions.AI.OpenAI": { + "type": "Transitive", + "resolved": "10.4.0", + "contentHash": "7R1fyxwF8KtQi8k2ih3Y6dHZiUfnnmZIgXY7hQ+dFlPkVZoefgKAzdnnrFZzYOjXPeJxh3gqAQ4psXnp59wwqw==", + "dependencies": { + "Microsoft.Extensions.AI.Abstractions": "10.4.0", + "OpenAI": "2.9.1", + "System.Text.Json": "10.0.4" + } + }, + "Microsoft.Extensions.Caching.Abstractions": { + "type": "Transitive", + "resolved": "10.0.4", + "contentHash": "uDRooaV6N3WZ0kdlNPMB68/MdGn/in1Fs7Db7DnIm85RBTPy4P321WO+daAImiYpH5dekjNggDqy1N44WaIlMA==", + "dependencies": { + "Microsoft.Extensions.Primitives": "10.0.4" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "0J/9YNXTMWSZP2p2+nvl8p71zpSwokZXZuJW+VjdErkegAnFdO1XlqtA62SJtgVYHdKu3uPxJHcMR/r35HwFBA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "KC5PslaTDnTuTvyke0KYAVBYdZ7IVTsU3JhHe69BpEbHLcj1YThP3bIGtZNOkZfast2AuLnul5lk4rZKxAdUGQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "10.0.2" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "mBMoXLsr5s1y2zOHWmKsE9veDcx8h1x/c3rz4baEdQKTeDcmQAPNbB54Pi/lhFO3K431eEq6PFbMgLaa6PHFfA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "J/Zmp6fY93JbaiZ11ckWvcyxMPjD6XVwIHQXBjryTBgn7O6O20HYg9uVLFcZlNfgH78MnreE/7EH+hjfzn7VyA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "10.0.4", + "contentHash": "SIe9zlVQJecnk/DTmevIcl6+aEDYhoVLc2eG2AKwVeNEC8CSyxHAbh4lf0xtHq9JUum0vVTEByGNTK+b6oihTQ==" + }, + "Microsoft.Extensions.Diagnostics": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "doVPCUUCY7c6LhBsEfiy3W1bvS7Mi6LkfQMS8nlC22jZWNxBv8VO8bdfeyvpYFst6Kxqk7HBC6lytmEoBssvSQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Diagnostics.Abstractions": "8.0.1", + "Microsoft.Extensions.Options.ConfigurationExtensions": "8.0.0" + } + }, + "Microsoft.Extensions.Diagnostics.Abstractions": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "GaiaeKUuLuUbRPkUokndDuzonhO6dk4lcfGflHsCeXiJ5JrZxcyks1KuG6eB9pON16x/+9uWfa4w9g3oP8AYvQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2", + "Microsoft.Extensions.Options": "10.0.2", + "System.Diagnostics.DiagnosticSource": "10.0.2" + } + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "+r/eJ+slW/EmwWmH3En4gzRg1k6+yTqexoHBrMuz5fxsIKJA8MDiSGepjw/ko3XyNqg+w3dxQe+huoVXs5XDJw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "10.0.2" + } + }, + "Microsoft.Extensions.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "CeAAPVOtI/wtBcHOwq6Pw3VPdGi+pNaGHZj6vfXX/5zr8beO9SyL7IOCSQ70BauFTAFS0QF7f6zu2A6hC8D6nw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.2", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2", + "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.2", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.2", + "Microsoft.Extensions.Logging.Abstractions": "10.0.2" + } + }, + "Microsoft.Extensions.Http": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "kDYeKJUzh0qeg/AI+nSr3ffthmXYQTEb0nS9qRC7YhSbbuN4M4NPbaB77AJwtkTnCV9XZ7qYj3dkZaNcyl73EA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Diagnostics": "8.0.1", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.Extensions.Http.Polly": { + "type": "Transitive", + "resolved": "8.0.22", + "contentHash": "0veowl2NhmxYSvHJN1VqVxghSUdoXRsBXbYO2Z5PpaHEHEiUzGyiVf3aFShVYW+yMMcGvtbJscmMmsvlyZWVXw==", + "dependencies": { + "Microsoft.Extensions.Http": "8.0.1", + "Polly": "7.2.4", + "Polly.Extensions.Http": "3.0.0" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "4x+pzsQEbqxhNf1QYRr5TDkLP9UsLT3A6MdRKDDEgrW7h1ljiEPgTNhKYUhNCCAaVpQECVQ+onA91PTPnIp6Lw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "10.0.4", + "contentHash": "PDMMt7fvBatv6hcxxyJtXIzSwn7Dy00W6I2vDAOTYrQqNM2dF5A2L9n0uMzdPz2IPoNZWkAmYjoOCEdDLq0i4w==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.4", + "System.Diagnostics.DiagnosticSource": "10.0.4" + } + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "1De2LJjmxdqopI5AYC5dIhoZQ79AR5ayywxNF1rXrXFtKQfbQOV9+n/IsZBa7qWlr0MqoGpW8+OY2v/57udZOA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.2", + "Microsoft.Extensions.Primitives": "10.0.2" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "0f4DMRqEd50zQh+UyJc+/HiBsZ3vhAQALgdkcQEalSH1L2isdC7Yj54M3cyo5e+BeO5fcBQ7Dxly8XiBBcvRgw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Configuration.Binder": "8.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Options": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "10.0.4", + "contentHash": "lABYqiRH9HgYJsjzO3W7+cucUwWXhEkiyrRylANdIubnzcESlkIsLowXpQ4E+sc7kjMLbk1hk5oxw4qTKowTEg==" + }, + "Microsoft.Extensions.VectorData.Abstractions": { + "type": "Transitive", + "resolved": "10.1.0", + "contentHash": "I2XfmqEOWOq0Esbo0eWQ6WE5MAJkGyIs057F8ncmPCLJFw9b1IB7Jj5WiFlH6C5YXCAG9Z91QMBD/SkcMLhE7w==", + "dependencies": { + "Microsoft.Extensions.AI.Abstractions": "10.4.0" + } + }, + "Microsoft.SemanticKernel": { + "type": "Transitive", + "resolved": "1.74.0", + "contentHash": "V1N0mR8VHLEY11w2w8ls3Bk60fOjp6TaHOduBXMwfaR5ZF2bho6rCQdonU+6zwAKyD1JB+yT0wJ2xt1hcm60+w==", + "dependencies": { + "Microsoft.SemanticKernel.Connectors.AzureOpenAI": "1.74.0", + "Microsoft.SemanticKernel.Core": "1.74.0" + } + }, + "Microsoft.SemanticKernel.Abstractions": { + "type": "Transitive", + "resolved": "1.74.0", + "contentHash": "e9sPaCiyvi3FzQWbBTjyvLpq4LDaqekz4/xt+Zi30C9cOZRMw6srULEy/jOo9nDXJQ2bsai6JT5TLxuxGwuFWg==", + "dependencies": { + "Microsoft.Bcl.HashCode": "1.1.1", + "Microsoft.Extensions.AI": "10.4.0", + "Microsoft.Extensions.VectorData.Abstractions": "10.1.0", + "System.Linq.AsyncEnumerable": "10.0.4", + "System.Text.Json": "10.0.4" + } + }, + "Microsoft.SemanticKernel.Connectors.AzureOpenAI": { + "type": "Transitive", + "resolved": "1.74.0", + "contentHash": "RZm+Bu4Y42ozRcAEJO9ruaBkyTPnLY/3v9hSWBhma6lj6O5Rva8EOLLZkaZM+Dn7d0dgBXOF4U+tedWtFXrjPg==", + "dependencies": { + "Azure.AI.OpenAI": "2.9.0-beta.1", + "Microsoft.SemanticKernel.Connectors.OpenAI": "1.74.0", + "Microsoft.SemanticKernel.Core": "1.74.0" + } + }, + "Microsoft.SemanticKernel.Connectors.OpenAI": { + "type": "Transitive", + "resolved": "1.74.0", + "contentHash": "xojSsxe0MoJNIQLNGsYiH4jSMDeLnD/yniMEumSz1lt3ybnPHu3Xw1M/C+jfFcqdEXJe64j06b6DRwUs4IjqdQ==", + "dependencies": { + "Microsoft.Extensions.AI.OpenAI": "10.4.0", + "Microsoft.SemanticKernel.Core": "1.74.0", + "OpenAI": "2.9.1" + } + }, + "Microsoft.SemanticKernel.Core": { + "type": "Transitive", + "resolved": "1.74.0", + "contentHash": "SfV2U3jvIy06BCrOkx3Am6c2lurJued7YEGX36wvk8WeSzgwwnkycqSOQTkbV0GLAzYeBKTA7+5mpPypjc7cPw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "10.0.2", + "Microsoft.SemanticKernel.Abstractions": "1.74.0", + "System.Numerics.Tensors": "10.0.4" + } + }, + "Microsoft.TestPlatform.ObjectModel": { + "type": "Transitive", + "resolved": "17.12.0", + "contentHash": "TDqkTKLfQuAaPcEb3pDDWnh7b3SyZF+/W9OZvWFp6eJCIiiYFdSB6taE2I6tWrFw5ywhzOb6sreoGJTI6m3rSQ==", + "dependencies": { + "System.Reflection.Metadata": "1.6.0" + } + }, + "Microsoft.TestPlatform.TestHost": { + "type": "Transitive", + "resolved": "17.12.0", + "contentHash": "MiPEJQNyADfwZ4pJNpQex+t9/jOClBGMiCiVVFuELCMSX2nmNfvUor3uFVxNNCg30uxDP8JDYfPnMXQzsfzYyg==", + "dependencies": { + "Microsoft.TestPlatform.ObjectModel": "17.12.0", + "Newtonsoft.Json": "13.0.1" + } + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.1", + "contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==" + }, + "OpenAI": { + "type": "Transitive", + "resolved": "2.9.1", + "contentHash": "KPTFYEt1EhrPeIZXGBE+DlutFEpMo/RspqSdUJ3p6pMqsw3NeGJcIja/K0He1j9KyRq8ASfzBgp2biWbNUGnFA==", + "dependencies": { + "System.ClientModel": "1.9.0", + "System.Net.ServerSentEvents": "10.0.2" + } + }, + "Polly": { + "type": "Transitive", + "resolved": "7.2.4", + "contentHash": "bw00Ck5sh6ekduDE3mnCo1ohzuad946uslCDEENu3091+6UKnBuKLo4e+yaNcCzXxOZCXWY2gV4a35+K1d4LDA==" + }, + "Polly.Contrib.WaitAndRetry": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "1MUQLiSo4KDkQe6nzQRhIU05lm9jlexX5BVsbuw0SL82ynZ+GzAHQxJVDPVBboxV37Po3SG077aX8DuSy8TkaA==" + }, + "Polly.Extensions.Http": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "drrG+hB3pYFY7w1c3BD+lSGYvH2oIclH8GRSehgfyP5kjnFnHKQuuBhuHLv+PWyFuaTDyk/vfRpnxOzd11+J8g==", + "dependencies": { + "Polly": "7.1.0" + } + }, + "Serilog": { + "type": "Transitive", + "resolved": "3.1.1", + "contentHash": "P6G4/4Kt9bT635bhuwdXlJ2SCqqn2nhh4gqFqQueCOr9bK/e7W9ll/IoX1Ter948cV2Z/5+5v8pAfJYUISY03A==" + }, + "Serilog.Sinks.Console": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "6Jt8jl9y2ey8VV7nVEUAyjjyxjAQuvd5+qj4XYAT9CwcsvR70HHULGBeD+K2WCALFXf7CFsNQT4lON6qXcu2AA==", + "dependencies": { + "Serilog": "3.1.1" + } + }, + "Serilog.Sinks.File": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "uwV5hdhWPwUH1szhO8PJpFiahqXmzPzJT/sOijH/kFgUx+cyoDTMM8MHD0adw9+Iem6itoibbUXHYslzXsLEAg==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "System.ClientModel": { + "type": "Transitive", + "resolved": "1.9.0", + "contentHash": "1wdwKtMMMEFEYsxJmtrOd3G+7zVOVO3MlVZAsbKv9H0PnIx6J27fYAarMn0eQS0vKJPQL018DOb7YRK1O97p0A==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.2", + "Microsoft.Extensions.Hosting.Abstractions": "10.0.2", + "Microsoft.Extensions.Logging.Abstractions": "10.0.2", + "System.Memory.Data": "10.0.1" + } + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "10.0.4", + "contentHash": "WBD8SloNQ9Fp+6Iz+H42w5/VdwYPz9q7iuT6V5ng2FrtR1bYsewmQ3i2PqRR4NnuSZobJ/XtiKkbQyrheDHHdQ==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "10.0.4", + "contentHash": "V7+RO17s/tzCpgqyj6t5vb54HFCvrRaMEwTcKDwpoQK66DRROzSff6kqtzHyiWRj6hrQQUmW80NL4pFSNhYpYA==" + }, + "System.Linq.AsyncEnumerable": { + "type": "Transitive", + "resolved": "10.0.4", + "contentHash": "zGjd0H9R+1ojPL5D5kwvHgKMm4aohcYOChSQrxb9s295xQNxgXhs9L4qAL34SbA2TfRFuAvPTF7AAqPeNacRcg==" + }, + "System.Memory.Data": { + "type": "Transitive", + "resolved": "10.0.1", + "contentHash": "BZC4mhdL569AXV56ep9YO6ShjhxFXGP7SwVX0Bc/e0dJPWnS6aBEXZJXqh64RVx8HquqWHkJUINBydLRQ1yq0g==", + "dependencies": { + "System.Text.Json": "10.0.1" + } + }, + "System.Net.ServerSentEvents": { + "type": "Transitive", + "resolved": "10.0.2", + "contentHash": "pRmUzK1Av9Lqg5tOnk5/0+pFw195eVDP/9gJ2LP0YVPLzOGwjK3Obiutw4CKcJ2Gl9fOYTEc5Za8sB1/xexeGg==" + }, + "System.Numerics.Tensors": { + "type": "Transitive", + "resolved": "10.0.4", + "contentHash": "EK8wJVxnVfeCzchnEqVjIfZDpVIcmjfjUs9x1nzI41X2naPGT57QjoHlQJma2vDQUxEtPQiGv/v90mwcflx6mQ==" + }, + "System.Reflection.Metadata": { + "type": "Transitive", + "resolved": "1.6.0", + "contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ==" + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "10.0.4", + "contentHash": "6g3B7jNsPRNf4luuYt1qE4R8S3JI+zMsfGWL9Idv4Mk1Z9Gh+rCagp9sG3AejPS87yBj1DjopM4i3wSz0WnEqg==" + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "10.0.4", + "contentHash": "1tRPRt8D/kzjGL7em1uJ3iJlvVIC3G/sZJ+ZgSvtVYLXGGO26Clkqy2b5uts/pyR706Yw8/xA7exeI2PI50dpw==", + "dependencies": { + "System.IO.Pipelines": "10.0.4", + "System.Text.Encodings.Web": "10.0.4" + } + }, + "System.Threading.Channels": { + "type": "Transitive", + "resolved": "10.0.4", + "contentHash": "YkecPP9I3PjRouQJzG/JwUoiASqHKddXQrgu+CKHra6yFv6AmTr8PCwzHanNus/kDeujWM4Bqunx7dYFRiPErg==" + }, + "xunit.abstractions": { + "type": "Transitive", + "resolved": "2.0.3", + "contentHash": "pot1I4YOxlWjIb5jmwvvQNbTrZ3lJQ+jUGkGjWE3hEFM0l5gOnBWS+H3qsex68s5cO52g+44vpGzhAt+42vwKg==" + }, + "xunit.analyzers": { + "type": "Transitive", + "resolved": "1.18.0", + "contentHash": "OtFMHN8yqIcYP9wcVIgJrq01AfTxijjAqVDy/WeQVSyrDC1RzBWeQPztL49DN2syXRah8TYnfvk035s7L95EZQ==" + }, + "xunit.assert": { + "type": "Transitive", + "resolved": "2.9.3", + "contentHash": "/Kq28fCE7MjOV42YLVRAJzRF0WmEqsmflm0cfpMjGtzQ2lR5mYVj1/i0Y8uDAOLczkL3/jArrwehfMD0YogMAA==" + }, + "xunit.core": { + "type": "Transitive", + "resolved": "2.9.3", + "contentHash": "BiAEvqGvyme19wE0wTKdADH+NloYqikiU0mcnmiNyXaF9HyHmE6sr/3DC5vnBkgsWaE6yPyWszKSPSApWdRVeQ==", + "dependencies": { + "xunit.extensibility.core": "[2.9.3]", + "xunit.extensibility.execution": "[2.9.3]" + } + }, + "xunit.extensibility.core": { + "type": "Transitive", + "resolved": "2.9.3", + "contentHash": "kf3si0YTn2a8J8eZNb+zFpwfoyvIrQ7ivNk5ZYA5yuYk1bEtMe4DxJ2CF/qsRgmEnDr7MnW1mxylBaHTZ4qErA==", + "dependencies": { + "xunit.abstractions": "2.0.3" + } + }, + "xunit.extensibility.execution": { + "type": "Transitive", + "resolved": "2.9.3", + "contentHash": "yMb6vMESlSrE3Wfj7V6cjQ3S4TXdXpRqYeNEI3zsX31uTsGMJjEw6oD5F5u1cHnMptjhEECnmZSsPxB6ChZHDQ==", + "dependencies": { + "xunit.extensibility.core": "[2.9.3]" + } + }, + "deepgramsemantickernel": { + "type": "Project", + "dependencies": { + "Deepgram": "[6.6.1, )", + "Microsoft.SemanticKernel": "[1.74.0, )" + } + } + } + } +} \ No newline at end of file