← All source files

V18 / 8d896b8a86e5

Core.cs

Lilith/Core/Core.cs

Unchanged from the preceding version
CS
namespace Lilith.Core;

/// <summary>
/// Root hub for agent addons. Create one instance and access <see cref="Logger"/>,
/// <see cref="OllamaClient"/>, and future services from the same object.
/// </summary>
public class Core(Action<LogEntry>? onLog = null) : IDisposable
{
    private static readonly Lazy<Core> Shared = new(() => new());
    private readonly object _sync = new();
    private OllamaClient? _client;
    private bool _ownsClient;
    private bool _disposed;

    /// <summary>Shared application core (optional).</summary>
    public static Core Default => Shared.Value;

    /// <summary>Subscribe-based logging (console, GUI, file, etc.).</summary>
    public Logger Logger { get; } = new(onLog);

    /// <summary>
    /// Ollama client addon. Assign after construction or via <see cref="UseOllamaAsync"/>.
    /// </summary>
    public OllamaClient? OllamaClient
    {
        get { lock (_sync) { ObjectDisposedException.ThrowIf(_disposed, this); return _client; } }
        set => Attach(value, owned: false);
    }

    /// <summary>Attach an Ollama client and return it for chaining.</summary>
    public OllamaClient UseOllama(OllamaClient ollamaClient)
    {
        Attach(ollamaClient ?? throw new ArgumentNullException(nameof(ollamaClient)), owned: false);
        return ollamaClient;
    }

    /// <summary>
    /// Creates and attaches a client for an already prepared model. Installation/download
    /// are explicit setup operations; this method only starts/checks the server and validates readiness.
    /// </summary>
    public async Task<OllamaClient> UseOllamaAsync(string model, string systemPrompt, bool startOllamaIfNotRunning = true)
    {
        lock (_sync) ObjectDisposedException.ThrowIf(_disposed, this);
        var client = await OllamaClient.CreateClient(model, systemPrompt, Logger, startOllamaIfNotRunning);
        try { Attach(client, owned: true); return client; }
        catch { client.Dispose(); throw; }
    }

    /// <summary>External attachments are borrowed; clients created by UseOllamaAsync are owned.</summary>
    internal void Attach(OllamaClient? client, bool owned)
    {
        lock (_sync)
        {
            ObjectDisposedException.ThrowIf(_disposed, this);
            if (ReferenceEquals(_client, client)) return;
            if (_ownsClient) _client?.Dispose();
            _client = client;
            _ownsClient = owned;
        }
    }

    public void Dispose()
    {
        lock (_sync)
        {
            if (_disposed) return;
            if (_ownsClient) _client?.Dispose();
            _disposed = true;
            _client = null;
            _ownsClient = false;
        }
        GC.SuppressFinalize(this);
    }
}