using Discord; using Discord.Interactions; using Microsoft.Extensions.Logging; using TentacleBot.Services; namespace TentacleBot.Commands; [Group("llm", "LLM chat commands")] public class LlmCommands : InteractionModuleBase { private readonly LlmService _llmService; private readonly ILogger _logger; public LlmCommands(LlmService llmService, ILogger logger) { _llmService = llmService; _logger = logger; } [SlashCommand("chat", "Chat with the LLM model")] public async Task HandleChatAsync( [Summary("prompt", "Your message to the LLM")] string prompt) { await DeferAsync(); var channelId = Context.Channel.Id; var userName = Context.User.Username; try { var accumulated = ""; await foreach (var text in _llmService.SendMessageAsync(channelId, userName, prompt)) { accumulated = text; } if (string.IsNullOrWhiteSpace(accumulated)) { await FollowupAsync(embed: new EmbedBuilder() .WithTitle("LLM Response") .WithDescription("The model returned an empty response.") .WithColor(Color.Orange) .Build()); return; } if (accumulated.Length <= 4096) { await FollowupAsync(embed: new EmbedBuilder() .WithTitle($"Response from {Context.Client.CurrentUser?.Username}") .WithDescription(Format.Code(accumulated)) .WithColor(Color.DarkTeal) .WithTimestamp(DateTimeOffset.UtcNow) .Build()); } else { var truncated = accumulated.Substring(0, 4096); await FollowupAsync(embed: new EmbedBuilder() .WithTitle("LLM Response (truncated)") .WithDescription($"{Format.Code(truncated)}\n\n*Response exceeded Discord's message limit and was truncated.*") .WithColor(Color.Orange) .WithTimestamp(DateTimeOffset.UtcNow) .Build()); var remaining = accumulated.Substring(4096); var continuation = "Continued..."; while (remaining.Length > 0) { var chunk = remaining.Length > 4096 ? remaining.Substring(0, 4096) : remaining; continuation += $"\n\n{Format.Code(chunk)}"; remaining = remaining.Substring(4096); try { await FollowupAsync(continuation, embed: new EmbedBuilder() .WithTitle("LLM Response (continued)") .WithColor(Color.DarkTeal) .Build()); continuation = ""; } catch (Exception ex) { _logger.LogWarning(ex, "Error sending continuation message"); break; } } } } catch (Exception ex) { _logger.LogError(ex, "Error in LLM chat command"); await FollowupAsync(embed: new EmbedBuilder() .WithTitle("Error") .WithDescription("An error occurred while communicating with the LLM.") .WithColor(Color.Red) .WithTimestamp(DateTimeOffset.UtcNow) .Build()); } } // [SlashCommand("reset", "Reset conversation history for this channel")] // public async Task HandleResetAsync() // { // _llmService.ResetHistory(Context.Channel.Id); // var embed = new EmbedBuilder() // .WithTitle("History Reset") // .WithDescription("Conversation history for this channel has been cleared.") // .WithColor(Color.Green) // .WithTimestamp(DateTimeOffset.UtcNow) // .Build(); // await RespondAsync(embed: embed); // } }