File: OllamaUtilities.cs
Web Access
Project: src\src\Libraries\Microsoft.Extensions.AI.Ollama\Microsoft.Extensions.AI.Ollama.csproj (Microsoft.Extensions.AI.Ollama)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Net.Http;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
 
namespace Microsoft.Extensions.AI;
 
internal static class OllamaUtilities
{
    /// <summary>Gets a singleton <see cref="HttpClient"/> used when no other instance is supplied.</summary>
    public static HttpClient SharedClient { get; } = new()
    {
        // Expected use is localhost access for non-production use. Typical production use should supply
        // an HttpClient configured with whatever more robust resilience policy / handlers are appropriate.
        Timeout = Timeout.InfiniteTimeSpan,
    };
 
    public static void TransferNanosecondsTime<TResponse>(TResponse response, Func<TResponse, long?> getNanoseconds, string key, ref AdditionalPropertiesDictionary<long>? metadata)
    {
        if (getNanoseconds(response) is long duration)
        {
            try
            {
                (metadata ??= [])[key] = duration;
            }
            catch (OverflowException)
            {
                // Ignore options that don't convert
            }
        }
    }
 
    [DoesNotReturn]
    public static async ValueTask ThrowUnsuccessfulOllamaResponseAsync(HttpResponseMessage response, CancellationToken cancellationToken)
    {
        Debug.Assert(!response.IsSuccessStatusCode, "must only be invoked for unsuccessful responses.");
 
        // Read the entire response content into a string.
        string errorContent =
#if NET
            await response.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false);
#else
            await response.Content.ReadAsStringAsync().ConfigureAwait(false);
#endif
 
        // The response content *could* be JSON formatted, try to extract the error field.
 
#pragma warning disable CA1031 // Do not catch general exception types
        try
        {
            using JsonDocument document = JsonDocument.Parse(errorContent);
            if (document.RootElement.TryGetProperty("error", out JsonElement errorElement) &&
                errorElement.ValueKind is JsonValueKind.String)
            {
                errorContent = errorElement.GetString()!;
            }
        }
        catch
        {
            // Ignore JSON parsing errors.
        }
#pragma warning restore CA1031 // Do not catch general exception types
 
        throw new InvalidOperationException($"Ollama error: {errorContent}");
    }
}