Merge pull request #1016 from visagang/features/vguruparan

Add webdriver hook to support file uploads
This commit is contained in:
Haiping 2025-04-20 18:25:54 -05:00 committed by GitHub
commit 69a5813eb7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 68 additions and 35 deletions

View file

@ -0,0 +1,8 @@
using BotSharp.Abstraction.Browsing.Models;
namespace BotSharp.Abstraction.Browsing;
public interface IWebDriverHook
{
Task<List<string>> GetUploadFiles(MessageInfo message);
}

View file

@ -12,6 +12,7 @@ public class MessageInfo : ICacheKey
public string? MessageId { get; set; }
public string? TaskId { get; set; }
public string StepId { get; set; } = Guid.NewGuid().ToString();
public string? FunctionArgs { get; set; }
public string GetCacheKey()
=> $"{nameof(MessageInfo)}";

View file

@ -80,8 +80,20 @@ public partial class PlaywrightWebDriver
}
else if (action.Action == BroswerActionEnum.FileUpload)
{
if (action.FileUrl.Length == 0)
var _states = _services.GetRequiredService<IConversationStateService>();
var files = new List<string>();
if (action.FileUrl != null && action.FileUrl.Length > 0)
{
files.AddRange(action.FileUrl);
}
var hooks = _services.GetServices<IWebDriverHook>();
foreach (var hook in hooks)
{
files.AddRange(await hook.GetUploadFiles(message));
}
if (files.Count == 0)
{
Serilog.Log.Warning($"No files found to upload: {action.Content}");
return;
}
var fileChooser = await page.RunAndWaitForFileChooserAsync(async () =>
@ -97,7 +109,7 @@ public partial class PlaywrightWebDriver
Directory.CreateDirectory(directory);
var localPaths = new List<string>();
using var httpClient = new HttpClient();
foreach (var fileUrl in action.FileUrl)
foreach (var fileUrl in files)
{
var bytes = await httpClient.GetByteArrayAsync(fileUrl);
var fileName = new Uri(fileUrl).AbsolutePath;

View file

@ -71,7 +71,7 @@ public partial class PlaywrightWebDriver : IWebBrowser
public void SetServiceProvider(IServiceProvider services)
{
_instance.SetServiceProvider(_services);
_instance.SetServiceProvider(services);
}
public async Task PressKey(MessageInfo message, string key)

View file

@ -19,44 +19,52 @@ public class UtilWebActionOnElementFn : IFunctionCallback
{
var locatorArgs = JsonSerializer.Deserialize<ElementLocatingArgs>(message.FunctionArgs);
var actionArgs = JsonSerializer.Deserialize<ElementActionArgs>(message.FunctionArgs);
if (actionArgs.Action == BroswerActionEnum.InputText)
try
{
// Replace variable in input text
if (actionArgs.Content.StartsWith("@"))
if (actionArgs.Action == BroswerActionEnum.InputText)
{
var config = _services.GetRequiredService<IConfiguration>();
var key = actionArgs.Content.Replace("@", string.Empty);
actionArgs.Content = key.Replace(key, config[key]);
// Replace variable in input text
if (actionArgs.Content.StartsWith("@"))
{
var config = _services.GetRequiredService<IConfiguration>();
var key = actionArgs.Content.Replace("@", string.Empty);
actionArgs.Content = key.Replace(key, config[key]);
}
}
actionArgs.WaitTime = actionArgs.WaitTime > 0 ? actionArgs.WaitTime : 2;
var services = _services.CreateScope().ServiceProvider;
var browser = services.GetRequiredService<IWebBrowser>();
var webDriverService = _services.GetRequiredService<WebDriverService>();
var msg = new MessageInfo
{
AgentId = message.CurrentAgentId,
MessageId = message.MessageId,
ContextId = webDriverService.GetMessageContext(message),
FunctionArgs = message.FunctionArgs
};
browser.SetServiceProvider(_services);
var result = await browser.ActionOnElement(msg, locatorArgs, actionArgs);
message.Content = $"{actionArgs.Action} executed {(result.IsSuccess ? "success" : "failed")}.";
// Add Current Url info to the message
if (actionArgs.ShowCurrentUrl)
{
message.Content += $" Current page url: '{result.UrlAfterAction}'.";
}
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
message.Data = await browser.ScreenshotAsync(msg, path);
}
actionArgs.WaitTime = actionArgs.WaitTime > 0 ? actionArgs.WaitTime : 2;
var conv = _services.GetRequiredService<IConversationService>();
var services = _services.CreateScope().ServiceProvider;
var browser = services.GetRequiredService<IWebBrowser>();
var webDriverService = _services.GetRequiredService<WebDriverService>();
var msg = new MessageInfo
catch (Exception ex)
{
AgentId = message.CurrentAgentId,
MessageId = message.MessageId,
ContextId = webDriverService.GetMessageContext(message),
};
var result = await browser.ActionOnElement(msg, locatorArgs, actionArgs);
message.Content = $"{actionArgs.Action} executed {(result.IsSuccess ? "success" : "failed")}.";
// Add Current Url info to the message
if (actionArgs.ShowCurrentUrl)
{
message.Content += $" Current page url: '{result.UrlAfterAction}'.";
message.Data = $"{actionArgs.Action} execution failed.";
_logger.LogError($"UtilWebActionOnElementFn exception: {ex.Message}. StackTrace: {ex.StackTrace}");
}
var path = webDriverService.GetScreenshotFilePath(message.MessageId);
message.Data = await browser.ScreenshotAsync(msg, path);
return true;
}
}

View file

@ -37,6 +37,10 @@
"wait_time": {
"type": "number",
"description": "wait time after action in seconds"
},
"metadata": {
"type": "string",
"description": "meta data information if user provided"
}
},
"required": [ "selector", "action" ]