V2 / df3fc286644d
Lilith.cs
Lilith/Agent/Lilith.cs
Changed in this versionCS
using Lilith.Core.Logging;
using Lilith.Core.Ollama;
using Lilith.Core.Providers;
using Lilith.Core.Kokoro;
namespace Lilith.Agent;
public partial class Lilith(Action<LogEntry> onLog, LilithCredentials? credentials = null) : IAsyncDisposable
{
private KokoroTts? _tts;
private readonly SemaphoreSlim _operation = new(1, 1);
private bool _disposed;
private ProviderClient _llmclient = null!;
private readonly LilithCredentials _credentials = credentials ?? new();
public LilithCredentials Credentials => _credentials;
public Logger Logger { get; } = new(onLog);
internal Func<bool, Task<ProviderClient>>? ProviderFactory { get; set; }
private ProviderClient Client
{
get
{
ObjectDisposedException.ThrowIf(_disposed, this);
return _llmclient ?? throw new InvalidOperationException("Boot the agent before using its conversation.");
}
}
public ChatHistory History => Client.History;
public int ContextMax => Client.ContextMax;
public int CurrentContextTokens => Client.CurrentContextTokens;
private async Task InitializeProviderAsync(bool startServerIfNotRunning)
{
_llmclient = ProviderFactory is { } factory ? await factory(startServerIfNotRunning) : await this.CreateClient(startServerIfNotRunning);
foreach (var tool in Tools) _llmclient.RegisterTool(tool);
}
/// <summary>Configure before boot. The template is deliberately not enabled.</summary>
public List<global::Lilith.Core.Tools.ILilithTool> Tools { get; } = [new global::Lilith.Core.Tools.CurrentTimeTool()];
private IDisposable EnterOperation(string? bootRequiredMessage = null)
{
var operation = _operation.EnterOrThrow("An agent operation is already in progress.");
try
{
ObjectDisposedException.ThrowIf(_disposed, this);
if (bootRequiredMessage is not null && !IsBooted) throw new InvalidOperationException(bootRequiredMessage);
return operation;
}
catch { operation.Dispose(); throw; }
}
public async ValueTask DisposeAsync()
{
using var operation = await _operation.EnterAsync();
if (_disposed) return;
_disposed = true;
try { if (_tts is not null) await _tts.DisposeAsync(); }
finally { _llmclient?.Dispose(); IsBooted = false; }
}
}