Merge pull request #1095 from iceljc/master

refine chat stream with initial states
This commit is contained in:
iceljc 2025-07-09 15:27:53 -05:00 committed by GitHub
commit 5adaa3ac96
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 28 additions and 15 deletions

View file

@ -13,5 +13,5 @@ public interface IRealtimeHub
IRealTimeCompletion Completer { get; }
Task ConnectToModel(Func<string, Task>? responseToUser = null, Func<string, Task>? init = null);
Task ConnectToModel(Func<string, Task>? responseToUser = null, Func<string, Task>? init = null, List<MessageState>? initStates = null);
}

View file

@ -1,5 +1,6 @@
using BotSharp.Abstraction.Functions.Models;
using BotSharp.Abstraction.Hooks;
using BotSharp.Abstraction.Models;
using BotSharp.Abstraction.Options;
using BotSharp.Core.Infrastructures;
@ -22,10 +23,10 @@ public class RealtimeHub : IRealtimeHub
_logger = logger;
}
public async Task ConnectToModel(Func<string, Task>? responseToUser = null, Func<string, Task>? init = null)
public async Task ConnectToModel(Func<string, Task>? responseToUser = null, Func<string, Task>? init = null, List<MessageState>? initStates = null)
{
var convService = _services.GetRequiredService<IConversationService>();
convService.SetConversationId(_conn.ConversationId, []);
convService.SetConversationId(_conn.ConversationId, initStates ?? []);
var conversation = await convService.GetConversation(_conn.ConversationId);
var routing = _services.GetRequiredService<IRoutingService>();

View file

@ -1,3 +1,4 @@
using BotSharp.Abstraction.Models;
using BotSharp.Abstraction.Realtime.Models.Session;
using BotSharp.Core.Session;
using Microsoft.AspNetCore.Http;
@ -66,6 +67,7 @@ public class ChatStreamMiddleware
// load conversation and state
var convService = services.GetRequiredService<IConversationService>();
var state = services.GetRequiredService<IConversationStateService>();
convService.SetConversationId(conversationId, []);
await convService.GetConversationRecordOrCreateNew(agentId);
@ -80,7 +82,8 @@ public class ChatStreamMiddleware
var (eventType, data) = MapEvents(conn, receivedText);
if (eventType == "start")
{
await ConnectToModel(hub, webSocket);
var states = InitStates(data);
await ConnectToModel(hub, webSocket, states);
}
else if (eventType == "media")
{
@ -96,25 +99,26 @@ public class ChatStreamMiddleware
}
}
convService.SaveStates();
await _session.DisconnectAsync();
_session.Dispose();
}
private async Task ConnectToModel(IRealtimeHub hub, WebSocket webSocket)
private async Task ConnectToModel(IRealtimeHub hub, WebSocket webSocket, List<MessageState>? states = null)
{
await hub.ConnectToModel(async data =>
await hub.ConnectToModel(responseToUser: async data =>
{
if (_session != null)
{
await _session.SendEventAsync(data);
}
});
}, initStates: states);
}
private (string, string) MapEvents(RealtimeHubConnection conn, string receivedText)
{
var response = JsonSerializer.Deserialize<ChatStreamEventResponse>(receivedText);
string data = string.Empty;
var data = response?.Body?.Payload ?? string.Empty;
switch (response.Event)
{
@ -122,8 +126,6 @@ public class ChatStreamMiddleware
conn.ResetStreamState();
break;
case "media":
var mediaResponse = JsonSerializer.Deserialize<ChatStreamMediaEventResponse>(receivedText);
data = mediaResponse?.Body?.Payload ?? string.Empty;
break;
case "disconnect":
break;
@ -154,4 +156,17 @@ public class ChatStreamMiddleware
@event = "clear"
});
}
private List<MessageState> InitStates(string data)
{
try
{
var states = JsonSerializer.Deserialize<List<MessageState>>(data, BotSharpOptions.defaultJsonOptions);
return states ?? [];
}
catch
{
return [];
}
}
}

View file

@ -6,15 +6,12 @@ internal class ChatStreamEventResponse
{
[JsonPropertyName("event")]
public string Event { get; set; }
}
internal class ChatStreamMediaEventResponse : ChatStreamEventResponse
{
[JsonPropertyName("body")]
public MediaEventResponseBody Body { get; set; }
public ChatStreamEventResponseBody Body { get; set; }
}
internal class MediaEventResponseBody
internal class ChatStreamEventResponseBody
{
[JsonPropertyName("payload")]
public string Payload { get; set; }