init
This commit is contained in:
16
Services/IChatSessionService.cs
Normal file
16
Services/IChatSessionService.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using Alchegos.HCI.Models;
|
||||
|
||||
namespace Alchegos.HCI.Services;
|
||||
public interface IChatSessionService
|
||||
{
|
||||
ChatSession GetOrCreateSession(string sessionId);
|
||||
ChatSession? GetSession(string sessionId);
|
||||
void AddMessage(string sessionId, ChatMessage message);
|
||||
void SetWaitingStatus(string sessionId, bool isWaiting);
|
||||
void RemoveSession(string sessionId);
|
||||
Task SendMessageToExternalWebhook(string sessionId, string chatInput);
|
||||
void RegisterSessionCallbacks(string sessionId, Func<ChatMessage, Task>? messageCallback, Func<Task>? closeCallback);
|
||||
void UnregisterSessionCallbacks(string sessionId);
|
||||
Task TriggerMessageReceived(string sessionId, string output);
|
||||
Task TriggerSessionClosed(string sessionId);
|
||||
}
|
||||
157
Services/InMemoryChatSessionService.cs
Normal file
157
Services/InMemoryChatSessionService.cs
Normal file
@@ -0,0 +1,157 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using Alchegos.HCI.Models;
|
||||
|
||||
namespace Alchegos.HCI.Services;
|
||||
|
||||
public class InMemoryChatSessionService : IChatSessionService
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, ChatSession> _sessions = new();
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly ILogger<InMemoryChatSessionService> _logger;
|
||||
|
||||
public InMemoryChatSessionService(IHttpClientFactory httpClientFactory, IConfiguration configuration,
|
||||
ILogger<InMemoryChatSessionService> logger)
|
||||
{
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_configuration = configuration;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public ChatSession GetOrCreateSession(string sessionId)
|
||||
{
|
||||
return _sessions.GetOrAdd(sessionId, id => new ChatSession { SessionId = id });
|
||||
}
|
||||
|
||||
public ChatSession? GetSession(string sessionId)
|
||||
{
|
||||
_sessions.TryGetValue(sessionId, out var session);
|
||||
return session;
|
||||
}
|
||||
|
||||
public void AddMessage(string sessionId, ChatMessage message)
|
||||
{
|
||||
if (_sessions.TryGetValue(sessionId, out var session))
|
||||
{
|
||||
session.Messages.Add(message);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetWaitingStatus(string sessionId, bool isWaiting)
|
||||
{
|
||||
if (_sessions.TryGetValue(sessionId, out var session))
|
||||
{
|
||||
session.IsWaitingForResponse = isWaiting;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveSession(string sessionId)
|
||||
{
|
||||
if (_sessions.TryRemove(sessionId, out var session))
|
||||
_logger.LogInformation("Session removed: {SessionId}", sessionId);
|
||||
else
|
||||
_logger.LogWarning("Attempted to remove non-existent session: {SessionId}", sessionId);
|
||||
}
|
||||
|
||||
public void RegisterSessionCallbacks(string sessionId, Func<ChatMessage, Task>? messageCallback,
|
||||
Func<Task>? closeCallback)
|
||||
{
|
||||
if (_sessions.TryGetValue(sessionId, out var session))
|
||||
{
|
||||
session.NotifyMessageReceived = messageCallback;
|
||||
session.NotifySessionClosed = closeCallback;
|
||||
_logger.LogInformation("Registered callbacks for session: {SessionId}", sessionId);
|
||||
}
|
||||
else
|
||||
_logger.LogWarning("Attempted to register callbacks for non-existent session: {SessionId}", sessionId);
|
||||
|
||||
}
|
||||
|
||||
public void UnregisterSessionCallbacks(string sessionId)
|
||||
{
|
||||
if (_sessions.TryGetValue(sessionId, out var session))
|
||||
{
|
||||
session.NotifyMessageReceived = null;
|
||||
session.NotifySessionClosed = null;
|
||||
_logger.LogInformation("Unregistered callbacks for session: {SessionId}", sessionId);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SendMessageToExternalWebhook(string sessionId, string chatInput)
|
||||
{
|
||||
var webhookUrl = _configuration["ChatSettings:ExternalWebhookUrl"];
|
||||
if (string.IsNullOrEmpty(webhookUrl))
|
||||
{
|
||||
_logger.LogError("ExternalWebhookUrl is not configured in ChatSettings.");
|
||||
SetWaitingStatus(sessionId, false);
|
||||
return;
|
||||
}
|
||||
|
||||
var payload = new { sessionId, chatInput };
|
||||
var jsonPayload = JsonSerializer.Serialize(payload);
|
||||
var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
|
||||
|
||||
try
|
||||
{
|
||||
var httpClient = _httpClientFactory.CreateClient();
|
||||
_logger.LogInformation("Sending message to webhook for session {SessionId}: {Url}", sessionId, webhookUrl);
|
||||
var response = await httpClient.PostAsync(webhookUrl, content);
|
||||
response.EnsureSuccessStatusCode();
|
||||
_logger.LogInformation("Successfully sent message to webhook for session {SessionId}", sessionId);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error sending message to external webhook for session {SessionId}", sessionId);
|
||||
AddMessage(sessionId, new ChatMessage { IsUser = false, Content = $"Error sending message: {ex.Message}" });
|
||||
SetWaitingStatus(sessionId, false);
|
||||
await TriggerMessageReceived(sessionId, $"Error: Could not reach the processing service.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Unexpected error sending message to external webhook for session {SessionId}",
|
||||
sessionId);
|
||||
AddMessage(sessionId,
|
||||
new ChatMessage { IsUser = false, Content = $"An unexpected error occurred: {ex.Message}" });
|
||||
SetWaitingStatus(sessionId, false);
|
||||
await TriggerMessageReceived(sessionId, $"Error: An unexpected error occurred.");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task TriggerMessageReceived(string sessionId, string output)
|
||||
{
|
||||
if (_sessions.TryGetValue(sessionId, out var session))
|
||||
{
|
||||
_logger.LogInformation("Received message via webhook for session {SessionId}", sessionId);
|
||||
var serverMessage = new ChatMessage { IsUser = false, Content = output };
|
||||
session.Messages.Add(serverMessage);
|
||||
session.IsWaitingForResponse = false;
|
||||
|
||||
if (session.NotifyMessageReceived != null)
|
||||
await session.NotifyMessageReceived(serverMessage);
|
||||
else
|
||||
_logger.LogWarning("No message callback registered for session {SessionId} to notify.", sessionId);
|
||||
|
||||
}
|
||||
else
|
||||
_logger.LogWarning("Received message for non-existent or inactive session: {SessionId}", sessionId);
|
||||
|
||||
}
|
||||
|
||||
public async Task TriggerSessionClosed(string sessionId)
|
||||
{
|
||||
if (_sessions.TryGetValue(sessionId, out var session))
|
||||
{
|
||||
_logger.LogInformation("Received close request via webhook for session {SessionId}", sessionId);
|
||||
if (session.NotifySessionClosed != null)
|
||||
await session.NotifySessionClosed();
|
||||
else
|
||||
_logger.LogWarning("No close callback registered for session {SessionId} to notify.", sessionId);
|
||||
RemoveSession(sessionId);
|
||||
}
|
||||
else
|
||||
_logger.LogWarning("Received close request for non-existent or already removed session: {SessionId}",
|
||||
sessionId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user