BotSharp/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs

564 lines
19 KiB
C#
Raw Normal View History

2024-01-10 14:18:59 +00:00
using Microsoft.AspNetCore.SignalR;
2024-04-23 21:27:09 +00:00
using System.Text.Encodings.Web;
using System.Text.Unicode;
2024-07-23 22:44:39 +00:00
using Newtonsoft.Json.Linq;
using JsonConvert = Newtonsoft.Json.JsonConvert;
using JsonSerializerSettings = Newtonsoft.Json.JsonSerializerSettings;
2024-01-10 14:18:59 +00:00
namespace BotSharp.Plugin.ChatHub.Hooks;
2024-02-28 16:21:14 +00:00
public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook, IRoutingHook
2024-01-10 14:18:59 +00:00
{
private readonly ConversationSetting _convSettings;
2024-03-18 19:36:41 +00:00
private readonly BotSharpOptions _options;
2024-05-08 19:32:09 +00:00
private readonly JsonSerializerOptions _localJsonOptions;
2024-01-10 14:18:59 +00:00
private readonly IServiceProvider _services;
private readonly IHubContext<SignalRHub> _chatHub;
2024-01-24 23:47:57 +00:00
private readonly IConversationStateService _state;
private readonly IUserIdentity _user;
2024-02-23 01:53:00 +00:00
private readonly IAgentService _agentService;
2024-02-28 20:40:59 +00:00
private readonly IRoutingContext _routingCtx;
2024-01-10 14:18:59 +00:00
2024-07-23 22:44:39 +00:00
#region Event
private const string CONTENT_LOG_GENERATED = "OnConversationContentLogGenerated";
private const string STATE_LOG_GENERATED = "OnConversateStateLogGenerated";
private const string AGENT_QUEUE_CHANGED = "OnAgentQueueChanged";
private const string STATE_CHANGED = "OnStateChangeGenerated";
#endregion
2024-01-10 14:18:59 +00:00
public StreamingLogHook(
ConversationSetting convSettings,
2024-03-18 19:36:41 +00:00
BotSharpOptions options,
2024-01-10 14:18:59 +00:00
IServiceProvider serivces,
2024-01-24 23:47:57 +00:00
IHubContext<SignalRHub> chatHub,
IConversationStateService state,
2024-02-23 01:53:00 +00:00
IUserIdentity user,
2024-02-28 20:40:59 +00:00
IAgentService agentService,
IRoutingContext routingCtx)
2024-01-10 14:18:59 +00:00
{
_convSettings = convSettings;
2024-03-18 19:36:41 +00:00
_options = options;
2024-01-10 14:18:59 +00:00
_services = serivces;
_chatHub = chatHub;
2024-01-24 23:47:57 +00:00
_state = state;
_user = user;
2024-02-23 01:53:00 +00:00
_agentService = agentService;
2024-02-28 20:40:59 +00:00
_routingCtx = routingCtx;
2024-05-08 19:32:09 +00:00
_localJsonOptions = InitLocalJsonOptions(options);
2024-01-10 14:18:59 +00:00
}
2024-02-22 17:25:13 +00:00
2024-03-22 19:06:20 +00:00
#region IConversationHook
2024-01-24 23:47:57 +00:00
public override async Task OnMessageReceived(RoleDialogModel message)
{
var conversationId = _state.GetConversationId();
if (string.IsNullOrEmpty(conversationId)) return;
2024-04-23 21:27:09 +00:00
var log = $"{GetMessageContent(message)}";
2024-02-29 23:17:43 +00:00
2024-03-01 02:50:39 +00:00
var input = new ContentLogInputModel(conversationId, message)
2024-02-29 23:17:43 +00:00
{
Name = _user.UserName,
Source = ContentLogSource.UserInput,
Log = log
};
2024-07-23 22:44:39 +00:00
await SendContentLog(input);
2024-01-24 23:47:57 +00:00
}
2024-01-10 14:18:59 +00:00
2024-03-16 14:43:00 +00:00
public override async Task OnPostbackMessageReceived(RoleDialogModel message, PostbackMessageModel replyMsg)
{
var conversationId = _state.GetConversationId();
if (string.IsNullOrEmpty(conversationId)) return;
2024-04-23 21:27:09 +00:00
var log = $"{GetMessageContent(message)}";
2024-03-18 19:36:41 +00:00
var replyContent = JsonSerializer.Serialize(replyMsg, _options.JsonSerializerOptions);
2024-03-16 14:43:00 +00:00
log += $"\r\n```json\r\n{replyContent}\r\n```";
var input = new ContentLogInputModel(conversationId, message)
{
Name = _user.UserName,
Source = ContentLogSource.UserInput,
Log = log
};
2024-07-23 22:44:39 +00:00
await SendContentLog(input);
2024-03-16 14:43:00 +00:00
}
2024-03-31 19:28:16 +00:00
public async Task OnRenderingTemplate(Agent agent, string name, string content)
{
if (!_convSettings.ShowVerboseLog) return;
var conversationId = _state.GetConversationId();
if (string.IsNullOrEmpty(conversationId)) return;
2024-03-31 19:28:16 +00:00
var log = $"{agent.Name} is using template {name}";
var message = new RoleDialogModel(AgentRole.System, log)
{
MessageId = _routingCtx.MessageId
};
var input = new ContentLogInputModel(conversationId, message)
{
Name = agent.Name,
Source = ContentLogSource.HardRule,
Log = log
};
2024-07-23 22:44:39 +00:00
await SendContentLog(input);
2024-03-31 19:28:16 +00:00
}
2024-01-10 14:18:59 +00:00
public async Task BeforeGenerating(Agent agent, List<RoleDialogModel> conversations)
{
if (!_convSettings.ShowVerboseLog) return;
2024-01-24 23:47:57 +00:00
}
2024-04-06 23:33:49 +00:00
public override async Task OnFunctionExecuting(RoleDialogModel message)
2024-01-24 23:47:57 +00:00
{
2024-02-20 20:37:32 +00:00
var conversationId = _state.GetConversationId();
if (string.IsNullOrEmpty(conversationId)) return;
if (message.FunctionName == "route_to_agent") return;
2024-02-23 01:53:00 +00:00
var agent = await _agentService.LoadAgent(message.CurrentAgentId);
message.FunctionArgs = message.FunctionArgs ?? "{}";
var args = message.FunctionArgs.FormatJson();
2024-04-06 23:33:49 +00:00
var log = $"{message.FunctionName} <u>executing</u>\r\n```json\r\n{args}\r\n```";
var input = new ContentLogInputModel(conversationId, message)
{
Name = agent?.Name,
AgentId = agent?.Id,
Source = ContentLogSource.FunctionCall,
Log = log
};
2024-07-23 22:44:39 +00:00
await SendContentLog(input);
2024-04-06 23:33:49 +00:00
}
public override async Task OnFunctionExecuted(RoleDialogModel message)
{
var conversationId = _state.GetConversationId();
if (string.IsNullOrEmpty(conversationId)) return;
if (message.FunctionName == "route_to_agent") return;
2024-04-06 23:33:49 +00:00
var agent = await _agentService.LoadAgent(message.CurrentAgentId);
message.FunctionArgs = message.FunctionArgs ?? "{}";
var log = $"{message.FunctionName} =>\r\n*{message.Content?.Trim()}*";
2024-02-29 23:17:43 +00:00
2024-03-01 02:50:39 +00:00
var input = new ContentLogInputModel(conversationId, message)
2024-02-29 23:17:43 +00:00
{
Name = agent?.Name,
AgentId = agent?.Id,
Source = ContentLogSource.FunctionCall,
Log = log
};
2024-07-23 22:44:39 +00:00
await SendContentLog(input);
2024-01-10 14:18:59 +00:00
}
2024-02-20 20:37:32 +00:00
/// <summary>
/// Used to log prompt
/// </summary>
/// <param name="message"></param>
/// <param name="tokenStats"></param>
/// <returns></returns>
2024-01-10 14:18:59 +00:00
public async Task AfterGenerated(RoleDialogModel message, TokenStatsModel tokenStats)
{
if (!_convSettings.ShowVerboseLog) return;
2024-01-24 23:47:57 +00:00
var conversationId = _state.GetConversationId();
if (string.IsNullOrEmpty(conversationId)) return;
2024-02-23 01:53:00 +00:00
var agent = await _agentService.LoadAgent(message.CurrentAgentId);
2024-01-10 14:18:59 +00:00
2024-02-22 21:14:13 +00:00
var log = tokenStats.Prompt;
2024-02-29 23:17:43 +00:00
2024-03-01 02:50:39 +00:00
var input = new ContentLogInputModel(conversationId, message)
2024-02-29 23:17:43 +00:00
{
Name = agent?.Name,
AgentId = agent?.Id,
Source = ContentLogSource.Prompt,
Log = log
};
2024-07-23 22:44:39 +00:00
await SendContentLog(input);
2024-01-19 04:38:44 +00:00
}
2024-02-20 20:37:32 +00:00
/// <summary>
/// Used to log final response
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
2024-02-16 21:58:39 +00:00
public override async Task OnResponseGenerated(RoleDialogModel message)
{
var conversationId = _state.GetConversationId();
if (string.IsNullOrEmpty(conversationId)) return;
2024-02-16 21:58:39 +00:00
var conv = _services.GetRequiredService<IConversationService>();
2024-07-23 22:44:39 +00:00
await SendStateLog(conv.ConversationId, _state.GetStates(), message);
2024-02-20 20:37:32 +00:00
if (message.Role == AgentRole.Assistant)
{
2024-02-23 01:53:00 +00:00
var agent = await _agentService.LoadAgent(message.CurrentAgentId);
2024-04-23 21:27:09 +00:00
var log = $"{GetMessageContent(message)}";
if (message.RichContent != null || message.SecondaryRichContent != null)
2024-02-20 20:37:32 +00:00
{
2024-05-08 19:32:09 +00:00
var richContent = JsonSerializer.Serialize(message.SecondaryRichContent ?? message.RichContent, _localJsonOptions);
log += $"\r\n```json\r\n{richContent}\r\n```";
2024-02-20 20:37:32 +00:00
}
2024-02-15 20:43:36 +00:00
2024-03-01 02:50:39 +00:00
var input = new ContentLogInputModel(conv.ConversationId, message)
2024-02-29 23:17:43 +00:00
{
Name = agent?.Name,
AgentId = agent?.Id,
Source = ContentLogSource.AgentResponse,
Log = log
};
2024-07-23 22:44:39 +00:00
await SendContentLog(input);
2024-02-16 21:58:39 +00:00
}
}
2024-02-28 16:21:14 +00:00
2024-03-22 19:06:20 +00:00
public override async Task OnTaskCompleted(RoleDialogModel message)
{
var conversationId = _state.GetConversationId();
if (string.IsNullOrEmpty(conversationId)) return;
2024-04-23 21:27:09 +00:00
var log = $"{GetMessageContent(message)}";
2024-03-22 19:06:20 +00:00
var agent = await _agentService.LoadAgent(message.CurrentAgentId);
var input = new ContentLogInputModel(conversationId, message)
{
Name = agent.Name,
Source = ContentLogSource.FunctionCall,
Log = log
};
2024-07-23 22:44:39 +00:00
await SendContentLog(input);
2024-03-22 19:06:20 +00:00
}
public override async Task OnConversationEnding(RoleDialogModel message)
{
var conversationId = _state.GetConversationId();
if (string.IsNullOrEmpty(conversationId)) return;
2024-03-22 19:06:20 +00:00
var log = $"Conversation ended";
var agent = await _agentService.LoadAgent(message.CurrentAgentId);
var input = new ContentLogInputModel(conversationId, message)
{
Name = agent?.Name ?? "System",
Source = ContentLogSource.FunctionCall,
Log = log
};
2024-07-23 22:44:39 +00:00
await SendContentLog(input);
2024-03-22 19:06:20 +00:00
}
2024-03-24 13:56:21 +00:00
public override async Task OnBreakpointUpdated(string conversationId, bool resetStates)
{
if (string.IsNullOrEmpty(conversationId)) return;
2024-03-24 13:56:21 +00:00
var log = $"Conversation breakpoint is updated";
if (resetStates)
{
log += ", states are reset";
}
var routing = _services.GetRequiredService<IRoutingService>();
var agentId = routing.Context.GetCurrentAgentId();
2024-03-24 13:56:21 +00:00
var agent = await _agentService.LoadAgent(agentId);
var input = new ContentLogInputModel()
{
Name = agent.Name,
AgentId = agentId,
2024-03-24 13:56:21 +00:00
ConversationId = conversationId,
2024-03-27 20:06:24 +00:00
Source = ContentLogSource.HardRule,
Message = new RoleDialogModel(AgentRole.Assistant, "OnBreakpointUpdated")
{
MessageId = _routingCtx.MessageId
},
2024-03-24 13:56:21 +00:00
Log = log
};
2024-07-23 22:44:39 +00:00
await SendContentLog(input);
2024-03-24 13:56:21 +00:00
}
2024-03-28 18:16:16 +00:00
public override async Task OnStateChanged(StateChangeModel stateChange)
{
var conversationId = _state.GetConversationId();
if (string.IsNullOrEmpty(conversationId)) return;
2024-03-28 18:16:16 +00:00
if (stateChange == null) return;
2024-07-23 22:44:39 +00:00
await SendStateChange(stateChange);
2024-03-28 18:16:16 +00:00
}
2024-03-22 19:06:20 +00:00
#endregion
2024-02-28 16:21:14 +00:00
#region IRoutingHook
2024-02-28 20:40:59 +00:00
public async Task OnAgentEnqueued(string agentId, string preAgentId, string? reason = null)
2024-02-28 16:21:14 +00:00
{
var conversationId = _state.GetConversationId();
if (string.IsNullOrEmpty(conversationId)) return;
2024-02-28 16:21:14 +00:00
var agent = await _agentService.LoadAgent(agentId);
2024-04-01 04:55:13 +00:00
// Agent queue log
var log = $"{agent.Name} is enqueued";
2024-07-23 22:44:39 +00:00
await SendAgentQueueLog(conversationId, log);
2024-04-01 04:55:13 +00:00
// Content log
log = $"{agent.Name} is enqueued{(reason != null ? $" ({reason})" : "")}";
2024-02-29 23:17:43 +00:00
var message = new RoleDialogModel(AgentRole.System, log)
{
MessageId = _routingCtx.MessageId
};
2024-03-01 02:50:39 +00:00
var input = new ContentLogInputModel(conversationId, message)
2024-02-29 23:17:43 +00:00
{
Name = "Router",
Source = ContentLogSource.HardRule,
Log = log
};
2024-07-23 22:44:39 +00:00
await SendContentLog(input);
2024-02-28 16:21:14 +00:00
}
2024-02-28 20:40:59 +00:00
public async Task OnAgentDequeued(string agentId, string currentAgentId, string? reason = null)
2024-02-28 16:21:14 +00:00
{
var conversationId = _state.GetConversationId();
if (string.IsNullOrEmpty(conversationId)) return;
2024-02-28 16:21:14 +00:00
var agent = await _agentService.LoadAgent(agentId);
var currentAgent = await _agentService.LoadAgent(currentAgentId);
2024-04-01 04:55:13 +00:00
// Agent queue log
var log = $"{agent.Name} is dequeued";
2024-07-23 22:44:39 +00:00
await SendAgentQueueLog(conversationId, log);
2024-04-01 04:55:13 +00:00
// Content log
log = $"{agent.Name} is dequeued{(reason != null ? $" ({reason})" : "")}, current agent is {currentAgent?.Name}";
2024-02-29 23:17:43 +00:00
var message = new RoleDialogModel(AgentRole.System, log)
{
MessageId = _routingCtx.MessageId
};
2024-03-01 02:50:39 +00:00
var input = new ContentLogInputModel(conversationId, message)
2024-02-29 23:17:43 +00:00
{
Name = "Router",
Source = ContentLogSource.HardRule,
Log = log
};
2024-07-23 22:44:39 +00:00
await SendContentLog(input);
2024-02-28 16:21:14 +00:00
}
2024-02-28 20:40:59 +00:00
public async Task OnAgentReplaced(string fromAgentId, string toAgentId, string? reason = null)
2024-02-28 16:21:14 +00:00
{
var conversationId = _state.GetConversationId();
if (string.IsNullOrEmpty(conversationId)) return;
2024-02-28 16:21:14 +00:00
var fromAgent = await _agentService.LoadAgent(fromAgentId);
var toAgent = await _agentService.LoadAgent(toAgentId);
2024-04-01 04:55:13 +00:00
// Agent queue log
var log = $"Agent queue is replaced from {fromAgent.Name} to {toAgent.Name}";
2024-07-23 22:44:39 +00:00
await SendAgentQueueLog(conversationId, log);
2024-04-01 04:55:13 +00:00
// Content log
log = $"{fromAgent.Name} is replaced to {toAgent.Name}{(reason != null ? $" ({reason})" : "")}";
2024-02-29 23:17:43 +00:00
var message = new RoleDialogModel(AgentRole.System, log)
{
MessageId = _routingCtx.MessageId
};
2024-03-01 02:50:39 +00:00
var input = new ContentLogInputModel(conversationId, message)
2024-02-29 23:17:43 +00:00
{
Name = "Router",
Source = ContentLogSource.HardRule,
Log = log
};
2024-07-23 22:44:39 +00:00
await SendContentLog(input);
2024-02-28 16:21:14 +00:00
}
2024-02-28 20:40:59 +00:00
public async Task OnAgentQueueEmptied(string agentId, string? reason = null)
2024-02-28 16:21:14 +00:00
{
var conversationId = _state.GetConversationId();
if (string.IsNullOrEmpty(conversationId)) return;
2024-02-28 16:21:14 +00:00
2024-04-01 04:55:13 +00:00
// Agent queue log
var log = $"Agent queue is empty";
2024-07-23 22:44:39 +00:00
await SendAgentQueueLog(conversationId, log);
2024-04-01 04:55:13 +00:00
// Content log
log = reason ?? "Agent queue is cleared";
2024-02-29 23:17:43 +00:00
var message = new RoleDialogModel(AgentRole.System, log)
{
MessageId = _routingCtx.MessageId
};
2024-03-01 02:50:39 +00:00
var input = new ContentLogInputModel(conversationId, message)
2024-02-29 23:17:43 +00:00
{
Name = "Router",
Source = ContentLogSource.HardRule,
Log = log
};
2024-07-23 22:44:39 +00:00
await SendContentLog(input);
2024-02-28 16:21:14 +00:00
}
2024-03-07 18:27:29 +00:00
public async Task OnRoutingInstructionReceived(FunctionCallFromLlm instruct, RoleDialogModel message)
2024-02-28 16:21:14 +00:00
{
var conversationId = _state.GetConversationId();
if (string.IsNullOrEmpty(conversationId)) return;
2024-02-28 16:21:14 +00:00
var agent = await _agentService.LoadAgent(message.CurrentAgentId);
2024-03-18 19:36:41 +00:00
var log = JsonSerializer.Serialize(instruct, _options.JsonSerializerOptions);
log = $"```json\r\n{log}\r\n```";
2024-02-29 23:17:43 +00:00
2024-03-01 02:50:39 +00:00
var input = new ContentLogInputModel(conversationId, message)
2024-02-29 23:17:43 +00:00
{
Name = agent?.Name,
AgentId = agent?.Id,
Source = ContentLogSource.AgentResponse,
Log = log
};
2024-07-23 22:44:39 +00:00
await SendContentLog(input);
2024-02-28 16:21:14 +00:00
}
2024-03-07 18:27:29 +00:00
public async Task OnRoutingInstructionRevised(FunctionCallFromLlm instruct, RoleDialogModel message)
{
var conversationId = _state.GetConversationId();
if (string.IsNullOrEmpty(conversationId)) return;
2024-03-07 18:27:29 +00:00
var agent = await _agentService.LoadAgent(message.CurrentAgentId);
2024-03-31 16:12:20 +00:00
var log = $"Revised user goal agent to {instruct.OriginalAgent}";
2024-03-07 18:27:29 +00:00
var input = new ContentLogInputModel(conversationId, message)
{
Name = agent?.Name,
AgentId = agent?.Id,
Source = ContentLogSource.HardRule,
Log = log
};
2024-07-23 22:44:39 +00:00
await SendContentLog(input);
2024-03-07 18:27:29 +00:00
}
2024-02-28 16:21:14 +00:00
#endregion
2024-02-29 23:17:43 +00:00
2024-07-23 22:44:39 +00:00
#region Private methods
private async Task SendContentLog(ContentLogInputModel input)
{
await _chatHub.Clients.User(_user.Id).SendAsync(CONTENT_LOG_GENERATED, BuildContentLog(input));
}
private async Task SendStateLog(string conversationId, Dictionary<string, string> states, RoleDialogModel message)
{
await _chatHub.Clients.User(_user.Id).SendAsync(STATE_LOG_GENERATED, BuildStateLog(conversationId, states, message));
}
private async Task SendAgentQueueLog(string conversationId, string log)
{
await _chatHub.Clients.User(_user.Id).SendAsync(AGENT_QUEUE_CHANGED, BuildAgentQueueChangedLog(conversationId, log));
}
private async Task SendStateChange(StateChangeModel stateChange)
{
await _chatHub.Clients.User(_user.Id).SendAsync(STATE_CHANGED, BuildStateChangeLog(stateChange));
}
2024-03-01 02:50:39 +00:00
private string BuildContentLog(ContentLogInputModel input)
2024-02-29 23:17:43 +00:00
{
2024-03-01 02:50:39 +00:00
var output = new ContentLogOutputModel
2024-02-29 23:17:43 +00:00
{
ConversationId = input.ConversationId,
MessageId = input.Message.MessageId,
Name = input.Name,
2024-03-01 02:50:39 +00:00
AgentId = input.AgentId,
2024-02-29 23:17:43 +00:00
Role = input.Message.Role,
Content = input.Log,
Source = input.Source,
2024-05-10 02:37:32 +00:00
CreateTime = DateTime.UtcNow
2024-02-29 23:17:43 +00:00
};
2024-03-18 19:36:41 +00:00
var json = JsonSerializer.Serialize(output, _options.JsonSerializerOptions);
2024-02-29 23:17:43 +00:00
var convSettings = _services.GetRequiredService<ConversationSetting>();
if (convSettings.EnableContentLog)
{
var db = _services.GetRequiredService<IBotSharpRepository>();
2024-03-01 02:50:39 +00:00
db.SaveConversationContentLog(output);
2024-02-29 23:17:43 +00:00
}
return json;
}
private string BuildStateLog(string conversationId, Dictionary<string, string> states, RoleDialogModel message)
{
var log = new ConversationStateLogModel
{
ConversationId = conversationId,
MessageId = message.MessageId,
States = states,
2024-05-10 02:37:32 +00:00
CreateTime = DateTime.UtcNow
2024-02-29 23:17:43 +00:00
};
var convSettings = _services.GetRequiredService<ConversationSetting>();
if (convSettings.EnableStateLog)
{
var db = _services.GetRequiredService<IBotSharpRepository>();
db.SaveConversationStateLog(log);
}
2024-03-18 19:36:41 +00:00
return JsonSerializer.Serialize(log, _options.JsonSerializerOptions);
2024-02-29 23:17:43 +00:00
}
2024-03-28 18:16:16 +00:00
private string BuildStateChangeLog(StateChangeModel stateChange)
{
var log = new StateChangeOutputModel
{
ConversationId = stateChange.ConversationId,
MessageId = stateChange.MessageId,
Name = stateChange.Name,
BeforeValue = stateChange.BeforeValue,
2024-03-31 03:43:45 +00:00
BeforeActiveRounds = stateChange.BeforeActiveRounds,
2024-03-28 18:16:16 +00:00
AfterValue = stateChange.AfterValue,
2024-03-31 03:43:45 +00:00
AfterActiveRounds = stateChange.AfterActiveRounds,
2024-04-02 19:09:42 +00:00
DataType = stateChange.DataType,
Source = stateChange.Source,
2024-04-02 20:39:14 +00:00
Readonly = stateChange.Readonly,
2024-03-28 18:16:16 +00:00
CreateTime = DateTime.UtcNow
};
return JsonSerializer.Serialize(log, _options.JsonSerializerOptions);
}
2024-04-01 04:55:13 +00:00
private string BuildAgentQueueChangedLog(string conversationId, string log)
{
var model = new AgentQueueChangedLogModel
{
ConversationId = conversationId,
Log = log,
CreateTime = DateTime.UtcNow
};
return JsonSerializer.Serialize(model, _options.JsonSerializerOptions);
}
2024-04-23 21:27:09 +00:00
private string GetMessageContent(RoleDialogModel message)
{
return !string.IsNullOrEmpty(message.SecondaryContent) ? message.SecondaryContent : message.Content;
}
2024-05-08 19:32:09 +00:00
private JsonSerializerOptions InitLocalJsonOptions(BotSharpOptions options)
{
var localOptions = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
AllowTrailingCommas = true,
WriteIndented = true,
Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
};
if (options?.JsonSerializerOptions != null && !options.JsonSerializerOptions.Converters.IsNullOrEmpty())
{
foreach (var converter in options.JsonSerializerOptions.Converters)
{
localOptions.Converters.Add(converter);
}
}
return localOptions;
}
2024-07-23 22:44:39 +00:00
#endregion
2024-03-27 20:06:24 +00:00
}