using AIStudio.Chat; using AIStudio.Provider; using AIStudio.Settings; // ReSharper disable MemberCanBePrivate.Global namespace AIStudio.Agents; public abstract class AgentBase(ILogger logger, SettingsManager settingsManager, ThreadSafeRandom rng) : IAgent { protected SettingsManager SettingsManager { get; init; } = settingsManager; protected ThreadSafeRandom RNG { get; init; } = rng; protected ILogger Logger { get; init; } = logger; /// /// Represents the type or category of this agent. /// protected abstract Type Type { get; } /// /// The name of the agent. /// public abstract string Id { get; } /// /// The agent's job description. Will be used for the system prompt. /// protected abstract string JobDescription { get; } /// /// Represents the system prompt provided for the agent. /// protected abstract string SystemPrompt(string additionalData); #region Implementation of IAgent public abstract AIStudio.Settings.Provider? ProviderSettings { get; set; } public abstract Task ProcessContext(ChatThread chatThread, IDictionary additionalData); public abstract Task ProcessInput(ContentBlock input, IDictionary additionalData); public abstract Task MadeDecision(ContentBlock input); public abstract IReadOnlyCollection GetContext(); public abstract IReadOnlyCollection GetAnswers(); #endregion protected ChatThread CreateChatThread(string systemPrompt) => new() { WorkspaceId = Guid.Empty, ChatId = Guid.NewGuid(), Name = string.Empty, Seed = this.RNG.Next(), SystemPrompt = systemPrompt, Blocks = [], }; protected DateTimeOffset AddUserRequest(ChatThread thread, string request) { var time = DateTimeOffset.Now; thread.Blocks.Add(new ContentBlock { Time = time, ContentType = ContentType.TEXT, Role = ChatRole.USER, Content = new ContentText { Text = request, }, }); return time; } protected async Task AddAIResponseAsync(ChatThread thread, DateTimeOffset time) { if(this.ProviderSettings is null) return; var providerSettings = this.ProviderSettings.Value; var aiText = new ContentText { // We have to wait for the remote // for the content stream: InitialRemoteWait = true, }; var resultingContentBlock = new ContentBlock { Time = time, ContentType = ContentType.TEXT, Role = ChatRole.AI, Content = aiText, }; thread.Blocks.Add(resultingContentBlock); // Use the selected provider to get the AI response. // By awaiting this line, we wait for the entire // content to be streamed. await aiText.CreateFromProviderAsync(providerSettings.CreateProvider(this.Logger), this.SettingsManager, providerSettings.Model, thread); } }