commit
f41820f830
|
|
@ -12,7 +12,7 @@ public interface IAgentService
|
|||
Task<Agent> CreateAgent(Agent agent);
|
||||
Task<string> RefreshAgents();
|
||||
Task<PagedItems<Agent>> GetAgents(AgentFilter filter);
|
||||
Task<List<IdName>> GetAgentOptions();
|
||||
Task<List<IdName>> GetAgentOptions(List<string>? agentIds = null);
|
||||
|
||||
/// <summary>
|
||||
/// Load agent configurations and trigger hooks
|
||||
|
|
|
|||
|
|
@ -6,4 +6,5 @@ public static class MessageTypeName
|
|||
public const string Notification = "notification";
|
||||
public const string FunctionCall = "function";
|
||||
public const string Audio = "audio";
|
||||
public const string Error = "error";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,14 +62,7 @@ public interface IConversationService
|
|||
|
||||
void SaveStates();
|
||||
|
||||
/// <summary>
|
||||
/// Get conversation keys for searching
|
||||
/// </summary>
|
||||
/// <param name="query">search query</param>
|
||||
/// <param name="convLimit">conversation limit</param>
|
||||
/// <param name="preLoad">if pre-loading, then keys are not filter by the search query</param>
|
||||
/// <returns></returns>
|
||||
Task<List<string>> GetConversationStateSearhKeys(string query, int convLimit = 100, int keyLimit = 10, bool preload = false);
|
||||
Task<List<string>> GetConversationStateSearhKeys(ConversationStateKeysFilter filter);
|
||||
|
||||
Task<bool> MigrateLatestStates(int batchSize = 100, int errorLimit = 10);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
using BotSharp.Abstraction.Instructs.Models;
|
||||
using BotSharp.Abstraction.Loggers.Models;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
|
||||
namespace BotSharp.Abstraction.Loggers.Services;
|
||||
|
||||
|
|
@ -12,5 +12,6 @@ public interface ILoggerService
|
|||
|
||||
#region Instruction
|
||||
Task<PagedItems<InstructionLogModel>> GetInstructionLogs(InstructLogFilter filter);
|
||||
Task<List<string>> GetInstructionLogSearchKeys(InstructLogKeysFilter filter);
|
||||
#endregion
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,9 +23,9 @@ public class ConversationFilter
|
|||
/// <summary>
|
||||
/// Check whether each key in the list is in the conversation states and its value equals to target value if not empty
|
||||
/// </summary>
|
||||
public IEnumerable<KeyValue>? States { get; set; } = [];
|
||||
public List<KeyValue>? States { get; set; }
|
||||
|
||||
public IEnumerable<string>? Tags { get; set; } = [];
|
||||
public List<string>? Tags { get; set; }
|
||||
|
||||
public static ConversationFilter Empty()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
namespace BotSharp.Abstraction.Repositories.Filters;
|
||||
|
||||
public class ConversationStateKeysFilter
|
||||
{
|
||||
public string? Query { get; set; }
|
||||
public int KeyLimit { get; set; } = 10;
|
||||
public int ConvLimit { get; set; } = 100;
|
||||
public bool PreLoad { get; set; }
|
||||
public List<string>? AgentIds { get; set; }
|
||||
public List<string>? UserIds { get; set; }
|
||||
|
||||
public ConversationStateKeysFilter()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static ConversationStateKeysFilter Empty()
|
||||
{
|
||||
return new();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
namespace BotSharp.Abstraction.Instructs.Models;
|
||||
namespace BotSharp.Abstraction.Repositories.Filters;
|
||||
|
||||
public class InstructLogFilter : Pagination
|
||||
{
|
||||
|
|
@ -11,6 +11,6 @@ public class InstructLogFilter : Pagination
|
|||
|
||||
public static InstructLogFilter Empty()
|
||||
{
|
||||
return new InstructLogFilter();
|
||||
return new();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
namespace BotSharp.Abstraction.Repositories.Filters;
|
||||
|
||||
public class InstructLogKeysFilter
|
||||
{
|
||||
public string? Query { get; set; }
|
||||
public int KeyLimit { get; set; } = 10;
|
||||
public int LogLimit { get; set; } = 100;
|
||||
public bool PreLoad { get; set; }
|
||||
public List<string>? AgentIds { get; set; }
|
||||
public List<string>? UserIds { get; set; }
|
||||
|
||||
public InstructLogKeysFilter()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static InstructLogKeysFilter Empty()
|
||||
{
|
||||
return new();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
using BotSharp.Abstraction.Instructs.Models;
|
||||
using BotSharp.Abstraction.Loggers.Models;
|
||||
using BotSharp.Abstraction.Plugins.Models;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
|
|
@ -149,7 +148,7 @@ public interface IBotSharpRepository : IHaveServiceProvider
|
|||
=> throw new NotImplementedException();
|
||||
List<string> TruncateConversation(string conversationId, string messageId, bool cleanLog = false)
|
||||
=> throw new NotImplementedException();
|
||||
List<string> GetConversationStateSearchKeys(int messageLowerLimit = 2, int convUpperLimit = 100)
|
||||
List<string> GetConversationStateSearchKeys(ConversationStateKeysFilter filter)
|
||||
=> throw new NotImplementedException();
|
||||
List<string> GetConversationsToMigrate(int batchSize = 100)
|
||||
=> throw new NotImplementedException();
|
||||
|
|
@ -182,6 +181,9 @@ public interface IBotSharpRepository : IHaveServiceProvider
|
|||
|
||||
PagedItems<InstructionLogModel> GetInstructionLogs(InstructLogFilter filter)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
List<string> GetInstructionLogSearchKeys(InstructLogKeysFilter filter)
|
||||
=> throw new NotImplementedException();
|
||||
#endregion
|
||||
|
||||
#region Statistics
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ public interface IUserService
|
|||
Task<PagedItems<User>> GetUsers(UserFilter filter);
|
||||
Task<List<User>> SearchLoginUsers(User filter);
|
||||
Task<User?> GetUserDetails(string userId, bool includeAgent = false);
|
||||
Task<bool> IsAdminUser(string userId);
|
||||
Task<(bool, User?)> IsAdminUser(string userId);
|
||||
Task<UserAuthorization> GetUserAuthorizations(IEnumerable<string>? agentIds = null);
|
||||
Task<bool> UpdateUser(User user, bool isUpdateUserAgents = false);
|
||||
Task<User> CreateUser(User user);
|
||||
|
|
|
|||
|
|
@ -30,9 +30,12 @@ public partial class AgentService
|
|||
#if !DEBUG
|
||||
[SharpCache(10, perInstanceCache: true)]
|
||||
#endif
|
||||
public async Task<List<IdName>> GetAgentOptions()
|
||||
public async Task<List<IdName>> GetAgentOptions(List<string>? agentIds)
|
||||
{
|
||||
var agents = _db.GetAgents(AgentFilter.Empty());
|
||||
var agents = _db.GetAgents(new AgentFilter
|
||||
{
|
||||
AgentIds = !agentIds.IsNullOrEmpty() ? agentIds : null
|
||||
});
|
||||
return agents?.Select(x => new IdName(x.Id, x.Name))?.OrderBy(x => x.Name)?.ToList() ?? [];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ public partial class AgentService
|
|||
|
||||
var userIdentity = _services.GetRequiredService<IUserIdentity>();
|
||||
var userService = _services.GetRequiredService<IUserService>();
|
||||
var isValid = await userService.IsAdminUser(userIdentity.Id);
|
||||
var (isValid, _) = await userService.IsAdminUser(userIdentity.Id);
|
||||
if (!isValid)
|
||||
{
|
||||
return "Unauthorized user.";
|
||||
|
|
|
|||
|
|
@ -222,17 +222,26 @@ public partial class ConversationService : IConversationService
|
|||
_state.Save();
|
||||
}
|
||||
|
||||
public async Task<List<string>> GetConversationStateSearhKeys(string query, int convLimit = 100, int keyLimit = 10, bool preload = false)
|
||||
public async Task<List<string>> GetConversationStateSearhKeys(ConversationStateKeysFilter filter)
|
||||
{
|
||||
if (filter == null)
|
||||
{
|
||||
filter = ConversationStateKeysFilter.Empty();
|
||||
}
|
||||
|
||||
var keys = new List<string>();
|
||||
if (!preload && string.IsNullOrWhiteSpace(query))
|
||||
if (!filter.PreLoad && string.IsNullOrWhiteSpace(filter.Query))
|
||||
{
|
||||
return keys;
|
||||
}
|
||||
|
||||
var userService = _services.GetRequiredService<IUserService>();
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
keys = db.GetConversationStateSearchKeys(convUpperLimit: convLimit);
|
||||
keys = preload ? keys : keys.Where(x => x.Contains(query, StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
return keys.OrderBy(x => x).Take(keyLimit).ToList();
|
||||
|
||||
var (isAdmin, user) = await userService.IsAdminUser(_user.Id);
|
||||
filter.UserIds = !isAdmin && user?.Id != null ? [user.Id] : [];
|
||||
keys = db.GetConversationStateSearchKeys(filter);
|
||||
keys = filter.PreLoad ? keys : keys.Where(x => x.Contains(filter.Query ?? string.Empty, StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
return keys.OrderBy(x => x).Take(filter.KeyLimit).ToList();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
using BotSharp.Abstraction.Instructs.Models;
|
||||
using BotSharp.Abstraction.Loggers.Models;
|
||||
using BotSharp.Abstraction.Users.Enums;
|
||||
using BotSharp.Abstraction.Users.Models;
|
||||
|
||||
namespace BotSharp.Core.Loggers.Services;
|
||||
|
|
@ -15,11 +13,10 @@ public partial class LoggerService
|
|||
}
|
||||
|
||||
var userService = _services.GetRequiredService<IUserService>();
|
||||
var user = await userService.GetUser(_user.Id);
|
||||
var isAdmin = UserConstant.AdminRoles.Contains(user?.Role);
|
||||
var (isAdmin, user) = await userService.IsAdminUser(_user.Id);
|
||||
if (!isAdmin && user?.Id == null) return new();
|
||||
|
||||
filter.UserIds = isAdmin ? [] : user?.Id != null ? [user.Id] : [];
|
||||
filter.UserIds = !isAdmin && user?.Id != null ? [user.Id] : null;
|
||||
|
||||
var agents = new List<Agent>();
|
||||
var users = new List<User>();
|
||||
|
|
@ -61,4 +58,27 @@ public partial class LoggerService
|
|||
Count = logs.Count
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<List<string>> GetInstructionLogSearchKeys(InstructLogKeysFilter filter)
|
||||
{
|
||||
if (filter == null)
|
||||
{
|
||||
filter = InstructLogKeysFilter.Empty();
|
||||
}
|
||||
|
||||
var keys = new List<string>();
|
||||
if (!filter.PreLoad && string.IsNullOrWhiteSpace(filter.Query))
|
||||
{
|
||||
return keys;
|
||||
}
|
||||
|
||||
var userService = _services.GetRequiredService<IUserService>();
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
|
||||
var (isAdmin, user) = await userService.IsAdminUser(_user.Id);
|
||||
filter.UserIds = !isAdmin && user?.Id != null ? [user.Id] : null;
|
||||
keys = db.GetInstructionLogSearchKeys(filter);
|
||||
keys = filter.PreLoad ? keys : keys.Where(x => x.Contains(filter.Query ?? string.Empty, StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
return keys.OrderBy(x => x).Take(filter.KeyLimit).ToList();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using BotSharp.Abstraction.Loggers.Models;
|
||||
using BotSharp.Abstraction.Users.Models;
|
||||
using System.IO;
|
||||
|
||||
namespace BotSharp.Core.Repository;
|
||||
|
|
@ -647,7 +648,7 @@ public partial class FileRepository
|
|||
#if !DEBUG
|
||||
[SharpCache(10)]
|
||||
#endif
|
||||
public List<string> GetConversationStateSearchKeys(int messageLowerLimit = 2, int convUpperLimit = 100)
|
||||
public List<string> GetConversationStateSearchKeys(ConversationStateKeysFilter filter)
|
||||
{
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, _conversationSettings.DataDir);
|
||||
if (!Directory.Exists(dir)) return [];
|
||||
|
|
@ -658,26 +659,29 @@ public partial class FileRepository
|
|||
foreach (var d in Directory.GetDirectories(dir))
|
||||
{
|
||||
var convFile = Path.Combine(d, CONVERSATION_FILE);
|
||||
var stateFile = Path.Combine(d, STATE_FILE);
|
||||
if (!File.Exists(convFile) || !File.Exists(stateFile))
|
||||
var latestStateFile = Path.Combine(d, CONV_LATEST_STATE_FILE);
|
||||
if (!File.Exists(convFile) || !File.Exists(latestStateFile))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var convJson = File.ReadAllText(convFile);
|
||||
var stateJson = File.ReadAllText(stateFile);
|
||||
var stateJson = File.ReadAllText(latestStateFile);
|
||||
var conv = JsonSerializer.Deserialize<Conversation>(convJson, _options);
|
||||
var states = JsonSerializer.Deserialize<List<StateKeyValue>>(stateJson, _options);
|
||||
if (conv == null || conv.DialogCount < messageLowerLimit)
|
||||
var states = JsonSerializer.Deserialize<Dictionary<string, JsonDocument>>(stateJson, _options);
|
||||
if (conv == null
|
||||
|| states.IsNullOrEmpty()
|
||||
|| (!filter.AgentIds.IsNullOrEmpty() && !filter.AgentIds.Contains(conv.AgentId))
|
||||
|| (!filter.UserIds.IsNullOrEmpty() && !filter.UserIds.Contains(conv.UserId)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var stateKeys = states?.Select(x => x.Key)?.Distinct()?.ToList() ?? [];
|
||||
var stateKeys = states?.Select(x => x.Key)?.ToList() ?? [];
|
||||
keys.AddRange(stateKeys);
|
||||
count++;
|
||||
|
||||
if (count >= convUpperLimit)
|
||||
if (count >= filter.ConvLimit)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
using BotSharp.Abstraction.Instructs.Models;
|
||||
using BotSharp.Abstraction.Loggers.Models;
|
||||
using System.IO;
|
||||
|
||||
|
|
@ -271,6 +270,44 @@ namespace BotSharp.Core.Repository
|
|||
Count = logs.Count()
|
||||
};
|
||||
}
|
||||
|
||||
public List<string> GetInstructionLogSearchKeys(InstructLogKeysFilter filter)
|
||||
{
|
||||
var keys = new List<string>();
|
||||
var baseDir = Path.Combine(_dbSettings.FileRepository, INSTRUCTION_LOG_FOLDER);
|
||||
if (!Directory.Exists(baseDir))
|
||||
{
|
||||
return keys;
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
var files = Directory.GetFiles(baseDir);
|
||||
foreach (var file in files)
|
||||
{
|
||||
var json = File.ReadAllText(file);
|
||||
var log = JsonSerializer.Deserialize<InstructionLogModel>(json, _options);
|
||||
if (log == null) continue;
|
||||
|
||||
if (log == null
|
||||
|| log.InnerStates.IsNullOrEmpty()
|
||||
|| (!filter.UserIds.IsNullOrEmpty() && !filter.UserIds.Contains(log.UserId))
|
||||
|| (!filter.AgentIds.IsNullOrEmpty() && !filter.AgentIds.Contains(log.AgentId)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var stateKeys = log.InnerStates.Select(x => x.Key)?.ToList() ?? [];
|
||||
keys.AddRange(stateKeys);
|
||||
count++;
|
||||
|
||||
if (count >= filter.LogLimit)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return keys.Distinct().ToList();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private methods
|
||||
|
|
|
|||
|
|
@ -418,23 +418,24 @@ public class UserService : IUserService
|
|||
return users;
|
||||
}
|
||||
|
||||
public async Task<bool> IsAdminUser(string userId)
|
||||
[SharpCache(10, perInstanceCache: true)]
|
||||
public async Task<(bool, User?)> IsAdminUser(string userId)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var user = db.GetUserById(userId);
|
||||
return user != null && UserConstant.AdminRoles.Contains(user.Role);
|
||||
var isAdmin = user != null && UserConstant.AdminRoles.Contains(user.Role);
|
||||
return (isAdmin, user);
|
||||
}
|
||||
|
||||
public async Task<UserAuthorization> GetUserAuthorizations(IEnumerable<string>? agentIds = null)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var user = db.GetUserById(_user.Id);
|
||||
var (isAdmin, user) = await IsAdminUser(_user.Id);
|
||||
var auth = new UserAuthorization();
|
||||
|
||||
if (user == null) return auth;
|
||||
|
||||
auth.IsAdmin = UserConstant.AdminRoles.Contains(user.Role);
|
||||
|
||||
auth.IsAdmin = isAdmin;
|
||||
var role = db.GetRoles(new RoleFilter { Names = [user.Role] }).FirstOrDefault();
|
||||
var permissions = user.Permissions?.Any() == true ? user.Permissions : role?.Permissions ?? [];
|
||||
auth.Permissions = permissions;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
using Azure;
|
||||
using BotSharp.Abstraction.Files.Constants;
|
||||
using BotSharp.Abstraction.Files.Enums;
|
||||
using BotSharp.Abstraction.Files.Utilities;
|
||||
using BotSharp.Abstraction.Options;
|
||||
using BotSharp.Abstraction.Routing;
|
||||
using BotSharp.Abstraction.Users.Enums;
|
||||
using BotSharp.Core.Infrastructures;
|
||||
|
||||
namespace BotSharp.OpenAPI.Controllers;
|
||||
|
|
@ -45,27 +43,33 @@ public class ConversationController : ControllerBase
|
|||
return ConversationViewModel.FromSession(conv);
|
||||
}
|
||||
|
||||
[HttpPost("/conversations")]
|
||||
public async Task<PagedItems<ConversationViewModel>> GetConversations([FromBody] ConversationFilter filter)
|
||||
[HttpGet("/conversations")]
|
||||
public async Task<PagedItems<ConversationViewModel>> GetConversations([FromQuery] ConversationFilter filter)
|
||||
{
|
||||
var convService = _services.GetRequiredService<IConversationService>();
|
||||
var userService = _services.GetRequiredService<IUserService>();
|
||||
var user = await userService.GetUser(_user.Id);
|
||||
var (isAdmin, user) = await userService.IsAdminUser(_user.Id);
|
||||
if (user == null)
|
||||
{
|
||||
return new PagedItems<ConversationViewModel>();
|
||||
}
|
||||
|
||||
filter.UserId = !UserConstant.AdminRoles.Contains(user?.Role) ? user.Id : filter.UserId;
|
||||
filter.UserId = !isAdmin ? user.Id : filter.UserId;
|
||||
var conversations = await convService.GetConversations(filter);
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var list = conversations.Items.Select(x => ConversationViewModel.FromSession(x)).ToList();
|
||||
|
||||
var agentIds = list.Select(x => x.AgentId).ToList();
|
||||
var agents = await agentService.GetAgentOptions(agentIds);
|
||||
|
||||
var userIds = list.Select(x => x.User.Id).ToList();
|
||||
var users = await userService.GetUsers(new UserFilter { UserIds = userIds, Size = filter.Pager.Size });
|
||||
|
||||
foreach (var item in list)
|
||||
{
|
||||
user = await userService.GetUser(item.User.Id);
|
||||
user = users.Items.FirstOrDefault(x => x.Id == item.User.Id);
|
||||
item.User = UserViewModel.FromUser(user);
|
||||
var agent = await agentService.GetAgent(item.AgentId);
|
||||
var agent = agents.FirstOrDefault(x => x.Id == item.AgentId);
|
||||
item.AgentName = agent?.Name ?? "Unkown";
|
||||
}
|
||||
|
||||
|
|
@ -138,7 +142,7 @@ public class ConversationController : ControllerBase
|
|||
{
|
||||
var service = _services.GetRequiredService<IConversationService>();
|
||||
var userService = _services.GetRequiredService<IUserService>();
|
||||
var user = await userService.GetUser(_user.Id);
|
||||
var (isAdmin, user) = await userService.IsAdminUser(_user.Id);
|
||||
if (user == null)
|
||||
{
|
||||
return null;
|
||||
|
|
@ -147,7 +151,7 @@ public class ConversationController : ControllerBase
|
|||
var filter = new ConversationFilter
|
||||
{
|
||||
Id = conversationId,
|
||||
UserId = !UserConstant.AdminRoles.Contains(user?.Role) ? user.Id : null
|
||||
UserId = !isAdmin ? user.Id : null
|
||||
};
|
||||
var conversations = await service.GetConversations(filter);
|
||||
if (conversations.Items.IsNullOrEmpty())
|
||||
|
|
@ -206,11 +210,11 @@ public class ConversationController : ControllerBase
|
|||
var userService = _services.GetRequiredService<IUserService>();
|
||||
var conv = _services.GetRequiredService<IConversationService>();
|
||||
|
||||
var user = await userService.GetUser(_user.Id);
|
||||
var (isAdmin, user) = await userService.IsAdminUser(_user.Id);
|
||||
var filter = new ConversationFilter
|
||||
{
|
||||
Id = conversationId,
|
||||
UserId = !UserConstant.AdminRoles.Contains(user?.Role) ? user.Id : null
|
||||
UserId = !isAdmin ? user?.Id : null
|
||||
};
|
||||
var conversations = await conv.GetConversations(filter);
|
||||
|
||||
|
|
@ -229,11 +233,11 @@ public class ConversationController : ControllerBase
|
|||
var userService = _services.GetRequiredService<IUserService>();
|
||||
var conversationService = _services.GetRequiredService<IConversationService>();
|
||||
|
||||
var user = await userService.GetUser(_user.Id);
|
||||
var (isAdmin, user) = await userService.IsAdminUser(_user.Id);
|
||||
var filter = new ConversationFilter
|
||||
{
|
||||
Id = conversationId,
|
||||
UserId = user.Role != UserRole.Admin ? user.Id : null
|
||||
UserId = !isAdmin ? user?.Id : null
|
||||
};
|
||||
var conversations = await conversationService.GetConversations(filter);
|
||||
|
||||
|
|
@ -283,11 +287,11 @@ public class ConversationController : ControllerBase
|
|||
var userService = _services.GetRequiredService<IUserService>();
|
||||
var conversationService = _services.GetRequiredService<IConversationService>();
|
||||
|
||||
var user = await userService.GetUser(_user.Id);
|
||||
var (isAdmin, user) = await userService.IsAdminUser(_user.Id);
|
||||
var filter = new ConversationFilter
|
||||
{
|
||||
Id = conversationId,
|
||||
UserId = !UserConstant.AdminRoles.Contains(user?.Role) ? user.Id : null
|
||||
UserId = !isAdmin ? user?.Id : null
|
||||
};
|
||||
var conversations = await conversationService.GetConversations(filter);
|
||||
|
||||
|
|
@ -555,10 +559,10 @@ public class ConversationController : ControllerBase
|
|||
|
||||
#region Search state keys
|
||||
[HttpGet("/conversation/state/keys")]
|
||||
public async Task<List<string>> GetConversationStateKeys([FromQuery] string query, [FromQuery] int keyLimit = 10, [FromQuery] int convLimit = 100, [FromQuery] bool preload = false)
|
||||
public async Task<List<string>> GetConversationStateKeys([FromQuery] ConversationStateKeysFilter request)
|
||||
{
|
||||
var convService = _services.GetRequiredService<IConversationService>();
|
||||
var keys = await convService.GetConversationStateSearhKeys(query, keyLimit: keyLimit, convLimit: convLimit, preload: preload);
|
||||
var keys = await convService.GetConversationStateSearhKeys(request);
|
||||
return keys;
|
||||
}
|
||||
#endregion
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
using BotSharp.Abstraction.Instructs.Models;
|
||||
using BotSharp.Abstraction.Loggers.Models;
|
||||
using BotSharp.Abstraction.Loggers.Services;
|
||||
using BotSharp.OpenAPI.ViewModels.Instructs;
|
||||
|
|
@ -39,6 +38,7 @@ public class LoggerController : ControllerBase
|
|||
}
|
||||
}
|
||||
|
||||
#region Conversation log
|
||||
[HttpGet("/logger/conversation/{conversationId}/content-log")]
|
||||
public async Task<List<ContentLogOutputModel>> GetConversationContentLogs([FromRoute] string conversationId)
|
||||
{
|
||||
|
|
@ -52,7 +52,9 @@ public class LoggerController : ControllerBase
|
|||
var logging = _services.GetRequiredService<ILoggerService>();
|
||||
return await logging.GetConversationStateLogs(conversationId);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Instruction log
|
||||
[HttpGet("/logger/instruction/log")]
|
||||
public async Task<PagedItems<InstructionLogViewModel>> GetInstructionLogs([FromQuery] InstructLogFilter request)
|
||||
{
|
||||
|
|
@ -65,4 +67,13 @@ public class LoggerController : ControllerBase
|
|||
Count = logs.Count
|
||||
};
|
||||
}
|
||||
|
||||
[HttpGet("/logger/instruction/log/keys")]
|
||||
public async Task<List<string>> GetInstructionLogKeys([FromQuery] InstructLogKeysFilter request)
|
||||
{
|
||||
var logging = _services.GetRequiredService<ILoggerService>();
|
||||
var keys = await logging.GetInstructionLogSearchKeys(request);
|
||||
return keys;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ public class PluginController(IServiceProvider services, IUserIdentity user, Plu
|
|||
private async Task<bool> IsValidUser()
|
||||
{
|
||||
var userService = services.GetRequiredService<IUserService>();
|
||||
return await userService.IsAdminUser(_user.Id);
|
||||
var (isAdmin, _) = await userService.IsAdminUser(_user.Id);
|
||||
return isAdmin;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using BotSharp.Abstraction.Roles;
|
||||
using BotSharp.Abstraction.Users.Enums;
|
||||
|
||||
namespace BotSharp.OpenAPI.Controllers;
|
||||
|
||||
|
|
@ -83,6 +82,7 @@ public class RoleController : ControllerBase
|
|||
private async Task<bool> IsValidUser()
|
||||
{
|
||||
var userService = _services.GetRequiredService<IUserService>();
|
||||
return await userService.IsAdminUser(_user.Id);
|
||||
var (isAdmin, _) = await userService.IsAdminUser(_user.Id);
|
||||
return isAdmin;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -254,7 +254,8 @@ public class UserController : ControllerBase
|
|||
private async Task<bool> IsValidUser()
|
||||
{
|
||||
var userService = _services.GetRequiredService<IUserService>();
|
||||
return await userService.IsAdminUser(_user.Id);
|
||||
var (isAdmin, _) = await userService.IsAdminUser(_user.Id);
|
||||
return isAdmin;
|
||||
}
|
||||
|
||||
private FileContentResult BuildFileResult(string file)
|
||||
|
|
|
|||
|
|
@ -644,21 +644,31 @@ public partial class MongoRepository
|
|||
#if !DEBUG
|
||||
[SharpCache(10)]
|
||||
#endif
|
||||
public List<string> GetConversationStateSearchKeys(int messageLowerLimit = 2, int convUpperLimit = 100)
|
||||
public List<string> GetConversationStateSearchKeys(ConversationStateKeysFilter filter)
|
||||
{
|
||||
var stateBuilder = Builders<ConversationStateDocument>.Filter;
|
||||
var sortDef = Builders<ConversationStateDocument>.Sort.Descending(x => x.UpdatedTime);
|
||||
var stateFilters = new List<FilterDefinition<ConversationStateDocument>>()
|
||||
var builder = Builders<ConversationDocument>.Filter;
|
||||
var sortDef = Builders<ConversationDocument>.Sort.Descending(x => x.UpdatedTime);
|
||||
var filters = new List<FilterDefinition<ConversationDocument>>()
|
||||
{
|
||||
stateBuilder.Exists(x => x.States),
|
||||
stateBuilder.Ne(x => x.States, [])
|
||||
builder.Exists(x => x.LatestStates),
|
||||
builder.Ne(x => x.LatestStates, [])
|
||||
};
|
||||
|
||||
var states = _dc.ConversationStates.Find(stateBuilder.And(stateFilters))
|
||||
.Sort(sortDef)
|
||||
.Limit(convUpperLimit)
|
||||
.ToList();
|
||||
var keys = states.SelectMany(x => x.States.Select(x => x.Key)).Distinct().ToList();
|
||||
if (!filter.AgentIds.IsNullOrEmpty())
|
||||
{
|
||||
filters.Add(builder.In(x => x.AgentId, filter.AgentIds));
|
||||
}
|
||||
|
||||
if (!filter.UserIds.IsNullOrEmpty())
|
||||
{
|
||||
filters.Add(builder.In(x => x.UserId, filter.UserIds));
|
||||
}
|
||||
|
||||
var convDocs = _dc.Conversations.Find(builder.And(filters))
|
||||
.Sort(sortDef)
|
||||
.Limit(filter.ConvLimit)
|
||||
.ToList();
|
||||
var keys = convDocs.SelectMany(x => x.LatestStates.Select(x => x.Key)).Distinct().ToList();
|
||||
return keys;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
using BotSharp.Abstraction.Instructs.Models;
|
||||
using BotSharp.Abstraction.Loggers.Models;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
using System.Text.Json;
|
||||
|
|
@ -241,5 +240,33 @@ public partial class MongoRepository
|
|||
Count = (int)count
|
||||
};
|
||||
}
|
||||
|
||||
public List<string> GetInstructionLogSearchKeys(InstructLogKeysFilter filter)
|
||||
{
|
||||
var builder = Builders<InstructionLogDocument>.Filter;
|
||||
var sortDef = Builders<InstructionLogDocument>.Sort.Descending(x => x.CreatedTime);
|
||||
var filters = new List<FilterDefinition<InstructionLogDocument>>()
|
||||
{
|
||||
builder.Exists(x => x.States),
|
||||
builder.Ne(x => x.States, [])
|
||||
};
|
||||
|
||||
if (!filter.AgentIds.IsNullOrEmpty())
|
||||
{
|
||||
filters.Add(builder.In(x => x.AgentId, filter.AgentIds));
|
||||
}
|
||||
|
||||
if (!filter.UserIds.IsNullOrEmpty())
|
||||
{
|
||||
filters.Add(builder.In(x => x.UserId, filter.UserIds));
|
||||
}
|
||||
|
||||
var convDocs = _dc.InstructionLogs.Find(builder.And(filters))
|
||||
.Sort(sortDef)
|
||||
.Limit(filter.LogLimit)
|
||||
.ToList();
|
||||
var keys = convDocs.SelectMany(x => x.States.Select(x => x.Key)).Distinct().ToList();
|
||||
return keys;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue