commit
4d5ebd8bb0
|
|
@ -18,6 +18,7 @@ public interface IBotSharpRepository
|
|||
#region User
|
||||
User? GetUserByEmail(string email);
|
||||
User? GetUserById(string id);
|
||||
User? GetUserByUserName(string userName);
|
||||
void CreateUser(User user);
|
||||
#endregion
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
using BotSharp.Abstraction.Users.Models;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace BotSharp.Abstraction.Users;
|
||||
|
||||
public interface IAuthenticationHook
|
||||
{
|
||||
Task<User> Authenticate(string id, string password);
|
||||
void AddClaims(List<Claim> claims);
|
||||
}
|
||||
|
|
@ -7,4 +7,5 @@ public interface IUserIdentity
|
|||
string UserName { get; }
|
||||
string FirstName { get; }
|
||||
string LastName { get; }
|
||||
string FullName { get; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ public class User
|
|||
public string Email { get; set; } = string.Empty;
|
||||
public string Salt { get; set; } = string.Empty;
|
||||
public string Password { get; set; } = string.Empty;
|
||||
public string Source { get; set; } = "internal";
|
||||
public string? ExternalId { get; set; }
|
||||
public string Role { get; set; } = UserRole.Client;
|
||||
public DateTime UpdatedTime { get; set; } = DateTime.UtcNow;
|
||||
|
|
|
|||
|
|
@ -36,9 +36,9 @@ public class AgentPlugin : IBotSharpPlugin
|
|||
{
|
||||
SubMenu = new List<PluginMenuDef>
|
||||
{
|
||||
new PluginMenuDef("Router", link: "/page/agent/router"), // icon: "bx bx-map-pin"
|
||||
new PluginMenuDef("Evaluator", link: "/page/agent/evaluator"), // icon: "bx bx-task"
|
||||
new PluginMenuDef("Agents", link: "/page/agent"), // icon: "bx bx-bot"
|
||||
new PluginMenuDef("Router", link: "page/agent/router"), // icon: "bx bx-map-pin"
|
||||
new PluginMenuDef("Evaluator", link: "page/agent/evaluator"), // icon: "bx bx-task"
|
||||
new PluginMenuDef("Agents", link: "page/agent"), // icon: "bx bx-bot"
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@
|
|||
<PackageReference Include="Colorful.Console" Version="1.2.15" />
|
||||
<PackageReference Include="EntityFrameworkCore.BootKit" Version="6.2.1" />
|
||||
<PackageReference Include="Fluid.Core" Version="2.5.0" />
|
||||
<PackageReference Include="Nanoid" Version="3.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ public class ConversationPlugin : IBotSharpPlugin
|
|||
public bool AttachMenu(List<PluginMenuDef> menu)
|
||||
{
|
||||
var section = menu.First(x => x.Label == "Apps");
|
||||
menu.Add(new PluginMenuDef("Conversation", link: "/page/conversation", icon: "bx bx-conversation", weight: section.Weight + 5));
|
||||
menu.Add(new PluginMenuDef("Conversation", link: "page/conversation", icon: "bx bx-conversation", weight: section.Weight + 5));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -192,20 +192,17 @@ public class BotSharpDbContext : Database, IBotSharpRepository
|
|||
#endregion
|
||||
|
||||
#region User
|
||||
public User? GetUserByEmail(string email)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public User? GetUserByEmail(string email)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public User? GetUserById(string id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public User? GetUserById(string id)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public void CreateUser(User user)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public User? GetUserByUserName(string userName)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public void CreateUser(User user)
|
||||
=> throw new NotImplementedException();
|
||||
#endregion
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,31 +1,35 @@
|
|||
using BotSharp.Abstraction.Users.Models;
|
||||
using System.IO;
|
||||
|
||||
namespace BotSharp.Core.Repository
|
||||
namespace BotSharp.Core.Repository;
|
||||
|
||||
public partial class FileRepository
|
||||
{
|
||||
public partial class FileRepository
|
||||
public User? GetUserByEmail(string email)
|
||||
{
|
||||
public User? GetUserByEmail(string email)
|
||||
{
|
||||
return Users.FirstOrDefault(x => x.Email == email);
|
||||
}
|
||||
return Users.FirstOrDefault(x => x.Email == email.ToLower());
|
||||
}
|
||||
|
||||
public User? GetUserById(string id = null)
|
||||
{
|
||||
return Users.FirstOrDefault(x => x.ExternalId == id || x.Id == id);
|
||||
}
|
||||
public User? GetUserById(string id = null)
|
||||
{
|
||||
return Users.FirstOrDefault(x => x.Id == id || (x.ExternalId != null && x.ExternalId == id));
|
||||
}
|
||||
|
||||
public void CreateUser(User user)
|
||||
public User? GetUserByUserName(string userName = null)
|
||||
{
|
||||
return Users.FirstOrDefault(x => x.UserName == userName.ToLower());
|
||||
}
|
||||
|
||||
public void CreateUser(User user)
|
||||
{
|
||||
var userId = Guid.NewGuid().ToString();
|
||||
user.Id = userId;
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, "users", userId);
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
var userId = Guid.NewGuid().ToString();
|
||||
user.Id = userId;
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, "users", userId);
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
}
|
||||
var path = Path.Combine(dir, "user.json");
|
||||
File.WriteAllText(path, JsonSerializer.Serialize(user, _options));
|
||||
Directory.CreateDirectory(dir);
|
||||
}
|
||||
var path = Path.Combine(dir, "user.json");
|
||||
File.WriteAllText(path, JsonSerializer.Serialize(user, _options));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,6 @@ using FunctionDef = BotSharp.Abstraction.Functions.Models.FunctionDef;
|
|||
using BotSharp.Abstraction.Users.Models;
|
||||
using BotSharp.Abstraction.Agents.Models;
|
||||
using MongoDB.Driver;
|
||||
using BotSharp.Abstraction.Routing.Models;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
using BotSharp.Abstraction.Repositories.Models;
|
||||
using BotSharp.Abstraction.Routing.Settings;
|
||||
using BotSharp.Abstraction.Evaluations.Settings;
|
||||
using System.Text.Encodings.Web;
|
||||
using BotSharp.Abstraction.Plugins.Models;
|
||||
using BotSharp.Abstraction.Statistics.Settings;
|
||||
|
|
|
|||
|
|
@ -28,4 +28,7 @@ public class UserIdentity : IUserIdentity
|
|||
|
||||
public string LastName
|
||||
=> _claims?.FirstOrDefault(x => x.Type == ClaimTypes.Surname)?.Value!;
|
||||
|
||||
public string FullName
|
||||
=> $"{FirstName} {LastName}".Trim();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ using BotSharp.Abstraction.Repositories;
|
|||
using BotSharp.Abstraction.Users.Models;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using NanoidDotNet;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
|
||||
|
|
@ -11,24 +12,42 @@ public class UserService : IUserService
|
|||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly IUserIdentity _user;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public UserService(IServiceProvider services, IUserIdentity user)
|
||||
public UserService(IServiceProvider services, IUserIdentity user, ILogger<UserService> logger)
|
||||
{
|
||||
_services = services;
|
||||
_user = user;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<User> CreateUser(User user)
|
||||
{
|
||||
if (string.IsNullOrEmpty(user.UserName))
|
||||
{
|
||||
// generate unique name
|
||||
var name = user.Email.Split("@").First() + "-" + Nanoid.Generate("0123456789botsharp", 6);
|
||||
user.UserName = name;
|
||||
}
|
||||
else
|
||||
{
|
||||
user.UserName = user.UserName.ToLower();
|
||||
}
|
||||
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var record = db.GetUserByEmail(user.Email);
|
||||
var record = db.GetUserByUserName(user.UserName);
|
||||
|
||||
if (record != null)
|
||||
{
|
||||
return record;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(user.Id))
|
||||
{
|
||||
user.Id = Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
record = user;
|
||||
record.UserName = user.UserName.ToLower();
|
||||
record.Email = user.Email.ToLower();
|
||||
record.Salt = Guid.NewGuid().ToString("N");
|
||||
record.Password = Utilities.HashText(user.Password, record.Salt);
|
||||
|
|
@ -43,10 +62,52 @@ public class UserService : IUserService
|
|||
public async Task<Token> GetToken(string authorization)
|
||||
{
|
||||
var base64 = Encoding.UTF8.GetString(Convert.FromBase64String(authorization));
|
||||
var (userEmail, password) = base64.SplitAsTuple(":");
|
||||
var (id, password) = base64.SplitAsTuple(":");
|
||||
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var record = db.GetUserByEmail(userEmail);
|
||||
var record = id.Contains("@") ? db.GetUserByEmail(id) : db.GetUserByUserName(id);
|
||||
if (record == null)
|
||||
{
|
||||
record = db.GetUserByUserName(id);
|
||||
}
|
||||
|
||||
if (record == null || record.Source != "internal")
|
||||
{
|
||||
// check 3rd party user
|
||||
var validators = _services.GetServices<IAuthenticationHook>();
|
||||
foreach (var validator in validators)
|
||||
{
|
||||
var user = await validator.Authenticate(id, password);
|
||||
if (user == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(user.Source) || user.Source == "internal")
|
||||
{
|
||||
_logger.LogError($"Please set source name in the Authenticate hook.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (record == null)
|
||||
{
|
||||
// create a local user record
|
||||
record = new User
|
||||
{
|
||||
UserName = user.UserName,
|
||||
Email = user.Email,
|
||||
FirstName = user.FirstName,
|
||||
LastName = user.LastName,
|
||||
Source = user.Source,
|
||||
ExternalId = user.ExternalId,
|
||||
Password = user.Password,
|
||||
};
|
||||
await CreateUser(record);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (record == null)
|
||||
{
|
||||
return default;
|
||||
|
|
@ -70,33 +131,43 @@ public class UserService : IUserService
|
|||
|
||||
private string GenerateJwtToken(User user)
|
||||
{
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new Claim(JwtRegisteredClaimNames.NameId, user.Id),
|
||||
new Claim(JwtRegisteredClaimNames.UniqueName, user.UserName),
|
||||
new Claim(JwtRegisteredClaimNames.Email, user.Email),
|
||||
new Claim(JwtRegisteredClaimNames.GivenName, user.FirstName),
|
||||
new Claim(JwtRegisteredClaimNames.FamilyName, user.LastName),
|
||||
new Claim("source", user.Source),
|
||||
new Claim("external_id", user.ExternalId),
|
||||
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
|
||||
};
|
||||
|
||||
var validators = _services.GetServices<IAuthenticationHook>();
|
||||
foreach (var validator in validators)
|
||||
{
|
||||
validator.AddClaims(claims);
|
||||
}
|
||||
|
||||
var config = _services.GetRequiredService<IConfiguration>();
|
||||
var issuer = config["Jwt:Issuer"];
|
||||
var audience = config["Jwt:Audience"];
|
||||
var key = Encoding.ASCII.GetBytes(config["Jwt:Key"]);
|
||||
var tokenDescriptor = new SecurityTokenDescriptor
|
||||
{
|
||||
Subject = new ClaimsIdentity(new[]
|
||||
{
|
||||
new Claim(JwtRegisteredClaimNames.NameId, user.Id),
|
||||
new Claim(JwtRegisteredClaimNames.Email, user.Email),
|
||||
new Claim(JwtRegisteredClaimNames.GivenName, user.FirstName),
|
||||
new Claim(JwtRegisteredClaimNames.FamilyName, user.LastName),
|
||||
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
|
||||
}),
|
||||
Expires = DateTime.UtcNow.AddMinutes(5),
|
||||
Subject = new ClaimsIdentity(claims),
|
||||
Expires = DateTime.UtcNow.AddHours(2),
|
||||
Issuer = issuer,
|
||||
Audience = audience,
|
||||
SigningCredentials = new SigningCredentials
|
||||
(new SymmetricSecurityKey(key),
|
||||
SecurityAlgorithms.HmacSha512Signature)
|
||||
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key),
|
||||
SecurityAlgorithms.HmacSha512Signature)
|
||||
};
|
||||
var tokenHandler = new JwtSecurityTokenHandler();
|
||||
var token = tokenHandler.CreateToken(tokenDescriptor);
|
||||
return tokenHandler.WriteToken(token);
|
||||
}
|
||||
|
||||
[MemoryCache(10 * 60)]
|
||||
[MemoryCache(10 * 60, perInstanceCache: true)]
|
||||
public async Task<User> GetMyProfile()
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
|
|
@ -109,6 +180,16 @@ public class UserService : IUserService
|
|||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var user = db.GetUserById(id);
|
||||
if (user == null)
|
||||
{
|
||||
user = new User
|
||||
{
|
||||
Id = id,
|
||||
FirstName = "Unknown",
|
||||
LastName = "Anonymous",
|
||||
Role = AgentRole.User
|
||||
};
|
||||
}
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
In order to execute the listed instructions in the order specified by the user.
|
||||
In order to sequentially execute user needs,
|
||||
What is the next step based on the CONVERSATION?
|
||||
|
|
@ -29,7 +29,7 @@ public class AgentController : ControllerBase
|
|||
{
|
||||
AgentIds = new List<string> { id }
|
||||
});
|
||||
return agents.Items.First();
|
||||
return agents.Items.FirstOrDefault();
|
||||
}
|
||||
|
||||
[HttpGet("/agents")]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
using BotSharp.Abstraction.Users.Models;
|
||||
|
||||
namespace BotSharp.OpenAPI.Controllers;
|
||||
|
||||
[Authorize]
|
||||
|
|
@ -66,20 +68,40 @@ public class ConversationController : ControllerBase
|
|||
var history = conv.GetDialogHistory();
|
||||
|
||||
var userService = _services.GetRequiredService<IUserService>();
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
|
||||
var dialogs = new List<ChatResponseModel>();
|
||||
foreach (var message in history)
|
||||
{
|
||||
var user = await userService.GetUser(message.SenderId);
|
||||
|
||||
dialogs.Add(new ChatResponseModel
|
||||
if (message.Role == AgentRole.User)
|
||||
{
|
||||
ConversationId = conversationId,
|
||||
MessageId = message.MessageId,
|
||||
CreatedAt = message.CreatedAt,
|
||||
Text = message.Content,
|
||||
Sender = UserViewModel.FromUser(user)
|
||||
});
|
||||
var user = await userService.GetUser(message.SenderId);
|
||||
|
||||
dialogs.Add(new ChatResponseModel
|
||||
{
|
||||
ConversationId = conversationId,
|
||||
MessageId = message.MessageId,
|
||||
CreatedAt = message.CreatedAt,
|
||||
Text = message.Content,
|
||||
Sender = UserViewModel.FromUser(user)
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
var agent = await agentService.GetAgent(message.CurrentAgentId);
|
||||
dialogs.Add(new ChatResponseModel
|
||||
{
|
||||
ConversationId = conversationId,
|
||||
MessageId = message.MessageId,
|
||||
CreatedAt = message.CreatedAt,
|
||||
Text = message.Content,
|
||||
Sender = new UserViewModel
|
||||
{
|
||||
FirstName = agent.Name,
|
||||
Role = message.Role,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return dialogs;
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ public class PluginController : ControllerBase
|
|||
{
|
||||
IsHeader = true
|
||||
},
|
||||
new PluginMenuDef("Plugins", link: "/page/plugin", icon: "bx bx-plug", weight: 31),
|
||||
new PluginMenuDef("Settings", link: "/page/setting", icon: "bx bx-cog", weight: 32),
|
||||
new PluginMenuDef("Plugins", link: "page/plugin", icon: "bx bx-plug", weight: 31),
|
||||
new PluginMenuDef("Settings", link: "page/setting", icon: "bx bx-cog", weight: 32),
|
||||
};
|
||||
|
||||
var loader = _services.GetRequiredService<PluginLoader>();
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@ public class UserViewModel
|
|||
{
|
||||
return new UserViewModel
|
||||
{
|
||||
FirstName = "AI",
|
||||
LastName = "Assistant",
|
||||
Role = AgentRole.Assistant
|
||||
FirstName = "Unknown",
|
||||
LastName = "Anonymous",
|
||||
Role = AgentRole.User
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ public class DashboardPlugin : IBotSharpPlugin
|
|||
public string Id => "d42a0c21-b461-44f6-ada2-499510d260af";
|
||||
public string Name => "Dashboard";
|
||||
public string Description => "Dashboard that offers real-time statistics on model performance, usage trends, and user feedback";
|
||||
|
||||
public string IconUrl => "https://cdn0.iconfinder.com/data/icons/octicons/1024/dashboard-512.png";
|
||||
public void RegisterDI(IServiceCollection services, IConfiguration config)
|
||||
{
|
||||
services.AddScoped<IConversationHook, StatsConversationHook>();
|
||||
|
|
@ -26,7 +26,7 @@ public class DashboardPlugin : IBotSharpPlugin
|
|||
public bool AttachMenu(List<PluginMenuDef> menu)
|
||||
{
|
||||
var section = menu.First(x => x.Label == "Apps");
|
||||
menu.Add(new PluginMenuDef("Dashboard", link: "/page/dashboard", icon: "bx bx-home-circle", weight: section.Weight - 1));
|
||||
menu.Add(new PluginMenuDef("Dashboard", link: "page/dashboard", icon: "bx bx-home-circle", weight: section.Weight - 1));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
using BotSharp.Abstraction.Agents;
|
||||
using BotSharp.Abstraction.Agents.Enums;
|
||||
using BotSharp.Abstraction.Conversations.Settings;
|
||||
using BotSharp.Abstraction.Loggers;
|
||||
using BotSharp.Plugin.HuggingFace.Services;
|
||||
using BotSharp.Plugin.HuggingFace.Settings;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
using BotSharp.Abstraction.Users.Models;
|
||||
|
||||
namespace BotSharp.Plugin.MongoStorage.Collections;
|
||||
|
||||
public class UserDocument : MongoBase
|
||||
|
|
@ -8,9 +10,27 @@ public class UserDocument : MongoBase
|
|||
public string Email { get; set; }
|
||||
public string Salt { get; set; }
|
||||
public string Password { get; set; }
|
||||
public string Source { get; set; } = "internal";
|
||||
public string? ExternalId { get; set; }
|
||||
public string Role { get; set; }
|
||||
|
||||
public DateTime CreatedTime { get; set; }
|
||||
public DateTime UpdatedTime { get; set; }
|
||||
|
||||
public User ToUser()
|
||||
{
|
||||
return new User
|
||||
{
|
||||
Id = Id,
|
||||
UserName = UserName,
|
||||
FirstName = FirstName,
|
||||
LastName = LastName,
|
||||
Email = Email,
|
||||
Password = Password,
|
||||
Salt = Salt,
|
||||
Source = Source,
|
||||
ExternalId = ExternalId,
|
||||
Role = Role
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ public class MongoStoragePlugin : IBotSharpPlugin
|
|||
public bool AttachMenu(List<PluginMenuDef> menu)
|
||||
{
|
||||
var section = menu.First(x => x.Label == "Apps");
|
||||
menu.Add(new PluginMenuDef("MongoDB", icon: "bx bx-data", link: "/page/mongodb", weight: section.Weight + 10));
|
||||
menu.Add(new PluginMenuDef("MongoDB", icon: "bx bx-data", link: "page/mongodb", weight: section.Weight + 10));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,36 +7,21 @@ public partial class MongoRepository
|
|||
{
|
||||
public User? GetUserByEmail(string email)
|
||||
{
|
||||
var user = _dc.Users.AsQueryable().FirstOrDefault(x => x.Email == email);
|
||||
return user != null ? new User
|
||||
{
|
||||
Id = user.Id,
|
||||
UserName = user.UserName,
|
||||
FirstName = user.FirstName,
|
||||
LastName = user.LastName,
|
||||
Email = user.Email,
|
||||
Password = user.Password,
|
||||
Salt = user.Salt,
|
||||
ExternalId = user.ExternalId,
|
||||
Role = user.Role
|
||||
} : null;
|
||||
var user = _dc.Users.AsQueryable().FirstOrDefault(x => x.Email == email.ToLower());
|
||||
return user != null ? user.ToUser() : null;
|
||||
}
|
||||
|
||||
public User? GetUserById(string id)
|
||||
{
|
||||
var user = _dc.Users.AsQueryable().FirstOrDefault(x => x.Id == id || x.ExternalId == id);
|
||||
return user != null ? new User
|
||||
{
|
||||
Id = user.Id,
|
||||
UserName = user.UserName,
|
||||
FirstName = user.FirstName,
|
||||
LastName = user.LastName,
|
||||
Email = user.Email,
|
||||
Password = user.Password,
|
||||
Salt = user.Salt,
|
||||
ExternalId = user.ExternalId,
|
||||
Role = user.Role
|
||||
} : null;
|
||||
var user = _dc.Users.AsQueryable()
|
||||
.FirstOrDefault(x => x.Id == id || (x.ExternalId != null && x.ExternalId == id));
|
||||
return user != null ? user.ToUser() : null;
|
||||
}
|
||||
|
||||
public User? GetUserByUserName(string userName)
|
||||
{
|
||||
var user = _dc.Users.AsQueryable().FirstOrDefault(x => x.UserName == userName.ToLower());
|
||||
return user != null ? user.ToUser() : null;
|
||||
}
|
||||
|
||||
public void CreateUser(User user)
|
||||
|
|
@ -45,13 +30,14 @@ public partial class MongoRepository
|
|||
|
||||
var userCollection = new UserDocument
|
||||
{
|
||||
Id = Guid.NewGuid().ToString(),
|
||||
Id = user.Id ?? Guid.NewGuid().ToString(),
|
||||
UserName = user.UserName,
|
||||
FirstName = user.FirstName,
|
||||
LastName = user.LastName,
|
||||
Salt = user.Salt,
|
||||
Password = user.Password,
|
||||
Email = user.Email,
|
||||
Source = user.Source,
|
||||
ExternalId = user.ExternalId,
|
||||
Role = user.Role,
|
||||
CreatedTime = DateTime.UtcNow,
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
using BotSharp.Plugin.WebDriver.Services;
|
||||
using System.Threading;
|
||||
|
||||
namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
|
||||
|
||||
public partial class PlaywrightWebDriver
|
||||
{
|
||||
public async Task ChangeListValue(Agent agent, BrowsingContextIn context, string messageId)
|
||||
{
|
||||
await _instance.Page.WaitForLoadStateAsync(LoadState.DOMContentLoaded);
|
||||
// Retrieve the page raw html and infer the element path
|
||||
var body = await _instance.Page.QuerySelectorAsync("body");
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ public partial class PlaywrightWebDriver
|
|||
{
|
||||
public async Task ClickElement(Agent agent, BrowsingContextIn context, string messageId)
|
||||
{
|
||||
await _instance.Page.WaitForLoadStateAsync(LoadState.DOMContentLoaded);
|
||||
var driverService = _services.GetRequiredService<WebDriverService>();
|
||||
|
||||
// Retrieve the page raw html and infer the element path
|
||||
|
|
@ -37,5 +38,6 @@ public partial class PlaywrightWebDriver
|
|||
messageId);
|
||||
ILocator element = Locator(htmlElementContextOut);
|
||||
await element.ClickAsync();
|
||||
await _instance.Page.WaitForLoadStateAsync(LoadState.NetworkIdle);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
|
||||
|
||||
public partial class PlaywrightWebDriver
|
||||
{
|
||||
public async Task CloseBrowser(Agent agent, BrowsingContextIn context, string messageId)
|
||||
{
|
||||
// await _instance.Browser.CloseAsync();
|
||||
_logger.LogInformation($"{agent.Name} closed browser with page {_instance.Page.Url}");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
using BotSharp.Plugin.WebDriver.Services;
|
||||
|
||||
namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
|
||||
|
||||
public partial class PlaywrightWebDriver
|
||||
{
|
||||
public async Task<string> ExtractData(Agent agent, BrowsingContextIn context, string messageId)
|
||||
{
|
||||
await _instance.Page.WaitForLoadStateAsync(LoadState.DOMContentLoaded);
|
||||
|
||||
// Retrieve the page raw html and infer the element path
|
||||
var body = await _instance.Page.QuerySelectorAsync("body");
|
||||
var content = await body.InnerTextAsync();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
|
||||
|
||||
public partial class PlaywrightWebDriver
|
||||
{
|
||||
public async Task GoToPage(Agent agent, BrowsingContextIn context, string messageId)
|
||||
{
|
||||
await _instance.Page.GotoAsync(context.Url);
|
||||
await _instance.Page.WaitForLoadStateAsync(LoadState.DOMContentLoaded);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
|
||||
|
||||
public partial class PlaywrightWebDriver
|
||||
{
|
||||
public async Task InputUserPassword(Agent agent, BrowsingContextIn context, string messageId)
|
||||
{
|
||||
await _instance.Page.WaitForLoadStateAsync(LoadState.DOMContentLoaded);
|
||||
|
||||
// Retrieve the page raw html and infer the element path
|
||||
var body = await _instance.Page.QuerySelectorAsync("body");
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ public partial class PlaywrightWebDriver
|
|||
{
|
||||
public async Task InputUserText(Agent agent, BrowsingContextIn context, string messageId)
|
||||
{
|
||||
await _instance.Page.WaitForLoadStateAsync(LoadState.DOMContentLoaded);
|
||||
// await _instance.Page.WaitForLoadStateAsync(LoadState.NetworkIdle);
|
||||
var driverService = _services.GetRequiredService<WebDriverService>();
|
||||
|
||||
// Retrieve the page raw html and infer the element path
|
||||
|
|
@ -17,12 +19,15 @@ public partial class PlaywrightWebDriver
|
|||
var id = await input.GetAttributeAsync("id");
|
||||
var name = await input.GetAttributeAsync("name");
|
||||
var type = await input.GetAttributeAsync("type");
|
||||
var placeholder = await input.GetAttributeAsync("placeholder");
|
||||
|
||||
str.Add(driverService.AssembleMarkup("input", new MarkupProperties
|
||||
{
|
||||
Id = id,
|
||||
Name = name,
|
||||
Type = type,
|
||||
Text = text
|
||||
Text = text,
|
||||
Placeholder = placeholder
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
@ -33,12 +38,14 @@ public partial class PlaywrightWebDriver
|
|||
var id = await input.GetAttributeAsync("id");
|
||||
var name = await input.GetAttributeAsync("name");
|
||||
var type = await input.GetAttributeAsync("type");
|
||||
var placeholder = await input.GetAttributeAsync("placeholder");
|
||||
str.Add(driverService.AssembleMarkup("textarea", new MarkupProperties
|
||||
{
|
||||
Id = id,
|
||||
Name = name,
|
||||
Type = type,
|
||||
Text = text
|
||||
Text = text,
|
||||
Placeholder = placeholder
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ public partial class PlaywrightWebDriver
|
|||
});
|
||||
_instance.SetPage(page);
|
||||
var response = await page.GotoAsync(url);
|
||||
await page.WaitForLoadStateAsync(LoadState.DOMContentLoaded);
|
||||
}
|
||||
|
||||
return _instance.Browser;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,19 @@
|
|||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
|
||||
|
||||
public partial class PlaywrightWebDriver
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly PlaywrightInstance _instance;
|
||||
private readonly ILogger _logger;
|
||||
public PlaywrightInstance Instance => _instance;
|
||||
|
||||
public PlaywrightWebDriver(IServiceProvider services, PlaywrightInstance instance)
|
||||
public PlaywrightWebDriver(IServiceProvider services, PlaywrightInstance instance, ILogger<PlaywrightWebDriver> logger)
|
||||
{
|
||||
_services = services;
|
||||
_instance = instance;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
private ILocator Locator(HtmlElementContextOut context)
|
||||
|
|
@ -20,6 +24,23 @@ public partial class PlaywrightWebDriver
|
|||
// await _instance.Page.WaitForSelectorAsync($"#{htmlElementContextOut.ElementId}", new PageWaitForSelectorOptions { Timeout = 3 });
|
||||
element = _instance.Page.Locator($"#{context.ElementId}");
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(context.ElementName))
|
||||
{
|
||||
var role = context.TagName switch
|
||||
{
|
||||
"input" => AriaRole.Textbox,
|
||||
"textarea" => AriaRole.Textbox,
|
||||
"button" => AriaRole.Button,
|
||||
_ => AriaRole.Generic
|
||||
};
|
||||
// await _instance.Page.WaitForSelectorAsync($"#{htmlElementContextOut.ElementId}", new PageWaitForSelectorOptions { Timeout = 3 });
|
||||
element = _instance.Page.Locator($"[name='{context.ElementName}']");
|
||||
|
||||
if (element.CountAsync().Result == 0)
|
||||
{
|
||||
_logger.LogError($"Can't locate element {role} {context.ElementName}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (context.Index < 0)
|
||||
|
|
|
|||
|
|
@ -23,10 +23,9 @@ public class ChangeListValueFn : IFunctionCallback
|
|||
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var agent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
await _driver.Instance.Page.WaitForLoadStateAsync(LoadState.Load);
|
||||
await _driver.ChangeListValue(agent, args, message.MessageId);
|
||||
|
||||
message.Content = $"Updat the value of \"${args.ElementName}\" to \"{args.UpdateValue}\" successfully.";
|
||||
message.Content = $"Updat the value of \"{args.ElementName}\" to \"{args.UpdateValue}\" successfully.";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ public class ClickButtonFn : IFunctionCallback
|
|||
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var agent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
await _driver.Instance.Page.WaitForLoadStateAsync(LoadState.Load);
|
||||
await _driver.ClickElement(agent, args, message.MessageId);
|
||||
|
||||
message.Content = $"Click button {args.ElementName} successfully.";
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
using BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
|
||||
|
||||
namespace BotSharp.Plugin.WebDriver.Functions;
|
||||
|
||||
public class CloseBrowserFn : IFunctionCallback
|
||||
{
|
||||
public string Name => "close_browser";
|
||||
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly PlaywrightWebDriver _driver;
|
||||
|
||||
public CloseBrowserFn(IServiceProvider services,
|
||||
PlaywrightWebDriver driver)
|
||||
{
|
||||
_services = services;
|
||||
_driver = driver;
|
||||
}
|
||||
|
||||
public async Task<bool> Execute(RoleDialogModel message)
|
||||
{
|
||||
var args = JsonSerializer.Deserialize<BrowsingContextIn>(message.FunctionArgs);
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var agent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
await _driver.CloseBrowser(agent, args, message.MessageId);
|
||||
message.Content = $"Browser is closed";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
|
||||
using BotSharp.Abstraction.Agents;
|
||||
using BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
|
||||
|
||||
namespace BotSharp.Plugin.WebDriver.Functions;
|
||||
|
|
@ -23,7 +21,6 @@ public class ExtractDataFn : IFunctionCallback
|
|||
var args = JsonSerializer.Deserialize<BrowsingContextIn>(message.FunctionArgs);
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var agent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
await _driver.Instance.Page.WaitForLoadStateAsync(LoadState.Load);
|
||||
message.Content = await _driver.ExtractData(agent, args, message.MessageId);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
using BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
|
||||
|
||||
namespace BotSharp.Plugin.WebDriver.Functions;
|
||||
|
||||
public class GoToPageFn : IFunctionCallback
|
||||
{
|
||||
public string Name => "go_to_page";
|
||||
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly PlaywrightWebDriver _driver;
|
||||
|
||||
public GoToPageFn(IServiceProvider services,
|
||||
PlaywrightWebDriver driver)
|
||||
{
|
||||
_services = services;
|
||||
_driver = driver;
|
||||
}
|
||||
|
||||
public async Task<bool> Execute(RoleDialogModel message)
|
||||
{
|
||||
var args = JsonSerializer.Deserialize<BrowsingContextIn>(message.FunctionArgs);
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var agent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
await _driver.GoToPage(agent, args, message.MessageId);
|
||||
message.Content = $"Page {args.Url} is open.";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -23,7 +23,6 @@ public class InputUserPasswordFn : IFunctionCallback
|
|||
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var agent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
await _driver.Instance.Page.WaitForLoadStateAsync(LoadState.Load);
|
||||
await _driver.InputUserPassword(agent, args, message.MessageId);
|
||||
|
||||
message.Content = "Input password successfully";
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ public class InputUserTextFn : IFunctionCallback
|
|||
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var agent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
await _driver.Instance.Page.WaitForLoadStateAsync(LoadState.Load);
|
||||
await _driver.InputUserText(agent, args, message.MessageId);
|
||||
|
||||
message.Content = $"Input text \"{args.InputText}\" successfully.";
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@ public class HtmlElementContextOut
|
|||
[JsonPropertyName("element_id")]
|
||||
public string ElementId { get; set; }
|
||||
|
||||
[JsonPropertyName("element_name")]
|
||||
public string ElementName { get; set; }
|
||||
|
||||
[JsonPropertyName("tag_name")]
|
||||
public string TagName { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -6,4 +6,5 @@ internal class MarkupProperties
|
|||
public string? Name { get; set; }
|
||||
public string? Type { get; set; }
|
||||
public string? Text { get; set; }
|
||||
public string? Placeholder { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,11 @@ public partial class WebDriverService
|
|||
html += $" type=\"{properties.Type}\"";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(properties.Placeholder))
|
||||
{
|
||||
html += $" placeholder=\"{properties.Placeholder}\"";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(properties.Text))
|
||||
{
|
||||
html += $">{properties.Text}</{tagName}>";
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ global using BotSharp.Abstraction.Plugins;
|
|||
global using System.Text.Json;
|
||||
global using BotSharp.Abstraction.Conversations.Models;
|
||||
global using Microsoft.Playwright;
|
||||
global using Microsoft.Extensions.Configuration;
|
||||
global using BotSharp.Plugin.WebDriver.Drivers;
|
||||
global using System.Threading.Tasks;
|
||||
global using BotSharp.Abstraction.Functions;
|
||||
|
|
@ -14,6 +15,7 @@ global using BotSharp.Abstraction.Templating;
|
|||
global using BotSharp.Plugin.WebDriver.LlmContexts;
|
||||
global using Microsoft.Extensions.DependencyInjection;
|
||||
global using System.Linq;
|
||||
global using BotSharp.Abstraction.Agents;
|
||||
global using BotSharp.Abstraction.Utilities;
|
||||
global using BotSharp.Plugin.WebDriver.Models;
|
||||
global using BotSharp.Plugin.WebDriver.Services;
|
||||
|
|
@ -8,6 +8,6 @@
|
|||
"isPublic": true,
|
||||
"profiles": [ "web-driver" ],
|
||||
"llmConfig": {
|
||||
"max_recursion_depth": 5
|
||||
"max_recursion_depth": 10
|
||||
}
|
||||
}
|
||||
|
|
@ -1,98 +1,122 @@
|
|||
[
|
||||
{
|
||||
"name": "open_browser",
|
||||
"description": "open a browser",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "website url starts with https://"
|
||||
}
|
||||
},
|
||||
"required": ["url"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "click_button",
|
||||
"description": "Click a button in a web page.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"element_name": {
|
||||
"type": "string",
|
||||
"description": "the html element name."
|
||||
}
|
||||
},
|
||||
"required": ["element_name"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "extract_data_from_page",
|
||||
"description": "Extract data from current web page.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"question": {
|
||||
"type": "string",
|
||||
"description": "the information user wants to know"
|
||||
}
|
||||
},
|
||||
"required": ["question"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "input_user_text",
|
||||
"description": "Input non-sensitive text in current web page.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"element_name": {
|
||||
"type": "string",
|
||||
"description": "the html input box element name."
|
||||
},
|
||||
"input_text": {
|
||||
"type": "string",
|
||||
"description": "non-sensitive text user provided."
|
||||
},
|
||||
"press_enter": {
|
||||
"type": "boolean",
|
||||
"description": "whether to press ENTER"
|
||||
}
|
||||
},
|
||||
"required": ["element_name", "input_text"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "change_list_value",
|
||||
"description": "Update value from dropdown list or radio button",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"element_name": {
|
||||
"type": "string",
|
||||
"description": "the html selection element name."
|
||||
},
|
||||
"update_value": {
|
||||
"type": "string",
|
||||
"description": "the value in the list."
|
||||
}
|
||||
},
|
||||
"required": ["element_name", "update_value"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "input_user_password",
|
||||
"description": "Input password in current web page",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"password": {
|
||||
"type": "string",
|
||||
"description": "user password"
|
||||
}
|
||||
},
|
||||
"required": ["password"]
|
||||
[
|
||||
{
|
||||
"name": "open_browser",
|
||||
"description": "open a browser",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "website url starts with https://"
|
||||
}
|
||||
},
|
||||
"required": [ "url" ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "close_browser",
|
||||
"description": "Close browser",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
},
|
||||
"required": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "go_to_page",
|
||||
"description": "go to another page",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "page url start with https://"
|
||||
}
|
||||
},
|
||||
"required": [ "url" ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "click_button",
|
||||
"description": "Click a button in a web page.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"element_name": {
|
||||
"type": "string",
|
||||
"description": "the html element name."
|
||||
}
|
||||
},
|
||||
"required": [ "element_name" ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "extract_data_from_page",
|
||||
"description": "Extract data from current web page.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"question": {
|
||||
"type": "string",
|
||||
"description": "the information user wants to know"
|
||||
}
|
||||
},
|
||||
"required": [ "question" ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "input_user_text",
|
||||
"description": "Input non-sensitive text in current web page.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"element_name": {
|
||||
"type": "string",
|
||||
"description": "the html input box element name."
|
||||
},
|
||||
"input_text": {
|
||||
"type": "string",
|
||||
"description": "non-sensitive text user provided."
|
||||
},
|
||||
"press_enter": {
|
||||
"type": "boolean",
|
||||
"description": "whether to press ENTER"
|
||||
}
|
||||
},
|
||||
"required": [ "element_name", "input_text" ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "change_list_value",
|
||||
"description": "Update value from dropdown list or radio button",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"element_name": {
|
||||
"type": "string",
|
||||
"description": "the html selection element name."
|
||||
},
|
||||
"update_value": {
|
||||
"type": "string",
|
||||
"description": "the value in the list."
|
||||
}
|
||||
},
|
||||
"required": [ "element_name", "update_value" ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "input_user_password",
|
||||
"description": "Input password in current web page",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"password": {
|
||||
"type": "string",
|
||||
"description": "user password"
|
||||
}
|
||||
},
|
||||
"required": [ "password" ]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -7,4 +7,5 @@ Follow below steps to response:
|
|||
|
||||
Additional response requirements:
|
||||
* Call function input_user_password if user wants to input password.
|
||||
* Don't do extra steps if user didn't ask.
|
||||
* Don't do extra steps if user didn't ask.
|
||||
* Don't miss any steps.
|
||||
|
|
@ -2,5 +2,5 @@
|
|||
|
||||
=== According to above HTML ===
|
||||
Find the html element in the similar meaning of "{{ element_name }}".
|
||||
Output in JSON format {"tag_name": "", "element_id": "populated if element has id", "index": -1} with appropriate values.
|
||||
Output in JSON format {"tag_name": "", "element_id": "populated if element has id", "element_name": "populated if element has name", "index": -1}.
|
||||
The index is the position of the element which starts with 0.
|
||||
|
|
@ -82,7 +82,7 @@
|
|||
"EnableLlmCompletionLog": false,
|
||||
"EnableExecutionLog": true
|
||||
},
|
||||
"Stats": {
|
||||
"Statistics": {
|
||||
"DataDir": "stats"
|
||||
},
|
||||
"LlamaSharp": {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
"name": "Pizza Bot",
|
||||
"description": "AI assistant that can help customer place pizza order.",
|
||||
"type": "routing",
|
||||
"inheritAgentId": "01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a",
|
||||
"createdDateTime": "2023-08-18T10:39:32.2349685Z",
|
||||
"updatedDateTime": "2023-08-18T14:39:32.2349686Z",
|
||||
"iconUrl": "https://cdn-icons-png.flaticon.com/512/6978/6978255.png",
|
||||
|
|
|
|||
Loading…
Reference in a new issue