forked from admin/VolcanicAgenticCore
76 lines
3.2 KiB
C#
76 lines
3.2 KiB
C#
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
using Volcanic.AgenticCore.Features.Agent;
|
|
using Volcanic.AgenticCore.Features.Extensions;
|
|
using Volcanic.AgenticCore.Features.Sessions;
|
|
using Volcanic.AgenticCore.Hosting;
|
|
using Volcanic.AgenticCore.Telegram.Chats;
|
|
using Volcanic.AgenticCore.Telegram.Rendering;
|
|
using Volcanic.AgenticCore.Testing;
|
|
|
|
namespace Volcanic.AgenticCore.Telegram.Tests.Support;
|
|
|
|
/// <summary>The bot's chat side wired to a <see cref="FakeBotClient"/> and the <see cref="FauxProvider"/>.</summary>
|
|
public sealed class ChatHost : IAsyncDisposable
|
|
{
|
|
public FakeBotClient Bot { get; } = new();
|
|
public FauxProvider Faux { get; } = new();
|
|
public TelegramOptions Options { get; }
|
|
public ChatRegistry Chats { get; }
|
|
public UpdateRouter Router { get; }
|
|
private readonly ServiceProvider _services;
|
|
private readonly string _root;
|
|
|
|
public ChatHost()
|
|
{
|
|
_root = Path.Combine(Path.GetTempPath(), "volcanic-telegram", Guid.NewGuid().ToString("N"));
|
|
Options = new TelegramOptions
|
|
{
|
|
BotToken = "test",
|
|
AllowedUserIds = [Updates.AllowedUser],
|
|
WorkspaceRoot = Path.Combine(_root, "workspaces"),
|
|
Model = FauxProvider.ModelKey,
|
|
EditInterval = TimeSpan.FromMilliseconds(20),
|
|
TypingInterval = TimeSpan.FromMilliseconds(50),
|
|
};
|
|
var store = new InMemorySessionStore();
|
|
var services = new ServiceCollection();
|
|
services.AddAgenticCore(o =>
|
|
{
|
|
o.AgentDir = Path.Combine(_root, "agent");
|
|
o.DiscoverExtensionAssemblies = false;
|
|
o.DefaultModel = FauxProvider.ModelKey;
|
|
o.Extensions.Add(ExtensionRegistration.FromInstance(Faux.Extension));
|
|
o.SessionStoreFactory = _ => store;
|
|
});
|
|
_services = services.BuildServiceProvider();
|
|
ILoggerFactory loggers = NullLoggerFactory.Instance;
|
|
var sender = new TelegramSender(Bot, NullLogger<TelegramSender>.Instance);
|
|
Chats = new ChatRegistry(_services.GetRequiredService<IAgentSessionFactory>(), sender, Options, loggers);
|
|
Router = new UpdateRouter(Options, Chats, new ChatCommands(sender), sender, NullLogger<UpdateRouter>.Instance);
|
|
}
|
|
|
|
public Task SendAsync(string text, long userId = Updates.AllowedUser) => Router.RouteAsync(Updates.Text(text, userId), CancellationToken.None);
|
|
|
|
public async Task<ChatContext> ChatAsync() => await Chats.GetAsync(Updates.AllowedUser);
|
|
|
|
/// <summary>Wait until the chat's run has settled and everything it produced is rendered.</summary>
|
|
public async Task SettleAsync()
|
|
{
|
|
var chat = await ChatAsync();
|
|
await chat.LastPrompt.WaitAsync(TimeSpan.FromSeconds(10));
|
|
await Wait.UntilAsync(() => !chat.Session.IsStreaming, "the run to settle");
|
|
await chat.Renderer.DrainAsync().WaitAsync(TimeSpan.FromSeconds(5));
|
|
}
|
|
|
|
public IEnumerable<string> Texts => Bot.CurrentTexts.OrderBy(kv => kv.Key).Select(kv => kv.Value);
|
|
|
|
public async ValueTask DisposeAsync()
|
|
{
|
|
await Chats.DisposeAsync();
|
|
await _services.DisposeAsync();
|
|
try { Directory.Delete(_root, true); } catch (IOException) { }
|
|
}
|
|
}
|