Merge pull request #492 from Qtoss-AI/master

Fix WebDriver locator issue.
This commit is contained in:
C. Oceania 2024-06-12 02:56:40 +00:00 committed by GitHub
commit dc6534f45f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
37 changed files with 311 additions and 149 deletions

View file

@ -4,4 +4,7 @@ public enum BroswerActionEnum
{
Click = 1,
InputText = 2,
Typing = 3,
Hover = 4,
Scroll = 5,
}

View file

@ -4,9 +4,9 @@ namespace BotSharp.Abstraction.Browsing;
public interface IWebBrowser
{
Task<BrowserActionResult> LaunchBrowser(string contextId, string? url);
Task<BrowserActionResult> ScreenshotAsync(string contextId, string path);
Task<BrowserActionResult> ScrollPageAsync(BrowserActionParams actionParams);
Task<BrowserActionResult> LaunchBrowser(MessageInfo message);
Task<BrowserActionResult> ScreenshotAsync(MessageInfo message, string path);
Task<BrowserActionResult> ScrollPage(MessageInfo message, PageActionArgs args);
Task<BrowserActionResult> ActionOnElement(MessageInfo message, ElementLocatingArgs location, ElementActionArgs action);
Task<BrowserActionResult> LocateElement(MessageInfo message, ElementLocatingArgs location);
@ -19,11 +19,11 @@ public interface IWebBrowser
Task<BrowserActionResult> ChangeListValue(BrowserActionParams actionParams);
Task<BrowserActionResult> CheckRadioButton(BrowserActionParams actionParams);
Task<BrowserActionResult> ChangeCheckbox(BrowserActionParams actionParams);
Task<BrowserActionResult> GoToPage(string contextId, string url, bool openNewTab = false);
Task<BrowserActionResult> GoToPage(MessageInfo message, PageActionArgs args);
Task<string> ExtractData(BrowserActionParams actionParams);
Task<T> EvaluateScript<T>(string contextId, string script);
Task CloseBrowser(string contextId);
Task CloseCurrentPage(string contextId);
Task<BrowserActionResult> CloseCurrentPage(MessageInfo message);
Task<BrowserActionResult> SendHttpRequest(MessageInfo message, HttpRequestParams actionParams);
Task<BrowserActionResult> GetAttributeValue(MessageInfo message, ElementLocatingArgs location);
}

View file

@ -2,7 +2,10 @@ namespace BotSharp.Abstraction.Browsing.Models;
public class MessageInfo
{
public string AgentId { get; set; }
public string ContextId { get; set; }
public string MessageId { get; set; }
public string AgentId { get; set; } = null!;
public string UserId { get; set; } = null!;
public string ContextId { get; set; } = null!;
public string? MessageId { get; set; }
public string? TaskId { get; set; }
public string StepId { get; set; } = Guid.NewGuid().ToString();
}

View file

@ -0,0 +1,14 @@
using BotSharp.Abstraction.Browsing.Enums;
namespace BotSharp.Abstraction.Browsing.Models;
public class PageActionArgs
{
public BroswerActionEnum Action { get; set; }
public string? Content { get; set; }
public string? Direction { get; set; }
public string Url { get; set; } = null!;
public bool OpenNewTab { get; set; } = false;
}

View file

@ -7,8 +7,9 @@ public class User
public string Id { get; set; } = string.Empty;
public string UserName { get; set; } = string.Empty;
public string FirstName { get; set; } = string.Empty;
public string LastName { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string? LastName { get; set; }
public string? Email { get; set; }
public string? Phone { get; set; }
public string Salt { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
public string Source { get; set; } = "internal";

View file

@ -161,7 +161,7 @@
<ItemGroup>
<PackageReference Include="Aspects.Cache" Version="2.0.4" />
<PackageReference Include="Colorful.Console" Version="1.2.15" />
<PackageReference Include="EntityFrameworkCore.BootKit" Version="8.2.1" />
<PackageReference Include="EntityFrameworkCore.BootKit" Version="8.3.1" />
<PackageReference Include="Fluid.Core" Version="2.8.0" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
<PackageReference Include="Nanoid" Version="3.0.0" />

View file

@ -6,6 +6,7 @@ using Microsoft.IdentityModel.Tokens;
using NanoidDotNet;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text.RegularExpressions;
namespace BotSharp.Core.Users.Services;
@ -55,6 +56,10 @@ public class UserService : IUserService
record = user;
record.Email = user.Email?.ToLower();
if (user.Phone != null)
{
record.Phone = "+" + Regex.Match(user.Phone, @"\d+").Value;
}
record.Salt = Guid.NewGuid().ToString("N");
record.Password = Utilities.HashText(user.Password, record.Salt);

View file

@ -95,12 +95,14 @@ public class UserController : ControllerBase
return UserViewModel.FromUser(user);
}
[AllowAnonymous]
[HttpGet("/user/name/existing")]
public async Task<bool> VerifyUserNameExisting([FromQuery] string userName)
{
return await _userService.VerifyUserNameExisting(userName);
}
[AllowAnonymous]
[HttpGet("/user/email/existing")]
public async Task<bool> VerifyEmailExisting([FromQuery] string email)
{

View file

@ -4,10 +4,11 @@ namespace BotSharp.OpenAPI.ViewModels.Users;
public class UserCreationModel
{
public string UserName { get; set; } = string.Empty;
public string? UserName { get; set; }
public string FirstName { get; set; } = string.Empty;
public string LastName { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string? LastName { get; set; }
public string? Email { get; set; }
public string? Phone { get; set; }
public string Password { get; set; } = string.Empty;
public string Role { get; set; } = UserRole.Client;
@ -19,6 +20,7 @@ public class UserCreationModel
FirstName = FirstName,
LastName = LastName,
Email = Email,
Phone = Phone,
Password = Password,
Role = Role
};

View file

@ -5,14 +5,15 @@ namespace BotSharp.OpenAPI.ViewModels.Users;
public class UserViewModel
{
public string Id { get; set; }
public string Id { get; set; } = null!;
[JsonPropertyName("user_name")]
public string UserName { get; set; }
public string UserName { get; set; } = null!;
[JsonPropertyName("first_name")]
public string FirstName { get; set; }
public string FirstName { get; set; } = null!;
[JsonPropertyName("last_name")]
public string LastName { get; set; }
public string Email { get; set; }
public string? LastName { get; set; }
public string? Email { get; set; }
public string? Phone { get; set; }
public string Role { get; set; } = UserRole.Client;
[JsonPropertyName("full_name")]
public string FullName => $"{FirstName} {LastName}".Trim();
@ -44,6 +45,7 @@ public class UserViewModel
FirstName = user.FirstName,
LastName = user.LastName,
Email = user.Email,
Phone = user.Phone,
Role = user.Role,
Source = user.Source,
ExternalId = user.ExternalId,

View file

@ -4,15 +4,16 @@ namespace BotSharp.Plugin.MongoStorage.Collections;
public class UserDocument : MongoBase
{
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Salt { get; set; }
public string Password { get; set; }
public string UserName { get; set; } = null!;
public string FirstName { get; set; } = null!;
public string? LastName { get; set; }
public string? Email { get; set; }
public string? Phone { get; set; }
public string Salt { get; set; } = null!;
public string Password { get; set; } = null!;
public string Source { get; set; } = "internal";
public string? ExternalId { get; set; }
public string Role { get; set; }
public string Role { get; set; } = null!;
public string? VerificationCode { get; set; }
public bool Verified { get; set; }
public DateTime CreatedTime { get; set; }
@ -27,6 +28,7 @@ public class UserDocument : MongoBase
FirstName = FirstName,
LastName = LastName,
Email = Email,
Phone = Phone,
Password = Password,
Salt = Salt,
Source = Source,

View file

@ -37,6 +37,7 @@ public partial class MongoRepository
Salt = user.Salt,
Password = user.Password,
Email = user.Email,
Phone = user.Phone,
Source = user.Source,
ExternalId = user.ExternalId,
Role = user.Role,

View file

@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<Nullable>enable</Nullable>
<LangVersion>$(LangVersion)</LangVersion>
<LangVersion>12.0</LangVersion>
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
<GenerateDocumentationFile>$(GenerateDocumentationFile)</GenerateDocumentationFile>
@ -19,6 +19,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.Playwright" Version="1.44.0" />
<PackageReference Include="Selenium.WebDriver" Version="4.21.0" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.61" />
</ItemGroup>
<ItemGroup>

View file

@ -38,16 +38,16 @@ public class PlaywrightInstance : IDisposable
Headless = true,
#endif
Channel = "chrome",
IgnoreDefaultArgs = new[]
{
IgnoreDefaultArgs =
[
"--enable-automation",
},
Args = new[]
{
],
Args =
[
"--disable-infobars",
"--no-sandbox",
"--test-type"
// "--start-maximized"
}
]
});
_contexts[id].Page += async (sender, e) =>

View file

@ -2,8 +2,14 @@ namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
public partial class PlaywrightWebDriver
{
public async Task CloseCurrentPage(string contextId)
public async Task<BrowserActionResult> CloseCurrentPage(MessageInfo message)
{
await _instance.CloseCurrentPage(contextId);
await _instance.CloseCurrentPage(message.ContextId);
var result = new BrowserActionResult
{
IsSuccess = true
};
return result;
}
}

View file

@ -34,5 +34,17 @@ public partial class PlaywrightWebDriver
await locator.PressAsync(action.PressKey);
}
}
else if (action.Action == BroswerActionEnum.Typing)
{
await locator.PressSequentiallyAsync(action.Content);
if (action.PressKey != null)
{
await locator.PressAsync(action.PressKey);
}
}
else if (action.Action == BroswerActionEnum.Hover)
{
await locator.HoverAsync();
}
}
}

View file

@ -2,36 +2,38 @@ namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
public partial class PlaywrightWebDriver
{
public async Task<BrowserActionResult> GoToPage(string contextId, string url, bool openNewTab = false)
public async Task<BrowserActionResult> GoToPage(MessageInfo message, PageActionArgs args)
{
var result = new BrowserActionResult();
var context = await _instance.InitInstance(contextId);
var context = await _instance.InitInstance(message.ContextId);
try
{
// Check if the page is already open
foreach (var p in context.Pages)
if (!args.OpenNewTab && context.Pages.Count > 0)
{
if (p.Url == url)
foreach (var p in context.Pages)
{
result.Body = await p.ContentAsync();
result.IsSuccess = true;
await p.BringToFrontAsync();
return result;
if (p.Url == args.Url)
{
// Disable this due to performance issue, some page is too large
// result.Body = await p.ContentAsync();
result.IsSuccess = true;
await p.BringToFrontAsync();
return result;
}
}
}
var page = openNewTab ? await _instance.NewPage(contextId) :
_instance.GetPage(contextId);
var response = await page.GotoAsync(url);
var page = args.OpenNewTab ? await _instance.NewPage(message.ContextId) :
_instance.GetPage(message.ContextId);
var response = await page.GotoAsync(args.Url);
await page.WaitForLoadStateAsync(LoadState.DOMContentLoaded);
await page.WaitForLoadStateAsync(LoadState.NetworkIdle, new PageWaitForLoadStateOptions
{
Timeout = 1000 * 60 * 5
});
await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
if (response.Status == 200)
{
result.Body = await page.ContentAsync();
// Disable this due to performance issue, some page is too large
// result.Body = await page.InnerHTMLAsync("body");
result.IsSuccess = true;
}
else

View file

@ -2,44 +2,13 @@ namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
public partial class PlaywrightWebDriver
{
public async Task<BrowserActionResult> LaunchBrowser(string contextId, string? url)
public async Task<BrowserActionResult> LaunchBrowser(MessageInfo message)
{
var result = new BrowserActionResult()
{
IsSuccess = true
};
var context = await _instance.InitInstance(contextId);
if (!string.IsNullOrEmpty(url))
var context = await _instance.InitInstance(message.ContextId);
var result = new BrowserActionResult
{
// Check if the page is already open
foreach (var p in context.Pages)
{
if (p.Url == url)
{
await p.BringToFrontAsync();
return result;
}
}
var page = await _instance.NewPage(contextId);
try
{
var response = await page.GotoAsync(url, new PageGotoOptions
{
Timeout = 15 * 1000
});
await page.WaitForLoadStateAsync(LoadState.DOMContentLoaded);
result.IsSuccess = response.Status == 200;
}
catch (Exception ex)
{
result.Message = ex.Message;
result.StackTrace = ex.StackTrace;
_logger.LogError(ex.Message);
}
}
IsSuccess = context.Pages.Count > 0
};
return result;
}

View file

@ -77,7 +77,7 @@ public partial class PlaywrightWebDriver
locator = locator.Locator("..");
}
result.Selector = locator.ToString().Split('@').Last();
result.Selector = locator.ToString().Split("Locator@").Last();
// Make sure the element is visible
/*if (!await locator.IsVisibleAsync())
@ -117,7 +117,7 @@ public partial class PlaywrightWebDriver
}
else
{
result.Selector = locator.ToString();
result.Selector = locator.ToString().Split("Locator@").Last();
result.IsSuccess = true;
}
}

View file

@ -2,12 +2,12 @@ namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
public partial class PlaywrightWebDriver
{
public async Task<BrowserActionResult> ScreenshotAsync(string contextId, string path)
public async Task<BrowserActionResult> ScreenshotAsync(MessageInfo message, string path)
{
var result = new BrowserActionResult();
await _instance.Wait(contextId);
var page = _instance.GetPage(contextId);
await _instance.Wait(message.ContextId);
var page = _instance.GetPage(message.ContextId);
await Task.Delay(500);
var bytes = await page.ScreenshotAsync(new PageScreenshotOptions

View file

@ -2,21 +2,43 @@ namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
public partial class PlaywrightWebDriver
{
public async Task<BrowserActionResult> ScrollPageAsync(BrowserActionParams actionParams)
public async Task<BrowserActionResult> ScrollPage(MessageInfo message, PageActionArgs args)
{
var result = new BrowserActionResult();
await _instance.Wait(actionParams.ContextId);
await _instance.Wait(message.ContextId);
var page = _instance.GetPage(actionParams.ContextId);
var page = _instance.GetPage(message.ContextId);
if(actionParams.Context.Direction == "down")
await page.EvaluateAsync("window.scrollBy(0, window.innerHeight - 200)");
else if (actionParams.Context.Direction == "up")
await page.EvaluateAsync("window.scrollBy(0, -window.innerHeight + 200)");
else if (actionParams.Context.Direction == "left")
await page.EvaluateAsync("window.scrollBy(-400, 0)");
else if (actionParams.Context.Direction == "right")
await page.EvaluateAsync("window.scrollBy(400, 0)");
if (args.Direction == "down")
{
// Get the total page height
int scrollY = await page.EvaluateAsync<int>("document.body.scrollHeight");
// Scroll to the bottom
await page.Mouse.WheelAsync(0, scrollY);
}
else if (args.Direction == "up")
{
// Get the total page height
int scrollY = await page.EvaluateAsync<int>("document.body.scrollHeight");
// Scroll to the bottom
await page.Mouse.WheelAsync(0, -scrollY);
}
else if (args.Direction == "left")
{
await page.EvaluateAsync(@"
var scrollingElement = (document.scrollingElement || document.body);
scrollingElement.scrollLeft = 0;
");
}
else if (args.Direction == "right")
{
await page.EvaluateAsync(@"
var scrollingElement = (document.scrollingElement || document.body);
scrollingElement.scrollLeft = scrollingElement.scrollWidth;
");
}
result.IsSuccess = true;
return result;

View file

@ -2,17 +2,17 @@ namespace BotSharp.Plugin.WebDriver.Drivers.SeleniumDriver;
public partial class SeleniumWebDriver
{
public async Task<BrowserActionResult> GoToPage(string contextId, string url, bool openNewTab = false)
public async Task<BrowserActionResult> GoToPage(MessageInfo message, PageActionArgs args)
{
var result = new BrowserActionResult();
try
{
var page = openNewTab ? await _instance.NewPage(contextId) :
_instance.GetPage(contextId);
page.GoToUrl(url);
await _instance.Wait(contextId);
var page = args.OpenNewTab ? await _instance.NewPage(message.ContextId) :
_instance.GetPage(message.ContextId);
page.GoToUrl(args.Url);
await _instance.Wait(message.ContextId);
result.Body = _instance.GetPageContent(contextId);
result.Body = _instance.GetPageContent(message.ContextId);
result.IsSuccess = true;
}
catch (Exception ex)

View file

@ -2,32 +2,13 @@ namespace BotSharp.Plugin.WebDriver.Drivers.SeleniumDriver;
public partial class SeleniumWebDriver
{
public async Task<BrowserActionResult> LaunchBrowser(string contextId, string? url)
public async Task<BrowserActionResult> LaunchBrowser(MessageInfo message)
{
var context = await _instance.InitInstance(message.ContextId);
var result = new BrowserActionResult()
{
IsSuccess = true
};
var context = await _instance.InitInstance(contextId);
if (!string.IsNullOrEmpty(url))
{
// Check if the page is already open
var page = await _instance.NewPage(contextId);
try
{
page.GoToUrl(url);
result.IsSuccess = true;
}
catch (Exception ex)
{
result.Message = ex.Message;
result.StackTrace = ex.StackTrace;
_logger.LogError(ex.Message);
}
}
return result;
}
}

View file

@ -52,7 +52,7 @@ public partial class SeleniumWebDriver : IWebBrowser
throw new NotImplementedException();
}
public Task CloseCurrentPage(string contextId)
public Task<BrowserActionResult> CloseCurrentPage(MessageInfo message)
{
throw new NotImplementedException();
}
@ -72,12 +72,12 @@ public partial class SeleniumWebDriver : IWebBrowser
throw new NotImplementedException();
}
public Task<BrowserActionResult> ScreenshotAsync(string contextId, string path)
public Task<BrowserActionResult> ScreenshotAsync(MessageInfo message, string path)
{
throw new NotImplementedException();
}
public Task<BrowserActionResult> ScrollPageAsync(BrowserActionParams actionParams)
public Task<BrowserActionResult> ScrollPage(MessageInfo message, PageActionArgs args)
{
throw new NotImplementedException();
}

View file

@ -31,7 +31,12 @@ public class ChangeCheckboxFn : IFunctionCallback
var webDriverService = _services.GetRequiredService<WebDriverService>();
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
message.Data = await _browser.ScreenshotAsync(new MessageInfo
{
AgentId = message.CurrentAgentId,
ContextId = convService.ConversationId,
MessageId = message.MessageId
}, path);
return true;
}

View file

@ -31,7 +31,12 @@ public class ChangeListValueFn : IFunctionCallback
var webDriverService = _services.GetRequiredService<WebDriverService>();
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
message.Data = await _browser.ScreenshotAsync(new MessageInfo
{
AgentId = message.CurrentAgentId,
ContextId = convService.ConversationId,
MessageId = message.MessageId
}, path);
return true;
}

View file

@ -31,7 +31,12 @@ public class CheckRadioButtonFn : IFunctionCallback
var webDriverService = _services.GetRequiredService<WebDriverService>();
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
message.Data = await _browser.ScreenshotAsync(new MessageInfo
{
AgentId = message.CurrentAgentId,
ContextId = convService.ConversationId,
MessageId = message.MessageId
}, path);
return true;
}

View file

@ -31,7 +31,12 @@ public class ClickButtonFn : IFunctionCallback
var webDriverService = _services.GetRequiredService<WebDriverService>();
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
message.Data = await _browser.ScreenshotAsync(new MessageInfo
{
AgentId = message.CurrentAgentId,
ContextId = convService.ConversationId,
MessageId = message.MessageId
}, path);
return true;
}

View file

@ -31,7 +31,12 @@ public class ClickElementFn : IFunctionCallback
var webDriverService = _services.GetRequiredService<WebDriverService>();
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
message.Data = await _browser.ScreenshotAsync(new MessageInfo
{
AgentId = message.CurrentAgentId,
ContextId = convService.ConversationId,
MessageId = message.MessageId
}, path);
return true;
}

View file

@ -25,7 +25,12 @@ public class ExtractDataFn : IFunctionCallback
var webDriverService = _services.GetRequiredService<WebDriverService>();
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
message.Data = await _browser.ScreenshotAsync(new MessageInfo
{
AgentId = message.CurrentAgentId,
ContextId = convService.ConversationId,
MessageId = message.MessageId
}, path);
return true;
}

View file

@ -26,12 +26,25 @@ public class GoToPageFn : IFunctionCallback
url = url.Replace("https://https://", "https://");
var result = await _browser.GoToPage(convService.ConversationId, url);
var result = await _browser.GoToPage(new MessageInfo
{
AgentId = message.CurrentAgentId,
ContextId = convService.ConversationId,
MessageId = message.MessageId
}, new PageActionArgs
{
Url = url
});
message.Content = result.IsSuccess ? $"Page {url} is open." : $"Page {url} open failed. {result.Message}";
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
message.Data = await _browser.ScreenshotAsync(new MessageInfo
{
AgentId = message.CurrentAgentId,
ContextId = convService.ConversationId,
MessageId = message.MessageId
}, path);
return result.IsSuccess;
}

View file

@ -30,7 +30,12 @@ public class InputUserPasswordFn : IFunctionCallback
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
message.Data = await _browser.ScreenshotAsync(new MessageInfo
{
AgentId = message.CurrentAgentId,
ContextId = convService.ConversationId,
MessageId = message.MessageId
}, path);
return true;
}

View file

@ -36,7 +36,12 @@ public class InputUserTextFn : IFunctionCallback
var webDriverService = _services.GetRequiredService<WebDriverService>();
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
message.Data = await _browser.ScreenshotAsync(new MessageInfo
{
AgentId = message.CurrentAgentId,
ContextId = convService.ConversationId,
MessageId = message.MessageId
}, path);
return true;
}

View file

@ -1,3 +1,5 @@
using SQLitePCL;
namespace BotSharp.Plugin.WebDriver.Functions;
public class OpenBrowserFn : IFunctionCallback
@ -23,7 +25,17 @@ public class OpenBrowserFn : IFunctionCallback
var url = webDriverService.ReplaceToken(args.Url);
url = url.Replace("https://https://", "https://");
var result = await _browser.LaunchBrowser(convService.ConversationId, url);
var msgInfo = new MessageInfo
{
AgentId = message.CurrentAgentId,
ContextId = convService.ConversationId,
MessageId = message.MessageId
};
var result = await _browser.LaunchBrowser(msgInfo);
result = await _browser.GoToPage(msgInfo, new PageActionArgs
{
Url = url
});
if (result.IsSuccess)
{
@ -36,7 +48,12 @@ public class OpenBrowserFn : IFunctionCallback
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
message.Data = await _browser.ScreenshotAsync(new MessageInfo
{
AgentId = message.CurrentAgentId,
ContextId = convService.ConversationId,
MessageId = message.MessageId
}, path);
return result.IsSuccess;
}

View file

@ -21,7 +21,12 @@ public class ScreenshotFn : IFunctionCallback
var webDriverService = _services.GetRequiredService<WebDriverService>();
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
message.Data = await _browser.ScreenshotAsync(new MessageInfo
{
AgentId = message.CurrentAgentId,
ContextId = convService.ConversationId,
MessageId = message.MessageId
}, path);
message.Content = "Took screenshot completed. You can take another screenshot if needed.";
return true;

View file

@ -22,13 +22,28 @@ public class ScrollPageFn : IFunctionCallback
var agentService = _services.GetRequiredService<IAgentService>();
var agent = await agentService.LoadAgent(message.CurrentAgentId);
message.Data = await _browser.ScrollPageAsync(new BrowserActionParams(agent, args, convService.ConversationId, message.MessageId));
message.Data = await _browser.ScrollPage(new MessageInfo
{
AgentId = agent.Id,
ContextId = convService.ConversationId,
MessageId = message.MessageId
}, new PageActionArgs
{
Action = BroswerActionEnum.Scroll,
Direction = args.Direction,
});
message.Content = "Scrolled. You can scroll more if needed.";
var webDriverService = _services.GetRequiredService<WebDriverService>();
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
message.Data = await _browser.ScreenshotAsync(convService.ConversationId, path);
message.Data = await _browser.ScreenshotAsync(new MessageInfo
{
AgentId = message.CurrentAgentId,
ContextId = convService.ConversationId,
MessageId = message.MessageId
}, path);
return true;
}

View file

@ -0,0 +1,44 @@
using HtmlAgilityPack;
using System.Net.Http;
namespace BotSharp.Plugin.WebDriver;
public static class WebPageHelper
{
public static string RemoveElements(string html, string selector)
{
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(html);
var nodesToRemove = htmlDoc.DocumentNode.SelectNodes(selector);
if (nodesToRemove != null)
{
foreach (var node in nodesToRemove)
{
node.Remove();
}
}
return htmlDoc.DocumentNode.OuterHtml;
}
public static string RemoveAttribute(string html, string attrName)
{
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(html);
// Select all elements with a style attribute
var nodesWithStyle = htmlDoc.DocumentNode.SelectNodes($"//*[@{attrName}]");
if (nodesWithStyle != null)
{
foreach (var node in nodesWithStyle)
{
node.Attributes.Remove(attrName);
}
}
return htmlDoc.DocumentNode.OuterHtml;
}
}